diff --git a/.nojekyll b/.nojekyll new file mode 100644 index 0000000000..e69de29bb2 diff --git a/3.21.0-scylla/.buildinfo b/3.21.0-scylla/.buildinfo new file mode 100644 index 0000000000..8437d9756a --- /dev/null +++ b/3.21.0-scylla/.buildinfo @@ -0,0 +1,4 @@ +# Sphinx build info version 1 +# This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done. +config: dec18ff41a2666eba618eb096134a5e7 +tags: 645f666f9bcd5a90fca523b33c5a78b7 diff --git a/3.21.0-scylla/.doctrees/CHANGELOG.doctree b/3.21.0-scylla/.doctrees/CHANGELOG.doctree new file mode 100644 index 0000000000..540aa742a0 Binary files /dev/null and b/3.21.0-scylla/.doctrees/CHANGELOG.doctree differ diff --git a/3.21.0-scylla/.doctrees/api/cassandra.doctree b/3.21.0-scylla/.doctrees/api/cassandra.doctree new file mode 100644 index 0000000000..5c8342329d Binary files /dev/null and b/3.21.0-scylla/.doctrees/api/cassandra.doctree differ diff --git a/3.21.0-scylla/.doctrees/api/cassandra/auth.doctree b/3.21.0-scylla/.doctrees/api/cassandra/auth.doctree new file mode 100644 index 0000000000..cae965e2a1 Binary files /dev/null and b/3.21.0-scylla/.doctrees/api/cassandra/auth.doctree differ diff --git a/3.21.0-scylla/.doctrees/api/cassandra/cluster.doctree b/3.21.0-scylla/.doctrees/api/cassandra/cluster.doctree new file mode 100644 index 0000000000..9a1e355908 Binary files /dev/null and b/3.21.0-scylla/.doctrees/api/cassandra/cluster.doctree differ diff --git a/3.21.0-scylla/.doctrees/api/cassandra/concurrent.doctree b/3.21.0-scylla/.doctrees/api/cassandra/concurrent.doctree new file mode 100644 index 0000000000..6055b7f1d9 Binary files /dev/null and b/3.21.0-scylla/.doctrees/api/cassandra/concurrent.doctree differ diff --git a/3.21.0-scylla/.doctrees/api/cassandra/connection.doctree b/3.21.0-scylla/.doctrees/api/cassandra/connection.doctree new file mode 100644 index 0000000000..42c7a80a36 Binary files /dev/null and b/3.21.0-scylla/.doctrees/api/cassandra/connection.doctree differ diff --git a/3.21.0-scylla/.doctrees/api/cassandra/cqlengine/columns.doctree b/3.21.0-scylla/.doctrees/api/cassandra/cqlengine/columns.doctree new file mode 100644 index 0000000000..7472f1d4f8 Binary files /dev/null and b/3.21.0-scylla/.doctrees/api/cassandra/cqlengine/columns.doctree differ diff --git a/3.21.0-scylla/.doctrees/api/cassandra/cqlengine/connection.doctree b/3.21.0-scylla/.doctrees/api/cassandra/cqlengine/connection.doctree new file mode 100644 index 0000000000..4ca34258fa Binary files /dev/null and b/3.21.0-scylla/.doctrees/api/cassandra/cqlengine/connection.doctree differ diff --git a/3.21.0-scylla/.doctrees/api/cassandra/cqlengine/management.doctree b/3.21.0-scylla/.doctrees/api/cassandra/cqlengine/management.doctree new file mode 100644 index 0000000000..7d2acfd8a4 Binary files /dev/null and b/3.21.0-scylla/.doctrees/api/cassandra/cqlengine/management.doctree differ diff --git a/3.21.0-scylla/.doctrees/api/cassandra/cqlengine/models.doctree b/3.21.0-scylla/.doctrees/api/cassandra/cqlengine/models.doctree new file mode 100644 index 0000000000..69e844b9ba Binary files /dev/null and b/3.21.0-scylla/.doctrees/api/cassandra/cqlengine/models.doctree differ diff --git a/3.21.0-scylla/.doctrees/api/cassandra/cqlengine/query.doctree b/3.21.0-scylla/.doctrees/api/cassandra/cqlengine/query.doctree new file mode 100644 index 0000000000..f5adb11317 Binary files /dev/null and b/3.21.0-scylla/.doctrees/api/cassandra/cqlengine/query.doctree differ diff --git a/3.21.0-scylla/.doctrees/api/cassandra/cqlengine/usertype.doctree b/3.21.0-scylla/.doctrees/api/cassandra/cqlengine/usertype.doctree new file mode 100644 index 0000000000..db488f9438 Binary files /dev/null and b/3.21.0-scylla/.doctrees/api/cassandra/cqlengine/usertype.doctree differ diff --git a/3.21.0-scylla/.doctrees/api/cassandra/datastax/graph/fluent/index.doctree b/3.21.0-scylla/.doctrees/api/cassandra/datastax/graph/fluent/index.doctree new file mode 100644 index 0000000000..0d04b06fc4 Binary files /dev/null and b/3.21.0-scylla/.doctrees/api/cassandra/datastax/graph/fluent/index.doctree differ diff --git a/3.21.0-scylla/.doctrees/api/cassandra/datastax/graph/fluent/predicates.doctree b/3.21.0-scylla/.doctrees/api/cassandra/datastax/graph/fluent/predicates.doctree new file mode 100644 index 0000000000..6e4c0df9ec Binary files /dev/null and b/3.21.0-scylla/.doctrees/api/cassandra/datastax/graph/fluent/predicates.doctree differ diff --git a/3.21.0-scylla/.doctrees/api/cassandra/datastax/graph/fluent/query.doctree b/3.21.0-scylla/.doctrees/api/cassandra/datastax/graph/fluent/query.doctree new file mode 100644 index 0000000000..6537cbc9cb Binary files /dev/null and b/3.21.0-scylla/.doctrees/api/cassandra/datastax/graph/fluent/query.doctree differ diff --git a/3.21.0-scylla/.doctrees/api/cassandra/datastax/graph/index.doctree b/3.21.0-scylla/.doctrees/api/cassandra/datastax/graph/index.doctree new file mode 100644 index 0000000000..f8590c87fa Binary files /dev/null and b/3.21.0-scylla/.doctrees/api/cassandra/datastax/graph/index.doctree differ diff --git a/3.21.0-scylla/.doctrees/api/cassandra/decoder.doctree b/3.21.0-scylla/.doctrees/api/cassandra/decoder.doctree new file mode 100644 index 0000000000..7a8928db05 Binary files /dev/null and b/3.21.0-scylla/.doctrees/api/cassandra/decoder.doctree differ diff --git a/3.21.0-scylla/.doctrees/api/cassandra/encoder.doctree b/3.21.0-scylla/.doctrees/api/cassandra/encoder.doctree new file mode 100644 index 0000000000..27b5919e04 Binary files /dev/null and b/3.21.0-scylla/.doctrees/api/cassandra/encoder.doctree differ diff --git a/3.21.0-scylla/.doctrees/api/cassandra/graph.doctree b/3.21.0-scylla/.doctrees/api/cassandra/graph.doctree new file mode 100644 index 0000000000..6cc0eb40cb Binary files /dev/null and b/3.21.0-scylla/.doctrees/api/cassandra/graph.doctree differ diff --git a/3.21.0-scylla/.doctrees/api/cassandra/io/asyncioreactor.doctree b/3.21.0-scylla/.doctrees/api/cassandra/io/asyncioreactor.doctree new file mode 100644 index 0000000000..1966f68735 Binary files /dev/null and b/3.21.0-scylla/.doctrees/api/cassandra/io/asyncioreactor.doctree differ diff --git a/3.21.0-scylla/.doctrees/api/cassandra/io/asyncorereactor.doctree b/3.21.0-scylla/.doctrees/api/cassandra/io/asyncorereactor.doctree new file mode 100644 index 0000000000..aa7bf856e4 Binary files /dev/null and b/3.21.0-scylla/.doctrees/api/cassandra/io/asyncorereactor.doctree differ diff --git a/3.21.0-scylla/.doctrees/api/cassandra/io/eventletreactor.doctree b/3.21.0-scylla/.doctrees/api/cassandra/io/eventletreactor.doctree new file mode 100644 index 0000000000..437b07b3ba Binary files /dev/null and b/3.21.0-scylla/.doctrees/api/cassandra/io/eventletreactor.doctree differ diff --git a/3.21.0-scylla/.doctrees/api/cassandra/io/geventreactor.doctree b/3.21.0-scylla/.doctrees/api/cassandra/io/geventreactor.doctree new file mode 100644 index 0000000000..03fea704a9 Binary files /dev/null and b/3.21.0-scylla/.doctrees/api/cassandra/io/geventreactor.doctree differ diff --git a/3.21.0-scylla/.doctrees/api/cassandra/io/libevreactor.doctree b/3.21.0-scylla/.doctrees/api/cassandra/io/libevreactor.doctree new file mode 100644 index 0000000000..6494c66c56 Binary files /dev/null and b/3.21.0-scylla/.doctrees/api/cassandra/io/libevreactor.doctree differ diff --git a/3.21.0-scylla/.doctrees/api/cassandra/io/twistedreactor.doctree b/3.21.0-scylla/.doctrees/api/cassandra/io/twistedreactor.doctree new file mode 100644 index 0000000000..d37aaa4784 Binary files /dev/null and b/3.21.0-scylla/.doctrees/api/cassandra/io/twistedreactor.doctree differ diff --git a/3.21.0-scylla/.doctrees/api/cassandra/metadata.doctree b/3.21.0-scylla/.doctrees/api/cassandra/metadata.doctree new file mode 100644 index 0000000000..76e7a412f0 Binary files /dev/null and b/3.21.0-scylla/.doctrees/api/cassandra/metadata.doctree differ diff --git a/3.21.0-scylla/.doctrees/api/cassandra/metrics.doctree b/3.21.0-scylla/.doctrees/api/cassandra/metrics.doctree new file mode 100644 index 0000000000..70751f4767 Binary files /dev/null and b/3.21.0-scylla/.doctrees/api/cassandra/metrics.doctree differ diff --git a/3.21.0-scylla/.doctrees/api/cassandra/policies.doctree b/3.21.0-scylla/.doctrees/api/cassandra/policies.doctree new file mode 100644 index 0000000000..94641d5be2 Binary files /dev/null and b/3.21.0-scylla/.doctrees/api/cassandra/policies.doctree differ diff --git a/3.21.0-scylla/.doctrees/api/cassandra/pool.doctree b/3.21.0-scylla/.doctrees/api/cassandra/pool.doctree new file mode 100644 index 0000000000..21649cde45 Binary files /dev/null and b/3.21.0-scylla/.doctrees/api/cassandra/pool.doctree differ diff --git a/3.21.0-scylla/.doctrees/api/cassandra/protocol.doctree b/3.21.0-scylla/.doctrees/api/cassandra/protocol.doctree new file mode 100644 index 0000000000..a74387fe8e Binary files /dev/null and b/3.21.0-scylla/.doctrees/api/cassandra/protocol.doctree differ diff --git a/3.21.0-scylla/.doctrees/api/cassandra/query.doctree b/3.21.0-scylla/.doctrees/api/cassandra/query.doctree new file mode 100644 index 0000000000..14df40c267 Binary files /dev/null and b/3.21.0-scylla/.doctrees/api/cassandra/query.doctree differ diff --git a/3.21.0-scylla/.doctrees/api/cassandra/timestamps.doctree b/3.21.0-scylla/.doctrees/api/cassandra/timestamps.doctree new file mode 100644 index 0000000000..7b49c6f005 Binary files /dev/null and b/3.21.0-scylla/.doctrees/api/cassandra/timestamps.doctree differ diff --git a/3.21.0-scylla/.doctrees/api/cassandra/util.doctree b/3.21.0-scylla/.doctrees/api/cassandra/util.doctree new file mode 100644 index 0000000000..dc6892d839 Binary files /dev/null and b/3.21.0-scylla/.doctrees/api/cassandra/util.doctree differ diff --git a/3.21.0-scylla/.doctrees/api/index.doctree b/3.21.0-scylla/.doctrees/api/index.doctree new file mode 100644 index 0000000000..1259c20e9b Binary files /dev/null and b/3.21.0-scylla/.doctrees/api/index.doctree differ diff --git a/3.21.0-scylla/.doctrees/cqlengine/batches.doctree b/3.21.0-scylla/.doctrees/cqlengine/batches.doctree new file mode 100644 index 0000000000..0fa5a9f361 Binary files /dev/null and b/3.21.0-scylla/.doctrees/cqlengine/batches.doctree differ diff --git a/3.21.0-scylla/.doctrees/cqlengine/connections.doctree b/3.21.0-scylla/.doctrees/cqlengine/connections.doctree new file mode 100644 index 0000000000..14af1b0a12 Binary files /dev/null and b/3.21.0-scylla/.doctrees/cqlengine/connections.doctree differ diff --git a/3.21.0-scylla/.doctrees/cqlengine/faq.doctree b/3.21.0-scylla/.doctrees/cqlengine/faq.doctree new file mode 100644 index 0000000000..d5fab3fdd3 Binary files /dev/null and b/3.21.0-scylla/.doctrees/cqlengine/faq.doctree differ diff --git a/3.21.0-scylla/.doctrees/cqlengine/models.doctree b/3.21.0-scylla/.doctrees/cqlengine/models.doctree new file mode 100644 index 0000000000..5f70e1ae63 Binary files /dev/null and b/3.21.0-scylla/.doctrees/cqlengine/models.doctree differ diff --git a/3.21.0-scylla/.doctrees/cqlengine/queryset.doctree b/3.21.0-scylla/.doctrees/cqlengine/queryset.doctree new file mode 100644 index 0000000000..34b8809565 Binary files /dev/null and b/3.21.0-scylla/.doctrees/cqlengine/queryset.doctree differ diff --git a/3.21.0-scylla/.doctrees/cqlengine/third_party.doctree b/3.21.0-scylla/.doctrees/cqlengine/third_party.doctree new file mode 100644 index 0000000000..09c29aa5c6 Binary files /dev/null and b/3.21.0-scylla/.doctrees/cqlengine/third_party.doctree differ diff --git a/3.21.0-scylla/.doctrees/cqlengine/upgrade_guide.doctree b/3.21.0-scylla/.doctrees/cqlengine/upgrade_guide.doctree new file mode 100644 index 0000000000..bbfa0a23ed Binary files /dev/null and b/3.21.0-scylla/.doctrees/cqlengine/upgrade_guide.doctree differ diff --git a/3.21.0-scylla/.doctrees/dates_and_times.doctree b/3.21.0-scylla/.doctrees/dates_and_times.doctree new file mode 100644 index 0000000000..9422b9ee16 Binary files /dev/null and b/3.21.0-scylla/.doctrees/dates_and_times.doctree differ diff --git a/3.21.0-scylla/.doctrees/environment.pickle b/3.21.0-scylla/.doctrees/environment.pickle new file mode 100644 index 0000000000..be959b0c09 Binary files /dev/null and b/3.21.0-scylla/.doctrees/environment.pickle differ diff --git a/3.21.0-scylla/.doctrees/execution_profiles.doctree b/3.21.0-scylla/.doctrees/execution_profiles.doctree new file mode 100644 index 0000000000..b8c05989b8 Binary files /dev/null and b/3.21.0-scylla/.doctrees/execution_profiles.doctree differ diff --git a/3.21.0-scylla/.doctrees/faq.doctree b/3.21.0-scylla/.doctrees/faq.doctree new file mode 100644 index 0000000000..5aacb33229 Binary files /dev/null and b/3.21.0-scylla/.doctrees/faq.doctree differ diff --git a/3.21.0-scylla/.doctrees/getting_started.doctree b/3.21.0-scylla/.doctrees/getting_started.doctree new file mode 100644 index 0000000000..c0165c2215 Binary files /dev/null and b/3.21.0-scylla/.doctrees/getting_started.doctree differ diff --git a/3.21.0-scylla/.doctrees/index.doctree b/3.21.0-scylla/.doctrees/index.doctree new file mode 100644 index 0000000000..68fdc892c4 Binary files /dev/null and b/3.21.0-scylla/.doctrees/index.doctree differ diff --git a/3.21.0-scylla/.doctrees/installation.doctree b/3.21.0-scylla/.doctrees/installation.doctree new file mode 100644 index 0000000000..bb9246beff Binary files /dev/null and b/3.21.0-scylla/.doctrees/installation.doctree differ diff --git a/3.21.0-scylla/.doctrees/lwt.doctree b/3.21.0-scylla/.doctrees/lwt.doctree new file mode 100644 index 0000000000..c2415e06af Binary files /dev/null and b/3.21.0-scylla/.doctrees/lwt.doctree differ diff --git a/3.21.0-scylla/.doctrees/object_mapper.doctree b/3.21.0-scylla/.doctrees/object_mapper.doctree new file mode 100644 index 0000000000..96f8715e99 Binary files /dev/null and b/3.21.0-scylla/.doctrees/object_mapper.doctree differ diff --git a/3.21.0-scylla/.doctrees/performance.doctree b/3.21.0-scylla/.doctrees/performance.doctree new file mode 100644 index 0000000000..bfa661256b Binary files /dev/null and b/3.21.0-scylla/.doctrees/performance.doctree differ diff --git a/3.21.0-scylla/.doctrees/query_paging.doctree b/3.21.0-scylla/.doctrees/query_paging.doctree new file mode 100644 index 0000000000..b6c7b52f5b Binary files /dev/null and b/3.21.0-scylla/.doctrees/query_paging.doctree differ diff --git a/3.21.0-scylla/.doctrees/security.doctree b/3.21.0-scylla/.doctrees/security.doctree new file mode 100644 index 0000000000..9ea4fe40ea Binary files /dev/null and b/3.21.0-scylla/.doctrees/security.doctree differ diff --git a/3.21.0-scylla/.doctrees/upgrading.doctree b/3.21.0-scylla/.doctrees/upgrading.doctree new file mode 100644 index 0000000000..48dd6f5368 Binary files /dev/null and b/3.21.0-scylla/.doctrees/upgrading.doctree differ diff --git a/3.21.0-scylla/.doctrees/user_defined_types.doctree b/3.21.0-scylla/.doctrees/user_defined_types.doctree new file mode 100644 index 0000000000..c3ea4c2d80 Binary files /dev/null and b/3.21.0-scylla/.doctrees/user_defined_types.doctree differ diff --git a/3.21.0-scylla/.nojekyll b/3.21.0-scylla/.nojekyll new file mode 100644 index 0000000000..e69de29bb2 diff --git a/3.21.0-scylla/404.html b/3.21.0-scylla/404.html new file mode 100644 index 0000000000..d60936cbfe --- /dev/null +++ b/3.21.0-scylla/404.html @@ -0,0 +1,31 @@ + + + + + + + + + ScyllaDB + + + + + + + + + + + +
+

404

+

The ScyllaDB monster ate your page!

+

+ Home +

+
+ + + \ No newline at end of file diff --git a/3.21.0-scylla/CHANGELOG.html b/3.21.0-scylla/CHANGELOG.html new file mode 100644 index 0000000000..4f90a6dbba --- /dev/null +++ b/3.21.0-scylla/CHANGELOG.html @@ -0,0 +1,2801 @@ + + + + + + + + + + + + + CHANGELOG | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ Download +
+
+ +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

CHANGELOG

+
+

3.22.0

+

UNRELEASED

+
+

Features

+
    +
  • Add all() function to the ResultSet API (PYTHON-1203)

  • +
+
+
+
+

3.21.0

+

January 15, 2020

+
+

Features

+
    +
  • Unified driver: merge core and DSE drivers into a single package (PYTHON-1130)

  • +
  • Add Python 3.8 support (PYTHON-1189)

  • +
  • Allow passing ssl context for Twisted (PYTHON-1161)

  • +
  • Ssl context and cloud support for Eventlet (PYTHON-1162)

  • +
  • Cloud Twisted support (PYTHON-1163)

  • +
  • Add additional_write_policy and read_repair to system schema parsing (PYTHON-1048)

  • +
  • Flexible version parsing (PYTHON-1174)

  • +
  • Support NULL in collection deserializer (PYTHON-1123)

  • +
  • [GRAPH] Ability to execute Fluent Graph queries asynchronously (PYTHON-1129)

  • +
+
+
+

Bug Fixes

+
    +
  • Handle prepared id mismatch when repreparing on the fly (PYTHON-1124)

  • +
  • re-raising the CQLEngineException will fail on Python 3 (PYTHON-1166)

  • +
  • asyncio message chunks can be processed discontinuously (PYTHON-1185)

  • +
  • Reconnect attempts persist after downed node removed from peers (PYTHON-1181)

  • +
  • Connection fails to validate ssl certificate hostname when SSLContext.check_hostname is set (PYTHON-1186)

  • +
  • ResponseFuture._set_result crashes on connection error when used with PrepareMessage (PYTHON-1187)

  • +
  • Insights fail to serialize the startup message when the SSL Context is from PyOpenSSL (PYTHON-1192)

  • +
+
+
+

Others

+
    +
  • The driver has a new dependency: geomet. It comes from the dse-driver unification and +is used to support DSE geo types.

  • +
  • Remove *read_repair_chance table options (PYTHON-1140)

  • +
  • Avoid warnings about unspecified load balancing policy when connecting to a cloud cluster (PYTHON-1177)

  • +
  • Add new DSE CQL keywords (PYTHON-1122)

  • +
  • Publish binary wheel distributions (PYTHON-1013)

  • +
+
+
+

Deprecations

+
    +
  • DSELoadBalancingPolicy will be removed in the next major, consider using +the DefaultLoadBalancingPolicy.

  • +
+

Merged from dse-driver:

+
+
+

Features

+
    +
  • Insights integration (PYTHON-1047)

  • +
  • Graph execution profiles should preserve their graph_source when graph_options is overridden (PYTHON-1021)

  • +
  • Add NodeSync metadata (PYTHON-799)

  • +
  • Add new NodeSync failure values (PYTHON-934)

  • +
  • DETERMINISTIC and MONOTONIC Clauses for Functions and Aggregates (PYTHON-955)

  • +
  • GraphOptions should show a warning for unknown parameters (PYTHON-819)

  • +
  • DSE protocol version 2 and continous paging backpressure (PYTHON-798)

  • +
  • GraphSON2 Serialization/Deserialization Support (PYTHON-775)

  • +
  • Add graph-results payload option for GraphSON format (PYTHON-773)

  • +
  • Create an AuthProvider for the DSE transitional mode (PYTHON-831)

  • +
  • Implement serializers for the Graph String API (PYTHON-778)

  • +
  • Provide deserializers for GraphSON types (PYTHON-782)

  • +
  • Add Graph DurationType support (PYTHON-607)

  • +
  • Support DSE DateRange type (PYTHON-668)

  • +
  • RLAC CQL output for materialized views (PYTHON-682)

  • +
  • Add Geom Types wkt deserializer

  • +
  • DSE Graph Client timeouts in custom payload (PYTHON-589)

  • +
  • Make DSEGSSAPIAuthProvider accept principal name (PYTHON-574)

  • +
  • Add config profiles to DSE graph execution (PYTHON-570)

  • +
  • DSE Driver version checking (PYTHON-568)

  • +
  • Distinct default timeout for graph queries (PYTHON-477)

  • +
  • Graph result parsing for known types (PYTHON-479,487)

  • +
  • Distinct read/write CL for graph execution (PYTHON-509)

  • +
  • Target graph analytics query to spark master when available (PYTHON-510)

  • +
+
+
+

Bug Fixes

+
    +
  • Continuous paging sessions raise RuntimeError when results are not entirely consumed (PYTHON-1054)

  • +
  • GraphSON Property deserializer should return a dict instead of a set (PYTHON-1033)

  • +
  • ResponseFuture.has_more_pages may hold the wrong value (PYTHON-946)

  • +
  • DETERMINISTIC clause in AGGREGATE misplaced in CQL generation (PYTHON-963)

  • +
  • graph module import cause a DLL issue on Windows due to its cythonizing failure (PYTHON-900)

  • +
  • Update date serialization to isoformat in graph (PYTHON-805)

  • +
  • DateRange Parse Error (PYTHON-729)

  • +
  • MontonicTimestampGenerator.__init__ ignores class defaults (PYTHON-728)

  • +
  • metadata.get_host returning None unexpectedly (PYTHON-709)

  • +
  • Sockets associated with sessions not getting cleaned up on session.shutdown() (PYTHON-673)

  • +
  • Resolve FQDN from ip address and use that as host passed to SASLClient (PYTHON-566)

  • +
  • Geospatial type implementations don’t handle ‘EMPTY’ values. (PYTHON-481)

  • +
  • Correctly handle other types in geo type equality (PYTHON-508)

  • +
+
+
+

Other

+
    +
  • Add tests around cqlengine and continuous paging (PYTHON-872)

  • +
  • Add an abstract GraphStatement to handle different graph statements (PYTHON-789)

  • +
  • Write documentation examples for DSE 2.0 features (PYTHON-732)

  • +
  • DSE_V1 protocol should not include all of protocol v5 (PYTHON-694)

  • +
+
+
+
+

3.20.2

+

November 19, 2019

+
+

Bug Fixes

+
    +
  • Fix import error for old python installation without SSLContext (PYTHON-1183)

  • +
+
+
+
+

3.20.1

+

November 6, 2019

+
+

Bug Fixes

+
    +
  • ValueError: too many values to unpack (expected 2)” when there are two dashes in server version number (PYTHON-1172)

  • +
+
+
+
+

3.20.0

+

October 28, 2019

+
+

Features

+
    +
  • DataStax Apollo Support (PYTHON-1074)

  • +
  • Use 4.0 schema parser in 4 alpha and snapshot builds (PYTHON-1158)

  • +
+
+
+

Bug Fixes

+
    +
  • Connection setup methods prevent using ExecutionProfile in cqlengine (PYTHON-1009)

  • +
  • Driver deadlock if all connections dropped by heartbeat whilst request in flight and request times out (PYTHON-1044)

  • +
  • Exception when use pk__token__gt filter In python 3.7 (PYTHON-1121)

  • +
+
+
+
+

3.19.0

+

August 26, 2019

+
+

Features

+
    +
  • Add Python 3.7 support (PYTHON-1016)

  • +
  • Future-proof Mapping imports (PYTHON-1023)

  • +
  • Include param values in cqlengine logging (PYTHON-1105)

  • +
  • NTS Token Replica Map Generation is slow (PYTHON-622)

  • +
+
+
+

Bug Fixes

+
    +
  • as_cql_query UDF/UDA parameters incorrectly includes “frozen” if arguments are collections (PYTHON-1031)

  • +
  • cqlengine does not currently support combining TTL and TIMESTAMP on INSERT (PYTHON-1093)

  • +
  • Fix incorrect metadata for compact counter tables (PYTHON-1100)

  • +
  • Call ConnectionException with correct kwargs (PYTHON-1117)

  • +
  • Can’t connect to clusters built from source because version parsing doesn’t handle ‘x.y-SNAPSHOT’ (PYTHON-1118)

  • +
  • Discovered node doesn´t honor the configured Cluster port on connection (PYTHON-1127)

  • +
  • Exception when use pk__token__gt filter In python 3.7 (PYTHON-1121)

  • +
+
+
+

Other

+
    +
  • Remove invalid warning in set_session when we initialize a default connection (PYTHON-1104)

  • +
  • Set the proper default ExecutionProfile.row_factory value (PYTHON-1119)

  • +
+
+
+
+

3.18.0

+

May 27, 2019

+
+

Features

+
    +
  • Abstract Host Connection information (PYTHON-1079)

  • +
  • Improve version parsing to support a non-integer 4th component (PYTHON-1091)

  • +
  • Expose on_request_error method in the RetryPolicy (PYTHON-1064)

  • +
  • Add jitter to ExponentialReconnectionPolicy (PYTHON-1065)

  • +
+
+
+

Bug Fixes

+
    +
  • Fix error when preparing queries with beta protocol v5 (PYTHON-1081)

  • +
  • Accept legacy empty strings as column names (PYTHON-1082)

  • +
  • Let util.SortedSet handle uncomparable elements (PYTHON-1087)

  • +
+
+
+
+

3.17.1

+

May 2, 2019

+
+

Bug Fixes

+
    +
  • Socket errors EAGAIN/EWOULDBLOCK are not handled properly and cause timeouts (PYTHON-1089)

  • +
+
+
+
+

3.17.0

+

February 19, 2019

+
+

Features

+
    +
  • Send driver name and version in startup message (PYTHON-1068)

  • +
  • Add Cluster ssl_context option to enable SSL (PYTHON-995)

  • +
  • Allow encrypted private keys for 2-way SSL cluster connections (PYTHON-995)

  • +
  • Introduce new method ConsistencyLevel.is_serial (PYTHON-1067)

  • +
  • Add Session.get_execution_profile (PYTHON-932)

  • +
  • Add host kwarg to Session.execute/execute_async APIs to send a query to a specific node (PYTHON-993)

  • +
+
+
+

Bug Fixes

+
    +
  • NoHostAvailable when all hosts are up and connectable (PYTHON-891)

  • +
  • Serial consistency level is not used (PYTHON-1007)

  • +
+
+
+

Other

+
    +
  • Fail faster on incorrect lz4 import (PYTHON-1042)

  • +
  • Bump Cython dependency version to 0.29 (PYTHON-1036)

  • +
  • Expand Driver SSL Documentation (PYTHON-740)

  • +
+
+
+

Deprecations

+
    +
  • Using Cluster.ssl_options to enable SSL is deprecated and will be removed in +the next major release, use ssl_context.

  • +
  • DowngradingConsistencyRetryPolicy is deprecated and will be +removed in the next major release. (PYTHON-937)

  • +
+
+
+
+

3.16.0

+

November 12, 2018

+
+

Bug Fixes

+
    +
  • Improve and fix socket error-catching code in nonblocking-socket reactors (PYTHON-1024)

  • +
  • Non-ASCII characters in schema break CQL string generation (PYTHON-1008)

  • +
  • Fix OSS driver’s virtual table support against DSE 6.0.X and future server releases (PYTHON-1020)

  • +
  • ResultSet.one() fails if the row_factory is using a generator (PYTHON-1026)

  • +
  • Log profile name on attempt to create existing profile (PYTHON-944)

  • +
  • Cluster instantiation fails if any contact points’ hostname resolution fails (PYTHON-895)

  • +
+
+
+

Other

+
    +
  • Fix tests when RF is not maintained if we decomission a node (PYTHON-1017)

  • +
  • Fix wrong use of ResultSet indexing (PYTHON-1015)

  • +
+
+
+
+

3.15.1

+

September 6, 2018

+
+

Bug Fixes

+
    +
  • C* 4.0 schema-parsing logic breaks running against DSE 6.0.X (PYTHON-1018)

  • +
+
+
+
+

3.15.0

+

August 30, 2018

+
+

Features

+
    +
  • Parse Virtual Keyspace Metadata (PYTHON-992)

  • +
+
+
+

Bug Fixes

+
    +
  • Tokenmap.get_replicas returns the wrong value if token coincides with the end of the range (PYTHON-978)

  • +
  • Python Driver fails with “more than 255 arguments” python exception when > 255 columns specified in query response (PYTHON-893)

  • +
  • Hang in integration.standard.test_cluster.ClusterTests.test_set_keyspace_twice (PYTHON-998)

  • +
  • Asyncore reactors should use a global variable instead of a class variable for the event loop (PYTHON-697)

  • +
+
+
+

Other

+
    +
  • Use global variable for libev loops so it can be subclassed (PYTHON-973)

  • +
  • Update SchemaParser for V4 (PYTHON-1006)

  • +
  • Bump Cython dependency version to 0.28 (PYTHON-1012)

  • +
+
+
+
+

3.14.0

+

April 17, 2018

+
+

Features

+
    +
  • Add one() function to the ResultSet API (PYTHON-947)

  • +
  • Create an utility function to fetch concurrently many keys from the same replica (PYTHON-647)

  • +
  • Allow filter queries with fields that have an index managed outside of cqlengine (PYTHON-966)

  • +
  • Twisted SSL Support (PYTHON-343)

  • +
  • Support IS NOT NULL operator in cqlengine (PYTHON-968)

  • +
+
+
+

Other

+
    +
  • Fix Broken Links in Docs (PYTHON-916)

  • +
  • Reevaluate MONKEY_PATCH_LOOP in test codebase (PYTHON-903)

  • +
  • Remove CASS_SERVER_VERSION and replace it for CASSANDRA_VERSION in tests (PYTHON-910)

  • +
  • Refactor CASSANDRA_VERSION to a some kind of version object (PYTHON-915)

  • +
  • Log warning when driver configures an authenticator, but server does not request authentication (PYTHON-940)

  • +
  • Warn users when using the deprecated Session.default_consistency_level (PYTHON-953)

  • +
  • Add DSE smoke test to OSS driver tests (PYTHON-894)

  • +
  • Document long compilation times and workarounds (PYTHON-868)

  • +
  • Improve error for batch WriteTimeouts (PYTHON-941)

  • +
  • Deprecate ResultSet indexing (PYTHON-945)

  • +
+
+
+
+

3.13.0

+

January 30, 2018

+
+

Features

+
    +
  • cqlengine: LIKE filter operator (PYTHON-512)

  • +
  • Support cassandra.query.BatchType with cqlengine BatchQuery (PYTHON-888)

  • +
+
+
+

Bug Fixes

+
    +
  • AttributeError: ‘NoneType’ object has no attribute ‘add_timer’ (PYTHON-862)

  • +
  • Support retry_policy in PreparedStatement (PYTHON-861)

  • +
  • __del__ method in Session is throwing an exception (PYTHON-813)

  • +
  • LZ4 import issue with recent versions (PYTHON-897)

  • +
  • ResponseFuture._connection can be None when returning request_id (PYTHON-853)

  • +
  • ResultSet.was_applied doesn’t support batch with LWT statements (PYTHON-848)

  • +
+
+
+

Other

+
    +
  • cqlengine: avoid warning when unregistering connection on shutdown (PYTHON-865)

  • +
  • Fix DeprecationWarning of log.warn (PYTHON-846)

  • +
  • Fix example_mapper.py for python3 (PYTHON-860)

  • +
  • Possible deadlock on cassandra.concurrent.execute_concurrent (PYTHON-768)

  • +
  • Add some known deprecated warnings for 4.x (PYTHON-877)

  • +
  • Remove copyright dates from copyright notices (PYTHON-863)

  • +
  • Remove “Experimental” tag from execution profiles documentation (PYTHON-840)

  • +
  • request_timer metrics descriptions are slightly incorrect (PYTHON-885)

  • +
  • Remove “Experimental” tag from cqlengine connections documentation (PYTHON-892)

  • +
  • Set in documentation default consistency for operations is LOCAL_ONE (PYTHON-901)

  • +
+
+
+
+

3.12.0

+

November 6, 2017

+
+

Features

+
    +
  • Send keyspace in QUERY, PREPARE, and BATCH messages (PYTHON-678)

  • +
  • Add IPv4Address/IPv6Address support for inet types (PYTHON-751)

  • +
  • WriteType.CDC and VIEW missing (PYTHON-794)

  • +
  • Warn on Cluster init if contact points are specified but LBP isn’t (legacy mode) (PYTHON-812)

  • +
  • Warn on Cluster init if contact points are specified but LBP isn’t (exection profile mode) (PYTHON-838)

  • +
  • Include hash of result set metadata in prepared stmt id (PYTHON-808)

  • +
  • Add NO_COMPACT startup option (PYTHON-839)

  • +
  • Add new exception type for CDC (PYTHON-837)

  • +
  • Allow 0ms in ConstantSpeculativeExecutionPolicy (PYTHON-836)

  • +
  • Add asyncio reactor (PYTHON-507)

  • +
+
+
+

Bug Fixes

+
    +
  • Both _set_final_exception/result called for the same ResponseFuture (PYTHON-630)

  • +
  • Use of DCAwareRoundRobinPolicy raises NoHostAvailable exception (PYTHON-781)

  • +
  • Not create two sessions by default in CQLEngine (PYTHON-814)

  • +
  • Bug when subclassing AyncoreConnection (PYTHON-827)

  • +
  • Error at cleanup when closing the asyncore connections (PYTHON-829)

  • +
  • Fix sites where sessions can change during iteration (PYTHON-793)

  • +
  • cqlengine: allow min_length=0 for Ascii and Text column types (PYTHON-735)

  • +
  • Rare exception when “sys.exit(0)” after query timeouts (PYTHON-752)

  • +
  • Dont set the session keyspace when preparing statements (PYTHON-843)

  • +
  • Use of DCAwareRoundRobinPolicy raises NoHostAvailable exception (PYTHON-781)

  • +
+
+
+

Other

+
    +
  • Remove DeprecationWarning when using WhiteListRoundRobinPolicy (PYTHON-810)

  • +
  • Bump Cython dependency version to 0.27 (PYTHON-833)

  • +
+
+
+
+

3.11.0

+

July 24, 2017

+
+

Features

+
    +
  • Add idle_heartbeat_timeout cluster option to tune how long to wait for heartbeat responses. (PYTHON-762)

  • +
  • Add HostFilterPolicy (PYTHON-761)

  • +
+
+
+

Bug Fixes

+
    +
  • is_idempotent flag is not propagated from PreparedStatement to BoundStatement (PYTHON-736)

  • +
  • Fix asyncore hang on exit (PYTHON-767)

  • +
  • Driver takes several minutes to remove a bad host from session (PYTHON-762)

  • +
  • Installation doesn’t always fall back to no cython in Windows (PYTHON-763)

  • +
  • Avoid to replace a connection that is supposed to shutdown (PYTHON-772)

  • +
  • request_ids may not be returned to the pool (PYTHON-739)

  • +
  • Fix murmur3 on big-endian systems (PYTHON-653)

  • +
  • Ensure unused connections are closed if a Session is deleted by the GC (PYTHON-774)

  • +
  • Fix .values_list by using db names internally (cqlengine) (PYTHON-785)

  • +
+
+
+

Other

+
    +
  • Bump Cython dependency version to 0.25.2 (PYTHON-754)

  • +
  • Fix DeprecationWarning when using lz4 (PYTHON-769)

  • +
  • Deprecate WhiteListRoundRobinPolicy (PYTHON-759)

  • +
  • Improve upgrade guide for materializing pages (PYTHON-464)

  • +
  • Documentation for time/date specifies timestamp inupt as microseconds (PYTHON-717)

  • +
  • Point to DSA Slack, not IRC, in docs index

  • +
+
+
+
+

3.10.0

+

May 24, 2017

+
+

Features

+
    +
  • Add Duration type to cqlengine (PYTHON-750)

  • +
  • Community PR review: Raise error on primary key update only if its value changed (PYTHON-705)

  • +
  • get_query_trace() contract is ambiguous (PYTHON-196)

  • +
+
+
+

Bug Fixes

+
    +
  • Queries using speculative execution policy timeout prematurely (PYTHON-755)

  • +
  • Fix map where results are not consumed (PYTHON-749)

  • +
  • Driver fails to encode Duration’s with large values (PYTHON-747)

  • +
  • UDT values are not updated correctly in CQLEngine (PYTHON-743)

  • +
  • UDT types are not validated in CQLEngine (PYTHON-742)

  • +
  • to_python is not implemented for types columns.Type and columns.Date in CQLEngine (PYTHON-741)

  • +
  • Clients spin infinitely trying to connect to a host that is drained (PYTHON-734)

  • +
  • Resulset.get_query_trace returns empty trace sometimes (PYTHON-730)

  • +
  • Memory grows and doesn’t get removed (PYTHON-720)

  • +
  • Fix RuntimeError caused by change dict size during iteration (PYTHON-708)

  • +
  • fix ExponentialReconnectionPolicy may throw OverflowError problem (PYTHON-707)

  • +
  • Avoid using nonexistent prepared statement in ResponseFuture (PYTHON-706)

  • +
+
+
+

Other

+
    +
  • Update README (PYTHON-746)

  • +
  • Test python versions 3.5 and 3.6 (PYTHON-737)

  • +
  • Docs Warning About Prepare “select *” (PYTHON-626)

  • +
  • Increase Coverage in CqlEngine Test Suite (PYTHON-505)

  • +
  • Example SSL connection code does not verify server certificates (PYTHON-469)

  • +
+
+
+
+

3.9.0

+
+

Features

+
    +
  • cqlengine: remove elements by key from a map (PYTHON-688)

  • +
+
+
+

Bug Fixes

+
    +
  • improve error handling when connecting to non-existent keyspace (PYTHON-665)

  • +
  • Sockets associated with sessions not getting cleaned up on session.shutdown() (PYTHON-673)

  • +
  • rare flake on integration.standard.test_cluster.ClusterTests.test_clone_shared_lbp (PYTHON-727)

  • +
  • MontonicTimestampGenerator.__init__ ignores class defaults (PYTHON-728)

  • +
  • race where callback or errback for request may not be called (PYTHON-733)

  • +
  • cqlengine: model.update() should not update columns with a default value that hasn’t changed (PYTHON-657)

  • +
  • cqlengine: field value manager’s explicit flag is True when queried back from cassandra (PYTHON-719)

  • +
+
+
+

Other

+
    +
  • Connection not closed in example_mapper (PYTHON-723)

  • +
  • Remove mention of pre-2.0 C* versions from OSS 3.0+ docs (PYTHON-710)

  • +
+
+
+
+

3.8.1

+

March 16, 2017

+
+

Bug Fixes

+
    +
  • implement __le__/__ge__/__ne__ on some custom types (PYTHON-714)

  • +
  • Fix bug in eventlet and gevent reactors that could cause hangs (PYTHON-721)

  • +
  • Fix DecimalType regression (PYTHON-724)

  • +
+
+
+
+

3.8.0

+
+

Features

+
    +
  • Quote index names in metadata CQL generation (PYTHON-616)

  • +
  • On column deserialization failure, keep error message consistent between python and cython (PYTHON-631)

  • +
  • TokenAwarePolicy always sends requests to the same replica for a given key (PYTHON-643)

  • +
  • Added cql types to result set (PYTHON-648)

  • +
  • Add __len__ to BatchStatement (PYTHON-650)

  • +
  • Duration Type for Cassandra (PYTHON-655)

  • +
  • Send flags with PREPARE message in v5 (PYTHON-684)

  • +
+
+
+

Bug Fixes

+
    +
  • Potential Timing issue if application exits prior to session pool initialization (PYTHON-636)

  • +
  • “Host X.X.X.X has been marked down” without any exceptions (PYTHON-640)

  • +
  • NoHostAvailable or OperationTimedOut when using execute_concurrent with a generator that inserts into more than one table (PYTHON-642)

  • +
  • ResponseFuture creates Timers and don’t cancel them even when result is received which leads to memory leaks (PYTHON-644)

  • +
  • Driver cannot connect to Cassandra version > 3 (PYTHON-646)

  • +
  • Unable to import model using UserType without setuping connection since 3.7 (PYTHON-649)

  • +
  • Don’t prepare queries on ignored hosts on_up (PYTHON-669)

  • +
  • Sockets associated with sessions not getting cleaned up on session.shutdown() (PYTHON-673)

  • +
  • Make client timestamps strictly monotonic (PYTHON-676)

  • +
  • cassandra.cqlengine.connection.register_connection broken when hosts=None (PYTHON-692)

  • +
+
+
+

Other

+
    +
  • Create a cqlengine doc section explaining None semantics (PYTHON-623)

  • +
  • Resolve warnings in documentation generation (PYTHON-645)

  • +
  • Cython dependency (PYTHON-686)

  • +
  • Drop Support for Python 2.6 (PYTHON-690)

  • +
+
+
+
+

3.7.1

+

October 26, 2016

+
+

Bug Fixes

+
    +
  • Cython upgrade has broken stable version of cassandra-driver (PYTHON-656)

  • +
+
+
+
+

3.7.0

+

September 13, 2016

+
+

Features

+
    +
  • Add v5 protocol failure map (PYTHON-619)

  • +
  • Don’t return from initial connect on first error (PYTHON-617)

  • +
  • Indicate failed column when deserialization fails (PYTHON-361)

  • +
  • Let Cluster.refresh_nodes force a token map rebuild (PYTHON-349)

  • +
  • Refresh UDTs after “keyspace updated” event with v1/v2 protocol (PYTHON-106)

  • +
  • EC2 Address Resolver (PYTHON-198)

  • +
  • Speculative query retries (PYTHON-218)

  • +
  • Expose paging state in API (PYTHON-200)

  • +
  • Don’t mark host down while one connection is active (PYTHON-498)

  • +
  • Query request size information (PYTHON-284)

  • +
  • Avoid quadratic ring processing with invalid replication factors (PYTHON-379)

  • +
  • Improve Connection/Pool creation concurrency on startup (PYTHON-82)

  • +
  • Add beta version native protocol flag (PYTHON-614)

  • +
  • cqlengine: Connections: support of multiple keyspaces and sessions (PYTHON-613)

  • +
+
+
+

Bug Fixes

+
    +
  • Race when adding a pool while setting keyspace (PYTHON-628)

  • +
  • Update results_metadata when prepared statement is reprepared (PYTHON-621)

  • +
  • CQL Export for Thrift Tables (PYTHON-213)

  • +
  • cqlengine: default value not applied to UserDefinedType (PYTHON-606)

  • +
  • cqlengine: columns are no longer hashable (PYTHON-618)

  • +
  • cqlengine: remove clustering keys from where clause when deleting only static columns (PYTHON-608)

  • +
+
+
+
+

3.6.0

+

August 1, 2016

+
+

Features

+
    +
  • Handle null values in NumpyProtocolHandler (PYTHON-553)

  • +
  • Collect greplin scales stats per cluster (PYTHON-561)

  • +
  • Update mock unit test dependency requirement (PYTHON-591)

  • +
  • Handle Missing CompositeType metadata following C* upgrade (PYTHON-562)

  • +
  • Improve Host.is_up state for HostDistance.IGNORED hosts (PYTHON-551)

  • +
  • Utilize v2 protocol’s ability to skip result set metadata for prepared statement execution (PYTHON-71)

  • +
  • Return from Cluster.connect() when first contact point connection(pool) is opened (PYTHON-105)

  • +
  • cqlengine: Add ContextQuery to allow cqlengine models to switch the keyspace context easily (PYTHON-598)

  • +
  • Standardize Validation between Ascii and Text types in Cqlengine (PYTHON-609)

  • +
+
+
+

Bug Fixes

+
    +
  • Fix geventreactor with SSL support (PYTHON-600)

  • +
  • Don’t downgrade protocol version if explicitly set (PYTHON-537)

  • +
  • Nonexistent contact point tries to connect indefinitely (PYTHON-549)

  • +
  • Execute_concurrent can exceed max recursion depth in failure mode (PYTHON-585)

  • +
  • Libev loop shutdown race (PYTHON-578)

  • +
  • Include aliases in DCT type string (PYTHON-579)

  • +
  • cqlengine: Comparison operators for Columns (PYTHON-595)

  • +
  • cqlengine: disentangle default_time_to_live table option from model query default TTL (PYTHON-538)

  • +
  • cqlengine: pk__token column name issue with the equality operator (PYTHON-584)

  • +
  • cqlengine: Fix “__in” filtering operator converts True to string “True” automatically (PYTHON-596)

  • +
  • cqlengine: Avoid LWTExceptions when updating columns that are part of the condition (PYTHON-580)

  • +
  • cqlengine: Cannot execute a query when the filter contains all columns (PYTHON-599)

  • +
  • cqlengine: routing key computation issue when a primary key column is overriden by model inheritance (PYTHON-576)

  • +
+
+
+
+

3.5.0

+

June 27, 2016

+
+

Features

+
    +
  • Optional Execution Profiles for the core driver (PYTHON-569)

  • +
  • API to get the host metadata associated with the control connection node (PYTHON-583)

  • +
  • Expose CDC option in table metadata CQL (PYTHON-593)

  • +
+
+
+

Bug Fixes

+
    +
  • Clean up Asyncore socket map when fork is detected (PYTHON-577)

  • +
  • cqlengine: QuerySet only() is not respected when there are deferred fields (PYTHON-560)

  • +
+
+
+
+

3.4.1

+

May 26, 2016

+
+

Bug Fixes

+
    +
  • Gevent connection closes on IO timeout (PYTHON-573)

  • +
  • “dictionary changed size during iteration” with Python 3 (PYTHON-572)

  • +
+
+
+
+

3.4.0

+

May 24, 2016

+
+

Features

+
    +
  • Include DSE version and workload in Host data (PYTHON-555)

  • +
  • Add a context manager to Cluster and Session (PYTHON-521)

  • +
  • Better Error Message for Unsupported Protocol Version (PYTHON-157)

  • +
  • Make the error message explicitly state when an error comes from the server (PYTHON-412)

  • +
  • Short Circuit meta refresh on topo change if NEW_NODE already exists (PYTHON-557)

  • +
  • Show warning when the wrong config is passed to SimpleStatement (PYTHON-219)

  • +
  • Return namedtuple result pairs from execute_concurrent (PYTHON-362)

  • +
  • BatchStatement should enforce batch size limit in a better way (PYTHON-151)

  • +
  • Validate min/max request thresholds for connection pool scaling (PYTHON-220)

  • +
  • Handle or warn about multiple hosts with the same rpc_address (PYTHON-365)

  • +
  • Write docs around working with datetime and timezones (PYTHON-394)

  • +
+
+
+

Bug Fixes

+
    +
  • High CPU utilization when using asyncore event loop (PYTHON-239)

  • +
  • Fix CQL Export for non-ASCII Identifiers (PYTHON-447)

  • +
  • Make stress scripts Python 2.6 compatible (PYTHON-434)

  • +
  • UnicodeDecodeError when unicode characters in key in BOP (PYTHON-559)

  • +
  • WhiteListRoundRobinPolicy should resolve hosts (PYTHON-565)

  • +
  • Cluster and Session do not GC after leaving scope (PYTHON-135)

  • +
  • Don’t wait for schema agreement on ignored nodes (PYTHON-531)

  • +
  • Reprepare on_up with many clients causes node overload (PYTHON-556)

  • +
  • None inserted into host map when control connection node is decommissioned (PYTHON-548)

  • +
  • weakref.ref does not accept keyword arguments (github #585)

  • +
+
+
+
+

3.3.0

+

May 2, 2016

+
+

Features

+
    +
  • Add an AddressTranslator interface (PYTHON-69)

  • +
  • New Retry Policy Decision - try next host (PYTHON-285)

  • +
  • Don’t mark host down on timeout (PYTHON-286)

  • +
  • SSL hostname verification (PYTHON-296)

  • +
  • Add C* version to metadata or cluster objects (PYTHON-301)

  • +
  • Options to Disable Schema, Token Metadata Processing (PYTHON-327)

  • +
  • Expose listen_address of node we get ring information from (PYTHON-332)

  • +
  • Use A-record with multiple IPs for contact points (PYTHON-415)

  • +
  • Custom consistency level for populating query traces (PYTHON-435)

  • +
  • Normalize Server Exception Types (PYTHON-443)

  • +
  • Propagate exception message when DDL schema agreement fails (PYTHON-444)

  • +
  • Specialized exceptions for metadata refresh methods failure (PYTHON-527)

  • +
+
+
+

Bug Fixes

+
    +
  • Resolve contact point hostnames to avoid duplicate hosts (PYTHON-103)

  • +
  • GeventConnection stalls requests when read is a multiple of the input buffer size (PYTHON-429)

  • +
  • named_tuple_factory breaks with duplicate “cleaned” col names (PYTHON-467)

  • +
  • Connection leak if Cluster.shutdown() happens during reconnection (PYTHON-482)

  • +
  • HostConnection.borrow_connection does not block when all request ids are used (PYTHON-514)

  • +
  • Empty field not being handled by the NumpyProtocolHandler (PYTHON-550)

  • +
+
+
+
+

3.2.2

+

April 19, 2016

+
    +
  • Fix counter save-after-no-update (PYTHON-547)

  • +
+
+
+

3.2.1

+

April 13, 2016

+
    +
  • Introduced an update to allow deserializer compilation with recently released Cython 0.24 (PYTHON-542)

  • +
+
+
+

3.2.0

+

April 12, 2016

+
+

Features

+
    +
  • cqlengine: Warn on sync_schema type mismatch (PYTHON-260)

  • +
  • cqlengine: Automatically defer fields with the ‘=’ operator (and immutable values) in select queries (PYTHON-520)

  • +
  • cqlengine: support non-equal conditions for LWT (PYTHON-528)

  • +
  • cqlengine: sync_table should validate the primary key composition (PYTHON-532)

  • +
  • cqlengine: token-aware routing for mapper statements (PYTHON-535)

  • +
+
+
+

Bug Fixes

+
    +
  • Deleting a column in a lightweight transaction raises a SyntaxException #325 (PYTHON-249)

  • +
  • cqlengine: make Token function works with named tables/columns #86 (PYTHON-272)

  • +
  • comparing models with datetime fields fail #79 (PYTHON-273)

  • +
  • cython date deserializer integer math should be aligned with CPython (PYTHON-480)

  • +
  • db_field is not always respected with UpdateStatement (PYTHON-530)

  • +
  • Sync_table fails on column.Set with secondary index (PYTHON-533)

  • +
+
+
+
+

3.1.1

+

March 14, 2016

+
+

Bug Fixes

+
    +
  • cqlengine: Fix performance issue related to additional “COUNT” queries (PYTHON-522)

  • +
+
+
+
+

3.1.0

+

March 10, 2016

+
+

Features

+
    +
  • Pass name of server auth class to AuthProvider (PYTHON-454)

  • +
  • Surface schema agreed flag for DDL statements (PYTHON-458)

  • +
  • Automatically convert float and int to Decimal on serialization (PYTHON-468)

  • +
  • Eventlet Reactor IO improvement (PYTHON-495)

  • +
  • Make pure Python ProtocolHandler available even when Cython is present (PYTHON-501)

  • +
  • Optional Cython deserializer for bytes as bytearray (PYTHON-503)

  • +
  • Add Session.default_serial_consistency_level (github #510)

  • +
  • cqlengine: Expose prior state information via cqlengine LWTException (github #343, PYTHON-336)

  • +
  • cqlengine: Collection datatype “contains” operators support (Cassandra 2.1) #278 (PYTHON-258)

  • +
  • cqlengine: Add DISTINCT query operator (PYTHON-266)

  • +
  • cqlengine: Tuple cqlengine api (PYTHON-306)

  • +
  • cqlengine: Add support for UPDATE/DELETE … IF EXISTS statements (PYTHON-432)

  • +
  • cqlengine: Allow nested container types (PYTHON-478)

  • +
  • cqlengine: Add ability to set query’s fetch_size and limit (PYTHON-323)

  • +
  • cqlengine: Internalize default keyspace from successive set_session (PYTHON-486)

  • +
  • cqlengine: Warn when Model.create() on Counters (to be deprecated) (PYTHON-333)

  • +
+
+
+

Bug Fixes

+
    +
  • Bus error (alignment issues) when running cython on some ARM platforms (PYTHON-450)

  • +
  • Overflow when decoding large collections (cython) (PYTHON-459)

  • +
  • Timer heap comparison issue with Python 3 (github #466)

  • +
  • Cython deserializer date overflow at 2^31 - 1 (PYTHON-452)

  • +
  • Decode error encountered when cython deserializing large map results (PYTHON-459)

  • +
  • Don’t require Cython for build if compiler or Python header not present (PYTHON-471)

  • +
  • Unorderable types in task scheduling with Python 3 (h(PYTHON-473)

  • +
  • cqlengine: Fix crash when updating a UDT column with a None value (github #467)

  • +
  • cqlengine: Race condition in ..connection.execute with lazy_connect (PYTHON-310)

  • +
  • cqlengine: doesn’t support case sensitive column family names (PYTHON-337)

  • +
  • cqlengine: UserDefinedType mandatory in create or update (PYTHON-344)

  • +
  • cqlengine: db_field breaks UserType (PYTHON-346)

  • +
  • cqlengine: UDT badly quoted (PYTHON-347)

  • +
  • cqlengine: Use of db_field on primary key prevents querying except while tracing. (PYTHON-351)

  • +
  • cqlengine: DateType.deserialize being called with one argument vs two (PYTHON-354)

  • +
  • cqlengine: Querying without setting up connection now throws AttributeError and not CQLEngineException (PYTHON-395)

  • +
  • cqlengine: BatchQuery multiple time executing execute statements. (PYTHON-445)

  • +
  • cqlengine: Better error for management functions when no connection set (PYTHON-451)

  • +
  • cqlengine: Handle None values for UDT attributes in cqlengine (PYTHON-470)

  • +
  • cqlengine: Fix inserting None for model save (PYTHON-475)

  • +
  • cqlengine: EQ doesn’t map to a QueryOperator (setup race condition) (PYTHON-476)

  • +
  • cqlengine: class.MultipleObjectsReturned has DoesNotExist as base class (PYTHON-489)

  • +
  • cqlengine: Typo in cqlengine UserType __len__ breaks attribute assignment (PYTHON-502)

  • +
+
+
+

Other

+
    +
  • cqlengine: a major improvement on queryset has been introduced. It +is a lot more efficient to iterate large datasets: the rows are +now fetched on demand using the driver pagination.

  • +
  • cqlengine: the queryset len() and count() behaviors have changed. It +now executes a “SELECT COUNT(*)” of the query rather than returning +the size of the internal result_cache (loaded rows). On large +queryset, you might want to avoid using them due to the performance +cost. Note that trying to access objects using list index/slicing +with negative indices also requires a count to be +executed.

  • +
+
+
+
+

3.0.0

+

November 24, 2015

+
+

Features

+
    +
  • Support datetime.date objects as a DateType (PYTHON-212)

  • +
  • Add Cluster.update_view_metadata (PYTHON-407)

  • +
  • QueryTrace option to populate partial trace sessions (PYTHON-438)

  • +
  • Attach column names to ResultSet (PYTHON-439)

  • +
  • Change default consistency level to LOCAL_ONE

  • +
+
+
+

Bug Fixes

+
    +
  • Properly SerDes nested collections when protocol_version < 3 (PYTHON-215)

  • +
  • Evict UDTs from UserType cache on change (PYTHON-226)

  • +
  • Make sure query strings are always encoded UTF-8 (PYTHON-334)

  • +
  • Track previous value of columns at instantiation in CQLengine (PYTHON-348)

  • +
  • UDT CQL encoding does not work for unicode values (PYTHON-353)

  • +
  • NetworkTopologyStrategy#make_token_replica_map does not account for multiple racks in a DC (PYTHON-378)

  • +
  • Cython integer overflow on decimal type deserialization (PYTHON-433)

  • +
  • Query trace: if session hasn’t been logged, query trace can throw exception (PYTHON-442)

  • +
+
+
+
+

3.0.0rc1

+

November 9, 2015

+
+

Features

+
    +
  • Process Modernized Schema Tables for Cassandra 3.0 (PYTHON-276, PYTHON-408, PYTHON-400, PYTHON-422)

  • +
  • Remove deprecated features (PYTHON-292)

  • +
  • Don’t assign trace data to Statements (PYTHON-318)

  • +
  • Normalize results return (PYTHON-368)

  • +
  • Process Materialized View Metadata/Events (PYTHON-371)

  • +
  • Remove blist as soft dependency (PYTHON-385)

  • +
  • Change default consistency level to LOCAL_QUORUM (PYTHON-416)

  • +
  • Normalize CQL query/export in metadata model (PYTHON-405)

  • +
+
+
+

Bug Fixes

+
    +
  • Implementation of named arguments bind is non-pythonic (PYTHON-178)

  • +
  • CQL encoding is incorrect for NaN and Infinity floats (PYTHON-282)

  • +
  • Protocol downgrade issue with C* 2.0.x, 2.1.x, and python3, with non-default logging (PYTHON-409)

  • +
  • ValueError when accessing usertype with non-alphanumeric field names (PYTHON-413)

  • +
  • NumpyProtocolHandler does not play well with PagedResult (PYTHON-430)

  • +
+
+
+
+

2.7.2

+

September 14, 2015

+
+

Bug Fixes

+
    +
  • Resolve CQL export error for UDF with zero parameters (PYTHON-392)

  • +
  • Remove futures dep. for Python 3 (PYTHON-393)

  • +
  • Avoid Python closure in cdef (supports earlier Cython compiler) (PYTHON-396)

  • +
  • Unit test runtime issues (PYTHON-397,398)

  • +
+
+
+
+

2.7.1

+

August 25, 2015

+
+

Bug Fixes

+
    +
  • Explicitly include extension source files in Manifest

  • +
+
+
+
+

2.7.0

+

August 25, 2015

+

Cython is introduced, providing compiled extensions for core modules, and +extensions for optimized results deserialization.

+
+

Features

+
    +
  • General Performance Improvements for Throughput (PYTHON-283)

  • +
  • Improve synchronous request performance with Timers (PYTHON-108)

  • +
  • Enable C Extensions for PyPy Runtime (PYTHON-357)

  • +
  • Refactor SerDes functionality for pluggable interface (PYTHON-313)

  • +
  • Cython SerDes Extension (PYTHON-377)

  • +
  • Accept iterators/generators for execute_concurrent() (PYTHON-123)

  • +
  • cythonize existing modules (PYTHON-342)

  • +
  • Pure Python murmur3 implementation (PYTHON-363)

  • +
  • Make driver tolerant of inconsistent metadata (PYTHON-370)

  • +
+
+
+

Bug Fixes

+
    +
  • Drop Events out-of-order Cause KeyError on Processing (PYTHON-358)

  • +
  • DowngradingConsistencyRetryPolicy doesn’t check response count on write timeouts (PYTHON-338)

  • +
  • Blocking connect does not use connect_timeout (PYTHON-381)

  • +
  • Properly protect partition key in CQL export (PYTHON-375)

  • +
  • Trigger error callbacks on timeout (PYTHON-294)

  • +
+
+
+
+

2.6.0

+

July 20, 2015

+
+

Bug Fixes

+
    +
  • Output proper CQL for compact tables with no clustering columns (PYTHON-360)

  • +
+
+
+
+

2.6.0c2

+

June 24, 2015

+
+

Features

+
    +
  • Automatic Protocol Version Downgrade (PYTHON-240)

  • +
  • cqlengine Python 2.6 compatibility (PYTHON-288)

  • +
  • Double-dollar string quote UDF body (PYTHON-345)

  • +
  • Set models.DEFAULT_KEYSPACE when calling set_session (github #352)

  • +
+
+
+

Bug Fixes

+
    +
  • Avoid stall while connecting to mixed version cluster (PYTHON-303)

  • +
  • Make SSL work with AsyncoreConnection in python 2.6.9 (PYTHON-322)

  • +
  • Fix Murmur3Token.from_key() on Windows (PYTHON-331)

  • +
  • Fix cqlengine TimeUUID rounding error for Windows (PYTHON-341)

  • +
  • Avoid invalid compaction options in CQL export for non-SizeTiered (PYTHON-352)

  • +
+
+
+
+

2.6.0c1

+

June 4, 2015

+

This release adds support for Cassandra 2.2 features, including version +4 of the native protocol.

+
+

Features

+
    +
  • Default load balancing policy to TokenAware(DCAware) (PYTHON-160)

  • +
  • Configuration option for connection timeout (PYTHON-206)

  • +
  • Support User Defined Function and Aggregate metadata in C* 2.2 (PYTHON-211)

  • +
  • Surface request client in QueryTrace for C* 2.2+ (PYTHON-235)

  • +
  • Implement new request failure messages in protocol v4+ (PYTHON-238)

  • +
  • Metadata model now maps index meta by index name (PYTHON-241)

  • +
  • Support new types in C* 2.2: date, time, smallint, tinyint (PYTHON-245, 295)

  • +
  • cqle: add Double column type and remove Float overload (PYTHON-246)

  • +
  • Use partition key column information in prepared response for protocol v4+ (PYTHON-277)

  • +
  • Support message custom payloads in protocol v4+ (PYTHON-280, PYTHON-329)

  • +
  • Deprecate refresh_schema and replace with functions for specific entities (PYTHON-291)

  • +
  • Save trace id even when trace complete times out (PYTHON-302)

  • +
  • Warn when registering client UDT class for protocol < v3 (PYTHON-305)

  • +
  • Support client warnings returned with messages in protocol v4+ (PYTHON-315)

  • +
  • Ability to distinguish between NULL and UNSET values in protocol v4+ (PYTHON-317)

  • +
  • Expose CQL keywords in API (PYTHON-324)

  • +
+
+
+

Bug Fixes

+
    +
  • IPv6 address support on Windows (PYTHON-20)

  • +
  • Convert exceptions during automatic re-preparation to nice exceptions (PYTHON-207)

  • +
  • cqle: Quote keywords properly in table management functions (PYTHON-244)

  • +
  • Don’t default to GeventConnection when gevent is loaded, but not monkey-patched (PYTHON-289)

  • +
  • Pass dynamic host from SaslAuthProvider to SaslAuthenticator (PYTHON-300)

  • +
  • Make protocol read_inet work for Windows (PYTHON-309)

  • +
  • cqle: Correct encoding for nested types (PYTHON-311)

  • +
  • Update list of CQL keywords used quoting identifiers (PYTHON-319)

  • +
  • Make ConstantReconnectionPolicy work with infinite retries (github #327, PYTHON-325)

  • +
  • Accept UUIDs with uppercase hex as valid in cqlengine (github #335)

  • +
+
+
+
+

2.5.1

+

April 23, 2015

+
+

Bug Fixes

+
    +
  • Fix thread safety in DC-aware load balancing policy (PYTHON-297)

  • +
  • Fix race condition in node/token rebuild (PYTHON-298)

  • +
  • Set and send serial consistency parameter (PYTHON-299)

  • +
+
+
+
+

2.5.0

+

March 30, 2015

+
+

Features

+
    +
  • Integrated cqlengine object mapping package

  • +
  • Utility functions for converting timeuuids and datetime (PYTHON-99)

  • +
  • Schema metadata fetch window randomized, config options added (PYTHON-202)

  • +
  • Support for new Date and Time Cassandra types (PYTHON-190)

  • +
+
+
+

Bug Fixes

+
    +
  • Fix index target for collection indexes (full(), keys()) (PYTHON-222)

  • +
  • Thread exception during GIL cleanup (PYTHON-229)

  • +
  • Workaround for rounding anomaly in datetime.utcfromtime (Python 3.4) (PYTHON-230)

  • +
  • Normalize text serialization for lookup in OrderedMap (PYTHON-231)

  • +
  • Support reading CompositeType data (PYTHON-234)

  • +
  • Preserve float precision in CQL encoding (PYTHON-243)

  • +
+
+
+
+

2.1.4

+

January 26, 2015

+
+

Features

+
    +
  • SaslAuthenticator for Kerberos support (PYTHON-109)

  • +
  • Heartbeat for network device keepalive and detecting failures on idle connections (PYTHON-197)

  • +
  • Support nested, frozen collections for Cassandra 2.1.3+ (PYTHON-186)

  • +
  • Schema agreement wait bypass config, new call for synchronous schema refresh (PYTHON-205)

  • +
  • Add eventlet connection support (PYTHON-194)

  • +
+
+
+

Bug Fixes

+
    +
  • Schema meta fix for complex thrift tables (PYTHON-191)

  • +
  • Support for ‘unknown’ replica placement strategies in schema meta (PYTHON-192)

  • +
  • Resolve stream ID leak on set_keyspace (PYTHON-195)

  • +
  • Remove implicit timestamp scaling on serialization of numeric timestamps (PYTHON-204)

  • +
  • Resolve stream id collision when using SASL auth (PYTHON-210)

  • +
  • Correct unhexlify usage for user defined type meta in Python3 (PYTHON-208)

  • +
+
+
+
+

2.1.3

+

December 16, 2014

+
+

Features

+
    +
  • INFO-level log confirmation that a connection was opened to a node that was marked up (PYTHON-116)

  • +
  • Avoid connecting to peer with incomplete metadata (PYTHON-163)

  • +
  • Add SSL support to gevent reactor (PYTHON-174)

  • +
  • Use control connection timeout in wait for schema agreement (PYTHON-175)

  • +
  • Better consistency level representation in unavailable+timeout exceptions (PYTHON-180)

  • +
  • Update schema metadata processing to accommodate coming schema modernization (PYTHON-185)

  • +
+
+
+

Bug Fixes

+
    +
  • Support large negative timestamps on Windows (PYTHON-119)

  • +
  • Fix schema agreement for clusters with peer rpc_addres 0.0.0.0 (PYTHON-166)

  • +
  • Retain table metadata following keyspace meta refresh (PYTHON-173)

  • +
  • Use a timeout when preparing a statement for all nodes (PYTHON-179)

  • +
  • Make TokenAware routing tolerant of statements with no keyspace (PYTHON-181)

  • +
  • Update add_collback to store/invoke multiple callbacks (PYTHON-182)

  • +
  • Correct routing key encoding for composite keys (PYTHON-184)

  • +
  • Include compression option in schema export string when disabled (PYTHON-187)

  • +
+
+
+
+

2.1.2

+

October 16, 2014

+
+

Features

+
    +
  • Allow DCAwareRoundRobinPolicy to be constructed without a local_dc, defaulting +instead to the DC of a contact_point (PYTHON-126)

  • +
  • Set routing key in BatchStatement.add() if none specified in batch (PYTHON-148)

  • +
  • Improved feedback on ValueError using named_tuple_factory with invalid column names (PYTHON-122)

  • +
+
+
+

Bug Fixes

+
    +
  • Make execute_concurrent compatible with Python 2.6 (PYTHON-159)

  • +
  • Handle Unauthorized message on schema_triggers query (PYTHON-155)

  • +
  • Pure Python sorted set in support of UDTs nested in collections (PYTON-167)

  • +
  • Support CUSTOM index metadata and string export (PYTHON-165)

  • +
+
+
+
+

2.1.1

+

September 11, 2014

+
+

Features

+
    +
  • Detect triggers and include them in CQL queries generated to recreate +the schema (github-189)

  • +
  • Support IPv6 addresses (PYTHON-144) (note: basic functionality added; Windows +platform not addressed (PYTHON-20))

  • +
+
+
+

Bug Fixes

+
    +
  • Fix NetworkTopologyStrategy.export_for_schema (PYTHON-120)

  • +
  • Keep timeout for paged results (PYTHON-150)

  • +
+
+
+

Other

+
    +
  • Add frozen<> type modifier to UDTs and tuples to handle CASSANDRA-7857

  • +
+
+
+
+

2.1.0

+

August 7, 2014

+
+

Bug Fixes

+
    +
  • Correctly serialize and deserialize null values in tuples and +user-defined types (PYTHON-110)

  • +
  • Include additional header and lib dirs, allowing libevwrapper to build +against Homebrew and Mac Ports installs of libev (PYTHON-112 and 804dea3)

  • +
+
+
+
+

2.1.0c1

+

July 25, 2014

+
+

Bug Fixes

+
    +
  • Properly specify UDTs for columns in CREATE TABLE statements

  • +
  • Avoid moving retries to a new host when using request ID zero (PYTHON-88)

  • +
  • Don’t ignore fetch_size arguments to Statement constructors (github-151)

  • +
  • Allow disabling automatic paging on a per-statement basis when it’s +enabled by default for the session (PYTHON-93)

  • +
  • Raise ValueError when tuple query parameters for prepared statements +have extra items (PYTHON-98)

  • +
  • Correctly encode nested tuples and UDTs for non-prepared statements (PYTHON-100)

  • +
  • Raise TypeError when a string is used for contact_points (github #164)

  • +
  • Include User Defined Types in KeyspaceMetadata.export_as_string() (PYTHON-96)

  • +
+
+
+

Other

+
    +
  • Return list collection columns as python lists instead of tuples +now that tuples are a specific Cassandra type

  • +
+
+
+
+

2.1.0b1

+

July 11, 2014

+

This release adds support for Cassandra 2.1 features, including version +3 of the native protocol.

+
+

Features

+
    +
  • When using the v3 protocol, only one connection is opened per-host, and +throughput is improved due to reduced pooling overhead and lock contention.

  • +
  • Support for user-defined types (Cassandra 2.1+)

  • +
  • Support for tuple type in (limited usage Cassandra 2.0.9, full usage +in Cassandra 2.1)

  • +
  • Protocol-level client-side timestamps (see Session.use_client_timestamp)

  • +
  • Overridable type encoding for non-prepared statements (see Session.encoders)

  • +
  • Configurable serial consistency levels for batch statements

  • +
  • Use io.BytesIO for reduced CPU consumption (github #143)

  • +
  • Support Twisted as a reactor. Note that a Twisted-compatible +API is not exposed (so no Deferreds), this is just a reactor +implementation. (github #135, PYTHON-8)

  • +
+
+
+

Bug Fixes

+
    +
  • Fix references to xrange that do not go through “six” in libevreactor and +geventreactor (github #138)

  • +
  • Make BoundStatements inherit fetch_size from their parent +PreparedStatement (PYTHON-80)

  • +
  • Clear reactor state in child process after forking to prevent errors with +multiprocessing when the parent process has connected a Cluster before +forking (github #141)

  • +
  • Don’t share prepared statement lock across Cluster instances

  • +
  • Format CompositeType and DynamicCompositeType columns correctly in +CREATE TABLE statements.

  • +
  • Fix cassandra.concurrent behavior when dealing with automatic paging +(PYTHON-81)

  • +
  • Properly defunct connections after protocol errors

  • +
  • Avoid UnicodeDecodeError when query string is unicode (PYTHON-76)

  • +
  • Correctly capture dclocal_read_repair_chance for tables and +use it when generating CREATE TABLE statements (PYTHON-84)

  • +
  • Avoid race condition with AsyncoreConnection that may cause messages +to fail to be written until a new message is pushed

  • +
  • Make sure cluster.metadata.partitioner and cluster.metadata.token_map +are populated when all nodes in the cluster are included in the +contact points (PYTHON-90)

  • +
  • Make Murmur3 hash match Cassandra’s hash for all values (PYTHON-89, +github #147)

  • +
  • Don’t attempt to reconnect to hosts that should be ignored (according +to the load balancing policy) when a notification is received that the +host is down.

  • +
  • Add CAS WriteType, avoiding KeyError on CAS write timeout (PYTHON-91)

  • +
+
+
+
+

2.0.2

+

June 10, 2014

+
+

Bug Fixes

+
    +
  • Add six to requirements.txt

  • +
  • Avoid KeyError during schema refresh when a keyspace is dropped +and TokenAwarePolicy is not in use

  • +
  • Avoid registering multiple atexit cleanup functions when the +asyncore event loop is restarted multiple times

  • +
  • Delay initialization of reactors in order to avoid problems +with shared state when using multiprocessing (PYTHON-60)

  • +
  • Add python-six to debian dependencies, move python-blist to recommends

  • +
  • Fix memory leak when libev connections are created and +destroyed (github #93)

  • +
  • Ensure token map is rebuilt when hosts are removed from the cluster

  • +
+
+
+
+

2.0.1

+

May 28, 2014

+
+

Bug Fixes

+
    +
  • Fix check for Cluster.is_shutdown in in @run_in_executor +decorator

  • +
+
+
+
+

2.0.0

+

May 28, 2014

+
+

Features

+
    +
  • Make libev C extension Python3-compatible (PYTHON-70)

  • +
  • Support v2 protocol authentication (PYTHON-73, github #125)

  • +
+
+
+

Bug Fixes

+
    +
  • Fix murmur3 C extension compilation under Python3.4 (github #124)

  • +
+
+
+

Merged From 1.x

+
+

Features

+
    +
  • Add Session.default_consistency_level (PYTHON-14)

  • +
+
+
+

Bug Fixes

+
    +
  • Don’t strip trailing underscores from column names when using the +named_tuple_factory (PYTHON-56)

  • +
  • Ensure replication factors are ints for NetworkTopologyStrategy +to avoid TypeErrors (github #120)

  • +
  • Pass WriteType instance to RetryPolicy.on_write_timeout() instead +of the string name of the write type. This caused write timeout +errors to always be rethrown instead of retrying. (github #123)

  • +
  • Avoid submitting tasks to the ThreadPoolExecutor after shutdown. With +retries enabled, this could cause Cluster.shutdown() to hang under +some circumstances.

  • +
  • Fix unintended rebuild of token replica map when keyspaces are +discovered (on startup), added, or updated and TokenAwarePolicy is not +in use.

  • +
  • Avoid rebuilding token metadata when cluster topology has not +actually changed

  • +
  • Avoid preparing queries for hosts that should be ignored (such as +remote hosts when using the DCAwareRoundRobinPolicy) (PYTHON-75)

  • +
+
+
+

Other

+
    +
  • Add 1 second timeout to join() call on event loop thread during +interpreter shutdown. This can help to prevent the process from +hanging during shutdown.

  • +
+
+
+
+
+

2.0.0b1

+

May 6, 2014

+
+

Upgrading from 1.x

+

Cluster.shutdown() should always be called when you are done with a +Cluster instance. If it is not called, there are no guarantees that the +driver will not hang. However, if you do have a reproduceable case +where Cluster.shutdown() is not called and the driver hangs, please +report it so that we can attempt to fix it.

+

If you’re using the 2.0 driver against Cassandra 1.2, you will need +to set your protocol version to 1. For example:

+
+

cluster = Cluster(…, protocol_version=1)

+
+
+
+

Features

+
    +
  • Support v2 of Cassandra’s native protocol, which includes the following +new features: automatic query paging support, protocol-level batch statements, +and lightweight transactions

  • +
  • Support for Python 3.3 and 3.4

  • +
  • Allow a default query timeout to be set per-Session

  • +
+
+
+

Bug Fixes

+
    +
  • Avoid errors during interpreter shutdown (the driver attempts to cleanup +daemonized worker threads before interpreter shutdown)

  • +
+
+
+

Deprecations

+

The following functions have moved from cassandra.decoder to cassandra.query. +The original functions have been left in place with a DeprecationWarning for +now:

+
    +
  • cassandra.decoder.tuple_factory has moved to cassandra.query.tuple_factory

  • +
  • cassandra.decoder.named_tuple_factory has moved to cassandra.query.named_tuple_factory

  • +
  • cassandra.decoder.dict_factory has moved to cassandra.query.dict_factory

  • +
  • cassandra.decoder.ordered_dict_factory has moved to cassandra.query.ordered_dict_factory

  • +
+

Exceptions that were in cassandra.decoder have been moved to cassandra.protocol. If +you handle any of these exceptions, you must adjust the code accordingly.

+
+
+
+

1.1.2

+

May 8, 2014

+
+

Features

+
    +
  • Allow a specific compression type to be requested for communications with +Cassandra and prefer lz4 if available

  • +
+
+
+

Bug Fixes

+
    +
  • Update token metadata (for TokenAware calculations) when a node is removed +from the ring

  • +
  • Fix file handle leak with gevent reactor due to blocking Greenlet kills when +closing excess connections

  • +
  • Avoid handling a node coming up multiple times due to a reconnection attempt +succeeding close to the same time that an UP notification is pushed

  • +
  • Fix duplicate node-up handling, which could result in multiple reconnectors +being started as well as the executor threads becoming deadlocked, preventing +future node up or node down handling from being executed.

  • +
  • Handle exhausted ReconnectionPolicy schedule correctly

  • +
+
+
+

Other

+
    +
  • Don’t log at ERROR when a connection is closed during the startup +communications

  • +
  • Mke scales, blist optional dependencies

  • +
+
+
+
+

1.1.1

+

April 16, 2014

+
+

Bug Fixes

+
    +
  • Fix unconditional import of nose in setup.py (github #111)

  • +
+
+
+
+

1.1.0

+

April 16, 2014

+
+

Features

+
    +
  • Gevent is now supported through monkey-patching the stdlib (PYTHON-7, +github issue #46)

  • +
  • Support static columns in schemas, which are available starting in +Cassandra 2.1. (github issue #91)

  • +
  • Add debian packaging (github issue #101)

  • +
  • Add utility methods for easy concurrent execution of statements. See +the new cassandra.concurrent module. (github issue #7)

  • +
+
+
+

Bug Fixes

+
    +
  • Correctly supply compaction and compression parameters in CREATE statements +for tables when working with Cassandra 2.0+

  • +
  • Lowercase boolean literals when generating schemas

  • +
  • Ignore SSL_ERROR_WANT_READ and SSL_ERROR_WANT_WRITE socket errors. Previously, +these resulted in the connection being defuncted, but they can safely be +ignored by the driver.

  • +
  • Don’t reconnect the control connection every time Cluster.connect() is +called

  • +
  • Avoid race condition that could leave ResponseFuture callbacks uncalled +if the callback was added outside of the event loop thread (github issue #95)

  • +
  • Properly escape keyspace name in Session.set_keyspace(). Previously, the +keyspace name was quoted, but any quotes in the string were not escaped.

  • +
  • Avoid adding hosts to the load balancing policy before their datacenter +and rack information has been set, if possible.

  • +
  • Avoid KeyError when updating metadata after droping a table (github issues +#97, #98)

  • +
  • Use tuples instead of sets for DCAwareLoadBalancingPolicy to ensure equal +distribution of requests

  • +
+
+
+

Other

+
    +
  • Don’t ignore column names when parsing typestrings. This is needed for +user-defined type support. (github issue #90)

  • +
  • Better error message when libevwrapper is not found

  • +
  • Only try to import scales when metrics are enabled (github issue #92)

  • +
  • Cut down on the number of queries executing when a new Cluster +connects and when the control connection has to reconnect (github issue #104, +PYTHON-59)

  • +
  • Issue warning log when schema versions do not match

  • +
+
+
+
+

1.0.2

+

March 4, 2014

+
+

Bug Fixes

+
    +
  • With asyncorereactor, correctly handle EAGAIN/EWOULDBLOCK when the message from +Cassandra is a multiple of the read buffer size. Previously, if no more data +became available to read on the socket, the message would never be processed, +resulting in an OperationTimedOut error.

  • +
  • Double quote keyspace, table and column names that require them (those using +uppercase characters or keywords) when generating CREATE statements through +KeyspaceMetadata and TableMetadata.

  • +
  • Decode TimestampType as DateType. (Cassandra replaced DateType with +TimestampType to fix sorting of pre-unix epoch dates in CASSANDRA-5723.)

  • +
  • Handle latest table options when parsing the schema and generating +CREATE statements.

  • +
  • Avoid ‘Set changed size during iteration’ during query plan generation +when hosts go up or down

  • +
+
+
+

Other

+
    +
  • Remove ignored tracing_enabled parameter for SimpleStatement. The +correct way to trace a query is by setting the trace argument to True +in Session.execute() and Session.execute_async().

  • +
  • Raise TypeError instead of cassandra.query.InvalidParameterTypeError when +a parameter for a prepared statement has the wrong type; remove +cassandra.query.InvalidParameterTypeError.

  • +
  • More consistent type checking for query parameters

  • +
  • Add option to a return special object for empty string values for non-string +columns

  • +
+
+
+
+

1.0.1

+

Feb 19, 2014

+
+

Bug Fixes

+
    +
  • Include table indexes in KeyspaceMetadata.export_as_string()

  • +
  • Fix broken token awareness on ByteOrderedPartitioner

  • +
  • Always close socket when defuncting error’ed connections to avoid a potential +file descriptor leak

  • +
  • Handle “custom” types (such as the replaced DateType) correctly

  • +
  • With libevreactor, correctly handle EAGAIN/EWOULDBLOCK when the message from +Cassandra is a multiple of the read buffer size. Previously, if no more data +became available to read on the socket, the message would never be processed, +resulting in an OperationTimedOut error.

  • +
  • Don’t break tracing when a Session’s row_factory is not the default +namedtuple_factory.

  • +
  • Handle data that is already utf8-encoded for UTF8Type values

  • +
  • Fix token-aware routing for tokens that fall before the first node token in +the ring and tokens that exactly match a node’s token

  • +
  • Tolerate null source_elapsed values for Trace events. These may not be +set when events complete after the main operation has already completed.

  • +
+
+
+

Other

+
    +
  • Skip sending OPTIONS message on connection creation if compression is +disabled or not available and a CQL version has not been explicitly +set

  • +
  • Add details about errors and the last queried host to OperationTimedOut

  • +
+
+
+
+

1.0.0 Final

+

Jan 29, 2014

+
+

Bug Fixes

+
    +
  • Prevent leak of Scheduler thread (even with proper shutdown)

  • +
  • Correctly handle ignored hosts, which are common with the +DCAwareRoundRobinPolicy

  • +
  • Hold strong reference to prepared statement while executing it to avoid +garbage collection

  • +
  • Add NullHandler logging handler to the cassandra package to avoid +warnings about there being no configured logger

  • +
  • Fix bad handling of nodes that have been removed from the cluster

  • +
  • Properly escape string types within cql collections

  • +
  • Handle setting the same keyspace twice in a row

  • +
  • Avoid race condition during schema agreement checks that could result +in schema update queries returning before all nodes had seen the change

  • +
  • Preserve millisecond-level precision in datetimes when performing inserts +with simple (non-prepared) statements

  • +
  • Properly defunct connections when libev reports an error by setting +errno instead of simply logging the error

  • +
  • Fix endless hanging of some requests when using the libev reactor

  • +
  • Always start a reconnection process when we fail to connect to +a newly bootstrapped node

  • +
  • Generators map to CQL lists, not key sequences

  • +
  • Always defunct connections when an internal operation fails

  • +
  • Correctly break from handle_write() if nothing was sent (asyncore +reactor only)

  • +
  • Avoid potential double-erroring of callbacks when a connection +becomes defunct

  • +
+
+
+

Features

+
    +
  • Add default query timeout to Session

  • +
  • Add timeout parameter to Session.execute()

  • +
  • Add WhiteListRoundRobinPolicy as a load balancing policy option

  • +
  • Support for consistency level LOCAL_ONE

  • +
  • Make the backoff for fetching traces exponentially increasing and +configurable

  • +
+
+
+

Other

+
    +
  • Raise Exception if TokenAwarePolicy is used against a cluster using the +Murmur3Partitioner if the murmur3 C extension has not been compiled

  • +
  • Add encoder mapping for OrderedDict

  • +
  • Use timeouts on all control connection queries

  • +
  • Benchmark improvements, including command line options and eay +multithreading support

  • +
  • Reduced lock contention when using the asyncore reactor

  • +
  • Warn when non-datetimes are used for ‘timestamp’ column values in +prepared statements

  • +
  • Add requirements.txt and test-requirements.txt

  • +
  • TravisCI integration for running unit tests against Python 2.6, +Python 2.7, and PyPy

  • +
+
+
+
+

1.0.0b7

+

Nov 12, 2013

+

This release makes many stability improvements, especially around +prepared statements and node failure handling. In particular, +several cases where a request would never be completed (and as a +result, leave the application hanging) have been resolved.

+
+

Features

+
    +
  • Add timeout kwarg to ResponseFuture.result()

  • +
  • Create connection pools to all hosts in parallel when initializing +new Sesssions.

  • +
+
+
+

Bug Fixes

+
    +
  • Properly set exception on ResponseFuture when a query fails +against all hosts

  • +
  • Improved cleanup and reconnection efforts when reconnection fails +on a node that has recently come up

  • +
  • Use correct consistency level when retrying failed operations +against a different host. (An invalid consistency level was being +used, causing the retry to fail.)

  • +
  • Better error messages for failed Session.prepare() opertaions

  • +
  • Prepare new statements against all hosts in parallel (formerly +sequential)

  • +
  • Fix failure to save the new current keyspace on connections. (This +could cause problems for prepared statements and lead to extra +operations to continuously re-set the keyspace.)

  • +
  • Avoid sharing LoadBalancingPolicies across Cluster instances. (When +a second Cluster was connected, it effectively mark nodes down for the +first Cluster.)

  • +
  • Better handling of failures during the re-preparation sequence for +unrecognized prepared statements

  • +
  • Throttle trashing of underutilized connections to avoid trashing newly +created connections

  • +
  • Fix race condition which could result in trashed connections being closed +before the last operations had completed

  • +
  • Avoid preparing statements on the event loop thread (which could lead to +deadlock)

  • +
  • Correctly mark up non-contact point nodes discovered by the control +connection. (This lead to prepared statements not being prepared +against those hosts, generating extra traffic later when the +statements were executed and unrecognized.)

  • +
  • Correctly handle large messages through libev

  • +
  • Add timeout to schema agreement check queries

  • +
  • More complete (and less contended) locking around manipulation of the +pending message deque for libev connections

  • +
+
+
+

Other

+
    +
  • Prepare statements in batches of 10. (When many prepared statements +are in use, this allows the driver to start utilizing nodes that +were restarted more quickly.)

  • +
  • Better debug logging around connection management

  • +
  • Don’t retain unreferenced prepared statements in the local cache. +(If many different prepared statements were created, this would +increase memory usage and greatly increase the amount of time +required to begin utilizing a node that was added or marked +up.)

  • +
+
+
+
+

1.0.0b6

+

Oct 22, 2013

+
+

Bug Fixes

+
    +
  • Use lazy string formatting when logging

  • +
  • Avoid several deadlock scenarios, especially when nodes go down

  • +
  • Avoid trashing newly created connections due to insufficient traffic

  • +
  • Gracefully handle un-handled Exceptions when erroring callbacks

  • +
+
+
+

Other

+
    +
  • Node state listeners (which are called when a node is added, removed, +goes down, or comes up) should now be registered through +Cluster.register_listener() instead of through a host’s HealthMonitor +(which has been removed)

  • +
+
+
+
+

1.0.0b5

+

Oct 10, 2013

+
+

Features

+
    +
  • SSL support

  • +
+
+
+

Bug Fixes

+
    +
  • Avoid KeyError when building replica map for NetworkTopologyStrategy

  • +
  • Work around python bug which causes deadlock when a thread imports +the utf8 module

  • +
  • Handle no blist library, which is not compatible with pypy

  • +
  • Avoid deadlock triggered by a keyspace being set on a connection (which +may happen automatically for new connections)

  • +
+
+
+

Other

+
    +
  • Switch packaging from Distribute to setuptools, improved C extension +support

  • +
  • Use PEP 386 compliant beta and post-release versions

  • +
+
+
+
+

1.0.0-beta4

+

Sep 24, 2013

+
+

Features

+
    +
  • Handle new blob syntax in Cassandra 2.0 by accepting bytearray +objects for blob values

  • +
  • Add cql_version kwarg to Cluster.__init__

  • +
+
+
+

Bug Fixes

+
    +
  • Fix KeyError when building token map with NetworkTopologyStrategy +keyspaces (this prevented a Cluster from successfully connecting +at all).

  • +
  • Don’t lose default consitency level from parent PreparedStatement +when creating BoundStatements

  • +
+
+
+
+

1.0.0-beta3

+

Sep 20, 2013

+
+

Features

+
    +
  • Support for LZ4 compression (Cassandra 2.0+)

  • +
  • Token-aware routing will now utilize all replicas for a query instead +of just the first replica

  • +
+
+
+

Bug Fixes

+
    +
  • Fix libev include path for CentOS

  • +
  • Fix varint packing of the value 0

  • +
  • Correctly pack unicode values

  • +
  • Don’t attempt to return failed connections to the pool when a final result +is set

  • +
  • Fix bad iteration of connection credentials

  • +
  • Use blist’s orderedset for set collections and OrderedDict for map +collections so that Cassandra’s ordering is preserved

  • +
  • Fix connection failure on Windows due to unavailability of inet_pton +and inet_ntop. (Note that IPv6 inet_address values are still not +supported on Windows.)

  • +
  • Boolean constants shouldn’t be surrounded by single quotes

  • +
  • Avoid a potential loss of precision on float constants due to string +formatting

  • +
  • Actually utilize non-standard ports set on Cluster objects

  • +
  • Fix export of schema as a set of CQL queries

  • +
+
+
+

Other

+
    +
  • Use cStringIO for connection buffer for better performance

  • +
  • Add __repr__ method for Statement classes

  • +
  • Raise InvalidTypeParameterError when parameters of the wrong +type are used with statements

  • +
  • Make all tests compatible with Python 2.6

  • +
  • Add 1s timeout for opening new connections

  • +
+
+
+
+

1.0.0-beta2

+

Aug 19, 2013

+
+

Bug Fixes

+
    +
  • Fix pip packaging

  • +
+
+
+
+

1.0.0-beta

+

Aug 16, 2013

+

Initial release

+
+
+ + +
+ + + + + +
+ + +
+
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.21.0-scylla/CNAME b/3.21.0-scylla/CNAME new file mode 100644 index 0000000000..9f3e01a070 --- /dev/null +++ b/3.21.0-scylla/CNAME @@ -0,0 +1 @@ +python-driver.docs.scylladb.com \ No newline at end of file diff --git a/3.21.0-scylla/_sources/CHANGELOG.rst.txt b/3.21.0-scylla/_sources/CHANGELOG.rst.txt new file mode 100644 index 0000000000..592a2c0efa --- /dev/null +++ b/3.21.0-scylla/_sources/CHANGELOG.rst.txt @@ -0,0 +1,5 @@ +********* +CHANGELOG +********* + +.. include:: ../CHANGELOG.rst diff --git a/3.21.0-scylla/_sources/api/cassandra.rst.txt b/3.21.0-scylla/_sources/api/cassandra.rst.txt new file mode 100644 index 0000000000..d46aae56cb --- /dev/null +++ b/3.21.0-scylla/_sources/api/cassandra.rst.txt @@ -0,0 +1,77 @@ +:mod:`cassandra` - Exceptions and Enums +======================================= + +.. module:: cassandra + +.. data:: __version_info__ + + The version of the driver in a tuple format + +.. data:: __version__ + + The version of the driver in a string format + +.. autoclass:: ConsistencyLevel + :members: + +.. autoclass:: ProtocolVersion + :members: + +.. autoclass:: UserFunctionDescriptor + :members: + :inherited-members: + +.. autoclass:: UserAggregateDescriptor + :members: + :inherited-members: + +.. autoexception:: DriverException() + :members: + +.. autoexception:: RequestExecutionException() + :members: + +.. autoexception:: Unavailable() + :members: + +.. autoexception:: Timeout() + :members: + +.. autoexception:: ReadTimeout() + :members: + +.. autoexception:: WriteTimeout() + :members: + +.. autoexception:: CoordinationFailure() + :members: + +.. autoexception:: ReadFailure() + :members: + +.. autoexception:: WriteFailure() + :members: + +.. autoexception:: FunctionFailure() + :members: + +.. autoexception:: RequestValidationException() + :members: + +.. autoexception:: ConfigurationException() + :members: + +.. autoexception:: AlreadyExists() + :members: + +.. autoexception:: InvalidRequest() + :members: + +.. autoexception:: Unauthorized() + :members: + +.. autoexception:: AuthenticationFailed() + :members: + +.. autoexception:: OperationTimedOut() + :members: diff --git a/3.21.0-scylla/_sources/api/cassandra/auth.rst.txt b/3.21.0-scylla/_sources/api/cassandra/auth.rst.txt new file mode 100644 index 0000000000..58c964cf89 --- /dev/null +++ b/3.21.0-scylla/_sources/api/cassandra/auth.rst.txt @@ -0,0 +1,22 @@ +``cassandra.auth`` - Authentication +=================================== + +.. module:: cassandra.auth + +.. autoclass:: AuthProvider + :members: + +.. autoclass:: Authenticator + :members: + +.. autoclass:: PlainTextAuthProvider + :members: + +.. autoclass:: PlainTextAuthenticator + :members: + +.. autoclass:: SaslAuthProvider + :members: + +.. autoclass:: SaslAuthenticator + :members: diff --git a/3.21.0-scylla/_sources/api/cassandra/cluster.rst.txt b/3.21.0-scylla/_sources/api/cassandra/cluster.rst.txt new file mode 100644 index 0000000000..71e110559e --- /dev/null +++ b/3.21.0-scylla/_sources/api/cassandra/cluster.rst.txt @@ -0,0 +1,222 @@ +``cassandra.cluster`` - Clusters and Sessions +============================================= + +.. module:: cassandra.cluster + +.. autoclass:: Cluster ([contact_points=('127.0.0.1',)][, port=9042][, executor_threads=2], **attr_kwargs) + + .. autoattribute:: contact_points + + .. autoattribute:: port + + .. autoattribute:: cql_version + + .. autoattribute:: protocol_version + + .. autoattribute:: compression + + .. autoattribute:: auth_provider + + .. autoattribute:: load_balancing_policy + + .. autoattribute:: reconnection_policy + + .. autoattribute:: default_retry_policy + :annotation: = + + .. autoattribute:: conviction_policy_factory + + .. autoattribute:: address_translator + + .. autoattribute:: metrics_enabled + + .. autoattribute:: metrics + + .. autoattribute:: ssl_context + + .. autoattribute:: ssl_options + + .. autoattribute:: sockopts + + .. autoattribute:: max_schema_agreement_wait + + .. autoattribute:: metadata + + .. autoattribute:: connection_class + + .. autoattribute:: control_connection_timeout + + .. autoattribute:: idle_heartbeat_interval + + .. autoattribute:: idle_heartbeat_timeout + + .. autoattribute:: schema_event_refresh_window + + .. autoattribute:: topology_event_refresh_window + + .. autoattribute:: status_event_refresh_window + + .. autoattribute:: prepare_on_all_hosts + + .. autoattribute:: reprepare_on_up + + .. autoattribute:: connect_timeout + + .. autoattribute:: schema_metadata_enabled + :annotation: = True + + .. autoattribute:: token_metadata_enabled + :annotation: = True + + .. autoattribute:: timestamp_generator + + .. autoattribute:: endpoint_factory + + .. autoattribute:: cloud + + .. automethod:: connect + + .. automethod:: shutdown + + .. automethod:: register_user_type + + .. automethod:: register_listener + + .. automethod:: unregister_listener + + .. automethod:: add_execution_profile + + .. automethod:: set_max_requests_per_connection + + .. automethod:: get_max_requests_per_connection + + .. automethod:: set_min_requests_per_connection + + .. automethod:: get_min_requests_per_connection + + .. automethod:: get_core_connections_per_host + + .. automethod:: set_core_connections_per_host + + .. automethod:: get_max_connections_per_host + + .. automethod:: set_max_connections_per_host + + .. automethod:: get_control_connection_host + + .. automethod:: refresh_schema_metadata + + .. automethod:: refresh_keyspace_metadata + + .. automethod:: refresh_table_metadata + + .. automethod:: refresh_user_type_metadata + + .. automethod:: refresh_user_function_metadata + + .. automethod:: refresh_user_aggregate_metadata + + .. automethod:: refresh_nodes + + .. automethod:: set_meta_refresh_enabled + +.. autoclass:: ExecutionProfile (load_balancing_policy=, retry_policy=None, consistency_level=LOCAL_ONE, serial_consistency_level=None, request_timeout=10.0, row_factory=, speculative_execution_policy=None) + :members: + :exclude-members: consistency_level + + .. autoattribute:: consistency_level + :annotation: = LOCAL_ONE + +.. autodata:: EXEC_PROFILE_DEFAULT + :annotation: + +.. autodata:: EXEC_PROFILE_GRAPH_DEFAULT + :annotation: + +.. autodata:: EXEC_PROFILE_GRAPH_SYSTEM_DEFAULT + :annotation: + +.. autodata:: EXEC_PROFILE_GRAPH_ANALYTICS_DEFAULT + :annotation: + +.. autoclass:: Session () + + .. autoattribute:: default_timeout + :annotation: = 10.0 + + .. autoattribute:: default_consistency_level + :annotation: = LOCAL_ONE + + .. autoattribute:: default_serial_consistency_level + :annotation: = None + + .. autoattribute:: row_factory + :annotation: = + + .. autoattribute:: default_fetch_size + + .. autoattribute:: use_client_timestamp + + .. autoattribute:: timestamp_generator + + .. autoattribute:: encoder + + .. autoattribute:: client_protocol_handler + + .. automethod:: execute(statement[, parameters][, timeout][, trace][, custom_payload][, paging_state][, host][, execute_as]) + + .. automethod:: execute_async(statement[, parameters][, trace][, custom_payload][, paging_state][, host][, execute_as]) + + .. automethod:: execute_graph(statement[, parameters][, trace][, execution_profile=EXEC_PROFILE_GRAPH_DEFAULT][, execute_as]) + + .. automethod:: execute_graph_async(statement[, parameters][, trace][, execution_profile=EXEC_PROFILE_GRAPH_DEFAULT][, execute_as]) + + .. automethod:: prepare(statement) + + .. automethod:: shutdown() + + .. automethod:: set_keyspace(keyspace) + + .. automethod:: get_execution_profile + + .. automethod:: execution_profile_clone_update + + .. automethod:: add_request_init_listener + + .. automethod:: remove_request_init_listener + +.. autoclass:: ResponseFuture () + + .. autoattribute:: query + + .. automethod:: result() + + .. automethod:: get_query_trace() + + .. automethod:: get_all_query_traces() + + .. autoattribute:: custom_payload() + + .. autoattribute:: is_schema_agreed + + .. autoattribute:: has_more_pages + + .. autoattribute:: warnings + + .. automethod:: start_fetching_next_page() + + .. automethod:: add_callback(fn, *args, **kwargs) + + .. automethod:: add_errback(fn, *args, **kwargs) + + .. automethod:: add_callbacks(callback, errback, callback_args=(), callback_kwargs=None, errback_args=(), errback_args=None) + +.. autoclass:: ResultSet () + :members: + +.. autoexception:: QueryExhausted () + +.. autoexception:: NoHostAvailable () + :members: + +.. autoexception:: UserTypeDoesNotExist () diff --git a/3.21.0-scylla/_sources/api/cassandra/concurrent.rst.txt b/3.21.0-scylla/_sources/api/cassandra/concurrent.rst.txt new file mode 100644 index 0000000000..f4bab6f048 --- /dev/null +++ b/3.21.0-scylla/_sources/api/cassandra/concurrent.rst.txt @@ -0,0 +1,8 @@ +``cassandra.concurrent`` - Utilities for Concurrent Statement Execution +======================================================================= + +.. module:: cassandra.concurrent + +.. autofunction:: execute_concurrent + +.. autofunction:: execute_concurrent_with_args diff --git a/3.21.0-scylla/_sources/api/cassandra/connection.rst.txt b/3.21.0-scylla/_sources/api/cassandra/connection.rst.txt new file mode 100644 index 0000000000..32cca590c0 --- /dev/null +++ b/3.21.0-scylla/_sources/api/cassandra/connection.rst.txt @@ -0,0 +1,21 @@ +``cassandra.connection`` - Low Level Connection Info +==================================================== + +.. module:: cassandra.connection + +.. autoexception:: ConnectionException () +.. autoexception:: ConnectionShutdown () +.. autoexception:: ConnectionBusy () +.. autoexception:: ProtocolError () + +.. autoclass:: EndPoint + :members: + +.. autoclass:: EndPointFactory + :members: + +.. autoclass:: SniEndPoint + +.. autoclass:: SniEndPointFactory + +.. autoclass:: UnixSocketEndPoint diff --git a/3.21.0-scylla/_sources/api/cassandra/cqlengine/columns.rst.txt b/3.21.0-scylla/_sources/api/cassandra/cqlengine/columns.rst.txt new file mode 100644 index 0000000000..d44be8adb8 --- /dev/null +++ b/3.21.0-scylla/_sources/api/cassandra/cqlengine/columns.rst.txt @@ -0,0 +1,89 @@ +``cassandra.cqlengine.columns`` - Column types for object mapping models +======================================================================== + +.. module:: cassandra.cqlengine.columns + +Columns +------- + +Columns in your models map to columns in your CQL table. You define CQL columns by defining column attributes on your model classes. +For a model to be valid it needs at least one primary key column and one non-primary key column. + +Just as in CQL, the order you define your columns in is important, and is the same order they are defined in on a model's corresponding table. + +Each column on your model definitions needs to be an instance of a Column class. + +.. autoclass:: Column(**kwargs) + + .. autoattribute:: primary_key + + .. autoattribute:: partition_key + + .. autoattribute:: index + + .. autoattribute:: custom_index + + .. autoattribute:: db_field + + .. autoattribute:: default + + .. autoattribute:: required + + .. autoattribute:: clustering_order + + .. autoattribute:: discriminator_column + + .. autoattribute:: static + +Column Types +------------ + +Columns of all types are initialized by passing :class:`.Column` attributes to the constructor by keyword. + +.. autoclass:: Ascii(**kwargs) + +.. autoclass:: BigInt(**kwargs) + +.. autoclass:: Blob(**kwargs) + +.. autoclass:: Bytes(**kwargs) + +.. autoclass:: Boolean(**kwargs) + +.. autoclass:: Counter + +.. autoclass:: Date(**kwargs) + +.. autoclass:: DateTime(**kwargs) + + .. autoattribute:: truncate_microseconds + +.. autoclass:: Decimal(**kwargs) + +.. autoclass:: Double(**kwargs) + +.. autoclass:: Float + +.. autoclass:: Integer(**kwargs) + +.. autoclass:: List + +.. autoclass:: Map + +.. autoclass:: Set + +.. autoclass:: SmallInt(**kwargs) + +.. autoclass:: Text + +.. autoclass:: Time(**kwargs) + +.. autoclass:: TimeUUID(**kwargs) + +.. autoclass:: TinyInt(**kwargs) + +.. autoclass:: UserDefinedType + +.. autoclass:: UUID(**kwargs) + +.. autoclass:: VarInt(**kwargs) diff --git a/3.21.0-scylla/_sources/api/cassandra/cqlengine/connection.rst.txt b/3.21.0-scylla/_sources/api/cassandra/cqlengine/connection.rst.txt new file mode 100644 index 0000000000..0f584fcca2 --- /dev/null +++ b/3.21.0-scylla/_sources/api/cassandra/cqlengine/connection.rst.txt @@ -0,0 +1,16 @@ +``cassandra.cqlengine.connection`` - Connection management for cqlengine +======================================================================== + +.. module:: cassandra.cqlengine.connection + +.. autofunction:: default + +.. autofunction:: set_session + +.. autofunction:: setup + +.. autofunction:: register_connection + +.. autofunction:: unregister_connection + +.. autofunction:: set_default_connection diff --git a/3.21.0-scylla/_sources/api/cassandra/cqlengine/management.rst.txt b/3.21.0-scylla/_sources/api/cassandra/cqlengine/management.rst.txt new file mode 100644 index 0000000000..fb483abc81 --- /dev/null +++ b/3.21.0-scylla/_sources/api/cassandra/cqlengine/management.rst.txt @@ -0,0 +1,19 @@ +``cassandra.cqlengine.management`` - Schema management for cqlengine +======================================================================== + +.. module:: cassandra.cqlengine.management + +A collection of functions for managing keyspace and table schema. + +.. autofunction:: create_keyspace_simple + +.. autofunction:: create_keyspace_network_topology + +.. autofunction:: drop_keyspace + +.. autofunction:: sync_table + +.. autofunction:: sync_type + +.. autofunction:: drop_table + diff --git a/3.21.0-scylla/_sources/api/cassandra/cqlengine/models.rst.txt b/3.21.0-scylla/_sources/api/cassandra/cqlengine/models.rst.txt new file mode 100644 index 0000000000..60b1471184 --- /dev/null +++ b/3.21.0-scylla/_sources/api/cassandra/cqlengine/models.rst.txt @@ -0,0 +1,197 @@ +``cassandra.cqlengine.models`` - Table models for object mapping +================================================================ + +.. module:: cassandra.cqlengine.models + +Model +----- +.. autoclass:: Model(\*\*kwargs) + + The initializer creates an instance of the model. Pass in keyword arguments for columns you've defined on the model. + + .. code-block:: python + + class Person(Model): + id = columns.UUID(primary_key=True) + first_name = columns.Text() + last_name = columns.Text() + + person = Person(first_name='Blake', last_name='Eggleston') + person.first_name #returns 'Blake' + person.last_name #returns 'Eggleston' + + Model attributes define how the model maps to tables in the database. These are class variables that should be set + when defining Model deriviatives. + + .. autoattribute:: __abstract__ + :annotation: = False + + .. autoattribute:: __table_name__ + + .. autoattribute:: __table_name_case_sensitive__ + + .. autoattribute:: __keyspace__ + + .. autoattribute:: __connection__ + + .. attribute:: __default_ttl__ + :annotation: = None + + Will be deprecated in release 4.0. You can set the default ttl by configuring the table ``__options__``. See :ref:`ttl-change` for more details. + + .. autoattribute:: __discriminator_value__ + + See :ref:`model_inheritance` for usage examples. + + Each table can have its own set of configuration options, including compaction. Unspecified, these default to sensible values in + the server. To override defaults, set options using the model ``__options__`` attribute, which allows options specified a dict. + + When a table is synced, it will be altered to match the options set on your table. + This means that if you are changing settings manually they will be changed back on resync. + + Do not use the options settings of cqlengine if you want to manage your compaction settings manually. + + See the `list of supported table properties for more information + `_. + + .. attribute:: __options__ + + For example: + + .. code-block:: python + + class User(Model): + __options__ = {'compaction': {'class': 'LeveledCompactionStrategy', + 'sstable_size_in_mb': '64', + 'tombstone_threshold': '.2'}, + 'comment': 'User data stored here'} + + user_id = columns.UUID(primary_key=True) + name = columns.Text() + + or : + + .. code-block:: python + + class TimeData(Model): + __options__ = {'compaction': {'class': 'SizeTieredCompactionStrategy', + 'bucket_low': '.3', + 'bucket_high': '2', + 'min_threshold': '2', + 'max_threshold': '64', + 'tombstone_compaction_interval': '86400'}, + 'gc_grace_seconds': '0'} + + .. autoattribute:: __compute_routing_key__ + + + The base methods allow creating, storing, and querying modeled objects. + + .. automethod:: create + + .. method:: if_not_exists() + + Check the existence of an object before insertion. The existence of an + object is determined by its primary key(s). And please note using this flag + would incur performance cost. + + If the insertion isn't applied, a :class:`~cassandra.cqlengine.query.LWTException` is raised. + + .. code-block:: python + + try: + TestIfNotExistsModel.if_not_exists().create(id=id, count=9, text='111111111111') + except LWTException as e: + # handle failure case + print e.existing # dict containing LWT result fields + + This method is supported on Cassandra 2.0 or later. + + .. method:: if_exists() + + Check the existence of an object before an update or delete. The existence of an + object is determined by its primary key(s). And please note using this flag + would incur performance cost. + + If the update or delete isn't applied, a :class:`~cassandra.cqlengine.query.LWTException` is raised. + + .. code-block:: python + + try: + TestIfExistsModel.objects(id=id).if_exists().update(count=9, text='111111111111') + except LWTException as e: + # handle failure case + pass + + This method is supported on Cassandra 2.0 or later. + + .. automethod:: save + + .. automethod:: update + + .. method:: iff(**values) + + Checks to ensure that the values specified are correct on the Cassandra cluster. + Simply specify the column(s) and the expected value(s). As with if_not_exists, + this incurs a performance cost. + + If the insertion isn't applied, a :class:`~cassandra.cqlengine.query.LWTException` is raised. + + .. code-block:: python + + t = TestTransactionModel(text='some text', count=5) + try: + t.iff(count=5).update('other text') + except LWTException as e: + # handle failure case + print e.existing # existing object + + .. automethod:: get + + .. automethod:: filter + + .. automethod:: all + + .. automethod:: delete + + .. method:: batch(batch_object) + + Sets the batch object to run instance updates and inserts queries with. + + See :doc:`/cqlengine/batches` for usage examples + + .. automethod:: timeout + + .. method:: timestamp(timedelta_or_datetime) + + Sets the timestamp for the query + + .. method:: ttl(ttl_in_sec) + + Sets the ttl values to run instance updates and inserts queries with. + + .. method:: using(connection=None) + + Change the context on the fly of the model instance (keyspace, connection) + + .. automethod:: column_family_name + + Models also support dict-like access: + + .. method:: len(m) + + Returns the number of columns defined in the model + + .. method:: m[col_name] + + Returns the value of column ``col_name`` + + .. method:: m[col_name] = value + + Set ``m[col_name]`` to value + + .. automethod:: keys + + .. automethod:: values + + .. automethod:: items diff --git a/3.21.0-scylla/_sources/api/cassandra/cqlengine/query.rst.txt b/3.21.0-scylla/_sources/api/cassandra/cqlengine/query.rst.txt new file mode 100644 index 0000000000..ce8f764b6b --- /dev/null +++ b/3.21.0-scylla/_sources/api/cassandra/cqlengine/query.rst.txt @@ -0,0 +1,71 @@ +``cassandra.cqlengine.query`` - Query and filter model objects +================================================================= + +.. module:: cassandra.cqlengine.query + +QuerySet +-------- +QuerySet objects are typically obtained by calling :meth:`~.cassandra.cqlengine.models.Model.objects` on a model class. +The methods here are used to filter, order, and constrain results. + +.. autoclass:: ModelQuerySet + + .. automethod:: all + + .. automethod:: batch + + .. automethod:: consistency + + .. automethod:: count + + .. method:: len(queryset) + + Returns the number of rows matched by this query. This function uses :meth:`~.cassandra.cqlengine.query.ModelQuerySet.count` internally. + + *Note: This function executes a SELECT COUNT() and has a performance cost on large datasets* + + .. automethod:: distinct + + .. automethod:: filter + + .. automethod:: get + + .. automethod:: limit + + .. automethod:: fetch_size + + .. automethod:: if_not_exists + + .. automethod:: if_exists + + .. automethod:: order_by + + .. automethod:: allow_filtering + + .. automethod:: only + + .. automethod:: defer + + .. automethod:: timestamp + + .. automethod:: ttl + + .. automethod:: using + + .. _blind_updates: + + .. automethod:: update + +.. autoclass:: BatchQuery + :members: + + .. automethod:: add_query + .. automethod:: execute + +.. autoclass:: ContextQuery + +.. autoclass:: DoesNotExist + +.. autoclass:: MultipleObjectsReturned + +.. autoclass:: LWTException diff --git a/3.21.0-scylla/_sources/api/cassandra/cqlengine/usertype.rst.txt b/3.21.0-scylla/_sources/api/cassandra/cqlengine/usertype.rst.txt new file mode 100644 index 0000000000..ebed187da9 --- /dev/null +++ b/3.21.0-scylla/_sources/api/cassandra/cqlengine/usertype.rst.txt @@ -0,0 +1,10 @@ +``cassandra.cqlengine.usertype`` - Model classes for User Defined Types +======================================================================= + +.. module:: cassandra.cqlengine.usertype + +UserType +-------- +.. autoclass:: UserType + + .. autoattribute:: __type_name__ diff --git a/3.21.0-scylla/_sources/api/cassandra/datastax/graph/fluent/index.rst.txt b/3.21.0-scylla/_sources/api/cassandra/datastax/graph/fluent/index.rst.txt new file mode 100644 index 0000000000..5547e0fdd7 --- /dev/null +++ b/3.21.0-scylla/_sources/api/cassandra/datastax/graph/fluent/index.rst.txt @@ -0,0 +1,24 @@ +:mod:`cassandra.datastax.graph.fluent` +====================================== + +.. module:: cassandra.datastax.graph.fluent + +.. autoclass:: DseGraph + + .. autoattribute:: DSE_GRAPH_QUERY_LANGUAGE + + .. automethod:: create_execution_profile + + .. automethod:: query_from_traversal + + .. automethod:: traversal_source(session=None, graph_name=None, execution_profile=EXEC_PROFILE_GRAPH_DEFAULT, traversal_class=None) + + .. automethod:: batch(session=None, execution_profile=None) + +.. autoclass:: DSESessionRemoteGraphConnection(session[, graph_name, execution_profile]) + +.. autoclass:: BaseGraphRowFactory + +.. autoclass:: graph_traversal_row_factory + +.. autoclass:: graph_traversal_dse_object_row_factory diff --git a/3.21.0-scylla/_sources/api/cassandra/datastax/graph/fluent/predicates.rst.txt b/3.21.0-scylla/_sources/api/cassandra/datastax/graph/fluent/predicates.rst.txt new file mode 100644 index 0000000000..09f9e4c8fa --- /dev/null +++ b/3.21.0-scylla/_sources/api/cassandra/datastax/graph/fluent/predicates.rst.txt @@ -0,0 +1,11 @@ +:mod:`cassandra.datastax.graph.fluent.predicates` +================================================= + +.. module:: cassandra.datastax.graph.fluent.predicates + + +.. autoclass:: Search + :members: + +.. autoclass:: Geo + :members: diff --git a/3.21.0-scylla/_sources/api/cassandra/datastax/graph/fluent/query.rst.txt b/3.21.0-scylla/_sources/api/cassandra/datastax/graph/fluent/query.rst.txt new file mode 100644 index 0000000000..3dd859f96e --- /dev/null +++ b/3.21.0-scylla/_sources/api/cassandra/datastax/graph/fluent/query.rst.txt @@ -0,0 +1,8 @@ +:mod:`cassandra.datastax.graph.fluent.query` +============================================ + +.. module:: cassandra.datastax.graph.fluent.query + + +.. autoclass:: TraversalBatch + :members: diff --git a/3.21.0-scylla/_sources/api/cassandra/datastax/graph/index.rst.txt b/3.21.0-scylla/_sources/api/cassandra/datastax/graph/index.rst.txt new file mode 100644 index 0000000000..285ca5ffc2 --- /dev/null +++ b/3.21.0-scylla/_sources/api/cassandra/datastax/graph/index.rst.txt @@ -0,0 +1,94 @@ +``cassandra.datastax.graph`` - Graph Statements, Options, and Row Factories +=========================================================================== + +.. _api-datastax-graph: + +.. module:: cassandra.datastax.graph + +.. autofunction:: single_object_row_factory + +.. autofunction:: graph_result_row_factory + +.. autofunction:: graph_object_row_factory + +.. autoclass:: GraphProtocol + :members: + +.. autoclass:: GraphOptions + + .. autoattribute:: graph_name + + .. autoattribute:: graph_source + + .. autoattribute:: graph_language + + .. autoattribute:: graph_read_consistency_level + + .. autoattribute:: graph_write_consistency_level + + .. autoattribute:: is_default_source + + .. autoattribute:: is_analytics_source + + .. autoattribute:: is_graph_source + + .. automethod:: set_source_default + + .. automethod:: set_source_analytics + + .. automethod:: set_source_graph + + +.. autoclass:: SimpleGraphStatement + :members: + +.. autoclass:: Result + :members: + +.. autoclass:: Vertex + :members: + +.. autoclass:: VertexProperty + :members: + +.. autoclass:: Edge + :members: + +.. autoclass:: Path + :members: + +.. autoclass:: GraphSON1Serializer + :members: + +.. autoclass:: GraphSON1Deserializer + + .. automethod:: deserialize_date + + .. automethod:: deserialize_timestamp + + .. automethod:: deserialize_time + + .. automethod:: deserialize_duration + + .. automethod:: deserialize_int + + .. automethod:: deserialize_bigint + + .. automethod:: deserialize_double + + .. automethod:: deserialize_float + + .. automethod:: deserialize_uuid + + .. automethod:: deserialize_blob + + .. automethod:: deserialize_decimal + + .. automethod:: deserialize_point + + .. automethod:: deserialize_linestring + + .. automethod:: deserialize_polygon + +.. autoclass:: GraphSON2Reader + :members: diff --git a/3.21.0-scylla/_sources/api/cassandra/decoder.rst.txt b/3.21.0-scylla/_sources/api/cassandra/decoder.rst.txt new file mode 100644 index 0000000000..e213cc6d74 --- /dev/null +++ b/3.21.0-scylla/_sources/api/cassandra/decoder.rst.txt @@ -0,0 +1,20 @@ +``cassandra.decoder`` - Data Return Formats +=========================================== + +.. module:: cassandra.decoder + +.. function:: tuple_factory + + **Deprecated in 2.0.0.** Use :meth:`cassandra.query.tuple_factory` + +.. function:: named_tuple_factory + + **Deprecated in 2.0.0.** Use :meth:`cassandra.query.named_tuple_factory` + +.. function:: dict_factory + + **Deprecated in 2.0.0.** Use :meth:`cassandra.query.dict_factory` + +.. function:: ordered_dict_factory + + **Deprecated in 2.0.0.** Use :meth:`cassandra.query.ordered_dict_factory` diff --git a/3.21.0-scylla/_sources/api/cassandra/encoder.rst.txt b/3.21.0-scylla/_sources/api/cassandra/encoder.rst.txt new file mode 100644 index 0000000000..de3b180510 --- /dev/null +++ b/3.21.0-scylla/_sources/api/cassandra/encoder.rst.txt @@ -0,0 +1,36 @@ +``cassandra.encoder`` - Encoders for non-prepared Statements +============================================================ + +.. module:: cassandra.encoder + +.. autoclass:: Encoder () + + .. autoattribute:: cassandra.encoder.Encoder.mapping + + .. automethod:: cassandra.encoder.Encoder.cql_encode_none () + + .. automethod:: cassandra.encoder.Encoder.cql_encode_object () + + .. automethod:: cassandra.encoder.Encoder.cql_encode_all_types () + + .. automethod:: cassandra.encoder.Encoder.cql_encode_sequence () + + .. automethod:: cassandra.encoder.Encoder.cql_encode_str () + + .. automethod:: cassandra.encoder.Encoder.cql_encode_unicode () + + .. automethod:: cassandra.encoder.Encoder.cql_encode_bytes () + + Converts strings, buffers, and bytearrays into CQL blob literals. + + .. automethod:: cassandra.encoder.Encoder.cql_encode_datetime () + + .. automethod:: cassandra.encoder.Encoder.cql_encode_date () + + .. automethod:: cassandra.encoder.Encoder.cql_encode_map_collection () + + .. automethod:: cassandra.encoder.Encoder.cql_encode_list_collection () + + .. automethod:: cassandra.encoder.Encoder.cql_encode_set_collection () + + .. automethod:: cql_encode_tuple () diff --git a/3.21.0-scylla/_sources/api/cassandra/graph.rst.txt b/3.21.0-scylla/_sources/api/cassandra/graph.rst.txt new file mode 100644 index 0000000000..2211a25d96 --- /dev/null +++ b/3.21.0-scylla/_sources/api/cassandra/graph.rst.txt @@ -0,0 +1,94 @@ +``cassandra.graph`` - Graph Statements, Options, and Row Factories +================================================================== + +.. note:: This module is only for backward compatibility for dse-driver users. Consider using :ref:`cassandra.datastax.graph `. + +.. module:: cassandra.graph + +.. autofunction:: single_object_row_factory + +.. autofunction:: graph_result_row_factory + +.. autofunction:: graph_object_row_factory + +.. autoclass:: GraphProtocol + :members: + +.. autoclass:: GraphOptions + + .. autoattribute:: graph_name + + .. autoattribute:: graph_source + + .. autoattribute:: graph_language + + .. autoattribute:: graph_read_consistency_level + + .. autoattribute:: graph_write_consistency_level + + .. autoattribute:: is_default_source + + .. autoattribute:: is_analytics_source + + .. autoattribute:: is_graph_source + + .. automethod:: set_source_default + + .. automethod:: set_source_analytics + + .. automethod:: set_source_graph + + +.. autoclass:: SimpleGraphStatement + :members: + +.. autoclass:: Result + :members: + +.. autoclass:: Vertex + :members: + +.. autoclass:: VertexProperty + :members: + +.. autoclass:: Edge + :members: + +.. autoclass:: Path + :members: + +.. autoclass:: GraphSON1Serializer + :members: + +.. autoclass:: GraphSON1Deserializer + + .. automethod:: deserialize_date + + .. automethod:: deserialize_timestamp + + .. automethod:: deserialize_time + + .. automethod:: deserialize_duration + + .. automethod:: deserialize_int + + .. automethod:: deserialize_bigint + + .. automethod:: deserialize_double + + .. automethod:: deserialize_float + + .. automethod:: deserialize_uuid + + .. automethod:: deserialize_blob + + .. automethod:: deserialize_decimal + + .. automethod:: deserialize_point + + .. automethod:: deserialize_linestring + + .. automethod:: deserialize_polygon + +.. autoclass:: GraphSON2Reader + :members: diff --git a/3.21.0-scylla/_sources/api/cassandra/io/asyncioreactor.rst.txt b/3.21.0-scylla/_sources/api/cassandra/io/asyncioreactor.rst.txt new file mode 100644 index 0000000000..38ae63ca7f --- /dev/null +++ b/3.21.0-scylla/_sources/api/cassandra/io/asyncioreactor.rst.txt @@ -0,0 +1,7 @@ +``cassandra.io.asyncioreactor`` - ``asyncio`` Event Loop +===================================================================== + +.. module:: cassandra.io.asyncioreactor + +.. autoclass:: AsyncioConnection + :members: diff --git a/3.21.0-scylla/_sources/api/cassandra/io/asyncorereactor.rst.txt b/3.21.0-scylla/_sources/api/cassandra/io/asyncorereactor.rst.txt new file mode 100644 index 0000000000..ade7887e70 --- /dev/null +++ b/3.21.0-scylla/_sources/api/cassandra/io/asyncorereactor.rst.txt @@ -0,0 +1,7 @@ +``cassandra.io.asyncorereactor`` - ``asyncore`` Event Loop +========================================================== + +.. module:: cassandra.io.asyncorereactor + +.. autoclass:: AsyncoreConnection + :members: diff --git a/3.21.0-scylla/_sources/api/cassandra/io/eventletreactor.rst.txt b/3.21.0-scylla/_sources/api/cassandra/io/eventletreactor.rst.txt new file mode 100644 index 0000000000..1ba742c7e9 --- /dev/null +++ b/3.21.0-scylla/_sources/api/cassandra/io/eventletreactor.rst.txt @@ -0,0 +1,7 @@ +``cassandra.io.eventletreactor`` - ``eventlet``-compatible Connection +===================================================================== + +.. module:: cassandra.io.eventletreactor + +.. autoclass:: EventletConnection + :members: diff --git a/3.21.0-scylla/_sources/api/cassandra/io/geventreactor.rst.txt b/3.21.0-scylla/_sources/api/cassandra/io/geventreactor.rst.txt new file mode 100644 index 0000000000..603affe140 --- /dev/null +++ b/3.21.0-scylla/_sources/api/cassandra/io/geventreactor.rst.txt @@ -0,0 +1,7 @@ +``cassandra.io.geventreactor`` - ``gevent``-compatible Event Loop +================================================================= + +.. module:: cassandra.io.geventreactor + +.. autoclass:: GeventConnection + :members: diff --git a/3.21.0-scylla/_sources/api/cassandra/io/libevreactor.rst.txt b/3.21.0-scylla/_sources/api/cassandra/io/libevreactor.rst.txt new file mode 100644 index 0000000000..5b7288edf2 --- /dev/null +++ b/3.21.0-scylla/_sources/api/cassandra/io/libevreactor.rst.txt @@ -0,0 +1,6 @@ +``cassandra.io.libevreactor`` - ``libev`` Event Loop +==================================================== + +.. module:: cassandra.io.libevreactor + +.. autoclass:: LibevConnection diff --git a/3.21.0-scylla/_sources/api/cassandra/io/twistedreactor.rst.txt b/3.21.0-scylla/_sources/api/cassandra/io/twistedreactor.rst.txt new file mode 100644 index 0000000000..24e93bd432 --- /dev/null +++ b/3.21.0-scylla/_sources/api/cassandra/io/twistedreactor.rst.txt @@ -0,0 +1,9 @@ +``cassandra.io.twistedreactor`` - Twisted Event Loop +==================================================== + +.. module:: cassandra.io.twistedreactor + +.. class:: TwistedConnection + + An implementation of :class:`~cassandra.io.connection.Connection` that uses + Twisted's reactor as its event loop. diff --git a/3.21.0-scylla/_sources/api/cassandra/metadata.rst.txt b/3.21.0-scylla/_sources/api/cassandra/metadata.rst.txt new file mode 100644 index 0000000000..ed79d04f42 --- /dev/null +++ b/3.21.0-scylla/_sources/api/cassandra/metadata.rst.txt @@ -0,0 +1,76 @@ +``cassandra.metadata`` - Schema and Ring Topology +================================================= + +.. module:: cassandra.metadata + +.. autodata:: cql_keywords + :annotation: + +.. autodata:: cql_keywords_unreserved + :annotation: + +.. autodata:: cql_keywords_reserved + :annotation: + +.. autoclass:: Metadata () + :members: + :exclude-members: rebuild_schema, rebuild_token_map, add_host, remove_host + +Schemas +------- + +.. autoclass:: KeyspaceMetadata () + :members: + +.. autoclass:: UserType () + :members: + +.. autoclass:: Function () + :members: + +.. autoclass:: Aggregate () + :members: + +.. autoclass:: TableMetadata () + :members: + +.. autoclass:: ColumnMetadata () + :members: + +.. autoclass:: IndexMetadata () + :members: + +.. autoclass:: MaterializedViewMetadata () + :members: + +Tokens and Ring Topology +------------------------ + +.. autoclass:: TokenMap () + :members: + +.. autoclass:: Token () + :members: + +.. autoclass:: Murmur3Token + :members: + +.. autoclass:: MD5Token + :members: + +.. autoclass:: BytesToken + :members: + +.. autoclass:: ReplicationStrategy + :members: + +.. autoclass:: SimpleStrategy + :members: + +.. autoclass:: NetworkTopologyStrategy + :members: + +.. autoclass:: LocalStrategy + :members: + +.. autofunction:: group_keys_by_replica diff --git a/3.21.0-scylla/_sources/api/cassandra/metrics.rst.txt b/3.21.0-scylla/_sources/api/cassandra/metrics.rst.txt new file mode 100644 index 0000000000..0df7f8b5b9 --- /dev/null +++ b/3.21.0-scylla/_sources/api/cassandra/metrics.rst.txt @@ -0,0 +1,7 @@ +``cassandra.metrics`` - Performance Metrics +=========================================== + +.. module:: cassandra.metrics + +.. autoclass:: cassandra.metrics.Metrics () + :members: diff --git a/3.21.0-scylla/_sources/api/cassandra/policies.rst.txt b/3.21.0-scylla/_sources/api/cassandra/policies.rst.txt new file mode 100644 index 0000000000..387b19ed95 --- /dev/null +++ b/3.21.0-scylla/_sources/api/cassandra/policies.rst.txt @@ -0,0 +1,96 @@ +``cassandra.policies`` - Load balancing and Failure Handling Policies +===================================================================== + +.. module:: cassandra.policies + +Load Balancing +-------------- + +.. autoclass:: HostDistance + :members: + +.. autoclass:: LoadBalancingPolicy + :members: + +.. autoclass:: RoundRobinPolicy + :members: + +.. autoclass:: DCAwareRoundRobinPolicy + :members: + +.. autoclass:: WhiteListRoundRobinPolicy + :members: + +.. autoclass:: TokenAwarePolicy + :members: + +.. autoclass:: HostFilterPolicy + + .. we document these methods manually so we can specify a param to predicate + + .. automethod:: predicate(host) + .. automethod:: distance + .. automethod:: make_query_plan + +.. autoclass:: DefaultLoadBalancingPolicy + :members: + +.. autoclass:: DSELoadBalancingPolicy + :members: + +Translating Server Node Addresses +--------------------------------- + +.. autoclass:: AddressTranslator + :members: + +.. autoclass:: IdentityTranslator + :members: + +.. autoclass:: EC2MultiRegionTranslator + :members: + +Marking Hosts Up or Down +------------------------ + +.. autoclass:: ConvictionPolicy + :members: + +.. autoclass:: SimpleConvictionPolicy + :members: + +Reconnecting to Dead Hosts +-------------------------- + +.. autoclass:: ReconnectionPolicy + :members: + +.. autoclass:: ConstantReconnectionPolicy + :members: + +.. autoclass:: ExponentialReconnectionPolicy + :members: + +Retrying Failed Operations +-------------------------- + +.. autoclass:: WriteType + :members: + +.. autoclass:: RetryPolicy + :members: + +.. autoclass:: FallthroughRetryPolicy + :members: + +.. autoclass:: DowngradingConsistencyRetryPolicy + :members: + +Retrying Idempotent Operations +------------------------------ + +.. autoclass:: SpeculativeExecutionPolicy + :members: + +.. autoclass:: ConstantSpeculativeExecutionPolicy + :members: diff --git a/3.21.0-scylla/_sources/api/cassandra/pool.rst.txt b/3.21.0-scylla/_sources/api/cassandra/pool.rst.txt new file mode 100644 index 0000000000..b14d30e19c --- /dev/null +++ b/3.21.0-scylla/_sources/api/cassandra/pool.rst.txt @@ -0,0 +1,11 @@ +``cassandra.pool`` - Hosts and Connection Pools +=============================================== + +.. automodule:: cassandra.pool + +.. autoclass:: Host () + :members: + :exclude-members: set_location_info, get_and_set_reconnection_handler + +.. autoexception:: NoConnectionsAvailable + :members: diff --git a/3.21.0-scylla/_sources/api/cassandra/protocol.rst.txt b/3.21.0-scylla/_sources/api/cassandra/protocol.rst.txt new file mode 100644 index 0000000000..f615ab1a70 --- /dev/null +++ b/3.21.0-scylla/_sources/api/cassandra/protocol.rst.txt @@ -0,0 +1,55 @@ +``cassandra.protocol`` - Protocol Features +===================================================================== + +.. module:: cassandra.protocol + +.. _custom_payload: + +Custom Payloads +--------------- +Native protocol version 4+ allows for a custom payload to be sent between clients +and custom query handlers. The payload is specified as a string:binary_type dict +holding custom key/value pairs. + +By default these are ignored by the server. They can be useful for servers implementing +a custom QueryHandler. + +See :meth:`.Session.execute`, ::meth:`.Session.execute_async`, :attr:`.ResponseFuture.custom_payload`. + +.. autoclass:: _ProtocolHandler + + .. autoattribute:: message_types_by_opcode + :annotation: = {default mapping} + + .. automethod:: encode_message + + .. automethod:: decode_message + +.. _faster_deser: + +Faster Deserialization +---------------------- +When python-driver is compiled with Cython, it uses a Cython-based deserialization path +to deserialize messages. By default, the driver will use a Cython-based parser that returns +lists of rows similar to the pure-Python version. In addition, there are two additional +ProtocolHandler classes that can be used to deserialize response messages: ``LazyProtocolHandler`` +and ``NumpyProtocolHandler``. They can be used as follows: + +.. code:: python + + from cassandra.protocol import NumpyProtocolHandler, LazyProtocolHandler + from cassandra.query import tuple_factory + s.client_protocol_handler = LazyProtocolHandler # for a result iterator + s.row_factory = tuple_factory #required for Numpy results + s.client_protocol_handler = NumpyProtocolHandler # for a dict of NumPy arrays as result + +These protocol handlers comprise different parsers, and return results as described below: + +- ProtocolHandler: this default implementation is a drop-in replacement for the pure-Python version. + The rows are all parsed upfront, before results are returned. + +- LazyProtocolHandler: near drop-in replacement for the above, except that it returns an iterator over rows, + lazily decoded into the default row format (this is more efficient since all decoded results are not materialized at once) + +- NumpyProtocolHander: deserializes results directly into NumPy arrays. This facilitates efficient integration with + analysis toolkits such as Pandas. diff --git a/3.21.0-scylla/_sources/api/cassandra/query.rst.txt b/3.21.0-scylla/_sources/api/cassandra/query.rst.txt new file mode 100644 index 0000000000..fcd79739b9 --- /dev/null +++ b/3.21.0-scylla/_sources/api/cassandra/query.rst.txt @@ -0,0 +1,59 @@ +``cassandra.query`` - Prepared Statements, Batch Statements, Tracing, and Row Factories +======================================================================================= + +.. module:: cassandra.query + +.. autofunction:: tuple_factory + +.. autofunction:: named_tuple_factory + +.. autofunction:: dict_factory + +.. autofunction:: ordered_dict_factory + +.. autoclass:: SimpleStatement + :members: + +.. autoclass:: PreparedStatement () + :members: + +.. autoclass:: BoundStatement + :members: + +.. autoclass:: Statement () + :members: + +.. autodata:: UNSET_VALUE + :annotation: + +.. autoclass:: BatchStatement (batch_type=BatchType.LOGGED, retry_policy=None, consistency_level=None) + :members: + +.. autoclass:: BatchType () + + .. autoattribute:: LOGGED + + .. autoattribute:: UNLOGGED + + .. autoattribute:: COUNTER + +.. autoclass:: cassandra.query.ValueSequence + + A wrapper class that is used to specify that a sequence of values should + be treated as a CQL list of values instead of a single column collection when used + as part of the `parameters` argument for :meth:`.Session.execute()`. + + This is typically needed when supplying a list of keys to select. + For example:: + + >>> my_user_ids = ('alice', 'bob', 'charles') + >>> query = "SELECT * FROM users WHERE user_id IN %s" + >>> session.execute(query, parameters=[ValueSequence(my_user_ids)]) + +.. autoclass:: QueryTrace () + :members: + +.. autoclass:: TraceEvent () + :members: + +.. autoexception:: TraceUnavailable diff --git a/3.21.0-scylla/_sources/api/cassandra/timestamps.rst.txt b/3.21.0-scylla/_sources/api/cassandra/timestamps.rst.txt new file mode 100644 index 0000000000..7c7f534aea --- /dev/null +++ b/3.21.0-scylla/_sources/api/cassandra/timestamps.rst.txt @@ -0,0 +1,14 @@ +``cassandra.timestamps`` - Timestamp Generation +============================================= + +.. module:: cassandra.timestamps + +.. autoclass:: MonotonicTimestampGenerator (warn_on_drift=True, warning_threshold=0, warning_interval=0) + + .. autoattribute:: warn_on_drift + + .. autoattribute:: warning_threshold + + .. autoattribute:: warning_interval + + .. automethod:: _next_timestamp diff --git a/3.21.0-scylla/_sources/api/cassandra/util.rst.txt b/3.21.0-scylla/_sources/api/cassandra/util.rst.txt new file mode 100644 index 0000000000..848d4d5fc2 --- /dev/null +++ b/3.21.0-scylla/_sources/api/cassandra/util.rst.txt @@ -0,0 +1,5 @@ +``cassandra.util`` - Utilities +=================================== + +.. automodule:: cassandra.util + :members: diff --git a/3.21.0-scylla/_sources/api/index.rst.txt b/3.21.0-scylla/_sources/api/index.rst.txt new file mode 100644 index 0000000000..9e778d508c --- /dev/null +++ b/3.21.0-scylla/_sources/api/index.rst.txt @@ -0,0 +1,54 @@ +API Documentation +================= + +Core Driver +----------- +.. toctree:: + :maxdepth: 2 + + cassandra + cassandra/cluster + cassandra/policies + cassandra/auth + cassandra/graph + cassandra/metadata + cassandra/metrics + cassandra/query + cassandra/pool + cassandra/protocol + cassandra/encoder + cassandra/decoder + cassandra/concurrent + cassandra/connection + cassandra/util + cassandra/timestamps + cassandra/io/asyncioreactor + cassandra/io/asyncorereactor + cassandra/io/eventletreactor + cassandra/io/libevreactor + cassandra/io/geventreactor + cassandra/io/twistedreactor + +.. _om_api: + +Object Mapper +------------- +.. toctree:: + :maxdepth: 1 + + cassandra/cqlengine/models + cassandra/cqlengine/columns + cassandra/cqlengine/query + cassandra/cqlengine/connection + cassandra/cqlengine/management + cassandra/cqlengine/usertype + +DataStax Graph +-------------- +.. toctree:: + :maxdepth: 1 + + cassandra/datastax/graph/index + cassandra/datastax/graph/fluent/index + cassandra/datastax/graph/fluent/query + cassandra/datastax/graph/fluent/predicates diff --git a/3.21.0-scylla/_sources/cqlengine/batches.rst.txt b/3.21.0-scylla/_sources/cqlengine/batches.rst.txt new file mode 100644 index 0000000000..306e7d01a6 --- /dev/null +++ b/3.21.0-scylla/_sources/cqlengine/batches.rst.txt @@ -0,0 +1,108 @@ +============= +Batch Queries +============= + +cqlengine supports batch queries using the BatchQuery class. Batch queries can be started and stopped manually, or within a context manager. To add queries to the batch object, you just need to precede the create/save/delete call with a call to batch, and pass in the batch object. + + +Batch Query General Use Pattern +=============================== + +You can only create, update, and delete rows with a batch query, attempting to read rows out of the database with a batch query will fail. + +.. code-block:: python + + from cassandra.cqlengine.query import BatchQuery + + #using a context manager + with BatchQuery() as b: + now = datetime.now() + em1 = ExampleModel.batch(b).create(example_type=0, description="1", created_at=now) + em2 = ExampleModel.batch(b).create(example_type=0, description="2", created_at=now) + em3 = ExampleModel.batch(b).create(example_type=0, description="3", created_at=now) + + # -- or -- + + #manually + b = BatchQuery() + now = datetime.now() + em1 = ExampleModel.batch(b).create(example_type=0, description="1", created_at=now) + em2 = ExampleModel.batch(b).create(example_type=0, description="2", created_at=now) + em3 = ExampleModel.batch(b).create(example_type=0, description="3", created_at=now) + b.execute() + + # updating in a batch + + b = BatchQuery() + em1.description = "new description" + em1.batch(b).save() + em2.description = "another new description" + em2.batch(b).save() + b.execute() + + # deleting in a batch + b = BatchQuery() + ExampleModel.objects(id=some_id).batch(b).delete() + ExampleModel.objects(id=some_id2).batch(b).delete() + b.execute() + + +Typically you will not want the block to execute if an exception occurs inside the `with` block. However, in the case that this is desirable, it's achievable by using the following syntax: + +.. code-block:: python + + with BatchQuery(execute_on_exception=True) as b: + LogEntry.batch(b).create(k=1, v=1) + mystery_function() # exception thrown in here + LogEntry.batch(b).create(k=1, v=2) # this code is never reached due to the exception, but anything leading up to here will execute in the batch. + +If an exception is thrown somewhere in the block, any statements that have been added to the batch will still be executed. This is useful for some logging situations. + +Batch Query Execution Callbacks +=============================== + +In order to allow secondary tasks to be chained to the end of batch, BatchQuery instances allow callbacks to be +registered with the batch, to be executed immediately after the batch executes. + +Multiple callbacks can be attached to same BatchQuery instance, they are executed in the same order that they +are added to the batch. + +The callbacks attached to a given batch instance are executed only if the batch executes. If the batch is used as a +context manager and an exception is raised, the queued up callbacks will not be run. + +.. code-block:: python + + def my_callback(*args, **kwargs): + pass + + batch = BatchQuery() + + batch.add_callback(my_callback) + batch.add_callback(my_callback, 'positional arg', named_arg='named arg value') + + # if you need reference to the batch within the callback, + # just trap it in the arguments to be passed to the callback: + batch.add_callback(my_callback, cqlengine_batch=batch) + + # once the batch executes... + batch.execute() + + # the effect of the above scheduled callbacks will be similar to + my_callback() + my_callback('positional arg', named_arg='named arg value') + my_callback(cqlengine_batch=batch) + +Failure in any of the callbacks does not affect the batch's execution, as the callbacks are started after the execution +of the batch is complete. + +Logged vs Unlogged Batches +--------------------------- +By default, queries in cqlengine are LOGGED, which carries additional overhead from UNLOGGED. To explicitly state which batch type to use, simply: + + +.. code-block:: python + + from cassandra.cqlengine.query import BatchType + with BatchQuery(batch_type=BatchType.Unlogged) as b: + LogEntry.batch(b).create(k=1, v=1) + LogEntry.batch(b).create(k=1, v=2) diff --git a/3.21.0-scylla/_sources/cqlengine/connections.rst.txt b/3.21.0-scylla/_sources/cqlengine/connections.rst.txt new file mode 100644 index 0000000000..03ade27521 --- /dev/null +++ b/3.21.0-scylla/_sources/cqlengine/connections.rst.txt @@ -0,0 +1,137 @@ +=========== +Connections +=========== + +Connections aim to ease the use of multiple sessions with cqlengine. Connections can be set on a model class, per query or using a context manager. + + +Register a new connection +========================= + +To use cqlengine, you need at least a default connection. If you initialize cqlengine's connections with with :func:`connection.setup <.connection.setup>`, a connection will be created automatically. If you want to use another cluster/session, you need to register a new cqlengine connection. You register a connection with :func:`~.connection.register_connection`: + +.. code-block:: python + + from cassandra.cqlengine import connection + + connection.setup(['127.0.0.1') + connection.register_connection('cluster2', ['127.0.0.2']) + +:func:`~.connection.register_connection` can take a list of hosts, as shown above, in which case it will create a connection with a new session. It can also take a `session` argument if you've already created a session: + +.. code-block:: python + + from cassandra.cqlengine import connection + from cassandra.cluster import Cluster + + session = Cluster(['127.0.0.1']).connect() + connection.register_connection('cluster3', session=session) + + +Change the default connection +============================= + +You can change the default cqlengine connection on registration: + +.. code-block:: python + + from cassandra.cqlengine import connection + + connection.register_connection('cluster2', ['127.0.0.2'] default=True) + +or on the fly using :func:`~.connection.set_default_connection` + +.. code-block:: python + + connection.set_default_connection('cluster2') + +Unregister a connection +======================= + +You can unregister a connection using :func:`~.connection.unregister_connection`: + +.. code-block:: python + + connection.unregister_connection('cluster2') + +Management +========== + +When using multiples connections, you also need to sync your models on all connections (and keyspaces) that you need operate on. Management commands have been improved to ease this part. Here is an example: + +.. code-block:: python + + from cassandra.cqlengine import management + + keyspaces = ['ks1', 'ks2'] + conns = ['cluster1', 'cluster2'] + + # registers your connections + # ... + + # create all keyspaces on all connections + for ks in keyspaces: + management.create_simple_keyspace(ks, connections=conns) + + # define your Automobile model + # ... + + # sync your models + management.sync_table(Automobile, keyspaces=keyspaces, connections=conns) + + +Connection Selection +==================== + +cqlengine will select the default connection, unless your specify a connection using one of the following methods. + +Default Model Connection +------------------------ + +You can specify a default connection per model: + +.. code-block:: python + + class Automobile(Model): + __keyspace__ = 'test' + __connection__ = 'cluster2' + manufacturer = columns.Text(primary_key=True) + year = columns.Integer(primary_key=True) + model = columns.Text(primary_key=True) + + print len(Automobile.objects.all()) # executed on the connection 'cluster2' + +QuerySet and model instance +--------------------------- + +You can use the :attr:`using() <.query.ModelQuerySet.using>` method to select a connection (or keyspace): + +.. code-block:: python + + Automobile.objects.using(connection='cluster1').create(manufacturer='honda', year=2010, model='civic') + q = Automobile.objects.filter(manufacturer='Tesla') + autos = q.using(keyspace='ks2', connection='cluster2').all() + + for auto in autos: + auto.using(connection='cluster1').save() + +Context Manager +--------------- + +You can use the ContextQuery as well to select a connection: + +.. code-block:: python + + with ContextQuery(Automobile, connection='cluster1') as A: + A.objects.filter(manufacturer='honda').all() # executed on 'cluster1' + + +BatchQuery +---------- + +With a BatchQuery, you can select the connection with the context manager. Note that all operations in the batch need to use the same connection. + +.. code-block:: python + + with BatchQuery(connection='cluster1') as b: + Automobile.objects.batch(b).create(manufacturer='honda', year=2010, model='civic') diff --git a/3.21.0-scylla/_sources/cqlengine/faq.rst.txt b/3.21.0-scylla/_sources/cqlengine/faq.rst.txt new file mode 100644 index 0000000000..6c056d02ea --- /dev/null +++ b/3.21.0-scylla/_sources/cqlengine/faq.rst.txt @@ -0,0 +1,67 @@ +========================== +Frequently Asked Questions +========================== + +Why don't updates work correctly on models instantiated as Model(field=value, field2=value2)? +------------------------------------------------------------------------------------------------ + +The recommended way to create new rows is with the models .create method. The values passed into a model's init method are interpreted by the model as the values as they were read from a row. This allows the model to "know" which rows have changed since the row was read out of cassandra, and create suitable update statements. + +How to preserve ordering in batch query? +------------------------------------------- + +Statement Ordering is not supported by CQL3 batches. Therefore, +once cassandra needs resolving conflict(Updating the same column in one batch), +The algorithm below would be used. + +* If timestamps are different, pick the column with the largest timestamp (the value being a regular column or a tombstone) +* If timestamps are the same, and one of the columns in a tombstone ('null') - pick the tombstone +* If timestamps are the same, and none of the columns are tombstones, pick the column with the largest value + +Below is an example to show this scenario. + +.. code-block:: python + + class MyMode(Model): + id = columns.Integer(primary_key=True) + count = columns.Integer() + text = columns.Text() + + with BatchQuery() as b: + MyModel.batch(b).create(id=1, count=2, text='123') + MyModel.batch(b).create(id=1, count=3, text='111') + + assert MyModel.objects(id=1).first().count == 3 + assert MyModel.objects(id=1).first().text == '123' + +The largest value of count is 3, and the largest value of text would be '123'. + +The workaround is applying timestamp to each statement, then Cassandra would +resolve to the statement with the lastest timestamp. + +.. code-block:: python + + with BatchQuery() as b: + MyModel.timestamp(datetime.now()).batch(b).create(id=1, count=2, text='123') + MyModel.timestamp(datetime.now()).batch(b).create(id=1, count=3, text='111') + + assert MyModel.objects(id=1).first().count == 3 + assert MyModel.objects(id=1).first().text == '111' + +How can I delete individual values from a row? +------------------------------------------------- + +When inserting with CQLEngine, ``None`` is equivalent to CQL ``NULL`` or to +issuing a ``DELETE`` on that column. For example: + +.. code-block:: python + + class MyModel(Model): + id = columns.Integer(primary_key=True) + text = columns.Text() + + m = MyModel.create(id=1, text='We can delete this with None') + assert MyModel.objects(id=1).first().text is not None + + m.update(text=None) + assert MyModel.objects(id=1).first().text is None diff --git a/3.21.0-scylla/_sources/cqlengine/models.rst.txt b/3.21.0-scylla/_sources/cqlengine/models.rst.txt new file mode 100644 index 0000000000..c0ba390119 --- /dev/null +++ b/3.21.0-scylla/_sources/cqlengine/models.rst.txt @@ -0,0 +1,218 @@ +====== +Models +====== + +.. module:: cqlengine.models + +A model is a python class representing a CQL table. Models derive from :class:`Model`, and +define basic table properties and columns for a table. + +Columns in your models map to columns in your CQL table. You define CQL columns by defining column attributes on your model classes. +For a model to be valid it needs at least one primary key column and one non-primary key column. Just as in CQL, the order you define +your columns in is important, and is the same order they are defined in on a model's corresponding table. + +Some basic examples defining models are shown below. Consult the :doc:`Model API docs ` and :doc:`Column API docs ` for complete details. + +Example Definitions +=================== + +This example defines a ``Person`` table, with the columns ``first_name`` and ``last_name`` + +.. code-block:: python + + from cassandra.cqlengine import columns + from cassandra.cqlengine.models import Model + + class Person(Model): + id = columns.UUID(primary_key=True) + first_name = columns.Text() + last_name = columns.Text() + + +The Person model would create this CQL table: + +.. code-block:: sql + + CREATE TABLE cqlengine.person ( + id uuid, + first_name text, + last_name text, + PRIMARY KEY (id) + ); + +Here's an example of a comment table created with clustering keys, in descending order: + +.. code-block:: python + + from cassandra.cqlengine import columns + from cassandra.cqlengine.models import Model + + class Comment(Model): + photo_id = columns.UUID(primary_key=True) + comment_id = columns.TimeUUID(primary_key=True, clustering_order="DESC") + comment = columns.Text() + +The Comment model's ``create table`` would look like the following: + +.. code-block:: sql + + CREATE TABLE comment ( + photo_id uuid, + comment_id timeuuid, + comment text, + PRIMARY KEY (photo_id, comment_id) + ) WITH CLUSTERING ORDER BY (comment_id DESC); + +To sync the models to the database, you may do the following*: + +.. code-block:: python + + from cassandra.cqlengine.management import sync_table + sync_table(Person) + sync_table(Comment) + +\*Note: synchronizing models causes schema changes, and should be done with caution. +Please see the discussion in :doc:`/api/cassandra/cqlengine/management` for considerations. + +For examples on manipulating data and creating queries, see :doc:`queryset` + +Manipulating model instances as dictionaries +============================================ + +Model instances can be accessed like dictionaries. + +.. code-block:: python + + class Person(Model): + first_name = columns.Text() + last_name = columns.Text() + + kevin = Person.create(first_name="Kevin", last_name="Deldycke") + dict(kevin) # returns {'first_name': 'Kevin', 'last_name': 'Deldycke'} + kevin['first_name'] # returns 'Kevin' + kevin.keys() # returns ['first_name', 'last_name'] + kevin.values() # returns ['Kevin', 'Deldycke'] + kevin.items() # returns [('first_name', 'Kevin'), ('last_name', 'Deldycke')] + + kevin['first_name'] = 'KEVIN5000' # changes the models first name + +Extending Model Validation +========================== + +Each time you save a model instance in cqlengine, the data in the model is validated against the schema you've defined +for your model. Most of the validation is fairly straightforward, it basically checks that you're not trying to do +something like save text into an integer column, and it enforces the ``required`` flag set on column definitions. +It also performs any transformations needed to save the data properly. + +However, there are often additional constraints or transformations you want to impose on your data, beyond simply +making sure that Cassandra won't complain when you try to insert it. To define additional validation on a model, +extend the model's validation method: + +.. code-block:: python + + class Member(Model): + person_id = UUID(primary_key=True) + name = Text(required=True) + + def validate(self): + super(Member, self).validate() + if self.name == 'jon': + raise ValidationError('no jon\'s allowed') + +*Note*: while not required, the convention is to raise a ``ValidationError`` (``from cassandra.cqlengine import ValidationError``) +if validation fails. + +.. _model_inheritance: + +Model Inheritance +================= +It is possible to save and load different model classes using a single CQL table. +This is useful in situations where you have different object types that you want to store in a single cassandra row. + +For instance, suppose you want a table that stores rows of pets owned by an owner: + +.. code-block:: python + + class Pet(Model): + __table_name__ = 'pet' + owner_id = UUID(primary_key=True) + pet_id = UUID(primary_key=True) + pet_type = Text(discriminator_column=True) + name = Text() + + def eat(self, food): + pass + + def sleep(self, time): + pass + + class Cat(Pet): + __discriminator_value__ = 'cat' + cuteness = Float() + + def tear_up_couch(self): + pass + + class Dog(Pet): + __discriminator_value__ = 'dog' + fierceness = Float() + + def bark_all_night(self): + pass + +After calling ``sync_table`` on each of these tables, the columns defined in each model will be added to the +``pet`` table. Additionally, saving ``Cat`` and ``Dog`` models will save the meta data needed to identify each row +as either a cat or dog. + +To setup a model structure with inheritance, follow these steps + +1. Create a base model with a column set as the distriminator (``distriminator_column=True`` in the column definition) +2. Create subclass models, and define a unique ``__discriminator_value__`` value on each +3. Run ``sync_table`` on each of the sub tables + +**About the discriminator value** + +The discriminator value is what cqlengine uses under the covers to map logical cql rows to the appropriate model type. The +base model maintains a map of discriminator values to subclasses. When a specialized model is saved, its discriminator value is +automatically saved into the discriminator column. The discriminator column may be any column type except counter and container types. +Additionally, if you set ``index=True`` on your discriminator column, you can execute queries against specialized subclasses, and a +``WHERE`` clause will be automatically added to your query, returning only rows of that type. Note that you must +define a unique ``__discriminator_value__`` to each subclass, and that you can only assign a single discriminator column per model. + +.. _user_types: + +User Defined Types +================== +cqlengine models User Defined Types (UDTs) much like tables, with fields defined by column type attributes. However, UDT instances +are only created, presisted, and queried via table Models. A short example to introduce the pattern:: + + from cassandra.cqlengine.columns import * + from cassandra.cqlengine.models import Model + from cassandra.cqlengine.usertype import UserType + + class address(UserType): + street = Text() + zipcode = Integer() + + class users(Model): + __keyspace__ = 'account' + name = Text(primary_key=True) + addr = UserDefinedType(address) + + users.create(name="Joe", addr=address(street="Easy St.", zipcode=99999)) + user = users.objects(name="Joe")[0] + print user.name, user.addr + # Joe address(street=u'Easy St.', zipcode=99999) + +UDTs are modeled by inheriting :class:`~.usertype.UserType`, and setting column type attributes. Types are then used in defining +models by declaring a column of type :class:`~.columns.UserDefinedType`, with the ``UserType`` class as a parameter. + +``sync_table`` will implicitly +synchronize any types contained in the table. Alternatively :func:`~.management.sync_type` can be used to create/alter types +explicitly. + +Upon declaration, types are automatically registered with the driver, so query results return instances of your ``UserType`` +class*. + +***Note**: UDTs were not added to the native protocol until v3. When setting up the cqlengine connection, be sure to specify +``protocol_version=3``. If using an earlier version, UDT queries will still work, but the returned type will be a namedtuple. diff --git a/3.21.0-scylla/_sources/cqlengine/queryset.rst.txt b/3.21.0-scylla/_sources/cqlengine/queryset.rst.txt new file mode 100644 index 0000000000..375ea22316 --- /dev/null +++ b/3.21.0-scylla/_sources/cqlengine/queryset.rst.txt @@ -0,0 +1,419 @@ +============== +Making Queries +============== + +.. module:: cqlengine.queryset + +Retrieving objects +================== +Once you've populated Cassandra with data, you'll probably want to retrieve some of it. This is accomplished with QuerySet objects. This section will describe how to use QuerySet objects to retrieve the data you're looking for. + +Retrieving all objects +---------------------- +The simplest query you can make is to return all objects from a table. + +This is accomplished with the ``.all()`` method, which returns a QuerySet of all objects in a table + +Using the Person example model, we would get all Person objects like this: + +.. code-block:: python + + all_objects = Person.objects.all() + +.. _retrieving-objects-with-filters: + +Retrieving objects with filters +------------------------------- +Typically, you'll want to query only a subset of the records in your database. + +That can be accomplished with the QuerySet's ``.filter(\*\*)`` method. + +For example, given the model definition: + +.. code-block:: python + + class Automobile(Model): + manufacturer = columns.Text(primary_key=True) + year = columns.Integer(primary_key=True) + model = columns.Text() + price = columns.Decimal() + options = columns.Set(columns.Text) + +...and assuming the Automobile table contains a record of every car model manufactured in the last 20 years or so, we can retrieve only the cars made by a single manufacturer like this: + + +.. code-block:: python + + q = Automobile.objects.filter(manufacturer='Tesla') + +You can also use the more convenient syntax: + +.. code-block:: python + + q = Automobile.objects(Automobile.manufacturer == 'Tesla') + +We can then further filter our query with another call to **.filter** + +.. code-block:: python + + q = q.filter(year=2012) + +*Note: all queries involving any filtering MUST define either an '=' or an 'in' relation to either a primary key column, or an indexed column.* + +Accessing objects in a QuerySet +=============================== + +There are several methods for getting objects out of a queryset + +* iterating over the queryset + .. code-block:: python + + for car in Automobile.objects.all(): + #...do something to the car instance + pass + +* list index + .. code-block:: python + + q = Automobile.objects.all() + q[0] #returns the first result + q[1] #returns the second result + + .. note:: + + * CQL does not support specifying a start position in it's queries. Therefore, accessing elements using array indexing will load every result up to the index value requested + * Using negative indices requires a "SELECT COUNT()" to be executed. This has a performance cost on large datasets. + +* list slicing + .. code-block:: python + + q = Automobile.objects.all() + q[1:] #returns all results except the first + q[1:9] #returns a slice of the results + + .. note:: + + * CQL does not support specifying a start position in it's queries. Therefore, accessing elements using array slicing will load every result up to the index value requested + * Using negative indices requires a "SELECT COUNT()" to be executed. This has a performance cost on large datasets. + +* calling :attr:`get() ` on the queryset + .. code-block:: python + + q = Automobile.objects.filter(manufacturer='Tesla') + q = q.filter(year=2012) + car = q.get() + + this returns the object matching the queryset + +* calling :attr:`first() ` on the queryset + .. code-block:: python + + q = Automobile.objects.filter(manufacturer='Tesla') + q = q.filter(year=2012) + car = q.first() + + this returns the first value in the queryset + +.. _query-filtering-operators: + +Filtering Operators +=================== + +:attr:`Equal To ` + +The default filtering operator. + +.. code-block:: python + + q = Automobile.objects.filter(manufacturer='Tesla') + q = q.filter(year=2012) #year == 2012 + +In addition to simple equal to queries, cqlengine also supports querying with other operators by appending a ``__`` to the field name on the filtering call + +:attr:`in (__in) ` + +.. code-block:: python + + q = Automobile.objects.filter(manufacturer='Tesla') + q = q.filter(year__in=[2011, 2012]) + + +:attr:`> (__gt) ` + +.. code-block:: python + + q = Automobile.objects.filter(manufacturer='Tesla') + q = q.filter(year__gt=2010) # year > 2010 + + # or the nicer syntax + + q.filter(Automobile.year > 2010) + +:attr:`>= (__gte) ` + +.. code-block:: python + + q = Automobile.objects.filter(manufacturer='Tesla') + q = q.filter(year__gte=2010) # year >= 2010 + + # or the nicer syntax + + q.filter(Automobile.year >= 2010) + +:attr:`< (__lt) ` + +.. code-block:: python + + q = Automobile.objects.filter(manufacturer='Tesla') + q = q.filter(year__lt=2012) # year < 2012 + + # or... + + q.filter(Automobile.year < 2012) + +:attr:`<= (__lte) ` + +.. code-block:: python + + q = Automobile.objects.filter(manufacturer='Tesla') + q = q.filter(year__lte=2012) # year <= 2012 + + q.filter(Automobile.year <= 2012) + +:attr:`CONTAINS (__contains) ` + +The CONTAINS operator is available for all collection types (List, Set, Map). + +.. code-block:: python + + q = Automobile.objects.filter(manufacturer='Tesla') + q.filter(options__contains='backup camera').allow_filtering() + +Note that we need to use allow_filtering() since the *options* column has no secondary index. + +:attr:`LIKE (__like) ` + +The LIKE operator is available for text columns that have a SASI secondary index. + +.. code-block:: python + + q = Automobile.objects.filter(model__like='%Civic%').allow_filtering() + +:attr:`IS NOT NULL (IsNotNull(column_name)) ` + +The IS NOT NULL operator is not yet supported for C*. + +.. code-block:: python + + q = Automobile.objects.filter(IsNotNull('model')) + +Limitations: + +- Currently, cqlengine does not support SASI index creation. To use this feature, you need to create the SASI index using the core driver. +- Queries using LIKE must use allow_filtering() since the *model* column has no standard secondary index. Note that the server will use the SASI index properly when executing the query. + +TimeUUID Functions +================== + +In addition to querying using regular values, there are two functions you can pass in when querying TimeUUID columns to help make filtering by them easier. Note that these functions don't actually return a value, but instruct the cql interpreter to use the functions in it's query. + +.. class:: MinTimeUUID(datetime) + + returns the minimum time uuid value possible for the given datetime + +.. class:: MaxTimeUUID(datetime) + + returns the maximum time uuid value possible for the given datetime + +*Example* + +.. code-block:: python + + class DataStream(Model): + id = columns.UUID(partition_key=True) + time = columns.TimeUUID(primary_key=True) + data = columns.Bytes() + + min_time = datetime(1982, 1, 1) + max_time = datetime(1982, 3, 9) + + DataStream.filter(time__gt=functions.MinTimeUUID(min_time), time__lt=functions.MaxTimeUUID(max_time)) + +Token Function +============== + +Token functon may be used only on special, virtual column pk__token, representing token of partition key (it also works for composite partition keys). +Cassandra orders returned items by value of partition key token, so using cqlengine.Token we can easy paginate through all table rows. + +See http://cassandra.apache.org/doc/cql3/CQL-3.0.html#tokenFun + +*Example* + +.. code-block:: python + + class Items(Model): + id = columns.Text(primary_key=True) + data = columns.Bytes() + + query = Items.objects.all().limit(10) + + first_page = list(query); + last = first_page[-1] + next_page = list(query.filter(pk__token__gt=cqlengine.Token(last.pk))) + +QuerySets are immutable +======================= + +When calling any method that changes a queryset, the method does not actually change the queryset object it's called on, but returns a new queryset object with the attributes of the original queryset, plus the attributes added in the method call. + +*Example* + +.. code-block:: python + + #this produces 3 different querysets + #q does not change after it's initial definition + q = Automobiles.objects.filter(year=2012) + tesla2012 = q.filter(manufacturer='Tesla') + honda2012 = q.filter(manufacturer='Honda') + +Ordering QuerySets +================== + +Since Cassandra is essentially a distributed hash table on steroids, the order you get records back in will not be particularly predictable. + +However, you can set a column to order on with the ``.order_by(column_name)`` method. + +*Example* + +.. code-block:: python + + #sort ascending + q = Automobiles.objects.all().order_by('year') + #sort descending + q = Automobiles.objects.all().order_by('-year') + +*Note: Cassandra only supports ordering on a clustering key. In other words, to support ordering results, your model must have more than one primary key, and you must order on a primary key, excluding the first one.* + +*For instance, given our Automobile model, year is the only column we can order on.* + +Values Lists +============ + +There is a special QuerySet's method ``.values_list()`` - when called, QuerySet returns lists of values instead of model instances. It may significantly speedup things with lower memory footprint for large responses. +Each tuple contains the value from the respective field passed into the ``values_list()`` call — so the first item is the first field, etc. For example: + +.. code-block:: python + + items = list(range(20)) + random.shuffle(items) + for i in items: + TestModel.create(id=1, clustering_key=i) + + values = list(TestModel.objects.values_list('clustering_key', flat=True)) + # [19L, 18L, 17L, 16L, 15L, 14L, 13L, 12L, 11L, 10L, 9L, 8L, 7L, 6L, 5L, 4L, 3L, 2L, 1L, 0L] + +Per Query Timeouts +=================== + +By default all queries are executed with the timeout defined in `~cqlengine.connection.setup()` +The examples below show how to specify a per-query timeout. +A timeout is specified in seconds and can be an int, float or None. +None means no timeout. + + +.. code-block:: python + + class Row(Model): + id = columns.Integer(primary_key=True) + name = columns.Text() + + +Fetch all objects with a timeout of 5 seconds + +.. code-block:: python + + Row.objects().timeout(5).all() + +Create a single row with a 50ms timeout + +.. code-block:: python + + Row(id=1, name='Jon').timeout(0.05).create() + +Delete a single row with no timeout + +.. code-block:: python + + Row(id=1).timeout(None).delete() + +Update a single row with no timeout + +.. code-block:: python + + Row(id=1).timeout(None).update(name='Blake') + +Batch query timeouts + +.. code-block:: python + + with BatchQuery(timeout=10) as b: + Row(id=1, name='Jon').create() + + +NOTE: You cannot set both timeout and batch at the same time, batch will use the timeout defined in it's constructor. +Setting the timeout on the model is meaningless and will raise an AssertionError. + + +.. _ttl-change: + +Default TTL and Per Query TTL +============================= + +Model default TTL now relies on the *default_time_to_live* feature, introduced in Cassandra 2.0. It is not handled anymore in the CQLEngine Model (scylla-driver >=3.6). You can set the default TTL of a table like this: + +Example: + +.. code-block:: python + + class User(Model): + __options__ = {'default_time_to_live': 20} + + user_id = columns.UUID(primary_key=True) + ... + +You can set TTL per-query if needed. Here are a some examples: + +Example: + +.. code-block:: python + + class User(Model): + __options__ = {'default_time_to_live': 20} + + user_id = columns.UUID(primary_key=True) + ... + + user = User.objects.create(user_id=1) # Default TTL 20 will be set automatically on the server + + user.ttl(30).update(age=21) # Update the TTL to 30 + User.objects.ttl(10).create(user_id=1) # TTL 10 + User(user_id=1, age=21).ttl(10).save() # TTL 10 + + +Named Tables +=================== + +Named tables are a way of querying a table without creating an class. They're useful for querying system tables or exploring an unfamiliar database. + + +.. code-block:: python + + from cassandra.cqlengine.connection import setup + setup("127.0.0.1", "cqlengine_test") + + from cassandra.cqlengine.named import NamedTable + user = NamedTable("cqlengine_test", "user") + user.objects() + user.objects()[0] + + # {u'pk': 1, u't': datetime.datetime(2014, 6, 26, 17, 10, 31, 774000)} diff --git a/3.21.0-scylla/_sources/cqlengine/third_party.rst.txt b/3.21.0-scylla/_sources/cqlengine/third_party.rst.txt new file mode 100644 index 0000000000..20c26df304 --- /dev/null +++ b/3.21.0-scylla/_sources/cqlengine/third_party.rst.txt @@ -0,0 +1,64 @@ +======================== +Third party integrations +======================== + + +Celery +------ + +Here's how, in substance, CQLengine can be plugged to `Celery +`_: + +.. code-block:: python + + from celery import Celery + from celery.signals import worker_process_init, beat_init + from cassandra.cqlengine import connection + from cassandra.cqlengine.connection import ( + cluster as cql_cluster, session as cql_session) + + def cassandra_init(**kwargs): + """ Initialize a clean Cassandra connection. """ + if cql_cluster is not None: + cql_cluster.shutdown() + if cql_session is not None: + cql_session.shutdown() + connection.setup() + + # Initialize worker context for both standard and periodic tasks. + worker_process_init.connect(cassandra_init) + beat_init.connect(cassandra_init) + + app = Celery() + + +uWSGI +----- + +This is the code required for proper connection handling of CQLengine for a +`uWSGI `_-run application: + +.. code-block:: python + + from cassandra.cqlengine import connection + from cassandra.cqlengine.connection import ( + cluster as cql_cluster, session as cql_session) + + try: + from uwsgidecorators import postfork + except ImportError: + # We're not in a uWSGI context, no need to hook Cassandra session + # initialization to the postfork event. + pass + else: + @postfork + def cassandra_init(**kwargs): + """ Initialize a new Cassandra session in the context. + + Ensures that a new session is returned for every new request. + """ + if cql_cluster is not None: + cql_cluster.shutdown() + if cql_session is not None: + cql_session.shutdown() + connection.setup() diff --git a/3.21.0-scylla/_sources/cqlengine/upgrade_guide.rst.txt b/3.21.0-scylla/_sources/cqlengine/upgrade_guide.rst.txt new file mode 100644 index 0000000000..5a10ebb757 --- /dev/null +++ b/3.21.0-scylla/_sources/cqlengine/upgrade_guide.rst.txt @@ -0,0 +1,155 @@ +======================== +Upgrade Guide +======================== + +This is an overview of things that changed as the cqlengine project was merged into +scylla-driver. While efforts were taken to preserve the API and most functionality exactly, +conversion to this package will still require certain minimal updates (namely, imports). + +**THERE IS ONE FUNCTIONAL CHANGE**, described in the first section below. + +Functional Changes +================== +List Prepend Reversing +---------------------- +Legacy cqlengine included a workaround for a Cassandra bug in which prepended list segments were +reversed (`CASSANDRA-8733 `_). As of +this integration, this workaround is removed. The first released integrated version emits +a warning when prepend is used. Subsequent versions will have this warning removed. + +Date Column Type +---------------- +The Date column type in legacy cqlengine used a ``timestamp`` CQL type and truncated the time. +Going forward, the :class:`~.columns.Date` type represents a ``date`` for Cassandra 2.2+ +(`PYTHON-245 `_). +Users of the legacy functionality should convert models to use :class:`~.columns.DateTime` (which +uses ``timestamp`` internally), and use the build-in ``datetime.date`` for input values. + +Remove cqlengine +================ +To avoid confusion or mistakes using the legacy package in your application, it +is prudent to remove the cqlengine package when upgrading to the integrated version. + +The driver setup script will warn if the legacy package is detected during install, +but it will not prevent side-by-side installation. + +Organization +============ +Imports +------- +cqlengine is now integrated as a sub-package of the driver base package 'cassandra'. +Upgrading will require adjusting imports to cqlengine. For example:: + + from cassandra.cqlengine import columns + +is now:: + + from cassandra.cqlengine import columns + +Package-Level Aliases +--------------------- +Legacy cqlengine defined a number of aliases at the package level, which became redundant +when the package was integrated for a driver. These have been removed in favor of absolute +imports, and referring to cannonical definitions. For example, ``cqlengine.ONE`` was an alias +of ``cassandra.ConsistencyLevel.ONE``. In the integrated package, only the +:class:`cassandra.ConsistencyLevel` remains. + +Additionally, submodule aliases are removed from cqlengine in favor of absolute imports. + +These aliases are removed, and not deprecated because they should be straightforward to iron out +at module load time. + +Exceptions +---------- +The legacy cqlengine.exceptions module had a number of Exception classes that were variously +common to the package, or only used in specific modules. Common exceptions were relocated to +cqlengine, and specialized exceptions were placed in the module that raises them. Below is a +listing of updated locations: + +============================ ========== +Exception class New module +============================ ========== +CQLEngineException cassandra.cqlengine +ModelException cassandra.cqlengine.models +ValidationError cassandra.cqlengine +UndefinedKeyspaceException cassandra.cqlengine.connection +LWTException cassandra.cqlengine.query +IfNotExistsWithCounterColumn cassandra.cqlengine.query +============================ ========== + +UnicodeMixin Consolidation +-------------------------- +``class UnicodeMixin`` was defined in several cqlengine modules. This has been consolidated +to a single definition in the cqlengine package init file. This is not technically part of +the API, but noted here for completeness. + +API Deprecations +================ +This upgrade served as a good juncture to deprecate certain API features and invite users to upgrade +to new ones. The first released version does not change functionality -- only introduces deprecation +warnings. Future releases will remove these features in favor of the alternatives. + +Float/Double Overload +--------------------- +Previously there was no ``Double`` column type. Doubles were modeled by specifying ``Float(double_precision=True)``. +This inititializer parameter is now deprecated. Applications should use :class:`~.columns.Double` for CQL ``double``, and :class:`~.columns.Float` +for CQL ``float``. + +Schema Management +----------------- +``cassandra.cqlengine.management.create_keyspace`` is deprecated. Instead, use the new replication-strategy-specific +functions that accept explicit options for known strategies: + +- :func:`~.create_keyspace_simple` +- :func:`~.create_keyspace_network_topology` + +``cassandra.cqlengine.management.delete_keyspace`` is deprecated in favor of a new function, :func:`~.drop_keyspace`. The +intent is simply to make the function match the CQL verb it invokes. + +Model Inheritance +----------------- +The names for class attributes controlling model inheritance are changing. Changes are as follows: + +- Replace 'polymorphic_key' in the base class Column definition with :attr:`~.discriminator_column` +- Replace the '__polymorphic_key__' class attribute the derived classes with :attr:`~.__discriminator_value__` + +The functionality is unchanged -- the intent here is to make the names and language around these attributes more precise. +For now, the old names are just deprecated, and the mapper will emit warnings if they are used. The old names +will be removed in a future version. + +The example below shows a simple translation: + +Before:: + + class Pet(Model): + __table_name__ = 'pet' + owner_id = UUID(primary_key=True) + pet_id = UUID(primary_key=True) + pet_type = Text(polymorphic_key=True) + name = Text() + + class Cat(Pet): + __polymorphic_key__ = 'cat' + + class Dog(Pet): + __polymorphic_key__ = 'dog' + +After:: + + class Pet(models.Model): + __table_name__ = 'pet' + owner_id = UUID(primary_key=True) + pet_id = UUID(primary_key=True) + pet_type = Text(discriminator_column=True) + name = Text() + + class Cat(Pet): + __discriminator_value__ = 'cat' + + class Dog(Pet): + __discriminator_value__ = 'dog' + + +TimeUUID.from_datetime +---------------------- +This function is deprecated in favor of the core utility function :func:`~.uuid_from_time`. diff --git a/3.21.0-scylla/_sources/dates_and_times.rst.txt b/3.21.0-scylla/_sources/dates_and_times.rst.txt new file mode 100644 index 0000000000..7a89f77437 --- /dev/null +++ b/3.21.0-scylla/_sources/dates_and_times.rst.txt @@ -0,0 +1,87 @@ +Working with Dates and Times +============================ + +This document is meant to provide on overview of the assumptions and limitations of the driver time handling, the +reasoning behind it, and describe approaches to working with these types. + +timestamps (Cassandra DateType) +------------------------------- + +Timestamps in Cassandra are timezone-naive timestamps encoded as millseconds since UNIX epoch. Clients working with +timestamps in this database usually find it easiest to reason about them if they are always assumed to be UTC. To quote the +pytz documentation, "The preferred way of dealing with times is to always work in UTC, converting to localtime only when +generating output to be read by humans." The driver adheres to this tenant, and assumes UTC is always in the database. The +driver attempts to make this correct on the way in, and assumes no timezone on the way out. + +Write Path +~~~~~~~~~~ +When inserting timestamps, the driver handles serialization for the write path as follows: + +If the input is a ``datetime.datetime``, the serialization is normalized by starting with the ``utctimetuple()`` of the +value. + +- If the ``datetime`` object is timezone-aware, the timestamp is shifted, and represents the UTC timestamp equivalent. +- If the ``datetime`` object is timezone-naive, this results in no shift -- any ``datetime`` with no timezone information is assumed to be UTC + +Note the second point above applies even to "local" times created using ``now()``:: + + >>> d = datetime.now() + + >>> print(d.tzinfo) + None + + +These do not contain timezone information intrinsically, so they will be assumed to be UTC and not shifted. When generating +timestamps in the application, it is clearer to use ``datetime.utcnow()`` to be explicit about it. + +If the input for a timestamp is numeric, it is assumed to be a epoch-relative millisecond timestamp, as specified in the +CQL spec -- no scaling or conversion is done. + +Read Path +~~~~~~~~~ +The driver always assumes persisted timestamps are UTC and makes no attempt to localize them. Returned values are +timezone-naive ``datetime.datetime``. We follow this approach because the datetime API has deficiencies around daylight +saving time, and the defacto package for handling this is a third-party package (we try to minimize external dependencies +and not make decisions for the integrator). + +The decision for how to handle timezones is left to the application. For the most part it is straightforward to apply +localization to the ``datetime``\s returned by queries. One prevalent method is to use pytz for localization:: + + import pytz + user_tz = pytz.timezone('US/Central') + timestamp_naive = row.ts + timestamp_utc = pytz.utc.localize(timestamp_naive) + timestamp_presented = timestamp_utc.astimezone(user_tz) + +This is the most robust approach (likely refactored into a function). If it is deemed too cumbersome to apply for all call +sites in the application, it is possible to patch the driver with custom deserialization for this type. However, doing +this depends depends some on internal APIs and what extensions are present, so we will only mention the possibility, and +not spell it out here. + +date, time (Cassandra DateType) +------------------------------- +Date and time in Cassandra are idealized markers, much like ``datetime.date`` and ``datetime.time`` in the Python standard +library. Unlike these Python implementations, the Cassandra encoding supports much wider ranges. To accommodate these +ranges without overflow, this driver returns these data in custom types: :class:`.util.Date` and :class:`.util.Time`. + +Write Path +~~~~~~~~~~ +For simple (not prepared) statements, the input values for each of these can be either a string literal or an encoded +integer. See `Working with dates `_ +or `Working with time `_ for details +on the encoding or string formats. + +For prepared statements, the driver accepts anything that can be used to construct the :class:`.util.Date` or +:class:`.util.Time` classes. See the linked API docs for details. + +Read Path +~~~~~~~~~ +The driver always returns custom types for ``date`` and ``time``. + +The driver returns :class:`.util.Date` for ``date`` in order to accommodate the wider range of values without overflow. +For applications working within the supported range of [``datetime.MINYEAR``, ``datetime.MAXYEAR``], these are easily +converted to standard ``datetime.date`` insances using :meth:`.Date.date`. + +The driver returns :class:`.util.Time` for ``time`` in order to retain nanosecond precision stored in the database. +For applications not concerned with this level of precision, these are easily converted to standard ``datetime.time`` +insances using :meth:`.Time.time`. diff --git a/3.21.0-scylla/_sources/execution_profiles.rst.txt b/3.21.0-scylla/_sources/execution_profiles.rst.txt new file mode 100644 index 0000000000..7be1a85e3f --- /dev/null +++ b/3.21.0-scylla/_sources/execution_profiles.rst.txt @@ -0,0 +1,156 @@ +Execution Profiles +================== + +Execution profiles aim at making it easier to execute requests in different ways within +a single connected ``Session``. Execution profiles are being introduced to deal with the exploding number of +configuration options, especially as the database platform evolves more complex workloads. + +The legacy configuration remains intact, but legacy and Execution Profile APIs +cannot be used simultaneously on the same client ``Cluster``. Legacy configuration +will be removed in the next major release (4.0). + +An execution profile and its parameters should be unique across ``Cluster`` instances. +For example, an execution profile and its ``LoadBalancingPolicy`` should +not be applied to more than one ``Cluster`` instance. + +This document explains how Execution Profiles relate to existing settings, and shows how to use the new profiles for +request execution. + +Mapping Legacy Parameters to Profiles +------------------------------------- + +Execution profiles can inherit from :class:`.cluster.ExecutionProfile`, and currently provide the following options, +previously input from the noted attributes: + +- load_balancing_policy - :attr:`.Cluster.load_balancing_policy` +- request_timeout - :attr:`.Session.default_timeout`, optional :meth:`.Session.execute` parameter +- retry_policy - :attr:`.Cluster.default_retry_policy`, optional :attr:`.Statement.retry_policy` attribute +- consistency_level - :attr:`.Session.default_consistency_level`, optional :attr:`.Statement.consistency_level` attribute +- serial_consistency_level - :attr:`.Session.default_serial_consistency_level`, optional :attr:`.Statement.serial_consistency_level` attribute +- row_factory - :attr:`.Session.row_factory` attribute + +When using the new API, these parameters can be defined by instances of :class:`.cluster.ExecutionProfile`. + +Using Execution Profiles +------------------------ +Default +~~~~~~~ + +.. code:: python + + from cassandra.cluster import Cluster + cluster = Cluster() + session = cluster.connect() + local_query = 'SELECT rpc_address FROM system.local' + for _ in cluster.metadata.all_hosts(): + print session.execute(local_query)[0] + + +.. parsed-literal:: + + Row(rpc_address='127.0.0.2') + Row(rpc_address='127.0.0.1') + + +The default execution profile is built from Cluster parameters and default Session attributes. This profile matches existing default +parameters. + +Initializing cluster with profiles +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. code:: python + + from cassandra.cluster import ExecutionProfile + from cassandra.policies import WhiteListRoundRobinPolicy + + node1_profile = ExecutionProfile(load_balancing_policy=WhiteListRoundRobinPolicy(['127.0.0.1'])) + node2_profile = ExecutionProfile(load_balancing_policy=WhiteListRoundRobinPolicy(['127.0.0.2'])) + + profiles = {'node1': node1_profile, 'node2': node2_profile} + session = Cluster(execution_profiles=profiles).connect() + for _ in cluster.metadata.all_hosts(): + print session.execute(local_query, execution_profile='node1')[0] + + +.. parsed-literal:: + + Row(rpc_address='127.0.0.1') + Row(rpc_address='127.0.0.1') + + +.. code:: python + + for _ in cluster.metadata.all_hosts(): + print session.execute(local_query, execution_profile='node2')[0] + + +.. parsed-literal:: + + Row(rpc_address='127.0.0.2') + Row(rpc_address='127.0.0.2') + + +.. code:: python + + for _ in cluster.metadata.all_hosts(): + print session.execute(local_query)[0] + + +.. parsed-literal:: + + Row(rpc_address='127.0.0.2') + Row(rpc_address='127.0.0.1') + +Note that, even when custom profiles are injected, the default ``TokenAwarePolicy(DCAwareRoundRobinPolicy())`` is still +present. To override the default, specify a policy with the :data:`~.cluster.EXEC_PROFILE_DEFAULT` key. + +.. code:: python + + from cassandra.cluster import EXEC_PROFILE_DEFAULT + profile = ExecutionProfile(request_timeout=30) + cluster = Cluster(execution_profiles={EXEC_PROFILE_DEFAULT: profile}) + + +Adding named profiles +~~~~~~~~~~~~~~~~~~~~~ + +New profiles can be added constructing from scratch, or deriving from default: + +.. code:: python + + locked_execution = ExecutionProfile(load_balancing_policy=WhiteListRoundRobinPolicy(['127.0.0.1'])) + node1_profile = 'node1_whitelist' + cluster.add_execution_profile(node1_profile, locked_execution) + + for _ in cluster.metadata.all_hosts(): + print session.execute(local_query, execution_profile=node1_profile)[0] + + +.. parsed-literal:: + + Row(rpc_address='127.0.0.1') + Row(rpc_address='127.0.0.1') + +See :meth:`.Cluster.add_execution_profile` for details and optional parameters. + +Passing a profile instance without mapping +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +We also have the ability to pass profile instances to be used for execution, but not added to the mapping: + +.. code:: python + + from cassandra.query import tuple_factory + + tmp = session.execution_profile_clone_update('node1', request_timeout=100, row_factory=tuple_factory) + + print session.execute(local_query, execution_profile=tmp)[0] + print session.execute(local_query, execution_profile='node1')[0] + +.. parsed-literal:: + + ('127.0.0.1',) + Row(rpc_address='127.0.0.1') + +The new profile is a shallow copy, so the ``tmp`` profile shares a load balancing policy with one managed by the cluster. +If reference objects are to be updated in the clone, one would typically set those attributes to a new instance. diff --git a/3.21.0-scylla/_sources/faq.rst.txt b/3.21.0-scylla/_sources/faq.rst.txt new file mode 100644 index 0000000000..56cb648a24 --- /dev/null +++ b/3.21.0-scylla/_sources/faq.rst.txt @@ -0,0 +1,83 @@ +Frequently Asked Questions +========================== + +See also :doc:`cqlengine FAQ ` + +Why do connections or IO operations timeout in my WSGI application? +------------------------------------------------------------------- +Depending on your application process model, it may be forking after driver Session is created. Most IO reactors do not handle this, and problems will manifest as timeouts. + +To avoid this, make sure to create sessions per process, after the fork. Using uWSGI and Flask for example: + +.. code-block:: python + + from flask import Flask + from uwsgidecorators import postfork + from cassandra.cluster import Cluster + + session = None + prepared = None + + @postfork + def connect(): + global session, prepared + session = Cluster().connect() + prepared = session.prepare("SELECT release_version FROM system.local WHERE key=?") + + app = Flask(__name__) + + @app.route('/') + def server_version(): + row = session.execute(prepared, ('local',))[0] + return row.release_version + +uWSGI provides a ``postfork`` hook you can use to create sessions and prepared statements after the child process forks. + +How do I trace a request? +------------------------- +Request tracing can be turned on for any request by setting ``trace=True`` in :meth:`.Session.execute_async`. View the results by waiting on the future, then :meth:`.ResponseFuture.get_query_trace`. +Since tracing is done asynchronously to the request, this method polls until the trace is complete before querying data. + +.. code-block:: python + + >>> future = session.execute_async("SELECT * FROM system.local", trace=True) + >>> result = future.result() + >>> trace = future.get_query_trace() + >>> for e in trace.events: + >>> print e.source_elapsed, e.description + + 0:00:00.000077 Parsing select * from system.local + 0:00:00.000153 Preparing statement + 0:00:00.000309 Computing ranges to query + 0:00:00.000368 Submitting range requests on 1 ranges with a concurrency of 1 (279.77142 rows per range expected) + 0:00:00.000422 Submitted 1 concurrent range requests covering 1 ranges + 0:00:00.000480 Executing seq scan across 1 sstables for (min(-9223372036854775808), min(-9223372036854775808)) + 0:00:00.000669 Read 1 live and 0 tombstone cells + 0:00:00.000755 Scanned 1 rows and matched 1 + +``trace`` is a :class:`QueryTrace` object. + +How do I determine the replicas for a query? +---------------------------------------------- +With prepared statements, the replicas are obtained by ``routing_key``, based on current cluster token metadata: + +.. code-block:: python + + >>> prepared = session.prepare("SELECT * FROM example.t WHERE key=?") + >>> bound = prepared.bind((1,)) + >>> replicas = cluster.metadata.get_replicas(bound.keyspace, bound.routing_key) + >>> for h in replicas: + >>> print h.address + 127.0.0.1 + 127.0.0.2 + +``replicas`` is a list of :class:`Host` objects. + +How does the driver manage request retries? +------------------------------------------- +By default, retries are managed by the :attr:`.Cluster.default_retry_policy` set on the session Cluster. It can also +be specialized per statement by setting :attr:`.Statement.retry_policy`. + +Retries are presently attempted on the same coordinator, but this may change in the future. + +Please see :class:`.policies.RetryPolicy` for further details. diff --git a/3.21.0-scylla/_sources/getting_started.rst.txt b/3.21.0-scylla/_sources/getting_started.rst.txt new file mode 100644 index 0000000000..8cb86a5504 --- /dev/null +++ b/3.21.0-scylla/_sources/getting_started.rst.txt @@ -0,0 +1,473 @@ +Getting Started +=============== + +First, make sure you have the driver properly :doc:`installed `. + +Connecting to Cassandra +----------------------- +Before we can start executing any queries against a Cassandra cluster we need to setup +an instance of :class:`~.Cluster`. As the name suggests, you will typically have one +instance of :class:`~.Cluster` for each Cassandra cluster you want to interact +with. + +The simplest way to create a :class:`~.Cluster` is like this: +First, make sure you have the Cassandra driver properly :doc:`installed `. + +.. code-block:: python + + from cassandra.cluster import Cluster + + cluster = Cluster() + +This will attempt to connection to a Cassandra instance on your +local machine (127.0.0.1). You can also specify a list of IP +addresses for nodes in your cluster: + +.. code-block:: python + + from cassandra.cluster import Cluster + + cluster = Cluster(['192.168.0.1', '192.168.0.2']) + +The set of IP addresses we pass to the :class:`~.Cluster` is simply +an initial set of contact points. After the driver connects to one +of these nodes it will *automatically discover* the rest of the +nodes in the cluster and connect to them, so you don't need to list +every node in your cluster. + +If you need to use a non-standard port, use SSL, or customize the driver's +behavior in some other way, this is the place to do it: + +.. code-block:: python + + from cassandra.cluster import Cluster + cluster = Cluster(['192.168.0.1', '192.168.0.2'], port=..., ssl_context=...) + +Instantiating a :class:`~.Cluster` does not actually connect us to any nodes. +To establish connections and begin executing queries we need a +:class:`~.Session`, which is created by calling :meth:`.Cluster.connect()`: + +.. code-block:: python + + cluster = Cluster() + session = cluster.connect() + +The :meth:`~.Cluster.connect()` method takes an optional ``keyspace`` argument +which sets the default keyspace for all queries made through that :class:`~.Session`: + +.. code-block:: python + + cluster = Cluster() + session = cluster.connect('mykeyspace') + + +You can always change a Session's keyspace using :meth:`~.Session.set_keyspace` or +by executing a ``USE `` query: + +.. code-block:: python + + session.set_keyspace('users') + # or you can do this instead + session.execute('USE users') + +Profiles are passed in by ``execution_profiles`` dict. + +In this case we can construct the base ``ExecutionProfile`` passing all attributes: + +.. code-block:: python + + from cassandra.cluster import Cluster, ExecutionProfile, EXEC_PROFILE_DEFAULT + from cassandra.policies import WhiteListRoundRobinPolicy, DowngradingConsistencyRetryPolicy + from cassandra.query import tuple_factory + + profile = ExecutionProfile( + load_balancing_policy=WhiteListRoundRobinPolicy(['127.0.0.1']), + retry_policy=DowngradingConsistencyRetryPolicy(), + consistency_level=ConsistencyLevel.LOCAL_QUORUM, + serial_consistency_level=ConsistencyLevel.LOCAL_SERIAL, + request_timeout=15, + row_factory=tuple_factory + ) + cluster = Cluster(execution_profiles={EXEC_PROFILE_DEFAULT: profile}) + session = cluster.connect() + + print(session.execute("SELECT release_version FROM system.local").one()) + +Users are free to setup additional profiles to be used by name: + +.. code-block:: python + + profile_long = ExecutionProfile(request_timeout=30) + cluster = Cluster(execution_profiles={'long': profile_long}) + session = cluster.connect() + session.execute(statement, execution_profile='long') + +Also, parameters passed to ``Session.execute`` or attached to ``Statement``\s are still honored as before. + +Executing Queries +----------------- +Now that we have a :class:`.Session` we can begin to execute queries. The simplest +way to execute a query is to use :meth:`~.Session.execute()`: + +.. code-block:: python + + rows = session.execute('SELECT name, age, email FROM users') + for user_row in rows: + print user_row.name, user_row.age, user_row.email + +This will transparently pick a Cassandra node to execute the query against +and handle any retries that are necessary if the operation fails. + +By default, each row in the result set will be a +`namedtuple `_. +Each row will have a matching attribute for each column defined in the schema, +such as ``name``, ``age``, and so on. You can also treat them as normal tuples +by unpacking them or accessing fields by position. The following three +examples are equivalent: + +.. code-block:: python + + rows = session.execute('SELECT name, age, email FROM users') + for row in rows: + print row.name, row.age, row.email + +.. code-block:: python + + rows = session.execute('SELECT name, age, email FROM users') + for (name, age, email) in rows: + print name, age, email + +.. code-block:: python + + rows = session.execute('SELECT name, age, email FROM users') + for row in rows: + print row[0], row[1], row[2] + +If you prefer another result format, such as a ``dict`` per row, you +can change the :attr:`~.Session.row_factory` attribute. + +As mentioned in our `Drivers Best Practices Guide `_, +it is highly recommended to use `Prepared statements <#prepared-statement>`_ for your +frequently run queries. + +.. _prepared-statement: + +Prepared Statements +------------------- +Prepared statements are queries that are parsed by Cassandra and then saved +for later use. When the driver uses a prepared statement, it only needs to +send the values of parameters to bind. This lowers network traffic +and CPU utilization within Cassandra because Cassandra does not have to +re-parse the query each time. + +To prepare a query, use :meth:`.Session.prepare()`: + +.. code-block:: python + + user_lookup_stmt = session.prepare("SELECT * FROM users WHERE user_id=?") + + users = [] + for user_id in user_ids_to_query: + user = session.execute(user_lookup_stmt, [user_id]) + users.append(user) + +:meth:`~.Session.prepare()` returns a :class:`~.PreparedStatement` instance +which can be used in place of :class:`~.SimpleStatement` instances or literal +string queries. It is automatically prepared against all nodes, and the driver +handles re-preparing against new nodes and restarted nodes when necessary. + +Note that the placeholders for prepared statements are ``?`` characters. This +is different than for simple, non-prepared statements (although future versions +of the driver may use the same placeholders for both). + +Passing Parameters to CQL Queries +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Althought it is not recommended, you can also pass parameters to non-prepared +statements. The driver supports two forms of parameter place-holders: positional +and named. + +Positional parameters are used with a ``%s`` placeholder. For example, +when you execute: + +.. code-block:: python + + session.execute( + """ + INSERT INTO users (name, credits, user_id) + VALUES (%s, %s, %s) + """, + ("John O'Reilly", 42, uuid.uuid1()) + ) + +It is translated to the following CQL query:: + + INSERT INTO users (name, credits, user_id) + VALUES ('John O''Reilly', 42, 2644bada-852c-11e3-89fb-e0b9a54a6d93) + +Note that you should use ``%s`` for all types of arguments, not just strings. +For example, this would be **wrong**: + +.. code-block:: python + + session.execute("INSERT INTO USERS (name, age) VALUES (%s, %d)", ("bob", 42)) # wrong + +Instead, use ``%s`` for the age placeholder. + +If you need to use a literal ``%`` character, use ``%%``. + +**Note**: you must always use a sequence for the second argument, even if you are +only passing in a single variable: + +.. code-block:: python + + session.execute("INSERT INTO foo (bar) VALUES (%s)", "blah") # wrong + session.execute("INSERT INTO foo (bar) VALUES (%s)", ("blah")) # wrong + session.execute("INSERT INTO foo (bar) VALUES (%s)", ("blah", )) # right + session.execute("INSERT INTO foo (bar) VALUES (%s)", ["blah"]) # right + + +Note that the second line is incorrect because in Python, single-element tuples +require a comma. + +Named place-holders use the ``%(name)s`` form: + +.. code-block:: python + + session.execute( + """ + INSERT INTO users (name, credits, user_id, username) + VALUES (%(name)s, %(credits)s, %(user_id)s, %(name)s) + """, + {'name': "John O'Reilly", 'credits': 42, 'user_id': uuid.uuid1()} + ) + +Note that you can repeat placeholders with the same name, such as ``%(name)s`` +in the above example. + +Only data values should be supplied this way. Other items, such as keyspaces, +table names, and column names should be set ahead of time (typically using +normal string formatting). + +.. _type-conversions: + +Type Conversions +^^^^^^^^^^^^^^^^ +For non-prepared statements, Python types are cast to CQL literals in the +following way: + +.. table:: + + +--------------------+-------------------------+ + | Python Type | CQL Literal Type | + +====================+=========================+ + | ``None`` | ``NULL`` | + +--------------------+-------------------------+ + | ``bool`` | ``boolean`` | + +--------------------+-------------------------+ + | ``float`` | | ``float`` | + | | | ``double`` | + +--------------------+-------------------------+ + | | ``int`` | | ``int`` | + | | ``long`` | | ``bigint`` | + | | | ``varint`` | + | | | ``smallint`` | + | | | ``tinyint`` | + | | | ``counter`` | + +--------------------+-------------------------+ + | ``decimal.Decimal``| ``decimal`` | + +--------------------+-------------------------+ + | | ``str`` | | ``ascii`` | + | | ``unicode`` | | ``varchar`` | + | | | ``text`` | + +--------------------+-------------------------+ + | | ``buffer`` | ``blob`` | + | | ``bytearray`` | | + +--------------------+-------------------------+ + | ``date`` | ``date`` | + +--------------------+-------------------------+ + | ``datetime`` | ``timestamp`` | + +--------------------+-------------------------+ + | ``time`` | ``time`` | + +--------------------+-------------------------+ + | | ``list`` | ``list`` | + | | ``tuple`` | | + | | generator | | + +--------------------+-------------------------+ + | | ``set`` | ``set`` | + | | ``frozenset`` | | + +--------------------+-------------------------+ + | | ``dict`` | ``map`` | + | | ``OrderedDict`` | | + +--------------------+-------------------------+ + | ``uuid.UUID`` | | ``timeuuid`` | + | | | ``uuid`` | + +--------------------+-------------------------+ + + +Asynchronous Queries +^^^^^^^^^^^^^^^^^^^^ +The driver supports asynchronous query execution through +:meth:`~.Session.execute_async()`. Instead of waiting for the query to +complete and returning rows directly, this method almost immediately +returns a :class:`~.ResponseFuture` object. There are two ways of +getting the final result from this object. + +The first is by calling :meth:`~.ResponseFuture.result()` on it. If +the query has not yet completed, this will block until it has and +then return the result or raise an Exception if an error occurred. +For example: + +.. code-block:: python + + from cassandra import ReadTimeout + + query = "SELECT * FROM users WHERE user_id=%s" + future = session.execute_async(query, [user_id]) + + # ... do some other work + + try: + rows = future.result() + user = rows[0] + print user.name, user.age + except ReadTimeout: + log.exception("Query timed out:") + +This works well for executing many queries concurrently: + +.. code-block:: python + + # build a list of futures + futures = [] + query = "SELECT * FROM users WHERE user_id=%s" + for user_id in ids_to_fetch: + futures.append(session.execute_async(query, [user_id]) + + # wait for them to complete and use the results + for future in futures: + rows = future.result() + print rows[0].name + +Alternatively, instead of calling :meth:`~.ResponseFuture.result()`, +you can attach callback and errback functions through the +:meth:`~.ResponseFuture.add_callback()`, +:meth:`~.ResponseFuture.add_errback()`, and +:meth:`~.ResponseFuture.add_callbacks()`, methods. If you have used +Twisted Python before, this is designed to be a lightweight version of +that: + +.. code-block:: python + + def handle_success(rows): + user = rows[0] + try: + process_user(user.name, user.age, user.id) + except Exception: + log.error("Failed to process user %s", user.id) + # don't re-raise errors in the callback + + def handle_error(exception): + log.error("Failed to fetch user info: %s", exception) + + + future = session.execute_async(query) + future.add_callbacks(handle_success, handle_error) + +There are a few important things to remember when working with callbacks: + * **Exceptions that are raised inside the callback functions will be logged and then ignored.** + * Your callback will be run on the event loop thread, so any long-running + operations will prevent other requests from being handled + + +Setting a Consistency Level +--------------------------- +The consistency level used for a query determines how many of the +replicas of the data you are interacting with need to respond for +the query to be considered a success. + +By default, :attr:`.ConsistencyLevel.LOCAL_ONE` will be used for all queries. +You can specify a different default by setting the :attr:`.ExecutionProfile.consistency_level` +for the execution profile with key :data:`~.cluster.EXEC_PROFILE_DEFAULT`. +To specify a different consistency level per request, wrap queries +in a :class:`~.SimpleStatement`: + +.. code-block:: python + + from cassandra import ConsistencyLevel + from cassandra.query import SimpleStatement + + query = SimpleStatement( + "INSERT INTO users (name, age) VALUES (%s, %s)", + consistency_level=ConsistencyLevel.QUORUM) + session.execute(query, ('John', 42)) + +Setting a Consistency Level with Prepared Statements +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +To specify a consistency level for prepared statements, you have two options. + +The first is to set a default consistency level for every execution of the +prepared statement: + +.. code-block:: python + + from cassandra import ConsistencyLevel + + cluster = Cluster() + session = cluster.connect("mykeyspace") + user_lookup_stmt = session.prepare("SELECT * FROM users WHERE user_id=?") + user_lookup_stmt.consistency_level = ConsistencyLevel.QUORUM + + # these will both use QUORUM + user1 = session.execute(user_lookup_stmt, [user_id1])[0] + user2 = session.execute(user_lookup_stmt, [user_id2])[0] + +The second option is to create a :class:`~.BoundStatement` from the +:class:`~.PreparedStatement` and binding parameters and set a consistency +level on that: + +.. code-block:: python + + # override the QUORUM default + user3_lookup = user_lookup_stmt.bind([user_id3]) + user3_lookup.consistency_level = ConsistencyLevel.ALL + user3 = session.execute(user3_lookup) + +Speculative Execution +^^^^^^^^^^^^^^^^^^^^^ + +Speculative execution is a way to minimize latency by preemptively executing several +instances of the same query against different nodes. For more details about this +technique, see `Speculative Execution with DataStax Drivers `_. + +To enable speculative execution: + +* Configure a :class:`~.policies.SpeculativeExecutionPolicy` with the ExecutionProfile +* Mark your query as idempotent, which mean it can be applied multiple + times without changing the result of the initial application. + See `Query Idempotence `_ for more details. + + +Example: + +.. code-block:: python + + from cassandra.cluster import Cluster, ExecutionProfile, EXEC_PROFILE_DEFAULT + from cassandra.policies import ConstantSpeculativeExecutionPolicy + from cassandra.query import SimpleStatement + + # Configure the speculative execution policy + ep = ExecutionProfile( + speculative_execution_policy=ConstantSpeculativeExecutionPolicy(delay=.5, max_attempts=10) + ) + cluster = Cluster(..., execution_profiles={EXEC_PROFILE_DEFAULT: ep}) + session = cluster.connect() + + # Mark the query idempotent + query = SimpleStatement( + "UPDATE my_table SET list_col = [1] WHERE pk = 1", + is_idempotent=True + ) + + # Execute. A new query will be sent to the server every 0.5 second + # until we receive a response, for a max number attempts of 10. + session.execute(query) diff --git a/3.21.0-scylla/_sources/index.rst.txt b/3.21.0-scylla/_sources/index.rst.txt new file mode 100644 index 0000000000..3a752975bd --- /dev/null +++ b/3.21.0-scylla/_sources/index.rst.txt @@ -0,0 +1,106 @@ +DataStax Python Driver for Apache Cassandra® +============================================ +A Python client driver for `Apache Cassandra® `_. +This driver works exclusively with the Cassandra Query Language v3 (CQL3) +and Cassandra's native protocol. Cassandra 2.1+ is supported, including DSE 4.7+. + +The driver supports Python 2.7, 3.4, 3.5, 3.6, 3.7 and 3.8. + +This driver is open source under the +`Apache v2 License `_. +The source code for this driver can be found on `GitHub `_. + +**Note:** DataStax products do not support big-endian systems. + +Contents +-------- +:doc:`installation` + How to install the driver. + +:doc:`getting_started` + A guide through the first steps of connecting to Cassandra and executing queries + +:doc:`execution_profiles` + An introduction to a more flexible way of configuring request execution + +:doc:`lwt` + Working with results of conditional requests + +:doc:`object_mapper` + Introduction to the integrated object mapper, cqlengine + +:doc:`performance` + Tips for getting good performance. + +:doc:`query_paging` + Notes on paging large query results + +:doc:`security` + An overview of the security features of the driver + +:doc:`upgrading` + A guide to upgrading versions of the driver + +:doc:`user_defined_types` + Working with Cassandra 2.1's user-defined types + +:doc:`dates_and_times` + Some discussion on the driver's approach to working with timestamp, date, time types + +:doc:`cloud` + A guide to connecting to Datastax Apollo + +:doc:`geo_types` + Working with DSE geometry types + +:doc:`graph` + Graph queries with DSE Graph + +:doc:`graph_fluent` + DataStax Graph Fluent API + +:doc:`CHANGELOG` + Log of changes to the driver, organized by version. + +:doc:`faq` + A collection of Frequently Asked Questions + +:doc:`api/index` + The API documentation. + +.. toctree:: + :hidden: + + api/index + installation + getting_started + upgrading + execution_profiles + performance + query_paging + lwt + security + user_defined_types + object_mapper + geo_types + graph + graph_fluent + dse_auth + dates_and_times + cloud + faq + +Getting Help +------------ +Visit the :doc:`FAQ section ` in this documentation. + +Please send questions to the `mailing list `_. + +Alternatively, you can use the `DataStax Community `_. + +Reporting Issues +---------------- +Please report any bugs and make any feature requests on the +`JIRA `_ issue tracker. + +If you would like to contribute, please feel free to open a pull request. diff --git a/3.21.0-scylla/_sources/installation.rst.txt b/3.21.0-scylla/_sources/installation.rst.txt new file mode 100644 index 0000000000..99a0b8a4cc --- /dev/null +++ b/3.21.0-scylla/_sources/installation.rst.txt @@ -0,0 +1,236 @@ +Installation +============ + +Supported Platforms +------------------- +Python 2.7, 3.4, 3.5, 3.6, 3.7 and 3.8 are supported. Both CPython (the standard Python +implementation) and `PyPy `_ are supported and tested. + +Linux, OSX, and Windows are supported. + +Installation through pip +------------------------ +`pip `_ is the suggested tool for installing +packages. It will handle installing all Python dependencies for the driver at +the same time as the driver itself. To install the driver*:: + + pip install scylla-driver + +You can use ``pip install --pre scylla-driver`` if you need to install a beta version. + +***Note**: if intending to use optional extensions, install the `dependencies <#optional-non-python-dependencies>`_ first. The driver may need to be reinstalled if dependencies are added after the initial installation. + +Verifying your Installation +--------------------------- +To check if the installation was successful, you can run:: + + python -c 'import cassandra; print cassandra.__version__' + +It should print something like "3.21.0". + +.. _installation-datastax-graph: + +(*Optional*) DataStax Graph +--------------------------- +The driver provides an optional fluent graph API that depends on Apache TinkerPop (gremlinpython). It is +not installed by default. To be able to build Gremlin traversals, you need to install +the `graph` requirements:: + + pip install scylla-driver[graph] + +See :doc:`graph_fluent` for more details about this API. + +(*Optional*) Compression Support +-------------------------------- +Compression can optionally be used for communication between the driver and +Cassandra. There are currently two supported compression algorithms: +snappy (in Cassandra 1.2+) and LZ4 (only in Cassandra 2.0+). If either is +available for the driver and Cassandra also supports it, it will +be used automatically. + +For lz4 support:: + + pip install lz4 + +For snappy support:: + + pip install python-snappy + +(If using a Debian Linux derivative such as Ubuntu, it may be easier to +just run ``apt-get install python-snappy``.) + +(*Optional*) Metrics Support +---------------------------- +The driver has built-in support for capturing :attr:`.Cluster.metrics` about +the queries you run. However, the ``scales`` library is required to +support this:: + + pip install scales + + +Speeding Up Installation +^^^^^^^^^^^^^^^^^^^^^^^^ + +By default, installing the driver through ``pip`` uses a pre-compiled, platform-specific wheel when available. +If using a source distribution rather than a wheel, Cython is used to compile certain parts of the driver. +This makes those hot paths faster at runtime, but the Cython compilation +process can take a long time -- as long as 10 minutes in some environments. + +In environments where performance is less important, it may be worth it to +:ref:`disable Cython as documented below `. +You can also use ``CASS_DRIVER_BUILD_CONCURRENCY`` to increase the number of +threads used to build the driver and any C extensions: + +.. code-block:: bash + + $ # installing from source + $ CASS_DRIVER_BUILD_CONCURRENCY=8 python setup.py install + $ # installing from pip + $ CASS_DRIVER_BUILD_CONCURRENCY=8 pip install scylla-driver + +OSX Installation Error +^^^^^^^^^^^^^^^^^^^^^^ +If you're installing on OSX and have XCode 5.1 installed, you may see an error like this:: + + clang: error: unknown argument: '-mno-fused-madd' [-Wunused-command-line-argument-hard-error-in-future] + +To fix this, re-run the installation with an extra compilation flag: + +.. code-block:: bash + + ARCHFLAGS=-Wno-error=unused-command-line-argument-hard-error-in-future pip install scylla-driver + +.. _windows_build: + +Windows Installation Notes +-------------------------- +Installing the driver with extensions in Windows sometimes presents some challenges. A few notes about common +hang-ups: + +Setup requires a compiler. When using Python 2, this is as simple as installing `this package `_ +(this link is also emitted during install if setuptools is unable to find the resources it needs). Depending on your +system settings, this package may install as a user-specific application. Make sure to install for everyone, or at least +as the user that will be building the Python environment. + +It is also possible to run the build with your compiler of choice. Just make sure to have your environment setup with +the proper paths. Make sure the compiler target architecture matches the bitness of your Python runtime. +Perhaps the easiest way to do this is to run the build/install from a Visual Studio Command Prompt (a +shortcut installed with Visual Studio that sources the appropriate environment and presents a shell). + +Manual Installation +------------------- +You can always install the driver directly from a source checkout or tarball. +When installing manually, ensure the python dependencies are already +installed. You can find the list of dependencies in +`requirements.txt `_. + +Once the dependencies are installed, simply run:: + + python setup.py install + + +(*Optional*) Non-python Dependencies +------------------------------------ +The driver has several **optional** features that have non-Python dependencies. + +C Extensions +^^^^^^^^^^^^ +By default, a number of extensions are compiled, providing faster hashing +for token-aware routing with the ``Murmur3Partitioner``, +`libev `_ event loop integration, +and Cython optimized extensions. + +When installing manually through setup.py, you can disable both with +the ``--no-extensions`` option, or selectively disable them with +with ``--no-murmur3``, ``--no-libev``, or ``--no-cython``. + +To compile the extensions, ensure that GCC and the Python headers are available. + +On Ubuntu and Debian, this can be accomplished by running:: + + $ sudo apt-get install gcc python-dev + +On RedHat and RedHat-based systems like CentOS and Fedora:: + + $ sudo yum install gcc python-devel + +On OS X, homebrew installations of Python should provide the necessary headers. + +See :ref:`windows_build` for notes on configuring the build environment on Windows. + +.. _cython-extensions: + +Cython-based Extensions +~~~~~~~~~~~~~~~~~~~~~~~ +By default, this package uses `Cython `_ to optimize core modules and build custom extensions. +This is not a hard requirement, but is engaged by default to build extensions offering better performance than the +pure Python implementation. + +This is a costly build phase, especially in clean environments where the Cython compiler must be built +This build phase can be avoided using the build switch, or an environment variable:: + + python setup.py install --no-cython + +Alternatively, an environment variable can be used to switch this option regardless of +context:: + + CASS_DRIVER_NO_CYTHON=1 + - or, to disable all extensions: + CASS_DRIVER_NO_EXTENSIONS=1 + +This method is required when using pip, which provides no other way of injecting user options in a single command:: + + CASS_DRIVER_NO_CYTHON=1 pip install scylla-driver + CASS_DRIVER_NO_CYTHON=1 sudo -E pip install ~/python-driver + +The environment variable is the preferred option because it spans all invocations of setup.py, and will +prevent Cython from being materialized as a setup requirement. + +If your sudo configuration does not allow SETENV, you must push the option flag down via pip. However, pip +applies these options to all dependencies (which break on the custom flag). Therefore, you must first install +dependencies, then use install-option:: + + sudo pip install six futures + sudo pip install --install-option="--no-cython" + + +libev support +^^^^^^^^^^^^^ +The driver currently uses Python's ``asyncore`` module for its default +event loop. For better performance, ``libev`` is also supported through +a C extension. + +If you're on Linux, you should be able to install libev +through a package manager. For example, on Debian/Ubuntu:: + + $ sudo apt-get install libev4 libev-dev + +On RHEL/CentOS/Fedora:: + + $ sudo yum install libev libev-devel + +If you're on Mac OS X, you should be able to install libev +through `Homebrew `_. For example, on Mac OS X:: + + $ brew install libev + +The libev extension is not built for Windows (the build process is complex, and the Windows implementation uses +select anyway). + +If successful, you should be able to build and install the extension +(just using ``setup.py build`` or ``setup.py install``) and then use +the libev event loop by doing the following: + +.. code-block:: python + + >>> from cassandra.io.libevreactor import LibevConnection + >>> from cassandra.cluster import Cluster + + >>> cluster = Cluster() + >>> cluster.connection_class = LibevConnection + >>> session = cluster.connect() + +(*Optional*) Configuring SSL +----------------------------- +Andrew Mussey has published a thorough guide on +`Using SSL with the DataStax Python driver `_. diff --git a/3.21.0-scylla/_sources/lwt.rst.txt b/3.21.0-scylla/_sources/lwt.rst.txt new file mode 100644 index 0000000000..2cc272f350 --- /dev/null +++ b/3.21.0-scylla/_sources/lwt.rst.txt @@ -0,0 +1,91 @@ +Lightweight Transactions (Compare-and-set) +========================================== + +Lightweight Transactions (LWTs) are mostly pass-through CQL for the driver. However, +the server returns some specialized results indicating the outcome and optional state +preceding the transaction. + +For pertinent execution parameters, see :attr:`.Statement.serial_consistency_level`. + +This section discusses working with specialized result sets returned by the server for LWTs, +and how to work with them using the driver. + + +Specialized Results +------------------- +The result returned from a LWT request is always a single row result. It will always have +prepended a special column named ``[applied]``. How this value appears in your results depends +on the row factory in use. See below for examples. + +The value of this ``[applied]`` column is boolean value indicating whether or not the transaction was applied. +If ``True``, it is the only column in the result. If ``False``, the additional columns depend on the LWT operation being +executed: + +- When using a ``UPDATE ... IF "col" = ...`` clause, the result will contain the ``[applied]`` column, plus the existing columns + and values for any columns in the ``IF`` clause (and thus the value that caused the transaction to fail). + +- When using ``INSERT ... IF NOT EXISTS``, the result will contain the ``[applied]`` column, plus all columns and values + of the existing row that rejected the transaction. + +- ``UPDATE .. IF EXISTS`` never has additional columns, regardless of ``[applied]`` status. + +How the ``[applied]`` column manifests depends on the row factory in use. Considering the following (initially empty) table:: + + CREATE TABLE test.t ( + k int PRIMARY KEY, + v int, + x int + ) + +... the following sections show the expected result for a number of example statements, using the three base row factories. + +named_tuple_factory (default) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +The name ``[applied]`` is not a valid Python identifier, so the square brackets are actually removed +from the attribute for the resulting ``namedtuple``. The row always has a boolean column ``applied`` in position 0:: + + >>> session.execute("INSERT INTO t (k,v) VALUES (0,0) IF NOT EXISTS") + Row(applied=True) + + >>> session.execute("INSERT INTO t (k,v) VALUES (0,0) IF NOT EXISTS") + Row(applied=False, k=0, v=0, x=None) + + >>> session.execute("UPDATE t SET v = 1, x = 2 WHERE k = 0 IF v =0") + Row(applied=True) + + >>> session.execute("UPDATE t SET v = 1, x = 2 WHERE k = 0 IF v =0 AND x = 1") + Row(applied=False, v=1, x=2) + +tuple_factory +~~~~~~~~~~~~~ +This return type does not refer to names, but the boolean value ``applied`` is always present in position 0:: + + >>> session.execute("INSERT INTO t (k,v) VALUES (0,0) IF NOT EXISTS") + (True,) + + >>> session.execute("INSERT INTO t (k,v) VALUES (0,0) IF NOT EXISTS") + (False, 0, 0, None) + + >>> session.execute("UPDATE t SET v = 1, x = 2 WHERE k = 0 IF v =0") + (True,) + + >>> session.execute("UPDATE t SET v = 1, x = 2 WHERE k = 0 IF v =0 AND x = 1") + (False, 1, 2) + +dict_factory +~~~~~~~~~~~~ +The retuned ``dict`` contains the ``[applied]`` key:: + + >>> session.execute("INSERT INTO t (k,v) VALUES (0,0) IF NOT EXISTS") + {u'[applied]': True} + + >>> session.execute("INSERT INTO t (k,v) VALUES (0,0) IF NOT EXISTS") + {u'x': 2, u'[applied]': False, u'v': 1} + + >>> session.execute("UPDATE t SET v = 1, x = 2 WHERE k = 0 IF v =0") + {u'x': None, u'[applied]': False, u'k': 0, u'v': 0} + + >>> session.execute("UPDATE t SET v = 1, x = 2 WHERE k = 0 IF v =0 AND x = 1") + {u'[applied]': True} + + diff --git a/3.21.0-scylla/_sources/object_mapper.rst.txt b/3.21.0-scylla/_sources/object_mapper.rst.txt new file mode 100644 index 0000000000..50d3cbf320 --- /dev/null +++ b/3.21.0-scylla/_sources/object_mapper.rst.txt @@ -0,0 +1,105 @@ +Object Mapper +============= + +cqlengine is the Cassandra CQL 3 Object Mapper packaged with this driver + +:ref:`Jump to Getting Started ` + +Contents +-------- +:doc:`cqlengine/upgrade_guide` + For migrating projects from legacy cqlengine, to the integrated product + +:doc:`cqlengine/models` + Examples defining models, and mapping them to tables + +:doc:`cqlengine/queryset` + Overview of query sets and filtering + +:doc:`cqlengine/batches` + Working with batch mutations + +:doc:`cqlengine/connections` + Working with multiple sessions + +:ref:`API Documentation ` + Index of API documentation + +:doc:`cqlengine/third_party` + High-level examples in Celery and uWSGI + +:doc:`cqlengine/faq` + +.. toctree:: + :hidden: + + cqlengine/upgrade_guide + cqlengine/models + cqlengine/queryset + cqlengine/batches + cqlengine/connections + cqlengine/third_party + cqlengine/faq + +.. _getting-started: + +Getting Started +--------------- + +.. code-block:: python + + import uuid + from cassandra.cqlengine import columns + from cassandra.cqlengine import connection + from datetime import datetime + from cassandra.cqlengine.management import sync_table + from cassandra.cqlengine.models import Model + + #first, define a model + class ExampleModel(Model): + example_id = columns.UUID(primary_key=True, default=uuid.uuid4) + example_type = columns.Integer(index=True) + created_at = columns.DateTime() + description = columns.Text(required=False) + + #next, setup the connection to your cassandra server(s)... + # see http://datastax.github.io/python-driver/api/cassandra/cluster.html for options + # the list of hosts will be passed to create a Cluster() instance + connection.setup(['127.0.0.1'], "cqlengine", protocol_version=3) + + #...and create your CQL table + >>> sync_table(ExampleModel) + + #now we can create some rows: + >>> em1 = ExampleModel.create(example_type=0, description="example1", created_at=datetime.now()) + >>> em2 = ExampleModel.create(example_type=0, description="example2", created_at=datetime.now()) + >>> em3 = ExampleModel.create(example_type=0, description="example3", created_at=datetime.now()) + >>> em4 = ExampleModel.create(example_type=0, description="example4", created_at=datetime.now()) + >>> em5 = ExampleModel.create(example_type=1, description="example5", created_at=datetime.now()) + >>> em6 = ExampleModel.create(example_type=1, description="example6", created_at=datetime.now()) + >>> em7 = ExampleModel.create(example_type=1, description="example7", created_at=datetime.now()) + >>> em8 = ExampleModel.create(example_type=1, description="example8", created_at=datetime.now()) + + #and now we can run some queries against our table + >>> ExampleModel.objects.count() + 8 + >>> q = ExampleModel.objects(example_type=1) + >>> q.count() + 4 + >>> for instance in q: + >>> print instance.description + example5 + example6 + example7 + example8 + + #here we are applying additional filtering to an existing query + #query objects are immutable, so calling filter returns a new + #query object + >>> q2 = q.filter(example_id=em5.example_id) + + >>> q2.count() + 1 + >>> for instance in q2: + >>> print instance.description + example5 diff --git a/3.21.0-scylla/_sources/performance.rst.txt b/3.21.0-scylla/_sources/performance.rst.txt new file mode 100644 index 0000000000..f7a3f49e0f --- /dev/null +++ b/3.21.0-scylla/_sources/performance.rst.txt @@ -0,0 +1,45 @@ +Performance Notes +================= +The Python driver for Cassandra offers several methods for executing queries. +You can synchronously block for queries to complete using +:meth:`.Session.execute()`, you can obtain asynchronous request futures through +:meth:`.Session.execute_async()`, and you can attach a callback to the future +with :meth:`.ResponseFuture.add_callback()`. + +Examples of multiple request patterns can be found in the benchmark scripts included in the driver project. + +The choice of execution pattern will depend on the application context. For applications dealing with multiple +requests in a given context, the recommended pattern is to use concurrent asynchronous +requests with callbacks. For many use cases, you don't need to implement this pattern yourself. +:meth:`cassandra.concurrent.execute_concurrent` and :meth:`cassandra.concurrent.execute_concurrent_with_args` +provide this pattern with a synchronous API and tunable concurrency. + +Due to the GIL and limited concurrency, the driver can become CPU-bound pretty quickly. The sections below +discuss further runtime and design considerations for mitigating this limitation. + +PyPy +---- +`PyPy `_ is an alternative Python runtime which uses a JIT compiler to +reduce CPU consumption. This leads to a huge improvement in the driver performance, +more than doubling throughput for many workloads. + +Cython Extensions +----------------- +`Cython `_ is an optimizing compiler and language that can be used to compile the core files and +optional extensions for the driver. Cython is not a strict dependency, but the extensions will be built by default. + +See :doc:`installation` for details on controlling this build. + +multiprocessing +--------------- +All of the patterns discussed above may be used over multiple processes using the +`multiprocessing `_ +module. Multiple processes will scale better than multiple threads, so if high throughput is your goal, +consider this option. + +Be sure to **never share any** :class:`~.Cluster`, :class:`~.Session`, +**or** :class:`~.ResponseFuture` **objects across multiple processes**. These +objects should all be created after forking the process, not before. + +For further discussion and simple examples using the driver with ``multiprocessing``, +see `this blog post `_. diff --git a/3.21.0-scylla/_sources/query_paging.rst.txt b/3.21.0-scylla/_sources/query_paging.rst.txt new file mode 100644 index 0000000000..2c4a4995ca --- /dev/null +++ b/3.21.0-scylla/_sources/query_paging.rst.txt @@ -0,0 +1,95 @@ +.. _query-paging: + +Paging Large Queries +==================== +Cassandra 2.0+ offers support for automatic query paging. Starting with +version 2.0 of the driver, if :attr:`~.Cluster.protocol_version` is greater than +:const:`2` (it is by default), queries returning large result sets will be +automatically paged. + +Controlling the Page Size +------------------------- +By default, :attr:`.Session.default_fetch_size` controls how many rows will +be fetched per page. This can be overridden per-query by setting +:attr:`~.fetch_size` on a :class:`~.Statement`. By default, each page +will contain at most 5000 rows. + +Handling Paged Results +---------------------- +Whenever the number of result rows for are query exceed the page size, an +instance of :class:`~.PagedResult` will be returned instead of a normal +list. This class implements the iterator interface, so you can treat +it like a normal iterator over rows:: + + from cassandra.query import SimpleStatement + query = "SELECT * FROM users" # users contains 100 rows + statement = SimpleStatement(query, fetch_size=10) + for user_row in session.execute(statement): + process_user(user_row) + +Whenever there are no more rows in the current page, the next page will +be fetched transparently. However, note that it *is* possible for +an :class:`Exception` to be raised while fetching the next page, just +like you might see on a normal call to ``session.execute()``. + +If you use :meth:`.Session.execute_async()` along with, +:meth:`.ResponseFuture.result()`, the first page will be fetched before +:meth:`~.ResponseFuture.result()` returns, but latter pages will be +transparently fetched synchronously while iterating the result. + +Handling Paged Results with Callbacks +------------------------------------- +If callbacks are attached to a query that returns a paged result, +the callback will be called once per page with a normal list of rows. + +Use :attr:`.ResponseFuture.has_more_pages` and +:meth:`.ResponseFuture.start_fetching_next_page()` to continue fetching +pages. For example:: + + class PagedResultHandler(object): + + def __init__(self, future): + self.error = None + self.finished_event = Event() + self.future = future + self.future.add_callbacks( + callback=self.handle_page, + errback=self.handle_err) + + def handle_page(self, rows): + for row in rows: + process_row(row) + + if self.future.has_more_pages: + self.future.start_fetching_next_page() + else: + self.finished_event.set() + + def handle_error(self, exc): + self.error = exc + self.finished_event.set() + + future = session.execute_async("SELECT * FROM users") + handler = PagedResultHandler(future) + handler.finished_event.wait() + if handler.error: + raise handler.error + +Resume Paged Results +-------------------- + +You can resume the pagination when executing a new query by using the :attr:`.ResultSet.paging_state`. This can be useful if you want to provide some stateless pagination capabilities to your application (ie. via http). For example:: + + from cassandra.query import SimpleStatement + query = "SELECT * FROM users" + statement = SimpleStatement(query, fetch_size=10) + results = session.execute(statement) + + # save the paging_state somewhere and return current results + web_session['paging_stage'] = results.paging_state + + + # resume the pagination sometime later... + statement = SimpleStatement(query, fetch_size=10) + ps = web_session['paging_state'] + results = session.execute(statement, paging_state=ps) diff --git a/3.21.0-scylla/_sources/security.rst.txt b/3.21.0-scylla/_sources/security.rst.txt new file mode 100644 index 0000000000..4cf3163fb0 --- /dev/null +++ b/3.21.0-scylla/_sources/security.rst.txt @@ -0,0 +1,421 @@ +.. _security: + +Security +======== +The two main security components you will use with the +Python driver are Authentication and SSL. + +Authentication +-------------- +Versions 2.0 and higher of the driver support a SASL-based +authentication mechanism when :attr:`~.Cluster.protocol_version` +is set to 2 or higher. To use this authentication, set +:attr:`~.Cluster.auth_provider` to an instance of a subclass +of :class:`~cassandra.auth.AuthProvider`. When working +with Cassandra's ``PasswordAuthenticator``, you can use +the :class:`~cassandra.auth.PlainTextAuthProvider` class. + +For example, suppose Cassandra is setup with its default +'cassandra' user with a password of 'cassandra': + +.. code-block:: python + + from cassandra.cluster import Cluster + from cassandra.auth import PlainTextAuthProvider + + auth_provider = PlainTextAuthProvider(username='cassandra', password='cassandra') + cluster = Cluster(auth_provider=auth_provider, protocol_version=2) + + + +Custom Authenticators +^^^^^^^^^^^^^^^^^^^^^ +If you're using something other than Cassandra's ``PasswordAuthenticator``, +:class:`~.SaslAuthProvider` is provided for generic SASL authentication mechanisms, +utilizing the ``pure-sasl`` package. +If these do not suit your needs, you may need to create your own subclasses of +:class:`~.AuthProvider` and :class:`~.Authenticator`. You can use the Sasl classes +as example implementations. + +Protocol v1 Authentication +^^^^^^^^^^^^^^^^^^^^^^^^^^ +When working with Cassandra 1.2 (or a higher version with +:attr:`~.Cluster.protocol_version` set to ``1``), you will not pass in +an :class:`~.AuthProvider` instance. Instead, you should pass in a +function that takes one argument, the IP address of a host, and returns +a dict of credentials with a ``username`` and ``password`` key: + +.. code-block:: python + + from cassandra.cluster import Cluster + + def get_credentials(host_address): + return {'username': 'joe', 'password': '1234'} + + cluster = Cluster(auth_provider=get_credentials, protocol_version=1) + +SSL +--- +SSL should be used when client encryption is enabled in Cassandra. + +To give you as much control as possible over your SSL configuration, our SSL +API takes a user-created `SSLContext` instance from the Python standard library. +These docs will include some examples for how to achieve common configurations, +but the `ssl.SSLContext `_ documentation +gives a more complete description of what is possible. + +To enable SSL with version 3.17.0 and higher, you will need to set :attr:`.Cluster.ssl_context` to a +``ssl.SSLContext`` instance to enable SSL. Optionally, you can also set :attr:`.Cluster.ssl_options` +to a dict of options. These will be passed as kwargs to ``ssl.SSLContext.wrap_socket()`` +when new sockets are created. + +If you create your SSLContext using `ssl.create_default_context `_, +be aware that SSLContext.check_hostname is set to True by default, so the hostname validation will be done +by Python and not the driver. For this reason, we need to set the server_hostname at best effort, which is the +resolved ip address. If this validation needs to be done against the FQDN, consider enabling it using the ssl_options +as described in the following examples or implement your own :class:`~.connection.EndPoint` and +:class:`~.connection.EndPointFactory`. + + +The following examples assume you have generated your Cassandra certificate and +keystore files with these intructions: + +* `Setup SSL Cert `_ + +It might be also useful to learn about the different levels of identity verification to understand the examples: + +* `Using SSL in DSE drivers `_ + +SSL with Twisted or Eventlet +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Twisted and Eventlet both use an alternative SSL implementation called pyOpenSSL, so if your `Cluster`'s connection class is +:class:`~cassandra.io.twistedreactor.TwistedConnection` or :class:`~cassandra.io.eventletreactor.EventletConnection`, you must pass a +`pyOpenSSL context `_ instead. +An example is provided in these docs, and more details can be found in the +`documentation `_. +pyOpenSSL is not installed by the driver and must be installed separately. + +SSL Configuration Examples +^^^^^^^^^^^^^^^^^^^^^^^^^^ +Here, we'll describe the server and driver configuration necessary to set up SSL to meet various goals, such as the client verifying the server and the server verifying the client. We'll also include Python code demonstrating how to use servers and drivers configured in these ways. + +.. _ssl-no-identify-verification: + +No identity verification +++++++++++++++++++++++++ + +No identity verification at all. Note that this is not recommended for for production deployments. + +The Cassandra configuration:: + + client_encryption_options: + enabled: true + keystore: /path/to/127.0.0.1.keystore + keystore_password: myStorePass + require_client_auth: false + +The driver configuration: + +.. code-block:: python + + from cassandra.cluster import Cluster, Session + from ssl import SSLContext, PROTOCOL_TLSv1 + + ssl_context = SSLContext(PROTOCOL_TLSv1) + + cluster = Cluster(['127.0.0.1'], ssl_context=ssl_context) + session = cluster.connect() + +.. _ssl-client-verifies-server: + +Client verifies server +++++++++++++++++++++++ + +Ensure the python driver verifies the identity of the server. + +The Cassandra configuration:: + + client_encryption_options: + enabled: true + keystore: /path/to/127.0.0.1.keystore + keystore_password: myStorePass + require_client_auth: false + +For the driver configuration, it's very important to set `ssl_context.verify_mode` +to `CERT_REQUIRED`. Otherwise, the loaded verify certificate will have no effect: + +.. code-block:: python + + from cassandra.cluster import Cluster, Session + from ssl import SSLContext, PROTOCOL_TLSv1, CERT_REQUIRED + + ssl_context = SSLContext(PROTOCOL_TLSv1) + ssl_context.load_verify_locations('/path/to/rootca.crt') + ssl_context.verify_mode = CERT_REQUIRED + + cluster = Cluster(['127.0.0.1'], ssl_context=ssl_context) + session = cluster.connect() + +Additionally, you can also force the driver to verify the `hostname` of the server by passing additional options to `ssl_context.wrap_socket` via the `ssl_options` kwarg: + +.. code-block:: python + + from cassandra.cluster import Cluster, Session + from ssl import SSLContext, PROTOCOL_TLSv1, CERT_REQUIRED + + ssl_context = SSLContext(PROTOCOL_TLSv1) + ssl_context.load_verify_locations('/path/to/rootca.crt') + ssl_context.verify_mode = CERT_REQUIRED + ssl_context.check_hostname = True + ssl_options = {'server_hostname': '127.0.0.1'} + + cluster = Cluster(['127.0.0.1'], ssl_context=ssl_context, ssl_options=ssl_options) + session = cluster.connect() + +.. _ssl-server-verifies-client: + +Server verifies client +++++++++++++++++++++++ + +If Cassandra is configured to verify clients (``require_client_auth``), you need to generate +SSL key and certificate files. + +The cassandra configuration:: + + client_encryption_options: + enabled: true + keystore: /path/to/127.0.0.1.keystore + keystore_password: myStorePass + require_client_auth: true + truststore: /path/to/dse-truststore.jks + truststore_password: myStorePass + +The Python ``ssl`` APIs require the certificate in PEM format. First, create a certificate +conf file: + +.. code-block:: bash + + cat > gen_client_cert.conf <`_ +for more details about ``SSLContext`` configuration. + +**Server verifies client and client verifies server using Twisted and pyOpenSSL** + +.. code-block:: python + + from OpenSSL import SSL, crypto + from cassandra.cluster import Cluster + from cassandra.io.twistedreactor import TwistedConnection + + ssl_context = SSL.Context(SSL.TLSv1_METHOD) + ssl_context.set_verify(SSL.VERIFY_PEER, callback=lambda _1, _2, _3, _4, ok: ok) + ssl_context.use_certificate_file('/path/to/client.crt_signed') + ssl_context.use_privatekey_file('/path/to/client.key') + ssl_context.load_verify_locations('/path/to/rootca.crt') + + cluster = Cluster( + contact_points=['127.0.0.1'], + connection_class=TwistedConnection, + ssl_context=ssl_context, + ssl_options={'check_hostname': True} + ) + session = cluster.connect() + + +Connecting using Eventlet would look similar except instead of importing and using ``TwistedConnection``, you would +import and use ``EventletConnection``, including the appropriate monkey-patching. + +Versions 3.16.0 and lower +^^^^^^^^^^^^^^^^^^^^^^^^^ + +To enable SSL you will need to set :attr:`.Cluster.ssl_options` to a +dict of options. These will be passed as kwargs to ``ssl.wrap_socket()`` +when new sockets are created. Note that this use of ssl_options will be +deprecated in the next major release. + +By default, a ``ca_certs`` value should be supplied (the value should be +a string pointing to the location of the CA certs file), and you probably +want to specify ``ssl_version`` as ``ssl.PROTOCOL_TLSv1`` to match +Cassandra's default protocol. + +For example: + +.. code-block:: python + + from cassandra.cluster import Cluster + from ssl import PROTOCOL_TLSv1, CERT_REQUIRED + + ssl_opts = { + 'ca_certs': '/path/to/my/ca.certs', + 'ssl_version': PROTOCOL_TLSv1, + 'cert_reqs': CERT_REQUIRED # Certificates are required and validated + } + cluster = Cluster(ssl_options=ssl_opts) + +This is only an example to show how to pass the ssl parameters. Consider reading +the `python ssl documentation `_ for +your configuration. For further reading, Andrew Mussey has published a thorough guide on +`Using SSL with the DataStax Python driver `_. + +SSL with Twisted +++++++++++++++++ + +In case the twisted event loop is used pyOpenSSL must be installed or an exception will be risen. Also +to set the ``ssl_version`` and ``cert_reqs`` in ``ssl_opts`` the appropriate constants from pyOpenSSL are expected. + +DSE Authentication +------------------ +When authenticating against DSE, the Cassandra driver provides two auth providers that work both with legacy kerberos and Cassandra authenticators, +as well as the new DSE Unified Authentication. This allows client to configure this auth provider independently, +and in advance of any server upgrade. These auth providers are configured in the same way as any previous implementation:: + + from cassandra.auth import DSEGSSAPIAuthProvider + auth_provider = DSEGSSAPIAuthProvider(service='dse', qops=["auth"]) + cluster = Cluster(auth_provider=auth_provider) + session = cluster.connect() + +Implementations are :attr:`.DSEPlainTextAuthProvider`, :class:`.DSEGSSAPIAuthProvider` and :class:`.SaslAuthProvider`. + +DSE Unified Authentication +^^^^^^^^^^^^^^^^^^^^^^^^^^ + +With DSE (>=5.1), unified Authentication allows you to: + +* Proxy Login: Authenticate using a fixed set of authentication credentials but allow authorization of resources based another user id. +* Proxy Execute: Authenticate using a fixed set of authentication credentials but execute requests based on another user id. + +Proxy Login ++++++++++++ + +Proxy login allows you to authenticate with a user but act as another one. You need to ensure the authenticated user has the permission to use the authorization of resources of the other user. ie. this example will allow the `server` user to authenticate as usual but use the authorization of `user1`: + +.. code-block:: text + + GRANT PROXY.LOGIN on role user1 to server + +then you can do the proxy authentication.... + +.. code-block:: python + + from cassandra.cluster import Cluster + from cassandra.auth import SaslAuthProvider + + sasl_kwargs = { + "service": 'dse', + "mechanism":"PLAIN", + "username": 'server', + 'password': 'server', + 'authorization_id': 'user1' + } + + auth_provider = SaslAuthProvider(**sasl_kwargs) + c = Cluster(auth_provider=auth_provider) + s = c.connect() + s.execute(...) # all requests will be executed as 'user1' + +If you are using kerberos, you can use directly :class:`.DSEGSSAPIAuthProvider` and pass the authorization_id, like this: + +.. code-block:: python + + from cassandra.cluster import Cluster + from cassandra.auth import DSEGSSAPIAuthProvider + + # Ensure the kerberos ticket of the server user is set with the kinit utility. + auth_provider = DSEGSSAPIAuthProvider(service='dse', qops=["auth"], principal="server@DATASTAX.COM", + authorization_id='user1@DATASTAX.COM') + c = Cluster(auth_provider=auth_provider) + s = c.connect() + s.execute(...) # all requests will be executed as 'user1' + + +Proxy Execute ++++++++++++++ + +Proxy execute allows you to execute requests as another user than the authenticated one. You need to ensure the authenticated user has the permission to use the authorization of resources of the specified user. ie. this example will allow the `server` user to execute requests as `user1`: + +.. code-block:: text + + GRANT PROXY.EXECUTE on role user1 to server + +then you can do a proxy execute... + +.. code-block:: python + + from cassandra.cluster import Cluster + from cassandra.auth import DSEPlainTextAuthProvider, + + auth_provider = DSEPlainTextAuthProvider('server', 'server') + + c = Cluster(auth_provider=auth_provider) + s = c.connect() + s.execute('select * from k.t;', execute_as='user1') # the request will be executed as 'user1' + +Please see the `official documentation `_ for more details on the feature and configuration process. diff --git a/3.21.0-scylla/_sources/upgrading.rst.txt b/3.21.0-scylla/_sources/upgrading.rst.txt new file mode 100644 index 0000000000..9559fa3579 --- /dev/null +++ b/3.21.0-scylla/_sources/upgrading.rst.txt @@ -0,0 +1,388 @@ +Upgrading +========= + +.. toctree:: + :maxdepth: 1 + +Upgrading from dse-driver +------------------------- + +Since 3.21.0, scylla-driver fully supports DataStax products. dse-driver and +dse-graph users should now migrate to scylla-driver to benefit from latest bug fixes +and new features. The upgrade to this new unified driver version is straightforward +with no major API changes. + +Installation +^^^^^^^^^^^^ + +Only the `scylla-driver` package should be installed. `dse-driver` and `dse-graph` +are not required anymore:: + + pip install scylla-driver + +If you need the Graph *Fluent* API (features provided by dse-graph):: + + pip install scylla-driver[graph] + +See :doc:`installation` for more details. + +Import from the cassandra module +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +There is no `dse` module, so you should import from the `cassandra` module. You +need to change only the first module of your import statements, not the submodules. + +.. code-block:: python + + from dse.cluster import Cluster, EXEC_PROFILE_GRAPH_DEFAULT + from dse.auth import PlainTextAuthProvider + from dse.policies import WhiteListRoundRobinPolicy + + # becomes + + from cassandra.cluster import Cluster, EXEC_PROFILE_GRAPH_DEFAULT + from cassandra.auth import PlainTextAuthProvider + from cassandra.policies import WhiteListRoundRobinPolicy + +Also note that the cassandra.hosts module doesn't exist in scylla-driver. This +module is named cassandra.pool. + +dse-graph +^^^^^^^^^ + +dse-graph features are now built into scylla-driver. The only change you need +to do is your import statements: + +.. code-block:: python + + from dse_graph import .. + from dse_graph.query import .. + + # becomes + + from cassandra.datastax.graph.fluent import .. + from cassandra.datastax.graph.fluent.query import .. + +See :mod:`~.datastax.graph.fluent`. + +Session.execute and Session.execute_async API +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Although it is not common to use this API with positional arguments, it is +important to be aware that the `host` and `execute_as` parameters have had +their positional order swapped. This is only because `execute_as` was added +in dse-driver before `host`. + +See :meth:`.Session.execute`. + +Deprecations +^^^^^^^^^^^^ + +These changes are optional, but recommended: + +* Importing from `cassandra.graph` is deprecated. Consider importing from `cassandra.datastax.graph`. +* Use :class:`~.policies.DefaultLoadBalancingPolicy` instead of DSELoadBalancingPolicy. + +Upgrading to 3.0 +---------------- +Version 3.0 of the DataStax Python driver for Apache Cassandra +adds support for Cassandra 3.0 while maintaining support for +previously supported versions. In addition to substantial internal rework, +there are several updates to the API that integrators will need +to consider: + +Default consistency is now ``LOCAL_ONE`` +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Previous value was ``ONE``. The new value is introduced to mesh with the default +DC-aware load balancing policy and to match other drivers. + +Execution API Updates +^^^^^^^^^^^^^^^^^^^^^ +Result return normalization +~~~~~~~~~~~~~~~~~~~~~~~~~~~ +`PYTHON-368 `_ + +Previously results would be returned as a ``list`` of rows for result rows +up to ``fetch_size``, and ``PagedResult`` afterward. This could break +application code that assumed one type and got another. + +Now, all results are returned as an iterable :class:`~.ResultSet`. + +The preferred way to consume results of unknown size is to iterate through +them, letting automatic paging occur as they are consumed. + +.. code-block:: python + + results = session.execute("SELECT * FROM system.local") + for row in results: + process(row) + +If the expected size of the results is known, it is still possible to +materialize a list using the iterator: + +.. code-block:: python + + results = session.execute("SELECT * FROM system.local") + row_list = list(results) + +For backward compatibility, :class:`~.ResultSet` supports indexing. When +accessed at an index, a `~.ResultSet` object will materialize all its pages: + +.. code-block:: python + + results = session.execute("SELECT * FROM system.local") + first_result = results[0] # materializes results, fetching all pages + +This can send requests and load (possibly large) results into memory, so +`~.ResultSet` will log a warning on implicit materialization. + +Trace information is not attached to executed Statements +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +`PYTHON-318 `_ + +Previously trace data was attached to Statements if tracing was enabled. This +could lead to confusion if the same statement was used for multiple executions. + +Now, trace data is associated with the ``ResponseFuture`` and ``ResultSet`` +returned for each query: + +:meth:`.ResponseFuture.get_query_trace()` + +:meth:`.ResponseFuture.get_all_query_traces()` + +:meth:`.ResultSet.get_query_trace()` + +:meth:`.ResultSet.get_all_query_traces()` + +Binding named parameters now ignores extra names +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +`PYTHON-178 `_ + +Previously, :meth:`.BoundStatement.bind()` would raise if a mapping +was passed with extra names not found in the prepared statement. + +Behavior in 3.0+ is to ignore extra names. + +blist removed as soft dependency +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +`PYTHON-385 `_ + +Previously the driver had a soft dependency on ``blist sortedset``, using +that where available and using an internal fallback where possible. + +Now, the driver never chooses the ``blist`` variant, instead returning the +internal :class:`.util.SortedSet` for all ``set`` results. The class implements +all standard set operations, so no integration code should need to change unless +it explicitly checks for ``sortedset`` type. + +Metadata API Updates +^^^^^^^^^^^^^^^^^^^^ +`PYTHON-276 `_, `PYTHON-408 `_, `PYTHON-400 `_, `PYTHON-422 `_ + +Cassandra 3.0 brought a substantial overhaul to the internal schema metadata representation. +This version of the driver supports that metadata in addition to the legacy version. Doing so +also brought some changes to the metadata model. + +The present API is documented: :any:`cassandra.metadata`. Changes highlighted below: + +* All types are now exposed as CQL types instead of types derived from the internal server implementation +* Some metadata attributes have changed names to match current nomenclature (for example, :attr:`.Index.kind` in place of ``Index.type``). +* Some metadata attributes removed + + * ``TableMetadata.keyspace`` reference replaced with :attr:`.TableMetadata.keyspace_name` + * ``ColumnMetadata.index`` is removed table- and keyspace-level mappings are still maintained + +Several deprecated features are removed +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +`PYTHON-292 `_ + +* ``ResponseFuture.result`` timeout parameter is removed, use ``Session.execute`` timeout instead (`031ebb0 `_) +* ``Cluster.refresh_schema`` removed, use ``Cluster.refresh_*_metadata`` instead (`419fcdf `_) +* ``Cluster.submit_schema_refresh`` removed (`574266d `_) +* ``cqltypes`` time/date functions removed, use ``util`` entry points instead (`bb984ee `_) +* ``decoder`` module removed (`e16a073 `_) +* ``TableMetadata.keyspace`` attribute replaced with ``keyspace_name`` (`cc94073 `_) +* ``cqlengine.columns.TimeUUID.from_datetime`` removed, use ``util`` variant instead (`96489cc `_) +* ``cqlengine.columns.Float(double_precision)`` parameter removed, use ``columns.Double`` instead (`a2d3a98 `_) +* ``cqlengine`` keyspace management functions are removed in favor of the strategy-specific entry points (`4bd5909 `_) +* ``cqlengine.Model.__polymorphic_*__`` attributes removed, use ``__discriminator*`` attributes instead (`9d98c8e `_) +* ``cqlengine.statements`` will no longer warn about list list prepend behavior (`79efe97 `_) + + +Upgrading to 2.1 from 2.0 +------------------------- +Version 2.1 of the DataStax Python driver for Apache Cassandra +adds support for Cassandra 2.1 and version 3 of the native protocol. + +Cassandra 1.2, 2.0, and 2.1 are all supported. However, 1.2 only +supports protocol version 1, and 2.0 only supports versions 1 and +2, so some features may not be available. + +Using the v3 Native Protocol +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +By default, the driver will attempt to use version 2 of the +native protocol. To use version 3, you must explicitly +set the :attr:`~.Cluster.protocol_version`: + +.. code-block:: python + + from cassandra.cluster import Cluster + + cluster = Cluster(protocol_version=3) + +Note that protocol version 3 is only supported by Cassandra 2.1+. + +In future releases, the driver may default to using protocol version +3. + +Working with User-Defined Types +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Cassandra 2.1 introduced the ability to define new types:: + + USE KEYSPACE mykeyspace; + + CREATE TYPE address (street text, city text, zip int); + +The driver generally expects you to use instances of a specific +class to represent column values of this type. You can let the +driver know what class to use with :meth:`.Cluster.register_user_type`: + +.. code-block:: python + + cluster = Cluster() + + class Address(object): + + def __init__(self, street, city, zipcode): + self.street = street + self.city = text + self.zipcode = zipcode + + cluster.register_user_type('mykeyspace', 'address', Address) + +When inserting data for ``address`` columns, you should pass in +instances of ``Address``. When querying data, ``address`` column +values will be instances of ``Address``. + +If no class is registered for a user-defined type, query results +will use a ``namedtuple`` class and data may only be inserted +though prepared statements. + +See :ref:`udts` for more details. + +Customizing Encoders for Non-prepared Statements +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Starting with version 2.1 of the driver, it is possible to customize +how Python types are converted to CQL literals when working with +non-prepared statements. This is done on a per-:class:`~.Session` +basis through :attr:`.Session.encoder`: + +.. code-block:: python + + cluster = Cluster() + session = cluster.connect() + session.encoder.mapping[tuple] = session.encoder.cql_encode_tuple + +See :ref:`type-conversions` for the table of default CQL literal conversions. + +Using Client-Side Protocol-Level Timestamps +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +With version 3 of the native protocol, timestamps may be supplied by the +client at the protocol level. (Normally, if they are not specified within +the CQL query itself, a timestamp is generated server-side.) + +When :attr:`~.Cluster.protocol_version` is set to 3 or higher, the driver +will automatically use client-side timestamps with microsecond precision +unless :attr:`.Session.use_client_timestamp` is changed to :const:`False`. +If a timestamp is specified within the CQL query, it will override the +timestamp generated by the driver. + +Upgrading to 2.0 from 1.x +------------------------- +Version 2.0 of the DataStax Python driver for Apache Cassandra +includes some notable improvements over version 1.x. This version +of the driver supports Cassandra 1.2, 2.0, and 2.1. However, not +all features may be used with Cassandra 1.2, and some new features +in 2.1 are not yet supported. + +Using the v2 Native Protocol +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +By default, the driver will attempt to use version 2 of Cassandra's +native protocol. You can explicitly set the protocol version to +2, though: + +.. code-block:: python + + from cassandra.cluster import Cluster + + cluster = Cluster(protocol_version=2) + +When working with Cassandra 1.2, you will need to +explicitly set the :attr:`~.Cluster.protocol_version` to 1: + +.. code-block:: python + + from cassandra.cluster import Cluster + + cluster = Cluster(protocol_version=1) + +Automatic Query Paging +^^^^^^^^^^^^^^^^^^^^^^ +Version 2 of the native protocol adds support for automatic query +paging, which can make dealing with large result sets much simpler. + +See :ref:`query-paging` for full details. + +Protocol-Level Batch Statements +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +With version 1 of the native protocol, batching of statements required +using a `BATCH cql query `_. +With version 2 of the native protocol, you can now batch statements at +the protocol level. This allows you to use many different prepared +statements within a single batch. + +See :class:`~.query.BatchStatement` for details and usage examples. + +SASL-based Authentication +^^^^^^^^^^^^^^^^^^^^^^^^^ +Also new in version 2 of the native protocol is SASL-based authentication. +See the section on :ref:`security` for details and examples. + +Lightweight Transactions +^^^^^^^^^^^^^^^^^^^^^^^^ +`Lightweight transactions `_ are another new feature. To use lightweight transactions, add ``IF`` clauses +to your CQL queries and set the :attr:`~.Statement.serial_consistency_level` +on your statements. + +Calling Cluster.shutdown() +^^^^^^^^^^^^^^^^^^^^^^^^^^ +In order to fix some issues around garbage collection and unclean interpreter +shutdowns, version 2.0 of the driver requires you to call :meth:`.Cluster.shutdown()` +on your :class:`~.Cluster` objects when you are through with them. +This helps to guarantee a clean shutdown. + +Deprecations +^^^^^^^^^^^^ +The following functions have moved from ``cassandra.decoder`` to ``cassandra.query``. +The original functions have been left in place with a :exc:`DeprecationWarning` for +now: + +* :attr:`cassandra.decoder.tuple_factory` has moved to + :attr:`cassandra.query.tuple_factory` +* :attr:`cassandra.decoder.named_tuple_factory` has moved to + :attr:`cassandra.query.named_tuple_factory` +* :attr:`cassandra.decoder.dict_factory` has moved to + :attr:`cassandra.query.dict_factory` +* :attr:`cassandra.decoder.ordered_dict_factory` has moved to + :attr:`cassandra.query.ordered_dict_factory` + +Dependency Changes +^^^^^^^^^^^^^^^^^^ +The following dependencies have officially been made optional: + +* ``scales`` +* ``blist`` + +And one new dependency has been added (to enable Python 3 support): + +* ``six`` diff --git a/3.21.0-scylla/_sources/user_defined_types.rst.txt b/3.21.0-scylla/_sources/user_defined_types.rst.txt new file mode 100644 index 0000000000..32c03e37e8 --- /dev/null +++ b/3.21.0-scylla/_sources/user_defined_types.rst.txt @@ -0,0 +1,118 @@ +.. _udts: + +User Defined Types +================== +Cassandra 2.1 introduced user-defined types (UDTs). You can create a +new type through ``CREATE TYPE`` statements in CQL:: + + CREATE TYPE address (street text, zip int); + +Version 2.1 of the Python driver adds support for user-defined types. + +Registering a UDT +----------------- +You can tell the Python driver to return columns of a specific UDT as +instances of a class or a dict by registering them with your :class:`~.Cluster` +instance through :meth:`.Cluster.register_user_type`: + + +Map a Class to a UDT +++++++++++++++++++++ + +.. code-block:: python + + cluster = Cluster(protocol_version=3) + session = cluster.connect() + session.set_keyspace('mykeyspace') + session.execute("CREATE TYPE address (street text, zipcode int)") + session.execute("CREATE TABLE users (id int PRIMARY KEY, location frozen
)") + + # create a class to map to the "address" UDT + class Address(object): + + def __init__(self, street, zipcode): + self.street = street + self.zipcode = zipcode + + cluster.register_user_type('mykeyspace', 'address', Address) + + # insert a row using an instance of Address + session.execute("INSERT INTO users (id, location) VALUES (%s, %s)", + (0, Address("123 Main St.", 78723))) + + # results will include Address instances + results = session.execute("SELECT * FROM users") + row = results[0] + print(row.id, row.location.street, row.location.zipcode) + +Map a dict to a UDT ++++++++++++++++++++ + +.. code-block:: python + + cluster = Cluster(protocol_version=3) + session = cluster.connect() + session.set_keyspace('mykeyspace') + session.execute("CREATE TYPE address (street text, zipcode int)") + session.execute("CREATE TABLE users (id int PRIMARY KEY, location frozen
)") + + cluster.register_user_type('mykeyspace', 'address', dict) + + # insert a row using a prepared statement and a tuple + insert_statement = session.prepare("INSERT INTO mykeyspace.users (id, location) VALUES (?, ?)") + session.execute(insert_statement, [0, ("123 Main St.", 78723)]) + + # results will include dict instances + results = session.execute("SELECT * FROM users") + row = results[0] + print(row.id, row.location['street'], row.location['zipcode']) + +Using UDTs Without Registering Them +----------------------------------- +Although it is recommended to register your types with +:meth:`.Cluster.register_user_type`, the driver gives you some options +for working with unregistered UDTS. + +When you use prepared statements, the driver knows what data types to +expect for each placeholder. This allows you to pass any object you +want for a UDT, as long as it has attributes that match the field names +for the UDT: + +.. code-block:: python + + cluster = Cluster(protocol_version=3) + session = cluster.connect() + session.set_keyspace('mykeyspace') + session.execute("CREATE TYPE address (street text, zipcode int)") + session.execute("CREATE TABLE users (id int PRIMARY KEY, location frozen
)") + + class Foo(object): + + def __init__(self, street, zipcode, otherstuff): + self.street = street + self.zipcode = zipcode + self.otherstuff = otherstuff + + insert_statement = session.prepare("INSERT INTO users (id, location) VALUES (?, ?)") + + # since we're using a prepared statement, we don't *have* to register + # a class to map to the UDT to insert data. The object just needs to have + # "street" and "zipcode" attributes (which Foo does): + session.execute(insert_statement, [0, Foo("123 Main St.", 78723, "some other stuff")]) + + # when we query data, UDT columns that don't have a class registered + # will be returned as namedtuples: + results = session.execute("SELECT * FROM users") + first_row = results[0] + address = first_row.location + print(address) # prints "Address(street='123 Main St.', zipcode=78723)" + street = address.street + zipcode = address.street + +As shown in the code example, inserting data for UDT columns without registering +a class works fine for prepared statements. However, **you must register a +class to insert UDT columns with unprepared statements**.\* You can still query +UDT columns without registered classes using unprepared statements, they will +simply return ``namedtuple`` instances (just like prepared statements do). + +\* this applies to *parameterized* unprepared statements, in which the driver will be formatting parameters -- not statements with interpolated UDT literals. diff --git a/3.21.0-scylla/_static/basic.css b/3.21.0-scylla/_static/basic.css new file mode 100644 index 0000000000..603f6a8798 --- /dev/null +++ b/3.21.0-scylla/_static/basic.css @@ -0,0 +1,905 @@ +/* + * basic.css + * ~~~~~~~~~ + * + * Sphinx stylesheet -- basic theme. + * + * :copyright: Copyright 2007-2021 by the Sphinx team, see AUTHORS. + * :license: BSD, see LICENSE for details. + * + */ + +/* -- main layout ----------------------------------------------------------- */ + +div.clearer { + clear: both; +} + +div.section::after { + display: block; + content: ''; + clear: left; +} + +/* -- relbar ---------------------------------------------------------------- */ + +div.related { + width: 100%; + font-size: 90%; +} + +div.related h3 { + display: none; +} + +div.related ul { + margin: 0; + padding: 0 0 0 10px; + list-style: none; +} + +div.related li { + display: inline; +} + +div.related li.right { + float: right; + margin-right: 5px; +} + +/* -- sidebar --------------------------------------------------------------- */ + +div.sphinxsidebarwrapper { + padding: 10px 5px 0 10px; +} + +div.sphinxsidebar { + float: left; + width: 230px; + margin-left: -100%; + font-size: 90%; + word-wrap: break-word; + overflow-wrap : break-word; +} + +div.sphinxsidebar ul { + list-style: none; +} + +div.sphinxsidebar ul ul, +div.sphinxsidebar ul.want-points { + margin-left: 20px; + list-style: square; +} + +div.sphinxsidebar ul ul { + margin-top: 0; + margin-bottom: 0; +} + +div.sphinxsidebar form { + margin-top: 10px; +} + +div.sphinxsidebar input { + border: 1px solid #98dbcc; + font-family: sans-serif; + font-size: 1em; +} + +div.sphinxsidebar #searchbox form.search { + overflow: hidden; +} + +div.sphinxsidebar #searchbox input[type="text"] { + float: left; + width: 80%; + padding: 0.25em; + box-sizing: border-box; +} + +div.sphinxsidebar #searchbox input[type="submit"] { + float: left; + width: 20%; + border-left: none; + padding: 0.25em; + box-sizing: border-box; +} + + +img { + border: 0; + max-width: 100%; +} + +/* -- search page ----------------------------------------------------------- */ + +ul.search { + margin: 10px 0 0 20px; + padding: 0; +} + +ul.search li { + padding: 5px 0 5px 20px; + background-image: url(file.png); + background-repeat: no-repeat; + background-position: 0 7px; +} + +ul.search li a { + font-weight: bold; +} + +ul.search li p.context { + color: #888; + margin: 2px 0 0 30px; + text-align: left; +} + +ul.keywordmatches li.goodmatch a { + font-weight: bold; +} + +/* -- index page ------------------------------------------------------------ */ + +table.contentstable { + width: 90%; + margin-left: auto; + margin-right: auto; +} + +table.contentstable p.biglink { + line-height: 150%; +} + +a.biglink { + font-size: 1.3em; +} + +span.linkdescr { + font-style: italic; + padding-top: 5px; + font-size: 90%; +} + +/* -- general index --------------------------------------------------------- */ + +table.indextable { + width: 100%; +} + +table.indextable td { + text-align: left; + vertical-align: top; +} + +table.indextable ul { + margin-top: 0; + margin-bottom: 0; + list-style-type: none; +} + +table.indextable > tbody > tr > td > ul { + padding-left: 0em; +} + +table.indextable tr.pcap { + height: 10px; +} + +table.indextable tr.cap { + margin-top: 10px; + background-color: #f2f2f2; +} + +img.toggler { + margin-right: 3px; + margin-top: 3px; + cursor: pointer; +} + +div.modindex-jumpbox { + border-top: 1px solid #ddd; + border-bottom: 1px solid #ddd; + margin: 1em 0 1em 0; + padding: 0.4em; +} + +div.genindex-jumpbox { + border-top: 1px solid #ddd; + border-bottom: 1px solid #ddd; + margin: 1em 0 1em 0; + padding: 0.4em; +} + +/* -- domain module index --------------------------------------------------- */ + +table.modindextable td { + padding: 2px; + border-collapse: collapse; +} + +/* -- general body styles --------------------------------------------------- */ + +div.body { + min-width: 450px; + max-width: 800px; +} + +div.body p, div.body dd, div.body li, div.body blockquote { + -moz-hyphens: auto; + -ms-hyphens: auto; + -webkit-hyphens: auto; + hyphens: auto; +} + +a.headerlink { + visibility: hidden; +} + +a.brackets:before, +span.brackets > a:before{ + content: "["; +} + +a.brackets:after, +span.brackets > a:after { + content: "]"; +} + +h1:hover > a.headerlink, +h2:hover > a.headerlink, +h3:hover > a.headerlink, +h4:hover > a.headerlink, +h5:hover > a.headerlink, +h6:hover > a.headerlink, +dt:hover > a.headerlink, +caption:hover > a.headerlink, +p.caption:hover > a.headerlink, +div.code-block-caption:hover > a.headerlink { + visibility: visible; +} + +div.body p.caption { + text-align: inherit; +} + +div.body td { + text-align: left; +} + +.first { + margin-top: 0 !important; +} + +p.rubric { + margin-top: 30px; + font-weight: bold; +} + +img.align-left, figure.align-left, .figure.align-left, object.align-left { + clear: left; + float: left; + margin-right: 1em; +} + +img.align-right, figure.align-right, .figure.align-right, object.align-right { + clear: right; + float: right; + margin-left: 1em; +} + +img.align-center, figure.align-center, .figure.align-center, object.align-center { + display: block; + margin-left: auto; + margin-right: auto; +} + +img.align-default, figure.align-default, .figure.align-default { + display: block; + margin-left: auto; + margin-right: auto; +} + +.align-left { + text-align: left; +} + +.align-center { + text-align: center; +} + +.align-default { + text-align: center; +} + +.align-right { + text-align: right; +} + +/* -- sidebars -------------------------------------------------------------- */ + +div.sidebar, +aside.sidebar { + margin: 0 0 0.5em 1em; + border: 1px solid #ddb; + padding: 7px; + background-color: #ffe; + width: 40%; + float: right; + clear: right; + overflow-x: auto; +} + +p.sidebar-title { + font-weight: bold; +} + +div.admonition, div.topic, blockquote { + clear: left; +} + +/* -- topics ---------------------------------------------------------------- */ + +div.topic { + border: 1px solid #ccc; + padding: 7px; + margin: 10px 0 10px 0; +} + +p.topic-title { + font-size: 1.1em; + font-weight: bold; + margin-top: 10px; +} + +/* -- admonitions ----------------------------------------------------------- */ + +div.admonition { + margin-top: 10px; + margin-bottom: 10px; + padding: 7px; +} + +div.admonition dt { + font-weight: bold; +} + +p.admonition-title { + margin: 0px 10px 5px 0px; + font-weight: bold; +} + +div.body p.centered { + text-align: center; + margin-top: 25px; +} + +/* -- content of sidebars/topics/admonitions -------------------------------- */ + +div.sidebar > :last-child, +aside.sidebar > :last-child, +div.topic > :last-child, +div.admonition > :last-child { + margin-bottom: 0; +} + +div.sidebar::after, +aside.sidebar::after, +div.topic::after, +div.admonition::after, +blockquote::after { + display: block; + content: ''; + clear: both; +} + +/* -- tables ---------------------------------------------------------------- */ + +table.docutils { + margin-top: 10px; + margin-bottom: 10px; + border: 0; + border-collapse: collapse; +} + +table.align-center { + margin-left: auto; + margin-right: auto; +} + +table.align-default { + margin-left: auto; + margin-right: auto; +} + +table caption span.caption-number { + font-style: italic; +} + +table caption span.caption-text { +} + +table.docutils td, table.docutils th { + padding: 1px 8px 1px 5px; + border-top: 0; + border-left: 0; + border-right: 0; + border-bottom: 1px solid #aaa; +} + +table.footnote td, table.footnote th { + border: 0 !important; +} + +th { + text-align: left; + padding-right: 5px; +} + +table.citation { + border-left: solid 1px gray; + margin-left: 1px; +} + +table.citation td { + border-bottom: none; +} + +th > :first-child, +td > :first-child { + margin-top: 0px; +} + +th > :last-child, +td > :last-child { + margin-bottom: 0px; +} + +/* -- figures --------------------------------------------------------------- */ + +div.figure, figure { + margin: 0.5em; + padding: 0.5em; +} + +div.figure p.caption, figcaption { + padding: 0.3em; +} + +div.figure p.caption span.caption-number, +figcaption span.caption-number { + font-style: italic; +} + +div.figure p.caption span.caption-text, +figcaption span.caption-text { +} + +/* -- field list styles ----------------------------------------------------- */ + +table.field-list td, table.field-list th { + border: 0 !important; +} + +.field-list ul { + margin: 0; + padding-left: 1em; +} + +.field-list p { + margin: 0; +} + +.field-name { + -moz-hyphens: manual; + -ms-hyphens: manual; + -webkit-hyphens: manual; + hyphens: manual; +} + +/* -- hlist styles ---------------------------------------------------------- */ + +table.hlist { + margin: 1em 0; +} + +table.hlist td { + vertical-align: top; +} + +/* -- object description styles --------------------------------------------- */ + +.sig { + font-family: 'Consolas', 'Menlo', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace; +} + +.sig-name, code.descname { + background-color: transparent; + font-weight: bold; +} + +.sig-name { + font-size: 1.1em; +} + +code.descname { + font-size: 1.2em; +} + +.sig-prename, code.descclassname { + background-color: transparent; +} + +.optional { + font-size: 1.3em; +} + +.sig-paren { + font-size: larger; +} + +.sig-param.n { + font-style: italic; +} + +/* C++ specific styling */ + +.sig-inline.c-texpr, +.sig-inline.cpp-texpr { + font-family: unset; +} + +.sig.c .k, .sig.c .kt, +.sig.cpp .k, .sig.cpp .kt { + color: #0033B3; +} + +.sig.c .m, +.sig.cpp .m { + color: #1750EB; +} + +.sig.c .s, .sig.c .sc, +.sig.cpp .s, .sig.cpp .sc { + color: #067D17; +} + + +/* -- other body styles ----------------------------------------------------- */ + +ol.arabic { + list-style: decimal; +} + +ol.loweralpha { + list-style: lower-alpha; +} + +ol.upperalpha { + list-style: upper-alpha; +} + +ol.lowerroman { + list-style: lower-roman; +} + +ol.upperroman { + list-style: upper-roman; +} + +:not(li) > ol > li:first-child > :first-child, +:not(li) > ul > li:first-child > :first-child { + margin-top: 0px; +} + +:not(li) > ol > li:last-child > :last-child, +:not(li) > ul > li:last-child > :last-child { + margin-bottom: 0px; +} + +ol.simple ol p, +ol.simple ul p, +ul.simple ol p, +ul.simple ul p { + margin-top: 0; +} + +ol.simple > li:not(:first-child) > p, +ul.simple > li:not(:first-child) > p { + margin-top: 0; +} + +ol.simple p, +ul.simple p { + margin-bottom: 0; +} + +dl.footnote > dt, +dl.citation > dt { + float: left; + margin-right: 0.5em; +} + +dl.footnote > dd, +dl.citation > dd { + margin-bottom: 0em; +} + +dl.footnote > dd:after, +dl.citation > dd:after { + content: ""; + clear: both; +} + +dl.field-list { + display: grid; + grid-template-columns: fit-content(30%) auto; +} + +dl.field-list > dt { + font-weight: bold; + word-break: break-word; + padding-left: 0.5em; + padding-right: 5px; +} + +dl.field-list > dt:after { + content: ":"; +} + +dl.field-list > dd { + padding-left: 0.5em; + margin-top: 0em; + margin-left: 0em; + margin-bottom: 0em; +} + +dl { + margin-bottom: 15px; +} + +dd > :first-child { + margin-top: 0px; +} + +dd ul, dd table { + margin-bottom: 10px; +} + +dd { + margin-top: 3px; + margin-bottom: 10px; + margin-left: 30px; +} + +dl > dd:last-child, +dl > dd:last-child > :last-child { + margin-bottom: 0; +} + +dt:target, span.highlighted { + background-color: #fbe54e; +} + +rect.highlighted { + fill: #fbe54e; +} + +dl.glossary dt { + font-weight: bold; + font-size: 1.1em; +} + +.versionmodified { + font-style: italic; +} + +.system-message { + background-color: #fda; + padding: 5px; + border: 3px solid red; +} + +.footnote:target { + background-color: #ffa; +} + +.line-block { + display: block; + margin-top: 1em; + margin-bottom: 1em; +} + +.line-block .line-block { + margin-top: 0; + margin-bottom: 0; + margin-left: 1.5em; +} + +.guilabel, .menuselection { + font-family: sans-serif; +} + +.accelerator { + text-decoration: underline; +} + +.classifier { + font-style: oblique; +} + +.classifier:before { + font-style: normal; + margin: 0 0.5em; + content: ":"; + display: inline-block; +} + +abbr, acronym { + border-bottom: dotted 1px; + cursor: help; +} + +/* -- code displays --------------------------------------------------------- */ + +pre { + overflow: auto; + overflow-y: hidden; /* fixes display issues on Chrome browsers */ +} + +pre, div[class*="highlight-"] { + clear: both; +} + +span.pre { + -moz-hyphens: none; + -ms-hyphens: none; + -webkit-hyphens: none; + hyphens: none; +} + +div[class*="highlight-"] { + margin: 1em 0; +} + +td.linenos pre { + border: 0; + background-color: transparent; + color: #aaa; +} + +table.highlighttable { + display: block; +} + +table.highlighttable tbody { + display: block; +} + +table.highlighttable tr { + display: flex; +} + +table.highlighttable td { + margin: 0; + padding: 0; +} + +table.highlighttable td.linenos { + padding-right: 0.5em; +} + +table.highlighttable td.code { + flex: 1; + overflow: hidden; +} + +.highlight .hll { + display: block; +} + +div.highlight pre, +table.highlighttable pre { + margin: 0; +} + +div.code-block-caption + div { + margin-top: 0; +} + +div.code-block-caption { + margin-top: 1em; + padding: 2px 5px; + font-size: small; +} + +div.code-block-caption code { + background-color: transparent; +} + +table.highlighttable td.linenos, +span.linenos, +div.highlight span.gp { /* gp: Generic.Prompt */ + user-select: none; + -webkit-user-select: text; /* Safari fallback only */ + -webkit-user-select: none; /* Chrome/Safari */ + -moz-user-select: none; /* Firefox */ + -ms-user-select: none; /* IE10+ */ +} + +div.code-block-caption span.caption-number { + padding: 0.1em 0.3em; + font-style: italic; +} + +div.code-block-caption span.caption-text { +} + +div.literal-block-wrapper { + margin: 1em 0; +} + +code.xref, a code { + background-color: transparent; + font-weight: bold; +} + +h1 code, h2 code, h3 code, h4 code, h5 code, h6 code { + background-color: transparent; +} + +.viewcode-link { + float: right; +} + +.viewcode-back { + float: right; + font-family: sans-serif; +} + +div.viewcode-block:target { + margin: -1px -10px; + padding: 0 10px; +} + +/* -- math display ---------------------------------------------------------- */ + +img.math { + vertical-align: middle; +} + +div.body div.math p { + text-align: center; +} + +span.eqno { + float: right; +} + +span.eqno a.headerlink { + position: absolute; + z-index: 1; +} + +div.math:hover a.headerlink { + visibility: visible; +} + +/* -- printout stylesheet --------------------------------------------------- */ + +@media print { + div.document, + div.documentwrapper, + div.bodywrapper { + margin: 0 !important; + width: 100%; + } + + div.sphinxsidebar, + div.related, + div.footer, + #top-link { + display: none; + } +} \ No newline at end of file diff --git a/3.21.0-scylla/_static/check-solid.svg b/3.21.0-scylla/_static/check-solid.svg new file mode 100644 index 0000000000..92fad4b5c0 --- /dev/null +++ b/3.21.0-scylla/_static/check-solid.svg @@ -0,0 +1,4 @@ + + + + diff --git a/3.21.0-scylla/_static/clipboard.min.js b/3.21.0-scylla/_static/clipboard.min.js new file mode 100644 index 0000000000..54b3c46381 --- /dev/null +++ b/3.21.0-scylla/_static/clipboard.min.js @@ -0,0 +1,7 @@ +/*! + * clipboard.js v2.0.8 + * https://clipboardjs.com/ + * + * Licensed MIT © Zeno Rocha + */ +!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?exports.ClipboardJS=e():t.ClipboardJS=e()}(this,function(){return n={686:function(t,e,n){"use strict";n.d(e,{default:function(){return o}});var e=n(279),i=n.n(e),e=n(370),u=n.n(e),e=n(817),c=n.n(e);function a(t){try{return document.execCommand(t)}catch(t){return}}var f=function(t){t=c()(t);return a("cut"),t};var l=function(t){var e,n,o,r=1 + + + + diff --git a/3.21.0-scylla/_static/copybutton.css b/3.21.0-scylla/_static/copybutton.css new file mode 100644 index 0000000000..f1916ec7d1 --- /dev/null +++ b/3.21.0-scylla/_static/copybutton.css @@ -0,0 +1,94 @@ +/* Copy buttons */ +button.copybtn { + position: absolute; + display: flex; + top: .3em; + right: .3em; + width: 1.7em; + height: 1.7em; + opacity: 0; + transition: opacity 0.3s, border .3s, background-color .3s; + user-select: none; + padding: 0; + border: none; + outline: none; + border-radius: 0.4em; + /* The colors that GitHub uses */ + border: #1b1f2426 1px solid; + background-color: #f6f8fa; + color: #57606a; +} + +button.copybtn.success { + border-color: #22863a; + color: #22863a; +} + +button.copybtn svg { + stroke: currentColor; + width: 1.5em; + height: 1.5em; + padding: 0.1em; +} + +div.highlight { + position: relative; +} + +/* Show the copybutton */ +.highlight:hover button.copybtn, button.copybtn.success { + opacity: 1; +} + +.highlight button.copybtn:hover { + background-color: rgb(235, 235, 235); +} + +.highlight button.copybtn:active { + background-color: rgb(187, 187, 187); +} + +/** + * A minimal CSS-only tooltip copied from: + * https://codepen.io/mildrenben/pen/rVBrpK + * + * To use, write HTML like the following: + * + *

Short

+ */ + .o-tooltip--left { + position: relative; + } + + .o-tooltip--left:after { + opacity: 0; + visibility: hidden; + position: absolute; + content: attr(data-tooltip); + padding: .2em; + font-size: .8em; + left: -.2em; + background: grey; + color: white; + white-space: nowrap; + z-index: 2; + border-radius: 2px; + transform: translateX(-102%) translateY(0); + transition: opacity 0.2s cubic-bezier(0.64, 0.09, 0.08, 1), transform 0.2s cubic-bezier(0.64, 0.09, 0.08, 1); +} + +.o-tooltip--left:hover:after { + display: block; + opacity: 1; + visibility: visible; + transform: translateX(-100%) translateY(0); + transition: opacity 0.2s cubic-bezier(0.64, 0.09, 0.08, 1), transform 0.2s cubic-bezier(0.64, 0.09, 0.08, 1); + transition-delay: .5s; +} + +/* By default the copy button shouldn't show up when printing a page */ +@media print { + button.copybtn { + display: none; + } +} diff --git a/3.21.0-scylla/_static/copybutton.js b/3.21.0-scylla/_static/copybutton.js new file mode 100644 index 0000000000..2ea7ff3e21 --- /dev/null +++ b/3.21.0-scylla/_static/copybutton.js @@ -0,0 +1,248 @@ +// Localization support +const messages = { + 'en': { + 'copy': 'Copy', + 'copy_to_clipboard': 'Copy to clipboard', + 'copy_success': 'Copied!', + 'copy_failure': 'Failed to copy', + }, + 'es' : { + 'copy': 'Copiar', + 'copy_to_clipboard': 'Copiar al portapapeles', + 'copy_success': '¡Copiado!', + 'copy_failure': 'Error al copiar', + }, + 'de' : { + 'copy': 'Kopieren', + 'copy_to_clipboard': 'In die Zwischenablage kopieren', + 'copy_success': 'Kopiert!', + 'copy_failure': 'Fehler beim Kopieren', + }, + 'fr' : { + 'copy': 'Copier', + 'copy_to_clipboard': 'Copier dans le presse-papier', + 'copy_success': 'Copié !', + 'copy_failure': 'Échec de la copie', + }, + 'ru': { + 'copy': 'Скопировать', + 'copy_to_clipboard': 'Скопировать в буфер', + 'copy_success': 'Скопировано!', + 'copy_failure': 'Не удалось скопировать', + }, + 'zh-CN': { + 'copy': '复制', + 'copy_to_clipboard': '复制到剪贴板', + 'copy_success': '复制成功!', + 'copy_failure': '复制失败', + }, + 'it' : { + 'copy': 'Copiare', + 'copy_to_clipboard': 'Copiato negli appunti', + 'copy_success': 'Copiato!', + 'copy_failure': 'Errore durante la copia', + } +} + +let locale = 'en' +if( document.documentElement.lang !== undefined + && messages[document.documentElement.lang] !== undefined ) { + locale = document.documentElement.lang +} + +let doc_url_root = DOCUMENTATION_OPTIONS.URL_ROOT; +if (doc_url_root == '#') { + doc_url_root = ''; +} + +/** + * SVG files for our copy buttons + */ +let iconCheck = ` + ${messages[locale]['copy_success']} + + +` + +// If the user specified their own SVG use that, otherwise use the default +let iconCopy = ``; +if (!iconCopy) { + iconCopy = ` + ${messages[locale]['copy_to_clipboard']} + + + +` +} + +/** + * Set up copy/paste for code blocks + */ + +const runWhenDOMLoaded = cb => { + if (document.readyState != 'loading') { + cb() + } else if (document.addEventListener) { + document.addEventListener('DOMContentLoaded', cb) + } else { + document.attachEvent('onreadystatechange', function() { + if (document.readyState == 'complete') cb() + }) + } +} + +const codeCellId = index => `codecell${index}` + +// Clears selected text since ClipboardJS will select the text when copying +const clearSelection = () => { + if (window.getSelection) { + window.getSelection().removeAllRanges() + } else if (document.selection) { + document.selection.empty() + } +} + +// Changes tooltip text for a moment, then changes it back +// We want the timeout of our `success` class to be a bit shorter than the +// tooltip and icon change, so that we can hide the icon before changing back. +var timeoutIcon = 2000; +var timeoutSuccessClass = 1500; + +const temporarilyChangeTooltip = (el, oldText, newText) => { + el.setAttribute('data-tooltip', newText) + el.classList.add('success') + // Remove success a little bit sooner than we change the tooltip + // So that we can use CSS to hide the copybutton first + setTimeout(() => el.classList.remove('success'), timeoutSuccessClass) + setTimeout(() => el.setAttribute('data-tooltip', oldText), timeoutIcon) +} + +// Changes the copy button icon for two seconds, then changes it back +const temporarilyChangeIcon = (el) => { + el.innerHTML = iconCheck; + setTimeout(() => {el.innerHTML = iconCopy}, timeoutIcon) +} + +const addCopyButtonToCodeCells = () => { + // If ClipboardJS hasn't loaded, wait a bit and try again. This + // happens because we load ClipboardJS asynchronously. + if (window.ClipboardJS === undefined) { + setTimeout(addCopyButtonToCodeCells, 250) + return + } + + // Add copybuttons to all of our code cells + const COPYBUTTON_SELECTOR = 'div.highlight pre'; + const codeCells = document.querySelectorAll(COPYBUTTON_SELECTOR) + codeCells.forEach((codeCell, index) => { + const id = codeCellId(index) + codeCell.setAttribute('id', id) + + const clipboardButton = id => + `` + codeCell.insertAdjacentHTML('afterend', clipboardButton(id)) + }) + +function escapeRegExp(string) { + return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string +} + +/** + * Removes excluded text from a Node. + * + * @param {Node} target Node to filter. + * @param {string} exclude CSS selector of nodes to exclude. + * @returns {DOMString} Text from `target` with text removed. + */ +function filterText(target, exclude) { + const clone = target.cloneNode(true); // clone as to not modify the live DOM + if (exclude) { + // remove excluded nodes + clone.querySelectorAll(exclude).forEach(node => node.remove()); + } + return clone.innerText; +} + +// Callback when a copy button is clicked. Will be passed the node that was clicked +// should then grab the text and replace pieces of text that shouldn't be used in output +function formatCopyText(textContent, copybuttonPromptText, isRegexp = false, onlyCopyPromptLines = true, removePrompts = true, copyEmptyLines = true, lineContinuationChar = "", hereDocDelim = "") { + var regexp; + var match; + + // Do we check for line continuation characters and "HERE-documents"? + var useLineCont = !!lineContinuationChar + var useHereDoc = !!hereDocDelim + + // create regexp to capture prompt and remaining line + if (isRegexp) { + regexp = new RegExp('^(' + copybuttonPromptText + ')(.*)') + } else { + regexp = new RegExp('^(' + escapeRegExp(copybuttonPromptText) + ')(.*)') + } + + const outputLines = []; + var promptFound = false; + var gotLineCont = false; + var gotHereDoc = false; + const lineGotPrompt = []; + for (const line of textContent.split('\n')) { + match = line.match(regexp) + if (match || gotLineCont || gotHereDoc) { + promptFound = regexp.test(line) + lineGotPrompt.push(promptFound) + if (removePrompts && promptFound) { + outputLines.push(match[2]) + } else { + outputLines.push(line) + } + gotLineCont = line.endsWith(lineContinuationChar) & useLineCont + if (line.includes(hereDocDelim) & useHereDoc) + gotHereDoc = !gotHereDoc + } else if (!onlyCopyPromptLines) { + outputLines.push(line) + } else if (copyEmptyLines && line.trim() === '') { + outputLines.push(line) + } + } + + // If no lines with the prompt were found then just use original lines + if (lineGotPrompt.some(v => v === true)) { + textContent = outputLines.join('\n'); + } + + // Remove a trailing newline to avoid auto-running when pasting + if (textContent.endsWith("\n")) { + textContent = textContent.slice(0, -1) + } + return textContent +} + + +var copyTargetText = (trigger) => { + var target = document.querySelector(trigger.attributes['data-clipboard-target'].value); + + // get filtered text + let exclude = '.linenos'; + + let text = filterText(target, exclude); + return formatCopyText(text, '', false, true, true, true, '', '') +} + + // Initialize with a callback so we can modify the text before copy + const clipboard = new ClipboardJS('.copybtn', {text: copyTargetText}) + + // Update UI with error/success messages + clipboard.on('success', event => { + clearSelection() + temporarilyChangeTooltip(event.trigger, messages[locale]['copy'], messages[locale]['copy_success']) + temporarilyChangeIcon(event.trigger) + }) + + clipboard.on('error', event => { + temporarilyChangeTooltip(event.trigger, messages[locale]['copy'], messages[locale]['copy_failure']) + }) +} + +runWhenDOMLoaded(addCopyButtonToCodeCells) \ No newline at end of file diff --git a/3.21.0-scylla/_static/copybutton_funcs.js b/3.21.0-scylla/_static/copybutton_funcs.js new file mode 100644 index 0000000000..dbe1aaad79 --- /dev/null +++ b/3.21.0-scylla/_static/copybutton_funcs.js @@ -0,0 +1,73 @@ +function escapeRegExp(string) { + return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string +} + +/** + * Removes excluded text from a Node. + * + * @param {Node} target Node to filter. + * @param {string} exclude CSS selector of nodes to exclude. + * @returns {DOMString} Text from `target` with text removed. + */ +export function filterText(target, exclude) { + const clone = target.cloneNode(true); // clone as to not modify the live DOM + if (exclude) { + // remove excluded nodes + clone.querySelectorAll(exclude).forEach(node => node.remove()); + } + return clone.innerText; +} + +// Callback when a copy button is clicked. Will be passed the node that was clicked +// should then grab the text and replace pieces of text that shouldn't be used in output +export function formatCopyText(textContent, copybuttonPromptText, isRegexp = false, onlyCopyPromptLines = true, removePrompts = true, copyEmptyLines = true, lineContinuationChar = "", hereDocDelim = "") { + var regexp; + var match; + + // Do we check for line continuation characters and "HERE-documents"? + var useLineCont = !!lineContinuationChar + var useHereDoc = !!hereDocDelim + + // create regexp to capture prompt and remaining line + if (isRegexp) { + regexp = new RegExp('^(' + copybuttonPromptText + ')(.*)') + } else { + regexp = new RegExp('^(' + escapeRegExp(copybuttonPromptText) + ')(.*)') + } + + const outputLines = []; + var promptFound = false; + var gotLineCont = false; + var gotHereDoc = false; + const lineGotPrompt = []; + for (const line of textContent.split('\n')) { + match = line.match(regexp) + if (match || gotLineCont || gotHereDoc) { + promptFound = regexp.test(line) + lineGotPrompt.push(promptFound) + if (removePrompts && promptFound) { + outputLines.push(match[2]) + } else { + outputLines.push(line) + } + gotLineCont = line.endsWith(lineContinuationChar) & useLineCont + if (line.includes(hereDocDelim) & useHereDoc) + gotHereDoc = !gotHereDoc + } else if (!onlyCopyPromptLines) { + outputLines.push(line) + } else if (copyEmptyLines && line.trim() === '') { + outputLines.push(line) + } + } + + // If no lines with the prompt were found then just use original lines + if (lineGotPrompt.some(v => v === true)) { + textContent = outputLines.join('\n'); + } + + // Remove a trailing newline to avoid auto-running when pasting + if (textContent.endsWith("\n")) { + textContent = textContent.slice(0, -1) + } + return textContent +} diff --git a/3.21.0-scylla/_static/css/main.css b/3.21.0-scylla/_static/css/main.css new file mode 100644 index 0000000000..4ac0174528 --- /dev/null +++ b/3.21.0-scylla/_static/css/main.css @@ -0,0 +1 @@ +@media print,screen and (min-width:40em){.reveal,.reveal.large,.reveal.small,.reveal.tiny{left:auto;margin:0 auto;right:auto}}/*! normalize.css v8.0.0 | MIT License | github.com/necolas/normalize.css */html{-webkit-text-size-adjust:100%;line-height:1.15}h1{font-size:2em;margin:.67em 0}hr{-webkit-box-sizing:content-box;box-sizing:content-box;overflow:visible}pre{font-family:monospace,monospace;font-size:1em}a{background-color:transparent}abbr[title]{border-bottom:0;-webkit-text-decoration:underline dotted;text-decoration:underline dotted}b,strong{font-weight:bolder}code,kbd,samp{font-family:monospace,monospace;font-size:1em}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}img{border-style:none}button,input,optgroup,select,textarea{font-size:100%;line-height:1.15;margin:0}button,input{overflow:visible}button,select{text-transform:none}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button}[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner,button::-moz-focus-inner{border-style:none;padding:0}[type=button]:-moz-focusring,[type=reset]:-moz-focusring,[type=submit]:-moz-focusring,button:-moz-focusring{outline:1px dotted ButtonText}fieldset{padding:.35em .75em .625em}legend{-webkit-box-sizing:border-box;box-sizing:border-box;color:inherit;display:table;padding:0;white-space:normal}progress{vertical-align:baseline}textarea{overflow:auto}[type=checkbox],[type=radio]{-webkit-box-sizing:border-box;box-sizing:border-box;padding:0}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}details{display:block}summary{display:list-item}template{display:none}[hidden]{display:none}[data-whatinput=mouse] *,[data-whatinput=mouse] :focus,[data-whatinput=touch] *,[data-whatinput=touch] :focus,[data-whatintent=mouse] *,[data-whatintent=mouse] :focus,[data-whatintent=touch] *,[data-whatintent=touch] :focus{outline:0}[draggable=false]{-webkit-touch-callout:none;-webkit-user-select:none}.foundation-mq{font-family:"small=0em&medium=40em&large=64em&xlarge=75em&xxlarge=90em"}html{-webkit-box-sizing:border-box;font-size:100%}*,:after,:before{-webkit-box-sizing:inherit}body{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;background:#fefefe;color:#0a0a0a;font-family:Helvetica Neue,Helvetica,Roboto,Arial,sans-serif;font-weight:400;line-height:1.5;margin:0;padding:0}img{-ms-interpolation-mode:bicubic;display:inline-block;height:auto;vertical-align:middle}textarea{border-radius:0;height:auto;min-height:50px}select{-webkit-box-sizing:border-box;box-sizing:border-box;width:100%}.map_canvas embed,.map_canvas img,.map_canvas object,.mqa-display embed,.mqa-display img,.mqa-display object{max-width:none!important}button{-webkit-appearance:none;-moz-appearance:none;appearance:none;background:0 0;border:0;border-radius:0;cursor:auto;line-height:1;padding:0}[data-whatinput=mouse] button{outline:0}pre{-webkit-overflow-scrolling:touch;overflow:auto}button,input,optgroup,select,textarea{font-family:inherit}.is-visible{display:block!important}.is-hidden{display:none!important}[type=color],[type=date],[type=datetime-local],[type=datetime],[type=email],[type=month],[type=number],[type=password],[type=search],[type=tel],[type=text],[type=time],[type=url],[type=week],textarea{-webkit-appearance:none;-moz-appearance:none;appearance:none;background-color:#fefefe;border:1px solid #cacaca;border-radius:0;-webkit-box-shadow:inset 0 1px 2px hsla(0,0%,4%,.1);box-shadow:inset 0 1px 2px hsla(0,0%,4%,.1);-webkit-box-sizing:border-box;box-sizing:border-box;color:#0a0a0a;display:block;font-family:inherit;font-size:1rem;font-weight:400;height:2.4375rem;line-height:1.5;margin:0 0 1rem;padding:.5rem;-webkit-transition:border-color .25s ease-in-out,-webkit-box-shadow .5s;transition:border-color .25s ease-in-out,-webkit-box-shadow .5s;transition:box-shadow .5s,border-color .25s ease-in-out;transition:box-shadow .5s,border-color .25s ease-in-out,-webkit-box-shadow .5s;width:100%}[type=color]:focus,[type=date]:focus,[type=datetime-local]:focus,[type=datetime]:focus,[type=email]:focus,[type=month]:focus,[type=number]:focus,[type=password]:focus,[type=search]:focus,[type=tel]:focus,[type=text]:focus,[type=time]:focus,[type=url]:focus,[type=week]:focus,textarea:focus{background-color:#fefefe;border:1px solid #8a8a8a;-webkit-box-shadow:0 0 5px #cacaca;box-shadow:0 0 5px #cacaca;outline:0;-webkit-transition:border-color .25s ease-in-out,-webkit-box-shadow .5s;transition:border-color .25s ease-in-out,-webkit-box-shadow .5s;transition:box-shadow .5s,border-color .25s ease-in-out;transition:box-shadow .5s,border-color .25s ease-in-out,-webkit-box-shadow .5s}textarea{max-width:100%}textarea[rows]{height:auto}input:disabled,input[readonly],textarea:disabled,textarea[readonly]{background-color:#e6e6e6;cursor:not-allowed}[type=button],[type=submit]{-webkit-appearance:none;-moz-appearance:none;appearance:none;border-radius:0}input[type=search]{-webkit-box-sizing:border-box;box-sizing:border-box}::-webkit-input-placeholder{color:#cacaca}::-moz-placeholder{color:#cacaca}:-ms-input-placeholder{color:#cacaca}::-ms-input-placeholder{color:#cacaca}::placeholder{color:#cacaca}[type=checkbox],[type=file],[type=radio]{margin:0 0 1rem}[type=checkbox]+label,[type=radio]+label{display:inline-block;margin-bottom:0;margin-left:.5rem;margin-right:1rem;vertical-align:baseline}[type=checkbox]+label[for],[type=radio]+label[for]{cursor:pointer}label>[type=checkbox],label>[type=radio]{margin-right:.5rem}[type=file]{width:100%}label{color:#0a0a0a;display:block;font-size:.875rem;font-weight:400;line-height:1.8;margin:0}label.middle{line-height:1.5;margin:0 0 1rem;padding:.5625rem 0}.help-text{color:#0a0a0a;font-size:.8125rem;font-style:italic;margin-top:-.5rem}.input-group{-webkit-box-align:stretch;-ms-flex-align:stretch;-webkit-align-items:stretch;align-items:stretch;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;margin-bottom:1rem;width:100%}.input-group>:first-child,.input-group>:first-child.input-group-button>*{border-radius:0}.input-group>:last-child,.input-group>:last-child.input-group-button>*{border-radius:0}.input-group-button,.input-group-button a,.input-group-button button,.input-group-button input,.input-group-button label,.input-group-field,.input-group-label{margin:0;white-space:nowrap}.input-group-label{-webkit-box-flex:0;-webkit-box-align:center;-ms-flex-align:center;-webkit-align-items:center;align-items:center;background:#e6e6e6;border:1px solid #cacaca;color:#0a0a0a;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto;padding:0 1rem;text-align:center;white-space:nowrap}.input-group-label:first-child{border-right:0}.input-group-label:last-child{border-left:0}.input-group-field{-webkit-box-flex:1;border-radius:0;-webkit-flex:1 1 0px;-ms-flex:1 1 0px;flex:1 1 0px;min-width:0}.input-group-button{-webkit-box-flex:0;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto;padding-bottom:0;padding-top:0;text-align:center}.input-group-button a,.input-group-button button,.input-group-button input,.input-group-button label{-ms-flex-item-align:stretch;-webkit-align-self:stretch;align-self:stretch;font-size:1rem;height:auto;padding-bottom:0;padding-top:0}fieldset{border:0;margin:0;padding:0}legend{margin-bottom:.5rem;max-width:100%}.fieldset{border:1px solid #cacaca;margin:1.125rem 0;padding:1.25rem}.fieldset legend{margin:0 0 0 -.1875rem;padding:0 .1875rem}select{-webkit-appearance:none;-moz-appearance:none;appearance:none;background-color:#fefefe;background-image:url('data:image/svg+xml;utf8,');background-origin:content-box;background-position:right -1rem center;background-repeat:no-repeat;background-size:9px 6px;border:1px solid #cacaca;border-radius:0;color:#0a0a0a;font-family:inherit;font-size:1rem;font-weight:400;height:2.4375rem;line-height:1.5;margin:0 0 1rem;padding:.5rem 1.5rem .5rem .5rem;-webkit-transition:border-color .25s ease-in-out,-webkit-box-shadow .5s;transition:border-color .25s ease-in-out,-webkit-box-shadow .5s;transition:box-shadow .5s,border-color .25s ease-in-out;transition:box-shadow .5s,border-color .25s ease-in-out,-webkit-box-shadow .5s}@media screen and (min-width:0\0){select{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAYCAYAAACbU/80AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAIpJREFUeNrEkckNgDAMBBfRkEt0ObRBBdsGXUDgmQfK4XhH2m8czQAAy27R3tsw4Qfe2x8uOO6oYLb6GlOor3GF+swURAOmUJ+RwtEJs9WvTGEYxBXqI1MQAZhCfUQKRzDMVj+TwrAIV6jvSUEkYAr1LSkcyTBb/V+KYfX7xAeusq3sLDtGH3kEGACPWIflNZfhRQAAAABJRU5ErkJggg==)}}select:focus{background-color:#fefefe;border:1px solid #8a8a8a;-webkit-box-shadow:0 0 5px #cacaca;box-shadow:0 0 5px #cacaca;outline:0;-webkit-transition:border-color .25s ease-in-out,-webkit-box-shadow .5s;transition:border-color .25s ease-in-out,-webkit-box-shadow .5s;transition:box-shadow .5s,border-color .25s ease-in-out;transition:box-shadow .5s,border-color .25s ease-in-out,-webkit-box-shadow .5s}select:disabled{background-color:#e6e6e6;cursor:not-allowed}select::-ms-expand{display:none}select[multiple]{background-image:none;height:auto}select:not([multiple]){padding-bottom:0;padding-top:0}.is-invalid-input:not(:focus){background-color:#f9ecea;border-color:#cc4b37}.is-invalid-input:not(:focus)::-webkit-input-placeholder{color:#cc4b37}.is-invalid-input:not(:focus)::-moz-placeholder{color:#cc4b37}.is-invalid-input:not(:focus):-ms-input-placeholder{color:#cc4b37}.is-invalid-input:not(:focus)::-ms-input-placeholder{color:#cc4b37}.is-invalid-input:not(:focus)::placeholder{color:#cc4b37}.form-error,.is-invalid-label{color:#cc4b37}.form-error{display:none;font-size:.75rem;font-weight:700;margin-bottom:1rem;margin-top:-.5rem}.form-error.is-visible{display:block}blockquote,dd,div,dl,dt,form,h1,h2,h3,h4,h5,h6,li,ol,p,pre,td,th,ul{margin:0;padding:0}p{text-rendering:optimizeLegibility;font-size:inherit;line-height:1.6;margin-bottom:1rem}em,i{font-style:italic}b,em,i,strong{line-height:inherit}b,strong{font-weight:700}small{font-size:80%;line-height:inherit}.h1,.h2,.h3,.h4,.h5,.h6,h1,h2,h3,h4,h5,h6{text-rendering:optimizeLegibility;color:inherit;font-family:Helvetica Neue,Helvetica,Roboto,Arial,sans-serif;font-style:normal;font-weight:400}.h1 small,.h2 small,.h3 small,.h4 small,.h5 small,.h6 small,h1 small,h2 small,h3 small,h4 small,h5 small,h6 small{color:#cacaca;line-height:0}.h1,h1{font-size:1.5rem}.h1,.h2,h1,h2{line-height:1.4;margin-bottom:.5rem;margin-top:0}.h2,h2{font-size:1.25rem}.h3,h3{font-size:1.1875rem}.h3,.h4,h3,h4{line-height:1.4;margin-bottom:.5rem;margin-top:0}.h4,h4{font-size:1.125rem}.h5,h5{font-size:1.0625rem}.h5,.h6,h5,h6{line-height:1.4;margin-bottom:.5rem;margin-top:0}.h6,h6{font-size:1rem}@media print,screen and (min-width:40em){.h1,h1{font-size:3rem}.h2,h2{font-size:2.5rem}.h3,h3{font-size:1.9375rem}.h4,h4{font-size:1.5625rem}.h5,h5{font-size:1.25rem}.h6,h6{font-size:1rem}}a{color:#1779ba;cursor:pointer;line-height:inherit;text-decoration:none}a:focus,a:hover{color:#1468a0}a img,hr{border:0}hr{border-bottom:1px solid #cacaca;clear:both;height:0;margin:1.25rem auto;max-width:75rem}dl,ol,ul{line-height:1.6;list-style-position:outside;margin-bottom:1rem}li{font-size:inherit}ul{list-style-type:disc}ol,ul{margin-left:1.25rem}ol ol,ol ul,ul ol,ul ul{margin-bottom:0;margin-left:1.25rem}dl{margin-bottom:1rem}dl dt{font-weight:700;margin-bottom:.3rem}blockquote{border-left:1px solid #cacaca;margin:0 0 1rem;padding:.5625rem 1.25rem 0 1.1875rem}blockquote,blockquote p{color:#8a8a8a;line-height:1.6}abbr,abbr[title]{border-bottom:1px dotted #0a0a0a;cursor:help;text-decoration:none}figure,kbd{margin:0}kbd{background-color:#e6e6e6;color:#0a0a0a;font-family:Consolas,Liberation Mono,Courier,monospace;padding:.125rem .25rem 0}.subheader{color:#8a8a8a;font-weight:400;line-height:1.4;margin-bottom:.5rem;margin-top:.2rem}.lead{font-size:125%;line-height:1.6}.stat{font-size:2.5rem;line-height:1}p+.stat{margin-top:-1rem}ol.no-bullet,ul.no-bullet{list-style:none;margin-left:0}.cite-block,cite{color:#8a8a8a;display:block;font-size:.8125rem}.cite-block:before,cite:before{content:"— "}.code-inline,code{word-wrap:break-word;display:inline;max-width:100%;padding:.125rem .3125rem .0625rem}.code-block,.code-inline,code{background-color:#e6e6e6;border:1px solid #cacaca;color:#0a0a0a;font-family:Consolas,Liberation Mono,Courier,monospace;font-weight:400}.code-block{display:block;margin-bottom:1.5rem;overflow:auto;padding:1rem;white-space:pre}.text-left{text-align:left}.text-right{text-align:right}.text-center{text-align:center}.text-justify{text-align:justify}@media print,screen and (min-width:40em){.medium-text-left{text-align:left}.medium-text-right{text-align:right}.medium-text-center{text-align:center}.medium-text-justify{text-align:justify}}@media print,screen and (min-width:64em){.large-text-left{text-align:left}.large-text-right{text-align:right}.large-text-center{text-align:center}.large-text-justify{text-align:justify}}.show-for-print{display:none!important}@media print{*{-webkit-print-color-adjust:economy;background:0 0!important;-webkit-box-shadow:none!important;box-shadow:none!important;color:#000!important;color-adjust:economy;text-shadow:none!important}.show-for-print{display:block!important}.hide-for-print{display:none!important}table.show-for-print{display:table!important}thead.show-for-print{display:table-header-group!important}tbody.show-for-print{display:table-row-group!important}tr.show-for-print{display:table-row!important}td.show-for-print,th.show-for-print{display:table-cell!important}a,a:visited{text-decoration:underline}a[href]:after{content:" (" attr(href) ")"}.ir a:after,a[href^="#"]:after,a[href^="javascript:"]:after{content:""}abbr[title]:after{content:" (" attr(title) ")"}blockquote,pre{border:1px solid #8a8a8a;page-break-inside:avoid}thead{display:table-header-group}img,tr{page-break-inside:avoid}img{max-width:100%!important}@page{margin:.5cm}h2,h3,p{orphans:3;widows:3}h2,h3{page-break-after:avoid}.print-break-inside{page-break-inside:auto}}.grid-container{margin-left:auto;margin-right:auto;max-width:75rem;padding-left:.625rem;padding-right:.625rem}@media print,screen and (min-width:40em){.grid-container{padding-left:.9375rem;padding-right:.9375rem}}.grid-container.fluid{margin-left:auto;margin-right:auto;max-width:100%;padding-left:.625rem;padding-right:.625rem}@media print,screen and (min-width:40em){.grid-container.fluid{padding-left:.9375rem;padding-right:.9375rem}}.grid-container.full{margin-left:auto;margin-right:auto;max-width:100%;padding-left:0;padding-right:0}.grid-x{-webkit-box-orient:horizontal;-webkit-box-direction:normal;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-flow:row wrap;-ms-flex-flow:row wrap;flex-flow:row wrap}.cell{-webkit-box-flex:0;-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto;min-height:0;min-width:0;width:100%}.cell.auto{-webkit-box-flex:1;-webkit-flex:1 1 0;-ms-flex:1 1 0px;flex:1 1 0}.cell.shrink{-webkit-box-flex:0;-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto}.grid-x>.auto{width:auto}.grid-x>.shrink{width:auto}.grid-x>.small-1,.grid-x>.small-2,.grid-x>.small-3,.grid-x>.small-4,.grid-x>.small-5,.grid-x>.small-6,.grid-x>.small-7,.grid-x>.small-8,.grid-x>.small-9,.grid-x>.small-10,.grid-x>.small-11,.grid-x>.small-12,.grid-x>.small-full,.grid-x>.small-shrink{-ms-flex-preferred-size:auto;-webkit-flex-basis:auto;flex-basis:auto}@media print,screen and (min-width:40em){.grid-x>.medium-1,.grid-x>.medium-2,.grid-x>.medium-3,.grid-x>.medium-4,.grid-x>.medium-5,.grid-x>.medium-6,.grid-x>.medium-7,.grid-x>.medium-8,.grid-x>.medium-9,.grid-x>.medium-10,.grid-x>.medium-11,.grid-x>.medium-12,.grid-x>.medium-full,.grid-x>.medium-shrink{-ms-flex-preferred-size:auto;-webkit-flex-basis:auto;flex-basis:auto}}@media print,screen and (min-width:64em){.grid-x>.large-1,.grid-x>.large-2,.grid-x>.large-3,.grid-x>.large-4,.grid-x>.large-5,.grid-x>.large-6,.grid-x>.large-7,.grid-x>.large-8,.grid-x>.large-9,.grid-x>.large-10,.grid-x>.large-11,.grid-x>.large-12,.grid-x>.large-full,.grid-x>.large-shrink{-ms-flex-preferred-size:auto;-webkit-flex-basis:auto;flex-basis:auto}}.grid-x>.small-1,.grid-x>.small-2,.grid-x>.small-3,.grid-x>.small-4,.grid-x>.small-5,.grid-x>.small-6,.grid-x>.small-7,.grid-x>.small-8,.grid-x>.small-9,.grid-x>.small-10,.grid-x>.small-11,.grid-x>.small-12{-webkit-box-flex:0;-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto}.grid-x>.small-1{width:8.33333%}.grid-x>.small-2{width:16.66667%}.grid-x>.small-3{width:25%}.grid-x>.small-4{width:33.33333%}.grid-x>.small-5{width:41.66667%}.grid-x>.small-6{width:50%}.grid-x>.small-7{width:58.33333%}.grid-x>.small-8{width:66.66667%}.grid-x>.small-9{width:75%}.grid-x>.small-10{width:83.33333%}.grid-x>.small-11{width:91.66667%}.grid-x>.small-12{width:100%}@media print,screen and (min-width:40em){.grid-x>.medium-auto{-webkit-box-flex:1;-webkit-flex:1 1 0;-ms-flex:1 1 0px;flex:1 1 0;width:auto}.grid-x>.medium-1,.grid-x>.medium-2,.grid-x>.medium-3,.grid-x>.medium-4,.grid-x>.medium-5,.grid-x>.medium-6,.grid-x>.medium-7,.grid-x>.medium-8,.grid-x>.medium-9,.grid-x>.medium-10,.grid-x>.medium-11,.grid-x>.medium-12,.grid-x>.medium-shrink{-webkit-box-flex:0;-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto}.grid-x>.medium-shrink{width:auto}.grid-x>.medium-1{width:8.33333%}.grid-x>.medium-2{width:16.66667%}.grid-x>.medium-3{width:25%}.grid-x>.medium-4{width:33.33333%}.grid-x>.medium-5{width:41.66667%}.grid-x>.medium-6{width:50%}.grid-x>.medium-7{width:58.33333%}.grid-x>.medium-8{width:66.66667%}.grid-x>.medium-9{width:75%}.grid-x>.medium-10{width:83.33333%}.grid-x>.medium-11{width:91.66667%}.grid-x>.medium-12{width:100%}}@media print,screen and (min-width:64em){.grid-x>.large-auto{-webkit-box-flex:1;-webkit-flex:1 1 0;-ms-flex:1 1 0px;flex:1 1 0;width:auto}.grid-x>.large-1,.grid-x>.large-2,.grid-x>.large-3,.grid-x>.large-4,.grid-x>.large-5,.grid-x>.large-6,.grid-x>.large-7,.grid-x>.large-8,.grid-x>.large-9,.grid-x>.large-10,.grid-x>.large-11,.grid-x>.large-12,.grid-x>.large-shrink{-webkit-box-flex:0;-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto}.grid-x>.large-shrink{width:auto}.grid-x>.large-1{width:8.33333%}.grid-x>.large-2{width:16.66667%}.grid-x>.large-3{width:25%}.grid-x>.large-4{width:33.33333%}.grid-x>.large-5{width:41.66667%}.grid-x>.large-6{width:50%}.grid-x>.large-7{width:58.33333%}.grid-x>.large-8{width:66.66667%}.grid-x>.large-9{width:75%}.grid-x>.large-10{width:83.33333%}.grid-x>.large-11{width:91.66667%}.grid-x>.large-12{width:100%}}.grid-margin-x:not(.grid-x)>.cell{width:auto}.grid-margin-y:not(.grid-y)>.cell{height:auto}.grid-margin-x{margin-left:-.625rem;margin-right:-.625rem}@media print,screen and (min-width:40em){.grid-margin-x{margin-left:-.9375rem;margin-right:-.9375rem}}.grid-margin-x>.cell{margin-left:.625rem;margin-right:.625rem;width:calc(100% - 1.25rem)}@media print,screen and (min-width:40em){.grid-margin-x>.cell{margin-left:.9375rem;margin-right:.9375rem;width:calc(100% - 1.875rem)}}.grid-margin-x>.auto{width:auto}.grid-margin-x>.shrink{width:auto}.grid-margin-x>.small-1{width:calc(8.33333% - 1.25rem)}.grid-margin-x>.small-2{width:calc(16.66667% - 1.25rem)}.grid-margin-x>.small-3{width:calc(25% - 1.25rem)}.grid-margin-x>.small-4{width:calc(33.33333% - 1.25rem)}.grid-margin-x>.small-5{width:calc(41.66667% - 1.25rem)}.grid-margin-x>.small-6{width:calc(50% - 1.25rem)}.grid-margin-x>.small-7{width:calc(58.33333% - 1.25rem)}.grid-margin-x>.small-8{width:calc(66.66667% - 1.25rem)}.grid-margin-x>.small-9{width:calc(75% - 1.25rem)}.grid-margin-x>.small-10{width:calc(83.33333% - 1.25rem)}.grid-margin-x>.small-11{width:calc(91.66667% - 1.25rem)}.grid-margin-x>.small-12{width:calc(100% - 1.25rem)}@media print,screen and (min-width:40em){.grid-margin-x>.auto{width:auto}.grid-margin-x>.shrink{width:auto}.grid-margin-x>.small-1{width:calc(8.33333% - 1.875rem)}.grid-margin-x>.small-2{width:calc(16.66667% - 1.875rem)}.grid-margin-x>.small-3{width:calc(25% - 1.875rem)}.grid-margin-x>.small-4{width:calc(33.33333% - 1.875rem)}.grid-margin-x>.small-5{width:calc(41.66667% - 1.875rem)}.grid-margin-x>.small-6{width:calc(50% - 1.875rem)}.grid-margin-x>.small-7{width:calc(58.33333% - 1.875rem)}.grid-margin-x>.small-8{width:calc(66.66667% - 1.875rem)}.grid-margin-x>.small-9{width:calc(75% - 1.875rem)}.grid-margin-x>.small-10{width:calc(83.33333% - 1.875rem)}.grid-margin-x>.small-11{width:calc(91.66667% - 1.875rem)}.grid-margin-x>.small-12{width:calc(100% - 1.875rem)}.grid-margin-x>.medium-auto{width:auto}.grid-margin-x>.medium-shrink{width:auto}.grid-margin-x>.medium-1{width:calc(8.33333% - 1.875rem)}.grid-margin-x>.medium-2{width:calc(16.66667% - 1.875rem)}.grid-margin-x>.medium-3{width:calc(25% - 1.875rem)}.grid-margin-x>.medium-4{width:calc(33.33333% - 1.875rem)}.grid-margin-x>.medium-5{width:calc(41.66667% - 1.875rem)}.grid-margin-x>.medium-6{width:calc(50% - 1.875rem)}.grid-margin-x>.medium-7{width:calc(58.33333% - 1.875rem)}.grid-margin-x>.medium-8{width:calc(66.66667% - 1.875rem)}.grid-margin-x>.medium-9{width:calc(75% - 1.875rem)}.grid-margin-x>.medium-10{width:calc(83.33333% - 1.875rem)}.grid-margin-x>.medium-11{width:calc(91.66667% - 1.875rem)}.grid-margin-x>.medium-12{width:calc(100% - 1.875rem)}}@media print,screen and (min-width:64em){.grid-margin-x>.large-auto{width:auto}.grid-margin-x>.large-shrink{width:auto}.grid-margin-x>.large-1{width:calc(8.33333% - 1.875rem)}.grid-margin-x>.large-2{width:calc(16.66667% - 1.875rem)}.grid-margin-x>.large-3{width:calc(25% - 1.875rem)}.grid-margin-x>.large-4{width:calc(33.33333% - 1.875rem)}.grid-margin-x>.large-5{width:calc(41.66667% - 1.875rem)}.grid-margin-x>.large-6{width:calc(50% - 1.875rem)}.grid-margin-x>.large-7{width:calc(58.33333% - 1.875rem)}.grid-margin-x>.large-8{width:calc(66.66667% - 1.875rem)}.grid-margin-x>.large-9{width:calc(75% - 1.875rem)}.grid-margin-x>.large-10{width:calc(83.33333% - 1.875rem)}.grid-margin-x>.large-11{width:calc(91.66667% - 1.875rem)}.grid-margin-x>.large-12{width:calc(100% - 1.875rem)}}.grid-padding-x .grid-padding-x{margin-left:-.625rem;margin-right:-.625rem}@media print,screen and (min-width:40em){.grid-padding-x .grid-padding-x{margin-left:-.9375rem;margin-right:-.9375rem}}.grid-container:not(.full)>.grid-padding-x{margin-left:-.625rem;margin-right:-.625rem}@media print,screen and (min-width:40em){.grid-container:not(.full)>.grid-padding-x{margin-left:-.9375rem;margin-right:-.9375rem}}.grid-padding-x>.cell{padding-left:.625rem;padding-right:.625rem}@media print,screen and (min-width:40em){.grid-padding-x>.cell{padding-left:.9375rem;padding-right:.9375rem}}.small-up-1>.cell{width:100%}.small-up-2>.cell{width:50%}.small-up-3>.cell{width:33.33333%}.small-up-4>.cell{width:25%}.small-up-5>.cell{width:20%}.small-up-6>.cell{width:16.66667%}.small-up-7>.cell{width:14.28571%}.small-up-8>.cell{width:12.5%}@media print,screen and (min-width:40em){.medium-up-1>.cell{width:100%}.medium-up-2>.cell{width:50%}.medium-up-3>.cell{width:33.33333%}.medium-up-4>.cell{width:25%}.medium-up-5>.cell{width:20%}.medium-up-6>.cell{width:16.66667%}.medium-up-7>.cell{width:14.28571%}.medium-up-8>.cell{width:12.5%}}@media print,screen and (min-width:64em){.large-up-1>.cell{width:100%}.large-up-2>.cell{width:50%}.large-up-3>.cell{width:33.33333%}.large-up-4>.cell{width:25%}.large-up-5>.cell{width:20%}.large-up-6>.cell{width:16.66667%}.large-up-7>.cell{width:14.28571%}.large-up-8>.cell{width:12.5%}}.grid-margin-x.small-up-1>.cell{width:calc(100% - 1.25rem)}.grid-margin-x.small-up-2>.cell{width:calc(50% - 1.25rem)}.grid-margin-x.small-up-3>.cell{width:calc(33.33333% - 1.25rem)}.grid-margin-x.small-up-4>.cell{width:calc(25% - 1.25rem)}.grid-margin-x.small-up-5>.cell{width:calc(20% - 1.25rem)}.grid-margin-x.small-up-6>.cell{width:calc(16.66667% - 1.25rem)}.grid-margin-x.small-up-7>.cell{width:calc(14.28571% - 1.25rem)}.grid-margin-x.small-up-8>.cell{width:calc(12.5% - 1.25rem)}@media print,screen and (min-width:40em){.grid-margin-x.small-up-1>.cell{width:calc(100% - 1.875rem)}.grid-margin-x.small-up-2>.cell{width:calc(50% - 1.875rem)}.grid-margin-x.small-up-3>.cell{width:calc(33.33333% - 1.875rem)}.grid-margin-x.small-up-4>.cell{width:calc(25% - 1.875rem)}.grid-margin-x.small-up-5>.cell{width:calc(20% - 1.875rem)}.grid-margin-x.small-up-6>.cell{width:calc(16.66667% - 1.875rem)}.grid-margin-x.small-up-7>.cell{width:calc(14.28571% - 1.875rem)}.grid-margin-x.small-up-8>.cell{width:calc(12.5% - 1.875rem)}.grid-margin-x.medium-up-1>.cell{width:calc(100% - 1.875rem)}.grid-margin-x.medium-up-2>.cell{width:calc(50% - 1.875rem)}.grid-margin-x.medium-up-3>.cell{width:calc(33.33333% - 1.875rem)}.grid-margin-x.medium-up-4>.cell{width:calc(25% - 1.875rem)}.grid-margin-x.medium-up-5>.cell{width:calc(20% - 1.875rem)}.grid-margin-x.medium-up-6>.cell{width:calc(16.66667% - 1.875rem)}.grid-margin-x.medium-up-7>.cell{width:calc(14.28571% - 1.875rem)}.grid-margin-x.medium-up-8>.cell{width:calc(12.5% - 1.875rem)}}@media print,screen and (min-width:64em){.grid-margin-x.large-up-1>.cell{width:calc(100% - 1.875rem)}.grid-margin-x.large-up-2>.cell{width:calc(50% - 1.875rem)}.grid-margin-x.large-up-3>.cell{width:calc(33.33333% - 1.875rem)}.grid-margin-x.large-up-4>.cell{width:calc(25% - 1.875rem)}.grid-margin-x.large-up-5>.cell{width:calc(20% - 1.875rem)}.grid-margin-x.large-up-6>.cell{width:calc(16.66667% - 1.875rem)}.grid-margin-x.large-up-7>.cell{width:calc(14.28571% - 1.875rem)}.grid-margin-x.large-up-8>.cell{width:calc(12.5% - 1.875rem)}}.small-margin-collapse{margin-left:0;margin-right:0}.small-margin-collapse>.cell{margin-left:0;margin-right:0}.small-margin-collapse>.small-1{width:8.33333%}.small-margin-collapse>.small-2{width:16.66667%}.small-margin-collapse>.small-3{width:25%}.small-margin-collapse>.small-4{width:33.33333%}.small-margin-collapse>.small-5{width:41.66667%}.small-margin-collapse>.small-6{width:50%}.small-margin-collapse>.small-7{width:58.33333%}.small-margin-collapse>.small-8{width:66.66667%}.small-margin-collapse>.small-9{width:75%}.small-margin-collapse>.small-10{width:83.33333%}.small-margin-collapse>.small-11{width:91.66667%}.small-margin-collapse>.small-12{width:100%}@media print,screen and (min-width:40em){.small-margin-collapse>.medium-1{width:8.33333%}.small-margin-collapse>.medium-2{width:16.66667%}.small-margin-collapse>.medium-3{width:25%}.small-margin-collapse>.medium-4{width:33.33333%}.small-margin-collapse>.medium-5{width:41.66667%}.small-margin-collapse>.medium-6{width:50%}.small-margin-collapse>.medium-7{width:58.33333%}.small-margin-collapse>.medium-8{width:66.66667%}.small-margin-collapse>.medium-9{width:75%}.small-margin-collapse>.medium-10{width:83.33333%}.small-margin-collapse>.medium-11{width:91.66667%}.small-margin-collapse>.medium-12{width:100%}}@media print,screen and (min-width:64em){.small-margin-collapse>.large-1{width:8.33333%}.small-margin-collapse>.large-2{width:16.66667%}.small-margin-collapse>.large-3{width:25%}.small-margin-collapse>.large-4{width:33.33333%}.small-margin-collapse>.large-5{width:41.66667%}.small-margin-collapse>.large-6{width:50%}.small-margin-collapse>.large-7{width:58.33333%}.small-margin-collapse>.large-8{width:66.66667%}.small-margin-collapse>.large-9{width:75%}.small-margin-collapse>.large-10{width:83.33333%}.small-margin-collapse>.large-11{width:91.66667%}.small-margin-collapse>.large-12{width:100%}}.small-padding-collapse{margin-left:0;margin-right:0}.small-padding-collapse>.cell{padding-left:0;padding-right:0}@media print,screen and (min-width:40em){.medium-margin-collapse{margin-left:0;margin-right:0}.medium-margin-collapse>.cell{margin-left:0;margin-right:0}}@media print,screen and (min-width:40em){.medium-margin-collapse>.small-1{width:8.33333%}.medium-margin-collapse>.small-2{width:16.66667%}.medium-margin-collapse>.small-3{width:25%}.medium-margin-collapse>.small-4{width:33.33333%}.medium-margin-collapse>.small-5{width:41.66667%}.medium-margin-collapse>.small-6{width:50%}.medium-margin-collapse>.small-7{width:58.33333%}.medium-margin-collapse>.small-8{width:66.66667%}.medium-margin-collapse>.small-9{width:75%}.medium-margin-collapse>.small-10{width:83.33333%}.medium-margin-collapse>.small-11{width:91.66667%}.medium-margin-collapse>.small-12{width:100%}}@media print,screen and (min-width:40em){.medium-margin-collapse>.medium-1{width:8.33333%}.medium-margin-collapse>.medium-2{width:16.66667%}.medium-margin-collapse>.medium-3{width:25%}.medium-margin-collapse>.medium-4{width:33.33333%}.medium-margin-collapse>.medium-5{width:41.66667%}.medium-margin-collapse>.medium-6{width:50%}.medium-margin-collapse>.medium-7{width:58.33333%}.medium-margin-collapse>.medium-8{width:66.66667%}.medium-margin-collapse>.medium-9{width:75%}.medium-margin-collapse>.medium-10{width:83.33333%}.medium-margin-collapse>.medium-11{width:91.66667%}.medium-margin-collapse>.medium-12{width:100%}}@media print,screen and (min-width:64em){.medium-margin-collapse>.large-1{width:8.33333%}.medium-margin-collapse>.large-2{width:16.66667%}.medium-margin-collapse>.large-3{width:25%}.medium-margin-collapse>.large-4{width:33.33333%}.medium-margin-collapse>.large-5{width:41.66667%}.medium-margin-collapse>.large-6{width:50%}.medium-margin-collapse>.large-7{width:58.33333%}.medium-margin-collapse>.large-8{width:66.66667%}.medium-margin-collapse>.large-9{width:75%}.medium-margin-collapse>.large-10{width:83.33333%}.medium-margin-collapse>.large-11{width:91.66667%}.medium-margin-collapse>.large-12{width:100%}}@media print,screen and (min-width:40em){.medium-padding-collapse{margin-left:0;margin-right:0}.medium-padding-collapse>.cell{padding-left:0;padding-right:0}}@media print,screen and (min-width:64em){.large-margin-collapse{margin-left:0;margin-right:0}.large-margin-collapse>.cell{margin-left:0;margin-right:0}}@media print,screen and (min-width:64em){.large-margin-collapse>.small-1{width:8.33333%}.large-margin-collapse>.small-2{width:16.66667%}.large-margin-collapse>.small-3{width:25%}.large-margin-collapse>.small-4{width:33.33333%}.large-margin-collapse>.small-5{width:41.66667%}.large-margin-collapse>.small-6{width:50%}.large-margin-collapse>.small-7{width:58.33333%}.large-margin-collapse>.small-8{width:66.66667%}.large-margin-collapse>.small-9{width:75%}.large-margin-collapse>.small-10{width:83.33333%}.large-margin-collapse>.small-11{width:91.66667%}.large-margin-collapse>.small-12{width:100%}}@media print,screen and (min-width:64em){.large-margin-collapse>.medium-1{width:8.33333%}.large-margin-collapse>.medium-2{width:16.66667%}.large-margin-collapse>.medium-3{width:25%}.large-margin-collapse>.medium-4{width:33.33333%}.large-margin-collapse>.medium-5{width:41.66667%}.large-margin-collapse>.medium-6{width:50%}.large-margin-collapse>.medium-7{width:58.33333%}.large-margin-collapse>.medium-8{width:66.66667%}.large-margin-collapse>.medium-9{width:75%}.large-margin-collapse>.medium-10{width:83.33333%}.large-margin-collapse>.medium-11{width:91.66667%}.large-margin-collapse>.medium-12{width:100%}}@media print,screen and (min-width:64em){.large-margin-collapse>.large-1{width:8.33333%}.large-margin-collapse>.large-2{width:16.66667%}.large-margin-collapse>.large-3{width:25%}.large-margin-collapse>.large-4{width:33.33333%}.large-margin-collapse>.large-5{width:41.66667%}.large-margin-collapse>.large-6{width:50%}.large-margin-collapse>.large-7{width:58.33333%}.large-margin-collapse>.large-8{width:66.66667%}.large-margin-collapse>.large-9{width:75%}.large-margin-collapse>.large-10{width:83.33333%}.large-margin-collapse>.large-11{width:91.66667%}.large-margin-collapse>.large-12{width:100%}}@media print,screen and (min-width:64em){.large-padding-collapse{margin-left:0;margin-right:0}.large-padding-collapse>.cell{padding-left:0;padding-right:0}}.small-offset-0{margin-left:0}.grid-margin-x>.small-offset-0{margin-left:.625rem}.small-offset-1{margin-left:8.33333%}.grid-margin-x>.small-offset-1{margin-left:calc(8.33333% + .625rem)}.small-offset-2{margin-left:16.66667%}.grid-margin-x>.small-offset-2{margin-left:calc(16.66667% + .625rem)}.small-offset-3{margin-left:25%}.grid-margin-x>.small-offset-3{margin-left:calc(25% + .625rem)}.small-offset-4{margin-left:33.33333%}.grid-margin-x>.small-offset-4{margin-left:calc(33.33333% + .625rem)}.small-offset-5{margin-left:41.66667%}.grid-margin-x>.small-offset-5{margin-left:calc(41.66667% + .625rem)}.small-offset-6{margin-left:50%}.grid-margin-x>.small-offset-6{margin-left:calc(50% + .625rem)}.small-offset-7{margin-left:58.33333%}.grid-margin-x>.small-offset-7{margin-left:calc(58.33333% + .625rem)}.small-offset-8{margin-left:66.66667%}.grid-margin-x>.small-offset-8{margin-left:calc(66.66667% + .625rem)}.small-offset-9{margin-left:75%}.grid-margin-x>.small-offset-9{margin-left:calc(75% + .625rem)}.small-offset-10{margin-left:83.33333%}.grid-margin-x>.small-offset-10{margin-left:calc(83.33333% + .625rem)}.small-offset-11{margin-left:91.66667%}.grid-margin-x>.small-offset-11{margin-left:calc(91.66667% + .625rem)}@media print,screen and (min-width:40em){.medium-offset-0{margin-left:0}.grid-margin-x>.medium-offset-0{margin-left:.9375rem}.medium-offset-1{margin-left:8.33333%}.grid-margin-x>.medium-offset-1{margin-left:calc(8.33333% + .9375rem)}.medium-offset-2{margin-left:16.66667%}.grid-margin-x>.medium-offset-2{margin-left:calc(16.66667% + .9375rem)}.medium-offset-3{margin-left:25%}.grid-margin-x>.medium-offset-3{margin-left:calc(25% + .9375rem)}.medium-offset-4{margin-left:33.33333%}.grid-margin-x>.medium-offset-4{margin-left:calc(33.33333% + .9375rem)}.medium-offset-5{margin-left:41.66667%}.grid-margin-x>.medium-offset-5{margin-left:calc(41.66667% + .9375rem)}.medium-offset-6{margin-left:50%}.grid-margin-x>.medium-offset-6{margin-left:calc(50% + .9375rem)}.medium-offset-7{margin-left:58.33333%}.grid-margin-x>.medium-offset-7{margin-left:calc(58.33333% + .9375rem)}.medium-offset-8{margin-left:66.66667%}.grid-margin-x>.medium-offset-8{margin-left:calc(66.66667% + .9375rem)}.medium-offset-9{margin-left:75%}.grid-margin-x>.medium-offset-9{margin-left:calc(75% + .9375rem)}.medium-offset-10{margin-left:83.33333%}.grid-margin-x>.medium-offset-10{margin-left:calc(83.33333% + .9375rem)}.medium-offset-11{margin-left:91.66667%}.grid-margin-x>.medium-offset-11{margin-left:calc(91.66667% + .9375rem)}}@media print,screen and (min-width:64em){.large-offset-0{margin-left:0}.grid-margin-x>.large-offset-0{margin-left:.9375rem}.large-offset-1{margin-left:8.33333%}.grid-margin-x>.large-offset-1{margin-left:calc(8.33333% + .9375rem)}.large-offset-2{margin-left:16.66667%}.grid-margin-x>.large-offset-2{margin-left:calc(16.66667% + .9375rem)}.large-offset-3{margin-left:25%}.grid-margin-x>.large-offset-3{margin-left:calc(25% + .9375rem)}.large-offset-4{margin-left:33.33333%}.grid-margin-x>.large-offset-4{margin-left:calc(33.33333% + .9375rem)}.large-offset-5{margin-left:41.66667%}.grid-margin-x>.large-offset-5{margin-left:calc(41.66667% + .9375rem)}.large-offset-6{margin-left:50%}.grid-margin-x>.large-offset-6{margin-left:calc(50% + .9375rem)}.large-offset-7{margin-left:58.33333%}.grid-margin-x>.large-offset-7{margin-left:calc(58.33333% + .9375rem)}.large-offset-8{margin-left:66.66667%}.grid-margin-x>.large-offset-8{margin-left:calc(66.66667% + .9375rem)}.large-offset-9{margin-left:75%}.grid-margin-x>.large-offset-9{margin-left:calc(75% + .9375rem)}.large-offset-10{margin-left:83.33333%}.grid-margin-x>.large-offset-10{margin-left:calc(83.33333% + .9375rem)}.large-offset-11{margin-left:91.66667%}.grid-margin-x>.large-offset-11{margin-left:calc(91.66667% + .9375rem)}}.grid-y{-webkit-box-orient:vertical;-webkit-box-direction:normal;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-flow:column nowrap;-ms-flex-flow:column nowrap;flex-flow:column nowrap}.grid-y>.cell{height:auto;max-height:none}.grid-y>.auto{height:auto}.grid-y>.shrink{height:auto}.grid-y>.small-1,.grid-y>.small-2,.grid-y>.small-3,.grid-y>.small-4,.grid-y>.small-5,.grid-y>.small-6,.grid-y>.small-7,.grid-y>.small-8,.grid-y>.small-9,.grid-y>.small-10,.grid-y>.small-11,.grid-y>.small-12,.grid-y>.small-full,.grid-y>.small-shrink{-ms-flex-preferred-size:auto;-webkit-flex-basis:auto;flex-basis:auto}@media print,screen and (min-width:40em){.grid-y>.medium-1,.grid-y>.medium-2,.grid-y>.medium-3,.grid-y>.medium-4,.grid-y>.medium-5,.grid-y>.medium-6,.grid-y>.medium-7,.grid-y>.medium-8,.grid-y>.medium-9,.grid-y>.medium-10,.grid-y>.medium-11,.grid-y>.medium-12,.grid-y>.medium-full,.grid-y>.medium-shrink{-ms-flex-preferred-size:auto;-webkit-flex-basis:auto;flex-basis:auto}}@media print,screen and (min-width:64em){.grid-y>.large-1,.grid-y>.large-2,.grid-y>.large-3,.grid-y>.large-4,.grid-y>.large-5,.grid-y>.large-6,.grid-y>.large-7,.grid-y>.large-8,.grid-y>.large-9,.grid-y>.large-10,.grid-y>.large-11,.grid-y>.large-12,.grid-y>.large-full,.grid-y>.large-shrink{-ms-flex-preferred-size:auto;-webkit-flex-basis:auto;flex-basis:auto}}.grid-y>.small-1,.grid-y>.small-2,.grid-y>.small-3,.grid-y>.small-4,.grid-y>.small-5,.grid-y>.small-6,.grid-y>.small-7,.grid-y>.small-8,.grid-y>.small-9,.grid-y>.small-10,.grid-y>.small-11,.grid-y>.small-12{-webkit-box-flex:0;-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto}.grid-y>.small-1{height:8.33333%}.grid-y>.small-2{height:16.66667%}.grid-y>.small-3{height:25%}.grid-y>.small-4{height:33.33333%}.grid-y>.small-5{height:41.66667%}.grid-y>.small-6{height:50%}.grid-y>.small-7{height:58.33333%}.grid-y>.small-8{height:66.66667%}.grid-y>.small-9{height:75%}.grid-y>.small-10{height:83.33333%}.grid-y>.small-11{height:91.66667%}.grid-y>.small-12{height:100%}@media print,screen and (min-width:40em){.grid-y>.medium-auto{-webkit-box-flex:1;-webkit-flex:1 1 0;-ms-flex:1 1 0px;flex:1 1 0;height:auto}.grid-y>.medium-1,.grid-y>.medium-2,.grid-y>.medium-3,.grid-y>.medium-4,.grid-y>.medium-5,.grid-y>.medium-6,.grid-y>.medium-7,.grid-y>.medium-8,.grid-y>.medium-9,.grid-y>.medium-10,.grid-y>.medium-11,.grid-y>.medium-12,.grid-y>.medium-shrink{-webkit-box-flex:0;-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto}.grid-y>.medium-shrink{height:auto}.grid-y>.medium-1{height:8.33333%}.grid-y>.medium-2{height:16.66667%}.grid-y>.medium-3{height:25%}.grid-y>.medium-4{height:33.33333%}.grid-y>.medium-5{height:41.66667%}.grid-y>.medium-6{height:50%}.grid-y>.medium-7{height:58.33333%}.grid-y>.medium-8{height:66.66667%}.grid-y>.medium-9{height:75%}.grid-y>.medium-10{height:83.33333%}.grid-y>.medium-11{height:91.66667%}.grid-y>.medium-12{height:100%}}@media print,screen and (min-width:64em){.grid-y>.large-auto{-webkit-box-flex:1;-webkit-flex:1 1 0;-ms-flex:1 1 0px;flex:1 1 0;height:auto}.grid-y>.large-1,.grid-y>.large-2,.grid-y>.large-3,.grid-y>.large-4,.grid-y>.large-5,.grid-y>.large-6,.grid-y>.large-7,.grid-y>.large-8,.grid-y>.large-9,.grid-y>.large-10,.grid-y>.large-11,.grid-y>.large-12,.grid-y>.large-shrink{-webkit-box-flex:0;-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto}.grid-y>.large-shrink{height:auto}.grid-y>.large-1{height:8.33333%}.grid-y>.large-2{height:16.66667%}.grid-y>.large-3{height:25%}.grid-y>.large-4{height:33.33333%}.grid-y>.large-5{height:41.66667%}.grid-y>.large-6{height:50%}.grid-y>.large-7{height:58.33333%}.grid-y>.large-8{height:66.66667%}.grid-y>.large-9{height:75%}.grid-y>.large-10{height:83.33333%}.grid-y>.large-11{height:91.66667%}.grid-y>.large-12{height:100%}}.grid-padding-y .grid-padding-y{margin-bottom:-.625rem;margin-top:-.625rem}@media print,screen and (min-width:40em){.grid-padding-y .grid-padding-y{margin-bottom:-.9375rem;margin-top:-.9375rem}}.grid-padding-y>.cell{padding-bottom:.625rem;padding-top:.625rem}@media print,screen and (min-width:40em){.grid-padding-y>.cell{padding-bottom:.9375rem;padding-top:.9375rem}}.grid-frame{-webkit-box-align:stretch;-ms-flex-align:stretch;-webkit-align-items:stretch;align-items:stretch;-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap;overflow:hidden;position:relative;width:100vw}.cell .grid-frame{width:100%}.cell-block{max-width:100%;overflow-x:auto}.cell-block,.cell-block-y{-webkit-overflow-scrolling:touch;-ms-overflow-style:-ms-autohiding-scrollbar}.cell-block-y{max-height:100%;min-height:100%;overflow-y:auto}.cell-block-container{-webkit-box-orient:vertical;-webkit-box-direction:normal;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;max-height:100%}.cell-block-container>.grid-x{-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap;max-height:100%}@media print,screen and (min-width:40em){.medium-grid-frame{-webkit-box-align:stretch;-ms-flex-align:stretch;-webkit-align-items:stretch;align-items:stretch;-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap;overflow:hidden;position:relative;width:100vw}.cell .medium-grid-frame{width:100%}.medium-cell-block{-webkit-overflow-scrolling:touch;-ms-overflow-style:-ms-autohiding-scrollbar;max-width:100%;overflow-x:auto}.medium-cell-block-container{-webkit-box-orient:vertical;-webkit-box-direction:normal;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;max-height:100%}.medium-cell-block-container>.grid-x{-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap;max-height:100%}.medium-cell-block-y{-webkit-overflow-scrolling:touch;-ms-overflow-style:-ms-autohiding-scrollbar;max-height:100%;min-height:100%;overflow-y:auto}}@media print,screen and (min-width:64em){.large-grid-frame{-webkit-box-align:stretch;-ms-flex-align:stretch;-webkit-align-items:stretch;align-items:stretch;-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap;overflow:hidden;position:relative;width:100vw}.cell .large-grid-frame{width:100%}.large-cell-block{-webkit-overflow-scrolling:touch;-ms-overflow-style:-ms-autohiding-scrollbar;max-width:100%;overflow-x:auto}.large-cell-block-container{-webkit-box-orient:vertical;-webkit-box-direction:normal;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;max-height:100%}.large-cell-block-container>.grid-x{-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap;max-height:100%}.large-cell-block-y{-webkit-overflow-scrolling:touch;-ms-overflow-style:-ms-autohiding-scrollbar;max-height:100%;min-height:100%;overflow-y:auto}}.grid-y.grid-frame{-webkit-box-align:stretch;-ms-flex-align:stretch;-webkit-align-items:stretch;align-items:stretch;-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap;height:100vh;overflow:hidden;position:relative;width:auto}@media print,screen and (min-width:40em){.grid-y.medium-grid-frame{-webkit-box-align:stretch;-ms-flex-align:stretch;-webkit-align-items:stretch;align-items:stretch;-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap;height:100vh;overflow:hidden;position:relative;width:auto}}@media print,screen and (min-width:64em){.grid-y.large-grid-frame{-webkit-box-align:stretch;-ms-flex-align:stretch;-webkit-align-items:stretch;align-items:stretch;-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap;height:100vh;overflow:hidden;position:relative;width:auto}}.cell .grid-y.grid-frame{height:100%}@media print,screen and (min-width:40em){.cell .grid-y.medium-grid-frame{height:100%}}@media print,screen and (min-width:64em){.cell .grid-y.large-grid-frame{height:100%}}.grid-margin-y{margin-bottom:-.625rem;margin-top:-.625rem}@media print,screen and (min-width:40em){.grid-margin-y{margin-bottom:-.9375rem;margin-top:-.9375rem}}.grid-margin-y>.cell{height:calc(100% - 1.25rem);margin-bottom:.625rem;margin-top:.625rem}@media print,screen and (min-width:40em){.grid-margin-y>.cell{height:calc(100% - 1.875rem);margin-bottom:.9375rem;margin-top:.9375rem}}.grid-margin-y>.auto{height:auto}.grid-margin-y>.shrink{height:auto}.grid-margin-y>.small-1{height:calc(8.33333% - 1.25rem)}.grid-margin-y>.small-2{height:calc(16.66667% - 1.25rem)}.grid-margin-y>.small-3{height:calc(25% - 1.25rem)}.grid-margin-y>.small-4{height:calc(33.33333% - 1.25rem)}.grid-margin-y>.small-5{height:calc(41.66667% - 1.25rem)}.grid-margin-y>.small-6{height:calc(50% - 1.25rem)}.grid-margin-y>.small-7{height:calc(58.33333% - 1.25rem)}.grid-margin-y>.small-8{height:calc(66.66667% - 1.25rem)}.grid-margin-y>.small-9{height:calc(75% - 1.25rem)}.grid-margin-y>.small-10{height:calc(83.33333% - 1.25rem)}.grid-margin-y>.small-11{height:calc(91.66667% - 1.25rem)}.grid-margin-y>.small-12{height:calc(100% - 1.25rem)}@media print,screen and (min-width:40em){.grid-margin-y>.auto{height:auto}.grid-margin-y>.shrink{height:auto}.grid-margin-y>.small-1{height:calc(8.33333% - 1.875rem)}.grid-margin-y>.small-2{height:calc(16.66667% - 1.875rem)}.grid-margin-y>.small-3{height:calc(25% - 1.875rem)}.grid-margin-y>.small-4{height:calc(33.33333% - 1.875rem)}.grid-margin-y>.small-5{height:calc(41.66667% - 1.875rem)}.grid-margin-y>.small-6{height:calc(50% - 1.875rem)}.grid-margin-y>.small-7{height:calc(58.33333% - 1.875rem)}.grid-margin-y>.small-8{height:calc(66.66667% - 1.875rem)}.grid-margin-y>.small-9{height:calc(75% - 1.875rem)}.grid-margin-y>.small-10{height:calc(83.33333% - 1.875rem)}.grid-margin-y>.small-11{height:calc(91.66667% - 1.875rem)}.grid-margin-y>.small-12{height:calc(100% - 1.875rem)}.grid-margin-y>.medium-auto{height:auto}.grid-margin-y>.medium-shrink{height:auto}.grid-margin-y>.medium-1{height:calc(8.33333% - 1.875rem)}.grid-margin-y>.medium-2{height:calc(16.66667% - 1.875rem)}.grid-margin-y>.medium-3{height:calc(25% - 1.875rem)}.grid-margin-y>.medium-4{height:calc(33.33333% - 1.875rem)}.grid-margin-y>.medium-5{height:calc(41.66667% - 1.875rem)}.grid-margin-y>.medium-6{height:calc(50% - 1.875rem)}.grid-margin-y>.medium-7{height:calc(58.33333% - 1.875rem)}.grid-margin-y>.medium-8{height:calc(66.66667% - 1.875rem)}.grid-margin-y>.medium-9{height:calc(75% - 1.875rem)}.grid-margin-y>.medium-10{height:calc(83.33333% - 1.875rem)}.grid-margin-y>.medium-11{height:calc(91.66667% - 1.875rem)}.grid-margin-y>.medium-12{height:calc(100% - 1.875rem)}}@media print,screen and (min-width:64em){.grid-margin-y>.large-auto{height:auto}.grid-margin-y>.large-shrink{height:auto}.grid-margin-y>.large-1{height:calc(8.33333% - 1.875rem)}.grid-margin-y>.large-2{height:calc(16.66667% - 1.875rem)}.grid-margin-y>.large-3{height:calc(25% - 1.875rem)}.grid-margin-y>.large-4{height:calc(33.33333% - 1.875rem)}.grid-margin-y>.large-5{height:calc(41.66667% - 1.875rem)}.grid-margin-y>.large-6{height:calc(50% - 1.875rem)}.grid-margin-y>.large-7{height:calc(58.33333% - 1.875rem)}.grid-margin-y>.large-8{height:calc(66.66667% - 1.875rem)}.grid-margin-y>.large-9{height:calc(75% - 1.875rem)}.grid-margin-y>.large-10{height:calc(83.33333% - 1.875rem)}.grid-margin-y>.large-11{height:calc(91.66667% - 1.875rem)}.grid-margin-y>.large-12{height:calc(100% - 1.875rem)}}.grid-frame.grid-margin-y{height:calc(100vh + 1.25rem)}@media print,screen and (min-width:40em){.grid-frame.grid-margin-y{height:calc(100vh + 1.875rem)}}@media print,screen and (min-width:64em){.grid-frame.grid-margin-y{height:calc(100vh + 1.875rem)}}@media print,screen and (min-width:40em){.grid-margin-y.medium-grid-frame{height:calc(100vh + 1.875rem)}}@media print,screen and (min-width:64em){.grid-margin-y.large-grid-frame{height:calc(100vh + 1.875rem)}}.button{-webkit-appearance:none;border:1px solid transparent;border-radius:0;cursor:pointer;display:inline-block;font-family:inherit;font-size:.9rem;line-height:1;margin:0 0 1rem;padding:.85em 1em;text-align:center;-webkit-transition:background-color .25s ease-out,color .25s ease-out;transition:background-color .25s ease-out,color .25s ease-out;vertical-align:middle}[data-whatinput=mouse] .button{outline:0}.button.tiny{font-size:.6rem}.button.small{font-size:.75rem}.button.large{font-size:1.25rem}.button.expanded{display:block;margin-left:0;margin-right:0;width:100%}.button,.button.disabled,.button.disabled:focus,.button.disabled:hover,.button[disabled],.button[disabled]:focus,.button[disabled]:hover{background-color:#1779ba;color:#fefefe}.button:focus,.button:hover{background-color:#14679e;color:#fefefe}.button.primary,.button.primary.disabled,.button.primary.disabled:focus,.button.primary.disabled:hover,.button.primary[disabled],.button.primary[disabled]:focus,.button.primary[disabled]:hover{background-color:#1779ba;color:#fefefe}.button.primary:focus,.button.primary:hover{background-color:#126195;color:#fefefe}.button.secondary,.button.secondary.disabled,.button.secondary.disabled:focus,.button.secondary.disabled:hover,.button.secondary[disabled],.button.secondary[disabled]:focus,.button.secondary[disabled]:hover{background-color:#767676;color:#fefefe}.button.secondary:focus,.button.secondary:hover{background-color:#5e5e5e;color:#fefefe}.button.success,.button.success.disabled,.button.success.disabled:focus,.button.success.disabled:hover,.button.success[disabled],.button.success[disabled]:focus,.button.success[disabled]:hover{background-color:#3adb76;color:#0a0a0a}.button.success:focus,.button.success:hover{background-color:#22bb5b;color:#0a0a0a}.button.warning,.button.warning.disabled,.button.warning.disabled:focus,.button.warning.disabled:hover,.button.warning[disabled],.button.warning[disabled]:focus,.button.warning[disabled]:hover{background-color:#ffae00;color:#0a0a0a}.button.warning:focus,.button.warning:hover{background-color:#cc8b00;color:#0a0a0a}.button.alert,.button.alert.disabled,.button.alert.disabled:focus,.button.alert.disabled:hover,.button.alert[disabled],.button.alert[disabled]:focus,.button.alert[disabled]:hover{background-color:#cc4b37;color:#fefefe}.button.alert:focus,.button.alert:hover{background-color:#a53b2a;color:#fefefe}.button.hollow,.button.hollow.disabled,.button.hollow.disabled:focus,.button.hollow.disabled:hover,.button.hollow:focus,.button.hollow:hover,.button.hollow[disabled],.button.hollow[disabled]:focus,.button.hollow[disabled]:hover{background-color:transparent}.button.hollow,.button.hollow.disabled,.button.hollow.disabled:focus,.button.hollow.disabled:hover,.button.hollow[disabled],.button.hollow[disabled]:focus,.button.hollow[disabled]:hover{border:1px solid #1779ba;color:#1779ba}.button.hollow:focus,.button.hollow:hover{border-color:#0c3d5d;color:#0c3d5d}.button.hollow.primary,.button.hollow.primary.disabled,.button.hollow.primary.disabled:focus,.button.hollow.primary.disabled:hover,.button.hollow.primary[disabled],.button.hollow.primary[disabled]:focus,.button.hollow.primary[disabled]:hover{border:1px solid #1779ba;color:#1779ba}.button.hollow.primary:focus,.button.hollow.primary:hover{border-color:#0c3d5d;color:#0c3d5d}.button.hollow.secondary,.button.hollow.secondary.disabled,.button.hollow.secondary.disabled:focus,.button.hollow.secondary.disabled:hover,.button.hollow.secondary[disabled],.button.hollow.secondary[disabled]:focus,.button.hollow.secondary[disabled]:hover{border:1px solid #767676;color:#767676}.button.hollow.secondary:focus,.button.hollow.secondary:hover{border-color:#3b3b3b;color:#3b3b3b}.button.hollow.success,.button.hollow.success.disabled,.button.hollow.success.disabled:focus,.button.hollow.success.disabled:hover,.button.hollow.success[disabled],.button.hollow.success[disabled]:focus,.button.hollow.success[disabled]:hover{border:1px solid #3adb76;color:#3adb76}.button.hollow.success:focus,.button.hollow.success:hover{border-color:#157539;color:#157539}.button.hollow.warning,.button.hollow.warning.disabled,.button.hollow.warning.disabled:focus,.button.hollow.warning.disabled:hover,.button.hollow.warning[disabled],.button.hollow.warning[disabled]:focus,.button.hollow.warning[disabled]:hover{border:1px solid #ffae00;color:#ffae00}.button.hollow.warning:focus,.button.hollow.warning:hover{border-color:#805700;color:#805700}.button.hollow.alert,.button.hollow.alert.disabled,.button.hollow.alert.disabled:focus,.button.hollow.alert.disabled:hover,.button.hollow.alert[disabled],.button.hollow.alert[disabled]:focus,.button.hollow.alert[disabled]:hover{border:1px solid #cc4b37;color:#cc4b37}.button.hollow.alert:focus,.button.hollow.alert:hover{border-color:#67251a;color:#67251a}.button.clear,.button.clear.disabled,.button.clear.disabled:focus,.button.clear.disabled:hover,.button.clear:focus,.button.clear:hover,.button.clear[disabled],.button.clear[disabled]:focus,.button.clear[disabled]:hover{background-color:transparent;border-color:transparent}.button.clear,.button.clear.disabled,.button.clear.disabled:focus,.button.clear.disabled:hover,.button.clear[disabled],.button.clear[disabled]:focus,.button.clear[disabled]:hover{color:#1779ba}.button.clear:focus,.button.clear:hover{color:#0c3d5d}.button.clear.primary,.button.clear.primary.disabled,.button.clear.primary.disabled:focus,.button.clear.primary.disabled:hover,.button.clear.primary[disabled],.button.clear.primary[disabled]:focus,.button.clear.primary[disabled]:hover{color:#1779ba}.button.clear.primary:focus,.button.clear.primary:hover{color:#0c3d5d}.button.clear.secondary,.button.clear.secondary.disabled,.button.clear.secondary.disabled:focus,.button.clear.secondary.disabled:hover,.button.clear.secondary[disabled],.button.clear.secondary[disabled]:focus,.button.clear.secondary[disabled]:hover{color:#767676}.button.clear.secondary:focus,.button.clear.secondary:hover{color:#3b3b3b}.button.clear.success,.button.clear.success.disabled,.button.clear.success.disabled:focus,.button.clear.success.disabled:hover,.button.clear.success[disabled],.button.clear.success[disabled]:focus,.button.clear.success[disabled]:hover{color:#3adb76}.button.clear.success:focus,.button.clear.success:hover{color:#157539}.button.clear.warning,.button.clear.warning.disabled,.button.clear.warning.disabled:focus,.button.clear.warning.disabled:hover,.button.clear.warning[disabled],.button.clear.warning[disabled]:focus,.button.clear.warning[disabled]:hover{color:#ffae00}.button.clear.warning:focus,.button.clear.warning:hover{color:#805700}.button.clear.alert,.button.clear.alert.disabled,.button.clear.alert.disabled:focus,.button.clear.alert.disabled:hover,.button.clear.alert[disabled],.button.clear.alert[disabled]:focus,.button.clear.alert[disabled]:hover{color:#cc4b37}.button.clear.alert:focus,.button.clear.alert:hover{color:#67251a}.button.disabled,.button[disabled]{cursor:not-allowed;opacity:.25}.button.dropdown:after{border-color:#fefefe transparent transparent;border-style:solid;border-width:.4em .4em 0;content:"";display:block;display:inline-block;float:right;height:0;margin-left:1em;position:relative;top:.4em;width:0}.button.dropdown.clear:after,.button.dropdown.hollow:after{border-top-color:#1779ba}.button.dropdown.clear.primary:after,.button.dropdown.hollow.primary:after{border-top-color:#1779ba}.button.dropdown.clear.secondary:after,.button.dropdown.hollow.secondary:after{border-top-color:#767676}.button.dropdown.clear.success:after,.button.dropdown.hollow.success:after{border-top-color:#3adb76}.button.dropdown.clear.warning:after,.button.dropdown.hollow.warning:after{border-top-color:#ffae00}.button.dropdown.clear.alert:after,.button.dropdown.hollow.alert:after{border-top-color:#cc4b37}.button.arrow-only:after{float:none;margin-left:0;top:-.1em}a.button:focus,a.button:hover{text-decoration:none}.button-group{-webkit-box-align:stretch;-ms-flex-align:stretch;-webkit-box-flex:1;-ms-flex-positive:1;-webkit-align-items:stretch;align-items:stretch;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-grow:1;flex-grow:1;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;margin-bottom:1rem}.button-group:after,.button-group:before{-ms-flex-preferred-size:0;-webkit-box-ordinal-group:2;-ms-flex-order:1;content:" ";display:table;-webkit-flex-basis:0;flex-basis:0;-webkit-order:1;order:1}.button-group:after{clear:both}.button-group:after,.button-group:before{display:none}.button-group .button{-webkit-box-flex:0;-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto;font-size:.9rem;margin:0 1px 1px 0}.button-group .button:last-child{margin-right:0}.button-group.tiny .button{font-size:.6rem}.button-group.small .button{font-size:.75rem}.button-group.large .button{font-size:1.25rem}.button-group.expanded .button{-webkit-box-flex:1;-webkit-flex:1 1 0px;-ms-flex:1 1 0px;flex:1 1 0px}.button-group.primary .button,.button-group.primary .button.disabled,.button-group.primary .button.disabled:focus,.button-group.primary .button.disabled:hover,.button-group.primary .button[disabled],.button-group.primary .button[disabled]:focus,.button-group.primary .button[disabled]:hover{background-color:#1779ba;color:#fefefe}.button-group.primary .button:focus,.button-group.primary .button:hover{background-color:#126195;color:#fefefe}.button-group.secondary .button,.button-group.secondary .button.disabled,.button-group.secondary .button.disabled:focus,.button-group.secondary .button.disabled:hover,.button-group.secondary .button[disabled],.button-group.secondary .button[disabled]:focus,.button-group.secondary .button[disabled]:hover{background-color:#767676;color:#fefefe}.button-group.secondary .button:focus,.button-group.secondary .button:hover{background-color:#5e5e5e;color:#fefefe}.button-group.success .button,.button-group.success .button.disabled,.button-group.success .button.disabled:focus,.button-group.success .button.disabled:hover,.button-group.success .button[disabled],.button-group.success .button[disabled]:focus,.button-group.success .button[disabled]:hover{background-color:#3adb76;color:#0a0a0a}.button-group.success .button:focus,.button-group.success .button:hover{background-color:#22bb5b;color:#0a0a0a}.button-group.warning .button,.button-group.warning .button.disabled,.button-group.warning .button.disabled:focus,.button-group.warning .button.disabled:hover,.button-group.warning .button[disabled],.button-group.warning .button[disabled]:focus,.button-group.warning .button[disabled]:hover{background-color:#ffae00;color:#0a0a0a}.button-group.warning .button:focus,.button-group.warning .button:hover{background-color:#cc8b00;color:#0a0a0a}.button-group.alert .button,.button-group.alert .button.disabled,.button-group.alert .button.disabled:focus,.button-group.alert .button.disabled:hover,.button-group.alert .button[disabled],.button-group.alert .button[disabled]:focus,.button-group.alert .button[disabled]:hover{background-color:#cc4b37;color:#fefefe}.button-group.alert .button:focus,.button-group.alert .button:hover{background-color:#a53b2a;color:#fefefe}.button-group.hollow .button,.button-group.hollow .button.disabled,.button-group.hollow .button.disabled:focus,.button-group.hollow .button.disabled:hover,.button-group.hollow .button:focus,.button-group.hollow .button:hover,.button-group.hollow .button[disabled],.button-group.hollow .button[disabled]:focus,.button-group.hollow .button[disabled]:hover{background-color:transparent}.button-group.hollow .button,.button-group.hollow .button.disabled,.button-group.hollow .button.disabled:focus,.button-group.hollow .button.disabled:hover,.button-group.hollow .button[disabled],.button-group.hollow .button[disabled]:focus,.button-group.hollow .button[disabled]:hover{border:1px solid #1779ba;color:#1779ba}.button-group.hollow .button:focus,.button-group.hollow .button:hover{border-color:#0c3d5d;color:#0c3d5d}.button-group.hollow .button.primary,.button-group.hollow .button.primary.disabled,.button-group.hollow .button.primary.disabled:focus,.button-group.hollow .button.primary.disabled:hover,.button-group.hollow .button.primary[disabled],.button-group.hollow .button.primary[disabled]:focus,.button-group.hollow .button.primary[disabled]:hover,.button-group.hollow.primary .button,.button-group.hollow.primary .button.disabled,.button-group.hollow.primary .button.disabled:focus,.button-group.hollow.primary .button.disabled:hover,.button-group.hollow.primary .button[disabled],.button-group.hollow.primary .button[disabled]:focus,.button-group.hollow.primary .button[disabled]:hover{border:1px solid #1779ba;color:#1779ba}.button-group.hollow .button.primary:focus,.button-group.hollow .button.primary:hover,.button-group.hollow.primary .button:focus,.button-group.hollow.primary .button:hover{border-color:#0c3d5d;color:#0c3d5d}.button-group.hollow .button.secondary,.button-group.hollow .button.secondary.disabled,.button-group.hollow .button.secondary.disabled:focus,.button-group.hollow .button.secondary.disabled:hover,.button-group.hollow .button.secondary[disabled],.button-group.hollow .button.secondary[disabled]:focus,.button-group.hollow .button.secondary[disabled]:hover,.button-group.hollow.secondary .button,.button-group.hollow.secondary .button.disabled,.button-group.hollow.secondary .button.disabled:focus,.button-group.hollow.secondary .button.disabled:hover,.button-group.hollow.secondary .button[disabled],.button-group.hollow.secondary .button[disabled]:focus,.button-group.hollow.secondary .button[disabled]:hover{border:1px solid #767676;color:#767676}.button-group.hollow .button.secondary:focus,.button-group.hollow .button.secondary:hover,.button-group.hollow.secondary .button:focus,.button-group.hollow.secondary .button:hover{border-color:#3b3b3b;color:#3b3b3b}.button-group.hollow .button.success,.button-group.hollow .button.success.disabled,.button-group.hollow .button.success.disabled:focus,.button-group.hollow .button.success.disabled:hover,.button-group.hollow .button.success[disabled],.button-group.hollow .button.success[disabled]:focus,.button-group.hollow .button.success[disabled]:hover,.button-group.hollow.success .button,.button-group.hollow.success .button.disabled,.button-group.hollow.success .button.disabled:focus,.button-group.hollow.success .button.disabled:hover,.button-group.hollow.success .button[disabled],.button-group.hollow.success .button[disabled]:focus,.button-group.hollow.success .button[disabled]:hover{border:1px solid #3adb76;color:#3adb76}.button-group.hollow .button.success:focus,.button-group.hollow .button.success:hover,.button-group.hollow.success .button:focus,.button-group.hollow.success .button:hover{border-color:#157539;color:#157539}.button-group.hollow .button.warning,.button-group.hollow .button.warning.disabled,.button-group.hollow .button.warning.disabled:focus,.button-group.hollow .button.warning.disabled:hover,.button-group.hollow .button.warning[disabled],.button-group.hollow .button.warning[disabled]:focus,.button-group.hollow .button.warning[disabled]:hover,.button-group.hollow.warning .button,.button-group.hollow.warning .button.disabled,.button-group.hollow.warning .button.disabled:focus,.button-group.hollow.warning .button.disabled:hover,.button-group.hollow.warning .button[disabled],.button-group.hollow.warning .button[disabled]:focus,.button-group.hollow.warning .button[disabled]:hover{border:1px solid #ffae00;color:#ffae00}.button-group.hollow .button.warning:focus,.button-group.hollow .button.warning:hover,.button-group.hollow.warning .button:focus,.button-group.hollow.warning .button:hover{border-color:#805700;color:#805700}.button-group.hollow.alert .button,.button-group.hollow.alert .button.disabled,.button-group.hollow.alert .button.disabled:focus,.button-group.hollow.alert .button.disabled:hover,.button-group.hollow.alert .button[disabled],.button-group.hollow.alert .button[disabled]:focus,.button-group.hollow.alert .button[disabled]:hover,.button-group.hollow .button.alert,.button-group.hollow .button.alert.disabled,.button-group.hollow .button.alert.disabled:focus,.button-group.hollow .button.alert.disabled:hover,.button-group.hollow .button.alert[disabled],.button-group.hollow .button.alert[disabled]:focus,.button-group.hollow .button.alert[disabled]:hover{border:1px solid #cc4b37;color:#cc4b37}.button-group.hollow.alert .button:focus,.button-group.hollow.alert .button:hover,.button-group.hollow .button.alert:focus,.button-group.hollow .button.alert:hover{border-color:#67251a;color:#67251a}.button-group.clear .button,.button-group.clear .button.disabled,.button-group.clear .button.disabled:focus,.button-group.clear .button.disabled:hover,.button-group.clear .button:focus,.button-group.clear .button:hover,.button-group.clear .button[disabled],.button-group.clear .button[disabled]:focus,.button-group.clear .button[disabled]:hover{background-color:transparent;border-color:transparent}.button-group.clear .button,.button-group.clear .button.disabled,.button-group.clear .button.disabled:focus,.button-group.clear .button.disabled:hover,.button-group.clear .button[disabled],.button-group.clear .button[disabled]:focus,.button-group.clear .button[disabled]:hover{color:#1779ba}.button-group.clear .button:focus,.button-group.clear .button:hover{color:#0c3d5d}.button-group.clear .button.primary,.button-group.clear .button.primary.disabled,.button-group.clear .button.primary.disabled:focus,.button-group.clear .button.primary.disabled:hover,.button-group.clear .button.primary[disabled],.button-group.clear .button.primary[disabled]:focus,.button-group.clear .button.primary[disabled]:hover,.button-group.clear.primary .button,.button-group.clear.primary .button.disabled,.button-group.clear.primary .button.disabled:focus,.button-group.clear.primary .button.disabled:hover,.button-group.clear.primary .button[disabled],.button-group.clear.primary .button[disabled]:focus,.button-group.clear.primary .button[disabled]:hover{color:#1779ba}.button-group.clear .button.primary:focus,.button-group.clear .button.primary:hover,.button-group.clear.primary .button:focus,.button-group.clear.primary .button:hover{color:#0c3d5d}.button-group.clear .button.secondary,.button-group.clear .button.secondary.disabled,.button-group.clear .button.secondary.disabled:focus,.button-group.clear .button.secondary.disabled:hover,.button-group.clear .button.secondary[disabled],.button-group.clear .button.secondary[disabled]:focus,.button-group.clear .button.secondary[disabled]:hover,.button-group.clear.secondary .button,.button-group.clear.secondary .button.disabled,.button-group.clear.secondary .button.disabled:focus,.button-group.clear.secondary .button.disabled:hover,.button-group.clear.secondary .button[disabled],.button-group.clear.secondary .button[disabled]:focus,.button-group.clear.secondary .button[disabled]:hover{color:#767676}.button-group.clear .button.secondary:focus,.button-group.clear .button.secondary:hover,.button-group.clear.secondary .button:focus,.button-group.clear.secondary .button:hover{color:#3b3b3b}.button-group.clear .button.success,.button-group.clear .button.success.disabled,.button-group.clear .button.success.disabled:focus,.button-group.clear .button.success.disabled:hover,.button-group.clear .button.success[disabled],.button-group.clear .button.success[disabled]:focus,.button-group.clear .button.success[disabled]:hover,.button-group.clear.success .button,.button-group.clear.success .button.disabled,.button-group.clear.success .button.disabled:focus,.button-group.clear.success .button.disabled:hover,.button-group.clear.success .button[disabled],.button-group.clear.success .button[disabled]:focus,.button-group.clear.success .button[disabled]:hover{color:#3adb76}.button-group.clear .button.success:focus,.button-group.clear .button.success:hover,.button-group.clear.success .button:focus,.button-group.clear.success .button:hover{color:#157539}.button-group.clear .button.warning,.button-group.clear .button.warning.disabled,.button-group.clear .button.warning.disabled:focus,.button-group.clear .button.warning.disabled:hover,.button-group.clear .button.warning[disabled],.button-group.clear .button.warning[disabled]:focus,.button-group.clear .button.warning[disabled]:hover,.button-group.clear.warning .button,.button-group.clear.warning .button.disabled,.button-group.clear.warning .button.disabled:focus,.button-group.clear.warning .button.disabled:hover,.button-group.clear.warning .button[disabled],.button-group.clear.warning .button[disabled]:focus,.button-group.clear.warning .button[disabled]:hover{color:#ffae00}.button-group.clear .button.warning:focus,.button-group.clear .button.warning:hover,.button-group.clear.warning .button:focus,.button-group.clear.warning .button:hover{color:#805700}.button-group.clear.alert .button,.button-group.clear.alert .button.disabled,.button-group.clear.alert .button.disabled:focus,.button-group.clear.alert .button.disabled:hover,.button-group.clear.alert .button[disabled],.button-group.clear.alert .button[disabled]:focus,.button-group.clear.alert .button[disabled]:hover,.button-group.clear .button.alert,.button-group.clear .button.alert.disabled,.button-group.clear .button.alert.disabled:focus,.button-group.clear .button.alert.disabled:hover,.button-group.clear .button.alert[disabled],.button-group.clear .button.alert[disabled]:focus,.button-group.clear .button.alert[disabled]:hover{color:#cc4b37}.button-group.clear.alert .button:focus,.button-group.clear.alert .button:hover,.button-group.clear .button.alert:focus,.button-group.clear .button.alert:hover{color:#67251a}.button-group.no-gaps .button{margin-right:-.0625rem}.button-group.no-gaps .button+.button{border-left-color:transparent}.button-group.stacked,.button-group.stacked-for-medium,.button-group.stacked-for-small{-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap}.button-group.stacked-for-medium .button,.button-group.stacked-for-small .button,.button-group.stacked .button{-webkit-box-flex:0;-webkit-flex:0 0 100%;-ms-flex:0 0 100%;flex:0 0 100%}.button-group.stacked-for-medium .button:last-child,.button-group.stacked-for-small .button:last-child,.button-group.stacked .button:last-child{margin-bottom:0}.button-group.stacked-for-medium.expanded .button,.button-group.stacked-for-small.expanded .button,.button-group.stacked.expanded .button{-webkit-box-flex:1;-webkit-flex:1 1 0px;-ms-flex:1 1 0px;flex:1 1 0px}@media print,screen and (min-width:40em){.button-group.stacked-for-small .button{-webkit-box-flex:0;-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto;margin-bottom:0}}@media print,screen and (min-width:64em){.button-group.stacked-for-medium .button{-webkit-box-flex:0;-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto;margin-bottom:0}}@media print,screen and (max-width:39.99875em){.button-group.stacked-for-small.expanded{display:block}.button-group.stacked-for-small.expanded .button{display:block;margin-right:0}}@media print,screen and (max-width:63.99875em){.button-group.stacked-for-medium.expanded{display:block}.button-group.stacked-for-medium.expanded .button{display:block;margin-right:0}}.close-button{color:#8a8a8a;cursor:pointer;position:absolute;z-index:10}[data-whatinput=mouse] .close-button{outline:0}.close-button:focus,.close-button:hover{color:#0a0a0a}.close-button.small{font-size:1.5em;line-height:1;right:.66rem;top:.33em}.close-button,.close-button.medium{font-size:2em;line-height:1;right:1rem;top:.5rem}.label{border-radius:0;cursor:default;display:inline-block;font-size:.8rem;line-height:1;padding:.33333rem .5rem;white-space:nowrap}.label,.label.primary{background:#1779ba;color:#fefefe}.label.secondary{background:#767676;color:#fefefe}.label.success{background:#3adb76;color:#0a0a0a}.label.warning{background:#ffae00;color:#0a0a0a}.label.alert{background:#cc4b37;color:#fefefe}.progress{background-color:#cacaca;border-radius:0;height:1rem;margin-bottom:1rem}.progress.primary .progress-meter{background-color:#1779ba}.progress.secondary .progress-meter{background-color:#767676}.progress.success .progress-meter{background-color:#3adb76}.progress.warning .progress-meter{background-color:#ffae00}.progress.alert .progress-meter{background-color:#cc4b37}.progress-meter{background-color:#1779ba;display:block;height:100%;position:relative;width:0}.progress-meter-text{color:#fefefe;font-size:.75rem;font-weight:700;left:50%;margin:0;position:absolute;top:50%;-webkit-transform:translate(-50%,-50%);-ms-transform:translate(-50%,-50%);transform:translate(-50%,-50%);white-space:nowrap}.slider{background-color:#e6e6e6;cursor:pointer;height:.5rem;margin-bottom:2.25rem;margin-top:1.25rem;position:relative;-ms-touch-action:none;touch-action:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.slider-fill{background-color:#cacaca;display:inline-block;height:.5rem;left:0;max-width:100%;position:absolute;top:0;-webkit-transition:all .2s ease-in-out;transition:all .2s ease-in-out}.slider-fill.is-dragging{-webkit-transition:all 0s linear;transition:all 0s linear}.slider-handle{background-color:#1779ba;border-radius:0;cursor:-webkit-grab;cursor:grab;display:inline-block;height:1.4rem;left:0;position:absolute;top:50%;-ms-touch-action:manipulation;touch-action:manipulation;-webkit-transform:translateY(-50%);-ms-transform:translateY(-50%);transform:translateY(-50%);-webkit-transition:all .2s ease-in-out;transition:all .2s ease-in-out;width:1.4rem;z-index:1}[data-whatinput=mouse] .slider-handle{outline:0}.slider-handle:hover{background-color:#14679e}.slider-handle.is-dragging{cursor:-webkit-grabbing;cursor:grabbing;-webkit-transition:all 0s linear;transition:all 0s linear}.slider.disabled,.slider[disabled]{cursor:not-allowed;opacity:.25}.slider.vertical{display:inline-block;height:12.5rem;margin:0 1.25rem;-webkit-transform:scaleY(-1);-ms-transform:scaleY(-1);transform:scaleY(-1);width:.5rem}.slider.vertical .slider-fill{max-height:100%;top:0;width:.5rem}.slider.vertical .slider-handle{height:1.4rem;left:50%;position:absolute;top:0;-webkit-transform:translateX(-50%);-ms-transform:translateX(-50%);transform:translateX(-50%);width:1.4rem}.switch{color:#fefefe;font-size:.875rem;font-weight:700;height:2rem;margin-bottom:1rem;outline:0;position:relative;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.switch-input{margin-bottom:0;opacity:0;position:absolute}.switch-paddle{background:#cacaca;border-radius:0;color:inherit;cursor:pointer;display:block;font-weight:inherit;height:2rem;position:relative;-webkit-transition:all .25s ease-out;transition:all .25s ease-out;width:4rem}input+.switch-paddle{margin:0}.switch-paddle:after{background:#fefefe;border-radius:0;content:"";display:block;height:1.5rem;left:.25rem;position:absolute;top:.25rem;-webkit-transform:translateZ(0);transform:translateZ(0);-webkit-transition:all .25s ease-out;transition:all .25s ease-out;width:1.5rem}input:checked~.switch-paddle{background:#1779ba}input:checked~.switch-paddle:after{left:2.25rem}input:disabled~.switch-paddle{cursor:not-allowed;opacity:.5}[data-whatinput=mouse] input:focus~.switch-paddle{outline:0}.switch-active,.switch-inactive{position:absolute;top:50%;-webkit-transform:translateY(-50%);-ms-transform:translateY(-50%);transform:translateY(-50%)}.switch-active{display:none;left:8%}input:checked+label>.switch-active{display:block}.switch-inactive{right:15%}input:checked+label>.switch-inactive{display:none}.switch.tiny{height:1.5rem}.switch.tiny .switch-paddle{font-size:.625rem;height:1.5rem;width:3rem}.switch.tiny .switch-paddle:after{height:1rem;left:.25rem;top:.25rem;width:1rem}.switch.tiny input:checked~.switch-paddle:after{left:1.75rem}.switch.small{height:1.75rem}.switch.small .switch-paddle{font-size:.75rem;height:1.75rem;width:3.5rem}.switch.small .switch-paddle:after{height:1.25rem;left:.25rem;top:.25rem;width:1.25rem}.switch.small input:checked~.switch-paddle:after{left:2rem}.switch.large{height:2.5rem}.switch.large .switch-paddle{font-size:1rem;height:2.5rem;width:5rem}.switch.large .switch-paddle:after{height:2rem;left:.25rem;top:.25rem;width:2rem}.switch.large input:checked~.switch-paddle:after{left:2.75rem}table{border-collapse:collapse;border-radius:0;margin-bottom:1rem;width:100%}tbody,tfoot,thead{background-color:#fefefe;border:1px solid #f1f1f1}caption{font-weight:700;padding:.5rem .625rem .625rem}thead{background:#f8f8f8}tfoot,thead{color:#0a0a0a}tfoot{background:#f1f1f1}tfoot tr,thead tr{background:0 0}tfoot td,tfoot th,thead td,thead th{font-weight:700;padding:.5rem .625rem .625rem;text-align:left}tbody td,tbody th{padding:.5rem .625rem .625rem}tbody tr:nth-child(2n){background-color:#f1f1f1;border-bottom:0}table.unstriped tbody{background-color:#fefefe}table.unstriped tbody tr{background-color:#fefefe;border-bottom:1px solid #f1f1f1}@media print,screen and (max-width:63.99875em){table.stack tfoot,table.stack thead{display:none}table.stack td,table.stack th,table.stack tr{display:block}table.stack td{border-top:0}}table.scroll{display:block;overflow-x:auto;width:100%}table.hover thead tr:hover{background-color:#f3f3f3}table.hover tfoot tr:hover{background-color:#ececec}table.hover tbody tr:hover{background-color:#f9f9f9}table.hover:not(.unstriped) tr:nth-of-type(2n):hover{background-color:#ececec}.table-scroll{overflow-x:auto}.badge{border-radius:50%;display:inline-block;font-size:.6rem;min-width:2.1em;padding:.3em;text-align:center}.badge,.badge.primary{background:#1779ba;color:#fefefe}.badge.secondary{background:#767676;color:#fefefe}.badge.success{background:#3adb76;color:#0a0a0a}.badge.warning{background:#ffae00;color:#0a0a0a}.badge.alert{background:#cc4b37;color:#fefefe}.breadcrumbs{list-style:none;margin:0 0 1rem}.breadcrumbs:after,.breadcrumbs:before{-ms-flex-preferred-size:0;-webkit-box-ordinal-group:2;-ms-flex-order:1;content:" ";display:table;-webkit-flex-basis:0;flex-basis:0;-webkit-order:1;order:1}.breadcrumbs:after{clear:both}.breadcrumbs li{color:#0a0a0a;cursor:default;float:left;font-size:.6875rem;text-transform:uppercase}.breadcrumbs li:not(:last-child):after{color:#cacaca;content:"/";margin:0 .75rem;opacity:1;position:relative}.breadcrumbs a{color:#1779ba}.breadcrumbs a:hover{text-decoration:underline}.breadcrumbs .disabled{color:#cacaca;cursor:not-allowed}.callout{background-color:#fff;border:1px solid hsla(0,0%,4%,.25);border-radius:0;color:#0a0a0a;margin:0 0 1rem;padding:1rem;position:relative}.callout>:first-child{margin-top:0}.callout>:last-child{margin-bottom:0}.callout.primary{background-color:#d7ecfa;color:#0a0a0a}.callout.secondary{background-color:#eaeaea;color:#0a0a0a}.callout.success{background-color:#e1faea;color:#0a0a0a}.callout.warning{background-color:#fff3d9;color:#0a0a0a}.callout.alert{background-color:#f7e4e1;color:#0a0a0a}.callout.small{padding:.5rem}.callout.large{padding:3rem}.card{-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-box-flex:1;-ms-flex-positive:1;background:#fefefe;border:1px solid #e6e6e6;border-radius:0;-webkit-box-shadow:none;box-shadow:none;color:#0a0a0a;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;-webkit-flex-grow:1;flex-grow:1;margin-bottom:1rem;overflow:hidden}.card>:last-child{margin-bottom:0}.card-divider{-webkit-box-flex:0;background:#e6e6e6;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex:0 1 auto;-ms-flex:0 1 auto;flex:0 1 auto;padding:1rem}.card-divider>:last-child{margin-bottom:0}.card-section{-webkit-box-flex:1;-webkit-flex:1 0 auto;-ms-flex:1 0 auto;flex:1 0 auto;padding:1rem}.card-section>:last-child{margin-bottom:0}.card-image{min-height:1px}.dropdown-pane{background-color:#fefefe;border:1px solid #cacaca;border-radius:0;display:none;font-size:1rem;padding:1rem;position:absolute;visibility:hidden;width:300px;z-index:10}.dropdown-pane.is-opening{display:block}.dropdown-pane.is-open{display:block;visibility:visible}.dropdown-pane.tiny{width:100px}.dropdown-pane.small{width:200px}.dropdown-pane.large{width:400px}.pagination{margin-bottom:1rem;margin-left:0}.pagination:after,.pagination:before{-ms-flex-preferred-size:0;-webkit-box-ordinal-group:2;-ms-flex-order:1;content:" ";display:table;-webkit-flex-basis:0;flex-basis:0;-webkit-order:1;order:1}.pagination:after{clear:both}.pagination li{border-radius:0;display:none;font-size:.875rem;margin-right:.0625rem}.pagination li:first-child,.pagination li:last-child{display:inline-block}@media print,screen and (min-width:40em){.pagination li{display:inline-block}}.pagination a,.pagination button{border-radius:0;color:#0a0a0a;display:block;padding:.1875rem .625rem}.pagination a:hover,.pagination button:hover{background:#e6e6e6}.pagination .current{background:#1779ba;color:#fefefe;cursor:default;padding:.1875rem .625rem}.pagination .disabled{color:#cacaca;cursor:not-allowed;padding:.1875rem .625rem}.pagination .disabled:hover{background:0 0}.pagination .ellipsis:after{color:#0a0a0a;content:"…";padding:.1875rem .625rem}.pagination-previous.disabled:before,.pagination-previous a:before{content:"«";display:inline-block;margin-right:.5rem}.pagination-next.disabled:after,.pagination-next a:after{content:"»";display:inline-block;margin-left:.5rem}.has-tip{border-bottom:1px dotted #8a8a8a;cursor:help;display:inline-block;font-weight:700;position:relative}.tooltip{background-color:#0a0a0a;border-radius:0;color:#fefefe;font-size:80%;max-width:10rem;padding:.75rem;position:absolute;top:calc(100% + .6495rem);z-index:1200}.tooltip:before{position:absolute}.tooltip.bottom:before{border-color:transparent transparent #0a0a0a;border-style:solid;border-width:0 .75rem .75rem;bottom:100%;content:"";display:block;height:0;width:0}.tooltip.bottom.align-center:before{left:50%;-webkit-transform:translateX(-50%);-ms-transform:translateX(-50%);transform:translateX(-50%)}.tooltip.top:before{border-color:#0a0a0a transparent transparent;border-style:solid;border-width:.75rem .75rem 0;bottom:auto;content:"";display:block;height:0;top:100%;width:0}.tooltip.top.align-center:before{left:50%;-webkit-transform:translateX(-50%);-ms-transform:translateX(-50%);transform:translateX(-50%)}.tooltip.left:before{border-color:transparent transparent transparent #0a0a0a;border-style:solid;border-width:.75rem 0 .75rem .75rem;content:"";display:block;height:0;left:100%;width:0}.tooltip.left.align-center:before{bottom:auto;top:50%;-webkit-transform:translateY(-50%);-ms-transform:translateY(-50%);transform:translateY(-50%)}.tooltip.right:before{border-color:transparent #0a0a0a transparent transparent;border-style:solid;border-width:.75rem .75rem .75rem 0;content:"";display:block;height:0;left:auto;right:100%;width:0}.tooltip.right.align-center:before{bottom:auto;top:50%;-webkit-transform:translateY(-50%);-ms-transform:translateY(-50%);transform:translateY(-50%)}.tooltip.align-top:before{bottom:auto;top:10%}.tooltip.align-bottom:before{bottom:10%;top:auto}.tooltip.align-left:before{left:10%;right:auto}.tooltip.align-right:before{left:auto;right:10%}.accordion{background:#fefefe;list-style-type:none;margin-left:0}.accordion[disabled] .accordion-title{cursor:not-allowed}.accordion-item:first-child>:first-child{border-radius:0}.accordion-item:last-child>:last-child{border-radius:0}.accordion-title{border:1px solid #e6e6e6;border-bottom:0;color:#1779ba;display:block;font-size:.75rem;line-height:1;padding:1.25rem 1rem;position:relative}:last-child:not(.is-active)>.accordion-title{border-bottom:1px solid #e6e6e6;border-radius:0}.accordion-title:focus,.accordion-title:hover{background-color:#e6e6e6}.accordion-title:before{content:"+";margin-top:-.5rem;position:absolute;right:1rem;top:50%}.is-active>.accordion-title:before{content:"–"}.accordion-content{background-color:#fefefe;border:1px solid #e6e6e6;border-bottom:0;color:#0a0a0a;display:none;padding:1rem}:last-child>.accordion-content:last-child{border-bottom:1px solid #e6e6e6}.media-object{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap;margin-bottom:1rem}.media-object img{max-width:none}@media print,screen and (max-width:39.99875em){.media-object.stack-for-small{-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap}}.media-object-section{-webkit-box-flex:0;-webkit-flex:0 1 auto;-ms-flex:0 1 auto;flex:0 1 auto}.media-object-section:first-child{padding-right:1rem}.media-object-section:last-child:not(:nth-child(2)){padding-left:1rem}.media-object-section>:last-child{margin-bottom:0}@media print,screen and (max-width:39.99875em){.stack-for-small .media-object-section{-ms-flex-preferred-size:100%;-webkit-flex-basis:100%;flex-basis:100%;max-width:100%;padding:0 0 1rem}.stack-for-small .media-object-section img{width:100%}}.media-object-section.main-section{-webkit-box-flex:1;-webkit-flex:1 1 0px;-ms-flex:1 1 0px;flex:1 1 0px}.orbit,.orbit-container{position:relative}.orbit-container{height:0;list-style:none;margin:0;overflow:hidden}.orbit-slide{position:absolute;width:100%}.orbit-slide.no-motionui.is-active{left:0;top:0}.orbit-figure{margin:0}.orbit-image{margin:0;max-width:100%;width:100%}.orbit-caption{background-color:hsla(0,0%,4%,.5);bottom:0;margin-bottom:0;width:100%}.orbit-caption,.orbit-next,.orbit-previous{color:#fefefe;padding:1rem;position:absolute}.orbit-next,.orbit-previous{top:50%;-webkit-transform:translateY(-50%);-ms-transform:translateY(-50%);transform:translateY(-50%);z-index:10}[data-whatinput=mouse] .orbit-next,[data-whatinput=mouse] .orbit-previous{outline:0}.orbit-next:active,.orbit-next:focus,.orbit-next:hover,.orbit-previous:active,.orbit-previous:focus,.orbit-previous:hover{background-color:hsla(0,0%,4%,.5)}.orbit-previous{left:0}.orbit-next{left:auto;right:0}.orbit-bullets{margin-bottom:.8rem;margin-top:.8rem;position:relative;text-align:center}[data-whatinput=mouse] .orbit-bullets{outline:0}.orbit-bullets button{background-color:#cacaca;border-radius:50%;height:1.2rem;margin:.1rem;width:1.2rem}.orbit-bullets button:hover{background-color:#8a8a8a}.orbit-bullets button.is-active{background-color:#8a8a8a}.flex-video,.responsive-embed{height:0;margin-bottom:1rem;overflow:hidden;padding-bottom:75%;position:relative}.flex-video embed,.flex-video iframe,.flex-video object,.flex-video video,.responsive-embed embed,.responsive-embed iframe,.responsive-embed object,.responsive-embed video{height:100%;left:0;position:absolute;top:0;width:100%}.flex-video.widescreen,.responsive-embed.widescreen{padding-bottom:56.25%}.tabs{background:#fefefe;border:1px solid #e6e6e6;list-style-type:none;margin:0}.tabs:after,.tabs:before{-ms-flex-preferred-size:0;-webkit-box-ordinal-group:2;-ms-flex-order:1;content:" ";display:table;-webkit-flex-basis:0;flex-basis:0;-webkit-order:1;order:1}.tabs:after{clear:both}.tabs.vertical>li{display:block;float:none;width:auto}.tabs.simple>li>a{padding:0}.tabs.simple>li>a:hover{background:0 0}.tabs.primary{background:#1779ba}.tabs.primary>li>a{color:#fefefe}.tabs.primary>li>a:focus,.tabs.primary>li>a:hover{background:#1673b1}.tabs-title{float:left}.tabs-title>a{color:#1779ba;display:block;font-size:.75rem;line-height:1;padding:1.25rem 1.5rem}[data-whatinput=mouse] .tabs-title>a{outline:0}.tabs-title>a:hover{background:#fefefe;color:#1468a0}.tabs-title>a:focus,.tabs-title>a[aria-selected=true]{background:#e6e6e6;color:#1779ba}.tabs-content{background:#fefefe;border:1px solid #e6e6e6;border-top:0;color:#0a0a0a;-webkit-transition:all .5s ease;transition:all .5s ease}.tabs-content.vertical{border:1px solid #e6e6e6;border-left:0}.tabs-panel{display:none;padding:1rem}.tabs-panel.is-active{display:block}.thumbnail{border:4px solid #fefefe;border-radius:0;-webkit-box-shadow:0 0 0 1px hsla(0,0%,4%,.2);box-shadow:0 0 0 1px hsla(0,0%,4%,.2);display:inline-block;line-height:0;margin-bottom:1rem;max-width:100%}a.thumbnail{-webkit-transition:-webkit-box-shadow .2s ease-out;transition:-webkit-box-shadow .2s ease-out;transition:box-shadow .2s ease-out;transition:box-shadow .2s ease-out,-webkit-box-shadow .2s ease-out}a.thumbnail:focus,a.thumbnail:hover{-webkit-box-shadow:0 0 6px 1px rgba(23,121,186,.5);box-shadow:0 0 6px 1px rgba(23,121,186,.5)}a.thumbnail image{-webkit-box-shadow:none;box-shadow:none}.menu{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;list-style:none;margin:0;padding:0;position:relative}[data-whatinput=mouse] .menu li{outline:0}.menu .button,.menu a{display:block;line-height:1;padding:.7rem 1rem;text-decoration:none}.menu a,.menu button,.menu input,.menu select{margin-bottom:0}.menu input{display:inline-block}.menu,.menu.horizontal{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap}.menu.vertical{-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap}.menu.vertical.icon-bottom li a i,.menu.vertical.icon-bottom li a img,.menu.vertical.icon-bottom li a svg,.menu.vertical.icon-top li a i,.menu.vertical.icon-top li a img,.menu.vertical.icon-top li a svg{text-align:left}.menu.expanded li{-webkit-box-flex:1;-webkit-flex:1 1 0px;-ms-flex:1 1 0px;flex:1 1 0px}.menu.expanded.icon-bottom li a i,.menu.expanded.icon-bottom li a img,.menu.expanded.icon-bottom li a svg,.menu.expanded.icon-top li a i,.menu.expanded.icon-top li a img,.menu.expanded.icon-top li a svg{text-align:left}.menu.simple{-webkit-box-align:center;-ms-flex-align:center;-webkit-align-items:center;align-items:center}.menu.simple li+li{margin-left:1rem}.menu.simple a{padding:0}@media print,screen and (min-width:40em){.menu.medium-horizontal{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap}.menu.medium-vertical{-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap}.menu.medium-expanded li,.menu.medium-simple li{-webkit-box-flex:1;-webkit-flex:1 1 0px;-ms-flex:1 1 0px;flex:1 1 0px}}@media print,screen and (min-width:64em){.menu.large-horizontal{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap}.menu.large-vertical{-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap}.menu.large-expanded li,.menu.large-simple li{-webkit-box-flex:1;-webkit-flex:1 1 0px;-ms-flex:1 1 0px;flex:1 1 0px}}.menu.nested{margin-left:1rem;margin-right:0}.menu.icon-bottom a,.menu.icon-left a,.menu.icon-right a,.menu.icon-top a,.menu.icons a{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex}.menu.icon-left li a,.menu.nested.icon-left li a{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-flow:row nowrap;-ms-flex-flow:row nowrap;flex-flow:row nowrap}.menu.icon-left li a i,.menu.icon-left li a img,.menu.icon-left li a svg,.menu.nested.icon-left li a i,.menu.nested.icon-left li a img,.menu.nested.icon-left li a svg{margin-right:.25rem}.menu.icon-right li a,.menu.nested.icon-right li a{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-flow:row nowrap;-ms-flex-flow:row nowrap;flex-flow:row nowrap}.menu.icon-right li a i,.menu.icon-right li a img,.menu.icon-right li a svg,.menu.nested.icon-right li a i,.menu.nested.icon-right li a img,.menu.nested.icon-right li a svg{margin-left:.25rem}.menu.icon-top li a,.menu.nested.icon-top li a{-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-flow:column nowrap;-ms-flex-flow:column nowrap;flex-flow:column nowrap}.menu.icon-top li a i,.menu.icon-top li a img,.menu.icon-top li a svg,.menu.nested.icon-top li a i,.menu.nested.icon-top li a img,.menu.nested.icon-top li a svg{-ms-flex-item-align:stretch;-webkit-align-self:stretch;align-self:stretch;margin-bottom:.25rem;text-align:center}.menu.icon-bottom li a,.menu.nested.icon-bottom li a{-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-flow:column nowrap;-ms-flex-flow:column nowrap;flex-flow:column nowrap}.menu.icon-bottom li a i,.menu.icon-bottom li a img,.menu.icon-bottom li a svg,.menu.nested.icon-bottom li a i,.menu.nested.icon-bottom li a img,.menu.nested.icon-bottom li a svg{-ms-flex-item-align:stretch;-webkit-align-self:stretch;align-self:stretch;margin-bottom:.25rem;text-align:center}.menu .is-active>a{background:#1779ba;color:#fefefe}.menu .active>a{background:#1779ba;color:#fefefe}.menu.align-left{-webkit-box-pack:start;-ms-flex-pack:start;-webkit-justify-content:flex-start;justify-content:flex-start}.menu.align-right li{-webkit-box-pack:end;-ms-flex-pack:end;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-justify-content:flex-end;justify-content:flex-end}.menu.align-right li .submenu li{-webkit-box-pack:start;-ms-flex-pack:start;-webkit-justify-content:flex-start;justify-content:flex-start}.menu.align-right.vertical li{display:block;text-align:right}.menu.align-right.icon-bottom li a i,.menu.align-right.icon-bottom li a img,.menu.align-right.icon-bottom li a svg,.menu.align-right.icon-top li a i,.menu.align-right.icon-top li a img,.menu.align-right.icon-top li a svg,.menu.align-right.vertical li .submenu li{text-align:right}.menu.align-right .nested{margin-left:0;margin-right:1rem}.menu.align-center li{-webkit-box-pack:center;-ms-flex-pack:center;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-justify-content:center;justify-content:center}.menu.align-center li .submenu li{-webkit-box-pack:start;-ms-flex-pack:start;-webkit-justify-content:flex-start;justify-content:flex-start}.menu .menu-text{color:inherit;font-weight:700;line-height:1;padding:.7rem 1rem}.menu-centered>.menu{-webkit-box-pack:center;-ms-flex-pack:center;-webkit-justify-content:center;justify-content:center}.menu-centered>.menu li{-webkit-box-pack:center;-ms-flex-pack:center;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-justify-content:center;justify-content:center}.menu-centered>.menu li .submenu li{-webkit-box-pack:start;-ms-flex-pack:start;-webkit-justify-content:flex-start;justify-content:flex-start}.no-js [data-responsive-menu] ul{display:none}.menu-icon{cursor:pointer;display:inline-block;height:16px;position:relative;vertical-align:middle;width:20px}.menu-icon:after{background:#fefefe;-webkit-box-shadow:0 7px 0 #fefefe,0 14px 0 #fefefe;box-shadow:0 7px 0 #fefefe,0 14px 0 #fefefe;content:"";display:block;height:2px;left:0;position:absolute;top:0;width:100%}.menu-icon:hover:after{background:#cacaca;-webkit-box-shadow:0 7px 0 #cacaca,0 14px 0 #cacaca;box-shadow:0 7px 0 #cacaca,0 14px 0 #cacaca}.menu-icon.dark{cursor:pointer;display:inline-block;height:16px;position:relative;vertical-align:middle;width:20px}.menu-icon.dark:after{background:#0a0a0a;-webkit-box-shadow:0 7px 0 #0a0a0a,0 14px 0 #0a0a0a;box-shadow:0 7px 0 #0a0a0a,0 14px 0 #0a0a0a;content:"";display:block;height:2px;left:0;position:absolute;top:0;width:100%}.menu-icon.dark:hover:after{background:#8a8a8a;-webkit-box-shadow:0 7px 0 #8a8a8a,0 14px 0 #8a8a8a;box-shadow:0 7px 0 #8a8a8a,0 14px 0 #8a8a8a}.accordion-menu li{width:100%}.accordion-menu .is-accordion-submenu a,.accordion-menu a{padding:.7rem 1rem}.accordion-menu .nested.is-accordion-submenu{margin-left:1rem;margin-right:0}.accordion-menu.align-right .nested.is-accordion-submenu{margin-left:0;margin-right:1rem}.accordion-menu .is-accordion-submenu-parent:not(.has-submenu-toggle)>a{position:relative}.accordion-menu .is-accordion-submenu-parent:not(.has-submenu-toggle)>a:after{border-color:#1779ba transparent transparent;border-style:solid;border-width:6px 6px 0;content:"";display:block;height:0;margin-top:-3px;position:absolute;right:1rem;top:50%;width:0}.accordion-menu.align-left .is-accordion-submenu-parent>a:after{left:auto;right:1rem}.accordion-menu.align-right .is-accordion-submenu-parent>a:after{left:1rem;right:auto}.accordion-menu .is-accordion-submenu-parent[aria-expanded=true]>a:after{-webkit-transform:rotate(180deg);-ms-transform:rotate(180deg);transform:rotate(180deg);-webkit-transform-origin:50% 50%;-ms-transform-origin:50% 50%;transform-origin:50% 50%}.is-accordion-submenu-parent{position:relative}.has-submenu-toggle>a{margin-right:40px}.submenu-toggle{cursor:pointer;height:40px;position:absolute;right:0;top:0;width:40px}.submenu-toggle:after{border-color:#1779ba transparent transparent;border-style:solid;border-width:6px 6px 0;bottom:0;content:"";display:block;height:0;margin:auto;top:0;width:0}.submenu-toggle[aria-expanded=true]:after{-webkit-transform:scaleY(-1);-ms-transform:scaleY(-1);transform:scaleY(-1);-webkit-transform-origin:50% 50%;-ms-transform-origin:50% 50%;transform-origin:50% 50%}.submenu-toggle-text{clip:rect(0,0,0,0)!important;border:0!important;height:1px!important;overflow:hidden!important;padding:0!important;position:absolute!important;white-space:nowrap!important;width:1px!important}.is-drilldown{overflow:hidden;position:relative}.is-drilldown li{display:block}.is-drilldown.animate-height{-webkit-transition:height .5s;transition:height .5s}.drilldown a{background:#fefefe;padding:.7rem 1rem}.drilldown .is-drilldown-submenu{background:#fefefe;left:100%;position:absolute;top:0;-webkit-transition:-webkit-transform .15s linear;transition:-webkit-transform .15s linear;transition:transform .15s linear;transition:transform .15s linear,-webkit-transform .15s linear;width:100%;z-index:-1}.drilldown .is-drilldown-submenu.is-active{display:block;-webkit-transform:translateX(-100%);-ms-transform:translateX(-100%);transform:translateX(-100%);z-index:1}.drilldown .is-drilldown-submenu.is-closing{-webkit-transform:translateX(100%);-ms-transform:translateX(100%);transform:translateX(100%)}.drilldown .is-drilldown-submenu a{padding:.7rem 1rem}.drilldown .nested.is-drilldown-submenu{margin-left:0;margin-right:0}.drilldown .drilldown-submenu-cover-previous{min-height:100%}.drilldown .is-drilldown-submenu-parent>a{position:relative}.drilldown .is-drilldown-submenu-parent>a:after{border-color:transparent transparent transparent #1779ba;border-style:solid;border-width:6px 0 6px 6px;content:"";display:block;height:0;margin-top:-6px;position:absolute;right:1rem;top:50%;width:0}.drilldown.align-left .is-drilldown-submenu-parent>a:after{border-color:transparent transparent transparent #1779ba;border-style:solid;border-width:6px 0 6px 6px;content:"";display:block;height:0;left:auto;right:1rem;width:0}.drilldown.align-right .is-drilldown-submenu-parent>a:after{border-color:transparent #1779ba transparent transparent;border-style:solid;border-width:6px 6px 6px 0;content:"";display:block;height:0;left:1rem;right:auto;width:0}.drilldown .js-drilldown-back>a:before{border-color:transparent #1779ba transparent transparent;border-style:solid;border-width:6px 6px 6px 0;content:"";display:block;display:inline-block;height:0;margin-right:.75rem;vertical-align:middle;width:0}.dropdown.menu>li.opens-left>.is-dropdown-submenu{left:auto;right:0;top:100%}.dropdown.menu>li.opens-right>.is-dropdown-submenu{left:0;right:auto;top:100%}.dropdown.menu>li.is-dropdown-submenu-parent>a{padding-right:1.5rem;position:relative}.dropdown.menu>li.is-dropdown-submenu-parent>a:after{border-color:#1779ba transparent transparent;border-style:solid;border-width:6px 6px 0;content:"";display:block;height:0;left:auto;margin-top:-3px;right:5px;width:0}[data-whatinput=mouse] .dropdown.menu a{outline:0}.dropdown.menu>li>a{padding:.7rem 1rem}.dropdown.menu>li.is-active>a{background:0 0;color:#1779ba}.no-js .dropdown.menu ul{display:none}.dropdown.menu .nested.is-dropdown-submenu{margin-left:0;margin-right:0}.dropdown.menu.vertical>li .is-dropdown-submenu{top:0}.dropdown.menu.vertical>li.opens-left>.is-dropdown-submenu{left:auto;right:100%;top:0}.dropdown.menu.vertical>li.opens-right>.is-dropdown-submenu{left:100%;right:auto}.dropdown.menu.vertical>li>a:after{right:14px}.dropdown.menu.vertical>li.opens-left>a:after{border-color:transparent #1779ba transparent transparent;border-style:solid;border-width:6px 6px 6px 0;content:"";display:block;height:0;left:5px;right:auto;width:0}.dropdown.menu.vertical>li.opens-right>a:after{border-color:transparent transparent transparent #1779ba;border-style:solid;border-width:6px 0 6px 6px;content:"";display:block;height:0;width:0}@media print,screen and (min-width:40em){.dropdown.menu.medium-horizontal>li.opens-left>.is-dropdown-submenu{left:auto;right:0;top:100%}.dropdown.menu.medium-horizontal>li.opens-right>.is-dropdown-submenu{left:0;right:auto;top:100%}.dropdown.menu.medium-horizontal>li.is-dropdown-submenu-parent>a{padding-right:1.5rem;position:relative}.dropdown.menu.medium-horizontal>li.is-dropdown-submenu-parent>a:after{border-color:#1779ba transparent transparent;border-style:solid;border-width:6px 6px 0;content:"";display:block;height:0;left:auto;margin-top:-3px;right:5px;width:0}.dropdown.menu.medium-vertical>li .is-dropdown-submenu{top:0}.dropdown.menu.medium-vertical>li.opens-left>.is-dropdown-submenu{left:auto;right:100%;top:0}.dropdown.menu.medium-vertical>li.opens-right>.is-dropdown-submenu{left:100%;right:auto}.dropdown.menu.medium-vertical>li>a:after{right:14px}.dropdown.menu.medium-vertical>li.opens-left>a:after{border-color:transparent #1779ba transparent transparent;border-style:solid;border-width:6px 6px 6px 0;content:"";display:block;height:0;left:5px;right:auto;width:0}.dropdown.menu.medium-vertical>li.opens-right>a:after{border-color:transparent transparent transparent #1779ba;border-style:solid;border-width:6px 0 6px 6px;content:"";display:block;height:0;width:0}}@media print,screen and (min-width:64em){.dropdown.menu.large-horizontal>li.opens-left>.is-dropdown-submenu{left:auto;right:0;top:100%}.dropdown.menu.large-horizontal>li.opens-right>.is-dropdown-submenu{left:0;right:auto;top:100%}.dropdown.menu.large-horizontal>li.is-dropdown-submenu-parent>a{padding-right:1.5rem;position:relative}.dropdown.menu.large-horizontal>li.is-dropdown-submenu-parent>a:after{border-color:#1779ba transparent transparent;border-style:solid;border-width:6px 6px 0;content:"";display:block;height:0;left:auto;margin-top:-3px;right:5px;width:0}.dropdown.menu.large-vertical>li .is-dropdown-submenu{top:0}.dropdown.menu.large-vertical>li.opens-left>.is-dropdown-submenu{left:auto;right:100%;top:0}.dropdown.menu.large-vertical>li.opens-right>.is-dropdown-submenu{left:100%;right:auto}.dropdown.menu.large-vertical>li>a:after{right:14px}.dropdown.menu.large-vertical>li.opens-left>a:after{border-color:transparent #1779ba transparent transparent;border-style:solid;border-width:6px 6px 6px 0;content:"";display:block;height:0;left:5px;right:auto;width:0}.dropdown.menu.large-vertical>li.opens-right>a:after{border-color:transparent transparent transparent #1779ba;border-style:solid;border-width:6px 0 6px 6px;content:"";display:block;height:0;width:0}}.dropdown.menu.align-right .is-dropdown-submenu.first-sub{left:auto;right:0;top:100%}.is-dropdown-menu.vertical{width:100px}.is-dropdown-menu.vertical.align-right{float:right}.is-dropdown-submenu-parent{position:relative}.is-dropdown-submenu-parent a:after{left:auto;margin-top:-6px;position:absolute;right:5px;top:50%}.is-dropdown-submenu-parent.opens-inner>.is-dropdown-submenu{left:auto;top:100%}.is-dropdown-submenu-parent.opens-left>.is-dropdown-submenu{left:auto;right:100%}.is-dropdown-submenu-parent.opens-right>.is-dropdown-submenu{left:100%;right:auto}.is-dropdown-submenu{background:#fefefe;border:1px solid #cacaca;display:none;left:100%;min-width:200px;position:absolute;top:0;z-index:1}.dropdown .is-dropdown-submenu a{padding:.7rem 1rem}.is-dropdown-submenu .is-dropdown-submenu-parent>a:after{right:14px}.is-dropdown-submenu .is-dropdown-submenu-parent.opens-left>a:after{border-color:transparent #1779ba transparent transparent;border-style:solid;border-width:6px 6px 6px 0;content:"";display:block;height:0;left:5px;right:auto;width:0}.is-dropdown-submenu .is-dropdown-submenu-parent.opens-right>a:after{border-color:transparent transparent transparent #1779ba;border-style:solid;border-width:6px 0 6px 6px;content:"";display:block;height:0;width:0}.is-dropdown-submenu .is-dropdown-submenu{margin-top:-1px}.is-dropdown-submenu>li{width:100%}.is-dropdown-submenu.js-dropdown-active{display:block}.is-off-canvas-open{overflow:hidden}.js-off-canvas-overlay{background:hsla(0,0%,100%,.25);height:100%;left:0;opacity:0;overflow:hidden;position:absolute;top:0;-webkit-transition:opacity .5s ease,visibility .5s ease;transition:opacity .5s ease,visibility .5s ease;visibility:hidden;width:100%;z-index:11}.js-off-canvas-overlay.is-visible{opacity:1;visibility:visible}.js-off-canvas-overlay.is-closable{cursor:pointer}.js-off-canvas-overlay.is-overlay-absolute{position:absolute}.js-off-canvas-overlay.is-overlay-fixed{position:fixed}.off-canvas-wrapper{overflow:hidden;position:relative}.off-canvas{-webkit-backface-visibility:hidden;backface-visibility:hidden;background:#e6e6e6;position:fixed;-webkit-transition:-webkit-transform .5s ease;transition:-webkit-transform .5s ease;transition:transform .5s ease;transition:transform .5s ease,-webkit-transform .5s ease;z-index:12}[data-whatinput=mouse] .off-canvas{outline:0}.off-canvas.is-transition-push{z-index:12}.off-canvas.is-closed{visibility:hidden}.off-canvas.is-transition-overlap{z-index:13}.off-canvas.is-transition-overlap.is-open{-webkit-box-shadow:0 0 10px hsla(0,0%,4%,.7);box-shadow:0 0 10px hsla(0,0%,4%,.7)}.off-canvas.is-open{-webkit-transform:translate(0);-ms-transform:translate(0);transform:translate(0)}.off-canvas-absolute{-webkit-backface-visibility:hidden;backface-visibility:hidden;background:#e6e6e6;position:absolute;-webkit-transition:-webkit-transform .5s ease;transition:-webkit-transform .5s ease;transition:transform .5s ease;transition:transform .5s ease,-webkit-transform .5s ease;z-index:12}[data-whatinput=mouse] .off-canvas-absolute{outline:0}.off-canvas-absolute.is-transition-push{z-index:12}.off-canvas-absolute.is-closed{visibility:hidden}.off-canvas-absolute.is-transition-overlap{z-index:13}.off-canvas-absolute.is-transition-overlap.is-open{-webkit-box-shadow:0 0 10px hsla(0,0%,4%,.7);box-shadow:0 0 10px hsla(0,0%,4%,.7)}.off-canvas-absolute.is-open{-webkit-transform:translate(0);-ms-transform:translate(0);transform:translate(0)}.position-left{-webkit-overflow-scrolling:touch;height:100%;left:0;overflow-y:auto;top:0;width:250px}.off-canvas-content .off-canvas.position-left,.position-left{-webkit-transform:translateX(-250px);-ms-transform:translateX(-250px);transform:translateX(-250px)}.off-canvas-content .off-canvas.position-left.is-transition-overlap.is-open{-webkit-transform:translate(0);-ms-transform:translate(0);transform:translate(0)}.off-canvas-content.is-open-left.has-transition-push{-webkit-transform:translateX(250px);-ms-transform:translateX(250px);transform:translateX(250px)}.position-left.is-transition-push{-webkit-box-shadow:inset -13px 0 20px -13px hsla(0,0%,4%,.25);box-shadow:inset -13px 0 20px -13px hsla(0,0%,4%,.25)}.position-right{-webkit-overflow-scrolling:touch;height:100%;overflow-y:auto;right:0;top:0;width:250px}.off-canvas-content .off-canvas.position-right,.position-right{-webkit-transform:translateX(250px);-ms-transform:translateX(250px);transform:translateX(250px)}.off-canvas-content .off-canvas.position-right.is-transition-overlap.is-open{-webkit-transform:translate(0);-ms-transform:translate(0);transform:translate(0)}.off-canvas-content.is-open-right.has-transition-push{-webkit-transform:translateX(-250px);-ms-transform:translateX(-250px);transform:translateX(-250px)}.position-right.is-transition-push{-webkit-box-shadow:inset 13px 0 20px -13px hsla(0,0%,4%,.25);box-shadow:inset 13px 0 20px -13px hsla(0,0%,4%,.25)}.position-top{-webkit-overflow-scrolling:touch;height:250px;left:0;overflow-x:auto;top:0;width:100%}.off-canvas-content .off-canvas.position-top,.position-top{-webkit-transform:translateY(-250px);-ms-transform:translateY(-250px);transform:translateY(-250px)}.off-canvas-content .off-canvas.position-top.is-transition-overlap.is-open{-webkit-transform:translate(0);-ms-transform:translate(0);transform:translate(0)}.off-canvas-content.is-open-top.has-transition-push{-webkit-transform:translateY(250px);-ms-transform:translateY(250px);transform:translateY(250px)}.position-top.is-transition-push{-webkit-box-shadow:inset 0 -13px 20px -13px hsla(0,0%,4%,.25);box-shadow:inset 0 -13px 20px -13px hsla(0,0%,4%,.25)}.position-bottom{-webkit-overflow-scrolling:touch;bottom:0;height:250px;left:0;overflow-x:auto;width:100%}.off-canvas-content .off-canvas.position-bottom,.position-bottom{-webkit-transform:translateY(250px);-ms-transform:translateY(250px);transform:translateY(250px)}.off-canvas-content .off-canvas.position-bottom.is-transition-overlap.is-open{-webkit-transform:translate(0);-ms-transform:translate(0);transform:translate(0)}.off-canvas-content.is-open-bottom.has-transition-push{-webkit-transform:translateY(-250px);-ms-transform:translateY(-250px);transform:translateY(-250px)}.position-bottom.is-transition-push{-webkit-box-shadow:inset 0 13px 20px -13px hsla(0,0%,4%,.25);box-shadow:inset 0 13px 20px -13px hsla(0,0%,4%,.25)}.off-canvas-content{-webkit-backface-visibility:hidden;backface-visibility:hidden;-webkit-transform:none;-ms-transform:none;transform:none}.off-canvas-content.has-transition-overlap,.off-canvas-content.has-transition-push{-webkit-transition:-webkit-transform .5s ease;transition:-webkit-transform .5s ease;transition:transform .5s ease;transition:transform .5s ease,-webkit-transform .5s ease}.off-canvas-content.has-transition-push,.off-canvas-content .off-canvas.is-open{-webkit-transform:translate(0);-ms-transform:translate(0);transform:translate(0)}@media print,screen and (min-width:40em){.position-left.reveal-for-medium{-webkit-transform:none;-ms-transform:none;transform:none;-webkit-transition:none;transition:none;visibility:visible;z-index:12}.position-left.reveal-for-medium .close-button{display:none}.off-canvas-content .position-left.reveal-for-medium{-webkit-transform:none;-ms-transform:none;transform:none}.off-canvas-content.has-reveal-left{margin-left:250px}.position-left.reveal-for-medium~.off-canvas-content{margin-left:250px}.position-right.reveal-for-medium{-webkit-transform:none;-ms-transform:none;transform:none;-webkit-transition:none;transition:none;visibility:visible;z-index:12}.position-right.reveal-for-medium .close-button{display:none}.off-canvas-content .position-right.reveal-for-medium{-webkit-transform:none;-ms-transform:none;transform:none}.off-canvas-content.has-reveal-right{margin-right:250px}.position-right.reveal-for-medium~.off-canvas-content{margin-right:250px}.position-top.reveal-for-medium{-webkit-transform:none;-ms-transform:none;transform:none;-webkit-transition:none;transition:none;visibility:visible;z-index:12}.position-top.reveal-for-medium .close-button{display:none}.off-canvas-content .position-top.reveal-for-medium{-webkit-transform:none;-ms-transform:none;transform:none}.off-canvas-content.has-reveal-top{margin-top:250px}.position-top.reveal-for-medium~.off-canvas-content{margin-top:250px}.position-bottom.reveal-for-medium{-webkit-transform:none;-ms-transform:none;transform:none;-webkit-transition:none;transition:none;visibility:visible;z-index:12}.position-bottom.reveal-for-medium .close-button{display:none}.off-canvas-content .position-bottom.reveal-for-medium{-webkit-transform:none;-ms-transform:none;transform:none}.off-canvas-content.has-reveal-bottom{margin-bottom:250px}.position-bottom.reveal-for-medium~.off-canvas-content{margin-bottom:250px}}@media print,screen and (min-width:64em){.position-left.reveal-for-large{-webkit-transform:none;-ms-transform:none;transform:none;-webkit-transition:none;transition:none;visibility:visible;z-index:12}.position-left.reveal-for-large .close-button{display:none}.off-canvas-content .position-left.reveal-for-large{-webkit-transform:none;-ms-transform:none;transform:none}.off-canvas-content.has-reveal-left{margin-left:250px}.position-left.reveal-for-large~.off-canvas-content{margin-left:250px}.position-right.reveal-for-large{-webkit-transform:none;-ms-transform:none;transform:none;-webkit-transition:none;transition:none;visibility:visible;z-index:12}.position-right.reveal-for-large .close-button{display:none}.off-canvas-content .position-right.reveal-for-large{-webkit-transform:none;-ms-transform:none;transform:none}.off-canvas-content.has-reveal-right{margin-right:250px}.position-right.reveal-for-large~.off-canvas-content{margin-right:250px}.position-top.reveal-for-large{-webkit-transform:none;-ms-transform:none;transform:none;-webkit-transition:none;transition:none;visibility:visible;z-index:12}.position-top.reveal-for-large .close-button{display:none}.off-canvas-content .position-top.reveal-for-large{-webkit-transform:none;-ms-transform:none;transform:none}.off-canvas-content.has-reveal-top{margin-top:250px}.position-top.reveal-for-large~.off-canvas-content{margin-top:250px}.position-bottom.reveal-for-large{-webkit-transform:none;-ms-transform:none;transform:none;-webkit-transition:none;transition:none;visibility:visible;z-index:12}.position-bottom.reveal-for-large .close-button{display:none}.off-canvas-content .position-bottom.reveal-for-large{-webkit-transform:none;-ms-transform:none;transform:none}.off-canvas-content.has-reveal-bottom{margin-bottom:250px}.position-bottom.reveal-for-large~.off-canvas-content{margin-bottom:250px}}@media print,screen and (min-width:40em){.off-canvas.in-canvas-for-medium{background:0 0;height:auto;overflow:visible;position:static;-webkit-transition:none;transition:none;visibility:visible;width:auto}.off-canvas.in-canvas-for-medium.position-bottom,.off-canvas.in-canvas-for-medium.position-left,.off-canvas.in-canvas-for-medium.position-right,.off-canvas.in-canvas-for-medium.position-top{-webkit-box-shadow:none;box-shadow:none;-webkit-transform:none;-ms-transform:none;transform:none}.off-canvas.in-canvas-for-medium .close-button{display:none}}@media print,screen and (min-width:64em){.off-canvas.in-canvas-for-large{background:0 0;height:auto;overflow:visible;position:static;-webkit-transition:none;transition:none;visibility:visible;width:auto}.off-canvas.in-canvas-for-large.position-bottom,.off-canvas.in-canvas-for-large.position-left,.off-canvas.in-canvas-for-large.position-right,.off-canvas.in-canvas-for-large.position-top{-webkit-box-shadow:none;box-shadow:none;-webkit-transform:none;-ms-transform:none;transform:none}.off-canvas.in-canvas-for-large .close-button{display:none}}html.is-reveal-open{overflow-y:hidden;position:fixed;width:100%}html.is-reveal-open.zf-has-scroll{-webkit-overflow-scrolling:touch;overflow-y:scroll}html.is-reveal-open body{overflow-y:hidden}.reveal-overlay{background-color:hsla(0,0%,4%,.45);bottom:0;left:0;position:fixed;right:0;top:0;z-index:1005}.reveal,.reveal-overlay{-webkit-overflow-scrolling:touch;display:none;overflow-y:auto}.reveal{-webkit-backface-visibility:hidden;backface-visibility:hidden;background-color:#fefefe;border:1px solid #cacaca;border-radius:0;margin-left:auto;margin-right:auto;padding:1rem;position:relative;top:100px;z-index:1006}[data-whatinput=mouse] .reveal{outline:0}@media print,screen and (min-width:40em){.reveal{min-height:0}}.reveal .column{min-width:0}.reveal>:last-child{margin-bottom:0}@media print,screen and (min-width:40em){.reveal{max-width:75rem;width:600px}}.reveal.collapse{padding:0}@media print,screen and (min-width:40em){.reveal.tiny{max-width:75rem;width:30%}.reveal.small{max-width:75rem;width:50%}.reveal.large{max-width:75rem;width:90%}}.reveal.full{border:0;border-radius:0;bottom:0;height:100%;left:0;margin-left:0;max-width:none;min-height:100%;right:0;top:0;width:100%}@media print,screen and (max-width:39.99875em){.reveal{border:0;border-radius:0;bottom:0;height:100%;left:0;margin-left:0;max-width:none;min-height:100%;right:0;top:0;width:100%}}.reveal.without-overlay{position:fixed}.sticky,.sticky-container{position:relative}.sticky{-webkit-transform:translateZ(0);transform:translateZ(0);z-index:0}.sticky.is-stuck{position:fixed;width:100%;z-index:5}.sticky.is-stuck.is-at-top{top:0}.sticky.is-stuck.is-at-bottom{bottom:0}.sticky.is-anchored{left:auto;position:relative;right:auto}.sticky.is-anchored.is-at-bottom{bottom:0}.title-bar{-webkit-box-pack:start;-ms-flex-pack:start;-webkit-box-align:center;-ms-flex-align:center;-webkit-align-items:center;align-items:center;background:#0a0a0a;color:#fefefe;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-justify-content:flex-start;justify-content:flex-start;padding:.5rem}.title-bar .menu-icon{margin-left:.25rem;margin-right:.25rem}.title-bar-left,.title-bar-right{-webkit-box-flex:1;-webkit-flex:1 1 0px;-ms-flex:1 1 0px;flex:1 1 0px}.title-bar-right{text-align:right}.title-bar-title{display:inline-block;font-weight:700;vertical-align:middle}.top-bar{-webkit-box-pack:justify;-ms-flex-pack:justify;-webkit-box-align:center;-ms-flex-align:center;-webkit-align-items:center;align-items:center;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;-webkit-justify-content:space-between;justify-content:space-between;padding:.5rem}.top-bar,.top-bar ul{background-color:#e6e6e6}.top-bar input{margin-right:1rem;max-width:200px}.top-bar .input-group-field{margin-right:0;width:100%}.top-bar input.button{width:auto}.top-bar .top-bar-left,.top-bar .top-bar-right{-webkit-box-flex:0;-webkit-flex:0 0 100%;-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}@media print,screen and (min-width:40em){.top-bar{-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap}.top-bar .top-bar-left{-webkit-box-flex:1;-webkit-flex:1 1 auto;-ms-flex:1 1 auto;flex:1 1 auto;margin-right:auto}.top-bar .top-bar-right{-webkit-box-flex:0;-webkit-flex:0 1 auto;-ms-flex:0 1 auto;flex:0 1 auto;margin-left:auto}}@media print,screen and (max-width:63.99875em){.top-bar.stacked-for-medium{-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap}.top-bar.stacked-for-medium .top-bar-left,.top-bar.stacked-for-medium .top-bar-right{-webkit-box-flex:0;-webkit-flex:0 0 100%;-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}}@media print,screen and (max-width:74.99875em){.top-bar.stacked-for-large{-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap}.top-bar.stacked-for-large .top-bar-left,.top-bar.stacked-for-large .top-bar-right{-webkit-box-flex:0;-webkit-flex:0 0 100%;-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}}.top-bar-title{margin:.5rem 1rem .5rem 0}.top-bar-left,.top-bar-right,.top-bar-title{-webkit-box-flex:0;-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto}.float-left{float:left!important}.float-right{float:right!important}.float-center{display:block;margin-left:auto;margin-right:auto}.clearfix:after,.clearfix:before{-ms-flex-preferred-size:0;-webkit-box-ordinal-group:2;-ms-flex-order:1;content:" ";display:table;-webkit-flex-basis:0;flex-basis:0;-webkit-order:1;order:1}.clearfix:after{clear:both}.align-left{-webkit-box-pack:start;-ms-flex-pack:start;-webkit-justify-content:flex-start;justify-content:flex-start}.align-right{-webkit-box-pack:end;-ms-flex-pack:end;-webkit-justify-content:flex-end;justify-content:flex-end}.align-center{-webkit-box-pack:center;-ms-flex-pack:center;-webkit-justify-content:center;justify-content:center}.align-justify{-webkit-box-pack:justify;-ms-flex-pack:justify;-webkit-justify-content:space-between;justify-content:space-between}.align-spaced{-ms-flex-pack:distribute;-webkit-justify-content:space-around;justify-content:space-around}.align-left.vertical.menu>li>a{-webkit-box-pack:start;-ms-flex-pack:start;-webkit-justify-content:flex-start;justify-content:flex-start}.align-right.vertical.menu>li>a{-webkit-box-pack:end;-ms-flex-pack:end;-webkit-justify-content:flex-end;justify-content:flex-end}.align-center.vertical.menu>li>a{-webkit-box-pack:center;-ms-flex-pack:center;-webkit-justify-content:center;justify-content:center}.align-top{-webkit-box-align:start;-ms-flex-align:start;-webkit-align-items:flex-start;align-items:flex-start}.align-self-top{-ms-flex-item-align:start;-webkit-align-self:flex-start;align-self:flex-start}.align-bottom{-webkit-box-align:end;-ms-flex-align:end;-webkit-align-items:flex-end;align-items:flex-end}.align-self-bottom{-ms-flex-item-align:end;-webkit-align-self:flex-end;align-self:flex-end}.align-middle{-webkit-box-align:center;-ms-flex-align:center;-webkit-align-items:center;align-items:center}.align-self-middle{-ms-flex-item-align:center;-webkit-align-self:center;align-self:center}.align-stretch{-webkit-box-align:stretch;-ms-flex-align:stretch;-webkit-align-items:stretch;align-items:stretch}.align-self-stretch{-ms-flex-item-align:stretch;-webkit-align-self:stretch;align-self:stretch}.align-center-middle{-webkit-box-pack:center;-ms-flex-pack:center;-webkit-box-align:center;-ms-flex-align:center;-ms-flex-line-pack:center;-webkit-align-content:center;align-content:center;-webkit-align-items:center;align-items:center;-webkit-justify-content:center;justify-content:center}.small-order-1{-webkit-box-ordinal-group:2;-ms-flex-order:1;-webkit-order:1;order:1}.small-order-2{-webkit-box-ordinal-group:3;-ms-flex-order:2;-webkit-order:2;order:2}.small-order-3{-webkit-box-ordinal-group:4;-ms-flex-order:3;-webkit-order:3;order:3}.small-order-4{-webkit-box-ordinal-group:5;-ms-flex-order:4;-webkit-order:4;order:4}.small-order-5{-webkit-box-ordinal-group:6;-ms-flex-order:5;-webkit-order:5;order:5}.small-order-6{-webkit-box-ordinal-group:7;-ms-flex-order:6;-webkit-order:6;order:6}@media print,screen and (min-width:40em){.medium-order-1{-webkit-box-ordinal-group:2;-ms-flex-order:1;-webkit-order:1;order:1}.medium-order-2{-webkit-box-ordinal-group:3;-ms-flex-order:2;-webkit-order:2;order:2}.medium-order-3{-webkit-box-ordinal-group:4;-ms-flex-order:3;-webkit-order:3;order:3}.medium-order-4{-webkit-box-ordinal-group:5;-ms-flex-order:4;-webkit-order:4;order:4}.medium-order-5{-webkit-box-ordinal-group:6;-ms-flex-order:5;-webkit-order:5;order:5}.medium-order-6{-webkit-box-ordinal-group:7;-ms-flex-order:6;-webkit-order:6;order:6}}@media print,screen and (min-width:64em){.large-order-1{-webkit-box-ordinal-group:2;-ms-flex-order:1;-webkit-order:1;order:1}.large-order-2{-webkit-box-ordinal-group:3;-ms-flex-order:2;-webkit-order:2;order:2}.large-order-3{-webkit-box-ordinal-group:4;-ms-flex-order:3;-webkit-order:3;order:3}.large-order-4{-webkit-box-ordinal-group:5;-ms-flex-order:4;-webkit-order:4;order:4}.large-order-5{-webkit-box-ordinal-group:6;-ms-flex-order:5;-webkit-order:5;order:5}.large-order-6{-webkit-box-ordinal-group:7;-ms-flex-order:6;-webkit-order:6;order:6}}.flex-container{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex}.flex-child-auto{-webkit-box-flex:1;-webkit-flex:1 1 auto;-ms-flex:1 1 auto;flex:1 1 auto}.flex-child-grow{-webkit-box-flex:1;-webkit-flex:1 0 auto;-ms-flex:1 0 auto;flex:1 0 auto}.flex-child-shrink{-webkit-box-flex:0;-webkit-flex:0 1 auto;-ms-flex:0 1 auto;flex:0 1 auto}.flex-dir-row{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row}.flex-dir-row-reverse{-webkit-box-orient:horizontal;-webkit-box-direction:reverse;-webkit-flex-direction:row-reverse;-ms-flex-direction:row-reverse;flex-direction:row-reverse}.flex-dir-column{-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column}.flex-dir-column-reverse{-webkit-box-orient:vertical;-webkit-box-direction:reverse;-webkit-flex-direction:column-reverse;-ms-flex-direction:column-reverse;flex-direction:column-reverse}@media print,screen and (min-width:40em){.medium-flex-container{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex}.medium-flex-child-auto{-webkit-box-flex:1;-webkit-flex:1 1 auto;-ms-flex:1 1 auto;flex:1 1 auto}.medium-flex-child-grow{-webkit-box-flex:1;-webkit-flex:1 0 auto;-ms-flex:1 0 auto;flex:1 0 auto}.medium-flex-child-shrink{-webkit-box-flex:0;-webkit-flex:0 1 auto;-ms-flex:0 1 auto;flex:0 1 auto}.medium-flex-dir-row{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row}.medium-flex-dir-row-reverse{-webkit-box-orient:horizontal;-webkit-box-direction:reverse;-webkit-flex-direction:row-reverse;-ms-flex-direction:row-reverse;flex-direction:row-reverse}.medium-flex-dir-column{-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column}.medium-flex-dir-column-reverse{-webkit-box-orient:vertical;-webkit-box-direction:reverse;-webkit-flex-direction:column-reverse;-ms-flex-direction:column-reverse;flex-direction:column-reverse}}@media print,screen and (min-width:64em){.large-flex-container{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex}.large-flex-child-auto{-webkit-box-flex:1;-webkit-flex:1 1 auto;-ms-flex:1 1 auto;flex:1 1 auto}.large-flex-child-grow{-webkit-box-flex:1;-webkit-flex:1 0 auto;-ms-flex:1 0 auto;flex:1 0 auto}.large-flex-child-shrink{-webkit-box-flex:0;-webkit-flex:0 1 auto;-ms-flex:0 1 auto;flex:0 1 auto}.large-flex-dir-row{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row}.large-flex-dir-row-reverse{-webkit-box-orient:horizontal;-webkit-box-direction:reverse;-webkit-flex-direction:row-reverse;-ms-flex-direction:row-reverse;flex-direction:row-reverse}.large-flex-dir-column{-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column}.large-flex-dir-column-reverse{-webkit-box-orient:vertical;-webkit-box-direction:reverse;-webkit-flex-direction:column-reverse;-ms-flex-direction:column-reverse;flex-direction:column-reverse}}.hide{display:none!important}.invisible{visibility:hidden}.visible{visibility:visible}@media print,screen and (max-width:39.99875em){.hide-for-small-only{display:none!important}}@media screen and (max-width:0em),screen and (min-width:40em){.show-for-small-only{display:none!important}}@media print,screen and (min-width:40em){.hide-for-medium{display:none!important}}@media screen and (max-width:39.99875em){.show-for-medium{display:none!important}}@media print,screen and (min-width:40em)and (max-width:63.99875em){.hide-for-medium-only{display:none!important}}@media screen and (max-width:39.99875em),screen and (min-width:64em){.show-for-medium-only{display:none!important}}@media print,screen and (min-width:64em){.hide-for-large{display:none!important}}@media screen and (max-width:63.99875em){.show-for-large{display:none!important}}@media print,screen and (min-width:64em)and (max-width:74.99875em){.hide-for-large-only{display:none!important}}@media screen and (max-width:63.99875em),screen and (min-width:75em){.show-for-large-only{display:none!important}}.show-for-sr,.show-on-focus{clip:rect(0,0,0,0)!important;border:0!important;height:1px!important;overflow:hidden!important;padding:0!important;position:absolute!important;white-space:nowrap!important;width:1px!important}.show-on-focus:active,.show-on-focus:focus{clip:auto!important;height:auto!important;overflow:visible!important;position:static!important;white-space:normal!important;width:auto!important}.hide-for-portrait,.show-for-landscape{display:block!important}@media screen and (orientation:landscape){.hide-for-portrait,.show-for-landscape{display:block!important}}@media screen and (orientation:portrait){.hide-for-portrait,.show-for-landscape{display:none!important}}.hide-for-landscape,.show-for-portrait{display:none!important}@media screen and (orientation:landscape){.hide-for-landscape,.show-for-portrait{display:none!important}}@media screen and (orientation:portrait){.hide-for-landscape,.show-for-portrait{display:block!important}}.show-for-dark-mode{display:none}.hide-for-dark-mode{display:block}@media screen and (prefers-color-scheme:dark){.show-for-dark-mode{display:block!important}.hide-for-dark-mode{display:none!important}}.show-for-ie{display:none}@media (-ms-high-contrast:active),(-ms-high-contrast:none){.show-for-ie{display:block!important}.hide-for-ie{display:none!important}}.show-for-sticky{display:none}.is-stuck .show-for-sticky{display:block}.is-stuck .hide-for-sticky{display:none}@font-face{font-display:"swap";font-family:FontAwesome}html{box-sizing:border-box}body{font-family:Roboto,sans-serif;font-size:16px;line-height:1}*,:after,:before{box-sizing:inherit}a{color:#3c4fe0}a.reference:after{font-family:FontAwesome;font-size:12px;padding:0 4px}a.reference.external:after{content:""}a.reference.download:after{content:""}a:hover{color:#3c4fe0;font-weight:500}.headerlink{margin-left:5px;visibility:hidden}.toc-backref:hover{color:#23263b}h1,h2,h3,h4,h5,h6{font-family:Roboto,sans-serif;font-size:16px;font-weight:500;letter-spacing:.2px;line-height:24px;margin-bottom:16px}h1:hover>a.headerlink,h2:hover>a.headerlink,h3:hover>a.headerlink,h4:hover>a.headerlink,h5:hover>a.headerlink,h6:hover>a.headerlink{visibility:visible}h1 a,h2 a,h3 a,h4 a,h5 a,h6 a{color:inherit}h1{font-size:32px;font-weight:700;line-height:40px;margin-bottom:28px}h2{font-size:24px;line-height:32px}h3{font-size:20px}h4{font-size:18px}h5{font-size:16px}h6{font-weight:400}img{max-width:100%}button:focus{outline:0}blockquote{border:0;margin:0;padding:0}blockquote,blockquote p,cite{color:inherit}cite{display:inline;font-size:inherit}cite:before{content:""}.show{display:block!important}.centered{display:block;margin:0 auto}.break{flex-basis:100%;height:0}@media screen and (min-width:1024px){h1{font-size:36px}}.admonition-title:before,.contents.local>ul>li a:before,.scylla-icon,.secondary-side-nav__content li a:before{background-repeat:no-repeat;background-size:contain;display:inline-block;filter:brightness(0);vertical-align:middle}.scylla-icon--about-team{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMSwuY2xzLTJ7ZmlsbDpub25lO3N0cm9rZTpncmF5O3N0cm9rZS1taXRlcmxpbWl0OjEwfS5jbHMtMntzdHJva2UtbGluZWNhcDpyb3VuZH08L3N0eWxlPjwvZGVmcz48ZyBpZD0iQ2FscXVlXzQiIGRhdGEtbmFtZT0iQ2FscXVlIDQiPjxwYXRoIGNsYXNzPSJjbHMtMSIgZD0iTTQuNjYgOS44MSAyLjYzIDExYTIuMDggMi4wOCAwIDAgMC0xLjEzIDEuODN2Ny44MWMuMTkgMS4xMS41IDEuNTMgMS41IDEuNDdNNy4wNiA5Ljk0bDEuNDQuOTQiLz48cGF0aCBjbGFzcz0iY2xzLTIiIGQ9Ik0zLjUgMTguNXY1LjM0TTkuNSAxOC41djUuMzRNOC41NCAxOC40MnY1LjMzTTE1LjUgMTguNXY1LjM0TTE2LjUgMTguNXY1LjM0TTMuMzMgMjAuNTNoNS4wOE0xMS40NSA4Ljg0bC4wNi4wNmExLjY1IDEuNjUgMCAwIDAgMi4zNCAwaDAiLz48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Ik0xMi40MiA3LjVhMS44MSAxLjgxIDAgMCAxLTEuOTItMS43N1Y1YTEuOTQgMS45NCAwIDAgMSAxLjkyLTIgMi4wNyAyLjA3IDAgMCAxIDIuMDggMnYuNzdhMiAyIDAgMCAxLTIuMDggMS43M1pNMTEuNDIgOC43NCA5LjYzIDkuOWEyLjA3IDIuMDcgMCAwIDAtMS4xMyAxLjg1djcuODJBMS40NyAxLjQ3IDAgMCAwIDEwIDIxTTEzLjc1IDkuMThsMiAuNjVjLjcuMzUuNzYgMS4wNi43NiAxLjg0djcuOWMwIC43Ny0uMjMgMS4yNC0xIDEuMjQiLz48cGF0aCBjbGFzcz0iY2xzLTIiIGQ9Ik05LjkzIDE5LjVoNS40Ii8+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNMTkuNDIgOS4xMmEyLjA3IDIuMDcgMCAwIDAgMi4wOC0xLjkzdi0uNzdhMi4wNyAyLjA3IDAgMCAwLTIuMDgtMS45MiAxLjkzIDEuOTMgMCAwIDAtMS45MiAxLjkydi43N2ExLjk0IDEuOTQgMCAwIDAgMS45MiAxLjkzWk01LjU5IDkuMTJhMS45MyAxLjkzIDAgMCAwIDEuOTItMS45M3YtLjc3QTEuOTMgMS45MyAwIDAgMCA1LjU5IDQuNSAyLjA4IDIuMDggMCAwIDAgMy41IDYuNDJ2Ljc3YTIuMDggMi4wOCAwIDAgMCAyLjA5IDEuOTNaTTIwLjQ0IDkuODFsMiAxLjE3YTIuMDYgMi4wNiAwIDAgMSAxLjEzIDEuODV2Ny44MWMtLjE4IDEuMTEtLjQ3IDEuNTMtMS40NyAxLjQ3TTE4LjA0IDkuOTRsLTEuNDQuOTMiLz48cGF0aCBjbGFzcz0iY2xzLTIiIGQ9Ik0yMS42IDE4LjV2NS4zNE0yMS43NyAyMC41M2gtNS4wOCIvPjwvZz48L3N2Zz4=)}.scylla-icon--about-us{background-image:url(data:image/svg+xml;base64,PHN2ZyBpZD0iTGF5ZXJfMyIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB2aWV3Qm94PSIwIDAgMjAgMjAiPjxkZWZzPjxzdHlsZT4uY2xzLTF7ZmlsbDpub25lO3N0cm9rZTojMDAwO3N0cm9rZS1saW5lY2FwOnJvdW5kO3N0cm9rZS1saW5lam9pbjpyb3VuZDtzdHJva2Utd2lkdGg6LjhweH08L3N0eWxlPjwvZGVmcz48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Ik02LjI4IDE5LjQ4Yy0uMTIuMDgtLjA4LjA3LS4yMy4xLS41OC4wOS0xLjEyLS4yOC0xLjI1LS44NCAwIDAtMi4zLTkuMTgtMi4zLTExLjExQzIuNSAzLjYgNS44OC40NCAxMC4zOC40NFMxNy41IDMuNDggMTcuNSA3LjVjMCAxLjkzLTEuMzIgMTEuMjMtMS4zMiAxMS4yMy0uMTMuNTYtLjY3Ljk0LTEuMjUuODQtLjEyLS4wMi0uMTMgMC0uMjMtLjA3Ii8+PHBhdGggZD0iTTE1Ljc1IDE1Ljc1Yy0uMTcgMS4xNS0uMjIgMi4zNC0uNTUgMy40Ni0uMzcuODUtMS42MyAxLjA2LTIuMjIuMzMtLjI1LS4yOC4xOS0uNjguNDQtLjQuNDMuNDYgMS4yNC4xOCAxLjMxLS40NGwuMDYtLjM0Yy4xOS0uODkuMzUtMS43OS41Ny0yLjY4LjA1LS4yNC40Mi0uMTcuMzkuMDdaIi8+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNMTEuNSA3YzAgMS45LTEuNTYgMy41LTMuNDYgMy41UzQuNSA4LjkgNC41IDdzMS42NC0zLjUgMy41NC0zLjVTMTEuNSA1LjEgMTEuNSA3WiIvPjxwYXRoIGQ9Ik04LjU1IDQuNzVjLS41OS4xMi0uNzEgMS40Mi0uMzYgMS43OC4yMy4yMy43MS4zMS43MS40N3MtLjQ4LjI0LS43MS40N2MtLjM2LjM2LS4yNCAxLjY2LjM2IDEuNzguNzEuMTQgMS43OC0uNzEgMS43OC0yLjI1UzkuMjYgNC42MSA4LjU1IDQuNzVaTTYuNTEgMTIuMmMyLjEyLjMxIDQuMzQtLjIgNS42OC0xLjk2LjMyLS40MS45Ni4xMS42Mi41MS0uNzYuOS0xLjc4IDEuNjMtMi45MyAxLjk1LTEuMTQuMzMtMi4zMy4zMS0zLjQ2LjE2YS4zNC4zNCAwIDAgMS0uMjktLjM4Yy4wMi0uMTguMTktLjMxLjM3LS4yOVpNNy45NyAxOS41OWMtLjk5Ljk2LTIuMzYuMDgtMi4zNi0xLjE1LS4xMi0uOS0uMjctMS43OS0uMzctMi42OS0uMDEtLjExLjA3LS4yMS4xOC0uMjIuMS0uMDEuMTkuMDYuMjEuMTUuMjIuODguMzggMS43Ny41NiAyLjY2LjAxLjc4LjY4IDEuMzggMS4zNS44My4yNy0uMjcuNjkuMTYuNDIuNDNaIi8+PHBhdGggZD0iTTkuNzUgMTkuMjdjLS40Mi45LTEuOC45Ni0yLjMyLjExLS41LTEuMTMtLjMxLTIuNS0uNDctMy43MiAwLS4xMS4wOC0uMi4xOS0uMjEuMSAwIC4xOS4wNy4yMS4xNy4xNy45NS4yOCAxLjkxLjQyIDIuODcuMDEuNDUuMjMuNzQuNTcuODUuMzMuMS43MS0uMDUuODgtLjM2LjE4LS4zNC43MS0uMDUuNTIuMjlaTTE0LjAzIDE1LjY2Yy0uMTYgMS4yMy4wMyAyLjU3LS40NiAzLjcyLS41Mi44Ni0xLjkxLjc5LTIuMzItLjExLS4xNy0uMzQuMzUtLjYxLjUzLS4yOC40Mi43MSAxLjQ4LjM4IDEuNDUtLjQ5LjE0LS45Ni4yNS0xLjkyLjQyLTIuODcuMDQtLjI0LjQxLS4yLjQuMDRaIi8+PHBhdGggZD0iTTExLjg1IDE1LjU0Yy4wMi43OS4wMSAxLjU4LjAxIDIuMzctLjAyLjQxLjA3LjktLjE0IDEuMjktLjQzIDEuMDItMi4wMSAxLjAyLTIuNDUgMC0uMjEtLjM5LS4xMy0uODktLjE0LTEuMjkgMC0uNzkgMC0xLjU4LjAxLTIuMzcgMC0uMTEuMS0uMi4yMS0uMTkuMSAwIC4xOC4wOC4xOS4xOC4wNy43OS4xIDEuNTguMTUgMi4zNy4wMy4yNyAwIC44Mi4xMyAxLjA0LjEzLjI2LjQuNDMuNjguNDIuNDYgMCAuNzktLjQuNzctLjg3bC4wMy0uNTljLjA0LS43OS4wOC0xLjU4LjE1LTIuMzcuMDItLjI0LjQtLjIzLjQuMDFaIi8+PC9zdmc+)}.scylla-icon--about-us-m{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNi4zOCAzMi40MyI+PHBhdGggZD0iTTYuNTUgMzEuNjRjLS4yLjEzLS40My4yMi0uNjkuMjZhMS44MSAxLjgxIDAgMCAxLTIuMDYtMS4zOVMuNDkgMTQuOTkuNDkgMTEuODJDLjUgNS4xOSA1Ljc3LjUgMTMuMTkuNXMxMi42OSA0LjY5IDEyLjY5IDExLjMyYzAgMy4xOC0zLjMxIDE4LjY5LTMuMzEgMTguNjlhMS44MSAxLjgxIDAgMCAxLTIuNjIgMS4yIiBzdHlsZT0iZmlsbDpub25lO3N0cm9rZTojMDAwO3N0cm9rZS1saW5lY2FwOnJvdW5kO3N0cm9rZS1saW5lam9pbjpyb3VuZCIvPjxwYXRoIGQ9Ik0yMS44NiAyNS4zNmMtLjI4IDEuOS0uMzcgMy44Ni0uOTEgNS43MS0uNjEgMS40MS0yLjY4IDEuNzUtMy42Ni41NS0uNDEtLjQ3LjMxLTEuMTEuNzMtLjY2LjcxLjc2IDIuMDQuMjkgMi4xNi0uNzMuMzItMS42Ni42NS0zLjMzIDEuMDQtNC45OC4wOS0uMzkuNy0uMjguNjUuMTFaIi8+PHBhdGggZD0iTTE0LjggMTAuNTdjMCAzLjEzLTIuNTMgNS42Ni01LjY2IDUuNjZzLTUuNDctMi41My01LjQ3LTUuNjYgMi4zNC01LjY2IDUuNDctNS42NiA1LjY2IDIuNTMgNS42NiA1LjY2WiIgc3R5bGU9InN0cm9rZS13aWR0aDouOXB4O2ZpbGw6bm9uZTtzdHJva2U6IzAwMDtzdHJva2UtbGluZWNhcDpyb3VuZDtzdHJva2UtbGluZWpvaW46cm91bmQiLz48cGF0aCBkPSJNMTAuMzEgNi44NmMtLjk4LjItMS4xNyAyLjM0LS41OSAyLjkzLjM4LjM4IDEuMTcuNTEgMS4xNy43OHMtLjc5LjQtMS4xNy43OGMtLjU5LjU5LS4zOSAyLjczLjU5IDIuOTMgMS4xNi4yMyAyLjkzLTEuMTcgMi45My0zLjcxcy0xLjc2LTMuOTQtMi45My0zLjcxWk02LjgyIDE4LjUxYzMuNDkuODkgNi45Ny0uNSA5LjUxLTIuOTMuNDctLjQ0IDEuMTYuMzEuNjguNzQtMS4zOCAxLjIzLTIuOTggMi4yOS00Ljc5IDIuODctMS44LjU5LTMuNzcuNTgtNS41OC4xNGEuNDIxLjQyMSAwIDAgMS0uMzEtLjVjLjA1LS4yMi4yOC0uMzYuNS0uMzFaIi8+PHBhdGggZD0iTTE2LjczIDE2LjY3Yy0uMTItLjQ2LS41MS0uODMtLjk5LS44My0uNzUtLjAyLS41OS0xLjE3LjE0LS45OS44MS4xNiAxLjQzLjg1IDEuNSAxLjY2LjA4LjQtLjU0LjU0LS42NS4xNVpNOS4wMyAzMS43Yy0xLjI2IDEuMzYtMy42Mi40NS0zLjgtMS4zNWwtLjA5LS41NWMtLjIxLTEuNDgtLjQ1LTIuOTUtLjYtNC40NC0uMDItLjE4LjExLS4zNC4yOS0uMzYuMTctLjAyLjMyLjA5LjM1LjI1LjM5IDEuNjMuNzEgMy4yOCAxLjAzIDQuOTMuMDkgMS4wMiAxLjM4IDEuNTQgMi4xMi44MS40NS0uNDQgMS4xNC4yNi42OS43WiIvPjxwYXRoIGQ9Ik0xMS45NiAzMS4xNmMtMSAxLjk4LTQuMDQgMS4zLTQuMjEtLjg4LS4xNS0xLjY5LS4zLTMuMzgtLjM5LTUuMDcgMC0uMTguMTMtLjM0LjMxLS4zNC4xNyAwIC4zMS4xMS4zNC4yNy4yOCAxLjY3LjUgMy4zNS43MiA1LjAzLjA5IDEuMiAxLjc3IDEuNTkgMi4zNi41MS4zMS0uNTYgMS4xNi0uMDkuODcuNDdaTTE5LjAzIDI1LjIxYy0uMDggMS42OS0uMjQgMy4zOC0uMzkgNS4wNy0uMDQuMzctLjE3Ljc1LS4zOCAxLjA2LS44NiAxLjQtMy4xMSAxLjMxLTMuODMtLjE3LS4zLS41Ni41NS0xLjAzLjg2LS40OC41OSAxLjA4IDIuMjcuNjkgMi4zNS0uNTIuMjItMS42OC40My0zLjM2LjcyLTUuMDMuMDYtLjQuNjgtLjMzLjY1LjA3WiIvPjxwYXRoIGQ9Ik0xNS40MyAyNS4wMmMuMDQgMS4zMS4wMiAyLjYxLjAyIDMuOTEtLjAzLjY3LjExIDEuNDgtLjIzIDIuMTMtLjc0IDEuNjktMy4yOSAxLjY5LTQuMDMgMC0uMzQtLjY1LS4yMS0xLjQ3LS4yNC0yLjEzIDAtMS4zLS4wMi0yLjYxLjAyLTMuOTEgMC0uMTguMTYtLjMyLjM0LS4zMi4xNyAwIC4zLjE0LjMyLjMuMTEgMS4zLjE3IDIuNi4yNCAzLjkxLjA1LjQ1IDAgMS4zNS4yMSAxLjcyLjIxLjQzLjY2LjcxIDEuMTIuNy40Ni4wMi45MS0uMjcgMS4xMi0uNjkuMjItLjM2LjE2LTEuMjguMjEtMS43Mi4wNy0xLjMuMTMtMi42MS4yNC0zLjkxLjAyLS40LjY2LS4zOC42Ni4wMloiLz48L3N2Zz4=)}.scylla-icon--alternator{background-image:url(data:image/svg+xml;base64,PHN2ZyBpZD0iTGF5ZXJfMyIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB2aWV3Qm94PSIwIDAgMjAgMjAiPjxkZWZzPjxzdHlsZT4uY2xzLTF7ZmlsbDpub25lO3N0cm9rZTojMDAwO3N0cm9rZS1saW5lY2FwOnJvdW5kO3N0cm9rZS1saW5lam9pbjpyb3VuZH08L3N0eWxlPjwvZGVmcz48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Ik0xNy41IDIuOTFjMCAxLjI4LTMuNjcgMi41OS04IDIuNTlzLTgtMS4zMS04LTIuNTlTNS4wOS41IDkuNDIuNXM4LjA4IDEuMTMgOC4wOCAyLjQxWk0xNy41IDcuNjZjMCAxLjI4LTMuNjMgMi44LTcuOTYgMi44UzEuNSA4LjkzIDEuNSA3LjY2TTE3LjUgMTIuNDdjMCAxLjI4LTMuNjcgMy4wMy04IDMuMDNzLTgtMS43NS04LTMuMDNNMTcuNSAxNy4yOWMwIDEuMjgtMy43NSAyLjMtOC4wOCAyLjNzLTcuOTItMS4wMy03LjkyLTIuM00xLjUgMTcuMTlWMi45MU0xNy41IDE3LjE5VjIuOTEiLz48L3N2Zz4=)}.scylla-icon--apps{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyMSAxOSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOm5vbmU7c3Ryb2tlOiM0ZDRkNGQ7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJDYWxxdWVfNCIgZGF0YS1uYW1lPSJDYWxxdWUgNCI+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNLjUgMS41aDIwdjE0SC41ek03LjUgMTUuNzR2Mi44OU0xMi44MyAxNS42M3YyLjMyTTUuNSAxOC41aDkuMTQiLz48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Im0zLjY0IDUuNTYgNC41OCAyLjkxLTQuNTggMi45Mk05LjEgMTIuMDhoNC4zMiIvPjwvZz48L3N2Zz4=)}.scylla-icon--architecture{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMSwuY2xzLTIsLmNscy01e2ZpbGw6bm9uZTtzdHJva2U6Z3JheX0uY2xzLTF7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfS5jbHMtMiwuY2xzLTV7c3Ryb2tlLW1pdGVybGltaXQ6MTB9LmNscy0ye3N0cm9rZS13aWR0aDouOThweH0uY2xzLTV7c3Ryb2tlLXdpZHRoOi45OXB4fTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJDYWxxdWVfMiIgZGF0YS1uYW1lPSJDYWxxdWUgMiI+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNMS45IDEwLjI3YTEwLjgzIDEwLjgzIDAgMCAxIDguNzMtOC4zOE0xMC41MSAyMy4wOEExMC43OSAxMC43OSAwIDAgMSAxLjc3IDE0TTIzLjIzIDE0YTEwLjgxIDEwLjgxIDAgMCAxLTkgOS4xMU0xNC4yNyAxLjg4YTEwLjgxIDEwLjgxIDAgMCAxIDguODMgOC4zNyIvPjxjaXJjbGUgY2xhc3M9ImNscy0yIiBjeD0iMTIuMjUiIGN5PSIxLjc1IiByPSIxLjc1Ii8+PGNpcmNsZSBjbGFzcz0iY2xzLTIiIGN4PSIxMi4yNSIgY3k9IjIyLjc1IiByPSIxLjc1Ii8+PGNpcmNsZSBjeD0iNC45MiIgY3k9IjQuNzUiIHI9IjEuNzUiIHN0eWxlPSJzdHJva2Utd2lkdGg6Ljk5cHg7ZmlsbDpncmF5O3N0cm9rZS1taXRlcmxpbWl0OjEwO3N0cm9rZTpncmF5Ii8+PGNpcmNsZSBjeD0iMjAuMDkiIGN5PSIxOS45MSIgcj0iMS43NSIgc3R5bGU9InN0cm9rZS13aWR0aDouOTlweDtmaWxsOmdyYXk7c3Ryb2tlLW1pdGVybGltaXQ6MTA7c3Ryb2tlOmdyYXkiLz48Y2lyY2xlIGNsYXNzPSJjbHMtNSIgY3g9IjEuNzUiIGN5PSIxMi4yNSIgcj0iMS43NSIvPjxjaXJjbGUgY2xhc3M9ImNscy01IiBjeD0iMjMuMjUiIGN5PSIxMi4yNSIgcj0iMS43NSIvPjxjaXJjbGUgY3g9IjQuNzUiIGN5PSIxOS42NCIgcj0iMS43NSIgc3R5bGU9InN0cm9rZS13aWR0aDouOTlweDtmaWxsOmdyYXk7c3Ryb2tlLW1pdGVybGltaXQ6MTA7c3Ryb2tlOmdyYXkiLz48Y2lyY2xlIGN4PSIxOS45MSIgY3k9IjQuNDgiIHI9IjEuNzUiIHN0eWxlPSJzdHJva2Utd2lkdGg6Ljk5cHg7ZmlsbDpncmF5O3N0cm9rZS1taXRlcmxpbWl0OjEwO3N0cm9rZTpncmF5Ii8+PC9nPjwvc3ZnPg==)}.scylla-icon--benchmarks{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVqb2luOnJvdW5kO3N0cm9rZS13aWR0aDozcHh9PC9zdHlsZT48L2RlZnM+PGcgaWQ9IkNhbHF1ZV8yIiBkYXRhLW5hbWU9IkNhbHF1ZSAyIj48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Ik01LjUxIDI0Ljkxdi01Ljg1TTEyLjU3IDI0Ljkxdi05Ljc0TTE5LjYyIDI0LjkxVjEwLjE1Ii8+PHBhdGggc3R5bGU9InN0cm9rZS1saW5lY2FwOnJvdW5kO2ZpbGw6bm9uZTtzdHJva2U6Z3JheTtzdHJva2UtbGluZWpvaW46cm91bmQiIGQ9Im0uOTEgMTQuOTggNS4xMy03Ljk0IDYuMjUgNS44OEwyNCAxIi8+PHBhdGggc3R5bGU9ImZpbGw6Z3JheSIgZD0ibTI1IDUtNS01aDV2NXoiLz48L2c+PC9zdmc+)}.scylla-icon--blog{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJDYWxxdWVfNCIgZGF0YS1uYW1lPSJDYWxxdWUgNCI+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJtOSAxNS0yLjUtMS41IDgtMTJMMTcgMyA5IDE1eiIvPjxwYXRoIHN0eWxlPSJmaWxsOmdyYXk7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kIiBkPSJtNi41IDEzLjUtLjUgM0w5IDE1bC0yLjUtMS41eiIvPjxwYXRoIGNsYXNzPSJjbHMtMSIgZD0iTTE5LjI1IDIuNWg0LjI1djE2aC0xM3Y0LjE3TDYuNDYgMTguNWwtNC45Ni0uMDRWMi41aDguMzFNMTQuNSAyLjVsMS42NyAxLjMzIi8+PC9nPjwvc3ZnPg==)}.scylla-icon--careers{background-image:url(data:image/svg+xml;base64,PHN2ZyBpZD0iQ2FscXVlXzEiIGRhdGEtbmFtZT0iQ2FscXVlIDEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmlld0JveD0iMCAwIDI1IDI1Ij48ZGVmcz48c3R5bGU+LmNscy0xe2ZpbGw6bm9uZTtzdHJva2U6Z3JheTtzdHJva2UtbGluZWNhcDpyb3VuZDtzdHJva2UtbGluZWpvaW46cm91bmR9PC9zdHlsZT48L2RlZnM+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNMS41IDExLjU1djhjMCAuNTYgMS4wNyAyIDIgMmgxOGMuODkgMCAyLTEuNDQgMi0ydi04Ii8+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNMjMuMzEgMy41SDEuODFjLS40OCAwLTEuMzEuNTUtMS4zMSAxdjZsMTAgMmE4LjQ1IDguNDUgMCAwIDAgNCAwbDEwLTJ2LTZjMC0uNDUtLjcyLTEtMS4xOS0xWk0xNS42MiAzLjV2LTFjMC0uNzYtLjYxLTEtMS4zOC0xaC0zLjQ1Yy0uNzYgMC0xLjM4LjI0LTEuMzggMXYxIi8+PHJlY3QgeD0iMTAiIHk9IjExIiB3aWR0aD0iNSIgaGVpZ2h0PSIzLjk5IiByeD0iLjU1IiByeT0iLjU1IiBzdHlsZT0iZmlsbDpncmF5Ii8+PC9zdmc+)}.scylla-icon--chevron-left{background-image:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTAiIGhlaWdodD0iMTYiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZD0iTTguMDkyIDE2IDEwIDE0LjExMyAzLjgxNyA4IDEwIDEuODg3IDguMDkyIDAgMCA4bDguMDkyIDhaIiBmaWxsPSIjMDAwIi8+PC9zdmc+)}.contents.local>ul>li a:before,.scylla-icon--chevron-right,.secondary-side-nav__content li a:before{background-image:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTAiIGhlaWdodD0iMTYiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZD0iTTEuOTA4IDAgMCAxLjg4NyA2LjE4MyA4IDAgMTQuMTEzIDEuOTA4IDE2IDEwIDggMS45MDggMFoiIGZpbGw9IiMwMDAiLz48L3N2Zz4=)}.scylla-icon--circe{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAzOCAzMCI+PGRlZnM+PHN0eWxlPi5jbHMtMiwuY2xzLTN7ZmlsbDpub25lO3N0cm9rZTojNGQ0ZDRkO3N0cm9rZS1saW5lY2FwOnJvdW5kO3N0cm9rZS1saW5lam9pbjpyb3VuZH0uY2xzLTN7c3Ryb2tlLXdpZHRoOjEuMTFweH08L3N0eWxlPjwvZGVmcz48ZyBpZD0iQ2FscXVlXzQiIGRhdGEtbmFtZT0iQ2FscXVlIDQiPjxwYXRoIGQ9Ik0yMi4xIDEyaC02LjE2YTEuMDYgMS4wNiAwIDAgMS0uOTQtMS4wNy45My45MyAwIDAgMSAuOTQtLjkzaDYuMTZhLjkzLjkzIDAgMCAxIC45NC45M0ExLjA2IDEuMDYgMCAwIDEgMjIuMSAxMloiIHN0eWxlPSJmaWxsOiM0ZDRkNGQiLz48cGF0aCBjbGFzcz0iY2xzLTIiIGQ9Ik0xMy40NCA0LjQ5SDkuNTF2MjRoMTl2LTI0SDI0LjUiLz48cGF0aCBjbGFzcz0iY2xzLTMiIGQ9Ik0xMyAzLjQ5SDguNWwtLjA4IDI2LjFIMjkuNVYzLjM5SDI1Ii8+PHBhdGggY2xhc3M9ImNscy0yIiBkPSJNMTIuNSAxOC4zOGgxM00xMi41IDE1LjQ5aDEzTTEyLjUgMjEuNDNoMTNNMTIuNSAyNC40N2gxM00xMy41IDIuNWgxMXYzLjk4aC0xMXoiLz48cGF0aCBjbGFzcz0iY2xzLTMiIGQ9Ik0yMS41LjVoLTUuMDR2MS45NWw1LjA0LjA1di0yeiIvPjwvZz48L3N2Zz4=)}.scylla-icon--clock{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyMSAxOSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOm5vbmU7c3Ryb2tlOiM0ZDRkNGQ7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJDYWxxdWVfNCIgZGF0YS1uYW1lPSJDYWxxdWUgNCI+PGNpcmNsZSBjbGFzcz0iY2xzLTEiIGN4PSIxMC41IiBjeT0iOS41IiByPSI5Ii8+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNMTAuNSAzLjV2NmwzLjA2IDMiLz48L2c+PC9zdmc+)}.scylla-icon--close{background-image:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMzQiIGhlaWdodD0iMzQiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGcgY2xpcC1wYXRoPSJ1cmwoI2EpIiBmaWxsPSIjZmZmIj48cGF0aCBkPSJNMTEuNjcgMjIuMTNhLjU2NC41NjQgMCAwIDEtLjM5OC0uOTYybDkuODk2LTkuODk2YS41NjMuNTYzIDAgMSAxIC43OTcuNzk3bC05Ljg5NiA5Ljg5NmEuNTU5LjU1OSAwIDAgMS0uMzk5LjE2NVoiLz48cGF0aCBkPSJNMjEuNTY2IDIyLjEzYS41NTkuNTU5IDAgMCAxLS4zOTgtLjE2NWwtOS44OTYtOS44OTZhLjU2My41NjMgMCAxIDEgLjc5Ny0uNzk3bDkuODk2IDkuODk1YS41NjQuNTY0IDAgMCAxLS4zOTkuOTYzWiIvPjxwYXRoIGQ9Ik0xNi42MTkgMzMuMjM3QzcuNDU1IDMzLjIzNyAwIDI1Ljc4MiAwIDE2LjYxOSAwIDcuNDU2IDcuNDU1IDAgMTYuNjE5IDBzMTYuNjE5IDcuNDU1IDE2LjYxOSAxNi42MTktNy40NTYgMTYuNjE4LTE2LjYyIDE2LjYxOFptMC0zMi4xMWMtOC41NDIgMC0xNS40OTIgNi45NS0xNS40OTIgMTUuNDkyIDAgOC41NDIgNi45NSAxNS40OTIgMTUuNDkyIDE1LjQ5MiA4LjU0MiAwIDE1LjQ5Mi02Ljk1IDE1LjQ5Mi0xNS40OTIgMC04LjU0Mi02Ljk1LTE1LjQ5Mi0xNS40OTItMTUuNDkyWiIvPjwvZz48ZGVmcz48Y2xpcFBhdGggaWQ9ImEiPjxwYXRoIGZpbGw9IiNmZmYiIGQ9Ik0wIDBoMzMuMjM3djMzLjIzN0gweiIvPjwvY2xpcFBhdGg+PC9kZWZzPjwvc3ZnPg==)}.scylla-icon--cloud{background-image:url(data:image/svg+xml;base64,PHN2ZyBpZD0iTGF5ZXJfMiIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB2aWV3Qm94PSIwIDAgNDMuMDQgMzIuMDMiPjxkZWZzPjxzdHlsZT4uY2xzLTF7ZmlsbDpub25lO3N0cm9rZTojMWQxZDFiO3N0cm9rZS1saW5lY2FwOnJvdW5kO3N0cm9rZS1saW5lam9pbjpyb3VuZH08L3N0eWxlPjwvZGVmcz48ZyBpZD0iTGF5ZXJfMyI+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNNDIuNTQgNC4wNmMwIDEuNjgtMy42MyAyLjQ0LTkgMi40NHMtMTAtLjczLTEwLTIuNFMyNy42Ny41IDMzLjA0LjVzOS41IDEuODkgOS41IDMuNTZaTTQyLjU0IDkuNjNjMCAxLjY4LTMuNzYgMi45MS05LjEyIDIuOTFzLTkuODQtMS4yMy05Ljg0LTIuOTFNNDIuNTQgMTUuMzRjMCAxLjY4LTMuNjggMy4yNS05LjA0IDMuMjUtNCAwLTcuNi0uOTYtOS4wOS0yLjA0TTQyLjU0IDIwLjY1YzAgMS42OC0zLjcyIDIuOTctOS4wOCAyLjk3TTIzLjU0IDE1LjQ2VjQuMU00Mi41NCAyMC43N1Y0LjEiLz48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Ik0yOC4xMSAyMS4wOGMtLjg3IDAtMS42Ny4yMy0yLjM5LjYxIDAtLjA3LjAxLS4xNC4wMS0uMjEgMC00Ljg1LTMuODMtOC45LTguNjgtOC45cy04Ljg4IDQuMDUtOC44OCA4LjljMCAuMTcuMDIuMzQuMDMuNTEtLjg0LS41Ny0xLjg1LS45MS0yLjk1LS45MS0yLjg4IDAtNC43NCAyLjU3LTQuNzQgNS40NnMxLjg2IDQuOTkgNC43NCA0Ljk5aDIyLjg2YzIuODggMCA1LjUyLTIuMjcgNS41Mi01LjE2cy0yLjYzLTUuMjktNS41Mi01LjI5WiIvPjwvZz48L3N2Zz4=)}.scylla-icon--cloud-docs{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyMSAxOSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOm5vbmU7c3Ryb2tlOiM0ZDRkNGQ7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJDYWxxdWVfNCIgZGF0YS1uYW1lPSJDYWxxdWUgNCI+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNNi41IDExLjVoOHYxaC04ek0xNS42NSA2LjU1YTMuNDIgMy40MiAwIDAgMC0zLjE1IDIiLz48cGF0aCBkPSJNMTAuMDYgMi44QTUuMTcgNS4xNyAwIDAgMSAxNSA2LjM1aC4yNGE0Ljg0IDQuODQgMCAwIDEgMCA5LjY3aC0xMWEzLjQ1IDMuNDUgMCAwIDEgMC02LjlBMy4xNyAzLjE3IDAgMCAxIDUgOS4yIDUuMzMgNS4zMyAwIDAgMSA0Ljg2IDhhNS4yIDUuMiAwIDAgMSA1LjItNS4ybTAtLjhhNiA2IDAgMCAwLTYgNnYuMzFhNC4yNSA0LjI1IDAgMCAwIC4xOCA4LjQ5aDExYTUuNjMgNS42MyAwIDAgMCAuMy0xMS4yNkE2IDYgMCAwIDAgMTAuMDYgMloiIHN0eWxlPSJmaWxsOiM0ZDRkNGQiLz48L2c+PC9zdmc+)}.scylla-icon--comparison{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMSwuY2xzLTIsLmNscy00e2ZpbGw6bm9uZTtzdHJva2U6Z3JheX0uY2xzLTEsLmNscy0ye3N0cm9rZS1taXRlcmxpbWl0OjEwfS5jbHMtMiwuY2xzLTR7c3Ryb2tlLWxpbmVjYXA6cm91bmR9LmNscy00e3N0cm9rZS1saW5lam9pbjpyb3VuZH08L3N0eWxlPjwvZGVmcz48ZyBpZD0iQ2FscXVlXzQiIGRhdGEtbmFtZT0iQ2FscXVlIDQiPjxwYXRoIGNsYXNzPSJjbHMtMSIgZD0iTTQuNSAxMy42M3YyLjg4aDYuMDZNMjAuNSAxMy41NHYyLjk2bC01LjUuMDEiLz48cGF0aCBjbGFzcz0iY2xzLTIiIGQ9Ik0xMi41IDE4LjV2Mi43Mk03LjUgMjEuNWgxMCIvPjxjaXJjbGUgY3g9IjEyLjUiIGN5PSIxNi41IiByPSIyIiBzdHlsZT0iZmlsbDpncmF5O3N0cm9rZS13aWR0aDouOTVweDtzdHJva2UtbWl0ZXJsaW1pdDoxMDtzdHJva2U6Z3JheSIvPjxwYXRoIGNsYXNzPSJjbHMtNCIgZD0iTTUuMDYgMTMuNThIMy44OEEzLjEgMy4xIDAgMCAxIC41IDEwLjVoOGEzLjE2IDMuMTYgMCAwIDEtMy40NCAzLjA4Wk0yMSAxMy41OGgtMS4xN2EzLjA5IDMuMDkgMCAwIDEtMy4zNy0zLjA3aDhBMy4xNiAzLjE2IDAgMCAxIDIxIDEzLjU4Wk03LjQ2IDUuMTJjMCAuNTctMS4xLjQ2LTIuNzkuNDZTMS41OCA1LjYgMS41OCA1IDMgNC40IDQuNjkgNC40czIuNzcuMTYgMi43Ny43MlpNMS41IDkuODVWNS4zMU03LjUgMTAuMzVWNS44MU0yMy41IDUuMTJjMCAuNTctMS4xLjQ2LTIuNzkuNDZzLTMuMDkgMC0zLjA5LS41NFMxOSA0LjQgMjAuNzMgNC40czIuNzcuMTYgMi43Ny43MlpNMTcuNTQgOS44NVY1LjMxTTIzLjU0IDEwLjM1VjUuODEiLz48L2c+PC9zdmc+)}.scylla-icon--contact-us{background-image:url(data:image/svg+xml;base64,PHN2ZyBpZD0iQ2FscXVlXzEiIGRhdGEtbmFtZT0iQ2FscXVlIDEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmlld0JveD0iMCAwIDI1IDI1Ij48ZGVmcz48c3R5bGU+LmNscy0xe2ZpbGw6bm9uZTtzdHJva2U6Z3JheTtzdHJva2UtbGluZWNhcDpyb3VuZDtzdHJva2UtbGluZWpvaW46cm91bmQ7c3Ryb2tlLXdpZHRoOjEuMDZweH08L3N0eWxlPjwvZGVmcz48cGF0aCBjbGFzcz0iY2xzLTEiIHRyYW5zZm9ybT0icm90YXRlKC0yNy40OSAxNS41NTIgMTEuMDgzKSIgZD0iTTcuNzYgNi4wMWgxNS41OXYxMC4xM0g3Ljc2eiIvPjxwYXRoIGNsYXNzPSJjbHMtMSIgZD0ibTYuMyAxMC4xOCA4LjYzIDEuNTZhMS40MiAxLjQyIDAgMCAwIDEuNTMtLjc0bDMuNjctOE0xMS4wMiAxOS4wM2wxLjc0LTVNMjQuNTkgMTEuOTdsLTUuMDktMS40NU03LjA5IDE3LjU4IDMuOSAxOS4zNE02LjA2IDE1LjQxLjU0IDE4LjM2Ii8+PC9zdmc+)}.scylla-icon--developers-blog{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOmdyYXl9PC9zdHlsZT48L2RlZnM+PGcgaWQ9IkNhbHF1ZV80IiBkYXRhLW5hbWU9IkNhbHF1ZSA0Ij48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Im02LjQ4IDEwLjU5LS41LjE3LjUuMTZMMTEgMTIuMTZWMTRsLTctMi40OVYxMGw3LTIuNXYxLjgzWk0xNCA5LjMyVjcuNWw3IDIuNXYxLjU0TDE0IDE0di0xLjgzbDQuMTQtMS4zLjQ0LS4xMy0uNDMtLjE0WiIvPjxwYXRoIHN0eWxlPSJmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kO3N0cm9rZS13aWR0aDouOThweCIgZD0iTTEuNSAyLjVoMjJ2MTZoLTEzdjQuMTdMNi40NiAxOC41bC00Ljk2LS4wNFYyLjV6Ii8+PC9nPjwvc3ZnPg==)}.scylla-icon--docs{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfS5jbHMtMntmaWxsOmdyYXl9PC9zdHlsZT48L2RlZnM+PGcgaWQ9IkNhbHF1ZV80IiBkYXRhLW5hbWU9IkNhbHF1ZSA0Ij48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Ik0zLjUgMi41MWgxNi45NHYyMC45MUgzLjV6Ii8+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJtMjIuNDUgMjEuNS4wNS0yMWgtMTdhMi4xNiAyLjE2IDAgMCAwLTIgMiIvPjxwYXRoIGNsYXNzPSJjbHMtMiIgZD0iTTYgNmg3djJINnpNNiA5aDExdjJINnoiLz48L2c+PC9zdmc+)}.scylla-icon--enterprise{background-image:url(data:image/svg+xml;base64,PHN2ZyBpZD0iTGF5ZXJfMyIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB2aWV3Qm94PSIwIDAgMjAgMjAiPjxkZWZzPjxzdHlsZT4uY2xzLTEsLmNscy0ye2ZpbGw6bm9uZTtzdHJva2U6IzAwMDtzdHJva2UtbGluZWNhcDpyb3VuZDtzdHJva2UtbGluZWpvaW46cm91bmR9LmNscy0ye3N0cm9rZS13aWR0aDoxLjA3cHh9PC9zdHlsZT48L2RlZnM+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJtMTMuNjIgNy41IDEuODgtMS4wOCAyIDIuMDh2N2gxTTE1LjUgMTUuNXYtNSIvPjxwYXRoIGNsYXNzPSJjbHMtMiIgZD0iTTUuNSAxNS41di0xMmw0LTIgNCAydjEyTTkuNSAxNS41VjEuNk03LjUgNS41djEwTTExLjUgNS41djEwIi8+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNNS41IDguNTQgMy40NiA3LjVsLTEuOTYuOTZ2Ny4wNGgtMU0zLjUgMTAuNXY1TS41IDE3LjVoMTgiLz48L3N2Zz4=)}.scylla-icon--enterprise-m{background-image:url(data:image/svg+xml;base64,PHN2ZyB2ZXJzaW9uPSIxLjEiIGlkPSJMYXllcl8yXzAwMDAwMDE2NzY4MDY2MDE5MjYzMjMyNzcwMDAwMDA1NDc1ODA5NTExODI4NjY2MDM2XyIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4PSIwIiB5PSIwIiB2aWV3Qm94PSIwIDAgNDMgMzEiIHN0eWxlPSJlbmFibGUtYmFja2dyb3VuZDpuZXcgMCAwIDQzIDMxIiB4bWw6c3BhY2U9InByZXNlcnZlIj48c3R5bGU+LnN0MHtmaWxsOm5vbmU7c3Ryb2tlOiMxZDFkMWI7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfTwvc3R5bGU+PGcgaWQ9IkxheWVyXzMiPjxwYXRoIGNsYXNzPSJzdDAiIGQ9Im0yOS42IDkuNSA0LTIgNi45IDQuMXYxNS45aDJNMzMuNiAyNy41VjcuNk0xNC42IDI3LjVWNC44TDIyLjUuNSAyOS42IDV2MjIuNU0yMi41IDI3LjVWMU0yNC41IDUuNmwzIDJNMjQuNSA5LjZsMyAyTTI0LjUgMTMuNmwzIDJNMjQuNSAxNy41bDMgMk0yNC41IDIxLjVsMyAyTTM1LjQgMTEuNmwzIDJNMzUuNCAxNS42bDMgMS45TTM1LjQgMTkuNWwzIDJNMzUuNCAyMy41bDMgMS45TTE4LjUgNS44djIxLjdNMTQuNiA5LjdsLTQuMS0yLjUtOCA0LjR2MTUuOWgtMk0xMC41IDI3LjVWNy4yTTEyLjUgMTEuNmwyIDFNMTIuNSAxNS42bDIgLjlNMTIuNSAxOS41bDIgMU0xMi41IDIzLjVsMi4xIDFNNi40IDEyLjR2MTUuMU0uNSAzMC41aDQyIi8+PC9nPjwvc3ZnPg==)}.scylla-icon--events{background-image:url(data:image/svg+xml;base64,PHN2ZyBpZD0iQ2FscXVlXzEiIGRhdGEtbmFtZT0iQ2FscXVlIDEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmlld0JveD0iMCAwIDI1IDI1Ij48ZGVmcz48c3R5bGU+LmNscy0xe2ZpbGw6bm9uZTtzdHJva2U6Z3JheTtzdHJva2UtbGluZWNhcDpyb3VuZDtzdHJva2UtbGluZWpvaW46cm91bmR9LmNscy0ye2ZpbGw6Z3JheX08L3N0eWxlPjwvZGVmcz48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Ik0yMi41IDIzLjVoLTIxdi0yMGgyMnYxNS4yMSIvPjxwYXRoIGNsYXNzPSJjbHMtMSIgZD0iTTQuNDIgMy41YzAtMS4zNiAxLjA5LTIgMi40NS0yYTIuNDYgMi40NiAwIDEgMSAwIDQuOTEgMi42MSAyLjYxIDAgMCAxLTEtLjIxTTEwLjY3IDMuNWMwLTEuMzYgMS4xLTIgMi40Ni0yYTIuNDYgMi40NiAwIDAgMSAwIDQuOTEgMi42MSAyLjYxIDAgMCAxLTEtLjIxTTE2LjkzIDMuNWMwLTEuMzYgMS4xLTIgMi40NS0yYTIuNDYgMi40NiAwIDEgMSAwIDQuOTEgMi41MiAyLjUyIDAgMCAxLTEtLjIxIi8+PHBhdGggY2xhc3M9ImNscy0yIiBkPSJNNyA5aDN2M0g3ek0xMiA5aDN2M2gtM3pNMTcgOWgzdjNoLTN6TTcgMTRoM3YzSDd6TTEyIDE0aDN2M2gtM3pNMTcgMTRoM3YzaC0zeiIvPjxwYXRoIGNsYXNzPSJjbHMtMSIgZD0iTTMuNSAzLjY3djE2LjY2TTMuNSAyMC40M2MwIDEuMjkuNDQgMi4zMyAxLjczIDIuMzNzMi4zMy0xLjkgMi4zMy0zLjE5bDE2Ljk0LS4wN2MwIDEuMjktLjU1IDMuMTItMS44MyAzLjEySDYuMyIvPjwvc3ZnPg==)}.admonition.note .admonition-title:before,.admonition.tip .admonition-title:before,.scylla-icon--exclamation{background-image:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PG1hc2sgaWQ9ImEiIG1hc2stdHlwZT0iYWxwaGEiIG1hc2tVbml0cz0idXNlclNwYWNlT25Vc2UiIHg9IjEiIHk9IjEiIHdpZHRoPSIyMiIgaGVpZ2h0PSIyMiI+PHBhdGggZD0iTTEyIDIzQzUuOSAyMyAxIDE4LjEgMSAxMlM1LjkgMSAxMiAxczExIDQuOSAxMSAxMS00LjkgMTEtMTEgMTFabTAtMjBjLTUgMC05IDQtOSA5czQgOSA5IDkgOS00IDktOS00LTktOS05WiIgZmlsbD0iI2ZmZiIvPjxwYXRoIGQ9Ik0xMiAxM2MtLjYgMC0xLS40LTEtMVY4YzAtLjYuNC0xIDEtMXMxIC40IDEgMXY0YzAgLjYtLjQgMS0xIDFaTTEyIDE3Yy0uMyAwLS41LS4xLS43LS4zLS4yLS4yLS4zLS40LS4zLS43IDAtLjEgMC0uMy4xLS40LjEtLjEuMS0uMi4yLS4zLjMtLjMuNy0uNCAxLjEtLjIuMSAwIC4xIDAgLjIuMSAwIDAgLjEuMS4yLjEuMS4xLjIuMi4yLjN2LjRjMCAuMSAwIC4zLS4xLjQtLjEuMS0uMS4yLS4yLjMtLjIuMi0uNC4zLS43LjNaIiBmaWxsPSIjZmZmIi8+PC9tYXNrPjxnIG1hc2s9InVybCgjYSkiPjxwYXRoIGZpbGw9IiNmZmYiIGQ9Ik0wIDBoMjR2MjRIMHoiLz48L2c+PC9zdmc+)}.collapsible-button i,.scylla-icon--expand{background-image:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYuMDAxIiBoZWlnaHQ9IjE2IiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjxwYXRoIGQ9Ik01IDEzYTEgMSAwIDAgMS0uNzEtLjI5bC00LTRhMSAxIDAgMCAxIDAtMS40MWw0LTRhMSAxIDAgMCAxIDEuNDIgMS40MUwyLjQxIDhsMy4yOSAzLjI5QTEgMSAwIDAgMSA1IDEzeiIvPjxwYXRoIGQ9Ik0xMSA5SDFhMSAxIDAgMCAxIDAtMmgxMGExIDEgMCAwIDEgMCAyek0xNSAxNmExIDEgMCAwIDEtMS0xVjFhMSAxIDAgMCAxIDIgMHYxNGExIDEgMCAwIDEtMSAxeiIvPjwvc3ZnPg==)}.scylla-icon--forum{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSJjdXJyZW50Q29sb3IiIHN0cm9rZS13aWR0aD0iMS41IiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiIGNsYXNzPSJmZWF0aGVyIGZlYXRoZXItdXNlcnMiPjxwYXRoIGQ9Ik0xNyAyMXYtMmE0IDQgMCAwIDAtNC00SDVhNCA0IDAgMCAwLTQgNHYyIi8+PGNpcmNsZSBjeD0iOSIgY3k9IjciIHI9IjQiLz48cGF0aCBkPSJNMjMgMjF2LTJhNCA0IDAgMCAwLTMtMy44N00xNiAzLjEzYTQgNCAwIDAgMSAwIDcuNzUiLz48L3N2Zz4=)}.scylla-icon--home{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyMSAxOSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOm5vbmU7c3Ryb2tlOiM0ZDRkNGQ7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJMYXllcl81IiBkYXRhLW5hbWU9IkxheWVyIDUiPjxwYXRoIGNsYXNzPSJjbHMtMSIgZD0iTTMuNSA2LjE0djExYTEuMzggMS4zOCAwIDAgMCAxLjM3IDEuMzZoMTEuMjZhMS4zOCAxLjM4IDAgMCAwIDEuMzctMS4zN3YtMTEiLz48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Im0xOS41IDcuNS04LTYuMjVhMS41OSAxLjU5IDAgMCAwLTEuOTQgMEwxLjUgNy41TTEyLjczIDE4LjAydi03LjIxSDguMjd2Ny4yMSIvPjwvZz48L3N2Zz4=)}.scylla-icon--getting-started{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyMSAxOSI+PGcgZGF0YS1uYW1lPSJDYWxxdWUgNCI+PHBhdGggc3R5bGU9ImZpbGw6IzRkNGQ0ZCIgZD0ibTcgNC41IDguNTEgNS4wNUw3IDE0LjV2LTEweiIvPjxyZWN0IHg9IjEuNSIgeT0iLjUiIHdpZHRoPSIxOCIgaGVpZ2h0PSIxOCIgcng9IjIuNDMiIHN0eWxlPSJmaWxsOm5vbmU7c3Ryb2tlOiM0ZDRkNGQ7c3Ryb2tlLW1pdGVybGltaXQ6MTAiLz48L2c+PC9zdmc+)}.scylla-icon--glossary{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyMSAxOSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOm5vbmU7c3Ryb2tlOiM0ZDRkNGQ7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJDYWxxdWVfNCIgZGF0YS1uYW1lPSJDYWxxdWUgNCI+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNMi41IDIuNWgxM3YxNmgtMTN6Ii8+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNMTUuNTggMTcuMjFoMS45MlYuNWgtMTNhMi4zNCAyLjM0IDAgMCAwLTIgMiIvPjxwYXRoIGQ9Ik00LjggMTMuOTNhMSAxIDAgMCAwIC43NS0uNDMgNiA2IDAgMCAwIC41Mi0xLjA4bDIuODctNy4wN2guMzZsMi44OCA2Ljc5YTguOTIgOC45MiAwIDAgMCAuNzIgMS40Ny43Ni43NiAwIDAgMCAuNjguMzJ2LjMySDkuNHYtLjMyYTMuMjQgMy4yNCAwIDAgMCAuODMtLjExYy4xMy0uMDYuMi0uMTkuMi0uNDJhMS41OSAxLjU5IDAgMCAwLS4xLS40NmMwLS4xMi0uMS0uMjctLjE3LS40NGwtLjMzLS43OGgtMi45Yy0uMTkuNTEtLjMxLjg1LS4zNiAxYTIuMzggMi4zOCAwIDAgMC0uMTcuNzNjMCAuMTguMTIuMzIuMzcuNGEyLjU2IDIuNTYgMCAwIDAgLjY2LjA4di4zMkg0LjhabTQuODQtMi43Mi0xLjI0LTNoLS4xMWwtMS4xNiAzWiIgc3R5bGU9ImZpbGw6IzRkNGQ0ZCIvPjwvZz48L3N2Zz4=)}.scylla-icon--infoworld{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLW1pdGVybGltaXQ6MTB9PC9zdHlsZT48L2RlZnM+PGcgaWQ9IkNhbHF1ZV80IiBkYXRhLW5hbWU9IkNhbHF1ZSA0Ij48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Ik0xMiAyLjVINi41VjZjMCAzIC41NSA3LjE3IDUgOS41djQiLz48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Ik02LjQgNC40NGgtNFMyLjU2IDExIDguNSAxM00xOC41IDQuNWw0LS4wNnMtLjA2IDYuNTYtNiA4LjU2Ii8+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNMTIgMi41aDYuNVY2YzAgMi45NC0uNCA3LjA4LTUgOS41djRNOS41IDE5LjVoNnYyaC02eiIvPjxwYXRoIHN0eWxlPSJmaWxsOmdyYXk7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLW1pdGVybGltaXQ6MTAiIGQ9Ik03LjUgMjEuNWgxMHYxaC0xMHoiLz48L2c+PC9zdmc+)}.scylla-icon--integrations{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOm5vbmU7c3Ryb2tlOiM0ZDRkNGQ7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJDYWxxdWVfNCIgZGF0YS1uYW1lPSJDYWxxdWUgNCI+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJtMTQuNTYgMTIuNy0xLjI1LTEuNTctMS4zMS43NmE2IDYgMCAwIDAtMS42NS0xbC4wOC0xLjQ5LTItLjQtLjUzIDEuNDRhNS43MyA1LjczIDAgMCAwLTEuODcuMzFsLS44OC0xLjE5LTEuNzcgMUwzLjkyIDEyYTYuMyA2LjMgMCAwIDAtMS4yMiAxLjQxbC0xLjUtLjM1LS43NCAxLjg3IDEuMzguOGE2LjIzIDYuMjMgMCAwIDAgMCAxLjgzbC0xLjQxLjcyLjY0IDEuOTEgMS41OS0uMjhhNy42MyA3LjYzIDAgMCAwIC40OC42OCA1Ljg2IDUuODYgMCAwIDAgLjY3LjczbC0uNjIgMS40NiAxLjcyIDEgMS0xLjI0YTYuNDYgNi40NiAwIDAgMCAxLjc5LjM1bC40NiAxLjUyIDItLjN2LTEuNmE2LjQzIDYuNDMgMCAwIDAgMS42Mi0uODlsMS4zLjg1TDE0LjQzIDIxbC0xLTEuMmE2LjI0IDYuMjQgMCAwIDAgLjY4LTEuNzVsMS41MS0uMTkuMDUtMi0xLjUxLS4yNmE2LjA3IDYuMDcgMCAwIDAtLjYyLTEuODFabS01LjM1IDUuNTFhMS45MyAxLjkzIDAgMSAxIC4zMS0yLjcxIDEuOTIgMS45MiAwIDAgMS0uMzEgMi43MVoiLz48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Im0yNC4zMSA4LjA1LS4xMy0xLjY1LTEuMjUtLjA5YTUuMjYgNS4yNiAwIDAgMC0uNjctMS40NGwuNzUtMS0xLjE2LTEuMTctMSAuNzRhNS4xOCA1LjE4IDAgMCAwLTEuNDMtLjY2bC0uMDYtMS4yNC0xLjY1LS4xNy0uMzIgMS4yNWE1Ljc3IDUuNzcgMCAwIDAtMS41Mi4zOEwxNSAyLjFsLTEuMzcuOS41OCAxLjE4YTQuODggNC44OCAwIDAgMC0uODYgMS4yNWwtMS4zLS4xNi0uNDUgMS42IDEuMjIuNTVhNS4xNyA1LjE3IDAgMCAwIDAgLjY4QTQuMjggNC4yOCAwIDAgMCAxMyA5bC0xLjExLjcyLjY5IDEuNTEgMS4yOC0uMzdhNC45NCA0Ljk0IDAgMCAwIDEuMDcgMS4wN2wtLjM5IDEuMjYgMS41LjcxLjc0LTEuMDlhNS4wNyA1LjA3IDAgMCAwIDEuNTIuMTRsLjUgMS4xOSAxLjYxLS40MS0uMTMtMS4yOWE1LjE0IDUuMTQgMCAwIDAgMS4yNy0uODhsMS4xMi41NyAxLTEuMzUtLjkxLS44OGE0LjkgNC45IDAgMCAwIC40Mi0xLjUyWm0tNi4yIDEuNDNhMS43NCAxLjc0IDAgMSAxIDEuNi0xLjg2IDEuNzQgMS43NCAwIDAgMS0xLjYgMS44NloiLz48L2c+PC9zdmc+)}.scylla-icon--knowledge-base{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyMSAxOSI+PGRlZnM+PHN0eWxlPi5jbHMtMSwuY2xzLTJ7ZmlsbDpub25lO3N0cm9rZTojNGQ0ZDRkfS5jbHMtMXtzdHJva2UtbGluZWNhcDpyb3VuZDtzdHJva2UtbGluZWpvaW46cm91bmR9LmNscy0ye3N0cm9rZS1taXRlcmxpbWl0OjEwfTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJMYXllcl81IiBkYXRhLW5hbWU9IkxheWVyIDUiPjxwYXRoIGNsYXNzPSJjbHMtMSIgZD0iTTE2LjIxIDYuMzhhNS4zNiA1LjM2IDAgMCAxLTEuNTEgMy43MyA1IDUgMCAwIDAtMS40NSAzLjMxSDguNDdhNS40MSA1LjQxIDAgMCAwLTEuMjgtMy4xMSA1LjM3IDUuMzcgMCAxIDEgOS0zLjkzWk0xMy4yMyAxNS42N0g4LjQ1Ii8+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNMTMuMjQgMTMuNGgtNC44djQuMTZhLjcuNyAwIDAgMCAuNzEuN2gzLjM4YS43LjcgMCAwIDAgLjcxLS43WiIvPjxwYXRoIGNsYXNzPSJjbHMtMiIgZD0iTTEwLjg0IDguMjFhMS42NSAxLjY1IDAgMSAxIDEuNjQtMS42NSAxLjY1IDEuNjUgMCAwIDEtMS42NCAxLjY1Wk0xMC44NCA4LjY3djQuNjQiLz48L2c+PC9zdmc+)}.scylla-icon--less{background-image:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTciIGhlaWdodD0iMTciIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHJlY3Qgd2lkdGg9IjE3IiBoZWlnaHQ9IjE3IiByeD0iMSIgZmlsbD0iI0IzQkFDNSIvPjxwYXRoIGQ9Ik0xMyA4LjVhMSAxIDAgMCAxLTEgMUg1YTEgMSAwIDAgMSAwLTJoN2ExIDEgMCAwIDEgMSAxWiIgZmlsbD0iI2ZmZiIvPjxwYXRoIGQ9Ik0xMyA4LjVhMSAxIDAgMCAxLTEgMUg1YTEgMSAwIDAgMSAwLTJoN2ExIDEgMCAwIDEgMSAxWiIgZmlsbD0iI2ZmZiIvPjxwYXRoIGQ9Ik0xMyA4LjVhMSAxIDAgMCAxLTEgMUg1YTEgMSAwIDAgMSAwLTJoN2ExIDEgMCAwIDEgMSAxWiIgZmlsbD0iI2ZmZiIvPjxwYXRoIGQ9Ik0xMyA4LjVhMSAxIDAgMCAxLTEgMUg1YTEgMSAwIDAgMSAwLTJoN2ExIDEgMCAwIDEgMSAxWiIgZmlsbD0iI2ZmZiIvPjxwYXRoIGQ9Ik0xMyA4LjVhMSAxIDAgMCAxLTEgMUg1YTEgMSAwIDAgMSAwLTJoN2ExIDEgMCAwIDEgMSAxWiIgZmlsbD0iI2ZmZiIvPjwvc3ZnPg==);filter:none}.scylla-icon--live-test{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtNntmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLW1pdGVybGltaXQ6MTA7c3Ryb2tlLWxpbmVjYXA6cm91bmR9PC9zdHlsZT48L2RlZnM+PGcgaWQ9IkNhbHF1ZV80IiBkYXRhLW5hbWU9IkNhbHF1ZSA0Ij48Y2lyY2xlIGN4PSIxMi41IiBjeT0iMTUiIHI9IjkuNSIgc3R5bGU9InN0cm9rZS13aWR0aDoxLjVweDtzdHJva2UtbWl0ZXJsaW1pdDoxMDtmaWxsOm5vbmU7c3Ryb2tlOmdyYXkiLz48cGF0aCBzdHlsZT0ic3Ryb2tlLXdpZHRoOjEuMXB4O3N0cm9rZS1saW5lam9pbjpyb3VuZDtzdHJva2UtbGluZWNhcDpyb3VuZDtmaWxsOm5vbmU7c3Ryb2tlOmdyYXkiIGQ9Ik0xMCAuNWg1djJoLTV6Ii8+PHBhdGggc3R5bGU9InN0cm9rZS13aWR0aDoxLjExcHg7c3Ryb2tlLWxpbmVqb2luOnJvdW5kO3N0cm9rZS1saW5lY2FwOnJvdW5kO2ZpbGw6bm9uZTtzdHJva2U6Z3JheSIgZD0iTTUuOCA4LjIgNC4xMyA2LjUzbDEuOC0xLjgxTDcuNiA2LjQiLz48cGF0aCBzdHlsZT0ic3Ryb2tlLXdpZHRoOjEuMTNweDtzdHJva2UtbWl0ZXJsaW1pdDoxMDtmaWxsOm5vbmU7c3Ryb2tlOmdyYXkiIGQ9Ik0xMiA2VjIuNSIvPjxwYXRoIHN0eWxlPSJzdHJva2Utd2lkdGg6MS4wOHB4O3N0cm9rZS1taXRlcmxpbWl0OjEwO2ZpbGw6bm9uZTtzdHJva2U6Z3JheSIgZD0iTTEzIDZWMi41Ii8+PHBhdGggY2xhc3M9ImNscy02IiBkPSJNMTIuNSA4LjA2VjEwTTEyLjUgMjAuMDR2MS44OE03LjEzIDEwLjA4bDEuNzkgMS44OE0xNi4wNCAxNy4wOGwyIDEuODhNNyAxOC45MmwxLjg4LTEuODhNMTYuMTMgMTEuOTZsMS43OS0xLjgzIi8+PGVsbGlwc2UgY3g9IjEyLjUiIGN5PSIxNC4zNiIgcng9IjEuNSIgcnk9IjEuMzYiIHN0eWxlPSJmaWxsOmdyYXkiLz48cGF0aCBjbGFzcz0iY2xzLTYiIGQ9Im0xMi42MyAxNC41NCAyLjUgNi4zOCIvPjwvZz48L3N2Zz4=)}.scylla-icon--mail-list{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSJjdXJyZW50Q29sb3IiIHN0cm9rZS13aWR0aD0iMS41IiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiIGNsYXNzPSJmZWF0aGVyIGZlYXRoZXItbWFpbCI+PHBhdGggZD0iTTQgNGgxNmMxLjEgMCAyIC45IDIgMnYxMmMwIDEuMS0uOSAyLTIgMkg0Yy0xLjEgMC0yLS45LTItMlY2YzAtMS4xLjktMiAyLTJ6Ii8+PHBhdGggZD0ibTIyIDYtMTAgN0wyIDYiLz48L3N2Zz4=)}.scylla-icon--manager{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtM3tmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kO3N0cm9rZS13aWR0aDouOTdweH0uY2xzLTR7ZmlsbDpncmF5fTwvc3R5bGU+PC9kZWZzPjxwYXRoIHN0eWxlPSJmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kIiBkPSJNMTggMmg1djIySDNWMmg0LjkyIiBpZD0iQ2FscXVlXzIiIGRhdGEtbmFtZT0iQ2FscXVlIDIiLz48ZyBpZD0iQ2FscXVlXzQiIGRhdGEtbmFtZT0iQ2FscXVlIDQiPjxwYXRoIHN0eWxlPSJzdHJva2Utd2lkdGg6MS4wN3B4O2ZpbGw6bm9uZTtzdHJva2U6Z3JheTtzdHJva2UtbGluZWNhcDpyb3VuZDtzdHJva2UtbGluZWpvaW46cm91bmQiIGQ9Ik04IDBoMTB2NEg4eiIvPjxwYXRoIGNsYXNzPSJjbHMtMyIgZD0iTTcgOWgzdjNIN3pNNyAxNmgzdjNIN3oiLz48cGF0aCBjbGFzcz0iY2xzLTQiIGQ9Ik0xMi41IDkuNWg3djJoLTd6TTEyLjUgMTYuNWg3djJoLTd6Ii8+PC9nPjwvc3ZnPg==)}.scylla-icon--memory-management{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMSwuY2xzLTJ7ZmlsbDpub25lO3N0cm9rZTpncmF5O3N0cm9rZS1saW5lY2FwOnJvdW5kO3N0cm9rZS1saW5lam9pbjpyb3VuZH0uY2xzLTJ7c3Ryb2tlLXdpZHRoOjEuMTNweH08L3N0eWxlPjwvZGVmcz48ZyBpZD0iQ2FscXVlXzQiIGRhdGEtbmFtZT0iQ2FscXVlIDQiPjxyZWN0IGNsYXNzPSJjbHMtMSIgeD0iNS41IiB5PSI1LjUiIHdpZHRoPSIxNSIgaGVpZ2h0PSIxNSIgcng9IjIuNzQiIHJ5PSIyLjc0Ii8+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNOS41IDkuNWg3djdoLTd6Ii8+PHBhdGggY2xhc3M9ImNscy0yIiBkPSJNOC41IDUuNXYtNE0xMS41IDUuNXYtNE0xNC41IDUuNXYtNE0xNy41IDUuNXYtNE04LjUgMjQuNXYtNE0xMS41IDI0LjV2LTRNMTQuNSAyNC41di00TTE3LjUgMjQuNXYtNE0yMC41IDguNWg0TTIwLjUgMTEuNWg0TTIwLjUgMTQuNWg0TTIwLjUgMTcuNWg0TTEuNSA4LjVoNE0xLjUgMTEuNWg0TTEuNSAxNC41aDRNMS41IDE3LjVoNCIvPjwvZz48L3N2Zz4=)}.scylla-icon--monitoring{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGcgZGF0YS1uYW1lPSJDYWxxdWUgNCI+PHBhdGggZD0iTTUuNTUgMTAuODlhMy44MyAzLjgzIDAgMCAxLS4xNS0zLjc2IiBzdHlsZT0ic3Ryb2tlLWxpbmVqb2luOnJvdW5kO3N0cm9rZS1saW5lY2FwOnJvdW5kO3N0cm9rZTpncmF5O2ZpbGw6bm9uZSIvPjxyZWN0IHg9IjE3LjYzIiB5PSIxNC4wMSIgd2lkdGg9IjMuMDUiIGhlaWdodD0iMTAuOCIgcng9Ii41NyIgcnk9Ii41NyIgdHJhbnNmb3JtPSJyb3RhdGUoLTQ1IDE5LjE1OCAxOS40MDUpIiBzdHlsZT0ic3Ryb2tlLW1pdGVybGltaXQ6MTA7ZmlsbDpncmF5O3N0cm9rZS13aWR0aDouOTVweDtzdHJva2U6Z3JheSIvPjxjaXJjbGUgY3g9IjguNSIgY3k9IjkiIHI9IjciIHN0eWxlPSJzdHJva2Utd2lkdGg6MnB4O3N0cm9rZS1taXRlcmxpbWl0OjEwO3N0cm9rZTpncmF5O2ZpbGw6bm9uZSIvPjxwYXRoIHN0eWxlPSJzdHJva2UtbWl0ZXJsaW1pdDoxMDtzdHJva2UtbGluZWNhcDpyb3VuZDtzdHJva2U6Z3JheTtmaWxsOm5vbmUiIGQ9Im0xNi4wNSAxNi4zOS0yLjI4LTIuMjgiLz48L2c+PC9zdmc+)}.scylla-icon--networking{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMntmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLW1pdGVybGltaXQ6MTB9PC9zdHlsZT48L2RlZnM+PGcgaWQ9IkNhbHF1ZV80IiBkYXRhLW5hbWU9IkNhbHF1ZSA0Ij48Y2lyY2xlIGN4PSIxMi41IiBjeT0iMTIuNSIgcj0iNCIgc3R5bGU9InN0cm9rZS13aWR0aDouOTRweDtmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLW1pdGVybGltaXQ6MTAiLz48Y2lyY2xlIGNsYXNzPSJjbHMtMiIgY3g9IjUiIGN5PSIzIiByPSIyLjUiLz48Y2lyY2xlIGNsYXNzPSJjbHMtMiIgY3g9IjE5IiBjeT0iMjAiIHI9IjIuNSIvPjxjaXJjbGUgY2xhc3M9ImNscy0yIiBjeD0iMjIiIGN5PSI2LjYiIHI9IjIuNSIvPjxjaXJjbGUgY2xhc3M9ImNscy0yIiBjeD0iNC41IiBjeT0iMjIiIHI9IjIuNSIvPjxwYXRoIGNsYXNzPSJjbHMtMiIgZD0ibTYuODMgNS41IDMuMjUgNC4zM00yMC4yMyA3Ljg1IDE1LjMzIDExTTkuODMgMTUuMDhsLTQuMDkgNS44NE0xNC41OCAxNS4zM2wzIDMuMDkiLz48Y2lyY2xlIGN4PSIxMi41IiBjeT0iMTIuNSIgcj0iMS41IiBzdHlsZT0iZmlsbDpncmF5Ii8+PC9nPjwvc3ZnPg==)}.scylla-icon--news{background-image:url(data:image/svg+xml;base64,PHN2ZyBpZD0iQ2FscXVlXzEiIGRhdGEtbmFtZT0iQ2FscXVlIDEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmlld0JveD0iMCAwIDI1IDI1Ij48ZGVmcz48c3R5bGU+LmNscy0xe2ZpbGw6bm9uZTtzdHJva2U6Z3JheTtzdHJva2UtbGluZWNhcDpyb3VuZDtzdHJva2UtbGluZWpvaW46cm91bmR9PC9zdHlsZT48L2RlZnM+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNMyAxNS4xNyAxNi4zMSAzLjgyYTEuNDggMS40OCAwIDAgMSAyLjIyLjQ2bDUuMTUgOS42NWExLjQ2IDEuNDYgMCAwIDEtLjkzIDIuMTJMNS42OSAxOS45Wk04LjcxIDE5LjMzbC43NiAyLjIyYTEuNTEgMS41MSAwIDAgMCAxLjg1IDFsMy41OC0xLjA2YTEuNSAxLjUgMCAwIDAgMS0xLjg2TDE1LjQ1IDE4TTUuNTQgMjBsLTEuODMgMWEuOTIuOTIgMCAwIDEtMS4yNS0uMzdMLjYxIDE3LjQ5QS45Mi45MiAwIDAgMSAxIDE2LjI0bDEuODMtMU04LjUgMTRsNy4zOC01LjUiLz48L3N2Zz4=)}.scylla-icon--newsletter{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMSwuY2xzLTJ7ZmlsbDpub25lO3N0cm9rZTpncmF5O3N0cm9rZS1taXRlcmxpbWl0OjEwfS5jbHMtMntzdHJva2UtbGluZWNhcDpyb3VuZH08L3N0eWxlPjwvZGVmcz48ZyBpZD0iQ2FscXVlXzQiIGRhdGEtbmFtZT0iQ2FscXVlIDQiPjxwYXRoIGNsYXNzPSJjbHMtMSIgZD0iTTE5LjUgOS41aDN2MTJoLTIwdi0xMmgzIi8+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJtMi42NSA5Ljg0IDkuODUgNi44OCA4LjYzLTYuODgiLz48cGF0aCBjbGFzcz0iY2xzLTIiIGQ9Im01LjUgNy41LTMgMk0xNC4zNSAzLjg2bC0xLjQ2LTEuMDktMS40NyAxLjA5TTIxLjUgOS41bC0yLTJNMTkuNSAxMS41di03aC0xNHY3LjQ3Ii8+PC9nPjwvc3ZnPg==)}.scylla-icon--nsql-guides{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGcgZGF0YS1uYW1lPSJDYWxxdWUgNCI+PHJlY3QgeD0iNC4zNyIgeT0iMTMuNzEiIHdpZHRoPSIxLjE1IiBoZWlnaHQ9IjkuNzIiIHJ4PSIuNTQiIHJ5PSIuNTQiIHRyYW5zZm9ybT0icm90YXRlKDQ1IDQuOTQ4IDE4LjU3KSIgc3R5bGU9InN0cm9rZTpncmF5O3N0cm9rZS1taXRlcmxpbWl0OjEwO2ZpbGw6Z3JheTtzdHJva2Utd2lkdGg6MS4wOXB4Ii8+PGNpcmNsZSBjeD0iMTIuMjUiIGN5PSIxMi4yNSIgcj0iNC43NSIgc3R5bGU9InN0cm9rZS13aWR0aDoxLjVweDtmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLW1pdGVybGltaXQ6MTAiLz48cGF0aCBzdHlsZT0ic3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLXdpZHRoOjEuMDZweDtmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLW1pdGVybGltaXQ6MTAiIGQ9Ik04LjUgMjAuNXYzaDE1di0yMWgtMTV2MiIvPjwvZz48L3N2Zz4=)}.scylla-icon--open-source{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfS5jbHMtMntmaWxsOmdyYXl9PC9zdHlsZT48L2RlZnM+PGcgaWQ9IkNhbHF1ZV80IiBkYXRhLW5hbWU9IkNhbHF1ZSA0Ij48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Ik0uMzEgMjEuNTEgNSAxOS42OWEyLjM3IDIuMzcgMCAwIDEgMS44OC4xOWw1LjI0IDEuNjhhMi4yMyAyLjIzIDAgMCAwIDItLjEybDkuNS00Ljc1Yy44LS40NCAxLjY0LTEuMzEgMS4xMy0xLjkxYTIuMzQgMi4zNCAwIDAgMC0yLjY0LS40MkwxOCAxNi4wOSIvPjxwYXRoIGNsYXNzPSJjbHMtMSIgZD0ibS4yNSAxNS42OSA0Ljg4LTEuMjFjMS4yNS0uMyAyLjE3LS42MyAzLjQ0LS4xM2ExNS4yMSAxNS4yMSAwIDAgMCA0IDEuMWg0LjUyYy44NSAwIC45NS41NC45NSAxLjEzYTEgMSAwIDAgMS0xLjA4IDEgNjUuODYgNjUuODYgMCAwIDEtNy0uMzEiLz48cGF0aCBjbGFzcz0iY2xzLTIiIGQ9Ik04LjU2IDkuNjh2LS44MWMwLS45MS0uMzgtMS4yMS0xLjI5LTEuMjFIN1Y2LjNoLjMxYy45MSAwIDEuMjktLjMgMS4yOS0xLjIxdi0uODFjMC0xLjIuNjYtMS45MiAyLjgyLTIuM3YxLjE2Yy0xLjI0LjM1LTEuNDMuNjgtMS40MyAxLjR2Ljg3QTEuNTIgMS41MiAwIDAgMSA4Ljc1IDcgMS41MiAxLjUyIDAgMCAxIDEwIDguNTZ2Ljg3YzAgLjcxLjE5IDEgMS40MyAxLjRWMTJjLTIuMjEtLjM1LTIuODctMS4xMi0yLjg3LTIuMzJaTTE3LjQzIDQuM3YuODFjMCAuOTEuMzcgMS4yMSAxLjI5IDEuMjFIMTl2MS4zNmgtLjMxYy0uOTIgMC0xLjI5LjMtMS4yOSAxLjIxdi44MWMwIDEuMi0uNjUgMi0yLjgxIDIuMzV2LTEuMmMxLjI1LS4zNiAxLjQ0LS42OSAxLjQ0LTEuNHYtLjg3QTEuNTMgMS41MyAwIDAgMSAxNy4yNSA3IDEuNTMgMS41MyAwIDAgMSAxNiA1LjQzdi0uODdjMC0uNzItLjE5LTEtMS40NC0xLjRWMmMyLjIyLjM4IDIuODcgMS4xIDIuODcgMi4zWiIvPjwvZz48L3N2Zz4=)}.scylla-icon--operator{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjQuODEgMS4wMSAyOC4zMiAyNy42NCI+PHBhdGggZD0iTTMyLjUyIDE4cy0uMDkgMC0uMDktLjA1LS4wOCAwLS4xNyAwYTIuMTkgMi4xOSAwIDAgMC0uNTEgMCAuNDcuNDcgMCAwIDEtLjI2LS4wNSA5LjI5IDkuMjkgMCAwIDEtMS40OS0uMzIuNTQuNTQgMCAwIDEtLjMtLjMxbC0uMzQtLjA4YTExLjI1IDExLjI1IDAgMCAwLS4xOC0zLjc5IDExLjU1IDExLjU1IDAgMCAwLTEuNS0zLjUybC4yNi0uMjZhLjU5LjU5IDAgMCAxIC4xMy0uMzkgNy43MyA3LjczIDAgMCAxIDEuMi0uODZsLjI2LS4xMy40Ny0uM3MuMDkgMCAuMTMtLjA4IDAtLjA1IDAtLjA5YS44NC44NCAwIDAgMCAuMTctMS4yLjc4Ljc4IDAgMCAwLS42LS4zIDEgMSAwIDAgMC0uNi4yMWMtLjA1LjA1LS4wOS4wOS0uMTMuMDlhMy4wOCAzLjA4IDAgMCAwLS4zNS4zOWMwIC4wOC0uMTMuMTMtLjE3LjE3YTUuNjQgNS42NCAwIDAgMS0xLjA3Ljk0LjU4LjU4IDAgMCAxLS4yNi4wOS4yNS4yNSAwIDAgMS0uMTcgMGgtLjA1bC0uMzQuMjEtMS4wOC0xYTExIDExIDAgMCAwLTUuNjUtMi4yN3YtLjM0YS42LjYgMCAwIDEtLjIyLS4zNEE4LjE4IDguMTggMCAwIDEgMTkuNjYgM3YtLjI1YzAtLjA4LjA1LS4zNS4wOS0uNTJ2LS4zMWEuODIuODIgMCAwIDAtMS40Ni0uNi44Ni44NiAwIDAgMC0uMjYuNnYuMjJhMS44MiAxLjgyIDAgMCAwIC4wOS41MS41OS41OSAwIDAgMSAwIC4yNlYzYTguODIgOC44MiAwIDAgMSAuMDggMS40Ny41OS41OSAwIDAgMS0uMjEuMzRWNS4yNGMtLjQ4IDAtMSAuMTMtMS40Ny4yMmExMC4xNiAxMC4xNiAwIDAgMC01LjI4IDNMMTEgOC4yNGgtLjE3YS43My43MyAwIDAgMS0uMjYtLjA5IDcuOCA3LjggMCAwIDEtMS4wNy0xYzAtLjA4LS4xMy0uMTMtLjE3LS4xN3MtLjI1LS4yLS4zMy0uMzMtLjA4IDAtLjEzLS4wOHYtLjA1YTEgMSAwIDAgMC0uNi0uMjEuNjQuNjQgMCAwIDAtLjYuMy45MS45MSAwIDAgMCAuMTcgMS4yczAgLjA1IDAgLjA1LjA5LjA4LjEzLjA4YTUgNSAwIDAgMCAuNDcuMjZsLjI2LjEzYTYuNjEgNi42MSAwIDAgMSAxLjIxLjg2LjQ3LjQ3IDAgMCAxIC4xMy4zOXYtLjA1bC4yNS4yNmEyLjUzIDIuNTMgMCAwIDEtLjEzLjIyIDEwLjIgMTAuMiAwIDAgMC0xLjUgN2wtLjM1LjA5YzAgLjEzLS4xNy4yMS0uMy4zYTguNTYgOC41NiAwIDAgMS0xLjQ2LjI2LjU5LjU5IDAgMCAwLS4yNiAwaC0uNTJjLS4xOCAwLS4wOC4wNS0uMTcuMDVoLS4wOGEuODQuODQgMCAwIDAtLjY5IDEgLjc5Ljc5IDAgMCAwIC44Ni42LjM5LjM5IDAgMCAwIC4yMSAwSDYuMTJhMy42MSAzLjYxIDAgMCAwIC40Ny0uMTcuNjUuNjUgMCAwIDEgLjI2LS4wOCA3LjY1IDcuNjUgMCAwIDEgMS40Mi0uMzkuNDkuNDkgMCAwIDEgLjM1LjEzaC4zOWExMC4zMiAxMC4zMiAwIDAgMCAzLjUzIDUgNi4zMSA2LjMxIDAgMCAwIDEuMTYuNzdsLS4yMi4zYS41MS41MSAwIDAgMSAwIC40MyA2LjU0IDYuNTQgMCAwIDEtLjY5IDEuMjR2LjA1YS43OC43OCAwIDAgMS0uMTcuMjFjLS4wOS4wOS0uMTcuMjYtLjMuNDNzMCAuMDktLjA5LjEzIDAgLjA1IDAgLjA1YS44OC44OCAwIDAgMCAuMzQgMS4xNi45LjkgMCAwIDAgLjMuMDggMSAxIDAgMCAwIC44Mi0uNTFzMC0uMDguMDktLjEzLjEzLS4zLjE3LS40N2wuMDktLjI2YTcuMDcgNy4wNyAwIDAgMSAuNTYtMS4zMy42Mi42MiAwIDAgMSAuMzQtLjI2bC4xNy0uMzVhMTAuMDUgMTAuMDUgMCAwIDAgMy43NS42OSA4LjQ1IDguNDUgMCAwIDAgMi4zMi0uMyAxMS40NiAxMS40NiAwIDAgMCAxLjM3LS4zOWwuMTguMzFhLjYyLjYyIDAgMCAxIC4zNC4yNiA3LjA3IDcuMDcgMCAwIDEgLjU2IDEuMzNsLjA5LjI2YTEuMzEgMS4zMSAwIDAgMCAuMTcuNDdjMCAuMDUgMCAuMDkuMDkuMTNhMSAxIDAgMCAwIC44Mi41MSAxLjA1IDEuMDUgMCAwIDAgLjM0LS4wOC43Ni43NiAwIDAgMCAuMzktLjQ4IDEuMDggMS4wOCAwIDAgMC0uMDUtLjY0LjIuMiAwIDAgMC0uMDgtLjEzIDEuNTMgMS41MyAwIDAgMC0uMzEtLjQzLjY1LjY1IDAgMCAwLS4xNy0uMjJ2LS4wOWE1LjIyIDUuMjIgMCAwIDEtLjY5LTEuMjQuNTEuNTEgMCAwIDEgLjA1LS40M2wtLjEzLS4zNEExMC42OCAxMC42OCAwIDAgMCAyOSAxOC44MmwuMzQuMDV2LS4wNWEuNTQuNTQgMCAwIDEgLjM1LS4xMyA3LjgyIDcuODIgMCAwIDEgMS4zOC4zOS42Mi42MiAwIDAgMCAuMjYuMDkgMi40MiAyLjQyIDAgMCAwIC40Ny4yMXMuMDkgMCAuMTcgMGguMDlhLjM5LjM5IDAgMCAwIC4yMSAwIC45NC45NCAwIDAgMCAuODYtLjYgMSAxIDAgMCAwLS43Ny0uOVptLTEyLjQzLTEuMzMtMS4xNi41Ni0xLjE2LS41Ni0uMy0xLjI1LjgxLTFoMS4yOWwuODIgMVptNy0yLjc5YTggOCAwIDAgMSAuMTcgMi43MWwtNC4xNS0uNzVjLS4zOC0uMDgtLjY4LS45LS43MS0xLjIyYTQgNCAwIDAgMSAuMjEtLjc0bDMuNDUtMi41NGE4LjU4IDguNTggMCAwIDEgMS4wNCAyLjU0Wm0tMi4zMS00LjEzLTMuMjIgMi42OWExLjI4IDEuMjggMCAwIDEtMS4yNS0uMzdjLS4wOS0uMDktLjM3LS4yNS0uMzctLjM4VjcuNDNhOC4wNyA4LjA3IDAgMCAxIDQuODYgMi4zMlpNMTcgNy41NmwxLS4xOC0uMDYgNC4zMWMwIC4zOC0uNjQuNjgtMSAuNjhhMS4xMSAxLjExIDAgMCAxLS4zNS0uMDhMMTMgOS43NWE4LjQxIDguNDEgMCAwIDEgNC0yLjE5Wm0tNS4yNCAzLjc4IDMuMzcgMi40Ny4zMi41M2ExLjE0IDEuMTQgMCAwIDEtLjI1IDEgLjc4Ljc4IDAgMCAxLS4zOC4zMWwtNC4zMS45YTkgOSAwIDAgMSAxLjI0LTUuMjFaTTExIDE4LjYxbDQuMS0xLjIzYy4zNSAwIC44NC43MS44OSAxLjA2YS41MS41MSAwIDAgMS0uMDUuNDNsLTEuNjMgMy45NUE4LjQxIDguNDEgMCAwIDEgMTEgMTguNjFabTkuNzYgNS4zM2E4LjY3IDguNjcgMCAwIDEtMS44NS4yMSA5LjU5IDkuNTkgMCAwIDEtMi43MS0uNDNsMS42Ni00Yy4yMS0uMjYgMS0uMiAxLjMxIDBhMi40OCAyLjQ4IDAgMCAxIC4zNC4zbDIuMDcgMy43NGE1LjcyIDUuNzIgMCAwIDAtLjguMThaTTI2IDIwLjJhOC4zNiA4LjM2IDAgMCAxLTIuNTggMi41OGwtMS45Mi0zLjcyYTEuMTUgMS4xNSAwIDAgMSAuNDEtMWMuMjEtLjI1LjU5LS41OS43MS0uNTlsNC4yMiAxLjA2QTYuMjcgNi4yNyAwIDAgMSAyNiAyMC4yWiIgc3R5bGU9ImZpbGw6IzRkNGQ0ZCIgZGF0YS1uYW1lPSJDYWxxdWUgMiIvPjwvc3ZnPg==)}.scylla-icon--overview{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJDYWxxdWVfNCIgZGF0YS1uYW1lPSJDYWxxdWUgNCI+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNMjIuNjEgMy40NUMyMi42MSA1LjA2IDE4IDYuNSAxMi41IDYuNXMtMTAtMS40NC0xMC0zIDQuNS0zIDEwLTMgMTAuMTEgMS4zMyAxMC4xMSAyLjk1Wk0yMi42MSA5LjQ0YzAgMS42MS00LjY0IDMuMDYtMTAuMTEgMy4wNnMtMTAtMS40NS0xMC0zLjA2TTIyLjYxIDE1LjUxYzAgMS42Mi00LjY0IDMtMTAuMTEgM3MtMTAtMS4zNy0xMC0zTTIyLjYxIDIxLjU5YzAgMS42Mi00LjY0IDIuOTEtMTAuMTEgMi45MXMtMTAtMS4yOS0xMC0yLjkxTTIuNSAyMS40N1YzLjQ1TTIyLjUgMjEuNDdWMy40NSIvPjwvZz48L3N2Zz4=)}.scylla-icon--partners{background-image:url(data:image/svg+xml;base64,PHN2ZyBpZD0iQ2FscXVlXzEiIGRhdGEtbmFtZT0iQ2FscXVlIDEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmlld0JveD0iMCAwIDI1IDI1Ij48ZGVmcz48c3R5bGU+LmNscy0xe2ZpbGw6bm9uZTtzdHJva2U6Z3JheTtzdHJva2UtbGluZWNhcDpyb3VuZDtzdHJva2UtbGluZWpvaW46cm91bmR9PC9zdHlsZT48L2RlZnM+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNMTguNSA4LjI2aC00LjcybC0xLjIzIDEuMjdNMi4zOSAxNS4wOS4xNSAxMy43NGw0Ljg3LTguNDIgMi4yNCAxLjM0LTQuODcgOC40M3pNMjIuNTkgMTUuMDlsMi4yNC0xLjM1LTQuODYtOC40Mi0yLjI0IDEuMzQgNC44NiA4LjQzek0xMC43MSAxNS4yNmwtMi45MyAyLjIxTTEyLjE4IDE2LjRsLTIuOTMgMi4yMU0xMy42OCAxNy41M2wtMi45MyAyLjIyIi8+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNNi4zOCA4LjNoMy43OGEyLjI3IDIuMjcgMCAwIDEgMS4zNy40N2MxLjI2IDEgNC4wOSAzLjE4IDQuNDggMy41NnMtMS4xNCAxLjY4LTIuMjcgMS4xYTE4LjM0IDE4LjM0IDAgMCAwLTIuMTEtLjkyLjU3LjU3IDAgMCAwLS41Ni4wOWwtNC43OSAzLjg5TDEyLjMzIDIxbDkuNDYtNy4wOU0zLjI0IDE0LjIybDMuNCAxLjg1Ii8+PC9zdmc+)}.scylla-icon--plus{background-image:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTciIGhlaWdodD0iMTciIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHJlY3Qgd2lkdGg9IjE3IiBoZWlnaHQ9IjE3IiByeD0iMSIgZmlsbD0iI0IzQkFDNSIvPjxwYXRoIGZpbGwtcnVsZT0iZXZlbm9kZCIgY2xpcC1ydWxlPSJldmVub2RkIiBkPSJNOS41IDVhMSAxIDAgMSAwLTIgMHYyLjVINWExIDEgMCAxIDAgMCAyaDIuNVYxMmExIDEgMCAxIDAgMiAwVjkuNUgxMmExIDEgMCAxIDAgMC0ySDkuNVY1WiIgZmlsbD0iI2ZmZiIvPjxwYXRoIGZpbGwtcnVsZT0iZXZlbm9kZCIgY2xpcC1ydWxlPSJldmVub2RkIiBkPSJNOS41IDVhMSAxIDAgMSAwLTIgMHYyLjVINWExIDEgMCAxIDAgMCAyaDIuNVYxMmExIDEgMCAxIDAgMiAwVjkuNUgxMmExIDEgMCAxIDAgMC0ySDkuNVY1WiIgZmlsbD0iI2ZmZiIvPjxwYXRoIGZpbGwtcnVsZT0iZXZlbm9kZCIgY2xpcC1ydWxlPSJldmVub2RkIiBkPSJNOS41IDVhMSAxIDAgMSAwLTIgMHYyLjVINWExIDEgMCAxIDAgMCAyaDIuNVYxMmExIDEgMCAxIDAgMiAwVjkuNUgxMmExIDEgMCAxIDAgMC0ySDkuNVY1WiIgZmlsbD0iI2ZmZiIvPjxwYXRoIGZpbGwtcnVsZT0iZXZlbm9kZCIgY2xpcC1ydWxlPSJldmVub2RkIiBkPSJNOS41IDVhMSAxIDAgMSAwLTIgMHYyLjVINWExIDEgMCAxIDAgMCAyaDIuNVYxMmExIDEgMCAxIDAgMiAwVjkuNUgxMmExIDEgMCAxIDAgMC0ySDkuNVY1WiIgZmlsbD0iI2ZmZiIvPjxwYXRoIGZpbGwtcnVsZT0iZXZlbm9kZCIgY2xpcC1ydWxlPSJldmVub2RkIiBkPSJNOS41IDVhMSAxIDAgMSAwLTIgMHYyLjVINWExIDEgMCAxIDAgMCAyaDIuNVYxMmExIDEgMCAxIDAgMiAwVjkuNUgxMmExIDEgMCAxIDAgMC0ySDkuNVY1WiIgZmlsbD0iI2ZmZiIvPjwvc3ZnPg==);filter:none}.scylla-icon--pricing{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJDYWxxdWVfMiIgZGF0YS1uYW1lPSJDYWxxdWUgMiI+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJtMjEuNzMgNy0yLjQxLTUuMTJhMi41MiAyLjUyIDAgMCAwLTIuODItMWwtNi4wOCAyLjA0QTEuNjkgMS42OSAwIDAgMCA5LjUxIDRMMy45MyAxOS4yOWExLjA2IDEuMDYgMCAwIDAgLjY0IDEuMTdsMTAuMzQgMy43NmExIDEgMCAwIDAgMS4yMi0uNDNsNS41OC0xNS4zM0ExLjg3IDEuODcgMCAwIDAgMjEuNzMgN1oiLz48Y2lyY2xlIGNsYXNzPSJjbHMtMSIgY3g9IjE1LjczIiBjeT0iNS44OSIgcj0iMiIvPjx0ZXh0IHRyYW5zZm9ybT0icm90YXRlKDIwIC00OC4yNDQgMzAuNjcpIiBzdHlsZT0iZm9udC1zaXplOjEycHg7ZmlsbDpncmF5O2ZvbnQtZmFtaWx5OlJvYm90by1NZWRpdW0sUm9ib3RvIj4kPC90ZXh0PjwvZz48L3N2Zz4=)}.scylla-icon--release-note{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMntmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kO3N0cm9rZS13aWR0aDouOTFweH08L3N0eWxlPjwvZGVmcz48ZyBpZD0iQ2FscXVlXzIiIGRhdGEtbmFtZT0iQ2FscXVlIDIiPjxwYXRoIHN0eWxlPSJzdHJva2Utd2lkdGg6LjlweDtmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kIiBkPSJNMjEuNSAyNC41aC0xN1Y1LjdMOC45NS41NCAyMS41LjV2MjR6Ii8+PHBhdGggY2xhc3M9ImNscy0yIiBkPSJNNC42NSA1LjVIOS41VjFNNy41IDguNWgxMU03LjUgMTEuNWgxMU03LjUgMTQuNWgxMU03LjUgMTcuNWgxMU03LjUgMjAuNWgxMSIvPjwvZz48L3N2Zz4=)}.scylla-icon--resource-center{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfS5jbHMtMntmaWxsOmdyYXl9PC9zdHlsZT48L2RlZnM+PGcgaWQ9IkNhbHF1ZV80IiBkYXRhLW5hbWU9IkNhbHF1ZSA0Ij48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Ik01LjUgMi41aDYuOTFsLjA5IDIwaC03di0yMHoiLz48cGF0aCBjbGFzcz0iY2xzLTIiIGQ9Ik04IDRoMnYxMC45N0w4IDE1VjR6Ii8+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNNS4zNiAyLjI5IDIuNSAzLjV2MThsMi43OSAxLjE0Ii8+PHBhdGggc3R5bGU9InN0cm9rZS13aWR0aDouNjhweDtmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kIiBkPSJtMTIuNTcgMjEuODYgMS41Ny43NSIvPjxwYXRoIHN0eWxlPSJzdHJva2Utd2lkdGg6Ljg1cHg7ZmlsbDpub25lO3N0cm9rZTpncmF5O3N0cm9rZS1saW5lY2FwOnJvdW5kO3N0cm9rZS1saW5lam9pbjpyb3VuZCIgZD0ibTE0LjExIDIuNS0xLjU0LjU3Ii8+PGNpcmNsZSBjbGFzcz0iY2xzLTIiIGN4PSI5IiBjeT0iMTkiIHI9IjEiLz48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Ik0xNC41IDIuNWg2Ljk0bC4wNiAyMGgtN3YtMjB6Ii8+PHBhdGggY2xhc3M9ImNscy0yIiBkPSJNMTcgNGgydjEwLjk3TDE3IDE1VjR6Ii8+PGNpcmNsZSBjbGFzcz0iY2xzLTIiIGN4PSIxOCIgY3k9IjE5IiByPSIxIi8+PHBhdGggY2xhc3M9ImNscy0yIiBkPSJNMTIuNiAyLjczaDEuNjdWMjIuNkgxMi42ek0yLjU4IDIxLjVsMi43NSAxLjFWMi43M2wtMi42Ni45NC0uMDkgMTcuODN6Ii8+PC9nPjwvc3ZnPg==)}.scylla-icon--roadmap{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMSwuY2xzLTJ7ZmlsbDpub25lO3N0cm9rZTpncmF5fS5jbHMtMXtzdHJva2UtbGluZWNhcDpyb3VuZDtzdHJva2UtbGluZWpvaW46cm91bmQ7c3Ryb2tlLXdpZHRoOi45OHB4fS5jbHMtMntzdHJva2UtbWl0ZXJsaW1pdDoxMH0uY2xzLTN7ZmlsbDpncmF5fTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJDYWxxdWVfNCIgZGF0YS1uYW1lPSJDYWxxdWUgNCI+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJtLjUgNC41IDgtMyA4IDQgOC0zdjE3bC04IDMtOC00LTggM3YtMTd6TTguNSAxLjVWMThNMTYuNSA1LjVWMjIiLz48cGF0aCBjbGFzcz0iY2xzLTIiIGQ9Ik0yLjUgMTMgNyAxNi41TTcgMTJsLTQuNSA1LjVNMTguNSA4bDQuNSAzLjVNMjMgN2wtNC41IDUuNSIvPjxwYXRoIGNsYXNzPSJjbHMtMyIgZD0iTTEwIDEzaDF2MWgtMXpNMTIgMTJoMXYxaC0xek0xNCAxMWgxdjFoLTF6Ii8+PC9nPjwvc3ZnPg==)}.scylla-icon--search{background-image:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZD0iTTEwLjUgMThhNy41IDcuNSAwIDEgMCAwLTE1IDcuNSA3LjUgMCAwIDAgMCAxNVpNMjEgMjFsLTUuMi01LjIiIHN0cm9rZT0iIzAwMCIgc3Ryb2tlLXdpZHRoPSIyIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiLz48L3N2Zz4=)}.scylla-icon--slack{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0NDggNTEyIj48IS0tISBGb250IEF3ZXNvbWUgUHJvIDYuMC4wIGJ5IEBmb250YXdlc29tZSAtIGh0dHBzOi8vZm9udGF3ZXNvbWUuY29tIExpY2Vuc2UgLSBodHRwczovL2ZvbnRhd2Vzb21lLmNvbS9saWNlbnNlIChDb21tZXJjaWFsIExpY2Vuc2UpIENvcHlyaWdodCAyMDIyIEZvbnRpY29ucywgSW5jLi0tPjxwYXRoIGQ9Ik05NC4xMiAzMTUuMWMwIDI1LjktMjEuMTYgNDcuMDYtNDcuMDYgNDcuMDZTMCAzNDEgMCAzMTUuMWMwLTI1LjkgMjEuMTYtNDcuMDYgNDcuMDYtNDcuMDZoNDcuMDZ2NDcuMDZ6bTIzLjcyIDBjMC0yNS45IDIxLjE2LTQ3LjA2IDQ3LjA2LTQ3LjA2czQ3LjA2IDIxLjE2IDQ3LjA2IDQ3LjA2djExNy44NGMwIDI1LjktMjEuMTYgNDcuMDYtNDcuMDYgNDcuMDZzLTQ3LjA2LTIxLjE2LTQ3LjA2LTQ3LjA2VjMxNS4xem00Ny4wNi0xODguOThjLTI1LjkgMC00Ny4wNi0yMS4xNi00Ny4wNi00Ny4wNlMxMzkgMzIgMTY0LjkgMzJzNDcuMDYgMjEuMTYgNDcuMDYgNDcuMDZ2NDcuMDZIMTY0Ljl6bTAgMjMuNzJjMjUuOSAwIDQ3LjA2IDIxLjE2IDQ3LjA2IDQ3LjA2cy0yMS4xNiA0Ny4wNi00Ny4wNiA0Ny4wNkg0Ny4wNkMyMS4xNiAyNDMuOTYgMCAyMjIuOCAwIDE5Ni45czIxLjE2LTQ3LjA2IDQ3LjA2LTQ3LjA2SDE2NC45em0xODguOTggNDcuMDZjMC0yNS45IDIxLjE2LTQ3LjA2IDQ3LjA2LTQ3LjA2IDI1LjkgMCA0Ny4wNiAyMS4xNiA0Ny4wNiA0Ny4wNnMtMjEuMTYgNDcuMDYtNDcuMDYgNDcuMDZoLTQ3LjA2VjE5Ni45em0tMjMuNzIgMGMwIDI1LjktMjEuMTYgNDcuMDYtNDcuMDYgNDcuMDYtMjUuOSAwLTQ3LjA2LTIxLjE2LTQ3LjA2LTQ3LjA2Vjc5LjA2YzAtMjUuOSAyMS4xNi00Ny4wNiA0Ny4wNi00Ny4wNiAyNS45IDAgNDcuMDYgMjEuMTYgNDcuMDYgNDcuMDZWMTk2Ljl6TTI4My4xIDM4NS44OGMyNS45IDAgNDcuMDYgMjEuMTYgNDcuMDYgNDcuMDYgMCAyNS45LTIxLjE2IDQ3LjA2LTQ3LjA2IDQ3LjA2LTI1LjkgMC00Ny4wNi0yMS4xNi00Ny4wNi00Ny4wNnYtNDcuMDZoNDcuMDZ6bTAtMjMuNzJjLTI1LjkgMC00Ny4wNi0yMS4xNi00Ny4wNi00Ny4wNiAwLTI1LjkgMjEuMTYtNDcuMDYgNDcuMDYtNDcuMDZoMTE3Ljg0YzI1LjkgMCA0Ny4wNiAyMS4xNiA0Ny4wNiA0Ny4wNiAwIDI1LjktMjEuMTYgNDcuMDYtNDcuMDYgNDcuMDZIMjgzLjF6Ii8+PC9zdmc+)}.scylla-icon--stack-overflow{background-image:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjQiIGhlaWdodD0iMzEiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Im0yMS45NDkuMTEzIDIuMDQzIDExLjY3LTIuNTE0LjQzMkwxOS40MzUuNTQ1IDIxLjk1LjExNFptLTE3Ljk3MyAyNiAxMS45NDUtLjAwNS0uMDAyLTIuNTMtMTEuOTQ0LjAwNi4wMDEgMi41M1ptMTIuMjMyLTUuNzc3TDQuMzE1IDE5LjI1bC0uMjM1IDIuNTIgMTEuODk0IDEuMDg1LjIzNC0yLjUxOVptLTEwLjc1LTYuMzc1IDExLjUzNSAzLjA3NC0uNjYyIDIuNDQzLTExLjUzNS0zLjA3NS42NjItMi40NDJabTEzLjA0LjE4TDguMjEyIDguMTI2bC0xLjI5NyAyLjE3OCAxMC4yODkgNi4wMTcgMS4yOTYtMi4xNzhabS00LjIwNi0xMS41NiA2LjczIDkuNzg3LTIuMTA4IDEuNDI0LTYuNzMtOS43ODUgMi4xMDgtMS40MjVaIiBmaWxsPSIjMDAwIi8+PHBhdGggZD0iTTE3Ljk1IDE3Ljc4OVYyOC4xM0gyLjI4MlYxNy43ODlILjI0M3YxMi4zMjZIMTkuOThWMTcuNzg5aC0yLjAzWiIgZmlsbD0iIzAwMCIvPjwvc3ZnPg==)}.scylla-icon--summit{background-image:url(data:image/svg+xml;base64,PHN2ZyBpZD0iQ2FscXVlXzEiIGRhdGEtbmFtZT0iQ2FscXVlIDEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmlld0JveD0iMCAwIDI1IDI1Ij48ZGVmcz48c3R5bGU+LmNscy0xe2ZpbGw6bm9uZTtzdHJva2U6IzRkNGQ0ZDtzdHJva2UtbGluZWNhcDpyb3VuZDtzdHJva2UtbGluZWpvaW46cm91bmR9PC9zdHlsZT48L2RlZnM+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJtMTYuNSAyMiAxLTYuNS0xMCAuMDMgMSA2LjQzIi8+PHBhdGggZD0iTTMuNDYgMTJBNS42OSA1LjY5IDAgMCAxIDUgNy41IiBzdHlsZT0ic3Ryb2tlLXdpZHRoOjEuMXB4O3N0cm9rZTojNGQ0ZDRkO3N0cm9rZS1saW5lY2FwOnJvdW5kO3N0cm9rZS1saW5lam9pbjpyb3VuZDtmaWxsOm5vbmUiLz48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Ik0xNC42MiA1YTIuMzMgMi4zMyAwIDAgMS0yLjI1IDIuNWMtMS4zMyAwLTItMS4xMi0xLjk1LTIuNDRzLjctMi41IDItMi40OEEyLjI3IDIuMjcgMCAwIDEgMTQuNjIgNVpNMTcuNTggMTJhMy4yMyAzLjIzIDAgMCAwLTMuNDYtMy41SDExQTMuMjYgMy4yNiAwIDAgMCA3LjUgMTIiLz48Y2lyY2xlIGN4PSI0Ljk0IiBjeT0iNi45NiIgcj0iMS4wMSIgc3R5bGU9ImZpbGw6IzRkNGQ0ZDtzdHJva2Utd2lkdGg6MS4xcHg7c3Ryb2tlOiM0ZDRkNGQ7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kIi8+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNNy41NCAxOC41SDQuNWwtMi02aDIwbC0yIDZoLTMiLz48L3N2Zz4=)}.scylla-icon--support{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJDYWxxdWVfNCIgZGF0YS1uYW1lPSJDYWxxdWUgNCI+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNMTguMTkgNy41YTEwIDEwIDAgMCAxIC4yMSAyLjA3YzAgNC4zNi0yLjYzIDYuOTMtNS45IDYuOTNzLTUuOTQtMi41Ny01Ljk0LTYuOTNhMTAuNTEgMTAuNTEgMCAwIDEgLjIyLTIuMTIiLz48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Ik03LjY3IDIuMjNBNi41OCA2LjU4IDAgMCAxIDEyLjUuNWE1LjY1IDUuNjUgMCAwIDEgNC4yOSAxLjdjMS45MyAxLjk0IDIuMzUgNS4wNyAyLjQzIDYuNzJhMS40OSAxLjQ5IDAgMCAwLS43OS4wNSA4LjY4IDguNjggMCAwIDAtLjA4LTEuMTZoMGE1LjUzIDUuNTMgMCAwIDEtMS43Ny0yLjM0TDE2LjQ5IDVsLS4zOC4yMkExOSAxOSAwIDAgMSA2LjggNy4zOGEuNTIuNTIgMCAwIDAtLjQyLjE2Yy0uMjMuMjQtLjE1LjY1LS4wNyAxLjA4IDAgLjExIDAgLjIyLjA1LjMyYTEuNCAxLjQgMCAwIDAtLjU4IDBjLS4xLTEuNDUtLjA2LTQuNjggMS44OS02LjcxWk02LjM4IDljLS42NS0uMDgtMSAuMS0xLjE0Ljc5YTIuMDYgMi4wNiAwIDAgMCAxLjM3IDIuMjlNMTguNTYgOWMuNjUtLjA4IDEuMDUuMSAxLjE0Ljc5YTIuMDYgMi4wNiAwIDAgMS0xLjM3IDIuMjlNOS41IDE4LjIzVjE1LjVNMTUuNSAxNS41djIuNzNNMi41IDI0LjE2Yy4yNC0yIC41OS0zLjYzIDIuNDMtNC40OWEyNC4yOSAyNC4yOSAwIDAgMSA0LjgyLTEuMzdNMjIuNSAyNC4zM2MtLjI0LTItLjQyLTMuOC0yLjI2LTQuNjZhMjQuMjkgMjQuMjkgMCAwIDAtNC44Mi0xLjM3Ii8+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNMTUuMzkgMTguMzlhNC4zNyA0LjM3IDAgMCAxLTIuOTEgMS4wNyA0LjQyIDQuNDIgMCAwIDEtMi44OS0xLjA1Ii8+PHBhdGggc3R5bGU9ImZpbGw6Z3JheSIgZD0iTTExIDEzaDN2MmgtM3oiLz48cGF0aCBkPSJNMTguMDcgMTJhOS4yMSA5LjIxIDAgMCAxLTUuNTMgMi4wNyIgc3R5bGU9InN0cm9rZS1taXRlcmxpbWl0OjEwO2ZpbGw6bm9uZTtzdHJva2U6Z3JheSIvPjwvZz48L3N2Zz4=)}.scylla-icon--tech-talks{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJDYWxxdWVfNCIgZGF0YS1uYW1lPSJDYWxxdWUgNCI+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNOC4zOSA0LjVIMjMuNXYxM2gtMTUiLz48Y2lyY2xlIGN4PSI0LjUiIGN5PSI2LjUiIHI9IjIiIHN0eWxlPSJzdHJva2UtbWl0ZXJsaW1pdDoxMDtmaWxsOm5vbmU7c3Ryb2tlOmdyYXkiLz48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Ik0xLjUgOS41aDJsLjguODYuNy0uODZoNS41OGExIDEgMCAxIDEgMCAySDYuNXYxMC44OGExIDEgMCAwIDEtMSAxLjEyIDEgMSAwIDAgMS0xLTEgMSAxIDAgMCAxLTEgMSAuOTMuOTMgMCAwIDEtMS0xdi02Yy0uNzggMC0yLS40Ny0yLTF2LTVhMSAxIDAgMCAxIDEtMVoiLz48L2c+PC9zdmc+)}.scylla-icon--testing{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJDYWxxdWVfNCIgZGF0YS1uYW1lPSJDYWxxdWUgNCI+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNNi41IDYuNWgxMnYxMmgtMTJ6Ii8+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNNC41IDQuNWgxNnYxNmgtMTZ6Ii8+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJtOC41IDEwLjUgNSA1IDExLTEyIi8+PC9nPjwvc3ZnPg==)}.scylla-icon--thumbs-up{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSJjdXJyZW50Q29sb3IiIHN0cm9rZS13aWR0aD0iMiIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIiBjbGFzcz0iZmVhdGhlciBmZWF0aGVyLXRodW1icy11cCI+PHBhdGggZD0iTTE0IDlWNWEzIDMgMCAwIDAtMy0zbC00IDl2MTFoMTEuMjhhMiAyIDAgMCAwIDItMS43bDEuMzgtOWEyIDIgMCAwIDAtMi0yLjN6TTcgMjJINGEyIDIgMCAwIDEtMi0ydi03YTIgMiAwIDAgMSAyLTJoMyIvPjwvc3ZnPg==)}.scylla-icon--thumbs-down{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSJjdXJyZW50Q29sb3IiIHN0cm9rZS13aWR0aD0iMiIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIiBjbGFzcz0iZmVhdGhlciBmZWF0aGVyLXRodW1icy1kb3duIj48cGF0aCBkPSJNMTAgMTV2NGEzIDMgMCAwIDAgMyAzbDQtOVYySDUuNzJhMiAyIDAgMCAwLTIgMS43bC0xLjM4IDlhMiAyIDAgMCAwIDIgMi4zem03LTEzaDIuNjdBMi4zMSAyLjMxIDAgMCAxIDIyIDR2N2EyLjMxIDIuMzEgMCAwIDEtMi4zMyAySDE3Ii8+PC9zdmc+)}.scylla-icon--tip{background-image:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZD0iTTEyIDI0QzUuNCAyNCAwIDE4LjYgMCAxMlM1LjQgMCAxMiAwczEyIDUuNCAxMiAxMi01LjQgMTItMTIgMTJabTAtMjJDNi41IDIgMiA2LjUgMiAxMnM0LjUgMTAgMTAgMTAgMTAtNC41IDEwLTEwUzE3LjUgMiAxMiAyWiIgZmlsbD0iI2ZmZiIvPjxwYXRoIGQ9Ik0xMSAxNmMtLjMgMC0uNS0uMS0uNy0uM2wtMy0zYy0uNC0uNC0uNC0xIDAtMS40LjQtLjQgMS0uNCAxLjQgMGwzIDNjLjQuNC40IDEgMCAxLjQtLjIuMi0uNC4zLS43LjNaIiBmaWxsPSIjZmZmIi8+PHBhdGggZD0iTTExIDE2Yy0uMyAwLS41LS4xLS43LS4zLS40LS40LS40LTEgMC0xLjRsNi02Yy40LS40IDEtLjQgMS40IDAgLjQuNC40IDEgMCAxLjRsLTYgNmMtLjIuMi0uNC4zLS43LjNaIiBmaWxsPSIjZmZmIi8+PC9zdmc+)}.scylla-icon--training{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJDYWxxdWVfMiIgZGF0YS1uYW1lPSJDYWxxdWUgMiI+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNMTcuNSAxNS41SC41di0xM2gxOE01LjUgMjVsNC00LjMgNCA0LjMiLz48Y2lyY2xlIGN4PSIyMSIgY3k9IjQiIHI9IjIuNSIgc3R5bGU9InN0cm9rZS1taXRlcmxpbWl0OjEwO2ZpbGw6bm9uZTtzdHJva2U6Z3JheSIvPjxwYXRoIGNsYXNzPSJjbHMtMSIgZD0iTTIzLjQxIDcuNWgtMS41MkwyMSA5bC0uOS0xLjVIMTNBMS44IDEuOCAwIDAgMCAxMS41IDlhMS44IDEuOCAwIDAgMCAxLjUgMS41aDQuNXYxMy4yNEExLjQxIDEuNDEgMCAwIDAgMTkgMjVhMS40MiAxLjQyIDAgMCAwIDEuNS0xLjIyIDEuNTMgMS41MyAwIDAgMCAzIDB2LTcuMTFhMS4xMSAxLjExIDAgMCAwIDEuMDktMS4xOFY4LjY3YTEuMTggMS4xOCAwIDAgMC0xLjE4LTEuMTdaTTkuNSAxNS40NHY1LjM4Ii8+PC9nPjwvc3ZnPg==)}.collapsible-button .side-nav__content .toctree-checkbox:checked~label i,.collapsible-button .side-nav__content i,.scylla-icon--triangle-down,.side-nav__content .collapsible-button i,.side-nav__content .scylla-icon--expand,.side-nav__content .toctree-checkbox:checked~label .collapsible-button i,.side-nav__content .toctree-checkbox:checked~label .scylla-icon--expand{background-image:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTAiIGhlaWdodD0iNSIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cGF0aCBmaWxsLXJ1bGU9ImV2ZW5vZGQiIGNsaXAtcnVsZT0iZXZlbm9kZCIgZD0ibTAgMCA1IDUgNS01SDBaIiBmaWxsPSIjM0EyRDU1Ii8+PC9zdmc+)}.scylla-icon--university{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJDYWxxdWVfNCIgZGF0YS1uYW1lPSJDYWxxdWUgNCI+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJtMS41IDguNSAxMS00IDExIDR2M2wtMTEgNC0xMS00di0zeiIvPjxwYXRoIGNsYXNzPSJjbHMtMSIgZD0iTTUuNSAxMi41djVhMTIuNDYgMTIuNDYgMCAwIDAgNyAyIDExLjIgMTEuMiAwIDAgMCA3LTJ2LTUiLz48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Im0xMy41IDkuNSA4IDEuMjN2OC43N00yMi41IDE2LjV2MyIvPjwvZz48L3N2Zz4=)}.scylla-icon--users-blog{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMntmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJDYWxxdWVfNCIgZGF0YS1uYW1lPSJDYWxxdWUgNCI+PHBhdGggc3R5bGU9InN0cm9rZS13aWR0aDouOThweDtmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kIiBkPSJNMjMuNSAyLjVoLTIydjE2aDEzdjQuMTdsNC4wNC00LjE3IDQuOTYtLjA0VjIuNXoiLz48cGF0aCBjbGFzcz0iY2xzLTIiIGQ9Ik0xMC44NSA4QTEwLjM4IDEwLjM4IDAgMCAxIDExIDkuNWMwIDIuNDctMS4yMSA0LTMgNHMtMy41LTItMy41LTQuNWE0LjE4IDQuMTggMCAwIDEgMC0xIi8+PHBhdGggY2xhc3M9ImNscy0yIiBkPSJNNS4yIDUuMDdhMy4yMiAzLjIyIDAgMCAxIDIuNS0xIDMuMTYgMy4xNiAwIDAgMSAyLjQgMSA2LjIyIDYuMjIgMCAwIDEgMS4zIDMuODEuNzQuNzQgMCAwIDAtLjQyIDBjMC0uMjQgMC0uNDQtLjA1LS42NmgwQTMgMyAwIDAgMSAxMCA2Ljl2LS4yNGwtLjIxLjEyQTkuNjIgOS42MiAwIDAgMSA0LjczIDhhLjI1LjI1IDAgMCAwLS4yMi4wOWMtLjEzLjE0LS4wOS4zNyAwIC42MXYuMThhLjg1Ljg1IDAgMCAwLS4zMiAwQTUuMzcgNS4zNyAwIDAgMSA1LjIgNS4wN1pNNC41MSA4LjkzYy0uMzUgMC0uNTcuMDUtLjYxLjQ0YTEuMTcgMS4xNyAwIDAgMCAuNzMgMS4zTTExIDguOTNjLjM2IDAgLjU3LjA1LjYyLjQ0YTEuMTcgMS4xNyAwIDAgMS0uNzQgMS4zTTYuMzEgMTQuMTN2LS44NE05LjI1IDEzLjE5di45NE0yLjQyIDE4Yy4xMy0xLjE1LjU4LTIuNTIgMS41OC0zYTE0LjcxIDE0LjcxIDAgMCAxIDIuMzEtLjgyTTEzLjUgMThjLS4xMy0xLjE1LS41MS0yLjUyLTEuNS0zcy0yLjUtMS0yLjUtMSIvPjxwYXRoIGNsYXNzPSJjbHMtMiIgZD0iTTkuMzQgMTQuMjJhMi4yMyAyLjIzIDAgMCAxLTEuNTYuNjEgMi4zMiAyLjMyIDAgMCAxLTEuNTUtLjU5TTIxLjUgNi41aC03TTIxLjUgOS41aC03TTE4LjUgMTIuNWgtNCIvPjwvZz48L3N2Zz4=)}.admonition.caution .admonition-title:before,.admonition.warning .admonition-title:before,.scylla-icon--warning{background-image:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PG1hc2sgaWQ9ImEiIG1hc2stdHlwZT0iYWxwaGEiIG1hc2tVbml0cz0idXNlclNwYWNlT25Vc2UiIHg9IjAiIHk9IjEiIHdpZHRoPSIyNCIgaGVpZ2h0PSIyMSI+PHBhdGggZD0iTTMuNSAyMmMtLjUgMC0xLS4xLTEuNS0uNEMuNiAyMC44LjEgMTguOS45IDE3LjVMOS40IDMuM2MuMy0uNC42LS44IDEtMSAuNy0uNCAxLjUtLjUgMi4zLS4zLjguMiAxLjQuNyAxLjkgMS40TDIzIDE3LjVjLjMuNS40IDEgLjQgMS41IDAgLjgtLjMgMS42LS45IDIuMS0uNS42LTEuMi45LTIgLjloLTE3Wm03LjYtMTcuNkwyLjcgMTguNWMtLjMuNS0uMSAxLjEuNCAxLjQuMS4xLjMuMS40LjFoMTYuOWMuMyAwIC41LS4xLjctLjMuMi0uMi4zLS40LjMtLjcgMC0uMiAwLS4zLS4xLS41TDEyLjkgNC40Yy0uMy0uNS0uOS0uNi0xLjQtLjQtLjIuMS0uMy4yLS40LjRaIiBmaWxsPSIjMDYxOTM4Ii8+PHBhdGggZD0iTTEyIDE0Yy0uNiAwLTEtLjQtMS0xVjljMC0uNi40LTEgMS0xczEgLjQgMSAxdjRjMCAuNi0uNCAxLTEgMVpNMTIgMThjLS4zIDAtLjUtLjEtLjctLjMtLjItLjItLjMtLjQtLjMtLjcgMC0uMSAwLS4zLjEtLjQuMS0uMS4xLS4yLjItLjMuMS0uMS4yLS4yLjMtLjIuMi0uMS40LS4xLjYtLjEuMSAwIC4xIDAgLjIuMS4xIDAgLjEgMCAuMi4xIDAgMCAuMS4xLjIuMS4xLjEuMi4yLjIuMyAwIC4xLjEuMy4xLjQgMCAuMy0uMS41LS4zLjctLjMuMi0uNS4zLS44LjNaIiBmaWxsPSIjMDYxOTM4Ii8+PC9tYXNrPjxnIG1hc2s9InVybCgjYSkiPjxwYXRoIGZpbGw9IiMwNjE5MzgiIGQ9Ik0wIDBoMjR2MjRIMHoiLz48L2c+PC9zdmc+)}.scylla-icon--webinars{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMntmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJDYWxxdWVfNCIgZGF0YS1uYW1lPSJDYWxxdWUgNCI+PHBhdGggc3R5bGU9InN0cm9rZS1taXRlcmxpbWl0OjEwO2ZpbGw6bm9uZTtzdHJva2U6Z3JheSIgZD0iTTEuNSA1LjVoMjJ2MTRoLTIyeiIvPjxwYXRoIGNsYXNzPSJjbHMtMiIgZD0iTTkuNDcgMjAuNXYxLjg4TTE1LjUgMjAuNXYyTTYuNSAyMi41aDEyIi8+PHBhdGggc3R5bGU9ImZpbGw6Z3JheSIgZD0ibTkgOSA3LjUgMy41M0w5IDE2Vjl6Ii8+PC9nPjwvc3ZnPg==)}.scylla-icon--whitepapers{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMntmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJDYWxxdWVfNCIgZGF0YS1uYW1lPSJDYWxxdWUgNCI+PHBhdGggc3R5bGU9ImZpbGw6Z3JheSIgZD0iTTggOWg4djJIOHoiLz48cGF0aCBjbGFzcz0iY2xzLTIiIGQ9Ik0xNC4wNiAxLjUgMy41IDEuNTJWMjMuNWgxN1Y3bC02LjQ0LTUuNXoiLz48cGF0aCBkPSJNMTQuMzIgMS40MnYzLjM3YTIuMDYgMi4wNiAwIDAgMCAyLjA4IDIuMWgzLjY3IiBzdHlsZT0ic3Ryb2tlLW1pdGVybGltaXQ6MTA7ZmlsbDpub25lO3N0cm9rZTpncmF5Ii8+PHBhdGggY2xhc3M9ImNscy0yIiBkPSJNNi41IDE5LjVoNE0xMy41IDE5LjVoNE02LjUgMTYuNWg0TTEzLjUgMTYuNWg0TTYuNSAxMy41aDRNMTMuNSAxMy41aDQiLz48L2c+PC9zdmc+)}.scylla-icon--workshop{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMSwuY2xzLTJ7ZmlsbDpub25lO3N0cm9rZTojNGQ0ZDRkfS5jbHMtMXtzdHJva2UtbWl0ZXJsaW1pdDoxMH0uY2xzLTJ7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJDYWxxdWVfNCIgZGF0YS1uYW1lPSJDYWxxdWUgNCI+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNMS41IDUuNWgyMnYxNGgtMjJ6Ii8+PHBhdGggY2xhc3M9ImNscy0yIiBkPSJtOS41IDE5LjUtLjAzIDIuODhNMTUuNSAxOS41djNNNi41IDIyLjVoMTIiLz48cGF0aCBzdHlsZT0iZmlsbDojNGQ0ZDRkIiBkPSJtNCA4IDIgOCAuOTctMy45NUwxMSAxMiA0IDh6Ii8+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJtNi40NyAxMS4zNCAzLjM3IDQuMjgiLz48L2c+PC9zdmc+)}.button{background:transparent;border:1px solid #3a2d55;border-radius:4px;color:#3a2d55;display:inline;font-size:14px;letter-spacing:1px;line-height:21px;margin:0;padding:12px 14px}.button:focus,.button:hover{background:transparent;color:#3a2d55;text-decoration:none}.button--reverse{background:#fff;border:0}.button--reverse:focus,.button--reverse:hover{background:#fff}.tooltip{background-color:rgba(0,0,0,.56);border-radius:4px;font-size:12px;padding:6px}.tooltip:before{display:none!important}.tooltip:empty{display:none!important}.has-tip{border:0;cursor:pointer}.scylla-dropdown{color:#23263b;font-size:14px;line-height:20px}.scylla-dropdown a,.scylla-dropdown a:focus,.scylla-dropdown a:hover{color:#23263b!important;padding:0!important}.scylla-dropdown__item{font-size:16px;padding:15px}.scylla-dropdown__title{align-items:center;display:flex!important;position:static!important}.scylla-dropdown__title:after{display:none!important}.scylla-dropdown__title .chevron{min-height:5px;width:10px}.scylla-dropdown__content{background:#fff;border:0;border-radius:8px;box-shadow:0 4px 25px rgba(0,0,0,.15);font-size:16px;list-style:none;margin-top:15px;overflow:hidden;padding:16px 0;width:max-content}.scylla-dropdown__content li{padding:7px 16px}.scylla-dropdown__content .contents.local>ul>li a:before,.scylla-dropdown__content .secondary-side-nav__content li a:before,.scylla-dropdown__content li .admonition-title:before,.scylla-dropdown__content li .scylla-icon,.secondary-side-nav__content .scylla-dropdown__content li a:before{margin-right:10px}.enlarge-image{cursor:zoom-in}.enlarge-image-reveal{background:transparent;border:none;cursor:zoom-out;padding:0;text-align:center;width:fit-content}.enlarge-image-reveal img{background-color:#fff;padding:15px}.header{background-color:#fff;box-shadow:0 2px 22px rgba(74,93,166,.15);justify-content:space-between;padding:12.75px 0;position:fixed;width:100%;z-index:99}.header,.header-logo{align-items:center;display:flex}.header-logo{margin-left:20px;width:auto}.header-logo__img{width:110px}.header-logo__bar{background-color:#3a2d55;border-left:1px solid #3a2d55;height:11.56px;margin:0 7.5px;width:0}.header-logo__text{color:#3a2d55;font-size:10.11px;letter-spacing:.722408px;line-height:12px;text-transform:uppercase}.header-navigation{display:none}.header-button{display:none;margin-left:15px;text-transform:uppercase}.header-search-box{display:none;margin-right:20px;width:200px}.scylla-dropdown--header .scylla-dropdown__item{font-size:14px}.scylla-dropdown--header .scylla-dropdown__title{text-transform:uppercase}.scylla-dropdown--header .scylla-dropdown__title .chevron{margin-left:10px}.contents.local>ul>li .scylla-dropdown--header .scylla-dropdown__content a:before,.scylla-dropdown--header .scylla-dropdown__content .admonition-title:before,.scylla-dropdown--header .scylla-dropdown__content .contents.local>ul>li a:before,.scylla-dropdown--header .scylla-dropdown__content .scylla-icon,.scylla-dropdown--header .scylla-dropdown__content .secondary-side-nav__content li a:before,.secondary-side-nav__content li .scylla-dropdown--header .scylla-dropdown__content a:before{min-height:20px;width:20px}@media screen and (min-width:1024px){.header{padding:18px 0}.header-logo__img{width:152px}.header-logo__bar{height:16px;margin:0 10px}.header-logo__text{font-size:14px;letter-spacing:.722408px;line-height:12px;text-transform:uppercase}.header-navigation{align-items:center;display:flex;justify-content:center}.header-search-box{display:block}}@media screen and (min-width:1200px){.header-logo{margin-left:30px;width:357px}.header-search-box{margin-right:30px;max-width:20%;width:318px}.header-button{display:block}}.side-nav{background:#fff;display:none;height:100vh;left:0;line-height:24px;max-height:calc(100vh - 50px);overflow-y:auto;padding:20px 20px 0;position:fixed;top:50px;width:100%;z-index:100}.side-nav__title{font-weight:700;margin-bottom:20px}.side-nav__content{max-width:90%;overflow-wrap:break-word}.side-nav__content label,.side-nav__content label i{margin:0;padding:0}.side-nav__content label{font-size:inherit;line-height:1;margin-left:5px;max-height:5px}.collapsible-button .side-nav__content i,.side-nav__content .collapsible-button i,.side-nav__content .scylla-icon--expand{height:5px;vertical-align:top;width:10px}.side-nav__content .toctree-checkbox{display:none;position:absolute;right:20px}.side-nav__content .toctree-checkbox~ul{display:none;margin-right:20px}.side-nav__content .toctree-checkbox:checked~ul{display:block}.side-nav__content ul{margin:0}.side-nav__content a{color:#23263b}.side-nav__content a:hover{color:#3c4fe0;font-weight:400}.side-nav__content li{list-style:none;padding:0 0 24px}.side-nav__content li.has-children{align-items:center;display:flex;flex-wrap:wrap}.side-nav__content li.has-children>a{max-width:calc(100% - 15px)}.side-nav__content li.has-children.current{padding-bottom:20px}.side-nav__content li.has-children:hover>a{color:#3c4fe0}.side-nav__content li.has-children:hover>.toctree-checkbox~label i{filter:invert(38%) sepia(71%) saturate(6789%) hue-rotate(231deg) brightness(90%) contrast(95%)}.side-nav__content li.current-page>a{color:#3c4fe0}.side-nav__content li.current-page>.toctree-checkbox:checked~label i{filter:invert(38%) sepia(71%) saturate(6789%) hue-rotate(231deg) brightness(90%) contrast(95%)}.side-nav__content li ul{margin-top:18px;width:100%}.side-nav__content li ul li{border-left:1px solid #3c4fe0;padding:4px 0 4px 13px}.side-nav__content li ul ul{margin-left:0}.side-nav__content li .label{display:none}.side-nav__versions{max-width:90%}.side-nav__search,.side-nav__versions .dropdown{margin-bottom:20px}.collapsible-button{background:#fff;background-color:#fff;border:0;border-radius:8px;border-radius:50%;bottom:10px;box-shadow:0 4px 25px rgba(0,0,0,.15);cursor:pointer;display:none;font-size:0;left:300px;overflow:hidden;padding:13.5px;position:fixed}.collapsible-button i{height:16px;margin:0;width:16px}.side-nav--collapsed .collapsible-button{border-radius:0 20px 20px 0;left:-10px}.side-nav--collapsed .collapsible-button i{transform:rotate(180deg)}.layout--has-banner .side-nav{max-height:calc(100vh - 92.5px)}@media screen and (min-width:1024px){.side-nav{background-color:#f6f8ff;display:block;height:100%;left:auto;max-height:100vh;max-height:calc(100vh - 80px);padding:30px 40px;top:80px;width:286px;z-index:25}.side-nav__content{max-width:100%;padding-bottom:180px}.side-nav__search{display:none}.side-nav__versions{max-width:100%}.toctree-checkbox{right:40px}.layout--has-banner .side-nav{max-height:calc(100vh - 150px)}}@media screen and (min-width:1200px){.side-nav{width:357px}.side-nav--collapsed{background-color:transparent;padding-left:0;padding-right:0;width:126px}.side-nav--collapsed .side-nav-content{display:none}.collapsible-button{display:block}}.side-nav-toggle{cursor:pointer;display:block;margin-right:20px;position:relative;z-index:300}@media screen and (min-width:1024px){.side-nav-toggle{display:none}}.secondary-side-nav{display:none;height:100%;line-height:24px;padding:20px;width:100%}.secondary-side-nav__content{overflow-wrap:break-word}.secondary-side-nav__content ul{list-style:none;margin:0}.secondary-side-nav__content li{border-bottom:1px solid rgba(90,94,154,.1);display:none;padding:10px 0;word-break:break-word}.secondary-side-nav__content li:last-child{border:0}.secondary-side-nav__content li .label{display:none}.secondary-side-nav__content li a{align-items:baseline;color:#b3bac5;display:flex;font-size:14px}.secondary-side-nav__content li a:before{content:"";filter:invert(40%) sepia(11%) saturate(2157%) hue-rotate(198deg) brightness(89%) contrast(87%)!important;flex-shrink:0;margin-right:10px;min-height:10px;opacity:.5;width:6px}.secondary-side-nav__content li a.current,.secondary-side-nav__content li a:hover{color:#23263b;font-weight:400}.secondary-side-nav__content li a.current:before,.secondary-side-nav__content li a:hover:before{filter:brightness(0);opacity:1}.secondary-side-nav__content li a.current{font-weight:700}.secondary-side-nav__content>ul>li>ul>li{display:block}.secondary-side-nav__content>ul>li{border:0;display:block}.secondary-side-nav__content>ul>li>a{display:none}@media screen and (min-width:1200px){.secondary-side-nav{display:block;max-height:100vh;max-height:calc(100vh - 80px);overflow-y:auto;padding:60px 60px 60px 20px;position:fixed;top:80px;width:286px}.secondary-side-nav__content{padding-bottom:180px}.layout--has-banner .secondary-side-nav{max-height:calc(100vh - 150px)}}.layout{display:flex}.pre-content{align-items:center;display:flex;justify-content:space-between;margin-bottom:20px}.content{margin-top:50px;max-width:1440px;overflow-wrap:break-word;padding:20px;scroll-margin-top:50px;width:100%}.content .line-block,.content p{line-height:28px;margin-bottom:20px}.content ul{list-style:none}.content ul li:before{color:#b3bac5;content:"•";float:left;font-family:FontAwesome;font-size:20px;font-weight:700;margin-left:-1em;margin-top:-2px;width:1em}.content ul ul{list-style:circle}.content ul ul li:before{content:""}.content ol ol{list-style:lower-latin}.content img{margin-bottom:30px}.content section{margin-top:-50px;padding-top:50px}.content .inline-icon.fa-check{color:#42c4e6}.layout--full-width .content{max-width:100%;padding:0;width:100%}.layout--full-width .content .hero-wrapper,.layout--full-width .content .topics-grid{max-width:1190px}.layout--full-width .content.content--collapsed{margin-left:0}.layout--full-width:not(.layout--sidebar) .content{margin-left:0}.layout--has-banner .content{scroll-margin-top:92.5px}.layout--has-banner .content section{margin-top:-92.5px;padding-top:92.5px}.landing__content{padding:0 16px}@media screen and (min-width:1024px){.content{margin-left:286px;margin-top:80px;min-height:calc(100vh - 260px);padding-bottom:100px;scroll-margin-top:80px;width:calc(100% - 286px)}.content section{margin-top:-80px;padding-top:80px}}@media screen and (min-width:1200px){.content{margin-left:357px;padding:60px 40px 40px;width:calc(100% - 643px)}.content--collapsed{margin-left:126px;width:calc(100% - 412px)}.pre-content{margin-bottom:10px}.layout--has-banner .content{scroll-margin-top:150px}.layout--has-banner .content section{margin-top:-150px;padding-top:150px}.landing__content{padding:0 60px}.landing--floating .landing__content{position:relative;top:-70px}}.contents.local>ul{margin-bottom:30px;margin-left:0}.contents.local>ul>li{border-bottom:1px solid rgba(90,94,154,.1);padding:10px 0;word-break:break-word}.contents.local>ul>li:before{content:""}.contents.local>ul>li:last-child{border:0}.contents.local>ul>li ul{display:none}.contents.local>ul>li p{margin:0}.contents.local>ul>li a{font-size:14px}.contents.local>ul>li a:before{content:"";filter:invert(40%) sepia(11%) saturate(2157%) hue-rotate(198deg) brightness(89%) contrast(87%)!important;margin-right:10px;min-height:10px;opacity:.5;width:10px}.contents.local>ul>li a.current:before,.contents.local>ul>li a:hover:before{filter:brightness(0);opacity:1}.topic-title{color:rgba(35,38,59,.75);font-size:10px;letter-spacing:1.5px;margin-bottom:0;text-transform:uppercase}.notice{margin-top:40px}.footer{background-color:#fff;box-shadow:0 -4px 10px hsla(0,0%,82%,.25);padding:30px 0;position:relative;width:100%;z-index:50}.footer-group{margin:0 auto;max-width:1030px;padding:0 20px}.footer-top{align-items:center;border-bottom:1px solid rgba(0,0,0,.1);display:flex;flex-wrap:wrap;justify-content:space-between;padding-bottom:8px;text-align:center}.footer-logo{margin-bottom:30px;width:100%}.footer-logo img{float:left;height:36px}.footer-links{text-align:left}.footer-links__link{color:#333;font-size:12px;font-weight:500;letter-spacing:2.4px;margin-right:16px;text-transform:uppercase}.footer-actions{align-items:center;display:flex;justify-content:space-between;width:90px}.footer-actions__link{color:#000}.footer-actions__link img{height:23px}.footer-bottom{color:#979797;display:flex;flex-wrap:wrap;font-size:12px;font-style:normal;font-weight:400;justify-content:center;letter-spacing:1.4px;line-height:23px;padding:20px 0 10px;text-align:center;text-transform:uppercase}@media screen and (max-width:510px){.footer-links{margin-bottom:20px}}@media screen and (min-width:1024px){.footer{padding:30px 0}.footer-group{padding:0}.footer-top{padding-bottom:30px}.footer-logo{margin:0;width:auto}.footer-links{padding:0 40px}.footer-links__link{font-size:14px;margin-right:28px}.footer-actions{width:110px}.footer-actions__link img{height:28px}.footer-bottom .footer-bottom__copyright,.footer-bottom .footer-bottom__last-updated,.footer-bottom .footer-bottom__version{padding:0 10px}.footer-bottom .footer-bottom__copyright{border-left:none}}.not-found{background-color:#f6f8ff;height:100%;overflow:hidden}.not-found__icon{display:block;margin:40px auto;max-width:300px}.not-found__text{text-align:center}.not-found__text h1{font-size:60px;line-height:1}.not-found__text p{margin:30px 0;width:100%}.not-found__button{text-transform:uppercase}.admonition{border-radius:4px;box-shadow:0 4px 4px rgba(0,0,0,.12);color:rgba(0,0,0,.56);font-size:14px;line-height:20px;margin-bottom:30px;overflow:auto;padding:20px;position:relative}.admonition:before{bottom:0;content:" ";left:0;position:absolute;right:0;top:0;z-index:-1}.admonition-title{color:#23263b;margin-bottom:0!important}.admonition-title:before{content:"";margin-right:8px;min-height:24px;width:24px}.admonition p:not(.admonition-title){margin-bottom:0!important;margin-left:32px}.admonition.tip{border:1px solid #43a047}.admonition.tip:before{border-left:8px solid rgba(67,160,71,.4)}.admonition.tip .admonition-title:before{filter:invert(47%) sepia(11%) saturate(2286%) hue-rotate(73deg) brightness(109%) contrast(88%)}.admonition.note{border:1px solid #1976d2}.admonition.note:before{border-left:8px solid rgba(25,118,210,.4)}.admonition.note .admonition-title:before{filter:invert(44%) sepia(55%) saturate(2310%) hue-rotate(191deg) brightness(81%) contrast(103%)}.admonition.caution{border:1px solid #ffab00}.admonition.caution:before{border-left:8px solid rgba(255,171,0,.4)}.admonition.caution .admonition-title:before{filter:invert(77%) sepia(56%) saturate(3332%) hue-rotate(357deg) brightness(98%) contrast(108%)}.admonition.warning{border:1px solid #e74c3c}.admonition.warning:before{border-left:8px solid rgba(231,76,60,.4)}.admonition.warning .admonition-title:before{filter:invert(41%) sepia(42%) saturate(6427%) hue-rotate(343deg) brightness(99%) contrast(83%)}.breadcrumbs{margin-bottom:0;text-transform:uppercase}.breadcrumbs .bread__item,.breadcrumbs .bread__item:not(.bread__item--last):after,.breadcrumbs a{color:#23263b;font-size:12px;font-weight:400;letter-spacing:1.5px;line-height:2;margin:0;padding:0}.breadcrumbs .bread__item:before{display:none}.breadcrumbs .bread__item:not(.bread__item--last):after{content:"/";margin:0 5px;opacity:1;position:relative}.breadcrumbs .bread__highlight{color:#3c4fe0}.breadcrumbs .bread__highlight:hover{font-weight:700;text-decoration:none}code{background-color:#f7f8f9;border:none;border-radius:4px;color:#23263b;font-size:14px}code.download{background:none;color:#23263b}.highlight{background:transparent!important}.highlight pre{background-color:#f7f8f9;border-radius:8px;color:#23263b;font-size:14px;line-height:26px;margin-bottom:30px;overflow:auto;padding:16px}.highlight a.copybtn{right:1em;top:1em}.highlighttable{background-color:#f7f8f9;border-radius:16px;box-shadow:none}.highlighttable tbody{background-color:transparent;border:0}.highlighttable tbody td{padding:15px!important}.highlighttable tbody tr{border-top:none}.highlighttable .linenos{background-color:#f7f8f9;color:#5a7184;width:50px}.highlighttable .linenos span{line-height:26px}.highlighttable .highlight pre{background-color:transparent;margin:0;padding:0}.highlighttable .highlight a.copybtn{right:.2em;top:.2em}.hide-copy-button .copybtn{display:none}.sphinx_collapse__label{display:flex!important;flex-direction:row-reverse;font-size:medium;font-weight:700;justify-content:flex-end;margin-left:0!important}.sphinx_collapse__icon{margin-left:5px;margin-right:0}.sphinx_collapse__input:checked~.sphinx_collapse__label,.sphinx_collapse__label:hover{color:#3c4fe0}.sphinx_collapse__input:checked~.sphinx_collapse__label .sphinx_collapse__icon,.sphinx_collapse__label:hover .sphinx_collapse__icon{border-top-color:#3c4fe0}.sphinx_collapse__content{margin-top:10px}.contribute{margin:0 0 20px}.contribute__item{font-size:14px;list-style:none;padding-bottom:10px}.contribute__item .icon{margin-right:5px}.content-navigation{display:flex;justify-content:space-between;margin-top:40px}.navigation{max-width:50%;word-break:break-word}.navigation,.navigation__link{display:flex}.navigation__title{word-wrap:break-word;color:#23263b;font-size:12px;font-weight:500;letter-spacing:1.5px;line-height:24px;text-transform:uppercase}.navigation__title .colored{color:#42c4e6}.navigation__button{background:#fff;background-color:#fff;border:0;border-radius:8px;box-shadow:0 4px 25px rgba(0,0,0,.15);cursor:pointer;display:none;font-size:0;height:fit-content;overflow:hidden;padding:13.5px 16.5px}.navigation__button i{height:16px;margin:0;width:10px}.navigation--prev .navigation__title{margin-left:15px}.navigation--next .navigation__title{margin-right:15px;text-align:right}@media screen and (min-width:1200px){.navigation__title{display:inline-block}.navigation__button{display:block}.navigation--next .navigation__title{text-align:left}}.scylla-dropdown--versions .scylla-dropdown__item{background:#fff;border-radius:8px;box-shadow:0 28px 32px rgba(0,0,0,.06);width:100%}.scylla-dropdown--versions .scylla-dropdown__title{align-items:center;display:flex;justify-content:space-between}.scylla-dropdown--versions .scylla-dropdown__title .chevron{min-height:12px;transform:rotate(90deg);width:8px}@media screen and (min-width:1024px){.scylla-dropdown--versions .scylla-dropdown__item{box-shadow:none}}.feedback-container{font-size:16px;margin-top:40px;text-align:left}.feedback-container__title{font-weight:700;margin-bottom:5px!important}.feedback-container__button{background:#fff;border:0;border-radius:8px;box-shadow:0 4px 25px rgba(0,0,0,.15);cursor:pointer;margin:4px;overflow:hidden;padding:8px}.feedback-container__button.active{border:1px solid #3c4fe0}.feedback-container__icon{height:20px;width:20px}.feedback-container__message{font-size:16px;margin-top:10px}.hero{background:#f6f8ff;margin-bottom:30px;overflow:hidden;padding:30px 16px;text-align:left}.hero__title{font-size:28px;font-weight:500;line-height:38px;margin-bottom:14px;max-width:229px}.hero__text{font-size:16px;line-height:26px;max-width:343px}.hero__text a{border-bottom:1px dotted #23263b;color:#23263b}.hero__text p{margin-bottom:0!important}.hero__img{position:absolute;right:-18px;top:20px}.hero__img img{margin-bottom:0!important;width:124px}.hero__button{margin-top:20px;text-transform:uppercase}.hero__button .icon{margin-right:5px}.hero__search-box{box-shadow:0 4px 25px rgba(0,0,0,.02);margin-top:20px}.hero-wrapper{align-items:center;display:flex;justify-content:space-between;margin:0 auto;position:relative}@media screen and (min-width:640px){.hero{padding:60px 16px}.hero__title{font-size:32px;line-height:42px;max-width:482px}.hero__text{font-size:18px;line-height:26px;max-width:482px}.hero__img{display:block;position:static}.hero__img img{height:100%;width:295px}.hero .hero-wrapper{flex-direction:row-reverse}.hero .landing--floating .hero{padding:30px 16px 100px}}@media screen and (min-width:1024px){.hero{padding:60px}}.label{background-color:#23263b;border:0;border-radius:4px;color:#fff;font-size:inherit}.label--note{background-color:#1976d2}.label--tip{background-color:#43a047}.label--caution{background-color:#ffab00}.label--warning{background-color:#e74c3c}.last-updated{color:#4458a3;font-size:12px;letter-spacing:1.5px;margin:10px 0;text-transform:uppercase}.last-updated__icon{font-size:14px}@media screen and (min-width:1024px){.last-updated{float:right;margin:0}}.panel{border:0;border-radius:4px;margin-bottom:30px}.promo-banner{background-color:#4458a3;background-image:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTQ0MCIgaGVpZ2h0PSI3MCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48bWFzayBpZD0iYSIgbWFzay10eXBlPSJhbHBoYSIgbWFza1VuaXRzPSJ1c2VyU3BhY2VPblVzZSIgeD0iMCIgeT0iMCIgd2lkdGg9IjE0NDAiIGhlaWdodD0iNzAiPjxwYXRoIGZpbGw9IiM0NDU4QTMiIGQ9Ik0wIDBoMTQ0MHY3MEgweiIvPjwvbWFzaz48ZyBtYXNrPSJ1cmwoI2EpIiBmaWxsPSIjNTA2NEFFIj48cGF0aCBkPSJNLTE5MyAyMDEuODg0IDEuNS0xMzUgMzU3LjQzNiA3MC41bC0xOTQuNSAzMzYuODg0ek0xMDkyLjkyLTM4LjAwOSA5NzIuODAzLTI0Ni4wNTcgNDAyLjk5NiA4Mi45MiA1MjMuMTEzIDI5MC45N3oiLz48cGF0aCBkPSJtMTAzOC0zOC4wMDkgMTIwLjExNy0yMDguMDQ5IDU2OS44MDcgMzI4Ljk3OS0xMjAuMTE3IDIwOC4wNDl6Ii8+PC9nPjwvc3ZnPg==);background-position:50%;background-repeat:no-repeat;background-size:cover;display:none;overflow:hidden;position:fixed;top:0;width:100%;z-index:900}.promo-banner__icon{margin-right:15px}.promo-banner__icon img{height:40px}.promo-banner__title{color:#fff;font-size:12px;line-height:16px;margin-right:15px}.promo-banner__button{background:#fff;border-radius:4px;font-size:12px;min-width:max-content;padding:5px}.promo-banner__close{display:none;position:absolute;right:16px;top:16px}.contents.local>ul>li .promo-banner__close a:before,.promo-banner__close .admonition-title:before,.promo-banner__close .contents.local>ul>li a:before,.promo-banner__close .scylla-icon,.promo-banner__close .secondary-side-nav__content li a:before,.secondary-side-nav__content li .promo-banner__close a:before{filter:brightness(100%);height:34px;width:34px}.promo-banner__close:hover{cursor:pointer;filter:opacity(.8)}.promo-banner-wrapper{align-items:center;display:flex;justify-content:center;padding:5.85px 20px}@media(min-width:1024px){.promo-banner__title{font-size:18px;line-height:23px}.promo-banner__button{font-size:14px;padding:8.5px}.promo-banner__close{display:block}.promo-banner-wrapper{flex-direction:unset;padding:16px}}.custom-scroll-bar::-webkit-scrollbar{background-color:transparent;width:5px}.custom-scroll-bar::-webkit-scrollbar-thumb{background-color:#b3bac5;-webkit-border-radius:8px;border-radius:8px}.search-box{background:#f7f8f9;border-radius:4px;display:flex;padding:10px 15px}.search-box--hero{background-color:#fff;padding:12px 14px}.search-box:before{background-image:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZD0iTTEwLjUgMThhNy41IDcuNSAwIDEgMCAwLTE1IDcuNSA3LjUgMCAwIDAgMCAxNVpNMjEgMjFsLTUuMi01LjIiIHN0cm9rZT0iIzAwMCIgc3Ryb2tlLXdpZHRoPSIyIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiLz48L3N2Zz4=);background-repeat:no-repeat;background-size:contain;content:"";display:inline-block;filter:brightness(0);margin-top:2px;min-height:18px;min-width:18px;vertical-align:middle;width:20px}.search-box .er-dummy-search,.search-box .er-dummy-search-box,.search-box .er-search-form,.search-box ci-search,.search-box input{margin:0!important;width:100%!important}.search-box input{background:transparent!important;color:rgba(80,80,80,.5)!important;font-size:14px!important;padding:0!important}.search-box input::placeholder{color:rgba(80,80,80,.5)!important;opacity:1!important}.search-box button{display:none!important}.er_search_suggestions{background:#fff;border:0;border:0!important;border-radius:8px;box-shadow:0 4px 25px rgba(0,0,0,.15);overflow:hidden}.er_search_suggestions .er-search-result-box{border-width:1px!important;padding-bottom:10px!important;padding-top:10px!important}.er_search_suggestions .er-search-result-box:hover{background:#f7f8f9!important}.er_search_suggestions .er_more_result_btn{cursor:pointer}.er_search_suggestions h3{font-size:16px!important}.er-search-content{padding:20px!important}#er_search_results .er-search-result-box{display:block!important;margin:10px auto 0!important;width:100%!important}#er_search_results .text,#er_search_results .title a,#er_search_results .url a{max-width:100%!important}#search-result-input-form{max-width:800px!important}#er_search_button{text-align:center}#er_clear_input{right:0!important;top:0!important}.er-facet-header{background-color:transparent!important;border:0!important;padding:0 0 8px!important}.er-facet-val{padding:5px 2px!important}.er-facet-val input{display:block!important;margin:0}#er_search_pagination{margin-top:20px!important}#er_search_pagination li.er-paginator-list.er-active{border-bottom:0!important;font-weight:700}.er-suggestion-sm .er_search_input_dummy{margin:0!important}.er-suggestion-sm .er_search_button_dummy{border:0!important}#er_gcs_mobile_model_container .er-facet-values .er-facet-val{align-items:baseline}@media screen and (min-width:640px){.er-facets{display:none;max-width:300px!important;min-width:auto!important;width:auto!important}}@media screen and (min-width:1024px){.er-suggestions{left:15px!important}}@media screen and (min-width:1200px){.er-facets{display:block;position:fixed!important}.er-facet-count{display:none}}.sphinx-tabs{margin-bottom:30px}.sphinx-tabs-tab{border-bottom:1px solid rgba(0,0,0,.56);color:rgba(0,0,0,.56);cursor:pointer;font-size:14px;font-weight:500;line-height:13px;padding:20px 25px}.sphinx-tabs-tab[aria-selected=true]{border-bottom:2px solid #2196f3;color:#2196f3;padding-bottom:19px}.sphinx-tabs-panel{margin:30px 0}.table-wrapper{border:1px solid #e0e0e0;border-radius:4px;box-shadow:0 1px 2px rgba(0,0,0,.25);display:block;margin-bottom:30px;max-width:100%;overflow-x:auto}table{color:#000;font-size:14px;line-height:24px;margin:0;overflow:hidden}table p{margin:0!important}table caption{background:#f6f8ff;border-bottom:1px solid #e0e0e0;color:#23263b;padding:10px 25px}table thead{background:#f6f8ff;border:0;border-bottom:1px solid #4458a3}table thead th{color:#23263b;font-size:14px;font-weight:700}table td,table thead th{padding:20px 25px}table tbody tr{background-color:transparent!important;border-top:1px solid #e0e0e0;line-height:18px}table:not(.highlighttable) tbody tr:first-child{border-top:1px solid #4458a3}table.thead-border thead .row-odd th{color:#23263b}table.thead-border thead .row-even th{font-weight:400}table.thead-border thead th{border:1px solid #e0e0e0}table.thead-border thead tr:first-child th{border-top:none}table.thead-border thead tr:last-child th{border-bottom:none}table.thead-border thead tr th:first-child{border-left:none}table.thead-border thead tr th:last-child{border-right:none}.topics-grid{display:block;margin:0 auto 30px}.topics-grid__title{color:#23263b;font-size:24px;font-weight:700;line-height:32px;margin-bottom:6px}.topics-grid__text{color:#4458a3;font-size:18px;line-height:24px}.topics-grid--scrollable .hs{-ms-overflow-style:none;display:grid;grid-auto-flow:column;overflow-x:scroll;padding:20px 10px;scrollbar-width:none}.topics-grid--scrollable .hs::-webkit-scrollbar{display:none}.topics-grid--scrollable .hs .topic-box:last-child:after{content:"";width:20px}.topic-box{align-items:stretch;display:flex}.topic-box .card{background:#fff;border:1px solid transparent;border-radius:8px;box-shadow:0 4px 25px rgba(0,0,0,.15);display:flex;flex-direction:column;font-size:18px;margin:0 auto 30px;overflow:hidden;padding:20px;position:relative}.topic-box .card:hover{border:1px solid #4458a3;color:#23263b;font-weight:400}.topic-box__title{color:#23263b;font-size:16px;font-weight:700;line-height:24px;margin-bottom:0}.topic-box__title img{bottom:0;opacity:.3;position:absolute;right:0;top:0}.topic-box__body{color:#000;display:flex;flex-direction:column;flex-grow:1;max-width:80%}.topic-box__body .container{flex-grow:1;margin:0;padding:0}.topic-box__body .line-block,.topic-box__body p{font-size:16px;line-height:19px;margin-top:10px}.topic-box__anchor{color:#42c4e6;font-size:14px;font-weight:700;line-height:24px}.topic-box__icon{display:block;font-size:50px;margin-bottom:20px}.topic-box__icon i{filter:brightness(0);min-height:50px;width:100%}.topic-box__icon img{bottom:-12px;display:none;height:140px;margin:0;opacity:.3;position:absolute;right:-5px}.topic-box--product .card{box-shadow:none;padding:20px;text-align:center}.topic-box--product .card .topic-box__title{color:#23263b;font-size:14px}.topic-box--product .card .topic-box__body{display:flex;flex-direction:column;max-width:100%}.topic-box--product .card .topic-box__body .line-block,.topic-box--product .card .topic-box__body p{font-size:12px}.topic-box--product .card .topic-box__icon img{display:inline-block;max-height:84px;opacity:1;position:static}.topic-box--product .card:hover{background:#fff;border:0;border-radius:8px;box-shadow:0 4px 25px rgba(0,0,0,.15);overflow:hidden}@media screen and (max-width:1024px){.topics-grid--scrollable .topic-box{width:280px!important}.topic-box--product:nth-last-child(-n+2) .card{margin-bottom:0}}@media screen and (min-width:1024px){.topics-grid{margin-bottom:10px}.topics-grid__text{font-size:16px}.topics-grid--scrollable .hs{display:flex;overflow-x:initial;padding:0}.topics-grid--scrollable .hs .topic-box:last-child:after{display:none}.topic-box .card{margin-bottom:60px;padding:45px 30px}.topic-box__title{font-size:20px;line-height:32px}.topic-box__body .line-block,.topic-box__body p{font-size:18px;line-height:26px}.topic-box__anchor{font-size:20px;line-height:26px}.topic-box .topic-box__icon img{display:inline-block}.topic-box--product .card{padding:20px}.topic-box--product .card .topic-box__title{font-size:18px;line-height:24px}.topic-box--product .card .topic-box__body .line-block,.topic-box--product .card .topic-box__body p{font-size:14px}.topic-box--product .card .topic-box__icon img{max-height:111px}.landing .topics-grid--products{margin-bottom:40px}} \ No newline at end of file diff --git a/3.21.0-scylla/_static/doctools.js b/3.21.0-scylla/_static/doctools.js new file mode 100644 index 0000000000..8cbf1b161a --- /dev/null +++ b/3.21.0-scylla/_static/doctools.js @@ -0,0 +1,323 @@ +/* + * doctools.js + * ~~~~~~~~~~~ + * + * Sphinx JavaScript utilities for all documentation. + * + * :copyright: Copyright 2007-2021 by the Sphinx team, see AUTHORS. + * :license: BSD, see LICENSE for details. + * + */ + +/** + * select a different prefix for underscore + */ +$u = _.noConflict(); + +/** + * make the code below compatible with browsers without + * an installed firebug like debugger +if (!window.console || !console.firebug) { + var names = ["log", "debug", "info", "warn", "error", "assert", "dir", + "dirxml", "group", "groupEnd", "time", "timeEnd", "count", "trace", + "profile", "profileEnd"]; + window.console = {}; + for (var i = 0; i < names.length; ++i) + window.console[names[i]] = function() {}; +} + */ + +/** + * small helper function to urldecode strings + * + * See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/decodeURIComponent#Decoding_query_parameters_from_a_URL + */ +jQuery.urldecode = function(x) { + if (!x) { + return x + } + return decodeURIComponent(x.replace(/\+/g, ' ')); +}; + +/** + * small helper function to urlencode strings + */ +jQuery.urlencode = encodeURIComponent; + +/** + * This function returns the parsed url parameters of the + * current request. Multiple values per key are supported, + * it will always return arrays of strings for the value parts. + */ +jQuery.getQueryParameters = function(s) { + if (typeof s === 'undefined') + s = document.location.search; + var parts = s.substr(s.indexOf('?') + 1).split('&'); + var result = {}; + for (var i = 0; i < parts.length; i++) { + var tmp = parts[i].split('=', 2); + var key = jQuery.urldecode(tmp[0]); + var value = jQuery.urldecode(tmp[1]); + if (key in result) + result[key].push(value); + else + result[key] = [value]; + } + return result; +}; + +/** + * highlight a given string on a jquery object by wrapping it in + * span elements with the given class name. + */ +jQuery.fn.highlightText = function(text, className) { + function highlight(node, addItems) { + if (node.nodeType === 3) { + var val = node.nodeValue; + var pos = val.toLowerCase().indexOf(text); + if (pos >= 0 && + !jQuery(node.parentNode).hasClass(className) && + !jQuery(node.parentNode).hasClass("nohighlight")) { + var span; + var isInSVG = jQuery(node).closest("body, svg, foreignObject").is("svg"); + if (isInSVG) { + span = document.createElementNS("http://www.w3.org/2000/svg", "tspan"); + } else { + span = document.createElement("span"); + span.className = className; + } + span.appendChild(document.createTextNode(val.substr(pos, text.length))); + node.parentNode.insertBefore(span, node.parentNode.insertBefore( + document.createTextNode(val.substr(pos + text.length)), + node.nextSibling)); + node.nodeValue = val.substr(0, pos); + if (isInSVG) { + var rect = document.createElementNS("http://www.w3.org/2000/svg", "rect"); + var bbox = node.parentElement.getBBox(); + rect.x.baseVal.value = bbox.x; + rect.y.baseVal.value = bbox.y; + rect.width.baseVal.value = bbox.width; + rect.height.baseVal.value = bbox.height; + rect.setAttribute('class', className); + addItems.push({ + "parent": node.parentNode, + "target": rect}); + } + } + } + else if (!jQuery(node).is("button, select, textarea")) { + jQuery.each(node.childNodes, function() { + highlight(this, addItems); + }); + } + } + var addItems = []; + var result = this.each(function() { + highlight(this, addItems); + }); + for (var i = 0; i < addItems.length; ++i) { + jQuery(addItems[i].parent).before(addItems[i].target); + } + return result; +}; + +/* + * backward compatibility for jQuery.browser + * This will be supported until firefox bug is fixed. + */ +if (!jQuery.browser) { + jQuery.uaMatch = function(ua) { + ua = ua.toLowerCase(); + + var match = /(chrome)[ \/]([\w.]+)/.exec(ua) || + /(webkit)[ \/]([\w.]+)/.exec(ua) || + /(opera)(?:.*version|)[ \/]([\w.]+)/.exec(ua) || + /(msie) ([\w.]+)/.exec(ua) || + ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec(ua) || + []; + + return { + browser: match[ 1 ] || "", + version: match[ 2 ] || "0" + }; + }; + jQuery.browser = {}; + jQuery.browser[jQuery.uaMatch(navigator.userAgent).browser] = true; +} + +/** + * Small JavaScript module for the documentation. + */ +var Documentation = { + + init : function() { + this.fixFirefoxAnchorBug(); + this.highlightSearchWords(); + this.initIndexTable(); + if (DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS) { + this.initOnKeyListeners(); + } + }, + + /** + * i18n support + */ + TRANSLATIONS : {}, + PLURAL_EXPR : function(n) { return n === 1 ? 0 : 1; }, + LOCALE : 'unknown', + + // gettext and ngettext don't access this so that the functions + // can safely bound to a different name (_ = Documentation.gettext) + gettext : function(string) { + var translated = Documentation.TRANSLATIONS[string]; + if (typeof translated === 'undefined') + return string; + return (typeof translated === 'string') ? translated : translated[0]; + }, + + ngettext : function(singular, plural, n) { + var translated = Documentation.TRANSLATIONS[singular]; + if (typeof translated === 'undefined') + return (n == 1) ? singular : plural; + return translated[Documentation.PLURALEXPR(n)]; + }, + + addTranslations : function(catalog) { + for (var key in catalog.messages) + this.TRANSLATIONS[key] = catalog.messages[key]; + this.PLURAL_EXPR = new Function('n', 'return +(' + catalog.plural_expr + ')'); + this.LOCALE = catalog.locale; + }, + + /** + * add context elements like header anchor links + */ + addContextElements : function() { + $('div[id] > :header:first').each(function() { + $('\u00B6'). + attr('href', '#' + this.id). + attr('title', _('Permalink to this headline')). + appendTo(this); + }); + $('dt[id]').each(function() { + $('\u00B6'). + attr('href', '#' + this.id). + attr('title', _('Permalink to this definition')). + appendTo(this); + }); + }, + + /** + * workaround a firefox stupidity + * see: https://bugzilla.mozilla.org/show_bug.cgi?id=645075 + */ + fixFirefoxAnchorBug : function() { + if (document.location.hash && $.browser.mozilla) + window.setTimeout(function() { + document.location.href += ''; + }, 10); + }, + + /** + * highlight the search words provided in the url in the text + */ + highlightSearchWords : function() { + var params = $.getQueryParameters(); + var terms = (params.highlight) ? params.highlight[0].split(/\s+/) : []; + if (terms.length) { + var body = $('div.body'); + if (!body.length) { + body = $('body'); + } + window.setTimeout(function() { + $.each(terms, function() { + body.highlightText(this.toLowerCase(), 'highlighted'); + }); + }, 10); + $('') + .appendTo($('#searchbox')); + } + }, + + /** + * init the domain index toggle buttons + */ + initIndexTable : function() { + var togglers = $('img.toggler').click(function() { + var src = $(this).attr('src'); + var idnum = $(this).attr('id').substr(7); + $('tr.cg-' + idnum).toggle(); + if (src.substr(-9) === 'minus.png') + $(this).attr('src', src.substr(0, src.length-9) + 'plus.png'); + else + $(this).attr('src', src.substr(0, src.length-8) + 'minus.png'); + }).css('display', ''); + if (DOCUMENTATION_OPTIONS.COLLAPSE_INDEX) { + togglers.click(); + } + }, + + /** + * helper function to hide the search marks again + */ + hideSearchWords : function() { + $('#searchbox .highlight-link').fadeOut(300); + $('span.highlighted').removeClass('highlighted'); + }, + + /** + * make the url absolute + */ + makeURL : function(relativeURL) { + return DOCUMENTATION_OPTIONS.URL_ROOT + '/' + relativeURL; + }, + + /** + * get the current relative url + */ + getCurrentURL : function() { + var path = document.location.pathname; + var parts = path.split(/\//); + $.each(DOCUMENTATION_OPTIONS.URL_ROOT.split(/\//), function() { + if (this === '..') + parts.pop(); + }); + var url = parts.join('/'); + return path.substring(url.lastIndexOf('/') + 1, path.length - 1); + }, + + initOnKeyListeners: function() { + $(document).keydown(function(event) { + var activeElementType = document.activeElement.tagName; + // don't navigate when in search box, textarea, dropdown or button + if (activeElementType !== 'TEXTAREA' && activeElementType !== 'INPUT' && activeElementType !== 'SELECT' + && activeElementType !== 'BUTTON' && !event.altKey && !event.ctrlKey && !event.metaKey + && !event.shiftKey) { + switch (event.keyCode) { + case 37: // left + var prevHref = $('link[rel="prev"]').prop('href'); + if (prevHref) { + window.location.href = prevHref; + return false; + } + break; + case 39: // right + var nextHref = $('link[rel="next"]').prop('href'); + if (nextHref) { + window.location.href = nextHref; + return false; + } + break; + } + } + }); + } +}; + +// quick alias for translations +_ = Documentation.gettext; + +$(document).ready(function() { + Documentation.init(); +}); diff --git a/3.21.0-scylla/_static/documentation_options.js b/3.21.0-scylla/_static/documentation_options.js new file mode 100644 index 0000000000..6ff40585a4 --- /dev/null +++ b/3.21.0-scylla/_static/documentation_options.js @@ -0,0 +1,12 @@ +var DOCUMENTATION_OPTIONS = { + URL_ROOT: document.getElementById("documentation_options").getAttribute('data-url_root'), + VERSION: '3.21.0', + LANGUAGE: 'None', + COLLAPSE_INDEX: false, + BUILDER: 'html', + FILE_SUFFIX: '.html', + LINK_SUFFIX: '.html', + HAS_SOURCE: true, + SOURCELINK_SUFFIX: '.txt', + NAVIGATION_WITH_KEYS: false +}; \ No newline at end of file diff --git a/3.21.0-scylla/_static/file.png b/3.21.0-scylla/_static/file.png new file mode 100644 index 0000000000..a858a410e4 Binary files /dev/null and b/3.21.0-scylla/_static/file.png differ diff --git a/3.21.0-scylla/_static/img/banner-background.svg b/3.21.0-scylla/_static/img/banner-background.svg new file mode 100644 index 0000000000..f8520d5b3e --- /dev/null +++ b/3.21.0-scylla/_static/img/banner-background.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/3.21.0-scylla/_static/img/favicon-228x228.png b/3.21.0-scylla/_static/img/favicon-228x228.png new file mode 100644 index 0000000000..f30770c7ed Binary files /dev/null and b/3.21.0-scylla/_static/img/favicon-228x228.png differ diff --git a/3.21.0-scylla/_static/img/favicon-32x32.png b/3.21.0-scylla/_static/img/favicon-32x32.png new file mode 100644 index 0000000000..aae1708f26 Binary files /dev/null and b/3.21.0-scylla/_static/img/favicon-32x32.png differ diff --git a/3.21.0-scylla/_static/img/favicon.ico b/3.21.0-scylla/_static/img/favicon.ico new file mode 100644 index 0000000000..6c7484f082 Binary files /dev/null and b/3.21.0-scylla/_static/img/favicon.ico differ diff --git a/3.21.0-scylla/_static/img/icons/icon-about-team.svg b/3.21.0-scylla/_static/img/icons/icon-about-team.svg new file mode 100644 index 0000000000..5448c7f007 --- /dev/null +++ b/3.21.0-scylla/_static/img/icons/icon-about-team.svg @@ -0,0 +1 @@ +icon-about-team diff --git a/3.21.0-scylla/_static/img/icons/icon-about-us-m.svg b/3.21.0-scylla/_static/img/icons/icon-about-us-m.svg new file mode 100644 index 0000000000..09107d9520 --- /dev/null +++ b/3.21.0-scylla/_static/img/icons/icon-about-us-m.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/3.21.0-scylla/_static/img/icons/icon-about-us.svg b/3.21.0-scylla/_static/img/icons/icon-about-us.svg new file mode 100644 index 0000000000..1b1fcc83e3 --- /dev/null +++ b/3.21.0-scylla/_static/img/icons/icon-about-us.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/3.21.0-scylla/_static/img/icons/icon-alternator.svg b/3.21.0-scylla/_static/img/icons/icon-alternator.svg new file mode 100644 index 0000000000..7c2b4ebae0 --- /dev/null +++ b/3.21.0-scylla/_static/img/icons/icon-alternator.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/3.21.0-scylla/_static/img/icons/icon-apps.svg b/3.21.0-scylla/_static/img/icons/icon-apps.svg new file mode 100644 index 0000000000..7e93612026 --- /dev/null +++ b/3.21.0-scylla/_static/img/icons/icon-apps.svg @@ -0,0 +1 @@ + diff --git a/3.21.0-scylla/_static/img/icons/icon-architecture.svg b/3.21.0-scylla/_static/img/icons/icon-architecture.svg new file mode 100644 index 0000000000..67ebbc2f38 --- /dev/null +++ b/3.21.0-scylla/_static/img/icons/icon-architecture.svg @@ -0,0 +1 @@ +icon-architecture diff --git a/3.21.0-scylla/_static/img/icons/icon-benchmarks.svg b/3.21.0-scylla/_static/img/icons/icon-benchmarks.svg new file mode 100644 index 0000000000..e1ce2c1d78 --- /dev/null +++ b/3.21.0-scylla/_static/img/icons/icon-benchmarks.svg @@ -0,0 +1 @@ +icon-benchmarks diff --git a/3.21.0-scylla/_static/img/icons/icon-blog.svg b/3.21.0-scylla/_static/img/icons/icon-blog.svg new file mode 100644 index 0000000000..f4096cbf11 --- /dev/null +++ b/3.21.0-scylla/_static/img/icons/icon-blog.svg @@ -0,0 +1 @@ +icon-blog2 diff --git a/3.21.0-scylla/_static/img/icons/icon-careers.svg b/3.21.0-scylla/_static/img/icons/icon-careers.svg new file mode 100644 index 0000000000..2a7c6ea0b7 --- /dev/null +++ b/3.21.0-scylla/_static/img/icons/icon-careers.svg @@ -0,0 +1 @@ +icon-careers diff --git a/3.21.0-scylla/_static/img/icons/icon-chevron-left.svg b/3.21.0-scylla/_static/img/icons/icon-chevron-left.svg new file mode 100644 index 0000000000..3afa25c481 --- /dev/null +++ b/3.21.0-scylla/_static/img/icons/icon-chevron-left.svg @@ -0,0 +1,3 @@ + + + diff --git a/3.21.0-scylla/_static/img/icons/icon-chevron-right.svg b/3.21.0-scylla/_static/img/icons/icon-chevron-right.svg new file mode 100644 index 0000000000..44eb829cdc --- /dev/null +++ b/3.21.0-scylla/_static/img/icons/icon-chevron-right.svg @@ -0,0 +1,3 @@ + + + diff --git a/3.21.0-scylla/_static/img/icons/icon-circe.svg b/3.21.0-scylla/_static/img/icons/icon-circe.svg new file mode 100644 index 0000000000..875e421670 --- /dev/null +++ b/3.21.0-scylla/_static/img/icons/icon-circe.svg @@ -0,0 +1 @@ + diff --git a/3.21.0-scylla/_static/img/icons/icon-clock.svg b/3.21.0-scylla/_static/img/icons/icon-clock.svg new file mode 100644 index 0000000000..8c92469808 --- /dev/null +++ b/3.21.0-scylla/_static/img/icons/icon-clock.svg @@ -0,0 +1 @@ + diff --git a/3.21.0-scylla/_static/img/icons/icon-close.svg b/3.21.0-scylla/_static/img/icons/icon-close.svg new file mode 100644 index 0000000000..d1162b73e7 --- /dev/null +++ b/3.21.0-scylla/_static/img/icons/icon-close.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/3.21.0-scylla/_static/img/icons/icon-cloud-docs.svg b/3.21.0-scylla/_static/img/icons/icon-cloud-docs.svg new file mode 100644 index 0000000000..a9069bb6e5 --- /dev/null +++ b/3.21.0-scylla/_static/img/icons/icon-cloud-docs.svg @@ -0,0 +1 @@ + diff --git a/3.21.0-scylla/_static/img/icons/icon-cloud.svg b/3.21.0-scylla/_static/img/icons/icon-cloud.svg new file mode 100644 index 0000000000..cfb2318dae --- /dev/null +++ b/3.21.0-scylla/_static/img/icons/icon-cloud.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/3.21.0-scylla/_static/img/icons/icon-comparison.svg b/3.21.0-scylla/_static/img/icons/icon-comparison.svg new file mode 100644 index 0000000000..49d809a5df --- /dev/null +++ b/3.21.0-scylla/_static/img/icons/icon-comparison.svg @@ -0,0 +1 @@ +icon-comparison diff --git a/3.21.0-scylla/_static/img/icons/icon-contact-us.svg b/3.21.0-scylla/_static/img/icons/icon-contact-us.svg new file mode 100644 index 0000000000..9df3145dd2 --- /dev/null +++ b/3.21.0-scylla/_static/img/icons/icon-contact-us.svg @@ -0,0 +1 @@ +icon-contact-us diff --git a/3.21.0-scylla/_static/img/icons/icon-developers-blog.svg b/3.21.0-scylla/_static/img/icons/icon-developers-blog.svg new file mode 100644 index 0000000000..ee804197a0 --- /dev/null +++ b/3.21.0-scylla/_static/img/icons/icon-developers-blog.svg @@ -0,0 +1 @@ +icon-developers-blog diff --git a/3.21.0-scylla/_static/img/icons/icon-docs.svg b/3.21.0-scylla/_static/img/icons/icon-docs.svg new file mode 100644 index 0000000000..5501492f3e --- /dev/null +++ b/3.21.0-scylla/_static/img/icons/icon-docs.svg @@ -0,0 +1 @@ +icon-docs diff --git a/3.21.0-scylla/_static/img/icons/icon-enterprise-m.svg b/3.21.0-scylla/_static/img/icons/icon-enterprise-m.svg new file mode 100644 index 0000000000..97be900b50 --- /dev/null +++ b/3.21.0-scylla/_static/img/icons/icon-enterprise-m.svg @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/3.21.0-scylla/_static/img/icons/icon-enterprise.svg b/3.21.0-scylla/_static/img/icons/icon-enterprise.svg new file mode 100644 index 0000000000..ee1ac26283 --- /dev/null +++ b/3.21.0-scylla/_static/img/icons/icon-enterprise.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/3.21.0-scylla/_static/img/icons/icon-events.svg b/3.21.0-scylla/_static/img/icons/icon-events.svg new file mode 100644 index 0000000000..ba5f211864 --- /dev/null +++ b/3.21.0-scylla/_static/img/icons/icon-events.svg @@ -0,0 +1 @@ +icon-events diff --git a/3.21.0-scylla/_static/img/icons/icon-exclamation.svg b/3.21.0-scylla/_static/img/icons/icon-exclamation.svg new file mode 100644 index 0000000000..a7eb4b77a4 --- /dev/null +++ b/3.21.0-scylla/_static/img/icons/icon-exclamation.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/3.21.0-scylla/_static/img/icons/icon-expand.svg b/3.21.0-scylla/_static/img/icons/icon-expand.svg new file mode 100644 index 0000000000..3806565367 --- /dev/null +++ b/3.21.0-scylla/_static/img/icons/icon-expand.svg @@ -0,0 +1,50 @@ + + + + + + + + + diff --git a/3.21.0-scylla/_static/img/icons/icon-forum.svg b/3.21.0-scylla/_static/img/icons/icon-forum.svg new file mode 100644 index 0000000000..37a709f7a8 --- /dev/null +++ b/3.21.0-scylla/_static/img/icons/icon-forum.svg @@ -0,0 +1 @@ + diff --git a/3.21.0-scylla/_static/img/icons/icon-getting-started.svg b/3.21.0-scylla/_static/img/icons/icon-getting-started.svg new file mode 100644 index 0000000000..702500be40 --- /dev/null +++ b/3.21.0-scylla/_static/img/icons/icon-getting-started.svg @@ -0,0 +1 @@ + diff --git a/3.21.0-scylla/_static/img/icons/icon-glossary.svg b/3.21.0-scylla/_static/img/icons/icon-glossary.svg new file mode 100644 index 0000000000..e8329c2afe --- /dev/null +++ b/3.21.0-scylla/_static/img/icons/icon-glossary.svg @@ -0,0 +1 @@ + diff --git a/3.21.0-scylla/_static/img/icons/icon-home.svg b/3.21.0-scylla/_static/img/icons/icon-home.svg new file mode 100644 index 0000000000..f0b9c25419 --- /dev/null +++ b/3.21.0-scylla/_static/img/icons/icon-home.svg @@ -0,0 +1 @@ + diff --git a/3.21.0-scylla/_static/img/icons/icon-infoworld.svg b/3.21.0-scylla/_static/img/icons/icon-infoworld.svg new file mode 100644 index 0000000000..906e87279c --- /dev/null +++ b/3.21.0-scylla/_static/img/icons/icon-infoworld.svg @@ -0,0 +1 @@ +icon-infoworld diff --git a/3.21.0-scylla/_static/img/icons/icon-integrations.svg b/3.21.0-scylla/_static/img/icons/icon-integrations.svg new file mode 100644 index 0000000000..1ef0920d49 --- /dev/null +++ b/3.21.0-scylla/_static/img/icons/icon-integrations.svg @@ -0,0 +1 @@ + diff --git a/3.21.0-scylla/_static/img/icons/icon-knowledge-base.svg b/3.21.0-scylla/_static/img/icons/icon-knowledge-base.svg new file mode 100644 index 0000000000..884451270d --- /dev/null +++ b/3.21.0-scylla/_static/img/icons/icon-knowledge-base.svg @@ -0,0 +1 @@ + diff --git a/3.21.0-scylla/_static/img/icons/icon-less.svg b/3.21.0-scylla/_static/img/icons/icon-less.svg new file mode 100644 index 0000000000..3094127dec --- /dev/null +++ b/3.21.0-scylla/_static/img/icons/icon-less.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/3.21.0-scylla/_static/img/icons/icon-live-test.svg b/3.21.0-scylla/_static/img/icons/icon-live-test.svg new file mode 100644 index 0000000000..dcb5916c26 --- /dev/null +++ b/3.21.0-scylla/_static/img/icons/icon-live-test.svg @@ -0,0 +1 @@ +icon-live-test diff --git a/3.21.0-scylla/_static/img/icons/icon-mail-list.svg b/3.21.0-scylla/_static/img/icons/icon-mail-list.svg new file mode 100644 index 0000000000..0e6192a352 --- /dev/null +++ b/3.21.0-scylla/_static/img/icons/icon-mail-list.svg @@ -0,0 +1 @@ + diff --git a/3.21.0-scylla/_static/img/icons/icon-manager.svg b/3.21.0-scylla/_static/img/icons/icon-manager.svg new file mode 100644 index 0000000000..02b4e425be --- /dev/null +++ b/3.21.0-scylla/_static/img/icons/icon-manager.svg @@ -0,0 +1 @@ +icon-manager diff --git a/3.21.0-scylla/_static/img/icons/icon-memory-management.svg b/3.21.0-scylla/_static/img/icons/icon-memory-management.svg new file mode 100644 index 0000000000..e34eb4504f --- /dev/null +++ b/3.21.0-scylla/_static/img/icons/icon-memory-management.svg @@ -0,0 +1 @@ +icon-memory-management diff --git a/3.21.0-scylla/_static/img/icons/icon-modeling.svg b/3.21.0-scylla/_static/img/icons/icon-modeling.svg new file mode 100644 index 0000000000..97fa3a0e21 --- /dev/null +++ b/3.21.0-scylla/_static/img/icons/icon-modeling.svg @@ -0,0 +1 @@ + diff --git a/3.21.0-scylla/_static/img/icons/icon-monitoring.svg b/3.21.0-scylla/_static/img/icons/icon-monitoring.svg new file mode 100644 index 0000000000..80b3787f66 --- /dev/null +++ b/3.21.0-scylla/_static/img/icons/icon-monitoring.svg @@ -0,0 +1 @@ +icon-monitoring diff --git a/3.21.0-scylla/_static/img/icons/icon-networking.svg b/3.21.0-scylla/_static/img/icons/icon-networking.svg new file mode 100644 index 0000000000..40a3fd5f6f --- /dev/null +++ b/3.21.0-scylla/_static/img/icons/icon-networking.svg @@ -0,0 +1 @@ +icon-networking diff --git a/3.21.0-scylla/_static/img/icons/icon-news.svg b/3.21.0-scylla/_static/img/icons/icon-news.svg new file mode 100644 index 0000000000..a952b59937 --- /dev/null +++ b/3.21.0-scylla/_static/img/icons/icon-news.svg @@ -0,0 +1 @@ +icon-news diff --git a/3.21.0-scylla/_static/img/icons/icon-newsletter.svg b/3.21.0-scylla/_static/img/icons/icon-newsletter.svg new file mode 100644 index 0000000000..5b8d47eb15 --- /dev/null +++ b/3.21.0-scylla/_static/img/icons/icon-newsletter.svg @@ -0,0 +1 @@ +icon-newsletter diff --git a/3.21.0-scylla/_static/img/icons/icon-nsql-guides.svg b/3.21.0-scylla/_static/img/icons/icon-nsql-guides.svg new file mode 100644 index 0000000000..60ebab3795 --- /dev/null +++ b/3.21.0-scylla/_static/img/icons/icon-nsql-guides.svg @@ -0,0 +1 @@ +icon-nsql-guides diff --git a/3.21.0-scylla/_static/img/icons/icon-open-source.svg b/3.21.0-scylla/_static/img/icons/icon-open-source.svg new file mode 100644 index 0000000000..98c2ea7d5b --- /dev/null +++ b/3.21.0-scylla/_static/img/icons/icon-open-source.svg @@ -0,0 +1 @@ +icon-open-source diff --git a/3.21.0-scylla/_static/img/icons/icon-operator.svg b/3.21.0-scylla/_static/img/icons/icon-operator.svg new file mode 100644 index 0000000000..bb7d8d3ea8 --- /dev/null +++ b/3.21.0-scylla/_static/img/icons/icon-operator.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/3.21.0-scylla/_static/img/icons/icon-overview.svg b/3.21.0-scylla/_static/img/icons/icon-overview.svg new file mode 100644 index 0000000000..515c1528a2 --- /dev/null +++ b/3.21.0-scylla/_static/img/icons/icon-overview.svg @@ -0,0 +1 @@ +icon-overview diff --git a/3.21.0-scylla/_static/img/icons/icon-partners.svg b/3.21.0-scylla/_static/img/icons/icon-partners.svg new file mode 100644 index 0000000000..d0146fc497 --- /dev/null +++ b/3.21.0-scylla/_static/img/icons/icon-partners.svg @@ -0,0 +1 @@ +icon-partners diff --git a/3.21.0-scylla/_static/img/icons/icon-plus.svg b/3.21.0-scylla/_static/img/icons/icon-plus.svg new file mode 100644 index 0000000000..5757435085 --- /dev/null +++ b/3.21.0-scylla/_static/img/icons/icon-plus.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/3.21.0-scylla/_static/img/icons/icon-pricing.svg b/3.21.0-scylla/_static/img/icons/icon-pricing.svg new file mode 100644 index 0000000000..74b01db168 --- /dev/null +++ b/3.21.0-scylla/_static/img/icons/icon-pricing.svg @@ -0,0 +1 @@ +icon-pricing$ diff --git a/3.21.0-scylla/_static/img/icons/icon-release-notes.svg b/3.21.0-scylla/_static/img/icons/icon-release-notes.svg new file mode 100644 index 0000000000..80c490c7b0 --- /dev/null +++ b/3.21.0-scylla/_static/img/icons/icon-release-notes.svg @@ -0,0 +1 @@ +icon-release-notes diff --git a/3.21.0-scylla/_static/img/icons/icon-resource-center.svg b/3.21.0-scylla/_static/img/icons/icon-resource-center.svg new file mode 100644 index 0000000000..6e3ab08e79 --- /dev/null +++ b/3.21.0-scylla/_static/img/icons/icon-resource-center.svg @@ -0,0 +1 @@ +icon-ressource-center diff --git a/3.21.0-scylla/_static/img/icons/icon-roadmap.svg b/3.21.0-scylla/_static/img/icons/icon-roadmap.svg new file mode 100644 index 0000000000..c8cbf67c8c --- /dev/null +++ b/3.21.0-scylla/_static/img/icons/icon-roadmap.svg @@ -0,0 +1 @@ +icon-roadmap-4 diff --git a/3.21.0-scylla/_static/img/icons/icon-search.svg b/3.21.0-scylla/_static/img/icons/icon-search.svg new file mode 100644 index 0000000000..81aae93eef --- /dev/null +++ b/3.21.0-scylla/_static/img/icons/icon-search.svg @@ -0,0 +1,4 @@ + + + + diff --git a/3.21.0-scylla/_static/img/icons/icon-slack.svg b/3.21.0-scylla/_static/img/icons/icon-slack.svg new file mode 100644 index 0000000000..fc164ea1e7 --- /dev/null +++ b/3.21.0-scylla/_static/img/icons/icon-slack.svg @@ -0,0 +1 @@ + diff --git a/3.21.0-scylla/_static/img/icons/icon-stack-overflow.svg b/3.21.0-scylla/_static/img/icons/icon-stack-overflow.svg new file mode 100644 index 0000000000..bebe9b8274 --- /dev/null +++ b/3.21.0-scylla/_static/img/icons/icon-stack-overflow.svg @@ -0,0 +1,4 @@ + + + + diff --git a/3.21.0-scylla/_static/img/icons/icon-summit.svg b/3.21.0-scylla/_static/img/icons/icon-summit.svg new file mode 100644 index 0000000000..4b900bd0c0 --- /dev/null +++ b/3.21.0-scylla/_static/img/icons/icon-summit.svg @@ -0,0 +1 @@ + diff --git a/3.21.0-scylla/_static/img/icons/icon-support.svg b/3.21.0-scylla/_static/img/icons/icon-support.svg new file mode 100644 index 0000000000..a4228b34e8 --- /dev/null +++ b/3.21.0-scylla/_static/img/icons/icon-support.svg @@ -0,0 +1 @@ +icon-support diff --git a/3.21.0-scylla/_static/img/icons/icon-tech-talks.svg b/3.21.0-scylla/_static/img/icons/icon-tech-talks.svg new file mode 100644 index 0000000000..df42b5522b --- /dev/null +++ b/3.21.0-scylla/_static/img/icons/icon-tech-talks.svg @@ -0,0 +1 @@ +icon-tech-talks diff --git a/3.21.0-scylla/_static/img/icons/icon-testing.svg b/3.21.0-scylla/_static/img/icons/icon-testing.svg new file mode 100644 index 0000000000..2fe54efdbc --- /dev/null +++ b/3.21.0-scylla/_static/img/icons/icon-testing.svg @@ -0,0 +1 @@ +icon-testing diff --git a/3.21.0-scylla/_static/img/icons/icon-thumbs-down.svg b/3.21.0-scylla/_static/img/icons/icon-thumbs-down.svg new file mode 100644 index 0000000000..3e7bcd6d90 --- /dev/null +++ b/3.21.0-scylla/_static/img/icons/icon-thumbs-down.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/3.21.0-scylla/_static/img/icons/icon-thumbs-up.svg b/3.21.0-scylla/_static/img/icons/icon-thumbs-up.svg new file mode 100644 index 0000000000..226c44d853 --- /dev/null +++ b/3.21.0-scylla/_static/img/icons/icon-thumbs-up.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/3.21.0-scylla/_static/img/icons/icon-tip.svg b/3.21.0-scylla/_static/img/icons/icon-tip.svg new file mode 100644 index 0000000000..bf7aa6af84 --- /dev/null +++ b/3.21.0-scylla/_static/img/icons/icon-tip.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/3.21.0-scylla/_static/img/icons/icon-training.svg b/3.21.0-scylla/_static/img/icons/icon-training.svg new file mode 100644 index 0000000000..08b95a88ed --- /dev/null +++ b/3.21.0-scylla/_static/img/icons/icon-training.svg @@ -0,0 +1 @@ +icon-training diff --git a/3.21.0-scylla/_static/img/icons/icon-triangle-down.svg b/3.21.0-scylla/_static/img/icons/icon-triangle-down.svg new file mode 100644 index 0000000000..e8ae088106 --- /dev/null +++ b/3.21.0-scylla/_static/img/icons/icon-triangle-down.svg @@ -0,0 +1,3 @@ + + + diff --git a/3.21.0-scylla/_static/img/icons/icon-university.svg b/3.21.0-scylla/_static/img/icons/icon-university.svg new file mode 100644 index 0000000000..f7547ab959 --- /dev/null +++ b/3.21.0-scylla/_static/img/icons/icon-university.svg @@ -0,0 +1 @@ +icon-university diff --git a/3.21.0-scylla/_static/img/icons/icon-users-blog.svg b/3.21.0-scylla/_static/img/icons/icon-users-blog.svg new file mode 100644 index 0000000000..47e56cddcf --- /dev/null +++ b/3.21.0-scylla/_static/img/icons/icon-users-blog.svg @@ -0,0 +1 @@ +icon-users-blog diff --git a/3.21.0-scylla/_static/img/icons/icon-warning.svg b/3.21.0-scylla/_static/img/icons/icon-warning.svg new file mode 100644 index 0000000000..e4b1d40331 --- /dev/null +++ b/3.21.0-scylla/_static/img/icons/icon-warning.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/3.21.0-scylla/_static/img/icons/icon-webinars.svg b/3.21.0-scylla/_static/img/icons/icon-webinars.svg new file mode 100644 index 0000000000..5e9f5cd427 --- /dev/null +++ b/3.21.0-scylla/_static/img/icons/icon-webinars.svg @@ -0,0 +1 @@ +icon-webinars diff --git a/3.21.0-scylla/_static/img/icons/icon-whitepapers.svg b/3.21.0-scylla/_static/img/icons/icon-whitepapers.svg new file mode 100644 index 0000000000..3351e51d23 --- /dev/null +++ b/3.21.0-scylla/_static/img/icons/icon-whitepapers.svg @@ -0,0 +1 @@ +icon-whitepapers diff --git a/3.21.0-scylla/_static/img/icons/icon-workshop.svg b/3.21.0-scylla/_static/img/icons/icon-workshop.svg new file mode 100644 index 0000000000..5206e58e98 --- /dev/null +++ b/3.21.0-scylla/_static/img/icons/icon-workshop.svg @@ -0,0 +1 @@ + diff --git a/3.21.0-scylla/_static/img/logo-docs.svg b/3.21.0-scylla/_static/img/logo-docs.svg new file mode 100644 index 0000000000..4fff669cb6 --- /dev/null +++ b/3.21.0-scylla/_static/img/logo-docs.svg @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/3.21.0-scylla/_static/img/logo-scylla-horizontal-RGB.svg b/3.21.0-scylla/_static/img/logo-scylla-horizontal-RGB.svg new file mode 100644 index 0000000000..b5022d7c4d --- /dev/null +++ b/3.21.0-scylla/_static/img/logo-scylla-horizontal-RGB.svg @@ -0,0 +1,74 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/3.21.0-scylla/_static/img/mascots/404.jpg b/3.21.0-scylla/_static/img/mascots/404.jpg new file mode 100644 index 0000000000..769fa0889f Binary files /dev/null and b/3.21.0-scylla/_static/img/mascots/404.jpg differ diff --git a/3.21.0-scylla/_static/img/mascots/scylla-3monsters.png b/3.21.0-scylla/_static/img/mascots/scylla-3monsters.png new file mode 100644 index 0000000000..7c06d01674 Binary files /dev/null and b/3.21.0-scylla/_static/img/mascots/scylla-3monsters.png differ diff --git a/3.21.0-scylla/_static/img/mascots/scylla-advisor-crystal.png b/3.21.0-scylla/_static/img/mascots/scylla-advisor-crystal.png new file mode 100644 index 0000000000..d33fddd62f Binary files /dev/null and b/3.21.0-scylla/_static/img/mascots/scylla-advisor-crystal.png differ diff --git a/3.21.0-scylla/_static/img/mascots/scylla-alternator.svg b/3.21.0-scylla/_static/img/mascots/scylla-alternator.svg new file mode 100644 index 0000000000..0462f893d5 --- /dev/null +++ b/3.21.0-scylla/_static/img/mascots/scylla-alternator.svg @@ -0,0 +1 @@ +scylla-alternator diff --git a/3.21.0-scylla/_static/img/mascots/scylla-cloud.svg b/3.21.0-scylla/_static/img/mascots/scylla-cloud.svg new file mode 100644 index 0000000000..a6c6a26fc9 --- /dev/null +++ b/3.21.0-scylla/_static/img/mascots/scylla-cloud.svg @@ -0,0 +1 @@ +scylla-cloud diff --git a/3.21.0-scylla/_static/img/mascots/scylla-computer-3-monsters.png b/3.21.0-scylla/_static/img/mascots/scylla-computer-3-monsters.png new file mode 100644 index 0000000000..d0368a7027 Binary files /dev/null and b/3.21.0-scylla/_static/img/mascots/scylla-computer-3-monsters.png differ diff --git a/3.21.0-scylla/_static/img/mascots/scylla-computer-headset.png b/3.21.0-scylla/_static/img/mascots/scylla-computer-headset.png new file mode 100644 index 0000000000..0cdadaa216 Binary files /dev/null and b/3.21.0-scylla/_static/img/mascots/scylla-computer-headset.png differ diff --git a/3.21.0-scylla/_static/img/mascots/scylla-cup-number-one.png b/3.21.0-scylla/_static/img/mascots/scylla-cup-number-one.png new file mode 100644 index 0000000000..e889f4e368 Binary files /dev/null and b/3.21.0-scylla/_static/img/mascots/scylla-cup-number-one.png differ diff --git a/3.21.0-scylla/_static/img/mascots/scylla-docs.svg b/3.21.0-scylla/_static/img/mascots/scylla-docs.svg new file mode 100644 index 0000000000..a5bce950c2 --- /dev/null +++ b/3.21.0-scylla/_static/img/mascots/scylla-docs.svg @@ -0,0 +1 @@ +scylla-docs diff --git a/3.21.0-scylla/_static/img/mascots/scylla-drivers.svg b/3.21.0-scylla/_static/img/mascots/scylla-drivers.svg new file mode 100644 index 0000000000..6012e71679 --- /dev/null +++ b/3.21.0-scylla/_static/img/mascots/scylla-drivers.svg @@ -0,0 +1 @@ +scylla-manager diff --git a/3.21.0-scylla/_static/img/mascots/scylla-enterprise.svg b/3.21.0-scylla/_static/img/mascots/scylla-enterprise.svg new file mode 100644 index 0000000000..a1aa0b46ac --- /dev/null +++ b/3.21.0-scylla/_static/img/mascots/scylla-enterprise.svg @@ -0,0 +1 @@ +scylla-enterprise diff --git a/3.21.0-scylla/_static/img/mascots/scylla-forklift-boxes.png b/3.21.0-scylla/_static/img/mascots/scylla-forklift-boxes.png new file mode 100644 index 0000000000..f64c29e6c7 Binary files /dev/null and b/3.21.0-scylla/_static/img/mascots/scylla-forklift-boxes.png differ diff --git a/3.21.0-scylla/_static/img/mascots/scylla-forklift-migration.png b/3.21.0-scylla/_static/img/mascots/scylla-forklift-migration.png new file mode 100644 index 0000000000..d2f645c645 Binary files /dev/null and b/3.21.0-scylla/_static/img/mascots/scylla-forklift-migration.png differ diff --git a/3.21.0-scylla/_static/img/mascots/scylla-gear.png b/3.21.0-scylla/_static/img/mascots/scylla-gear.png new file mode 100644 index 0000000000..0f53b26afa Binary files /dev/null and b/3.21.0-scylla/_static/img/mascots/scylla-gear.png differ diff --git a/3.21.0-scylla/_static/img/mascots/scylla-hardhat.png b/3.21.0-scylla/_static/img/mascots/scylla-hardhat.png new file mode 100644 index 0000000000..630f2d9094 Binary files /dev/null and b/3.21.0-scylla/_static/img/mascots/scylla-hardhat.png differ diff --git a/3.21.0-scylla/_static/img/mascots/scylla-headband.png b/3.21.0-scylla/_static/img/mascots/scylla-headband.png new file mode 100644 index 0000000000..c87abe684d Binary files /dev/null and b/3.21.0-scylla/_static/img/mascots/scylla-headband.png differ diff --git a/3.21.0-scylla/_static/img/mascots/scylla-headset.png b/3.21.0-scylla/_static/img/mascots/scylla-headset.png new file mode 100644 index 0000000000..ba52cd223d Binary files /dev/null and b/3.21.0-scylla/_static/img/mascots/scylla-headset.png differ diff --git a/3.21.0-scylla/_static/img/mascots/scylla-hearts.png b/3.21.0-scylla/_static/img/mascots/scylla-hearts.png new file mode 100644 index 0000000000..cef08c8654 Binary files /dev/null and b/3.21.0-scylla/_static/img/mascots/scylla-hearts.png differ diff --git a/3.21.0-scylla/_static/img/mascots/scylla-looking-down.png b/3.21.0-scylla/_static/img/mascots/scylla-looking-down.png new file mode 100644 index 0000000000..75cccbfdf1 Binary files /dev/null and b/3.21.0-scylla/_static/img/mascots/scylla-looking-down.png differ diff --git a/3.21.0-scylla/_static/img/mascots/scylla-looking-up.png b/3.21.0-scylla/_static/img/mascots/scylla-looking-up.png new file mode 100644 index 0000000000..6f10405f21 Binary files /dev/null and b/3.21.0-scylla/_static/img/mascots/scylla-looking-up.png differ diff --git a/3.21.0-scylla/_static/img/mascots/scylla-magnifying-glass-fronting.png b/3.21.0-scylla/_static/img/mascots/scylla-magnifying-glass-fronting.png new file mode 100644 index 0000000000..e368cae169 Binary files /dev/null and b/3.21.0-scylla/_static/img/mascots/scylla-magnifying-glass-fronting.png differ diff --git a/3.21.0-scylla/_static/img/mascots/scylla-magnifying-glass.png b/3.21.0-scylla/_static/img/mascots/scylla-magnifying-glass.png new file mode 100644 index 0000000000..74ad669500 Binary files /dev/null and b/3.21.0-scylla/_static/img/mascots/scylla-magnifying-glass.png differ diff --git a/3.21.0-scylla/_static/img/mascots/scylla-manager.svg b/3.21.0-scylla/_static/img/mascots/scylla-manager.svg new file mode 100644 index 0000000000..6ba9ed937c --- /dev/null +++ b/3.21.0-scylla/_static/img/mascots/scylla-manager.svg @@ -0,0 +1 @@ +scylla-manager-2 diff --git a/3.21.0-scylla/_static/img/mascots/scylla-monitor.svg b/3.21.0-scylla/_static/img/mascots/scylla-monitor.svg new file mode 100644 index 0000000000..48bec7dde3 --- /dev/null +++ b/3.21.0-scylla/_static/img/mascots/scylla-monitor.svg @@ -0,0 +1 @@ +scylla-monitor diff --git a/3.21.0-scylla/_static/img/mascots/scylla-movement-fast.png b/3.21.0-scylla/_static/img/mascots/scylla-movement-fast.png new file mode 100644 index 0000000000..956d1dd0e2 Binary files /dev/null and b/3.21.0-scylla/_static/img/mascots/scylla-movement-fast.png differ diff --git a/3.21.0-scylla/_static/img/mascots/scylla-movement.png b/3.21.0-scylla/_static/img/mascots/scylla-movement.png new file mode 100644 index 0000000000..7ee2b04338 Binary files /dev/null and b/3.21.0-scylla/_static/img/mascots/scylla-movement.png differ diff --git a/3.21.0-scylla/_static/img/mascots/scylla-onpremise.png b/3.21.0-scylla/_static/img/mascots/scylla-onpremise.png new file mode 100644 index 0000000000..3b2dc8f1a2 Binary files /dev/null and b/3.21.0-scylla/_static/img/mascots/scylla-onpremise.png differ diff --git a/3.21.0-scylla/_static/img/mascots/scylla-opensource.svg b/3.21.0-scylla/_static/img/mascots/scylla-opensource.svg new file mode 100644 index 0000000000..299e9cb995 --- /dev/null +++ b/3.21.0-scylla/_static/img/mascots/scylla-opensource.svg @@ -0,0 +1 @@ +Plan de travail 1 diff --git a/3.21.0-scylla/_static/img/mascots/scylla-operator.svg b/3.21.0-scylla/_static/img/mascots/scylla-operator.svg new file mode 100644 index 0000000000..655a450b2a --- /dev/null +++ b/3.21.0-scylla/_static/img/mascots/scylla-operator.svg @@ -0,0 +1 @@ +scylla-operator diff --git a/3.21.0-scylla/_static/img/mascots/scylla-plugin.png b/3.21.0-scylla/_static/img/mascots/scylla-plugin.png new file mode 100644 index 0000000000..b28dc857cc Binary files /dev/null and b/3.21.0-scylla/_static/img/mascots/scylla-plugin.png differ diff --git a/3.21.0-scylla/_static/img/mascots/scylla-release-mascot.png b/3.21.0-scylla/_static/img/mascots/scylla-release-mascot.png new file mode 100644 index 0000000000..09342ac687 Binary files /dev/null and b/3.21.0-scylla/_static/img/mascots/scylla-release-mascot.png differ diff --git a/3.21.0-scylla/_static/img/mascots/scylla-repair.png b/3.21.0-scylla/_static/img/mascots/scylla-repair.png new file mode 100644 index 0000000000..9b4c613e70 Binary files /dev/null and b/3.21.0-scylla/_static/img/mascots/scylla-repair.png differ diff --git a/3.21.0-scylla/_static/img/mascots/scylla-server.png b/3.21.0-scylla/_static/img/mascots/scylla-server.png new file mode 100644 index 0000000000..96dc785298 Binary files /dev/null and b/3.21.0-scylla/_static/img/mascots/scylla-server.png differ diff --git a/3.21.0-scylla/_static/img/mascots/scylla-sleeping.png b/3.21.0-scylla/_static/img/mascots/scylla-sleeping.png new file mode 100644 index 0000000000..f88598e05a Binary files /dev/null and b/3.21.0-scylla/_static/img/mascots/scylla-sleeping.png differ diff --git a/3.21.0-scylla/_static/img/mascots/scylla-tall-measure.png b/3.21.0-scylla/_static/img/mascots/scylla-tall-measure.png new file mode 100644 index 0000000000..6f0ca146c0 Binary files /dev/null and b/3.21.0-scylla/_static/img/mascots/scylla-tall-measure.png differ diff --git a/3.21.0-scylla/_static/img/mascots/scylla-university.png b/3.21.0-scylla/_static/img/mascots/scylla-university.png new file mode 100644 index 0000000000..b3d0621193 Binary files /dev/null and b/3.21.0-scylla/_static/img/mascots/scylla-university.png differ diff --git a/3.21.0-scylla/_static/img/mascots/scylla-weights.png b/3.21.0-scylla/_static/img/mascots/scylla-weights.png new file mode 100644 index 0000000000..b070bb022c Binary files /dev/null and b/3.21.0-scylla/_static/img/mascots/scylla-weights.png differ diff --git a/3.21.0-scylla/_static/img/mascots/scylla-window-cleaning.png b/3.21.0-scylla/_static/img/mascots/scylla-window-cleaning.png new file mode 100644 index 0000000000..6a8b16a6b4 Binary files /dev/null and b/3.21.0-scylla/_static/img/mascots/scylla-window-cleaning.png differ diff --git a/3.21.0-scylla/_static/img/mascots/scylla-with-computer-2.png b/3.21.0-scylla/_static/img/mascots/scylla-with-computer-2.png new file mode 100644 index 0000000000..f3b8b2984f Binary files /dev/null and b/3.21.0-scylla/_static/img/mascots/scylla-with-computer-2.png differ diff --git a/3.21.0-scylla/_static/img/mascots/scylla-with-computer.png b/3.21.0-scylla/_static/img/mascots/scylla-with-computer.png new file mode 100644 index 0000000000..b38a6fbbe0 Binary files /dev/null and b/3.21.0-scylla/_static/img/mascots/scylla-with-computer.png differ diff --git a/3.21.0-scylla/_static/img/mascots/scylla-with-linux.png b/3.21.0-scylla/_static/img/mascots/scylla-with-linux.png new file mode 100644 index 0000000000..954bf13bc2 Binary files /dev/null and b/3.21.0-scylla/_static/img/mascots/scylla-with-linux.png differ diff --git a/3.21.0-scylla/_static/img/mascots/scylla-writting.png b/3.21.0-scylla/_static/img/mascots/scylla-writting.png new file mode 100644 index 0000000000..d35a13d380 Binary files /dev/null and b/3.21.0-scylla/_static/img/mascots/scylla-writting.png differ diff --git a/3.21.0-scylla/_static/img/menu.svg b/3.21.0-scylla/_static/img/menu.svg new file mode 100644 index 0000000000..30ea1d901e --- /dev/null +++ b/3.21.0-scylla/_static/img/menu.svg @@ -0,0 +1,3 @@ + + + diff --git a/3.21.0-scylla/_static/jquery-3.5.1.js b/3.21.0-scylla/_static/jquery-3.5.1.js new file mode 100644 index 0000000000..50937333b9 --- /dev/null +++ b/3.21.0-scylla/_static/jquery-3.5.1.js @@ -0,0 +1,10872 @@ +/*! + * jQuery JavaScript Library v3.5.1 + * https://jquery.com/ + * + * Includes Sizzle.js + * https://sizzlejs.com/ + * + * Copyright JS Foundation and other contributors + * Released under the MIT license + * https://jquery.org/license + * + * Date: 2020-05-04T22:49Z + */ +( function( global, factory ) { + + "use strict"; + + if ( typeof module === "object" && typeof module.exports === "object" ) { + + // For CommonJS and CommonJS-like environments where a proper `window` + // is present, execute the factory and get jQuery. + // For environments that do not have a `window` with a `document` + // (such as Node.js), expose a factory as module.exports. + // This accentuates the need for the creation of a real `window`. + // e.g. var jQuery = require("jquery")(window); + // See ticket #14549 for more info. + module.exports = global.document ? + factory( global, true ) : + function( w ) { + if ( !w.document ) { + throw new Error( "jQuery requires a window with a document" ); + } + return factory( w ); + }; + } else { + factory( global ); + } + +// Pass this if window is not defined yet +} )( typeof window !== "undefined" ? window : this, function( window, noGlobal ) { + +// Edge <= 12 - 13+, Firefox <=18 - 45+, IE 10 - 11, Safari 5.1 - 9+, iOS 6 - 9.1 +// throw exceptions when non-strict code (e.g., ASP.NET 4.5) accesses strict mode +// arguments.callee.caller (trac-13335). But as of jQuery 3.0 (2016), strict mode should be common +// enough that all such attempts are guarded in a try block. +"use strict"; + +var arr = []; + +var getProto = Object.getPrototypeOf; + +var slice = arr.slice; + +var flat = arr.flat ? function( array ) { + return arr.flat.call( array ); +} : function( array ) { + return arr.concat.apply( [], array ); +}; + + +var push = arr.push; + +var indexOf = arr.indexOf; + +var class2type = {}; + +var toString = class2type.toString; + +var hasOwn = class2type.hasOwnProperty; + +var fnToString = hasOwn.toString; + +var ObjectFunctionString = fnToString.call( Object ); + +var support = {}; + +var isFunction = function isFunction( obj ) { + + // Support: Chrome <=57, Firefox <=52 + // In some browsers, typeof returns "function" for HTML elements + // (i.e., `typeof document.createElement( "object" ) === "function"`). + // We don't want to classify *any* DOM node as a function. + return typeof obj === "function" && typeof obj.nodeType !== "number"; + }; + + +var isWindow = function isWindow( obj ) { + return obj != null && obj === obj.window; + }; + + +var document = window.document; + + + + var preservedScriptAttributes = { + type: true, + src: true, + nonce: true, + noModule: true + }; + + function DOMEval( code, node, doc ) { + doc = doc || document; + + var i, val, + script = doc.createElement( "script" ); + + script.text = code; + if ( node ) { + for ( i in preservedScriptAttributes ) { + + // Support: Firefox 64+, Edge 18+ + // Some browsers don't support the "nonce" property on scripts. + // On the other hand, just using `getAttribute` is not enough as + // the `nonce` attribute is reset to an empty string whenever it + // becomes browsing-context connected. + // See https://github.com/whatwg/html/issues/2369 + // See https://html.spec.whatwg.org/#nonce-attributes + // The `node.getAttribute` check was added for the sake of + // `jQuery.globalEval` so that it can fake a nonce-containing node + // via an object. + val = node[ i ] || node.getAttribute && node.getAttribute( i ); + if ( val ) { + script.setAttribute( i, val ); + } + } + } + doc.head.appendChild( script ).parentNode.removeChild( script ); + } + + +function toType( obj ) { + if ( obj == null ) { + return obj + ""; + } + + // Support: Android <=2.3 only (functionish RegExp) + return typeof obj === "object" || typeof obj === "function" ? + class2type[ toString.call( obj ) ] || "object" : + typeof obj; +} +/* global Symbol */ +// Defining this global in .eslintrc.json would create a danger of using the global +// unguarded in another place, it seems safer to define global only for this module + + + +var + version = "3.5.1", + + // Define a local copy of jQuery + jQuery = function( selector, context ) { + + // The jQuery object is actually just the init constructor 'enhanced' + // Need init if jQuery is called (just allow error to be thrown if not included) + return new jQuery.fn.init( selector, context ); + }; + +jQuery.fn = jQuery.prototype = { + + // The current version of jQuery being used + jquery: version, + + constructor: jQuery, + + // The default length of a jQuery object is 0 + length: 0, + + toArray: function() { + return slice.call( this ); + }, + + // Get the Nth element in the matched element set OR + // Get the whole matched element set as a clean array + get: function( num ) { + + // Return all the elements in a clean array + if ( num == null ) { + return slice.call( this ); + } + + // Return just the one element from the set + return num < 0 ? this[ num + this.length ] : this[ num ]; + }, + + // Take an array of elements and push it onto the stack + // (returning the new matched element set) + pushStack: function( elems ) { + + // Build a new jQuery matched element set + var ret = jQuery.merge( this.constructor(), elems ); + + // Add the old object onto the stack (as a reference) + ret.prevObject = this; + + // Return the newly-formed element set + return ret; + }, + + // Execute a callback for every element in the matched set. + each: function( callback ) { + return jQuery.each( this, callback ); + }, + + map: function( callback ) { + return this.pushStack( jQuery.map( this, function( elem, i ) { + return callback.call( elem, i, elem ); + } ) ); + }, + + slice: function() { + return this.pushStack( slice.apply( this, arguments ) ); + }, + + first: function() { + return this.eq( 0 ); + }, + + last: function() { + return this.eq( -1 ); + }, + + even: function() { + return this.pushStack( jQuery.grep( this, function( _elem, i ) { + return ( i + 1 ) % 2; + } ) ); + }, + + odd: function() { + return this.pushStack( jQuery.grep( this, function( _elem, i ) { + return i % 2; + } ) ); + }, + + eq: function( i ) { + var len = this.length, + j = +i + ( i < 0 ? len : 0 ); + return this.pushStack( j >= 0 && j < len ? [ this[ j ] ] : [] ); + }, + + end: function() { + return this.prevObject || this.constructor(); + }, + + // For internal use only. + // Behaves like an Array's method, not like a jQuery method. + push: push, + sort: arr.sort, + splice: arr.splice +}; + +jQuery.extend = jQuery.fn.extend = function() { + var options, name, src, copy, copyIsArray, clone, + target = arguments[ 0 ] || {}, + i = 1, + length = arguments.length, + deep = false; + + // Handle a deep copy situation + if ( typeof target === "boolean" ) { + deep = target; + + // Skip the boolean and the target + target = arguments[ i ] || {}; + i++; + } + + // Handle case when target is a string or something (possible in deep copy) + if ( typeof target !== "object" && !isFunction( target ) ) { + target = {}; + } + + // Extend jQuery itself if only one argument is passed + if ( i === length ) { + target = this; + i--; + } + + for ( ; i < length; i++ ) { + + // Only deal with non-null/undefined values + if ( ( options = arguments[ i ] ) != null ) { + + // Extend the base object + for ( name in options ) { + copy = options[ name ]; + + // Prevent Object.prototype pollution + // Prevent never-ending loop + if ( name === "__proto__" || target === copy ) { + continue; + } + + // Recurse if we're merging plain objects or arrays + if ( deep && copy && ( jQuery.isPlainObject( copy ) || + ( copyIsArray = Array.isArray( copy ) ) ) ) { + src = target[ name ]; + + // Ensure proper type for the source value + if ( copyIsArray && !Array.isArray( src ) ) { + clone = []; + } else if ( !copyIsArray && !jQuery.isPlainObject( src ) ) { + clone = {}; + } else { + clone = src; + } + copyIsArray = false; + + // Never move original objects, clone them + target[ name ] = jQuery.extend( deep, clone, copy ); + + // Don't bring in undefined values + } else if ( copy !== undefined ) { + target[ name ] = copy; + } + } + } + } + + // Return the modified object + return target; +}; + +jQuery.extend( { + + // Unique for each copy of jQuery on the page + expando: "jQuery" + ( version + Math.random() ).replace( /\D/g, "" ), + + // Assume jQuery is ready without the ready module + isReady: true, + + error: function( msg ) { + throw new Error( msg ); + }, + + noop: function() {}, + + isPlainObject: function( obj ) { + var proto, Ctor; + + // Detect obvious negatives + // Use toString instead of jQuery.type to catch host objects + if ( !obj || toString.call( obj ) !== "[object Object]" ) { + return false; + } + + proto = getProto( obj ); + + // Objects with no prototype (e.g., `Object.create( null )`) are plain + if ( !proto ) { + return true; + } + + // Objects with prototype are plain iff they were constructed by a global Object function + Ctor = hasOwn.call( proto, "constructor" ) && proto.constructor; + return typeof Ctor === "function" && fnToString.call( Ctor ) === ObjectFunctionString; + }, + + isEmptyObject: function( obj ) { + var name; + + for ( name in obj ) { + return false; + } + return true; + }, + + // Evaluates a script in a provided context; falls back to the global one + // if not specified. + globalEval: function( code, options, doc ) { + DOMEval( code, { nonce: options && options.nonce }, doc ); + }, + + each: function( obj, callback ) { + var length, i = 0; + + if ( isArrayLike( obj ) ) { + length = obj.length; + for ( ; i < length; i++ ) { + if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) { + break; + } + } + } else { + for ( i in obj ) { + if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) { + break; + } + } + } + + return obj; + }, + + // results is for internal usage only + makeArray: function( arr, results ) { + var ret = results || []; + + if ( arr != null ) { + if ( isArrayLike( Object( arr ) ) ) { + jQuery.merge( ret, + typeof arr === "string" ? + [ arr ] : arr + ); + } else { + push.call( ret, arr ); + } + } + + return ret; + }, + + inArray: function( elem, arr, i ) { + return arr == null ? -1 : indexOf.call( arr, elem, i ); + }, + + // Support: Android <=4.0 only, PhantomJS 1 only + // push.apply(_, arraylike) throws on ancient WebKit + merge: function( first, second ) { + var len = +second.length, + j = 0, + i = first.length; + + for ( ; j < len; j++ ) { + first[ i++ ] = second[ j ]; + } + + first.length = i; + + return first; + }, + + grep: function( elems, callback, invert ) { + var callbackInverse, + matches = [], + i = 0, + length = elems.length, + callbackExpect = !invert; + + // Go through the array, only saving the items + // that pass the validator function + for ( ; i < length; i++ ) { + callbackInverse = !callback( elems[ i ], i ); + if ( callbackInverse !== callbackExpect ) { + matches.push( elems[ i ] ); + } + } + + return matches; + }, + + // arg is for internal usage only + map: function( elems, callback, arg ) { + var length, value, + i = 0, + ret = []; + + // Go through the array, translating each of the items to their new values + if ( isArrayLike( elems ) ) { + length = elems.length; + for ( ; i < length; i++ ) { + value = callback( elems[ i ], i, arg ); + + if ( value != null ) { + ret.push( value ); + } + } + + // Go through every key on the object, + } else { + for ( i in elems ) { + value = callback( elems[ i ], i, arg ); + + if ( value != null ) { + ret.push( value ); + } + } + } + + // Flatten any nested arrays + return flat( ret ); + }, + + // A global GUID counter for objects + guid: 1, + + // jQuery.support is not used in Core but other projects attach their + // properties to it so it needs to exist. + support: support +} ); + +if ( typeof Symbol === "function" ) { + jQuery.fn[ Symbol.iterator ] = arr[ Symbol.iterator ]; +} + +// Populate the class2type map +jQuery.each( "Boolean Number String Function Array Date RegExp Object Error Symbol".split( " " ), +function( _i, name ) { + class2type[ "[object " + name + "]" ] = name.toLowerCase(); +} ); + +function isArrayLike( obj ) { + + // Support: real iOS 8.2 only (not reproducible in simulator) + // `in` check used to prevent JIT error (gh-2145) + // hasOwn isn't used here due to false negatives + // regarding Nodelist length in IE + var length = !!obj && "length" in obj && obj.length, + type = toType( obj ); + + if ( isFunction( obj ) || isWindow( obj ) ) { + return false; + } + + return type === "array" || length === 0 || + typeof length === "number" && length > 0 && ( length - 1 ) in obj; +} +var Sizzle = +/*! + * Sizzle CSS Selector Engine v2.3.5 + * https://sizzlejs.com/ + * + * Copyright JS Foundation and other contributors + * Released under the MIT license + * https://js.foundation/ + * + * Date: 2020-03-14 + */ +( function( window ) { +var i, + support, + Expr, + getText, + isXML, + tokenize, + compile, + select, + outermostContext, + sortInput, + hasDuplicate, + + // Local document vars + setDocument, + document, + docElem, + documentIsHTML, + rbuggyQSA, + rbuggyMatches, + matches, + contains, + + // Instance-specific data + expando = "sizzle" + 1 * new Date(), + preferredDoc = window.document, + dirruns = 0, + done = 0, + classCache = createCache(), + tokenCache = createCache(), + compilerCache = createCache(), + nonnativeSelectorCache = createCache(), + sortOrder = function( a, b ) { + if ( a === b ) { + hasDuplicate = true; + } + return 0; + }, + + // Instance methods + hasOwn = ( {} ).hasOwnProperty, + arr = [], + pop = arr.pop, + pushNative = arr.push, + push = arr.push, + slice = arr.slice, + + // Use a stripped-down indexOf as it's faster than native + // https://jsperf.com/thor-indexof-vs-for/5 + indexOf = function( list, elem ) { + var i = 0, + len = list.length; + for ( ; i < len; i++ ) { + if ( list[ i ] === elem ) { + return i; + } + } + return -1; + }, + + booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|" + + "ismap|loop|multiple|open|readonly|required|scoped", + + // Regular expressions + + // http://www.w3.org/TR/css3-selectors/#whitespace + whitespace = "[\\x20\\t\\r\\n\\f]", + + // https://www.w3.org/TR/css-syntax-3/#ident-token-diagram + identifier = "(?:\\\\[\\da-fA-F]{1,6}" + whitespace + + "?|\\\\[^\\r\\n\\f]|[\\w-]|[^\0-\\x7f])+", + + // Attribute selectors: http://www.w3.org/TR/selectors/#attribute-selectors + attributes = "\\[" + whitespace + "*(" + identifier + ")(?:" + whitespace + + + // Operator (capture 2) + "*([*^$|!~]?=)" + whitespace + + + // "Attribute values must be CSS identifiers [capture 5] + // or strings [capture 3 or capture 4]" + "*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|(" + identifier + "))|)" + + whitespace + "*\\]", + + pseudos = ":(" + identifier + ")(?:\\((" + + + // To reduce the number of selectors needing tokenize in the preFilter, prefer arguments: + // 1. quoted (capture 3; capture 4 or capture 5) + "('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|" + + + // 2. simple (capture 6) + "((?:\\\\.|[^\\\\()[\\]]|" + attributes + ")*)|" + + + // 3. anything else (capture 2) + ".*" + + ")\\)|)", + + // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter + rwhitespace = new RegExp( whitespace + "+", "g" ), + rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + + whitespace + "+$", "g" ), + + rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ), + rcombinators = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + + "*" ), + rdescend = new RegExp( whitespace + "|>" ), + + rpseudo = new RegExp( pseudos ), + ridentifier = new RegExp( "^" + identifier + "$" ), + + matchExpr = { + "ID": new RegExp( "^#(" + identifier + ")" ), + "CLASS": new RegExp( "^\\.(" + identifier + ")" ), + "TAG": new RegExp( "^(" + identifier + "|[*])" ), + "ATTR": new RegExp( "^" + attributes ), + "PSEUDO": new RegExp( "^" + pseudos ), + "CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + + whitespace + "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + + whitespace + "*(\\d+)|))" + whitespace + "*\\)|)", "i" ), + "bool": new RegExp( "^(?:" + booleans + ")$", "i" ), + + // For use in libraries implementing .is() + // We use this for POS matching in `select` + "needsContext": new RegExp( "^" + whitespace + + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" + whitespace + + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" ) + }, + + rhtml = /HTML$/i, + rinputs = /^(?:input|select|textarea|button)$/i, + rheader = /^h\d$/i, + + rnative = /^[^{]+\{\s*\[native \w/, + + // Easily-parseable/retrievable ID or TAG or CLASS selectors + rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/, + + rsibling = /[+~]/, + + // CSS escapes + // http://www.w3.org/TR/CSS21/syndata.html#escaped-characters + runescape = new RegExp( "\\\\[\\da-fA-F]{1,6}" + whitespace + "?|\\\\([^\\r\\n\\f])", "g" ), + funescape = function( escape, nonHex ) { + var high = "0x" + escape.slice( 1 ) - 0x10000; + + return nonHex ? + + // Strip the backslash prefix from a non-hex escape sequence + nonHex : + + // Replace a hexadecimal escape sequence with the encoded Unicode code point + // Support: IE <=11+ + // For values outside the Basic Multilingual Plane (BMP), manually construct a + // surrogate pair + high < 0 ? + String.fromCharCode( high + 0x10000 ) : + String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 ); + }, + + // CSS string/identifier serialization + // https://drafts.csswg.org/cssom/#common-serializing-idioms + rcssescape = /([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g, + fcssescape = function( ch, asCodePoint ) { + if ( asCodePoint ) { + + // U+0000 NULL becomes U+FFFD REPLACEMENT CHARACTER + if ( ch === "\0" ) { + return "\uFFFD"; + } + + // Control characters and (dependent upon position) numbers get escaped as code points + return ch.slice( 0, -1 ) + "\\" + + ch.charCodeAt( ch.length - 1 ).toString( 16 ) + " "; + } + + // Other potentially-special ASCII characters get backslash-escaped + return "\\" + ch; + }, + + // Used for iframes + // See setDocument() + // Removing the function wrapper causes a "Permission Denied" + // error in IE + unloadHandler = function() { + setDocument(); + }, + + inDisabledFieldset = addCombinator( + function( elem ) { + return elem.disabled === true && elem.nodeName.toLowerCase() === "fieldset"; + }, + { dir: "parentNode", next: "legend" } + ); + +// Optimize for push.apply( _, NodeList ) +try { + push.apply( + ( arr = slice.call( preferredDoc.childNodes ) ), + preferredDoc.childNodes + ); + + // Support: Android<4.0 + // Detect silently failing push.apply + // eslint-disable-next-line no-unused-expressions + arr[ preferredDoc.childNodes.length ].nodeType; +} catch ( e ) { + push = { apply: arr.length ? + + // Leverage slice if possible + function( target, els ) { + pushNative.apply( target, slice.call( els ) ); + } : + + // Support: IE<9 + // Otherwise append directly + function( target, els ) { + var j = target.length, + i = 0; + + // Can't trust NodeList.length + while ( ( target[ j++ ] = els[ i++ ] ) ) {} + target.length = j - 1; + } + }; +} + +function Sizzle( selector, context, results, seed ) { + var m, i, elem, nid, match, groups, newSelector, + newContext = context && context.ownerDocument, + + // nodeType defaults to 9, since context defaults to document + nodeType = context ? context.nodeType : 9; + + results = results || []; + + // Return early from calls with invalid selector or context + if ( typeof selector !== "string" || !selector || + nodeType !== 1 && nodeType !== 9 && nodeType !== 11 ) { + + return results; + } + + // Try to shortcut find operations (as opposed to filters) in HTML documents + if ( !seed ) { + setDocument( context ); + context = context || document; + + if ( documentIsHTML ) { + + // If the selector is sufficiently simple, try using a "get*By*" DOM method + // (excepting DocumentFragment context, where the methods don't exist) + if ( nodeType !== 11 && ( match = rquickExpr.exec( selector ) ) ) { + + // ID selector + if ( ( m = match[ 1 ] ) ) { + + // Document context + if ( nodeType === 9 ) { + if ( ( elem = context.getElementById( m ) ) ) { + + // Support: IE, Opera, Webkit + // TODO: identify versions + // getElementById can match elements by name instead of ID + if ( elem.id === m ) { + results.push( elem ); + return results; + } + } else { + return results; + } + + // Element context + } else { + + // Support: IE, Opera, Webkit + // TODO: identify versions + // getElementById can match elements by name instead of ID + if ( newContext && ( elem = newContext.getElementById( m ) ) && + contains( context, elem ) && + elem.id === m ) { + + results.push( elem ); + return results; + } + } + + // Type selector + } else if ( match[ 2 ] ) { + push.apply( results, context.getElementsByTagName( selector ) ); + return results; + + // Class selector + } else if ( ( m = match[ 3 ] ) && support.getElementsByClassName && + context.getElementsByClassName ) { + + push.apply( results, context.getElementsByClassName( m ) ); + return results; + } + } + + // Take advantage of querySelectorAll + if ( support.qsa && + !nonnativeSelectorCache[ selector + " " ] && + ( !rbuggyQSA || !rbuggyQSA.test( selector ) ) && + + // Support: IE 8 only + // Exclude object elements + ( nodeType !== 1 || context.nodeName.toLowerCase() !== "object" ) ) { + + newSelector = selector; + newContext = context; + + // qSA considers elements outside a scoping root when evaluating child or + // descendant combinators, which is not what we want. + // In such cases, we work around the behavior by prefixing every selector in the + // list with an ID selector referencing the scope context. + // The technique has to be used as well when a leading combinator is used + // as such selectors are not recognized by querySelectorAll. + // Thanks to Andrew Dupont for this technique. + if ( nodeType === 1 && + ( rdescend.test( selector ) || rcombinators.test( selector ) ) ) { + + // Expand context for sibling selectors + newContext = rsibling.test( selector ) && testContext( context.parentNode ) || + context; + + // We can use :scope instead of the ID hack if the browser + // supports it & if we're not changing the context. + if ( newContext !== context || !support.scope ) { + + // Capture the context ID, setting it first if necessary + if ( ( nid = context.getAttribute( "id" ) ) ) { + nid = nid.replace( rcssescape, fcssescape ); + } else { + context.setAttribute( "id", ( nid = expando ) ); + } + } + + // Prefix every selector in the list + groups = tokenize( selector ); + i = groups.length; + while ( i-- ) { + groups[ i ] = ( nid ? "#" + nid : ":scope" ) + " " + + toSelector( groups[ i ] ); + } + newSelector = groups.join( "," ); + } + + try { + push.apply( results, + newContext.querySelectorAll( newSelector ) + ); + return results; + } catch ( qsaError ) { + nonnativeSelectorCache( selector, true ); + } finally { + if ( nid === expando ) { + context.removeAttribute( "id" ); + } + } + } + } + } + + // All others + return select( selector.replace( rtrim, "$1" ), context, results, seed ); +} + +/** + * Create key-value caches of limited size + * @returns {function(string, object)} Returns the Object data after storing it on itself with + * property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength) + * deleting the oldest entry + */ +function createCache() { + var keys = []; + + function cache( key, value ) { + + // Use (key + " ") to avoid collision with native prototype properties (see Issue #157) + if ( keys.push( key + " " ) > Expr.cacheLength ) { + + // Only keep the most recent entries + delete cache[ keys.shift() ]; + } + return ( cache[ key + " " ] = value ); + } + return cache; +} + +/** + * Mark a function for special use by Sizzle + * @param {Function} fn The function to mark + */ +function markFunction( fn ) { + fn[ expando ] = true; + return fn; +} + +/** + * Support testing using an element + * @param {Function} fn Passed the created element and returns a boolean result + */ +function assert( fn ) { + var el = document.createElement( "fieldset" ); + + try { + return !!fn( el ); + } catch ( e ) { + return false; + } finally { + + // Remove from its parent by default + if ( el.parentNode ) { + el.parentNode.removeChild( el ); + } + + // release memory in IE + el = null; + } +} + +/** + * Adds the same handler for all of the specified attrs + * @param {String} attrs Pipe-separated list of attributes + * @param {Function} handler The method that will be applied + */ +function addHandle( attrs, handler ) { + var arr = attrs.split( "|" ), + i = arr.length; + + while ( i-- ) { + Expr.attrHandle[ arr[ i ] ] = handler; + } +} + +/** + * Checks document order of two siblings + * @param {Element} a + * @param {Element} b + * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b + */ +function siblingCheck( a, b ) { + var cur = b && a, + diff = cur && a.nodeType === 1 && b.nodeType === 1 && + a.sourceIndex - b.sourceIndex; + + // Use IE sourceIndex if available on both nodes + if ( diff ) { + return diff; + } + + // Check if b follows a + if ( cur ) { + while ( ( cur = cur.nextSibling ) ) { + if ( cur === b ) { + return -1; + } + } + } + + return a ? 1 : -1; +} + +/** + * Returns a function to use in pseudos for input types + * @param {String} type + */ +function createInputPseudo( type ) { + return function( elem ) { + var name = elem.nodeName.toLowerCase(); + return name === "input" && elem.type === type; + }; +} + +/** + * Returns a function to use in pseudos for buttons + * @param {String} type + */ +function createButtonPseudo( type ) { + return function( elem ) { + var name = elem.nodeName.toLowerCase(); + return ( name === "input" || name === "button" ) && elem.type === type; + }; +} + +/** + * Returns a function to use in pseudos for :enabled/:disabled + * @param {Boolean} disabled true for :disabled; false for :enabled + */ +function createDisabledPseudo( disabled ) { + + // Known :disabled false positives: fieldset[disabled] > legend:nth-of-type(n+2) :can-disable + return function( elem ) { + + // Only certain elements can match :enabled or :disabled + // https://html.spec.whatwg.org/multipage/scripting.html#selector-enabled + // https://html.spec.whatwg.org/multipage/scripting.html#selector-disabled + if ( "form" in elem ) { + + // Check for inherited disabledness on relevant non-disabled elements: + // * listed form-associated elements in a disabled fieldset + // https://html.spec.whatwg.org/multipage/forms.html#category-listed + // https://html.spec.whatwg.org/multipage/forms.html#concept-fe-disabled + // * option elements in a disabled optgroup + // https://html.spec.whatwg.org/multipage/forms.html#concept-option-disabled + // All such elements have a "form" property. + if ( elem.parentNode && elem.disabled === false ) { + + // Option elements defer to a parent optgroup if present + if ( "label" in elem ) { + if ( "label" in elem.parentNode ) { + return elem.parentNode.disabled === disabled; + } else { + return elem.disabled === disabled; + } + } + + // Support: IE 6 - 11 + // Use the isDisabled shortcut property to check for disabled fieldset ancestors + return elem.isDisabled === disabled || + + // Where there is no isDisabled, check manually + /* jshint -W018 */ + elem.isDisabled !== !disabled && + inDisabledFieldset( elem ) === disabled; + } + + return elem.disabled === disabled; + + // Try to winnow out elements that can't be disabled before trusting the disabled property. + // Some victims get caught in our net (label, legend, menu, track), but it shouldn't + // even exist on them, let alone have a boolean value. + } else if ( "label" in elem ) { + return elem.disabled === disabled; + } + + // Remaining elements are neither :enabled nor :disabled + return false; + }; +} + +/** + * Returns a function to use in pseudos for positionals + * @param {Function} fn + */ +function createPositionalPseudo( fn ) { + return markFunction( function( argument ) { + argument = +argument; + return markFunction( function( seed, matches ) { + var j, + matchIndexes = fn( [], seed.length, argument ), + i = matchIndexes.length; + + // Match elements found at the specified indexes + while ( i-- ) { + if ( seed[ ( j = matchIndexes[ i ] ) ] ) { + seed[ j ] = !( matches[ j ] = seed[ j ] ); + } + } + } ); + } ); +} + +/** + * Checks a node for validity as a Sizzle context + * @param {Element|Object=} context + * @returns {Element|Object|Boolean} The input node if acceptable, otherwise a falsy value + */ +function testContext( context ) { + return context && typeof context.getElementsByTagName !== "undefined" && context; +} + +// Expose support vars for convenience +support = Sizzle.support = {}; + +/** + * Detects XML nodes + * @param {Element|Object} elem An element or a document + * @returns {Boolean} True iff elem is a non-HTML XML node + */ +isXML = Sizzle.isXML = function( elem ) { + var namespace = elem.namespaceURI, + docElem = ( elem.ownerDocument || elem ).documentElement; + + // Support: IE <=8 + // Assume HTML when documentElement doesn't yet exist, such as inside loading iframes + // https://bugs.jquery.com/ticket/4833 + return !rhtml.test( namespace || docElem && docElem.nodeName || "HTML" ); +}; + +/** + * Sets document-related variables once based on the current document + * @param {Element|Object} [doc] An element or document object to use to set the document + * @returns {Object} Returns the current document + */ +setDocument = Sizzle.setDocument = function( node ) { + var hasCompare, subWindow, + doc = node ? node.ownerDocument || node : preferredDoc; + + // Return early if doc is invalid or already selected + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( doc == document || doc.nodeType !== 9 || !doc.documentElement ) { + return document; + } + + // Update global variables + document = doc; + docElem = document.documentElement; + documentIsHTML = !isXML( document ); + + // Support: IE 9 - 11+, Edge 12 - 18+ + // Accessing iframe documents after unload throws "permission denied" errors (jQuery #13936) + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( preferredDoc != document && + ( subWindow = document.defaultView ) && subWindow.top !== subWindow ) { + + // Support: IE 11, Edge + if ( subWindow.addEventListener ) { + subWindow.addEventListener( "unload", unloadHandler, false ); + + // Support: IE 9 - 10 only + } else if ( subWindow.attachEvent ) { + subWindow.attachEvent( "onunload", unloadHandler ); + } + } + + // Support: IE 8 - 11+, Edge 12 - 18+, Chrome <=16 - 25 only, Firefox <=3.6 - 31 only, + // Safari 4 - 5 only, Opera <=11.6 - 12.x only + // IE/Edge & older browsers don't support the :scope pseudo-class. + // Support: Safari 6.0 only + // Safari 6.0 supports :scope but it's an alias of :root there. + support.scope = assert( function( el ) { + docElem.appendChild( el ).appendChild( document.createElement( "div" ) ); + return typeof el.querySelectorAll !== "undefined" && + !el.querySelectorAll( ":scope fieldset div" ).length; + } ); + + /* Attributes + ---------------------------------------------------------------------- */ + + // Support: IE<8 + // Verify that getAttribute really returns attributes and not properties + // (excepting IE8 booleans) + support.attributes = assert( function( el ) { + el.className = "i"; + return !el.getAttribute( "className" ); + } ); + + /* getElement(s)By* + ---------------------------------------------------------------------- */ + + // Check if getElementsByTagName("*") returns only elements + support.getElementsByTagName = assert( function( el ) { + el.appendChild( document.createComment( "" ) ); + return !el.getElementsByTagName( "*" ).length; + } ); + + // Support: IE<9 + support.getElementsByClassName = rnative.test( document.getElementsByClassName ); + + // Support: IE<10 + // Check if getElementById returns elements by name + // The broken getElementById methods don't pick up programmatically-set names, + // so use a roundabout getElementsByName test + support.getById = assert( function( el ) { + docElem.appendChild( el ).id = expando; + return !document.getElementsByName || !document.getElementsByName( expando ).length; + } ); + + // ID filter and find + if ( support.getById ) { + Expr.filter[ "ID" ] = function( id ) { + var attrId = id.replace( runescape, funescape ); + return function( elem ) { + return elem.getAttribute( "id" ) === attrId; + }; + }; + Expr.find[ "ID" ] = function( id, context ) { + if ( typeof context.getElementById !== "undefined" && documentIsHTML ) { + var elem = context.getElementById( id ); + return elem ? [ elem ] : []; + } + }; + } else { + Expr.filter[ "ID" ] = function( id ) { + var attrId = id.replace( runescape, funescape ); + return function( elem ) { + var node = typeof elem.getAttributeNode !== "undefined" && + elem.getAttributeNode( "id" ); + return node && node.value === attrId; + }; + }; + + // Support: IE 6 - 7 only + // getElementById is not reliable as a find shortcut + Expr.find[ "ID" ] = function( id, context ) { + if ( typeof context.getElementById !== "undefined" && documentIsHTML ) { + var node, i, elems, + elem = context.getElementById( id ); + + if ( elem ) { + + // Verify the id attribute + node = elem.getAttributeNode( "id" ); + if ( node && node.value === id ) { + return [ elem ]; + } + + // Fall back on getElementsByName + elems = context.getElementsByName( id ); + i = 0; + while ( ( elem = elems[ i++ ] ) ) { + node = elem.getAttributeNode( "id" ); + if ( node && node.value === id ) { + return [ elem ]; + } + } + } + + return []; + } + }; + } + + // Tag + Expr.find[ "TAG" ] = support.getElementsByTagName ? + function( tag, context ) { + if ( typeof context.getElementsByTagName !== "undefined" ) { + return context.getElementsByTagName( tag ); + + // DocumentFragment nodes don't have gEBTN + } else if ( support.qsa ) { + return context.querySelectorAll( tag ); + } + } : + + function( tag, context ) { + var elem, + tmp = [], + i = 0, + + // By happy coincidence, a (broken) gEBTN appears on DocumentFragment nodes too + results = context.getElementsByTagName( tag ); + + // Filter out possible comments + if ( tag === "*" ) { + while ( ( elem = results[ i++ ] ) ) { + if ( elem.nodeType === 1 ) { + tmp.push( elem ); + } + } + + return tmp; + } + return results; + }; + + // Class + Expr.find[ "CLASS" ] = support.getElementsByClassName && function( className, context ) { + if ( typeof context.getElementsByClassName !== "undefined" && documentIsHTML ) { + return context.getElementsByClassName( className ); + } + }; + + /* QSA/matchesSelector + ---------------------------------------------------------------------- */ + + // QSA and matchesSelector support + + // matchesSelector(:active) reports false when true (IE9/Opera 11.5) + rbuggyMatches = []; + + // qSa(:focus) reports false when true (Chrome 21) + // We allow this because of a bug in IE8/9 that throws an error + // whenever `document.activeElement` is accessed on an iframe + // So, we allow :focus to pass through QSA all the time to avoid the IE error + // See https://bugs.jquery.com/ticket/13378 + rbuggyQSA = []; + + if ( ( support.qsa = rnative.test( document.querySelectorAll ) ) ) { + + // Build QSA regex + // Regex strategy adopted from Diego Perini + assert( function( el ) { + + var input; + + // Select is set to empty string on purpose + // This is to test IE's treatment of not explicitly + // setting a boolean content attribute, + // since its presence should be enough + // https://bugs.jquery.com/ticket/12359 + docElem.appendChild( el ).innerHTML = "" + + ""; + + // Support: IE8, Opera 11-12.16 + // Nothing should be selected when empty strings follow ^= or $= or *= + // The test attribute must be unknown in Opera but "safe" for WinRT + // https://msdn.microsoft.com/en-us/library/ie/hh465388.aspx#attribute_section + if ( el.querySelectorAll( "[msallowcapture^='']" ).length ) { + rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:''|\"\")" ); + } + + // Support: IE8 + // Boolean attributes and "value" are not treated correctly + if ( !el.querySelectorAll( "[selected]" ).length ) { + rbuggyQSA.push( "\\[" + whitespace + "*(?:value|" + booleans + ")" ); + } + + // Support: Chrome<29, Android<4.4, Safari<7.0+, iOS<7.0+, PhantomJS<1.9.8+ + if ( !el.querySelectorAll( "[id~=" + expando + "-]" ).length ) { + rbuggyQSA.push( "~=" ); + } + + // Support: IE 11+, Edge 15 - 18+ + // IE 11/Edge don't find elements on a `[name='']` query in some cases. + // Adding a temporary attribute to the document before the selection works + // around the issue. + // Interestingly, IE 10 & older don't seem to have the issue. + input = document.createElement( "input" ); + input.setAttribute( "name", "" ); + el.appendChild( input ); + if ( !el.querySelectorAll( "[name='']" ).length ) { + rbuggyQSA.push( "\\[" + whitespace + "*name" + whitespace + "*=" + + whitespace + "*(?:''|\"\")" ); + } + + // Webkit/Opera - :checked should return selected option elements + // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked + // IE8 throws error here and will not see later tests + if ( !el.querySelectorAll( ":checked" ).length ) { + rbuggyQSA.push( ":checked" ); + } + + // Support: Safari 8+, iOS 8+ + // https://bugs.webkit.org/show_bug.cgi?id=136851 + // In-page `selector#id sibling-combinator selector` fails + if ( !el.querySelectorAll( "a#" + expando + "+*" ).length ) { + rbuggyQSA.push( ".#.+[+~]" ); + } + + // Support: Firefox <=3.6 - 5 only + // Old Firefox doesn't throw on a badly-escaped identifier. + el.querySelectorAll( "\\\f" ); + rbuggyQSA.push( "[\\r\\n\\f]" ); + } ); + + assert( function( el ) { + el.innerHTML = "" + + ""; + + // Support: Windows 8 Native Apps + // The type and name attributes are restricted during .innerHTML assignment + var input = document.createElement( "input" ); + input.setAttribute( "type", "hidden" ); + el.appendChild( input ).setAttribute( "name", "D" ); + + // Support: IE8 + // Enforce case-sensitivity of name attribute + if ( el.querySelectorAll( "[name=d]" ).length ) { + rbuggyQSA.push( "name" + whitespace + "*[*^$|!~]?=" ); + } + + // FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled) + // IE8 throws error here and will not see later tests + if ( el.querySelectorAll( ":enabled" ).length !== 2 ) { + rbuggyQSA.push( ":enabled", ":disabled" ); + } + + // Support: IE9-11+ + // IE's :disabled selector does not pick up the children of disabled fieldsets + docElem.appendChild( el ).disabled = true; + if ( el.querySelectorAll( ":disabled" ).length !== 2 ) { + rbuggyQSA.push( ":enabled", ":disabled" ); + } + + // Support: Opera 10 - 11 only + // Opera 10-11 does not throw on post-comma invalid pseudos + el.querySelectorAll( "*,:x" ); + rbuggyQSA.push( ",.*:" ); + } ); + } + + if ( ( support.matchesSelector = rnative.test( ( matches = docElem.matches || + docElem.webkitMatchesSelector || + docElem.mozMatchesSelector || + docElem.oMatchesSelector || + docElem.msMatchesSelector ) ) ) ) { + + assert( function( el ) { + + // Check to see if it's possible to do matchesSelector + // on a disconnected node (IE 9) + support.disconnectedMatch = matches.call( el, "*" ); + + // This should fail with an exception + // Gecko does not error, returns false instead + matches.call( el, "[s!='']:x" ); + rbuggyMatches.push( "!=", pseudos ); + } ); + } + + rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join( "|" ) ); + rbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join( "|" ) ); + + /* Contains + ---------------------------------------------------------------------- */ + hasCompare = rnative.test( docElem.compareDocumentPosition ); + + // Element contains another + // Purposefully self-exclusive + // As in, an element does not contain itself + contains = hasCompare || rnative.test( docElem.contains ) ? + function( a, b ) { + var adown = a.nodeType === 9 ? a.documentElement : a, + bup = b && b.parentNode; + return a === bup || !!( bup && bup.nodeType === 1 && ( + adown.contains ? + adown.contains( bup ) : + a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16 + ) ); + } : + function( a, b ) { + if ( b ) { + while ( ( b = b.parentNode ) ) { + if ( b === a ) { + return true; + } + } + } + return false; + }; + + /* Sorting + ---------------------------------------------------------------------- */ + + // Document order sorting + sortOrder = hasCompare ? + function( a, b ) { + + // Flag for duplicate removal + if ( a === b ) { + hasDuplicate = true; + return 0; + } + + // Sort on method existence if only one input has compareDocumentPosition + var compare = !a.compareDocumentPosition - !b.compareDocumentPosition; + if ( compare ) { + return compare; + } + + // Calculate position if both inputs belong to the same document + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + compare = ( a.ownerDocument || a ) == ( b.ownerDocument || b ) ? + a.compareDocumentPosition( b ) : + + // Otherwise we know they are disconnected + 1; + + // Disconnected nodes + if ( compare & 1 || + ( !support.sortDetached && b.compareDocumentPosition( a ) === compare ) ) { + + // Choose the first element that is related to our preferred document + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( a == document || a.ownerDocument == preferredDoc && + contains( preferredDoc, a ) ) { + return -1; + } + + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( b == document || b.ownerDocument == preferredDoc && + contains( preferredDoc, b ) ) { + return 1; + } + + // Maintain original order + return sortInput ? + ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) : + 0; + } + + return compare & 4 ? -1 : 1; + } : + function( a, b ) { + + // Exit early if the nodes are identical + if ( a === b ) { + hasDuplicate = true; + return 0; + } + + var cur, + i = 0, + aup = a.parentNode, + bup = b.parentNode, + ap = [ a ], + bp = [ b ]; + + // Parentless nodes are either documents or disconnected + if ( !aup || !bup ) { + + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + /* eslint-disable eqeqeq */ + return a == document ? -1 : + b == document ? 1 : + /* eslint-enable eqeqeq */ + aup ? -1 : + bup ? 1 : + sortInput ? + ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) : + 0; + + // If the nodes are siblings, we can do a quick check + } else if ( aup === bup ) { + return siblingCheck( a, b ); + } + + // Otherwise we need full lists of their ancestors for comparison + cur = a; + while ( ( cur = cur.parentNode ) ) { + ap.unshift( cur ); + } + cur = b; + while ( ( cur = cur.parentNode ) ) { + bp.unshift( cur ); + } + + // Walk down the tree looking for a discrepancy + while ( ap[ i ] === bp[ i ] ) { + i++; + } + + return i ? + + // Do a sibling check if the nodes have a common ancestor + siblingCheck( ap[ i ], bp[ i ] ) : + + // Otherwise nodes in our document sort first + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + /* eslint-disable eqeqeq */ + ap[ i ] == preferredDoc ? -1 : + bp[ i ] == preferredDoc ? 1 : + /* eslint-enable eqeqeq */ + 0; + }; + + return document; +}; + +Sizzle.matches = function( expr, elements ) { + return Sizzle( expr, null, null, elements ); +}; + +Sizzle.matchesSelector = function( elem, expr ) { + setDocument( elem ); + + if ( support.matchesSelector && documentIsHTML && + !nonnativeSelectorCache[ expr + " " ] && + ( !rbuggyMatches || !rbuggyMatches.test( expr ) ) && + ( !rbuggyQSA || !rbuggyQSA.test( expr ) ) ) { + + try { + var ret = matches.call( elem, expr ); + + // IE 9's matchesSelector returns false on disconnected nodes + if ( ret || support.disconnectedMatch || + + // As well, disconnected nodes are said to be in a document + // fragment in IE 9 + elem.document && elem.document.nodeType !== 11 ) { + return ret; + } + } catch ( e ) { + nonnativeSelectorCache( expr, true ); + } + } + + return Sizzle( expr, document, null, [ elem ] ).length > 0; +}; + +Sizzle.contains = function( context, elem ) { + + // Set document vars if needed + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( ( context.ownerDocument || context ) != document ) { + setDocument( context ); + } + return contains( context, elem ); +}; + +Sizzle.attr = function( elem, name ) { + + // Set document vars if needed + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( ( elem.ownerDocument || elem ) != document ) { + setDocument( elem ); + } + + var fn = Expr.attrHandle[ name.toLowerCase() ], + + // Don't get fooled by Object.prototype properties (jQuery #13807) + val = fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ? + fn( elem, name, !documentIsHTML ) : + undefined; + + return val !== undefined ? + val : + support.attributes || !documentIsHTML ? + elem.getAttribute( name ) : + ( val = elem.getAttributeNode( name ) ) && val.specified ? + val.value : + null; +}; + +Sizzle.escape = function( sel ) { + return ( sel + "" ).replace( rcssescape, fcssescape ); +}; + +Sizzle.error = function( msg ) { + throw new Error( "Syntax error, unrecognized expression: " + msg ); +}; + +/** + * Document sorting and removing duplicates + * @param {ArrayLike} results + */ +Sizzle.uniqueSort = function( results ) { + var elem, + duplicates = [], + j = 0, + i = 0; + + // Unless we *know* we can detect duplicates, assume their presence + hasDuplicate = !support.detectDuplicates; + sortInput = !support.sortStable && results.slice( 0 ); + results.sort( sortOrder ); + + if ( hasDuplicate ) { + while ( ( elem = results[ i++ ] ) ) { + if ( elem === results[ i ] ) { + j = duplicates.push( i ); + } + } + while ( j-- ) { + results.splice( duplicates[ j ], 1 ); + } + } + + // Clear input after sorting to release objects + // See https://github.com/jquery/sizzle/pull/225 + sortInput = null; + + return results; +}; + +/** + * Utility function for retrieving the text value of an array of DOM nodes + * @param {Array|Element} elem + */ +getText = Sizzle.getText = function( elem ) { + var node, + ret = "", + i = 0, + nodeType = elem.nodeType; + + if ( !nodeType ) { + + // If no nodeType, this is expected to be an array + while ( ( node = elem[ i++ ] ) ) { + + // Do not traverse comment nodes + ret += getText( node ); + } + } else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) { + + // Use textContent for elements + // innerText usage removed for consistency of new lines (jQuery #11153) + if ( typeof elem.textContent === "string" ) { + return elem.textContent; + } else { + + // Traverse its children + for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { + ret += getText( elem ); + } + } + } else if ( nodeType === 3 || nodeType === 4 ) { + return elem.nodeValue; + } + + // Do not include comment or processing instruction nodes + + return ret; +}; + +Expr = Sizzle.selectors = { + + // Can be adjusted by the user + cacheLength: 50, + + createPseudo: markFunction, + + match: matchExpr, + + attrHandle: {}, + + find: {}, + + relative: { + ">": { dir: "parentNode", first: true }, + " ": { dir: "parentNode" }, + "+": { dir: "previousSibling", first: true }, + "~": { dir: "previousSibling" } + }, + + preFilter: { + "ATTR": function( match ) { + match[ 1 ] = match[ 1 ].replace( runescape, funescape ); + + // Move the given value to match[3] whether quoted or unquoted + match[ 3 ] = ( match[ 3 ] || match[ 4 ] || + match[ 5 ] || "" ).replace( runescape, funescape ); + + if ( match[ 2 ] === "~=" ) { + match[ 3 ] = " " + match[ 3 ] + " "; + } + + return match.slice( 0, 4 ); + }, + + "CHILD": function( match ) { + + /* matches from matchExpr["CHILD"] + 1 type (only|nth|...) + 2 what (child|of-type) + 3 argument (even|odd|\d*|\d*n([+-]\d+)?|...) + 4 xn-component of xn+y argument ([+-]?\d*n|) + 5 sign of xn-component + 6 x of xn-component + 7 sign of y-component + 8 y of y-component + */ + match[ 1 ] = match[ 1 ].toLowerCase(); + + if ( match[ 1 ].slice( 0, 3 ) === "nth" ) { + + // nth-* requires argument + if ( !match[ 3 ] ) { + Sizzle.error( match[ 0 ] ); + } + + // numeric x and y parameters for Expr.filter.CHILD + // remember that false/true cast respectively to 0/1 + match[ 4 ] = +( match[ 4 ] ? + match[ 5 ] + ( match[ 6 ] || 1 ) : + 2 * ( match[ 3 ] === "even" || match[ 3 ] === "odd" ) ); + match[ 5 ] = +( ( match[ 7 ] + match[ 8 ] ) || match[ 3 ] === "odd" ); + + // other types prohibit arguments + } else if ( match[ 3 ] ) { + Sizzle.error( match[ 0 ] ); + } + + return match; + }, + + "PSEUDO": function( match ) { + var excess, + unquoted = !match[ 6 ] && match[ 2 ]; + + if ( matchExpr[ "CHILD" ].test( match[ 0 ] ) ) { + return null; + } + + // Accept quoted arguments as-is + if ( match[ 3 ] ) { + match[ 2 ] = match[ 4 ] || match[ 5 ] || ""; + + // Strip excess characters from unquoted arguments + } else if ( unquoted && rpseudo.test( unquoted ) && + + // Get excess from tokenize (recursively) + ( excess = tokenize( unquoted, true ) ) && + + // advance to the next closing parenthesis + ( excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length ) ) { + + // excess is a negative index + match[ 0 ] = match[ 0 ].slice( 0, excess ); + match[ 2 ] = unquoted.slice( 0, excess ); + } + + // Return only captures needed by the pseudo filter method (type and argument) + return match.slice( 0, 3 ); + } + }, + + filter: { + + "TAG": function( nodeNameSelector ) { + var nodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase(); + return nodeNameSelector === "*" ? + function() { + return true; + } : + function( elem ) { + return elem.nodeName && elem.nodeName.toLowerCase() === nodeName; + }; + }, + + "CLASS": function( className ) { + var pattern = classCache[ className + " " ]; + + return pattern || + ( pattern = new RegExp( "(^|" + whitespace + + ")" + className + "(" + whitespace + "|$)" ) ) && classCache( + className, function( elem ) { + return pattern.test( + typeof elem.className === "string" && elem.className || + typeof elem.getAttribute !== "undefined" && + elem.getAttribute( "class" ) || + "" + ); + } ); + }, + + "ATTR": function( name, operator, check ) { + return function( elem ) { + var result = Sizzle.attr( elem, name ); + + if ( result == null ) { + return operator === "!="; + } + if ( !operator ) { + return true; + } + + result += ""; + + /* eslint-disable max-len */ + + return operator === "=" ? result === check : + operator === "!=" ? result !== check : + operator === "^=" ? check && result.indexOf( check ) === 0 : + operator === "*=" ? check && result.indexOf( check ) > -1 : + operator === "$=" ? check && result.slice( -check.length ) === check : + operator === "~=" ? ( " " + result.replace( rwhitespace, " " ) + " " ).indexOf( check ) > -1 : + operator === "|=" ? result === check || result.slice( 0, check.length + 1 ) === check + "-" : + false; + /* eslint-enable max-len */ + + }; + }, + + "CHILD": function( type, what, _argument, first, last ) { + var simple = type.slice( 0, 3 ) !== "nth", + forward = type.slice( -4 ) !== "last", + ofType = what === "of-type"; + + return first === 1 && last === 0 ? + + // Shortcut for :nth-*(n) + function( elem ) { + return !!elem.parentNode; + } : + + function( elem, _context, xml ) { + var cache, uniqueCache, outerCache, node, nodeIndex, start, + dir = simple !== forward ? "nextSibling" : "previousSibling", + parent = elem.parentNode, + name = ofType && elem.nodeName.toLowerCase(), + useCache = !xml && !ofType, + diff = false; + + if ( parent ) { + + // :(first|last|only)-(child|of-type) + if ( simple ) { + while ( dir ) { + node = elem; + while ( ( node = node[ dir ] ) ) { + if ( ofType ? + node.nodeName.toLowerCase() === name : + node.nodeType === 1 ) { + + return false; + } + } + + // Reverse direction for :only-* (if we haven't yet done so) + start = dir = type === "only" && !start && "nextSibling"; + } + return true; + } + + start = [ forward ? parent.firstChild : parent.lastChild ]; + + // non-xml :nth-child(...) stores cache data on `parent` + if ( forward && useCache ) { + + // Seek `elem` from a previously-cached index + + // ...in a gzip-friendly way + node = parent; + outerCache = node[ expando ] || ( node[ expando ] = {} ); + + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ node.uniqueID ] || + ( outerCache[ node.uniqueID ] = {} ); + + cache = uniqueCache[ type ] || []; + nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ]; + diff = nodeIndex && cache[ 2 ]; + node = nodeIndex && parent.childNodes[ nodeIndex ]; + + while ( ( node = ++nodeIndex && node && node[ dir ] || + + // Fallback to seeking `elem` from the start + ( diff = nodeIndex = 0 ) || start.pop() ) ) { + + // When found, cache indexes on `parent` and break + if ( node.nodeType === 1 && ++diff && node === elem ) { + uniqueCache[ type ] = [ dirruns, nodeIndex, diff ]; + break; + } + } + + } else { + + // Use previously-cached element index if available + if ( useCache ) { + + // ...in a gzip-friendly way + node = elem; + outerCache = node[ expando ] || ( node[ expando ] = {} ); + + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ node.uniqueID ] || + ( outerCache[ node.uniqueID ] = {} ); + + cache = uniqueCache[ type ] || []; + nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ]; + diff = nodeIndex; + } + + // xml :nth-child(...) + // or :nth-last-child(...) or :nth(-last)?-of-type(...) + if ( diff === false ) { + + // Use the same loop as above to seek `elem` from the start + while ( ( node = ++nodeIndex && node && node[ dir ] || + ( diff = nodeIndex = 0 ) || start.pop() ) ) { + + if ( ( ofType ? + node.nodeName.toLowerCase() === name : + node.nodeType === 1 ) && + ++diff ) { + + // Cache the index of each encountered element + if ( useCache ) { + outerCache = node[ expando ] || + ( node[ expando ] = {} ); + + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ node.uniqueID ] || + ( outerCache[ node.uniqueID ] = {} ); + + uniqueCache[ type ] = [ dirruns, diff ]; + } + + if ( node === elem ) { + break; + } + } + } + } + } + + // Incorporate the offset, then check against cycle size + diff -= last; + return diff === first || ( diff % first === 0 && diff / first >= 0 ); + } + }; + }, + + "PSEUDO": function( pseudo, argument ) { + + // pseudo-class names are case-insensitive + // http://www.w3.org/TR/selectors/#pseudo-classes + // Prioritize by case sensitivity in case custom pseudos are added with uppercase letters + // Remember that setFilters inherits from pseudos + var args, + fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] || + Sizzle.error( "unsupported pseudo: " + pseudo ); + + // The user may use createPseudo to indicate that + // arguments are needed to create the filter function + // just as Sizzle does + if ( fn[ expando ] ) { + return fn( argument ); + } + + // But maintain support for old signatures + if ( fn.length > 1 ) { + args = [ pseudo, pseudo, "", argument ]; + return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ? + markFunction( function( seed, matches ) { + var idx, + matched = fn( seed, argument ), + i = matched.length; + while ( i-- ) { + idx = indexOf( seed, matched[ i ] ); + seed[ idx ] = !( matches[ idx ] = matched[ i ] ); + } + } ) : + function( elem ) { + return fn( elem, 0, args ); + }; + } + + return fn; + } + }, + + pseudos: { + + // Potentially complex pseudos + "not": markFunction( function( selector ) { + + // Trim the selector passed to compile + // to avoid treating leading and trailing + // spaces as combinators + var input = [], + results = [], + matcher = compile( selector.replace( rtrim, "$1" ) ); + + return matcher[ expando ] ? + markFunction( function( seed, matches, _context, xml ) { + var elem, + unmatched = matcher( seed, null, xml, [] ), + i = seed.length; + + // Match elements unmatched by `matcher` + while ( i-- ) { + if ( ( elem = unmatched[ i ] ) ) { + seed[ i ] = !( matches[ i ] = elem ); + } + } + } ) : + function( elem, _context, xml ) { + input[ 0 ] = elem; + matcher( input, null, xml, results ); + + // Don't keep the element (issue #299) + input[ 0 ] = null; + return !results.pop(); + }; + } ), + + "has": markFunction( function( selector ) { + return function( elem ) { + return Sizzle( selector, elem ).length > 0; + }; + } ), + + "contains": markFunction( function( text ) { + text = text.replace( runescape, funescape ); + return function( elem ) { + return ( elem.textContent || getText( elem ) ).indexOf( text ) > -1; + }; + } ), + + // "Whether an element is represented by a :lang() selector + // is based solely on the element's language value + // being equal to the identifier C, + // or beginning with the identifier C immediately followed by "-". + // The matching of C against the element's language value is performed case-insensitively. + // The identifier C does not have to be a valid language name." + // http://www.w3.org/TR/selectors/#lang-pseudo + "lang": markFunction( function( lang ) { + + // lang value must be a valid identifier + if ( !ridentifier.test( lang || "" ) ) { + Sizzle.error( "unsupported lang: " + lang ); + } + lang = lang.replace( runescape, funescape ).toLowerCase(); + return function( elem ) { + var elemLang; + do { + if ( ( elemLang = documentIsHTML ? + elem.lang : + elem.getAttribute( "xml:lang" ) || elem.getAttribute( "lang" ) ) ) { + + elemLang = elemLang.toLowerCase(); + return elemLang === lang || elemLang.indexOf( lang + "-" ) === 0; + } + } while ( ( elem = elem.parentNode ) && elem.nodeType === 1 ); + return false; + }; + } ), + + // Miscellaneous + "target": function( elem ) { + var hash = window.location && window.location.hash; + return hash && hash.slice( 1 ) === elem.id; + }, + + "root": function( elem ) { + return elem === docElem; + }, + + "focus": function( elem ) { + return elem === document.activeElement && + ( !document.hasFocus || document.hasFocus() ) && + !!( elem.type || elem.href || ~elem.tabIndex ); + }, + + // Boolean properties + "enabled": createDisabledPseudo( false ), + "disabled": createDisabledPseudo( true ), + + "checked": function( elem ) { + + // In CSS3, :checked should return both checked and selected elements + // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked + var nodeName = elem.nodeName.toLowerCase(); + return ( nodeName === "input" && !!elem.checked ) || + ( nodeName === "option" && !!elem.selected ); + }, + + "selected": function( elem ) { + + // Accessing this property makes selected-by-default + // options in Safari work properly + if ( elem.parentNode ) { + // eslint-disable-next-line no-unused-expressions + elem.parentNode.selectedIndex; + } + + return elem.selected === true; + }, + + // Contents + "empty": function( elem ) { + + // http://www.w3.org/TR/selectors/#empty-pseudo + // :empty is negated by element (1) or content nodes (text: 3; cdata: 4; entity ref: 5), + // but not by others (comment: 8; processing instruction: 7; etc.) + // nodeType < 6 works because attributes (2) do not appear as children + for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { + if ( elem.nodeType < 6 ) { + return false; + } + } + return true; + }, + + "parent": function( elem ) { + return !Expr.pseudos[ "empty" ]( elem ); + }, + + // Element/input types + "header": function( elem ) { + return rheader.test( elem.nodeName ); + }, + + "input": function( elem ) { + return rinputs.test( elem.nodeName ); + }, + + "button": function( elem ) { + var name = elem.nodeName.toLowerCase(); + return name === "input" && elem.type === "button" || name === "button"; + }, + + "text": function( elem ) { + var attr; + return elem.nodeName.toLowerCase() === "input" && + elem.type === "text" && + + // Support: IE<8 + // New HTML5 attribute values (e.g., "search") appear with elem.type === "text" + ( ( attr = elem.getAttribute( "type" ) ) == null || + attr.toLowerCase() === "text" ); + }, + + // Position-in-collection + "first": createPositionalPseudo( function() { + return [ 0 ]; + } ), + + "last": createPositionalPseudo( function( _matchIndexes, length ) { + return [ length - 1 ]; + } ), + + "eq": createPositionalPseudo( function( _matchIndexes, length, argument ) { + return [ argument < 0 ? argument + length : argument ]; + } ), + + "even": createPositionalPseudo( function( matchIndexes, length ) { + var i = 0; + for ( ; i < length; i += 2 ) { + matchIndexes.push( i ); + } + return matchIndexes; + } ), + + "odd": createPositionalPseudo( function( matchIndexes, length ) { + var i = 1; + for ( ; i < length; i += 2 ) { + matchIndexes.push( i ); + } + return matchIndexes; + } ), + + "lt": createPositionalPseudo( function( matchIndexes, length, argument ) { + var i = argument < 0 ? + argument + length : + argument > length ? + length : + argument; + for ( ; --i >= 0; ) { + matchIndexes.push( i ); + } + return matchIndexes; + } ), + + "gt": createPositionalPseudo( function( matchIndexes, length, argument ) { + var i = argument < 0 ? argument + length : argument; + for ( ; ++i < length; ) { + matchIndexes.push( i ); + } + return matchIndexes; + } ) + } +}; + +Expr.pseudos[ "nth" ] = Expr.pseudos[ "eq" ]; + +// Add button/input type pseudos +for ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) { + Expr.pseudos[ i ] = createInputPseudo( i ); +} +for ( i in { submit: true, reset: true } ) { + Expr.pseudos[ i ] = createButtonPseudo( i ); +} + +// Easy API for creating new setFilters +function setFilters() {} +setFilters.prototype = Expr.filters = Expr.pseudos; +Expr.setFilters = new setFilters(); + +tokenize = Sizzle.tokenize = function( selector, parseOnly ) { + var matched, match, tokens, type, + soFar, groups, preFilters, + cached = tokenCache[ selector + " " ]; + + if ( cached ) { + return parseOnly ? 0 : cached.slice( 0 ); + } + + soFar = selector; + groups = []; + preFilters = Expr.preFilter; + + while ( soFar ) { + + // Comma and first run + if ( !matched || ( match = rcomma.exec( soFar ) ) ) { + if ( match ) { + + // Don't consume trailing commas as valid + soFar = soFar.slice( match[ 0 ].length ) || soFar; + } + groups.push( ( tokens = [] ) ); + } + + matched = false; + + // Combinators + if ( ( match = rcombinators.exec( soFar ) ) ) { + matched = match.shift(); + tokens.push( { + value: matched, + + // Cast descendant combinators to space + type: match[ 0 ].replace( rtrim, " " ) + } ); + soFar = soFar.slice( matched.length ); + } + + // Filters + for ( type in Expr.filter ) { + if ( ( match = matchExpr[ type ].exec( soFar ) ) && ( !preFilters[ type ] || + ( match = preFilters[ type ]( match ) ) ) ) { + matched = match.shift(); + tokens.push( { + value: matched, + type: type, + matches: match + } ); + soFar = soFar.slice( matched.length ); + } + } + + if ( !matched ) { + break; + } + } + + // Return the length of the invalid excess + // if we're just parsing + // Otherwise, throw an error or return tokens + return parseOnly ? + soFar.length : + soFar ? + Sizzle.error( selector ) : + + // Cache the tokens + tokenCache( selector, groups ).slice( 0 ); +}; + +function toSelector( tokens ) { + var i = 0, + len = tokens.length, + selector = ""; + for ( ; i < len; i++ ) { + selector += tokens[ i ].value; + } + return selector; +} + +function addCombinator( matcher, combinator, base ) { + var dir = combinator.dir, + skip = combinator.next, + key = skip || dir, + checkNonElements = base && key === "parentNode", + doneName = done++; + + return combinator.first ? + + // Check against closest ancestor/preceding element + function( elem, context, xml ) { + while ( ( elem = elem[ dir ] ) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + return matcher( elem, context, xml ); + } + } + return false; + } : + + // Check against all ancestor/preceding elements + function( elem, context, xml ) { + var oldCache, uniqueCache, outerCache, + newCache = [ dirruns, doneName ]; + + // We can't set arbitrary data on XML nodes, so they don't benefit from combinator caching + if ( xml ) { + while ( ( elem = elem[ dir ] ) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + if ( matcher( elem, context, xml ) ) { + return true; + } + } + } + } else { + while ( ( elem = elem[ dir ] ) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + outerCache = elem[ expando ] || ( elem[ expando ] = {} ); + + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ elem.uniqueID ] || + ( outerCache[ elem.uniqueID ] = {} ); + + if ( skip && skip === elem.nodeName.toLowerCase() ) { + elem = elem[ dir ] || elem; + } else if ( ( oldCache = uniqueCache[ key ] ) && + oldCache[ 0 ] === dirruns && oldCache[ 1 ] === doneName ) { + + // Assign to newCache so results back-propagate to previous elements + return ( newCache[ 2 ] = oldCache[ 2 ] ); + } else { + + // Reuse newcache so results back-propagate to previous elements + uniqueCache[ key ] = newCache; + + // A match means we're done; a fail means we have to keep checking + if ( ( newCache[ 2 ] = matcher( elem, context, xml ) ) ) { + return true; + } + } + } + } + } + return false; + }; +} + +function elementMatcher( matchers ) { + return matchers.length > 1 ? + function( elem, context, xml ) { + var i = matchers.length; + while ( i-- ) { + if ( !matchers[ i ]( elem, context, xml ) ) { + return false; + } + } + return true; + } : + matchers[ 0 ]; +} + +function multipleContexts( selector, contexts, results ) { + var i = 0, + len = contexts.length; + for ( ; i < len; i++ ) { + Sizzle( selector, contexts[ i ], results ); + } + return results; +} + +function condense( unmatched, map, filter, context, xml ) { + var elem, + newUnmatched = [], + i = 0, + len = unmatched.length, + mapped = map != null; + + for ( ; i < len; i++ ) { + if ( ( elem = unmatched[ i ] ) ) { + if ( !filter || filter( elem, context, xml ) ) { + newUnmatched.push( elem ); + if ( mapped ) { + map.push( i ); + } + } + } + } + + return newUnmatched; +} + +function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) { + if ( postFilter && !postFilter[ expando ] ) { + postFilter = setMatcher( postFilter ); + } + if ( postFinder && !postFinder[ expando ] ) { + postFinder = setMatcher( postFinder, postSelector ); + } + return markFunction( function( seed, results, context, xml ) { + var temp, i, elem, + preMap = [], + postMap = [], + preexisting = results.length, + + // Get initial elements from seed or context + elems = seed || multipleContexts( + selector || "*", + context.nodeType ? [ context ] : context, + [] + ), + + // Prefilter to get matcher input, preserving a map for seed-results synchronization + matcherIn = preFilter && ( seed || !selector ) ? + condense( elems, preMap, preFilter, context, xml ) : + elems, + + matcherOut = matcher ? + + // If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results, + postFinder || ( seed ? preFilter : preexisting || postFilter ) ? + + // ...intermediate processing is necessary + [] : + + // ...otherwise use results directly + results : + matcherIn; + + // Find primary matches + if ( matcher ) { + matcher( matcherIn, matcherOut, context, xml ); + } + + // Apply postFilter + if ( postFilter ) { + temp = condense( matcherOut, postMap ); + postFilter( temp, [], context, xml ); + + // Un-match failing elements by moving them back to matcherIn + i = temp.length; + while ( i-- ) { + if ( ( elem = temp[ i ] ) ) { + matcherOut[ postMap[ i ] ] = !( matcherIn[ postMap[ i ] ] = elem ); + } + } + } + + if ( seed ) { + if ( postFinder || preFilter ) { + if ( postFinder ) { + + // Get the final matcherOut by condensing this intermediate into postFinder contexts + temp = []; + i = matcherOut.length; + while ( i-- ) { + if ( ( elem = matcherOut[ i ] ) ) { + + // Restore matcherIn since elem is not yet a final match + temp.push( ( matcherIn[ i ] = elem ) ); + } + } + postFinder( null, ( matcherOut = [] ), temp, xml ); + } + + // Move matched elements from seed to results to keep them synchronized + i = matcherOut.length; + while ( i-- ) { + if ( ( elem = matcherOut[ i ] ) && + ( temp = postFinder ? indexOf( seed, elem ) : preMap[ i ] ) > -1 ) { + + seed[ temp ] = !( results[ temp ] = elem ); + } + } + } + + // Add elements to results, through postFinder if defined + } else { + matcherOut = condense( + matcherOut === results ? + matcherOut.splice( preexisting, matcherOut.length ) : + matcherOut + ); + if ( postFinder ) { + postFinder( null, results, matcherOut, xml ); + } else { + push.apply( results, matcherOut ); + } + } + } ); +} + +function matcherFromTokens( tokens ) { + var checkContext, matcher, j, + len = tokens.length, + leadingRelative = Expr.relative[ tokens[ 0 ].type ], + implicitRelative = leadingRelative || Expr.relative[ " " ], + i = leadingRelative ? 1 : 0, + + // The foundational matcher ensures that elements are reachable from top-level context(s) + matchContext = addCombinator( function( elem ) { + return elem === checkContext; + }, implicitRelative, true ), + matchAnyContext = addCombinator( function( elem ) { + return indexOf( checkContext, elem ) > -1; + }, implicitRelative, true ), + matchers = [ function( elem, context, xml ) { + var ret = ( !leadingRelative && ( xml || context !== outermostContext ) ) || ( + ( checkContext = context ).nodeType ? + matchContext( elem, context, xml ) : + matchAnyContext( elem, context, xml ) ); + + // Avoid hanging onto element (issue #299) + checkContext = null; + return ret; + } ]; + + for ( ; i < len; i++ ) { + if ( ( matcher = Expr.relative[ tokens[ i ].type ] ) ) { + matchers = [ addCombinator( elementMatcher( matchers ), matcher ) ]; + } else { + matcher = Expr.filter[ tokens[ i ].type ].apply( null, tokens[ i ].matches ); + + // Return special upon seeing a positional matcher + if ( matcher[ expando ] ) { + + // Find the next relative operator (if any) for proper handling + j = ++i; + for ( ; j < len; j++ ) { + if ( Expr.relative[ tokens[ j ].type ] ) { + break; + } + } + return setMatcher( + i > 1 && elementMatcher( matchers ), + i > 1 && toSelector( + + // If the preceding token was a descendant combinator, insert an implicit any-element `*` + tokens + .slice( 0, i - 1 ) + .concat( { value: tokens[ i - 2 ].type === " " ? "*" : "" } ) + ).replace( rtrim, "$1" ), + matcher, + i < j && matcherFromTokens( tokens.slice( i, j ) ), + j < len && matcherFromTokens( ( tokens = tokens.slice( j ) ) ), + j < len && toSelector( tokens ) + ); + } + matchers.push( matcher ); + } + } + + return elementMatcher( matchers ); +} + +function matcherFromGroupMatchers( elementMatchers, setMatchers ) { + var bySet = setMatchers.length > 0, + byElement = elementMatchers.length > 0, + superMatcher = function( seed, context, xml, results, outermost ) { + var elem, j, matcher, + matchedCount = 0, + i = "0", + unmatched = seed && [], + setMatched = [], + contextBackup = outermostContext, + + // We must always have either seed elements or outermost context + elems = seed || byElement && Expr.find[ "TAG" ]( "*", outermost ), + + // Use integer dirruns iff this is the outermost matcher + dirrunsUnique = ( dirruns += contextBackup == null ? 1 : Math.random() || 0.1 ), + len = elems.length; + + if ( outermost ) { + + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + outermostContext = context == document || context || outermost; + } + + // Add elements passing elementMatchers directly to results + // Support: IE<9, Safari + // Tolerate NodeList properties (IE: "length"; Safari: ) matching elements by id + for ( ; i !== len && ( elem = elems[ i ] ) != null; i++ ) { + if ( byElement && elem ) { + j = 0; + + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( !context && elem.ownerDocument != document ) { + setDocument( elem ); + xml = !documentIsHTML; + } + while ( ( matcher = elementMatchers[ j++ ] ) ) { + if ( matcher( elem, context || document, xml ) ) { + results.push( elem ); + break; + } + } + if ( outermost ) { + dirruns = dirrunsUnique; + } + } + + // Track unmatched elements for set filters + if ( bySet ) { + + // They will have gone through all possible matchers + if ( ( elem = !matcher && elem ) ) { + matchedCount--; + } + + // Lengthen the array for every element, matched or not + if ( seed ) { + unmatched.push( elem ); + } + } + } + + // `i` is now the count of elements visited above, and adding it to `matchedCount` + // makes the latter nonnegative. + matchedCount += i; + + // Apply set filters to unmatched elements + // NOTE: This can be skipped if there are no unmatched elements (i.e., `matchedCount` + // equals `i`), unless we didn't visit _any_ elements in the above loop because we have + // no element matchers and no seed. + // Incrementing an initially-string "0" `i` allows `i` to remain a string only in that + // case, which will result in a "00" `matchedCount` that differs from `i` but is also + // numerically zero. + if ( bySet && i !== matchedCount ) { + j = 0; + while ( ( matcher = setMatchers[ j++ ] ) ) { + matcher( unmatched, setMatched, context, xml ); + } + + if ( seed ) { + + // Reintegrate element matches to eliminate the need for sorting + if ( matchedCount > 0 ) { + while ( i-- ) { + if ( !( unmatched[ i ] || setMatched[ i ] ) ) { + setMatched[ i ] = pop.call( results ); + } + } + } + + // Discard index placeholder values to get only actual matches + setMatched = condense( setMatched ); + } + + // Add matches to results + push.apply( results, setMatched ); + + // Seedless set matches succeeding multiple successful matchers stipulate sorting + if ( outermost && !seed && setMatched.length > 0 && + ( matchedCount + setMatchers.length ) > 1 ) { + + Sizzle.uniqueSort( results ); + } + } + + // Override manipulation of globals by nested matchers + if ( outermost ) { + dirruns = dirrunsUnique; + outermostContext = contextBackup; + } + + return unmatched; + }; + + return bySet ? + markFunction( superMatcher ) : + superMatcher; +} + +compile = Sizzle.compile = function( selector, match /* Internal Use Only */ ) { + var i, + setMatchers = [], + elementMatchers = [], + cached = compilerCache[ selector + " " ]; + + if ( !cached ) { + + // Generate a function of recursive functions that can be used to check each element + if ( !match ) { + match = tokenize( selector ); + } + i = match.length; + while ( i-- ) { + cached = matcherFromTokens( match[ i ] ); + if ( cached[ expando ] ) { + setMatchers.push( cached ); + } else { + elementMatchers.push( cached ); + } + } + + // Cache the compiled function + cached = compilerCache( + selector, + matcherFromGroupMatchers( elementMatchers, setMatchers ) + ); + + // Save selector and tokenization + cached.selector = selector; + } + return cached; +}; + +/** + * A low-level selection function that works with Sizzle's compiled + * selector functions + * @param {String|Function} selector A selector or a pre-compiled + * selector function built with Sizzle.compile + * @param {Element} context + * @param {Array} [results] + * @param {Array} [seed] A set of elements to match against + */ +select = Sizzle.select = function( selector, context, results, seed ) { + var i, tokens, token, type, find, + compiled = typeof selector === "function" && selector, + match = !seed && tokenize( ( selector = compiled.selector || selector ) ); + + results = results || []; + + // Try to minimize operations if there is only one selector in the list and no seed + // (the latter of which guarantees us context) + if ( match.length === 1 ) { + + // Reduce context if the leading compound selector is an ID + tokens = match[ 0 ] = match[ 0 ].slice( 0 ); + if ( tokens.length > 2 && ( token = tokens[ 0 ] ).type === "ID" && + context.nodeType === 9 && documentIsHTML && Expr.relative[ tokens[ 1 ].type ] ) { + + context = ( Expr.find[ "ID" ]( token.matches[ 0 ] + .replace( runescape, funescape ), context ) || [] )[ 0 ]; + if ( !context ) { + return results; + + // Precompiled matchers will still verify ancestry, so step up a level + } else if ( compiled ) { + context = context.parentNode; + } + + selector = selector.slice( tokens.shift().value.length ); + } + + // Fetch a seed set for right-to-left matching + i = matchExpr[ "needsContext" ].test( selector ) ? 0 : tokens.length; + while ( i-- ) { + token = tokens[ i ]; + + // Abort if we hit a combinator + if ( Expr.relative[ ( type = token.type ) ] ) { + break; + } + if ( ( find = Expr.find[ type ] ) ) { + + // Search, expanding context for leading sibling combinators + if ( ( seed = find( + token.matches[ 0 ].replace( runescape, funescape ), + rsibling.test( tokens[ 0 ].type ) && testContext( context.parentNode ) || + context + ) ) ) { + + // If seed is empty or no tokens remain, we can return early + tokens.splice( i, 1 ); + selector = seed.length && toSelector( tokens ); + if ( !selector ) { + push.apply( results, seed ); + return results; + } + + break; + } + } + } + } + + // Compile and execute a filtering function if one is not provided + // Provide `match` to avoid retokenization if we modified the selector above + ( compiled || compile( selector, match ) )( + seed, + context, + !documentIsHTML, + results, + !context || rsibling.test( selector ) && testContext( context.parentNode ) || context + ); + return results; +}; + +// One-time assignments + +// Sort stability +support.sortStable = expando.split( "" ).sort( sortOrder ).join( "" ) === expando; + +// Support: Chrome 14-35+ +// Always assume duplicates if they aren't passed to the comparison function +support.detectDuplicates = !!hasDuplicate; + +// Initialize against the default document +setDocument(); + +// Support: Webkit<537.32 - Safari 6.0.3/Chrome 25 (fixed in Chrome 27) +// Detached nodes confoundingly follow *each other* +support.sortDetached = assert( function( el ) { + + // Should return 1, but returns 4 (following) + return el.compareDocumentPosition( document.createElement( "fieldset" ) ) & 1; +} ); + +// Support: IE<8 +// Prevent attribute/property "interpolation" +// https://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx +if ( !assert( function( el ) { + el.innerHTML = ""; + return el.firstChild.getAttribute( "href" ) === "#"; +} ) ) { + addHandle( "type|href|height|width", function( elem, name, isXML ) { + if ( !isXML ) { + return elem.getAttribute( name, name.toLowerCase() === "type" ? 1 : 2 ); + } + } ); +} + +// Support: IE<9 +// Use defaultValue in place of getAttribute("value") +if ( !support.attributes || !assert( function( el ) { + el.innerHTML = ""; + el.firstChild.setAttribute( "value", "" ); + return el.firstChild.getAttribute( "value" ) === ""; +} ) ) { + addHandle( "value", function( elem, _name, isXML ) { + if ( !isXML && elem.nodeName.toLowerCase() === "input" ) { + return elem.defaultValue; + } + } ); +} + +// Support: IE<9 +// Use getAttributeNode to fetch booleans when getAttribute lies +if ( !assert( function( el ) { + return el.getAttribute( "disabled" ) == null; +} ) ) { + addHandle( booleans, function( elem, name, isXML ) { + var val; + if ( !isXML ) { + return elem[ name ] === true ? name.toLowerCase() : + ( val = elem.getAttributeNode( name ) ) && val.specified ? + val.value : + null; + } + } ); +} + +return Sizzle; + +} )( window ); + + + +jQuery.find = Sizzle; +jQuery.expr = Sizzle.selectors; + +// Deprecated +jQuery.expr[ ":" ] = jQuery.expr.pseudos; +jQuery.uniqueSort = jQuery.unique = Sizzle.uniqueSort; +jQuery.text = Sizzle.getText; +jQuery.isXMLDoc = Sizzle.isXML; +jQuery.contains = Sizzle.contains; +jQuery.escapeSelector = Sizzle.escape; + + + + +var dir = function( elem, dir, until ) { + var matched = [], + truncate = until !== undefined; + + while ( ( elem = elem[ dir ] ) && elem.nodeType !== 9 ) { + if ( elem.nodeType === 1 ) { + if ( truncate && jQuery( elem ).is( until ) ) { + break; + } + matched.push( elem ); + } + } + return matched; +}; + + +var siblings = function( n, elem ) { + var matched = []; + + for ( ; n; n = n.nextSibling ) { + if ( n.nodeType === 1 && n !== elem ) { + matched.push( n ); + } + } + + return matched; +}; + + +var rneedsContext = jQuery.expr.match.needsContext; + + + +function nodeName( elem, name ) { + + return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase(); + +}; +var rsingleTag = ( /^<([a-z][^\/\0>:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i ); + + + +// Implement the identical functionality for filter and not +function winnow( elements, qualifier, not ) { + if ( isFunction( qualifier ) ) { + return jQuery.grep( elements, function( elem, i ) { + return !!qualifier.call( elem, i, elem ) !== not; + } ); + } + + // Single element + if ( qualifier.nodeType ) { + return jQuery.grep( elements, function( elem ) { + return ( elem === qualifier ) !== not; + } ); + } + + // Arraylike of elements (jQuery, arguments, Array) + if ( typeof qualifier !== "string" ) { + return jQuery.grep( elements, function( elem ) { + return ( indexOf.call( qualifier, elem ) > -1 ) !== not; + } ); + } + + // Filtered directly for both simple and complex selectors + return jQuery.filter( qualifier, elements, not ); +} + +jQuery.filter = function( expr, elems, not ) { + var elem = elems[ 0 ]; + + if ( not ) { + expr = ":not(" + expr + ")"; + } + + if ( elems.length === 1 && elem.nodeType === 1 ) { + return jQuery.find.matchesSelector( elem, expr ) ? [ elem ] : []; + } + + return jQuery.find.matches( expr, jQuery.grep( elems, function( elem ) { + return elem.nodeType === 1; + } ) ); +}; + +jQuery.fn.extend( { + find: function( selector ) { + var i, ret, + len = this.length, + self = this; + + if ( typeof selector !== "string" ) { + return this.pushStack( jQuery( selector ).filter( function() { + for ( i = 0; i < len; i++ ) { + if ( jQuery.contains( self[ i ], this ) ) { + return true; + } + } + } ) ); + } + + ret = this.pushStack( [] ); + + for ( i = 0; i < len; i++ ) { + jQuery.find( selector, self[ i ], ret ); + } + + return len > 1 ? jQuery.uniqueSort( ret ) : ret; + }, + filter: function( selector ) { + return this.pushStack( winnow( this, selector || [], false ) ); + }, + not: function( selector ) { + return this.pushStack( winnow( this, selector || [], true ) ); + }, + is: function( selector ) { + return !!winnow( + this, + + // If this is a positional/relative selector, check membership in the returned set + // so $("p:first").is("p:last") won't return true for a doc with two "p". + typeof selector === "string" && rneedsContext.test( selector ) ? + jQuery( selector ) : + selector || [], + false + ).length; + } +} ); + + +// Initialize a jQuery object + + +// A central reference to the root jQuery(document) +var rootjQuery, + + // A simple way to check for HTML strings + // Prioritize #id over to avoid XSS via location.hash (#9521) + // Strict HTML recognition (#11290: must start with <) + // Shortcut simple #id case for speed + rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]+))$/, + + init = jQuery.fn.init = function( selector, context, root ) { + var match, elem; + + // HANDLE: $(""), $(null), $(undefined), $(false) + if ( !selector ) { + return this; + } + + // Method init() accepts an alternate rootjQuery + // so migrate can support jQuery.sub (gh-2101) + root = root || rootjQuery; + + // Handle HTML strings + if ( typeof selector === "string" ) { + if ( selector[ 0 ] === "<" && + selector[ selector.length - 1 ] === ">" && + selector.length >= 3 ) { + + // Assume that strings that start and end with <> are HTML and skip the regex check + match = [ null, selector, null ]; + + } else { + match = rquickExpr.exec( selector ); + } + + // Match html or make sure no context is specified for #id + if ( match && ( match[ 1 ] || !context ) ) { + + // HANDLE: $(html) -> $(array) + if ( match[ 1 ] ) { + context = context instanceof jQuery ? context[ 0 ] : context; + + // Option to run scripts is true for back-compat + // Intentionally let the error be thrown if parseHTML is not present + jQuery.merge( this, jQuery.parseHTML( + match[ 1 ], + context && context.nodeType ? context.ownerDocument || context : document, + true + ) ); + + // HANDLE: $(html, props) + if ( rsingleTag.test( match[ 1 ] ) && jQuery.isPlainObject( context ) ) { + for ( match in context ) { + + // Properties of context are called as methods if possible + if ( isFunction( this[ match ] ) ) { + this[ match ]( context[ match ] ); + + // ...and otherwise set as attributes + } else { + this.attr( match, context[ match ] ); + } + } + } + + return this; + + // HANDLE: $(#id) + } else { + elem = document.getElementById( match[ 2 ] ); + + if ( elem ) { + + // Inject the element directly into the jQuery object + this[ 0 ] = elem; + this.length = 1; + } + return this; + } + + // HANDLE: $(expr, $(...)) + } else if ( !context || context.jquery ) { + return ( context || root ).find( selector ); + + // HANDLE: $(expr, context) + // (which is just equivalent to: $(context).find(expr) + } else { + return this.constructor( context ).find( selector ); + } + + // HANDLE: $(DOMElement) + } else if ( selector.nodeType ) { + this[ 0 ] = selector; + this.length = 1; + return this; + + // HANDLE: $(function) + // Shortcut for document ready + } else if ( isFunction( selector ) ) { + return root.ready !== undefined ? + root.ready( selector ) : + + // Execute immediately if ready is not present + selector( jQuery ); + } + + return jQuery.makeArray( selector, this ); + }; + +// Give the init function the jQuery prototype for later instantiation +init.prototype = jQuery.fn; + +// Initialize central reference +rootjQuery = jQuery( document ); + + +var rparentsprev = /^(?:parents|prev(?:Until|All))/, + + // Methods guaranteed to produce a unique set when starting from a unique set + guaranteedUnique = { + children: true, + contents: true, + next: true, + prev: true + }; + +jQuery.fn.extend( { + has: function( target ) { + var targets = jQuery( target, this ), + l = targets.length; + + return this.filter( function() { + var i = 0; + for ( ; i < l; i++ ) { + if ( jQuery.contains( this, targets[ i ] ) ) { + return true; + } + } + } ); + }, + + closest: function( selectors, context ) { + var cur, + i = 0, + l = this.length, + matched = [], + targets = typeof selectors !== "string" && jQuery( selectors ); + + // Positional selectors never match, since there's no _selection_ context + if ( !rneedsContext.test( selectors ) ) { + for ( ; i < l; i++ ) { + for ( cur = this[ i ]; cur && cur !== context; cur = cur.parentNode ) { + + // Always skip document fragments + if ( cur.nodeType < 11 && ( targets ? + targets.index( cur ) > -1 : + + // Don't pass non-elements to Sizzle + cur.nodeType === 1 && + jQuery.find.matchesSelector( cur, selectors ) ) ) { + + matched.push( cur ); + break; + } + } + } + } + + return this.pushStack( matched.length > 1 ? jQuery.uniqueSort( matched ) : matched ); + }, + + // Determine the position of an element within the set + index: function( elem ) { + + // No argument, return index in parent + if ( !elem ) { + return ( this[ 0 ] && this[ 0 ].parentNode ) ? this.first().prevAll().length : -1; + } + + // Index in selector + if ( typeof elem === "string" ) { + return indexOf.call( jQuery( elem ), this[ 0 ] ); + } + + // Locate the position of the desired element + return indexOf.call( this, + + // If it receives a jQuery object, the first element is used + elem.jquery ? elem[ 0 ] : elem + ); + }, + + add: function( selector, context ) { + return this.pushStack( + jQuery.uniqueSort( + jQuery.merge( this.get(), jQuery( selector, context ) ) + ) + ); + }, + + addBack: function( selector ) { + return this.add( selector == null ? + this.prevObject : this.prevObject.filter( selector ) + ); + } +} ); + +function sibling( cur, dir ) { + while ( ( cur = cur[ dir ] ) && cur.nodeType !== 1 ) {} + return cur; +} + +jQuery.each( { + parent: function( elem ) { + var parent = elem.parentNode; + return parent && parent.nodeType !== 11 ? parent : null; + }, + parents: function( elem ) { + return dir( elem, "parentNode" ); + }, + parentsUntil: function( elem, _i, until ) { + return dir( elem, "parentNode", until ); + }, + next: function( elem ) { + return sibling( elem, "nextSibling" ); + }, + prev: function( elem ) { + return sibling( elem, "previousSibling" ); + }, + nextAll: function( elem ) { + return dir( elem, "nextSibling" ); + }, + prevAll: function( elem ) { + return dir( elem, "previousSibling" ); + }, + nextUntil: function( elem, _i, until ) { + return dir( elem, "nextSibling", until ); + }, + prevUntil: function( elem, _i, until ) { + return dir( elem, "previousSibling", until ); + }, + siblings: function( elem ) { + return siblings( ( elem.parentNode || {} ).firstChild, elem ); + }, + children: function( elem ) { + return siblings( elem.firstChild ); + }, + contents: function( elem ) { + if ( elem.contentDocument != null && + + // Support: IE 11+ + // elements with no `data` attribute has an object + // `contentDocument` with a `null` prototype. + getProto( elem.contentDocument ) ) { + + return elem.contentDocument; + } + + // Support: IE 9 - 11 only, iOS 7 only, Android Browser <=4.3 only + // Treat the template element as a regular one in browsers that + // don't support it. + if ( nodeName( elem, "template" ) ) { + elem = elem.content || elem; + } + + return jQuery.merge( [], elem.childNodes ); + } +}, function( name, fn ) { + jQuery.fn[ name ] = function( until, selector ) { + var matched = jQuery.map( this, fn, until ); + + if ( name.slice( -5 ) !== "Until" ) { + selector = until; + } + + if ( selector && typeof selector === "string" ) { + matched = jQuery.filter( selector, matched ); + } + + if ( this.length > 1 ) { + + // Remove duplicates + if ( !guaranteedUnique[ name ] ) { + jQuery.uniqueSort( matched ); + } + + // Reverse order for parents* and prev-derivatives + if ( rparentsprev.test( name ) ) { + matched.reverse(); + } + } + + return this.pushStack( matched ); + }; +} ); +var rnothtmlwhite = ( /[^\x20\t\r\n\f]+/g ); + + + +// Convert String-formatted options into Object-formatted ones +function createOptions( options ) { + var object = {}; + jQuery.each( options.match( rnothtmlwhite ) || [], function( _, flag ) { + object[ flag ] = true; + } ); + return object; +} + +/* + * Create a callback list using the following parameters: + * + * options: an optional list of space-separated options that will change how + * the callback list behaves or a more traditional option object + * + * By default a callback list will act like an event callback list and can be + * "fired" multiple times. + * + * Possible options: + * + * once: will ensure the callback list can only be fired once (like a Deferred) + * + * memory: will keep track of previous values and will call any callback added + * after the list has been fired right away with the latest "memorized" + * values (like a Deferred) + * + * unique: will ensure a callback can only be added once (no duplicate in the list) + * + * stopOnFalse: interrupt callings when a callback returns false + * + */ +jQuery.Callbacks = function( options ) { + + // Convert options from String-formatted to Object-formatted if needed + // (we check in cache first) + options = typeof options === "string" ? + createOptions( options ) : + jQuery.extend( {}, options ); + + var // Flag to know if list is currently firing + firing, + + // Last fire value for non-forgettable lists + memory, + + // Flag to know if list was already fired + fired, + + // Flag to prevent firing + locked, + + // Actual callback list + list = [], + + // Queue of execution data for repeatable lists + queue = [], + + // Index of currently firing callback (modified by add/remove as needed) + firingIndex = -1, + + // Fire callbacks + fire = function() { + + // Enforce single-firing + locked = locked || options.once; + + // Execute callbacks for all pending executions, + // respecting firingIndex overrides and runtime changes + fired = firing = true; + for ( ; queue.length; firingIndex = -1 ) { + memory = queue.shift(); + while ( ++firingIndex < list.length ) { + + // Run callback and check for early termination + if ( list[ firingIndex ].apply( memory[ 0 ], memory[ 1 ] ) === false && + options.stopOnFalse ) { + + // Jump to end and forget the data so .add doesn't re-fire + firingIndex = list.length; + memory = false; + } + } + } + + // Forget the data if we're done with it + if ( !options.memory ) { + memory = false; + } + + firing = false; + + // Clean up if we're done firing for good + if ( locked ) { + + // Keep an empty list if we have data for future add calls + if ( memory ) { + list = []; + + // Otherwise, this object is spent + } else { + list = ""; + } + } + }, + + // Actual Callbacks object + self = { + + // Add a callback or a collection of callbacks to the list + add: function() { + if ( list ) { + + // If we have memory from a past run, we should fire after adding + if ( memory && !firing ) { + firingIndex = list.length - 1; + queue.push( memory ); + } + + ( function add( args ) { + jQuery.each( args, function( _, arg ) { + if ( isFunction( arg ) ) { + if ( !options.unique || !self.has( arg ) ) { + list.push( arg ); + } + } else if ( arg && arg.length && toType( arg ) !== "string" ) { + + // Inspect recursively + add( arg ); + } + } ); + } )( arguments ); + + if ( memory && !firing ) { + fire(); + } + } + return this; + }, + + // Remove a callback from the list + remove: function() { + jQuery.each( arguments, function( _, arg ) { + var index; + while ( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) { + list.splice( index, 1 ); + + // Handle firing indexes + if ( index <= firingIndex ) { + firingIndex--; + } + } + } ); + return this; + }, + + // Check if a given callback is in the list. + // If no argument is given, return whether or not list has callbacks attached. + has: function( fn ) { + return fn ? + jQuery.inArray( fn, list ) > -1 : + list.length > 0; + }, + + // Remove all callbacks from the list + empty: function() { + if ( list ) { + list = []; + } + return this; + }, + + // Disable .fire and .add + // Abort any current/pending executions + // Clear all callbacks and values + disable: function() { + locked = queue = []; + list = memory = ""; + return this; + }, + disabled: function() { + return !list; + }, + + // Disable .fire + // Also disable .add unless we have memory (since it would have no effect) + // Abort any pending executions + lock: function() { + locked = queue = []; + if ( !memory && !firing ) { + list = memory = ""; + } + return this; + }, + locked: function() { + return !!locked; + }, + + // Call all callbacks with the given context and arguments + fireWith: function( context, args ) { + if ( !locked ) { + args = args || []; + args = [ context, args.slice ? args.slice() : args ]; + queue.push( args ); + if ( !firing ) { + fire(); + } + } + return this; + }, + + // Call all the callbacks with the given arguments + fire: function() { + self.fireWith( this, arguments ); + return this; + }, + + // To know if the callbacks have already been called at least once + fired: function() { + return !!fired; + } + }; + + return self; +}; + + +function Identity( v ) { + return v; +} +function Thrower( ex ) { + throw ex; +} + +function adoptValue( value, resolve, reject, noValue ) { + var method; + + try { + + // Check for promise aspect first to privilege synchronous behavior + if ( value && isFunction( ( method = value.promise ) ) ) { + method.call( value ).done( resolve ).fail( reject ); + + // Other thenables + } else if ( value && isFunction( ( method = value.then ) ) ) { + method.call( value, resolve, reject ); + + // Other non-thenables + } else { + + // Control `resolve` arguments by letting Array#slice cast boolean `noValue` to integer: + // * false: [ value ].slice( 0 ) => resolve( value ) + // * true: [ value ].slice( 1 ) => resolve() + resolve.apply( undefined, [ value ].slice( noValue ) ); + } + + // For Promises/A+, convert exceptions into rejections + // Since jQuery.when doesn't unwrap thenables, we can skip the extra checks appearing in + // Deferred#then to conditionally suppress rejection. + } catch ( value ) { + + // Support: Android 4.0 only + // Strict mode functions invoked without .call/.apply get global-object context + reject.apply( undefined, [ value ] ); + } +} + +jQuery.extend( { + + Deferred: function( func ) { + var tuples = [ + + // action, add listener, callbacks, + // ... .then handlers, argument index, [final state] + [ "notify", "progress", jQuery.Callbacks( "memory" ), + jQuery.Callbacks( "memory" ), 2 ], + [ "resolve", "done", jQuery.Callbacks( "once memory" ), + jQuery.Callbacks( "once memory" ), 0, "resolved" ], + [ "reject", "fail", jQuery.Callbacks( "once memory" ), + jQuery.Callbacks( "once memory" ), 1, "rejected" ] + ], + state = "pending", + promise = { + state: function() { + return state; + }, + always: function() { + deferred.done( arguments ).fail( arguments ); + return this; + }, + "catch": function( fn ) { + return promise.then( null, fn ); + }, + + // Keep pipe for back-compat + pipe: function( /* fnDone, fnFail, fnProgress */ ) { + var fns = arguments; + + return jQuery.Deferred( function( newDefer ) { + jQuery.each( tuples, function( _i, tuple ) { + + // Map tuples (progress, done, fail) to arguments (done, fail, progress) + var fn = isFunction( fns[ tuple[ 4 ] ] ) && fns[ tuple[ 4 ] ]; + + // deferred.progress(function() { bind to newDefer or newDefer.notify }) + // deferred.done(function() { bind to newDefer or newDefer.resolve }) + // deferred.fail(function() { bind to newDefer or newDefer.reject }) + deferred[ tuple[ 1 ] ]( function() { + var returned = fn && fn.apply( this, arguments ); + if ( returned && isFunction( returned.promise ) ) { + returned.promise() + .progress( newDefer.notify ) + .done( newDefer.resolve ) + .fail( newDefer.reject ); + } else { + newDefer[ tuple[ 0 ] + "With" ]( + this, + fn ? [ returned ] : arguments + ); + } + } ); + } ); + fns = null; + } ).promise(); + }, + then: function( onFulfilled, onRejected, onProgress ) { + var maxDepth = 0; + function resolve( depth, deferred, handler, special ) { + return function() { + var that = this, + args = arguments, + mightThrow = function() { + var returned, then; + + // Support: Promises/A+ section 2.3.3.3.3 + // https://promisesaplus.com/#point-59 + // Ignore double-resolution attempts + if ( depth < maxDepth ) { + return; + } + + returned = handler.apply( that, args ); + + // Support: Promises/A+ section 2.3.1 + // https://promisesaplus.com/#point-48 + if ( returned === deferred.promise() ) { + throw new TypeError( "Thenable self-resolution" ); + } + + // Support: Promises/A+ sections 2.3.3.1, 3.5 + // https://promisesaplus.com/#point-54 + // https://promisesaplus.com/#point-75 + // Retrieve `then` only once + then = returned && + + // Support: Promises/A+ section 2.3.4 + // https://promisesaplus.com/#point-64 + // Only check objects and functions for thenability + ( typeof returned === "object" || + typeof returned === "function" ) && + returned.then; + + // Handle a returned thenable + if ( isFunction( then ) ) { + + // Special processors (notify) just wait for resolution + if ( special ) { + then.call( + returned, + resolve( maxDepth, deferred, Identity, special ), + resolve( maxDepth, deferred, Thrower, special ) + ); + + // Normal processors (resolve) also hook into progress + } else { + + // ...and disregard older resolution values + maxDepth++; + + then.call( + returned, + resolve( maxDepth, deferred, Identity, special ), + resolve( maxDepth, deferred, Thrower, special ), + resolve( maxDepth, deferred, Identity, + deferred.notifyWith ) + ); + } + + // Handle all other returned values + } else { + + // Only substitute handlers pass on context + // and multiple values (non-spec behavior) + if ( handler !== Identity ) { + that = undefined; + args = [ returned ]; + } + + // Process the value(s) + // Default process is resolve + ( special || deferred.resolveWith )( that, args ); + } + }, + + // Only normal processors (resolve) catch and reject exceptions + process = special ? + mightThrow : + function() { + try { + mightThrow(); + } catch ( e ) { + + if ( jQuery.Deferred.exceptionHook ) { + jQuery.Deferred.exceptionHook( e, + process.stackTrace ); + } + + // Support: Promises/A+ section 2.3.3.3.4.1 + // https://promisesaplus.com/#point-61 + // Ignore post-resolution exceptions + if ( depth + 1 >= maxDepth ) { + + // Only substitute handlers pass on context + // and multiple values (non-spec behavior) + if ( handler !== Thrower ) { + that = undefined; + args = [ e ]; + } + + deferred.rejectWith( that, args ); + } + } + }; + + // Support: Promises/A+ section 2.3.3.3.1 + // https://promisesaplus.com/#point-57 + // Re-resolve promises immediately to dodge false rejection from + // subsequent errors + if ( depth ) { + process(); + } else { + + // Call an optional hook to record the stack, in case of exception + // since it's otherwise lost when execution goes async + if ( jQuery.Deferred.getStackHook ) { + process.stackTrace = jQuery.Deferred.getStackHook(); + } + window.setTimeout( process ); + } + }; + } + + return jQuery.Deferred( function( newDefer ) { + + // progress_handlers.add( ... ) + tuples[ 0 ][ 3 ].add( + resolve( + 0, + newDefer, + isFunction( onProgress ) ? + onProgress : + Identity, + newDefer.notifyWith + ) + ); + + // fulfilled_handlers.add( ... ) + tuples[ 1 ][ 3 ].add( + resolve( + 0, + newDefer, + isFunction( onFulfilled ) ? + onFulfilled : + Identity + ) + ); + + // rejected_handlers.add( ... ) + tuples[ 2 ][ 3 ].add( + resolve( + 0, + newDefer, + isFunction( onRejected ) ? + onRejected : + Thrower + ) + ); + } ).promise(); + }, + + // Get a promise for this deferred + // If obj is provided, the promise aspect is added to the object + promise: function( obj ) { + return obj != null ? jQuery.extend( obj, promise ) : promise; + } + }, + deferred = {}; + + // Add list-specific methods + jQuery.each( tuples, function( i, tuple ) { + var list = tuple[ 2 ], + stateString = tuple[ 5 ]; + + // promise.progress = list.add + // promise.done = list.add + // promise.fail = list.add + promise[ tuple[ 1 ] ] = list.add; + + // Handle state + if ( stateString ) { + list.add( + function() { + + // state = "resolved" (i.e., fulfilled) + // state = "rejected" + state = stateString; + }, + + // rejected_callbacks.disable + // fulfilled_callbacks.disable + tuples[ 3 - i ][ 2 ].disable, + + // rejected_handlers.disable + // fulfilled_handlers.disable + tuples[ 3 - i ][ 3 ].disable, + + // progress_callbacks.lock + tuples[ 0 ][ 2 ].lock, + + // progress_handlers.lock + tuples[ 0 ][ 3 ].lock + ); + } + + // progress_handlers.fire + // fulfilled_handlers.fire + // rejected_handlers.fire + list.add( tuple[ 3 ].fire ); + + // deferred.notify = function() { deferred.notifyWith(...) } + // deferred.resolve = function() { deferred.resolveWith(...) } + // deferred.reject = function() { deferred.rejectWith(...) } + deferred[ tuple[ 0 ] ] = function() { + deferred[ tuple[ 0 ] + "With" ]( this === deferred ? undefined : this, arguments ); + return this; + }; + + // deferred.notifyWith = list.fireWith + // deferred.resolveWith = list.fireWith + // deferred.rejectWith = list.fireWith + deferred[ tuple[ 0 ] + "With" ] = list.fireWith; + } ); + + // Make the deferred a promise + promise.promise( deferred ); + + // Call given func if any + if ( func ) { + func.call( deferred, deferred ); + } + + // All done! + return deferred; + }, + + // Deferred helper + when: function( singleValue ) { + var + + // count of uncompleted subordinates + remaining = arguments.length, + + // count of unprocessed arguments + i = remaining, + + // subordinate fulfillment data + resolveContexts = Array( i ), + resolveValues = slice.call( arguments ), + + // the master Deferred + master = jQuery.Deferred(), + + // subordinate callback factory + updateFunc = function( i ) { + return function( value ) { + resolveContexts[ i ] = this; + resolveValues[ i ] = arguments.length > 1 ? slice.call( arguments ) : value; + if ( !( --remaining ) ) { + master.resolveWith( resolveContexts, resolveValues ); + } + }; + }; + + // Single- and empty arguments are adopted like Promise.resolve + if ( remaining <= 1 ) { + adoptValue( singleValue, master.done( updateFunc( i ) ).resolve, master.reject, + !remaining ); + + // Use .then() to unwrap secondary thenables (cf. gh-3000) + if ( master.state() === "pending" || + isFunction( resolveValues[ i ] && resolveValues[ i ].then ) ) { + + return master.then(); + } + } + + // Multiple arguments are aggregated like Promise.all array elements + while ( i-- ) { + adoptValue( resolveValues[ i ], updateFunc( i ), master.reject ); + } + + return master.promise(); + } +} ); + + +// These usually indicate a programmer mistake during development, +// warn about them ASAP rather than swallowing them by default. +var rerrorNames = /^(Eval|Internal|Range|Reference|Syntax|Type|URI)Error$/; + +jQuery.Deferred.exceptionHook = function( error, stack ) { + + // Support: IE 8 - 9 only + // Console exists when dev tools are open, which can happen at any time + if ( window.console && window.console.warn && error && rerrorNames.test( error.name ) ) { + window.console.warn( "jQuery.Deferred exception: " + error.message, error.stack, stack ); + } +}; + + + + +jQuery.readyException = function( error ) { + window.setTimeout( function() { + throw error; + } ); +}; + + + + +// The deferred used on DOM ready +var readyList = jQuery.Deferred(); + +jQuery.fn.ready = function( fn ) { + + readyList + .then( fn ) + + // Wrap jQuery.readyException in a function so that the lookup + // happens at the time of error handling instead of callback + // registration. + .catch( function( error ) { + jQuery.readyException( error ); + } ); + + return this; +}; + +jQuery.extend( { + + // Is the DOM ready to be used? Set to true once it occurs. + isReady: false, + + // A counter to track how many items to wait for before + // the ready event fires. See #6781 + readyWait: 1, + + // Handle when the DOM is ready + ready: function( wait ) { + + // Abort if there are pending holds or we're already ready + if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) { + return; + } + + // Remember that the DOM is ready + jQuery.isReady = true; + + // If a normal DOM Ready event fired, decrement, and wait if need be + if ( wait !== true && --jQuery.readyWait > 0 ) { + return; + } + + // If there are functions bound, to execute + readyList.resolveWith( document, [ jQuery ] ); + } +} ); + +jQuery.ready.then = readyList.then; + +// The ready event handler and self cleanup method +function completed() { + document.removeEventListener( "DOMContentLoaded", completed ); + window.removeEventListener( "load", completed ); + jQuery.ready(); +} + +// Catch cases where $(document).ready() is called +// after the browser event has already occurred. +// Support: IE <=9 - 10 only +// Older IE sometimes signals "interactive" too soon +if ( document.readyState === "complete" || + ( document.readyState !== "loading" && !document.documentElement.doScroll ) ) { + + // Handle it asynchronously to allow scripts the opportunity to delay ready + window.setTimeout( jQuery.ready ); + +} else { + + // Use the handy event callback + document.addEventListener( "DOMContentLoaded", completed ); + + // A fallback to window.onload, that will always work + window.addEventListener( "load", completed ); +} + + + + +// Multifunctional method to get and set values of a collection +// The value/s can optionally be executed if it's a function +var access = function( elems, fn, key, value, chainable, emptyGet, raw ) { + var i = 0, + len = elems.length, + bulk = key == null; + + // Sets many values + if ( toType( key ) === "object" ) { + chainable = true; + for ( i in key ) { + access( elems, fn, i, key[ i ], true, emptyGet, raw ); + } + + // Sets one value + } else if ( value !== undefined ) { + chainable = true; + + if ( !isFunction( value ) ) { + raw = true; + } + + if ( bulk ) { + + // Bulk operations run against the entire set + if ( raw ) { + fn.call( elems, value ); + fn = null; + + // ...except when executing function values + } else { + bulk = fn; + fn = function( elem, _key, value ) { + return bulk.call( jQuery( elem ), value ); + }; + } + } + + if ( fn ) { + for ( ; i < len; i++ ) { + fn( + elems[ i ], key, raw ? + value : + value.call( elems[ i ], i, fn( elems[ i ], key ) ) + ); + } + } + } + + if ( chainable ) { + return elems; + } + + // Gets + if ( bulk ) { + return fn.call( elems ); + } + + return len ? fn( elems[ 0 ], key ) : emptyGet; +}; + + +// Matches dashed string for camelizing +var rmsPrefix = /^-ms-/, + rdashAlpha = /-([a-z])/g; + +// Used by camelCase as callback to replace() +function fcamelCase( _all, letter ) { + return letter.toUpperCase(); +} + +// Convert dashed to camelCase; used by the css and data modules +// Support: IE <=9 - 11, Edge 12 - 15 +// Microsoft forgot to hump their vendor prefix (#9572) +function camelCase( string ) { + return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase ); +} +var acceptData = function( owner ) { + + // Accepts only: + // - Node + // - Node.ELEMENT_NODE + // - Node.DOCUMENT_NODE + // - Object + // - Any + return owner.nodeType === 1 || owner.nodeType === 9 || !( +owner.nodeType ); +}; + + + + +function Data() { + this.expando = jQuery.expando + Data.uid++; +} + +Data.uid = 1; + +Data.prototype = { + + cache: function( owner ) { + + // Check if the owner object already has a cache + var value = owner[ this.expando ]; + + // If not, create one + if ( !value ) { + value = {}; + + // We can accept data for non-element nodes in modern browsers, + // but we should not, see #8335. + // Always return an empty object. + if ( acceptData( owner ) ) { + + // If it is a node unlikely to be stringify-ed or looped over + // use plain assignment + if ( owner.nodeType ) { + owner[ this.expando ] = value; + + // Otherwise secure it in a non-enumerable property + // configurable must be true to allow the property to be + // deleted when data is removed + } else { + Object.defineProperty( owner, this.expando, { + value: value, + configurable: true + } ); + } + } + } + + return value; + }, + set: function( owner, data, value ) { + var prop, + cache = this.cache( owner ); + + // Handle: [ owner, key, value ] args + // Always use camelCase key (gh-2257) + if ( typeof data === "string" ) { + cache[ camelCase( data ) ] = value; + + // Handle: [ owner, { properties } ] args + } else { + + // Copy the properties one-by-one to the cache object + for ( prop in data ) { + cache[ camelCase( prop ) ] = data[ prop ]; + } + } + return cache; + }, + get: function( owner, key ) { + return key === undefined ? + this.cache( owner ) : + + // Always use camelCase key (gh-2257) + owner[ this.expando ] && owner[ this.expando ][ camelCase( key ) ]; + }, + access: function( owner, key, value ) { + + // In cases where either: + // + // 1. No key was specified + // 2. A string key was specified, but no value provided + // + // Take the "read" path and allow the get method to determine + // which value to return, respectively either: + // + // 1. The entire cache object + // 2. The data stored at the key + // + if ( key === undefined || + ( ( key && typeof key === "string" ) && value === undefined ) ) { + + return this.get( owner, key ); + } + + // When the key is not a string, or both a key and value + // are specified, set or extend (existing objects) with either: + // + // 1. An object of properties + // 2. A key and value + // + this.set( owner, key, value ); + + // Since the "set" path can have two possible entry points + // return the expected data based on which path was taken[*] + return value !== undefined ? value : key; + }, + remove: function( owner, key ) { + var i, + cache = owner[ this.expando ]; + + if ( cache === undefined ) { + return; + } + + if ( key !== undefined ) { + + // Support array or space separated string of keys + if ( Array.isArray( key ) ) { + + // If key is an array of keys... + // We always set camelCase keys, so remove that. + key = key.map( camelCase ); + } else { + key = camelCase( key ); + + // If a key with the spaces exists, use it. + // Otherwise, create an array by matching non-whitespace + key = key in cache ? + [ key ] : + ( key.match( rnothtmlwhite ) || [] ); + } + + i = key.length; + + while ( i-- ) { + delete cache[ key[ i ] ]; + } + } + + // Remove the expando if there's no more data + if ( key === undefined || jQuery.isEmptyObject( cache ) ) { + + // Support: Chrome <=35 - 45 + // Webkit & Blink performance suffers when deleting properties + // from DOM nodes, so set to undefined instead + // https://bugs.chromium.org/p/chromium/issues/detail?id=378607 (bug restricted) + if ( owner.nodeType ) { + owner[ this.expando ] = undefined; + } else { + delete owner[ this.expando ]; + } + } + }, + hasData: function( owner ) { + var cache = owner[ this.expando ]; + return cache !== undefined && !jQuery.isEmptyObject( cache ); + } +}; +var dataPriv = new Data(); + +var dataUser = new Data(); + + + +// Implementation Summary +// +// 1. Enforce API surface and semantic compatibility with 1.9.x branch +// 2. Improve the module's maintainability by reducing the storage +// paths to a single mechanism. +// 3. Use the same single mechanism to support "private" and "user" data. +// 4. _Never_ expose "private" data to user code (TODO: Drop _data, _removeData) +// 5. Avoid exposing implementation details on user objects (eg. expando properties) +// 6. Provide a clear path for implementation upgrade to WeakMap in 2014 + +var rbrace = /^(?:\{[\w\W]*\}|\[[\w\W]*\])$/, + rmultiDash = /[A-Z]/g; + +function getData( data ) { + if ( data === "true" ) { + return true; + } + + if ( data === "false" ) { + return false; + } + + if ( data === "null" ) { + return null; + } + + // Only convert to a number if it doesn't change the string + if ( data === +data + "" ) { + return +data; + } + + if ( rbrace.test( data ) ) { + return JSON.parse( data ); + } + + return data; +} + +function dataAttr( elem, key, data ) { + var name; + + // If nothing was found internally, try to fetch any + // data from the HTML5 data-* attribute + if ( data === undefined && elem.nodeType === 1 ) { + name = "data-" + key.replace( rmultiDash, "-$&" ).toLowerCase(); + data = elem.getAttribute( name ); + + if ( typeof data === "string" ) { + try { + data = getData( data ); + } catch ( e ) {} + + // Make sure we set the data so it isn't changed later + dataUser.set( elem, key, data ); + } else { + data = undefined; + } + } + return data; +} + +jQuery.extend( { + hasData: function( elem ) { + return dataUser.hasData( elem ) || dataPriv.hasData( elem ); + }, + + data: function( elem, name, data ) { + return dataUser.access( elem, name, data ); + }, + + removeData: function( elem, name ) { + dataUser.remove( elem, name ); + }, + + // TODO: Now that all calls to _data and _removeData have been replaced + // with direct calls to dataPriv methods, these can be deprecated. + _data: function( elem, name, data ) { + return dataPriv.access( elem, name, data ); + }, + + _removeData: function( elem, name ) { + dataPriv.remove( elem, name ); + } +} ); + +jQuery.fn.extend( { + data: function( key, value ) { + var i, name, data, + elem = this[ 0 ], + attrs = elem && elem.attributes; + + // Gets all values + if ( key === undefined ) { + if ( this.length ) { + data = dataUser.get( elem ); + + if ( elem.nodeType === 1 && !dataPriv.get( elem, "hasDataAttrs" ) ) { + i = attrs.length; + while ( i-- ) { + + // Support: IE 11 only + // The attrs elements can be null (#14894) + if ( attrs[ i ] ) { + name = attrs[ i ].name; + if ( name.indexOf( "data-" ) === 0 ) { + name = camelCase( name.slice( 5 ) ); + dataAttr( elem, name, data[ name ] ); + } + } + } + dataPriv.set( elem, "hasDataAttrs", true ); + } + } + + return data; + } + + // Sets multiple values + if ( typeof key === "object" ) { + return this.each( function() { + dataUser.set( this, key ); + } ); + } + + return access( this, function( value ) { + var data; + + // The calling jQuery object (element matches) is not empty + // (and therefore has an element appears at this[ 0 ]) and the + // `value` parameter was not undefined. An empty jQuery object + // will result in `undefined` for elem = this[ 0 ] which will + // throw an exception if an attempt to read a data cache is made. + if ( elem && value === undefined ) { + + // Attempt to get data from the cache + // The key will always be camelCased in Data + data = dataUser.get( elem, key ); + if ( data !== undefined ) { + return data; + } + + // Attempt to "discover" the data in + // HTML5 custom data-* attrs + data = dataAttr( elem, key ); + if ( data !== undefined ) { + return data; + } + + // We tried really hard, but the data doesn't exist. + return; + } + + // Set the data... + this.each( function() { + + // We always store the camelCased key + dataUser.set( this, key, value ); + } ); + }, null, value, arguments.length > 1, null, true ); + }, + + removeData: function( key ) { + return this.each( function() { + dataUser.remove( this, key ); + } ); + } +} ); + + +jQuery.extend( { + queue: function( elem, type, data ) { + var queue; + + if ( elem ) { + type = ( type || "fx" ) + "queue"; + queue = dataPriv.get( elem, type ); + + // Speed up dequeue by getting out quickly if this is just a lookup + if ( data ) { + if ( !queue || Array.isArray( data ) ) { + queue = dataPriv.access( elem, type, jQuery.makeArray( data ) ); + } else { + queue.push( data ); + } + } + return queue || []; + } + }, + + dequeue: function( elem, type ) { + type = type || "fx"; + + var queue = jQuery.queue( elem, type ), + startLength = queue.length, + fn = queue.shift(), + hooks = jQuery._queueHooks( elem, type ), + next = function() { + jQuery.dequeue( elem, type ); + }; + + // If the fx queue is dequeued, always remove the progress sentinel + if ( fn === "inprogress" ) { + fn = queue.shift(); + startLength--; + } + + if ( fn ) { + + // Add a progress sentinel to prevent the fx queue from being + // automatically dequeued + if ( type === "fx" ) { + queue.unshift( "inprogress" ); + } + + // Clear up the last queue stop function + delete hooks.stop; + fn.call( elem, next, hooks ); + } + + if ( !startLength && hooks ) { + hooks.empty.fire(); + } + }, + + // Not public - generate a queueHooks object, or return the current one + _queueHooks: function( elem, type ) { + var key = type + "queueHooks"; + return dataPriv.get( elem, key ) || dataPriv.access( elem, key, { + empty: jQuery.Callbacks( "once memory" ).add( function() { + dataPriv.remove( elem, [ type + "queue", key ] ); + } ) + } ); + } +} ); + +jQuery.fn.extend( { + queue: function( type, data ) { + var setter = 2; + + if ( typeof type !== "string" ) { + data = type; + type = "fx"; + setter--; + } + + if ( arguments.length < setter ) { + return jQuery.queue( this[ 0 ], type ); + } + + return data === undefined ? + this : + this.each( function() { + var queue = jQuery.queue( this, type, data ); + + // Ensure a hooks for this queue + jQuery._queueHooks( this, type ); + + if ( type === "fx" && queue[ 0 ] !== "inprogress" ) { + jQuery.dequeue( this, type ); + } + } ); + }, + dequeue: function( type ) { + return this.each( function() { + jQuery.dequeue( this, type ); + } ); + }, + clearQueue: function( type ) { + return this.queue( type || "fx", [] ); + }, + + // Get a promise resolved when queues of a certain type + // are emptied (fx is the type by default) + promise: function( type, obj ) { + var tmp, + count = 1, + defer = jQuery.Deferred(), + elements = this, + i = this.length, + resolve = function() { + if ( !( --count ) ) { + defer.resolveWith( elements, [ elements ] ); + } + }; + + if ( typeof type !== "string" ) { + obj = type; + type = undefined; + } + type = type || "fx"; + + while ( i-- ) { + tmp = dataPriv.get( elements[ i ], type + "queueHooks" ); + if ( tmp && tmp.empty ) { + count++; + tmp.empty.add( resolve ); + } + } + resolve(); + return defer.promise( obj ); + } +} ); +var pnum = ( /[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/ ).source; + +var rcssNum = new RegExp( "^(?:([+-])=|)(" + pnum + ")([a-z%]*)$", "i" ); + + +var cssExpand = [ "Top", "Right", "Bottom", "Left" ]; + +var documentElement = document.documentElement; + + + + var isAttached = function( elem ) { + return jQuery.contains( elem.ownerDocument, elem ); + }, + composed = { composed: true }; + + // Support: IE 9 - 11+, Edge 12 - 18+, iOS 10.0 - 10.2 only + // Check attachment across shadow DOM boundaries when possible (gh-3504) + // Support: iOS 10.0-10.2 only + // Early iOS 10 versions support `attachShadow` but not `getRootNode`, + // leading to errors. We need to check for `getRootNode`. + if ( documentElement.getRootNode ) { + isAttached = function( elem ) { + return jQuery.contains( elem.ownerDocument, elem ) || + elem.getRootNode( composed ) === elem.ownerDocument; + }; + } +var isHiddenWithinTree = function( elem, el ) { + + // isHiddenWithinTree might be called from jQuery#filter function; + // in that case, element will be second argument + elem = el || elem; + + // Inline style trumps all + return elem.style.display === "none" || + elem.style.display === "" && + + // Otherwise, check computed style + // Support: Firefox <=43 - 45 + // Disconnected elements can have computed display: none, so first confirm that elem is + // in the document. + isAttached( elem ) && + + jQuery.css( elem, "display" ) === "none"; + }; + + + +function adjustCSS( elem, prop, valueParts, tween ) { + var adjusted, scale, + maxIterations = 20, + currentValue = tween ? + function() { + return tween.cur(); + } : + function() { + return jQuery.css( elem, prop, "" ); + }, + initial = currentValue(), + unit = valueParts && valueParts[ 3 ] || ( jQuery.cssNumber[ prop ] ? "" : "px" ), + + // Starting value computation is required for potential unit mismatches + initialInUnit = elem.nodeType && + ( jQuery.cssNumber[ prop ] || unit !== "px" && +initial ) && + rcssNum.exec( jQuery.css( elem, prop ) ); + + if ( initialInUnit && initialInUnit[ 3 ] !== unit ) { + + // Support: Firefox <=54 + // Halve the iteration target value to prevent interference from CSS upper bounds (gh-2144) + initial = initial / 2; + + // Trust units reported by jQuery.css + unit = unit || initialInUnit[ 3 ]; + + // Iteratively approximate from a nonzero starting point + initialInUnit = +initial || 1; + + while ( maxIterations-- ) { + + // Evaluate and update our best guess (doubling guesses that zero out). + // Finish if the scale equals or crosses 1 (making the old*new product non-positive). + jQuery.style( elem, prop, initialInUnit + unit ); + if ( ( 1 - scale ) * ( 1 - ( scale = currentValue() / initial || 0.5 ) ) <= 0 ) { + maxIterations = 0; + } + initialInUnit = initialInUnit / scale; + + } + + initialInUnit = initialInUnit * 2; + jQuery.style( elem, prop, initialInUnit + unit ); + + // Make sure we update the tween properties later on + valueParts = valueParts || []; + } + + if ( valueParts ) { + initialInUnit = +initialInUnit || +initial || 0; + + // Apply relative offset (+=/-=) if specified + adjusted = valueParts[ 1 ] ? + initialInUnit + ( valueParts[ 1 ] + 1 ) * valueParts[ 2 ] : + +valueParts[ 2 ]; + if ( tween ) { + tween.unit = unit; + tween.start = initialInUnit; + tween.end = adjusted; + } + } + return adjusted; +} + + +var defaultDisplayMap = {}; + +function getDefaultDisplay( elem ) { + var temp, + doc = elem.ownerDocument, + nodeName = elem.nodeName, + display = defaultDisplayMap[ nodeName ]; + + if ( display ) { + return display; + } + + temp = doc.body.appendChild( doc.createElement( nodeName ) ); + display = jQuery.css( temp, "display" ); + + temp.parentNode.removeChild( temp ); + + if ( display === "none" ) { + display = "block"; + } + defaultDisplayMap[ nodeName ] = display; + + return display; +} + +function showHide( elements, show ) { + var display, elem, + values = [], + index = 0, + length = elements.length; + + // Determine new display value for elements that need to change + for ( ; index < length; index++ ) { + elem = elements[ index ]; + if ( !elem.style ) { + continue; + } + + display = elem.style.display; + if ( show ) { + + // Since we force visibility upon cascade-hidden elements, an immediate (and slow) + // check is required in this first loop unless we have a nonempty display value (either + // inline or about-to-be-restored) + if ( display === "none" ) { + values[ index ] = dataPriv.get( elem, "display" ) || null; + if ( !values[ index ] ) { + elem.style.display = ""; + } + } + if ( elem.style.display === "" && isHiddenWithinTree( elem ) ) { + values[ index ] = getDefaultDisplay( elem ); + } + } else { + if ( display !== "none" ) { + values[ index ] = "none"; + + // Remember what we're overwriting + dataPriv.set( elem, "display", display ); + } + } + } + + // Set the display of the elements in a second loop to avoid constant reflow + for ( index = 0; index < length; index++ ) { + if ( values[ index ] != null ) { + elements[ index ].style.display = values[ index ]; + } + } + + return elements; +} + +jQuery.fn.extend( { + show: function() { + return showHide( this, true ); + }, + hide: function() { + return showHide( this ); + }, + toggle: function( state ) { + if ( typeof state === "boolean" ) { + return state ? this.show() : this.hide(); + } + + return this.each( function() { + if ( isHiddenWithinTree( this ) ) { + jQuery( this ).show(); + } else { + jQuery( this ).hide(); + } + } ); + } +} ); +var rcheckableType = ( /^(?:checkbox|radio)$/i ); + +var rtagName = ( /<([a-z][^\/\0>\x20\t\r\n\f]*)/i ); + +var rscriptType = ( /^$|^module$|\/(?:java|ecma)script/i ); + + + +( function() { + var fragment = document.createDocumentFragment(), + div = fragment.appendChild( document.createElement( "div" ) ), + input = document.createElement( "input" ); + + // Support: Android 4.0 - 4.3 only + // Check state lost if the name is set (#11217) + // Support: Windows Web Apps (WWA) + // `name` and `type` must use .setAttribute for WWA (#14901) + input.setAttribute( "type", "radio" ); + input.setAttribute( "checked", "checked" ); + input.setAttribute( "name", "t" ); + + div.appendChild( input ); + + // Support: Android <=4.1 only + // Older WebKit doesn't clone checked state correctly in fragments + support.checkClone = div.cloneNode( true ).cloneNode( true ).lastChild.checked; + + // Support: IE <=11 only + // Make sure textarea (and checkbox) defaultValue is properly cloned + div.innerHTML = ""; + support.noCloneChecked = !!div.cloneNode( true ).lastChild.defaultValue; + + // Support: IE <=9 only + // IE <=9 replaces "; + support.option = !!div.lastChild; +} )(); + + +// We have to close these tags to support XHTML (#13200) +var wrapMap = { + + // XHTML parsers do not magically insert elements in the + // same way that tag soup parsers do. So we cannot shorten + // this by omitting or other required elements. + thead: [ 1, "", "
" ], + col: [ 2, "", "
" ], + tr: [ 2, "", "
" ], + td: [ 3, "", "
" ], + + _default: [ 0, "", "" ] +}; + +wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; +wrapMap.th = wrapMap.td; + +// Support: IE <=9 only +if ( !support.option ) { + wrapMap.optgroup = wrapMap.option = [ 1, "" ]; +} + + +function getAll( context, tag ) { + + // Support: IE <=9 - 11 only + // Use typeof to avoid zero-argument method invocation on host objects (#15151) + var ret; + + if ( typeof context.getElementsByTagName !== "undefined" ) { + ret = context.getElementsByTagName( tag || "*" ); + + } else if ( typeof context.querySelectorAll !== "undefined" ) { + ret = context.querySelectorAll( tag || "*" ); + + } else { + ret = []; + } + + if ( tag === undefined || tag && nodeName( context, tag ) ) { + return jQuery.merge( [ context ], ret ); + } + + return ret; +} + + +// Mark scripts as having already been evaluated +function setGlobalEval( elems, refElements ) { + var i = 0, + l = elems.length; + + for ( ; i < l; i++ ) { + dataPriv.set( + elems[ i ], + "globalEval", + !refElements || dataPriv.get( refElements[ i ], "globalEval" ) + ); + } +} + + +var rhtml = /<|&#?\w+;/; + +function buildFragment( elems, context, scripts, selection, ignored ) { + var elem, tmp, tag, wrap, attached, j, + fragment = context.createDocumentFragment(), + nodes = [], + i = 0, + l = elems.length; + + for ( ; i < l; i++ ) { + elem = elems[ i ]; + + if ( elem || elem === 0 ) { + + // Add nodes directly + if ( toType( elem ) === "object" ) { + + // Support: Android <=4.0 only, PhantomJS 1 only + // push.apply(_, arraylike) throws on ancient WebKit + jQuery.merge( nodes, elem.nodeType ? [ elem ] : elem ); + + // Convert non-html into a text node + } else if ( !rhtml.test( elem ) ) { + nodes.push( context.createTextNode( elem ) ); + + // Convert html into DOM nodes + } else { + tmp = tmp || fragment.appendChild( context.createElement( "div" ) ); + + // Deserialize a standard representation + tag = ( rtagName.exec( elem ) || [ "", "" ] )[ 1 ].toLowerCase(); + wrap = wrapMap[ tag ] || wrapMap._default; + tmp.innerHTML = wrap[ 1 ] + jQuery.htmlPrefilter( elem ) + wrap[ 2 ]; + + // Descend through wrappers to the right content + j = wrap[ 0 ]; + while ( j-- ) { + tmp = tmp.lastChild; + } + + // Support: Android <=4.0 only, PhantomJS 1 only + // push.apply(_, arraylike) throws on ancient WebKit + jQuery.merge( nodes, tmp.childNodes ); + + // Remember the top-level container + tmp = fragment.firstChild; + + // Ensure the created nodes are orphaned (#12392) + tmp.textContent = ""; + } + } + } + + // Remove wrapper from fragment + fragment.textContent = ""; + + i = 0; + while ( ( elem = nodes[ i++ ] ) ) { + + // Skip elements already in the context collection (trac-4087) + if ( selection && jQuery.inArray( elem, selection ) > -1 ) { + if ( ignored ) { + ignored.push( elem ); + } + continue; + } + + attached = isAttached( elem ); + + // Append to fragment + tmp = getAll( fragment.appendChild( elem ), "script" ); + + // Preserve script evaluation history + if ( attached ) { + setGlobalEval( tmp ); + } + + // Capture executables + if ( scripts ) { + j = 0; + while ( ( elem = tmp[ j++ ] ) ) { + if ( rscriptType.test( elem.type || "" ) ) { + scripts.push( elem ); + } + } + } + } + + return fragment; +} + + +var + rkeyEvent = /^key/, + rmouseEvent = /^(?:mouse|pointer|contextmenu|drag|drop)|click/, + rtypenamespace = /^([^.]*)(?:\.(.+)|)/; + +function returnTrue() { + return true; +} + +function returnFalse() { + return false; +} + +// Support: IE <=9 - 11+ +// focus() and blur() are asynchronous, except when they are no-op. +// So expect focus to be synchronous when the element is already active, +// and blur to be synchronous when the element is not already active. +// (focus and blur are always synchronous in other supported browsers, +// this just defines when we can count on it). +function expectSync( elem, type ) { + return ( elem === safeActiveElement() ) === ( type === "focus" ); +} + +// Support: IE <=9 only +// Accessing document.activeElement can throw unexpectedly +// https://bugs.jquery.com/ticket/13393 +function safeActiveElement() { + try { + return document.activeElement; + } catch ( err ) { } +} + +function on( elem, types, selector, data, fn, one ) { + var origFn, type; + + // Types can be a map of types/handlers + if ( typeof types === "object" ) { + + // ( types-Object, selector, data ) + if ( typeof selector !== "string" ) { + + // ( types-Object, data ) + data = data || selector; + selector = undefined; + } + for ( type in types ) { + on( elem, type, selector, data, types[ type ], one ); + } + return elem; + } + + if ( data == null && fn == null ) { + + // ( types, fn ) + fn = selector; + data = selector = undefined; + } else if ( fn == null ) { + if ( typeof selector === "string" ) { + + // ( types, selector, fn ) + fn = data; + data = undefined; + } else { + + // ( types, data, fn ) + fn = data; + data = selector; + selector = undefined; + } + } + if ( fn === false ) { + fn = returnFalse; + } else if ( !fn ) { + return elem; + } + + if ( one === 1 ) { + origFn = fn; + fn = function( event ) { + + // Can use an empty set, since event contains the info + jQuery().off( event ); + return origFn.apply( this, arguments ); + }; + + // Use same guid so caller can remove using origFn + fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ ); + } + return elem.each( function() { + jQuery.event.add( this, types, fn, data, selector ); + } ); +} + +/* + * Helper functions for managing events -- not part of the public interface. + * Props to Dean Edwards' addEvent library for many of the ideas. + */ +jQuery.event = { + + global: {}, + + add: function( elem, types, handler, data, selector ) { + + var handleObjIn, eventHandle, tmp, + events, t, handleObj, + special, handlers, type, namespaces, origType, + elemData = dataPriv.get( elem ); + + // Only attach events to objects that accept data + if ( !acceptData( elem ) ) { + return; + } + + // Caller can pass in an object of custom data in lieu of the handler + if ( handler.handler ) { + handleObjIn = handler; + handler = handleObjIn.handler; + selector = handleObjIn.selector; + } + + // Ensure that invalid selectors throw exceptions at attach time + // Evaluate against documentElement in case elem is a non-element node (e.g., document) + if ( selector ) { + jQuery.find.matchesSelector( documentElement, selector ); + } + + // Make sure that the handler has a unique ID, used to find/remove it later + if ( !handler.guid ) { + handler.guid = jQuery.guid++; + } + + // Init the element's event structure and main handler, if this is the first + if ( !( events = elemData.events ) ) { + events = elemData.events = Object.create( null ); + } + if ( !( eventHandle = elemData.handle ) ) { + eventHandle = elemData.handle = function( e ) { + + // Discard the second event of a jQuery.event.trigger() and + // when an event is called after a page has unloaded + return typeof jQuery !== "undefined" && jQuery.event.triggered !== e.type ? + jQuery.event.dispatch.apply( elem, arguments ) : undefined; + }; + } + + // Handle multiple events separated by a space + types = ( types || "" ).match( rnothtmlwhite ) || [ "" ]; + t = types.length; + while ( t-- ) { + tmp = rtypenamespace.exec( types[ t ] ) || []; + type = origType = tmp[ 1 ]; + namespaces = ( tmp[ 2 ] || "" ).split( "." ).sort(); + + // There *must* be a type, no attaching namespace-only handlers + if ( !type ) { + continue; + } + + // If event changes its type, use the special event handlers for the changed type + special = jQuery.event.special[ type ] || {}; + + // If selector defined, determine special event api type, otherwise given type + type = ( selector ? special.delegateType : special.bindType ) || type; + + // Update special based on newly reset type + special = jQuery.event.special[ type ] || {}; + + // handleObj is passed to all event handlers + handleObj = jQuery.extend( { + type: type, + origType: origType, + data: data, + handler: handler, + guid: handler.guid, + selector: selector, + needsContext: selector && jQuery.expr.match.needsContext.test( selector ), + namespace: namespaces.join( "." ) + }, handleObjIn ); + + // Init the event handler queue if we're the first + if ( !( handlers = events[ type ] ) ) { + handlers = events[ type ] = []; + handlers.delegateCount = 0; + + // Only use addEventListener if the special events handler returns false + if ( !special.setup || + special.setup.call( elem, data, namespaces, eventHandle ) === false ) { + + if ( elem.addEventListener ) { + elem.addEventListener( type, eventHandle ); + } + } + } + + if ( special.add ) { + special.add.call( elem, handleObj ); + + if ( !handleObj.handler.guid ) { + handleObj.handler.guid = handler.guid; + } + } + + // Add to the element's handler list, delegates in front + if ( selector ) { + handlers.splice( handlers.delegateCount++, 0, handleObj ); + } else { + handlers.push( handleObj ); + } + + // Keep track of which events have ever been used, for event optimization + jQuery.event.global[ type ] = true; + } + + }, + + // Detach an event or set of events from an element + remove: function( elem, types, handler, selector, mappedTypes ) { + + var j, origCount, tmp, + events, t, handleObj, + special, handlers, type, namespaces, origType, + elemData = dataPriv.hasData( elem ) && dataPriv.get( elem ); + + if ( !elemData || !( events = elemData.events ) ) { + return; + } + + // Once for each type.namespace in types; type may be omitted + types = ( types || "" ).match( rnothtmlwhite ) || [ "" ]; + t = types.length; + while ( t-- ) { + tmp = rtypenamespace.exec( types[ t ] ) || []; + type = origType = tmp[ 1 ]; + namespaces = ( tmp[ 2 ] || "" ).split( "." ).sort(); + + // Unbind all events (on this namespace, if provided) for the element + if ( !type ) { + for ( type in events ) { + jQuery.event.remove( elem, type + types[ t ], handler, selector, true ); + } + continue; + } + + special = jQuery.event.special[ type ] || {}; + type = ( selector ? special.delegateType : special.bindType ) || type; + handlers = events[ type ] || []; + tmp = tmp[ 2 ] && + new RegExp( "(^|\\.)" + namespaces.join( "\\.(?:.*\\.|)" ) + "(\\.|$)" ); + + // Remove matching events + origCount = j = handlers.length; + while ( j-- ) { + handleObj = handlers[ j ]; + + if ( ( mappedTypes || origType === handleObj.origType ) && + ( !handler || handler.guid === handleObj.guid ) && + ( !tmp || tmp.test( handleObj.namespace ) ) && + ( !selector || selector === handleObj.selector || + selector === "**" && handleObj.selector ) ) { + handlers.splice( j, 1 ); + + if ( handleObj.selector ) { + handlers.delegateCount--; + } + if ( special.remove ) { + special.remove.call( elem, handleObj ); + } + } + } + + // Remove generic event handler if we removed something and no more handlers exist + // (avoids potential for endless recursion during removal of special event handlers) + if ( origCount && !handlers.length ) { + if ( !special.teardown || + special.teardown.call( elem, namespaces, elemData.handle ) === false ) { + + jQuery.removeEvent( elem, type, elemData.handle ); + } + + delete events[ type ]; + } + } + + // Remove data and the expando if it's no longer used + if ( jQuery.isEmptyObject( events ) ) { + dataPriv.remove( elem, "handle events" ); + } + }, + + dispatch: function( nativeEvent ) { + + var i, j, ret, matched, handleObj, handlerQueue, + args = new Array( arguments.length ), + + // Make a writable jQuery.Event from the native event object + event = jQuery.event.fix( nativeEvent ), + + handlers = ( + dataPriv.get( this, "events" ) || Object.create( null ) + )[ event.type ] || [], + special = jQuery.event.special[ event.type ] || {}; + + // Use the fix-ed jQuery.Event rather than the (read-only) native event + args[ 0 ] = event; + + for ( i = 1; i < arguments.length; i++ ) { + args[ i ] = arguments[ i ]; + } + + event.delegateTarget = this; + + // Call the preDispatch hook for the mapped type, and let it bail if desired + if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) { + return; + } + + // Determine handlers + handlerQueue = jQuery.event.handlers.call( this, event, handlers ); + + // Run delegates first; they may want to stop propagation beneath us + i = 0; + while ( ( matched = handlerQueue[ i++ ] ) && !event.isPropagationStopped() ) { + event.currentTarget = matched.elem; + + j = 0; + while ( ( handleObj = matched.handlers[ j++ ] ) && + !event.isImmediatePropagationStopped() ) { + + // If the event is namespaced, then each handler is only invoked if it is + // specially universal or its namespaces are a superset of the event's. + if ( !event.rnamespace || handleObj.namespace === false || + event.rnamespace.test( handleObj.namespace ) ) { + + event.handleObj = handleObj; + event.data = handleObj.data; + + ret = ( ( jQuery.event.special[ handleObj.origType ] || {} ).handle || + handleObj.handler ).apply( matched.elem, args ); + + if ( ret !== undefined ) { + if ( ( event.result = ret ) === false ) { + event.preventDefault(); + event.stopPropagation(); + } + } + } + } + } + + // Call the postDispatch hook for the mapped type + if ( special.postDispatch ) { + special.postDispatch.call( this, event ); + } + + return event.result; + }, + + handlers: function( event, handlers ) { + var i, handleObj, sel, matchedHandlers, matchedSelectors, + handlerQueue = [], + delegateCount = handlers.delegateCount, + cur = event.target; + + // Find delegate handlers + if ( delegateCount && + + // Support: IE <=9 + // Black-hole SVG instance trees (trac-13180) + cur.nodeType && + + // Support: Firefox <=42 + // Suppress spec-violating clicks indicating a non-primary pointer button (trac-3861) + // https://www.w3.org/TR/DOM-Level-3-Events/#event-type-click + // Support: IE 11 only + // ...but not arrow key "clicks" of radio inputs, which can have `button` -1 (gh-2343) + !( event.type === "click" && event.button >= 1 ) ) { + + for ( ; cur !== this; cur = cur.parentNode || this ) { + + // Don't check non-elements (#13208) + // Don't process clicks on disabled elements (#6911, #8165, #11382, #11764) + if ( cur.nodeType === 1 && !( event.type === "click" && cur.disabled === true ) ) { + matchedHandlers = []; + matchedSelectors = {}; + for ( i = 0; i < delegateCount; i++ ) { + handleObj = handlers[ i ]; + + // Don't conflict with Object.prototype properties (#13203) + sel = handleObj.selector + " "; + + if ( matchedSelectors[ sel ] === undefined ) { + matchedSelectors[ sel ] = handleObj.needsContext ? + jQuery( sel, this ).index( cur ) > -1 : + jQuery.find( sel, this, null, [ cur ] ).length; + } + if ( matchedSelectors[ sel ] ) { + matchedHandlers.push( handleObj ); + } + } + if ( matchedHandlers.length ) { + handlerQueue.push( { elem: cur, handlers: matchedHandlers } ); + } + } + } + } + + // Add the remaining (directly-bound) handlers + cur = this; + if ( delegateCount < handlers.length ) { + handlerQueue.push( { elem: cur, handlers: handlers.slice( delegateCount ) } ); + } + + return handlerQueue; + }, + + addProp: function( name, hook ) { + Object.defineProperty( jQuery.Event.prototype, name, { + enumerable: true, + configurable: true, + + get: isFunction( hook ) ? + function() { + if ( this.originalEvent ) { + return hook( this.originalEvent ); + } + } : + function() { + if ( this.originalEvent ) { + return this.originalEvent[ name ]; + } + }, + + set: function( value ) { + Object.defineProperty( this, name, { + enumerable: true, + configurable: true, + writable: true, + value: value + } ); + } + } ); + }, + + fix: function( originalEvent ) { + return originalEvent[ jQuery.expando ] ? + originalEvent : + new jQuery.Event( originalEvent ); + }, + + special: { + load: { + + // Prevent triggered image.load events from bubbling to window.load + noBubble: true + }, + click: { + + // Utilize native event to ensure correct state for checkable inputs + setup: function( data ) { + + // For mutual compressibility with _default, replace `this` access with a local var. + // `|| data` is dead code meant only to preserve the variable through minification. + var el = this || data; + + // Claim the first handler + if ( rcheckableType.test( el.type ) && + el.click && nodeName( el, "input" ) ) { + + // dataPriv.set( el, "click", ... ) + leverageNative( el, "click", returnTrue ); + } + + // Return false to allow normal processing in the caller + return false; + }, + trigger: function( data ) { + + // For mutual compressibility with _default, replace `this` access with a local var. + // `|| data` is dead code meant only to preserve the variable through minification. + var el = this || data; + + // Force setup before triggering a click + if ( rcheckableType.test( el.type ) && + el.click && nodeName( el, "input" ) ) { + + leverageNative( el, "click" ); + } + + // Return non-false to allow normal event-path propagation + return true; + }, + + // For cross-browser consistency, suppress native .click() on links + // Also prevent it if we're currently inside a leveraged native-event stack + _default: function( event ) { + var target = event.target; + return rcheckableType.test( target.type ) && + target.click && nodeName( target, "input" ) && + dataPriv.get( target, "click" ) || + nodeName( target, "a" ); + } + }, + + beforeunload: { + postDispatch: function( event ) { + + // Support: Firefox 20+ + // Firefox doesn't alert if the returnValue field is not set. + if ( event.result !== undefined && event.originalEvent ) { + event.originalEvent.returnValue = event.result; + } + } + } + } +}; + +// Ensure the presence of an event listener that handles manually-triggered +// synthetic events by interrupting progress until reinvoked in response to +// *native* events that it fires directly, ensuring that state changes have +// already occurred before other listeners are invoked. +function leverageNative( el, type, expectSync ) { + + // Missing expectSync indicates a trigger call, which must force setup through jQuery.event.add + if ( !expectSync ) { + if ( dataPriv.get( el, type ) === undefined ) { + jQuery.event.add( el, type, returnTrue ); + } + return; + } + + // Register the controller as a special universal handler for all event namespaces + dataPriv.set( el, type, false ); + jQuery.event.add( el, type, { + namespace: false, + handler: function( event ) { + var notAsync, result, + saved = dataPriv.get( this, type ); + + if ( ( event.isTrigger & 1 ) && this[ type ] ) { + + // Interrupt processing of the outer synthetic .trigger()ed event + // Saved data should be false in such cases, but might be a leftover capture object + // from an async native handler (gh-4350) + if ( !saved.length ) { + + // Store arguments for use when handling the inner native event + // There will always be at least one argument (an event object), so this array + // will not be confused with a leftover capture object. + saved = slice.call( arguments ); + dataPriv.set( this, type, saved ); + + // Trigger the native event and capture its result + // Support: IE <=9 - 11+ + // focus() and blur() are asynchronous + notAsync = expectSync( this, type ); + this[ type ](); + result = dataPriv.get( this, type ); + if ( saved !== result || notAsync ) { + dataPriv.set( this, type, false ); + } else { + result = {}; + } + if ( saved !== result ) { + + // Cancel the outer synthetic event + event.stopImmediatePropagation(); + event.preventDefault(); + return result.value; + } + + // If this is an inner synthetic event for an event with a bubbling surrogate + // (focus or blur), assume that the surrogate already propagated from triggering the + // native event and prevent that from happening again here. + // This technically gets the ordering wrong w.r.t. to `.trigger()` (in which the + // bubbling surrogate propagates *after* the non-bubbling base), but that seems + // less bad than duplication. + } else if ( ( jQuery.event.special[ type ] || {} ).delegateType ) { + event.stopPropagation(); + } + + // If this is a native event triggered above, everything is now in order + // Fire an inner synthetic event with the original arguments + } else if ( saved.length ) { + + // ...and capture the result + dataPriv.set( this, type, { + value: jQuery.event.trigger( + + // Support: IE <=9 - 11+ + // Extend with the prototype to reset the above stopImmediatePropagation() + jQuery.extend( saved[ 0 ], jQuery.Event.prototype ), + saved.slice( 1 ), + this + ) + } ); + + // Abort handling of the native event + event.stopImmediatePropagation(); + } + } + } ); +} + +jQuery.removeEvent = function( elem, type, handle ) { + + // This "if" is needed for plain objects + if ( elem.removeEventListener ) { + elem.removeEventListener( type, handle ); + } +}; + +jQuery.Event = function( src, props ) { + + // Allow instantiation without the 'new' keyword + if ( !( this instanceof jQuery.Event ) ) { + return new jQuery.Event( src, props ); + } + + // Event object + if ( src && src.type ) { + this.originalEvent = src; + this.type = src.type; + + // Events bubbling up the document may have been marked as prevented + // by a handler lower down the tree; reflect the correct value. + this.isDefaultPrevented = src.defaultPrevented || + src.defaultPrevented === undefined && + + // Support: Android <=2.3 only + src.returnValue === false ? + returnTrue : + returnFalse; + + // Create target properties + // Support: Safari <=6 - 7 only + // Target should not be a text node (#504, #13143) + this.target = ( src.target && src.target.nodeType === 3 ) ? + src.target.parentNode : + src.target; + + this.currentTarget = src.currentTarget; + this.relatedTarget = src.relatedTarget; + + // Event type + } else { + this.type = src; + } + + // Put explicitly provided properties onto the event object + if ( props ) { + jQuery.extend( this, props ); + } + + // Create a timestamp if incoming event doesn't have one + this.timeStamp = src && src.timeStamp || Date.now(); + + // Mark it as fixed + this[ jQuery.expando ] = true; +}; + +// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding +// https://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html +jQuery.Event.prototype = { + constructor: jQuery.Event, + isDefaultPrevented: returnFalse, + isPropagationStopped: returnFalse, + isImmediatePropagationStopped: returnFalse, + isSimulated: false, + + preventDefault: function() { + var e = this.originalEvent; + + this.isDefaultPrevented = returnTrue; + + if ( e && !this.isSimulated ) { + e.preventDefault(); + } + }, + stopPropagation: function() { + var e = this.originalEvent; + + this.isPropagationStopped = returnTrue; + + if ( e && !this.isSimulated ) { + e.stopPropagation(); + } + }, + stopImmediatePropagation: function() { + var e = this.originalEvent; + + this.isImmediatePropagationStopped = returnTrue; + + if ( e && !this.isSimulated ) { + e.stopImmediatePropagation(); + } + + this.stopPropagation(); + } +}; + +// Includes all common event props including KeyEvent and MouseEvent specific props +jQuery.each( { + altKey: true, + bubbles: true, + cancelable: true, + changedTouches: true, + ctrlKey: true, + detail: true, + eventPhase: true, + metaKey: true, + pageX: true, + pageY: true, + shiftKey: true, + view: true, + "char": true, + code: true, + charCode: true, + key: true, + keyCode: true, + button: true, + buttons: true, + clientX: true, + clientY: true, + offsetX: true, + offsetY: true, + pointerId: true, + pointerType: true, + screenX: true, + screenY: true, + targetTouches: true, + toElement: true, + touches: true, + + which: function( event ) { + var button = event.button; + + // Add which for key events + if ( event.which == null && rkeyEvent.test( event.type ) ) { + return event.charCode != null ? event.charCode : event.keyCode; + } + + // Add which for click: 1 === left; 2 === middle; 3 === right + if ( !event.which && button !== undefined && rmouseEvent.test( event.type ) ) { + if ( button & 1 ) { + return 1; + } + + if ( button & 2 ) { + return 3; + } + + if ( button & 4 ) { + return 2; + } + + return 0; + } + + return event.which; + } +}, jQuery.event.addProp ); + +jQuery.each( { focus: "focusin", blur: "focusout" }, function( type, delegateType ) { + jQuery.event.special[ type ] = { + + // Utilize native event if possible so blur/focus sequence is correct + setup: function() { + + // Claim the first handler + // dataPriv.set( this, "focus", ... ) + // dataPriv.set( this, "blur", ... ) + leverageNative( this, type, expectSync ); + + // Return false to allow normal processing in the caller + return false; + }, + trigger: function() { + + // Force setup before trigger + leverageNative( this, type ); + + // Return non-false to allow normal event-path propagation + return true; + }, + + delegateType: delegateType + }; +} ); + +// Create mouseenter/leave events using mouseover/out and event-time checks +// so that event delegation works in jQuery. +// Do the same for pointerenter/pointerleave and pointerover/pointerout +// +// Support: Safari 7 only +// Safari sends mouseenter too often; see: +// https://bugs.chromium.org/p/chromium/issues/detail?id=470258 +// for the description of the bug (it existed in older Chrome versions as well). +jQuery.each( { + mouseenter: "mouseover", + mouseleave: "mouseout", + pointerenter: "pointerover", + pointerleave: "pointerout" +}, function( orig, fix ) { + jQuery.event.special[ orig ] = { + delegateType: fix, + bindType: fix, + + handle: function( event ) { + var ret, + target = this, + related = event.relatedTarget, + handleObj = event.handleObj; + + // For mouseenter/leave call the handler if related is outside the target. + // NB: No relatedTarget if the mouse left/entered the browser window + if ( !related || ( related !== target && !jQuery.contains( target, related ) ) ) { + event.type = handleObj.origType; + ret = handleObj.handler.apply( this, arguments ); + event.type = fix; + } + return ret; + } + }; +} ); + +jQuery.fn.extend( { + + on: function( types, selector, data, fn ) { + return on( this, types, selector, data, fn ); + }, + one: function( types, selector, data, fn ) { + return on( this, types, selector, data, fn, 1 ); + }, + off: function( types, selector, fn ) { + var handleObj, type; + if ( types && types.preventDefault && types.handleObj ) { + + // ( event ) dispatched jQuery.Event + handleObj = types.handleObj; + jQuery( types.delegateTarget ).off( + handleObj.namespace ? + handleObj.origType + "." + handleObj.namespace : + handleObj.origType, + handleObj.selector, + handleObj.handler + ); + return this; + } + if ( typeof types === "object" ) { + + // ( types-object [, selector] ) + for ( type in types ) { + this.off( type, selector, types[ type ] ); + } + return this; + } + if ( selector === false || typeof selector === "function" ) { + + // ( types [, fn] ) + fn = selector; + selector = undefined; + } + if ( fn === false ) { + fn = returnFalse; + } + return this.each( function() { + jQuery.event.remove( this, types, fn, selector ); + } ); + } +} ); + + +var + + // Support: IE <=10 - 11, Edge 12 - 13 only + // In IE/Edge using regex groups here causes severe slowdowns. + // See https://connect.microsoft.com/IE/feedback/details/1736512/ + rnoInnerhtml = /\s*$/g; + +// Prefer a tbody over its parent table for containing new rows +function manipulationTarget( elem, content ) { + if ( nodeName( elem, "table" ) && + nodeName( content.nodeType !== 11 ? content : content.firstChild, "tr" ) ) { + + return jQuery( elem ).children( "tbody" )[ 0 ] || elem; + } + + return elem; +} + +// Replace/restore the type attribute of script elements for safe DOM manipulation +function disableScript( elem ) { + elem.type = ( elem.getAttribute( "type" ) !== null ) + "/" + elem.type; + return elem; +} +function restoreScript( elem ) { + if ( ( elem.type || "" ).slice( 0, 5 ) === "true/" ) { + elem.type = elem.type.slice( 5 ); + } else { + elem.removeAttribute( "type" ); + } + + return elem; +} + +function cloneCopyEvent( src, dest ) { + var i, l, type, pdataOld, udataOld, udataCur, events; + + if ( dest.nodeType !== 1 ) { + return; + } + + // 1. Copy private data: events, handlers, etc. + if ( dataPriv.hasData( src ) ) { + pdataOld = dataPriv.get( src ); + events = pdataOld.events; + + if ( events ) { + dataPriv.remove( dest, "handle events" ); + + for ( type in events ) { + for ( i = 0, l = events[ type ].length; i < l; i++ ) { + jQuery.event.add( dest, type, events[ type ][ i ] ); + } + } + } + } + + // 2. Copy user data + if ( dataUser.hasData( src ) ) { + udataOld = dataUser.access( src ); + udataCur = jQuery.extend( {}, udataOld ); + + dataUser.set( dest, udataCur ); + } +} + +// Fix IE bugs, see support tests +function fixInput( src, dest ) { + var nodeName = dest.nodeName.toLowerCase(); + + // Fails to persist the checked state of a cloned checkbox or radio button. + if ( nodeName === "input" && rcheckableType.test( src.type ) ) { + dest.checked = src.checked; + + // Fails to return the selected option to the default selected state when cloning options + } else if ( nodeName === "input" || nodeName === "textarea" ) { + dest.defaultValue = src.defaultValue; + } +} + +function domManip( collection, args, callback, ignored ) { + + // Flatten any nested arrays + args = flat( args ); + + var fragment, first, scripts, hasScripts, node, doc, + i = 0, + l = collection.length, + iNoClone = l - 1, + value = args[ 0 ], + valueIsFunction = isFunction( value ); + + // We can't cloneNode fragments that contain checked, in WebKit + if ( valueIsFunction || + ( l > 1 && typeof value === "string" && + !support.checkClone && rchecked.test( value ) ) ) { + return collection.each( function( index ) { + var self = collection.eq( index ); + if ( valueIsFunction ) { + args[ 0 ] = value.call( this, index, self.html() ); + } + domManip( self, args, callback, ignored ); + } ); + } + + if ( l ) { + fragment = buildFragment( args, collection[ 0 ].ownerDocument, false, collection, ignored ); + first = fragment.firstChild; + + if ( fragment.childNodes.length === 1 ) { + fragment = first; + } + + // Require either new content or an interest in ignored elements to invoke the callback + if ( first || ignored ) { + scripts = jQuery.map( getAll( fragment, "script" ), disableScript ); + hasScripts = scripts.length; + + // Use the original fragment for the last item + // instead of the first because it can end up + // being emptied incorrectly in certain situations (#8070). + for ( ; i < l; i++ ) { + node = fragment; + + if ( i !== iNoClone ) { + node = jQuery.clone( node, true, true ); + + // Keep references to cloned scripts for later restoration + if ( hasScripts ) { + + // Support: Android <=4.0 only, PhantomJS 1 only + // push.apply(_, arraylike) throws on ancient WebKit + jQuery.merge( scripts, getAll( node, "script" ) ); + } + } + + callback.call( collection[ i ], node, i ); + } + + if ( hasScripts ) { + doc = scripts[ scripts.length - 1 ].ownerDocument; + + // Reenable scripts + jQuery.map( scripts, restoreScript ); + + // Evaluate executable scripts on first document insertion + for ( i = 0; i < hasScripts; i++ ) { + node = scripts[ i ]; + if ( rscriptType.test( node.type || "" ) && + !dataPriv.access( node, "globalEval" ) && + jQuery.contains( doc, node ) ) { + + if ( node.src && ( node.type || "" ).toLowerCase() !== "module" ) { + + // Optional AJAX dependency, but won't run scripts if not present + if ( jQuery._evalUrl && !node.noModule ) { + jQuery._evalUrl( node.src, { + nonce: node.nonce || node.getAttribute( "nonce" ) + }, doc ); + } + } else { + DOMEval( node.textContent.replace( rcleanScript, "" ), node, doc ); + } + } + } + } + } + } + + return collection; +} + +function remove( elem, selector, keepData ) { + var node, + nodes = selector ? jQuery.filter( selector, elem ) : elem, + i = 0; + + for ( ; ( node = nodes[ i ] ) != null; i++ ) { + if ( !keepData && node.nodeType === 1 ) { + jQuery.cleanData( getAll( node ) ); + } + + if ( node.parentNode ) { + if ( keepData && isAttached( node ) ) { + setGlobalEval( getAll( node, "script" ) ); + } + node.parentNode.removeChild( node ); + } + } + + return elem; +} + +jQuery.extend( { + htmlPrefilter: function( html ) { + return html; + }, + + clone: function( elem, dataAndEvents, deepDataAndEvents ) { + var i, l, srcElements, destElements, + clone = elem.cloneNode( true ), + inPage = isAttached( elem ); + + // Fix IE cloning issues + if ( !support.noCloneChecked && ( elem.nodeType === 1 || elem.nodeType === 11 ) && + !jQuery.isXMLDoc( elem ) ) { + + // We eschew Sizzle here for performance reasons: https://jsperf.com/getall-vs-sizzle/2 + destElements = getAll( clone ); + srcElements = getAll( elem ); + + for ( i = 0, l = srcElements.length; i < l; i++ ) { + fixInput( srcElements[ i ], destElements[ i ] ); + } + } + + // Copy the events from the original to the clone + if ( dataAndEvents ) { + if ( deepDataAndEvents ) { + srcElements = srcElements || getAll( elem ); + destElements = destElements || getAll( clone ); + + for ( i = 0, l = srcElements.length; i < l; i++ ) { + cloneCopyEvent( srcElements[ i ], destElements[ i ] ); + } + } else { + cloneCopyEvent( elem, clone ); + } + } + + // Preserve script evaluation history + destElements = getAll( clone, "script" ); + if ( destElements.length > 0 ) { + setGlobalEval( destElements, !inPage && getAll( elem, "script" ) ); + } + + // Return the cloned set + return clone; + }, + + cleanData: function( elems ) { + var data, elem, type, + special = jQuery.event.special, + i = 0; + + for ( ; ( elem = elems[ i ] ) !== undefined; i++ ) { + if ( acceptData( elem ) ) { + if ( ( data = elem[ dataPriv.expando ] ) ) { + if ( data.events ) { + for ( type in data.events ) { + if ( special[ type ] ) { + jQuery.event.remove( elem, type ); + + // This is a shortcut to avoid jQuery.event.remove's overhead + } else { + jQuery.removeEvent( elem, type, data.handle ); + } + } + } + + // Support: Chrome <=35 - 45+ + // Assign undefined instead of using delete, see Data#remove + elem[ dataPriv.expando ] = undefined; + } + if ( elem[ dataUser.expando ] ) { + + // Support: Chrome <=35 - 45+ + // Assign undefined instead of using delete, see Data#remove + elem[ dataUser.expando ] = undefined; + } + } + } + } +} ); + +jQuery.fn.extend( { + detach: function( selector ) { + return remove( this, selector, true ); + }, + + remove: function( selector ) { + return remove( this, selector ); + }, + + text: function( value ) { + return access( this, function( value ) { + return value === undefined ? + jQuery.text( this ) : + this.empty().each( function() { + if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { + this.textContent = value; + } + } ); + }, null, value, arguments.length ); + }, + + append: function() { + return domManip( this, arguments, function( elem ) { + if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { + var target = manipulationTarget( this, elem ); + target.appendChild( elem ); + } + } ); + }, + + prepend: function() { + return domManip( this, arguments, function( elem ) { + if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { + var target = manipulationTarget( this, elem ); + target.insertBefore( elem, target.firstChild ); + } + } ); + }, + + before: function() { + return domManip( this, arguments, function( elem ) { + if ( this.parentNode ) { + this.parentNode.insertBefore( elem, this ); + } + } ); + }, + + after: function() { + return domManip( this, arguments, function( elem ) { + if ( this.parentNode ) { + this.parentNode.insertBefore( elem, this.nextSibling ); + } + } ); + }, + + empty: function() { + var elem, + i = 0; + + for ( ; ( elem = this[ i ] ) != null; i++ ) { + if ( elem.nodeType === 1 ) { + + // Prevent memory leaks + jQuery.cleanData( getAll( elem, false ) ); + + // Remove any remaining nodes + elem.textContent = ""; + } + } + + return this; + }, + + clone: function( dataAndEvents, deepDataAndEvents ) { + dataAndEvents = dataAndEvents == null ? false : dataAndEvents; + deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents; + + return this.map( function() { + return jQuery.clone( this, dataAndEvents, deepDataAndEvents ); + } ); + }, + + html: function( value ) { + return access( this, function( value ) { + var elem = this[ 0 ] || {}, + i = 0, + l = this.length; + + if ( value === undefined && elem.nodeType === 1 ) { + return elem.innerHTML; + } + + // See if we can take a shortcut and just use innerHTML + if ( typeof value === "string" && !rnoInnerhtml.test( value ) && + !wrapMap[ ( rtagName.exec( value ) || [ "", "" ] )[ 1 ].toLowerCase() ] ) { + + value = jQuery.htmlPrefilter( value ); + + try { + for ( ; i < l; i++ ) { + elem = this[ i ] || {}; + + // Remove element nodes and prevent memory leaks + if ( elem.nodeType === 1 ) { + jQuery.cleanData( getAll( elem, false ) ); + elem.innerHTML = value; + } + } + + elem = 0; + + // If using innerHTML throws an exception, use the fallback method + } catch ( e ) {} + } + + if ( elem ) { + this.empty().append( value ); + } + }, null, value, arguments.length ); + }, + + replaceWith: function() { + var ignored = []; + + // Make the changes, replacing each non-ignored context element with the new content + return domManip( this, arguments, function( elem ) { + var parent = this.parentNode; + + if ( jQuery.inArray( this, ignored ) < 0 ) { + jQuery.cleanData( getAll( this ) ); + if ( parent ) { + parent.replaceChild( elem, this ); + } + } + + // Force callback invocation + }, ignored ); + } +} ); + +jQuery.each( { + appendTo: "append", + prependTo: "prepend", + insertBefore: "before", + insertAfter: "after", + replaceAll: "replaceWith" +}, function( name, original ) { + jQuery.fn[ name ] = function( selector ) { + var elems, + ret = [], + insert = jQuery( selector ), + last = insert.length - 1, + i = 0; + + for ( ; i <= last; i++ ) { + elems = i === last ? this : this.clone( true ); + jQuery( insert[ i ] )[ original ]( elems ); + + // Support: Android <=4.0 only, PhantomJS 1 only + // .get() because push.apply(_, arraylike) throws on ancient WebKit + push.apply( ret, elems.get() ); + } + + return this.pushStack( ret ); + }; +} ); +var rnumnonpx = new RegExp( "^(" + pnum + ")(?!px)[a-z%]+$", "i" ); + +var getStyles = function( elem ) { + + // Support: IE <=11 only, Firefox <=30 (#15098, #14150) + // IE throws on elements created in popups + // FF meanwhile throws on frame elements through "defaultView.getComputedStyle" + var view = elem.ownerDocument.defaultView; + + if ( !view || !view.opener ) { + view = window; + } + + return view.getComputedStyle( elem ); + }; + +var swap = function( elem, options, callback ) { + var ret, name, + old = {}; + + // Remember the old values, and insert the new ones + for ( name in options ) { + old[ name ] = elem.style[ name ]; + elem.style[ name ] = options[ name ]; + } + + ret = callback.call( elem ); + + // Revert the old values + for ( name in options ) { + elem.style[ name ] = old[ name ]; + } + + return ret; +}; + + +var rboxStyle = new RegExp( cssExpand.join( "|" ), "i" ); + + + +( function() { + + // Executing both pixelPosition & boxSizingReliable tests require only one layout + // so they're executed at the same time to save the second computation. + function computeStyleTests() { + + // This is a singleton, we need to execute it only once + if ( !div ) { + return; + } + + container.style.cssText = "position:absolute;left:-11111px;width:60px;" + + "margin-top:1px;padding:0;border:0"; + div.style.cssText = + "position:relative;display:block;box-sizing:border-box;overflow:scroll;" + + "margin:auto;border:1px;padding:1px;" + + "width:60%;top:1%"; + documentElement.appendChild( container ).appendChild( div ); + + var divStyle = window.getComputedStyle( div ); + pixelPositionVal = divStyle.top !== "1%"; + + // Support: Android 4.0 - 4.3 only, Firefox <=3 - 44 + reliableMarginLeftVal = roundPixelMeasures( divStyle.marginLeft ) === 12; + + // Support: Android 4.0 - 4.3 only, Safari <=9.1 - 10.1, iOS <=7.0 - 9.3 + // Some styles come back with percentage values, even though they shouldn't + div.style.right = "60%"; + pixelBoxStylesVal = roundPixelMeasures( divStyle.right ) === 36; + + // Support: IE 9 - 11 only + // Detect misreporting of content dimensions for box-sizing:border-box elements + boxSizingReliableVal = roundPixelMeasures( divStyle.width ) === 36; + + // Support: IE 9 only + // Detect overflow:scroll screwiness (gh-3699) + // Support: Chrome <=64 + // Don't get tricked when zoom affects offsetWidth (gh-4029) + div.style.position = "absolute"; + scrollboxSizeVal = roundPixelMeasures( div.offsetWidth / 3 ) === 12; + + documentElement.removeChild( container ); + + // Nullify the div so it wouldn't be stored in the memory and + // it will also be a sign that checks already performed + div = null; + } + + function roundPixelMeasures( measure ) { + return Math.round( parseFloat( measure ) ); + } + + var pixelPositionVal, boxSizingReliableVal, scrollboxSizeVal, pixelBoxStylesVal, + reliableTrDimensionsVal, reliableMarginLeftVal, + container = document.createElement( "div" ), + div = document.createElement( "div" ); + + // Finish early in limited (non-browser) environments + if ( !div.style ) { + return; + } + + // Support: IE <=9 - 11 only + // Style of cloned element affects source element cloned (#8908) + div.style.backgroundClip = "content-box"; + div.cloneNode( true ).style.backgroundClip = ""; + support.clearCloneStyle = div.style.backgroundClip === "content-box"; + + jQuery.extend( support, { + boxSizingReliable: function() { + computeStyleTests(); + return boxSizingReliableVal; + }, + pixelBoxStyles: function() { + computeStyleTests(); + return pixelBoxStylesVal; + }, + pixelPosition: function() { + computeStyleTests(); + return pixelPositionVal; + }, + reliableMarginLeft: function() { + computeStyleTests(); + return reliableMarginLeftVal; + }, + scrollboxSize: function() { + computeStyleTests(); + return scrollboxSizeVal; + }, + + // Support: IE 9 - 11+, Edge 15 - 18+ + // IE/Edge misreport `getComputedStyle` of table rows with width/height + // set in CSS while `offset*` properties report correct values. + // Behavior in IE 9 is more subtle than in newer versions & it passes + // some versions of this test; make sure not to make it pass there! + reliableTrDimensions: function() { + var table, tr, trChild, trStyle; + if ( reliableTrDimensionsVal == null ) { + table = document.createElement( "table" ); + tr = document.createElement( "tr" ); + trChild = document.createElement( "div" ); + + table.style.cssText = "position:absolute;left:-11111px"; + tr.style.height = "1px"; + trChild.style.height = "9px"; + + documentElement + .appendChild( table ) + .appendChild( tr ) + .appendChild( trChild ); + + trStyle = window.getComputedStyle( tr ); + reliableTrDimensionsVal = parseInt( trStyle.height ) > 3; + + documentElement.removeChild( table ); + } + return reliableTrDimensionsVal; + } + } ); +} )(); + + +function curCSS( elem, name, computed ) { + var width, minWidth, maxWidth, ret, + + // Support: Firefox 51+ + // Retrieving style before computed somehow + // fixes an issue with getting wrong values + // on detached elements + style = elem.style; + + computed = computed || getStyles( elem ); + + // getPropertyValue is needed for: + // .css('filter') (IE 9 only, #12537) + // .css('--customProperty) (#3144) + if ( computed ) { + ret = computed.getPropertyValue( name ) || computed[ name ]; + + if ( ret === "" && !isAttached( elem ) ) { + ret = jQuery.style( elem, name ); + } + + // A tribute to the "awesome hack by Dean Edwards" + // Android Browser returns percentage for some values, + // but width seems to be reliably pixels. + // This is against the CSSOM draft spec: + // https://drafts.csswg.org/cssom/#resolved-values + if ( !support.pixelBoxStyles() && rnumnonpx.test( ret ) && rboxStyle.test( name ) ) { + + // Remember the original values + width = style.width; + minWidth = style.minWidth; + maxWidth = style.maxWidth; + + // Put in the new values to get a computed value out + style.minWidth = style.maxWidth = style.width = ret; + ret = computed.width; + + // Revert the changed values + style.width = width; + style.minWidth = minWidth; + style.maxWidth = maxWidth; + } + } + + return ret !== undefined ? + + // Support: IE <=9 - 11 only + // IE returns zIndex value as an integer. + ret + "" : + ret; +} + + +function addGetHookIf( conditionFn, hookFn ) { + + // Define the hook, we'll check on the first run if it's really needed. + return { + get: function() { + if ( conditionFn() ) { + + // Hook not needed (or it's not possible to use it due + // to missing dependency), remove it. + delete this.get; + return; + } + + // Hook needed; redefine it so that the support test is not executed again. + return ( this.get = hookFn ).apply( this, arguments ); + } + }; +} + + +var cssPrefixes = [ "Webkit", "Moz", "ms" ], + emptyStyle = document.createElement( "div" ).style, + vendorProps = {}; + +// Return a vendor-prefixed property or undefined +function vendorPropName( name ) { + + // Check for vendor prefixed names + var capName = name[ 0 ].toUpperCase() + name.slice( 1 ), + i = cssPrefixes.length; + + while ( i-- ) { + name = cssPrefixes[ i ] + capName; + if ( name in emptyStyle ) { + return name; + } + } +} + +// Return a potentially-mapped jQuery.cssProps or vendor prefixed property +function finalPropName( name ) { + var final = jQuery.cssProps[ name ] || vendorProps[ name ]; + + if ( final ) { + return final; + } + if ( name in emptyStyle ) { + return name; + } + return vendorProps[ name ] = vendorPropName( name ) || name; +} + + +var + + // Swappable if display is none or starts with table + // except "table", "table-cell", or "table-caption" + // See here for display values: https://developer.mozilla.org/en-US/docs/CSS/display + rdisplayswap = /^(none|table(?!-c[ea]).+)/, + rcustomProp = /^--/, + cssShow = { position: "absolute", visibility: "hidden", display: "block" }, + cssNormalTransform = { + letterSpacing: "0", + fontWeight: "400" + }; + +function setPositiveNumber( _elem, value, subtract ) { + + // Any relative (+/-) values have already been + // normalized at this point + var matches = rcssNum.exec( value ); + return matches ? + + // Guard against undefined "subtract", e.g., when used as in cssHooks + Math.max( 0, matches[ 2 ] - ( subtract || 0 ) ) + ( matches[ 3 ] || "px" ) : + value; +} + +function boxModelAdjustment( elem, dimension, box, isBorderBox, styles, computedVal ) { + var i = dimension === "width" ? 1 : 0, + extra = 0, + delta = 0; + + // Adjustment may not be necessary + if ( box === ( isBorderBox ? "border" : "content" ) ) { + return 0; + } + + for ( ; i < 4; i += 2 ) { + + // Both box models exclude margin + if ( box === "margin" ) { + delta += jQuery.css( elem, box + cssExpand[ i ], true, styles ); + } + + // If we get here with a content-box, we're seeking "padding" or "border" or "margin" + if ( !isBorderBox ) { + + // Add padding + delta += jQuery.css( elem, "padding" + cssExpand[ i ], true, styles ); + + // For "border" or "margin", add border + if ( box !== "padding" ) { + delta += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); + + // But still keep track of it otherwise + } else { + extra += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); + } + + // If we get here with a border-box (content + padding + border), we're seeking "content" or + // "padding" or "margin" + } else { + + // For "content", subtract padding + if ( box === "content" ) { + delta -= jQuery.css( elem, "padding" + cssExpand[ i ], true, styles ); + } + + // For "content" or "padding", subtract border + if ( box !== "margin" ) { + delta -= jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); + } + } + } + + // Account for positive content-box scroll gutter when requested by providing computedVal + if ( !isBorderBox && computedVal >= 0 ) { + + // offsetWidth/offsetHeight is a rounded sum of content, padding, scroll gutter, and border + // Assuming integer scroll gutter, subtract the rest and round down + delta += Math.max( 0, Math.ceil( + elem[ "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ) ] - + computedVal - + delta - + extra - + 0.5 + + // If offsetWidth/offsetHeight is unknown, then we can't determine content-box scroll gutter + // Use an explicit zero to avoid NaN (gh-3964) + ) ) || 0; + } + + return delta; +} + +function getWidthOrHeight( elem, dimension, extra ) { + + // Start with computed style + var styles = getStyles( elem ), + + // To avoid forcing a reflow, only fetch boxSizing if we need it (gh-4322). + // Fake content-box until we know it's needed to know the true value. + boxSizingNeeded = !support.boxSizingReliable() || extra, + isBorderBox = boxSizingNeeded && + jQuery.css( elem, "boxSizing", false, styles ) === "border-box", + valueIsBorderBox = isBorderBox, + + val = curCSS( elem, dimension, styles ), + offsetProp = "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ); + + // Support: Firefox <=54 + // Return a confounding non-pixel value or feign ignorance, as appropriate. + if ( rnumnonpx.test( val ) ) { + if ( !extra ) { + return val; + } + val = "auto"; + } + + + // Support: IE 9 - 11 only + // Use offsetWidth/offsetHeight for when box sizing is unreliable. + // In those cases, the computed value can be trusted to be border-box. + if ( ( !support.boxSizingReliable() && isBorderBox || + + // Support: IE 10 - 11+, Edge 15 - 18+ + // IE/Edge misreport `getComputedStyle` of table rows with width/height + // set in CSS while `offset*` properties report correct values. + // Interestingly, in some cases IE 9 doesn't suffer from this issue. + !support.reliableTrDimensions() && nodeName( elem, "tr" ) || + + // Fall back to offsetWidth/offsetHeight when value is "auto" + // This happens for inline elements with no explicit setting (gh-3571) + val === "auto" || + + // Support: Android <=4.1 - 4.3 only + // Also use offsetWidth/offsetHeight for misreported inline dimensions (gh-3602) + !parseFloat( val ) && jQuery.css( elem, "display", false, styles ) === "inline" ) && + + // Make sure the element is visible & connected + elem.getClientRects().length ) { + + isBorderBox = jQuery.css( elem, "boxSizing", false, styles ) === "border-box"; + + // Where available, offsetWidth/offsetHeight approximate border box dimensions. + // Where not available (e.g., SVG), assume unreliable box-sizing and interpret the + // retrieved value as a content box dimension. + valueIsBorderBox = offsetProp in elem; + if ( valueIsBorderBox ) { + val = elem[ offsetProp ]; + } + } + + // Normalize "" and auto + val = parseFloat( val ) || 0; + + // Adjust for the element's box model + return ( val + + boxModelAdjustment( + elem, + dimension, + extra || ( isBorderBox ? "border" : "content" ), + valueIsBorderBox, + styles, + + // Provide the current computed size to request scroll gutter calculation (gh-3589) + val + ) + ) + "px"; +} + +jQuery.extend( { + + // Add in style property hooks for overriding the default + // behavior of getting and setting a style property + cssHooks: { + opacity: { + get: function( elem, computed ) { + if ( computed ) { + + // We should always get a number back from opacity + var ret = curCSS( elem, "opacity" ); + return ret === "" ? "1" : ret; + } + } + } + }, + + // Don't automatically add "px" to these possibly-unitless properties + cssNumber: { + "animationIterationCount": true, + "columnCount": true, + "fillOpacity": true, + "flexGrow": true, + "flexShrink": true, + "fontWeight": true, + "gridArea": true, + "gridColumn": true, + "gridColumnEnd": true, + "gridColumnStart": true, + "gridRow": true, + "gridRowEnd": true, + "gridRowStart": true, + "lineHeight": true, + "opacity": true, + "order": true, + "orphans": true, + "widows": true, + "zIndex": true, + "zoom": true + }, + + // Add in properties whose names you wish to fix before + // setting or getting the value + cssProps: {}, + + // Get and set the style property on a DOM Node + style: function( elem, name, value, extra ) { + + // Don't set styles on text and comment nodes + if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) { + return; + } + + // Make sure that we're working with the right name + var ret, type, hooks, + origName = camelCase( name ), + isCustomProp = rcustomProp.test( name ), + style = elem.style; + + // Make sure that we're working with the right name. We don't + // want to query the value if it is a CSS custom property + // since they are user-defined. + if ( !isCustomProp ) { + name = finalPropName( origName ); + } + + // Gets hook for the prefixed version, then unprefixed version + hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ]; + + // Check if we're setting a value + if ( value !== undefined ) { + type = typeof value; + + // Convert "+=" or "-=" to relative numbers (#7345) + if ( type === "string" && ( ret = rcssNum.exec( value ) ) && ret[ 1 ] ) { + value = adjustCSS( elem, name, ret ); + + // Fixes bug #9237 + type = "number"; + } + + // Make sure that null and NaN values aren't set (#7116) + if ( value == null || value !== value ) { + return; + } + + // If a number was passed in, add the unit (except for certain CSS properties) + // The isCustomProp check can be removed in jQuery 4.0 when we only auto-append + // "px" to a few hardcoded values. + if ( type === "number" && !isCustomProp ) { + value += ret && ret[ 3 ] || ( jQuery.cssNumber[ origName ] ? "" : "px" ); + } + + // background-* props affect original clone's values + if ( !support.clearCloneStyle && value === "" && name.indexOf( "background" ) === 0 ) { + style[ name ] = "inherit"; + } + + // If a hook was provided, use that value, otherwise just set the specified value + if ( !hooks || !( "set" in hooks ) || + ( value = hooks.set( elem, value, extra ) ) !== undefined ) { + + if ( isCustomProp ) { + style.setProperty( name, value ); + } else { + style[ name ] = value; + } + } + + } else { + + // If a hook was provided get the non-computed value from there + if ( hooks && "get" in hooks && + ( ret = hooks.get( elem, false, extra ) ) !== undefined ) { + + return ret; + } + + // Otherwise just get the value from the style object + return style[ name ]; + } + }, + + css: function( elem, name, extra, styles ) { + var val, num, hooks, + origName = camelCase( name ), + isCustomProp = rcustomProp.test( name ); + + // Make sure that we're working with the right name. We don't + // want to modify the value if it is a CSS custom property + // since they are user-defined. + if ( !isCustomProp ) { + name = finalPropName( origName ); + } + + // Try prefixed name followed by the unprefixed name + hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ]; + + // If a hook was provided get the computed value from there + if ( hooks && "get" in hooks ) { + val = hooks.get( elem, true, extra ); + } + + // Otherwise, if a way to get the computed value exists, use that + if ( val === undefined ) { + val = curCSS( elem, name, styles ); + } + + // Convert "normal" to computed value + if ( val === "normal" && name in cssNormalTransform ) { + val = cssNormalTransform[ name ]; + } + + // Make numeric if forced or a qualifier was provided and val looks numeric + if ( extra === "" || extra ) { + num = parseFloat( val ); + return extra === true || isFinite( num ) ? num || 0 : val; + } + + return val; + } +} ); + +jQuery.each( [ "height", "width" ], function( _i, dimension ) { + jQuery.cssHooks[ dimension ] = { + get: function( elem, computed, extra ) { + if ( computed ) { + + // Certain elements can have dimension info if we invisibly show them + // but it must have a current display style that would benefit + return rdisplayswap.test( jQuery.css( elem, "display" ) ) && + + // Support: Safari 8+ + // Table columns in Safari have non-zero offsetWidth & zero + // getBoundingClientRect().width unless display is changed. + // Support: IE <=11 only + // Running getBoundingClientRect on a disconnected node + // in IE throws an error. + ( !elem.getClientRects().length || !elem.getBoundingClientRect().width ) ? + swap( elem, cssShow, function() { + return getWidthOrHeight( elem, dimension, extra ); + } ) : + getWidthOrHeight( elem, dimension, extra ); + } + }, + + set: function( elem, value, extra ) { + var matches, + styles = getStyles( elem ), + + // Only read styles.position if the test has a chance to fail + // to avoid forcing a reflow. + scrollboxSizeBuggy = !support.scrollboxSize() && + styles.position === "absolute", + + // To avoid forcing a reflow, only fetch boxSizing if we need it (gh-3991) + boxSizingNeeded = scrollboxSizeBuggy || extra, + isBorderBox = boxSizingNeeded && + jQuery.css( elem, "boxSizing", false, styles ) === "border-box", + subtract = extra ? + boxModelAdjustment( + elem, + dimension, + extra, + isBorderBox, + styles + ) : + 0; + + // Account for unreliable border-box dimensions by comparing offset* to computed and + // faking a content-box to get border and padding (gh-3699) + if ( isBorderBox && scrollboxSizeBuggy ) { + subtract -= Math.ceil( + elem[ "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ) ] - + parseFloat( styles[ dimension ] ) - + boxModelAdjustment( elem, dimension, "border", false, styles ) - + 0.5 + ); + } + + // Convert to pixels if value adjustment is needed + if ( subtract && ( matches = rcssNum.exec( value ) ) && + ( matches[ 3 ] || "px" ) !== "px" ) { + + elem.style[ dimension ] = value; + value = jQuery.css( elem, dimension ); + } + + return setPositiveNumber( elem, value, subtract ); + } + }; +} ); + +jQuery.cssHooks.marginLeft = addGetHookIf( support.reliableMarginLeft, + function( elem, computed ) { + if ( computed ) { + return ( parseFloat( curCSS( elem, "marginLeft" ) ) || + elem.getBoundingClientRect().left - + swap( elem, { marginLeft: 0 }, function() { + return elem.getBoundingClientRect().left; + } ) + ) + "px"; + } + } +); + +// These hooks are used by animate to expand properties +jQuery.each( { + margin: "", + padding: "", + border: "Width" +}, function( prefix, suffix ) { + jQuery.cssHooks[ prefix + suffix ] = { + expand: function( value ) { + var i = 0, + expanded = {}, + + // Assumes a single number if not a string + parts = typeof value === "string" ? value.split( " " ) : [ value ]; + + for ( ; i < 4; i++ ) { + expanded[ prefix + cssExpand[ i ] + suffix ] = + parts[ i ] || parts[ i - 2 ] || parts[ 0 ]; + } + + return expanded; + } + }; + + if ( prefix !== "margin" ) { + jQuery.cssHooks[ prefix + suffix ].set = setPositiveNumber; + } +} ); + +jQuery.fn.extend( { + css: function( name, value ) { + return access( this, function( elem, name, value ) { + var styles, len, + map = {}, + i = 0; + + if ( Array.isArray( name ) ) { + styles = getStyles( elem ); + len = name.length; + + for ( ; i < len; i++ ) { + map[ name[ i ] ] = jQuery.css( elem, name[ i ], false, styles ); + } + + return map; + } + + return value !== undefined ? + jQuery.style( elem, name, value ) : + jQuery.css( elem, name ); + }, name, value, arguments.length > 1 ); + } +} ); + + +function Tween( elem, options, prop, end, easing ) { + return new Tween.prototype.init( elem, options, prop, end, easing ); +} +jQuery.Tween = Tween; + +Tween.prototype = { + constructor: Tween, + init: function( elem, options, prop, end, easing, unit ) { + this.elem = elem; + this.prop = prop; + this.easing = easing || jQuery.easing._default; + this.options = options; + this.start = this.now = this.cur(); + this.end = end; + this.unit = unit || ( jQuery.cssNumber[ prop ] ? "" : "px" ); + }, + cur: function() { + var hooks = Tween.propHooks[ this.prop ]; + + return hooks && hooks.get ? + hooks.get( this ) : + Tween.propHooks._default.get( this ); + }, + run: function( percent ) { + var eased, + hooks = Tween.propHooks[ this.prop ]; + + if ( this.options.duration ) { + this.pos = eased = jQuery.easing[ this.easing ]( + percent, this.options.duration * percent, 0, 1, this.options.duration + ); + } else { + this.pos = eased = percent; + } + this.now = ( this.end - this.start ) * eased + this.start; + + if ( this.options.step ) { + this.options.step.call( this.elem, this.now, this ); + } + + if ( hooks && hooks.set ) { + hooks.set( this ); + } else { + Tween.propHooks._default.set( this ); + } + return this; + } +}; + +Tween.prototype.init.prototype = Tween.prototype; + +Tween.propHooks = { + _default: { + get: function( tween ) { + var result; + + // Use a property on the element directly when it is not a DOM element, + // or when there is no matching style property that exists. + if ( tween.elem.nodeType !== 1 || + tween.elem[ tween.prop ] != null && tween.elem.style[ tween.prop ] == null ) { + return tween.elem[ tween.prop ]; + } + + // Passing an empty string as a 3rd parameter to .css will automatically + // attempt a parseFloat and fallback to a string if the parse fails. + // Simple values such as "10px" are parsed to Float; + // complex values such as "rotate(1rad)" are returned as-is. + result = jQuery.css( tween.elem, tween.prop, "" ); + + // Empty strings, null, undefined and "auto" are converted to 0. + return !result || result === "auto" ? 0 : result; + }, + set: function( tween ) { + + // Use step hook for back compat. + // Use cssHook if its there. + // Use .style if available and use plain properties where available. + if ( jQuery.fx.step[ tween.prop ] ) { + jQuery.fx.step[ tween.prop ]( tween ); + } else if ( tween.elem.nodeType === 1 && ( + jQuery.cssHooks[ tween.prop ] || + tween.elem.style[ finalPropName( tween.prop ) ] != null ) ) { + jQuery.style( tween.elem, tween.prop, tween.now + tween.unit ); + } else { + tween.elem[ tween.prop ] = tween.now; + } + } + } +}; + +// Support: IE <=9 only +// Panic based approach to setting things on disconnected nodes +Tween.propHooks.scrollTop = Tween.propHooks.scrollLeft = { + set: function( tween ) { + if ( tween.elem.nodeType && tween.elem.parentNode ) { + tween.elem[ tween.prop ] = tween.now; + } + } +}; + +jQuery.easing = { + linear: function( p ) { + return p; + }, + swing: function( p ) { + return 0.5 - Math.cos( p * Math.PI ) / 2; + }, + _default: "swing" +}; + +jQuery.fx = Tween.prototype.init; + +// Back compat <1.8 extension point +jQuery.fx.step = {}; + + + + +var + fxNow, inProgress, + rfxtypes = /^(?:toggle|show|hide)$/, + rrun = /queueHooks$/; + +function schedule() { + if ( inProgress ) { + if ( document.hidden === false && window.requestAnimationFrame ) { + window.requestAnimationFrame( schedule ); + } else { + window.setTimeout( schedule, jQuery.fx.interval ); + } + + jQuery.fx.tick(); + } +} + +// Animations created synchronously will run synchronously +function createFxNow() { + window.setTimeout( function() { + fxNow = undefined; + } ); + return ( fxNow = Date.now() ); +} + +// Generate parameters to create a standard animation +function genFx( type, includeWidth ) { + var which, + i = 0, + attrs = { height: type }; + + // If we include width, step value is 1 to do all cssExpand values, + // otherwise step value is 2 to skip over Left and Right + includeWidth = includeWidth ? 1 : 0; + for ( ; i < 4; i += 2 - includeWidth ) { + which = cssExpand[ i ]; + attrs[ "margin" + which ] = attrs[ "padding" + which ] = type; + } + + if ( includeWidth ) { + attrs.opacity = attrs.width = type; + } + + return attrs; +} + +function createTween( value, prop, animation ) { + var tween, + collection = ( Animation.tweeners[ prop ] || [] ).concat( Animation.tweeners[ "*" ] ), + index = 0, + length = collection.length; + for ( ; index < length; index++ ) { + if ( ( tween = collection[ index ].call( animation, prop, value ) ) ) { + + // We're done with this property + return tween; + } + } +} + +function defaultPrefilter( elem, props, opts ) { + var prop, value, toggle, hooks, oldfire, propTween, restoreDisplay, display, + isBox = "width" in props || "height" in props, + anim = this, + orig = {}, + style = elem.style, + hidden = elem.nodeType && isHiddenWithinTree( elem ), + dataShow = dataPriv.get( elem, "fxshow" ); + + // Queue-skipping animations hijack the fx hooks + if ( !opts.queue ) { + hooks = jQuery._queueHooks( elem, "fx" ); + if ( hooks.unqueued == null ) { + hooks.unqueued = 0; + oldfire = hooks.empty.fire; + hooks.empty.fire = function() { + if ( !hooks.unqueued ) { + oldfire(); + } + }; + } + hooks.unqueued++; + + anim.always( function() { + + // Ensure the complete handler is called before this completes + anim.always( function() { + hooks.unqueued--; + if ( !jQuery.queue( elem, "fx" ).length ) { + hooks.empty.fire(); + } + } ); + } ); + } + + // Detect show/hide animations + for ( prop in props ) { + value = props[ prop ]; + if ( rfxtypes.test( value ) ) { + delete props[ prop ]; + toggle = toggle || value === "toggle"; + if ( value === ( hidden ? "hide" : "show" ) ) { + + // Pretend to be hidden if this is a "show" and + // there is still data from a stopped show/hide + if ( value === "show" && dataShow && dataShow[ prop ] !== undefined ) { + hidden = true; + + // Ignore all other no-op show/hide data + } else { + continue; + } + } + orig[ prop ] = dataShow && dataShow[ prop ] || jQuery.style( elem, prop ); + } + } + + // Bail out if this is a no-op like .hide().hide() + propTween = !jQuery.isEmptyObject( props ); + if ( !propTween && jQuery.isEmptyObject( orig ) ) { + return; + } + + // Restrict "overflow" and "display" styles during box animations + if ( isBox && elem.nodeType === 1 ) { + + // Support: IE <=9 - 11, Edge 12 - 15 + // Record all 3 overflow attributes because IE does not infer the shorthand + // from identically-valued overflowX and overflowY and Edge just mirrors + // the overflowX value there. + opts.overflow = [ style.overflow, style.overflowX, style.overflowY ]; + + // Identify a display type, preferring old show/hide data over the CSS cascade + restoreDisplay = dataShow && dataShow.display; + if ( restoreDisplay == null ) { + restoreDisplay = dataPriv.get( elem, "display" ); + } + display = jQuery.css( elem, "display" ); + if ( display === "none" ) { + if ( restoreDisplay ) { + display = restoreDisplay; + } else { + + // Get nonempty value(s) by temporarily forcing visibility + showHide( [ elem ], true ); + restoreDisplay = elem.style.display || restoreDisplay; + display = jQuery.css( elem, "display" ); + showHide( [ elem ] ); + } + } + + // Animate inline elements as inline-block + if ( display === "inline" || display === "inline-block" && restoreDisplay != null ) { + if ( jQuery.css( elem, "float" ) === "none" ) { + + // Restore the original display value at the end of pure show/hide animations + if ( !propTween ) { + anim.done( function() { + style.display = restoreDisplay; + } ); + if ( restoreDisplay == null ) { + display = style.display; + restoreDisplay = display === "none" ? "" : display; + } + } + style.display = "inline-block"; + } + } + } + + if ( opts.overflow ) { + style.overflow = "hidden"; + anim.always( function() { + style.overflow = opts.overflow[ 0 ]; + style.overflowX = opts.overflow[ 1 ]; + style.overflowY = opts.overflow[ 2 ]; + } ); + } + + // Implement show/hide animations + propTween = false; + for ( prop in orig ) { + + // General show/hide setup for this element animation + if ( !propTween ) { + if ( dataShow ) { + if ( "hidden" in dataShow ) { + hidden = dataShow.hidden; + } + } else { + dataShow = dataPriv.access( elem, "fxshow", { display: restoreDisplay } ); + } + + // Store hidden/visible for toggle so `.stop().toggle()` "reverses" + if ( toggle ) { + dataShow.hidden = !hidden; + } + + // Show elements before animating them + if ( hidden ) { + showHide( [ elem ], true ); + } + + /* eslint-disable no-loop-func */ + + anim.done( function() { + + /* eslint-enable no-loop-func */ + + // The final step of a "hide" animation is actually hiding the element + if ( !hidden ) { + showHide( [ elem ] ); + } + dataPriv.remove( elem, "fxshow" ); + for ( prop in orig ) { + jQuery.style( elem, prop, orig[ prop ] ); + } + } ); + } + + // Per-property setup + propTween = createTween( hidden ? dataShow[ prop ] : 0, prop, anim ); + if ( !( prop in dataShow ) ) { + dataShow[ prop ] = propTween.start; + if ( hidden ) { + propTween.end = propTween.start; + propTween.start = 0; + } + } + } +} + +function propFilter( props, specialEasing ) { + var index, name, easing, value, hooks; + + // camelCase, specialEasing and expand cssHook pass + for ( index in props ) { + name = camelCase( index ); + easing = specialEasing[ name ]; + value = props[ index ]; + if ( Array.isArray( value ) ) { + easing = value[ 1 ]; + value = props[ index ] = value[ 0 ]; + } + + if ( index !== name ) { + props[ name ] = value; + delete props[ index ]; + } + + hooks = jQuery.cssHooks[ name ]; + if ( hooks && "expand" in hooks ) { + value = hooks.expand( value ); + delete props[ name ]; + + // Not quite $.extend, this won't overwrite existing keys. + // Reusing 'index' because we have the correct "name" + for ( index in value ) { + if ( !( index in props ) ) { + props[ index ] = value[ index ]; + specialEasing[ index ] = easing; + } + } + } else { + specialEasing[ name ] = easing; + } + } +} + +function Animation( elem, properties, options ) { + var result, + stopped, + index = 0, + length = Animation.prefilters.length, + deferred = jQuery.Deferred().always( function() { + + // Don't match elem in the :animated selector + delete tick.elem; + } ), + tick = function() { + if ( stopped ) { + return false; + } + var currentTime = fxNow || createFxNow(), + remaining = Math.max( 0, animation.startTime + animation.duration - currentTime ), + + // Support: Android 2.3 only + // Archaic crash bug won't allow us to use `1 - ( 0.5 || 0 )` (#12497) + temp = remaining / animation.duration || 0, + percent = 1 - temp, + index = 0, + length = animation.tweens.length; + + for ( ; index < length; index++ ) { + animation.tweens[ index ].run( percent ); + } + + deferred.notifyWith( elem, [ animation, percent, remaining ] ); + + // If there's more to do, yield + if ( percent < 1 && length ) { + return remaining; + } + + // If this was an empty animation, synthesize a final progress notification + if ( !length ) { + deferred.notifyWith( elem, [ animation, 1, 0 ] ); + } + + // Resolve the animation and report its conclusion + deferred.resolveWith( elem, [ animation ] ); + return false; + }, + animation = deferred.promise( { + elem: elem, + props: jQuery.extend( {}, properties ), + opts: jQuery.extend( true, { + specialEasing: {}, + easing: jQuery.easing._default + }, options ), + originalProperties: properties, + originalOptions: options, + startTime: fxNow || createFxNow(), + duration: options.duration, + tweens: [], + createTween: function( prop, end ) { + var tween = jQuery.Tween( elem, animation.opts, prop, end, + animation.opts.specialEasing[ prop ] || animation.opts.easing ); + animation.tweens.push( tween ); + return tween; + }, + stop: function( gotoEnd ) { + var index = 0, + + // If we are going to the end, we want to run all the tweens + // otherwise we skip this part + length = gotoEnd ? animation.tweens.length : 0; + if ( stopped ) { + return this; + } + stopped = true; + for ( ; index < length; index++ ) { + animation.tweens[ index ].run( 1 ); + } + + // Resolve when we played the last frame; otherwise, reject + if ( gotoEnd ) { + deferred.notifyWith( elem, [ animation, 1, 0 ] ); + deferred.resolveWith( elem, [ animation, gotoEnd ] ); + } else { + deferred.rejectWith( elem, [ animation, gotoEnd ] ); + } + return this; + } + } ), + props = animation.props; + + propFilter( props, animation.opts.specialEasing ); + + for ( ; index < length; index++ ) { + result = Animation.prefilters[ index ].call( animation, elem, props, animation.opts ); + if ( result ) { + if ( isFunction( result.stop ) ) { + jQuery._queueHooks( animation.elem, animation.opts.queue ).stop = + result.stop.bind( result ); + } + return result; + } + } + + jQuery.map( props, createTween, animation ); + + if ( isFunction( animation.opts.start ) ) { + animation.opts.start.call( elem, animation ); + } + + // Attach callbacks from options + animation + .progress( animation.opts.progress ) + .done( animation.opts.done, animation.opts.complete ) + .fail( animation.opts.fail ) + .always( animation.opts.always ); + + jQuery.fx.timer( + jQuery.extend( tick, { + elem: elem, + anim: animation, + queue: animation.opts.queue + } ) + ); + + return animation; +} + +jQuery.Animation = jQuery.extend( Animation, { + + tweeners: { + "*": [ function( prop, value ) { + var tween = this.createTween( prop, value ); + adjustCSS( tween.elem, prop, rcssNum.exec( value ), tween ); + return tween; + } ] + }, + + tweener: function( props, callback ) { + if ( isFunction( props ) ) { + callback = props; + props = [ "*" ]; + } else { + props = props.match( rnothtmlwhite ); + } + + var prop, + index = 0, + length = props.length; + + for ( ; index < length; index++ ) { + prop = props[ index ]; + Animation.tweeners[ prop ] = Animation.tweeners[ prop ] || []; + Animation.tweeners[ prop ].unshift( callback ); + } + }, + + prefilters: [ defaultPrefilter ], + + prefilter: function( callback, prepend ) { + if ( prepend ) { + Animation.prefilters.unshift( callback ); + } else { + Animation.prefilters.push( callback ); + } + } +} ); + +jQuery.speed = function( speed, easing, fn ) { + var opt = speed && typeof speed === "object" ? jQuery.extend( {}, speed ) : { + complete: fn || !fn && easing || + isFunction( speed ) && speed, + duration: speed, + easing: fn && easing || easing && !isFunction( easing ) && easing + }; + + // Go to the end state if fx are off + if ( jQuery.fx.off ) { + opt.duration = 0; + + } else { + if ( typeof opt.duration !== "number" ) { + if ( opt.duration in jQuery.fx.speeds ) { + opt.duration = jQuery.fx.speeds[ opt.duration ]; + + } else { + opt.duration = jQuery.fx.speeds._default; + } + } + } + + // Normalize opt.queue - true/undefined/null -> "fx" + if ( opt.queue == null || opt.queue === true ) { + opt.queue = "fx"; + } + + // Queueing + opt.old = opt.complete; + + opt.complete = function() { + if ( isFunction( opt.old ) ) { + opt.old.call( this ); + } + + if ( opt.queue ) { + jQuery.dequeue( this, opt.queue ); + } + }; + + return opt; +}; + +jQuery.fn.extend( { + fadeTo: function( speed, to, easing, callback ) { + + // Show any hidden elements after setting opacity to 0 + return this.filter( isHiddenWithinTree ).css( "opacity", 0 ).show() + + // Animate to the value specified + .end().animate( { opacity: to }, speed, easing, callback ); + }, + animate: function( prop, speed, easing, callback ) { + var empty = jQuery.isEmptyObject( prop ), + optall = jQuery.speed( speed, easing, callback ), + doAnimation = function() { + + // Operate on a copy of prop so per-property easing won't be lost + var anim = Animation( this, jQuery.extend( {}, prop ), optall ); + + // Empty animations, or finishing resolves immediately + if ( empty || dataPriv.get( this, "finish" ) ) { + anim.stop( true ); + } + }; + doAnimation.finish = doAnimation; + + return empty || optall.queue === false ? + this.each( doAnimation ) : + this.queue( optall.queue, doAnimation ); + }, + stop: function( type, clearQueue, gotoEnd ) { + var stopQueue = function( hooks ) { + var stop = hooks.stop; + delete hooks.stop; + stop( gotoEnd ); + }; + + if ( typeof type !== "string" ) { + gotoEnd = clearQueue; + clearQueue = type; + type = undefined; + } + if ( clearQueue ) { + this.queue( type || "fx", [] ); + } + + return this.each( function() { + var dequeue = true, + index = type != null && type + "queueHooks", + timers = jQuery.timers, + data = dataPriv.get( this ); + + if ( index ) { + if ( data[ index ] && data[ index ].stop ) { + stopQueue( data[ index ] ); + } + } else { + for ( index in data ) { + if ( data[ index ] && data[ index ].stop && rrun.test( index ) ) { + stopQueue( data[ index ] ); + } + } + } + + for ( index = timers.length; index--; ) { + if ( timers[ index ].elem === this && + ( type == null || timers[ index ].queue === type ) ) { + + timers[ index ].anim.stop( gotoEnd ); + dequeue = false; + timers.splice( index, 1 ); + } + } + + // Start the next in the queue if the last step wasn't forced. + // Timers currently will call their complete callbacks, which + // will dequeue but only if they were gotoEnd. + if ( dequeue || !gotoEnd ) { + jQuery.dequeue( this, type ); + } + } ); + }, + finish: function( type ) { + if ( type !== false ) { + type = type || "fx"; + } + return this.each( function() { + var index, + data = dataPriv.get( this ), + queue = data[ type + "queue" ], + hooks = data[ type + "queueHooks" ], + timers = jQuery.timers, + length = queue ? queue.length : 0; + + // Enable finishing flag on private data + data.finish = true; + + // Empty the queue first + jQuery.queue( this, type, [] ); + + if ( hooks && hooks.stop ) { + hooks.stop.call( this, true ); + } + + // Look for any active animations, and finish them + for ( index = timers.length; index--; ) { + if ( timers[ index ].elem === this && timers[ index ].queue === type ) { + timers[ index ].anim.stop( true ); + timers.splice( index, 1 ); + } + } + + // Look for any animations in the old queue and finish them + for ( index = 0; index < length; index++ ) { + if ( queue[ index ] && queue[ index ].finish ) { + queue[ index ].finish.call( this ); + } + } + + // Turn off finishing flag + delete data.finish; + } ); + } +} ); + +jQuery.each( [ "toggle", "show", "hide" ], function( _i, name ) { + var cssFn = jQuery.fn[ name ]; + jQuery.fn[ name ] = function( speed, easing, callback ) { + return speed == null || typeof speed === "boolean" ? + cssFn.apply( this, arguments ) : + this.animate( genFx( name, true ), speed, easing, callback ); + }; +} ); + +// Generate shortcuts for custom animations +jQuery.each( { + slideDown: genFx( "show" ), + slideUp: genFx( "hide" ), + slideToggle: genFx( "toggle" ), + fadeIn: { opacity: "show" }, + fadeOut: { opacity: "hide" }, + fadeToggle: { opacity: "toggle" } +}, function( name, props ) { + jQuery.fn[ name ] = function( speed, easing, callback ) { + return this.animate( props, speed, easing, callback ); + }; +} ); + +jQuery.timers = []; +jQuery.fx.tick = function() { + var timer, + i = 0, + timers = jQuery.timers; + + fxNow = Date.now(); + + for ( ; i < timers.length; i++ ) { + timer = timers[ i ]; + + // Run the timer and safely remove it when done (allowing for external removal) + if ( !timer() && timers[ i ] === timer ) { + timers.splice( i--, 1 ); + } + } + + if ( !timers.length ) { + jQuery.fx.stop(); + } + fxNow = undefined; +}; + +jQuery.fx.timer = function( timer ) { + jQuery.timers.push( timer ); + jQuery.fx.start(); +}; + +jQuery.fx.interval = 13; +jQuery.fx.start = function() { + if ( inProgress ) { + return; + } + + inProgress = true; + schedule(); +}; + +jQuery.fx.stop = function() { + inProgress = null; +}; + +jQuery.fx.speeds = { + slow: 600, + fast: 200, + + // Default speed + _default: 400 +}; + + +// Based off of the plugin by Clint Helfers, with permission. +// https://web.archive.org/web/20100324014747/http://blindsignals.com/index.php/2009/07/jquery-delay/ +jQuery.fn.delay = function( time, type ) { + time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time; + type = type || "fx"; + + return this.queue( type, function( next, hooks ) { + var timeout = window.setTimeout( next, time ); + hooks.stop = function() { + window.clearTimeout( timeout ); + }; + } ); +}; + + +( function() { + var input = document.createElement( "input" ), + select = document.createElement( "select" ), + opt = select.appendChild( document.createElement( "option" ) ); + + input.type = "checkbox"; + + // Support: Android <=4.3 only + // Default value for a checkbox should be "on" + support.checkOn = input.value !== ""; + + // Support: IE <=11 only + // Must access selectedIndex to make default options select + support.optSelected = opt.selected; + + // Support: IE <=11 only + // An input loses its value after becoming a radio + input = document.createElement( "input" ); + input.value = "t"; + input.type = "radio"; + support.radioValue = input.value === "t"; +} )(); + + +var boolHook, + attrHandle = jQuery.expr.attrHandle; + +jQuery.fn.extend( { + attr: function( name, value ) { + return access( this, jQuery.attr, name, value, arguments.length > 1 ); + }, + + removeAttr: function( name ) { + return this.each( function() { + jQuery.removeAttr( this, name ); + } ); + } +} ); + +jQuery.extend( { + attr: function( elem, name, value ) { + var ret, hooks, + nType = elem.nodeType; + + // Don't get/set attributes on text, comment and attribute nodes + if ( nType === 3 || nType === 8 || nType === 2 ) { + return; + } + + // Fallback to prop when attributes are not supported + if ( typeof elem.getAttribute === "undefined" ) { + return jQuery.prop( elem, name, value ); + } + + // Attribute hooks are determined by the lowercase version + // Grab necessary hook if one is defined + if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) { + hooks = jQuery.attrHooks[ name.toLowerCase() ] || + ( jQuery.expr.match.bool.test( name ) ? boolHook : undefined ); + } + + if ( value !== undefined ) { + if ( value === null ) { + jQuery.removeAttr( elem, name ); + return; + } + + if ( hooks && "set" in hooks && + ( ret = hooks.set( elem, value, name ) ) !== undefined ) { + return ret; + } + + elem.setAttribute( name, value + "" ); + return value; + } + + if ( hooks && "get" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) { + return ret; + } + + ret = jQuery.find.attr( elem, name ); + + // Non-existent attributes return null, we normalize to undefined + return ret == null ? undefined : ret; + }, + + attrHooks: { + type: { + set: function( elem, value ) { + if ( !support.radioValue && value === "radio" && + nodeName( elem, "input" ) ) { + var val = elem.value; + elem.setAttribute( "type", value ); + if ( val ) { + elem.value = val; + } + return value; + } + } + } + }, + + removeAttr: function( elem, value ) { + var name, + i = 0, + + // Attribute names can contain non-HTML whitespace characters + // https://html.spec.whatwg.org/multipage/syntax.html#attributes-2 + attrNames = value && value.match( rnothtmlwhite ); + + if ( attrNames && elem.nodeType === 1 ) { + while ( ( name = attrNames[ i++ ] ) ) { + elem.removeAttribute( name ); + } + } + } +} ); + +// Hooks for boolean attributes +boolHook = { + set: function( elem, value, name ) { + if ( value === false ) { + + // Remove boolean attributes when set to false + jQuery.removeAttr( elem, name ); + } else { + elem.setAttribute( name, name ); + } + return name; + } +}; + +jQuery.each( jQuery.expr.match.bool.source.match( /\w+/g ), function( _i, name ) { + var getter = attrHandle[ name ] || jQuery.find.attr; + + attrHandle[ name ] = function( elem, name, isXML ) { + var ret, handle, + lowercaseName = name.toLowerCase(); + + if ( !isXML ) { + + // Avoid an infinite loop by temporarily removing this function from the getter + handle = attrHandle[ lowercaseName ]; + attrHandle[ lowercaseName ] = ret; + ret = getter( elem, name, isXML ) != null ? + lowercaseName : + null; + attrHandle[ lowercaseName ] = handle; + } + return ret; + }; +} ); + + + + +var rfocusable = /^(?:input|select|textarea|button)$/i, + rclickable = /^(?:a|area)$/i; + +jQuery.fn.extend( { + prop: function( name, value ) { + return access( this, jQuery.prop, name, value, arguments.length > 1 ); + }, + + removeProp: function( name ) { + return this.each( function() { + delete this[ jQuery.propFix[ name ] || name ]; + } ); + } +} ); + +jQuery.extend( { + prop: function( elem, name, value ) { + var ret, hooks, + nType = elem.nodeType; + + // Don't get/set properties on text, comment and attribute nodes + if ( nType === 3 || nType === 8 || nType === 2 ) { + return; + } + + if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) { + + // Fix name and attach hooks + name = jQuery.propFix[ name ] || name; + hooks = jQuery.propHooks[ name ]; + } + + if ( value !== undefined ) { + if ( hooks && "set" in hooks && + ( ret = hooks.set( elem, value, name ) ) !== undefined ) { + return ret; + } + + return ( elem[ name ] = value ); + } + + if ( hooks && "get" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) { + return ret; + } + + return elem[ name ]; + }, + + propHooks: { + tabIndex: { + get: function( elem ) { + + // Support: IE <=9 - 11 only + // elem.tabIndex doesn't always return the + // correct value when it hasn't been explicitly set + // https://web.archive.org/web/20141116233347/http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/ + // Use proper attribute retrieval(#12072) + var tabindex = jQuery.find.attr( elem, "tabindex" ); + + if ( tabindex ) { + return parseInt( tabindex, 10 ); + } + + if ( + rfocusable.test( elem.nodeName ) || + rclickable.test( elem.nodeName ) && + elem.href + ) { + return 0; + } + + return -1; + } + } + }, + + propFix: { + "for": "htmlFor", + "class": "className" + } +} ); + +// Support: IE <=11 only +// Accessing the selectedIndex property +// forces the browser to respect setting selected +// on the option +// The getter ensures a default option is selected +// when in an optgroup +// eslint rule "no-unused-expressions" is disabled for this code +// since it considers such accessions noop +if ( !support.optSelected ) { + jQuery.propHooks.selected = { + get: function( elem ) { + + /* eslint no-unused-expressions: "off" */ + + var parent = elem.parentNode; + if ( parent && parent.parentNode ) { + parent.parentNode.selectedIndex; + } + return null; + }, + set: function( elem ) { + + /* eslint no-unused-expressions: "off" */ + + var parent = elem.parentNode; + if ( parent ) { + parent.selectedIndex; + + if ( parent.parentNode ) { + parent.parentNode.selectedIndex; + } + } + } + }; +} + +jQuery.each( [ + "tabIndex", + "readOnly", + "maxLength", + "cellSpacing", + "cellPadding", + "rowSpan", + "colSpan", + "useMap", + "frameBorder", + "contentEditable" +], function() { + jQuery.propFix[ this.toLowerCase() ] = this; +} ); + + + + + // Strip and collapse whitespace according to HTML spec + // https://infra.spec.whatwg.org/#strip-and-collapse-ascii-whitespace + function stripAndCollapse( value ) { + var tokens = value.match( rnothtmlwhite ) || []; + return tokens.join( " " ); + } + + +function getClass( elem ) { + return elem.getAttribute && elem.getAttribute( "class" ) || ""; +} + +function classesToArray( value ) { + if ( Array.isArray( value ) ) { + return value; + } + if ( typeof value === "string" ) { + return value.match( rnothtmlwhite ) || []; + } + return []; +} + +jQuery.fn.extend( { + addClass: function( value ) { + var classes, elem, cur, curValue, clazz, j, finalValue, + i = 0; + + if ( isFunction( value ) ) { + return this.each( function( j ) { + jQuery( this ).addClass( value.call( this, j, getClass( this ) ) ); + } ); + } + + classes = classesToArray( value ); + + if ( classes.length ) { + while ( ( elem = this[ i++ ] ) ) { + curValue = getClass( elem ); + cur = elem.nodeType === 1 && ( " " + stripAndCollapse( curValue ) + " " ); + + if ( cur ) { + j = 0; + while ( ( clazz = classes[ j++ ] ) ) { + if ( cur.indexOf( " " + clazz + " " ) < 0 ) { + cur += clazz + " "; + } + } + + // Only assign if different to avoid unneeded rendering. + finalValue = stripAndCollapse( cur ); + if ( curValue !== finalValue ) { + elem.setAttribute( "class", finalValue ); + } + } + } + } + + return this; + }, + + removeClass: function( value ) { + var classes, elem, cur, curValue, clazz, j, finalValue, + i = 0; + + if ( isFunction( value ) ) { + return this.each( function( j ) { + jQuery( this ).removeClass( value.call( this, j, getClass( this ) ) ); + } ); + } + + if ( !arguments.length ) { + return this.attr( "class", "" ); + } + + classes = classesToArray( value ); + + if ( classes.length ) { + while ( ( elem = this[ i++ ] ) ) { + curValue = getClass( elem ); + + // This expression is here for better compressibility (see addClass) + cur = elem.nodeType === 1 && ( " " + stripAndCollapse( curValue ) + " " ); + + if ( cur ) { + j = 0; + while ( ( clazz = classes[ j++ ] ) ) { + + // Remove *all* instances + while ( cur.indexOf( " " + clazz + " " ) > -1 ) { + cur = cur.replace( " " + clazz + " ", " " ); + } + } + + // Only assign if different to avoid unneeded rendering. + finalValue = stripAndCollapse( cur ); + if ( curValue !== finalValue ) { + elem.setAttribute( "class", finalValue ); + } + } + } + } + + return this; + }, + + toggleClass: function( value, stateVal ) { + var type = typeof value, + isValidValue = type === "string" || Array.isArray( value ); + + if ( typeof stateVal === "boolean" && isValidValue ) { + return stateVal ? this.addClass( value ) : this.removeClass( value ); + } + + if ( isFunction( value ) ) { + return this.each( function( i ) { + jQuery( this ).toggleClass( + value.call( this, i, getClass( this ), stateVal ), + stateVal + ); + } ); + } + + return this.each( function() { + var className, i, self, classNames; + + if ( isValidValue ) { + + // Toggle individual class names + i = 0; + self = jQuery( this ); + classNames = classesToArray( value ); + + while ( ( className = classNames[ i++ ] ) ) { + + // Check each className given, space separated list + if ( self.hasClass( className ) ) { + self.removeClass( className ); + } else { + self.addClass( className ); + } + } + + // Toggle whole class name + } else if ( value === undefined || type === "boolean" ) { + className = getClass( this ); + if ( className ) { + + // Store className if set + dataPriv.set( this, "__className__", className ); + } + + // If the element has a class name or if we're passed `false`, + // then remove the whole classname (if there was one, the above saved it). + // Otherwise bring back whatever was previously saved (if anything), + // falling back to the empty string if nothing was stored. + if ( this.setAttribute ) { + this.setAttribute( "class", + className || value === false ? + "" : + dataPriv.get( this, "__className__" ) || "" + ); + } + } + } ); + }, + + hasClass: function( selector ) { + var className, elem, + i = 0; + + className = " " + selector + " "; + while ( ( elem = this[ i++ ] ) ) { + if ( elem.nodeType === 1 && + ( " " + stripAndCollapse( getClass( elem ) ) + " " ).indexOf( className ) > -1 ) { + return true; + } + } + + return false; + } +} ); + + + + +var rreturn = /\r/g; + +jQuery.fn.extend( { + val: function( value ) { + var hooks, ret, valueIsFunction, + elem = this[ 0 ]; + + if ( !arguments.length ) { + if ( elem ) { + hooks = jQuery.valHooks[ elem.type ] || + jQuery.valHooks[ elem.nodeName.toLowerCase() ]; + + if ( hooks && + "get" in hooks && + ( ret = hooks.get( elem, "value" ) ) !== undefined + ) { + return ret; + } + + ret = elem.value; + + // Handle most common string cases + if ( typeof ret === "string" ) { + return ret.replace( rreturn, "" ); + } + + // Handle cases where value is null/undef or number + return ret == null ? "" : ret; + } + + return; + } + + valueIsFunction = isFunction( value ); + + return this.each( function( i ) { + var val; + + if ( this.nodeType !== 1 ) { + return; + } + + if ( valueIsFunction ) { + val = value.call( this, i, jQuery( this ).val() ); + } else { + val = value; + } + + // Treat null/undefined as ""; convert numbers to string + if ( val == null ) { + val = ""; + + } else if ( typeof val === "number" ) { + val += ""; + + } else if ( Array.isArray( val ) ) { + val = jQuery.map( val, function( value ) { + return value == null ? "" : value + ""; + } ); + } + + hooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ]; + + // If set returns undefined, fall back to normal setting + if ( !hooks || !( "set" in hooks ) || hooks.set( this, val, "value" ) === undefined ) { + this.value = val; + } + } ); + } +} ); + +jQuery.extend( { + valHooks: { + option: { + get: function( elem ) { + + var val = jQuery.find.attr( elem, "value" ); + return val != null ? + val : + + // Support: IE <=10 - 11 only + // option.text throws exceptions (#14686, #14858) + // Strip and collapse whitespace + // https://html.spec.whatwg.org/#strip-and-collapse-whitespace + stripAndCollapse( jQuery.text( elem ) ); + } + }, + select: { + get: function( elem ) { + var value, option, i, + options = elem.options, + index = elem.selectedIndex, + one = elem.type === "select-one", + values = one ? null : [], + max = one ? index + 1 : options.length; + + if ( index < 0 ) { + i = max; + + } else { + i = one ? index : 0; + } + + // Loop through all the selected options + for ( ; i < max; i++ ) { + option = options[ i ]; + + // Support: IE <=9 only + // IE8-9 doesn't update selected after form reset (#2551) + if ( ( option.selected || i === index ) && + + // Don't return options that are disabled or in a disabled optgroup + !option.disabled && + ( !option.parentNode.disabled || + !nodeName( option.parentNode, "optgroup" ) ) ) { + + // Get the specific value for the option + value = jQuery( option ).val(); + + // We don't need an array for one selects + if ( one ) { + return value; + } + + // Multi-Selects return an array + values.push( value ); + } + } + + return values; + }, + + set: function( elem, value ) { + var optionSet, option, + options = elem.options, + values = jQuery.makeArray( value ), + i = options.length; + + while ( i-- ) { + option = options[ i ]; + + /* eslint-disable no-cond-assign */ + + if ( option.selected = + jQuery.inArray( jQuery.valHooks.option.get( option ), values ) > -1 + ) { + optionSet = true; + } + + /* eslint-enable no-cond-assign */ + } + + // Force browsers to behave consistently when non-matching value is set + if ( !optionSet ) { + elem.selectedIndex = -1; + } + return values; + } + } + } +} ); + +// Radios and checkboxes getter/setter +jQuery.each( [ "radio", "checkbox" ], function() { + jQuery.valHooks[ this ] = { + set: function( elem, value ) { + if ( Array.isArray( value ) ) { + return ( elem.checked = jQuery.inArray( jQuery( elem ).val(), value ) > -1 ); + } + } + }; + if ( !support.checkOn ) { + jQuery.valHooks[ this ].get = function( elem ) { + return elem.getAttribute( "value" ) === null ? "on" : elem.value; + }; + } +} ); + + + + +// Return jQuery for attributes-only inclusion + + +support.focusin = "onfocusin" in window; + + +var rfocusMorph = /^(?:focusinfocus|focusoutblur)$/, + stopPropagationCallback = function( e ) { + e.stopPropagation(); + }; + +jQuery.extend( jQuery.event, { + + trigger: function( event, data, elem, onlyHandlers ) { + + var i, cur, tmp, bubbleType, ontype, handle, special, lastElement, + eventPath = [ elem || document ], + type = hasOwn.call( event, "type" ) ? event.type : event, + namespaces = hasOwn.call( event, "namespace" ) ? event.namespace.split( "." ) : []; + + cur = lastElement = tmp = elem = elem || document; + + // Don't do events on text and comment nodes + if ( elem.nodeType === 3 || elem.nodeType === 8 ) { + return; + } + + // focus/blur morphs to focusin/out; ensure we're not firing them right now + if ( rfocusMorph.test( type + jQuery.event.triggered ) ) { + return; + } + + if ( type.indexOf( "." ) > -1 ) { + + // Namespaced trigger; create a regexp to match event type in handle() + namespaces = type.split( "." ); + type = namespaces.shift(); + namespaces.sort(); + } + ontype = type.indexOf( ":" ) < 0 && "on" + type; + + // Caller can pass in a jQuery.Event object, Object, or just an event type string + event = event[ jQuery.expando ] ? + event : + new jQuery.Event( type, typeof event === "object" && event ); + + // Trigger bitmask: & 1 for native handlers; & 2 for jQuery (always true) + event.isTrigger = onlyHandlers ? 2 : 3; + event.namespace = namespaces.join( "." ); + event.rnamespace = event.namespace ? + new RegExp( "(^|\\.)" + namespaces.join( "\\.(?:.*\\.|)" ) + "(\\.|$)" ) : + null; + + // Clean up the event in case it is being reused + event.result = undefined; + if ( !event.target ) { + event.target = elem; + } + + // Clone any incoming data and prepend the event, creating the handler arg list + data = data == null ? + [ event ] : + jQuery.makeArray( data, [ event ] ); + + // Allow special events to draw outside the lines + special = jQuery.event.special[ type ] || {}; + if ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) { + return; + } + + // Determine event propagation path in advance, per W3C events spec (#9951) + // Bubble up to document, then to window; watch for a global ownerDocument var (#9724) + if ( !onlyHandlers && !special.noBubble && !isWindow( elem ) ) { + + bubbleType = special.delegateType || type; + if ( !rfocusMorph.test( bubbleType + type ) ) { + cur = cur.parentNode; + } + for ( ; cur; cur = cur.parentNode ) { + eventPath.push( cur ); + tmp = cur; + } + + // Only add window if we got to document (e.g., not plain obj or detached DOM) + if ( tmp === ( elem.ownerDocument || document ) ) { + eventPath.push( tmp.defaultView || tmp.parentWindow || window ); + } + } + + // Fire handlers on the event path + i = 0; + while ( ( cur = eventPath[ i++ ] ) && !event.isPropagationStopped() ) { + lastElement = cur; + event.type = i > 1 ? + bubbleType : + special.bindType || type; + + // jQuery handler + handle = ( + dataPriv.get( cur, "events" ) || Object.create( null ) + )[ event.type ] && + dataPriv.get( cur, "handle" ); + if ( handle ) { + handle.apply( cur, data ); + } + + // Native handler + handle = ontype && cur[ ontype ]; + if ( handle && handle.apply && acceptData( cur ) ) { + event.result = handle.apply( cur, data ); + if ( event.result === false ) { + event.preventDefault(); + } + } + } + event.type = type; + + // If nobody prevented the default action, do it now + if ( !onlyHandlers && !event.isDefaultPrevented() ) { + + if ( ( !special._default || + special._default.apply( eventPath.pop(), data ) === false ) && + acceptData( elem ) ) { + + // Call a native DOM method on the target with the same name as the event. + // Don't do default actions on window, that's where global variables be (#6170) + if ( ontype && isFunction( elem[ type ] ) && !isWindow( elem ) ) { + + // Don't re-trigger an onFOO event when we call its FOO() method + tmp = elem[ ontype ]; + + if ( tmp ) { + elem[ ontype ] = null; + } + + // Prevent re-triggering of the same event, since we already bubbled it above + jQuery.event.triggered = type; + + if ( event.isPropagationStopped() ) { + lastElement.addEventListener( type, stopPropagationCallback ); + } + + elem[ type ](); + + if ( event.isPropagationStopped() ) { + lastElement.removeEventListener( type, stopPropagationCallback ); + } + + jQuery.event.triggered = undefined; + + if ( tmp ) { + elem[ ontype ] = tmp; + } + } + } + } + + return event.result; + }, + + // Piggyback on a donor event to simulate a different one + // Used only for `focus(in | out)` events + simulate: function( type, elem, event ) { + var e = jQuery.extend( + new jQuery.Event(), + event, + { + type: type, + isSimulated: true + } + ); + + jQuery.event.trigger( e, null, elem ); + } + +} ); + +jQuery.fn.extend( { + + trigger: function( type, data ) { + return this.each( function() { + jQuery.event.trigger( type, data, this ); + } ); + }, + triggerHandler: function( type, data ) { + var elem = this[ 0 ]; + if ( elem ) { + return jQuery.event.trigger( type, data, elem, true ); + } + } +} ); + + +// Support: Firefox <=44 +// Firefox doesn't have focus(in | out) events +// Related ticket - https://bugzilla.mozilla.org/show_bug.cgi?id=687787 +// +// Support: Chrome <=48 - 49, Safari <=9.0 - 9.1 +// focus(in | out) events fire after focus & blur events, +// which is spec violation - http://www.w3.org/TR/DOM-Level-3-Events/#events-focusevent-event-order +// Related ticket - https://bugs.chromium.org/p/chromium/issues/detail?id=449857 +if ( !support.focusin ) { + jQuery.each( { focus: "focusin", blur: "focusout" }, function( orig, fix ) { + + // Attach a single capturing handler on the document while someone wants focusin/focusout + var handler = function( event ) { + jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ) ); + }; + + jQuery.event.special[ fix ] = { + setup: function() { + + // Handle: regular nodes (via `this.ownerDocument`), window + // (via `this.document`) & document (via `this`). + var doc = this.ownerDocument || this.document || this, + attaches = dataPriv.access( doc, fix ); + + if ( !attaches ) { + doc.addEventListener( orig, handler, true ); + } + dataPriv.access( doc, fix, ( attaches || 0 ) + 1 ); + }, + teardown: function() { + var doc = this.ownerDocument || this.document || this, + attaches = dataPriv.access( doc, fix ) - 1; + + if ( !attaches ) { + doc.removeEventListener( orig, handler, true ); + dataPriv.remove( doc, fix ); + + } else { + dataPriv.access( doc, fix, attaches ); + } + } + }; + } ); +} +var location = window.location; + +var nonce = { guid: Date.now() }; + +var rquery = ( /\?/ ); + + + +// Cross-browser xml parsing +jQuery.parseXML = function( data ) { + var xml; + if ( !data || typeof data !== "string" ) { + return null; + } + + // Support: IE 9 - 11 only + // IE throws on parseFromString with invalid input. + try { + xml = ( new window.DOMParser() ).parseFromString( data, "text/xml" ); + } catch ( e ) { + xml = undefined; + } + + if ( !xml || xml.getElementsByTagName( "parsererror" ).length ) { + jQuery.error( "Invalid XML: " + data ); + } + return xml; +}; + + +var + rbracket = /\[\]$/, + rCRLF = /\r?\n/g, + rsubmitterTypes = /^(?:submit|button|image|reset|file)$/i, + rsubmittable = /^(?:input|select|textarea|keygen)/i; + +function buildParams( prefix, obj, traditional, add ) { + var name; + + if ( Array.isArray( obj ) ) { + + // Serialize array item. + jQuery.each( obj, function( i, v ) { + if ( traditional || rbracket.test( prefix ) ) { + + // Treat each array item as a scalar. + add( prefix, v ); + + } else { + + // Item is non-scalar (array or object), encode its numeric index. + buildParams( + prefix + "[" + ( typeof v === "object" && v != null ? i : "" ) + "]", + v, + traditional, + add + ); + } + } ); + + } else if ( !traditional && toType( obj ) === "object" ) { + + // Serialize object item. + for ( name in obj ) { + buildParams( prefix + "[" + name + "]", obj[ name ], traditional, add ); + } + + } else { + + // Serialize scalar item. + add( prefix, obj ); + } +} + +// Serialize an array of form elements or a set of +// key/values into a query string +jQuery.param = function( a, traditional ) { + var prefix, + s = [], + add = function( key, valueOrFunction ) { + + // If value is a function, invoke it and use its return value + var value = isFunction( valueOrFunction ) ? + valueOrFunction() : + valueOrFunction; + + s[ s.length ] = encodeURIComponent( key ) + "=" + + encodeURIComponent( value == null ? "" : value ); + }; + + if ( a == null ) { + return ""; + } + + // If an array was passed in, assume that it is an array of form elements. + if ( Array.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) { + + // Serialize the form elements + jQuery.each( a, function() { + add( this.name, this.value ); + } ); + + } else { + + // If traditional, encode the "old" way (the way 1.3.2 or older + // did it), otherwise encode params recursively. + for ( prefix in a ) { + buildParams( prefix, a[ prefix ], traditional, add ); + } + } + + // Return the resulting serialization + return s.join( "&" ); +}; + +jQuery.fn.extend( { + serialize: function() { + return jQuery.param( this.serializeArray() ); + }, + serializeArray: function() { + return this.map( function() { + + // Can add propHook for "elements" to filter or add form elements + var elements = jQuery.prop( this, "elements" ); + return elements ? jQuery.makeArray( elements ) : this; + } ) + .filter( function() { + var type = this.type; + + // Use .is( ":disabled" ) so that fieldset[disabled] works + return this.name && !jQuery( this ).is( ":disabled" ) && + rsubmittable.test( this.nodeName ) && !rsubmitterTypes.test( type ) && + ( this.checked || !rcheckableType.test( type ) ); + } ) + .map( function( _i, elem ) { + var val = jQuery( this ).val(); + + if ( val == null ) { + return null; + } + + if ( Array.isArray( val ) ) { + return jQuery.map( val, function( val ) { + return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) }; + } ); + } + + return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) }; + } ).get(); + } +} ); + + +var + r20 = /%20/g, + rhash = /#.*$/, + rantiCache = /([?&])_=[^&]*/, + rheaders = /^(.*?):[ \t]*([^\r\n]*)$/mg, + + // #7653, #8125, #8152: local protocol detection + rlocalProtocol = /^(?:about|app|app-storage|.+-extension|file|res|widget):$/, + rnoContent = /^(?:GET|HEAD)$/, + rprotocol = /^\/\//, + + /* Prefilters + * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example) + * 2) These are called: + * - BEFORE asking for a transport + * - AFTER param serialization (s.data is a string if s.processData is true) + * 3) key is the dataType + * 4) the catchall symbol "*" can be used + * 5) execution will start with transport dataType and THEN continue down to "*" if needed + */ + prefilters = {}, + + /* Transports bindings + * 1) key is the dataType + * 2) the catchall symbol "*" can be used + * 3) selection will start with transport dataType and THEN go to "*" if needed + */ + transports = {}, + + // Avoid comment-prolog char sequence (#10098); must appease lint and evade compression + allTypes = "*/".concat( "*" ), + + // Anchor tag for parsing the document origin + originAnchor = document.createElement( "a" ); + originAnchor.href = location.href; + +// Base "constructor" for jQuery.ajaxPrefilter and jQuery.ajaxTransport +function addToPrefiltersOrTransports( structure ) { + + // dataTypeExpression is optional and defaults to "*" + return function( dataTypeExpression, func ) { + + if ( typeof dataTypeExpression !== "string" ) { + func = dataTypeExpression; + dataTypeExpression = "*"; + } + + var dataType, + i = 0, + dataTypes = dataTypeExpression.toLowerCase().match( rnothtmlwhite ) || []; + + if ( isFunction( func ) ) { + + // For each dataType in the dataTypeExpression + while ( ( dataType = dataTypes[ i++ ] ) ) { + + // Prepend if requested + if ( dataType[ 0 ] === "+" ) { + dataType = dataType.slice( 1 ) || "*"; + ( structure[ dataType ] = structure[ dataType ] || [] ).unshift( func ); + + // Otherwise append + } else { + ( structure[ dataType ] = structure[ dataType ] || [] ).push( func ); + } + } + } + }; +} + +// Base inspection function for prefilters and transports +function inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR ) { + + var inspected = {}, + seekingTransport = ( structure === transports ); + + function inspect( dataType ) { + var selected; + inspected[ dataType ] = true; + jQuery.each( structure[ dataType ] || [], function( _, prefilterOrFactory ) { + var dataTypeOrTransport = prefilterOrFactory( options, originalOptions, jqXHR ); + if ( typeof dataTypeOrTransport === "string" && + !seekingTransport && !inspected[ dataTypeOrTransport ] ) { + + options.dataTypes.unshift( dataTypeOrTransport ); + inspect( dataTypeOrTransport ); + return false; + } else if ( seekingTransport ) { + return !( selected = dataTypeOrTransport ); + } + } ); + return selected; + } + + return inspect( options.dataTypes[ 0 ] ) || !inspected[ "*" ] && inspect( "*" ); +} + +// A special extend for ajax options +// that takes "flat" options (not to be deep extended) +// Fixes #9887 +function ajaxExtend( target, src ) { + var key, deep, + flatOptions = jQuery.ajaxSettings.flatOptions || {}; + + for ( key in src ) { + if ( src[ key ] !== undefined ) { + ( flatOptions[ key ] ? target : ( deep || ( deep = {} ) ) )[ key ] = src[ key ]; + } + } + if ( deep ) { + jQuery.extend( true, target, deep ); + } + + return target; +} + +/* Handles responses to an ajax request: + * - finds the right dataType (mediates between content-type and expected dataType) + * - returns the corresponding response + */ +function ajaxHandleResponses( s, jqXHR, responses ) { + + var ct, type, finalDataType, firstDataType, + contents = s.contents, + dataTypes = s.dataTypes; + + // Remove auto dataType and get content-type in the process + while ( dataTypes[ 0 ] === "*" ) { + dataTypes.shift(); + if ( ct === undefined ) { + ct = s.mimeType || jqXHR.getResponseHeader( "Content-Type" ); + } + } + + // Check if we're dealing with a known content-type + if ( ct ) { + for ( type in contents ) { + if ( contents[ type ] && contents[ type ].test( ct ) ) { + dataTypes.unshift( type ); + break; + } + } + } + + // Check to see if we have a response for the expected dataType + if ( dataTypes[ 0 ] in responses ) { + finalDataType = dataTypes[ 0 ]; + } else { + + // Try convertible dataTypes + for ( type in responses ) { + if ( !dataTypes[ 0 ] || s.converters[ type + " " + dataTypes[ 0 ] ] ) { + finalDataType = type; + break; + } + if ( !firstDataType ) { + firstDataType = type; + } + } + + // Or just use first one + finalDataType = finalDataType || firstDataType; + } + + // If we found a dataType + // We add the dataType to the list if needed + // and return the corresponding response + if ( finalDataType ) { + if ( finalDataType !== dataTypes[ 0 ] ) { + dataTypes.unshift( finalDataType ); + } + return responses[ finalDataType ]; + } +} + +/* Chain conversions given the request and the original response + * Also sets the responseXXX fields on the jqXHR instance + */ +function ajaxConvert( s, response, jqXHR, isSuccess ) { + var conv2, current, conv, tmp, prev, + converters = {}, + + // Work with a copy of dataTypes in case we need to modify it for conversion + dataTypes = s.dataTypes.slice(); + + // Create converters map with lowercased keys + if ( dataTypes[ 1 ] ) { + for ( conv in s.converters ) { + converters[ conv.toLowerCase() ] = s.converters[ conv ]; + } + } + + current = dataTypes.shift(); + + // Convert to each sequential dataType + while ( current ) { + + if ( s.responseFields[ current ] ) { + jqXHR[ s.responseFields[ current ] ] = response; + } + + // Apply the dataFilter if provided + if ( !prev && isSuccess && s.dataFilter ) { + response = s.dataFilter( response, s.dataType ); + } + + prev = current; + current = dataTypes.shift(); + + if ( current ) { + + // There's only work to do if current dataType is non-auto + if ( current === "*" ) { + + current = prev; + + // Convert response if prev dataType is non-auto and differs from current + } else if ( prev !== "*" && prev !== current ) { + + // Seek a direct converter + conv = converters[ prev + " " + current ] || converters[ "* " + current ]; + + // If none found, seek a pair + if ( !conv ) { + for ( conv2 in converters ) { + + // If conv2 outputs current + tmp = conv2.split( " " ); + if ( tmp[ 1 ] === current ) { + + // If prev can be converted to accepted input + conv = converters[ prev + " " + tmp[ 0 ] ] || + converters[ "* " + tmp[ 0 ] ]; + if ( conv ) { + + // Condense equivalence converters + if ( conv === true ) { + conv = converters[ conv2 ]; + + // Otherwise, insert the intermediate dataType + } else if ( converters[ conv2 ] !== true ) { + current = tmp[ 0 ]; + dataTypes.unshift( tmp[ 1 ] ); + } + break; + } + } + } + } + + // Apply converter (if not an equivalence) + if ( conv !== true ) { + + // Unless errors are allowed to bubble, catch and return them + if ( conv && s.throws ) { + response = conv( response ); + } else { + try { + response = conv( response ); + } catch ( e ) { + return { + state: "parsererror", + error: conv ? e : "No conversion from " + prev + " to " + current + }; + } + } + } + } + } + } + + return { state: "success", data: response }; +} + +jQuery.extend( { + + // Counter for holding the number of active queries + active: 0, + + // Last-Modified header cache for next request + lastModified: {}, + etag: {}, + + ajaxSettings: { + url: location.href, + type: "GET", + isLocal: rlocalProtocol.test( location.protocol ), + global: true, + processData: true, + async: true, + contentType: "application/x-www-form-urlencoded; charset=UTF-8", + + /* + timeout: 0, + data: null, + dataType: null, + username: null, + password: null, + cache: null, + throws: false, + traditional: false, + headers: {}, + */ + + accepts: { + "*": allTypes, + text: "text/plain", + html: "text/html", + xml: "application/xml, text/xml", + json: "application/json, text/javascript" + }, + + contents: { + xml: /\bxml\b/, + html: /\bhtml/, + json: /\bjson\b/ + }, + + responseFields: { + xml: "responseXML", + text: "responseText", + json: "responseJSON" + }, + + // Data converters + // Keys separate source (or catchall "*") and destination types with a single space + converters: { + + // Convert anything to text + "* text": String, + + // Text to html (true = no transformation) + "text html": true, + + // Evaluate text as a json expression + "text json": JSON.parse, + + // Parse text as xml + "text xml": jQuery.parseXML + }, + + // For options that shouldn't be deep extended: + // you can add your own custom options here if + // and when you create one that shouldn't be + // deep extended (see ajaxExtend) + flatOptions: { + url: true, + context: true + } + }, + + // Creates a full fledged settings object into target + // with both ajaxSettings and settings fields. + // If target is omitted, writes into ajaxSettings. + ajaxSetup: function( target, settings ) { + return settings ? + + // Building a settings object + ajaxExtend( ajaxExtend( target, jQuery.ajaxSettings ), settings ) : + + // Extending ajaxSettings + ajaxExtend( jQuery.ajaxSettings, target ); + }, + + ajaxPrefilter: addToPrefiltersOrTransports( prefilters ), + ajaxTransport: addToPrefiltersOrTransports( transports ), + + // Main method + ajax: function( url, options ) { + + // If url is an object, simulate pre-1.5 signature + if ( typeof url === "object" ) { + options = url; + url = undefined; + } + + // Force options to be an object + options = options || {}; + + var transport, + + // URL without anti-cache param + cacheURL, + + // Response headers + responseHeadersString, + responseHeaders, + + // timeout handle + timeoutTimer, + + // Url cleanup var + urlAnchor, + + // Request state (becomes false upon send and true upon completion) + completed, + + // To know if global events are to be dispatched + fireGlobals, + + // Loop variable + i, + + // uncached part of the url + uncached, + + // Create the final options object + s = jQuery.ajaxSetup( {}, options ), + + // Callbacks context + callbackContext = s.context || s, + + // Context for global events is callbackContext if it is a DOM node or jQuery collection + globalEventContext = s.context && + ( callbackContext.nodeType || callbackContext.jquery ) ? + jQuery( callbackContext ) : + jQuery.event, + + // Deferreds + deferred = jQuery.Deferred(), + completeDeferred = jQuery.Callbacks( "once memory" ), + + // Status-dependent callbacks + statusCode = s.statusCode || {}, + + // Headers (they are sent all at once) + requestHeaders = {}, + requestHeadersNames = {}, + + // Default abort message + strAbort = "canceled", + + // Fake xhr + jqXHR = { + readyState: 0, + + // Builds headers hashtable if needed + getResponseHeader: function( key ) { + var match; + if ( completed ) { + if ( !responseHeaders ) { + responseHeaders = {}; + while ( ( match = rheaders.exec( responseHeadersString ) ) ) { + responseHeaders[ match[ 1 ].toLowerCase() + " " ] = + ( responseHeaders[ match[ 1 ].toLowerCase() + " " ] || [] ) + .concat( match[ 2 ] ); + } + } + match = responseHeaders[ key.toLowerCase() + " " ]; + } + return match == null ? null : match.join( ", " ); + }, + + // Raw string + getAllResponseHeaders: function() { + return completed ? responseHeadersString : null; + }, + + // Caches the header + setRequestHeader: function( name, value ) { + if ( completed == null ) { + name = requestHeadersNames[ name.toLowerCase() ] = + requestHeadersNames[ name.toLowerCase() ] || name; + requestHeaders[ name ] = value; + } + return this; + }, + + // Overrides response content-type header + overrideMimeType: function( type ) { + if ( completed == null ) { + s.mimeType = type; + } + return this; + }, + + // Status-dependent callbacks + statusCode: function( map ) { + var code; + if ( map ) { + if ( completed ) { + + // Execute the appropriate callbacks + jqXHR.always( map[ jqXHR.status ] ); + } else { + + // Lazy-add the new callbacks in a way that preserves old ones + for ( code in map ) { + statusCode[ code ] = [ statusCode[ code ], map[ code ] ]; + } + } + } + return this; + }, + + // Cancel the request + abort: function( statusText ) { + var finalText = statusText || strAbort; + if ( transport ) { + transport.abort( finalText ); + } + done( 0, finalText ); + return this; + } + }; + + // Attach deferreds + deferred.promise( jqXHR ); + + // Add protocol if not provided (prefilters might expect it) + // Handle falsy url in the settings object (#10093: consistency with old signature) + // We also use the url parameter if available + s.url = ( ( url || s.url || location.href ) + "" ) + .replace( rprotocol, location.protocol + "//" ); + + // Alias method option to type as per ticket #12004 + s.type = options.method || options.type || s.method || s.type; + + // Extract dataTypes list + s.dataTypes = ( s.dataType || "*" ).toLowerCase().match( rnothtmlwhite ) || [ "" ]; + + // A cross-domain request is in order when the origin doesn't match the current origin. + if ( s.crossDomain == null ) { + urlAnchor = document.createElement( "a" ); + + // Support: IE <=8 - 11, Edge 12 - 15 + // IE throws exception on accessing the href property if url is malformed, + // e.g. http://example.com:80x/ + try { + urlAnchor.href = s.url; + + // Support: IE <=8 - 11 only + // Anchor's host property isn't correctly set when s.url is relative + urlAnchor.href = urlAnchor.href; + s.crossDomain = originAnchor.protocol + "//" + originAnchor.host !== + urlAnchor.protocol + "//" + urlAnchor.host; + } catch ( e ) { + + // If there is an error parsing the URL, assume it is crossDomain, + // it can be rejected by the transport if it is invalid + s.crossDomain = true; + } + } + + // Convert data if not already a string + if ( s.data && s.processData && typeof s.data !== "string" ) { + s.data = jQuery.param( s.data, s.traditional ); + } + + // Apply prefilters + inspectPrefiltersOrTransports( prefilters, s, options, jqXHR ); + + // If request was aborted inside a prefilter, stop there + if ( completed ) { + return jqXHR; + } + + // We can fire global events as of now if asked to + // Don't fire events if jQuery.event is undefined in an AMD-usage scenario (#15118) + fireGlobals = jQuery.event && s.global; + + // Watch for a new set of requests + if ( fireGlobals && jQuery.active++ === 0 ) { + jQuery.event.trigger( "ajaxStart" ); + } + + // Uppercase the type + s.type = s.type.toUpperCase(); + + // Determine if request has content + s.hasContent = !rnoContent.test( s.type ); + + // Save the URL in case we're toying with the If-Modified-Since + // and/or If-None-Match header later on + // Remove hash to simplify url manipulation + cacheURL = s.url.replace( rhash, "" ); + + // More options handling for requests with no content + if ( !s.hasContent ) { + + // Remember the hash so we can put it back + uncached = s.url.slice( cacheURL.length ); + + // If data is available and should be processed, append data to url + if ( s.data && ( s.processData || typeof s.data === "string" ) ) { + cacheURL += ( rquery.test( cacheURL ) ? "&" : "?" ) + s.data; + + // #9682: remove data so that it's not used in an eventual retry + delete s.data; + } + + // Add or update anti-cache param if needed + if ( s.cache === false ) { + cacheURL = cacheURL.replace( rantiCache, "$1" ); + uncached = ( rquery.test( cacheURL ) ? "&" : "?" ) + "_=" + ( nonce.guid++ ) + + uncached; + } + + // Put hash and anti-cache on the URL that will be requested (gh-1732) + s.url = cacheURL + uncached; + + // Change '%20' to '+' if this is encoded form body content (gh-2658) + } else if ( s.data && s.processData && + ( s.contentType || "" ).indexOf( "application/x-www-form-urlencoded" ) === 0 ) { + s.data = s.data.replace( r20, "+" ); + } + + // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode. + if ( s.ifModified ) { + if ( jQuery.lastModified[ cacheURL ] ) { + jqXHR.setRequestHeader( "If-Modified-Since", jQuery.lastModified[ cacheURL ] ); + } + if ( jQuery.etag[ cacheURL ] ) { + jqXHR.setRequestHeader( "If-None-Match", jQuery.etag[ cacheURL ] ); + } + } + + // Set the correct header, if data is being sent + if ( s.data && s.hasContent && s.contentType !== false || options.contentType ) { + jqXHR.setRequestHeader( "Content-Type", s.contentType ); + } + + // Set the Accepts header for the server, depending on the dataType + jqXHR.setRequestHeader( + "Accept", + s.dataTypes[ 0 ] && s.accepts[ s.dataTypes[ 0 ] ] ? + s.accepts[ s.dataTypes[ 0 ] ] + + ( s.dataTypes[ 0 ] !== "*" ? ", " + allTypes + "; q=0.01" : "" ) : + s.accepts[ "*" ] + ); + + // Check for headers option + for ( i in s.headers ) { + jqXHR.setRequestHeader( i, s.headers[ i ] ); + } + + // Allow custom headers/mimetypes and early abort + if ( s.beforeSend && + ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || completed ) ) { + + // Abort if not done already and return + return jqXHR.abort(); + } + + // Aborting is no longer a cancellation + strAbort = "abort"; + + // Install callbacks on deferreds + completeDeferred.add( s.complete ); + jqXHR.done( s.success ); + jqXHR.fail( s.error ); + + // Get transport + transport = inspectPrefiltersOrTransports( transports, s, options, jqXHR ); + + // If no transport, we auto-abort + if ( !transport ) { + done( -1, "No Transport" ); + } else { + jqXHR.readyState = 1; + + // Send global event + if ( fireGlobals ) { + globalEventContext.trigger( "ajaxSend", [ jqXHR, s ] ); + } + + // If request was aborted inside ajaxSend, stop there + if ( completed ) { + return jqXHR; + } + + // Timeout + if ( s.async && s.timeout > 0 ) { + timeoutTimer = window.setTimeout( function() { + jqXHR.abort( "timeout" ); + }, s.timeout ); + } + + try { + completed = false; + transport.send( requestHeaders, done ); + } catch ( e ) { + + // Rethrow post-completion exceptions + if ( completed ) { + throw e; + } + + // Propagate others as results + done( -1, e ); + } + } + + // Callback for when everything is done + function done( status, nativeStatusText, responses, headers ) { + var isSuccess, success, error, response, modified, + statusText = nativeStatusText; + + // Ignore repeat invocations + if ( completed ) { + return; + } + + completed = true; + + // Clear timeout if it exists + if ( timeoutTimer ) { + window.clearTimeout( timeoutTimer ); + } + + // Dereference transport for early garbage collection + // (no matter how long the jqXHR object will be used) + transport = undefined; + + // Cache response headers + responseHeadersString = headers || ""; + + // Set readyState + jqXHR.readyState = status > 0 ? 4 : 0; + + // Determine if successful + isSuccess = status >= 200 && status < 300 || status === 304; + + // Get response data + if ( responses ) { + response = ajaxHandleResponses( s, jqXHR, responses ); + } + + // Use a noop converter for missing script + if ( !isSuccess && jQuery.inArray( "script", s.dataTypes ) > -1 ) { + s.converters[ "text script" ] = function() {}; + } + + // Convert no matter what (that way responseXXX fields are always set) + response = ajaxConvert( s, response, jqXHR, isSuccess ); + + // If successful, handle type chaining + if ( isSuccess ) { + + // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode. + if ( s.ifModified ) { + modified = jqXHR.getResponseHeader( "Last-Modified" ); + if ( modified ) { + jQuery.lastModified[ cacheURL ] = modified; + } + modified = jqXHR.getResponseHeader( "etag" ); + if ( modified ) { + jQuery.etag[ cacheURL ] = modified; + } + } + + // if no content + if ( status === 204 || s.type === "HEAD" ) { + statusText = "nocontent"; + + // if not modified + } else if ( status === 304 ) { + statusText = "notmodified"; + + // If we have data, let's convert it + } else { + statusText = response.state; + success = response.data; + error = response.error; + isSuccess = !error; + } + } else { + + // Extract error from statusText and normalize for non-aborts + error = statusText; + if ( status || !statusText ) { + statusText = "error"; + if ( status < 0 ) { + status = 0; + } + } + } + + // Set data for the fake xhr object + jqXHR.status = status; + jqXHR.statusText = ( nativeStatusText || statusText ) + ""; + + // Success/Error + if ( isSuccess ) { + deferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] ); + } else { + deferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] ); + } + + // Status-dependent callbacks + jqXHR.statusCode( statusCode ); + statusCode = undefined; + + if ( fireGlobals ) { + globalEventContext.trigger( isSuccess ? "ajaxSuccess" : "ajaxError", + [ jqXHR, s, isSuccess ? success : error ] ); + } + + // Complete + completeDeferred.fireWith( callbackContext, [ jqXHR, statusText ] ); + + if ( fireGlobals ) { + globalEventContext.trigger( "ajaxComplete", [ jqXHR, s ] ); + + // Handle the global AJAX counter + if ( !( --jQuery.active ) ) { + jQuery.event.trigger( "ajaxStop" ); + } + } + } + + return jqXHR; + }, + + getJSON: function( url, data, callback ) { + return jQuery.get( url, data, callback, "json" ); + }, + + getScript: function( url, callback ) { + return jQuery.get( url, undefined, callback, "script" ); + } +} ); + +jQuery.each( [ "get", "post" ], function( _i, method ) { + jQuery[ method ] = function( url, data, callback, type ) { + + // Shift arguments if data argument was omitted + if ( isFunction( data ) ) { + type = type || callback; + callback = data; + data = undefined; + } + + // The url can be an options object (which then must have .url) + return jQuery.ajax( jQuery.extend( { + url: url, + type: method, + dataType: type, + data: data, + success: callback + }, jQuery.isPlainObject( url ) && url ) ); + }; +} ); + +jQuery.ajaxPrefilter( function( s ) { + var i; + for ( i in s.headers ) { + if ( i.toLowerCase() === "content-type" ) { + s.contentType = s.headers[ i ] || ""; + } + } +} ); + + +jQuery._evalUrl = function( url, options, doc ) { + return jQuery.ajax( { + url: url, + + // Make this explicit, since user can override this through ajaxSetup (#11264) + type: "GET", + dataType: "script", + cache: true, + async: false, + global: false, + + // Only evaluate the response if it is successful (gh-4126) + // dataFilter is not invoked for failure responses, so using it instead + // of the default converter is kludgy but it works. + converters: { + "text script": function() {} + }, + dataFilter: function( response ) { + jQuery.globalEval( response, options, doc ); + } + } ); +}; + + +jQuery.fn.extend( { + wrapAll: function( html ) { + var wrap; + + if ( this[ 0 ] ) { + if ( isFunction( html ) ) { + html = html.call( this[ 0 ] ); + } + + // The elements to wrap the target around + wrap = jQuery( html, this[ 0 ].ownerDocument ).eq( 0 ).clone( true ); + + if ( this[ 0 ].parentNode ) { + wrap.insertBefore( this[ 0 ] ); + } + + wrap.map( function() { + var elem = this; + + while ( elem.firstElementChild ) { + elem = elem.firstElementChild; + } + + return elem; + } ).append( this ); + } + + return this; + }, + + wrapInner: function( html ) { + if ( isFunction( html ) ) { + return this.each( function( i ) { + jQuery( this ).wrapInner( html.call( this, i ) ); + } ); + } + + return this.each( function() { + var self = jQuery( this ), + contents = self.contents(); + + if ( contents.length ) { + contents.wrapAll( html ); + + } else { + self.append( html ); + } + } ); + }, + + wrap: function( html ) { + var htmlIsFunction = isFunction( html ); + + return this.each( function( i ) { + jQuery( this ).wrapAll( htmlIsFunction ? html.call( this, i ) : html ); + } ); + }, + + unwrap: function( selector ) { + this.parent( selector ).not( "body" ).each( function() { + jQuery( this ).replaceWith( this.childNodes ); + } ); + return this; + } +} ); + + +jQuery.expr.pseudos.hidden = function( elem ) { + return !jQuery.expr.pseudos.visible( elem ); +}; +jQuery.expr.pseudos.visible = function( elem ) { + return !!( elem.offsetWidth || elem.offsetHeight || elem.getClientRects().length ); +}; + + + + +jQuery.ajaxSettings.xhr = function() { + try { + return new window.XMLHttpRequest(); + } catch ( e ) {} +}; + +var xhrSuccessStatus = { + + // File protocol always yields status code 0, assume 200 + 0: 200, + + // Support: IE <=9 only + // #1450: sometimes IE returns 1223 when it should be 204 + 1223: 204 + }, + xhrSupported = jQuery.ajaxSettings.xhr(); + +support.cors = !!xhrSupported && ( "withCredentials" in xhrSupported ); +support.ajax = xhrSupported = !!xhrSupported; + +jQuery.ajaxTransport( function( options ) { + var callback, errorCallback; + + // Cross domain only allowed if supported through XMLHttpRequest + if ( support.cors || xhrSupported && !options.crossDomain ) { + return { + send: function( headers, complete ) { + var i, + xhr = options.xhr(); + + xhr.open( + options.type, + options.url, + options.async, + options.username, + options.password + ); + + // Apply custom fields if provided + if ( options.xhrFields ) { + for ( i in options.xhrFields ) { + xhr[ i ] = options.xhrFields[ i ]; + } + } + + // Override mime type if needed + if ( options.mimeType && xhr.overrideMimeType ) { + xhr.overrideMimeType( options.mimeType ); + } + + // X-Requested-With header + // For cross-domain requests, seeing as conditions for a preflight are + // akin to a jigsaw puzzle, we simply never set it to be sure. + // (it can always be set on a per-request basis or even using ajaxSetup) + // For same-domain requests, won't change header if already provided. + if ( !options.crossDomain && !headers[ "X-Requested-With" ] ) { + headers[ "X-Requested-With" ] = "XMLHttpRequest"; + } + + // Set headers + for ( i in headers ) { + xhr.setRequestHeader( i, headers[ i ] ); + } + + // Callback + callback = function( type ) { + return function() { + if ( callback ) { + callback = errorCallback = xhr.onload = + xhr.onerror = xhr.onabort = xhr.ontimeout = + xhr.onreadystatechange = null; + + if ( type === "abort" ) { + xhr.abort(); + } else if ( type === "error" ) { + + // Support: IE <=9 only + // On a manual native abort, IE9 throws + // errors on any property access that is not readyState + if ( typeof xhr.status !== "number" ) { + complete( 0, "error" ); + } else { + complete( + + // File: protocol always yields status 0; see #8605, #14207 + xhr.status, + xhr.statusText + ); + } + } else { + complete( + xhrSuccessStatus[ xhr.status ] || xhr.status, + xhr.statusText, + + // Support: IE <=9 only + // IE9 has no XHR2 but throws on binary (trac-11426) + // For XHR2 non-text, let the caller handle it (gh-2498) + ( xhr.responseType || "text" ) !== "text" || + typeof xhr.responseText !== "string" ? + { binary: xhr.response } : + { text: xhr.responseText }, + xhr.getAllResponseHeaders() + ); + } + } + }; + }; + + // Listen to events + xhr.onload = callback(); + errorCallback = xhr.onerror = xhr.ontimeout = callback( "error" ); + + // Support: IE 9 only + // Use onreadystatechange to replace onabort + // to handle uncaught aborts + if ( xhr.onabort !== undefined ) { + xhr.onabort = errorCallback; + } else { + xhr.onreadystatechange = function() { + + // Check readyState before timeout as it changes + if ( xhr.readyState === 4 ) { + + // Allow onerror to be called first, + // but that will not handle a native abort + // Also, save errorCallback to a variable + // as xhr.onerror cannot be accessed + window.setTimeout( function() { + if ( callback ) { + errorCallback(); + } + } ); + } + }; + } + + // Create the abort callback + callback = callback( "abort" ); + + try { + + // Do send the request (this may raise an exception) + xhr.send( options.hasContent && options.data || null ); + } catch ( e ) { + + // #14683: Only rethrow if this hasn't been notified as an error yet + if ( callback ) { + throw e; + } + } + }, + + abort: function() { + if ( callback ) { + callback(); + } + } + }; + } +} ); + + + + +// Prevent auto-execution of scripts when no explicit dataType was provided (See gh-2432) +jQuery.ajaxPrefilter( function( s ) { + if ( s.crossDomain ) { + s.contents.script = false; + } +} ); + +// Install script dataType +jQuery.ajaxSetup( { + accepts: { + script: "text/javascript, application/javascript, " + + "application/ecmascript, application/x-ecmascript" + }, + contents: { + script: /\b(?:java|ecma)script\b/ + }, + converters: { + "text script": function( text ) { + jQuery.globalEval( text ); + return text; + } + } +} ); + +// Handle cache's special case and crossDomain +jQuery.ajaxPrefilter( "script", function( s ) { + if ( s.cache === undefined ) { + s.cache = false; + } + if ( s.crossDomain ) { + s.type = "GET"; + } +} ); + +// Bind script tag hack transport +jQuery.ajaxTransport( "script", function( s ) { + + // This transport only deals with cross domain or forced-by-attrs requests + if ( s.crossDomain || s.scriptAttrs ) { + var script, callback; + return { + send: function( _, complete ) { + script = jQuery( " + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra - Exceptions and Enums

+
+
+cassandra.__version_info__
+

The version of the driver in a tuple format

+
+ +
+
+cassandra.__version__
+

The version of the driver in a string format

+
+ +
+
+class cassandra.ConsistencyLevel
+

Spcifies how many replicas must respond for an operation to be considered +a success. By default, ONE is used for all operations.

+
+
+ANY = 0
+

Only requires that one replica receives the write or the coordinator +stores a hint to replay later. Valid only for writes.

+
+ +
+
+ONE = 1
+

Only one replica needs to respond to consider the operation a success

+
+ +
+
+TWO = 2
+

Two replicas must respond to consider the operation a success

+
+ +
+
+THREE = 3
+

Three replicas must respond to consider the operation a success

+
+ +
+
+QUORUM = 4
+

ceil(RF/2) + 1 replicas must respond to consider the operation a success

+
+ +
+
+ALL = 5
+

All replicas must respond to consider the operation a success

+
+ +
+
+LOCAL_QUORUM = 6
+

Requires a quorum of replicas in the local datacenter

+
+ +
+
+EACH_QUORUM = 7
+

Requires a quorum of replicas in each datacenter

+
+ +
+
+SERIAL = 8
+

For conditional inserts/updates that utilize Cassandra’s lightweight +transactions, this requires consensus among all replicas for the +modified data.

+
+ +
+
+LOCAL_SERIAL = 9
+

Like SERIAL, but only requires consensus +among replicas in the local datacenter.

+
+ +
+
+LOCAL_ONE = 10
+

Sends a request only to replicas in the local datacenter and waits for +one response.

+
+ +
+ +
+
+class cassandra.ProtocolVersion
+

Defines native protocol versions supported by this driver.

+
+
+V1 = 1
+

v1, supported in Cassandra 1.2–>2.2

+
+ +
+
+V2 = 2
+

v2, supported in Cassandra 2.0–>2.2; +added support for lightweight transactions, batch operations, and automatic query paging.

+
+ +
+
+V3 = 3
+

v3, supported in Cassandra 2.1–>3.x+; +added support for protocol-level client-side timestamps (see Session.use_client_timestamp), +serial consistency levels for BatchStatement, and an improved connection pool.

+
+ +
+
+V4 = 4
+

v4, supported in Cassandra 2.2–>3.x+; +added a number of new types, server warnings, new failure messages, and custom payloads. Details in the +project docs

+
+ +
+
+V5 = 5
+

v5, in beta from 3.x+. Finalised in 4.0-beta5

+
+ +
+
+V6 = 6
+

v6, in beta from 4.0-beta5

+
+ +
+
+DSE_V1 = 65
+

DSE private protocol v1, supported in DSE 5.1+

+
+ +
+
+DSE_V2 = 66
+

DSE private protocol v2, supported in DSE 6.0+

+
+ +
+
+SUPPORTED_VERSIONS = (66, 65, 6, 5, 4, 3, 2, 1)
+

A tuple of all supported protocol versions

+
+ +
+
+BETA_VERSIONS = (6,)
+

A tuple of all beta protocol versions

+
+ +
+
+MIN_SUPPORTED = 1
+

Minimum protocol version supported by this driver.

+
+ +
+
+MAX_SUPPORTED = 66
+

Maximum protocol version supported by this driver.

+
+ +
+
+classmethod get_lower_supported(previous_version)
+

Return the lower supported protocol version. Beta versions are omitted.

+
+ +
+ +
+
+class cassandra.UserFunctionDescriptor(name, argument_types)
+

Describes a User function by name and argument signature

+
+
+name = None
+

name of the function

+
+ +
+
+argument_types = None
+

Ordered list of CQL argument type names comprising the type signature

+
+ +
+
+property signature
+

function signature string in the form ‘name([type0[,type1[…]]])’

+

can be used to uniquely identify overloaded function names within a keyspace

+
+ +
+ +
+
+class cassandra.UserAggregateDescriptor(name, argument_types)
+

Describes a User aggregate function by name and argument signature

+
+
+name = None
+

name of the aggregate

+
+ +
+
+argument_types = None
+

Ordered list of CQL argument type names comprising the type signature

+
+ +
+
+property signature
+

function signature string in the form ‘name([type0[,type1[…]]])’

+

can be used to uniquely identify overloaded function names within a keyspace

+
+ +
+ +
+
+exception cassandra.DriverException
+

Base for all exceptions explicitly raised by the driver.

+
+ +
+
+exception cassandra.RequestExecutionException
+

Base for request execution exceptions returned from the server.

+
+ +
+
+exception cassandra.Unavailable
+

There were not enough live replicas to satisfy the requested consistency +level, so the coordinator node immediately failed the request without +forwarding it to any replicas.

+
+
+consistency = None
+

The requested ConsistencyLevel

+
+ +
+
+required_replicas = None
+

The number of replicas that needed to be live to complete the operation

+
+ +
+
+alive_replicas = None
+

The number of replicas that were actually alive

+
+ +
+ +
+
+exception cassandra.Timeout
+

Replicas failed to respond to the coordinator node before timing out.

+
+
+consistency = None
+

The requested ConsistencyLevel

+
+ +
+
+required_responses = None
+

The number of required replica responses

+
+ +
+
+received_responses = None
+

The number of replicas that responded before the coordinator timed out +the operation

+
+ +
+ +
+
+exception cassandra.ReadTimeout
+

A subclass of Timeout for read operations.

+

This indicates that the replicas failed to respond to the coordinator +node before the configured timeout. This timeout is configured in +cassandra.yaml with the read_request_timeout_in_ms +and range_request_timeout_in_ms options.

+
+
+data_retrieved = None
+

A boolean indicating whether the requested data was retrieved +by the coordinator from any replicas before it timed out the +operation

+
+ +
+ +
+
+exception cassandra.WriteTimeout
+

A subclass of Timeout for write operations.

+

This indicates that the replicas failed to respond to the coordinator +node before the configured timeout. This timeout is configured in +cassandra.yaml with the write_request_timeout_in_ms +option.

+
+
+write_type = None
+

The type of write operation, enum on WriteType

+
+ +
+ +
+
+exception cassandra.CoordinationFailure
+

Replicas sent a failure to the coordinator.

+
+
+consistency = None
+

The requested ConsistencyLevel

+
+ +
+
+required_responses = None
+

The number of required replica responses

+
+ +
+
+received_responses = None
+

The number of replicas that responded before the coordinator timed out +the operation

+
+ +
+
+failures = None
+

The number of replicas that sent a failure message

+
+ +
+
+error_code_map = None
+

A map of inet addresses to error codes representing replicas that sent +a failure message. Only set when protocol_version is 5 or higher.

+
+ +
+ +
+
+exception cassandra.ReadFailure
+

A subclass of CoordinationFailure for read operations.

+

This indicates that the replicas sent a failure message to the coordinator.

+
+
+data_retrieved = None
+

A boolean indicating whether the requested data was retrieved +by the coordinator from any replicas before it timed out the +operation

+
+ +
+ +
+
+exception cassandra.WriteFailure
+

A subclass of CoordinationFailure for write operations.

+

This indicates that the replicas sent a failure message to the coordinator.

+
+
+write_type = None
+

The type of write operation, enum on WriteType

+
+ +
+ +
+
+exception cassandra.FunctionFailure
+

User Defined Function failed during execution

+
+
+keyspace = None
+

Keyspace of the function

+
+ +
+
+function = None
+

Name of the function

+
+ +
+
+arg_types = None
+

List of argument type names of the function

+
+ +
+ +
+
+exception cassandra.RequestValidationException
+

Server request validation failed

+
+ +
+
+exception cassandra.ConfigurationException
+

Server indicated request errro due to current configuration

+
+ +
+
+exception cassandra.AlreadyExists
+

An attempt was made to create a keyspace or table that already exists.

+
+
+keyspace = None
+

The name of the keyspace that already exists, or, if an attempt was +made to create a new table, the keyspace that the table is in.

+
+ +
+
+table = None
+

The name of the table that already exists, or, if an attempt was +make to create a keyspace, None.

+
+ +
+ +
+
+exception cassandra.InvalidRequest
+

A query was made that was invalid for some reason, such as trying to set +the keyspace for a connection to a nonexistent keyspace.

+
+ +
+
+exception cassandra.Unauthorized
+

The current user is not authorized to perform the requested operation.

+
+ +
+
+exception cassandra.AuthenticationFailed
+

Failed to authenticate.

+
+ +
+
+exception cassandra.OperationTimedOut
+

The operation took longer than the specified (client-side) timeout +to complete. This is not an error generated by Cassandra, only +the driver.

+
+
+errors = None
+

A dict of errors keyed by the Host against which they occurred.

+
+ +
+
+last_host = None
+

The last Host this operation was attempted against.

+
+ +
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.21.0-scylla/api/cassandra/auth.html b/3.21.0-scylla/api/cassandra/auth.html new file mode 100644 index 0000000000..c643c147d8 --- /dev/null +++ b/3.21.0-scylla/api/cassandra/auth.html @@ -0,0 +1,804 @@ + + + + + + + + + + + + + cassandra.auth - Authentication | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.auth - Authentication

+
+
+class cassandra.auth.AuthProvider
+

An abstract class that defines the interface that will be used for +creating Authenticator instances when opening new +connections to Cassandra.

+
+

New in version 2.0.0.

+
+
+
+new_authenticator(host)
+

Implementations of this class should return a new instance +of Authenticator or one of its subclasses.

+
+ +
+ +
+
+class cassandra.auth.Authenticator
+

An abstract class that handles SASL authentication with Cassandra servers.

+

Each time a new connection is created and the server requires authentication, +a new instance of this class will be created by the corresponding +AuthProvider to handler that authentication. The lifecycle of the +new Authenticator will the be:

+

1) The initial_response() method will be called. The return +value will be sent to the server to initiate the handshake.

+

2) The server will respond to each client response by either issuing a +challenge or indicating that the authentication is complete (successful or not). +If a new challenge is issued, evaluate_challenge() +will be called to produce a response that will be sent to the +server. This challenge/response negotiation will continue until the server +responds that authentication is successful (or an AuthenticationFailed +is raised).

+

3) When the server indicates that authentication is successful, +on_authentication_success() will be called a token string that +that the server may optionally have sent.

+

The exact nature of the negotiation between the client and server is specific +to the authentication mechanism configured server-side.

+
+

New in version 2.0.0.

+
+
+
+server_authenticator_class = None
+

Set during the connection AUTHENTICATE phase

+
+ +
+
+initial_response()
+

Returns an message to send to the server to initiate the SASL handshake. +None may be returned to send an empty message.

+
+ +
+
+evaluate_challenge(challenge)
+

Called when the server sends a challenge message. Generally, this method +should return None when authentication is complete from a +client perspective. Otherwise, a string should be returned.

+
+ +
+
+on_authentication_success(token)
+

Called when the server indicates that authentication was successful. +Depending on the authentication mechanism, token may be None +or a string.

+
+ +
+ +
+
+class cassandra.auth.PlainTextAuthProvider(username, password)
+

An AuthProvider that works with Cassandra’s PasswordAuthenticator.

+

Example usage:

+
from cassandra.cluster import Cluster
+from cassandra.auth import PlainTextAuthProvider
+
+auth_provider = PlainTextAuthProvider(
+        username='cassandra', password='cassandra')
+cluster = Cluster(auth_provider=auth_provider)
+
+
+
+

New in version 2.0.0.

+
+
+
+new_authenticator(host)
+

Implementations of this class should return a new instance +of Authenticator or one of its subclasses.

+
+ +
+ +
+
+class cassandra.auth.PlainTextAuthenticator(username, password)
+
+
+evaluate_challenge(challenge)
+

Called when the server sends a challenge message. Generally, this method +should return None when authentication is complete from a +client perspective. Otherwise, a string should be returned.

+
+ +
+ +
+
+class cassandra.auth.SaslAuthProvider(**sasl_kwargs)
+

An AuthProvider supporting general SASL auth mechanisms

+

Suitable for GSSAPI or other SASL mechanisms

+

Example usage:

+
from cassandra.cluster import Cluster
+from cassandra.auth import SaslAuthProvider
+
+sasl_kwargs = {'service': 'something',
+               'mechanism': 'GSSAPI',
+               'qops': 'auth'.split(',')}
+auth_provider = SaslAuthProvider(**sasl_kwargs)
+cluster = Cluster(auth_provider=auth_provider)
+
+
+
+

New in version 2.1.4.

+
+
+
+new_authenticator(host)
+

Implementations of this class should return a new instance +of Authenticator or one of its subclasses.

+
+ +
+ +
+
+class cassandra.auth.SaslAuthenticator(host, service, mechanism='GSSAPI', **sasl_kwargs)
+

A pass-through Authenticator using the third party package +‘pure-sasl’ for authentication

+
+

New in version 2.1.4.

+
+
+
+initial_response()
+

Returns an message to send to the server to initiate the SASL handshake. +None may be returned to send an empty message.

+
+ +
+
+evaluate_challenge(challenge)
+

Called when the server sends a challenge message. Generally, this method +should return None when authentication is complete from a +client perspective. Otherwise, a string should be returned.

+
+ +
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.21.0-scylla/api/cassandra/cluster.html b/3.21.0-scylla/api/cassandra/cluster.html new file mode 100644 index 0000000000..7b68c8364d --- /dev/null +++ b/3.21.0-scylla/api/cassandra/cluster.html @@ -0,0 +1,1752 @@ + + + + + + + + + + + + + cassandra.cluster - Clusters and Sessions | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.cluster - Clusters and Sessions

+
+
+class cassandra.cluster.Cluster([contact_points=('127.0.0.1',)][, port=9042][, executor_threads=2], **attr_kwargs)
+

The main class to use when interacting with a Cassandra cluster. +Typically, one instance of this class will be created for each +separate Cassandra cluster that your application interacts with.

+

Example usage:

+
>>> from cassandra.cluster import Cluster
+>>> cluster = Cluster(['192.168.1.1', '192.168.1.2'])
+>>> session = cluster.connect()
+>>> session.execute("CREATE KEYSPACE ...")
+>>> ...
+>>> cluster.shutdown()
+
+
+

Cluster and Session also provide context management functions +which implicitly handle shutdown when leaving scope.

+

executor_threads defines the number of threads in a pool for handling asynchronous tasks such as +extablishing connection pools or refreshing metadata.

+

Any of the mutable Cluster attributes may be set as keyword arguments to the constructor.

+
+
+contact_points = ['127.0.0.1']
+
+ +
+
+port = 9042
+
+ +
+
+cql_version = None
+
+ +
+
+protocol_version = 66
+
+ +
+
+compression = True
+
+ +
+
+auth_provider
+

When protocol_version is 2 or higher, this should +be an instance of a subclass of AuthProvider, +such as PlainTextAuthProvider.

+

When protocol_version is 1, this should be +a function that accepts one argument, the IP address of a node, +and returns a dict of credentials for that node.

+

When not using authentication, this should be left as None.

+
+ +
+
+load_balancing_policy
+

An instance of policies.LoadBalancingPolicy or +one of its subclasses.

+
+

Changed in version 2.6.0.

+
+

Defaults to TokenAwarePolicy (DCAwareRoundRobinPolicy). +when using CPython (where the murmur3 extension is available). DCAwareRoundRobinPolicy +otherwise. Default local DC will be chosen from contact points.

+

Please see DCAwareRoundRobinPolicy for a discussion on default behavior with respect to +DC locality and remote nodes.

+
+ +
+
+reconnection_policy = <cassandra.policies.ExponentialReconnectionPolicy object>
+
+ +
+
+default_retry_policy = <cassandra.policies.RetryPolicy object>
+

A default policies.RetryPolicy instance to use for all +Statement objects which do not have a retry_policy +explicitly set.

+
+ +
+
+conviction_policy_factory = <class 'cassandra.policies.SimpleConvictionPolicy'>
+
+ +
+
+address_translator = <cassandra.policies.IdentityTranslator object>
+
+ +
+
+metrics_enabled = False
+
+ +
+
+metrics = None
+
+ +
+
+ssl_context = None
+
+ +
+
+ssl_options = None
+
+ +
+
+sockopts = None
+
+ +
+
+max_schema_agreement_wait = 10
+
+ +
+
+metadata = None
+
+ +
+
+connection_class = <class 'cassandra.io.libevreactor.LibevConnection'>
+
+ +
+
+control_connection_timeout = 2.0
+
+ +
+
+idle_heartbeat_interval = 30
+
+ +
+
+idle_heartbeat_timeout = 30
+
+ +
+
+schema_event_refresh_window = 2
+
+ +
+
+topology_event_refresh_window = 10
+
+ +
+
+status_event_refresh_window = 2
+
+ +
+
+prepare_on_all_hosts = True
+
+ +
+
+reprepare_on_up = True
+
+ +
+
+connect_timeout = 5
+
+ +
+
+schema_metadata_enabled = True
+

Flag indicating whether internal schema metadata is updated.

+

When disabled, the driver does not populate Cluster.metadata.keyspaces on connect, or on schema change events. This +can be used to speed initial connection, and reduce load on client and server during operation. Turning this off +gives away token aware request routing, and programmatic inspection of the metadata model.

+
+ +
+
+token_metadata_enabled = True
+

Flag indicating whether internal token metadata is updated.

+

When disabled, the driver does not query node token information on connect, or on topology change events. This +can be used to speed initial connection, and reduce load on client and server during operation. It is most useful +in large clusters using vnodes, where the token map can be expensive to compute. Turning this off +gives away token aware request routing, and programmatic inspection of the token ring.

+
+ +
+
+timestamp_generator = None
+
+ +
+
+endpoint_factory = None
+
+ +
+
+cloud = None
+
+ +
+
+connect(keyspace=None, wait_for_all_pools=False)
+

Creates and returns a new Session object.

+

If keyspace is specified, that keyspace will be the default keyspace for +operations on the Session.

+

wait_for_all_pools specifies whether this call should wait for all connection pools to be +established or attempted. Default is False, which means it will return when the first +successful connection is established. Remaining pools are added asynchronously.

+
+ +
+
+shutdown()
+

Closes all sessions and connection associated with this Cluster. +To ensure all connections are properly closed, you should always +call shutdown() on a Cluster instance when you are done with it.

+

Once shutdown, a Cluster should not be used for any purpose.

+
+ +
+
+register_user_type(keyspace, user_type, klass)
+

Registers a class to use to represent a particular user-defined type. +Query parameters for this user-defined type will be assumed to be +instances of klass. Result sets for this user-defined type will +be instances of klass. If no class is registered for a user-defined +type, a namedtuple will be used for result sets, and non-prepared +statements may not encode parameters for this type correctly.

+

keyspace is the name of the keyspace that the UDT is defined in.

+

user_type is the string name of the UDT to register the mapping +for.

+

klass should be a class with attributes whose names match the +fields of the user-defined type. The constructor must accepts kwargs +for each of the fields in the UDT.

+

This method should only be called after the type has been created +within Cassandra.

+

Example:

+
cluster = Cluster(protocol_version=3)
+session = cluster.connect()
+session.set_keyspace('mykeyspace')
+session.execute("CREATE TYPE address (street text, zipcode int)")
+session.execute("CREATE TABLE users (id int PRIMARY KEY, location address)")
+
+# create a class to map to the "address" UDT
+class Address(object):
+
+    def __init__(self, street, zipcode):
+        self.street = street
+        self.zipcode = zipcode
+
+cluster.register_user_type('mykeyspace', 'address', Address)
+
+# insert a row using an instance of Address
+session.execute("INSERT INTO users (id, location) VALUES (%s, %s)",
+                (0, Address("123 Main St.", 78723)))
+
+# results will include Address instances
+results = session.execute("SELECT * FROM users")
+row = results[0]
+print row.id, row.location.street, row.location.zipcode
+
+
+
+ +
+
+register_listener(listener)
+

Adds a cassandra.policies.HostStateListener subclass instance to +the list of listeners to be notified when a host is added, removed, +marked up, or marked down.

+
+ +
+
+unregister_listener(listener)
+

Removes a registered listener.

+
+ +
+
+add_execution_profile(name, profile, pool_wait_timeout=5)
+

Adds an ExecutionProfile to the cluster. This makes it available for use by name in Session.execute() +and Session.execute_async(). This method will raise if the profile already exists.

+

Normally profiles will be injected at cluster initialization via Cluster(execution_profiles). This method +provides a way of adding them dynamically.

+

Adding a new profile updates the connection pools according to the specified load_balancing_policy. By default, +this method will wait up to five seconds for the pool creation to complete, so the profile can be used immediately +upon return. This behavior can be controlled using pool_wait_timeout (see +concurrent.futures.wait +for timeout semantics).

+
+ +
+
+set_max_requests_per_connection(host_distance, max_requests)
+

Sets a threshold for concurrent requests per connection, above which new +connections will be created to a host (up to max connections; +see set_max_connections_per_host()).

+

Pertains to connection pool management in protocol versions {1,2}.

+
+ +
+
+get_max_requests_per_connection(host_distance)
+
+ +
+
+set_min_requests_per_connection(host_distance, min_requests)
+

Sets a threshold for concurrent requests per connection, below which +connections will be considered for disposal (down to core connections; +see set_core_connections_per_host()).

+

Pertains to connection pool management in protocol versions {1,2}.

+
+ +
+
+get_min_requests_per_connection(host_distance)
+
+ +
+
+get_core_connections_per_host(host_distance)
+

Gets the minimum number of connections per Session that will be opened +for each host with HostDistance equal to host_distance. +The default is 2 for LOCAL and 1 for +REMOTE.

+

This property is ignored if protocol_version is +3 or higher.

+
+ +
+
+set_core_connections_per_host(host_distance, core_connections)
+

Sets the minimum number of connections per Session that will be opened +for each host with HostDistance equal to host_distance. +The default is 2 for LOCAL and 1 for +REMOTE.

+

Protocol version 1 and 2 are limited in the number of concurrent +requests they can send per connection. The driver implements connection +pooling to support higher levels of concurrency.

+

If protocol_version is set to 3 or higher, this +is not supported (there is always one connection per host, unless +the host is remote and connect_to_remote_hosts is False) +and using this will result in an UnsupportedOperation.

+
+ +
+
+get_max_connections_per_host(host_distance)
+

Gets the maximum number of connections per Session that will be opened +for each host with HostDistance equal to host_distance. +The default is 8 for LOCAL and 2 for +REMOTE.

+

This property is ignored if protocol_version is +3 or higher.

+
+ +
+
+set_max_connections_per_host(host_distance, max_connections)
+

Sets the maximum number of connections per Session that will be opened +for each host with HostDistance equal to host_distance. +The default is 2 for LOCAL and 1 for +REMOTE.

+

If protocol_version is set to 3 or higher, this +is not supported (there is always one connection per host, unless +the host is remote and connect_to_remote_hosts is False) +and using this will result in an UnsupportedOperation.

+
+ +
+
+get_control_connection_host()
+

Returns the control connection host metadata.

+
+ +
+
+refresh_schema_metadata(max_schema_agreement_wait=None)
+

Synchronously refresh all schema metadata.

+

By default, the timeout for this operation is governed by max_schema_agreement_wait +and control_connection_timeout.

+

Passing max_schema_agreement_wait here overrides max_schema_agreement_wait.

+

Setting max_schema_agreement_wait <= 0 will bypass schema agreement and refresh schema immediately.

+

An Exception is raised if schema refresh fails for any reason.

+
+ +
+
+refresh_keyspace_metadata(keyspace, max_schema_agreement_wait=None)
+

Synchronously refresh keyspace metadata. This applies to keyspace-level information such as replication +and durability settings. It does not refresh tables, types, etc. contained in the keyspace.

+

See refresh_schema_metadata() for description of max_schema_agreement_wait behavior

+
+ +
+
+refresh_table_metadata(keyspace, table, max_schema_agreement_wait=None)
+

Synchronously refresh table metadata. This applies to a table, and any triggers or indexes attached +to the table.

+

See refresh_schema_metadata() for description of max_schema_agreement_wait behavior

+
+ +
+
+refresh_user_type_metadata(keyspace, user_type, max_schema_agreement_wait=None)
+

Synchronously refresh user defined type metadata.

+

See refresh_schema_metadata() for description of max_schema_agreement_wait behavior

+
+ +
+
+refresh_user_function_metadata(keyspace, function, max_schema_agreement_wait=None)
+

Synchronously refresh user defined function metadata.

+

function is a cassandra.UserFunctionDescriptor.

+

See refresh_schema_metadata() for description of max_schema_agreement_wait behavior

+
+ +
+
+refresh_user_aggregate_metadata(keyspace, aggregate, max_schema_agreement_wait=None)
+

Synchronously refresh user defined aggregate metadata.

+

aggregate is a cassandra.UserAggregateDescriptor.

+

See refresh_schema_metadata() for description of max_schema_agreement_wait behavior

+
+ +
+
+refresh_nodes(force_token_rebuild=False)
+

Synchronously refresh the node list and token metadata

+

force_token_rebuild can be used to rebuild the token map metadata, even if no new nodes are discovered.

+

An Exception is raised if node refresh fails for any reason.

+
+ +
+
+set_meta_refresh_enabled(enabled)
+

Deprecated: set schema_metadata_enabled token_metadata_enabled instead

+

Sets a flag to enable (True) or disable (False) all metadata refresh queries. +This applies to both schema and node topology.

+

Disabling this is useful to minimize refreshes during multiple changes.

+

Meta refresh must be enabled for the driver to become aware of any cluster +topology changes or schema updates.

+
+ +
+ +
+
+class cassandra.cluster.ExecutionProfile(load_balancing_policy=<object object>, retry_policy=None, consistency_level=LOCAL_ONE, serial_consistency_level=None, request_timeout=10.0, row_factory=<function named_tuple_factory>, speculative_execution_policy=None)
+
+
+consistency_level = LOCAL_ONE
+
+ +
+
+static row_factory(colnames, rows)
+

Returns each row as a namedtuple. +This is the default row factory.

+

Example:

+
>>> from cassandra.query import named_tuple_factory
+>>> session = cluster.connect('mykeyspace')
+>>> session.row_factory = named_tuple_factory
+>>> rows = session.execute("SELECT name, age FROM users LIMIT 1")
+>>> user = rows[0]
+
+>>> # you can access field by their name:
+>>> print "name: %s, age: %d" % (user.name, user.age)
+name: Bob, age: 42
+
+>>> # or you can access fields by their position (like a tuple)
+>>> name, age = user
+>>> print "name: %s, age: %d" % (name, age)
+name: Bob, age: 42
+>>> name = user[0]
+>>> age = user[1]
+>>> print "name: %s, age: %d" % (name, age)
+name: Bob, age: 42
+
+
+
+

Changed in version 2.0.0: moved from cassandra.decoder to cassandra.query

+
+
+ +
+ +
+
+cassandra.cluster.EXEC_PROFILE_DEFAULT
+

The most base type

+
+ +
+
+cassandra.cluster.EXEC_PROFILE_GRAPH_DEFAULT
+

The most base type

+
+ +
+
+cassandra.cluster.EXEC_PROFILE_GRAPH_SYSTEM_DEFAULT
+

The most base type

+
+ +
+
+cassandra.cluster.EXEC_PROFILE_GRAPH_ANALYTICS_DEFAULT
+

The most base type

+
+ +
+
+class cassandra.cluster.Session
+

A collection of connection pools for each host in the cluster. +Instances of this class should not be created directly, only +using Cluster.connect().

+

Queries and statements can be executed through Session instances +using the execute() and execute_async() +methods.

+

Example usage:

+
>>> session = cluster.connect()
+>>> session.set_keyspace("mykeyspace")
+>>> session.execute("SELECT * FROM mycf")
+
+
+
+
+default_timeout = 10.0
+

A default timeout, measured in seconds, for queries executed through +execute() or execute_async(). This default may be +overridden with the timeout parameter for either of those methods.

+

Setting this to None will cause no timeouts to be set by default.

+

Please see ResponseFuture.result() for details on the scope and +effect of this timeout.

+
+

New in version 2.0.0.

+
+
+ +
+
+default_consistency_level = LOCAL_ONE
+

Deprecated: use execution profiles instead +The default ConsistencyLevel for operations executed through +this session. This default may be overridden by setting the +consistency_level on individual statements.

+
+

New in version 1.2.0.

+
+
+

Changed in version 3.0.0: default changed from ONE to LOCAL_ONE

+
+
+ +
+
+default_serial_consistency_level = None
+

The default ConsistencyLevel for serial phase of conditional updates executed through +this session. This default may be overridden by setting the +serial_consistency_level on individual statements.

+

Only valid for protocol_version >= 2.

+
+ +
+
+row_factory = <function named_tuple_factory>
+

The format to return row results in. By default, each +returned row will be a named tuple. You can alternatively +use any of the following:

+ +
+ +
+
+default_fetch_size = 5000
+
+ +
+
+use_client_timestamp = True
+
+ +
+
+timestamp_generator = None
+
+ +
+
+encoder = None
+
+ +
+
+client_protocol_handler = <class 'cassandra.protocol.cython_protocol_handler.<locals>.CythonProtocolHandler'>
+
+ +
+
+execute(statement[, parameters][, timeout][, trace][, custom_payload][, paging_state][, host][, execute_as])
+

Execute the given query and synchronously wait for the response.

+

If an error is encountered while executing the query, an Exception +will be raised.

+

query may be a query string or an instance of cassandra.query.Statement.

+

parameters may be a sequence or dict of parameters to bind. If a +sequence is used, %s should be used the placeholder for each +argument. If a dict is used, %(name)s style placeholders must +be used.

+

timeout should specify a floating-point timeout (in seconds) after +which an OperationTimedOut exception will be raised if the query +has not completed. If not set, the timeout defaults to the request_timeout of the selected execution_profile. +If set to None, there is no timeout. Please see ResponseFuture.result() for details on +the scope and effect of this timeout.

+

If trace is set to True, the query will be sent with tracing enabled. +The trace details can be obtained using the returned ResultSet object.

+

custom_payload is a Custom Payloads dict to be passed to the server. +If query is a Statement with its own custom_payload. The message payload +will be a union of the two, with the values specified here taking precedence.

+

execution_profile is the execution profile to use for this request. It can be a key to a profile configured +via Cluster.add_execution_profile() or an instance (from Session.execution_profile_clone_update(), +for example

+

paging_state is an optional paging state, reused from a previous ResultSet.

+

host is the cassandra.pool.Host that should handle the query. If the host specified is down or +not yet connected, the query will fail with NoHostAvailable. Using this is +discouraged except in a few cases, e.g., querying node-local tables and applying schema changes.

+

execute_as the user that will be used on the server to execute the request. This is only available +on a DSE cluster.

+
+ +
+
+execute_async(statement[, parameters][, trace][, custom_payload][, paging_state][, host][, execute_as])
+

Execute the given query and return a ResponseFuture object +which callbacks may be attached to for asynchronous response +delivery. You may also call result() +on the ResponseFuture to synchronously block for results at +any time.

+

See Session.execute() for parameter definitions.

+

Example usage:

+
>>> session = cluster.connect()
+>>> future = session.execute_async("SELECT * FROM mycf")
+
+>>> def log_results(results):
+...     for row in results:
+...         log.info("Results: %s", row)
+
+>>> def log_error(exc):
+>>>     log.error("Operation failed: %s", exc)
+
+>>> future.add_callbacks(log_results, log_error)
+
+
+

Async execution with blocking wait for results:

+
>>> future = session.execute_async("SELECT * FROM mycf")
+>>> # do other stuff...
+
+>>> try:
+...     results = future.result()
+... except Exception:
+...     log.exception("Operation failed:")
+
+
+
+ +
+
+execute_graph(statement[, parameters][, trace][, execution_profile=EXEC_PROFILE_GRAPH_DEFAULT][, execute_as])
+

Executes a Gremlin query string or GraphStatement synchronously, +and returns a ResultSet from this execution.

+

parameters is dict of named parameters to bind. The values must be +JSON-serializable.

+

execution_profile: Selects an execution profile for the request.

+

execute_as the user that will be used on the server to execute the request.

+
+ +
+
+execute_graph_async(statement[, parameters][, trace][, execution_profile=EXEC_PROFILE_GRAPH_DEFAULT][, execute_as])
+

Execute the graph query and return a ResponseFuture +object which callbacks may be attached to for asynchronous response delivery. You may also call ResponseFuture.result() to synchronously block for +results at any time.

+
+ +
+
+prepare(statement)
+

Prepares a query string, returning a PreparedStatement +instance which can be used as follows:

+
>>> session = cluster.connect("mykeyspace")
+>>> query = "INSERT INTO users (id, name, age) VALUES (?, ?, ?)"
+>>> prepared = session.prepare(query)
+>>> session.execute(prepared, (user.id, user.name, user.age))
+
+
+

Or you may bind values to the prepared statement ahead of time:

+
>>> prepared = session.prepare(query)
+>>> bound_stmt = prepared.bind((user.id, user.name, user.age))
+>>> session.execute(bound_stmt)
+
+
+

Of course, prepared statements may (and should) be reused:

+
>>> prepared = session.prepare(query)
+>>> for user in users:
+...     bound = prepared.bind((user.id, user.name, user.age))
+...     session.execute(bound)
+
+
+

Alternatively, if protocol_version is 5 or higher +(requires Cassandra 4.0+), the keyspace can be specified as a +parameter. This will allow you to avoid specifying the keyspace in the +query without specifying a keyspace in connect(). It +even will let you prepare and use statements against a keyspace other +than the one originally specified on connection:

+
>>> analyticskeyspace_prepared = session.prepare(
+...     "INSERT INTO user_activity id, last_activity VALUES (?, ?)",
+...     keyspace="analyticskeyspace")  # note the different keyspace
+
+
+

Important: PreparedStatements should be prepared only once. +Preparing the same query more than once will likely affect performance.

+

custom_payload is a key value map to be passed along with the prepare +message. See Custom Payloads.

+
+ +
+
+shutdown()
+

Close all connections. Session instances should not be used +for any purpose after being shutdown.

+
+ +
+
+set_keyspace(keyspace)
+

Set the default keyspace for all queries made through this Session. +This operation blocks until complete.

+
+ +
+
+get_execution_profile(name)
+

Returns the execution profile associated with the provided name.

+
+
Parameters
+

name – The name (or key) of the execution profile.

+
+
+
+ +
+
+execution_profile_clone_update(ep, **kwargs)
+

Returns a clone of the ep profile. kwargs can be specified to update attributes +of the returned profile.

+

This is a shallow clone, so any objects referenced by the profile are shared. This means Load Balancing Policy +is maintained by inclusion in the active profiles. It also means updating any other rich objects will be seen +by the active profile. In cases where this is not desirable, be sure to replace the instance instead of manipulating +the shared object.

+
+ +
+
+add_request_init_listener(fn, *args, **kwargs)
+

Adds a callback with arguments to be called when any request is created.

+

It will be invoked as fn(response_future, *args, **kwargs) after each client request is created, +and before the request is sent. This can be used to create extensions by adding result callbacks to the +response future.

+

response_future is the ResponseFuture for the request.

+

Note that the init callback is done on the client thread creating the request, so you may need to consider +synchronization if you have multiple threads. Any callbacks added to the response future will be executed +on the event loop thread, so the normal advice about minimizing cycles and avoiding blocking apply (see Note in +ResponseFuture.add_callbacks().

+

See this example in the +source tree for an example.

+
+ +
+
+remove_request_init_listener(fn, *args, **kwargs)
+

Removes a callback and arguments from the list.

+

See Session.add_request_init_listener().

+
+ +
+ +
+
+class cassandra.cluster.ResponseFuture
+

An asynchronous response delivery mechanism that is returned from calls +to Session.execute_async().

+
+
There are two ways for results to be delivered:
+
+
+
+
+query = None
+
+ +
+
+result()
+

Return the final result or raise an Exception if errors were +encountered. If the final result or error has not been set +yet, this method will block until it is set, or the timeout +set for the request expires.

+

Timeout is specified in the Session request execution functions. +If the timeout is exceeded, an cassandra.OperationTimedOut will be raised. +This is a client-side timeout. For more information +about server-side coordinator timeouts, see policies.RetryPolicy.

+

Example usage:

+
>>> future = session.execute_async("SELECT * FROM mycf")
+>>> # do other stuff...
+
+>>> try:
+...     rows = future.result()
+...     for row in rows:
+...         ... # process results
+... except Exception:
+...     log.exception("Operation failed:")
+
+
+
+ +
+
+get_query_trace()
+

Fetches and returns the query trace of the last response, or None if tracing was +not enabled.

+

Note that this may raise an exception if there are problems retrieving the trace +details from Cassandra. If the trace is not available after max_wait, +cassandra.query.TraceUnavailable will be raised.

+

If the ResponseFuture is not done (async execution) and you try to retrieve the trace, +cassandra.query.TraceUnavailable will be raised.

+

query_cl is the consistency level used to poll the trace tables.

+
+ +
+
+get_all_query_traces()
+

Fetches and returns the query traces for all query pages, if tracing was enabled.

+

See note in get_query_trace() regarding possible exceptions.

+
+ +
+
+custom_payload
+

The custom payload returned from the server, if any. This will only be +set by Cassandra servers implementing a custom QueryHandler, and only +for protocol_version 4+.

+

Ensure the future is complete before trying to access this property +(call result(), or after callback is invoked). +Otherwise it may throw if the response has not been received.

+
+
Returns
+

Custom Payloads.

+
+
+
+ +
+
+is_schema_agreed = True
+
+ +
+
+has_more_pages
+

Returns True if there are more pages left in the +query results, False otherwise. This should only +be checked after the first page has been returned.

+
+

New in version 2.0.0.

+
+
+ +
+
+warnings
+

Warnings returned from the server, if any. This will only be +set for protocol_version 4+.

+

Warnings may be returned for such things as oversized batches, +or too many tombstones in slice queries.

+

Ensure the future is complete before trying to access this property +(call result(), or after callback is invoked). +Otherwise it may throw if the response has not been received.

+
+ +
+
+start_fetching_next_page()
+

If there are more pages left in the query result, this asynchronously +starts fetching the next page. If there are no pages left, QueryExhausted +is raised. Also see has_more_pages.

+

This should only be called after the first page has been returned.

+
+

New in version 2.0.0.

+
+
+ +
+
+add_callback(fn, *args, **kwargs)
+

Attaches a callback function to be called when the final results arrive.

+

By default, fn will be called with the results as the first and only +argument. If *args or **kwargs are supplied, they will be passed +through as additional positional or keyword arguments to fn.

+

If an error is hit while executing the operation, a callback attached +here will not be called. Use add_errback() or add_callbacks() +if you wish to handle that case.

+

If the final result has already been seen when this method is called, +the callback will be called immediately (before this method returns).

+

Note: in the case that the result is not available when the callback is added, +the callback is executed by IO event thread. This means that the callback +should not block or attempt further synchronous requests, because no further +IO will be processed until the callback returns.

+

Important: if the callback you attach results in an exception being +raised, the exception will be ignored, so please ensure your +callback handles all error cases that you care about.

+

Usage example:

+
>>> session = cluster.connect("mykeyspace")
+
+>>> def handle_results(rows, start_time, should_log=False):
+...     if should_log:
+...         log.info("Total time: %f", time.time() - start_time)
+...     ...
+
+>>> future = session.execute_async("SELECT * FROM users")
+>>> future.add_callback(handle_results, time.time(), should_log=True)
+
+
+
+ +
+
+add_errback(fn, *args, **kwargs)
+

Like add_callback(), but handles error cases. +An Exception instance will be passed as the first positional argument +to fn.

+
+ +
+
+ResponseFuture.add_callbacks(callback, errback, callback_args=(), callback_kwargs=None, errback_args=(), errback_args=None)
+

A convenient combination of add_callback() and +add_errback().

+

Example usage:

+
>>> session = cluster.connect()
+>>> query = "SELECT * FROM mycf"
+>>> future = session.execute_async(query)
+
+>>> def log_results(results, level='debug'):
+...     for row in results:
+...         log.log(level, "Result: %s", row)
+
+>>> def log_error(exc, query):
+...     log.error("Query '%s' failed: %s", query, exc)
+
+>>> future.add_callbacks(
+...     callback=log_results, callback_kwargs={'level': 'info'},
+...     errback=log_error, errback_args=(query,))
+
+
+
+ +
+ +
+
+class cassandra.cluster.ResultSet
+

An iterator over the rows from a query result. Also supplies basic equality +and indexing methods for backward-compatability. These methods materialize +the entire result set (loading all pages), and should only be used if the +total result size is understood. Warnings are emitted when paged results +are materialized in this fashion.

+

You can treat this as a normal iterator over rows:

+
>>> from cassandra.query import SimpleStatement
+>>> statement = SimpleStatement("SELECT * FROM users", fetch_size=10)
+>>> for user_row in session.execute(statement):
+...     process_user(user_row)
+
+
+

Whenever there are no more rows in the current page, the next page will +be fetched transparently. However, note that it is possible for +an Exception to be raised while fetching the next page, just +like you might see on a normal call to session.execute().

+
+
+all()
+

Returns all the remaining rows as a list. This is basically +a convenient shortcut to list(result_set).

+

This function is not recommended for queries that return a large number of elements.

+
+ +
+
+property current_rows
+

The list of current page rows. May be empty if the result was empty, +or this is the last page.

+
+ +
+
+fetch_next_page()
+

Manually, synchronously fetch the next page. Supplied for manually retrieving pages +and inspecting current_page(). It is not necessary to call this when iterating +through results; paging happens implicitly in iteration.

+
+ +
+
+get_all_query_traces(max_wait_sec_per=None)
+

Gets all query traces from the associated future. +See ResponseFuture.get_all_query_traces() for details.

+
+ +
+
+get_query_trace(max_wait_sec=None)
+

Gets the last query trace from the associated future. +See ResponseFuture.get_query_trace() for details.

+
+ +
+
+property has_more_pages
+

True if the last response indicated more pages; False otherwise

+
+ +
+
+one()
+

Return a single row of the results or None if empty. This is basically +a shortcut to result_set.current_rows[0] and should only be used when +you know a query returns a single row. Consider using an iterator if the +ResultSet contains more than one row.

+
+ +
+
+property paging_state
+

Server paging state of the query. Can be None if the query was not paged.

+

The driver treats paging state as opaque, but it may contain primary key data, so applications may want to +avoid sending this to untrusted parties.

+
+ +
+
+property was_applied
+

For LWT results, returns whether the transaction was applied.

+

Result is indeterminate if called on a result that was not an LWT request or on +a query.BatchStatement containing LWT. In the latter case either all the batch +succeeds or fails.

+

Only valid when one of the of the internal row factories is in use.

+
+ +
+ +
+
+exception cassandra.cluster.QueryExhausted
+

Raised when ResponseFuture.start_fetching_next_page() is called and +there are no more pages. You can check ResponseFuture.has_more_pages +before calling to avoid this.

+
+

New in version 2.0.0.

+
+
+ +
+
+exception cassandra.cluster.NoHostAvailable
+

Raised when an operation is attempted but all connections are +busy, defunct, closed, or resulted in errors when used.

+
+ +
+
+exception cassandra.cluster.UserTypeDoesNotExist
+

An attempt was made to use a user-defined type that does not exist.

+
+

New in version 2.1.0.

+
+
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.21.0-scylla/api/cassandra/concurrent.html b/3.21.0-scylla/api/cassandra/concurrent.html new file mode 100644 index 0000000000..e4b66a5bc3 --- /dev/null +++ b/3.21.0-scylla/api/cassandra/concurrent.html @@ -0,0 +1,708 @@ + + + + + + + + + + + + + cassandra.concurrent - Utilities for Concurrent Statement Execution | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.concurrent - Utilities for Concurrent Statement Execution

+
+
+cassandra.concurrent.execute_concurrent(session, statements_and_parameters, concurrency=100, raise_on_first_error=True, results_generator=False, execution_profile=<object object>)
+

Executes a sequence of (statement, parameters) tuples concurrently. Each +parameters item must be a sequence or None.

+

The concurrency parameter controls how many statements will be executed +concurrently. When Cluster.protocol_version is set to 1 or 2, +it is recommended that this be kept below 100 times the number of +core connections per host times the number of connected hosts (see +Cluster.set_core_connections_per_host()). If that amount is exceeded, +the event loop thread may attempt to block on new connection creation, +substantially impacting throughput. If protocol_version +is 3 or higher, you can safely experiment with higher levels of concurrency.

+

If raise_on_first_error is left as True, execution will stop +after the first failed statement and the corresponding exception will be +raised.

+

results_generator controls how the results are returned.

+
    +
  • If False, the results are returned only after all requests have completed.

  • +
  • If True, a generator expression is returned. Using a generator results in a constrained +memory footprint when the results set will be large – results are yielded +as they return instead of materializing the entire list at once. The trade for lower memory +footprint is marginal CPU overhead (more thread coordination and sorting out-of-order results +on-the-fly).

  • +
+

execution_profile argument is the execution profile to use for this +request, it is passed directly to Session.execute_async().

+

A sequence of ExecutionResult(success, result_or_exc) namedtuples is returned +in the same order that the statements were passed in. If success is False, +there was an error executing the statement, and result_or_exc will be +an Exception. If success is True, result_or_exc +will be the query result.

+

Example usage:

+
select_statement = session.prepare("SELECT * FROM users WHERE id=?")
+
+statements_and_params = []
+for user_id in user_ids:
+    params = (user_id, )
+    statements_and_params.append((select_statement, params))
+
+results = execute_concurrent(
+    session, statements_and_params, raise_on_first_error=False)
+
+for (success, result) in results:
+    if not success:
+        handle_error(result)  # result will be an Exception
+    else:
+        process_user(result[0])  # result will be a list of rows
+
+
+

Note: in the case that generators are used, it is important to ensure the consumers do not +block or attempt further synchronous requests, because no further IO will be processed until +the consumer returns. This may also produce a deadlock in the IO event thread.

+
+ +
+
+cassandra.concurrent.execute_concurrent_with_args(session, statement, parameters, *args, **kwargs)
+

Like execute_concurrent(), but takes a single +statement and a sequence of parameters. Each item in parameters +should be a sequence or None.

+

Example usage:

+
statement = session.prepare("INSERT INTO mytable (a, b) VALUES (1, ?)")
+parameters = [(x,) for x in range(1000)]
+execute_concurrent_with_args(session, statement, parameters, concurrency=50)
+
+
+
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.21.0-scylla/api/cassandra/connection.html b/3.21.0-scylla/api/cassandra/connection.html new file mode 100644 index 0000000000..1406327bb8 --- /dev/null +++ b/3.21.0-scylla/api/cassandra/connection.html @@ -0,0 +1,736 @@ + + + + + + + + + + + + + cassandra.connection - Low Level Connection Info | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.connection - Low Level Connection Info

+
+
+exception cassandra.connection.ConnectionException
+

An unrecoverable error was hit when attempting to use a connection, +or the connection was already closed or defunct.

+
+ +
+
+exception cassandra.connection.ConnectionShutdown
+

Raised when a connection has been marked as defunct or has been closed.

+
+ +
+
+exception cassandra.connection.ConnectionBusy
+

An attempt was made to send a message through a Connection that +was already at the max number of in-flight operations.

+
+ +
+
+exception cassandra.connection.ProtocolError
+

Communication did not match the protocol that this driver expects.

+
+ +
+
+class cassandra.connection.EndPoint
+

Represents the information to connect to a cassandra node.

+
+
+property address
+

The IP address of the node. This is the RPC address the driver uses when connecting to the node

+
+ +
+
+property port
+

The port of the node.

+
+ +
+
+resolve()
+

Resolve the endpoint to an address/port. This is called +only on socket connection.

+
+ +
+
+property socket_family
+

The socket family of the endpoint.

+
+ +
+
+property ssl_options
+

SSL options specific to this endpoint.

+
+ +
+ +
+
+class cassandra.connection.EndPointFactory
+
+
+configure(cluster)
+

This is called by the cluster during its initialization.

+
+ +
+
+create(row)
+

Create an EndPoint from a system.peers row.

+
+ +
+ +
+
+class cassandra.connection.SniEndPoint(proxy_address, server_name, port=9042)
+

SNI Proxy EndPoint implementation.

+
+ +
+
+class cassandra.connection.SniEndPointFactory(proxy_address, port, node_domain=None)
+
+ +
+
+class cassandra.connection.UnixSocketEndPoint(unix_socket_path)
+

Unix Socket EndPoint implementation.

+
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.21.0-scylla/api/cassandra/cqlengine/columns.html b/3.21.0-scylla/api/cassandra/cqlengine/columns.html new file mode 100644 index 0000000000..5911e9b5af --- /dev/null +++ b/3.21.0-scylla/api/cassandra/cqlengine/columns.html @@ -0,0 +1,954 @@ + + + + + + + + + + + + + cassandra.cqlengine.columns - Column types for object mapping models | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.cqlengine.columns - Column types for object mapping models

+
+

Columns

+

Columns in your models map to columns in your CQL table. You define CQL columns by defining column attributes on your model classes. +For a model to be valid it needs at least one primary key column and one non-primary key column.

+

Just as in CQL, the order you define your columns in is important, and is the same order they are defined in on a model’s corresponding table.

+

Each column on your model definitions needs to be an instance of a Column class.

+
+
+class cassandra.cqlengine.columns.Column(**kwargs)
+
+
+primary_key = False
+

bool flag, indicates this column is a primary key. The first primary key defined +on a model is the partition key (unless partition keys are set), all others are cluster keys

+
+ +
+
+partition_key = False
+

indicates that this column should be the partition key, defining +more than one partition key column creates a compound partition key

+
+ +
+
+index = False
+

bool flag, indicates an index should be created for this column

+
+ +
+
+custom_index = False
+

bool flag, indicates an index is managed outside of cqlengine. This is +useful if you want to do filter queries on fields that have custom +indexes.

+
+ +
+
+db_field = None
+

the fieldname this field will map to in the database

+
+ +
+
+default = None
+

the default value, can be a value or a callable (no args)

+
+ +
+
+required = False
+

boolean, is the field required? Model validation will raise and +exception if required is set to True and there is a None value assigned

+
+ +
+
+clustering_order = None
+

only applicable on clustering keys (primary keys that are not partition keys) +determines the order that the clustering keys are sorted on disk

+
+ +
+
+discriminator_column = False
+

boolean, if set to True, this column will be used for discriminating records +of inherited models.

+

Should only be set on a column of an abstract model being used for inheritance.

+

There may only be one discriminator column per model. See __discriminator_value__ +for how to specify the value of this column on specialized models.

+
+ +
+
+static = False
+

boolean, if set to True, this is a static column, with a single value per partition

+
+ +
+ +
+
+

Column Types

+

Columns of all types are initialized by passing Column attributes to the constructor by keyword.

+
+
+class cassandra.cqlengine.columns.Ascii(**kwargs)
+

Stores a US-ASCII character string

+
+
Parameters
+
    +
  • min_length (int) – Sets the minimum length of this string, for validation purposes. +Defaults to 1 if this is a required column. Otherwise, None.

  • +
  • max_length (int) – Sets the maximum length of this string, for validation purposes.

  • +
+
+
+
+ +
+
+class cassandra.cqlengine.columns.BigInt(**kwargs)
+

Stores a 64-bit signed integer value

+
+ +
+
+class cassandra.cqlengine.columns.Blob(**kwargs)
+

Stores a raw binary value

+
+ +
+
+cassandra.cqlengine.columns.Bytes
+

alias of cassandra.cqlengine.columns.Blob

+
+ +
+
+class cassandra.cqlengine.columns.Boolean(**kwargs)
+

Stores a boolean True or False value

+
+ +
+
+class cassandra.cqlengine.columns.Counter(index=False, db_field=None, required=False)
+

Stores a counter that can be incremented and decremented

+
+ +
+
+class cassandra.cqlengine.columns.Date(**kwargs)
+

Stores a simple date, with no time-of-day

+
+

Changed in version 2.6.0: removed overload of Date and DateTime. DateTime is a drop-in replacement for legacy models

+
+

requires C* 2.2+ and protocol v4+

+
+ +
+
+class cassandra.cqlengine.columns.DateTime(**kwargs)
+

Stores a datetime value

+
+
+truncate_microseconds = False
+

Set this True to have model instances truncate the date, quantizing it in the same way it will be in the database. +This allows equality comparison between assigned values and values read back from the database:

+
DateTime.truncate_microseconds = True
+assert Model.create(id=0, d=datetime.utcnow()) == Model.objects(id=0).first()
+
+
+

Defaults to False to preserve legacy behavior. May change in the future.

+
+ +
+ +
+
+class cassandra.cqlengine.columns.Decimal(**kwargs)
+

Stores a variable precision decimal value

+
+ +
+
+class cassandra.cqlengine.columns.Double(**kwargs)
+

Stores a double-precision floating-point value

+
+ +
+
+class cassandra.cqlengine.columns.Float(primary_key=False, partition_key=False, index=False, db_field=None, default=None, required=False, clustering_order=None, discriminator_column=False, static=False, custom_index=False)
+

Stores a single-precision floating-point value

+
+ +
+
+class cassandra.cqlengine.columns.Integer(**kwargs)
+

Stores a 32-bit signed integer value

+
+ +
+
+class cassandra.cqlengine.columns.List(value_type, default=<class 'list'>, **kwargs)
+

Stores a list of ordered values

+

http://www.datastax.com/documentation/cql/3.1/cql/cql_using/use_list_t.html

+
+
Parameters
+

value_type – a column class indicating the types of the value

+
+
+
+ +
+
+class cassandra.cqlengine.columns.Map(key_type, value_type, default=<class 'dict'>, **kwargs)
+

Stores a key -> value map (dictionary)

+

https://docs.datastax.com/en/dse/6.7/cql/cql/cql_using/useMap.html

+
+
Parameters
+
    +
  • key_type – a column class indicating the types of the key

  • +
  • value_type – a column class indicating the types of the value

  • +
+
+
+
+ +
+
+class cassandra.cqlengine.columns.Set(value_type, strict=True, default=<class 'set'>, **kwargs)
+

Stores a set of unordered, unique values

+

http://www.datastax.com/documentation/cql/3.1/cql/cql_using/use_set_t.html

+
+
Parameters
+
    +
  • value_type – a column class indicating the types of the value

  • +
  • strict – sets whether non set values will be coerced to set +type on validation, or raise a validation error, defaults to True

  • +
+
+
+
+ +
+
+class cassandra.cqlengine.columns.SmallInt(**kwargs)
+

Stores a 16-bit signed integer value

+
+

New in version 2.6.0.

+
+

requires C* 2.2+ and protocol v4+

+
+ +
+
+class cassandra.cqlengine.columns.Text(min_length=None, max_length=None, **kwargs)
+

Stores a UTF-8 encoded string

+
+
Parameters
+
    +
  • min_length (int) – Sets the minimum length of this string, for validation purposes. +Defaults to 1 if this is a required column. Otherwise, None.

  • +
  • max_length (int) – Sets the maximum length of this string, for validation purposes.

  • +
+
+
+
+ +
+
+class cassandra.cqlengine.columns.Time(**kwargs)
+

Stores a timezone-naive time-of-day, with nanosecond precision

+
+

New in version 2.6.0.

+
+

requires C* 2.2+ and protocol v4+

+
+ +
+
+class cassandra.cqlengine.columns.TimeUUID(**kwargs)
+

UUID containing timestamp

+
+ +
+
+class cassandra.cqlengine.columns.TinyInt(**kwargs)
+

Stores an 8-bit signed integer value

+
+

New in version 2.6.0.

+
+

requires C* 2.2+ and protocol v4+

+
+ +
+
+class cassandra.cqlengine.columns.UserDefinedType(user_type, **kwargs)
+

User Defined Type column

+

http://www.datastax.com/documentation/cql/3.1/cql/cql_using/cqlUseUDT.html

+

These columns are represented by a specialization of cassandra.cqlengine.usertype.UserType.

+

Please see User Defined Types for examples and discussion.

+
+
Parameters
+

user_type (type) – specifies the UserType model of the column

+
+
+
+ +
+
+class cassandra.cqlengine.columns.UUID(**kwargs)
+

Stores a type 1 or 4 UUID

+
+ +
+
+class cassandra.cqlengine.columns.VarInt(**kwargs)
+

Stores an arbitrary-precision integer

+
+ +
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.21.0-scylla/api/cassandra/cqlengine/connection.html b/3.21.0-scylla/api/cassandra/cqlengine/connection.html new file mode 100644 index 0000000000..68a3dc2b79 --- /dev/null +++ b/3.21.0-scylla/api/cassandra/cqlengine/connection.html @@ -0,0 +1,715 @@ + + + + + + + + + + + + + cassandra.cqlengine.connection - Connection management for cqlengine | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.cqlengine.connection - Connection management for cqlengine

+
+
+cassandra.cqlengine.connection.default()
+

Configures the default connection to localhost, using the driver defaults +(except for row_factory)

+
+ +
+
+cassandra.cqlengine.connection.set_session(s)
+

Configures the default connection with a preexisting cassandra.cluster.Session

+

Note: the mapper presently requires a Session cassandra.cluster.Session.row_factory set to dict_factory. +This may be relaxed in the future

+
+ +
+
+cassandra.cqlengine.connection.setup(hosts, default_keyspace, consistency=None, lazy_connect=False, retry_connect=False, **kwargs)
+

Setup a the driver connection used by the mapper

+
+
Parameters
+
    +
  • hosts (list) – list of hosts, (contact_points for cassandra.cluster.Cluster)

  • +
  • default_keyspace (str) – The default keyspace to use

  • +
  • consistency (int) – The global default ConsistencyLevel - default is the same as Session.default_consistency_level

  • +
  • lazy_connect (bool) – True if should not connect until first use

  • +
  • retry_connect (bool) – True if we should retry to connect even if there was a connection failure initially

  • +
  • **kwargs – Pass-through keyword arguments for cassandra.cluster.Cluster

  • +
+
+
+
+ +
+
+cassandra.cqlengine.connection.register_connection(name, hosts=None, consistency=None, lazy_connect=False, retry_connect=False, cluster_options=None, default=False, session=None)
+

Add a connection to the connection registry. hosts and session are +mutually exclusive, and consistency, lazy_connect, +retry_connect, and cluster_options only work with hosts. Using +hosts will create a new cassandra.cluster.Cluster and +cassandra.cluster.Session.

+
+
Parameters
+
    +
  • hosts (list) – list of hosts, (contact_points for cassandra.cluster.Cluster).

  • +
  • consistency (int) – The default ConsistencyLevel for the +registered connection’s new session. Default is the same as +Session.default_consistency_level. For use with hosts only; +will fail when used with session.

  • +
  • lazy_connect (bool) – True if should not connect until first use. For +use with hosts only; will fail when used with session.

  • +
  • retry_connect (bool) – True if we should retry to connect even if there +was a connection failure initially. For use with hosts only; will +fail when used with session.

  • +
  • cluster_options (dict) – A dict of options to be used as keyword +arguments to cassandra.cluster.Cluster. For use with hosts +only; will fail when used with session.

  • +
  • default (bool) – If True, set the new connection as the cqlengine +default

  • +
  • session (Session) – A cassandra.cluster.Session to be used in +the created connection.

  • +
+
+
+
+ +
+
+cassandra.cqlengine.connection.unregister_connection(name)
+
+ +
+
+cassandra.cqlengine.connection.set_default_connection(name)
+
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.21.0-scylla/api/cassandra/cqlengine/management.html b/3.21.0-scylla/api/cassandra/cqlengine/management.html new file mode 100644 index 0000000000..4cba9f0a19 --- /dev/null +++ b/3.21.0-scylla/api/cassandra/cqlengine/management.html @@ -0,0 +1,737 @@ + + + + + + + + + + + + + cassandra.cqlengine.management - Schema management for cqlengine | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.cqlengine.management - Schema management for cqlengine

+

A collection of functions for managing keyspace and table schema.

+
+
+cassandra.cqlengine.management.create_keyspace_simple(name, replication_factor, durable_writes=True, connections=None)
+

Creates a keyspace with SimpleStrategy for replica placement

+

If the keyspace already exists, it will not be modified.

+

This function should be used with caution, especially in production environments. +Take care to execute schema modifications in a single context (i.e. not concurrently with other clients).

+

There are plans to guard schema-modifying functions with an environment-driven conditional.

+
+
Parameters
+
    +
  • name (str) – name of keyspace to create

  • +
  • replication_factor (int) – keyspace replication factor, used with SimpleStrategy

  • +
  • durable_writes (bool) – Write log is bypassed if set to False

  • +
  • connections (list) – List of connection names

  • +
+
+
+
+ +
+
+cassandra.cqlengine.management.create_keyspace_network_topology(name, dc_replication_map, durable_writes=True, connections=None)
+

Creates a keyspace with NetworkTopologyStrategy for replica placement

+

If the keyspace already exists, it will not be modified.

+

This function should be used with caution, especially in production environments. +Take care to execute schema modifications in a single context (i.e. not concurrently with other clients).

+

There are plans to guard schema-modifying functions with an environment-driven conditional.

+
+
Parameters
+
    +
  • name (str) – name of keyspace to create

  • +
  • dc_replication_map (dict) – map of dc_names: replication_factor

  • +
  • durable_writes (bool) – Write log is bypassed if set to False

  • +
  • connections (list) – List of connection names

  • +
+
+
+
+ +
+
+cassandra.cqlengine.management.drop_keyspace(name, connections=None)
+

Drops a keyspace, if it exists.

+

There are plans to guard schema-modifying functions with an environment-driven conditional.

+

This function should be used with caution, especially in production environments. +Take care to execute schema modifications in a single context (i.e. not concurrently with other clients).

+
+
Parameters
+
    +
  • name (str) – name of keyspace to drop

  • +
  • connections (list) – List of connection names

  • +
+
+
+
+ +
+
+cassandra.cqlengine.management.sync_table(model, keyspaces=None, connections=None)
+

Inspects the model and creates / updates the corresponding table and columns.

+

If keyspaces is specified, the table will be synched for all specified keyspaces. +Note that the Model.__keyspace__ is ignored in that case.

+

If connections is specified, the table will be synched for all specified connections. Note that the Model.__connection__ is ignored in that case. +If not specified, it will try to get the connection from the Model.

+

Any User Defined Types used in the table are implicitly synchronized.

+

This function can only add fields that are not part of the primary key.

+

Note that the attributes removed from the model are not deleted on the database. +They become effectively ignored by (will not show up on) the model.

+

This function should be used with caution, especially in production environments. +Take care to execute schema modifications in a single context (i.e. not concurrently with other clients).

+

There are plans to guard schema-modifying functions with an environment-driven conditional.

+
+ +
+
+cassandra.cqlengine.management.sync_type(ks_name, type_model, connection=None)
+

Inspects the type_model and creates / updates the corresponding type.

+

Note that the attributes removed from the type_model are not deleted on the database (this operation is not supported). +They become effectively ignored by (will not show up on) the type_model.

+

This function should be used with caution, especially in production environments. +Take care to execute schema modifications in a single context (i.e. not concurrently with other clients).

+

There are plans to guard schema-modifying functions with an environment-driven conditional.

+
+ +
+
+cassandra.cqlengine.management.drop_table(model, keyspaces=None, connections=None)
+

Drops the table indicated by the model, if it exists.

+

If keyspaces is specified, the table will be dropped for all specified keyspaces. Note that the Model.__keyspace__ is ignored in that case.

+

If connections is specified, the table will be synched for all specified connections. Note that the Model.__connection__ is ignored in that case. +If not specified, it will try to get the connection from the Model.

+

This function should be used with caution, especially in production environments. +Take care to execute schema modifications in a single context (i.e. not concurrently with other clients).

+

There are plans to guard schema-modifying functions with an environment-driven conditional.

+
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.21.0-scylla/api/cassandra/cqlengine/models.html b/3.21.0-scylla/api/cassandra/cqlengine/models.html new file mode 100644 index 0000000000..9360a49f9f --- /dev/null +++ b/3.21.0-scylla/api/cassandra/cqlengine/models.html @@ -0,0 +1,942 @@ + + + + + + + + + + + + + cassandra.cqlengine.models - Table models for object mapping | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.cqlengine.models - Table models for object mapping

+
+

Model

+
+
+class cassandra.cqlengine.models.Model(\*\*kwargs)
+

The initializer creates an instance of the model. Pass in keyword arguments for columns you’ve defined on the model.

+
class Person(Model):
+    id = columns.UUID(primary_key=True)
+    first_name  = columns.Text()
+    last_name = columns.Text()
+
+person = Person(first_name='Blake', last_name='Eggleston')
+person.first_name  #returns 'Blake'
+person.last_name  #returns 'Eggleston'
+
+
+

Model attributes define how the model maps to tables in the database. These are class variables that should be set +when defining Model deriviatives.

+
+
+__abstract__ = False
+

Optional. Indicates that this model is only intended to be used as a base class for other models. +You can’t create tables for abstract models, but checks around schema validity are skipped during class construction.

+
+ +
+
+__table_name__ = None
+

Optional. Sets the name of the CQL table for this model. If left blank, the table name will be the name of the model, with it’s module name as it’s prefix. Manually defined table names are not inherited.

+
+ +
+
+__table_name_case_sensitive__ = False
+

Optional. By default, __table_name__ is case insensitive. Set this to True if you want to preserve the case sensitivity.

+
+ +
+
+__keyspace__ = None
+

Sets the name of the keyspace used by this model.

+
+ +
+
+__connection__ = None
+

Sets the name of the default connection used by this model.

+
+ +
+
+__default_ttl__ = None
+

Will be deprecated in release 4.0. You can set the default ttl by configuring the table __options__. See Default TTL and Per Query TTL for more details.

+
+ +
+
+__discriminator_value__ = None
+

Optional Specifies a value for the discriminator column when using model inheritance.

+

See Model Inheritance for usage examples.

+
+ +

Each table can have its own set of configuration options, including compaction. Unspecified, these default to sensible values in +the server. To override defaults, set options using the model __options__ attribute, which allows options specified a dict.

+

When a table is synced, it will be altered to match the options set on your table. +This means that if you are changing settings manually they will be changed back on resync.

+

Do not use the options settings of cqlengine if you want to manage your compaction settings manually.

+

See the list of supported table properties for more information.

+
+
+__options__
+

For example:

+
class User(Model):
+    __options__ = {'compaction': {'class': 'LeveledCompactionStrategy',
+                                  'sstable_size_in_mb': '64',
+                                  'tombstone_threshold': '.2'},
+                   'comment': 'User data stored here'}
+
+    user_id = columns.UUID(primary_key=True)
+    name = columns.Text()
+
+
+

or :

+
class TimeData(Model):
+    __options__ = {'compaction': {'class': 'SizeTieredCompactionStrategy',
+                                  'bucket_low': '.3',
+                                  'bucket_high': '2',
+                                  'min_threshold': '2',
+                                  'max_threshold': '64',
+                                  'tombstone_compaction_interval': '86400'},
+                   'gc_grace_seconds': '0'}
+
+
+
+ +
+
+__compute_routing_key__ = True
+

Optional Setting False disables computing the routing key for TokenAwareRouting

+
+ +

The base methods allow creating, storing, and querying modeled objects.

+
+
+classmethod create(**kwargs)
+

Create an instance of this model in the database.

+

Takes the model column values as keyword arguments. Setting a value to +None is equivalent to running a CQL DELETE on that column.

+

Returns the instance.

+
+ +
+
+if_not_exists()
+

Check the existence of an object before insertion. The existence of an +object is determined by its primary key(s). And please note using this flag +would incur performance cost.

+

If the insertion isn’t applied, a LWTException is raised.

+
try:
+    TestIfNotExistsModel.if_not_exists().create(id=id, count=9, text='111111111111')
+except LWTException as e:
+    # handle failure case
+    print e.existing  # dict containing LWT result fields
+
+
+

This method is supported on Cassandra 2.0 or later.

+
+ +
+
+if_exists()
+

Check the existence of an object before an update or delete. The existence of an +object is determined by its primary key(s). And please note using this flag +would incur performance cost.

+

If the update or delete isn’t applied, a LWTException is raised.

+
try:
+    TestIfExistsModel.objects(id=id).if_exists().update(count=9, text='111111111111')
+except LWTException as e:
+    # handle failure case
+    pass
+
+
+

This method is supported on Cassandra 2.0 or later.

+
+ +
+
+save()
+

Saves an object to the database.

+
#create a person instance
+person = Person(first_name='Kimberly', last_name='Eggleston')
+#saves it to Cassandra
+person.save()
+
+
+
+ +
+
+update(**values)
+

Performs an update on the model instance. You can pass in values to set on the model +for updating, or you can call without values to execute an update against any modified +fields. If no fields on the model have been modified since loading, no query will be +performed. Model validation is performed normally. Setting a value to None is +equivalent to running a CQL DELETE on that column.

+

It is possible to do a blind update, that is, to update a field without having first selected the object out of the database. +See Blind Updates

+
+ +
+
+iff(**values)
+

Checks to ensure that the values specified are correct on the Cassandra cluster. +Simply specify the column(s) and the expected value(s). As with if_not_exists, +this incurs a performance cost.

+

If the insertion isn’t applied, a LWTException is raised.

+
t = TestTransactionModel(text='some text', count=5)
+try:
+     t.iff(count=5).update('other text')
+except LWTException as e:
+    # handle failure case
+    print e.existing # existing object
+
+
+
+ +
+
+classmethod get(*args, **kwargs)
+

Returns a single object based on the passed filter constraints.

+

This is a pass-through to the model objects().:method:~cqlengine.queries.get.

+
+ +
+
+classmethod filter(*args, **kwargs)
+

Returns a queryset based on filter parameters.

+

This is a pass-through to the model objects().:method:~cqlengine.queries.filter.

+
+ +
+
+classmethod all()
+

Returns a queryset representing all stored objects

+

This is a pass-through to the model objects().all()

+
+ +
+
+delete()
+

Deletes the object from the database

+
+ +
+
+batch(batch_object)
+

Sets the batch object to run instance updates and inserts queries with.

+

See Batch Queries for usage examples

+
+ +
+
+timeout(timeout)
+

Sets a timeout for use in save(), update(), and delete() +operations

+
+ +
+
+timestamp(timedelta_or_datetime)
+

Sets the timestamp for the query

+
+ +
+
+ttl(ttl_in_sec)
+

Sets the ttl values to run instance updates and inserts queries with.

+
+ +
+
+using(connection=None)
+

Change the context on the fly of the model instance (keyspace, connection)

+
+ +
+
+classmethod column_family_name(include_keyspace=True)
+

Returns the column family name if it’s been defined +otherwise, it creates it from the module and class name

+
+ +

Models also support dict-like access:

+
+
+len(m)
+

Returns the number of columns defined in the model

+
+ +
+
+m[col_name]
+

Returns the value of column col_name

+
+ +
+
+m[col_name] = value
+

Set m[col_name] to value

+
+ +
+
+keys()
+

Returns a list of column IDs.

+
+ +
+
+values()
+

Returns list of column values.

+
+ +
+
+items()
+

Returns a list of column ID/value tuples.

+
+ +
+ +
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.21.0-scylla/api/cassandra/cqlengine/query.html b/3.21.0-scylla/api/cassandra/cqlengine/query.html new file mode 100644 index 0000000000..d3b841cd2c --- /dev/null +++ b/3.21.0-scylla/api/cassandra/cqlengine/query.html @@ -0,0 +1,1038 @@ + + + + + + + + + + + + + cassandra.cqlengine.query - Query and filter model objects | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.cqlengine.query - Query and filter model objects

+
+

QuerySet

+

QuerySet objects are typically obtained by calling objects() on a model class. +The methods here are used to filter, order, and constrain results.

+
+
+class cassandra.cqlengine.query.ModelQuerySet(model)
+
+
+all()
+

Returns a queryset matching all rows

+
for user in User.objects().all():
+    print(user)
+
+
+
+ +
+
+batch(batch_obj)
+

Set a batch object to run the query on.

+

Note: running a select query with a batch object will raise an exception

+
+ +
+
+consistency(consistency)
+

Sets the consistency level for the operation. See ConsistencyLevel.

+
for user in User.objects(id=3).consistency(CL.ONE):
+    print(user)
+
+
+
+ +
+
+count()
+

Returns the number of rows matched by this query.

+

Note: This function executes a SELECT COUNT() and has a performance cost on large datasets

+
+ +
+
+len(queryset)
+

Returns the number of rows matched by this query. This function uses count() internally.

+

Note: This function executes a SELECT COUNT() and has a performance cost on large datasets

+
+ +
+
+distinct(distinct_fields=None)
+

Returns the DISTINCT rows matched by this query.

+

distinct_fields default to the partition key fields if not specified.

+

Note: distinct_fields must be a partition key or a static column

+
class Automobile(Model):
+    manufacturer = columns.Text(partition_key=True)
+    year = columns.Integer(primary_key=True)
+    model = columns.Text(primary_key=True)
+    price = columns.Decimal()
+
+sync_table(Automobile)
+
+# create rows
+
+Automobile.objects.distinct()
+
+# or
+
+Automobile.objects.distinct(['manufacturer'])
+
+
+
+ +
+
+filter(*args, **kwargs)
+

Adds WHERE arguments to the queryset, returning a new queryset

+

See Retrieving objects with filters

+

Returns a QuerySet filtered on the keyword arguments

+
+ +
+
+get(*args, **kwargs)
+

Returns a single instance matching this query, optionally with additional filter kwargs.

+

See Retrieving objects with filters

+

Returns a single object matching the QuerySet.

+
user = User.get(id=1)
+
+
+

If no objects are matched, a DoesNotExist exception is raised.

+

If more than one object is found, a MultipleObjectsReturned exception is raised.

+
+ +
+
+limit(v)
+

Limits the number of results returned by Cassandra. Use 0 or None to disable.

+

Note that CQL’s default limit is 10,000, so all queries without a limit set explicitly will have an implicit limit of 10,000

+
# Fetch 100 users
+for user in User.objects().limit(100):
+    print(user)
+
+# Fetch all users
+for user in User.objects().limit(None):
+    print(user)
+
+
+
+ +
+
+fetch_size(v)
+

Sets the number of rows that are fetched at a time.

+

Note that driver’s default fetch size is 5000.

+
for user in User.objects().fetch_size(500):
+    print(user)
+
+
+
+ +
+
+if_not_exists()
+

Check the existence of an object before insertion.

+

If the insertion isn’t applied, a LWTException is raised.

+
+ +
+
+if_exists()
+

Check the existence of an object before an update or delete.

+

If the update or delete isn’t applied, a LWTException is raised.

+
+ +
+
+order_by(*colnames)
+

Sets the column(s) to be used for ordering

+

Default order is ascending, prepend a ‘-’ to any column name for descending

+

Note: column names must be a clustering key

+
from uuid import uuid1,uuid4
+
+class Comment(Model):
+    photo_id = UUID(primary_key=True)
+    comment_id = TimeUUID(primary_key=True, default=uuid1) # second primary key component is a clustering key
+    comment = Text()
+
+sync_table(Comment)
+
+u = uuid4()
+for x in range(5):
+    Comment.create(photo_id=u, comment="test %d" % x)
+
+print("Normal")
+for comment in Comment.objects(photo_id=u):
+    print comment.comment_id
+
+print("Reversed")
+for comment in Comment.objects(photo_id=u).order_by("-comment_id"):
+    print comment.comment_id
+
+
+
+ +
+
+allow_filtering()
+

Enables the (usually) unwise practive of querying on a clustering key without also defining a partition key

+
+ +
+
+only(fields)
+

Load only these fields for the returned query

+
+ +
+
+defer(fields)
+

Don’t load these fields for the returned query

+
+ +
+
+timestamp(timestamp)
+

Allows for custom timestamps to be saved with the record.

+
+ +
+
+ttl(ttl)
+

Sets the ttl (in seconds) for modified data.

+

Note that running a select query with a ttl value will raise an exception

+
+ +
+
+using(keyspace=None, connection=None)
+

Change the context on-the-fly of the Model class (keyspace, connection)

+
+ +
+
+update(**values)
+

Performs an update on the row selected by the queryset. Include values to update in the +update like so:

+
Model.objects(key=n).update(value='x')
+
+
+

Passing in updates for columns which are not part of the model will raise a ValidationError.

+

Per column validation will be performed, but instance level validation will not +(i.e., Model.validate is not called). This is sometimes referred to as a blind update.

+

For example:

+
class User(Model):
+    id = Integer(primary_key=True)
+    name = Text()
+
+setup(["localhost"], "test")
+sync_table(User)
+
+u = User.create(id=1, name="jon")
+
+User.objects(id=1).update(name="Steve")
+
+# sets name to null
+User.objects(id=1).update(name=None)
+
+
+

Also supported is blindly adding and removing elements from container columns, +without loading a model instance from Cassandra.

+

Using the syntax .update(column_name={x, y, z}) will overwrite the contents of the container, like updating a +non container column. However, adding __<operation> to the end of the keyword arg, makes the update call add +or remove items from the collection, without overwriting then entire column.

+

Given the model below, here are the operations that can be performed on the different container columns:

+
class Row(Model):
+    row_id      = columns.Integer(primary_key=True)
+    set_column  = columns.Set(Integer)
+    list_column = columns.List(Integer)
+    map_column  = columns.Map(Integer, Integer)
+
+
+

Set

+
    +
  • add: adds the elements of the given set to the column

  • +
  • remove: removes the elements of the given set to the column

  • +
+
# add elements to a set
+Row.objects(row_id=5).update(set_column__add={6})
+
+# remove elements to a set
+Row.objects(row_id=5).update(set_column__remove={4})
+
+
+

List

+
    +
  • append: appends the elements of the given list to the end of the column

  • +
  • prepend: prepends the elements of the given list to the beginning of the column

  • +
+
# append items to a list
+Row.objects(row_id=5).update(list_column__append=[6, 7])
+
+# prepend items to a list
+Row.objects(row_id=5).update(list_column__prepend=[1, 2])
+
+
+

Map

+
    +
  • update: adds the given keys/values to the columns, creating new entries if they didn’t exist, and overwriting old ones if they did

  • +
+
# add items to a map
+Row.objects(row_id=5).update(map_column__update={1: 2, 3: 4})
+
+# remove items from a map
+Row.objects(row_id=5).update(map_column__remove={1, 2})
+
+
+
+ +
+ +
+
+class cassandra.cqlengine.query.BatchQuery(batch_type=None, timestamp=None, consistency=None, execute_on_exception=False, timeout=<object object>, connection=None)
+

Handles the batching of queries

+

http://docs.datastax.com/en/cql/3.0/cql/cql_reference/batch_r.html

+

See Batch Queries for more details.

+
+
Parameters
+
    +
  • batch_type (BatchType, str or None) – (optional) One of batch type values available through BatchType enum

  • +
  • timestamp (datetime or timedelta or None) – (optional) A datetime or timedelta object with desired timestamp to be applied +to the batch conditional.

  • +
  • consistency (The ConsistencyLevel to be used for the batch query, or None.) – (optional) One of consistency values (“ANY”, “ONE”, “QUORUM” etc)

  • +
  • execute_on_exception (bool) – (Defaults to False) Indicates that when the BatchQuery instance is used +as a context manager the queries accumulated within the context must be executed despite +encountering an error within the context. By default, any exception raised from within +the context scope will cause the batched queries not to be executed.

  • +
  • timeout (float or None) – (optional) Timeout for the entire batch (in seconds), if not specified fallback +to default session timeout

  • +
  • connection (str) – Connection name to use for the batch execution

  • +
+
+
+
+
+add_query(query)
+
+ +
+
+execute()
+
+ +
+
+add_callback(fn, *args, **kwargs)
+

Add a function and arguments to be passed to it to be executed after the batch executes.

+

A batch can support multiple callbacks.

+

Note, that if the batch does not execute, the callbacks are not executed. +A callback, thus, is an “on batch success” handler.

+
+
Parameters
+
    +
  • fn (callable) – Callable object

  • +
  • *args – Positional arguments to be passed to the callback at the time of execution

  • +
  • **kwargs – Named arguments to be passed to the callback at the time of execution

  • +
+
+
+
+ +
+ +
+
+class cassandra.cqlengine.query.ContextQuery(*args, **kwargs)
+

A Context manager to allow a Model to switch context easily. Presently, the context only +specifies a keyspace for model IO.

+
+
Parameters
+
    +
  • *args – One or more models. A model should be a class type, not an instance.

  • +
  • **kwargs – (optional) Context parameters: can be keyspace or connection

  • +
+
+
+

For example:

+
with ContextQuery(Automobile, keyspace='test2') as A:
+    A.objects.create(manufacturer='honda', year=2008, model='civic')
+    print len(A.objects.all())  # 1 result
+
+with ContextQuery(Automobile, keyspace='test4') as A:
+    print len(A.objects.all())  # 0 result
+
+# Multiple models
+with ContextQuery(Automobile, Automobile2, connection='cluster2') as (A, A2):
+    print len(A.objects.all())
+    print len(A2.objects.all())
+
+
+
+ +
+
+class cassandra.cqlengine.query.DoesNotExist
+
+ +
+
+class cassandra.cqlengine.query.MultipleObjectsReturned
+
+ +
+
+class cassandra.cqlengine.query.LWTException(existing)
+

Lightweight conditional exception.

+

This exception will be raised when a write using an IF clause could not be +applied due to existing data violating the condition. The existing data is +available through the existing attribute.

+
+
Parameters
+

existing – The current state of the data which prevented the write.

+
+
+
+ +
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.21.0-scylla/api/cassandra/cqlengine/usertype.html b/3.21.0-scylla/api/cassandra/cqlengine/usertype.html new file mode 100644 index 0000000000..40736375eb --- /dev/null +++ b/3.21.0-scylla/api/cassandra/cqlengine/usertype.html @@ -0,0 +1,681 @@ + + + + + + + + + + + + + cassandra.cqlengine.usertype - Model classes for User Defined Types | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.cqlengine.usertype - Model classes for User Defined Types

+
+

UserType

+
+
+class cassandra.cqlengine.usertype.UserType(**values)
+

This class is used to model User Defined Types. To define a type, declare a class inheriting from this, +and assign field types as class attributes:

+
# connect with default keyspace ...
+
+from cassandra.cqlengine.columns import Text, Integer
+from cassandra.cqlengine.usertype import UserType
+
+class address(UserType):
+    street = Text()
+    zipcode = Integer()
+
+from cassandra.cqlengine import management
+management.sync_type(address)
+
+
+

Please see User Defined Types for a complete example and discussion.

+
+
+__type_name__ = None
+

Optional. Sets the name of the CQL type for this type.

+

If not specified, the type name will be the name of the class, with it’s module name as it’s prefix.

+
+ +
+ +
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.21.0-scylla/api/cassandra/datastax/graph/fluent/index.html b/3.21.0-scylla/api/cassandra/datastax/graph/fluent/index.html new file mode 100644 index 0000000000..4c9b5325ba --- /dev/null +++ b/3.21.0-scylla/api/cassandra/datastax/graph/fluent/index.html @@ -0,0 +1,755 @@ + + + + + + + + + + + + + cassandra.datastax.graph.fluent | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.datastax.graph.fluent

+
+
+class cassandra.datastax.graph.fluent.DseGraph
+

Dse Graph utility class for GraphTraversal construction and execution.

+
+
+DSE_GRAPH_QUERY_LANGUAGE = 'bytecode-json'
+

Graph query language, Default is ‘bytecode-json’ (GraphSON).

+
+ +
+
+static create_execution_profile(graph_name, graph_protocol=b'graphson-2.0', **kwargs)
+

Creates an ExecutionProfile for GraphTraversal execution. You need to register that execution profile to the +cluster by using cluster.add_execution_profile.

+
+
Parameters
+
    +
  • graph_name – The graph name

  • +
  • graph_protocol – (Optional) The graph protocol, default is DSE_GRAPH_QUERY_PROTOCOL.

  • +
+
+
+
+ +
+
+static query_from_traversal(traversal, graph_protocol=b'graphson-2.0', context=None)
+

From a GraphTraversal, return a query string based on the language specified in DseGraph.DSE_GRAPH_QUERY_LANGUAGE.

+
+
Parameters
+
    +
  • traversal – The GraphTraversal object

  • +
  • graph_protocol – The graph protocol. Default is DseGraph.DSE_GRAPH_QUERY_PROTOCOL.

  • +
  • context – The dict of the serialization context, needed for GraphSON3 (tuple, udt). +e.g: {‘cluster’: cluster, ‘graph_name’: name}

  • +
+
+
+
+ +
+
+static traversal_source(session=None, graph_name=None, execution_profile=EXEC_PROFILE_GRAPH_DEFAULT, traversal_class=None)
+

Returns a TinkerPop GraphTraversalSource binded to the session and graph_name if provided.

+
+
Parameters
+
    +
  • session – (Optional) A DSE session

  • +
  • graph_name – (Optional) DSE Graph name

  • +
  • execution_profile – (Optional) Execution profile for traversal queries. Default is set to EXEC_PROFILE_GRAPH_DEFAULT.

  • +
  • traversal_class – (Optional) The GraphTraversalSource class to use (DSL).

  • +
+
+
+
from cassandra.cluster import Cluster
+from cassandra.datastax.graph.fluent import DseGraph
+
+c = Cluster()
+session = c.connect()
+
+g = DseGraph.traversal_source(session, 'my_graph')
+print g.V().valueMap().toList()
+
+
+
+ +
+
+static batch(session=None, execution_profile=None)
+

Returns the cassandra.datastax.graph.fluent.query.TraversalBatch object allowing to +execute multiple traversals in the same transaction.

+
+ +
+ +
+
+class cassandra.datastax.graph.fluent.DSESessionRemoteGraphConnection(session[, graph_name, execution_profile])
+

A Tinkerpop RemoteConnection to execute traversal queries on DSE.

+
+
Parameters
+
    +
  • session – A DSE session

  • +
  • graph_name – (Optional) DSE Graph name.

  • +
  • execution_profile – (Optional) Execution profile for traversal queries. Default is set to EXEC_PROFILE_GRAPH_DEFAULT.

  • +
+
+
+
+ +
+
+class cassandra.datastax.graph.fluent.BaseGraphRowFactory(cluster)
+

Base row factory for graph traversal. This class basically wraps a +graphson reader function to handle additional features of Gremlin/DSE +and is callable as a normal row factory.

+
+
Currently supported:
    +
  • bulk results

  • +
+
+
+
+ +
+
+cassandra.datastax.graph.fluent.graph_traversal_row_factory
+

alias of cassandra.datastax.graph.fluent._GremlinGraphSON2RowFactory

+
+ +
+
+cassandra.datastax.graph.fluent.graph_traversal_dse_object_row_factory
+

alias of cassandra.datastax.graph.fluent._DseGraphSON2RowFactory

+
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.21.0-scylla/api/cassandra/datastax/graph/fluent/predicates.html b/3.21.0-scylla/api/cassandra/datastax/graph/fluent/predicates.html new file mode 100644 index 0000000000..150d905715 --- /dev/null +++ b/3.21.0-scylla/api/cassandra/datastax/graph/fluent/predicates.html @@ -0,0 +1,718 @@ + + + + + + + + + + + + + cassandra.datastax.graph.fluent.predicates | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.datastax.graph.fluent.predicates

+
+
+class cassandra.datastax.graph.fluent.predicates.Search
+
+
+static token(value)
+

Search any instance of a certain token within the text property targeted. +:param value: the value to look for.

+
+ +
+
+static token_prefix(value)
+

Search any instance of a certain token prefix withing the text property targeted. +:param value: the value to look for.

+
+ +
+
+static token_regex(value)
+

Search any instance of the provided regular expression for the targeted property. +:param value: the value to look for.

+
+ +
+
+static prefix(value)
+

Search for a specific prefix at the beginning of the text property targeted. +:param value: the value to look for.

+
+ +
+
+static regex(value)
+

Search for this regular expression inside the text property targeted. +:param value: the value to look for.

+
+ +
+
+static fuzzy(value, distance)
+

Search for a fuzzy string inside the text property targeted. +:param value: the value to look for. +:param distance: The distance for the fuzzy search. ie. 1, to allow a one-letter misspellings.

+
+ +
+
+static token_fuzzy(value, distance)
+

Search for a token fuzzy inside the text property targeted. +:param value: the value to look for. +:param distance: The distance for the token fuzzy search. ie. 1, to allow a one-letter misspellings.

+
+ +
+
+static phrase(value, proximity)
+

Search for a phrase inside the text property targeted. +:param value: the value to look for. +:param proximity: The proximity for the phrase search. ie. phrase(‘David Felcey’, 2).. to find ‘David Felcey’ with up to two middle names.

+
+ +
+ +
+
+class cassandra.datastax.graph.fluent.predicates.Geo
+
+
+static inside(value, units=1)
+

Search any instance of geometry inside the Distance targeted. +:param value: A Distance to look for. +:param units: The units for value. See GeoUnit enum. (Can also +provide an integer to use as a multiplier to convert value to +degrees.)

+
+ +
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.21.0-scylla/api/cassandra/datastax/graph/fluent/query.html b/3.21.0-scylla/api/cassandra/datastax/graph/fluent/query.html new file mode 100644 index 0000000000..055af42ef2 --- /dev/null +++ b/3.21.0-scylla/api/cassandra/datastax/graph/fluent/query.html @@ -0,0 +1,702 @@ + + + + + + + + + + + + + cassandra.datastax.graph.fluent.query | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.datastax.graph.fluent.query

+
+
+class cassandra.datastax.graph.fluent.query.TraversalBatch(session=None, execution_profile=None)
+

A TraversalBatch is used to execute multiple graph traversals in a +single transaction. If any traversal in the batch fails, the entire +batch will fail to apply.

+

If a TraversalBatch is bounded to a DSE session, it can be executed using +traversal_batch.execute().

+
+
Parameters
+
    +
  • session – (Optional) A DSE session

  • +
  • execution_profile – (Optional) The execution profile to use for the batch execution

  • +
+
+
+
+
+add(traversal)
+

Add a traversal to the batch.

+
+
Parameters
+

traversal – A gremlin GraphTraversal

+
+
+
+ +
+
+add_all(traversals)
+

Adds a sequence of traversals to the batch.

+
+
Parameters
+

traversals – A sequence of gremlin GraphTraversal

+
+
+
+ +
+
+execute()
+

Execute the traversal batch if bounded to a DSE Session.

+
+ +
+
+as_graph_statement(graph_protocol=b'graphson-2.0')
+

Return the traversal batch as GraphStatement.

+
+
Parameters
+

graph_protocol – The graph protocol for the GraphSONWriter. Default is GraphProtocol.GRAPHSON_2_0.

+
+
+
+ +
+
+clear()
+

Clear a traversal batch for reuse.

+
+ +
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.21.0-scylla/api/cassandra/datastax/graph/index.html b/3.21.0-scylla/api/cassandra/datastax/graph/index.html new file mode 100644 index 0000000000..6467fd08cc --- /dev/null +++ b/3.21.0-scylla/api/cassandra/datastax/graph/index.html @@ -0,0 +1,965 @@ + + + + + + + + + + + + + cassandra.datastax.graph - Graph Statements, Options, and Row Factories | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.datastax.graph - Graph Statements, Options, and Row Factories

+
+
+cassandra.datastax.graph.single_object_row_factory(column_names, rows)
+

returns the JSON string value of graph results

+
+ +
+
+cassandra.datastax.graph.graph_result_row_factory(column_names, rows)
+

Returns a Result object that can load graph results and produce specific types. +The Result JSON is deserialized and unpacked from the top-level ‘result’ dict.

+
+ +
+
+cassandra.datastax.graph.graph_object_row_factory(column_names, rows)
+

Like graph_result_row_factory(), except known element types (Vertex, Edge) are +converted to their simplified objects. Some low-level metadata is shed in this conversion. Unknown result types are +still returned as Result.

+
+ +
+
+class cassandra.datastax.graph.GraphProtocol
+
+
+GRAPHSON_1_0 = b'graphson-1.0'
+

GraphSON1

+
+ +
+
+GRAPHSON_2_0 = b'graphson-2.0'
+

GraphSON2

+
+ +
+
+GRAPHSON_3_0 = b'graphson-3.0'
+

GraphSON3

+
+ +
+ +
+
+class cassandra.datastax.graph.GraphOptions(**kwargs)
+

Options for DSE Graph Query handler.

+
+
+graph_name
+

name of the targeted graph.

+
+ +
+
+graph_source
+

choose the graph traversal source, configured on the server side.

+
+ +
+
+graph_language
+

the language used in the queries (default “gremlin-groovy”)

+
+ +
+
+graph_read_consistency_level
+

read cassandra.ConsistencyLevel for graph queries (if distinct from session default). +Setting this overrides the native Statement.consistency_level for read operations from Cassandra persistence

+
+ +
+
+graph_write_consistency_level
+

write cassandra.ConsistencyLevel for graph queries (if distinct from session default). +Setting this overrides the native Statement.consistency_level for write operations to Cassandra persistence.

+
+ +
+
+is_default_source
+
+ +
+
+is_analytics_source
+

True if graph_source is set to the server-defined analytics traversal source (‘a’)

+
+ +
+
+is_graph_source
+

True if graph_source is set to the server-defined graph traversal source (‘g’)

+
+ +
+
+set_source_default()
+

Sets graph_source to the server-defined default traversal source (‘default’)

+
+ +
+
+set_source_analytics()
+

Sets graph_source to the server-defined analytic traversal source (‘a’)

+
+ +
+
+set_source_graph()
+

Sets graph_source to the server-defined graph traversal source (‘g’)

+
+ +
+ +
+
+class cassandra.datastax.graph.SimpleGraphStatement(query_string, retry_policy=None, consistency_level=None, routing_key=None, serial_consistency_level=None, fetch_size=<object object>, keyspace=None, custom_payload=None, is_idempotent=False)
+

Simple graph statement for Session.execute_graph(). +Takes the same parameters as SimpleStatement.

+

query_string should be a literal CQL statement with the exception +of parameter placeholders that will be filled through the +parameters argument of Session.execute().

+

See Statement attributes for a description of the other parameters.

+
+ +
+
+class cassandra.datastax.graph.Result(value)
+

Represents deserialized graph results. +Property and item getters are provided for convenience.

+
+
+value = None
+

Deserialized value from the result

+
+ +
+
+as_vertex()
+

Return a Vertex parsed from this result

+

Raises TypeError if parsing fails (i.e. the result structure is not valid).

+
+ +
+
+as_edge()
+

Return a Edge parsed from this result

+

Raises TypeError if parsing fails (i.e. the result structure is not valid).

+
+ +
+
+as_path()
+

Return a Path parsed from this result

+

Raises TypeError if parsing fails (i.e. the result structure is not valid).

+
+ +
+ +
+
+class cassandra.datastax.graph.Vertex(id, label, type, properties)
+

Represents a Vertex element from a graph query.

+

Vertex properties are extracted into a dict of property names to list of VertexProperty (list +because they are always encoded that way, and sometimes have multiple cardinality; VertexProperty because sometimes +the properties themselves have property maps).

+
+ +
+
+class cassandra.datastax.graph.VertexProperty(label, value, properties=None)
+

Vertex properties have a top-level value and an optional dict of properties.

+
+
+label = None
+

label of the property

+
+ +
+
+value = None
+

Value of the property

+
+ +
+
+properties = None
+

dict of properties attached to the property

+
+ +
+ +
+
+class cassandra.datastax.graph.Edge(id, label, type, properties, inV, inVLabel, outV, outVLabel)
+

Represents an Edge element from a graph query.

+

Attributes match initializer parameters.

+
+ +
+
+class cassandra.datastax.graph.Path(labels, objects)
+

Represents a graph path.

+

Labels list is taken verbatim from the results.

+

Objects are either Result or Vertex/Edge for recognized types

+
+
+labels = None
+

List of labels in the path

+
+ +
+
+objects = None
+

List of objects in the path

+
+ +
+ +
+
+class cassandra.datastax.graph.GraphSON1Serializer
+

Serialize python objects to graphson types.

+
+ +
+
+class cassandra.datastax.graph.GraphSON1Deserializer
+

Deserialize graphson1 types to python objects.

+
+
+classmethod deserialize_date(value)
+
+ +
+
+classmethod deserialize_timestamp(value)
+
+ +
+
+classmethod deserialize_time(value)
+
+ +
+
+classmethod deserialize_duration(value)
+
+ +
+
+classmethod deserialize_int(value)
+
+ +
+
+classmethod deserialize_bigint(value)
+
+ +
+
+classmethod deserialize_double(value)
+
+ +
+
+classmethod deserialize_float(value)
+
+ +
+
+classmethod deserialize_uuid(value)
+
+ +
+
+classmethod deserialize_blob(value)
+
+ +
+
+classmethod deserialize_decimal(value)
+
+ +
+
+classmethod deserialize_point(value)
+
+ +
+
+classmethod deserialize_linestring(value)
+
+ +
+
+classmethod deserialize_polygon(value)
+
+ +
+ +
+
+class cassandra.datastax.graph.GraphSON2Reader(context, extra_deserializer_map=None)
+

GraphSON2 Reader that parse json and deserialize to python objects.

+
+
Parameters
+

extra_deserializer_map – map from GraphSON type tag to deserializer instance implementing deserialize

+
+
+
+
+read(json_data)
+

Read and deserialize json_data.

+
+ +
+
+deserialize(obj)
+

Deserialize GraphSON type-tagged dict values into objects mapped in self.deserializers

+
+ +
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.21.0-scylla/api/cassandra/decoder.html b/3.21.0-scylla/api/cassandra/decoder.html new file mode 100644 index 0000000000..cec545dd11 --- /dev/null +++ b/3.21.0-scylla/api/cassandra/decoder.html @@ -0,0 +1,663 @@ + + + + + + + + + + + + + cassandra.decoder - Data Return Formats | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.decoder - Data Return Formats

+
+
+cassandra.decoder.tuple_factory()
+

Deprecated in 2.0.0. Use cassandra.query.tuple_factory()

+
+ +
+
+cassandra.decoder.named_tuple_factory()
+

Deprecated in 2.0.0. Use cassandra.query.named_tuple_factory()

+
+ +
+
+cassandra.decoder.dict_factory()
+

Deprecated in 2.0.0. Use cassandra.query.dict_factory()

+
+ +
+
+cassandra.decoder.ordered_dict_factory()
+

Deprecated in 2.0.0. Use cassandra.query.ordered_dict_factory()

+
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.21.0-scylla/api/cassandra/encoder.html b/3.21.0-scylla/api/cassandra/encoder.html new file mode 100644 index 0000000000..c3a92770d8 --- /dev/null +++ b/3.21.0-scylla/api/cassandra/encoder.html @@ -0,0 +1,740 @@ + + + + + + + + + + + + + cassandra.encoder - Encoders for non-prepared Statements | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.encoder - Encoders for non-prepared Statements

+
+
+class cassandra.encoder.Encoder
+

A container for mapping python types to CQL string literals when working +with non-prepared statements. The type mapping can be +directly customized by users.

+
+
+mapping = None
+

A map of python types to encoder functions.

+
+ +
+
+cql_encode_none()
+

Converts None to the string ‘NULL’.

+
+ +
+
+cql_encode_object()
+

Default encoder for all objects that do not have a specific encoder function +registered. This function simply calls str() on the object.

+
+ +
+
+cql_encode_all_types()
+

Converts any type into a CQL string, defaulting to cql_encode_object +if mapping does not contain an entry for the type.

+
+ +
+
+cql_encode_sequence()
+

Converts a sequence to a string of the form (item1, item2, ...). This +is suitable for IN value lists.

+
+ +
+
+cql_encode_str()
+

Escapes quotes in str objects.

+
+ +
+
+cql_encode_unicode()
+

Converts unicode objects to UTF-8 encoded strings with quote escaping.

+
+ +
+
+cql_encode_bytes()
+

Converts strings, buffers, and bytearrays into CQL blob literals.

+
+ +
+
+cql_encode_datetime()
+

Converts a datetime.datetime object to a (string) integer timestamp +with millisecond precision.

+
+ +
+
+cql_encode_date()
+

Converts a datetime.date object to a string with format +YYYY-MM-DD.

+
+ +
+
+cql_encode_map_collection()
+

Converts a dict into a string of the form {key1: val1, key2: val2, ...}. +This is suitable for map type columns.

+
+ +
+
+cql_encode_list_collection()
+

Converts a sequence to a string of the form [item1, item2, ...]. This +is suitable for list type columns.

+
+ +
+
+cql_encode_set_collection()
+

Converts a sequence to a string of the form {item1, item2, ...}. This +is suitable for set type columns.

+
+ +
+
+cql_encode_tuple()
+

Converts a sequence to a string of the form (item1, item2, ...). This +is suitable for tuple type columns.

+
+ +
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.21.0-scylla/api/cassandra/graph.html b/3.21.0-scylla/api/cassandra/graph.html new file mode 100644 index 0000000000..62fff882b9 --- /dev/null +++ b/3.21.0-scylla/api/cassandra/graph.html @@ -0,0 +1,970 @@ + + + + + + + + + + + + + cassandra.graph - Graph Statements, Options, and Row Factories | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.graph - Graph Statements, Options, and Row Factories

+
+

Note

+

This module is only for backward compatibility for dse-driver users. Consider using cassandra.datastax.graph.

+
+
+
+cassandra.graph.single_object_row_factory(column_names, rows)
+

returns the JSON string value of graph results

+
+ +
+
+cassandra.graph.graph_result_row_factory(column_names, rows)
+

Returns a Result object that can load graph results and produce specific types. +The Result JSON is deserialized and unpacked from the top-level ‘result’ dict.

+
+ +
+
+cassandra.graph.graph_object_row_factory(column_names, rows)
+

Like graph_result_row_factory(), except known element types (Vertex, Edge) are +converted to their simplified objects. Some low-level metadata is shed in this conversion. Unknown result types are +still returned as Result.

+
+ +
+
+class cassandra.graph.GraphProtocol
+
+
+GRAPHSON_1_0 = b'graphson-1.0'
+

GraphSON1

+
+ +
+
+GRAPHSON_2_0 = b'graphson-2.0'
+

GraphSON2

+
+ +
+
+GRAPHSON_3_0 = b'graphson-3.0'
+

GraphSON3

+
+ +
+ +
+
+class cassandra.graph.GraphOptions(**kwargs)
+

Options for DSE Graph Query handler.

+
+
+graph_name
+

name of the targeted graph.

+
+ +
+
+graph_source
+

choose the graph traversal source, configured on the server side.

+
+ +
+
+graph_language
+

the language used in the queries (default “gremlin-groovy”)

+
+ +
+
+graph_read_consistency_level
+

read cassandra.ConsistencyLevel for graph queries (if distinct from session default). +Setting this overrides the native Statement.consistency_level for read operations from Cassandra persistence

+
+ +
+
+graph_write_consistency_level
+

write cassandra.ConsistencyLevel for graph queries (if distinct from session default). +Setting this overrides the native Statement.consistency_level for write operations to Cassandra persistence.

+
+ +
+
+is_default_source
+
+ +
+
+is_analytics_source
+

True if graph_source is set to the server-defined analytics traversal source (‘a’)

+
+ +
+
+is_graph_source
+

True if graph_source is set to the server-defined graph traversal source (‘g’)

+
+ +
+
+set_source_default()
+

Sets graph_source to the server-defined default traversal source (‘default’)

+
+ +
+
+set_source_analytics()
+

Sets graph_source to the server-defined analytic traversal source (‘a’)

+
+ +
+
+set_source_graph()
+

Sets graph_source to the server-defined graph traversal source (‘g’)

+
+ +
+ +
+
+class cassandra.graph.SimpleGraphStatement(query_string, retry_policy=None, consistency_level=None, routing_key=None, serial_consistency_level=None, fetch_size=<object object>, keyspace=None, custom_payload=None, is_idempotent=False)
+

Simple graph statement for Session.execute_graph(). +Takes the same parameters as SimpleStatement.

+

query_string should be a literal CQL statement with the exception +of parameter placeholders that will be filled through the +parameters argument of Session.execute().

+

See Statement attributes for a description of the other parameters.

+
+ +
+
+class cassandra.graph.Result(value)
+

Represents deserialized graph results. +Property and item getters are provided for convenience.

+
+
+value = None
+

Deserialized value from the result

+
+ +
+
+as_vertex()
+

Return a Vertex parsed from this result

+

Raises TypeError if parsing fails (i.e. the result structure is not valid).

+
+ +
+
+as_edge()
+

Return a Edge parsed from this result

+

Raises TypeError if parsing fails (i.e. the result structure is not valid).

+
+ +
+
+as_path()
+

Return a Path parsed from this result

+

Raises TypeError if parsing fails (i.e. the result structure is not valid).

+
+ +
+ +
+
+class cassandra.graph.Vertex(id, label, type, properties)
+

Represents a Vertex element from a graph query.

+

Vertex properties are extracted into a dict of property names to list of VertexProperty (list +because they are always encoded that way, and sometimes have multiple cardinality; VertexProperty because sometimes +the properties themselves have property maps).

+
+ +
+
+class cassandra.graph.VertexProperty(label, value, properties=None)
+

Vertex properties have a top-level value and an optional dict of properties.

+
+
+label = None
+

label of the property

+
+ +
+
+value = None
+

Value of the property

+
+ +
+
+properties = None
+

dict of properties attached to the property

+
+ +
+ +
+
+class cassandra.graph.Edge(id, label, type, properties, inV, inVLabel, outV, outVLabel)
+

Represents an Edge element from a graph query.

+

Attributes match initializer parameters.

+
+ +
+
+class cassandra.graph.Path(labels, objects)
+

Represents a graph path.

+

Labels list is taken verbatim from the results.

+

Objects are either Result or Vertex/Edge for recognized types

+
+
+labels = None
+

List of labels in the path

+
+ +
+
+objects = None
+

List of objects in the path

+
+ +
+ +
+
+class cassandra.graph.GraphSON1Serializer
+

Serialize python objects to graphson types.

+
+ +
+
+class cassandra.graph.GraphSON1Deserializer
+

Deserialize graphson1 types to python objects.

+
+
+classmethod deserialize_date(value)
+
+ +
+
+classmethod deserialize_timestamp(value)
+
+ +
+
+classmethod deserialize_time(value)
+
+ +
+
+classmethod deserialize_duration(value)
+
+ +
+
+classmethod deserialize_int(value)
+
+ +
+
+classmethod deserialize_bigint(value)
+
+ +
+
+classmethod deserialize_double(value)
+
+ +
+
+classmethod deserialize_float(value)
+
+ +
+
+classmethod deserialize_uuid(value)
+
+ +
+
+classmethod deserialize_blob(value)
+
+ +
+
+classmethod deserialize_decimal(value)
+
+ +
+
+classmethod deserialize_point(value)
+
+ +
+
+classmethod deserialize_linestring(value)
+
+ +
+
+classmethod deserialize_polygon(value)
+
+ +
+ +
+
+class cassandra.graph.GraphSON2Reader(context, extra_deserializer_map=None)
+

GraphSON2 Reader that parse json and deserialize to python objects.

+
+
Parameters
+

extra_deserializer_map – map from GraphSON type tag to deserializer instance implementing deserialize

+
+
+
+
+read(json_data)
+

Read and deserialize json_data.

+
+ +
+
+deserialize(obj)
+

Deserialize GraphSON type-tagged dict values into objects mapped in self.deserializers

+
+ +
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.21.0-scylla/api/cassandra/io/asyncioreactor.html b/3.21.0-scylla/api/cassandra/io/asyncioreactor.html new file mode 100644 index 0000000000..23a63c9320 --- /dev/null +++ b/3.21.0-scylla/api/cassandra/io/asyncioreactor.html @@ -0,0 +1,655 @@ + + + + + + + + + + + + + cassandra.io.asyncioreactor - asyncio Event Loop | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.io.asyncioreactor - asyncio Event Loop

+
+
+class cassandra.io.asyncioreactor.AsyncioConnection(*args, **kwargs)
+

An experimental implementation of Connection that uses the +asyncio module in the Python standard library for its event loop.

+

Note that it requires asyncio features that were only introduced in the +3.4 line in 3.4.6, and in the 3.5 line in 3.5.1.

+
+
+classmethod initialize_reactor()
+

Called once by Cluster.connect(). This should be used by implementations +to set up any resources that will be shared across connections.

+
+ +
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.21.0-scylla/api/cassandra/io/asyncorereactor.html b/3.21.0-scylla/api/cassandra/io/asyncorereactor.html new file mode 100644 index 0000000000..eeead2b40e --- /dev/null +++ b/3.21.0-scylla/api/cassandra/io/asyncorereactor.html @@ -0,0 +1,660 @@ + + + + + + + + + + + + + cassandra.io.asyncorereactor - asyncore Event Loop | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.io.asyncorereactor - asyncore Event Loop

+
+
+class cassandra.io.asyncorereactor.AsyncoreConnection(*args, **kwargs)
+

An implementation of Connection that uses the asyncore +module in the Python standard library for its event loop.

+
+
+classmethod initialize_reactor()
+

Called once by Cluster.connect(). This should be used by implementations +to set up any resources that will be shared across connections.

+
+ +
+
+classmethod handle_fork()
+

Called after a forking. This should cleanup any remaining reactor state +from the parent process.

+
+ +
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.21.0-scylla/api/cassandra/io/eventletreactor.html b/3.21.0-scylla/api/cassandra/io/eventletreactor.html new file mode 100644 index 0000000000..c603d35817 --- /dev/null +++ b/3.21.0-scylla/api/cassandra/io/eventletreactor.html @@ -0,0 +1,662 @@ + + + + + + + + + + + + + cassandra.io.eventletreactor - eventlet-compatible Connection | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.io.eventletreactor - eventlet-compatible Connection

+
+
+class cassandra.io.eventletreactor.EventletConnection(*args, **kwargs)
+

An implementation of Connection that utilizes eventlet.

+

This implementation assumes all eventlet monkey patching is active. It is not tested with partial patching.

+
+
+classmethod initialize_reactor()
+

Called once by Cluster.connect(). This should be used by implementations +to set up any resources that will be shared across connections.

+
+ +
+
+classmethod service_timeouts()
+

cls._timeout_watcher runs in this loop forever. +It is usually waiting for the next timeout on the cls._new_timer Event. +When new timers are added, that event is set so that the watcher can +wake up and possibly set an earlier timeout.

+
+ +
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.21.0-scylla/api/cassandra/io/geventreactor.html b/3.21.0-scylla/api/cassandra/io/geventreactor.html new file mode 100644 index 0000000000..c6ee8d6cb9 --- /dev/null +++ b/3.21.0-scylla/api/cassandra/io/geventreactor.html @@ -0,0 +1,653 @@ + + + + + + + + + + + + + cassandra.io.geventreactor - gevent-compatible Event Loop | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.io.geventreactor - gevent-compatible Event Loop

+
+
+class cassandra.io.geventreactor.GeventConnection(*args, **kwargs)
+

An implementation of Connection that utilizes gevent.

+

This implementation assumes all gevent monkey patching is active. It is not tested with partial patching.

+
+
+classmethod initialize_reactor()
+

Called once by Cluster.connect(). This should be used by implementations +to set up any resources that will be shared across connections.

+
+ +
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.21.0-scylla/api/cassandra/io/libevreactor.html b/3.21.0-scylla/api/cassandra/io/libevreactor.html new file mode 100644 index 0000000000..0ef1cee277 --- /dev/null +++ b/3.21.0-scylla/api/cassandra/io/libevreactor.html @@ -0,0 +1,645 @@ + + + + + + + + + + + + + cassandra.io.libevreactor - libev Event Loop | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.io.libevreactor - libev Event Loop

+
+
+class cassandra.io.libevreactor.LibevConnection(*args, **kwargs)
+

An implementation of Connection that uses libev for its event loop.

+
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.21.0-scylla/api/cassandra/io/twistedreactor.html b/3.21.0-scylla/api/cassandra/io/twistedreactor.html new file mode 100644 index 0000000000..bc0cad6766 --- /dev/null +++ b/3.21.0-scylla/api/cassandra/io/twistedreactor.html @@ -0,0 +1,646 @@ + + + + + + + + + + + + + cassandra.io.twistedreactor - Twisted Event Loop | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.io.twistedreactor - Twisted Event Loop

+
+
+class cassandra.io.twistedreactor.TwistedConnection
+

An implementation of Connection that uses +Twisted’s reactor as its event loop.

+
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.21.0-scylla/api/cassandra/metadata.html b/3.21.0-scylla/api/cassandra/metadata.html new file mode 100644 index 0000000000..a2634001ad --- /dev/null +++ b/3.21.0-scylla/api/cassandra/metadata.html @@ -0,0 +1,986 @@ + + + + + + + + + + + + + cassandra.metadata - Schema and Ring Topology | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.metadata - Schema and Ring Topology

+
+
+cassandra.metadata.cql_keywords
+

set() -> new empty set object +set(iterable) -> new set object

+

Build an unordered collection of unique elements.

+
+ +
+
+cassandra.metadata.cql_keywords_unreserved
+

set() -> new empty set object +set(iterable) -> new set object

+

Build an unordered collection of unique elements.

+
+ +
+
+cassandra.metadata.cql_keywords_reserved
+

set() -> new empty set object +set(iterable) -> new set object

+

Build an unordered collection of unique elements.

+
+ +
+
+class cassandra.metadata.Metadata
+

Holds a representation of the cluster schema and topology.

+
+
+add_or_return_host(host)
+

Returns a tuple (host, new), where host is a Host +instance, and new is a bool indicating whether +the host was newly added.

+
+ +
+
+all_hosts()
+

Returns a list of all known Host instances in the cluster.

+
+ +
+
+export_schema_as_string()
+

Returns a string that can be executed as a query in order to recreate +the entire schema. The string is formatted to be human readable.

+
+ +
+
+get_host(endpoint_or_address, port=None)
+

Find a host in the metadata for a specific endpoint. If a string inet address and port are passed, +iterate all hosts to match the broadcast_rpc_address and +broadcast_rpc_port attributes.

+
+ +
+
+get_host_by_host_id(host_id)
+

Same as get_host() but use host_id for lookup.

+
+ +
+
+get_replicas(keyspace, key)
+

Returns a list of Host instances that are replicas for a given +partition key.

+
+ +
+ +
+

Schemas

+
+
+class cassandra.metadata.KeyspaceMetadata
+

A representation of the schema for a single keyspace.

+
+
+as_cql_query()
+

Returns a CQL query string that can be used to recreate just this keyspace, +not including user-defined types and tables.

+
+ +
+
+export_as_string()
+

Returns a CQL query string that can be used to recreate the entire keyspace, +including user-defined types and tables.

+
+ +
+ +
+
+class cassandra.metadata.UserType
+

A user defined type, as created by CREATE TYPE statements.

+

User-defined types were introduced in Cassandra 2.1.

+
+

New in version 2.1.0.

+
+
+
+as_cql_query(formatted=False)
+

Returns a CQL query that can be used to recreate this type. +If formatted is set to True, extra whitespace will +be added to make the query more readable.

+
+ +
+ +
+
+class cassandra.metadata.Function
+

A user defined function, as created by CREATE FUNCTION statements.

+

User-defined functions were introduced in Cassandra 2.2

+
+

New in version 2.6.0.

+
+
+
+as_cql_query(formatted=False)
+

Returns a CQL query that can be used to recreate this function. +If formatted is set to True, extra whitespace will +be added to make the query more readable.

+
+ +
+ +
+
+class cassandra.metadata.Aggregate
+

A user defined aggregate function, as created by CREATE AGGREGATE statements.

+

Aggregate functions were introduced in Cassandra 2.2

+
+

New in version 2.6.0.

+
+
+
+as_cql_query(formatted=False)
+

Returns a CQL query that can be used to recreate this aggregate. +If formatted is set to True, extra whitespace will +be added to make the query more readable.

+
+ +
+ +
+
+class cassandra.metadata.TableMetadata
+

A representation of the schema for a single table.

+
+
+as_cql_query(formatted=False)
+

Returns a CQL query that can be used to recreate this table (index +creations are not included). If formatted is set to True, +extra whitespace will be added to make the query human readable.

+
+ +
+
+export_as_string()
+

Returns a string of CQL queries that can be used to recreate this table +along with all indexes on it. The returned string is formatted to +be human readable.

+
+ +
+
+property is_cql_compatible
+

A boolean indicating if this table can be represented as CQL in export

+
+ +
+
+property primary_key
+

A list of ColumnMetadata representing the components of +the primary key for this table.

+
+ +
+ +
+
+class cassandra.metadata.ColumnMetadata
+

A representation of a single column in a table.

+
+ +
+
+class cassandra.metadata.IndexMetadata
+

A representation of a secondary index on a column.

+
+
+as_cql_query()
+

Returns a CQL query that can be used to recreate this index.

+
+ +
+
+export_as_string()
+

Returns a CQL query string that can be used to recreate this index.

+
+ +
+ +
+
+class cassandra.metadata.MaterializedViewMetadata
+

A representation of a materialized view on a table

+
+
+as_cql_query(formatted=False)
+

Returns a CQL query that can be used to recreate this function. +If formatted is set to True, extra whitespace will +be added to make the query more readable.

+
+ +
+ +
+
+

Tokens and Ring Topology

+
+
+class cassandra.metadata.TokenMap
+

Information about the layout of the ring.

+
+
+get_replicas(keyspace, token)
+

Get a set of Host instances representing all of the +replica nodes for a given Token.

+
+ +
+ +
+
+class cassandra.metadata.Token
+

Abstract class representing a token.

+
+ +
+
+class cassandra.metadata.Murmur3Token(token)
+

A token for Murmur3Partitioner.

+

token is an int or string representing the token.

+
+ +
+
+class cassandra.metadata.MD5Token(token)
+

A token for RandomPartitioner.

+
+ +
+
+class cassandra.metadata.BytesToken(token)
+

A token for ByteOrderedPartitioner.

+
+
+classmethod from_string(token_string)
+

token_string should be the string representation from the server.

+
+ +
+ +
+
+cassandra.metadata.ReplicationStrategy
+

alias of cassandra.metadata._ReplicationStrategy

+
+ +
+
+class cassandra.metadata.SimpleStrategy(options_map)
+
+
+export_for_schema()
+

Returns a string version of these replication options which are +suitable for use in a CREATE KEYSPACE statement.

+
+ +
+
+property replication_factor
+

The replication factor for this keyspace.

+

For backward compatibility, this returns the +cassandra.metadata.ReplicationFactor.full_replicas value of +cassandra.metadata.SimpleStrategy.replication_factor_info.

+
+ +
+ +
+
+class cassandra.metadata.NetworkTopologyStrategy(dc_replication_factors)
+
+
+export_for_schema()
+

Returns a string version of these replication options which are +suitable for use in a CREATE KEYSPACE statement.

+
+ +
+ +
+
+class cassandra.metadata.LocalStrategy(options_map)
+
+
+export_for_schema()
+

Returns a string version of these replication options which are +suitable for use in a CREATE KEYSPACE statement.

+
+ +
+ +
+
+cassandra.metadata.group_keys_by_replica(session, keyspace, table, keys)
+

Returns a dict with the keys grouped per host. This can be +used to more accurately group by IN clause or to batch the keys per host.

+

If a valid replica is not found for a particular key it will be grouped under +NO_VALID_REPLICA

+

Example usage:

+
>>> result = group_keys_by_replica(
+...     session, "system", "peers",
+...     (("127.0.0.1", ), ("127.0.0.2", )))
+
+
+
+ +
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.21.0-scylla/api/cassandra/metrics.html b/3.21.0-scylla/api/cassandra/metrics.html new file mode 100644 index 0000000000..f82c135cf9 --- /dev/null +++ b/3.21.0-scylla/api/cassandra/metrics.html @@ -0,0 +1,753 @@ + + + + + + + + + + + + + cassandra.metrics - Performance Metrics | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.metrics - Performance Metrics

+
+
+class cassandra.metrics.Metrics
+

A collection of timers and counters for various performance metrics.

+

Timer metrics are represented as floating point seconds.

+
+
+request_timer = None
+

A greplin.scales.PmfStat timer for requests. This is a dict-like +object with the following keys:

+
    +
  • count - number of requests that have been timed

  • +
  • min - min latency

  • +
  • max - max latency

  • +
  • mean - mean latency

  • +
  • stddev - standard deviation for latencies

  • +
  • median - median latency

  • +
  • 75percentile - 75th percentile latencies

  • +
  • 95percentile - 95th percentile latencies

  • +
  • 98percentile - 98th percentile latencies

  • +
  • 99percentile - 99th percentile latencies

  • +
  • 999percentile - 99.9th percentile latencies

  • +
+
+ +
+
+connection_errors = None
+

A greplin.scales.IntStat count of the number of times that a +request to a Cassandra node has failed due to a connection problem.

+
+ +
+
+write_timeouts = None
+

A greplin.scales.IntStat count of write requests that resulted +in a timeout.

+
+ +
+
+read_timeouts = None
+

A greplin.scales.IntStat count of read requests that resulted +in a timeout.

+
+ +
+
+unavailables = None
+

A greplin.scales.IntStat count of write or read requests that +failed due to an insufficient number of replicas being alive to meet +the requested ConsistencyLevel.

+
+ +
+
+other_errors = None
+

A greplin.scales.IntStat count of all other request failures, +including failures caused by invalid requests, bootstrapping nodes, +overloaded nodes, etc.

+
+ +
+
+retries = None
+

A greplin.scales.IntStat count of the number of times a +request was retried based on the RetryPolicy decision.

+
+ +
+
+ignores = None
+

A greplin.scales.IntStat count of the number of times a +failed request was ignored based on the RetryPolicy decision.

+
+ +
+
+known_hosts = None
+

A greplin.scales.IntStat count of the number of nodes in +the cluster that the driver is aware of, regardless of whether any +connections are opened to those nodes.

+
+ +
+
+connected_to = None
+

A greplin.scales.IntStat count of the number of nodes that +the driver currently has at least one connection open to.

+
+ +
+
+open_connections = None
+

A greplin.scales.IntStat count of the number connections +the driver currently has open.

+
+ +
+
+get_stats()
+

Returns the metrics for the registered cluster instance.

+
+ +
+
+set_stats_name(stats_name)
+

Set the metrics stats name. +The stats_name is a string used to access the metris through scales: scales.getStats()[<stats_name>] +Default is ‘cassandra-<num>’.

+
+ +
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.21.0-scylla/api/cassandra/policies.html b/3.21.0-scylla/api/cassandra/policies.html new file mode 100644 index 0000000000..3fb2efbeb8 --- /dev/null +++ b/3.21.0-scylla/api/cassandra/policies.html @@ -0,0 +1,1740 @@ + + + + + + + + + + + + + cassandra.policies - Load balancing and Failure Handling Policies | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.policies - Load balancing and Failure Handling Policies

+
+

Load Balancing

+
+
+class cassandra.policies.HostDistance
+

A measure of how “distant” a node is from the client, which +may influence how the load balancer distributes requests +and how many connections are opened to the node.

+
+
+IGNORED = -1
+

A node with this distance should never be queried or have +connections opened to it.

+
+ +
+
+LOCAL = 0
+

Nodes with LOCAL distance will be preferred for operations +under some load balancing policies (such as DCAwareRoundRobinPolicy) +and will have a greater number of connections opened against +them by default.

+

This distance is typically used for nodes within the same +datacenter as the client.

+
+ +
+
+REMOTE = 1
+

Nodes with REMOTE distance will be treated as a last resort +by some load balancing policies (such as DCAwareRoundRobinPolicy) +and will have a smaller number of connections opened against +them by default.

+

This distance is typically used for nodes outside of the +datacenter that the client is running in.

+
+ +
+ +
+
+class cassandra.policies.LoadBalancingPolicy
+

Load balancing policies are used to decide how to distribute +requests among all possible coordinator nodes in the cluster.

+

In particular, they may focus on querying “near” nodes (those +in a local datacenter) or on querying nodes who happen to +be replicas for the requested data.

+

You may also use subclasses of LoadBalancingPolicy for +custom behavior.

+
+
+distance(host)
+

Returns a measure of how remote a Host is in +terms of the HostDistance enums.

+
+ +
+
+populate(cluster, hosts)
+

This method is called to initialize the load balancing +policy with a set of Host instances before its +first use. The cluster parameter is an instance of +Cluster.

+
+ +
+
+make_query_plan(working_keyspace=None, query=None)
+

Given a Statement instance, return a iterable +of Host instances which should be queried in that +order. A generator may work well for custom implementations +of this method.

+

Note that the query argument may be None when preparing +statements.

+

working_keyspace should be the string name of the current keyspace, +as set through Session.set_keyspace() or with a USE +statement.

+
+ +
+
+check_supported()
+

This will be called after the cluster Metadata has been initialized. +If the load balancing policy implementation cannot be supported for +some reason (such as a missing C extension), this is the point at +which it should raise an exception.

+
+ +
+ +
+
+class cassandra.policies.RoundRobinPolicy
+

A subclass of LoadBalancingPolicy which evenly +distributes queries across all nodes in the cluster, +regardless of what datacenter the nodes may be in.

+
+
+populate(cluster, hosts)
+

This method is called to initialize the load balancing +policy with a set of Host instances before its +first use. The cluster parameter is an instance of +Cluster.

+
+ +
+
+distance(host)
+

Returns a measure of how remote a Host is in +terms of the HostDistance enums.

+
+ +
+
+make_query_plan(working_keyspace=None, query=None)
+

Given a Statement instance, return a iterable +of Host instances which should be queried in that +order. A generator may work well for custom implementations +of this method.

+

Note that the query argument may be None when preparing +statements.

+

working_keyspace should be the string name of the current keyspace, +as set through Session.set_keyspace() or with a USE +statement.

+
+ +
+
+on_up(host)
+

Called when a node is marked up.

+
+ +
+
+on_down(host)
+

Called when a node is marked down.

+
+ +
+
+on_add(host)
+

Called when a node is added to the cluster. The newly added node +should be considered up.

+
+ +
+
+on_remove(host)
+

Called when a node is removed from the cluster.

+
+ +
+ +
+
+class cassandra.policies.DCAwareRoundRobinPolicy(local_dc='', used_hosts_per_remote_dc=0)
+

Similar to RoundRobinPolicy, but prefers hosts +in the local datacenter and only uses nodes in remote +datacenters as a last resort.

+

The local_dc parameter should be the name of the datacenter +(such as is reported by nodetool ring) that should +be considered local. If not specified, the driver will choose +a local_dc based on the first host among Cluster.contact_points +having a valid DC. If relying on this mechanism, all specified +contact points should be nodes in a single, local DC.

+

used_hosts_per_remote_dc controls how many nodes in +each remote datacenter will have connections opened +against them. In other words, used_hosts_per_remote_dc hosts +will be considered REMOTE and the +rest will be considered IGNORED. +By default, all remote hosts are ignored.

+
+
+populate(cluster, hosts)
+

This method is called to initialize the load balancing +policy with a set of Host instances before its +first use. The cluster parameter is an instance of +Cluster.

+
+ +
+
+distance(host)
+

Returns a measure of how remote a Host is in +terms of the HostDistance enums.

+
+ +
+
+make_query_plan(working_keyspace=None, query=None)
+

Given a Statement instance, return a iterable +of Host instances which should be queried in that +order. A generator may work well for custom implementations +of this method.

+

Note that the query argument may be None when preparing +statements.

+

working_keyspace should be the string name of the current keyspace, +as set through Session.set_keyspace() or with a USE +statement.

+
+ +
+
+on_up(host)
+

Called when a node is marked up.

+
+ +
+
+on_down(host)
+

Called when a node is marked down.

+
+ +
+
+on_add(host)
+

Called when a node is added to the cluster. The newly added node +should be considered up.

+
+ +
+
+on_remove(host)
+

Called when a node is removed from the cluster.

+
+ +
+ +
+
+class cassandra.policies.WhiteListRoundRobinPolicy(hosts)
+

A subclass of RoundRobinPolicy which evenly +distributes queries across all nodes in the cluster, +regardless of what datacenter the nodes may be in, but +only if that node exists in the list of allowed nodes

+

This policy is addresses the issue described in +https://datastax-oss.atlassian.net/browse/JAVA-145 +Where connection errors occur when connection +attempts are made to private IP addresses remotely

+

The hosts parameter should be a sequence of hosts to permit +connections to.

+
+
+populate(cluster, hosts)
+

This method is called to initialize the load balancing +policy with a set of Host instances before its +first use. The cluster parameter is an instance of +Cluster.

+
+ +
+
+distance(host)
+

Returns a measure of how remote a Host is in +terms of the HostDistance enums.

+
+ +
+
+on_up(host)
+

Called when a node is marked up.

+
+ +
+
+on_add(host)
+

Called when a node is added to the cluster. The newly added node +should be considered up.

+
+ +
+ +
+
+class cassandra.policies.TokenAwarePolicy(child_policy, shuffle_replicas=False)
+

A LoadBalancingPolicy wrapper that adds token awareness to +a child policy.

+

This alters the child policy’s behavior so that it first attempts to +send queries to LOCAL replicas (as determined +by the child policy) based on the Statement’s +routing_key. If shuffle_replicas is +truthy, these replicas will be yielded in a random order. Once those +hosts are exhausted, the remaining hosts in the child policy’s query +plan will be used in the order provided by the child policy.

+

If no routing_key is set on the query, the child +policy’s query plan will be used as is.

+
+
+shuffle_replicas = False
+

Yield local replicas in a random order.

+
+ +
+
+populate(cluster, hosts)
+

This method is called to initialize the load balancing +policy with a set of Host instances before its +first use. The cluster parameter is an instance of +Cluster.

+
+ +
+
+check_supported()
+

This will be called after the cluster Metadata has been initialized. +If the load balancing policy implementation cannot be supported for +some reason (such as a missing C extension), this is the point at +which it should raise an exception.

+
+ +
+
+distance(*args, **kwargs)
+

Returns a measure of how remote a Host is in +terms of the HostDistance enums.

+
+ +
+
+make_query_plan(working_keyspace=None, query=None)
+

Given a Statement instance, return a iterable +of Host instances which should be queried in that +order. A generator may work well for custom implementations +of this method.

+

Note that the query argument may be None when preparing +statements.

+

working_keyspace should be the string name of the current keyspace, +as set through Session.set_keyspace() or with a USE +statement.

+
+ +
+
+on_up(*args, **kwargs)
+

Called when a node is marked up.

+
+ +
+
+on_down(*args, **kwargs)
+

Called when a node is marked down.

+
+ +
+
+on_add(*args, **kwargs)
+

Called when a node is added to the cluster. The newly added node +should be considered up.

+
+ +
+
+on_remove(*args, **kwargs)
+

Called when a node is removed from the cluster.

+
+ +
+ +
+
+class cassandra.policies.HostFilterPolicy(child_policy, predicate)
+

A LoadBalancingPolicy subclass configured with a child policy, +and a single-argument predicate. This policy defers to the child policy for +hosts where predicate(host) is truthy. Hosts for which +predicate(host) is falsey will be considered IGNORED, and will +not be used in a query plan.

+

This can be used in the cases where you need a whitelist or blacklist +policy, e.g. to prepare for decommissioning nodes or for testing:

+
def address_is_ignored(host):
+    return host.address in [ignored_address0, ignored_address1]
+
+blacklist_filter_policy = HostFilterPolicy(
+    child_policy=RoundRobinPolicy(),
+    predicate=address_is_ignored
+)
+
+cluster = Cluster(
+    primary_host,
+    load_balancing_policy=blacklist_filter_policy,
+)
+
+
+

See the note in the make_query_plan() documentation for a caveat on +how wrapping ordering polices (e.g. RoundRobinPolicy) may break +desirable properties of the wrapped policy.

+

Please note that whitelist and blacklist policies are not recommended for +general, day-to-day use. You probably want something like +DCAwareRoundRobinPolicy, which prefers a local DC but has +fallbacks, over a brute-force method like whitelisting or blacklisting.

+
+
Parameters
+
    +
  • child_policy – an instantiated LoadBalancingPolicy +that this one will defer to.

  • +
  • predicate – a one-parameter function that takes a Host. +If it returns a falsey value, the Host will +be IGNORED and not returned in query plans.

  • +
+
+
+
+
+predicate(host)
+

A predicate, set on object initialization, that takes a Host +and returns a value. If the value is falsy, the Host is +IGNORED. If the value is truthy, +HostFilterPolicy defers to the child policy to determine the +host’s distance.

+

This is a read-only value set in __init__, implemented as a +property.

+
+ +
+
+distance(host)
+

Checks if predicate(host), then returns +IGNORED if falsey, and defers to the child policy +otherwise.

+
+ +
+
+make_query_plan(working_keyspace=None, query=None)
+

Defers to the child policy’s +LoadBalancingPolicy.make_query_plan() and filters the results.

+

Note that this filtering may break desirable properties of the wrapped +policy in some cases. For instance, imagine if you configure this +policy to filter out host2, and to wrap a round-robin policy that +rotates through three hosts in the order host1, host2, host3, +host2, host3, host1, host3, host1, host2, repeating. This +policy will yield host1, host3, host3, host1, host3, host1, +disproportionately favoring host3.

+
+ +
+ +
+
+class cassandra.policies.DefaultLoadBalancingPolicy(child_policy)
+

A LoadBalancingPolicy wrapper that adds the ability to target a specific host first.

+

If no host is set on the query, the child policy’s query plan will be used as is.

+
+
+populate(cluster, hosts)
+

This method is called to initialize the load balancing +policy with a set of Host instances before its +first use. The cluster parameter is an instance of +Cluster.

+
+ +
+
+make_query_plan(working_keyspace=None, query=None)
+

Given a Statement instance, return a iterable +of Host instances which should be queried in that +order. A generator may work well for custom implementations +of this method.

+

Note that the query argument may be None when preparing +statements.

+

working_keyspace should be the string name of the current keyspace, +as set through Session.set_keyspace() or with a USE +statement.

+
+ +
+ +
+
+class cassandra.policies.DSELoadBalancingPolicy(*args, **kwargs)
+

Deprecated: This will be removed in the next major release, +consider using DefaultLoadBalancingPolicy.

+
+ +
+
+

Translating Server Node Addresses

+
+
+class cassandra.policies.AddressTranslator
+

Interface for translating cluster-defined endpoints.

+

The driver discovers nodes using server metadata and topology change events. Normally, +the endpoint defined by the server is the right way to connect to a node. In some environments, +these addresses may not be reachable, or not preferred (public vs. private IPs in cloud environments, +suboptimal routing, etc). This interface allows for translating from server defined endpoints to +preferred addresses for driver connections.

+

Note: contact_points provided while creating the Cluster instance are not +translated using this mechanism – only addresses received from Cassandra nodes are.

+
+
+translate(addr)
+

Accepts the node ip address, and returns a translated address to be used connecting to this node.

+
+ +
+ +
+
+class cassandra.policies.IdentityTranslator
+

Returns the endpoint with no translation

+
+
+translate(addr)
+

Accepts the node ip address, and returns a translated address to be used connecting to this node.

+
+ +
+ +
+
+class cassandra.policies.EC2MultiRegionTranslator
+

Resolves private ips of the hosts in the same datacenter as the client, and public ips of hosts in other datacenters.

+
+
+translate(addr)
+

Reverse DNS the public broadcast_address, then lookup that hostname to get the AWS-resolved IP, which +will point to the private IP address within the same datacenter.

+
+ +
+ +
+
+

Marking Hosts Up or Down

+
+
+class cassandra.policies.ConvictionPolicy(host)
+

A policy which decides when hosts should be considered down +based on the types of failures and the number of failures.

+

If custom behavior is needed, this class may be subclassed.

+

host is an instance of Host.

+
+
+add_failure(connection_exc)
+

Implementations should return True if the host should be +convicted, False otherwise.

+
+ +
+
+reset()
+

Implementations should clear out any convictions or state regarding +the host.

+
+ +
+ +
+
+class cassandra.policies.SimpleConvictionPolicy(host)
+

The default implementation of ConvictionPolicy, +which simply marks a host as down after the first failure +of any kind.

+

host is an instance of Host.

+
+
+add_failure(connection_exc)
+

Implementations should return True if the host should be +convicted, False otherwise.

+
+ +
+
+reset()
+

Implementations should clear out any convictions or state regarding +the host.

+
+ +
+ +
+
+

Reconnecting to Dead Hosts

+
+
+class cassandra.policies.ReconnectionPolicy
+

This class and its subclasses govern how frequently an attempt is made +to reconnect to nodes that are marked as dead.

+

If custom behavior is needed, this class may be subclassed.

+
+
+new_schedule()
+

This should return a finite or infinite iterable of delays (each as a +floating point number of seconds) inbetween each failed reconnection +attempt. Note that if the iterable is finite, reconnection attempts +will cease once the iterable is exhausted.

+
+ +
+ +
+
+class cassandra.policies.ConstantReconnectionPolicy(delay, max_attempts=64)
+

A ReconnectionPolicy subclass which sleeps for a fixed delay +inbetween each reconnection attempt.

+

delay should be a floating point number of seconds to wait inbetween +each attempt.

+

max_attempts should be a total number of attempts to be made before +giving up, or None to continue reconnection attempts forever. +The default is 64.

+
+
+new_schedule()
+

This should return a finite or infinite iterable of delays (each as a +floating point number of seconds) inbetween each failed reconnection +attempt. Note that if the iterable is finite, reconnection attempts +will cease once the iterable is exhausted.

+
+ +
+ +
+
+class cassandra.policies.ExponentialReconnectionPolicy(base_delay, max_delay, max_attempts=64)
+

A ReconnectionPolicy subclass which exponentially increases +the length of the delay inbetween each reconnection attempt up to +a set maximum delay.

+

A random amount of jitter (+/- 15%) will be added to the pure exponential +delay value to avoid the situations where many reconnection handlers are +trying to reconnect at exactly the same time.

+

base_delay and max_delay should be in floating point units of +seconds.

+

max_attempts should be a total number of attempts to be made before +giving up, or None to continue reconnection attempts forever. +The default is 64.

+
+
+new_schedule()
+

This should return a finite or infinite iterable of delays (each as a +floating point number of seconds) inbetween each failed reconnection +attempt. Note that if the iterable is finite, reconnection attempts +will cease once the iterable is exhausted.

+
+ +
+ +
+
+

Retrying Failed Operations

+
+
+class cassandra.policies.WriteType
+

For usage with RetryPolicy, this describe a type +of write operation.

+
+
+SIMPLE = 0
+

A write to a single partition key. Such writes are guaranteed to be atomic +and isolated.

+
+ +
+
+BATCH = 1
+

A write to multiple partition keys that used the distributed batch log to +ensure atomicity.

+
+ +
+
+UNLOGGED_BATCH = 2
+

A write to multiple partition keys that did not use the distributed batch +log. Atomicity for such writes is not guaranteed.

+
+ +
+
+COUNTER = 3
+

A counter write (for one or multiple partition keys). Such writes should +not be replayed in order to avoid overcount.

+
+ +
+
+BATCH_LOG = 4
+

The initial write to the distributed batch log that Cassandra performs +internally before a BATCH write.

+
+ +
+
+CAS = 5
+

A lighweight-transaction write, such as “DELETE … IF EXISTS”.

+
+ +
+
+VIEW = 6
+

This WriteType is only seen in results for requests that were unable to +complete MV operations.

+
+ +
+
+CDC = 7
+

This WriteType is only seen in results for requests that were unable to +complete CDC operations.

+
+ +
+ +
+
+class cassandra.policies.RetryPolicy
+

A policy that describes whether to retry, rethrow, or ignore coordinator +timeout and unavailable failures. These are failures reported from the +server side. Timeouts are configured by +settings in cassandra.yaml. +Unavailable failures occur when the coordinator cannot acheive the consistency +level for a request. For further information see the method descriptions +below.

+

To specify a default retry policy, set the +Cluster.default_retry_policy attribute to an instance of this +class or one of its subclasses.

+

To specify a retry policy per query, set the Statement.retry_policy +attribute to an instance of this class or one of its subclasses.

+

If custom behavior is needed for retrying certain operations, +this class may be subclassed.

+
+
+RETRY = 0
+

This should be returned from the below methods if the operation +should be retried on the same connection.

+
+ +
+
+RETHROW = 1
+

This should be returned from the below methods if the failure +should be propagated and no more retries attempted.

+
+ +
+
+IGNORE = 2
+

This should be returned from the below methods if the failure +should be ignored but no more retries should be attempted.

+
+ +
+
+RETRY_NEXT_HOST = 3
+

This should be returned from the below methods if the operation +should be retried on another connection.

+
+ +
+
+on_read_timeout(query, consistency, required_responses, received_responses, data_retrieved, retry_num)
+

This is called when a read operation times out from the coordinator’s +perspective (i.e. a replica did not respond to the coordinator in time). +It should return a tuple with two items: one of the class enums (such +as RETRY) and a ConsistencyLevel to retry the +operation at or None to keep the same consistency level.

+

query is the Statement that timed out.

+

consistency is the ConsistencyLevel that the operation was +attempted at.

+

The required_responses and received_responses parameters describe +how many replicas needed to respond to meet the requested consistency +level and how many actually did respond before the coordinator timed +out the request. data_retrieved is a boolean indicating whether +any of those responses contained data (as opposed to just a digest).

+

retry_num counts how many times the operation has been retried, so +the first time this method is called, retry_num will be 0.

+

By default, operations will be retried at most once, and only if +a sufficient number of replicas responded (with data digests).

+
+ +
+
+on_write_timeout(query, consistency, write_type, required_responses, received_responses, retry_num)
+

This is called when a write operation times out from the coordinator’s +perspective (i.e. a replica did not respond to the coordinator in time).

+

query is the Statement that timed out.

+

consistency is the ConsistencyLevel that the operation was +attempted at.

+

write_type is one of the WriteType enums describing the +type of write operation.

+

The required_responses and received_responses parameters describe +how many replicas needed to acknowledge the write to meet the requested +consistency level and how many replicas actually did acknowledge the +write before the coordinator timed out the request.

+

retry_num counts how many times the operation has been retried, so +the first time this method is called, retry_num will be 0.

+

By default, failed write operations will retried at most once, and +they will only be retried if the write_type was +BATCH_LOG.

+
+ +
+
+on_unavailable(query, consistency, required_replicas, alive_replicas, retry_num)
+

This is called when the coordinator node determines that a read or +write operation cannot be successful because the number of live +replicas are too low to meet the requested ConsistencyLevel. +This means that the read or write operation was never forwarded to +any replicas.

+

query is the Statement that failed.

+

consistency is the ConsistencyLevel that the operation was +attempted at.

+

required_replicas is the number of replicas that would have needed to +acknowledge the operation to meet the requested consistency level. +alive_replicas is the number of replicas that the coordinator +considered alive at the time of the request.

+

retry_num counts how many times the operation has been retried, so +the first time this method is called, retry_num will be 0.

+

By default, if this is the first retry, it triggers a retry on the next +host in the query plan with the same consistency level. If this is not the +first retry, no retries will be attempted and the error will be re-raised.

+
+ +
+
+on_request_error(query, consistency, error, retry_num)
+

This is called when an unexpected error happens. This can be in the +following situations:

+
    +
  • On a connection error

  • +
  • On server errors: overloaded, isBootstrapping, serverError, etc.

  • +
+

query is the Statement that timed out.

+

consistency is the ConsistencyLevel that the operation was +attempted at.

+

error the instance of the exception.

+

retry_num counts how many times the operation has been retried, so +the first time this method is called, retry_num will be 0.

+

The default, it triggers a retry on the next host in the query plan +with the same consistency level.

+
+ +
+ +
+
+class cassandra.policies.FallthroughRetryPolicy
+

A retry policy that never retries and always propagates failures to +the application.

+
+
+on_read_timeout(*args, **kwargs)
+

This is called when a read operation times out from the coordinator’s +perspective (i.e. a replica did not respond to the coordinator in time). +It should return a tuple with two items: one of the class enums (such +as RETRY) and a ConsistencyLevel to retry the +operation at or None to keep the same consistency level.

+

query is the Statement that timed out.

+

consistency is the ConsistencyLevel that the operation was +attempted at.

+

The required_responses and received_responses parameters describe +how many replicas needed to respond to meet the requested consistency +level and how many actually did respond before the coordinator timed +out the request. data_retrieved is a boolean indicating whether +any of those responses contained data (as opposed to just a digest).

+

retry_num counts how many times the operation has been retried, so +the first time this method is called, retry_num will be 0.

+

By default, operations will be retried at most once, and only if +a sufficient number of replicas responded (with data digests).

+
+ +
+
+on_write_timeout(*args, **kwargs)
+

This is called when a write operation times out from the coordinator’s +perspective (i.e. a replica did not respond to the coordinator in time).

+

query is the Statement that timed out.

+

consistency is the ConsistencyLevel that the operation was +attempted at.

+

write_type is one of the WriteType enums describing the +type of write operation.

+

The required_responses and received_responses parameters describe +how many replicas needed to acknowledge the write to meet the requested +consistency level and how many replicas actually did acknowledge the +write before the coordinator timed out the request.

+

retry_num counts how many times the operation has been retried, so +the first time this method is called, retry_num will be 0.

+

By default, failed write operations will retried at most once, and +they will only be retried if the write_type was +BATCH_LOG.

+
+ +
+
+on_unavailable(*args, **kwargs)
+

This is called when the coordinator node determines that a read or +write operation cannot be successful because the number of live +replicas are too low to meet the requested ConsistencyLevel. +This means that the read or write operation was never forwarded to +any replicas.

+

query is the Statement that failed.

+

consistency is the ConsistencyLevel that the operation was +attempted at.

+

required_replicas is the number of replicas that would have needed to +acknowledge the operation to meet the requested consistency level. +alive_replicas is the number of replicas that the coordinator +considered alive at the time of the request.

+

retry_num counts how many times the operation has been retried, so +the first time this method is called, retry_num will be 0.

+

By default, if this is the first retry, it triggers a retry on the next +host in the query plan with the same consistency level. If this is not the +first retry, no retries will be attempted and the error will be re-raised.

+
+ +
+
+on_request_error(*args, **kwargs)
+

This is called when an unexpected error happens. This can be in the +following situations:

+
    +
  • On a connection error

  • +
  • On server errors: overloaded, isBootstrapping, serverError, etc.

  • +
+

query is the Statement that timed out.

+

consistency is the ConsistencyLevel that the operation was +attempted at.

+

error the instance of the exception.

+

retry_num counts how many times the operation has been retried, so +the first time this method is called, retry_num will be 0.

+

The default, it triggers a retry on the next host in the query plan +with the same consistency level.

+
+ +
+ +
+
+class cassandra.policies.DowngradingConsistencyRetryPolicy(*args, **kwargs)
+

Deprecated: This retry policy will be removed in the next major release.

+

A retry policy that sometimes retries with a lower consistency level than +the one initially requested.

+

BEWARE: This policy may retry queries using a lower consistency +level than the one initially requested. By doing so, it may break +consistency guarantees. In other words, if you use this retry policy, +there are cases (documented below) where a read at QUORUM +may not see a preceding write at QUORUM. Do not use this +policy unless you have understood the cases where this can happen and +are ok with that. It is also recommended to subclass this class so +that queries that required a consistency level downgrade can be +recorded (so that repairs can be made later, etc).

+

This policy implements the same retries as RetryPolicy, +but on top of that, it also retries in the following cases:

+
    +
  • On a read timeout: if the number of replicas that responded is +greater than one but lower than is required by the requested +consistency level, the operation is retried at a lower consistency +level.

  • +
  • On a write timeout: if the operation is an UNLOGGED_BATCH +and at least one replica acknowledged the write, the operation is +retried at a lower consistency level. Furthermore, for other +write types, if at least one replica acknowledged the write, the +timeout is ignored.

  • +
  • On an unavailable exception: if at least one replica is alive, the +operation is retried at a lower consistency level.

  • +
+

The reasoning behind this retry policy is as follows: if, based +on the information the Cassandra coordinator node returns, retrying the +operation with the initially requested consistency has a chance to +succeed, do it. Otherwise, if based on that information we know the +initially requested consistency level cannot be achieved currently, then:

+
    +
  • For writes, ignore the exception (thus silently failing the +consistency requirement) if we know the write has been persisted on at +least one replica.

  • +
  • For reads, try reading at a lower consistency level (thus silently +failing the consistency requirement).

  • +
+

In other words, this policy implements the idea that if the requested +consistency level cannot be achieved, the next best thing for writes is +to make sure the data is persisted, and that reading something is better +than reading nothing, even if there is a risk of reading stale data.

+
+
+on_read_timeout(query, consistency, required_responses, received_responses, data_retrieved, retry_num)
+

This is called when a read operation times out from the coordinator’s +perspective (i.e. a replica did not respond to the coordinator in time). +It should return a tuple with two items: one of the class enums (such +as RETRY) and a ConsistencyLevel to retry the +operation at or None to keep the same consistency level.

+

query is the Statement that timed out.

+

consistency is the ConsistencyLevel that the operation was +attempted at.

+

The required_responses and received_responses parameters describe +how many replicas needed to respond to meet the requested consistency +level and how many actually did respond before the coordinator timed +out the request. data_retrieved is a boolean indicating whether +any of those responses contained data (as opposed to just a digest).

+

retry_num counts how many times the operation has been retried, so +the first time this method is called, retry_num will be 0.

+

By default, operations will be retried at most once, and only if +a sufficient number of replicas responded (with data digests).

+
+ +
+
+on_write_timeout(query, consistency, write_type, required_responses, received_responses, retry_num)
+

This is called when a write operation times out from the coordinator’s +perspective (i.e. a replica did not respond to the coordinator in time).

+

query is the Statement that timed out.

+

consistency is the ConsistencyLevel that the operation was +attempted at.

+

write_type is one of the WriteType enums describing the +type of write operation.

+

The required_responses and received_responses parameters describe +how many replicas needed to acknowledge the write to meet the requested +consistency level and how many replicas actually did acknowledge the +write before the coordinator timed out the request.

+

retry_num counts how many times the operation has been retried, so +the first time this method is called, retry_num will be 0.

+

By default, failed write operations will retried at most once, and +they will only be retried if the write_type was +BATCH_LOG.

+
+ +
+
+on_unavailable(query, consistency, required_replicas, alive_replicas, retry_num)
+

This is called when the coordinator node determines that a read or +write operation cannot be successful because the number of live +replicas are too low to meet the requested ConsistencyLevel. +This means that the read or write operation was never forwarded to +any replicas.

+

query is the Statement that failed.

+

consistency is the ConsistencyLevel that the operation was +attempted at.

+

required_replicas is the number of replicas that would have needed to +acknowledge the operation to meet the requested consistency level. +alive_replicas is the number of replicas that the coordinator +considered alive at the time of the request.

+

retry_num counts how many times the operation has been retried, so +the first time this method is called, retry_num will be 0.

+

By default, if this is the first retry, it triggers a retry on the next +host in the query plan with the same consistency level. If this is not the +first retry, no retries will be attempted and the error will be re-raised.

+
+ +
+ +
+
+

Retrying Idempotent Operations

+
+
+class cassandra.policies.SpeculativeExecutionPolicy
+

Interface for specifying speculative execution plans

+
+
+new_plan(keyspace, statement)
+

Returns

+
+
Parameters
+
    +
  • keyspace

  • +
  • statement

  • +
+
+
Returns
+

+
+
+
+ +
+ +
+
+class cassandra.policies.ConstantSpeculativeExecutionPolicy(delay, max_attempts)
+

A speculative execution policy that sends a new query every X seconds (delay) for a maximum of Y attempts (max_attempts).

+
+
+new_plan(keyspace, statement)
+

Returns

+
+
Parameters
+
    +
  • keyspace

  • +
  • statement

  • +
+
+
Returns
+

+
+
+
+ +
+ +
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.21.0-scylla/api/cassandra/pool.html b/3.21.0-scylla/api/cassandra/pool.html new file mode 100644 index 0000000000..8998e221cc --- /dev/null +++ b/3.21.0-scylla/api/cassandra/pool.html @@ -0,0 +1,671 @@ + + + + + + + + + + + + + cassandra.pool - Hosts and Connection Pools | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.pool - Hosts and Connection Pools

+

Connection pooling and host management.

+
+
+class cassandra.pool.Host
+

Represents a single Cassandra node.

+
+
+property address
+

The IP address of the endpoint. This is the RPC address the driver uses when connecting to the node.

+
+ +
+
+property datacenter
+

The datacenter the node is in.

+
+ +
+
+property rack
+

The rack the node is in.

+
+ +
+ +
+
+exception cassandra.pool.NoConnectionsAvailable
+

All existing connections to a given host are busy, or there are +no open connections.

+
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.21.0-scylla/api/cassandra/protocol.html b/3.21.0-scylla/api/cassandra/protocol.html new file mode 100644 index 0000000000..38d41f8205 --- /dev/null +++ b/3.21.0-scylla/api/cassandra/protocol.html @@ -0,0 +1,737 @@ + + + + + + + + + + + + + cassandra.protocol - Protocol Features | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.protocol - Protocol Features

+
+

Custom Payloads

+

Native protocol version 4+ allows for a custom payload to be sent between clients +and custom query handlers. The payload is specified as a string:binary_type dict +holding custom key/value pairs.

+

By default these are ignored by the server. They can be useful for servers implementing +a custom QueryHandler.

+

See Session.execute(), :Session.execute_async(), ResponseFuture.custom_payload.

+
+
+class cassandra.protocol._ProtocolHandler
+

_ProtocolHander handles encoding and decoding messages.

+

This class can be specialized to compose Handlers which implement alternative +result decoding or type deserialization. Class definitions are passed to cassandra.cluster.Cluster +on initialization.

+

Contracted class methods are _ProtocolHandler.encode_message() and _ProtocolHandler.decode_message().

+
+
+message_types_by_opcode = {default mapping}
+
+ +
+
+classmethod encode_message(msg, stream_id, protocol_version, compressor, allow_beta_protocol_version)
+

Encodes a message using the specified frame parameters, and compressor

+
+
Parameters
+
    +
  • msg – the message, typically of cassandra.protocol._MessageType, generated by the driver

  • +
  • stream_id – protocol stream id for the frame header

  • +
  • protocol_version – version for the frame header, and used encoding contents

  • +
  • compressor – optional compression function to be used on the body

  • +
+
+
+
+ +
+
+classmethod decode_message(protocol_version, user_type_map, stream_id, flags, opcode, body, decompressor, result_metadata)
+

Decodes a native protocol message body

+
+
Parameters
+
    +
  • protocol_version – version to use decoding contents

  • +
  • user_type_map – map[keyspace name] = map[type name] = custom type to instantiate when deserializing this type

  • +
  • stream_id – native protocol stream id from the frame header

  • +
  • flags – native protocol flags bitmap from the header

  • +
  • opcode – native protocol opcode from the header

  • +
  • body – frame body

  • +
  • decompressor – optional decompression function to inflate the body

  • +
+
+
Returns
+

a message decoded from the body and frame attributes

+
+
+
+ +
+ +
+
+

Faster Deserialization

+

When python-driver is compiled with Cython, it uses a Cython-based deserialization path +to deserialize messages. By default, the driver will use a Cython-based parser that returns +lists of rows similar to the pure-Python version. In addition, there are two additional +ProtocolHandler classes that can be used to deserialize response messages: LazyProtocolHandler +and NumpyProtocolHandler. They can be used as follows:

+
from cassandra.protocol import NumpyProtocolHandler, LazyProtocolHandler
+from cassandra.query import tuple_factory
+s.client_protocol_handler = LazyProtocolHandler   # for a result iterator
+s.row_factory = tuple_factory  #required for Numpy results
+s.client_protocol_handler = NumpyProtocolHandler  # for a dict of NumPy arrays as result
+
+
+

These protocol handlers comprise different parsers, and return results as described below:

+
    +
  • ProtocolHandler: this default implementation is a drop-in replacement for the pure-Python version. +The rows are all parsed upfront, before results are returned.

  • +
  • LazyProtocolHandler: near drop-in replacement for the above, except that it returns an iterator over rows, +lazily decoded into the default row format (this is more efficient since all decoded results are not materialized at once)

  • +
  • NumpyProtocolHander: deserializes results directly into NumPy arrays. This facilitates efficient integration with +analysis toolkits such as Pandas.

  • +
+
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.21.0-scylla/api/cassandra/query.html b/3.21.0-scylla/api/cassandra/query.html new file mode 100644 index 0000000000..30f12d545c --- /dev/null +++ b/3.21.0-scylla/api/cassandra/query.html @@ -0,0 +1,1000 @@ + + + + + + + + + + + + + cassandra.query - Prepared Statements, Batch Statements, Tracing, and Row Factories | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.query - Prepared Statements, Batch Statements, Tracing, and Row Factories

+
+
+cassandra.query.tuple_factory(colnames, rows)
+

Returns each row as a tuple

+

Example:

+
>>> from cassandra.query import tuple_factory
+>>> session = cluster.connect('mykeyspace')
+>>> session.row_factory = tuple_factory
+>>> rows = session.execute("SELECT name, age FROM users LIMIT 1")
+>>> print rows[0]
+('Bob', 42)
+
+
+
+

Changed in version 2.0.0: moved from cassandra.decoder to cassandra.query

+
+
+ +
+
+cassandra.query.named_tuple_factory(colnames, rows)
+

Returns each row as a namedtuple. +This is the default row factory.

+

Example:

+
>>> from cassandra.query import named_tuple_factory
+>>> session = cluster.connect('mykeyspace')
+>>> session.row_factory = named_tuple_factory
+>>> rows = session.execute("SELECT name, age FROM users LIMIT 1")
+>>> user = rows[0]
+
+>>> # you can access field by their name:
+>>> print "name: %s, age: %d" % (user.name, user.age)
+name: Bob, age: 42
+
+>>> # or you can access fields by their position (like a tuple)
+>>> name, age = user
+>>> print "name: %s, age: %d" % (name, age)
+name: Bob, age: 42
+>>> name = user[0]
+>>> age = user[1]
+>>> print "name: %s, age: %d" % (name, age)
+name: Bob, age: 42
+
+
+
+

Changed in version 2.0.0: moved from cassandra.decoder to cassandra.query

+
+
+ +
+
+cassandra.query.dict_factory(colnames, rows)
+

Returns each row as a dict.

+

Example:

+
>>> from cassandra.query import dict_factory
+>>> session = cluster.connect('mykeyspace')
+>>> session.row_factory = dict_factory
+>>> rows = session.execute("SELECT name, age FROM users LIMIT 1")
+>>> print rows[0]
+{u'age': 42, u'name': u'Bob'}
+
+
+
+

Changed in version 2.0.0: moved from cassandra.decoder to cassandra.query

+
+
+ +
+
+cassandra.query.ordered_dict_factory(colnames, rows)
+

Like dict_factory(), but returns each row as an OrderedDict, +so the order of the columns is preserved.

+
+

Changed in version 2.0.0: moved from cassandra.decoder to cassandra.query

+
+
+ +
+
+class cassandra.query.SimpleStatement(query_string, retry_policy=None, consistency_level=None, routing_key=None, serial_consistency_level=None, fetch_size=<object object>, keyspace=None, custom_payload=None, is_idempotent=False)
+

A simple, un-prepared query.

+

query_string should be a literal CQL statement with the exception +of parameter placeholders that will be filled through the +parameters argument of Session.execute().

+

See Statement attributes for a description of the other parameters.

+
+ +
+
+class cassandra.query.PreparedStatement
+

A statement that has been prepared against at least one Cassandra node. +Instances of this class should not be created directly, but through +Session.prepare().

+

A PreparedStatement should be prepared only once. Re-preparing a statement +may affect performance (as the operation requires a network roundtrip).

+

A note about * in prepared statements: Do not use * in prepared statements if you might +change the schema of the table being queried. The driver and server each +maintain a map between metadata for a schema and statements that were +prepared against that schema. When a user changes a schema, e.g. by adding +or removing a column, the server invalidates its mappings involving that +schema. However, there is currently no way to propagate that invalidation +to drivers. Thus, after a schema change, the driver will incorrectly +interpret the results of SELECT * queries prepared before the schema +change. This is currently being addressed in CASSANDRA-10786.

+
+
+bind(values)
+

Creates and returns a BoundStatement instance using values.

+

See BoundStatement.bind() for rules on input values.

+
+ +
+ +
+
+class cassandra.query.BoundStatement(prepared_statement, retry_policy=None, consistency_level=None, routing_key=None, serial_consistency_level=None, fetch_size=<object object>, keyspace=None, custom_payload=None)
+

A prepared statement that has been bound to a particular set of values. +These may be created directly or through PreparedStatement.bind().

+

prepared_statement should be an instance of PreparedStatement.

+

See Statement attributes for a description of the other parameters.

+
+
+bind(values)
+

Binds a sequence of values for the prepared statement parameters +and returns this instance. Note that values must be:

+
    +
  • a sequence, even if you are only binding one value, or

  • +
  • a dict that relates 1-to-1 between dict keys and columns

  • +
+
+

Changed in version 2.6.0: UNSET_VALUE was introduced. These can be bound as positional parameters +in a sequence, or by name in a dict. Additionally, when using protocol v4+:

+
    +
  • short sequences will be extended to match bind parameters with UNSET_VALUE

  • +
  • names may be omitted from a dict with UNSET_VALUE implied.

  • +
+
+
+

Changed in version 3.0.0: method will not throw if extra keys are present in bound dict (PYTHON-178)

+
+
+ +
+
+property routing_key
+

The partition_key portion of the primary key, +which can be used to determine which nodes are replicas for the query.

+

If the partition key is a composite, a list or tuple must be passed in. +Each key component should be in its packed (binary) format, so all +components should be strings.

+
+ +
+ +
+
+class cassandra.query.Statement
+

An abstract class representing a single query. There are three subclasses: +SimpleStatement, BoundStatement, and BatchStatement. +These can be passed to Session.execute().

+
+
+property routing_key
+

The partition_key portion of the primary key, +which can be used to determine which nodes are replicas for the query.

+

If the partition key is a composite, a list or tuple must be passed in. +Each key component should be in its packed (binary) format, so all +components should be strings.

+
+ +
+
+property serial_consistency_level
+

The serial consistency level is only used by conditional updates +(INSERT, UPDATE and DELETE with an IF condition). For +those, the serial_consistency_level defines the consistency level of +the serial phase (or “paxos” phase) while the normal +consistency_level defines the consistency for the “learn” phase, +i.e. what type of reads will be guaranteed to see the update right away. +For example, if a conditional write has a consistency_level of +QUORUM (and is successful), then a +QUORUM read is guaranteed to see that write. +But if the regular consistency_level of that write is +ANY, then only a read with a +consistency_level of SERIAL is +guaranteed to see it (even a read with consistency +ALL is not guaranteed to be enough).

+

The serial consistency can only be one of SERIAL +or LOCAL_SERIAL. While SERIAL guarantees full +linearizability (with other SERIAL updates), LOCAL_SERIAL only +guarantees it in the local data center.

+

The serial consistency level is ignored for any query that is not a +conditional update. Serial reads should use the regular +consistency_level.

+

Serial consistency levels may only be used against Cassandra 2.0+ +and the protocol_version must be set to 2 or higher.

+

See Lightweight Transactions (Compare-and-set) for a discussion on how to work with results returned from +conditional statements.

+
+

New in version 2.0.0.

+
+
+ +
+ +
+
+cassandra.query.UNSET_VALUE
+

The most base type

+
+ +
+
+class cassandra.query.BatchStatement(batch_type=BatchType.LOGGED, retry_policy=None, consistency_level=None)
+

A protocol-level batch of operations which are applied atomically +by default.

+
+

New in version 2.0.0.

+
+

batch_type specifies The BatchType for the batch operation. +Defaults to BatchType.LOGGED.

+

retry_policy should be a RetryPolicy instance for +controlling retries on the operation.

+

consistency_level should be a ConsistencyLevel value +to be used for all operations in the batch.

+

custom_payload is a Custom Payloads passed to the server. +Note: as Statement objects are added to the batch, this map is +updated with any values found in their custom payloads. These are +only allowed when using protocol version 4 or higher.

+

Example usage:

+
insert_user = session.prepare("INSERT INTO users (name, age) VALUES (?, ?)")
+batch = BatchStatement(consistency_level=ConsistencyLevel.QUORUM)
+
+for (name, age) in users_to_insert:
+    batch.add(insert_user, (name, age))
+
+session.execute(batch)
+
+
+

You can also mix different types of operations within a batch:

+
batch = BatchStatement()
+batch.add(SimpleStatement("INSERT INTO users (name, age) VALUES (%s, %s)"), (name, age))
+batch.add(SimpleStatement("DELETE FROM pending_users WHERE name=%s"), (name,))
+session.execute(batch)
+
+
+
+

New in version 2.0.0.

+
+
+

Changed in version 2.1.0: Added serial_consistency_level as a parameter

+
+
+

Changed in version 2.6.0: Added custom_payload as a parameter

+
+
+
+add(statement, parameters=None)
+

Adds a Statement and optional sequence of parameters +to be used with the statement to the batch.

+

Like with other statements, parameters must be a sequence, even +if there is only one item.

+
+ +
+
+add_all(statements, parameters)
+

Adds a sequence of Statement objects and a matching sequence +of parameters to the batch. Statement and parameter sequences must be of equal length or +one will be truncated. None can be used in the parameters position where are needed.

+
+ +
+
+clear()
+

This is a convenience method to clear a batch statement for reuse.

+

Note: it should not be used concurrently with uncompleted execution futures executing the same +BatchStatement.

+
+ +
+
+serial_consistency_level = None
+
+ +
+ +
+
+class cassandra.query.BatchType
+

A BatchType is used with BatchStatement instances to control +the atomicity of the batch operation.

+
+

New in version 2.0.0.

+
+
+
+LOGGED = BatchType.LOGGED
+
+ +
+
+UNLOGGED = BatchType.UNLOGGED
+
+ +
+
+COUNTER = BatchType.COUNTER
+
+ +
+ +
+
+class cassandra.query.ValueSequence(iterable=(), /)
+

A wrapper class that is used to specify that a sequence of values should +be treated as a CQL list of values instead of a single column collection when used +as part of the parameters argument for Session.execute().

+

This is typically needed when supplying a list of keys to select. +For example:

+
>>> my_user_ids = ('alice', 'bob', 'charles')
+>>> query = "SELECT * FROM users WHERE user_id IN %s"
+>>> session.execute(query, parameters=[ValueSequence(my_user_ids)])
+
+
+
+ +
+
+class cassandra.query.QueryTrace
+

A trace of the duration and events that occurred when executing +an operation.

+
+
+populate(max_wait=2.0, wait_for_complete=True, query_cl=None)
+

Retrieves the actual tracing details from Cassandra and populates the +attributes of this instance. Because tracing details are stored +asynchronously by Cassandra, this may need to retry the session +detail fetch. If the trace is still not available after max_wait +seconds, TraceUnavailable will be raised; if max_wait is +None, this will retry forever.

+

wait_for_complete=False bypasses the wait for duration to be populated. +This can be used to query events from partial sessions.

+

query_cl specifies a consistency level to use for polling the trace tables, +if it should be different than the session default.

+
+ +
+ +
+
+class cassandra.query.TraceEvent
+

Representation of a single event within a query trace.

+
+ +
+
+exception cassandra.query.TraceUnavailable
+

Raised when complete trace details cannot be fetched from Cassandra.

+
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.21.0-scylla/api/cassandra/timestamps.html b/3.21.0-scylla/api/cassandra/timestamps.html new file mode 100644 index 0000000000..9d289f191d --- /dev/null +++ b/3.21.0-scylla/api/cassandra/timestamps.html @@ -0,0 +1,693 @@ + + + + + + + + + + + + + cassandra.timestamps - Timestamp Generation | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.timestamps - Timestamp Generation

+
+
+class cassandra.timestamps.MonotonicTimestampGenerator(warn_on_drift=True, warning_threshold=0, warning_interval=0)
+

An object that, when called, returns int(time.time() * 1e6) when +possible, but, if the value returned by time.time doesn’t increase, +drifts into the future and logs warnings. +Exposed configuration attributes can be configured with arguments to +__init__ or by changing attributes on an initialized object.

+
+

New in version 3.8.0.

+
+
+
+warn_on_drift = True
+

If true, log warnings when timestamps drift into the future as allowed by +warning_threshold and warning_interval.

+
+ +
+
+warning_threshold = 1
+

This object will only issue warnings when the returned timestamp drifts +more than warning_threshold seconds into the future. +Defaults to 1 second.

+
+ +
+
+warning_interval = 1
+

This object will only issue warnings every warning_interval seconds. +Defaults to 1 second.

+
+ +
+
+_next_timestamp(now, last)
+

Returns the timestamp that should be used if now is the current +time and last is the last timestamp returned by this object. +Intended for internal and testing use only; to generate timestamps, +call an instantiated MonotonicTimestampGenerator object.

+
+
Parameters
+
    +
  • now (int) – an integer to be used as the current time, typically +representing the current time in microseconds since the UNIX epoch

  • +
  • last (int) – an integer representing the last timestamp returned by +this object

  • +
+
+
+
+ +
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.21.0-scylla/api/cassandra/util.html b/3.21.0-scylla/api/cassandra/util.html new file mode 100644 index 0000000000..5717f83115 --- /dev/null +++ b/3.21.0-scylla/api/cassandra/util.html @@ -0,0 +1,1028 @@ + + + + + + + + + + + + + cassandra.util - Utilities | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.util - Utilities

+
+
+class cassandra.util.Date(value)
+

Idealized date: year, month, day

+

Offers wider year range than datetime.date. For Dates that cannot be represented +as a datetime.date (because datetime.MINYEAR, datetime.MAXYEAR), this type falls back +to printing days_from_epoch offset.

+

Initializer value can be:

+
    +
  • integer_type: absolute days from epoch (1970, 1, 1). Can be negative.

  • +
  • datetime.date: built-in date

  • +
  • string_type: a string time of the form “yyyy-mm-dd”

  • +
+
+
+date()
+

Return a built-in datetime.date for Dates falling in the years [datetime.MINYEAR, datetime.MAXYEAR]

+

ValueError is raised for Dates outside this range.

+
+ +
+
+property seconds
+

Absolute seconds from epoch (can be negative)

+
+ +
+ +
+
+class cassandra.util.DateRange(lower_bound=None, upper_bound=None, value=None)
+

DSE DateRange Type

+
+
+lower_bound
+

DateRangeBound representing the lower bound of a bounded range.

+
+ +
+
+upper_bound
+

DateRangeBound representing the upper bound of a bounded range.

+
+ +
+
+value
+

DateRangeBound representing the value of a single-value range.

+
+ +

As noted in its documentation, DateRangeBound uses a millisecond +offset from the UNIX epoch to allow DateRange to represent values +datetime.datetime cannot. For such values, string representions will show +this offset rather than the CQL representation.

+
+
Parameters
+
+
+
+
+ +
+
+class cassandra.util.DateRangeBound(value, precision)
+

Represents a single date value and its precision for DateRange.

+
+
+milliseconds
+

Integer representing milliseconds since the UNIX epoch. May be negative.

+
+ +
+
+precision
+

String representing the precision of a bound. Must be a valid +DateRangePrecision member.

+
+ +

DateRangeBound uses a millisecond offset from the UNIX epoch to +allow DateRange to represent values datetime.datetime cannot. +For such values, string representions will show this offset rather than the +CQL representation.

+
+
Parameters
+
    +
  • value – a value representing ms since the epoch. Accepts an +integer or a datetime.

  • +
  • precision – a string representing precision

  • +
+
+
+
+
+datetime()
+

Return milliseconds as a datetime.datetime if possible. +Raises an OverflowError if the value is out of range.

+
+ +
+
+classmethod from_value(value)
+

Construct a new DateRangeBound from a given value. If +possible, use the value[‘milliseconds’] and value[‘precision’] keys +of the argument. Otherwise, use the argument as a (milliseconds, +precision) iterable.

+
+
Parameters
+

value – a dictlike or iterable object

+
+
+
+ +
+ +
+
+class cassandra.util.DateRangePrecision
+

An “enum” representing the valid values for DateRange.precision.

+
+ +
+
+class cassandra.util.Distance(x=nan, y=nan, radius=nan)
+

Represents a Distance geometry for DSE

+
+
+static from_wkt(s)
+

Parse a Distance geometry from a wkt string and return a new Distance object.

+
+ +
+ +
+
+class cassandra.util.Duration(months=0, days=0, nanoseconds=0)
+

Cassandra Duration Type

+
+ +
+
+class cassandra.util.LineString(coords=())
+

Represents a linestring geometry for DSE

+

‘coords`: a sequence of (x, y) coordinates of points in the linestring

+
+
+static from_wkt(s)
+

Parse a LineString geometry from a wkt string and return a new LineString object.

+
+ +
+ +
+
+class cassandra.util.OrderedMap(*args, **kwargs)
+

An ordered map that accepts non-hashable types for keys. It also maintains the +insertion order of items, behaving as OrderedDict in that regard. These maps +are constructed and read just as normal mapping types, except that they may +contain arbitrary collections and other non-hashable items as keys:

+
>>> od = OrderedMap([({'one': 1, 'two': 2}, 'value'),
+...                  ({'three': 3, 'four': 4}, 'value2')])
+>>> list(od.keys())
+[{'two': 2, 'one': 1}, {'three': 3, 'four': 4}]
+>>> list(od.values())
+['value', 'value2']
+
+
+

These constructs are needed to support nested collections in Cassandra 2.1.3+, +where frozen collections can be specified as parameters to others:

+
CREATE TABLE example (
+    ...
+    value map<frozen<map<int, int>>, double>
+    ...
+)
+
+
+

This class derives from the (immutable) Mapping API. Objects in these maps +are not intended be modified.

+
+ +
+
+class cassandra.util.OrderedMapSerializedKey(cass_type, protocol_version)
+
+ +
+
+class cassandra.util.Point(x=nan, y=nan)
+

Represents a point geometry for DSE

+
+
+static from_wkt(s)
+

Parse a Point geometry from a wkt string and return a new Point object.

+
+ +
+ +
+
+class cassandra.util.Polygon(exterior=(), interiors=None)
+

Represents a polygon geometry for DSE

+

‘exterior`: a sequence of (x, y) coordinates of points in the linestring +interiors: None, or a sequence of sequences or (x, y) coordinates of points describing interior linear rings

+
+
+static from_wkt(s)
+

Parse a Polygon geometry from a wkt string and return a new Polygon object.

+
+ +
+ +
+
+class cassandra.util.SortedSet(iterable=())
+

A sorted set based on sorted list

+

A sorted set implementation is used in this case because it does not +require its elements to be immutable/hashable.

+

#Not implemented: update functions, inplace operators

+
+ +
+
+class cassandra.util.Time(value)
+

Idealized time, independent of day.

+

Up to nanosecond resolution

+

Initializer value can be:

+
    +
  • integer_type: absolute nanoseconds in the day

  • +
  • datetime.time: built-in time

  • +
  • string_type: a string time of the form “HH:MM:SS[.mmmuuunnn]”

  • +
+
+
+property hour
+

The hour component of this time (0-23)

+
+ +
+
+property minute
+

The minute component of this time (0-59)

+
+ +
+
+property nanosecond
+

The fractional seconds component of the time, in nanoseconds

+
+ +
+
+property second
+

The second component of this time (0-59)

+
+ +
+
+time()
+

Return a built-in datetime.time (nanosecond precision truncated to micros).

+
+ +
+ +
+
+class cassandra.util.Version(version)
+

Internal minimalist class to compare versions. +A valid version is: <int>.<int>.<int>.<int or str>.

+

TODO: when python2 support is removed, use packaging.version.

+
+ +
+
+cassandra.util.datetime_from_timestamp(timestamp)
+

Creates a timezone-agnostic datetime from timestamp (in seconds) in a consistent manner. +Works around a Windows issue with large negative timestamps (PYTHON-119), +and rounding differences in Python 3.4 (PYTHON-340).

+
+
Parameters
+

timestamp – a unix timestamp, in seconds

+
+
+
+ +
+
+cassandra.util.datetime_from_uuid1(uuid_arg)
+

Creates a timezone-agnostic datetime from the timestamp in the +specified type-1 UUID.

+
+
Parameters
+

uuid_arg – a version 1 UUID

+
+
+
+ +
+
+cassandra.util.max_uuid_from_time(timestamp)
+

Generates the maximum TimeUUID (type 1) for a given timestamp, as compared by Cassandra.

+

See uuid_from_time() for argument and return types.

+
+ +
+
+cassandra.util.min_uuid_from_time(timestamp)
+

Generates the minimum TimeUUID (type 1) for a given timestamp, as compared by Cassandra.

+

See uuid_from_time() for argument and return types.

+
+ +
+
+cassandra.util.ms_timestamp_from_datetime(dt)
+

Converts a datetime to a timestamp expressed in milliseconds.

+
+
Parameters
+

dt – a datetime.datetime

+
+
+
+ +
+
+cassandra.util.sortedset
+

alias of cassandra.util.SortedSet

+
+ +
+
+cassandra.util.unix_time_from_uuid1(uuid_arg)
+

Converts a version 1 uuid.UUID to a timestamp with the same precision +as time.time() returns. This is useful for examining the +results of queries returning a v1 UUID.

+
+
Parameters
+

uuid_arg – a version 1 UUID

+
+
+
+ +
+
+cassandra.util.utc_datetime_from_ms_timestamp(timestamp)
+

Creates a UTC datetime from a timestamp in milliseconds. See +datetime_from_timestamp().

+

Raises an OverflowError if the timestamp is out of range for +datetime.

+
+
Parameters
+

timestamp – timestamp, in milliseconds

+
+
+
+ +
+
+cassandra.util.uuid_from_time(time_arg, node=None, clock_seq=None)
+

Converts a datetime or timestamp to a type 1 uuid.UUID.

+
+
Parameters
+
    +
  • time_arg – The time to use for the timestamp portion of the UUID. +This can either be a datetime object or a timestamp +in seconds (as returned from time.time()).

  • +
  • node (long) – None integer for the UUID (up to 48 bits). If not specified, this +field is randomized.

  • +
  • clock_seq (int) – Clock sequence field for the UUID (up to 14 bits). If not specified, +a random sequence is generated.

  • +
+
+
Return type
+

uuid.UUID

+
+
+
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.21.0-scylla/api/index.html b/3.21.0-scylla/api/index.html new file mode 100644 index 0000000000..306787f3b7 --- /dev/null +++ b/3.21.0-scylla/api/index.html @@ -0,0 +1,714 @@ + + + + + + + + + + + + + API Documentation | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

API Documentation

+
+

Core Driver

+ +
+
+

Object Mapper

+ +
+
+

DataStax Graph

+ +
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.21.0-scylla/cqlengine/batches.html b/3.21.0-scylla/cqlengine/batches.html new file mode 100644 index 0000000000..e1e6bd2f6c --- /dev/null +++ b/3.21.0-scylla/cqlengine/batches.html @@ -0,0 +1,744 @@ + + + + + + + + + + + + + Batch Queries | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + + + +
+

Batch Queries

+

cqlengine supports batch queries using the BatchQuery class. Batch queries can be started and stopped manually, or within a context manager. To add queries to the batch object, you just need to precede the create/save/delete call with a call to batch, and pass in the batch object.

+
+

Batch Query General Use Pattern

+

You can only create, update, and delete rows with a batch query, attempting to read rows out of the database with a batch query will fail.

+
from cassandra.cqlengine.query import BatchQuery
+
+#using a context manager
+with BatchQuery() as b:
+    now = datetime.now()
+    em1 = ExampleModel.batch(b).create(example_type=0, description="1", created_at=now)
+    em2 = ExampleModel.batch(b).create(example_type=0, description="2", created_at=now)
+    em3 = ExampleModel.batch(b).create(example_type=0, description="3", created_at=now)
+
+# -- or --
+
+#manually
+b = BatchQuery()
+now = datetime.now()
+em1 = ExampleModel.batch(b).create(example_type=0, description="1", created_at=now)
+em2 = ExampleModel.batch(b).create(example_type=0, description="2", created_at=now)
+em3 = ExampleModel.batch(b).create(example_type=0, description="3", created_at=now)
+b.execute()
+
+# updating in a batch
+
+b = BatchQuery()
+em1.description = "new description"
+em1.batch(b).save()
+em2.description = "another new description"
+em2.batch(b).save()
+b.execute()
+
+# deleting in a batch
+b = BatchQuery()
+ExampleModel.objects(id=some_id).batch(b).delete()
+ExampleModel.objects(id=some_id2).batch(b).delete()
+b.execute()
+
+
+

Typically you will not want the block to execute if an exception occurs inside the with block. However, in the case that this is desirable, it’s achievable by using the following syntax:

+
with BatchQuery(execute_on_exception=True) as b:
+    LogEntry.batch(b).create(k=1, v=1)
+    mystery_function() # exception thrown in here
+    LogEntry.batch(b).create(k=1, v=2) # this code is never reached due to the exception, but anything leading up to here will execute in the batch.
+
+
+

If an exception is thrown somewhere in the block, any statements that have been added to the batch will still be executed. This is useful for some logging situations.

+
+
+

Batch Query Execution Callbacks

+

In order to allow secondary tasks to be chained to the end of batch, BatchQuery instances allow callbacks to be +registered with the batch, to be executed immediately after the batch executes.

+

Multiple callbacks can be attached to same BatchQuery instance, they are executed in the same order that they +are added to the batch.

+

The callbacks attached to a given batch instance are executed only if the batch executes. If the batch is used as a +context manager and an exception is raised, the queued up callbacks will not be run.

+
def my_callback(*args, **kwargs):
+    pass
+
+batch = BatchQuery()
+
+batch.add_callback(my_callback)
+batch.add_callback(my_callback, 'positional arg', named_arg='named arg value')
+
+# if you need reference to the batch within the callback,
+# just trap it in the arguments to be passed to the callback:
+batch.add_callback(my_callback, cqlengine_batch=batch)
+
+# once the batch executes...
+batch.execute()
+
+# the effect of the above scheduled callbacks will be similar to
+my_callback()
+my_callback('positional arg', named_arg='named arg value')
+my_callback(cqlengine_batch=batch)
+
+
+

Failure in any of the callbacks does not affect the batch’s execution, as the callbacks are started after the execution +of the batch is complete.

+
+

Logged vs Unlogged Batches

+

By default, queries in cqlengine are LOGGED, which carries additional overhead from UNLOGGED. To explicitly state which batch type to use, simply:

+
from cassandra.cqlengine.query import BatchType
+with BatchQuery(batch_type=BatchType.Unlogged) as b:
+    LogEntry.batch(b).create(k=1, v=1)
+    LogEntry.batch(b).create(k=1, v=2)
+
+
+
+
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.21.0-scylla/cqlengine/connections.html b/3.21.0-scylla/cqlengine/connections.html new file mode 100644 index 0000000000..69a9fe2f95 --- /dev/null +++ b/3.21.0-scylla/cqlengine/connections.html @@ -0,0 +1,768 @@ + + + + + + + + + + + + + Connections | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + + + +
+

Connections

+

Connections aim to ease the use of multiple sessions with cqlengine. Connections can be set on a model class, per query or using a context manager.

+
+

Register a new connection

+

To use cqlengine, you need at least a default connection. If you initialize cqlengine’s connections with with connection.setup, a connection will be created automatically. If you want to use another cluster/session, you need to register a new cqlengine connection. You register a connection with register_connection():

+
from cassandra.cqlengine import connection
+
+connection.setup(['127.0.0.1')
+connection.register_connection('cluster2', ['127.0.0.2'])
+
+
+

register_connection() can take a list of hosts, as shown above, in which case it will create a connection with a new session. It can also take a session argument if you’ve already created a session:

+
from cassandra.cqlengine import connection
+from cassandra.cluster import Cluster
+
+session = Cluster(['127.0.0.1']).connect()
+connection.register_connection('cluster3', session=session)
+
+
+
+
+

Change the default connection

+

You can change the default cqlengine connection on registration:

+
from cassandra.cqlengine import connection
+
+connection.register_connection('cluster2', ['127.0.0.2'] default=True)
+
+
+

or on the fly using set_default_connection()

+
connection.set_default_connection('cluster2')
+
+
+
+
+

Unregister a connection

+

You can unregister a connection using unregister_connection():

+
connection.unregister_connection('cluster2')
+
+
+
+
+

Management

+

When using multiples connections, you also need to sync your models on all connections (and keyspaces) that you need operate on. Management commands have been improved to ease this part. Here is an example:

+
from cassandra.cqlengine import management
+
+keyspaces = ['ks1', 'ks2']
+conns = ['cluster1', 'cluster2']
+
+# registers your connections
+# ...
+
+# create all keyspaces on all connections
+for ks in keyspaces:
+    management.create_simple_keyspace(ks, connections=conns)
+
+# define your Automobile model
+# ...
+
+# sync your models
+management.sync_table(Automobile, keyspaces=keyspaces, connections=conns)
+
+
+
+
+

Connection Selection

+

cqlengine will select the default connection, unless your specify a connection using one of the following methods.

+
+

Default Model Connection

+

You can specify a default connection per model:

+
class Automobile(Model):
+    __keyspace__ = 'test'
+    __connection__ = 'cluster2'
+    manufacturer = columns.Text(primary_key=True)
+    year = columns.Integer(primary_key=True)
+    model = columns.Text(primary_key=True)
+
+print len(Automobile.objects.all())  # executed on the connection 'cluster2'
+
+
+
+
+

QuerySet and model instance

+

You can use the using() method to select a connection (or keyspace):

+
Automobile.objects.using(connection='cluster1').create(manufacturer='honda', year=2010, model='civic')
+q = Automobile.objects.filter(manufacturer='Tesla')
+autos = q.using(keyspace='ks2', connection='cluster2').all()
+
+for auto in autos:
+    auto.using(connection='cluster1').save()
+
+
+
+
+

Context Manager

+

You can use the ContextQuery as well to select a connection:

+
with ContextQuery(Automobile, connection='cluster1') as A:
+    A.objects.filter(manufacturer='honda').all()  # executed on 'cluster1'
+
+
+
+
+

BatchQuery

+

With a BatchQuery, you can select the connection with the context manager. Note that all operations in the batch need to use the same connection.

+
with BatchQuery(connection='cluster1') as b:
+    Automobile.objects.batch(b).create(manufacturer='honda', year=2010, model='civic')
+
+
+
+
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.21.0-scylla/cqlengine/faq.html b/3.21.0-scylla/cqlengine/faq.html new file mode 100644 index 0000000000..1b853e276f --- /dev/null +++ b/3.21.0-scylla/cqlengine/faq.html @@ -0,0 +1,708 @@ + + + + + + + + + + + + + Frequently Asked Questions | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

Frequently Asked Questions

+
+

Why don’t updates work correctly on models instantiated as Model(field=value, field2=value2)?

+

The recommended way to create new rows is with the models .create method. The values passed into a model’s init method are interpreted by the model as the values as they were read from a row. This allows the model to “know” which rows have changed since the row was read out of cassandra, and create suitable update statements.

+
+
+

How to preserve ordering in batch query?

+

Statement Ordering is not supported by CQL3 batches. Therefore, +once cassandra needs resolving conflict(Updating the same column in one batch), +The algorithm below would be used.

+
    +
  • If timestamps are different, pick the column with the largest timestamp (the value being a regular column or a tombstone)

  • +
  • If timestamps are the same, and one of the columns in a tombstone (‘null’) - pick the tombstone

  • +
  • If timestamps are the same, and none of the columns are tombstones, pick the column with the largest value

  • +
+

Below is an example to show this scenario.

+
class MyMode(Model):
+    id    = columns.Integer(primary_key=True)
+    count = columns.Integer()
+    text  = columns.Text()
+
+with BatchQuery() as b:
+   MyModel.batch(b).create(id=1, count=2, text='123')
+   MyModel.batch(b).create(id=1, count=3, text='111')
+
+assert MyModel.objects(id=1).first().count == 3
+assert MyModel.objects(id=1).first().text  == '123'
+
+
+

The largest value of count is 3, and the largest value of text would be ‘123’.

+

The workaround is applying timestamp to each statement, then Cassandra would +resolve to the statement with the lastest timestamp.

+
with BatchQuery() as b:
+    MyModel.timestamp(datetime.now()).batch(b).create(id=1, count=2, text='123')
+    MyModel.timestamp(datetime.now()).batch(b).create(id=1, count=3, text='111')
+
+assert MyModel.objects(id=1).first().count == 3
+assert MyModel.objects(id=1).first().text  == '111'
+
+
+
+
+

How can I delete individual values from a row?

+

When inserting with CQLEngine, None is equivalent to CQL NULL or to +issuing a DELETE on that column. For example:

+
class MyModel(Model):
+    id    = columns.Integer(primary_key=True)
+    text  = columns.Text()
+
+m = MyModel.create(id=1, text='We can delete this with None')
+assert MyModel.objects(id=1).first().text is not None
+
+m.update(text=None)
+assert MyModel.objects(id=1).first().text is None
+
+
+
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.21.0-scylla/cqlengine/models.html b/3.21.0-scylla/cqlengine/models.html new file mode 100644 index 0000000000..6367b611ff --- /dev/null +++ b/3.21.0-scylla/cqlengine/models.html @@ -0,0 +1,833 @@ + + + + + + + + + + + + + Models | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + + + +
+

Models

+

A model is a python class representing a CQL table. Models derive from Model, and +define basic table properties and columns for a table.

+

Columns in your models map to columns in your CQL table. You define CQL columns by defining column attributes on your model classes. +For a model to be valid it needs at least one primary key column and one non-primary key column. Just as in CQL, the order you define +your columns in is important, and is the same order they are defined in on a model’s corresponding table.

+

Some basic examples defining models are shown below. Consult the Model API docs and Column API docs for complete details.

+
+

Example Definitions

+

This example defines a Person table, with the columns first_name and last_name

+
from cassandra.cqlengine import columns
+from cassandra.cqlengine.models import Model
+
+ class Person(Model):
+     id = columns.UUID(primary_key=True)
+     first_name  = columns.Text()
+     last_name = columns.Text()
+
+
+

The Person model would create this CQL table:

+
CREATE TABLE cqlengine.person (
+    id uuid,
+    first_name text,
+    last_name text,
+    PRIMARY KEY (id)
+);
+
+
+

Here’s an example of a comment table created with clustering keys, in descending order:

+
from cassandra.cqlengine import columns
+from cassandra.cqlengine.models import Model
+
+class Comment(Model):
+    photo_id = columns.UUID(primary_key=True)
+    comment_id = columns.TimeUUID(primary_key=True, clustering_order="DESC")
+    comment = columns.Text()
+
+
+

The Comment model’s create table would look like the following:

+
CREATE TABLE comment (
+  photo_id uuid,
+  comment_id timeuuid,
+  comment text,
+  PRIMARY KEY (photo_id, comment_id)
+) WITH CLUSTERING ORDER BY (comment_id DESC);
+
+
+

To sync the models to the database, you may do the following*:

+
from cassandra.cqlengine.management import sync_table
+sync_table(Person)
+sync_table(Comment)
+
+
+

*Note: synchronizing models causes schema changes, and should be done with caution. +Please see the discussion in cassandra.cqlengine.management - Schema management for cqlengine for considerations.

+

For examples on manipulating data and creating queries, see Making Queries

+
+
+

Manipulating model instances as dictionaries

+

Model instances can be accessed like dictionaries.

+
class Person(Model):
+    first_name  = columns.Text()
+    last_name = columns.Text()
+
+kevin = Person.create(first_name="Kevin", last_name="Deldycke")
+dict(kevin)  # returns {'first_name': 'Kevin', 'last_name': 'Deldycke'}
+kevin['first_name']  # returns 'Kevin'
+kevin.keys()  # returns ['first_name', 'last_name']
+kevin.values()  # returns ['Kevin', 'Deldycke']
+kevin.items()  # returns [('first_name', 'Kevin'), ('last_name', 'Deldycke')]
+
+kevin['first_name'] = 'KEVIN5000'  # changes the models first name
+
+
+
+
+

Extending Model Validation

+

Each time you save a model instance in cqlengine, the data in the model is validated against the schema you’ve defined +for your model. Most of the validation is fairly straightforward, it basically checks that you’re not trying to do +something like save text into an integer column, and it enforces the required flag set on column definitions. +It also performs any transformations needed to save the data properly.

+

However, there are often additional constraints or transformations you want to impose on your data, beyond simply +making sure that Cassandra won’t complain when you try to insert it. To define additional validation on a model, +extend the model’s validation method:

+
class Member(Model):
+    person_id = UUID(primary_key=True)
+    name = Text(required=True)
+
+    def validate(self):
+        super(Member, self).validate()
+        if self.name == 'jon':
+            raise ValidationError('no jon\'s allowed')
+
+
+

Note: while not required, the convention is to raise a ValidationError (from cassandra.cqlengine import ValidationError) +if validation fails.

+
+
+

Model Inheritance

+

It is possible to save and load different model classes using a single CQL table. +This is useful in situations where you have different object types that you want to store in a single cassandra row.

+

For instance, suppose you want a table that stores rows of pets owned by an owner:

+
class Pet(Model):
+    __table_name__ = 'pet'
+    owner_id = UUID(primary_key=True)
+    pet_id = UUID(primary_key=True)
+    pet_type = Text(discriminator_column=True)
+    name = Text()
+
+    def eat(self, food):
+        pass
+
+    def sleep(self, time):
+        pass
+
+class Cat(Pet):
+    __discriminator_value__ = 'cat'
+    cuteness = Float()
+
+    def tear_up_couch(self):
+        pass
+
+class Dog(Pet):
+    __discriminator_value__ = 'dog'
+    fierceness = Float()
+
+    def bark_all_night(self):
+        pass
+
+
+

After calling sync_table on each of these tables, the columns defined in each model will be added to the +pet table. Additionally, saving Cat and Dog models will save the meta data needed to identify each row +as either a cat or dog.

+

To setup a model structure with inheritance, follow these steps

+
    +
  1. Create a base model with a column set as the distriminator (distriminator_column=True in the column definition)

  2. +
  3. Create subclass models, and define a unique __discriminator_value__ value on each

  4. +
  5. Run sync_table on each of the sub tables

  6. +
+

About the discriminator value

+

The discriminator value is what cqlengine uses under the covers to map logical cql rows to the appropriate model type. The +base model maintains a map of discriminator values to subclasses. When a specialized model is saved, its discriminator value is +automatically saved into the discriminator column. The discriminator column may be any column type except counter and container types. +Additionally, if you set index=True on your discriminator column, you can execute queries against specialized subclasses, and a +WHERE clause will be automatically added to your query, returning only rows of that type. Note that you must +define a unique __discriminator_value__ to each subclass, and that you can only assign a single discriminator column per model.

+
+
+

User Defined Types

+

cqlengine models User Defined Types (UDTs) much like tables, with fields defined by column type attributes. However, UDT instances +are only created, presisted, and queried via table Models. A short example to introduce the pattern:

+
from cassandra.cqlengine.columns import *
+from cassandra.cqlengine.models import Model
+from cassandra.cqlengine.usertype import UserType
+
+class address(UserType):
+    street = Text()
+    zipcode = Integer()
+
+class users(Model):
+    __keyspace__ = 'account'
+    name = Text(primary_key=True)
+    addr = UserDefinedType(address)
+
+users.create(name="Joe", addr=address(street="Easy St.", zipcode=99999))
+user = users.objects(name="Joe")[0]
+print user.name, user.addr
+# Joe address(street=u'Easy St.', zipcode=99999)
+
+
+

UDTs are modeled by inheriting UserType, and setting column type attributes. Types are then used in defining +models by declaring a column of type UserDefinedType, with the UserType class as a parameter.

+

sync_table will implicitly +synchronize any types contained in the table. Alternatively sync_type() can be used to create/alter types +explicitly.

+

Upon declaration, types are automatically registered with the driver, so query results return instances of your UserType +class*.

+

*Note: UDTs were not added to the native protocol until v3. When setting up the cqlengine connection, be sure to specify +protocol_version=3. If using an earlier version, UDT queries will still work, but the returned type will be a namedtuple.

+
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.21.0-scylla/cqlengine/queryset.html b/3.21.0-scylla/cqlengine/queryset.html new file mode 100644 index 0000000000..39a28f7305 --- /dev/null +++ b/3.21.0-scylla/cqlengine/queryset.html @@ -0,0 +1,1005 @@ + + + + + + + + + + + + + Making Queries | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

Making Queries

+
+

Retrieving objects

+

Once you’ve populated Cassandra with data, you’ll probably want to retrieve some of it. This is accomplished with QuerySet objects. This section will describe how to use QuerySet objects to retrieve the data you’re looking for.

+
+

Retrieving all objects

+

The simplest query you can make is to return all objects from a table.

+

This is accomplished with the .all() method, which returns a QuerySet of all objects in a table

+

Using the Person example model, we would get all Person objects like this:

+
all_objects = Person.objects.all()
+
+
+
+
+

Retrieving objects with filters

+

Typically, you’ll want to query only a subset of the records in your database.

+

That can be accomplished with the QuerySet’s .filter(\*\*) method.

+

For example, given the model definition:

+
class Automobile(Model):
+    manufacturer = columns.Text(primary_key=True)
+    year = columns.Integer(primary_key=True)
+    model = columns.Text()
+    price = columns.Decimal()
+    options = columns.Set(columns.Text)
+
+
+

…and assuming the Automobile table contains a record of every car model manufactured in the last 20 years or so, we can retrieve only the cars made by a single manufacturer like this:

+
q = Automobile.objects.filter(manufacturer='Tesla')
+
+
+

You can also use the more convenient syntax:

+
q = Automobile.objects(Automobile.manufacturer == 'Tesla')
+
+
+

We can then further filter our query with another call to .filter

+
q = q.filter(year=2012)
+
+
+

Note: all queries involving any filtering MUST define either an ‘=’ or an ‘in’ relation to either a primary key column, or an indexed column.

+
+
+
+

Accessing objects in a QuerySet

+

There are several methods for getting objects out of a queryset

+
    +
  • +
    iterating over the queryset
    for car in Automobile.objects.all():
    +    #...do something to the car instance
    +    pass
    +
    +
    +
    +
    +
  • +
  • +
    list index
    q = Automobile.objects.all()
    +q[0] #returns the first result
    +q[1] #returns the second result
    +
    +
    +
    +

    Note

    +
      +
    • CQL does not support specifying a start position in it’s queries. Therefore, accessing elements using array indexing will load every result up to the index value requested

    • +
    • Using negative indices requires a “SELECT COUNT()” to be executed. This has a performance cost on large datasets.

    • +
    +
    +
    +
    +
  • +
  • +
    list slicing
    q = Automobile.objects.all()
    +q[1:] #returns all results except the first
    +q[1:9] #returns a slice of the results
    +
    +
    +
    +

    Note

    +
      +
    • CQL does not support specifying a start position in it’s queries. Therefore, accessing elements using array slicing will load every result up to the index value requested

    • +
    • Using negative indices requires a “SELECT COUNT()” to be executed. This has a performance cost on large datasets.

    • +
    +
    +
    +
    +
  • +
  • +
    calling get() on the queryset
    q = Automobile.objects.filter(manufacturer='Tesla')
    +q = q.filter(year=2012)
    +car = q.get()
    +
    +
    +

    this returns the object matching the queryset

    +
    +
    +
  • +
  • +
    calling first() on the queryset
    q = Automobile.objects.filter(manufacturer='Tesla')
    +q = q.filter(year=2012)
    +car = q.first()
    +
    +
    +

    this returns the first value in the queryset

    +
    +
    +
  • +
+
+
+

Filtering Operators

+

Equal To

+

The default filtering operator.

+
q = Automobile.objects.filter(manufacturer='Tesla')
+q = q.filter(year=2012)  #year == 2012
+
+
+

In addition to simple equal to queries, cqlengine also supports querying with other operators by appending a __<op> to the field name on the filtering call

+

in (__in)

+
q = Automobile.objects.filter(manufacturer='Tesla')
+q = q.filter(year__in=[2011, 2012])
+
+
+

> (__gt)

+
q = Automobile.objects.filter(manufacturer='Tesla')
+q = q.filter(year__gt=2010)  # year > 2010
+
+# or the nicer syntax
+
+q.filter(Automobile.year > 2010)
+
+
+

>= (__gte)

+
q = Automobile.objects.filter(manufacturer='Tesla')
+q = q.filter(year__gte=2010)  # year >= 2010
+
+# or the nicer syntax
+
+q.filter(Automobile.year >= 2010)
+
+
+

< (__lt)

+
q = Automobile.objects.filter(manufacturer='Tesla')
+q = q.filter(year__lt=2012)  # year < 2012
+
+# or...
+
+q.filter(Automobile.year < 2012)
+
+
+

<= (__lte)

+
q = Automobile.objects.filter(manufacturer='Tesla')
+q = q.filter(year__lte=2012)  # year <= 2012
+
+q.filter(Automobile.year <= 2012)
+
+
+

CONTAINS (__contains)

+

The CONTAINS operator is available for all collection types (List, Set, Map).

+
q = Automobile.objects.filter(manufacturer='Tesla')
+q.filter(options__contains='backup camera').allow_filtering()
+
+
+

Note that we need to use allow_filtering() since the options column has no secondary index.

+

LIKE (__like)

+

The LIKE operator is available for text columns that have a SASI secondary index.

+
q = Automobile.objects.filter(model__like='%Civic%').allow_filtering()
+
+
+

IS NOT NULL (IsNotNull(column_name))

+

The IS NOT NULL operator is not yet supported for C*.

+
q = Automobile.objects.filter(IsNotNull('model'))
+
+
+

Limitations:

+
    +
  • Currently, cqlengine does not support SASI index creation. To use this feature, you need to create the SASI index using the core driver.

  • +
  • Queries using LIKE must use allow_filtering() since the model column has no standard secondary index. Note that the server will use the SASI index properly when executing the query.

  • +
+
+
+

TimeUUID Functions

+

In addition to querying using regular values, there are two functions you can pass in when querying TimeUUID columns to help make filtering by them easier. Note that these functions don’t actually return a value, but instruct the cql interpreter to use the functions in it’s query.

+
+
+class cqlengine.queryset.MinTimeUUID(datetime)
+

returns the minimum time uuid value possible for the given datetime

+
+ +
+
+class cqlengine.queryset.MaxTimeUUID(datetime)
+

returns the maximum time uuid value possible for the given datetime

+
+ +

Example

+
class DataStream(Model):
+    id      = columns.UUID(partition_key=True)
+    time    = columns.TimeUUID(primary_key=True)
+    data    = columns.Bytes()
+
+min_time = datetime(1982, 1, 1)
+max_time = datetime(1982, 3, 9)
+
+DataStream.filter(time__gt=functions.MinTimeUUID(min_time), time__lt=functions.MaxTimeUUID(max_time))
+
+
+
+
+

Token Function

+

Token functon may be used only on special, virtual column pk__token, representing token of partition key (it also works for composite partition keys). +Cassandra orders returned items by value of partition key token, so using cqlengine.Token we can easy paginate through all table rows.

+

See http://cassandra.apache.org/doc/cql3/CQL-3.0.html#tokenFun

+

Example

+
class Items(Model):
+    id      = columns.Text(primary_key=True)
+    data    = columns.Bytes()
+
+query = Items.objects.all().limit(10)
+
+first_page = list(query);
+last = first_page[-1]
+next_page = list(query.filter(pk__token__gt=cqlengine.Token(last.pk)))
+
+
+
+
+

QuerySets are immutable

+

When calling any method that changes a queryset, the method does not actually change the queryset object it’s called on, but returns a new queryset object with the attributes of the original queryset, plus the attributes added in the method call.

+

Example

+
#this produces 3 different querysets
+#q does not change after it's initial definition
+q = Automobiles.objects.filter(year=2012)
+tesla2012 = q.filter(manufacturer='Tesla')
+honda2012 = q.filter(manufacturer='Honda')
+
+
+
+
+

Ordering QuerySets

+

Since Cassandra is essentially a distributed hash table on steroids, the order you get records back in will not be particularly predictable.

+

However, you can set a column to order on with the .order_by(column_name) method.

+

Example

+
#sort ascending
+q = Automobiles.objects.all().order_by('year')
+#sort descending
+q = Automobiles.objects.all().order_by('-year')
+
+
+

Note: Cassandra only supports ordering on a clustering key. In other words, to support ordering results, your model must have more than one primary key, and you must order on a primary key, excluding the first one.

+

For instance, given our Automobile model, year is the only column we can order on.

+
+
+

Values Lists

+

There is a special QuerySet’s method .values_list() - when called, QuerySet returns lists of values instead of model instances. It may significantly speedup things with lower memory footprint for large responses. +Each tuple contains the value from the respective field passed into the values_list() call — so the first item is the first field, etc. For example:

+
items = list(range(20))
+random.shuffle(items)
+for i in items:
+    TestModel.create(id=1, clustering_key=i)
+
+values = list(TestModel.objects.values_list('clustering_key', flat=True))
+# [19L, 18L, 17L, 16L, 15L, 14L, 13L, 12L, 11L, 10L, 9L, 8L, 7L, 6L, 5L, 4L, 3L, 2L, 1L, 0L]
+
+
+
+
+

Per Query Timeouts

+

By default all queries are executed with the timeout defined in ~cqlengine.connection.setup() +The examples below show how to specify a per-query timeout. +A timeout is specified in seconds and can be an int, float or None. +None means no timeout.

+
class Row(Model):
+    id = columns.Integer(primary_key=True)
+    name = columns.Text()
+
+
+

Fetch all objects with a timeout of 5 seconds

+
Row.objects().timeout(5).all()
+
+
+

Create a single row with a 50ms timeout

+
Row(id=1, name='Jon').timeout(0.05).create()
+
+
+

Delete a single row with no timeout

+
Row(id=1).timeout(None).delete()
+
+
+

Update a single row with no timeout

+
Row(id=1).timeout(None).update(name='Blake')
+
+
+

Batch query timeouts

+
with BatchQuery(timeout=10) as b:
+    Row(id=1, name='Jon').create()
+
+
+

NOTE: You cannot set both timeout and batch at the same time, batch will use the timeout defined in it’s constructor. +Setting the timeout on the model is meaningless and will raise an AssertionError.

+
+
+

Default TTL and Per Query TTL

+

Model default TTL now relies on the default_time_to_live feature, introduced in Cassandra 2.0. It is not handled anymore in the CQLEngine Model (scylla-driver >=3.6). You can set the default TTL of a table like this:

+

Example:

+
class User(Model):
+    __options__ = {'default_time_to_live': 20}
+
+    user_id = columns.UUID(primary_key=True)
+    ...
+
+
+

You can set TTL per-query if needed. Here are a some examples:

+

Example:

+
class User(Model):
+    __options__ = {'default_time_to_live': 20}
+
+    user_id = columns.UUID(primary_key=True)
+    ...
+
+user = User.objects.create(user_id=1)  # Default TTL 20 will be set automatically on the server
+
+user.ttl(30).update(age=21)            # Update the TTL to 30
+User.objects.ttl(10).create(user_id=1)  # TTL 10
+User(user_id=1, age=21).ttl(10).save()  # TTL 10
+
+
+
+
+

Named Tables

+

Named tables are a way of querying a table without creating an class. They’re useful for querying system tables or exploring an unfamiliar database.

+
from cassandra.cqlengine.connection import setup
+setup("127.0.0.1", "cqlengine_test")
+
+from cassandra.cqlengine.named import NamedTable
+user = NamedTable("cqlengine_test", "user")
+user.objects()
+user.objects()[0]
+
+# {u'pk': 1, u't': datetime.datetime(2014, 6, 26, 17, 10, 31, 774000)}
+
+
+
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.21.0-scylla/cqlengine/third_party.html b/3.21.0-scylla/cqlengine/third_party.html new file mode 100644 index 0000000000..d4cb258454 --- /dev/null +++ b/3.21.0-scylla/cqlengine/third_party.html @@ -0,0 +1,705 @@ + + + + + + + + + + + + + Third party integrations | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

Third party integrations

+
+

Celery

+

Here’s how, in substance, CQLengine can be plugged to Celery:

+
from celery import Celery
+from celery.signals import worker_process_init, beat_init
+from cassandra.cqlengine import connection
+from cassandra.cqlengine.connection import (
+    cluster as cql_cluster, session as cql_session)
+
+def cassandra_init(**kwargs):
+    """ Initialize a clean Cassandra connection. """
+    if cql_cluster is not None:
+        cql_cluster.shutdown()
+    if cql_session is not None:
+        cql_session.shutdown()
+    connection.setup()
+
+# Initialize worker context for both standard and periodic tasks.
+worker_process_init.connect(cassandra_init)
+beat_init.connect(cassandra_init)
+
+app = Celery()
+
+
+
+
+

uWSGI

+

This is the code required for proper connection handling of CQLengine for a +uWSGI-run application:

+
from cassandra.cqlengine import connection
+from cassandra.cqlengine.connection import (
+    cluster as cql_cluster, session as cql_session)
+
+try:
+    from uwsgidecorators import postfork
+except ImportError:
+    # We're not in a uWSGI context, no need to hook Cassandra session
+    # initialization to the postfork event.
+    pass
+else:
+    @postfork
+    def cassandra_init(**kwargs):
+        """ Initialize a new Cassandra session in the context.
+
+        Ensures that a new session is returned for every new request.
+        """
+        if cql_cluster is not None:
+            cql_cluster.shutdown()
+        if cql_session is not None:
+            cql_session.shutdown()
+        connection.setup()
+
+
+
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.21.0-scylla/cqlengine/upgrade_guide.html b/3.21.0-scylla/cqlengine/upgrade_guide.html new file mode 100644 index 0000000000..74df188121 --- /dev/null +++ b/3.21.0-scylla/cqlengine/upgrade_guide.html @@ -0,0 +1,837 @@ + + + + + + + + + + + + + Upgrade Guide | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + + + +
+

Upgrade Guide

+

This is an overview of things that changed as the cqlengine project was merged into +scylla-driver. While efforts were taken to preserve the API and most functionality exactly, +conversion to this package will still require certain minimal updates (namely, imports).

+

THERE IS ONE FUNCTIONAL CHANGE, described in the first section below.

+
+

Functional Changes

+
+

List Prepend Reversing

+

Legacy cqlengine included a workaround for a Cassandra bug in which prepended list segments were +reversed (CASSANDRA-8733). As of +this integration, this workaround is removed. The first released integrated version emits +a warning when prepend is used. Subsequent versions will have this warning removed.

+
+
+

Date Column Type

+

The Date column type in legacy cqlengine used a timestamp CQL type and truncated the time. +Going forward, the Date type represents a date for Cassandra 2.2+ +(PYTHON-245). +Users of the legacy functionality should convert models to use DateTime (which +uses timestamp internally), and use the build-in datetime.date for input values.

+
+
+
+

Remove cqlengine

+

To avoid confusion or mistakes using the legacy package in your application, it +is prudent to remove the cqlengine package when upgrading to the integrated version.

+

The driver setup script will warn if the legacy package is detected during install, +but it will not prevent side-by-side installation.

+
+
+

Organization

+
+

Imports

+

cqlengine is now integrated as a sub-package of the driver base package ‘cassandra’. +Upgrading will require adjusting imports to cqlengine. For example:

+
from cassandra.cqlengine import columns
+
+
+

is now:

+
from cassandra.cqlengine import columns
+
+
+
+
+

Package-Level Aliases

+

Legacy cqlengine defined a number of aliases at the package level, which became redundant +when the package was integrated for a driver. These have been removed in favor of absolute +imports, and referring to cannonical definitions. For example, cqlengine.ONE was an alias +of cassandra.ConsistencyLevel.ONE. In the integrated package, only the +cassandra.ConsistencyLevel remains.

+

Additionally, submodule aliases are removed from cqlengine in favor of absolute imports.

+

These aliases are removed, and not deprecated because they should be straightforward to iron out +at module load time.

+
+
+

Exceptions

+

The legacy cqlengine.exceptions module had a number of Exception classes that were variously +common to the package, or only used in specific modules. Common exceptions were relocated to +cqlengine, and specialized exceptions were placed in the module that raises them. Below is a +listing of updated locations:

+ ++++ + + + + + + + + + + + + + + + + + + + + + + + + + +

Exception class

New module

CQLEngineException

cassandra.cqlengine

ModelException

cassandra.cqlengine.models

ValidationError

cassandra.cqlengine

UndefinedKeyspaceException

cassandra.cqlengine.connection

LWTException

cassandra.cqlengine.query

IfNotExistsWithCounterColumn

cassandra.cqlengine.query

+
+
+

UnicodeMixin Consolidation

+

class UnicodeMixin was defined in several cqlengine modules. This has been consolidated +to a single definition in the cqlengine package init file. This is not technically part of +the API, but noted here for completeness.

+
+
+
+

API Deprecations

+

This upgrade served as a good juncture to deprecate certain API features and invite users to upgrade +to new ones. The first released version does not change functionality – only introduces deprecation +warnings. Future releases will remove these features in favor of the alternatives.

+
+

Float/Double Overload

+

Previously there was no Double column type. Doubles were modeled by specifying Float(double_precision=True). +This inititializer parameter is now deprecated. Applications should use Double for CQL double, and Float +for CQL float.

+
+
+

Schema Management

+

cassandra.cqlengine.management.create_keyspace is deprecated. Instead, use the new replication-strategy-specific +functions that accept explicit options for known strategies:

+ +

cassandra.cqlengine.management.delete_keyspace is deprecated in favor of a new function, drop_keyspace(). The +intent is simply to make the function match the CQL verb it invokes.

+
+
+

Model Inheritance

+

The names for class attributes controlling model inheritance are changing. Changes are as follows:

+ +

The functionality is unchanged – the intent here is to make the names and language around these attributes more precise. +For now, the old names are just deprecated, and the mapper will emit warnings if they are used. The old names +will be removed in a future version.

+

The example below shows a simple translation:

+

Before:

+
class Pet(Model):
+    __table_name__ = 'pet'
+    owner_id = UUID(primary_key=True)
+    pet_id = UUID(primary_key=True)
+    pet_type = Text(polymorphic_key=True)
+    name = Text()
+
+class Cat(Pet):
+    __polymorphic_key__ = 'cat'
+
+class Dog(Pet):
+    __polymorphic_key__ = 'dog'
+
+
+

After:

+
class Pet(models.Model):
+    __table_name__ = 'pet'
+    owner_id = UUID(primary_key=True)
+    pet_id = UUID(primary_key=True)
+    pet_type = Text(discriminator_column=True)
+    name = Text()
+
+class Cat(Pet):
+    __discriminator_value__ = 'cat'
+
+class Dog(Pet):
+    __discriminator_value__ = 'dog'
+
+
+
+
+

TimeUUID.from_datetime

+

This function is deprecated in favor of the core utility function uuid_from_time().

+
+
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.21.0-scylla/dates_and_times.html b/3.21.0-scylla/dates_and_times.html new file mode 100644 index 0000000000..16397544b3 --- /dev/null +++ b/3.21.0-scylla/dates_and_times.html @@ -0,0 +1,729 @@ + + + + + + + + + + + + + Working with Dates and Times | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

Working with Dates and Times

+

This document is meant to provide on overview of the assumptions and limitations of the driver time handling, the +reasoning behind it, and describe approaches to working with these types.

+
+

timestamps (Cassandra DateType)

+

Timestamps in Cassandra are timezone-naive timestamps encoded as millseconds since UNIX epoch. Clients working with +timestamps in this database usually find it easiest to reason about them if they are always assumed to be UTC. To quote the +pytz documentation, “The preferred way of dealing with times is to always work in UTC, converting to localtime only when +generating output to be read by humans.” The driver adheres to this tenant, and assumes UTC is always in the database. The +driver attempts to make this correct on the way in, and assumes no timezone on the way out.

+
+

Write Path

+

When inserting timestamps, the driver handles serialization for the write path as follows:

+

If the input is a datetime.datetime, the serialization is normalized by starting with the utctimetuple() of the +value.

+
    +
  • If the datetime object is timezone-aware, the timestamp is shifted, and represents the UTC timestamp equivalent.

  • +
  • If the datetime object is timezone-naive, this results in no shift – any datetime with no timezone information is assumed to be UTC

  • +
+

Note the second point above applies even to “local” times created using now():

+
>>> d = datetime.now()
+
+>>> print(d.tzinfo)
+None
+
+
+

These do not contain timezone information intrinsically, so they will be assumed to be UTC and not shifted. When generating +timestamps in the application, it is clearer to use datetime.utcnow() to be explicit about it.

+

If the input for a timestamp is numeric, it is assumed to be a epoch-relative millisecond timestamp, as specified in the +CQL spec – no scaling or conversion is done.

+
+
+

Read Path

+

The driver always assumes persisted timestamps are UTC and makes no attempt to localize them. Returned values are +timezone-naive datetime.datetime. We follow this approach because the datetime API has deficiencies around daylight +saving time, and the defacto package for handling this is a third-party package (we try to minimize external dependencies +and not make decisions for the integrator).

+

The decision for how to handle timezones is left to the application. For the most part it is straightforward to apply +localization to the datetimes returned by queries. One prevalent method is to use pytz for localization:

+
import pytz
+user_tz = pytz.timezone('US/Central')
+timestamp_naive = row.ts
+timestamp_utc = pytz.utc.localize(timestamp_naive)
+timestamp_presented = timestamp_utc.astimezone(user_tz)
+
+
+

This is the most robust approach (likely refactored into a function). If it is deemed too cumbersome to apply for all call +sites in the application, it is possible to patch the driver with custom deserialization for this type. However, doing +this depends depends some on internal APIs and what extensions are present, so we will only mention the possibility, and +not spell it out here.

+
+
+
+

date, time (Cassandra DateType)

+

Date and time in Cassandra are idealized markers, much like datetime.date and datetime.time in the Python standard +library. Unlike these Python implementations, the Cassandra encoding supports much wider ranges. To accommodate these +ranges without overflow, this driver returns these data in custom types: util.Date and util.Time.

+
+

Write Path

+

For simple (not prepared) statements, the input values for each of these can be either a string literal or an encoded +integer. See Working with dates +or Working with time for details +on the encoding or string formats.

+

For prepared statements, the driver accepts anything that can be used to construct the util.Date or +util.Time classes. See the linked API docs for details.

+
+
+

Read Path

+

The driver always returns custom types for date and time.

+

The driver returns util.Date for date in order to accommodate the wider range of values without overflow. +For applications working within the supported range of [datetime.MINYEAR, datetime.MAXYEAR], these are easily +converted to standard datetime.date insances using Date.date().

+

The driver returns util.Time for time in order to retain nanosecond precision stored in the database. +For applications not concerned with this level of precision, these are easily converted to standard datetime.time +insances using Time.time().

+
+
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.21.0-scylla/execution_profiles.html b/3.21.0-scylla/execution_profiles.html new file mode 100644 index 0000000000..8cc8f97beb --- /dev/null +++ b/3.21.0-scylla/execution_profiles.html @@ -0,0 +1,773 @@ + + + + + + + + + + + + + Execution Profiles | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

Execution Profiles

+

Execution profiles aim at making it easier to execute requests in different ways within +a single connected Session. Execution profiles are being introduced to deal with the exploding number of +configuration options, especially as the database platform evolves more complex workloads.

+

The legacy configuration remains intact, but legacy and Execution Profile APIs +cannot be used simultaneously on the same client Cluster. Legacy configuration +will be removed in the next major release (4.0).

+

An execution profile and its parameters should be unique across Cluster instances. +For example, an execution profile and its LoadBalancingPolicy should +not be applied to more than one Cluster instance.

+

This document explains how Execution Profiles relate to existing settings, and shows how to use the new profiles for +request execution.

+
+

Mapping Legacy Parameters to Profiles

+

Execution profiles can inherit from cluster.ExecutionProfile, and currently provide the following options, +previously input from the noted attributes:

+ +

When using the new API, these parameters can be defined by instances of cluster.ExecutionProfile.

+
+
+

Using Execution Profiles

+
+

Default

+
from cassandra.cluster import Cluster
+cluster = Cluster()
+session = cluster.connect()
+local_query = 'SELECT rpc_address FROM system.local'
+for _ in cluster.metadata.all_hosts():
+    print session.execute(local_query)[0]
+
+
+
Row(rpc_address='127.0.0.2')
+Row(rpc_address='127.0.0.1')
+
+
+

The default execution profile is built from Cluster parameters and default Session attributes. This profile matches existing default +parameters.

+
+
+

Initializing cluster with profiles

+
from cassandra.cluster import ExecutionProfile
+from cassandra.policies import WhiteListRoundRobinPolicy
+
+node1_profile = ExecutionProfile(load_balancing_policy=WhiteListRoundRobinPolicy(['127.0.0.1']))
+node2_profile = ExecutionProfile(load_balancing_policy=WhiteListRoundRobinPolicy(['127.0.0.2']))
+
+profiles = {'node1': node1_profile, 'node2': node2_profile}
+session = Cluster(execution_profiles=profiles).connect()
+for _ in cluster.metadata.all_hosts():
+    print session.execute(local_query, execution_profile='node1')[0]
+
+
+
Row(rpc_address='127.0.0.1')
+Row(rpc_address='127.0.0.1')
+
+
+
for _ in cluster.metadata.all_hosts():
+    print session.execute(local_query, execution_profile='node2')[0]
+
+
+
Row(rpc_address='127.0.0.2')
+Row(rpc_address='127.0.0.2')
+
+
+
for _ in cluster.metadata.all_hosts():
+    print session.execute(local_query)[0]
+
+
+
Row(rpc_address='127.0.0.2')
+Row(rpc_address='127.0.0.1')
+
+
+

Note that, even when custom profiles are injected, the default TokenAwarePolicy(DCAwareRoundRobinPolicy()) is still +present. To override the default, specify a policy with the EXEC_PROFILE_DEFAULT key.

+
from cassandra.cluster import EXEC_PROFILE_DEFAULT
+profile = ExecutionProfile(request_timeout=30)
+cluster = Cluster(execution_profiles={EXEC_PROFILE_DEFAULT: profile})
+
+
+
+
+

Adding named profiles

+

New profiles can be added constructing from scratch, or deriving from default:

+
locked_execution = ExecutionProfile(load_balancing_policy=WhiteListRoundRobinPolicy(['127.0.0.1']))
+node1_profile = 'node1_whitelist'
+cluster.add_execution_profile(node1_profile, locked_execution)
+
+for _ in cluster.metadata.all_hosts():
+    print session.execute(local_query, execution_profile=node1_profile)[0]
+
+
+
Row(rpc_address='127.0.0.1')
+Row(rpc_address='127.0.0.1')
+
+
+

See Cluster.add_execution_profile() for details and optional parameters.

+
+
+

Passing a profile instance without mapping

+

We also have the ability to pass profile instances to be used for execution, but not added to the mapping:

+
from cassandra.query import tuple_factory
+
+tmp = session.execution_profile_clone_update('node1', request_timeout=100, row_factory=tuple_factory)
+
+print session.execute(local_query, execution_profile=tmp)[0]
+print session.execute(local_query, execution_profile='node1')[0]
+
+
+
('127.0.0.1',)
+Row(rpc_address='127.0.0.1')
+
+
+

The new profile is a shallow copy, so the tmp profile shares a load balancing policy with one managed by the cluster. +If reference objects are to be updated in the clone, one would typically set those attributes to a new instance.

+
+
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.21.0-scylla/faq.html b/3.21.0-scylla/faq.html new file mode 100644 index 0000000000..74cbebbbe5 --- /dev/null +++ b/3.21.0-scylla/faq.html @@ -0,0 +1,709 @@ + + + + + + + + + + + + + Frequently Asked Questions | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

Frequently Asked Questions

+

See also cqlengine FAQ

+
+

Why do connections or IO operations timeout in my WSGI application?

+

Depending on your application process model, it may be forking after driver Session is created. Most IO reactors do not handle this, and problems will manifest as timeouts.

+

To avoid this, make sure to create sessions per process, after the fork. Using uWSGI and Flask for example:

+
from flask import Flask
+from uwsgidecorators import postfork
+from cassandra.cluster import Cluster
+
+session = None
+prepared = None
+
+@postfork
+def connect():
+    global session, prepared
+    session = Cluster().connect()
+    prepared = session.prepare("SELECT release_version FROM system.local WHERE key=?")
+
+app = Flask(__name__)
+
+@app.route('/')
+def server_version():
+    row = session.execute(prepared, ('local',))[0]
+    return row.release_version
+
+
+

uWSGI provides a postfork hook you can use to create sessions and prepared statements after the child process forks.

+
+
+

How do I trace a request?

+

Request tracing can be turned on for any request by setting trace=True in Session.execute_async(). View the results by waiting on the future, then ResponseFuture.get_query_trace(). +Since tracing is done asynchronously to the request, this method polls until the trace is complete before querying data.

+
>>> future = session.execute_async("SELECT * FROM system.local", trace=True)
+>>> result = future.result()
+>>> trace = future.get_query_trace()
+>>> for e in trace.events:
+>>>     print e.source_elapsed, e.description
+
+0:00:00.000077 Parsing select * from system.local
+0:00:00.000153 Preparing statement
+0:00:00.000309 Computing ranges to query
+0:00:00.000368 Submitting range requests on 1 ranges with a concurrency of 1 (279.77142 rows per range expected)
+0:00:00.000422 Submitted 1 concurrent range requests covering 1 ranges
+0:00:00.000480 Executing seq scan across 1 sstables for (min(-9223372036854775808), min(-9223372036854775808))
+0:00:00.000669 Read 1 live and 0 tombstone cells
+0:00:00.000755 Scanned 1 rows and matched 1
+
+
+

trace is a QueryTrace object.

+
+
+

How do I determine the replicas for a query?

+

With prepared statements, the replicas are obtained by routing_key, based on current cluster token metadata:

+
>>> prepared = session.prepare("SELECT * FROM example.t WHERE key=?")
+>>> bound = prepared.bind((1,))
+>>> replicas = cluster.metadata.get_replicas(bound.keyspace, bound.routing_key)
+>>> for h in replicas:
+>>>   print h.address
+127.0.0.1
+127.0.0.2
+
+
+

replicas is a list of Host objects.

+
+
+

How does the driver manage request retries?

+

By default, retries are managed by the Cluster.default_retry_policy set on the session Cluster. It can also +be specialized per statement by setting Statement.retry_policy.

+

Retries are presently attempted on the same coordinator, but this may change in the future.

+

Please see policies.RetryPolicy for further details.

+
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.21.0-scylla/getting_started.html b/3.21.0-scylla/getting_started.html new file mode 100644 index 0000000000..4b329b1b8d --- /dev/null +++ b/3.21.0-scylla/getting_started.html @@ -0,0 +1,1114 @@ + + + + + + + + + + + + + Getting Started | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

Getting Started

+

First, make sure you have the driver properly installed.

+
+

Connecting to Cassandra

+

Before we can start executing any queries against a Cassandra cluster we need to setup +an instance of Cluster. As the name suggests, you will typically have one +instance of Cluster for each Cassandra cluster you want to interact +with.

+

The simplest way to create a Cluster is like this: +First, make sure you have the Cassandra driver properly installed.

+
from cassandra.cluster import Cluster
+
+cluster = Cluster()
+
+
+

This will attempt to connection to a Cassandra instance on your +local machine (127.0.0.1). You can also specify a list of IP +addresses for nodes in your cluster:

+
from cassandra.cluster import Cluster
+
+cluster = Cluster(['192.168.0.1', '192.168.0.2'])
+
+
+

The set of IP addresses we pass to the Cluster is simply +an initial set of contact points. After the driver connects to one +of these nodes it will automatically discover the rest of the +nodes in the cluster and connect to them, so you don’t need to list +every node in your cluster.

+

If you need to use a non-standard port, use SSL, or customize the driver’s +behavior in some other way, this is the place to do it:

+
from cassandra.cluster import Cluster
+cluster = Cluster(['192.168.0.1', '192.168.0.2'], port=..., ssl_context=...)
+
+
+

Instantiating a Cluster does not actually connect us to any nodes. +To establish connections and begin executing queries we need a +Session, which is created by calling Cluster.connect():

+
cluster = Cluster()
+session = cluster.connect()
+
+
+

The connect() method takes an optional keyspace argument +which sets the default keyspace for all queries made through that Session:

+
cluster = Cluster()
+session = cluster.connect('mykeyspace')
+
+
+

You can always change a Session’s keyspace using set_keyspace() or +by executing a USE <keyspace> query:

+
session.set_keyspace('users')
+# or you can do this instead
+session.execute('USE users')
+
+
+

Profiles are passed in by execution_profiles dict.

+

In this case we can construct the base ExecutionProfile passing all attributes:

+
from cassandra.cluster import Cluster, ExecutionProfile, EXEC_PROFILE_DEFAULT
+from cassandra.policies import WhiteListRoundRobinPolicy, DowngradingConsistencyRetryPolicy
+from cassandra.query import tuple_factory
+
+profile = ExecutionProfile(
+    load_balancing_policy=WhiteListRoundRobinPolicy(['127.0.0.1']),
+    retry_policy=DowngradingConsistencyRetryPolicy(),
+    consistency_level=ConsistencyLevel.LOCAL_QUORUM,
+    serial_consistency_level=ConsistencyLevel.LOCAL_SERIAL,
+    request_timeout=15,
+    row_factory=tuple_factory
+)
+cluster = Cluster(execution_profiles={EXEC_PROFILE_DEFAULT: profile})
+session = cluster.connect()
+
+print(session.execute("SELECT release_version FROM system.local").one())
+
+
+

Users are free to setup additional profiles to be used by name:

+
profile_long = ExecutionProfile(request_timeout=30)
+cluster = Cluster(execution_profiles={'long': profile_long})
+session = cluster.connect()
+session.execute(statement, execution_profile='long')
+
+
+

Also, parameters passed to Session.execute or attached to Statements are still honored as before.

+
+
+

Executing Queries

+

Now that we have a Session we can begin to execute queries. The simplest +way to execute a query is to use execute():

+
rows = session.execute('SELECT name, age, email FROM users')
+for user_row in rows:
+    print user_row.name, user_row.age, user_row.email
+
+
+

This will transparently pick a Cassandra node to execute the query against +and handle any retries that are necessary if the operation fails.

+

By default, each row in the result set will be a +namedtuple. +Each row will have a matching attribute for each column defined in the schema, +such as name, age, and so on. You can also treat them as normal tuples +by unpacking them or accessing fields by position. The following three +examples are equivalent:

+
rows = session.execute('SELECT name, age, email FROM users')
+for row in rows:
+    print row.name, row.age, row.email
+
+
+
rows = session.execute('SELECT name, age, email FROM users')
+for (name, age, email) in rows:
+    print name, age, email
+
+
+
rows = session.execute('SELECT name, age, email FROM users')
+for row in rows:
+    print row[0], row[1], row[2]
+
+
+

If you prefer another result format, such as a dict per row, you +can change the row_factory attribute.

+

As mentioned in our Drivers Best Practices Guide, +it is highly recommended to use Prepared statements for your +frequently run queries.

+
+
+

Prepared Statements

+

Prepared statements are queries that are parsed by Cassandra and then saved +for later use. When the driver uses a prepared statement, it only needs to +send the values of parameters to bind. This lowers network traffic +and CPU utilization within Cassandra because Cassandra does not have to +re-parse the query each time.

+

To prepare a query, use Session.prepare():

+
user_lookup_stmt = session.prepare("SELECT * FROM users WHERE user_id=?")
+
+users = []
+for user_id in user_ids_to_query:
+    user = session.execute(user_lookup_stmt, [user_id])
+    users.append(user)
+
+
+

prepare() returns a PreparedStatement instance +which can be used in place of SimpleStatement instances or literal +string queries. It is automatically prepared against all nodes, and the driver +handles re-preparing against new nodes and restarted nodes when necessary.

+

Note that the placeholders for prepared statements are ? characters. This +is different than for simple, non-prepared statements (although future versions +of the driver may use the same placeholders for both).

+
+

Passing Parameters to CQL Queries

+

Althought it is not recommended, you can also pass parameters to non-prepared +statements. The driver supports two forms of parameter place-holders: positional +and named.

+

Positional parameters are used with a %s placeholder. For example, +when you execute:

+
session.execute(
+    """
+    INSERT INTO users (name, credits, user_id)
+    VALUES (%s, %s, %s)
+    """,
+    ("John O'Reilly", 42, uuid.uuid1())
+)
+
+
+

It is translated to the following CQL query:

+
INSERT INTO users (name, credits, user_id)
+VALUES ('John O''Reilly', 42, 2644bada-852c-11e3-89fb-e0b9a54a6d93)
+
+
+

Note that you should use %s for all types of arguments, not just strings. +For example, this would be wrong:

+
session.execute("INSERT INTO USERS (name, age) VALUES (%s, %d)", ("bob", 42))  # wrong
+
+
+

Instead, use %s for the age placeholder.

+

If you need to use a literal % character, use %%.

+

Note: you must always use a sequence for the second argument, even if you are +only passing in a single variable:

+
session.execute("INSERT INTO foo (bar) VALUES (%s)", "blah")  # wrong
+session.execute("INSERT INTO foo (bar) VALUES (%s)", ("blah"))  # wrong
+session.execute("INSERT INTO foo (bar) VALUES (%s)", ("blah", ))  # right
+session.execute("INSERT INTO foo (bar) VALUES (%s)", ["blah"])  # right
+
+
+

Note that the second line is incorrect because in Python, single-element tuples +require a comma.

+

Named place-holders use the %(name)s form:

+
session.execute(
+    """
+    INSERT INTO users (name, credits, user_id, username)
+    VALUES (%(name)s, %(credits)s, %(user_id)s, %(name)s)
+    """,
+    {'name': "John O'Reilly", 'credits': 42, 'user_id': uuid.uuid1()}
+)
+
+
+

Note that you can repeat placeholders with the same name, such as %(name)s +in the above example.

+

Only data values should be supplied this way. Other items, such as keyspaces, +table names, and column names should be set ahead of time (typically using +normal string formatting).

+
+
+

Type Conversions

+

For non-prepared statements, Python types are cast to CQL literals in the +following way:

+ ++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Python Type

CQL Literal Type

None

NULL

bool

boolean

float

+
float
+
double
+
+
+
int
+
long
+
+
+
int
+
bigint
+
varint
+
smallint
+
tinyint
+
counter
+
+

decimal.Decimal

decimal

+
str
+
unicode
+
+
+
ascii
+
varchar
+
text
+
+
+
buffer
+
bytearray
+
+

blob

date

date

datetime

timestamp

time

time

+
list
+
tuple
+
generator
+
+

list

+
set
+
frozenset
+
+

set

+
dict
+
OrderedDict
+
+

map

uuid.UUID

+
timeuuid
+
uuid
+
+
+
+
+

Asynchronous Queries

+

The driver supports asynchronous query execution through +execute_async(). Instead of waiting for the query to +complete and returning rows directly, this method almost immediately +returns a ResponseFuture object. There are two ways of +getting the final result from this object.

+

The first is by calling result() on it. If +the query has not yet completed, this will block until it has and +then return the result or raise an Exception if an error occurred. +For example:

+
from cassandra import ReadTimeout
+
+query = "SELECT * FROM users WHERE user_id=%s"
+future = session.execute_async(query, [user_id])
+
+# ... do some other work
+
+try:
+    rows = future.result()
+    user = rows[0]
+    print user.name, user.age
+except ReadTimeout:
+    log.exception("Query timed out:")
+
+
+

This works well for executing many queries concurrently:

+
# build a list of futures
+futures = []
+query = "SELECT * FROM users WHERE user_id=%s"
+for user_id in ids_to_fetch:
+    futures.append(session.execute_async(query, [user_id])
+
+# wait for them to complete and use the results
+for future in futures:
+    rows = future.result()
+    print rows[0].name
+
+
+

Alternatively, instead of calling result(), +you can attach callback and errback functions through the +add_callback(), +add_errback(), and +add_callbacks(), methods. If you have used +Twisted Python before, this is designed to be a lightweight version of +that:

+
def handle_success(rows):
+    user = rows[0]
+    try:
+        process_user(user.name, user.age, user.id)
+    except Exception:
+        log.error("Failed to process user %s", user.id)
+        # don't re-raise errors in the callback
+
+def handle_error(exception):
+    log.error("Failed to fetch user info: %s", exception)
+
+
+future = session.execute_async(query)
+future.add_callbacks(handle_success, handle_error)
+
+
+
+
There are a few important things to remember when working with callbacks:
    +
  • Exceptions that are raised inside the callback functions will be logged and then ignored.

  • +
  • Your callback will be run on the event loop thread, so any long-running +operations will prevent other requests from being handled

  • +
+
+
+
+
+
+

Setting a Consistency Level

+

The consistency level used for a query determines how many of the +replicas of the data you are interacting with need to respond for +the query to be considered a success.

+

By default, ConsistencyLevel.LOCAL_ONE will be used for all queries. +You can specify a different default by setting the ExecutionProfile.consistency_level +for the execution profile with key EXEC_PROFILE_DEFAULT. +To specify a different consistency level per request, wrap queries +in a SimpleStatement:

+
from cassandra import ConsistencyLevel
+from cassandra.query import SimpleStatement
+
+query = SimpleStatement(
+    "INSERT INTO users (name, age) VALUES (%s, %s)",
+    consistency_level=ConsistencyLevel.QUORUM)
+session.execute(query, ('John', 42))
+
+
+
+

Setting a Consistency Level with Prepared Statements

+

To specify a consistency level for prepared statements, you have two options.

+

The first is to set a default consistency level for every execution of the +prepared statement:

+
from cassandra import ConsistencyLevel
+
+cluster = Cluster()
+session = cluster.connect("mykeyspace")
+user_lookup_stmt = session.prepare("SELECT * FROM users WHERE user_id=?")
+user_lookup_stmt.consistency_level = ConsistencyLevel.QUORUM
+
+# these will both use QUORUM
+user1 = session.execute(user_lookup_stmt, [user_id1])[0]
+user2 = session.execute(user_lookup_stmt, [user_id2])[0]
+
+
+

The second option is to create a BoundStatement from the +PreparedStatement and binding parameters and set a consistency +level on that:

+
# override the QUORUM default
+user3_lookup = user_lookup_stmt.bind([user_id3])
+user3_lookup.consistency_level = ConsistencyLevel.ALL
+user3 = session.execute(user3_lookup)
+
+
+
+
+

Speculative Execution

+

Speculative execution is a way to minimize latency by preemptively executing several +instances of the same query against different nodes. For more details about this +technique, see Speculative Execution with DataStax Drivers.

+

To enable speculative execution:

+
    +
  • Configure a SpeculativeExecutionPolicy with the ExecutionProfile

  • +
  • Mark your query as idempotent, which mean it can be applied multiple +times without changing the result of the initial application. +See Query Idempotence for more details.

  • +
+

Example:

+
from cassandra.cluster import Cluster, ExecutionProfile, EXEC_PROFILE_DEFAULT
+from cassandra.policies import ConstantSpeculativeExecutionPolicy
+from cassandra.query import SimpleStatement
+
+# Configure the speculative execution policy
+ep = ExecutionProfile(
+    speculative_execution_policy=ConstantSpeculativeExecutionPolicy(delay=.5, max_attempts=10)
+)
+cluster = Cluster(..., execution_profiles={EXEC_PROFILE_DEFAULT: ep})
+session = cluster.connect()
+
+# Mark the query idempotent
+query = SimpleStatement(
+    "UPDATE my_table SET list_col = [1] WHERE pk = 1",
+    is_idempotent=True
+)
+
+# Execute. A new query will be sent to the server every 0.5 second
+# until we receive a response, for a max number attempts of 10.
+session.execute(query)
+
+
+
+
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.21.0-scylla/index.html b/3.21.0-scylla/index.html new file mode 100644 index 0000000000..332966dddd --- /dev/null +++ b/3.21.0-scylla/index.html @@ -0,0 +1,699 @@ + + + + + + + + + + + + + DataStax Python Driver for Apache Cassandra® | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

DataStax Python Driver for Apache Cassandra®

+

A Python client driver for Apache Cassandra®. +This driver works exclusively with the Cassandra Query Language v3 (CQL3) +and Cassandra’s native protocol. Cassandra 2.1+ is supported, including DSE 4.7+.

+

The driver supports Python 2.7, 3.4, 3.5, 3.6, 3.7 and 3.8.

+

This driver is open source under the +Apache v2 License. +The source code for this driver can be found on GitHub.

+

Note: DataStax products do not support big-endian systems.

+
+

Contents

+
+
Installation

How to install the driver.

+
+
Getting Started

A guide through the first steps of connecting to Cassandra and executing queries

+
+
Execution Profiles

An introduction to a more flexible way of configuring request execution

+
+
Lightweight Transactions (Compare-and-set)

Working with results of conditional requests

+
+
Object Mapper

Introduction to the integrated object mapper, cqlengine

+
+
Performance Notes

Tips for getting good performance.

+
+
Paging Large Queries

Notes on paging large query results

+
+
Security

An overview of the security features of the driver

+
+
Upgrading

A guide to upgrading versions of the driver

+
+
User Defined Types

Working with Cassandra 2.1’s user-defined types

+
+
Working with Dates and Times

Some discussion on the driver’s approach to working with timestamp, date, time types

+
+
cloud

A guide to connecting to Datastax Apollo

+
+
geo_types

Working with DSE geometry types

+
+
graph

Graph queries with DSE Graph

+
+
graph_fluent

DataStax Graph Fluent API

+
+
CHANGELOG

Log of changes to the driver, organized by version.

+
+
Frequently Asked Questions

A collection of Frequently Asked Questions

+
+
API Documentation

The API documentation.

+
+
+
+
+
+
+

Getting Help

+

Visit the FAQ section in this documentation.

+

Please send questions to the mailing list.

+

Alternatively, you can use the DataStax Community.

+
+
+

Reporting Issues

+

Please report any bugs and make any feature requests on the +JIRA issue tracker.

+

If you would like to contribute, please feel free to open a pull request.

+
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.21.0-scylla/installation.html b/3.21.0-scylla/installation.html new file mode 100644 index 0000000000..1d1f4382ad --- /dev/null +++ b/3.21.0-scylla/installation.html @@ -0,0 +1,873 @@ + + + + + + + + + + + + + Installation | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

Installation

+
+

Supported Platforms

+

Python 2.7, 3.4, 3.5, 3.6, 3.7 and 3.8 are supported. Both CPython (the standard Python +implementation) and PyPy are supported and tested.

+

Linux, OSX, and Windows are supported.

+
+
+

Installation through pip

+

pip is the suggested tool for installing +packages. It will handle installing all Python dependencies for the driver at +the same time as the driver itself. To install the driver*:

+
pip install scylla-driver
+
+
+

You can use pip install --pre scylla-driver if you need to install a beta version.

+

*Note: if intending to use optional extensions, install the dependencies first. The driver may need to be reinstalled if dependencies are added after the initial installation.

+
+
+

Verifying your Installation

+

To check if the installation was successful, you can run:

+
python -c 'import cassandra; print cassandra.__version__'
+
+
+

It should print something like “3.21.0”.

+
+
+

(Optional) DataStax Graph

+

The driver provides an optional fluent graph API that depends on Apache TinkerPop (gremlinpython). It is +not installed by default. To be able to build Gremlin traversals, you need to install +the graph requirements:

+
pip install scylla-driver[graph]
+
+
+

See graph_fluent for more details about this API.

+
+
+

(Optional) Compression Support

+

Compression can optionally be used for communication between the driver and +Cassandra. There are currently two supported compression algorithms: +snappy (in Cassandra 1.2+) and LZ4 (only in Cassandra 2.0+). If either is +available for the driver and Cassandra also supports it, it will +be used automatically.

+

For lz4 support:

+
pip install lz4
+
+
+

For snappy support:

+
pip install python-snappy
+
+
+

(If using a Debian Linux derivative such as Ubuntu, it may be easier to +just run apt-get install python-snappy.)

+
+
+

(Optional) Metrics Support

+

The driver has built-in support for capturing Cluster.metrics about +the queries you run. However, the scales library is required to +support this:

+
pip install scales
+
+
+
+

Speeding Up Installation

+

By default, installing the driver through pip uses a pre-compiled, platform-specific wheel when available. +If using a source distribution rather than a wheel, Cython is used to compile certain parts of the driver. +This makes those hot paths faster at runtime, but the Cython compilation +process can take a long time – as long as 10 minutes in some environments.

+

In environments where performance is less important, it may be worth it to +disable Cython as documented below. +You can also use CASS_DRIVER_BUILD_CONCURRENCY to increase the number of +threads used to build the driver and any C extensions:

+
$ # installing from source
+$ CASS_DRIVER_BUILD_CONCURRENCY=8 python setup.py install
+$ # installing from pip
+$ CASS_DRIVER_BUILD_CONCURRENCY=8 pip install scylla-driver
+
+
+
+
+

OSX Installation Error

+

If you’re installing on OSX and have XCode 5.1 installed, you may see an error like this:

+
clang: error: unknown argument: '-mno-fused-madd' [-Wunused-command-line-argument-hard-error-in-future]
+
+
+

To fix this, re-run the installation with an extra compilation flag:

+
ARCHFLAGS=-Wno-error=unused-command-line-argument-hard-error-in-future pip install scylla-driver
+
+
+
+
+
+

Windows Installation Notes

+

Installing the driver with extensions in Windows sometimes presents some challenges. A few notes about common +hang-ups:

+

Setup requires a compiler. When using Python 2, this is as simple as installing this package +(this link is also emitted during install if setuptools is unable to find the resources it needs). Depending on your +system settings, this package may install as a user-specific application. Make sure to install for everyone, or at least +as the user that will be building the Python environment.

+

It is also possible to run the build with your compiler of choice. Just make sure to have your environment setup with +the proper paths. Make sure the compiler target architecture matches the bitness of your Python runtime. +Perhaps the easiest way to do this is to run the build/install from a Visual Studio Command Prompt (a +shortcut installed with Visual Studio that sources the appropriate environment and presents a shell).

+
+
+

Manual Installation

+

You can always install the driver directly from a source checkout or tarball. +When installing manually, ensure the python dependencies are already +installed. You can find the list of dependencies in +requirements.txt.

+

Once the dependencies are installed, simply run:

+
python setup.py install
+
+
+
+
+

(Optional) Non-python Dependencies

+

The driver has several optional features that have non-Python dependencies.

+
+

C Extensions

+

By default, a number of extensions are compiled, providing faster hashing +for token-aware routing with the Murmur3Partitioner, +libev event loop integration, +and Cython optimized extensions.

+

When installing manually through setup.py, you can disable both with +the --no-extensions option, or selectively disable them with +with --no-murmur3, --no-libev, or --no-cython.

+

To compile the extensions, ensure that GCC and the Python headers are available.

+

On Ubuntu and Debian, this can be accomplished by running:

+
$ sudo apt-get install gcc python-dev
+
+
+

On RedHat and RedHat-based systems like CentOS and Fedora:

+
$ sudo yum install gcc python-devel
+
+
+

On OS X, homebrew installations of Python should provide the necessary headers.

+

See Windows Installation Notes for notes on configuring the build environment on Windows.

+
+

Cython-based Extensions

+

By default, this package uses Cython to optimize core modules and build custom extensions. +This is not a hard requirement, but is engaged by default to build extensions offering better performance than the +pure Python implementation.

+

This is a costly build phase, especially in clean environments where the Cython compiler must be built +This build phase can be avoided using the build switch, or an environment variable:

+
python setup.py install --no-cython
+
+
+

Alternatively, an environment variable can be used to switch this option regardless of +context:

+
CASS_DRIVER_NO_CYTHON=1 <your script here>
+- or, to disable all extensions:
+CASS_DRIVER_NO_EXTENSIONS=1 <your script here>
+
+
+

This method is required when using pip, which provides no other way of injecting user options in a single command:

+
CASS_DRIVER_NO_CYTHON=1 pip install scylla-driver
+CASS_DRIVER_NO_CYTHON=1 sudo -E pip install ~/python-driver
+
+
+

The environment variable is the preferred option because it spans all invocations of setup.py, and will +prevent Cython from being materialized as a setup requirement.

+

If your sudo configuration does not allow SETENV, you must push the option flag down via pip. However, pip +applies these options to all dependencies (which break on the custom flag). Therefore, you must first install +dependencies, then use install-option:

+
sudo pip install six futures
+sudo pip install --install-option="--no-cython"
+
+
+
+
+
+

libev support

+

The driver currently uses Python’s asyncore module for its default +event loop. For better performance, libev is also supported through +a C extension.

+

If you’re on Linux, you should be able to install libev +through a package manager. For example, on Debian/Ubuntu:

+
$ sudo apt-get install libev4 libev-dev
+
+
+

On RHEL/CentOS/Fedora:

+
$ sudo yum install libev libev-devel
+
+
+

If you’re on Mac OS X, you should be able to install libev +through Homebrew. For example, on Mac OS X:

+
$ brew install libev
+
+
+

The libev extension is not built for Windows (the build process is complex, and the Windows implementation uses +select anyway).

+

If successful, you should be able to build and install the extension +(just using setup.py build or setup.py install) and then use +the libev event loop by doing the following:

+
>>> from cassandra.io.libevreactor import LibevConnection
+>>> from cassandra.cluster import Cluster
+
+>>> cluster = Cluster()
+>>> cluster.connection_class = LibevConnection
+>>> session = cluster.connect()
+
+
+
+
+
+

(Optional) Configuring SSL

+

Andrew Mussey has published a thorough guide on +Using SSL with the DataStax Python driver.

+
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.21.0-scylla/lwt.html b/3.21.0-scylla/lwt.html new file mode 100644 index 0000000000..2b0bea4483 --- /dev/null +++ b/3.21.0-scylla/lwt.html @@ -0,0 +1,732 @@ + + + + + + + + + + + + + Lightweight Transactions (Compare-and-set) | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

Lightweight Transactions (Compare-and-set)

+

Lightweight Transactions (LWTs) are mostly pass-through CQL for the driver. However, +the server returns some specialized results indicating the outcome and optional state +preceding the transaction.

+

For pertinent execution parameters, see Statement.serial_consistency_level.

+

This section discusses working with specialized result sets returned by the server for LWTs, +and how to work with them using the driver.

+
+

Specialized Results

+

The result returned from a LWT request is always a single row result. It will always have +prepended a special column named [applied]. How this value appears in your results depends +on the row factory in use. See below for examples.

+

The value of this [applied] column is boolean value indicating whether or not the transaction was applied. +If True, it is the only column in the result. If False, the additional columns depend on the LWT operation being +executed:

+
    +
  • When using a UPDATE ... IF "col" = ... clause, the result will contain the [applied] column, plus the existing columns +and values for any columns in the IF clause (and thus the value that caused the transaction to fail).

  • +
  • When using INSERT ... IF NOT EXISTS, the result will contain the [applied] column, plus all columns and values +of the existing row that rejected the transaction.

  • +
  • UPDATE .. IF EXISTS never has additional columns, regardless of [applied] status.

  • +
+

How the [applied] column manifests depends on the row factory in use. Considering the following (initially empty) table:

+
CREATE TABLE test.t (
+    k int PRIMARY KEY,
+    v int,
+    x int
+)
+
+
+

… the following sections show the expected result for a number of example statements, using the three base row factories.

+
+

named_tuple_factory (default)

+

The name [applied] is not a valid Python identifier, so the square brackets are actually removed +from the attribute for the resulting namedtuple. The row always has a boolean column applied in position 0:

+
>>> session.execute("INSERT INTO t (k,v) VALUES (0,0) IF NOT EXISTS")
+Row(applied=True)
+
+>>> session.execute("INSERT INTO t (k,v) VALUES (0,0) IF NOT EXISTS")
+Row(applied=False, k=0, v=0, x=None)
+
+>>> session.execute("UPDATE t SET v = 1, x = 2 WHERE k = 0 IF v =0")
+Row(applied=True)
+
+>>> session.execute("UPDATE t SET v = 1, x = 2 WHERE k = 0 IF v =0 AND x = 1")
+Row(applied=False, v=1, x=2)
+
+
+
+
+

tuple_factory

+

This return type does not refer to names, but the boolean value applied is always present in position 0:

+
>>> session.execute("INSERT INTO t (k,v) VALUES (0,0) IF NOT EXISTS")
+(True,)
+
+>>> session.execute("INSERT INTO t (k,v) VALUES (0,0) IF NOT EXISTS")
+(False, 0, 0, None)
+
+>>> session.execute("UPDATE t SET v = 1, x = 2 WHERE k = 0 IF v =0")
+(True,)
+
+>>> session.execute("UPDATE t SET v = 1, x = 2 WHERE k = 0 IF v =0 AND x = 1")
+(False, 1, 2)
+
+
+
+
+

dict_factory

+

The retuned dict contains the [applied] key:

+
>>> session.execute("INSERT INTO t (k,v) VALUES (0,0) IF NOT EXISTS")
+{u'[applied]': True}
+
+>>> session.execute("INSERT INTO t (k,v) VALUES (0,0) IF NOT EXISTS")
+{u'x': 2, u'[applied]': False, u'v': 1}
+
+>>> session.execute("UPDATE t SET v = 1, x = 2 WHERE k = 0 IF v =0")
+{u'x': None, u'[applied]': False, u'k': 0, u'v': 0}
+
+>>> session.execute("UPDATE t SET v = 1, x = 2 WHERE k = 0 IF v =0 AND x = 1")
+{u'[applied]': True}
+
+
+
+
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.21.0-scylla/object_mapper.html b/3.21.0-scylla/object_mapper.html new file mode 100644 index 0000000000..f0b3325f82 --- /dev/null +++ b/3.21.0-scylla/object_mapper.html @@ -0,0 +1,729 @@ + + + + + + + + + + + + + Object Mapper | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

Object Mapper

+

cqlengine is the Cassandra CQL 3 Object Mapper packaged with this driver

+

Jump to Getting Started

+
+

Contents

+
+
Upgrade Guide

For migrating projects from legacy cqlengine, to the integrated product

+
+
Models

Examples defining models, and mapping them to tables

+
+
Making Queries

Overview of query sets and filtering

+
+
Batch Queries

Working with batch mutations

+
+
Connections

Working with multiple sessions

+
+
API Documentation

Index of API documentation

+
+
Third party integrations

High-level examples in Celery and uWSGI

+
+
+

Frequently Asked Questions

+
+
+
+
+

Getting Started

+
import uuid
+from cassandra.cqlengine import columns
+from cassandra.cqlengine import connection
+from datetime import datetime
+from cassandra.cqlengine.management import sync_table
+from cassandra.cqlengine.models import Model
+
+#first, define a model
+class ExampleModel(Model):
+    example_id      = columns.UUID(primary_key=True, default=uuid.uuid4)
+    example_type    = columns.Integer(index=True)
+    created_at      = columns.DateTime()
+    description     = columns.Text(required=False)
+
+#next, setup the connection to your cassandra server(s)...
+# see http://datastax.github.io/python-driver/api/cassandra/cluster.html for options
+# the list of hosts will be passed to create a Cluster() instance
+connection.setup(['127.0.0.1'], "cqlengine", protocol_version=3)
+
+#...and create your CQL table
+>>> sync_table(ExampleModel)
+
+#now we can create some rows:
+>>> em1 = ExampleModel.create(example_type=0, description="example1", created_at=datetime.now())
+>>> em2 = ExampleModel.create(example_type=0, description="example2", created_at=datetime.now())
+>>> em3 = ExampleModel.create(example_type=0, description="example3", created_at=datetime.now())
+>>> em4 = ExampleModel.create(example_type=0, description="example4", created_at=datetime.now())
+>>> em5 = ExampleModel.create(example_type=1, description="example5", created_at=datetime.now())
+>>> em6 = ExampleModel.create(example_type=1, description="example6", created_at=datetime.now())
+>>> em7 = ExampleModel.create(example_type=1, description="example7", created_at=datetime.now())
+>>> em8 = ExampleModel.create(example_type=1, description="example8", created_at=datetime.now())
+
+#and now we can run some queries against our table
+>>> ExampleModel.objects.count()
+8
+>>> q = ExampleModel.objects(example_type=1)
+>>> q.count()
+4
+>>> for instance in q:
+>>>     print instance.description
+example5
+example6
+example7
+example8
+
+#here we are applying additional filtering to an existing query
+#query objects are immutable, so calling filter returns a new
+#query object
+>>> q2 = q.filter(example_id=em5.example_id)
+
+>>> q2.count()
+1
+>>> for instance in q2:
+>>>     print instance.description
+example5
+
+
+
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.21.0-scylla/objects.inv b/3.21.0-scylla/objects.inv new file mode 100644 index 0000000000..1d50b138f4 Binary files /dev/null and b/3.21.0-scylla/objects.inv differ diff --git a/3.21.0-scylla/performance.html b/3.21.0-scylla/performance.html new file mode 100644 index 0000000000..d5b8fa7d67 --- /dev/null +++ b/3.21.0-scylla/performance.html @@ -0,0 +1,683 @@ + + + + + + + + + + + + + Performance Notes | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

Performance Notes

+

The Python driver for Cassandra offers several methods for executing queries. +You can synchronously block for queries to complete using +Session.execute(), you can obtain asynchronous request futures through +Session.execute_async(), and you can attach a callback to the future +with ResponseFuture.add_callback().

+

Examples of multiple request patterns can be found in the benchmark scripts included in the driver project.

+

The choice of execution pattern will depend on the application context. For applications dealing with multiple +requests in a given context, the recommended pattern is to use concurrent asynchronous +requests with callbacks. For many use cases, you don’t need to implement this pattern yourself. +cassandra.concurrent.execute_concurrent() and cassandra.concurrent.execute_concurrent_with_args() +provide this pattern with a synchronous API and tunable concurrency.

+

Due to the GIL and limited concurrency, the driver can become CPU-bound pretty quickly. The sections below +discuss further runtime and design considerations for mitigating this limitation.

+
+

PyPy

+

PyPy is an alternative Python runtime which uses a JIT compiler to +reduce CPU consumption. This leads to a huge improvement in the driver performance, +more than doubling throughput for many workloads.

+
+
+

Cython Extensions

+

Cython is an optimizing compiler and language that can be used to compile the core files and +optional extensions for the driver. Cython is not a strict dependency, but the extensions will be built by default.

+

See Installation for details on controlling this build.

+
+
+

multiprocessing

+

All of the patterns discussed above may be used over multiple processes using the +multiprocessing +module. Multiple processes will scale better than multiple threads, so if high throughput is your goal, +consider this option.

+

Be sure to never share any Cluster, Session, +or ResponseFuture objects across multiple processes. These +objects should all be created after forking the process, not before.

+

For further discussion and simple examples using the driver with multiprocessing, +see this blog post.

+
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.21.0-scylla/py-modindex.html b/3.21.0-scylla/py-modindex.html new file mode 100644 index 0000000000..eb334ddd51 --- /dev/null +++ b/3.21.0-scylla/py-modindex.html @@ -0,0 +1,616 @@ + + + + + + + + + + + + + Python Module Index | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ + + +
+ + + + + +
+ + +
+
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.21.0-scylla/query_paging.html b/3.21.0-scylla/query_paging.html new file mode 100644 index 0000000000..364d3a9a91 --- /dev/null +++ b/3.21.0-scylla/query_paging.html @@ -0,0 +1,737 @@ + + + + + + + + + + + + + Paging Large Queries | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

Paging Large Queries

+

Cassandra 2.0+ offers support for automatic query paging. Starting with +version 2.0 of the driver, if protocol_version is greater than +2 (it is by default), queries returning large result sets will be +automatically paged.

+
+

Controlling the Page Size

+

By default, Session.default_fetch_size controls how many rows will +be fetched per page. This can be overridden per-query by setting +fetch_size on a Statement. By default, each page +will contain at most 5000 rows.

+
+
+

Handling Paged Results

+

Whenever the number of result rows for are query exceed the page size, an +instance of PagedResult will be returned instead of a normal +list. This class implements the iterator interface, so you can treat +it like a normal iterator over rows:

+
from cassandra.query import SimpleStatement
+query = "SELECT * FROM users"  # users contains 100 rows
+statement = SimpleStatement(query, fetch_size=10)
+for user_row in session.execute(statement):
+    process_user(user_row)
+
+
+

Whenever there are no more rows in the current page, the next page will +be fetched transparently. However, note that it is possible for +an Exception to be raised while fetching the next page, just +like you might see on a normal call to session.execute().

+

If you use Session.execute_async() along with, +ResponseFuture.result(), the first page will be fetched before +result() returns, but latter pages will be +transparently fetched synchronously while iterating the result.

+
+
+

Handling Paged Results with Callbacks

+

If callbacks are attached to a query that returns a paged result, +the callback will be called once per page with a normal list of rows.

+

Use ResponseFuture.has_more_pages and +ResponseFuture.start_fetching_next_page() to continue fetching +pages. For example:

+
class PagedResultHandler(object):
+
+    def __init__(self, future):
+        self.error = None
+        self.finished_event = Event()
+        self.future = future
+        self.future.add_callbacks(
+            callback=self.handle_page,
+            errback=self.handle_err)
+
+    def handle_page(self, rows):
+        for row in rows:
+            process_row(row)
+
+        if self.future.has_more_pages:
+            self.future.start_fetching_next_page()
+        else:
+            self.finished_event.set()
+
+    def handle_error(self, exc):
+        self.error = exc
+        self.finished_event.set()
+
+future = session.execute_async("SELECT * FROM users")
+handler = PagedResultHandler(future)
+handler.finished_event.wait()
+if handler.error:
+    raise handler.error
+
+
+
+
+

Resume Paged Results

+

You can resume the pagination when executing a new query by using the ResultSet.paging_state. This can be useful if you want to provide some stateless pagination capabilities to your application (ie. via http). For example:

+
from cassandra.query import SimpleStatement
+query = "SELECT * FROM users"
+statement = SimpleStatement(query, fetch_size=10)
+results = session.execute(statement)
+
+# save the paging_state somewhere and return current results
+web_session['paging_stage'] = results.paging_state
+
+
+# resume the pagination sometime later...
+statement = SimpleStatement(query, fetch_size=10)
+ps = web_session['paging_state']
+results = session.execute(statement, paging_state=ps)
+
+
+
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.21.0-scylla/search.html b/3.21.0-scylla/search.html new file mode 100644 index 0000000000..a38cbce7ff --- /dev/null +++ b/3.21.0-scylla/search.html @@ -0,0 +1,619 @@ + + + + + + + + + + + + + Search | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + + + + + +
+ + + + + +
+ + +
+
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.21.0-scylla/searchindex.js b/3.21.0-scylla/searchindex.js new file mode 100644 index 0000000000..63cc7aba72 --- /dev/null +++ b/3.21.0-scylla/searchindex.js @@ -0,0 +1 @@ +Search.setIndex({docnames:["CHANGELOG","api/cassandra","api/cassandra/auth","api/cassandra/cluster","api/cassandra/concurrent","api/cassandra/connection","api/cassandra/cqlengine/columns","api/cassandra/cqlengine/connection","api/cassandra/cqlengine/management","api/cassandra/cqlengine/models","api/cassandra/cqlengine/query","api/cassandra/cqlengine/usertype","api/cassandra/datastax/graph/fluent/index","api/cassandra/datastax/graph/fluent/predicates","api/cassandra/datastax/graph/fluent/query","api/cassandra/datastax/graph/index","api/cassandra/decoder","api/cassandra/encoder","api/cassandra/graph","api/cassandra/io/asyncioreactor","api/cassandra/io/asyncorereactor","api/cassandra/io/eventletreactor","api/cassandra/io/geventreactor","api/cassandra/io/libevreactor","api/cassandra/io/twistedreactor","api/cassandra/metadata","api/cassandra/metrics","api/cassandra/policies","api/cassandra/pool","api/cassandra/protocol","api/cassandra/query","api/cassandra/timestamps","api/cassandra/util","api/index","cqlengine/batches","cqlengine/connections","cqlengine/faq","cqlengine/models","cqlengine/queryset","cqlengine/third_party","cqlengine/upgrade_guide","dates_and_times","execution_profiles","faq","getting_started","index","installation","lwt","object_mapper","performance","query_paging","security","upgrading","user_defined_types"],envversion:{"sphinx.domains.c":2,"sphinx.domains.changeset":1,"sphinx.domains.citation":1,"sphinx.domains.cpp":4,"sphinx.domains.index":1,"sphinx.domains.javascript":2,"sphinx.domains.math":2,"sphinx.domains.python":3,"sphinx.domains.rst":2,"sphinx.domains.std":2,"sphinx.ext.todo":2,sphinx:56},filenames:["CHANGELOG.rst","api/cassandra.rst","api/cassandra/auth.rst","api/cassandra/cluster.rst","api/cassandra/concurrent.rst","api/cassandra/connection.rst","api/cassandra/cqlengine/columns.rst","api/cassandra/cqlengine/connection.rst","api/cassandra/cqlengine/management.rst","api/cassandra/cqlengine/models.rst","api/cassandra/cqlengine/query.rst","api/cassandra/cqlengine/usertype.rst","api/cassandra/datastax/graph/fluent/index.rst","api/cassandra/datastax/graph/fluent/predicates.rst","api/cassandra/datastax/graph/fluent/query.rst","api/cassandra/datastax/graph/index.rst","api/cassandra/decoder.rst","api/cassandra/encoder.rst","api/cassandra/graph.rst","api/cassandra/io/asyncioreactor.rst","api/cassandra/io/asyncorereactor.rst","api/cassandra/io/eventletreactor.rst","api/cassandra/io/geventreactor.rst","api/cassandra/io/libevreactor.rst","api/cassandra/io/twistedreactor.rst","api/cassandra/metadata.rst","api/cassandra/metrics.rst","api/cassandra/policies.rst","api/cassandra/pool.rst","api/cassandra/protocol.rst","api/cassandra/query.rst","api/cassandra/timestamps.rst","api/cassandra/util.rst","api/index.rst","cqlengine/batches.rst","cqlengine/connections.rst","cqlengine/faq.rst","cqlengine/models.rst","cqlengine/queryset.rst","cqlengine/third_party.rst","cqlengine/upgrade_guide.rst","dates_and_times.rst","execution_profiles.rst","faq.rst","getting_started.rst","index.rst","installation.rst","lwt.rst","object_mapper.rst","performance.rst","query_paging.rst","security.rst","upgrading.rst","user_defined_types.rst"],objects:{"":[[1,0,0,"-","cassandra"]],"cassandra.AlreadyExists":[[1,2,1,"","keyspace"],[1,2,1,"","table"]],"cassandra.ConsistencyLevel":[[1,2,1,"","ALL"],[1,2,1,"","ANY"],[1,2,1,"","EACH_QUORUM"],[1,2,1,"","LOCAL_ONE"],[1,2,1,"","LOCAL_QUORUM"],[1,2,1,"","LOCAL_SERIAL"],[1,2,1,"","ONE"],[1,2,1,"","QUORUM"],[1,2,1,"","SERIAL"],[1,2,1,"","THREE"],[1,2,1,"","TWO"]],"cassandra.CoordinationFailure":[[1,2,1,"","consistency"],[1,2,1,"","error_code_map"],[1,2,1,"","failures"],[1,2,1,"","received_responses"],[1,2,1,"","required_responses"]],"cassandra.FunctionFailure":[[1,2,1,"","arg_types"],[1,2,1,"","function"],[1,2,1,"","keyspace"]],"cassandra.OperationTimedOut":[[1,2,1,"","errors"],[1,2,1,"","last_host"]],"cassandra.ProtocolVersion":[[1,2,1,"","BETA_VERSIONS"],[1,2,1,"","DSE_V1"],[1,2,1,"","DSE_V2"],[1,2,1,"","MAX_SUPPORTED"],[1,2,1,"","MIN_SUPPORTED"],[1,2,1,"","SUPPORTED_VERSIONS"],[1,2,1,"","V1"],[1,2,1,"","V2"],[1,2,1,"","V3"],[1,2,1,"","V4"],[1,2,1,"","V5"],[1,2,1,"","V6"],[1,4,1,"","get_lower_supported"]],"cassandra.ReadFailure":[[1,2,1,"","data_retrieved"]],"cassandra.ReadTimeout":[[1,2,1,"","data_retrieved"]],"cassandra.Timeout":[[1,2,1,"","consistency"],[1,2,1,"","received_responses"],[1,2,1,"","required_responses"]],"cassandra.Unavailable":[[1,2,1,"","alive_replicas"],[1,2,1,"","consistency"],[1,2,1,"","required_replicas"]],"cassandra.UserAggregateDescriptor":[[1,2,1,"","argument_types"],[1,2,1,"","name"],[1,5,1,"","signature"]],"cassandra.UserFunctionDescriptor":[[1,2,1,"","argument_types"],[1,2,1,"","name"],[1,5,1,"","signature"]],"cassandra.WriteFailure":[[1,2,1,"","write_type"]],"cassandra.WriteTimeout":[[1,2,1,"","write_type"]],"cassandra.auth":[[2,3,1,"","AuthProvider"],[2,3,1,"","Authenticator"],[2,3,1,"","PlainTextAuthProvider"],[2,3,1,"","PlainTextAuthenticator"],[2,3,1,"","SaslAuthProvider"],[2,3,1,"","SaslAuthenticator"]],"cassandra.auth.AuthProvider":[[2,4,1,"","new_authenticator"]],"cassandra.auth.Authenticator":[[2,4,1,"","evaluate_challenge"],[2,4,1,"","initial_response"],[2,4,1,"","on_authentication_success"],[2,2,1,"","server_authenticator_class"]],"cassandra.auth.PlainTextAuthProvider":[[2,4,1,"","new_authenticator"]],"cassandra.auth.PlainTextAuthenticator":[[2,4,1,"","evaluate_challenge"]],"cassandra.auth.SaslAuthProvider":[[2,4,1,"","new_authenticator"]],"cassandra.auth.SaslAuthenticator":[[2,4,1,"","evaluate_challenge"],[2,4,1,"","initial_response"]],"cassandra.cluster":[[3,3,1,"","Cluster"],[3,6,1,"","EXEC_PROFILE_DEFAULT"],[3,6,1,"","EXEC_PROFILE_GRAPH_ANALYTICS_DEFAULT"],[3,6,1,"","EXEC_PROFILE_GRAPH_DEFAULT"],[3,6,1,"","EXEC_PROFILE_GRAPH_SYSTEM_DEFAULT"],[3,3,1,"","ExecutionProfile"],[3,1,1,"","NoHostAvailable"],[3,1,1,"","QueryExhausted"],[3,3,1,"","ResponseFuture"],[3,3,1,"","ResultSet"],[3,3,1,"","Session"],[3,1,1,"","UserTypeDoesNotExist"]],"cassandra.cluster.Cluster":[[3,4,1,"","add_execution_profile"],[3,2,1,"","address_translator"],[3,2,1,"","auth_provider"],[3,2,1,"","cloud"],[3,2,1,"","compression"],[3,4,1,"","connect"],[3,2,1,"","connect_timeout"],[3,2,1,"","connection_class"],[3,2,1,"","contact_points"],[3,2,1,"","control_connection_timeout"],[3,2,1,"","conviction_policy_factory"],[3,2,1,"","cql_version"],[3,2,1,"","default_retry_policy"],[3,2,1,"","endpoint_factory"],[3,4,1,"","get_control_connection_host"],[3,4,1,"","get_core_connections_per_host"],[3,4,1,"","get_max_connections_per_host"],[3,4,1,"","get_max_requests_per_connection"],[3,4,1,"","get_min_requests_per_connection"],[3,2,1,"","idle_heartbeat_interval"],[3,2,1,"","idle_heartbeat_timeout"],[3,2,1,"","load_balancing_policy"],[3,2,1,"","max_schema_agreement_wait"],[3,2,1,"","metadata"],[3,2,1,"","metrics"],[3,2,1,"","metrics_enabled"],[3,2,1,"","port"],[3,2,1,"","prepare_on_all_hosts"],[3,2,1,"","protocol_version"],[3,2,1,"","reconnection_policy"],[3,4,1,"","refresh_keyspace_metadata"],[3,4,1,"","refresh_nodes"],[3,4,1,"","refresh_schema_metadata"],[3,4,1,"","refresh_table_metadata"],[3,4,1,"","refresh_user_aggregate_metadata"],[3,4,1,"","refresh_user_function_metadata"],[3,4,1,"","refresh_user_type_metadata"],[3,4,1,"","register_listener"],[3,4,1,"","register_user_type"],[3,2,1,"","reprepare_on_up"],[3,2,1,"","schema_event_refresh_window"],[3,2,1,"","schema_metadata_enabled"],[3,4,1,"","set_core_connections_per_host"],[3,4,1,"","set_max_connections_per_host"],[3,4,1,"","set_max_requests_per_connection"],[3,4,1,"","set_meta_refresh_enabled"],[3,4,1,"","set_min_requests_per_connection"],[3,4,1,"","shutdown"],[3,2,1,"","sockopts"],[3,2,1,"","ssl_context"],[3,2,1,"","ssl_options"],[3,2,1,"","status_event_refresh_window"],[3,2,1,"","timestamp_generator"],[3,2,1,"","token_metadata_enabled"],[3,2,1,"","topology_event_refresh_window"],[3,4,1,"","unregister_listener"]],"cassandra.cluster.ExecutionProfile":[[3,2,1,"","consistency_level"],[3,4,1,"","row_factory"]],"cassandra.cluster.ResponseFuture":[[3,4,1,"","add_callback"],[3,4,1,"","add_errback"],[3,2,1,"","custom_payload"],[3,4,1,"","get_all_query_traces"],[3,4,1,"","get_query_trace"],[3,2,1,"","has_more_pages"],[3,2,1,"","is_schema_agreed"],[3,2,1,"","query"],[3,4,1,"","result"],[3,4,1,"","start_fetching_next_page"],[3,2,1,"","warnings"]],"cassandra.cluster.ResultSet":[[3,4,1,"","all"],[3,5,1,"","current_rows"],[3,4,1,"","fetch_next_page"],[3,4,1,"","get_all_query_traces"],[3,4,1,"","get_query_trace"],[3,5,1,"","has_more_pages"],[3,4,1,"","one"],[3,5,1,"","paging_state"],[3,5,1,"","was_applied"]],"cassandra.cluster.Session":[[3,4,1,"","add_request_init_listener"],[3,2,1,"","client_protocol_handler"],[3,2,1,"","default_consistency_level"],[3,2,1,"","default_fetch_size"],[3,2,1,"","default_serial_consistency_level"],[3,2,1,"","default_timeout"],[3,2,1,"","encoder"],[3,4,1,"","execute"],[3,4,1,"","execute_async"],[3,4,1,"","execute_graph"],[3,4,1,"","execute_graph_async"],[3,4,1,"","execution_profile_clone_update"],[3,4,1,"","get_execution_profile"],[3,4,1,"","prepare"],[3,4,1,"","remove_request_init_listener"],[3,2,1,"","row_factory"],[3,4,1,"","set_keyspace"],[3,4,1,"","shutdown"],[3,2,1,"","timestamp_generator"],[3,2,1,"","use_client_timestamp"]],"cassandra.concurrent":[[4,7,1,"","execute_concurrent"],[4,7,1,"","execute_concurrent_with_args"]],"cassandra.connection":[[5,1,1,"","ConnectionBusy"],[5,1,1,"","ConnectionException"],[5,1,1,"","ConnectionShutdown"],[5,3,1,"","EndPoint"],[5,3,1,"","EndPointFactory"],[5,1,1,"","ProtocolError"],[5,3,1,"","SniEndPoint"],[5,3,1,"","SniEndPointFactory"],[5,3,1,"","UnixSocketEndPoint"]],"cassandra.connection.EndPoint":[[5,5,1,"","address"],[5,5,1,"","port"],[5,4,1,"","resolve"],[5,5,1,"","socket_family"],[5,5,1,"","ssl_options"]],"cassandra.connection.EndPointFactory":[[5,4,1,"","configure"],[5,4,1,"","create"]],"cassandra.cqlengine":[[6,0,0,"-","columns"],[7,0,0,"-","connection"],[8,0,0,"-","management"],[9,0,0,"-","models"],[10,0,0,"-","query"],[11,0,0,"-","usertype"]],"cassandra.cqlengine.columns":[[6,3,1,"","Ascii"],[6,3,1,"","BigInt"],[6,3,1,"","Blob"],[6,3,1,"","Boolean"],[6,2,1,"","Bytes"],[6,3,1,"","Column"],[6,3,1,"","Counter"],[6,3,1,"","Date"],[6,3,1,"","DateTime"],[6,3,1,"","Decimal"],[6,3,1,"","Double"],[6,3,1,"","Float"],[6,3,1,"","Integer"],[6,3,1,"","List"],[6,3,1,"","Map"],[6,3,1,"","Set"],[6,3,1,"","SmallInt"],[6,3,1,"","Text"],[6,3,1,"","Time"],[6,3,1,"","TimeUUID"],[6,3,1,"","TinyInt"],[6,3,1,"","UUID"],[6,3,1,"","UserDefinedType"],[6,3,1,"","VarInt"]],"cassandra.cqlengine.columns.Column":[[6,2,1,"","clustering_order"],[6,2,1,"","custom_index"],[6,2,1,"","db_field"],[6,2,1,"","default"],[6,2,1,"","discriminator_column"],[6,2,1,"","index"],[6,2,1,"","partition_key"],[6,2,1,"","primary_key"],[6,2,1,"","required"],[6,2,1,"","static"]],"cassandra.cqlengine.columns.DateTime":[[6,2,1,"","truncate_microseconds"]],"cassandra.cqlengine.connection":[[7,7,1,"","default"],[7,7,1,"","register_connection"],[7,7,1,"","set_default_connection"],[7,7,1,"","set_session"],[7,7,1,"","setup"],[7,7,1,"","unregister_connection"]],"cassandra.cqlengine.management":[[8,7,1,"","create_keyspace_network_topology"],[8,7,1,"","create_keyspace_simple"],[8,7,1,"","drop_keyspace"],[8,7,1,"","drop_table"],[8,7,1,"","sync_table"],[8,7,1,"","sync_type"]],"cassandra.cqlengine.models":[[9,3,1,"","Model"]],"cassandra.cqlengine.models.Model":[[9,2,1,"","__abstract__"],[9,2,1,"","__compute_routing_key__"],[9,2,1,"","__connection__"],[9,2,1,"","__default_ttl__"],[9,2,1,"","__discriminator_value__"],[9,2,1,"","__keyspace__"],[9,2,1,"","__options__"],[9,2,1,"","__table_name__"],[9,2,1,"","__table_name_case_sensitive__"],[9,4,1,"","all"],[9,4,1,"","batch"],[9,4,1,"","column_family_name"],[9,4,1,"","create"],[9,4,1,"","delete"],[9,4,1,"","filter"],[9,4,1,"","get"],[9,4,1,"","if_exists"],[9,4,1,"","if_not_exists"],[9,4,1,"","iff"],[9,4,1,"","items"],[9,4,1,"","keys"],[9,4,1,"","len"],[9,4,1,"","save"],[9,4,1,"","timeout"],[9,4,1,"","timestamp"],[9,4,1,"","ttl"],[9,4,1,"","update"],[9,4,1,"","using"],[9,4,1,"","values"]],"cassandra.cqlengine.query":[[10,3,1,"","BatchQuery"],[10,3,1,"","ContextQuery"],[10,3,1,"","DoesNotExist"],[10,3,1,"","LWTException"],[10,3,1,"","ModelQuerySet"],[10,3,1,"","MultipleObjectsReturned"]],"cassandra.cqlengine.query.BatchQuery":[[10,4,1,"","add_callback"],[10,4,1,"","add_query"],[10,4,1,"","execute"]],"cassandra.cqlengine.query.ModelQuerySet":[[10,4,1,"","all"],[10,4,1,"","allow_filtering"],[10,4,1,"","batch"],[10,4,1,"","consistency"],[10,4,1,"","count"],[10,4,1,"","defer"],[10,4,1,"","distinct"],[10,4,1,"","fetch_size"],[10,4,1,"","filter"],[10,4,1,"","get"],[10,4,1,"","if_exists"],[10,4,1,"","if_not_exists"],[10,4,1,"","len"],[10,4,1,"","limit"],[10,4,1,"","only"],[10,4,1,"","order_by"],[10,4,1,"","timestamp"],[10,4,1,"","ttl"],[10,4,1,"","update"],[10,4,1,"","using"]],"cassandra.cqlengine.usertype":[[11,3,1,"","UserType"]],"cassandra.cqlengine.usertype.UserType":[[11,2,1,"","__type_name__"]],"cassandra.datastax":[[15,0,0,"-","graph"]],"cassandra.datastax.graph":[[15,3,1,"","Edge"],[15,3,1,"","GraphOptions"],[15,3,1,"","GraphProtocol"],[15,3,1,"","GraphSON1Deserializer"],[15,3,1,"","GraphSON1Serializer"],[15,3,1,"","GraphSON2Reader"],[15,3,1,"","Path"],[15,3,1,"","Result"],[15,3,1,"","SimpleGraphStatement"],[15,3,1,"","Vertex"],[15,3,1,"","VertexProperty"],[12,0,0,"-","fluent"],[15,7,1,"","graph_object_row_factory"],[15,7,1,"","graph_result_row_factory"],[15,7,1,"","single_object_row_factory"]],"cassandra.datastax.graph.GraphOptions":[[15,2,1,"","graph_language"],[15,2,1,"","graph_name"],[15,2,1,"","graph_read_consistency_level"],[15,2,1,"","graph_source"],[15,2,1,"","graph_write_consistency_level"],[15,2,1,"","is_analytics_source"],[15,2,1,"","is_default_source"],[15,2,1,"","is_graph_source"],[15,4,1,"","set_source_analytics"],[15,4,1,"","set_source_default"],[15,4,1,"","set_source_graph"]],"cassandra.datastax.graph.GraphProtocol":[[15,2,1,"","GRAPHSON_1_0"],[15,2,1,"","GRAPHSON_2_0"],[15,2,1,"","GRAPHSON_3_0"]],"cassandra.datastax.graph.GraphSON1Deserializer":[[15,4,1,"","deserialize_bigint"],[15,4,1,"","deserialize_blob"],[15,4,1,"","deserialize_date"],[15,4,1,"","deserialize_decimal"],[15,4,1,"","deserialize_double"],[15,4,1,"","deserialize_duration"],[15,4,1,"","deserialize_float"],[15,4,1,"","deserialize_int"],[15,4,1,"","deserialize_linestring"],[15,4,1,"","deserialize_point"],[15,4,1,"","deserialize_polygon"],[15,4,1,"","deserialize_time"],[15,4,1,"","deserialize_timestamp"],[15,4,1,"","deserialize_uuid"]],"cassandra.datastax.graph.GraphSON2Reader":[[15,4,1,"","deserialize"],[15,4,1,"","read"]],"cassandra.datastax.graph.Path":[[15,2,1,"","labels"],[15,2,1,"","objects"]],"cassandra.datastax.graph.Result":[[15,4,1,"","as_edge"],[15,4,1,"","as_path"],[15,4,1,"","as_vertex"],[15,2,1,"","value"]],"cassandra.datastax.graph.VertexProperty":[[15,2,1,"","label"],[15,2,1,"","properties"],[15,2,1,"","value"]],"cassandra.datastax.graph.fluent":[[12,3,1,"","BaseGraphRowFactory"],[12,3,1,"","DSESessionRemoteGraphConnection"],[12,3,1,"","DseGraph"],[12,2,1,"","graph_traversal_dse_object_row_factory"],[12,2,1,"","graph_traversal_row_factory"],[13,0,0,"-","predicates"],[14,0,0,"-","query"]],"cassandra.datastax.graph.fluent.DseGraph":[[12,2,1,"","DSE_GRAPH_QUERY_LANGUAGE"],[12,4,1,"","batch"],[12,4,1,"","create_execution_profile"],[12,4,1,"","query_from_traversal"],[12,4,1,"","traversal_source"]],"cassandra.datastax.graph.fluent.predicates":[[13,3,1,"","Geo"],[13,3,1,"","Search"]],"cassandra.datastax.graph.fluent.predicates.Geo":[[13,4,1,"","inside"]],"cassandra.datastax.graph.fluent.predicates.Search":[[13,4,1,"","fuzzy"],[13,4,1,"","phrase"],[13,4,1,"","prefix"],[13,4,1,"","regex"],[13,4,1,"","token"],[13,4,1,"","token_fuzzy"],[13,4,1,"","token_prefix"],[13,4,1,"","token_regex"]],"cassandra.datastax.graph.fluent.query":[[14,3,1,"","TraversalBatch"]],"cassandra.datastax.graph.fluent.query.TraversalBatch":[[14,4,1,"","add"],[14,4,1,"","add_all"],[14,4,1,"","as_graph_statement"],[14,4,1,"","clear"],[14,4,1,"","execute"]],"cassandra.decoder":[[16,7,1,"","dict_factory"],[16,7,1,"","named_tuple_factory"],[16,7,1,"","ordered_dict_factory"],[16,7,1,"","tuple_factory"]],"cassandra.encoder":[[17,3,1,"","Encoder"]],"cassandra.encoder.Encoder":[[17,4,1,"","cql_encode_all_types"],[17,4,1,"","cql_encode_bytes"],[17,4,1,"","cql_encode_date"],[17,4,1,"","cql_encode_datetime"],[17,4,1,"","cql_encode_list_collection"],[17,4,1,"","cql_encode_map_collection"],[17,4,1,"","cql_encode_none"],[17,4,1,"","cql_encode_object"],[17,4,1,"","cql_encode_sequence"],[17,4,1,"","cql_encode_set_collection"],[17,4,1,"","cql_encode_str"],[17,4,1,"","cql_encode_tuple"],[17,4,1,"","cql_encode_unicode"],[17,2,1,"","mapping"]],"cassandra.graph":[[18,3,1,"","Edge"],[18,3,1,"","GraphOptions"],[18,3,1,"","GraphProtocol"],[18,3,1,"","GraphSON1Deserializer"],[18,3,1,"","GraphSON1Serializer"],[18,3,1,"","GraphSON2Reader"],[18,3,1,"","Path"],[18,3,1,"","Result"],[18,3,1,"","SimpleGraphStatement"],[18,3,1,"","Vertex"],[18,3,1,"","VertexProperty"],[18,7,1,"","graph_object_row_factory"],[18,7,1,"","graph_result_row_factory"],[18,7,1,"","single_object_row_factory"]],"cassandra.graph.GraphOptions":[[18,2,1,"","graph_language"],[18,2,1,"","graph_name"],[18,2,1,"","graph_read_consistency_level"],[18,2,1,"","graph_source"],[18,2,1,"","graph_write_consistency_level"],[18,2,1,"","is_analytics_source"],[18,2,1,"","is_default_source"],[18,2,1,"","is_graph_source"],[18,4,1,"","set_source_analytics"],[18,4,1,"","set_source_default"],[18,4,1,"","set_source_graph"]],"cassandra.graph.GraphProtocol":[[18,2,1,"","GRAPHSON_1_0"],[18,2,1,"","GRAPHSON_2_0"],[18,2,1,"","GRAPHSON_3_0"]],"cassandra.graph.GraphSON1Deserializer":[[18,4,1,"","deserialize_bigint"],[18,4,1,"","deserialize_blob"],[18,4,1,"","deserialize_date"],[18,4,1,"","deserialize_decimal"],[18,4,1,"","deserialize_double"],[18,4,1,"","deserialize_duration"],[18,4,1,"","deserialize_float"],[18,4,1,"","deserialize_int"],[18,4,1,"","deserialize_linestring"],[18,4,1,"","deserialize_point"],[18,4,1,"","deserialize_polygon"],[18,4,1,"","deserialize_time"],[18,4,1,"","deserialize_timestamp"],[18,4,1,"","deserialize_uuid"]],"cassandra.graph.GraphSON2Reader":[[18,4,1,"","deserialize"],[18,4,1,"","read"]],"cassandra.graph.Path":[[18,2,1,"","labels"],[18,2,1,"","objects"]],"cassandra.graph.Result":[[18,4,1,"","as_edge"],[18,4,1,"","as_path"],[18,4,1,"","as_vertex"],[18,2,1,"","value"]],"cassandra.graph.VertexProperty":[[18,2,1,"","label"],[18,2,1,"","properties"],[18,2,1,"","value"]],"cassandra.io":[[19,0,0,"-","asyncioreactor"],[20,0,0,"-","asyncorereactor"],[21,0,0,"-","eventletreactor"],[22,0,0,"-","geventreactor"],[23,0,0,"-","libevreactor"],[24,0,0,"-","twistedreactor"]],"cassandra.io.asyncioreactor":[[19,3,1,"","AsyncioConnection"]],"cassandra.io.asyncioreactor.AsyncioConnection":[[19,4,1,"","initialize_reactor"]],"cassandra.io.asyncorereactor":[[20,3,1,"","AsyncoreConnection"]],"cassandra.io.asyncorereactor.AsyncoreConnection":[[20,4,1,"","handle_fork"],[20,4,1,"","initialize_reactor"]],"cassandra.io.eventletreactor":[[21,3,1,"","EventletConnection"]],"cassandra.io.eventletreactor.EventletConnection":[[21,4,1,"","initialize_reactor"],[21,4,1,"","service_timeouts"]],"cassandra.io.geventreactor":[[22,3,1,"","GeventConnection"]],"cassandra.io.geventreactor.GeventConnection":[[22,4,1,"","initialize_reactor"]],"cassandra.io.libevreactor":[[23,3,1,"","LibevConnection"]],"cassandra.io.twistedreactor":[[24,3,1,"","TwistedConnection"]],"cassandra.metadata":[[25,3,1,"","Aggregate"],[25,3,1,"","BytesToken"],[25,3,1,"","ColumnMetadata"],[25,3,1,"","Function"],[25,3,1,"","IndexMetadata"],[25,3,1,"","KeyspaceMetadata"],[25,3,1,"","LocalStrategy"],[25,3,1,"","MD5Token"],[25,3,1,"","MaterializedViewMetadata"],[25,3,1,"","Metadata"],[25,3,1,"","Murmur3Token"],[25,3,1,"","NetworkTopologyStrategy"],[25,2,1,"","ReplicationStrategy"],[25,3,1,"","SimpleStrategy"],[25,3,1,"","TableMetadata"],[25,3,1,"","Token"],[25,3,1,"","TokenMap"],[25,3,1,"","UserType"],[25,6,1,"","cql_keywords"],[25,6,1,"","cql_keywords_reserved"],[25,6,1,"","cql_keywords_unreserved"],[25,7,1,"","group_keys_by_replica"]],"cassandra.metadata.Aggregate":[[25,4,1,"","as_cql_query"]],"cassandra.metadata.BytesToken":[[25,4,1,"","from_string"]],"cassandra.metadata.Function":[[25,4,1,"","as_cql_query"]],"cassandra.metadata.IndexMetadata":[[25,4,1,"","as_cql_query"],[25,4,1,"","export_as_string"]],"cassandra.metadata.KeyspaceMetadata":[[25,4,1,"","as_cql_query"],[25,4,1,"","export_as_string"]],"cassandra.metadata.LocalStrategy":[[25,4,1,"","export_for_schema"]],"cassandra.metadata.MaterializedViewMetadata":[[25,4,1,"","as_cql_query"]],"cassandra.metadata.Metadata":[[25,4,1,"","add_or_return_host"],[25,4,1,"","all_hosts"],[25,4,1,"","export_schema_as_string"],[25,4,1,"","get_host"],[25,4,1,"","get_host_by_host_id"],[25,4,1,"","get_replicas"]],"cassandra.metadata.NetworkTopologyStrategy":[[25,4,1,"","export_for_schema"]],"cassandra.metadata.SimpleStrategy":[[25,4,1,"","export_for_schema"],[25,5,1,"","replication_factor"]],"cassandra.metadata.TableMetadata":[[25,4,1,"","as_cql_query"],[25,4,1,"","export_as_string"],[25,5,1,"","is_cql_compatible"],[25,5,1,"","primary_key"]],"cassandra.metadata.TokenMap":[[25,4,1,"","get_replicas"]],"cassandra.metadata.UserType":[[25,4,1,"","as_cql_query"]],"cassandra.metrics":[[26,3,1,"","Metrics"]],"cassandra.metrics.Metrics":[[26,2,1,"","connected_to"],[26,2,1,"","connection_errors"],[26,4,1,"","get_stats"],[26,2,1,"","ignores"],[26,2,1,"","known_hosts"],[26,2,1,"","open_connections"],[26,2,1,"","other_errors"],[26,2,1,"","read_timeouts"],[26,2,1,"","request_timer"],[26,2,1,"","retries"],[26,4,1,"","set_stats_name"],[26,2,1,"","unavailables"],[26,2,1,"","write_timeouts"]],"cassandra.policies":[[27,3,1,"","AddressTranslator"],[27,3,1,"","ConstantReconnectionPolicy"],[27,3,1,"","ConstantSpeculativeExecutionPolicy"],[27,3,1,"","ConvictionPolicy"],[27,3,1,"","DCAwareRoundRobinPolicy"],[27,3,1,"","DSELoadBalancingPolicy"],[27,3,1,"","DefaultLoadBalancingPolicy"],[27,3,1,"","DowngradingConsistencyRetryPolicy"],[27,3,1,"","EC2MultiRegionTranslator"],[27,3,1,"","ExponentialReconnectionPolicy"],[27,3,1,"","FallthroughRetryPolicy"],[27,3,1,"","HostDistance"],[27,3,1,"","HostFilterPolicy"],[27,3,1,"","IdentityTranslator"],[27,3,1,"","LoadBalancingPolicy"],[27,3,1,"","ReconnectionPolicy"],[27,3,1,"","RetryPolicy"],[27,3,1,"","RoundRobinPolicy"],[27,3,1,"","SimpleConvictionPolicy"],[27,3,1,"","SpeculativeExecutionPolicy"],[27,3,1,"","TokenAwarePolicy"],[27,3,1,"","WhiteListRoundRobinPolicy"],[27,3,1,"","WriteType"]],"cassandra.policies.AddressTranslator":[[27,4,1,"","translate"]],"cassandra.policies.ConstantReconnectionPolicy":[[27,4,1,"","new_schedule"]],"cassandra.policies.ConstantSpeculativeExecutionPolicy":[[27,4,1,"","new_plan"]],"cassandra.policies.ConvictionPolicy":[[27,4,1,"","add_failure"],[27,4,1,"","reset"]],"cassandra.policies.DCAwareRoundRobinPolicy":[[27,4,1,"","distance"],[27,4,1,"","make_query_plan"],[27,4,1,"","on_add"],[27,4,1,"","on_down"],[27,4,1,"","on_remove"],[27,4,1,"","on_up"],[27,4,1,"","populate"]],"cassandra.policies.DefaultLoadBalancingPolicy":[[27,4,1,"","make_query_plan"],[27,4,1,"","populate"]],"cassandra.policies.DowngradingConsistencyRetryPolicy":[[27,4,1,"","on_read_timeout"],[27,4,1,"","on_unavailable"],[27,4,1,"","on_write_timeout"]],"cassandra.policies.EC2MultiRegionTranslator":[[27,4,1,"","translate"]],"cassandra.policies.ExponentialReconnectionPolicy":[[27,4,1,"","new_schedule"]],"cassandra.policies.FallthroughRetryPolicy":[[27,4,1,"","on_read_timeout"],[27,4,1,"","on_request_error"],[27,4,1,"","on_unavailable"],[27,4,1,"","on_write_timeout"]],"cassandra.policies.HostDistance":[[27,2,1,"","IGNORED"],[27,2,1,"","LOCAL"],[27,2,1,"","REMOTE"]],"cassandra.policies.HostFilterPolicy":[[27,4,1,"","distance"],[27,4,1,"","make_query_plan"],[27,4,1,"","predicate"]],"cassandra.policies.IdentityTranslator":[[27,4,1,"","translate"]],"cassandra.policies.LoadBalancingPolicy":[[27,4,1,"","check_supported"],[27,4,1,"","distance"],[27,4,1,"","make_query_plan"],[27,4,1,"","populate"]],"cassandra.policies.ReconnectionPolicy":[[27,4,1,"","new_schedule"]],"cassandra.policies.RetryPolicy":[[27,2,1,"","IGNORE"],[27,2,1,"","RETHROW"],[27,2,1,"","RETRY"],[27,2,1,"","RETRY_NEXT_HOST"],[27,4,1,"","on_read_timeout"],[27,4,1,"","on_request_error"],[27,4,1,"","on_unavailable"],[27,4,1,"","on_write_timeout"]],"cassandra.policies.RoundRobinPolicy":[[27,4,1,"","distance"],[27,4,1,"","make_query_plan"],[27,4,1,"","on_add"],[27,4,1,"","on_down"],[27,4,1,"","on_remove"],[27,4,1,"","on_up"],[27,4,1,"","populate"]],"cassandra.policies.SimpleConvictionPolicy":[[27,4,1,"","add_failure"],[27,4,1,"","reset"]],"cassandra.policies.SpeculativeExecutionPolicy":[[27,4,1,"","new_plan"]],"cassandra.policies.TokenAwarePolicy":[[27,4,1,"","check_supported"],[27,4,1,"","distance"],[27,4,1,"","make_query_plan"],[27,4,1,"","on_add"],[27,4,1,"","on_down"],[27,4,1,"","on_remove"],[27,4,1,"","on_up"],[27,4,1,"","populate"],[27,2,1,"","shuffle_replicas"]],"cassandra.policies.WhiteListRoundRobinPolicy":[[27,4,1,"","distance"],[27,4,1,"","on_add"],[27,4,1,"","on_up"],[27,4,1,"","populate"]],"cassandra.policies.WriteType":[[27,2,1,"","BATCH"],[27,2,1,"","BATCH_LOG"],[27,2,1,"","CAS"],[27,2,1,"","CDC"],[27,2,1,"","COUNTER"],[27,2,1,"","SIMPLE"],[27,2,1,"","UNLOGGED_BATCH"],[27,2,1,"","VIEW"]],"cassandra.pool":[[28,3,1,"","Host"],[28,1,1,"","NoConnectionsAvailable"]],"cassandra.pool.Host":[[28,5,1,"","address"],[28,5,1,"","datacenter"],[28,5,1,"","rack"]],"cassandra.protocol":[[29,3,1,"","_ProtocolHandler"]],"cassandra.protocol._ProtocolHandler":[[29,4,1,"","decode_message"],[29,4,1,"","encode_message"],[29,2,1,"","message_types_by_opcode"]],"cassandra.query":[[30,3,1,"","BatchStatement"],[30,3,1,"","BatchType"],[30,3,1,"","BoundStatement"],[30,3,1,"","PreparedStatement"],[30,3,1,"","QueryTrace"],[30,3,1,"","SimpleStatement"],[30,3,1,"","Statement"],[30,3,1,"","TraceEvent"],[30,1,1,"","TraceUnavailable"],[30,6,1,"","UNSET_VALUE"],[30,3,1,"","ValueSequence"],[30,7,1,"","dict_factory"],[30,7,1,"","named_tuple_factory"],[30,7,1,"","ordered_dict_factory"],[30,7,1,"","tuple_factory"]],"cassandra.query.BatchStatement":[[30,4,1,"","add"],[30,4,1,"","add_all"],[30,4,1,"","clear"],[30,2,1,"","serial_consistency_level"]],"cassandra.query.BatchType":[[30,2,1,"","COUNTER"],[30,2,1,"","LOGGED"],[30,2,1,"","UNLOGGED"]],"cassandra.query.BoundStatement":[[30,4,1,"","bind"],[30,5,1,"","routing_key"]],"cassandra.query.PreparedStatement":[[30,4,1,"","bind"]],"cassandra.query.QueryTrace":[[30,4,1,"","populate"]],"cassandra.query.Statement":[[30,5,1,"","routing_key"],[30,5,1,"","serial_consistency_level"]],"cassandra.timestamps":[[31,3,1,"","MonotonicTimestampGenerator"]],"cassandra.timestamps.MonotonicTimestampGenerator":[[31,4,1,"","_next_timestamp"],[31,2,1,"","warn_on_drift"],[31,2,1,"","warning_interval"],[31,2,1,"","warning_threshold"]],"cassandra.util":[[32,3,1,"","Date"],[32,3,1,"","DateRange"],[32,3,1,"","DateRangeBound"],[32,3,1,"","DateRangePrecision"],[32,3,1,"","Distance"],[32,3,1,"","Duration"],[32,3,1,"","LineString"],[32,3,1,"","OrderedMap"],[32,3,1,"","OrderedMapSerializedKey"],[32,3,1,"","Point"],[32,3,1,"","Polygon"],[32,3,1,"","SortedSet"],[32,3,1,"","Time"],[32,3,1,"","Version"],[32,7,1,"","datetime_from_timestamp"],[32,7,1,"","datetime_from_uuid1"],[32,7,1,"","max_uuid_from_time"],[32,7,1,"","min_uuid_from_time"],[32,7,1,"","ms_timestamp_from_datetime"],[32,2,1,"","sortedset"],[32,7,1,"","unix_time_from_uuid1"],[32,7,1,"","utc_datetime_from_ms_timestamp"],[32,7,1,"","uuid_from_time"]],"cassandra.util.Date":[[32,4,1,"","date"],[32,5,1,"","seconds"]],"cassandra.util.DateRange":[[32,2,1,"","lower_bound"],[32,2,1,"","upper_bound"],[32,2,1,"","value"]],"cassandra.util.DateRangeBound":[[32,4,1,"","datetime"],[32,4,1,"","from_value"],[32,2,1,"","milliseconds"],[32,2,1,"","precision"]],"cassandra.util.Distance":[[32,4,1,"","from_wkt"]],"cassandra.util.LineString":[[32,4,1,"","from_wkt"]],"cassandra.util.Point":[[32,4,1,"","from_wkt"]],"cassandra.util.Polygon":[[32,4,1,"","from_wkt"]],"cassandra.util.Time":[[32,5,1,"","hour"],[32,5,1,"","minute"],[32,5,1,"","nanosecond"],[32,5,1,"","second"],[32,4,1,"","time"]],"cqlengine.queryset":[[38,3,1,"","MaxTimeUUID"],[38,3,1,"","MinTimeUUID"]],cassandra:[[1,1,1,"","AlreadyExists"],[1,1,1,"","AuthenticationFailed"],[1,1,1,"","ConfigurationException"],[1,3,1,"","ConsistencyLevel"],[1,1,1,"","CoordinationFailure"],[1,1,1,"","DriverException"],[1,1,1,"","FunctionFailure"],[1,1,1,"","InvalidRequest"],[1,1,1,"","OperationTimedOut"],[1,3,1,"","ProtocolVersion"],[1,1,1,"","ReadFailure"],[1,1,1,"","ReadTimeout"],[1,1,1,"","RequestExecutionException"],[1,1,1,"","RequestValidationException"],[1,1,1,"","Timeout"],[1,1,1,"","Unauthorized"],[1,1,1,"","Unavailable"],[1,3,1,"","UserAggregateDescriptor"],[1,3,1,"","UserFunctionDescriptor"],[1,1,1,"","WriteFailure"],[1,1,1,"","WriteTimeout"],[1,6,1,"","__version__"],[1,6,1,"","__version_info__"],[2,0,0,"-","auth"],[3,0,0,"-","cluster"],[4,0,0,"-","concurrent"],[5,0,0,"-","connection"],[16,0,0,"-","decoder"],[17,0,0,"-","encoder"],[18,0,0,"-","graph"],[25,0,0,"-","metadata"],[26,0,0,"-","metrics"],[27,0,0,"-","policies"],[28,0,0,"-","pool"],[29,0,0,"-","protocol"],[30,0,0,"-","query"],[31,0,0,"-","timestamps"],[32,0,0,"-","util"]],cqlengine:[[37,0,0,"-","models"],[38,0,0,"-","queryset"]]},objnames:{"0":["py","module","Python module"],"1":["py","exception","Python exception"],"2":["py","attribute","Python attribute"],"3":["py","class","Python class"],"4":["py","method","Python method"],"5":["py","property","Python property"],"6":["py","data","Python data"],"7":["py","function","Python function"]},objtypes:{"0":"py:module","1":"py:exception","2":"py:attribute","3":"py:class","4":"py:method","5":"py:property","6":"py:data","7":"py:function"},terms:{"0":[1,2,3,4,6,9,10,12,14,15,16,18,25,27,30,31,32,34,35,37,38,42,43,44,46,47,48,50,53],"00":43,"000":10,"000077":43,"000153":43,"000309":43,"000368":43,"000422":43,"000480":43,"000669":43,"000755":43,"031ebb0":52,"05":38,"0l":38,"0m":0,"1":[1,2,3,4,6,10,13,15,18,19,25,27,30,31,32,34,35,36,38,42,43,44,45,46,47,48,51,53],"10":[1,3,10,38,44,46,50],"100":[0,4,10,42,50],"1000":4,"1006":0,"1007":0,"1008":0,"1009":0,"101":0,"1012":0,"1013":0,"1015":0,"1016":0,"1017":0,"1018":0,"1020":0,"1021":0,"1023":0,"1024":0,"1026":0,"103":0,"1031":0,"1033":0,"1036":0,"104":0,"1042":0,"1044":0,"1047":0,"1048":0,"105":0,"1054":0,"106":0,"1064":0,"1065":0,"1067":0,"1068":0,"1074":0,"10786":30,"1079":0,"108":0,"1081":0,"1082":0,"1087":0,"1089":0,"109":0,"1091":0,"1093":0,"10l":38,"110":0,"1100":0,"1104":0,"1105":0,"111":[0,36],"111111111111":9,"1117":0,"1118":0,"1119":0,"112":0,"1121":0,"1122":0,"1123":0,"1124":0,"1127":0,"1129":0,"1130":0,"1140":0,"1158":0,"116":0,"1161":0,"1162":0,"1163":0,"1166":0,"1172":0,"1174":0,"1177":0,"1181":0,"1183":0,"1185":0,"1186":0,"1187":0,"1189":0,"119":[0,32],"1192":0,"11e3":44,"11l":38,"120":0,"1203":0,"122":0,"123":[0,3,36,53],"1234":51,"124":0,"125":0,"126":0,"127":[3,25,35,38,42,43,44,48,51],"12l":38,"135":0,"138":0,"13l":38,"14":32,"141":0,"143":0,"144":0,"145":27,"147":0,"148":0,"14l":38,"15":[27,44],"150":0,"151":0,"155":0,"157":0,"159":0,"15l":38,"16":6,"160":0,"163":0,"164":0,"165":0,"166":0,"167":0,"168":[3,44],"16l":38,"17":[38,51],"173":0,"174":0,"175":0,"178":[0,30,52],"179":0,"17l":38,"180":0,"181":0,"182":0,"184":0,"185":0,"186":0,"187":0,"189":0,"18l":38,"190":0,"191":0,"192":[0,3,44],"194":0,"195":0,"196":0,"197":0,"1970":32,"198":0,"1982":38,"19l":38,"1e6":31,"1l":38,"1s":0,"2":[1,2,3,4,6,9,10,12,13,14,15,16,18,25,27,30,32,34,35,36,38,40,42,43,44,45,46,47,50,51,53],"20":38,"200":0,"2008":10,"2010":[35,38],"2011":38,"2012":38,"2013":0,"2014":[0,38],"2015":0,"2016":0,"2017":0,"2018":0,"2019":0,"202":0,"2020":0,"204":0,"2048":51,"205":0,"206":0,"207":0,"208":0,"21":[38,46,52],"210":0,"211":0,"212":0,"213":0,"215":0,"218":0,"219":0,"220":0,"222":0,"226":0,"229":0,"23":[0,32],"230":0,"231":0,"234":0,"235":0,"238":0,"239":0,"24":0,"240":0,"241":0,"243":0,"244":0,"245":[0,40],"246":0,"249":0,"25":0,"255":0,"258":0,"26":[0,38],"260":0,"2644bada":44,"266":0,"27":0,"272":0,"273":0,"276":[0,52],"277":0,"278":0,"279":43,"28":0,"280":0,"282":0,"283":0,"284":0,"285":0,"286":0,"288":0,"289":0,"29":0,"291":0,"292":[0,52],"294":0,"295":0,"296":0,"297":0,"298":0,"299":0,"2l":38,"3":[1,2,3,4,6,9,10,15,18,19,27,30,31,32,34,36,37,38,45,46,48,53],"30":[0,3,38,42,44],"300":0,"301":0,"302":0,"303":0,"305":0,"306":0,"309":0,"31":[0,38],"310":0,"311":0,"313":0,"315":0,"317":0,"318":[0,52],"319":0,"32":6,"322":0,"323":0,"324":0,"325":0,"327":0,"329":0,"331":0,"332":0,"333":0,"334":0,"335":0,"336":0,"337":0,"338":0,"340":32,"341":0,"342":0,"343":0,"344":0,"345":0,"346":0,"347":0,"348":0,"349":0,"351":0,"352":0,"353":0,"354":0,"357":0,"358":0,"360":0,"361":0,"362":0,"363":0,"365":0,"368":[0,52],"370":0,"371":0,"375":0,"377":0,"378":0,"379":0,"381":0,"385":[0,52],"386":0,"392":0,"393":0,"394":0,"395":0,"396":0,"397":0,"398":0,"3l":38,"4":[1,2,3,6,9,10,19,27,29,30,32,42,45,46,48],"400":[0,52],"405":0,"407":0,"408":[0,52],"409":0,"412":0,"413":0,"415":0,"416":0,"419fcdf":52,"42":[3,30,44],"422":[0,52],"429":0,"430":0,"432":0,"433":0,"434":0,"435":0,"438":0,"439":0,"442":0,"443":0,"444":0,"445":0,"447":0,"450":0,"451":0,"452":0,"454":0,"458":0,"459":0,"46":0,"464":0,"466":0,"467":0,"468":0,"469":0,"470":0,"471":0,"473":0,"475":0,"476":0,"477":0,"478":0,"479":0,"48":32,"480":0,"481":0,"482":0,"486":0,"487":0,"489":0,"495":0,"498":0,"4bd5909":52,"4l":38,"4th":0,"5":[1,3,9,10,19,27,38,44,45,46,51],"50":4,"500":10,"5000":[3,10,50],"501":0,"502":0,"503":0,"505":0,"507":0,"508":0,"509":0,"50m":38,"510":0,"512":0,"514":0,"520":0,"521":0,"522":0,"527":0,"528":0,"530":0,"531":0,"532":0,"533":0,"535":0,"537":0,"538":0,"542":0,"547":0,"548":0,"549":0,"550":0,"551":0,"553":0,"555":0,"556":0,"557":0,"559":0,"56":0,"560":0,"561":0,"562":0,"565":0,"566":0,"568":0,"569":0,"570":0,"572":0,"5723":0,"573":0,"574":0,"574266d":52,"576":0,"577":0,"578":0,"579":0,"580":0,"583":0,"584":0,"585":0,"589":0,"59":[0,32],"591":0,"593":0,"595":0,"596":0,"598":0,"599":0,"5l":38,"6":[1,3,6,10,19,25,27,30,38,45,46],"60":0,"600":0,"606":0,"607":0,"608":0,"609":0,"613":0,"614":0,"616":0,"617":0,"618":0,"619":0,"621":0,"622":0,"623":0,"626":0,"628":0,"630":0,"631":0,"636":0,"64":[6,9,27],"640":0,"642":0,"643":0,"644":0,"645":0,"646":0,"647":0,"648":0,"649":0,"65":1,"650":0,"653":0,"655":0,"656":0,"657":0,"66":[1,3],"665":0,"668":0,"669":0,"673":0,"676":0,"678":0,"682":0,"684":0,"686":0,"688":0,"69":0,"690":0,"692":0,"694":0,"697":0,"6l":38,"7":[1,6,10,27,45,46],"70":0,"705":0,"706":0,"707":0,"708":0,"709":0,"71":0,"710":0,"714":0,"717":0,"719":0,"720":0,"721":0,"723":0,"724":0,"727":0,"728":0,"729":0,"73":0,"730":0,"732":0,"733":0,"734":0,"735":0,"736":0,"737":0,"739":0,"740":0,"741":0,"742":0,"743":0,"746":0,"747":0,"749":0,"75":0,"750":0,"751":0,"752":0,"754":0,"755":0,"759":0,"75percentil":26,"75th":26,"76":0,"761":0,"762":0,"763":0,"767":0,"768":0,"769":0,"77142":43,"772":0,"773":0,"774":0,"774000":38,"775":0,"778":0,"781":0,"782":0,"785":0,"7857":0,"78723":[3,53],"789":0,"79":0,"793":0,"794":0,"798":0,"799":0,"79efe97":52,"7l":38,"8":[1,3,6,17,31,45,46,48],"80":0,"804dea3":0,"805":0,"808":0,"81":0,"810":0,"812":0,"813":0,"814":0,"819":0,"82":0,"827":0,"829":0,"831":0,"833":0,"836":0,"837":0,"838":0,"839":0,"84":0,"840":0,"843":0,"846":0,"848":0,"852c":44,"853":0,"86":0,"860":0,"861":0,"862":0,"863":0,"86400":9,"865":0,"868":0,"872":0,"8733":40,"877":0,"88":0,"885":0,"888":0,"89":0,"891":0,"892":0,"893":0,"894":0,"895":0,"897":0,"89fb":44,"8l":38,"9":[1,9,38],"90":0,"900":0,"901":0,"903":0,"9042":[3,5],"91":0,"910":0,"915":0,"916":0,"92":0,"9223372036854775808":43,"93":0,"932":0,"934":0,"937":0,"940":0,"941":0,"944":0,"945":0,"946":0,"947":0,"95":0,"953":0,"955":0,"95percentil":26,"95th":26,"96":0,"963":0,"96489cc":52,"966":0,"968":0,"97":0,"973":0,"978":0,"98":0,"98percentil":26,"98th":26,"99":[0,26],"992":0,"993":0,"995":0,"998":0,"99999":37,"999percentil":26,"99percentil":26,"99th":26,"9d98c8e":52,"9l":38,"9th":26,"abstract":[0,2,6,9,25,30],"boolean":[0,1,6,25,27,44,47],"break":[0,27,46,52],"byte":[0,6,38],"case":[0,3,4,8,9,27,32,34,35,44,49,51],"catch":0,"class":[0,1,2,3,5,6,9,10,12,13,14,15,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,40,41,48,50,51,52],"default":[0,1,3,6,7,9,10,11,12,14,15,17,18,26,27,29,30,31,34,43,44,46,48,49,50,51],"do":[0,3,4,6,9,17,27,30,37,38,41,44,45,46,51,52,53],"enum":[10,13,27,32,33],"export":[0,25],"final":[3,44,51],"float":[0,3,6,10,26,27,37,38,44,52],"function":[0,1,3,8,10,12,17,25,27,29,32,41,44,51,52],"import":[0,2,3,4,6,10,11,12,29,30,34,35,37,38,39,41,42,43,44,46,48,50,51],"int":[0,3,6,7,8,25,31,32,38,44,47,52,53],"long":[0,32,44,46,53],"new":[0,1,2,3,4,6,7,10,21,25,27,30,31,32,34,36,38,39,40,42,44,48,50,51,52,53],"null":[0,10,17,36,38,44],"public":27,"return":[0,1,2,3,4,9,10,12,14,15,18,25,26,27,29,30,31,32,33,37,38,39,41,43,44,47,48,50,51,53],"short":[0,30,37],"static":[0,3,6,10,12,13,32],"super":37,"switch":[0,10,46],"throw":[0,3,30],"true":[0,3,4,6,7,8,9,10,15,18,25,27,30,31,34,35,36,37,38,40,43,44,47,48,51],"try":[0,1,3,8,9,27,37,39,41,44],"while":[0,3,27,30,37,40,50,52],A:[0,1,2,3,4,7,8,10,12,13,14,17,25,26,27,30,32,35,37,38,44,45,46],AND:47,And:[9,51,52],As:[9,32,40,44,53],BY:37,Be:49,But:30,By:[1,3,9,10,27,29,34,38,43,44,46,50,51,52],For:[0,1,3,6,7,9,10,25,27,30,32,36,37,38,40,41,42,44,46,47,48,49,50,51,52],IF:[0,10,27,30,47,52],IN:[17,25,30],INTO:[3,4,30,44,47,53],IS:[0,38,40],If:[0,2,3,4,7,8,9,10,11,14,25,27,30,31,32,34,35,36,37,41,42,44,45,46,47,50,51,52],In:[0,3,27,29,34,38,40,44,46,51,52],It:[0,3,9,21,22,27,32,35,37,38,43,44,46,47,51],NOT:[0,38,47],Not:[0,32],ONE:[1,3,10,40,52],Of:3,On:[0,27,46],One:[10,41],Or:3,Such:27,THERE:40,That:38,The:[0,1,2,3,4,5,6,7,9,10,12,13,14,15,17,18,25,26,27,28,29,30,32,34,36,37,38,40,41,42,44,45,46,47,49,51,52,53],Then:51,There:[1,3,6,8,30,38,44,46,52],These:[0,3,6,9,27,29,30,32,40,41,49,51,52],To:[3,9,11,27,34,35,37,38,40,41,42,43,44,46,51,52],WITH:37,Will:9,With:[0,35,43,51,52],_1:51,_2:51,_3:51,_4:51,_:42,__:[10,38,52],__abstract__:9,__compute_routing_key__:9,__connection__:[8,9,35],__contain:38,__default_ttl__:9,__del__:0,__discrimin:52,__discriminator_value__:[6,9,37,40],__ge__:0,__gt:38,__gte:38,__in:[0,38],__init__:[0,3,27,31,50,52,53],__keyspace__:[8,9,35,37],__le__:0,__len__:0,__like:38,__lt:38,__lte:38,__name__:43,__ne__:0,__options__:[9,38],__polymorphic_:52,__polymorphic_key__:40,__repr__:0,__table_name__:[9,37,40],__table_name_case_sensitive__:9,__type_name__:11,__version__:[1,46],__version_info__:1,_connect:0,_dsegraphson2rowfactori:12,_gremlingraphson2rowfactori:12,_messagetyp:29,_metadata:52,_new_tim:21,_next_timestamp:31,_protocolhand:29,_protocolhandl:29,_replicationstrategi:25,_set_final_except:0,_set_result:0,_timeout_watch:21,a2:10,a2d3a98:52,abil:[0,27,42,52],abl:46,about:[0,3,25,30,37,41,44,46,51,52],abov:[3,29,34,35,41,44,49],absolut:[32,40],accept:[0,3,27,32,40,41],access:[0,3,9,26,30,37,44,52],accommod:[0,41],accomplish:[38,46],accord:[0,3],accordingli:0,account:[0,37],accumul:10,accur:25,acheiv:27,achiev:[27,34,51],acknowledg:27,across:[0,19,20,21,22,27,42,43,49],act:51,activ:[0,3,21,22],actual:[0,1,27,30,38,44,47],ad:[0,1,3,10,21,25,27,30,34,37,38,46,52],add:[0,3,7,8,10,14,27,30,34,52,53],add_al:[14,30],add_callback:[3,10,34,44,49,50],add_collback:0,add_errback:[3,44],add_execution_profil:[3,12,42],add_failur:27,add_or_return_host:25,add_queri:10,add_request_init_listen:3,add_tim:0,addit:[0,3,10,12,29,34,37,38,44,47,48,51,52],addition:[30,37,40,51],additional_write_polici:0,addr:[27,37],address:[0,1,3,5,11,25,28,30,33,37,43,44,51,52,53],address_is_ignor:27,address_transl:3,addresstransl:[0,27],adher:41,adjust:[0,40],advanc:51,advic:3,affect:[3,30,34],after:[0,3,4,10,20,27,30,34,37,38,40,43,44,46,49],afterward:52,ag:[3,30,38,44],against:[0,1,3,9,27,30,37,44,48,51],aggreg:[0,1,3,25],agnost:32,agre:0,agreement:[0,3],ahead:[3,44],aim:[35,42],algorithm:[36,46],alia:[6,12,25,32,40],alias:0,alic:30,align:0,aliv:[1,26,27],alive_replica:[1,27],all:[0,1,3,4,6,8,9,10,17,21,22,25,26,27,28,29,30,35,41,44,46,47,49,51,52],all_host:[25,42],all_object:38,allow:[0,3,6,9,10,12,13,27,29,30,31,32,34,36,37,46,51,52,53],allow_beta_protocol_vers:29,allow_filt:[10,38],almost:44,along:[3,25,50],alpha:0,alphanumer:0,alreadi:[0,1,3,5,8,35,46],alreadyexist:1,also:[0,3,4,9,10,13,27,30,32,35,37,38,42,43,44,46,51,52],alter:[9,27,37],altern:[3,29,37,40,44,45,46,49,51],although:[44,52,53],althought:44,alwai:[0,3,15,18,27,41,44,46,47],ambigu:0,among:[1,27],amount:[0,4,27],an:[0,1,2,3,4,5,6,8,9,10,12,13,15,17,18,19,20,21,22,23,24,25,26,27,29,30,31,32,34,35,36,37,38,40,41,42,44,45,46,48,49,50,51,52,53],analysi:29,analyt:[0,15,18],analyticskeyspac:3,analyticskeyspace_prepar:3,andrew:[46,51],ani:[0,1,3,8,9,10,13,14,17,19,20,21,22,26,27,30,34,37,38,41,43,44,45,46,47,49,51,53],anomali:0,anoth:[27,34,35,38,44,51,52],anymor:[38,52],anyth:[34,41],anywai:46,apach:[38,46,52],api:[0,32,37,41,42,45,46,48,49,51],apollo:[0,45],app:[39,43],appear:47,append:[4,10,38,44],appli:[0,3,9,10,14,30,36,41,42,44,46,47,48,53],applic:[0,3,6,27,39,40,41,44,46,49,50,52],approach:[41,45],appropri:[37,46,51],april:0,apt:46,ar:[0,1,3,4,6,7,8,9,10,15,18,21,25,26,27,28,29,30,32,34,36,37,40,41,42,43,44,46,47,48,50,51],arbitrari:[6,32],archflag:46,architectur:46,arg:[3,4,6,9,10,19,20,21,22,23,27,32,34],arg_typ:1,argument:[0,1,3,4,7,9,10,15,18,27,30,31,32,34,35,44,46,51,52],argument_typ:1,arm:0,around:[0,9,32,40,41,52],arrai:[29,38],arriv:3,as_cql_queri:[0,25],as_edg:[15,18],as_graph_stat:14,as_path:[15,18],as_vertex:[15,18],ascend:[10,38],ascii:[0,6,44],ask:[45,48],assert:[6,36],assertionerror:38,assign:[0,6,11,37],associ:[0,3,52],assum:[3,21,22,38,41,51,52],assumpt:41,astimezon:41,async:3,asynchron:[0,3,30,43,49],asyncio:[0,33],asyncioconnect:19,asyncioreactor:33,asyncor:[0,33,46],asyncoreconnect:[0,20],asyncorereactor:[0,33],atexit:0,atlassian:27,atom:[27,30],attach:[0,3,15,18,34,44,49,50],attempt:[0,1,3,4,5,27,34,41,43,44,52],attr_kwarg:3,attribut:[0,3,6,8,9,10,11,15,18,25,27,29,30,31,37,38,40,42,44,47,52,53],attributeerror:0,aug:0,august:0,auth:[0,33,51,52],auth_provid:[2,3,51],authent:[0,1,3,33],authenticationfail:[1,2],author:[1,51],authorization_id:51,authprovid:[0,2,3,51],auto:35,automat:[0,1,35,37,38,44,46,50],automobil:[10,35,38],automobile2:10,avail:[0,3,10,30,38,46,52],avoid:[0,3,27,40,43,46],aw:27,awai:[3,30],awar:[0,3,26,27,41,46,51,52],ayncoreconnect:0,b:[4,12,14,15,18,34,35,36,38],back:[0,6,9,32,38],backoff:0,backpressur:0,backup:38,backward:[3,18,25,52],bad:0,badli:0,balanc:[0,3,33,42,52],bar:44,bark_all_night:37,base:[0,1,3,9,12,26,27,29,30,32,37,40,43,44,47,51],base_delai:27,basegraphrowfactori:12,basi:[0,52],basic:[0,3,12,37],batch:[0,1,3,9,10,12,14,25,27,33,35,38,48],batch_log:27,batch_obj:10,batch_object:9,batch_r:10,batch_typ:[10,30,34],batchqueri:[0,10,34,36,38],batchstat:[0,1,3,30,52],batchtyp:[0,10,30,34],bb984ee:52,beat_init:39,becam:[0,40],becaus:[0,3,4,15,18,27,30,32,40,41,44,46,52],becom:[0,3,8,49,52],been:[0,3,5,9,26,27,30,34,35,40,52],befor:[0,1,3,9,10,27,29,30,40,43,44,49,50,52],begin:[0,10,13,44],behav:32,behavior:[0,3,6,27,44,52],behind:[27,41],being:[0,3,6,26,30,36,42,44,46,47],below:[3,4,10,27,29,36,37,38,40,46,47,49,52],benchmark:[0,49],benefit:52,best:[27,44,51],beta5:1,beta:[1,46],beta_vers:1,better:[0,27,46,49],between:[0,2,6,29,30,46],bewar:27,beyond:37,big:[0,45],bigint:[6,44],binari:[0,6,30],binary_typ:29,bind:[0,3,12,30,43,44],bit:[6,32,46],bitmap:29,blacklist:27,blacklist_filter_polici:27,blah:44,blake:[9,38],blank:9,blind:[9,10],blindli:10,blist:0,blob:[0,6,17,44],block:[0,3,4,34,44,49],blog:49,bob:[3,30,44],bodi:[0,29],bool:[6,7,8,10,25,44],bootstrap:[0,26],bop:0,borrow_connect:0,both:[0,3,38,39,44,46,51],bound:[3,14,30,32,43,49],bound_stmt:3,boundstat:[0,30,44,52],bracket:47,brew:46,broadcast_address:27,broadcast_rpc_address:25,broadcast_rpc_port:25,broken:0,brought:52,brows:27,brute:27,bu:0,bucket_high:9,bucket_low:9,buffer:[0,17,44],bug:[40,45,52],build:[0,25,40,44,46,49],built:[0,32,42,46,49,52],bulk:12,bump:0,busi:[3,28],bypass:[0,3,8,30],bytearrai:[0,17,44],bytecod:12,byteorderedpartition:[0,25],bytesio:0,bytestoken:25,c:[0,6,12,27,38,51],ca:[0,27,51],ca_cert:51,cach:0,cacreateseri:51,cakei:51,calcul:0,call:[0,2,3,5,9,10,17,19,20,21,22,27,31,34,37,38,41,44,48,50,51],callabl:[6,10,12],callback:[0,3,10,44,49,51],callback_arg:3,callback_kwarg:3,camera:38,can:[0,1,3,4,6,8,9,10,13,14,15,17,18,21,25,27,29,30,31,32,34,35,37,38,39,41,42,43,44,45,46,48,49,50,51,52,53],cancel:0,cannon:40,cannot:[0,27,30,32,38,42],capabl:50,captur:[0,46],car:38,cardin:[15,18],care:[3,8],carri:34,cass_driver_build_concurr:46,cass_driver_no_cython:46,cass_driver_no_extens:46,cass_server_vers:0,cass_typ:32,cassandra:[0,33,34,35,36,37,38,39,40,42,43,46,48,49,50,51,53],cassandra_init:39,cassandra_vers:0,cast:44,cat:[37,40,51],caus:[0,3,10,26,37,47],caution:[8,37],caveat:27,cc94073:52,cdc:[0,27],cdef:0,ceas:27,ceil:1,celeri:48,cell:43,center:30,cento:[0,46],central:41,cert:51,cert_countri:51,cert_org_nam:51,cert_ou:51,cert_req:51,cert_requir:51,cert_valid:51,certain:[13,27,40,46],certfil:51,certif:[0,51],chain:34,challeng:[2,46],chanc:27,chang:[0,3,6,9,10,27,30,31,36,37,38,43,44,45],changelog:45,charact:[0,6,44],charl:30,check:[0,3,9,10,27,37,46,52],check_hostnam:[0,51],check_support:27,checkout:46,child:[0,27,43],child_polici:27,choic:[46,49],choos:[15,18,27,52],chosen:3,chunk:0,circuit:0,circumst:0,citi:52,civic:[10,35,38],cl:[0,10,21],clang:46,classmethod:[1,9,15,18,19,20,21,22,25,29,32],claus:[0,10,25,37,47,52],clean:[0,39,46,52],cleanup:[0,20],clear:[0,14,27,30],clearer:41,client:[0,1,2,3,8,27,29,41,42,45],client_encryption_opt:51,client_protocol_handl:[3,29],clock:32,clock_seq:32,clone:[3,42],close:[0,3,5],closur:0,cloud:[0,3,27,45],cluster1:35,cluster2:[10,35],cluster3:35,cluster:[0,2,4,5,6,7,9,10,12,19,20,21,22,25,26,27,29,30,33,35,37,38,39,43,44,46,48,49,51,53],cluster_opt:7,clustering_kei:38,clustering_ord:[6,37],clustertest:0,cn:51,code:[0,1,34,39,45,51,52,53],codebas:0,coerc:6,coincid:0,col:[0,47],col_nam:9,collect:[0,3,8,10,25,26,30,32,38,45,52],collis:0,colnam:[3,10,30],column:[0,8,9,10,11,17,25,30,33,35,36,37,38,44,47,48,52,53],column_family_nam:9,column_nam:[10,15,18,38],columnmetadata:[25,52],com:[6,10,51],combin:[0,3],come:0,comma:44,command:[0,35,46],comment:[9,10,37],comment_id:[10,37],common:[0,40,46,51,52],commun:[0,5,45,46],compact:[0,9],compar:[0,30,32,45],comparison:[0,6],compat:[0,3,18,25,33,52],compil:[0,29,46,49],complain:37,complet:[0,1,2,3,4,11,27,30,34,37,40,43,44,49,51],complex:[0,42,46],compliant:0,compon:[0,10,25,30,32,51],compos:29,composit:[0,30,38],compositetyp:0,compound:6,compress:[0,3,29],compressor:29,compris:[1,29],comput:[0,3,9,43],concern:41,concurr:[0,3,8,30,33,43,44,49],condit:[0,1,3,8,10,30,45],conf:51,config:[0,51],configur:[0,1,2,3,5,7,9,15,18,27,31,42,44,45],configurationexcept:1,confirm:0,conflict:36,confus:[40,52],conn:35,connect:[0,1,2,3,4,8,9,10,11,12,19,20,22,23,24,26,27,30,33,37,38,39,40,42,45,46,48,51,52,53],connect_timeout:[0,3],connect_to_remote_host:3,connected_to:26,connection_class:[3,46,51],connection_error:26,connection_exc:27,connectionbusi:5,connectionexcept:[0,5],connectionshutdown:5,consensu:1,consid:[0,1,3,18,27,44,47,49,51,52],consider:[37,49],consist:[0,1,3,7,10,27,30,32],consistency_level:[3,15,18,30,42,44],consistencylevel:[0,1,3,7,10,15,18,26,27,30,40,44],consit:0,constant:[0,51],constantreconnectionpolici:[0,27],constantspeculativeexecutionpolici:[0,27,44],constrain:[4,10],constraint:[9,37],construct:[0,9,12,32,41,42,44],constructor:[0,3,6,38],consult:37,consum:[0,4,52],consumpt:[0,49],contact:[0,3,27,44],contact_point:[0,3,7,27,51],contain:[0,3,6,9,10,17,27,32,37,38,41,47,50],contend:0,content:[0,10,29],context:[0,3,8,9,10,12,15,18,34,39,46,49,51],contextqueri:[0,10,35],contin:0,continu:[0,2,27,50],contract:[0,29],contribut:45,control:[0,3,4,27,30,40,49,51],control_connection_timeout:3,conveni:[3,15,18,30,38],convent:37,convers:[15,18,40,41,52],convert:[0,13,15,17,18,32,40,41,52],convict:27,conviction_policy_factori:3,convictionpolici:27,coord:32,coordin:[1,3,4,27,32,43],coordinationfailur:1,copi:42,copyright:0,core:[0,3,4,38,40,46,49],core_connect:3,correct:[0,9,41],correctli:[0,3],correspond:[2,4,6,8,37],cost:[0,9,10,38],costli:46,could:[0,10,52],count:[0,9,10,26,27,36,38,48],counter:[0,6,26,27,30,37,44],cours:3,cover:[37,43],coverag:0,cpu:[0,4,44,49],cpython:[0,3,46],cql3:[36,38,45],cql:[0,1,6,9,10,11,15,17,18,25,30,32,36,37,38,40,41,47,48,52,53],cql_cluster:39,cql_encode_all_typ:17,cql_encode_byt:17,cql_encode_d:17,cql_encode_datetim:17,cql_encode_list_collect:17,cql_encode_map_collect:17,cql_encode_non:17,cql_encode_object:17,cql_encode_sequ:17,cql_encode_set_collect:17,cql_encode_str:17,cql_encode_tupl:[17,52],cql_encode_unicod:17,cql_keyword:25,cql_keywords_reserv:25,cql_keywords_unreserv:25,cql_refer:10,cql_session:39,cql_use:6,cql_version:[0,3],cqle:0,cqlengin:[0,33,34,35,36,37,38,39,43,45,48,52],cqlengine_batch:34,cqlengine_test:38,cqlengineexcept:[0,40],cqltype:52,cqluseudt:6,crash:0,creat:[0,1,2,3,5,6,7,8,9,10,12,25,27,30,32,34,35,36,37,38,41,43,44,47,48,49,51,52,53],create_default_context:51,create_execution_profil:12,create_keyspac:40,create_keyspace_network_topolog:[8,40],create_keyspace_simpl:[8,40],create_simple_keyspac:35,created_at:[34,48],creation:[0,3,4,25,38],credenti:[0,3,51],credit:44,crt:51,crt_sign:51,crypto:51,csr:51,cstringio:0,cumbersom:41,current:[0,1,3,10,12,26,27,30,31,38,42,43,46,50,52],current_pag:3,current_row:3,custom:[0,1,3,6,10,17,27,30,33,41,42,44,46],custom_index:6,custom_payload:[3,15,18,29,30],cut:0,cute:37,cycl:3,cython:[0,29],cython_protocol_handl:3,cythonprotocolhandl:3,d:[3,6,10,30,41,44],daemon:0,dai:[6,27,32,51],dash:0,data:[0,1,3,9,10,27,30,33,37,38,41,43,44,52,53],data_retriev:[1,27],databas:[6,8,9,34,37,38,41,42],datacent:[0,1,27,28],dataset:[0,10,38],datastax:[0,6,10,18,27,44,48,51,52],datastream:38,datatyp:0,date:[0,6,17,32,44,45,52],daterang:[0,32],daterangebound:32,daterangeprecis:32,datetim:[0,6,10,17,32,34,36,38,40,41,44,48],datetime_from_timestamp:32,datetime_from_uuid1:32,datetyp:0,david:13,daylight:41,days_from_epoch:32,db:0,db_field:[0,6],dc:[0,3,27,52],dc_name:8,dc_replication_factor:25,dc_replication_map:8,dcawar:0,dcawareloadbalancingpolici:0,dcawareroundrobinpolici:[0,3,27,42],dclocal_read_repair_ch:0,dct:0,dd:[17,32],ddl:0,dead:33,deadlock:[0,4],deal:[0,41,42,49,52],debian:[0,46],debug:[0,3],decemb:0,decid:27,decim:[0,6,10,38,44],decimaltyp:0,decis:[0,26,41],declar:[11,37],decod:[0,3,29,30,33,52],decode_messag:29,decomiss:0,decommiss:[0,27],decompress:29,decompressor:29,decor:0,decrement:6,deem:41,def:[3,27,34,37,39,43,44,50,51,52,53],defacto:41,default_bit:51,default_consistency_level:[0,3,7,42],default_fetch_s:[3,50],default_keyspac:[0,7],default_retry_polici:[3,27,42,43],default_serial_consistency_level:[0,3,42],default_time_to_l:[0,38],default_timeout:[3,42],defaultloadbalancingpolici:[0,27,52],defer:[0,10,27],defici:41,defin:[0,1,2,3,6,8,9,10,15,18,25,27,30,33,35,38,40,42,44,45,48],definit:[3,6,29,38,40],defunct:[0,3,5],degre:13,delai:[0,27,44],deldyck:37,delet:[0,8,9,10,27,30,34,38],delete_keyspac:40,deliv:3,deliveri:3,demand:0,demonstr:51,dep:0,depend:[0,2,41,43,47,49],deploy:51,deprec:[3,9,16,27,51],deprecationwarn:[0,52],depth:0,dequ:0,deriv:[32,37,40,42,46,52],derivi:9,desc:37,descend:[10,37,38],describ:[1,27,29,32,38,40,41,51],descript:[0,3,15,18,27,30,34,43,48,51],descriptor:0,deseri:[0,15,18,33,41],deserialize_bigint:[15,18],deserialize_blob:[15,18],deserialize_d:[15,18],deserialize_decim:[15,18],deserialize_doubl:[15,18],deserialize_dur:[15,18],deserialize_float:[15,18],deserialize_int:[15,18],deserialize_linestr:[15,18],deserialize_point:[15,18],deserialize_polygon:[15,18],deserialize_tim:[15,18],deserialize_timestamp:[15,18],deserialize_uuid:[15,18],design:[44,49],desir:[3,10,27,34],despit:10,destroi:0,detail:[0,1,3,9,10,30,37,41,42,43,44,46,49,51,52],detect:[0,40],determin:[6,9,27,30,44],determinist:0,dev:46,devel:46,deviat:26,devic:0,dict:[0,1,3,6,7,8,9,12,15,17,18,25,26,29,30,37,44,47,51],dict_factori:[0,3,7,16,30,52],dictionari:[0,6],dictlik:32,did:[5,10,27],didn:10,differ:[0,3,10,29,30,32,36,37,38,42,44,51,52],digest:27,dir:0,directli:[3,4,17,29,30,44,46,51],disabl:[0,3,9,10,46],discontinu:0,discourag:3,discov:[0,3,27,44],discrimin:[6,9,37],discriminator_column:[6,37,40],discuss:[3,6,11,30,37,45,47,49],disentangl:0,disk:6,dispos:3,disproportion:27,distanc:[13,27,32],distant:27,distinct:[0,10,15,18],distinct_field:10,distinguish:0,distinguished_nam:51,distribut:[0,27,38,46],distrimin:37,distriminator_column:37,dll:0,dn:27,doc:[0,1,6,10,37,38,41,51],document:[0,6,27,32,41,42,45,46,48,51,52],doe:[0,3,10,17,32,34,38,40,44,46,47,53],doesn:[0,31,52],doesnotexist:[0,10],dog:[37,40],dollar:0,don:[0,10,38,44,49,53],done:[0,3,37,41,43,51,52],dont:0,doubl:[0,6,32,44,49,52],double_precis:[40,52],down:[0,3,33,46],downgrad:[0,27],downgradingconsistencyretrypolici:[0,27,44],drain:0,drift:31,driven:8,driver:[0,1,3,5,7,10,18,26,27,28,29,30,37,38,40,41,44,46,47,48,49,50,51,53],driverexcept:1,drop:[0,6,8,29],drop_keyspac:[8,40],drop_tabl:8,drope:0,dsa:0,dse:[0,1,3,6,12,14,15,18,32,45],dse_graph:52,dse_graph_query_languag:12,dse_graph_query_protocol:12,dse_v1:[0,1],dse_v2:1,dsegraph:12,dsegssapiauthprovid:[0,51],dseloadbalancingpolici:[0,27,52],dseplaintextauthprovid:51,dsesessionremotegraphconnect:12,dsl:12,dt:32,due:[0,1,10,26,34,49],duplic:0,durabl:3,durable_writ:8,durat:[0,30,32],durationtyp:0,dure:[0,1,2,3,5,9,40,46],dynam:[0,3],dynamiccompositetyp:0,e0b9a54a6d93:44,e16a073:52,e:[3,8,9,10,12,15,18,27,30,43,46],each:[1,2,3,4,6,9,27,30,36,37,38,41,44,50,52,53],each_quorum:1,eagain:0,eai:0,earlier:[0,21,37],eas:35,easi:[0,37,38],easier:[38,42,46],easiest:[41,46],easili:[0,10,41],eat:37,ec2:0,ec2multiregiontransl:27,ed:0,edg:[15,18],effect:[0,3,8,34,51],effici:[0,29],effort:[0,40,51],eggleston:9,either:[2,3,15,18,32,37,38,41,46],element:[0,3,10,15,18,25,32,38,44],els:[4,39,50],em1:[34,48],em2:[34,48],em3:[34,48],em4:48,em5:48,em6:48,em7:48,em8:48,email:44,emit:[3,40,46],empti:[0,2,3,25,47],en:[6,10],enabl:[0,3,10,44,51,52],encod:[0,3,6,15,18,29,33,41],encode_messag:29,encount:[0,3,10],encrypt:[0,51],end:[0,10,34],endian:[0,45],endless:0,endpoint:[5,25,27,28,51],endpoint_factori:3,endpoint_or_address:25,endpointfactori:[5,51],enforc:[0,37],engag:46,enough:[1,30],ensur:[0,3,4,9,27,39,46,51],entir:[0,3,4,10,14,25],entiti:0,entri:[10,17,52],environ:[8,27,46],eof:51,ep:[3,44],epoch:[0,31,32,41],eq:0,equal:[0,3,6,30,38],equival:[9,36,41,44],errback:[0,3,44,50],errback_arg:3,errno:0,error:[0,1,3,4,5,6,10,27,44,50],error_code_map:1,errro:1,escap:[0,17],especi:[0,8,42,46],essenti:38,establish:[3,44],etc:[3,10,26,27,38],evaluate_challeng:2,even:[0,3,7,27,30,41,42,44],evenli:27,event:[0,3,4,21,27,30,33,39,43,44,46,50,51],eventlet:[0,33],eventletconnect:[21,51],eventletreactor:33,everi:[0,27,31,38,39,44],everyon:46,evict:0,evolv:42,ewouldblock:0,exact:2,exactli:[0,27,40],examin:32,exampl:[0,2,3,4,6,9,10,11,25,30,32,35,36,38,40,42,43,44,46,47,48,49,50,52,53],example1:48,example2:48,example3:48,example4:48,example5:48,example6:48,example7:48,example8:48,example_id:48,example_mapp:0,example_typ:[34,48],examplemodel:[34,48],exc:[3,50],exce:[0,50],exceed:[3,4],except:[0,3,4,5,6,7,9,10,15,18,27,28,29,30,32,33,34,37,38,39,44,50,51],excess:0,exclud:38,exclus:[7,32,45],exec_profile_default:[3,42,44],exec_profile_graph_analytics_default:3,exec_profile_graph_default:[3,12,52],exec_profile_graph_system_default:3,exect:0,execut:[0,1,3,8,9,10,12,14,15,18,25,27,29,30,33,35,37,38,43,45,47,49,50,53],execute_a:[3,51,52],execute_async:[0,3,4,29,43,44,49,50],execute_concurr:[0,4,49],execute_concurrent_with_arg:[4,49],execute_graph:[3,15,18],execute_graph_async:3,execute_on_except:[10,34],execution_profil:[3,4,12,14,42,44],execution_profile_clone_upd:[3,42],executionprofil:[0,3,12,42,44],executionresult:4,executor:0,executor_thread:3,exhaust:[0,27],exist:[0,1,3,8,9,10,27,28,42,47,48,52],exit:0,expand:0,expect:[0,5,9,43,47,51,52,53],expens:3,experi:4,experiment:[0,19],expir:3,explain:[0,42],explicit:[0,40,41],explicitli:[0,1,3,10,34,37,52],explod:42,explor:38,exponenti:[0,27],exponentialreconnectionpolici:[0,3,27],export_as_str:[0,25],export_for_schema:[0,25],export_schema_as_str:25,expos:[0,31,52],express:[4,13,32],extablish:3,extend:30,extens:[0,3,27,41],exterior:32,extern:41,extra:[0,25,30,46],extra_deserializer_map:[15,18],extract:[15,18],f:3,facilit:29,factor:[0,8,25],factori:[3,12,33,47],fail:[0,1,3,4,7,14,15,18,26,33,34,37,44,47],failur:[0,1,7,9,26,33,34],fairli:37,fall:[0,32],fallback:[10,27,52],fallthroughretrypolici:27,fals:[3,4,6,7,8,9,10,15,18,25,27,30,47,48,51,52],falsei:27,falsi:27,famili:[0,5,9],faq:[43,45],fashion:3,faster:[0,33,46],favor:[27,40,52],featur:[12,19,33,38,40,45,46,51],feb:0,februari:0,fedora:46,feedback:0,feel:45,felcei:13,fetch:[0,3,10,30,38,44,50,52],fetch_next_pag:3,fetch_siz:[0,3,10,15,18,30,50,52],few:[3,44,46],field:[0,3,6,8,9,10,11,30,32,37,38,44,53],fieldnam:6,fierc:37,file:[0,40,49,51],fill:[15,18,30],filter:[0,6,9,27,33,35,48],finalis:1,find:[13,25,41,46],fine:53,finished_ev:50,finit:27,first:[0,3,4,6,7,9,27,36,37,38,40,44,45,46,48,50,51,52],first_nam:[9,37],first_pag:38,first_result:52,first_row:53,five:3,fix:[27,46,51,52],flag:[0,3,6,9,29,37,46],flake:0,flask:43,flat:38,flexibl:[0,45],flight:[0,5],fluent:[0,33,45,46,52],fly:[0,4,9,10,35],fn:[3,10],focu:27,follow:[0,3,26,27,29,34,35,37,40,41,42,44,46,47,51,52],foo:[44,53],food:37,footprint:[4,38],forc:[0,27,51],force_token_rebuild:3,forev:[21,27,30],fork:[0,20,43,49],form:[1,17,32,44],format:[0,1,3,17,25,29,30,33,41,44,51,53],formerli:0,forward:[1,27,40],found:[0,10,25,30,45,49,51,52],four:32,fqdn:[0,51],fraction:32,frame:29,free:[44,45],frequent:[27,44,45,48],from:[1,2,3,4,5,6,8,9,10,11,12,15,18,20,25,27,29,30,32,34,35,37,38,39,40,42,43,44,46,47,48,50,51,53],from_datetim:52,from_kei:0,from_str:25,from_valu:32,from_wkt:32,frozen:[0,32,53],frozenset:44,full:[0,30,52],full_replica:25,fulli:52,functionfailur:1,functon:38,further:[3,4,27,38,43,49,51],furthermor:27,fuse:46,futur:[0,3,6,7,30,31,40,43,44,46,49,50,52],fuzzi:13,g:[3,12,15,18,27,30],garbag:[0,52],gc:0,gc_grace_second:9,gcc:46,gen_client_cert:51,gener:[0,1,2,4,27,29,32,33,41,44,51,52],geo:[0,13],geo_typ:45,geom:0,geomet:0,geometri:[13,32,45],geospati:0,geounit:13,get:[0,3,8,9,10,25,27,38,46],get_all_query_trac:[3,52],get_control_connection_host:3,get_core_connections_per_host:3,get_credenti:51,get_execution_profil:[0,3],get_host:[0,25],get_host_by_host_id:25,get_lower_support:1,get_max_connections_per_host:3,get_max_requests_per_connect:3,get_min_requests_per_connect:3,get_query_trac:[0,3,43,52],get_replica:[0,25,43],get_stat:26,getstat:26,getter:[15,18],gevent:[0,33],geventconnect:[0,22],geventreactor:[0,33],gil:[0,49],github:[0,45,48],give:[3,27,51,53],given:[0,3,10,25,27,28,32,34,38,49],global:[0,7,43],go:[0,40],goal:[49,51],goe:0,good:[40,45],got:52,govern:[3,27],gracefulli:0,grant:51,graph:[0,3,45],graph_fluent:[45,46],graph_languag:[15,18],graph_nam:[12,15,18],graph_object_row_factori:[15,18],graph_opt:0,graph_protocol:[12,14],graph_read_consistency_level:[15,18],graph_result_row_factori:[15,18],graph_sourc:[0,15,18],graph_traversal_dse_object_row_factori:12,graph_traversal_row_factori:12,graph_write_consistency_level:[15,18],graphopt:[0,15,18],graphprotocol:[14,15,18],graphson1:[15,18],graphson1deseri:[15,18],graphson1seri:[15,18],graphson2:[0,15,18],graphson2read:[15,18],graphson3:[12,15,18],graphson:[0,12,14,15,18],graphson_1_0:[15,18],graphson_2_0:[14,15,18],graphson_3_0:[15,18],graphsonwrit:14,graphstat:[0,3,14],graphtravers:[12,14],graphtraversalsourc:12,greater:[27,50],greatli:0,greenlet:0,gremlin:[3,12,14,15,18,46],gremlinpython:46,greplin:[0,26],groovi:[15,18],group:25,group_keys_by_replica:25,grow:0,gssapi:2,guarante:[0,27,30,52],guard:8,guid:[0,44,45,46,48,51],h:[0,43],ha:[0,3,5,10,26,27,30,38,40,41,44,46,47,51,52,53],had:[0,40,52],handl:[0,2,3,9,10,12,29,33,38,39,41,43,44,46],handle_err:50,handle_error:[4,44,50],handle_fork:20,handle_pag:50,handle_result:3,handle_success:44,handle_writ:0,handler:[0,2,10,15,18,27,29,50],handshak:2,hang:[0,46],happen:[0,3,27],hard:46,has_more_pag:[0,3,50],hash:[0,38,46],hashabl:[0,32],hasn:0,have:[0,2,3,4,6,9,10,15,17,18,26,27,34,35,36,37,38,40,42,44,46,47,51,52,53],header:[0,29,46],healthmonitor:0,heap:0,heartbeat:0,help:[0,38,52],here:[3,9,10,34,35,37,38,39,40,41,46,48,51],hex:0,hh:32,high:[0,48,49],higher:[1,3,4,30,51,52],highli:44,highlight:52,hint:1,hit:[3,5],hold:[0,25,29],holder:44,homebrew:[0,46],honda2012:38,honda:[10,35,38],honor:[0,44],hook:[39,43],host1:27,host2:27,host3:27,host:[0,1,2,3,4,7,25,33,35,43,48,51,52],host_address:51,host_dist:3,host_id:25,hostconnect:0,hostdist:[0,3,27],hostfilterpolici:[0,27],hostnam:[0,27,51],hoststatelisten:3,hot:46,hour:32,how:[0,1,4,6,9,27,30,38,39,41,42,44,45,47,50,51,52],howev:[0,3,10,30,34,37,38,41,46,47,50,52,53],html:[6,10,38,48],http:[6,10,27,38,48,50],huge:49,human:[25,41],i:[8,10,15,18,27,30,38],id:[0,3,4,6,9,10,15,18,29,34,36,37,38,44,51,53],idea:27,ideal:[32,41],idempot:[33,44],identifi:[0,1,37,47],identitytransl:[3,27],idl:0,idle_heartbeat_interv:3,idle_heartbeat_timeout:[0,3],ids_to_fetch:44,ie:[13,50,51],if_exist:[9,10],if_not_exist:[9,10],iff:9,ifnotexistswithcountercolumn:40,ignor:[0,3,8,26,27,29,30,44],ignored_address0:27,ignored_address1:27,imagin:27,immedi:[1,3,34,44],immut:[0,32,48],impact:4,implement:[0,2,3,5,15,18,19,20,21,22,23,24,27,29,32,41,46,49,50,51,52],impli:30,implicit:[0,10,52],implicitli:[3,8,37],importerror:39,impos:37,improv:[0,1,35,49,52],inbetween:27,includ:[0,3,9,10,25,26,40,45,49,51,52,53],include_keyspac:9,inclus:3,incomplet:0,inconsist:0,incorrect:[0,44],incorrectli:[0,30],increas:[0,27,31,46],increment:6,incur:9,indefinit:0,independ:[32,51],indetermin:3,index:[0,3,6,25,37,38,48,52],indexmetadata:25,indic:[0,1,2,3,6,8,9,10,25,27,38,47],individu:3,inet:[0,1,25],inet_address:0,inet_ntop:0,inet_pton:0,infin:0,infinit:[0,27],inflat:29,influenc:27,info:[0,3,33,44],inform:[0,3,5,9,25,27,41],inherit:[0,6,9,11,42],init:[0,3,36,40],initi:[0,2,3,5,6,7,9,15,18,27,29,31,32,35,38,39,44,46,47,51],initial_respons:2,initialize_reactor:[19,20,21,22],inititi:40,inject:[3,42,46],inplac:32,input:[0,30,40,41,42],insanc:41,insensit:9,insert:[0,1,3,4,9,10,30,32,36,37,41,44,47,52,53],insert_stat:53,insert_us:30,insid:[13,34,44],insight:0,inspect:[3,8],instal:[0,40,44,45,49,51],instanc:[0,2,3,6,9,10,13,15,18,25,26,27,30,34,38,44,48,50,51,52,53],instanti:[0,27,29,31,44],instead:[0,3,4,30,38,40,44,50,51,52],instruct:38,insuffici:[0,26],intact:42,integ:[0,6,10,11,13,17,31,32,35,36,37,38,41,48],integer_typ:32,integr:[0,29,40,41,45,46,48,52],intend:[9,31,32,46],intent:40,interact:[3,44],interfac:[0,2,27,50],interior:32,intern:[0,3,10,27,31,32,40,41,52],interpol:53,interpret:[0,30,36,38,52],intrins:41,introduc:[0,19,25,30,37,38,40,42,52,53],introduct:45,intruct:51,intstat:26,inupt:0,inv:[15,18],invalid:[0,1,26,30],invalidparametertypeerror:0,invalidrequest:1,invalidtypeparametererror:0,invit:40,invlabel:[15,18],invoc:46,invok:[0,3,40],involv:[30,38],io:[0,3,4,10,33,46,48,51],ip:[0,3,5,27,28,44,51],ipv4address:0,ipv6:0,ipv6address:0,irc:0,iron:40,is_analytics_sourc:[15,18],is_cql_compat:25,is_default_sourc:[15,18],is_graph_sourc:[15,18],is_idempot:[0,15,18,30,44],is_schema_agre:3,is_seri:0,is_shutdown:0,is_up:0,isbootstrap:27,isn:[0,9,10],isnotnul:38,isoformat:0,isol:27,issu:[0,2,27,31,32,36,52],item1:17,item2:17,item:[0,4,9,10,15,18,27,30,32,37,38,44],iter:[0,3,25,27,29,30,32,38,50,52],its:[0,2,3,5,9,19,20,23,24,27,30,32,37,42,46,51,52],itself:[46,52],jan:0,januari:0,java:27,jira:45,jit:49,jitter:[0,27],jk:51,joe:[37,51],john:44,join:0,jon:[10,37,38],json:[3,12,15,18],json_data:[15,18],juli:0,jump:48,junctur:40,june:0,just:[0,3,6,25,27,32,34,37,40,44,46,50,53],k:[34,47,51],keep:[0,27],keepal:0,kei:[0,1,3,6,8,9,10,25,26,27,29,30,32,37,38,42,43,44,47,51,53],kept:4,kerbero:[0,51],kevin5000:37,kevin:37,key1:17,key2:17,key_typ:6,keyerror:0,keyfil:51,keyout:51,keyspac:[0,1,3,7,8,9,10,11,15,18,25,27,29,30,35,43,44,52],keyspace_nam:52,keyspacemetadata:[0,25],keystor:51,keystore_password:51,keyword:[0,3,6,7,9,10],kill:0,kimberli:9,kind:[0,27,52],kinit:51,klass:3,know:[3,27,36,52,53],known:[0,15,18,25,40,52],known_host:26,ks1:35,ks2:35,ks:35,ks_name:8,kwarg:[0,3,4,6,7,9,10,12,15,18,19,20,21,22,23,27,32,34,39,51],label:[15,18],lambda:51,languag:[12,15,18,40,45,49],larg:[0,3,4,10,32,38,45,52],largest:36,last:[0,1,3,27,31,38],last_act:3,last_host:1,last_nam:[9,37],lastest:36,latenc:[26,44],later:[0,1,9,27,44,50],latest:[0,52],latter:[3,50],layout:25,lazi:0,lazili:29,lazy_connect:[0,7],lazyprotocolhandl:29,lbp:0,lead:[0,34,49,52],leak:0,learn:[30,51],least:[6,26,27,30,35,37,46],leav:[0,3],left:[0,3,4,9,41,52],legaci:[0,6,40,48,51,52],len:[0,9,10,35],length:[6,27,30],less:[0,46],let:[0,3,52],letter:13,level:[0,1,3,4,10,15,18,27,30,33,41,48,51],leveledcompactionstrategi:9,lib:0,libev4:46,libev:[0,33],libevconnect:[3,23,46],libevreactor:[0,3,33,46],libevwrapp:0,librari:[0,19,20,41,46,51],licens:45,lifecycl:2,lightweight:[0,1,10,30,44,45],lighweight:27,like:[0,1,3,4,9,10,15,18,26,27,30,37,38,41,44,45,46,50,51,53],limit:[0,3,10,30,38,41,49],line:[0,19,44,46],linear:32,lineariz:30,linestr:32,link:[0,41,46],linux:46,list:[0,1,3,4,6,7,8,9,10,15,17,18,25,27,29,30,32,35,43,44,45,46,48,50,52],list_col:44,list_column:10,list_column__append:10,list_column__prepend:10,listen:[0,3],listen_address:0,liter:[0,15,17,18,30,41,44,52,53],live:[1,27,43],ll:[38,51],load:[0,3,9,10,15,18,33,37,38,40,42,51,52],load_balancing_polici:[3,27,42,44],load_cert_chain:51,load_verify_loc:51,loadbalancingpolici:[0,3,27,42],local:[0,1,3,27,30,41,42,43,44,52],local_dc:[0,27],local_on:[0,1,3,44],local_queri:42,local_quorum:[0,1,44],local_seri:[1,30,44],localhost:[7,10],localstrategi:25,localtim:41,locat:[3,40,51,53],lock:0,locked_execut:42,log:[0,3,8,27,30,31,44,45,52],log_error:3,log_result:3,logentri:34,logger:0,logic:[0,37],longer:[0,1,52],look:[13,37,38,51],lookup:[0,25,27],loop:[0,3,4,21,33,44,46,51],lose:0,loss:0,lot:0,low:[15,18,27,33],lower:[1,4,27,32,38,44],lower_bound:32,lowercas:0,lwt:[0,3,9,47],lwtexcept:[0,9,10,40],lz4:[0,46],m:[9,36],mac:[0,46],machin:44,madd:46,made:[1,3,5,27,38,44,52],mai:[0,2,3,4,6,7,27,30,32,37,38,43,44,46,49,51,52],mail:45,main:[0,3,51,53],maintain:[0,3,30,32,37,52],major:[0,27,42,51,52],make:[0,1,3,10,25,27,37,40,41,42,43,44,45,46,48,51,52],make_query_plan:27,make_token_replica_map:0,manag:[0,3,6,9,10,11,28,33,34,37,42,46,48,52],mandatori:0,mani:[0,1,3,4,27,44,49,50,51,52],manifest:[0,43,47],manipul:[0,3],manner:32,manual:[3,9,34],manufactur:[10,35,38],map:[0,1,3,8,10,15,17,18,29,30,32,33,37,38,44,48,52],map_column:10,map_column__remov:10,map_column__upd:10,mapper:[0,7,40,45],march:0,margin:4,mark:[0,3,5,33,44],marker:41,master:0,match:[0,3,5,9,10,15,18,25,30,38,40,42,43,44,46,51,52,53],materi:[0,3,4,25,29,46,52],materializedviewmetadata:25,math:0,max:[0,3,5,26,44],max_attempt:[27,44],max_connect:3,max_delai:27,max_length:6,max_request:3,max_schema_agreement_wait:3,max_support:1,max_threshold:9,max_tim:38,max_uuid_from_tim:32,max_wait:[3,30],max_wait_sec:3,max_wait_sec_p:3,maximum:[1,3,6,27,32,38],maxtimeuuid:38,maxyear:[32,41],md5token:25,mean:[3,9,26,27,38,44],meaningless:38,meant:41,measur:[3,27],mechan:[2,3,27,51],median:26,meet:[26,27,51],member:[32,37],memori:[0,4,38,52],mention:[0,41,44],merg:40,mesh:52,messag:[0,1,2,3,5,29],message_types_by_opcod:29,meta:[0,3,37],metadata:[0,3,15,18,27,30,33,42,43],method:[0,2,3,9,10,27,29,30,35,36,37,38,41,43,44,46,49],metri:26,metric:[0,3,33],metrics_en:3,micro:32,microsecond:[0,31,52],middl:13,might:[0,3,30,50,51],migrat:[48,52],millisecond:[0,17,32,41],millsecond:41,min:[0,26,43],min_length:[0,6],min_request:3,min_support:1,min_threshold:9,min_tim:38,min_uuid_from_tim:32,minim:[3,40,41,44],minimalist:32,minimum:[1,3,6,32,38],mintimeuuid:38,minut:[0,32,46],minyear:[32,41],mismatch:0,misplac:0,miss:[0,27],misspel:13,mistak:40,mitig:49,mix:[0,30],mke:0,mm:[17,32],mmmuuunnn:32,mno:46,mock:0,mode:0,model:[0,3,8,33,38,43,48,52],model__lik:38,modelexcept:40,modelqueryset:10,modern:0,modif:8,modifi:[0,1,8,9,10,32],modul:[0,9,11,18,19,20,40,46,49],monkei:[0,21,22,51],monkey_patch_loop:0,monoton:0,monotonictimestampgener:31,month:32,montonictimestampgener:0,more:[0,3,4,6,9,10,25,27,29,31,38,40,42,44,45,46,49,50,51,52],most:[3,27,30,37,40,41,43,50],mostli:47,move:[0,3,30,52],ms:32,ms_timestamp_from_datetim:32,msg:29,much:[37,41,51,52],multipl:[0,3,10,12,14,15,18,27,34,35,44,48,49,52],multipleobjectsreturn:[0,10],multipli:13,multiprocess:0,multithread:0,murmur3:[0,3,46],murmur3partition:[0,25,46],murmur3token:[0,25],mussei:[46,51],must:[0,1,3,4,10,30,32,37,38,44,46,51,52,53],mutabl:3,mutat:48,mutual:[7,32],mv:27,my:51,my_callback:34,my_graph:12,my_tabl:44,my_user_id:30,mycf:3,mykeyspac:[3,30,44,52,53],mymod:36,mymodel:36,mystery_funct:34,mystorepass:51,mytabl:4,n:10,naiv:[6,41],name:[0,1,3,7,8,9,10,11,12,13,15,18,26,27,29,30,34,37,40,44,47,53],named_arg:34,named_tuple_factori:[0,3,16,30,52],namedt:38,namedtupl:[0,3,4,30,37,44,47,52,53],namedtuple_factori:0,nan:[0,32],nanosecond:[6,32,41],nativ:[0,1,15,18,29,37,45],natur:2,necessari:[3,44,46,51],need:[0,1,3,6,12,27,30,32,34,35,36,37,38,39,44,46,49,51,52,53],neg:[0,32,38],negoti:2,nest:[0,32],net:27,network:[0,30,44],networktopologystrategi:[0,8,25],never:[0,27,34,47,49,52],new_authent:2,new_nod:0,new_plan:27,new_schedul:27,newkei:51,newli:[0,25,27],next:[0,3,21,27,42,48,50,51],next_pag:38,nice:0,nicer:38,no_compact:0,no_valid_replica:25,noconnectionsavail:28,node1:42,node1_profil:42,node1_whitelist:42,node2:42,node2_profil:42,node:[0,1,3,5,25,26,28,30,32,33,44,51],node_domain:5,nodesync:0,nodetool:27,nohostavail:[0,3],nomenclatur:52,non:[0,3,6,10,32,33,37,44],nonblock:0,none:[0,1,2,3,4,5,6,7,8,9,10,11,12,14,15,17,18,25,26,27,30,32,36,38,39,41,43,44,47,50],nonetyp:0,nonexist:[0,1],normal:[0,3,9,10,12,27,30,32,41,44,50],nose:0,notabl:52,note:[0,3,4,7,8,9,10,19,27,30,32,35,37,38,40,41,42,44,45,50,51,52],noth:[0,27],notic:0,notif:0,notifi:3,nov:0,novemb:0,now:[0,31,34,36,38,40,41,44,48],nt:0,nullhandl:0,num:26,number:[0,1,3,4,5,9,10,26,27,40,42,44,46,47,50],numer:[0,41],numpi:29,numpyprotocolhand:29,numpyprotocolhandl:[0,29],o:[44,51],obj:[15,18],object:[0,3,4,12,15,17,18,25,26,27,30,31,32,34,35,36,37,41,42,43,44,45,49,50,52,53],obtain:[3,10,43,49],occur:[1,27,30,34,44,52],oct:0,octob:0,od:32,off:3,offer:[32,46,49,50],offici:[51,52],offset:32,often:37,ok:[27,51],old:[0,10,40],omit:[1,30],on_add:27,on_authentication_success:2,on_down:27,on_read_timeout:27,on_remov:27,on_request_error:[0,27],on_unavail:27,on_up:[0,27],on_write_timeout:[0,27],onc:[3,4,19,20,21,22,27,29,30,34,36,38,46,50],one:[0,1,2,3,6,10,13,26,27,30,32,35,36,37,38,42,44,51,52],ones:[10,40],onli:[0,1,3,4,5,6,7,8,9,10,18,19,27,30,31,34,37,38,40,41,44,46,47,51,52],op:38,opaqu:3,opcod:29,open:[0,2,3,26,27,28,32,45],open_connect:26,openssl:51,oper:[0,1,3,5,8,9,10,15,18,30,32,33,35,44,47,52],operationtimedout:[0,1,3],opertaion:0,oppos:27,optim:[0,46,49],option:[0,1,2,3,5,7,9,10,11,12,14,25,29,30,33,38,40,42,44,47,48,49,51,52,53],options__contain:38,options_map:25,order:[0,1,4,6,10,25,27,30,32,34,37,41,52],order_bi:[10,38],ordered_dict_factori:[0,3,16,30,52],ordereddict:[0,3,30,32,44],orderedmap:[0,32],orderedmapserializedkei:32,orderedset:0,org:38,organ:45,origin:[0,3,38,52],os:46,oss:[0,27],other:[2,3,6,8,9,15,18,26,27,30,32,38,44,46,51,52,53],other_error:26,otherstuff:53,otherwis:[2,3,6,9,27,32,51],ou:51,our:[38,44,48,51],out:[0,1,4,9,27,32,34,36,38,40,41,44,51],outcom:47,output:[0,41],output_password:51,outsid:[0,6,27,32],outv:[15,18],outvlabel:[15,18],over:[3,27,29,38,49,50,51,52],overcount:27,overflow:[0,41],overflowerror:[0,32],overhaul:52,overhead:[0,4,34],overload:[0,1,6,26,27],overrid:[0,3,9,15,18,42,44,52],overridden:[0,3,50],overriden:0,overs:3,overview:[40,41,45,48],overwrit:10,own:[3,9,37,51],owner:37,owner_id:[37,40],pack:[0,30],packag:[0,2,32,41,46,48,51,52],page:[0,1,3,45],pagedresult:[0,50,52],pagedresulthandl:50,pagin:[0,38,50],paging_st:[3,50],paging_stag:50,pair:[0,29],panda:29,parallel:0,param:[0,4,13],paramet:[0,3,4,6,7,8,9,10,12,14,15,18,27,29,30,31,32,37,40,47,51,53],parameter:53,parent:[0,20],pars:[0,15,18,29,32,43,44],parser:[0,29],part:[0,8,10,30,35,40,41,46],parti:[2,3,41,48],partial:[0,21,22,30],particular:[0,3,25,27,30],particularli:38,partit:[0,6,10,25,27,30,38],partition:0,partition_kei:[6,10,30,38],pass:[0,2,3,4,6,7,9,10,25,29,30,34,36,37,38,39,47,48,51,52,53],passin:51,password:[2,51],passwordauthent:[2,51],patch:[0,21,22,41,51],path:[0,15,18,29,46,51],pattern:[37,49],paxo:30,payload:[0,1,3,30,33],peer:[0,5,25],pem:51,pend:0,pending_us:30,pep:0,per:[0,3,4,6,9,10,25,27,35,37,43,44,50,52],percentil:26,perform:[0,1,3,9,10,27,30,33,37,38,45,46],perhap:46,period:39,permiss:51,permit:27,persist:[0,15,18,27,41],person:[9,37,38],person_id:37,perspect:[2,27],pertain:3,pertin:47,pet:[37,40],pet_id:[37,40],pet_typ:[37,40],phase:[2,3,30,46],photo_id:[10,37],phrase:13,pick:[36,44],pip:[0,52],pk:[38,44],pk__token:[0,38],pk__token__gt:[0,38],place:[0,40,44,52],placehold:[3,15,18,30,44,53],placement:[0,8],plai:0,plain:51,plaintextauthent:2,plaintextauthprovid:[2,3,51,52],plan:[0,8,27],platform:[0,42],pleas:[0,3,6,9,11,27,37,43,45,51],plu:[38,47],plug:39,pluggabl:0,pmfstat:26,point:[0,3,6,26,27,32,41,44,51,52],polic:27,polici:[0,3,33,42,43,44,52],poll:[3,30,43],polygon:32,polymorphic_kei:40,pool:[0,1,3,33,52],pool_wait_timeout:3,popul:[0,3,27,30,38],port:[0,3,5,25,44],portion:[30,32],posit:[3,10,30,34,38,44,47,52],possibl:[0,3,9,21,27,31,32,37,38,41,46,50,51,52],post:[0,49],postfork:[39,43],potenti:0,pr:0,practic:44,practiv:10,pre:[0,46],preced:[3,27,34,47],precis:[0,6,17,32,40,41,52],predic:[27,33],predict:38,preemptiv:44,preexist:7,prefer:[0,27,41,44,46,52],prefix:[9,11,13],prematur:0,prepar:[0,3,4,27,33,41,43,51,53],prepare_on_all_host:3,prepared_stat:30,preparedstat:[0,3,30,44],preparemessag:0,prepend:[10,47,52],present:[0,7,10,30,41,42,43,46,47,52],preserv:[0,6,9,30,40],presist:37,pretti:49,preval:41,prevent:[0,10,40,44,46],previou:[0,3,51,52],previous:[0,40,42,52],previous_vers:1,price:[10,38],primari:[0,3,6,8,9,10,25,30,37,38,47,53],primary_host:27,primary_kei:[6,9,10,25,35,36,37,38,40,48],princip:[0,51],print:[3,9,10,12,30,32,35,37,41,42,43,44,46,48,53],prior:0,privat:[0,1,27],probabl:[27,38,51],problem:[0,3,26,43],process:[0,3,4,20,43,44,46,49,51,52],process_row:50,process_us:[3,4,44,50],produc:[2,4,15,18,38],product:[8,45,48,51,52],profil:[0,3,4,12,14,44,45],profile_long:44,programmat:3,project:[1,40,48,49],prompt:[46,51],proof:0,propag:[0,27,30],proper:[0,39,46],properli:[0,3,37,38,44],properti:[0,1,3,5,9,13,15,18,25,27,28,30,32,37],protect:0,protocol:[0,1,3,5,6,12,14,30,33,37,45],protocol_tlsv1:51,protocol_vers:[0,1,3,4,29,30,32,37,48,50,51,52,53],protocolerror:5,protocolhandl:[0,29],protocolvers:1,provid:[0,3,12,13,15,18,27,41,42,43,46,49,50,51,52],proxi:5,proxim:13,proxy_address:5,prudent:40,ps:50,publish:[0,46,51],pull:45,pure:[0,2,27,29,46,51],purpos:[3,6],push:[0,46],py:[0,46],pyopenssl:[0,51],pypi:[0,46],python2:32,python3:0,python:[0,15,17,18,19,20,29,30,32,37,40,41,44,47,48,49,51,52,53],pyton:0,pytz:41,q2:48,q:[35,38,48],qop:[2,51],quadrat:0,quantiz:6,queri:[0,1,3,4,6,9,12,15,16,18,25,27,29,32,33,35,37,40,41,42,45,46,48,49,53],query_cl:[3,30],query_from_travers:12,query_str:[15,18,30],queryexhaust:3,queryhandl:[3,29],queryoper:0,queryset:[0,9],querytrac:[0,30,43],question:[45,48],queu:34,quickli:[0,49],quorum:[1,10,27,30,44],quot:[0,17,41],race:0,rack:[0,28],radiu:32,rais:[0,1,2,3,4,5,6,9,10,15,18,27,30,32,34,37,38,40,44,50,52],raise_on_first_error:4,random:[0,27,32,38],randompartition:25,rang:[0,4,10,32,38,41,43],range_request_timeout_in_m:1,rare:0,rather:[0,32,46],raw:6,re:[0,27,30,37,38,39,44,46,51,53],reach:34,reachabl:27,reactor:[0,20,24,43],read:[0,1,6,15,18,26,27,30,32,34,36,43,51],read_inet:0,read_repair:0,read_repair_ch:0,read_request_timeout_in_m:1,read_timeout:26,readabl:25,reader:[12,15,18],readfailur:1,readm:0,readtimeout:[1,44],reason:[1,3,27,41,51],rebuild:[0,3],rebuilt:0,receiv:[0,1,3,27,44],received_respons:[1,27],recent:0,recogn:[15,18],recommend:[0,3,4,27,36,44,49,51,52,53],reconnect:[0,33],reconnection_polici:3,reconnectionpolici:[0,27],reconnector:0,record:[0,6,10,27,38],recreat:[0,25],recurs:0,redhat:46,reduc:[0,3,49],redund:40,reevalu:0,ref:0,refactor:[0,41],refer:[0,10,34,40,42,47,52],referenc:3,refresh:[0,3],refresh_:52,refresh_keyspace_metadata:3,refresh_nod:[0,3],refresh_schema:[0,52],refresh_schema_metadata:3,refresh_table_metadata:3,refresh_user_aggregate_metadata:3,refresh_user_function_metadata:3,refresh_user_type_metadata:3,regard:[3,27,32],regardless:[26,27,46,47],regex:13,regist:[0,3,7,12,17,26,34,37,52],register_connect:[0,7,35],register_listen:[0,3],register_user_typ:[3,52,53],registr:35,registri:7,regress:0,regular:[13,30,36,38],reilli:44,reinstal:46,reject:47,rel:41,relat:[0,30,38,42],relax:7,releas:[0,9,27,40,42,51,52],release_vers:[43,44],reli:[27,38],reloc:40,remain:[3,20,27,40,42],rememb:44,remot:[0,3,27],remoteconnect:12,remov:[0,3,6,8,10,27,30,32,42,47],remove_request_init_listen:3,repair:27,repeat:[27,44],replac:[0,3,6,29,40,51,52],replai:[1,27],replic:[0,3,8,25,40],replica:[0,1,8,25,26,27,30,44],replication_factor:[8,25],replication_factor_info:25,replicationfactor:25,replicationstrategi:25,report:[0,27],reprepar:0,reprepare_on_up:3,repres:[1,3,5,6,9,15,18,25,26,28,30,31,32,37,38,40,41,52],represent:[0,25,30,32,52],reproduc:0,req:51,req_distinguished_nam:51,request:[0,1,3,4,26,27,38,39,42,44,45,47,49,51,52],request_id:0,request_tim:[0,26],request_timeout:[3,42,44],requestexecutionexcept:1,requestvalidationexcept:1,requir:[0,1,2,3,6,7,19,27,29,30,32,37,38,39,40,44,46,48,51,52],require_client_auth:51,required_replica:[1,27],required_respons:[1,27],reset:27,resolut:[0,32],resolv:[0,5,27,36,51],resort:27,resourc:[19,20,21,22,46,51],respect:[0,3,38],respond:[1,2,27,44],respons:[0,1,2,3,27,29,38,44],response_futur:3,responsefutur:[0,3,29,43,44,49,50,52],rest:[27,44],restart:[0,44],resulset:0,result:[0,3,4,9,10,12,15,18,25,26,27,29,30,32,37,38,41,43,44,45,53],result_cach:0,result_metadata:29,result_or_exc:4,result_set:3,results_gener:4,results_metadata:0,resultset:[0,3,50,52],resync:9,retain:[0,41],rethrow:27,rethrown:0,retri:[0,7,26,30,33,44],retriev:[1,3,10,30],retry_connect:7,retry_next_host:27,retry_num:27,retry_polici:[0,3,15,18,27,30,42,43,44],retrypolici:[0,3,26,27,30,43],retun:47,reus:[3,14,30],revers:[10,27],review:0,rework:52,rf:[0,1],rhel:46,rich:3,right:[27,30,44],ring:[0,3,27,32,33],risen:51,risk:27,rlac:0,robin:27,robust:41,role:51,root:51,root_ca_base_nam:51,root_cert_pass:51,rootca:51,rotat:27,round:[0,27,32],roundrobinpolici:27,roundtrip:30,rout:[0,3,9,27,43,46],routing_kei:[15,18,27,30,43],row:[0,3,4,5,10,12,29,33,34,37,38,41,42,43,44,47,48,50,52,53],row_factori:[0,3,7,29,30,42,44],row_id:10,row_list:52,rpc:[5,28],rpc_addr:0,rpc_address:[0,42],rsa:51,rule:30,run:[0,9,10,21,27,34,37,39,44,46,48],run_in_executor:0,runtim:[0,46,49],runtimeerror:0,s:[0,1,2,3,6,7,9,10,11,24,27,29,30,32,34,35,36,37,38,39,41,44,45,46,48,51,52,53],safe:[0,4],safeti:0,same:[0,3,4,6,7,12,15,18,25,27,30,32,34,35,36,37,38,42,43,44,46,51,52],sasi:38,sasl:[0,2,51],sasl_kwarg:[2,51],saslauthent:[0,2],saslauthprovid:[0,2,51],saslclient:0,satisfi:1,save:[0,9,10,34,35,37,38,41,44,50],scale:[0,26,41,46,49,52],scan:43,scenario:[0,36],schedul:[0,34],schema:[0,3,9,30,33,37,44,52],schema_event_refresh_window:3,schema_metadata_en:3,schema_trigg:0,schemapars:0,scope:[0,3,10],scratch:42,script:[0,40,46,49],scylla:[38,40,46,52],search:13,second:[0,3,10,26,27,30,31,32,38,41,44],secondari:[0,25,34,38],section:[0,38,40,45,47,49,51,52],secur:[45,52],see:[0,1,3,4,6,9,10,11,13,15,18,27,29,30,32,37,38,41,42,43,44,46,47,48,49,50,51,52],seen:[0,3,27],segment:40,select:[0,3,4,9,10,30,38,42,43,44,46,50,51,52,53],select_stat:4,self:[3,15,18,37,50,52,53],semant:[0,3],send:[0,1,2,3,5,27,44,45,52],sensibl:9,sensit:[0,9],sent:[0,1,2,3,29,44],sep:0,separ:[3,51],septemb:0,seq:43,sequenc:[0,3,4,14,17,27,30,32,44],sequenti:0,serd:0,serial:[0,1,3,12,15,18,30,41],serial_consistency_level:[3,15,18,30,42,44,47,52],serializ:3,serv:40,server:[0,1,2,3,9,15,18,25,29,30,33,38,44,47,48,52],server_authenticator_class:2,server_hostnam:51,server_nam:5,server_vers:43,servererror:27,servic:[2,51],service_timeout:21,session:[0,1,4,7,10,12,14,15,18,25,27,29,30,33,35,39,42,43,44,46,47,48,49,50,51,53],sesssion:0,set:[0,1,2,3,4,6,7,8,9,10,11,12,15,17,18,19,20,21,22,25,26,27,30,32,35,37,38,42,43,45,46,48,50,51,52],set_column:10,set_column__add:10,set_column__remov:10,set_core_connections_per_host:[3,4],set_default_connect:[7,35],set_keyspac:[0,3,27,44,53],set_max_connections_per_host:3,set_max_requests_per_connect:3,set_meta_refresh_en:3,set_min_requests_per_connect:3,set_sess:[0,7],set_source_analyt:[15,18],set_source_default:[15,18],set_source_graph:[15,18],set_stats_nam:26,set_verifi:51,setenv:46,setup:[0,7,10,35,37,38,39,40,44,46,48,51],setuptool:[0,46],sever:[0,38,40,44,46,49],shallow:[3,42],share:[0,3,19,20,21,22,42,49],shed:[15,18],shell:46,shift:41,shortcut:[3,46],should:[0,2,3,4,6,7,8,9,10,15,18,19,20,21,22,25,27,30,31,37,40,42,44,46,49,51,52],should_log:3,shouldn:0,show:[0,8,32,36,38,40,42,47,51],shown:[35,37,53],shuffl:38,shuffle_replica:27,shutdown:[0,3,39],side:[0,1,2,3,15,18,27,40],sign:[6,51],signal:39,signatur:1,significantli:38,silent:27,similar:[27,29,34,51],simpl:[0,6,15,18,27,30,38,40,41,44,46,49],simpleconvictionpolici:[3,27],simplegraphstat:[15,18],simpler:52,simplest:[38,44],simplestat:[0,3,15,18,30,44,50],simplestrategi:[8,25],simpli:[0,9,17,27,34,37,40,44,46,53],simplifi:[15,18],simultan:42,sinc:[0,9,29,31,32,36,38,41,43,52,53],singl:[0,3,4,6,8,9,10,14,25,27,28,30,32,37,38,40,42,44,46,47,52],single_object_row_factori:[15,18],site:[0,41],situat:[27,34,37],six:[0,46,52],size:[0,3,10,52],sizeti:0,sizetieredcompactionstrategi:9,skip:[0,9],slack:0,sleep:[27,37],slice:[0,3,38],slightli:0,slow:0,smaller:27,smallint:[0,6,44],smoke:0,snappi:46,snapshot:0,sni:5,sniendpoint:5,sniendpointfactori:5,so:[0,1,3,10,21,27,30,37,38,41,42,44,47,48,49,50,51,52],socket:[0,5,51],socket_famili:5,sockopt:3,soft:0,some:[0,1,9,15,18,27,34,37,38,41,44,45,46,47,48,50,51,52,53],some_id2:34,some_id:34,someth:[2,27,37,38,46,51],sometim:[0,10,15,18,27,46,50],somewher:[34,50],sort:[0,4,6,32,38],sortedset:[0,32,52],sourc:[0,3,15,18,45,46],source_elaps:[0,43],span:46,spark:0,spcifi:1,spec:41,special:[0,6,29,37,38,40,43],specif:[0,2,5,13,15,17,18,25,27,40,46,52,53],specifi:[0,1,3,6,8,9,10,11,12,27,29,30,32,35,37,38,40,41,42,44,51,52],specul:[0,27],speculative_execution_polici:[3,44],speculativeexecutionpolici:[27,44],speed:3,speedup:38,spell:41,spin:0,split:2,squar:47,ss:32,ssl:[0,5,44],ssl_context:[0,3,44,51],ssl_error_want_read:0,ssl_error_want_writ:0,ssl_opt:51,ssl_option:[0,3,5,51],ssl_version:51,sslcontext:[0,51],sstabl:43,sstable_size_in_mb:9,st:[3,37,53],stabil:0,stabl:0,stale:27,stall:0,standard:[0,19,20,26,38,39,41,44,46,51,52],start:[0,3,34,38,41,45,50,52],start_fetching_next_pag:[3,50],start_tim:3,startup:0,stat:[0,26],state:[0,3,10,20,27,34,47],stateless:50,statement:[0,3,25,27,33,34,36,41,42,43,47,50,53],statements_and_param:4,statements_and_paramet:4,stats_nam:26,statu:47,status_event_refresh_window:3,stddev:26,stdlib:0,step:[37,45],steroid:38,steve:10,still:[0,15,18,30,34,37,40,42,44,52,53],stmt:0,stop:[4,34],store:[0,1,6,9,30,37,41],str:[7,8,10,17,32,44],straightforward:[37,40,41,52],strategi:[0,40,52],stream:[0,29],stream_id:29,street:[3,11,37,52,53],stress:0,strict:[6,49],strictli:0,string:[0,1,2,3,6,12,13,15,17,18,25,26,27,29,30,32,41,44,51],string_typ:32,strip:0,strong:0,structur:[15,18,37],studio:46,stuff:[3,53],style:3,sub:[37,40],subclass:[0,1,2,3,27,30,37,51],submit:[0,43],submit_schema_refresh:52,submodul:[40,52],suboptim:27,subsequ:40,subset:38,substanc:39,substanti:[4,52],succe:[3,27],succeed:0,success:[0,1,2,3,4,10,27,30,44,46],successfulli:0,sudo:46,suffici:27,suggest:[44,46],suit:[0,51],suitabl:[2,17,25,36],suppli:[0,3,30,44,51,52],support:[0,1,2,3,8,9,10,12,27,32,34,36,38,41,44,45,50,51,52,53],supported_vers:1,suppos:[0,37,51],sure:[0,3,27,37,43,44,46,49,51],surfac:0,surround:0,swap:52,sy:0,sync:[9,35,37],sync_schema:0,sync_tabl:[0,8,10,35,37,48],sync_typ:[8,11,37],synch:8,synchron:[0,3,4,8,37,49,50],syntax:[0,10,34,38],syntaxexcept:0,system:[0,5,25,38,42,43,44,45,46,52],t:[0,9,10,31,37,38,43,44,47,49,51,52,53],tabl:[0,1,3,6,8,25,30,32,33,37,44,47,48,52,53],tablemetadata:[0,25,52],tag:[0,15,18],take:[0,3,4,8,9,15,18,27,35,44,46,51],taken:[15,18,40],tarbal:46,target:[0,13,15,18,27,46],task:[0,3,34,39],tear_up_couch:37,technic:40,techniqu:44,tell:53,tenant:41,term:27,tesla2012:38,tesla:[35,38],test2:10,test4:10,test:[0,10,21,22,27,31,35,46,47],test_clone_shared_lbp:0,test_clust:0,test_set_keyspace_twic:0,testifexistsmodel:9,testifnotexistsmodel:9,testmodel:38,testtransactionmodel:9,text:[0,3,6,9,10,11,13,35,36,37,38,40,44,48,52,53],than:[0,1,3,6,10,27,30,31,32,38,42,44,46,49,50,51],thei:[0,1,3,4,6,8,9,10,15,18,27,29,32,34,36,37,38,40,41,52,53],them:[0,3,27,38,40,41,44,46,47,48,52],themselv:[15,18],therefor:[36,38,46],thi:[0,1,2,3,4,5,6,7,8,9,10,11,12,13,15,17,18,19,20,21,22,25,26,27,28,29,30,31,32,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53],thing:[3,27,38,40,44],third:[2,41,48],thorough:[46,51],those:[0,3,26,27,30,42,46],though:52,thread:[0,3,4,44,46,49],threadpoolexecutor:0,three:[1,27,30,32,44,47],threshold:[0,3],thrift:0,throttl:0,through:[0,2,3,5,7,9,10,15,18,26,27,30,38,44,45,47,49,52,53],throughput:[0,4,49],thrown:34,thu:[10,27,30,47],ticket:51,time:[0,1,2,3,4,6,10,26,27,31,32,37,38,40,44,45,46,52],time__gt:38,time__lt:38,time_arg:32,timedata:9,timedelta:10,timedelta_or_datetim:9,timeout:[0,1,3,9,10,21,26,27,52],timer:[0,21,26],timestamp:[0,1,6,9,10,17,32,33,36,40,44,45],timestamp_gener:3,timestamp_na:41,timestamp_pres:41,timestamp_utc:41,timestamptyp:0,timeuuid:[0,6,10,32,37,44,52],timezon:[0,6,32,41],tinkerpop:[12,46],tinyint:[0,6,44],tip:45,tlsv1_method:51,tmp:42,to_python:0,todo:32,token:[0,2,3,13,27,33,43,46],token_fuzzi:13,token_map:0,token_metadata_en:3,token_prefix:13,token_regex:13,token_str:25,tokenawar:0,tokenawarepolici:[0,3,27,42],tokenawarerout:9,tokenfun:38,tokenmap:[0,25],toler:0,tolist:12,tombston:[3,36,43],tombstone_compaction_interv:9,tombstone_threshold:9,too:[0,3,27,41],took:1,tool:46,toolkit:29,top:[15,18,27],topo:0,topolog:[0,3,27,33],topology_event_refresh_window:3,total:[3,27],trace:[0,3,33],traceev:30,traceunavail:[3,30],tracing_en:0,track:0,tracker:45,trade:4,traffic:[0,44],trail:0,transact:[0,1,3,12,14,27,30,45],transform:37,transit:0,translat:[33,40,44],transpar:[3,44,50],trap:34,trash:0,travers:[12,14,15,18,46],traversal_batch:14,traversal_class:12,traversal_sourc:12,traversalbatch:[12,14],travisci:0,treat:[3,27,30,44,50],tree:3,tri:0,trigger:[0,3,27],truncat:[6,30,32,40],truncate_microsecond:6,truststor:51,truststore_password:51,truthi:27,ts:41,ttl:[0,9,10],ttl_in_sec:9,tunabl:49,tune:0,tupl:[0,1,3,4,9,12,17,25,27,30,38,44,52,53],tuple_factori:[0,3,16,29,30,42,44,52],turn:[3,43],twice:0,twist:[0,33,44],twistedconnect:[24,51],twistedreactor:[33,51],two:[0,1,3,13,27,29,32,38,44,46,51],txt:[0,46],type0:1,type1:1,type:[0,1,3,8,10,15,17,18,25,27,29,30,32,33,34,38,41,45,47],type_model:8,typeerror:[0,15,18],typestr:0,typic:[3,10,27,29,30,31,34,38,42,44],typo:0,tzinfo:41,u:[10,30,37,38,47],ubuntu:46,uda:0,udf:0,udt:[0,3,12,37],un:[0,30],unabl:[0,27,46],unauthor:[0,1],unavail:[0,1,26,27],uncal:0,unchang:40,unclean:52,uncompar:0,uncomplet:30,uncondit:0,undefinedkeyspaceexcept:40,under:[0,25,27,37,45],underscor:0,understand:51,understood:[3,27],underutil:0,unexpect:27,unexpectedli:0,unfamiliar:38,unhexlifi:0,unicod:[0,17,44],unicodedecodeerror:0,unif:0,unifi:[0,52],unintend:0,union:3,uniqu:[1,6,25,37,42],unit:[0,13,27],unix:[0,5,31,32,41],unix_socket_path:5,unix_time_from_uuid1:32,unixsocketendpoint:5,unknown:[0,15,18,46,52],unless:[3,6,27,35,52],unlik:41,unlog:30,unlogged_batch:27,unord:[6,25],unorder:0,unpack:[0,15,18,44],unprepar:53,unrecogn:0,unrecover:5,unreferenc:0,unregist:[0,53],unregister_connect:[7,35],unregister_listen:3,unreleas:0,unset:0,unset_valu:30,unspecifi:[0,9],unsupport:0,unsupportedoper:3,until:[0,2,3,4,7,37,43,44],untrust:3,unus:[0,46],unwis:10,up:[0,3,8,13,19,20,21,22,32,33,34,37,38,51,52],updat:[0,1,3,8,9,10,30,32,34,38,40,42,44,47],update_view_metadata:0,updatestat:0,upfront:29,upgrad:[45,48,51],upon:[3,37],upper:32,upper_bound:32,uppercas:0,us:[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,35,36,37,38,40,41,43,44,45,46,47,49,50,51],usag:[0,2,3,4,9,25,27,30,52],use_certificate_fil:51,use_client_timestamp:[0,1,3,52],use_list_t:6,use_privatekey_fil:51,use_set_t:6,used_hosts_per_remote_dc:27,usemap:6,user1:[44,51],user2:44,user3:44,user3_lookup:44,user:[0,1,3,4,6,8,9,10,17,18,25,30,33,38,40,44,45,46,50,51],user_act:3,user_id1:44,user_id2:44,user_id3:44,user_id:[4,9,30,38,44],user_ids_to_queri:44,user_lookup_stmt:44,user_row:[3,44,50],user_typ:[3,6],user_type_map:29,user_tz:41,useraggregatedescriptor:[1,3],userdefinedtyp:[0,6,37],userfunctiondescriptor:[1,3],usernam:[2,44,51],users_to_insert:30,usertyp:[0,6,25,33,37],usertypedoesnotexist:3,usual:[10,21,41,51],utc:[32,41],utc_datetime_from_ms_timestamp:32,utcfromtim:0,utcnow:[6,41],utctimetupl:41,utf8:0,utf8typ:0,utf:[0,6,17],util:[0,1,12,21,22,33,40,41,44,51,52],uuid1:[10,44],uuid4:[10,48],uuid:[0,6,9,10,32,37,38,40,44,48],uuid_arg:32,uuid_from_tim:[32,40],uwsgi:[43,48],uwsgidecor:[39,43],v1:[0,1,32],v2:[0,1,45],v3:[0,1,37,45],v4:[0,1,6,30],v5:[0,1],v6:1,v:[10,12,34,47],val1:17,val2:17,valid:[0,1,3,6,9,10,15,18,25,27,32,47,51],validationerror:[10,37,40],valu:[0,2,3,4,6,9,10,11,13,15,17,18,25,27,29,30,31,32,34,37,40,41,44,47,51,52,53],value2:32,value_typ:6,valueerror:[0,32],valuemap:12,values_list:[0,38],valuesequ:30,varchar:44,variabl:[0,6,9,44,46,51],variant:52,varint:[0,6,44],variou:[26,51],various:40,ve:[9,35,37,38],verb:40,verbatim:[15,18],veri:51,verif:0,verifi:0,verify_mod:51,verify_p:51,version:[0,1,2,3,6,25,29,30,31,32,37,40,44,45,46,50,52,53],vertex:[15,18],vertexproperti:[15,18],via:[0,3,37,46,50,51],view:[0,25,27,43],violat:10,virtual:[0,38],visit:45,visual:46,vnode:3,vs:[0,27],wa:[0,1,2,3,4,5,7,25,26,27,30,36,40,46,47,52],wai:[0,3,6,15,18,27,30,36,38,41,42,44,45,46,51,52],wait:[0,1,3,21,27,30,43,44,50],wait_for_all_pool:3,wait_for_complet:30,wake:21,want:[0,3,6,9,27,34,35,37,38,44,50,51,53],warn:[0,1,3,31,40,52],warn_on_drift:31,warning_interv:31,warning_threshold:31,was_appli:[0,3],watcher:21,we:[0,7,27,36,38,39,41,42,44,48,51,53],weakref:0,web_sess:50,well:[0,27,35,44,51],were:[0,1,3,4,19,25,27,30,36,37,40],what:[27,30,37,41,51,52,53],wheel:[0,46],when:[0,1,2,3,4,5,7,9,10,17,21,27,28,29,30,31,32,35,36,37,38,40,41,42,44,46,47,50,51,52,53],whenev:[3,50],where:[0,3,4,10,25,27,30,32,37,43,44,46,47,52],whether:[1,3,6,25,26,27,47],which:[0,1,3,9,10,25,27,29,30,34,35,36,38,40,44,46,49,51,52,53],whilst:0,whitelist:27,whitelistroundrobinpolici:[0,27,42,44,52],whitespac:25,who:27,whose:3,wider:[32,41],window:[0,32],wish:3,within:[0,1,3,10,13,27,30,34,41,42,44,52],withing:13,without:[0,1,3,9,10,38,41,44],wkt:[0,32],wno:46,won:37,word:[27,38],work:[0,2,7,17,27,30,32,37,38,44,45,47,48,51,53],workaround:[0,36,40],worker:[0,39],worker_process_init:39,working_keyspac:27,workload:[0,42,49],worth:46,would:[0,9,27,36,37,38,42,44,45,51,52],wrap:[12,27,44],wrap_socket:51,wrapper:[27,30],write:[0,1,8,10,15,18,26,27,30],write_request_timeout_in_m:1,write_timeout:26,write_typ:[1,27],writefailur:1,writetimeout:[0,1],writetyp:[0,1,27],written:0,wrong:[0,44],wunus:46,www:6,x509:51,x:[1,4,10,27,32,46,47],xcode:46,xrang:0,y:[0,10,27,32],yaml:[1,27],year:[10,32,35,38],year__gt:38,year__in:38,year__lt:38,yet:[3,38,44,52],yield:[4,27],you:[0,3,4,6,9,12,27,30,34,35,37,38,43,44,45,46,49,50,51,52,53],your:[0,3,6,9,35,37,38,40,43,44,47,48,49,50,51,52,53],yourself:49,yum:46,yyyi:[17,32],z:10,zero:0,zip:[52,53],zipcod:[3,11,37,52,53]},titles:["CHANGELOG","cassandra - Exceptions and Enums","cassandra.auth - Authentication","cassandra.cluster - Clusters and Sessions","cassandra.concurrent - Utilities for Concurrent Statement Execution","cassandra.connection - Low Level Connection Info","cassandra.cqlengine.columns - Column types for object mapping models","cassandra.cqlengine.connection - Connection management for cqlengine","cassandra.cqlengine.management - Schema management for cqlengine","cassandra.cqlengine.models - Table models for object mapping","cassandra.cqlengine.query - Query and filter model objects","cassandra.cqlengine.usertype - Model classes for User Defined Types","cassandra.datastax.graph.fluent","cassandra.datastax.graph.fluent.predicates","cassandra.datastax.graph.fluent.query","cassandra.datastax.graph - Graph Statements, Options, and Row Factories","cassandra.decoder - Data Return Formats","cassandra.encoder - Encoders for non-prepared Statements","cassandra.graph - Graph Statements, Options, and Row Factories","cassandra.io.asyncioreactor - asyncio Event Loop","cassandra.io.asyncorereactor - asyncore Event Loop","cassandra.io.eventletreactor - eventlet-compatible Connection","cassandra.io.geventreactor - gevent-compatible Event Loop","cassandra.io.libevreactor - libev Event Loop","cassandra.io.twistedreactor - Twisted Event Loop","cassandra.metadata - Schema and Ring Topology","cassandra.metrics - Performance Metrics","cassandra.policies - Load balancing and Failure Handling Policies","cassandra.pool - Hosts and Connection Pools","cassandra.protocol - Protocol Features","cassandra.query - Prepared Statements, Batch Statements, Tracing, and Row Factories","cassandra.timestamps - Timestamp Generation","cassandra.util - Utilities","API Documentation","Batch Queries","Connections","Frequently Asked Questions","Models","Making Queries","Third party integrations","Upgrade Guide","Working with Dates and Times","Execution Profiles","Frequently Asked Questions","Getting Started","DataStax Python Driver for Apache Cassandra\u00ae","Installation","Lightweight Transactions (Compare-and-set)","Object Mapper","Performance Notes","Paging Large Queries","Security","Upgrading","User Defined Types"],titleterms:{"0":[0,51,52],"0b1":0,"0b5":0,"0b6":0,"0b7":0,"0c1":0,"0c2":0,"0rc1":0,"1":[0,52],"10":0,"11":0,"12":0,"13":0,"14":0,"15":0,"16":[0,51],"17":0,"18":0,"19":0,"2":[0,52],"20":0,"21":0,"22":0,"3":[0,51,52],"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"class":[11,53],"default":[35,38,42,47,52],"do":43,"enum":1,"final":0,"float":40,"function":[38,40],"import":[40,52],"new":35,"return":[16,52],No:51,access:38,ad:42,address:27,alias:40,all:38,apach:45,api:[33,40,52],applic:43,ar:[38,52],ask:[36,43],asynchron:44,asyncio:19,asyncioreactor:19,asyncor:20,asyncorereactor:20,attach:52,auth:2,authent:[2,51,52],automat:52,balanc:27,base:[46,52],batch:[30,34,36,52],batchqueri:35,beta2:0,beta3:0,beta4:0,beta:0,bind:52,blist:52,bug:0,c:46,call:52,callback:[34,50],can:36,cassandra:[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,41,44,45,52],celeri:39,chang:[35,40,52],changelog:0,client:[51,52],cluster:[3,42,52],column:[6,40],compar:47,compat:[21,22],compress:46,concurr:4,configur:[46,51],connect:[5,7,21,28,35,43,44],consist:[44,52],consolid:40,content:[45,48],context:35,control:50,convers:44,core:33,correctli:36,cql:44,cqlengin:[6,7,8,9,10,11,40],custom:[29,51,52],cython:[46,49],data:16,datastax:[12,13,14,15,33,45,46],date:[40,41],datetyp:41,dead:27,decod:16,defin:[11,37,52,53],definit:37,delet:36,depend:[46,52],deprec:[0,40,52],deseri:29,determin:43,dict:53,dict_factori:47,dictionari:37,document:33,doe:43,don:36,doubl:40,down:27,driver:[33,43,45,52],dse:[51,52],encod:[17,52],error:46,event:[19,20,22,23,24],eventlet:[21,51],eventletreactor:21,exampl:[37,51],except:[1,40],execut:[4,34,42,44,51,52],execute_async:52,extend:37,extens:[46,49],extra:52,factori:[15,18,30],fail:27,failur:27,faster:29,featur:[0,29,52],field2:36,field:36,filter:[10,38],fix:0,fluent:[12,13,14],format:16,frequent:[36,43],from:[0,36,52],from_datetim:40,gener:[31,34],get:[44,45,48],gevent:22,geventreactor:22,graph:[12,13,14,15,18,33,46,52],guid:40,handl:[27,50],help:45,host:[27,28],how:[36,43],i:[36,43],idempot:27,ident:51,ignor:52,immut:38,individu:36,info:5,inform:52,inherit:[37,40],initi:42,instal:[46,52],instanc:[35,37,42],instanti:36,integr:39,io:[19,20,21,22,23,24,43],issu:45,larg:50,legaci:42,level:[5,40,44,52],libev:[23,46],libevreactor:23,lightweight:[47,52],list:[38,40],load:27,local_on:52,log:34,login:51,loop:[19,20,22,23,24],low:5,lower:51,make:38,manag:[7,8,35,40,43],manipul:37,manual:46,map:[6,9,42,53],mapper:[33,48],mark:27,merg:0,metadata:[25,52],metric:[26,46],model:[6,9,10,11,35,36,37,40],modul:52,multiprocess:49,my:43,name:[38,42,52],named_tuple_factori:47,nativ:52,node:27,non:[17,46,52],normal:52,note:[46,49],now:52,object:[6,9,10,33,38,48],oper:[27,38,43],option:[15,18,46],order:[36,38],organ:40,osx:46,other:0,overload:40,packag:40,page:[50,52],paramet:[42,44,52],parti:39,pass:[42,44],path:41,pattern:34,payload:29,per:38,perform:[26,49],pip:46,platform:46,polici:27,pool:28,predic:13,prepar:[17,30,44,52],prepend:40,preserv:36,profil:42,protocol:[29,51,52],proxi:51,pypi:49,python:[45,46],queri:[10,14,30,34,36,38,43,44,50,52],queryset:[10,35,38],question:[36,43],read:41,reconnect:27,regist:[35,53],remov:[40,52],replica:43,report:45,request:43,result:[47,50,52],resum:50,retri:[27,43],retriev:38,revers:40,ring:25,row:[15,18,30,36],sasl:52,schema:[8,25,40],secur:51,select:35,server:[27,51],session:[3,52],set:[44,47],sever:52,shutdown:52,side:52,size:50,soft:52,special:47,specul:44,speed:46,ssl:[46,51],start:[44,48],statement:[4,15,17,18,30,44,52],support:46,t:36,tabl:[9,38],them:53,third:39,through:46,time:41,timeout:[38,43],timestamp:[31,41,52],timeuuid:[38,40],token:[25,38],topolog:25,trace:[30,43,52],transact:[47,52],translat:27,ttl:38,tuple_factori:47,twist:[24,51],twistedreactor:24,type:[6,11,37,40,44,52,53],udt:53,unicodemixin:40,unifi:51,unlog:34,unregist:35,up:[27,46],updat:[36,52],upgrad:[0,40,52],us:[34,42,52,53],user:[11,37,52,53],usertyp:11,util:[4,32],uwsgi:39,v1:51,v2:52,v3:52,valid:37,valu:[36,38],value2:36,verif:51,verifi:[46,51],version:51,vs:34,why:[36,43],window:46,without:[42,53],work:[36,41,52],write:41,wsgi:43,x:[0,52],your:46}}) \ No newline at end of file diff --git a/3.21.0-scylla/security.html b/3.21.0-scylla/security.html new file mode 100644 index 0000000000..cb8b785ecd --- /dev/null +++ b/3.21.0-scylla/security.html @@ -0,0 +1,1027 @@ + + + + + + + + + + + + + Security | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

Security

+

The two main security components you will use with the +Python driver are Authentication and SSL.

+
+

Authentication

+

Versions 2.0 and higher of the driver support a SASL-based +authentication mechanism when protocol_version +is set to 2 or higher. To use this authentication, set +auth_provider to an instance of a subclass +of AuthProvider. When working +with Cassandra’s PasswordAuthenticator, you can use +the PlainTextAuthProvider class.

+

For example, suppose Cassandra is setup with its default +‘cassandra’ user with a password of ‘cassandra’:

+
from cassandra.cluster import Cluster
+from cassandra.auth import PlainTextAuthProvider
+
+auth_provider = PlainTextAuthProvider(username='cassandra', password='cassandra')
+cluster = Cluster(auth_provider=auth_provider, protocol_version=2)
+
+
+
+

Custom Authenticators

+

If you’re using something other than Cassandra’s PasswordAuthenticator, +SaslAuthProvider is provided for generic SASL authentication mechanisms, +utilizing the pure-sasl package. +If these do not suit your needs, you may need to create your own subclasses of +AuthProvider and Authenticator. You can use the Sasl classes +as example implementations.

+
+
+

Protocol v1 Authentication

+

When working with Cassandra 1.2 (or a higher version with +protocol_version set to 1), you will not pass in +an AuthProvider instance. Instead, you should pass in a +function that takes one argument, the IP address of a host, and returns +a dict of credentials with a username and password key:

+
from cassandra.cluster import Cluster
+
+def get_credentials(host_address):
+    return {'username': 'joe', 'password': '1234'}
+
+cluster = Cluster(auth_provider=get_credentials, protocol_version=1)
+
+
+
+
+
+

SSL

+

SSL should be used when client encryption is enabled in Cassandra.

+

To give you as much control as possible over your SSL configuration, our SSL +API takes a user-created SSLContext instance from the Python standard library. +These docs will include some examples for how to achieve common configurations, +but the ssl.SSLContext documentation +gives a more complete description of what is possible.

+

To enable SSL with version 3.17.0 and higher, you will need to set Cluster.ssl_context to a +ssl.SSLContext instance to enable SSL. Optionally, you can also set Cluster.ssl_options +to a dict of options. These will be passed as kwargs to ssl.SSLContext.wrap_socket() +when new sockets are created.

+

If you create your SSLContext using ssl.create_default_context, +be aware that SSLContext.check_hostname is set to True by default, so the hostname validation will be done +by Python and not the driver. For this reason, we need to set the server_hostname at best effort, which is the +resolved ip address. If this validation needs to be done against the FQDN, consider enabling it using the ssl_options +as described in the following examples or implement your own EndPoint and +EndPointFactory.

+

The following examples assume you have generated your Cassandra certificate and +keystore files with these intructions:

+ +

It might be also useful to learn about the different levels of identity verification to understand the examples:

+ +
+

SSL with Twisted or Eventlet

+

Twisted and Eventlet both use an alternative SSL implementation called pyOpenSSL, so if your Cluster’s connection class is +TwistedConnection or EventletConnection, you must pass a +pyOpenSSL context instead. +An example is provided in these docs, and more details can be found in the +documentation. +pyOpenSSL is not installed by the driver and must be installed separately.

+
+
+

SSL Configuration Examples

+

Here, we’ll describe the server and driver configuration necessary to set up SSL to meet various goals, such as the client verifying the server and the server verifying the client. We’ll also include Python code demonstrating how to use servers and drivers configured in these ways.

+
+

No identity verification

+

No identity verification at all. Note that this is not recommended for for production deployments.

+

The Cassandra configuration:

+
client_encryption_options:
+  enabled: true
+  keystore: /path/to/127.0.0.1.keystore
+  keystore_password: myStorePass
+  require_client_auth: false
+
+
+

The driver configuration:

+
from cassandra.cluster import Cluster, Session
+from ssl import SSLContext, PROTOCOL_TLSv1
+
+ssl_context = SSLContext(PROTOCOL_TLSv1)
+
+cluster = Cluster(['127.0.0.1'], ssl_context=ssl_context)
+session = cluster.connect()
+
+
+
+
+

Client verifies server

+

Ensure the python driver verifies the identity of the server.

+

The Cassandra configuration:

+
client_encryption_options:
+  enabled: true
+  keystore: /path/to/127.0.0.1.keystore
+  keystore_password: myStorePass
+  require_client_auth: false
+
+
+

For the driver configuration, it’s very important to set ssl_context.verify_mode +to CERT_REQUIRED. Otherwise, the loaded verify certificate will have no effect:

+
from cassandra.cluster import Cluster, Session
+from ssl import SSLContext, PROTOCOL_TLSv1, CERT_REQUIRED
+
+ssl_context = SSLContext(PROTOCOL_TLSv1)
+ssl_context.load_verify_locations('/path/to/rootca.crt')
+ssl_context.verify_mode = CERT_REQUIRED
+
+cluster = Cluster(['127.0.0.1'], ssl_context=ssl_context)
+session = cluster.connect()
+
+
+

Additionally, you can also force the driver to verify the hostname of the server by passing additional options to ssl_context.wrap_socket via the ssl_options kwarg:

+
from cassandra.cluster import Cluster, Session
+from ssl import SSLContext, PROTOCOL_TLSv1, CERT_REQUIRED
+
+ssl_context = SSLContext(PROTOCOL_TLSv1)
+ssl_context.load_verify_locations('/path/to/rootca.crt')
+ssl_context.verify_mode = CERT_REQUIRED
+ssl_context.check_hostname = True
+ssl_options = {'server_hostname': '127.0.0.1'}
+
+cluster = Cluster(['127.0.0.1'], ssl_context=ssl_context, ssl_options=ssl_options)
+session = cluster.connect()
+
+
+
+
+

Server verifies client

+

If Cassandra is configured to verify clients (require_client_auth), you need to generate +SSL key and certificate files.

+

The cassandra configuration:

+
client_encryption_options:
+  enabled: true
+  keystore: /path/to/127.0.0.1.keystore
+  keystore_password: myStorePass
+  require_client_auth: true
+  truststore: /path/to/dse-truststore.jks
+  truststore_password: myStorePass
+
+
+

The Python ssl APIs require the certificate in PEM format. First, create a certificate +conf file:

+
cat > gen_client_cert.conf <<EOF
+[ req ]
+distinguished_name = req_distinguished_name
+prompt = no
+output_password = ${ROOT_CERT_PASS}
+default_bits = 2048
+
+[ req_distinguished_name ]
+C = ${CERT_COUNTRY}
+O = ${CERT_ORG_NAME}
+OU = ${CERT_OU}
+CN = client
+EOF
+
+
+

Make sure you replaced the variables with the same values you used for the initial +root CA certificate. Then, generate the key:

+
openssl req -newkey rsa:2048 -nodes -keyout client.key -out client.csr -config gen_client_cert.conf
+
+
+

And generate the client signed certificate:

+
openssl x509 -req -CA ${ROOT_CA_BASE_NAME}.crt -CAkey ${ROOT_CA_BASE_NAME}.key -passin pass:${ROOT_CERT_PASS} \
+    -in client.csr -out client.crt_signed -days ${CERT_VALIDITY} -CAcreateserial
+
+
+

Finally, you can use that configuration with the following driver code:

+
from cassandra.cluster import Cluster, Session
+from ssl import SSLContext, PROTOCOL_TLSv1
+
+ssl_context = SSLContext(PROTOCOL_TLSv1)
+ssl_context.load_cert_chain(
+    certfile='/path/to/client.crt_signed',
+    keyfile='/path/to/client.key')
+
+cluster = Cluster(['127.0.0.1'], ssl_context=ssl_context)
+session = cluster.connect()
+
+
+
+
+

Server verifies client and client verifies server

+

See the previous section for examples of Cassandra configuration and preparing +the client certificates.

+

The following driver code specifies that the connection should use two-way verification:

+
from cassandra.cluster import Cluster, Session
+from ssl import SSLContext, PROTOCOL_TLSv1, CERT_REQUIRED
+
+ssl_context = SSLContext(PROTOCOL_TLSv1)
+ssl_context.load_verify_locations('/path/to/rootca.crt')
+ssl_context.verify_mode = CERT_REQUIRED
+ssl_context.load_cert_chain(
+    certfile='/path/to/client.crt_signed',
+    keyfile='/path/to/client.key')
+
+cluster = Cluster(['127.0.0.1'], ssl_context=ssl_context)
+session = cluster.connect()
+
+
+

The driver uses SSLContext directly to give you many other options in configuring SSL. Consider reading the Python SSL documentation +for more details about SSLContext configuration.

+

Server verifies client and client verifies server using Twisted and pyOpenSSL

+
from OpenSSL import SSL, crypto
+from cassandra.cluster import Cluster
+from cassandra.io.twistedreactor import TwistedConnection
+
+ssl_context = SSL.Context(SSL.TLSv1_METHOD)
+ssl_context.set_verify(SSL.VERIFY_PEER, callback=lambda _1, _2, _3, _4, ok: ok)
+ssl_context.use_certificate_file('/path/to/client.crt_signed')
+ssl_context.use_privatekey_file('/path/to/client.key')
+ssl_context.load_verify_locations('/path/to/rootca.crt')
+
+cluster = Cluster(
+    contact_points=['127.0.0.1'],
+    connection_class=TwistedConnection,
+    ssl_context=ssl_context,
+    ssl_options={'check_hostname': True}
+)
+session = cluster.connect()
+
+
+

Connecting using Eventlet would look similar except instead of importing and using TwistedConnection, you would +import and use EventletConnection, including the appropriate monkey-patching.

+
+
+
+

Versions 3.16.0 and lower

+

To enable SSL you will need to set Cluster.ssl_options to a +dict of options. These will be passed as kwargs to ssl.wrap_socket() +when new sockets are created. Note that this use of ssl_options will be +deprecated in the next major release.

+

By default, a ca_certs value should be supplied (the value should be +a string pointing to the location of the CA certs file), and you probably +want to specify ssl_version as ssl.PROTOCOL_TLSv1 to match +Cassandra’s default protocol.

+

For example:

+
from cassandra.cluster import Cluster
+from ssl import PROTOCOL_TLSv1, CERT_REQUIRED
+
+ssl_opts = {
+    'ca_certs': '/path/to/my/ca.certs',
+    'ssl_version': PROTOCOL_TLSv1,
+    'cert_reqs': CERT_REQUIRED  # Certificates are required and validated
+}
+cluster = Cluster(ssl_options=ssl_opts)
+
+
+

This is only an example to show how to pass the ssl parameters. Consider reading +the python ssl documentation for +your configuration. For further reading, Andrew Mussey has published a thorough guide on +Using SSL with the DataStax Python driver.

+
+

SSL with Twisted

+

In case the twisted event loop is used pyOpenSSL must be installed or an exception will be risen. Also +to set the ssl_version and cert_reqs in ssl_opts the appropriate constants from pyOpenSSL are expected.

+
+
+
+
+

DSE Authentication

+

When authenticating against DSE, the Cassandra driver provides two auth providers that work both with legacy kerberos and Cassandra authenticators, +as well as the new DSE Unified Authentication. This allows client to configure this auth provider independently, +and in advance of any server upgrade. These auth providers are configured in the same way as any previous implementation:

+
from cassandra.auth import DSEGSSAPIAuthProvider
+auth_provider = DSEGSSAPIAuthProvider(service='dse', qops=["auth"])
+cluster = Cluster(auth_provider=auth_provider)
+session = cluster.connect()
+
+
+

Implementations are DSEPlainTextAuthProvider, DSEGSSAPIAuthProvider and SaslAuthProvider.

+
+

DSE Unified Authentication

+

With DSE (>=5.1), unified Authentication allows you to:

+
    +
  • Proxy Login: Authenticate using a fixed set of authentication credentials but allow authorization of resources based another user id.

  • +
  • Proxy Execute: Authenticate using a fixed set of authentication credentials but execute requests based on another user id.

  • +
+
+

Proxy Login

+

Proxy login allows you to authenticate with a user but act as another one. You need to ensure the authenticated user has the permission to use the authorization of resources of the other user. ie. this example will allow the server user to authenticate as usual but use the authorization of user1:

+
GRANT PROXY.LOGIN on role user1 to server
+
+
+

then you can do the proxy authentication….

+
from cassandra.cluster import Cluster
+from cassandra.auth import SaslAuthProvider
+
+sasl_kwargs = {
+  "service": 'dse',
+  "mechanism":"PLAIN",
+  "username": 'server',
+  'password': 'server',
+  'authorization_id': 'user1'
+}
+
+auth_provider = SaslAuthProvider(**sasl_kwargs)
+c = Cluster(auth_provider=auth_provider)
+s = c.connect()
+s.execute(...)  # all requests will be executed as 'user1'
+
+
+

If you are using kerberos, you can use directly DSEGSSAPIAuthProvider and pass the authorization_id, like this:

+
from cassandra.cluster import Cluster
+from cassandra.auth import DSEGSSAPIAuthProvider
+
+# Ensure the kerberos ticket of the server user is set with the kinit utility.
+auth_provider = DSEGSSAPIAuthProvider(service='dse', qops=["auth"], principal="server@DATASTAX.COM",
+                                      authorization_id='user1@DATASTAX.COM')
+c = Cluster(auth_provider=auth_provider)
+s = c.connect()
+s.execute(...)  # all requests will be executed as 'user1'
+
+
+
+
+

Proxy Execute

+

Proxy execute allows you to execute requests as another user than the authenticated one. You need to ensure the authenticated user has the permission to use the authorization of resources of the specified user. ie. this example will allow the server user to execute requests as user1:

+
GRANT PROXY.EXECUTE on role user1 to server
+
+
+

then you can do a proxy execute…

+
from cassandra.cluster import Cluster
+from cassandra.auth import DSEPlainTextAuthProvider,
+
+auth_provider = DSEPlainTextAuthProvider('server', 'server')
+
+c = Cluster(auth_provider=auth_provider)
+s = c.connect()
+s.execute('select * from k.t;', execute_as='user1')  # the request will be executed as 'user1'
+
+
+

Please see the official documentation for more details on the feature and configuration process.

+
+
+
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.21.0-scylla/sitemap.xml b/3.21.0-scylla/sitemap.xml new file mode 100644 index 0000000000..0ea98441a9 --- /dev/null +++ b/3.21.0-scylla/sitemap.xml @@ -0,0 +1,2 @@ + +https://python-driver.docs.scylladb.com/stable/CHANGELOG.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/auth.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/cluster.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/concurrent.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/connection.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/cqlengine/columns.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/cqlengine/connection.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/cqlengine/management.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/cqlengine/models.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/cqlengine/query.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/cqlengine/usertype.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/datastax/graph/fluent/index.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/datastax/graph/fluent/predicates.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/datastax/graph/fluent/query.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/datastax/graph/index.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/decoder.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/encoder.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/graph.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/io/asyncioreactor.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/io/asyncorereactor.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/io/eventletreactor.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/io/geventreactor.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/io/libevreactor.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/io/twistedreactor.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/metadata.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/metrics.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/policies.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/pool.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/protocol.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/query.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/timestamps.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/util.htmlhttps://python-driver.docs.scylladb.com/stable/api/index.htmlhttps://python-driver.docs.scylladb.com/stable/cqlengine/batches.htmlhttps://python-driver.docs.scylladb.com/stable/cqlengine/connections.htmlhttps://python-driver.docs.scylladb.com/stable/cqlengine/faq.htmlhttps://python-driver.docs.scylladb.com/stable/cqlengine/models.htmlhttps://python-driver.docs.scylladb.com/stable/cqlengine/queryset.htmlhttps://python-driver.docs.scylladb.com/stable/cqlengine/third_party.htmlhttps://python-driver.docs.scylladb.com/stable/cqlengine/upgrade_guide.htmlhttps://python-driver.docs.scylladb.com/stable/dates_and_times.htmlhttps://python-driver.docs.scylladb.com/stable/execution_profiles.htmlhttps://python-driver.docs.scylladb.com/stable/faq.htmlhttps://python-driver.docs.scylladb.com/stable/getting_started.htmlhttps://python-driver.docs.scylladb.com/stable/index.htmlhttps://python-driver.docs.scylladb.com/stable/installation.htmlhttps://python-driver.docs.scylladb.com/stable/lwt.htmlhttps://python-driver.docs.scylladb.com/stable/object_mapper.htmlhttps://python-driver.docs.scylladb.com/stable/performance.htmlhttps://python-driver.docs.scylladb.com/stable/query_paging.htmlhttps://python-driver.docs.scylladb.com/stable/security.htmlhttps://python-driver.docs.scylladb.com/stable/upgrading.htmlhttps://python-driver.docs.scylladb.com/stable/user_defined_types.htmlhttps://python-driver.docs.scylladb.com/stable/py-modindex.htmlhttps://python-driver.docs.scylladb.com/stable/404.htmlhttps://python-driver.docs.scylladb.com/stable/search.html \ No newline at end of file diff --git a/3.21.0-scylla/upgrading.html b/3.21.0-scylla/upgrading.html new file mode 100644 index 0000000000..6f8f274a2c --- /dev/null +++ b/3.21.0-scylla/upgrading.html @@ -0,0 +1,1026 @@ + + + + + + + + + + + + + Upgrading | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

Upgrading

+
+
+
+

Upgrading from dse-driver

+

Since 3.21.0, scylla-driver fully supports DataStax products. dse-driver and +dse-graph users should now migrate to scylla-driver to benefit from latest bug fixes +and new features. The upgrade to this new unified driver version is straightforward +with no major API changes.

+
+

Installation

+

Only the scylla-driver package should be installed. dse-driver and dse-graph +are not required anymore:

+
pip install scylla-driver
+
+
+

If you need the Graph Fluent API (features provided by dse-graph):

+
pip install scylla-driver[graph]
+
+
+

See Installation for more details.

+
+
+

Import from the cassandra module

+

There is no dse module, so you should import from the cassandra module. You +need to change only the first module of your import statements, not the submodules.

+
from dse.cluster import Cluster, EXEC_PROFILE_GRAPH_DEFAULT
+from dse.auth import PlainTextAuthProvider
+from dse.policies import WhiteListRoundRobinPolicy
+
+# becomes
+
+from cassandra.cluster import Cluster, EXEC_PROFILE_GRAPH_DEFAULT
+from cassandra.auth import PlainTextAuthProvider
+from cassandra.policies import WhiteListRoundRobinPolicy
+
+
+

Also note that the cassandra.hosts module doesn’t exist in scylla-driver. This +module is named cassandra.pool.

+
+
+

dse-graph

+

dse-graph features are now built into scylla-driver. The only change you need +to do is your import statements:

+
from dse_graph import ..
+from dse_graph.query import ..
+
+# becomes
+
+from cassandra.datastax.graph.fluent import ..
+from cassandra.datastax.graph.fluent.query import ..
+
+
+

See fluent.

+
+
+

Session.execute and Session.execute_async API

+

Although it is not common to use this API with positional arguments, it is +important to be aware that the host and execute_as parameters have had +their positional order swapped. This is only because execute_as was added +in dse-driver before host.

+

See Session.execute().

+
+
+

Deprecations

+

These changes are optional, but recommended:

+
    +
  • Importing from cassandra.graph is deprecated. Consider importing from cassandra.datastax.graph.

  • +
  • Use DefaultLoadBalancingPolicy instead of DSELoadBalancingPolicy.

  • +
+
+
+
+

Upgrading to 3.0

+

Version 3.0 of the DataStax Python driver for Apache Cassandra +adds support for Cassandra 3.0 while maintaining support for +previously supported versions. In addition to substantial internal rework, +there are several updates to the API that integrators will need +to consider:

+
+

Default consistency is now LOCAL_ONE

+

Previous value was ONE. The new value is introduced to mesh with the default +DC-aware load balancing policy and to match other drivers.

+
+
+

Execution API Updates

+
+

Result return normalization

+

PYTHON-368

+

Previously results would be returned as a list of rows for result rows +up to fetch_size, and PagedResult afterward. This could break +application code that assumed one type and got another.

+

Now, all results are returned as an iterable ResultSet.

+

The preferred way to consume results of unknown size is to iterate through +them, letting automatic paging occur as they are consumed.

+
results = session.execute("SELECT * FROM system.local")
+for row in results:
+    process(row)
+
+
+

If the expected size of the results is known, it is still possible to +materialize a list using the iterator:

+
results = session.execute("SELECT * FROM system.local")
+row_list = list(results)
+
+
+

For backward compatibility, ResultSet supports indexing. When +accessed at an index, a ~.ResultSet object will materialize all its pages:

+
results = session.execute("SELECT * FROM system.local")
+first_result = results[0]  # materializes results, fetching all pages
+
+
+

This can send requests and load (possibly large) results into memory, so +~.ResultSet will log a warning on implicit materialization.

+
+
+

Trace information is not attached to executed Statements

+

PYTHON-318

+

Previously trace data was attached to Statements if tracing was enabled. This +could lead to confusion if the same statement was used for multiple executions.

+

Now, trace data is associated with the ResponseFuture and ResultSet +returned for each query:

+

ResponseFuture.get_query_trace()

+

ResponseFuture.get_all_query_traces()

+

ResultSet.get_query_trace()

+

ResultSet.get_all_query_traces()

+
+
+

Binding named parameters now ignores extra names

+

PYTHON-178

+

Previously, BoundStatement.bind() would raise if a mapping +was passed with extra names not found in the prepared statement.

+

Behavior in 3.0+ is to ignore extra names.

+
+
+
+

blist removed as soft dependency

+

PYTHON-385

+

Previously the driver had a soft dependency on blist sortedset, using +that where available and using an internal fallback where possible.

+

Now, the driver never chooses the blist variant, instead returning the +internal util.SortedSet for all set results. The class implements +all standard set operations, so no integration code should need to change unless +it explicitly checks for sortedset type.

+
+
+

Metadata API Updates

+

PYTHON-276, PYTHON-408, PYTHON-400, PYTHON-422

+

Cassandra 3.0 brought a substantial overhaul to the internal schema metadata representation. +This version of the driver supports that metadata in addition to the legacy version. Doing so +also brought some changes to the metadata model.

+

The present API is documented: cassandra.metadata. Changes highlighted below:

+
    +
  • All types are now exposed as CQL types instead of types derived from the internal server implementation

  • +
  • Some metadata attributes have changed names to match current nomenclature (for example, Index.kind in place of Index.type).

  • +
  • Some metadata attributes removed

    +
      +
    • TableMetadata.keyspace reference replaced with TableMetadata.keyspace_name

    • +
    • ColumnMetadata.index is removed table- and keyspace-level mappings are still maintained

    • +
    +
  • +
+
+
+

Several deprecated features are removed

+

PYTHON-292

+
    +
  • ResponseFuture.result timeout parameter is removed, use Session.execute timeout instead (031ebb0)

  • +
  • Cluster.refresh_schema removed, use Cluster.refresh_*_metadata instead (419fcdf)

  • +
  • Cluster.submit_schema_refresh removed (574266d)

  • +
  • cqltypes time/date functions removed, use util entry points instead (bb984ee)

  • +
  • decoder module removed (e16a073)

  • +
  • TableMetadata.keyspace attribute replaced with keyspace_name (cc94073)

  • +
  • cqlengine.columns.TimeUUID.from_datetime removed, use util variant instead (96489cc)

  • +
  • cqlengine.columns.Float(double_precision) parameter removed, use columns.Double instead (a2d3a98)

  • +
  • cqlengine keyspace management functions are removed in favor of the strategy-specific entry points (4bd5909)

  • +
  • cqlengine.Model.__polymorphic_*__ attributes removed, use __discriminator* attributes instead (9d98c8e)

  • +
  • cqlengine.statements will no longer warn about list list prepend behavior (79efe97)

  • +
+
+
+
+

Upgrading to 2.1 from 2.0

+

Version 2.1 of the DataStax Python driver for Apache Cassandra +adds support for Cassandra 2.1 and version 3 of the native protocol.

+

Cassandra 1.2, 2.0, and 2.1 are all supported. However, 1.2 only +supports protocol version 1, and 2.0 only supports versions 1 and +2, so some features may not be available.

+
+

Using the v3 Native Protocol

+

By default, the driver will attempt to use version 2 of the +native protocol. To use version 3, you must explicitly +set the protocol_version:

+
from cassandra.cluster import Cluster
+
+cluster = Cluster(protocol_version=3)
+
+
+

Note that protocol version 3 is only supported by Cassandra 2.1+.

+

In future releases, the driver may default to using protocol version +3.

+
+
+

Working with User-Defined Types

+

Cassandra 2.1 introduced the ability to define new types:

+
USE KEYSPACE mykeyspace;
+
+CREATE TYPE address (street text, city text, zip int);
+
+
+

The driver generally expects you to use instances of a specific +class to represent column values of this type. You can let the +driver know what class to use with Cluster.register_user_type():

+
cluster = Cluster()
+
+class Address(object):
+
+    def __init__(self, street, city, zipcode):
+        self.street = street
+        self.city = text
+        self.zipcode = zipcode
+
+cluster.register_user_type('mykeyspace', 'address', Address)
+
+
+

When inserting data for address columns, you should pass in +instances of Address. When querying data, address column +values will be instances of Address.

+

If no class is registered for a user-defined type, query results +will use a namedtuple class and data may only be inserted +though prepared statements.

+

See User Defined Types for more details.

+
+
+

Customizing Encoders for Non-prepared Statements

+

Starting with version 2.1 of the driver, it is possible to customize +how Python types are converted to CQL literals when working with +non-prepared statements. This is done on a per-Session +basis through Session.encoder:

+
cluster = Cluster()
+session = cluster.connect()
+session.encoder.mapping[tuple] = session.encoder.cql_encode_tuple
+
+
+

See Type Conversions for the table of default CQL literal conversions.

+
+
+

Using Client-Side Protocol-Level Timestamps

+

With version 3 of the native protocol, timestamps may be supplied by the +client at the protocol level. (Normally, if they are not specified within +the CQL query itself, a timestamp is generated server-side.)

+

When protocol_version is set to 3 or higher, the driver +will automatically use client-side timestamps with microsecond precision +unless Session.use_client_timestamp is changed to False. +If a timestamp is specified within the CQL query, it will override the +timestamp generated by the driver.

+
+
+
+

Upgrading to 2.0 from 1.x

+

Version 2.0 of the DataStax Python driver for Apache Cassandra +includes some notable improvements over version 1.x. This version +of the driver supports Cassandra 1.2, 2.0, and 2.1. However, not +all features may be used with Cassandra 1.2, and some new features +in 2.1 are not yet supported.

+
+

Using the v2 Native Protocol

+

By default, the driver will attempt to use version 2 of Cassandra’s +native protocol. You can explicitly set the protocol version to +2, though:

+
from cassandra.cluster import Cluster
+
+cluster = Cluster(protocol_version=2)
+
+
+

When working with Cassandra 1.2, you will need to +explicitly set the protocol_version to 1:

+
from cassandra.cluster import Cluster
+
+cluster = Cluster(protocol_version=1)
+
+
+
+
+

Automatic Query Paging

+

Version 2 of the native protocol adds support for automatic query +paging, which can make dealing with large result sets much simpler.

+

See Paging Large Queries for full details.

+
+
+

Protocol-Level Batch Statements

+

With version 1 of the native protocol, batching of statements required +using a BATCH cql query. +With version 2 of the native protocol, you can now batch statements at +the protocol level. This allows you to use many different prepared +statements within a single batch.

+

See BatchStatement for details and usage examples.

+
+
+

SASL-based Authentication

+

Also new in version 2 of the native protocol is SASL-based authentication. +See the section on Security for details and examples.

+
+
+

Lightweight Transactions

+

Lightweight transactions are another new feature. To use lightweight transactions, add IF clauses +to your CQL queries and set the serial_consistency_level +on your statements.

+
+
+

Calling Cluster.shutdown()

+

In order to fix some issues around garbage collection and unclean interpreter +shutdowns, version 2.0 of the driver requires you to call Cluster.shutdown() +on your Cluster objects when you are through with them. +This helps to guarantee a clean shutdown.

+
+
+

Deprecations

+

The following functions have moved from cassandra.decoder to cassandra.query. +The original functions have been left in place with a DeprecationWarning for +now:

+ +
+
+

Dependency Changes

+

The following dependencies have officially been made optional:

+
    +
  • scales

  • +
  • blist

  • +
+

And one new dependency has been added (to enable Python 3 support):

+
    +
  • six

  • +
+
+
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.21.0-scylla/user_defined_types.html b/3.21.0-scylla/user_defined_types.html new file mode 100644 index 0000000000..6b2542696d --- /dev/null +++ b/3.21.0-scylla/user_defined_types.html @@ -0,0 +1,756 @@ + + + + + + + + + + + + + User Defined Types | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

User Defined Types

+

Cassandra 2.1 introduced user-defined types (UDTs). You can create a +new type through CREATE TYPE statements in CQL:

+
CREATE TYPE address (street text, zip int);
+
+
+

Version 2.1 of the Python driver adds support for user-defined types.

+
+

Registering a UDT

+

You can tell the Python driver to return columns of a specific UDT as +instances of a class or a dict by registering them with your Cluster +instance through Cluster.register_user_type():

+
+

Map a Class to a UDT

+
cluster = Cluster(protocol_version=3)
+session = cluster.connect()
+session.set_keyspace('mykeyspace')
+session.execute("CREATE TYPE address (street text, zipcode int)")
+session.execute("CREATE TABLE users (id int PRIMARY KEY, location frozen<address>)")
+
+# create a class to map to the "address" UDT
+class Address(object):
+
+    def __init__(self, street, zipcode):
+        self.street = street
+        self.zipcode = zipcode
+
+cluster.register_user_type('mykeyspace', 'address', Address)
+
+# insert a row using an instance of Address
+session.execute("INSERT INTO users (id, location) VALUES (%s, %s)",
+                (0, Address("123 Main St.", 78723)))
+
+# results will include Address instances
+results = session.execute("SELECT * FROM users")
+row = results[0]
+print(row.id, row.location.street, row.location.zipcode)
+
+
+
+
+

Map a dict to a UDT

+
cluster = Cluster(protocol_version=3)
+session = cluster.connect()
+session.set_keyspace('mykeyspace')
+session.execute("CREATE TYPE address (street text, zipcode int)")
+session.execute("CREATE TABLE users (id int PRIMARY KEY, location frozen<address>)")
+
+cluster.register_user_type('mykeyspace', 'address', dict)
+
+# insert a row using a prepared statement and a tuple
+insert_statement = session.prepare("INSERT INTO mykeyspace.users (id, location) VALUES (?, ?)")
+session.execute(insert_statement, [0, ("123 Main St.", 78723)])
+
+# results will include dict instances
+results = session.execute("SELECT * FROM users")
+row = results[0]
+print(row.id, row.location['street'], row.location['zipcode'])
+
+
+
+
+
+

Using UDTs Without Registering Them

+

Although it is recommended to register your types with +Cluster.register_user_type(), the driver gives you some options +for working with unregistered UDTS.

+

When you use prepared statements, the driver knows what data types to +expect for each placeholder. This allows you to pass any object you +want for a UDT, as long as it has attributes that match the field names +for the UDT:

+
cluster = Cluster(protocol_version=3)
+session = cluster.connect()
+session.set_keyspace('mykeyspace')
+session.execute("CREATE TYPE address (street text, zipcode int)")
+session.execute("CREATE TABLE users (id int PRIMARY KEY, location frozen<address>)")
+
+class Foo(object):
+
+    def __init__(self, street, zipcode, otherstuff):
+        self.street = street
+        self.zipcode = zipcode
+        self.otherstuff = otherstuff
+
+insert_statement = session.prepare("INSERT INTO users (id, location) VALUES (?, ?)")
+
+# since we're using a prepared statement, we don't *have* to register
+# a class to map to the UDT to insert data.  The object just needs to have
+# "street" and "zipcode" attributes (which Foo does):
+session.execute(insert_statement, [0, Foo("123 Main St.", 78723, "some other stuff")])
+
+# when we query data, UDT columns that don't have a class registered
+# will be returned as namedtuples:
+results = session.execute("SELECT * FROM users")
+first_row = results[0]
+address = first_row.location
+print(address)  # prints "Address(street='123 Main St.', zipcode=78723)"
+street = address.street
+zipcode = address.street
+
+
+

As shown in the code example, inserting data for UDT columns without registering +a class works fine for prepared statements. However, you must register a +class to insert UDT columns with unprepared statements.* You can still query +UDT columns without registered classes using unprepared statements, they will +simply return namedtuple instances (just like prepared statements do).

+

* this applies to parameterized unprepared statements, in which the driver will be formatting parameters – not statements with interpolated UDT literals.

+
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.22.3-scylla/.buildinfo b/3.22.3-scylla/.buildinfo new file mode 100644 index 0000000000..be00da77e8 --- /dev/null +++ b/3.22.3-scylla/.buildinfo @@ -0,0 +1,4 @@ +# Sphinx build info version 1 +# This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done. +config: cf8c8838978b25b85039f42a8d9277b5 +tags: 645f666f9bcd5a90fca523b33c5a78b7 diff --git a/3.22.3-scylla/.doctrees/CHANGELOG.doctree b/3.22.3-scylla/.doctrees/CHANGELOG.doctree new file mode 100644 index 0000000000..b2f07eef5c Binary files /dev/null and b/3.22.3-scylla/.doctrees/CHANGELOG.doctree differ diff --git a/3.22.3-scylla/.doctrees/api/cassandra.doctree b/3.22.3-scylla/.doctrees/api/cassandra.doctree new file mode 100644 index 0000000000..0c3e119d13 Binary files /dev/null and b/3.22.3-scylla/.doctrees/api/cassandra.doctree differ diff --git a/3.22.3-scylla/.doctrees/api/cassandra/auth.doctree b/3.22.3-scylla/.doctrees/api/cassandra/auth.doctree new file mode 100644 index 0000000000..57ca89c228 Binary files /dev/null and b/3.22.3-scylla/.doctrees/api/cassandra/auth.doctree differ diff --git a/3.22.3-scylla/.doctrees/api/cassandra/cluster.doctree b/3.22.3-scylla/.doctrees/api/cassandra/cluster.doctree new file mode 100644 index 0000000000..fffb5cea72 Binary files /dev/null and b/3.22.3-scylla/.doctrees/api/cassandra/cluster.doctree differ diff --git a/3.22.3-scylla/.doctrees/api/cassandra/concurrent.doctree b/3.22.3-scylla/.doctrees/api/cassandra/concurrent.doctree new file mode 100644 index 0000000000..740fdd8747 Binary files /dev/null and b/3.22.3-scylla/.doctrees/api/cassandra/concurrent.doctree differ diff --git a/3.22.3-scylla/.doctrees/api/cassandra/connection.doctree b/3.22.3-scylla/.doctrees/api/cassandra/connection.doctree new file mode 100644 index 0000000000..f5836e6c38 Binary files /dev/null and b/3.22.3-scylla/.doctrees/api/cassandra/connection.doctree differ diff --git a/3.22.3-scylla/.doctrees/api/cassandra/cqlengine/columns.doctree b/3.22.3-scylla/.doctrees/api/cassandra/cqlengine/columns.doctree new file mode 100644 index 0000000000..de15171fcb Binary files /dev/null and b/3.22.3-scylla/.doctrees/api/cassandra/cqlengine/columns.doctree differ diff --git a/3.22.3-scylla/.doctrees/api/cassandra/cqlengine/connection.doctree b/3.22.3-scylla/.doctrees/api/cassandra/cqlengine/connection.doctree new file mode 100644 index 0000000000..b53d71ea80 Binary files /dev/null and b/3.22.3-scylla/.doctrees/api/cassandra/cqlengine/connection.doctree differ diff --git a/3.22.3-scylla/.doctrees/api/cassandra/cqlengine/management.doctree b/3.22.3-scylla/.doctrees/api/cassandra/cqlengine/management.doctree new file mode 100644 index 0000000000..4c75a37e27 Binary files /dev/null and b/3.22.3-scylla/.doctrees/api/cassandra/cqlengine/management.doctree differ diff --git a/3.22.3-scylla/.doctrees/api/cassandra/cqlengine/models.doctree b/3.22.3-scylla/.doctrees/api/cassandra/cqlengine/models.doctree new file mode 100644 index 0000000000..6c6e6367b4 Binary files /dev/null and b/3.22.3-scylla/.doctrees/api/cassandra/cqlengine/models.doctree differ diff --git a/3.22.3-scylla/.doctrees/api/cassandra/cqlengine/query.doctree b/3.22.3-scylla/.doctrees/api/cassandra/cqlengine/query.doctree new file mode 100644 index 0000000000..3b1df6d92b Binary files /dev/null and b/3.22.3-scylla/.doctrees/api/cassandra/cqlengine/query.doctree differ diff --git a/3.22.3-scylla/.doctrees/api/cassandra/cqlengine/usertype.doctree b/3.22.3-scylla/.doctrees/api/cassandra/cqlengine/usertype.doctree new file mode 100644 index 0000000000..706c5ea4c4 Binary files /dev/null and b/3.22.3-scylla/.doctrees/api/cassandra/cqlengine/usertype.doctree differ diff --git a/3.22.3-scylla/.doctrees/api/cassandra/datastax/graph/fluent/index.doctree b/3.22.3-scylla/.doctrees/api/cassandra/datastax/graph/fluent/index.doctree new file mode 100644 index 0000000000..354f8ffccf Binary files /dev/null and b/3.22.3-scylla/.doctrees/api/cassandra/datastax/graph/fluent/index.doctree differ diff --git a/3.22.3-scylla/.doctrees/api/cassandra/datastax/graph/fluent/predicates.doctree b/3.22.3-scylla/.doctrees/api/cassandra/datastax/graph/fluent/predicates.doctree new file mode 100644 index 0000000000..0e10988450 Binary files /dev/null and b/3.22.3-scylla/.doctrees/api/cassandra/datastax/graph/fluent/predicates.doctree differ diff --git a/3.22.3-scylla/.doctrees/api/cassandra/datastax/graph/fluent/query.doctree b/3.22.3-scylla/.doctrees/api/cassandra/datastax/graph/fluent/query.doctree new file mode 100644 index 0000000000..e1a492fcce Binary files /dev/null and b/3.22.3-scylla/.doctrees/api/cassandra/datastax/graph/fluent/query.doctree differ diff --git a/3.22.3-scylla/.doctrees/api/cassandra/datastax/graph/index.doctree b/3.22.3-scylla/.doctrees/api/cassandra/datastax/graph/index.doctree new file mode 100644 index 0000000000..c1e915cbae Binary files /dev/null and b/3.22.3-scylla/.doctrees/api/cassandra/datastax/graph/index.doctree differ diff --git a/3.22.3-scylla/.doctrees/api/cassandra/decoder.doctree b/3.22.3-scylla/.doctrees/api/cassandra/decoder.doctree new file mode 100644 index 0000000000..f20765c0f3 Binary files /dev/null and b/3.22.3-scylla/.doctrees/api/cassandra/decoder.doctree differ diff --git a/3.22.3-scylla/.doctrees/api/cassandra/encoder.doctree b/3.22.3-scylla/.doctrees/api/cassandra/encoder.doctree new file mode 100644 index 0000000000..d56a740d9a Binary files /dev/null and b/3.22.3-scylla/.doctrees/api/cassandra/encoder.doctree differ diff --git a/3.22.3-scylla/.doctrees/api/cassandra/graph.doctree b/3.22.3-scylla/.doctrees/api/cassandra/graph.doctree new file mode 100644 index 0000000000..08cd587434 Binary files /dev/null and b/3.22.3-scylla/.doctrees/api/cassandra/graph.doctree differ diff --git a/3.22.3-scylla/.doctrees/api/cassandra/io/asyncioreactor.doctree b/3.22.3-scylla/.doctrees/api/cassandra/io/asyncioreactor.doctree new file mode 100644 index 0000000000..b9ca726ce9 Binary files /dev/null and b/3.22.3-scylla/.doctrees/api/cassandra/io/asyncioreactor.doctree differ diff --git a/3.22.3-scylla/.doctrees/api/cassandra/io/asyncorereactor.doctree b/3.22.3-scylla/.doctrees/api/cassandra/io/asyncorereactor.doctree new file mode 100644 index 0000000000..ecb41a90d5 Binary files /dev/null and b/3.22.3-scylla/.doctrees/api/cassandra/io/asyncorereactor.doctree differ diff --git a/3.22.3-scylla/.doctrees/api/cassandra/io/eventletreactor.doctree b/3.22.3-scylla/.doctrees/api/cassandra/io/eventletreactor.doctree new file mode 100644 index 0000000000..d2845c6f48 Binary files /dev/null and b/3.22.3-scylla/.doctrees/api/cassandra/io/eventletreactor.doctree differ diff --git a/3.22.3-scylla/.doctrees/api/cassandra/io/geventreactor.doctree b/3.22.3-scylla/.doctrees/api/cassandra/io/geventreactor.doctree new file mode 100644 index 0000000000..80a10661b1 Binary files /dev/null and b/3.22.3-scylla/.doctrees/api/cassandra/io/geventreactor.doctree differ diff --git a/3.22.3-scylla/.doctrees/api/cassandra/io/libevreactor.doctree b/3.22.3-scylla/.doctrees/api/cassandra/io/libevreactor.doctree new file mode 100644 index 0000000000..1e0ff5b029 Binary files /dev/null and b/3.22.3-scylla/.doctrees/api/cassandra/io/libevreactor.doctree differ diff --git a/3.22.3-scylla/.doctrees/api/cassandra/io/twistedreactor.doctree b/3.22.3-scylla/.doctrees/api/cassandra/io/twistedreactor.doctree new file mode 100644 index 0000000000..446cd75791 Binary files /dev/null and b/3.22.3-scylla/.doctrees/api/cassandra/io/twistedreactor.doctree differ diff --git a/3.22.3-scylla/.doctrees/api/cassandra/metadata.doctree b/3.22.3-scylla/.doctrees/api/cassandra/metadata.doctree new file mode 100644 index 0000000000..8ea199fbd9 Binary files /dev/null and b/3.22.3-scylla/.doctrees/api/cassandra/metadata.doctree differ diff --git a/3.22.3-scylla/.doctrees/api/cassandra/metrics.doctree b/3.22.3-scylla/.doctrees/api/cassandra/metrics.doctree new file mode 100644 index 0000000000..973261fd82 Binary files /dev/null and b/3.22.3-scylla/.doctrees/api/cassandra/metrics.doctree differ diff --git a/3.22.3-scylla/.doctrees/api/cassandra/policies.doctree b/3.22.3-scylla/.doctrees/api/cassandra/policies.doctree new file mode 100644 index 0000000000..41466036da Binary files /dev/null and b/3.22.3-scylla/.doctrees/api/cassandra/policies.doctree differ diff --git a/3.22.3-scylla/.doctrees/api/cassandra/pool.doctree b/3.22.3-scylla/.doctrees/api/cassandra/pool.doctree new file mode 100644 index 0000000000..0dd6fa31ee Binary files /dev/null and b/3.22.3-scylla/.doctrees/api/cassandra/pool.doctree differ diff --git a/3.22.3-scylla/.doctrees/api/cassandra/protocol.doctree b/3.22.3-scylla/.doctrees/api/cassandra/protocol.doctree new file mode 100644 index 0000000000..c7f3754714 Binary files /dev/null and b/3.22.3-scylla/.doctrees/api/cassandra/protocol.doctree differ diff --git a/3.22.3-scylla/.doctrees/api/cassandra/query.doctree b/3.22.3-scylla/.doctrees/api/cassandra/query.doctree new file mode 100644 index 0000000000..ee651df77e Binary files /dev/null and b/3.22.3-scylla/.doctrees/api/cassandra/query.doctree differ diff --git a/3.22.3-scylla/.doctrees/api/cassandra/timestamps.doctree b/3.22.3-scylla/.doctrees/api/cassandra/timestamps.doctree new file mode 100644 index 0000000000..48465d5f11 Binary files /dev/null and b/3.22.3-scylla/.doctrees/api/cassandra/timestamps.doctree differ diff --git a/3.22.3-scylla/.doctrees/api/cassandra/util.doctree b/3.22.3-scylla/.doctrees/api/cassandra/util.doctree new file mode 100644 index 0000000000..173505b1d9 Binary files /dev/null and b/3.22.3-scylla/.doctrees/api/cassandra/util.doctree differ diff --git a/3.22.3-scylla/.doctrees/api/index.doctree b/3.22.3-scylla/.doctrees/api/index.doctree new file mode 100644 index 0000000000..a7e7ebd133 Binary files /dev/null and b/3.22.3-scylla/.doctrees/api/index.doctree differ diff --git a/3.22.3-scylla/.doctrees/cqlengine/batches.doctree b/3.22.3-scylla/.doctrees/cqlengine/batches.doctree new file mode 100644 index 0000000000..526f61de71 Binary files /dev/null and b/3.22.3-scylla/.doctrees/cqlengine/batches.doctree differ diff --git a/3.22.3-scylla/.doctrees/cqlengine/connections.doctree b/3.22.3-scylla/.doctrees/cqlengine/connections.doctree new file mode 100644 index 0000000000..aa52730e94 Binary files /dev/null and b/3.22.3-scylla/.doctrees/cqlengine/connections.doctree differ diff --git a/3.22.3-scylla/.doctrees/cqlengine/faq.doctree b/3.22.3-scylla/.doctrees/cqlengine/faq.doctree new file mode 100644 index 0000000000..a34e1f7c42 Binary files /dev/null and b/3.22.3-scylla/.doctrees/cqlengine/faq.doctree differ diff --git a/3.22.3-scylla/.doctrees/cqlengine/models.doctree b/3.22.3-scylla/.doctrees/cqlengine/models.doctree new file mode 100644 index 0000000000..13e59f8ec2 Binary files /dev/null and b/3.22.3-scylla/.doctrees/cqlengine/models.doctree differ diff --git a/3.22.3-scylla/.doctrees/cqlengine/queryset.doctree b/3.22.3-scylla/.doctrees/cqlengine/queryset.doctree new file mode 100644 index 0000000000..213b79897d Binary files /dev/null and b/3.22.3-scylla/.doctrees/cqlengine/queryset.doctree differ diff --git a/3.22.3-scylla/.doctrees/cqlengine/third_party.doctree b/3.22.3-scylla/.doctrees/cqlengine/third_party.doctree new file mode 100644 index 0000000000..ff5ecefd5e Binary files /dev/null and b/3.22.3-scylla/.doctrees/cqlengine/third_party.doctree differ diff --git a/3.22.3-scylla/.doctrees/cqlengine/upgrade_guide.doctree b/3.22.3-scylla/.doctrees/cqlengine/upgrade_guide.doctree new file mode 100644 index 0000000000..5cc3eeb63a Binary files /dev/null and b/3.22.3-scylla/.doctrees/cqlengine/upgrade_guide.doctree differ diff --git a/3.22.3-scylla/.doctrees/dates_and_times.doctree b/3.22.3-scylla/.doctrees/dates_and_times.doctree new file mode 100644 index 0000000000..72529a85a3 Binary files /dev/null and b/3.22.3-scylla/.doctrees/dates_and_times.doctree differ diff --git a/3.22.3-scylla/.doctrees/environment.pickle b/3.22.3-scylla/.doctrees/environment.pickle new file mode 100644 index 0000000000..6c898b045a Binary files /dev/null and b/3.22.3-scylla/.doctrees/environment.pickle differ diff --git a/3.22.3-scylla/.doctrees/execution_profiles.doctree b/3.22.3-scylla/.doctrees/execution_profiles.doctree new file mode 100644 index 0000000000..e3f1966ca6 Binary files /dev/null and b/3.22.3-scylla/.doctrees/execution_profiles.doctree differ diff --git a/3.22.3-scylla/.doctrees/faq.doctree b/3.22.3-scylla/.doctrees/faq.doctree new file mode 100644 index 0000000000..ddd2ee1ac7 Binary files /dev/null and b/3.22.3-scylla/.doctrees/faq.doctree differ diff --git a/3.22.3-scylla/.doctrees/getting_started.doctree b/3.22.3-scylla/.doctrees/getting_started.doctree new file mode 100644 index 0000000000..7c159e4d59 Binary files /dev/null and b/3.22.3-scylla/.doctrees/getting_started.doctree differ diff --git a/3.22.3-scylla/.doctrees/index.doctree b/3.22.3-scylla/.doctrees/index.doctree new file mode 100644 index 0000000000..bd6b999d4c Binary files /dev/null and b/3.22.3-scylla/.doctrees/index.doctree differ diff --git a/3.22.3-scylla/.doctrees/installation.doctree b/3.22.3-scylla/.doctrees/installation.doctree new file mode 100644 index 0000000000..78645677fd Binary files /dev/null and b/3.22.3-scylla/.doctrees/installation.doctree differ diff --git a/3.22.3-scylla/.doctrees/lwt.doctree b/3.22.3-scylla/.doctrees/lwt.doctree new file mode 100644 index 0000000000..047e4b8607 Binary files /dev/null and b/3.22.3-scylla/.doctrees/lwt.doctree differ diff --git a/3.22.3-scylla/.doctrees/object_mapper.doctree b/3.22.3-scylla/.doctrees/object_mapper.doctree new file mode 100644 index 0000000000..250390be1f Binary files /dev/null and b/3.22.3-scylla/.doctrees/object_mapper.doctree differ diff --git a/3.22.3-scylla/.doctrees/performance.doctree b/3.22.3-scylla/.doctrees/performance.doctree new file mode 100644 index 0000000000..4bae6fe014 Binary files /dev/null and b/3.22.3-scylla/.doctrees/performance.doctree differ diff --git a/3.22.3-scylla/.doctrees/query_paging.doctree b/3.22.3-scylla/.doctrees/query_paging.doctree new file mode 100644 index 0000000000..ff569536d0 Binary files /dev/null and b/3.22.3-scylla/.doctrees/query_paging.doctree differ diff --git a/3.22.3-scylla/.doctrees/scylla_cloud.doctree b/3.22.3-scylla/.doctrees/scylla_cloud.doctree new file mode 100644 index 0000000000..cac280624c Binary files /dev/null and b/3.22.3-scylla/.doctrees/scylla_cloud.doctree differ diff --git a/3.22.3-scylla/.doctrees/scylla_specific.doctree b/3.22.3-scylla/.doctrees/scylla_specific.doctree new file mode 100644 index 0000000000..abb647522c Binary files /dev/null and b/3.22.3-scylla/.doctrees/scylla_specific.doctree differ diff --git a/3.22.3-scylla/.doctrees/security.doctree b/3.22.3-scylla/.doctrees/security.doctree new file mode 100644 index 0000000000..1b6796edf1 Binary files /dev/null and b/3.22.3-scylla/.doctrees/security.doctree differ diff --git a/3.22.3-scylla/.doctrees/upgrading.doctree b/3.22.3-scylla/.doctrees/upgrading.doctree new file mode 100644 index 0000000000..99d42eb839 Binary files /dev/null and b/3.22.3-scylla/.doctrees/upgrading.doctree differ diff --git a/3.22.3-scylla/.doctrees/user_defined_types.doctree b/3.22.3-scylla/.doctrees/user_defined_types.doctree new file mode 100644 index 0000000000..5a44071bd6 Binary files /dev/null and b/3.22.3-scylla/.doctrees/user_defined_types.doctree differ diff --git a/3.22.3-scylla/.nojekyll b/3.22.3-scylla/.nojekyll new file mode 100644 index 0000000000..e69de29bb2 diff --git a/3.22.3-scylla/404.html b/3.22.3-scylla/404.html new file mode 100644 index 0000000000..d60936cbfe --- /dev/null +++ b/3.22.3-scylla/404.html @@ -0,0 +1,31 @@ + + + + + + + + + ScyllaDB + + + + + + + + + + + +
+

404

+

The ScyllaDB monster ate your page!

+

+ Home +

+
+ + + \ No newline at end of file diff --git a/3.22.3-scylla/CHANGELOG.html b/3.22.3-scylla/CHANGELOG.html new file mode 100644 index 0000000000..4d4c363561 --- /dev/null +++ b/3.22.3-scylla/CHANGELOG.html @@ -0,0 +1,2828 @@ + + + + + + + + + + + + + CHANGELOG | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

CHANGELOG

+
+

3.22.0

+

February 26, 2020

+
+

Features

+
    +
  • Add all() function to the ResultSet API (PYTHON-1203)

  • +
  • Parse new schema metadata in NGDG and generate table edges CQL syntax (PYTHON-996)

  • +
  • Add GraphSON3 support (PYTHON-788)

  • +
  • Use GraphSON3 as default for Native graphs (PYTHON-1004)

  • +
  • Add Tuple and UDT types for native graph (PYTHON-1005)

  • +
  • Add Duration type for native graph (PYTHON-1000)

  • +
  • Add gx:ByteBuffer graphson type support for Blob field (PYTHON-1027)

  • +
  • Enable Paging Through DSE Driver for Gremlin Traversals (PYTHON-1045)

  • +
  • Provide numerical wrappers to ensure proper graphson schema definition (PYTHON-1051)

  • +
  • Resolve the row_factory automatically for native graphs (PYTHON-1056)

  • +
  • Add g:TraversalMetrics/g:Metrics graph deserializers (PYTHON-1057)

  • +
  • Add g:BulkSet graph deserializers (PYTHON-1060)

  • +
  • Update Graph Engine names and the way to create a Classic/Native Graph (PYTHON-1090)

  • +
  • Update Native to Core Graph Engine

  • +
  • Add graphson3 and native graph support (PYTHON-1039)

  • +
  • Enable Paging Through DSE Driver for Gremlin Traversals (PYTHON-1045)

  • +
  • Expose filter predicates for cql collections (PYTHON-1019)

  • +
  • Add g:TraversalMetrics/Metrics deserializers (PYTHON-1057)

  • +
  • Make graph metadata handling more robust (PYTHON-1204)

  • +
+
+
+

Bug Fixes

+
    +
  • Make sure to only query the native_transport_address column with DSE (PYTHON-1205)

  • +
+
+
+
+

3.21.0

+

January 15, 2020

+
+

Features

+
    +
  • Unified driver: merge core and DSE drivers into a single package (PYTHON-1130)

  • +
  • Add Python 3.8 support (PYTHON-1189)

  • +
  • Allow passing ssl context for Twisted (PYTHON-1161)

  • +
  • Ssl context and cloud support for Eventlet (PYTHON-1162)

  • +
  • Cloud Twisted support (PYTHON-1163)

  • +
  • Add additional_write_policy and read_repair to system schema parsing (PYTHON-1048)

  • +
  • Flexible version parsing (PYTHON-1174)

  • +
  • Support NULL in collection deserializer (PYTHON-1123)

  • +
  • [GRAPH] Ability to execute Fluent Graph queries asynchronously (PYTHON-1129)

  • +
+
+
+

Bug Fixes

+
    +
  • Handle prepared id mismatch when repreparing on the fly (PYTHON-1124)

  • +
  • re-raising the CQLEngineException will fail on Python 3 (PYTHON-1166)

  • +
  • asyncio message chunks can be processed discontinuously (PYTHON-1185)

  • +
  • Reconnect attempts persist after downed node removed from peers (PYTHON-1181)

  • +
  • Connection fails to validate ssl certificate hostname when SSLContext.check_hostname is set (PYTHON-1186)

  • +
  • ResponseFuture._set_result crashes on connection error when used with PrepareMessage (PYTHON-1187)

  • +
  • Insights fail to serialize the startup message when the SSL Context is from PyOpenSSL (PYTHON-1192)

  • +
+
+
+

Others

+
    +
  • The driver has a new dependency: geomet. It comes from the dse-driver unification and +is used to support DSE geo types.

  • +
  • Remove *read_repair_chance table options (PYTHON-1140)

  • +
  • Avoid warnings about unspecified load balancing policy when connecting to a cloud cluster (PYTHON-1177)

  • +
  • Add new DSE CQL keywords (PYTHON-1122)

  • +
  • Publish binary wheel distributions (PYTHON-1013)

  • +
+
+
+

Deprecations

+
    +
  • DSELoadBalancingPolicy will be removed in the next major, consider using +the DefaultLoadBalancingPolicy.

  • +
+

Merged from dse-driver:

+
+
+

Features

+
    +
  • Insights integration (PYTHON-1047)

  • +
  • Graph execution profiles should preserve their graph_source when graph_options is overridden (PYTHON-1021)

  • +
  • Add NodeSync metadata (PYTHON-799)

  • +
  • Add new NodeSync failure values (PYTHON-934)

  • +
  • DETERMINISTIC and MONOTONIC Clauses for Functions and Aggregates (PYTHON-955)

  • +
  • GraphOptions should show a warning for unknown parameters (PYTHON-819)

  • +
  • DSE protocol version 2 and continous paging backpressure (PYTHON-798)

  • +
  • GraphSON2 Serialization/Deserialization Support (PYTHON-775)

  • +
  • Add graph-results payload option for GraphSON format (PYTHON-773)

  • +
  • Create an AuthProvider for the DSE transitional mode (PYTHON-831)

  • +
  • Implement serializers for the Graph String API (PYTHON-778)

  • +
  • Provide deserializers for GraphSON types (PYTHON-782)

  • +
  • Add Graph DurationType support (PYTHON-607)

  • +
  • Support DSE DateRange type (PYTHON-668)

  • +
  • RLAC CQL output for materialized views (PYTHON-682)

  • +
  • Add Geom Types wkt deserializer

  • +
  • DSE Graph Client timeouts in custom payload (PYTHON-589)

  • +
  • Make DSEGSSAPIAuthProvider accept principal name (PYTHON-574)

  • +
  • Add config profiles to DSE graph execution (PYTHON-570)

  • +
  • DSE Driver version checking (PYTHON-568)

  • +
  • Distinct default timeout for graph queries (PYTHON-477)

  • +
  • Graph result parsing for known types (PYTHON-479,487)

  • +
  • Distinct read/write CL for graph execution (PYTHON-509)

  • +
  • Target graph analytics query to spark master when available (PYTHON-510)

  • +
+
+
+

Bug Fixes

+
    +
  • Continuous paging sessions raise RuntimeError when results are not entirely consumed (PYTHON-1054)

  • +
  • GraphSON Property deserializer should return a dict instead of a set (PYTHON-1033)

  • +
  • ResponseFuture.has_more_pages may hold the wrong value (PYTHON-946)

  • +
  • DETERMINISTIC clause in AGGREGATE misplaced in CQL generation (PYTHON-963)

  • +
  • graph module import cause a DLL issue on Windows due to its cythonizing failure (PYTHON-900)

  • +
  • Update date serialization to isoformat in graph (PYTHON-805)

  • +
  • DateRange Parse Error (PYTHON-729)

  • +
  • MontonicTimestampGenerator.__init__ ignores class defaults (PYTHON-728)

  • +
  • metadata.get_host returning None unexpectedly (PYTHON-709)

  • +
  • Sockets associated with sessions not getting cleaned up on session.shutdown() (PYTHON-673)

  • +
  • Resolve FQDN from ip address and use that as host passed to SASLClient (PYTHON-566)

  • +
  • Geospatial type implementations don’t handle ‘EMPTY’ values. (PYTHON-481)

  • +
  • Correctly handle other types in geo type equality (PYTHON-508)

  • +
+
+
+

Other

+
    +
  • Add tests around cqlengine and continuous paging (PYTHON-872)

  • +
  • Add an abstract GraphStatement to handle different graph statements (PYTHON-789)

  • +
  • Write documentation examples for DSE 2.0 features (PYTHON-732)

  • +
  • DSE_V1 protocol should not include all of protocol v5 (PYTHON-694)

  • +
+
+
+
+

3.20.2

+

November 19, 2019

+
+

Bug Fixes

+
    +
  • Fix import error for old python installation without SSLContext (PYTHON-1183)

  • +
+
+
+
+

3.20.1

+

November 6, 2019

+
+

Bug Fixes

+
    +
  • ValueError: too many values to unpack (expected 2)” when there are two dashes in server version number (PYTHON-1172)

  • +
+
+
+
+

3.20.0

+

October 28, 2019

+
+

Features

+
    +
  • DataStax Apollo Support (PYTHON-1074)

  • +
  • Use 4.0 schema parser in 4 alpha and snapshot builds (PYTHON-1158)

  • +
+
+
+

Bug Fixes

+
    +
  • Connection setup methods prevent using ExecutionProfile in cqlengine (PYTHON-1009)

  • +
  • Driver deadlock if all connections dropped by heartbeat whilst request in flight and request times out (PYTHON-1044)

  • +
  • Exception when use pk__token__gt filter In python 3.7 (PYTHON-1121)

  • +
+
+
+
+

3.19.0

+

August 26, 2019

+
+

Features

+
    +
  • Add Python 3.7 support (PYTHON-1016)

  • +
  • Future-proof Mapping imports (PYTHON-1023)

  • +
  • Include param values in cqlengine logging (PYTHON-1105)

  • +
  • NTS Token Replica Map Generation is slow (PYTHON-622)

  • +
+
+
+

Bug Fixes

+
    +
  • as_cql_query UDF/UDA parameters incorrectly includes “frozen” if arguments are collections (PYTHON-1031)

  • +
  • cqlengine does not currently support combining TTL and TIMESTAMP on INSERT (PYTHON-1093)

  • +
  • Fix incorrect metadata for compact counter tables (PYTHON-1100)

  • +
  • Call ConnectionException with correct kwargs (PYTHON-1117)

  • +
  • Can’t connect to clusters built from source because version parsing doesn’t handle ‘x.y-SNAPSHOT’ (PYTHON-1118)

  • +
  • Discovered node doesn´t honor the configured Cluster port on connection (PYTHON-1127)

  • +
  • Exception when use pk__token__gt filter In python 3.7 (PYTHON-1121)

  • +
+
+
+

Other

+
    +
  • Remove invalid warning in set_session when we initialize a default connection (PYTHON-1104)

  • +
  • Set the proper default ExecutionProfile.row_factory value (PYTHON-1119)

  • +
+
+
+
+

3.18.0

+

May 27, 2019

+
+

Features

+
    +
  • Abstract Host Connection information (PYTHON-1079)

  • +
  • Improve version parsing to support a non-integer 4th component (PYTHON-1091)

  • +
  • Expose on_request_error method in the RetryPolicy (PYTHON-1064)

  • +
  • Add jitter to ExponentialReconnectionPolicy (PYTHON-1065)

  • +
+
+
+

Bug Fixes

+
    +
  • Fix error when preparing queries with beta protocol v5 (PYTHON-1081)

  • +
  • Accept legacy empty strings as column names (PYTHON-1082)

  • +
  • Let util.SortedSet handle uncomparable elements (PYTHON-1087)

  • +
+
+
+
+

3.17.1

+

May 2, 2019

+
+

Bug Fixes

+
    +
  • Socket errors EAGAIN/EWOULDBLOCK are not handled properly and cause timeouts (PYTHON-1089)

  • +
+
+
+
+

3.17.0

+

February 19, 2019

+
+

Features

+
    +
  • Send driver name and version in startup message (PYTHON-1068)

  • +
  • Add Cluster ssl_context option to enable SSL (PYTHON-995)

  • +
  • Allow encrypted private keys for 2-way SSL cluster connections (PYTHON-995)

  • +
  • Introduce new method ConsistencyLevel.is_serial (PYTHON-1067)

  • +
  • Add Session.get_execution_profile (PYTHON-932)

  • +
  • Add host kwarg to Session.execute/execute_async APIs to send a query to a specific node (PYTHON-993)

  • +
+
+
+

Bug Fixes

+
    +
  • NoHostAvailable when all hosts are up and connectable (PYTHON-891)

  • +
  • Serial consistency level is not used (PYTHON-1007)

  • +
+
+
+

Other

+
    +
  • Fail faster on incorrect lz4 import (PYTHON-1042)

  • +
  • Bump Cython dependency version to 0.29 (PYTHON-1036)

  • +
  • Expand Driver SSL Documentation (PYTHON-740)

  • +
+
+
+

Deprecations

+
    +
  • Using Cluster.ssl_options to enable SSL is deprecated and will be removed in +the next major release, use ssl_context.

  • +
  • DowngradingConsistencyRetryPolicy is deprecated and will be +removed in the next major release. (PYTHON-937)

  • +
+
+
+
+

3.16.0

+

November 12, 2018

+
+

Bug Fixes

+
    +
  • Improve and fix socket error-catching code in nonblocking-socket reactors (PYTHON-1024)

  • +
  • Non-ASCII characters in schema break CQL string generation (PYTHON-1008)

  • +
  • Fix OSS driver’s virtual table support against DSE 6.0.X and future server releases (PYTHON-1020)

  • +
  • ResultSet.one() fails if the row_factory is using a generator (PYTHON-1026)

  • +
  • Log profile name on attempt to create existing profile (PYTHON-944)

  • +
  • Cluster instantiation fails if any contact points’ hostname resolution fails (PYTHON-895)

  • +
+
+
+

Other

+
    +
  • Fix tests when RF is not maintained if we decomission a node (PYTHON-1017)

  • +
  • Fix wrong use of ResultSet indexing (PYTHON-1015)

  • +
+
+
+
+

3.15.1

+

September 6, 2018

+
+

Bug Fixes

+
    +
  • C* 4.0 schema-parsing logic breaks running against DSE 6.0.X (PYTHON-1018)

  • +
+
+
+
+

3.15.0

+

August 30, 2018

+
+

Features

+
    +
  • Parse Virtual Keyspace Metadata (PYTHON-992)

  • +
+
+
+

Bug Fixes

+
    +
  • Tokenmap.get_replicas returns the wrong value if token coincides with the end of the range (PYTHON-978)

  • +
  • Python Driver fails with “more than 255 arguments” python exception when > 255 columns specified in query response (PYTHON-893)

  • +
  • Hang in integration.standard.test_cluster.ClusterTests.test_set_keyspace_twice (PYTHON-998)

  • +
  • Asyncore reactors should use a global variable instead of a class variable for the event loop (PYTHON-697)

  • +
+
+
+

Other

+
    +
  • Use global variable for libev loops so it can be subclassed (PYTHON-973)

  • +
  • Update SchemaParser for V4 (PYTHON-1006)

  • +
  • Bump Cython dependency version to 0.28 (PYTHON-1012)

  • +
+
+
+
+

3.14.0

+

April 17, 2018

+
+

Features

+
    +
  • Add one() function to the ResultSet API (PYTHON-947)

  • +
  • Create an utility function to fetch concurrently many keys from the same replica (PYTHON-647)

  • +
  • Allow filter queries with fields that have an index managed outside of cqlengine (PYTHON-966)

  • +
  • Twisted SSL Support (PYTHON-343)

  • +
  • Support IS NOT NULL operator in cqlengine (PYTHON-968)

  • +
+
+
+

Other

+
    +
  • Fix Broken Links in Docs (PYTHON-916)

  • +
  • Reevaluate MONKEY_PATCH_LOOP in test codebase (PYTHON-903)

  • +
  • Remove CASS_SERVER_VERSION and replace it for CASSANDRA_VERSION in tests (PYTHON-910)

  • +
  • Refactor CASSANDRA_VERSION to a some kind of version object (PYTHON-915)

  • +
  • Log warning when driver configures an authenticator, but server does not request authentication (PYTHON-940)

  • +
  • Warn users when using the deprecated Session.default_consistency_level (PYTHON-953)

  • +
  • Add DSE smoke test to OSS driver tests (PYTHON-894)

  • +
  • Document long compilation times and workarounds (PYTHON-868)

  • +
  • Improve error for batch WriteTimeouts (PYTHON-941)

  • +
  • Deprecate ResultSet indexing (PYTHON-945)

  • +
+
+
+
+

3.13.0

+

January 30, 2018

+
+

Features

+
    +
  • cqlengine: LIKE filter operator (PYTHON-512)

  • +
  • Support cassandra.query.BatchType with cqlengine BatchQuery (PYTHON-888)

  • +
+
+
+

Bug Fixes

+
    +
  • AttributeError: ‘NoneType’ object has no attribute ‘add_timer’ (PYTHON-862)

  • +
  • Support retry_policy in PreparedStatement (PYTHON-861)

  • +
  • __del__ method in Session is throwing an exception (PYTHON-813)

  • +
  • LZ4 import issue with recent versions (PYTHON-897)

  • +
  • ResponseFuture._connection can be None when returning request_id (PYTHON-853)

  • +
  • ResultSet.was_applied doesn’t support batch with LWT statements (PYTHON-848)

  • +
+
+
+

Other

+
    +
  • cqlengine: avoid warning when unregistering connection on shutdown (PYTHON-865)

  • +
  • Fix DeprecationWarning of log.warn (PYTHON-846)

  • +
  • Fix example_mapper.py for python3 (PYTHON-860)

  • +
  • Possible deadlock on cassandra.concurrent.execute_concurrent (PYTHON-768)

  • +
  • Add some known deprecated warnings for 4.x (PYTHON-877)

  • +
  • Remove copyright dates from copyright notices (PYTHON-863)

  • +
  • Remove “Experimental” tag from execution profiles documentation (PYTHON-840)

  • +
  • request_timer metrics descriptions are slightly incorrect (PYTHON-885)

  • +
  • Remove “Experimental” tag from cqlengine connections documentation (PYTHON-892)

  • +
  • Set in documentation default consistency for operations is LOCAL_ONE (PYTHON-901)

  • +
+
+
+
+

3.12.0

+

November 6, 2017

+
+

Features

+
    +
  • Send keyspace in QUERY, PREPARE, and BATCH messages (PYTHON-678)

  • +
  • Add IPv4Address/IPv6Address support for inet types (PYTHON-751)

  • +
  • WriteType.CDC and VIEW missing (PYTHON-794)

  • +
  • Warn on Cluster init if contact points are specified but LBP isn’t (legacy mode) (PYTHON-812)

  • +
  • Warn on Cluster init if contact points are specified but LBP isn’t (exection profile mode) (PYTHON-838)

  • +
  • Include hash of result set metadata in prepared stmt id (PYTHON-808)

  • +
  • Add NO_COMPACT startup option (PYTHON-839)

  • +
  • Add new exception type for CDC (PYTHON-837)

  • +
  • Allow 0ms in ConstantSpeculativeExecutionPolicy (PYTHON-836)

  • +
  • Add asyncio reactor (PYTHON-507)

  • +
+
+
+

Bug Fixes

+
    +
  • Both _set_final_exception/result called for the same ResponseFuture (PYTHON-630)

  • +
  • Use of DCAwareRoundRobinPolicy raises NoHostAvailable exception (PYTHON-781)

  • +
  • Not create two sessions by default in CQLEngine (PYTHON-814)

  • +
  • Bug when subclassing AyncoreConnection (PYTHON-827)

  • +
  • Error at cleanup when closing the asyncore connections (PYTHON-829)

  • +
  • Fix sites where sessions can change during iteration (PYTHON-793)

  • +
  • cqlengine: allow min_length=0 for Ascii and Text column types (PYTHON-735)

  • +
  • Rare exception when “sys.exit(0)” after query timeouts (PYTHON-752)

  • +
  • Dont set the session keyspace when preparing statements (PYTHON-843)

  • +
  • Use of DCAwareRoundRobinPolicy raises NoHostAvailable exception (PYTHON-781)

  • +
+
+
+

Other

+
    +
  • Remove DeprecationWarning when using WhiteListRoundRobinPolicy (PYTHON-810)

  • +
  • Bump Cython dependency version to 0.27 (PYTHON-833)

  • +
+
+
+
+

3.11.0

+

July 24, 2017

+
+

Features

+
    +
  • Add idle_heartbeat_timeout cluster option to tune how long to wait for heartbeat responses. (PYTHON-762)

  • +
  • Add HostFilterPolicy (PYTHON-761)

  • +
+
+
+

Bug Fixes

+
    +
  • is_idempotent flag is not propagated from PreparedStatement to BoundStatement (PYTHON-736)

  • +
  • Fix asyncore hang on exit (PYTHON-767)

  • +
  • Driver takes several minutes to remove a bad host from session (PYTHON-762)

  • +
  • Installation doesn’t always fall back to no cython in Windows (PYTHON-763)

  • +
  • Avoid to replace a connection that is supposed to shutdown (PYTHON-772)

  • +
  • request_ids may not be returned to the pool (PYTHON-739)

  • +
  • Fix murmur3 on big-endian systems (PYTHON-653)

  • +
  • Ensure unused connections are closed if a Session is deleted by the GC (PYTHON-774)

  • +
  • Fix .values_list by using db names internally (cqlengine) (PYTHON-785)

  • +
+
+
+

Other

+
    +
  • Bump Cython dependency version to 0.25.2 (PYTHON-754)

  • +
  • Fix DeprecationWarning when using lz4 (PYTHON-769)

  • +
  • Deprecate WhiteListRoundRobinPolicy (PYTHON-759)

  • +
  • Improve upgrade guide for materializing pages (PYTHON-464)

  • +
  • Documentation for time/date specifies timestamp inupt as microseconds (PYTHON-717)

  • +
  • Point to DSA Slack, not IRC, in docs index

  • +
+
+
+
+

3.10.0

+

May 24, 2017

+
+

Features

+
    +
  • Add Duration type to cqlengine (PYTHON-750)

  • +
  • Community PR review: Raise error on primary key update only if its value changed (PYTHON-705)

  • +
  • get_query_trace() contract is ambiguous (PYTHON-196)

  • +
+
+
+

Bug Fixes

+
    +
  • Queries using speculative execution policy timeout prematurely (PYTHON-755)

  • +
  • Fix map where results are not consumed (PYTHON-749)

  • +
  • Driver fails to encode Duration’s with large values (PYTHON-747)

  • +
  • UDT values are not updated correctly in CQLEngine (PYTHON-743)

  • +
  • UDT types are not validated in CQLEngine (PYTHON-742)

  • +
  • to_python is not implemented for types columns.Type and columns.Date in CQLEngine (PYTHON-741)

  • +
  • Clients spin infinitely trying to connect to a host that is drained (PYTHON-734)

  • +
  • Resulset.get_query_trace returns empty trace sometimes (PYTHON-730)

  • +
  • Memory grows and doesn’t get removed (PYTHON-720)

  • +
  • Fix RuntimeError caused by change dict size during iteration (PYTHON-708)

  • +
  • fix ExponentialReconnectionPolicy may throw OverflowError problem (PYTHON-707)

  • +
  • Avoid using nonexistent prepared statement in ResponseFuture (PYTHON-706)

  • +
+
+
+

Other

+
    +
  • Update README (PYTHON-746)

  • +
  • Test python versions 3.5 and 3.6 (PYTHON-737)

  • +
  • Docs Warning About Prepare select * (PYTHON-626)

  • +
  • Increase Coverage in CqlEngine Test Suite (PYTHON-505)

  • +
  • Example SSL connection code does not verify server certificates (PYTHON-469)

  • +
+
+
+
+

3.9.0

+
+

Features

+
    +
  • cqlengine: remove elements by key from a map (PYTHON-688)

  • +
+
+
+

Bug Fixes

+
    +
  • improve error handling when connecting to non-existent keyspace (PYTHON-665)

  • +
  • Sockets associated with sessions not getting cleaned up on session.shutdown() (PYTHON-673)

  • +
  • rare flake on integration.standard.test_cluster.ClusterTests.test_clone_shared_lbp (PYTHON-727)

  • +
  • MontonicTimestampGenerator.__init__ ignores class defaults (PYTHON-728)

  • +
  • race where callback or errback for request may not be called (PYTHON-733)

  • +
  • cqlengine: model.update() should not update columns with a default value that hasn’t changed (PYTHON-657)

  • +
  • cqlengine: field value manager’s explicit flag is True when queried back from cassandra (PYTHON-719)

  • +
+
+
+

Other

+
    +
  • Connection not closed in example_mapper (PYTHON-723)

  • +
  • Remove mention of pre-2.0 C* versions from OSS 3.0+ docs (PYTHON-710)

  • +
+
+
+
+

3.8.1

+

March 16, 2017

+
+

Bug Fixes

+
    +
  • implement __le__/__ge__/__ne__ on some custom types (PYTHON-714)

  • +
  • Fix bug in eventlet and gevent reactors that could cause hangs (PYTHON-721)

  • +
  • Fix DecimalType regression (PYTHON-724)

  • +
+
+
+
+

3.8.0

+
+

Features

+
    +
  • Quote index names in metadata CQL generation (PYTHON-616)

  • +
  • On column deserialization failure, keep error message consistent between python and cython (PYTHON-631)

  • +
  • TokenAwarePolicy always sends requests to the same replica for a given key (PYTHON-643)

  • +
  • Added cql types to result set (PYTHON-648)

  • +
  • Add __len__ to BatchStatement (PYTHON-650)

  • +
  • Duration Type for Cassandra (PYTHON-655)

  • +
  • Send flags with PREPARE message in v5 (PYTHON-684)

  • +
+
+
+

Bug Fixes

+
    +
  • Potential Timing issue if application exits prior to session pool initialization (PYTHON-636)

  • +
  • “Host X.X.X.X has been marked down” without any exceptions (PYTHON-640)

  • +
  • NoHostAvailable or OperationTimedOut when using execute_concurrent with a generator that inserts into more than one table (PYTHON-642)

  • +
  • ResponseFuture creates Timers and don’t cancel them even when result is received which leads to memory leaks (PYTHON-644)

  • +
  • Driver cannot connect to Cassandra version > 3 (PYTHON-646)

  • +
  • Unable to import model using UserType without setuping connection since 3.7 (PYTHON-649)

  • +
  • Don’t prepare queries on ignored hosts on_up (PYTHON-669)

  • +
  • Sockets associated with sessions not getting cleaned up on session.shutdown() (PYTHON-673)

  • +
  • Make client timestamps strictly monotonic (PYTHON-676)

  • +
  • cassandra.cqlengine.connection.register_connection broken when hosts=None (PYTHON-692)

  • +
+
+
+

Other

+
    +
  • Create a cqlengine doc section explaining None semantics (PYTHON-623)

  • +
  • Resolve warnings in documentation generation (PYTHON-645)

  • +
  • Cython dependency (PYTHON-686)

  • +
  • Drop Support for Python 2.6 (PYTHON-690)

  • +
+
+
+
+

3.7.1

+

October 26, 2016

+
+

Bug Fixes

+
    +
  • Cython upgrade has broken stable version of cassandra-driver (PYTHON-656)

  • +
+
+
+
+

3.7.0

+

September 13, 2016

+
+

Features

+
    +
  • Add v5 protocol failure map (PYTHON-619)

  • +
  • Don’t return from initial connect on first error (PYTHON-617)

  • +
  • Indicate failed column when deserialization fails (PYTHON-361)

  • +
  • Let Cluster.refresh_nodes force a token map rebuild (PYTHON-349)

  • +
  • Refresh UDTs after “keyspace updated” event with v1/v2 protocol (PYTHON-106)

  • +
  • EC2 Address Resolver (PYTHON-198)

  • +
  • Speculative query retries (PYTHON-218)

  • +
  • Expose paging state in API (PYTHON-200)

  • +
  • Don’t mark host down while one connection is active (PYTHON-498)

  • +
  • Query request size information (PYTHON-284)

  • +
  • Avoid quadratic ring processing with invalid replication factors (PYTHON-379)

  • +
  • Improve Connection/Pool creation concurrency on startup (PYTHON-82)

  • +
  • Add beta version native protocol flag (PYTHON-614)

  • +
  • cqlengine: Connections: support of multiple keyspaces and sessions (PYTHON-613)

  • +
+
+
+

Bug Fixes

+
    +
  • Race when adding a pool while setting keyspace (PYTHON-628)

  • +
  • Update results_metadata when prepared statement is reprepared (PYTHON-621)

  • +
  • CQL Export for Thrift Tables (PYTHON-213)

  • +
  • cqlengine: default value not applied to UserDefinedType (PYTHON-606)

  • +
  • cqlengine: columns are no longer hashable (PYTHON-618)

  • +
  • cqlengine: remove clustering keys from where clause when deleting only static columns (PYTHON-608)

  • +
+
+
+
+

3.6.0

+

August 1, 2016

+
+

Features

+
    +
  • Handle null values in NumpyProtocolHandler (PYTHON-553)

  • +
  • Collect greplin scales stats per cluster (PYTHON-561)

  • +
  • Update mock unit test dependency requirement (PYTHON-591)

  • +
  • Handle Missing CompositeType metadata following C* upgrade (PYTHON-562)

  • +
  • Improve Host.is_up state for HostDistance.IGNORED hosts (PYTHON-551)

  • +
  • Utilize v2 protocol’s ability to skip result set metadata for prepared statement execution (PYTHON-71)

  • +
  • Return from Cluster.connect() when first contact point connection(pool) is opened (PYTHON-105)

  • +
  • cqlengine: Add ContextQuery to allow cqlengine models to switch the keyspace context easily (PYTHON-598)

  • +
  • Standardize Validation between Ascii and Text types in Cqlengine (PYTHON-609)

  • +
+
+
+

Bug Fixes

+
    +
  • Fix geventreactor with SSL support (PYTHON-600)

  • +
  • Don’t downgrade protocol version if explicitly set (PYTHON-537)

  • +
  • Nonexistent contact point tries to connect indefinitely (PYTHON-549)

  • +
  • Execute_concurrent can exceed max recursion depth in failure mode (PYTHON-585)

  • +
  • Libev loop shutdown race (PYTHON-578)

  • +
  • Include aliases in DCT type string (PYTHON-579)

  • +
  • cqlengine: Comparison operators for Columns (PYTHON-595)

  • +
  • cqlengine: disentangle default_time_to_live table option from model query default TTL (PYTHON-538)

  • +
  • cqlengine: pk__token column name issue with the equality operator (PYTHON-584)

  • +
  • cqlengine: Fix “__in” filtering operator converts True to string “True” automatically (PYTHON-596)

  • +
  • cqlengine: Avoid LWTExceptions when updating columns that are part of the condition (PYTHON-580)

  • +
  • cqlengine: Cannot execute a query when the filter contains all columns (PYTHON-599)

  • +
  • cqlengine: routing key computation issue when a primary key column is overriden by model inheritance (PYTHON-576)

  • +
+
+
+
+

3.5.0

+

June 27, 2016

+
+

Features

+
    +
  • Optional Execution Profiles for the core driver (PYTHON-569)

  • +
  • API to get the host metadata associated with the control connection node (PYTHON-583)

  • +
  • Expose CDC option in table metadata CQL (PYTHON-593)

  • +
+
+
+

Bug Fixes

+
    +
  • Clean up Asyncore socket map when fork is detected (PYTHON-577)

  • +
  • cqlengine: QuerySet only() is not respected when there are deferred fields (PYTHON-560)

  • +
+
+
+
+

3.4.1

+

May 26, 2016

+
+

Bug Fixes

+
    +
  • Gevent connection closes on IO timeout (PYTHON-573)

  • +
  • “dictionary changed size during iteration” with Python 3 (PYTHON-572)

  • +
+
+
+
+

3.4.0

+

May 24, 2016

+
+

Features

+
    +
  • Include DSE version and workload in Host data (PYTHON-555)

  • +
  • Add a context manager to Cluster and Session (PYTHON-521)

  • +
  • Better Error Message for Unsupported Protocol Version (PYTHON-157)

  • +
  • Make the error message explicitly state when an error comes from the server (PYTHON-412)

  • +
  • Short Circuit meta refresh on topo change if NEW_NODE already exists (PYTHON-557)

  • +
  • Show warning when the wrong config is passed to SimpleStatement (PYTHON-219)

  • +
  • Return namedtuple result pairs from execute_concurrent (PYTHON-362)

  • +
  • BatchStatement should enforce batch size limit in a better way (PYTHON-151)

  • +
  • Validate min/max request thresholds for connection pool scaling (PYTHON-220)

  • +
  • Handle or warn about multiple hosts with the same rpc_address (PYTHON-365)

  • +
  • Write docs around working with datetime and timezones (PYTHON-394)

  • +
+
+
+

Bug Fixes

+
    +
  • High CPU utilization when using asyncore event loop (PYTHON-239)

  • +
  • Fix CQL Export for non-ASCII Identifiers (PYTHON-447)

  • +
  • Make stress scripts Python 2.6 compatible (PYTHON-434)

  • +
  • UnicodeDecodeError when unicode characters in key in BOP (PYTHON-559)

  • +
  • WhiteListRoundRobinPolicy should resolve hosts (PYTHON-565)

  • +
  • Cluster and Session do not GC after leaving scope (PYTHON-135)

  • +
  • Don’t wait for schema agreement on ignored nodes (PYTHON-531)

  • +
  • Reprepare on_up with many clients causes node overload (PYTHON-556)

  • +
  • None inserted into host map when control connection node is decommissioned (PYTHON-548)

  • +
  • weakref.ref does not accept keyword arguments (github #585)

  • +
+
+
+
+

3.3.0

+

May 2, 2016

+
+

Features

+
    +
  • Add an AddressTranslator interface (PYTHON-69)

  • +
  • New Retry Policy Decision - try next host (PYTHON-285)

  • +
  • Don’t mark host down on timeout (PYTHON-286)

  • +
  • SSL hostname verification (PYTHON-296)

  • +
  • Add C* version to metadata or cluster objects (PYTHON-301)

  • +
  • Options to Disable Schema, Token Metadata Processing (PYTHON-327)

  • +
  • Expose listen_address of node we get ring information from (PYTHON-332)

  • +
  • Use A-record with multiple IPs for contact points (PYTHON-415)

  • +
  • Custom consistency level for populating query traces (PYTHON-435)

  • +
  • Normalize Server Exception Types (PYTHON-443)

  • +
  • Propagate exception message when DDL schema agreement fails (PYTHON-444)

  • +
  • Specialized exceptions for metadata refresh methods failure (PYTHON-527)

  • +
+
+
+

Bug Fixes

+
    +
  • Resolve contact point hostnames to avoid duplicate hosts (PYTHON-103)

  • +
  • GeventConnection stalls requests when read is a multiple of the input buffer size (PYTHON-429)

  • +
  • named_tuple_factory breaks with duplicate “cleaned” col names (PYTHON-467)

  • +
  • Connection leak if Cluster.shutdown() happens during reconnection (PYTHON-482)

  • +
  • HostConnection.borrow_connection does not block when all request ids are used (PYTHON-514)

  • +
  • Empty field not being handled by the NumpyProtocolHandler (PYTHON-550)

  • +
+
+
+
+

3.2.2

+

April 19, 2016

+
    +
  • Fix counter save-after-no-update (PYTHON-547)

  • +
+
+
+

3.2.1

+

April 13, 2016

+
    +
  • Introduced an update to allow deserializer compilation with recently released Cython 0.24 (PYTHON-542)

  • +
+
+
+

3.2.0

+

April 12, 2016

+
+

Features

+
    +
  • cqlengine: Warn on sync_schema type mismatch (PYTHON-260)

  • +
  • cqlengine: Automatically defer fields with the ‘=’ operator (and immutable values) in select queries (PYTHON-520)

  • +
  • cqlengine: support non-equal conditions for LWT (PYTHON-528)

  • +
  • cqlengine: sync_table should validate the primary key composition (PYTHON-532)

  • +
  • cqlengine: token-aware routing for mapper statements (PYTHON-535)

  • +
+
+
+

Bug Fixes

+
    +
  • Deleting a column in a lightweight transaction raises a SyntaxException #325 (PYTHON-249)

  • +
  • cqlengine: make Token function works with named tables/columns #86 (PYTHON-272)

  • +
  • comparing models with datetime fields fail #79 (PYTHON-273)

  • +
  • cython date deserializer integer math should be aligned with CPython (PYTHON-480)

  • +
  • db_field is not always respected with UpdateStatement (PYTHON-530)

  • +
  • Sync_table fails on column.Set with secondary index (PYTHON-533)

  • +
+
+
+
+

3.1.1

+

March 14, 2016

+
+

Bug Fixes

+
    +
  • cqlengine: Fix performance issue related to additional “COUNT” queries (PYTHON-522)

  • +
+
+
+
+

3.1.0

+

March 10, 2016

+
+

Features

+
    +
  • Pass name of server auth class to AuthProvider (PYTHON-454)

  • +
  • Surface schema agreed flag for DDL statements (PYTHON-458)

  • +
  • Automatically convert float and int to Decimal on serialization (PYTHON-468)

  • +
  • Eventlet Reactor IO improvement (PYTHON-495)

  • +
  • Make pure Python ProtocolHandler available even when Cython is present (PYTHON-501)

  • +
  • Optional Cython deserializer for bytes as bytearray (PYTHON-503)

  • +
  • Add Session.default_serial_consistency_level (github #510)

  • +
  • cqlengine: Expose prior state information via cqlengine LWTException (github #343, PYTHON-336)

  • +
  • cqlengine: Collection datatype “contains” operators support (Cassandra 2.1) #278 (PYTHON-258)

  • +
  • cqlengine: Add DISTINCT query operator (PYTHON-266)

  • +
  • cqlengine: Tuple cqlengine api (PYTHON-306)

  • +
  • cqlengine: Add support for UPDATE/DELETE … IF EXISTS statements (PYTHON-432)

  • +
  • cqlengine: Allow nested container types (PYTHON-478)

  • +
  • cqlengine: Add ability to set query’s fetch_size and limit (PYTHON-323)

  • +
  • cqlengine: Internalize default keyspace from successive set_session (PYTHON-486)

  • +
  • cqlengine: Warn when Model.create() on Counters (to be deprecated) (PYTHON-333)

  • +
+
+
+

Bug Fixes

+
    +
  • Bus error (alignment issues) when running cython on some ARM platforms (PYTHON-450)

  • +
  • Overflow when decoding large collections (cython) (PYTHON-459)

  • +
  • Timer heap comparison issue with Python 3 (github #466)

  • +
  • Cython deserializer date overflow at 2^31 - 1 (PYTHON-452)

  • +
  • Decode error encountered when cython deserializing large map results (PYTHON-459)

  • +
  • Don’t require Cython for build if compiler or Python header not present (PYTHON-471)

  • +
  • Unorderable types in task scheduling with Python 3 (h(PYTHON-473)

  • +
  • cqlengine: Fix crash when updating a UDT column with a None value (github #467)

  • +
  • cqlengine: Race condition in ..connection.execute with lazy_connect (PYTHON-310)

  • +
  • cqlengine: doesn’t support case sensitive column family names (PYTHON-337)

  • +
  • cqlengine: UserDefinedType mandatory in create or update (PYTHON-344)

  • +
  • cqlengine: db_field breaks UserType (PYTHON-346)

  • +
  • cqlengine: UDT badly quoted (PYTHON-347)

  • +
  • cqlengine: Use of db_field on primary key prevents querying except while tracing. (PYTHON-351)

  • +
  • cqlengine: DateType.deserialize being called with one argument vs two (PYTHON-354)

  • +
  • cqlengine: Querying without setting up connection now throws AttributeError and not CQLEngineException (PYTHON-395)

  • +
  • cqlengine: BatchQuery multiple time executing execute statements. (PYTHON-445)

  • +
  • cqlengine: Better error for management functions when no connection set (PYTHON-451)

  • +
  • cqlengine: Handle None values for UDT attributes in cqlengine (PYTHON-470)

  • +
  • cqlengine: Fix inserting None for model save (PYTHON-475)

  • +
  • cqlengine: EQ doesn’t map to a QueryOperator (setup race condition) (PYTHON-476)

  • +
  • cqlengine: class.MultipleObjectsReturned has DoesNotExist as base class (PYTHON-489)

  • +
  • cqlengine: Typo in cqlengine UserType __len__ breaks attribute assignment (PYTHON-502)

  • +
+
+
+

Other

+
    +
  • cqlengine: a major improvement on queryset has been introduced. It +is a lot more efficient to iterate large datasets: the rows are +now fetched on demand using the driver pagination.

  • +
  • cqlengine: the queryset len() and count() behaviors have changed. It +now executes a “SELECT COUNT(*)” of the query rather than returning +the size of the internal result_cache (loaded rows). On large +queryset, you might want to avoid using them due to the performance +cost. Note that trying to access objects using list index/slicing +with negative indices also requires a count to be +executed.

  • +
+
+
+
+

3.0.0

+

November 24, 2015

+
+

Features

+
    +
  • Support datetime.date objects as a DateType (PYTHON-212)

  • +
  • Add Cluster.update_view_metadata (PYTHON-407)

  • +
  • QueryTrace option to populate partial trace sessions (PYTHON-438)

  • +
  • Attach column names to ResultSet (PYTHON-439)

  • +
  • Change default consistency level to LOCAL_ONE

  • +
+
+
+

Bug Fixes

+
    +
  • Properly SerDes nested collections when protocol_version < 3 (PYTHON-215)

  • +
  • Evict UDTs from UserType cache on change (PYTHON-226)

  • +
  • Make sure query strings are always encoded UTF-8 (PYTHON-334)

  • +
  • Track previous value of columns at instantiation in CQLengine (PYTHON-348)

  • +
  • UDT CQL encoding does not work for unicode values (PYTHON-353)

  • +
  • NetworkTopologyStrategy#make_token_replica_map does not account for multiple racks in a DC (PYTHON-378)

  • +
  • Cython integer overflow on decimal type deserialization (PYTHON-433)

  • +
  • Query trace: if session hasn’t been logged, query trace can throw exception (PYTHON-442)

  • +
+
+
+
+

3.0.0rc1

+

November 9, 2015

+
+

Features

+
    +
  • Process Modernized Schema Tables for Cassandra 3.0 (PYTHON-276, PYTHON-408, PYTHON-400, PYTHON-422)

  • +
  • Remove deprecated features (PYTHON-292)

  • +
  • Don’t assign trace data to Statements (PYTHON-318)

  • +
  • Normalize results return (PYTHON-368)

  • +
  • Process Materialized View Metadata/Events (PYTHON-371)

  • +
  • Remove blist as soft dependency (PYTHON-385)

  • +
  • Change default consistency level to LOCAL_QUORUM (PYTHON-416)

  • +
  • Normalize CQL query/export in metadata model (PYTHON-405)

  • +
+
+
+

Bug Fixes

+
    +
  • Implementation of named arguments bind is non-pythonic (PYTHON-178)

  • +
  • CQL encoding is incorrect for NaN and Infinity floats (PYTHON-282)

  • +
  • Protocol downgrade issue with C* 2.0.x, 2.1.x, and python3, with non-default logging (PYTHON-409)

  • +
  • ValueError when accessing usertype with non-alphanumeric field names (PYTHON-413)

  • +
  • NumpyProtocolHandler does not play well with PagedResult (PYTHON-430)

  • +
+
+
+
+

2.7.2

+

September 14, 2015

+
+

Bug Fixes

+
    +
  • Resolve CQL export error for UDF with zero parameters (PYTHON-392)

  • +
  • Remove futures dep. for Python 3 (PYTHON-393)

  • +
  • Avoid Python closure in cdef (supports earlier Cython compiler) (PYTHON-396)

  • +
  • Unit test runtime issues (PYTHON-397,398)

  • +
+
+
+
+

2.7.1

+

August 25, 2015

+
+

Bug Fixes

+
    +
  • Explicitly include extension source files in Manifest

  • +
+
+
+
+

2.7.0

+

August 25, 2015

+

Cython is introduced, providing compiled extensions for core modules, and +extensions for optimized results deserialization.

+
+

Features

+
    +
  • General Performance Improvements for Throughput (PYTHON-283)

  • +
  • Improve synchronous request performance with Timers (PYTHON-108)

  • +
  • Enable C Extensions for PyPy Runtime (PYTHON-357)

  • +
  • Refactor SerDes functionality for pluggable interface (PYTHON-313)

  • +
  • Cython SerDes Extension (PYTHON-377)

  • +
  • Accept iterators/generators for execute_concurrent() (PYTHON-123)

  • +
  • cythonize existing modules (PYTHON-342)

  • +
  • Pure Python murmur3 implementation (PYTHON-363)

  • +
  • Make driver tolerant of inconsistent metadata (PYTHON-370)

  • +
+
+
+

Bug Fixes

+
    +
  • Drop Events out-of-order Cause KeyError on Processing (PYTHON-358)

  • +
  • DowngradingConsistencyRetryPolicy doesn’t check response count on write timeouts (PYTHON-338)

  • +
  • Blocking connect does not use connect_timeout (PYTHON-381)

  • +
  • Properly protect partition key in CQL export (PYTHON-375)

  • +
  • Trigger error callbacks on timeout (PYTHON-294)

  • +
+
+
+
+

2.6.0

+

July 20, 2015

+
+

Bug Fixes

+
    +
  • Output proper CQL for compact tables with no clustering columns (PYTHON-360)

  • +
+
+
+
+

2.6.0c2

+

June 24, 2015

+
+

Features

+
    +
  • Automatic Protocol Version Downgrade (PYTHON-240)

  • +
  • cqlengine Python 2.6 compatibility (PYTHON-288)

  • +
  • Double-dollar string quote UDF body (PYTHON-345)

  • +
  • Set models.DEFAULT_KEYSPACE when calling set_session (github #352)

  • +
+
+
+

Bug Fixes

+
    +
  • Avoid stall while connecting to mixed version cluster (PYTHON-303)

  • +
  • Make SSL work with AsyncoreConnection in python 2.6.9 (PYTHON-322)

  • +
  • Fix Murmur3Token.from_key() on Windows (PYTHON-331)

  • +
  • Fix cqlengine TimeUUID rounding error for Windows (PYTHON-341)

  • +
  • Avoid invalid compaction options in CQL export for non-SizeTiered (PYTHON-352)

  • +
+
+
+
+

2.6.0c1

+

June 4, 2015

+

This release adds support for Cassandra 2.2 features, including version +4 of the native protocol.

+
+

Features

+
    +
  • Default load balancing policy to TokenAware(DCAware) (PYTHON-160)

  • +
  • Configuration option for connection timeout (PYTHON-206)

  • +
  • Support User Defined Function and Aggregate metadata in C* 2.2 (PYTHON-211)

  • +
  • Surface request client in QueryTrace for C* 2.2+ (PYTHON-235)

  • +
  • Implement new request failure messages in protocol v4+ (PYTHON-238)

  • +
  • Metadata model now maps index meta by index name (PYTHON-241)

  • +
  • Support new types in C* 2.2: date, time, smallint, tinyint (PYTHON-245, 295)

  • +
  • cqle: add Double column type and remove Float overload (PYTHON-246)

  • +
  • Use partition key column information in prepared response for protocol v4+ (PYTHON-277)

  • +
  • Support message custom payloads in protocol v4+ (PYTHON-280, PYTHON-329)

  • +
  • Deprecate refresh_schema and replace with functions for specific entities (PYTHON-291)

  • +
  • Save trace id even when trace complete times out (PYTHON-302)

  • +
  • Warn when registering client UDT class for protocol < v3 (PYTHON-305)

  • +
  • Support client warnings returned with messages in protocol v4+ (PYTHON-315)

  • +
  • Ability to distinguish between NULL and UNSET values in protocol v4+ (PYTHON-317)

  • +
  • Expose CQL keywords in API (PYTHON-324)

  • +
+
+
+

Bug Fixes

+
    +
  • IPv6 address support on Windows (PYTHON-20)

  • +
  • Convert exceptions during automatic re-preparation to nice exceptions (PYTHON-207)

  • +
  • cqle: Quote keywords properly in table management functions (PYTHON-244)

  • +
  • Don’t default to GeventConnection when gevent is loaded, but not monkey-patched (PYTHON-289)

  • +
  • Pass dynamic host from SaslAuthProvider to SaslAuthenticator (PYTHON-300)

  • +
  • Make protocol read_inet work for Windows (PYTHON-309)

  • +
  • cqle: Correct encoding for nested types (PYTHON-311)

  • +
  • Update list of CQL keywords used quoting identifiers (PYTHON-319)

  • +
  • Make ConstantReconnectionPolicy work with infinite retries (github #327, PYTHON-325)

  • +
  • Accept UUIDs with uppercase hex as valid in cqlengine (github #335)

  • +
+
+
+
+

2.5.1

+

April 23, 2015

+
+

Bug Fixes

+
    +
  • Fix thread safety in DC-aware load balancing policy (PYTHON-297)

  • +
  • Fix race condition in node/token rebuild (PYTHON-298)

  • +
  • Set and send serial consistency parameter (PYTHON-299)

  • +
+
+
+
+

2.5.0

+

March 30, 2015

+
+

Features

+
    +
  • Integrated cqlengine object mapping package

  • +
  • Utility functions for converting timeuuids and datetime (PYTHON-99)

  • +
  • Schema metadata fetch window randomized, config options added (PYTHON-202)

  • +
  • Support for new Date and Time Cassandra types (PYTHON-190)

  • +
+
+
+

Bug Fixes

+
    +
  • Fix index target for collection indexes (full(), keys()) (PYTHON-222)

  • +
  • Thread exception during GIL cleanup (PYTHON-229)

  • +
  • Workaround for rounding anomaly in datetime.utcfromtime (Python 3.4) (PYTHON-230)

  • +
  • Normalize text serialization for lookup in OrderedMap (PYTHON-231)

  • +
  • Support reading CompositeType data (PYTHON-234)

  • +
  • Preserve float precision in CQL encoding (PYTHON-243)

  • +
+
+
+
+

2.1.4

+

January 26, 2015

+
+

Features

+
    +
  • SaslAuthenticator for Kerberos support (PYTHON-109)

  • +
  • Heartbeat for network device keepalive and detecting failures on idle connections (PYTHON-197)

  • +
  • Support nested, frozen collections for Cassandra 2.1.3+ (PYTHON-186)

  • +
  • Schema agreement wait bypass config, new call for synchronous schema refresh (PYTHON-205)

  • +
  • Add eventlet connection support (PYTHON-194)

  • +
+
+
+

Bug Fixes

+
    +
  • Schema meta fix for complex thrift tables (PYTHON-191)

  • +
  • Support for ‘unknown’ replica placement strategies in schema meta (PYTHON-192)

  • +
  • Resolve stream ID leak on set_keyspace (PYTHON-195)

  • +
  • Remove implicit timestamp scaling on serialization of numeric timestamps (PYTHON-204)

  • +
  • Resolve stream id collision when using SASL auth (PYTHON-210)

  • +
  • Correct unhexlify usage for user defined type meta in Python3 (PYTHON-208)

  • +
+
+
+
+

2.1.3

+

December 16, 2014

+
+

Features

+
    +
  • INFO-level log confirmation that a connection was opened to a node that was marked up (PYTHON-116)

  • +
  • Avoid connecting to peer with incomplete metadata (PYTHON-163)

  • +
  • Add SSL support to gevent reactor (PYTHON-174)

  • +
  • Use control connection timeout in wait for schema agreement (PYTHON-175)

  • +
  • Better consistency level representation in unavailable+timeout exceptions (PYTHON-180)

  • +
  • Update schema metadata processing to accommodate coming schema modernization (PYTHON-185)

  • +
+
+
+

Bug Fixes

+
    +
  • Support large negative timestamps on Windows (PYTHON-119)

  • +
  • Fix schema agreement for clusters with peer rpc_addres 0.0.0.0 (PYTHON-166)

  • +
  • Retain table metadata following keyspace meta refresh (PYTHON-173)

  • +
  • Use a timeout when preparing a statement for all nodes (PYTHON-179)

  • +
  • Make TokenAware routing tolerant of statements with no keyspace (PYTHON-181)

  • +
  • Update add_collback to store/invoke multiple callbacks (PYTHON-182)

  • +
  • Correct routing key encoding for composite keys (PYTHON-184)

  • +
  • Include compression option in schema export string when disabled (PYTHON-187)

  • +
+
+
+
+

2.1.2

+

October 16, 2014

+
+

Features

+
    +
  • Allow DCAwareRoundRobinPolicy to be constructed without a local_dc, defaulting +instead to the DC of a contact_point (PYTHON-126)

  • +
  • Set routing key in BatchStatement.add() if none specified in batch (PYTHON-148)

  • +
  • Improved feedback on ValueError using named_tuple_factory with invalid column names (PYTHON-122)

  • +
+
+
+

Bug Fixes

+
    +
  • Make execute_concurrent compatible with Python 2.6 (PYTHON-159)

  • +
  • Handle Unauthorized message on schema_triggers query (PYTHON-155)

  • +
  • Pure Python sorted set in support of UDTs nested in collections (PYTON-167)

  • +
  • Support CUSTOM index metadata and string export (PYTHON-165)

  • +
+
+
+
+

2.1.1

+

September 11, 2014

+
+

Features

+
    +
  • Detect triggers and include them in CQL queries generated to recreate +the schema (github-189)

  • +
  • Support IPv6 addresses (PYTHON-144) (note: basic functionality added; Windows +platform not addressed (PYTHON-20))

  • +
+
+
+

Bug Fixes

+
    +
  • Fix NetworkTopologyStrategy.export_for_schema (PYTHON-120)

  • +
  • Keep timeout for paged results (PYTHON-150)

  • +
+
+
+

Other

+
    +
  • Add frozen<> type modifier to UDTs and tuples to handle CASSANDRA-7857

  • +
+
+
+
+

2.1.0

+

August 7, 2014

+
+

Bug Fixes

+
    +
  • Correctly serialize and deserialize null values in tuples and +user-defined types (PYTHON-110)

  • +
  • Include additional header and lib dirs, allowing libevwrapper to build +against Homebrew and Mac Ports installs of libev (PYTHON-112 and 804dea3)

  • +
+
+
+
+

2.1.0c1

+

July 25, 2014

+
+

Bug Fixes

+
    +
  • Properly specify UDTs for columns in CREATE TABLE statements

  • +
  • Avoid moving retries to a new host when using request ID zero (PYTHON-88)

  • +
  • Don’t ignore fetch_size arguments to Statement constructors (github-151)

  • +
  • Allow disabling automatic paging on a per-statement basis when it’s +enabled by default for the session (PYTHON-93)

  • +
  • Raise ValueError when tuple query parameters for prepared statements +have extra items (PYTHON-98)

  • +
  • Correctly encode nested tuples and UDTs for non-prepared statements (PYTHON-100)

  • +
  • Raise TypeError when a string is used for contact_points (github #164)

  • +
  • Include User Defined Types in KeyspaceMetadata.export_as_string() (PYTHON-96)

  • +
+
+
+

Other

+
    +
  • Return list collection columns as python lists instead of tuples +now that tuples are a specific Cassandra type

  • +
+
+
+
+

2.1.0b1

+

July 11, 2014

+

This release adds support for Cassandra 2.1 features, including version +3 of the native protocol.

+
+

Features

+
    +
  • When using the v3 protocol, only one connection is opened per-host, and +throughput is improved due to reduced pooling overhead and lock contention.

  • +
  • Support for user-defined types (Cassandra 2.1+)

  • +
  • Support for tuple type in (limited usage Cassandra 2.0.9, full usage +in Cassandra 2.1)

  • +
  • Protocol-level client-side timestamps (see Session.use_client_timestamp)

  • +
  • Overridable type encoding for non-prepared statements (see Session.encoders)

  • +
  • Configurable serial consistency levels for batch statements

  • +
  • Use io.BytesIO for reduced CPU consumption (github #143)

  • +
  • Support Twisted as a reactor. Note that a Twisted-compatible +API is not exposed (so no Deferreds), this is just a reactor +implementation. (github #135, PYTHON-8)

  • +
+
+
+

Bug Fixes

+
    +
  • Fix references to xrange that do not go through “six” in libevreactor and +geventreactor (github #138)

  • +
  • Make BoundStatements inherit fetch_size from their parent +PreparedStatement (PYTHON-80)

  • +
  • Clear reactor state in child process after forking to prevent errors with +multiprocessing when the parent process has connected a Cluster before +forking (github #141)

  • +
  • Don’t share prepared statement lock across Cluster instances

  • +
  • Format CompositeType and DynamicCompositeType columns correctly in +CREATE TABLE statements.

  • +
  • Fix cassandra.concurrent behavior when dealing with automatic paging +(PYTHON-81)

  • +
  • Properly defunct connections after protocol errors

  • +
  • Avoid UnicodeDecodeError when query string is unicode (PYTHON-76)

  • +
  • Correctly capture dclocal_read_repair_chance for tables and +use it when generating CREATE TABLE statements (PYTHON-84)

  • +
  • Avoid race condition with AsyncoreConnection that may cause messages +to fail to be written until a new message is pushed

  • +
  • Make sure cluster.metadata.partitioner and cluster.metadata.token_map +are populated when all nodes in the cluster are included in the +contact points (PYTHON-90)

  • +
  • Make Murmur3 hash match Cassandra’s hash for all values (PYTHON-89, +github #147)

  • +
  • Don’t attempt to reconnect to hosts that should be ignored (according +to the load balancing policy) when a notification is received that the +host is down.

  • +
  • Add CAS WriteType, avoiding KeyError on CAS write timeout (PYTHON-91)

  • +
+
+
+
+

2.0.2

+

June 10, 2014

+
+

Bug Fixes

+
    +
  • Add six to requirements.txt

  • +
  • Avoid KeyError during schema refresh when a keyspace is dropped +and TokenAwarePolicy is not in use

  • +
  • Avoid registering multiple atexit cleanup functions when the +asyncore event loop is restarted multiple times

  • +
  • Delay initialization of reactors in order to avoid problems +with shared state when using multiprocessing (PYTHON-60)

  • +
  • Add python-six to debian dependencies, move python-blist to recommends

  • +
  • Fix memory leak when libev connections are created and +destroyed (github #93)

  • +
  • Ensure token map is rebuilt when hosts are removed from the cluster

  • +
+
+
+
+

2.0.1

+

May 28, 2014

+
+

Bug Fixes

+
    +
  • Fix check for Cluster.is_shutdown in in @run_in_executor +decorator

  • +
+
+
+
+

2.0.0

+

May 28, 2014

+
+

Features

+
    +
  • Make libev C extension Python3-compatible (PYTHON-70)

  • +
  • Support v2 protocol authentication (PYTHON-73, github #125)

  • +
+
+
+

Bug Fixes

+
    +
  • Fix murmur3 C extension compilation under Python3.4 (github #124)

  • +
+
+
+

Merged From 1.x

+
+

Features

+
    +
  • Add Session.default_consistency_level (PYTHON-14)

  • +
+
+
+

Bug Fixes

+
    +
  • Don’t strip trailing underscores from column names when using the +named_tuple_factory (PYTHON-56)

  • +
  • Ensure replication factors are ints for NetworkTopologyStrategy +to avoid TypeErrors (github #120)

  • +
  • Pass WriteType instance to RetryPolicy.on_write_timeout() instead +of the string name of the write type. This caused write timeout +errors to always be rethrown instead of retrying. (github #123)

  • +
  • Avoid submitting tasks to the ThreadPoolExecutor after shutdown. With +retries enabled, this could cause Cluster.shutdown() to hang under +some circumstances.

  • +
  • Fix unintended rebuild of token replica map when keyspaces are +discovered (on startup), added, or updated and TokenAwarePolicy is not +in use.

  • +
  • Avoid rebuilding token metadata when cluster topology has not +actually changed

  • +
  • Avoid preparing queries for hosts that should be ignored (such as +remote hosts when using the DCAwareRoundRobinPolicy) (PYTHON-75)

  • +
+
+
+

Other

+
    +
  • Add 1 second timeout to join() call on event loop thread during +interpreter shutdown. This can help to prevent the process from +hanging during shutdown.

  • +
+
+
+
+
+

2.0.0b1

+

May 6, 2014

+
+

Upgrading from 1.x

+

Cluster.shutdown() should always be called when you are done with a +Cluster instance. If it is not called, there are no guarantees that the +driver will not hang. However, if you do have a reproduceable case +where Cluster.shutdown() is not called and the driver hangs, please +report it so that we can attempt to fix it.

+

If you’re using the 2.0 driver against Cassandra 1.2, you will need +to set your protocol version to 1. For example:

+
+

cluster = Cluster(…, protocol_version=1)

+
+
+
+

Features

+
    +
  • Support v2 of Cassandra’s native protocol, which includes the following +new features: automatic query paging support, protocol-level batch statements, +and lightweight transactions

  • +
  • Support for Python 3.3 and 3.4

  • +
  • Allow a default query timeout to be set per-Session

  • +
+
+
+

Bug Fixes

+
    +
  • Avoid errors during interpreter shutdown (the driver attempts to cleanup +daemonized worker threads before interpreter shutdown)

  • +
+
+
+

Deprecations

+

The following functions have moved from cassandra.decoder to cassandra.query. +The original functions have been left in place with a DeprecationWarning for +now:

+
    +
  • cassandra.decoder.tuple_factory has moved to cassandra.query.tuple_factory

  • +
  • cassandra.decoder.named_tuple_factory has moved to cassandra.query.named_tuple_factory

  • +
  • cassandra.decoder.dict_factory has moved to cassandra.query.dict_factory

  • +
  • cassandra.decoder.ordered_dict_factory has moved to cassandra.query.ordered_dict_factory

  • +
+

Exceptions that were in cassandra.decoder have been moved to cassandra.protocol. If +you handle any of these exceptions, you must adjust the code accordingly.

+
+
+
+

1.1.2

+

May 8, 2014

+
+

Features

+
    +
  • Allow a specific compression type to be requested for communications with +Cassandra and prefer lz4 if available

  • +
+
+
+

Bug Fixes

+
    +
  • Update token metadata (for TokenAware calculations) when a node is removed +from the ring

  • +
  • Fix file handle leak with gevent reactor due to blocking Greenlet kills when +closing excess connections

  • +
  • Avoid handling a node coming up multiple times due to a reconnection attempt +succeeding close to the same time that an UP notification is pushed

  • +
  • Fix duplicate node-up handling, which could result in multiple reconnectors +being started as well as the executor threads becoming deadlocked, preventing +future node up or node down handling from being executed.

  • +
  • Handle exhausted ReconnectionPolicy schedule correctly

  • +
+
+
+

Other

+
    +
  • Don’t log at ERROR when a connection is closed during the startup +communications

  • +
  • Mke scales, blist optional dependencies

  • +
+
+
+
+

1.1.1

+

April 16, 2014

+
+

Bug Fixes

+
    +
  • Fix unconditional import of nose in setup.py (github #111)

  • +
+
+
+
+

1.1.0

+

April 16, 2014

+
+

Features

+
    +
  • Gevent is now supported through monkey-patching the stdlib (PYTHON-7, +github issue #46)

  • +
  • Support static columns in schemas, which are available starting in +Cassandra 2.1. (github issue #91)

  • +
  • Add debian packaging (github issue #101)

  • +
  • Add utility methods for easy concurrent execution of statements. See +the new cassandra.concurrent module. (github issue #7)

  • +
+
+
+

Bug Fixes

+
    +
  • Correctly supply compaction and compression parameters in CREATE statements +for tables when working with Cassandra 2.0+

  • +
  • Lowercase boolean literals when generating schemas

  • +
  • Ignore SSL_ERROR_WANT_READ and SSL_ERROR_WANT_WRITE socket errors. Previously, +these resulted in the connection being defuncted, but they can safely be +ignored by the driver.

  • +
  • Don’t reconnect the control connection every time Cluster.connect() is +called

  • +
  • Avoid race condition that could leave ResponseFuture callbacks uncalled +if the callback was added outside of the event loop thread (github issue #95)

  • +
  • Properly escape keyspace name in Session.set_keyspace(). Previously, the +keyspace name was quoted, but any quotes in the string were not escaped.

  • +
  • Avoid adding hosts to the load balancing policy before their datacenter +and rack information has been set, if possible.

  • +
  • Avoid KeyError when updating metadata after droping a table (github issues +#97, #98)

  • +
  • Use tuples instead of sets for DCAwareLoadBalancingPolicy to ensure equal +distribution of requests

  • +
+
+
+

Other

+
    +
  • Don’t ignore column names when parsing typestrings. This is needed for +user-defined type support. (github issue #90)

  • +
  • Better error message when libevwrapper is not found

  • +
  • Only try to import scales when metrics are enabled (github issue #92)

  • +
  • Cut down on the number of queries executing when a new Cluster +connects and when the control connection has to reconnect (github issue #104, +PYTHON-59)

  • +
  • Issue warning log when schema versions do not match

  • +
+
+
+
+

1.0.2

+

March 4, 2014

+
+

Bug Fixes

+
    +
  • With asyncorereactor, correctly handle EAGAIN/EWOULDBLOCK when the message from +Cassandra is a multiple of the read buffer size. Previously, if no more data +became available to read on the socket, the message would never be processed, +resulting in an OperationTimedOut error.

  • +
  • Double quote keyspace, table and column names that require them (those using +uppercase characters or keywords) when generating CREATE statements through +KeyspaceMetadata and TableMetadata.

  • +
  • Decode TimestampType as DateType. (Cassandra replaced DateType with +TimestampType to fix sorting of pre-unix epoch dates in CASSANDRA-5723.)

  • +
  • Handle latest table options when parsing the schema and generating +CREATE statements.

  • +
  • Avoid ‘Set changed size during iteration’ during query plan generation +when hosts go up or down

  • +
+
+
+

Other

+
    +
  • Remove ignored tracing_enabled parameter for SimpleStatement. The +correct way to trace a query is by setting the trace argument to True +in Session.execute() and Session.execute_async().

  • +
  • Raise TypeError instead of cassandra.query.InvalidParameterTypeError when +a parameter for a prepared statement has the wrong type; remove +cassandra.query.InvalidParameterTypeError.

  • +
  • More consistent type checking for query parameters

  • +
  • Add option to a return special object for empty string values for non-string +columns

  • +
+
+
+
+

1.0.1

+

Feb 19, 2014

+
+

Bug Fixes

+
    +
  • Include table indexes in KeyspaceMetadata.export_as_string()

  • +
  • Fix broken token awareness on ByteOrderedPartitioner

  • +
  • Always close socket when defuncting error’ed connections to avoid a potential +file descriptor leak

  • +
  • Handle “custom” types (such as the replaced DateType) correctly

  • +
  • With libevreactor, correctly handle EAGAIN/EWOULDBLOCK when the message from +Cassandra is a multiple of the read buffer size. Previously, if no more data +became available to read on the socket, the message would never be processed, +resulting in an OperationTimedOut error.

  • +
  • Don’t break tracing when a Session’s row_factory is not the default +namedtuple_factory.

  • +
  • Handle data that is already utf8-encoded for UTF8Type values

  • +
  • Fix token-aware routing for tokens that fall before the first node token in +the ring and tokens that exactly match a node’s token

  • +
  • Tolerate null source_elapsed values for Trace events. These may not be +set when events complete after the main operation has already completed.

  • +
+
+
+

Other

+
    +
  • Skip sending OPTIONS message on connection creation if compression is +disabled or not available and a CQL version has not been explicitly +set

  • +
  • Add details about errors and the last queried host to OperationTimedOut

  • +
+
+
+
+

1.0.0 Final

+

Jan 29, 2014

+
+

Bug Fixes

+
    +
  • Prevent leak of Scheduler thread (even with proper shutdown)

  • +
  • Correctly handle ignored hosts, which are common with the +DCAwareRoundRobinPolicy

  • +
  • Hold strong reference to prepared statement while executing it to avoid +garbage collection

  • +
  • Add NullHandler logging handler to the cassandra package to avoid +warnings about there being no configured logger

  • +
  • Fix bad handling of nodes that have been removed from the cluster

  • +
  • Properly escape string types within cql collections

  • +
  • Handle setting the same keyspace twice in a row

  • +
  • Avoid race condition during schema agreement checks that could result +in schema update queries returning before all nodes had seen the change

  • +
  • Preserve millisecond-level precision in datetimes when performing inserts +with simple (non-prepared) statements

  • +
  • Properly defunct connections when libev reports an error by setting +errno instead of simply logging the error

  • +
  • Fix endless hanging of some requests when using the libev reactor

  • +
  • Always start a reconnection process when we fail to connect to +a newly bootstrapped node

  • +
  • Generators map to CQL lists, not key sequences

  • +
  • Always defunct connections when an internal operation fails

  • +
  • Correctly break from handle_write() if nothing was sent (asyncore +reactor only)

  • +
  • Avoid potential double-erroring of callbacks when a connection +becomes defunct

  • +
+
+
+

Features

+
    +
  • Add default query timeout to Session

  • +
  • Add timeout parameter to Session.execute()

  • +
  • Add WhiteListRoundRobinPolicy as a load balancing policy option

  • +
  • Support for consistency level LOCAL_ONE

  • +
  • Make the backoff for fetching traces exponentially increasing and +configurable

  • +
+
+
+

Other

+
    +
  • Raise Exception if TokenAwarePolicy is used against a cluster using the +Murmur3Partitioner if the murmur3 C extension has not been compiled

  • +
  • Add encoder mapping for OrderedDict

  • +
  • Use timeouts on all control connection queries

  • +
  • Benchmark improvements, including command line options and eay +multithreading support

  • +
  • Reduced lock contention when using the asyncore reactor

  • +
  • Warn when non-datetimes are used for ‘timestamp’ column values in +prepared statements

  • +
  • Add requirements.txt and test-requirements.txt

  • +
  • TravisCI integration for running unit tests against Python 2.6, +Python 2.7, and PyPy

  • +
+
+
+
+

1.0.0b7

+

Nov 12, 2013

+

This release makes many stability improvements, especially around +prepared statements and node failure handling. In particular, +several cases where a request would never be completed (and as a +result, leave the application hanging) have been resolved.

+
+

Features

+
    +
  • Add timeout kwarg to ResponseFuture.result()

  • +
  • Create connection pools to all hosts in parallel when initializing +new Sesssions.

  • +
+
+
+

Bug Fixes

+
    +
  • Properly set exception on ResponseFuture when a query fails +against all hosts

  • +
  • Improved cleanup and reconnection efforts when reconnection fails +on a node that has recently come up

  • +
  • Use correct consistency level when retrying failed operations +against a different host. (An invalid consistency level was being +used, causing the retry to fail.)

  • +
  • Better error messages for failed Session.prepare() opertaions

  • +
  • Prepare new statements against all hosts in parallel (formerly +sequential)

  • +
  • Fix failure to save the new current keyspace on connections. (This +could cause problems for prepared statements and lead to extra +operations to continuously re-set the keyspace.)

  • +
  • Avoid sharing LoadBalancingPolicies across Cluster instances. (When +a second Cluster was connected, it effectively mark nodes down for the +first Cluster.)

  • +
  • Better handling of failures during the re-preparation sequence for +unrecognized prepared statements

  • +
  • Throttle trashing of underutilized connections to avoid trashing newly +created connections

  • +
  • Fix race condition which could result in trashed connections being closed +before the last operations had completed

  • +
  • Avoid preparing statements on the event loop thread (which could lead to +deadlock)

  • +
  • Correctly mark up non-contact point nodes discovered by the control +connection. (This lead to prepared statements not being prepared +against those hosts, generating extra traffic later when the +statements were executed and unrecognized.)

  • +
  • Correctly handle large messages through libev

  • +
  • Add timeout to schema agreement check queries

  • +
  • More complete (and less contended) locking around manipulation of the +pending message deque for libev connections

  • +
+
+
+

Other

+
    +
  • Prepare statements in batches of 10. (When many prepared statements +are in use, this allows the driver to start utilizing nodes that +were restarted more quickly.)

  • +
  • Better debug logging around connection management

  • +
  • Don’t retain unreferenced prepared statements in the local cache. +(If many different prepared statements were created, this would +increase memory usage and greatly increase the amount of time +required to begin utilizing a node that was added or marked +up.)

  • +
+
+
+
+

1.0.0b6

+

Oct 22, 2013

+
+

Bug Fixes

+
    +
  • Use lazy string formatting when logging

  • +
  • Avoid several deadlock scenarios, especially when nodes go down

  • +
  • Avoid trashing newly created connections due to insufficient traffic

  • +
  • Gracefully handle un-handled Exceptions when erroring callbacks

  • +
+
+
+

Other

+
    +
  • Node state listeners (which are called when a node is added, removed, +goes down, or comes up) should now be registered through +Cluster.register_listener() instead of through a host’s HealthMonitor +(which has been removed)

  • +
+
+
+
+

1.0.0b5

+

Oct 10, 2013

+
+

Features

+
    +
  • SSL support

  • +
+
+
+

Bug Fixes

+
    +
  • Avoid KeyError when building replica map for NetworkTopologyStrategy

  • +
  • Work around python bug which causes deadlock when a thread imports +the utf8 module

  • +
  • Handle no blist library, which is not compatible with pypy

  • +
  • Avoid deadlock triggered by a keyspace being set on a connection (which +may happen automatically for new connections)

  • +
+
+
+

Other

+
    +
  • Switch packaging from Distribute to setuptools, improved C extension +support

  • +
  • Use PEP 386 compliant beta and post-release versions

  • +
+
+
+
+

1.0.0-beta4

+

Sep 24, 2013

+
+

Features

+
    +
  • Handle new blob syntax in Cassandra 2.0 by accepting bytearray +objects for blob values

  • +
  • Add cql_version kwarg to Cluster.__init__

  • +
+
+
+

Bug Fixes

+
    +
  • Fix KeyError when building token map with NetworkTopologyStrategy +keyspaces (this prevented a Cluster from successfully connecting +at all).

  • +
  • Don’t lose default consitency level from parent PreparedStatement +when creating BoundStatements

  • +
+
+
+
+

1.0.0-beta3

+

Sep 20, 2013

+
+

Features

+
    +
  • Support for LZ4 compression (Cassandra 2.0+)

  • +
  • Token-aware routing will now utilize all replicas for a query instead +of just the first replica

  • +
+
+
+

Bug Fixes

+
    +
  • Fix libev include path for CentOS

  • +
  • Fix varint packing of the value 0

  • +
  • Correctly pack unicode values

  • +
  • Don’t attempt to return failed connections to the pool when a final result +is set

  • +
  • Fix bad iteration of connection credentials

  • +
  • Use blist’s orderedset for set collections and OrderedDict for map +collections so that Cassandra’s ordering is preserved

  • +
  • Fix connection failure on Windows due to unavailability of inet_pton +and inet_ntop. (Note that IPv6 inet_address values are still not +supported on Windows.)

  • +
  • Boolean constants shouldn’t be surrounded by single quotes

  • +
  • Avoid a potential loss of precision on float constants due to string +formatting

  • +
  • Actually utilize non-standard ports set on Cluster objects

  • +
  • Fix export of schema as a set of CQL queries

  • +
+
+
+

Other

+
    +
  • Use cStringIO for connection buffer for better performance

  • +
  • Add __repr__ method for Statement classes

  • +
  • Raise InvalidTypeParameterError when parameters of the wrong +type are used with statements

  • +
  • Make all tests compatible with Python 2.6

  • +
  • Add 1s timeout for opening new connections

  • +
+
+
+
+

1.0.0-beta2

+

Aug 19, 2013

+
+

Bug Fixes

+
    +
  • Fix pip packaging

  • +
+
+
+
+

1.0.0-beta

+

Aug 16, 2013

+

Initial release

+
+
+ + +
+ + + + + +
+ + +
+
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.22.3-scylla/CNAME b/3.22.3-scylla/CNAME new file mode 100644 index 0000000000..9f3e01a070 --- /dev/null +++ b/3.22.3-scylla/CNAME @@ -0,0 +1 @@ +python-driver.docs.scylladb.com \ No newline at end of file diff --git a/3.22.3-scylla/_sources/CHANGELOG.rst.txt b/3.22.3-scylla/_sources/CHANGELOG.rst.txt new file mode 100644 index 0000000000..f6d642b27f --- /dev/null +++ b/3.22.3-scylla/_sources/CHANGELOG.rst.txt @@ -0,0 +1,7 @@ +:orphan: + +********* +CHANGELOG +********* + +.. include:: ../CHANGELOG.rst diff --git a/3.22.3-scylla/_sources/api/cassandra.rst.txt b/3.22.3-scylla/_sources/api/cassandra.rst.txt new file mode 100644 index 0000000000..d46aae56cb --- /dev/null +++ b/3.22.3-scylla/_sources/api/cassandra.rst.txt @@ -0,0 +1,77 @@ +:mod:`cassandra` - Exceptions and Enums +======================================= + +.. module:: cassandra + +.. data:: __version_info__ + + The version of the driver in a tuple format + +.. data:: __version__ + + The version of the driver in a string format + +.. autoclass:: ConsistencyLevel + :members: + +.. autoclass:: ProtocolVersion + :members: + +.. autoclass:: UserFunctionDescriptor + :members: + :inherited-members: + +.. autoclass:: UserAggregateDescriptor + :members: + :inherited-members: + +.. autoexception:: DriverException() + :members: + +.. autoexception:: RequestExecutionException() + :members: + +.. autoexception:: Unavailable() + :members: + +.. autoexception:: Timeout() + :members: + +.. autoexception:: ReadTimeout() + :members: + +.. autoexception:: WriteTimeout() + :members: + +.. autoexception:: CoordinationFailure() + :members: + +.. autoexception:: ReadFailure() + :members: + +.. autoexception:: WriteFailure() + :members: + +.. autoexception:: FunctionFailure() + :members: + +.. autoexception:: RequestValidationException() + :members: + +.. autoexception:: ConfigurationException() + :members: + +.. autoexception:: AlreadyExists() + :members: + +.. autoexception:: InvalidRequest() + :members: + +.. autoexception:: Unauthorized() + :members: + +.. autoexception:: AuthenticationFailed() + :members: + +.. autoexception:: OperationTimedOut() + :members: diff --git a/3.22.3-scylla/_sources/api/cassandra/auth.rst.txt b/3.22.3-scylla/_sources/api/cassandra/auth.rst.txt new file mode 100644 index 0000000000..58c964cf89 --- /dev/null +++ b/3.22.3-scylla/_sources/api/cassandra/auth.rst.txt @@ -0,0 +1,22 @@ +``cassandra.auth`` - Authentication +=================================== + +.. module:: cassandra.auth + +.. autoclass:: AuthProvider + :members: + +.. autoclass:: Authenticator + :members: + +.. autoclass:: PlainTextAuthProvider + :members: + +.. autoclass:: PlainTextAuthenticator + :members: + +.. autoclass:: SaslAuthProvider + :members: + +.. autoclass:: SaslAuthenticator + :members: diff --git a/3.22.3-scylla/_sources/api/cassandra/cluster.rst.txt b/3.22.3-scylla/_sources/api/cassandra/cluster.rst.txt new file mode 100644 index 0000000000..2b3d7828a8 --- /dev/null +++ b/3.22.3-scylla/_sources/api/cassandra/cluster.rst.txt @@ -0,0 +1,228 @@ +``cassandra.cluster`` - Clusters and Sessions +============================================= + +.. module:: cassandra.cluster + +.. autoclass:: Cluster ([contact_points=('127.0.0.1',)][, port=9042][, executor_threads=2], **attr_kwargs) + + .. autoattribute:: contact_points + + .. autoattribute:: port + + .. autoattribute:: cql_version + + .. autoattribute:: protocol_version + + .. autoattribute:: compression + + .. autoattribute:: auth_provider + + .. autoattribute:: load_balancing_policy + + .. autoattribute:: reconnection_policy + + .. autoattribute:: default_retry_policy + :annotation: = + + .. autoattribute:: conviction_policy_factory + + .. autoattribute:: address_translator + + .. autoattribute:: metrics_enabled + + .. autoattribute:: metrics + + .. autoattribute:: ssl_context + + .. autoattribute:: ssl_options + + .. autoattribute:: sockopts + + .. autoattribute:: max_schema_agreement_wait + + .. autoattribute:: metadata + + .. autoattribute:: connection_class + + .. autoattribute:: control_connection_timeout + + .. autoattribute:: idle_heartbeat_interval + + .. autoattribute:: idle_heartbeat_timeout + + .. autoattribute:: schema_event_refresh_window + + .. autoattribute:: topology_event_refresh_window + + .. autoattribute:: status_event_refresh_window + + .. autoattribute:: prepare_on_all_hosts + + .. autoattribute:: reprepare_on_up + + .. autoattribute:: connect_timeout + + .. autoattribute:: schema_metadata_enabled + :annotation: = True + + .. autoattribute:: token_metadata_enabled + :annotation: = True + + .. autoattribute:: timestamp_generator + + .. autoattribute:: endpoint_factory + + .. autoattribute:: cloud + + .. automethod:: connect + + .. automethod:: shutdown + + .. automethod:: register_user_type + + .. automethod:: register_listener + + .. automethod:: unregister_listener + + .. automethod:: add_execution_profile + + .. automethod:: set_max_requests_per_connection + + .. automethod:: get_max_requests_per_connection + + .. automethod:: set_min_requests_per_connection + + .. automethod:: get_min_requests_per_connection + + .. automethod:: get_core_connections_per_host + + .. automethod:: set_core_connections_per_host + + .. automethod:: get_max_connections_per_host + + .. automethod:: set_max_connections_per_host + + .. automethod:: get_control_connection_host + + .. automethod:: refresh_schema_metadata + + .. automethod:: refresh_keyspace_metadata + + .. automethod:: refresh_table_metadata + + .. automethod:: refresh_user_type_metadata + + .. automethod:: refresh_user_function_metadata + + .. automethod:: refresh_user_aggregate_metadata + + .. automethod:: refresh_nodes + + .. automethod:: set_meta_refresh_enabled + +.. autoclass:: ExecutionProfile (load_balancing_policy=, retry_policy=None, consistency_level=ConsistencyLevel.LOCAL_ONE, serial_consistency_level=None, request_timeout=10.0, row_factory=, speculative_execution_policy=None) + :members: + :exclude-members: consistency_level + + .. autoattribute:: consistency_level + :annotation: = LOCAL_ONE + +.. autoclass:: GraphExecutionProfile (load_balancing_policy=_NOT_SET, retry_policy=None, consistency_level=ConsistencyLevel.LOCAL_ONE, serial_consistency_level=None, request_timeout=30.0, row_factory=None, graph_options=None, continuous_paging_options=_NOT_SET) + :members: + +.. autoclass:: GraphAnalyticsExecutionProfile (load_balancing_policy=None, retry_policy=None, consistency_level=ConsistencyLevel.LOCAL_ONE, serial_consistency_level=None, request_timeout=3600. * 24. * 7., row_factory=None, graph_options=None) + :members: + +.. autodata:: EXEC_PROFILE_DEFAULT + :annotation: + +.. autodata:: EXEC_PROFILE_GRAPH_DEFAULT + :annotation: + +.. autodata:: EXEC_PROFILE_GRAPH_SYSTEM_DEFAULT + :annotation: + +.. autodata:: EXEC_PROFILE_GRAPH_ANALYTICS_DEFAULT + :annotation: + +.. autoclass:: Session () + + .. autoattribute:: default_timeout + :annotation: = 10.0 + + .. autoattribute:: default_consistency_level + :annotation: = LOCAL_ONE + + .. autoattribute:: default_serial_consistency_level + :annotation: = None + + .. autoattribute:: row_factory + :annotation: = + + .. autoattribute:: default_fetch_size + + .. autoattribute:: use_client_timestamp + + .. autoattribute:: timestamp_generator + + .. autoattribute:: encoder + + .. autoattribute:: client_protocol_handler + + .. automethod:: execute(statement[, parameters][, timeout][, trace][, custom_payload][, paging_state][, host][, execute_as]) + + .. automethod:: execute_async(statement[, parameters][, trace][, custom_payload][, paging_state][, host][, execute_as]) + + .. automethod:: execute_graph(statement[, parameters][, trace][, execution_profile=EXEC_PROFILE_GRAPH_DEFAULT][, execute_as]) + + .. automethod:: execute_graph_async(statement[, parameters][, trace][, execution_profile=EXEC_PROFILE_GRAPH_DEFAULT][, execute_as]) + + .. automethod:: prepare(statement) + + .. automethod:: shutdown() + + .. automethod:: set_keyspace(keyspace) + + .. automethod:: get_execution_profile + + .. automethod:: execution_profile_clone_update + + .. automethod:: add_request_init_listener + + .. automethod:: remove_request_init_listener + +.. autoclass:: ResponseFuture () + + .. autoattribute:: query + + .. automethod:: result() + + .. automethod:: get_query_trace() + + .. automethod:: get_all_query_traces() + + .. autoattribute:: custom_payload() + + .. autoattribute:: is_schema_agreed + + .. autoattribute:: has_more_pages + + .. autoattribute:: warnings + + .. automethod:: start_fetching_next_page() + + .. automethod:: add_callback(fn, *args, **kwargs) + + .. automethod:: add_errback(fn, *args, **kwargs) + + .. automethod:: add_callbacks(callback, errback, callback_args=(), callback_kwargs=None, errback_args=(), errback_args=None) + +.. autoclass:: ResultSet () + :members: + +.. autoexception:: QueryExhausted () + +.. autoexception:: NoHostAvailable () + :members: + +.. autoexception:: UserTypeDoesNotExist () diff --git a/3.22.3-scylla/_sources/api/cassandra/concurrent.rst.txt b/3.22.3-scylla/_sources/api/cassandra/concurrent.rst.txt new file mode 100644 index 0000000000..f4bab6f048 --- /dev/null +++ b/3.22.3-scylla/_sources/api/cassandra/concurrent.rst.txt @@ -0,0 +1,8 @@ +``cassandra.concurrent`` - Utilities for Concurrent Statement Execution +======================================================================= + +.. module:: cassandra.concurrent + +.. autofunction:: execute_concurrent + +.. autofunction:: execute_concurrent_with_args diff --git a/3.22.3-scylla/_sources/api/cassandra/connection.rst.txt b/3.22.3-scylla/_sources/api/cassandra/connection.rst.txt new file mode 100644 index 0000000000..32cca590c0 --- /dev/null +++ b/3.22.3-scylla/_sources/api/cassandra/connection.rst.txt @@ -0,0 +1,21 @@ +``cassandra.connection`` - Low Level Connection Info +==================================================== + +.. module:: cassandra.connection + +.. autoexception:: ConnectionException () +.. autoexception:: ConnectionShutdown () +.. autoexception:: ConnectionBusy () +.. autoexception:: ProtocolError () + +.. autoclass:: EndPoint + :members: + +.. autoclass:: EndPointFactory + :members: + +.. autoclass:: SniEndPoint + +.. autoclass:: SniEndPointFactory + +.. autoclass:: UnixSocketEndPoint diff --git a/3.22.3-scylla/_sources/api/cassandra/cqlengine/columns.rst.txt b/3.22.3-scylla/_sources/api/cassandra/cqlengine/columns.rst.txt new file mode 100644 index 0000000000..d44be8adb8 --- /dev/null +++ b/3.22.3-scylla/_sources/api/cassandra/cqlengine/columns.rst.txt @@ -0,0 +1,89 @@ +``cassandra.cqlengine.columns`` - Column types for object mapping models +======================================================================== + +.. module:: cassandra.cqlengine.columns + +Columns +------- + +Columns in your models map to columns in your CQL table. You define CQL columns by defining column attributes on your model classes. +For a model to be valid it needs at least one primary key column and one non-primary key column. + +Just as in CQL, the order you define your columns in is important, and is the same order they are defined in on a model's corresponding table. + +Each column on your model definitions needs to be an instance of a Column class. + +.. autoclass:: Column(**kwargs) + + .. autoattribute:: primary_key + + .. autoattribute:: partition_key + + .. autoattribute:: index + + .. autoattribute:: custom_index + + .. autoattribute:: db_field + + .. autoattribute:: default + + .. autoattribute:: required + + .. autoattribute:: clustering_order + + .. autoattribute:: discriminator_column + + .. autoattribute:: static + +Column Types +------------ + +Columns of all types are initialized by passing :class:`.Column` attributes to the constructor by keyword. + +.. autoclass:: Ascii(**kwargs) + +.. autoclass:: BigInt(**kwargs) + +.. autoclass:: Blob(**kwargs) + +.. autoclass:: Bytes(**kwargs) + +.. autoclass:: Boolean(**kwargs) + +.. autoclass:: Counter + +.. autoclass:: Date(**kwargs) + +.. autoclass:: DateTime(**kwargs) + + .. autoattribute:: truncate_microseconds + +.. autoclass:: Decimal(**kwargs) + +.. autoclass:: Double(**kwargs) + +.. autoclass:: Float + +.. autoclass:: Integer(**kwargs) + +.. autoclass:: List + +.. autoclass:: Map + +.. autoclass:: Set + +.. autoclass:: SmallInt(**kwargs) + +.. autoclass:: Text + +.. autoclass:: Time(**kwargs) + +.. autoclass:: TimeUUID(**kwargs) + +.. autoclass:: TinyInt(**kwargs) + +.. autoclass:: UserDefinedType + +.. autoclass:: UUID(**kwargs) + +.. autoclass:: VarInt(**kwargs) diff --git a/3.22.3-scylla/_sources/api/cassandra/cqlengine/connection.rst.txt b/3.22.3-scylla/_sources/api/cassandra/cqlengine/connection.rst.txt new file mode 100644 index 0000000000..0f584fcca2 --- /dev/null +++ b/3.22.3-scylla/_sources/api/cassandra/cqlengine/connection.rst.txt @@ -0,0 +1,16 @@ +``cassandra.cqlengine.connection`` - Connection management for cqlengine +======================================================================== + +.. module:: cassandra.cqlengine.connection + +.. autofunction:: default + +.. autofunction:: set_session + +.. autofunction:: setup + +.. autofunction:: register_connection + +.. autofunction:: unregister_connection + +.. autofunction:: set_default_connection diff --git a/3.22.3-scylla/_sources/api/cassandra/cqlengine/management.rst.txt b/3.22.3-scylla/_sources/api/cassandra/cqlengine/management.rst.txt new file mode 100644 index 0000000000..fb483abc81 --- /dev/null +++ b/3.22.3-scylla/_sources/api/cassandra/cqlengine/management.rst.txt @@ -0,0 +1,19 @@ +``cassandra.cqlengine.management`` - Schema management for cqlengine +======================================================================== + +.. module:: cassandra.cqlengine.management + +A collection of functions for managing keyspace and table schema. + +.. autofunction:: create_keyspace_simple + +.. autofunction:: create_keyspace_network_topology + +.. autofunction:: drop_keyspace + +.. autofunction:: sync_table + +.. autofunction:: sync_type + +.. autofunction:: drop_table + diff --git a/3.22.3-scylla/_sources/api/cassandra/cqlengine/models.rst.txt b/3.22.3-scylla/_sources/api/cassandra/cqlengine/models.rst.txt new file mode 100644 index 0000000000..60b1471184 --- /dev/null +++ b/3.22.3-scylla/_sources/api/cassandra/cqlengine/models.rst.txt @@ -0,0 +1,197 @@ +``cassandra.cqlengine.models`` - Table models for object mapping +================================================================ + +.. module:: cassandra.cqlengine.models + +Model +----- +.. autoclass:: Model(\*\*kwargs) + + The initializer creates an instance of the model. Pass in keyword arguments for columns you've defined on the model. + + .. code-block:: python + + class Person(Model): + id = columns.UUID(primary_key=True) + first_name = columns.Text() + last_name = columns.Text() + + person = Person(first_name='Blake', last_name='Eggleston') + person.first_name #returns 'Blake' + person.last_name #returns 'Eggleston' + + Model attributes define how the model maps to tables in the database. These are class variables that should be set + when defining Model deriviatives. + + .. autoattribute:: __abstract__ + :annotation: = False + + .. autoattribute:: __table_name__ + + .. autoattribute:: __table_name_case_sensitive__ + + .. autoattribute:: __keyspace__ + + .. autoattribute:: __connection__ + + .. attribute:: __default_ttl__ + :annotation: = None + + Will be deprecated in release 4.0. You can set the default ttl by configuring the table ``__options__``. See :ref:`ttl-change` for more details. + + .. autoattribute:: __discriminator_value__ + + See :ref:`model_inheritance` for usage examples. + + Each table can have its own set of configuration options, including compaction. Unspecified, these default to sensible values in + the server. To override defaults, set options using the model ``__options__`` attribute, which allows options specified a dict. + + When a table is synced, it will be altered to match the options set on your table. + This means that if you are changing settings manually they will be changed back on resync. + + Do not use the options settings of cqlengine if you want to manage your compaction settings manually. + + See the `list of supported table properties for more information + `_. + + .. attribute:: __options__ + + For example: + + .. code-block:: python + + class User(Model): + __options__ = {'compaction': {'class': 'LeveledCompactionStrategy', + 'sstable_size_in_mb': '64', + 'tombstone_threshold': '.2'}, + 'comment': 'User data stored here'} + + user_id = columns.UUID(primary_key=True) + name = columns.Text() + + or : + + .. code-block:: python + + class TimeData(Model): + __options__ = {'compaction': {'class': 'SizeTieredCompactionStrategy', + 'bucket_low': '.3', + 'bucket_high': '2', + 'min_threshold': '2', + 'max_threshold': '64', + 'tombstone_compaction_interval': '86400'}, + 'gc_grace_seconds': '0'} + + .. autoattribute:: __compute_routing_key__ + + + The base methods allow creating, storing, and querying modeled objects. + + .. automethod:: create + + .. method:: if_not_exists() + + Check the existence of an object before insertion. The existence of an + object is determined by its primary key(s). And please note using this flag + would incur performance cost. + + If the insertion isn't applied, a :class:`~cassandra.cqlengine.query.LWTException` is raised. + + .. code-block:: python + + try: + TestIfNotExistsModel.if_not_exists().create(id=id, count=9, text='111111111111') + except LWTException as e: + # handle failure case + print e.existing # dict containing LWT result fields + + This method is supported on Cassandra 2.0 or later. + + .. method:: if_exists() + + Check the existence of an object before an update or delete. The existence of an + object is determined by its primary key(s). And please note using this flag + would incur performance cost. + + If the update or delete isn't applied, a :class:`~cassandra.cqlengine.query.LWTException` is raised. + + .. code-block:: python + + try: + TestIfExistsModel.objects(id=id).if_exists().update(count=9, text='111111111111') + except LWTException as e: + # handle failure case + pass + + This method is supported on Cassandra 2.0 or later. + + .. automethod:: save + + .. automethod:: update + + .. method:: iff(**values) + + Checks to ensure that the values specified are correct on the Cassandra cluster. + Simply specify the column(s) and the expected value(s). As with if_not_exists, + this incurs a performance cost. + + If the insertion isn't applied, a :class:`~cassandra.cqlengine.query.LWTException` is raised. + + .. code-block:: python + + t = TestTransactionModel(text='some text', count=5) + try: + t.iff(count=5).update('other text') + except LWTException as e: + # handle failure case + print e.existing # existing object + + .. automethod:: get + + .. automethod:: filter + + .. automethod:: all + + .. automethod:: delete + + .. method:: batch(batch_object) + + Sets the batch object to run instance updates and inserts queries with. + + See :doc:`/cqlengine/batches` for usage examples + + .. automethod:: timeout + + .. method:: timestamp(timedelta_or_datetime) + + Sets the timestamp for the query + + .. method:: ttl(ttl_in_sec) + + Sets the ttl values to run instance updates and inserts queries with. + + .. method:: using(connection=None) + + Change the context on the fly of the model instance (keyspace, connection) + + .. automethod:: column_family_name + + Models also support dict-like access: + + .. method:: len(m) + + Returns the number of columns defined in the model + + .. method:: m[col_name] + + Returns the value of column ``col_name`` + + .. method:: m[col_name] = value + + Set ``m[col_name]`` to value + + .. automethod:: keys + + .. automethod:: values + + .. automethod:: items diff --git a/3.22.3-scylla/_sources/api/cassandra/cqlengine/query.rst.txt b/3.22.3-scylla/_sources/api/cassandra/cqlengine/query.rst.txt new file mode 100644 index 0000000000..ce8f764b6b --- /dev/null +++ b/3.22.3-scylla/_sources/api/cassandra/cqlengine/query.rst.txt @@ -0,0 +1,71 @@ +``cassandra.cqlengine.query`` - Query and filter model objects +================================================================= + +.. module:: cassandra.cqlengine.query + +QuerySet +-------- +QuerySet objects are typically obtained by calling :meth:`~.cassandra.cqlengine.models.Model.objects` on a model class. +The methods here are used to filter, order, and constrain results. + +.. autoclass:: ModelQuerySet + + .. automethod:: all + + .. automethod:: batch + + .. automethod:: consistency + + .. automethod:: count + + .. method:: len(queryset) + + Returns the number of rows matched by this query. This function uses :meth:`~.cassandra.cqlengine.query.ModelQuerySet.count` internally. + + *Note: This function executes a SELECT COUNT() and has a performance cost on large datasets* + + .. automethod:: distinct + + .. automethod:: filter + + .. automethod:: get + + .. automethod:: limit + + .. automethod:: fetch_size + + .. automethod:: if_not_exists + + .. automethod:: if_exists + + .. automethod:: order_by + + .. automethod:: allow_filtering + + .. automethod:: only + + .. automethod:: defer + + .. automethod:: timestamp + + .. automethod:: ttl + + .. automethod:: using + + .. _blind_updates: + + .. automethod:: update + +.. autoclass:: BatchQuery + :members: + + .. automethod:: add_query + .. automethod:: execute + +.. autoclass:: ContextQuery + +.. autoclass:: DoesNotExist + +.. autoclass:: MultipleObjectsReturned + +.. autoclass:: LWTException diff --git a/3.22.3-scylla/_sources/api/cassandra/cqlengine/usertype.rst.txt b/3.22.3-scylla/_sources/api/cassandra/cqlengine/usertype.rst.txt new file mode 100644 index 0000000000..ebed187da9 --- /dev/null +++ b/3.22.3-scylla/_sources/api/cassandra/cqlengine/usertype.rst.txt @@ -0,0 +1,10 @@ +``cassandra.cqlengine.usertype`` - Model classes for User Defined Types +======================================================================= + +.. module:: cassandra.cqlengine.usertype + +UserType +-------- +.. autoclass:: UserType + + .. autoattribute:: __type_name__ diff --git a/3.22.3-scylla/_sources/api/cassandra/datastax/graph/fluent/index.rst.txt b/3.22.3-scylla/_sources/api/cassandra/datastax/graph/fluent/index.rst.txt new file mode 100644 index 0000000000..5547e0fdd7 --- /dev/null +++ b/3.22.3-scylla/_sources/api/cassandra/datastax/graph/fluent/index.rst.txt @@ -0,0 +1,24 @@ +:mod:`cassandra.datastax.graph.fluent` +====================================== + +.. module:: cassandra.datastax.graph.fluent + +.. autoclass:: DseGraph + + .. autoattribute:: DSE_GRAPH_QUERY_LANGUAGE + + .. automethod:: create_execution_profile + + .. automethod:: query_from_traversal + + .. automethod:: traversal_source(session=None, graph_name=None, execution_profile=EXEC_PROFILE_GRAPH_DEFAULT, traversal_class=None) + + .. automethod:: batch(session=None, execution_profile=None) + +.. autoclass:: DSESessionRemoteGraphConnection(session[, graph_name, execution_profile]) + +.. autoclass:: BaseGraphRowFactory + +.. autoclass:: graph_traversal_row_factory + +.. autoclass:: graph_traversal_dse_object_row_factory diff --git a/3.22.3-scylla/_sources/api/cassandra/datastax/graph/fluent/predicates.rst.txt b/3.22.3-scylla/_sources/api/cassandra/datastax/graph/fluent/predicates.rst.txt new file mode 100644 index 0000000000..f6e86f6451 --- /dev/null +++ b/3.22.3-scylla/_sources/api/cassandra/datastax/graph/fluent/predicates.rst.txt @@ -0,0 +1,14 @@ +:mod:`cassandra.datastax.graph.fluent.predicates` +================================================= + +.. module:: cassandra.datastax.graph.fluent.predicates + + +.. autoclass:: Search + :members: + +.. autoclass:: CqlCollection + :members: + +.. autoclass:: Geo + :members: diff --git a/3.22.3-scylla/_sources/api/cassandra/datastax/graph/fluent/query.rst.txt b/3.22.3-scylla/_sources/api/cassandra/datastax/graph/fluent/query.rst.txt new file mode 100644 index 0000000000..3dd859f96e --- /dev/null +++ b/3.22.3-scylla/_sources/api/cassandra/datastax/graph/fluent/query.rst.txt @@ -0,0 +1,8 @@ +:mod:`cassandra.datastax.graph.fluent.query` +============================================ + +.. module:: cassandra.datastax.graph.fluent.query + + +.. autoclass:: TraversalBatch + :members: diff --git a/3.22.3-scylla/_sources/api/cassandra/datastax/graph/index.rst.txt b/3.22.3-scylla/_sources/api/cassandra/datastax/graph/index.rst.txt new file mode 100644 index 0000000000..18a0e7c511 --- /dev/null +++ b/3.22.3-scylla/_sources/api/cassandra/datastax/graph/index.rst.txt @@ -0,0 +1,118 @@ +``cassandra.datastax.graph`` - Graph Statements, Options, and Row Factories +=========================================================================== + +.. _api-datastax-graph: + +.. module:: cassandra.datastax.graph + +.. autofunction:: single_object_row_factory + +.. autofunction:: graph_result_row_factory + +.. autofunction:: graph_object_row_factory + +.. autofunction:: graph_graphson2_row_factory + +.. autofunction:: graph_graphson3_row_factory + +.. function:: to_int(value) + + Wraps a value to be explicitly serialized as a graphson Int. + +.. function:: to_bigint(value) + + Wraps a value to be explicitly serialized as a graphson Bigint. + +.. function:: to_smallint(value) + + Wraps a value to be explicitly serialized as a graphson Smallint. + +.. function:: to_float(value) + + Wraps a value to be explicitly serialized as a graphson Float. + +.. function:: to_double(value) + + Wraps a value to be explicitly serialized as a graphson Double. + +.. autoclass:: GraphProtocol + :members: + +.. autoclass:: GraphOptions + + .. autoattribute:: graph_name + + .. autoattribute:: graph_source + + .. autoattribute:: graph_language + + .. autoattribute:: graph_read_consistency_level + + .. autoattribute:: graph_write_consistency_level + + .. autoattribute:: is_default_source + + .. autoattribute:: is_analytics_source + + .. autoattribute:: is_graph_source + + .. automethod:: set_source_default + + .. automethod:: set_source_analytics + + .. automethod:: set_source_graph + + +.. autoclass:: SimpleGraphStatement + :members: + +.. autoclass:: Result + :members: + +.. autoclass:: Vertex + :members: + +.. autoclass:: VertexProperty + :members: + +.. autoclass:: Edge + :members: + +.. autoclass:: Path + :members: + +.. autoclass:: GraphSON1Serializer + :members: + +.. autoclass:: GraphSON1Deserializer + + .. automethod:: deserialize_date + + .. automethod:: deserialize_timestamp + + .. automethod:: deserialize_time + + .. automethod:: deserialize_duration + + .. automethod:: deserialize_int + + .. automethod:: deserialize_bigint + + .. automethod:: deserialize_double + + .. automethod:: deserialize_float + + .. automethod:: deserialize_uuid + + .. automethod:: deserialize_blob + + .. automethod:: deserialize_decimal + + .. automethod:: deserialize_point + + .. automethod:: deserialize_linestring + + .. automethod:: deserialize_polygon + +.. autoclass:: GraphSON2Reader + :members: diff --git a/3.22.3-scylla/_sources/api/cassandra/decoder.rst.txt b/3.22.3-scylla/_sources/api/cassandra/decoder.rst.txt new file mode 100644 index 0000000000..e213cc6d74 --- /dev/null +++ b/3.22.3-scylla/_sources/api/cassandra/decoder.rst.txt @@ -0,0 +1,20 @@ +``cassandra.decoder`` - Data Return Formats +=========================================== + +.. module:: cassandra.decoder + +.. function:: tuple_factory + + **Deprecated in 2.0.0.** Use :meth:`cassandra.query.tuple_factory` + +.. function:: named_tuple_factory + + **Deprecated in 2.0.0.** Use :meth:`cassandra.query.named_tuple_factory` + +.. function:: dict_factory + + **Deprecated in 2.0.0.** Use :meth:`cassandra.query.dict_factory` + +.. function:: ordered_dict_factory + + **Deprecated in 2.0.0.** Use :meth:`cassandra.query.ordered_dict_factory` diff --git a/3.22.3-scylla/_sources/api/cassandra/encoder.rst.txt b/3.22.3-scylla/_sources/api/cassandra/encoder.rst.txt new file mode 100644 index 0000000000..de3b180510 --- /dev/null +++ b/3.22.3-scylla/_sources/api/cassandra/encoder.rst.txt @@ -0,0 +1,36 @@ +``cassandra.encoder`` - Encoders for non-prepared Statements +============================================================ + +.. module:: cassandra.encoder + +.. autoclass:: Encoder () + + .. autoattribute:: cassandra.encoder.Encoder.mapping + + .. automethod:: cassandra.encoder.Encoder.cql_encode_none () + + .. automethod:: cassandra.encoder.Encoder.cql_encode_object () + + .. automethod:: cassandra.encoder.Encoder.cql_encode_all_types () + + .. automethod:: cassandra.encoder.Encoder.cql_encode_sequence () + + .. automethod:: cassandra.encoder.Encoder.cql_encode_str () + + .. automethod:: cassandra.encoder.Encoder.cql_encode_unicode () + + .. automethod:: cassandra.encoder.Encoder.cql_encode_bytes () + + Converts strings, buffers, and bytearrays into CQL blob literals. + + .. automethod:: cassandra.encoder.Encoder.cql_encode_datetime () + + .. automethod:: cassandra.encoder.Encoder.cql_encode_date () + + .. automethod:: cassandra.encoder.Encoder.cql_encode_map_collection () + + .. automethod:: cassandra.encoder.Encoder.cql_encode_list_collection () + + .. automethod:: cassandra.encoder.Encoder.cql_encode_set_collection () + + .. automethod:: cql_encode_tuple () diff --git a/3.22.3-scylla/_sources/api/cassandra/graph.rst.txt b/3.22.3-scylla/_sources/api/cassandra/graph.rst.txt new file mode 100644 index 0000000000..43ddd3086c --- /dev/null +++ b/3.22.3-scylla/_sources/api/cassandra/graph.rst.txt @@ -0,0 +1,121 @@ +``cassandra.graph`` - Graph Statements, Options, and Row Factories +================================================================== + +.. note:: This module is only for backward compatibility for dse-driver users. Consider using :ref:`cassandra.datastax.graph `. + +.. module:: cassandra.graph + +.. autofunction:: single_object_row_factory + +.. autofunction:: graph_result_row_factory + +.. autofunction:: graph_object_row_factory + +.. autofunction:: graph_graphson2_row_factory + +.. autofunction:: graph_graphson3_row_factory + +.. function:: to_int(value) + + Wraps a value to be explicitly serialized as a graphson Int. + +.. function:: to_bigint(value) + + Wraps a value to be explicitly serialized as a graphson Bigint. + +.. function:: to_smallint(value) + + Wraps a value to be explicitly serialized as a graphson Smallint. + +.. function:: to_float(value) + + Wraps a value to be explicitly serialized as a graphson Float. + +.. function:: to_double(value) + + Wraps a value to be explicitly serialized as a graphson Double. + +.. autoclass:: GraphProtocol + :members: + +.. autoclass:: GraphOptions + + .. autoattribute:: graph_name + + .. autoattribute:: graph_source + + .. autoattribute:: graph_language + + .. autoattribute:: graph_read_consistency_level + + .. autoattribute:: graph_write_consistency_level + + .. autoattribute:: is_default_source + + .. autoattribute:: is_analytics_source + + .. autoattribute:: is_graph_source + + .. automethod:: set_source_default + + .. automethod:: set_source_analytics + + .. automethod:: set_source_graph + + +.. autoclass:: SimpleGraphStatement + :members: + +.. autoclass:: Result + :members: + +.. autoclass:: Vertex + :members: + +.. autoclass:: VertexProperty + :members: + +.. autoclass:: Edge + :members: + +.. autoclass:: Path + :members: + +.. autoclass:: GraphSON1Serializer + :members: + +.. autoclass:: GraphSON1Deserializer + + .. automethod:: deserialize_date + + .. automethod:: deserialize_timestamp + + .. automethod:: deserialize_time + + .. automethod:: deserialize_duration + + .. automethod:: deserialize_int + + .. automethod:: deserialize_bigint + + .. automethod:: deserialize_double + + .. automethod:: deserialize_float + + .. automethod:: deserialize_uuid + + .. automethod:: deserialize_blob + + .. automethod:: deserialize_decimal + + .. automethod:: deserialize_point + + .. automethod:: deserialize_linestring + + .. automethod:: deserialize_polygon + +.. autoclass:: GraphSON2Reader + :members: + +.. autoclass:: GraphSON3Reader + :members: diff --git a/3.22.3-scylla/_sources/api/cassandra/io/asyncioreactor.rst.txt b/3.22.3-scylla/_sources/api/cassandra/io/asyncioreactor.rst.txt new file mode 100644 index 0000000000..38ae63ca7f --- /dev/null +++ b/3.22.3-scylla/_sources/api/cassandra/io/asyncioreactor.rst.txt @@ -0,0 +1,7 @@ +``cassandra.io.asyncioreactor`` - ``asyncio`` Event Loop +===================================================================== + +.. module:: cassandra.io.asyncioreactor + +.. autoclass:: AsyncioConnection + :members: diff --git a/3.22.3-scylla/_sources/api/cassandra/io/asyncorereactor.rst.txt b/3.22.3-scylla/_sources/api/cassandra/io/asyncorereactor.rst.txt new file mode 100644 index 0000000000..ade7887e70 --- /dev/null +++ b/3.22.3-scylla/_sources/api/cassandra/io/asyncorereactor.rst.txt @@ -0,0 +1,7 @@ +``cassandra.io.asyncorereactor`` - ``asyncore`` Event Loop +========================================================== + +.. module:: cassandra.io.asyncorereactor + +.. autoclass:: AsyncoreConnection + :members: diff --git a/3.22.3-scylla/_sources/api/cassandra/io/eventletreactor.rst.txt b/3.22.3-scylla/_sources/api/cassandra/io/eventletreactor.rst.txt new file mode 100644 index 0000000000..1ba742c7e9 --- /dev/null +++ b/3.22.3-scylla/_sources/api/cassandra/io/eventletreactor.rst.txt @@ -0,0 +1,7 @@ +``cassandra.io.eventletreactor`` - ``eventlet``-compatible Connection +===================================================================== + +.. module:: cassandra.io.eventletreactor + +.. autoclass:: EventletConnection + :members: diff --git a/3.22.3-scylla/_sources/api/cassandra/io/geventreactor.rst.txt b/3.22.3-scylla/_sources/api/cassandra/io/geventreactor.rst.txt new file mode 100644 index 0000000000..603affe140 --- /dev/null +++ b/3.22.3-scylla/_sources/api/cassandra/io/geventreactor.rst.txt @@ -0,0 +1,7 @@ +``cassandra.io.geventreactor`` - ``gevent``-compatible Event Loop +================================================================= + +.. module:: cassandra.io.geventreactor + +.. autoclass:: GeventConnection + :members: diff --git a/3.22.3-scylla/_sources/api/cassandra/io/libevreactor.rst.txt b/3.22.3-scylla/_sources/api/cassandra/io/libevreactor.rst.txt new file mode 100644 index 0000000000..5b7288edf2 --- /dev/null +++ b/3.22.3-scylla/_sources/api/cassandra/io/libevreactor.rst.txt @@ -0,0 +1,6 @@ +``cassandra.io.libevreactor`` - ``libev`` Event Loop +==================================================== + +.. module:: cassandra.io.libevreactor + +.. autoclass:: LibevConnection diff --git a/3.22.3-scylla/_sources/api/cassandra/io/twistedreactor.rst.txt b/3.22.3-scylla/_sources/api/cassandra/io/twistedreactor.rst.txt new file mode 100644 index 0000000000..24e93bd432 --- /dev/null +++ b/3.22.3-scylla/_sources/api/cassandra/io/twistedreactor.rst.txt @@ -0,0 +1,9 @@ +``cassandra.io.twistedreactor`` - Twisted Event Loop +==================================================== + +.. module:: cassandra.io.twistedreactor + +.. class:: TwistedConnection + + An implementation of :class:`~cassandra.io.connection.Connection` that uses + Twisted's reactor as its event loop. diff --git a/3.22.3-scylla/_sources/api/cassandra/metadata.rst.txt b/3.22.3-scylla/_sources/api/cassandra/metadata.rst.txt new file mode 100644 index 0000000000..602b767722 --- /dev/null +++ b/3.22.3-scylla/_sources/api/cassandra/metadata.rst.txt @@ -0,0 +1,89 @@ +``cassandra.metadata`` - Schema and Ring Topology +================================================= + +.. module:: cassandra.metadata + +.. autodata:: cql_keywords + :annotation: + +.. autodata:: cql_keywords_unreserved + :annotation: + +.. autodata:: cql_keywords_reserved + :annotation: + +.. autoclass:: Metadata () + :members: + :exclude-members: rebuild_schema, rebuild_token_map, add_host, remove_host + +Schemas +------- + +.. autoclass:: KeyspaceMetadata () + :members: + +.. autoclass:: UserType () + :members: + +.. autoclass:: Function () + :members: + +.. autoclass:: Aggregate () + :members: + +.. autoclass:: TableMetadata () + :members: + +.. autoclass:: TableMetadataV3 () + :members: + +.. autoclass:: TableMetadataDSE68 () + :members: + +.. autoclass:: ColumnMetadata () + :members: + +.. autoclass:: IndexMetadata () + :members: + +.. autoclass:: MaterializedViewMetadata () + :members: + +.. autoclass:: VertexMetadata () + :members: + +.. autoclass:: EdgeMetadata () + :members: + +Tokens and Ring Topology +------------------------ + +.. autoclass:: TokenMap () + :members: + +.. autoclass:: Token () + :members: + +.. autoclass:: Murmur3Token + :members: + +.. autoclass:: MD5Token + :members: + +.. autoclass:: BytesToken + :members: + +.. autoclass:: ReplicationStrategy + :members: + +.. autoclass:: SimpleStrategy + :members: + +.. autoclass:: NetworkTopologyStrategy + :members: + +.. autoclass:: LocalStrategy + :members: + +.. autofunction:: group_keys_by_replica + diff --git a/3.22.3-scylla/_sources/api/cassandra/metrics.rst.txt b/3.22.3-scylla/_sources/api/cassandra/metrics.rst.txt new file mode 100644 index 0000000000..0df7f8b5b9 --- /dev/null +++ b/3.22.3-scylla/_sources/api/cassandra/metrics.rst.txt @@ -0,0 +1,7 @@ +``cassandra.metrics`` - Performance Metrics +=========================================== + +.. module:: cassandra.metrics + +.. autoclass:: cassandra.metrics.Metrics () + :members: diff --git a/3.22.3-scylla/_sources/api/cassandra/policies.rst.txt b/3.22.3-scylla/_sources/api/cassandra/policies.rst.txt new file mode 100644 index 0000000000..387b19ed95 --- /dev/null +++ b/3.22.3-scylla/_sources/api/cassandra/policies.rst.txt @@ -0,0 +1,96 @@ +``cassandra.policies`` - Load balancing and Failure Handling Policies +===================================================================== + +.. module:: cassandra.policies + +Load Balancing +-------------- + +.. autoclass:: HostDistance + :members: + +.. autoclass:: LoadBalancingPolicy + :members: + +.. autoclass:: RoundRobinPolicy + :members: + +.. autoclass:: DCAwareRoundRobinPolicy + :members: + +.. autoclass:: WhiteListRoundRobinPolicy + :members: + +.. autoclass:: TokenAwarePolicy + :members: + +.. autoclass:: HostFilterPolicy + + .. we document these methods manually so we can specify a param to predicate + + .. automethod:: predicate(host) + .. automethod:: distance + .. automethod:: make_query_plan + +.. autoclass:: DefaultLoadBalancingPolicy + :members: + +.. autoclass:: DSELoadBalancingPolicy + :members: + +Translating Server Node Addresses +--------------------------------- + +.. autoclass:: AddressTranslator + :members: + +.. autoclass:: IdentityTranslator + :members: + +.. autoclass:: EC2MultiRegionTranslator + :members: + +Marking Hosts Up or Down +------------------------ + +.. autoclass:: ConvictionPolicy + :members: + +.. autoclass:: SimpleConvictionPolicy + :members: + +Reconnecting to Dead Hosts +-------------------------- + +.. autoclass:: ReconnectionPolicy + :members: + +.. autoclass:: ConstantReconnectionPolicy + :members: + +.. autoclass:: ExponentialReconnectionPolicy + :members: + +Retrying Failed Operations +-------------------------- + +.. autoclass:: WriteType + :members: + +.. autoclass:: RetryPolicy + :members: + +.. autoclass:: FallthroughRetryPolicy + :members: + +.. autoclass:: DowngradingConsistencyRetryPolicy + :members: + +Retrying Idempotent Operations +------------------------------ + +.. autoclass:: SpeculativeExecutionPolicy + :members: + +.. autoclass:: ConstantSpeculativeExecutionPolicy + :members: diff --git a/3.22.3-scylla/_sources/api/cassandra/pool.rst.txt b/3.22.3-scylla/_sources/api/cassandra/pool.rst.txt new file mode 100644 index 0000000000..b14d30e19c --- /dev/null +++ b/3.22.3-scylla/_sources/api/cassandra/pool.rst.txt @@ -0,0 +1,11 @@ +``cassandra.pool`` - Hosts and Connection Pools +=============================================== + +.. automodule:: cassandra.pool + +.. autoclass:: Host () + :members: + :exclude-members: set_location_info, get_and_set_reconnection_handler + +.. autoexception:: NoConnectionsAvailable + :members: diff --git a/3.22.3-scylla/_sources/api/cassandra/protocol.rst.txt b/3.22.3-scylla/_sources/api/cassandra/protocol.rst.txt new file mode 100644 index 0000000000..f615ab1a70 --- /dev/null +++ b/3.22.3-scylla/_sources/api/cassandra/protocol.rst.txt @@ -0,0 +1,55 @@ +``cassandra.protocol`` - Protocol Features +===================================================================== + +.. module:: cassandra.protocol + +.. _custom_payload: + +Custom Payloads +--------------- +Native protocol version 4+ allows for a custom payload to be sent between clients +and custom query handlers. The payload is specified as a string:binary_type dict +holding custom key/value pairs. + +By default these are ignored by the server. They can be useful for servers implementing +a custom QueryHandler. + +See :meth:`.Session.execute`, ::meth:`.Session.execute_async`, :attr:`.ResponseFuture.custom_payload`. + +.. autoclass:: _ProtocolHandler + + .. autoattribute:: message_types_by_opcode + :annotation: = {default mapping} + + .. automethod:: encode_message + + .. automethod:: decode_message + +.. _faster_deser: + +Faster Deserialization +---------------------- +When python-driver is compiled with Cython, it uses a Cython-based deserialization path +to deserialize messages. By default, the driver will use a Cython-based parser that returns +lists of rows similar to the pure-Python version. In addition, there are two additional +ProtocolHandler classes that can be used to deserialize response messages: ``LazyProtocolHandler`` +and ``NumpyProtocolHandler``. They can be used as follows: + +.. code:: python + + from cassandra.protocol import NumpyProtocolHandler, LazyProtocolHandler + from cassandra.query import tuple_factory + s.client_protocol_handler = LazyProtocolHandler # for a result iterator + s.row_factory = tuple_factory #required for Numpy results + s.client_protocol_handler = NumpyProtocolHandler # for a dict of NumPy arrays as result + +These protocol handlers comprise different parsers, and return results as described below: + +- ProtocolHandler: this default implementation is a drop-in replacement for the pure-Python version. + The rows are all parsed upfront, before results are returned. + +- LazyProtocolHandler: near drop-in replacement for the above, except that it returns an iterator over rows, + lazily decoded into the default row format (this is more efficient since all decoded results are not materialized at once) + +- NumpyProtocolHander: deserializes results directly into NumPy arrays. This facilitates efficient integration with + analysis toolkits such as Pandas. diff --git a/3.22.3-scylla/_sources/api/cassandra/query.rst.txt b/3.22.3-scylla/_sources/api/cassandra/query.rst.txt new file mode 100644 index 0000000000..fcd79739b9 --- /dev/null +++ b/3.22.3-scylla/_sources/api/cassandra/query.rst.txt @@ -0,0 +1,59 @@ +``cassandra.query`` - Prepared Statements, Batch Statements, Tracing, and Row Factories +======================================================================================= + +.. module:: cassandra.query + +.. autofunction:: tuple_factory + +.. autofunction:: named_tuple_factory + +.. autofunction:: dict_factory + +.. autofunction:: ordered_dict_factory + +.. autoclass:: SimpleStatement + :members: + +.. autoclass:: PreparedStatement () + :members: + +.. autoclass:: BoundStatement + :members: + +.. autoclass:: Statement () + :members: + +.. autodata:: UNSET_VALUE + :annotation: + +.. autoclass:: BatchStatement (batch_type=BatchType.LOGGED, retry_policy=None, consistency_level=None) + :members: + +.. autoclass:: BatchType () + + .. autoattribute:: LOGGED + + .. autoattribute:: UNLOGGED + + .. autoattribute:: COUNTER + +.. autoclass:: cassandra.query.ValueSequence + + A wrapper class that is used to specify that a sequence of values should + be treated as a CQL list of values instead of a single column collection when used + as part of the `parameters` argument for :meth:`.Session.execute()`. + + This is typically needed when supplying a list of keys to select. + For example:: + + >>> my_user_ids = ('alice', 'bob', 'charles') + >>> query = "SELECT * FROM users WHERE user_id IN %s" + >>> session.execute(query, parameters=[ValueSequence(my_user_ids)]) + +.. autoclass:: QueryTrace () + :members: + +.. autoclass:: TraceEvent () + :members: + +.. autoexception:: TraceUnavailable diff --git a/3.22.3-scylla/_sources/api/cassandra/timestamps.rst.txt b/3.22.3-scylla/_sources/api/cassandra/timestamps.rst.txt new file mode 100644 index 0000000000..00d25b06d9 --- /dev/null +++ b/3.22.3-scylla/_sources/api/cassandra/timestamps.rst.txt @@ -0,0 +1,14 @@ +``cassandra.timestamps`` - Timestamp Generation +=============================================== + +.. module:: cassandra.timestamps + +.. autoclass:: MonotonicTimestampGenerator (warn_on_drift=True, warning_threshold=0, warning_interval=0) + + .. autoattribute:: warn_on_drift + + .. autoattribute:: warning_threshold + + .. autoattribute:: warning_interval + + .. automethod:: _next_timestamp diff --git a/3.22.3-scylla/_sources/api/cassandra/util.rst.txt b/3.22.3-scylla/_sources/api/cassandra/util.rst.txt new file mode 100644 index 0000000000..848d4d5fc2 --- /dev/null +++ b/3.22.3-scylla/_sources/api/cassandra/util.rst.txt @@ -0,0 +1,5 @@ +``cassandra.util`` - Utilities +=================================== + +.. automodule:: cassandra.util + :members: diff --git a/3.22.3-scylla/_sources/api/index.rst.txt b/3.22.3-scylla/_sources/api/index.rst.txt new file mode 100644 index 0000000000..9e778d508c --- /dev/null +++ b/3.22.3-scylla/_sources/api/index.rst.txt @@ -0,0 +1,54 @@ +API Documentation +================= + +Core Driver +----------- +.. toctree:: + :maxdepth: 2 + + cassandra + cassandra/cluster + cassandra/policies + cassandra/auth + cassandra/graph + cassandra/metadata + cassandra/metrics + cassandra/query + cassandra/pool + cassandra/protocol + cassandra/encoder + cassandra/decoder + cassandra/concurrent + cassandra/connection + cassandra/util + cassandra/timestamps + cassandra/io/asyncioreactor + cassandra/io/asyncorereactor + cassandra/io/eventletreactor + cassandra/io/libevreactor + cassandra/io/geventreactor + cassandra/io/twistedreactor + +.. _om_api: + +Object Mapper +------------- +.. toctree:: + :maxdepth: 1 + + cassandra/cqlengine/models + cassandra/cqlengine/columns + cassandra/cqlengine/query + cassandra/cqlengine/connection + cassandra/cqlengine/management + cassandra/cqlengine/usertype + +DataStax Graph +-------------- +.. toctree:: + :maxdepth: 1 + + cassandra/datastax/graph/index + cassandra/datastax/graph/fluent/index + cassandra/datastax/graph/fluent/query + cassandra/datastax/graph/fluent/predicates diff --git a/3.22.3-scylla/_sources/cqlengine/batches.rst.txt b/3.22.3-scylla/_sources/cqlengine/batches.rst.txt new file mode 100644 index 0000000000..306e7d01a6 --- /dev/null +++ b/3.22.3-scylla/_sources/cqlengine/batches.rst.txt @@ -0,0 +1,108 @@ +============= +Batch Queries +============= + +cqlengine supports batch queries using the BatchQuery class. Batch queries can be started and stopped manually, or within a context manager. To add queries to the batch object, you just need to precede the create/save/delete call with a call to batch, and pass in the batch object. + + +Batch Query General Use Pattern +=============================== + +You can only create, update, and delete rows with a batch query, attempting to read rows out of the database with a batch query will fail. + +.. code-block:: python + + from cassandra.cqlengine.query import BatchQuery + + #using a context manager + with BatchQuery() as b: + now = datetime.now() + em1 = ExampleModel.batch(b).create(example_type=0, description="1", created_at=now) + em2 = ExampleModel.batch(b).create(example_type=0, description="2", created_at=now) + em3 = ExampleModel.batch(b).create(example_type=0, description="3", created_at=now) + + # -- or -- + + #manually + b = BatchQuery() + now = datetime.now() + em1 = ExampleModel.batch(b).create(example_type=0, description="1", created_at=now) + em2 = ExampleModel.batch(b).create(example_type=0, description="2", created_at=now) + em3 = ExampleModel.batch(b).create(example_type=0, description="3", created_at=now) + b.execute() + + # updating in a batch + + b = BatchQuery() + em1.description = "new description" + em1.batch(b).save() + em2.description = "another new description" + em2.batch(b).save() + b.execute() + + # deleting in a batch + b = BatchQuery() + ExampleModel.objects(id=some_id).batch(b).delete() + ExampleModel.objects(id=some_id2).batch(b).delete() + b.execute() + + +Typically you will not want the block to execute if an exception occurs inside the `with` block. However, in the case that this is desirable, it's achievable by using the following syntax: + +.. code-block:: python + + with BatchQuery(execute_on_exception=True) as b: + LogEntry.batch(b).create(k=1, v=1) + mystery_function() # exception thrown in here + LogEntry.batch(b).create(k=1, v=2) # this code is never reached due to the exception, but anything leading up to here will execute in the batch. + +If an exception is thrown somewhere in the block, any statements that have been added to the batch will still be executed. This is useful for some logging situations. + +Batch Query Execution Callbacks +=============================== + +In order to allow secondary tasks to be chained to the end of batch, BatchQuery instances allow callbacks to be +registered with the batch, to be executed immediately after the batch executes. + +Multiple callbacks can be attached to same BatchQuery instance, they are executed in the same order that they +are added to the batch. + +The callbacks attached to a given batch instance are executed only if the batch executes. If the batch is used as a +context manager and an exception is raised, the queued up callbacks will not be run. + +.. code-block:: python + + def my_callback(*args, **kwargs): + pass + + batch = BatchQuery() + + batch.add_callback(my_callback) + batch.add_callback(my_callback, 'positional arg', named_arg='named arg value') + + # if you need reference to the batch within the callback, + # just trap it in the arguments to be passed to the callback: + batch.add_callback(my_callback, cqlengine_batch=batch) + + # once the batch executes... + batch.execute() + + # the effect of the above scheduled callbacks will be similar to + my_callback() + my_callback('positional arg', named_arg='named arg value') + my_callback(cqlengine_batch=batch) + +Failure in any of the callbacks does not affect the batch's execution, as the callbacks are started after the execution +of the batch is complete. + +Logged vs Unlogged Batches +--------------------------- +By default, queries in cqlengine are LOGGED, which carries additional overhead from UNLOGGED. To explicitly state which batch type to use, simply: + + +.. code-block:: python + + from cassandra.cqlengine.query import BatchType + with BatchQuery(batch_type=BatchType.Unlogged) as b: + LogEntry.batch(b).create(k=1, v=1) + LogEntry.batch(b).create(k=1, v=2) diff --git a/3.22.3-scylla/_sources/cqlengine/connections.rst.txt b/3.22.3-scylla/_sources/cqlengine/connections.rst.txt new file mode 100644 index 0000000000..03ade27521 --- /dev/null +++ b/3.22.3-scylla/_sources/cqlengine/connections.rst.txt @@ -0,0 +1,137 @@ +=========== +Connections +=========== + +Connections aim to ease the use of multiple sessions with cqlengine. Connections can be set on a model class, per query or using a context manager. + + +Register a new connection +========================= + +To use cqlengine, you need at least a default connection. If you initialize cqlengine's connections with with :func:`connection.setup <.connection.setup>`, a connection will be created automatically. If you want to use another cluster/session, you need to register a new cqlengine connection. You register a connection with :func:`~.connection.register_connection`: + +.. code-block:: python + + from cassandra.cqlengine import connection + + connection.setup(['127.0.0.1') + connection.register_connection('cluster2', ['127.0.0.2']) + +:func:`~.connection.register_connection` can take a list of hosts, as shown above, in which case it will create a connection with a new session. It can also take a `session` argument if you've already created a session: + +.. code-block:: python + + from cassandra.cqlengine import connection + from cassandra.cluster import Cluster + + session = Cluster(['127.0.0.1']).connect() + connection.register_connection('cluster3', session=session) + + +Change the default connection +============================= + +You can change the default cqlengine connection on registration: + +.. code-block:: python + + from cassandra.cqlengine import connection + + connection.register_connection('cluster2', ['127.0.0.2'] default=True) + +or on the fly using :func:`~.connection.set_default_connection` + +.. code-block:: python + + connection.set_default_connection('cluster2') + +Unregister a connection +======================= + +You can unregister a connection using :func:`~.connection.unregister_connection`: + +.. code-block:: python + + connection.unregister_connection('cluster2') + +Management +========== + +When using multiples connections, you also need to sync your models on all connections (and keyspaces) that you need operate on. Management commands have been improved to ease this part. Here is an example: + +.. code-block:: python + + from cassandra.cqlengine import management + + keyspaces = ['ks1', 'ks2'] + conns = ['cluster1', 'cluster2'] + + # registers your connections + # ... + + # create all keyspaces on all connections + for ks in keyspaces: + management.create_simple_keyspace(ks, connections=conns) + + # define your Automobile model + # ... + + # sync your models + management.sync_table(Automobile, keyspaces=keyspaces, connections=conns) + + +Connection Selection +==================== + +cqlengine will select the default connection, unless your specify a connection using one of the following methods. + +Default Model Connection +------------------------ + +You can specify a default connection per model: + +.. code-block:: python + + class Automobile(Model): + __keyspace__ = 'test' + __connection__ = 'cluster2' + manufacturer = columns.Text(primary_key=True) + year = columns.Integer(primary_key=True) + model = columns.Text(primary_key=True) + + print len(Automobile.objects.all()) # executed on the connection 'cluster2' + +QuerySet and model instance +--------------------------- + +You can use the :attr:`using() <.query.ModelQuerySet.using>` method to select a connection (or keyspace): + +.. code-block:: python + + Automobile.objects.using(connection='cluster1').create(manufacturer='honda', year=2010, model='civic') + q = Automobile.objects.filter(manufacturer='Tesla') + autos = q.using(keyspace='ks2', connection='cluster2').all() + + for auto in autos: + auto.using(connection='cluster1').save() + +Context Manager +--------------- + +You can use the ContextQuery as well to select a connection: + +.. code-block:: python + + with ContextQuery(Automobile, connection='cluster1') as A: + A.objects.filter(manufacturer='honda').all() # executed on 'cluster1' + + +BatchQuery +---------- + +With a BatchQuery, you can select the connection with the context manager. Note that all operations in the batch need to use the same connection. + +.. code-block:: python + + with BatchQuery(connection='cluster1') as b: + Automobile.objects.batch(b).create(manufacturer='honda', year=2010, model='civic') diff --git a/3.22.3-scylla/_sources/cqlengine/faq.rst.txt b/3.22.3-scylla/_sources/cqlengine/faq.rst.txt new file mode 100644 index 0000000000..6c056d02ea --- /dev/null +++ b/3.22.3-scylla/_sources/cqlengine/faq.rst.txt @@ -0,0 +1,67 @@ +========================== +Frequently Asked Questions +========================== + +Why don't updates work correctly on models instantiated as Model(field=value, field2=value2)? +------------------------------------------------------------------------------------------------ + +The recommended way to create new rows is with the models .create method. The values passed into a model's init method are interpreted by the model as the values as they were read from a row. This allows the model to "know" which rows have changed since the row was read out of cassandra, and create suitable update statements. + +How to preserve ordering in batch query? +------------------------------------------- + +Statement Ordering is not supported by CQL3 batches. Therefore, +once cassandra needs resolving conflict(Updating the same column in one batch), +The algorithm below would be used. + +* If timestamps are different, pick the column with the largest timestamp (the value being a regular column or a tombstone) +* If timestamps are the same, and one of the columns in a tombstone ('null') - pick the tombstone +* If timestamps are the same, and none of the columns are tombstones, pick the column with the largest value + +Below is an example to show this scenario. + +.. code-block:: python + + class MyMode(Model): + id = columns.Integer(primary_key=True) + count = columns.Integer() + text = columns.Text() + + with BatchQuery() as b: + MyModel.batch(b).create(id=1, count=2, text='123') + MyModel.batch(b).create(id=1, count=3, text='111') + + assert MyModel.objects(id=1).first().count == 3 + assert MyModel.objects(id=1).first().text == '123' + +The largest value of count is 3, and the largest value of text would be '123'. + +The workaround is applying timestamp to each statement, then Cassandra would +resolve to the statement with the lastest timestamp. + +.. code-block:: python + + with BatchQuery() as b: + MyModel.timestamp(datetime.now()).batch(b).create(id=1, count=2, text='123') + MyModel.timestamp(datetime.now()).batch(b).create(id=1, count=3, text='111') + + assert MyModel.objects(id=1).first().count == 3 + assert MyModel.objects(id=1).first().text == '111' + +How can I delete individual values from a row? +------------------------------------------------- + +When inserting with CQLEngine, ``None`` is equivalent to CQL ``NULL`` or to +issuing a ``DELETE`` on that column. For example: + +.. code-block:: python + + class MyModel(Model): + id = columns.Integer(primary_key=True) + text = columns.Text() + + m = MyModel.create(id=1, text='We can delete this with None') + assert MyModel.objects(id=1).first().text is not None + + m.update(text=None) + assert MyModel.objects(id=1).first().text is None diff --git a/3.22.3-scylla/_sources/cqlengine/models.rst.txt b/3.22.3-scylla/_sources/cqlengine/models.rst.txt new file mode 100644 index 0000000000..c0ba390119 --- /dev/null +++ b/3.22.3-scylla/_sources/cqlengine/models.rst.txt @@ -0,0 +1,218 @@ +====== +Models +====== + +.. module:: cqlengine.models + +A model is a python class representing a CQL table. Models derive from :class:`Model`, and +define basic table properties and columns for a table. + +Columns in your models map to columns in your CQL table. You define CQL columns by defining column attributes on your model classes. +For a model to be valid it needs at least one primary key column and one non-primary key column. Just as in CQL, the order you define +your columns in is important, and is the same order they are defined in on a model's corresponding table. + +Some basic examples defining models are shown below. Consult the :doc:`Model API docs ` and :doc:`Column API docs ` for complete details. + +Example Definitions +=================== + +This example defines a ``Person`` table, with the columns ``first_name`` and ``last_name`` + +.. code-block:: python + + from cassandra.cqlengine import columns + from cassandra.cqlengine.models import Model + + class Person(Model): + id = columns.UUID(primary_key=True) + first_name = columns.Text() + last_name = columns.Text() + + +The Person model would create this CQL table: + +.. code-block:: sql + + CREATE TABLE cqlengine.person ( + id uuid, + first_name text, + last_name text, + PRIMARY KEY (id) + ); + +Here's an example of a comment table created with clustering keys, in descending order: + +.. code-block:: python + + from cassandra.cqlengine import columns + from cassandra.cqlengine.models import Model + + class Comment(Model): + photo_id = columns.UUID(primary_key=True) + comment_id = columns.TimeUUID(primary_key=True, clustering_order="DESC") + comment = columns.Text() + +The Comment model's ``create table`` would look like the following: + +.. code-block:: sql + + CREATE TABLE comment ( + photo_id uuid, + comment_id timeuuid, + comment text, + PRIMARY KEY (photo_id, comment_id) + ) WITH CLUSTERING ORDER BY (comment_id DESC); + +To sync the models to the database, you may do the following*: + +.. code-block:: python + + from cassandra.cqlengine.management import sync_table + sync_table(Person) + sync_table(Comment) + +\*Note: synchronizing models causes schema changes, and should be done with caution. +Please see the discussion in :doc:`/api/cassandra/cqlengine/management` for considerations. + +For examples on manipulating data and creating queries, see :doc:`queryset` + +Manipulating model instances as dictionaries +============================================ + +Model instances can be accessed like dictionaries. + +.. code-block:: python + + class Person(Model): + first_name = columns.Text() + last_name = columns.Text() + + kevin = Person.create(first_name="Kevin", last_name="Deldycke") + dict(kevin) # returns {'first_name': 'Kevin', 'last_name': 'Deldycke'} + kevin['first_name'] # returns 'Kevin' + kevin.keys() # returns ['first_name', 'last_name'] + kevin.values() # returns ['Kevin', 'Deldycke'] + kevin.items() # returns [('first_name', 'Kevin'), ('last_name', 'Deldycke')] + + kevin['first_name'] = 'KEVIN5000' # changes the models first name + +Extending Model Validation +========================== + +Each time you save a model instance in cqlengine, the data in the model is validated against the schema you've defined +for your model. Most of the validation is fairly straightforward, it basically checks that you're not trying to do +something like save text into an integer column, and it enforces the ``required`` flag set on column definitions. +It also performs any transformations needed to save the data properly. + +However, there are often additional constraints or transformations you want to impose on your data, beyond simply +making sure that Cassandra won't complain when you try to insert it. To define additional validation on a model, +extend the model's validation method: + +.. code-block:: python + + class Member(Model): + person_id = UUID(primary_key=True) + name = Text(required=True) + + def validate(self): + super(Member, self).validate() + if self.name == 'jon': + raise ValidationError('no jon\'s allowed') + +*Note*: while not required, the convention is to raise a ``ValidationError`` (``from cassandra.cqlengine import ValidationError``) +if validation fails. + +.. _model_inheritance: + +Model Inheritance +================= +It is possible to save and load different model classes using a single CQL table. +This is useful in situations where you have different object types that you want to store in a single cassandra row. + +For instance, suppose you want a table that stores rows of pets owned by an owner: + +.. code-block:: python + + class Pet(Model): + __table_name__ = 'pet' + owner_id = UUID(primary_key=True) + pet_id = UUID(primary_key=True) + pet_type = Text(discriminator_column=True) + name = Text() + + def eat(self, food): + pass + + def sleep(self, time): + pass + + class Cat(Pet): + __discriminator_value__ = 'cat' + cuteness = Float() + + def tear_up_couch(self): + pass + + class Dog(Pet): + __discriminator_value__ = 'dog' + fierceness = Float() + + def bark_all_night(self): + pass + +After calling ``sync_table`` on each of these tables, the columns defined in each model will be added to the +``pet`` table. Additionally, saving ``Cat`` and ``Dog`` models will save the meta data needed to identify each row +as either a cat or dog. + +To setup a model structure with inheritance, follow these steps + +1. Create a base model with a column set as the distriminator (``distriminator_column=True`` in the column definition) +2. Create subclass models, and define a unique ``__discriminator_value__`` value on each +3. Run ``sync_table`` on each of the sub tables + +**About the discriminator value** + +The discriminator value is what cqlengine uses under the covers to map logical cql rows to the appropriate model type. The +base model maintains a map of discriminator values to subclasses. When a specialized model is saved, its discriminator value is +automatically saved into the discriminator column. The discriminator column may be any column type except counter and container types. +Additionally, if you set ``index=True`` on your discriminator column, you can execute queries against specialized subclasses, and a +``WHERE`` clause will be automatically added to your query, returning only rows of that type. Note that you must +define a unique ``__discriminator_value__`` to each subclass, and that you can only assign a single discriminator column per model. + +.. _user_types: + +User Defined Types +================== +cqlengine models User Defined Types (UDTs) much like tables, with fields defined by column type attributes. However, UDT instances +are only created, presisted, and queried via table Models. A short example to introduce the pattern:: + + from cassandra.cqlengine.columns import * + from cassandra.cqlengine.models import Model + from cassandra.cqlengine.usertype import UserType + + class address(UserType): + street = Text() + zipcode = Integer() + + class users(Model): + __keyspace__ = 'account' + name = Text(primary_key=True) + addr = UserDefinedType(address) + + users.create(name="Joe", addr=address(street="Easy St.", zipcode=99999)) + user = users.objects(name="Joe")[0] + print user.name, user.addr + # Joe address(street=u'Easy St.', zipcode=99999) + +UDTs are modeled by inheriting :class:`~.usertype.UserType`, and setting column type attributes. Types are then used in defining +models by declaring a column of type :class:`~.columns.UserDefinedType`, with the ``UserType`` class as a parameter. + +``sync_table`` will implicitly +synchronize any types contained in the table. Alternatively :func:`~.management.sync_type` can be used to create/alter types +explicitly. + +Upon declaration, types are automatically registered with the driver, so query results return instances of your ``UserType`` +class*. + +***Note**: UDTs were not added to the native protocol until v3. When setting up the cqlengine connection, be sure to specify +``protocol_version=3``. If using an earlier version, UDT queries will still work, but the returned type will be a namedtuple. diff --git a/3.22.3-scylla/_sources/cqlengine/queryset.rst.txt b/3.22.3-scylla/_sources/cqlengine/queryset.rst.txt new file mode 100644 index 0000000000..375ea22316 --- /dev/null +++ b/3.22.3-scylla/_sources/cqlengine/queryset.rst.txt @@ -0,0 +1,419 @@ +============== +Making Queries +============== + +.. module:: cqlengine.queryset + +Retrieving objects +================== +Once you've populated Cassandra with data, you'll probably want to retrieve some of it. This is accomplished with QuerySet objects. This section will describe how to use QuerySet objects to retrieve the data you're looking for. + +Retrieving all objects +---------------------- +The simplest query you can make is to return all objects from a table. + +This is accomplished with the ``.all()`` method, which returns a QuerySet of all objects in a table + +Using the Person example model, we would get all Person objects like this: + +.. code-block:: python + + all_objects = Person.objects.all() + +.. _retrieving-objects-with-filters: + +Retrieving objects with filters +------------------------------- +Typically, you'll want to query only a subset of the records in your database. + +That can be accomplished with the QuerySet's ``.filter(\*\*)`` method. + +For example, given the model definition: + +.. code-block:: python + + class Automobile(Model): + manufacturer = columns.Text(primary_key=True) + year = columns.Integer(primary_key=True) + model = columns.Text() + price = columns.Decimal() + options = columns.Set(columns.Text) + +...and assuming the Automobile table contains a record of every car model manufactured in the last 20 years or so, we can retrieve only the cars made by a single manufacturer like this: + + +.. code-block:: python + + q = Automobile.objects.filter(manufacturer='Tesla') + +You can also use the more convenient syntax: + +.. code-block:: python + + q = Automobile.objects(Automobile.manufacturer == 'Tesla') + +We can then further filter our query with another call to **.filter** + +.. code-block:: python + + q = q.filter(year=2012) + +*Note: all queries involving any filtering MUST define either an '=' or an 'in' relation to either a primary key column, or an indexed column.* + +Accessing objects in a QuerySet +=============================== + +There are several methods for getting objects out of a queryset + +* iterating over the queryset + .. code-block:: python + + for car in Automobile.objects.all(): + #...do something to the car instance + pass + +* list index + .. code-block:: python + + q = Automobile.objects.all() + q[0] #returns the first result + q[1] #returns the second result + + .. note:: + + * CQL does not support specifying a start position in it's queries. Therefore, accessing elements using array indexing will load every result up to the index value requested + * Using negative indices requires a "SELECT COUNT()" to be executed. This has a performance cost on large datasets. + +* list slicing + .. code-block:: python + + q = Automobile.objects.all() + q[1:] #returns all results except the first + q[1:9] #returns a slice of the results + + .. note:: + + * CQL does not support specifying a start position in it's queries. Therefore, accessing elements using array slicing will load every result up to the index value requested + * Using negative indices requires a "SELECT COUNT()" to be executed. This has a performance cost on large datasets. + +* calling :attr:`get() ` on the queryset + .. code-block:: python + + q = Automobile.objects.filter(manufacturer='Tesla') + q = q.filter(year=2012) + car = q.get() + + this returns the object matching the queryset + +* calling :attr:`first() ` on the queryset + .. code-block:: python + + q = Automobile.objects.filter(manufacturer='Tesla') + q = q.filter(year=2012) + car = q.first() + + this returns the first value in the queryset + +.. _query-filtering-operators: + +Filtering Operators +=================== + +:attr:`Equal To ` + +The default filtering operator. + +.. code-block:: python + + q = Automobile.objects.filter(manufacturer='Tesla') + q = q.filter(year=2012) #year == 2012 + +In addition to simple equal to queries, cqlengine also supports querying with other operators by appending a ``__`` to the field name on the filtering call + +:attr:`in (__in) ` + +.. code-block:: python + + q = Automobile.objects.filter(manufacturer='Tesla') + q = q.filter(year__in=[2011, 2012]) + + +:attr:`> (__gt) ` + +.. code-block:: python + + q = Automobile.objects.filter(manufacturer='Tesla') + q = q.filter(year__gt=2010) # year > 2010 + + # or the nicer syntax + + q.filter(Automobile.year > 2010) + +:attr:`>= (__gte) ` + +.. code-block:: python + + q = Automobile.objects.filter(manufacturer='Tesla') + q = q.filter(year__gte=2010) # year >= 2010 + + # or the nicer syntax + + q.filter(Automobile.year >= 2010) + +:attr:`< (__lt) ` + +.. code-block:: python + + q = Automobile.objects.filter(manufacturer='Tesla') + q = q.filter(year__lt=2012) # year < 2012 + + # or... + + q.filter(Automobile.year < 2012) + +:attr:`<= (__lte) ` + +.. code-block:: python + + q = Automobile.objects.filter(manufacturer='Tesla') + q = q.filter(year__lte=2012) # year <= 2012 + + q.filter(Automobile.year <= 2012) + +:attr:`CONTAINS (__contains) ` + +The CONTAINS operator is available for all collection types (List, Set, Map). + +.. code-block:: python + + q = Automobile.objects.filter(manufacturer='Tesla') + q.filter(options__contains='backup camera').allow_filtering() + +Note that we need to use allow_filtering() since the *options* column has no secondary index. + +:attr:`LIKE (__like) ` + +The LIKE operator is available for text columns that have a SASI secondary index. + +.. code-block:: python + + q = Automobile.objects.filter(model__like='%Civic%').allow_filtering() + +:attr:`IS NOT NULL (IsNotNull(column_name)) ` + +The IS NOT NULL operator is not yet supported for C*. + +.. code-block:: python + + q = Automobile.objects.filter(IsNotNull('model')) + +Limitations: + +- Currently, cqlengine does not support SASI index creation. To use this feature, you need to create the SASI index using the core driver. +- Queries using LIKE must use allow_filtering() since the *model* column has no standard secondary index. Note that the server will use the SASI index properly when executing the query. + +TimeUUID Functions +================== + +In addition to querying using regular values, there are two functions you can pass in when querying TimeUUID columns to help make filtering by them easier. Note that these functions don't actually return a value, but instruct the cql interpreter to use the functions in it's query. + +.. class:: MinTimeUUID(datetime) + + returns the minimum time uuid value possible for the given datetime + +.. class:: MaxTimeUUID(datetime) + + returns the maximum time uuid value possible for the given datetime + +*Example* + +.. code-block:: python + + class DataStream(Model): + id = columns.UUID(partition_key=True) + time = columns.TimeUUID(primary_key=True) + data = columns.Bytes() + + min_time = datetime(1982, 1, 1) + max_time = datetime(1982, 3, 9) + + DataStream.filter(time__gt=functions.MinTimeUUID(min_time), time__lt=functions.MaxTimeUUID(max_time)) + +Token Function +============== + +Token functon may be used only on special, virtual column pk__token, representing token of partition key (it also works for composite partition keys). +Cassandra orders returned items by value of partition key token, so using cqlengine.Token we can easy paginate through all table rows. + +See http://cassandra.apache.org/doc/cql3/CQL-3.0.html#tokenFun + +*Example* + +.. code-block:: python + + class Items(Model): + id = columns.Text(primary_key=True) + data = columns.Bytes() + + query = Items.objects.all().limit(10) + + first_page = list(query); + last = first_page[-1] + next_page = list(query.filter(pk__token__gt=cqlengine.Token(last.pk))) + +QuerySets are immutable +======================= + +When calling any method that changes a queryset, the method does not actually change the queryset object it's called on, but returns a new queryset object with the attributes of the original queryset, plus the attributes added in the method call. + +*Example* + +.. code-block:: python + + #this produces 3 different querysets + #q does not change after it's initial definition + q = Automobiles.objects.filter(year=2012) + tesla2012 = q.filter(manufacturer='Tesla') + honda2012 = q.filter(manufacturer='Honda') + +Ordering QuerySets +================== + +Since Cassandra is essentially a distributed hash table on steroids, the order you get records back in will not be particularly predictable. + +However, you can set a column to order on with the ``.order_by(column_name)`` method. + +*Example* + +.. code-block:: python + + #sort ascending + q = Automobiles.objects.all().order_by('year') + #sort descending + q = Automobiles.objects.all().order_by('-year') + +*Note: Cassandra only supports ordering on a clustering key. In other words, to support ordering results, your model must have more than one primary key, and you must order on a primary key, excluding the first one.* + +*For instance, given our Automobile model, year is the only column we can order on.* + +Values Lists +============ + +There is a special QuerySet's method ``.values_list()`` - when called, QuerySet returns lists of values instead of model instances. It may significantly speedup things with lower memory footprint for large responses. +Each tuple contains the value from the respective field passed into the ``values_list()`` call — so the first item is the first field, etc. For example: + +.. code-block:: python + + items = list(range(20)) + random.shuffle(items) + for i in items: + TestModel.create(id=1, clustering_key=i) + + values = list(TestModel.objects.values_list('clustering_key', flat=True)) + # [19L, 18L, 17L, 16L, 15L, 14L, 13L, 12L, 11L, 10L, 9L, 8L, 7L, 6L, 5L, 4L, 3L, 2L, 1L, 0L] + +Per Query Timeouts +=================== + +By default all queries are executed with the timeout defined in `~cqlengine.connection.setup()` +The examples below show how to specify a per-query timeout. +A timeout is specified in seconds and can be an int, float or None. +None means no timeout. + + +.. code-block:: python + + class Row(Model): + id = columns.Integer(primary_key=True) + name = columns.Text() + + +Fetch all objects with a timeout of 5 seconds + +.. code-block:: python + + Row.objects().timeout(5).all() + +Create a single row with a 50ms timeout + +.. code-block:: python + + Row(id=1, name='Jon').timeout(0.05).create() + +Delete a single row with no timeout + +.. code-block:: python + + Row(id=1).timeout(None).delete() + +Update a single row with no timeout + +.. code-block:: python + + Row(id=1).timeout(None).update(name='Blake') + +Batch query timeouts + +.. code-block:: python + + with BatchQuery(timeout=10) as b: + Row(id=1, name='Jon').create() + + +NOTE: You cannot set both timeout and batch at the same time, batch will use the timeout defined in it's constructor. +Setting the timeout on the model is meaningless and will raise an AssertionError. + + +.. _ttl-change: + +Default TTL and Per Query TTL +============================= + +Model default TTL now relies on the *default_time_to_live* feature, introduced in Cassandra 2.0. It is not handled anymore in the CQLEngine Model (scylla-driver >=3.6). You can set the default TTL of a table like this: + +Example: + +.. code-block:: python + + class User(Model): + __options__ = {'default_time_to_live': 20} + + user_id = columns.UUID(primary_key=True) + ... + +You can set TTL per-query if needed. Here are a some examples: + +Example: + +.. code-block:: python + + class User(Model): + __options__ = {'default_time_to_live': 20} + + user_id = columns.UUID(primary_key=True) + ... + + user = User.objects.create(user_id=1) # Default TTL 20 will be set automatically on the server + + user.ttl(30).update(age=21) # Update the TTL to 30 + User.objects.ttl(10).create(user_id=1) # TTL 10 + User(user_id=1, age=21).ttl(10).save() # TTL 10 + + +Named Tables +=================== + +Named tables are a way of querying a table without creating an class. They're useful for querying system tables or exploring an unfamiliar database. + + +.. code-block:: python + + from cassandra.cqlengine.connection import setup + setup("127.0.0.1", "cqlengine_test") + + from cassandra.cqlengine.named import NamedTable + user = NamedTable("cqlengine_test", "user") + user.objects() + user.objects()[0] + + # {u'pk': 1, u't': datetime.datetime(2014, 6, 26, 17, 10, 31, 774000)} diff --git a/3.22.3-scylla/_sources/cqlengine/third_party.rst.txt b/3.22.3-scylla/_sources/cqlengine/third_party.rst.txt new file mode 100644 index 0000000000..20c26df304 --- /dev/null +++ b/3.22.3-scylla/_sources/cqlengine/third_party.rst.txt @@ -0,0 +1,64 @@ +======================== +Third party integrations +======================== + + +Celery +------ + +Here's how, in substance, CQLengine can be plugged to `Celery +`_: + +.. code-block:: python + + from celery import Celery + from celery.signals import worker_process_init, beat_init + from cassandra.cqlengine import connection + from cassandra.cqlengine.connection import ( + cluster as cql_cluster, session as cql_session) + + def cassandra_init(**kwargs): + """ Initialize a clean Cassandra connection. """ + if cql_cluster is not None: + cql_cluster.shutdown() + if cql_session is not None: + cql_session.shutdown() + connection.setup() + + # Initialize worker context for both standard and periodic tasks. + worker_process_init.connect(cassandra_init) + beat_init.connect(cassandra_init) + + app = Celery() + + +uWSGI +----- + +This is the code required for proper connection handling of CQLengine for a +`uWSGI `_-run application: + +.. code-block:: python + + from cassandra.cqlengine import connection + from cassandra.cqlengine.connection import ( + cluster as cql_cluster, session as cql_session) + + try: + from uwsgidecorators import postfork + except ImportError: + # We're not in a uWSGI context, no need to hook Cassandra session + # initialization to the postfork event. + pass + else: + @postfork + def cassandra_init(**kwargs): + """ Initialize a new Cassandra session in the context. + + Ensures that a new session is returned for every new request. + """ + if cql_cluster is not None: + cql_cluster.shutdown() + if cql_session is not None: + cql_session.shutdown() + connection.setup() diff --git a/3.22.3-scylla/_sources/cqlengine/upgrade_guide.rst.txt b/3.22.3-scylla/_sources/cqlengine/upgrade_guide.rst.txt new file mode 100644 index 0000000000..5a10ebb757 --- /dev/null +++ b/3.22.3-scylla/_sources/cqlengine/upgrade_guide.rst.txt @@ -0,0 +1,155 @@ +======================== +Upgrade Guide +======================== + +This is an overview of things that changed as the cqlengine project was merged into +scylla-driver. While efforts were taken to preserve the API and most functionality exactly, +conversion to this package will still require certain minimal updates (namely, imports). + +**THERE IS ONE FUNCTIONAL CHANGE**, described in the first section below. + +Functional Changes +================== +List Prepend Reversing +---------------------- +Legacy cqlengine included a workaround for a Cassandra bug in which prepended list segments were +reversed (`CASSANDRA-8733 `_). As of +this integration, this workaround is removed. The first released integrated version emits +a warning when prepend is used. Subsequent versions will have this warning removed. + +Date Column Type +---------------- +The Date column type in legacy cqlengine used a ``timestamp`` CQL type and truncated the time. +Going forward, the :class:`~.columns.Date` type represents a ``date`` for Cassandra 2.2+ +(`PYTHON-245 `_). +Users of the legacy functionality should convert models to use :class:`~.columns.DateTime` (which +uses ``timestamp`` internally), and use the build-in ``datetime.date`` for input values. + +Remove cqlengine +================ +To avoid confusion or mistakes using the legacy package in your application, it +is prudent to remove the cqlengine package when upgrading to the integrated version. + +The driver setup script will warn if the legacy package is detected during install, +but it will not prevent side-by-side installation. + +Organization +============ +Imports +------- +cqlengine is now integrated as a sub-package of the driver base package 'cassandra'. +Upgrading will require adjusting imports to cqlengine. For example:: + + from cassandra.cqlengine import columns + +is now:: + + from cassandra.cqlengine import columns + +Package-Level Aliases +--------------------- +Legacy cqlengine defined a number of aliases at the package level, which became redundant +when the package was integrated for a driver. These have been removed in favor of absolute +imports, and referring to cannonical definitions. For example, ``cqlengine.ONE`` was an alias +of ``cassandra.ConsistencyLevel.ONE``. In the integrated package, only the +:class:`cassandra.ConsistencyLevel` remains. + +Additionally, submodule aliases are removed from cqlengine in favor of absolute imports. + +These aliases are removed, and not deprecated because they should be straightforward to iron out +at module load time. + +Exceptions +---------- +The legacy cqlengine.exceptions module had a number of Exception classes that were variously +common to the package, or only used in specific modules. Common exceptions were relocated to +cqlengine, and specialized exceptions were placed in the module that raises them. Below is a +listing of updated locations: + +============================ ========== +Exception class New module +============================ ========== +CQLEngineException cassandra.cqlengine +ModelException cassandra.cqlengine.models +ValidationError cassandra.cqlengine +UndefinedKeyspaceException cassandra.cqlengine.connection +LWTException cassandra.cqlengine.query +IfNotExistsWithCounterColumn cassandra.cqlengine.query +============================ ========== + +UnicodeMixin Consolidation +-------------------------- +``class UnicodeMixin`` was defined in several cqlengine modules. This has been consolidated +to a single definition in the cqlengine package init file. This is not technically part of +the API, but noted here for completeness. + +API Deprecations +================ +This upgrade served as a good juncture to deprecate certain API features and invite users to upgrade +to new ones. The first released version does not change functionality -- only introduces deprecation +warnings. Future releases will remove these features in favor of the alternatives. + +Float/Double Overload +--------------------- +Previously there was no ``Double`` column type. Doubles were modeled by specifying ``Float(double_precision=True)``. +This inititializer parameter is now deprecated. Applications should use :class:`~.columns.Double` for CQL ``double``, and :class:`~.columns.Float` +for CQL ``float``. + +Schema Management +----------------- +``cassandra.cqlengine.management.create_keyspace`` is deprecated. Instead, use the new replication-strategy-specific +functions that accept explicit options for known strategies: + +- :func:`~.create_keyspace_simple` +- :func:`~.create_keyspace_network_topology` + +``cassandra.cqlengine.management.delete_keyspace`` is deprecated in favor of a new function, :func:`~.drop_keyspace`. The +intent is simply to make the function match the CQL verb it invokes. + +Model Inheritance +----------------- +The names for class attributes controlling model inheritance are changing. Changes are as follows: + +- Replace 'polymorphic_key' in the base class Column definition with :attr:`~.discriminator_column` +- Replace the '__polymorphic_key__' class attribute the derived classes with :attr:`~.__discriminator_value__` + +The functionality is unchanged -- the intent here is to make the names and language around these attributes more precise. +For now, the old names are just deprecated, and the mapper will emit warnings if they are used. The old names +will be removed in a future version. + +The example below shows a simple translation: + +Before:: + + class Pet(Model): + __table_name__ = 'pet' + owner_id = UUID(primary_key=True) + pet_id = UUID(primary_key=True) + pet_type = Text(polymorphic_key=True) + name = Text() + + class Cat(Pet): + __polymorphic_key__ = 'cat' + + class Dog(Pet): + __polymorphic_key__ = 'dog' + +After:: + + class Pet(models.Model): + __table_name__ = 'pet' + owner_id = UUID(primary_key=True) + pet_id = UUID(primary_key=True) + pet_type = Text(discriminator_column=True) + name = Text() + + class Cat(Pet): + __discriminator_value__ = 'cat' + + class Dog(Pet): + __discriminator_value__ = 'dog' + + +TimeUUID.from_datetime +---------------------- +This function is deprecated in favor of the core utility function :func:`~.uuid_from_time`. diff --git a/3.22.3-scylla/_sources/dates_and_times.rst.txt b/3.22.3-scylla/_sources/dates_and_times.rst.txt new file mode 100644 index 0000000000..7a89f77437 --- /dev/null +++ b/3.22.3-scylla/_sources/dates_and_times.rst.txt @@ -0,0 +1,87 @@ +Working with Dates and Times +============================ + +This document is meant to provide on overview of the assumptions and limitations of the driver time handling, the +reasoning behind it, and describe approaches to working with these types. + +timestamps (Cassandra DateType) +------------------------------- + +Timestamps in Cassandra are timezone-naive timestamps encoded as millseconds since UNIX epoch. Clients working with +timestamps in this database usually find it easiest to reason about them if they are always assumed to be UTC. To quote the +pytz documentation, "The preferred way of dealing with times is to always work in UTC, converting to localtime only when +generating output to be read by humans." The driver adheres to this tenant, and assumes UTC is always in the database. The +driver attempts to make this correct on the way in, and assumes no timezone on the way out. + +Write Path +~~~~~~~~~~ +When inserting timestamps, the driver handles serialization for the write path as follows: + +If the input is a ``datetime.datetime``, the serialization is normalized by starting with the ``utctimetuple()`` of the +value. + +- If the ``datetime`` object is timezone-aware, the timestamp is shifted, and represents the UTC timestamp equivalent. +- If the ``datetime`` object is timezone-naive, this results in no shift -- any ``datetime`` with no timezone information is assumed to be UTC + +Note the second point above applies even to "local" times created using ``now()``:: + + >>> d = datetime.now() + + >>> print(d.tzinfo) + None + + +These do not contain timezone information intrinsically, so they will be assumed to be UTC and not shifted. When generating +timestamps in the application, it is clearer to use ``datetime.utcnow()`` to be explicit about it. + +If the input for a timestamp is numeric, it is assumed to be a epoch-relative millisecond timestamp, as specified in the +CQL spec -- no scaling or conversion is done. + +Read Path +~~~~~~~~~ +The driver always assumes persisted timestamps are UTC and makes no attempt to localize them. Returned values are +timezone-naive ``datetime.datetime``. We follow this approach because the datetime API has deficiencies around daylight +saving time, and the defacto package for handling this is a third-party package (we try to minimize external dependencies +and not make decisions for the integrator). + +The decision for how to handle timezones is left to the application. For the most part it is straightforward to apply +localization to the ``datetime``\s returned by queries. One prevalent method is to use pytz for localization:: + + import pytz + user_tz = pytz.timezone('US/Central') + timestamp_naive = row.ts + timestamp_utc = pytz.utc.localize(timestamp_naive) + timestamp_presented = timestamp_utc.astimezone(user_tz) + +This is the most robust approach (likely refactored into a function). If it is deemed too cumbersome to apply for all call +sites in the application, it is possible to patch the driver with custom deserialization for this type. However, doing +this depends depends some on internal APIs and what extensions are present, so we will only mention the possibility, and +not spell it out here. + +date, time (Cassandra DateType) +------------------------------- +Date and time in Cassandra are idealized markers, much like ``datetime.date`` and ``datetime.time`` in the Python standard +library. Unlike these Python implementations, the Cassandra encoding supports much wider ranges. To accommodate these +ranges without overflow, this driver returns these data in custom types: :class:`.util.Date` and :class:`.util.Time`. + +Write Path +~~~~~~~~~~ +For simple (not prepared) statements, the input values for each of these can be either a string literal or an encoded +integer. See `Working with dates `_ +or `Working with time `_ for details +on the encoding or string formats. + +For prepared statements, the driver accepts anything that can be used to construct the :class:`.util.Date` or +:class:`.util.Time` classes. See the linked API docs for details. + +Read Path +~~~~~~~~~ +The driver always returns custom types for ``date`` and ``time``. + +The driver returns :class:`.util.Date` for ``date`` in order to accommodate the wider range of values without overflow. +For applications working within the supported range of [``datetime.MINYEAR``, ``datetime.MAXYEAR``], these are easily +converted to standard ``datetime.date`` insances using :meth:`.Date.date`. + +The driver returns :class:`.util.Time` for ``time`` in order to retain nanosecond precision stored in the database. +For applications not concerned with this level of precision, these are easily converted to standard ``datetime.time`` +insances using :meth:`.Time.time`. diff --git a/3.22.3-scylla/_sources/execution_profiles.rst.txt b/3.22.3-scylla/_sources/execution_profiles.rst.txt new file mode 100644 index 0000000000..7be1a85e3f --- /dev/null +++ b/3.22.3-scylla/_sources/execution_profiles.rst.txt @@ -0,0 +1,156 @@ +Execution Profiles +================== + +Execution profiles aim at making it easier to execute requests in different ways within +a single connected ``Session``. Execution profiles are being introduced to deal with the exploding number of +configuration options, especially as the database platform evolves more complex workloads. + +The legacy configuration remains intact, but legacy and Execution Profile APIs +cannot be used simultaneously on the same client ``Cluster``. Legacy configuration +will be removed in the next major release (4.0). + +An execution profile and its parameters should be unique across ``Cluster`` instances. +For example, an execution profile and its ``LoadBalancingPolicy`` should +not be applied to more than one ``Cluster`` instance. + +This document explains how Execution Profiles relate to existing settings, and shows how to use the new profiles for +request execution. + +Mapping Legacy Parameters to Profiles +------------------------------------- + +Execution profiles can inherit from :class:`.cluster.ExecutionProfile`, and currently provide the following options, +previously input from the noted attributes: + +- load_balancing_policy - :attr:`.Cluster.load_balancing_policy` +- request_timeout - :attr:`.Session.default_timeout`, optional :meth:`.Session.execute` parameter +- retry_policy - :attr:`.Cluster.default_retry_policy`, optional :attr:`.Statement.retry_policy` attribute +- consistency_level - :attr:`.Session.default_consistency_level`, optional :attr:`.Statement.consistency_level` attribute +- serial_consistency_level - :attr:`.Session.default_serial_consistency_level`, optional :attr:`.Statement.serial_consistency_level` attribute +- row_factory - :attr:`.Session.row_factory` attribute + +When using the new API, these parameters can be defined by instances of :class:`.cluster.ExecutionProfile`. + +Using Execution Profiles +------------------------ +Default +~~~~~~~ + +.. code:: python + + from cassandra.cluster import Cluster + cluster = Cluster() + session = cluster.connect() + local_query = 'SELECT rpc_address FROM system.local' + for _ in cluster.metadata.all_hosts(): + print session.execute(local_query)[0] + + +.. parsed-literal:: + + Row(rpc_address='127.0.0.2') + Row(rpc_address='127.0.0.1') + + +The default execution profile is built from Cluster parameters and default Session attributes. This profile matches existing default +parameters. + +Initializing cluster with profiles +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. code:: python + + from cassandra.cluster import ExecutionProfile + from cassandra.policies import WhiteListRoundRobinPolicy + + node1_profile = ExecutionProfile(load_balancing_policy=WhiteListRoundRobinPolicy(['127.0.0.1'])) + node2_profile = ExecutionProfile(load_balancing_policy=WhiteListRoundRobinPolicy(['127.0.0.2'])) + + profiles = {'node1': node1_profile, 'node2': node2_profile} + session = Cluster(execution_profiles=profiles).connect() + for _ in cluster.metadata.all_hosts(): + print session.execute(local_query, execution_profile='node1')[0] + + +.. parsed-literal:: + + Row(rpc_address='127.0.0.1') + Row(rpc_address='127.0.0.1') + + +.. code:: python + + for _ in cluster.metadata.all_hosts(): + print session.execute(local_query, execution_profile='node2')[0] + + +.. parsed-literal:: + + Row(rpc_address='127.0.0.2') + Row(rpc_address='127.0.0.2') + + +.. code:: python + + for _ in cluster.metadata.all_hosts(): + print session.execute(local_query)[0] + + +.. parsed-literal:: + + Row(rpc_address='127.0.0.2') + Row(rpc_address='127.0.0.1') + +Note that, even when custom profiles are injected, the default ``TokenAwarePolicy(DCAwareRoundRobinPolicy())`` is still +present. To override the default, specify a policy with the :data:`~.cluster.EXEC_PROFILE_DEFAULT` key. + +.. code:: python + + from cassandra.cluster import EXEC_PROFILE_DEFAULT + profile = ExecutionProfile(request_timeout=30) + cluster = Cluster(execution_profiles={EXEC_PROFILE_DEFAULT: profile}) + + +Adding named profiles +~~~~~~~~~~~~~~~~~~~~~ + +New profiles can be added constructing from scratch, or deriving from default: + +.. code:: python + + locked_execution = ExecutionProfile(load_balancing_policy=WhiteListRoundRobinPolicy(['127.0.0.1'])) + node1_profile = 'node1_whitelist' + cluster.add_execution_profile(node1_profile, locked_execution) + + for _ in cluster.metadata.all_hosts(): + print session.execute(local_query, execution_profile=node1_profile)[0] + + +.. parsed-literal:: + + Row(rpc_address='127.0.0.1') + Row(rpc_address='127.0.0.1') + +See :meth:`.Cluster.add_execution_profile` for details and optional parameters. + +Passing a profile instance without mapping +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +We also have the ability to pass profile instances to be used for execution, but not added to the mapping: + +.. code:: python + + from cassandra.query import tuple_factory + + tmp = session.execution_profile_clone_update('node1', request_timeout=100, row_factory=tuple_factory) + + print session.execute(local_query, execution_profile=tmp)[0] + print session.execute(local_query, execution_profile='node1')[0] + +.. parsed-literal:: + + ('127.0.0.1',) + Row(rpc_address='127.0.0.1') + +The new profile is a shallow copy, so the ``tmp`` profile shares a load balancing policy with one managed by the cluster. +If reference objects are to be updated in the clone, one would typically set those attributes to a new instance. diff --git a/3.22.3-scylla/_sources/faq.rst.txt b/3.22.3-scylla/_sources/faq.rst.txt new file mode 100644 index 0000000000..56cb648a24 --- /dev/null +++ b/3.22.3-scylla/_sources/faq.rst.txt @@ -0,0 +1,83 @@ +Frequently Asked Questions +========================== + +See also :doc:`cqlengine FAQ ` + +Why do connections or IO operations timeout in my WSGI application? +------------------------------------------------------------------- +Depending on your application process model, it may be forking after driver Session is created. Most IO reactors do not handle this, and problems will manifest as timeouts. + +To avoid this, make sure to create sessions per process, after the fork. Using uWSGI and Flask for example: + +.. code-block:: python + + from flask import Flask + from uwsgidecorators import postfork + from cassandra.cluster import Cluster + + session = None + prepared = None + + @postfork + def connect(): + global session, prepared + session = Cluster().connect() + prepared = session.prepare("SELECT release_version FROM system.local WHERE key=?") + + app = Flask(__name__) + + @app.route('/') + def server_version(): + row = session.execute(prepared, ('local',))[0] + return row.release_version + +uWSGI provides a ``postfork`` hook you can use to create sessions and prepared statements after the child process forks. + +How do I trace a request? +------------------------- +Request tracing can be turned on for any request by setting ``trace=True`` in :meth:`.Session.execute_async`. View the results by waiting on the future, then :meth:`.ResponseFuture.get_query_trace`. +Since tracing is done asynchronously to the request, this method polls until the trace is complete before querying data. + +.. code-block:: python + + >>> future = session.execute_async("SELECT * FROM system.local", trace=True) + >>> result = future.result() + >>> trace = future.get_query_trace() + >>> for e in trace.events: + >>> print e.source_elapsed, e.description + + 0:00:00.000077 Parsing select * from system.local + 0:00:00.000153 Preparing statement + 0:00:00.000309 Computing ranges to query + 0:00:00.000368 Submitting range requests on 1 ranges with a concurrency of 1 (279.77142 rows per range expected) + 0:00:00.000422 Submitted 1 concurrent range requests covering 1 ranges + 0:00:00.000480 Executing seq scan across 1 sstables for (min(-9223372036854775808), min(-9223372036854775808)) + 0:00:00.000669 Read 1 live and 0 tombstone cells + 0:00:00.000755 Scanned 1 rows and matched 1 + +``trace`` is a :class:`QueryTrace` object. + +How do I determine the replicas for a query? +---------------------------------------------- +With prepared statements, the replicas are obtained by ``routing_key``, based on current cluster token metadata: + +.. code-block:: python + + >>> prepared = session.prepare("SELECT * FROM example.t WHERE key=?") + >>> bound = prepared.bind((1,)) + >>> replicas = cluster.metadata.get_replicas(bound.keyspace, bound.routing_key) + >>> for h in replicas: + >>> print h.address + 127.0.0.1 + 127.0.0.2 + +``replicas`` is a list of :class:`Host` objects. + +How does the driver manage request retries? +------------------------------------------- +By default, retries are managed by the :attr:`.Cluster.default_retry_policy` set on the session Cluster. It can also +be specialized per statement by setting :attr:`.Statement.retry_policy`. + +Retries are presently attempted on the same coordinator, but this may change in the future. + +Please see :class:`.policies.RetryPolicy` for further details. diff --git a/3.22.3-scylla/_sources/getting_started.rst.txt b/3.22.3-scylla/_sources/getting_started.rst.txt new file mode 100644 index 0000000000..8cb86a5504 --- /dev/null +++ b/3.22.3-scylla/_sources/getting_started.rst.txt @@ -0,0 +1,473 @@ +Getting Started +=============== + +First, make sure you have the driver properly :doc:`installed `. + +Connecting to Cassandra +----------------------- +Before we can start executing any queries against a Cassandra cluster we need to setup +an instance of :class:`~.Cluster`. As the name suggests, you will typically have one +instance of :class:`~.Cluster` for each Cassandra cluster you want to interact +with. + +The simplest way to create a :class:`~.Cluster` is like this: +First, make sure you have the Cassandra driver properly :doc:`installed `. + +.. code-block:: python + + from cassandra.cluster import Cluster + + cluster = Cluster() + +This will attempt to connection to a Cassandra instance on your +local machine (127.0.0.1). You can also specify a list of IP +addresses for nodes in your cluster: + +.. code-block:: python + + from cassandra.cluster import Cluster + + cluster = Cluster(['192.168.0.1', '192.168.0.2']) + +The set of IP addresses we pass to the :class:`~.Cluster` is simply +an initial set of contact points. After the driver connects to one +of these nodes it will *automatically discover* the rest of the +nodes in the cluster and connect to them, so you don't need to list +every node in your cluster. + +If you need to use a non-standard port, use SSL, or customize the driver's +behavior in some other way, this is the place to do it: + +.. code-block:: python + + from cassandra.cluster import Cluster + cluster = Cluster(['192.168.0.1', '192.168.0.2'], port=..., ssl_context=...) + +Instantiating a :class:`~.Cluster` does not actually connect us to any nodes. +To establish connections and begin executing queries we need a +:class:`~.Session`, which is created by calling :meth:`.Cluster.connect()`: + +.. code-block:: python + + cluster = Cluster() + session = cluster.connect() + +The :meth:`~.Cluster.connect()` method takes an optional ``keyspace`` argument +which sets the default keyspace for all queries made through that :class:`~.Session`: + +.. code-block:: python + + cluster = Cluster() + session = cluster.connect('mykeyspace') + + +You can always change a Session's keyspace using :meth:`~.Session.set_keyspace` or +by executing a ``USE `` query: + +.. code-block:: python + + session.set_keyspace('users') + # or you can do this instead + session.execute('USE users') + +Profiles are passed in by ``execution_profiles`` dict. + +In this case we can construct the base ``ExecutionProfile`` passing all attributes: + +.. code-block:: python + + from cassandra.cluster import Cluster, ExecutionProfile, EXEC_PROFILE_DEFAULT + from cassandra.policies import WhiteListRoundRobinPolicy, DowngradingConsistencyRetryPolicy + from cassandra.query import tuple_factory + + profile = ExecutionProfile( + load_balancing_policy=WhiteListRoundRobinPolicy(['127.0.0.1']), + retry_policy=DowngradingConsistencyRetryPolicy(), + consistency_level=ConsistencyLevel.LOCAL_QUORUM, + serial_consistency_level=ConsistencyLevel.LOCAL_SERIAL, + request_timeout=15, + row_factory=tuple_factory + ) + cluster = Cluster(execution_profiles={EXEC_PROFILE_DEFAULT: profile}) + session = cluster.connect() + + print(session.execute("SELECT release_version FROM system.local").one()) + +Users are free to setup additional profiles to be used by name: + +.. code-block:: python + + profile_long = ExecutionProfile(request_timeout=30) + cluster = Cluster(execution_profiles={'long': profile_long}) + session = cluster.connect() + session.execute(statement, execution_profile='long') + +Also, parameters passed to ``Session.execute`` or attached to ``Statement``\s are still honored as before. + +Executing Queries +----------------- +Now that we have a :class:`.Session` we can begin to execute queries. The simplest +way to execute a query is to use :meth:`~.Session.execute()`: + +.. code-block:: python + + rows = session.execute('SELECT name, age, email FROM users') + for user_row in rows: + print user_row.name, user_row.age, user_row.email + +This will transparently pick a Cassandra node to execute the query against +and handle any retries that are necessary if the operation fails. + +By default, each row in the result set will be a +`namedtuple `_. +Each row will have a matching attribute for each column defined in the schema, +such as ``name``, ``age``, and so on. You can also treat them as normal tuples +by unpacking them or accessing fields by position. The following three +examples are equivalent: + +.. code-block:: python + + rows = session.execute('SELECT name, age, email FROM users') + for row in rows: + print row.name, row.age, row.email + +.. code-block:: python + + rows = session.execute('SELECT name, age, email FROM users') + for (name, age, email) in rows: + print name, age, email + +.. code-block:: python + + rows = session.execute('SELECT name, age, email FROM users') + for row in rows: + print row[0], row[1], row[2] + +If you prefer another result format, such as a ``dict`` per row, you +can change the :attr:`~.Session.row_factory` attribute. + +As mentioned in our `Drivers Best Practices Guide `_, +it is highly recommended to use `Prepared statements <#prepared-statement>`_ for your +frequently run queries. + +.. _prepared-statement: + +Prepared Statements +------------------- +Prepared statements are queries that are parsed by Cassandra and then saved +for later use. When the driver uses a prepared statement, it only needs to +send the values of parameters to bind. This lowers network traffic +and CPU utilization within Cassandra because Cassandra does not have to +re-parse the query each time. + +To prepare a query, use :meth:`.Session.prepare()`: + +.. code-block:: python + + user_lookup_stmt = session.prepare("SELECT * FROM users WHERE user_id=?") + + users = [] + for user_id in user_ids_to_query: + user = session.execute(user_lookup_stmt, [user_id]) + users.append(user) + +:meth:`~.Session.prepare()` returns a :class:`~.PreparedStatement` instance +which can be used in place of :class:`~.SimpleStatement` instances or literal +string queries. It is automatically prepared against all nodes, and the driver +handles re-preparing against new nodes and restarted nodes when necessary. + +Note that the placeholders for prepared statements are ``?`` characters. This +is different than for simple, non-prepared statements (although future versions +of the driver may use the same placeholders for both). + +Passing Parameters to CQL Queries +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Althought it is not recommended, you can also pass parameters to non-prepared +statements. The driver supports two forms of parameter place-holders: positional +and named. + +Positional parameters are used with a ``%s`` placeholder. For example, +when you execute: + +.. code-block:: python + + session.execute( + """ + INSERT INTO users (name, credits, user_id) + VALUES (%s, %s, %s) + """, + ("John O'Reilly", 42, uuid.uuid1()) + ) + +It is translated to the following CQL query:: + + INSERT INTO users (name, credits, user_id) + VALUES ('John O''Reilly', 42, 2644bada-852c-11e3-89fb-e0b9a54a6d93) + +Note that you should use ``%s`` for all types of arguments, not just strings. +For example, this would be **wrong**: + +.. code-block:: python + + session.execute("INSERT INTO USERS (name, age) VALUES (%s, %d)", ("bob", 42)) # wrong + +Instead, use ``%s`` for the age placeholder. + +If you need to use a literal ``%`` character, use ``%%``. + +**Note**: you must always use a sequence for the second argument, even if you are +only passing in a single variable: + +.. code-block:: python + + session.execute("INSERT INTO foo (bar) VALUES (%s)", "blah") # wrong + session.execute("INSERT INTO foo (bar) VALUES (%s)", ("blah")) # wrong + session.execute("INSERT INTO foo (bar) VALUES (%s)", ("blah", )) # right + session.execute("INSERT INTO foo (bar) VALUES (%s)", ["blah"]) # right + + +Note that the second line is incorrect because in Python, single-element tuples +require a comma. + +Named place-holders use the ``%(name)s`` form: + +.. code-block:: python + + session.execute( + """ + INSERT INTO users (name, credits, user_id, username) + VALUES (%(name)s, %(credits)s, %(user_id)s, %(name)s) + """, + {'name': "John O'Reilly", 'credits': 42, 'user_id': uuid.uuid1()} + ) + +Note that you can repeat placeholders with the same name, such as ``%(name)s`` +in the above example. + +Only data values should be supplied this way. Other items, such as keyspaces, +table names, and column names should be set ahead of time (typically using +normal string formatting). + +.. _type-conversions: + +Type Conversions +^^^^^^^^^^^^^^^^ +For non-prepared statements, Python types are cast to CQL literals in the +following way: + +.. table:: + + +--------------------+-------------------------+ + | Python Type | CQL Literal Type | + +====================+=========================+ + | ``None`` | ``NULL`` | + +--------------------+-------------------------+ + | ``bool`` | ``boolean`` | + +--------------------+-------------------------+ + | ``float`` | | ``float`` | + | | | ``double`` | + +--------------------+-------------------------+ + | | ``int`` | | ``int`` | + | | ``long`` | | ``bigint`` | + | | | ``varint`` | + | | | ``smallint`` | + | | | ``tinyint`` | + | | | ``counter`` | + +--------------------+-------------------------+ + | ``decimal.Decimal``| ``decimal`` | + +--------------------+-------------------------+ + | | ``str`` | | ``ascii`` | + | | ``unicode`` | | ``varchar`` | + | | | ``text`` | + +--------------------+-------------------------+ + | | ``buffer`` | ``blob`` | + | | ``bytearray`` | | + +--------------------+-------------------------+ + | ``date`` | ``date`` | + +--------------------+-------------------------+ + | ``datetime`` | ``timestamp`` | + +--------------------+-------------------------+ + | ``time`` | ``time`` | + +--------------------+-------------------------+ + | | ``list`` | ``list`` | + | | ``tuple`` | | + | | generator | | + +--------------------+-------------------------+ + | | ``set`` | ``set`` | + | | ``frozenset`` | | + +--------------------+-------------------------+ + | | ``dict`` | ``map`` | + | | ``OrderedDict`` | | + +--------------------+-------------------------+ + | ``uuid.UUID`` | | ``timeuuid`` | + | | | ``uuid`` | + +--------------------+-------------------------+ + + +Asynchronous Queries +^^^^^^^^^^^^^^^^^^^^ +The driver supports asynchronous query execution through +:meth:`~.Session.execute_async()`. Instead of waiting for the query to +complete and returning rows directly, this method almost immediately +returns a :class:`~.ResponseFuture` object. There are two ways of +getting the final result from this object. + +The first is by calling :meth:`~.ResponseFuture.result()` on it. If +the query has not yet completed, this will block until it has and +then return the result or raise an Exception if an error occurred. +For example: + +.. code-block:: python + + from cassandra import ReadTimeout + + query = "SELECT * FROM users WHERE user_id=%s" + future = session.execute_async(query, [user_id]) + + # ... do some other work + + try: + rows = future.result() + user = rows[0] + print user.name, user.age + except ReadTimeout: + log.exception("Query timed out:") + +This works well for executing many queries concurrently: + +.. code-block:: python + + # build a list of futures + futures = [] + query = "SELECT * FROM users WHERE user_id=%s" + for user_id in ids_to_fetch: + futures.append(session.execute_async(query, [user_id]) + + # wait for them to complete and use the results + for future in futures: + rows = future.result() + print rows[0].name + +Alternatively, instead of calling :meth:`~.ResponseFuture.result()`, +you can attach callback and errback functions through the +:meth:`~.ResponseFuture.add_callback()`, +:meth:`~.ResponseFuture.add_errback()`, and +:meth:`~.ResponseFuture.add_callbacks()`, methods. If you have used +Twisted Python before, this is designed to be a lightweight version of +that: + +.. code-block:: python + + def handle_success(rows): + user = rows[0] + try: + process_user(user.name, user.age, user.id) + except Exception: + log.error("Failed to process user %s", user.id) + # don't re-raise errors in the callback + + def handle_error(exception): + log.error("Failed to fetch user info: %s", exception) + + + future = session.execute_async(query) + future.add_callbacks(handle_success, handle_error) + +There are a few important things to remember when working with callbacks: + * **Exceptions that are raised inside the callback functions will be logged and then ignored.** + * Your callback will be run on the event loop thread, so any long-running + operations will prevent other requests from being handled + + +Setting a Consistency Level +--------------------------- +The consistency level used for a query determines how many of the +replicas of the data you are interacting with need to respond for +the query to be considered a success. + +By default, :attr:`.ConsistencyLevel.LOCAL_ONE` will be used for all queries. +You can specify a different default by setting the :attr:`.ExecutionProfile.consistency_level` +for the execution profile with key :data:`~.cluster.EXEC_PROFILE_DEFAULT`. +To specify a different consistency level per request, wrap queries +in a :class:`~.SimpleStatement`: + +.. code-block:: python + + from cassandra import ConsistencyLevel + from cassandra.query import SimpleStatement + + query = SimpleStatement( + "INSERT INTO users (name, age) VALUES (%s, %s)", + consistency_level=ConsistencyLevel.QUORUM) + session.execute(query, ('John', 42)) + +Setting a Consistency Level with Prepared Statements +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +To specify a consistency level for prepared statements, you have two options. + +The first is to set a default consistency level for every execution of the +prepared statement: + +.. code-block:: python + + from cassandra import ConsistencyLevel + + cluster = Cluster() + session = cluster.connect("mykeyspace") + user_lookup_stmt = session.prepare("SELECT * FROM users WHERE user_id=?") + user_lookup_stmt.consistency_level = ConsistencyLevel.QUORUM + + # these will both use QUORUM + user1 = session.execute(user_lookup_stmt, [user_id1])[0] + user2 = session.execute(user_lookup_stmt, [user_id2])[0] + +The second option is to create a :class:`~.BoundStatement` from the +:class:`~.PreparedStatement` and binding parameters and set a consistency +level on that: + +.. code-block:: python + + # override the QUORUM default + user3_lookup = user_lookup_stmt.bind([user_id3]) + user3_lookup.consistency_level = ConsistencyLevel.ALL + user3 = session.execute(user3_lookup) + +Speculative Execution +^^^^^^^^^^^^^^^^^^^^^ + +Speculative execution is a way to minimize latency by preemptively executing several +instances of the same query against different nodes. For more details about this +technique, see `Speculative Execution with DataStax Drivers `_. + +To enable speculative execution: + +* Configure a :class:`~.policies.SpeculativeExecutionPolicy` with the ExecutionProfile +* Mark your query as idempotent, which mean it can be applied multiple + times without changing the result of the initial application. + See `Query Idempotence `_ for more details. + + +Example: + +.. code-block:: python + + from cassandra.cluster import Cluster, ExecutionProfile, EXEC_PROFILE_DEFAULT + from cassandra.policies import ConstantSpeculativeExecutionPolicy + from cassandra.query import SimpleStatement + + # Configure the speculative execution policy + ep = ExecutionProfile( + speculative_execution_policy=ConstantSpeculativeExecutionPolicy(delay=.5, max_attempts=10) + ) + cluster = Cluster(..., execution_profiles={EXEC_PROFILE_DEFAULT: ep}) + session = cluster.connect() + + # Mark the query idempotent + query = SimpleStatement( + "UPDATE my_table SET list_col = [1] WHERE pk = 1", + is_idempotent=True + ) + + # Execute. A new query will be sent to the server every 0.5 second + # until we receive a response, for a max number attempts of 10. + session.execute(query) diff --git a/3.22.3-scylla/_sources/index.rst.txt b/3.22.3-scylla/_sources/index.rst.txt new file mode 100644 index 0000000000..371a79c987 --- /dev/null +++ b/3.22.3-scylla/_sources/index.rst.txt @@ -0,0 +1,105 @@ +Python Driver for Scylla and Apache Cassandra® +============================================== +A Python client driver for `Scylla `_. +This driver works exclusively with the Cassandra Query Language v3 (CQL3) +and Cassandra's native protocol. + +The driver supports Python 2.7, 3.4, 3.5, 3.6, 3.7 and 3.8. + +This driver is open source under the +`Apache v2 License `_. +The source code for this driver can be found on `GitHub `_. + +Scylla Driver is a fork from `DataStax Python Driver `_, including some non-breaking changes for Scylla optimization, with more updates planned. + +Contents +-------- +:doc:`installation` + How to install the driver. + +:doc:`getting_started` + A guide through the first steps of connecting to Scylla and executing queries + +:doc:`scylla_specific` + A list of feature available only on ``scylla-driver`` + +:doc:`execution_profiles` + An introduction to a more flexible way of configuring request execution + +:doc:`lwt` + Working with results of conditional requests + +:doc:`object_mapper` + Introduction to the integrated object mapper, cqlengine + +:doc:`performance` + Tips for getting good performance. + +:doc:`query_paging` + Notes on paging large query results + +:doc:`security` + An overview of the security features of the driver + +:doc:`upgrading` + A guide to upgrading versions of the driver + +:doc:`user_defined_types` + Working with Scylla's user-defined types (UDT) + +:doc:`dates_and_times` + Some discussion on the driver's approach to working with timestamp, date, time types + +:doc:`scylla_cloud` + Connect to Scylla Cloud + +:doc:`CHANGELOG` + Log of changes to the driver, organized by version. + +:doc:`faq` + A collection of Frequently Asked Questions + +:doc:`api/index` + The API documentation. + +.. toctree:: + :hidden: + + api/index + installation + getting_started + scylla_specific + upgrading + execution_profiles + performance + query_paging + lwt + security + user_defined_types + object_mapper + dates_and_times + scylla_cloud + faq + +Getting Help +------------ +Visit the :doc:`FAQ section ` in this documentation. + +Please send questions to the Scylla `user list `_. + + +Reporting Issues +---------------- + +Please report any bugs and make any feature requests on the `Github project issues `_ + + +Copyright +--------- + +© 2013-2017 DataStax + +© 2016, The Apache Software Foundation. +Apache®, Apache Cassandra®, Cassandra®, the Apache feather logo and the Apache Cassandra® Eye logo are either registered trademarks or trademarks of the Apache Software Foundation in the United States and/or other countries. No endorsement by The Apache Software Foundation is implied by the use of these marks. + + diff --git a/3.22.3-scylla/_sources/installation.rst.txt b/3.22.3-scylla/_sources/installation.rst.txt new file mode 100644 index 0000000000..c67b9e7909 --- /dev/null +++ b/3.22.3-scylla/_sources/installation.rst.txt @@ -0,0 +1,236 @@ +Installation +============ + +Supported Platforms +------------------- +Python 2.7, 3.4, 3.5, 3.6, 3.7 and 3.8 are supported. Both CPython (the standard Python +implementation) and `PyPy `_ are supported and tested. + +Linux, OSX, and Windows are supported. + +Installation through pip +------------------------ +`pip `_ is the suggested tool for installing +packages. It will handle installing all Python dependencies for the driver at +the same time as the driver itself. To install the driver*:: + + pip install scylla-driver + +You can use ``pip install --pre scylla-driver`` if you need to install a beta version. + +***Note**: if intending to use optional extensions, install the `dependencies <#optional-non-python-dependencies>`_ first. The driver may need to be reinstalled if dependencies are added after the initial installation. + +Verifying your Installation +--------------------------- +To check if the installation was successful, you can run:: + + python -c 'import cassandra; print cassandra.__version__' + +It should print something like "3.22.0". + +.. _installation-datastax-graph: + +(*Optional*) DataStax Graph +--------------------------- +The driver provides an optional fluent graph API that depends on Apache TinkerPop (gremlinpython). It is +not installed by default. To be able to build Gremlin traversals, you need to install +the `graph` requirements:: + + pip install scylla-driver[graph] + +See :doc:`graph_fluent` for more details about this API. + +(*Optional*) Compression Support +-------------------------------- +Compression can optionally be used for communication between the driver and +Cassandra. There are currently two supported compression algorithms: +snappy (in Cassandra 1.2+) and LZ4 (only in Cassandra 2.0+). If either is +available for the driver and Cassandra also supports it, it will +be used automatically. + +For lz4 support:: + + pip install lz4 + +For snappy support:: + + pip install python-snappy + +(If using a Debian Linux derivative such as Ubuntu, it may be easier to +just run ``apt-get install python-snappy``.) + +(*Optional*) Metrics Support +---------------------------- +The driver has built-in support for capturing :attr:`.Cluster.metrics` about +the queries you run. However, the ``scales`` library is required to +support this:: + + pip install scales + + +Speeding Up Installation +^^^^^^^^^^^^^^^^^^^^^^^^ + +By default, installing the driver through ``pip`` uses a pre-compiled, platform-specific wheel when available. +If using a source distribution rather than a wheel, Cython is used to compile certain parts of the driver. +This makes those hot paths faster at runtime, but the Cython compilation +process can take a long time -- as long as 10 minutes in some environments. + +In environments where performance is less important, it may be worth it to +:ref:`disable Cython as documented below `. +You can also use ``CASS_DRIVER_BUILD_CONCURRENCY`` to increase the number of +threads used to build the driver and any C extensions: + +.. code-block:: bash + + $ # installing from source + $ CASS_DRIVER_BUILD_CONCURRENCY=8 python setup.py install + $ # installing from pip + $ CASS_DRIVER_BUILD_CONCURRENCY=8 pip install scylla-driver + +OSX Installation Error +^^^^^^^^^^^^^^^^^^^^^^ +If you're installing on OSX and have XCode 5.1 installed, you may see an error like this:: + + clang: error: unknown argument: '-mno-fused-madd' [-Wunused-command-line-argument-hard-error-in-future] + +To fix this, re-run the installation with an extra compilation flag: + +.. code-block:: bash + + ARCHFLAGS=-Wno-error=unused-command-line-argument-hard-error-in-future pip install scylla-driver + +.. _windows_build: + +Windows Installation Notes +-------------------------- +Installing the driver with extensions in Windows sometimes presents some challenges. A few notes about common +hang-ups: + +Setup requires a compiler. When using Python 2, this is as simple as installing `this package `_ +(this link is also emitted during install if setuptools is unable to find the resources it needs). Depending on your +system settings, this package may install as a user-specific application. Make sure to install for everyone, or at least +as the user that will be building the Python environment. + +It is also possible to run the build with your compiler of choice. Just make sure to have your environment setup with +the proper paths. Make sure the compiler target architecture matches the bitness of your Python runtime. +Perhaps the easiest way to do this is to run the build/install from a Visual Studio Command Prompt (a +shortcut installed with Visual Studio that sources the appropriate environment and presents a shell). + +Manual Installation +------------------- +You can always install the driver directly from a source checkout or tarball. +When installing manually, ensure the python dependencies are already +installed. You can find the list of dependencies in +`requirements.txt `_. + +Once the dependencies are installed, simply run:: + + python setup.py install + + +(*Optional*) Non-python Dependencies +------------------------------------ +The driver has several **optional** features that have non-Python dependencies. + +C Extensions +^^^^^^^^^^^^ +By default, a number of extensions are compiled, providing faster hashing +for token-aware routing with the ``Murmur3Partitioner``, +`libev `_ event loop integration, +and Cython optimized extensions. + +When installing manually through setup.py, you can disable both with +the ``--no-extensions`` option, or selectively disable them with +with ``--no-murmur3``, ``--no-libev``, or ``--no-cython``. + +To compile the extensions, ensure that GCC and the Python headers are available. + +On Ubuntu and Debian, this can be accomplished by running:: + + $ sudo apt-get install gcc python-dev + +On RedHat and RedHat-based systems like CentOS and Fedora:: + + $ sudo yum install gcc python-devel + +On OS X, homebrew installations of Python should provide the necessary headers. + +See :ref:`windows_build` for notes on configuring the build environment on Windows. + +.. _cython-extensions: + +Cython-based Extensions +~~~~~~~~~~~~~~~~~~~~~~~ +By default, this package uses `Cython `_ to optimize core modules and build custom extensions. +This is not a hard requirement, but is engaged by default to build extensions offering better performance than the +pure Python implementation. + +This is a costly build phase, especially in clean environments where the Cython compiler must be built +This build phase can be avoided using the build switch, or an environment variable:: + + python setup.py install --no-cython + +Alternatively, an environment variable can be used to switch this option regardless of +context:: + + CASS_DRIVER_NO_CYTHON=1 + - or, to disable all extensions: + CASS_DRIVER_NO_EXTENSIONS=1 + +This method is required when using pip, which provides no other way of injecting user options in a single command:: + + CASS_DRIVER_NO_CYTHON=1 pip install scylla-driver + CASS_DRIVER_NO_CYTHON=1 sudo -E pip install ~/python-driver + +The environment variable is the preferred option because it spans all invocations of setup.py, and will +prevent Cython from being materialized as a setup requirement. + +If your sudo configuration does not allow SETENV, you must push the option flag down via pip. However, pip +applies these options to all dependencies (which break on the custom flag). Therefore, you must first install +dependencies, then use install-option:: + + sudo pip install six futures + sudo pip install --install-option="--no-cython" + + +libev support +^^^^^^^^^^^^^ +The driver currently uses Python's ``asyncore`` module for its default +event loop. For better performance, ``libev`` is also supported through +a C extension. + +If you're on Linux, you should be able to install libev +through a package manager. For example, on Debian/Ubuntu:: + + $ sudo apt-get install libev4 libev-dev + +On RHEL/CentOS/Fedora:: + + $ sudo yum install libev libev-devel + +If you're on Mac OS X, you should be able to install libev +through `Homebrew `_. For example, on Mac OS X:: + + $ brew install libev + +The libev extension is not built for Windows (the build process is complex, and the Windows implementation uses +select anyway). + +If successful, you should be able to build and install the extension +(just using ``setup.py build`` or ``setup.py install``) and then use +the libev event loop by doing the following: + +.. code-block:: python + + >>> from cassandra.io.libevreactor import LibevConnection + >>> from cassandra.cluster import Cluster + + >>> cluster = Cluster() + >>> cluster.connection_class = LibevConnection + >>> session = cluster.connect() + +(*Optional*) Configuring SSL +----------------------------- +Andrew Mussey has published a thorough guide on +`Using SSL with the DataStax Python driver `_. diff --git a/3.22.3-scylla/_sources/lwt.rst.txt b/3.22.3-scylla/_sources/lwt.rst.txt new file mode 100644 index 0000000000..2cc272f350 --- /dev/null +++ b/3.22.3-scylla/_sources/lwt.rst.txt @@ -0,0 +1,91 @@ +Lightweight Transactions (Compare-and-set) +========================================== + +Lightweight Transactions (LWTs) are mostly pass-through CQL for the driver. However, +the server returns some specialized results indicating the outcome and optional state +preceding the transaction. + +For pertinent execution parameters, see :attr:`.Statement.serial_consistency_level`. + +This section discusses working with specialized result sets returned by the server for LWTs, +and how to work with them using the driver. + + +Specialized Results +------------------- +The result returned from a LWT request is always a single row result. It will always have +prepended a special column named ``[applied]``. How this value appears in your results depends +on the row factory in use. See below for examples. + +The value of this ``[applied]`` column is boolean value indicating whether or not the transaction was applied. +If ``True``, it is the only column in the result. If ``False``, the additional columns depend on the LWT operation being +executed: + +- When using a ``UPDATE ... IF "col" = ...`` clause, the result will contain the ``[applied]`` column, plus the existing columns + and values for any columns in the ``IF`` clause (and thus the value that caused the transaction to fail). + +- When using ``INSERT ... IF NOT EXISTS``, the result will contain the ``[applied]`` column, plus all columns and values + of the existing row that rejected the transaction. + +- ``UPDATE .. IF EXISTS`` never has additional columns, regardless of ``[applied]`` status. + +How the ``[applied]`` column manifests depends on the row factory in use. Considering the following (initially empty) table:: + + CREATE TABLE test.t ( + k int PRIMARY KEY, + v int, + x int + ) + +... the following sections show the expected result for a number of example statements, using the three base row factories. + +named_tuple_factory (default) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +The name ``[applied]`` is not a valid Python identifier, so the square brackets are actually removed +from the attribute for the resulting ``namedtuple``. The row always has a boolean column ``applied`` in position 0:: + + >>> session.execute("INSERT INTO t (k,v) VALUES (0,0) IF NOT EXISTS") + Row(applied=True) + + >>> session.execute("INSERT INTO t (k,v) VALUES (0,0) IF NOT EXISTS") + Row(applied=False, k=0, v=0, x=None) + + >>> session.execute("UPDATE t SET v = 1, x = 2 WHERE k = 0 IF v =0") + Row(applied=True) + + >>> session.execute("UPDATE t SET v = 1, x = 2 WHERE k = 0 IF v =0 AND x = 1") + Row(applied=False, v=1, x=2) + +tuple_factory +~~~~~~~~~~~~~ +This return type does not refer to names, but the boolean value ``applied`` is always present in position 0:: + + >>> session.execute("INSERT INTO t (k,v) VALUES (0,0) IF NOT EXISTS") + (True,) + + >>> session.execute("INSERT INTO t (k,v) VALUES (0,0) IF NOT EXISTS") + (False, 0, 0, None) + + >>> session.execute("UPDATE t SET v = 1, x = 2 WHERE k = 0 IF v =0") + (True,) + + >>> session.execute("UPDATE t SET v = 1, x = 2 WHERE k = 0 IF v =0 AND x = 1") + (False, 1, 2) + +dict_factory +~~~~~~~~~~~~ +The retuned ``dict`` contains the ``[applied]`` key:: + + >>> session.execute("INSERT INTO t (k,v) VALUES (0,0) IF NOT EXISTS") + {u'[applied]': True} + + >>> session.execute("INSERT INTO t (k,v) VALUES (0,0) IF NOT EXISTS") + {u'x': 2, u'[applied]': False, u'v': 1} + + >>> session.execute("UPDATE t SET v = 1, x = 2 WHERE k = 0 IF v =0") + {u'x': None, u'[applied]': False, u'k': 0, u'v': 0} + + >>> session.execute("UPDATE t SET v = 1, x = 2 WHERE k = 0 IF v =0 AND x = 1") + {u'[applied]': True} + + diff --git a/3.22.3-scylla/_sources/object_mapper.rst.txt b/3.22.3-scylla/_sources/object_mapper.rst.txt new file mode 100644 index 0000000000..50d3cbf320 --- /dev/null +++ b/3.22.3-scylla/_sources/object_mapper.rst.txt @@ -0,0 +1,105 @@ +Object Mapper +============= + +cqlengine is the Cassandra CQL 3 Object Mapper packaged with this driver + +:ref:`Jump to Getting Started ` + +Contents +-------- +:doc:`cqlengine/upgrade_guide` + For migrating projects from legacy cqlengine, to the integrated product + +:doc:`cqlengine/models` + Examples defining models, and mapping them to tables + +:doc:`cqlengine/queryset` + Overview of query sets and filtering + +:doc:`cqlengine/batches` + Working with batch mutations + +:doc:`cqlengine/connections` + Working with multiple sessions + +:ref:`API Documentation ` + Index of API documentation + +:doc:`cqlengine/third_party` + High-level examples in Celery and uWSGI + +:doc:`cqlengine/faq` + +.. toctree:: + :hidden: + + cqlengine/upgrade_guide + cqlengine/models + cqlengine/queryset + cqlengine/batches + cqlengine/connections + cqlengine/third_party + cqlengine/faq + +.. _getting-started: + +Getting Started +--------------- + +.. code-block:: python + + import uuid + from cassandra.cqlengine import columns + from cassandra.cqlengine import connection + from datetime import datetime + from cassandra.cqlengine.management import sync_table + from cassandra.cqlengine.models import Model + + #first, define a model + class ExampleModel(Model): + example_id = columns.UUID(primary_key=True, default=uuid.uuid4) + example_type = columns.Integer(index=True) + created_at = columns.DateTime() + description = columns.Text(required=False) + + #next, setup the connection to your cassandra server(s)... + # see http://datastax.github.io/python-driver/api/cassandra/cluster.html for options + # the list of hosts will be passed to create a Cluster() instance + connection.setup(['127.0.0.1'], "cqlengine", protocol_version=3) + + #...and create your CQL table + >>> sync_table(ExampleModel) + + #now we can create some rows: + >>> em1 = ExampleModel.create(example_type=0, description="example1", created_at=datetime.now()) + >>> em2 = ExampleModel.create(example_type=0, description="example2", created_at=datetime.now()) + >>> em3 = ExampleModel.create(example_type=0, description="example3", created_at=datetime.now()) + >>> em4 = ExampleModel.create(example_type=0, description="example4", created_at=datetime.now()) + >>> em5 = ExampleModel.create(example_type=1, description="example5", created_at=datetime.now()) + >>> em6 = ExampleModel.create(example_type=1, description="example6", created_at=datetime.now()) + >>> em7 = ExampleModel.create(example_type=1, description="example7", created_at=datetime.now()) + >>> em8 = ExampleModel.create(example_type=1, description="example8", created_at=datetime.now()) + + #and now we can run some queries against our table + >>> ExampleModel.objects.count() + 8 + >>> q = ExampleModel.objects(example_type=1) + >>> q.count() + 4 + >>> for instance in q: + >>> print instance.description + example5 + example6 + example7 + example8 + + #here we are applying additional filtering to an existing query + #query objects are immutable, so calling filter returns a new + #query object + >>> q2 = q.filter(example_id=em5.example_id) + + >>> q2.count() + 1 + >>> for instance in q2: + >>> print instance.description + example5 diff --git a/3.22.3-scylla/_sources/performance.rst.txt b/3.22.3-scylla/_sources/performance.rst.txt new file mode 100644 index 0000000000..f7a3f49e0f --- /dev/null +++ b/3.22.3-scylla/_sources/performance.rst.txt @@ -0,0 +1,45 @@ +Performance Notes +================= +The Python driver for Cassandra offers several methods for executing queries. +You can synchronously block for queries to complete using +:meth:`.Session.execute()`, you can obtain asynchronous request futures through +:meth:`.Session.execute_async()`, and you can attach a callback to the future +with :meth:`.ResponseFuture.add_callback()`. + +Examples of multiple request patterns can be found in the benchmark scripts included in the driver project. + +The choice of execution pattern will depend on the application context. For applications dealing with multiple +requests in a given context, the recommended pattern is to use concurrent asynchronous +requests with callbacks. For many use cases, you don't need to implement this pattern yourself. +:meth:`cassandra.concurrent.execute_concurrent` and :meth:`cassandra.concurrent.execute_concurrent_with_args` +provide this pattern with a synchronous API and tunable concurrency. + +Due to the GIL and limited concurrency, the driver can become CPU-bound pretty quickly. The sections below +discuss further runtime and design considerations for mitigating this limitation. + +PyPy +---- +`PyPy `_ is an alternative Python runtime which uses a JIT compiler to +reduce CPU consumption. This leads to a huge improvement in the driver performance, +more than doubling throughput for many workloads. + +Cython Extensions +----------------- +`Cython `_ is an optimizing compiler and language that can be used to compile the core files and +optional extensions for the driver. Cython is not a strict dependency, but the extensions will be built by default. + +See :doc:`installation` for details on controlling this build. + +multiprocessing +--------------- +All of the patterns discussed above may be used over multiple processes using the +`multiprocessing `_ +module. Multiple processes will scale better than multiple threads, so if high throughput is your goal, +consider this option. + +Be sure to **never share any** :class:`~.Cluster`, :class:`~.Session`, +**or** :class:`~.ResponseFuture` **objects across multiple processes**. These +objects should all be created after forking the process, not before. + +For further discussion and simple examples using the driver with ``multiprocessing``, +see `this blog post `_. diff --git a/3.22.3-scylla/_sources/query_paging.rst.txt b/3.22.3-scylla/_sources/query_paging.rst.txt new file mode 100644 index 0000000000..2c4a4995ca --- /dev/null +++ b/3.22.3-scylla/_sources/query_paging.rst.txt @@ -0,0 +1,95 @@ +.. _query-paging: + +Paging Large Queries +==================== +Cassandra 2.0+ offers support for automatic query paging. Starting with +version 2.0 of the driver, if :attr:`~.Cluster.protocol_version` is greater than +:const:`2` (it is by default), queries returning large result sets will be +automatically paged. + +Controlling the Page Size +------------------------- +By default, :attr:`.Session.default_fetch_size` controls how many rows will +be fetched per page. This can be overridden per-query by setting +:attr:`~.fetch_size` on a :class:`~.Statement`. By default, each page +will contain at most 5000 rows. + +Handling Paged Results +---------------------- +Whenever the number of result rows for are query exceed the page size, an +instance of :class:`~.PagedResult` will be returned instead of a normal +list. This class implements the iterator interface, so you can treat +it like a normal iterator over rows:: + + from cassandra.query import SimpleStatement + query = "SELECT * FROM users" # users contains 100 rows + statement = SimpleStatement(query, fetch_size=10) + for user_row in session.execute(statement): + process_user(user_row) + +Whenever there are no more rows in the current page, the next page will +be fetched transparently. However, note that it *is* possible for +an :class:`Exception` to be raised while fetching the next page, just +like you might see on a normal call to ``session.execute()``. + +If you use :meth:`.Session.execute_async()` along with, +:meth:`.ResponseFuture.result()`, the first page will be fetched before +:meth:`~.ResponseFuture.result()` returns, but latter pages will be +transparently fetched synchronously while iterating the result. + +Handling Paged Results with Callbacks +------------------------------------- +If callbacks are attached to a query that returns a paged result, +the callback will be called once per page with a normal list of rows. + +Use :attr:`.ResponseFuture.has_more_pages` and +:meth:`.ResponseFuture.start_fetching_next_page()` to continue fetching +pages. For example:: + + class PagedResultHandler(object): + + def __init__(self, future): + self.error = None + self.finished_event = Event() + self.future = future + self.future.add_callbacks( + callback=self.handle_page, + errback=self.handle_err) + + def handle_page(self, rows): + for row in rows: + process_row(row) + + if self.future.has_more_pages: + self.future.start_fetching_next_page() + else: + self.finished_event.set() + + def handle_error(self, exc): + self.error = exc + self.finished_event.set() + + future = session.execute_async("SELECT * FROM users") + handler = PagedResultHandler(future) + handler.finished_event.wait() + if handler.error: + raise handler.error + +Resume Paged Results +-------------------- + +You can resume the pagination when executing a new query by using the :attr:`.ResultSet.paging_state`. This can be useful if you want to provide some stateless pagination capabilities to your application (ie. via http). For example:: + + from cassandra.query import SimpleStatement + query = "SELECT * FROM users" + statement = SimpleStatement(query, fetch_size=10) + results = session.execute(statement) + + # save the paging_state somewhere and return current results + web_session['paging_stage'] = results.paging_state + + + # resume the pagination sometime later... + statement = SimpleStatement(query, fetch_size=10) + ps = web_session['paging_state'] + results = session.execute(statement, paging_state=ps) diff --git a/3.22.3-scylla/_sources/scylla_cloud.rst.txt b/3.22.3-scylla/_sources/scylla_cloud.rst.txt new file mode 100644 index 0000000000..62aaf76433 --- /dev/null +++ b/3.22.3-scylla/_sources/scylla_cloud.rst.txt @@ -0,0 +1,5 @@ +Scylla Cloud +------------ + +To connect to a `Scylla Cloud `_ cluster, go to the Cluster Connect page, Python example. +For best performance, make sure to use the Scylla Driver. diff --git a/3.22.3-scylla/_sources/scylla_specific.rst.txt b/3.22.3-scylla/_sources/scylla_specific.rst.txt new file mode 100644 index 0000000000..966f87336b --- /dev/null +++ b/3.22.3-scylla/_sources/scylla_specific.rst.txt @@ -0,0 +1,84 @@ +Scylla Specific Features +======================== + +Shard Awareness +--------------- + +**scylla-driver** is shard aware and contains extensions that work with the TokenAwarePolicy supported by Scylla 2.3 and onwards. Using this policy, the driver can select a connection to a particular shard based on the shard's token. +As a result, latency is significantly reduced because there is no need to pass data between the shards. + +Details on the scylla cql protocol extensions +https://github.com/scylladb/scylla/blob/master/docs/protocol-extensions.md + +For using it you only need to enable ``TokenAwarePolicy`` on the ``Cluster`` + +.. code:: python + + from cassandra.cluster import Cluster + from cassandra.policies import TokenAwarePolicy, RoundRobinPolicy + + cluster = Cluster(load_balancing_policy=TokenAwarePolicy(RoundRobinPolicy())) + + +New Cluster Helpers +------------------- + +* ``cluster.is_shard_aware()`` + + New method available on ``Cluster`` allowing to check whether the remote cluster supports shard awareness (bool) + +.. code:: python + + from cassandra.cluster import Cluster + + cluster = Cluster() + session = cluster.connect() + + if cluster.is_shard_aware(): + print("connected to a scylla cluster") + +* ``cluster.shard_aware_stats()`` + + New method available on ``Cluster`` allowing to check the status of shard aware connections to all available hosts (dict) + +.. code:: python + + from cassandra.cluster import Cluster + + cluster = Cluster() + session = cluster.connect() + + stats = cluster.shard_aware_stats() + if all([v["shards_count"] == v["connected"] for v in stats.values()]): + print("successfully connected to all shards of all scylla nodes") + + +New Table Attributes +-------------------- + +* ``in_memory`` flag + + New flag available on ``TableMetadata.options`` to indicate that it is an `In Memory `_ table + +.. note:: in memory tables is a feature existing only in Scylla Enterprise + +.. code:: python + + from cassandra.cluster import Cluster + + cluster = Cluster() + session = cluster.connect() + session.execute(""" + CREATE KEYSPACE IF NOT EXISTS keyspace1 + WITH replication = {'class': 'SimpleStrategy', 'replication_factor': '1'}; + """) + + session.execute(""" + CREATE TABLE IF NOT EXISTS keyspace1.standard1 ( + key blob PRIMARY KEY, + "C0" blob + ) WITH in_memory=true AND compaction={'class': 'InMemoryCompactionStrategy'} + """) + + cluster.refresh_table_metadata("keyspace1", "standard1") + assert cluster.metadata.keyspaces["keyspace1"].tables["standard1"].options["in_memory"] == True diff --git a/3.22.3-scylla/_sources/security.rst.txt b/3.22.3-scylla/_sources/security.rst.txt new file mode 100644 index 0000000000..0276f6fc51 --- /dev/null +++ b/3.22.3-scylla/_sources/security.rst.txt @@ -0,0 +1,421 @@ +.. _security: + +Security +======== +The two main security components you will use with the +Python driver are Authentication and SSL. + +Authentication +-------------- +Versions 2.0 and higher of the driver support a SASL-based +authentication mechanism when :attr:`~.Cluster.protocol_version` +is set to 2 or higher. To use this authentication, set +:attr:`~.Cluster.auth_provider` to an instance of a subclass +of :class:`~cassandra.auth.AuthProvider`. When working +with Cassandra's ``PasswordAuthenticator``, you can use +the :class:`~cassandra.auth.PlainTextAuthProvider` class. + +For example, suppose Cassandra is setup with its default +'cassandra' user with a password of 'cassandra': + +.. code-block:: python + + from cassandra.cluster import Cluster + from cassandra.auth import PlainTextAuthProvider + + auth_provider = PlainTextAuthProvider(username='cassandra', password='cassandra') + cluster = Cluster(auth_provider=auth_provider, protocol_version=2) + + + +Custom Authenticators +^^^^^^^^^^^^^^^^^^^^^ +If you're using something other than Cassandra's ``PasswordAuthenticator``, +:class:`~.SaslAuthProvider` is provided for generic SASL authentication mechanisms, +utilizing the ``pure-sasl`` package. +If these do not suit your needs, you may need to create your own subclasses of +:class:`~.AuthProvider` and :class:`~.Authenticator`. You can use the Sasl classes +as example implementations. + +Protocol v1 Authentication +^^^^^^^^^^^^^^^^^^^^^^^^^^ +When working with Cassandra 1.2 (or a higher version with +:attr:`~.Cluster.protocol_version` set to ``1``), you will not pass in +an :class:`~.AuthProvider` instance. Instead, you should pass in a +function that takes one argument, the IP address of a host, and returns +a dict of credentials with a ``username`` and ``password`` key: + +.. code-block:: python + + from cassandra.cluster import Cluster + + def get_credentials(host_address): + return {'username': 'joe', 'password': '1234'} + + cluster = Cluster(auth_provider=get_credentials, protocol_version=1) + +SSL +--- +SSL should be used when client encryption is enabled in Cassandra. + +To give you as much control as possible over your SSL configuration, our SSL +API takes a user-created `SSLContext` instance from the Python standard library. +These docs will include some examples for how to achieve common configurations, +but the `ssl.SSLContext `_ documentation +gives a more complete description of what is possible. + +To enable SSL with version 3.17.0 and higher, you will need to set :attr:`.Cluster.ssl_context` to a +``ssl.SSLContext`` instance to enable SSL. Optionally, you can also set :attr:`.Cluster.ssl_options` +to a dict of options. These will be passed as kwargs to ``ssl.SSLContext.wrap_socket()`` +when new sockets are created. + +If you create your SSLContext using `ssl.create_default_context `_, +be aware that SSLContext.check_hostname is set to True by default, so the hostname validation will be done +by Python and not the driver. For this reason, we need to set the server_hostname at best effort, which is the +resolved ip address. If this validation needs to be done against the FQDN, consider enabling it using the ssl_options +as described in the following examples or implement your own :class:`~.connection.EndPoint` and +:class:`~.connection.EndPointFactory`. + + +The following examples assume you have generated your Cassandra certificate and +keystore files with these intructions: + +* `Setup SSL Cert `_ + +It might be also useful to learn about the different levels of identity verification to understand the examples: + +* `Using SSL in DSE drivers `_ + +SSL with Twisted or Eventlet +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Twisted and Eventlet both use an alternative SSL implementation called pyOpenSSL, so if your `Cluster`'s connection class is +:class:`~cassandra.io.twistedreactor.TwistedConnection` or :class:`~cassandra.io.eventletreactor.EventletConnection`, you must pass a +`pyOpenSSL context `_ instead. +An example is provided in these docs, and more details can be found in the +`documentation `_. +pyOpenSSL is not installed by the driver and must be installed separately. + +SSL Configuration Examples +^^^^^^^^^^^^^^^^^^^^^^^^^^ +Here, we'll describe the server and driver configuration necessary to set up SSL to meet various goals, such as the client verifying the server and the server verifying the client. We'll also include Python code demonstrating how to use servers and drivers configured in these ways. + +.. _ssl-no-identify-verification: + +No identity verification +++++++++++++++++++++++++ + +No identity verification at all. Note that this is not recommended for for production deployments. + +The Cassandra configuration:: + + client_encryption_options: + enabled: true + keystore: /path/to/127.0.0.1.keystore + keystore_password: myStorePass + require_client_auth: false + +The driver configuration: + +.. code-block:: python + + from cassandra.cluster import Cluster, Session + from ssl import SSLContext, PROTOCOL_TLSv1 + + ssl_context = SSLContext(PROTOCOL_TLSv1) + + cluster = Cluster(['127.0.0.1'], ssl_context=ssl_context) + session = cluster.connect() + +.. _ssl-client-verifies-server: + +Client verifies server +++++++++++++++++++++++ + +Ensure the python driver verifies the identity of the server. + +The Cassandra configuration:: + + client_encryption_options: + enabled: true + keystore: /path/to/127.0.0.1.keystore + keystore_password: myStorePass + require_client_auth: false + +For the driver configuration, it's very important to set `ssl_context.verify_mode` +to `CERT_REQUIRED`. Otherwise, the loaded verify certificate will have no effect: + +.. code-block:: python + + from cassandra.cluster import Cluster, Session + from ssl import SSLContext, PROTOCOL_TLSv1, CERT_REQUIRED + + ssl_context = SSLContext(PROTOCOL_TLSv1) + ssl_context.load_verify_locations('/path/to/rootca.crt') + ssl_context.verify_mode = CERT_REQUIRED + + cluster = Cluster(['127.0.0.1'], ssl_context=ssl_context) + session = cluster.connect() + +Additionally, you can also force the driver to verify the `hostname` of the server by passing additional options to `ssl_context.wrap_socket` via the `ssl_options` kwarg: + +.. code-block:: python + + from cassandra.cluster import Cluster, Session + from ssl import SSLContext, PROTOCOL_TLSv1, CERT_REQUIRED + + ssl_context = SSLContext(PROTOCOL_TLSv1) + ssl_context.load_verify_locations('/path/to/rootca.crt') + ssl_context.verify_mode = CERT_REQUIRED + ssl_context.check_hostname = True + ssl_options = {'server_hostname': '127.0.0.1'} + + cluster = Cluster(['127.0.0.1'], ssl_context=ssl_context, ssl_options=ssl_options) + session = cluster.connect() + +.. _ssl-server-verifies-client: + +Server verifies client +++++++++++++++++++++++ + +If Cassandra is configured to verify clients (``require_client_auth``), you need to generate +SSL key and certificate files. + +The cassandra configuration:: + + client_encryption_options: + enabled: true + keystore: /path/to/127.0.0.1.keystore + keystore_password: myStorePass + require_client_auth: true + truststore: /path/to/dse-truststore.jks + truststore_password: myStorePass + +The Python ``ssl`` APIs require the certificate in PEM format. First, create a certificate +conf file: + +.. code-block:: bash + + cat > gen_client_cert.conf <`__ +for more details about ``SSLContext`` configuration. + +**Server verifies client and client verifies server using Twisted and pyOpenSSL** + +.. code-block:: python + + from OpenSSL import SSL, crypto + from cassandra.cluster import Cluster + from cassandra.io.twistedreactor import TwistedConnection + + ssl_context = SSL.Context(SSL.TLSv1_METHOD) + ssl_context.set_verify(SSL.VERIFY_PEER, callback=lambda _1, _2, _3, _4, ok: ok) + ssl_context.use_certificate_file('/path/to/client.crt_signed') + ssl_context.use_privatekey_file('/path/to/client.key') + ssl_context.load_verify_locations('/path/to/rootca.crt') + + cluster = Cluster( + contact_points=['127.0.0.1'], + connection_class=TwistedConnection, + ssl_context=ssl_context, + ssl_options={'check_hostname': True} + ) + session = cluster.connect() + + +Connecting using Eventlet would look similar except instead of importing and using ``TwistedConnection``, you would +import and use ``EventletConnection``, including the appropriate monkey-patching. + +Versions 3.16.0 and lower +^^^^^^^^^^^^^^^^^^^^^^^^^ + +To enable SSL you will need to set :attr:`.Cluster.ssl_options` to a +dict of options. These will be passed as kwargs to ``ssl.wrap_socket()`` +when new sockets are created. Note that this use of ssl_options will be +deprecated in the next major release. + +By default, a ``ca_certs`` value should be supplied (the value should be +a string pointing to the location of the CA certs file), and you probably +want to specify ``ssl_version`` as ``ssl.PROTOCOL_TLSv1`` to match +Cassandra's default protocol. + +For example: + +.. code-block:: python + + from cassandra.cluster import Cluster + from ssl import PROTOCOL_TLSv1, CERT_REQUIRED + + ssl_opts = { + 'ca_certs': '/path/to/my/ca.certs', + 'ssl_version': PROTOCOL_TLSv1, + 'cert_reqs': CERT_REQUIRED # Certificates are required and validated + } + cluster = Cluster(ssl_options=ssl_opts) + +This is only an example to show how to pass the ssl parameters. Consider reading +the `python ssl documentation `__ for +your configuration. For further reading, Andrew Mussey has published a thorough guide on +`Using SSL with the DataStax Python driver `_. + +SSL with Twisted +++++++++++++++++ + +In case the twisted event loop is used pyOpenSSL must be installed or an exception will be risen. Also +to set the ``ssl_version`` and ``cert_reqs`` in ``ssl_opts`` the appropriate constants from pyOpenSSL are expected. + +DSE Authentication +------------------ +When authenticating against DSE, the Cassandra driver provides two auth providers that work both with legacy kerberos and Cassandra authenticators, +as well as the new DSE Unified Authentication. This allows client to configure this auth provider independently, +and in advance of any server upgrade. These auth providers are configured in the same way as any previous implementation:: + + from cassandra.auth import DSEGSSAPIAuthProvider + auth_provider = DSEGSSAPIAuthProvider(service='dse', qops=["auth"]) + cluster = Cluster(auth_provider=auth_provider) + session = cluster.connect() + +Implementations are :attr:`.DSEPlainTextAuthProvider`, :class:`.DSEGSSAPIAuthProvider` and :class:`.SaslAuthProvider`. + +DSE Unified Authentication +^^^^^^^^^^^^^^^^^^^^^^^^^^ + +With DSE (>=5.1), unified Authentication allows you to: + +* Proxy Login: Authenticate using a fixed set of authentication credentials but allow authorization of resources based another user id. +* Proxy Execute: Authenticate using a fixed set of authentication credentials but execute requests based on another user id. + +Proxy Login ++++++++++++ + +Proxy login allows you to authenticate with a user but act as another one. You need to ensure the authenticated user has the permission to use the authorization of resources of the other user. ie. this example will allow the `server` user to authenticate as usual but use the authorization of `user1`: + +.. code-block:: text + + GRANT PROXY.LOGIN on role user1 to server + +then you can do the proxy authentication.... + +.. code-block:: python + + from cassandra.cluster import Cluster + from cassandra.auth import SaslAuthProvider + + sasl_kwargs = { + "service": 'dse', + "mechanism":"PLAIN", + "username": 'server', + 'password': 'server', + 'authorization_id': 'user1' + } + + auth_provider = SaslAuthProvider(**sasl_kwargs) + c = Cluster(auth_provider=auth_provider) + s = c.connect() + s.execute(...) # all requests will be executed as 'user1' + +If you are using kerberos, you can use directly :class:`.DSEGSSAPIAuthProvider` and pass the authorization_id, like this: + +.. code-block:: python + + from cassandra.cluster import Cluster + from cassandra.auth import DSEGSSAPIAuthProvider + + # Ensure the kerberos ticket of the server user is set with the kinit utility. + auth_provider = DSEGSSAPIAuthProvider(service='dse', qops=["auth"], principal="server@DATASTAX.COM", + authorization_id='user1@DATASTAX.COM') + c = Cluster(auth_provider=auth_provider) + s = c.connect() + s.execute(...) # all requests will be executed as 'user1' + + +Proxy Execute ++++++++++++++ + +Proxy execute allows you to execute requests as another user than the authenticated one. You need to ensure the authenticated user has the permission to use the authorization of resources of the specified user. ie. this example will allow the `server` user to execute requests as `user1`: + +.. code-block:: text + + GRANT PROXY.EXECUTE on role user1 to server + +then you can do a proxy execute... + +.. code-block:: python + + from cassandra.cluster import Cluster + from cassandra.auth import DSEPlainTextAuthProvider, + + auth_provider = DSEPlainTextAuthProvider('server', 'server') + + c = Cluster(auth_provider=auth_provider) + s = c.connect() + s.execute('select * from k.t;', execute_as='user1') # the request will be executed as 'user1' + +Please see the `official documentation `_ for more details on the feature and configuration process. diff --git a/3.22.3-scylla/_sources/upgrading.rst.txt b/3.22.3-scylla/_sources/upgrading.rst.txt new file mode 100644 index 0000000000..9559fa3579 --- /dev/null +++ b/3.22.3-scylla/_sources/upgrading.rst.txt @@ -0,0 +1,388 @@ +Upgrading +========= + +.. toctree:: + :maxdepth: 1 + +Upgrading from dse-driver +------------------------- + +Since 3.21.0, scylla-driver fully supports DataStax products. dse-driver and +dse-graph users should now migrate to scylla-driver to benefit from latest bug fixes +and new features. The upgrade to this new unified driver version is straightforward +with no major API changes. + +Installation +^^^^^^^^^^^^ + +Only the `scylla-driver` package should be installed. `dse-driver` and `dse-graph` +are not required anymore:: + + pip install scylla-driver + +If you need the Graph *Fluent* API (features provided by dse-graph):: + + pip install scylla-driver[graph] + +See :doc:`installation` for more details. + +Import from the cassandra module +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +There is no `dse` module, so you should import from the `cassandra` module. You +need to change only the first module of your import statements, not the submodules. + +.. code-block:: python + + from dse.cluster import Cluster, EXEC_PROFILE_GRAPH_DEFAULT + from dse.auth import PlainTextAuthProvider + from dse.policies import WhiteListRoundRobinPolicy + + # becomes + + from cassandra.cluster import Cluster, EXEC_PROFILE_GRAPH_DEFAULT + from cassandra.auth import PlainTextAuthProvider + from cassandra.policies import WhiteListRoundRobinPolicy + +Also note that the cassandra.hosts module doesn't exist in scylla-driver. This +module is named cassandra.pool. + +dse-graph +^^^^^^^^^ + +dse-graph features are now built into scylla-driver. The only change you need +to do is your import statements: + +.. code-block:: python + + from dse_graph import .. + from dse_graph.query import .. + + # becomes + + from cassandra.datastax.graph.fluent import .. + from cassandra.datastax.graph.fluent.query import .. + +See :mod:`~.datastax.graph.fluent`. + +Session.execute and Session.execute_async API +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Although it is not common to use this API with positional arguments, it is +important to be aware that the `host` and `execute_as` parameters have had +their positional order swapped. This is only because `execute_as` was added +in dse-driver before `host`. + +See :meth:`.Session.execute`. + +Deprecations +^^^^^^^^^^^^ + +These changes are optional, but recommended: + +* Importing from `cassandra.graph` is deprecated. Consider importing from `cassandra.datastax.graph`. +* Use :class:`~.policies.DefaultLoadBalancingPolicy` instead of DSELoadBalancingPolicy. + +Upgrading to 3.0 +---------------- +Version 3.0 of the DataStax Python driver for Apache Cassandra +adds support for Cassandra 3.0 while maintaining support for +previously supported versions. In addition to substantial internal rework, +there are several updates to the API that integrators will need +to consider: + +Default consistency is now ``LOCAL_ONE`` +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Previous value was ``ONE``. The new value is introduced to mesh with the default +DC-aware load balancing policy and to match other drivers. + +Execution API Updates +^^^^^^^^^^^^^^^^^^^^^ +Result return normalization +~~~~~~~~~~~~~~~~~~~~~~~~~~~ +`PYTHON-368 `_ + +Previously results would be returned as a ``list`` of rows for result rows +up to ``fetch_size``, and ``PagedResult`` afterward. This could break +application code that assumed one type and got another. + +Now, all results are returned as an iterable :class:`~.ResultSet`. + +The preferred way to consume results of unknown size is to iterate through +them, letting automatic paging occur as they are consumed. + +.. code-block:: python + + results = session.execute("SELECT * FROM system.local") + for row in results: + process(row) + +If the expected size of the results is known, it is still possible to +materialize a list using the iterator: + +.. code-block:: python + + results = session.execute("SELECT * FROM system.local") + row_list = list(results) + +For backward compatibility, :class:`~.ResultSet` supports indexing. When +accessed at an index, a `~.ResultSet` object will materialize all its pages: + +.. code-block:: python + + results = session.execute("SELECT * FROM system.local") + first_result = results[0] # materializes results, fetching all pages + +This can send requests and load (possibly large) results into memory, so +`~.ResultSet` will log a warning on implicit materialization. + +Trace information is not attached to executed Statements +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +`PYTHON-318 `_ + +Previously trace data was attached to Statements if tracing was enabled. This +could lead to confusion if the same statement was used for multiple executions. + +Now, trace data is associated with the ``ResponseFuture`` and ``ResultSet`` +returned for each query: + +:meth:`.ResponseFuture.get_query_trace()` + +:meth:`.ResponseFuture.get_all_query_traces()` + +:meth:`.ResultSet.get_query_trace()` + +:meth:`.ResultSet.get_all_query_traces()` + +Binding named parameters now ignores extra names +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +`PYTHON-178 `_ + +Previously, :meth:`.BoundStatement.bind()` would raise if a mapping +was passed with extra names not found in the prepared statement. + +Behavior in 3.0+ is to ignore extra names. + +blist removed as soft dependency +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +`PYTHON-385 `_ + +Previously the driver had a soft dependency on ``blist sortedset``, using +that where available and using an internal fallback where possible. + +Now, the driver never chooses the ``blist`` variant, instead returning the +internal :class:`.util.SortedSet` for all ``set`` results. The class implements +all standard set operations, so no integration code should need to change unless +it explicitly checks for ``sortedset`` type. + +Metadata API Updates +^^^^^^^^^^^^^^^^^^^^ +`PYTHON-276 `_, `PYTHON-408 `_, `PYTHON-400 `_, `PYTHON-422 `_ + +Cassandra 3.0 brought a substantial overhaul to the internal schema metadata representation. +This version of the driver supports that metadata in addition to the legacy version. Doing so +also brought some changes to the metadata model. + +The present API is documented: :any:`cassandra.metadata`. Changes highlighted below: + +* All types are now exposed as CQL types instead of types derived from the internal server implementation +* Some metadata attributes have changed names to match current nomenclature (for example, :attr:`.Index.kind` in place of ``Index.type``). +* Some metadata attributes removed + + * ``TableMetadata.keyspace`` reference replaced with :attr:`.TableMetadata.keyspace_name` + * ``ColumnMetadata.index`` is removed table- and keyspace-level mappings are still maintained + +Several deprecated features are removed +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +`PYTHON-292 `_ + +* ``ResponseFuture.result`` timeout parameter is removed, use ``Session.execute`` timeout instead (`031ebb0 `_) +* ``Cluster.refresh_schema`` removed, use ``Cluster.refresh_*_metadata`` instead (`419fcdf `_) +* ``Cluster.submit_schema_refresh`` removed (`574266d `_) +* ``cqltypes`` time/date functions removed, use ``util`` entry points instead (`bb984ee `_) +* ``decoder`` module removed (`e16a073 `_) +* ``TableMetadata.keyspace`` attribute replaced with ``keyspace_name`` (`cc94073 `_) +* ``cqlengine.columns.TimeUUID.from_datetime`` removed, use ``util`` variant instead (`96489cc `_) +* ``cqlengine.columns.Float(double_precision)`` parameter removed, use ``columns.Double`` instead (`a2d3a98 `_) +* ``cqlengine`` keyspace management functions are removed in favor of the strategy-specific entry points (`4bd5909 `_) +* ``cqlengine.Model.__polymorphic_*__`` attributes removed, use ``__discriminator*`` attributes instead (`9d98c8e `_) +* ``cqlengine.statements`` will no longer warn about list list prepend behavior (`79efe97 `_) + + +Upgrading to 2.1 from 2.0 +------------------------- +Version 2.1 of the DataStax Python driver for Apache Cassandra +adds support for Cassandra 2.1 and version 3 of the native protocol. + +Cassandra 1.2, 2.0, and 2.1 are all supported. However, 1.2 only +supports protocol version 1, and 2.0 only supports versions 1 and +2, so some features may not be available. + +Using the v3 Native Protocol +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +By default, the driver will attempt to use version 2 of the +native protocol. To use version 3, you must explicitly +set the :attr:`~.Cluster.protocol_version`: + +.. code-block:: python + + from cassandra.cluster import Cluster + + cluster = Cluster(protocol_version=3) + +Note that protocol version 3 is only supported by Cassandra 2.1+. + +In future releases, the driver may default to using protocol version +3. + +Working with User-Defined Types +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Cassandra 2.1 introduced the ability to define new types:: + + USE KEYSPACE mykeyspace; + + CREATE TYPE address (street text, city text, zip int); + +The driver generally expects you to use instances of a specific +class to represent column values of this type. You can let the +driver know what class to use with :meth:`.Cluster.register_user_type`: + +.. code-block:: python + + cluster = Cluster() + + class Address(object): + + def __init__(self, street, city, zipcode): + self.street = street + self.city = text + self.zipcode = zipcode + + cluster.register_user_type('mykeyspace', 'address', Address) + +When inserting data for ``address`` columns, you should pass in +instances of ``Address``. When querying data, ``address`` column +values will be instances of ``Address``. + +If no class is registered for a user-defined type, query results +will use a ``namedtuple`` class and data may only be inserted +though prepared statements. + +See :ref:`udts` for more details. + +Customizing Encoders for Non-prepared Statements +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Starting with version 2.1 of the driver, it is possible to customize +how Python types are converted to CQL literals when working with +non-prepared statements. This is done on a per-:class:`~.Session` +basis through :attr:`.Session.encoder`: + +.. code-block:: python + + cluster = Cluster() + session = cluster.connect() + session.encoder.mapping[tuple] = session.encoder.cql_encode_tuple + +See :ref:`type-conversions` for the table of default CQL literal conversions. + +Using Client-Side Protocol-Level Timestamps +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +With version 3 of the native protocol, timestamps may be supplied by the +client at the protocol level. (Normally, if they are not specified within +the CQL query itself, a timestamp is generated server-side.) + +When :attr:`~.Cluster.protocol_version` is set to 3 or higher, the driver +will automatically use client-side timestamps with microsecond precision +unless :attr:`.Session.use_client_timestamp` is changed to :const:`False`. +If a timestamp is specified within the CQL query, it will override the +timestamp generated by the driver. + +Upgrading to 2.0 from 1.x +------------------------- +Version 2.0 of the DataStax Python driver for Apache Cassandra +includes some notable improvements over version 1.x. This version +of the driver supports Cassandra 1.2, 2.0, and 2.1. However, not +all features may be used with Cassandra 1.2, and some new features +in 2.1 are not yet supported. + +Using the v2 Native Protocol +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +By default, the driver will attempt to use version 2 of Cassandra's +native protocol. You can explicitly set the protocol version to +2, though: + +.. code-block:: python + + from cassandra.cluster import Cluster + + cluster = Cluster(protocol_version=2) + +When working with Cassandra 1.2, you will need to +explicitly set the :attr:`~.Cluster.protocol_version` to 1: + +.. code-block:: python + + from cassandra.cluster import Cluster + + cluster = Cluster(protocol_version=1) + +Automatic Query Paging +^^^^^^^^^^^^^^^^^^^^^^ +Version 2 of the native protocol adds support for automatic query +paging, which can make dealing with large result sets much simpler. + +See :ref:`query-paging` for full details. + +Protocol-Level Batch Statements +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +With version 1 of the native protocol, batching of statements required +using a `BATCH cql query `_. +With version 2 of the native protocol, you can now batch statements at +the protocol level. This allows you to use many different prepared +statements within a single batch. + +See :class:`~.query.BatchStatement` for details and usage examples. + +SASL-based Authentication +^^^^^^^^^^^^^^^^^^^^^^^^^ +Also new in version 2 of the native protocol is SASL-based authentication. +See the section on :ref:`security` for details and examples. + +Lightweight Transactions +^^^^^^^^^^^^^^^^^^^^^^^^ +`Lightweight transactions `_ are another new feature. To use lightweight transactions, add ``IF`` clauses +to your CQL queries and set the :attr:`~.Statement.serial_consistency_level` +on your statements. + +Calling Cluster.shutdown() +^^^^^^^^^^^^^^^^^^^^^^^^^^ +In order to fix some issues around garbage collection and unclean interpreter +shutdowns, version 2.0 of the driver requires you to call :meth:`.Cluster.shutdown()` +on your :class:`~.Cluster` objects when you are through with them. +This helps to guarantee a clean shutdown. + +Deprecations +^^^^^^^^^^^^ +The following functions have moved from ``cassandra.decoder`` to ``cassandra.query``. +The original functions have been left in place with a :exc:`DeprecationWarning` for +now: + +* :attr:`cassandra.decoder.tuple_factory` has moved to + :attr:`cassandra.query.tuple_factory` +* :attr:`cassandra.decoder.named_tuple_factory` has moved to + :attr:`cassandra.query.named_tuple_factory` +* :attr:`cassandra.decoder.dict_factory` has moved to + :attr:`cassandra.query.dict_factory` +* :attr:`cassandra.decoder.ordered_dict_factory` has moved to + :attr:`cassandra.query.ordered_dict_factory` + +Dependency Changes +^^^^^^^^^^^^^^^^^^ +The following dependencies have officially been made optional: + +* ``scales`` +* ``blist`` + +And one new dependency has been added (to enable Python 3 support): + +* ``six`` diff --git a/3.22.3-scylla/_sources/user_defined_types.rst.txt b/3.22.3-scylla/_sources/user_defined_types.rst.txt new file mode 100644 index 0000000000..32c03e37e8 --- /dev/null +++ b/3.22.3-scylla/_sources/user_defined_types.rst.txt @@ -0,0 +1,118 @@ +.. _udts: + +User Defined Types +================== +Cassandra 2.1 introduced user-defined types (UDTs). You can create a +new type through ``CREATE TYPE`` statements in CQL:: + + CREATE TYPE address (street text, zip int); + +Version 2.1 of the Python driver adds support for user-defined types. + +Registering a UDT +----------------- +You can tell the Python driver to return columns of a specific UDT as +instances of a class or a dict by registering them with your :class:`~.Cluster` +instance through :meth:`.Cluster.register_user_type`: + + +Map a Class to a UDT +++++++++++++++++++++ + +.. code-block:: python + + cluster = Cluster(protocol_version=3) + session = cluster.connect() + session.set_keyspace('mykeyspace') + session.execute("CREATE TYPE address (street text, zipcode int)") + session.execute("CREATE TABLE users (id int PRIMARY KEY, location frozen
)") + + # create a class to map to the "address" UDT + class Address(object): + + def __init__(self, street, zipcode): + self.street = street + self.zipcode = zipcode + + cluster.register_user_type('mykeyspace', 'address', Address) + + # insert a row using an instance of Address + session.execute("INSERT INTO users (id, location) VALUES (%s, %s)", + (0, Address("123 Main St.", 78723))) + + # results will include Address instances + results = session.execute("SELECT * FROM users") + row = results[0] + print(row.id, row.location.street, row.location.zipcode) + +Map a dict to a UDT ++++++++++++++++++++ + +.. code-block:: python + + cluster = Cluster(protocol_version=3) + session = cluster.connect() + session.set_keyspace('mykeyspace') + session.execute("CREATE TYPE address (street text, zipcode int)") + session.execute("CREATE TABLE users (id int PRIMARY KEY, location frozen
)") + + cluster.register_user_type('mykeyspace', 'address', dict) + + # insert a row using a prepared statement and a tuple + insert_statement = session.prepare("INSERT INTO mykeyspace.users (id, location) VALUES (?, ?)") + session.execute(insert_statement, [0, ("123 Main St.", 78723)]) + + # results will include dict instances + results = session.execute("SELECT * FROM users") + row = results[0] + print(row.id, row.location['street'], row.location['zipcode']) + +Using UDTs Without Registering Them +----------------------------------- +Although it is recommended to register your types with +:meth:`.Cluster.register_user_type`, the driver gives you some options +for working with unregistered UDTS. + +When you use prepared statements, the driver knows what data types to +expect for each placeholder. This allows you to pass any object you +want for a UDT, as long as it has attributes that match the field names +for the UDT: + +.. code-block:: python + + cluster = Cluster(protocol_version=3) + session = cluster.connect() + session.set_keyspace('mykeyspace') + session.execute("CREATE TYPE address (street text, zipcode int)") + session.execute("CREATE TABLE users (id int PRIMARY KEY, location frozen
)") + + class Foo(object): + + def __init__(self, street, zipcode, otherstuff): + self.street = street + self.zipcode = zipcode + self.otherstuff = otherstuff + + insert_statement = session.prepare("INSERT INTO users (id, location) VALUES (?, ?)") + + # since we're using a prepared statement, we don't *have* to register + # a class to map to the UDT to insert data. The object just needs to have + # "street" and "zipcode" attributes (which Foo does): + session.execute(insert_statement, [0, Foo("123 Main St.", 78723, "some other stuff")]) + + # when we query data, UDT columns that don't have a class registered + # will be returned as namedtuples: + results = session.execute("SELECT * FROM users") + first_row = results[0] + address = first_row.location + print(address) # prints "Address(street='123 Main St.', zipcode=78723)" + street = address.street + zipcode = address.street + +As shown in the code example, inserting data for UDT columns without registering +a class works fine for prepared statements. However, **you must register a +class to insert UDT columns with unprepared statements**.\* You can still query +UDT columns without registered classes using unprepared statements, they will +simply return ``namedtuple`` instances (just like prepared statements do). + +\* this applies to *parameterized* unprepared statements, in which the driver will be formatting parameters -- not statements with interpolated UDT literals. diff --git a/3.22.3-scylla/_static/basic.css b/3.22.3-scylla/_static/basic.css new file mode 100644 index 0000000000..603f6a8798 --- /dev/null +++ b/3.22.3-scylla/_static/basic.css @@ -0,0 +1,905 @@ +/* + * basic.css + * ~~~~~~~~~ + * + * Sphinx stylesheet -- basic theme. + * + * :copyright: Copyright 2007-2021 by the Sphinx team, see AUTHORS. + * :license: BSD, see LICENSE for details. + * + */ + +/* -- main layout ----------------------------------------------------------- */ + +div.clearer { + clear: both; +} + +div.section::after { + display: block; + content: ''; + clear: left; +} + +/* -- relbar ---------------------------------------------------------------- */ + +div.related { + width: 100%; + font-size: 90%; +} + +div.related h3 { + display: none; +} + +div.related ul { + margin: 0; + padding: 0 0 0 10px; + list-style: none; +} + +div.related li { + display: inline; +} + +div.related li.right { + float: right; + margin-right: 5px; +} + +/* -- sidebar --------------------------------------------------------------- */ + +div.sphinxsidebarwrapper { + padding: 10px 5px 0 10px; +} + +div.sphinxsidebar { + float: left; + width: 230px; + margin-left: -100%; + font-size: 90%; + word-wrap: break-word; + overflow-wrap : break-word; +} + +div.sphinxsidebar ul { + list-style: none; +} + +div.sphinxsidebar ul ul, +div.sphinxsidebar ul.want-points { + margin-left: 20px; + list-style: square; +} + +div.sphinxsidebar ul ul { + margin-top: 0; + margin-bottom: 0; +} + +div.sphinxsidebar form { + margin-top: 10px; +} + +div.sphinxsidebar input { + border: 1px solid #98dbcc; + font-family: sans-serif; + font-size: 1em; +} + +div.sphinxsidebar #searchbox form.search { + overflow: hidden; +} + +div.sphinxsidebar #searchbox input[type="text"] { + float: left; + width: 80%; + padding: 0.25em; + box-sizing: border-box; +} + +div.sphinxsidebar #searchbox input[type="submit"] { + float: left; + width: 20%; + border-left: none; + padding: 0.25em; + box-sizing: border-box; +} + + +img { + border: 0; + max-width: 100%; +} + +/* -- search page ----------------------------------------------------------- */ + +ul.search { + margin: 10px 0 0 20px; + padding: 0; +} + +ul.search li { + padding: 5px 0 5px 20px; + background-image: url(file.png); + background-repeat: no-repeat; + background-position: 0 7px; +} + +ul.search li a { + font-weight: bold; +} + +ul.search li p.context { + color: #888; + margin: 2px 0 0 30px; + text-align: left; +} + +ul.keywordmatches li.goodmatch a { + font-weight: bold; +} + +/* -- index page ------------------------------------------------------------ */ + +table.contentstable { + width: 90%; + margin-left: auto; + margin-right: auto; +} + +table.contentstable p.biglink { + line-height: 150%; +} + +a.biglink { + font-size: 1.3em; +} + +span.linkdescr { + font-style: italic; + padding-top: 5px; + font-size: 90%; +} + +/* -- general index --------------------------------------------------------- */ + +table.indextable { + width: 100%; +} + +table.indextable td { + text-align: left; + vertical-align: top; +} + +table.indextable ul { + margin-top: 0; + margin-bottom: 0; + list-style-type: none; +} + +table.indextable > tbody > tr > td > ul { + padding-left: 0em; +} + +table.indextable tr.pcap { + height: 10px; +} + +table.indextable tr.cap { + margin-top: 10px; + background-color: #f2f2f2; +} + +img.toggler { + margin-right: 3px; + margin-top: 3px; + cursor: pointer; +} + +div.modindex-jumpbox { + border-top: 1px solid #ddd; + border-bottom: 1px solid #ddd; + margin: 1em 0 1em 0; + padding: 0.4em; +} + +div.genindex-jumpbox { + border-top: 1px solid #ddd; + border-bottom: 1px solid #ddd; + margin: 1em 0 1em 0; + padding: 0.4em; +} + +/* -- domain module index --------------------------------------------------- */ + +table.modindextable td { + padding: 2px; + border-collapse: collapse; +} + +/* -- general body styles --------------------------------------------------- */ + +div.body { + min-width: 450px; + max-width: 800px; +} + +div.body p, div.body dd, div.body li, div.body blockquote { + -moz-hyphens: auto; + -ms-hyphens: auto; + -webkit-hyphens: auto; + hyphens: auto; +} + +a.headerlink { + visibility: hidden; +} + +a.brackets:before, +span.brackets > a:before{ + content: "["; +} + +a.brackets:after, +span.brackets > a:after { + content: "]"; +} + +h1:hover > a.headerlink, +h2:hover > a.headerlink, +h3:hover > a.headerlink, +h4:hover > a.headerlink, +h5:hover > a.headerlink, +h6:hover > a.headerlink, +dt:hover > a.headerlink, +caption:hover > a.headerlink, +p.caption:hover > a.headerlink, +div.code-block-caption:hover > a.headerlink { + visibility: visible; +} + +div.body p.caption { + text-align: inherit; +} + +div.body td { + text-align: left; +} + +.first { + margin-top: 0 !important; +} + +p.rubric { + margin-top: 30px; + font-weight: bold; +} + +img.align-left, figure.align-left, .figure.align-left, object.align-left { + clear: left; + float: left; + margin-right: 1em; +} + +img.align-right, figure.align-right, .figure.align-right, object.align-right { + clear: right; + float: right; + margin-left: 1em; +} + +img.align-center, figure.align-center, .figure.align-center, object.align-center { + display: block; + margin-left: auto; + margin-right: auto; +} + +img.align-default, figure.align-default, .figure.align-default { + display: block; + margin-left: auto; + margin-right: auto; +} + +.align-left { + text-align: left; +} + +.align-center { + text-align: center; +} + +.align-default { + text-align: center; +} + +.align-right { + text-align: right; +} + +/* -- sidebars -------------------------------------------------------------- */ + +div.sidebar, +aside.sidebar { + margin: 0 0 0.5em 1em; + border: 1px solid #ddb; + padding: 7px; + background-color: #ffe; + width: 40%; + float: right; + clear: right; + overflow-x: auto; +} + +p.sidebar-title { + font-weight: bold; +} + +div.admonition, div.topic, blockquote { + clear: left; +} + +/* -- topics ---------------------------------------------------------------- */ + +div.topic { + border: 1px solid #ccc; + padding: 7px; + margin: 10px 0 10px 0; +} + +p.topic-title { + font-size: 1.1em; + font-weight: bold; + margin-top: 10px; +} + +/* -- admonitions ----------------------------------------------------------- */ + +div.admonition { + margin-top: 10px; + margin-bottom: 10px; + padding: 7px; +} + +div.admonition dt { + font-weight: bold; +} + +p.admonition-title { + margin: 0px 10px 5px 0px; + font-weight: bold; +} + +div.body p.centered { + text-align: center; + margin-top: 25px; +} + +/* -- content of sidebars/topics/admonitions -------------------------------- */ + +div.sidebar > :last-child, +aside.sidebar > :last-child, +div.topic > :last-child, +div.admonition > :last-child { + margin-bottom: 0; +} + +div.sidebar::after, +aside.sidebar::after, +div.topic::after, +div.admonition::after, +blockquote::after { + display: block; + content: ''; + clear: both; +} + +/* -- tables ---------------------------------------------------------------- */ + +table.docutils { + margin-top: 10px; + margin-bottom: 10px; + border: 0; + border-collapse: collapse; +} + +table.align-center { + margin-left: auto; + margin-right: auto; +} + +table.align-default { + margin-left: auto; + margin-right: auto; +} + +table caption span.caption-number { + font-style: italic; +} + +table caption span.caption-text { +} + +table.docutils td, table.docutils th { + padding: 1px 8px 1px 5px; + border-top: 0; + border-left: 0; + border-right: 0; + border-bottom: 1px solid #aaa; +} + +table.footnote td, table.footnote th { + border: 0 !important; +} + +th { + text-align: left; + padding-right: 5px; +} + +table.citation { + border-left: solid 1px gray; + margin-left: 1px; +} + +table.citation td { + border-bottom: none; +} + +th > :first-child, +td > :first-child { + margin-top: 0px; +} + +th > :last-child, +td > :last-child { + margin-bottom: 0px; +} + +/* -- figures --------------------------------------------------------------- */ + +div.figure, figure { + margin: 0.5em; + padding: 0.5em; +} + +div.figure p.caption, figcaption { + padding: 0.3em; +} + +div.figure p.caption span.caption-number, +figcaption span.caption-number { + font-style: italic; +} + +div.figure p.caption span.caption-text, +figcaption span.caption-text { +} + +/* -- field list styles ----------------------------------------------------- */ + +table.field-list td, table.field-list th { + border: 0 !important; +} + +.field-list ul { + margin: 0; + padding-left: 1em; +} + +.field-list p { + margin: 0; +} + +.field-name { + -moz-hyphens: manual; + -ms-hyphens: manual; + -webkit-hyphens: manual; + hyphens: manual; +} + +/* -- hlist styles ---------------------------------------------------------- */ + +table.hlist { + margin: 1em 0; +} + +table.hlist td { + vertical-align: top; +} + +/* -- object description styles --------------------------------------------- */ + +.sig { + font-family: 'Consolas', 'Menlo', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace; +} + +.sig-name, code.descname { + background-color: transparent; + font-weight: bold; +} + +.sig-name { + font-size: 1.1em; +} + +code.descname { + font-size: 1.2em; +} + +.sig-prename, code.descclassname { + background-color: transparent; +} + +.optional { + font-size: 1.3em; +} + +.sig-paren { + font-size: larger; +} + +.sig-param.n { + font-style: italic; +} + +/* C++ specific styling */ + +.sig-inline.c-texpr, +.sig-inline.cpp-texpr { + font-family: unset; +} + +.sig.c .k, .sig.c .kt, +.sig.cpp .k, .sig.cpp .kt { + color: #0033B3; +} + +.sig.c .m, +.sig.cpp .m { + color: #1750EB; +} + +.sig.c .s, .sig.c .sc, +.sig.cpp .s, .sig.cpp .sc { + color: #067D17; +} + + +/* -- other body styles ----------------------------------------------------- */ + +ol.arabic { + list-style: decimal; +} + +ol.loweralpha { + list-style: lower-alpha; +} + +ol.upperalpha { + list-style: upper-alpha; +} + +ol.lowerroman { + list-style: lower-roman; +} + +ol.upperroman { + list-style: upper-roman; +} + +:not(li) > ol > li:first-child > :first-child, +:not(li) > ul > li:first-child > :first-child { + margin-top: 0px; +} + +:not(li) > ol > li:last-child > :last-child, +:not(li) > ul > li:last-child > :last-child { + margin-bottom: 0px; +} + +ol.simple ol p, +ol.simple ul p, +ul.simple ol p, +ul.simple ul p { + margin-top: 0; +} + +ol.simple > li:not(:first-child) > p, +ul.simple > li:not(:first-child) > p { + margin-top: 0; +} + +ol.simple p, +ul.simple p { + margin-bottom: 0; +} + +dl.footnote > dt, +dl.citation > dt { + float: left; + margin-right: 0.5em; +} + +dl.footnote > dd, +dl.citation > dd { + margin-bottom: 0em; +} + +dl.footnote > dd:after, +dl.citation > dd:after { + content: ""; + clear: both; +} + +dl.field-list { + display: grid; + grid-template-columns: fit-content(30%) auto; +} + +dl.field-list > dt { + font-weight: bold; + word-break: break-word; + padding-left: 0.5em; + padding-right: 5px; +} + +dl.field-list > dt:after { + content: ":"; +} + +dl.field-list > dd { + padding-left: 0.5em; + margin-top: 0em; + margin-left: 0em; + margin-bottom: 0em; +} + +dl { + margin-bottom: 15px; +} + +dd > :first-child { + margin-top: 0px; +} + +dd ul, dd table { + margin-bottom: 10px; +} + +dd { + margin-top: 3px; + margin-bottom: 10px; + margin-left: 30px; +} + +dl > dd:last-child, +dl > dd:last-child > :last-child { + margin-bottom: 0; +} + +dt:target, span.highlighted { + background-color: #fbe54e; +} + +rect.highlighted { + fill: #fbe54e; +} + +dl.glossary dt { + font-weight: bold; + font-size: 1.1em; +} + +.versionmodified { + font-style: italic; +} + +.system-message { + background-color: #fda; + padding: 5px; + border: 3px solid red; +} + +.footnote:target { + background-color: #ffa; +} + +.line-block { + display: block; + margin-top: 1em; + margin-bottom: 1em; +} + +.line-block .line-block { + margin-top: 0; + margin-bottom: 0; + margin-left: 1.5em; +} + +.guilabel, .menuselection { + font-family: sans-serif; +} + +.accelerator { + text-decoration: underline; +} + +.classifier { + font-style: oblique; +} + +.classifier:before { + font-style: normal; + margin: 0 0.5em; + content: ":"; + display: inline-block; +} + +abbr, acronym { + border-bottom: dotted 1px; + cursor: help; +} + +/* -- code displays --------------------------------------------------------- */ + +pre { + overflow: auto; + overflow-y: hidden; /* fixes display issues on Chrome browsers */ +} + +pre, div[class*="highlight-"] { + clear: both; +} + +span.pre { + -moz-hyphens: none; + -ms-hyphens: none; + -webkit-hyphens: none; + hyphens: none; +} + +div[class*="highlight-"] { + margin: 1em 0; +} + +td.linenos pre { + border: 0; + background-color: transparent; + color: #aaa; +} + +table.highlighttable { + display: block; +} + +table.highlighttable tbody { + display: block; +} + +table.highlighttable tr { + display: flex; +} + +table.highlighttable td { + margin: 0; + padding: 0; +} + +table.highlighttable td.linenos { + padding-right: 0.5em; +} + +table.highlighttable td.code { + flex: 1; + overflow: hidden; +} + +.highlight .hll { + display: block; +} + +div.highlight pre, +table.highlighttable pre { + margin: 0; +} + +div.code-block-caption + div { + margin-top: 0; +} + +div.code-block-caption { + margin-top: 1em; + padding: 2px 5px; + font-size: small; +} + +div.code-block-caption code { + background-color: transparent; +} + +table.highlighttable td.linenos, +span.linenos, +div.highlight span.gp { /* gp: Generic.Prompt */ + user-select: none; + -webkit-user-select: text; /* Safari fallback only */ + -webkit-user-select: none; /* Chrome/Safari */ + -moz-user-select: none; /* Firefox */ + -ms-user-select: none; /* IE10+ */ +} + +div.code-block-caption span.caption-number { + padding: 0.1em 0.3em; + font-style: italic; +} + +div.code-block-caption span.caption-text { +} + +div.literal-block-wrapper { + margin: 1em 0; +} + +code.xref, a code { + background-color: transparent; + font-weight: bold; +} + +h1 code, h2 code, h3 code, h4 code, h5 code, h6 code { + background-color: transparent; +} + +.viewcode-link { + float: right; +} + +.viewcode-back { + float: right; + font-family: sans-serif; +} + +div.viewcode-block:target { + margin: -1px -10px; + padding: 0 10px; +} + +/* -- math display ---------------------------------------------------------- */ + +img.math { + vertical-align: middle; +} + +div.body div.math p { + text-align: center; +} + +span.eqno { + float: right; +} + +span.eqno a.headerlink { + position: absolute; + z-index: 1; +} + +div.math:hover a.headerlink { + visibility: visible; +} + +/* -- printout stylesheet --------------------------------------------------- */ + +@media print { + div.document, + div.documentwrapper, + div.bodywrapper { + margin: 0 !important; + width: 100%; + } + + div.sphinxsidebar, + div.related, + div.footer, + #top-link { + display: none; + } +} \ No newline at end of file diff --git a/3.22.3-scylla/_static/check-solid.svg b/3.22.3-scylla/_static/check-solid.svg new file mode 100644 index 0000000000..92fad4b5c0 --- /dev/null +++ b/3.22.3-scylla/_static/check-solid.svg @@ -0,0 +1,4 @@ + + + + diff --git a/3.22.3-scylla/_static/clipboard.min.js b/3.22.3-scylla/_static/clipboard.min.js new file mode 100644 index 0000000000..54b3c46381 --- /dev/null +++ b/3.22.3-scylla/_static/clipboard.min.js @@ -0,0 +1,7 @@ +/*! + * clipboard.js v2.0.8 + * https://clipboardjs.com/ + * + * Licensed MIT © Zeno Rocha + */ +!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?exports.ClipboardJS=e():t.ClipboardJS=e()}(this,function(){return n={686:function(t,e,n){"use strict";n.d(e,{default:function(){return o}});var e=n(279),i=n.n(e),e=n(370),u=n.n(e),e=n(817),c=n.n(e);function a(t){try{return document.execCommand(t)}catch(t){return}}var f=function(t){t=c()(t);return a("cut"),t};var l=function(t){var e,n,o,r=1 + + + + diff --git a/3.22.3-scylla/_static/copybutton.css b/3.22.3-scylla/_static/copybutton.css new file mode 100644 index 0000000000..f1916ec7d1 --- /dev/null +++ b/3.22.3-scylla/_static/copybutton.css @@ -0,0 +1,94 @@ +/* Copy buttons */ +button.copybtn { + position: absolute; + display: flex; + top: .3em; + right: .3em; + width: 1.7em; + height: 1.7em; + opacity: 0; + transition: opacity 0.3s, border .3s, background-color .3s; + user-select: none; + padding: 0; + border: none; + outline: none; + border-radius: 0.4em; + /* The colors that GitHub uses */ + border: #1b1f2426 1px solid; + background-color: #f6f8fa; + color: #57606a; +} + +button.copybtn.success { + border-color: #22863a; + color: #22863a; +} + +button.copybtn svg { + stroke: currentColor; + width: 1.5em; + height: 1.5em; + padding: 0.1em; +} + +div.highlight { + position: relative; +} + +/* Show the copybutton */ +.highlight:hover button.copybtn, button.copybtn.success { + opacity: 1; +} + +.highlight button.copybtn:hover { + background-color: rgb(235, 235, 235); +} + +.highlight button.copybtn:active { + background-color: rgb(187, 187, 187); +} + +/** + * A minimal CSS-only tooltip copied from: + * https://codepen.io/mildrenben/pen/rVBrpK + * + * To use, write HTML like the following: + * + *

Short

+ */ + .o-tooltip--left { + position: relative; + } + + .o-tooltip--left:after { + opacity: 0; + visibility: hidden; + position: absolute; + content: attr(data-tooltip); + padding: .2em; + font-size: .8em; + left: -.2em; + background: grey; + color: white; + white-space: nowrap; + z-index: 2; + border-radius: 2px; + transform: translateX(-102%) translateY(0); + transition: opacity 0.2s cubic-bezier(0.64, 0.09, 0.08, 1), transform 0.2s cubic-bezier(0.64, 0.09, 0.08, 1); +} + +.o-tooltip--left:hover:after { + display: block; + opacity: 1; + visibility: visible; + transform: translateX(-100%) translateY(0); + transition: opacity 0.2s cubic-bezier(0.64, 0.09, 0.08, 1), transform 0.2s cubic-bezier(0.64, 0.09, 0.08, 1); + transition-delay: .5s; +} + +/* By default the copy button shouldn't show up when printing a page */ +@media print { + button.copybtn { + display: none; + } +} diff --git a/3.22.3-scylla/_static/copybutton.js b/3.22.3-scylla/_static/copybutton.js new file mode 100644 index 0000000000..2ea7ff3e21 --- /dev/null +++ b/3.22.3-scylla/_static/copybutton.js @@ -0,0 +1,248 @@ +// Localization support +const messages = { + 'en': { + 'copy': 'Copy', + 'copy_to_clipboard': 'Copy to clipboard', + 'copy_success': 'Copied!', + 'copy_failure': 'Failed to copy', + }, + 'es' : { + 'copy': 'Copiar', + 'copy_to_clipboard': 'Copiar al portapapeles', + 'copy_success': '¡Copiado!', + 'copy_failure': 'Error al copiar', + }, + 'de' : { + 'copy': 'Kopieren', + 'copy_to_clipboard': 'In die Zwischenablage kopieren', + 'copy_success': 'Kopiert!', + 'copy_failure': 'Fehler beim Kopieren', + }, + 'fr' : { + 'copy': 'Copier', + 'copy_to_clipboard': 'Copier dans le presse-papier', + 'copy_success': 'Copié !', + 'copy_failure': 'Échec de la copie', + }, + 'ru': { + 'copy': 'Скопировать', + 'copy_to_clipboard': 'Скопировать в буфер', + 'copy_success': 'Скопировано!', + 'copy_failure': 'Не удалось скопировать', + }, + 'zh-CN': { + 'copy': '复制', + 'copy_to_clipboard': '复制到剪贴板', + 'copy_success': '复制成功!', + 'copy_failure': '复制失败', + }, + 'it' : { + 'copy': 'Copiare', + 'copy_to_clipboard': 'Copiato negli appunti', + 'copy_success': 'Copiato!', + 'copy_failure': 'Errore durante la copia', + } +} + +let locale = 'en' +if( document.documentElement.lang !== undefined + && messages[document.documentElement.lang] !== undefined ) { + locale = document.documentElement.lang +} + +let doc_url_root = DOCUMENTATION_OPTIONS.URL_ROOT; +if (doc_url_root == '#') { + doc_url_root = ''; +} + +/** + * SVG files for our copy buttons + */ +let iconCheck = ` + ${messages[locale]['copy_success']} + + +` + +// If the user specified their own SVG use that, otherwise use the default +let iconCopy = ``; +if (!iconCopy) { + iconCopy = ` + ${messages[locale]['copy_to_clipboard']} + + + +` +} + +/** + * Set up copy/paste for code blocks + */ + +const runWhenDOMLoaded = cb => { + if (document.readyState != 'loading') { + cb() + } else if (document.addEventListener) { + document.addEventListener('DOMContentLoaded', cb) + } else { + document.attachEvent('onreadystatechange', function() { + if (document.readyState == 'complete') cb() + }) + } +} + +const codeCellId = index => `codecell${index}` + +// Clears selected text since ClipboardJS will select the text when copying +const clearSelection = () => { + if (window.getSelection) { + window.getSelection().removeAllRanges() + } else if (document.selection) { + document.selection.empty() + } +} + +// Changes tooltip text for a moment, then changes it back +// We want the timeout of our `success` class to be a bit shorter than the +// tooltip and icon change, so that we can hide the icon before changing back. +var timeoutIcon = 2000; +var timeoutSuccessClass = 1500; + +const temporarilyChangeTooltip = (el, oldText, newText) => { + el.setAttribute('data-tooltip', newText) + el.classList.add('success') + // Remove success a little bit sooner than we change the tooltip + // So that we can use CSS to hide the copybutton first + setTimeout(() => el.classList.remove('success'), timeoutSuccessClass) + setTimeout(() => el.setAttribute('data-tooltip', oldText), timeoutIcon) +} + +// Changes the copy button icon for two seconds, then changes it back +const temporarilyChangeIcon = (el) => { + el.innerHTML = iconCheck; + setTimeout(() => {el.innerHTML = iconCopy}, timeoutIcon) +} + +const addCopyButtonToCodeCells = () => { + // If ClipboardJS hasn't loaded, wait a bit and try again. This + // happens because we load ClipboardJS asynchronously. + if (window.ClipboardJS === undefined) { + setTimeout(addCopyButtonToCodeCells, 250) + return + } + + // Add copybuttons to all of our code cells + const COPYBUTTON_SELECTOR = 'div.highlight pre'; + const codeCells = document.querySelectorAll(COPYBUTTON_SELECTOR) + codeCells.forEach((codeCell, index) => { + const id = codeCellId(index) + codeCell.setAttribute('id', id) + + const clipboardButton = id => + `` + codeCell.insertAdjacentHTML('afterend', clipboardButton(id)) + }) + +function escapeRegExp(string) { + return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string +} + +/** + * Removes excluded text from a Node. + * + * @param {Node} target Node to filter. + * @param {string} exclude CSS selector of nodes to exclude. + * @returns {DOMString} Text from `target` with text removed. + */ +function filterText(target, exclude) { + const clone = target.cloneNode(true); // clone as to not modify the live DOM + if (exclude) { + // remove excluded nodes + clone.querySelectorAll(exclude).forEach(node => node.remove()); + } + return clone.innerText; +} + +// Callback when a copy button is clicked. Will be passed the node that was clicked +// should then grab the text and replace pieces of text that shouldn't be used in output +function formatCopyText(textContent, copybuttonPromptText, isRegexp = false, onlyCopyPromptLines = true, removePrompts = true, copyEmptyLines = true, lineContinuationChar = "", hereDocDelim = "") { + var regexp; + var match; + + // Do we check for line continuation characters and "HERE-documents"? + var useLineCont = !!lineContinuationChar + var useHereDoc = !!hereDocDelim + + // create regexp to capture prompt and remaining line + if (isRegexp) { + regexp = new RegExp('^(' + copybuttonPromptText + ')(.*)') + } else { + regexp = new RegExp('^(' + escapeRegExp(copybuttonPromptText) + ')(.*)') + } + + const outputLines = []; + var promptFound = false; + var gotLineCont = false; + var gotHereDoc = false; + const lineGotPrompt = []; + for (const line of textContent.split('\n')) { + match = line.match(regexp) + if (match || gotLineCont || gotHereDoc) { + promptFound = regexp.test(line) + lineGotPrompt.push(promptFound) + if (removePrompts && promptFound) { + outputLines.push(match[2]) + } else { + outputLines.push(line) + } + gotLineCont = line.endsWith(lineContinuationChar) & useLineCont + if (line.includes(hereDocDelim) & useHereDoc) + gotHereDoc = !gotHereDoc + } else if (!onlyCopyPromptLines) { + outputLines.push(line) + } else if (copyEmptyLines && line.trim() === '') { + outputLines.push(line) + } + } + + // If no lines with the prompt were found then just use original lines + if (lineGotPrompt.some(v => v === true)) { + textContent = outputLines.join('\n'); + } + + // Remove a trailing newline to avoid auto-running when pasting + if (textContent.endsWith("\n")) { + textContent = textContent.slice(0, -1) + } + return textContent +} + + +var copyTargetText = (trigger) => { + var target = document.querySelector(trigger.attributes['data-clipboard-target'].value); + + // get filtered text + let exclude = '.linenos'; + + let text = filterText(target, exclude); + return formatCopyText(text, '', false, true, true, true, '', '') +} + + // Initialize with a callback so we can modify the text before copy + const clipboard = new ClipboardJS('.copybtn', {text: copyTargetText}) + + // Update UI with error/success messages + clipboard.on('success', event => { + clearSelection() + temporarilyChangeTooltip(event.trigger, messages[locale]['copy'], messages[locale]['copy_success']) + temporarilyChangeIcon(event.trigger) + }) + + clipboard.on('error', event => { + temporarilyChangeTooltip(event.trigger, messages[locale]['copy'], messages[locale]['copy_failure']) + }) +} + +runWhenDOMLoaded(addCopyButtonToCodeCells) \ No newline at end of file diff --git a/3.22.3-scylla/_static/copybutton_funcs.js b/3.22.3-scylla/_static/copybutton_funcs.js new file mode 100644 index 0000000000..dbe1aaad79 --- /dev/null +++ b/3.22.3-scylla/_static/copybutton_funcs.js @@ -0,0 +1,73 @@ +function escapeRegExp(string) { + return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string +} + +/** + * Removes excluded text from a Node. + * + * @param {Node} target Node to filter. + * @param {string} exclude CSS selector of nodes to exclude. + * @returns {DOMString} Text from `target` with text removed. + */ +export function filterText(target, exclude) { + const clone = target.cloneNode(true); // clone as to not modify the live DOM + if (exclude) { + // remove excluded nodes + clone.querySelectorAll(exclude).forEach(node => node.remove()); + } + return clone.innerText; +} + +// Callback when a copy button is clicked. Will be passed the node that was clicked +// should then grab the text and replace pieces of text that shouldn't be used in output +export function formatCopyText(textContent, copybuttonPromptText, isRegexp = false, onlyCopyPromptLines = true, removePrompts = true, copyEmptyLines = true, lineContinuationChar = "", hereDocDelim = "") { + var regexp; + var match; + + // Do we check for line continuation characters and "HERE-documents"? + var useLineCont = !!lineContinuationChar + var useHereDoc = !!hereDocDelim + + // create regexp to capture prompt and remaining line + if (isRegexp) { + regexp = new RegExp('^(' + copybuttonPromptText + ')(.*)') + } else { + regexp = new RegExp('^(' + escapeRegExp(copybuttonPromptText) + ')(.*)') + } + + const outputLines = []; + var promptFound = false; + var gotLineCont = false; + var gotHereDoc = false; + const lineGotPrompt = []; + for (const line of textContent.split('\n')) { + match = line.match(regexp) + if (match || gotLineCont || gotHereDoc) { + promptFound = regexp.test(line) + lineGotPrompt.push(promptFound) + if (removePrompts && promptFound) { + outputLines.push(match[2]) + } else { + outputLines.push(line) + } + gotLineCont = line.endsWith(lineContinuationChar) & useLineCont + if (line.includes(hereDocDelim) & useHereDoc) + gotHereDoc = !gotHereDoc + } else if (!onlyCopyPromptLines) { + outputLines.push(line) + } else if (copyEmptyLines && line.trim() === '') { + outputLines.push(line) + } + } + + // If no lines with the prompt were found then just use original lines + if (lineGotPrompt.some(v => v === true)) { + textContent = outputLines.join('\n'); + } + + // Remove a trailing newline to avoid auto-running when pasting + if (textContent.endsWith("\n")) { + textContent = textContent.slice(0, -1) + } + return textContent +} diff --git a/3.22.3-scylla/_static/css/main.css b/3.22.3-scylla/_static/css/main.css new file mode 100644 index 0000000000..4ac0174528 --- /dev/null +++ b/3.22.3-scylla/_static/css/main.css @@ -0,0 +1 @@ +@media print,screen and (min-width:40em){.reveal,.reveal.large,.reveal.small,.reveal.tiny{left:auto;margin:0 auto;right:auto}}/*! normalize.css v8.0.0 | MIT License | github.com/necolas/normalize.css */html{-webkit-text-size-adjust:100%;line-height:1.15}h1{font-size:2em;margin:.67em 0}hr{-webkit-box-sizing:content-box;box-sizing:content-box;overflow:visible}pre{font-family:monospace,monospace;font-size:1em}a{background-color:transparent}abbr[title]{border-bottom:0;-webkit-text-decoration:underline dotted;text-decoration:underline dotted}b,strong{font-weight:bolder}code,kbd,samp{font-family:monospace,monospace;font-size:1em}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}img{border-style:none}button,input,optgroup,select,textarea{font-size:100%;line-height:1.15;margin:0}button,input{overflow:visible}button,select{text-transform:none}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button}[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner,button::-moz-focus-inner{border-style:none;padding:0}[type=button]:-moz-focusring,[type=reset]:-moz-focusring,[type=submit]:-moz-focusring,button:-moz-focusring{outline:1px dotted ButtonText}fieldset{padding:.35em .75em .625em}legend{-webkit-box-sizing:border-box;box-sizing:border-box;color:inherit;display:table;padding:0;white-space:normal}progress{vertical-align:baseline}textarea{overflow:auto}[type=checkbox],[type=radio]{-webkit-box-sizing:border-box;box-sizing:border-box;padding:0}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}details{display:block}summary{display:list-item}template{display:none}[hidden]{display:none}[data-whatinput=mouse] *,[data-whatinput=mouse] :focus,[data-whatinput=touch] *,[data-whatinput=touch] :focus,[data-whatintent=mouse] *,[data-whatintent=mouse] :focus,[data-whatintent=touch] *,[data-whatintent=touch] :focus{outline:0}[draggable=false]{-webkit-touch-callout:none;-webkit-user-select:none}.foundation-mq{font-family:"small=0em&medium=40em&large=64em&xlarge=75em&xxlarge=90em"}html{-webkit-box-sizing:border-box;font-size:100%}*,:after,:before{-webkit-box-sizing:inherit}body{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;background:#fefefe;color:#0a0a0a;font-family:Helvetica Neue,Helvetica,Roboto,Arial,sans-serif;font-weight:400;line-height:1.5;margin:0;padding:0}img{-ms-interpolation-mode:bicubic;display:inline-block;height:auto;vertical-align:middle}textarea{border-radius:0;height:auto;min-height:50px}select{-webkit-box-sizing:border-box;box-sizing:border-box;width:100%}.map_canvas embed,.map_canvas img,.map_canvas object,.mqa-display embed,.mqa-display img,.mqa-display object{max-width:none!important}button{-webkit-appearance:none;-moz-appearance:none;appearance:none;background:0 0;border:0;border-radius:0;cursor:auto;line-height:1;padding:0}[data-whatinput=mouse] button{outline:0}pre{-webkit-overflow-scrolling:touch;overflow:auto}button,input,optgroup,select,textarea{font-family:inherit}.is-visible{display:block!important}.is-hidden{display:none!important}[type=color],[type=date],[type=datetime-local],[type=datetime],[type=email],[type=month],[type=number],[type=password],[type=search],[type=tel],[type=text],[type=time],[type=url],[type=week],textarea{-webkit-appearance:none;-moz-appearance:none;appearance:none;background-color:#fefefe;border:1px solid #cacaca;border-radius:0;-webkit-box-shadow:inset 0 1px 2px hsla(0,0%,4%,.1);box-shadow:inset 0 1px 2px hsla(0,0%,4%,.1);-webkit-box-sizing:border-box;box-sizing:border-box;color:#0a0a0a;display:block;font-family:inherit;font-size:1rem;font-weight:400;height:2.4375rem;line-height:1.5;margin:0 0 1rem;padding:.5rem;-webkit-transition:border-color .25s ease-in-out,-webkit-box-shadow .5s;transition:border-color .25s ease-in-out,-webkit-box-shadow .5s;transition:box-shadow .5s,border-color .25s ease-in-out;transition:box-shadow .5s,border-color .25s ease-in-out,-webkit-box-shadow .5s;width:100%}[type=color]:focus,[type=date]:focus,[type=datetime-local]:focus,[type=datetime]:focus,[type=email]:focus,[type=month]:focus,[type=number]:focus,[type=password]:focus,[type=search]:focus,[type=tel]:focus,[type=text]:focus,[type=time]:focus,[type=url]:focus,[type=week]:focus,textarea:focus{background-color:#fefefe;border:1px solid #8a8a8a;-webkit-box-shadow:0 0 5px #cacaca;box-shadow:0 0 5px #cacaca;outline:0;-webkit-transition:border-color .25s ease-in-out,-webkit-box-shadow .5s;transition:border-color .25s ease-in-out,-webkit-box-shadow .5s;transition:box-shadow .5s,border-color .25s ease-in-out;transition:box-shadow .5s,border-color .25s ease-in-out,-webkit-box-shadow .5s}textarea{max-width:100%}textarea[rows]{height:auto}input:disabled,input[readonly],textarea:disabled,textarea[readonly]{background-color:#e6e6e6;cursor:not-allowed}[type=button],[type=submit]{-webkit-appearance:none;-moz-appearance:none;appearance:none;border-radius:0}input[type=search]{-webkit-box-sizing:border-box;box-sizing:border-box}::-webkit-input-placeholder{color:#cacaca}::-moz-placeholder{color:#cacaca}:-ms-input-placeholder{color:#cacaca}::-ms-input-placeholder{color:#cacaca}::placeholder{color:#cacaca}[type=checkbox],[type=file],[type=radio]{margin:0 0 1rem}[type=checkbox]+label,[type=radio]+label{display:inline-block;margin-bottom:0;margin-left:.5rem;margin-right:1rem;vertical-align:baseline}[type=checkbox]+label[for],[type=radio]+label[for]{cursor:pointer}label>[type=checkbox],label>[type=radio]{margin-right:.5rem}[type=file]{width:100%}label{color:#0a0a0a;display:block;font-size:.875rem;font-weight:400;line-height:1.8;margin:0}label.middle{line-height:1.5;margin:0 0 1rem;padding:.5625rem 0}.help-text{color:#0a0a0a;font-size:.8125rem;font-style:italic;margin-top:-.5rem}.input-group{-webkit-box-align:stretch;-ms-flex-align:stretch;-webkit-align-items:stretch;align-items:stretch;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;margin-bottom:1rem;width:100%}.input-group>:first-child,.input-group>:first-child.input-group-button>*{border-radius:0}.input-group>:last-child,.input-group>:last-child.input-group-button>*{border-radius:0}.input-group-button,.input-group-button a,.input-group-button button,.input-group-button input,.input-group-button label,.input-group-field,.input-group-label{margin:0;white-space:nowrap}.input-group-label{-webkit-box-flex:0;-webkit-box-align:center;-ms-flex-align:center;-webkit-align-items:center;align-items:center;background:#e6e6e6;border:1px solid #cacaca;color:#0a0a0a;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto;padding:0 1rem;text-align:center;white-space:nowrap}.input-group-label:first-child{border-right:0}.input-group-label:last-child{border-left:0}.input-group-field{-webkit-box-flex:1;border-radius:0;-webkit-flex:1 1 0px;-ms-flex:1 1 0px;flex:1 1 0px;min-width:0}.input-group-button{-webkit-box-flex:0;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto;padding-bottom:0;padding-top:0;text-align:center}.input-group-button a,.input-group-button button,.input-group-button input,.input-group-button label{-ms-flex-item-align:stretch;-webkit-align-self:stretch;align-self:stretch;font-size:1rem;height:auto;padding-bottom:0;padding-top:0}fieldset{border:0;margin:0;padding:0}legend{margin-bottom:.5rem;max-width:100%}.fieldset{border:1px solid #cacaca;margin:1.125rem 0;padding:1.25rem}.fieldset legend{margin:0 0 0 -.1875rem;padding:0 .1875rem}select{-webkit-appearance:none;-moz-appearance:none;appearance:none;background-color:#fefefe;background-image:url('data:image/svg+xml;utf8,');background-origin:content-box;background-position:right -1rem center;background-repeat:no-repeat;background-size:9px 6px;border:1px solid #cacaca;border-radius:0;color:#0a0a0a;font-family:inherit;font-size:1rem;font-weight:400;height:2.4375rem;line-height:1.5;margin:0 0 1rem;padding:.5rem 1.5rem .5rem .5rem;-webkit-transition:border-color .25s ease-in-out,-webkit-box-shadow .5s;transition:border-color .25s ease-in-out,-webkit-box-shadow .5s;transition:box-shadow .5s,border-color .25s ease-in-out;transition:box-shadow .5s,border-color .25s ease-in-out,-webkit-box-shadow .5s}@media screen and (min-width:0\0){select{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAYCAYAAACbU/80AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAIpJREFUeNrEkckNgDAMBBfRkEt0ObRBBdsGXUDgmQfK4XhH2m8czQAAy27R3tsw4Qfe2x8uOO6oYLb6GlOor3GF+swURAOmUJ+RwtEJs9WvTGEYxBXqI1MQAZhCfUQKRzDMVj+TwrAIV6jvSUEkYAr1LSkcyTBb/V+KYfX7xAeusq3sLDtGH3kEGACPWIflNZfhRQAAAABJRU5ErkJggg==)}}select:focus{background-color:#fefefe;border:1px solid #8a8a8a;-webkit-box-shadow:0 0 5px #cacaca;box-shadow:0 0 5px #cacaca;outline:0;-webkit-transition:border-color .25s ease-in-out,-webkit-box-shadow .5s;transition:border-color .25s ease-in-out,-webkit-box-shadow .5s;transition:box-shadow .5s,border-color .25s ease-in-out;transition:box-shadow .5s,border-color .25s ease-in-out,-webkit-box-shadow .5s}select:disabled{background-color:#e6e6e6;cursor:not-allowed}select::-ms-expand{display:none}select[multiple]{background-image:none;height:auto}select:not([multiple]){padding-bottom:0;padding-top:0}.is-invalid-input:not(:focus){background-color:#f9ecea;border-color:#cc4b37}.is-invalid-input:not(:focus)::-webkit-input-placeholder{color:#cc4b37}.is-invalid-input:not(:focus)::-moz-placeholder{color:#cc4b37}.is-invalid-input:not(:focus):-ms-input-placeholder{color:#cc4b37}.is-invalid-input:not(:focus)::-ms-input-placeholder{color:#cc4b37}.is-invalid-input:not(:focus)::placeholder{color:#cc4b37}.form-error,.is-invalid-label{color:#cc4b37}.form-error{display:none;font-size:.75rem;font-weight:700;margin-bottom:1rem;margin-top:-.5rem}.form-error.is-visible{display:block}blockquote,dd,div,dl,dt,form,h1,h2,h3,h4,h5,h6,li,ol,p,pre,td,th,ul{margin:0;padding:0}p{text-rendering:optimizeLegibility;font-size:inherit;line-height:1.6;margin-bottom:1rem}em,i{font-style:italic}b,em,i,strong{line-height:inherit}b,strong{font-weight:700}small{font-size:80%;line-height:inherit}.h1,.h2,.h3,.h4,.h5,.h6,h1,h2,h3,h4,h5,h6{text-rendering:optimizeLegibility;color:inherit;font-family:Helvetica Neue,Helvetica,Roboto,Arial,sans-serif;font-style:normal;font-weight:400}.h1 small,.h2 small,.h3 small,.h4 small,.h5 small,.h6 small,h1 small,h2 small,h3 small,h4 small,h5 small,h6 small{color:#cacaca;line-height:0}.h1,h1{font-size:1.5rem}.h1,.h2,h1,h2{line-height:1.4;margin-bottom:.5rem;margin-top:0}.h2,h2{font-size:1.25rem}.h3,h3{font-size:1.1875rem}.h3,.h4,h3,h4{line-height:1.4;margin-bottom:.5rem;margin-top:0}.h4,h4{font-size:1.125rem}.h5,h5{font-size:1.0625rem}.h5,.h6,h5,h6{line-height:1.4;margin-bottom:.5rem;margin-top:0}.h6,h6{font-size:1rem}@media print,screen and (min-width:40em){.h1,h1{font-size:3rem}.h2,h2{font-size:2.5rem}.h3,h3{font-size:1.9375rem}.h4,h4{font-size:1.5625rem}.h5,h5{font-size:1.25rem}.h6,h6{font-size:1rem}}a{color:#1779ba;cursor:pointer;line-height:inherit;text-decoration:none}a:focus,a:hover{color:#1468a0}a img,hr{border:0}hr{border-bottom:1px solid #cacaca;clear:both;height:0;margin:1.25rem auto;max-width:75rem}dl,ol,ul{line-height:1.6;list-style-position:outside;margin-bottom:1rem}li{font-size:inherit}ul{list-style-type:disc}ol,ul{margin-left:1.25rem}ol ol,ol ul,ul ol,ul ul{margin-bottom:0;margin-left:1.25rem}dl{margin-bottom:1rem}dl dt{font-weight:700;margin-bottom:.3rem}blockquote{border-left:1px solid #cacaca;margin:0 0 1rem;padding:.5625rem 1.25rem 0 1.1875rem}blockquote,blockquote p{color:#8a8a8a;line-height:1.6}abbr,abbr[title]{border-bottom:1px dotted #0a0a0a;cursor:help;text-decoration:none}figure,kbd{margin:0}kbd{background-color:#e6e6e6;color:#0a0a0a;font-family:Consolas,Liberation Mono,Courier,monospace;padding:.125rem .25rem 0}.subheader{color:#8a8a8a;font-weight:400;line-height:1.4;margin-bottom:.5rem;margin-top:.2rem}.lead{font-size:125%;line-height:1.6}.stat{font-size:2.5rem;line-height:1}p+.stat{margin-top:-1rem}ol.no-bullet,ul.no-bullet{list-style:none;margin-left:0}.cite-block,cite{color:#8a8a8a;display:block;font-size:.8125rem}.cite-block:before,cite:before{content:"— "}.code-inline,code{word-wrap:break-word;display:inline;max-width:100%;padding:.125rem .3125rem .0625rem}.code-block,.code-inline,code{background-color:#e6e6e6;border:1px solid #cacaca;color:#0a0a0a;font-family:Consolas,Liberation Mono,Courier,monospace;font-weight:400}.code-block{display:block;margin-bottom:1.5rem;overflow:auto;padding:1rem;white-space:pre}.text-left{text-align:left}.text-right{text-align:right}.text-center{text-align:center}.text-justify{text-align:justify}@media print,screen and (min-width:40em){.medium-text-left{text-align:left}.medium-text-right{text-align:right}.medium-text-center{text-align:center}.medium-text-justify{text-align:justify}}@media print,screen and (min-width:64em){.large-text-left{text-align:left}.large-text-right{text-align:right}.large-text-center{text-align:center}.large-text-justify{text-align:justify}}.show-for-print{display:none!important}@media print{*{-webkit-print-color-adjust:economy;background:0 0!important;-webkit-box-shadow:none!important;box-shadow:none!important;color:#000!important;color-adjust:economy;text-shadow:none!important}.show-for-print{display:block!important}.hide-for-print{display:none!important}table.show-for-print{display:table!important}thead.show-for-print{display:table-header-group!important}tbody.show-for-print{display:table-row-group!important}tr.show-for-print{display:table-row!important}td.show-for-print,th.show-for-print{display:table-cell!important}a,a:visited{text-decoration:underline}a[href]:after{content:" (" attr(href) ")"}.ir a:after,a[href^="#"]:after,a[href^="javascript:"]:after{content:""}abbr[title]:after{content:" (" attr(title) ")"}blockquote,pre{border:1px solid #8a8a8a;page-break-inside:avoid}thead{display:table-header-group}img,tr{page-break-inside:avoid}img{max-width:100%!important}@page{margin:.5cm}h2,h3,p{orphans:3;widows:3}h2,h3{page-break-after:avoid}.print-break-inside{page-break-inside:auto}}.grid-container{margin-left:auto;margin-right:auto;max-width:75rem;padding-left:.625rem;padding-right:.625rem}@media print,screen and (min-width:40em){.grid-container{padding-left:.9375rem;padding-right:.9375rem}}.grid-container.fluid{margin-left:auto;margin-right:auto;max-width:100%;padding-left:.625rem;padding-right:.625rem}@media print,screen and (min-width:40em){.grid-container.fluid{padding-left:.9375rem;padding-right:.9375rem}}.grid-container.full{margin-left:auto;margin-right:auto;max-width:100%;padding-left:0;padding-right:0}.grid-x{-webkit-box-orient:horizontal;-webkit-box-direction:normal;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-flow:row wrap;-ms-flex-flow:row wrap;flex-flow:row wrap}.cell{-webkit-box-flex:0;-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto;min-height:0;min-width:0;width:100%}.cell.auto{-webkit-box-flex:1;-webkit-flex:1 1 0;-ms-flex:1 1 0px;flex:1 1 0}.cell.shrink{-webkit-box-flex:0;-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto}.grid-x>.auto{width:auto}.grid-x>.shrink{width:auto}.grid-x>.small-1,.grid-x>.small-2,.grid-x>.small-3,.grid-x>.small-4,.grid-x>.small-5,.grid-x>.small-6,.grid-x>.small-7,.grid-x>.small-8,.grid-x>.small-9,.grid-x>.small-10,.grid-x>.small-11,.grid-x>.small-12,.grid-x>.small-full,.grid-x>.small-shrink{-ms-flex-preferred-size:auto;-webkit-flex-basis:auto;flex-basis:auto}@media print,screen and (min-width:40em){.grid-x>.medium-1,.grid-x>.medium-2,.grid-x>.medium-3,.grid-x>.medium-4,.grid-x>.medium-5,.grid-x>.medium-6,.grid-x>.medium-7,.grid-x>.medium-8,.grid-x>.medium-9,.grid-x>.medium-10,.grid-x>.medium-11,.grid-x>.medium-12,.grid-x>.medium-full,.grid-x>.medium-shrink{-ms-flex-preferred-size:auto;-webkit-flex-basis:auto;flex-basis:auto}}@media print,screen and (min-width:64em){.grid-x>.large-1,.grid-x>.large-2,.grid-x>.large-3,.grid-x>.large-4,.grid-x>.large-5,.grid-x>.large-6,.grid-x>.large-7,.grid-x>.large-8,.grid-x>.large-9,.grid-x>.large-10,.grid-x>.large-11,.grid-x>.large-12,.grid-x>.large-full,.grid-x>.large-shrink{-ms-flex-preferred-size:auto;-webkit-flex-basis:auto;flex-basis:auto}}.grid-x>.small-1,.grid-x>.small-2,.grid-x>.small-3,.grid-x>.small-4,.grid-x>.small-5,.grid-x>.small-6,.grid-x>.small-7,.grid-x>.small-8,.grid-x>.small-9,.grid-x>.small-10,.grid-x>.small-11,.grid-x>.small-12{-webkit-box-flex:0;-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto}.grid-x>.small-1{width:8.33333%}.grid-x>.small-2{width:16.66667%}.grid-x>.small-3{width:25%}.grid-x>.small-4{width:33.33333%}.grid-x>.small-5{width:41.66667%}.grid-x>.small-6{width:50%}.grid-x>.small-7{width:58.33333%}.grid-x>.small-8{width:66.66667%}.grid-x>.small-9{width:75%}.grid-x>.small-10{width:83.33333%}.grid-x>.small-11{width:91.66667%}.grid-x>.small-12{width:100%}@media print,screen and (min-width:40em){.grid-x>.medium-auto{-webkit-box-flex:1;-webkit-flex:1 1 0;-ms-flex:1 1 0px;flex:1 1 0;width:auto}.grid-x>.medium-1,.grid-x>.medium-2,.grid-x>.medium-3,.grid-x>.medium-4,.grid-x>.medium-5,.grid-x>.medium-6,.grid-x>.medium-7,.grid-x>.medium-8,.grid-x>.medium-9,.grid-x>.medium-10,.grid-x>.medium-11,.grid-x>.medium-12,.grid-x>.medium-shrink{-webkit-box-flex:0;-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto}.grid-x>.medium-shrink{width:auto}.grid-x>.medium-1{width:8.33333%}.grid-x>.medium-2{width:16.66667%}.grid-x>.medium-3{width:25%}.grid-x>.medium-4{width:33.33333%}.grid-x>.medium-5{width:41.66667%}.grid-x>.medium-6{width:50%}.grid-x>.medium-7{width:58.33333%}.grid-x>.medium-8{width:66.66667%}.grid-x>.medium-9{width:75%}.grid-x>.medium-10{width:83.33333%}.grid-x>.medium-11{width:91.66667%}.grid-x>.medium-12{width:100%}}@media print,screen and (min-width:64em){.grid-x>.large-auto{-webkit-box-flex:1;-webkit-flex:1 1 0;-ms-flex:1 1 0px;flex:1 1 0;width:auto}.grid-x>.large-1,.grid-x>.large-2,.grid-x>.large-3,.grid-x>.large-4,.grid-x>.large-5,.grid-x>.large-6,.grid-x>.large-7,.grid-x>.large-8,.grid-x>.large-9,.grid-x>.large-10,.grid-x>.large-11,.grid-x>.large-12,.grid-x>.large-shrink{-webkit-box-flex:0;-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto}.grid-x>.large-shrink{width:auto}.grid-x>.large-1{width:8.33333%}.grid-x>.large-2{width:16.66667%}.grid-x>.large-3{width:25%}.grid-x>.large-4{width:33.33333%}.grid-x>.large-5{width:41.66667%}.grid-x>.large-6{width:50%}.grid-x>.large-7{width:58.33333%}.grid-x>.large-8{width:66.66667%}.grid-x>.large-9{width:75%}.grid-x>.large-10{width:83.33333%}.grid-x>.large-11{width:91.66667%}.grid-x>.large-12{width:100%}}.grid-margin-x:not(.grid-x)>.cell{width:auto}.grid-margin-y:not(.grid-y)>.cell{height:auto}.grid-margin-x{margin-left:-.625rem;margin-right:-.625rem}@media print,screen and (min-width:40em){.grid-margin-x{margin-left:-.9375rem;margin-right:-.9375rem}}.grid-margin-x>.cell{margin-left:.625rem;margin-right:.625rem;width:calc(100% - 1.25rem)}@media print,screen and (min-width:40em){.grid-margin-x>.cell{margin-left:.9375rem;margin-right:.9375rem;width:calc(100% - 1.875rem)}}.grid-margin-x>.auto{width:auto}.grid-margin-x>.shrink{width:auto}.grid-margin-x>.small-1{width:calc(8.33333% - 1.25rem)}.grid-margin-x>.small-2{width:calc(16.66667% - 1.25rem)}.grid-margin-x>.small-3{width:calc(25% - 1.25rem)}.grid-margin-x>.small-4{width:calc(33.33333% - 1.25rem)}.grid-margin-x>.small-5{width:calc(41.66667% - 1.25rem)}.grid-margin-x>.small-6{width:calc(50% - 1.25rem)}.grid-margin-x>.small-7{width:calc(58.33333% - 1.25rem)}.grid-margin-x>.small-8{width:calc(66.66667% - 1.25rem)}.grid-margin-x>.small-9{width:calc(75% - 1.25rem)}.grid-margin-x>.small-10{width:calc(83.33333% - 1.25rem)}.grid-margin-x>.small-11{width:calc(91.66667% - 1.25rem)}.grid-margin-x>.small-12{width:calc(100% - 1.25rem)}@media print,screen and (min-width:40em){.grid-margin-x>.auto{width:auto}.grid-margin-x>.shrink{width:auto}.grid-margin-x>.small-1{width:calc(8.33333% - 1.875rem)}.grid-margin-x>.small-2{width:calc(16.66667% - 1.875rem)}.grid-margin-x>.small-3{width:calc(25% - 1.875rem)}.grid-margin-x>.small-4{width:calc(33.33333% - 1.875rem)}.grid-margin-x>.small-5{width:calc(41.66667% - 1.875rem)}.grid-margin-x>.small-6{width:calc(50% - 1.875rem)}.grid-margin-x>.small-7{width:calc(58.33333% - 1.875rem)}.grid-margin-x>.small-8{width:calc(66.66667% - 1.875rem)}.grid-margin-x>.small-9{width:calc(75% - 1.875rem)}.grid-margin-x>.small-10{width:calc(83.33333% - 1.875rem)}.grid-margin-x>.small-11{width:calc(91.66667% - 1.875rem)}.grid-margin-x>.small-12{width:calc(100% - 1.875rem)}.grid-margin-x>.medium-auto{width:auto}.grid-margin-x>.medium-shrink{width:auto}.grid-margin-x>.medium-1{width:calc(8.33333% - 1.875rem)}.grid-margin-x>.medium-2{width:calc(16.66667% - 1.875rem)}.grid-margin-x>.medium-3{width:calc(25% - 1.875rem)}.grid-margin-x>.medium-4{width:calc(33.33333% - 1.875rem)}.grid-margin-x>.medium-5{width:calc(41.66667% - 1.875rem)}.grid-margin-x>.medium-6{width:calc(50% - 1.875rem)}.grid-margin-x>.medium-7{width:calc(58.33333% - 1.875rem)}.grid-margin-x>.medium-8{width:calc(66.66667% - 1.875rem)}.grid-margin-x>.medium-9{width:calc(75% - 1.875rem)}.grid-margin-x>.medium-10{width:calc(83.33333% - 1.875rem)}.grid-margin-x>.medium-11{width:calc(91.66667% - 1.875rem)}.grid-margin-x>.medium-12{width:calc(100% - 1.875rem)}}@media print,screen and (min-width:64em){.grid-margin-x>.large-auto{width:auto}.grid-margin-x>.large-shrink{width:auto}.grid-margin-x>.large-1{width:calc(8.33333% - 1.875rem)}.grid-margin-x>.large-2{width:calc(16.66667% - 1.875rem)}.grid-margin-x>.large-3{width:calc(25% - 1.875rem)}.grid-margin-x>.large-4{width:calc(33.33333% - 1.875rem)}.grid-margin-x>.large-5{width:calc(41.66667% - 1.875rem)}.grid-margin-x>.large-6{width:calc(50% - 1.875rem)}.grid-margin-x>.large-7{width:calc(58.33333% - 1.875rem)}.grid-margin-x>.large-8{width:calc(66.66667% - 1.875rem)}.grid-margin-x>.large-9{width:calc(75% - 1.875rem)}.grid-margin-x>.large-10{width:calc(83.33333% - 1.875rem)}.grid-margin-x>.large-11{width:calc(91.66667% - 1.875rem)}.grid-margin-x>.large-12{width:calc(100% - 1.875rem)}}.grid-padding-x .grid-padding-x{margin-left:-.625rem;margin-right:-.625rem}@media print,screen and (min-width:40em){.grid-padding-x .grid-padding-x{margin-left:-.9375rem;margin-right:-.9375rem}}.grid-container:not(.full)>.grid-padding-x{margin-left:-.625rem;margin-right:-.625rem}@media print,screen and (min-width:40em){.grid-container:not(.full)>.grid-padding-x{margin-left:-.9375rem;margin-right:-.9375rem}}.grid-padding-x>.cell{padding-left:.625rem;padding-right:.625rem}@media print,screen and (min-width:40em){.grid-padding-x>.cell{padding-left:.9375rem;padding-right:.9375rem}}.small-up-1>.cell{width:100%}.small-up-2>.cell{width:50%}.small-up-3>.cell{width:33.33333%}.small-up-4>.cell{width:25%}.small-up-5>.cell{width:20%}.small-up-6>.cell{width:16.66667%}.small-up-7>.cell{width:14.28571%}.small-up-8>.cell{width:12.5%}@media print,screen and (min-width:40em){.medium-up-1>.cell{width:100%}.medium-up-2>.cell{width:50%}.medium-up-3>.cell{width:33.33333%}.medium-up-4>.cell{width:25%}.medium-up-5>.cell{width:20%}.medium-up-6>.cell{width:16.66667%}.medium-up-7>.cell{width:14.28571%}.medium-up-8>.cell{width:12.5%}}@media print,screen and (min-width:64em){.large-up-1>.cell{width:100%}.large-up-2>.cell{width:50%}.large-up-3>.cell{width:33.33333%}.large-up-4>.cell{width:25%}.large-up-5>.cell{width:20%}.large-up-6>.cell{width:16.66667%}.large-up-7>.cell{width:14.28571%}.large-up-8>.cell{width:12.5%}}.grid-margin-x.small-up-1>.cell{width:calc(100% - 1.25rem)}.grid-margin-x.small-up-2>.cell{width:calc(50% - 1.25rem)}.grid-margin-x.small-up-3>.cell{width:calc(33.33333% - 1.25rem)}.grid-margin-x.small-up-4>.cell{width:calc(25% - 1.25rem)}.grid-margin-x.small-up-5>.cell{width:calc(20% - 1.25rem)}.grid-margin-x.small-up-6>.cell{width:calc(16.66667% - 1.25rem)}.grid-margin-x.small-up-7>.cell{width:calc(14.28571% - 1.25rem)}.grid-margin-x.small-up-8>.cell{width:calc(12.5% - 1.25rem)}@media print,screen and (min-width:40em){.grid-margin-x.small-up-1>.cell{width:calc(100% - 1.875rem)}.grid-margin-x.small-up-2>.cell{width:calc(50% - 1.875rem)}.grid-margin-x.small-up-3>.cell{width:calc(33.33333% - 1.875rem)}.grid-margin-x.small-up-4>.cell{width:calc(25% - 1.875rem)}.grid-margin-x.small-up-5>.cell{width:calc(20% - 1.875rem)}.grid-margin-x.small-up-6>.cell{width:calc(16.66667% - 1.875rem)}.grid-margin-x.small-up-7>.cell{width:calc(14.28571% - 1.875rem)}.grid-margin-x.small-up-8>.cell{width:calc(12.5% - 1.875rem)}.grid-margin-x.medium-up-1>.cell{width:calc(100% - 1.875rem)}.grid-margin-x.medium-up-2>.cell{width:calc(50% - 1.875rem)}.grid-margin-x.medium-up-3>.cell{width:calc(33.33333% - 1.875rem)}.grid-margin-x.medium-up-4>.cell{width:calc(25% - 1.875rem)}.grid-margin-x.medium-up-5>.cell{width:calc(20% - 1.875rem)}.grid-margin-x.medium-up-6>.cell{width:calc(16.66667% - 1.875rem)}.grid-margin-x.medium-up-7>.cell{width:calc(14.28571% - 1.875rem)}.grid-margin-x.medium-up-8>.cell{width:calc(12.5% - 1.875rem)}}@media print,screen and (min-width:64em){.grid-margin-x.large-up-1>.cell{width:calc(100% - 1.875rem)}.grid-margin-x.large-up-2>.cell{width:calc(50% - 1.875rem)}.grid-margin-x.large-up-3>.cell{width:calc(33.33333% - 1.875rem)}.grid-margin-x.large-up-4>.cell{width:calc(25% - 1.875rem)}.grid-margin-x.large-up-5>.cell{width:calc(20% - 1.875rem)}.grid-margin-x.large-up-6>.cell{width:calc(16.66667% - 1.875rem)}.grid-margin-x.large-up-7>.cell{width:calc(14.28571% - 1.875rem)}.grid-margin-x.large-up-8>.cell{width:calc(12.5% - 1.875rem)}}.small-margin-collapse{margin-left:0;margin-right:0}.small-margin-collapse>.cell{margin-left:0;margin-right:0}.small-margin-collapse>.small-1{width:8.33333%}.small-margin-collapse>.small-2{width:16.66667%}.small-margin-collapse>.small-3{width:25%}.small-margin-collapse>.small-4{width:33.33333%}.small-margin-collapse>.small-5{width:41.66667%}.small-margin-collapse>.small-6{width:50%}.small-margin-collapse>.small-7{width:58.33333%}.small-margin-collapse>.small-8{width:66.66667%}.small-margin-collapse>.small-9{width:75%}.small-margin-collapse>.small-10{width:83.33333%}.small-margin-collapse>.small-11{width:91.66667%}.small-margin-collapse>.small-12{width:100%}@media print,screen and (min-width:40em){.small-margin-collapse>.medium-1{width:8.33333%}.small-margin-collapse>.medium-2{width:16.66667%}.small-margin-collapse>.medium-3{width:25%}.small-margin-collapse>.medium-4{width:33.33333%}.small-margin-collapse>.medium-5{width:41.66667%}.small-margin-collapse>.medium-6{width:50%}.small-margin-collapse>.medium-7{width:58.33333%}.small-margin-collapse>.medium-8{width:66.66667%}.small-margin-collapse>.medium-9{width:75%}.small-margin-collapse>.medium-10{width:83.33333%}.small-margin-collapse>.medium-11{width:91.66667%}.small-margin-collapse>.medium-12{width:100%}}@media print,screen and (min-width:64em){.small-margin-collapse>.large-1{width:8.33333%}.small-margin-collapse>.large-2{width:16.66667%}.small-margin-collapse>.large-3{width:25%}.small-margin-collapse>.large-4{width:33.33333%}.small-margin-collapse>.large-5{width:41.66667%}.small-margin-collapse>.large-6{width:50%}.small-margin-collapse>.large-7{width:58.33333%}.small-margin-collapse>.large-8{width:66.66667%}.small-margin-collapse>.large-9{width:75%}.small-margin-collapse>.large-10{width:83.33333%}.small-margin-collapse>.large-11{width:91.66667%}.small-margin-collapse>.large-12{width:100%}}.small-padding-collapse{margin-left:0;margin-right:0}.small-padding-collapse>.cell{padding-left:0;padding-right:0}@media print,screen and (min-width:40em){.medium-margin-collapse{margin-left:0;margin-right:0}.medium-margin-collapse>.cell{margin-left:0;margin-right:0}}@media print,screen and (min-width:40em){.medium-margin-collapse>.small-1{width:8.33333%}.medium-margin-collapse>.small-2{width:16.66667%}.medium-margin-collapse>.small-3{width:25%}.medium-margin-collapse>.small-4{width:33.33333%}.medium-margin-collapse>.small-5{width:41.66667%}.medium-margin-collapse>.small-6{width:50%}.medium-margin-collapse>.small-7{width:58.33333%}.medium-margin-collapse>.small-8{width:66.66667%}.medium-margin-collapse>.small-9{width:75%}.medium-margin-collapse>.small-10{width:83.33333%}.medium-margin-collapse>.small-11{width:91.66667%}.medium-margin-collapse>.small-12{width:100%}}@media print,screen and (min-width:40em){.medium-margin-collapse>.medium-1{width:8.33333%}.medium-margin-collapse>.medium-2{width:16.66667%}.medium-margin-collapse>.medium-3{width:25%}.medium-margin-collapse>.medium-4{width:33.33333%}.medium-margin-collapse>.medium-5{width:41.66667%}.medium-margin-collapse>.medium-6{width:50%}.medium-margin-collapse>.medium-7{width:58.33333%}.medium-margin-collapse>.medium-8{width:66.66667%}.medium-margin-collapse>.medium-9{width:75%}.medium-margin-collapse>.medium-10{width:83.33333%}.medium-margin-collapse>.medium-11{width:91.66667%}.medium-margin-collapse>.medium-12{width:100%}}@media print,screen and (min-width:64em){.medium-margin-collapse>.large-1{width:8.33333%}.medium-margin-collapse>.large-2{width:16.66667%}.medium-margin-collapse>.large-3{width:25%}.medium-margin-collapse>.large-4{width:33.33333%}.medium-margin-collapse>.large-5{width:41.66667%}.medium-margin-collapse>.large-6{width:50%}.medium-margin-collapse>.large-7{width:58.33333%}.medium-margin-collapse>.large-8{width:66.66667%}.medium-margin-collapse>.large-9{width:75%}.medium-margin-collapse>.large-10{width:83.33333%}.medium-margin-collapse>.large-11{width:91.66667%}.medium-margin-collapse>.large-12{width:100%}}@media print,screen and (min-width:40em){.medium-padding-collapse{margin-left:0;margin-right:0}.medium-padding-collapse>.cell{padding-left:0;padding-right:0}}@media print,screen and (min-width:64em){.large-margin-collapse{margin-left:0;margin-right:0}.large-margin-collapse>.cell{margin-left:0;margin-right:0}}@media print,screen and (min-width:64em){.large-margin-collapse>.small-1{width:8.33333%}.large-margin-collapse>.small-2{width:16.66667%}.large-margin-collapse>.small-3{width:25%}.large-margin-collapse>.small-4{width:33.33333%}.large-margin-collapse>.small-5{width:41.66667%}.large-margin-collapse>.small-6{width:50%}.large-margin-collapse>.small-7{width:58.33333%}.large-margin-collapse>.small-8{width:66.66667%}.large-margin-collapse>.small-9{width:75%}.large-margin-collapse>.small-10{width:83.33333%}.large-margin-collapse>.small-11{width:91.66667%}.large-margin-collapse>.small-12{width:100%}}@media print,screen and (min-width:64em){.large-margin-collapse>.medium-1{width:8.33333%}.large-margin-collapse>.medium-2{width:16.66667%}.large-margin-collapse>.medium-3{width:25%}.large-margin-collapse>.medium-4{width:33.33333%}.large-margin-collapse>.medium-5{width:41.66667%}.large-margin-collapse>.medium-6{width:50%}.large-margin-collapse>.medium-7{width:58.33333%}.large-margin-collapse>.medium-8{width:66.66667%}.large-margin-collapse>.medium-9{width:75%}.large-margin-collapse>.medium-10{width:83.33333%}.large-margin-collapse>.medium-11{width:91.66667%}.large-margin-collapse>.medium-12{width:100%}}@media print,screen and (min-width:64em){.large-margin-collapse>.large-1{width:8.33333%}.large-margin-collapse>.large-2{width:16.66667%}.large-margin-collapse>.large-3{width:25%}.large-margin-collapse>.large-4{width:33.33333%}.large-margin-collapse>.large-5{width:41.66667%}.large-margin-collapse>.large-6{width:50%}.large-margin-collapse>.large-7{width:58.33333%}.large-margin-collapse>.large-8{width:66.66667%}.large-margin-collapse>.large-9{width:75%}.large-margin-collapse>.large-10{width:83.33333%}.large-margin-collapse>.large-11{width:91.66667%}.large-margin-collapse>.large-12{width:100%}}@media print,screen and (min-width:64em){.large-padding-collapse{margin-left:0;margin-right:0}.large-padding-collapse>.cell{padding-left:0;padding-right:0}}.small-offset-0{margin-left:0}.grid-margin-x>.small-offset-0{margin-left:.625rem}.small-offset-1{margin-left:8.33333%}.grid-margin-x>.small-offset-1{margin-left:calc(8.33333% + .625rem)}.small-offset-2{margin-left:16.66667%}.grid-margin-x>.small-offset-2{margin-left:calc(16.66667% + .625rem)}.small-offset-3{margin-left:25%}.grid-margin-x>.small-offset-3{margin-left:calc(25% + .625rem)}.small-offset-4{margin-left:33.33333%}.grid-margin-x>.small-offset-4{margin-left:calc(33.33333% + .625rem)}.small-offset-5{margin-left:41.66667%}.grid-margin-x>.small-offset-5{margin-left:calc(41.66667% + .625rem)}.small-offset-6{margin-left:50%}.grid-margin-x>.small-offset-6{margin-left:calc(50% + .625rem)}.small-offset-7{margin-left:58.33333%}.grid-margin-x>.small-offset-7{margin-left:calc(58.33333% + .625rem)}.small-offset-8{margin-left:66.66667%}.grid-margin-x>.small-offset-8{margin-left:calc(66.66667% + .625rem)}.small-offset-9{margin-left:75%}.grid-margin-x>.small-offset-9{margin-left:calc(75% + .625rem)}.small-offset-10{margin-left:83.33333%}.grid-margin-x>.small-offset-10{margin-left:calc(83.33333% + .625rem)}.small-offset-11{margin-left:91.66667%}.grid-margin-x>.small-offset-11{margin-left:calc(91.66667% + .625rem)}@media print,screen and (min-width:40em){.medium-offset-0{margin-left:0}.grid-margin-x>.medium-offset-0{margin-left:.9375rem}.medium-offset-1{margin-left:8.33333%}.grid-margin-x>.medium-offset-1{margin-left:calc(8.33333% + .9375rem)}.medium-offset-2{margin-left:16.66667%}.grid-margin-x>.medium-offset-2{margin-left:calc(16.66667% + .9375rem)}.medium-offset-3{margin-left:25%}.grid-margin-x>.medium-offset-3{margin-left:calc(25% + .9375rem)}.medium-offset-4{margin-left:33.33333%}.grid-margin-x>.medium-offset-4{margin-left:calc(33.33333% + .9375rem)}.medium-offset-5{margin-left:41.66667%}.grid-margin-x>.medium-offset-5{margin-left:calc(41.66667% + .9375rem)}.medium-offset-6{margin-left:50%}.grid-margin-x>.medium-offset-6{margin-left:calc(50% + .9375rem)}.medium-offset-7{margin-left:58.33333%}.grid-margin-x>.medium-offset-7{margin-left:calc(58.33333% + .9375rem)}.medium-offset-8{margin-left:66.66667%}.grid-margin-x>.medium-offset-8{margin-left:calc(66.66667% + .9375rem)}.medium-offset-9{margin-left:75%}.grid-margin-x>.medium-offset-9{margin-left:calc(75% + .9375rem)}.medium-offset-10{margin-left:83.33333%}.grid-margin-x>.medium-offset-10{margin-left:calc(83.33333% + .9375rem)}.medium-offset-11{margin-left:91.66667%}.grid-margin-x>.medium-offset-11{margin-left:calc(91.66667% + .9375rem)}}@media print,screen and (min-width:64em){.large-offset-0{margin-left:0}.grid-margin-x>.large-offset-0{margin-left:.9375rem}.large-offset-1{margin-left:8.33333%}.grid-margin-x>.large-offset-1{margin-left:calc(8.33333% + .9375rem)}.large-offset-2{margin-left:16.66667%}.grid-margin-x>.large-offset-2{margin-left:calc(16.66667% + .9375rem)}.large-offset-3{margin-left:25%}.grid-margin-x>.large-offset-3{margin-left:calc(25% + .9375rem)}.large-offset-4{margin-left:33.33333%}.grid-margin-x>.large-offset-4{margin-left:calc(33.33333% + .9375rem)}.large-offset-5{margin-left:41.66667%}.grid-margin-x>.large-offset-5{margin-left:calc(41.66667% + .9375rem)}.large-offset-6{margin-left:50%}.grid-margin-x>.large-offset-6{margin-left:calc(50% + .9375rem)}.large-offset-7{margin-left:58.33333%}.grid-margin-x>.large-offset-7{margin-left:calc(58.33333% + .9375rem)}.large-offset-8{margin-left:66.66667%}.grid-margin-x>.large-offset-8{margin-left:calc(66.66667% + .9375rem)}.large-offset-9{margin-left:75%}.grid-margin-x>.large-offset-9{margin-left:calc(75% + .9375rem)}.large-offset-10{margin-left:83.33333%}.grid-margin-x>.large-offset-10{margin-left:calc(83.33333% + .9375rem)}.large-offset-11{margin-left:91.66667%}.grid-margin-x>.large-offset-11{margin-left:calc(91.66667% + .9375rem)}}.grid-y{-webkit-box-orient:vertical;-webkit-box-direction:normal;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-flow:column nowrap;-ms-flex-flow:column nowrap;flex-flow:column nowrap}.grid-y>.cell{height:auto;max-height:none}.grid-y>.auto{height:auto}.grid-y>.shrink{height:auto}.grid-y>.small-1,.grid-y>.small-2,.grid-y>.small-3,.grid-y>.small-4,.grid-y>.small-5,.grid-y>.small-6,.grid-y>.small-7,.grid-y>.small-8,.grid-y>.small-9,.grid-y>.small-10,.grid-y>.small-11,.grid-y>.small-12,.grid-y>.small-full,.grid-y>.small-shrink{-ms-flex-preferred-size:auto;-webkit-flex-basis:auto;flex-basis:auto}@media print,screen and (min-width:40em){.grid-y>.medium-1,.grid-y>.medium-2,.grid-y>.medium-3,.grid-y>.medium-4,.grid-y>.medium-5,.grid-y>.medium-6,.grid-y>.medium-7,.grid-y>.medium-8,.grid-y>.medium-9,.grid-y>.medium-10,.grid-y>.medium-11,.grid-y>.medium-12,.grid-y>.medium-full,.grid-y>.medium-shrink{-ms-flex-preferred-size:auto;-webkit-flex-basis:auto;flex-basis:auto}}@media print,screen and (min-width:64em){.grid-y>.large-1,.grid-y>.large-2,.grid-y>.large-3,.grid-y>.large-4,.grid-y>.large-5,.grid-y>.large-6,.grid-y>.large-7,.grid-y>.large-8,.grid-y>.large-9,.grid-y>.large-10,.grid-y>.large-11,.grid-y>.large-12,.grid-y>.large-full,.grid-y>.large-shrink{-ms-flex-preferred-size:auto;-webkit-flex-basis:auto;flex-basis:auto}}.grid-y>.small-1,.grid-y>.small-2,.grid-y>.small-3,.grid-y>.small-4,.grid-y>.small-5,.grid-y>.small-6,.grid-y>.small-7,.grid-y>.small-8,.grid-y>.small-9,.grid-y>.small-10,.grid-y>.small-11,.grid-y>.small-12{-webkit-box-flex:0;-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto}.grid-y>.small-1{height:8.33333%}.grid-y>.small-2{height:16.66667%}.grid-y>.small-3{height:25%}.grid-y>.small-4{height:33.33333%}.grid-y>.small-5{height:41.66667%}.grid-y>.small-6{height:50%}.grid-y>.small-7{height:58.33333%}.grid-y>.small-8{height:66.66667%}.grid-y>.small-9{height:75%}.grid-y>.small-10{height:83.33333%}.grid-y>.small-11{height:91.66667%}.grid-y>.small-12{height:100%}@media print,screen and (min-width:40em){.grid-y>.medium-auto{-webkit-box-flex:1;-webkit-flex:1 1 0;-ms-flex:1 1 0px;flex:1 1 0;height:auto}.grid-y>.medium-1,.grid-y>.medium-2,.grid-y>.medium-3,.grid-y>.medium-4,.grid-y>.medium-5,.grid-y>.medium-6,.grid-y>.medium-7,.grid-y>.medium-8,.grid-y>.medium-9,.grid-y>.medium-10,.grid-y>.medium-11,.grid-y>.medium-12,.grid-y>.medium-shrink{-webkit-box-flex:0;-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto}.grid-y>.medium-shrink{height:auto}.grid-y>.medium-1{height:8.33333%}.grid-y>.medium-2{height:16.66667%}.grid-y>.medium-3{height:25%}.grid-y>.medium-4{height:33.33333%}.grid-y>.medium-5{height:41.66667%}.grid-y>.medium-6{height:50%}.grid-y>.medium-7{height:58.33333%}.grid-y>.medium-8{height:66.66667%}.grid-y>.medium-9{height:75%}.grid-y>.medium-10{height:83.33333%}.grid-y>.medium-11{height:91.66667%}.grid-y>.medium-12{height:100%}}@media print,screen and (min-width:64em){.grid-y>.large-auto{-webkit-box-flex:1;-webkit-flex:1 1 0;-ms-flex:1 1 0px;flex:1 1 0;height:auto}.grid-y>.large-1,.grid-y>.large-2,.grid-y>.large-3,.grid-y>.large-4,.grid-y>.large-5,.grid-y>.large-6,.grid-y>.large-7,.grid-y>.large-8,.grid-y>.large-9,.grid-y>.large-10,.grid-y>.large-11,.grid-y>.large-12,.grid-y>.large-shrink{-webkit-box-flex:0;-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto}.grid-y>.large-shrink{height:auto}.grid-y>.large-1{height:8.33333%}.grid-y>.large-2{height:16.66667%}.grid-y>.large-3{height:25%}.grid-y>.large-4{height:33.33333%}.grid-y>.large-5{height:41.66667%}.grid-y>.large-6{height:50%}.grid-y>.large-7{height:58.33333%}.grid-y>.large-8{height:66.66667%}.grid-y>.large-9{height:75%}.grid-y>.large-10{height:83.33333%}.grid-y>.large-11{height:91.66667%}.grid-y>.large-12{height:100%}}.grid-padding-y .grid-padding-y{margin-bottom:-.625rem;margin-top:-.625rem}@media print,screen and (min-width:40em){.grid-padding-y .grid-padding-y{margin-bottom:-.9375rem;margin-top:-.9375rem}}.grid-padding-y>.cell{padding-bottom:.625rem;padding-top:.625rem}@media print,screen and (min-width:40em){.grid-padding-y>.cell{padding-bottom:.9375rem;padding-top:.9375rem}}.grid-frame{-webkit-box-align:stretch;-ms-flex-align:stretch;-webkit-align-items:stretch;align-items:stretch;-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap;overflow:hidden;position:relative;width:100vw}.cell .grid-frame{width:100%}.cell-block{max-width:100%;overflow-x:auto}.cell-block,.cell-block-y{-webkit-overflow-scrolling:touch;-ms-overflow-style:-ms-autohiding-scrollbar}.cell-block-y{max-height:100%;min-height:100%;overflow-y:auto}.cell-block-container{-webkit-box-orient:vertical;-webkit-box-direction:normal;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;max-height:100%}.cell-block-container>.grid-x{-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap;max-height:100%}@media print,screen and (min-width:40em){.medium-grid-frame{-webkit-box-align:stretch;-ms-flex-align:stretch;-webkit-align-items:stretch;align-items:stretch;-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap;overflow:hidden;position:relative;width:100vw}.cell .medium-grid-frame{width:100%}.medium-cell-block{-webkit-overflow-scrolling:touch;-ms-overflow-style:-ms-autohiding-scrollbar;max-width:100%;overflow-x:auto}.medium-cell-block-container{-webkit-box-orient:vertical;-webkit-box-direction:normal;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;max-height:100%}.medium-cell-block-container>.grid-x{-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap;max-height:100%}.medium-cell-block-y{-webkit-overflow-scrolling:touch;-ms-overflow-style:-ms-autohiding-scrollbar;max-height:100%;min-height:100%;overflow-y:auto}}@media print,screen and (min-width:64em){.large-grid-frame{-webkit-box-align:stretch;-ms-flex-align:stretch;-webkit-align-items:stretch;align-items:stretch;-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap;overflow:hidden;position:relative;width:100vw}.cell .large-grid-frame{width:100%}.large-cell-block{-webkit-overflow-scrolling:touch;-ms-overflow-style:-ms-autohiding-scrollbar;max-width:100%;overflow-x:auto}.large-cell-block-container{-webkit-box-orient:vertical;-webkit-box-direction:normal;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;max-height:100%}.large-cell-block-container>.grid-x{-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap;max-height:100%}.large-cell-block-y{-webkit-overflow-scrolling:touch;-ms-overflow-style:-ms-autohiding-scrollbar;max-height:100%;min-height:100%;overflow-y:auto}}.grid-y.grid-frame{-webkit-box-align:stretch;-ms-flex-align:stretch;-webkit-align-items:stretch;align-items:stretch;-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap;height:100vh;overflow:hidden;position:relative;width:auto}@media print,screen and (min-width:40em){.grid-y.medium-grid-frame{-webkit-box-align:stretch;-ms-flex-align:stretch;-webkit-align-items:stretch;align-items:stretch;-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap;height:100vh;overflow:hidden;position:relative;width:auto}}@media print,screen and (min-width:64em){.grid-y.large-grid-frame{-webkit-box-align:stretch;-ms-flex-align:stretch;-webkit-align-items:stretch;align-items:stretch;-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap;height:100vh;overflow:hidden;position:relative;width:auto}}.cell .grid-y.grid-frame{height:100%}@media print,screen and (min-width:40em){.cell .grid-y.medium-grid-frame{height:100%}}@media print,screen and (min-width:64em){.cell .grid-y.large-grid-frame{height:100%}}.grid-margin-y{margin-bottom:-.625rem;margin-top:-.625rem}@media print,screen and (min-width:40em){.grid-margin-y{margin-bottom:-.9375rem;margin-top:-.9375rem}}.grid-margin-y>.cell{height:calc(100% - 1.25rem);margin-bottom:.625rem;margin-top:.625rem}@media print,screen and (min-width:40em){.grid-margin-y>.cell{height:calc(100% - 1.875rem);margin-bottom:.9375rem;margin-top:.9375rem}}.grid-margin-y>.auto{height:auto}.grid-margin-y>.shrink{height:auto}.grid-margin-y>.small-1{height:calc(8.33333% - 1.25rem)}.grid-margin-y>.small-2{height:calc(16.66667% - 1.25rem)}.grid-margin-y>.small-3{height:calc(25% - 1.25rem)}.grid-margin-y>.small-4{height:calc(33.33333% - 1.25rem)}.grid-margin-y>.small-5{height:calc(41.66667% - 1.25rem)}.grid-margin-y>.small-6{height:calc(50% - 1.25rem)}.grid-margin-y>.small-7{height:calc(58.33333% - 1.25rem)}.grid-margin-y>.small-8{height:calc(66.66667% - 1.25rem)}.grid-margin-y>.small-9{height:calc(75% - 1.25rem)}.grid-margin-y>.small-10{height:calc(83.33333% - 1.25rem)}.grid-margin-y>.small-11{height:calc(91.66667% - 1.25rem)}.grid-margin-y>.small-12{height:calc(100% - 1.25rem)}@media print,screen and (min-width:40em){.grid-margin-y>.auto{height:auto}.grid-margin-y>.shrink{height:auto}.grid-margin-y>.small-1{height:calc(8.33333% - 1.875rem)}.grid-margin-y>.small-2{height:calc(16.66667% - 1.875rem)}.grid-margin-y>.small-3{height:calc(25% - 1.875rem)}.grid-margin-y>.small-4{height:calc(33.33333% - 1.875rem)}.grid-margin-y>.small-5{height:calc(41.66667% - 1.875rem)}.grid-margin-y>.small-6{height:calc(50% - 1.875rem)}.grid-margin-y>.small-7{height:calc(58.33333% - 1.875rem)}.grid-margin-y>.small-8{height:calc(66.66667% - 1.875rem)}.grid-margin-y>.small-9{height:calc(75% - 1.875rem)}.grid-margin-y>.small-10{height:calc(83.33333% - 1.875rem)}.grid-margin-y>.small-11{height:calc(91.66667% - 1.875rem)}.grid-margin-y>.small-12{height:calc(100% - 1.875rem)}.grid-margin-y>.medium-auto{height:auto}.grid-margin-y>.medium-shrink{height:auto}.grid-margin-y>.medium-1{height:calc(8.33333% - 1.875rem)}.grid-margin-y>.medium-2{height:calc(16.66667% - 1.875rem)}.grid-margin-y>.medium-3{height:calc(25% - 1.875rem)}.grid-margin-y>.medium-4{height:calc(33.33333% - 1.875rem)}.grid-margin-y>.medium-5{height:calc(41.66667% - 1.875rem)}.grid-margin-y>.medium-6{height:calc(50% - 1.875rem)}.grid-margin-y>.medium-7{height:calc(58.33333% - 1.875rem)}.grid-margin-y>.medium-8{height:calc(66.66667% - 1.875rem)}.grid-margin-y>.medium-9{height:calc(75% - 1.875rem)}.grid-margin-y>.medium-10{height:calc(83.33333% - 1.875rem)}.grid-margin-y>.medium-11{height:calc(91.66667% - 1.875rem)}.grid-margin-y>.medium-12{height:calc(100% - 1.875rem)}}@media print,screen and (min-width:64em){.grid-margin-y>.large-auto{height:auto}.grid-margin-y>.large-shrink{height:auto}.grid-margin-y>.large-1{height:calc(8.33333% - 1.875rem)}.grid-margin-y>.large-2{height:calc(16.66667% - 1.875rem)}.grid-margin-y>.large-3{height:calc(25% - 1.875rem)}.grid-margin-y>.large-4{height:calc(33.33333% - 1.875rem)}.grid-margin-y>.large-5{height:calc(41.66667% - 1.875rem)}.grid-margin-y>.large-6{height:calc(50% - 1.875rem)}.grid-margin-y>.large-7{height:calc(58.33333% - 1.875rem)}.grid-margin-y>.large-8{height:calc(66.66667% - 1.875rem)}.grid-margin-y>.large-9{height:calc(75% - 1.875rem)}.grid-margin-y>.large-10{height:calc(83.33333% - 1.875rem)}.grid-margin-y>.large-11{height:calc(91.66667% - 1.875rem)}.grid-margin-y>.large-12{height:calc(100% - 1.875rem)}}.grid-frame.grid-margin-y{height:calc(100vh + 1.25rem)}@media print,screen and (min-width:40em){.grid-frame.grid-margin-y{height:calc(100vh + 1.875rem)}}@media print,screen and (min-width:64em){.grid-frame.grid-margin-y{height:calc(100vh + 1.875rem)}}@media print,screen and (min-width:40em){.grid-margin-y.medium-grid-frame{height:calc(100vh + 1.875rem)}}@media print,screen and (min-width:64em){.grid-margin-y.large-grid-frame{height:calc(100vh + 1.875rem)}}.button{-webkit-appearance:none;border:1px solid transparent;border-radius:0;cursor:pointer;display:inline-block;font-family:inherit;font-size:.9rem;line-height:1;margin:0 0 1rem;padding:.85em 1em;text-align:center;-webkit-transition:background-color .25s ease-out,color .25s ease-out;transition:background-color .25s ease-out,color .25s ease-out;vertical-align:middle}[data-whatinput=mouse] .button{outline:0}.button.tiny{font-size:.6rem}.button.small{font-size:.75rem}.button.large{font-size:1.25rem}.button.expanded{display:block;margin-left:0;margin-right:0;width:100%}.button,.button.disabled,.button.disabled:focus,.button.disabled:hover,.button[disabled],.button[disabled]:focus,.button[disabled]:hover{background-color:#1779ba;color:#fefefe}.button:focus,.button:hover{background-color:#14679e;color:#fefefe}.button.primary,.button.primary.disabled,.button.primary.disabled:focus,.button.primary.disabled:hover,.button.primary[disabled],.button.primary[disabled]:focus,.button.primary[disabled]:hover{background-color:#1779ba;color:#fefefe}.button.primary:focus,.button.primary:hover{background-color:#126195;color:#fefefe}.button.secondary,.button.secondary.disabled,.button.secondary.disabled:focus,.button.secondary.disabled:hover,.button.secondary[disabled],.button.secondary[disabled]:focus,.button.secondary[disabled]:hover{background-color:#767676;color:#fefefe}.button.secondary:focus,.button.secondary:hover{background-color:#5e5e5e;color:#fefefe}.button.success,.button.success.disabled,.button.success.disabled:focus,.button.success.disabled:hover,.button.success[disabled],.button.success[disabled]:focus,.button.success[disabled]:hover{background-color:#3adb76;color:#0a0a0a}.button.success:focus,.button.success:hover{background-color:#22bb5b;color:#0a0a0a}.button.warning,.button.warning.disabled,.button.warning.disabled:focus,.button.warning.disabled:hover,.button.warning[disabled],.button.warning[disabled]:focus,.button.warning[disabled]:hover{background-color:#ffae00;color:#0a0a0a}.button.warning:focus,.button.warning:hover{background-color:#cc8b00;color:#0a0a0a}.button.alert,.button.alert.disabled,.button.alert.disabled:focus,.button.alert.disabled:hover,.button.alert[disabled],.button.alert[disabled]:focus,.button.alert[disabled]:hover{background-color:#cc4b37;color:#fefefe}.button.alert:focus,.button.alert:hover{background-color:#a53b2a;color:#fefefe}.button.hollow,.button.hollow.disabled,.button.hollow.disabled:focus,.button.hollow.disabled:hover,.button.hollow:focus,.button.hollow:hover,.button.hollow[disabled],.button.hollow[disabled]:focus,.button.hollow[disabled]:hover{background-color:transparent}.button.hollow,.button.hollow.disabled,.button.hollow.disabled:focus,.button.hollow.disabled:hover,.button.hollow[disabled],.button.hollow[disabled]:focus,.button.hollow[disabled]:hover{border:1px solid #1779ba;color:#1779ba}.button.hollow:focus,.button.hollow:hover{border-color:#0c3d5d;color:#0c3d5d}.button.hollow.primary,.button.hollow.primary.disabled,.button.hollow.primary.disabled:focus,.button.hollow.primary.disabled:hover,.button.hollow.primary[disabled],.button.hollow.primary[disabled]:focus,.button.hollow.primary[disabled]:hover{border:1px solid #1779ba;color:#1779ba}.button.hollow.primary:focus,.button.hollow.primary:hover{border-color:#0c3d5d;color:#0c3d5d}.button.hollow.secondary,.button.hollow.secondary.disabled,.button.hollow.secondary.disabled:focus,.button.hollow.secondary.disabled:hover,.button.hollow.secondary[disabled],.button.hollow.secondary[disabled]:focus,.button.hollow.secondary[disabled]:hover{border:1px solid #767676;color:#767676}.button.hollow.secondary:focus,.button.hollow.secondary:hover{border-color:#3b3b3b;color:#3b3b3b}.button.hollow.success,.button.hollow.success.disabled,.button.hollow.success.disabled:focus,.button.hollow.success.disabled:hover,.button.hollow.success[disabled],.button.hollow.success[disabled]:focus,.button.hollow.success[disabled]:hover{border:1px solid #3adb76;color:#3adb76}.button.hollow.success:focus,.button.hollow.success:hover{border-color:#157539;color:#157539}.button.hollow.warning,.button.hollow.warning.disabled,.button.hollow.warning.disabled:focus,.button.hollow.warning.disabled:hover,.button.hollow.warning[disabled],.button.hollow.warning[disabled]:focus,.button.hollow.warning[disabled]:hover{border:1px solid #ffae00;color:#ffae00}.button.hollow.warning:focus,.button.hollow.warning:hover{border-color:#805700;color:#805700}.button.hollow.alert,.button.hollow.alert.disabled,.button.hollow.alert.disabled:focus,.button.hollow.alert.disabled:hover,.button.hollow.alert[disabled],.button.hollow.alert[disabled]:focus,.button.hollow.alert[disabled]:hover{border:1px solid #cc4b37;color:#cc4b37}.button.hollow.alert:focus,.button.hollow.alert:hover{border-color:#67251a;color:#67251a}.button.clear,.button.clear.disabled,.button.clear.disabled:focus,.button.clear.disabled:hover,.button.clear:focus,.button.clear:hover,.button.clear[disabled],.button.clear[disabled]:focus,.button.clear[disabled]:hover{background-color:transparent;border-color:transparent}.button.clear,.button.clear.disabled,.button.clear.disabled:focus,.button.clear.disabled:hover,.button.clear[disabled],.button.clear[disabled]:focus,.button.clear[disabled]:hover{color:#1779ba}.button.clear:focus,.button.clear:hover{color:#0c3d5d}.button.clear.primary,.button.clear.primary.disabled,.button.clear.primary.disabled:focus,.button.clear.primary.disabled:hover,.button.clear.primary[disabled],.button.clear.primary[disabled]:focus,.button.clear.primary[disabled]:hover{color:#1779ba}.button.clear.primary:focus,.button.clear.primary:hover{color:#0c3d5d}.button.clear.secondary,.button.clear.secondary.disabled,.button.clear.secondary.disabled:focus,.button.clear.secondary.disabled:hover,.button.clear.secondary[disabled],.button.clear.secondary[disabled]:focus,.button.clear.secondary[disabled]:hover{color:#767676}.button.clear.secondary:focus,.button.clear.secondary:hover{color:#3b3b3b}.button.clear.success,.button.clear.success.disabled,.button.clear.success.disabled:focus,.button.clear.success.disabled:hover,.button.clear.success[disabled],.button.clear.success[disabled]:focus,.button.clear.success[disabled]:hover{color:#3adb76}.button.clear.success:focus,.button.clear.success:hover{color:#157539}.button.clear.warning,.button.clear.warning.disabled,.button.clear.warning.disabled:focus,.button.clear.warning.disabled:hover,.button.clear.warning[disabled],.button.clear.warning[disabled]:focus,.button.clear.warning[disabled]:hover{color:#ffae00}.button.clear.warning:focus,.button.clear.warning:hover{color:#805700}.button.clear.alert,.button.clear.alert.disabled,.button.clear.alert.disabled:focus,.button.clear.alert.disabled:hover,.button.clear.alert[disabled],.button.clear.alert[disabled]:focus,.button.clear.alert[disabled]:hover{color:#cc4b37}.button.clear.alert:focus,.button.clear.alert:hover{color:#67251a}.button.disabled,.button[disabled]{cursor:not-allowed;opacity:.25}.button.dropdown:after{border-color:#fefefe transparent transparent;border-style:solid;border-width:.4em .4em 0;content:"";display:block;display:inline-block;float:right;height:0;margin-left:1em;position:relative;top:.4em;width:0}.button.dropdown.clear:after,.button.dropdown.hollow:after{border-top-color:#1779ba}.button.dropdown.clear.primary:after,.button.dropdown.hollow.primary:after{border-top-color:#1779ba}.button.dropdown.clear.secondary:after,.button.dropdown.hollow.secondary:after{border-top-color:#767676}.button.dropdown.clear.success:after,.button.dropdown.hollow.success:after{border-top-color:#3adb76}.button.dropdown.clear.warning:after,.button.dropdown.hollow.warning:after{border-top-color:#ffae00}.button.dropdown.clear.alert:after,.button.dropdown.hollow.alert:after{border-top-color:#cc4b37}.button.arrow-only:after{float:none;margin-left:0;top:-.1em}a.button:focus,a.button:hover{text-decoration:none}.button-group{-webkit-box-align:stretch;-ms-flex-align:stretch;-webkit-box-flex:1;-ms-flex-positive:1;-webkit-align-items:stretch;align-items:stretch;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-grow:1;flex-grow:1;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;margin-bottom:1rem}.button-group:after,.button-group:before{-ms-flex-preferred-size:0;-webkit-box-ordinal-group:2;-ms-flex-order:1;content:" ";display:table;-webkit-flex-basis:0;flex-basis:0;-webkit-order:1;order:1}.button-group:after{clear:both}.button-group:after,.button-group:before{display:none}.button-group .button{-webkit-box-flex:0;-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto;font-size:.9rem;margin:0 1px 1px 0}.button-group .button:last-child{margin-right:0}.button-group.tiny .button{font-size:.6rem}.button-group.small .button{font-size:.75rem}.button-group.large .button{font-size:1.25rem}.button-group.expanded .button{-webkit-box-flex:1;-webkit-flex:1 1 0px;-ms-flex:1 1 0px;flex:1 1 0px}.button-group.primary .button,.button-group.primary .button.disabled,.button-group.primary .button.disabled:focus,.button-group.primary .button.disabled:hover,.button-group.primary .button[disabled],.button-group.primary .button[disabled]:focus,.button-group.primary .button[disabled]:hover{background-color:#1779ba;color:#fefefe}.button-group.primary .button:focus,.button-group.primary .button:hover{background-color:#126195;color:#fefefe}.button-group.secondary .button,.button-group.secondary .button.disabled,.button-group.secondary .button.disabled:focus,.button-group.secondary .button.disabled:hover,.button-group.secondary .button[disabled],.button-group.secondary .button[disabled]:focus,.button-group.secondary .button[disabled]:hover{background-color:#767676;color:#fefefe}.button-group.secondary .button:focus,.button-group.secondary .button:hover{background-color:#5e5e5e;color:#fefefe}.button-group.success .button,.button-group.success .button.disabled,.button-group.success .button.disabled:focus,.button-group.success .button.disabled:hover,.button-group.success .button[disabled],.button-group.success .button[disabled]:focus,.button-group.success .button[disabled]:hover{background-color:#3adb76;color:#0a0a0a}.button-group.success .button:focus,.button-group.success .button:hover{background-color:#22bb5b;color:#0a0a0a}.button-group.warning .button,.button-group.warning .button.disabled,.button-group.warning .button.disabled:focus,.button-group.warning .button.disabled:hover,.button-group.warning .button[disabled],.button-group.warning .button[disabled]:focus,.button-group.warning .button[disabled]:hover{background-color:#ffae00;color:#0a0a0a}.button-group.warning .button:focus,.button-group.warning .button:hover{background-color:#cc8b00;color:#0a0a0a}.button-group.alert .button,.button-group.alert .button.disabled,.button-group.alert .button.disabled:focus,.button-group.alert .button.disabled:hover,.button-group.alert .button[disabled],.button-group.alert .button[disabled]:focus,.button-group.alert .button[disabled]:hover{background-color:#cc4b37;color:#fefefe}.button-group.alert .button:focus,.button-group.alert .button:hover{background-color:#a53b2a;color:#fefefe}.button-group.hollow .button,.button-group.hollow .button.disabled,.button-group.hollow .button.disabled:focus,.button-group.hollow .button.disabled:hover,.button-group.hollow .button:focus,.button-group.hollow .button:hover,.button-group.hollow .button[disabled],.button-group.hollow .button[disabled]:focus,.button-group.hollow .button[disabled]:hover{background-color:transparent}.button-group.hollow .button,.button-group.hollow .button.disabled,.button-group.hollow .button.disabled:focus,.button-group.hollow .button.disabled:hover,.button-group.hollow .button[disabled],.button-group.hollow .button[disabled]:focus,.button-group.hollow .button[disabled]:hover{border:1px solid #1779ba;color:#1779ba}.button-group.hollow .button:focus,.button-group.hollow .button:hover{border-color:#0c3d5d;color:#0c3d5d}.button-group.hollow .button.primary,.button-group.hollow .button.primary.disabled,.button-group.hollow .button.primary.disabled:focus,.button-group.hollow .button.primary.disabled:hover,.button-group.hollow .button.primary[disabled],.button-group.hollow .button.primary[disabled]:focus,.button-group.hollow .button.primary[disabled]:hover,.button-group.hollow.primary .button,.button-group.hollow.primary .button.disabled,.button-group.hollow.primary .button.disabled:focus,.button-group.hollow.primary .button.disabled:hover,.button-group.hollow.primary .button[disabled],.button-group.hollow.primary .button[disabled]:focus,.button-group.hollow.primary .button[disabled]:hover{border:1px solid #1779ba;color:#1779ba}.button-group.hollow .button.primary:focus,.button-group.hollow .button.primary:hover,.button-group.hollow.primary .button:focus,.button-group.hollow.primary .button:hover{border-color:#0c3d5d;color:#0c3d5d}.button-group.hollow .button.secondary,.button-group.hollow .button.secondary.disabled,.button-group.hollow .button.secondary.disabled:focus,.button-group.hollow .button.secondary.disabled:hover,.button-group.hollow .button.secondary[disabled],.button-group.hollow .button.secondary[disabled]:focus,.button-group.hollow .button.secondary[disabled]:hover,.button-group.hollow.secondary .button,.button-group.hollow.secondary .button.disabled,.button-group.hollow.secondary .button.disabled:focus,.button-group.hollow.secondary .button.disabled:hover,.button-group.hollow.secondary .button[disabled],.button-group.hollow.secondary .button[disabled]:focus,.button-group.hollow.secondary .button[disabled]:hover{border:1px solid #767676;color:#767676}.button-group.hollow .button.secondary:focus,.button-group.hollow .button.secondary:hover,.button-group.hollow.secondary .button:focus,.button-group.hollow.secondary .button:hover{border-color:#3b3b3b;color:#3b3b3b}.button-group.hollow .button.success,.button-group.hollow .button.success.disabled,.button-group.hollow .button.success.disabled:focus,.button-group.hollow .button.success.disabled:hover,.button-group.hollow .button.success[disabled],.button-group.hollow .button.success[disabled]:focus,.button-group.hollow .button.success[disabled]:hover,.button-group.hollow.success .button,.button-group.hollow.success .button.disabled,.button-group.hollow.success .button.disabled:focus,.button-group.hollow.success .button.disabled:hover,.button-group.hollow.success .button[disabled],.button-group.hollow.success .button[disabled]:focus,.button-group.hollow.success .button[disabled]:hover{border:1px solid #3adb76;color:#3adb76}.button-group.hollow .button.success:focus,.button-group.hollow .button.success:hover,.button-group.hollow.success .button:focus,.button-group.hollow.success .button:hover{border-color:#157539;color:#157539}.button-group.hollow .button.warning,.button-group.hollow .button.warning.disabled,.button-group.hollow .button.warning.disabled:focus,.button-group.hollow .button.warning.disabled:hover,.button-group.hollow .button.warning[disabled],.button-group.hollow .button.warning[disabled]:focus,.button-group.hollow .button.warning[disabled]:hover,.button-group.hollow.warning .button,.button-group.hollow.warning .button.disabled,.button-group.hollow.warning .button.disabled:focus,.button-group.hollow.warning .button.disabled:hover,.button-group.hollow.warning .button[disabled],.button-group.hollow.warning .button[disabled]:focus,.button-group.hollow.warning .button[disabled]:hover{border:1px solid #ffae00;color:#ffae00}.button-group.hollow .button.warning:focus,.button-group.hollow .button.warning:hover,.button-group.hollow.warning .button:focus,.button-group.hollow.warning .button:hover{border-color:#805700;color:#805700}.button-group.hollow.alert .button,.button-group.hollow.alert .button.disabled,.button-group.hollow.alert .button.disabled:focus,.button-group.hollow.alert .button.disabled:hover,.button-group.hollow.alert .button[disabled],.button-group.hollow.alert .button[disabled]:focus,.button-group.hollow.alert .button[disabled]:hover,.button-group.hollow .button.alert,.button-group.hollow .button.alert.disabled,.button-group.hollow .button.alert.disabled:focus,.button-group.hollow .button.alert.disabled:hover,.button-group.hollow .button.alert[disabled],.button-group.hollow .button.alert[disabled]:focus,.button-group.hollow .button.alert[disabled]:hover{border:1px solid #cc4b37;color:#cc4b37}.button-group.hollow.alert .button:focus,.button-group.hollow.alert .button:hover,.button-group.hollow .button.alert:focus,.button-group.hollow .button.alert:hover{border-color:#67251a;color:#67251a}.button-group.clear .button,.button-group.clear .button.disabled,.button-group.clear .button.disabled:focus,.button-group.clear .button.disabled:hover,.button-group.clear .button:focus,.button-group.clear .button:hover,.button-group.clear .button[disabled],.button-group.clear .button[disabled]:focus,.button-group.clear .button[disabled]:hover{background-color:transparent;border-color:transparent}.button-group.clear .button,.button-group.clear .button.disabled,.button-group.clear .button.disabled:focus,.button-group.clear .button.disabled:hover,.button-group.clear .button[disabled],.button-group.clear .button[disabled]:focus,.button-group.clear .button[disabled]:hover{color:#1779ba}.button-group.clear .button:focus,.button-group.clear .button:hover{color:#0c3d5d}.button-group.clear .button.primary,.button-group.clear .button.primary.disabled,.button-group.clear .button.primary.disabled:focus,.button-group.clear .button.primary.disabled:hover,.button-group.clear .button.primary[disabled],.button-group.clear .button.primary[disabled]:focus,.button-group.clear .button.primary[disabled]:hover,.button-group.clear.primary .button,.button-group.clear.primary .button.disabled,.button-group.clear.primary .button.disabled:focus,.button-group.clear.primary .button.disabled:hover,.button-group.clear.primary .button[disabled],.button-group.clear.primary .button[disabled]:focus,.button-group.clear.primary .button[disabled]:hover{color:#1779ba}.button-group.clear .button.primary:focus,.button-group.clear .button.primary:hover,.button-group.clear.primary .button:focus,.button-group.clear.primary .button:hover{color:#0c3d5d}.button-group.clear .button.secondary,.button-group.clear .button.secondary.disabled,.button-group.clear .button.secondary.disabled:focus,.button-group.clear .button.secondary.disabled:hover,.button-group.clear .button.secondary[disabled],.button-group.clear .button.secondary[disabled]:focus,.button-group.clear .button.secondary[disabled]:hover,.button-group.clear.secondary .button,.button-group.clear.secondary .button.disabled,.button-group.clear.secondary .button.disabled:focus,.button-group.clear.secondary .button.disabled:hover,.button-group.clear.secondary .button[disabled],.button-group.clear.secondary .button[disabled]:focus,.button-group.clear.secondary .button[disabled]:hover{color:#767676}.button-group.clear .button.secondary:focus,.button-group.clear .button.secondary:hover,.button-group.clear.secondary .button:focus,.button-group.clear.secondary .button:hover{color:#3b3b3b}.button-group.clear .button.success,.button-group.clear .button.success.disabled,.button-group.clear .button.success.disabled:focus,.button-group.clear .button.success.disabled:hover,.button-group.clear .button.success[disabled],.button-group.clear .button.success[disabled]:focus,.button-group.clear .button.success[disabled]:hover,.button-group.clear.success .button,.button-group.clear.success .button.disabled,.button-group.clear.success .button.disabled:focus,.button-group.clear.success .button.disabled:hover,.button-group.clear.success .button[disabled],.button-group.clear.success .button[disabled]:focus,.button-group.clear.success .button[disabled]:hover{color:#3adb76}.button-group.clear .button.success:focus,.button-group.clear .button.success:hover,.button-group.clear.success .button:focus,.button-group.clear.success .button:hover{color:#157539}.button-group.clear .button.warning,.button-group.clear .button.warning.disabled,.button-group.clear .button.warning.disabled:focus,.button-group.clear .button.warning.disabled:hover,.button-group.clear .button.warning[disabled],.button-group.clear .button.warning[disabled]:focus,.button-group.clear .button.warning[disabled]:hover,.button-group.clear.warning .button,.button-group.clear.warning .button.disabled,.button-group.clear.warning .button.disabled:focus,.button-group.clear.warning .button.disabled:hover,.button-group.clear.warning .button[disabled],.button-group.clear.warning .button[disabled]:focus,.button-group.clear.warning .button[disabled]:hover{color:#ffae00}.button-group.clear .button.warning:focus,.button-group.clear .button.warning:hover,.button-group.clear.warning .button:focus,.button-group.clear.warning .button:hover{color:#805700}.button-group.clear.alert .button,.button-group.clear.alert .button.disabled,.button-group.clear.alert .button.disabled:focus,.button-group.clear.alert .button.disabled:hover,.button-group.clear.alert .button[disabled],.button-group.clear.alert .button[disabled]:focus,.button-group.clear.alert .button[disabled]:hover,.button-group.clear .button.alert,.button-group.clear .button.alert.disabled,.button-group.clear .button.alert.disabled:focus,.button-group.clear .button.alert.disabled:hover,.button-group.clear .button.alert[disabled],.button-group.clear .button.alert[disabled]:focus,.button-group.clear .button.alert[disabled]:hover{color:#cc4b37}.button-group.clear.alert .button:focus,.button-group.clear.alert .button:hover,.button-group.clear .button.alert:focus,.button-group.clear .button.alert:hover{color:#67251a}.button-group.no-gaps .button{margin-right:-.0625rem}.button-group.no-gaps .button+.button{border-left-color:transparent}.button-group.stacked,.button-group.stacked-for-medium,.button-group.stacked-for-small{-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap}.button-group.stacked-for-medium .button,.button-group.stacked-for-small .button,.button-group.stacked .button{-webkit-box-flex:0;-webkit-flex:0 0 100%;-ms-flex:0 0 100%;flex:0 0 100%}.button-group.stacked-for-medium .button:last-child,.button-group.stacked-for-small .button:last-child,.button-group.stacked .button:last-child{margin-bottom:0}.button-group.stacked-for-medium.expanded .button,.button-group.stacked-for-small.expanded .button,.button-group.stacked.expanded .button{-webkit-box-flex:1;-webkit-flex:1 1 0px;-ms-flex:1 1 0px;flex:1 1 0px}@media print,screen and (min-width:40em){.button-group.stacked-for-small .button{-webkit-box-flex:0;-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto;margin-bottom:0}}@media print,screen and (min-width:64em){.button-group.stacked-for-medium .button{-webkit-box-flex:0;-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto;margin-bottom:0}}@media print,screen and (max-width:39.99875em){.button-group.stacked-for-small.expanded{display:block}.button-group.stacked-for-small.expanded .button{display:block;margin-right:0}}@media print,screen and (max-width:63.99875em){.button-group.stacked-for-medium.expanded{display:block}.button-group.stacked-for-medium.expanded .button{display:block;margin-right:0}}.close-button{color:#8a8a8a;cursor:pointer;position:absolute;z-index:10}[data-whatinput=mouse] .close-button{outline:0}.close-button:focus,.close-button:hover{color:#0a0a0a}.close-button.small{font-size:1.5em;line-height:1;right:.66rem;top:.33em}.close-button,.close-button.medium{font-size:2em;line-height:1;right:1rem;top:.5rem}.label{border-radius:0;cursor:default;display:inline-block;font-size:.8rem;line-height:1;padding:.33333rem .5rem;white-space:nowrap}.label,.label.primary{background:#1779ba;color:#fefefe}.label.secondary{background:#767676;color:#fefefe}.label.success{background:#3adb76;color:#0a0a0a}.label.warning{background:#ffae00;color:#0a0a0a}.label.alert{background:#cc4b37;color:#fefefe}.progress{background-color:#cacaca;border-radius:0;height:1rem;margin-bottom:1rem}.progress.primary .progress-meter{background-color:#1779ba}.progress.secondary .progress-meter{background-color:#767676}.progress.success .progress-meter{background-color:#3adb76}.progress.warning .progress-meter{background-color:#ffae00}.progress.alert .progress-meter{background-color:#cc4b37}.progress-meter{background-color:#1779ba;display:block;height:100%;position:relative;width:0}.progress-meter-text{color:#fefefe;font-size:.75rem;font-weight:700;left:50%;margin:0;position:absolute;top:50%;-webkit-transform:translate(-50%,-50%);-ms-transform:translate(-50%,-50%);transform:translate(-50%,-50%);white-space:nowrap}.slider{background-color:#e6e6e6;cursor:pointer;height:.5rem;margin-bottom:2.25rem;margin-top:1.25rem;position:relative;-ms-touch-action:none;touch-action:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.slider-fill{background-color:#cacaca;display:inline-block;height:.5rem;left:0;max-width:100%;position:absolute;top:0;-webkit-transition:all .2s ease-in-out;transition:all .2s ease-in-out}.slider-fill.is-dragging{-webkit-transition:all 0s linear;transition:all 0s linear}.slider-handle{background-color:#1779ba;border-radius:0;cursor:-webkit-grab;cursor:grab;display:inline-block;height:1.4rem;left:0;position:absolute;top:50%;-ms-touch-action:manipulation;touch-action:manipulation;-webkit-transform:translateY(-50%);-ms-transform:translateY(-50%);transform:translateY(-50%);-webkit-transition:all .2s ease-in-out;transition:all .2s ease-in-out;width:1.4rem;z-index:1}[data-whatinput=mouse] .slider-handle{outline:0}.slider-handle:hover{background-color:#14679e}.slider-handle.is-dragging{cursor:-webkit-grabbing;cursor:grabbing;-webkit-transition:all 0s linear;transition:all 0s linear}.slider.disabled,.slider[disabled]{cursor:not-allowed;opacity:.25}.slider.vertical{display:inline-block;height:12.5rem;margin:0 1.25rem;-webkit-transform:scaleY(-1);-ms-transform:scaleY(-1);transform:scaleY(-1);width:.5rem}.slider.vertical .slider-fill{max-height:100%;top:0;width:.5rem}.slider.vertical .slider-handle{height:1.4rem;left:50%;position:absolute;top:0;-webkit-transform:translateX(-50%);-ms-transform:translateX(-50%);transform:translateX(-50%);width:1.4rem}.switch{color:#fefefe;font-size:.875rem;font-weight:700;height:2rem;margin-bottom:1rem;outline:0;position:relative;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.switch-input{margin-bottom:0;opacity:0;position:absolute}.switch-paddle{background:#cacaca;border-radius:0;color:inherit;cursor:pointer;display:block;font-weight:inherit;height:2rem;position:relative;-webkit-transition:all .25s ease-out;transition:all .25s ease-out;width:4rem}input+.switch-paddle{margin:0}.switch-paddle:after{background:#fefefe;border-radius:0;content:"";display:block;height:1.5rem;left:.25rem;position:absolute;top:.25rem;-webkit-transform:translateZ(0);transform:translateZ(0);-webkit-transition:all .25s ease-out;transition:all .25s ease-out;width:1.5rem}input:checked~.switch-paddle{background:#1779ba}input:checked~.switch-paddle:after{left:2.25rem}input:disabled~.switch-paddle{cursor:not-allowed;opacity:.5}[data-whatinput=mouse] input:focus~.switch-paddle{outline:0}.switch-active,.switch-inactive{position:absolute;top:50%;-webkit-transform:translateY(-50%);-ms-transform:translateY(-50%);transform:translateY(-50%)}.switch-active{display:none;left:8%}input:checked+label>.switch-active{display:block}.switch-inactive{right:15%}input:checked+label>.switch-inactive{display:none}.switch.tiny{height:1.5rem}.switch.tiny .switch-paddle{font-size:.625rem;height:1.5rem;width:3rem}.switch.tiny .switch-paddle:after{height:1rem;left:.25rem;top:.25rem;width:1rem}.switch.tiny input:checked~.switch-paddle:after{left:1.75rem}.switch.small{height:1.75rem}.switch.small .switch-paddle{font-size:.75rem;height:1.75rem;width:3.5rem}.switch.small .switch-paddle:after{height:1.25rem;left:.25rem;top:.25rem;width:1.25rem}.switch.small input:checked~.switch-paddle:after{left:2rem}.switch.large{height:2.5rem}.switch.large .switch-paddle{font-size:1rem;height:2.5rem;width:5rem}.switch.large .switch-paddle:after{height:2rem;left:.25rem;top:.25rem;width:2rem}.switch.large input:checked~.switch-paddle:after{left:2.75rem}table{border-collapse:collapse;border-radius:0;margin-bottom:1rem;width:100%}tbody,tfoot,thead{background-color:#fefefe;border:1px solid #f1f1f1}caption{font-weight:700;padding:.5rem .625rem .625rem}thead{background:#f8f8f8}tfoot,thead{color:#0a0a0a}tfoot{background:#f1f1f1}tfoot tr,thead tr{background:0 0}tfoot td,tfoot th,thead td,thead th{font-weight:700;padding:.5rem .625rem .625rem;text-align:left}tbody td,tbody th{padding:.5rem .625rem .625rem}tbody tr:nth-child(2n){background-color:#f1f1f1;border-bottom:0}table.unstriped tbody{background-color:#fefefe}table.unstriped tbody tr{background-color:#fefefe;border-bottom:1px solid #f1f1f1}@media print,screen and (max-width:63.99875em){table.stack tfoot,table.stack thead{display:none}table.stack td,table.stack th,table.stack tr{display:block}table.stack td{border-top:0}}table.scroll{display:block;overflow-x:auto;width:100%}table.hover thead tr:hover{background-color:#f3f3f3}table.hover tfoot tr:hover{background-color:#ececec}table.hover tbody tr:hover{background-color:#f9f9f9}table.hover:not(.unstriped) tr:nth-of-type(2n):hover{background-color:#ececec}.table-scroll{overflow-x:auto}.badge{border-radius:50%;display:inline-block;font-size:.6rem;min-width:2.1em;padding:.3em;text-align:center}.badge,.badge.primary{background:#1779ba;color:#fefefe}.badge.secondary{background:#767676;color:#fefefe}.badge.success{background:#3adb76;color:#0a0a0a}.badge.warning{background:#ffae00;color:#0a0a0a}.badge.alert{background:#cc4b37;color:#fefefe}.breadcrumbs{list-style:none;margin:0 0 1rem}.breadcrumbs:after,.breadcrumbs:before{-ms-flex-preferred-size:0;-webkit-box-ordinal-group:2;-ms-flex-order:1;content:" ";display:table;-webkit-flex-basis:0;flex-basis:0;-webkit-order:1;order:1}.breadcrumbs:after{clear:both}.breadcrumbs li{color:#0a0a0a;cursor:default;float:left;font-size:.6875rem;text-transform:uppercase}.breadcrumbs li:not(:last-child):after{color:#cacaca;content:"/";margin:0 .75rem;opacity:1;position:relative}.breadcrumbs a{color:#1779ba}.breadcrumbs a:hover{text-decoration:underline}.breadcrumbs .disabled{color:#cacaca;cursor:not-allowed}.callout{background-color:#fff;border:1px solid hsla(0,0%,4%,.25);border-radius:0;color:#0a0a0a;margin:0 0 1rem;padding:1rem;position:relative}.callout>:first-child{margin-top:0}.callout>:last-child{margin-bottom:0}.callout.primary{background-color:#d7ecfa;color:#0a0a0a}.callout.secondary{background-color:#eaeaea;color:#0a0a0a}.callout.success{background-color:#e1faea;color:#0a0a0a}.callout.warning{background-color:#fff3d9;color:#0a0a0a}.callout.alert{background-color:#f7e4e1;color:#0a0a0a}.callout.small{padding:.5rem}.callout.large{padding:3rem}.card{-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-box-flex:1;-ms-flex-positive:1;background:#fefefe;border:1px solid #e6e6e6;border-radius:0;-webkit-box-shadow:none;box-shadow:none;color:#0a0a0a;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;-webkit-flex-grow:1;flex-grow:1;margin-bottom:1rem;overflow:hidden}.card>:last-child{margin-bottom:0}.card-divider{-webkit-box-flex:0;background:#e6e6e6;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex:0 1 auto;-ms-flex:0 1 auto;flex:0 1 auto;padding:1rem}.card-divider>:last-child{margin-bottom:0}.card-section{-webkit-box-flex:1;-webkit-flex:1 0 auto;-ms-flex:1 0 auto;flex:1 0 auto;padding:1rem}.card-section>:last-child{margin-bottom:0}.card-image{min-height:1px}.dropdown-pane{background-color:#fefefe;border:1px solid #cacaca;border-radius:0;display:none;font-size:1rem;padding:1rem;position:absolute;visibility:hidden;width:300px;z-index:10}.dropdown-pane.is-opening{display:block}.dropdown-pane.is-open{display:block;visibility:visible}.dropdown-pane.tiny{width:100px}.dropdown-pane.small{width:200px}.dropdown-pane.large{width:400px}.pagination{margin-bottom:1rem;margin-left:0}.pagination:after,.pagination:before{-ms-flex-preferred-size:0;-webkit-box-ordinal-group:2;-ms-flex-order:1;content:" ";display:table;-webkit-flex-basis:0;flex-basis:0;-webkit-order:1;order:1}.pagination:after{clear:both}.pagination li{border-radius:0;display:none;font-size:.875rem;margin-right:.0625rem}.pagination li:first-child,.pagination li:last-child{display:inline-block}@media print,screen and (min-width:40em){.pagination li{display:inline-block}}.pagination a,.pagination button{border-radius:0;color:#0a0a0a;display:block;padding:.1875rem .625rem}.pagination a:hover,.pagination button:hover{background:#e6e6e6}.pagination .current{background:#1779ba;color:#fefefe;cursor:default;padding:.1875rem .625rem}.pagination .disabled{color:#cacaca;cursor:not-allowed;padding:.1875rem .625rem}.pagination .disabled:hover{background:0 0}.pagination .ellipsis:after{color:#0a0a0a;content:"…";padding:.1875rem .625rem}.pagination-previous.disabled:before,.pagination-previous a:before{content:"«";display:inline-block;margin-right:.5rem}.pagination-next.disabled:after,.pagination-next a:after{content:"»";display:inline-block;margin-left:.5rem}.has-tip{border-bottom:1px dotted #8a8a8a;cursor:help;display:inline-block;font-weight:700;position:relative}.tooltip{background-color:#0a0a0a;border-radius:0;color:#fefefe;font-size:80%;max-width:10rem;padding:.75rem;position:absolute;top:calc(100% + .6495rem);z-index:1200}.tooltip:before{position:absolute}.tooltip.bottom:before{border-color:transparent transparent #0a0a0a;border-style:solid;border-width:0 .75rem .75rem;bottom:100%;content:"";display:block;height:0;width:0}.tooltip.bottom.align-center:before{left:50%;-webkit-transform:translateX(-50%);-ms-transform:translateX(-50%);transform:translateX(-50%)}.tooltip.top:before{border-color:#0a0a0a transparent transparent;border-style:solid;border-width:.75rem .75rem 0;bottom:auto;content:"";display:block;height:0;top:100%;width:0}.tooltip.top.align-center:before{left:50%;-webkit-transform:translateX(-50%);-ms-transform:translateX(-50%);transform:translateX(-50%)}.tooltip.left:before{border-color:transparent transparent transparent #0a0a0a;border-style:solid;border-width:.75rem 0 .75rem .75rem;content:"";display:block;height:0;left:100%;width:0}.tooltip.left.align-center:before{bottom:auto;top:50%;-webkit-transform:translateY(-50%);-ms-transform:translateY(-50%);transform:translateY(-50%)}.tooltip.right:before{border-color:transparent #0a0a0a transparent transparent;border-style:solid;border-width:.75rem .75rem .75rem 0;content:"";display:block;height:0;left:auto;right:100%;width:0}.tooltip.right.align-center:before{bottom:auto;top:50%;-webkit-transform:translateY(-50%);-ms-transform:translateY(-50%);transform:translateY(-50%)}.tooltip.align-top:before{bottom:auto;top:10%}.tooltip.align-bottom:before{bottom:10%;top:auto}.tooltip.align-left:before{left:10%;right:auto}.tooltip.align-right:before{left:auto;right:10%}.accordion{background:#fefefe;list-style-type:none;margin-left:0}.accordion[disabled] .accordion-title{cursor:not-allowed}.accordion-item:first-child>:first-child{border-radius:0}.accordion-item:last-child>:last-child{border-radius:0}.accordion-title{border:1px solid #e6e6e6;border-bottom:0;color:#1779ba;display:block;font-size:.75rem;line-height:1;padding:1.25rem 1rem;position:relative}:last-child:not(.is-active)>.accordion-title{border-bottom:1px solid #e6e6e6;border-radius:0}.accordion-title:focus,.accordion-title:hover{background-color:#e6e6e6}.accordion-title:before{content:"+";margin-top:-.5rem;position:absolute;right:1rem;top:50%}.is-active>.accordion-title:before{content:"–"}.accordion-content{background-color:#fefefe;border:1px solid #e6e6e6;border-bottom:0;color:#0a0a0a;display:none;padding:1rem}:last-child>.accordion-content:last-child{border-bottom:1px solid #e6e6e6}.media-object{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap;margin-bottom:1rem}.media-object img{max-width:none}@media print,screen and (max-width:39.99875em){.media-object.stack-for-small{-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap}}.media-object-section{-webkit-box-flex:0;-webkit-flex:0 1 auto;-ms-flex:0 1 auto;flex:0 1 auto}.media-object-section:first-child{padding-right:1rem}.media-object-section:last-child:not(:nth-child(2)){padding-left:1rem}.media-object-section>:last-child{margin-bottom:0}@media print,screen and (max-width:39.99875em){.stack-for-small .media-object-section{-ms-flex-preferred-size:100%;-webkit-flex-basis:100%;flex-basis:100%;max-width:100%;padding:0 0 1rem}.stack-for-small .media-object-section img{width:100%}}.media-object-section.main-section{-webkit-box-flex:1;-webkit-flex:1 1 0px;-ms-flex:1 1 0px;flex:1 1 0px}.orbit,.orbit-container{position:relative}.orbit-container{height:0;list-style:none;margin:0;overflow:hidden}.orbit-slide{position:absolute;width:100%}.orbit-slide.no-motionui.is-active{left:0;top:0}.orbit-figure{margin:0}.orbit-image{margin:0;max-width:100%;width:100%}.orbit-caption{background-color:hsla(0,0%,4%,.5);bottom:0;margin-bottom:0;width:100%}.orbit-caption,.orbit-next,.orbit-previous{color:#fefefe;padding:1rem;position:absolute}.orbit-next,.orbit-previous{top:50%;-webkit-transform:translateY(-50%);-ms-transform:translateY(-50%);transform:translateY(-50%);z-index:10}[data-whatinput=mouse] .orbit-next,[data-whatinput=mouse] .orbit-previous{outline:0}.orbit-next:active,.orbit-next:focus,.orbit-next:hover,.orbit-previous:active,.orbit-previous:focus,.orbit-previous:hover{background-color:hsla(0,0%,4%,.5)}.orbit-previous{left:0}.orbit-next{left:auto;right:0}.orbit-bullets{margin-bottom:.8rem;margin-top:.8rem;position:relative;text-align:center}[data-whatinput=mouse] .orbit-bullets{outline:0}.orbit-bullets button{background-color:#cacaca;border-radius:50%;height:1.2rem;margin:.1rem;width:1.2rem}.orbit-bullets button:hover{background-color:#8a8a8a}.orbit-bullets button.is-active{background-color:#8a8a8a}.flex-video,.responsive-embed{height:0;margin-bottom:1rem;overflow:hidden;padding-bottom:75%;position:relative}.flex-video embed,.flex-video iframe,.flex-video object,.flex-video video,.responsive-embed embed,.responsive-embed iframe,.responsive-embed object,.responsive-embed video{height:100%;left:0;position:absolute;top:0;width:100%}.flex-video.widescreen,.responsive-embed.widescreen{padding-bottom:56.25%}.tabs{background:#fefefe;border:1px solid #e6e6e6;list-style-type:none;margin:0}.tabs:after,.tabs:before{-ms-flex-preferred-size:0;-webkit-box-ordinal-group:2;-ms-flex-order:1;content:" ";display:table;-webkit-flex-basis:0;flex-basis:0;-webkit-order:1;order:1}.tabs:after{clear:both}.tabs.vertical>li{display:block;float:none;width:auto}.tabs.simple>li>a{padding:0}.tabs.simple>li>a:hover{background:0 0}.tabs.primary{background:#1779ba}.tabs.primary>li>a{color:#fefefe}.tabs.primary>li>a:focus,.tabs.primary>li>a:hover{background:#1673b1}.tabs-title{float:left}.tabs-title>a{color:#1779ba;display:block;font-size:.75rem;line-height:1;padding:1.25rem 1.5rem}[data-whatinput=mouse] .tabs-title>a{outline:0}.tabs-title>a:hover{background:#fefefe;color:#1468a0}.tabs-title>a:focus,.tabs-title>a[aria-selected=true]{background:#e6e6e6;color:#1779ba}.tabs-content{background:#fefefe;border:1px solid #e6e6e6;border-top:0;color:#0a0a0a;-webkit-transition:all .5s ease;transition:all .5s ease}.tabs-content.vertical{border:1px solid #e6e6e6;border-left:0}.tabs-panel{display:none;padding:1rem}.tabs-panel.is-active{display:block}.thumbnail{border:4px solid #fefefe;border-radius:0;-webkit-box-shadow:0 0 0 1px hsla(0,0%,4%,.2);box-shadow:0 0 0 1px hsla(0,0%,4%,.2);display:inline-block;line-height:0;margin-bottom:1rem;max-width:100%}a.thumbnail{-webkit-transition:-webkit-box-shadow .2s ease-out;transition:-webkit-box-shadow .2s ease-out;transition:box-shadow .2s ease-out;transition:box-shadow .2s ease-out,-webkit-box-shadow .2s ease-out}a.thumbnail:focus,a.thumbnail:hover{-webkit-box-shadow:0 0 6px 1px rgba(23,121,186,.5);box-shadow:0 0 6px 1px rgba(23,121,186,.5)}a.thumbnail image{-webkit-box-shadow:none;box-shadow:none}.menu{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;list-style:none;margin:0;padding:0;position:relative}[data-whatinput=mouse] .menu li{outline:0}.menu .button,.menu a{display:block;line-height:1;padding:.7rem 1rem;text-decoration:none}.menu a,.menu button,.menu input,.menu select{margin-bottom:0}.menu input{display:inline-block}.menu,.menu.horizontal{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap}.menu.vertical{-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap}.menu.vertical.icon-bottom li a i,.menu.vertical.icon-bottom li a img,.menu.vertical.icon-bottom li a svg,.menu.vertical.icon-top li a i,.menu.vertical.icon-top li a img,.menu.vertical.icon-top li a svg{text-align:left}.menu.expanded li{-webkit-box-flex:1;-webkit-flex:1 1 0px;-ms-flex:1 1 0px;flex:1 1 0px}.menu.expanded.icon-bottom li a i,.menu.expanded.icon-bottom li a img,.menu.expanded.icon-bottom li a svg,.menu.expanded.icon-top li a i,.menu.expanded.icon-top li a img,.menu.expanded.icon-top li a svg{text-align:left}.menu.simple{-webkit-box-align:center;-ms-flex-align:center;-webkit-align-items:center;align-items:center}.menu.simple li+li{margin-left:1rem}.menu.simple a{padding:0}@media print,screen and (min-width:40em){.menu.medium-horizontal{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap}.menu.medium-vertical{-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap}.menu.medium-expanded li,.menu.medium-simple li{-webkit-box-flex:1;-webkit-flex:1 1 0px;-ms-flex:1 1 0px;flex:1 1 0px}}@media print,screen and (min-width:64em){.menu.large-horizontal{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap}.menu.large-vertical{-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap}.menu.large-expanded li,.menu.large-simple li{-webkit-box-flex:1;-webkit-flex:1 1 0px;-ms-flex:1 1 0px;flex:1 1 0px}}.menu.nested{margin-left:1rem;margin-right:0}.menu.icon-bottom a,.menu.icon-left a,.menu.icon-right a,.menu.icon-top a,.menu.icons a{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex}.menu.icon-left li a,.menu.nested.icon-left li a{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-flow:row nowrap;-ms-flex-flow:row nowrap;flex-flow:row nowrap}.menu.icon-left li a i,.menu.icon-left li a img,.menu.icon-left li a svg,.menu.nested.icon-left li a i,.menu.nested.icon-left li a img,.menu.nested.icon-left li a svg{margin-right:.25rem}.menu.icon-right li a,.menu.nested.icon-right li a{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-flow:row nowrap;-ms-flex-flow:row nowrap;flex-flow:row nowrap}.menu.icon-right li a i,.menu.icon-right li a img,.menu.icon-right li a svg,.menu.nested.icon-right li a i,.menu.nested.icon-right li a img,.menu.nested.icon-right li a svg{margin-left:.25rem}.menu.icon-top li a,.menu.nested.icon-top li a{-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-flow:column nowrap;-ms-flex-flow:column nowrap;flex-flow:column nowrap}.menu.icon-top li a i,.menu.icon-top li a img,.menu.icon-top li a svg,.menu.nested.icon-top li a i,.menu.nested.icon-top li a img,.menu.nested.icon-top li a svg{-ms-flex-item-align:stretch;-webkit-align-self:stretch;align-self:stretch;margin-bottom:.25rem;text-align:center}.menu.icon-bottom li a,.menu.nested.icon-bottom li a{-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-flow:column nowrap;-ms-flex-flow:column nowrap;flex-flow:column nowrap}.menu.icon-bottom li a i,.menu.icon-bottom li a img,.menu.icon-bottom li a svg,.menu.nested.icon-bottom li a i,.menu.nested.icon-bottom li a img,.menu.nested.icon-bottom li a svg{-ms-flex-item-align:stretch;-webkit-align-self:stretch;align-self:stretch;margin-bottom:.25rem;text-align:center}.menu .is-active>a{background:#1779ba;color:#fefefe}.menu .active>a{background:#1779ba;color:#fefefe}.menu.align-left{-webkit-box-pack:start;-ms-flex-pack:start;-webkit-justify-content:flex-start;justify-content:flex-start}.menu.align-right li{-webkit-box-pack:end;-ms-flex-pack:end;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-justify-content:flex-end;justify-content:flex-end}.menu.align-right li .submenu li{-webkit-box-pack:start;-ms-flex-pack:start;-webkit-justify-content:flex-start;justify-content:flex-start}.menu.align-right.vertical li{display:block;text-align:right}.menu.align-right.icon-bottom li a i,.menu.align-right.icon-bottom li a img,.menu.align-right.icon-bottom li a svg,.menu.align-right.icon-top li a i,.menu.align-right.icon-top li a img,.menu.align-right.icon-top li a svg,.menu.align-right.vertical li .submenu li{text-align:right}.menu.align-right .nested{margin-left:0;margin-right:1rem}.menu.align-center li{-webkit-box-pack:center;-ms-flex-pack:center;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-justify-content:center;justify-content:center}.menu.align-center li .submenu li{-webkit-box-pack:start;-ms-flex-pack:start;-webkit-justify-content:flex-start;justify-content:flex-start}.menu .menu-text{color:inherit;font-weight:700;line-height:1;padding:.7rem 1rem}.menu-centered>.menu{-webkit-box-pack:center;-ms-flex-pack:center;-webkit-justify-content:center;justify-content:center}.menu-centered>.menu li{-webkit-box-pack:center;-ms-flex-pack:center;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-justify-content:center;justify-content:center}.menu-centered>.menu li .submenu li{-webkit-box-pack:start;-ms-flex-pack:start;-webkit-justify-content:flex-start;justify-content:flex-start}.no-js [data-responsive-menu] ul{display:none}.menu-icon{cursor:pointer;display:inline-block;height:16px;position:relative;vertical-align:middle;width:20px}.menu-icon:after{background:#fefefe;-webkit-box-shadow:0 7px 0 #fefefe,0 14px 0 #fefefe;box-shadow:0 7px 0 #fefefe,0 14px 0 #fefefe;content:"";display:block;height:2px;left:0;position:absolute;top:0;width:100%}.menu-icon:hover:after{background:#cacaca;-webkit-box-shadow:0 7px 0 #cacaca,0 14px 0 #cacaca;box-shadow:0 7px 0 #cacaca,0 14px 0 #cacaca}.menu-icon.dark{cursor:pointer;display:inline-block;height:16px;position:relative;vertical-align:middle;width:20px}.menu-icon.dark:after{background:#0a0a0a;-webkit-box-shadow:0 7px 0 #0a0a0a,0 14px 0 #0a0a0a;box-shadow:0 7px 0 #0a0a0a,0 14px 0 #0a0a0a;content:"";display:block;height:2px;left:0;position:absolute;top:0;width:100%}.menu-icon.dark:hover:after{background:#8a8a8a;-webkit-box-shadow:0 7px 0 #8a8a8a,0 14px 0 #8a8a8a;box-shadow:0 7px 0 #8a8a8a,0 14px 0 #8a8a8a}.accordion-menu li{width:100%}.accordion-menu .is-accordion-submenu a,.accordion-menu a{padding:.7rem 1rem}.accordion-menu .nested.is-accordion-submenu{margin-left:1rem;margin-right:0}.accordion-menu.align-right .nested.is-accordion-submenu{margin-left:0;margin-right:1rem}.accordion-menu .is-accordion-submenu-parent:not(.has-submenu-toggle)>a{position:relative}.accordion-menu .is-accordion-submenu-parent:not(.has-submenu-toggle)>a:after{border-color:#1779ba transparent transparent;border-style:solid;border-width:6px 6px 0;content:"";display:block;height:0;margin-top:-3px;position:absolute;right:1rem;top:50%;width:0}.accordion-menu.align-left .is-accordion-submenu-parent>a:after{left:auto;right:1rem}.accordion-menu.align-right .is-accordion-submenu-parent>a:after{left:1rem;right:auto}.accordion-menu .is-accordion-submenu-parent[aria-expanded=true]>a:after{-webkit-transform:rotate(180deg);-ms-transform:rotate(180deg);transform:rotate(180deg);-webkit-transform-origin:50% 50%;-ms-transform-origin:50% 50%;transform-origin:50% 50%}.is-accordion-submenu-parent{position:relative}.has-submenu-toggle>a{margin-right:40px}.submenu-toggle{cursor:pointer;height:40px;position:absolute;right:0;top:0;width:40px}.submenu-toggle:after{border-color:#1779ba transparent transparent;border-style:solid;border-width:6px 6px 0;bottom:0;content:"";display:block;height:0;margin:auto;top:0;width:0}.submenu-toggle[aria-expanded=true]:after{-webkit-transform:scaleY(-1);-ms-transform:scaleY(-1);transform:scaleY(-1);-webkit-transform-origin:50% 50%;-ms-transform-origin:50% 50%;transform-origin:50% 50%}.submenu-toggle-text{clip:rect(0,0,0,0)!important;border:0!important;height:1px!important;overflow:hidden!important;padding:0!important;position:absolute!important;white-space:nowrap!important;width:1px!important}.is-drilldown{overflow:hidden;position:relative}.is-drilldown li{display:block}.is-drilldown.animate-height{-webkit-transition:height .5s;transition:height .5s}.drilldown a{background:#fefefe;padding:.7rem 1rem}.drilldown .is-drilldown-submenu{background:#fefefe;left:100%;position:absolute;top:0;-webkit-transition:-webkit-transform .15s linear;transition:-webkit-transform .15s linear;transition:transform .15s linear;transition:transform .15s linear,-webkit-transform .15s linear;width:100%;z-index:-1}.drilldown .is-drilldown-submenu.is-active{display:block;-webkit-transform:translateX(-100%);-ms-transform:translateX(-100%);transform:translateX(-100%);z-index:1}.drilldown .is-drilldown-submenu.is-closing{-webkit-transform:translateX(100%);-ms-transform:translateX(100%);transform:translateX(100%)}.drilldown .is-drilldown-submenu a{padding:.7rem 1rem}.drilldown .nested.is-drilldown-submenu{margin-left:0;margin-right:0}.drilldown .drilldown-submenu-cover-previous{min-height:100%}.drilldown .is-drilldown-submenu-parent>a{position:relative}.drilldown .is-drilldown-submenu-parent>a:after{border-color:transparent transparent transparent #1779ba;border-style:solid;border-width:6px 0 6px 6px;content:"";display:block;height:0;margin-top:-6px;position:absolute;right:1rem;top:50%;width:0}.drilldown.align-left .is-drilldown-submenu-parent>a:after{border-color:transparent transparent transparent #1779ba;border-style:solid;border-width:6px 0 6px 6px;content:"";display:block;height:0;left:auto;right:1rem;width:0}.drilldown.align-right .is-drilldown-submenu-parent>a:after{border-color:transparent #1779ba transparent transparent;border-style:solid;border-width:6px 6px 6px 0;content:"";display:block;height:0;left:1rem;right:auto;width:0}.drilldown .js-drilldown-back>a:before{border-color:transparent #1779ba transparent transparent;border-style:solid;border-width:6px 6px 6px 0;content:"";display:block;display:inline-block;height:0;margin-right:.75rem;vertical-align:middle;width:0}.dropdown.menu>li.opens-left>.is-dropdown-submenu{left:auto;right:0;top:100%}.dropdown.menu>li.opens-right>.is-dropdown-submenu{left:0;right:auto;top:100%}.dropdown.menu>li.is-dropdown-submenu-parent>a{padding-right:1.5rem;position:relative}.dropdown.menu>li.is-dropdown-submenu-parent>a:after{border-color:#1779ba transparent transparent;border-style:solid;border-width:6px 6px 0;content:"";display:block;height:0;left:auto;margin-top:-3px;right:5px;width:0}[data-whatinput=mouse] .dropdown.menu a{outline:0}.dropdown.menu>li>a{padding:.7rem 1rem}.dropdown.menu>li.is-active>a{background:0 0;color:#1779ba}.no-js .dropdown.menu ul{display:none}.dropdown.menu .nested.is-dropdown-submenu{margin-left:0;margin-right:0}.dropdown.menu.vertical>li .is-dropdown-submenu{top:0}.dropdown.menu.vertical>li.opens-left>.is-dropdown-submenu{left:auto;right:100%;top:0}.dropdown.menu.vertical>li.opens-right>.is-dropdown-submenu{left:100%;right:auto}.dropdown.menu.vertical>li>a:after{right:14px}.dropdown.menu.vertical>li.opens-left>a:after{border-color:transparent #1779ba transparent transparent;border-style:solid;border-width:6px 6px 6px 0;content:"";display:block;height:0;left:5px;right:auto;width:0}.dropdown.menu.vertical>li.opens-right>a:after{border-color:transparent transparent transparent #1779ba;border-style:solid;border-width:6px 0 6px 6px;content:"";display:block;height:0;width:0}@media print,screen and (min-width:40em){.dropdown.menu.medium-horizontal>li.opens-left>.is-dropdown-submenu{left:auto;right:0;top:100%}.dropdown.menu.medium-horizontal>li.opens-right>.is-dropdown-submenu{left:0;right:auto;top:100%}.dropdown.menu.medium-horizontal>li.is-dropdown-submenu-parent>a{padding-right:1.5rem;position:relative}.dropdown.menu.medium-horizontal>li.is-dropdown-submenu-parent>a:after{border-color:#1779ba transparent transparent;border-style:solid;border-width:6px 6px 0;content:"";display:block;height:0;left:auto;margin-top:-3px;right:5px;width:0}.dropdown.menu.medium-vertical>li .is-dropdown-submenu{top:0}.dropdown.menu.medium-vertical>li.opens-left>.is-dropdown-submenu{left:auto;right:100%;top:0}.dropdown.menu.medium-vertical>li.opens-right>.is-dropdown-submenu{left:100%;right:auto}.dropdown.menu.medium-vertical>li>a:after{right:14px}.dropdown.menu.medium-vertical>li.opens-left>a:after{border-color:transparent #1779ba transparent transparent;border-style:solid;border-width:6px 6px 6px 0;content:"";display:block;height:0;left:5px;right:auto;width:0}.dropdown.menu.medium-vertical>li.opens-right>a:after{border-color:transparent transparent transparent #1779ba;border-style:solid;border-width:6px 0 6px 6px;content:"";display:block;height:0;width:0}}@media print,screen and (min-width:64em){.dropdown.menu.large-horizontal>li.opens-left>.is-dropdown-submenu{left:auto;right:0;top:100%}.dropdown.menu.large-horizontal>li.opens-right>.is-dropdown-submenu{left:0;right:auto;top:100%}.dropdown.menu.large-horizontal>li.is-dropdown-submenu-parent>a{padding-right:1.5rem;position:relative}.dropdown.menu.large-horizontal>li.is-dropdown-submenu-parent>a:after{border-color:#1779ba transparent transparent;border-style:solid;border-width:6px 6px 0;content:"";display:block;height:0;left:auto;margin-top:-3px;right:5px;width:0}.dropdown.menu.large-vertical>li .is-dropdown-submenu{top:0}.dropdown.menu.large-vertical>li.opens-left>.is-dropdown-submenu{left:auto;right:100%;top:0}.dropdown.menu.large-vertical>li.opens-right>.is-dropdown-submenu{left:100%;right:auto}.dropdown.menu.large-vertical>li>a:after{right:14px}.dropdown.menu.large-vertical>li.opens-left>a:after{border-color:transparent #1779ba transparent transparent;border-style:solid;border-width:6px 6px 6px 0;content:"";display:block;height:0;left:5px;right:auto;width:0}.dropdown.menu.large-vertical>li.opens-right>a:after{border-color:transparent transparent transparent #1779ba;border-style:solid;border-width:6px 0 6px 6px;content:"";display:block;height:0;width:0}}.dropdown.menu.align-right .is-dropdown-submenu.first-sub{left:auto;right:0;top:100%}.is-dropdown-menu.vertical{width:100px}.is-dropdown-menu.vertical.align-right{float:right}.is-dropdown-submenu-parent{position:relative}.is-dropdown-submenu-parent a:after{left:auto;margin-top:-6px;position:absolute;right:5px;top:50%}.is-dropdown-submenu-parent.opens-inner>.is-dropdown-submenu{left:auto;top:100%}.is-dropdown-submenu-parent.opens-left>.is-dropdown-submenu{left:auto;right:100%}.is-dropdown-submenu-parent.opens-right>.is-dropdown-submenu{left:100%;right:auto}.is-dropdown-submenu{background:#fefefe;border:1px solid #cacaca;display:none;left:100%;min-width:200px;position:absolute;top:0;z-index:1}.dropdown .is-dropdown-submenu a{padding:.7rem 1rem}.is-dropdown-submenu .is-dropdown-submenu-parent>a:after{right:14px}.is-dropdown-submenu .is-dropdown-submenu-parent.opens-left>a:after{border-color:transparent #1779ba transparent transparent;border-style:solid;border-width:6px 6px 6px 0;content:"";display:block;height:0;left:5px;right:auto;width:0}.is-dropdown-submenu .is-dropdown-submenu-parent.opens-right>a:after{border-color:transparent transparent transparent #1779ba;border-style:solid;border-width:6px 0 6px 6px;content:"";display:block;height:0;width:0}.is-dropdown-submenu .is-dropdown-submenu{margin-top:-1px}.is-dropdown-submenu>li{width:100%}.is-dropdown-submenu.js-dropdown-active{display:block}.is-off-canvas-open{overflow:hidden}.js-off-canvas-overlay{background:hsla(0,0%,100%,.25);height:100%;left:0;opacity:0;overflow:hidden;position:absolute;top:0;-webkit-transition:opacity .5s ease,visibility .5s ease;transition:opacity .5s ease,visibility .5s ease;visibility:hidden;width:100%;z-index:11}.js-off-canvas-overlay.is-visible{opacity:1;visibility:visible}.js-off-canvas-overlay.is-closable{cursor:pointer}.js-off-canvas-overlay.is-overlay-absolute{position:absolute}.js-off-canvas-overlay.is-overlay-fixed{position:fixed}.off-canvas-wrapper{overflow:hidden;position:relative}.off-canvas{-webkit-backface-visibility:hidden;backface-visibility:hidden;background:#e6e6e6;position:fixed;-webkit-transition:-webkit-transform .5s ease;transition:-webkit-transform .5s ease;transition:transform .5s ease;transition:transform .5s ease,-webkit-transform .5s ease;z-index:12}[data-whatinput=mouse] .off-canvas{outline:0}.off-canvas.is-transition-push{z-index:12}.off-canvas.is-closed{visibility:hidden}.off-canvas.is-transition-overlap{z-index:13}.off-canvas.is-transition-overlap.is-open{-webkit-box-shadow:0 0 10px hsla(0,0%,4%,.7);box-shadow:0 0 10px hsla(0,0%,4%,.7)}.off-canvas.is-open{-webkit-transform:translate(0);-ms-transform:translate(0);transform:translate(0)}.off-canvas-absolute{-webkit-backface-visibility:hidden;backface-visibility:hidden;background:#e6e6e6;position:absolute;-webkit-transition:-webkit-transform .5s ease;transition:-webkit-transform .5s ease;transition:transform .5s ease;transition:transform .5s ease,-webkit-transform .5s ease;z-index:12}[data-whatinput=mouse] .off-canvas-absolute{outline:0}.off-canvas-absolute.is-transition-push{z-index:12}.off-canvas-absolute.is-closed{visibility:hidden}.off-canvas-absolute.is-transition-overlap{z-index:13}.off-canvas-absolute.is-transition-overlap.is-open{-webkit-box-shadow:0 0 10px hsla(0,0%,4%,.7);box-shadow:0 0 10px hsla(0,0%,4%,.7)}.off-canvas-absolute.is-open{-webkit-transform:translate(0);-ms-transform:translate(0);transform:translate(0)}.position-left{-webkit-overflow-scrolling:touch;height:100%;left:0;overflow-y:auto;top:0;width:250px}.off-canvas-content .off-canvas.position-left,.position-left{-webkit-transform:translateX(-250px);-ms-transform:translateX(-250px);transform:translateX(-250px)}.off-canvas-content .off-canvas.position-left.is-transition-overlap.is-open{-webkit-transform:translate(0);-ms-transform:translate(0);transform:translate(0)}.off-canvas-content.is-open-left.has-transition-push{-webkit-transform:translateX(250px);-ms-transform:translateX(250px);transform:translateX(250px)}.position-left.is-transition-push{-webkit-box-shadow:inset -13px 0 20px -13px hsla(0,0%,4%,.25);box-shadow:inset -13px 0 20px -13px hsla(0,0%,4%,.25)}.position-right{-webkit-overflow-scrolling:touch;height:100%;overflow-y:auto;right:0;top:0;width:250px}.off-canvas-content .off-canvas.position-right,.position-right{-webkit-transform:translateX(250px);-ms-transform:translateX(250px);transform:translateX(250px)}.off-canvas-content .off-canvas.position-right.is-transition-overlap.is-open{-webkit-transform:translate(0);-ms-transform:translate(0);transform:translate(0)}.off-canvas-content.is-open-right.has-transition-push{-webkit-transform:translateX(-250px);-ms-transform:translateX(-250px);transform:translateX(-250px)}.position-right.is-transition-push{-webkit-box-shadow:inset 13px 0 20px -13px hsla(0,0%,4%,.25);box-shadow:inset 13px 0 20px -13px hsla(0,0%,4%,.25)}.position-top{-webkit-overflow-scrolling:touch;height:250px;left:0;overflow-x:auto;top:0;width:100%}.off-canvas-content .off-canvas.position-top,.position-top{-webkit-transform:translateY(-250px);-ms-transform:translateY(-250px);transform:translateY(-250px)}.off-canvas-content .off-canvas.position-top.is-transition-overlap.is-open{-webkit-transform:translate(0);-ms-transform:translate(0);transform:translate(0)}.off-canvas-content.is-open-top.has-transition-push{-webkit-transform:translateY(250px);-ms-transform:translateY(250px);transform:translateY(250px)}.position-top.is-transition-push{-webkit-box-shadow:inset 0 -13px 20px -13px hsla(0,0%,4%,.25);box-shadow:inset 0 -13px 20px -13px hsla(0,0%,4%,.25)}.position-bottom{-webkit-overflow-scrolling:touch;bottom:0;height:250px;left:0;overflow-x:auto;width:100%}.off-canvas-content .off-canvas.position-bottom,.position-bottom{-webkit-transform:translateY(250px);-ms-transform:translateY(250px);transform:translateY(250px)}.off-canvas-content .off-canvas.position-bottom.is-transition-overlap.is-open{-webkit-transform:translate(0);-ms-transform:translate(0);transform:translate(0)}.off-canvas-content.is-open-bottom.has-transition-push{-webkit-transform:translateY(-250px);-ms-transform:translateY(-250px);transform:translateY(-250px)}.position-bottom.is-transition-push{-webkit-box-shadow:inset 0 13px 20px -13px hsla(0,0%,4%,.25);box-shadow:inset 0 13px 20px -13px hsla(0,0%,4%,.25)}.off-canvas-content{-webkit-backface-visibility:hidden;backface-visibility:hidden;-webkit-transform:none;-ms-transform:none;transform:none}.off-canvas-content.has-transition-overlap,.off-canvas-content.has-transition-push{-webkit-transition:-webkit-transform .5s ease;transition:-webkit-transform .5s ease;transition:transform .5s ease;transition:transform .5s ease,-webkit-transform .5s ease}.off-canvas-content.has-transition-push,.off-canvas-content .off-canvas.is-open{-webkit-transform:translate(0);-ms-transform:translate(0);transform:translate(0)}@media print,screen and (min-width:40em){.position-left.reveal-for-medium{-webkit-transform:none;-ms-transform:none;transform:none;-webkit-transition:none;transition:none;visibility:visible;z-index:12}.position-left.reveal-for-medium .close-button{display:none}.off-canvas-content .position-left.reveal-for-medium{-webkit-transform:none;-ms-transform:none;transform:none}.off-canvas-content.has-reveal-left{margin-left:250px}.position-left.reveal-for-medium~.off-canvas-content{margin-left:250px}.position-right.reveal-for-medium{-webkit-transform:none;-ms-transform:none;transform:none;-webkit-transition:none;transition:none;visibility:visible;z-index:12}.position-right.reveal-for-medium .close-button{display:none}.off-canvas-content .position-right.reveal-for-medium{-webkit-transform:none;-ms-transform:none;transform:none}.off-canvas-content.has-reveal-right{margin-right:250px}.position-right.reveal-for-medium~.off-canvas-content{margin-right:250px}.position-top.reveal-for-medium{-webkit-transform:none;-ms-transform:none;transform:none;-webkit-transition:none;transition:none;visibility:visible;z-index:12}.position-top.reveal-for-medium .close-button{display:none}.off-canvas-content .position-top.reveal-for-medium{-webkit-transform:none;-ms-transform:none;transform:none}.off-canvas-content.has-reveal-top{margin-top:250px}.position-top.reveal-for-medium~.off-canvas-content{margin-top:250px}.position-bottom.reveal-for-medium{-webkit-transform:none;-ms-transform:none;transform:none;-webkit-transition:none;transition:none;visibility:visible;z-index:12}.position-bottom.reveal-for-medium .close-button{display:none}.off-canvas-content .position-bottom.reveal-for-medium{-webkit-transform:none;-ms-transform:none;transform:none}.off-canvas-content.has-reveal-bottom{margin-bottom:250px}.position-bottom.reveal-for-medium~.off-canvas-content{margin-bottom:250px}}@media print,screen and (min-width:64em){.position-left.reveal-for-large{-webkit-transform:none;-ms-transform:none;transform:none;-webkit-transition:none;transition:none;visibility:visible;z-index:12}.position-left.reveal-for-large .close-button{display:none}.off-canvas-content .position-left.reveal-for-large{-webkit-transform:none;-ms-transform:none;transform:none}.off-canvas-content.has-reveal-left{margin-left:250px}.position-left.reveal-for-large~.off-canvas-content{margin-left:250px}.position-right.reveal-for-large{-webkit-transform:none;-ms-transform:none;transform:none;-webkit-transition:none;transition:none;visibility:visible;z-index:12}.position-right.reveal-for-large .close-button{display:none}.off-canvas-content .position-right.reveal-for-large{-webkit-transform:none;-ms-transform:none;transform:none}.off-canvas-content.has-reveal-right{margin-right:250px}.position-right.reveal-for-large~.off-canvas-content{margin-right:250px}.position-top.reveal-for-large{-webkit-transform:none;-ms-transform:none;transform:none;-webkit-transition:none;transition:none;visibility:visible;z-index:12}.position-top.reveal-for-large .close-button{display:none}.off-canvas-content .position-top.reveal-for-large{-webkit-transform:none;-ms-transform:none;transform:none}.off-canvas-content.has-reveal-top{margin-top:250px}.position-top.reveal-for-large~.off-canvas-content{margin-top:250px}.position-bottom.reveal-for-large{-webkit-transform:none;-ms-transform:none;transform:none;-webkit-transition:none;transition:none;visibility:visible;z-index:12}.position-bottom.reveal-for-large .close-button{display:none}.off-canvas-content .position-bottom.reveal-for-large{-webkit-transform:none;-ms-transform:none;transform:none}.off-canvas-content.has-reveal-bottom{margin-bottom:250px}.position-bottom.reveal-for-large~.off-canvas-content{margin-bottom:250px}}@media print,screen and (min-width:40em){.off-canvas.in-canvas-for-medium{background:0 0;height:auto;overflow:visible;position:static;-webkit-transition:none;transition:none;visibility:visible;width:auto}.off-canvas.in-canvas-for-medium.position-bottom,.off-canvas.in-canvas-for-medium.position-left,.off-canvas.in-canvas-for-medium.position-right,.off-canvas.in-canvas-for-medium.position-top{-webkit-box-shadow:none;box-shadow:none;-webkit-transform:none;-ms-transform:none;transform:none}.off-canvas.in-canvas-for-medium .close-button{display:none}}@media print,screen and (min-width:64em){.off-canvas.in-canvas-for-large{background:0 0;height:auto;overflow:visible;position:static;-webkit-transition:none;transition:none;visibility:visible;width:auto}.off-canvas.in-canvas-for-large.position-bottom,.off-canvas.in-canvas-for-large.position-left,.off-canvas.in-canvas-for-large.position-right,.off-canvas.in-canvas-for-large.position-top{-webkit-box-shadow:none;box-shadow:none;-webkit-transform:none;-ms-transform:none;transform:none}.off-canvas.in-canvas-for-large .close-button{display:none}}html.is-reveal-open{overflow-y:hidden;position:fixed;width:100%}html.is-reveal-open.zf-has-scroll{-webkit-overflow-scrolling:touch;overflow-y:scroll}html.is-reveal-open body{overflow-y:hidden}.reveal-overlay{background-color:hsla(0,0%,4%,.45);bottom:0;left:0;position:fixed;right:0;top:0;z-index:1005}.reveal,.reveal-overlay{-webkit-overflow-scrolling:touch;display:none;overflow-y:auto}.reveal{-webkit-backface-visibility:hidden;backface-visibility:hidden;background-color:#fefefe;border:1px solid #cacaca;border-radius:0;margin-left:auto;margin-right:auto;padding:1rem;position:relative;top:100px;z-index:1006}[data-whatinput=mouse] .reveal{outline:0}@media print,screen and (min-width:40em){.reveal{min-height:0}}.reveal .column{min-width:0}.reveal>:last-child{margin-bottom:0}@media print,screen and (min-width:40em){.reveal{max-width:75rem;width:600px}}.reveal.collapse{padding:0}@media print,screen and (min-width:40em){.reveal.tiny{max-width:75rem;width:30%}.reveal.small{max-width:75rem;width:50%}.reveal.large{max-width:75rem;width:90%}}.reveal.full{border:0;border-radius:0;bottom:0;height:100%;left:0;margin-left:0;max-width:none;min-height:100%;right:0;top:0;width:100%}@media print,screen and (max-width:39.99875em){.reveal{border:0;border-radius:0;bottom:0;height:100%;left:0;margin-left:0;max-width:none;min-height:100%;right:0;top:0;width:100%}}.reveal.without-overlay{position:fixed}.sticky,.sticky-container{position:relative}.sticky{-webkit-transform:translateZ(0);transform:translateZ(0);z-index:0}.sticky.is-stuck{position:fixed;width:100%;z-index:5}.sticky.is-stuck.is-at-top{top:0}.sticky.is-stuck.is-at-bottom{bottom:0}.sticky.is-anchored{left:auto;position:relative;right:auto}.sticky.is-anchored.is-at-bottom{bottom:0}.title-bar{-webkit-box-pack:start;-ms-flex-pack:start;-webkit-box-align:center;-ms-flex-align:center;-webkit-align-items:center;align-items:center;background:#0a0a0a;color:#fefefe;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-justify-content:flex-start;justify-content:flex-start;padding:.5rem}.title-bar .menu-icon{margin-left:.25rem;margin-right:.25rem}.title-bar-left,.title-bar-right{-webkit-box-flex:1;-webkit-flex:1 1 0px;-ms-flex:1 1 0px;flex:1 1 0px}.title-bar-right{text-align:right}.title-bar-title{display:inline-block;font-weight:700;vertical-align:middle}.top-bar{-webkit-box-pack:justify;-ms-flex-pack:justify;-webkit-box-align:center;-ms-flex-align:center;-webkit-align-items:center;align-items:center;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;-webkit-justify-content:space-between;justify-content:space-between;padding:.5rem}.top-bar,.top-bar ul{background-color:#e6e6e6}.top-bar input{margin-right:1rem;max-width:200px}.top-bar .input-group-field{margin-right:0;width:100%}.top-bar input.button{width:auto}.top-bar .top-bar-left,.top-bar .top-bar-right{-webkit-box-flex:0;-webkit-flex:0 0 100%;-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}@media print,screen and (min-width:40em){.top-bar{-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap}.top-bar .top-bar-left{-webkit-box-flex:1;-webkit-flex:1 1 auto;-ms-flex:1 1 auto;flex:1 1 auto;margin-right:auto}.top-bar .top-bar-right{-webkit-box-flex:0;-webkit-flex:0 1 auto;-ms-flex:0 1 auto;flex:0 1 auto;margin-left:auto}}@media print,screen and (max-width:63.99875em){.top-bar.stacked-for-medium{-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap}.top-bar.stacked-for-medium .top-bar-left,.top-bar.stacked-for-medium .top-bar-right{-webkit-box-flex:0;-webkit-flex:0 0 100%;-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}}@media print,screen and (max-width:74.99875em){.top-bar.stacked-for-large{-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap}.top-bar.stacked-for-large .top-bar-left,.top-bar.stacked-for-large .top-bar-right{-webkit-box-flex:0;-webkit-flex:0 0 100%;-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}}.top-bar-title{margin:.5rem 1rem .5rem 0}.top-bar-left,.top-bar-right,.top-bar-title{-webkit-box-flex:0;-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto}.float-left{float:left!important}.float-right{float:right!important}.float-center{display:block;margin-left:auto;margin-right:auto}.clearfix:after,.clearfix:before{-ms-flex-preferred-size:0;-webkit-box-ordinal-group:2;-ms-flex-order:1;content:" ";display:table;-webkit-flex-basis:0;flex-basis:0;-webkit-order:1;order:1}.clearfix:after{clear:both}.align-left{-webkit-box-pack:start;-ms-flex-pack:start;-webkit-justify-content:flex-start;justify-content:flex-start}.align-right{-webkit-box-pack:end;-ms-flex-pack:end;-webkit-justify-content:flex-end;justify-content:flex-end}.align-center{-webkit-box-pack:center;-ms-flex-pack:center;-webkit-justify-content:center;justify-content:center}.align-justify{-webkit-box-pack:justify;-ms-flex-pack:justify;-webkit-justify-content:space-between;justify-content:space-between}.align-spaced{-ms-flex-pack:distribute;-webkit-justify-content:space-around;justify-content:space-around}.align-left.vertical.menu>li>a{-webkit-box-pack:start;-ms-flex-pack:start;-webkit-justify-content:flex-start;justify-content:flex-start}.align-right.vertical.menu>li>a{-webkit-box-pack:end;-ms-flex-pack:end;-webkit-justify-content:flex-end;justify-content:flex-end}.align-center.vertical.menu>li>a{-webkit-box-pack:center;-ms-flex-pack:center;-webkit-justify-content:center;justify-content:center}.align-top{-webkit-box-align:start;-ms-flex-align:start;-webkit-align-items:flex-start;align-items:flex-start}.align-self-top{-ms-flex-item-align:start;-webkit-align-self:flex-start;align-self:flex-start}.align-bottom{-webkit-box-align:end;-ms-flex-align:end;-webkit-align-items:flex-end;align-items:flex-end}.align-self-bottom{-ms-flex-item-align:end;-webkit-align-self:flex-end;align-self:flex-end}.align-middle{-webkit-box-align:center;-ms-flex-align:center;-webkit-align-items:center;align-items:center}.align-self-middle{-ms-flex-item-align:center;-webkit-align-self:center;align-self:center}.align-stretch{-webkit-box-align:stretch;-ms-flex-align:stretch;-webkit-align-items:stretch;align-items:stretch}.align-self-stretch{-ms-flex-item-align:stretch;-webkit-align-self:stretch;align-self:stretch}.align-center-middle{-webkit-box-pack:center;-ms-flex-pack:center;-webkit-box-align:center;-ms-flex-align:center;-ms-flex-line-pack:center;-webkit-align-content:center;align-content:center;-webkit-align-items:center;align-items:center;-webkit-justify-content:center;justify-content:center}.small-order-1{-webkit-box-ordinal-group:2;-ms-flex-order:1;-webkit-order:1;order:1}.small-order-2{-webkit-box-ordinal-group:3;-ms-flex-order:2;-webkit-order:2;order:2}.small-order-3{-webkit-box-ordinal-group:4;-ms-flex-order:3;-webkit-order:3;order:3}.small-order-4{-webkit-box-ordinal-group:5;-ms-flex-order:4;-webkit-order:4;order:4}.small-order-5{-webkit-box-ordinal-group:6;-ms-flex-order:5;-webkit-order:5;order:5}.small-order-6{-webkit-box-ordinal-group:7;-ms-flex-order:6;-webkit-order:6;order:6}@media print,screen and (min-width:40em){.medium-order-1{-webkit-box-ordinal-group:2;-ms-flex-order:1;-webkit-order:1;order:1}.medium-order-2{-webkit-box-ordinal-group:3;-ms-flex-order:2;-webkit-order:2;order:2}.medium-order-3{-webkit-box-ordinal-group:4;-ms-flex-order:3;-webkit-order:3;order:3}.medium-order-4{-webkit-box-ordinal-group:5;-ms-flex-order:4;-webkit-order:4;order:4}.medium-order-5{-webkit-box-ordinal-group:6;-ms-flex-order:5;-webkit-order:5;order:5}.medium-order-6{-webkit-box-ordinal-group:7;-ms-flex-order:6;-webkit-order:6;order:6}}@media print,screen and (min-width:64em){.large-order-1{-webkit-box-ordinal-group:2;-ms-flex-order:1;-webkit-order:1;order:1}.large-order-2{-webkit-box-ordinal-group:3;-ms-flex-order:2;-webkit-order:2;order:2}.large-order-3{-webkit-box-ordinal-group:4;-ms-flex-order:3;-webkit-order:3;order:3}.large-order-4{-webkit-box-ordinal-group:5;-ms-flex-order:4;-webkit-order:4;order:4}.large-order-5{-webkit-box-ordinal-group:6;-ms-flex-order:5;-webkit-order:5;order:5}.large-order-6{-webkit-box-ordinal-group:7;-ms-flex-order:6;-webkit-order:6;order:6}}.flex-container{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex}.flex-child-auto{-webkit-box-flex:1;-webkit-flex:1 1 auto;-ms-flex:1 1 auto;flex:1 1 auto}.flex-child-grow{-webkit-box-flex:1;-webkit-flex:1 0 auto;-ms-flex:1 0 auto;flex:1 0 auto}.flex-child-shrink{-webkit-box-flex:0;-webkit-flex:0 1 auto;-ms-flex:0 1 auto;flex:0 1 auto}.flex-dir-row{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row}.flex-dir-row-reverse{-webkit-box-orient:horizontal;-webkit-box-direction:reverse;-webkit-flex-direction:row-reverse;-ms-flex-direction:row-reverse;flex-direction:row-reverse}.flex-dir-column{-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column}.flex-dir-column-reverse{-webkit-box-orient:vertical;-webkit-box-direction:reverse;-webkit-flex-direction:column-reverse;-ms-flex-direction:column-reverse;flex-direction:column-reverse}@media print,screen and (min-width:40em){.medium-flex-container{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex}.medium-flex-child-auto{-webkit-box-flex:1;-webkit-flex:1 1 auto;-ms-flex:1 1 auto;flex:1 1 auto}.medium-flex-child-grow{-webkit-box-flex:1;-webkit-flex:1 0 auto;-ms-flex:1 0 auto;flex:1 0 auto}.medium-flex-child-shrink{-webkit-box-flex:0;-webkit-flex:0 1 auto;-ms-flex:0 1 auto;flex:0 1 auto}.medium-flex-dir-row{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row}.medium-flex-dir-row-reverse{-webkit-box-orient:horizontal;-webkit-box-direction:reverse;-webkit-flex-direction:row-reverse;-ms-flex-direction:row-reverse;flex-direction:row-reverse}.medium-flex-dir-column{-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column}.medium-flex-dir-column-reverse{-webkit-box-orient:vertical;-webkit-box-direction:reverse;-webkit-flex-direction:column-reverse;-ms-flex-direction:column-reverse;flex-direction:column-reverse}}@media print,screen and (min-width:64em){.large-flex-container{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex}.large-flex-child-auto{-webkit-box-flex:1;-webkit-flex:1 1 auto;-ms-flex:1 1 auto;flex:1 1 auto}.large-flex-child-grow{-webkit-box-flex:1;-webkit-flex:1 0 auto;-ms-flex:1 0 auto;flex:1 0 auto}.large-flex-child-shrink{-webkit-box-flex:0;-webkit-flex:0 1 auto;-ms-flex:0 1 auto;flex:0 1 auto}.large-flex-dir-row{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row}.large-flex-dir-row-reverse{-webkit-box-orient:horizontal;-webkit-box-direction:reverse;-webkit-flex-direction:row-reverse;-ms-flex-direction:row-reverse;flex-direction:row-reverse}.large-flex-dir-column{-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column}.large-flex-dir-column-reverse{-webkit-box-orient:vertical;-webkit-box-direction:reverse;-webkit-flex-direction:column-reverse;-ms-flex-direction:column-reverse;flex-direction:column-reverse}}.hide{display:none!important}.invisible{visibility:hidden}.visible{visibility:visible}@media print,screen and (max-width:39.99875em){.hide-for-small-only{display:none!important}}@media screen and (max-width:0em),screen and (min-width:40em){.show-for-small-only{display:none!important}}@media print,screen and (min-width:40em){.hide-for-medium{display:none!important}}@media screen and (max-width:39.99875em){.show-for-medium{display:none!important}}@media print,screen and (min-width:40em)and (max-width:63.99875em){.hide-for-medium-only{display:none!important}}@media screen and (max-width:39.99875em),screen and (min-width:64em){.show-for-medium-only{display:none!important}}@media print,screen and (min-width:64em){.hide-for-large{display:none!important}}@media screen and (max-width:63.99875em){.show-for-large{display:none!important}}@media print,screen and (min-width:64em)and (max-width:74.99875em){.hide-for-large-only{display:none!important}}@media screen and (max-width:63.99875em),screen and (min-width:75em){.show-for-large-only{display:none!important}}.show-for-sr,.show-on-focus{clip:rect(0,0,0,0)!important;border:0!important;height:1px!important;overflow:hidden!important;padding:0!important;position:absolute!important;white-space:nowrap!important;width:1px!important}.show-on-focus:active,.show-on-focus:focus{clip:auto!important;height:auto!important;overflow:visible!important;position:static!important;white-space:normal!important;width:auto!important}.hide-for-portrait,.show-for-landscape{display:block!important}@media screen and (orientation:landscape){.hide-for-portrait,.show-for-landscape{display:block!important}}@media screen and (orientation:portrait){.hide-for-portrait,.show-for-landscape{display:none!important}}.hide-for-landscape,.show-for-portrait{display:none!important}@media screen and (orientation:landscape){.hide-for-landscape,.show-for-portrait{display:none!important}}@media screen and (orientation:portrait){.hide-for-landscape,.show-for-portrait{display:block!important}}.show-for-dark-mode{display:none}.hide-for-dark-mode{display:block}@media screen and (prefers-color-scheme:dark){.show-for-dark-mode{display:block!important}.hide-for-dark-mode{display:none!important}}.show-for-ie{display:none}@media (-ms-high-contrast:active),(-ms-high-contrast:none){.show-for-ie{display:block!important}.hide-for-ie{display:none!important}}.show-for-sticky{display:none}.is-stuck .show-for-sticky{display:block}.is-stuck .hide-for-sticky{display:none}@font-face{font-display:"swap";font-family:FontAwesome}html{box-sizing:border-box}body{font-family:Roboto,sans-serif;font-size:16px;line-height:1}*,:after,:before{box-sizing:inherit}a{color:#3c4fe0}a.reference:after{font-family:FontAwesome;font-size:12px;padding:0 4px}a.reference.external:after{content:""}a.reference.download:after{content:""}a:hover{color:#3c4fe0;font-weight:500}.headerlink{margin-left:5px;visibility:hidden}.toc-backref:hover{color:#23263b}h1,h2,h3,h4,h5,h6{font-family:Roboto,sans-serif;font-size:16px;font-weight:500;letter-spacing:.2px;line-height:24px;margin-bottom:16px}h1:hover>a.headerlink,h2:hover>a.headerlink,h3:hover>a.headerlink,h4:hover>a.headerlink,h5:hover>a.headerlink,h6:hover>a.headerlink{visibility:visible}h1 a,h2 a,h3 a,h4 a,h5 a,h6 a{color:inherit}h1{font-size:32px;font-weight:700;line-height:40px;margin-bottom:28px}h2{font-size:24px;line-height:32px}h3{font-size:20px}h4{font-size:18px}h5{font-size:16px}h6{font-weight:400}img{max-width:100%}button:focus{outline:0}blockquote{border:0;margin:0;padding:0}blockquote,blockquote p,cite{color:inherit}cite{display:inline;font-size:inherit}cite:before{content:""}.show{display:block!important}.centered{display:block;margin:0 auto}.break{flex-basis:100%;height:0}@media screen and (min-width:1024px){h1{font-size:36px}}.admonition-title:before,.contents.local>ul>li a:before,.scylla-icon,.secondary-side-nav__content li a:before{background-repeat:no-repeat;background-size:contain;display:inline-block;filter:brightness(0);vertical-align:middle}.scylla-icon--about-team{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMSwuY2xzLTJ7ZmlsbDpub25lO3N0cm9rZTpncmF5O3N0cm9rZS1taXRlcmxpbWl0OjEwfS5jbHMtMntzdHJva2UtbGluZWNhcDpyb3VuZH08L3N0eWxlPjwvZGVmcz48ZyBpZD0iQ2FscXVlXzQiIGRhdGEtbmFtZT0iQ2FscXVlIDQiPjxwYXRoIGNsYXNzPSJjbHMtMSIgZD0iTTQuNjYgOS44MSAyLjYzIDExYTIuMDggMi4wOCAwIDAgMC0xLjEzIDEuODN2Ny44MWMuMTkgMS4xMS41IDEuNTMgMS41IDEuNDdNNy4wNiA5Ljk0bDEuNDQuOTQiLz48cGF0aCBjbGFzcz0iY2xzLTIiIGQ9Ik0zLjUgMTguNXY1LjM0TTkuNSAxOC41djUuMzRNOC41NCAxOC40MnY1LjMzTTE1LjUgMTguNXY1LjM0TTE2LjUgMTguNXY1LjM0TTMuMzMgMjAuNTNoNS4wOE0xMS40NSA4Ljg0bC4wNi4wNmExLjY1IDEuNjUgMCAwIDAgMi4zNCAwaDAiLz48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Ik0xMi40MiA3LjVhMS44MSAxLjgxIDAgMCAxLTEuOTItMS43N1Y1YTEuOTQgMS45NCAwIDAgMSAxLjkyLTIgMi4wNyAyLjA3IDAgMCAxIDIuMDggMnYuNzdhMiAyIDAgMCAxLTIuMDggMS43M1pNMTEuNDIgOC43NCA5LjYzIDkuOWEyLjA3IDIuMDcgMCAwIDAtMS4xMyAxLjg1djcuODJBMS40NyAxLjQ3IDAgMCAwIDEwIDIxTTEzLjc1IDkuMThsMiAuNjVjLjcuMzUuNzYgMS4wNi43NiAxLjg0djcuOWMwIC43Ny0uMjMgMS4yNC0xIDEuMjQiLz48cGF0aCBjbGFzcz0iY2xzLTIiIGQ9Ik05LjkzIDE5LjVoNS40Ii8+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNMTkuNDIgOS4xMmEyLjA3IDIuMDcgMCAwIDAgMi4wOC0xLjkzdi0uNzdhMi4wNyAyLjA3IDAgMCAwLTIuMDgtMS45MiAxLjkzIDEuOTMgMCAwIDAtMS45MiAxLjkydi43N2ExLjk0IDEuOTQgMCAwIDAgMS45MiAxLjkzWk01LjU5IDkuMTJhMS45MyAxLjkzIDAgMCAwIDEuOTItMS45M3YtLjc3QTEuOTMgMS45MyAwIDAgMCA1LjU5IDQuNSAyLjA4IDIuMDggMCAwIDAgMy41IDYuNDJ2Ljc3YTIuMDggMi4wOCAwIDAgMCAyLjA5IDEuOTNaTTIwLjQ0IDkuODFsMiAxLjE3YTIuMDYgMi4wNiAwIDAgMSAxLjEzIDEuODV2Ny44MWMtLjE4IDEuMTEtLjQ3IDEuNTMtMS40NyAxLjQ3TTE4LjA0IDkuOTRsLTEuNDQuOTMiLz48cGF0aCBjbGFzcz0iY2xzLTIiIGQ9Ik0yMS42IDE4LjV2NS4zNE0yMS43NyAyMC41M2gtNS4wOCIvPjwvZz48L3N2Zz4=)}.scylla-icon--about-us{background-image:url(data:image/svg+xml;base64,PHN2ZyBpZD0iTGF5ZXJfMyIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB2aWV3Qm94PSIwIDAgMjAgMjAiPjxkZWZzPjxzdHlsZT4uY2xzLTF7ZmlsbDpub25lO3N0cm9rZTojMDAwO3N0cm9rZS1saW5lY2FwOnJvdW5kO3N0cm9rZS1saW5lam9pbjpyb3VuZDtzdHJva2Utd2lkdGg6LjhweH08L3N0eWxlPjwvZGVmcz48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Ik02LjI4IDE5LjQ4Yy0uMTIuMDgtLjA4LjA3LS4yMy4xLS41OC4wOS0xLjEyLS4yOC0xLjI1LS44NCAwIDAtMi4zLTkuMTgtMi4zLTExLjExQzIuNSAzLjYgNS44OC40NCAxMC4zOC40NFMxNy41IDMuNDggMTcuNSA3LjVjMCAxLjkzLTEuMzIgMTEuMjMtMS4zMiAxMS4yMy0uMTMuNTYtLjY3Ljk0LTEuMjUuODQtLjEyLS4wMi0uMTMgMC0uMjMtLjA3Ii8+PHBhdGggZD0iTTE1Ljc1IDE1Ljc1Yy0uMTcgMS4xNS0uMjIgMi4zNC0uNTUgMy40Ni0uMzcuODUtMS42MyAxLjA2LTIuMjIuMzMtLjI1LS4yOC4xOS0uNjguNDQtLjQuNDMuNDYgMS4yNC4xOCAxLjMxLS40NGwuMDYtLjM0Yy4xOS0uODkuMzUtMS43OS41Ny0yLjY4LjA1LS4yNC40Mi0uMTcuMzkuMDdaIi8+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNMTEuNSA3YzAgMS45LTEuNTYgMy41LTMuNDYgMy41UzQuNSA4LjkgNC41IDdzMS42NC0zLjUgMy41NC0zLjVTMTEuNSA1LjEgMTEuNSA3WiIvPjxwYXRoIGQ9Ik04LjU1IDQuNzVjLS41OS4xMi0uNzEgMS40Mi0uMzYgMS43OC4yMy4yMy43MS4zMS43MS40N3MtLjQ4LjI0LS43MS40N2MtLjM2LjM2LS4yNCAxLjY2LjM2IDEuNzguNzEuMTQgMS43OC0uNzEgMS43OC0yLjI1UzkuMjYgNC42MSA4LjU1IDQuNzVaTTYuNTEgMTIuMmMyLjEyLjMxIDQuMzQtLjIgNS42OC0xLjk2LjMyLS40MS45Ni4xMS42Mi41MS0uNzYuOS0xLjc4IDEuNjMtMi45MyAxLjk1LTEuMTQuMzMtMi4zMy4zMS0zLjQ2LjE2YS4zNC4zNCAwIDAgMS0uMjktLjM4Yy4wMi0uMTguMTktLjMxLjM3LS4yOVpNNy45NyAxOS41OWMtLjk5Ljk2LTIuMzYuMDgtMi4zNi0xLjE1LS4xMi0uOS0uMjctMS43OS0uMzctMi42OS0uMDEtLjExLjA3LS4yMS4xOC0uMjIuMS0uMDEuMTkuMDYuMjEuMTUuMjIuODguMzggMS43Ny41NiAyLjY2LjAxLjc4LjY4IDEuMzggMS4zNS44My4yNy0uMjcuNjkuMTYuNDIuNDNaIi8+PHBhdGggZD0iTTkuNzUgMTkuMjdjLS40Mi45LTEuOC45Ni0yLjMyLjExLS41LTEuMTMtLjMxLTIuNS0uNDctMy43MiAwLS4xMS4wOC0uMi4xOS0uMjEuMSAwIC4xOS4wNy4yMS4xNy4xNy45NS4yOCAxLjkxLjQyIDIuODcuMDEuNDUuMjMuNzQuNTcuODUuMzMuMS43MS0uMDUuODgtLjM2LjE4LS4zNC43MS0uMDUuNTIuMjlaTTE0LjAzIDE1LjY2Yy0uMTYgMS4yMy4wMyAyLjU3LS40NiAzLjcyLS41Mi44Ni0xLjkxLjc5LTIuMzItLjExLS4xNy0uMzQuMzUtLjYxLjUzLS4yOC40Mi43MSAxLjQ4LjM4IDEuNDUtLjQ5LjE0LS45Ni4yNS0xLjkyLjQyLTIuODcuMDQtLjI0LjQxLS4yLjQuMDRaIi8+PHBhdGggZD0iTTExLjg1IDE1LjU0Yy4wMi43OS4wMSAxLjU4LjAxIDIuMzctLjAyLjQxLjA3LjktLjE0IDEuMjktLjQzIDEuMDItMi4wMSAxLjAyLTIuNDUgMC0uMjEtLjM5LS4xMy0uODktLjE0LTEuMjkgMC0uNzkgMC0xLjU4LjAxLTIuMzcgMC0uMTEuMS0uMi4yMS0uMTkuMSAwIC4xOC4wOC4xOS4xOC4wNy43OS4xIDEuNTguMTUgMi4zNy4wMy4yNyAwIC44Mi4xMyAxLjA0LjEzLjI2LjQuNDMuNjguNDIuNDYgMCAuNzktLjQuNzctLjg3bC4wMy0uNTljLjA0LS43OS4wOC0xLjU4LjE1LTIuMzcuMDItLjI0LjQtLjIzLjQuMDFaIi8+PC9zdmc+)}.scylla-icon--about-us-m{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNi4zOCAzMi40MyI+PHBhdGggZD0iTTYuNTUgMzEuNjRjLS4yLjEzLS40My4yMi0uNjkuMjZhMS44MSAxLjgxIDAgMCAxLTIuMDYtMS4zOVMuNDkgMTQuOTkuNDkgMTEuODJDLjUgNS4xOSA1Ljc3LjUgMTMuMTkuNXMxMi42OSA0LjY5IDEyLjY5IDExLjMyYzAgMy4xOC0zLjMxIDE4LjY5LTMuMzEgMTguNjlhMS44MSAxLjgxIDAgMCAxLTIuNjIgMS4yIiBzdHlsZT0iZmlsbDpub25lO3N0cm9rZTojMDAwO3N0cm9rZS1saW5lY2FwOnJvdW5kO3N0cm9rZS1saW5lam9pbjpyb3VuZCIvPjxwYXRoIGQ9Ik0yMS44NiAyNS4zNmMtLjI4IDEuOS0uMzcgMy44Ni0uOTEgNS43MS0uNjEgMS40MS0yLjY4IDEuNzUtMy42Ni41NS0uNDEtLjQ3LjMxLTEuMTEuNzMtLjY2LjcxLjc2IDIuMDQuMjkgMi4xNi0uNzMuMzItMS42Ni42NS0zLjMzIDEuMDQtNC45OC4wOS0uMzkuNy0uMjguNjUuMTFaIi8+PHBhdGggZD0iTTE0LjggMTAuNTdjMCAzLjEzLTIuNTMgNS42Ni01LjY2IDUuNjZzLTUuNDctMi41My01LjQ3LTUuNjYgMi4zNC01LjY2IDUuNDctNS42NiA1LjY2IDIuNTMgNS42NiA1LjY2WiIgc3R5bGU9InN0cm9rZS13aWR0aDouOXB4O2ZpbGw6bm9uZTtzdHJva2U6IzAwMDtzdHJva2UtbGluZWNhcDpyb3VuZDtzdHJva2UtbGluZWpvaW46cm91bmQiLz48cGF0aCBkPSJNMTAuMzEgNi44NmMtLjk4LjItMS4xNyAyLjM0LS41OSAyLjkzLjM4LjM4IDEuMTcuNTEgMS4xNy43OHMtLjc5LjQtMS4xNy43OGMtLjU5LjU5LS4zOSAyLjczLjU5IDIuOTMgMS4xNi4yMyAyLjkzLTEuMTcgMi45My0zLjcxcy0xLjc2LTMuOTQtMi45My0zLjcxWk02LjgyIDE4LjUxYzMuNDkuODkgNi45Ny0uNSA5LjUxLTIuOTMuNDctLjQ0IDEuMTYuMzEuNjguNzQtMS4zOCAxLjIzLTIuOTggMi4yOS00Ljc5IDIuODctMS44LjU5LTMuNzcuNTgtNS41OC4xNGEuNDIxLjQyMSAwIDAgMS0uMzEtLjVjLjA1LS4yMi4yOC0uMzYuNS0uMzFaIi8+PHBhdGggZD0iTTE2LjczIDE2LjY3Yy0uMTItLjQ2LS41MS0uODMtLjk5LS44My0uNzUtLjAyLS41OS0xLjE3LjE0LS45OS44MS4xNiAxLjQzLjg1IDEuNSAxLjY2LjA4LjQtLjU0LjU0LS42NS4xNVpNOS4wMyAzMS43Yy0xLjI2IDEuMzYtMy42Mi40NS0zLjgtMS4zNWwtLjA5LS41NWMtLjIxLTEuNDgtLjQ1LTIuOTUtLjYtNC40NC0uMDItLjE4LjExLS4zNC4yOS0uMzYuMTctLjAyLjMyLjA5LjM1LjI1LjM5IDEuNjMuNzEgMy4yOCAxLjAzIDQuOTMuMDkgMS4wMiAxLjM4IDEuNTQgMi4xMi44MS40NS0uNDQgMS4xNC4yNi42OS43WiIvPjxwYXRoIGQ9Ik0xMS45NiAzMS4xNmMtMSAxLjk4LTQuMDQgMS4zLTQuMjEtLjg4LS4xNS0xLjY5LS4zLTMuMzgtLjM5LTUuMDcgMC0uMTguMTMtLjM0LjMxLS4zNC4xNyAwIC4zMS4xMS4zNC4yNy4yOCAxLjY3LjUgMy4zNS43MiA1LjAzLjA5IDEuMiAxLjc3IDEuNTkgMi4zNi41MS4zMS0uNTYgMS4xNi0uMDkuODcuNDdaTTE5LjAzIDI1LjIxYy0uMDggMS42OS0uMjQgMy4zOC0uMzkgNS4wNy0uMDQuMzctLjE3Ljc1LS4zOCAxLjA2LS44NiAxLjQtMy4xMSAxLjMxLTMuODMtLjE3LS4zLS41Ni41NS0xLjAzLjg2LS40OC41OSAxLjA4IDIuMjcuNjkgMi4zNS0uNTIuMjItMS42OC40My0zLjM2LjcyLTUuMDMuMDYtLjQuNjgtLjMzLjY1LjA3WiIvPjxwYXRoIGQ9Ik0xNS40MyAyNS4wMmMuMDQgMS4zMS4wMiAyLjYxLjAyIDMuOTEtLjAzLjY3LjExIDEuNDgtLjIzIDIuMTMtLjc0IDEuNjktMy4yOSAxLjY5LTQuMDMgMC0uMzQtLjY1LS4yMS0xLjQ3LS4yNC0yLjEzIDAtMS4zLS4wMi0yLjYxLjAyLTMuOTEgMC0uMTguMTYtLjMyLjM0LS4zMi4xNyAwIC4zLjE0LjMyLjMuMTEgMS4zLjE3IDIuNi4yNCAzLjkxLjA1LjQ1IDAgMS4zNS4yMSAxLjcyLjIxLjQzLjY2LjcxIDEuMTIuNy40Ni4wMi45MS0uMjcgMS4xMi0uNjkuMjItLjM2LjE2LTEuMjguMjEtMS43Mi4wNy0xLjMuMTMtMi42MS4yNC0zLjkxLjAyLS40LjY2LS4zOC42Ni4wMloiLz48L3N2Zz4=)}.scylla-icon--alternator{background-image:url(data:image/svg+xml;base64,PHN2ZyBpZD0iTGF5ZXJfMyIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB2aWV3Qm94PSIwIDAgMjAgMjAiPjxkZWZzPjxzdHlsZT4uY2xzLTF7ZmlsbDpub25lO3N0cm9rZTojMDAwO3N0cm9rZS1saW5lY2FwOnJvdW5kO3N0cm9rZS1saW5lam9pbjpyb3VuZH08L3N0eWxlPjwvZGVmcz48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Ik0xNy41IDIuOTFjMCAxLjI4LTMuNjcgMi41OS04IDIuNTlzLTgtMS4zMS04LTIuNTlTNS4wOS41IDkuNDIuNXM4LjA4IDEuMTMgOC4wOCAyLjQxWk0xNy41IDcuNjZjMCAxLjI4LTMuNjMgMi44LTcuOTYgMi44UzEuNSA4LjkzIDEuNSA3LjY2TTE3LjUgMTIuNDdjMCAxLjI4LTMuNjcgMy4wMy04IDMuMDNzLTgtMS43NS04LTMuMDNNMTcuNSAxNy4yOWMwIDEuMjgtMy43NSAyLjMtOC4wOCAyLjNzLTcuOTItMS4wMy03LjkyLTIuM00xLjUgMTcuMTlWMi45MU0xNy41IDE3LjE5VjIuOTEiLz48L3N2Zz4=)}.scylla-icon--apps{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyMSAxOSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOm5vbmU7c3Ryb2tlOiM0ZDRkNGQ7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJDYWxxdWVfNCIgZGF0YS1uYW1lPSJDYWxxdWUgNCI+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNLjUgMS41aDIwdjE0SC41ek03LjUgMTUuNzR2Mi44OU0xMi44MyAxNS42M3YyLjMyTTUuNSAxOC41aDkuMTQiLz48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Im0zLjY0IDUuNTYgNC41OCAyLjkxLTQuNTggMi45Mk05LjEgMTIuMDhoNC4zMiIvPjwvZz48L3N2Zz4=)}.scylla-icon--architecture{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMSwuY2xzLTIsLmNscy01e2ZpbGw6bm9uZTtzdHJva2U6Z3JheX0uY2xzLTF7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfS5jbHMtMiwuY2xzLTV7c3Ryb2tlLW1pdGVybGltaXQ6MTB9LmNscy0ye3N0cm9rZS13aWR0aDouOThweH0uY2xzLTV7c3Ryb2tlLXdpZHRoOi45OXB4fTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJDYWxxdWVfMiIgZGF0YS1uYW1lPSJDYWxxdWUgMiI+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNMS45IDEwLjI3YTEwLjgzIDEwLjgzIDAgMCAxIDguNzMtOC4zOE0xMC41MSAyMy4wOEExMC43OSAxMC43OSAwIDAgMSAxLjc3IDE0TTIzLjIzIDE0YTEwLjgxIDEwLjgxIDAgMCAxLTkgOS4xMU0xNC4yNyAxLjg4YTEwLjgxIDEwLjgxIDAgMCAxIDguODMgOC4zNyIvPjxjaXJjbGUgY2xhc3M9ImNscy0yIiBjeD0iMTIuMjUiIGN5PSIxLjc1IiByPSIxLjc1Ii8+PGNpcmNsZSBjbGFzcz0iY2xzLTIiIGN4PSIxMi4yNSIgY3k9IjIyLjc1IiByPSIxLjc1Ii8+PGNpcmNsZSBjeD0iNC45MiIgY3k9IjQuNzUiIHI9IjEuNzUiIHN0eWxlPSJzdHJva2Utd2lkdGg6Ljk5cHg7ZmlsbDpncmF5O3N0cm9rZS1taXRlcmxpbWl0OjEwO3N0cm9rZTpncmF5Ii8+PGNpcmNsZSBjeD0iMjAuMDkiIGN5PSIxOS45MSIgcj0iMS43NSIgc3R5bGU9InN0cm9rZS13aWR0aDouOTlweDtmaWxsOmdyYXk7c3Ryb2tlLW1pdGVybGltaXQ6MTA7c3Ryb2tlOmdyYXkiLz48Y2lyY2xlIGNsYXNzPSJjbHMtNSIgY3g9IjEuNzUiIGN5PSIxMi4yNSIgcj0iMS43NSIvPjxjaXJjbGUgY2xhc3M9ImNscy01IiBjeD0iMjMuMjUiIGN5PSIxMi4yNSIgcj0iMS43NSIvPjxjaXJjbGUgY3g9IjQuNzUiIGN5PSIxOS42NCIgcj0iMS43NSIgc3R5bGU9InN0cm9rZS13aWR0aDouOTlweDtmaWxsOmdyYXk7c3Ryb2tlLW1pdGVybGltaXQ6MTA7c3Ryb2tlOmdyYXkiLz48Y2lyY2xlIGN4PSIxOS45MSIgY3k9IjQuNDgiIHI9IjEuNzUiIHN0eWxlPSJzdHJva2Utd2lkdGg6Ljk5cHg7ZmlsbDpncmF5O3N0cm9rZS1taXRlcmxpbWl0OjEwO3N0cm9rZTpncmF5Ii8+PC9nPjwvc3ZnPg==)}.scylla-icon--benchmarks{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVqb2luOnJvdW5kO3N0cm9rZS13aWR0aDozcHh9PC9zdHlsZT48L2RlZnM+PGcgaWQ9IkNhbHF1ZV8yIiBkYXRhLW5hbWU9IkNhbHF1ZSAyIj48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Ik01LjUxIDI0Ljkxdi01Ljg1TTEyLjU3IDI0Ljkxdi05Ljc0TTE5LjYyIDI0LjkxVjEwLjE1Ii8+PHBhdGggc3R5bGU9InN0cm9rZS1saW5lY2FwOnJvdW5kO2ZpbGw6bm9uZTtzdHJva2U6Z3JheTtzdHJva2UtbGluZWpvaW46cm91bmQiIGQ9Im0uOTEgMTQuOTggNS4xMy03Ljk0IDYuMjUgNS44OEwyNCAxIi8+PHBhdGggc3R5bGU9ImZpbGw6Z3JheSIgZD0ibTI1IDUtNS01aDV2NXoiLz48L2c+PC9zdmc+)}.scylla-icon--blog{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJDYWxxdWVfNCIgZGF0YS1uYW1lPSJDYWxxdWUgNCI+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJtOSAxNS0yLjUtMS41IDgtMTJMMTcgMyA5IDE1eiIvPjxwYXRoIHN0eWxlPSJmaWxsOmdyYXk7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kIiBkPSJtNi41IDEzLjUtLjUgM0w5IDE1bC0yLjUtMS41eiIvPjxwYXRoIGNsYXNzPSJjbHMtMSIgZD0iTTE5LjI1IDIuNWg0LjI1djE2aC0xM3Y0LjE3TDYuNDYgMTguNWwtNC45Ni0uMDRWMi41aDguMzFNMTQuNSAyLjVsMS42NyAxLjMzIi8+PC9nPjwvc3ZnPg==)}.scylla-icon--careers{background-image:url(data:image/svg+xml;base64,PHN2ZyBpZD0iQ2FscXVlXzEiIGRhdGEtbmFtZT0iQ2FscXVlIDEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmlld0JveD0iMCAwIDI1IDI1Ij48ZGVmcz48c3R5bGU+LmNscy0xe2ZpbGw6bm9uZTtzdHJva2U6Z3JheTtzdHJva2UtbGluZWNhcDpyb3VuZDtzdHJva2UtbGluZWpvaW46cm91bmR9PC9zdHlsZT48L2RlZnM+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNMS41IDExLjU1djhjMCAuNTYgMS4wNyAyIDIgMmgxOGMuODkgMCAyLTEuNDQgMi0ydi04Ii8+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNMjMuMzEgMy41SDEuODFjLS40OCAwLTEuMzEuNTUtMS4zMSAxdjZsMTAgMmE4LjQ1IDguNDUgMCAwIDAgNCAwbDEwLTJ2LTZjMC0uNDUtLjcyLTEtMS4xOS0xWk0xNS42MiAzLjV2LTFjMC0uNzYtLjYxLTEtMS4zOC0xaC0zLjQ1Yy0uNzYgMC0xLjM4LjI0LTEuMzggMXYxIi8+PHJlY3QgeD0iMTAiIHk9IjExIiB3aWR0aD0iNSIgaGVpZ2h0PSIzLjk5IiByeD0iLjU1IiByeT0iLjU1IiBzdHlsZT0iZmlsbDpncmF5Ii8+PC9zdmc+)}.scylla-icon--chevron-left{background-image:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTAiIGhlaWdodD0iMTYiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZD0iTTguMDkyIDE2IDEwIDE0LjExMyAzLjgxNyA4IDEwIDEuODg3IDguMDkyIDAgMCA4bDguMDkyIDhaIiBmaWxsPSIjMDAwIi8+PC9zdmc+)}.contents.local>ul>li a:before,.scylla-icon--chevron-right,.secondary-side-nav__content li a:before{background-image:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTAiIGhlaWdodD0iMTYiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZD0iTTEuOTA4IDAgMCAxLjg4NyA2LjE4MyA4IDAgMTQuMTEzIDEuOTA4IDE2IDEwIDggMS45MDggMFoiIGZpbGw9IiMwMDAiLz48L3N2Zz4=)}.scylla-icon--circe{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAzOCAzMCI+PGRlZnM+PHN0eWxlPi5jbHMtMiwuY2xzLTN7ZmlsbDpub25lO3N0cm9rZTojNGQ0ZDRkO3N0cm9rZS1saW5lY2FwOnJvdW5kO3N0cm9rZS1saW5lam9pbjpyb3VuZH0uY2xzLTN7c3Ryb2tlLXdpZHRoOjEuMTFweH08L3N0eWxlPjwvZGVmcz48ZyBpZD0iQ2FscXVlXzQiIGRhdGEtbmFtZT0iQ2FscXVlIDQiPjxwYXRoIGQ9Ik0yMi4xIDEyaC02LjE2YTEuMDYgMS4wNiAwIDAgMS0uOTQtMS4wNy45My45MyAwIDAgMSAuOTQtLjkzaDYuMTZhLjkzLjkzIDAgMCAxIC45NC45M0ExLjA2IDEuMDYgMCAwIDEgMjIuMSAxMloiIHN0eWxlPSJmaWxsOiM0ZDRkNGQiLz48cGF0aCBjbGFzcz0iY2xzLTIiIGQ9Ik0xMy40NCA0LjQ5SDkuNTF2MjRoMTl2LTI0SDI0LjUiLz48cGF0aCBjbGFzcz0iY2xzLTMiIGQ9Ik0xMyAzLjQ5SDguNWwtLjA4IDI2LjFIMjkuNVYzLjM5SDI1Ii8+PHBhdGggY2xhc3M9ImNscy0yIiBkPSJNMTIuNSAxOC4zOGgxM00xMi41IDE1LjQ5aDEzTTEyLjUgMjEuNDNoMTNNMTIuNSAyNC40N2gxM00xMy41IDIuNWgxMXYzLjk4aC0xMXoiLz48cGF0aCBjbGFzcz0iY2xzLTMiIGQ9Ik0yMS41LjVoLTUuMDR2MS45NWw1LjA0LjA1di0yeiIvPjwvZz48L3N2Zz4=)}.scylla-icon--clock{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyMSAxOSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOm5vbmU7c3Ryb2tlOiM0ZDRkNGQ7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJDYWxxdWVfNCIgZGF0YS1uYW1lPSJDYWxxdWUgNCI+PGNpcmNsZSBjbGFzcz0iY2xzLTEiIGN4PSIxMC41IiBjeT0iOS41IiByPSI5Ii8+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNMTAuNSAzLjV2NmwzLjA2IDMiLz48L2c+PC9zdmc+)}.scylla-icon--close{background-image:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMzQiIGhlaWdodD0iMzQiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGcgY2xpcC1wYXRoPSJ1cmwoI2EpIiBmaWxsPSIjZmZmIj48cGF0aCBkPSJNMTEuNjcgMjIuMTNhLjU2NC41NjQgMCAwIDEtLjM5OC0uOTYybDkuODk2LTkuODk2YS41NjMuNTYzIDAgMSAxIC43OTcuNzk3bC05Ljg5NiA5Ljg5NmEuNTU5LjU1OSAwIDAgMS0uMzk5LjE2NVoiLz48cGF0aCBkPSJNMjEuNTY2IDIyLjEzYS41NTkuNTU5IDAgMCAxLS4zOTgtLjE2NWwtOS44OTYtOS44OTZhLjU2My41NjMgMCAxIDEgLjc5Ny0uNzk3bDkuODk2IDkuODk1YS41NjQuNTY0IDAgMCAxLS4zOTkuOTYzWiIvPjxwYXRoIGQ9Ik0xNi42MTkgMzMuMjM3QzcuNDU1IDMzLjIzNyAwIDI1Ljc4MiAwIDE2LjYxOSAwIDcuNDU2IDcuNDU1IDAgMTYuNjE5IDBzMTYuNjE5IDcuNDU1IDE2LjYxOSAxNi42MTktNy40NTYgMTYuNjE4LTE2LjYyIDE2LjYxOFptMC0zMi4xMWMtOC41NDIgMC0xNS40OTIgNi45NS0xNS40OTIgMTUuNDkyIDAgOC41NDIgNi45NSAxNS40OTIgMTUuNDkyIDE1LjQ5MiA4LjU0MiAwIDE1LjQ5Mi02Ljk1IDE1LjQ5Mi0xNS40OTIgMC04LjU0Mi02Ljk1LTE1LjQ5Mi0xNS40OTItMTUuNDkyWiIvPjwvZz48ZGVmcz48Y2xpcFBhdGggaWQ9ImEiPjxwYXRoIGZpbGw9IiNmZmYiIGQ9Ik0wIDBoMzMuMjM3djMzLjIzN0gweiIvPjwvY2xpcFBhdGg+PC9kZWZzPjwvc3ZnPg==)}.scylla-icon--cloud{background-image:url(data:image/svg+xml;base64,PHN2ZyBpZD0iTGF5ZXJfMiIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB2aWV3Qm94PSIwIDAgNDMuMDQgMzIuMDMiPjxkZWZzPjxzdHlsZT4uY2xzLTF7ZmlsbDpub25lO3N0cm9rZTojMWQxZDFiO3N0cm9rZS1saW5lY2FwOnJvdW5kO3N0cm9rZS1saW5lam9pbjpyb3VuZH08L3N0eWxlPjwvZGVmcz48ZyBpZD0iTGF5ZXJfMyI+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNNDIuNTQgNC4wNmMwIDEuNjgtMy42MyAyLjQ0LTkgMi40NHMtMTAtLjczLTEwLTIuNFMyNy42Ny41IDMzLjA0LjVzOS41IDEuODkgOS41IDMuNTZaTTQyLjU0IDkuNjNjMCAxLjY4LTMuNzYgMi45MS05LjEyIDIuOTFzLTkuODQtMS4yMy05Ljg0LTIuOTFNNDIuNTQgMTUuMzRjMCAxLjY4LTMuNjggMy4yNS05LjA0IDMuMjUtNCAwLTcuNi0uOTYtOS4wOS0yLjA0TTQyLjU0IDIwLjY1YzAgMS42OC0zLjcyIDIuOTctOS4wOCAyLjk3TTIzLjU0IDE1LjQ2VjQuMU00Mi41NCAyMC43N1Y0LjEiLz48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Ik0yOC4xMSAyMS4wOGMtLjg3IDAtMS42Ny4yMy0yLjM5LjYxIDAtLjA3LjAxLS4xNC4wMS0uMjEgMC00Ljg1LTMuODMtOC45LTguNjgtOC45cy04Ljg4IDQuMDUtOC44OCA4LjljMCAuMTcuMDIuMzQuMDMuNTEtLjg0LS41Ny0xLjg1LS45MS0yLjk1LS45MS0yLjg4IDAtNC43NCAyLjU3LTQuNzQgNS40NnMxLjg2IDQuOTkgNC43NCA0Ljk5aDIyLjg2YzIuODggMCA1LjUyLTIuMjcgNS41Mi01LjE2cy0yLjYzLTUuMjktNS41Mi01LjI5WiIvPjwvZz48L3N2Zz4=)}.scylla-icon--cloud-docs{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyMSAxOSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOm5vbmU7c3Ryb2tlOiM0ZDRkNGQ7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJDYWxxdWVfNCIgZGF0YS1uYW1lPSJDYWxxdWUgNCI+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNNi41IDExLjVoOHYxaC04ek0xNS42NSA2LjU1YTMuNDIgMy40MiAwIDAgMC0zLjE1IDIiLz48cGF0aCBkPSJNMTAuMDYgMi44QTUuMTcgNS4xNyAwIDAgMSAxNSA2LjM1aC4yNGE0Ljg0IDQuODQgMCAwIDEgMCA5LjY3aC0xMWEzLjQ1IDMuNDUgMCAwIDEgMC02LjlBMy4xNyAzLjE3IDAgMCAxIDUgOS4yIDUuMzMgNS4zMyAwIDAgMSA0Ljg2IDhhNS4yIDUuMiAwIDAgMSA1LjItNS4ybTAtLjhhNiA2IDAgMCAwLTYgNnYuMzFhNC4yNSA0LjI1IDAgMCAwIC4xOCA4LjQ5aDExYTUuNjMgNS42MyAwIDAgMCAuMy0xMS4yNkE2IDYgMCAwIDAgMTAuMDYgMloiIHN0eWxlPSJmaWxsOiM0ZDRkNGQiLz48L2c+PC9zdmc+)}.scylla-icon--comparison{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMSwuY2xzLTIsLmNscy00e2ZpbGw6bm9uZTtzdHJva2U6Z3JheX0uY2xzLTEsLmNscy0ye3N0cm9rZS1taXRlcmxpbWl0OjEwfS5jbHMtMiwuY2xzLTR7c3Ryb2tlLWxpbmVjYXA6cm91bmR9LmNscy00e3N0cm9rZS1saW5lam9pbjpyb3VuZH08L3N0eWxlPjwvZGVmcz48ZyBpZD0iQ2FscXVlXzQiIGRhdGEtbmFtZT0iQ2FscXVlIDQiPjxwYXRoIGNsYXNzPSJjbHMtMSIgZD0iTTQuNSAxMy42M3YyLjg4aDYuMDZNMjAuNSAxMy41NHYyLjk2bC01LjUuMDEiLz48cGF0aCBjbGFzcz0iY2xzLTIiIGQ9Ik0xMi41IDE4LjV2Mi43Mk03LjUgMjEuNWgxMCIvPjxjaXJjbGUgY3g9IjEyLjUiIGN5PSIxNi41IiByPSIyIiBzdHlsZT0iZmlsbDpncmF5O3N0cm9rZS13aWR0aDouOTVweDtzdHJva2UtbWl0ZXJsaW1pdDoxMDtzdHJva2U6Z3JheSIvPjxwYXRoIGNsYXNzPSJjbHMtNCIgZD0iTTUuMDYgMTMuNThIMy44OEEzLjEgMy4xIDAgMCAxIC41IDEwLjVoOGEzLjE2IDMuMTYgMCAwIDEtMy40NCAzLjA4Wk0yMSAxMy41OGgtMS4xN2EzLjA5IDMuMDkgMCAwIDEtMy4zNy0zLjA3aDhBMy4xNiAzLjE2IDAgMCAxIDIxIDEzLjU4Wk03LjQ2IDUuMTJjMCAuNTctMS4xLjQ2LTIuNzkuNDZTMS41OCA1LjYgMS41OCA1IDMgNC40IDQuNjkgNC40czIuNzcuMTYgMi43Ny43MlpNMS41IDkuODVWNS4zMU03LjUgMTAuMzVWNS44MU0yMy41IDUuMTJjMCAuNTctMS4xLjQ2LTIuNzkuNDZzLTMuMDkgMC0zLjA5LS41NFMxOSA0LjQgMjAuNzMgNC40czIuNzcuMTYgMi43Ny43MlpNMTcuNTQgOS44NVY1LjMxTTIzLjU0IDEwLjM1VjUuODEiLz48L2c+PC9zdmc+)}.scylla-icon--contact-us{background-image:url(data:image/svg+xml;base64,PHN2ZyBpZD0iQ2FscXVlXzEiIGRhdGEtbmFtZT0iQ2FscXVlIDEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmlld0JveD0iMCAwIDI1IDI1Ij48ZGVmcz48c3R5bGU+LmNscy0xe2ZpbGw6bm9uZTtzdHJva2U6Z3JheTtzdHJva2UtbGluZWNhcDpyb3VuZDtzdHJva2UtbGluZWpvaW46cm91bmQ7c3Ryb2tlLXdpZHRoOjEuMDZweH08L3N0eWxlPjwvZGVmcz48cGF0aCBjbGFzcz0iY2xzLTEiIHRyYW5zZm9ybT0icm90YXRlKC0yNy40OSAxNS41NTIgMTEuMDgzKSIgZD0iTTcuNzYgNi4wMWgxNS41OXYxMC4xM0g3Ljc2eiIvPjxwYXRoIGNsYXNzPSJjbHMtMSIgZD0ibTYuMyAxMC4xOCA4LjYzIDEuNTZhMS40MiAxLjQyIDAgMCAwIDEuNTMtLjc0bDMuNjctOE0xMS4wMiAxOS4wM2wxLjc0LTVNMjQuNTkgMTEuOTdsLTUuMDktMS40NU03LjA5IDE3LjU4IDMuOSAxOS4zNE02LjA2IDE1LjQxLjU0IDE4LjM2Ii8+PC9zdmc+)}.scylla-icon--developers-blog{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOmdyYXl9PC9zdHlsZT48L2RlZnM+PGcgaWQ9IkNhbHF1ZV80IiBkYXRhLW5hbWU9IkNhbHF1ZSA0Ij48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Im02LjQ4IDEwLjU5LS41LjE3LjUuMTZMMTEgMTIuMTZWMTRsLTctMi40OVYxMGw3LTIuNXYxLjgzWk0xNCA5LjMyVjcuNWw3IDIuNXYxLjU0TDE0IDE0di0xLjgzbDQuMTQtMS4zLjQ0LS4xMy0uNDMtLjE0WiIvPjxwYXRoIHN0eWxlPSJmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kO3N0cm9rZS13aWR0aDouOThweCIgZD0iTTEuNSAyLjVoMjJ2MTZoLTEzdjQuMTdMNi40NiAxOC41bC00Ljk2LS4wNFYyLjV6Ii8+PC9nPjwvc3ZnPg==)}.scylla-icon--docs{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfS5jbHMtMntmaWxsOmdyYXl9PC9zdHlsZT48L2RlZnM+PGcgaWQ9IkNhbHF1ZV80IiBkYXRhLW5hbWU9IkNhbHF1ZSA0Ij48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Ik0zLjUgMi41MWgxNi45NHYyMC45MUgzLjV6Ii8+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJtMjIuNDUgMjEuNS4wNS0yMWgtMTdhMi4xNiAyLjE2IDAgMCAwLTIgMiIvPjxwYXRoIGNsYXNzPSJjbHMtMiIgZD0iTTYgNmg3djJINnpNNiA5aDExdjJINnoiLz48L2c+PC9zdmc+)}.scylla-icon--enterprise{background-image:url(data:image/svg+xml;base64,PHN2ZyBpZD0iTGF5ZXJfMyIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB2aWV3Qm94PSIwIDAgMjAgMjAiPjxkZWZzPjxzdHlsZT4uY2xzLTEsLmNscy0ye2ZpbGw6bm9uZTtzdHJva2U6IzAwMDtzdHJva2UtbGluZWNhcDpyb3VuZDtzdHJva2UtbGluZWpvaW46cm91bmR9LmNscy0ye3N0cm9rZS13aWR0aDoxLjA3cHh9PC9zdHlsZT48L2RlZnM+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJtMTMuNjIgNy41IDEuODgtMS4wOCAyIDIuMDh2N2gxTTE1LjUgMTUuNXYtNSIvPjxwYXRoIGNsYXNzPSJjbHMtMiIgZD0iTTUuNSAxNS41di0xMmw0LTIgNCAydjEyTTkuNSAxNS41VjEuNk03LjUgNS41djEwTTExLjUgNS41djEwIi8+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNNS41IDguNTQgMy40NiA3LjVsLTEuOTYuOTZ2Ny4wNGgtMU0zLjUgMTAuNXY1TS41IDE3LjVoMTgiLz48L3N2Zz4=)}.scylla-icon--enterprise-m{background-image:url(data:image/svg+xml;base64,PHN2ZyB2ZXJzaW9uPSIxLjEiIGlkPSJMYXllcl8yXzAwMDAwMDE2NzY4MDY2MDE5MjYzMjMyNzcwMDAwMDA1NDc1ODA5NTExODI4NjY2MDM2XyIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4PSIwIiB5PSIwIiB2aWV3Qm94PSIwIDAgNDMgMzEiIHN0eWxlPSJlbmFibGUtYmFja2dyb3VuZDpuZXcgMCAwIDQzIDMxIiB4bWw6c3BhY2U9InByZXNlcnZlIj48c3R5bGU+LnN0MHtmaWxsOm5vbmU7c3Ryb2tlOiMxZDFkMWI7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfTwvc3R5bGU+PGcgaWQ9IkxheWVyXzMiPjxwYXRoIGNsYXNzPSJzdDAiIGQ9Im0yOS42IDkuNSA0LTIgNi45IDQuMXYxNS45aDJNMzMuNiAyNy41VjcuNk0xNC42IDI3LjVWNC44TDIyLjUuNSAyOS42IDV2MjIuNU0yMi41IDI3LjVWMU0yNC41IDUuNmwzIDJNMjQuNSA5LjZsMyAyTTI0LjUgMTMuNmwzIDJNMjQuNSAxNy41bDMgMk0yNC41IDIxLjVsMyAyTTM1LjQgMTEuNmwzIDJNMzUuNCAxNS42bDMgMS45TTM1LjQgMTkuNWwzIDJNMzUuNCAyMy41bDMgMS45TTE4LjUgNS44djIxLjdNMTQuNiA5LjdsLTQuMS0yLjUtOCA0LjR2MTUuOWgtMk0xMC41IDI3LjVWNy4yTTEyLjUgMTEuNmwyIDFNMTIuNSAxNS42bDIgLjlNMTIuNSAxOS41bDIgMU0xMi41IDIzLjVsMi4xIDFNNi40IDEyLjR2MTUuMU0uNSAzMC41aDQyIi8+PC9nPjwvc3ZnPg==)}.scylla-icon--events{background-image:url(data:image/svg+xml;base64,PHN2ZyBpZD0iQ2FscXVlXzEiIGRhdGEtbmFtZT0iQ2FscXVlIDEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmlld0JveD0iMCAwIDI1IDI1Ij48ZGVmcz48c3R5bGU+LmNscy0xe2ZpbGw6bm9uZTtzdHJva2U6Z3JheTtzdHJva2UtbGluZWNhcDpyb3VuZDtzdHJva2UtbGluZWpvaW46cm91bmR9LmNscy0ye2ZpbGw6Z3JheX08L3N0eWxlPjwvZGVmcz48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Ik0yMi41IDIzLjVoLTIxdi0yMGgyMnYxNS4yMSIvPjxwYXRoIGNsYXNzPSJjbHMtMSIgZD0iTTQuNDIgMy41YzAtMS4zNiAxLjA5LTIgMi40NS0yYTIuNDYgMi40NiAwIDEgMSAwIDQuOTEgMi42MSAyLjYxIDAgMCAxLTEtLjIxTTEwLjY3IDMuNWMwLTEuMzYgMS4xLTIgMi40Ni0yYTIuNDYgMi40NiAwIDAgMSAwIDQuOTEgMi42MSAyLjYxIDAgMCAxLTEtLjIxTTE2LjkzIDMuNWMwLTEuMzYgMS4xLTIgMi40NS0yYTIuNDYgMi40NiAwIDEgMSAwIDQuOTEgMi41MiAyLjUyIDAgMCAxLTEtLjIxIi8+PHBhdGggY2xhc3M9ImNscy0yIiBkPSJNNyA5aDN2M0g3ek0xMiA5aDN2M2gtM3pNMTcgOWgzdjNoLTN6TTcgMTRoM3YzSDd6TTEyIDE0aDN2M2gtM3pNMTcgMTRoM3YzaC0zeiIvPjxwYXRoIGNsYXNzPSJjbHMtMSIgZD0iTTMuNSAzLjY3djE2LjY2TTMuNSAyMC40M2MwIDEuMjkuNDQgMi4zMyAxLjczIDIuMzNzMi4zMy0xLjkgMi4zMy0zLjE5bDE2Ljk0LS4wN2MwIDEuMjktLjU1IDMuMTItMS44MyAzLjEySDYuMyIvPjwvc3ZnPg==)}.admonition.note .admonition-title:before,.admonition.tip .admonition-title:before,.scylla-icon--exclamation{background-image:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PG1hc2sgaWQ9ImEiIG1hc2stdHlwZT0iYWxwaGEiIG1hc2tVbml0cz0idXNlclNwYWNlT25Vc2UiIHg9IjEiIHk9IjEiIHdpZHRoPSIyMiIgaGVpZ2h0PSIyMiI+PHBhdGggZD0iTTEyIDIzQzUuOSAyMyAxIDE4LjEgMSAxMlM1LjkgMSAxMiAxczExIDQuOSAxMSAxMS00LjkgMTEtMTEgMTFabTAtMjBjLTUgMC05IDQtOSA5czQgOSA5IDkgOS00IDktOS00LTktOS05WiIgZmlsbD0iI2ZmZiIvPjxwYXRoIGQ9Ik0xMiAxM2MtLjYgMC0xLS40LTEtMVY4YzAtLjYuNC0xIDEtMXMxIC40IDEgMXY0YzAgLjYtLjQgMS0xIDFaTTEyIDE3Yy0uMyAwLS41LS4xLS43LS4zLS4yLS4yLS4zLS40LS4zLS43IDAtLjEgMC0uMy4xLS40LjEtLjEuMS0uMi4yLS4zLjMtLjMuNy0uNCAxLjEtLjIuMSAwIC4xIDAgLjIuMSAwIDAgLjEuMS4yLjEuMS4xLjIuMi4yLjN2LjRjMCAuMSAwIC4zLS4xLjQtLjEuMS0uMS4yLS4yLjMtLjIuMi0uNC4zLS43LjNaIiBmaWxsPSIjZmZmIi8+PC9tYXNrPjxnIG1hc2s9InVybCgjYSkiPjxwYXRoIGZpbGw9IiNmZmYiIGQ9Ik0wIDBoMjR2MjRIMHoiLz48L2c+PC9zdmc+)}.collapsible-button i,.scylla-icon--expand{background-image:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYuMDAxIiBoZWlnaHQ9IjE2IiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjxwYXRoIGQ9Ik01IDEzYTEgMSAwIDAgMS0uNzEtLjI5bC00LTRhMSAxIDAgMCAxIDAtMS40MWw0LTRhMSAxIDAgMCAxIDEuNDIgMS40MUwyLjQxIDhsMy4yOSAzLjI5QTEgMSAwIDAgMSA1IDEzeiIvPjxwYXRoIGQ9Ik0xMSA5SDFhMSAxIDAgMCAxIDAtMmgxMGExIDEgMCAwIDEgMCAyek0xNSAxNmExIDEgMCAwIDEtMS0xVjFhMSAxIDAgMCAxIDIgMHYxNGExIDEgMCAwIDEtMSAxeiIvPjwvc3ZnPg==)}.scylla-icon--forum{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSJjdXJyZW50Q29sb3IiIHN0cm9rZS13aWR0aD0iMS41IiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiIGNsYXNzPSJmZWF0aGVyIGZlYXRoZXItdXNlcnMiPjxwYXRoIGQ9Ik0xNyAyMXYtMmE0IDQgMCAwIDAtNC00SDVhNCA0IDAgMCAwLTQgNHYyIi8+PGNpcmNsZSBjeD0iOSIgY3k9IjciIHI9IjQiLz48cGF0aCBkPSJNMjMgMjF2LTJhNCA0IDAgMCAwLTMtMy44N00xNiAzLjEzYTQgNCAwIDAgMSAwIDcuNzUiLz48L3N2Zz4=)}.scylla-icon--home{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyMSAxOSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOm5vbmU7c3Ryb2tlOiM0ZDRkNGQ7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJMYXllcl81IiBkYXRhLW5hbWU9IkxheWVyIDUiPjxwYXRoIGNsYXNzPSJjbHMtMSIgZD0iTTMuNSA2LjE0djExYTEuMzggMS4zOCAwIDAgMCAxLjM3IDEuMzZoMTEuMjZhMS4zOCAxLjM4IDAgMCAwIDEuMzctMS4zN3YtMTEiLz48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Im0xOS41IDcuNS04LTYuMjVhMS41OSAxLjU5IDAgMCAwLTEuOTQgMEwxLjUgNy41TTEyLjczIDE4LjAydi03LjIxSDguMjd2Ny4yMSIvPjwvZz48L3N2Zz4=)}.scylla-icon--getting-started{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyMSAxOSI+PGcgZGF0YS1uYW1lPSJDYWxxdWUgNCI+PHBhdGggc3R5bGU9ImZpbGw6IzRkNGQ0ZCIgZD0ibTcgNC41IDguNTEgNS4wNUw3IDE0LjV2LTEweiIvPjxyZWN0IHg9IjEuNSIgeT0iLjUiIHdpZHRoPSIxOCIgaGVpZ2h0PSIxOCIgcng9IjIuNDMiIHN0eWxlPSJmaWxsOm5vbmU7c3Ryb2tlOiM0ZDRkNGQ7c3Ryb2tlLW1pdGVybGltaXQ6MTAiLz48L2c+PC9zdmc+)}.scylla-icon--glossary{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyMSAxOSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOm5vbmU7c3Ryb2tlOiM0ZDRkNGQ7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJDYWxxdWVfNCIgZGF0YS1uYW1lPSJDYWxxdWUgNCI+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNMi41IDIuNWgxM3YxNmgtMTN6Ii8+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNMTUuNTggMTcuMjFoMS45MlYuNWgtMTNhMi4zNCAyLjM0IDAgMCAwLTIgMiIvPjxwYXRoIGQ9Ik00LjggMTMuOTNhMSAxIDAgMCAwIC43NS0uNDMgNiA2IDAgMCAwIC41Mi0xLjA4bDIuODctNy4wN2guMzZsMi44OCA2Ljc5YTguOTIgOC45MiAwIDAgMCAuNzIgMS40Ny43Ni43NiAwIDAgMCAuNjguMzJ2LjMySDkuNHYtLjMyYTMuMjQgMy4yNCAwIDAgMCAuODMtLjExYy4xMy0uMDYuMi0uMTkuMi0uNDJhMS41OSAxLjU5IDAgMCAwLS4xLS40NmMwLS4xMi0uMS0uMjctLjE3LS40NGwtLjMzLS43OGgtMi45Yy0uMTkuNTEtLjMxLjg1LS4zNiAxYTIuMzggMi4zOCAwIDAgMC0uMTcuNzNjMCAuMTguMTIuMzIuMzcuNGEyLjU2IDIuNTYgMCAwIDAgLjY2LjA4di4zMkg0LjhabTQuODQtMi43Mi0xLjI0LTNoLS4xMWwtMS4xNiAzWiIgc3R5bGU9ImZpbGw6IzRkNGQ0ZCIvPjwvZz48L3N2Zz4=)}.scylla-icon--infoworld{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLW1pdGVybGltaXQ6MTB9PC9zdHlsZT48L2RlZnM+PGcgaWQ9IkNhbHF1ZV80IiBkYXRhLW5hbWU9IkNhbHF1ZSA0Ij48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Ik0xMiAyLjVINi41VjZjMCAzIC41NSA3LjE3IDUgOS41djQiLz48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Ik02LjQgNC40NGgtNFMyLjU2IDExIDguNSAxM00xOC41IDQuNWw0LS4wNnMtLjA2IDYuNTYtNiA4LjU2Ii8+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNMTIgMi41aDYuNVY2YzAgMi45NC0uNCA3LjA4LTUgOS41djRNOS41IDE5LjVoNnYyaC02eiIvPjxwYXRoIHN0eWxlPSJmaWxsOmdyYXk7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLW1pdGVybGltaXQ6MTAiIGQ9Ik03LjUgMjEuNWgxMHYxaC0xMHoiLz48L2c+PC9zdmc+)}.scylla-icon--integrations{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOm5vbmU7c3Ryb2tlOiM0ZDRkNGQ7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJDYWxxdWVfNCIgZGF0YS1uYW1lPSJDYWxxdWUgNCI+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJtMTQuNTYgMTIuNy0xLjI1LTEuNTctMS4zMS43NmE2IDYgMCAwIDAtMS42NS0xbC4wOC0xLjQ5LTItLjQtLjUzIDEuNDRhNS43MyA1LjczIDAgMCAwLTEuODcuMzFsLS44OC0xLjE5LTEuNzcgMUwzLjkyIDEyYTYuMyA2LjMgMCAwIDAtMS4yMiAxLjQxbC0xLjUtLjM1LS43NCAxLjg3IDEuMzguOGE2LjIzIDYuMjMgMCAwIDAgMCAxLjgzbC0xLjQxLjcyLjY0IDEuOTEgMS41OS0uMjhhNy42MyA3LjYzIDAgMCAwIC40OC42OCA1Ljg2IDUuODYgMCAwIDAgLjY3LjczbC0uNjIgMS40NiAxLjcyIDEgMS0xLjI0YTYuNDYgNi40NiAwIDAgMCAxLjc5LjM1bC40NiAxLjUyIDItLjN2LTEuNmE2LjQzIDYuNDMgMCAwIDAgMS42Mi0uODlsMS4zLjg1TDE0LjQzIDIxbC0xLTEuMmE2LjI0IDYuMjQgMCAwIDAgLjY4LTEuNzVsMS41MS0uMTkuMDUtMi0xLjUxLS4yNmE2LjA3IDYuMDcgMCAwIDAtLjYyLTEuODFabS01LjM1IDUuNTFhMS45MyAxLjkzIDAgMSAxIC4zMS0yLjcxIDEuOTIgMS45MiAwIDAgMS0uMzEgMi43MVoiLz48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Im0yNC4zMSA4LjA1LS4xMy0xLjY1LTEuMjUtLjA5YTUuMjYgNS4yNiAwIDAgMC0uNjctMS40NGwuNzUtMS0xLjE2LTEuMTctMSAuNzRhNS4xOCA1LjE4IDAgMCAwLTEuNDMtLjY2bC0uMDYtMS4yNC0xLjY1LS4xNy0uMzIgMS4yNWE1Ljc3IDUuNzcgMCAwIDAtMS41Mi4zOEwxNSAyLjFsLTEuMzcuOS41OCAxLjE4YTQuODggNC44OCAwIDAgMC0uODYgMS4yNWwtMS4zLS4xNi0uNDUgMS42IDEuMjIuNTVhNS4xNyA1LjE3IDAgMCAwIDAgLjY4QTQuMjggNC4yOCAwIDAgMCAxMyA5bC0xLjExLjcyLjY5IDEuNTEgMS4yOC0uMzdhNC45NCA0Ljk0IDAgMCAwIDEuMDcgMS4wN2wtLjM5IDEuMjYgMS41LjcxLjc0LTEuMDlhNS4wNyA1LjA3IDAgMCAwIDEuNTIuMTRsLjUgMS4xOSAxLjYxLS40MS0uMTMtMS4yOWE1LjE0IDUuMTQgMCAwIDAgMS4yNy0uODhsMS4xMi41NyAxLTEuMzUtLjkxLS44OGE0LjkgNC45IDAgMCAwIC40Mi0xLjUyWm0tNi4yIDEuNDNhMS43NCAxLjc0IDAgMSAxIDEuNi0xLjg2IDEuNzQgMS43NCAwIDAgMS0xLjYgMS44NloiLz48L2c+PC9zdmc+)}.scylla-icon--knowledge-base{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyMSAxOSI+PGRlZnM+PHN0eWxlPi5jbHMtMSwuY2xzLTJ7ZmlsbDpub25lO3N0cm9rZTojNGQ0ZDRkfS5jbHMtMXtzdHJva2UtbGluZWNhcDpyb3VuZDtzdHJva2UtbGluZWpvaW46cm91bmR9LmNscy0ye3N0cm9rZS1taXRlcmxpbWl0OjEwfTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJMYXllcl81IiBkYXRhLW5hbWU9IkxheWVyIDUiPjxwYXRoIGNsYXNzPSJjbHMtMSIgZD0iTTE2LjIxIDYuMzhhNS4zNiA1LjM2IDAgMCAxLTEuNTEgMy43MyA1IDUgMCAwIDAtMS40NSAzLjMxSDguNDdhNS40MSA1LjQxIDAgMCAwLTEuMjgtMy4xMSA1LjM3IDUuMzcgMCAxIDEgOS0zLjkzWk0xMy4yMyAxNS42N0g4LjQ1Ii8+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNMTMuMjQgMTMuNGgtNC44djQuMTZhLjcuNyAwIDAgMCAuNzEuN2gzLjM4YS43LjcgMCAwIDAgLjcxLS43WiIvPjxwYXRoIGNsYXNzPSJjbHMtMiIgZD0iTTEwLjg0IDguMjFhMS42NSAxLjY1IDAgMSAxIDEuNjQtMS42NSAxLjY1IDEuNjUgMCAwIDEtMS42NCAxLjY1Wk0xMC44NCA4LjY3djQuNjQiLz48L2c+PC9zdmc+)}.scylla-icon--less{background-image:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTciIGhlaWdodD0iMTciIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHJlY3Qgd2lkdGg9IjE3IiBoZWlnaHQ9IjE3IiByeD0iMSIgZmlsbD0iI0IzQkFDNSIvPjxwYXRoIGQ9Ik0xMyA4LjVhMSAxIDAgMCAxLTEgMUg1YTEgMSAwIDAgMSAwLTJoN2ExIDEgMCAwIDEgMSAxWiIgZmlsbD0iI2ZmZiIvPjxwYXRoIGQ9Ik0xMyA4LjVhMSAxIDAgMCAxLTEgMUg1YTEgMSAwIDAgMSAwLTJoN2ExIDEgMCAwIDEgMSAxWiIgZmlsbD0iI2ZmZiIvPjxwYXRoIGQ9Ik0xMyA4LjVhMSAxIDAgMCAxLTEgMUg1YTEgMSAwIDAgMSAwLTJoN2ExIDEgMCAwIDEgMSAxWiIgZmlsbD0iI2ZmZiIvPjxwYXRoIGQ9Ik0xMyA4LjVhMSAxIDAgMCAxLTEgMUg1YTEgMSAwIDAgMSAwLTJoN2ExIDEgMCAwIDEgMSAxWiIgZmlsbD0iI2ZmZiIvPjxwYXRoIGQ9Ik0xMyA4LjVhMSAxIDAgMCAxLTEgMUg1YTEgMSAwIDAgMSAwLTJoN2ExIDEgMCAwIDEgMSAxWiIgZmlsbD0iI2ZmZiIvPjwvc3ZnPg==);filter:none}.scylla-icon--live-test{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtNntmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLW1pdGVybGltaXQ6MTA7c3Ryb2tlLWxpbmVjYXA6cm91bmR9PC9zdHlsZT48L2RlZnM+PGcgaWQ9IkNhbHF1ZV80IiBkYXRhLW5hbWU9IkNhbHF1ZSA0Ij48Y2lyY2xlIGN4PSIxMi41IiBjeT0iMTUiIHI9IjkuNSIgc3R5bGU9InN0cm9rZS13aWR0aDoxLjVweDtzdHJva2UtbWl0ZXJsaW1pdDoxMDtmaWxsOm5vbmU7c3Ryb2tlOmdyYXkiLz48cGF0aCBzdHlsZT0ic3Ryb2tlLXdpZHRoOjEuMXB4O3N0cm9rZS1saW5lam9pbjpyb3VuZDtzdHJva2UtbGluZWNhcDpyb3VuZDtmaWxsOm5vbmU7c3Ryb2tlOmdyYXkiIGQ9Ik0xMCAuNWg1djJoLTV6Ii8+PHBhdGggc3R5bGU9InN0cm9rZS13aWR0aDoxLjExcHg7c3Ryb2tlLWxpbmVqb2luOnJvdW5kO3N0cm9rZS1saW5lY2FwOnJvdW5kO2ZpbGw6bm9uZTtzdHJva2U6Z3JheSIgZD0iTTUuOCA4LjIgNC4xMyA2LjUzbDEuOC0xLjgxTDcuNiA2LjQiLz48cGF0aCBzdHlsZT0ic3Ryb2tlLXdpZHRoOjEuMTNweDtzdHJva2UtbWl0ZXJsaW1pdDoxMDtmaWxsOm5vbmU7c3Ryb2tlOmdyYXkiIGQ9Ik0xMiA2VjIuNSIvPjxwYXRoIHN0eWxlPSJzdHJva2Utd2lkdGg6MS4wOHB4O3N0cm9rZS1taXRlcmxpbWl0OjEwO2ZpbGw6bm9uZTtzdHJva2U6Z3JheSIgZD0iTTEzIDZWMi41Ii8+PHBhdGggY2xhc3M9ImNscy02IiBkPSJNMTIuNSA4LjA2VjEwTTEyLjUgMjAuMDR2MS44OE03LjEzIDEwLjA4bDEuNzkgMS44OE0xNi4wNCAxNy4wOGwyIDEuODhNNyAxOC45MmwxLjg4LTEuODhNMTYuMTMgMTEuOTZsMS43OS0xLjgzIi8+PGVsbGlwc2UgY3g9IjEyLjUiIGN5PSIxNC4zNiIgcng9IjEuNSIgcnk9IjEuMzYiIHN0eWxlPSJmaWxsOmdyYXkiLz48cGF0aCBjbGFzcz0iY2xzLTYiIGQ9Im0xMi42MyAxNC41NCAyLjUgNi4zOCIvPjwvZz48L3N2Zz4=)}.scylla-icon--mail-list{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSJjdXJyZW50Q29sb3IiIHN0cm9rZS13aWR0aD0iMS41IiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiIGNsYXNzPSJmZWF0aGVyIGZlYXRoZXItbWFpbCI+PHBhdGggZD0iTTQgNGgxNmMxLjEgMCAyIC45IDIgMnYxMmMwIDEuMS0uOSAyLTIgMkg0Yy0xLjEgMC0yLS45LTItMlY2YzAtMS4xLjktMiAyLTJ6Ii8+PHBhdGggZD0ibTIyIDYtMTAgN0wyIDYiLz48L3N2Zz4=)}.scylla-icon--manager{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtM3tmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kO3N0cm9rZS13aWR0aDouOTdweH0uY2xzLTR7ZmlsbDpncmF5fTwvc3R5bGU+PC9kZWZzPjxwYXRoIHN0eWxlPSJmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kIiBkPSJNMTggMmg1djIySDNWMmg0LjkyIiBpZD0iQ2FscXVlXzIiIGRhdGEtbmFtZT0iQ2FscXVlIDIiLz48ZyBpZD0iQ2FscXVlXzQiIGRhdGEtbmFtZT0iQ2FscXVlIDQiPjxwYXRoIHN0eWxlPSJzdHJva2Utd2lkdGg6MS4wN3B4O2ZpbGw6bm9uZTtzdHJva2U6Z3JheTtzdHJva2UtbGluZWNhcDpyb3VuZDtzdHJva2UtbGluZWpvaW46cm91bmQiIGQ9Ik04IDBoMTB2NEg4eiIvPjxwYXRoIGNsYXNzPSJjbHMtMyIgZD0iTTcgOWgzdjNIN3pNNyAxNmgzdjNIN3oiLz48cGF0aCBjbGFzcz0iY2xzLTQiIGQ9Ik0xMi41IDkuNWg3djJoLTd6TTEyLjUgMTYuNWg3djJoLTd6Ii8+PC9nPjwvc3ZnPg==)}.scylla-icon--memory-management{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMSwuY2xzLTJ7ZmlsbDpub25lO3N0cm9rZTpncmF5O3N0cm9rZS1saW5lY2FwOnJvdW5kO3N0cm9rZS1saW5lam9pbjpyb3VuZH0uY2xzLTJ7c3Ryb2tlLXdpZHRoOjEuMTNweH08L3N0eWxlPjwvZGVmcz48ZyBpZD0iQ2FscXVlXzQiIGRhdGEtbmFtZT0iQ2FscXVlIDQiPjxyZWN0IGNsYXNzPSJjbHMtMSIgeD0iNS41IiB5PSI1LjUiIHdpZHRoPSIxNSIgaGVpZ2h0PSIxNSIgcng9IjIuNzQiIHJ5PSIyLjc0Ii8+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNOS41IDkuNWg3djdoLTd6Ii8+PHBhdGggY2xhc3M9ImNscy0yIiBkPSJNOC41IDUuNXYtNE0xMS41IDUuNXYtNE0xNC41IDUuNXYtNE0xNy41IDUuNXYtNE04LjUgMjQuNXYtNE0xMS41IDI0LjV2LTRNMTQuNSAyNC41di00TTE3LjUgMjQuNXYtNE0yMC41IDguNWg0TTIwLjUgMTEuNWg0TTIwLjUgMTQuNWg0TTIwLjUgMTcuNWg0TTEuNSA4LjVoNE0xLjUgMTEuNWg0TTEuNSAxNC41aDRNMS41IDE3LjVoNCIvPjwvZz48L3N2Zz4=)}.scylla-icon--monitoring{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGcgZGF0YS1uYW1lPSJDYWxxdWUgNCI+PHBhdGggZD0iTTUuNTUgMTAuODlhMy44MyAzLjgzIDAgMCAxLS4xNS0zLjc2IiBzdHlsZT0ic3Ryb2tlLWxpbmVqb2luOnJvdW5kO3N0cm9rZS1saW5lY2FwOnJvdW5kO3N0cm9rZTpncmF5O2ZpbGw6bm9uZSIvPjxyZWN0IHg9IjE3LjYzIiB5PSIxNC4wMSIgd2lkdGg9IjMuMDUiIGhlaWdodD0iMTAuOCIgcng9Ii41NyIgcnk9Ii41NyIgdHJhbnNmb3JtPSJyb3RhdGUoLTQ1IDE5LjE1OCAxOS40MDUpIiBzdHlsZT0ic3Ryb2tlLW1pdGVybGltaXQ6MTA7ZmlsbDpncmF5O3N0cm9rZS13aWR0aDouOTVweDtzdHJva2U6Z3JheSIvPjxjaXJjbGUgY3g9IjguNSIgY3k9IjkiIHI9IjciIHN0eWxlPSJzdHJva2Utd2lkdGg6MnB4O3N0cm9rZS1taXRlcmxpbWl0OjEwO3N0cm9rZTpncmF5O2ZpbGw6bm9uZSIvPjxwYXRoIHN0eWxlPSJzdHJva2UtbWl0ZXJsaW1pdDoxMDtzdHJva2UtbGluZWNhcDpyb3VuZDtzdHJva2U6Z3JheTtmaWxsOm5vbmUiIGQ9Im0xNi4wNSAxNi4zOS0yLjI4LTIuMjgiLz48L2c+PC9zdmc+)}.scylla-icon--networking{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMntmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLW1pdGVybGltaXQ6MTB9PC9zdHlsZT48L2RlZnM+PGcgaWQ9IkNhbHF1ZV80IiBkYXRhLW5hbWU9IkNhbHF1ZSA0Ij48Y2lyY2xlIGN4PSIxMi41IiBjeT0iMTIuNSIgcj0iNCIgc3R5bGU9InN0cm9rZS13aWR0aDouOTRweDtmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLW1pdGVybGltaXQ6MTAiLz48Y2lyY2xlIGNsYXNzPSJjbHMtMiIgY3g9IjUiIGN5PSIzIiByPSIyLjUiLz48Y2lyY2xlIGNsYXNzPSJjbHMtMiIgY3g9IjE5IiBjeT0iMjAiIHI9IjIuNSIvPjxjaXJjbGUgY2xhc3M9ImNscy0yIiBjeD0iMjIiIGN5PSI2LjYiIHI9IjIuNSIvPjxjaXJjbGUgY2xhc3M9ImNscy0yIiBjeD0iNC41IiBjeT0iMjIiIHI9IjIuNSIvPjxwYXRoIGNsYXNzPSJjbHMtMiIgZD0ibTYuODMgNS41IDMuMjUgNC4zM00yMC4yMyA3Ljg1IDE1LjMzIDExTTkuODMgMTUuMDhsLTQuMDkgNS44NE0xNC41OCAxNS4zM2wzIDMuMDkiLz48Y2lyY2xlIGN4PSIxMi41IiBjeT0iMTIuNSIgcj0iMS41IiBzdHlsZT0iZmlsbDpncmF5Ii8+PC9nPjwvc3ZnPg==)}.scylla-icon--news{background-image:url(data:image/svg+xml;base64,PHN2ZyBpZD0iQ2FscXVlXzEiIGRhdGEtbmFtZT0iQ2FscXVlIDEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmlld0JveD0iMCAwIDI1IDI1Ij48ZGVmcz48c3R5bGU+LmNscy0xe2ZpbGw6bm9uZTtzdHJva2U6Z3JheTtzdHJva2UtbGluZWNhcDpyb3VuZDtzdHJva2UtbGluZWpvaW46cm91bmR9PC9zdHlsZT48L2RlZnM+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNMyAxNS4xNyAxNi4zMSAzLjgyYTEuNDggMS40OCAwIDAgMSAyLjIyLjQ2bDUuMTUgOS42NWExLjQ2IDEuNDYgMCAwIDEtLjkzIDIuMTJMNS42OSAxOS45Wk04LjcxIDE5LjMzbC43NiAyLjIyYTEuNTEgMS41MSAwIDAgMCAxLjg1IDFsMy41OC0xLjA2YTEuNSAxLjUgMCAwIDAgMS0xLjg2TDE1LjQ1IDE4TTUuNTQgMjBsLTEuODMgMWEuOTIuOTIgMCAwIDEtMS4yNS0uMzdMLjYxIDE3LjQ5QS45Mi45MiAwIDAgMSAxIDE2LjI0bDEuODMtMU04LjUgMTRsNy4zOC01LjUiLz48L3N2Zz4=)}.scylla-icon--newsletter{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMSwuY2xzLTJ7ZmlsbDpub25lO3N0cm9rZTpncmF5O3N0cm9rZS1taXRlcmxpbWl0OjEwfS5jbHMtMntzdHJva2UtbGluZWNhcDpyb3VuZH08L3N0eWxlPjwvZGVmcz48ZyBpZD0iQ2FscXVlXzQiIGRhdGEtbmFtZT0iQ2FscXVlIDQiPjxwYXRoIGNsYXNzPSJjbHMtMSIgZD0iTTE5LjUgOS41aDN2MTJoLTIwdi0xMmgzIi8+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJtMi42NSA5Ljg0IDkuODUgNi44OCA4LjYzLTYuODgiLz48cGF0aCBjbGFzcz0iY2xzLTIiIGQ9Im01LjUgNy41LTMgMk0xNC4zNSAzLjg2bC0xLjQ2LTEuMDktMS40NyAxLjA5TTIxLjUgOS41bC0yLTJNMTkuNSAxMS41di03aC0xNHY3LjQ3Ii8+PC9nPjwvc3ZnPg==)}.scylla-icon--nsql-guides{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGcgZGF0YS1uYW1lPSJDYWxxdWUgNCI+PHJlY3QgeD0iNC4zNyIgeT0iMTMuNzEiIHdpZHRoPSIxLjE1IiBoZWlnaHQ9IjkuNzIiIHJ4PSIuNTQiIHJ5PSIuNTQiIHRyYW5zZm9ybT0icm90YXRlKDQ1IDQuOTQ4IDE4LjU3KSIgc3R5bGU9InN0cm9rZTpncmF5O3N0cm9rZS1taXRlcmxpbWl0OjEwO2ZpbGw6Z3JheTtzdHJva2Utd2lkdGg6MS4wOXB4Ii8+PGNpcmNsZSBjeD0iMTIuMjUiIGN5PSIxMi4yNSIgcj0iNC43NSIgc3R5bGU9InN0cm9rZS13aWR0aDoxLjVweDtmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLW1pdGVybGltaXQ6MTAiLz48cGF0aCBzdHlsZT0ic3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLXdpZHRoOjEuMDZweDtmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLW1pdGVybGltaXQ6MTAiIGQ9Ik04LjUgMjAuNXYzaDE1di0yMWgtMTV2MiIvPjwvZz48L3N2Zz4=)}.scylla-icon--open-source{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfS5jbHMtMntmaWxsOmdyYXl9PC9zdHlsZT48L2RlZnM+PGcgaWQ9IkNhbHF1ZV80IiBkYXRhLW5hbWU9IkNhbHF1ZSA0Ij48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Ik0uMzEgMjEuNTEgNSAxOS42OWEyLjM3IDIuMzcgMCAwIDEgMS44OC4xOWw1LjI0IDEuNjhhMi4yMyAyLjIzIDAgMCAwIDItLjEybDkuNS00Ljc1Yy44LS40NCAxLjY0LTEuMzEgMS4xMy0xLjkxYTIuMzQgMi4zNCAwIDAgMC0yLjY0LS40MkwxOCAxNi4wOSIvPjxwYXRoIGNsYXNzPSJjbHMtMSIgZD0ibS4yNSAxNS42OSA0Ljg4LTEuMjFjMS4yNS0uMyAyLjE3LS42MyAzLjQ0LS4xM2ExNS4yMSAxNS4yMSAwIDAgMCA0IDEuMWg0LjUyYy44NSAwIC45NS41NC45NSAxLjEzYTEgMSAwIDAgMS0xLjA4IDEgNjUuODYgNjUuODYgMCAwIDEtNy0uMzEiLz48cGF0aCBjbGFzcz0iY2xzLTIiIGQ9Ik04LjU2IDkuNjh2LS44MWMwLS45MS0uMzgtMS4yMS0xLjI5LTEuMjFIN1Y2LjNoLjMxYy45MSAwIDEuMjktLjMgMS4yOS0xLjIxdi0uODFjMC0xLjIuNjYtMS45MiAyLjgyLTIuM3YxLjE2Yy0xLjI0LjM1LTEuNDMuNjgtMS40MyAxLjR2Ljg3QTEuNTIgMS41MiAwIDAgMSA4Ljc1IDcgMS41MiAxLjUyIDAgMCAxIDEwIDguNTZ2Ljg3YzAgLjcxLjE5IDEgMS40MyAxLjRWMTJjLTIuMjEtLjM1LTIuODctMS4xMi0yLjg3LTIuMzJaTTE3LjQzIDQuM3YuODFjMCAuOTEuMzcgMS4yMSAxLjI5IDEuMjFIMTl2MS4zNmgtLjMxYy0uOTIgMC0xLjI5LjMtMS4yOSAxLjIxdi44MWMwIDEuMi0uNjUgMi0yLjgxIDIuMzV2LTEuMmMxLjI1LS4zNiAxLjQ0LS42OSAxLjQ0LTEuNHYtLjg3QTEuNTMgMS41MyAwIDAgMSAxNy4yNSA3IDEuNTMgMS41MyAwIDAgMSAxNiA1LjQzdi0uODdjMC0uNzItLjE5LTEtMS40NC0xLjRWMmMyLjIyLjM4IDIuODcgMS4xIDIuODcgMi4zWiIvPjwvZz48L3N2Zz4=)}.scylla-icon--operator{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjQuODEgMS4wMSAyOC4zMiAyNy42NCI+PHBhdGggZD0iTTMyLjUyIDE4cy0uMDkgMC0uMDktLjA1LS4wOCAwLS4xNyAwYTIuMTkgMi4xOSAwIDAgMC0uNTEgMCAuNDcuNDcgMCAwIDEtLjI2LS4wNSA5LjI5IDkuMjkgMCAwIDEtMS40OS0uMzIuNTQuNTQgMCAwIDEtLjMtLjMxbC0uMzQtLjA4YTExLjI1IDExLjI1IDAgMCAwLS4xOC0zLjc5IDExLjU1IDExLjU1IDAgMCAwLTEuNS0zLjUybC4yNi0uMjZhLjU5LjU5IDAgMCAxIC4xMy0uMzkgNy43MyA3LjczIDAgMCAxIDEuMi0uODZsLjI2LS4xMy40Ny0uM3MuMDkgMCAuMTMtLjA4IDAtLjA1IDAtLjA5YS44NC44NCAwIDAgMCAuMTctMS4yLjc4Ljc4IDAgMCAwLS42LS4zIDEgMSAwIDAgMC0uNi4yMWMtLjA1LjA1LS4wOS4wOS0uMTMuMDlhMy4wOCAzLjA4IDAgMCAwLS4zNS4zOWMwIC4wOC0uMTMuMTMtLjE3LjE3YTUuNjQgNS42NCAwIDAgMS0xLjA3Ljk0LjU4LjU4IDAgMCAxLS4yNi4wOS4yNS4yNSAwIDAgMS0uMTcgMGgtLjA1bC0uMzQuMjEtMS4wOC0xYTExIDExIDAgMCAwLTUuNjUtMi4yN3YtLjM0YS42LjYgMCAwIDEtLjIyLS4zNEE4LjE4IDguMTggMCAwIDEgMTkuNjYgM3YtLjI1YzAtLjA4LjA1LS4zNS4wOS0uNTJ2LS4zMWEuODIuODIgMCAwIDAtMS40Ni0uNi44Ni44NiAwIDAgMC0uMjYuNnYuMjJhMS44MiAxLjgyIDAgMCAwIC4wOS41MS41OS41OSAwIDAgMSAwIC4yNlYzYTguODIgOC44MiAwIDAgMSAuMDggMS40Ny41OS41OSAwIDAgMS0uMjEuMzRWNS4yNGMtLjQ4IDAtMSAuMTMtMS40Ny4yMmExMC4xNiAxMC4xNiAwIDAgMC01LjI4IDNMMTEgOC4yNGgtLjE3YS43My43MyAwIDAgMS0uMjYtLjA5IDcuOCA3LjggMCAwIDEtMS4wNy0xYzAtLjA4LS4xMy0uMTMtLjE3LS4xN3MtLjI1LS4yLS4zMy0uMzMtLjA4IDAtLjEzLS4wOHYtLjA1YTEgMSAwIDAgMC0uNi0uMjEuNjQuNjQgMCAwIDAtLjYuMy45MS45MSAwIDAgMCAuMTcgMS4yczAgLjA1IDAgLjA1LjA5LjA4LjEzLjA4YTUgNSAwIDAgMCAuNDcuMjZsLjI2LjEzYTYuNjEgNi42MSAwIDAgMSAxLjIxLjg2LjQ3LjQ3IDAgMCAxIC4xMy4zOXYtLjA1bC4yNS4yNmEyLjUzIDIuNTMgMCAwIDEtLjEzLjIyIDEwLjIgMTAuMiAwIDAgMC0xLjUgN2wtLjM1LjA5YzAgLjEzLS4xNy4yMS0uMy4zYTguNTYgOC41NiAwIDAgMS0xLjQ2LjI2LjU5LjU5IDAgMCAwLS4yNiAwaC0uNTJjLS4xOCAwLS4wOC4wNS0uMTcuMDVoLS4wOGEuODQuODQgMCAwIDAtLjY5IDEgLjc5Ljc5IDAgMCAwIC44Ni42LjM5LjM5IDAgMCAwIC4yMSAwSDYuMTJhMy42MSAzLjYxIDAgMCAwIC40Ny0uMTcuNjUuNjUgMCAwIDEgLjI2LS4wOCA3LjY1IDcuNjUgMCAwIDEgMS40Mi0uMzkuNDkuNDkgMCAwIDEgLjM1LjEzaC4zOWExMC4zMiAxMC4zMiAwIDAgMCAzLjUzIDUgNi4zMSA2LjMxIDAgMCAwIDEuMTYuNzdsLS4yMi4zYS41MS41MSAwIDAgMSAwIC40MyA2LjU0IDYuNTQgMCAwIDEtLjY5IDEuMjR2LjA1YS43OC43OCAwIDAgMS0uMTcuMjFjLS4wOS4wOS0uMTcuMjYtLjMuNDNzMCAuMDktLjA5LjEzIDAgLjA1IDAgLjA1YS44OC44OCAwIDAgMCAuMzQgMS4xNi45LjkgMCAwIDAgLjMuMDggMSAxIDAgMCAwIC44Mi0uNTFzMC0uMDguMDktLjEzLjEzLS4zLjE3LS40N2wuMDktLjI2YTcuMDcgNy4wNyAwIDAgMSAuNTYtMS4zMy42Mi42MiAwIDAgMSAuMzQtLjI2bC4xNy0uMzVhMTAuMDUgMTAuMDUgMCAwIDAgMy43NS42OSA4LjQ1IDguNDUgMCAwIDAgMi4zMi0uMyAxMS40NiAxMS40NiAwIDAgMCAxLjM3LS4zOWwuMTguMzFhLjYyLjYyIDAgMCAxIC4zNC4yNiA3LjA3IDcuMDcgMCAwIDEgLjU2IDEuMzNsLjA5LjI2YTEuMzEgMS4zMSAwIDAgMCAuMTcuNDdjMCAuMDUgMCAuMDkuMDkuMTNhMSAxIDAgMCAwIC44Mi41MSAxLjA1IDEuMDUgMCAwIDAgLjM0LS4wOC43Ni43NiAwIDAgMCAuMzktLjQ4IDEuMDggMS4wOCAwIDAgMC0uMDUtLjY0LjIuMiAwIDAgMC0uMDgtLjEzIDEuNTMgMS41MyAwIDAgMC0uMzEtLjQzLjY1LjY1IDAgMCAwLS4xNy0uMjJ2LS4wOWE1LjIyIDUuMjIgMCAwIDEtLjY5LTEuMjQuNTEuNTEgMCAwIDEgLjA1LS40M2wtLjEzLS4zNEExMC42OCAxMC42OCAwIDAgMCAyOSAxOC44MmwuMzQuMDV2LS4wNWEuNTQuNTQgMCAwIDEgLjM1LS4xMyA3LjgyIDcuODIgMCAwIDEgMS4zOC4zOS42Mi42MiAwIDAgMCAuMjYuMDkgMi40MiAyLjQyIDAgMCAwIC40Ny4yMXMuMDkgMCAuMTcgMGguMDlhLjM5LjM5IDAgMCAwIC4yMSAwIC45NC45NCAwIDAgMCAuODYtLjYgMSAxIDAgMCAwLS43Ny0uOVptLTEyLjQzLTEuMzMtMS4xNi41Ni0xLjE2LS41Ni0uMy0xLjI1LjgxLTFoMS4yOWwuODIgMVptNy0yLjc5YTggOCAwIDAgMSAuMTcgMi43MWwtNC4xNS0uNzVjLS4zOC0uMDgtLjY4LS45LS43MS0xLjIyYTQgNCAwIDAgMSAuMjEtLjc0bDMuNDUtMi41NGE4LjU4IDguNTggMCAwIDEgMS4wNCAyLjU0Wm0tMi4zMS00LjEzLTMuMjIgMi42OWExLjI4IDEuMjggMCAwIDEtMS4yNS0uMzdjLS4wOS0uMDktLjM3LS4yNS0uMzctLjM4VjcuNDNhOC4wNyA4LjA3IDAgMCAxIDQuODYgMi4zMlpNMTcgNy41NmwxLS4xOC0uMDYgNC4zMWMwIC4zOC0uNjQuNjgtMSAuNjhhMS4xMSAxLjExIDAgMCAxLS4zNS0uMDhMMTMgOS43NWE4LjQxIDguNDEgMCAwIDEgNC0yLjE5Wm0tNS4yNCAzLjc4IDMuMzcgMi40Ny4zMi41M2ExLjE0IDEuMTQgMCAwIDEtLjI1IDEgLjc4Ljc4IDAgMCAxLS4zOC4zMWwtNC4zMS45YTkgOSAwIDAgMSAxLjI0LTUuMjFaTTExIDE4LjYxbDQuMS0xLjIzYy4zNSAwIC44NC43MS44OSAxLjA2YS41MS41MSAwIDAgMS0uMDUuNDNsLTEuNjMgMy45NUE4LjQxIDguNDEgMCAwIDEgMTEgMTguNjFabTkuNzYgNS4zM2E4LjY3IDguNjcgMCAwIDEtMS44NS4yMSA5LjU5IDkuNTkgMCAwIDEtMi43MS0uNDNsMS42Ni00Yy4yMS0uMjYgMS0uMiAxLjMxIDBhMi40OCAyLjQ4IDAgMCAxIC4zNC4zbDIuMDcgMy43NGE1LjcyIDUuNzIgMCAwIDAtLjguMThaTTI2IDIwLjJhOC4zNiA4LjM2IDAgMCAxLTIuNTggMi41OGwtMS45Mi0zLjcyYTEuMTUgMS4xNSAwIDAgMSAuNDEtMWMuMjEtLjI1LjU5LS41OS43MS0uNTlsNC4yMiAxLjA2QTYuMjcgNi4yNyAwIDAgMSAyNiAyMC4yWiIgc3R5bGU9ImZpbGw6IzRkNGQ0ZCIgZGF0YS1uYW1lPSJDYWxxdWUgMiIvPjwvc3ZnPg==)}.scylla-icon--overview{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJDYWxxdWVfNCIgZGF0YS1uYW1lPSJDYWxxdWUgNCI+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNMjIuNjEgMy40NUMyMi42MSA1LjA2IDE4IDYuNSAxMi41IDYuNXMtMTAtMS40NC0xMC0zIDQuNS0zIDEwLTMgMTAuMTEgMS4zMyAxMC4xMSAyLjk1Wk0yMi42MSA5LjQ0YzAgMS42MS00LjY0IDMuMDYtMTAuMTEgMy4wNnMtMTAtMS40NS0xMC0zLjA2TTIyLjYxIDE1LjUxYzAgMS42Mi00LjY0IDMtMTAuMTEgM3MtMTAtMS4zNy0xMC0zTTIyLjYxIDIxLjU5YzAgMS42Mi00LjY0IDIuOTEtMTAuMTEgMi45MXMtMTAtMS4yOS0xMC0yLjkxTTIuNSAyMS40N1YzLjQ1TTIyLjUgMjEuNDdWMy40NSIvPjwvZz48L3N2Zz4=)}.scylla-icon--partners{background-image:url(data:image/svg+xml;base64,PHN2ZyBpZD0iQ2FscXVlXzEiIGRhdGEtbmFtZT0iQ2FscXVlIDEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmlld0JveD0iMCAwIDI1IDI1Ij48ZGVmcz48c3R5bGU+LmNscy0xe2ZpbGw6bm9uZTtzdHJva2U6Z3JheTtzdHJva2UtbGluZWNhcDpyb3VuZDtzdHJva2UtbGluZWpvaW46cm91bmR9PC9zdHlsZT48L2RlZnM+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNMTguNSA4LjI2aC00LjcybC0xLjIzIDEuMjdNMi4zOSAxNS4wOS4xNSAxMy43NGw0Ljg3LTguNDIgMi4yNCAxLjM0LTQuODcgOC40M3pNMjIuNTkgMTUuMDlsMi4yNC0xLjM1LTQuODYtOC40Mi0yLjI0IDEuMzQgNC44NiA4LjQzek0xMC43MSAxNS4yNmwtMi45MyAyLjIxTTEyLjE4IDE2LjRsLTIuOTMgMi4yMU0xMy42OCAxNy41M2wtMi45MyAyLjIyIi8+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNNi4zOCA4LjNoMy43OGEyLjI3IDIuMjcgMCAwIDEgMS4zNy40N2MxLjI2IDEgNC4wOSAzLjE4IDQuNDggMy41NnMtMS4xNCAxLjY4LTIuMjcgMS4xYTE4LjM0IDE4LjM0IDAgMCAwLTIuMTEtLjkyLjU3LjU3IDAgMCAwLS41Ni4wOWwtNC43OSAzLjg5TDEyLjMzIDIxbDkuNDYtNy4wOU0zLjI0IDE0LjIybDMuNCAxLjg1Ii8+PC9zdmc+)}.scylla-icon--plus{background-image:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTciIGhlaWdodD0iMTciIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHJlY3Qgd2lkdGg9IjE3IiBoZWlnaHQ9IjE3IiByeD0iMSIgZmlsbD0iI0IzQkFDNSIvPjxwYXRoIGZpbGwtcnVsZT0iZXZlbm9kZCIgY2xpcC1ydWxlPSJldmVub2RkIiBkPSJNOS41IDVhMSAxIDAgMSAwLTIgMHYyLjVINWExIDEgMCAxIDAgMCAyaDIuNVYxMmExIDEgMCAxIDAgMiAwVjkuNUgxMmExIDEgMCAxIDAgMC0ySDkuNVY1WiIgZmlsbD0iI2ZmZiIvPjxwYXRoIGZpbGwtcnVsZT0iZXZlbm9kZCIgY2xpcC1ydWxlPSJldmVub2RkIiBkPSJNOS41IDVhMSAxIDAgMSAwLTIgMHYyLjVINWExIDEgMCAxIDAgMCAyaDIuNVYxMmExIDEgMCAxIDAgMiAwVjkuNUgxMmExIDEgMCAxIDAgMC0ySDkuNVY1WiIgZmlsbD0iI2ZmZiIvPjxwYXRoIGZpbGwtcnVsZT0iZXZlbm9kZCIgY2xpcC1ydWxlPSJldmVub2RkIiBkPSJNOS41IDVhMSAxIDAgMSAwLTIgMHYyLjVINWExIDEgMCAxIDAgMCAyaDIuNVYxMmExIDEgMCAxIDAgMiAwVjkuNUgxMmExIDEgMCAxIDAgMC0ySDkuNVY1WiIgZmlsbD0iI2ZmZiIvPjxwYXRoIGZpbGwtcnVsZT0iZXZlbm9kZCIgY2xpcC1ydWxlPSJldmVub2RkIiBkPSJNOS41IDVhMSAxIDAgMSAwLTIgMHYyLjVINWExIDEgMCAxIDAgMCAyaDIuNVYxMmExIDEgMCAxIDAgMiAwVjkuNUgxMmExIDEgMCAxIDAgMC0ySDkuNVY1WiIgZmlsbD0iI2ZmZiIvPjxwYXRoIGZpbGwtcnVsZT0iZXZlbm9kZCIgY2xpcC1ydWxlPSJldmVub2RkIiBkPSJNOS41IDVhMSAxIDAgMSAwLTIgMHYyLjVINWExIDEgMCAxIDAgMCAyaDIuNVYxMmExIDEgMCAxIDAgMiAwVjkuNUgxMmExIDEgMCAxIDAgMC0ySDkuNVY1WiIgZmlsbD0iI2ZmZiIvPjwvc3ZnPg==);filter:none}.scylla-icon--pricing{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJDYWxxdWVfMiIgZGF0YS1uYW1lPSJDYWxxdWUgMiI+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJtMjEuNzMgNy0yLjQxLTUuMTJhMi41MiAyLjUyIDAgMCAwLTIuODItMWwtNi4wOCAyLjA0QTEuNjkgMS42OSAwIDAgMCA5LjUxIDRMMy45MyAxOS4yOWExLjA2IDEuMDYgMCAwIDAgLjY0IDEuMTdsMTAuMzQgMy43NmExIDEgMCAwIDAgMS4yMi0uNDNsNS41OC0xNS4zM0ExLjg3IDEuODcgMCAwIDAgMjEuNzMgN1oiLz48Y2lyY2xlIGNsYXNzPSJjbHMtMSIgY3g9IjE1LjczIiBjeT0iNS44OSIgcj0iMiIvPjx0ZXh0IHRyYW5zZm9ybT0icm90YXRlKDIwIC00OC4yNDQgMzAuNjcpIiBzdHlsZT0iZm9udC1zaXplOjEycHg7ZmlsbDpncmF5O2ZvbnQtZmFtaWx5OlJvYm90by1NZWRpdW0sUm9ib3RvIj4kPC90ZXh0PjwvZz48L3N2Zz4=)}.scylla-icon--release-note{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMntmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kO3N0cm9rZS13aWR0aDouOTFweH08L3N0eWxlPjwvZGVmcz48ZyBpZD0iQ2FscXVlXzIiIGRhdGEtbmFtZT0iQ2FscXVlIDIiPjxwYXRoIHN0eWxlPSJzdHJva2Utd2lkdGg6LjlweDtmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kIiBkPSJNMjEuNSAyNC41aC0xN1Y1LjdMOC45NS41NCAyMS41LjV2MjR6Ii8+PHBhdGggY2xhc3M9ImNscy0yIiBkPSJNNC42NSA1LjVIOS41VjFNNy41IDguNWgxMU03LjUgMTEuNWgxMU03LjUgMTQuNWgxMU03LjUgMTcuNWgxMU03LjUgMjAuNWgxMSIvPjwvZz48L3N2Zz4=)}.scylla-icon--resource-center{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfS5jbHMtMntmaWxsOmdyYXl9PC9zdHlsZT48L2RlZnM+PGcgaWQ9IkNhbHF1ZV80IiBkYXRhLW5hbWU9IkNhbHF1ZSA0Ij48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Ik01LjUgMi41aDYuOTFsLjA5IDIwaC03di0yMHoiLz48cGF0aCBjbGFzcz0iY2xzLTIiIGQ9Ik04IDRoMnYxMC45N0w4IDE1VjR6Ii8+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNNS4zNiAyLjI5IDIuNSAzLjV2MThsMi43OSAxLjE0Ii8+PHBhdGggc3R5bGU9InN0cm9rZS13aWR0aDouNjhweDtmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kIiBkPSJtMTIuNTcgMjEuODYgMS41Ny43NSIvPjxwYXRoIHN0eWxlPSJzdHJva2Utd2lkdGg6Ljg1cHg7ZmlsbDpub25lO3N0cm9rZTpncmF5O3N0cm9rZS1saW5lY2FwOnJvdW5kO3N0cm9rZS1saW5lam9pbjpyb3VuZCIgZD0ibTE0LjExIDIuNS0xLjU0LjU3Ii8+PGNpcmNsZSBjbGFzcz0iY2xzLTIiIGN4PSI5IiBjeT0iMTkiIHI9IjEiLz48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Ik0xNC41IDIuNWg2Ljk0bC4wNiAyMGgtN3YtMjB6Ii8+PHBhdGggY2xhc3M9ImNscy0yIiBkPSJNMTcgNGgydjEwLjk3TDE3IDE1VjR6Ii8+PGNpcmNsZSBjbGFzcz0iY2xzLTIiIGN4PSIxOCIgY3k9IjE5IiByPSIxIi8+PHBhdGggY2xhc3M9ImNscy0yIiBkPSJNMTIuNiAyLjczaDEuNjdWMjIuNkgxMi42ek0yLjU4IDIxLjVsMi43NSAxLjFWMi43M2wtMi42Ni45NC0uMDkgMTcuODN6Ii8+PC9nPjwvc3ZnPg==)}.scylla-icon--roadmap{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMSwuY2xzLTJ7ZmlsbDpub25lO3N0cm9rZTpncmF5fS5jbHMtMXtzdHJva2UtbGluZWNhcDpyb3VuZDtzdHJva2UtbGluZWpvaW46cm91bmQ7c3Ryb2tlLXdpZHRoOi45OHB4fS5jbHMtMntzdHJva2UtbWl0ZXJsaW1pdDoxMH0uY2xzLTN7ZmlsbDpncmF5fTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJDYWxxdWVfNCIgZGF0YS1uYW1lPSJDYWxxdWUgNCI+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJtLjUgNC41IDgtMyA4IDQgOC0zdjE3bC04IDMtOC00LTggM3YtMTd6TTguNSAxLjVWMThNMTYuNSA1LjVWMjIiLz48cGF0aCBjbGFzcz0iY2xzLTIiIGQ9Ik0yLjUgMTMgNyAxNi41TTcgMTJsLTQuNSA1LjVNMTguNSA4bDQuNSAzLjVNMjMgN2wtNC41IDUuNSIvPjxwYXRoIGNsYXNzPSJjbHMtMyIgZD0iTTEwIDEzaDF2MWgtMXpNMTIgMTJoMXYxaC0xek0xNCAxMWgxdjFoLTF6Ii8+PC9nPjwvc3ZnPg==)}.scylla-icon--search{background-image:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZD0iTTEwLjUgMThhNy41IDcuNSAwIDEgMCAwLTE1IDcuNSA3LjUgMCAwIDAgMCAxNVpNMjEgMjFsLTUuMi01LjIiIHN0cm9rZT0iIzAwMCIgc3Ryb2tlLXdpZHRoPSIyIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiLz48L3N2Zz4=)}.scylla-icon--slack{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0NDggNTEyIj48IS0tISBGb250IEF3ZXNvbWUgUHJvIDYuMC4wIGJ5IEBmb250YXdlc29tZSAtIGh0dHBzOi8vZm9udGF3ZXNvbWUuY29tIExpY2Vuc2UgLSBodHRwczovL2ZvbnRhd2Vzb21lLmNvbS9saWNlbnNlIChDb21tZXJjaWFsIExpY2Vuc2UpIENvcHlyaWdodCAyMDIyIEZvbnRpY29ucywgSW5jLi0tPjxwYXRoIGQ9Ik05NC4xMiAzMTUuMWMwIDI1LjktMjEuMTYgNDcuMDYtNDcuMDYgNDcuMDZTMCAzNDEgMCAzMTUuMWMwLTI1LjkgMjEuMTYtNDcuMDYgNDcuMDYtNDcuMDZoNDcuMDZ2NDcuMDZ6bTIzLjcyIDBjMC0yNS45IDIxLjE2LTQ3LjA2IDQ3LjA2LTQ3LjA2czQ3LjA2IDIxLjE2IDQ3LjA2IDQ3LjA2djExNy44NGMwIDI1LjktMjEuMTYgNDcuMDYtNDcuMDYgNDcuMDZzLTQ3LjA2LTIxLjE2LTQ3LjA2LTQ3LjA2VjMxNS4xem00Ny4wNi0xODguOThjLTI1LjkgMC00Ny4wNi0yMS4xNi00Ny4wNi00Ny4wNlMxMzkgMzIgMTY0LjkgMzJzNDcuMDYgMjEuMTYgNDcuMDYgNDcuMDZ2NDcuMDZIMTY0Ljl6bTAgMjMuNzJjMjUuOSAwIDQ3LjA2IDIxLjE2IDQ3LjA2IDQ3LjA2cy0yMS4xNiA0Ny4wNi00Ny4wNiA0Ny4wNkg0Ny4wNkMyMS4xNiAyNDMuOTYgMCAyMjIuOCAwIDE5Ni45czIxLjE2LTQ3LjA2IDQ3LjA2LTQ3LjA2SDE2NC45em0xODguOTggNDcuMDZjMC0yNS45IDIxLjE2LTQ3LjA2IDQ3LjA2LTQ3LjA2IDI1LjkgMCA0Ny4wNiAyMS4xNiA0Ny4wNiA0Ny4wNnMtMjEuMTYgNDcuMDYtNDcuMDYgNDcuMDZoLTQ3LjA2VjE5Ni45em0tMjMuNzIgMGMwIDI1LjktMjEuMTYgNDcuMDYtNDcuMDYgNDcuMDYtMjUuOSAwLTQ3LjA2LTIxLjE2LTQ3LjA2LTQ3LjA2Vjc5LjA2YzAtMjUuOSAyMS4xNi00Ny4wNiA0Ny4wNi00Ny4wNiAyNS45IDAgNDcuMDYgMjEuMTYgNDcuMDYgNDcuMDZWMTk2Ljl6TTI4My4xIDM4NS44OGMyNS45IDAgNDcuMDYgMjEuMTYgNDcuMDYgNDcuMDYgMCAyNS45LTIxLjE2IDQ3LjA2LTQ3LjA2IDQ3LjA2LTI1LjkgMC00Ny4wNi0yMS4xNi00Ny4wNi00Ny4wNnYtNDcuMDZoNDcuMDZ6bTAtMjMuNzJjLTI1LjkgMC00Ny4wNi0yMS4xNi00Ny4wNi00Ny4wNiAwLTI1LjkgMjEuMTYtNDcuMDYgNDcuMDYtNDcuMDZoMTE3Ljg0YzI1LjkgMCA0Ny4wNiAyMS4xNiA0Ny4wNiA0Ny4wNiAwIDI1LjktMjEuMTYgNDcuMDYtNDcuMDYgNDcuMDZIMjgzLjF6Ii8+PC9zdmc+)}.scylla-icon--stack-overflow{background-image:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjQiIGhlaWdodD0iMzEiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Im0yMS45NDkuMTEzIDIuMDQzIDExLjY3LTIuNTE0LjQzMkwxOS40MzUuNTQ1IDIxLjk1LjExNFptLTE3Ljk3MyAyNiAxMS45NDUtLjAwNS0uMDAyLTIuNTMtMTEuOTQ0LjAwNi4wMDEgMi41M1ptMTIuMjMyLTUuNzc3TDQuMzE1IDE5LjI1bC0uMjM1IDIuNTIgMTEuODk0IDEuMDg1LjIzNC0yLjUxOVptLTEwLjc1LTYuMzc1IDExLjUzNSAzLjA3NC0uNjYyIDIuNDQzLTExLjUzNS0zLjA3NS42NjItMi40NDJabTEzLjA0LjE4TDguMjEyIDguMTI2bC0xLjI5NyAyLjE3OCAxMC4yODkgNi4wMTcgMS4yOTYtMi4xNzhabS00LjIwNi0xMS41NiA2LjczIDkuNzg3LTIuMTA4IDEuNDI0LTYuNzMtOS43ODUgMi4xMDgtMS40MjVaIiBmaWxsPSIjMDAwIi8+PHBhdGggZD0iTTE3Ljk1IDE3Ljc4OVYyOC4xM0gyLjI4MlYxNy43ODlILjI0M3YxMi4zMjZIMTkuOThWMTcuNzg5aC0yLjAzWiIgZmlsbD0iIzAwMCIvPjwvc3ZnPg==)}.scylla-icon--summit{background-image:url(data:image/svg+xml;base64,PHN2ZyBpZD0iQ2FscXVlXzEiIGRhdGEtbmFtZT0iQ2FscXVlIDEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmlld0JveD0iMCAwIDI1IDI1Ij48ZGVmcz48c3R5bGU+LmNscy0xe2ZpbGw6bm9uZTtzdHJva2U6IzRkNGQ0ZDtzdHJva2UtbGluZWNhcDpyb3VuZDtzdHJva2UtbGluZWpvaW46cm91bmR9PC9zdHlsZT48L2RlZnM+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJtMTYuNSAyMiAxLTYuNS0xMCAuMDMgMSA2LjQzIi8+PHBhdGggZD0iTTMuNDYgMTJBNS42OSA1LjY5IDAgMCAxIDUgNy41IiBzdHlsZT0ic3Ryb2tlLXdpZHRoOjEuMXB4O3N0cm9rZTojNGQ0ZDRkO3N0cm9rZS1saW5lY2FwOnJvdW5kO3N0cm9rZS1saW5lam9pbjpyb3VuZDtmaWxsOm5vbmUiLz48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Ik0xNC42MiA1YTIuMzMgMi4zMyAwIDAgMS0yLjI1IDIuNWMtMS4zMyAwLTItMS4xMi0xLjk1LTIuNDRzLjctMi41IDItMi40OEEyLjI3IDIuMjcgMCAwIDEgMTQuNjIgNVpNMTcuNTggMTJhMy4yMyAzLjIzIDAgMCAwLTMuNDYtMy41SDExQTMuMjYgMy4yNiAwIDAgMCA3LjUgMTIiLz48Y2lyY2xlIGN4PSI0Ljk0IiBjeT0iNi45NiIgcj0iMS4wMSIgc3R5bGU9ImZpbGw6IzRkNGQ0ZDtzdHJva2Utd2lkdGg6MS4xcHg7c3Ryb2tlOiM0ZDRkNGQ7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kIi8+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNNy41NCAxOC41SDQuNWwtMi02aDIwbC0yIDZoLTMiLz48L3N2Zz4=)}.scylla-icon--support{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJDYWxxdWVfNCIgZGF0YS1uYW1lPSJDYWxxdWUgNCI+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNMTguMTkgNy41YTEwIDEwIDAgMCAxIC4yMSAyLjA3YzAgNC4zNi0yLjYzIDYuOTMtNS45IDYuOTNzLTUuOTQtMi41Ny01Ljk0LTYuOTNhMTAuNTEgMTAuNTEgMCAwIDEgLjIyLTIuMTIiLz48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Ik03LjY3IDIuMjNBNi41OCA2LjU4IDAgMCAxIDEyLjUuNWE1LjY1IDUuNjUgMCAwIDEgNC4yOSAxLjdjMS45MyAxLjk0IDIuMzUgNS4wNyAyLjQzIDYuNzJhMS40OSAxLjQ5IDAgMCAwLS43OS4wNSA4LjY4IDguNjggMCAwIDAtLjA4LTEuMTZoMGE1LjUzIDUuNTMgMCAwIDEtMS43Ny0yLjM0TDE2LjQ5IDVsLS4zOC4yMkExOSAxOSAwIDAgMSA2LjggNy4zOGEuNTIuNTIgMCAwIDAtLjQyLjE2Yy0uMjMuMjQtLjE1LjY1LS4wNyAxLjA4IDAgLjExIDAgLjIyLjA1LjMyYTEuNCAxLjQgMCAwIDAtLjU4IDBjLS4xLTEuNDUtLjA2LTQuNjggMS44OS02LjcxWk02LjM4IDljLS42NS0uMDgtMSAuMS0xLjE0Ljc5YTIuMDYgMi4wNiAwIDAgMCAxLjM3IDIuMjlNMTguNTYgOWMuNjUtLjA4IDEuMDUuMSAxLjE0Ljc5YTIuMDYgMi4wNiAwIDAgMS0xLjM3IDIuMjlNOS41IDE4LjIzVjE1LjVNMTUuNSAxNS41djIuNzNNMi41IDI0LjE2Yy4yNC0yIC41OS0zLjYzIDIuNDMtNC40OWEyNC4yOSAyNC4yOSAwIDAgMSA0LjgyLTEuMzdNMjIuNSAyNC4zM2MtLjI0LTItLjQyLTMuOC0yLjI2LTQuNjZhMjQuMjkgMjQuMjkgMCAwIDAtNC44Mi0xLjM3Ii8+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNMTUuMzkgMTguMzlhNC4zNyA0LjM3IDAgMCAxLTIuOTEgMS4wNyA0LjQyIDQuNDIgMCAwIDEtMi44OS0xLjA1Ii8+PHBhdGggc3R5bGU9ImZpbGw6Z3JheSIgZD0iTTExIDEzaDN2MmgtM3oiLz48cGF0aCBkPSJNMTguMDcgMTJhOS4yMSA5LjIxIDAgMCAxLTUuNTMgMi4wNyIgc3R5bGU9InN0cm9rZS1taXRlcmxpbWl0OjEwO2ZpbGw6bm9uZTtzdHJva2U6Z3JheSIvPjwvZz48L3N2Zz4=)}.scylla-icon--tech-talks{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJDYWxxdWVfNCIgZGF0YS1uYW1lPSJDYWxxdWUgNCI+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNOC4zOSA0LjVIMjMuNXYxM2gtMTUiLz48Y2lyY2xlIGN4PSI0LjUiIGN5PSI2LjUiIHI9IjIiIHN0eWxlPSJzdHJva2UtbWl0ZXJsaW1pdDoxMDtmaWxsOm5vbmU7c3Ryb2tlOmdyYXkiLz48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Ik0xLjUgOS41aDJsLjguODYuNy0uODZoNS41OGExIDEgMCAxIDEgMCAySDYuNXYxMC44OGExIDEgMCAwIDEtMSAxLjEyIDEgMSAwIDAgMS0xLTEgMSAxIDAgMCAxLTEgMSAuOTMuOTMgMCAwIDEtMS0xdi02Yy0uNzggMC0yLS40Ny0yLTF2LTVhMSAxIDAgMCAxIDEtMVoiLz48L2c+PC9zdmc+)}.scylla-icon--testing{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJDYWxxdWVfNCIgZGF0YS1uYW1lPSJDYWxxdWUgNCI+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNNi41IDYuNWgxMnYxMmgtMTJ6Ii8+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNNC41IDQuNWgxNnYxNmgtMTZ6Ii8+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJtOC41IDEwLjUgNSA1IDExLTEyIi8+PC9nPjwvc3ZnPg==)}.scylla-icon--thumbs-up{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSJjdXJyZW50Q29sb3IiIHN0cm9rZS13aWR0aD0iMiIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIiBjbGFzcz0iZmVhdGhlciBmZWF0aGVyLXRodW1icy11cCI+PHBhdGggZD0iTTE0IDlWNWEzIDMgMCAwIDAtMy0zbC00IDl2MTFoMTEuMjhhMiAyIDAgMCAwIDItMS43bDEuMzgtOWEyIDIgMCAwIDAtMi0yLjN6TTcgMjJINGEyIDIgMCAwIDEtMi0ydi03YTIgMiAwIDAgMSAyLTJoMyIvPjwvc3ZnPg==)}.scylla-icon--thumbs-down{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSJjdXJyZW50Q29sb3IiIHN0cm9rZS13aWR0aD0iMiIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIiBjbGFzcz0iZmVhdGhlciBmZWF0aGVyLXRodW1icy1kb3duIj48cGF0aCBkPSJNMTAgMTV2NGEzIDMgMCAwIDAgMyAzbDQtOVYySDUuNzJhMiAyIDAgMCAwLTIgMS43bC0xLjM4IDlhMiAyIDAgMCAwIDIgMi4zem03LTEzaDIuNjdBMi4zMSAyLjMxIDAgMCAxIDIyIDR2N2EyLjMxIDIuMzEgMCAwIDEtMi4zMyAySDE3Ii8+PC9zdmc+)}.scylla-icon--tip{background-image:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZD0iTTEyIDI0QzUuNCAyNCAwIDE4LjYgMCAxMlM1LjQgMCAxMiAwczEyIDUuNCAxMiAxMi01LjQgMTItMTIgMTJabTAtMjJDNi41IDIgMiA2LjUgMiAxMnM0LjUgMTAgMTAgMTAgMTAtNC41IDEwLTEwUzE3LjUgMiAxMiAyWiIgZmlsbD0iI2ZmZiIvPjxwYXRoIGQ9Ik0xMSAxNmMtLjMgMC0uNS0uMS0uNy0uM2wtMy0zYy0uNC0uNC0uNC0xIDAtMS40LjQtLjQgMS0uNCAxLjQgMGwzIDNjLjQuNC40IDEgMCAxLjQtLjIuMi0uNC4zLS43LjNaIiBmaWxsPSIjZmZmIi8+PHBhdGggZD0iTTExIDE2Yy0uMyAwLS41LS4xLS43LS4zLS40LS40LS40LTEgMC0xLjRsNi02Yy40LS40IDEtLjQgMS40IDAgLjQuNC40IDEgMCAxLjRsLTYgNmMtLjIuMi0uNC4zLS43LjNaIiBmaWxsPSIjZmZmIi8+PC9zdmc+)}.scylla-icon--training{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJDYWxxdWVfMiIgZGF0YS1uYW1lPSJDYWxxdWUgMiI+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNMTcuNSAxNS41SC41di0xM2gxOE01LjUgMjVsNC00LjMgNCA0LjMiLz48Y2lyY2xlIGN4PSIyMSIgY3k9IjQiIHI9IjIuNSIgc3R5bGU9InN0cm9rZS1taXRlcmxpbWl0OjEwO2ZpbGw6bm9uZTtzdHJva2U6Z3JheSIvPjxwYXRoIGNsYXNzPSJjbHMtMSIgZD0iTTIzLjQxIDcuNWgtMS41MkwyMSA5bC0uOS0xLjVIMTNBMS44IDEuOCAwIDAgMCAxMS41IDlhMS44IDEuOCAwIDAgMCAxLjUgMS41aDQuNXYxMy4yNEExLjQxIDEuNDEgMCAwIDAgMTkgMjVhMS40MiAxLjQyIDAgMCAwIDEuNS0xLjIyIDEuNTMgMS41MyAwIDAgMCAzIDB2LTcuMTFhMS4xMSAxLjExIDAgMCAwIDEuMDktMS4xOFY4LjY3YTEuMTggMS4xOCAwIDAgMC0xLjE4LTEuMTdaTTkuNSAxNS40NHY1LjM4Ii8+PC9nPjwvc3ZnPg==)}.collapsible-button .side-nav__content .toctree-checkbox:checked~label i,.collapsible-button .side-nav__content i,.scylla-icon--triangle-down,.side-nav__content .collapsible-button i,.side-nav__content .scylla-icon--expand,.side-nav__content .toctree-checkbox:checked~label .collapsible-button i,.side-nav__content .toctree-checkbox:checked~label .scylla-icon--expand{background-image:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTAiIGhlaWdodD0iNSIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cGF0aCBmaWxsLXJ1bGU9ImV2ZW5vZGQiIGNsaXAtcnVsZT0iZXZlbm9kZCIgZD0ibTAgMCA1IDUgNS01SDBaIiBmaWxsPSIjM0EyRDU1Ii8+PC9zdmc+)}.scylla-icon--university{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJDYWxxdWVfNCIgZGF0YS1uYW1lPSJDYWxxdWUgNCI+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJtMS41IDguNSAxMS00IDExIDR2M2wtMTEgNC0xMS00di0zeiIvPjxwYXRoIGNsYXNzPSJjbHMtMSIgZD0iTTUuNSAxMi41djVhMTIuNDYgMTIuNDYgMCAwIDAgNyAyIDExLjIgMTEuMiAwIDAgMCA3LTJ2LTUiLz48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Im0xMy41IDkuNSA4IDEuMjN2OC43N00yMi41IDE2LjV2MyIvPjwvZz48L3N2Zz4=)}.scylla-icon--users-blog{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMntmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJDYWxxdWVfNCIgZGF0YS1uYW1lPSJDYWxxdWUgNCI+PHBhdGggc3R5bGU9InN0cm9rZS13aWR0aDouOThweDtmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kIiBkPSJNMjMuNSAyLjVoLTIydjE2aDEzdjQuMTdsNC4wNC00LjE3IDQuOTYtLjA0VjIuNXoiLz48cGF0aCBjbGFzcz0iY2xzLTIiIGQ9Ik0xMC44NSA4QTEwLjM4IDEwLjM4IDAgMCAxIDExIDkuNWMwIDIuNDctMS4yMSA0LTMgNHMtMy41LTItMy41LTQuNWE0LjE4IDQuMTggMCAwIDEgMC0xIi8+PHBhdGggY2xhc3M9ImNscy0yIiBkPSJNNS4yIDUuMDdhMy4yMiAzLjIyIDAgMCAxIDIuNS0xIDMuMTYgMy4xNiAwIDAgMSAyLjQgMSA2LjIyIDYuMjIgMCAwIDEgMS4zIDMuODEuNzQuNzQgMCAwIDAtLjQyIDBjMC0uMjQgMC0uNDQtLjA1LS42NmgwQTMgMyAwIDAgMSAxMCA2Ljl2LS4yNGwtLjIxLjEyQTkuNjIgOS42MiAwIDAgMSA0LjczIDhhLjI1LjI1IDAgMCAwLS4yMi4wOWMtLjEzLjE0LS4wOS4zNyAwIC42MXYuMThhLjg1Ljg1IDAgMCAwLS4zMiAwQTUuMzcgNS4zNyAwIDAgMSA1LjIgNS4wN1pNNC41MSA4LjkzYy0uMzUgMC0uNTcuMDUtLjYxLjQ0YTEuMTcgMS4xNyAwIDAgMCAuNzMgMS4zTTExIDguOTNjLjM2IDAgLjU3LjA1LjYyLjQ0YTEuMTcgMS4xNyAwIDAgMS0uNzQgMS4zTTYuMzEgMTQuMTN2LS44NE05LjI1IDEzLjE5di45NE0yLjQyIDE4Yy4xMy0xLjE1LjU4LTIuNTIgMS41OC0zYTE0LjcxIDE0LjcxIDAgMCAxIDIuMzEtLjgyTTEzLjUgMThjLS4xMy0xLjE1LS41MS0yLjUyLTEuNS0zcy0yLjUtMS0yLjUtMSIvPjxwYXRoIGNsYXNzPSJjbHMtMiIgZD0iTTkuMzQgMTQuMjJhMi4yMyAyLjIzIDAgMCAxLTEuNTYuNjEgMi4zMiAyLjMyIDAgMCAxLTEuNTUtLjU5TTIxLjUgNi41aC03TTIxLjUgOS41aC03TTE4LjUgMTIuNWgtNCIvPjwvZz48L3N2Zz4=)}.admonition.caution .admonition-title:before,.admonition.warning .admonition-title:before,.scylla-icon--warning{background-image:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PG1hc2sgaWQ9ImEiIG1hc2stdHlwZT0iYWxwaGEiIG1hc2tVbml0cz0idXNlclNwYWNlT25Vc2UiIHg9IjAiIHk9IjEiIHdpZHRoPSIyNCIgaGVpZ2h0PSIyMSI+PHBhdGggZD0iTTMuNSAyMmMtLjUgMC0xLS4xLTEuNS0uNEMuNiAyMC44LjEgMTguOS45IDE3LjVMOS40IDMuM2MuMy0uNC42LS44IDEtMSAuNy0uNCAxLjUtLjUgMi4zLS4zLjguMiAxLjQuNyAxLjkgMS40TDIzIDE3LjVjLjMuNS40IDEgLjQgMS41IDAgLjgtLjMgMS42LS45IDIuMS0uNS42LTEuMi45LTIgLjloLTE3Wm03LjYtMTcuNkwyLjcgMTguNWMtLjMuNS0uMSAxLjEuNCAxLjQuMS4xLjMuMS40LjFoMTYuOWMuMyAwIC41LS4xLjctLjMuMi0uMi4zLS40LjMtLjcgMC0uMiAwLS4zLS4xLS41TDEyLjkgNC40Yy0uMy0uNS0uOS0uNi0xLjQtLjQtLjIuMS0uMy4yLS40LjRaIiBmaWxsPSIjMDYxOTM4Ii8+PHBhdGggZD0iTTEyIDE0Yy0uNiAwLTEtLjQtMS0xVjljMC0uNi40LTEgMS0xczEgLjQgMSAxdjRjMCAuNi0uNCAxLTEgMVpNMTIgMThjLS4zIDAtLjUtLjEtLjctLjMtLjItLjItLjMtLjQtLjMtLjcgMC0uMSAwLS4zLjEtLjQuMS0uMS4xLS4yLjItLjMuMS0uMS4yLS4yLjMtLjIuMi0uMS40LS4xLjYtLjEuMSAwIC4xIDAgLjIuMS4xIDAgLjEgMCAuMi4xIDAgMCAuMS4xLjIuMS4xLjEuMi4yLjIuMyAwIC4xLjEuMy4xLjQgMCAuMy0uMS41LS4zLjctLjMuMi0uNS4zLS44LjNaIiBmaWxsPSIjMDYxOTM4Ii8+PC9tYXNrPjxnIG1hc2s9InVybCgjYSkiPjxwYXRoIGZpbGw9IiMwNjE5MzgiIGQ9Ik0wIDBoMjR2MjRIMHoiLz48L2c+PC9zdmc+)}.scylla-icon--webinars{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMntmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJDYWxxdWVfNCIgZGF0YS1uYW1lPSJDYWxxdWUgNCI+PHBhdGggc3R5bGU9InN0cm9rZS1taXRlcmxpbWl0OjEwO2ZpbGw6bm9uZTtzdHJva2U6Z3JheSIgZD0iTTEuNSA1LjVoMjJ2MTRoLTIyeiIvPjxwYXRoIGNsYXNzPSJjbHMtMiIgZD0iTTkuNDcgMjAuNXYxLjg4TTE1LjUgMjAuNXYyTTYuNSAyMi41aDEyIi8+PHBhdGggc3R5bGU9ImZpbGw6Z3JheSIgZD0ibTkgOSA3LjUgMy41M0w5IDE2Vjl6Ii8+PC9nPjwvc3ZnPg==)}.scylla-icon--whitepapers{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMntmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJDYWxxdWVfNCIgZGF0YS1uYW1lPSJDYWxxdWUgNCI+PHBhdGggc3R5bGU9ImZpbGw6Z3JheSIgZD0iTTggOWg4djJIOHoiLz48cGF0aCBjbGFzcz0iY2xzLTIiIGQ9Ik0xNC4wNiAxLjUgMy41IDEuNTJWMjMuNWgxN1Y3bC02LjQ0LTUuNXoiLz48cGF0aCBkPSJNMTQuMzIgMS40MnYzLjM3YTIuMDYgMi4wNiAwIDAgMCAyLjA4IDIuMWgzLjY3IiBzdHlsZT0ic3Ryb2tlLW1pdGVybGltaXQ6MTA7ZmlsbDpub25lO3N0cm9rZTpncmF5Ii8+PHBhdGggY2xhc3M9ImNscy0yIiBkPSJNNi41IDE5LjVoNE0xMy41IDE5LjVoNE02LjUgMTYuNWg0TTEzLjUgMTYuNWg0TTYuNSAxMy41aDRNMTMuNSAxMy41aDQiLz48L2c+PC9zdmc+)}.scylla-icon--workshop{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMSwuY2xzLTJ7ZmlsbDpub25lO3N0cm9rZTojNGQ0ZDRkfS5jbHMtMXtzdHJva2UtbWl0ZXJsaW1pdDoxMH0uY2xzLTJ7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJDYWxxdWVfNCIgZGF0YS1uYW1lPSJDYWxxdWUgNCI+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNMS41IDUuNWgyMnYxNGgtMjJ6Ii8+PHBhdGggY2xhc3M9ImNscy0yIiBkPSJtOS41IDE5LjUtLjAzIDIuODhNMTUuNSAxOS41djNNNi41IDIyLjVoMTIiLz48cGF0aCBzdHlsZT0iZmlsbDojNGQ0ZDRkIiBkPSJtNCA4IDIgOCAuOTctMy45NUwxMSAxMiA0IDh6Ii8+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJtNi40NyAxMS4zNCAzLjM3IDQuMjgiLz48L2c+PC9zdmc+)}.button{background:transparent;border:1px solid #3a2d55;border-radius:4px;color:#3a2d55;display:inline;font-size:14px;letter-spacing:1px;line-height:21px;margin:0;padding:12px 14px}.button:focus,.button:hover{background:transparent;color:#3a2d55;text-decoration:none}.button--reverse{background:#fff;border:0}.button--reverse:focus,.button--reverse:hover{background:#fff}.tooltip{background-color:rgba(0,0,0,.56);border-radius:4px;font-size:12px;padding:6px}.tooltip:before{display:none!important}.tooltip:empty{display:none!important}.has-tip{border:0;cursor:pointer}.scylla-dropdown{color:#23263b;font-size:14px;line-height:20px}.scylla-dropdown a,.scylla-dropdown a:focus,.scylla-dropdown a:hover{color:#23263b!important;padding:0!important}.scylla-dropdown__item{font-size:16px;padding:15px}.scylla-dropdown__title{align-items:center;display:flex!important;position:static!important}.scylla-dropdown__title:after{display:none!important}.scylla-dropdown__title .chevron{min-height:5px;width:10px}.scylla-dropdown__content{background:#fff;border:0;border-radius:8px;box-shadow:0 4px 25px rgba(0,0,0,.15);font-size:16px;list-style:none;margin-top:15px;overflow:hidden;padding:16px 0;width:max-content}.scylla-dropdown__content li{padding:7px 16px}.scylla-dropdown__content .contents.local>ul>li a:before,.scylla-dropdown__content .secondary-side-nav__content li a:before,.scylla-dropdown__content li .admonition-title:before,.scylla-dropdown__content li .scylla-icon,.secondary-side-nav__content .scylla-dropdown__content li a:before{margin-right:10px}.enlarge-image{cursor:zoom-in}.enlarge-image-reveal{background:transparent;border:none;cursor:zoom-out;padding:0;text-align:center;width:fit-content}.enlarge-image-reveal img{background-color:#fff;padding:15px}.header{background-color:#fff;box-shadow:0 2px 22px rgba(74,93,166,.15);justify-content:space-between;padding:12.75px 0;position:fixed;width:100%;z-index:99}.header,.header-logo{align-items:center;display:flex}.header-logo{margin-left:20px;width:auto}.header-logo__img{width:110px}.header-logo__bar{background-color:#3a2d55;border-left:1px solid #3a2d55;height:11.56px;margin:0 7.5px;width:0}.header-logo__text{color:#3a2d55;font-size:10.11px;letter-spacing:.722408px;line-height:12px;text-transform:uppercase}.header-navigation{display:none}.header-button{display:none;margin-left:15px;text-transform:uppercase}.header-search-box{display:none;margin-right:20px;width:200px}.scylla-dropdown--header .scylla-dropdown__item{font-size:14px}.scylla-dropdown--header .scylla-dropdown__title{text-transform:uppercase}.scylla-dropdown--header .scylla-dropdown__title .chevron{margin-left:10px}.contents.local>ul>li .scylla-dropdown--header .scylla-dropdown__content a:before,.scylla-dropdown--header .scylla-dropdown__content .admonition-title:before,.scylla-dropdown--header .scylla-dropdown__content .contents.local>ul>li a:before,.scylla-dropdown--header .scylla-dropdown__content .scylla-icon,.scylla-dropdown--header .scylla-dropdown__content .secondary-side-nav__content li a:before,.secondary-side-nav__content li .scylla-dropdown--header .scylla-dropdown__content a:before{min-height:20px;width:20px}@media screen and (min-width:1024px){.header{padding:18px 0}.header-logo__img{width:152px}.header-logo__bar{height:16px;margin:0 10px}.header-logo__text{font-size:14px;letter-spacing:.722408px;line-height:12px;text-transform:uppercase}.header-navigation{align-items:center;display:flex;justify-content:center}.header-search-box{display:block}}@media screen and (min-width:1200px){.header-logo{margin-left:30px;width:357px}.header-search-box{margin-right:30px;max-width:20%;width:318px}.header-button{display:block}}.side-nav{background:#fff;display:none;height:100vh;left:0;line-height:24px;max-height:calc(100vh - 50px);overflow-y:auto;padding:20px 20px 0;position:fixed;top:50px;width:100%;z-index:100}.side-nav__title{font-weight:700;margin-bottom:20px}.side-nav__content{max-width:90%;overflow-wrap:break-word}.side-nav__content label,.side-nav__content label i{margin:0;padding:0}.side-nav__content label{font-size:inherit;line-height:1;margin-left:5px;max-height:5px}.collapsible-button .side-nav__content i,.side-nav__content .collapsible-button i,.side-nav__content .scylla-icon--expand{height:5px;vertical-align:top;width:10px}.side-nav__content .toctree-checkbox{display:none;position:absolute;right:20px}.side-nav__content .toctree-checkbox~ul{display:none;margin-right:20px}.side-nav__content .toctree-checkbox:checked~ul{display:block}.side-nav__content ul{margin:0}.side-nav__content a{color:#23263b}.side-nav__content a:hover{color:#3c4fe0;font-weight:400}.side-nav__content li{list-style:none;padding:0 0 24px}.side-nav__content li.has-children{align-items:center;display:flex;flex-wrap:wrap}.side-nav__content li.has-children>a{max-width:calc(100% - 15px)}.side-nav__content li.has-children.current{padding-bottom:20px}.side-nav__content li.has-children:hover>a{color:#3c4fe0}.side-nav__content li.has-children:hover>.toctree-checkbox~label i{filter:invert(38%) sepia(71%) saturate(6789%) hue-rotate(231deg) brightness(90%) contrast(95%)}.side-nav__content li.current-page>a{color:#3c4fe0}.side-nav__content li.current-page>.toctree-checkbox:checked~label i{filter:invert(38%) sepia(71%) saturate(6789%) hue-rotate(231deg) brightness(90%) contrast(95%)}.side-nav__content li ul{margin-top:18px;width:100%}.side-nav__content li ul li{border-left:1px solid #3c4fe0;padding:4px 0 4px 13px}.side-nav__content li ul ul{margin-left:0}.side-nav__content li .label{display:none}.side-nav__versions{max-width:90%}.side-nav__search,.side-nav__versions .dropdown{margin-bottom:20px}.collapsible-button{background:#fff;background-color:#fff;border:0;border-radius:8px;border-radius:50%;bottom:10px;box-shadow:0 4px 25px rgba(0,0,0,.15);cursor:pointer;display:none;font-size:0;left:300px;overflow:hidden;padding:13.5px;position:fixed}.collapsible-button i{height:16px;margin:0;width:16px}.side-nav--collapsed .collapsible-button{border-radius:0 20px 20px 0;left:-10px}.side-nav--collapsed .collapsible-button i{transform:rotate(180deg)}.layout--has-banner .side-nav{max-height:calc(100vh - 92.5px)}@media screen and (min-width:1024px){.side-nav{background-color:#f6f8ff;display:block;height:100%;left:auto;max-height:100vh;max-height:calc(100vh - 80px);padding:30px 40px;top:80px;width:286px;z-index:25}.side-nav__content{max-width:100%;padding-bottom:180px}.side-nav__search{display:none}.side-nav__versions{max-width:100%}.toctree-checkbox{right:40px}.layout--has-banner .side-nav{max-height:calc(100vh - 150px)}}@media screen and (min-width:1200px){.side-nav{width:357px}.side-nav--collapsed{background-color:transparent;padding-left:0;padding-right:0;width:126px}.side-nav--collapsed .side-nav-content{display:none}.collapsible-button{display:block}}.side-nav-toggle{cursor:pointer;display:block;margin-right:20px;position:relative;z-index:300}@media screen and (min-width:1024px){.side-nav-toggle{display:none}}.secondary-side-nav{display:none;height:100%;line-height:24px;padding:20px;width:100%}.secondary-side-nav__content{overflow-wrap:break-word}.secondary-side-nav__content ul{list-style:none;margin:0}.secondary-side-nav__content li{border-bottom:1px solid rgba(90,94,154,.1);display:none;padding:10px 0;word-break:break-word}.secondary-side-nav__content li:last-child{border:0}.secondary-side-nav__content li .label{display:none}.secondary-side-nav__content li a{align-items:baseline;color:#b3bac5;display:flex;font-size:14px}.secondary-side-nav__content li a:before{content:"";filter:invert(40%) sepia(11%) saturate(2157%) hue-rotate(198deg) brightness(89%) contrast(87%)!important;flex-shrink:0;margin-right:10px;min-height:10px;opacity:.5;width:6px}.secondary-side-nav__content li a.current,.secondary-side-nav__content li a:hover{color:#23263b;font-weight:400}.secondary-side-nav__content li a.current:before,.secondary-side-nav__content li a:hover:before{filter:brightness(0);opacity:1}.secondary-side-nav__content li a.current{font-weight:700}.secondary-side-nav__content>ul>li>ul>li{display:block}.secondary-side-nav__content>ul>li{border:0;display:block}.secondary-side-nav__content>ul>li>a{display:none}@media screen and (min-width:1200px){.secondary-side-nav{display:block;max-height:100vh;max-height:calc(100vh - 80px);overflow-y:auto;padding:60px 60px 60px 20px;position:fixed;top:80px;width:286px}.secondary-side-nav__content{padding-bottom:180px}.layout--has-banner .secondary-side-nav{max-height:calc(100vh - 150px)}}.layout{display:flex}.pre-content{align-items:center;display:flex;justify-content:space-between;margin-bottom:20px}.content{margin-top:50px;max-width:1440px;overflow-wrap:break-word;padding:20px;scroll-margin-top:50px;width:100%}.content .line-block,.content p{line-height:28px;margin-bottom:20px}.content ul{list-style:none}.content ul li:before{color:#b3bac5;content:"•";float:left;font-family:FontAwesome;font-size:20px;font-weight:700;margin-left:-1em;margin-top:-2px;width:1em}.content ul ul{list-style:circle}.content ul ul li:before{content:""}.content ol ol{list-style:lower-latin}.content img{margin-bottom:30px}.content section{margin-top:-50px;padding-top:50px}.content .inline-icon.fa-check{color:#42c4e6}.layout--full-width .content{max-width:100%;padding:0;width:100%}.layout--full-width .content .hero-wrapper,.layout--full-width .content .topics-grid{max-width:1190px}.layout--full-width .content.content--collapsed{margin-left:0}.layout--full-width:not(.layout--sidebar) .content{margin-left:0}.layout--has-banner .content{scroll-margin-top:92.5px}.layout--has-banner .content section{margin-top:-92.5px;padding-top:92.5px}.landing__content{padding:0 16px}@media screen and (min-width:1024px){.content{margin-left:286px;margin-top:80px;min-height:calc(100vh - 260px);padding-bottom:100px;scroll-margin-top:80px;width:calc(100% - 286px)}.content section{margin-top:-80px;padding-top:80px}}@media screen and (min-width:1200px){.content{margin-left:357px;padding:60px 40px 40px;width:calc(100% - 643px)}.content--collapsed{margin-left:126px;width:calc(100% - 412px)}.pre-content{margin-bottom:10px}.layout--has-banner .content{scroll-margin-top:150px}.layout--has-banner .content section{margin-top:-150px;padding-top:150px}.landing__content{padding:0 60px}.landing--floating .landing__content{position:relative;top:-70px}}.contents.local>ul{margin-bottom:30px;margin-left:0}.contents.local>ul>li{border-bottom:1px solid rgba(90,94,154,.1);padding:10px 0;word-break:break-word}.contents.local>ul>li:before{content:""}.contents.local>ul>li:last-child{border:0}.contents.local>ul>li ul{display:none}.contents.local>ul>li p{margin:0}.contents.local>ul>li a{font-size:14px}.contents.local>ul>li a:before{content:"";filter:invert(40%) sepia(11%) saturate(2157%) hue-rotate(198deg) brightness(89%) contrast(87%)!important;margin-right:10px;min-height:10px;opacity:.5;width:10px}.contents.local>ul>li a.current:before,.contents.local>ul>li a:hover:before{filter:brightness(0);opacity:1}.topic-title{color:rgba(35,38,59,.75);font-size:10px;letter-spacing:1.5px;margin-bottom:0;text-transform:uppercase}.notice{margin-top:40px}.footer{background-color:#fff;box-shadow:0 -4px 10px hsla(0,0%,82%,.25);padding:30px 0;position:relative;width:100%;z-index:50}.footer-group{margin:0 auto;max-width:1030px;padding:0 20px}.footer-top{align-items:center;border-bottom:1px solid rgba(0,0,0,.1);display:flex;flex-wrap:wrap;justify-content:space-between;padding-bottom:8px;text-align:center}.footer-logo{margin-bottom:30px;width:100%}.footer-logo img{float:left;height:36px}.footer-links{text-align:left}.footer-links__link{color:#333;font-size:12px;font-weight:500;letter-spacing:2.4px;margin-right:16px;text-transform:uppercase}.footer-actions{align-items:center;display:flex;justify-content:space-between;width:90px}.footer-actions__link{color:#000}.footer-actions__link img{height:23px}.footer-bottom{color:#979797;display:flex;flex-wrap:wrap;font-size:12px;font-style:normal;font-weight:400;justify-content:center;letter-spacing:1.4px;line-height:23px;padding:20px 0 10px;text-align:center;text-transform:uppercase}@media screen and (max-width:510px){.footer-links{margin-bottom:20px}}@media screen and (min-width:1024px){.footer{padding:30px 0}.footer-group{padding:0}.footer-top{padding-bottom:30px}.footer-logo{margin:0;width:auto}.footer-links{padding:0 40px}.footer-links__link{font-size:14px;margin-right:28px}.footer-actions{width:110px}.footer-actions__link img{height:28px}.footer-bottom .footer-bottom__copyright,.footer-bottom .footer-bottom__last-updated,.footer-bottom .footer-bottom__version{padding:0 10px}.footer-bottom .footer-bottom__copyright{border-left:none}}.not-found{background-color:#f6f8ff;height:100%;overflow:hidden}.not-found__icon{display:block;margin:40px auto;max-width:300px}.not-found__text{text-align:center}.not-found__text h1{font-size:60px;line-height:1}.not-found__text p{margin:30px 0;width:100%}.not-found__button{text-transform:uppercase}.admonition{border-radius:4px;box-shadow:0 4px 4px rgba(0,0,0,.12);color:rgba(0,0,0,.56);font-size:14px;line-height:20px;margin-bottom:30px;overflow:auto;padding:20px;position:relative}.admonition:before{bottom:0;content:" ";left:0;position:absolute;right:0;top:0;z-index:-1}.admonition-title{color:#23263b;margin-bottom:0!important}.admonition-title:before{content:"";margin-right:8px;min-height:24px;width:24px}.admonition p:not(.admonition-title){margin-bottom:0!important;margin-left:32px}.admonition.tip{border:1px solid #43a047}.admonition.tip:before{border-left:8px solid rgba(67,160,71,.4)}.admonition.tip .admonition-title:before{filter:invert(47%) sepia(11%) saturate(2286%) hue-rotate(73deg) brightness(109%) contrast(88%)}.admonition.note{border:1px solid #1976d2}.admonition.note:before{border-left:8px solid rgba(25,118,210,.4)}.admonition.note .admonition-title:before{filter:invert(44%) sepia(55%) saturate(2310%) hue-rotate(191deg) brightness(81%) contrast(103%)}.admonition.caution{border:1px solid #ffab00}.admonition.caution:before{border-left:8px solid rgba(255,171,0,.4)}.admonition.caution .admonition-title:before{filter:invert(77%) sepia(56%) saturate(3332%) hue-rotate(357deg) brightness(98%) contrast(108%)}.admonition.warning{border:1px solid #e74c3c}.admonition.warning:before{border-left:8px solid rgba(231,76,60,.4)}.admonition.warning .admonition-title:before{filter:invert(41%) sepia(42%) saturate(6427%) hue-rotate(343deg) brightness(99%) contrast(83%)}.breadcrumbs{margin-bottom:0;text-transform:uppercase}.breadcrumbs .bread__item,.breadcrumbs .bread__item:not(.bread__item--last):after,.breadcrumbs a{color:#23263b;font-size:12px;font-weight:400;letter-spacing:1.5px;line-height:2;margin:0;padding:0}.breadcrumbs .bread__item:before{display:none}.breadcrumbs .bread__item:not(.bread__item--last):after{content:"/";margin:0 5px;opacity:1;position:relative}.breadcrumbs .bread__highlight{color:#3c4fe0}.breadcrumbs .bread__highlight:hover{font-weight:700;text-decoration:none}code{background-color:#f7f8f9;border:none;border-radius:4px;color:#23263b;font-size:14px}code.download{background:none;color:#23263b}.highlight{background:transparent!important}.highlight pre{background-color:#f7f8f9;border-radius:8px;color:#23263b;font-size:14px;line-height:26px;margin-bottom:30px;overflow:auto;padding:16px}.highlight a.copybtn{right:1em;top:1em}.highlighttable{background-color:#f7f8f9;border-radius:16px;box-shadow:none}.highlighttable tbody{background-color:transparent;border:0}.highlighttable tbody td{padding:15px!important}.highlighttable tbody tr{border-top:none}.highlighttable .linenos{background-color:#f7f8f9;color:#5a7184;width:50px}.highlighttable .linenos span{line-height:26px}.highlighttable .highlight pre{background-color:transparent;margin:0;padding:0}.highlighttable .highlight a.copybtn{right:.2em;top:.2em}.hide-copy-button .copybtn{display:none}.sphinx_collapse__label{display:flex!important;flex-direction:row-reverse;font-size:medium;font-weight:700;justify-content:flex-end;margin-left:0!important}.sphinx_collapse__icon{margin-left:5px;margin-right:0}.sphinx_collapse__input:checked~.sphinx_collapse__label,.sphinx_collapse__label:hover{color:#3c4fe0}.sphinx_collapse__input:checked~.sphinx_collapse__label .sphinx_collapse__icon,.sphinx_collapse__label:hover .sphinx_collapse__icon{border-top-color:#3c4fe0}.sphinx_collapse__content{margin-top:10px}.contribute{margin:0 0 20px}.contribute__item{font-size:14px;list-style:none;padding-bottom:10px}.contribute__item .icon{margin-right:5px}.content-navigation{display:flex;justify-content:space-between;margin-top:40px}.navigation{max-width:50%;word-break:break-word}.navigation,.navigation__link{display:flex}.navigation__title{word-wrap:break-word;color:#23263b;font-size:12px;font-weight:500;letter-spacing:1.5px;line-height:24px;text-transform:uppercase}.navigation__title .colored{color:#42c4e6}.navigation__button{background:#fff;background-color:#fff;border:0;border-radius:8px;box-shadow:0 4px 25px rgba(0,0,0,.15);cursor:pointer;display:none;font-size:0;height:fit-content;overflow:hidden;padding:13.5px 16.5px}.navigation__button i{height:16px;margin:0;width:10px}.navigation--prev .navigation__title{margin-left:15px}.navigation--next .navigation__title{margin-right:15px;text-align:right}@media screen and (min-width:1200px){.navigation__title{display:inline-block}.navigation__button{display:block}.navigation--next .navigation__title{text-align:left}}.scylla-dropdown--versions .scylla-dropdown__item{background:#fff;border-radius:8px;box-shadow:0 28px 32px rgba(0,0,0,.06);width:100%}.scylla-dropdown--versions .scylla-dropdown__title{align-items:center;display:flex;justify-content:space-between}.scylla-dropdown--versions .scylla-dropdown__title .chevron{min-height:12px;transform:rotate(90deg);width:8px}@media screen and (min-width:1024px){.scylla-dropdown--versions .scylla-dropdown__item{box-shadow:none}}.feedback-container{font-size:16px;margin-top:40px;text-align:left}.feedback-container__title{font-weight:700;margin-bottom:5px!important}.feedback-container__button{background:#fff;border:0;border-radius:8px;box-shadow:0 4px 25px rgba(0,0,0,.15);cursor:pointer;margin:4px;overflow:hidden;padding:8px}.feedback-container__button.active{border:1px solid #3c4fe0}.feedback-container__icon{height:20px;width:20px}.feedback-container__message{font-size:16px;margin-top:10px}.hero{background:#f6f8ff;margin-bottom:30px;overflow:hidden;padding:30px 16px;text-align:left}.hero__title{font-size:28px;font-weight:500;line-height:38px;margin-bottom:14px;max-width:229px}.hero__text{font-size:16px;line-height:26px;max-width:343px}.hero__text a{border-bottom:1px dotted #23263b;color:#23263b}.hero__text p{margin-bottom:0!important}.hero__img{position:absolute;right:-18px;top:20px}.hero__img img{margin-bottom:0!important;width:124px}.hero__button{margin-top:20px;text-transform:uppercase}.hero__button .icon{margin-right:5px}.hero__search-box{box-shadow:0 4px 25px rgba(0,0,0,.02);margin-top:20px}.hero-wrapper{align-items:center;display:flex;justify-content:space-between;margin:0 auto;position:relative}@media screen and (min-width:640px){.hero{padding:60px 16px}.hero__title{font-size:32px;line-height:42px;max-width:482px}.hero__text{font-size:18px;line-height:26px;max-width:482px}.hero__img{display:block;position:static}.hero__img img{height:100%;width:295px}.hero .hero-wrapper{flex-direction:row-reverse}.hero .landing--floating .hero{padding:30px 16px 100px}}@media screen and (min-width:1024px){.hero{padding:60px}}.label{background-color:#23263b;border:0;border-radius:4px;color:#fff;font-size:inherit}.label--note{background-color:#1976d2}.label--tip{background-color:#43a047}.label--caution{background-color:#ffab00}.label--warning{background-color:#e74c3c}.last-updated{color:#4458a3;font-size:12px;letter-spacing:1.5px;margin:10px 0;text-transform:uppercase}.last-updated__icon{font-size:14px}@media screen and (min-width:1024px){.last-updated{float:right;margin:0}}.panel{border:0;border-radius:4px;margin-bottom:30px}.promo-banner{background-color:#4458a3;background-image:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTQ0MCIgaGVpZ2h0PSI3MCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48bWFzayBpZD0iYSIgbWFzay10eXBlPSJhbHBoYSIgbWFza1VuaXRzPSJ1c2VyU3BhY2VPblVzZSIgeD0iMCIgeT0iMCIgd2lkdGg9IjE0NDAiIGhlaWdodD0iNzAiPjxwYXRoIGZpbGw9IiM0NDU4QTMiIGQ9Ik0wIDBoMTQ0MHY3MEgweiIvPjwvbWFzaz48ZyBtYXNrPSJ1cmwoI2EpIiBmaWxsPSIjNTA2NEFFIj48cGF0aCBkPSJNLTE5MyAyMDEuODg0IDEuNS0xMzUgMzU3LjQzNiA3MC41bC0xOTQuNSAzMzYuODg0ek0xMDkyLjkyLTM4LjAwOSA5NzIuODAzLTI0Ni4wNTcgNDAyLjk5NiA4Mi45MiA1MjMuMTEzIDI5MC45N3oiLz48cGF0aCBkPSJtMTAzOC0zOC4wMDkgMTIwLjExNy0yMDguMDQ5IDU2OS44MDcgMzI4Ljk3OS0xMjAuMTE3IDIwOC4wNDl6Ii8+PC9nPjwvc3ZnPg==);background-position:50%;background-repeat:no-repeat;background-size:cover;display:none;overflow:hidden;position:fixed;top:0;width:100%;z-index:900}.promo-banner__icon{margin-right:15px}.promo-banner__icon img{height:40px}.promo-banner__title{color:#fff;font-size:12px;line-height:16px;margin-right:15px}.promo-banner__button{background:#fff;border-radius:4px;font-size:12px;min-width:max-content;padding:5px}.promo-banner__close{display:none;position:absolute;right:16px;top:16px}.contents.local>ul>li .promo-banner__close a:before,.promo-banner__close .admonition-title:before,.promo-banner__close .contents.local>ul>li a:before,.promo-banner__close .scylla-icon,.promo-banner__close .secondary-side-nav__content li a:before,.secondary-side-nav__content li .promo-banner__close a:before{filter:brightness(100%);height:34px;width:34px}.promo-banner__close:hover{cursor:pointer;filter:opacity(.8)}.promo-banner-wrapper{align-items:center;display:flex;justify-content:center;padding:5.85px 20px}@media(min-width:1024px){.promo-banner__title{font-size:18px;line-height:23px}.promo-banner__button{font-size:14px;padding:8.5px}.promo-banner__close{display:block}.promo-banner-wrapper{flex-direction:unset;padding:16px}}.custom-scroll-bar::-webkit-scrollbar{background-color:transparent;width:5px}.custom-scroll-bar::-webkit-scrollbar-thumb{background-color:#b3bac5;-webkit-border-radius:8px;border-radius:8px}.search-box{background:#f7f8f9;border-radius:4px;display:flex;padding:10px 15px}.search-box--hero{background-color:#fff;padding:12px 14px}.search-box:before{background-image:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZD0iTTEwLjUgMThhNy41IDcuNSAwIDEgMCAwLTE1IDcuNSA3LjUgMCAwIDAgMCAxNVpNMjEgMjFsLTUuMi01LjIiIHN0cm9rZT0iIzAwMCIgc3Ryb2tlLXdpZHRoPSIyIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiLz48L3N2Zz4=);background-repeat:no-repeat;background-size:contain;content:"";display:inline-block;filter:brightness(0);margin-top:2px;min-height:18px;min-width:18px;vertical-align:middle;width:20px}.search-box .er-dummy-search,.search-box .er-dummy-search-box,.search-box .er-search-form,.search-box ci-search,.search-box input{margin:0!important;width:100%!important}.search-box input{background:transparent!important;color:rgba(80,80,80,.5)!important;font-size:14px!important;padding:0!important}.search-box input::placeholder{color:rgba(80,80,80,.5)!important;opacity:1!important}.search-box button{display:none!important}.er_search_suggestions{background:#fff;border:0;border:0!important;border-radius:8px;box-shadow:0 4px 25px rgba(0,0,0,.15);overflow:hidden}.er_search_suggestions .er-search-result-box{border-width:1px!important;padding-bottom:10px!important;padding-top:10px!important}.er_search_suggestions .er-search-result-box:hover{background:#f7f8f9!important}.er_search_suggestions .er_more_result_btn{cursor:pointer}.er_search_suggestions h3{font-size:16px!important}.er-search-content{padding:20px!important}#er_search_results .er-search-result-box{display:block!important;margin:10px auto 0!important;width:100%!important}#er_search_results .text,#er_search_results .title a,#er_search_results .url a{max-width:100%!important}#search-result-input-form{max-width:800px!important}#er_search_button{text-align:center}#er_clear_input{right:0!important;top:0!important}.er-facet-header{background-color:transparent!important;border:0!important;padding:0 0 8px!important}.er-facet-val{padding:5px 2px!important}.er-facet-val input{display:block!important;margin:0}#er_search_pagination{margin-top:20px!important}#er_search_pagination li.er-paginator-list.er-active{border-bottom:0!important;font-weight:700}.er-suggestion-sm .er_search_input_dummy{margin:0!important}.er-suggestion-sm .er_search_button_dummy{border:0!important}#er_gcs_mobile_model_container .er-facet-values .er-facet-val{align-items:baseline}@media screen and (min-width:640px){.er-facets{display:none;max-width:300px!important;min-width:auto!important;width:auto!important}}@media screen and (min-width:1024px){.er-suggestions{left:15px!important}}@media screen and (min-width:1200px){.er-facets{display:block;position:fixed!important}.er-facet-count{display:none}}.sphinx-tabs{margin-bottom:30px}.sphinx-tabs-tab{border-bottom:1px solid rgba(0,0,0,.56);color:rgba(0,0,0,.56);cursor:pointer;font-size:14px;font-weight:500;line-height:13px;padding:20px 25px}.sphinx-tabs-tab[aria-selected=true]{border-bottom:2px solid #2196f3;color:#2196f3;padding-bottom:19px}.sphinx-tabs-panel{margin:30px 0}.table-wrapper{border:1px solid #e0e0e0;border-radius:4px;box-shadow:0 1px 2px rgba(0,0,0,.25);display:block;margin-bottom:30px;max-width:100%;overflow-x:auto}table{color:#000;font-size:14px;line-height:24px;margin:0;overflow:hidden}table p{margin:0!important}table caption{background:#f6f8ff;border-bottom:1px solid #e0e0e0;color:#23263b;padding:10px 25px}table thead{background:#f6f8ff;border:0;border-bottom:1px solid #4458a3}table thead th{color:#23263b;font-size:14px;font-weight:700}table td,table thead th{padding:20px 25px}table tbody tr{background-color:transparent!important;border-top:1px solid #e0e0e0;line-height:18px}table:not(.highlighttable) tbody tr:first-child{border-top:1px solid #4458a3}table.thead-border thead .row-odd th{color:#23263b}table.thead-border thead .row-even th{font-weight:400}table.thead-border thead th{border:1px solid #e0e0e0}table.thead-border thead tr:first-child th{border-top:none}table.thead-border thead tr:last-child th{border-bottom:none}table.thead-border thead tr th:first-child{border-left:none}table.thead-border thead tr th:last-child{border-right:none}.topics-grid{display:block;margin:0 auto 30px}.topics-grid__title{color:#23263b;font-size:24px;font-weight:700;line-height:32px;margin-bottom:6px}.topics-grid__text{color:#4458a3;font-size:18px;line-height:24px}.topics-grid--scrollable .hs{-ms-overflow-style:none;display:grid;grid-auto-flow:column;overflow-x:scroll;padding:20px 10px;scrollbar-width:none}.topics-grid--scrollable .hs::-webkit-scrollbar{display:none}.topics-grid--scrollable .hs .topic-box:last-child:after{content:"";width:20px}.topic-box{align-items:stretch;display:flex}.topic-box .card{background:#fff;border:1px solid transparent;border-radius:8px;box-shadow:0 4px 25px rgba(0,0,0,.15);display:flex;flex-direction:column;font-size:18px;margin:0 auto 30px;overflow:hidden;padding:20px;position:relative}.topic-box .card:hover{border:1px solid #4458a3;color:#23263b;font-weight:400}.topic-box__title{color:#23263b;font-size:16px;font-weight:700;line-height:24px;margin-bottom:0}.topic-box__title img{bottom:0;opacity:.3;position:absolute;right:0;top:0}.topic-box__body{color:#000;display:flex;flex-direction:column;flex-grow:1;max-width:80%}.topic-box__body .container{flex-grow:1;margin:0;padding:0}.topic-box__body .line-block,.topic-box__body p{font-size:16px;line-height:19px;margin-top:10px}.topic-box__anchor{color:#42c4e6;font-size:14px;font-weight:700;line-height:24px}.topic-box__icon{display:block;font-size:50px;margin-bottom:20px}.topic-box__icon i{filter:brightness(0);min-height:50px;width:100%}.topic-box__icon img{bottom:-12px;display:none;height:140px;margin:0;opacity:.3;position:absolute;right:-5px}.topic-box--product .card{box-shadow:none;padding:20px;text-align:center}.topic-box--product .card .topic-box__title{color:#23263b;font-size:14px}.topic-box--product .card .topic-box__body{display:flex;flex-direction:column;max-width:100%}.topic-box--product .card .topic-box__body .line-block,.topic-box--product .card .topic-box__body p{font-size:12px}.topic-box--product .card .topic-box__icon img{display:inline-block;max-height:84px;opacity:1;position:static}.topic-box--product .card:hover{background:#fff;border:0;border-radius:8px;box-shadow:0 4px 25px rgba(0,0,0,.15);overflow:hidden}@media screen and (max-width:1024px){.topics-grid--scrollable .topic-box{width:280px!important}.topic-box--product:nth-last-child(-n+2) .card{margin-bottom:0}}@media screen and (min-width:1024px){.topics-grid{margin-bottom:10px}.topics-grid__text{font-size:16px}.topics-grid--scrollable .hs{display:flex;overflow-x:initial;padding:0}.topics-grid--scrollable .hs .topic-box:last-child:after{display:none}.topic-box .card{margin-bottom:60px;padding:45px 30px}.topic-box__title{font-size:20px;line-height:32px}.topic-box__body .line-block,.topic-box__body p{font-size:18px;line-height:26px}.topic-box__anchor{font-size:20px;line-height:26px}.topic-box .topic-box__icon img{display:inline-block}.topic-box--product .card{padding:20px}.topic-box--product .card .topic-box__title{font-size:18px;line-height:24px}.topic-box--product .card .topic-box__body .line-block,.topic-box--product .card .topic-box__body p{font-size:14px}.topic-box--product .card .topic-box__icon img{max-height:111px}.landing .topics-grid--products{margin-bottom:40px}} \ No newline at end of file diff --git a/3.22.3-scylla/_static/doctools.js b/3.22.3-scylla/_static/doctools.js new file mode 100644 index 0000000000..8cbf1b161a --- /dev/null +++ b/3.22.3-scylla/_static/doctools.js @@ -0,0 +1,323 @@ +/* + * doctools.js + * ~~~~~~~~~~~ + * + * Sphinx JavaScript utilities for all documentation. + * + * :copyright: Copyright 2007-2021 by the Sphinx team, see AUTHORS. + * :license: BSD, see LICENSE for details. + * + */ + +/** + * select a different prefix for underscore + */ +$u = _.noConflict(); + +/** + * make the code below compatible with browsers without + * an installed firebug like debugger +if (!window.console || !console.firebug) { + var names = ["log", "debug", "info", "warn", "error", "assert", "dir", + "dirxml", "group", "groupEnd", "time", "timeEnd", "count", "trace", + "profile", "profileEnd"]; + window.console = {}; + for (var i = 0; i < names.length; ++i) + window.console[names[i]] = function() {}; +} + */ + +/** + * small helper function to urldecode strings + * + * See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/decodeURIComponent#Decoding_query_parameters_from_a_URL + */ +jQuery.urldecode = function(x) { + if (!x) { + return x + } + return decodeURIComponent(x.replace(/\+/g, ' ')); +}; + +/** + * small helper function to urlencode strings + */ +jQuery.urlencode = encodeURIComponent; + +/** + * This function returns the parsed url parameters of the + * current request. Multiple values per key are supported, + * it will always return arrays of strings for the value parts. + */ +jQuery.getQueryParameters = function(s) { + if (typeof s === 'undefined') + s = document.location.search; + var parts = s.substr(s.indexOf('?') + 1).split('&'); + var result = {}; + for (var i = 0; i < parts.length; i++) { + var tmp = parts[i].split('=', 2); + var key = jQuery.urldecode(tmp[0]); + var value = jQuery.urldecode(tmp[1]); + if (key in result) + result[key].push(value); + else + result[key] = [value]; + } + return result; +}; + +/** + * highlight a given string on a jquery object by wrapping it in + * span elements with the given class name. + */ +jQuery.fn.highlightText = function(text, className) { + function highlight(node, addItems) { + if (node.nodeType === 3) { + var val = node.nodeValue; + var pos = val.toLowerCase().indexOf(text); + if (pos >= 0 && + !jQuery(node.parentNode).hasClass(className) && + !jQuery(node.parentNode).hasClass("nohighlight")) { + var span; + var isInSVG = jQuery(node).closest("body, svg, foreignObject").is("svg"); + if (isInSVG) { + span = document.createElementNS("http://www.w3.org/2000/svg", "tspan"); + } else { + span = document.createElement("span"); + span.className = className; + } + span.appendChild(document.createTextNode(val.substr(pos, text.length))); + node.parentNode.insertBefore(span, node.parentNode.insertBefore( + document.createTextNode(val.substr(pos + text.length)), + node.nextSibling)); + node.nodeValue = val.substr(0, pos); + if (isInSVG) { + var rect = document.createElementNS("http://www.w3.org/2000/svg", "rect"); + var bbox = node.parentElement.getBBox(); + rect.x.baseVal.value = bbox.x; + rect.y.baseVal.value = bbox.y; + rect.width.baseVal.value = bbox.width; + rect.height.baseVal.value = bbox.height; + rect.setAttribute('class', className); + addItems.push({ + "parent": node.parentNode, + "target": rect}); + } + } + } + else if (!jQuery(node).is("button, select, textarea")) { + jQuery.each(node.childNodes, function() { + highlight(this, addItems); + }); + } + } + var addItems = []; + var result = this.each(function() { + highlight(this, addItems); + }); + for (var i = 0; i < addItems.length; ++i) { + jQuery(addItems[i].parent).before(addItems[i].target); + } + return result; +}; + +/* + * backward compatibility for jQuery.browser + * This will be supported until firefox bug is fixed. + */ +if (!jQuery.browser) { + jQuery.uaMatch = function(ua) { + ua = ua.toLowerCase(); + + var match = /(chrome)[ \/]([\w.]+)/.exec(ua) || + /(webkit)[ \/]([\w.]+)/.exec(ua) || + /(opera)(?:.*version|)[ \/]([\w.]+)/.exec(ua) || + /(msie) ([\w.]+)/.exec(ua) || + ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec(ua) || + []; + + return { + browser: match[ 1 ] || "", + version: match[ 2 ] || "0" + }; + }; + jQuery.browser = {}; + jQuery.browser[jQuery.uaMatch(navigator.userAgent).browser] = true; +} + +/** + * Small JavaScript module for the documentation. + */ +var Documentation = { + + init : function() { + this.fixFirefoxAnchorBug(); + this.highlightSearchWords(); + this.initIndexTable(); + if (DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS) { + this.initOnKeyListeners(); + } + }, + + /** + * i18n support + */ + TRANSLATIONS : {}, + PLURAL_EXPR : function(n) { return n === 1 ? 0 : 1; }, + LOCALE : 'unknown', + + // gettext and ngettext don't access this so that the functions + // can safely bound to a different name (_ = Documentation.gettext) + gettext : function(string) { + var translated = Documentation.TRANSLATIONS[string]; + if (typeof translated === 'undefined') + return string; + return (typeof translated === 'string') ? translated : translated[0]; + }, + + ngettext : function(singular, plural, n) { + var translated = Documentation.TRANSLATIONS[singular]; + if (typeof translated === 'undefined') + return (n == 1) ? singular : plural; + return translated[Documentation.PLURALEXPR(n)]; + }, + + addTranslations : function(catalog) { + for (var key in catalog.messages) + this.TRANSLATIONS[key] = catalog.messages[key]; + this.PLURAL_EXPR = new Function('n', 'return +(' + catalog.plural_expr + ')'); + this.LOCALE = catalog.locale; + }, + + /** + * add context elements like header anchor links + */ + addContextElements : function() { + $('div[id] > :header:first').each(function() { + $('\u00B6'). + attr('href', '#' + this.id). + attr('title', _('Permalink to this headline')). + appendTo(this); + }); + $('dt[id]').each(function() { + $('\u00B6'). + attr('href', '#' + this.id). + attr('title', _('Permalink to this definition')). + appendTo(this); + }); + }, + + /** + * workaround a firefox stupidity + * see: https://bugzilla.mozilla.org/show_bug.cgi?id=645075 + */ + fixFirefoxAnchorBug : function() { + if (document.location.hash && $.browser.mozilla) + window.setTimeout(function() { + document.location.href += ''; + }, 10); + }, + + /** + * highlight the search words provided in the url in the text + */ + highlightSearchWords : function() { + var params = $.getQueryParameters(); + var terms = (params.highlight) ? params.highlight[0].split(/\s+/) : []; + if (terms.length) { + var body = $('div.body'); + if (!body.length) { + body = $('body'); + } + window.setTimeout(function() { + $.each(terms, function() { + body.highlightText(this.toLowerCase(), 'highlighted'); + }); + }, 10); + $('') + .appendTo($('#searchbox')); + } + }, + + /** + * init the domain index toggle buttons + */ + initIndexTable : function() { + var togglers = $('img.toggler').click(function() { + var src = $(this).attr('src'); + var idnum = $(this).attr('id').substr(7); + $('tr.cg-' + idnum).toggle(); + if (src.substr(-9) === 'minus.png') + $(this).attr('src', src.substr(0, src.length-9) + 'plus.png'); + else + $(this).attr('src', src.substr(0, src.length-8) + 'minus.png'); + }).css('display', ''); + if (DOCUMENTATION_OPTIONS.COLLAPSE_INDEX) { + togglers.click(); + } + }, + + /** + * helper function to hide the search marks again + */ + hideSearchWords : function() { + $('#searchbox .highlight-link').fadeOut(300); + $('span.highlighted').removeClass('highlighted'); + }, + + /** + * make the url absolute + */ + makeURL : function(relativeURL) { + return DOCUMENTATION_OPTIONS.URL_ROOT + '/' + relativeURL; + }, + + /** + * get the current relative url + */ + getCurrentURL : function() { + var path = document.location.pathname; + var parts = path.split(/\//); + $.each(DOCUMENTATION_OPTIONS.URL_ROOT.split(/\//), function() { + if (this === '..') + parts.pop(); + }); + var url = parts.join('/'); + return path.substring(url.lastIndexOf('/') + 1, path.length - 1); + }, + + initOnKeyListeners: function() { + $(document).keydown(function(event) { + var activeElementType = document.activeElement.tagName; + // don't navigate when in search box, textarea, dropdown or button + if (activeElementType !== 'TEXTAREA' && activeElementType !== 'INPUT' && activeElementType !== 'SELECT' + && activeElementType !== 'BUTTON' && !event.altKey && !event.ctrlKey && !event.metaKey + && !event.shiftKey) { + switch (event.keyCode) { + case 37: // left + var prevHref = $('link[rel="prev"]').prop('href'); + if (prevHref) { + window.location.href = prevHref; + return false; + } + break; + case 39: // right + var nextHref = $('link[rel="next"]').prop('href'); + if (nextHref) { + window.location.href = nextHref; + return false; + } + break; + } + } + }); + } +}; + +// quick alias for translations +_ = Documentation.gettext; + +$(document).ready(function() { + Documentation.init(); +}); diff --git a/3.22.3-scylla/_static/documentation_options.js b/3.22.3-scylla/_static/documentation_options.js new file mode 100644 index 0000000000..5e0840c1ce --- /dev/null +++ b/3.22.3-scylla/_static/documentation_options.js @@ -0,0 +1,12 @@ +var DOCUMENTATION_OPTIONS = { + URL_ROOT: document.getElementById("documentation_options").getAttribute('data-url_root'), + VERSION: '3.22.3', + LANGUAGE: 'None', + COLLAPSE_INDEX: false, + BUILDER: 'html', + FILE_SUFFIX: '.html', + LINK_SUFFIX: '.html', + HAS_SOURCE: true, + SOURCELINK_SUFFIX: '.txt', + NAVIGATION_WITH_KEYS: false +}; \ No newline at end of file diff --git a/3.22.3-scylla/_static/file.png b/3.22.3-scylla/_static/file.png new file mode 100644 index 0000000000..a858a410e4 Binary files /dev/null and b/3.22.3-scylla/_static/file.png differ diff --git a/3.22.3-scylla/_static/img/banner-background.svg b/3.22.3-scylla/_static/img/banner-background.svg new file mode 100644 index 0000000000..f8520d5b3e --- /dev/null +++ b/3.22.3-scylla/_static/img/banner-background.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/3.22.3-scylla/_static/img/favicon-228x228.png b/3.22.3-scylla/_static/img/favicon-228x228.png new file mode 100644 index 0000000000..f30770c7ed Binary files /dev/null and b/3.22.3-scylla/_static/img/favicon-228x228.png differ diff --git a/3.22.3-scylla/_static/img/favicon-32x32.png b/3.22.3-scylla/_static/img/favicon-32x32.png new file mode 100644 index 0000000000..aae1708f26 Binary files /dev/null and b/3.22.3-scylla/_static/img/favicon-32x32.png differ diff --git a/3.22.3-scylla/_static/img/favicon.ico b/3.22.3-scylla/_static/img/favicon.ico new file mode 100644 index 0000000000..6c7484f082 Binary files /dev/null and b/3.22.3-scylla/_static/img/favicon.ico differ diff --git a/3.22.3-scylla/_static/img/icons/icon-about-team.svg b/3.22.3-scylla/_static/img/icons/icon-about-team.svg new file mode 100644 index 0000000000..5448c7f007 --- /dev/null +++ b/3.22.3-scylla/_static/img/icons/icon-about-team.svg @@ -0,0 +1 @@ +icon-about-team diff --git a/3.22.3-scylla/_static/img/icons/icon-about-us-m.svg b/3.22.3-scylla/_static/img/icons/icon-about-us-m.svg new file mode 100644 index 0000000000..09107d9520 --- /dev/null +++ b/3.22.3-scylla/_static/img/icons/icon-about-us-m.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/3.22.3-scylla/_static/img/icons/icon-about-us.svg b/3.22.3-scylla/_static/img/icons/icon-about-us.svg new file mode 100644 index 0000000000..1b1fcc83e3 --- /dev/null +++ b/3.22.3-scylla/_static/img/icons/icon-about-us.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/3.22.3-scylla/_static/img/icons/icon-alternator.svg b/3.22.3-scylla/_static/img/icons/icon-alternator.svg new file mode 100644 index 0000000000..7c2b4ebae0 --- /dev/null +++ b/3.22.3-scylla/_static/img/icons/icon-alternator.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/3.22.3-scylla/_static/img/icons/icon-apps.svg b/3.22.3-scylla/_static/img/icons/icon-apps.svg new file mode 100644 index 0000000000..7e93612026 --- /dev/null +++ b/3.22.3-scylla/_static/img/icons/icon-apps.svg @@ -0,0 +1 @@ + diff --git a/3.22.3-scylla/_static/img/icons/icon-architecture.svg b/3.22.3-scylla/_static/img/icons/icon-architecture.svg new file mode 100644 index 0000000000..67ebbc2f38 --- /dev/null +++ b/3.22.3-scylla/_static/img/icons/icon-architecture.svg @@ -0,0 +1 @@ +icon-architecture diff --git a/3.22.3-scylla/_static/img/icons/icon-benchmarks.svg b/3.22.3-scylla/_static/img/icons/icon-benchmarks.svg new file mode 100644 index 0000000000..e1ce2c1d78 --- /dev/null +++ b/3.22.3-scylla/_static/img/icons/icon-benchmarks.svg @@ -0,0 +1 @@ +icon-benchmarks diff --git a/3.22.3-scylla/_static/img/icons/icon-blog.svg b/3.22.3-scylla/_static/img/icons/icon-blog.svg new file mode 100644 index 0000000000..f4096cbf11 --- /dev/null +++ b/3.22.3-scylla/_static/img/icons/icon-blog.svg @@ -0,0 +1 @@ +icon-blog2 diff --git a/3.22.3-scylla/_static/img/icons/icon-careers.svg b/3.22.3-scylla/_static/img/icons/icon-careers.svg new file mode 100644 index 0000000000..2a7c6ea0b7 --- /dev/null +++ b/3.22.3-scylla/_static/img/icons/icon-careers.svg @@ -0,0 +1 @@ +icon-careers diff --git a/3.22.3-scylla/_static/img/icons/icon-chevron-left.svg b/3.22.3-scylla/_static/img/icons/icon-chevron-left.svg new file mode 100644 index 0000000000..3afa25c481 --- /dev/null +++ b/3.22.3-scylla/_static/img/icons/icon-chevron-left.svg @@ -0,0 +1,3 @@ + + + diff --git a/3.22.3-scylla/_static/img/icons/icon-chevron-right.svg b/3.22.3-scylla/_static/img/icons/icon-chevron-right.svg new file mode 100644 index 0000000000..44eb829cdc --- /dev/null +++ b/3.22.3-scylla/_static/img/icons/icon-chevron-right.svg @@ -0,0 +1,3 @@ + + + diff --git a/3.22.3-scylla/_static/img/icons/icon-circe.svg b/3.22.3-scylla/_static/img/icons/icon-circe.svg new file mode 100644 index 0000000000..875e421670 --- /dev/null +++ b/3.22.3-scylla/_static/img/icons/icon-circe.svg @@ -0,0 +1 @@ + diff --git a/3.22.3-scylla/_static/img/icons/icon-clock.svg b/3.22.3-scylla/_static/img/icons/icon-clock.svg new file mode 100644 index 0000000000..8c92469808 --- /dev/null +++ b/3.22.3-scylla/_static/img/icons/icon-clock.svg @@ -0,0 +1 @@ + diff --git a/3.22.3-scylla/_static/img/icons/icon-close.svg b/3.22.3-scylla/_static/img/icons/icon-close.svg new file mode 100644 index 0000000000..d1162b73e7 --- /dev/null +++ b/3.22.3-scylla/_static/img/icons/icon-close.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/3.22.3-scylla/_static/img/icons/icon-cloud-docs.svg b/3.22.3-scylla/_static/img/icons/icon-cloud-docs.svg new file mode 100644 index 0000000000..a9069bb6e5 --- /dev/null +++ b/3.22.3-scylla/_static/img/icons/icon-cloud-docs.svg @@ -0,0 +1 @@ + diff --git a/3.22.3-scylla/_static/img/icons/icon-cloud.svg b/3.22.3-scylla/_static/img/icons/icon-cloud.svg new file mode 100644 index 0000000000..cfb2318dae --- /dev/null +++ b/3.22.3-scylla/_static/img/icons/icon-cloud.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/3.22.3-scylla/_static/img/icons/icon-comparison.svg b/3.22.3-scylla/_static/img/icons/icon-comparison.svg new file mode 100644 index 0000000000..49d809a5df --- /dev/null +++ b/3.22.3-scylla/_static/img/icons/icon-comparison.svg @@ -0,0 +1 @@ +icon-comparison diff --git a/3.22.3-scylla/_static/img/icons/icon-contact-us.svg b/3.22.3-scylla/_static/img/icons/icon-contact-us.svg new file mode 100644 index 0000000000..9df3145dd2 --- /dev/null +++ b/3.22.3-scylla/_static/img/icons/icon-contact-us.svg @@ -0,0 +1 @@ +icon-contact-us diff --git a/3.22.3-scylla/_static/img/icons/icon-developers-blog.svg b/3.22.3-scylla/_static/img/icons/icon-developers-blog.svg new file mode 100644 index 0000000000..ee804197a0 --- /dev/null +++ b/3.22.3-scylla/_static/img/icons/icon-developers-blog.svg @@ -0,0 +1 @@ +icon-developers-blog diff --git a/3.22.3-scylla/_static/img/icons/icon-docs.svg b/3.22.3-scylla/_static/img/icons/icon-docs.svg new file mode 100644 index 0000000000..5501492f3e --- /dev/null +++ b/3.22.3-scylla/_static/img/icons/icon-docs.svg @@ -0,0 +1 @@ +icon-docs diff --git a/3.22.3-scylla/_static/img/icons/icon-enterprise-m.svg b/3.22.3-scylla/_static/img/icons/icon-enterprise-m.svg new file mode 100644 index 0000000000..97be900b50 --- /dev/null +++ b/3.22.3-scylla/_static/img/icons/icon-enterprise-m.svg @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/3.22.3-scylla/_static/img/icons/icon-enterprise.svg b/3.22.3-scylla/_static/img/icons/icon-enterprise.svg new file mode 100644 index 0000000000..ee1ac26283 --- /dev/null +++ b/3.22.3-scylla/_static/img/icons/icon-enterprise.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/3.22.3-scylla/_static/img/icons/icon-events.svg b/3.22.3-scylla/_static/img/icons/icon-events.svg new file mode 100644 index 0000000000..ba5f211864 --- /dev/null +++ b/3.22.3-scylla/_static/img/icons/icon-events.svg @@ -0,0 +1 @@ +icon-events diff --git a/3.22.3-scylla/_static/img/icons/icon-exclamation.svg b/3.22.3-scylla/_static/img/icons/icon-exclamation.svg new file mode 100644 index 0000000000..a7eb4b77a4 --- /dev/null +++ b/3.22.3-scylla/_static/img/icons/icon-exclamation.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/3.22.3-scylla/_static/img/icons/icon-expand.svg b/3.22.3-scylla/_static/img/icons/icon-expand.svg new file mode 100644 index 0000000000..3806565367 --- /dev/null +++ b/3.22.3-scylla/_static/img/icons/icon-expand.svg @@ -0,0 +1,50 @@ + + + + + + + + + diff --git a/3.22.3-scylla/_static/img/icons/icon-forum.svg b/3.22.3-scylla/_static/img/icons/icon-forum.svg new file mode 100644 index 0000000000..37a709f7a8 --- /dev/null +++ b/3.22.3-scylla/_static/img/icons/icon-forum.svg @@ -0,0 +1 @@ + diff --git a/3.22.3-scylla/_static/img/icons/icon-getting-started.svg b/3.22.3-scylla/_static/img/icons/icon-getting-started.svg new file mode 100644 index 0000000000..702500be40 --- /dev/null +++ b/3.22.3-scylla/_static/img/icons/icon-getting-started.svg @@ -0,0 +1 @@ + diff --git a/3.22.3-scylla/_static/img/icons/icon-glossary.svg b/3.22.3-scylla/_static/img/icons/icon-glossary.svg new file mode 100644 index 0000000000..e8329c2afe --- /dev/null +++ b/3.22.3-scylla/_static/img/icons/icon-glossary.svg @@ -0,0 +1 @@ + diff --git a/3.22.3-scylla/_static/img/icons/icon-home.svg b/3.22.3-scylla/_static/img/icons/icon-home.svg new file mode 100644 index 0000000000..f0b9c25419 --- /dev/null +++ b/3.22.3-scylla/_static/img/icons/icon-home.svg @@ -0,0 +1 @@ + diff --git a/3.22.3-scylla/_static/img/icons/icon-infoworld.svg b/3.22.3-scylla/_static/img/icons/icon-infoworld.svg new file mode 100644 index 0000000000..906e87279c --- /dev/null +++ b/3.22.3-scylla/_static/img/icons/icon-infoworld.svg @@ -0,0 +1 @@ +icon-infoworld diff --git a/3.22.3-scylla/_static/img/icons/icon-integrations.svg b/3.22.3-scylla/_static/img/icons/icon-integrations.svg new file mode 100644 index 0000000000..1ef0920d49 --- /dev/null +++ b/3.22.3-scylla/_static/img/icons/icon-integrations.svg @@ -0,0 +1 @@ + diff --git a/3.22.3-scylla/_static/img/icons/icon-knowledge-base.svg b/3.22.3-scylla/_static/img/icons/icon-knowledge-base.svg new file mode 100644 index 0000000000..884451270d --- /dev/null +++ b/3.22.3-scylla/_static/img/icons/icon-knowledge-base.svg @@ -0,0 +1 @@ + diff --git a/3.22.3-scylla/_static/img/icons/icon-less.svg b/3.22.3-scylla/_static/img/icons/icon-less.svg new file mode 100644 index 0000000000..3094127dec --- /dev/null +++ b/3.22.3-scylla/_static/img/icons/icon-less.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/3.22.3-scylla/_static/img/icons/icon-live-test.svg b/3.22.3-scylla/_static/img/icons/icon-live-test.svg new file mode 100644 index 0000000000..dcb5916c26 --- /dev/null +++ b/3.22.3-scylla/_static/img/icons/icon-live-test.svg @@ -0,0 +1 @@ +icon-live-test diff --git a/3.22.3-scylla/_static/img/icons/icon-mail-list.svg b/3.22.3-scylla/_static/img/icons/icon-mail-list.svg new file mode 100644 index 0000000000..0e6192a352 --- /dev/null +++ b/3.22.3-scylla/_static/img/icons/icon-mail-list.svg @@ -0,0 +1 @@ + diff --git a/3.22.3-scylla/_static/img/icons/icon-manager.svg b/3.22.3-scylla/_static/img/icons/icon-manager.svg new file mode 100644 index 0000000000..02b4e425be --- /dev/null +++ b/3.22.3-scylla/_static/img/icons/icon-manager.svg @@ -0,0 +1 @@ +icon-manager diff --git a/3.22.3-scylla/_static/img/icons/icon-memory-management.svg b/3.22.3-scylla/_static/img/icons/icon-memory-management.svg new file mode 100644 index 0000000000..e34eb4504f --- /dev/null +++ b/3.22.3-scylla/_static/img/icons/icon-memory-management.svg @@ -0,0 +1 @@ +icon-memory-management diff --git a/3.22.3-scylla/_static/img/icons/icon-modeling.svg b/3.22.3-scylla/_static/img/icons/icon-modeling.svg new file mode 100644 index 0000000000..97fa3a0e21 --- /dev/null +++ b/3.22.3-scylla/_static/img/icons/icon-modeling.svg @@ -0,0 +1 @@ + diff --git a/3.22.3-scylla/_static/img/icons/icon-monitoring.svg b/3.22.3-scylla/_static/img/icons/icon-monitoring.svg new file mode 100644 index 0000000000..80b3787f66 --- /dev/null +++ b/3.22.3-scylla/_static/img/icons/icon-monitoring.svg @@ -0,0 +1 @@ +icon-monitoring diff --git a/3.22.3-scylla/_static/img/icons/icon-networking.svg b/3.22.3-scylla/_static/img/icons/icon-networking.svg new file mode 100644 index 0000000000..40a3fd5f6f --- /dev/null +++ b/3.22.3-scylla/_static/img/icons/icon-networking.svg @@ -0,0 +1 @@ +icon-networking diff --git a/3.22.3-scylla/_static/img/icons/icon-news.svg b/3.22.3-scylla/_static/img/icons/icon-news.svg new file mode 100644 index 0000000000..a952b59937 --- /dev/null +++ b/3.22.3-scylla/_static/img/icons/icon-news.svg @@ -0,0 +1 @@ +icon-news diff --git a/3.22.3-scylla/_static/img/icons/icon-newsletter.svg b/3.22.3-scylla/_static/img/icons/icon-newsletter.svg new file mode 100644 index 0000000000..5b8d47eb15 --- /dev/null +++ b/3.22.3-scylla/_static/img/icons/icon-newsletter.svg @@ -0,0 +1 @@ +icon-newsletter diff --git a/3.22.3-scylla/_static/img/icons/icon-nsql-guides.svg b/3.22.3-scylla/_static/img/icons/icon-nsql-guides.svg new file mode 100644 index 0000000000..60ebab3795 --- /dev/null +++ b/3.22.3-scylla/_static/img/icons/icon-nsql-guides.svg @@ -0,0 +1 @@ +icon-nsql-guides diff --git a/3.22.3-scylla/_static/img/icons/icon-open-source.svg b/3.22.3-scylla/_static/img/icons/icon-open-source.svg new file mode 100644 index 0000000000..98c2ea7d5b --- /dev/null +++ b/3.22.3-scylla/_static/img/icons/icon-open-source.svg @@ -0,0 +1 @@ +icon-open-source diff --git a/3.22.3-scylla/_static/img/icons/icon-operator.svg b/3.22.3-scylla/_static/img/icons/icon-operator.svg new file mode 100644 index 0000000000..bb7d8d3ea8 --- /dev/null +++ b/3.22.3-scylla/_static/img/icons/icon-operator.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/3.22.3-scylla/_static/img/icons/icon-overview.svg b/3.22.3-scylla/_static/img/icons/icon-overview.svg new file mode 100644 index 0000000000..515c1528a2 --- /dev/null +++ b/3.22.3-scylla/_static/img/icons/icon-overview.svg @@ -0,0 +1 @@ +icon-overview diff --git a/3.22.3-scylla/_static/img/icons/icon-partners.svg b/3.22.3-scylla/_static/img/icons/icon-partners.svg new file mode 100644 index 0000000000..d0146fc497 --- /dev/null +++ b/3.22.3-scylla/_static/img/icons/icon-partners.svg @@ -0,0 +1 @@ +icon-partners diff --git a/3.22.3-scylla/_static/img/icons/icon-plus.svg b/3.22.3-scylla/_static/img/icons/icon-plus.svg new file mode 100644 index 0000000000..5757435085 --- /dev/null +++ b/3.22.3-scylla/_static/img/icons/icon-plus.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/3.22.3-scylla/_static/img/icons/icon-pricing.svg b/3.22.3-scylla/_static/img/icons/icon-pricing.svg new file mode 100644 index 0000000000..74b01db168 --- /dev/null +++ b/3.22.3-scylla/_static/img/icons/icon-pricing.svg @@ -0,0 +1 @@ +icon-pricing$ diff --git a/3.22.3-scylla/_static/img/icons/icon-release-notes.svg b/3.22.3-scylla/_static/img/icons/icon-release-notes.svg new file mode 100644 index 0000000000..80c490c7b0 --- /dev/null +++ b/3.22.3-scylla/_static/img/icons/icon-release-notes.svg @@ -0,0 +1 @@ +icon-release-notes diff --git a/3.22.3-scylla/_static/img/icons/icon-resource-center.svg b/3.22.3-scylla/_static/img/icons/icon-resource-center.svg new file mode 100644 index 0000000000..6e3ab08e79 --- /dev/null +++ b/3.22.3-scylla/_static/img/icons/icon-resource-center.svg @@ -0,0 +1 @@ +icon-ressource-center diff --git a/3.22.3-scylla/_static/img/icons/icon-roadmap.svg b/3.22.3-scylla/_static/img/icons/icon-roadmap.svg new file mode 100644 index 0000000000..c8cbf67c8c --- /dev/null +++ b/3.22.3-scylla/_static/img/icons/icon-roadmap.svg @@ -0,0 +1 @@ +icon-roadmap-4 diff --git a/3.22.3-scylla/_static/img/icons/icon-search.svg b/3.22.3-scylla/_static/img/icons/icon-search.svg new file mode 100644 index 0000000000..81aae93eef --- /dev/null +++ b/3.22.3-scylla/_static/img/icons/icon-search.svg @@ -0,0 +1,4 @@ + + + + diff --git a/3.22.3-scylla/_static/img/icons/icon-slack.svg b/3.22.3-scylla/_static/img/icons/icon-slack.svg new file mode 100644 index 0000000000..fc164ea1e7 --- /dev/null +++ b/3.22.3-scylla/_static/img/icons/icon-slack.svg @@ -0,0 +1 @@ + diff --git a/3.22.3-scylla/_static/img/icons/icon-stack-overflow.svg b/3.22.3-scylla/_static/img/icons/icon-stack-overflow.svg new file mode 100644 index 0000000000..bebe9b8274 --- /dev/null +++ b/3.22.3-scylla/_static/img/icons/icon-stack-overflow.svg @@ -0,0 +1,4 @@ + + + + diff --git a/3.22.3-scylla/_static/img/icons/icon-summit.svg b/3.22.3-scylla/_static/img/icons/icon-summit.svg new file mode 100644 index 0000000000..4b900bd0c0 --- /dev/null +++ b/3.22.3-scylla/_static/img/icons/icon-summit.svg @@ -0,0 +1 @@ + diff --git a/3.22.3-scylla/_static/img/icons/icon-support.svg b/3.22.3-scylla/_static/img/icons/icon-support.svg new file mode 100644 index 0000000000..a4228b34e8 --- /dev/null +++ b/3.22.3-scylla/_static/img/icons/icon-support.svg @@ -0,0 +1 @@ +icon-support diff --git a/3.22.3-scylla/_static/img/icons/icon-tech-talks.svg b/3.22.3-scylla/_static/img/icons/icon-tech-talks.svg new file mode 100644 index 0000000000..df42b5522b --- /dev/null +++ b/3.22.3-scylla/_static/img/icons/icon-tech-talks.svg @@ -0,0 +1 @@ +icon-tech-talks diff --git a/3.22.3-scylla/_static/img/icons/icon-testing.svg b/3.22.3-scylla/_static/img/icons/icon-testing.svg new file mode 100644 index 0000000000..2fe54efdbc --- /dev/null +++ b/3.22.3-scylla/_static/img/icons/icon-testing.svg @@ -0,0 +1 @@ +icon-testing diff --git a/3.22.3-scylla/_static/img/icons/icon-thumbs-down.svg b/3.22.3-scylla/_static/img/icons/icon-thumbs-down.svg new file mode 100644 index 0000000000..3e7bcd6d90 --- /dev/null +++ b/3.22.3-scylla/_static/img/icons/icon-thumbs-down.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/3.22.3-scylla/_static/img/icons/icon-thumbs-up.svg b/3.22.3-scylla/_static/img/icons/icon-thumbs-up.svg new file mode 100644 index 0000000000..226c44d853 --- /dev/null +++ b/3.22.3-scylla/_static/img/icons/icon-thumbs-up.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/3.22.3-scylla/_static/img/icons/icon-tip.svg b/3.22.3-scylla/_static/img/icons/icon-tip.svg new file mode 100644 index 0000000000..bf7aa6af84 --- /dev/null +++ b/3.22.3-scylla/_static/img/icons/icon-tip.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/3.22.3-scylla/_static/img/icons/icon-training.svg b/3.22.3-scylla/_static/img/icons/icon-training.svg new file mode 100644 index 0000000000..08b95a88ed --- /dev/null +++ b/3.22.3-scylla/_static/img/icons/icon-training.svg @@ -0,0 +1 @@ +icon-training diff --git a/3.22.3-scylla/_static/img/icons/icon-triangle-down.svg b/3.22.3-scylla/_static/img/icons/icon-triangle-down.svg new file mode 100644 index 0000000000..e8ae088106 --- /dev/null +++ b/3.22.3-scylla/_static/img/icons/icon-triangle-down.svg @@ -0,0 +1,3 @@ + + + diff --git a/3.22.3-scylla/_static/img/icons/icon-university.svg b/3.22.3-scylla/_static/img/icons/icon-university.svg new file mode 100644 index 0000000000..f7547ab959 --- /dev/null +++ b/3.22.3-scylla/_static/img/icons/icon-university.svg @@ -0,0 +1 @@ +icon-university diff --git a/3.22.3-scylla/_static/img/icons/icon-users-blog.svg b/3.22.3-scylla/_static/img/icons/icon-users-blog.svg new file mode 100644 index 0000000000..47e56cddcf --- /dev/null +++ b/3.22.3-scylla/_static/img/icons/icon-users-blog.svg @@ -0,0 +1 @@ +icon-users-blog diff --git a/3.22.3-scylla/_static/img/icons/icon-warning.svg b/3.22.3-scylla/_static/img/icons/icon-warning.svg new file mode 100644 index 0000000000..e4b1d40331 --- /dev/null +++ b/3.22.3-scylla/_static/img/icons/icon-warning.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/3.22.3-scylla/_static/img/icons/icon-webinars.svg b/3.22.3-scylla/_static/img/icons/icon-webinars.svg new file mode 100644 index 0000000000..5e9f5cd427 --- /dev/null +++ b/3.22.3-scylla/_static/img/icons/icon-webinars.svg @@ -0,0 +1 @@ +icon-webinars diff --git a/3.22.3-scylla/_static/img/icons/icon-whitepapers.svg b/3.22.3-scylla/_static/img/icons/icon-whitepapers.svg new file mode 100644 index 0000000000..3351e51d23 --- /dev/null +++ b/3.22.3-scylla/_static/img/icons/icon-whitepapers.svg @@ -0,0 +1 @@ +icon-whitepapers diff --git a/3.22.3-scylla/_static/img/icons/icon-workshop.svg b/3.22.3-scylla/_static/img/icons/icon-workshop.svg new file mode 100644 index 0000000000..5206e58e98 --- /dev/null +++ b/3.22.3-scylla/_static/img/icons/icon-workshop.svg @@ -0,0 +1 @@ + diff --git a/3.22.3-scylla/_static/img/logo-docs.svg b/3.22.3-scylla/_static/img/logo-docs.svg new file mode 100644 index 0000000000..4fff669cb6 --- /dev/null +++ b/3.22.3-scylla/_static/img/logo-docs.svg @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/3.22.3-scylla/_static/img/logo-scylla-horizontal-RGB.svg b/3.22.3-scylla/_static/img/logo-scylla-horizontal-RGB.svg new file mode 100644 index 0000000000..b5022d7c4d --- /dev/null +++ b/3.22.3-scylla/_static/img/logo-scylla-horizontal-RGB.svg @@ -0,0 +1,74 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/3.22.3-scylla/_static/img/mascots/404.jpg b/3.22.3-scylla/_static/img/mascots/404.jpg new file mode 100644 index 0000000000..769fa0889f Binary files /dev/null and b/3.22.3-scylla/_static/img/mascots/404.jpg differ diff --git a/3.22.3-scylla/_static/img/mascots/scylla-3monsters.png b/3.22.3-scylla/_static/img/mascots/scylla-3monsters.png new file mode 100644 index 0000000000..7c06d01674 Binary files /dev/null and b/3.22.3-scylla/_static/img/mascots/scylla-3monsters.png differ diff --git a/3.22.3-scylla/_static/img/mascots/scylla-advisor-crystal.png b/3.22.3-scylla/_static/img/mascots/scylla-advisor-crystal.png new file mode 100644 index 0000000000..d33fddd62f Binary files /dev/null and b/3.22.3-scylla/_static/img/mascots/scylla-advisor-crystal.png differ diff --git a/3.22.3-scylla/_static/img/mascots/scylla-alternator.svg b/3.22.3-scylla/_static/img/mascots/scylla-alternator.svg new file mode 100644 index 0000000000..0462f893d5 --- /dev/null +++ b/3.22.3-scylla/_static/img/mascots/scylla-alternator.svg @@ -0,0 +1 @@ +scylla-alternator diff --git a/3.22.3-scylla/_static/img/mascots/scylla-cloud.svg b/3.22.3-scylla/_static/img/mascots/scylla-cloud.svg new file mode 100644 index 0000000000..a6c6a26fc9 --- /dev/null +++ b/3.22.3-scylla/_static/img/mascots/scylla-cloud.svg @@ -0,0 +1 @@ +scylla-cloud diff --git a/3.22.3-scylla/_static/img/mascots/scylla-computer-3-monsters.png b/3.22.3-scylla/_static/img/mascots/scylla-computer-3-monsters.png new file mode 100644 index 0000000000..d0368a7027 Binary files /dev/null and b/3.22.3-scylla/_static/img/mascots/scylla-computer-3-monsters.png differ diff --git a/3.22.3-scylla/_static/img/mascots/scylla-computer-headset.png b/3.22.3-scylla/_static/img/mascots/scylla-computer-headset.png new file mode 100644 index 0000000000..0cdadaa216 Binary files /dev/null and b/3.22.3-scylla/_static/img/mascots/scylla-computer-headset.png differ diff --git a/3.22.3-scylla/_static/img/mascots/scylla-cup-number-one.png b/3.22.3-scylla/_static/img/mascots/scylla-cup-number-one.png new file mode 100644 index 0000000000..e889f4e368 Binary files /dev/null and b/3.22.3-scylla/_static/img/mascots/scylla-cup-number-one.png differ diff --git a/3.22.3-scylla/_static/img/mascots/scylla-docs.svg b/3.22.3-scylla/_static/img/mascots/scylla-docs.svg new file mode 100644 index 0000000000..a5bce950c2 --- /dev/null +++ b/3.22.3-scylla/_static/img/mascots/scylla-docs.svg @@ -0,0 +1 @@ +scylla-docs diff --git a/3.22.3-scylla/_static/img/mascots/scylla-drivers.svg b/3.22.3-scylla/_static/img/mascots/scylla-drivers.svg new file mode 100644 index 0000000000..6012e71679 --- /dev/null +++ b/3.22.3-scylla/_static/img/mascots/scylla-drivers.svg @@ -0,0 +1 @@ +scylla-manager diff --git a/3.22.3-scylla/_static/img/mascots/scylla-enterprise.svg b/3.22.3-scylla/_static/img/mascots/scylla-enterprise.svg new file mode 100644 index 0000000000..a1aa0b46ac --- /dev/null +++ b/3.22.3-scylla/_static/img/mascots/scylla-enterprise.svg @@ -0,0 +1 @@ +scylla-enterprise diff --git a/3.22.3-scylla/_static/img/mascots/scylla-forklift-boxes.png b/3.22.3-scylla/_static/img/mascots/scylla-forklift-boxes.png new file mode 100644 index 0000000000..f64c29e6c7 Binary files /dev/null and b/3.22.3-scylla/_static/img/mascots/scylla-forklift-boxes.png differ diff --git a/3.22.3-scylla/_static/img/mascots/scylla-forklift-migration.png b/3.22.3-scylla/_static/img/mascots/scylla-forklift-migration.png new file mode 100644 index 0000000000..d2f645c645 Binary files /dev/null and b/3.22.3-scylla/_static/img/mascots/scylla-forklift-migration.png differ diff --git a/3.22.3-scylla/_static/img/mascots/scylla-gear.png b/3.22.3-scylla/_static/img/mascots/scylla-gear.png new file mode 100644 index 0000000000..0f53b26afa Binary files /dev/null and b/3.22.3-scylla/_static/img/mascots/scylla-gear.png differ diff --git a/3.22.3-scylla/_static/img/mascots/scylla-hardhat.png b/3.22.3-scylla/_static/img/mascots/scylla-hardhat.png new file mode 100644 index 0000000000..630f2d9094 Binary files /dev/null and b/3.22.3-scylla/_static/img/mascots/scylla-hardhat.png differ diff --git a/3.22.3-scylla/_static/img/mascots/scylla-headband.png b/3.22.3-scylla/_static/img/mascots/scylla-headband.png new file mode 100644 index 0000000000..c87abe684d Binary files /dev/null and b/3.22.3-scylla/_static/img/mascots/scylla-headband.png differ diff --git a/3.22.3-scylla/_static/img/mascots/scylla-headset.png b/3.22.3-scylla/_static/img/mascots/scylla-headset.png new file mode 100644 index 0000000000..ba52cd223d Binary files /dev/null and b/3.22.3-scylla/_static/img/mascots/scylla-headset.png differ diff --git a/3.22.3-scylla/_static/img/mascots/scylla-hearts.png b/3.22.3-scylla/_static/img/mascots/scylla-hearts.png new file mode 100644 index 0000000000..cef08c8654 Binary files /dev/null and b/3.22.3-scylla/_static/img/mascots/scylla-hearts.png differ diff --git a/3.22.3-scylla/_static/img/mascots/scylla-looking-down.png b/3.22.3-scylla/_static/img/mascots/scylla-looking-down.png new file mode 100644 index 0000000000..75cccbfdf1 Binary files /dev/null and b/3.22.3-scylla/_static/img/mascots/scylla-looking-down.png differ diff --git a/3.22.3-scylla/_static/img/mascots/scylla-looking-up.png b/3.22.3-scylla/_static/img/mascots/scylla-looking-up.png new file mode 100644 index 0000000000..6f10405f21 Binary files /dev/null and b/3.22.3-scylla/_static/img/mascots/scylla-looking-up.png differ diff --git a/3.22.3-scylla/_static/img/mascots/scylla-magnifying-glass-fronting.png b/3.22.3-scylla/_static/img/mascots/scylla-magnifying-glass-fronting.png new file mode 100644 index 0000000000..e368cae169 Binary files /dev/null and b/3.22.3-scylla/_static/img/mascots/scylla-magnifying-glass-fronting.png differ diff --git a/3.22.3-scylla/_static/img/mascots/scylla-magnifying-glass.png b/3.22.3-scylla/_static/img/mascots/scylla-magnifying-glass.png new file mode 100644 index 0000000000..74ad669500 Binary files /dev/null and b/3.22.3-scylla/_static/img/mascots/scylla-magnifying-glass.png differ diff --git a/3.22.3-scylla/_static/img/mascots/scylla-manager.svg b/3.22.3-scylla/_static/img/mascots/scylla-manager.svg new file mode 100644 index 0000000000..6ba9ed937c --- /dev/null +++ b/3.22.3-scylla/_static/img/mascots/scylla-manager.svg @@ -0,0 +1 @@ +scylla-manager-2 diff --git a/3.22.3-scylla/_static/img/mascots/scylla-monitor.svg b/3.22.3-scylla/_static/img/mascots/scylla-monitor.svg new file mode 100644 index 0000000000..48bec7dde3 --- /dev/null +++ b/3.22.3-scylla/_static/img/mascots/scylla-monitor.svg @@ -0,0 +1 @@ +scylla-monitor diff --git a/3.22.3-scylla/_static/img/mascots/scylla-movement-fast.png b/3.22.3-scylla/_static/img/mascots/scylla-movement-fast.png new file mode 100644 index 0000000000..956d1dd0e2 Binary files /dev/null and b/3.22.3-scylla/_static/img/mascots/scylla-movement-fast.png differ diff --git a/3.22.3-scylla/_static/img/mascots/scylla-movement.png b/3.22.3-scylla/_static/img/mascots/scylla-movement.png new file mode 100644 index 0000000000..7ee2b04338 Binary files /dev/null and b/3.22.3-scylla/_static/img/mascots/scylla-movement.png differ diff --git a/3.22.3-scylla/_static/img/mascots/scylla-onpremise.png b/3.22.3-scylla/_static/img/mascots/scylla-onpremise.png new file mode 100644 index 0000000000..3b2dc8f1a2 Binary files /dev/null and b/3.22.3-scylla/_static/img/mascots/scylla-onpremise.png differ diff --git a/3.22.3-scylla/_static/img/mascots/scylla-opensource.svg b/3.22.3-scylla/_static/img/mascots/scylla-opensource.svg new file mode 100644 index 0000000000..299e9cb995 --- /dev/null +++ b/3.22.3-scylla/_static/img/mascots/scylla-opensource.svg @@ -0,0 +1 @@ +Plan de travail 1 diff --git a/3.22.3-scylla/_static/img/mascots/scylla-operator.svg b/3.22.3-scylla/_static/img/mascots/scylla-operator.svg new file mode 100644 index 0000000000..655a450b2a --- /dev/null +++ b/3.22.3-scylla/_static/img/mascots/scylla-operator.svg @@ -0,0 +1 @@ +scylla-operator diff --git a/3.22.3-scylla/_static/img/mascots/scylla-plugin.png b/3.22.3-scylla/_static/img/mascots/scylla-plugin.png new file mode 100644 index 0000000000..b28dc857cc Binary files /dev/null and b/3.22.3-scylla/_static/img/mascots/scylla-plugin.png differ diff --git a/3.22.3-scylla/_static/img/mascots/scylla-release-mascot.png b/3.22.3-scylla/_static/img/mascots/scylla-release-mascot.png new file mode 100644 index 0000000000..09342ac687 Binary files /dev/null and b/3.22.3-scylla/_static/img/mascots/scylla-release-mascot.png differ diff --git a/3.22.3-scylla/_static/img/mascots/scylla-repair.png b/3.22.3-scylla/_static/img/mascots/scylla-repair.png new file mode 100644 index 0000000000..9b4c613e70 Binary files /dev/null and b/3.22.3-scylla/_static/img/mascots/scylla-repair.png differ diff --git a/3.22.3-scylla/_static/img/mascots/scylla-server.png b/3.22.3-scylla/_static/img/mascots/scylla-server.png new file mode 100644 index 0000000000..96dc785298 Binary files /dev/null and b/3.22.3-scylla/_static/img/mascots/scylla-server.png differ diff --git a/3.22.3-scylla/_static/img/mascots/scylla-sleeping.png b/3.22.3-scylla/_static/img/mascots/scylla-sleeping.png new file mode 100644 index 0000000000..f88598e05a Binary files /dev/null and b/3.22.3-scylla/_static/img/mascots/scylla-sleeping.png differ diff --git a/3.22.3-scylla/_static/img/mascots/scylla-tall-measure.png b/3.22.3-scylla/_static/img/mascots/scylla-tall-measure.png new file mode 100644 index 0000000000..6f0ca146c0 Binary files /dev/null and b/3.22.3-scylla/_static/img/mascots/scylla-tall-measure.png differ diff --git a/3.22.3-scylla/_static/img/mascots/scylla-university.png b/3.22.3-scylla/_static/img/mascots/scylla-university.png new file mode 100644 index 0000000000..b3d0621193 Binary files /dev/null and b/3.22.3-scylla/_static/img/mascots/scylla-university.png differ diff --git a/3.22.3-scylla/_static/img/mascots/scylla-weights.png b/3.22.3-scylla/_static/img/mascots/scylla-weights.png new file mode 100644 index 0000000000..b070bb022c Binary files /dev/null and b/3.22.3-scylla/_static/img/mascots/scylla-weights.png differ diff --git a/3.22.3-scylla/_static/img/mascots/scylla-window-cleaning.png b/3.22.3-scylla/_static/img/mascots/scylla-window-cleaning.png new file mode 100644 index 0000000000..6a8b16a6b4 Binary files /dev/null and b/3.22.3-scylla/_static/img/mascots/scylla-window-cleaning.png differ diff --git a/3.22.3-scylla/_static/img/mascots/scylla-with-computer-2.png b/3.22.3-scylla/_static/img/mascots/scylla-with-computer-2.png new file mode 100644 index 0000000000..f3b8b2984f Binary files /dev/null and b/3.22.3-scylla/_static/img/mascots/scylla-with-computer-2.png differ diff --git a/3.22.3-scylla/_static/img/mascots/scylla-with-computer.png b/3.22.3-scylla/_static/img/mascots/scylla-with-computer.png new file mode 100644 index 0000000000..b38a6fbbe0 Binary files /dev/null and b/3.22.3-scylla/_static/img/mascots/scylla-with-computer.png differ diff --git a/3.22.3-scylla/_static/img/mascots/scylla-with-linux.png b/3.22.3-scylla/_static/img/mascots/scylla-with-linux.png new file mode 100644 index 0000000000..954bf13bc2 Binary files /dev/null and b/3.22.3-scylla/_static/img/mascots/scylla-with-linux.png differ diff --git a/3.22.3-scylla/_static/img/mascots/scylla-writting.png b/3.22.3-scylla/_static/img/mascots/scylla-writting.png new file mode 100644 index 0000000000..d35a13d380 Binary files /dev/null and b/3.22.3-scylla/_static/img/mascots/scylla-writting.png differ diff --git a/3.22.3-scylla/_static/img/menu.svg b/3.22.3-scylla/_static/img/menu.svg new file mode 100644 index 0000000000..30ea1d901e --- /dev/null +++ b/3.22.3-scylla/_static/img/menu.svg @@ -0,0 +1,3 @@ + + + diff --git a/3.22.3-scylla/_static/jquery-3.5.1.js b/3.22.3-scylla/_static/jquery-3.5.1.js new file mode 100644 index 0000000000..50937333b9 --- /dev/null +++ b/3.22.3-scylla/_static/jquery-3.5.1.js @@ -0,0 +1,10872 @@ +/*! + * jQuery JavaScript Library v3.5.1 + * https://jquery.com/ + * + * Includes Sizzle.js + * https://sizzlejs.com/ + * + * Copyright JS Foundation and other contributors + * Released under the MIT license + * https://jquery.org/license + * + * Date: 2020-05-04T22:49Z + */ +( function( global, factory ) { + + "use strict"; + + if ( typeof module === "object" && typeof module.exports === "object" ) { + + // For CommonJS and CommonJS-like environments where a proper `window` + // is present, execute the factory and get jQuery. + // For environments that do not have a `window` with a `document` + // (such as Node.js), expose a factory as module.exports. + // This accentuates the need for the creation of a real `window`. + // e.g. var jQuery = require("jquery")(window); + // See ticket #14549 for more info. + module.exports = global.document ? + factory( global, true ) : + function( w ) { + if ( !w.document ) { + throw new Error( "jQuery requires a window with a document" ); + } + return factory( w ); + }; + } else { + factory( global ); + } + +// Pass this if window is not defined yet +} )( typeof window !== "undefined" ? window : this, function( window, noGlobal ) { + +// Edge <= 12 - 13+, Firefox <=18 - 45+, IE 10 - 11, Safari 5.1 - 9+, iOS 6 - 9.1 +// throw exceptions when non-strict code (e.g., ASP.NET 4.5) accesses strict mode +// arguments.callee.caller (trac-13335). But as of jQuery 3.0 (2016), strict mode should be common +// enough that all such attempts are guarded in a try block. +"use strict"; + +var arr = []; + +var getProto = Object.getPrototypeOf; + +var slice = arr.slice; + +var flat = arr.flat ? function( array ) { + return arr.flat.call( array ); +} : function( array ) { + return arr.concat.apply( [], array ); +}; + + +var push = arr.push; + +var indexOf = arr.indexOf; + +var class2type = {}; + +var toString = class2type.toString; + +var hasOwn = class2type.hasOwnProperty; + +var fnToString = hasOwn.toString; + +var ObjectFunctionString = fnToString.call( Object ); + +var support = {}; + +var isFunction = function isFunction( obj ) { + + // Support: Chrome <=57, Firefox <=52 + // In some browsers, typeof returns "function" for HTML elements + // (i.e., `typeof document.createElement( "object" ) === "function"`). + // We don't want to classify *any* DOM node as a function. + return typeof obj === "function" && typeof obj.nodeType !== "number"; + }; + + +var isWindow = function isWindow( obj ) { + return obj != null && obj === obj.window; + }; + + +var document = window.document; + + + + var preservedScriptAttributes = { + type: true, + src: true, + nonce: true, + noModule: true + }; + + function DOMEval( code, node, doc ) { + doc = doc || document; + + var i, val, + script = doc.createElement( "script" ); + + script.text = code; + if ( node ) { + for ( i in preservedScriptAttributes ) { + + // Support: Firefox 64+, Edge 18+ + // Some browsers don't support the "nonce" property on scripts. + // On the other hand, just using `getAttribute` is not enough as + // the `nonce` attribute is reset to an empty string whenever it + // becomes browsing-context connected. + // See https://github.com/whatwg/html/issues/2369 + // See https://html.spec.whatwg.org/#nonce-attributes + // The `node.getAttribute` check was added for the sake of + // `jQuery.globalEval` so that it can fake a nonce-containing node + // via an object. + val = node[ i ] || node.getAttribute && node.getAttribute( i ); + if ( val ) { + script.setAttribute( i, val ); + } + } + } + doc.head.appendChild( script ).parentNode.removeChild( script ); + } + + +function toType( obj ) { + if ( obj == null ) { + return obj + ""; + } + + // Support: Android <=2.3 only (functionish RegExp) + return typeof obj === "object" || typeof obj === "function" ? + class2type[ toString.call( obj ) ] || "object" : + typeof obj; +} +/* global Symbol */ +// Defining this global in .eslintrc.json would create a danger of using the global +// unguarded in another place, it seems safer to define global only for this module + + + +var + version = "3.5.1", + + // Define a local copy of jQuery + jQuery = function( selector, context ) { + + // The jQuery object is actually just the init constructor 'enhanced' + // Need init if jQuery is called (just allow error to be thrown if not included) + return new jQuery.fn.init( selector, context ); + }; + +jQuery.fn = jQuery.prototype = { + + // The current version of jQuery being used + jquery: version, + + constructor: jQuery, + + // The default length of a jQuery object is 0 + length: 0, + + toArray: function() { + return slice.call( this ); + }, + + // Get the Nth element in the matched element set OR + // Get the whole matched element set as a clean array + get: function( num ) { + + // Return all the elements in a clean array + if ( num == null ) { + return slice.call( this ); + } + + // Return just the one element from the set + return num < 0 ? this[ num + this.length ] : this[ num ]; + }, + + // Take an array of elements and push it onto the stack + // (returning the new matched element set) + pushStack: function( elems ) { + + // Build a new jQuery matched element set + var ret = jQuery.merge( this.constructor(), elems ); + + // Add the old object onto the stack (as a reference) + ret.prevObject = this; + + // Return the newly-formed element set + return ret; + }, + + // Execute a callback for every element in the matched set. + each: function( callback ) { + return jQuery.each( this, callback ); + }, + + map: function( callback ) { + return this.pushStack( jQuery.map( this, function( elem, i ) { + return callback.call( elem, i, elem ); + } ) ); + }, + + slice: function() { + return this.pushStack( slice.apply( this, arguments ) ); + }, + + first: function() { + return this.eq( 0 ); + }, + + last: function() { + return this.eq( -1 ); + }, + + even: function() { + return this.pushStack( jQuery.grep( this, function( _elem, i ) { + return ( i + 1 ) % 2; + } ) ); + }, + + odd: function() { + return this.pushStack( jQuery.grep( this, function( _elem, i ) { + return i % 2; + } ) ); + }, + + eq: function( i ) { + var len = this.length, + j = +i + ( i < 0 ? len : 0 ); + return this.pushStack( j >= 0 && j < len ? [ this[ j ] ] : [] ); + }, + + end: function() { + return this.prevObject || this.constructor(); + }, + + // For internal use only. + // Behaves like an Array's method, not like a jQuery method. + push: push, + sort: arr.sort, + splice: arr.splice +}; + +jQuery.extend = jQuery.fn.extend = function() { + var options, name, src, copy, copyIsArray, clone, + target = arguments[ 0 ] || {}, + i = 1, + length = arguments.length, + deep = false; + + // Handle a deep copy situation + if ( typeof target === "boolean" ) { + deep = target; + + // Skip the boolean and the target + target = arguments[ i ] || {}; + i++; + } + + // Handle case when target is a string or something (possible in deep copy) + if ( typeof target !== "object" && !isFunction( target ) ) { + target = {}; + } + + // Extend jQuery itself if only one argument is passed + if ( i === length ) { + target = this; + i--; + } + + for ( ; i < length; i++ ) { + + // Only deal with non-null/undefined values + if ( ( options = arguments[ i ] ) != null ) { + + // Extend the base object + for ( name in options ) { + copy = options[ name ]; + + // Prevent Object.prototype pollution + // Prevent never-ending loop + if ( name === "__proto__" || target === copy ) { + continue; + } + + // Recurse if we're merging plain objects or arrays + if ( deep && copy && ( jQuery.isPlainObject( copy ) || + ( copyIsArray = Array.isArray( copy ) ) ) ) { + src = target[ name ]; + + // Ensure proper type for the source value + if ( copyIsArray && !Array.isArray( src ) ) { + clone = []; + } else if ( !copyIsArray && !jQuery.isPlainObject( src ) ) { + clone = {}; + } else { + clone = src; + } + copyIsArray = false; + + // Never move original objects, clone them + target[ name ] = jQuery.extend( deep, clone, copy ); + + // Don't bring in undefined values + } else if ( copy !== undefined ) { + target[ name ] = copy; + } + } + } + } + + // Return the modified object + return target; +}; + +jQuery.extend( { + + // Unique for each copy of jQuery on the page + expando: "jQuery" + ( version + Math.random() ).replace( /\D/g, "" ), + + // Assume jQuery is ready without the ready module + isReady: true, + + error: function( msg ) { + throw new Error( msg ); + }, + + noop: function() {}, + + isPlainObject: function( obj ) { + var proto, Ctor; + + // Detect obvious negatives + // Use toString instead of jQuery.type to catch host objects + if ( !obj || toString.call( obj ) !== "[object Object]" ) { + return false; + } + + proto = getProto( obj ); + + // Objects with no prototype (e.g., `Object.create( null )`) are plain + if ( !proto ) { + return true; + } + + // Objects with prototype are plain iff they were constructed by a global Object function + Ctor = hasOwn.call( proto, "constructor" ) && proto.constructor; + return typeof Ctor === "function" && fnToString.call( Ctor ) === ObjectFunctionString; + }, + + isEmptyObject: function( obj ) { + var name; + + for ( name in obj ) { + return false; + } + return true; + }, + + // Evaluates a script in a provided context; falls back to the global one + // if not specified. + globalEval: function( code, options, doc ) { + DOMEval( code, { nonce: options && options.nonce }, doc ); + }, + + each: function( obj, callback ) { + var length, i = 0; + + if ( isArrayLike( obj ) ) { + length = obj.length; + for ( ; i < length; i++ ) { + if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) { + break; + } + } + } else { + for ( i in obj ) { + if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) { + break; + } + } + } + + return obj; + }, + + // results is for internal usage only + makeArray: function( arr, results ) { + var ret = results || []; + + if ( arr != null ) { + if ( isArrayLike( Object( arr ) ) ) { + jQuery.merge( ret, + typeof arr === "string" ? + [ arr ] : arr + ); + } else { + push.call( ret, arr ); + } + } + + return ret; + }, + + inArray: function( elem, arr, i ) { + return arr == null ? -1 : indexOf.call( arr, elem, i ); + }, + + // Support: Android <=4.0 only, PhantomJS 1 only + // push.apply(_, arraylike) throws on ancient WebKit + merge: function( first, second ) { + var len = +second.length, + j = 0, + i = first.length; + + for ( ; j < len; j++ ) { + first[ i++ ] = second[ j ]; + } + + first.length = i; + + return first; + }, + + grep: function( elems, callback, invert ) { + var callbackInverse, + matches = [], + i = 0, + length = elems.length, + callbackExpect = !invert; + + // Go through the array, only saving the items + // that pass the validator function + for ( ; i < length; i++ ) { + callbackInverse = !callback( elems[ i ], i ); + if ( callbackInverse !== callbackExpect ) { + matches.push( elems[ i ] ); + } + } + + return matches; + }, + + // arg is for internal usage only + map: function( elems, callback, arg ) { + var length, value, + i = 0, + ret = []; + + // Go through the array, translating each of the items to their new values + if ( isArrayLike( elems ) ) { + length = elems.length; + for ( ; i < length; i++ ) { + value = callback( elems[ i ], i, arg ); + + if ( value != null ) { + ret.push( value ); + } + } + + // Go through every key on the object, + } else { + for ( i in elems ) { + value = callback( elems[ i ], i, arg ); + + if ( value != null ) { + ret.push( value ); + } + } + } + + // Flatten any nested arrays + return flat( ret ); + }, + + // A global GUID counter for objects + guid: 1, + + // jQuery.support is not used in Core but other projects attach their + // properties to it so it needs to exist. + support: support +} ); + +if ( typeof Symbol === "function" ) { + jQuery.fn[ Symbol.iterator ] = arr[ Symbol.iterator ]; +} + +// Populate the class2type map +jQuery.each( "Boolean Number String Function Array Date RegExp Object Error Symbol".split( " " ), +function( _i, name ) { + class2type[ "[object " + name + "]" ] = name.toLowerCase(); +} ); + +function isArrayLike( obj ) { + + // Support: real iOS 8.2 only (not reproducible in simulator) + // `in` check used to prevent JIT error (gh-2145) + // hasOwn isn't used here due to false negatives + // regarding Nodelist length in IE + var length = !!obj && "length" in obj && obj.length, + type = toType( obj ); + + if ( isFunction( obj ) || isWindow( obj ) ) { + return false; + } + + return type === "array" || length === 0 || + typeof length === "number" && length > 0 && ( length - 1 ) in obj; +} +var Sizzle = +/*! + * Sizzle CSS Selector Engine v2.3.5 + * https://sizzlejs.com/ + * + * Copyright JS Foundation and other contributors + * Released under the MIT license + * https://js.foundation/ + * + * Date: 2020-03-14 + */ +( function( window ) { +var i, + support, + Expr, + getText, + isXML, + tokenize, + compile, + select, + outermostContext, + sortInput, + hasDuplicate, + + // Local document vars + setDocument, + document, + docElem, + documentIsHTML, + rbuggyQSA, + rbuggyMatches, + matches, + contains, + + // Instance-specific data + expando = "sizzle" + 1 * new Date(), + preferredDoc = window.document, + dirruns = 0, + done = 0, + classCache = createCache(), + tokenCache = createCache(), + compilerCache = createCache(), + nonnativeSelectorCache = createCache(), + sortOrder = function( a, b ) { + if ( a === b ) { + hasDuplicate = true; + } + return 0; + }, + + // Instance methods + hasOwn = ( {} ).hasOwnProperty, + arr = [], + pop = arr.pop, + pushNative = arr.push, + push = arr.push, + slice = arr.slice, + + // Use a stripped-down indexOf as it's faster than native + // https://jsperf.com/thor-indexof-vs-for/5 + indexOf = function( list, elem ) { + var i = 0, + len = list.length; + for ( ; i < len; i++ ) { + if ( list[ i ] === elem ) { + return i; + } + } + return -1; + }, + + booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|" + + "ismap|loop|multiple|open|readonly|required|scoped", + + // Regular expressions + + // http://www.w3.org/TR/css3-selectors/#whitespace + whitespace = "[\\x20\\t\\r\\n\\f]", + + // https://www.w3.org/TR/css-syntax-3/#ident-token-diagram + identifier = "(?:\\\\[\\da-fA-F]{1,6}" + whitespace + + "?|\\\\[^\\r\\n\\f]|[\\w-]|[^\0-\\x7f])+", + + // Attribute selectors: http://www.w3.org/TR/selectors/#attribute-selectors + attributes = "\\[" + whitespace + "*(" + identifier + ")(?:" + whitespace + + + // Operator (capture 2) + "*([*^$|!~]?=)" + whitespace + + + // "Attribute values must be CSS identifiers [capture 5] + // or strings [capture 3 or capture 4]" + "*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|(" + identifier + "))|)" + + whitespace + "*\\]", + + pseudos = ":(" + identifier + ")(?:\\((" + + + // To reduce the number of selectors needing tokenize in the preFilter, prefer arguments: + // 1. quoted (capture 3; capture 4 or capture 5) + "('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|" + + + // 2. simple (capture 6) + "((?:\\\\.|[^\\\\()[\\]]|" + attributes + ")*)|" + + + // 3. anything else (capture 2) + ".*" + + ")\\)|)", + + // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter + rwhitespace = new RegExp( whitespace + "+", "g" ), + rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + + whitespace + "+$", "g" ), + + rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ), + rcombinators = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + + "*" ), + rdescend = new RegExp( whitespace + "|>" ), + + rpseudo = new RegExp( pseudos ), + ridentifier = new RegExp( "^" + identifier + "$" ), + + matchExpr = { + "ID": new RegExp( "^#(" + identifier + ")" ), + "CLASS": new RegExp( "^\\.(" + identifier + ")" ), + "TAG": new RegExp( "^(" + identifier + "|[*])" ), + "ATTR": new RegExp( "^" + attributes ), + "PSEUDO": new RegExp( "^" + pseudos ), + "CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + + whitespace + "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + + whitespace + "*(\\d+)|))" + whitespace + "*\\)|)", "i" ), + "bool": new RegExp( "^(?:" + booleans + ")$", "i" ), + + // For use in libraries implementing .is() + // We use this for POS matching in `select` + "needsContext": new RegExp( "^" + whitespace + + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" + whitespace + + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" ) + }, + + rhtml = /HTML$/i, + rinputs = /^(?:input|select|textarea|button)$/i, + rheader = /^h\d$/i, + + rnative = /^[^{]+\{\s*\[native \w/, + + // Easily-parseable/retrievable ID or TAG or CLASS selectors + rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/, + + rsibling = /[+~]/, + + // CSS escapes + // http://www.w3.org/TR/CSS21/syndata.html#escaped-characters + runescape = new RegExp( "\\\\[\\da-fA-F]{1,6}" + whitespace + "?|\\\\([^\\r\\n\\f])", "g" ), + funescape = function( escape, nonHex ) { + var high = "0x" + escape.slice( 1 ) - 0x10000; + + return nonHex ? + + // Strip the backslash prefix from a non-hex escape sequence + nonHex : + + // Replace a hexadecimal escape sequence with the encoded Unicode code point + // Support: IE <=11+ + // For values outside the Basic Multilingual Plane (BMP), manually construct a + // surrogate pair + high < 0 ? + String.fromCharCode( high + 0x10000 ) : + String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 ); + }, + + // CSS string/identifier serialization + // https://drafts.csswg.org/cssom/#common-serializing-idioms + rcssescape = /([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g, + fcssescape = function( ch, asCodePoint ) { + if ( asCodePoint ) { + + // U+0000 NULL becomes U+FFFD REPLACEMENT CHARACTER + if ( ch === "\0" ) { + return "\uFFFD"; + } + + // Control characters and (dependent upon position) numbers get escaped as code points + return ch.slice( 0, -1 ) + "\\" + + ch.charCodeAt( ch.length - 1 ).toString( 16 ) + " "; + } + + // Other potentially-special ASCII characters get backslash-escaped + return "\\" + ch; + }, + + // Used for iframes + // See setDocument() + // Removing the function wrapper causes a "Permission Denied" + // error in IE + unloadHandler = function() { + setDocument(); + }, + + inDisabledFieldset = addCombinator( + function( elem ) { + return elem.disabled === true && elem.nodeName.toLowerCase() === "fieldset"; + }, + { dir: "parentNode", next: "legend" } + ); + +// Optimize for push.apply( _, NodeList ) +try { + push.apply( + ( arr = slice.call( preferredDoc.childNodes ) ), + preferredDoc.childNodes + ); + + // Support: Android<4.0 + // Detect silently failing push.apply + // eslint-disable-next-line no-unused-expressions + arr[ preferredDoc.childNodes.length ].nodeType; +} catch ( e ) { + push = { apply: arr.length ? + + // Leverage slice if possible + function( target, els ) { + pushNative.apply( target, slice.call( els ) ); + } : + + // Support: IE<9 + // Otherwise append directly + function( target, els ) { + var j = target.length, + i = 0; + + // Can't trust NodeList.length + while ( ( target[ j++ ] = els[ i++ ] ) ) {} + target.length = j - 1; + } + }; +} + +function Sizzle( selector, context, results, seed ) { + var m, i, elem, nid, match, groups, newSelector, + newContext = context && context.ownerDocument, + + // nodeType defaults to 9, since context defaults to document + nodeType = context ? context.nodeType : 9; + + results = results || []; + + // Return early from calls with invalid selector or context + if ( typeof selector !== "string" || !selector || + nodeType !== 1 && nodeType !== 9 && nodeType !== 11 ) { + + return results; + } + + // Try to shortcut find operations (as opposed to filters) in HTML documents + if ( !seed ) { + setDocument( context ); + context = context || document; + + if ( documentIsHTML ) { + + // If the selector is sufficiently simple, try using a "get*By*" DOM method + // (excepting DocumentFragment context, where the methods don't exist) + if ( nodeType !== 11 && ( match = rquickExpr.exec( selector ) ) ) { + + // ID selector + if ( ( m = match[ 1 ] ) ) { + + // Document context + if ( nodeType === 9 ) { + if ( ( elem = context.getElementById( m ) ) ) { + + // Support: IE, Opera, Webkit + // TODO: identify versions + // getElementById can match elements by name instead of ID + if ( elem.id === m ) { + results.push( elem ); + return results; + } + } else { + return results; + } + + // Element context + } else { + + // Support: IE, Opera, Webkit + // TODO: identify versions + // getElementById can match elements by name instead of ID + if ( newContext && ( elem = newContext.getElementById( m ) ) && + contains( context, elem ) && + elem.id === m ) { + + results.push( elem ); + return results; + } + } + + // Type selector + } else if ( match[ 2 ] ) { + push.apply( results, context.getElementsByTagName( selector ) ); + return results; + + // Class selector + } else if ( ( m = match[ 3 ] ) && support.getElementsByClassName && + context.getElementsByClassName ) { + + push.apply( results, context.getElementsByClassName( m ) ); + return results; + } + } + + // Take advantage of querySelectorAll + if ( support.qsa && + !nonnativeSelectorCache[ selector + " " ] && + ( !rbuggyQSA || !rbuggyQSA.test( selector ) ) && + + // Support: IE 8 only + // Exclude object elements + ( nodeType !== 1 || context.nodeName.toLowerCase() !== "object" ) ) { + + newSelector = selector; + newContext = context; + + // qSA considers elements outside a scoping root when evaluating child or + // descendant combinators, which is not what we want. + // In such cases, we work around the behavior by prefixing every selector in the + // list with an ID selector referencing the scope context. + // The technique has to be used as well when a leading combinator is used + // as such selectors are not recognized by querySelectorAll. + // Thanks to Andrew Dupont for this technique. + if ( nodeType === 1 && + ( rdescend.test( selector ) || rcombinators.test( selector ) ) ) { + + // Expand context for sibling selectors + newContext = rsibling.test( selector ) && testContext( context.parentNode ) || + context; + + // We can use :scope instead of the ID hack if the browser + // supports it & if we're not changing the context. + if ( newContext !== context || !support.scope ) { + + // Capture the context ID, setting it first if necessary + if ( ( nid = context.getAttribute( "id" ) ) ) { + nid = nid.replace( rcssescape, fcssescape ); + } else { + context.setAttribute( "id", ( nid = expando ) ); + } + } + + // Prefix every selector in the list + groups = tokenize( selector ); + i = groups.length; + while ( i-- ) { + groups[ i ] = ( nid ? "#" + nid : ":scope" ) + " " + + toSelector( groups[ i ] ); + } + newSelector = groups.join( "," ); + } + + try { + push.apply( results, + newContext.querySelectorAll( newSelector ) + ); + return results; + } catch ( qsaError ) { + nonnativeSelectorCache( selector, true ); + } finally { + if ( nid === expando ) { + context.removeAttribute( "id" ); + } + } + } + } + } + + // All others + return select( selector.replace( rtrim, "$1" ), context, results, seed ); +} + +/** + * Create key-value caches of limited size + * @returns {function(string, object)} Returns the Object data after storing it on itself with + * property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength) + * deleting the oldest entry + */ +function createCache() { + var keys = []; + + function cache( key, value ) { + + // Use (key + " ") to avoid collision with native prototype properties (see Issue #157) + if ( keys.push( key + " " ) > Expr.cacheLength ) { + + // Only keep the most recent entries + delete cache[ keys.shift() ]; + } + return ( cache[ key + " " ] = value ); + } + return cache; +} + +/** + * Mark a function for special use by Sizzle + * @param {Function} fn The function to mark + */ +function markFunction( fn ) { + fn[ expando ] = true; + return fn; +} + +/** + * Support testing using an element + * @param {Function} fn Passed the created element and returns a boolean result + */ +function assert( fn ) { + var el = document.createElement( "fieldset" ); + + try { + return !!fn( el ); + } catch ( e ) { + return false; + } finally { + + // Remove from its parent by default + if ( el.parentNode ) { + el.parentNode.removeChild( el ); + } + + // release memory in IE + el = null; + } +} + +/** + * Adds the same handler for all of the specified attrs + * @param {String} attrs Pipe-separated list of attributes + * @param {Function} handler The method that will be applied + */ +function addHandle( attrs, handler ) { + var arr = attrs.split( "|" ), + i = arr.length; + + while ( i-- ) { + Expr.attrHandle[ arr[ i ] ] = handler; + } +} + +/** + * Checks document order of two siblings + * @param {Element} a + * @param {Element} b + * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b + */ +function siblingCheck( a, b ) { + var cur = b && a, + diff = cur && a.nodeType === 1 && b.nodeType === 1 && + a.sourceIndex - b.sourceIndex; + + // Use IE sourceIndex if available on both nodes + if ( diff ) { + return diff; + } + + // Check if b follows a + if ( cur ) { + while ( ( cur = cur.nextSibling ) ) { + if ( cur === b ) { + return -1; + } + } + } + + return a ? 1 : -1; +} + +/** + * Returns a function to use in pseudos for input types + * @param {String} type + */ +function createInputPseudo( type ) { + return function( elem ) { + var name = elem.nodeName.toLowerCase(); + return name === "input" && elem.type === type; + }; +} + +/** + * Returns a function to use in pseudos for buttons + * @param {String} type + */ +function createButtonPseudo( type ) { + return function( elem ) { + var name = elem.nodeName.toLowerCase(); + return ( name === "input" || name === "button" ) && elem.type === type; + }; +} + +/** + * Returns a function to use in pseudos for :enabled/:disabled + * @param {Boolean} disabled true for :disabled; false for :enabled + */ +function createDisabledPseudo( disabled ) { + + // Known :disabled false positives: fieldset[disabled] > legend:nth-of-type(n+2) :can-disable + return function( elem ) { + + // Only certain elements can match :enabled or :disabled + // https://html.spec.whatwg.org/multipage/scripting.html#selector-enabled + // https://html.spec.whatwg.org/multipage/scripting.html#selector-disabled + if ( "form" in elem ) { + + // Check for inherited disabledness on relevant non-disabled elements: + // * listed form-associated elements in a disabled fieldset + // https://html.spec.whatwg.org/multipage/forms.html#category-listed + // https://html.spec.whatwg.org/multipage/forms.html#concept-fe-disabled + // * option elements in a disabled optgroup + // https://html.spec.whatwg.org/multipage/forms.html#concept-option-disabled + // All such elements have a "form" property. + if ( elem.parentNode && elem.disabled === false ) { + + // Option elements defer to a parent optgroup if present + if ( "label" in elem ) { + if ( "label" in elem.parentNode ) { + return elem.parentNode.disabled === disabled; + } else { + return elem.disabled === disabled; + } + } + + // Support: IE 6 - 11 + // Use the isDisabled shortcut property to check for disabled fieldset ancestors + return elem.isDisabled === disabled || + + // Where there is no isDisabled, check manually + /* jshint -W018 */ + elem.isDisabled !== !disabled && + inDisabledFieldset( elem ) === disabled; + } + + return elem.disabled === disabled; + + // Try to winnow out elements that can't be disabled before trusting the disabled property. + // Some victims get caught in our net (label, legend, menu, track), but it shouldn't + // even exist on them, let alone have a boolean value. + } else if ( "label" in elem ) { + return elem.disabled === disabled; + } + + // Remaining elements are neither :enabled nor :disabled + return false; + }; +} + +/** + * Returns a function to use in pseudos for positionals + * @param {Function} fn + */ +function createPositionalPseudo( fn ) { + return markFunction( function( argument ) { + argument = +argument; + return markFunction( function( seed, matches ) { + var j, + matchIndexes = fn( [], seed.length, argument ), + i = matchIndexes.length; + + // Match elements found at the specified indexes + while ( i-- ) { + if ( seed[ ( j = matchIndexes[ i ] ) ] ) { + seed[ j ] = !( matches[ j ] = seed[ j ] ); + } + } + } ); + } ); +} + +/** + * Checks a node for validity as a Sizzle context + * @param {Element|Object=} context + * @returns {Element|Object|Boolean} The input node if acceptable, otherwise a falsy value + */ +function testContext( context ) { + return context && typeof context.getElementsByTagName !== "undefined" && context; +} + +// Expose support vars for convenience +support = Sizzle.support = {}; + +/** + * Detects XML nodes + * @param {Element|Object} elem An element or a document + * @returns {Boolean} True iff elem is a non-HTML XML node + */ +isXML = Sizzle.isXML = function( elem ) { + var namespace = elem.namespaceURI, + docElem = ( elem.ownerDocument || elem ).documentElement; + + // Support: IE <=8 + // Assume HTML when documentElement doesn't yet exist, such as inside loading iframes + // https://bugs.jquery.com/ticket/4833 + return !rhtml.test( namespace || docElem && docElem.nodeName || "HTML" ); +}; + +/** + * Sets document-related variables once based on the current document + * @param {Element|Object} [doc] An element or document object to use to set the document + * @returns {Object} Returns the current document + */ +setDocument = Sizzle.setDocument = function( node ) { + var hasCompare, subWindow, + doc = node ? node.ownerDocument || node : preferredDoc; + + // Return early if doc is invalid or already selected + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( doc == document || doc.nodeType !== 9 || !doc.documentElement ) { + return document; + } + + // Update global variables + document = doc; + docElem = document.documentElement; + documentIsHTML = !isXML( document ); + + // Support: IE 9 - 11+, Edge 12 - 18+ + // Accessing iframe documents after unload throws "permission denied" errors (jQuery #13936) + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( preferredDoc != document && + ( subWindow = document.defaultView ) && subWindow.top !== subWindow ) { + + // Support: IE 11, Edge + if ( subWindow.addEventListener ) { + subWindow.addEventListener( "unload", unloadHandler, false ); + + // Support: IE 9 - 10 only + } else if ( subWindow.attachEvent ) { + subWindow.attachEvent( "onunload", unloadHandler ); + } + } + + // Support: IE 8 - 11+, Edge 12 - 18+, Chrome <=16 - 25 only, Firefox <=3.6 - 31 only, + // Safari 4 - 5 only, Opera <=11.6 - 12.x only + // IE/Edge & older browsers don't support the :scope pseudo-class. + // Support: Safari 6.0 only + // Safari 6.0 supports :scope but it's an alias of :root there. + support.scope = assert( function( el ) { + docElem.appendChild( el ).appendChild( document.createElement( "div" ) ); + return typeof el.querySelectorAll !== "undefined" && + !el.querySelectorAll( ":scope fieldset div" ).length; + } ); + + /* Attributes + ---------------------------------------------------------------------- */ + + // Support: IE<8 + // Verify that getAttribute really returns attributes and not properties + // (excepting IE8 booleans) + support.attributes = assert( function( el ) { + el.className = "i"; + return !el.getAttribute( "className" ); + } ); + + /* getElement(s)By* + ---------------------------------------------------------------------- */ + + // Check if getElementsByTagName("*") returns only elements + support.getElementsByTagName = assert( function( el ) { + el.appendChild( document.createComment( "" ) ); + return !el.getElementsByTagName( "*" ).length; + } ); + + // Support: IE<9 + support.getElementsByClassName = rnative.test( document.getElementsByClassName ); + + // Support: IE<10 + // Check if getElementById returns elements by name + // The broken getElementById methods don't pick up programmatically-set names, + // so use a roundabout getElementsByName test + support.getById = assert( function( el ) { + docElem.appendChild( el ).id = expando; + return !document.getElementsByName || !document.getElementsByName( expando ).length; + } ); + + // ID filter and find + if ( support.getById ) { + Expr.filter[ "ID" ] = function( id ) { + var attrId = id.replace( runescape, funescape ); + return function( elem ) { + return elem.getAttribute( "id" ) === attrId; + }; + }; + Expr.find[ "ID" ] = function( id, context ) { + if ( typeof context.getElementById !== "undefined" && documentIsHTML ) { + var elem = context.getElementById( id ); + return elem ? [ elem ] : []; + } + }; + } else { + Expr.filter[ "ID" ] = function( id ) { + var attrId = id.replace( runescape, funescape ); + return function( elem ) { + var node = typeof elem.getAttributeNode !== "undefined" && + elem.getAttributeNode( "id" ); + return node && node.value === attrId; + }; + }; + + // Support: IE 6 - 7 only + // getElementById is not reliable as a find shortcut + Expr.find[ "ID" ] = function( id, context ) { + if ( typeof context.getElementById !== "undefined" && documentIsHTML ) { + var node, i, elems, + elem = context.getElementById( id ); + + if ( elem ) { + + // Verify the id attribute + node = elem.getAttributeNode( "id" ); + if ( node && node.value === id ) { + return [ elem ]; + } + + // Fall back on getElementsByName + elems = context.getElementsByName( id ); + i = 0; + while ( ( elem = elems[ i++ ] ) ) { + node = elem.getAttributeNode( "id" ); + if ( node && node.value === id ) { + return [ elem ]; + } + } + } + + return []; + } + }; + } + + // Tag + Expr.find[ "TAG" ] = support.getElementsByTagName ? + function( tag, context ) { + if ( typeof context.getElementsByTagName !== "undefined" ) { + return context.getElementsByTagName( tag ); + + // DocumentFragment nodes don't have gEBTN + } else if ( support.qsa ) { + return context.querySelectorAll( tag ); + } + } : + + function( tag, context ) { + var elem, + tmp = [], + i = 0, + + // By happy coincidence, a (broken) gEBTN appears on DocumentFragment nodes too + results = context.getElementsByTagName( tag ); + + // Filter out possible comments + if ( tag === "*" ) { + while ( ( elem = results[ i++ ] ) ) { + if ( elem.nodeType === 1 ) { + tmp.push( elem ); + } + } + + return tmp; + } + return results; + }; + + // Class + Expr.find[ "CLASS" ] = support.getElementsByClassName && function( className, context ) { + if ( typeof context.getElementsByClassName !== "undefined" && documentIsHTML ) { + return context.getElementsByClassName( className ); + } + }; + + /* QSA/matchesSelector + ---------------------------------------------------------------------- */ + + // QSA and matchesSelector support + + // matchesSelector(:active) reports false when true (IE9/Opera 11.5) + rbuggyMatches = []; + + // qSa(:focus) reports false when true (Chrome 21) + // We allow this because of a bug in IE8/9 that throws an error + // whenever `document.activeElement` is accessed on an iframe + // So, we allow :focus to pass through QSA all the time to avoid the IE error + // See https://bugs.jquery.com/ticket/13378 + rbuggyQSA = []; + + if ( ( support.qsa = rnative.test( document.querySelectorAll ) ) ) { + + // Build QSA regex + // Regex strategy adopted from Diego Perini + assert( function( el ) { + + var input; + + // Select is set to empty string on purpose + // This is to test IE's treatment of not explicitly + // setting a boolean content attribute, + // since its presence should be enough + // https://bugs.jquery.com/ticket/12359 + docElem.appendChild( el ).innerHTML = "" + + ""; + + // Support: IE8, Opera 11-12.16 + // Nothing should be selected when empty strings follow ^= or $= or *= + // The test attribute must be unknown in Opera but "safe" for WinRT + // https://msdn.microsoft.com/en-us/library/ie/hh465388.aspx#attribute_section + if ( el.querySelectorAll( "[msallowcapture^='']" ).length ) { + rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:''|\"\")" ); + } + + // Support: IE8 + // Boolean attributes and "value" are not treated correctly + if ( !el.querySelectorAll( "[selected]" ).length ) { + rbuggyQSA.push( "\\[" + whitespace + "*(?:value|" + booleans + ")" ); + } + + // Support: Chrome<29, Android<4.4, Safari<7.0+, iOS<7.0+, PhantomJS<1.9.8+ + if ( !el.querySelectorAll( "[id~=" + expando + "-]" ).length ) { + rbuggyQSA.push( "~=" ); + } + + // Support: IE 11+, Edge 15 - 18+ + // IE 11/Edge don't find elements on a `[name='']` query in some cases. + // Adding a temporary attribute to the document before the selection works + // around the issue. + // Interestingly, IE 10 & older don't seem to have the issue. + input = document.createElement( "input" ); + input.setAttribute( "name", "" ); + el.appendChild( input ); + if ( !el.querySelectorAll( "[name='']" ).length ) { + rbuggyQSA.push( "\\[" + whitespace + "*name" + whitespace + "*=" + + whitespace + "*(?:''|\"\")" ); + } + + // Webkit/Opera - :checked should return selected option elements + // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked + // IE8 throws error here and will not see later tests + if ( !el.querySelectorAll( ":checked" ).length ) { + rbuggyQSA.push( ":checked" ); + } + + // Support: Safari 8+, iOS 8+ + // https://bugs.webkit.org/show_bug.cgi?id=136851 + // In-page `selector#id sibling-combinator selector` fails + if ( !el.querySelectorAll( "a#" + expando + "+*" ).length ) { + rbuggyQSA.push( ".#.+[+~]" ); + } + + // Support: Firefox <=3.6 - 5 only + // Old Firefox doesn't throw on a badly-escaped identifier. + el.querySelectorAll( "\\\f" ); + rbuggyQSA.push( "[\\r\\n\\f]" ); + } ); + + assert( function( el ) { + el.innerHTML = "" + + ""; + + // Support: Windows 8 Native Apps + // The type and name attributes are restricted during .innerHTML assignment + var input = document.createElement( "input" ); + input.setAttribute( "type", "hidden" ); + el.appendChild( input ).setAttribute( "name", "D" ); + + // Support: IE8 + // Enforce case-sensitivity of name attribute + if ( el.querySelectorAll( "[name=d]" ).length ) { + rbuggyQSA.push( "name" + whitespace + "*[*^$|!~]?=" ); + } + + // FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled) + // IE8 throws error here and will not see later tests + if ( el.querySelectorAll( ":enabled" ).length !== 2 ) { + rbuggyQSA.push( ":enabled", ":disabled" ); + } + + // Support: IE9-11+ + // IE's :disabled selector does not pick up the children of disabled fieldsets + docElem.appendChild( el ).disabled = true; + if ( el.querySelectorAll( ":disabled" ).length !== 2 ) { + rbuggyQSA.push( ":enabled", ":disabled" ); + } + + // Support: Opera 10 - 11 only + // Opera 10-11 does not throw on post-comma invalid pseudos + el.querySelectorAll( "*,:x" ); + rbuggyQSA.push( ",.*:" ); + } ); + } + + if ( ( support.matchesSelector = rnative.test( ( matches = docElem.matches || + docElem.webkitMatchesSelector || + docElem.mozMatchesSelector || + docElem.oMatchesSelector || + docElem.msMatchesSelector ) ) ) ) { + + assert( function( el ) { + + // Check to see if it's possible to do matchesSelector + // on a disconnected node (IE 9) + support.disconnectedMatch = matches.call( el, "*" ); + + // This should fail with an exception + // Gecko does not error, returns false instead + matches.call( el, "[s!='']:x" ); + rbuggyMatches.push( "!=", pseudos ); + } ); + } + + rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join( "|" ) ); + rbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join( "|" ) ); + + /* Contains + ---------------------------------------------------------------------- */ + hasCompare = rnative.test( docElem.compareDocumentPosition ); + + // Element contains another + // Purposefully self-exclusive + // As in, an element does not contain itself + contains = hasCompare || rnative.test( docElem.contains ) ? + function( a, b ) { + var adown = a.nodeType === 9 ? a.documentElement : a, + bup = b && b.parentNode; + return a === bup || !!( bup && bup.nodeType === 1 && ( + adown.contains ? + adown.contains( bup ) : + a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16 + ) ); + } : + function( a, b ) { + if ( b ) { + while ( ( b = b.parentNode ) ) { + if ( b === a ) { + return true; + } + } + } + return false; + }; + + /* Sorting + ---------------------------------------------------------------------- */ + + // Document order sorting + sortOrder = hasCompare ? + function( a, b ) { + + // Flag for duplicate removal + if ( a === b ) { + hasDuplicate = true; + return 0; + } + + // Sort on method existence if only one input has compareDocumentPosition + var compare = !a.compareDocumentPosition - !b.compareDocumentPosition; + if ( compare ) { + return compare; + } + + // Calculate position if both inputs belong to the same document + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + compare = ( a.ownerDocument || a ) == ( b.ownerDocument || b ) ? + a.compareDocumentPosition( b ) : + + // Otherwise we know they are disconnected + 1; + + // Disconnected nodes + if ( compare & 1 || + ( !support.sortDetached && b.compareDocumentPosition( a ) === compare ) ) { + + // Choose the first element that is related to our preferred document + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( a == document || a.ownerDocument == preferredDoc && + contains( preferredDoc, a ) ) { + return -1; + } + + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( b == document || b.ownerDocument == preferredDoc && + contains( preferredDoc, b ) ) { + return 1; + } + + // Maintain original order + return sortInput ? + ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) : + 0; + } + + return compare & 4 ? -1 : 1; + } : + function( a, b ) { + + // Exit early if the nodes are identical + if ( a === b ) { + hasDuplicate = true; + return 0; + } + + var cur, + i = 0, + aup = a.parentNode, + bup = b.parentNode, + ap = [ a ], + bp = [ b ]; + + // Parentless nodes are either documents or disconnected + if ( !aup || !bup ) { + + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + /* eslint-disable eqeqeq */ + return a == document ? -1 : + b == document ? 1 : + /* eslint-enable eqeqeq */ + aup ? -1 : + bup ? 1 : + sortInput ? + ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) : + 0; + + // If the nodes are siblings, we can do a quick check + } else if ( aup === bup ) { + return siblingCheck( a, b ); + } + + // Otherwise we need full lists of their ancestors for comparison + cur = a; + while ( ( cur = cur.parentNode ) ) { + ap.unshift( cur ); + } + cur = b; + while ( ( cur = cur.parentNode ) ) { + bp.unshift( cur ); + } + + // Walk down the tree looking for a discrepancy + while ( ap[ i ] === bp[ i ] ) { + i++; + } + + return i ? + + // Do a sibling check if the nodes have a common ancestor + siblingCheck( ap[ i ], bp[ i ] ) : + + // Otherwise nodes in our document sort first + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + /* eslint-disable eqeqeq */ + ap[ i ] == preferredDoc ? -1 : + bp[ i ] == preferredDoc ? 1 : + /* eslint-enable eqeqeq */ + 0; + }; + + return document; +}; + +Sizzle.matches = function( expr, elements ) { + return Sizzle( expr, null, null, elements ); +}; + +Sizzle.matchesSelector = function( elem, expr ) { + setDocument( elem ); + + if ( support.matchesSelector && documentIsHTML && + !nonnativeSelectorCache[ expr + " " ] && + ( !rbuggyMatches || !rbuggyMatches.test( expr ) ) && + ( !rbuggyQSA || !rbuggyQSA.test( expr ) ) ) { + + try { + var ret = matches.call( elem, expr ); + + // IE 9's matchesSelector returns false on disconnected nodes + if ( ret || support.disconnectedMatch || + + // As well, disconnected nodes are said to be in a document + // fragment in IE 9 + elem.document && elem.document.nodeType !== 11 ) { + return ret; + } + } catch ( e ) { + nonnativeSelectorCache( expr, true ); + } + } + + return Sizzle( expr, document, null, [ elem ] ).length > 0; +}; + +Sizzle.contains = function( context, elem ) { + + // Set document vars if needed + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( ( context.ownerDocument || context ) != document ) { + setDocument( context ); + } + return contains( context, elem ); +}; + +Sizzle.attr = function( elem, name ) { + + // Set document vars if needed + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( ( elem.ownerDocument || elem ) != document ) { + setDocument( elem ); + } + + var fn = Expr.attrHandle[ name.toLowerCase() ], + + // Don't get fooled by Object.prototype properties (jQuery #13807) + val = fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ? + fn( elem, name, !documentIsHTML ) : + undefined; + + return val !== undefined ? + val : + support.attributes || !documentIsHTML ? + elem.getAttribute( name ) : + ( val = elem.getAttributeNode( name ) ) && val.specified ? + val.value : + null; +}; + +Sizzle.escape = function( sel ) { + return ( sel + "" ).replace( rcssescape, fcssescape ); +}; + +Sizzle.error = function( msg ) { + throw new Error( "Syntax error, unrecognized expression: " + msg ); +}; + +/** + * Document sorting and removing duplicates + * @param {ArrayLike} results + */ +Sizzle.uniqueSort = function( results ) { + var elem, + duplicates = [], + j = 0, + i = 0; + + // Unless we *know* we can detect duplicates, assume their presence + hasDuplicate = !support.detectDuplicates; + sortInput = !support.sortStable && results.slice( 0 ); + results.sort( sortOrder ); + + if ( hasDuplicate ) { + while ( ( elem = results[ i++ ] ) ) { + if ( elem === results[ i ] ) { + j = duplicates.push( i ); + } + } + while ( j-- ) { + results.splice( duplicates[ j ], 1 ); + } + } + + // Clear input after sorting to release objects + // See https://github.com/jquery/sizzle/pull/225 + sortInput = null; + + return results; +}; + +/** + * Utility function for retrieving the text value of an array of DOM nodes + * @param {Array|Element} elem + */ +getText = Sizzle.getText = function( elem ) { + var node, + ret = "", + i = 0, + nodeType = elem.nodeType; + + if ( !nodeType ) { + + // If no nodeType, this is expected to be an array + while ( ( node = elem[ i++ ] ) ) { + + // Do not traverse comment nodes + ret += getText( node ); + } + } else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) { + + // Use textContent for elements + // innerText usage removed for consistency of new lines (jQuery #11153) + if ( typeof elem.textContent === "string" ) { + return elem.textContent; + } else { + + // Traverse its children + for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { + ret += getText( elem ); + } + } + } else if ( nodeType === 3 || nodeType === 4 ) { + return elem.nodeValue; + } + + // Do not include comment or processing instruction nodes + + return ret; +}; + +Expr = Sizzle.selectors = { + + // Can be adjusted by the user + cacheLength: 50, + + createPseudo: markFunction, + + match: matchExpr, + + attrHandle: {}, + + find: {}, + + relative: { + ">": { dir: "parentNode", first: true }, + " ": { dir: "parentNode" }, + "+": { dir: "previousSibling", first: true }, + "~": { dir: "previousSibling" } + }, + + preFilter: { + "ATTR": function( match ) { + match[ 1 ] = match[ 1 ].replace( runescape, funescape ); + + // Move the given value to match[3] whether quoted or unquoted + match[ 3 ] = ( match[ 3 ] || match[ 4 ] || + match[ 5 ] || "" ).replace( runescape, funescape ); + + if ( match[ 2 ] === "~=" ) { + match[ 3 ] = " " + match[ 3 ] + " "; + } + + return match.slice( 0, 4 ); + }, + + "CHILD": function( match ) { + + /* matches from matchExpr["CHILD"] + 1 type (only|nth|...) + 2 what (child|of-type) + 3 argument (even|odd|\d*|\d*n([+-]\d+)?|...) + 4 xn-component of xn+y argument ([+-]?\d*n|) + 5 sign of xn-component + 6 x of xn-component + 7 sign of y-component + 8 y of y-component + */ + match[ 1 ] = match[ 1 ].toLowerCase(); + + if ( match[ 1 ].slice( 0, 3 ) === "nth" ) { + + // nth-* requires argument + if ( !match[ 3 ] ) { + Sizzle.error( match[ 0 ] ); + } + + // numeric x and y parameters for Expr.filter.CHILD + // remember that false/true cast respectively to 0/1 + match[ 4 ] = +( match[ 4 ] ? + match[ 5 ] + ( match[ 6 ] || 1 ) : + 2 * ( match[ 3 ] === "even" || match[ 3 ] === "odd" ) ); + match[ 5 ] = +( ( match[ 7 ] + match[ 8 ] ) || match[ 3 ] === "odd" ); + + // other types prohibit arguments + } else if ( match[ 3 ] ) { + Sizzle.error( match[ 0 ] ); + } + + return match; + }, + + "PSEUDO": function( match ) { + var excess, + unquoted = !match[ 6 ] && match[ 2 ]; + + if ( matchExpr[ "CHILD" ].test( match[ 0 ] ) ) { + return null; + } + + // Accept quoted arguments as-is + if ( match[ 3 ] ) { + match[ 2 ] = match[ 4 ] || match[ 5 ] || ""; + + // Strip excess characters from unquoted arguments + } else if ( unquoted && rpseudo.test( unquoted ) && + + // Get excess from tokenize (recursively) + ( excess = tokenize( unquoted, true ) ) && + + // advance to the next closing parenthesis + ( excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length ) ) { + + // excess is a negative index + match[ 0 ] = match[ 0 ].slice( 0, excess ); + match[ 2 ] = unquoted.slice( 0, excess ); + } + + // Return only captures needed by the pseudo filter method (type and argument) + return match.slice( 0, 3 ); + } + }, + + filter: { + + "TAG": function( nodeNameSelector ) { + var nodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase(); + return nodeNameSelector === "*" ? + function() { + return true; + } : + function( elem ) { + return elem.nodeName && elem.nodeName.toLowerCase() === nodeName; + }; + }, + + "CLASS": function( className ) { + var pattern = classCache[ className + " " ]; + + return pattern || + ( pattern = new RegExp( "(^|" + whitespace + + ")" + className + "(" + whitespace + "|$)" ) ) && classCache( + className, function( elem ) { + return pattern.test( + typeof elem.className === "string" && elem.className || + typeof elem.getAttribute !== "undefined" && + elem.getAttribute( "class" ) || + "" + ); + } ); + }, + + "ATTR": function( name, operator, check ) { + return function( elem ) { + var result = Sizzle.attr( elem, name ); + + if ( result == null ) { + return operator === "!="; + } + if ( !operator ) { + return true; + } + + result += ""; + + /* eslint-disable max-len */ + + return operator === "=" ? result === check : + operator === "!=" ? result !== check : + operator === "^=" ? check && result.indexOf( check ) === 0 : + operator === "*=" ? check && result.indexOf( check ) > -1 : + operator === "$=" ? check && result.slice( -check.length ) === check : + operator === "~=" ? ( " " + result.replace( rwhitespace, " " ) + " " ).indexOf( check ) > -1 : + operator === "|=" ? result === check || result.slice( 0, check.length + 1 ) === check + "-" : + false; + /* eslint-enable max-len */ + + }; + }, + + "CHILD": function( type, what, _argument, first, last ) { + var simple = type.slice( 0, 3 ) !== "nth", + forward = type.slice( -4 ) !== "last", + ofType = what === "of-type"; + + return first === 1 && last === 0 ? + + // Shortcut for :nth-*(n) + function( elem ) { + return !!elem.parentNode; + } : + + function( elem, _context, xml ) { + var cache, uniqueCache, outerCache, node, nodeIndex, start, + dir = simple !== forward ? "nextSibling" : "previousSibling", + parent = elem.parentNode, + name = ofType && elem.nodeName.toLowerCase(), + useCache = !xml && !ofType, + diff = false; + + if ( parent ) { + + // :(first|last|only)-(child|of-type) + if ( simple ) { + while ( dir ) { + node = elem; + while ( ( node = node[ dir ] ) ) { + if ( ofType ? + node.nodeName.toLowerCase() === name : + node.nodeType === 1 ) { + + return false; + } + } + + // Reverse direction for :only-* (if we haven't yet done so) + start = dir = type === "only" && !start && "nextSibling"; + } + return true; + } + + start = [ forward ? parent.firstChild : parent.lastChild ]; + + // non-xml :nth-child(...) stores cache data on `parent` + if ( forward && useCache ) { + + // Seek `elem` from a previously-cached index + + // ...in a gzip-friendly way + node = parent; + outerCache = node[ expando ] || ( node[ expando ] = {} ); + + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ node.uniqueID ] || + ( outerCache[ node.uniqueID ] = {} ); + + cache = uniqueCache[ type ] || []; + nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ]; + diff = nodeIndex && cache[ 2 ]; + node = nodeIndex && parent.childNodes[ nodeIndex ]; + + while ( ( node = ++nodeIndex && node && node[ dir ] || + + // Fallback to seeking `elem` from the start + ( diff = nodeIndex = 0 ) || start.pop() ) ) { + + // When found, cache indexes on `parent` and break + if ( node.nodeType === 1 && ++diff && node === elem ) { + uniqueCache[ type ] = [ dirruns, nodeIndex, diff ]; + break; + } + } + + } else { + + // Use previously-cached element index if available + if ( useCache ) { + + // ...in a gzip-friendly way + node = elem; + outerCache = node[ expando ] || ( node[ expando ] = {} ); + + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ node.uniqueID ] || + ( outerCache[ node.uniqueID ] = {} ); + + cache = uniqueCache[ type ] || []; + nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ]; + diff = nodeIndex; + } + + // xml :nth-child(...) + // or :nth-last-child(...) or :nth(-last)?-of-type(...) + if ( diff === false ) { + + // Use the same loop as above to seek `elem` from the start + while ( ( node = ++nodeIndex && node && node[ dir ] || + ( diff = nodeIndex = 0 ) || start.pop() ) ) { + + if ( ( ofType ? + node.nodeName.toLowerCase() === name : + node.nodeType === 1 ) && + ++diff ) { + + // Cache the index of each encountered element + if ( useCache ) { + outerCache = node[ expando ] || + ( node[ expando ] = {} ); + + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ node.uniqueID ] || + ( outerCache[ node.uniqueID ] = {} ); + + uniqueCache[ type ] = [ dirruns, diff ]; + } + + if ( node === elem ) { + break; + } + } + } + } + } + + // Incorporate the offset, then check against cycle size + diff -= last; + return diff === first || ( diff % first === 0 && diff / first >= 0 ); + } + }; + }, + + "PSEUDO": function( pseudo, argument ) { + + // pseudo-class names are case-insensitive + // http://www.w3.org/TR/selectors/#pseudo-classes + // Prioritize by case sensitivity in case custom pseudos are added with uppercase letters + // Remember that setFilters inherits from pseudos + var args, + fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] || + Sizzle.error( "unsupported pseudo: " + pseudo ); + + // The user may use createPseudo to indicate that + // arguments are needed to create the filter function + // just as Sizzle does + if ( fn[ expando ] ) { + return fn( argument ); + } + + // But maintain support for old signatures + if ( fn.length > 1 ) { + args = [ pseudo, pseudo, "", argument ]; + return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ? + markFunction( function( seed, matches ) { + var idx, + matched = fn( seed, argument ), + i = matched.length; + while ( i-- ) { + idx = indexOf( seed, matched[ i ] ); + seed[ idx ] = !( matches[ idx ] = matched[ i ] ); + } + } ) : + function( elem ) { + return fn( elem, 0, args ); + }; + } + + return fn; + } + }, + + pseudos: { + + // Potentially complex pseudos + "not": markFunction( function( selector ) { + + // Trim the selector passed to compile + // to avoid treating leading and trailing + // spaces as combinators + var input = [], + results = [], + matcher = compile( selector.replace( rtrim, "$1" ) ); + + return matcher[ expando ] ? + markFunction( function( seed, matches, _context, xml ) { + var elem, + unmatched = matcher( seed, null, xml, [] ), + i = seed.length; + + // Match elements unmatched by `matcher` + while ( i-- ) { + if ( ( elem = unmatched[ i ] ) ) { + seed[ i ] = !( matches[ i ] = elem ); + } + } + } ) : + function( elem, _context, xml ) { + input[ 0 ] = elem; + matcher( input, null, xml, results ); + + // Don't keep the element (issue #299) + input[ 0 ] = null; + return !results.pop(); + }; + } ), + + "has": markFunction( function( selector ) { + return function( elem ) { + return Sizzle( selector, elem ).length > 0; + }; + } ), + + "contains": markFunction( function( text ) { + text = text.replace( runescape, funescape ); + return function( elem ) { + return ( elem.textContent || getText( elem ) ).indexOf( text ) > -1; + }; + } ), + + // "Whether an element is represented by a :lang() selector + // is based solely on the element's language value + // being equal to the identifier C, + // or beginning with the identifier C immediately followed by "-". + // The matching of C against the element's language value is performed case-insensitively. + // The identifier C does not have to be a valid language name." + // http://www.w3.org/TR/selectors/#lang-pseudo + "lang": markFunction( function( lang ) { + + // lang value must be a valid identifier + if ( !ridentifier.test( lang || "" ) ) { + Sizzle.error( "unsupported lang: " + lang ); + } + lang = lang.replace( runescape, funescape ).toLowerCase(); + return function( elem ) { + var elemLang; + do { + if ( ( elemLang = documentIsHTML ? + elem.lang : + elem.getAttribute( "xml:lang" ) || elem.getAttribute( "lang" ) ) ) { + + elemLang = elemLang.toLowerCase(); + return elemLang === lang || elemLang.indexOf( lang + "-" ) === 0; + } + } while ( ( elem = elem.parentNode ) && elem.nodeType === 1 ); + return false; + }; + } ), + + // Miscellaneous + "target": function( elem ) { + var hash = window.location && window.location.hash; + return hash && hash.slice( 1 ) === elem.id; + }, + + "root": function( elem ) { + return elem === docElem; + }, + + "focus": function( elem ) { + return elem === document.activeElement && + ( !document.hasFocus || document.hasFocus() ) && + !!( elem.type || elem.href || ~elem.tabIndex ); + }, + + // Boolean properties + "enabled": createDisabledPseudo( false ), + "disabled": createDisabledPseudo( true ), + + "checked": function( elem ) { + + // In CSS3, :checked should return both checked and selected elements + // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked + var nodeName = elem.nodeName.toLowerCase(); + return ( nodeName === "input" && !!elem.checked ) || + ( nodeName === "option" && !!elem.selected ); + }, + + "selected": function( elem ) { + + // Accessing this property makes selected-by-default + // options in Safari work properly + if ( elem.parentNode ) { + // eslint-disable-next-line no-unused-expressions + elem.parentNode.selectedIndex; + } + + return elem.selected === true; + }, + + // Contents + "empty": function( elem ) { + + // http://www.w3.org/TR/selectors/#empty-pseudo + // :empty is negated by element (1) or content nodes (text: 3; cdata: 4; entity ref: 5), + // but not by others (comment: 8; processing instruction: 7; etc.) + // nodeType < 6 works because attributes (2) do not appear as children + for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { + if ( elem.nodeType < 6 ) { + return false; + } + } + return true; + }, + + "parent": function( elem ) { + return !Expr.pseudos[ "empty" ]( elem ); + }, + + // Element/input types + "header": function( elem ) { + return rheader.test( elem.nodeName ); + }, + + "input": function( elem ) { + return rinputs.test( elem.nodeName ); + }, + + "button": function( elem ) { + var name = elem.nodeName.toLowerCase(); + return name === "input" && elem.type === "button" || name === "button"; + }, + + "text": function( elem ) { + var attr; + return elem.nodeName.toLowerCase() === "input" && + elem.type === "text" && + + // Support: IE<8 + // New HTML5 attribute values (e.g., "search") appear with elem.type === "text" + ( ( attr = elem.getAttribute( "type" ) ) == null || + attr.toLowerCase() === "text" ); + }, + + // Position-in-collection + "first": createPositionalPseudo( function() { + return [ 0 ]; + } ), + + "last": createPositionalPseudo( function( _matchIndexes, length ) { + return [ length - 1 ]; + } ), + + "eq": createPositionalPseudo( function( _matchIndexes, length, argument ) { + return [ argument < 0 ? argument + length : argument ]; + } ), + + "even": createPositionalPseudo( function( matchIndexes, length ) { + var i = 0; + for ( ; i < length; i += 2 ) { + matchIndexes.push( i ); + } + return matchIndexes; + } ), + + "odd": createPositionalPseudo( function( matchIndexes, length ) { + var i = 1; + for ( ; i < length; i += 2 ) { + matchIndexes.push( i ); + } + return matchIndexes; + } ), + + "lt": createPositionalPseudo( function( matchIndexes, length, argument ) { + var i = argument < 0 ? + argument + length : + argument > length ? + length : + argument; + for ( ; --i >= 0; ) { + matchIndexes.push( i ); + } + return matchIndexes; + } ), + + "gt": createPositionalPseudo( function( matchIndexes, length, argument ) { + var i = argument < 0 ? argument + length : argument; + for ( ; ++i < length; ) { + matchIndexes.push( i ); + } + return matchIndexes; + } ) + } +}; + +Expr.pseudos[ "nth" ] = Expr.pseudos[ "eq" ]; + +// Add button/input type pseudos +for ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) { + Expr.pseudos[ i ] = createInputPseudo( i ); +} +for ( i in { submit: true, reset: true } ) { + Expr.pseudos[ i ] = createButtonPseudo( i ); +} + +// Easy API for creating new setFilters +function setFilters() {} +setFilters.prototype = Expr.filters = Expr.pseudos; +Expr.setFilters = new setFilters(); + +tokenize = Sizzle.tokenize = function( selector, parseOnly ) { + var matched, match, tokens, type, + soFar, groups, preFilters, + cached = tokenCache[ selector + " " ]; + + if ( cached ) { + return parseOnly ? 0 : cached.slice( 0 ); + } + + soFar = selector; + groups = []; + preFilters = Expr.preFilter; + + while ( soFar ) { + + // Comma and first run + if ( !matched || ( match = rcomma.exec( soFar ) ) ) { + if ( match ) { + + // Don't consume trailing commas as valid + soFar = soFar.slice( match[ 0 ].length ) || soFar; + } + groups.push( ( tokens = [] ) ); + } + + matched = false; + + // Combinators + if ( ( match = rcombinators.exec( soFar ) ) ) { + matched = match.shift(); + tokens.push( { + value: matched, + + // Cast descendant combinators to space + type: match[ 0 ].replace( rtrim, " " ) + } ); + soFar = soFar.slice( matched.length ); + } + + // Filters + for ( type in Expr.filter ) { + if ( ( match = matchExpr[ type ].exec( soFar ) ) && ( !preFilters[ type ] || + ( match = preFilters[ type ]( match ) ) ) ) { + matched = match.shift(); + tokens.push( { + value: matched, + type: type, + matches: match + } ); + soFar = soFar.slice( matched.length ); + } + } + + if ( !matched ) { + break; + } + } + + // Return the length of the invalid excess + // if we're just parsing + // Otherwise, throw an error or return tokens + return parseOnly ? + soFar.length : + soFar ? + Sizzle.error( selector ) : + + // Cache the tokens + tokenCache( selector, groups ).slice( 0 ); +}; + +function toSelector( tokens ) { + var i = 0, + len = tokens.length, + selector = ""; + for ( ; i < len; i++ ) { + selector += tokens[ i ].value; + } + return selector; +} + +function addCombinator( matcher, combinator, base ) { + var dir = combinator.dir, + skip = combinator.next, + key = skip || dir, + checkNonElements = base && key === "parentNode", + doneName = done++; + + return combinator.first ? + + // Check against closest ancestor/preceding element + function( elem, context, xml ) { + while ( ( elem = elem[ dir ] ) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + return matcher( elem, context, xml ); + } + } + return false; + } : + + // Check against all ancestor/preceding elements + function( elem, context, xml ) { + var oldCache, uniqueCache, outerCache, + newCache = [ dirruns, doneName ]; + + // We can't set arbitrary data on XML nodes, so they don't benefit from combinator caching + if ( xml ) { + while ( ( elem = elem[ dir ] ) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + if ( matcher( elem, context, xml ) ) { + return true; + } + } + } + } else { + while ( ( elem = elem[ dir ] ) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + outerCache = elem[ expando ] || ( elem[ expando ] = {} ); + + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ elem.uniqueID ] || + ( outerCache[ elem.uniqueID ] = {} ); + + if ( skip && skip === elem.nodeName.toLowerCase() ) { + elem = elem[ dir ] || elem; + } else if ( ( oldCache = uniqueCache[ key ] ) && + oldCache[ 0 ] === dirruns && oldCache[ 1 ] === doneName ) { + + // Assign to newCache so results back-propagate to previous elements + return ( newCache[ 2 ] = oldCache[ 2 ] ); + } else { + + // Reuse newcache so results back-propagate to previous elements + uniqueCache[ key ] = newCache; + + // A match means we're done; a fail means we have to keep checking + if ( ( newCache[ 2 ] = matcher( elem, context, xml ) ) ) { + return true; + } + } + } + } + } + return false; + }; +} + +function elementMatcher( matchers ) { + return matchers.length > 1 ? + function( elem, context, xml ) { + var i = matchers.length; + while ( i-- ) { + if ( !matchers[ i ]( elem, context, xml ) ) { + return false; + } + } + return true; + } : + matchers[ 0 ]; +} + +function multipleContexts( selector, contexts, results ) { + var i = 0, + len = contexts.length; + for ( ; i < len; i++ ) { + Sizzle( selector, contexts[ i ], results ); + } + return results; +} + +function condense( unmatched, map, filter, context, xml ) { + var elem, + newUnmatched = [], + i = 0, + len = unmatched.length, + mapped = map != null; + + for ( ; i < len; i++ ) { + if ( ( elem = unmatched[ i ] ) ) { + if ( !filter || filter( elem, context, xml ) ) { + newUnmatched.push( elem ); + if ( mapped ) { + map.push( i ); + } + } + } + } + + return newUnmatched; +} + +function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) { + if ( postFilter && !postFilter[ expando ] ) { + postFilter = setMatcher( postFilter ); + } + if ( postFinder && !postFinder[ expando ] ) { + postFinder = setMatcher( postFinder, postSelector ); + } + return markFunction( function( seed, results, context, xml ) { + var temp, i, elem, + preMap = [], + postMap = [], + preexisting = results.length, + + // Get initial elements from seed or context + elems = seed || multipleContexts( + selector || "*", + context.nodeType ? [ context ] : context, + [] + ), + + // Prefilter to get matcher input, preserving a map for seed-results synchronization + matcherIn = preFilter && ( seed || !selector ) ? + condense( elems, preMap, preFilter, context, xml ) : + elems, + + matcherOut = matcher ? + + // If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results, + postFinder || ( seed ? preFilter : preexisting || postFilter ) ? + + // ...intermediate processing is necessary + [] : + + // ...otherwise use results directly + results : + matcherIn; + + // Find primary matches + if ( matcher ) { + matcher( matcherIn, matcherOut, context, xml ); + } + + // Apply postFilter + if ( postFilter ) { + temp = condense( matcherOut, postMap ); + postFilter( temp, [], context, xml ); + + // Un-match failing elements by moving them back to matcherIn + i = temp.length; + while ( i-- ) { + if ( ( elem = temp[ i ] ) ) { + matcherOut[ postMap[ i ] ] = !( matcherIn[ postMap[ i ] ] = elem ); + } + } + } + + if ( seed ) { + if ( postFinder || preFilter ) { + if ( postFinder ) { + + // Get the final matcherOut by condensing this intermediate into postFinder contexts + temp = []; + i = matcherOut.length; + while ( i-- ) { + if ( ( elem = matcherOut[ i ] ) ) { + + // Restore matcherIn since elem is not yet a final match + temp.push( ( matcherIn[ i ] = elem ) ); + } + } + postFinder( null, ( matcherOut = [] ), temp, xml ); + } + + // Move matched elements from seed to results to keep them synchronized + i = matcherOut.length; + while ( i-- ) { + if ( ( elem = matcherOut[ i ] ) && + ( temp = postFinder ? indexOf( seed, elem ) : preMap[ i ] ) > -1 ) { + + seed[ temp ] = !( results[ temp ] = elem ); + } + } + } + + // Add elements to results, through postFinder if defined + } else { + matcherOut = condense( + matcherOut === results ? + matcherOut.splice( preexisting, matcherOut.length ) : + matcherOut + ); + if ( postFinder ) { + postFinder( null, results, matcherOut, xml ); + } else { + push.apply( results, matcherOut ); + } + } + } ); +} + +function matcherFromTokens( tokens ) { + var checkContext, matcher, j, + len = tokens.length, + leadingRelative = Expr.relative[ tokens[ 0 ].type ], + implicitRelative = leadingRelative || Expr.relative[ " " ], + i = leadingRelative ? 1 : 0, + + // The foundational matcher ensures that elements are reachable from top-level context(s) + matchContext = addCombinator( function( elem ) { + return elem === checkContext; + }, implicitRelative, true ), + matchAnyContext = addCombinator( function( elem ) { + return indexOf( checkContext, elem ) > -1; + }, implicitRelative, true ), + matchers = [ function( elem, context, xml ) { + var ret = ( !leadingRelative && ( xml || context !== outermostContext ) ) || ( + ( checkContext = context ).nodeType ? + matchContext( elem, context, xml ) : + matchAnyContext( elem, context, xml ) ); + + // Avoid hanging onto element (issue #299) + checkContext = null; + return ret; + } ]; + + for ( ; i < len; i++ ) { + if ( ( matcher = Expr.relative[ tokens[ i ].type ] ) ) { + matchers = [ addCombinator( elementMatcher( matchers ), matcher ) ]; + } else { + matcher = Expr.filter[ tokens[ i ].type ].apply( null, tokens[ i ].matches ); + + // Return special upon seeing a positional matcher + if ( matcher[ expando ] ) { + + // Find the next relative operator (if any) for proper handling + j = ++i; + for ( ; j < len; j++ ) { + if ( Expr.relative[ tokens[ j ].type ] ) { + break; + } + } + return setMatcher( + i > 1 && elementMatcher( matchers ), + i > 1 && toSelector( + + // If the preceding token was a descendant combinator, insert an implicit any-element `*` + tokens + .slice( 0, i - 1 ) + .concat( { value: tokens[ i - 2 ].type === " " ? "*" : "" } ) + ).replace( rtrim, "$1" ), + matcher, + i < j && matcherFromTokens( tokens.slice( i, j ) ), + j < len && matcherFromTokens( ( tokens = tokens.slice( j ) ) ), + j < len && toSelector( tokens ) + ); + } + matchers.push( matcher ); + } + } + + return elementMatcher( matchers ); +} + +function matcherFromGroupMatchers( elementMatchers, setMatchers ) { + var bySet = setMatchers.length > 0, + byElement = elementMatchers.length > 0, + superMatcher = function( seed, context, xml, results, outermost ) { + var elem, j, matcher, + matchedCount = 0, + i = "0", + unmatched = seed && [], + setMatched = [], + contextBackup = outermostContext, + + // We must always have either seed elements or outermost context + elems = seed || byElement && Expr.find[ "TAG" ]( "*", outermost ), + + // Use integer dirruns iff this is the outermost matcher + dirrunsUnique = ( dirruns += contextBackup == null ? 1 : Math.random() || 0.1 ), + len = elems.length; + + if ( outermost ) { + + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + outermostContext = context == document || context || outermost; + } + + // Add elements passing elementMatchers directly to results + // Support: IE<9, Safari + // Tolerate NodeList properties (IE: "length"; Safari: ) matching elements by id + for ( ; i !== len && ( elem = elems[ i ] ) != null; i++ ) { + if ( byElement && elem ) { + j = 0; + + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( !context && elem.ownerDocument != document ) { + setDocument( elem ); + xml = !documentIsHTML; + } + while ( ( matcher = elementMatchers[ j++ ] ) ) { + if ( matcher( elem, context || document, xml ) ) { + results.push( elem ); + break; + } + } + if ( outermost ) { + dirruns = dirrunsUnique; + } + } + + // Track unmatched elements for set filters + if ( bySet ) { + + // They will have gone through all possible matchers + if ( ( elem = !matcher && elem ) ) { + matchedCount--; + } + + // Lengthen the array for every element, matched or not + if ( seed ) { + unmatched.push( elem ); + } + } + } + + // `i` is now the count of elements visited above, and adding it to `matchedCount` + // makes the latter nonnegative. + matchedCount += i; + + // Apply set filters to unmatched elements + // NOTE: This can be skipped if there are no unmatched elements (i.e., `matchedCount` + // equals `i`), unless we didn't visit _any_ elements in the above loop because we have + // no element matchers and no seed. + // Incrementing an initially-string "0" `i` allows `i` to remain a string only in that + // case, which will result in a "00" `matchedCount` that differs from `i` but is also + // numerically zero. + if ( bySet && i !== matchedCount ) { + j = 0; + while ( ( matcher = setMatchers[ j++ ] ) ) { + matcher( unmatched, setMatched, context, xml ); + } + + if ( seed ) { + + // Reintegrate element matches to eliminate the need for sorting + if ( matchedCount > 0 ) { + while ( i-- ) { + if ( !( unmatched[ i ] || setMatched[ i ] ) ) { + setMatched[ i ] = pop.call( results ); + } + } + } + + // Discard index placeholder values to get only actual matches + setMatched = condense( setMatched ); + } + + // Add matches to results + push.apply( results, setMatched ); + + // Seedless set matches succeeding multiple successful matchers stipulate sorting + if ( outermost && !seed && setMatched.length > 0 && + ( matchedCount + setMatchers.length ) > 1 ) { + + Sizzle.uniqueSort( results ); + } + } + + // Override manipulation of globals by nested matchers + if ( outermost ) { + dirruns = dirrunsUnique; + outermostContext = contextBackup; + } + + return unmatched; + }; + + return bySet ? + markFunction( superMatcher ) : + superMatcher; +} + +compile = Sizzle.compile = function( selector, match /* Internal Use Only */ ) { + var i, + setMatchers = [], + elementMatchers = [], + cached = compilerCache[ selector + " " ]; + + if ( !cached ) { + + // Generate a function of recursive functions that can be used to check each element + if ( !match ) { + match = tokenize( selector ); + } + i = match.length; + while ( i-- ) { + cached = matcherFromTokens( match[ i ] ); + if ( cached[ expando ] ) { + setMatchers.push( cached ); + } else { + elementMatchers.push( cached ); + } + } + + // Cache the compiled function + cached = compilerCache( + selector, + matcherFromGroupMatchers( elementMatchers, setMatchers ) + ); + + // Save selector and tokenization + cached.selector = selector; + } + return cached; +}; + +/** + * A low-level selection function that works with Sizzle's compiled + * selector functions + * @param {String|Function} selector A selector or a pre-compiled + * selector function built with Sizzle.compile + * @param {Element} context + * @param {Array} [results] + * @param {Array} [seed] A set of elements to match against + */ +select = Sizzle.select = function( selector, context, results, seed ) { + var i, tokens, token, type, find, + compiled = typeof selector === "function" && selector, + match = !seed && tokenize( ( selector = compiled.selector || selector ) ); + + results = results || []; + + // Try to minimize operations if there is only one selector in the list and no seed + // (the latter of which guarantees us context) + if ( match.length === 1 ) { + + // Reduce context if the leading compound selector is an ID + tokens = match[ 0 ] = match[ 0 ].slice( 0 ); + if ( tokens.length > 2 && ( token = tokens[ 0 ] ).type === "ID" && + context.nodeType === 9 && documentIsHTML && Expr.relative[ tokens[ 1 ].type ] ) { + + context = ( Expr.find[ "ID" ]( token.matches[ 0 ] + .replace( runescape, funescape ), context ) || [] )[ 0 ]; + if ( !context ) { + return results; + + // Precompiled matchers will still verify ancestry, so step up a level + } else if ( compiled ) { + context = context.parentNode; + } + + selector = selector.slice( tokens.shift().value.length ); + } + + // Fetch a seed set for right-to-left matching + i = matchExpr[ "needsContext" ].test( selector ) ? 0 : tokens.length; + while ( i-- ) { + token = tokens[ i ]; + + // Abort if we hit a combinator + if ( Expr.relative[ ( type = token.type ) ] ) { + break; + } + if ( ( find = Expr.find[ type ] ) ) { + + // Search, expanding context for leading sibling combinators + if ( ( seed = find( + token.matches[ 0 ].replace( runescape, funescape ), + rsibling.test( tokens[ 0 ].type ) && testContext( context.parentNode ) || + context + ) ) ) { + + // If seed is empty or no tokens remain, we can return early + tokens.splice( i, 1 ); + selector = seed.length && toSelector( tokens ); + if ( !selector ) { + push.apply( results, seed ); + return results; + } + + break; + } + } + } + } + + // Compile and execute a filtering function if one is not provided + // Provide `match` to avoid retokenization if we modified the selector above + ( compiled || compile( selector, match ) )( + seed, + context, + !documentIsHTML, + results, + !context || rsibling.test( selector ) && testContext( context.parentNode ) || context + ); + return results; +}; + +// One-time assignments + +// Sort stability +support.sortStable = expando.split( "" ).sort( sortOrder ).join( "" ) === expando; + +// Support: Chrome 14-35+ +// Always assume duplicates if they aren't passed to the comparison function +support.detectDuplicates = !!hasDuplicate; + +// Initialize against the default document +setDocument(); + +// Support: Webkit<537.32 - Safari 6.0.3/Chrome 25 (fixed in Chrome 27) +// Detached nodes confoundingly follow *each other* +support.sortDetached = assert( function( el ) { + + // Should return 1, but returns 4 (following) + return el.compareDocumentPosition( document.createElement( "fieldset" ) ) & 1; +} ); + +// Support: IE<8 +// Prevent attribute/property "interpolation" +// https://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx +if ( !assert( function( el ) { + el.innerHTML = ""; + return el.firstChild.getAttribute( "href" ) === "#"; +} ) ) { + addHandle( "type|href|height|width", function( elem, name, isXML ) { + if ( !isXML ) { + return elem.getAttribute( name, name.toLowerCase() === "type" ? 1 : 2 ); + } + } ); +} + +// Support: IE<9 +// Use defaultValue in place of getAttribute("value") +if ( !support.attributes || !assert( function( el ) { + el.innerHTML = ""; + el.firstChild.setAttribute( "value", "" ); + return el.firstChild.getAttribute( "value" ) === ""; +} ) ) { + addHandle( "value", function( elem, _name, isXML ) { + if ( !isXML && elem.nodeName.toLowerCase() === "input" ) { + return elem.defaultValue; + } + } ); +} + +// Support: IE<9 +// Use getAttributeNode to fetch booleans when getAttribute lies +if ( !assert( function( el ) { + return el.getAttribute( "disabled" ) == null; +} ) ) { + addHandle( booleans, function( elem, name, isXML ) { + var val; + if ( !isXML ) { + return elem[ name ] === true ? name.toLowerCase() : + ( val = elem.getAttributeNode( name ) ) && val.specified ? + val.value : + null; + } + } ); +} + +return Sizzle; + +} )( window ); + + + +jQuery.find = Sizzle; +jQuery.expr = Sizzle.selectors; + +// Deprecated +jQuery.expr[ ":" ] = jQuery.expr.pseudos; +jQuery.uniqueSort = jQuery.unique = Sizzle.uniqueSort; +jQuery.text = Sizzle.getText; +jQuery.isXMLDoc = Sizzle.isXML; +jQuery.contains = Sizzle.contains; +jQuery.escapeSelector = Sizzle.escape; + + + + +var dir = function( elem, dir, until ) { + var matched = [], + truncate = until !== undefined; + + while ( ( elem = elem[ dir ] ) && elem.nodeType !== 9 ) { + if ( elem.nodeType === 1 ) { + if ( truncate && jQuery( elem ).is( until ) ) { + break; + } + matched.push( elem ); + } + } + return matched; +}; + + +var siblings = function( n, elem ) { + var matched = []; + + for ( ; n; n = n.nextSibling ) { + if ( n.nodeType === 1 && n !== elem ) { + matched.push( n ); + } + } + + return matched; +}; + + +var rneedsContext = jQuery.expr.match.needsContext; + + + +function nodeName( elem, name ) { + + return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase(); + +}; +var rsingleTag = ( /^<([a-z][^\/\0>:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i ); + + + +// Implement the identical functionality for filter and not +function winnow( elements, qualifier, not ) { + if ( isFunction( qualifier ) ) { + return jQuery.grep( elements, function( elem, i ) { + return !!qualifier.call( elem, i, elem ) !== not; + } ); + } + + // Single element + if ( qualifier.nodeType ) { + return jQuery.grep( elements, function( elem ) { + return ( elem === qualifier ) !== not; + } ); + } + + // Arraylike of elements (jQuery, arguments, Array) + if ( typeof qualifier !== "string" ) { + return jQuery.grep( elements, function( elem ) { + return ( indexOf.call( qualifier, elem ) > -1 ) !== not; + } ); + } + + // Filtered directly for both simple and complex selectors + return jQuery.filter( qualifier, elements, not ); +} + +jQuery.filter = function( expr, elems, not ) { + var elem = elems[ 0 ]; + + if ( not ) { + expr = ":not(" + expr + ")"; + } + + if ( elems.length === 1 && elem.nodeType === 1 ) { + return jQuery.find.matchesSelector( elem, expr ) ? [ elem ] : []; + } + + return jQuery.find.matches( expr, jQuery.grep( elems, function( elem ) { + return elem.nodeType === 1; + } ) ); +}; + +jQuery.fn.extend( { + find: function( selector ) { + var i, ret, + len = this.length, + self = this; + + if ( typeof selector !== "string" ) { + return this.pushStack( jQuery( selector ).filter( function() { + for ( i = 0; i < len; i++ ) { + if ( jQuery.contains( self[ i ], this ) ) { + return true; + } + } + } ) ); + } + + ret = this.pushStack( [] ); + + for ( i = 0; i < len; i++ ) { + jQuery.find( selector, self[ i ], ret ); + } + + return len > 1 ? jQuery.uniqueSort( ret ) : ret; + }, + filter: function( selector ) { + return this.pushStack( winnow( this, selector || [], false ) ); + }, + not: function( selector ) { + return this.pushStack( winnow( this, selector || [], true ) ); + }, + is: function( selector ) { + return !!winnow( + this, + + // If this is a positional/relative selector, check membership in the returned set + // so $("p:first").is("p:last") won't return true for a doc with two "p". + typeof selector === "string" && rneedsContext.test( selector ) ? + jQuery( selector ) : + selector || [], + false + ).length; + } +} ); + + +// Initialize a jQuery object + + +// A central reference to the root jQuery(document) +var rootjQuery, + + // A simple way to check for HTML strings + // Prioritize #id over to avoid XSS via location.hash (#9521) + // Strict HTML recognition (#11290: must start with <) + // Shortcut simple #id case for speed + rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]+))$/, + + init = jQuery.fn.init = function( selector, context, root ) { + var match, elem; + + // HANDLE: $(""), $(null), $(undefined), $(false) + if ( !selector ) { + return this; + } + + // Method init() accepts an alternate rootjQuery + // so migrate can support jQuery.sub (gh-2101) + root = root || rootjQuery; + + // Handle HTML strings + if ( typeof selector === "string" ) { + if ( selector[ 0 ] === "<" && + selector[ selector.length - 1 ] === ">" && + selector.length >= 3 ) { + + // Assume that strings that start and end with <> are HTML and skip the regex check + match = [ null, selector, null ]; + + } else { + match = rquickExpr.exec( selector ); + } + + // Match html or make sure no context is specified for #id + if ( match && ( match[ 1 ] || !context ) ) { + + // HANDLE: $(html) -> $(array) + if ( match[ 1 ] ) { + context = context instanceof jQuery ? context[ 0 ] : context; + + // Option to run scripts is true for back-compat + // Intentionally let the error be thrown if parseHTML is not present + jQuery.merge( this, jQuery.parseHTML( + match[ 1 ], + context && context.nodeType ? context.ownerDocument || context : document, + true + ) ); + + // HANDLE: $(html, props) + if ( rsingleTag.test( match[ 1 ] ) && jQuery.isPlainObject( context ) ) { + for ( match in context ) { + + // Properties of context are called as methods if possible + if ( isFunction( this[ match ] ) ) { + this[ match ]( context[ match ] ); + + // ...and otherwise set as attributes + } else { + this.attr( match, context[ match ] ); + } + } + } + + return this; + + // HANDLE: $(#id) + } else { + elem = document.getElementById( match[ 2 ] ); + + if ( elem ) { + + // Inject the element directly into the jQuery object + this[ 0 ] = elem; + this.length = 1; + } + return this; + } + + // HANDLE: $(expr, $(...)) + } else if ( !context || context.jquery ) { + return ( context || root ).find( selector ); + + // HANDLE: $(expr, context) + // (which is just equivalent to: $(context).find(expr) + } else { + return this.constructor( context ).find( selector ); + } + + // HANDLE: $(DOMElement) + } else if ( selector.nodeType ) { + this[ 0 ] = selector; + this.length = 1; + return this; + + // HANDLE: $(function) + // Shortcut for document ready + } else if ( isFunction( selector ) ) { + return root.ready !== undefined ? + root.ready( selector ) : + + // Execute immediately if ready is not present + selector( jQuery ); + } + + return jQuery.makeArray( selector, this ); + }; + +// Give the init function the jQuery prototype for later instantiation +init.prototype = jQuery.fn; + +// Initialize central reference +rootjQuery = jQuery( document ); + + +var rparentsprev = /^(?:parents|prev(?:Until|All))/, + + // Methods guaranteed to produce a unique set when starting from a unique set + guaranteedUnique = { + children: true, + contents: true, + next: true, + prev: true + }; + +jQuery.fn.extend( { + has: function( target ) { + var targets = jQuery( target, this ), + l = targets.length; + + return this.filter( function() { + var i = 0; + for ( ; i < l; i++ ) { + if ( jQuery.contains( this, targets[ i ] ) ) { + return true; + } + } + } ); + }, + + closest: function( selectors, context ) { + var cur, + i = 0, + l = this.length, + matched = [], + targets = typeof selectors !== "string" && jQuery( selectors ); + + // Positional selectors never match, since there's no _selection_ context + if ( !rneedsContext.test( selectors ) ) { + for ( ; i < l; i++ ) { + for ( cur = this[ i ]; cur && cur !== context; cur = cur.parentNode ) { + + // Always skip document fragments + if ( cur.nodeType < 11 && ( targets ? + targets.index( cur ) > -1 : + + // Don't pass non-elements to Sizzle + cur.nodeType === 1 && + jQuery.find.matchesSelector( cur, selectors ) ) ) { + + matched.push( cur ); + break; + } + } + } + } + + return this.pushStack( matched.length > 1 ? jQuery.uniqueSort( matched ) : matched ); + }, + + // Determine the position of an element within the set + index: function( elem ) { + + // No argument, return index in parent + if ( !elem ) { + return ( this[ 0 ] && this[ 0 ].parentNode ) ? this.first().prevAll().length : -1; + } + + // Index in selector + if ( typeof elem === "string" ) { + return indexOf.call( jQuery( elem ), this[ 0 ] ); + } + + // Locate the position of the desired element + return indexOf.call( this, + + // If it receives a jQuery object, the first element is used + elem.jquery ? elem[ 0 ] : elem + ); + }, + + add: function( selector, context ) { + return this.pushStack( + jQuery.uniqueSort( + jQuery.merge( this.get(), jQuery( selector, context ) ) + ) + ); + }, + + addBack: function( selector ) { + return this.add( selector == null ? + this.prevObject : this.prevObject.filter( selector ) + ); + } +} ); + +function sibling( cur, dir ) { + while ( ( cur = cur[ dir ] ) && cur.nodeType !== 1 ) {} + return cur; +} + +jQuery.each( { + parent: function( elem ) { + var parent = elem.parentNode; + return parent && parent.nodeType !== 11 ? parent : null; + }, + parents: function( elem ) { + return dir( elem, "parentNode" ); + }, + parentsUntil: function( elem, _i, until ) { + return dir( elem, "parentNode", until ); + }, + next: function( elem ) { + return sibling( elem, "nextSibling" ); + }, + prev: function( elem ) { + return sibling( elem, "previousSibling" ); + }, + nextAll: function( elem ) { + return dir( elem, "nextSibling" ); + }, + prevAll: function( elem ) { + return dir( elem, "previousSibling" ); + }, + nextUntil: function( elem, _i, until ) { + return dir( elem, "nextSibling", until ); + }, + prevUntil: function( elem, _i, until ) { + return dir( elem, "previousSibling", until ); + }, + siblings: function( elem ) { + return siblings( ( elem.parentNode || {} ).firstChild, elem ); + }, + children: function( elem ) { + return siblings( elem.firstChild ); + }, + contents: function( elem ) { + if ( elem.contentDocument != null && + + // Support: IE 11+ + // elements with no `data` attribute has an object + // `contentDocument` with a `null` prototype. + getProto( elem.contentDocument ) ) { + + return elem.contentDocument; + } + + // Support: IE 9 - 11 only, iOS 7 only, Android Browser <=4.3 only + // Treat the template element as a regular one in browsers that + // don't support it. + if ( nodeName( elem, "template" ) ) { + elem = elem.content || elem; + } + + return jQuery.merge( [], elem.childNodes ); + } +}, function( name, fn ) { + jQuery.fn[ name ] = function( until, selector ) { + var matched = jQuery.map( this, fn, until ); + + if ( name.slice( -5 ) !== "Until" ) { + selector = until; + } + + if ( selector && typeof selector === "string" ) { + matched = jQuery.filter( selector, matched ); + } + + if ( this.length > 1 ) { + + // Remove duplicates + if ( !guaranteedUnique[ name ] ) { + jQuery.uniqueSort( matched ); + } + + // Reverse order for parents* and prev-derivatives + if ( rparentsprev.test( name ) ) { + matched.reverse(); + } + } + + return this.pushStack( matched ); + }; +} ); +var rnothtmlwhite = ( /[^\x20\t\r\n\f]+/g ); + + + +// Convert String-formatted options into Object-formatted ones +function createOptions( options ) { + var object = {}; + jQuery.each( options.match( rnothtmlwhite ) || [], function( _, flag ) { + object[ flag ] = true; + } ); + return object; +} + +/* + * Create a callback list using the following parameters: + * + * options: an optional list of space-separated options that will change how + * the callback list behaves or a more traditional option object + * + * By default a callback list will act like an event callback list and can be + * "fired" multiple times. + * + * Possible options: + * + * once: will ensure the callback list can only be fired once (like a Deferred) + * + * memory: will keep track of previous values and will call any callback added + * after the list has been fired right away with the latest "memorized" + * values (like a Deferred) + * + * unique: will ensure a callback can only be added once (no duplicate in the list) + * + * stopOnFalse: interrupt callings when a callback returns false + * + */ +jQuery.Callbacks = function( options ) { + + // Convert options from String-formatted to Object-formatted if needed + // (we check in cache first) + options = typeof options === "string" ? + createOptions( options ) : + jQuery.extend( {}, options ); + + var // Flag to know if list is currently firing + firing, + + // Last fire value for non-forgettable lists + memory, + + // Flag to know if list was already fired + fired, + + // Flag to prevent firing + locked, + + // Actual callback list + list = [], + + // Queue of execution data for repeatable lists + queue = [], + + // Index of currently firing callback (modified by add/remove as needed) + firingIndex = -1, + + // Fire callbacks + fire = function() { + + // Enforce single-firing + locked = locked || options.once; + + // Execute callbacks for all pending executions, + // respecting firingIndex overrides and runtime changes + fired = firing = true; + for ( ; queue.length; firingIndex = -1 ) { + memory = queue.shift(); + while ( ++firingIndex < list.length ) { + + // Run callback and check for early termination + if ( list[ firingIndex ].apply( memory[ 0 ], memory[ 1 ] ) === false && + options.stopOnFalse ) { + + // Jump to end and forget the data so .add doesn't re-fire + firingIndex = list.length; + memory = false; + } + } + } + + // Forget the data if we're done with it + if ( !options.memory ) { + memory = false; + } + + firing = false; + + // Clean up if we're done firing for good + if ( locked ) { + + // Keep an empty list if we have data for future add calls + if ( memory ) { + list = []; + + // Otherwise, this object is spent + } else { + list = ""; + } + } + }, + + // Actual Callbacks object + self = { + + // Add a callback or a collection of callbacks to the list + add: function() { + if ( list ) { + + // If we have memory from a past run, we should fire after adding + if ( memory && !firing ) { + firingIndex = list.length - 1; + queue.push( memory ); + } + + ( function add( args ) { + jQuery.each( args, function( _, arg ) { + if ( isFunction( arg ) ) { + if ( !options.unique || !self.has( arg ) ) { + list.push( arg ); + } + } else if ( arg && arg.length && toType( arg ) !== "string" ) { + + // Inspect recursively + add( arg ); + } + } ); + } )( arguments ); + + if ( memory && !firing ) { + fire(); + } + } + return this; + }, + + // Remove a callback from the list + remove: function() { + jQuery.each( arguments, function( _, arg ) { + var index; + while ( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) { + list.splice( index, 1 ); + + // Handle firing indexes + if ( index <= firingIndex ) { + firingIndex--; + } + } + } ); + return this; + }, + + // Check if a given callback is in the list. + // If no argument is given, return whether or not list has callbacks attached. + has: function( fn ) { + return fn ? + jQuery.inArray( fn, list ) > -1 : + list.length > 0; + }, + + // Remove all callbacks from the list + empty: function() { + if ( list ) { + list = []; + } + return this; + }, + + // Disable .fire and .add + // Abort any current/pending executions + // Clear all callbacks and values + disable: function() { + locked = queue = []; + list = memory = ""; + return this; + }, + disabled: function() { + return !list; + }, + + // Disable .fire + // Also disable .add unless we have memory (since it would have no effect) + // Abort any pending executions + lock: function() { + locked = queue = []; + if ( !memory && !firing ) { + list = memory = ""; + } + return this; + }, + locked: function() { + return !!locked; + }, + + // Call all callbacks with the given context and arguments + fireWith: function( context, args ) { + if ( !locked ) { + args = args || []; + args = [ context, args.slice ? args.slice() : args ]; + queue.push( args ); + if ( !firing ) { + fire(); + } + } + return this; + }, + + // Call all the callbacks with the given arguments + fire: function() { + self.fireWith( this, arguments ); + return this; + }, + + // To know if the callbacks have already been called at least once + fired: function() { + return !!fired; + } + }; + + return self; +}; + + +function Identity( v ) { + return v; +} +function Thrower( ex ) { + throw ex; +} + +function adoptValue( value, resolve, reject, noValue ) { + var method; + + try { + + // Check for promise aspect first to privilege synchronous behavior + if ( value && isFunction( ( method = value.promise ) ) ) { + method.call( value ).done( resolve ).fail( reject ); + + // Other thenables + } else if ( value && isFunction( ( method = value.then ) ) ) { + method.call( value, resolve, reject ); + + // Other non-thenables + } else { + + // Control `resolve` arguments by letting Array#slice cast boolean `noValue` to integer: + // * false: [ value ].slice( 0 ) => resolve( value ) + // * true: [ value ].slice( 1 ) => resolve() + resolve.apply( undefined, [ value ].slice( noValue ) ); + } + + // For Promises/A+, convert exceptions into rejections + // Since jQuery.when doesn't unwrap thenables, we can skip the extra checks appearing in + // Deferred#then to conditionally suppress rejection. + } catch ( value ) { + + // Support: Android 4.0 only + // Strict mode functions invoked without .call/.apply get global-object context + reject.apply( undefined, [ value ] ); + } +} + +jQuery.extend( { + + Deferred: function( func ) { + var tuples = [ + + // action, add listener, callbacks, + // ... .then handlers, argument index, [final state] + [ "notify", "progress", jQuery.Callbacks( "memory" ), + jQuery.Callbacks( "memory" ), 2 ], + [ "resolve", "done", jQuery.Callbacks( "once memory" ), + jQuery.Callbacks( "once memory" ), 0, "resolved" ], + [ "reject", "fail", jQuery.Callbacks( "once memory" ), + jQuery.Callbacks( "once memory" ), 1, "rejected" ] + ], + state = "pending", + promise = { + state: function() { + return state; + }, + always: function() { + deferred.done( arguments ).fail( arguments ); + return this; + }, + "catch": function( fn ) { + return promise.then( null, fn ); + }, + + // Keep pipe for back-compat + pipe: function( /* fnDone, fnFail, fnProgress */ ) { + var fns = arguments; + + return jQuery.Deferred( function( newDefer ) { + jQuery.each( tuples, function( _i, tuple ) { + + // Map tuples (progress, done, fail) to arguments (done, fail, progress) + var fn = isFunction( fns[ tuple[ 4 ] ] ) && fns[ tuple[ 4 ] ]; + + // deferred.progress(function() { bind to newDefer or newDefer.notify }) + // deferred.done(function() { bind to newDefer or newDefer.resolve }) + // deferred.fail(function() { bind to newDefer or newDefer.reject }) + deferred[ tuple[ 1 ] ]( function() { + var returned = fn && fn.apply( this, arguments ); + if ( returned && isFunction( returned.promise ) ) { + returned.promise() + .progress( newDefer.notify ) + .done( newDefer.resolve ) + .fail( newDefer.reject ); + } else { + newDefer[ tuple[ 0 ] + "With" ]( + this, + fn ? [ returned ] : arguments + ); + } + } ); + } ); + fns = null; + } ).promise(); + }, + then: function( onFulfilled, onRejected, onProgress ) { + var maxDepth = 0; + function resolve( depth, deferred, handler, special ) { + return function() { + var that = this, + args = arguments, + mightThrow = function() { + var returned, then; + + // Support: Promises/A+ section 2.3.3.3.3 + // https://promisesaplus.com/#point-59 + // Ignore double-resolution attempts + if ( depth < maxDepth ) { + return; + } + + returned = handler.apply( that, args ); + + // Support: Promises/A+ section 2.3.1 + // https://promisesaplus.com/#point-48 + if ( returned === deferred.promise() ) { + throw new TypeError( "Thenable self-resolution" ); + } + + // Support: Promises/A+ sections 2.3.3.1, 3.5 + // https://promisesaplus.com/#point-54 + // https://promisesaplus.com/#point-75 + // Retrieve `then` only once + then = returned && + + // Support: Promises/A+ section 2.3.4 + // https://promisesaplus.com/#point-64 + // Only check objects and functions for thenability + ( typeof returned === "object" || + typeof returned === "function" ) && + returned.then; + + // Handle a returned thenable + if ( isFunction( then ) ) { + + // Special processors (notify) just wait for resolution + if ( special ) { + then.call( + returned, + resolve( maxDepth, deferred, Identity, special ), + resolve( maxDepth, deferred, Thrower, special ) + ); + + // Normal processors (resolve) also hook into progress + } else { + + // ...and disregard older resolution values + maxDepth++; + + then.call( + returned, + resolve( maxDepth, deferred, Identity, special ), + resolve( maxDepth, deferred, Thrower, special ), + resolve( maxDepth, deferred, Identity, + deferred.notifyWith ) + ); + } + + // Handle all other returned values + } else { + + // Only substitute handlers pass on context + // and multiple values (non-spec behavior) + if ( handler !== Identity ) { + that = undefined; + args = [ returned ]; + } + + // Process the value(s) + // Default process is resolve + ( special || deferred.resolveWith )( that, args ); + } + }, + + // Only normal processors (resolve) catch and reject exceptions + process = special ? + mightThrow : + function() { + try { + mightThrow(); + } catch ( e ) { + + if ( jQuery.Deferred.exceptionHook ) { + jQuery.Deferred.exceptionHook( e, + process.stackTrace ); + } + + // Support: Promises/A+ section 2.3.3.3.4.1 + // https://promisesaplus.com/#point-61 + // Ignore post-resolution exceptions + if ( depth + 1 >= maxDepth ) { + + // Only substitute handlers pass on context + // and multiple values (non-spec behavior) + if ( handler !== Thrower ) { + that = undefined; + args = [ e ]; + } + + deferred.rejectWith( that, args ); + } + } + }; + + // Support: Promises/A+ section 2.3.3.3.1 + // https://promisesaplus.com/#point-57 + // Re-resolve promises immediately to dodge false rejection from + // subsequent errors + if ( depth ) { + process(); + } else { + + // Call an optional hook to record the stack, in case of exception + // since it's otherwise lost when execution goes async + if ( jQuery.Deferred.getStackHook ) { + process.stackTrace = jQuery.Deferred.getStackHook(); + } + window.setTimeout( process ); + } + }; + } + + return jQuery.Deferred( function( newDefer ) { + + // progress_handlers.add( ... ) + tuples[ 0 ][ 3 ].add( + resolve( + 0, + newDefer, + isFunction( onProgress ) ? + onProgress : + Identity, + newDefer.notifyWith + ) + ); + + // fulfilled_handlers.add( ... ) + tuples[ 1 ][ 3 ].add( + resolve( + 0, + newDefer, + isFunction( onFulfilled ) ? + onFulfilled : + Identity + ) + ); + + // rejected_handlers.add( ... ) + tuples[ 2 ][ 3 ].add( + resolve( + 0, + newDefer, + isFunction( onRejected ) ? + onRejected : + Thrower + ) + ); + } ).promise(); + }, + + // Get a promise for this deferred + // If obj is provided, the promise aspect is added to the object + promise: function( obj ) { + return obj != null ? jQuery.extend( obj, promise ) : promise; + } + }, + deferred = {}; + + // Add list-specific methods + jQuery.each( tuples, function( i, tuple ) { + var list = tuple[ 2 ], + stateString = tuple[ 5 ]; + + // promise.progress = list.add + // promise.done = list.add + // promise.fail = list.add + promise[ tuple[ 1 ] ] = list.add; + + // Handle state + if ( stateString ) { + list.add( + function() { + + // state = "resolved" (i.e., fulfilled) + // state = "rejected" + state = stateString; + }, + + // rejected_callbacks.disable + // fulfilled_callbacks.disable + tuples[ 3 - i ][ 2 ].disable, + + // rejected_handlers.disable + // fulfilled_handlers.disable + tuples[ 3 - i ][ 3 ].disable, + + // progress_callbacks.lock + tuples[ 0 ][ 2 ].lock, + + // progress_handlers.lock + tuples[ 0 ][ 3 ].lock + ); + } + + // progress_handlers.fire + // fulfilled_handlers.fire + // rejected_handlers.fire + list.add( tuple[ 3 ].fire ); + + // deferred.notify = function() { deferred.notifyWith(...) } + // deferred.resolve = function() { deferred.resolveWith(...) } + // deferred.reject = function() { deferred.rejectWith(...) } + deferred[ tuple[ 0 ] ] = function() { + deferred[ tuple[ 0 ] + "With" ]( this === deferred ? undefined : this, arguments ); + return this; + }; + + // deferred.notifyWith = list.fireWith + // deferred.resolveWith = list.fireWith + // deferred.rejectWith = list.fireWith + deferred[ tuple[ 0 ] + "With" ] = list.fireWith; + } ); + + // Make the deferred a promise + promise.promise( deferred ); + + // Call given func if any + if ( func ) { + func.call( deferred, deferred ); + } + + // All done! + return deferred; + }, + + // Deferred helper + when: function( singleValue ) { + var + + // count of uncompleted subordinates + remaining = arguments.length, + + // count of unprocessed arguments + i = remaining, + + // subordinate fulfillment data + resolveContexts = Array( i ), + resolveValues = slice.call( arguments ), + + // the master Deferred + master = jQuery.Deferred(), + + // subordinate callback factory + updateFunc = function( i ) { + return function( value ) { + resolveContexts[ i ] = this; + resolveValues[ i ] = arguments.length > 1 ? slice.call( arguments ) : value; + if ( !( --remaining ) ) { + master.resolveWith( resolveContexts, resolveValues ); + } + }; + }; + + // Single- and empty arguments are adopted like Promise.resolve + if ( remaining <= 1 ) { + adoptValue( singleValue, master.done( updateFunc( i ) ).resolve, master.reject, + !remaining ); + + // Use .then() to unwrap secondary thenables (cf. gh-3000) + if ( master.state() === "pending" || + isFunction( resolveValues[ i ] && resolveValues[ i ].then ) ) { + + return master.then(); + } + } + + // Multiple arguments are aggregated like Promise.all array elements + while ( i-- ) { + adoptValue( resolveValues[ i ], updateFunc( i ), master.reject ); + } + + return master.promise(); + } +} ); + + +// These usually indicate a programmer mistake during development, +// warn about them ASAP rather than swallowing them by default. +var rerrorNames = /^(Eval|Internal|Range|Reference|Syntax|Type|URI)Error$/; + +jQuery.Deferred.exceptionHook = function( error, stack ) { + + // Support: IE 8 - 9 only + // Console exists when dev tools are open, which can happen at any time + if ( window.console && window.console.warn && error && rerrorNames.test( error.name ) ) { + window.console.warn( "jQuery.Deferred exception: " + error.message, error.stack, stack ); + } +}; + + + + +jQuery.readyException = function( error ) { + window.setTimeout( function() { + throw error; + } ); +}; + + + + +// The deferred used on DOM ready +var readyList = jQuery.Deferred(); + +jQuery.fn.ready = function( fn ) { + + readyList + .then( fn ) + + // Wrap jQuery.readyException in a function so that the lookup + // happens at the time of error handling instead of callback + // registration. + .catch( function( error ) { + jQuery.readyException( error ); + } ); + + return this; +}; + +jQuery.extend( { + + // Is the DOM ready to be used? Set to true once it occurs. + isReady: false, + + // A counter to track how many items to wait for before + // the ready event fires. See #6781 + readyWait: 1, + + // Handle when the DOM is ready + ready: function( wait ) { + + // Abort if there are pending holds or we're already ready + if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) { + return; + } + + // Remember that the DOM is ready + jQuery.isReady = true; + + // If a normal DOM Ready event fired, decrement, and wait if need be + if ( wait !== true && --jQuery.readyWait > 0 ) { + return; + } + + // If there are functions bound, to execute + readyList.resolveWith( document, [ jQuery ] ); + } +} ); + +jQuery.ready.then = readyList.then; + +// The ready event handler and self cleanup method +function completed() { + document.removeEventListener( "DOMContentLoaded", completed ); + window.removeEventListener( "load", completed ); + jQuery.ready(); +} + +// Catch cases where $(document).ready() is called +// after the browser event has already occurred. +// Support: IE <=9 - 10 only +// Older IE sometimes signals "interactive" too soon +if ( document.readyState === "complete" || + ( document.readyState !== "loading" && !document.documentElement.doScroll ) ) { + + // Handle it asynchronously to allow scripts the opportunity to delay ready + window.setTimeout( jQuery.ready ); + +} else { + + // Use the handy event callback + document.addEventListener( "DOMContentLoaded", completed ); + + // A fallback to window.onload, that will always work + window.addEventListener( "load", completed ); +} + + + + +// Multifunctional method to get and set values of a collection +// The value/s can optionally be executed if it's a function +var access = function( elems, fn, key, value, chainable, emptyGet, raw ) { + var i = 0, + len = elems.length, + bulk = key == null; + + // Sets many values + if ( toType( key ) === "object" ) { + chainable = true; + for ( i in key ) { + access( elems, fn, i, key[ i ], true, emptyGet, raw ); + } + + // Sets one value + } else if ( value !== undefined ) { + chainable = true; + + if ( !isFunction( value ) ) { + raw = true; + } + + if ( bulk ) { + + // Bulk operations run against the entire set + if ( raw ) { + fn.call( elems, value ); + fn = null; + + // ...except when executing function values + } else { + bulk = fn; + fn = function( elem, _key, value ) { + return bulk.call( jQuery( elem ), value ); + }; + } + } + + if ( fn ) { + for ( ; i < len; i++ ) { + fn( + elems[ i ], key, raw ? + value : + value.call( elems[ i ], i, fn( elems[ i ], key ) ) + ); + } + } + } + + if ( chainable ) { + return elems; + } + + // Gets + if ( bulk ) { + return fn.call( elems ); + } + + return len ? fn( elems[ 0 ], key ) : emptyGet; +}; + + +// Matches dashed string for camelizing +var rmsPrefix = /^-ms-/, + rdashAlpha = /-([a-z])/g; + +// Used by camelCase as callback to replace() +function fcamelCase( _all, letter ) { + return letter.toUpperCase(); +} + +// Convert dashed to camelCase; used by the css and data modules +// Support: IE <=9 - 11, Edge 12 - 15 +// Microsoft forgot to hump their vendor prefix (#9572) +function camelCase( string ) { + return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase ); +} +var acceptData = function( owner ) { + + // Accepts only: + // - Node + // - Node.ELEMENT_NODE + // - Node.DOCUMENT_NODE + // - Object + // - Any + return owner.nodeType === 1 || owner.nodeType === 9 || !( +owner.nodeType ); +}; + + + + +function Data() { + this.expando = jQuery.expando + Data.uid++; +} + +Data.uid = 1; + +Data.prototype = { + + cache: function( owner ) { + + // Check if the owner object already has a cache + var value = owner[ this.expando ]; + + // If not, create one + if ( !value ) { + value = {}; + + // We can accept data for non-element nodes in modern browsers, + // but we should not, see #8335. + // Always return an empty object. + if ( acceptData( owner ) ) { + + // If it is a node unlikely to be stringify-ed or looped over + // use plain assignment + if ( owner.nodeType ) { + owner[ this.expando ] = value; + + // Otherwise secure it in a non-enumerable property + // configurable must be true to allow the property to be + // deleted when data is removed + } else { + Object.defineProperty( owner, this.expando, { + value: value, + configurable: true + } ); + } + } + } + + return value; + }, + set: function( owner, data, value ) { + var prop, + cache = this.cache( owner ); + + // Handle: [ owner, key, value ] args + // Always use camelCase key (gh-2257) + if ( typeof data === "string" ) { + cache[ camelCase( data ) ] = value; + + // Handle: [ owner, { properties } ] args + } else { + + // Copy the properties one-by-one to the cache object + for ( prop in data ) { + cache[ camelCase( prop ) ] = data[ prop ]; + } + } + return cache; + }, + get: function( owner, key ) { + return key === undefined ? + this.cache( owner ) : + + // Always use camelCase key (gh-2257) + owner[ this.expando ] && owner[ this.expando ][ camelCase( key ) ]; + }, + access: function( owner, key, value ) { + + // In cases where either: + // + // 1. No key was specified + // 2. A string key was specified, but no value provided + // + // Take the "read" path and allow the get method to determine + // which value to return, respectively either: + // + // 1. The entire cache object + // 2. The data stored at the key + // + if ( key === undefined || + ( ( key && typeof key === "string" ) && value === undefined ) ) { + + return this.get( owner, key ); + } + + // When the key is not a string, or both a key and value + // are specified, set or extend (existing objects) with either: + // + // 1. An object of properties + // 2. A key and value + // + this.set( owner, key, value ); + + // Since the "set" path can have two possible entry points + // return the expected data based on which path was taken[*] + return value !== undefined ? value : key; + }, + remove: function( owner, key ) { + var i, + cache = owner[ this.expando ]; + + if ( cache === undefined ) { + return; + } + + if ( key !== undefined ) { + + // Support array or space separated string of keys + if ( Array.isArray( key ) ) { + + // If key is an array of keys... + // We always set camelCase keys, so remove that. + key = key.map( camelCase ); + } else { + key = camelCase( key ); + + // If a key with the spaces exists, use it. + // Otherwise, create an array by matching non-whitespace + key = key in cache ? + [ key ] : + ( key.match( rnothtmlwhite ) || [] ); + } + + i = key.length; + + while ( i-- ) { + delete cache[ key[ i ] ]; + } + } + + // Remove the expando if there's no more data + if ( key === undefined || jQuery.isEmptyObject( cache ) ) { + + // Support: Chrome <=35 - 45 + // Webkit & Blink performance suffers when deleting properties + // from DOM nodes, so set to undefined instead + // https://bugs.chromium.org/p/chromium/issues/detail?id=378607 (bug restricted) + if ( owner.nodeType ) { + owner[ this.expando ] = undefined; + } else { + delete owner[ this.expando ]; + } + } + }, + hasData: function( owner ) { + var cache = owner[ this.expando ]; + return cache !== undefined && !jQuery.isEmptyObject( cache ); + } +}; +var dataPriv = new Data(); + +var dataUser = new Data(); + + + +// Implementation Summary +// +// 1. Enforce API surface and semantic compatibility with 1.9.x branch +// 2. Improve the module's maintainability by reducing the storage +// paths to a single mechanism. +// 3. Use the same single mechanism to support "private" and "user" data. +// 4. _Never_ expose "private" data to user code (TODO: Drop _data, _removeData) +// 5. Avoid exposing implementation details on user objects (eg. expando properties) +// 6. Provide a clear path for implementation upgrade to WeakMap in 2014 + +var rbrace = /^(?:\{[\w\W]*\}|\[[\w\W]*\])$/, + rmultiDash = /[A-Z]/g; + +function getData( data ) { + if ( data === "true" ) { + return true; + } + + if ( data === "false" ) { + return false; + } + + if ( data === "null" ) { + return null; + } + + // Only convert to a number if it doesn't change the string + if ( data === +data + "" ) { + return +data; + } + + if ( rbrace.test( data ) ) { + return JSON.parse( data ); + } + + return data; +} + +function dataAttr( elem, key, data ) { + var name; + + // If nothing was found internally, try to fetch any + // data from the HTML5 data-* attribute + if ( data === undefined && elem.nodeType === 1 ) { + name = "data-" + key.replace( rmultiDash, "-$&" ).toLowerCase(); + data = elem.getAttribute( name ); + + if ( typeof data === "string" ) { + try { + data = getData( data ); + } catch ( e ) {} + + // Make sure we set the data so it isn't changed later + dataUser.set( elem, key, data ); + } else { + data = undefined; + } + } + return data; +} + +jQuery.extend( { + hasData: function( elem ) { + return dataUser.hasData( elem ) || dataPriv.hasData( elem ); + }, + + data: function( elem, name, data ) { + return dataUser.access( elem, name, data ); + }, + + removeData: function( elem, name ) { + dataUser.remove( elem, name ); + }, + + // TODO: Now that all calls to _data and _removeData have been replaced + // with direct calls to dataPriv methods, these can be deprecated. + _data: function( elem, name, data ) { + return dataPriv.access( elem, name, data ); + }, + + _removeData: function( elem, name ) { + dataPriv.remove( elem, name ); + } +} ); + +jQuery.fn.extend( { + data: function( key, value ) { + var i, name, data, + elem = this[ 0 ], + attrs = elem && elem.attributes; + + // Gets all values + if ( key === undefined ) { + if ( this.length ) { + data = dataUser.get( elem ); + + if ( elem.nodeType === 1 && !dataPriv.get( elem, "hasDataAttrs" ) ) { + i = attrs.length; + while ( i-- ) { + + // Support: IE 11 only + // The attrs elements can be null (#14894) + if ( attrs[ i ] ) { + name = attrs[ i ].name; + if ( name.indexOf( "data-" ) === 0 ) { + name = camelCase( name.slice( 5 ) ); + dataAttr( elem, name, data[ name ] ); + } + } + } + dataPriv.set( elem, "hasDataAttrs", true ); + } + } + + return data; + } + + // Sets multiple values + if ( typeof key === "object" ) { + return this.each( function() { + dataUser.set( this, key ); + } ); + } + + return access( this, function( value ) { + var data; + + // The calling jQuery object (element matches) is not empty + // (and therefore has an element appears at this[ 0 ]) and the + // `value` parameter was not undefined. An empty jQuery object + // will result in `undefined` for elem = this[ 0 ] which will + // throw an exception if an attempt to read a data cache is made. + if ( elem && value === undefined ) { + + // Attempt to get data from the cache + // The key will always be camelCased in Data + data = dataUser.get( elem, key ); + if ( data !== undefined ) { + return data; + } + + // Attempt to "discover" the data in + // HTML5 custom data-* attrs + data = dataAttr( elem, key ); + if ( data !== undefined ) { + return data; + } + + // We tried really hard, but the data doesn't exist. + return; + } + + // Set the data... + this.each( function() { + + // We always store the camelCased key + dataUser.set( this, key, value ); + } ); + }, null, value, arguments.length > 1, null, true ); + }, + + removeData: function( key ) { + return this.each( function() { + dataUser.remove( this, key ); + } ); + } +} ); + + +jQuery.extend( { + queue: function( elem, type, data ) { + var queue; + + if ( elem ) { + type = ( type || "fx" ) + "queue"; + queue = dataPriv.get( elem, type ); + + // Speed up dequeue by getting out quickly if this is just a lookup + if ( data ) { + if ( !queue || Array.isArray( data ) ) { + queue = dataPriv.access( elem, type, jQuery.makeArray( data ) ); + } else { + queue.push( data ); + } + } + return queue || []; + } + }, + + dequeue: function( elem, type ) { + type = type || "fx"; + + var queue = jQuery.queue( elem, type ), + startLength = queue.length, + fn = queue.shift(), + hooks = jQuery._queueHooks( elem, type ), + next = function() { + jQuery.dequeue( elem, type ); + }; + + // If the fx queue is dequeued, always remove the progress sentinel + if ( fn === "inprogress" ) { + fn = queue.shift(); + startLength--; + } + + if ( fn ) { + + // Add a progress sentinel to prevent the fx queue from being + // automatically dequeued + if ( type === "fx" ) { + queue.unshift( "inprogress" ); + } + + // Clear up the last queue stop function + delete hooks.stop; + fn.call( elem, next, hooks ); + } + + if ( !startLength && hooks ) { + hooks.empty.fire(); + } + }, + + // Not public - generate a queueHooks object, or return the current one + _queueHooks: function( elem, type ) { + var key = type + "queueHooks"; + return dataPriv.get( elem, key ) || dataPriv.access( elem, key, { + empty: jQuery.Callbacks( "once memory" ).add( function() { + dataPriv.remove( elem, [ type + "queue", key ] ); + } ) + } ); + } +} ); + +jQuery.fn.extend( { + queue: function( type, data ) { + var setter = 2; + + if ( typeof type !== "string" ) { + data = type; + type = "fx"; + setter--; + } + + if ( arguments.length < setter ) { + return jQuery.queue( this[ 0 ], type ); + } + + return data === undefined ? + this : + this.each( function() { + var queue = jQuery.queue( this, type, data ); + + // Ensure a hooks for this queue + jQuery._queueHooks( this, type ); + + if ( type === "fx" && queue[ 0 ] !== "inprogress" ) { + jQuery.dequeue( this, type ); + } + } ); + }, + dequeue: function( type ) { + return this.each( function() { + jQuery.dequeue( this, type ); + } ); + }, + clearQueue: function( type ) { + return this.queue( type || "fx", [] ); + }, + + // Get a promise resolved when queues of a certain type + // are emptied (fx is the type by default) + promise: function( type, obj ) { + var tmp, + count = 1, + defer = jQuery.Deferred(), + elements = this, + i = this.length, + resolve = function() { + if ( !( --count ) ) { + defer.resolveWith( elements, [ elements ] ); + } + }; + + if ( typeof type !== "string" ) { + obj = type; + type = undefined; + } + type = type || "fx"; + + while ( i-- ) { + tmp = dataPriv.get( elements[ i ], type + "queueHooks" ); + if ( tmp && tmp.empty ) { + count++; + tmp.empty.add( resolve ); + } + } + resolve(); + return defer.promise( obj ); + } +} ); +var pnum = ( /[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/ ).source; + +var rcssNum = new RegExp( "^(?:([+-])=|)(" + pnum + ")([a-z%]*)$", "i" ); + + +var cssExpand = [ "Top", "Right", "Bottom", "Left" ]; + +var documentElement = document.documentElement; + + + + var isAttached = function( elem ) { + return jQuery.contains( elem.ownerDocument, elem ); + }, + composed = { composed: true }; + + // Support: IE 9 - 11+, Edge 12 - 18+, iOS 10.0 - 10.2 only + // Check attachment across shadow DOM boundaries when possible (gh-3504) + // Support: iOS 10.0-10.2 only + // Early iOS 10 versions support `attachShadow` but not `getRootNode`, + // leading to errors. We need to check for `getRootNode`. + if ( documentElement.getRootNode ) { + isAttached = function( elem ) { + return jQuery.contains( elem.ownerDocument, elem ) || + elem.getRootNode( composed ) === elem.ownerDocument; + }; + } +var isHiddenWithinTree = function( elem, el ) { + + // isHiddenWithinTree might be called from jQuery#filter function; + // in that case, element will be second argument + elem = el || elem; + + // Inline style trumps all + return elem.style.display === "none" || + elem.style.display === "" && + + // Otherwise, check computed style + // Support: Firefox <=43 - 45 + // Disconnected elements can have computed display: none, so first confirm that elem is + // in the document. + isAttached( elem ) && + + jQuery.css( elem, "display" ) === "none"; + }; + + + +function adjustCSS( elem, prop, valueParts, tween ) { + var adjusted, scale, + maxIterations = 20, + currentValue = tween ? + function() { + return tween.cur(); + } : + function() { + return jQuery.css( elem, prop, "" ); + }, + initial = currentValue(), + unit = valueParts && valueParts[ 3 ] || ( jQuery.cssNumber[ prop ] ? "" : "px" ), + + // Starting value computation is required for potential unit mismatches + initialInUnit = elem.nodeType && + ( jQuery.cssNumber[ prop ] || unit !== "px" && +initial ) && + rcssNum.exec( jQuery.css( elem, prop ) ); + + if ( initialInUnit && initialInUnit[ 3 ] !== unit ) { + + // Support: Firefox <=54 + // Halve the iteration target value to prevent interference from CSS upper bounds (gh-2144) + initial = initial / 2; + + // Trust units reported by jQuery.css + unit = unit || initialInUnit[ 3 ]; + + // Iteratively approximate from a nonzero starting point + initialInUnit = +initial || 1; + + while ( maxIterations-- ) { + + // Evaluate and update our best guess (doubling guesses that zero out). + // Finish if the scale equals or crosses 1 (making the old*new product non-positive). + jQuery.style( elem, prop, initialInUnit + unit ); + if ( ( 1 - scale ) * ( 1 - ( scale = currentValue() / initial || 0.5 ) ) <= 0 ) { + maxIterations = 0; + } + initialInUnit = initialInUnit / scale; + + } + + initialInUnit = initialInUnit * 2; + jQuery.style( elem, prop, initialInUnit + unit ); + + // Make sure we update the tween properties later on + valueParts = valueParts || []; + } + + if ( valueParts ) { + initialInUnit = +initialInUnit || +initial || 0; + + // Apply relative offset (+=/-=) if specified + adjusted = valueParts[ 1 ] ? + initialInUnit + ( valueParts[ 1 ] + 1 ) * valueParts[ 2 ] : + +valueParts[ 2 ]; + if ( tween ) { + tween.unit = unit; + tween.start = initialInUnit; + tween.end = adjusted; + } + } + return adjusted; +} + + +var defaultDisplayMap = {}; + +function getDefaultDisplay( elem ) { + var temp, + doc = elem.ownerDocument, + nodeName = elem.nodeName, + display = defaultDisplayMap[ nodeName ]; + + if ( display ) { + return display; + } + + temp = doc.body.appendChild( doc.createElement( nodeName ) ); + display = jQuery.css( temp, "display" ); + + temp.parentNode.removeChild( temp ); + + if ( display === "none" ) { + display = "block"; + } + defaultDisplayMap[ nodeName ] = display; + + return display; +} + +function showHide( elements, show ) { + var display, elem, + values = [], + index = 0, + length = elements.length; + + // Determine new display value for elements that need to change + for ( ; index < length; index++ ) { + elem = elements[ index ]; + if ( !elem.style ) { + continue; + } + + display = elem.style.display; + if ( show ) { + + // Since we force visibility upon cascade-hidden elements, an immediate (and slow) + // check is required in this first loop unless we have a nonempty display value (either + // inline or about-to-be-restored) + if ( display === "none" ) { + values[ index ] = dataPriv.get( elem, "display" ) || null; + if ( !values[ index ] ) { + elem.style.display = ""; + } + } + if ( elem.style.display === "" && isHiddenWithinTree( elem ) ) { + values[ index ] = getDefaultDisplay( elem ); + } + } else { + if ( display !== "none" ) { + values[ index ] = "none"; + + // Remember what we're overwriting + dataPriv.set( elem, "display", display ); + } + } + } + + // Set the display of the elements in a second loop to avoid constant reflow + for ( index = 0; index < length; index++ ) { + if ( values[ index ] != null ) { + elements[ index ].style.display = values[ index ]; + } + } + + return elements; +} + +jQuery.fn.extend( { + show: function() { + return showHide( this, true ); + }, + hide: function() { + return showHide( this ); + }, + toggle: function( state ) { + if ( typeof state === "boolean" ) { + return state ? this.show() : this.hide(); + } + + return this.each( function() { + if ( isHiddenWithinTree( this ) ) { + jQuery( this ).show(); + } else { + jQuery( this ).hide(); + } + } ); + } +} ); +var rcheckableType = ( /^(?:checkbox|radio)$/i ); + +var rtagName = ( /<([a-z][^\/\0>\x20\t\r\n\f]*)/i ); + +var rscriptType = ( /^$|^module$|\/(?:java|ecma)script/i ); + + + +( function() { + var fragment = document.createDocumentFragment(), + div = fragment.appendChild( document.createElement( "div" ) ), + input = document.createElement( "input" ); + + // Support: Android 4.0 - 4.3 only + // Check state lost if the name is set (#11217) + // Support: Windows Web Apps (WWA) + // `name` and `type` must use .setAttribute for WWA (#14901) + input.setAttribute( "type", "radio" ); + input.setAttribute( "checked", "checked" ); + input.setAttribute( "name", "t" ); + + div.appendChild( input ); + + // Support: Android <=4.1 only + // Older WebKit doesn't clone checked state correctly in fragments + support.checkClone = div.cloneNode( true ).cloneNode( true ).lastChild.checked; + + // Support: IE <=11 only + // Make sure textarea (and checkbox) defaultValue is properly cloned + div.innerHTML = ""; + support.noCloneChecked = !!div.cloneNode( true ).lastChild.defaultValue; + + // Support: IE <=9 only + // IE <=9 replaces "; + support.option = !!div.lastChild; +} )(); + + +// We have to close these tags to support XHTML (#13200) +var wrapMap = { + + // XHTML parsers do not magically insert elements in the + // same way that tag soup parsers do. So we cannot shorten + // this by omitting or other required elements. + thead: [ 1, "", "
" ], + col: [ 2, "", "
" ], + tr: [ 2, "", "
" ], + td: [ 3, "", "
" ], + + _default: [ 0, "", "" ] +}; + +wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; +wrapMap.th = wrapMap.td; + +// Support: IE <=9 only +if ( !support.option ) { + wrapMap.optgroup = wrapMap.option = [ 1, "" ]; +} + + +function getAll( context, tag ) { + + // Support: IE <=9 - 11 only + // Use typeof to avoid zero-argument method invocation on host objects (#15151) + var ret; + + if ( typeof context.getElementsByTagName !== "undefined" ) { + ret = context.getElementsByTagName( tag || "*" ); + + } else if ( typeof context.querySelectorAll !== "undefined" ) { + ret = context.querySelectorAll( tag || "*" ); + + } else { + ret = []; + } + + if ( tag === undefined || tag && nodeName( context, tag ) ) { + return jQuery.merge( [ context ], ret ); + } + + return ret; +} + + +// Mark scripts as having already been evaluated +function setGlobalEval( elems, refElements ) { + var i = 0, + l = elems.length; + + for ( ; i < l; i++ ) { + dataPriv.set( + elems[ i ], + "globalEval", + !refElements || dataPriv.get( refElements[ i ], "globalEval" ) + ); + } +} + + +var rhtml = /<|&#?\w+;/; + +function buildFragment( elems, context, scripts, selection, ignored ) { + var elem, tmp, tag, wrap, attached, j, + fragment = context.createDocumentFragment(), + nodes = [], + i = 0, + l = elems.length; + + for ( ; i < l; i++ ) { + elem = elems[ i ]; + + if ( elem || elem === 0 ) { + + // Add nodes directly + if ( toType( elem ) === "object" ) { + + // Support: Android <=4.0 only, PhantomJS 1 only + // push.apply(_, arraylike) throws on ancient WebKit + jQuery.merge( nodes, elem.nodeType ? [ elem ] : elem ); + + // Convert non-html into a text node + } else if ( !rhtml.test( elem ) ) { + nodes.push( context.createTextNode( elem ) ); + + // Convert html into DOM nodes + } else { + tmp = tmp || fragment.appendChild( context.createElement( "div" ) ); + + // Deserialize a standard representation + tag = ( rtagName.exec( elem ) || [ "", "" ] )[ 1 ].toLowerCase(); + wrap = wrapMap[ tag ] || wrapMap._default; + tmp.innerHTML = wrap[ 1 ] + jQuery.htmlPrefilter( elem ) + wrap[ 2 ]; + + // Descend through wrappers to the right content + j = wrap[ 0 ]; + while ( j-- ) { + tmp = tmp.lastChild; + } + + // Support: Android <=4.0 only, PhantomJS 1 only + // push.apply(_, arraylike) throws on ancient WebKit + jQuery.merge( nodes, tmp.childNodes ); + + // Remember the top-level container + tmp = fragment.firstChild; + + // Ensure the created nodes are orphaned (#12392) + tmp.textContent = ""; + } + } + } + + // Remove wrapper from fragment + fragment.textContent = ""; + + i = 0; + while ( ( elem = nodes[ i++ ] ) ) { + + // Skip elements already in the context collection (trac-4087) + if ( selection && jQuery.inArray( elem, selection ) > -1 ) { + if ( ignored ) { + ignored.push( elem ); + } + continue; + } + + attached = isAttached( elem ); + + // Append to fragment + tmp = getAll( fragment.appendChild( elem ), "script" ); + + // Preserve script evaluation history + if ( attached ) { + setGlobalEval( tmp ); + } + + // Capture executables + if ( scripts ) { + j = 0; + while ( ( elem = tmp[ j++ ] ) ) { + if ( rscriptType.test( elem.type || "" ) ) { + scripts.push( elem ); + } + } + } + } + + return fragment; +} + + +var + rkeyEvent = /^key/, + rmouseEvent = /^(?:mouse|pointer|contextmenu|drag|drop)|click/, + rtypenamespace = /^([^.]*)(?:\.(.+)|)/; + +function returnTrue() { + return true; +} + +function returnFalse() { + return false; +} + +// Support: IE <=9 - 11+ +// focus() and blur() are asynchronous, except when they are no-op. +// So expect focus to be synchronous when the element is already active, +// and blur to be synchronous when the element is not already active. +// (focus and blur are always synchronous in other supported browsers, +// this just defines when we can count on it). +function expectSync( elem, type ) { + return ( elem === safeActiveElement() ) === ( type === "focus" ); +} + +// Support: IE <=9 only +// Accessing document.activeElement can throw unexpectedly +// https://bugs.jquery.com/ticket/13393 +function safeActiveElement() { + try { + return document.activeElement; + } catch ( err ) { } +} + +function on( elem, types, selector, data, fn, one ) { + var origFn, type; + + // Types can be a map of types/handlers + if ( typeof types === "object" ) { + + // ( types-Object, selector, data ) + if ( typeof selector !== "string" ) { + + // ( types-Object, data ) + data = data || selector; + selector = undefined; + } + for ( type in types ) { + on( elem, type, selector, data, types[ type ], one ); + } + return elem; + } + + if ( data == null && fn == null ) { + + // ( types, fn ) + fn = selector; + data = selector = undefined; + } else if ( fn == null ) { + if ( typeof selector === "string" ) { + + // ( types, selector, fn ) + fn = data; + data = undefined; + } else { + + // ( types, data, fn ) + fn = data; + data = selector; + selector = undefined; + } + } + if ( fn === false ) { + fn = returnFalse; + } else if ( !fn ) { + return elem; + } + + if ( one === 1 ) { + origFn = fn; + fn = function( event ) { + + // Can use an empty set, since event contains the info + jQuery().off( event ); + return origFn.apply( this, arguments ); + }; + + // Use same guid so caller can remove using origFn + fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ ); + } + return elem.each( function() { + jQuery.event.add( this, types, fn, data, selector ); + } ); +} + +/* + * Helper functions for managing events -- not part of the public interface. + * Props to Dean Edwards' addEvent library for many of the ideas. + */ +jQuery.event = { + + global: {}, + + add: function( elem, types, handler, data, selector ) { + + var handleObjIn, eventHandle, tmp, + events, t, handleObj, + special, handlers, type, namespaces, origType, + elemData = dataPriv.get( elem ); + + // Only attach events to objects that accept data + if ( !acceptData( elem ) ) { + return; + } + + // Caller can pass in an object of custom data in lieu of the handler + if ( handler.handler ) { + handleObjIn = handler; + handler = handleObjIn.handler; + selector = handleObjIn.selector; + } + + // Ensure that invalid selectors throw exceptions at attach time + // Evaluate against documentElement in case elem is a non-element node (e.g., document) + if ( selector ) { + jQuery.find.matchesSelector( documentElement, selector ); + } + + // Make sure that the handler has a unique ID, used to find/remove it later + if ( !handler.guid ) { + handler.guid = jQuery.guid++; + } + + // Init the element's event structure and main handler, if this is the first + if ( !( events = elemData.events ) ) { + events = elemData.events = Object.create( null ); + } + if ( !( eventHandle = elemData.handle ) ) { + eventHandle = elemData.handle = function( e ) { + + // Discard the second event of a jQuery.event.trigger() and + // when an event is called after a page has unloaded + return typeof jQuery !== "undefined" && jQuery.event.triggered !== e.type ? + jQuery.event.dispatch.apply( elem, arguments ) : undefined; + }; + } + + // Handle multiple events separated by a space + types = ( types || "" ).match( rnothtmlwhite ) || [ "" ]; + t = types.length; + while ( t-- ) { + tmp = rtypenamespace.exec( types[ t ] ) || []; + type = origType = tmp[ 1 ]; + namespaces = ( tmp[ 2 ] || "" ).split( "." ).sort(); + + // There *must* be a type, no attaching namespace-only handlers + if ( !type ) { + continue; + } + + // If event changes its type, use the special event handlers for the changed type + special = jQuery.event.special[ type ] || {}; + + // If selector defined, determine special event api type, otherwise given type + type = ( selector ? special.delegateType : special.bindType ) || type; + + // Update special based on newly reset type + special = jQuery.event.special[ type ] || {}; + + // handleObj is passed to all event handlers + handleObj = jQuery.extend( { + type: type, + origType: origType, + data: data, + handler: handler, + guid: handler.guid, + selector: selector, + needsContext: selector && jQuery.expr.match.needsContext.test( selector ), + namespace: namespaces.join( "." ) + }, handleObjIn ); + + // Init the event handler queue if we're the first + if ( !( handlers = events[ type ] ) ) { + handlers = events[ type ] = []; + handlers.delegateCount = 0; + + // Only use addEventListener if the special events handler returns false + if ( !special.setup || + special.setup.call( elem, data, namespaces, eventHandle ) === false ) { + + if ( elem.addEventListener ) { + elem.addEventListener( type, eventHandle ); + } + } + } + + if ( special.add ) { + special.add.call( elem, handleObj ); + + if ( !handleObj.handler.guid ) { + handleObj.handler.guid = handler.guid; + } + } + + // Add to the element's handler list, delegates in front + if ( selector ) { + handlers.splice( handlers.delegateCount++, 0, handleObj ); + } else { + handlers.push( handleObj ); + } + + // Keep track of which events have ever been used, for event optimization + jQuery.event.global[ type ] = true; + } + + }, + + // Detach an event or set of events from an element + remove: function( elem, types, handler, selector, mappedTypes ) { + + var j, origCount, tmp, + events, t, handleObj, + special, handlers, type, namespaces, origType, + elemData = dataPriv.hasData( elem ) && dataPriv.get( elem ); + + if ( !elemData || !( events = elemData.events ) ) { + return; + } + + // Once for each type.namespace in types; type may be omitted + types = ( types || "" ).match( rnothtmlwhite ) || [ "" ]; + t = types.length; + while ( t-- ) { + tmp = rtypenamespace.exec( types[ t ] ) || []; + type = origType = tmp[ 1 ]; + namespaces = ( tmp[ 2 ] || "" ).split( "." ).sort(); + + // Unbind all events (on this namespace, if provided) for the element + if ( !type ) { + for ( type in events ) { + jQuery.event.remove( elem, type + types[ t ], handler, selector, true ); + } + continue; + } + + special = jQuery.event.special[ type ] || {}; + type = ( selector ? special.delegateType : special.bindType ) || type; + handlers = events[ type ] || []; + tmp = tmp[ 2 ] && + new RegExp( "(^|\\.)" + namespaces.join( "\\.(?:.*\\.|)" ) + "(\\.|$)" ); + + // Remove matching events + origCount = j = handlers.length; + while ( j-- ) { + handleObj = handlers[ j ]; + + if ( ( mappedTypes || origType === handleObj.origType ) && + ( !handler || handler.guid === handleObj.guid ) && + ( !tmp || tmp.test( handleObj.namespace ) ) && + ( !selector || selector === handleObj.selector || + selector === "**" && handleObj.selector ) ) { + handlers.splice( j, 1 ); + + if ( handleObj.selector ) { + handlers.delegateCount--; + } + if ( special.remove ) { + special.remove.call( elem, handleObj ); + } + } + } + + // Remove generic event handler if we removed something and no more handlers exist + // (avoids potential for endless recursion during removal of special event handlers) + if ( origCount && !handlers.length ) { + if ( !special.teardown || + special.teardown.call( elem, namespaces, elemData.handle ) === false ) { + + jQuery.removeEvent( elem, type, elemData.handle ); + } + + delete events[ type ]; + } + } + + // Remove data and the expando if it's no longer used + if ( jQuery.isEmptyObject( events ) ) { + dataPriv.remove( elem, "handle events" ); + } + }, + + dispatch: function( nativeEvent ) { + + var i, j, ret, matched, handleObj, handlerQueue, + args = new Array( arguments.length ), + + // Make a writable jQuery.Event from the native event object + event = jQuery.event.fix( nativeEvent ), + + handlers = ( + dataPriv.get( this, "events" ) || Object.create( null ) + )[ event.type ] || [], + special = jQuery.event.special[ event.type ] || {}; + + // Use the fix-ed jQuery.Event rather than the (read-only) native event + args[ 0 ] = event; + + for ( i = 1; i < arguments.length; i++ ) { + args[ i ] = arguments[ i ]; + } + + event.delegateTarget = this; + + // Call the preDispatch hook for the mapped type, and let it bail if desired + if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) { + return; + } + + // Determine handlers + handlerQueue = jQuery.event.handlers.call( this, event, handlers ); + + // Run delegates first; they may want to stop propagation beneath us + i = 0; + while ( ( matched = handlerQueue[ i++ ] ) && !event.isPropagationStopped() ) { + event.currentTarget = matched.elem; + + j = 0; + while ( ( handleObj = matched.handlers[ j++ ] ) && + !event.isImmediatePropagationStopped() ) { + + // If the event is namespaced, then each handler is only invoked if it is + // specially universal or its namespaces are a superset of the event's. + if ( !event.rnamespace || handleObj.namespace === false || + event.rnamespace.test( handleObj.namespace ) ) { + + event.handleObj = handleObj; + event.data = handleObj.data; + + ret = ( ( jQuery.event.special[ handleObj.origType ] || {} ).handle || + handleObj.handler ).apply( matched.elem, args ); + + if ( ret !== undefined ) { + if ( ( event.result = ret ) === false ) { + event.preventDefault(); + event.stopPropagation(); + } + } + } + } + } + + // Call the postDispatch hook for the mapped type + if ( special.postDispatch ) { + special.postDispatch.call( this, event ); + } + + return event.result; + }, + + handlers: function( event, handlers ) { + var i, handleObj, sel, matchedHandlers, matchedSelectors, + handlerQueue = [], + delegateCount = handlers.delegateCount, + cur = event.target; + + // Find delegate handlers + if ( delegateCount && + + // Support: IE <=9 + // Black-hole SVG instance trees (trac-13180) + cur.nodeType && + + // Support: Firefox <=42 + // Suppress spec-violating clicks indicating a non-primary pointer button (trac-3861) + // https://www.w3.org/TR/DOM-Level-3-Events/#event-type-click + // Support: IE 11 only + // ...but not arrow key "clicks" of radio inputs, which can have `button` -1 (gh-2343) + !( event.type === "click" && event.button >= 1 ) ) { + + for ( ; cur !== this; cur = cur.parentNode || this ) { + + // Don't check non-elements (#13208) + // Don't process clicks on disabled elements (#6911, #8165, #11382, #11764) + if ( cur.nodeType === 1 && !( event.type === "click" && cur.disabled === true ) ) { + matchedHandlers = []; + matchedSelectors = {}; + for ( i = 0; i < delegateCount; i++ ) { + handleObj = handlers[ i ]; + + // Don't conflict with Object.prototype properties (#13203) + sel = handleObj.selector + " "; + + if ( matchedSelectors[ sel ] === undefined ) { + matchedSelectors[ sel ] = handleObj.needsContext ? + jQuery( sel, this ).index( cur ) > -1 : + jQuery.find( sel, this, null, [ cur ] ).length; + } + if ( matchedSelectors[ sel ] ) { + matchedHandlers.push( handleObj ); + } + } + if ( matchedHandlers.length ) { + handlerQueue.push( { elem: cur, handlers: matchedHandlers } ); + } + } + } + } + + // Add the remaining (directly-bound) handlers + cur = this; + if ( delegateCount < handlers.length ) { + handlerQueue.push( { elem: cur, handlers: handlers.slice( delegateCount ) } ); + } + + return handlerQueue; + }, + + addProp: function( name, hook ) { + Object.defineProperty( jQuery.Event.prototype, name, { + enumerable: true, + configurable: true, + + get: isFunction( hook ) ? + function() { + if ( this.originalEvent ) { + return hook( this.originalEvent ); + } + } : + function() { + if ( this.originalEvent ) { + return this.originalEvent[ name ]; + } + }, + + set: function( value ) { + Object.defineProperty( this, name, { + enumerable: true, + configurable: true, + writable: true, + value: value + } ); + } + } ); + }, + + fix: function( originalEvent ) { + return originalEvent[ jQuery.expando ] ? + originalEvent : + new jQuery.Event( originalEvent ); + }, + + special: { + load: { + + // Prevent triggered image.load events from bubbling to window.load + noBubble: true + }, + click: { + + // Utilize native event to ensure correct state for checkable inputs + setup: function( data ) { + + // For mutual compressibility with _default, replace `this` access with a local var. + // `|| data` is dead code meant only to preserve the variable through minification. + var el = this || data; + + // Claim the first handler + if ( rcheckableType.test( el.type ) && + el.click && nodeName( el, "input" ) ) { + + // dataPriv.set( el, "click", ... ) + leverageNative( el, "click", returnTrue ); + } + + // Return false to allow normal processing in the caller + return false; + }, + trigger: function( data ) { + + // For mutual compressibility with _default, replace `this` access with a local var. + // `|| data` is dead code meant only to preserve the variable through minification. + var el = this || data; + + // Force setup before triggering a click + if ( rcheckableType.test( el.type ) && + el.click && nodeName( el, "input" ) ) { + + leverageNative( el, "click" ); + } + + // Return non-false to allow normal event-path propagation + return true; + }, + + // For cross-browser consistency, suppress native .click() on links + // Also prevent it if we're currently inside a leveraged native-event stack + _default: function( event ) { + var target = event.target; + return rcheckableType.test( target.type ) && + target.click && nodeName( target, "input" ) && + dataPriv.get( target, "click" ) || + nodeName( target, "a" ); + } + }, + + beforeunload: { + postDispatch: function( event ) { + + // Support: Firefox 20+ + // Firefox doesn't alert if the returnValue field is not set. + if ( event.result !== undefined && event.originalEvent ) { + event.originalEvent.returnValue = event.result; + } + } + } + } +}; + +// Ensure the presence of an event listener that handles manually-triggered +// synthetic events by interrupting progress until reinvoked in response to +// *native* events that it fires directly, ensuring that state changes have +// already occurred before other listeners are invoked. +function leverageNative( el, type, expectSync ) { + + // Missing expectSync indicates a trigger call, which must force setup through jQuery.event.add + if ( !expectSync ) { + if ( dataPriv.get( el, type ) === undefined ) { + jQuery.event.add( el, type, returnTrue ); + } + return; + } + + // Register the controller as a special universal handler for all event namespaces + dataPriv.set( el, type, false ); + jQuery.event.add( el, type, { + namespace: false, + handler: function( event ) { + var notAsync, result, + saved = dataPriv.get( this, type ); + + if ( ( event.isTrigger & 1 ) && this[ type ] ) { + + // Interrupt processing of the outer synthetic .trigger()ed event + // Saved data should be false in such cases, but might be a leftover capture object + // from an async native handler (gh-4350) + if ( !saved.length ) { + + // Store arguments for use when handling the inner native event + // There will always be at least one argument (an event object), so this array + // will not be confused with a leftover capture object. + saved = slice.call( arguments ); + dataPriv.set( this, type, saved ); + + // Trigger the native event and capture its result + // Support: IE <=9 - 11+ + // focus() and blur() are asynchronous + notAsync = expectSync( this, type ); + this[ type ](); + result = dataPriv.get( this, type ); + if ( saved !== result || notAsync ) { + dataPriv.set( this, type, false ); + } else { + result = {}; + } + if ( saved !== result ) { + + // Cancel the outer synthetic event + event.stopImmediatePropagation(); + event.preventDefault(); + return result.value; + } + + // If this is an inner synthetic event for an event with a bubbling surrogate + // (focus or blur), assume that the surrogate already propagated from triggering the + // native event and prevent that from happening again here. + // This technically gets the ordering wrong w.r.t. to `.trigger()` (in which the + // bubbling surrogate propagates *after* the non-bubbling base), but that seems + // less bad than duplication. + } else if ( ( jQuery.event.special[ type ] || {} ).delegateType ) { + event.stopPropagation(); + } + + // If this is a native event triggered above, everything is now in order + // Fire an inner synthetic event with the original arguments + } else if ( saved.length ) { + + // ...and capture the result + dataPriv.set( this, type, { + value: jQuery.event.trigger( + + // Support: IE <=9 - 11+ + // Extend with the prototype to reset the above stopImmediatePropagation() + jQuery.extend( saved[ 0 ], jQuery.Event.prototype ), + saved.slice( 1 ), + this + ) + } ); + + // Abort handling of the native event + event.stopImmediatePropagation(); + } + } + } ); +} + +jQuery.removeEvent = function( elem, type, handle ) { + + // This "if" is needed for plain objects + if ( elem.removeEventListener ) { + elem.removeEventListener( type, handle ); + } +}; + +jQuery.Event = function( src, props ) { + + // Allow instantiation without the 'new' keyword + if ( !( this instanceof jQuery.Event ) ) { + return new jQuery.Event( src, props ); + } + + // Event object + if ( src && src.type ) { + this.originalEvent = src; + this.type = src.type; + + // Events bubbling up the document may have been marked as prevented + // by a handler lower down the tree; reflect the correct value. + this.isDefaultPrevented = src.defaultPrevented || + src.defaultPrevented === undefined && + + // Support: Android <=2.3 only + src.returnValue === false ? + returnTrue : + returnFalse; + + // Create target properties + // Support: Safari <=6 - 7 only + // Target should not be a text node (#504, #13143) + this.target = ( src.target && src.target.nodeType === 3 ) ? + src.target.parentNode : + src.target; + + this.currentTarget = src.currentTarget; + this.relatedTarget = src.relatedTarget; + + // Event type + } else { + this.type = src; + } + + // Put explicitly provided properties onto the event object + if ( props ) { + jQuery.extend( this, props ); + } + + // Create a timestamp if incoming event doesn't have one + this.timeStamp = src && src.timeStamp || Date.now(); + + // Mark it as fixed + this[ jQuery.expando ] = true; +}; + +// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding +// https://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html +jQuery.Event.prototype = { + constructor: jQuery.Event, + isDefaultPrevented: returnFalse, + isPropagationStopped: returnFalse, + isImmediatePropagationStopped: returnFalse, + isSimulated: false, + + preventDefault: function() { + var e = this.originalEvent; + + this.isDefaultPrevented = returnTrue; + + if ( e && !this.isSimulated ) { + e.preventDefault(); + } + }, + stopPropagation: function() { + var e = this.originalEvent; + + this.isPropagationStopped = returnTrue; + + if ( e && !this.isSimulated ) { + e.stopPropagation(); + } + }, + stopImmediatePropagation: function() { + var e = this.originalEvent; + + this.isImmediatePropagationStopped = returnTrue; + + if ( e && !this.isSimulated ) { + e.stopImmediatePropagation(); + } + + this.stopPropagation(); + } +}; + +// Includes all common event props including KeyEvent and MouseEvent specific props +jQuery.each( { + altKey: true, + bubbles: true, + cancelable: true, + changedTouches: true, + ctrlKey: true, + detail: true, + eventPhase: true, + metaKey: true, + pageX: true, + pageY: true, + shiftKey: true, + view: true, + "char": true, + code: true, + charCode: true, + key: true, + keyCode: true, + button: true, + buttons: true, + clientX: true, + clientY: true, + offsetX: true, + offsetY: true, + pointerId: true, + pointerType: true, + screenX: true, + screenY: true, + targetTouches: true, + toElement: true, + touches: true, + + which: function( event ) { + var button = event.button; + + // Add which for key events + if ( event.which == null && rkeyEvent.test( event.type ) ) { + return event.charCode != null ? event.charCode : event.keyCode; + } + + // Add which for click: 1 === left; 2 === middle; 3 === right + if ( !event.which && button !== undefined && rmouseEvent.test( event.type ) ) { + if ( button & 1 ) { + return 1; + } + + if ( button & 2 ) { + return 3; + } + + if ( button & 4 ) { + return 2; + } + + return 0; + } + + return event.which; + } +}, jQuery.event.addProp ); + +jQuery.each( { focus: "focusin", blur: "focusout" }, function( type, delegateType ) { + jQuery.event.special[ type ] = { + + // Utilize native event if possible so blur/focus sequence is correct + setup: function() { + + // Claim the first handler + // dataPriv.set( this, "focus", ... ) + // dataPriv.set( this, "blur", ... ) + leverageNative( this, type, expectSync ); + + // Return false to allow normal processing in the caller + return false; + }, + trigger: function() { + + // Force setup before trigger + leverageNative( this, type ); + + // Return non-false to allow normal event-path propagation + return true; + }, + + delegateType: delegateType + }; +} ); + +// Create mouseenter/leave events using mouseover/out and event-time checks +// so that event delegation works in jQuery. +// Do the same for pointerenter/pointerleave and pointerover/pointerout +// +// Support: Safari 7 only +// Safari sends mouseenter too often; see: +// https://bugs.chromium.org/p/chromium/issues/detail?id=470258 +// for the description of the bug (it existed in older Chrome versions as well). +jQuery.each( { + mouseenter: "mouseover", + mouseleave: "mouseout", + pointerenter: "pointerover", + pointerleave: "pointerout" +}, function( orig, fix ) { + jQuery.event.special[ orig ] = { + delegateType: fix, + bindType: fix, + + handle: function( event ) { + var ret, + target = this, + related = event.relatedTarget, + handleObj = event.handleObj; + + // For mouseenter/leave call the handler if related is outside the target. + // NB: No relatedTarget if the mouse left/entered the browser window + if ( !related || ( related !== target && !jQuery.contains( target, related ) ) ) { + event.type = handleObj.origType; + ret = handleObj.handler.apply( this, arguments ); + event.type = fix; + } + return ret; + } + }; +} ); + +jQuery.fn.extend( { + + on: function( types, selector, data, fn ) { + return on( this, types, selector, data, fn ); + }, + one: function( types, selector, data, fn ) { + return on( this, types, selector, data, fn, 1 ); + }, + off: function( types, selector, fn ) { + var handleObj, type; + if ( types && types.preventDefault && types.handleObj ) { + + // ( event ) dispatched jQuery.Event + handleObj = types.handleObj; + jQuery( types.delegateTarget ).off( + handleObj.namespace ? + handleObj.origType + "." + handleObj.namespace : + handleObj.origType, + handleObj.selector, + handleObj.handler + ); + return this; + } + if ( typeof types === "object" ) { + + // ( types-object [, selector] ) + for ( type in types ) { + this.off( type, selector, types[ type ] ); + } + return this; + } + if ( selector === false || typeof selector === "function" ) { + + // ( types [, fn] ) + fn = selector; + selector = undefined; + } + if ( fn === false ) { + fn = returnFalse; + } + return this.each( function() { + jQuery.event.remove( this, types, fn, selector ); + } ); + } +} ); + + +var + + // Support: IE <=10 - 11, Edge 12 - 13 only + // In IE/Edge using regex groups here causes severe slowdowns. + // See https://connect.microsoft.com/IE/feedback/details/1736512/ + rnoInnerhtml = /\s*$/g; + +// Prefer a tbody over its parent table for containing new rows +function manipulationTarget( elem, content ) { + if ( nodeName( elem, "table" ) && + nodeName( content.nodeType !== 11 ? content : content.firstChild, "tr" ) ) { + + return jQuery( elem ).children( "tbody" )[ 0 ] || elem; + } + + return elem; +} + +// Replace/restore the type attribute of script elements for safe DOM manipulation +function disableScript( elem ) { + elem.type = ( elem.getAttribute( "type" ) !== null ) + "/" + elem.type; + return elem; +} +function restoreScript( elem ) { + if ( ( elem.type || "" ).slice( 0, 5 ) === "true/" ) { + elem.type = elem.type.slice( 5 ); + } else { + elem.removeAttribute( "type" ); + } + + return elem; +} + +function cloneCopyEvent( src, dest ) { + var i, l, type, pdataOld, udataOld, udataCur, events; + + if ( dest.nodeType !== 1 ) { + return; + } + + // 1. Copy private data: events, handlers, etc. + if ( dataPriv.hasData( src ) ) { + pdataOld = dataPriv.get( src ); + events = pdataOld.events; + + if ( events ) { + dataPriv.remove( dest, "handle events" ); + + for ( type in events ) { + for ( i = 0, l = events[ type ].length; i < l; i++ ) { + jQuery.event.add( dest, type, events[ type ][ i ] ); + } + } + } + } + + // 2. Copy user data + if ( dataUser.hasData( src ) ) { + udataOld = dataUser.access( src ); + udataCur = jQuery.extend( {}, udataOld ); + + dataUser.set( dest, udataCur ); + } +} + +// Fix IE bugs, see support tests +function fixInput( src, dest ) { + var nodeName = dest.nodeName.toLowerCase(); + + // Fails to persist the checked state of a cloned checkbox or radio button. + if ( nodeName === "input" && rcheckableType.test( src.type ) ) { + dest.checked = src.checked; + + // Fails to return the selected option to the default selected state when cloning options + } else if ( nodeName === "input" || nodeName === "textarea" ) { + dest.defaultValue = src.defaultValue; + } +} + +function domManip( collection, args, callback, ignored ) { + + // Flatten any nested arrays + args = flat( args ); + + var fragment, first, scripts, hasScripts, node, doc, + i = 0, + l = collection.length, + iNoClone = l - 1, + value = args[ 0 ], + valueIsFunction = isFunction( value ); + + // We can't cloneNode fragments that contain checked, in WebKit + if ( valueIsFunction || + ( l > 1 && typeof value === "string" && + !support.checkClone && rchecked.test( value ) ) ) { + return collection.each( function( index ) { + var self = collection.eq( index ); + if ( valueIsFunction ) { + args[ 0 ] = value.call( this, index, self.html() ); + } + domManip( self, args, callback, ignored ); + } ); + } + + if ( l ) { + fragment = buildFragment( args, collection[ 0 ].ownerDocument, false, collection, ignored ); + first = fragment.firstChild; + + if ( fragment.childNodes.length === 1 ) { + fragment = first; + } + + // Require either new content or an interest in ignored elements to invoke the callback + if ( first || ignored ) { + scripts = jQuery.map( getAll( fragment, "script" ), disableScript ); + hasScripts = scripts.length; + + // Use the original fragment for the last item + // instead of the first because it can end up + // being emptied incorrectly in certain situations (#8070). + for ( ; i < l; i++ ) { + node = fragment; + + if ( i !== iNoClone ) { + node = jQuery.clone( node, true, true ); + + // Keep references to cloned scripts for later restoration + if ( hasScripts ) { + + // Support: Android <=4.0 only, PhantomJS 1 only + // push.apply(_, arraylike) throws on ancient WebKit + jQuery.merge( scripts, getAll( node, "script" ) ); + } + } + + callback.call( collection[ i ], node, i ); + } + + if ( hasScripts ) { + doc = scripts[ scripts.length - 1 ].ownerDocument; + + // Reenable scripts + jQuery.map( scripts, restoreScript ); + + // Evaluate executable scripts on first document insertion + for ( i = 0; i < hasScripts; i++ ) { + node = scripts[ i ]; + if ( rscriptType.test( node.type || "" ) && + !dataPriv.access( node, "globalEval" ) && + jQuery.contains( doc, node ) ) { + + if ( node.src && ( node.type || "" ).toLowerCase() !== "module" ) { + + // Optional AJAX dependency, but won't run scripts if not present + if ( jQuery._evalUrl && !node.noModule ) { + jQuery._evalUrl( node.src, { + nonce: node.nonce || node.getAttribute( "nonce" ) + }, doc ); + } + } else { + DOMEval( node.textContent.replace( rcleanScript, "" ), node, doc ); + } + } + } + } + } + } + + return collection; +} + +function remove( elem, selector, keepData ) { + var node, + nodes = selector ? jQuery.filter( selector, elem ) : elem, + i = 0; + + for ( ; ( node = nodes[ i ] ) != null; i++ ) { + if ( !keepData && node.nodeType === 1 ) { + jQuery.cleanData( getAll( node ) ); + } + + if ( node.parentNode ) { + if ( keepData && isAttached( node ) ) { + setGlobalEval( getAll( node, "script" ) ); + } + node.parentNode.removeChild( node ); + } + } + + return elem; +} + +jQuery.extend( { + htmlPrefilter: function( html ) { + return html; + }, + + clone: function( elem, dataAndEvents, deepDataAndEvents ) { + var i, l, srcElements, destElements, + clone = elem.cloneNode( true ), + inPage = isAttached( elem ); + + // Fix IE cloning issues + if ( !support.noCloneChecked && ( elem.nodeType === 1 || elem.nodeType === 11 ) && + !jQuery.isXMLDoc( elem ) ) { + + // We eschew Sizzle here for performance reasons: https://jsperf.com/getall-vs-sizzle/2 + destElements = getAll( clone ); + srcElements = getAll( elem ); + + for ( i = 0, l = srcElements.length; i < l; i++ ) { + fixInput( srcElements[ i ], destElements[ i ] ); + } + } + + // Copy the events from the original to the clone + if ( dataAndEvents ) { + if ( deepDataAndEvents ) { + srcElements = srcElements || getAll( elem ); + destElements = destElements || getAll( clone ); + + for ( i = 0, l = srcElements.length; i < l; i++ ) { + cloneCopyEvent( srcElements[ i ], destElements[ i ] ); + } + } else { + cloneCopyEvent( elem, clone ); + } + } + + // Preserve script evaluation history + destElements = getAll( clone, "script" ); + if ( destElements.length > 0 ) { + setGlobalEval( destElements, !inPage && getAll( elem, "script" ) ); + } + + // Return the cloned set + return clone; + }, + + cleanData: function( elems ) { + var data, elem, type, + special = jQuery.event.special, + i = 0; + + for ( ; ( elem = elems[ i ] ) !== undefined; i++ ) { + if ( acceptData( elem ) ) { + if ( ( data = elem[ dataPriv.expando ] ) ) { + if ( data.events ) { + for ( type in data.events ) { + if ( special[ type ] ) { + jQuery.event.remove( elem, type ); + + // This is a shortcut to avoid jQuery.event.remove's overhead + } else { + jQuery.removeEvent( elem, type, data.handle ); + } + } + } + + // Support: Chrome <=35 - 45+ + // Assign undefined instead of using delete, see Data#remove + elem[ dataPriv.expando ] = undefined; + } + if ( elem[ dataUser.expando ] ) { + + // Support: Chrome <=35 - 45+ + // Assign undefined instead of using delete, see Data#remove + elem[ dataUser.expando ] = undefined; + } + } + } + } +} ); + +jQuery.fn.extend( { + detach: function( selector ) { + return remove( this, selector, true ); + }, + + remove: function( selector ) { + return remove( this, selector ); + }, + + text: function( value ) { + return access( this, function( value ) { + return value === undefined ? + jQuery.text( this ) : + this.empty().each( function() { + if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { + this.textContent = value; + } + } ); + }, null, value, arguments.length ); + }, + + append: function() { + return domManip( this, arguments, function( elem ) { + if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { + var target = manipulationTarget( this, elem ); + target.appendChild( elem ); + } + } ); + }, + + prepend: function() { + return domManip( this, arguments, function( elem ) { + if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { + var target = manipulationTarget( this, elem ); + target.insertBefore( elem, target.firstChild ); + } + } ); + }, + + before: function() { + return domManip( this, arguments, function( elem ) { + if ( this.parentNode ) { + this.parentNode.insertBefore( elem, this ); + } + } ); + }, + + after: function() { + return domManip( this, arguments, function( elem ) { + if ( this.parentNode ) { + this.parentNode.insertBefore( elem, this.nextSibling ); + } + } ); + }, + + empty: function() { + var elem, + i = 0; + + for ( ; ( elem = this[ i ] ) != null; i++ ) { + if ( elem.nodeType === 1 ) { + + // Prevent memory leaks + jQuery.cleanData( getAll( elem, false ) ); + + // Remove any remaining nodes + elem.textContent = ""; + } + } + + return this; + }, + + clone: function( dataAndEvents, deepDataAndEvents ) { + dataAndEvents = dataAndEvents == null ? false : dataAndEvents; + deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents; + + return this.map( function() { + return jQuery.clone( this, dataAndEvents, deepDataAndEvents ); + } ); + }, + + html: function( value ) { + return access( this, function( value ) { + var elem = this[ 0 ] || {}, + i = 0, + l = this.length; + + if ( value === undefined && elem.nodeType === 1 ) { + return elem.innerHTML; + } + + // See if we can take a shortcut and just use innerHTML + if ( typeof value === "string" && !rnoInnerhtml.test( value ) && + !wrapMap[ ( rtagName.exec( value ) || [ "", "" ] )[ 1 ].toLowerCase() ] ) { + + value = jQuery.htmlPrefilter( value ); + + try { + for ( ; i < l; i++ ) { + elem = this[ i ] || {}; + + // Remove element nodes and prevent memory leaks + if ( elem.nodeType === 1 ) { + jQuery.cleanData( getAll( elem, false ) ); + elem.innerHTML = value; + } + } + + elem = 0; + + // If using innerHTML throws an exception, use the fallback method + } catch ( e ) {} + } + + if ( elem ) { + this.empty().append( value ); + } + }, null, value, arguments.length ); + }, + + replaceWith: function() { + var ignored = []; + + // Make the changes, replacing each non-ignored context element with the new content + return domManip( this, arguments, function( elem ) { + var parent = this.parentNode; + + if ( jQuery.inArray( this, ignored ) < 0 ) { + jQuery.cleanData( getAll( this ) ); + if ( parent ) { + parent.replaceChild( elem, this ); + } + } + + // Force callback invocation + }, ignored ); + } +} ); + +jQuery.each( { + appendTo: "append", + prependTo: "prepend", + insertBefore: "before", + insertAfter: "after", + replaceAll: "replaceWith" +}, function( name, original ) { + jQuery.fn[ name ] = function( selector ) { + var elems, + ret = [], + insert = jQuery( selector ), + last = insert.length - 1, + i = 0; + + for ( ; i <= last; i++ ) { + elems = i === last ? this : this.clone( true ); + jQuery( insert[ i ] )[ original ]( elems ); + + // Support: Android <=4.0 only, PhantomJS 1 only + // .get() because push.apply(_, arraylike) throws on ancient WebKit + push.apply( ret, elems.get() ); + } + + return this.pushStack( ret ); + }; +} ); +var rnumnonpx = new RegExp( "^(" + pnum + ")(?!px)[a-z%]+$", "i" ); + +var getStyles = function( elem ) { + + // Support: IE <=11 only, Firefox <=30 (#15098, #14150) + // IE throws on elements created in popups + // FF meanwhile throws on frame elements through "defaultView.getComputedStyle" + var view = elem.ownerDocument.defaultView; + + if ( !view || !view.opener ) { + view = window; + } + + return view.getComputedStyle( elem ); + }; + +var swap = function( elem, options, callback ) { + var ret, name, + old = {}; + + // Remember the old values, and insert the new ones + for ( name in options ) { + old[ name ] = elem.style[ name ]; + elem.style[ name ] = options[ name ]; + } + + ret = callback.call( elem ); + + // Revert the old values + for ( name in options ) { + elem.style[ name ] = old[ name ]; + } + + return ret; +}; + + +var rboxStyle = new RegExp( cssExpand.join( "|" ), "i" ); + + + +( function() { + + // Executing both pixelPosition & boxSizingReliable tests require only one layout + // so they're executed at the same time to save the second computation. + function computeStyleTests() { + + // This is a singleton, we need to execute it only once + if ( !div ) { + return; + } + + container.style.cssText = "position:absolute;left:-11111px;width:60px;" + + "margin-top:1px;padding:0;border:0"; + div.style.cssText = + "position:relative;display:block;box-sizing:border-box;overflow:scroll;" + + "margin:auto;border:1px;padding:1px;" + + "width:60%;top:1%"; + documentElement.appendChild( container ).appendChild( div ); + + var divStyle = window.getComputedStyle( div ); + pixelPositionVal = divStyle.top !== "1%"; + + // Support: Android 4.0 - 4.3 only, Firefox <=3 - 44 + reliableMarginLeftVal = roundPixelMeasures( divStyle.marginLeft ) === 12; + + // Support: Android 4.0 - 4.3 only, Safari <=9.1 - 10.1, iOS <=7.0 - 9.3 + // Some styles come back with percentage values, even though they shouldn't + div.style.right = "60%"; + pixelBoxStylesVal = roundPixelMeasures( divStyle.right ) === 36; + + // Support: IE 9 - 11 only + // Detect misreporting of content dimensions for box-sizing:border-box elements + boxSizingReliableVal = roundPixelMeasures( divStyle.width ) === 36; + + // Support: IE 9 only + // Detect overflow:scroll screwiness (gh-3699) + // Support: Chrome <=64 + // Don't get tricked when zoom affects offsetWidth (gh-4029) + div.style.position = "absolute"; + scrollboxSizeVal = roundPixelMeasures( div.offsetWidth / 3 ) === 12; + + documentElement.removeChild( container ); + + // Nullify the div so it wouldn't be stored in the memory and + // it will also be a sign that checks already performed + div = null; + } + + function roundPixelMeasures( measure ) { + return Math.round( parseFloat( measure ) ); + } + + var pixelPositionVal, boxSizingReliableVal, scrollboxSizeVal, pixelBoxStylesVal, + reliableTrDimensionsVal, reliableMarginLeftVal, + container = document.createElement( "div" ), + div = document.createElement( "div" ); + + // Finish early in limited (non-browser) environments + if ( !div.style ) { + return; + } + + // Support: IE <=9 - 11 only + // Style of cloned element affects source element cloned (#8908) + div.style.backgroundClip = "content-box"; + div.cloneNode( true ).style.backgroundClip = ""; + support.clearCloneStyle = div.style.backgroundClip === "content-box"; + + jQuery.extend( support, { + boxSizingReliable: function() { + computeStyleTests(); + return boxSizingReliableVal; + }, + pixelBoxStyles: function() { + computeStyleTests(); + return pixelBoxStylesVal; + }, + pixelPosition: function() { + computeStyleTests(); + return pixelPositionVal; + }, + reliableMarginLeft: function() { + computeStyleTests(); + return reliableMarginLeftVal; + }, + scrollboxSize: function() { + computeStyleTests(); + return scrollboxSizeVal; + }, + + // Support: IE 9 - 11+, Edge 15 - 18+ + // IE/Edge misreport `getComputedStyle` of table rows with width/height + // set in CSS while `offset*` properties report correct values. + // Behavior in IE 9 is more subtle than in newer versions & it passes + // some versions of this test; make sure not to make it pass there! + reliableTrDimensions: function() { + var table, tr, trChild, trStyle; + if ( reliableTrDimensionsVal == null ) { + table = document.createElement( "table" ); + tr = document.createElement( "tr" ); + trChild = document.createElement( "div" ); + + table.style.cssText = "position:absolute;left:-11111px"; + tr.style.height = "1px"; + trChild.style.height = "9px"; + + documentElement + .appendChild( table ) + .appendChild( tr ) + .appendChild( trChild ); + + trStyle = window.getComputedStyle( tr ); + reliableTrDimensionsVal = parseInt( trStyle.height ) > 3; + + documentElement.removeChild( table ); + } + return reliableTrDimensionsVal; + } + } ); +} )(); + + +function curCSS( elem, name, computed ) { + var width, minWidth, maxWidth, ret, + + // Support: Firefox 51+ + // Retrieving style before computed somehow + // fixes an issue with getting wrong values + // on detached elements + style = elem.style; + + computed = computed || getStyles( elem ); + + // getPropertyValue is needed for: + // .css('filter') (IE 9 only, #12537) + // .css('--customProperty) (#3144) + if ( computed ) { + ret = computed.getPropertyValue( name ) || computed[ name ]; + + if ( ret === "" && !isAttached( elem ) ) { + ret = jQuery.style( elem, name ); + } + + // A tribute to the "awesome hack by Dean Edwards" + // Android Browser returns percentage for some values, + // but width seems to be reliably pixels. + // This is against the CSSOM draft spec: + // https://drafts.csswg.org/cssom/#resolved-values + if ( !support.pixelBoxStyles() && rnumnonpx.test( ret ) && rboxStyle.test( name ) ) { + + // Remember the original values + width = style.width; + minWidth = style.minWidth; + maxWidth = style.maxWidth; + + // Put in the new values to get a computed value out + style.minWidth = style.maxWidth = style.width = ret; + ret = computed.width; + + // Revert the changed values + style.width = width; + style.minWidth = minWidth; + style.maxWidth = maxWidth; + } + } + + return ret !== undefined ? + + // Support: IE <=9 - 11 only + // IE returns zIndex value as an integer. + ret + "" : + ret; +} + + +function addGetHookIf( conditionFn, hookFn ) { + + // Define the hook, we'll check on the first run if it's really needed. + return { + get: function() { + if ( conditionFn() ) { + + // Hook not needed (or it's not possible to use it due + // to missing dependency), remove it. + delete this.get; + return; + } + + // Hook needed; redefine it so that the support test is not executed again. + return ( this.get = hookFn ).apply( this, arguments ); + } + }; +} + + +var cssPrefixes = [ "Webkit", "Moz", "ms" ], + emptyStyle = document.createElement( "div" ).style, + vendorProps = {}; + +// Return a vendor-prefixed property or undefined +function vendorPropName( name ) { + + // Check for vendor prefixed names + var capName = name[ 0 ].toUpperCase() + name.slice( 1 ), + i = cssPrefixes.length; + + while ( i-- ) { + name = cssPrefixes[ i ] + capName; + if ( name in emptyStyle ) { + return name; + } + } +} + +// Return a potentially-mapped jQuery.cssProps or vendor prefixed property +function finalPropName( name ) { + var final = jQuery.cssProps[ name ] || vendorProps[ name ]; + + if ( final ) { + return final; + } + if ( name in emptyStyle ) { + return name; + } + return vendorProps[ name ] = vendorPropName( name ) || name; +} + + +var + + // Swappable if display is none or starts with table + // except "table", "table-cell", or "table-caption" + // See here for display values: https://developer.mozilla.org/en-US/docs/CSS/display + rdisplayswap = /^(none|table(?!-c[ea]).+)/, + rcustomProp = /^--/, + cssShow = { position: "absolute", visibility: "hidden", display: "block" }, + cssNormalTransform = { + letterSpacing: "0", + fontWeight: "400" + }; + +function setPositiveNumber( _elem, value, subtract ) { + + // Any relative (+/-) values have already been + // normalized at this point + var matches = rcssNum.exec( value ); + return matches ? + + // Guard against undefined "subtract", e.g., when used as in cssHooks + Math.max( 0, matches[ 2 ] - ( subtract || 0 ) ) + ( matches[ 3 ] || "px" ) : + value; +} + +function boxModelAdjustment( elem, dimension, box, isBorderBox, styles, computedVal ) { + var i = dimension === "width" ? 1 : 0, + extra = 0, + delta = 0; + + // Adjustment may not be necessary + if ( box === ( isBorderBox ? "border" : "content" ) ) { + return 0; + } + + for ( ; i < 4; i += 2 ) { + + // Both box models exclude margin + if ( box === "margin" ) { + delta += jQuery.css( elem, box + cssExpand[ i ], true, styles ); + } + + // If we get here with a content-box, we're seeking "padding" or "border" or "margin" + if ( !isBorderBox ) { + + // Add padding + delta += jQuery.css( elem, "padding" + cssExpand[ i ], true, styles ); + + // For "border" or "margin", add border + if ( box !== "padding" ) { + delta += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); + + // But still keep track of it otherwise + } else { + extra += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); + } + + // If we get here with a border-box (content + padding + border), we're seeking "content" or + // "padding" or "margin" + } else { + + // For "content", subtract padding + if ( box === "content" ) { + delta -= jQuery.css( elem, "padding" + cssExpand[ i ], true, styles ); + } + + // For "content" or "padding", subtract border + if ( box !== "margin" ) { + delta -= jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); + } + } + } + + // Account for positive content-box scroll gutter when requested by providing computedVal + if ( !isBorderBox && computedVal >= 0 ) { + + // offsetWidth/offsetHeight is a rounded sum of content, padding, scroll gutter, and border + // Assuming integer scroll gutter, subtract the rest and round down + delta += Math.max( 0, Math.ceil( + elem[ "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ) ] - + computedVal - + delta - + extra - + 0.5 + + // If offsetWidth/offsetHeight is unknown, then we can't determine content-box scroll gutter + // Use an explicit zero to avoid NaN (gh-3964) + ) ) || 0; + } + + return delta; +} + +function getWidthOrHeight( elem, dimension, extra ) { + + // Start with computed style + var styles = getStyles( elem ), + + // To avoid forcing a reflow, only fetch boxSizing if we need it (gh-4322). + // Fake content-box until we know it's needed to know the true value. + boxSizingNeeded = !support.boxSizingReliable() || extra, + isBorderBox = boxSizingNeeded && + jQuery.css( elem, "boxSizing", false, styles ) === "border-box", + valueIsBorderBox = isBorderBox, + + val = curCSS( elem, dimension, styles ), + offsetProp = "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ); + + // Support: Firefox <=54 + // Return a confounding non-pixel value or feign ignorance, as appropriate. + if ( rnumnonpx.test( val ) ) { + if ( !extra ) { + return val; + } + val = "auto"; + } + + + // Support: IE 9 - 11 only + // Use offsetWidth/offsetHeight for when box sizing is unreliable. + // In those cases, the computed value can be trusted to be border-box. + if ( ( !support.boxSizingReliable() && isBorderBox || + + // Support: IE 10 - 11+, Edge 15 - 18+ + // IE/Edge misreport `getComputedStyle` of table rows with width/height + // set in CSS while `offset*` properties report correct values. + // Interestingly, in some cases IE 9 doesn't suffer from this issue. + !support.reliableTrDimensions() && nodeName( elem, "tr" ) || + + // Fall back to offsetWidth/offsetHeight when value is "auto" + // This happens for inline elements with no explicit setting (gh-3571) + val === "auto" || + + // Support: Android <=4.1 - 4.3 only + // Also use offsetWidth/offsetHeight for misreported inline dimensions (gh-3602) + !parseFloat( val ) && jQuery.css( elem, "display", false, styles ) === "inline" ) && + + // Make sure the element is visible & connected + elem.getClientRects().length ) { + + isBorderBox = jQuery.css( elem, "boxSizing", false, styles ) === "border-box"; + + // Where available, offsetWidth/offsetHeight approximate border box dimensions. + // Where not available (e.g., SVG), assume unreliable box-sizing and interpret the + // retrieved value as a content box dimension. + valueIsBorderBox = offsetProp in elem; + if ( valueIsBorderBox ) { + val = elem[ offsetProp ]; + } + } + + // Normalize "" and auto + val = parseFloat( val ) || 0; + + // Adjust for the element's box model + return ( val + + boxModelAdjustment( + elem, + dimension, + extra || ( isBorderBox ? "border" : "content" ), + valueIsBorderBox, + styles, + + // Provide the current computed size to request scroll gutter calculation (gh-3589) + val + ) + ) + "px"; +} + +jQuery.extend( { + + // Add in style property hooks for overriding the default + // behavior of getting and setting a style property + cssHooks: { + opacity: { + get: function( elem, computed ) { + if ( computed ) { + + // We should always get a number back from opacity + var ret = curCSS( elem, "opacity" ); + return ret === "" ? "1" : ret; + } + } + } + }, + + // Don't automatically add "px" to these possibly-unitless properties + cssNumber: { + "animationIterationCount": true, + "columnCount": true, + "fillOpacity": true, + "flexGrow": true, + "flexShrink": true, + "fontWeight": true, + "gridArea": true, + "gridColumn": true, + "gridColumnEnd": true, + "gridColumnStart": true, + "gridRow": true, + "gridRowEnd": true, + "gridRowStart": true, + "lineHeight": true, + "opacity": true, + "order": true, + "orphans": true, + "widows": true, + "zIndex": true, + "zoom": true + }, + + // Add in properties whose names you wish to fix before + // setting or getting the value + cssProps: {}, + + // Get and set the style property on a DOM Node + style: function( elem, name, value, extra ) { + + // Don't set styles on text and comment nodes + if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) { + return; + } + + // Make sure that we're working with the right name + var ret, type, hooks, + origName = camelCase( name ), + isCustomProp = rcustomProp.test( name ), + style = elem.style; + + // Make sure that we're working with the right name. We don't + // want to query the value if it is a CSS custom property + // since they are user-defined. + if ( !isCustomProp ) { + name = finalPropName( origName ); + } + + // Gets hook for the prefixed version, then unprefixed version + hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ]; + + // Check if we're setting a value + if ( value !== undefined ) { + type = typeof value; + + // Convert "+=" or "-=" to relative numbers (#7345) + if ( type === "string" && ( ret = rcssNum.exec( value ) ) && ret[ 1 ] ) { + value = adjustCSS( elem, name, ret ); + + // Fixes bug #9237 + type = "number"; + } + + // Make sure that null and NaN values aren't set (#7116) + if ( value == null || value !== value ) { + return; + } + + // If a number was passed in, add the unit (except for certain CSS properties) + // The isCustomProp check can be removed in jQuery 4.0 when we only auto-append + // "px" to a few hardcoded values. + if ( type === "number" && !isCustomProp ) { + value += ret && ret[ 3 ] || ( jQuery.cssNumber[ origName ] ? "" : "px" ); + } + + // background-* props affect original clone's values + if ( !support.clearCloneStyle && value === "" && name.indexOf( "background" ) === 0 ) { + style[ name ] = "inherit"; + } + + // If a hook was provided, use that value, otherwise just set the specified value + if ( !hooks || !( "set" in hooks ) || + ( value = hooks.set( elem, value, extra ) ) !== undefined ) { + + if ( isCustomProp ) { + style.setProperty( name, value ); + } else { + style[ name ] = value; + } + } + + } else { + + // If a hook was provided get the non-computed value from there + if ( hooks && "get" in hooks && + ( ret = hooks.get( elem, false, extra ) ) !== undefined ) { + + return ret; + } + + // Otherwise just get the value from the style object + return style[ name ]; + } + }, + + css: function( elem, name, extra, styles ) { + var val, num, hooks, + origName = camelCase( name ), + isCustomProp = rcustomProp.test( name ); + + // Make sure that we're working with the right name. We don't + // want to modify the value if it is a CSS custom property + // since they are user-defined. + if ( !isCustomProp ) { + name = finalPropName( origName ); + } + + // Try prefixed name followed by the unprefixed name + hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ]; + + // If a hook was provided get the computed value from there + if ( hooks && "get" in hooks ) { + val = hooks.get( elem, true, extra ); + } + + // Otherwise, if a way to get the computed value exists, use that + if ( val === undefined ) { + val = curCSS( elem, name, styles ); + } + + // Convert "normal" to computed value + if ( val === "normal" && name in cssNormalTransform ) { + val = cssNormalTransform[ name ]; + } + + // Make numeric if forced or a qualifier was provided and val looks numeric + if ( extra === "" || extra ) { + num = parseFloat( val ); + return extra === true || isFinite( num ) ? num || 0 : val; + } + + return val; + } +} ); + +jQuery.each( [ "height", "width" ], function( _i, dimension ) { + jQuery.cssHooks[ dimension ] = { + get: function( elem, computed, extra ) { + if ( computed ) { + + // Certain elements can have dimension info if we invisibly show them + // but it must have a current display style that would benefit + return rdisplayswap.test( jQuery.css( elem, "display" ) ) && + + // Support: Safari 8+ + // Table columns in Safari have non-zero offsetWidth & zero + // getBoundingClientRect().width unless display is changed. + // Support: IE <=11 only + // Running getBoundingClientRect on a disconnected node + // in IE throws an error. + ( !elem.getClientRects().length || !elem.getBoundingClientRect().width ) ? + swap( elem, cssShow, function() { + return getWidthOrHeight( elem, dimension, extra ); + } ) : + getWidthOrHeight( elem, dimension, extra ); + } + }, + + set: function( elem, value, extra ) { + var matches, + styles = getStyles( elem ), + + // Only read styles.position if the test has a chance to fail + // to avoid forcing a reflow. + scrollboxSizeBuggy = !support.scrollboxSize() && + styles.position === "absolute", + + // To avoid forcing a reflow, only fetch boxSizing if we need it (gh-3991) + boxSizingNeeded = scrollboxSizeBuggy || extra, + isBorderBox = boxSizingNeeded && + jQuery.css( elem, "boxSizing", false, styles ) === "border-box", + subtract = extra ? + boxModelAdjustment( + elem, + dimension, + extra, + isBorderBox, + styles + ) : + 0; + + // Account for unreliable border-box dimensions by comparing offset* to computed and + // faking a content-box to get border and padding (gh-3699) + if ( isBorderBox && scrollboxSizeBuggy ) { + subtract -= Math.ceil( + elem[ "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ) ] - + parseFloat( styles[ dimension ] ) - + boxModelAdjustment( elem, dimension, "border", false, styles ) - + 0.5 + ); + } + + // Convert to pixels if value adjustment is needed + if ( subtract && ( matches = rcssNum.exec( value ) ) && + ( matches[ 3 ] || "px" ) !== "px" ) { + + elem.style[ dimension ] = value; + value = jQuery.css( elem, dimension ); + } + + return setPositiveNumber( elem, value, subtract ); + } + }; +} ); + +jQuery.cssHooks.marginLeft = addGetHookIf( support.reliableMarginLeft, + function( elem, computed ) { + if ( computed ) { + return ( parseFloat( curCSS( elem, "marginLeft" ) ) || + elem.getBoundingClientRect().left - + swap( elem, { marginLeft: 0 }, function() { + return elem.getBoundingClientRect().left; + } ) + ) + "px"; + } + } +); + +// These hooks are used by animate to expand properties +jQuery.each( { + margin: "", + padding: "", + border: "Width" +}, function( prefix, suffix ) { + jQuery.cssHooks[ prefix + suffix ] = { + expand: function( value ) { + var i = 0, + expanded = {}, + + // Assumes a single number if not a string + parts = typeof value === "string" ? value.split( " " ) : [ value ]; + + for ( ; i < 4; i++ ) { + expanded[ prefix + cssExpand[ i ] + suffix ] = + parts[ i ] || parts[ i - 2 ] || parts[ 0 ]; + } + + return expanded; + } + }; + + if ( prefix !== "margin" ) { + jQuery.cssHooks[ prefix + suffix ].set = setPositiveNumber; + } +} ); + +jQuery.fn.extend( { + css: function( name, value ) { + return access( this, function( elem, name, value ) { + var styles, len, + map = {}, + i = 0; + + if ( Array.isArray( name ) ) { + styles = getStyles( elem ); + len = name.length; + + for ( ; i < len; i++ ) { + map[ name[ i ] ] = jQuery.css( elem, name[ i ], false, styles ); + } + + return map; + } + + return value !== undefined ? + jQuery.style( elem, name, value ) : + jQuery.css( elem, name ); + }, name, value, arguments.length > 1 ); + } +} ); + + +function Tween( elem, options, prop, end, easing ) { + return new Tween.prototype.init( elem, options, prop, end, easing ); +} +jQuery.Tween = Tween; + +Tween.prototype = { + constructor: Tween, + init: function( elem, options, prop, end, easing, unit ) { + this.elem = elem; + this.prop = prop; + this.easing = easing || jQuery.easing._default; + this.options = options; + this.start = this.now = this.cur(); + this.end = end; + this.unit = unit || ( jQuery.cssNumber[ prop ] ? "" : "px" ); + }, + cur: function() { + var hooks = Tween.propHooks[ this.prop ]; + + return hooks && hooks.get ? + hooks.get( this ) : + Tween.propHooks._default.get( this ); + }, + run: function( percent ) { + var eased, + hooks = Tween.propHooks[ this.prop ]; + + if ( this.options.duration ) { + this.pos = eased = jQuery.easing[ this.easing ]( + percent, this.options.duration * percent, 0, 1, this.options.duration + ); + } else { + this.pos = eased = percent; + } + this.now = ( this.end - this.start ) * eased + this.start; + + if ( this.options.step ) { + this.options.step.call( this.elem, this.now, this ); + } + + if ( hooks && hooks.set ) { + hooks.set( this ); + } else { + Tween.propHooks._default.set( this ); + } + return this; + } +}; + +Tween.prototype.init.prototype = Tween.prototype; + +Tween.propHooks = { + _default: { + get: function( tween ) { + var result; + + // Use a property on the element directly when it is not a DOM element, + // or when there is no matching style property that exists. + if ( tween.elem.nodeType !== 1 || + tween.elem[ tween.prop ] != null && tween.elem.style[ tween.prop ] == null ) { + return tween.elem[ tween.prop ]; + } + + // Passing an empty string as a 3rd parameter to .css will automatically + // attempt a parseFloat and fallback to a string if the parse fails. + // Simple values such as "10px" are parsed to Float; + // complex values such as "rotate(1rad)" are returned as-is. + result = jQuery.css( tween.elem, tween.prop, "" ); + + // Empty strings, null, undefined and "auto" are converted to 0. + return !result || result === "auto" ? 0 : result; + }, + set: function( tween ) { + + // Use step hook for back compat. + // Use cssHook if its there. + // Use .style if available and use plain properties where available. + if ( jQuery.fx.step[ tween.prop ] ) { + jQuery.fx.step[ tween.prop ]( tween ); + } else if ( tween.elem.nodeType === 1 && ( + jQuery.cssHooks[ tween.prop ] || + tween.elem.style[ finalPropName( tween.prop ) ] != null ) ) { + jQuery.style( tween.elem, tween.prop, tween.now + tween.unit ); + } else { + tween.elem[ tween.prop ] = tween.now; + } + } + } +}; + +// Support: IE <=9 only +// Panic based approach to setting things on disconnected nodes +Tween.propHooks.scrollTop = Tween.propHooks.scrollLeft = { + set: function( tween ) { + if ( tween.elem.nodeType && tween.elem.parentNode ) { + tween.elem[ tween.prop ] = tween.now; + } + } +}; + +jQuery.easing = { + linear: function( p ) { + return p; + }, + swing: function( p ) { + return 0.5 - Math.cos( p * Math.PI ) / 2; + }, + _default: "swing" +}; + +jQuery.fx = Tween.prototype.init; + +// Back compat <1.8 extension point +jQuery.fx.step = {}; + + + + +var + fxNow, inProgress, + rfxtypes = /^(?:toggle|show|hide)$/, + rrun = /queueHooks$/; + +function schedule() { + if ( inProgress ) { + if ( document.hidden === false && window.requestAnimationFrame ) { + window.requestAnimationFrame( schedule ); + } else { + window.setTimeout( schedule, jQuery.fx.interval ); + } + + jQuery.fx.tick(); + } +} + +// Animations created synchronously will run synchronously +function createFxNow() { + window.setTimeout( function() { + fxNow = undefined; + } ); + return ( fxNow = Date.now() ); +} + +// Generate parameters to create a standard animation +function genFx( type, includeWidth ) { + var which, + i = 0, + attrs = { height: type }; + + // If we include width, step value is 1 to do all cssExpand values, + // otherwise step value is 2 to skip over Left and Right + includeWidth = includeWidth ? 1 : 0; + for ( ; i < 4; i += 2 - includeWidth ) { + which = cssExpand[ i ]; + attrs[ "margin" + which ] = attrs[ "padding" + which ] = type; + } + + if ( includeWidth ) { + attrs.opacity = attrs.width = type; + } + + return attrs; +} + +function createTween( value, prop, animation ) { + var tween, + collection = ( Animation.tweeners[ prop ] || [] ).concat( Animation.tweeners[ "*" ] ), + index = 0, + length = collection.length; + for ( ; index < length; index++ ) { + if ( ( tween = collection[ index ].call( animation, prop, value ) ) ) { + + // We're done with this property + return tween; + } + } +} + +function defaultPrefilter( elem, props, opts ) { + var prop, value, toggle, hooks, oldfire, propTween, restoreDisplay, display, + isBox = "width" in props || "height" in props, + anim = this, + orig = {}, + style = elem.style, + hidden = elem.nodeType && isHiddenWithinTree( elem ), + dataShow = dataPriv.get( elem, "fxshow" ); + + // Queue-skipping animations hijack the fx hooks + if ( !opts.queue ) { + hooks = jQuery._queueHooks( elem, "fx" ); + if ( hooks.unqueued == null ) { + hooks.unqueued = 0; + oldfire = hooks.empty.fire; + hooks.empty.fire = function() { + if ( !hooks.unqueued ) { + oldfire(); + } + }; + } + hooks.unqueued++; + + anim.always( function() { + + // Ensure the complete handler is called before this completes + anim.always( function() { + hooks.unqueued--; + if ( !jQuery.queue( elem, "fx" ).length ) { + hooks.empty.fire(); + } + } ); + } ); + } + + // Detect show/hide animations + for ( prop in props ) { + value = props[ prop ]; + if ( rfxtypes.test( value ) ) { + delete props[ prop ]; + toggle = toggle || value === "toggle"; + if ( value === ( hidden ? "hide" : "show" ) ) { + + // Pretend to be hidden if this is a "show" and + // there is still data from a stopped show/hide + if ( value === "show" && dataShow && dataShow[ prop ] !== undefined ) { + hidden = true; + + // Ignore all other no-op show/hide data + } else { + continue; + } + } + orig[ prop ] = dataShow && dataShow[ prop ] || jQuery.style( elem, prop ); + } + } + + // Bail out if this is a no-op like .hide().hide() + propTween = !jQuery.isEmptyObject( props ); + if ( !propTween && jQuery.isEmptyObject( orig ) ) { + return; + } + + // Restrict "overflow" and "display" styles during box animations + if ( isBox && elem.nodeType === 1 ) { + + // Support: IE <=9 - 11, Edge 12 - 15 + // Record all 3 overflow attributes because IE does not infer the shorthand + // from identically-valued overflowX and overflowY and Edge just mirrors + // the overflowX value there. + opts.overflow = [ style.overflow, style.overflowX, style.overflowY ]; + + // Identify a display type, preferring old show/hide data over the CSS cascade + restoreDisplay = dataShow && dataShow.display; + if ( restoreDisplay == null ) { + restoreDisplay = dataPriv.get( elem, "display" ); + } + display = jQuery.css( elem, "display" ); + if ( display === "none" ) { + if ( restoreDisplay ) { + display = restoreDisplay; + } else { + + // Get nonempty value(s) by temporarily forcing visibility + showHide( [ elem ], true ); + restoreDisplay = elem.style.display || restoreDisplay; + display = jQuery.css( elem, "display" ); + showHide( [ elem ] ); + } + } + + // Animate inline elements as inline-block + if ( display === "inline" || display === "inline-block" && restoreDisplay != null ) { + if ( jQuery.css( elem, "float" ) === "none" ) { + + // Restore the original display value at the end of pure show/hide animations + if ( !propTween ) { + anim.done( function() { + style.display = restoreDisplay; + } ); + if ( restoreDisplay == null ) { + display = style.display; + restoreDisplay = display === "none" ? "" : display; + } + } + style.display = "inline-block"; + } + } + } + + if ( opts.overflow ) { + style.overflow = "hidden"; + anim.always( function() { + style.overflow = opts.overflow[ 0 ]; + style.overflowX = opts.overflow[ 1 ]; + style.overflowY = opts.overflow[ 2 ]; + } ); + } + + // Implement show/hide animations + propTween = false; + for ( prop in orig ) { + + // General show/hide setup for this element animation + if ( !propTween ) { + if ( dataShow ) { + if ( "hidden" in dataShow ) { + hidden = dataShow.hidden; + } + } else { + dataShow = dataPriv.access( elem, "fxshow", { display: restoreDisplay } ); + } + + // Store hidden/visible for toggle so `.stop().toggle()` "reverses" + if ( toggle ) { + dataShow.hidden = !hidden; + } + + // Show elements before animating them + if ( hidden ) { + showHide( [ elem ], true ); + } + + /* eslint-disable no-loop-func */ + + anim.done( function() { + + /* eslint-enable no-loop-func */ + + // The final step of a "hide" animation is actually hiding the element + if ( !hidden ) { + showHide( [ elem ] ); + } + dataPriv.remove( elem, "fxshow" ); + for ( prop in orig ) { + jQuery.style( elem, prop, orig[ prop ] ); + } + } ); + } + + // Per-property setup + propTween = createTween( hidden ? dataShow[ prop ] : 0, prop, anim ); + if ( !( prop in dataShow ) ) { + dataShow[ prop ] = propTween.start; + if ( hidden ) { + propTween.end = propTween.start; + propTween.start = 0; + } + } + } +} + +function propFilter( props, specialEasing ) { + var index, name, easing, value, hooks; + + // camelCase, specialEasing and expand cssHook pass + for ( index in props ) { + name = camelCase( index ); + easing = specialEasing[ name ]; + value = props[ index ]; + if ( Array.isArray( value ) ) { + easing = value[ 1 ]; + value = props[ index ] = value[ 0 ]; + } + + if ( index !== name ) { + props[ name ] = value; + delete props[ index ]; + } + + hooks = jQuery.cssHooks[ name ]; + if ( hooks && "expand" in hooks ) { + value = hooks.expand( value ); + delete props[ name ]; + + // Not quite $.extend, this won't overwrite existing keys. + // Reusing 'index' because we have the correct "name" + for ( index in value ) { + if ( !( index in props ) ) { + props[ index ] = value[ index ]; + specialEasing[ index ] = easing; + } + } + } else { + specialEasing[ name ] = easing; + } + } +} + +function Animation( elem, properties, options ) { + var result, + stopped, + index = 0, + length = Animation.prefilters.length, + deferred = jQuery.Deferred().always( function() { + + // Don't match elem in the :animated selector + delete tick.elem; + } ), + tick = function() { + if ( stopped ) { + return false; + } + var currentTime = fxNow || createFxNow(), + remaining = Math.max( 0, animation.startTime + animation.duration - currentTime ), + + // Support: Android 2.3 only + // Archaic crash bug won't allow us to use `1 - ( 0.5 || 0 )` (#12497) + temp = remaining / animation.duration || 0, + percent = 1 - temp, + index = 0, + length = animation.tweens.length; + + for ( ; index < length; index++ ) { + animation.tweens[ index ].run( percent ); + } + + deferred.notifyWith( elem, [ animation, percent, remaining ] ); + + // If there's more to do, yield + if ( percent < 1 && length ) { + return remaining; + } + + // If this was an empty animation, synthesize a final progress notification + if ( !length ) { + deferred.notifyWith( elem, [ animation, 1, 0 ] ); + } + + // Resolve the animation and report its conclusion + deferred.resolveWith( elem, [ animation ] ); + return false; + }, + animation = deferred.promise( { + elem: elem, + props: jQuery.extend( {}, properties ), + opts: jQuery.extend( true, { + specialEasing: {}, + easing: jQuery.easing._default + }, options ), + originalProperties: properties, + originalOptions: options, + startTime: fxNow || createFxNow(), + duration: options.duration, + tweens: [], + createTween: function( prop, end ) { + var tween = jQuery.Tween( elem, animation.opts, prop, end, + animation.opts.specialEasing[ prop ] || animation.opts.easing ); + animation.tweens.push( tween ); + return tween; + }, + stop: function( gotoEnd ) { + var index = 0, + + // If we are going to the end, we want to run all the tweens + // otherwise we skip this part + length = gotoEnd ? animation.tweens.length : 0; + if ( stopped ) { + return this; + } + stopped = true; + for ( ; index < length; index++ ) { + animation.tweens[ index ].run( 1 ); + } + + // Resolve when we played the last frame; otherwise, reject + if ( gotoEnd ) { + deferred.notifyWith( elem, [ animation, 1, 0 ] ); + deferred.resolveWith( elem, [ animation, gotoEnd ] ); + } else { + deferred.rejectWith( elem, [ animation, gotoEnd ] ); + } + return this; + } + } ), + props = animation.props; + + propFilter( props, animation.opts.specialEasing ); + + for ( ; index < length; index++ ) { + result = Animation.prefilters[ index ].call( animation, elem, props, animation.opts ); + if ( result ) { + if ( isFunction( result.stop ) ) { + jQuery._queueHooks( animation.elem, animation.opts.queue ).stop = + result.stop.bind( result ); + } + return result; + } + } + + jQuery.map( props, createTween, animation ); + + if ( isFunction( animation.opts.start ) ) { + animation.opts.start.call( elem, animation ); + } + + // Attach callbacks from options + animation + .progress( animation.opts.progress ) + .done( animation.opts.done, animation.opts.complete ) + .fail( animation.opts.fail ) + .always( animation.opts.always ); + + jQuery.fx.timer( + jQuery.extend( tick, { + elem: elem, + anim: animation, + queue: animation.opts.queue + } ) + ); + + return animation; +} + +jQuery.Animation = jQuery.extend( Animation, { + + tweeners: { + "*": [ function( prop, value ) { + var tween = this.createTween( prop, value ); + adjustCSS( tween.elem, prop, rcssNum.exec( value ), tween ); + return tween; + } ] + }, + + tweener: function( props, callback ) { + if ( isFunction( props ) ) { + callback = props; + props = [ "*" ]; + } else { + props = props.match( rnothtmlwhite ); + } + + var prop, + index = 0, + length = props.length; + + for ( ; index < length; index++ ) { + prop = props[ index ]; + Animation.tweeners[ prop ] = Animation.tweeners[ prop ] || []; + Animation.tweeners[ prop ].unshift( callback ); + } + }, + + prefilters: [ defaultPrefilter ], + + prefilter: function( callback, prepend ) { + if ( prepend ) { + Animation.prefilters.unshift( callback ); + } else { + Animation.prefilters.push( callback ); + } + } +} ); + +jQuery.speed = function( speed, easing, fn ) { + var opt = speed && typeof speed === "object" ? jQuery.extend( {}, speed ) : { + complete: fn || !fn && easing || + isFunction( speed ) && speed, + duration: speed, + easing: fn && easing || easing && !isFunction( easing ) && easing + }; + + // Go to the end state if fx are off + if ( jQuery.fx.off ) { + opt.duration = 0; + + } else { + if ( typeof opt.duration !== "number" ) { + if ( opt.duration in jQuery.fx.speeds ) { + opt.duration = jQuery.fx.speeds[ opt.duration ]; + + } else { + opt.duration = jQuery.fx.speeds._default; + } + } + } + + // Normalize opt.queue - true/undefined/null -> "fx" + if ( opt.queue == null || opt.queue === true ) { + opt.queue = "fx"; + } + + // Queueing + opt.old = opt.complete; + + opt.complete = function() { + if ( isFunction( opt.old ) ) { + opt.old.call( this ); + } + + if ( opt.queue ) { + jQuery.dequeue( this, opt.queue ); + } + }; + + return opt; +}; + +jQuery.fn.extend( { + fadeTo: function( speed, to, easing, callback ) { + + // Show any hidden elements after setting opacity to 0 + return this.filter( isHiddenWithinTree ).css( "opacity", 0 ).show() + + // Animate to the value specified + .end().animate( { opacity: to }, speed, easing, callback ); + }, + animate: function( prop, speed, easing, callback ) { + var empty = jQuery.isEmptyObject( prop ), + optall = jQuery.speed( speed, easing, callback ), + doAnimation = function() { + + // Operate on a copy of prop so per-property easing won't be lost + var anim = Animation( this, jQuery.extend( {}, prop ), optall ); + + // Empty animations, or finishing resolves immediately + if ( empty || dataPriv.get( this, "finish" ) ) { + anim.stop( true ); + } + }; + doAnimation.finish = doAnimation; + + return empty || optall.queue === false ? + this.each( doAnimation ) : + this.queue( optall.queue, doAnimation ); + }, + stop: function( type, clearQueue, gotoEnd ) { + var stopQueue = function( hooks ) { + var stop = hooks.stop; + delete hooks.stop; + stop( gotoEnd ); + }; + + if ( typeof type !== "string" ) { + gotoEnd = clearQueue; + clearQueue = type; + type = undefined; + } + if ( clearQueue ) { + this.queue( type || "fx", [] ); + } + + return this.each( function() { + var dequeue = true, + index = type != null && type + "queueHooks", + timers = jQuery.timers, + data = dataPriv.get( this ); + + if ( index ) { + if ( data[ index ] && data[ index ].stop ) { + stopQueue( data[ index ] ); + } + } else { + for ( index in data ) { + if ( data[ index ] && data[ index ].stop && rrun.test( index ) ) { + stopQueue( data[ index ] ); + } + } + } + + for ( index = timers.length; index--; ) { + if ( timers[ index ].elem === this && + ( type == null || timers[ index ].queue === type ) ) { + + timers[ index ].anim.stop( gotoEnd ); + dequeue = false; + timers.splice( index, 1 ); + } + } + + // Start the next in the queue if the last step wasn't forced. + // Timers currently will call their complete callbacks, which + // will dequeue but only if they were gotoEnd. + if ( dequeue || !gotoEnd ) { + jQuery.dequeue( this, type ); + } + } ); + }, + finish: function( type ) { + if ( type !== false ) { + type = type || "fx"; + } + return this.each( function() { + var index, + data = dataPriv.get( this ), + queue = data[ type + "queue" ], + hooks = data[ type + "queueHooks" ], + timers = jQuery.timers, + length = queue ? queue.length : 0; + + // Enable finishing flag on private data + data.finish = true; + + // Empty the queue first + jQuery.queue( this, type, [] ); + + if ( hooks && hooks.stop ) { + hooks.stop.call( this, true ); + } + + // Look for any active animations, and finish them + for ( index = timers.length; index--; ) { + if ( timers[ index ].elem === this && timers[ index ].queue === type ) { + timers[ index ].anim.stop( true ); + timers.splice( index, 1 ); + } + } + + // Look for any animations in the old queue and finish them + for ( index = 0; index < length; index++ ) { + if ( queue[ index ] && queue[ index ].finish ) { + queue[ index ].finish.call( this ); + } + } + + // Turn off finishing flag + delete data.finish; + } ); + } +} ); + +jQuery.each( [ "toggle", "show", "hide" ], function( _i, name ) { + var cssFn = jQuery.fn[ name ]; + jQuery.fn[ name ] = function( speed, easing, callback ) { + return speed == null || typeof speed === "boolean" ? + cssFn.apply( this, arguments ) : + this.animate( genFx( name, true ), speed, easing, callback ); + }; +} ); + +// Generate shortcuts for custom animations +jQuery.each( { + slideDown: genFx( "show" ), + slideUp: genFx( "hide" ), + slideToggle: genFx( "toggle" ), + fadeIn: { opacity: "show" }, + fadeOut: { opacity: "hide" }, + fadeToggle: { opacity: "toggle" } +}, function( name, props ) { + jQuery.fn[ name ] = function( speed, easing, callback ) { + return this.animate( props, speed, easing, callback ); + }; +} ); + +jQuery.timers = []; +jQuery.fx.tick = function() { + var timer, + i = 0, + timers = jQuery.timers; + + fxNow = Date.now(); + + for ( ; i < timers.length; i++ ) { + timer = timers[ i ]; + + // Run the timer and safely remove it when done (allowing for external removal) + if ( !timer() && timers[ i ] === timer ) { + timers.splice( i--, 1 ); + } + } + + if ( !timers.length ) { + jQuery.fx.stop(); + } + fxNow = undefined; +}; + +jQuery.fx.timer = function( timer ) { + jQuery.timers.push( timer ); + jQuery.fx.start(); +}; + +jQuery.fx.interval = 13; +jQuery.fx.start = function() { + if ( inProgress ) { + return; + } + + inProgress = true; + schedule(); +}; + +jQuery.fx.stop = function() { + inProgress = null; +}; + +jQuery.fx.speeds = { + slow: 600, + fast: 200, + + // Default speed + _default: 400 +}; + + +// Based off of the plugin by Clint Helfers, with permission. +// https://web.archive.org/web/20100324014747/http://blindsignals.com/index.php/2009/07/jquery-delay/ +jQuery.fn.delay = function( time, type ) { + time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time; + type = type || "fx"; + + return this.queue( type, function( next, hooks ) { + var timeout = window.setTimeout( next, time ); + hooks.stop = function() { + window.clearTimeout( timeout ); + }; + } ); +}; + + +( function() { + var input = document.createElement( "input" ), + select = document.createElement( "select" ), + opt = select.appendChild( document.createElement( "option" ) ); + + input.type = "checkbox"; + + // Support: Android <=4.3 only + // Default value for a checkbox should be "on" + support.checkOn = input.value !== ""; + + // Support: IE <=11 only + // Must access selectedIndex to make default options select + support.optSelected = opt.selected; + + // Support: IE <=11 only + // An input loses its value after becoming a radio + input = document.createElement( "input" ); + input.value = "t"; + input.type = "radio"; + support.radioValue = input.value === "t"; +} )(); + + +var boolHook, + attrHandle = jQuery.expr.attrHandle; + +jQuery.fn.extend( { + attr: function( name, value ) { + return access( this, jQuery.attr, name, value, arguments.length > 1 ); + }, + + removeAttr: function( name ) { + return this.each( function() { + jQuery.removeAttr( this, name ); + } ); + } +} ); + +jQuery.extend( { + attr: function( elem, name, value ) { + var ret, hooks, + nType = elem.nodeType; + + // Don't get/set attributes on text, comment and attribute nodes + if ( nType === 3 || nType === 8 || nType === 2 ) { + return; + } + + // Fallback to prop when attributes are not supported + if ( typeof elem.getAttribute === "undefined" ) { + return jQuery.prop( elem, name, value ); + } + + // Attribute hooks are determined by the lowercase version + // Grab necessary hook if one is defined + if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) { + hooks = jQuery.attrHooks[ name.toLowerCase() ] || + ( jQuery.expr.match.bool.test( name ) ? boolHook : undefined ); + } + + if ( value !== undefined ) { + if ( value === null ) { + jQuery.removeAttr( elem, name ); + return; + } + + if ( hooks && "set" in hooks && + ( ret = hooks.set( elem, value, name ) ) !== undefined ) { + return ret; + } + + elem.setAttribute( name, value + "" ); + return value; + } + + if ( hooks && "get" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) { + return ret; + } + + ret = jQuery.find.attr( elem, name ); + + // Non-existent attributes return null, we normalize to undefined + return ret == null ? undefined : ret; + }, + + attrHooks: { + type: { + set: function( elem, value ) { + if ( !support.radioValue && value === "radio" && + nodeName( elem, "input" ) ) { + var val = elem.value; + elem.setAttribute( "type", value ); + if ( val ) { + elem.value = val; + } + return value; + } + } + } + }, + + removeAttr: function( elem, value ) { + var name, + i = 0, + + // Attribute names can contain non-HTML whitespace characters + // https://html.spec.whatwg.org/multipage/syntax.html#attributes-2 + attrNames = value && value.match( rnothtmlwhite ); + + if ( attrNames && elem.nodeType === 1 ) { + while ( ( name = attrNames[ i++ ] ) ) { + elem.removeAttribute( name ); + } + } + } +} ); + +// Hooks for boolean attributes +boolHook = { + set: function( elem, value, name ) { + if ( value === false ) { + + // Remove boolean attributes when set to false + jQuery.removeAttr( elem, name ); + } else { + elem.setAttribute( name, name ); + } + return name; + } +}; + +jQuery.each( jQuery.expr.match.bool.source.match( /\w+/g ), function( _i, name ) { + var getter = attrHandle[ name ] || jQuery.find.attr; + + attrHandle[ name ] = function( elem, name, isXML ) { + var ret, handle, + lowercaseName = name.toLowerCase(); + + if ( !isXML ) { + + // Avoid an infinite loop by temporarily removing this function from the getter + handle = attrHandle[ lowercaseName ]; + attrHandle[ lowercaseName ] = ret; + ret = getter( elem, name, isXML ) != null ? + lowercaseName : + null; + attrHandle[ lowercaseName ] = handle; + } + return ret; + }; +} ); + + + + +var rfocusable = /^(?:input|select|textarea|button)$/i, + rclickable = /^(?:a|area)$/i; + +jQuery.fn.extend( { + prop: function( name, value ) { + return access( this, jQuery.prop, name, value, arguments.length > 1 ); + }, + + removeProp: function( name ) { + return this.each( function() { + delete this[ jQuery.propFix[ name ] || name ]; + } ); + } +} ); + +jQuery.extend( { + prop: function( elem, name, value ) { + var ret, hooks, + nType = elem.nodeType; + + // Don't get/set properties on text, comment and attribute nodes + if ( nType === 3 || nType === 8 || nType === 2 ) { + return; + } + + if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) { + + // Fix name and attach hooks + name = jQuery.propFix[ name ] || name; + hooks = jQuery.propHooks[ name ]; + } + + if ( value !== undefined ) { + if ( hooks && "set" in hooks && + ( ret = hooks.set( elem, value, name ) ) !== undefined ) { + return ret; + } + + return ( elem[ name ] = value ); + } + + if ( hooks && "get" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) { + return ret; + } + + return elem[ name ]; + }, + + propHooks: { + tabIndex: { + get: function( elem ) { + + // Support: IE <=9 - 11 only + // elem.tabIndex doesn't always return the + // correct value when it hasn't been explicitly set + // https://web.archive.org/web/20141116233347/http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/ + // Use proper attribute retrieval(#12072) + var tabindex = jQuery.find.attr( elem, "tabindex" ); + + if ( tabindex ) { + return parseInt( tabindex, 10 ); + } + + if ( + rfocusable.test( elem.nodeName ) || + rclickable.test( elem.nodeName ) && + elem.href + ) { + return 0; + } + + return -1; + } + } + }, + + propFix: { + "for": "htmlFor", + "class": "className" + } +} ); + +// Support: IE <=11 only +// Accessing the selectedIndex property +// forces the browser to respect setting selected +// on the option +// The getter ensures a default option is selected +// when in an optgroup +// eslint rule "no-unused-expressions" is disabled for this code +// since it considers such accessions noop +if ( !support.optSelected ) { + jQuery.propHooks.selected = { + get: function( elem ) { + + /* eslint no-unused-expressions: "off" */ + + var parent = elem.parentNode; + if ( parent && parent.parentNode ) { + parent.parentNode.selectedIndex; + } + return null; + }, + set: function( elem ) { + + /* eslint no-unused-expressions: "off" */ + + var parent = elem.parentNode; + if ( parent ) { + parent.selectedIndex; + + if ( parent.parentNode ) { + parent.parentNode.selectedIndex; + } + } + } + }; +} + +jQuery.each( [ + "tabIndex", + "readOnly", + "maxLength", + "cellSpacing", + "cellPadding", + "rowSpan", + "colSpan", + "useMap", + "frameBorder", + "contentEditable" +], function() { + jQuery.propFix[ this.toLowerCase() ] = this; +} ); + + + + + // Strip and collapse whitespace according to HTML spec + // https://infra.spec.whatwg.org/#strip-and-collapse-ascii-whitespace + function stripAndCollapse( value ) { + var tokens = value.match( rnothtmlwhite ) || []; + return tokens.join( " " ); + } + + +function getClass( elem ) { + return elem.getAttribute && elem.getAttribute( "class" ) || ""; +} + +function classesToArray( value ) { + if ( Array.isArray( value ) ) { + return value; + } + if ( typeof value === "string" ) { + return value.match( rnothtmlwhite ) || []; + } + return []; +} + +jQuery.fn.extend( { + addClass: function( value ) { + var classes, elem, cur, curValue, clazz, j, finalValue, + i = 0; + + if ( isFunction( value ) ) { + return this.each( function( j ) { + jQuery( this ).addClass( value.call( this, j, getClass( this ) ) ); + } ); + } + + classes = classesToArray( value ); + + if ( classes.length ) { + while ( ( elem = this[ i++ ] ) ) { + curValue = getClass( elem ); + cur = elem.nodeType === 1 && ( " " + stripAndCollapse( curValue ) + " " ); + + if ( cur ) { + j = 0; + while ( ( clazz = classes[ j++ ] ) ) { + if ( cur.indexOf( " " + clazz + " " ) < 0 ) { + cur += clazz + " "; + } + } + + // Only assign if different to avoid unneeded rendering. + finalValue = stripAndCollapse( cur ); + if ( curValue !== finalValue ) { + elem.setAttribute( "class", finalValue ); + } + } + } + } + + return this; + }, + + removeClass: function( value ) { + var classes, elem, cur, curValue, clazz, j, finalValue, + i = 0; + + if ( isFunction( value ) ) { + return this.each( function( j ) { + jQuery( this ).removeClass( value.call( this, j, getClass( this ) ) ); + } ); + } + + if ( !arguments.length ) { + return this.attr( "class", "" ); + } + + classes = classesToArray( value ); + + if ( classes.length ) { + while ( ( elem = this[ i++ ] ) ) { + curValue = getClass( elem ); + + // This expression is here for better compressibility (see addClass) + cur = elem.nodeType === 1 && ( " " + stripAndCollapse( curValue ) + " " ); + + if ( cur ) { + j = 0; + while ( ( clazz = classes[ j++ ] ) ) { + + // Remove *all* instances + while ( cur.indexOf( " " + clazz + " " ) > -1 ) { + cur = cur.replace( " " + clazz + " ", " " ); + } + } + + // Only assign if different to avoid unneeded rendering. + finalValue = stripAndCollapse( cur ); + if ( curValue !== finalValue ) { + elem.setAttribute( "class", finalValue ); + } + } + } + } + + return this; + }, + + toggleClass: function( value, stateVal ) { + var type = typeof value, + isValidValue = type === "string" || Array.isArray( value ); + + if ( typeof stateVal === "boolean" && isValidValue ) { + return stateVal ? this.addClass( value ) : this.removeClass( value ); + } + + if ( isFunction( value ) ) { + return this.each( function( i ) { + jQuery( this ).toggleClass( + value.call( this, i, getClass( this ), stateVal ), + stateVal + ); + } ); + } + + return this.each( function() { + var className, i, self, classNames; + + if ( isValidValue ) { + + // Toggle individual class names + i = 0; + self = jQuery( this ); + classNames = classesToArray( value ); + + while ( ( className = classNames[ i++ ] ) ) { + + // Check each className given, space separated list + if ( self.hasClass( className ) ) { + self.removeClass( className ); + } else { + self.addClass( className ); + } + } + + // Toggle whole class name + } else if ( value === undefined || type === "boolean" ) { + className = getClass( this ); + if ( className ) { + + // Store className if set + dataPriv.set( this, "__className__", className ); + } + + // If the element has a class name or if we're passed `false`, + // then remove the whole classname (if there was one, the above saved it). + // Otherwise bring back whatever was previously saved (if anything), + // falling back to the empty string if nothing was stored. + if ( this.setAttribute ) { + this.setAttribute( "class", + className || value === false ? + "" : + dataPriv.get( this, "__className__" ) || "" + ); + } + } + } ); + }, + + hasClass: function( selector ) { + var className, elem, + i = 0; + + className = " " + selector + " "; + while ( ( elem = this[ i++ ] ) ) { + if ( elem.nodeType === 1 && + ( " " + stripAndCollapse( getClass( elem ) ) + " " ).indexOf( className ) > -1 ) { + return true; + } + } + + return false; + } +} ); + + + + +var rreturn = /\r/g; + +jQuery.fn.extend( { + val: function( value ) { + var hooks, ret, valueIsFunction, + elem = this[ 0 ]; + + if ( !arguments.length ) { + if ( elem ) { + hooks = jQuery.valHooks[ elem.type ] || + jQuery.valHooks[ elem.nodeName.toLowerCase() ]; + + if ( hooks && + "get" in hooks && + ( ret = hooks.get( elem, "value" ) ) !== undefined + ) { + return ret; + } + + ret = elem.value; + + // Handle most common string cases + if ( typeof ret === "string" ) { + return ret.replace( rreturn, "" ); + } + + // Handle cases where value is null/undef or number + return ret == null ? "" : ret; + } + + return; + } + + valueIsFunction = isFunction( value ); + + return this.each( function( i ) { + var val; + + if ( this.nodeType !== 1 ) { + return; + } + + if ( valueIsFunction ) { + val = value.call( this, i, jQuery( this ).val() ); + } else { + val = value; + } + + // Treat null/undefined as ""; convert numbers to string + if ( val == null ) { + val = ""; + + } else if ( typeof val === "number" ) { + val += ""; + + } else if ( Array.isArray( val ) ) { + val = jQuery.map( val, function( value ) { + return value == null ? "" : value + ""; + } ); + } + + hooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ]; + + // If set returns undefined, fall back to normal setting + if ( !hooks || !( "set" in hooks ) || hooks.set( this, val, "value" ) === undefined ) { + this.value = val; + } + } ); + } +} ); + +jQuery.extend( { + valHooks: { + option: { + get: function( elem ) { + + var val = jQuery.find.attr( elem, "value" ); + return val != null ? + val : + + // Support: IE <=10 - 11 only + // option.text throws exceptions (#14686, #14858) + // Strip and collapse whitespace + // https://html.spec.whatwg.org/#strip-and-collapse-whitespace + stripAndCollapse( jQuery.text( elem ) ); + } + }, + select: { + get: function( elem ) { + var value, option, i, + options = elem.options, + index = elem.selectedIndex, + one = elem.type === "select-one", + values = one ? null : [], + max = one ? index + 1 : options.length; + + if ( index < 0 ) { + i = max; + + } else { + i = one ? index : 0; + } + + // Loop through all the selected options + for ( ; i < max; i++ ) { + option = options[ i ]; + + // Support: IE <=9 only + // IE8-9 doesn't update selected after form reset (#2551) + if ( ( option.selected || i === index ) && + + // Don't return options that are disabled or in a disabled optgroup + !option.disabled && + ( !option.parentNode.disabled || + !nodeName( option.parentNode, "optgroup" ) ) ) { + + // Get the specific value for the option + value = jQuery( option ).val(); + + // We don't need an array for one selects + if ( one ) { + return value; + } + + // Multi-Selects return an array + values.push( value ); + } + } + + return values; + }, + + set: function( elem, value ) { + var optionSet, option, + options = elem.options, + values = jQuery.makeArray( value ), + i = options.length; + + while ( i-- ) { + option = options[ i ]; + + /* eslint-disable no-cond-assign */ + + if ( option.selected = + jQuery.inArray( jQuery.valHooks.option.get( option ), values ) > -1 + ) { + optionSet = true; + } + + /* eslint-enable no-cond-assign */ + } + + // Force browsers to behave consistently when non-matching value is set + if ( !optionSet ) { + elem.selectedIndex = -1; + } + return values; + } + } + } +} ); + +// Radios and checkboxes getter/setter +jQuery.each( [ "radio", "checkbox" ], function() { + jQuery.valHooks[ this ] = { + set: function( elem, value ) { + if ( Array.isArray( value ) ) { + return ( elem.checked = jQuery.inArray( jQuery( elem ).val(), value ) > -1 ); + } + } + }; + if ( !support.checkOn ) { + jQuery.valHooks[ this ].get = function( elem ) { + return elem.getAttribute( "value" ) === null ? "on" : elem.value; + }; + } +} ); + + + + +// Return jQuery for attributes-only inclusion + + +support.focusin = "onfocusin" in window; + + +var rfocusMorph = /^(?:focusinfocus|focusoutblur)$/, + stopPropagationCallback = function( e ) { + e.stopPropagation(); + }; + +jQuery.extend( jQuery.event, { + + trigger: function( event, data, elem, onlyHandlers ) { + + var i, cur, tmp, bubbleType, ontype, handle, special, lastElement, + eventPath = [ elem || document ], + type = hasOwn.call( event, "type" ) ? event.type : event, + namespaces = hasOwn.call( event, "namespace" ) ? event.namespace.split( "." ) : []; + + cur = lastElement = tmp = elem = elem || document; + + // Don't do events on text and comment nodes + if ( elem.nodeType === 3 || elem.nodeType === 8 ) { + return; + } + + // focus/blur morphs to focusin/out; ensure we're not firing them right now + if ( rfocusMorph.test( type + jQuery.event.triggered ) ) { + return; + } + + if ( type.indexOf( "." ) > -1 ) { + + // Namespaced trigger; create a regexp to match event type in handle() + namespaces = type.split( "." ); + type = namespaces.shift(); + namespaces.sort(); + } + ontype = type.indexOf( ":" ) < 0 && "on" + type; + + // Caller can pass in a jQuery.Event object, Object, or just an event type string + event = event[ jQuery.expando ] ? + event : + new jQuery.Event( type, typeof event === "object" && event ); + + // Trigger bitmask: & 1 for native handlers; & 2 for jQuery (always true) + event.isTrigger = onlyHandlers ? 2 : 3; + event.namespace = namespaces.join( "." ); + event.rnamespace = event.namespace ? + new RegExp( "(^|\\.)" + namespaces.join( "\\.(?:.*\\.|)" ) + "(\\.|$)" ) : + null; + + // Clean up the event in case it is being reused + event.result = undefined; + if ( !event.target ) { + event.target = elem; + } + + // Clone any incoming data and prepend the event, creating the handler arg list + data = data == null ? + [ event ] : + jQuery.makeArray( data, [ event ] ); + + // Allow special events to draw outside the lines + special = jQuery.event.special[ type ] || {}; + if ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) { + return; + } + + // Determine event propagation path in advance, per W3C events spec (#9951) + // Bubble up to document, then to window; watch for a global ownerDocument var (#9724) + if ( !onlyHandlers && !special.noBubble && !isWindow( elem ) ) { + + bubbleType = special.delegateType || type; + if ( !rfocusMorph.test( bubbleType + type ) ) { + cur = cur.parentNode; + } + for ( ; cur; cur = cur.parentNode ) { + eventPath.push( cur ); + tmp = cur; + } + + // Only add window if we got to document (e.g., not plain obj or detached DOM) + if ( tmp === ( elem.ownerDocument || document ) ) { + eventPath.push( tmp.defaultView || tmp.parentWindow || window ); + } + } + + // Fire handlers on the event path + i = 0; + while ( ( cur = eventPath[ i++ ] ) && !event.isPropagationStopped() ) { + lastElement = cur; + event.type = i > 1 ? + bubbleType : + special.bindType || type; + + // jQuery handler + handle = ( + dataPriv.get( cur, "events" ) || Object.create( null ) + )[ event.type ] && + dataPriv.get( cur, "handle" ); + if ( handle ) { + handle.apply( cur, data ); + } + + // Native handler + handle = ontype && cur[ ontype ]; + if ( handle && handle.apply && acceptData( cur ) ) { + event.result = handle.apply( cur, data ); + if ( event.result === false ) { + event.preventDefault(); + } + } + } + event.type = type; + + // If nobody prevented the default action, do it now + if ( !onlyHandlers && !event.isDefaultPrevented() ) { + + if ( ( !special._default || + special._default.apply( eventPath.pop(), data ) === false ) && + acceptData( elem ) ) { + + // Call a native DOM method on the target with the same name as the event. + // Don't do default actions on window, that's where global variables be (#6170) + if ( ontype && isFunction( elem[ type ] ) && !isWindow( elem ) ) { + + // Don't re-trigger an onFOO event when we call its FOO() method + tmp = elem[ ontype ]; + + if ( tmp ) { + elem[ ontype ] = null; + } + + // Prevent re-triggering of the same event, since we already bubbled it above + jQuery.event.triggered = type; + + if ( event.isPropagationStopped() ) { + lastElement.addEventListener( type, stopPropagationCallback ); + } + + elem[ type ](); + + if ( event.isPropagationStopped() ) { + lastElement.removeEventListener( type, stopPropagationCallback ); + } + + jQuery.event.triggered = undefined; + + if ( tmp ) { + elem[ ontype ] = tmp; + } + } + } + } + + return event.result; + }, + + // Piggyback on a donor event to simulate a different one + // Used only for `focus(in | out)` events + simulate: function( type, elem, event ) { + var e = jQuery.extend( + new jQuery.Event(), + event, + { + type: type, + isSimulated: true + } + ); + + jQuery.event.trigger( e, null, elem ); + } + +} ); + +jQuery.fn.extend( { + + trigger: function( type, data ) { + return this.each( function() { + jQuery.event.trigger( type, data, this ); + } ); + }, + triggerHandler: function( type, data ) { + var elem = this[ 0 ]; + if ( elem ) { + return jQuery.event.trigger( type, data, elem, true ); + } + } +} ); + + +// Support: Firefox <=44 +// Firefox doesn't have focus(in | out) events +// Related ticket - https://bugzilla.mozilla.org/show_bug.cgi?id=687787 +// +// Support: Chrome <=48 - 49, Safari <=9.0 - 9.1 +// focus(in | out) events fire after focus & blur events, +// which is spec violation - http://www.w3.org/TR/DOM-Level-3-Events/#events-focusevent-event-order +// Related ticket - https://bugs.chromium.org/p/chromium/issues/detail?id=449857 +if ( !support.focusin ) { + jQuery.each( { focus: "focusin", blur: "focusout" }, function( orig, fix ) { + + // Attach a single capturing handler on the document while someone wants focusin/focusout + var handler = function( event ) { + jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ) ); + }; + + jQuery.event.special[ fix ] = { + setup: function() { + + // Handle: regular nodes (via `this.ownerDocument`), window + // (via `this.document`) & document (via `this`). + var doc = this.ownerDocument || this.document || this, + attaches = dataPriv.access( doc, fix ); + + if ( !attaches ) { + doc.addEventListener( orig, handler, true ); + } + dataPriv.access( doc, fix, ( attaches || 0 ) + 1 ); + }, + teardown: function() { + var doc = this.ownerDocument || this.document || this, + attaches = dataPriv.access( doc, fix ) - 1; + + if ( !attaches ) { + doc.removeEventListener( orig, handler, true ); + dataPriv.remove( doc, fix ); + + } else { + dataPriv.access( doc, fix, attaches ); + } + } + }; + } ); +} +var location = window.location; + +var nonce = { guid: Date.now() }; + +var rquery = ( /\?/ ); + + + +// Cross-browser xml parsing +jQuery.parseXML = function( data ) { + var xml; + if ( !data || typeof data !== "string" ) { + return null; + } + + // Support: IE 9 - 11 only + // IE throws on parseFromString with invalid input. + try { + xml = ( new window.DOMParser() ).parseFromString( data, "text/xml" ); + } catch ( e ) { + xml = undefined; + } + + if ( !xml || xml.getElementsByTagName( "parsererror" ).length ) { + jQuery.error( "Invalid XML: " + data ); + } + return xml; +}; + + +var + rbracket = /\[\]$/, + rCRLF = /\r?\n/g, + rsubmitterTypes = /^(?:submit|button|image|reset|file)$/i, + rsubmittable = /^(?:input|select|textarea|keygen)/i; + +function buildParams( prefix, obj, traditional, add ) { + var name; + + if ( Array.isArray( obj ) ) { + + // Serialize array item. + jQuery.each( obj, function( i, v ) { + if ( traditional || rbracket.test( prefix ) ) { + + // Treat each array item as a scalar. + add( prefix, v ); + + } else { + + // Item is non-scalar (array or object), encode its numeric index. + buildParams( + prefix + "[" + ( typeof v === "object" && v != null ? i : "" ) + "]", + v, + traditional, + add + ); + } + } ); + + } else if ( !traditional && toType( obj ) === "object" ) { + + // Serialize object item. + for ( name in obj ) { + buildParams( prefix + "[" + name + "]", obj[ name ], traditional, add ); + } + + } else { + + // Serialize scalar item. + add( prefix, obj ); + } +} + +// Serialize an array of form elements or a set of +// key/values into a query string +jQuery.param = function( a, traditional ) { + var prefix, + s = [], + add = function( key, valueOrFunction ) { + + // If value is a function, invoke it and use its return value + var value = isFunction( valueOrFunction ) ? + valueOrFunction() : + valueOrFunction; + + s[ s.length ] = encodeURIComponent( key ) + "=" + + encodeURIComponent( value == null ? "" : value ); + }; + + if ( a == null ) { + return ""; + } + + // If an array was passed in, assume that it is an array of form elements. + if ( Array.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) { + + // Serialize the form elements + jQuery.each( a, function() { + add( this.name, this.value ); + } ); + + } else { + + // If traditional, encode the "old" way (the way 1.3.2 or older + // did it), otherwise encode params recursively. + for ( prefix in a ) { + buildParams( prefix, a[ prefix ], traditional, add ); + } + } + + // Return the resulting serialization + return s.join( "&" ); +}; + +jQuery.fn.extend( { + serialize: function() { + return jQuery.param( this.serializeArray() ); + }, + serializeArray: function() { + return this.map( function() { + + // Can add propHook for "elements" to filter or add form elements + var elements = jQuery.prop( this, "elements" ); + return elements ? jQuery.makeArray( elements ) : this; + } ) + .filter( function() { + var type = this.type; + + // Use .is( ":disabled" ) so that fieldset[disabled] works + return this.name && !jQuery( this ).is( ":disabled" ) && + rsubmittable.test( this.nodeName ) && !rsubmitterTypes.test( type ) && + ( this.checked || !rcheckableType.test( type ) ); + } ) + .map( function( _i, elem ) { + var val = jQuery( this ).val(); + + if ( val == null ) { + return null; + } + + if ( Array.isArray( val ) ) { + return jQuery.map( val, function( val ) { + return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) }; + } ); + } + + return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) }; + } ).get(); + } +} ); + + +var + r20 = /%20/g, + rhash = /#.*$/, + rantiCache = /([?&])_=[^&]*/, + rheaders = /^(.*?):[ \t]*([^\r\n]*)$/mg, + + // #7653, #8125, #8152: local protocol detection + rlocalProtocol = /^(?:about|app|app-storage|.+-extension|file|res|widget):$/, + rnoContent = /^(?:GET|HEAD)$/, + rprotocol = /^\/\//, + + /* Prefilters + * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example) + * 2) These are called: + * - BEFORE asking for a transport + * - AFTER param serialization (s.data is a string if s.processData is true) + * 3) key is the dataType + * 4) the catchall symbol "*" can be used + * 5) execution will start with transport dataType and THEN continue down to "*" if needed + */ + prefilters = {}, + + /* Transports bindings + * 1) key is the dataType + * 2) the catchall symbol "*" can be used + * 3) selection will start with transport dataType and THEN go to "*" if needed + */ + transports = {}, + + // Avoid comment-prolog char sequence (#10098); must appease lint and evade compression + allTypes = "*/".concat( "*" ), + + // Anchor tag for parsing the document origin + originAnchor = document.createElement( "a" ); + originAnchor.href = location.href; + +// Base "constructor" for jQuery.ajaxPrefilter and jQuery.ajaxTransport +function addToPrefiltersOrTransports( structure ) { + + // dataTypeExpression is optional and defaults to "*" + return function( dataTypeExpression, func ) { + + if ( typeof dataTypeExpression !== "string" ) { + func = dataTypeExpression; + dataTypeExpression = "*"; + } + + var dataType, + i = 0, + dataTypes = dataTypeExpression.toLowerCase().match( rnothtmlwhite ) || []; + + if ( isFunction( func ) ) { + + // For each dataType in the dataTypeExpression + while ( ( dataType = dataTypes[ i++ ] ) ) { + + // Prepend if requested + if ( dataType[ 0 ] === "+" ) { + dataType = dataType.slice( 1 ) || "*"; + ( structure[ dataType ] = structure[ dataType ] || [] ).unshift( func ); + + // Otherwise append + } else { + ( structure[ dataType ] = structure[ dataType ] || [] ).push( func ); + } + } + } + }; +} + +// Base inspection function for prefilters and transports +function inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR ) { + + var inspected = {}, + seekingTransport = ( structure === transports ); + + function inspect( dataType ) { + var selected; + inspected[ dataType ] = true; + jQuery.each( structure[ dataType ] || [], function( _, prefilterOrFactory ) { + var dataTypeOrTransport = prefilterOrFactory( options, originalOptions, jqXHR ); + if ( typeof dataTypeOrTransport === "string" && + !seekingTransport && !inspected[ dataTypeOrTransport ] ) { + + options.dataTypes.unshift( dataTypeOrTransport ); + inspect( dataTypeOrTransport ); + return false; + } else if ( seekingTransport ) { + return !( selected = dataTypeOrTransport ); + } + } ); + return selected; + } + + return inspect( options.dataTypes[ 0 ] ) || !inspected[ "*" ] && inspect( "*" ); +} + +// A special extend for ajax options +// that takes "flat" options (not to be deep extended) +// Fixes #9887 +function ajaxExtend( target, src ) { + var key, deep, + flatOptions = jQuery.ajaxSettings.flatOptions || {}; + + for ( key in src ) { + if ( src[ key ] !== undefined ) { + ( flatOptions[ key ] ? target : ( deep || ( deep = {} ) ) )[ key ] = src[ key ]; + } + } + if ( deep ) { + jQuery.extend( true, target, deep ); + } + + return target; +} + +/* Handles responses to an ajax request: + * - finds the right dataType (mediates between content-type and expected dataType) + * - returns the corresponding response + */ +function ajaxHandleResponses( s, jqXHR, responses ) { + + var ct, type, finalDataType, firstDataType, + contents = s.contents, + dataTypes = s.dataTypes; + + // Remove auto dataType and get content-type in the process + while ( dataTypes[ 0 ] === "*" ) { + dataTypes.shift(); + if ( ct === undefined ) { + ct = s.mimeType || jqXHR.getResponseHeader( "Content-Type" ); + } + } + + // Check if we're dealing with a known content-type + if ( ct ) { + for ( type in contents ) { + if ( contents[ type ] && contents[ type ].test( ct ) ) { + dataTypes.unshift( type ); + break; + } + } + } + + // Check to see if we have a response for the expected dataType + if ( dataTypes[ 0 ] in responses ) { + finalDataType = dataTypes[ 0 ]; + } else { + + // Try convertible dataTypes + for ( type in responses ) { + if ( !dataTypes[ 0 ] || s.converters[ type + " " + dataTypes[ 0 ] ] ) { + finalDataType = type; + break; + } + if ( !firstDataType ) { + firstDataType = type; + } + } + + // Or just use first one + finalDataType = finalDataType || firstDataType; + } + + // If we found a dataType + // We add the dataType to the list if needed + // and return the corresponding response + if ( finalDataType ) { + if ( finalDataType !== dataTypes[ 0 ] ) { + dataTypes.unshift( finalDataType ); + } + return responses[ finalDataType ]; + } +} + +/* Chain conversions given the request and the original response + * Also sets the responseXXX fields on the jqXHR instance + */ +function ajaxConvert( s, response, jqXHR, isSuccess ) { + var conv2, current, conv, tmp, prev, + converters = {}, + + // Work with a copy of dataTypes in case we need to modify it for conversion + dataTypes = s.dataTypes.slice(); + + // Create converters map with lowercased keys + if ( dataTypes[ 1 ] ) { + for ( conv in s.converters ) { + converters[ conv.toLowerCase() ] = s.converters[ conv ]; + } + } + + current = dataTypes.shift(); + + // Convert to each sequential dataType + while ( current ) { + + if ( s.responseFields[ current ] ) { + jqXHR[ s.responseFields[ current ] ] = response; + } + + // Apply the dataFilter if provided + if ( !prev && isSuccess && s.dataFilter ) { + response = s.dataFilter( response, s.dataType ); + } + + prev = current; + current = dataTypes.shift(); + + if ( current ) { + + // There's only work to do if current dataType is non-auto + if ( current === "*" ) { + + current = prev; + + // Convert response if prev dataType is non-auto and differs from current + } else if ( prev !== "*" && prev !== current ) { + + // Seek a direct converter + conv = converters[ prev + " " + current ] || converters[ "* " + current ]; + + // If none found, seek a pair + if ( !conv ) { + for ( conv2 in converters ) { + + // If conv2 outputs current + tmp = conv2.split( " " ); + if ( tmp[ 1 ] === current ) { + + // If prev can be converted to accepted input + conv = converters[ prev + " " + tmp[ 0 ] ] || + converters[ "* " + tmp[ 0 ] ]; + if ( conv ) { + + // Condense equivalence converters + if ( conv === true ) { + conv = converters[ conv2 ]; + + // Otherwise, insert the intermediate dataType + } else if ( converters[ conv2 ] !== true ) { + current = tmp[ 0 ]; + dataTypes.unshift( tmp[ 1 ] ); + } + break; + } + } + } + } + + // Apply converter (if not an equivalence) + if ( conv !== true ) { + + // Unless errors are allowed to bubble, catch and return them + if ( conv && s.throws ) { + response = conv( response ); + } else { + try { + response = conv( response ); + } catch ( e ) { + return { + state: "parsererror", + error: conv ? e : "No conversion from " + prev + " to " + current + }; + } + } + } + } + } + } + + return { state: "success", data: response }; +} + +jQuery.extend( { + + // Counter for holding the number of active queries + active: 0, + + // Last-Modified header cache for next request + lastModified: {}, + etag: {}, + + ajaxSettings: { + url: location.href, + type: "GET", + isLocal: rlocalProtocol.test( location.protocol ), + global: true, + processData: true, + async: true, + contentType: "application/x-www-form-urlencoded; charset=UTF-8", + + /* + timeout: 0, + data: null, + dataType: null, + username: null, + password: null, + cache: null, + throws: false, + traditional: false, + headers: {}, + */ + + accepts: { + "*": allTypes, + text: "text/plain", + html: "text/html", + xml: "application/xml, text/xml", + json: "application/json, text/javascript" + }, + + contents: { + xml: /\bxml\b/, + html: /\bhtml/, + json: /\bjson\b/ + }, + + responseFields: { + xml: "responseXML", + text: "responseText", + json: "responseJSON" + }, + + // Data converters + // Keys separate source (or catchall "*") and destination types with a single space + converters: { + + // Convert anything to text + "* text": String, + + // Text to html (true = no transformation) + "text html": true, + + // Evaluate text as a json expression + "text json": JSON.parse, + + // Parse text as xml + "text xml": jQuery.parseXML + }, + + // For options that shouldn't be deep extended: + // you can add your own custom options here if + // and when you create one that shouldn't be + // deep extended (see ajaxExtend) + flatOptions: { + url: true, + context: true + } + }, + + // Creates a full fledged settings object into target + // with both ajaxSettings and settings fields. + // If target is omitted, writes into ajaxSettings. + ajaxSetup: function( target, settings ) { + return settings ? + + // Building a settings object + ajaxExtend( ajaxExtend( target, jQuery.ajaxSettings ), settings ) : + + // Extending ajaxSettings + ajaxExtend( jQuery.ajaxSettings, target ); + }, + + ajaxPrefilter: addToPrefiltersOrTransports( prefilters ), + ajaxTransport: addToPrefiltersOrTransports( transports ), + + // Main method + ajax: function( url, options ) { + + // If url is an object, simulate pre-1.5 signature + if ( typeof url === "object" ) { + options = url; + url = undefined; + } + + // Force options to be an object + options = options || {}; + + var transport, + + // URL without anti-cache param + cacheURL, + + // Response headers + responseHeadersString, + responseHeaders, + + // timeout handle + timeoutTimer, + + // Url cleanup var + urlAnchor, + + // Request state (becomes false upon send and true upon completion) + completed, + + // To know if global events are to be dispatched + fireGlobals, + + // Loop variable + i, + + // uncached part of the url + uncached, + + // Create the final options object + s = jQuery.ajaxSetup( {}, options ), + + // Callbacks context + callbackContext = s.context || s, + + // Context for global events is callbackContext if it is a DOM node or jQuery collection + globalEventContext = s.context && + ( callbackContext.nodeType || callbackContext.jquery ) ? + jQuery( callbackContext ) : + jQuery.event, + + // Deferreds + deferred = jQuery.Deferred(), + completeDeferred = jQuery.Callbacks( "once memory" ), + + // Status-dependent callbacks + statusCode = s.statusCode || {}, + + // Headers (they are sent all at once) + requestHeaders = {}, + requestHeadersNames = {}, + + // Default abort message + strAbort = "canceled", + + // Fake xhr + jqXHR = { + readyState: 0, + + // Builds headers hashtable if needed + getResponseHeader: function( key ) { + var match; + if ( completed ) { + if ( !responseHeaders ) { + responseHeaders = {}; + while ( ( match = rheaders.exec( responseHeadersString ) ) ) { + responseHeaders[ match[ 1 ].toLowerCase() + " " ] = + ( responseHeaders[ match[ 1 ].toLowerCase() + " " ] || [] ) + .concat( match[ 2 ] ); + } + } + match = responseHeaders[ key.toLowerCase() + " " ]; + } + return match == null ? null : match.join( ", " ); + }, + + // Raw string + getAllResponseHeaders: function() { + return completed ? responseHeadersString : null; + }, + + // Caches the header + setRequestHeader: function( name, value ) { + if ( completed == null ) { + name = requestHeadersNames[ name.toLowerCase() ] = + requestHeadersNames[ name.toLowerCase() ] || name; + requestHeaders[ name ] = value; + } + return this; + }, + + // Overrides response content-type header + overrideMimeType: function( type ) { + if ( completed == null ) { + s.mimeType = type; + } + return this; + }, + + // Status-dependent callbacks + statusCode: function( map ) { + var code; + if ( map ) { + if ( completed ) { + + // Execute the appropriate callbacks + jqXHR.always( map[ jqXHR.status ] ); + } else { + + // Lazy-add the new callbacks in a way that preserves old ones + for ( code in map ) { + statusCode[ code ] = [ statusCode[ code ], map[ code ] ]; + } + } + } + return this; + }, + + // Cancel the request + abort: function( statusText ) { + var finalText = statusText || strAbort; + if ( transport ) { + transport.abort( finalText ); + } + done( 0, finalText ); + return this; + } + }; + + // Attach deferreds + deferred.promise( jqXHR ); + + // Add protocol if not provided (prefilters might expect it) + // Handle falsy url in the settings object (#10093: consistency with old signature) + // We also use the url parameter if available + s.url = ( ( url || s.url || location.href ) + "" ) + .replace( rprotocol, location.protocol + "//" ); + + // Alias method option to type as per ticket #12004 + s.type = options.method || options.type || s.method || s.type; + + // Extract dataTypes list + s.dataTypes = ( s.dataType || "*" ).toLowerCase().match( rnothtmlwhite ) || [ "" ]; + + // A cross-domain request is in order when the origin doesn't match the current origin. + if ( s.crossDomain == null ) { + urlAnchor = document.createElement( "a" ); + + // Support: IE <=8 - 11, Edge 12 - 15 + // IE throws exception on accessing the href property if url is malformed, + // e.g. http://example.com:80x/ + try { + urlAnchor.href = s.url; + + // Support: IE <=8 - 11 only + // Anchor's host property isn't correctly set when s.url is relative + urlAnchor.href = urlAnchor.href; + s.crossDomain = originAnchor.protocol + "//" + originAnchor.host !== + urlAnchor.protocol + "//" + urlAnchor.host; + } catch ( e ) { + + // If there is an error parsing the URL, assume it is crossDomain, + // it can be rejected by the transport if it is invalid + s.crossDomain = true; + } + } + + // Convert data if not already a string + if ( s.data && s.processData && typeof s.data !== "string" ) { + s.data = jQuery.param( s.data, s.traditional ); + } + + // Apply prefilters + inspectPrefiltersOrTransports( prefilters, s, options, jqXHR ); + + // If request was aborted inside a prefilter, stop there + if ( completed ) { + return jqXHR; + } + + // We can fire global events as of now if asked to + // Don't fire events if jQuery.event is undefined in an AMD-usage scenario (#15118) + fireGlobals = jQuery.event && s.global; + + // Watch for a new set of requests + if ( fireGlobals && jQuery.active++ === 0 ) { + jQuery.event.trigger( "ajaxStart" ); + } + + // Uppercase the type + s.type = s.type.toUpperCase(); + + // Determine if request has content + s.hasContent = !rnoContent.test( s.type ); + + // Save the URL in case we're toying with the If-Modified-Since + // and/or If-None-Match header later on + // Remove hash to simplify url manipulation + cacheURL = s.url.replace( rhash, "" ); + + // More options handling for requests with no content + if ( !s.hasContent ) { + + // Remember the hash so we can put it back + uncached = s.url.slice( cacheURL.length ); + + // If data is available and should be processed, append data to url + if ( s.data && ( s.processData || typeof s.data === "string" ) ) { + cacheURL += ( rquery.test( cacheURL ) ? "&" : "?" ) + s.data; + + // #9682: remove data so that it's not used in an eventual retry + delete s.data; + } + + // Add or update anti-cache param if needed + if ( s.cache === false ) { + cacheURL = cacheURL.replace( rantiCache, "$1" ); + uncached = ( rquery.test( cacheURL ) ? "&" : "?" ) + "_=" + ( nonce.guid++ ) + + uncached; + } + + // Put hash and anti-cache on the URL that will be requested (gh-1732) + s.url = cacheURL + uncached; + + // Change '%20' to '+' if this is encoded form body content (gh-2658) + } else if ( s.data && s.processData && + ( s.contentType || "" ).indexOf( "application/x-www-form-urlencoded" ) === 0 ) { + s.data = s.data.replace( r20, "+" ); + } + + // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode. + if ( s.ifModified ) { + if ( jQuery.lastModified[ cacheURL ] ) { + jqXHR.setRequestHeader( "If-Modified-Since", jQuery.lastModified[ cacheURL ] ); + } + if ( jQuery.etag[ cacheURL ] ) { + jqXHR.setRequestHeader( "If-None-Match", jQuery.etag[ cacheURL ] ); + } + } + + // Set the correct header, if data is being sent + if ( s.data && s.hasContent && s.contentType !== false || options.contentType ) { + jqXHR.setRequestHeader( "Content-Type", s.contentType ); + } + + // Set the Accepts header for the server, depending on the dataType + jqXHR.setRequestHeader( + "Accept", + s.dataTypes[ 0 ] && s.accepts[ s.dataTypes[ 0 ] ] ? + s.accepts[ s.dataTypes[ 0 ] ] + + ( s.dataTypes[ 0 ] !== "*" ? ", " + allTypes + "; q=0.01" : "" ) : + s.accepts[ "*" ] + ); + + // Check for headers option + for ( i in s.headers ) { + jqXHR.setRequestHeader( i, s.headers[ i ] ); + } + + // Allow custom headers/mimetypes and early abort + if ( s.beforeSend && + ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || completed ) ) { + + // Abort if not done already and return + return jqXHR.abort(); + } + + // Aborting is no longer a cancellation + strAbort = "abort"; + + // Install callbacks on deferreds + completeDeferred.add( s.complete ); + jqXHR.done( s.success ); + jqXHR.fail( s.error ); + + // Get transport + transport = inspectPrefiltersOrTransports( transports, s, options, jqXHR ); + + // If no transport, we auto-abort + if ( !transport ) { + done( -1, "No Transport" ); + } else { + jqXHR.readyState = 1; + + // Send global event + if ( fireGlobals ) { + globalEventContext.trigger( "ajaxSend", [ jqXHR, s ] ); + } + + // If request was aborted inside ajaxSend, stop there + if ( completed ) { + return jqXHR; + } + + // Timeout + if ( s.async && s.timeout > 0 ) { + timeoutTimer = window.setTimeout( function() { + jqXHR.abort( "timeout" ); + }, s.timeout ); + } + + try { + completed = false; + transport.send( requestHeaders, done ); + } catch ( e ) { + + // Rethrow post-completion exceptions + if ( completed ) { + throw e; + } + + // Propagate others as results + done( -1, e ); + } + } + + // Callback for when everything is done + function done( status, nativeStatusText, responses, headers ) { + var isSuccess, success, error, response, modified, + statusText = nativeStatusText; + + // Ignore repeat invocations + if ( completed ) { + return; + } + + completed = true; + + // Clear timeout if it exists + if ( timeoutTimer ) { + window.clearTimeout( timeoutTimer ); + } + + // Dereference transport for early garbage collection + // (no matter how long the jqXHR object will be used) + transport = undefined; + + // Cache response headers + responseHeadersString = headers || ""; + + // Set readyState + jqXHR.readyState = status > 0 ? 4 : 0; + + // Determine if successful + isSuccess = status >= 200 && status < 300 || status === 304; + + // Get response data + if ( responses ) { + response = ajaxHandleResponses( s, jqXHR, responses ); + } + + // Use a noop converter for missing script + if ( !isSuccess && jQuery.inArray( "script", s.dataTypes ) > -1 ) { + s.converters[ "text script" ] = function() {}; + } + + // Convert no matter what (that way responseXXX fields are always set) + response = ajaxConvert( s, response, jqXHR, isSuccess ); + + // If successful, handle type chaining + if ( isSuccess ) { + + // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode. + if ( s.ifModified ) { + modified = jqXHR.getResponseHeader( "Last-Modified" ); + if ( modified ) { + jQuery.lastModified[ cacheURL ] = modified; + } + modified = jqXHR.getResponseHeader( "etag" ); + if ( modified ) { + jQuery.etag[ cacheURL ] = modified; + } + } + + // if no content + if ( status === 204 || s.type === "HEAD" ) { + statusText = "nocontent"; + + // if not modified + } else if ( status === 304 ) { + statusText = "notmodified"; + + // If we have data, let's convert it + } else { + statusText = response.state; + success = response.data; + error = response.error; + isSuccess = !error; + } + } else { + + // Extract error from statusText and normalize for non-aborts + error = statusText; + if ( status || !statusText ) { + statusText = "error"; + if ( status < 0 ) { + status = 0; + } + } + } + + // Set data for the fake xhr object + jqXHR.status = status; + jqXHR.statusText = ( nativeStatusText || statusText ) + ""; + + // Success/Error + if ( isSuccess ) { + deferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] ); + } else { + deferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] ); + } + + // Status-dependent callbacks + jqXHR.statusCode( statusCode ); + statusCode = undefined; + + if ( fireGlobals ) { + globalEventContext.trigger( isSuccess ? "ajaxSuccess" : "ajaxError", + [ jqXHR, s, isSuccess ? success : error ] ); + } + + // Complete + completeDeferred.fireWith( callbackContext, [ jqXHR, statusText ] ); + + if ( fireGlobals ) { + globalEventContext.trigger( "ajaxComplete", [ jqXHR, s ] ); + + // Handle the global AJAX counter + if ( !( --jQuery.active ) ) { + jQuery.event.trigger( "ajaxStop" ); + } + } + } + + return jqXHR; + }, + + getJSON: function( url, data, callback ) { + return jQuery.get( url, data, callback, "json" ); + }, + + getScript: function( url, callback ) { + return jQuery.get( url, undefined, callback, "script" ); + } +} ); + +jQuery.each( [ "get", "post" ], function( _i, method ) { + jQuery[ method ] = function( url, data, callback, type ) { + + // Shift arguments if data argument was omitted + if ( isFunction( data ) ) { + type = type || callback; + callback = data; + data = undefined; + } + + // The url can be an options object (which then must have .url) + return jQuery.ajax( jQuery.extend( { + url: url, + type: method, + dataType: type, + data: data, + success: callback + }, jQuery.isPlainObject( url ) && url ) ); + }; +} ); + +jQuery.ajaxPrefilter( function( s ) { + var i; + for ( i in s.headers ) { + if ( i.toLowerCase() === "content-type" ) { + s.contentType = s.headers[ i ] || ""; + } + } +} ); + + +jQuery._evalUrl = function( url, options, doc ) { + return jQuery.ajax( { + url: url, + + // Make this explicit, since user can override this through ajaxSetup (#11264) + type: "GET", + dataType: "script", + cache: true, + async: false, + global: false, + + // Only evaluate the response if it is successful (gh-4126) + // dataFilter is not invoked for failure responses, so using it instead + // of the default converter is kludgy but it works. + converters: { + "text script": function() {} + }, + dataFilter: function( response ) { + jQuery.globalEval( response, options, doc ); + } + } ); +}; + + +jQuery.fn.extend( { + wrapAll: function( html ) { + var wrap; + + if ( this[ 0 ] ) { + if ( isFunction( html ) ) { + html = html.call( this[ 0 ] ); + } + + // The elements to wrap the target around + wrap = jQuery( html, this[ 0 ].ownerDocument ).eq( 0 ).clone( true ); + + if ( this[ 0 ].parentNode ) { + wrap.insertBefore( this[ 0 ] ); + } + + wrap.map( function() { + var elem = this; + + while ( elem.firstElementChild ) { + elem = elem.firstElementChild; + } + + return elem; + } ).append( this ); + } + + return this; + }, + + wrapInner: function( html ) { + if ( isFunction( html ) ) { + return this.each( function( i ) { + jQuery( this ).wrapInner( html.call( this, i ) ); + } ); + } + + return this.each( function() { + var self = jQuery( this ), + contents = self.contents(); + + if ( contents.length ) { + contents.wrapAll( html ); + + } else { + self.append( html ); + } + } ); + }, + + wrap: function( html ) { + var htmlIsFunction = isFunction( html ); + + return this.each( function( i ) { + jQuery( this ).wrapAll( htmlIsFunction ? html.call( this, i ) : html ); + } ); + }, + + unwrap: function( selector ) { + this.parent( selector ).not( "body" ).each( function() { + jQuery( this ).replaceWith( this.childNodes ); + } ); + return this; + } +} ); + + +jQuery.expr.pseudos.hidden = function( elem ) { + return !jQuery.expr.pseudos.visible( elem ); +}; +jQuery.expr.pseudos.visible = function( elem ) { + return !!( elem.offsetWidth || elem.offsetHeight || elem.getClientRects().length ); +}; + + + + +jQuery.ajaxSettings.xhr = function() { + try { + return new window.XMLHttpRequest(); + } catch ( e ) {} +}; + +var xhrSuccessStatus = { + + // File protocol always yields status code 0, assume 200 + 0: 200, + + // Support: IE <=9 only + // #1450: sometimes IE returns 1223 when it should be 204 + 1223: 204 + }, + xhrSupported = jQuery.ajaxSettings.xhr(); + +support.cors = !!xhrSupported && ( "withCredentials" in xhrSupported ); +support.ajax = xhrSupported = !!xhrSupported; + +jQuery.ajaxTransport( function( options ) { + var callback, errorCallback; + + // Cross domain only allowed if supported through XMLHttpRequest + if ( support.cors || xhrSupported && !options.crossDomain ) { + return { + send: function( headers, complete ) { + var i, + xhr = options.xhr(); + + xhr.open( + options.type, + options.url, + options.async, + options.username, + options.password + ); + + // Apply custom fields if provided + if ( options.xhrFields ) { + for ( i in options.xhrFields ) { + xhr[ i ] = options.xhrFields[ i ]; + } + } + + // Override mime type if needed + if ( options.mimeType && xhr.overrideMimeType ) { + xhr.overrideMimeType( options.mimeType ); + } + + // X-Requested-With header + // For cross-domain requests, seeing as conditions for a preflight are + // akin to a jigsaw puzzle, we simply never set it to be sure. + // (it can always be set on a per-request basis or even using ajaxSetup) + // For same-domain requests, won't change header if already provided. + if ( !options.crossDomain && !headers[ "X-Requested-With" ] ) { + headers[ "X-Requested-With" ] = "XMLHttpRequest"; + } + + // Set headers + for ( i in headers ) { + xhr.setRequestHeader( i, headers[ i ] ); + } + + // Callback + callback = function( type ) { + return function() { + if ( callback ) { + callback = errorCallback = xhr.onload = + xhr.onerror = xhr.onabort = xhr.ontimeout = + xhr.onreadystatechange = null; + + if ( type === "abort" ) { + xhr.abort(); + } else if ( type === "error" ) { + + // Support: IE <=9 only + // On a manual native abort, IE9 throws + // errors on any property access that is not readyState + if ( typeof xhr.status !== "number" ) { + complete( 0, "error" ); + } else { + complete( + + // File: protocol always yields status 0; see #8605, #14207 + xhr.status, + xhr.statusText + ); + } + } else { + complete( + xhrSuccessStatus[ xhr.status ] || xhr.status, + xhr.statusText, + + // Support: IE <=9 only + // IE9 has no XHR2 but throws on binary (trac-11426) + // For XHR2 non-text, let the caller handle it (gh-2498) + ( xhr.responseType || "text" ) !== "text" || + typeof xhr.responseText !== "string" ? + { binary: xhr.response } : + { text: xhr.responseText }, + xhr.getAllResponseHeaders() + ); + } + } + }; + }; + + // Listen to events + xhr.onload = callback(); + errorCallback = xhr.onerror = xhr.ontimeout = callback( "error" ); + + // Support: IE 9 only + // Use onreadystatechange to replace onabort + // to handle uncaught aborts + if ( xhr.onabort !== undefined ) { + xhr.onabort = errorCallback; + } else { + xhr.onreadystatechange = function() { + + // Check readyState before timeout as it changes + if ( xhr.readyState === 4 ) { + + // Allow onerror to be called first, + // but that will not handle a native abort + // Also, save errorCallback to a variable + // as xhr.onerror cannot be accessed + window.setTimeout( function() { + if ( callback ) { + errorCallback(); + } + } ); + } + }; + } + + // Create the abort callback + callback = callback( "abort" ); + + try { + + // Do send the request (this may raise an exception) + xhr.send( options.hasContent && options.data || null ); + } catch ( e ) { + + // #14683: Only rethrow if this hasn't been notified as an error yet + if ( callback ) { + throw e; + } + } + }, + + abort: function() { + if ( callback ) { + callback(); + } + } + }; + } +} ); + + + + +// Prevent auto-execution of scripts when no explicit dataType was provided (See gh-2432) +jQuery.ajaxPrefilter( function( s ) { + if ( s.crossDomain ) { + s.contents.script = false; + } +} ); + +// Install script dataType +jQuery.ajaxSetup( { + accepts: { + script: "text/javascript, application/javascript, " + + "application/ecmascript, application/x-ecmascript" + }, + contents: { + script: /\b(?:java|ecma)script\b/ + }, + converters: { + "text script": function( text ) { + jQuery.globalEval( text ); + return text; + } + } +} ); + +// Handle cache's special case and crossDomain +jQuery.ajaxPrefilter( "script", function( s ) { + if ( s.cache === undefined ) { + s.cache = false; + } + if ( s.crossDomain ) { + s.type = "GET"; + } +} ); + +// Bind script tag hack transport +jQuery.ajaxTransport( "script", function( s ) { + + // This transport only deals with cross domain or forced-by-attrs requests + if ( s.crossDomain || s.scriptAttrs ) { + var script, callback; + return { + send: function( _, complete ) { + script = jQuery( " + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra - Exceptions and Enums

+
+
+cassandra.__version_info__
+

The version of the driver in a tuple format

+
+ +
+
+cassandra.__version__
+

The version of the driver in a string format

+
+ +
+
+class cassandra.ConsistencyLevel
+

Spcifies how many replicas must respond for an operation to be considered +a success. By default, ONE is used for all operations.

+
+
+ANY = 0
+

Only requires that one replica receives the write or the coordinator +stores a hint to replay later. Valid only for writes.

+
+ +
+
+ONE = 1
+

Only one replica needs to respond to consider the operation a success

+
+ +
+
+TWO = 2
+

Two replicas must respond to consider the operation a success

+
+ +
+
+THREE = 3
+

Three replicas must respond to consider the operation a success

+
+ +
+
+QUORUM = 4
+

ceil(RF/2) + 1 replicas must respond to consider the operation a success

+
+ +
+
+ALL = 5
+

All replicas must respond to consider the operation a success

+
+ +
+
+LOCAL_QUORUM = 6
+

Requires a quorum of replicas in the local datacenter

+
+ +
+
+EACH_QUORUM = 7
+

Requires a quorum of replicas in each datacenter

+
+ +
+
+SERIAL = 8
+

For conditional inserts/updates that utilize Cassandra’s lightweight +transactions, this requires consensus among all replicas for the +modified data.

+
+ +
+
+LOCAL_SERIAL = 9
+

Like SERIAL, but only requires consensus +among replicas in the local datacenter.

+
+ +
+
+LOCAL_ONE = 10
+

Sends a request only to replicas in the local datacenter and waits for +one response.

+
+ +
+ +
+
+class cassandra.ProtocolVersion
+

Defines native protocol versions supported by this driver.

+
+
+V1 = 1
+

v1, supported in Cassandra 1.2–>2.2

+
+ +
+
+V2 = 2
+

v2, supported in Cassandra 2.0–>2.2; +added support for lightweight transactions, batch operations, and automatic query paging.

+
+ +
+
+V3 = 3
+

v3, supported in Cassandra 2.1–>3.x+; +added support for protocol-level client-side timestamps (see Session.use_client_timestamp), +serial consistency levels for BatchStatement, and an improved connection pool.

+
+ +
+
+V4 = 4
+

v4, supported in Cassandra 2.2–>3.x+; +added a number of new types, server warnings, new failure messages, and custom payloads. Details in the +project docs

+
+ +
+
+V5 = 5
+

v5, in beta from 3.x+. Finalised in 4.0-beta5

+
+ +
+
+V6 = 6
+

v6, in beta from 4.0-beta5

+
+ +
+
+DSE_V1 = 65
+

DSE private protocol v1, supported in DSE 5.1+

+
+ +
+
+DSE_V2 = 66
+

DSE private protocol v2, supported in DSE 6.0+

+
+ +
+
+SUPPORTED_VERSIONS = (66, 65, 6, 5, 4, 3, 2, 1)
+

A tuple of all supported protocol versions

+
+ +
+
+BETA_VERSIONS = (6,)
+

A tuple of all beta protocol versions

+
+ +
+
+MIN_SUPPORTED = 1
+

Minimum protocol version supported by this driver.

+
+ +
+
+MAX_SUPPORTED = 66
+

Maximum protocol version supported by this driver.

+
+ +
+
+classmethod get_lower_supported(previous_version)
+

Return the lower supported protocol version. Beta versions are omitted.

+
+ +
+ +
+
+class cassandra.UserFunctionDescriptor(name, argument_types)
+

Describes a User function by name and argument signature

+
+
+name = None
+

name of the function

+
+ +
+
+argument_types = None
+

Ordered list of CQL argument type names comprising the type signature

+
+ +
+
+property signature
+

function signature string in the form ‘name([type0[,type1[…]]])’

+

can be used to uniquely identify overloaded function names within a keyspace

+
+ +
+ +
+
+class cassandra.UserAggregateDescriptor(name, argument_types)
+

Describes a User aggregate function by name and argument signature

+
+
+name = None
+

name of the aggregate

+
+ +
+
+argument_types = None
+

Ordered list of CQL argument type names comprising the type signature

+
+ +
+
+property signature
+

function signature string in the form ‘name([type0[,type1[…]]])’

+

can be used to uniquely identify overloaded function names within a keyspace

+
+ +
+ +
+
+exception cassandra.DriverException
+

Base for all exceptions explicitly raised by the driver.

+
+ +
+
+exception cassandra.RequestExecutionException
+

Base for request execution exceptions returned from the server.

+
+ +
+
+exception cassandra.Unavailable
+

There were not enough live replicas to satisfy the requested consistency +level, so the coordinator node immediately failed the request without +forwarding it to any replicas.

+
+
+consistency = None
+

The requested ConsistencyLevel

+
+ +
+
+required_replicas = None
+

The number of replicas that needed to be live to complete the operation

+
+ +
+
+alive_replicas = None
+

The number of replicas that were actually alive

+
+ +
+ +
+
+exception cassandra.Timeout
+

Replicas failed to respond to the coordinator node before timing out.

+
+
+consistency = None
+

The requested ConsistencyLevel

+
+ +
+
+required_responses = None
+

The number of required replica responses

+
+ +
+
+received_responses = None
+

The number of replicas that responded before the coordinator timed out +the operation

+
+ +
+ +
+
+exception cassandra.ReadTimeout
+

A subclass of Timeout for read operations.

+

This indicates that the replicas failed to respond to the coordinator +node before the configured timeout. This timeout is configured in +cassandra.yaml with the read_request_timeout_in_ms +and range_request_timeout_in_ms options.

+
+
+data_retrieved = None
+

A boolean indicating whether the requested data was retrieved +by the coordinator from any replicas before it timed out the +operation

+
+ +
+ +
+
+exception cassandra.WriteTimeout
+

A subclass of Timeout for write operations.

+

This indicates that the replicas failed to respond to the coordinator +node before the configured timeout. This timeout is configured in +cassandra.yaml with the write_request_timeout_in_ms +option.

+
+
+write_type = None
+

The type of write operation, enum on WriteType

+
+ +
+ +
+
+exception cassandra.CoordinationFailure
+

Replicas sent a failure to the coordinator.

+
+
+consistency = None
+

The requested ConsistencyLevel

+
+ +
+
+required_responses = None
+

The number of required replica responses

+
+ +
+
+received_responses = None
+

The number of replicas that responded before the coordinator timed out +the operation

+
+ +
+
+failures = None
+

The number of replicas that sent a failure message

+
+ +
+
+error_code_map = None
+

A map of inet addresses to error codes representing replicas that sent +a failure message. Only set when protocol_version is 5 or higher.

+
+ +
+ +
+
+exception cassandra.ReadFailure
+

A subclass of CoordinationFailure for read operations.

+

This indicates that the replicas sent a failure message to the coordinator.

+
+
+data_retrieved = None
+

A boolean indicating whether the requested data was retrieved +by the coordinator from any replicas before it timed out the +operation

+
+ +
+ +
+
+exception cassandra.WriteFailure
+

A subclass of CoordinationFailure for write operations.

+

This indicates that the replicas sent a failure message to the coordinator.

+
+
+write_type = None
+

The type of write operation, enum on WriteType

+
+ +
+ +
+
+exception cassandra.FunctionFailure
+

User Defined Function failed during execution

+
+
+keyspace = None
+

Keyspace of the function

+
+ +
+
+function = None
+

Name of the function

+
+ +
+
+arg_types = None
+

List of argument type names of the function

+
+ +
+ +
+
+exception cassandra.RequestValidationException
+

Server request validation failed

+
+ +
+
+exception cassandra.ConfigurationException
+

Server indicated request errro due to current configuration

+
+ +
+
+exception cassandra.AlreadyExists
+

An attempt was made to create a keyspace or table that already exists.

+
+
+keyspace = None
+

The name of the keyspace that already exists, or, if an attempt was +made to create a new table, the keyspace that the table is in.

+
+ +
+
+table = None
+

The name of the table that already exists, or, if an attempt was +make to create a keyspace, None.

+
+ +
+ +
+
+exception cassandra.InvalidRequest
+

A query was made that was invalid for some reason, such as trying to set +the keyspace for a connection to a nonexistent keyspace.

+
+ +
+
+exception cassandra.Unauthorized
+

The current user is not authorized to perform the requested operation.

+
+ +
+
+exception cassandra.AuthenticationFailed
+

Failed to authenticate.

+
+ +
+
+exception cassandra.OperationTimedOut
+

The operation took longer than the specified (client-side) timeout +to complete. This is not an error generated by Cassandra, only +the driver.

+
+
+errors = None
+

A dict of errors keyed by the Host against which they occurred.

+
+ +
+
+last_host = None
+

The last Host this operation was attempted against.

+
+ +
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.22.3-scylla/api/cassandra/auth.html b/3.22.3-scylla/api/cassandra/auth.html new file mode 100644 index 0000000000..c8bf418b10 --- /dev/null +++ b/3.22.3-scylla/api/cassandra/auth.html @@ -0,0 +1,806 @@ + + + + + + + + + + + + + cassandra.auth - Authentication | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.auth - Authentication

+
+
+class cassandra.auth.AuthProvider
+

An abstract class that defines the interface that will be used for +creating Authenticator instances when opening new +connections to Cassandra.

+
+

New in version 2.0.0.

+
+
+
+new_authenticator(host)
+

Implementations of this class should return a new instance +of Authenticator or one of its subclasses.

+
+ +
+ +
+
+class cassandra.auth.Authenticator
+

An abstract class that handles SASL authentication with Cassandra servers.

+

Each time a new connection is created and the server requires authentication, +a new instance of this class will be created by the corresponding +AuthProvider to handler that authentication. The lifecycle of the +new Authenticator will the be:

+

1) The initial_response() method will be called. The return +value will be sent to the server to initiate the handshake.

+

2) The server will respond to each client response by either issuing a +challenge or indicating that the authentication is complete (successful or not). +If a new challenge is issued, evaluate_challenge() +will be called to produce a response that will be sent to the +server. This challenge/response negotiation will continue until the server +responds that authentication is successful (or an AuthenticationFailed +is raised).

+

3) When the server indicates that authentication is successful, +on_authentication_success() will be called a token string that +that the server may optionally have sent.

+

The exact nature of the negotiation between the client and server is specific +to the authentication mechanism configured server-side.

+
+

New in version 2.0.0.

+
+
+
+server_authenticator_class = None
+

Set during the connection AUTHENTICATE phase

+
+ +
+
+initial_response()
+

Returns an message to send to the server to initiate the SASL handshake. +None may be returned to send an empty message.

+
+ +
+
+evaluate_challenge(challenge)
+

Called when the server sends a challenge message. Generally, this method +should return None when authentication is complete from a +client perspective. Otherwise, a string should be returned.

+
+ +
+
+on_authentication_success(token)
+

Called when the server indicates that authentication was successful. +Depending on the authentication mechanism, token may be None +or a string.

+
+ +
+ +
+
+class cassandra.auth.PlainTextAuthProvider(username, password)
+

An AuthProvider that works with Cassandra’s PasswordAuthenticator.

+

Example usage:

+
from cassandra.cluster import Cluster
+from cassandra.auth import PlainTextAuthProvider
+
+auth_provider = PlainTextAuthProvider(
+        username='cassandra', password='cassandra')
+cluster = Cluster(auth_provider=auth_provider)
+
+
+
+

New in version 2.0.0.

+
+
+
+new_authenticator(host)
+

Implementations of this class should return a new instance +of Authenticator or one of its subclasses.

+
+ +
+ +
+
+class cassandra.auth.PlainTextAuthenticator(username, password)
+
+
+evaluate_challenge(challenge)
+

Called when the server sends a challenge message. Generally, this method +should return None when authentication is complete from a +client perspective. Otherwise, a string should be returned.

+
+ +
+ +
+
+class cassandra.auth.SaslAuthProvider(**sasl_kwargs)
+

An AuthProvider supporting general SASL auth mechanisms

+

Suitable for GSSAPI or other SASL mechanisms

+

Example usage:

+
from cassandra.cluster import Cluster
+from cassandra.auth import SaslAuthProvider
+
+sasl_kwargs = {'service': 'something',
+               'mechanism': 'GSSAPI',
+               'qops': 'auth'.split(',')}
+auth_provider = SaslAuthProvider(**sasl_kwargs)
+cluster = Cluster(auth_provider=auth_provider)
+
+
+
+

New in version 2.1.4.

+
+
+
+new_authenticator(host)
+

Implementations of this class should return a new instance +of Authenticator or one of its subclasses.

+
+ +
+ +
+
+class cassandra.auth.SaslAuthenticator(host, service, mechanism='GSSAPI', **sasl_kwargs)
+

A pass-through Authenticator using the third party package +‘pure-sasl’ for authentication

+
+

New in version 2.1.4.

+
+
+
+initial_response()
+

Returns an message to send to the server to initiate the SASL handshake. +None may be returned to send an empty message.

+
+ +
+
+evaluate_challenge(challenge)
+

Called when the server sends a challenge message. Generally, this method +should return None when authentication is complete from a +client perspective. Otherwise, a string should be returned.

+
+ +
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.22.3-scylla/api/cassandra/cluster.html b/3.22.3-scylla/api/cassandra/cluster.html new file mode 100644 index 0000000000..66a61b6300 --- /dev/null +++ b/3.22.3-scylla/api/cassandra/cluster.html @@ -0,0 +1,1778 @@ + + + + + + + + + + + + + cassandra.cluster - Clusters and Sessions | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.cluster - Clusters and Sessions

+
+
+class cassandra.cluster.Cluster([contact_points=('127.0.0.1',)][, port=9042][, executor_threads=2], **attr_kwargs)
+

The main class to use when interacting with a Cassandra cluster. +Typically, one instance of this class will be created for each +separate Cassandra cluster that your application interacts with.

+

Example usage:

+
>>> from cassandra.cluster import Cluster
+>>> cluster = Cluster(['192.168.1.1', '192.168.1.2'])
+>>> session = cluster.connect()
+>>> session.execute("CREATE KEYSPACE ...")
+>>> ...
+>>> cluster.shutdown()
+
+
+

Cluster and Session also provide context management functions +which implicitly handle shutdown when leaving scope.

+

executor_threads defines the number of threads in a pool for handling asynchronous tasks such as +extablishing connection pools or refreshing metadata.

+

Any of the mutable Cluster attributes may be set as keyword arguments to the constructor.

+
+
+contact_points = ['127.0.0.1']
+
+ +
+
+port = 9042
+
+ +
+
+cql_version = None
+
+ +
+
+protocol_version = 66
+
+ +
+
+compression = True
+
+ +
+
+auth_provider
+

When protocol_version is 2 or higher, this should +be an instance of a subclass of AuthProvider, +such as PlainTextAuthProvider.

+

When protocol_version is 1, this should be +a function that accepts one argument, the IP address of a node, +and returns a dict of credentials for that node.

+

When not using authentication, this should be left as None.

+
+ +
+
+load_balancing_policy
+

An instance of policies.LoadBalancingPolicy or +one of its subclasses.

+
+

Changed in version 2.6.0.

+
+

Defaults to TokenAwarePolicy (DCAwareRoundRobinPolicy). +when using CPython (where the murmur3 extension is available). DCAwareRoundRobinPolicy +otherwise. Default local DC will be chosen from contact points.

+

Please see DCAwareRoundRobinPolicy for a discussion on default behavior with respect to +DC locality and remote nodes.

+
+ +
+
+reconnection_policy = <cassandra.policies.ExponentialReconnectionPolicy object>
+
+ +
+
+default_retry_policy = <cassandra.policies.RetryPolicy object>
+

A default policies.RetryPolicy instance to use for all +Statement objects which do not have a retry_policy +explicitly set.

+
+ +
+
+conviction_policy_factory = <class 'cassandra.policies.SimpleConvictionPolicy'>
+
+ +
+
+address_translator = <cassandra.policies.IdentityTranslator object>
+
+ +
+
+metrics_enabled = False
+
+ +
+
+metrics = None
+
+ +
+
+ssl_context = None
+
+ +
+
+ssl_options = None
+
+ +
+
+sockopts = None
+
+ +
+
+max_schema_agreement_wait = 10
+
+ +
+
+metadata = None
+
+ +
+
+connection_class = <class 'cassandra.io.libevreactor.LibevConnection'>
+
+ +
+
+control_connection_timeout = 2.0
+
+ +
+
+idle_heartbeat_interval = 30
+
+ +
+
+idle_heartbeat_timeout = 30
+
+ +
+
+schema_event_refresh_window = 2
+
+ +
+
+topology_event_refresh_window = 10
+
+ +
+
+status_event_refresh_window = 2
+
+ +
+
+prepare_on_all_hosts = True
+
+ +
+
+reprepare_on_up = True
+
+ +
+
+connect_timeout = 5
+
+ +
+
+schema_metadata_enabled = True
+

Flag indicating whether internal schema metadata is updated.

+

When disabled, the driver does not populate Cluster.metadata.keyspaces on connect, or on schema change events. This +can be used to speed initial connection, and reduce load on client and server during operation. Turning this off +gives away token aware request routing, and programmatic inspection of the metadata model.

+
+ +
+
+token_metadata_enabled = True
+

Flag indicating whether internal token metadata is updated.

+

When disabled, the driver does not query node token information on connect, or on topology change events. This +can be used to speed initial connection, and reduce load on client and server during operation. It is most useful +in large clusters using vnodes, where the token map can be expensive to compute. Turning this off +gives away token aware request routing, and programmatic inspection of the token ring.

+
+ +
+
+timestamp_generator = None
+
+ +
+
+endpoint_factory = None
+
+ +
+
+cloud = None
+
+ +
+
+connect(keyspace=None, wait_for_all_pools=False)
+

Creates and returns a new Session object.

+

If keyspace is specified, that keyspace will be the default keyspace for +operations on the Session.

+

wait_for_all_pools specifies whether this call should wait for all connection pools to be +established or attempted. Default is False, which means it will return when the first +successful connection is established. Remaining pools are added asynchronously.

+
+ +
+
+shutdown()
+

Closes all sessions and connection associated with this Cluster. +To ensure all connections are properly closed, you should always +call shutdown() on a Cluster instance when you are done with it.

+

Once shutdown, a Cluster should not be used for any purpose.

+
+ +
+
+register_user_type(keyspace, user_type, klass)
+

Registers a class to use to represent a particular user-defined type. +Query parameters for this user-defined type will be assumed to be +instances of klass. Result sets for this user-defined type will +be instances of klass. If no class is registered for a user-defined +type, a namedtuple will be used for result sets, and non-prepared +statements may not encode parameters for this type correctly.

+

keyspace is the name of the keyspace that the UDT is defined in.

+

user_type is the string name of the UDT to register the mapping +for.

+

klass should be a class with attributes whose names match the +fields of the user-defined type. The constructor must accepts kwargs +for each of the fields in the UDT.

+

This method should only be called after the type has been created +within Cassandra.

+

Example:

+
cluster = Cluster(protocol_version=3)
+session = cluster.connect()
+session.set_keyspace('mykeyspace')
+session.execute("CREATE TYPE address (street text, zipcode int)")
+session.execute("CREATE TABLE users (id int PRIMARY KEY, location address)")
+
+# create a class to map to the "address" UDT
+class Address(object):
+
+    def __init__(self, street, zipcode):
+        self.street = street
+        self.zipcode = zipcode
+
+cluster.register_user_type('mykeyspace', 'address', Address)
+
+# insert a row using an instance of Address
+session.execute("INSERT INTO users (id, location) VALUES (%s, %s)",
+                (0, Address("123 Main St.", 78723)))
+
+# results will include Address instances
+results = session.execute("SELECT * FROM users")
+row = results[0]
+print row.id, row.location.street, row.location.zipcode
+
+
+
+ +
+
+register_listener(listener)
+

Adds a cassandra.policies.HostStateListener subclass instance to +the list of listeners to be notified when a host is added, removed, +marked up, or marked down.

+
+ +
+
+unregister_listener(listener)
+

Removes a registered listener.

+
+ +
+
+add_execution_profile(name, profile, pool_wait_timeout=5)
+

Adds an ExecutionProfile to the cluster. This makes it available for use by name in Session.execute() +and Session.execute_async(). This method will raise if the profile already exists.

+

Normally profiles will be injected at cluster initialization via Cluster(execution_profiles). This method +provides a way of adding them dynamically.

+

Adding a new profile updates the connection pools according to the specified load_balancing_policy. By default, +this method will wait up to five seconds for the pool creation to complete, so the profile can be used immediately +upon return. This behavior can be controlled using pool_wait_timeout (see +concurrent.futures.wait +for timeout semantics).

+
+ +
+
+set_max_requests_per_connection(host_distance, max_requests)
+

Sets a threshold for concurrent requests per connection, above which new +connections will be created to a host (up to max connections; +see set_max_connections_per_host()).

+

Pertains to connection pool management in protocol versions {1,2}.

+
+ +
+
+get_max_requests_per_connection(host_distance)
+
+ +
+
+set_min_requests_per_connection(host_distance, min_requests)
+

Sets a threshold for concurrent requests per connection, below which +connections will be considered for disposal (down to core connections; +see set_core_connections_per_host()).

+

Pertains to connection pool management in protocol versions {1,2}.

+
+ +
+
+get_min_requests_per_connection(host_distance)
+
+ +
+
+get_core_connections_per_host(host_distance)
+

Gets the minimum number of connections per Session that will be opened +for each host with HostDistance equal to host_distance. +The default is 2 for LOCAL and 1 for +REMOTE.

+

This property is ignored if protocol_version is +3 or higher.

+
+ +
+
+set_core_connections_per_host(host_distance, core_connections)
+

Sets the minimum number of connections per Session that will be opened +for each host with HostDistance equal to host_distance. +The default is 2 for LOCAL and 1 for +REMOTE.

+

Protocol version 1 and 2 are limited in the number of concurrent +requests they can send per connection. The driver implements connection +pooling to support higher levels of concurrency.

+

If protocol_version is set to 3 or higher, this +is not supported (there is always one connection per host, unless +the host is remote and connect_to_remote_hosts is False) +and using this will result in an UnsupportedOperation.

+
+ +
+
+get_max_connections_per_host(host_distance)
+

Gets the maximum number of connections per Session that will be opened +for each host with HostDistance equal to host_distance. +The default is 8 for LOCAL and 2 for +REMOTE.

+

This property is ignored if protocol_version is +3 or higher.

+
+ +
+
+set_max_connections_per_host(host_distance, max_connections)
+

Sets the maximum number of connections per Session that will be opened +for each host with HostDistance equal to host_distance. +The default is 2 for LOCAL and 1 for +REMOTE.

+

If protocol_version is set to 3 or higher, this +is not supported (there is always one connection per host, unless +the host is remote and connect_to_remote_hosts is False) +and using this will result in an UnsupportedOperation.

+
+ +
+
+get_control_connection_host()
+

Returns the control connection host metadata.

+
+ +
+
+refresh_schema_metadata(max_schema_agreement_wait=None)
+

Synchronously refresh all schema metadata.

+

By default, the timeout for this operation is governed by max_schema_agreement_wait +and control_connection_timeout.

+

Passing max_schema_agreement_wait here overrides max_schema_agreement_wait.

+

Setting max_schema_agreement_wait <= 0 will bypass schema agreement and refresh schema immediately.

+

An Exception is raised if schema refresh fails for any reason.

+
+ +
+
+refresh_keyspace_metadata(keyspace, max_schema_agreement_wait=None)
+

Synchronously refresh keyspace metadata. This applies to keyspace-level information such as replication +and durability settings. It does not refresh tables, types, etc. contained in the keyspace.

+

See refresh_schema_metadata() for description of max_schema_agreement_wait behavior

+
+ +
+
+refresh_table_metadata(keyspace, table, max_schema_agreement_wait=None)
+

Synchronously refresh table metadata. This applies to a table, and any triggers or indexes attached +to the table.

+

See refresh_schema_metadata() for description of max_schema_agreement_wait behavior

+
+ +
+
+refresh_user_type_metadata(keyspace, user_type, max_schema_agreement_wait=None)
+

Synchronously refresh user defined type metadata.

+

See refresh_schema_metadata() for description of max_schema_agreement_wait behavior

+
+ +
+
+refresh_user_function_metadata(keyspace, function, max_schema_agreement_wait=None)
+

Synchronously refresh user defined function metadata.

+

function is a cassandra.UserFunctionDescriptor.

+

See refresh_schema_metadata() for description of max_schema_agreement_wait behavior

+
+ +
+
+refresh_user_aggregate_metadata(keyspace, aggregate, max_schema_agreement_wait=None)
+

Synchronously refresh user defined aggregate metadata.

+

aggregate is a cassandra.UserAggregateDescriptor.

+

See refresh_schema_metadata() for description of max_schema_agreement_wait behavior

+
+ +
+
+refresh_nodes(force_token_rebuild=False)
+

Synchronously refresh the node list and token metadata

+

force_token_rebuild can be used to rebuild the token map metadata, even if no new nodes are discovered.

+

An Exception is raised if node refresh fails for any reason.

+
+ +
+
+set_meta_refresh_enabled(enabled)
+

Deprecated: set schema_metadata_enabled token_metadata_enabled instead

+

Sets a flag to enable (True) or disable (False) all metadata refresh queries. +This applies to both schema and node topology.

+

Disabling this is useful to minimize refreshes during multiple changes.

+

Meta refresh must be enabled for the driver to become aware of any cluster +topology changes or schema updates.

+
+ +
+ +
+
+class cassandra.cluster.ExecutionProfile(load_balancing_policy=<object object>, retry_policy=None, consistency_level=ConsistencyLevel.LOCAL_ONE, serial_consistency_level=None, request_timeout=10.0, row_factory=<function named_tuple_factory>, speculative_execution_policy=None)
+
+
+consistency_level = LOCAL_ONE
+
+ +
+
+static row_factory(colnames, rows)
+

Returns each row as a namedtuple. +This is the default row factory.

+

Example:

+
>>> from cassandra.query import named_tuple_factory
+>>> session = cluster.connect('mykeyspace')
+>>> session.row_factory = named_tuple_factory
+>>> rows = session.execute("SELECT name, age FROM users LIMIT 1")
+>>> user = rows[0]
+
+>>> # you can access field by their name:
+>>> print "name: %s, age: %d" % (user.name, user.age)
+name: Bob, age: 42
+
+>>> # or you can access fields by their position (like a tuple)
+>>> name, age = user
+>>> print "name: %s, age: %d" % (name, age)
+name: Bob, age: 42
+>>> name = user[0]
+>>> age = user[1]
+>>> print "name: %s, age: %d" % (name, age)
+name: Bob, age: 42
+
+
+
+

Changed in version 2.0.0: moved from cassandra.decoder to cassandra.query

+
+
+ +
+ +
+
+class cassandra.cluster.GraphExecutionProfile(load_balancing_policy=_NOT_SET, retry_policy=None, consistency_level=ConsistencyLevel.LOCAL_ONE, serial_consistency_level=None, request_timeout=30.0, row_factory=None, graph_options=None, continuous_paging_options=_NOT_SET)
+

Default execution profile for graph execution.

+

See ExecutionProfile for base attributes. Note that if not explicitly set, +the row_factory and graph_options.graph_protocol are resolved during the query execution. +These options will resolve to graph_graphson3_row_factory and GraphProtocol.GRAPHSON_3_0 +for the core graph engine (DSE 6.8+), otherwise graph_object_row_factory and GraphProtocol.GRAPHSON_1_0

+

In addition to default parameters shown in the signature, this profile also defaults retry_policy to +cassandra.policies.NeverRetryPolicy.

+
+ +
+
+class cassandra.cluster.GraphAnalyticsExecutionProfile(load_balancing_policy=None, retry_policy=None, consistency_level=ConsistencyLevel.LOCAL_ONE, serial_consistency_level=None, request_timeout=3600.0 * 24.0 * 7.0, row_factory=None, graph_options=None)
+

Execution profile with timeout and load balancing appropriate for graph analytics queries.

+

See also GraphExecutionPolicy.

+

In addition to default parameters shown in the signature, this profile also defaults retry_policy to +cassandra.policies.NeverRetryPolicy, and load_balancing_policy to one that targets the current Spark +master.

+

Note: The graph_options.graph_source is set automatically to b’a’ (analytics) +when using GraphAnalyticsExecutionProfile. This is mandatory to target analytics nodes.

+
+ +
+
+cassandra.cluster.EXEC_PROFILE_DEFAULT
+

The most base type

+
+ +
+
+cassandra.cluster.EXEC_PROFILE_GRAPH_DEFAULT
+

The most base type

+
+ +
+
+cassandra.cluster.EXEC_PROFILE_GRAPH_SYSTEM_DEFAULT
+

The most base type

+
+ +
+
+cassandra.cluster.EXEC_PROFILE_GRAPH_ANALYTICS_DEFAULT
+

The most base type

+
+ +
+
+class cassandra.cluster.Session
+

A collection of connection pools for each host in the cluster. +Instances of this class should not be created directly, only +using Cluster.connect().

+

Queries and statements can be executed through Session instances +using the execute() and execute_async() +methods.

+

Example usage:

+
>>> session = cluster.connect()
+>>> session.set_keyspace("mykeyspace")
+>>> session.execute("SELECT * FROM mycf")
+
+
+
+
+default_timeout = 10.0
+

A default timeout, measured in seconds, for queries executed through +execute() or execute_async(). This default may be +overridden with the timeout parameter for either of those methods.

+

Setting this to None will cause no timeouts to be set by default.

+

Please see ResponseFuture.result() for details on the scope and +effect of this timeout.

+
+

New in version 2.0.0.

+
+
+ +
+
+default_consistency_level = LOCAL_ONE
+

Deprecated: use execution profiles instead +The default ConsistencyLevel for operations executed through +this session. This default may be overridden by setting the +consistency_level on individual statements.

+
+

New in version 1.2.0.

+
+
+

Changed in version 3.0.0: default changed from ONE to LOCAL_ONE

+
+
+ +
+
+default_serial_consistency_level = None
+

The default ConsistencyLevel for serial phase of conditional updates executed through +this session. This default may be overridden by setting the +serial_consistency_level on individual statements.

+

Only valid for protocol_version >= 2.

+
+ +
+
+row_factory = <function named_tuple_factory>
+

The format to return row results in. By default, each +returned row will be a named tuple. You can alternatively +use any of the following:

+ +
+ +
+
+default_fetch_size = 5000
+
+ +
+
+use_client_timestamp = True
+
+ +
+
+timestamp_generator = None
+
+ +
+
+encoder = None
+
+ +
+
+client_protocol_handler = <class 'cassandra.protocol.cython_protocol_handler.<locals>.CythonProtocolHandler'>
+
+ +
+
+execute(statement[, parameters][, timeout][, trace][, custom_payload][, paging_state][, host][, execute_as])
+

Execute the given query and synchronously wait for the response.

+

If an error is encountered while executing the query, an Exception +will be raised.

+

query may be a query string or an instance of cassandra.query.Statement.

+

parameters may be a sequence or dict of parameters to bind. If a +sequence is used, %s should be used the placeholder for each +argument. If a dict is used, %(name)s style placeholders must +be used.

+

timeout should specify a floating-point timeout (in seconds) after +which an OperationTimedOut exception will be raised if the query +has not completed. If not set, the timeout defaults to the request_timeout of the selected execution_profile. +If set to None, there is no timeout. Please see ResponseFuture.result() for details on +the scope and effect of this timeout.

+

If trace is set to True, the query will be sent with tracing enabled. +The trace details can be obtained using the returned ResultSet object.

+

custom_payload is a Custom Payloads dict to be passed to the server. +If query is a Statement with its own custom_payload. The message payload +will be a union of the two, with the values specified here taking precedence.

+

execution_profile is the execution profile to use for this request. It can be a key to a profile configured +via Cluster.add_execution_profile() or an instance (from Session.execution_profile_clone_update(), +for example

+

paging_state is an optional paging state, reused from a previous ResultSet.

+

host is the cassandra.pool.Host that should handle the query. If the host specified is down or +not yet connected, the query will fail with NoHostAvailable. Using this is +discouraged except in a few cases, e.g., querying node-local tables and applying schema changes.

+

execute_as the user that will be used on the server to execute the request. This is only available +on a DSE cluster.

+
+ +
+
+execute_async(statement[, parameters][, trace][, custom_payload][, paging_state][, host][, execute_as])
+

Execute the given query and return a ResponseFuture object +which callbacks may be attached to for asynchronous response +delivery. You may also call result() +on the ResponseFuture to synchronously block for results at +any time.

+

See Session.execute() for parameter definitions.

+

Example usage:

+
>>> session = cluster.connect()
+>>> future = session.execute_async("SELECT * FROM mycf")
+
+>>> def log_results(results):
+...     for row in results:
+...         log.info("Results: %s", row)
+
+>>> def log_error(exc):
+>>>     log.error("Operation failed: %s", exc)
+
+>>> future.add_callbacks(log_results, log_error)
+
+
+

Async execution with blocking wait for results:

+
>>> future = session.execute_async("SELECT * FROM mycf")
+>>> # do other stuff...
+
+>>> try:
+...     results = future.result()
+... except Exception:
+...     log.exception("Operation failed:")
+
+
+
+ +
+
+execute_graph(statement[, parameters][, trace][, execution_profile=EXEC_PROFILE_GRAPH_DEFAULT][, execute_as])
+

Executes a Gremlin query string or GraphStatement synchronously, +and returns a ResultSet from this execution.

+

parameters is dict of named parameters to bind. The values must be +JSON-serializable.

+

execution_profile: Selects an execution profile for the request.

+

execute_as the user that will be used on the server to execute the request.

+
+ +
+
+execute_graph_async(statement[, parameters][, trace][, execution_profile=EXEC_PROFILE_GRAPH_DEFAULT][, execute_as])
+

Execute the graph query and return a ResponseFuture +object which callbacks may be attached to for asynchronous response delivery. You may also call ResponseFuture.result() to synchronously block for +results at any time.

+
+ +
+
+prepare(statement)
+

Prepares a query string, returning a PreparedStatement +instance which can be used as follows:

+
>>> session = cluster.connect("mykeyspace")
+>>> query = "INSERT INTO users (id, name, age) VALUES (?, ?, ?)"
+>>> prepared = session.prepare(query)
+>>> session.execute(prepared, (user.id, user.name, user.age))
+
+
+

Or you may bind values to the prepared statement ahead of time:

+
>>> prepared = session.prepare(query)
+>>> bound_stmt = prepared.bind((user.id, user.name, user.age))
+>>> session.execute(bound_stmt)
+
+
+

Of course, prepared statements may (and should) be reused:

+
>>> prepared = session.prepare(query)
+>>> for user in users:
+...     bound = prepared.bind((user.id, user.name, user.age))
+...     session.execute(bound)
+
+
+

Alternatively, if protocol_version is 5 or higher +(requires Cassandra 4.0+), the keyspace can be specified as a +parameter. This will allow you to avoid specifying the keyspace in the +query without specifying a keyspace in connect(). It +even will let you prepare and use statements against a keyspace other +than the one originally specified on connection:

+
>>> analyticskeyspace_prepared = session.prepare(
+...     "INSERT INTO user_activity id, last_activity VALUES (?, ?)",
+...     keyspace="analyticskeyspace")  # note the different keyspace
+
+
+

Important: PreparedStatements should be prepared only once. +Preparing the same query more than once will likely affect performance.

+

custom_payload is a key value map to be passed along with the prepare +message. See Custom Payloads.

+
+ +
+
+shutdown()
+

Close all connections. Session instances should not be used +for any purpose after being shutdown.

+
+ +
+
+set_keyspace(keyspace)
+

Set the default keyspace for all queries made through this Session. +This operation blocks until complete.

+
+ +
+
+get_execution_profile(name)
+

Returns the execution profile associated with the provided name.

+
+
Parameters
+

name – The name (or key) of the execution profile.

+
+
+
+ +
+
+execution_profile_clone_update(ep, **kwargs)
+

Returns a clone of the ep profile. kwargs can be specified to update attributes +of the returned profile.

+

This is a shallow clone, so any objects referenced by the profile are shared. This means Load Balancing Policy +is maintained by inclusion in the active profiles. It also means updating any other rich objects will be seen +by the active profile. In cases where this is not desirable, be sure to replace the instance instead of manipulating +the shared object.

+
+ +
+
+add_request_init_listener(fn, *args, **kwargs)
+

Adds a callback with arguments to be called when any request is created.

+

It will be invoked as fn(response_future, *args, **kwargs) after each client request is created, +and before the request is sent. This can be used to create extensions by adding result callbacks to the +response future.

+

response_future is the ResponseFuture for the request.

+

Note that the init callback is done on the client thread creating the request, so you may need to consider +synchronization if you have multiple threads. Any callbacks added to the response future will be executed +on the event loop thread, so the normal advice about minimizing cycles and avoiding blocking apply (see Note in +ResponseFuture.add_callbacks().

+

See this example in the +source tree for an example.

+
+ +
+
+remove_request_init_listener(fn, *args, **kwargs)
+

Removes a callback and arguments from the list.

+

See Session.add_request_init_listener().

+
+ +
+ +
+
+class cassandra.cluster.ResponseFuture
+

An asynchronous response delivery mechanism that is returned from calls +to Session.execute_async().

+
+
There are two ways for results to be delivered:
+
+
+
+
+query = None
+
+ +
+
+result()
+

Return the final result or raise an Exception if errors were +encountered. If the final result or error has not been set +yet, this method will block until it is set, or the timeout +set for the request expires.

+

Timeout is specified in the Session request execution functions. +If the timeout is exceeded, an cassandra.OperationTimedOut will be raised. +This is a client-side timeout. For more information +about server-side coordinator timeouts, see policies.RetryPolicy.

+

Example usage:

+
>>> future = session.execute_async("SELECT * FROM mycf")
+>>> # do other stuff...
+
+>>> try:
+...     rows = future.result()
+...     for row in rows:
+...         ... # process results
+... except Exception:
+...     log.exception("Operation failed:")
+
+
+
+ +
+
+get_query_trace()
+

Fetches and returns the query trace of the last response, or None if tracing was +not enabled.

+

Note that this may raise an exception if there are problems retrieving the trace +details from Cassandra. If the trace is not available after max_wait, +cassandra.query.TraceUnavailable will be raised.

+

If the ResponseFuture is not done (async execution) and you try to retrieve the trace, +cassandra.query.TraceUnavailable will be raised.

+

query_cl is the consistency level used to poll the trace tables.

+
+ +
+
+get_all_query_traces()
+

Fetches and returns the query traces for all query pages, if tracing was enabled.

+

See note in get_query_trace() regarding possible exceptions.

+
+ +
+
+custom_payload
+

The custom payload returned from the server, if any. This will only be +set by Cassandra servers implementing a custom QueryHandler, and only +for protocol_version 4+.

+

Ensure the future is complete before trying to access this property +(call result(), or after callback is invoked). +Otherwise it may throw if the response has not been received.

+
+
Returns
+

Custom Payloads.

+
+
+
+ +
+
+is_schema_agreed = True
+
+ +
+
+has_more_pages
+

Returns True if there are more pages left in the +query results, False otherwise. This should only +be checked after the first page has been returned.

+
+

New in version 2.0.0.

+
+
+ +
+
+warnings
+

Warnings returned from the server, if any. This will only be +set for protocol_version 4+.

+

Warnings may be returned for such things as oversized batches, +or too many tombstones in slice queries.

+

Ensure the future is complete before trying to access this property +(call result(), or after callback is invoked). +Otherwise it may throw if the response has not been received.

+
+ +
+
+start_fetching_next_page()
+

If there are more pages left in the query result, this asynchronously +starts fetching the next page. If there are no pages left, QueryExhausted +is raised. Also see has_more_pages.

+

This should only be called after the first page has been returned.

+
+

New in version 2.0.0.

+
+
+ +
+
+add_callback(fn, *args, **kwargs)
+

Attaches a callback function to be called when the final results arrive.

+

By default, fn will be called with the results as the first and only +argument. If *args or **kwargs are supplied, they will be passed +through as additional positional or keyword arguments to fn.

+

If an error is hit while executing the operation, a callback attached +here will not be called. Use add_errback() or add_callbacks() +if you wish to handle that case.

+

If the final result has already been seen when this method is called, +the callback will be called immediately (before this method returns).

+

Note: in the case that the result is not available when the callback is added, +the callback is executed by IO event thread. This means that the callback +should not block or attempt further synchronous requests, because no further +IO will be processed until the callback returns.

+

Important: if the callback you attach results in an exception being +raised, the exception will be ignored, so please ensure your +callback handles all error cases that you care about.

+

Usage example:

+
>>> session = cluster.connect("mykeyspace")
+
+>>> def handle_results(rows, start_time, should_log=False):
+...     if should_log:
+...         log.info("Total time: %f", time.time() - start_time)
+...     ...
+
+>>> future = session.execute_async("SELECT * FROM users")
+>>> future.add_callback(handle_results, time.time(), should_log=True)
+
+
+
+ +
+
+add_errback(fn, *args, **kwargs)
+

Like add_callback(), but handles error cases. +An Exception instance will be passed as the first positional argument +to fn.

+
+ +
+
+ResponseFuture.add_callbacks(callback, errback, callback_args=(), callback_kwargs=None, errback_args=(), errback_args=None)
+

A convenient combination of add_callback() and +add_errback().

+

Example usage:

+
>>> session = cluster.connect()
+>>> query = "SELECT * FROM mycf"
+>>> future = session.execute_async(query)
+
+>>> def log_results(results, level='debug'):
+...     for row in results:
+...         log.log(level, "Result: %s", row)
+
+>>> def log_error(exc, query):
+...     log.error("Query '%s' failed: %s", query, exc)
+
+>>> future.add_callbacks(
+...     callback=log_results, callback_kwargs={'level': 'info'},
+...     errback=log_error, errback_args=(query,))
+
+
+
+ +
+ +
+
+class cassandra.cluster.ResultSet
+

An iterator over the rows from a query result. Also supplies basic equality +and indexing methods for backward-compatability. These methods materialize +the entire result set (loading all pages), and should only be used if the +total result size is understood. Warnings are emitted when paged results +are materialized in this fashion.

+

You can treat this as a normal iterator over rows:

+
>>> from cassandra.query import SimpleStatement
+>>> statement = SimpleStatement("SELECT * FROM users", fetch_size=10)
+>>> for user_row in session.execute(statement):
+...     process_user(user_row)
+
+
+

Whenever there are no more rows in the current page, the next page will +be fetched transparently. However, note that it is possible for +an Exception to be raised while fetching the next page, just +like you might see on a normal call to session.execute().

+
+
+all()
+

Returns all the remaining rows as a list. This is basically +a convenient shortcut to list(result_set).

+

This function is not recommended for queries that return a large number of elements.

+
+ +
+
+property current_rows
+

The list of current page rows. May be empty if the result was empty, +or this is the last page.

+
+ +
+
+fetch_next_page()
+

Manually, synchronously fetch the next page. Supplied for manually retrieving pages +and inspecting current_page(). It is not necessary to call this when iterating +through results; paging happens implicitly in iteration.

+
+ +
+
+get_all_query_traces(max_wait_sec_per=None)
+

Gets all query traces from the associated future. +See ResponseFuture.get_all_query_traces() for details.

+
+ +
+
+get_query_trace(max_wait_sec=None)
+

Gets the last query trace from the associated future. +See ResponseFuture.get_query_trace() for details.

+
+ +
+
+property has_more_pages
+

True if the last response indicated more pages; False otherwise

+
+ +
+
+one()
+

Return a single row of the results or None if empty. This is basically +a shortcut to result_set.current_rows[0] and should only be used when +you know a query returns a single row. Consider using an iterator if the +ResultSet contains more than one row.

+
+ +
+
+property paging_state
+

Server paging state of the query. Can be None if the query was not paged.

+

The driver treats paging state as opaque, but it may contain primary key data, so applications may want to +avoid sending this to untrusted parties.

+
+ +
+
+property was_applied
+

For LWT results, returns whether the transaction was applied.

+

Result is indeterminate if called on a result that was not an LWT request or on +a query.BatchStatement containing LWT. In the latter case either all the batch +succeeds or fails.

+

Only valid when one of the of the internal row factories is in use.

+
+ +
+ +
+
+exception cassandra.cluster.QueryExhausted
+

Raised when ResponseFuture.start_fetching_next_page() is called and +there are no more pages. You can check ResponseFuture.has_more_pages +before calling to avoid this.

+
+

New in version 2.0.0.

+
+
+ +
+
+exception cassandra.cluster.NoHostAvailable
+

Raised when an operation is attempted but all connections are +busy, defunct, closed, or resulted in errors when used.

+
+ +
+
+exception cassandra.cluster.UserTypeDoesNotExist
+

An attempt was made to use a user-defined type that does not exist.

+
+

New in version 2.1.0.

+
+
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.22.3-scylla/api/cassandra/concurrent.html b/3.22.3-scylla/api/cassandra/concurrent.html new file mode 100644 index 0000000000..64e888a838 --- /dev/null +++ b/3.22.3-scylla/api/cassandra/concurrent.html @@ -0,0 +1,710 @@ + + + + + + + + + + + + + cassandra.concurrent - Utilities for Concurrent Statement Execution | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.concurrent - Utilities for Concurrent Statement Execution

+
+
+cassandra.concurrent.execute_concurrent(session, statements_and_parameters, concurrency=100, raise_on_first_error=True, results_generator=False, execution_profile=<object object>)
+

Executes a sequence of (statement, parameters) tuples concurrently. Each +parameters item must be a sequence or None.

+

The concurrency parameter controls how many statements will be executed +concurrently. When Cluster.protocol_version is set to 1 or 2, +it is recommended that this be kept below 100 times the number of +core connections per host times the number of connected hosts (see +Cluster.set_core_connections_per_host()). If that amount is exceeded, +the event loop thread may attempt to block on new connection creation, +substantially impacting throughput. If protocol_version +is 3 or higher, you can safely experiment with higher levels of concurrency.

+

If raise_on_first_error is left as True, execution will stop +after the first failed statement and the corresponding exception will be +raised.

+

results_generator controls how the results are returned.

+
    +
  • If False, the results are returned only after all requests have completed.

  • +
  • If True, a generator expression is returned. Using a generator results in a constrained +memory footprint when the results set will be large – results are yielded +as they return instead of materializing the entire list at once. The trade for lower memory +footprint is marginal CPU overhead (more thread coordination and sorting out-of-order results +on-the-fly).

  • +
+

execution_profile argument is the execution profile to use for this +request, it is passed directly to Session.execute_async().

+

A sequence of ExecutionResult(success, result_or_exc) namedtuples is returned +in the same order that the statements were passed in. If success is False, +there was an error executing the statement, and result_or_exc will be +an Exception. If success is True, result_or_exc +will be the query result.

+

Example usage:

+
select_statement = session.prepare("SELECT * FROM users WHERE id=?")
+
+statements_and_params = []
+for user_id in user_ids:
+    params = (user_id, )
+    statements_and_params.append((select_statement, params))
+
+results = execute_concurrent(
+    session, statements_and_params, raise_on_first_error=False)
+
+for (success, result) in results:
+    if not success:
+        handle_error(result)  # result will be an Exception
+    else:
+        process_user(result[0])  # result will be a list of rows
+
+
+

Note: in the case that generators are used, it is important to ensure the consumers do not +block or attempt further synchronous requests, because no further IO will be processed until +the consumer returns. This may also produce a deadlock in the IO event thread.

+
+ +
+
+cassandra.concurrent.execute_concurrent_with_args(session, statement, parameters, *args, **kwargs)
+

Like execute_concurrent(), but takes a single +statement and a sequence of parameters. Each item in parameters +should be a sequence or None.

+

Example usage:

+
statement = session.prepare("INSERT INTO mytable (a, b) VALUES (1, ?)")
+parameters = [(x,) for x in range(1000)]
+execute_concurrent_with_args(session, statement, parameters, concurrency=50)
+
+
+
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.22.3-scylla/api/cassandra/connection.html b/3.22.3-scylla/api/cassandra/connection.html new file mode 100644 index 0000000000..99fa4b43ff --- /dev/null +++ b/3.22.3-scylla/api/cassandra/connection.html @@ -0,0 +1,738 @@ + + + + + + + + + + + + + cassandra.connection - Low Level Connection Info | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.connection - Low Level Connection Info

+
+
+exception cassandra.connection.ConnectionException
+

An unrecoverable error was hit when attempting to use a connection, +or the connection was already closed or defunct.

+
+ +
+
+exception cassandra.connection.ConnectionShutdown
+

Raised when a connection has been marked as defunct or has been closed.

+
+ +
+
+exception cassandra.connection.ConnectionBusy
+

An attempt was made to send a message through a Connection that +was already at the max number of in-flight operations.

+
+ +
+
+exception cassandra.connection.ProtocolError
+

Communication did not match the protocol that this driver expects.

+
+ +
+
+class cassandra.connection.EndPoint
+

Represents the information to connect to a cassandra node.

+
+
+property address
+

The IP address of the node. This is the RPC address the driver uses when connecting to the node

+
+ +
+
+property port
+

The port of the node.

+
+ +
+
+resolve()
+

Resolve the endpoint to an address/port. This is called +only on socket connection.

+
+ +
+
+property socket_family
+

The socket family of the endpoint.

+
+ +
+
+property ssl_options
+

SSL options specific to this endpoint.

+
+ +
+ +
+
+class cassandra.connection.EndPointFactory
+
+
+configure(cluster)
+

This is called by the cluster during its initialization.

+
+ +
+
+create(row)
+

Create an EndPoint from a system.peers row.

+
+ +
+ +
+
+class cassandra.connection.SniEndPoint(proxy_address, server_name, port=9042)
+

SNI Proxy EndPoint implementation.

+
+ +
+
+class cassandra.connection.SniEndPointFactory(proxy_address, port, node_domain=None)
+
+ +
+
+class cassandra.connection.UnixSocketEndPoint(unix_socket_path)
+

Unix Socket EndPoint implementation.

+
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.22.3-scylla/api/cassandra/cqlengine/columns.html b/3.22.3-scylla/api/cassandra/cqlengine/columns.html new file mode 100644 index 0000000000..5c96ae7a7e --- /dev/null +++ b/3.22.3-scylla/api/cassandra/cqlengine/columns.html @@ -0,0 +1,956 @@ + + + + + + + + + + + + + cassandra.cqlengine.columns - Column types for object mapping models | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.cqlengine.columns - Column types for object mapping models

+
+

Columns

+

Columns in your models map to columns in your CQL table. You define CQL columns by defining column attributes on your model classes. +For a model to be valid it needs at least one primary key column and one non-primary key column.

+

Just as in CQL, the order you define your columns in is important, and is the same order they are defined in on a model’s corresponding table.

+

Each column on your model definitions needs to be an instance of a Column class.

+
+
+class cassandra.cqlengine.columns.Column(**kwargs)
+
+
+primary_key = False
+

bool flag, indicates this column is a primary key. The first primary key defined +on a model is the partition key (unless partition keys are set), all others are cluster keys

+
+ +
+
+partition_key = False
+

indicates that this column should be the partition key, defining +more than one partition key column creates a compound partition key

+
+ +
+
+index = False
+

bool flag, indicates an index should be created for this column

+
+ +
+
+custom_index = False
+

bool flag, indicates an index is managed outside of cqlengine. This is +useful if you want to do filter queries on fields that have custom +indexes.

+
+ +
+
+db_field = None
+

the fieldname this field will map to in the database

+
+ +
+
+default = None
+

the default value, can be a value or a callable (no args)

+
+ +
+
+required = False
+

boolean, is the field required? Model validation will raise and +exception if required is set to True and there is a None value assigned

+
+ +
+
+clustering_order = None
+

only applicable on clustering keys (primary keys that are not partition keys) +determines the order that the clustering keys are sorted on disk

+
+ +
+
+discriminator_column = False
+

boolean, if set to True, this column will be used for discriminating records +of inherited models.

+

Should only be set on a column of an abstract model being used for inheritance.

+

There may only be one discriminator column per model. See __discriminator_value__ +for how to specify the value of this column on specialized models.

+
+ +
+
+static = False
+

boolean, if set to True, this is a static column, with a single value per partition

+
+ +
+ +
+
+

Column Types

+

Columns of all types are initialized by passing Column attributes to the constructor by keyword.

+
+
+class cassandra.cqlengine.columns.Ascii(**kwargs)
+

Stores a US-ASCII character string

+
+
Parameters
+
    +
  • min_length (int) – Sets the minimum length of this string, for validation purposes. +Defaults to 1 if this is a required column. Otherwise, None.

  • +
  • max_length (int) – Sets the maximum length of this string, for validation purposes.

  • +
+
+
+
+ +
+
+class cassandra.cqlengine.columns.BigInt(**kwargs)
+

Stores a 64-bit signed integer value

+
+ +
+
+class cassandra.cqlengine.columns.Blob(**kwargs)
+

Stores a raw binary value

+
+ +
+
+cassandra.cqlengine.columns.Bytes
+

alias of cassandra.cqlengine.columns.Blob

+
+ +
+
+class cassandra.cqlengine.columns.Boolean(**kwargs)
+

Stores a boolean True or False value

+
+ +
+
+class cassandra.cqlengine.columns.Counter(index=False, db_field=None, required=False)
+

Stores a counter that can be incremented and decremented

+
+ +
+
+class cassandra.cqlengine.columns.Date(**kwargs)
+

Stores a simple date, with no time-of-day

+
+

Changed in version 2.6.0: removed overload of Date and DateTime. DateTime is a drop-in replacement for legacy models

+
+

requires C* 2.2+ and protocol v4+

+
+ +
+
+class cassandra.cqlengine.columns.DateTime(**kwargs)
+

Stores a datetime value

+
+
+truncate_microseconds = False
+

Set this True to have model instances truncate the date, quantizing it in the same way it will be in the database. +This allows equality comparison between assigned values and values read back from the database:

+
DateTime.truncate_microseconds = True
+assert Model.create(id=0, d=datetime.utcnow()) == Model.objects(id=0).first()
+
+
+

Defaults to False to preserve legacy behavior. May change in the future.

+
+ +
+ +
+
+class cassandra.cqlengine.columns.Decimal(**kwargs)
+

Stores a variable precision decimal value

+
+ +
+
+class cassandra.cqlengine.columns.Double(**kwargs)
+

Stores a double-precision floating-point value

+
+ +
+
+class cassandra.cqlengine.columns.Float(primary_key=False, partition_key=False, index=False, db_field=None, default=None, required=False, clustering_order=None, discriminator_column=False, static=False, custom_index=False)
+

Stores a single-precision floating-point value

+
+ +
+
+class cassandra.cqlengine.columns.Integer(**kwargs)
+

Stores a 32-bit signed integer value

+
+ +
+
+class cassandra.cqlengine.columns.List(value_type, default=<class 'list'>, **kwargs)
+

Stores a list of ordered values

+

http://www.datastax.com/documentation/cql/3.1/cql/cql_using/use_list_t.html

+
+
Parameters
+

value_type – a column class indicating the types of the value

+
+
+
+ +
+
+class cassandra.cqlengine.columns.Map(key_type, value_type, default=<class 'dict'>, **kwargs)
+

Stores a key -> value map (dictionary)

+

https://docs.datastax.com/en/dse/6.7/cql/cql/cql_using/useMap.html

+
+
Parameters
+
    +
  • key_type – a column class indicating the types of the key

  • +
  • value_type – a column class indicating the types of the value

  • +
+
+
+
+ +
+
+class cassandra.cqlengine.columns.Set(value_type, strict=True, default=<class 'set'>, **kwargs)
+

Stores a set of unordered, unique values

+

http://www.datastax.com/documentation/cql/3.1/cql/cql_using/use_set_t.html

+
+
Parameters
+
    +
  • value_type – a column class indicating the types of the value

  • +
  • strict – sets whether non set values will be coerced to set +type on validation, or raise a validation error, defaults to True

  • +
+
+
+
+ +
+
+class cassandra.cqlengine.columns.SmallInt(**kwargs)
+

Stores a 16-bit signed integer value

+
+

New in version 2.6.0.

+
+

requires C* 2.2+ and protocol v4+

+
+ +
+
+class cassandra.cqlengine.columns.Text(min_length=None, max_length=None, **kwargs)
+

Stores a UTF-8 encoded string

+
+
Parameters
+
    +
  • min_length (int) – Sets the minimum length of this string, for validation purposes. +Defaults to 1 if this is a required column. Otherwise, None.

  • +
  • max_length (int) – Sets the maximum length of this string, for validation purposes.

  • +
+
+
+
+ +
+
+class cassandra.cqlengine.columns.Time(**kwargs)
+

Stores a timezone-naive time-of-day, with nanosecond precision

+
+

New in version 2.6.0.

+
+

requires C* 2.2+ and protocol v4+

+
+ +
+
+class cassandra.cqlengine.columns.TimeUUID(**kwargs)
+

UUID containing timestamp

+
+ +
+
+class cassandra.cqlengine.columns.TinyInt(**kwargs)
+

Stores an 8-bit signed integer value

+
+

New in version 2.6.0.

+
+

requires C* 2.2+ and protocol v4+

+
+ +
+
+class cassandra.cqlengine.columns.UserDefinedType(user_type, **kwargs)
+

User Defined Type column

+

http://www.datastax.com/documentation/cql/3.1/cql/cql_using/cqlUseUDT.html

+

These columns are represented by a specialization of cassandra.cqlengine.usertype.UserType.

+

Please see User Defined Types for examples and discussion.

+
+
Parameters
+

user_type (type) – specifies the UserType model of the column

+
+
+
+ +
+
+class cassandra.cqlengine.columns.UUID(**kwargs)
+

Stores a type 1 or 4 UUID

+
+ +
+
+class cassandra.cqlengine.columns.VarInt(**kwargs)
+

Stores an arbitrary-precision integer

+
+ +
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.22.3-scylla/api/cassandra/cqlengine/connection.html b/3.22.3-scylla/api/cassandra/cqlengine/connection.html new file mode 100644 index 0000000000..40b7c40768 --- /dev/null +++ b/3.22.3-scylla/api/cassandra/cqlengine/connection.html @@ -0,0 +1,717 @@ + + + + + + + + + + + + + cassandra.cqlengine.connection - Connection management for cqlengine | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.cqlengine.connection - Connection management for cqlengine

+
+
+cassandra.cqlengine.connection.default()
+

Configures the default connection to localhost, using the driver defaults +(except for row_factory)

+
+ +
+
+cassandra.cqlengine.connection.set_session(s)
+

Configures the default connection with a preexisting cassandra.cluster.Session

+

Note: the mapper presently requires a Session cassandra.cluster.Session.row_factory set to dict_factory. +This may be relaxed in the future

+
+ +
+
+cassandra.cqlengine.connection.setup(hosts, default_keyspace, consistency=None, lazy_connect=False, retry_connect=False, **kwargs)
+

Setup a the driver connection used by the mapper

+
+
Parameters
+
    +
  • hosts (list) – list of hosts, (contact_points for cassandra.cluster.Cluster)

  • +
  • default_keyspace (str) – The default keyspace to use

  • +
  • consistency (int) – The global default ConsistencyLevel - default is the same as Session.default_consistency_level

  • +
  • lazy_connect (bool) – True if should not connect until first use

  • +
  • retry_connect (bool) – True if we should retry to connect even if there was a connection failure initially

  • +
  • **kwargs – Pass-through keyword arguments for cassandra.cluster.Cluster

  • +
+
+
+
+ +
+
+cassandra.cqlengine.connection.register_connection(name, hosts=None, consistency=None, lazy_connect=False, retry_connect=False, cluster_options=None, default=False, session=None)
+

Add a connection to the connection registry. hosts and session are +mutually exclusive, and consistency, lazy_connect, +retry_connect, and cluster_options only work with hosts. Using +hosts will create a new cassandra.cluster.Cluster and +cassandra.cluster.Session.

+
+
Parameters
+
    +
  • hosts (list) – list of hosts, (contact_points for cassandra.cluster.Cluster).

  • +
  • consistency (int) – The default ConsistencyLevel for the +registered connection’s new session. Default is the same as +Session.default_consistency_level. For use with hosts only; +will fail when used with session.

  • +
  • lazy_connect (bool) – True if should not connect until first use. For +use with hosts only; will fail when used with session.

  • +
  • retry_connect (bool) – True if we should retry to connect even if there +was a connection failure initially. For use with hosts only; will +fail when used with session.

  • +
  • cluster_options (dict) – A dict of options to be used as keyword +arguments to cassandra.cluster.Cluster. For use with hosts +only; will fail when used with session.

  • +
  • default (bool) – If True, set the new connection as the cqlengine +default

  • +
  • session (Session) – A cassandra.cluster.Session to be used in +the created connection.

  • +
+
+
+
+ +
+
+cassandra.cqlengine.connection.unregister_connection(name)
+
+ +
+
+cassandra.cqlengine.connection.set_default_connection(name)
+
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.22.3-scylla/api/cassandra/cqlengine/management.html b/3.22.3-scylla/api/cassandra/cqlengine/management.html new file mode 100644 index 0000000000..b4af83de60 --- /dev/null +++ b/3.22.3-scylla/api/cassandra/cqlengine/management.html @@ -0,0 +1,739 @@ + + + + + + + + + + + + + cassandra.cqlengine.management - Schema management for cqlengine | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.cqlengine.management - Schema management for cqlengine

+

A collection of functions for managing keyspace and table schema.

+
+
+cassandra.cqlengine.management.create_keyspace_simple(name, replication_factor, durable_writes=True, connections=None)
+

Creates a keyspace with SimpleStrategy for replica placement

+

If the keyspace already exists, it will not be modified.

+

This function should be used with caution, especially in production environments. +Take care to execute schema modifications in a single context (i.e. not concurrently with other clients).

+

There are plans to guard schema-modifying functions with an environment-driven conditional.

+
+
Parameters
+
    +
  • name (str) – name of keyspace to create

  • +
  • replication_factor (int) – keyspace replication factor, used with SimpleStrategy

  • +
  • durable_writes (bool) – Write log is bypassed if set to False

  • +
  • connections (list) – List of connection names

  • +
+
+
+
+ +
+
+cassandra.cqlengine.management.create_keyspace_network_topology(name, dc_replication_map, durable_writes=True, connections=None)
+

Creates a keyspace with NetworkTopologyStrategy for replica placement

+

If the keyspace already exists, it will not be modified.

+

This function should be used with caution, especially in production environments. +Take care to execute schema modifications in a single context (i.e. not concurrently with other clients).

+

There are plans to guard schema-modifying functions with an environment-driven conditional.

+
+
Parameters
+
    +
  • name (str) – name of keyspace to create

  • +
  • dc_replication_map (dict) – map of dc_names: replication_factor

  • +
  • durable_writes (bool) – Write log is bypassed if set to False

  • +
  • connections (list) – List of connection names

  • +
+
+
+
+ +
+
+cassandra.cqlengine.management.drop_keyspace(name, connections=None)
+

Drops a keyspace, if it exists.

+

There are plans to guard schema-modifying functions with an environment-driven conditional.

+

This function should be used with caution, especially in production environments. +Take care to execute schema modifications in a single context (i.e. not concurrently with other clients).

+
+
Parameters
+
    +
  • name (str) – name of keyspace to drop

  • +
  • connections (list) – List of connection names

  • +
+
+
+
+ +
+
+cassandra.cqlengine.management.sync_table(model, keyspaces=None, connections=None)
+

Inspects the model and creates / updates the corresponding table and columns.

+

If keyspaces is specified, the table will be synched for all specified keyspaces. +Note that the Model.__keyspace__ is ignored in that case.

+

If connections is specified, the table will be synched for all specified connections. Note that the Model.__connection__ is ignored in that case. +If not specified, it will try to get the connection from the Model.

+

Any User Defined Types used in the table are implicitly synchronized.

+

This function can only add fields that are not part of the primary key.

+

Note that the attributes removed from the model are not deleted on the database. +They become effectively ignored by (will not show up on) the model.

+

This function should be used with caution, especially in production environments. +Take care to execute schema modifications in a single context (i.e. not concurrently with other clients).

+

There are plans to guard schema-modifying functions with an environment-driven conditional.

+
+ +
+
+cassandra.cqlengine.management.sync_type(ks_name, type_model, connection=None)
+

Inspects the type_model and creates / updates the corresponding type.

+

Note that the attributes removed from the type_model are not deleted on the database (this operation is not supported). +They become effectively ignored by (will not show up on) the type_model.

+

This function should be used with caution, especially in production environments. +Take care to execute schema modifications in a single context (i.e. not concurrently with other clients).

+

There are plans to guard schema-modifying functions with an environment-driven conditional.

+
+ +
+
+cassandra.cqlengine.management.drop_table(model, keyspaces=None, connections=None)
+

Drops the table indicated by the model, if it exists.

+

If keyspaces is specified, the table will be dropped for all specified keyspaces. Note that the Model.__keyspace__ is ignored in that case.

+

If connections is specified, the table will be synched for all specified connections. Note that the Model.__connection__ is ignored in that case. +If not specified, it will try to get the connection from the Model.

+

This function should be used with caution, especially in production environments. +Take care to execute schema modifications in a single context (i.e. not concurrently with other clients).

+

There are plans to guard schema-modifying functions with an environment-driven conditional.

+
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.22.3-scylla/api/cassandra/cqlengine/models.html b/3.22.3-scylla/api/cassandra/cqlengine/models.html new file mode 100644 index 0000000000..52dcff108b --- /dev/null +++ b/3.22.3-scylla/api/cassandra/cqlengine/models.html @@ -0,0 +1,944 @@ + + + + + + + + + + + + + cassandra.cqlengine.models - Table models for object mapping | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.cqlengine.models - Table models for object mapping

+
+

Model

+
+
+class cassandra.cqlengine.models.Model(\*\*kwargs)
+

The initializer creates an instance of the model. Pass in keyword arguments for columns you’ve defined on the model.

+
class Person(Model):
+    id = columns.UUID(primary_key=True)
+    first_name  = columns.Text()
+    last_name = columns.Text()
+
+person = Person(first_name='Blake', last_name='Eggleston')
+person.first_name  #returns 'Blake'
+person.last_name  #returns 'Eggleston'
+
+
+

Model attributes define how the model maps to tables in the database. These are class variables that should be set +when defining Model deriviatives.

+
+
+__abstract__ = False
+

Optional. Indicates that this model is only intended to be used as a base class for other models. +You can’t create tables for abstract models, but checks around schema validity are skipped during class construction.

+
+ +
+
+__table_name__ = None
+

Optional. Sets the name of the CQL table for this model. If left blank, the table name will be the name of the model, with it’s module name as it’s prefix. Manually defined table names are not inherited.

+
+ +
+
+__table_name_case_sensitive__ = False
+

Optional. By default, __table_name__ is case insensitive. Set this to True if you want to preserve the case sensitivity.

+
+ +
+
+__keyspace__ = None
+

Sets the name of the keyspace used by this model.

+
+ +
+
+__connection__ = None
+

Sets the name of the default connection used by this model.

+
+ +
+
+__default_ttl__ = None
+

Will be deprecated in release 4.0. You can set the default ttl by configuring the table __options__. See Default TTL and Per Query TTL for more details.

+
+ +
+
+__discriminator_value__ = None
+

Optional Specifies a value for the discriminator column when using model inheritance.

+

See Model Inheritance for usage examples.

+
+ +

Each table can have its own set of configuration options, including compaction. Unspecified, these default to sensible values in +the server. To override defaults, set options using the model __options__ attribute, which allows options specified a dict.

+

When a table is synced, it will be altered to match the options set on your table. +This means that if you are changing settings manually they will be changed back on resync.

+

Do not use the options settings of cqlengine if you want to manage your compaction settings manually.

+

See the list of supported table properties for more information.

+
+
+__options__
+

For example:

+
class User(Model):
+    __options__ = {'compaction': {'class': 'LeveledCompactionStrategy',
+                                  'sstable_size_in_mb': '64',
+                                  'tombstone_threshold': '.2'},
+                   'comment': 'User data stored here'}
+
+    user_id = columns.UUID(primary_key=True)
+    name = columns.Text()
+
+
+

or :

+
class TimeData(Model):
+    __options__ = {'compaction': {'class': 'SizeTieredCompactionStrategy',
+                                  'bucket_low': '.3',
+                                  'bucket_high': '2',
+                                  'min_threshold': '2',
+                                  'max_threshold': '64',
+                                  'tombstone_compaction_interval': '86400'},
+                   'gc_grace_seconds': '0'}
+
+
+
+ +
+
+__compute_routing_key__ = True
+

Optional Setting False disables computing the routing key for TokenAwareRouting

+
+ +

The base methods allow creating, storing, and querying modeled objects.

+
+
+classmethod create(**kwargs)
+

Create an instance of this model in the database.

+

Takes the model column values as keyword arguments. Setting a value to +None is equivalent to running a CQL DELETE on that column.

+

Returns the instance.

+
+ +
+
+if_not_exists()
+

Check the existence of an object before insertion. The existence of an +object is determined by its primary key(s). And please note using this flag +would incur performance cost.

+

If the insertion isn’t applied, a LWTException is raised.

+
try:
+    TestIfNotExistsModel.if_not_exists().create(id=id, count=9, text='111111111111')
+except LWTException as e:
+    # handle failure case
+    print e.existing  # dict containing LWT result fields
+
+
+

This method is supported on Cassandra 2.0 or later.

+
+ +
+
+if_exists()
+

Check the existence of an object before an update or delete. The existence of an +object is determined by its primary key(s). And please note using this flag +would incur performance cost.

+

If the update or delete isn’t applied, a LWTException is raised.

+
try:
+    TestIfExistsModel.objects(id=id).if_exists().update(count=9, text='111111111111')
+except LWTException as e:
+    # handle failure case
+    pass
+
+
+

This method is supported on Cassandra 2.0 or later.

+
+ +
+
+save()
+

Saves an object to the database.

+
#create a person instance
+person = Person(first_name='Kimberly', last_name='Eggleston')
+#saves it to Cassandra
+person.save()
+
+
+
+ +
+
+update(**values)
+

Performs an update on the model instance. You can pass in values to set on the model +for updating, or you can call without values to execute an update against any modified +fields. If no fields on the model have been modified since loading, no query will be +performed. Model validation is performed normally. Setting a value to None is +equivalent to running a CQL DELETE on that column.

+

It is possible to do a blind update, that is, to update a field without having first selected the object out of the database. +See Blind Updates

+
+ +
+
+iff(**values)
+

Checks to ensure that the values specified are correct on the Cassandra cluster. +Simply specify the column(s) and the expected value(s). As with if_not_exists, +this incurs a performance cost.

+

If the insertion isn’t applied, a LWTException is raised.

+
t = TestTransactionModel(text='some text', count=5)
+try:
+     t.iff(count=5).update('other text')
+except LWTException as e:
+    # handle failure case
+    print e.existing # existing object
+
+
+
+ +
+
+classmethod get(*args, **kwargs)
+

Returns a single object based on the passed filter constraints.

+

This is a pass-through to the model objects().:method:~cqlengine.queries.get.

+
+ +
+
+classmethod filter(*args, **kwargs)
+

Returns a queryset based on filter parameters.

+

This is a pass-through to the model objects().:method:~cqlengine.queries.filter.

+
+ +
+
+classmethod all()
+

Returns a queryset representing all stored objects

+

This is a pass-through to the model objects().all()

+
+ +
+
+delete()
+

Deletes the object from the database

+
+ +
+
+batch(batch_object)
+

Sets the batch object to run instance updates and inserts queries with.

+

See Batch Queries for usage examples

+
+ +
+
+timeout(timeout)
+

Sets a timeout for use in save(), update(), and delete() +operations

+
+ +
+
+timestamp(timedelta_or_datetime)
+

Sets the timestamp for the query

+
+ +
+
+ttl(ttl_in_sec)
+

Sets the ttl values to run instance updates and inserts queries with.

+
+ +
+
+using(connection=None)
+

Change the context on the fly of the model instance (keyspace, connection)

+
+ +
+
+classmethod column_family_name(include_keyspace=True)
+

Returns the column family name if it’s been defined +otherwise, it creates it from the module and class name

+
+ +

Models also support dict-like access:

+
+
+len(m)
+

Returns the number of columns defined in the model

+
+ +
+
+m[col_name]
+

Returns the value of column col_name

+
+ +
+
+m[col_name] = value
+

Set m[col_name] to value

+
+ +
+
+keys()
+

Returns a list of column IDs.

+
+ +
+
+values()
+

Returns list of column values.

+
+ +
+
+items()
+

Returns a list of column ID/value tuples.

+
+ +
+ +
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.22.3-scylla/api/cassandra/cqlengine/query.html b/3.22.3-scylla/api/cassandra/cqlengine/query.html new file mode 100644 index 0000000000..e0545bf220 --- /dev/null +++ b/3.22.3-scylla/api/cassandra/cqlengine/query.html @@ -0,0 +1,1040 @@ + + + + + + + + + + + + + cassandra.cqlengine.query - Query and filter model objects | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.cqlengine.query - Query and filter model objects

+
+

QuerySet

+

QuerySet objects are typically obtained by calling objects() on a model class. +The methods here are used to filter, order, and constrain results.

+
+
+class cassandra.cqlengine.query.ModelQuerySet(model)
+
+
+all()
+

Returns a queryset matching all rows

+
for user in User.objects().all():
+    print(user)
+
+
+
+ +
+
+batch(batch_obj)
+

Set a batch object to run the query on.

+

Note: running a select query with a batch object will raise an exception

+
+ +
+
+consistency(consistency)
+

Sets the consistency level for the operation. See ConsistencyLevel.

+
for user in User.objects(id=3).consistency(CL.ONE):
+    print(user)
+
+
+
+ +
+
+count()
+

Returns the number of rows matched by this query.

+

Note: This function executes a SELECT COUNT() and has a performance cost on large datasets

+
+ +
+
+len(queryset)
+

Returns the number of rows matched by this query. This function uses count() internally.

+

Note: This function executes a SELECT COUNT() and has a performance cost on large datasets

+
+ +
+
+distinct(distinct_fields=None)
+

Returns the DISTINCT rows matched by this query.

+

distinct_fields default to the partition key fields if not specified.

+

Note: distinct_fields must be a partition key or a static column

+
class Automobile(Model):
+    manufacturer = columns.Text(partition_key=True)
+    year = columns.Integer(primary_key=True)
+    model = columns.Text(primary_key=True)
+    price = columns.Decimal()
+
+sync_table(Automobile)
+
+# create rows
+
+Automobile.objects.distinct()
+
+# or
+
+Automobile.objects.distinct(['manufacturer'])
+
+
+
+ +
+
+filter(*args, **kwargs)
+

Adds WHERE arguments to the queryset, returning a new queryset

+

See Retrieving objects with filters

+

Returns a QuerySet filtered on the keyword arguments

+
+ +
+
+get(*args, **kwargs)
+

Returns a single instance matching this query, optionally with additional filter kwargs.

+

See Retrieving objects with filters

+

Returns a single object matching the QuerySet.

+
user = User.get(id=1)
+
+
+

If no objects are matched, a DoesNotExist exception is raised.

+

If more than one object is found, a MultipleObjectsReturned exception is raised.

+
+ +
+
+limit(v)
+

Limits the number of results returned by Cassandra. Use 0 or None to disable.

+

Note that CQL’s default limit is 10,000, so all queries without a limit set explicitly will have an implicit limit of 10,000

+
# Fetch 100 users
+for user in User.objects().limit(100):
+    print(user)
+
+# Fetch all users
+for user in User.objects().limit(None):
+    print(user)
+
+
+
+ +
+
+fetch_size(v)
+

Sets the number of rows that are fetched at a time.

+

Note that driver’s default fetch size is 5000.

+
for user in User.objects().fetch_size(500):
+    print(user)
+
+
+
+ +
+
+if_not_exists()
+

Check the existence of an object before insertion.

+

If the insertion isn’t applied, a LWTException is raised.

+
+ +
+
+if_exists()
+

Check the existence of an object before an update or delete.

+

If the update or delete isn’t applied, a LWTException is raised.

+
+ +
+
+order_by(*colnames)
+

Sets the column(s) to be used for ordering

+

Default order is ascending, prepend a ‘-’ to any column name for descending

+

Note: column names must be a clustering key

+
from uuid import uuid1,uuid4
+
+class Comment(Model):
+    photo_id = UUID(primary_key=True)
+    comment_id = TimeUUID(primary_key=True, default=uuid1) # second primary key component is a clustering key
+    comment = Text()
+
+sync_table(Comment)
+
+u = uuid4()
+for x in range(5):
+    Comment.create(photo_id=u, comment="test %d" % x)
+
+print("Normal")
+for comment in Comment.objects(photo_id=u):
+    print comment.comment_id
+
+print("Reversed")
+for comment in Comment.objects(photo_id=u).order_by("-comment_id"):
+    print comment.comment_id
+
+
+
+ +
+
+allow_filtering()
+

Enables the (usually) unwise practive of querying on a clustering key without also defining a partition key

+
+ +
+
+only(fields)
+

Load only these fields for the returned query

+
+ +
+
+defer(fields)
+

Don’t load these fields for the returned query

+
+ +
+
+timestamp(timestamp)
+

Allows for custom timestamps to be saved with the record.

+
+ +
+
+ttl(ttl)
+

Sets the ttl (in seconds) for modified data.

+

Note that running a select query with a ttl value will raise an exception

+
+ +
+
+using(keyspace=None, connection=None)
+

Change the context on-the-fly of the Model class (keyspace, connection)

+
+ +
+
+update(**values)
+

Performs an update on the row selected by the queryset. Include values to update in the +update like so:

+
Model.objects(key=n).update(value='x')
+
+
+

Passing in updates for columns which are not part of the model will raise a ValidationError.

+

Per column validation will be performed, but instance level validation will not +(i.e., Model.validate is not called). This is sometimes referred to as a blind update.

+

For example:

+
class User(Model):
+    id = Integer(primary_key=True)
+    name = Text()
+
+setup(["localhost"], "test")
+sync_table(User)
+
+u = User.create(id=1, name="jon")
+
+User.objects(id=1).update(name="Steve")
+
+# sets name to null
+User.objects(id=1).update(name=None)
+
+
+

Also supported is blindly adding and removing elements from container columns, +without loading a model instance from Cassandra.

+

Using the syntax .update(column_name={x, y, z}) will overwrite the contents of the container, like updating a +non container column. However, adding __<operation> to the end of the keyword arg, makes the update call add +or remove items from the collection, without overwriting then entire column.

+

Given the model below, here are the operations that can be performed on the different container columns:

+
class Row(Model):
+    row_id      = columns.Integer(primary_key=True)
+    set_column  = columns.Set(Integer)
+    list_column = columns.List(Integer)
+    map_column  = columns.Map(Integer, Integer)
+
+
+

Set

+
    +
  • add: adds the elements of the given set to the column

  • +
  • remove: removes the elements of the given set to the column

  • +
+
# add elements to a set
+Row.objects(row_id=5).update(set_column__add={6})
+
+# remove elements to a set
+Row.objects(row_id=5).update(set_column__remove={4})
+
+
+

List

+
    +
  • append: appends the elements of the given list to the end of the column

  • +
  • prepend: prepends the elements of the given list to the beginning of the column

  • +
+
# append items to a list
+Row.objects(row_id=5).update(list_column__append=[6, 7])
+
+# prepend items to a list
+Row.objects(row_id=5).update(list_column__prepend=[1, 2])
+
+
+

Map

+
    +
  • update: adds the given keys/values to the columns, creating new entries if they didn’t exist, and overwriting old ones if they did

  • +
+
# add items to a map
+Row.objects(row_id=5).update(map_column__update={1: 2, 3: 4})
+
+# remove items from a map
+Row.objects(row_id=5).update(map_column__remove={1, 2})
+
+
+
+ +
+ +
+
+class cassandra.cqlengine.query.BatchQuery(batch_type=None, timestamp=None, consistency=None, execute_on_exception=False, timeout=<object object>, connection=None)
+

Handles the batching of queries

+

http://docs.datastax.com/en/cql/3.0/cql/cql_reference/batch_r.html

+

See Batch Queries for more details.

+
+
Parameters
+
    +
  • batch_type (BatchType, str or None) – (optional) One of batch type values available through BatchType enum

  • +
  • timestamp (datetime or timedelta or None) – (optional) A datetime or timedelta object with desired timestamp to be applied +to the batch conditional.

  • +
  • consistency (The ConsistencyLevel to be used for the batch query, or None.) – (optional) One of consistency values (“ANY”, “ONE”, “QUORUM” etc)

  • +
  • execute_on_exception (bool) – (Defaults to False) Indicates that when the BatchQuery instance is used +as a context manager the queries accumulated within the context must be executed despite +encountering an error within the context. By default, any exception raised from within +the context scope will cause the batched queries not to be executed.

  • +
  • timeout (float or None) – (optional) Timeout for the entire batch (in seconds), if not specified fallback +to default session timeout

  • +
  • connection (str) – Connection name to use for the batch execution

  • +
+
+
+
+
+add_query(query)
+
+ +
+
+execute()
+
+ +
+
+add_callback(fn, *args, **kwargs)
+

Add a function and arguments to be passed to it to be executed after the batch executes.

+

A batch can support multiple callbacks.

+

Note, that if the batch does not execute, the callbacks are not executed. +A callback, thus, is an “on batch success” handler.

+
+
Parameters
+
    +
  • fn (callable) – Callable object

  • +
  • *args – Positional arguments to be passed to the callback at the time of execution

  • +
  • **kwargs – Named arguments to be passed to the callback at the time of execution

  • +
+
+
+
+ +
+ +
+
+class cassandra.cqlengine.query.ContextQuery(*args, **kwargs)
+

A Context manager to allow a Model to switch context easily. Presently, the context only +specifies a keyspace for model IO.

+
+
Parameters
+
    +
  • *args – One or more models. A model should be a class type, not an instance.

  • +
  • **kwargs – (optional) Context parameters: can be keyspace or connection

  • +
+
+
+

For example:

+
with ContextQuery(Automobile, keyspace='test2') as A:
+    A.objects.create(manufacturer='honda', year=2008, model='civic')
+    print len(A.objects.all())  # 1 result
+
+with ContextQuery(Automobile, keyspace='test4') as A:
+    print len(A.objects.all())  # 0 result
+
+# Multiple models
+with ContextQuery(Automobile, Automobile2, connection='cluster2') as (A, A2):
+    print len(A.objects.all())
+    print len(A2.objects.all())
+
+
+
+ +
+
+class cassandra.cqlengine.query.DoesNotExist
+
+ +
+
+class cassandra.cqlengine.query.MultipleObjectsReturned
+
+ +
+
+class cassandra.cqlengine.query.LWTException(existing)
+

Lightweight conditional exception.

+

This exception will be raised when a write using an IF clause could not be +applied due to existing data violating the condition. The existing data is +available through the existing attribute.

+
+
Parameters
+

existing – The current state of the data which prevented the write.

+
+
+
+ +
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.22.3-scylla/api/cassandra/cqlengine/usertype.html b/3.22.3-scylla/api/cassandra/cqlengine/usertype.html new file mode 100644 index 0000000000..2aafbcc0e3 --- /dev/null +++ b/3.22.3-scylla/api/cassandra/cqlengine/usertype.html @@ -0,0 +1,683 @@ + + + + + + + + + + + + + cassandra.cqlengine.usertype - Model classes for User Defined Types | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.cqlengine.usertype - Model classes for User Defined Types

+
+

UserType

+
+
+class cassandra.cqlengine.usertype.UserType(**values)
+

This class is used to model User Defined Types. To define a type, declare a class inheriting from this, +and assign field types as class attributes:

+
# connect with default keyspace ...
+
+from cassandra.cqlengine.columns import Text, Integer
+from cassandra.cqlengine.usertype import UserType
+
+class address(UserType):
+    street = Text()
+    zipcode = Integer()
+
+from cassandra.cqlengine import management
+management.sync_type(address)
+
+
+

Please see User Defined Types for a complete example and discussion.

+
+
+__type_name__ = None
+

Optional. Sets the name of the CQL type for this type.

+

If not specified, the type name will be the name of the class, with it’s module name as it’s prefix.

+
+ +
+ +
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.22.3-scylla/api/cassandra/datastax/graph/fluent/index.html b/3.22.3-scylla/api/cassandra/datastax/graph/fluent/index.html new file mode 100644 index 0000000000..7a14a19584 --- /dev/null +++ b/3.22.3-scylla/api/cassandra/datastax/graph/fluent/index.html @@ -0,0 +1,757 @@ + + + + + + + + + + + + + cassandra.datastax.graph.fluent | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.datastax.graph.fluent

+
+
+class cassandra.datastax.graph.fluent.DseGraph
+

Dse Graph utility class for GraphTraversal construction and execution.

+
+
+DSE_GRAPH_QUERY_LANGUAGE = 'bytecode-json'
+

Graph query language, Default is ‘bytecode-json’ (GraphSON).

+
+ +
+
+static create_execution_profile(graph_name, graph_protocol=b'graphson-2.0', **kwargs)
+

Creates an ExecutionProfile for GraphTraversal execution. You need to register that execution profile to the +cluster by using cluster.add_execution_profile.

+
+
Parameters
+
    +
  • graph_name – The graph name

  • +
  • graph_protocol – (Optional) The graph protocol, default is DSE_GRAPH_QUERY_PROTOCOL.

  • +
+
+
+
+ +
+
+static query_from_traversal(traversal, graph_protocol=b'graphson-2.0', context=None)
+

From a GraphTraversal, return a query string based on the language specified in DseGraph.DSE_GRAPH_QUERY_LANGUAGE.

+
+
Parameters
+
    +
  • traversal – The GraphTraversal object

  • +
  • graph_protocol – The graph protocol. Default is DseGraph.DSE_GRAPH_QUERY_PROTOCOL.

  • +
  • context – The dict of the serialization context, needed for GraphSON3 (tuple, udt). +e.g: {‘cluster’: cluster, ‘graph_name’: name}

  • +
+
+
+
+ +
+
+static traversal_source(session=None, graph_name=None, execution_profile=EXEC_PROFILE_GRAPH_DEFAULT, traversal_class=None)
+

Returns a TinkerPop GraphTraversalSource binded to the session and graph_name if provided.

+
+
Parameters
+
    +
  • session – (Optional) A DSE session

  • +
  • graph_name – (Optional) DSE Graph name

  • +
  • execution_profile – (Optional) Execution profile for traversal queries. Default is set to EXEC_PROFILE_GRAPH_DEFAULT.

  • +
  • traversal_class – (Optional) The GraphTraversalSource class to use (DSL).

  • +
+
+
+
from cassandra.cluster import Cluster
+from cassandra.datastax.graph.fluent import DseGraph
+
+c = Cluster()
+session = c.connect()
+
+g = DseGraph.traversal_source(session, 'my_graph')
+print g.V().valueMap().toList()
+
+
+
+ +
+
+static batch(session=None, execution_profile=None)
+

Returns the cassandra.datastax.graph.fluent.query.TraversalBatch object allowing to +execute multiple traversals in the same transaction.

+
+ +
+ +
+
+class cassandra.datastax.graph.fluent.DSESessionRemoteGraphConnection(session[, graph_name, execution_profile])
+

A Tinkerpop RemoteConnection to execute traversal queries on DSE.

+
+
Parameters
+
    +
  • session – A DSE session

  • +
  • graph_name – (Optional) DSE Graph name.

  • +
  • execution_profile – (Optional) Execution profile for traversal queries. Default is set to EXEC_PROFILE_GRAPH_DEFAULT.

  • +
+
+
+
+ +
+
+class cassandra.datastax.graph.fluent.BaseGraphRowFactory(cluster)
+

Base row factory for graph traversal. This class basically wraps a +graphson reader function to handle additional features of Gremlin/DSE +and is callable as a normal row factory.

+
+
Currently supported:
    +
  • bulk results

  • +
+
+
+
+ +
+
+cassandra.datastax.graph.fluent.graph_traversal_row_factory
+

alias of cassandra.datastax.graph.fluent._GremlinGraphSON2RowFactory

+
+ +
+
+cassandra.datastax.graph.fluent.graph_traversal_dse_object_row_factory
+

alias of cassandra.datastax.graph.fluent._DseGraphSON2RowFactory

+
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.22.3-scylla/api/cassandra/datastax/graph/fluent/predicates.html b/3.22.3-scylla/api/cassandra/datastax/graph/fluent/predicates.html new file mode 100644 index 0000000000..8ec535f857 --- /dev/null +++ b/3.22.3-scylla/api/cassandra/datastax/graph/fluent/predicates.html @@ -0,0 +1,753 @@ + + + + + + + + + + + + + cassandra.datastax.graph.fluent.predicates | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.datastax.graph.fluent.predicates

+
+
+class cassandra.datastax.graph.fluent.predicates.Search
+
+
+static token(value)
+

Search any instance of a certain token within the text property targeted. +:param value: the value to look for.

+
+ +
+
+static token_prefix(value)
+

Search any instance of a certain token prefix withing the text property targeted. +:param value: the value to look for.

+
+ +
+
+static token_regex(value)
+

Search any instance of the provided regular expression for the targeted property. +:param value: the value to look for.

+
+ +
+
+static prefix(value)
+

Search for a specific prefix at the beginning of the text property targeted. +:param value: the value to look for.

+
+ +
+
+static regex(value)
+

Search for this regular expression inside the text property targeted. +:param value: the value to look for.

+
+ +
+
+static fuzzy(value, distance)
+

Search for a fuzzy string inside the text property targeted. +:param value: the value to look for. +:param distance: The distance for the fuzzy search. ie. 1, to allow a one-letter misspellings.

+
+ +
+
+static token_fuzzy(value, distance)
+

Search for a token fuzzy inside the text property targeted. +:param value: the value to look for. +:param distance: The distance for the token fuzzy search. ie. 1, to allow a one-letter misspellings.

+
+ +
+
+static phrase(value, proximity)
+

Search for a phrase inside the text property targeted. +:param value: the value to look for. +:param proximity: The proximity for the phrase search. ie. phrase(‘David Felcey’, 2).. to find ‘David Felcey’ with up to two middle names.

+
+ +
+ +
+
+class cassandra.datastax.graph.fluent.predicates.CqlCollection
+
+
+static contains(value)
+

Search for a value inside a cql list/set column. +:param value: the value to look for.

+
+ +
+
+static contains_value(value)
+

Search for a map value. +:param value: the value to look for.

+
+ +
+
+static contains_key(value)
+

Search for a map key. +:param value: the value to look for.

+
+ +
+
+static entry_eq(value)
+

Search for a map entry. +:param value: the value to look for.

+
+ +
+ +
+
+class cassandra.datastax.graph.fluent.predicates.Geo
+
+
+static inside(value, units=1)
+

Search any instance of geometry inside the Distance targeted. +:param value: A Distance to look for. +:param units: The units for value. See GeoUnit enum. (Can also +provide an integer to use as a multiplier to convert value to +degrees.)

+
+ +
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.22.3-scylla/api/cassandra/datastax/graph/fluent/query.html b/3.22.3-scylla/api/cassandra/datastax/graph/fluent/query.html new file mode 100644 index 0000000000..925437779f --- /dev/null +++ b/3.22.3-scylla/api/cassandra/datastax/graph/fluent/query.html @@ -0,0 +1,704 @@ + + + + + + + + + + + + + cassandra.datastax.graph.fluent.query | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.datastax.graph.fluent.query

+
+
+class cassandra.datastax.graph.fluent.query.TraversalBatch(session=None, execution_profile=None)
+

A TraversalBatch is used to execute multiple graph traversals in a +single transaction. If any traversal in the batch fails, the entire +batch will fail to apply.

+

If a TraversalBatch is bounded to a DSE session, it can be executed using +traversal_batch.execute().

+
+
Parameters
+
    +
  • session – (Optional) A DSE session

  • +
  • execution_profile – (Optional) The execution profile to use for the batch execution

  • +
+
+
+
+
+add(traversal)
+

Add a traversal to the batch.

+
+
Parameters
+

traversal – A gremlin GraphTraversal

+
+
+
+ +
+
+add_all(traversals)
+

Adds a sequence of traversals to the batch.

+
+
Parameters
+

traversals – A sequence of gremlin GraphTraversal

+
+
+
+ +
+
+execute()
+

Execute the traversal batch if bounded to a DSE Session.

+
+ +
+
+as_graph_statement(graph_protocol=b'graphson-2.0')
+

Return the traversal batch as GraphStatement.

+
+
Parameters
+

graph_protocol – The graph protocol for the GraphSONWriter. Default is GraphProtocol.GRAPHSON_2_0.

+
+
+
+ +
+
+clear()
+

Clear a traversal batch for reuse.

+
+ +
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.22.3-scylla/api/cassandra/datastax/graph/index.html b/3.22.3-scylla/api/cassandra/datastax/graph/index.html new file mode 100644 index 0000000000..69ff70b2e1 --- /dev/null +++ b/3.22.3-scylla/api/cassandra/datastax/graph/index.html @@ -0,0 +1,1009 @@ + + + + + + + + + + + + + cassandra.datastax.graph - Graph Statements, Options, and Row Factories | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.datastax.graph - Graph Statements, Options, and Row Factories

+
+
+cassandra.datastax.graph.single_object_row_factory(column_names, rows)
+

returns the JSON string value of graph results

+
+ +
+
+cassandra.datastax.graph.graph_result_row_factory(column_names, rows)
+

Returns a Result object that can load graph results and produce specific types. +The Result JSON is deserialized and unpacked from the top-level ‘result’ dict.

+
+ +
+
+cassandra.datastax.graph.graph_object_row_factory(column_names, rows)
+

Like graph_result_row_factory(), except known element types (Vertex, Edge) are +converted to their simplified objects. Some low-level metadata is shed in this conversion. Unknown result types are +still returned as Result.

+
+ +
+
+cassandra.datastax.graph.graph_graphson2_row_factory(cluster)
+

Row factory to deserialize GraphSON2 results.

+
+ +
+
+cassandra.datastax.graph.graph_graphson3_row_factory(cluster)
+

Row factory to deserialize GraphSON3 results.

+
+ +
+
+cassandra.datastax.graph.to_int(value)
+

Wraps a value to be explicitly serialized as a graphson Int.

+
+ +
+
+cassandra.datastax.graph.to_bigint(value)
+

Wraps a value to be explicitly serialized as a graphson Bigint.

+
+ +
+
+cassandra.datastax.graph.to_smallint(value)
+

Wraps a value to be explicitly serialized as a graphson Smallint.

+
+ +
+
+cassandra.datastax.graph.to_float(value)
+

Wraps a value to be explicitly serialized as a graphson Float.

+
+ +
+
+cassandra.datastax.graph.to_double(value)
+

Wraps a value to be explicitly serialized as a graphson Double.

+
+ +
+
+class cassandra.datastax.graph.GraphProtocol
+
+
+GRAPHSON_1_0 = b'graphson-1.0'
+

GraphSON1

+
+ +
+
+GRAPHSON_2_0 = b'graphson-2.0'
+

GraphSON2

+
+ +
+
+GRAPHSON_3_0 = b'graphson-3.0'
+

GraphSON3

+
+ +
+ +
+
+class cassandra.datastax.graph.GraphOptions(**kwargs)
+

Options for DSE Graph Query handler.

+
+
+graph_name
+

name of the targeted graph.

+
+ +
+
+graph_source
+

choose the graph traversal source, configured on the server side.

+
+ +
+
+graph_language
+

the language used in the queries (default “gremlin-groovy”)

+
+ +
+
+graph_read_consistency_level
+

read cassandra.ConsistencyLevel for graph queries (if distinct from session default). +Setting this overrides the native Statement.consistency_level for read operations from Cassandra persistence

+
+ +
+
+graph_write_consistency_level
+

write cassandra.ConsistencyLevel for graph queries (if distinct from session default). +Setting this overrides the native Statement.consistency_level for write operations to Cassandra persistence.

+
+ +
+
+is_default_source
+
+ +
+
+is_analytics_source
+

True if graph_source is set to the server-defined analytics traversal source (‘a’)

+
+ +
+
+is_graph_source
+

True if graph_source is set to the server-defined graph traversal source (‘g’)

+
+ +
+
+set_source_default()
+

Sets graph_source to the server-defined default traversal source (‘default’)

+
+ +
+
+set_source_analytics()
+

Sets graph_source to the server-defined analytic traversal source (‘a’)

+
+ +
+
+set_source_graph()
+

Sets graph_source to the server-defined graph traversal source (‘g’)

+
+ +
+ +
+
+class cassandra.datastax.graph.SimpleGraphStatement(query_string, retry_policy=None, consistency_level=None, routing_key=None, serial_consistency_level=None, fetch_size=<object object>, keyspace=None, custom_payload=None, is_idempotent=False)
+

Simple graph statement for Session.execute_graph(). +Takes the same parameters as SimpleStatement.

+

query_string should be a literal CQL statement with the exception +of parameter placeholders that will be filled through the +parameters argument of Session.execute().

+

See Statement attributes for a description of the other parameters.

+
+ +
+
+class cassandra.datastax.graph.Result(value)
+

Represents deserialized graph results. +Property and item getters are provided for convenience.

+
+
+value = None
+

Deserialized value from the result

+
+ +
+
+as_vertex()
+

Return a Vertex parsed from this result

+

Raises TypeError if parsing fails (i.e. the result structure is not valid).

+
+ +
+
+as_edge()
+

Return a Edge parsed from this result

+

Raises TypeError if parsing fails (i.e. the result structure is not valid).

+
+ +
+
+as_path()
+

Return a Path parsed from this result

+

Raises TypeError if parsing fails (i.e. the result structure is not valid).

+
+ +
+ +
+
+class cassandra.datastax.graph.Vertex(id, label, type, properties)
+

Represents a Vertex element from a graph query.

+

Vertex properties are extracted into a dict of property names to list of VertexProperty (list +because they are always encoded that way, and sometimes have multiple cardinality; VertexProperty because sometimes +the properties themselves have property maps).

+
+ +
+
+class cassandra.datastax.graph.VertexProperty(label, value, properties=None)
+

Vertex properties have a top-level value and an optional dict of properties.

+
+
+label = None
+

label of the property

+
+ +
+
+value = None
+

Value of the property

+
+ +
+
+properties = None
+

dict of properties attached to the property

+
+ +
+ +
+
+class cassandra.datastax.graph.Edge(id, label, type, properties, inV, inVLabel, outV, outVLabel)
+

Represents an Edge element from a graph query.

+

Attributes match initializer parameters.

+
+ +
+
+class cassandra.datastax.graph.Path(labels, objects)
+

Represents a graph path.

+

Labels list is taken verbatim from the results.

+

Objects are either Result or Vertex/Edge for recognized types

+
+
+labels = None
+

List of labels in the path

+
+ +
+
+objects = None
+

List of objects in the path

+
+ +
+ +
+
+class cassandra.datastax.graph.GraphSON1Serializer
+

Serialize python objects to graphson types.

+
+ +
+
+class cassandra.datastax.graph.GraphSON1Deserializer
+

Deserialize graphson1 types to python objects.

+
+
+classmethod deserialize_date(value)
+
+ +
+
+classmethod deserialize_timestamp(value)
+
+ +
+
+classmethod deserialize_time(value)
+
+ +
+
+classmethod deserialize_duration(value)
+
+ +
+
+classmethod deserialize_int(value)
+
+ +
+
+classmethod deserialize_bigint(value)
+
+ +
+
+classmethod deserialize_double(value)
+
+ +
+
+classmethod deserialize_float(value)
+
+ +
+
+classmethod deserialize_uuid(value)
+
+ +
+
+classmethod deserialize_blob(value)
+
+ +
+
+classmethod deserialize_decimal(value)
+
+ +
+
+classmethod deserialize_point(value)
+
+ +
+
+classmethod deserialize_linestring(value)
+
+ +
+
+classmethod deserialize_polygon(value)
+
+ +
+ +
+
+class cassandra.datastax.graph.GraphSON2Reader(context, extra_deserializer_map=None)
+

GraphSON2 Reader that parse json and deserialize to python objects.

+
+
Parameters
+

extra_deserializer_map – map from GraphSON type tag to deserializer instance implementing deserialize

+
+
+
+
+read(json_data)
+

Read and deserialize json_data.

+
+ +
+
+deserialize(obj)
+

Deserialize GraphSON type-tagged dict values into objects mapped in self.deserializers

+
+ +
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.22.3-scylla/api/cassandra/decoder.html b/3.22.3-scylla/api/cassandra/decoder.html new file mode 100644 index 0000000000..bf1593fbe5 --- /dev/null +++ b/3.22.3-scylla/api/cassandra/decoder.html @@ -0,0 +1,665 @@ + + + + + + + + + + + + + cassandra.decoder - Data Return Formats | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.decoder - Data Return Formats

+
+
+cassandra.decoder.tuple_factory()
+

Deprecated in 2.0.0. Use cassandra.query.tuple_factory()

+
+ +
+
+cassandra.decoder.named_tuple_factory()
+

Deprecated in 2.0.0. Use cassandra.query.named_tuple_factory()

+
+ +
+
+cassandra.decoder.dict_factory()
+

Deprecated in 2.0.0. Use cassandra.query.dict_factory()

+
+ +
+
+cassandra.decoder.ordered_dict_factory()
+

Deprecated in 2.0.0. Use cassandra.query.ordered_dict_factory()

+
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.22.3-scylla/api/cassandra/encoder.html b/3.22.3-scylla/api/cassandra/encoder.html new file mode 100644 index 0000000000..15a8f9c7c6 --- /dev/null +++ b/3.22.3-scylla/api/cassandra/encoder.html @@ -0,0 +1,742 @@ + + + + + + + + + + + + + cassandra.encoder - Encoders for non-prepared Statements | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.encoder - Encoders for non-prepared Statements

+
+
+class cassandra.encoder.Encoder
+

A container for mapping python types to CQL string literals when working +with non-prepared statements. The type mapping can be +directly customized by users.

+
+
+mapping = None
+

A map of python types to encoder functions.

+
+ +
+
+cql_encode_none()
+

Converts None to the string ‘NULL’.

+
+ +
+
+cql_encode_object()
+

Default encoder for all objects that do not have a specific encoder function +registered. This function simply calls str() on the object.

+
+ +
+
+cql_encode_all_types()
+

Converts any type into a CQL string, defaulting to cql_encode_object +if mapping does not contain an entry for the type.

+
+ +
+
+cql_encode_sequence()
+

Converts a sequence to a string of the form (item1, item2, ...). This +is suitable for IN value lists.

+
+ +
+
+cql_encode_str()
+

Escapes quotes in str objects.

+
+ +
+
+cql_encode_unicode()
+

Converts unicode objects to UTF-8 encoded strings with quote escaping.

+
+ +
+
+cql_encode_bytes()
+

Converts strings, buffers, and bytearrays into CQL blob literals.

+
+ +
+
+cql_encode_datetime()
+

Converts a datetime.datetime object to a (string) integer timestamp +with millisecond precision.

+
+ +
+
+cql_encode_date()
+

Converts a datetime.date object to a string with format +YYYY-MM-DD.

+
+ +
+
+cql_encode_map_collection()
+

Converts a dict into a string of the form {key1: val1, key2: val2, ...}. +This is suitable for map type columns.

+
+ +
+
+cql_encode_list_collection()
+

Converts a sequence to a string of the form [item1, item2, ...]. This +is suitable for list type columns.

+
+ +
+
+cql_encode_set_collection()
+

Converts a sequence to a string of the form {item1, item2, ...}. This +is suitable for set type columns.

+
+ +
+
+cql_encode_tuple()
+

Converts a sequence to a string of the form (item1, item2, ...). This +is suitable for tuple type columns.

+
+ +
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.22.3-scylla/api/cassandra/graph.html b/3.22.3-scylla/api/cassandra/graph.html new file mode 100644 index 0000000000..262c813643 --- /dev/null +++ b/3.22.3-scylla/api/cassandra/graph.html @@ -0,0 +1,1028 @@ + + + + + + + + + + + + + cassandra.graph - Graph Statements, Options, and Row Factories | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.graph - Graph Statements, Options, and Row Factories

+
+

Note

+

This module is only for backward compatibility for dse-driver users. Consider using cassandra.datastax.graph.

+
+
+
+cassandra.graph.single_object_row_factory(column_names, rows)
+

returns the JSON string value of graph results

+
+ +
+
+cassandra.graph.graph_result_row_factory(column_names, rows)
+

Returns a Result object that can load graph results and produce specific types. +The Result JSON is deserialized and unpacked from the top-level ‘result’ dict.

+
+ +
+
+cassandra.graph.graph_object_row_factory(column_names, rows)
+

Like graph_result_row_factory(), except known element types (Vertex, Edge) are +converted to their simplified objects. Some low-level metadata is shed in this conversion. Unknown result types are +still returned as Result.

+
+ +
+
+cassandra.graph.graph_graphson2_row_factory(cluster)
+

Row factory to deserialize GraphSON2 results.

+
+ +
+
+cassandra.graph.graph_graphson3_row_factory(cluster)
+

Row factory to deserialize GraphSON3 results.

+
+ +
+
+cassandra.graph.to_int(value)
+

Wraps a value to be explicitly serialized as a graphson Int.

+
+ +
+
+cassandra.graph.to_bigint(value)
+

Wraps a value to be explicitly serialized as a graphson Bigint.

+
+ +
+
+cassandra.graph.to_smallint(value)
+

Wraps a value to be explicitly serialized as a graphson Smallint.

+
+ +
+
+cassandra.graph.to_float(value)
+

Wraps a value to be explicitly serialized as a graphson Float.

+
+ +
+
+cassandra.graph.to_double(value)
+

Wraps a value to be explicitly serialized as a graphson Double.

+
+ +
+
+class cassandra.graph.GraphProtocol
+
+
+GRAPHSON_1_0 = b'graphson-1.0'
+

GraphSON1

+
+ +
+
+GRAPHSON_2_0 = b'graphson-2.0'
+

GraphSON2

+
+ +
+
+GRAPHSON_3_0 = b'graphson-3.0'
+

GraphSON3

+
+ +
+ +
+
+class cassandra.graph.GraphOptions(**kwargs)
+

Options for DSE Graph Query handler.

+
+
+graph_name
+

name of the targeted graph.

+
+ +
+
+graph_source
+

choose the graph traversal source, configured on the server side.

+
+ +
+
+graph_language
+

the language used in the queries (default “gremlin-groovy”)

+
+ +
+
+graph_read_consistency_level
+

read cassandra.ConsistencyLevel for graph queries (if distinct from session default). +Setting this overrides the native Statement.consistency_level for read operations from Cassandra persistence

+
+ +
+
+graph_write_consistency_level
+

write cassandra.ConsistencyLevel for graph queries (if distinct from session default). +Setting this overrides the native Statement.consistency_level for write operations to Cassandra persistence.

+
+ +
+
+is_default_source
+
+ +
+
+is_analytics_source
+

True if graph_source is set to the server-defined analytics traversal source (‘a’)

+
+ +
+
+is_graph_source
+

True if graph_source is set to the server-defined graph traversal source (‘g’)

+
+ +
+
+set_source_default()
+

Sets graph_source to the server-defined default traversal source (‘default’)

+
+ +
+
+set_source_analytics()
+

Sets graph_source to the server-defined analytic traversal source (‘a’)

+
+ +
+
+set_source_graph()
+

Sets graph_source to the server-defined graph traversal source (‘g’)

+
+ +
+ +
+
+class cassandra.graph.SimpleGraphStatement(query_string, retry_policy=None, consistency_level=None, routing_key=None, serial_consistency_level=None, fetch_size=<object object>, keyspace=None, custom_payload=None, is_idempotent=False)
+

Simple graph statement for Session.execute_graph(). +Takes the same parameters as SimpleStatement.

+

query_string should be a literal CQL statement with the exception +of parameter placeholders that will be filled through the +parameters argument of Session.execute().

+

See Statement attributes for a description of the other parameters.

+
+ +
+
+class cassandra.graph.Result(value)
+

Represents deserialized graph results. +Property and item getters are provided for convenience.

+
+
+value = None
+

Deserialized value from the result

+
+ +
+
+as_vertex()
+

Return a Vertex parsed from this result

+

Raises TypeError if parsing fails (i.e. the result structure is not valid).

+
+ +
+
+as_edge()
+

Return a Edge parsed from this result

+

Raises TypeError if parsing fails (i.e. the result structure is not valid).

+
+ +
+
+as_path()
+

Return a Path parsed from this result

+

Raises TypeError if parsing fails (i.e. the result structure is not valid).

+
+ +
+ +
+
+class cassandra.graph.Vertex(id, label, type, properties)
+

Represents a Vertex element from a graph query.

+

Vertex properties are extracted into a dict of property names to list of VertexProperty (list +because they are always encoded that way, and sometimes have multiple cardinality; VertexProperty because sometimes +the properties themselves have property maps).

+
+ +
+
+class cassandra.graph.VertexProperty(label, value, properties=None)
+

Vertex properties have a top-level value and an optional dict of properties.

+
+
+label = None
+

label of the property

+
+ +
+
+value = None
+

Value of the property

+
+ +
+
+properties = None
+

dict of properties attached to the property

+
+ +
+ +
+
+class cassandra.graph.Edge(id, label, type, properties, inV, inVLabel, outV, outVLabel)
+

Represents an Edge element from a graph query.

+

Attributes match initializer parameters.

+
+ +
+
+class cassandra.graph.Path(labels, objects)
+

Represents a graph path.

+

Labels list is taken verbatim from the results.

+

Objects are either Result or Vertex/Edge for recognized types

+
+
+labels = None
+

List of labels in the path

+
+ +
+
+objects = None
+

List of objects in the path

+
+ +
+ +
+
+class cassandra.graph.GraphSON1Serializer
+

Serialize python objects to graphson types.

+
+ +
+
+class cassandra.graph.GraphSON1Deserializer
+

Deserialize graphson1 types to python objects.

+
+
+classmethod deserialize_date(value)
+
+ +
+
+classmethod deserialize_timestamp(value)
+
+ +
+
+classmethod deserialize_time(value)
+
+ +
+
+classmethod deserialize_duration(value)
+
+ +
+
+classmethod deserialize_int(value)
+
+ +
+
+classmethod deserialize_bigint(value)
+
+ +
+
+classmethod deserialize_double(value)
+
+ +
+
+classmethod deserialize_float(value)
+
+ +
+
+classmethod deserialize_uuid(value)
+
+ +
+
+classmethod deserialize_blob(value)
+
+ +
+
+classmethod deserialize_decimal(value)
+
+ +
+
+classmethod deserialize_point(value)
+
+ +
+
+classmethod deserialize_linestring(value)
+
+ +
+
+classmethod deserialize_polygon(value)
+
+ +
+ +
+
+class cassandra.graph.GraphSON2Reader(context, extra_deserializer_map=None)
+

GraphSON2 Reader that parse json and deserialize to python objects.

+
+
Parameters
+

extra_deserializer_map – map from GraphSON type tag to deserializer instance implementing deserialize

+
+
+
+
+read(json_data)
+

Read and deserialize json_data.

+
+ +
+
+deserialize(obj)
+

Deserialize GraphSON type-tagged dict values into objects mapped in self.deserializers

+
+ +
+ +
+
+class cassandra.graph.GraphSON3Reader(context, extra_deserializer_map=None)
+

GraphSON3 Reader that parse json and deserialize to python objects.

+
+
Parameters
+
    +
  • context – A dict of the context, mostly used as context for udt deserialization.

  • +
  • extra_deserializer_map – map from GraphSON type tag to deserializer instance implementing deserialize

  • +
+
+
+
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.22.3-scylla/api/cassandra/io/asyncioreactor.html b/3.22.3-scylla/api/cassandra/io/asyncioreactor.html new file mode 100644 index 0000000000..9691576dae --- /dev/null +++ b/3.22.3-scylla/api/cassandra/io/asyncioreactor.html @@ -0,0 +1,657 @@ + + + + + + + + + + + + + cassandra.io.asyncioreactor - asyncio Event Loop | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.io.asyncioreactor - asyncio Event Loop

+
+
+class cassandra.io.asyncioreactor.AsyncioConnection(*args, **kwargs)
+

An experimental implementation of Connection that uses the +asyncio module in the Python standard library for its event loop.

+

Note that it requires asyncio features that were only introduced in the +3.4 line in 3.4.6, and in the 3.5 line in 3.5.1.

+
+
+classmethod initialize_reactor()
+

Called once by Cluster.connect(). This should be used by implementations +to set up any resources that will be shared across connections.

+
+ +
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.22.3-scylla/api/cassandra/io/asyncorereactor.html b/3.22.3-scylla/api/cassandra/io/asyncorereactor.html new file mode 100644 index 0000000000..f6321734d6 --- /dev/null +++ b/3.22.3-scylla/api/cassandra/io/asyncorereactor.html @@ -0,0 +1,662 @@ + + + + + + + + + + + + + cassandra.io.asyncorereactor - asyncore Event Loop | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.io.asyncorereactor - asyncore Event Loop

+
+
+class cassandra.io.asyncorereactor.AsyncoreConnection(*args, **kwargs)
+

An implementation of Connection that uses the asyncore +module in the Python standard library for its event loop.

+
+
+classmethod initialize_reactor()
+

Called once by Cluster.connect(). This should be used by implementations +to set up any resources that will be shared across connections.

+
+ +
+
+classmethod handle_fork()
+

Called after a forking. This should cleanup any remaining reactor state +from the parent process.

+
+ +
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.22.3-scylla/api/cassandra/io/eventletreactor.html b/3.22.3-scylla/api/cassandra/io/eventletreactor.html new file mode 100644 index 0000000000..a3c8d807b8 --- /dev/null +++ b/3.22.3-scylla/api/cassandra/io/eventletreactor.html @@ -0,0 +1,664 @@ + + + + + + + + + + + + + cassandra.io.eventletreactor - eventlet-compatible Connection | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.io.eventletreactor - eventlet-compatible Connection

+
+
+class cassandra.io.eventletreactor.EventletConnection(*args, **kwargs)
+

An implementation of Connection that utilizes eventlet.

+

This implementation assumes all eventlet monkey patching is active. It is not tested with partial patching.

+
+
+classmethod initialize_reactor()
+

Called once by Cluster.connect(). This should be used by implementations +to set up any resources that will be shared across connections.

+
+ +
+
+classmethod service_timeouts()
+

cls._timeout_watcher runs in this loop forever. +It is usually waiting for the next timeout on the cls._new_timer Event. +When new timers are added, that event is set so that the watcher can +wake up and possibly set an earlier timeout.

+
+ +
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.22.3-scylla/api/cassandra/io/geventreactor.html b/3.22.3-scylla/api/cassandra/io/geventreactor.html new file mode 100644 index 0000000000..b5089894e9 --- /dev/null +++ b/3.22.3-scylla/api/cassandra/io/geventreactor.html @@ -0,0 +1,655 @@ + + + + + + + + + + + + + cassandra.io.geventreactor - gevent-compatible Event Loop | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.io.geventreactor - gevent-compatible Event Loop

+
+
+class cassandra.io.geventreactor.GeventConnection(*args, **kwargs)
+

An implementation of Connection that utilizes gevent.

+

This implementation assumes all gevent monkey patching is active. It is not tested with partial patching.

+
+
+classmethod initialize_reactor()
+

Called once by Cluster.connect(). This should be used by implementations +to set up any resources that will be shared across connections.

+
+ +
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.22.3-scylla/api/cassandra/io/libevreactor.html b/3.22.3-scylla/api/cassandra/io/libevreactor.html new file mode 100644 index 0000000000..f9219c6850 --- /dev/null +++ b/3.22.3-scylla/api/cassandra/io/libevreactor.html @@ -0,0 +1,647 @@ + + + + + + + + + + + + + cassandra.io.libevreactor - libev Event Loop | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.io.libevreactor - libev Event Loop

+
+
+class cassandra.io.libevreactor.LibevConnection(*args, **kwargs)
+

An implementation of Connection that uses libev for its event loop.

+
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.22.3-scylla/api/cassandra/io/twistedreactor.html b/3.22.3-scylla/api/cassandra/io/twistedreactor.html new file mode 100644 index 0000000000..09eef2f340 --- /dev/null +++ b/3.22.3-scylla/api/cassandra/io/twistedreactor.html @@ -0,0 +1,648 @@ + + + + + + + + + + + + + cassandra.io.twistedreactor - Twisted Event Loop | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.io.twistedreactor - Twisted Event Loop

+
+
+class cassandra.io.twistedreactor.TwistedConnection
+

An implementation of Connection that uses +Twisted’s reactor as its event loop.

+
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.22.3-scylla/api/cassandra/metadata.html b/3.22.3-scylla/api/cassandra/metadata.html new file mode 100644 index 0000000000..e0870dfaf6 --- /dev/null +++ b/3.22.3-scylla/api/cassandra/metadata.html @@ -0,0 +1,1026 @@ + + + + + + + + + + + + + cassandra.metadata - Schema and Ring Topology | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.metadata - Schema and Ring Topology

+
+
+cassandra.metadata.cql_keywords
+

set() -> new empty set object +set(iterable) -> new set object

+

Build an unordered collection of unique elements.

+
+ +
+
+cassandra.metadata.cql_keywords_unreserved
+

set() -> new empty set object +set(iterable) -> new set object

+

Build an unordered collection of unique elements.

+
+ +
+
+cassandra.metadata.cql_keywords_reserved
+

set() -> new empty set object +set(iterable) -> new set object

+

Build an unordered collection of unique elements.

+
+ +
+
+class cassandra.metadata.Metadata
+

Holds a representation of the cluster schema and topology.

+
+
+add_or_return_host(host)
+

Returns a tuple (host, new), where host is a Host +instance, and new is a bool indicating whether +the host was newly added.

+
+ +
+
+all_hosts()
+

Returns a list of all known Host instances in the cluster.

+
+ +
+
+export_schema_as_string()
+

Returns a string that can be executed as a query in order to recreate +the entire schema. The string is formatted to be human readable.

+
+ +
+
+get_host(endpoint_or_address, port=None)
+

Find a host in the metadata for a specific endpoint. If a string inet address and port are passed, +iterate all hosts to match the broadcast_rpc_address and +broadcast_rpc_port attributes.

+
+ +
+
+get_host_by_host_id(host_id)
+

Same as get_host() but use host_id for lookup.

+
+ +
+
+get_replicas(keyspace, key)
+

Returns a list of Host instances that are replicas for a given +partition key.

+
+ +
+ +
+

Schemas

+
+
+class cassandra.metadata.KeyspaceMetadata
+

A representation of the schema for a single keyspace.

+
+
+as_cql_query()
+

Returns a CQL query string that can be used to recreate just this keyspace, +not including user-defined types and tables.

+
+ +
+
+export_as_string()
+

Returns a CQL query string that can be used to recreate the entire keyspace, +including user-defined types and tables.

+
+ +
+ +
+
+class cassandra.metadata.UserType
+

A user defined type, as created by CREATE TYPE statements.

+

User-defined types were introduced in Cassandra 2.1.

+
+

New in version 2.1.0.

+
+
+
+as_cql_query(formatted=False)
+

Returns a CQL query that can be used to recreate this type. +If formatted is set to True, extra whitespace will +be added to make the query more readable.

+
+ +
+ +
+
+class cassandra.metadata.Function
+

A user defined function, as created by CREATE FUNCTION statements.

+

User-defined functions were introduced in Cassandra 2.2

+
+

New in version 2.6.0.

+
+
+
+as_cql_query(formatted=False)
+

Returns a CQL query that can be used to recreate this function. +If formatted is set to True, extra whitespace will +be added to make the query more readable.

+
+ +
+ +
+
+class cassandra.metadata.Aggregate
+

A user defined aggregate function, as created by CREATE AGGREGATE statements.

+

Aggregate functions were introduced in Cassandra 2.2

+
+

New in version 2.6.0.

+
+
+
+as_cql_query(formatted=False)
+

Returns a CQL query that can be used to recreate this aggregate. +If formatted is set to True, extra whitespace will +be added to make the query more readable.

+
+ +
+ +
+
+class cassandra.metadata.TableMetadata
+

A representation of the schema for a single table.

+
+
+as_cql_query(formatted=False)
+

Returns a CQL query that can be used to recreate this table (index +creations are not included). If formatted is set to True, +extra whitespace will be added to make the query human readable.

+
+ +
+
+export_as_string()
+

Returns a string of CQL queries that can be used to recreate this table +along with all indexes on it. The returned string is formatted to +be human readable.

+
+ +
+
+property is_cql_compatible
+

A boolean indicating if this table can be represented as CQL in export

+
+ +
+
+property primary_key
+

A list of ColumnMetadata representing the components of +the primary key for this table.

+
+ +
+ +
+
+class cassandra.metadata.TableMetadataV3
+

For C* 3.0+. option_maps take a superset of map names, so if nothing +changes structurally, new option maps can just be appended to the list.

+
+
+property is_cql_compatible
+

A boolean indicating if this table can be represented as CQL in export

+
+ +
+ +
+
+class cassandra.metadata.TableMetadataDSE68
+
+
+as_cql_query(formatted=False)
+

Returns a CQL query that can be used to recreate this table (index +creations are not included). If formatted is set to True, +extra whitespace will be added to make the query human readable.

+
+ +
+ +
+
+class cassandra.metadata.ColumnMetadata
+

A representation of a single column in a table.

+
+ +
+
+class cassandra.metadata.IndexMetadata
+

A representation of a secondary index on a column.

+
+
+as_cql_query()
+

Returns a CQL query that can be used to recreate this index.

+
+ +
+
+export_as_string()
+

Returns a CQL query string that can be used to recreate this index.

+
+ +
+ +
+
+class cassandra.metadata.MaterializedViewMetadata
+

A representation of a materialized view on a table

+
+
+as_cql_query(formatted=False)
+

Returns a CQL query that can be used to recreate this function. +If formatted is set to True, extra whitespace will +be added to make the query more readable.

+
+ +
+ +
+
+class cassandra.metadata.VertexMetadata
+

A representation of a vertex on a table

+
+ +
+
+class cassandra.metadata.EdgeMetadata
+

A representation of an edge on a table

+
+ +
+
+

Tokens and Ring Topology

+
+
+class cassandra.metadata.TokenMap
+

Information about the layout of the ring.

+
+
+get_replicas(keyspace, token)
+

Get a set of Host instances representing all of the +replica nodes for a given Token.

+
+ +
+ +
+
+class cassandra.metadata.Token
+

Abstract class representing a token.

+
+ +
+
+class cassandra.metadata.Murmur3Token(token)
+

A token for Murmur3Partitioner.

+

token is an int or string representing the token.

+
+ +
+
+class cassandra.metadata.MD5Token(token)
+

A token for RandomPartitioner.

+
+ +
+
+class cassandra.metadata.BytesToken(token)
+

A token for ByteOrderedPartitioner.

+
+
+classmethod from_string(token_string)
+

token_string should be the string representation from the server.

+
+ +
+ +
+
+cassandra.metadata.ReplicationStrategy
+

alias of cassandra.metadata._ReplicationStrategy

+
+ +
+
+class cassandra.metadata.SimpleStrategy(options_map)
+
+
+export_for_schema()
+

Returns a string version of these replication options which are +suitable for use in a CREATE KEYSPACE statement.

+
+ +
+
+property replication_factor
+

The replication factor for this keyspace.

+

For backward compatibility, this returns the +cassandra.metadata.ReplicationFactor.full_replicas value of +cassandra.metadata.SimpleStrategy.replication_factor_info.

+
+ +
+ +
+
+class cassandra.metadata.NetworkTopologyStrategy(dc_replication_factors)
+
+
+export_for_schema()
+

Returns a string version of these replication options which are +suitable for use in a CREATE KEYSPACE statement.

+
+ +
+ +
+
+class cassandra.metadata.LocalStrategy(options_map)
+
+
+export_for_schema()
+

Returns a string version of these replication options which are +suitable for use in a CREATE KEYSPACE statement.

+
+ +
+ +
+
+cassandra.metadata.group_keys_by_replica(session, keyspace, table, keys)
+

Returns a dict with the keys grouped per host. This can be +used to more accurately group by IN clause or to batch the keys per host.

+

If a valid replica is not found for a particular key it will be grouped under +NO_VALID_REPLICA

+

Example usage:

+
>>> result = group_keys_by_replica(
+...     session, "system", "peers",
+...     (("127.0.0.1", ), ("127.0.0.2", )))
+
+
+
+ +
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.22.3-scylla/api/cassandra/metrics.html b/3.22.3-scylla/api/cassandra/metrics.html new file mode 100644 index 0000000000..5d20fadae4 --- /dev/null +++ b/3.22.3-scylla/api/cassandra/metrics.html @@ -0,0 +1,755 @@ + + + + + + + + + + + + + cassandra.metrics - Performance Metrics | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.metrics - Performance Metrics

+
+
+class cassandra.metrics.Metrics
+

A collection of timers and counters for various performance metrics.

+

Timer metrics are represented as floating point seconds.

+
+
+request_timer = None
+

A greplin.scales.PmfStat timer for requests. This is a dict-like +object with the following keys:

+
    +
  • count - number of requests that have been timed

  • +
  • min - min latency

  • +
  • max - max latency

  • +
  • mean - mean latency

  • +
  • stddev - standard deviation for latencies

  • +
  • median - median latency

  • +
  • 75percentile - 75th percentile latencies

  • +
  • 95percentile - 95th percentile latencies

  • +
  • 98percentile - 98th percentile latencies

  • +
  • 99percentile - 99th percentile latencies

  • +
  • 999percentile - 99.9th percentile latencies

  • +
+
+ +
+
+connection_errors = None
+

A greplin.scales.IntStat count of the number of times that a +request to a Cassandra node has failed due to a connection problem.

+
+ +
+
+write_timeouts = None
+

A greplin.scales.IntStat count of write requests that resulted +in a timeout.

+
+ +
+
+read_timeouts = None
+

A greplin.scales.IntStat count of read requests that resulted +in a timeout.

+
+ +
+
+unavailables = None
+

A greplin.scales.IntStat count of write or read requests that +failed due to an insufficient number of replicas being alive to meet +the requested ConsistencyLevel.

+
+ +
+
+other_errors = None
+

A greplin.scales.IntStat count of all other request failures, +including failures caused by invalid requests, bootstrapping nodes, +overloaded nodes, etc.

+
+ +
+
+retries = None
+

A greplin.scales.IntStat count of the number of times a +request was retried based on the RetryPolicy decision.

+
+ +
+
+ignores = None
+

A greplin.scales.IntStat count of the number of times a +failed request was ignored based on the RetryPolicy decision.

+
+ +
+
+known_hosts = None
+

A greplin.scales.IntStat count of the number of nodes in +the cluster that the driver is aware of, regardless of whether any +connections are opened to those nodes.

+
+ +
+
+connected_to = None
+

A greplin.scales.IntStat count of the number of nodes that +the driver currently has at least one connection open to.

+
+ +
+
+open_connections = None
+

A greplin.scales.IntStat count of the number connections +the driver currently has open.

+
+ +
+
+get_stats()
+

Returns the metrics for the registered cluster instance.

+
+ +
+
+set_stats_name(stats_name)
+

Set the metrics stats name. +The stats_name is a string used to access the metris through scales: scales.getStats()[<stats_name>] +Default is ‘cassandra-<num>’.

+
+ +
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.22.3-scylla/api/cassandra/policies.html b/3.22.3-scylla/api/cassandra/policies.html new file mode 100644 index 0000000000..bac204b5ca --- /dev/null +++ b/3.22.3-scylla/api/cassandra/policies.html @@ -0,0 +1,1742 @@ + + + + + + + + + + + + + cassandra.policies - Load balancing and Failure Handling Policies | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.policies - Load balancing and Failure Handling Policies

+
+

Load Balancing

+
+
+class cassandra.policies.HostDistance
+

A measure of how “distant” a node is from the client, which +may influence how the load balancer distributes requests +and how many connections are opened to the node.

+
+
+IGNORED = -1
+

A node with this distance should never be queried or have +connections opened to it.

+
+ +
+
+LOCAL = 0
+

Nodes with LOCAL distance will be preferred for operations +under some load balancing policies (such as DCAwareRoundRobinPolicy) +and will have a greater number of connections opened against +them by default.

+

This distance is typically used for nodes within the same +datacenter as the client.

+
+ +
+
+REMOTE = 1
+

Nodes with REMOTE distance will be treated as a last resort +by some load balancing policies (such as DCAwareRoundRobinPolicy) +and will have a smaller number of connections opened against +them by default.

+

This distance is typically used for nodes outside of the +datacenter that the client is running in.

+
+ +
+ +
+
+class cassandra.policies.LoadBalancingPolicy
+

Load balancing policies are used to decide how to distribute +requests among all possible coordinator nodes in the cluster.

+

In particular, they may focus on querying “near” nodes (those +in a local datacenter) or on querying nodes who happen to +be replicas for the requested data.

+

You may also use subclasses of LoadBalancingPolicy for +custom behavior.

+
+
+distance(host)
+

Returns a measure of how remote a Host is in +terms of the HostDistance enums.

+
+ +
+
+populate(cluster, hosts)
+

This method is called to initialize the load balancing +policy with a set of Host instances before its +first use. The cluster parameter is an instance of +Cluster.

+
+ +
+
+make_query_plan(working_keyspace=None, query=None)
+

Given a Statement instance, return a iterable +of Host instances which should be queried in that +order. A generator may work well for custom implementations +of this method.

+

Note that the query argument may be None when preparing +statements.

+

working_keyspace should be the string name of the current keyspace, +as set through Session.set_keyspace() or with a USE +statement.

+
+ +
+
+check_supported()
+

This will be called after the cluster Metadata has been initialized. +If the load balancing policy implementation cannot be supported for +some reason (such as a missing C extension), this is the point at +which it should raise an exception.

+
+ +
+ +
+
+class cassandra.policies.RoundRobinPolicy
+

A subclass of LoadBalancingPolicy which evenly +distributes queries across all nodes in the cluster, +regardless of what datacenter the nodes may be in.

+
+
+populate(cluster, hosts)
+

This method is called to initialize the load balancing +policy with a set of Host instances before its +first use. The cluster parameter is an instance of +Cluster.

+
+ +
+
+distance(host)
+

Returns a measure of how remote a Host is in +terms of the HostDistance enums.

+
+ +
+
+make_query_plan(working_keyspace=None, query=None)
+

Given a Statement instance, return a iterable +of Host instances which should be queried in that +order. A generator may work well for custom implementations +of this method.

+

Note that the query argument may be None when preparing +statements.

+

working_keyspace should be the string name of the current keyspace, +as set through Session.set_keyspace() or with a USE +statement.

+
+ +
+
+on_up(host)
+

Called when a node is marked up.

+
+ +
+
+on_down(host)
+

Called when a node is marked down.

+
+ +
+
+on_add(host)
+

Called when a node is added to the cluster. The newly added node +should be considered up.

+
+ +
+
+on_remove(host)
+

Called when a node is removed from the cluster.

+
+ +
+ +
+
+class cassandra.policies.DCAwareRoundRobinPolicy(local_dc='', used_hosts_per_remote_dc=0)
+

Similar to RoundRobinPolicy, but prefers hosts +in the local datacenter and only uses nodes in remote +datacenters as a last resort.

+

The local_dc parameter should be the name of the datacenter +(such as is reported by nodetool ring) that should +be considered local. If not specified, the driver will choose +a local_dc based on the first host among Cluster.contact_points +having a valid DC. If relying on this mechanism, all specified +contact points should be nodes in a single, local DC.

+

used_hosts_per_remote_dc controls how many nodes in +each remote datacenter will have connections opened +against them. In other words, used_hosts_per_remote_dc hosts +will be considered REMOTE and the +rest will be considered IGNORED. +By default, all remote hosts are ignored.

+
+
+populate(cluster, hosts)
+

This method is called to initialize the load balancing +policy with a set of Host instances before its +first use. The cluster parameter is an instance of +Cluster.

+
+ +
+
+distance(host)
+

Returns a measure of how remote a Host is in +terms of the HostDistance enums.

+
+ +
+
+make_query_plan(working_keyspace=None, query=None)
+

Given a Statement instance, return a iterable +of Host instances which should be queried in that +order. A generator may work well for custom implementations +of this method.

+

Note that the query argument may be None when preparing +statements.

+

working_keyspace should be the string name of the current keyspace, +as set through Session.set_keyspace() or with a USE +statement.

+
+ +
+
+on_up(host)
+

Called when a node is marked up.

+
+ +
+
+on_down(host)
+

Called when a node is marked down.

+
+ +
+
+on_add(host)
+

Called when a node is added to the cluster. The newly added node +should be considered up.

+
+ +
+
+on_remove(host)
+

Called when a node is removed from the cluster.

+
+ +
+ +
+
+class cassandra.policies.WhiteListRoundRobinPolicy(hosts)
+

A subclass of RoundRobinPolicy which evenly +distributes queries across all nodes in the cluster, +regardless of what datacenter the nodes may be in, but +only if that node exists in the list of allowed nodes

+

This policy is addresses the issue described in +https://datastax-oss.atlassian.net/browse/JAVA-145 +Where connection errors occur when connection +attempts are made to private IP addresses remotely

+

The hosts parameter should be a sequence of hosts to permit +connections to.

+
+
+populate(cluster, hosts)
+

This method is called to initialize the load balancing +policy with a set of Host instances before its +first use. The cluster parameter is an instance of +Cluster.

+
+ +
+
+distance(host)
+

Returns a measure of how remote a Host is in +terms of the HostDistance enums.

+
+ +
+
+on_up(host)
+

Called when a node is marked up.

+
+ +
+
+on_add(host)
+

Called when a node is added to the cluster. The newly added node +should be considered up.

+
+ +
+ +
+
+class cassandra.policies.TokenAwarePolicy(child_policy, shuffle_replicas=False)
+

A LoadBalancingPolicy wrapper that adds token awareness to +a child policy.

+

This alters the child policy’s behavior so that it first attempts to +send queries to LOCAL replicas (as determined +by the child policy) based on the Statement’s +routing_key. If shuffle_replicas is +truthy, these replicas will be yielded in a random order. Once those +hosts are exhausted, the remaining hosts in the child policy’s query +plan will be used in the order provided by the child policy.

+

If no routing_key is set on the query, the child +policy’s query plan will be used as is.

+
+
+shuffle_replicas = False
+

Yield local replicas in a random order.

+
+ +
+
+populate(cluster, hosts)
+

This method is called to initialize the load balancing +policy with a set of Host instances before its +first use. The cluster parameter is an instance of +Cluster.

+
+ +
+
+check_supported()
+

This will be called after the cluster Metadata has been initialized. +If the load balancing policy implementation cannot be supported for +some reason (such as a missing C extension), this is the point at +which it should raise an exception.

+
+ +
+
+distance(*args, **kwargs)
+

Returns a measure of how remote a Host is in +terms of the HostDistance enums.

+
+ +
+
+make_query_plan(working_keyspace=None, query=None)
+

Given a Statement instance, return a iterable +of Host instances which should be queried in that +order. A generator may work well for custom implementations +of this method.

+

Note that the query argument may be None when preparing +statements.

+

working_keyspace should be the string name of the current keyspace, +as set through Session.set_keyspace() or with a USE +statement.

+
+ +
+
+on_up(*args, **kwargs)
+

Called when a node is marked up.

+
+ +
+
+on_down(*args, **kwargs)
+

Called when a node is marked down.

+
+ +
+
+on_add(*args, **kwargs)
+

Called when a node is added to the cluster. The newly added node +should be considered up.

+
+ +
+
+on_remove(*args, **kwargs)
+

Called when a node is removed from the cluster.

+
+ +
+ +
+
+class cassandra.policies.HostFilterPolicy(child_policy, predicate)
+

A LoadBalancingPolicy subclass configured with a child policy, +and a single-argument predicate. This policy defers to the child policy for +hosts where predicate(host) is truthy. Hosts for which +predicate(host) is falsey will be considered IGNORED, and will +not be used in a query plan.

+

This can be used in the cases where you need a whitelist or blacklist +policy, e.g. to prepare for decommissioning nodes or for testing:

+
def address_is_ignored(host):
+    return host.address in [ignored_address0, ignored_address1]
+
+blacklist_filter_policy = HostFilterPolicy(
+    child_policy=RoundRobinPolicy(),
+    predicate=address_is_ignored
+)
+
+cluster = Cluster(
+    primary_host,
+    load_balancing_policy=blacklist_filter_policy,
+)
+
+
+

See the note in the make_query_plan() documentation for a caveat on +how wrapping ordering polices (e.g. RoundRobinPolicy) may break +desirable properties of the wrapped policy.

+

Please note that whitelist and blacklist policies are not recommended for +general, day-to-day use. You probably want something like +DCAwareRoundRobinPolicy, which prefers a local DC but has +fallbacks, over a brute-force method like whitelisting or blacklisting.

+
+
Parameters
+
    +
  • child_policy – an instantiated LoadBalancingPolicy +that this one will defer to.

  • +
  • predicate – a one-parameter function that takes a Host. +If it returns a falsey value, the Host will +be IGNORED and not returned in query plans.

  • +
+
+
+
+
+predicate(host)
+

A predicate, set on object initialization, that takes a Host +and returns a value. If the value is falsy, the Host is +IGNORED. If the value is truthy, +HostFilterPolicy defers to the child policy to determine the +host’s distance.

+

This is a read-only value set in __init__, implemented as a +property.

+
+ +
+
+distance(host)
+

Checks if predicate(host), then returns +IGNORED if falsey, and defers to the child policy +otherwise.

+
+ +
+
+make_query_plan(working_keyspace=None, query=None)
+

Defers to the child policy’s +LoadBalancingPolicy.make_query_plan() and filters the results.

+

Note that this filtering may break desirable properties of the wrapped +policy in some cases. For instance, imagine if you configure this +policy to filter out host2, and to wrap a round-robin policy that +rotates through three hosts in the order host1, host2, host3, +host2, host3, host1, host3, host1, host2, repeating. This +policy will yield host1, host3, host3, host1, host3, host1, +disproportionately favoring host3.

+
+ +
+ +
+
+class cassandra.policies.DefaultLoadBalancingPolicy(child_policy)
+

A LoadBalancingPolicy wrapper that adds the ability to target a specific host first.

+

If no host is set on the query, the child policy’s query plan will be used as is.

+
+
+populate(cluster, hosts)
+

This method is called to initialize the load balancing +policy with a set of Host instances before its +first use. The cluster parameter is an instance of +Cluster.

+
+ +
+
+make_query_plan(working_keyspace=None, query=None)
+

Given a Statement instance, return a iterable +of Host instances which should be queried in that +order. A generator may work well for custom implementations +of this method.

+

Note that the query argument may be None when preparing +statements.

+

working_keyspace should be the string name of the current keyspace, +as set through Session.set_keyspace() or with a USE +statement.

+
+ +
+ +
+
+class cassandra.policies.DSELoadBalancingPolicy(*args, **kwargs)
+

Deprecated: This will be removed in the next major release, +consider using DefaultLoadBalancingPolicy.

+
+ +
+
+

Translating Server Node Addresses

+
+
+class cassandra.policies.AddressTranslator
+

Interface for translating cluster-defined endpoints.

+

The driver discovers nodes using server metadata and topology change events. Normally, +the endpoint defined by the server is the right way to connect to a node. In some environments, +these addresses may not be reachable, or not preferred (public vs. private IPs in cloud environments, +suboptimal routing, etc). This interface allows for translating from server defined endpoints to +preferred addresses for driver connections.

+

Note: contact_points provided while creating the Cluster instance are not +translated using this mechanism – only addresses received from Cassandra nodes are.

+
+
+translate(addr)
+

Accepts the node ip address, and returns a translated address to be used connecting to this node.

+
+ +
+ +
+
+class cassandra.policies.IdentityTranslator
+

Returns the endpoint with no translation

+
+
+translate(addr)
+

Accepts the node ip address, and returns a translated address to be used connecting to this node.

+
+ +
+ +
+
+class cassandra.policies.EC2MultiRegionTranslator
+

Resolves private ips of the hosts in the same datacenter as the client, and public ips of hosts in other datacenters.

+
+
+translate(addr)
+

Reverse DNS the public broadcast_address, then lookup that hostname to get the AWS-resolved IP, which +will point to the private IP address within the same datacenter.

+
+ +
+ +
+
+

Marking Hosts Up or Down

+
+
+class cassandra.policies.ConvictionPolicy(host)
+

A policy which decides when hosts should be considered down +based on the types of failures and the number of failures.

+

If custom behavior is needed, this class may be subclassed.

+

host is an instance of Host.

+
+
+add_failure(connection_exc)
+

Implementations should return True if the host should be +convicted, False otherwise.

+
+ +
+
+reset()
+

Implementations should clear out any convictions or state regarding +the host.

+
+ +
+ +
+
+class cassandra.policies.SimpleConvictionPolicy(host)
+

The default implementation of ConvictionPolicy, +which simply marks a host as down after the first failure +of any kind.

+

host is an instance of Host.

+
+
+add_failure(connection_exc)
+

Implementations should return True if the host should be +convicted, False otherwise.

+
+ +
+
+reset()
+

Implementations should clear out any convictions or state regarding +the host.

+
+ +
+ +
+
+

Reconnecting to Dead Hosts

+
+
+class cassandra.policies.ReconnectionPolicy
+

This class and its subclasses govern how frequently an attempt is made +to reconnect to nodes that are marked as dead.

+

If custom behavior is needed, this class may be subclassed.

+
+
+new_schedule()
+

This should return a finite or infinite iterable of delays (each as a +floating point number of seconds) inbetween each failed reconnection +attempt. Note that if the iterable is finite, reconnection attempts +will cease once the iterable is exhausted.

+
+ +
+ +
+
+class cassandra.policies.ConstantReconnectionPolicy(delay, max_attempts=64)
+

A ReconnectionPolicy subclass which sleeps for a fixed delay +inbetween each reconnection attempt.

+

delay should be a floating point number of seconds to wait inbetween +each attempt.

+

max_attempts should be a total number of attempts to be made before +giving up, or None to continue reconnection attempts forever. +The default is 64.

+
+
+new_schedule()
+

This should return a finite or infinite iterable of delays (each as a +floating point number of seconds) inbetween each failed reconnection +attempt. Note that if the iterable is finite, reconnection attempts +will cease once the iterable is exhausted.

+
+ +
+ +
+
+class cassandra.policies.ExponentialReconnectionPolicy(base_delay, max_delay, max_attempts=64)
+

A ReconnectionPolicy subclass which exponentially increases +the length of the delay inbetween each reconnection attempt up to +a set maximum delay.

+

A random amount of jitter (+/- 15%) will be added to the pure exponential +delay value to avoid the situations where many reconnection handlers are +trying to reconnect at exactly the same time.

+

base_delay and max_delay should be in floating point units of +seconds.

+

max_attempts should be a total number of attempts to be made before +giving up, or None to continue reconnection attempts forever. +The default is 64.

+
+
+new_schedule()
+

This should return a finite or infinite iterable of delays (each as a +floating point number of seconds) inbetween each failed reconnection +attempt. Note that if the iterable is finite, reconnection attempts +will cease once the iterable is exhausted.

+
+ +
+ +
+
+

Retrying Failed Operations

+
+
+class cassandra.policies.WriteType
+

For usage with RetryPolicy, this describe a type +of write operation.

+
+
+SIMPLE = 0
+

A write to a single partition key. Such writes are guaranteed to be atomic +and isolated.

+
+ +
+
+BATCH = 1
+

A write to multiple partition keys that used the distributed batch log to +ensure atomicity.

+
+ +
+
+UNLOGGED_BATCH = 2
+

A write to multiple partition keys that did not use the distributed batch +log. Atomicity for such writes is not guaranteed.

+
+ +
+
+COUNTER = 3
+

A counter write (for one or multiple partition keys). Such writes should +not be replayed in order to avoid overcount.

+
+ +
+
+BATCH_LOG = 4
+

The initial write to the distributed batch log that Cassandra performs +internally before a BATCH write.

+
+ +
+
+CAS = 5
+

A lighweight-transaction write, such as “DELETE … IF EXISTS”.

+
+ +
+
+VIEW = 6
+

This WriteType is only seen in results for requests that were unable to +complete MV operations.

+
+ +
+
+CDC = 7
+

This WriteType is only seen in results for requests that were unable to +complete CDC operations.

+
+ +
+ +
+
+class cassandra.policies.RetryPolicy
+

A policy that describes whether to retry, rethrow, or ignore coordinator +timeout and unavailable failures. These are failures reported from the +server side. Timeouts are configured by +settings in cassandra.yaml. +Unavailable failures occur when the coordinator cannot acheive the consistency +level for a request. For further information see the method descriptions +below.

+

To specify a default retry policy, set the +Cluster.default_retry_policy attribute to an instance of this +class or one of its subclasses.

+

To specify a retry policy per query, set the Statement.retry_policy +attribute to an instance of this class or one of its subclasses.

+

If custom behavior is needed for retrying certain operations, +this class may be subclassed.

+
+
+RETRY = 0
+

This should be returned from the below methods if the operation +should be retried on the same connection.

+
+ +
+
+RETHROW = 1
+

This should be returned from the below methods if the failure +should be propagated and no more retries attempted.

+
+ +
+
+IGNORE = 2
+

This should be returned from the below methods if the failure +should be ignored but no more retries should be attempted.

+
+ +
+
+RETRY_NEXT_HOST = 3
+

This should be returned from the below methods if the operation +should be retried on another connection.

+
+ +
+
+on_read_timeout(query, consistency, required_responses, received_responses, data_retrieved, retry_num)
+

This is called when a read operation times out from the coordinator’s +perspective (i.e. a replica did not respond to the coordinator in time). +It should return a tuple with two items: one of the class enums (such +as RETRY) and a ConsistencyLevel to retry the +operation at or None to keep the same consistency level.

+

query is the Statement that timed out.

+

consistency is the ConsistencyLevel that the operation was +attempted at.

+

The required_responses and received_responses parameters describe +how many replicas needed to respond to meet the requested consistency +level and how many actually did respond before the coordinator timed +out the request. data_retrieved is a boolean indicating whether +any of those responses contained data (as opposed to just a digest).

+

retry_num counts how many times the operation has been retried, so +the first time this method is called, retry_num will be 0.

+

By default, operations will be retried at most once, and only if +a sufficient number of replicas responded (with data digests).

+
+ +
+
+on_write_timeout(query, consistency, write_type, required_responses, received_responses, retry_num)
+

This is called when a write operation times out from the coordinator’s +perspective (i.e. a replica did not respond to the coordinator in time).

+

query is the Statement that timed out.

+

consistency is the ConsistencyLevel that the operation was +attempted at.

+

write_type is one of the WriteType enums describing the +type of write operation.

+

The required_responses and received_responses parameters describe +how many replicas needed to acknowledge the write to meet the requested +consistency level and how many replicas actually did acknowledge the +write before the coordinator timed out the request.

+

retry_num counts how many times the operation has been retried, so +the first time this method is called, retry_num will be 0.

+

By default, failed write operations will retried at most once, and +they will only be retried if the write_type was +BATCH_LOG.

+
+ +
+
+on_unavailable(query, consistency, required_replicas, alive_replicas, retry_num)
+

This is called when the coordinator node determines that a read or +write operation cannot be successful because the number of live +replicas are too low to meet the requested ConsistencyLevel. +This means that the read or write operation was never forwarded to +any replicas.

+

query is the Statement that failed.

+

consistency is the ConsistencyLevel that the operation was +attempted at.

+

required_replicas is the number of replicas that would have needed to +acknowledge the operation to meet the requested consistency level. +alive_replicas is the number of replicas that the coordinator +considered alive at the time of the request.

+

retry_num counts how many times the operation has been retried, so +the first time this method is called, retry_num will be 0.

+

By default, if this is the first retry, it triggers a retry on the next +host in the query plan with the same consistency level. If this is not the +first retry, no retries will be attempted and the error will be re-raised.

+
+ +
+
+on_request_error(query, consistency, error, retry_num)
+

This is called when an unexpected error happens. This can be in the +following situations:

+
    +
  • On a connection error

  • +
  • On server errors: overloaded, isBootstrapping, serverError, etc.

  • +
+

query is the Statement that timed out.

+

consistency is the ConsistencyLevel that the operation was +attempted at.

+

error the instance of the exception.

+

retry_num counts how many times the operation has been retried, so +the first time this method is called, retry_num will be 0.

+

The default, it triggers a retry on the next host in the query plan +with the same consistency level.

+
+ +
+ +
+
+class cassandra.policies.FallthroughRetryPolicy
+

A retry policy that never retries and always propagates failures to +the application.

+
+
+on_read_timeout(*args, **kwargs)
+

This is called when a read operation times out from the coordinator’s +perspective (i.e. a replica did not respond to the coordinator in time). +It should return a tuple with two items: one of the class enums (such +as RETRY) and a ConsistencyLevel to retry the +operation at or None to keep the same consistency level.

+

query is the Statement that timed out.

+

consistency is the ConsistencyLevel that the operation was +attempted at.

+

The required_responses and received_responses parameters describe +how many replicas needed to respond to meet the requested consistency +level and how many actually did respond before the coordinator timed +out the request. data_retrieved is a boolean indicating whether +any of those responses contained data (as opposed to just a digest).

+

retry_num counts how many times the operation has been retried, so +the first time this method is called, retry_num will be 0.

+

By default, operations will be retried at most once, and only if +a sufficient number of replicas responded (with data digests).

+
+ +
+
+on_write_timeout(*args, **kwargs)
+

This is called when a write operation times out from the coordinator’s +perspective (i.e. a replica did not respond to the coordinator in time).

+

query is the Statement that timed out.

+

consistency is the ConsistencyLevel that the operation was +attempted at.

+

write_type is one of the WriteType enums describing the +type of write operation.

+

The required_responses and received_responses parameters describe +how many replicas needed to acknowledge the write to meet the requested +consistency level and how many replicas actually did acknowledge the +write before the coordinator timed out the request.

+

retry_num counts how many times the operation has been retried, so +the first time this method is called, retry_num will be 0.

+

By default, failed write operations will retried at most once, and +they will only be retried if the write_type was +BATCH_LOG.

+
+ +
+
+on_unavailable(*args, **kwargs)
+

This is called when the coordinator node determines that a read or +write operation cannot be successful because the number of live +replicas are too low to meet the requested ConsistencyLevel. +This means that the read or write operation was never forwarded to +any replicas.

+

query is the Statement that failed.

+

consistency is the ConsistencyLevel that the operation was +attempted at.

+

required_replicas is the number of replicas that would have needed to +acknowledge the operation to meet the requested consistency level. +alive_replicas is the number of replicas that the coordinator +considered alive at the time of the request.

+

retry_num counts how many times the operation has been retried, so +the first time this method is called, retry_num will be 0.

+

By default, if this is the first retry, it triggers a retry on the next +host in the query plan with the same consistency level. If this is not the +first retry, no retries will be attempted and the error will be re-raised.

+
+ +
+
+on_request_error(*args, **kwargs)
+

This is called when an unexpected error happens. This can be in the +following situations:

+
    +
  • On a connection error

  • +
  • On server errors: overloaded, isBootstrapping, serverError, etc.

  • +
+

query is the Statement that timed out.

+

consistency is the ConsistencyLevel that the operation was +attempted at.

+

error the instance of the exception.

+

retry_num counts how many times the operation has been retried, so +the first time this method is called, retry_num will be 0.

+

The default, it triggers a retry on the next host in the query plan +with the same consistency level.

+
+ +
+ +
+
+class cassandra.policies.DowngradingConsistencyRetryPolicy(*args, **kwargs)
+

Deprecated: This retry policy will be removed in the next major release.

+

A retry policy that sometimes retries with a lower consistency level than +the one initially requested.

+

BEWARE: This policy may retry queries using a lower consistency +level than the one initially requested. By doing so, it may break +consistency guarantees. In other words, if you use this retry policy, +there are cases (documented below) where a read at QUORUM +may not see a preceding write at QUORUM. Do not use this +policy unless you have understood the cases where this can happen and +are ok with that. It is also recommended to subclass this class so +that queries that required a consistency level downgrade can be +recorded (so that repairs can be made later, etc).

+

This policy implements the same retries as RetryPolicy, +but on top of that, it also retries in the following cases:

+
    +
  • On a read timeout: if the number of replicas that responded is +greater than one but lower than is required by the requested +consistency level, the operation is retried at a lower consistency +level.

  • +
  • On a write timeout: if the operation is an UNLOGGED_BATCH +and at least one replica acknowledged the write, the operation is +retried at a lower consistency level. Furthermore, for other +write types, if at least one replica acknowledged the write, the +timeout is ignored.

  • +
  • On an unavailable exception: if at least one replica is alive, the +operation is retried at a lower consistency level.

  • +
+

The reasoning behind this retry policy is as follows: if, based +on the information the Cassandra coordinator node returns, retrying the +operation with the initially requested consistency has a chance to +succeed, do it. Otherwise, if based on that information we know the +initially requested consistency level cannot be achieved currently, then:

+
    +
  • For writes, ignore the exception (thus silently failing the +consistency requirement) if we know the write has been persisted on at +least one replica.

  • +
  • For reads, try reading at a lower consistency level (thus silently +failing the consistency requirement).

  • +
+

In other words, this policy implements the idea that if the requested +consistency level cannot be achieved, the next best thing for writes is +to make sure the data is persisted, and that reading something is better +than reading nothing, even if there is a risk of reading stale data.

+
+
+on_read_timeout(query, consistency, required_responses, received_responses, data_retrieved, retry_num)
+

This is called when a read operation times out from the coordinator’s +perspective (i.e. a replica did not respond to the coordinator in time). +It should return a tuple with two items: one of the class enums (such +as RETRY) and a ConsistencyLevel to retry the +operation at or None to keep the same consistency level.

+

query is the Statement that timed out.

+

consistency is the ConsistencyLevel that the operation was +attempted at.

+

The required_responses and received_responses parameters describe +how many replicas needed to respond to meet the requested consistency +level and how many actually did respond before the coordinator timed +out the request. data_retrieved is a boolean indicating whether +any of those responses contained data (as opposed to just a digest).

+

retry_num counts how many times the operation has been retried, so +the first time this method is called, retry_num will be 0.

+

By default, operations will be retried at most once, and only if +a sufficient number of replicas responded (with data digests).

+
+ +
+
+on_write_timeout(query, consistency, write_type, required_responses, received_responses, retry_num)
+

This is called when a write operation times out from the coordinator’s +perspective (i.e. a replica did not respond to the coordinator in time).

+

query is the Statement that timed out.

+

consistency is the ConsistencyLevel that the operation was +attempted at.

+

write_type is one of the WriteType enums describing the +type of write operation.

+

The required_responses and received_responses parameters describe +how many replicas needed to acknowledge the write to meet the requested +consistency level and how many replicas actually did acknowledge the +write before the coordinator timed out the request.

+

retry_num counts how many times the operation has been retried, so +the first time this method is called, retry_num will be 0.

+

By default, failed write operations will retried at most once, and +they will only be retried if the write_type was +BATCH_LOG.

+
+ +
+
+on_unavailable(query, consistency, required_replicas, alive_replicas, retry_num)
+

This is called when the coordinator node determines that a read or +write operation cannot be successful because the number of live +replicas are too low to meet the requested ConsistencyLevel. +This means that the read or write operation was never forwarded to +any replicas.

+

query is the Statement that failed.

+

consistency is the ConsistencyLevel that the operation was +attempted at.

+

required_replicas is the number of replicas that would have needed to +acknowledge the operation to meet the requested consistency level. +alive_replicas is the number of replicas that the coordinator +considered alive at the time of the request.

+

retry_num counts how many times the operation has been retried, so +the first time this method is called, retry_num will be 0.

+

By default, if this is the first retry, it triggers a retry on the next +host in the query plan with the same consistency level. If this is not the +first retry, no retries will be attempted and the error will be re-raised.

+
+ +
+ +
+
+

Retrying Idempotent Operations

+
+
+class cassandra.policies.SpeculativeExecutionPolicy
+

Interface for specifying speculative execution plans

+
+
+new_plan(keyspace, statement)
+

Returns

+
+
Parameters
+
    +
  • keyspace

  • +
  • statement

  • +
+
+
Returns
+

+
+
+
+ +
+ +
+
+class cassandra.policies.ConstantSpeculativeExecutionPolicy(delay, max_attempts)
+

A speculative execution policy that sends a new query every X seconds (delay) for a maximum of Y attempts (max_attempts).

+
+
+new_plan(keyspace, statement)
+

Returns

+
+
Parameters
+
    +
  • keyspace

  • +
  • statement

  • +
+
+
Returns
+

+
+
+
+ +
+ +
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.22.3-scylla/api/cassandra/pool.html b/3.22.3-scylla/api/cassandra/pool.html new file mode 100644 index 0000000000..e34e92e102 --- /dev/null +++ b/3.22.3-scylla/api/cassandra/pool.html @@ -0,0 +1,673 @@ + + + + + + + + + + + + + cassandra.pool - Hosts and Connection Pools | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.pool - Hosts and Connection Pools

+

Connection pooling and host management.

+
+
+class cassandra.pool.Host
+

Represents a single Cassandra node.

+
+
+property address
+

The IP address of the endpoint. This is the RPC address the driver uses when connecting to the node.

+
+ +
+
+property datacenter
+

The datacenter the node is in.

+
+ +
+
+property rack
+

The rack the node is in.

+
+ +
+ +
+
+exception cassandra.pool.NoConnectionsAvailable
+

All existing connections to a given host are busy, or there are +no open connections.

+
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.22.3-scylla/api/cassandra/protocol.html b/3.22.3-scylla/api/cassandra/protocol.html new file mode 100644 index 0000000000..f3a4350dc7 --- /dev/null +++ b/3.22.3-scylla/api/cassandra/protocol.html @@ -0,0 +1,739 @@ + + + + + + + + + + + + + cassandra.protocol - Protocol Features | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.protocol - Protocol Features

+
+

Custom Payloads

+

Native protocol version 4+ allows for a custom payload to be sent between clients +and custom query handlers. The payload is specified as a string:binary_type dict +holding custom key/value pairs.

+

By default these are ignored by the server. They can be useful for servers implementing +a custom QueryHandler.

+

See Session.execute(), :Session.execute_async(), ResponseFuture.custom_payload.

+
+
+class cassandra.protocol._ProtocolHandler
+

_ProtocolHander handles encoding and decoding messages.

+

This class can be specialized to compose Handlers which implement alternative +result decoding or type deserialization. Class definitions are passed to cassandra.cluster.Cluster +on initialization.

+

Contracted class methods are _ProtocolHandler.encode_message() and _ProtocolHandler.decode_message().

+
+
+message_types_by_opcode = {default mapping}
+
+ +
+
+classmethod encode_message(msg, stream_id, protocol_version, compressor, allow_beta_protocol_version)
+

Encodes a message using the specified frame parameters, and compressor

+
+
Parameters
+
    +
  • msg – the message, typically of cassandra.protocol._MessageType, generated by the driver

  • +
  • stream_id – protocol stream id for the frame header

  • +
  • protocol_version – version for the frame header, and used encoding contents

  • +
  • compressor – optional compression function to be used on the body

  • +
+
+
+
+ +
+
+classmethod decode_message(protocol_version, user_type_map, stream_id, flags, opcode, body, decompressor, result_metadata)
+

Decodes a native protocol message body

+
+
Parameters
+
    +
  • protocol_version – version to use decoding contents

  • +
  • user_type_map – map[keyspace name] = map[type name] = custom type to instantiate when deserializing this type

  • +
  • stream_id – native protocol stream id from the frame header

  • +
  • flags – native protocol flags bitmap from the header

  • +
  • opcode – native protocol opcode from the header

  • +
  • body – frame body

  • +
  • decompressor – optional decompression function to inflate the body

  • +
+
+
Returns
+

a message decoded from the body and frame attributes

+
+
+
+ +
+ +
+
+

Faster Deserialization

+

When python-driver is compiled with Cython, it uses a Cython-based deserialization path +to deserialize messages. By default, the driver will use a Cython-based parser that returns +lists of rows similar to the pure-Python version. In addition, there are two additional +ProtocolHandler classes that can be used to deserialize response messages: LazyProtocolHandler +and NumpyProtocolHandler. They can be used as follows:

+
from cassandra.protocol import NumpyProtocolHandler, LazyProtocolHandler
+from cassandra.query import tuple_factory
+s.client_protocol_handler = LazyProtocolHandler   # for a result iterator
+s.row_factory = tuple_factory  #required for Numpy results
+s.client_protocol_handler = NumpyProtocolHandler  # for a dict of NumPy arrays as result
+
+
+

These protocol handlers comprise different parsers, and return results as described below:

+
    +
  • ProtocolHandler: this default implementation is a drop-in replacement for the pure-Python version. +The rows are all parsed upfront, before results are returned.

  • +
  • LazyProtocolHandler: near drop-in replacement for the above, except that it returns an iterator over rows, +lazily decoded into the default row format (this is more efficient since all decoded results are not materialized at once)

  • +
  • NumpyProtocolHander: deserializes results directly into NumPy arrays. This facilitates efficient integration with +analysis toolkits such as Pandas.

  • +
+
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.22.3-scylla/api/cassandra/query.html b/3.22.3-scylla/api/cassandra/query.html new file mode 100644 index 0000000000..84a3847665 --- /dev/null +++ b/3.22.3-scylla/api/cassandra/query.html @@ -0,0 +1,1002 @@ + + + + + + + + + + + + + cassandra.query - Prepared Statements, Batch Statements, Tracing, and Row Factories | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.query - Prepared Statements, Batch Statements, Tracing, and Row Factories

+
+
+cassandra.query.tuple_factory(colnames, rows)
+

Returns each row as a tuple

+

Example:

+
>>> from cassandra.query import tuple_factory
+>>> session = cluster.connect('mykeyspace')
+>>> session.row_factory = tuple_factory
+>>> rows = session.execute("SELECT name, age FROM users LIMIT 1")
+>>> print rows[0]
+('Bob', 42)
+
+
+
+

Changed in version 2.0.0: moved from cassandra.decoder to cassandra.query

+
+
+ +
+
+cassandra.query.named_tuple_factory(colnames, rows)
+

Returns each row as a namedtuple. +This is the default row factory.

+

Example:

+
>>> from cassandra.query import named_tuple_factory
+>>> session = cluster.connect('mykeyspace')
+>>> session.row_factory = named_tuple_factory
+>>> rows = session.execute("SELECT name, age FROM users LIMIT 1")
+>>> user = rows[0]
+
+>>> # you can access field by their name:
+>>> print "name: %s, age: %d" % (user.name, user.age)
+name: Bob, age: 42
+
+>>> # or you can access fields by their position (like a tuple)
+>>> name, age = user
+>>> print "name: %s, age: %d" % (name, age)
+name: Bob, age: 42
+>>> name = user[0]
+>>> age = user[1]
+>>> print "name: %s, age: %d" % (name, age)
+name: Bob, age: 42
+
+
+
+

Changed in version 2.0.0: moved from cassandra.decoder to cassandra.query

+
+
+ +
+
+cassandra.query.dict_factory(colnames, rows)
+

Returns each row as a dict.

+

Example:

+
>>> from cassandra.query import dict_factory
+>>> session = cluster.connect('mykeyspace')
+>>> session.row_factory = dict_factory
+>>> rows = session.execute("SELECT name, age FROM users LIMIT 1")
+>>> print rows[0]
+{u'age': 42, u'name': u'Bob'}
+
+
+
+

Changed in version 2.0.0: moved from cassandra.decoder to cassandra.query

+
+
+ +
+
+cassandra.query.ordered_dict_factory(colnames, rows)
+

Like dict_factory(), but returns each row as an OrderedDict, +so the order of the columns is preserved.

+
+

Changed in version 2.0.0: moved from cassandra.decoder to cassandra.query

+
+
+ +
+
+class cassandra.query.SimpleStatement(query_string, retry_policy=None, consistency_level=None, routing_key=None, serial_consistency_level=None, fetch_size=<object object>, keyspace=None, custom_payload=None, is_idempotent=False)
+

A simple, un-prepared query.

+

query_string should be a literal CQL statement with the exception +of parameter placeholders that will be filled through the +parameters argument of Session.execute().

+

See Statement attributes for a description of the other parameters.

+
+ +
+
+class cassandra.query.PreparedStatement
+

A statement that has been prepared against at least one Cassandra node. +Instances of this class should not be created directly, but through +Session.prepare().

+

A PreparedStatement should be prepared only once. Re-preparing a statement +may affect performance (as the operation requires a network roundtrip).

+

A note about * in prepared statements: Do not use * in prepared statements if you might +change the schema of the table being queried. The driver and server each +maintain a map between metadata for a schema and statements that were +prepared against that schema. When a user changes a schema, e.g. by adding +or removing a column, the server invalidates its mappings involving that +schema. However, there is currently no way to propagate that invalidation +to drivers. Thus, after a schema change, the driver will incorrectly +interpret the results of SELECT * queries prepared before the schema +change. This is currently being addressed in CASSANDRA-10786.

+
+
+bind(values)
+

Creates and returns a BoundStatement instance using values.

+

See BoundStatement.bind() for rules on input values.

+
+ +
+ +
+
+class cassandra.query.BoundStatement(prepared_statement, retry_policy=None, consistency_level=None, routing_key=None, serial_consistency_level=None, fetch_size=<object object>, keyspace=None, custom_payload=None)
+

A prepared statement that has been bound to a particular set of values. +These may be created directly or through PreparedStatement.bind().

+

prepared_statement should be an instance of PreparedStatement.

+

See Statement attributes for a description of the other parameters.

+
+
+bind(values)
+

Binds a sequence of values for the prepared statement parameters +and returns this instance. Note that values must be:

+
    +
  • a sequence, even if you are only binding one value, or

  • +
  • a dict that relates 1-to-1 between dict keys and columns

  • +
+
+

Changed in version 2.6.0: UNSET_VALUE was introduced. These can be bound as positional parameters +in a sequence, or by name in a dict. Additionally, when using protocol v4+:

+
    +
  • short sequences will be extended to match bind parameters with UNSET_VALUE

  • +
  • names may be omitted from a dict with UNSET_VALUE implied.

  • +
+
+
+

Changed in version 3.0.0: method will not throw if extra keys are present in bound dict (PYTHON-178)

+
+
+ +
+
+property routing_key
+

The partition_key portion of the primary key, +which can be used to determine which nodes are replicas for the query.

+

If the partition key is a composite, a list or tuple must be passed in. +Each key component should be in its packed (binary) format, so all +components should be strings.

+
+ +
+ +
+
+class cassandra.query.Statement
+

An abstract class representing a single query. There are three subclasses: +SimpleStatement, BoundStatement, and BatchStatement. +These can be passed to Session.execute().

+
+
+property routing_key
+

The partition_key portion of the primary key, +which can be used to determine which nodes are replicas for the query.

+

If the partition key is a composite, a list or tuple must be passed in. +Each key component should be in its packed (binary) format, so all +components should be strings.

+
+ +
+
+property serial_consistency_level
+

The serial consistency level is only used by conditional updates +(INSERT, UPDATE and DELETE with an IF condition). For +those, the serial_consistency_level defines the consistency level of +the serial phase (or “paxos” phase) while the normal +consistency_level defines the consistency for the “learn” phase, +i.e. what type of reads will be guaranteed to see the update right away. +For example, if a conditional write has a consistency_level of +QUORUM (and is successful), then a +QUORUM read is guaranteed to see that write. +But if the regular consistency_level of that write is +ANY, then only a read with a +consistency_level of SERIAL is +guaranteed to see it (even a read with consistency +ALL is not guaranteed to be enough).

+

The serial consistency can only be one of SERIAL +or LOCAL_SERIAL. While SERIAL guarantees full +linearizability (with other SERIAL updates), LOCAL_SERIAL only +guarantees it in the local data center.

+

The serial consistency level is ignored for any query that is not a +conditional update. Serial reads should use the regular +consistency_level.

+

Serial consistency levels may only be used against Cassandra 2.0+ +and the protocol_version must be set to 2 or higher.

+

See Lightweight Transactions (Compare-and-set) for a discussion on how to work with results returned from +conditional statements.

+
+

New in version 2.0.0.

+
+
+ +
+ +
+
+cassandra.query.UNSET_VALUE
+

The most base type

+
+ +
+
+class cassandra.query.BatchStatement(batch_type=BatchType.LOGGED, retry_policy=None, consistency_level=None)
+

A protocol-level batch of operations which are applied atomically +by default.

+
+

New in version 2.0.0.

+
+

batch_type specifies The BatchType for the batch operation. +Defaults to BatchType.LOGGED.

+

retry_policy should be a RetryPolicy instance for +controlling retries on the operation.

+

consistency_level should be a ConsistencyLevel value +to be used for all operations in the batch.

+

custom_payload is a Custom Payloads passed to the server. +Note: as Statement objects are added to the batch, this map is +updated with any values found in their custom payloads. These are +only allowed when using protocol version 4 or higher.

+

Example usage:

+
insert_user = session.prepare("INSERT INTO users (name, age) VALUES (?, ?)")
+batch = BatchStatement(consistency_level=ConsistencyLevel.QUORUM)
+
+for (name, age) in users_to_insert:
+    batch.add(insert_user, (name, age))
+
+session.execute(batch)
+
+
+

You can also mix different types of operations within a batch:

+
batch = BatchStatement()
+batch.add(SimpleStatement("INSERT INTO users (name, age) VALUES (%s, %s)"), (name, age))
+batch.add(SimpleStatement("DELETE FROM pending_users WHERE name=%s"), (name,))
+session.execute(batch)
+
+
+
+

New in version 2.0.0.

+
+
+

Changed in version 2.1.0: Added serial_consistency_level as a parameter

+
+
+

Changed in version 2.6.0: Added custom_payload as a parameter

+
+
+
+add(statement, parameters=None)
+

Adds a Statement and optional sequence of parameters +to be used with the statement to the batch.

+

Like with other statements, parameters must be a sequence, even +if there is only one item.

+
+ +
+
+add_all(statements, parameters)
+

Adds a sequence of Statement objects and a matching sequence +of parameters to the batch. Statement and parameter sequences must be of equal length or +one will be truncated. None can be used in the parameters position where are needed.

+
+ +
+
+clear()
+

This is a convenience method to clear a batch statement for reuse.

+

Note: it should not be used concurrently with uncompleted execution futures executing the same +BatchStatement.

+
+ +
+
+serial_consistency_level = None
+
+ +
+ +
+
+class cassandra.query.BatchType
+

A BatchType is used with BatchStatement instances to control +the atomicity of the batch operation.

+
+

New in version 2.0.0.

+
+
+
+LOGGED = BatchType.LOGGED
+
+ +
+
+UNLOGGED = BatchType.UNLOGGED
+
+ +
+
+COUNTER = BatchType.COUNTER
+
+ +
+ +
+
+class cassandra.query.ValueSequence(iterable=(), /)
+

A wrapper class that is used to specify that a sequence of values should +be treated as a CQL list of values instead of a single column collection when used +as part of the parameters argument for Session.execute().

+

This is typically needed when supplying a list of keys to select. +For example:

+
>>> my_user_ids = ('alice', 'bob', 'charles')
+>>> query = "SELECT * FROM users WHERE user_id IN %s"
+>>> session.execute(query, parameters=[ValueSequence(my_user_ids)])
+
+
+
+ +
+
+class cassandra.query.QueryTrace
+

A trace of the duration and events that occurred when executing +an operation.

+
+
+populate(max_wait=2.0, wait_for_complete=True, query_cl=None)
+

Retrieves the actual tracing details from Cassandra and populates the +attributes of this instance. Because tracing details are stored +asynchronously by Cassandra, this may need to retry the session +detail fetch. If the trace is still not available after max_wait +seconds, TraceUnavailable will be raised; if max_wait is +None, this will retry forever.

+

wait_for_complete=False bypasses the wait for duration to be populated. +This can be used to query events from partial sessions.

+

query_cl specifies a consistency level to use for polling the trace tables, +if it should be different than the session default.

+
+ +
+ +
+
+class cassandra.query.TraceEvent
+

Representation of a single event within a query trace.

+
+ +
+
+exception cassandra.query.TraceUnavailable
+

Raised when complete trace details cannot be fetched from Cassandra.

+
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.22.3-scylla/api/cassandra/timestamps.html b/3.22.3-scylla/api/cassandra/timestamps.html new file mode 100644 index 0000000000..5e87f786ca --- /dev/null +++ b/3.22.3-scylla/api/cassandra/timestamps.html @@ -0,0 +1,695 @@ + + + + + + + + + + + + + cassandra.timestamps - Timestamp Generation | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.timestamps - Timestamp Generation

+
+
+class cassandra.timestamps.MonotonicTimestampGenerator(warn_on_drift=True, warning_threshold=0, warning_interval=0)
+

An object that, when called, returns int(time.time() * 1e6) when +possible, but, if the value returned by time.time doesn’t increase, +drifts into the future and logs warnings. +Exposed configuration attributes can be configured with arguments to +__init__ or by changing attributes on an initialized object.

+
+

New in version 3.8.0.

+
+
+
+warn_on_drift = True
+

If true, log warnings when timestamps drift into the future as allowed by +warning_threshold and warning_interval.

+
+ +
+
+warning_threshold = 1
+

This object will only issue warnings when the returned timestamp drifts +more than warning_threshold seconds into the future. +Defaults to 1 second.

+
+ +
+
+warning_interval = 1
+

This object will only issue warnings every warning_interval seconds. +Defaults to 1 second.

+
+ +
+
+_next_timestamp(now, last)
+

Returns the timestamp that should be used if now is the current +time and last is the last timestamp returned by this object. +Intended for internal and testing use only; to generate timestamps, +call an instantiated MonotonicTimestampGenerator object.

+
+
Parameters
+
    +
  • now (int) – an integer to be used as the current time, typically +representing the current time in microseconds since the UNIX epoch

  • +
  • last (int) – an integer representing the last timestamp returned by +this object

  • +
+
+
+
+ +
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.22.3-scylla/api/cassandra/util.html b/3.22.3-scylla/api/cassandra/util.html new file mode 100644 index 0000000000..fdeed591cc --- /dev/null +++ b/3.22.3-scylla/api/cassandra/util.html @@ -0,0 +1,1030 @@ + + + + + + + + + + + + + cassandra.util - Utilities | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.util - Utilities

+
+
+class cassandra.util.Date(value)
+

Idealized date: year, month, day

+

Offers wider year range than datetime.date. For Dates that cannot be represented +as a datetime.date (because datetime.MINYEAR, datetime.MAXYEAR), this type falls back +to printing days_from_epoch offset.

+

Initializer value can be:

+
    +
  • integer_type: absolute days from epoch (1970, 1, 1). Can be negative.

  • +
  • datetime.date: built-in date

  • +
  • string_type: a string time of the form “yyyy-mm-dd”

  • +
+
+
+date()
+

Return a built-in datetime.date for Dates falling in the years [datetime.MINYEAR, datetime.MAXYEAR]

+

ValueError is raised for Dates outside this range.

+
+ +
+
+property seconds
+

Absolute seconds from epoch (can be negative)

+
+ +
+ +
+
+class cassandra.util.DateRange(lower_bound=None, upper_bound=None, value=None)
+

DSE DateRange Type

+
+
+lower_bound
+

DateRangeBound representing the lower bound of a bounded range.

+
+ +
+
+upper_bound
+

DateRangeBound representing the upper bound of a bounded range.

+
+ +
+
+value
+

DateRangeBound representing the value of a single-value range.

+
+ +

As noted in its documentation, DateRangeBound uses a millisecond +offset from the UNIX epoch to allow DateRange to represent values +datetime.datetime cannot. For such values, string representions will show +this offset rather than the CQL representation.

+
+
Parameters
+
+
+
+
+ +
+
+class cassandra.util.DateRangeBound(value, precision)
+

Represents a single date value and its precision for DateRange.

+
+
+milliseconds
+

Integer representing milliseconds since the UNIX epoch. May be negative.

+
+ +
+
+precision
+

String representing the precision of a bound. Must be a valid +DateRangePrecision member.

+
+ +

DateRangeBound uses a millisecond offset from the UNIX epoch to +allow DateRange to represent values datetime.datetime cannot. +For such values, string representions will show this offset rather than the +CQL representation.

+
+
Parameters
+
    +
  • value – a value representing ms since the epoch. Accepts an +integer or a datetime.

  • +
  • precision – a string representing precision

  • +
+
+
+
+
+datetime()
+

Return milliseconds as a datetime.datetime if possible. +Raises an OverflowError if the value is out of range.

+
+ +
+
+classmethod from_value(value)
+

Construct a new DateRangeBound from a given value. If +possible, use the value[‘milliseconds’] and value[‘precision’] keys +of the argument. Otherwise, use the argument as a (milliseconds, +precision) iterable.

+
+
Parameters
+

value – a dictlike or iterable object

+
+
+
+ +
+ +
+
+class cassandra.util.DateRangePrecision
+

An “enum” representing the valid values for DateRange.precision.

+
+ +
+
+class cassandra.util.Distance(x=nan, y=nan, radius=nan)
+

Represents a Distance geometry for DSE

+
+
+static from_wkt(s)
+

Parse a Distance geometry from a wkt string and return a new Distance object.

+
+ +
+ +
+
+class cassandra.util.Duration(months=0, days=0, nanoseconds=0)
+

Cassandra Duration Type

+
+ +
+
+class cassandra.util.LineString(coords=())
+

Represents a linestring geometry for DSE

+

‘coords`: a sequence of (x, y) coordinates of points in the linestring

+
+
+static from_wkt(s)
+

Parse a LineString geometry from a wkt string and return a new LineString object.

+
+ +
+ +
+
+class cassandra.util.OrderedMap(*args, **kwargs)
+

An ordered map that accepts non-hashable types for keys. It also maintains the +insertion order of items, behaving as OrderedDict in that regard. These maps +are constructed and read just as normal mapping types, except that they may +contain arbitrary collections and other non-hashable items as keys:

+
>>> od = OrderedMap([({'one': 1, 'two': 2}, 'value'),
+...                  ({'three': 3, 'four': 4}, 'value2')])
+>>> list(od.keys())
+[{'two': 2, 'one': 1}, {'three': 3, 'four': 4}]
+>>> list(od.values())
+['value', 'value2']
+
+
+

These constructs are needed to support nested collections in Cassandra 2.1.3+, +where frozen collections can be specified as parameters to others:

+
CREATE TABLE example (
+    ...
+    value map<frozen<map<int, int>>, double>
+    ...
+)
+
+
+

This class derives from the (immutable) Mapping API. Objects in these maps +are not intended be modified.

+
+ +
+
+class cassandra.util.OrderedMapSerializedKey(cass_type, protocol_version)
+
+ +
+
+class cassandra.util.Point(x=nan, y=nan)
+

Represents a point geometry for DSE

+
+
+static from_wkt(s)
+

Parse a Point geometry from a wkt string and return a new Point object.

+
+ +
+ +
+
+class cassandra.util.Polygon(exterior=(), interiors=None)
+

Represents a polygon geometry for DSE

+

‘exterior`: a sequence of (x, y) coordinates of points in the linestring +interiors: None, or a sequence of sequences or (x, y) coordinates of points describing interior linear rings

+
+
+static from_wkt(s)
+

Parse a Polygon geometry from a wkt string and return a new Polygon object.

+
+ +
+ +
+
+class cassandra.util.SortedSet(iterable=())
+

A sorted set based on sorted list

+

A sorted set implementation is used in this case because it does not +require its elements to be immutable/hashable.

+

#Not implemented: update functions, inplace operators

+
+ +
+
+class cassandra.util.Time(value)
+

Idealized time, independent of day.

+

Up to nanosecond resolution

+

Initializer value can be:

+
    +
  • integer_type: absolute nanoseconds in the day

  • +
  • datetime.time: built-in time

  • +
  • string_type: a string time of the form “HH:MM:SS[.mmmuuunnn]”

  • +
+
+
+property hour
+

The hour component of this time (0-23)

+
+ +
+
+property minute
+

The minute component of this time (0-59)

+
+ +
+
+property nanosecond
+

The fractional seconds component of the time, in nanoseconds

+
+ +
+
+property second
+

The second component of this time (0-59)

+
+ +
+
+time()
+

Return a built-in datetime.time (nanosecond precision truncated to micros).

+
+ +
+ +
+
+class cassandra.util.Version(version)
+

Internal minimalist class to compare versions. +A valid version is: <int>.<int>.<int>.<int or str>.

+

TODO: when python2 support is removed, use packaging.version.

+
+ +
+
+cassandra.util.datetime_from_timestamp(timestamp)
+

Creates a timezone-agnostic datetime from timestamp (in seconds) in a consistent manner. +Works around a Windows issue with large negative timestamps (PYTHON-119), +and rounding differences in Python 3.4 (PYTHON-340).

+
+
Parameters
+

timestamp – a unix timestamp, in seconds

+
+
+
+ +
+
+cassandra.util.datetime_from_uuid1(uuid_arg)
+

Creates a timezone-agnostic datetime from the timestamp in the +specified type-1 UUID.

+
+
Parameters
+

uuid_arg – a version 1 UUID

+
+
+
+ +
+
+cassandra.util.max_uuid_from_time(timestamp)
+

Generates the maximum TimeUUID (type 1) for a given timestamp, as compared by Cassandra.

+

See uuid_from_time() for argument and return types.

+
+ +
+
+cassandra.util.min_uuid_from_time(timestamp)
+

Generates the minimum TimeUUID (type 1) for a given timestamp, as compared by Cassandra.

+

See uuid_from_time() for argument and return types.

+
+ +
+
+cassandra.util.ms_timestamp_from_datetime(dt)
+

Converts a datetime to a timestamp expressed in milliseconds.

+
+
Parameters
+

dt – a datetime.datetime

+
+
+
+ +
+
+cassandra.util.sortedset
+

alias of cassandra.util.SortedSet

+
+ +
+
+cassandra.util.unix_time_from_uuid1(uuid_arg)
+

Converts a version 1 uuid.UUID to a timestamp with the same precision +as time.time() returns. This is useful for examining the +results of queries returning a v1 UUID.

+
+
Parameters
+

uuid_arg – a version 1 UUID

+
+
+
+ +
+
+cassandra.util.utc_datetime_from_ms_timestamp(timestamp)
+

Creates a UTC datetime from a timestamp in milliseconds. See +datetime_from_timestamp().

+

Raises an OverflowError if the timestamp is out of range for +datetime.

+
+
Parameters
+

timestamp – timestamp, in milliseconds

+
+
+
+ +
+
+cassandra.util.uuid_from_time(time_arg, node=None, clock_seq=None)
+

Converts a datetime or timestamp to a type 1 uuid.UUID.

+
+
Parameters
+
    +
  • time_arg – The time to use for the timestamp portion of the UUID. +This can either be a datetime object or a timestamp +in seconds (as returned from time.time()).

  • +
  • node (long) – None integer for the UUID (up to 48 bits). If not specified, this +field is randomized.

  • +
  • clock_seq (int) – Clock sequence field for the UUID (up to 14 bits). If not specified, +a random sequence is generated.

  • +
+
+
Return type
+

uuid.UUID

+
+
+
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.22.3-scylla/api/index.html b/3.22.3-scylla/api/index.html new file mode 100644 index 0000000000..6e4e876eed --- /dev/null +++ b/3.22.3-scylla/api/index.html @@ -0,0 +1,716 @@ + + + + + + + + + + + + + API Documentation | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

API Documentation

+
+

Core Driver

+ +
+
+

Object Mapper

+ +
+
+

DataStax Graph

+ +
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.22.3-scylla/cqlengine/batches.html b/3.22.3-scylla/cqlengine/batches.html new file mode 100644 index 0000000000..06209867a7 --- /dev/null +++ b/3.22.3-scylla/cqlengine/batches.html @@ -0,0 +1,746 @@ + + + + + + + + + + + + + Batch Queries | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + + + +
+

Batch Queries

+

cqlengine supports batch queries using the BatchQuery class. Batch queries can be started and stopped manually, or within a context manager. To add queries to the batch object, you just need to precede the create/save/delete call with a call to batch, and pass in the batch object.

+
+

Batch Query General Use Pattern

+

You can only create, update, and delete rows with a batch query, attempting to read rows out of the database with a batch query will fail.

+
from cassandra.cqlengine.query import BatchQuery
+
+#using a context manager
+with BatchQuery() as b:
+    now = datetime.now()
+    em1 = ExampleModel.batch(b).create(example_type=0, description="1", created_at=now)
+    em2 = ExampleModel.batch(b).create(example_type=0, description="2", created_at=now)
+    em3 = ExampleModel.batch(b).create(example_type=0, description="3", created_at=now)
+
+# -- or --
+
+#manually
+b = BatchQuery()
+now = datetime.now()
+em1 = ExampleModel.batch(b).create(example_type=0, description="1", created_at=now)
+em2 = ExampleModel.batch(b).create(example_type=0, description="2", created_at=now)
+em3 = ExampleModel.batch(b).create(example_type=0, description="3", created_at=now)
+b.execute()
+
+# updating in a batch
+
+b = BatchQuery()
+em1.description = "new description"
+em1.batch(b).save()
+em2.description = "another new description"
+em2.batch(b).save()
+b.execute()
+
+# deleting in a batch
+b = BatchQuery()
+ExampleModel.objects(id=some_id).batch(b).delete()
+ExampleModel.objects(id=some_id2).batch(b).delete()
+b.execute()
+
+
+

Typically you will not want the block to execute if an exception occurs inside the with block. However, in the case that this is desirable, it’s achievable by using the following syntax:

+
with BatchQuery(execute_on_exception=True) as b:
+    LogEntry.batch(b).create(k=1, v=1)
+    mystery_function() # exception thrown in here
+    LogEntry.batch(b).create(k=1, v=2) # this code is never reached due to the exception, but anything leading up to here will execute in the batch.
+
+
+

If an exception is thrown somewhere in the block, any statements that have been added to the batch will still be executed. This is useful for some logging situations.

+
+
+

Batch Query Execution Callbacks

+

In order to allow secondary tasks to be chained to the end of batch, BatchQuery instances allow callbacks to be +registered with the batch, to be executed immediately after the batch executes.

+

Multiple callbacks can be attached to same BatchQuery instance, they are executed in the same order that they +are added to the batch.

+

The callbacks attached to a given batch instance are executed only if the batch executes. If the batch is used as a +context manager and an exception is raised, the queued up callbacks will not be run.

+
def my_callback(*args, **kwargs):
+    pass
+
+batch = BatchQuery()
+
+batch.add_callback(my_callback)
+batch.add_callback(my_callback, 'positional arg', named_arg='named arg value')
+
+# if you need reference to the batch within the callback,
+# just trap it in the arguments to be passed to the callback:
+batch.add_callback(my_callback, cqlengine_batch=batch)
+
+# once the batch executes...
+batch.execute()
+
+# the effect of the above scheduled callbacks will be similar to
+my_callback()
+my_callback('positional arg', named_arg='named arg value')
+my_callback(cqlengine_batch=batch)
+
+
+

Failure in any of the callbacks does not affect the batch’s execution, as the callbacks are started after the execution +of the batch is complete.

+
+

Logged vs Unlogged Batches

+

By default, queries in cqlengine are LOGGED, which carries additional overhead from UNLOGGED. To explicitly state which batch type to use, simply:

+
from cassandra.cqlengine.query import BatchType
+with BatchQuery(batch_type=BatchType.Unlogged) as b:
+    LogEntry.batch(b).create(k=1, v=1)
+    LogEntry.batch(b).create(k=1, v=2)
+
+
+
+
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.22.3-scylla/cqlengine/connections.html b/3.22.3-scylla/cqlengine/connections.html new file mode 100644 index 0000000000..53e1e40351 --- /dev/null +++ b/3.22.3-scylla/cqlengine/connections.html @@ -0,0 +1,770 @@ + + + + + + + + + + + + + Connections | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + + + +
+

Connections

+

Connections aim to ease the use of multiple sessions with cqlengine. Connections can be set on a model class, per query or using a context manager.

+
+

Register a new connection

+

To use cqlengine, you need at least a default connection. If you initialize cqlengine’s connections with with connection.setup, a connection will be created automatically. If you want to use another cluster/session, you need to register a new cqlengine connection. You register a connection with register_connection():

+
from cassandra.cqlengine import connection
+
+connection.setup(['127.0.0.1')
+connection.register_connection('cluster2', ['127.0.0.2'])
+
+
+

register_connection() can take a list of hosts, as shown above, in which case it will create a connection with a new session. It can also take a session argument if you’ve already created a session:

+
from cassandra.cqlengine import connection
+from cassandra.cluster import Cluster
+
+session = Cluster(['127.0.0.1']).connect()
+connection.register_connection('cluster3', session=session)
+
+
+
+
+

Change the default connection

+

You can change the default cqlengine connection on registration:

+
from cassandra.cqlengine import connection
+
+connection.register_connection('cluster2', ['127.0.0.2'] default=True)
+
+
+

or on the fly using set_default_connection()

+
connection.set_default_connection('cluster2')
+
+
+
+
+

Unregister a connection

+

You can unregister a connection using unregister_connection():

+
connection.unregister_connection('cluster2')
+
+
+
+
+

Management

+

When using multiples connections, you also need to sync your models on all connections (and keyspaces) that you need operate on. Management commands have been improved to ease this part. Here is an example:

+
from cassandra.cqlengine import management
+
+keyspaces = ['ks1', 'ks2']
+conns = ['cluster1', 'cluster2']
+
+# registers your connections
+# ...
+
+# create all keyspaces on all connections
+for ks in keyspaces:
+    management.create_simple_keyspace(ks, connections=conns)
+
+# define your Automobile model
+# ...
+
+# sync your models
+management.sync_table(Automobile, keyspaces=keyspaces, connections=conns)
+
+
+
+
+

Connection Selection

+

cqlengine will select the default connection, unless your specify a connection using one of the following methods.

+
+

Default Model Connection

+

You can specify a default connection per model:

+
class Automobile(Model):
+    __keyspace__ = 'test'
+    __connection__ = 'cluster2'
+    manufacturer = columns.Text(primary_key=True)
+    year = columns.Integer(primary_key=True)
+    model = columns.Text(primary_key=True)
+
+print len(Automobile.objects.all())  # executed on the connection 'cluster2'
+
+
+
+
+

QuerySet and model instance

+

You can use the using() method to select a connection (or keyspace):

+
Automobile.objects.using(connection='cluster1').create(manufacturer='honda', year=2010, model='civic')
+q = Automobile.objects.filter(manufacturer='Tesla')
+autos = q.using(keyspace='ks2', connection='cluster2').all()
+
+for auto in autos:
+    auto.using(connection='cluster1').save()
+
+
+
+
+

Context Manager

+

You can use the ContextQuery as well to select a connection:

+
with ContextQuery(Automobile, connection='cluster1') as A:
+    A.objects.filter(manufacturer='honda').all()  # executed on 'cluster1'
+
+
+
+
+

BatchQuery

+

With a BatchQuery, you can select the connection with the context manager. Note that all operations in the batch need to use the same connection.

+
with BatchQuery(connection='cluster1') as b:
+    Automobile.objects.batch(b).create(manufacturer='honda', year=2010, model='civic')
+
+
+
+
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.22.3-scylla/cqlengine/faq.html b/3.22.3-scylla/cqlengine/faq.html new file mode 100644 index 0000000000..f1740b567f --- /dev/null +++ b/3.22.3-scylla/cqlengine/faq.html @@ -0,0 +1,710 @@ + + + + + + + + + + + + + Frequently Asked Questions | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

Frequently Asked Questions

+
+

Why don’t updates work correctly on models instantiated as Model(field=value, field2=value2)?

+

The recommended way to create new rows is with the models .create method. The values passed into a model’s init method are interpreted by the model as the values as they were read from a row. This allows the model to “know” which rows have changed since the row was read out of cassandra, and create suitable update statements.

+
+
+

How to preserve ordering in batch query?

+

Statement Ordering is not supported by CQL3 batches. Therefore, +once cassandra needs resolving conflict(Updating the same column in one batch), +The algorithm below would be used.

+
    +
  • If timestamps are different, pick the column with the largest timestamp (the value being a regular column or a tombstone)

  • +
  • If timestamps are the same, and one of the columns in a tombstone (‘null’) - pick the tombstone

  • +
  • If timestamps are the same, and none of the columns are tombstones, pick the column with the largest value

  • +
+

Below is an example to show this scenario.

+
class MyMode(Model):
+    id    = columns.Integer(primary_key=True)
+    count = columns.Integer()
+    text  = columns.Text()
+
+with BatchQuery() as b:
+   MyModel.batch(b).create(id=1, count=2, text='123')
+   MyModel.batch(b).create(id=1, count=3, text='111')
+
+assert MyModel.objects(id=1).first().count == 3
+assert MyModel.objects(id=1).first().text  == '123'
+
+
+

The largest value of count is 3, and the largest value of text would be ‘123’.

+

The workaround is applying timestamp to each statement, then Cassandra would +resolve to the statement with the lastest timestamp.

+
with BatchQuery() as b:
+    MyModel.timestamp(datetime.now()).batch(b).create(id=1, count=2, text='123')
+    MyModel.timestamp(datetime.now()).batch(b).create(id=1, count=3, text='111')
+
+assert MyModel.objects(id=1).first().count == 3
+assert MyModel.objects(id=1).first().text  == '111'
+
+
+
+
+

How can I delete individual values from a row?

+

When inserting with CQLEngine, None is equivalent to CQL NULL or to +issuing a DELETE on that column. For example:

+
class MyModel(Model):
+    id    = columns.Integer(primary_key=True)
+    text  = columns.Text()
+
+m = MyModel.create(id=1, text='We can delete this with None')
+assert MyModel.objects(id=1).first().text is not None
+
+m.update(text=None)
+assert MyModel.objects(id=1).first().text is None
+
+
+
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.22.3-scylla/cqlengine/models.html b/3.22.3-scylla/cqlengine/models.html new file mode 100644 index 0000000000..266886aa95 --- /dev/null +++ b/3.22.3-scylla/cqlengine/models.html @@ -0,0 +1,835 @@ + + + + + + + + + + + + + Models | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + + + +
+

Models

+

A model is a python class representing a CQL table. Models derive from Model, and +define basic table properties and columns for a table.

+

Columns in your models map to columns in your CQL table. You define CQL columns by defining column attributes on your model classes. +For a model to be valid it needs at least one primary key column and one non-primary key column. Just as in CQL, the order you define +your columns in is important, and is the same order they are defined in on a model’s corresponding table.

+

Some basic examples defining models are shown below. Consult the Model API docs and Column API docs for complete details.

+
+

Example Definitions

+

This example defines a Person table, with the columns first_name and last_name

+
from cassandra.cqlengine import columns
+from cassandra.cqlengine.models import Model
+
+ class Person(Model):
+     id = columns.UUID(primary_key=True)
+     first_name  = columns.Text()
+     last_name = columns.Text()
+
+
+

The Person model would create this CQL table:

+
CREATE TABLE cqlengine.person (
+    id uuid,
+    first_name text,
+    last_name text,
+    PRIMARY KEY (id)
+);
+
+
+

Here’s an example of a comment table created with clustering keys, in descending order:

+
from cassandra.cqlengine import columns
+from cassandra.cqlengine.models import Model
+
+class Comment(Model):
+    photo_id = columns.UUID(primary_key=True)
+    comment_id = columns.TimeUUID(primary_key=True, clustering_order="DESC")
+    comment = columns.Text()
+
+
+

The Comment model’s create table would look like the following:

+
CREATE TABLE comment (
+  photo_id uuid,
+  comment_id timeuuid,
+  comment text,
+  PRIMARY KEY (photo_id, comment_id)
+) WITH CLUSTERING ORDER BY (comment_id DESC);
+
+
+

To sync the models to the database, you may do the following*:

+
from cassandra.cqlengine.management import sync_table
+sync_table(Person)
+sync_table(Comment)
+
+
+

*Note: synchronizing models causes schema changes, and should be done with caution. +Please see the discussion in cassandra.cqlengine.management - Schema management for cqlengine for considerations.

+

For examples on manipulating data and creating queries, see Making Queries

+
+
+

Manipulating model instances as dictionaries

+

Model instances can be accessed like dictionaries.

+
class Person(Model):
+    first_name  = columns.Text()
+    last_name = columns.Text()
+
+kevin = Person.create(first_name="Kevin", last_name="Deldycke")
+dict(kevin)  # returns {'first_name': 'Kevin', 'last_name': 'Deldycke'}
+kevin['first_name']  # returns 'Kevin'
+kevin.keys()  # returns ['first_name', 'last_name']
+kevin.values()  # returns ['Kevin', 'Deldycke']
+kevin.items()  # returns [('first_name', 'Kevin'), ('last_name', 'Deldycke')]
+
+kevin['first_name'] = 'KEVIN5000'  # changes the models first name
+
+
+
+
+

Extending Model Validation

+

Each time you save a model instance in cqlengine, the data in the model is validated against the schema you’ve defined +for your model. Most of the validation is fairly straightforward, it basically checks that you’re not trying to do +something like save text into an integer column, and it enforces the required flag set on column definitions. +It also performs any transformations needed to save the data properly.

+

However, there are often additional constraints or transformations you want to impose on your data, beyond simply +making sure that Cassandra won’t complain when you try to insert it. To define additional validation on a model, +extend the model’s validation method:

+
class Member(Model):
+    person_id = UUID(primary_key=True)
+    name = Text(required=True)
+
+    def validate(self):
+        super(Member, self).validate()
+        if self.name == 'jon':
+            raise ValidationError('no jon\'s allowed')
+
+
+

Note: while not required, the convention is to raise a ValidationError (from cassandra.cqlengine import ValidationError) +if validation fails.

+
+
+

Model Inheritance

+

It is possible to save and load different model classes using a single CQL table. +This is useful in situations where you have different object types that you want to store in a single cassandra row.

+

For instance, suppose you want a table that stores rows of pets owned by an owner:

+
class Pet(Model):
+    __table_name__ = 'pet'
+    owner_id = UUID(primary_key=True)
+    pet_id = UUID(primary_key=True)
+    pet_type = Text(discriminator_column=True)
+    name = Text()
+
+    def eat(self, food):
+        pass
+
+    def sleep(self, time):
+        pass
+
+class Cat(Pet):
+    __discriminator_value__ = 'cat'
+    cuteness = Float()
+
+    def tear_up_couch(self):
+        pass
+
+class Dog(Pet):
+    __discriminator_value__ = 'dog'
+    fierceness = Float()
+
+    def bark_all_night(self):
+        pass
+
+
+

After calling sync_table on each of these tables, the columns defined in each model will be added to the +pet table. Additionally, saving Cat and Dog models will save the meta data needed to identify each row +as either a cat or dog.

+

To setup a model structure with inheritance, follow these steps

+
    +
  1. Create a base model with a column set as the distriminator (distriminator_column=True in the column definition)

  2. +
  3. Create subclass models, and define a unique __discriminator_value__ value on each

  4. +
  5. Run sync_table on each of the sub tables

  6. +
+

About the discriminator value

+

The discriminator value is what cqlengine uses under the covers to map logical cql rows to the appropriate model type. The +base model maintains a map of discriminator values to subclasses. When a specialized model is saved, its discriminator value is +automatically saved into the discriminator column. The discriminator column may be any column type except counter and container types. +Additionally, if you set index=True on your discriminator column, you can execute queries against specialized subclasses, and a +WHERE clause will be automatically added to your query, returning only rows of that type. Note that you must +define a unique __discriminator_value__ to each subclass, and that you can only assign a single discriminator column per model.

+
+
+

User Defined Types

+

cqlengine models User Defined Types (UDTs) much like tables, with fields defined by column type attributes. However, UDT instances +are only created, presisted, and queried via table Models. A short example to introduce the pattern:

+
from cassandra.cqlengine.columns import *
+from cassandra.cqlengine.models import Model
+from cassandra.cqlengine.usertype import UserType
+
+class address(UserType):
+    street = Text()
+    zipcode = Integer()
+
+class users(Model):
+    __keyspace__ = 'account'
+    name = Text(primary_key=True)
+    addr = UserDefinedType(address)
+
+users.create(name="Joe", addr=address(street="Easy St.", zipcode=99999))
+user = users.objects(name="Joe")[0]
+print user.name, user.addr
+# Joe address(street=u'Easy St.', zipcode=99999)
+
+
+

UDTs are modeled by inheriting UserType, and setting column type attributes. Types are then used in defining +models by declaring a column of type UserDefinedType, with the UserType class as a parameter.

+

sync_table will implicitly +synchronize any types contained in the table. Alternatively sync_type() can be used to create/alter types +explicitly.

+

Upon declaration, types are automatically registered with the driver, so query results return instances of your UserType +class*.

+

*Note: UDTs were not added to the native protocol until v3. When setting up the cqlengine connection, be sure to specify +protocol_version=3. If using an earlier version, UDT queries will still work, but the returned type will be a namedtuple.

+
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.22.3-scylla/cqlengine/queryset.html b/3.22.3-scylla/cqlengine/queryset.html new file mode 100644 index 0000000000..b961170cc4 --- /dev/null +++ b/3.22.3-scylla/cqlengine/queryset.html @@ -0,0 +1,1007 @@ + + + + + + + + + + + + + Making Queries | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

Making Queries

+
+

Retrieving objects

+

Once you’ve populated Cassandra with data, you’ll probably want to retrieve some of it. This is accomplished with QuerySet objects. This section will describe how to use QuerySet objects to retrieve the data you’re looking for.

+
+

Retrieving all objects

+

The simplest query you can make is to return all objects from a table.

+

This is accomplished with the .all() method, which returns a QuerySet of all objects in a table

+

Using the Person example model, we would get all Person objects like this:

+
all_objects = Person.objects.all()
+
+
+
+
+

Retrieving objects with filters

+

Typically, you’ll want to query only a subset of the records in your database.

+

That can be accomplished with the QuerySet’s .filter(\*\*) method.

+

For example, given the model definition:

+
class Automobile(Model):
+    manufacturer = columns.Text(primary_key=True)
+    year = columns.Integer(primary_key=True)
+    model = columns.Text()
+    price = columns.Decimal()
+    options = columns.Set(columns.Text)
+
+
+

…and assuming the Automobile table contains a record of every car model manufactured in the last 20 years or so, we can retrieve only the cars made by a single manufacturer like this:

+
q = Automobile.objects.filter(manufacturer='Tesla')
+
+
+

You can also use the more convenient syntax:

+
q = Automobile.objects(Automobile.manufacturer == 'Tesla')
+
+
+

We can then further filter our query with another call to .filter

+
q = q.filter(year=2012)
+
+
+

Note: all queries involving any filtering MUST define either an ‘=’ or an ‘in’ relation to either a primary key column, or an indexed column.

+
+
+
+

Accessing objects in a QuerySet

+

There are several methods for getting objects out of a queryset

+
    +
  • +
    iterating over the queryset
    for car in Automobile.objects.all():
    +    #...do something to the car instance
    +    pass
    +
    +
    +
    +
    +
  • +
  • +
    list index
    q = Automobile.objects.all()
    +q[0] #returns the first result
    +q[1] #returns the second result
    +
    +
    +
    +

    Note

    +
      +
    • CQL does not support specifying a start position in it’s queries. Therefore, accessing elements using array indexing will load every result up to the index value requested

    • +
    • Using negative indices requires a “SELECT COUNT()” to be executed. This has a performance cost on large datasets.

    • +
    +
    +
    +
    +
  • +
  • +
    list slicing
    q = Automobile.objects.all()
    +q[1:] #returns all results except the first
    +q[1:9] #returns a slice of the results
    +
    +
    +
    +

    Note

    +
      +
    • CQL does not support specifying a start position in it’s queries. Therefore, accessing elements using array slicing will load every result up to the index value requested

    • +
    • Using negative indices requires a “SELECT COUNT()” to be executed. This has a performance cost on large datasets.

    • +
    +
    +
    +
    +
  • +
  • +
    calling get() on the queryset
    q = Automobile.objects.filter(manufacturer='Tesla')
    +q = q.filter(year=2012)
    +car = q.get()
    +
    +
    +

    this returns the object matching the queryset

    +
    +
    +
  • +
  • +
    calling first() on the queryset
    q = Automobile.objects.filter(manufacturer='Tesla')
    +q = q.filter(year=2012)
    +car = q.first()
    +
    +
    +

    this returns the first value in the queryset

    +
    +
    +
  • +
+
+
+

Filtering Operators

+

Equal To

+

The default filtering operator.

+
q = Automobile.objects.filter(manufacturer='Tesla')
+q = q.filter(year=2012)  #year == 2012
+
+
+

In addition to simple equal to queries, cqlengine also supports querying with other operators by appending a __<op> to the field name on the filtering call

+

in (__in)

+
q = Automobile.objects.filter(manufacturer='Tesla')
+q = q.filter(year__in=[2011, 2012])
+
+
+

> (__gt)

+
q = Automobile.objects.filter(manufacturer='Tesla')
+q = q.filter(year__gt=2010)  # year > 2010
+
+# or the nicer syntax
+
+q.filter(Automobile.year > 2010)
+
+
+

>= (__gte)

+
q = Automobile.objects.filter(manufacturer='Tesla')
+q = q.filter(year__gte=2010)  # year >= 2010
+
+# or the nicer syntax
+
+q.filter(Automobile.year >= 2010)
+
+
+

< (__lt)

+
q = Automobile.objects.filter(manufacturer='Tesla')
+q = q.filter(year__lt=2012)  # year < 2012
+
+# or...
+
+q.filter(Automobile.year < 2012)
+
+
+

<= (__lte)

+
q = Automobile.objects.filter(manufacturer='Tesla')
+q = q.filter(year__lte=2012)  # year <= 2012
+
+q.filter(Automobile.year <= 2012)
+
+
+

CONTAINS (__contains)

+

The CONTAINS operator is available for all collection types (List, Set, Map).

+
q = Automobile.objects.filter(manufacturer='Tesla')
+q.filter(options__contains='backup camera').allow_filtering()
+
+
+

Note that we need to use allow_filtering() since the options column has no secondary index.

+

LIKE (__like)

+

The LIKE operator is available for text columns that have a SASI secondary index.

+
q = Automobile.objects.filter(model__like='%Civic%').allow_filtering()
+
+
+

IS NOT NULL (IsNotNull(column_name))

+

The IS NOT NULL operator is not yet supported for C*.

+
q = Automobile.objects.filter(IsNotNull('model'))
+
+
+

Limitations:

+
    +
  • Currently, cqlengine does not support SASI index creation. To use this feature, you need to create the SASI index using the core driver.

  • +
  • Queries using LIKE must use allow_filtering() since the model column has no standard secondary index. Note that the server will use the SASI index properly when executing the query.

  • +
+
+
+

TimeUUID Functions

+

In addition to querying using regular values, there are two functions you can pass in when querying TimeUUID columns to help make filtering by them easier. Note that these functions don’t actually return a value, but instruct the cql interpreter to use the functions in it’s query.

+
+
+class cqlengine.queryset.MinTimeUUID(datetime)
+

returns the minimum time uuid value possible for the given datetime

+
+ +
+
+class cqlengine.queryset.MaxTimeUUID(datetime)
+

returns the maximum time uuid value possible for the given datetime

+
+ +

Example

+
class DataStream(Model):
+    id      = columns.UUID(partition_key=True)
+    time    = columns.TimeUUID(primary_key=True)
+    data    = columns.Bytes()
+
+min_time = datetime(1982, 1, 1)
+max_time = datetime(1982, 3, 9)
+
+DataStream.filter(time__gt=functions.MinTimeUUID(min_time), time__lt=functions.MaxTimeUUID(max_time))
+
+
+
+
+

Token Function

+

Token functon may be used only on special, virtual column pk__token, representing token of partition key (it also works for composite partition keys). +Cassandra orders returned items by value of partition key token, so using cqlengine.Token we can easy paginate through all table rows.

+

See http://cassandra.apache.org/doc/cql3/CQL-3.0.html#tokenFun

+

Example

+
class Items(Model):
+    id      = columns.Text(primary_key=True)
+    data    = columns.Bytes()
+
+query = Items.objects.all().limit(10)
+
+first_page = list(query);
+last = first_page[-1]
+next_page = list(query.filter(pk__token__gt=cqlengine.Token(last.pk)))
+
+
+
+
+

QuerySets are immutable

+

When calling any method that changes a queryset, the method does not actually change the queryset object it’s called on, but returns a new queryset object with the attributes of the original queryset, plus the attributes added in the method call.

+

Example

+
#this produces 3 different querysets
+#q does not change after it's initial definition
+q = Automobiles.objects.filter(year=2012)
+tesla2012 = q.filter(manufacturer='Tesla')
+honda2012 = q.filter(manufacturer='Honda')
+
+
+
+
+

Ordering QuerySets

+

Since Cassandra is essentially a distributed hash table on steroids, the order you get records back in will not be particularly predictable.

+

However, you can set a column to order on with the .order_by(column_name) method.

+

Example

+
#sort ascending
+q = Automobiles.objects.all().order_by('year')
+#sort descending
+q = Automobiles.objects.all().order_by('-year')
+
+
+

Note: Cassandra only supports ordering on a clustering key. In other words, to support ordering results, your model must have more than one primary key, and you must order on a primary key, excluding the first one.

+

For instance, given our Automobile model, year is the only column we can order on.

+
+
+

Values Lists

+

There is a special QuerySet’s method .values_list() - when called, QuerySet returns lists of values instead of model instances. It may significantly speedup things with lower memory footprint for large responses. +Each tuple contains the value from the respective field passed into the values_list() call — so the first item is the first field, etc. For example:

+
items = list(range(20))
+random.shuffle(items)
+for i in items:
+    TestModel.create(id=1, clustering_key=i)
+
+values = list(TestModel.objects.values_list('clustering_key', flat=True))
+# [19L, 18L, 17L, 16L, 15L, 14L, 13L, 12L, 11L, 10L, 9L, 8L, 7L, 6L, 5L, 4L, 3L, 2L, 1L, 0L]
+
+
+
+
+

Per Query Timeouts

+

By default all queries are executed with the timeout defined in ~cqlengine.connection.setup() +The examples below show how to specify a per-query timeout. +A timeout is specified in seconds and can be an int, float or None. +None means no timeout.

+
class Row(Model):
+    id = columns.Integer(primary_key=True)
+    name = columns.Text()
+
+
+

Fetch all objects with a timeout of 5 seconds

+
Row.objects().timeout(5).all()
+
+
+

Create a single row with a 50ms timeout

+
Row(id=1, name='Jon').timeout(0.05).create()
+
+
+

Delete a single row with no timeout

+
Row(id=1).timeout(None).delete()
+
+
+

Update a single row with no timeout

+
Row(id=1).timeout(None).update(name='Blake')
+
+
+

Batch query timeouts

+
with BatchQuery(timeout=10) as b:
+    Row(id=1, name='Jon').create()
+
+
+

NOTE: You cannot set both timeout and batch at the same time, batch will use the timeout defined in it’s constructor. +Setting the timeout on the model is meaningless and will raise an AssertionError.

+
+
+

Default TTL and Per Query TTL

+

Model default TTL now relies on the default_time_to_live feature, introduced in Cassandra 2.0. It is not handled anymore in the CQLEngine Model (scylla-driver >=3.6). You can set the default TTL of a table like this:

+

Example:

+
class User(Model):
+    __options__ = {'default_time_to_live': 20}
+
+    user_id = columns.UUID(primary_key=True)
+    ...
+
+
+

You can set TTL per-query if needed. Here are a some examples:

+

Example:

+
class User(Model):
+    __options__ = {'default_time_to_live': 20}
+
+    user_id = columns.UUID(primary_key=True)
+    ...
+
+user = User.objects.create(user_id=1)  # Default TTL 20 will be set automatically on the server
+
+user.ttl(30).update(age=21)            # Update the TTL to 30
+User.objects.ttl(10).create(user_id=1)  # TTL 10
+User(user_id=1, age=21).ttl(10).save()  # TTL 10
+
+
+
+
+

Named Tables

+

Named tables are a way of querying a table without creating an class. They’re useful for querying system tables or exploring an unfamiliar database.

+
from cassandra.cqlengine.connection import setup
+setup("127.0.0.1", "cqlengine_test")
+
+from cassandra.cqlengine.named import NamedTable
+user = NamedTable("cqlengine_test", "user")
+user.objects()
+user.objects()[0]
+
+# {u'pk': 1, u't': datetime.datetime(2014, 6, 26, 17, 10, 31, 774000)}
+
+
+
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.22.3-scylla/cqlengine/third_party.html b/3.22.3-scylla/cqlengine/third_party.html new file mode 100644 index 0000000000..4dbb905930 --- /dev/null +++ b/3.22.3-scylla/cqlengine/third_party.html @@ -0,0 +1,707 @@ + + + + + + + + + + + + + Third party integrations | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

Third party integrations

+
+

Celery

+

Here’s how, in substance, CQLengine can be plugged to Celery:

+
from celery import Celery
+from celery.signals import worker_process_init, beat_init
+from cassandra.cqlengine import connection
+from cassandra.cqlengine.connection import (
+    cluster as cql_cluster, session as cql_session)
+
+def cassandra_init(**kwargs):
+    """ Initialize a clean Cassandra connection. """
+    if cql_cluster is not None:
+        cql_cluster.shutdown()
+    if cql_session is not None:
+        cql_session.shutdown()
+    connection.setup()
+
+# Initialize worker context for both standard and periodic tasks.
+worker_process_init.connect(cassandra_init)
+beat_init.connect(cassandra_init)
+
+app = Celery()
+
+
+
+
+

uWSGI

+

This is the code required for proper connection handling of CQLengine for a +uWSGI-run application:

+
from cassandra.cqlengine import connection
+from cassandra.cqlengine.connection import (
+    cluster as cql_cluster, session as cql_session)
+
+try:
+    from uwsgidecorators import postfork
+except ImportError:
+    # We're not in a uWSGI context, no need to hook Cassandra session
+    # initialization to the postfork event.
+    pass
+else:
+    @postfork
+    def cassandra_init(**kwargs):
+        """ Initialize a new Cassandra session in the context.
+
+        Ensures that a new session is returned for every new request.
+        """
+        if cql_cluster is not None:
+            cql_cluster.shutdown()
+        if cql_session is not None:
+            cql_session.shutdown()
+        connection.setup()
+
+
+
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.22.3-scylla/cqlengine/upgrade_guide.html b/3.22.3-scylla/cqlengine/upgrade_guide.html new file mode 100644 index 0000000000..a483db64a5 --- /dev/null +++ b/3.22.3-scylla/cqlengine/upgrade_guide.html @@ -0,0 +1,839 @@ + + + + + + + + + + + + + Upgrade Guide | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + + + +
+

Upgrade Guide

+

This is an overview of things that changed as the cqlengine project was merged into +scylla-driver. While efforts were taken to preserve the API and most functionality exactly, +conversion to this package will still require certain minimal updates (namely, imports).

+

THERE IS ONE FUNCTIONAL CHANGE, described in the first section below.

+
+

Functional Changes

+
+

List Prepend Reversing

+

Legacy cqlengine included a workaround for a Cassandra bug in which prepended list segments were +reversed (CASSANDRA-8733). As of +this integration, this workaround is removed. The first released integrated version emits +a warning when prepend is used. Subsequent versions will have this warning removed.

+
+
+

Date Column Type

+

The Date column type in legacy cqlengine used a timestamp CQL type and truncated the time. +Going forward, the Date type represents a date for Cassandra 2.2+ +(PYTHON-245). +Users of the legacy functionality should convert models to use DateTime (which +uses timestamp internally), and use the build-in datetime.date for input values.

+
+
+
+

Remove cqlengine

+

To avoid confusion or mistakes using the legacy package in your application, it +is prudent to remove the cqlengine package when upgrading to the integrated version.

+

The driver setup script will warn if the legacy package is detected during install, +but it will not prevent side-by-side installation.

+
+
+

Organization

+
+

Imports

+

cqlengine is now integrated as a sub-package of the driver base package ‘cassandra’. +Upgrading will require adjusting imports to cqlengine. For example:

+
from cassandra.cqlengine import columns
+
+
+

is now:

+
from cassandra.cqlengine import columns
+
+
+
+
+

Package-Level Aliases

+

Legacy cqlengine defined a number of aliases at the package level, which became redundant +when the package was integrated for a driver. These have been removed in favor of absolute +imports, and referring to cannonical definitions. For example, cqlengine.ONE was an alias +of cassandra.ConsistencyLevel.ONE. In the integrated package, only the +cassandra.ConsistencyLevel remains.

+

Additionally, submodule aliases are removed from cqlengine in favor of absolute imports.

+

These aliases are removed, and not deprecated because they should be straightforward to iron out +at module load time.

+
+
+

Exceptions

+

The legacy cqlengine.exceptions module had a number of Exception classes that were variously +common to the package, or only used in specific modules. Common exceptions were relocated to +cqlengine, and specialized exceptions were placed in the module that raises them. Below is a +listing of updated locations:

+ ++++ + + + + + + + + + + + + + + + + + + + + + + + + + +

Exception class

New module

CQLEngineException

cassandra.cqlengine

ModelException

cassandra.cqlengine.models

ValidationError

cassandra.cqlengine

UndefinedKeyspaceException

cassandra.cqlengine.connection

LWTException

cassandra.cqlengine.query

IfNotExistsWithCounterColumn

cassandra.cqlengine.query

+
+
+

UnicodeMixin Consolidation

+

class UnicodeMixin was defined in several cqlengine modules. This has been consolidated +to a single definition in the cqlengine package init file. This is not technically part of +the API, but noted here for completeness.

+
+
+
+

API Deprecations

+

This upgrade served as a good juncture to deprecate certain API features and invite users to upgrade +to new ones. The first released version does not change functionality – only introduces deprecation +warnings. Future releases will remove these features in favor of the alternatives.

+
+

Float/Double Overload

+

Previously there was no Double column type. Doubles were modeled by specifying Float(double_precision=True). +This inititializer parameter is now deprecated. Applications should use Double for CQL double, and Float +for CQL float.

+
+
+

Schema Management

+

cassandra.cqlengine.management.create_keyspace is deprecated. Instead, use the new replication-strategy-specific +functions that accept explicit options for known strategies:

+ +

cassandra.cqlengine.management.delete_keyspace is deprecated in favor of a new function, drop_keyspace(). The +intent is simply to make the function match the CQL verb it invokes.

+
+
+

Model Inheritance

+

The names for class attributes controlling model inheritance are changing. Changes are as follows:

+ +

The functionality is unchanged – the intent here is to make the names and language around these attributes more precise. +For now, the old names are just deprecated, and the mapper will emit warnings if they are used. The old names +will be removed in a future version.

+

The example below shows a simple translation:

+

Before:

+
class Pet(Model):
+    __table_name__ = 'pet'
+    owner_id = UUID(primary_key=True)
+    pet_id = UUID(primary_key=True)
+    pet_type = Text(polymorphic_key=True)
+    name = Text()
+
+class Cat(Pet):
+    __polymorphic_key__ = 'cat'
+
+class Dog(Pet):
+    __polymorphic_key__ = 'dog'
+
+
+

After:

+
class Pet(models.Model):
+    __table_name__ = 'pet'
+    owner_id = UUID(primary_key=True)
+    pet_id = UUID(primary_key=True)
+    pet_type = Text(discriminator_column=True)
+    name = Text()
+
+class Cat(Pet):
+    __discriminator_value__ = 'cat'
+
+class Dog(Pet):
+    __discriminator_value__ = 'dog'
+
+
+
+
+

TimeUUID.from_datetime

+

This function is deprecated in favor of the core utility function uuid_from_time().

+
+
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.22.3-scylla/dates_and_times.html b/3.22.3-scylla/dates_and_times.html new file mode 100644 index 0000000000..02a7ae136e --- /dev/null +++ b/3.22.3-scylla/dates_and_times.html @@ -0,0 +1,731 @@ + + + + + + + + + + + + + Working with Dates and Times | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

Working with Dates and Times

+

This document is meant to provide on overview of the assumptions and limitations of the driver time handling, the +reasoning behind it, and describe approaches to working with these types.

+
+

timestamps (Cassandra DateType)

+

Timestamps in Cassandra are timezone-naive timestamps encoded as millseconds since UNIX epoch. Clients working with +timestamps in this database usually find it easiest to reason about them if they are always assumed to be UTC. To quote the +pytz documentation, “The preferred way of dealing with times is to always work in UTC, converting to localtime only when +generating output to be read by humans.” The driver adheres to this tenant, and assumes UTC is always in the database. The +driver attempts to make this correct on the way in, and assumes no timezone on the way out.

+
+

Write Path

+

When inserting timestamps, the driver handles serialization for the write path as follows:

+

If the input is a datetime.datetime, the serialization is normalized by starting with the utctimetuple() of the +value.

+
    +
  • If the datetime object is timezone-aware, the timestamp is shifted, and represents the UTC timestamp equivalent.

  • +
  • If the datetime object is timezone-naive, this results in no shift – any datetime with no timezone information is assumed to be UTC

  • +
+

Note the second point above applies even to “local” times created using now():

+
>>> d = datetime.now()
+
+>>> print(d.tzinfo)
+None
+
+
+

These do not contain timezone information intrinsically, so they will be assumed to be UTC and not shifted. When generating +timestamps in the application, it is clearer to use datetime.utcnow() to be explicit about it.

+

If the input for a timestamp is numeric, it is assumed to be a epoch-relative millisecond timestamp, as specified in the +CQL spec – no scaling or conversion is done.

+
+
+

Read Path

+

The driver always assumes persisted timestamps are UTC and makes no attempt to localize them. Returned values are +timezone-naive datetime.datetime. We follow this approach because the datetime API has deficiencies around daylight +saving time, and the defacto package for handling this is a third-party package (we try to minimize external dependencies +and not make decisions for the integrator).

+

The decision for how to handle timezones is left to the application. For the most part it is straightforward to apply +localization to the datetimes returned by queries. One prevalent method is to use pytz for localization:

+
import pytz
+user_tz = pytz.timezone('US/Central')
+timestamp_naive = row.ts
+timestamp_utc = pytz.utc.localize(timestamp_naive)
+timestamp_presented = timestamp_utc.astimezone(user_tz)
+
+
+

This is the most robust approach (likely refactored into a function). If it is deemed too cumbersome to apply for all call +sites in the application, it is possible to patch the driver with custom deserialization for this type. However, doing +this depends depends some on internal APIs and what extensions are present, so we will only mention the possibility, and +not spell it out here.

+
+
+
+

date, time (Cassandra DateType)

+

Date and time in Cassandra are idealized markers, much like datetime.date and datetime.time in the Python standard +library. Unlike these Python implementations, the Cassandra encoding supports much wider ranges. To accommodate these +ranges without overflow, this driver returns these data in custom types: util.Date and util.Time.

+
+

Write Path

+

For simple (not prepared) statements, the input values for each of these can be either a string literal or an encoded +integer. See Working with dates +or Working with time for details +on the encoding or string formats.

+

For prepared statements, the driver accepts anything that can be used to construct the util.Date or +util.Time classes. See the linked API docs for details.

+
+
+

Read Path

+

The driver always returns custom types for date and time.

+

The driver returns util.Date for date in order to accommodate the wider range of values without overflow. +For applications working within the supported range of [datetime.MINYEAR, datetime.MAXYEAR], these are easily +converted to standard datetime.date insances using Date.date().

+

The driver returns util.Time for time in order to retain nanosecond precision stored in the database. +For applications not concerned with this level of precision, these are easily converted to standard datetime.time +insances using Time.time().

+
+
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.22.3-scylla/execution_profiles.html b/3.22.3-scylla/execution_profiles.html new file mode 100644 index 0000000000..7dd3773ab3 --- /dev/null +++ b/3.22.3-scylla/execution_profiles.html @@ -0,0 +1,775 @@ + + + + + + + + + + + + + Execution Profiles | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

Execution Profiles

+

Execution profiles aim at making it easier to execute requests in different ways within +a single connected Session. Execution profiles are being introduced to deal with the exploding number of +configuration options, especially as the database platform evolves more complex workloads.

+

The legacy configuration remains intact, but legacy and Execution Profile APIs +cannot be used simultaneously on the same client Cluster. Legacy configuration +will be removed in the next major release (4.0).

+

An execution profile and its parameters should be unique across Cluster instances. +For example, an execution profile and its LoadBalancingPolicy should +not be applied to more than one Cluster instance.

+

This document explains how Execution Profiles relate to existing settings, and shows how to use the new profiles for +request execution.

+
+

Mapping Legacy Parameters to Profiles

+

Execution profiles can inherit from cluster.ExecutionProfile, and currently provide the following options, +previously input from the noted attributes:

+ +

When using the new API, these parameters can be defined by instances of cluster.ExecutionProfile.

+
+
+

Using Execution Profiles

+
+

Default

+
from cassandra.cluster import Cluster
+cluster = Cluster()
+session = cluster.connect()
+local_query = 'SELECT rpc_address FROM system.local'
+for _ in cluster.metadata.all_hosts():
+    print session.execute(local_query)[0]
+
+
+
Row(rpc_address='127.0.0.2')
+Row(rpc_address='127.0.0.1')
+
+
+

The default execution profile is built from Cluster parameters and default Session attributes. This profile matches existing default +parameters.

+
+
+

Initializing cluster with profiles

+
from cassandra.cluster import ExecutionProfile
+from cassandra.policies import WhiteListRoundRobinPolicy
+
+node1_profile = ExecutionProfile(load_balancing_policy=WhiteListRoundRobinPolicy(['127.0.0.1']))
+node2_profile = ExecutionProfile(load_balancing_policy=WhiteListRoundRobinPolicy(['127.0.0.2']))
+
+profiles = {'node1': node1_profile, 'node2': node2_profile}
+session = Cluster(execution_profiles=profiles).connect()
+for _ in cluster.metadata.all_hosts():
+    print session.execute(local_query, execution_profile='node1')[0]
+
+
+
Row(rpc_address='127.0.0.1')
+Row(rpc_address='127.0.0.1')
+
+
+
for _ in cluster.metadata.all_hosts():
+    print session.execute(local_query, execution_profile='node2')[0]
+
+
+
Row(rpc_address='127.0.0.2')
+Row(rpc_address='127.0.0.2')
+
+
+
for _ in cluster.metadata.all_hosts():
+    print session.execute(local_query)[0]
+
+
+
Row(rpc_address='127.0.0.2')
+Row(rpc_address='127.0.0.1')
+
+
+

Note that, even when custom profiles are injected, the default TokenAwarePolicy(DCAwareRoundRobinPolicy()) is still +present. To override the default, specify a policy with the EXEC_PROFILE_DEFAULT key.

+
from cassandra.cluster import EXEC_PROFILE_DEFAULT
+profile = ExecutionProfile(request_timeout=30)
+cluster = Cluster(execution_profiles={EXEC_PROFILE_DEFAULT: profile})
+
+
+
+
+

Adding named profiles

+

New profiles can be added constructing from scratch, or deriving from default:

+
locked_execution = ExecutionProfile(load_balancing_policy=WhiteListRoundRobinPolicy(['127.0.0.1']))
+node1_profile = 'node1_whitelist'
+cluster.add_execution_profile(node1_profile, locked_execution)
+
+for _ in cluster.metadata.all_hosts():
+    print session.execute(local_query, execution_profile=node1_profile)[0]
+
+
+
Row(rpc_address='127.0.0.1')
+Row(rpc_address='127.0.0.1')
+
+
+

See Cluster.add_execution_profile() for details and optional parameters.

+
+
+

Passing a profile instance without mapping

+

We also have the ability to pass profile instances to be used for execution, but not added to the mapping:

+
from cassandra.query import tuple_factory
+
+tmp = session.execution_profile_clone_update('node1', request_timeout=100, row_factory=tuple_factory)
+
+print session.execute(local_query, execution_profile=tmp)[0]
+print session.execute(local_query, execution_profile='node1')[0]
+
+
+
('127.0.0.1',)
+Row(rpc_address='127.0.0.1')
+
+
+

The new profile is a shallow copy, so the tmp profile shares a load balancing policy with one managed by the cluster. +If reference objects are to be updated in the clone, one would typically set those attributes to a new instance.

+
+
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.22.3-scylla/faq.html b/3.22.3-scylla/faq.html new file mode 100644 index 0000000000..5f87995eb4 --- /dev/null +++ b/3.22.3-scylla/faq.html @@ -0,0 +1,711 @@ + + + + + + + + + + + + + Frequently Asked Questions | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

Frequently Asked Questions

+

See also cqlengine FAQ

+
+

Why do connections or IO operations timeout in my WSGI application?

+

Depending on your application process model, it may be forking after driver Session is created. Most IO reactors do not handle this, and problems will manifest as timeouts.

+

To avoid this, make sure to create sessions per process, after the fork. Using uWSGI and Flask for example:

+
from flask import Flask
+from uwsgidecorators import postfork
+from cassandra.cluster import Cluster
+
+session = None
+prepared = None
+
+@postfork
+def connect():
+    global session, prepared
+    session = Cluster().connect()
+    prepared = session.prepare("SELECT release_version FROM system.local WHERE key=?")
+
+app = Flask(__name__)
+
+@app.route('/')
+def server_version():
+    row = session.execute(prepared, ('local',))[0]
+    return row.release_version
+
+
+

uWSGI provides a postfork hook you can use to create sessions and prepared statements after the child process forks.

+
+
+

How do I trace a request?

+

Request tracing can be turned on for any request by setting trace=True in Session.execute_async(). View the results by waiting on the future, then ResponseFuture.get_query_trace(). +Since tracing is done asynchronously to the request, this method polls until the trace is complete before querying data.

+
>>> future = session.execute_async("SELECT * FROM system.local", trace=True)
+>>> result = future.result()
+>>> trace = future.get_query_trace()
+>>> for e in trace.events:
+>>>     print e.source_elapsed, e.description
+
+0:00:00.000077 Parsing select * from system.local
+0:00:00.000153 Preparing statement
+0:00:00.000309 Computing ranges to query
+0:00:00.000368 Submitting range requests on 1 ranges with a concurrency of 1 (279.77142 rows per range expected)
+0:00:00.000422 Submitted 1 concurrent range requests covering 1 ranges
+0:00:00.000480 Executing seq scan across 1 sstables for (min(-9223372036854775808), min(-9223372036854775808))
+0:00:00.000669 Read 1 live and 0 tombstone cells
+0:00:00.000755 Scanned 1 rows and matched 1
+
+
+

trace is a QueryTrace object.

+
+
+

How do I determine the replicas for a query?

+

With prepared statements, the replicas are obtained by routing_key, based on current cluster token metadata:

+
>>> prepared = session.prepare("SELECT * FROM example.t WHERE key=?")
+>>> bound = prepared.bind((1,))
+>>> replicas = cluster.metadata.get_replicas(bound.keyspace, bound.routing_key)
+>>> for h in replicas:
+>>>   print h.address
+127.0.0.1
+127.0.0.2
+
+
+

replicas is a list of Host objects.

+
+
+

How does the driver manage request retries?

+

By default, retries are managed by the Cluster.default_retry_policy set on the session Cluster. It can also +be specialized per statement by setting Statement.retry_policy.

+

Retries are presently attempted on the same coordinator, but this may change in the future.

+

Please see policies.RetryPolicy for further details.

+
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.22.3-scylla/getting_started.html b/3.22.3-scylla/getting_started.html new file mode 100644 index 0000000000..1d3686dd90 --- /dev/null +++ b/3.22.3-scylla/getting_started.html @@ -0,0 +1,1116 @@ + + + + + + + + + + + + + Getting Started | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

Getting Started

+

First, make sure you have the driver properly installed.

+
+

Connecting to Cassandra

+

Before we can start executing any queries against a Cassandra cluster we need to setup +an instance of Cluster. As the name suggests, you will typically have one +instance of Cluster for each Cassandra cluster you want to interact +with.

+

The simplest way to create a Cluster is like this: +First, make sure you have the Cassandra driver properly installed.

+
from cassandra.cluster import Cluster
+
+cluster = Cluster()
+
+
+

This will attempt to connection to a Cassandra instance on your +local machine (127.0.0.1). You can also specify a list of IP +addresses for nodes in your cluster:

+
from cassandra.cluster import Cluster
+
+cluster = Cluster(['192.168.0.1', '192.168.0.2'])
+
+
+

The set of IP addresses we pass to the Cluster is simply +an initial set of contact points. After the driver connects to one +of these nodes it will automatically discover the rest of the +nodes in the cluster and connect to them, so you don’t need to list +every node in your cluster.

+

If you need to use a non-standard port, use SSL, or customize the driver’s +behavior in some other way, this is the place to do it:

+
from cassandra.cluster import Cluster
+cluster = Cluster(['192.168.0.1', '192.168.0.2'], port=..., ssl_context=...)
+
+
+

Instantiating a Cluster does not actually connect us to any nodes. +To establish connections and begin executing queries we need a +Session, which is created by calling Cluster.connect():

+
cluster = Cluster()
+session = cluster.connect()
+
+
+

The connect() method takes an optional keyspace argument +which sets the default keyspace for all queries made through that Session:

+
cluster = Cluster()
+session = cluster.connect('mykeyspace')
+
+
+

You can always change a Session’s keyspace using set_keyspace() or +by executing a USE <keyspace> query:

+
session.set_keyspace('users')
+# or you can do this instead
+session.execute('USE users')
+
+
+

Profiles are passed in by execution_profiles dict.

+

In this case we can construct the base ExecutionProfile passing all attributes:

+
from cassandra.cluster import Cluster, ExecutionProfile, EXEC_PROFILE_DEFAULT
+from cassandra.policies import WhiteListRoundRobinPolicy, DowngradingConsistencyRetryPolicy
+from cassandra.query import tuple_factory
+
+profile = ExecutionProfile(
+    load_balancing_policy=WhiteListRoundRobinPolicy(['127.0.0.1']),
+    retry_policy=DowngradingConsistencyRetryPolicy(),
+    consistency_level=ConsistencyLevel.LOCAL_QUORUM,
+    serial_consistency_level=ConsistencyLevel.LOCAL_SERIAL,
+    request_timeout=15,
+    row_factory=tuple_factory
+)
+cluster = Cluster(execution_profiles={EXEC_PROFILE_DEFAULT: profile})
+session = cluster.connect()
+
+print(session.execute("SELECT release_version FROM system.local").one())
+
+
+

Users are free to setup additional profiles to be used by name:

+
profile_long = ExecutionProfile(request_timeout=30)
+cluster = Cluster(execution_profiles={'long': profile_long})
+session = cluster.connect()
+session.execute(statement, execution_profile='long')
+
+
+

Also, parameters passed to Session.execute or attached to Statements are still honored as before.

+
+
+

Executing Queries

+

Now that we have a Session we can begin to execute queries. The simplest +way to execute a query is to use execute():

+
rows = session.execute('SELECT name, age, email FROM users')
+for user_row in rows:
+    print user_row.name, user_row.age, user_row.email
+
+
+

This will transparently pick a Cassandra node to execute the query against +and handle any retries that are necessary if the operation fails.

+

By default, each row in the result set will be a +namedtuple. +Each row will have a matching attribute for each column defined in the schema, +such as name, age, and so on. You can also treat them as normal tuples +by unpacking them or accessing fields by position. The following three +examples are equivalent:

+
rows = session.execute('SELECT name, age, email FROM users')
+for row in rows:
+    print row.name, row.age, row.email
+
+
+
rows = session.execute('SELECT name, age, email FROM users')
+for (name, age, email) in rows:
+    print name, age, email
+
+
+
rows = session.execute('SELECT name, age, email FROM users')
+for row in rows:
+    print row[0], row[1], row[2]
+
+
+

If you prefer another result format, such as a dict per row, you +can change the row_factory attribute.

+

As mentioned in our Drivers Best Practices Guide, +it is highly recommended to use Prepared statements for your +frequently run queries.

+
+
+

Prepared Statements

+

Prepared statements are queries that are parsed by Cassandra and then saved +for later use. When the driver uses a prepared statement, it only needs to +send the values of parameters to bind. This lowers network traffic +and CPU utilization within Cassandra because Cassandra does not have to +re-parse the query each time.

+

To prepare a query, use Session.prepare():

+
user_lookup_stmt = session.prepare("SELECT * FROM users WHERE user_id=?")
+
+users = []
+for user_id in user_ids_to_query:
+    user = session.execute(user_lookup_stmt, [user_id])
+    users.append(user)
+
+
+

prepare() returns a PreparedStatement instance +which can be used in place of SimpleStatement instances or literal +string queries. It is automatically prepared against all nodes, and the driver +handles re-preparing against new nodes and restarted nodes when necessary.

+

Note that the placeholders for prepared statements are ? characters. This +is different than for simple, non-prepared statements (although future versions +of the driver may use the same placeholders for both).

+
+

Passing Parameters to CQL Queries

+

Althought it is not recommended, you can also pass parameters to non-prepared +statements. The driver supports two forms of parameter place-holders: positional +and named.

+

Positional parameters are used with a %s placeholder. For example, +when you execute:

+
session.execute(
+    """
+    INSERT INTO users (name, credits, user_id)
+    VALUES (%s, %s, %s)
+    """,
+    ("John O'Reilly", 42, uuid.uuid1())
+)
+
+
+

It is translated to the following CQL query:

+
INSERT INTO users (name, credits, user_id)
+VALUES ('John O''Reilly', 42, 2644bada-852c-11e3-89fb-e0b9a54a6d93)
+
+
+

Note that you should use %s for all types of arguments, not just strings. +For example, this would be wrong:

+
session.execute("INSERT INTO USERS (name, age) VALUES (%s, %d)", ("bob", 42))  # wrong
+
+
+

Instead, use %s for the age placeholder.

+

If you need to use a literal % character, use %%.

+

Note: you must always use a sequence for the second argument, even if you are +only passing in a single variable:

+
session.execute("INSERT INTO foo (bar) VALUES (%s)", "blah")  # wrong
+session.execute("INSERT INTO foo (bar) VALUES (%s)", ("blah"))  # wrong
+session.execute("INSERT INTO foo (bar) VALUES (%s)", ("blah", ))  # right
+session.execute("INSERT INTO foo (bar) VALUES (%s)", ["blah"])  # right
+
+
+

Note that the second line is incorrect because in Python, single-element tuples +require a comma.

+

Named place-holders use the %(name)s form:

+
session.execute(
+    """
+    INSERT INTO users (name, credits, user_id, username)
+    VALUES (%(name)s, %(credits)s, %(user_id)s, %(name)s)
+    """,
+    {'name': "John O'Reilly", 'credits': 42, 'user_id': uuid.uuid1()}
+)
+
+
+

Note that you can repeat placeholders with the same name, such as %(name)s +in the above example.

+

Only data values should be supplied this way. Other items, such as keyspaces, +table names, and column names should be set ahead of time (typically using +normal string formatting).

+
+
+

Type Conversions

+

For non-prepared statements, Python types are cast to CQL literals in the +following way:

+ ++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Python Type

CQL Literal Type

None

NULL

bool

boolean

float

+
float
+
double
+
+
+
int
+
long
+
+
+
int
+
bigint
+
varint
+
smallint
+
tinyint
+
counter
+
+

decimal.Decimal

decimal

+
str
+
unicode
+
+
+
ascii
+
varchar
+
text
+
+
+
buffer
+
bytearray
+
+

blob

date

date

datetime

timestamp

time

time

+
list
+
tuple
+
generator
+
+

list

+
set
+
frozenset
+
+

set

+
dict
+
OrderedDict
+
+

map

uuid.UUID

+
timeuuid
+
uuid
+
+
+
+
+

Asynchronous Queries

+

The driver supports asynchronous query execution through +execute_async(). Instead of waiting for the query to +complete and returning rows directly, this method almost immediately +returns a ResponseFuture object. There are two ways of +getting the final result from this object.

+

The first is by calling result() on it. If +the query has not yet completed, this will block until it has and +then return the result or raise an Exception if an error occurred. +For example:

+
from cassandra import ReadTimeout
+
+query = "SELECT * FROM users WHERE user_id=%s"
+future = session.execute_async(query, [user_id])
+
+# ... do some other work
+
+try:
+    rows = future.result()
+    user = rows[0]
+    print user.name, user.age
+except ReadTimeout:
+    log.exception("Query timed out:")
+
+
+

This works well for executing many queries concurrently:

+
# build a list of futures
+futures = []
+query = "SELECT * FROM users WHERE user_id=%s"
+for user_id in ids_to_fetch:
+    futures.append(session.execute_async(query, [user_id])
+
+# wait for them to complete and use the results
+for future in futures:
+    rows = future.result()
+    print rows[0].name
+
+
+

Alternatively, instead of calling result(), +you can attach callback and errback functions through the +add_callback(), +add_errback(), and +add_callbacks(), methods. If you have used +Twisted Python before, this is designed to be a lightweight version of +that:

+
def handle_success(rows):
+    user = rows[0]
+    try:
+        process_user(user.name, user.age, user.id)
+    except Exception:
+        log.error("Failed to process user %s", user.id)
+        # don't re-raise errors in the callback
+
+def handle_error(exception):
+    log.error("Failed to fetch user info: %s", exception)
+
+
+future = session.execute_async(query)
+future.add_callbacks(handle_success, handle_error)
+
+
+
+
There are a few important things to remember when working with callbacks:
    +
  • Exceptions that are raised inside the callback functions will be logged and then ignored.

  • +
  • Your callback will be run on the event loop thread, so any long-running +operations will prevent other requests from being handled

  • +
+
+
+
+
+
+

Setting a Consistency Level

+

The consistency level used for a query determines how many of the +replicas of the data you are interacting with need to respond for +the query to be considered a success.

+

By default, ConsistencyLevel.LOCAL_ONE will be used for all queries. +You can specify a different default by setting the ExecutionProfile.consistency_level +for the execution profile with key EXEC_PROFILE_DEFAULT. +To specify a different consistency level per request, wrap queries +in a SimpleStatement:

+
from cassandra import ConsistencyLevel
+from cassandra.query import SimpleStatement
+
+query = SimpleStatement(
+    "INSERT INTO users (name, age) VALUES (%s, %s)",
+    consistency_level=ConsistencyLevel.QUORUM)
+session.execute(query, ('John', 42))
+
+
+
+

Setting a Consistency Level with Prepared Statements

+

To specify a consistency level for prepared statements, you have two options.

+

The first is to set a default consistency level for every execution of the +prepared statement:

+
from cassandra import ConsistencyLevel
+
+cluster = Cluster()
+session = cluster.connect("mykeyspace")
+user_lookup_stmt = session.prepare("SELECT * FROM users WHERE user_id=?")
+user_lookup_stmt.consistency_level = ConsistencyLevel.QUORUM
+
+# these will both use QUORUM
+user1 = session.execute(user_lookup_stmt, [user_id1])[0]
+user2 = session.execute(user_lookup_stmt, [user_id2])[0]
+
+
+

The second option is to create a BoundStatement from the +PreparedStatement and binding parameters and set a consistency +level on that:

+
# override the QUORUM default
+user3_lookup = user_lookup_stmt.bind([user_id3])
+user3_lookup.consistency_level = ConsistencyLevel.ALL
+user3 = session.execute(user3_lookup)
+
+
+
+
+

Speculative Execution

+

Speculative execution is a way to minimize latency by preemptively executing several +instances of the same query against different nodes. For more details about this +technique, see Speculative Execution with DataStax Drivers.

+

To enable speculative execution:

+
    +
  • Configure a SpeculativeExecutionPolicy with the ExecutionProfile

  • +
  • Mark your query as idempotent, which mean it can be applied multiple +times without changing the result of the initial application. +See Query Idempotence for more details.

  • +
+

Example:

+
from cassandra.cluster import Cluster, ExecutionProfile, EXEC_PROFILE_DEFAULT
+from cassandra.policies import ConstantSpeculativeExecutionPolicy
+from cassandra.query import SimpleStatement
+
+# Configure the speculative execution policy
+ep = ExecutionProfile(
+    speculative_execution_policy=ConstantSpeculativeExecutionPolicy(delay=.5, max_attempts=10)
+)
+cluster = Cluster(..., execution_profiles={EXEC_PROFILE_DEFAULT: ep})
+session = cluster.connect()
+
+# Mark the query idempotent
+query = SimpleStatement(
+    "UPDATE my_table SET list_col = [1] WHERE pk = 1",
+    is_idempotent=True
+)
+
+# Execute. A new query will be sent to the server every 0.5 second
+# until we receive a response, for a max number attempts of 10.
+session.execute(query)
+
+
+
+
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.22.3-scylla/index.html b/3.22.3-scylla/index.html new file mode 100644 index 0000000000..f954fb0db5 --- /dev/null +++ b/3.22.3-scylla/index.html @@ -0,0 +1,701 @@ + + + + + + + + + + + + + Python Driver for Scylla and Apache Cassandra® | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

Python Driver for Scylla and Apache Cassandra®

+

A Python client driver for Scylla. +This driver works exclusively with the Cassandra Query Language v3 (CQL3) +and Cassandra’s native protocol.

+

The driver supports Python 2.7, 3.4, 3.5, 3.6, 3.7 and 3.8.

+

This driver is open source under the +Apache v2 License. +The source code for this driver can be found on GitHub.

+

Scylla Driver is a fork from DataStax Python Driver, including some non-breaking changes for Scylla optimization, with more updates planned.

+
+

Contents

+
+
Installation

How to install the driver.

+
+
Getting Started

A guide through the first steps of connecting to Scylla and executing queries

+
+
Scylla Specific Features

A list of feature available only on scylla-driver

+
+
Execution Profiles

An introduction to a more flexible way of configuring request execution

+
+
Lightweight Transactions (Compare-and-set)

Working with results of conditional requests

+
+
Object Mapper

Introduction to the integrated object mapper, cqlengine

+
+
Performance Notes

Tips for getting good performance.

+
+
Paging Large Queries

Notes on paging large query results

+
+
Security

An overview of the security features of the driver

+
+
Upgrading

A guide to upgrading versions of the driver

+
+
User Defined Types

Working with Scylla’s user-defined types (UDT)

+
+
Working with Dates and Times

Some discussion on the driver’s approach to working with timestamp, date, time types

+
+
Scylla Cloud

Connect to Scylla Cloud

+
+
CHANGELOG

Log of changes to the driver, organized by version.

+
+
Frequently Asked Questions

A collection of Frequently Asked Questions

+
+
API Documentation

The API documentation.

+
+
+
+
+
+
+

Getting Help

+

Visit the FAQ section in this documentation.

+

Please send questions to the Scylla user list.

+
+
+

Reporting Issues

+

Please report any bugs and make any feature requests on the Github project issues

+
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.22.3-scylla/installation.html b/3.22.3-scylla/installation.html new file mode 100644 index 0000000000..ea214085c5 --- /dev/null +++ b/3.22.3-scylla/installation.html @@ -0,0 +1,875 @@ + + + + + + + + + + + + + Installation | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

Installation

+
+

Supported Platforms

+

Python 2.7, 3.4, 3.5, 3.6, 3.7 and 3.8 are supported. Both CPython (the standard Python +implementation) and PyPy are supported and tested.

+

Linux, OSX, and Windows are supported.

+
+
+

Installation through pip

+

pip is the suggested tool for installing +packages. It will handle installing all Python dependencies for the driver at +the same time as the driver itself. To install the driver*:

+
pip install scylla-driver
+
+
+

You can use pip install --pre scylla-driver if you need to install a beta version.

+

*Note: if intending to use optional extensions, install the dependencies first. The driver may need to be reinstalled if dependencies are added after the initial installation.

+
+
+

Verifying your Installation

+

To check if the installation was successful, you can run:

+
python -c 'import cassandra; print cassandra.__version__'
+
+
+

It should print something like “3.22.0”.

+
+
+

(Optional) DataStax Graph

+

The driver provides an optional fluent graph API that depends on Apache TinkerPop (gremlinpython). It is +not installed by default. To be able to build Gremlin traversals, you need to install +the graph requirements:

+
pip install scylla-driver[graph]
+
+
+

See graph_fluent for more details about this API.

+
+
+

(Optional) Compression Support

+

Compression can optionally be used for communication between the driver and +Cassandra. There are currently two supported compression algorithms: +snappy (in Cassandra 1.2+) and LZ4 (only in Cassandra 2.0+). If either is +available for the driver and Cassandra also supports it, it will +be used automatically.

+

For lz4 support:

+
pip install lz4
+
+
+

For snappy support:

+
pip install python-snappy
+
+
+

(If using a Debian Linux derivative such as Ubuntu, it may be easier to +just run apt-get install python-snappy.)

+
+
+

(Optional) Metrics Support

+

The driver has built-in support for capturing Cluster.metrics about +the queries you run. However, the scales library is required to +support this:

+
pip install scales
+
+
+
+

Speeding Up Installation

+

By default, installing the driver through pip uses a pre-compiled, platform-specific wheel when available. +If using a source distribution rather than a wheel, Cython is used to compile certain parts of the driver. +This makes those hot paths faster at runtime, but the Cython compilation +process can take a long time – as long as 10 minutes in some environments.

+

In environments where performance is less important, it may be worth it to +disable Cython as documented below. +You can also use CASS_DRIVER_BUILD_CONCURRENCY to increase the number of +threads used to build the driver and any C extensions:

+
$ # installing from source
+$ CASS_DRIVER_BUILD_CONCURRENCY=8 python setup.py install
+$ # installing from pip
+$ CASS_DRIVER_BUILD_CONCURRENCY=8 pip install scylla-driver
+
+
+
+
+

OSX Installation Error

+

If you’re installing on OSX and have XCode 5.1 installed, you may see an error like this:

+
clang: error: unknown argument: '-mno-fused-madd' [-Wunused-command-line-argument-hard-error-in-future]
+
+
+

To fix this, re-run the installation with an extra compilation flag:

+
ARCHFLAGS=-Wno-error=unused-command-line-argument-hard-error-in-future pip install scylla-driver
+
+
+
+
+
+

Windows Installation Notes

+

Installing the driver with extensions in Windows sometimes presents some challenges. A few notes about common +hang-ups:

+

Setup requires a compiler. When using Python 2, this is as simple as installing this package +(this link is also emitted during install if setuptools is unable to find the resources it needs). Depending on your +system settings, this package may install as a user-specific application. Make sure to install for everyone, or at least +as the user that will be building the Python environment.

+

It is also possible to run the build with your compiler of choice. Just make sure to have your environment setup with +the proper paths. Make sure the compiler target architecture matches the bitness of your Python runtime. +Perhaps the easiest way to do this is to run the build/install from a Visual Studio Command Prompt (a +shortcut installed with Visual Studio that sources the appropriate environment and presents a shell).

+
+
+

Manual Installation

+

You can always install the driver directly from a source checkout or tarball. +When installing manually, ensure the python dependencies are already +installed. You can find the list of dependencies in +requirements.txt.

+

Once the dependencies are installed, simply run:

+
python setup.py install
+
+
+
+
+

(Optional) Non-python Dependencies

+

The driver has several optional features that have non-Python dependencies.

+
+

C Extensions

+

By default, a number of extensions are compiled, providing faster hashing +for token-aware routing with the Murmur3Partitioner, +libev event loop integration, +and Cython optimized extensions.

+

When installing manually through setup.py, you can disable both with +the --no-extensions option, or selectively disable them with +with --no-murmur3, --no-libev, or --no-cython.

+

To compile the extensions, ensure that GCC and the Python headers are available.

+

On Ubuntu and Debian, this can be accomplished by running:

+
$ sudo apt-get install gcc python-dev
+
+
+

On RedHat and RedHat-based systems like CentOS and Fedora:

+
$ sudo yum install gcc python-devel
+
+
+

On OS X, homebrew installations of Python should provide the necessary headers.

+

See Windows Installation Notes for notes on configuring the build environment on Windows.

+
+

Cython-based Extensions

+

By default, this package uses Cython to optimize core modules and build custom extensions. +This is not a hard requirement, but is engaged by default to build extensions offering better performance than the +pure Python implementation.

+

This is a costly build phase, especially in clean environments where the Cython compiler must be built +This build phase can be avoided using the build switch, or an environment variable:

+
python setup.py install --no-cython
+
+
+

Alternatively, an environment variable can be used to switch this option regardless of +context:

+
CASS_DRIVER_NO_CYTHON=1 <your script here>
+- or, to disable all extensions:
+CASS_DRIVER_NO_EXTENSIONS=1 <your script here>
+
+
+

This method is required when using pip, which provides no other way of injecting user options in a single command:

+
CASS_DRIVER_NO_CYTHON=1 pip install scylla-driver
+CASS_DRIVER_NO_CYTHON=1 sudo -E pip install ~/python-driver
+
+
+

The environment variable is the preferred option because it spans all invocations of setup.py, and will +prevent Cython from being materialized as a setup requirement.

+

If your sudo configuration does not allow SETENV, you must push the option flag down via pip. However, pip +applies these options to all dependencies (which break on the custom flag). Therefore, you must first install +dependencies, then use install-option:

+
sudo pip install six futures
+sudo pip install --install-option="--no-cython"
+
+
+
+
+
+

libev support

+

The driver currently uses Python’s asyncore module for its default +event loop. For better performance, libev is also supported through +a C extension.

+

If you’re on Linux, you should be able to install libev +through a package manager. For example, on Debian/Ubuntu:

+
$ sudo apt-get install libev4 libev-dev
+
+
+

On RHEL/CentOS/Fedora:

+
$ sudo yum install libev libev-devel
+
+
+

If you’re on Mac OS X, you should be able to install libev +through Homebrew. For example, on Mac OS X:

+
$ brew install libev
+
+
+

The libev extension is not built for Windows (the build process is complex, and the Windows implementation uses +select anyway).

+

If successful, you should be able to build and install the extension +(just using setup.py build or setup.py install) and then use +the libev event loop by doing the following:

+
>>> from cassandra.io.libevreactor import LibevConnection
+>>> from cassandra.cluster import Cluster
+
+>>> cluster = Cluster()
+>>> cluster.connection_class = LibevConnection
+>>> session = cluster.connect()
+
+
+
+
+
+

(Optional) Configuring SSL

+

Andrew Mussey has published a thorough guide on +Using SSL with the DataStax Python driver.

+
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.22.3-scylla/lwt.html b/3.22.3-scylla/lwt.html new file mode 100644 index 0000000000..bcb4067087 --- /dev/null +++ b/3.22.3-scylla/lwt.html @@ -0,0 +1,734 @@ + + + + + + + + + + + + + Lightweight Transactions (Compare-and-set) | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

Lightweight Transactions (Compare-and-set)

+

Lightweight Transactions (LWTs) are mostly pass-through CQL for the driver. However, +the server returns some specialized results indicating the outcome and optional state +preceding the transaction.

+

For pertinent execution parameters, see Statement.serial_consistency_level.

+

This section discusses working with specialized result sets returned by the server for LWTs, +and how to work with them using the driver.

+
+

Specialized Results

+

The result returned from a LWT request is always a single row result. It will always have +prepended a special column named [applied]. How this value appears in your results depends +on the row factory in use. See below for examples.

+

The value of this [applied] column is boolean value indicating whether or not the transaction was applied. +If True, it is the only column in the result. If False, the additional columns depend on the LWT operation being +executed:

+
    +
  • When using a UPDATE ... IF "col" = ... clause, the result will contain the [applied] column, plus the existing columns +and values for any columns in the IF clause (and thus the value that caused the transaction to fail).

  • +
  • When using INSERT ... IF NOT EXISTS, the result will contain the [applied] column, plus all columns and values +of the existing row that rejected the transaction.

  • +
  • UPDATE .. IF EXISTS never has additional columns, regardless of [applied] status.

  • +
+

How the [applied] column manifests depends on the row factory in use. Considering the following (initially empty) table:

+
CREATE TABLE test.t (
+    k int PRIMARY KEY,
+    v int,
+    x int
+)
+
+
+

… the following sections show the expected result for a number of example statements, using the three base row factories.

+
+

named_tuple_factory (default)

+

The name [applied] is not a valid Python identifier, so the square brackets are actually removed +from the attribute for the resulting namedtuple. The row always has a boolean column applied in position 0:

+
>>> session.execute("INSERT INTO t (k,v) VALUES (0,0) IF NOT EXISTS")
+Row(applied=True)
+
+>>> session.execute("INSERT INTO t (k,v) VALUES (0,0) IF NOT EXISTS")
+Row(applied=False, k=0, v=0, x=None)
+
+>>> session.execute("UPDATE t SET v = 1, x = 2 WHERE k = 0 IF v =0")
+Row(applied=True)
+
+>>> session.execute("UPDATE t SET v = 1, x = 2 WHERE k = 0 IF v =0 AND x = 1")
+Row(applied=False, v=1, x=2)
+
+
+
+
+

tuple_factory

+

This return type does not refer to names, but the boolean value applied is always present in position 0:

+
>>> session.execute("INSERT INTO t (k,v) VALUES (0,0) IF NOT EXISTS")
+(True,)
+
+>>> session.execute("INSERT INTO t (k,v) VALUES (0,0) IF NOT EXISTS")
+(False, 0, 0, None)
+
+>>> session.execute("UPDATE t SET v = 1, x = 2 WHERE k = 0 IF v =0")
+(True,)
+
+>>> session.execute("UPDATE t SET v = 1, x = 2 WHERE k = 0 IF v =0 AND x = 1")
+(False, 1, 2)
+
+
+
+
+

dict_factory

+

The retuned dict contains the [applied] key:

+
>>> session.execute("INSERT INTO t (k,v) VALUES (0,0) IF NOT EXISTS")
+{u'[applied]': True}
+
+>>> session.execute("INSERT INTO t (k,v) VALUES (0,0) IF NOT EXISTS")
+{u'x': 2, u'[applied]': False, u'v': 1}
+
+>>> session.execute("UPDATE t SET v = 1, x = 2 WHERE k = 0 IF v =0")
+{u'x': None, u'[applied]': False, u'k': 0, u'v': 0}
+
+>>> session.execute("UPDATE t SET v = 1, x = 2 WHERE k = 0 IF v =0 AND x = 1")
+{u'[applied]': True}
+
+
+
+
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.22.3-scylla/object_mapper.html b/3.22.3-scylla/object_mapper.html new file mode 100644 index 0000000000..bd6cbb3f82 --- /dev/null +++ b/3.22.3-scylla/object_mapper.html @@ -0,0 +1,731 @@ + + + + + + + + + + + + + Object Mapper | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

Object Mapper

+

cqlengine is the Cassandra CQL 3 Object Mapper packaged with this driver

+

Jump to Getting Started

+
+

Contents

+
+
Upgrade Guide

For migrating projects from legacy cqlengine, to the integrated product

+
+
Models

Examples defining models, and mapping them to tables

+
+
Making Queries

Overview of query sets and filtering

+
+
Batch Queries

Working with batch mutations

+
+
Connections

Working with multiple sessions

+
+
API Documentation

Index of API documentation

+
+
Third party integrations

High-level examples in Celery and uWSGI

+
+
+

Frequently Asked Questions

+
+
+
+
+

Getting Started

+
import uuid
+from cassandra.cqlengine import columns
+from cassandra.cqlengine import connection
+from datetime import datetime
+from cassandra.cqlengine.management import sync_table
+from cassandra.cqlengine.models import Model
+
+#first, define a model
+class ExampleModel(Model):
+    example_id      = columns.UUID(primary_key=True, default=uuid.uuid4)
+    example_type    = columns.Integer(index=True)
+    created_at      = columns.DateTime()
+    description     = columns.Text(required=False)
+
+#next, setup the connection to your cassandra server(s)...
+# see http://datastax.github.io/python-driver/api/cassandra/cluster.html for options
+# the list of hosts will be passed to create a Cluster() instance
+connection.setup(['127.0.0.1'], "cqlengine", protocol_version=3)
+
+#...and create your CQL table
+>>> sync_table(ExampleModel)
+
+#now we can create some rows:
+>>> em1 = ExampleModel.create(example_type=0, description="example1", created_at=datetime.now())
+>>> em2 = ExampleModel.create(example_type=0, description="example2", created_at=datetime.now())
+>>> em3 = ExampleModel.create(example_type=0, description="example3", created_at=datetime.now())
+>>> em4 = ExampleModel.create(example_type=0, description="example4", created_at=datetime.now())
+>>> em5 = ExampleModel.create(example_type=1, description="example5", created_at=datetime.now())
+>>> em6 = ExampleModel.create(example_type=1, description="example6", created_at=datetime.now())
+>>> em7 = ExampleModel.create(example_type=1, description="example7", created_at=datetime.now())
+>>> em8 = ExampleModel.create(example_type=1, description="example8", created_at=datetime.now())
+
+#and now we can run some queries against our table
+>>> ExampleModel.objects.count()
+8
+>>> q = ExampleModel.objects(example_type=1)
+>>> q.count()
+4
+>>> for instance in q:
+>>>     print instance.description
+example5
+example6
+example7
+example8
+
+#here we are applying additional filtering to an existing query
+#query objects are immutable, so calling filter returns a new
+#query object
+>>> q2 = q.filter(example_id=em5.example_id)
+
+>>> q2.count()
+1
+>>> for instance in q2:
+>>>     print instance.description
+example5
+
+
+
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.22.3-scylla/objects.inv b/3.22.3-scylla/objects.inv new file mode 100644 index 0000000000..6be7bc0115 Binary files /dev/null and b/3.22.3-scylla/objects.inv differ diff --git a/3.22.3-scylla/performance.html b/3.22.3-scylla/performance.html new file mode 100644 index 0000000000..0f5b5ff2e6 --- /dev/null +++ b/3.22.3-scylla/performance.html @@ -0,0 +1,685 @@ + + + + + + + + + + + + + Performance Notes | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

Performance Notes

+

The Python driver for Cassandra offers several methods for executing queries. +You can synchronously block for queries to complete using +Session.execute(), you can obtain asynchronous request futures through +Session.execute_async(), and you can attach a callback to the future +with ResponseFuture.add_callback().

+

Examples of multiple request patterns can be found in the benchmark scripts included in the driver project.

+

The choice of execution pattern will depend on the application context. For applications dealing with multiple +requests in a given context, the recommended pattern is to use concurrent asynchronous +requests with callbacks. For many use cases, you don’t need to implement this pattern yourself. +cassandra.concurrent.execute_concurrent() and cassandra.concurrent.execute_concurrent_with_args() +provide this pattern with a synchronous API and tunable concurrency.

+

Due to the GIL and limited concurrency, the driver can become CPU-bound pretty quickly. The sections below +discuss further runtime and design considerations for mitigating this limitation.

+
+

PyPy

+

PyPy is an alternative Python runtime which uses a JIT compiler to +reduce CPU consumption. This leads to a huge improvement in the driver performance, +more than doubling throughput for many workloads.

+
+
+

Cython Extensions

+

Cython is an optimizing compiler and language that can be used to compile the core files and +optional extensions for the driver. Cython is not a strict dependency, but the extensions will be built by default.

+

See Installation for details on controlling this build.

+
+
+

multiprocessing

+

All of the patterns discussed above may be used over multiple processes using the +multiprocessing +module. Multiple processes will scale better than multiple threads, so if high throughput is your goal, +consider this option.

+

Be sure to never share any Cluster, Session, +or ResponseFuture objects across multiple processes. These +objects should all be created after forking the process, not before.

+

For further discussion and simple examples using the driver with multiprocessing, +see this blog post.

+
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.22.3-scylla/py-modindex.html b/3.22.3-scylla/py-modindex.html new file mode 100644 index 0000000000..e1edff9b63 --- /dev/null +++ b/3.22.3-scylla/py-modindex.html @@ -0,0 +1,618 @@ + + + + + + + + + + + + + Python Module Index | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ + + +
+ + + + + +
+ + +
+
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.22.3-scylla/query_paging.html b/3.22.3-scylla/query_paging.html new file mode 100644 index 0000000000..6b32a66bd3 --- /dev/null +++ b/3.22.3-scylla/query_paging.html @@ -0,0 +1,739 @@ + + + + + + + + + + + + + Paging Large Queries | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

Paging Large Queries

+

Cassandra 2.0+ offers support for automatic query paging. Starting with +version 2.0 of the driver, if protocol_version is greater than +2 (it is by default), queries returning large result sets will be +automatically paged.

+
+

Controlling the Page Size

+

By default, Session.default_fetch_size controls how many rows will +be fetched per page. This can be overridden per-query by setting +fetch_size on a Statement. By default, each page +will contain at most 5000 rows.

+
+
+

Handling Paged Results

+

Whenever the number of result rows for are query exceed the page size, an +instance of PagedResult will be returned instead of a normal +list. This class implements the iterator interface, so you can treat +it like a normal iterator over rows:

+
from cassandra.query import SimpleStatement
+query = "SELECT * FROM users"  # users contains 100 rows
+statement = SimpleStatement(query, fetch_size=10)
+for user_row in session.execute(statement):
+    process_user(user_row)
+
+
+

Whenever there are no more rows in the current page, the next page will +be fetched transparently. However, note that it is possible for +an Exception to be raised while fetching the next page, just +like you might see on a normal call to session.execute().

+

If you use Session.execute_async() along with, +ResponseFuture.result(), the first page will be fetched before +result() returns, but latter pages will be +transparently fetched synchronously while iterating the result.

+
+
+

Handling Paged Results with Callbacks

+

If callbacks are attached to a query that returns a paged result, +the callback will be called once per page with a normal list of rows.

+

Use ResponseFuture.has_more_pages and +ResponseFuture.start_fetching_next_page() to continue fetching +pages. For example:

+
class PagedResultHandler(object):
+
+    def __init__(self, future):
+        self.error = None
+        self.finished_event = Event()
+        self.future = future
+        self.future.add_callbacks(
+            callback=self.handle_page,
+            errback=self.handle_err)
+
+    def handle_page(self, rows):
+        for row in rows:
+            process_row(row)
+
+        if self.future.has_more_pages:
+            self.future.start_fetching_next_page()
+        else:
+            self.finished_event.set()
+
+    def handle_error(self, exc):
+        self.error = exc
+        self.finished_event.set()
+
+future = session.execute_async("SELECT * FROM users")
+handler = PagedResultHandler(future)
+handler.finished_event.wait()
+if handler.error:
+    raise handler.error
+
+
+
+
+

Resume Paged Results

+

You can resume the pagination when executing a new query by using the ResultSet.paging_state. This can be useful if you want to provide some stateless pagination capabilities to your application (ie. via http). For example:

+
from cassandra.query import SimpleStatement
+query = "SELECT * FROM users"
+statement = SimpleStatement(query, fetch_size=10)
+results = session.execute(statement)
+
+# save the paging_state somewhere and return current results
+web_session['paging_stage'] = results.paging_state
+
+
+# resume the pagination sometime later...
+statement = SimpleStatement(query, fetch_size=10)
+ps = web_session['paging_state']
+results = session.execute(statement, paging_state=ps)
+
+
+
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.22.3-scylla/scylla_cloud.html b/3.22.3-scylla/scylla_cloud.html new file mode 100644 index 0000000000..93b881fa26 --- /dev/null +++ b/3.22.3-scylla/scylla_cloud.html @@ -0,0 +1,637 @@ + + + + + + + + + + + + + Scylla Cloud | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

Scylla Cloud

+

To connect to a Scylla Cloud cluster, go to the Cluster Connect page, Python example. +For best performance, make sure to use the Scylla Driver.

+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.22.3-scylla/scylla_specific.html b/3.22.3-scylla/scylla_specific.html new file mode 100644 index 0000000000..ba28cf80dd --- /dev/null +++ b/3.22.3-scylla/scylla_specific.html @@ -0,0 +1,726 @@ + + + + + + + + + + + + + Scylla Specific Features | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

Scylla Specific Features

+
+

Shard Awareness

+

scylla-driver is shard aware and contains extensions that work with the TokenAwarePolicy supported by Scylla 2.3 and onwards. Using this policy, the driver can select a connection to a particular shard based on the shard’s token. +As a result, latency is significantly reduced because there is no need to pass data between the shards.

+

Details on the scylla cql protocol extensions +https://github.com/scylladb/scylla/blob/master/docs/protocol-extensions.md

+

For using it you only need to enable TokenAwarePolicy on the Cluster

+
from cassandra.cluster import Cluster
+from cassandra.policies import TokenAwarePolicy, RoundRobinPolicy
+
+cluster = Cluster(load_balancing_policy=TokenAwarePolicy(RoundRobinPolicy()))
+
+
+
+
+

New Cluster Helpers

+
    +
  • cluster.is_shard_aware()

    +

    New method available on Cluster allowing to check whether the remote cluster supports shard awareness (bool)

    +
  • +
+
from cassandra.cluster import Cluster
+
+cluster = Cluster()
+session = cluster.connect()
+
+if cluster.is_shard_aware():
+    print("connected to a scylla cluster")
+
+
+
    +
  • cluster.shard_aware_stats()

    +

    New method available on Cluster allowing to check the status of shard aware connections to all available hosts (dict)

    +
  • +
+
from cassandra.cluster import Cluster
+
+cluster = Cluster()
+session = cluster.connect()
+
+stats = cluster.shard_aware_stats()
+if all([v["shards_count"] == v["connected"] for v in stats.values()]):
+    print("successfully connected to all shards of all scylla nodes")
+
+
+
+
+

New Table Attributes

+
    +
  • in_memory flag

    +

    New flag available on TableMetadata.options to indicate that it is an In Memory table

    +
  • +
+
+

Note

+

in memory tables is a feature existing only in Scylla Enterprise

+
+
from cassandra.cluster import Cluster
+
+cluster = Cluster()
+session = cluster.connect()
+session.execute("""
+    CREATE KEYSPACE IF NOT EXISTS keyspace1
+    WITH replication = {'class': 'SimpleStrategy', 'replication_factor': '1'};
+""")
+
+session.execute("""
+    CREATE TABLE IF NOT EXISTS keyspace1.standard1 (
+        key blob PRIMARY KEY,
+        "C0" blob
+    ) WITH in_memory=true AND compaction={'class': 'InMemoryCompactionStrategy'}
+""")
+
+cluster.refresh_table_metadata("keyspace1", "standard1")
+assert cluster.metadata.keyspaces["keyspace1"].tables["standard1"].options["in_memory"] == True
+
+
+
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.22.3-scylla/search.html b/3.22.3-scylla/search.html new file mode 100644 index 0000000000..588fc48cb8 --- /dev/null +++ b/3.22.3-scylla/search.html @@ -0,0 +1,621 @@ + + + + + + + + + + + + + Search | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + + + + + +
+ + + + + +
+ + +
+
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.22.3-scylla/searchindex.js b/3.22.3-scylla/searchindex.js new file mode 100644 index 0000000000..930137ed64 --- /dev/null +++ b/3.22.3-scylla/searchindex.js @@ -0,0 +1 @@ +Search.setIndex({docnames:["CHANGELOG","api/cassandra","api/cassandra/auth","api/cassandra/cluster","api/cassandra/concurrent","api/cassandra/connection","api/cassandra/cqlengine/columns","api/cassandra/cqlengine/connection","api/cassandra/cqlengine/management","api/cassandra/cqlengine/models","api/cassandra/cqlengine/query","api/cassandra/cqlengine/usertype","api/cassandra/datastax/graph/fluent/index","api/cassandra/datastax/graph/fluent/predicates","api/cassandra/datastax/graph/fluent/query","api/cassandra/datastax/graph/index","api/cassandra/decoder","api/cassandra/encoder","api/cassandra/graph","api/cassandra/io/asyncioreactor","api/cassandra/io/asyncorereactor","api/cassandra/io/eventletreactor","api/cassandra/io/geventreactor","api/cassandra/io/libevreactor","api/cassandra/io/twistedreactor","api/cassandra/metadata","api/cassandra/metrics","api/cassandra/policies","api/cassandra/pool","api/cassandra/protocol","api/cassandra/query","api/cassandra/timestamps","api/cassandra/util","api/index","cqlengine/batches","cqlengine/connections","cqlengine/faq","cqlengine/models","cqlengine/queryset","cqlengine/third_party","cqlengine/upgrade_guide","dates_and_times","execution_profiles","faq","getting_started","index","installation","lwt","object_mapper","performance","query_paging","scylla_cloud","scylla_specific","security","upgrading","user_defined_types"],envversion:{"sphinx.domains.c":2,"sphinx.domains.changeset":1,"sphinx.domains.citation":1,"sphinx.domains.cpp":4,"sphinx.domains.index":1,"sphinx.domains.javascript":2,"sphinx.domains.math":2,"sphinx.domains.python":3,"sphinx.domains.rst":2,"sphinx.domains.std":2,"sphinx.ext.todo":2,sphinx:56},filenames:["CHANGELOG.rst","api/cassandra.rst","api/cassandra/auth.rst","api/cassandra/cluster.rst","api/cassandra/concurrent.rst","api/cassandra/connection.rst","api/cassandra/cqlengine/columns.rst","api/cassandra/cqlengine/connection.rst","api/cassandra/cqlengine/management.rst","api/cassandra/cqlengine/models.rst","api/cassandra/cqlengine/query.rst","api/cassandra/cqlengine/usertype.rst","api/cassandra/datastax/graph/fluent/index.rst","api/cassandra/datastax/graph/fluent/predicates.rst","api/cassandra/datastax/graph/fluent/query.rst","api/cassandra/datastax/graph/index.rst","api/cassandra/decoder.rst","api/cassandra/encoder.rst","api/cassandra/graph.rst","api/cassandra/io/asyncioreactor.rst","api/cassandra/io/asyncorereactor.rst","api/cassandra/io/eventletreactor.rst","api/cassandra/io/geventreactor.rst","api/cassandra/io/libevreactor.rst","api/cassandra/io/twistedreactor.rst","api/cassandra/metadata.rst","api/cassandra/metrics.rst","api/cassandra/policies.rst","api/cassandra/pool.rst","api/cassandra/protocol.rst","api/cassandra/query.rst","api/cassandra/timestamps.rst","api/cassandra/util.rst","api/index.rst","cqlengine/batches.rst","cqlengine/connections.rst","cqlengine/faq.rst","cqlengine/models.rst","cqlengine/queryset.rst","cqlengine/third_party.rst","cqlengine/upgrade_guide.rst","dates_and_times.rst","execution_profiles.rst","faq.rst","getting_started.rst","index.rst","installation.rst","lwt.rst","object_mapper.rst","performance.rst","query_paging.rst","scylla_cloud.rst","scylla_specific.rst","security.rst","upgrading.rst","user_defined_types.rst"],objects:{"":[[1,0,0,"-","cassandra"]],"cassandra.AlreadyExists":[[1,2,1,"","keyspace"],[1,2,1,"","table"]],"cassandra.ConsistencyLevel":[[1,2,1,"","ALL"],[1,2,1,"","ANY"],[1,2,1,"","EACH_QUORUM"],[1,2,1,"","LOCAL_ONE"],[1,2,1,"","LOCAL_QUORUM"],[1,2,1,"","LOCAL_SERIAL"],[1,2,1,"","ONE"],[1,2,1,"","QUORUM"],[1,2,1,"","SERIAL"],[1,2,1,"","THREE"],[1,2,1,"","TWO"]],"cassandra.CoordinationFailure":[[1,2,1,"","consistency"],[1,2,1,"","error_code_map"],[1,2,1,"","failures"],[1,2,1,"","received_responses"],[1,2,1,"","required_responses"]],"cassandra.FunctionFailure":[[1,2,1,"","arg_types"],[1,2,1,"","function"],[1,2,1,"","keyspace"]],"cassandra.OperationTimedOut":[[1,2,1,"","errors"],[1,2,1,"","last_host"]],"cassandra.ProtocolVersion":[[1,2,1,"","BETA_VERSIONS"],[1,2,1,"","DSE_V1"],[1,2,1,"","DSE_V2"],[1,2,1,"","MAX_SUPPORTED"],[1,2,1,"","MIN_SUPPORTED"],[1,2,1,"","SUPPORTED_VERSIONS"],[1,2,1,"","V1"],[1,2,1,"","V2"],[1,2,1,"","V3"],[1,2,1,"","V4"],[1,2,1,"","V5"],[1,2,1,"","V6"],[1,4,1,"","get_lower_supported"]],"cassandra.ReadFailure":[[1,2,1,"","data_retrieved"]],"cassandra.ReadTimeout":[[1,2,1,"","data_retrieved"]],"cassandra.Timeout":[[1,2,1,"","consistency"],[1,2,1,"","received_responses"],[1,2,1,"","required_responses"]],"cassandra.Unavailable":[[1,2,1,"","alive_replicas"],[1,2,1,"","consistency"],[1,2,1,"","required_replicas"]],"cassandra.UserAggregateDescriptor":[[1,2,1,"","argument_types"],[1,2,1,"","name"],[1,5,1,"","signature"]],"cassandra.UserFunctionDescriptor":[[1,2,1,"","argument_types"],[1,2,1,"","name"],[1,5,1,"","signature"]],"cassandra.WriteFailure":[[1,2,1,"","write_type"]],"cassandra.WriteTimeout":[[1,2,1,"","write_type"]],"cassandra.auth":[[2,3,1,"","AuthProvider"],[2,3,1,"","Authenticator"],[2,3,1,"","PlainTextAuthProvider"],[2,3,1,"","PlainTextAuthenticator"],[2,3,1,"","SaslAuthProvider"],[2,3,1,"","SaslAuthenticator"]],"cassandra.auth.AuthProvider":[[2,4,1,"","new_authenticator"]],"cassandra.auth.Authenticator":[[2,4,1,"","evaluate_challenge"],[2,4,1,"","initial_response"],[2,4,1,"","on_authentication_success"],[2,2,1,"","server_authenticator_class"]],"cassandra.auth.PlainTextAuthProvider":[[2,4,1,"","new_authenticator"]],"cassandra.auth.PlainTextAuthenticator":[[2,4,1,"","evaluate_challenge"]],"cassandra.auth.SaslAuthProvider":[[2,4,1,"","new_authenticator"]],"cassandra.auth.SaslAuthenticator":[[2,4,1,"","evaluate_challenge"],[2,4,1,"","initial_response"]],"cassandra.cluster":[[3,3,1,"","Cluster"],[3,6,1,"","EXEC_PROFILE_DEFAULT"],[3,6,1,"","EXEC_PROFILE_GRAPH_ANALYTICS_DEFAULT"],[3,6,1,"","EXEC_PROFILE_GRAPH_DEFAULT"],[3,6,1,"","EXEC_PROFILE_GRAPH_SYSTEM_DEFAULT"],[3,3,1,"","ExecutionProfile"],[3,3,1,"","GraphAnalyticsExecutionProfile"],[3,3,1,"","GraphExecutionProfile"],[3,1,1,"","NoHostAvailable"],[3,1,1,"","QueryExhausted"],[3,3,1,"","ResponseFuture"],[3,3,1,"","ResultSet"],[3,3,1,"","Session"],[3,1,1,"","UserTypeDoesNotExist"]],"cassandra.cluster.Cluster":[[3,4,1,"","add_execution_profile"],[3,2,1,"","address_translator"],[3,2,1,"","auth_provider"],[3,2,1,"","cloud"],[3,2,1,"","compression"],[3,4,1,"","connect"],[3,2,1,"","connect_timeout"],[3,2,1,"","connection_class"],[3,2,1,"","contact_points"],[3,2,1,"","control_connection_timeout"],[3,2,1,"","conviction_policy_factory"],[3,2,1,"","cql_version"],[3,2,1,"","default_retry_policy"],[3,2,1,"","endpoint_factory"],[3,4,1,"","get_control_connection_host"],[3,4,1,"","get_core_connections_per_host"],[3,4,1,"","get_max_connections_per_host"],[3,4,1,"","get_max_requests_per_connection"],[3,4,1,"","get_min_requests_per_connection"],[3,2,1,"","idle_heartbeat_interval"],[3,2,1,"","idle_heartbeat_timeout"],[3,2,1,"","load_balancing_policy"],[3,2,1,"","max_schema_agreement_wait"],[3,2,1,"","metadata"],[3,2,1,"","metrics"],[3,2,1,"","metrics_enabled"],[3,2,1,"","port"],[3,2,1,"","prepare_on_all_hosts"],[3,2,1,"","protocol_version"],[3,2,1,"","reconnection_policy"],[3,4,1,"","refresh_keyspace_metadata"],[3,4,1,"","refresh_nodes"],[3,4,1,"","refresh_schema_metadata"],[3,4,1,"","refresh_table_metadata"],[3,4,1,"","refresh_user_aggregate_metadata"],[3,4,1,"","refresh_user_function_metadata"],[3,4,1,"","refresh_user_type_metadata"],[3,4,1,"","register_listener"],[3,4,1,"","register_user_type"],[3,2,1,"","reprepare_on_up"],[3,2,1,"","schema_event_refresh_window"],[3,2,1,"","schema_metadata_enabled"],[3,4,1,"","set_core_connections_per_host"],[3,4,1,"","set_max_connections_per_host"],[3,4,1,"","set_max_requests_per_connection"],[3,4,1,"","set_meta_refresh_enabled"],[3,4,1,"","set_min_requests_per_connection"],[3,4,1,"","shutdown"],[3,2,1,"","sockopts"],[3,2,1,"","ssl_context"],[3,2,1,"","ssl_options"],[3,2,1,"","status_event_refresh_window"],[3,2,1,"","timestamp_generator"],[3,2,1,"","token_metadata_enabled"],[3,2,1,"","topology_event_refresh_window"],[3,4,1,"","unregister_listener"]],"cassandra.cluster.ExecutionProfile":[[3,2,1,"","consistency_level"],[3,4,1,"","row_factory"]],"cassandra.cluster.ResponseFuture":[[3,4,1,"","add_callback"],[3,4,1,"","add_errback"],[3,2,1,"","custom_payload"],[3,4,1,"","get_all_query_traces"],[3,4,1,"","get_query_trace"],[3,2,1,"","has_more_pages"],[3,2,1,"","is_schema_agreed"],[3,2,1,"","query"],[3,4,1,"","result"],[3,4,1,"","start_fetching_next_page"],[3,2,1,"","warnings"]],"cassandra.cluster.ResultSet":[[3,4,1,"","all"],[3,5,1,"","current_rows"],[3,4,1,"","fetch_next_page"],[3,4,1,"","get_all_query_traces"],[3,4,1,"","get_query_trace"],[3,5,1,"","has_more_pages"],[3,4,1,"","one"],[3,5,1,"","paging_state"],[3,5,1,"","was_applied"]],"cassandra.cluster.Session":[[3,4,1,"","add_request_init_listener"],[3,2,1,"","client_protocol_handler"],[3,2,1,"","default_consistency_level"],[3,2,1,"","default_fetch_size"],[3,2,1,"","default_serial_consistency_level"],[3,2,1,"","default_timeout"],[3,2,1,"","encoder"],[3,4,1,"","execute"],[3,4,1,"","execute_async"],[3,4,1,"","execute_graph"],[3,4,1,"","execute_graph_async"],[3,4,1,"","execution_profile_clone_update"],[3,4,1,"","get_execution_profile"],[3,4,1,"","prepare"],[3,4,1,"","remove_request_init_listener"],[3,2,1,"","row_factory"],[3,4,1,"","set_keyspace"],[3,4,1,"","shutdown"],[3,2,1,"","timestamp_generator"],[3,2,1,"","use_client_timestamp"]],"cassandra.concurrent":[[4,7,1,"","execute_concurrent"],[4,7,1,"","execute_concurrent_with_args"]],"cassandra.connection":[[5,1,1,"","ConnectionBusy"],[5,1,1,"","ConnectionException"],[5,1,1,"","ConnectionShutdown"],[5,3,1,"","EndPoint"],[5,3,1,"","EndPointFactory"],[5,1,1,"","ProtocolError"],[5,3,1,"","SniEndPoint"],[5,3,1,"","SniEndPointFactory"],[5,3,1,"","UnixSocketEndPoint"]],"cassandra.connection.EndPoint":[[5,5,1,"","address"],[5,5,1,"","port"],[5,4,1,"","resolve"],[5,5,1,"","socket_family"],[5,5,1,"","ssl_options"]],"cassandra.connection.EndPointFactory":[[5,4,1,"","configure"],[5,4,1,"","create"]],"cassandra.cqlengine":[[6,0,0,"-","columns"],[7,0,0,"-","connection"],[8,0,0,"-","management"],[9,0,0,"-","models"],[10,0,0,"-","query"],[11,0,0,"-","usertype"]],"cassandra.cqlengine.columns":[[6,3,1,"","Ascii"],[6,3,1,"","BigInt"],[6,3,1,"","Blob"],[6,3,1,"","Boolean"],[6,2,1,"","Bytes"],[6,3,1,"","Column"],[6,3,1,"","Counter"],[6,3,1,"","Date"],[6,3,1,"","DateTime"],[6,3,1,"","Decimal"],[6,3,1,"","Double"],[6,3,1,"","Float"],[6,3,1,"","Integer"],[6,3,1,"","List"],[6,3,1,"","Map"],[6,3,1,"","Set"],[6,3,1,"","SmallInt"],[6,3,1,"","Text"],[6,3,1,"","Time"],[6,3,1,"","TimeUUID"],[6,3,1,"","TinyInt"],[6,3,1,"","UUID"],[6,3,1,"","UserDefinedType"],[6,3,1,"","VarInt"]],"cassandra.cqlengine.columns.Column":[[6,2,1,"","clustering_order"],[6,2,1,"","custom_index"],[6,2,1,"","db_field"],[6,2,1,"","default"],[6,2,1,"","discriminator_column"],[6,2,1,"","index"],[6,2,1,"","partition_key"],[6,2,1,"","primary_key"],[6,2,1,"","required"],[6,2,1,"","static"]],"cassandra.cqlengine.columns.DateTime":[[6,2,1,"","truncate_microseconds"]],"cassandra.cqlengine.connection":[[7,7,1,"","default"],[7,7,1,"","register_connection"],[7,7,1,"","set_default_connection"],[7,7,1,"","set_session"],[7,7,1,"","setup"],[7,7,1,"","unregister_connection"]],"cassandra.cqlengine.management":[[8,7,1,"","create_keyspace_network_topology"],[8,7,1,"","create_keyspace_simple"],[8,7,1,"","drop_keyspace"],[8,7,1,"","drop_table"],[8,7,1,"","sync_table"],[8,7,1,"","sync_type"]],"cassandra.cqlengine.models":[[9,3,1,"","Model"]],"cassandra.cqlengine.models.Model":[[9,2,1,"","__abstract__"],[9,2,1,"","__compute_routing_key__"],[9,2,1,"","__connection__"],[9,2,1,"","__default_ttl__"],[9,2,1,"","__discriminator_value__"],[9,2,1,"","__keyspace__"],[9,2,1,"","__options__"],[9,2,1,"","__table_name__"],[9,2,1,"","__table_name_case_sensitive__"],[9,4,1,"","all"],[9,4,1,"","batch"],[9,4,1,"","column_family_name"],[9,4,1,"","create"],[9,4,1,"","delete"],[9,4,1,"","filter"],[9,4,1,"","get"],[9,4,1,"","if_exists"],[9,4,1,"","if_not_exists"],[9,4,1,"","iff"],[9,4,1,"","items"],[9,4,1,"","keys"],[9,4,1,"","len"],[9,4,1,"","save"],[9,4,1,"","timeout"],[9,4,1,"","timestamp"],[9,4,1,"","ttl"],[9,4,1,"","update"],[9,4,1,"","using"],[9,4,1,"","values"]],"cassandra.cqlengine.query":[[10,3,1,"","BatchQuery"],[10,3,1,"","ContextQuery"],[10,3,1,"","DoesNotExist"],[10,3,1,"","LWTException"],[10,3,1,"","ModelQuerySet"],[10,3,1,"","MultipleObjectsReturned"]],"cassandra.cqlengine.query.BatchQuery":[[10,4,1,"","add_callback"],[10,4,1,"","add_query"],[10,4,1,"","execute"]],"cassandra.cqlengine.query.ModelQuerySet":[[10,4,1,"","all"],[10,4,1,"","allow_filtering"],[10,4,1,"","batch"],[10,4,1,"","consistency"],[10,4,1,"","count"],[10,4,1,"","defer"],[10,4,1,"","distinct"],[10,4,1,"","fetch_size"],[10,4,1,"","filter"],[10,4,1,"","get"],[10,4,1,"","if_exists"],[10,4,1,"","if_not_exists"],[10,4,1,"","len"],[10,4,1,"","limit"],[10,4,1,"","only"],[10,4,1,"","order_by"],[10,4,1,"","timestamp"],[10,4,1,"","ttl"],[10,4,1,"","update"],[10,4,1,"","using"]],"cassandra.cqlengine.usertype":[[11,3,1,"","UserType"]],"cassandra.cqlengine.usertype.UserType":[[11,2,1,"","__type_name__"]],"cassandra.datastax":[[15,0,0,"-","graph"]],"cassandra.datastax.graph":[[15,3,1,"","Edge"],[15,3,1,"","GraphOptions"],[15,3,1,"","GraphProtocol"],[15,3,1,"","GraphSON1Deserializer"],[15,3,1,"","GraphSON1Serializer"],[15,3,1,"","GraphSON2Reader"],[15,3,1,"","Path"],[15,3,1,"","Result"],[15,3,1,"","SimpleGraphStatement"],[15,3,1,"","Vertex"],[15,3,1,"","VertexProperty"],[12,0,0,"-","fluent"],[15,7,1,"","graph_graphson2_row_factory"],[15,7,1,"","graph_graphson3_row_factory"],[15,7,1,"","graph_object_row_factory"],[15,7,1,"","graph_result_row_factory"],[15,7,1,"","single_object_row_factory"],[15,7,1,"","to_bigint"],[15,7,1,"","to_double"],[15,7,1,"","to_float"],[15,7,1,"","to_int"],[15,7,1,"","to_smallint"]],"cassandra.datastax.graph.GraphOptions":[[15,2,1,"","graph_language"],[15,2,1,"","graph_name"],[15,2,1,"","graph_read_consistency_level"],[15,2,1,"","graph_source"],[15,2,1,"","graph_write_consistency_level"],[15,2,1,"","is_analytics_source"],[15,2,1,"","is_default_source"],[15,2,1,"","is_graph_source"],[15,4,1,"","set_source_analytics"],[15,4,1,"","set_source_default"],[15,4,1,"","set_source_graph"]],"cassandra.datastax.graph.GraphProtocol":[[15,2,1,"","GRAPHSON_1_0"],[15,2,1,"","GRAPHSON_2_0"],[15,2,1,"","GRAPHSON_3_0"]],"cassandra.datastax.graph.GraphSON1Deserializer":[[15,4,1,"","deserialize_bigint"],[15,4,1,"","deserialize_blob"],[15,4,1,"","deserialize_date"],[15,4,1,"","deserialize_decimal"],[15,4,1,"","deserialize_double"],[15,4,1,"","deserialize_duration"],[15,4,1,"","deserialize_float"],[15,4,1,"","deserialize_int"],[15,4,1,"","deserialize_linestring"],[15,4,1,"","deserialize_point"],[15,4,1,"","deserialize_polygon"],[15,4,1,"","deserialize_time"],[15,4,1,"","deserialize_timestamp"],[15,4,1,"","deserialize_uuid"]],"cassandra.datastax.graph.GraphSON2Reader":[[15,4,1,"","deserialize"],[15,4,1,"","read"]],"cassandra.datastax.graph.Path":[[15,2,1,"","labels"],[15,2,1,"","objects"]],"cassandra.datastax.graph.Result":[[15,4,1,"","as_edge"],[15,4,1,"","as_path"],[15,4,1,"","as_vertex"],[15,2,1,"","value"]],"cassandra.datastax.graph.VertexProperty":[[15,2,1,"","label"],[15,2,1,"","properties"],[15,2,1,"","value"]],"cassandra.datastax.graph.fluent":[[12,3,1,"","BaseGraphRowFactory"],[12,3,1,"","DSESessionRemoteGraphConnection"],[12,3,1,"","DseGraph"],[12,2,1,"","graph_traversal_dse_object_row_factory"],[12,2,1,"","graph_traversal_row_factory"],[13,0,0,"-","predicates"],[14,0,0,"-","query"]],"cassandra.datastax.graph.fluent.DseGraph":[[12,2,1,"","DSE_GRAPH_QUERY_LANGUAGE"],[12,4,1,"","batch"],[12,4,1,"","create_execution_profile"],[12,4,1,"","query_from_traversal"],[12,4,1,"","traversal_source"]],"cassandra.datastax.graph.fluent.predicates":[[13,3,1,"","CqlCollection"],[13,3,1,"","Geo"],[13,3,1,"","Search"]],"cassandra.datastax.graph.fluent.predicates.CqlCollection":[[13,4,1,"","contains"],[13,4,1,"","contains_key"],[13,4,1,"","contains_value"],[13,4,1,"","entry_eq"]],"cassandra.datastax.graph.fluent.predicates.Geo":[[13,4,1,"","inside"]],"cassandra.datastax.graph.fluent.predicates.Search":[[13,4,1,"","fuzzy"],[13,4,1,"","phrase"],[13,4,1,"","prefix"],[13,4,1,"","regex"],[13,4,1,"","token"],[13,4,1,"","token_fuzzy"],[13,4,1,"","token_prefix"],[13,4,1,"","token_regex"]],"cassandra.datastax.graph.fluent.query":[[14,3,1,"","TraversalBatch"]],"cassandra.datastax.graph.fluent.query.TraversalBatch":[[14,4,1,"","add"],[14,4,1,"","add_all"],[14,4,1,"","as_graph_statement"],[14,4,1,"","clear"],[14,4,1,"","execute"]],"cassandra.decoder":[[16,7,1,"","dict_factory"],[16,7,1,"","named_tuple_factory"],[16,7,1,"","ordered_dict_factory"],[16,7,1,"","tuple_factory"]],"cassandra.encoder":[[17,3,1,"","Encoder"]],"cassandra.encoder.Encoder":[[17,4,1,"","cql_encode_all_types"],[17,4,1,"","cql_encode_bytes"],[17,4,1,"","cql_encode_date"],[17,4,1,"","cql_encode_datetime"],[17,4,1,"","cql_encode_list_collection"],[17,4,1,"","cql_encode_map_collection"],[17,4,1,"","cql_encode_none"],[17,4,1,"","cql_encode_object"],[17,4,1,"","cql_encode_sequence"],[17,4,1,"","cql_encode_set_collection"],[17,4,1,"","cql_encode_str"],[17,4,1,"","cql_encode_tuple"],[17,4,1,"","cql_encode_unicode"],[17,2,1,"","mapping"]],"cassandra.graph":[[18,3,1,"","Edge"],[18,3,1,"","GraphOptions"],[18,3,1,"","GraphProtocol"],[18,3,1,"","GraphSON1Deserializer"],[18,3,1,"","GraphSON1Serializer"],[18,3,1,"","GraphSON2Reader"],[18,3,1,"","GraphSON3Reader"],[18,3,1,"","Path"],[18,3,1,"","Result"],[18,3,1,"","SimpleGraphStatement"],[18,3,1,"","Vertex"],[18,3,1,"","VertexProperty"],[18,7,1,"","graph_graphson2_row_factory"],[18,7,1,"","graph_graphson3_row_factory"],[18,7,1,"","graph_object_row_factory"],[18,7,1,"","graph_result_row_factory"],[18,7,1,"","single_object_row_factory"],[18,7,1,"","to_bigint"],[18,7,1,"","to_double"],[18,7,1,"","to_float"],[18,7,1,"","to_int"],[18,7,1,"","to_smallint"]],"cassandra.graph.GraphOptions":[[18,2,1,"","graph_language"],[18,2,1,"","graph_name"],[18,2,1,"","graph_read_consistency_level"],[18,2,1,"","graph_source"],[18,2,1,"","graph_write_consistency_level"],[18,2,1,"","is_analytics_source"],[18,2,1,"","is_default_source"],[18,2,1,"","is_graph_source"],[18,4,1,"","set_source_analytics"],[18,4,1,"","set_source_default"],[18,4,1,"","set_source_graph"]],"cassandra.graph.GraphProtocol":[[18,2,1,"","GRAPHSON_1_0"],[18,2,1,"","GRAPHSON_2_0"],[18,2,1,"","GRAPHSON_3_0"]],"cassandra.graph.GraphSON1Deserializer":[[18,4,1,"","deserialize_bigint"],[18,4,1,"","deserialize_blob"],[18,4,1,"","deserialize_date"],[18,4,1,"","deserialize_decimal"],[18,4,1,"","deserialize_double"],[18,4,1,"","deserialize_duration"],[18,4,1,"","deserialize_float"],[18,4,1,"","deserialize_int"],[18,4,1,"","deserialize_linestring"],[18,4,1,"","deserialize_point"],[18,4,1,"","deserialize_polygon"],[18,4,1,"","deserialize_time"],[18,4,1,"","deserialize_timestamp"],[18,4,1,"","deserialize_uuid"]],"cassandra.graph.GraphSON2Reader":[[18,4,1,"","deserialize"],[18,4,1,"","read"]],"cassandra.graph.Path":[[18,2,1,"","labels"],[18,2,1,"","objects"]],"cassandra.graph.Result":[[18,4,1,"","as_edge"],[18,4,1,"","as_path"],[18,4,1,"","as_vertex"],[18,2,1,"","value"]],"cassandra.graph.VertexProperty":[[18,2,1,"","label"],[18,2,1,"","properties"],[18,2,1,"","value"]],"cassandra.io":[[19,0,0,"-","asyncioreactor"],[20,0,0,"-","asyncorereactor"],[21,0,0,"-","eventletreactor"],[22,0,0,"-","geventreactor"],[23,0,0,"-","libevreactor"],[24,0,0,"-","twistedreactor"]],"cassandra.io.asyncioreactor":[[19,3,1,"","AsyncioConnection"]],"cassandra.io.asyncioreactor.AsyncioConnection":[[19,4,1,"","initialize_reactor"]],"cassandra.io.asyncorereactor":[[20,3,1,"","AsyncoreConnection"]],"cassandra.io.asyncorereactor.AsyncoreConnection":[[20,4,1,"","handle_fork"],[20,4,1,"","initialize_reactor"]],"cassandra.io.eventletreactor":[[21,3,1,"","EventletConnection"]],"cassandra.io.eventletreactor.EventletConnection":[[21,4,1,"","initialize_reactor"],[21,4,1,"","service_timeouts"]],"cassandra.io.geventreactor":[[22,3,1,"","GeventConnection"]],"cassandra.io.geventreactor.GeventConnection":[[22,4,1,"","initialize_reactor"]],"cassandra.io.libevreactor":[[23,3,1,"","LibevConnection"]],"cassandra.io.twistedreactor":[[24,3,1,"","TwistedConnection"]],"cassandra.metadata":[[25,3,1,"","Aggregate"],[25,3,1,"","BytesToken"],[25,3,1,"","ColumnMetadata"],[25,3,1,"","EdgeMetadata"],[25,3,1,"","Function"],[25,3,1,"","IndexMetadata"],[25,3,1,"","KeyspaceMetadata"],[25,3,1,"","LocalStrategy"],[25,3,1,"","MD5Token"],[25,3,1,"","MaterializedViewMetadata"],[25,3,1,"","Metadata"],[25,3,1,"","Murmur3Token"],[25,3,1,"","NetworkTopologyStrategy"],[25,2,1,"","ReplicationStrategy"],[25,3,1,"","SimpleStrategy"],[25,3,1,"","TableMetadata"],[25,3,1,"","TableMetadataDSE68"],[25,3,1,"","TableMetadataV3"],[25,3,1,"","Token"],[25,3,1,"","TokenMap"],[25,3,1,"","UserType"],[25,3,1,"","VertexMetadata"],[25,6,1,"","cql_keywords"],[25,6,1,"","cql_keywords_reserved"],[25,6,1,"","cql_keywords_unreserved"],[25,7,1,"","group_keys_by_replica"]],"cassandra.metadata.Aggregate":[[25,4,1,"","as_cql_query"]],"cassandra.metadata.BytesToken":[[25,4,1,"","from_string"]],"cassandra.metadata.Function":[[25,4,1,"","as_cql_query"]],"cassandra.metadata.IndexMetadata":[[25,4,1,"","as_cql_query"],[25,4,1,"","export_as_string"]],"cassandra.metadata.KeyspaceMetadata":[[25,4,1,"","as_cql_query"],[25,4,1,"","export_as_string"]],"cassandra.metadata.LocalStrategy":[[25,4,1,"","export_for_schema"]],"cassandra.metadata.MaterializedViewMetadata":[[25,4,1,"","as_cql_query"]],"cassandra.metadata.Metadata":[[25,4,1,"","add_or_return_host"],[25,4,1,"","all_hosts"],[25,4,1,"","export_schema_as_string"],[25,4,1,"","get_host"],[25,4,1,"","get_host_by_host_id"],[25,4,1,"","get_replicas"]],"cassandra.metadata.NetworkTopologyStrategy":[[25,4,1,"","export_for_schema"]],"cassandra.metadata.SimpleStrategy":[[25,4,1,"","export_for_schema"],[25,5,1,"","replication_factor"]],"cassandra.metadata.TableMetadata":[[25,4,1,"","as_cql_query"],[25,4,1,"","export_as_string"],[25,5,1,"","is_cql_compatible"],[25,5,1,"","primary_key"]],"cassandra.metadata.TableMetadataDSE68":[[25,4,1,"","as_cql_query"]],"cassandra.metadata.TableMetadataV3":[[25,5,1,"","is_cql_compatible"]],"cassandra.metadata.TokenMap":[[25,4,1,"","get_replicas"]],"cassandra.metadata.UserType":[[25,4,1,"","as_cql_query"]],"cassandra.metrics":[[26,3,1,"","Metrics"]],"cassandra.metrics.Metrics":[[26,2,1,"","connected_to"],[26,2,1,"","connection_errors"],[26,4,1,"","get_stats"],[26,2,1,"","ignores"],[26,2,1,"","known_hosts"],[26,2,1,"","open_connections"],[26,2,1,"","other_errors"],[26,2,1,"","read_timeouts"],[26,2,1,"","request_timer"],[26,2,1,"","retries"],[26,4,1,"","set_stats_name"],[26,2,1,"","unavailables"],[26,2,1,"","write_timeouts"]],"cassandra.policies":[[27,3,1,"","AddressTranslator"],[27,3,1,"","ConstantReconnectionPolicy"],[27,3,1,"","ConstantSpeculativeExecutionPolicy"],[27,3,1,"","ConvictionPolicy"],[27,3,1,"","DCAwareRoundRobinPolicy"],[27,3,1,"","DSELoadBalancingPolicy"],[27,3,1,"","DefaultLoadBalancingPolicy"],[27,3,1,"","DowngradingConsistencyRetryPolicy"],[27,3,1,"","EC2MultiRegionTranslator"],[27,3,1,"","ExponentialReconnectionPolicy"],[27,3,1,"","FallthroughRetryPolicy"],[27,3,1,"","HostDistance"],[27,3,1,"","HostFilterPolicy"],[27,3,1,"","IdentityTranslator"],[27,3,1,"","LoadBalancingPolicy"],[27,3,1,"","ReconnectionPolicy"],[27,3,1,"","RetryPolicy"],[27,3,1,"","RoundRobinPolicy"],[27,3,1,"","SimpleConvictionPolicy"],[27,3,1,"","SpeculativeExecutionPolicy"],[27,3,1,"","TokenAwarePolicy"],[27,3,1,"","WhiteListRoundRobinPolicy"],[27,3,1,"","WriteType"]],"cassandra.policies.AddressTranslator":[[27,4,1,"","translate"]],"cassandra.policies.ConstantReconnectionPolicy":[[27,4,1,"","new_schedule"]],"cassandra.policies.ConstantSpeculativeExecutionPolicy":[[27,4,1,"","new_plan"]],"cassandra.policies.ConvictionPolicy":[[27,4,1,"","add_failure"],[27,4,1,"","reset"]],"cassandra.policies.DCAwareRoundRobinPolicy":[[27,4,1,"","distance"],[27,4,1,"","make_query_plan"],[27,4,1,"","on_add"],[27,4,1,"","on_down"],[27,4,1,"","on_remove"],[27,4,1,"","on_up"],[27,4,1,"","populate"]],"cassandra.policies.DefaultLoadBalancingPolicy":[[27,4,1,"","make_query_plan"],[27,4,1,"","populate"]],"cassandra.policies.DowngradingConsistencyRetryPolicy":[[27,4,1,"","on_read_timeout"],[27,4,1,"","on_unavailable"],[27,4,1,"","on_write_timeout"]],"cassandra.policies.EC2MultiRegionTranslator":[[27,4,1,"","translate"]],"cassandra.policies.ExponentialReconnectionPolicy":[[27,4,1,"","new_schedule"]],"cassandra.policies.FallthroughRetryPolicy":[[27,4,1,"","on_read_timeout"],[27,4,1,"","on_request_error"],[27,4,1,"","on_unavailable"],[27,4,1,"","on_write_timeout"]],"cassandra.policies.HostDistance":[[27,2,1,"","IGNORED"],[27,2,1,"","LOCAL"],[27,2,1,"","REMOTE"]],"cassandra.policies.HostFilterPolicy":[[27,4,1,"","distance"],[27,4,1,"","make_query_plan"],[27,4,1,"","predicate"]],"cassandra.policies.IdentityTranslator":[[27,4,1,"","translate"]],"cassandra.policies.LoadBalancingPolicy":[[27,4,1,"","check_supported"],[27,4,1,"","distance"],[27,4,1,"","make_query_plan"],[27,4,1,"","populate"]],"cassandra.policies.ReconnectionPolicy":[[27,4,1,"","new_schedule"]],"cassandra.policies.RetryPolicy":[[27,2,1,"","IGNORE"],[27,2,1,"","RETHROW"],[27,2,1,"","RETRY"],[27,2,1,"","RETRY_NEXT_HOST"],[27,4,1,"","on_read_timeout"],[27,4,1,"","on_request_error"],[27,4,1,"","on_unavailable"],[27,4,1,"","on_write_timeout"]],"cassandra.policies.RoundRobinPolicy":[[27,4,1,"","distance"],[27,4,1,"","make_query_plan"],[27,4,1,"","on_add"],[27,4,1,"","on_down"],[27,4,1,"","on_remove"],[27,4,1,"","on_up"],[27,4,1,"","populate"]],"cassandra.policies.SimpleConvictionPolicy":[[27,4,1,"","add_failure"],[27,4,1,"","reset"]],"cassandra.policies.SpeculativeExecutionPolicy":[[27,4,1,"","new_plan"]],"cassandra.policies.TokenAwarePolicy":[[27,4,1,"","check_supported"],[27,4,1,"","distance"],[27,4,1,"","make_query_plan"],[27,4,1,"","on_add"],[27,4,1,"","on_down"],[27,4,1,"","on_remove"],[27,4,1,"","on_up"],[27,4,1,"","populate"],[27,2,1,"","shuffle_replicas"]],"cassandra.policies.WhiteListRoundRobinPolicy":[[27,4,1,"","distance"],[27,4,1,"","on_add"],[27,4,1,"","on_up"],[27,4,1,"","populate"]],"cassandra.policies.WriteType":[[27,2,1,"","BATCH"],[27,2,1,"","BATCH_LOG"],[27,2,1,"","CAS"],[27,2,1,"","CDC"],[27,2,1,"","COUNTER"],[27,2,1,"","SIMPLE"],[27,2,1,"","UNLOGGED_BATCH"],[27,2,1,"","VIEW"]],"cassandra.pool":[[28,3,1,"","Host"],[28,1,1,"","NoConnectionsAvailable"]],"cassandra.pool.Host":[[28,5,1,"","address"],[28,5,1,"","datacenter"],[28,5,1,"","rack"]],"cassandra.protocol":[[29,3,1,"","_ProtocolHandler"]],"cassandra.protocol._ProtocolHandler":[[29,4,1,"","decode_message"],[29,4,1,"","encode_message"],[29,2,1,"","message_types_by_opcode"]],"cassandra.query":[[30,3,1,"","BatchStatement"],[30,3,1,"","BatchType"],[30,3,1,"","BoundStatement"],[30,3,1,"","PreparedStatement"],[30,3,1,"","QueryTrace"],[30,3,1,"","SimpleStatement"],[30,3,1,"","Statement"],[30,3,1,"","TraceEvent"],[30,1,1,"","TraceUnavailable"],[30,6,1,"","UNSET_VALUE"],[30,3,1,"","ValueSequence"],[30,7,1,"","dict_factory"],[30,7,1,"","named_tuple_factory"],[30,7,1,"","ordered_dict_factory"],[30,7,1,"","tuple_factory"]],"cassandra.query.BatchStatement":[[30,4,1,"","add"],[30,4,1,"","add_all"],[30,4,1,"","clear"],[30,2,1,"","serial_consistency_level"]],"cassandra.query.BatchType":[[30,2,1,"","COUNTER"],[30,2,1,"","LOGGED"],[30,2,1,"","UNLOGGED"]],"cassandra.query.BoundStatement":[[30,4,1,"","bind"],[30,5,1,"","routing_key"]],"cassandra.query.PreparedStatement":[[30,4,1,"","bind"]],"cassandra.query.QueryTrace":[[30,4,1,"","populate"]],"cassandra.query.Statement":[[30,5,1,"","routing_key"],[30,5,1,"","serial_consistency_level"]],"cassandra.timestamps":[[31,3,1,"","MonotonicTimestampGenerator"]],"cassandra.timestamps.MonotonicTimestampGenerator":[[31,4,1,"","_next_timestamp"],[31,2,1,"","warn_on_drift"],[31,2,1,"","warning_interval"],[31,2,1,"","warning_threshold"]],"cassandra.util":[[32,3,1,"","Date"],[32,3,1,"","DateRange"],[32,3,1,"","DateRangeBound"],[32,3,1,"","DateRangePrecision"],[32,3,1,"","Distance"],[32,3,1,"","Duration"],[32,3,1,"","LineString"],[32,3,1,"","OrderedMap"],[32,3,1,"","OrderedMapSerializedKey"],[32,3,1,"","Point"],[32,3,1,"","Polygon"],[32,3,1,"","SortedSet"],[32,3,1,"","Time"],[32,3,1,"","Version"],[32,7,1,"","datetime_from_timestamp"],[32,7,1,"","datetime_from_uuid1"],[32,7,1,"","max_uuid_from_time"],[32,7,1,"","min_uuid_from_time"],[32,7,1,"","ms_timestamp_from_datetime"],[32,2,1,"","sortedset"],[32,7,1,"","unix_time_from_uuid1"],[32,7,1,"","utc_datetime_from_ms_timestamp"],[32,7,1,"","uuid_from_time"]],"cassandra.util.Date":[[32,4,1,"","date"],[32,5,1,"","seconds"]],"cassandra.util.DateRange":[[32,2,1,"","lower_bound"],[32,2,1,"","upper_bound"],[32,2,1,"","value"]],"cassandra.util.DateRangeBound":[[32,4,1,"","datetime"],[32,4,1,"","from_value"],[32,2,1,"","milliseconds"],[32,2,1,"","precision"]],"cassandra.util.Distance":[[32,4,1,"","from_wkt"]],"cassandra.util.LineString":[[32,4,1,"","from_wkt"]],"cassandra.util.Point":[[32,4,1,"","from_wkt"]],"cassandra.util.Polygon":[[32,4,1,"","from_wkt"]],"cassandra.util.Time":[[32,5,1,"","hour"],[32,5,1,"","minute"],[32,5,1,"","nanosecond"],[32,5,1,"","second"],[32,4,1,"","time"]],"cqlengine.queryset":[[38,3,1,"","MaxTimeUUID"],[38,3,1,"","MinTimeUUID"]],cassandra:[[1,1,1,"","AlreadyExists"],[1,1,1,"","AuthenticationFailed"],[1,1,1,"","ConfigurationException"],[1,3,1,"","ConsistencyLevel"],[1,1,1,"","CoordinationFailure"],[1,1,1,"","DriverException"],[1,1,1,"","FunctionFailure"],[1,1,1,"","InvalidRequest"],[1,1,1,"","OperationTimedOut"],[1,3,1,"","ProtocolVersion"],[1,1,1,"","ReadFailure"],[1,1,1,"","ReadTimeout"],[1,1,1,"","RequestExecutionException"],[1,1,1,"","RequestValidationException"],[1,1,1,"","Timeout"],[1,1,1,"","Unauthorized"],[1,1,1,"","Unavailable"],[1,3,1,"","UserAggregateDescriptor"],[1,3,1,"","UserFunctionDescriptor"],[1,1,1,"","WriteFailure"],[1,1,1,"","WriteTimeout"],[1,6,1,"","__version__"],[1,6,1,"","__version_info__"],[2,0,0,"-","auth"],[3,0,0,"-","cluster"],[4,0,0,"-","concurrent"],[5,0,0,"-","connection"],[16,0,0,"-","decoder"],[17,0,0,"-","encoder"],[18,0,0,"-","graph"],[25,0,0,"-","metadata"],[26,0,0,"-","metrics"],[27,0,0,"-","policies"],[28,0,0,"-","pool"],[29,0,0,"-","protocol"],[30,0,0,"-","query"],[31,0,0,"-","timestamps"],[32,0,0,"-","util"]],cqlengine:[[37,0,0,"-","models"],[38,0,0,"-","queryset"]]},objnames:{"0":["py","module","Python module"],"1":["py","exception","Python exception"],"2":["py","attribute","Python attribute"],"3":["py","class","Python class"],"4":["py","method","Python method"],"5":["py","property","Python property"],"6":["py","data","Python data"],"7":["py","function","Python function"]},objtypes:{"0":"py:module","1":"py:exception","2":"py:attribute","3":"py:class","4":"py:method","5":"py:property","6":"py:data","7":"py:function"},terms:{"0":[1,2,3,4,6,9,10,12,14,15,16,18,25,27,30,31,32,34,35,37,38,42,43,44,46,47,48,50,55],"00":43,"000":10,"000077":43,"000153":43,"000309":43,"000368":43,"000422":43,"000480":43,"000669":43,"000755":43,"031ebb0":54,"05":38,"0l":38,"0m":0,"1":[1,2,3,4,6,10,13,15,18,19,25,27,30,31,32,34,35,36,38,42,43,44,46,47,48,52,53,55],"10":[1,3,10,38,44,46,50],"100":[0,4,10,42,50],"1000":[0,4],"1004":0,"1005":0,"1006":0,"1007":0,"1008":0,"1009":0,"101":0,"1012":0,"1013":0,"1015":0,"1016":0,"1017":0,"1018":0,"1019":0,"1020":0,"1021":0,"1023":0,"1024":0,"1026":0,"1027":0,"103":0,"1031":0,"1033":0,"1036":0,"1039":0,"104":0,"1042":0,"1044":0,"1045":0,"1047":0,"1048":0,"105":0,"1051":0,"1054":0,"1056":0,"1057":0,"106":0,"1060":0,"1064":0,"1065":0,"1067":0,"1068":0,"1074":0,"10786":30,"1079":0,"108":0,"1081":0,"1082":0,"1087":0,"1089":0,"109":0,"1090":0,"1091":0,"1093":0,"10l":38,"110":0,"1100":0,"1104":0,"1105":0,"111":[0,36],"111111111111":9,"1117":0,"1118":0,"1119":0,"112":0,"1121":0,"1122":0,"1123":0,"1124":0,"1127":0,"1129":0,"1130":0,"1140":0,"1158":0,"116":0,"1161":0,"1162":0,"1163":0,"1166":0,"1172":0,"1174":0,"1177":0,"1181":0,"1183":0,"1185":0,"1186":0,"1187":0,"1189":0,"119":[0,32],"1192":0,"11e3":44,"11l":38,"120":0,"1203":0,"1204":0,"1205":0,"122":0,"123":[0,3,36,55],"1234":53,"124":0,"125":0,"126":0,"127":[3,25,35,38,42,43,44,48,53],"12l":38,"135":0,"138":0,"13l":38,"14":32,"141":0,"143":0,"144":0,"145":27,"147":0,"148":0,"14l":38,"15":[27,44],"150":0,"151":0,"155":0,"157":0,"159":0,"15l":38,"16":6,"160":0,"163":0,"164":0,"165":0,"166":0,"167":0,"168":[3,44],"16l":38,"17":[38,53],"173":0,"174":0,"175":0,"178":[0,30,54],"179":0,"17l":38,"180":0,"181":0,"182":0,"184":0,"185":0,"186":0,"187":0,"189":0,"18l":38,"190":0,"191":0,"192":[0,3,44],"194":0,"195":0,"196":0,"197":0,"1970":32,"198":0,"1982":38,"19l":38,"1e6":31,"1l":38,"1s":0,"2":[1,2,3,4,6,9,10,12,13,14,15,16,18,25,27,30,32,34,35,36,38,40,42,43,44,45,46,47,50,52,53,55],"20":38,"200":0,"2008":10,"2010":[35,38],"2011":38,"2012":38,"2013":[0,45],"2014":[0,38],"2015":0,"2016":[0,45],"2017":[0,45],"2018":0,"2019":0,"202":0,"2020":0,"204":0,"2048":53,"205":0,"206":0,"207":0,"208":0,"21":[38,54],"210":0,"211":0,"212":0,"213":0,"215":0,"218":0,"219":0,"22":46,"220":0,"222":0,"226":0,"229":0,"23":[0,32],"230":0,"231":0,"234":0,"235":0,"238":0,"239":0,"24":[0,3],"240":0,"241":0,"243":0,"244":0,"245":[0,40],"246":0,"249":0,"25":0,"255":0,"258":0,"26":[0,38],"260":0,"2644bada":44,"266":0,"27":0,"272":0,"273":0,"276":[0,54],"277":0,"278":0,"279":43,"28":0,"280":0,"282":0,"283":0,"284":0,"285":0,"286":0,"288":0,"289":0,"29":0,"291":0,"292":[0,54],"294":0,"295":0,"296":0,"297":0,"298":0,"299":0,"2l":38,"3":[1,2,3,4,6,9,10,15,18,19,25,27,30,31,32,34,36,37,38,45,46,48,52,55],"30":[0,3,38,42,44],"300":0,"301":0,"302":0,"303":0,"305":0,"306":0,"309":0,"31":[0,38],"310":0,"311":0,"313":0,"315":0,"317":0,"318":[0,54],"319":0,"32":6,"322":0,"323":0,"324":0,"325":0,"327":0,"329":0,"331":0,"332":0,"333":0,"334":0,"335":0,"336":0,"337":0,"338":0,"340":32,"341":0,"342":0,"343":0,"344":0,"345":0,"346":0,"347":0,"348":0,"349":0,"351":0,"352":0,"353":0,"354":0,"357":0,"358":0,"360":0,"3600":3,"361":0,"362":0,"363":0,"365":0,"368":[0,54],"370":0,"371":0,"375":0,"377":0,"378":0,"379":0,"381":0,"385":[0,54],"386":0,"392":0,"393":0,"394":0,"395":0,"396":0,"397":0,"398":0,"3l":38,"4":[1,2,3,6,9,10,19,27,29,30,32,42,45,46,48],"400":[0,54],"405":0,"407":0,"408":[0,54],"409":0,"412":0,"413":0,"415":0,"416":0,"419fcdf":54,"42":[3,30,44],"422":[0,54],"429":0,"430":0,"432":0,"433":0,"434":0,"435":0,"438":0,"439":0,"442":0,"443":0,"444":0,"445":0,"447":0,"450":0,"451":0,"452":0,"454":0,"458":0,"459":0,"46":0,"464":0,"466":0,"467":0,"468":0,"469":0,"470":0,"471":0,"473":0,"475":0,"476":0,"477":0,"478":0,"479":0,"48":32,"480":0,"481":0,"482":0,"486":0,"487":0,"489":0,"495":0,"498":0,"4bd5909":54,"4l":38,"4th":0,"5":[1,3,9,10,19,27,38,44,45,46,53],"50":4,"500":10,"5000":[3,10,50],"501":0,"502":0,"503":0,"505":0,"507":0,"508":0,"509":0,"50m":38,"510":0,"512":0,"514":0,"520":0,"521":0,"522":0,"527":0,"528":0,"530":0,"531":0,"532":0,"533":0,"535":0,"537":0,"538":0,"542":0,"547":0,"548":0,"549":0,"550":0,"551":0,"553":0,"555":0,"556":0,"557":0,"559":0,"56":0,"560":0,"561":0,"562":0,"565":0,"566":0,"568":0,"569":0,"570":0,"572":0,"5723":0,"573":0,"574":0,"574266d":54,"576":0,"577":0,"578":0,"579":0,"580":0,"583":0,"584":0,"585":0,"589":0,"59":[0,32],"591":0,"593":0,"595":0,"596":0,"598":0,"599":0,"5l":38,"6":[1,3,6,10,19,25,27,30,38,45,46],"60":0,"600":0,"606":0,"607":0,"608":0,"609":0,"613":0,"614":0,"616":0,"617":0,"618":0,"619":0,"621":0,"622":0,"623":0,"626":0,"628":0,"630":0,"631":0,"636":0,"64":[6,9,27],"640":0,"642":0,"643":0,"644":0,"645":0,"646":0,"647":0,"648":0,"649":0,"65":1,"650":0,"653":0,"655":0,"656":0,"657":0,"66":[1,3],"665":0,"668":0,"669":0,"673":0,"676":0,"678":0,"682":0,"684":0,"686":0,"688":0,"69":0,"690":0,"692":0,"694":0,"697":0,"6l":38,"7":[1,3,6,10,27,45,46],"70":0,"705":0,"706":0,"707":0,"708":0,"709":0,"71":0,"710":0,"714":0,"717":0,"719":0,"720":0,"721":0,"723":0,"724":0,"727":0,"728":0,"729":0,"73":0,"730":0,"732":0,"733":0,"734":0,"735":0,"736":0,"737":0,"739":0,"740":0,"741":0,"742":0,"743":0,"746":0,"747":0,"749":0,"75":0,"750":0,"751":0,"752":0,"754":0,"755":0,"759":0,"75percentil":26,"75th":26,"76":0,"761":0,"762":0,"763":0,"767":0,"768":0,"769":0,"77142":43,"772":0,"773":0,"774":0,"774000":38,"775":0,"778":0,"781":0,"782":0,"785":0,"7857":0,"78723":[3,55],"788":0,"789":0,"79":0,"793":0,"794":0,"798":0,"799":0,"79efe97":54,"7l":38,"8":[1,3,6,17,31,45,46,48],"80":0,"804dea3":0,"805":0,"808":0,"81":0,"810":0,"812":0,"813":0,"814":0,"819":0,"82":0,"827":0,"829":0,"831":0,"833":0,"836":0,"837":0,"838":0,"839":0,"84":0,"840":0,"843":0,"846":0,"848":0,"852c":44,"853":0,"86":0,"860":0,"861":0,"862":0,"863":0,"86400":9,"865":0,"868":0,"872":0,"8733":40,"877":0,"88":0,"885":0,"888":0,"89":0,"891":0,"892":0,"893":0,"894":0,"895":0,"897":0,"89fb":44,"8l":38,"9":[1,9,38],"90":0,"900":0,"901":0,"903":0,"9042":[3,5],"91":0,"910":0,"915":0,"916":0,"92":0,"9223372036854775808":43,"93":0,"932":0,"934":0,"937":0,"940":0,"941":0,"944":0,"945":0,"946":0,"947":0,"95":0,"953":0,"955":0,"95percentil":26,"95th":26,"96":0,"963":0,"96489cc":54,"966":0,"968":0,"97":0,"973":0,"978":0,"98":0,"98percentil":26,"98th":26,"99":[0,26],"992":0,"993":0,"995":0,"996":0,"998":0,"99999":37,"999percentil":26,"99percentil":26,"99th":26,"9d98c8e":54,"9l":38,"9th":26,"abstract":[0,2,6,9,25,30],"boolean":[0,1,6,25,27,44,47],"break":[0,27,45,46,54],"byte":[0,6,38],"case":[0,3,4,8,9,27,32,34,35,44,49,53],"catch":0,"class":[0,1,2,3,5,6,9,10,12,13,14,15,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,40,41,48,50,52,53,54],"default":[0,1,3,6,7,9,10,11,12,14,15,17,18,26,27,29,30,31,34,43,44,46,48,49,50,53],"do":[0,3,4,6,9,17,27,30,37,38,41,44,46,53,54,55],"enum":[10,13,27,32,33],"export":[0,25],"final":[3,44,53],"float":[0,3,6,10,15,18,26,27,37,38,44,54],"function":[0,1,3,8,10,12,17,25,27,29,32,41,44,53,54],"import":[0,2,3,4,6,10,11,12,29,30,34,35,37,38,39,41,42,43,44,46,48,50,52,53],"int":[0,3,6,7,8,15,18,25,31,32,38,44,47,54,55],"long":[0,32,44,46,55],"new":[0,1,2,3,4,6,7,10,21,25,27,30,31,32,34,36,38,39,40,42,44,48,50,53,54,55],"null":[0,10,17,36,38,44],"public":27,"return":[0,1,2,3,4,9,10,12,14,15,18,25,26,27,29,30,31,32,33,37,38,39,41,43,44,47,48,50,53,55],"short":[0,30,37],"static":[0,3,6,10,12,13,32],"super":37,"switch":[0,10,46],"throw":[0,3,30],"true":[0,3,4,6,7,8,9,10,15,18,25,27,30,31,34,35,36,37,38,40,43,44,47,48,52,53],"try":[0,1,3,8,9,27,37,39,41,44],"while":[0,3,27,30,37,40,50,54],A:[0,1,2,3,4,7,8,10,12,13,14,17,18,25,26,27,30,32,35,37,38,44,45,46],AND:[47,52],And:[9,53,54],As:[9,32,40,44,52,55],BY:37,Be:49,But:30,By:[1,3,9,10,27,29,34,38,43,44,46,50,53,54],For:[0,1,3,6,7,9,10,25,27,30,32,36,37,38,40,41,42,44,46,47,48,49,50,51,52,53,54],IF:[0,10,27,30,47,52,54],IN:[17,25,30],INTO:[3,4,30,44,47,55],IS:[0,38,40],If:[0,2,3,4,7,8,9,10,11,14,25,27,30,31,32,34,35,36,37,41,42,44,46,47,50,53,54],In:[0,3,27,29,34,38,40,44,46,52,53,54],It:[0,3,9,21,22,27,32,35,37,38,43,44,46,47,53],NOT:[0,38,47,52],No:45,Not:[0,32],ONE:[1,3,10,40,54],Of:3,On:[0,27,46],One:[10,41],Or:3,Such:27,THERE:40,That:38,The:[0,1,2,3,4,5,6,7,9,10,12,13,14,15,17,18,25,26,27,28,29,30,32,34,36,37,38,40,41,42,44,45,46,47,49,53,54,55],Then:53,There:[1,3,6,8,30,38,44,46,54],These:[0,3,6,9,27,29,30,32,40,41,49,53,54],To:[3,9,11,27,34,35,37,38,40,41,42,43,44,46,51,53,54],WITH:[37,52],Will:9,With:[0,35,43,53,54],_1:53,_2:53,_3:53,_4:53,_:42,__:[10,38,54],__abstract__:9,__compute_routing_key__:9,__connection__:[8,9,35],__contain:38,__default_ttl__:9,__del__:0,__discrimin:54,__discriminator_value__:[6,9,37,40],__ge__:0,__gt:38,__gte:38,__in:[0,38],__init__:[0,3,27,31,50,54,55],__keyspace__:[8,9,35,37],__le__:0,__len__:0,__like:38,__lt:38,__lte:38,__name__:43,__ne__:0,__options__:[9,38],__polymorphic_:54,__polymorphic_key__:40,__repr__:0,__table_name__:[9,37,40],__table_name_case_sensitive__:9,__type_name__:11,__version__:[1,46],__version_info__:1,_connect:0,_dsegraphson2rowfactori:12,_gremlingraphson2rowfactori:12,_messagetyp:29,_metadata:54,_new_tim:21,_next_timestamp:31,_not_set:3,_protocolhand:29,_protocolhandl:29,_replicationstrategi:25,_set_final_except:0,_set_result:0,_timeout_watch:21,a2:10,a2d3a98:54,abil:[0,27,42,54],abl:46,about:[0,3,25,30,37,41,44,46,53,54],abov:[3,29,34,35,41,44,49],absolut:[32,40],accept:[0,3,27,32,40,41],access:[0,3,9,26,30,37,44,54],accommod:[0,41],accomplish:[38,46],accord:[0,3],accordingli:0,account:[0,37],accumul:10,accur:25,acheiv:27,achiev:[27,34,53],acknowledg:27,across:[0,19,20,21,22,27,42,43,49],act:53,activ:[0,3,21,22],actual:[0,1,27,30,38,44,47],ad:[0,1,3,10,21,25,27,30,34,37,38,46,54],add:[0,3,7,8,10,14,27,30,34,54,55],add_al:[14,30],add_callback:[3,10,34,44,49,50],add_collback:0,add_errback:[3,44],add_execution_profil:[3,12,42],add_failur:27,add_or_return_host:25,add_queri:10,add_request_init_listen:3,add_tim:0,addit:[0,3,10,12,29,34,37,38,44,47,48,53,54],addition:[30,37,40,53],additional_write_polici:0,addr:[27,37],address:[0,1,3,5,11,25,28,30,33,37,43,44,53,54,55],address_is_ignor:27,address_transl:3,addresstransl:[0,27],adher:41,adjust:[0,40],advanc:53,advic:3,affect:[3,30,34],after:[0,3,4,10,20,27,30,34,37,38,40,43,44,46,49],afterward:54,ag:[3,30,38,44],against:[0,1,3,9,27,30,37,44,48,53],aggreg:[0,1,3,25],agnost:32,agre:0,agreement:[0,3],ahead:[3,44],aim:[35,42],algorithm:[36,46],alia:[6,12,25,32,40],alias:0,alic:30,align:0,aliv:[1,26,27],alive_replica:[1,27],all:[0,1,3,4,6,8,9,10,17,21,22,25,26,27,28,29,30,35,41,44,46,47,49,52,53,54],all_host:[25,42],all_object:38,allow:[0,3,6,9,10,12,13,27,29,30,31,32,34,36,37,46,52,53,54,55],allow_beta_protocol_vers:29,allow_filt:[10,38],almost:44,along:[3,25,50],alpha:0,alphanumer:0,alreadi:[0,1,3,5,8,35,46],alreadyexist:1,also:[0,3,4,9,10,13,27,30,32,35,37,38,42,43,44,46,53,54],alter:[9,27,37],altern:[3,29,37,40,44,46,49,53],although:[44,54,55],althought:44,alwai:[0,3,15,18,27,41,44,46,47],ambigu:0,among:[1,27],amount:[0,4,27],an:[0,1,2,3,4,5,6,8,9,10,12,13,15,17,18,19,20,21,22,23,24,25,26,27,29,30,31,32,34,35,36,37,38,40,41,42,44,45,46,48,49,50,52,53,54,55],analysi:29,analyt:[0,3,15,18],analyticskeyspac:3,analyticskeyspace_prepar:3,andrew:[46,53],ani:[0,1,3,8,9,10,13,14,17,19,20,21,22,26,27,30,34,37,38,41,43,44,45,46,47,49,53,55],anomali:0,anoth:[27,34,35,38,44,53,54],anymor:[38,54],anyth:[34,41],anywai:46,apach:[38,46,54],api:[0,32,37,41,42,45,46,48,49,53],apollo:0,app:[39,43],appear:47,append:[4,10,25,38,44],appli:[0,3,9,10,14,30,36,41,42,44,46,47,48,55],applic:[0,3,6,27,39,40,41,44,46,49,50,54],approach:[41,45],appropri:[3,37,46,53],april:0,apt:46,ar:[0,1,3,4,6,7,8,9,10,15,18,21,25,26,27,28,29,30,32,34,36,37,40,41,42,43,44,45,46,47,48,50,53],arbitrari:[6,32],archflag:46,architectur:46,arg:[3,4,6,9,10,19,20,21,22,23,27,32,34],arg_typ:1,argument:[0,1,3,4,7,9,10,15,18,27,30,31,32,34,35,44,46,53,54],argument_typ:1,arm:0,around:[0,9,32,40,41,54],arrai:[29,38],arriv:3,as_cql_queri:[0,25],as_edg:[15,18],as_graph_stat:14,as_path:[15,18],as_vertex:[15,18],ascend:[10,38],ascii:[0,6,44],ask:[45,48],assert:[6,36,52],assertionerror:38,assign:[0,6,11,37],associ:[0,3,54],assum:[3,21,22,38,41,53,54],assumpt:41,astimezon:41,async:3,asynchron:[0,3,30,43,49],asyncio:[0,33],asyncioconnect:19,asyncioreactor:33,asyncor:[0,33,46],asyncoreconnect:[0,20],asyncorereactor:[0,33],atexit:0,atlassian:27,atom:[27,30],attach:[0,3,15,18,34,44,49,50],attempt:[0,1,3,4,5,27,34,41,43,44,54],attr_kwarg:3,attribut:[0,3,6,8,9,10,11,15,18,25,27,29,30,31,37,38,40,42,44,47,54,55],attributeerror:0,aug:0,august:0,auth:[0,33,53,54],auth_provid:[2,3,53],authent:[0,1,3,33],authenticationfail:[1,2],author:[1,53],authorization_id:53,authprovid:[0,2,3,53],auto:35,automat:[0,1,3,35,37,38,44,46,50],automobil:[10,35,38],automobile2:10,avail:[0,3,10,30,38,45,46,52,54],avoid:[0,3,27,40,43,46],aw:27,awai:[3,30],awar:[0,3,26,27,41,46,53,54],ayncoreconnect:0,b:[3,4,12,14,15,18,34,35,36,38],back:[0,6,9,32,38],backoff:0,backpressur:0,backup:38,backward:[3,18,25,54],bad:0,badli:0,balanc:[0,3,33,42,54],bar:44,bark_all_night:37,base:[0,1,3,9,12,26,27,29,30,32,37,40,43,44,47,52,53],base_delai:27,basegraphrowfactori:12,basi:[0,54],basic:[0,3,12,37],batch:[0,1,3,9,10,12,14,25,27,33,35,38,48],batch_log:27,batch_obj:10,batch_object:9,batch_r:10,batch_typ:[10,30,34],batchqueri:[0,10,34,36,38],batchstat:[0,1,3,30,54],batchtyp:[0,10,30,34],bb984ee:54,beat_init:39,becam:[0,40],becaus:[0,3,4,15,18,27,30,32,40,41,44,46,52,54],becom:[0,3,8,49,54],been:[0,3,5,9,26,27,30,34,35,40,54],befor:[0,1,3,9,10,27,29,30,40,43,44,49,50,54],begin:[0,10,13,44],behav:32,behavior:[0,3,6,27,44,54],behind:[27,41],being:[0,3,6,26,30,36,42,44,46,47],below:[3,4,10,27,29,36,37,38,40,46,47,49,54],benchmark:[0,49],benefit:54,best:[27,44,51,53],beta5:1,beta:[1,46],beta_vers:1,better:[0,27,46,49],between:[0,2,6,29,30,46,52],bewar:27,beyond:37,big:0,bigint:[6,15,18,44],binari:[0,6,30],binary_typ:29,bind:[0,3,12,30,43,44],bit:[6,32,46],bitmap:29,blacklist:27,blacklist_filter_polici:27,blah:44,blake:[9,38],blank:9,blind:[9,10],blindli:10,blist:0,blob:[0,6,17,44,52],block:[0,3,4,34,44,49],blog:49,bob:[3,30,44],bodi:[0,29],bool:[6,7,8,10,25,44,52],bootstrap:[0,26],bop:0,borrow_connect:0,both:[0,3,38,39,44,46,53],bound:[3,14,30,32,43,49],bound_stmt:3,boundstat:[0,30,44,54],bracket:47,brew:46,broadcast_address:27,broadcast_rpc_address:25,broadcast_rpc_port:25,broken:0,brought:54,brows:27,brute:27,bu:0,bucket_high:9,bucket_low:9,buffer:[0,17,44],bug:[40,45,54],build:[0,25,40,44,46,49],built:[0,32,42,46,49,54],bulk:12,bulkset:0,bump:0,busi:[3,28],bypass:[0,3,8,30],bytearrai:[0,17,44],bytebuff:0,bytecod:12,byteorderedpartition:[0,25],bytesio:0,bytestoken:25,c0:52,c:[0,6,12,25,27,38,53],ca:[0,27,53],ca_cert:53,cach:0,cacreateseri:53,cakei:53,calcul:0,call:[0,2,3,5,9,10,17,19,20,21,22,27,31,34,37,38,41,44,48,50,53],callabl:[6,10,12],callback:[0,3,10,44,49,53],callback_arg:3,callback_kwarg:3,camera:38,can:[0,1,3,4,6,8,9,10,13,14,15,17,18,21,25,27,29,30,31,32,34,35,37,38,39,41,42,43,44,45,46,48,49,50,52,53,54,55],cancel:0,cannon:40,cannot:[0,27,30,32,38,42],capabl:50,captur:[0,46],car:38,cardin:[15,18],care:[3,8],carri:34,cass_driver_build_concurr:46,cass_driver_no_cython:46,cass_driver_no_extens:46,cass_server_vers:0,cass_typ:32,cassandra:[0,33,34,35,36,37,38,39,40,42,43,46,48,49,50,52,53,55],cassandra_init:39,cassandra_vers:0,cast:44,cat:[37,40,53],caus:[0,3,10,26,37,47],caution:[8,37],caveat:27,cc94073:54,cdc:[0,27],cdef:0,ceas:27,ceil:1,celeri:48,cell:43,center:30,cento:[0,46],central:41,cert:53,cert_countri:53,cert_org_nam:53,cert_ou:53,cert_req:53,cert_requir:53,cert_valid:53,certain:[13,27,40,46],certfil:53,certif:[0,53],chain:34,challeng:[2,46],chanc:27,chang:[0,3,6,9,10,25,27,30,31,36,37,38,43,44,45],changelog:45,charact:[0,6,44],charl:30,check:[0,3,9,10,27,37,46,52,54],check_hostnam:[0,53],check_support:27,checkout:46,child:[0,27,43],child_polici:27,choic:[46,49],choos:[15,18,27,54],chosen:3,chunk:0,circuit:0,circumst:0,citi:54,civic:[10,35,38],cl:[0,10,21],clang:46,classic:0,classmethod:[1,9,15,18,19,20,21,22,25,29,32],claus:[0,10,25,37,47,54],clean:[0,39,46,54],cleanup:[0,20],clear:[0,14,27,30],clearer:41,client:[0,1,2,3,8,27,29,41,42,45],client_encryption_opt:53,client_protocol_handl:[3,29],clock:32,clock_seq:32,clone:[3,42],close:[0,3,5],closur:0,cloud:[0,3,27,45],cluster1:35,cluster2:[10,35],cluster3:35,cluster:[0,2,4,5,6,7,9,10,12,15,18,19,20,21,22,25,26,27,29,30,33,35,37,38,39,43,44,46,48,49,51,53,55],cluster_opt:7,clustering_kei:38,clustering_ord:[6,37],clustertest:0,cn:53,code:[0,1,34,39,45,53,54,55],codebas:0,coerc:6,coincid:0,col:[0,47],col_nam:9,collect:[0,3,8,10,25,26,30,32,38,45,54],collis:0,colnam:[3,10,30],column:[0,8,9,10,11,13,17,25,30,33,35,36,37,38,44,47,48,54,55],column_family_nam:9,column_nam:[10,15,18,38],columnmetadata:[25,54],com:[6,10,52,53],combin:[0,3],come:0,comma:44,command:[0,35,46],comment:[9,10,37],comment_id:[10,37],common:[0,40,46,53,54],commun:[0,5,46],compact:[0,9,52],compar:[0,30,32,45],comparison:[0,6],compat:[0,3,18,25,33,54],compil:[0,29,46,49],complain:37,complet:[0,1,2,3,4,11,27,30,34,37,40,43,44,49,53],complex:[0,42,46],compliant:0,compon:[0,10,25,30,32,53],compos:29,composit:[0,30,38],compositetyp:0,compound:6,compress:[0,3,29],compressor:29,compris:[1,29],comput:[0,3,9,43],concern:41,concurr:[0,3,8,30,33,43,44,49],condit:[0,1,3,8,10,30,45],conf:53,config:[0,53],configur:[0,1,2,3,5,7,9,15,18,27,31,42,44,45],configurationexcept:1,confirm:0,conflict:36,confus:[40,54],conn:35,connect:[0,1,2,3,4,8,9,10,11,12,19,20,22,23,24,26,27,30,33,37,38,39,40,42,45,46,48,51,52,53,54,55],connect_timeout:[0,3],connect_to_remote_host:3,connected_to:26,connection_class:[3,46,53],connection_error:26,connection_exc:27,connectionbusi:5,connectionexcept:[0,5],connectionshutdown:5,consensu:1,consid:[0,1,3,18,27,44,47,49,53,54],consider:[37,49],consist:[0,1,3,7,10,27,30,32],consistency_level:[3,15,18,30,42,44],consistencylevel:[0,1,3,7,10,15,18,26,27,30,40,44],consit:0,constant:[0,53],constantreconnectionpolici:[0,27],constantspeculativeexecutionpolici:[0,27,44],constrain:[4,10],constraint:[9,37],construct:[0,9,12,32,41,42,44],constructor:[0,3,6,38],consult:37,consum:[0,4,54],consumpt:[0,49],contact:[0,3,27,44],contact_point:[0,3,7,27,53],contain:[0,3,6,9,10,13,17,27,32,37,38,41,47,50,52],contains_kei:13,contains_valu:13,contend:0,content:[0,10,29],context:[0,3,8,9,10,12,15,18,34,39,46,49,53],contextqueri:[0,10,35],contin:0,continu:[0,2,27,50],continuous_paging_opt:3,contract:[0,29],control:[0,3,4,27,30,40,49,53],control_connection_timeout:3,conveni:[3,15,18,30,38],convent:37,convers:[15,18,40,41,54],convert:[0,13,15,17,18,32,40,41,54],convict:27,conviction_policy_factori:3,convictionpolici:27,coord:32,coordin:[1,3,4,27,32,43],coordinationfailur:1,copi:42,copyright:0,core:[0,3,4,38,40,46,49],core_connect:3,correct:[0,9,41],correctli:[0,3],correspond:[2,4,6,8,37],cost:[0,9,10,38],costli:46,could:[0,10,54],count:[0,9,10,26,27,36,38,48],counter:[0,6,26,27,30,37,44],countri:45,cours:3,cover:[37,43],coverag:0,cpu:[0,4,44,49],cpython:[0,3,46],cql3:[36,38,45],cql:[0,1,6,9,10,11,13,15,17,18,25,30,32,36,37,38,40,41,47,48,52,54,55],cql_cluster:39,cql_encode_all_typ:17,cql_encode_byt:17,cql_encode_d:17,cql_encode_datetim:17,cql_encode_list_collect:17,cql_encode_map_collect:17,cql_encode_non:17,cql_encode_object:17,cql_encode_sequ:17,cql_encode_set_collect:17,cql_encode_str:17,cql_encode_tupl:[17,54],cql_encode_unicod:17,cql_keyword:25,cql_keywords_reserv:25,cql_keywords_unreserv:25,cql_refer:10,cql_session:39,cql_use:6,cql_version:[0,3],cqlcollect:13,cqle:0,cqlengin:[0,33,34,35,36,37,38,39,43,45,48,54],cqlengine_batch:34,cqlengine_test:38,cqlengineexcept:[0,40],cqltype:54,cqluseudt:6,crash:0,creat:[0,1,2,3,5,6,7,8,9,10,12,25,27,30,32,34,35,36,37,38,41,43,44,47,48,49,52,53,54,55],create_default_context:53,create_execution_profil:12,create_keyspac:40,create_keyspace_network_topolog:[8,40],create_keyspace_simpl:[8,40],create_simple_keyspac:35,created_at:[34,48],creation:[0,3,4,25,38],credenti:[0,3,53],credit:44,crt:53,crt_sign:53,crypto:53,csr:53,cstringio:0,cumbersom:41,current:[0,1,3,10,12,26,27,30,31,38,42,43,46,50,54],current_pag:3,current_row:3,custom:[0,1,3,6,10,17,27,30,33,41,42,44,46],custom_index:6,custom_payload:[3,15,18,29,30],cut:0,cute:37,cycl:3,cython:[0,29],cython_protocol_handl:3,cythonprotocolhandl:3,d:[3,6,10,30,41,44],daemon:0,dai:[6,27,32,53],dash:0,data:[0,1,3,9,10,27,30,33,37,38,41,43,44,52,54,55],data_retriev:[1,27],databas:[6,8,9,34,37,38,41,42],datacent:[0,1,27,28],dataset:[0,10,38],datastax:[0,6,10,18,27,44,45,48,53,54],datastream:38,datatyp:0,date:[0,6,17,32,44,45,54],daterang:[0,32],daterangebound:32,daterangeprecis:32,datetim:[0,6,10,17,32,34,36,38,40,41,44,48],datetime_from_timestamp:32,datetime_from_uuid1:32,datetyp:0,david:13,daylight:41,days_from_epoch:32,db:0,db_field:[0,6],dc:[0,3,27,54],dc_name:8,dc_replication_factor:25,dc_replication_map:8,dcawar:0,dcawareloadbalancingpolici:0,dcawareroundrobinpolici:[0,3,27,42],dclocal_read_repair_ch:0,dct:0,dd:[17,32],ddl:0,dead:33,deadlock:[0,4],deal:[0,41,42,49,54],debian:[0,46],debug:[0,3],decemb:0,decid:27,decim:[0,6,10,38,44],decimaltyp:0,decis:[0,26,41],declar:[11,37],decod:[0,3,29,30,33,54],decode_messag:29,decomiss:0,decommiss:[0,27],decompress:29,decompressor:29,decor:0,decrement:6,deem:41,def:[3,27,34,37,39,43,44,50,53,54,55],defacto:41,default_bit:53,default_consistency_level:[0,3,7,42],default_fetch_s:[3,50],default_keyspac:[0,7],default_retry_polici:[3,27,42,43],default_serial_consistency_level:[0,3,42],default_time_to_l:[0,38],default_timeout:[3,42],defaultloadbalancingpolici:[0,27,54],defer:[0,10,27],defici:41,defin:[0,1,2,3,6,8,9,10,15,18,25,27,30,33,35,38,40,42,44,45,48],definit:[0,3,6,29,38,40],defunct:[0,3,5],degre:13,delai:[0,27,44],deldyck:37,delet:[0,8,9,10,27,30,34,38],delete_keyspac:40,deliv:3,deliveri:3,demand:0,demonstr:53,dep:0,depend:[0,2,41,43,47,49],deploy:53,deprec:[3,9,16,27,53],deprecationwarn:[0,54],depth:0,dequ:0,deriv:[32,37,40,42,46,54],derivi:9,desc:37,descend:[10,37,38],describ:[1,27,29,32,38,40,41,53],descript:[0,3,15,18,27,30,34,43,48,53],descriptor:0,deseri:[0,15,18,33,41],deserialize_bigint:[15,18],deserialize_blob:[15,18],deserialize_d:[15,18],deserialize_decim:[15,18],deserialize_doubl:[15,18],deserialize_dur:[15,18],deserialize_float:[15,18],deserialize_int:[15,18],deserialize_linestr:[15,18],deserialize_point:[15,18],deserialize_polygon:[15,18],deserialize_tim:[15,18],deserialize_timestamp:[15,18],deserialize_uuid:[15,18],design:[44,49],desir:[3,10,27,34],despit:10,destroi:0,detail:[0,1,3,9,10,30,37,41,42,43,44,46,49,52,53,54],detect:[0,40],determin:[6,9,27,30,44],determinist:0,dev:46,devel:46,deviat:26,devic:0,dict:[0,1,3,6,7,8,9,12,15,17,18,25,26,29,30,37,44,47,52,53],dict_factori:[0,3,7,16,30,54],dictionari:[0,6],dictlik:32,did:[5,10,27],didn:10,differ:[0,3,10,29,30,32,36,37,38,42,44,53,54],digest:27,dir:0,directli:[3,4,17,29,30,44,46,53],disabl:[0,3,9,10,46],discontinu:0,discourag:3,discov:[0,3,27,44],discrimin:[6,9,37],discriminator_column:[6,37,40],discuss:[3,6,11,30,37,45,47,49],disentangl:0,disk:6,dispos:3,disproportion:27,distanc:[13,27,32],distant:27,distinct:[0,10,15,18],distinct_field:10,distinguish:0,distinguished_nam:53,distribut:[0,27,38,46],distrimin:37,distriminator_column:37,dll:0,dn:27,doc:[0,1,6,10,37,38,41,52,53],document:[0,6,27,32,41,42,45,46,48,53,54],doe:[0,3,10,17,32,34,38,40,44,46,47,55],doesn:[0,31,54],doesnotexist:[0,10],dog:[37,40],dollar:0,don:[0,10,38,44,49,55],done:[0,3,37,41,43,53,54],dont:0,doubl:[0,6,15,18,32,44,49,54],double_precis:[40,54],down:[0,3,33,46],downgrad:[0,27],downgradingconsistencyretrypolici:[0,27,44],drain:0,drift:31,driven:8,driver:[0,1,3,5,7,10,18,26,27,28,29,30,37,38,40,41,44,46,47,48,49,50,51,52,53,55],driverexcept:1,drop:[0,6,8,29],drop_keyspac:[8,40],drop_tabl:8,drope:0,dsa:0,dse:[0,1,3,6,12,14,15,18,32],dse_graph:54,dse_graph_query_languag:12,dse_graph_query_protocol:12,dse_v1:[0,1],dse_v2:1,dsegraph:12,dsegssapiauthprovid:[0,53],dseloadbalancingpolici:[0,27,54],dseplaintextauthprovid:53,dsesessionremotegraphconnect:12,dsl:12,dt:32,due:[0,1,10,26,34,49],duplic:0,durabl:3,durable_writ:8,durat:[0,30,32],durationtyp:0,dure:[0,1,2,3,5,9,40,46],dynam:[0,3],dynamiccompositetyp:0,e0b9a54a6d93:44,e16a073:54,e:[3,8,9,10,12,15,18,27,30,43,46],each:[1,2,3,4,6,9,27,30,36,37,38,41,44,50,54,55],each_quorum:1,eagain:0,eai:0,earlier:[0,21,37],eas:35,easi:[0,37,38],easier:[38,42,46],easiest:[41,46],easili:[0,10,41],eat:37,ec2:0,ec2multiregiontransl:27,ed:0,edg:[0,15,18,25],edgemetadata:25,effect:[0,3,8,34,53],effici:[0,29],effort:[0,40,53],eggleston:9,either:[2,3,15,18,32,37,38,41,45,46],element:[0,3,10,15,18,25,32,38,44],els:[4,39,50],em1:[34,48],em2:[34,48],em3:[34,48],em4:48,em5:48,em6:48,em7:48,em8:48,email:44,emit:[3,40,46],empti:[0,2,3,25,47],en:[6,10],enabl:[0,3,10,44,52,53,54],encod:[0,3,6,15,18,29,33,41],encode_messag:29,encount:[0,3,10],encrypt:[0,53],end:[0,10,34],endian:0,endless:0,endors:45,endpoint:[5,25,27,28,53],endpoint_factori:3,endpoint_or_address:25,endpointfactori:[5,53],enforc:[0,37],engag:46,engin:[0,3],enough:[1,30],ensur:[0,3,4,9,27,39,46,53],enterpris:52,entir:[0,3,4,10,14,25],entiti:0,entri:[10,13,17,54],entry_eq:13,environ:[8,27,46],eof:53,ep:[3,44],epoch:[0,31,32,41],eq:0,equal:[0,3,6,30,38],equival:[9,36,41,44],errback:[0,3,44,50],errback_arg:3,errno:0,error:[0,1,3,4,5,6,10,27,44,50],error_code_map:1,errro:1,escap:[0,17],especi:[0,8,42,46],essenti:38,establish:[3,44],etc:[3,10,26,27,38],evaluate_challeng:2,even:[0,3,7,27,30,41,42,44],evenli:27,event:[0,3,4,21,27,30,33,39,43,44,46,50,53],eventlet:[0,33],eventletconnect:[21,53],eventletreactor:33,everi:[0,27,31,38,39,44],everyon:46,evict:0,evolv:42,ewouldblock:0,exact:2,exactli:[0,27,40],examin:32,exampl:[0,2,3,4,6,9,10,11,25,30,32,35,36,38,40,42,43,44,46,47,48,49,50,51,54,55],example1:48,example2:48,example3:48,example4:48,example5:48,example6:48,example7:48,example8:48,example_id:48,example_mapp:0,example_typ:[34,48],examplemodel:[34,48],exc:[3,50],exce:[0,50],exceed:[3,4],except:[0,3,4,5,6,7,9,10,15,18,27,28,29,30,32,33,34,37,38,39,44,50,53],excess:0,exclud:38,exclus:[7,32,45],exec_profile_default:[3,42,44],exec_profile_graph_analytics_default:3,exec_profile_graph_default:[3,12,54],exec_profile_graph_system_default:3,exect:0,execut:[0,1,3,8,9,10,12,14,15,18,25,27,29,30,33,35,37,38,43,45,47,49,50,52,55],execute_a:[3,53,54],execute_async:[0,3,4,29,43,44,49,50],execute_concurr:[0,4,49],execute_concurrent_with_arg:[4,49],execute_graph:[3,15,18],execute_graph_async:3,execute_on_except:[10,34],execution_profil:[3,4,12,14,42,44],execution_profile_clone_upd:[3,42],executionprofil:[0,3,12,42,44],executionresult:4,executor:0,executor_thread:3,exhaust:[0,27],exist:[0,1,3,8,9,10,27,28,42,47,48,52,54],exit:0,expand:0,expect:[0,5,9,43,47,53,54,55],expens:3,experi:4,experiment:[0,19],expir:3,explain:[0,42],explicit:[0,40,41],explicitli:[0,1,3,10,15,18,34,37,54],explod:42,explor:38,exponenti:[0,27],exponentialreconnectionpolici:[0,3,27],export_as_str:[0,25],export_for_schema:[0,25],export_schema_as_str:25,expos:[0,31,54],express:[4,13,32],extablish:3,extend:30,extens:[0,3,27,41,52],exterior:32,extern:41,extra:[0,25,30,46],extra_deserializer_map:[15,18],extract:[15,18],ey:45,f:3,facilit:29,factor:[0,8,25],factori:[3,12,33,47],fail:[0,1,3,4,7,14,15,18,26,33,34,37,44,47],failur:[0,1,7,9,26,33,34],fairli:37,fall:[0,32],fallback:[10,27,54],fallthroughretrypolici:27,fals:[3,4,6,7,8,9,10,15,18,25,27,30,47,48,53,54],falsei:27,falsi:27,famili:[0,5,9],faq:[43,45],fashion:3,faster:[0,33,46],favor:[27,40,54],feather:45,featur:[12,19,33,38,40,45,46,53],feb:0,februari:0,fedora:46,feedback:0,felcei:13,fetch:[0,3,10,30,38,44,50,54],fetch_next_pag:3,fetch_siz:[0,3,10,15,18,30,50,54],few:[3,44,46],field:[0,3,6,8,9,10,11,30,32,37,38,44,55],fieldnam:6,fierc:37,file:[0,40,49,53],fill:[15,18,30],filter:[0,6,9,27,33,35,48],finalis:1,find:[13,25,41,46],fine:55,finished_ev:50,finit:27,first:[0,3,4,6,7,9,27,36,37,38,40,44,45,46,48,50,53,54],first_nam:[9,37],first_pag:38,first_result:54,first_row:55,five:3,fix:[27,46,53,54],flag:[0,3,6,9,29,37,46,52],flake:0,flask:43,flat:38,flexibl:[0,45],flight:[0,5],fluent:[0,33,46,54],fly:[0,4,9,10,35],fn:[3,10],focu:27,follow:[0,3,26,27,29,34,35,37,40,41,42,44,46,47,53,54],foo:[44,55],food:37,footprint:[4,38],forc:[0,27,53],force_token_rebuild:3,forev:[21,27,30],fork:[0,20,43,45,49],form:[1,17,32,44],format:[0,1,3,17,25,29,30,33,41,44,53,55],formerli:0,forward:[1,27,40],found:[0,10,25,30,45,49,53,54],foundat:45,four:32,fqdn:[0,53],fraction:32,frame:29,free:44,frequent:[27,44,45,48],from:[1,2,3,4,5,6,8,9,10,11,12,15,18,20,25,27,29,30,32,34,35,37,38,39,40,42,43,44,45,46,47,48,50,52,53,55],from_datetim:54,from_kei:0,from_str:25,from_valu:32,from_wkt:32,frozen:[0,32,55],frozenset:44,full:[0,30,54],full_replica:25,fulli:54,functionfailur:1,functon:38,further:[3,4,27,38,43,49,53],furthermor:27,fuse:46,futur:[0,3,6,7,30,31,40,43,44,46,49,50,54],fuzzi:13,g:[0,3,12,15,18,27,30],garbag:[0,54],gc:0,gc_grace_second:9,gcc:46,gen_client_cert:53,gener:[0,1,2,4,27,29,32,33,41,44,53,54],geo:[0,13],geom:0,geomet:0,geometri:[13,32],geospati:0,geounit:13,get:[0,3,8,9,10,25,27,38,46],get_all_query_trac:[3,54],get_control_connection_host:3,get_core_connections_per_host:3,get_credenti:53,get_execution_profil:[0,3],get_host:[0,25],get_host_by_host_id:25,get_lower_support:1,get_max_connections_per_host:3,get_max_requests_per_connect:3,get_min_requests_per_connect:3,get_query_trac:[0,3,43,54],get_replica:[0,25,43],get_stat:26,getstat:26,getter:[15,18],gevent:[0,33],geventconnect:[0,22],geventreactor:[0,33],gil:[0,49],github:[0,45,48,52],give:[3,27,53,55],given:[0,3,10,25,27,28,32,34,38,49],global:[0,7,43],go:[0,40,51],goal:[49,53],goe:0,good:[40,45],got:54,govern:[3,27],gracefulli:0,grant:53,graph:[0,3],graph_fluent:46,graph_graphson2_row_factori:[15,18],graph_graphson3_row_factori:[3,15,18],graph_languag:[15,18],graph_nam:[12,15,18],graph_object_row_factori:[3,15,18],graph_opt:[0,3],graph_protocol:[3,12,14],graph_read_consistency_level:[15,18],graph_result_row_factori:[15,18],graph_sourc:[0,3,15,18],graph_traversal_dse_object_row_factori:12,graph_traversal_row_factori:12,graph_write_consistency_level:[15,18],graphanalyticsexecutionprofil:3,graphexecutionpolici:3,graphexecutionprofil:3,graphopt:[0,15,18],graphprotocol:[3,14,15,18],graphson1:[15,18],graphson1deseri:[15,18],graphson1seri:[15,18],graphson2:[0,15,18],graphson2read:[15,18],graphson3:[0,12,15,18],graphson3read:18,graphson:[0,12,14,15,18],graphson_1_0:[3,15,18],graphson_2_0:[14,15,18],graphson_3_0:[3,15,18],graphsonwrit:14,graphstat:[0,3,14],graphtravers:[12,14],graphtraversalsourc:12,greater:[27,50],greatli:0,greenlet:0,gremlin:[0,3,12,14,15,18,46],gremlinpython:46,greplin:[0,26],groovi:[15,18],group:25,group_keys_by_replica:25,grow:0,gssapi:2,guarante:[0,27,30,54],guard:8,guid:[0,44,45,46,48,53],gx:0,h:[0,43],ha:[0,3,5,10,26,27,30,38,40,41,44,46,47,53,54,55],had:[0,40,54],handl:[0,2,3,9,10,12,29,33,38,39,41,43,44,46],handle_err:50,handle_error:[4,44,50],handle_fork:20,handle_pag:50,handle_result:3,handle_success:44,handle_writ:0,handler:[0,2,10,15,18,27,29,50],handshak:2,hang:[0,46],happen:[0,3,27],hard:46,has_more_pag:[0,3,50],hash:[0,38,46],hashabl:[0,32],hasn:0,have:[0,2,3,4,6,9,10,15,17,18,26,27,34,35,36,37,38,40,42,44,46,47,53,54,55],header:[0,29,46],healthmonitor:0,heap:0,heartbeat:0,help:[0,38,54],here:[3,9,10,34,35,37,38,39,40,41,46,48,53],hex:0,hh:32,high:[0,48,49],higher:[1,3,4,30,53,54],highli:44,highlight:54,hint:1,hit:[3,5],hold:[0,25,29],holder:44,homebrew:[0,46],honda2012:38,honda:[10,35,38],honor:[0,44],hook:[39,43],host1:27,host2:27,host3:27,host:[0,1,2,3,4,7,25,33,35,43,48,52,53,54],host_address:53,host_dist:3,host_id:25,hostconnect:0,hostdist:[0,3,27],hostfilterpolici:[0,27],hostnam:[0,27,53],hoststatelisten:3,hot:46,hour:32,how:[0,1,4,6,9,27,30,38,39,41,42,44,45,47,50,53,54],howev:[0,3,10,30,34,37,38,41,46,47,50,54,55],html:[6,10,38,48],http:[6,10,27,38,48,50,52],huge:49,human:[25,41],i:[8,10,15,18,27,30,38],id:[0,3,4,6,9,10,15,18,29,34,36,37,38,44,53,55],idea:27,ideal:[32,41],idempot:[33,44],identifi:[0,1,37,47],identitytransl:[3,27],idl:0,idle_heartbeat_interv:3,idle_heartbeat_timeout:[0,3],ids_to_fetch:44,ie:[13,50,53],if_exist:[9,10],if_not_exist:[9,10],iff:9,ifnotexistswithcountercolumn:40,ignor:[0,3,8,26,27,29,30,44],ignored_address0:27,ignored_address1:27,imagin:27,immedi:[1,3,34,44],immut:[0,32,48],impact:4,implement:[0,2,3,5,15,18,19,20,21,22,23,24,27,29,32,41,46,49,50,53,54],impli:[30,45],implicit:[0,10,54],implicitli:[3,8,37],importerror:39,impos:37,improv:[0,1,35,49,54],in_memori:52,inbetween:27,includ:[0,3,9,10,25,26,40,45,49,53,54,55],include_keyspac:9,inclus:3,incomplet:0,inconsist:0,incorrect:[0,44],incorrectli:[0,30],increas:[0,27,31,46],increment:6,incur:9,indefinit:0,independ:[32,53],indetermin:3,index:[0,3,6,25,37,38,48,54],indexmetadata:25,indic:[0,1,2,3,6,8,9,10,25,27,38,47,52],individu:3,inet:[0,1,25],inet_address:0,inet_ntop:0,inet_pton:0,infin:0,infinit:[0,27],inflat:29,influenc:27,info:[0,3,33,44],inform:[0,3,5,9,25,27,41],inherit:[0,6,9,11,42],init:[0,3,36,40],initi:[0,2,3,5,6,7,9,15,18,27,29,31,32,35,38,39,44,46,47,53],initial_respons:2,initialize_reactor:[19,20,21,22],inititi:40,inject:[3,42,46],inmemorycompactionstrategi:52,inplac:32,input:[0,30,40,41,42],insanc:41,insensit:9,insert:[0,1,3,4,9,10,30,32,36,37,41,44,47,54,55],insert_stat:55,insert_us:30,insid:[13,34,44],insight:0,inspect:[3,8],instal:[0,40,44,45,49,53],instanc:[0,2,3,6,9,10,13,15,18,25,26,27,30,34,38,44,48,50,53,54,55],instanti:[0,27,29,31,44],instead:[0,3,4,30,38,40,44,50,53,54],instruct:38,insuffici:[0,26],intact:42,integ:[0,6,10,11,13,17,31,32,35,36,37,38,41,48],integer_typ:32,integr:[0,29,40,41,45,46,48,54],intend:[9,31,32,46],intent:40,interact:[3,44],interfac:[0,2,27,50],interior:32,intern:[0,3,10,27,31,32,40,41,54],interpol:55,interpret:[0,30,36,38,54],intrins:41,introduc:[0,19,25,30,37,38,40,42,54,55],introduct:45,intruct:53,intstat:26,inupt:0,inv:[15,18],invalid:[0,1,26,30],invalidparametertypeerror:0,invalidrequest:1,invalidtypeparametererror:0,invit:40,invlabel:[15,18],invoc:46,invok:[0,3,40],involv:[30,38],io:[0,3,4,10,33,46,48,53],ip:[0,3,5,27,28,44,53],ipv4address:0,ipv6:0,ipv6address:0,irc:0,iron:40,is_analytics_sourc:[15,18],is_cql_compat:25,is_default_sourc:[15,18],is_graph_sourc:[15,18],is_idempot:[0,15,18,30,44],is_schema_agre:3,is_seri:0,is_shard_awar:52,is_shutdown:0,is_up:0,isbootstrap:27,isn:[0,9,10],isnotnul:38,isoformat:0,isol:27,issu:[0,2,27,31,32,36,54],item1:17,item2:17,item:[0,4,9,10,15,18,27,30,32,37,38,44],iter:[0,3,25,27,29,30,32,38,50,54],its:[0,2,3,5,9,19,20,23,24,27,30,32,37,42,46,53,54],itself:[46,54],jan:0,januari:0,java:27,jit:49,jitter:[0,27],jk:53,joe:[37,53],john:44,join:0,jon:[10,37,38],json:[3,12,15,18],json_data:[15,18],juli:0,jump:48,junctur:40,june:0,just:[0,3,6,25,27,32,34,37,40,44,46,50,55],k:[34,47,53],keep:[0,27],keepal:0,kei:[0,1,3,6,8,9,10,13,25,26,27,29,30,32,37,38,42,43,44,47,52,53,55],kept:4,kerbero:[0,53],kevin5000:37,kevin:37,key1:17,key2:17,key_typ:6,keyerror:0,keyfil:53,keyout:53,keyspac:[0,1,3,7,8,9,10,11,15,18,25,27,29,30,35,43,44,52,54],keyspace1:52,keyspace_nam:54,keyspacemetadata:[0,25],keystor:53,keystore_password:53,keyword:[0,3,6,7,9,10],kill:0,kimberli:9,kind:[0,27,54],kinit:53,klass:3,know:[3,27,36,54,55],known:[0,15,18,25,40,54],known_host:26,ks1:35,ks2:35,ks:35,ks_name:8,kwarg:[0,3,4,6,7,9,10,12,15,18,19,20,21,22,23,27,32,34,39,53],label:[15,18],lambda:53,languag:[12,15,18,40,45,49],larg:[0,3,4,10,32,38,45,54],largest:36,last:[0,1,3,27,31,38],last_act:3,last_host:1,last_nam:[9,37],lastest:36,latenc:[26,44,52],later:[0,1,9,27,44,50],latest:[0,54],latter:[3,50],layout:25,lazi:0,lazili:29,lazy_connect:[0,7],lazyprotocolhandl:29,lbp:0,lead:[0,34,49,54],leak:0,learn:[30,53],least:[6,26,27,30,35,37,46],leav:[0,3],left:[0,3,4,9,41,54],legaci:[0,6,40,48,53,54],len:[0,9,10,35],length:[6,27,30],less:[0,46],let:[0,3,54],letter:13,level:[0,1,3,4,10,15,18,27,30,33,41,48,53],leveledcompactionstrategi:9,lib:0,libev4:46,libev:[0,33],libevconnect:[3,23,46],libevreactor:[0,3,33,46],libevwrapp:0,librari:[0,19,20,41,46,53],licens:45,lifecycl:2,lightweight:[0,1,10,30,44,45],lighweight:27,like:[0,1,3,4,9,10,15,18,26,27,30,37,38,41,44,46,50,53,55],limit:[0,3,10,30,38,41,49],line:[0,19,44,46],linear:32,lineariz:30,linestr:32,link:[0,41,46],linux:46,list:[0,1,3,4,6,7,8,9,10,13,15,17,18,25,27,29,30,32,35,43,44,45,46,48,50,54],list_col:44,list_column:10,list_column__append:10,list_column__prepend:10,listen:[0,3],listen_address:0,liter:[0,15,17,18,30,41,44,54,55],live:[1,27,43],ll:[38,53],load:[0,3,9,10,15,18,33,37,38,40,42,53,54],load_balancing_polici:[3,27,42,44,52],load_cert_chain:53,load_verify_loc:53,loadbalancingpolici:[0,3,27,42],local:[0,1,3,27,30,41,42,43,44,54],local_dc:[0,27],local_on:[0,1,3,44],local_queri:42,local_quorum:[0,1,44],local_seri:[1,30,44],localhost:[7,10],localstrategi:25,localtim:41,locat:[3,40,53,55],lock:0,locked_execut:42,log:[0,3,8,27,30,31,44,45,54],log_error:3,log_result:3,logentri:34,logger:0,logic:[0,37],logo:45,longer:[0,1,54],look:[13,37,38,53],lookup:[0,25,27],loop:[0,3,4,21,33,44,46,53],lose:0,loss:0,lot:0,low:[15,18,27,33],lower:[1,4,27,32,38,44],lower_bound:32,lowercas:0,lwt:[0,3,9,47],lwtexcept:[0,9,10,40],lz4:[0,46],m:[9,36],mac:[0,46],machin:44,madd:46,made:[1,3,5,27,38,44,54],mai:[0,2,3,4,6,7,27,30,32,37,38,43,44,46,49,53,54],main:[0,3,53,55],maintain:[0,3,30,32,37,54],major:[0,27,42,53,54],make:[0,1,3,10,25,27,37,40,41,42,43,44,45,46,48,51,53,54],make_query_plan:27,make_token_replica_map:0,manag:[0,3,6,9,10,11,28,33,34,37,42,46,48,54],mandatori:[0,3],mani:[0,1,3,4,27,44,49,50,53,54],manifest:[0,43,47],manipul:[0,3],manner:32,manual:[3,9,34],manufactur:[10,35,38],map:[0,1,3,8,10,13,15,17,18,25,29,30,32,33,37,38,44,48,54],map_column:10,map_column__remov:10,map_column__upd:10,mapper:[0,7,40,45],march:0,margin:4,mark:[0,3,5,33,44,45],marker:41,master:[0,3,52],match:[0,3,5,9,10,15,18,25,30,38,40,42,43,44,46,53,54,55],materi:[0,3,4,25,29,46,54],materializedviewmetadata:25,math:0,max:[0,3,5,26,44],max_attempt:[27,44],max_connect:3,max_delai:27,max_length:6,max_request:3,max_schema_agreement_wait:3,max_support:1,max_threshold:9,max_tim:38,max_uuid_from_tim:32,max_wait:[3,30],max_wait_sec:3,max_wait_sec_p:3,maximum:[1,3,6,27,32,38],maxtimeuuid:38,maxyear:[32,41],md5token:25,md:52,mean:[3,9,26,27,38,44],meaningless:38,meant:41,measur:[3,27],mechan:[2,3,27,53],median:26,meet:[26,27,53],member:[32,37],memori:[0,4,38,52,54],mention:[0,41,44],merg:40,mesh:54,messag:[0,1,2,3,5,29],message_types_by_opcod:29,meta:[0,3,37],metadata:[0,3,15,18,27,30,33,42,43,52],method:[0,2,3,9,10,27,29,30,35,36,37,38,41,43,44,46,49,52],metri:26,metric:[0,3,33],metrics_en:3,micro:32,microsecond:[0,31,54],middl:13,might:[0,3,30,50,53],migrat:[48,54],millisecond:[0,17,32,41],millsecond:41,min:[0,26,43],min_length:[0,6],min_request:3,min_support:1,min_threshold:9,min_tim:38,min_uuid_from_tim:32,minim:[3,40,41,44],minimalist:32,minimum:[1,3,6,32,38],mintimeuuid:38,minut:[0,32,46],minyear:[32,41],mismatch:0,misplac:0,miss:[0,27],misspel:13,mistak:40,mitig:49,mix:[0,30],mke:0,mm:[17,32],mmmuuunnn:32,mno:46,mock:0,mode:0,model:[0,3,8,33,38,43,48,54],model__lik:38,modelexcept:40,modelqueryset:10,modern:0,modif:8,modifi:[0,1,8,9,10,32],modul:[0,9,11,18,19,20,40,46,49],monkei:[0,21,22,53],monkey_patch_loop:0,monoton:0,monotonictimestampgener:31,month:32,montonictimestampgener:0,more:[0,3,4,6,9,10,25,27,29,31,38,40,42,44,45,46,49,50,53,54],most:[3,27,30,37,40,41,43,50],mostli:[18,47],move:[0,3,30,54],ms:32,ms_timestamp_from_datetim:32,msg:29,much:[37,41,53,54],multipl:[0,3,10,12,14,15,18,27,34,35,44,48,49,54],multipleobjectsreturn:[0,10],multipli:13,multiprocess:0,multithread:0,murmur3:[0,3,46],murmur3partition:[0,25,46],murmur3token:[0,25],mussei:[46,53],must:[0,1,3,4,10,30,32,37,38,44,46,53,54,55],mutabl:3,mutat:48,mutual:[7,32],mv:27,my:53,my_callback:34,my_graph:12,my_tabl:44,my_user_id:30,mycf:3,mykeyspac:[3,30,44,54,55],mymod:36,mymodel:36,mystery_funct:34,mystorepass:53,mytabl:4,n:10,naiv:[6,41],name:[0,1,3,7,8,9,10,11,12,13,15,18,25,26,27,29,30,34,37,40,44,47,55],named_arg:34,named_tuple_factori:[0,3,16,30,54],namedt:38,namedtupl:[0,3,4,30,37,44,47,54,55],namedtuple_factori:0,nan:[0,32],nanosecond:[6,32,41],nativ:[0,1,15,18,29,37,45],native_transport_address:0,natur:2,necessari:[3,44,46,53],need:[0,1,3,6,12,27,30,32,34,35,36,37,38,39,44,46,49,52,53,54,55],neg:[0,32,38],negoti:2,nest:[0,32],net:27,network:[0,30,44],networktopologystrategi:[0,8,25],never:[0,27,34,47,49,54],neverretrypolici:3,new_authent:2,new_nod:0,new_plan:27,new_schedul:27,newkei:53,newli:[0,25,27],next:[0,3,21,27,42,48,50,53],next_pag:38,ngdg:0,nice:0,nicer:38,no_compact:0,no_valid_replica:25,noconnectionsavail:28,node1:42,node1_profil:42,node1_whitelist:42,node2:42,node2_profil:42,node:[0,1,3,5,25,26,28,30,32,33,44,52,53],node_domain:5,nodesync:0,nodetool:27,nohostavail:[0,3],nomenclatur:54,non:[0,3,6,10,32,33,37,44,45],nonblock:0,none:[0,1,2,3,4,5,6,7,8,9,10,11,12,14,15,17,18,25,26,27,30,32,36,38,39,41,43,44,47,50],nonetyp:0,nonexist:[0,1],normal:[0,3,9,10,12,27,30,32,41,44,50],nose:0,notabl:54,note:[0,3,4,7,8,9,10,19,27,30,32,35,37,38,40,41,42,44,45,50,53,54],noth:[0,25,27],notic:0,notif:0,notifi:3,nov:0,novemb:0,now:[0,31,34,36,38,40,41,44,48],nt:0,nullhandl:0,num:26,number:[0,1,3,4,5,9,10,26,27,40,42,44,46,47,50],numer:[0,41],numpi:29,numpyprotocolhand:29,numpyprotocolhandl:[0,29],o:[44,53],obj:[15,18],object:[0,3,4,12,15,17,18,25,26,27,30,31,32,34,35,36,37,41,42,43,44,45,49,50,54,55],obtain:[3,10,43,49],occur:[1,27,30,34,44,54],oct:0,octob:0,od:32,off:3,offer:[32,46,49,50],offici:[53,54],offset:32,often:37,ok:[27,53],old:[0,10,40],omit:[1,30],on_add:27,on_authentication_success:2,on_down:27,on_read_timeout:27,on_remov:27,on_request_error:[0,27],on_unavail:27,on_up:[0,27],on_write_timeout:[0,27],onc:[3,4,19,20,21,22,27,29,30,34,36,38,46,50],one:[0,1,2,3,6,10,13,26,27,30,32,35,36,37,38,42,44,53,54],ones:[10,40],onli:[0,1,3,4,5,6,7,8,9,10,18,19,27,30,31,34,37,38,40,41,44,45,46,47,52,53,54],onward:52,op:38,opaqu:3,opcod:29,open:[0,2,3,26,27,28,32,45],open_connect:26,openssl:53,oper:[0,1,3,5,8,9,10,15,18,30,32,33,35,44,47,54],operationtimedout:[0,1,3],opertaion:0,oppos:27,optim:[0,45,46,49],option:[0,1,2,3,5,7,9,10,11,12,14,25,29,30,33,38,40,42,44,47,48,49,52,53,54,55],option_map:25,options__contain:38,options_map:25,order:[0,1,4,6,10,25,27,30,32,34,37,41,54],order_bi:[10,38],ordered_dict_factori:[0,3,16,30,54],ordereddict:[0,3,30,32,44],orderedmap:[0,32],orderedmapserializedkei:32,orderedset:0,org:38,organ:45,origin:[0,3,38,54],os:46,oss:[0,27],other:[2,3,6,8,9,15,18,26,27,30,32,38,44,45,46,53,54,55],other_error:26,otherstuff:55,otherwis:[2,3,6,9,27,32,53],ou:53,our:[38,44,48,53],out:[0,1,4,9,27,32,34,36,38,40,41,44,53],outcom:47,output:[0,41],output_password:53,outsid:[0,6,27,32],outv:[15,18],outvlabel:[15,18],over:[3,27,29,38,49,50,53,54],overcount:27,overflow:[0,41],overflowerror:[0,32],overhaul:54,overhead:[0,4,34],overload:[0,1,6,26,27],overrid:[0,3,9,15,18,42,44,54],overridden:[0,3,50],overriden:0,overs:3,overview:[40,41,45,48],overwrit:10,own:[3,9,37,53],owner:37,owner_id:[37,40],pack:[0,30],packag:[0,2,32,41,46,48,53,54],page:[0,1,3,45,51],pagedresult:[0,50,54],pagedresulthandl:50,pagin:[0,38,50],paging_st:[3,50],paging_stag:50,pair:[0,29],panda:29,parallel:0,param:[0,4,13],paramet:[0,3,4,6,7,8,9,10,12,14,15,18,27,29,30,31,32,37,40,47,53,55],parameter:55,parent:[0,20],pars:[0,15,18,29,32,43,44],parser:[0,29],part:[0,8,10,30,35,40,41,46],parti:[2,3,41,48],partial:[0,21,22,30],particular:[0,3,25,27,30,52],particularli:38,partit:[0,6,10,25,27,30,38],partition:0,partition_kei:[6,10,30,38],pass:[0,2,3,4,6,7,9,10,25,29,30,34,36,37,38,39,47,48,52,53,54,55],passin:53,password:[2,53],passwordauthent:[2,53],patch:[0,21,22,41,53],path:[0,15,18,29,46,53],pattern:[37,49],paxo:30,payload:[0,1,3,30,33],peer:[0,5,25],pem:53,pend:0,pending_us:30,pep:0,per:[0,3,4,6,9,10,25,27,35,37,43,44,50,54],percentil:26,perform:[0,1,3,9,10,27,30,33,37,38,45,46,51],perhap:46,period:39,permiss:53,permit:27,persist:[0,15,18,27,41],person:[9,37,38],person_id:37,perspect:[2,27],pertain:3,pertin:47,pet:[37,40],pet_id:[37,40],pet_typ:[37,40],phase:[2,3,30,46],photo_id:[10,37],phrase:13,pick:[36,44],pip:[0,54],pk:[38,44],pk__token:[0,38],pk__token__gt:[0,38],place:[0,40,44,54],placehold:[3,15,18,30,44,55],placement:[0,8],plai:0,plain:53,plaintextauthent:2,plaintextauthprovid:[2,3,53,54],plan:[0,8,27,45],platform:[0,42],pleas:[0,3,6,9,11,27,37,43,45,53],plu:[38,47],plug:39,pluggabl:0,pmfstat:26,point:[0,3,6,26,27,32,41,44,53,54],polic:27,polici:[0,3,33,42,43,44,52,54],poll:[3,30,43],polygon:32,polymorphic_kei:40,pool:[0,1,3,33,54],pool_wait_timeout:3,popul:[0,3,27,30,38],port:[0,3,5,25,44],portion:[30,32],posit:[3,10,30,34,38,44,47,54],possibl:[0,3,9,21,27,31,32,37,38,41,46,50,53,54],post:[0,49],postfork:[39,43],potenti:0,pr:0,practic:44,practiv:10,pre:[0,46],preced:[3,27,34,47],precis:[0,6,17,32,40,41,54],predic:[0,27,33],predict:38,preemptiv:44,preexist:7,prefer:[0,27,41,44,46,54],prefix:[9,11,13],prematur:0,prepar:[0,3,4,27,33,41,43,53,55],prepare_on_all_host:3,prepared_stat:30,preparedstat:[0,3,30,44],preparemessag:0,prepend:[10,47,54],present:[0,7,10,30,41,42,43,46,47,54],preserv:[0,6,9,30,40],presist:37,pretti:49,preval:41,prevent:[0,10,40,44,46],previou:[0,3,53,54],previous:[0,40,42,54],previous_vers:1,price:[10,38],primari:[0,3,6,8,9,10,25,30,37,38,47,52,55],primary_host:27,primary_kei:[6,9,10,25,35,36,37,38,40,48],princip:[0,53],print:[3,9,10,12,30,32,35,37,41,42,43,44,46,48,52,55],prior:0,privat:[0,1,27],probabl:[27,38,53],problem:[0,3,26,43],process:[0,3,4,20,43,44,46,49,53,54],process_row:50,process_us:[3,4,44,50],produc:[2,4,15,18,38],product:[8,48,53,54],profil:[0,3,4,12,14,44,45],profile_long:44,programmat:3,project:[1,40,45,48,49],prompt:[46,53],proof:0,propag:[0,27,30],proper:[0,39,46],properli:[0,3,37,38,44],properti:[0,1,3,5,9,13,15,18,25,27,28,30,32,37],protect:0,protocol:[0,1,3,5,6,12,14,30,33,37,45,52],protocol_tlsv1:53,protocol_vers:[0,1,3,4,29,30,32,37,48,50,53,54,55],protocolerror:5,protocolhandl:[0,29],protocolvers:1,provid:[0,3,12,13,15,18,27,41,42,43,46,49,50,53,54],proxi:5,proxim:13,proxy_address:5,prudent:40,ps:50,publish:[0,46,53],pure:[0,2,27,29,46,53],purpos:[3,6],push:[0,46],py:[0,46],pyopenssl:[0,53],pypi:[0,46],python2:32,python3:0,python:[0,15,17,18,19,20,29,30,32,37,40,41,44,47,48,49,51,53,54,55],pyton:0,pytz:41,q2:48,q:[35,38,48],qop:[2,53],quadrat:0,quantiz:6,queri:[0,1,3,4,6,9,12,15,16,18,25,27,29,32,33,35,37,40,41,42,45,46,48,49,55],query_cl:[3,30],query_from_travers:12,query_str:[15,18,30],queryexhaust:3,queryhandl:[3,29],queryoper:0,queryset:[0,9],querytrac:[0,30,43],question:[45,48],queu:34,quickli:[0,49],quorum:[1,10,27,30,44],quot:[0,17,41],race:0,rack:[0,28],radiu:32,rais:[0,1,2,3,4,5,6,9,10,15,18,27,30,32,34,37,38,40,44,50,54],raise_on_first_error:4,random:[0,27,32,38],randompartition:25,rang:[0,4,10,32,38,41,43],range_request_timeout_in_m:1,rare:0,rather:[0,32,46],raw:6,re:[0,27,30,37,38,39,44,46,53,55],reach:34,reachabl:27,reactor:[0,20,24,43],read:[0,1,6,15,18,26,27,30,32,34,36,43,53],read_inet:0,read_repair:0,read_repair_ch:0,read_request_timeout_in_m:1,read_timeout:26,readabl:25,reader:[12,15,18],readfailur:1,readm:0,readtimeout:[1,44],reason:[1,3,27,41,53],rebuild:[0,3],rebuilt:0,receiv:[0,1,3,27,44],received_respons:[1,27],recent:0,recogn:[15,18],recommend:[0,3,4,27,36,44,49,53,54,55],reconnect:[0,33],reconnection_polici:3,reconnectionpolici:[0,27],reconnector:0,record:[0,6,10,27,38],recreat:[0,25],recurs:0,redhat:46,reduc:[0,3,49,52],redund:40,reevalu:0,ref:0,refactor:[0,41],refer:[0,10,34,40,42,47,54],referenc:3,refresh:[0,3],refresh_:54,refresh_keyspace_metadata:3,refresh_nod:[0,3],refresh_schema:[0,54],refresh_schema_metadata:3,refresh_table_metadata:[3,52],refresh_user_aggregate_metadata:3,refresh_user_function_metadata:3,refresh_user_type_metadata:3,regard:[3,27,32],regardless:[26,27,46,47],regex:13,regist:[0,3,7,12,17,26,34,37,45,54],register_connect:[0,7,35],register_listen:[0,3],register_user_typ:[3,54,55],registr:35,registri:7,regress:0,regular:[13,30,36,38],reilli:44,reinstal:46,reject:47,rel:41,relat:[0,30,38,42],relax:7,releas:[0,9,27,40,42,53,54],release_vers:[43,44],reli:[27,38],reloc:40,remain:[3,20,27,40,42],rememb:44,remot:[0,3,27,52],remoteconnect:12,remov:[0,3,6,8,10,27,30,32,42,47],remove_request_init_listen:3,repair:27,repeat:[27,44],replac:[0,3,6,29,40,53,54],replai:[1,27],replic:[0,3,8,25,40,52],replica:[0,1,8,25,26,27,30,44],replication_factor:[8,25,52],replication_factor_info:25,replicationfactor:25,replicationstrategi:25,report:[0,27],reprepar:0,reprepare_on_up:3,repres:[1,3,5,6,9,15,18,25,26,28,30,31,32,37,38,40,41,54],represent:[0,25,30,32,54],reproduc:0,req:53,req_distinguished_nam:53,request:[0,1,3,4,26,27,38,39,42,44,45,47,49,53,54],request_id:0,request_tim:[0,26],request_timeout:[3,42,44],requestexecutionexcept:1,requestvalidationexcept:1,requir:[0,1,2,3,6,7,19,27,29,30,32,37,38,39,40,44,46,48,53,54],require_client_auth:53,required_replica:[1,27],required_respons:[1,27],reset:27,resolut:[0,32],resolv:[0,3,5,27,36,53],resort:27,resourc:[19,20,21,22,46,53],respect:[0,3,38],respond:[1,2,27,44],respons:[0,1,2,3,27,29,38,44],response_futur:3,responsefutur:[0,3,29,43,44,49,50,54],rest:[27,44],restart:[0,44],resulset:0,result:[0,3,4,9,10,12,15,18,25,26,27,29,30,32,37,38,41,43,44,45,52,55],result_cach:0,result_metadata:29,result_or_exc:4,result_set:3,results_gener:4,results_metadata:0,resultset:[0,3,50,54],resync:9,retain:[0,41],rethrow:27,rethrown:0,retri:[0,7,26,30,33,44],retriev:[1,3,10,30],retry_connect:7,retry_next_host:27,retry_num:27,retry_polici:[0,3,15,18,27,30,42,43,44],retrypolici:[0,3,26,27,30,43],retun:47,reus:[3,14,30],revers:[10,27],review:0,rework:54,rf:[0,1],rhel:46,rich:3,right:[27,30,44],ring:[0,3,27,32,33],risen:53,risk:27,rlac:0,robin:27,robust:[0,41],role:53,root:53,root_ca_base_nam:53,root_cert_pass:53,rootca:53,rotat:27,round:[0,27,32],roundrobinpolici:[27,52],roundtrip:30,rout:[0,3,9,27,43,46],routing_kei:[15,18,27,30,43],row:[0,3,4,5,10,12,29,33,34,37,38,41,42,43,44,47,48,50,54,55],row_factori:[0,3,7,29,30,42,44],row_id:10,row_list:54,rpc:[5,28],rpc_addr:0,rpc_address:[0,42],rsa:53,rule:30,run:[0,9,10,21,27,34,37,39,44,46,48],run_in_executor:0,runtim:[0,46,49],runtimeerror:0,s:[0,1,2,3,6,7,9,10,11,24,27,29,30,32,34,35,36,37,38,39,41,44,45,46,48,52,53,54,55],safe:[0,4],safeti:0,same:[0,3,4,6,7,12,15,18,25,27,30,32,34,35,36,37,38,42,43,44,46,53,54],sasi:38,sasl:[0,2,53],sasl_kwarg:[2,53],saslauthent:[0,2],saslauthprovid:[0,2,53],saslclient:0,satisfi:1,save:[0,9,10,34,35,37,38,41,44,50],scale:[0,26,41,46,49,54],scan:43,scenario:[0,36],schedul:[0,34],schema:[0,3,9,30,33,37,44,54],schema_event_refresh_window:3,schema_metadata_en:3,schema_trigg:0,schemapars:0,scope:[0,3,10],scratch:42,script:[0,40,46,49],scylla:[38,40,46,54],scylladb:52,search:13,second:[0,3,10,26,27,30,31,32,38,41,44],secondari:[0,25,34,38],section:[0,38,40,45,47,49,53,54],secur:[45,54],see:[0,1,3,4,6,9,10,11,13,15,18,27,29,30,32,37,38,41,42,43,44,46,47,48,49,50,53,54],seen:[0,3,27],segment:40,select:[0,3,4,9,10,30,38,42,43,44,46,50,52,53,54,55],select_stat:4,self:[3,15,18,37,50,54,55],semant:[0,3],send:[0,1,2,3,5,27,44,45,54],sensibl:9,sensit:[0,9],sent:[0,1,2,3,29,44],sep:0,separ:[3,53],septemb:0,seq:43,sequenc:[0,3,4,14,17,27,30,32,44],sequenti:0,serd:0,serial:[0,1,3,12,15,18,30,41],serial_consistency_level:[3,15,18,30,42,44,47,54],serializ:3,serv:40,server:[0,1,2,3,9,15,18,25,29,30,33,38,44,47,48,54],server_authenticator_class:2,server_hostnam:53,server_nam:5,server_vers:43,servererror:27,servic:[2,53],service_timeout:21,session:[0,1,4,7,10,12,14,15,18,25,27,29,30,33,35,39,42,43,44,46,47,48,49,50,52,53,55],sesssion:0,set:[0,1,2,3,4,6,7,8,9,10,11,12,13,15,17,18,19,20,21,22,25,26,27,30,32,35,37,38,42,43,45,46,48,50,53,54],set_column:10,set_column__add:10,set_column__remov:10,set_core_connections_per_host:[3,4],set_default_connect:[7,35],set_keyspac:[0,3,27,44,55],set_max_connections_per_host:3,set_max_requests_per_connect:3,set_meta_refresh_en:3,set_min_requests_per_connect:3,set_sess:[0,7],set_source_analyt:[15,18],set_source_default:[15,18],set_source_graph:[15,18],set_stats_nam:26,set_verifi:53,setenv:46,setup:[0,7,10,35,37,38,39,40,44,46,48,53],setuptool:[0,46],sever:[0,38,40,44,46,49],shallow:[3,42],shard_aware_stat:52,shards_count:52,share:[0,3,19,20,21,22,42,49],shed:[15,18],shell:46,shift:41,shortcut:[3,46],should:[0,2,3,4,6,7,8,9,10,15,18,19,20,21,22,25,27,30,31,37,40,42,44,46,49,53,54],should_log:3,shouldn:0,show:[0,8,32,36,38,40,42,47,53],shown:[3,35,37,55],shuffl:38,shuffle_replica:27,shutdown:[0,3,39],side:[0,1,2,3,15,18,27,40],sign:[6,53],signal:39,signatur:[1,3],significantli:[38,52],silent:27,similar:[27,29,34,53],simpl:[0,6,15,18,27,30,38,40,41,44,46,49],simpleconvictionpolici:[3,27],simplegraphstat:[15,18],simpler:54,simplest:[38,44],simplestat:[0,3,15,18,30,44,50],simplestrategi:[8,25,52],simpli:[0,9,17,27,34,37,40,44,46,55],simplifi:[15,18],simultan:42,sinc:[0,9,29,31,32,36,38,41,43,54,55],singl:[0,3,4,6,8,9,10,14,25,27,28,30,32,37,38,40,42,44,46,47,54],single_object_row_factori:[15,18],site:[0,41],situat:[27,34,37],six:[0,46,54],size:[0,3,10,54],sizeti:0,sizetieredcompactionstrategi:9,skip:[0,9],slack:0,sleep:[27,37],slice:[0,3,38],slightli:0,slow:0,smaller:27,smallint:[0,6,15,18,44],smoke:0,snappi:46,snapshot:0,sni:5,sniendpoint:5,sniendpointfactori:5,so:[0,1,3,10,21,25,27,30,37,38,41,42,44,47,48,49,50,53,54],socket:[0,5,53],socket_famili:5,sockopt:3,soft:0,softwar:45,some:[0,1,9,15,18,27,34,37,38,41,44,45,46,47,48,50,53,54,55],some_id2:34,some_id:34,someth:[2,27,37,38,46,53],sometim:[0,10,15,18,27,46,50],somewher:[34,50],sort:[0,4,6,32,38],sortedset:[0,32,54],sourc:[0,3,15,18,45,46],source_elaps:[0,43],span:46,spark:[0,3],spcifi:1,spec:41,special:[0,6,29,37,38,40,43],specif:[0,2,5,13,15,17,18,25,27,40,45,46,54,55],specifi:[0,1,3,6,8,9,10,11,12,27,29,30,32,35,37,38,40,41,42,44,53,54],specul:[0,27],speculative_execution_polici:[3,44],speculativeexecutionpolici:[27,44],speed:3,speedup:38,spell:41,spin:0,split:2,squar:47,ss:32,ssl:[0,5,44],ssl_context:[0,3,44,53],ssl_error_want_read:0,ssl_error_want_writ:0,ssl_opt:53,ssl_option:[0,3,5,53],ssl_version:53,sslcontext:[0,53],sstabl:43,sstable_size_in_mb:9,st:[3,37,55],stabil:0,stabl:0,stale:27,stall:0,standard1:52,standard:[0,19,20,26,38,39,41,44,46,53,54],start:[0,3,34,38,41,45,50,54],start_fetching_next_pag:[3,50],start_tim:3,startup:0,stat:[0,26,52],state:[0,3,10,20,27,34,45,47],stateless:50,statement:[0,3,25,27,33,34,36,41,42,43,47,50,55],statements_and_param:4,statements_and_paramet:4,stats_nam:26,statu:[47,52],status_event_refresh_window:3,stddev:26,stdlib:0,step:[37,45],steroid:38,steve:10,still:[0,15,18,30,34,37,40,42,44,54,55],stmt:0,stop:[4,34],store:[0,1,6,9,30,37,41],str:[7,8,10,17,32,44],straightforward:[37,40,41,54],strategi:[0,40,54],stream:[0,29],stream_id:29,street:[3,11,37,54,55],stress:0,strict:[6,49],strictli:0,string:[0,1,2,3,6,12,13,15,17,18,25,26,27,29,30,32,41,44,53],string_typ:32,strip:0,strong:0,structur:[15,18,25,37],studio:46,stuff:[3,55],style:3,sub:[37,40],subclass:[0,1,2,3,27,30,37,53],submit:[0,43],submit_schema_refresh:54,submodul:[40,54],suboptim:27,subsequ:40,subset:38,substanc:39,substanti:[4,54],succe:[3,27],succeed:0,success:[0,1,2,3,4,10,27,30,44,46],successfulli:[0,52],sudo:46,suffici:27,suggest:[44,46],suit:[0,53],suitabl:[2,17,25,36],superset:25,suppli:[0,3,30,44,53,54],support:[0,1,2,3,8,9,10,12,27,32,34,36,38,41,44,45,50,52,53,54,55],supported_vers:1,suppos:[0,37,53],sure:[0,3,27,37,43,44,46,49,51,53],surfac:0,surround:0,swap:54,sy:0,sync:[9,35,37],sync_schema:0,sync_tabl:[0,8,10,35,37,48],sync_typ:[8,11,37],synch:8,synchron:[0,3,4,8,37,49,50],syntax:[0,10,34,38],syntaxexcept:0,system:[0,5,25,38,42,43,44,46,54],t:[0,9,10,31,37,38,43,44,47,49,53,54,55],tabl:[0,1,3,6,8,25,30,32,33,37,44,47,48,54,55],tablemetadata:[0,25,52,54],tablemetadatadse68:25,tablemetadatav3:25,tag:[0,15,18],take:[0,3,4,8,9,15,18,25,27,35,44,46,53],taken:[15,18,40],tarbal:46,target:[0,3,13,15,18,27,46],task:[0,3,34,39],tear_up_couch:37,technic:40,techniqu:44,tell:55,tenant:41,term:27,tesla2012:38,tesla:[35,38],test2:10,test4:10,test:[0,10,21,22,27,31,35,46,47],test_clone_shared_lbp:0,test_clust:0,test_set_keyspace_twic:0,testifexistsmodel:9,testifnotexistsmodel:9,testmodel:38,testtransactionmodel:9,text:[0,3,6,9,10,11,13,35,36,37,38,40,44,48,54,55],than:[0,1,3,6,10,27,30,31,32,38,42,44,46,49,50,53],thei:[0,1,3,4,6,8,9,10,15,18,27,29,32,34,36,37,38,40,41,54,55],them:[0,3,27,38,40,41,44,46,47,48,54],themselv:[15,18],therefor:[36,38,46],thi:[0,1,2,3,4,5,6,7,8,9,10,11,12,13,15,17,18,19,20,21,22,25,26,27,28,29,30,31,32,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,52,53,54,55],thing:[3,27,38,40,44],third:[2,41,48],thorough:[46,53],those:[0,3,26,27,30,42,46],though:54,thread:[0,3,4,44,46,49],threadpoolexecutor:0,three:[1,27,30,32,44,47],threshold:[0,3],thrift:0,throttl:0,through:[0,2,3,5,7,9,10,15,18,26,27,30,38,44,45,47,49,54,55],throughput:[0,4,49],thrown:34,thu:[10,27,30,47],ticket:53,time:[0,1,2,3,4,6,10,26,27,31,32,37,38,40,44,45,46,54],time__gt:38,time__lt:38,time_arg:32,timedata:9,timedelta:10,timedelta_or_datetim:9,timeout:[0,1,3,9,10,21,26,27,54],timer:[0,21,26],timestamp:[0,1,6,9,10,17,32,33,36,40,44,45],timestamp_gener:3,timestamp_na:41,timestamp_pres:41,timestamp_utc:41,timestamptyp:0,timeuuid:[0,6,10,32,37,44,54],timezon:[0,6,32,41],tinkerpop:[12,46],tinyint:[0,6,44],tip:45,tlsv1_method:53,tmp:42,to_bigint:[15,18],to_doubl:[15,18],to_float:[15,18],to_int:[15,18],to_python:0,to_smallint:[15,18],todo:32,token:[0,2,3,13,27,33,43,46,52],token_fuzzi:13,token_map:0,token_metadata_en:3,token_prefix:13,token_regex:13,token_str:25,tokenawar:0,tokenawarepolici:[0,3,27,42,52],tokenawarerout:9,tokenfun:38,tokenmap:[0,25],toler:0,tolist:12,tombston:[3,36,43],tombstone_compaction_interv:9,tombstone_threshold:9,too:[0,3,27,41],took:1,tool:46,toolkit:29,top:[15,18,27],topo:0,topolog:[0,3,27,33],topology_event_refresh_window:3,total:[3,27],trace:[0,3,33],traceev:30,traceunavail:[3,30],tracing_en:0,track:0,trade:4,trademark:45,traffic:[0,44],trail:0,transact:[0,1,3,12,14,27,30,45],transform:37,transit:0,translat:[33,40,44],transpar:[3,44,50],trap:34,trash:0,travers:[0,12,14,15,18,46],traversal_batch:14,traversal_class:12,traversal_sourc:12,traversalbatch:[12,14],traversalmetr:0,travisci:0,treat:[3,27,30,44,50],tree:3,tri:0,trigger:[0,3,27],truncat:[6,30,32,40],truncate_microsecond:6,truststor:53,truststore_password:53,truthi:27,ts:41,ttl:[0,9,10],ttl_in_sec:9,tunabl:49,tune:0,tupl:[0,1,3,4,9,12,17,25,27,30,38,44,54,55],tuple_factori:[0,3,16,29,30,42,44,54],turn:[3,43],twice:0,twist:[0,33,44],twistedconnect:[24,53],twistedreactor:[33,53],two:[0,1,3,13,27,29,32,38,44,46,53],txt:[0,46],type0:1,type1:1,type:[0,1,3,8,10,15,17,18,25,27,29,30,32,33,34,38,41,45,47],type_model:8,typeerror:[0,15,18],typestr:0,typic:[3,10,27,29,30,31,34,38,42,44],typo:0,tzinfo:41,u:[10,30,37,38,47],ubuntu:46,uda:0,udf:0,udt:[0,3,12,18,37,45],un:[0,30],unabl:[0,27,46],unauthor:[0,1],unavail:[0,1,26,27],uncal:0,unchang:40,unclean:54,uncompar:0,uncomplet:30,uncondit:0,undefinedkeyspaceexcept:40,under:[0,25,27,37,45],underscor:0,understand:53,understood:[3,27],underutil:0,unexpect:27,unexpectedli:0,unfamiliar:38,unhexlifi:0,unicod:[0,17,44],unicodedecodeerror:0,unif:0,unifi:[0,54],unintend:0,union:3,uniqu:[1,6,25,37,42],unit:[0,13,27,45],unix:[0,5,31,32,41],unix_socket_path:5,unix_time_from_uuid1:32,unixsocketendpoint:5,unknown:[0,15,18,46,54],unless:[3,6,27,35,54],unlik:41,unlog:30,unlogged_batch:27,unord:[6,25],unorder:0,unpack:[0,15,18,44],unprepar:55,unrecogn:0,unrecover:5,unreferenc:0,unregist:[0,55],unregister_connect:[7,35],unregister_listen:3,unset:0,unset_valu:30,unspecifi:[0,9],unsupport:0,unsupportedoper:3,until:[0,2,3,4,7,37,43,44],untrust:3,unus:[0,46],unwis:10,up:[0,3,8,13,19,20,21,22,32,33,34,37,38,53,54],updat:[0,1,3,8,9,10,30,32,34,38,40,42,44,45,47],update_view_metadata:0,updatestat:0,upfront:29,upgrad:[45,48,53],upon:[3,37],upper:32,upper_bound:32,uppercas:0,us:[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,35,36,37,38,40,41,43,44,45,46,47,49,50,51,52,53],usag:[0,2,3,4,9,25,27,30,54],use_certificate_fil:53,use_client_timestamp:[0,1,3,54],use_list_t:6,use_privatekey_fil:53,use_set_t:6,used_hosts_per_remote_dc:27,usemap:6,user1:[44,53],user2:44,user3:44,user3_lookup:44,user:[0,1,3,4,6,8,9,10,17,18,25,30,33,38,40,44,45,46,50,53],user_act:3,user_id1:44,user_id2:44,user_id3:44,user_id:[4,9,30,38,44],user_ids_to_queri:44,user_lookup_stmt:44,user_row:[3,44,50],user_typ:[3,6],user_type_map:29,user_tz:41,useraggregatedescriptor:[1,3],userdefinedtyp:[0,6,37],userfunctiondescriptor:[1,3],usernam:[2,44,53],users_to_insert:30,usertyp:[0,6,25,33,37],usertypedoesnotexist:3,usual:[10,21,41,53],utc:[32,41],utc_datetime_from_ms_timestamp:32,utcfromtim:0,utcnow:[6,41],utctimetupl:41,utf8:0,utf8typ:0,utf:[0,6,17],util:[0,1,12,21,22,33,40,41,44,53,54],uuid1:[10,44],uuid4:[10,48],uuid:[0,6,9,10,32,37,38,40,44,48],uuid_arg:32,uuid_from_tim:[32,40],uwsgi:[43,48],uwsgidecor:[39,43],v1:[0,1,32],v2:[0,1,45],v3:[0,1,37,45],v4:[0,1,6,30],v5:[0,1],v6:1,v:[10,12,34,47,52],val1:17,val2:17,valid:[0,1,3,6,9,10,15,18,25,27,32,47,53],validationerror:[10,37,40],valu:[0,2,3,4,6,9,10,11,13,15,17,18,25,27,29,30,31,32,34,37,40,41,44,47,52,53,54,55],value2:32,value_typ:6,valueerror:[0,32],valuemap:12,values_list:[0,38],valuesequ:30,varchar:44,variabl:[0,6,9,44,46,53],variant:54,varint:[0,6,44],variou:[26,53],various:40,ve:[9,35,37,38],verb:40,verbatim:[15,18],veri:53,verif:0,verifi:0,verify_mod:53,verify_p:53,version:[0,1,2,3,6,25,29,30,31,32,37,40,44,45,46,50,54,55],vertex:[15,18,25],vertexmetadata:25,vertexproperti:[15,18],via:[0,3,37,46,50,53],view:[0,25,27,43],violat:10,virtual:[0,38],visit:45,visual:46,vnode:3,vs:[0,27],wa:[0,1,2,3,4,5,7,25,26,27,30,36,40,46,47,54],wai:[0,3,6,15,18,27,30,36,38,41,42,44,45,46,53,54],wait:[0,1,3,21,27,30,43,44,50],wait_for_all_pool:3,wait_for_complet:30,wake:21,want:[0,3,6,9,27,34,35,37,38,44,50,53,55],warn:[0,1,3,31,40,54],warn_on_drift:31,warning_interv:31,warning_threshold:31,was_appli:[0,3],watcher:21,we:[0,7,27,36,38,39,41,42,44,48,53,55],weakref:0,web_sess:50,well:[0,27,35,44,53],were:[0,1,3,4,19,25,27,30,36,37,40],what:[27,30,37,41,53,54,55],wheel:[0,46],when:[0,1,2,3,4,5,7,9,10,17,21,27,28,29,30,31,32,35,36,37,38,40,41,42,44,46,47,50,53,54,55],whenev:[3,50],where:[0,3,4,10,25,27,30,32,37,43,44,46,47,54],whether:[1,3,6,25,26,27,47,52],which:[0,1,3,9,10,25,27,29,30,34,35,36,38,40,44,46,49,53,54,55],whilst:0,whitelist:27,whitelistroundrobinpolici:[0,27,42,44,54],whitespac:25,who:27,whose:3,wider:[32,41],window:[0,32],wish:3,within:[0,1,3,10,13,27,30,34,41,42,44,54],withing:13,without:[0,1,3,9,10,38,41,44],wkt:[0,32],wno:46,won:37,word:[27,38],work:[0,2,7,17,27,30,32,37,38,44,45,47,48,52,53,55],workaround:[0,36,40],worker:[0,39],worker_process_init:39,working_keyspac:27,workload:[0,42,49],worth:46,would:[0,9,27,36,37,38,42,44,53,54],wrap:[12,15,18,27,44],wrap_socket:53,wrapper:[0,27,30],write:[0,1,8,10,15,18,26,27,30],write_request_timeout_in_m:1,write_timeout:26,write_typ:[1,27],writefailur:1,writetimeout:[0,1],writetyp:[0,1,27],written:0,wrong:[0,44],wunus:46,www:6,x509:53,x:[1,4,10,27,32,46,47],xcode:46,xrang:0,y:[0,10,27,32],yaml:[1,27],year:[10,32,35,38],year__gt:38,year__in:38,year__lt:38,yet:[3,38,44,54],yield:[4,27],you:[0,3,4,6,9,12,27,30,34,35,37,38,43,44,46,49,50,52,53,54,55],your:[0,3,6,9,35,37,38,40,43,44,47,48,49,50,53,54,55],yourself:49,yum:46,yyyi:[17,32],z:10,zero:0,zip:[54,55],zipcod:[3,11,37,54,55]},titles:["CHANGELOG","cassandra - Exceptions and Enums","cassandra.auth - Authentication","cassandra.cluster - Clusters and Sessions","cassandra.concurrent - Utilities for Concurrent Statement Execution","cassandra.connection - Low Level Connection Info","cassandra.cqlengine.columns - Column types for object mapping models","cassandra.cqlengine.connection - Connection management for cqlengine","cassandra.cqlengine.management - Schema management for cqlengine","cassandra.cqlengine.models - Table models for object mapping","cassandra.cqlengine.query - Query and filter model objects","cassandra.cqlengine.usertype - Model classes for User Defined Types","cassandra.datastax.graph.fluent","cassandra.datastax.graph.fluent.predicates","cassandra.datastax.graph.fluent.query","cassandra.datastax.graph - Graph Statements, Options, and Row Factories","cassandra.decoder - Data Return Formats","cassandra.encoder - Encoders for non-prepared Statements","cassandra.graph - Graph Statements, Options, and Row Factories","cassandra.io.asyncioreactor - asyncio Event Loop","cassandra.io.asyncorereactor - asyncore Event Loop","cassandra.io.eventletreactor - eventlet-compatible Connection","cassandra.io.geventreactor - gevent-compatible Event Loop","cassandra.io.libevreactor - libev Event Loop","cassandra.io.twistedreactor - Twisted Event Loop","cassandra.metadata - Schema and Ring Topology","cassandra.metrics - Performance Metrics","cassandra.policies - Load balancing and Failure Handling Policies","cassandra.pool - Hosts and Connection Pools","cassandra.protocol - Protocol Features","cassandra.query - Prepared Statements, Batch Statements, Tracing, and Row Factories","cassandra.timestamps - Timestamp Generation","cassandra.util - Utilities","API Documentation","Batch Queries","Connections","Frequently Asked Questions","Models","Making Queries","Third party integrations","Upgrade Guide","Working with Dates and Times","Execution Profiles","Frequently Asked Questions","Getting Started","Python Driver for Scylla and Apache Cassandra\u00ae","Installation","Lightweight Transactions (Compare-and-set)","Object Mapper","Performance Notes","Paging Large Queries","Scylla Cloud","Scylla Specific Features","Security","Upgrading","User Defined Types"],titleterms:{"0":[0,53,54],"0b1":0,"0b5":0,"0b6":0,"0b7":0,"0c1":0,"0c2":0,"0rc1":0,"1":[0,54],"10":0,"11":0,"12":0,"13":0,"14":0,"15":0,"16":[0,53],"17":0,"18":0,"19":0,"2":[0,54],"20":0,"21":0,"22":0,"3":[0,53,54],"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"class":[11,55],"default":[35,38,42,47,54],"do":43,"enum":1,"final":0,"float":40,"function":[38,40],"import":[40,54],"new":[35,52],"return":[16,54],No:53,access:38,ad:42,address:27,alias:40,all:38,apach:45,api:[33,40,54],applic:43,ar:[38,54],ask:[36,43],asynchron:44,asyncio:19,asyncioreactor:19,asyncor:20,asyncorereactor:20,attach:54,attribut:52,auth:2,authent:[2,53,54],automat:54,awar:52,balanc:27,base:[46,54],batch:[30,34,36,54],batchqueri:35,beta2:0,beta3:0,beta4:0,beta:0,bind:54,blist:54,bug:0,c:46,call:54,callback:[34,50],can:36,cassandra:[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,41,44,45,54],celeri:39,chang:[35,40,54],changelog:0,client:[53,54],cloud:51,cluster:[3,42,52,54],column:[6,40],compar:47,compat:[21,22],compress:46,concurr:4,configur:[46,53],connect:[5,7,21,28,35,43,44],consist:[44,54],consolid:40,content:[45,48],context:35,control:50,convers:44,copyright:45,core:33,correctli:36,cql:44,cqlengin:[6,7,8,9,10,11,40],custom:[29,53,54],cython:[46,49],data:16,datastax:[12,13,14,15,33,46],date:[40,41],datetyp:41,dead:27,decod:16,defin:[11,37,54,55],definit:37,delet:36,depend:[46,54],deprec:[0,40,54],deseri:29,determin:43,dict:55,dict_factori:47,dictionari:37,document:33,doe:43,don:36,doubl:40,down:27,driver:[33,43,45,54],dse:[53,54],encod:[17,54],error:46,event:[19,20,22,23,24],eventlet:[21,53],eventletreactor:21,exampl:[37,53],except:[1,40],execut:[4,34,42,44,53,54],execute_async:54,extend:37,extens:[46,49],extra:54,factori:[15,18,30],fail:27,failur:27,faster:29,featur:[0,29,52,54],field2:36,field:36,filter:[10,38],fix:0,fluent:[12,13,14],format:16,frequent:[36,43],from:[0,36,54],from_datetim:40,gener:[31,34],get:[44,45,48],gevent:22,geventreactor:22,graph:[12,13,14,15,18,33,46,54],guid:40,handl:[27,50],help:45,helper:52,host:[27,28],how:[36,43],i:[36,43],idempot:27,ident:53,ignor:54,immut:38,individu:36,info:5,inform:54,inherit:[37,40],initi:42,instal:[46,54],instanc:[35,37,42],instanti:36,integr:39,io:[19,20,21,22,23,24,43],issu:45,larg:50,legaci:42,level:[5,40,44,54],libev:[23,46],libevreactor:23,lightweight:[47,54],list:[38,40],load:27,local_on:54,log:34,login:53,loop:[19,20,22,23,24],low:5,lower:53,make:38,manag:[7,8,35,40,43],manipul:37,manual:46,map:[6,9,42,55],mapper:[33,48],mark:27,merg:0,metadata:[25,54],metric:[26,46],model:[6,9,10,11,35,36,37,40],modul:54,multiprocess:49,my:43,name:[38,42,54],named_tuple_factori:47,nativ:54,node:27,non:[17,46,54],normal:54,note:[46,49],now:54,object:[6,9,10,33,38,48],oper:[27,38,43],option:[15,18,46],order:[36,38],organ:40,osx:46,other:0,overload:40,packag:40,page:[50,54],paramet:[42,44,54],parti:39,pass:[42,44],path:41,pattern:34,payload:29,per:38,perform:[26,49],pip:46,platform:46,polici:27,pool:28,predic:13,prepar:[17,30,44,54],prepend:40,preserv:36,profil:42,protocol:[29,53,54],proxi:53,pypi:49,python:[45,46],queri:[10,14,30,34,36,38,43,44,50,54],queryset:[10,35,38],question:[36,43],read:41,reconnect:27,regist:[35,55],remov:[40,54],replica:43,report:45,request:43,result:[47,50,54],resum:50,retri:[27,43],retriev:38,revers:40,ring:25,row:[15,18,30,36],sasl:54,schema:[8,25,40],scylla:[45,51,52],secur:53,select:35,server:[27,53],session:[3,54],set:[44,47],sever:54,shard:52,shutdown:54,side:54,size:50,soft:54,special:47,specif:52,specul:44,speed:46,ssl:[46,53],start:[44,48],statement:[4,15,17,18,30,44,54],support:46,t:36,tabl:[9,38,52],them:55,third:39,through:46,time:41,timeout:[38,43],timestamp:[31,41,54],timeuuid:[38,40],token:[25,38],topolog:25,trace:[30,43,54],transact:[47,54],translat:27,ttl:38,tuple_factori:47,twist:[24,53],twistedreactor:24,type:[6,11,37,40,44,54,55],udt:55,unicodemixin:40,unifi:53,unlog:34,unregist:35,up:[27,46],updat:[36,54],upgrad:[0,40,54],us:[34,42,54,55],user:[11,37,54,55],usertyp:11,util:[4,32],uwsgi:39,v1:53,v2:54,v3:54,valid:37,valu:[36,38],value2:36,verif:53,verifi:[46,53],version:53,vs:34,why:[36,43],window:46,without:[42,55],work:[36,41,54],write:41,wsgi:43,x:[0,54],your:46}}) \ No newline at end of file diff --git a/3.22.3-scylla/security.html b/3.22.3-scylla/security.html new file mode 100644 index 0000000000..ec381a957d --- /dev/null +++ b/3.22.3-scylla/security.html @@ -0,0 +1,1029 @@ + + + + + + + + + + + + + Security | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

Security

+

The two main security components you will use with the +Python driver are Authentication and SSL.

+
+

Authentication

+

Versions 2.0 and higher of the driver support a SASL-based +authentication mechanism when protocol_version +is set to 2 or higher. To use this authentication, set +auth_provider to an instance of a subclass +of AuthProvider. When working +with Cassandra’s PasswordAuthenticator, you can use +the PlainTextAuthProvider class.

+

For example, suppose Cassandra is setup with its default +‘cassandra’ user with a password of ‘cassandra’:

+
from cassandra.cluster import Cluster
+from cassandra.auth import PlainTextAuthProvider
+
+auth_provider = PlainTextAuthProvider(username='cassandra', password='cassandra')
+cluster = Cluster(auth_provider=auth_provider, protocol_version=2)
+
+
+
+

Custom Authenticators

+

If you’re using something other than Cassandra’s PasswordAuthenticator, +SaslAuthProvider is provided for generic SASL authentication mechanisms, +utilizing the pure-sasl package. +If these do not suit your needs, you may need to create your own subclasses of +AuthProvider and Authenticator. You can use the Sasl classes +as example implementations.

+
+
+

Protocol v1 Authentication

+

When working with Cassandra 1.2 (or a higher version with +protocol_version set to 1), you will not pass in +an AuthProvider instance. Instead, you should pass in a +function that takes one argument, the IP address of a host, and returns +a dict of credentials with a username and password key:

+
from cassandra.cluster import Cluster
+
+def get_credentials(host_address):
+    return {'username': 'joe', 'password': '1234'}
+
+cluster = Cluster(auth_provider=get_credentials, protocol_version=1)
+
+
+
+
+
+

SSL

+

SSL should be used when client encryption is enabled in Cassandra.

+

To give you as much control as possible over your SSL configuration, our SSL +API takes a user-created SSLContext instance from the Python standard library. +These docs will include some examples for how to achieve common configurations, +but the ssl.SSLContext documentation +gives a more complete description of what is possible.

+

To enable SSL with version 3.17.0 and higher, you will need to set Cluster.ssl_context to a +ssl.SSLContext instance to enable SSL. Optionally, you can also set Cluster.ssl_options +to a dict of options. These will be passed as kwargs to ssl.SSLContext.wrap_socket() +when new sockets are created.

+

If you create your SSLContext using ssl.create_default_context, +be aware that SSLContext.check_hostname is set to True by default, so the hostname validation will be done +by Python and not the driver. For this reason, we need to set the server_hostname at best effort, which is the +resolved ip address. If this validation needs to be done against the FQDN, consider enabling it using the ssl_options +as described in the following examples or implement your own EndPoint and +EndPointFactory.

+

The following examples assume you have generated your Cassandra certificate and +keystore files with these intructions:

+ +

It might be also useful to learn about the different levels of identity verification to understand the examples:

+ +
+

SSL with Twisted or Eventlet

+

Twisted and Eventlet both use an alternative SSL implementation called pyOpenSSL, so if your Cluster’s connection class is +TwistedConnection or EventletConnection, you must pass a +pyOpenSSL context instead. +An example is provided in these docs, and more details can be found in the +documentation. +pyOpenSSL is not installed by the driver and must be installed separately.

+
+
+

SSL Configuration Examples

+

Here, we’ll describe the server and driver configuration necessary to set up SSL to meet various goals, such as the client verifying the server and the server verifying the client. We’ll also include Python code demonstrating how to use servers and drivers configured in these ways.

+
+

No identity verification

+

No identity verification at all. Note that this is not recommended for for production deployments.

+

The Cassandra configuration:

+
client_encryption_options:
+  enabled: true
+  keystore: /path/to/127.0.0.1.keystore
+  keystore_password: myStorePass
+  require_client_auth: false
+
+
+

The driver configuration:

+
from cassandra.cluster import Cluster, Session
+from ssl import SSLContext, PROTOCOL_TLSv1
+
+ssl_context = SSLContext(PROTOCOL_TLSv1)
+
+cluster = Cluster(['127.0.0.1'], ssl_context=ssl_context)
+session = cluster.connect()
+
+
+
+
+

Client verifies server

+

Ensure the python driver verifies the identity of the server.

+

The Cassandra configuration:

+
client_encryption_options:
+  enabled: true
+  keystore: /path/to/127.0.0.1.keystore
+  keystore_password: myStorePass
+  require_client_auth: false
+
+
+

For the driver configuration, it’s very important to set ssl_context.verify_mode +to CERT_REQUIRED. Otherwise, the loaded verify certificate will have no effect:

+
from cassandra.cluster import Cluster, Session
+from ssl import SSLContext, PROTOCOL_TLSv1, CERT_REQUIRED
+
+ssl_context = SSLContext(PROTOCOL_TLSv1)
+ssl_context.load_verify_locations('/path/to/rootca.crt')
+ssl_context.verify_mode = CERT_REQUIRED
+
+cluster = Cluster(['127.0.0.1'], ssl_context=ssl_context)
+session = cluster.connect()
+
+
+

Additionally, you can also force the driver to verify the hostname of the server by passing additional options to ssl_context.wrap_socket via the ssl_options kwarg:

+
from cassandra.cluster import Cluster, Session
+from ssl import SSLContext, PROTOCOL_TLSv1, CERT_REQUIRED
+
+ssl_context = SSLContext(PROTOCOL_TLSv1)
+ssl_context.load_verify_locations('/path/to/rootca.crt')
+ssl_context.verify_mode = CERT_REQUIRED
+ssl_context.check_hostname = True
+ssl_options = {'server_hostname': '127.0.0.1'}
+
+cluster = Cluster(['127.0.0.1'], ssl_context=ssl_context, ssl_options=ssl_options)
+session = cluster.connect()
+
+
+
+
+

Server verifies client

+

If Cassandra is configured to verify clients (require_client_auth), you need to generate +SSL key and certificate files.

+

The cassandra configuration:

+
client_encryption_options:
+  enabled: true
+  keystore: /path/to/127.0.0.1.keystore
+  keystore_password: myStorePass
+  require_client_auth: true
+  truststore: /path/to/dse-truststore.jks
+  truststore_password: myStorePass
+
+
+

The Python ssl APIs require the certificate in PEM format. First, create a certificate +conf file:

+
cat > gen_client_cert.conf <<EOF
+[ req ]
+distinguished_name = req_distinguished_name
+prompt = no
+output_password = ${ROOT_CERT_PASS}
+default_bits = 2048
+
+[ req_distinguished_name ]
+C = ${CERT_COUNTRY}
+O = ${CERT_ORG_NAME}
+OU = ${CERT_OU}
+CN = client
+EOF
+
+
+

Make sure you replaced the variables with the same values you used for the initial +root CA certificate. Then, generate the key:

+
openssl req -newkey rsa:2048 -nodes -keyout client.key -out client.csr -config gen_client_cert.conf
+
+
+

And generate the client signed certificate:

+
openssl x509 -req -CA ${ROOT_CA_BASE_NAME}.crt -CAkey ${ROOT_CA_BASE_NAME}.key -passin pass:${ROOT_CERT_PASS} \
+    -in client.csr -out client.crt_signed -days ${CERT_VALIDITY} -CAcreateserial
+
+
+

Finally, you can use that configuration with the following driver code:

+
from cassandra.cluster import Cluster, Session
+from ssl import SSLContext, PROTOCOL_TLSv1
+
+ssl_context = SSLContext(PROTOCOL_TLSv1)
+ssl_context.load_cert_chain(
+    certfile='/path/to/client.crt_signed',
+    keyfile='/path/to/client.key')
+
+cluster = Cluster(['127.0.0.1'], ssl_context=ssl_context)
+session = cluster.connect()
+
+
+
+
+

Server verifies client and client verifies server

+

See the previous section for examples of Cassandra configuration and preparing +the client certificates.

+

The following driver code specifies that the connection should use two-way verification:

+
from cassandra.cluster import Cluster, Session
+from ssl import SSLContext, PROTOCOL_TLSv1, CERT_REQUIRED
+
+ssl_context = SSLContext(PROTOCOL_TLSv1)
+ssl_context.load_verify_locations('/path/to/rootca.crt')
+ssl_context.verify_mode = CERT_REQUIRED
+ssl_context.load_cert_chain(
+    certfile='/path/to/client.crt_signed',
+    keyfile='/path/to/client.key')
+
+cluster = Cluster(['127.0.0.1'], ssl_context=ssl_context)
+session = cluster.connect()
+
+
+

The driver uses SSLContext directly to give you many other options in configuring SSL. Consider reading the Python SSL documentation +for more details about SSLContext configuration.

+

Server verifies client and client verifies server using Twisted and pyOpenSSL

+
from OpenSSL import SSL, crypto
+from cassandra.cluster import Cluster
+from cassandra.io.twistedreactor import TwistedConnection
+
+ssl_context = SSL.Context(SSL.TLSv1_METHOD)
+ssl_context.set_verify(SSL.VERIFY_PEER, callback=lambda _1, _2, _3, _4, ok: ok)
+ssl_context.use_certificate_file('/path/to/client.crt_signed')
+ssl_context.use_privatekey_file('/path/to/client.key')
+ssl_context.load_verify_locations('/path/to/rootca.crt')
+
+cluster = Cluster(
+    contact_points=['127.0.0.1'],
+    connection_class=TwistedConnection,
+    ssl_context=ssl_context,
+    ssl_options={'check_hostname': True}
+)
+session = cluster.connect()
+
+
+

Connecting using Eventlet would look similar except instead of importing and using TwistedConnection, you would +import and use EventletConnection, including the appropriate monkey-patching.

+
+
+
+

Versions 3.16.0 and lower

+

To enable SSL you will need to set Cluster.ssl_options to a +dict of options. These will be passed as kwargs to ssl.wrap_socket() +when new sockets are created. Note that this use of ssl_options will be +deprecated in the next major release.

+

By default, a ca_certs value should be supplied (the value should be +a string pointing to the location of the CA certs file), and you probably +want to specify ssl_version as ssl.PROTOCOL_TLSv1 to match +Cassandra’s default protocol.

+

For example:

+
from cassandra.cluster import Cluster
+from ssl import PROTOCOL_TLSv1, CERT_REQUIRED
+
+ssl_opts = {
+    'ca_certs': '/path/to/my/ca.certs',
+    'ssl_version': PROTOCOL_TLSv1,
+    'cert_reqs': CERT_REQUIRED  # Certificates are required and validated
+}
+cluster = Cluster(ssl_options=ssl_opts)
+
+
+

This is only an example to show how to pass the ssl parameters. Consider reading +the python ssl documentation for +your configuration. For further reading, Andrew Mussey has published a thorough guide on +Using SSL with the DataStax Python driver.

+
+

SSL with Twisted

+

In case the twisted event loop is used pyOpenSSL must be installed or an exception will be risen. Also +to set the ssl_version and cert_reqs in ssl_opts the appropriate constants from pyOpenSSL are expected.

+
+
+
+
+

DSE Authentication

+

When authenticating against DSE, the Cassandra driver provides two auth providers that work both with legacy kerberos and Cassandra authenticators, +as well as the new DSE Unified Authentication. This allows client to configure this auth provider independently, +and in advance of any server upgrade. These auth providers are configured in the same way as any previous implementation:

+
from cassandra.auth import DSEGSSAPIAuthProvider
+auth_provider = DSEGSSAPIAuthProvider(service='dse', qops=["auth"])
+cluster = Cluster(auth_provider=auth_provider)
+session = cluster.connect()
+
+
+

Implementations are DSEPlainTextAuthProvider, DSEGSSAPIAuthProvider and SaslAuthProvider.

+
+

DSE Unified Authentication

+

With DSE (>=5.1), unified Authentication allows you to:

+
    +
  • Proxy Login: Authenticate using a fixed set of authentication credentials but allow authorization of resources based another user id.

  • +
  • Proxy Execute: Authenticate using a fixed set of authentication credentials but execute requests based on another user id.

  • +
+
+

Proxy Login

+

Proxy login allows you to authenticate with a user but act as another one. You need to ensure the authenticated user has the permission to use the authorization of resources of the other user. ie. this example will allow the server user to authenticate as usual but use the authorization of user1:

+
GRANT PROXY.LOGIN on role user1 to server
+
+
+

then you can do the proxy authentication….

+
from cassandra.cluster import Cluster
+from cassandra.auth import SaslAuthProvider
+
+sasl_kwargs = {
+  "service": 'dse',
+  "mechanism":"PLAIN",
+  "username": 'server',
+  'password': 'server',
+  'authorization_id': 'user1'
+}
+
+auth_provider = SaslAuthProvider(**sasl_kwargs)
+c = Cluster(auth_provider=auth_provider)
+s = c.connect()
+s.execute(...)  # all requests will be executed as 'user1'
+
+
+

If you are using kerberos, you can use directly DSEGSSAPIAuthProvider and pass the authorization_id, like this:

+
from cassandra.cluster import Cluster
+from cassandra.auth import DSEGSSAPIAuthProvider
+
+# Ensure the kerberos ticket of the server user is set with the kinit utility.
+auth_provider = DSEGSSAPIAuthProvider(service='dse', qops=["auth"], principal="server@DATASTAX.COM",
+                                      authorization_id='user1@DATASTAX.COM')
+c = Cluster(auth_provider=auth_provider)
+s = c.connect()
+s.execute(...)  # all requests will be executed as 'user1'
+
+
+
+
+

Proxy Execute

+

Proxy execute allows you to execute requests as another user than the authenticated one. You need to ensure the authenticated user has the permission to use the authorization of resources of the specified user. ie. this example will allow the server user to execute requests as user1:

+
GRANT PROXY.EXECUTE on role user1 to server
+
+
+

then you can do a proxy execute…

+
from cassandra.cluster import Cluster
+from cassandra.auth import DSEPlainTextAuthProvider,
+
+auth_provider = DSEPlainTextAuthProvider('server', 'server')
+
+c = Cluster(auth_provider=auth_provider)
+s = c.connect()
+s.execute('select * from k.t;', execute_as='user1')  # the request will be executed as 'user1'
+
+
+

Please see the official documentation for more details on the feature and configuration process.

+
+
+
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.22.3-scylla/sitemap.xml b/3.22.3-scylla/sitemap.xml new file mode 100644 index 0000000000..f03cce40f2 --- /dev/null +++ b/3.22.3-scylla/sitemap.xml @@ -0,0 +1,2 @@ + +https://python-driver.docs.scylladb.com/stable/CHANGELOG.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/auth.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/cluster.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/concurrent.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/connection.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/cqlengine/columns.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/cqlengine/connection.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/cqlengine/management.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/cqlengine/models.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/cqlengine/query.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/cqlengine/usertype.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/datastax/graph/fluent/index.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/datastax/graph/fluent/predicates.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/datastax/graph/fluent/query.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/datastax/graph/index.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/decoder.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/encoder.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/graph.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/io/asyncioreactor.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/io/asyncorereactor.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/io/eventletreactor.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/io/geventreactor.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/io/libevreactor.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/io/twistedreactor.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/metadata.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/metrics.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/policies.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/pool.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/protocol.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/query.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/timestamps.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/util.htmlhttps://python-driver.docs.scylladb.com/stable/api/index.htmlhttps://python-driver.docs.scylladb.com/stable/cqlengine/batches.htmlhttps://python-driver.docs.scylladb.com/stable/cqlengine/connections.htmlhttps://python-driver.docs.scylladb.com/stable/cqlengine/faq.htmlhttps://python-driver.docs.scylladb.com/stable/cqlengine/models.htmlhttps://python-driver.docs.scylladb.com/stable/cqlengine/queryset.htmlhttps://python-driver.docs.scylladb.com/stable/cqlengine/third_party.htmlhttps://python-driver.docs.scylladb.com/stable/cqlengine/upgrade_guide.htmlhttps://python-driver.docs.scylladb.com/stable/dates_and_times.htmlhttps://python-driver.docs.scylladb.com/stable/execution_profiles.htmlhttps://python-driver.docs.scylladb.com/stable/faq.htmlhttps://python-driver.docs.scylladb.com/stable/getting_started.htmlhttps://python-driver.docs.scylladb.com/stable/index.htmlhttps://python-driver.docs.scylladb.com/stable/installation.htmlhttps://python-driver.docs.scylladb.com/stable/lwt.htmlhttps://python-driver.docs.scylladb.com/stable/object_mapper.htmlhttps://python-driver.docs.scylladb.com/stable/performance.htmlhttps://python-driver.docs.scylladb.com/stable/query_paging.htmlhttps://python-driver.docs.scylladb.com/stable/scylla_cloud.htmlhttps://python-driver.docs.scylladb.com/stable/scylla_specific.htmlhttps://python-driver.docs.scylladb.com/stable/security.htmlhttps://python-driver.docs.scylladb.com/stable/upgrading.htmlhttps://python-driver.docs.scylladb.com/stable/user_defined_types.htmlhttps://python-driver.docs.scylladb.com/stable/py-modindex.htmlhttps://python-driver.docs.scylladb.com/stable/404.htmlhttps://python-driver.docs.scylladb.com/stable/search.html \ No newline at end of file diff --git a/3.22.3-scylla/upgrading.html b/3.22.3-scylla/upgrading.html new file mode 100644 index 0000000000..15988827d2 --- /dev/null +++ b/3.22.3-scylla/upgrading.html @@ -0,0 +1,1028 @@ + + + + + + + + + + + + + Upgrading | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

Upgrading

+
+
+
+

Upgrading from dse-driver

+

Since 3.21.0, scylla-driver fully supports DataStax products. dse-driver and +dse-graph users should now migrate to scylla-driver to benefit from latest bug fixes +and new features. The upgrade to this new unified driver version is straightforward +with no major API changes.

+
+

Installation

+

Only the scylla-driver package should be installed. dse-driver and dse-graph +are not required anymore:

+
pip install scylla-driver
+
+
+

If you need the Graph Fluent API (features provided by dse-graph):

+
pip install scylla-driver[graph]
+
+
+

See Installation for more details.

+
+
+

Import from the cassandra module

+

There is no dse module, so you should import from the cassandra module. You +need to change only the first module of your import statements, not the submodules.

+
from dse.cluster import Cluster, EXEC_PROFILE_GRAPH_DEFAULT
+from dse.auth import PlainTextAuthProvider
+from dse.policies import WhiteListRoundRobinPolicy
+
+# becomes
+
+from cassandra.cluster import Cluster, EXEC_PROFILE_GRAPH_DEFAULT
+from cassandra.auth import PlainTextAuthProvider
+from cassandra.policies import WhiteListRoundRobinPolicy
+
+
+

Also note that the cassandra.hosts module doesn’t exist in scylla-driver. This +module is named cassandra.pool.

+
+
+

dse-graph

+

dse-graph features are now built into scylla-driver. The only change you need +to do is your import statements:

+
from dse_graph import ..
+from dse_graph.query import ..
+
+# becomes
+
+from cassandra.datastax.graph.fluent import ..
+from cassandra.datastax.graph.fluent.query import ..
+
+
+

See fluent.

+
+
+

Session.execute and Session.execute_async API

+

Although it is not common to use this API with positional arguments, it is +important to be aware that the host and execute_as parameters have had +their positional order swapped. This is only because execute_as was added +in dse-driver before host.

+

See Session.execute().

+
+
+

Deprecations

+

These changes are optional, but recommended:

+
    +
  • Importing from cassandra.graph is deprecated. Consider importing from cassandra.datastax.graph.

  • +
  • Use DefaultLoadBalancingPolicy instead of DSELoadBalancingPolicy.

  • +
+
+
+
+

Upgrading to 3.0

+

Version 3.0 of the DataStax Python driver for Apache Cassandra +adds support for Cassandra 3.0 while maintaining support for +previously supported versions. In addition to substantial internal rework, +there are several updates to the API that integrators will need +to consider:

+
+

Default consistency is now LOCAL_ONE

+

Previous value was ONE. The new value is introduced to mesh with the default +DC-aware load balancing policy and to match other drivers.

+
+
+

Execution API Updates

+
+

Result return normalization

+

PYTHON-368

+

Previously results would be returned as a list of rows for result rows +up to fetch_size, and PagedResult afterward. This could break +application code that assumed one type and got another.

+

Now, all results are returned as an iterable ResultSet.

+

The preferred way to consume results of unknown size is to iterate through +them, letting automatic paging occur as they are consumed.

+
results = session.execute("SELECT * FROM system.local")
+for row in results:
+    process(row)
+
+
+

If the expected size of the results is known, it is still possible to +materialize a list using the iterator:

+
results = session.execute("SELECT * FROM system.local")
+row_list = list(results)
+
+
+

For backward compatibility, ResultSet supports indexing. When +accessed at an index, a ~.ResultSet object will materialize all its pages:

+
results = session.execute("SELECT * FROM system.local")
+first_result = results[0]  # materializes results, fetching all pages
+
+
+

This can send requests and load (possibly large) results into memory, so +~.ResultSet will log a warning on implicit materialization.

+
+
+

Trace information is not attached to executed Statements

+

PYTHON-318

+

Previously trace data was attached to Statements if tracing was enabled. This +could lead to confusion if the same statement was used for multiple executions.

+

Now, trace data is associated with the ResponseFuture and ResultSet +returned for each query:

+

ResponseFuture.get_query_trace()

+

ResponseFuture.get_all_query_traces()

+

ResultSet.get_query_trace()

+

ResultSet.get_all_query_traces()

+
+
+

Binding named parameters now ignores extra names

+

PYTHON-178

+

Previously, BoundStatement.bind() would raise if a mapping +was passed with extra names not found in the prepared statement.

+

Behavior in 3.0+ is to ignore extra names.

+
+
+
+

blist removed as soft dependency

+

PYTHON-385

+

Previously the driver had a soft dependency on blist sortedset, using +that where available and using an internal fallback where possible.

+

Now, the driver never chooses the blist variant, instead returning the +internal util.SortedSet for all set results. The class implements +all standard set operations, so no integration code should need to change unless +it explicitly checks for sortedset type.

+
+
+

Metadata API Updates

+

PYTHON-276, PYTHON-408, PYTHON-400, PYTHON-422

+

Cassandra 3.0 brought a substantial overhaul to the internal schema metadata representation. +This version of the driver supports that metadata in addition to the legacy version. Doing so +also brought some changes to the metadata model.

+

The present API is documented: cassandra.metadata. Changes highlighted below:

+
    +
  • All types are now exposed as CQL types instead of types derived from the internal server implementation

  • +
  • Some metadata attributes have changed names to match current nomenclature (for example, Index.kind in place of Index.type).

  • +
  • Some metadata attributes removed

    +
      +
    • TableMetadata.keyspace reference replaced with TableMetadata.keyspace_name

    • +
    • ColumnMetadata.index is removed table- and keyspace-level mappings are still maintained

    • +
    +
  • +
+
+
+

Several deprecated features are removed

+

PYTHON-292

+
    +
  • ResponseFuture.result timeout parameter is removed, use Session.execute timeout instead (031ebb0)

  • +
  • Cluster.refresh_schema removed, use Cluster.refresh_*_metadata instead (419fcdf)

  • +
  • Cluster.submit_schema_refresh removed (574266d)

  • +
  • cqltypes time/date functions removed, use util entry points instead (bb984ee)

  • +
  • decoder module removed (e16a073)

  • +
  • TableMetadata.keyspace attribute replaced with keyspace_name (cc94073)

  • +
  • cqlengine.columns.TimeUUID.from_datetime removed, use util variant instead (96489cc)

  • +
  • cqlengine.columns.Float(double_precision) parameter removed, use columns.Double instead (a2d3a98)

  • +
  • cqlengine keyspace management functions are removed in favor of the strategy-specific entry points (4bd5909)

  • +
  • cqlengine.Model.__polymorphic_*__ attributes removed, use __discriminator* attributes instead (9d98c8e)

  • +
  • cqlengine.statements will no longer warn about list list prepend behavior (79efe97)

  • +
+
+
+
+

Upgrading to 2.1 from 2.0

+

Version 2.1 of the DataStax Python driver for Apache Cassandra +adds support for Cassandra 2.1 and version 3 of the native protocol.

+

Cassandra 1.2, 2.0, and 2.1 are all supported. However, 1.2 only +supports protocol version 1, and 2.0 only supports versions 1 and +2, so some features may not be available.

+
+

Using the v3 Native Protocol

+

By default, the driver will attempt to use version 2 of the +native protocol. To use version 3, you must explicitly +set the protocol_version:

+
from cassandra.cluster import Cluster
+
+cluster = Cluster(protocol_version=3)
+
+
+

Note that protocol version 3 is only supported by Cassandra 2.1+.

+

In future releases, the driver may default to using protocol version +3.

+
+
+

Working with User-Defined Types

+

Cassandra 2.1 introduced the ability to define new types:

+
USE KEYSPACE mykeyspace;
+
+CREATE TYPE address (street text, city text, zip int);
+
+
+

The driver generally expects you to use instances of a specific +class to represent column values of this type. You can let the +driver know what class to use with Cluster.register_user_type():

+
cluster = Cluster()
+
+class Address(object):
+
+    def __init__(self, street, city, zipcode):
+        self.street = street
+        self.city = text
+        self.zipcode = zipcode
+
+cluster.register_user_type('mykeyspace', 'address', Address)
+
+
+

When inserting data for address columns, you should pass in +instances of Address. When querying data, address column +values will be instances of Address.

+

If no class is registered for a user-defined type, query results +will use a namedtuple class and data may only be inserted +though prepared statements.

+

See User Defined Types for more details.

+
+
+

Customizing Encoders for Non-prepared Statements

+

Starting with version 2.1 of the driver, it is possible to customize +how Python types are converted to CQL literals when working with +non-prepared statements. This is done on a per-Session +basis through Session.encoder:

+
cluster = Cluster()
+session = cluster.connect()
+session.encoder.mapping[tuple] = session.encoder.cql_encode_tuple
+
+
+

See Type Conversions for the table of default CQL literal conversions.

+
+
+

Using Client-Side Protocol-Level Timestamps

+

With version 3 of the native protocol, timestamps may be supplied by the +client at the protocol level. (Normally, if they are not specified within +the CQL query itself, a timestamp is generated server-side.)

+

When protocol_version is set to 3 or higher, the driver +will automatically use client-side timestamps with microsecond precision +unless Session.use_client_timestamp is changed to False. +If a timestamp is specified within the CQL query, it will override the +timestamp generated by the driver.

+
+
+
+

Upgrading to 2.0 from 1.x

+

Version 2.0 of the DataStax Python driver for Apache Cassandra +includes some notable improvements over version 1.x. This version +of the driver supports Cassandra 1.2, 2.0, and 2.1. However, not +all features may be used with Cassandra 1.2, and some new features +in 2.1 are not yet supported.

+
+

Using the v2 Native Protocol

+

By default, the driver will attempt to use version 2 of Cassandra’s +native protocol. You can explicitly set the protocol version to +2, though:

+
from cassandra.cluster import Cluster
+
+cluster = Cluster(protocol_version=2)
+
+
+

When working with Cassandra 1.2, you will need to +explicitly set the protocol_version to 1:

+
from cassandra.cluster import Cluster
+
+cluster = Cluster(protocol_version=1)
+
+
+
+
+

Automatic Query Paging

+

Version 2 of the native protocol adds support for automatic query +paging, which can make dealing with large result sets much simpler.

+

See Paging Large Queries for full details.

+
+
+

Protocol-Level Batch Statements

+

With version 1 of the native protocol, batching of statements required +using a BATCH cql query. +With version 2 of the native protocol, you can now batch statements at +the protocol level. This allows you to use many different prepared +statements within a single batch.

+

See BatchStatement for details and usage examples.

+
+
+

SASL-based Authentication

+

Also new in version 2 of the native protocol is SASL-based authentication. +See the section on Security for details and examples.

+
+
+

Lightweight Transactions

+

Lightweight transactions are another new feature. To use lightweight transactions, add IF clauses +to your CQL queries and set the serial_consistency_level +on your statements.

+
+
+

Calling Cluster.shutdown()

+

In order to fix some issues around garbage collection and unclean interpreter +shutdowns, version 2.0 of the driver requires you to call Cluster.shutdown() +on your Cluster objects when you are through with them. +This helps to guarantee a clean shutdown.

+
+
+

Deprecations

+

The following functions have moved from cassandra.decoder to cassandra.query. +The original functions have been left in place with a DeprecationWarning for +now:

+ +
+
+

Dependency Changes

+

The following dependencies have officially been made optional:

+
    +
  • scales

  • +
  • blist

  • +
+

And one new dependency has been added (to enable Python 3 support):

+
    +
  • six

  • +
+
+
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.22.3-scylla/user_defined_types.html b/3.22.3-scylla/user_defined_types.html new file mode 100644 index 0000000000..7b2ab5e5cc --- /dev/null +++ b/3.22.3-scylla/user_defined_types.html @@ -0,0 +1,758 @@ + + + + + + + + + + + + + User Defined Types | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

User Defined Types

+

Cassandra 2.1 introduced user-defined types (UDTs). You can create a +new type through CREATE TYPE statements in CQL:

+
CREATE TYPE address (street text, zip int);
+
+
+

Version 2.1 of the Python driver adds support for user-defined types.

+
+

Registering a UDT

+

You can tell the Python driver to return columns of a specific UDT as +instances of a class or a dict by registering them with your Cluster +instance through Cluster.register_user_type():

+
+

Map a Class to a UDT

+
cluster = Cluster(protocol_version=3)
+session = cluster.connect()
+session.set_keyspace('mykeyspace')
+session.execute("CREATE TYPE address (street text, zipcode int)")
+session.execute("CREATE TABLE users (id int PRIMARY KEY, location frozen<address>)")
+
+# create a class to map to the "address" UDT
+class Address(object):
+
+    def __init__(self, street, zipcode):
+        self.street = street
+        self.zipcode = zipcode
+
+cluster.register_user_type('mykeyspace', 'address', Address)
+
+# insert a row using an instance of Address
+session.execute("INSERT INTO users (id, location) VALUES (%s, %s)",
+                (0, Address("123 Main St.", 78723)))
+
+# results will include Address instances
+results = session.execute("SELECT * FROM users")
+row = results[0]
+print(row.id, row.location.street, row.location.zipcode)
+
+
+
+
+

Map a dict to a UDT

+
cluster = Cluster(protocol_version=3)
+session = cluster.connect()
+session.set_keyspace('mykeyspace')
+session.execute("CREATE TYPE address (street text, zipcode int)")
+session.execute("CREATE TABLE users (id int PRIMARY KEY, location frozen<address>)")
+
+cluster.register_user_type('mykeyspace', 'address', dict)
+
+# insert a row using a prepared statement and a tuple
+insert_statement = session.prepare("INSERT INTO mykeyspace.users (id, location) VALUES (?, ?)")
+session.execute(insert_statement, [0, ("123 Main St.", 78723)])
+
+# results will include dict instances
+results = session.execute("SELECT * FROM users")
+row = results[0]
+print(row.id, row.location['street'], row.location['zipcode'])
+
+
+
+
+
+

Using UDTs Without Registering Them

+

Although it is recommended to register your types with +Cluster.register_user_type(), the driver gives you some options +for working with unregistered UDTS.

+

When you use prepared statements, the driver knows what data types to +expect for each placeholder. This allows you to pass any object you +want for a UDT, as long as it has attributes that match the field names +for the UDT:

+
cluster = Cluster(protocol_version=3)
+session = cluster.connect()
+session.set_keyspace('mykeyspace')
+session.execute("CREATE TYPE address (street text, zipcode int)")
+session.execute("CREATE TABLE users (id int PRIMARY KEY, location frozen<address>)")
+
+class Foo(object):
+
+    def __init__(self, street, zipcode, otherstuff):
+        self.street = street
+        self.zipcode = zipcode
+        self.otherstuff = otherstuff
+
+insert_statement = session.prepare("INSERT INTO users (id, location) VALUES (?, ?)")
+
+# since we're using a prepared statement, we don't *have* to register
+# a class to map to the UDT to insert data.  The object just needs to have
+# "street" and "zipcode" attributes (which Foo does):
+session.execute(insert_statement, [0, Foo("123 Main St.", 78723, "some other stuff")])
+
+# when we query data, UDT columns that don't have a class registered
+# will be returned as namedtuples:
+results = session.execute("SELECT * FROM users")
+first_row = results[0]
+address = first_row.location
+print(address)  # prints "Address(street='123 Main St.', zipcode=78723)"
+street = address.street
+zipcode = address.street
+
+
+

As shown in the code example, inserting data for UDT columns without registering +a class works fine for prepared statements. However, you must register a +class to insert UDT columns with unprepared statements.* You can still query +UDT columns without registered classes using unprepared statements, they will +simply return namedtuple instances (just like prepared statements do).

+

* this applies to parameterized unprepared statements, in which the driver will be formatting parameters – not statements with interpolated UDT literals.

+
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.24.8-scylla/.buildinfo b/3.24.8-scylla/.buildinfo new file mode 100644 index 0000000000..a80c44a674 --- /dev/null +++ b/3.24.8-scylla/.buildinfo @@ -0,0 +1,4 @@ +# Sphinx build info version 1 +# This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done. +config: 4ed399866ee34631784d9e1a77c96297 +tags: 645f666f9bcd5a90fca523b33c5a78b7 diff --git a/3.24.8-scylla/.doctrees/CHANGELOG.doctree b/3.24.8-scylla/.doctrees/CHANGELOG.doctree new file mode 100644 index 0000000000..77dff143ef Binary files /dev/null and b/3.24.8-scylla/.doctrees/CHANGELOG.doctree differ diff --git a/3.24.8-scylla/.doctrees/api/cassandra.doctree b/3.24.8-scylla/.doctrees/api/cassandra.doctree new file mode 100644 index 0000000000..3c26ddc513 Binary files /dev/null and b/3.24.8-scylla/.doctrees/api/cassandra.doctree differ diff --git a/3.24.8-scylla/.doctrees/api/cassandra/auth.doctree b/3.24.8-scylla/.doctrees/api/cassandra/auth.doctree new file mode 100644 index 0000000000..cd16959a2a Binary files /dev/null and b/3.24.8-scylla/.doctrees/api/cassandra/auth.doctree differ diff --git a/3.24.8-scylla/.doctrees/api/cassandra/cluster.doctree b/3.24.8-scylla/.doctrees/api/cassandra/cluster.doctree new file mode 100644 index 0000000000..6bc333e6c8 Binary files /dev/null and b/3.24.8-scylla/.doctrees/api/cassandra/cluster.doctree differ diff --git a/3.24.8-scylla/.doctrees/api/cassandra/concurrent.doctree b/3.24.8-scylla/.doctrees/api/cassandra/concurrent.doctree new file mode 100644 index 0000000000..cbe402cc2f Binary files /dev/null and b/3.24.8-scylla/.doctrees/api/cassandra/concurrent.doctree differ diff --git a/3.24.8-scylla/.doctrees/api/cassandra/connection.doctree b/3.24.8-scylla/.doctrees/api/cassandra/connection.doctree new file mode 100644 index 0000000000..5f010664cf Binary files /dev/null and b/3.24.8-scylla/.doctrees/api/cassandra/connection.doctree differ diff --git a/3.24.8-scylla/.doctrees/api/cassandra/cqlengine/columns.doctree b/3.24.8-scylla/.doctrees/api/cassandra/cqlengine/columns.doctree new file mode 100644 index 0000000000..2ebf52ba44 Binary files /dev/null and b/3.24.8-scylla/.doctrees/api/cassandra/cqlengine/columns.doctree differ diff --git a/3.24.8-scylla/.doctrees/api/cassandra/cqlengine/connection.doctree b/3.24.8-scylla/.doctrees/api/cassandra/cqlengine/connection.doctree new file mode 100644 index 0000000000..a52e527204 Binary files /dev/null and b/3.24.8-scylla/.doctrees/api/cassandra/cqlengine/connection.doctree differ diff --git a/3.24.8-scylla/.doctrees/api/cassandra/cqlengine/management.doctree b/3.24.8-scylla/.doctrees/api/cassandra/cqlengine/management.doctree new file mode 100644 index 0000000000..f092f8eb0e Binary files /dev/null and b/3.24.8-scylla/.doctrees/api/cassandra/cqlengine/management.doctree differ diff --git a/3.24.8-scylla/.doctrees/api/cassandra/cqlengine/models.doctree b/3.24.8-scylla/.doctrees/api/cassandra/cqlengine/models.doctree new file mode 100644 index 0000000000..459014c073 Binary files /dev/null and b/3.24.8-scylla/.doctrees/api/cassandra/cqlengine/models.doctree differ diff --git a/3.24.8-scylla/.doctrees/api/cassandra/cqlengine/query.doctree b/3.24.8-scylla/.doctrees/api/cassandra/cqlengine/query.doctree new file mode 100644 index 0000000000..a6c1cef31a Binary files /dev/null and b/3.24.8-scylla/.doctrees/api/cassandra/cqlengine/query.doctree differ diff --git a/3.24.8-scylla/.doctrees/api/cassandra/cqlengine/usertype.doctree b/3.24.8-scylla/.doctrees/api/cassandra/cqlengine/usertype.doctree new file mode 100644 index 0000000000..750ed43906 Binary files /dev/null and b/3.24.8-scylla/.doctrees/api/cassandra/cqlengine/usertype.doctree differ diff --git a/3.24.8-scylla/.doctrees/api/cassandra/datastax/graph/fluent/index.doctree b/3.24.8-scylla/.doctrees/api/cassandra/datastax/graph/fluent/index.doctree new file mode 100644 index 0000000000..bf61ac49fe Binary files /dev/null and b/3.24.8-scylla/.doctrees/api/cassandra/datastax/graph/fluent/index.doctree differ diff --git a/3.24.8-scylla/.doctrees/api/cassandra/datastax/graph/fluent/predicates.doctree b/3.24.8-scylla/.doctrees/api/cassandra/datastax/graph/fluent/predicates.doctree new file mode 100644 index 0000000000..99ebc437f3 Binary files /dev/null and b/3.24.8-scylla/.doctrees/api/cassandra/datastax/graph/fluent/predicates.doctree differ diff --git a/3.24.8-scylla/.doctrees/api/cassandra/datastax/graph/fluent/query.doctree b/3.24.8-scylla/.doctrees/api/cassandra/datastax/graph/fluent/query.doctree new file mode 100644 index 0000000000..d35b6e10c7 Binary files /dev/null and b/3.24.8-scylla/.doctrees/api/cassandra/datastax/graph/fluent/query.doctree differ diff --git a/3.24.8-scylla/.doctrees/api/cassandra/datastax/graph/index.doctree b/3.24.8-scylla/.doctrees/api/cassandra/datastax/graph/index.doctree new file mode 100644 index 0000000000..7c2bc271e4 Binary files /dev/null and b/3.24.8-scylla/.doctrees/api/cassandra/datastax/graph/index.doctree differ diff --git a/3.24.8-scylla/.doctrees/api/cassandra/decoder.doctree b/3.24.8-scylla/.doctrees/api/cassandra/decoder.doctree new file mode 100644 index 0000000000..d7dc9b5f60 Binary files /dev/null and b/3.24.8-scylla/.doctrees/api/cassandra/decoder.doctree differ diff --git a/3.24.8-scylla/.doctrees/api/cassandra/encoder.doctree b/3.24.8-scylla/.doctrees/api/cassandra/encoder.doctree new file mode 100644 index 0000000000..67a916d685 Binary files /dev/null and b/3.24.8-scylla/.doctrees/api/cassandra/encoder.doctree differ diff --git a/3.24.8-scylla/.doctrees/api/cassandra/graph.doctree b/3.24.8-scylla/.doctrees/api/cassandra/graph.doctree new file mode 100644 index 0000000000..b0def0b9a5 Binary files /dev/null and b/3.24.8-scylla/.doctrees/api/cassandra/graph.doctree differ diff --git a/3.24.8-scylla/.doctrees/api/cassandra/io/asyncioreactor.doctree b/3.24.8-scylla/.doctrees/api/cassandra/io/asyncioreactor.doctree new file mode 100644 index 0000000000..6ec8f72c6c Binary files /dev/null and b/3.24.8-scylla/.doctrees/api/cassandra/io/asyncioreactor.doctree differ diff --git a/3.24.8-scylla/.doctrees/api/cassandra/io/asyncorereactor.doctree b/3.24.8-scylla/.doctrees/api/cassandra/io/asyncorereactor.doctree new file mode 100644 index 0000000000..75a5673848 Binary files /dev/null and b/3.24.8-scylla/.doctrees/api/cassandra/io/asyncorereactor.doctree differ diff --git a/3.24.8-scylla/.doctrees/api/cassandra/io/eventletreactor.doctree b/3.24.8-scylla/.doctrees/api/cassandra/io/eventletreactor.doctree new file mode 100644 index 0000000000..30a0f25132 Binary files /dev/null and b/3.24.8-scylla/.doctrees/api/cassandra/io/eventletreactor.doctree differ diff --git a/3.24.8-scylla/.doctrees/api/cassandra/io/geventreactor.doctree b/3.24.8-scylla/.doctrees/api/cassandra/io/geventreactor.doctree new file mode 100644 index 0000000000..a68926d77b Binary files /dev/null and b/3.24.8-scylla/.doctrees/api/cassandra/io/geventreactor.doctree differ diff --git a/3.24.8-scylla/.doctrees/api/cassandra/io/libevreactor.doctree b/3.24.8-scylla/.doctrees/api/cassandra/io/libevreactor.doctree new file mode 100644 index 0000000000..486ec4e3c3 Binary files /dev/null and b/3.24.8-scylla/.doctrees/api/cassandra/io/libevreactor.doctree differ diff --git a/3.24.8-scylla/.doctrees/api/cassandra/io/twistedreactor.doctree b/3.24.8-scylla/.doctrees/api/cassandra/io/twistedreactor.doctree new file mode 100644 index 0000000000..b3f0af9161 Binary files /dev/null and b/3.24.8-scylla/.doctrees/api/cassandra/io/twistedreactor.doctree differ diff --git a/3.24.8-scylla/.doctrees/api/cassandra/metadata.doctree b/3.24.8-scylla/.doctrees/api/cassandra/metadata.doctree new file mode 100644 index 0000000000..ff71d038e4 Binary files /dev/null and b/3.24.8-scylla/.doctrees/api/cassandra/metadata.doctree differ diff --git a/3.24.8-scylla/.doctrees/api/cassandra/metrics.doctree b/3.24.8-scylla/.doctrees/api/cassandra/metrics.doctree new file mode 100644 index 0000000000..c8d70c457f Binary files /dev/null and b/3.24.8-scylla/.doctrees/api/cassandra/metrics.doctree differ diff --git a/3.24.8-scylla/.doctrees/api/cassandra/policies.doctree b/3.24.8-scylla/.doctrees/api/cassandra/policies.doctree new file mode 100644 index 0000000000..1e417abe37 Binary files /dev/null and b/3.24.8-scylla/.doctrees/api/cassandra/policies.doctree differ diff --git a/3.24.8-scylla/.doctrees/api/cassandra/pool.doctree b/3.24.8-scylla/.doctrees/api/cassandra/pool.doctree new file mode 100644 index 0000000000..f94a4462db Binary files /dev/null and b/3.24.8-scylla/.doctrees/api/cassandra/pool.doctree differ diff --git a/3.24.8-scylla/.doctrees/api/cassandra/protocol.doctree b/3.24.8-scylla/.doctrees/api/cassandra/protocol.doctree new file mode 100644 index 0000000000..77184753e3 Binary files /dev/null and b/3.24.8-scylla/.doctrees/api/cassandra/protocol.doctree differ diff --git a/3.24.8-scylla/.doctrees/api/cassandra/query.doctree b/3.24.8-scylla/.doctrees/api/cassandra/query.doctree new file mode 100644 index 0000000000..428b92bd71 Binary files /dev/null and b/3.24.8-scylla/.doctrees/api/cassandra/query.doctree differ diff --git a/3.24.8-scylla/.doctrees/api/cassandra/timestamps.doctree b/3.24.8-scylla/.doctrees/api/cassandra/timestamps.doctree new file mode 100644 index 0000000000..d8d08c438d Binary files /dev/null and b/3.24.8-scylla/.doctrees/api/cassandra/timestamps.doctree differ diff --git a/3.24.8-scylla/.doctrees/api/cassandra/util.doctree b/3.24.8-scylla/.doctrees/api/cassandra/util.doctree new file mode 100644 index 0000000000..d9eea8d509 Binary files /dev/null and b/3.24.8-scylla/.doctrees/api/cassandra/util.doctree differ diff --git a/3.24.8-scylla/.doctrees/api/index.doctree b/3.24.8-scylla/.doctrees/api/index.doctree new file mode 100644 index 0000000000..eff1f0518e Binary files /dev/null and b/3.24.8-scylla/.doctrees/api/index.doctree differ diff --git a/3.24.8-scylla/.doctrees/cqlengine/batches.doctree b/3.24.8-scylla/.doctrees/cqlengine/batches.doctree new file mode 100644 index 0000000000..e84422015e Binary files /dev/null and b/3.24.8-scylla/.doctrees/cqlengine/batches.doctree differ diff --git a/3.24.8-scylla/.doctrees/cqlengine/connections.doctree b/3.24.8-scylla/.doctrees/cqlengine/connections.doctree new file mode 100644 index 0000000000..ff51c8c3aa Binary files /dev/null and b/3.24.8-scylla/.doctrees/cqlengine/connections.doctree differ diff --git a/3.24.8-scylla/.doctrees/cqlengine/faq.doctree b/3.24.8-scylla/.doctrees/cqlengine/faq.doctree new file mode 100644 index 0000000000..130be8fd98 Binary files /dev/null and b/3.24.8-scylla/.doctrees/cqlengine/faq.doctree differ diff --git a/3.24.8-scylla/.doctrees/cqlengine/models.doctree b/3.24.8-scylla/.doctrees/cqlengine/models.doctree new file mode 100644 index 0000000000..d8494a2341 Binary files /dev/null and b/3.24.8-scylla/.doctrees/cqlengine/models.doctree differ diff --git a/3.24.8-scylla/.doctrees/cqlengine/queryset.doctree b/3.24.8-scylla/.doctrees/cqlengine/queryset.doctree new file mode 100644 index 0000000000..e2641403e7 Binary files /dev/null and b/3.24.8-scylla/.doctrees/cqlengine/queryset.doctree differ diff --git a/3.24.8-scylla/.doctrees/cqlengine/third_party.doctree b/3.24.8-scylla/.doctrees/cqlengine/third_party.doctree new file mode 100644 index 0000000000..11ea92927d Binary files /dev/null and b/3.24.8-scylla/.doctrees/cqlengine/third_party.doctree differ diff --git a/3.24.8-scylla/.doctrees/cqlengine/upgrade_guide.doctree b/3.24.8-scylla/.doctrees/cqlengine/upgrade_guide.doctree new file mode 100644 index 0000000000..33edc703a0 Binary files /dev/null and b/3.24.8-scylla/.doctrees/cqlengine/upgrade_guide.doctree differ diff --git a/3.24.8-scylla/.doctrees/dates_and_times.doctree b/3.24.8-scylla/.doctrees/dates_and_times.doctree new file mode 100644 index 0000000000..9a075b7cbd Binary files /dev/null and b/3.24.8-scylla/.doctrees/dates_and_times.doctree differ diff --git a/3.24.8-scylla/.doctrees/environment.pickle b/3.24.8-scylla/.doctrees/environment.pickle new file mode 100644 index 0000000000..f395b1c30e Binary files /dev/null and b/3.24.8-scylla/.doctrees/environment.pickle differ diff --git a/3.24.8-scylla/.doctrees/execution_profiles.doctree b/3.24.8-scylla/.doctrees/execution_profiles.doctree new file mode 100644 index 0000000000..3c6f18be5c Binary files /dev/null and b/3.24.8-scylla/.doctrees/execution_profiles.doctree differ diff --git a/3.24.8-scylla/.doctrees/faq.doctree b/3.24.8-scylla/.doctrees/faq.doctree new file mode 100644 index 0000000000..7b9f5271c0 Binary files /dev/null and b/3.24.8-scylla/.doctrees/faq.doctree differ diff --git a/3.24.8-scylla/.doctrees/getting_started.doctree b/3.24.8-scylla/.doctrees/getting_started.doctree new file mode 100644 index 0000000000..5332260ed3 Binary files /dev/null and b/3.24.8-scylla/.doctrees/getting_started.doctree differ diff --git a/3.24.8-scylla/.doctrees/index.doctree b/3.24.8-scylla/.doctrees/index.doctree new file mode 100644 index 0000000000..c42bba7eba Binary files /dev/null and b/3.24.8-scylla/.doctrees/index.doctree differ diff --git a/3.24.8-scylla/.doctrees/installation.doctree b/3.24.8-scylla/.doctrees/installation.doctree new file mode 100644 index 0000000000..f0951207a3 Binary files /dev/null and b/3.24.8-scylla/.doctrees/installation.doctree differ diff --git a/3.24.8-scylla/.doctrees/lwt.doctree b/3.24.8-scylla/.doctrees/lwt.doctree new file mode 100644 index 0000000000..29737a0420 Binary files /dev/null and b/3.24.8-scylla/.doctrees/lwt.doctree differ diff --git a/3.24.8-scylla/.doctrees/object_mapper.doctree b/3.24.8-scylla/.doctrees/object_mapper.doctree new file mode 100644 index 0000000000..6c3ec194ad Binary files /dev/null and b/3.24.8-scylla/.doctrees/object_mapper.doctree differ diff --git a/3.24.8-scylla/.doctrees/performance.doctree b/3.24.8-scylla/.doctrees/performance.doctree new file mode 100644 index 0000000000..7aa0470fc6 Binary files /dev/null and b/3.24.8-scylla/.doctrees/performance.doctree differ diff --git a/3.24.8-scylla/.doctrees/query_paging.doctree b/3.24.8-scylla/.doctrees/query_paging.doctree new file mode 100644 index 0000000000..b04508c630 Binary files /dev/null and b/3.24.8-scylla/.doctrees/query_paging.doctree differ diff --git a/3.24.8-scylla/.doctrees/scylla_cloud.doctree b/3.24.8-scylla/.doctrees/scylla_cloud.doctree new file mode 100644 index 0000000000..9949289c4d Binary files /dev/null and b/3.24.8-scylla/.doctrees/scylla_cloud.doctree differ diff --git a/3.24.8-scylla/.doctrees/scylla_specific.doctree b/3.24.8-scylla/.doctrees/scylla_specific.doctree new file mode 100644 index 0000000000..c77ab0dcdf Binary files /dev/null and b/3.24.8-scylla/.doctrees/scylla_specific.doctree differ diff --git a/3.24.8-scylla/.doctrees/security.doctree b/3.24.8-scylla/.doctrees/security.doctree new file mode 100644 index 0000000000..90d8a16f75 Binary files /dev/null and b/3.24.8-scylla/.doctrees/security.doctree differ diff --git a/3.24.8-scylla/.doctrees/upgrading.doctree b/3.24.8-scylla/.doctrees/upgrading.doctree new file mode 100644 index 0000000000..39851cfa64 Binary files /dev/null and b/3.24.8-scylla/.doctrees/upgrading.doctree differ diff --git a/3.24.8-scylla/.doctrees/user_defined_types.doctree b/3.24.8-scylla/.doctrees/user_defined_types.doctree new file mode 100644 index 0000000000..c15e67892e Binary files /dev/null and b/3.24.8-scylla/.doctrees/user_defined_types.doctree differ diff --git a/3.24.8-scylla/.nojekyll b/3.24.8-scylla/.nojekyll new file mode 100644 index 0000000000..e69de29bb2 diff --git a/3.24.8-scylla/404.html b/3.24.8-scylla/404.html new file mode 100644 index 0000000000..d60936cbfe --- /dev/null +++ b/3.24.8-scylla/404.html @@ -0,0 +1,31 @@ + + + + + + + + + ScyllaDB + + + + + + + + + + + +
+

404

+

The ScyllaDB monster ate your page!

+

+ Home +

+
+ + + \ No newline at end of file diff --git a/3.24.8-scylla/CHANGELOG.html b/3.24.8-scylla/CHANGELOG.html new file mode 100644 index 0000000000..a0cb93de34 --- /dev/null +++ b/3.24.8-scylla/CHANGELOG.html @@ -0,0 +1,2886 @@ + + + + + + + + + + + + + CHANGELOG | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

CHANGELOG

+
+

3.24.0

+

June 18, 2020

+
+

Features

+
    +
  • Make geomet an optional dependency at runtime (PYTHON-1237)

  • +
  • Add use_default_tempdir cloud config options (PYTHON-1245)

  • +
  • Tcp flow control for libevreactor (PYTHON-1248)

  • +
+
+
+

Bug Fixes

+
    +
  • Unable to connect to a cloud cluster using Ubuntu 20.04 (PYTHON-1238)

  • +
  • PlainTextAuthProvider fails with unicode chars and Python3 (PYTHON-1241)

  • +
  • [GRAPH] Graph execution profiles consistency level are not set to LOCAL_QUORUM with a cloud cluster (PYTHON-1240)

  • +
  • [GRAPH] Can’t write data in a Boolean field using the Fluent API (PYTHON-1239)

  • +
  • [GRAPH] Fix elementMap() result deserialization (PYTHON-1233)

  • +
+
+
+

Others

+
    +
  • Bump geomet dependency version to 0.2 (PYTHON-1243)

  • +
  • Bump gremlinpython dependency version to 3.4.6 (PYTHON-1212)

  • +
  • Improve fluent graph documentation for core graphs (PYTHON-1244)

  • +
+
+
+
+

3.23.0

+

April 6, 2020

+
+

Features

+
    +
  • Transient Replication Support (PYTHON-1207)

  • +
  • Support system.peers_v2 and port discovery for C* 4.0 (PYTHON-700)

  • +
+
+
+

Bug Fixes

+
    +
  • Asyncore logging exception on shutdown (PYTHON-1228)

  • +
+
+
+
+

3.22.0

+

February 26, 2020

+
+

Features

+
    +
  • Add all() function to the ResultSet API (PYTHON-1203)

  • +
  • Parse new schema metadata in NGDG and generate table edges CQL syntax (PYTHON-996)

  • +
  • Add GraphSON3 support (PYTHON-788)

  • +
  • Use GraphSON3 as default for Native graphs (PYTHON-1004)

  • +
  • Add Tuple and UDT types for native graph (PYTHON-1005)

  • +
  • Add Duration type for native graph (PYTHON-1000)

  • +
  • Add gx:ByteBuffer graphson type support for Blob field (PYTHON-1027)

  • +
  • Enable Paging Through DSE Driver for Gremlin Traversals (PYTHON-1045)

  • +
  • Provide numerical wrappers to ensure proper graphson schema definition (PYTHON-1051)

  • +
  • Resolve the row_factory automatically for native graphs (PYTHON-1056)

  • +
  • Add g:TraversalMetrics/g:Metrics graph deserializers (PYTHON-1057)

  • +
  • Add g:BulkSet graph deserializers (PYTHON-1060)

  • +
  • Update Graph Engine names and the way to create a Classic/Native Graph (PYTHON-1090)

  • +
  • Update Native to Core Graph Engine

  • +
  • Add graphson3 and native graph support (PYTHON-1039)

  • +
  • Enable Paging Through DSE Driver for Gremlin Traversals (PYTHON-1045)

  • +
  • Expose filter predicates for cql collections (PYTHON-1019)

  • +
  • Add g:TraversalMetrics/Metrics deserializers (PYTHON-1057)

  • +
  • Make graph metadata handling more robust (PYTHON-1204)

  • +
+
+
+

Bug Fixes

+
    +
  • Make sure to only query the native_transport_address column with DSE (PYTHON-1205)

  • +
+
+
+
+

3.21.0

+

January 15, 2020

+
+

Features

+
    +
  • Unified driver: merge core and DSE drivers into a single package (PYTHON-1130)

  • +
  • Add Python 3.8 support (PYTHON-1189)

  • +
  • Allow passing ssl context for Twisted (PYTHON-1161)

  • +
  • Ssl context and cloud support for Eventlet (PYTHON-1162)

  • +
  • Cloud Twisted support (PYTHON-1163)

  • +
  • Add additional_write_policy and read_repair to system schema parsing (PYTHON-1048)

  • +
  • Flexible version parsing (PYTHON-1174)

  • +
  • Support NULL in collection deserializer (PYTHON-1123)

  • +
  • [GRAPH] Ability to execute Fluent Graph queries asynchronously (PYTHON-1129)

  • +
+
+
+

Bug Fixes

+
    +
  • Handle prepared id mismatch when repreparing on the fly (PYTHON-1124)

  • +
  • re-raising the CQLEngineException will fail on Python 3 (PYTHON-1166)

  • +
  • asyncio message chunks can be processed discontinuously (PYTHON-1185)

  • +
  • Reconnect attempts persist after downed node removed from peers (PYTHON-1181)

  • +
  • Connection fails to validate ssl certificate hostname when SSLContext.check_hostname is set (PYTHON-1186)

  • +
  • ResponseFuture._set_result crashes on connection error when used with PrepareMessage (PYTHON-1187)

  • +
  • Insights fail to serialize the startup message when the SSL Context is from PyOpenSSL (PYTHON-1192)

  • +
+
+
+

Others

+
    +
  • The driver has a new dependency: geomet. It comes from the dse-driver unification and +is used to support DSE geo types.

  • +
  • Remove *read_repair_chance table options (PYTHON-1140)

  • +
  • Avoid warnings about unspecified load balancing policy when connecting to a cloud cluster (PYTHON-1177)

  • +
  • Add new DSE CQL keywords (PYTHON-1122)

  • +
  • Publish binary wheel distributions (PYTHON-1013)

  • +
+
+
+

Deprecations

+
    +
  • DSELoadBalancingPolicy will be removed in the next major, consider using +the DefaultLoadBalancingPolicy.

  • +
+

Merged from dse-driver:

+
+
+

Features

+
    +
  • Insights integration (PYTHON-1047)

  • +
  • Graph execution profiles should preserve their graph_source when graph_options is overridden (PYTHON-1021)

  • +
  • Add NodeSync metadata (PYTHON-799)

  • +
  • Add new NodeSync failure values (PYTHON-934)

  • +
  • DETERMINISTIC and MONOTONIC Clauses for Functions and Aggregates (PYTHON-955)

  • +
  • GraphOptions should show a warning for unknown parameters (PYTHON-819)

  • +
  • DSE protocol version 2 and continous paging backpressure (PYTHON-798)

  • +
  • GraphSON2 Serialization/Deserialization Support (PYTHON-775)

  • +
  • Add graph-results payload option for GraphSON format (PYTHON-773)

  • +
  • Create an AuthProvider for the DSE transitional mode (PYTHON-831)

  • +
  • Implement serializers for the Graph String API (PYTHON-778)

  • +
  • Provide deserializers for GraphSON types (PYTHON-782)

  • +
  • Add Graph DurationType support (PYTHON-607)

  • +
  • Support DSE DateRange type (PYTHON-668)

  • +
  • RLAC CQL output for materialized views (PYTHON-682)

  • +
  • Add Geom Types wkt deserializer

  • +
  • DSE Graph Client timeouts in custom payload (PYTHON-589)

  • +
  • Make DSEGSSAPIAuthProvider accept principal name (PYTHON-574)

  • +
  • Add config profiles to DSE graph execution (PYTHON-570)

  • +
  • DSE Driver version checking (PYTHON-568)

  • +
  • Distinct default timeout for graph queries (PYTHON-477)

  • +
  • Graph result parsing for known types (PYTHON-479,487)

  • +
  • Distinct read/write CL for graph execution (PYTHON-509)

  • +
  • Target graph analytics query to spark master when available (PYTHON-510)

  • +
+
+
+

Bug Fixes

+
    +
  • Continuous paging sessions raise RuntimeError when results are not entirely consumed (PYTHON-1054)

  • +
  • GraphSON Property deserializer should return a dict instead of a set (PYTHON-1033)

  • +
  • ResponseFuture.has_more_pages may hold the wrong value (PYTHON-946)

  • +
  • DETERMINISTIC clause in AGGREGATE misplaced in CQL generation (PYTHON-963)

  • +
  • graph module import cause a DLL issue on Windows due to its cythonizing failure (PYTHON-900)

  • +
  • Update date serialization to isoformat in graph (PYTHON-805)

  • +
  • DateRange Parse Error (PYTHON-729)

  • +
  • MontonicTimestampGenerator.__init__ ignores class defaults (PYTHON-728)

  • +
  • metadata.get_host returning None unexpectedly (PYTHON-709)

  • +
  • Sockets associated with sessions not getting cleaned up on session.shutdown() (PYTHON-673)

  • +
  • Resolve FQDN from ip address and use that as host passed to SASLClient (PYTHON-566)

  • +
  • Geospatial type implementations don’t handle ‘EMPTY’ values. (PYTHON-481)

  • +
  • Correctly handle other types in geo type equality (PYTHON-508)

  • +
+
+
+

Other

+
    +
  • Add tests around cqlengine and continuous paging (PYTHON-872)

  • +
  • Add an abstract GraphStatement to handle different graph statements (PYTHON-789)

  • +
  • Write documentation examples for DSE 2.0 features (PYTHON-732)

  • +
  • DSE_V1 protocol should not include all of protocol v5 (PYTHON-694)

  • +
+
+
+
+

3.20.2

+

November 19, 2019

+
+

Bug Fixes

+
    +
  • Fix import error for old python installation without SSLContext (PYTHON-1183)

  • +
+
+
+
+

3.20.1

+

November 6, 2019

+
+

Bug Fixes

+
    +
  • ValueError: too many values to unpack (expected 2)” when there are two dashes in server version number (PYTHON-1172)

  • +
+
+
+
+

3.20.0

+

October 28, 2019

+
+

Features

+
    +
  • DataStax Astra Support (PYTHON-1074)

  • +
  • Use 4.0 schema parser in 4 alpha and snapshot builds (PYTHON-1158)

  • +
+
+
+

Bug Fixes

+
    +
  • Connection setup methods prevent using ExecutionProfile in cqlengine (PYTHON-1009)

  • +
  • Driver deadlock if all connections dropped by heartbeat whilst request in flight and request times out (PYTHON-1044)

  • +
  • Exception when use pk__token__gt filter In python 3.7 (PYTHON-1121)

  • +
+
+
+
+

3.19.0

+

August 26, 2019

+
+

Features

+
    +
  • Add Python 3.7 support (PYTHON-1016)

  • +
  • Future-proof Mapping imports (PYTHON-1023)

  • +
  • Include param values in cqlengine logging (PYTHON-1105)

  • +
  • NTS Token Replica Map Generation is slow (PYTHON-622)

  • +
+
+
+

Bug Fixes

+
    +
  • as_cql_query UDF/UDA parameters incorrectly includes “frozen” if arguments are collections (PYTHON-1031)

  • +
  • cqlengine does not currently support combining TTL and TIMESTAMP on INSERT (PYTHON-1093)

  • +
  • Fix incorrect metadata for compact counter tables (PYTHON-1100)

  • +
  • Call ConnectionException with correct kwargs (PYTHON-1117)

  • +
  • Can’t connect to clusters built from source because version parsing doesn’t handle ‘x.y-SNAPSHOT’ (PYTHON-1118)

  • +
  • Discovered node doesn´t honor the configured Cluster port on connection (PYTHON-1127)

  • +
  • Exception when use pk__token__gt filter In python 3.7 (PYTHON-1121)

  • +
+
+
+

Other

+
    +
  • Remove invalid warning in set_session when we initialize a default connection (PYTHON-1104)

  • +
  • Set the proper default ExecutionProfile.row_factory value (PYTHON-1119)

  • +
+
+
+
+

3.18.0

+

May 27, 2019

+
+

Features

+
    +
  • Abstract Host Connection information (PYTHON-1079)

  • +
  • Improve version parsing to support a non-integer 4th component (PYTHON-1091)

  • +
  • Expose on_request_error method in the RetryPolicy (PYTHON-1064)

  • +
  • Add jitter to ExponentialReconnectionPolicy (PYTHON-1065)

  • +
+
+
+

Bug Fixes

+
    +
  • Fix error when preparing queries with beta protocol v5 (PYTHON-1081)

  • +
  • Accept legacy empty strings as column names (PYTHON-1082)

  • +
  • Let util.SortedSet handle uncomparable elements (PYTHON-1087)

  • +
+
+
+
+

3.17.1

+

May 2, 2019

+
+

Bug Fixes

+
    +
  • Socket errors EAGAIN/EWOULDBLOCK are not handled properly and cause timeouts (PYTHON-1089)

  • +
+
+
+
+

3.17.0

+

February 19, 2019

+
+

Features

+
    +
  • Send driver name and version in startup message (PYTHON-1068)

  • +
  • Add Cluster ssl_context option to enable SSL (PYTHON-995)

  • +
  • Allow encrypted private keys for 2-way SSL cluster connections (PYTHON-995)

  • +
  • Introduce new method ConsistencyLevel.is_serial (PYTHON-1067)

  • +
  • Add Session.get_execution_profile (PYTHON-932)

  • +
  • Add host kwarg to Session.execute/execute_async APIs to send a query to a specific node (PYTHON-993)

  • +
+
+
+

Bug Fixes

+
    +
  • NoHostAvailable when all hosts are up and connectable (PYTHON-891)

  • +
  • Serial consistency level is not used (PYTHON-1007)

  • +
+
+
+

Other

+
    +
  • Fail faster on incorrect lz4 import (PYTHON-1042)

  • +
  • Bump Cython dependency version to 0.29 (PYTHON-1036)

  • +
  • Expand Driver SSL Documentation (PYTHON-740)

  • +
+
+
+

Deprecations

+
    +
  • Using Cluster.ssl_options to enable SSL is deprecated and will be removed in +the next major release, use ssl_context.

  • +
  • DowngradingConsistencyRetryPolicy is deprecated and will be +removed in the next major release. (PYTHON-937)

  • +
+
+
+
+

3.16.0

+

November 12, 2018

+
+

Bug Fixes

+
    +
  • Improve and fix socket error-catching code in nonblocking-socket reactors (PYTHON-1024)

  • +
  • Non-ASCII characters in schema break CQL string generation (PYTHON-1008)

  • +
  • Fix OSS driver’s virtual table support against DSE 6.0.X and future server releases (PYTHON-1020)

  • +
  • ResultSet.one() fails if the row_factory is using a generator (PYTHON-1026)

  • +
  • Log profile name on attempt to create existing profile (PYTHON-944)

  • +
  • Cluster instantiation fails if any contact points’ hostname resolution fails (PYTHON-895)

  • +
+
+
+

Other

+
    +
  • Fix tests when RF is not maintained if we decomission a node (PYTHON-1017)

  • +
  • Fix wrong use of ResultSet indexing (PYTHON-1015)

  • +
+
+
+
+

3.15.1

+

September 6, 2018

+
+

Bug Fixes

+
    +
  • C* 4.0 schema-parsing logic breaks running against DSE 6.0.X (PYTHON-1018)

  • +
+
+
+
+

3.15.0

+

August 30, 2018

+
+

Features

+
    +
  • Parse Virtual Keyspace Metadata (PYTHON-992)

  • +
+
+
+

Bug Fixes

+
    +
  • Tokenmap.get_replicas returns the wrong value if token coincides with the end of the range (PYTHON-978)

  • +
  • Python Driver fails with “more than 255 arguments” python exception when > 255 columns specified in query response (PYTHON-893)

  • +
  • Hang in integration.standard.test_cluster.ClusterTests.test_set_keyspace_twice (PYTHON-998)

  • +
  • Asyncore reactors should use a global variable instead of a class variable for the event loop (PYTHON-697)

  • +
+
+
+

Other

+
    +
  • Use global variable for libev loops so it can be subclassed (PYTHON-973)

  • +
  • Update SchemaParser for V4 (PYTHON-1006)

  • +
  • Bump Cython dependency version to 0.28 (PYTHON-1012)

  • +
+
+
+
+

3.14.0

+

April 17, 2018

+
+

Features

+
    +
  • Add one() function to the ResultSet API (PYTHON-947)

  • +
  • Create an utility function to fetch concurrently many keys from the same replica (PYTHON-647)

  • +
  • Allow filter queries with fields that have an index managed outside of cqlengine (PYTHON-966)

  • +
  • Twisted SSL Support (PYTHON-343)

  • +
  • Support IS NOT NULL operator in cqlengine (PYTHON-968)

  • +
+
+
+

Other

+
    +
  • Fix Broken Links in Docs (PYTHON-916)

  • +
  • Reevaluate MONKEY_PATCH_LOOP in test codebase (PYTHON-903)

  • +
  • Remove CASS_SERVER_VERSION and replace it for CASSANDRA_VERSION in tests (PYTHON-910)

  • +
  • Refactor CASSANDRA_VERSION to a some kind of version object (PYTHON-915)

  • +
  • Log warning when driver configures an authenticator, but server does not request authentication (PYTHON-940)

  • +
  • Warn users when using the deprecated Session.default_consistency_level (PYTHON-953)

  • +
  • Add DSE smoke test to OSS driver tests (PYTHON-894)

  • +
  • Document long compilation times and workarounds (PYTHON-868)

  • +
  • Improve error for batch WriteTimeouts (PYTHON-941)

  • +
  • Deprecate ResultSet indexing (PYTHON-945)

  • +
+
+
+
+

3.13.0

+

January 30, 2018

+
+

Features

+
    +
  • cqlengine: LIKE filter operator (PYTHON-512)

  • +
  • Support cassandra.query.BatchType with cqlengine BatchQuery (PYTHON-888)

  • +
+
+
+

Bug Fixes

+
    +
  • AttributeError: ‘NoneType’ object has no attribute ‘add_timer’ (PYTHON-862)

  • +
  • Support retry_policy in PreparedStatement (PYTHON-861)

  • +
  • __del__ method in Session is throwing an exception (PYTHON-813)

  • +
  • LZ4 import issue with recent versions (PYTHON-897)

  • +
  • ResponseFuture._connection can be None when returning request_id (PYTHON-853)

  • +
  • ResultSet.was_applied doesn’t support batch with LWT statements (PYTHON-848)

  • +
+
+
+

Other

+
    +
  • cqlengine: avoid warning when unregistering connection on shutdown (PYTHON-865)

  • +
  • Fix DeprecationWarning of log.warn (PYTHON-846)

  • +
  • Fix example_mapper.py for python3 (PYTHON-860)

  • +
  • Possible deadlock on cassandra.concurrent.execute_concurrent (PYTHON-768)

  • +
  • Add some known deprecated warnings for 4.x (PYTHON-877)

  • +
  • Remove copyright dates from copyright notices (PYTHON-863)

  • +
  • Remove “Experimental” tag from execution profiles documentation (PYTHON-840)

  • +
  • request_timer metrics descriptions are slightly incorrect (PYTHON-885)

  • +
  • Remove “Experimental” tag from cqlengine connections documentation (PYTHON-892)

  • +
  • Set in documentation default consistency for operations is LOCAL_ONE (PYTHON-901)

  • +
+
+
+
+

3.12.0

+

November 6, 2017

+
+

Features

+
    +
  • Send keyspace in QUERY, PREPARE, and BATCH messages (PYTHON-678)

  • +
  • Add IPv4Address/IPv6Address support for inet types (PYTHON-751)

  • +
  • WriteType.CDC and VIEW missing (PYTHON-794)

  • +
  • Warn on Cluster init if contact points are specified but LBP isn’t (legacy mode) (PYTHON-812)

  • +
  • Warn on Cluster init if contact points are specified but LBP isn’t (exection profile mode) (PYTHON-838)

  • +
  • Include hash of result set metadata in prepared stmt id (PYTHON-808)

  • +
  • Add NO_COMPACT startup option (PYTHON-839)

  • +
  • Add new exception type for CDC (PYTHON-837)

  • +
  • Allow 0ms in ConstantSpeculativeExecutionPolicy (PYTHON-836)

  • +
  • Add asyncio reactor (PYTHON-507)

  • +
+
+
+

Bug Fixes

+
    +
  • Both _set_final_exception/result called for the same ResponseFuture (PYTHON-630)

  • +
  • Use of DCAwareRoundRobinPolicy raises NoHostAvailable exception (PYTHON-781)

  • +
  • Not create two sessions by default in CQLEngine (PYTHON-814)

  • +
  • Bug when subclassing AyncoreConnection (PYTHON-827)

  • +
  • Error at cleanup when closing the asyncore connections (PYTHON-829)

  • +
  • Fix sites where sessions can change during iteration (PYTHON-793)

  • +
  • cqlengine: allow min_length=0 for Ascii and Text column types (PYTHON-735)

  • +
  • Rare exception when “sys.exit(0)” after query timeouts (PYTHON-752)

  • +
  • Dont set the session keyspace when preparing statements (PYTHON-843)

  • +
  • Use of DCAwareRoundRobinPolicy raises NoHostAvailable exception (PYTHON-781)

  • +
+
+
+

Other

+
    +
  • Remove DeprecationWarning when using WhiteListRoundRobinPolicy (PYTHON-810)

  • +
  • Bump Cython dependency version to 0.27 (PYTHON-833)

  • +
+
+
+
+

3.11.0

+

July 24, 2017

+
+

Features

+
    +
  • Add idle_heartbeat_timeout cluster option to tune how long to wait for heartbeat responses. (PYTHON-762)

  • +
  • Add HostFilterPolicy (PYTHON-761)

  • +
+
+
+

Bug Fixes

+
    +
  • is_idempotent flag is not propagated from PreparedStatement to BoundStatement (PYTHON-736)

  • +
  • Fix asyncore hang on exit (PYTHON-767)

  • +
  • Driver takes several minutes to remove a bad host from session (PYTHON-762)

  • +
  • Installation doesn’t always fall back to no cython in Windows (PYTHON-763)

  • +
  • Avoid to replace a connection that is supposed to shutdown (PYTHON-772)

  • +
  • request_ids may not be returned to the pool (PYTHON-739)

  • +
  • Fix murmur3 on big-endian systems (PYTHON-653)

  • +
  • Ensure unused connections are closed if a Session is deleted by the GC (PYTHON-774)

  • +
  • Fix .values_list by using db names internally (cqlengine) (PYTHON-785)

  • +
+
+
+

Other

+
    +
  • Bump Cython dependency version to 0.25.2 (PYTHON-754)

  • +
  • Fix DeprecationWarning when using lz4 (PYTHON-769)

  • +
  • Deprecate WhiteListRoundRobinPolicy (PYTHON-759)

  • +
  • Improve upgrade guide for materializing pages (PYTHON-464)

  • +
  • Documentation for time/date specifies timestamp inupt as microseconds (PYTHON-717)

  • +
  • Point to DSA Slack, not IRC, in docs index

  • +
+
+
+
+

3.10.0

+

May 24, 2017

+
+

Features

+
    +
  • Add Duration type to cqlengine (PYTHON-750)

  • +
  • Community PR review: Raise error on primary key update only if its value changed (PYTHON-705)

  • +
  • get_query_trace() contract is ambiguous (PYTHON-196)

  • +
+
+
+

Bug Fixes

+
    +
  • Queries using speculative execution policy timeout prematurely (PYTHON-755)

  • +
  • Fix map where results are not consumed (PYTHON-749)

  • +
  • Driver fails to encode Duration’s with large values (PYTHON-747)

  • +
  • UDT values are not updated correctly in CQLEngine (PYTHON-743)

  • +
  • UDT types are not validated in CQLEngine (PYTHON-742)

  • +
  • to_python is not implemented for types columns.Type and columns.Date in CQLEngine (PYTHON-741)

  • +
  • Clients spin infinitely trying to connect to a host that is drained (PYTHON-734)

  • +
  • Resulset.get_query_trace returns empty trace sometimes (PYTHON-730)

  • +
  • Memory grows and doesn’t get removed (PYTHON-720)

  • +
  • Fix RuntimeError caused by change dict size during iteration (PYTHON-708)

  • +
  • fix ExponentialReconnectionPolicy may throw OverflowError problem (PYTHON-707)

  • +
  • Avoid using nonexistent prepared statement in ResponseFuture (PYTHON-706)

  • +
+
+
+

Other

+
    +
  • Update README (PYTHON-746)

  • +
  • Test python versions 3.5 and 3.6 (PYTHON-737)

  • +
  • Docs Warning About Prepare select * (PYTHON-626)

  • +
  • Increase Coverage in CqlEngine Test Suite (PYTHON-505)

  • +
  • Example SSL connection code does not verify server certificates (PYTHON-469)

  • +
+
+
+
+

3.9.0

+
+

Features

+
    +
  • cqlengine: remove elements by key from a map (PYTHON-688)

  • +
+
+
+

Bug Fixes

+
    +
  • improve error handling when connecting to non-existent keyspace (PYTHON-665)

  • +
  • Sockets associated with sessions not getting cleaned up on session.shutdown() (PYTHON-673)

  • +
  • rare flake on integration.standard.test_cluster.ClusterTests.test_clone_shared_lbp (PYTHON-727)

  • +
  • MontonicTimestampGenerator.__init__ ignores class defaults (PYTHON-728)

  • +
  • race where callback or errback for request may not be called (PYTHON-733)

  • +
  • cqlengine: model.update() should not update columns with a default value that hasn’t changed (PYTHON-657)

  • +
  • cqlengine: field value manager’s explicit flag is True when queried back from cassandra (PYTHON-719)

  • +
+
+
+

Other

+
    +
  • Connection not closed in example_mapper (PYTHON-723)

  • +
  • Remove mention of pre-2.0 C* versions from OSS 3.0+ docs (PYTHON-710)

  • +
+
+
+
+

3.8.1

+

March 16, 2017

+
+

Bug Fixes

+
    +
  • implement __le__/__ge__/__ne__ on some custom types (PYTHON-714)

  • +
  • Fix bug in eventlet and gevent reactors that could cause hangs (PYTHON-721)

  • +
  • Fix DecimalType regression (PYTHON-724)

  • +
+
+
+
+

3.8.0

+
+

Features

+
    +
  • Quote index names in metadata CQL generation (PYTHON-616)

  • +
  • On column deserialization failure, keep error message consistent between python and cython (PYTHON-631)

  • +
  • TokenAwarePolicy always sends requests to the same replica for a given key (PYTHON-643)

  • +
  • Added cql types to result set (PYTHON-648)

  • +
  • Add __len__ to BatchStatement (PYTHON-650)

  • +
  • Duration Type for Cassandra (PYTHON-655)

  • +
  • Send flags with PREPARE message in v5 (PYTHON-684)

  • +
+
+
+

Bug Fixes

+
    +
  • Potential Timing issue if application exits prior to session pool initialization (PYTHON-636)

  • +
  • “Host X.X.X.X has been marked down” without any exceptions (PYTHON-640)

  • +
  • NoHostAvailable or OperationTimedOut when using execute_concurrent with a generator that inserts into more than one table (PYTHON-642)

  • +
  • ResponseFuture creates Timers and don’t cancel them even when result is received which leads to memory leaks (PYTHON-644)

  • +
  • Driver cannot connect to Cassandra version > 3 (PYTHON-646)

  • +
  • Unable to import model using UserType without setuping connection since 3.7 (PYTHON-649)

  • +
  • Don’t prepare queries on ignored hosts on_up (PYTHON-669)

  • +
  • Sockets associated with sessions not getting cleaned up on session.shutdown() (PYTHON-673)

  • +
  • Make client timestamps strictly monotonic (PYTHON-676)

  • +
  • cassandra.cqlengine.connection.register_connection broken when hosts=None (PYTHON-692)

  • +
+
+
+

Other

+
    +
  • Create a cqlengine doc section explaining None semantics (PYTHON-623)

  • +
  • Resolve warnings in documentation generation (PYTHON-645)

  • +
  • Cython dependency (PYTHON-686)

  • +
  • Drop Support for Python 2.6 (PYTHON-690)

  • +
+
+
+
+

3.7.1

+

October 26, 2016

+
+

Bug Fixes

+
    +
  • Cython upgrade has broken stable version of cassandra-driver (PYTHON-656)

  • +
+
+
+
+

3.7.0

+

September 13, 2016

+
+

Features

+
    +
  • Add v5 protocol failure map (PYTHON-619)

  • +
  • Don’t return from initial connect on first error (PYTHON-617)

  • +
  • Indicate failed column when deserialization fails (PYTHON-361)

  • +
  • Let Cluster.refresh_nodes force a token map rebuild (PYTHON-349)

  • +
  • Refresh UDTs after “keyspace updated” event with v1/v2 protocol (PYTHON-106)

  • +
  • EC2 Address Resolver (PYTHON-198)

  • +
  • Speculative query retries (PYTHON-218)

  • +
  • Expose paging state in API (PYTHON-200)

  • +
  • Don’t mark host down while one connection is active (PYTHON-498)

  • +
  • Query request size information (PYTHON-284)

  • +
  • Avoid quadratic ring processing with invalid replication factors (PYTHON-379)

  • +
  • Improve Connection/Pool creation concurrency on startup (PYTHON-82)

  • +
  • Add beta version native protocol flag (PYTHON-614)

  • +
  • cqlengine: Connections: support of multiple keyspaces and sessions (PYTHON-613)

  • +
+
+
+

Bug Fixes

+
    +
  • Race when adding a pool while setting keyspace (PYTHON-628)

  • +
  • Update results_metadata when prepared statement is reprepared (PYTHON-621)

  • +
  • CQL Export for Thrift Tables (PYTHON-213)

  • +
  • cqlengine: default value not applied to UserDefinedType (PYTHON-606)

  • +
  • cqlengine: columns are no longer hashable (PYTHON-618)

  • +
  • cqlengine: remove clustering keys from where clause when deleting only static columns (PYTHON-608)

  • +
+
+
+
+

3.6.0

+

August 1, 2016

+
+

Features

+
    +
  • Handle null values in NumpyProtocolHandler (PYTHON-553)

  • +
  • Collect greplin scales stats per cluster (PYTHON-561)

  • +
  • Update mock unit test dependency requirement (PYTHON-591)

  • +
  • Handle Missing CompositeType metadata following C* upgrade (PYTHON-562)

  • +
  • Improve Host.is_up state for HostDistance.IGNORED hosts (PYTHON-551)

  • +
  • Utilize v2 protocol’s ability to skip result set metadata for prepared statement execution (PYTHON-71)

  • +
  • Return from Cluster.connect() when first contact point connection(pool) is opened (PYTHON-105)

  • +
  • cqlengine: Add ContextQuery to allow cqlengine models to switch the keyspace context easily (PYTHON-598)

  • +
  • Standardize Validation between Ascii and Text types in Cqlengine (PYTHON-609)

  • +
+
+
+

Bug Fixes

+
    +
  • Fix geventreactor with SSL support (PYTHON-600)

  • +
  • Don’t downgrade protocol version if explicitly set (PYTHON-537)

  • +
  • Nonexistent contact point tries to connect indefinitely (PYTHON-549)

  • +
  • Execute_concurrent can exceed max recursion depth in failure mode (PYTHON-585)

  • +
  • Libev loop shutdown race (PYTHON-578)

  • +
  • Include aliases in DCT type string (PYTHON-579)

  • +
  • cqlengine: Comparison operators for Columns (PYTHON-595)

  • +
  • cqlengine: disentangle default_time_to_live table option from model query default TTL (PYTHON-538)

  • +
  • cqlengine: pk__token column name issue with the equality operator (PYTHON-584)

  • +
  • cqlengine: Fix “__in” filtering operator converts True to string “True” automatically (PYTHON-596)

  • +
  • cqlengine: Avoid LWTExceptions when updating columns that are part of the condition (PYTHON-580)

  • +
  • cqlengine: Cannot execute a query when the filter contains all columns (PYTHON-599)

  • +
  • cqlengine: routing key computation issue when a primary key column is overriden by model inheritance (PYTHON-576)

  • +
+
+
+
+

3.5.0

+

June 27, 2016

+
+

Features

+
    +
  • Optional Execution Profiles for the core driver (PYTHON-569)

  • +
  • API to get the host metadata associated with the control connection node (PYTHON-583)

  • +
  • Expose CDC option in table metadata CQL (PYTHON-593)

  • +
+
+
+

Bug Fixes

+
    +
  • Clean up Asyncore socket map when fork is detected (PYTHON-577)

  • +
  • cqlengine: QuerySet only() is not respected when there are deferred fields (PYTHON-560)

  • +
+
+
+
+

3.4.1

+

May 26, 2016

+
+

Bug Fixes

+
    +
  • Gevent connection closes on IO timeout (PYTHON-573)

  • +
  • “dictionary changed size during iteration” with Python 3 (PYTHON-572)

  • +
+
+
+
+

3.4.0

+

May 24, 2016

+
+

Features

+
    +
  • Include DSE version and workload in Host data (PYTHON-555)

  • +
  • Add a context manager to Cluster and Session (PYTHON-521)

  • +
  • Better Error Message for Unsupported Protocol Version (PYTHON-157)

  • +
  • Make the error message explicitly state when an error comes from the server (PYTHON-412)

  • +
  • Short Circuit meta refresh on topo change if NEW_NODE already exists (PYTHON-557)

  • +
  • Show warning when the wrong config is passed to SimpleStatement (PYTHON-219)

  • +
  • Return namedtuple result pairs from execute_concurrent (PYTHON-362)

  • +
  • BatchStatement should enforce batch size limit in a better way (PYTHON-151)

  • +
  • Validate min/max request thresholds for connection pool scaling (PYTHON-220)

  • +
  • Handle or warn about multiple hosts with the same rpc_address (PYTHON-365)

  • +
  • Write docs around working with datetime and timezones (PYTHON-394)

  • +
+
+
+

Bug Fixes

+
    +
  • High CPU utilization when using asyncore event loop (PYTHON-239)

  • +
  • Fix CQL Export for non-ASCII Identifiers (PYTHON-447)

  • +
  • Make stress scripts Python 2.6 compatible (PYTHON-434)

  • +
  • UnicodeDecodeError when unicode characters in key in BOP (PYTHON-559)

  • +
  • WhiteListRoundRobinPolicy should resolve hosts (PYTHON-565)

  • +
  • Cluster and Session do not GC after leaving scope (PYTHON-135)

  • +
  • Don’t wait for schema agreement on ignored nodes (PYTHON-531)

  • +
  • Reprepare on_up with many clients causes node overload (PYTHON-556)

  • +
  • None inserted into host map when control connection node is decommissioned (PYTHON-548)

  • +
  • weakref.ref does not accept keyword arguments (github #585)

  • +
+
+
+
+

3.3.0

+

May 2, 2016

+
+

Features

+
    +
  • Add an AddressTranslator interface (PYTHON-69)

  • +
  • New Retry Policy Decision - try next host (PYTHON-285)

  • +
  • Don’t mark host down on timeout (PYTHON-286)

  • +
  • SSL hostname verification (PYTHON-296)

  • +
  • Add C* version to metadata or cluster objects (PYTHON-301)

  • +
  • Options to Disable Schema, Token Metadata Processing (PYTHON-327)

  • +
  • Expose listen_address of node we get ring information from (PYTHON-332)

  • +
  • Use A-record with multiple IPs for contact points (PYTHON-415)

  • +
  • Custom consistency level for populating query traces (PYTHON-435)

  • +
  • Normalize Server Exception Types (PYTHON-443)

  • +
  • Propagate exception message when DDL schema agreement fails (PYTHON-444)

  • +
  • Specialized exceptions for metadata refresh methods failure (PYTHON-527)

  • +
+
+
+

Bug Fixes

+
    +
  • Resolve contact point hostnames to avoid duplicate hosts (PYTHON-103)

  • +
  • GeventConnection stalls requests when read is a multiple of the input buffer size (PYTHON-429)

  • +
  • named_tuple_factory breaks with duplicate “cleaned” col names (PYTHON-467)

  • +
  • Connection leak if Cluster.shutdown() happens during reconnection (PYTHON-482)

  • +
  • HostConnection.borrow_connection does not block when all request ids are used (PYTHON-514)

  • +
  • Empty field not being handled by the NumpyProtocolHandler (PYTHON-550)

  • +
+
+
+
+

3.2.2

+

April 19, 2016

+
    +
  • Fix counter save-after-no-update (PYTHON-547)

  • +
+
+
+

3.2.1

+

April 13, 2016

+
    +
  • Introduced an update to allow deserializer compilation with recently released Cython 0.24 (PYTHON-542)

  • +
+
+
+

3.2.0

+

April 12, 2016

+
+

Features

+
    +
  • cqlengine: Warn on sync_schema type mismatch (PYTHON-260)

  • +
  • cqlengine: Automatically defer fields with the ‘=’ operator (and immutable values) in select queries (PYTHON-520)

  • +
  • cqlengine: support non-equal conditions for LWT (PYTHON-528)

  • +
  • cqlengine: sync_table should validate the primary key composition (PYTHON-532)

  • +
  • cqlengine: token-aware routing for mapper statements (PYTHON-535)

  • +
+
+
+

Bug Fixes

+
    +
  • Deleting a column in a lightweight transaction raises a SyntaxException #325 (PYTHON-249)

  • +
  • cqlengine: make Token function works with named tables/columns #86 (PYTHON-272)

  • +
  • comparing models with datetime fields fail #79 (PYTHON-273)

  • +
  • cython date deserializer integer math should be aligned with CPython (PYTHON-480)

  • +
  • db_field is not always respected with UpdateStatement (PYTHON-530)

  • +
  • Sync_table fails on column.Set with secondary index (PYTHON-533)

  • +
+
+
+
+

3.1.1

+

March 14, 2016

+
+

Bug Fixes

+
    +
  • cqlengine: Fix performance issue related to additional “COUNT” queries (PYTHON-522)

  • +
+
+
+
+

3.1.0

+

March 10, 2016

+
+

Features

+
    +
  • Pass name of server auth class to AuthProvider (PYTHON-454)

  • +
  • Surface schema agreed flag for DDL statements (PYTHON-458)

  • +
  • Automatically convert float and int to Decimal on serialization (PYTHON-468)

  • +
  • Eventlet Reactor IO improvement (PYTHON-495)

  • +
  • Make pure Python ProtocolHandler available even when Cython is present (PYTHON-501)

  • +
  • Optional Cython deserializer for bytes as bytearray (PYTHON-503)

  • +
  • Add Session.default_serial_consistency_level (github #510)

  • +
  • cqlengine: Expose prior state information via cqlengine LWTException (github #343, PYTHON-336)

  • +
  • cqlengine: Collection datatype “contains” operators support (Cassandra 2.1) #278 (PYTHON-258)

  • +
  • cqlengine: Add DISTINCT query operator (PYTHON-266)

  • +
  • cqlengine: Tuple cqlengine api (PYTHON-306)

  • +
  • cqlengine: Add support for UPDATE/DELETE … IF EXISTS statements (PYTHON-432)

  • +
  • cqlengine: Allow nested container types (PYTHON-478)

  • +
  • cqlengine: Add ability to set query’s fetch_size and limit (PYTHON-323)

  • +
  • cqlengine: Internalize default keyspace from successive set_session (PYTHON-486)

  • +
  • cqlengine: Warn when Model.create() on Counters (to be deprecated) (PYTHON-333)

  • +
+
+
+

Bug Fixes

+
    +
  • Bus error (alignment issues) when running cython on some ARM platforms (PYTHON-450)

  • +
  • Overflow when decoding large collections (cython) (PYTHON-459)

  • +
  • Timer heap comparison issue with Python 3 (github #466)

  • +
  • Cython deserializer date overflow at 2^31 - 1 (PYTHON-452)

  • +
  • Decode error encountered when cython deserializing large map results (PYTHON-459)

  • +
  • Don’t require Cython for build if compiler or Python header not present (PYTHON-471)

  • +
  • Unorderable types in task scheduling with Python 3 (h(PYTHON-473)

  • +
  • cqlengine: Fix crash when updating a UDT column with a None value (github #467)

  • +
  • cqlengine: Race condition in ..connection.execute with lazy_connect (PYTHON-310)

  • +
  • cqlengine: doesn’t support case sensitive column family names (PYTHON-337)

  • +
  • cqlengine: UserDefinedType mandatory in create or update (PYTHON-344)

  • +
  • cqlengine: db_field breaks UserType (PYTHON-346)

  • +
  • cqlengine: UDT badly quoted (PYTHON-347)

  • +
  • cqlengine: Use of db_field on primary key prevents querying except while tracing. (PYTHON-351)

  • +
  • cqlengine: DateType.deserialize being called with one argument vs two (PYTHON-354)

  • +
  • cqlengine: Querying without setting up connection now throws AttributeError and not CQLEngineException (PYTHON-395)

  • +
  • cqlengine: BatchQuery multiple time executing execute statements. (PYTHON-445)

  • +
  • cqlengine: Better error for management functions when no connection set (PYTHON-451)

  • +
  • cqlengine: Handle None values for UDT attributes in cqlengine (PYTHON-470)

  • +
  • cqlengine: Fix inserting None for model save (PYTHON-475)

  • +
  • cqlengine: EQ doesn’t map to a QueryOperator (setup race condition) (PYTHON-476)

  • +
  • cqlengine: class.MultipleObjectsReturned has DoesNotExist as base class (PYTHON-489)

  • +
  • cqlengine: Typo in cqlengine UserType __len__ breaks attribute assignment (PYTHON-502)

  • +
+
+
+

Other

+
    +
  • cqlengine: a major improvement on queryset has been introduced. It +is a lot more efficient to iterate large datasets: the rows are +now fetched on demand using the driver pagination.

  • +
  • cqlengine: the queryset len() and count() behaviors have changed. It +now executes a “SELECT COUNT(*)” of the query rather than returning +the size of the internal result_cache (loaded rows). On large +queryset, you might want to avoid using them due to the performance +cost. Note that trying to access objects using list index/slicing +with negative indices also requires a count to be +executed.

  • +
+
+
+
+

3.0.0

+

November 24, 2015

+
+

Features

+
    +
  • Support datetime.date objects as a DateType (PYTHON-212)

  • +
  • Add Cluster.update_view_metadata (PYTHON-407)

  • +
  • QueryTrace option to populate partial trace sessions (PYTHON-438)

  • +
  • Attach column names to ResultSet (PYTHON-439)

  • +
  • Change default consistency level to LOCAL_ONE

  • +
+
+
+

Bug Fixes

+
    +
  • Properly SerDes nested collections when protocol_version < 3 (PYTHON-215)

  • +
  • Evict UDTs from UserType cache on change (PYTHON-226)

  • +
  • Make sure query strings are always encoded UTF-8 (PYTHON-334)

  • +
  • Track previous value of columns at instantiation in CQLengine (PYTHON-348)

  • +
  • UDT CQL encoding does not work for unicode values (PYTHON-353)

  • +
  • NetworkTopologyStrategy#make_token_replica_map does not account for multiple racks in a DC (PYTHON-378)

  • +
  • Cython integer overflow on decimal type deserialization (PYTHON-433)

  • +
  • Query trace: if session hasn’t been logged, query trace can throw exception (PYTHON-442)

  • +
+
+
+
+

3.0.0rc1

+

November 9, 2015

+
+

Features

+
    +
  • Process Modernized Schema Tables for Cassandra 3.0 (PYTHON-276, PYTHON-408, PYTHON-400, PYTHON-422)

  • +
  • Remove deprecated features (PYTHON-292)

  • +
  • Don’t assign trace data to Statements (PYTHON-318)

  • +
  • Normalize results return (PYTHON-368)

  • +
  • Process Materialized View Metadata/Events (PYTHON-371)

  • +
  • Remove blist as soft dependency (PYTHON-385)

  • +
  • Change default consistency level to LOCAL_QUORUM (PYTHON-416)

  • +
  • Normalize CQL query/export in metadata model (PYTHON-405)

  • +
+
+
+

Bug Fixes

+
    +
  • Implementation of named arguments bind is non-pythonic (PYTHON-178)

  • +
  • CQL encoding is incorrect for NaN and Infinity floats (PYTHON-282)

  • +
  • Protocol downgrade issue with C* 2.0.x, 2.1.x, and python3, with non-default logging (PYTHON-409)

  • +
  • ValueError when accessing usertype with non-alphanumeric field names (PYTHON-413)

  • +
  • NumpyProtocolHandler does not play well with PagedResult (PYTHON-430)

  • +
+
+
+
+

2.7.2

+

September 14, 2015

+
+

Bug Fixes

+
    +
  • Resolve CQL export error for UDF with zero parameters (PYTHON-392)

  • +
  • Remove futures dep. for Python 3 (PYTHON-393)

  • +
  • Avoid Python closure in cdef (supports earlier Cython compiler) (PYTHON-396)

  • +
  • Unit test runtime issues (PYTHON-397,398)

  • +
+
+
+
+

2.7.1

+

August 25, 2015

+
+

Bug Fixes

+
    +
  • Explicitly include extension source files in Manifest

  • +
+
+
+
+

2.7.0

+

August 25, 2015

+

Cython is introduced, providing compiled extensions for core modules, and +extensions for optimized results deserialization.

+
+

Features

+
    +
  • General Performance Improvements for Throughput (PYTHON-283)

  • +
  • Improve synchronous request performance with Timers (PYTHON-108)

  • +
  • Enable C Extensions for PyPy Runtime (PYTHON-357)

  • +
  • Refactor SerDes functionality for pluggable interface (PYTHON-313)

  • +
  • Cython SerDes Extension (PYTHON-377)

  • +
  • Accept iterators/generators for execute_concurrent() (PYTHON-123)

  • +
  • cythonize existing modules (PYTHON-342)

  • +
  • Pure Python murmur3 implementation (PYTHON-363)

  • +
  • Make driver tolerant of inconsistent metadata (PYTHON-370)

  • +
+
+
+

Bug Fixes

+
    +
  • Drop Events out-of-order Cause KeyError on Processing (PYTHON-358)

  • +
  • DowngradingConsistencyRetryPolicy doesn’t check response count on write timeouts (PYTHON-338)

  • +
  • Blocking connect does not use connect_timeout (PYTHON-381)

  • +
  • Properly protect partition key in CQL export (PYTHON-375)

  • +
  • Trigger error callbacks on timeout (PYTHON-294)

  • +
+
+
+
+

2.6.0

+

July 20, 2015

+
+

Bug Fixes

+
    +
  • Output proper CQL for compact tables with no clustering columns (PYTHON-360)

  • +
+
+
+
+

2.6.0c2

+

June 24, 2015

+
+

Features

+
    +
  • Automatic Protocol Version Downgrade (PYTHON-240)

  • +
  • cqlengine Python 2.6 compatibility (PYTHON-288)

  • +
  • Double-dollar string quote UDF body (PYTHON-345)

  • +
  • Set models.DEFAULT_KEYSPACE when calling set_session (github #352)

  • +
+
+
+

Bug Fixes

+
    +
  • Avoid stall while connecting to mixed version cluster (PYTHON-303)

  • +
  • Make SSL work with AsyncoreConnection in python 2.6.9 (PYTHON-322)

  • +
  • Fix Murmur3Token.from_key() on Windows (PYTHON-331)

  • +
  • Fix cqlengine TimeUUID rounding error for Windows (PYTHON-341)

  • +
  • Avoid invalid compaction options in CQL export for non-SizeTiered (PYTHON-352)

  • +
+
+
+
+

2.6.0c1

+

June 4, 2015

+

This release adds support for Cassandra 2.2 features, including version +4 of the native protocol.

+
+

Features

+
    +
  • Default load balancing policy to TokenAware(DCAware) (PYTHON-160)

  • +
  • Configuration option for connection timeout (PYTHON-206)

  • +
  • Support User Defined Function and Aggregate metadata in C* 2.2 (PYTHON-211)

  • +
  • Surface request client in QueryTrace for C* 2.2+ (PYTHON-235)

  • +
  • Implement new request failure messages in protocol v4+ (PYTHON-238)

  • +
  • Metadata model now maps index meta by index name (PYTHON-241)

  • +
  • Support new types in C* 2.2: date, time, smallint, tinyint (PYTHON-245, 295)

  • +
  • cqle: add Double column type and remove Float overload (PYTHON-246)

  • +
  • Use partition key column information in prepared response for protocol v4+ (PYTHON-277)

  • +
  • Support message custom payloads in protocol v4+ (PYTHON-280, PYTHON-329)

  • +
  • Deprecate refresh_schema and replace with functions for specific entities (PYTHON-291)

  • +
  • Save trace id even when trace complete times out (PYTHON-302)

  • +
  • Warn when registering client UDT class for protocol < v3 (PYTHON-305)

  • +
  • Support client warnings returned with messages in protocol v4+ (PYTHON-315)

  • +
  • Ability to distinguish between NULL and UNSET values in protocol v4+ (PYTHON-317)

  • +
  • Expose CQL keywords in API (PYTHON-324)

  • +
+
+
+

Bug Fixes

+
    +
  • IPv6 address support on Windows (PYTHON-20)

  • +
  • Convert exceptions during automatic re-preparation to nice exceptions (PYTHON-207)

  • +
  • cqle: Quote keywords properly in table management functions (PYTHON-244)

  • +
  • Don’t default to GeventConnection when gevent is loaded, but not monkey-patched (PYTHON-289)

  • +
  • Pass dynamic host from SaslAuthProvider to SaslAuthenticator (PYTHON-300)

  • +
  • Make protocol read_inet work for Windows (PYTHON-309)

  • +
  • cqle: Correct encoding for nested types (PYTHON-311)

  • +
  • Update list of CQL keywords used quoting identifiers (PYTHON-319)

  • +
  • Make ConstantReconnectionPolicy work with infinite retries (github #327, PYTHON-325)

  • +
  • Accept UUIDs with uppercase hex as valid in cqlengine (github #335)

  • +
+
+
+
+

2.5.1

+

April 23, 2015

+
+

Bug Fixes

+
    +
  • Fix thread safety in DC-aware load balancing policy (PYTHON-297)

  • +
  • Fix race condition in node/token rebuild (PYTHON-298)

  • +
  • Set and send serial consistency parameter (PYTHON-299)

  • +
+
+
+
+

2.5.0

+

March 30, 2015

+
+

Features

+
    +
  • Integrated cqlengine object mapping package

  • +
  • Utility functions for converting timeuuids and datetime (PYTHON-99)

  • +
  • Schema metadata fetch window randomized, config options added (PYTHON-202)

  • +
  • Support for new Date and Time Cassandra types (PYTHON-190)

  • +
+
+
+

Bug Fixes

+
    +
  • Fix index target for collection indexes (full(), keys()) (PYTHON-222)

  • +
  • Thread exception during GIL cleanup (PYTHON-229)

  • +
  • Workaround for rounding anomaly in datetime.utcfromtime (Python 3.4) (PYTHON-230)

  • +
  • Normalize text serialization for lookup in OrderedMap (PYTHON-231)

  • +
  • Support reading CompositeType data (PYTHON-234)

  • +
  • Preserve float precision in CQL encoding (PYTHON-243)

  • +
+
+
+
+

2.1.4

+

January 26, 2015

+
+

Features

+
    +
  • SaslAuthenticator for Kerberos support (PYTHON-109)

  • +
  • Heartbeat for network device keepalive and detecting failures on idle connections (PYTHON-197)

  • +
  • Support nested, frozen collections for Cassandra 2.1.3+ (PYTHON-186)

  • +
  • Schema agreement wait bypass config, new call for synchronous schema refresh (PYTHON-205)

  • +
  • Add eventlet connection support (PYTHON-194)

  • +
+
+
+

Bug Fixes

+
    +
  • Schema meta fix for complex thrift tables (PYTHON-191)

  • +
  • Support for ‘unknown’ replica placement strategies in schema meta (PYTHON-192)

  • +
  • Resolve stream ID leak on set_keyspace (PYTHON-195)

  • +
  • Remove implicit timestamp scaling on serialization of numeric timestamps (PYTHON-204)

  • +
  • Resolve stream id collision when using SASL auth (PYTHON-210)

  • +
  • Correct unhexlify usage for user defined type meta in Python3 (PYTHON-208)

  • +
+
+
+
+

2.1.3

+

December 16, 2014

+
+

Features

+
    +
  • INFO-level log confirmation that a connection was opened to a node that was marked up (PYTHON-116)

  • +
  • Avoid connecting to peer with incomplete metadata (PYTHON-163)

  • +
  • Add SSL support to gevent reactor (PYTHON-174)

  • +
  • Use control connection timeout in wait for schema agreement (PYTHON-175)

  • +
  • Better consistency level representation in unavailable+timeout exceptions (PYTHON-180)

  • +
  • Update schema metadata processing to accommodate coming schema modernization (PYTHON-185)

  • +
+
+
+

Bug Fixes

+
    +
  • Support large negative timestamps on Windows (PYTHON-119)

  • +
  • Fix schema agreement for clusters with peer rpc_addres 0.0.0.0 (PYTHON-166)

  • +
  • Retain table metadata following keyspace meta refresh (PYTHON-173)

  • +
  • Use a timeout when preparing a statement for all nodes (PYTHON-179)

  • +
  • Make TokenAware routing tolerant of statements with no keyspace (PYTHON-181)

  • +
  • Update add_collback to store/invoke multiple callbacks (PYTHON-182)

  • +
  • Correct routing key encoding for composite keys (PYTHON-184)

  • +
  • Include compression option in schema export string when disabled (PYTHON-187)

  • +
+
+
+
+

2.1.2

+

October 16, 2014

+
+

Features

+
    +
  • Allow DCAwareRoundRobinPolicy to be constructed without a local_dc, defaulting +instead to the DC of a contact_point (PYTHON-126)

  • +
  • Set routing key in BatchStatement.add() if none specified in batch (PYTHON-148)

  • +
  • Improved feedback on ValueError using named_tuple_factory with invalid column names (PYTHON-122)

  • +
+
+
+

Bug Fixes

+
    +
  • Make execute_concurrent compatible with Python 2.6 (PYTHON-159)

  • +
  • Handle Unauthorized message on schema_triggers query (PYTHON-155)

  • +
  • Pure Python sorted set in support of UDTs nested in collections (PYTON-167)

  • +
  • Support CUSTOM index metadata and string export (PYTHON-165)

  • +
+
+
+
+

2.1.1

+

September 11, 2014

+
+

Features

+
    +
  • Detect triggers and include them in CQL queries generated to recreate +the schema (github-189)

  • +
  • Support IPv6 addresses (PYTHON-144) (note: basic functionality added; Windows +platform not addressed (PYTHON-20))

  • +
+
+
+

Bug Fixes

+
    +
  • Fix NetworkTopologyStrategy.export_for_schema (PYTHON-120)

  • +
  • Keep timeout for paged results (PYTHON-150)

  • +
+
+
+

Other

+
    +
  • Add frozen<> type modifier to UDTs and tuples to handle CASSANDRA-7857

  • +
+
+
+
+

2.1.0

+

August 7, 2014

+
+

Bug Fixes

+
    +
  • Correctly serialize and deserialize null values in tuples and +user-defined types (PYTHON-110)

  • +
  • Include additional header and lib dirs, allowing libevwrapper to build +against Homebrew and Mac Ports installs of libev (PYTHON-112 and 804dea3)

  • +
+
+
+
+

2.1.0c1

+

July 25, 2014

+
+

Bug Fixes

+
    +
  • Properly specify UDTs for columns in CREATE TABLE statements

  • +
  • Avoid moving retries to a new host when using request ID zero (PYTHON-88)

  • +
  • Don’t ignore fetch_size arguments to Statement constructors (github-151)

  • +
  • Allow disabling automatic paging on a per-statement basis when it’s +enabled by default for the session (PYTHON-93)

  • +
  • Raise ValueError when tuple query parameters for prepared statements +have extra items (PYTHON-98)

  • +
  • Correctly encode nested tuples and UDTs for non-prepared statements (PYTHON-100)

  • +
  • Raise TypeError when a string is used for contact_points (github #164)

  • +
  • Include User Defined Types in KeyspaceMetadata.export_as_string() (PYTHON-96)

  • +
+
+
+

Other

+
    +
  • Return list collection columns as python lists instead of tuples +now that tuples are a specific Cassandra type

  • +
+
+
+
+

2.1.0b1

+

July 11, 2014

+

This release adds support for Cassandra 2.1 features, including version +3 of the native protocol.

+
+

Features

+
    +
  • When using the v3 protocol, only one connection is opened per-host, and +throughput is improved due to reduced pooling overhead and lock contention.

  • +
  • Support for user-defined types (Cassandra 2.1+)

  • +
  • Support for tuple type in (limited usage Cassandra 2.0.9, full usage +in Cassandra 2.1)

  • +
  • Protocol-level client-side timestamps (see Session.use_client_timestamp)

  • +
  • Overridable type encoding for non-prepared statements (see Session.encoders)

  • +
  • Configurable serial consistency levels for batch statements

  • +
  • Use io.BytesIO for reduced CPU consumption (github #143)

  • +
  • Support Twisted as a reactor. Note that a Twisted-compatible +API is not exposed (so no Deferreds), this is just a reactor +implementation. (github #135, PYTHON-8)

  • +
+
+
+

Bug Fixes

+
    +
  • Fix references to xrange that do not go through “six” in libevreactor and +geventreactor (github #138)

  • +
  • Make BoundStatements inherit fetch_size from their parent +PreparedStatement (PYTHON-80)

  • +
  • Clear reactor state in child process after forking to prevent errors with +multiprocessing when the parent process has connected a Cluster before +forking (github #141)

  • +
  • Don’t share prepared statement lock across Cluster instances

  • +
  • Format CompositeType and DynamicCompositeType columns correctly in +CREATE TABLE statements.

  • +
  • Fix cassandra.concurrent behavior when dealing with automatic paging +(PYTHON-81)

  • +
  • Properly defunct connections after protocol errors

  • +
  • Avoid UnicodeDecodeError when query string is unicode (PYTHON-76)

  • +
  • Correctly capture dclocal_read_repair_chance for tables and +use it when generating CREATE TABLE statements (PYTHON-84)

  • +
  • Avoid race condition with AsyncoreConnection that may cause messages +to fail to be written until a new message is pushed

  • +
  • Make sure cluster.metadata.partitioner and cluster.metadata.token_map +are populated when all nodes in the cluster are included in the +contact points (PYTHON-90)

  • +
  • Make Murmur3 hash match Cassandra’s hash for all values (PYTHON-89, +github #147)

  • +
  • Don’t attempt to reconnect to hosts that should be ignored (according +to the load balancing policy) when a notification is received that the +host is down.

  • +
  • Add CAS WriteType, avoiding KeyError on CAS write timeout (PYTHON-91)

  • +
+
+
+
+

2.0.2

+

June 10, 2014

+
+

Bug Fixes

+
    +
  • Add six to requirements.txt

  • +
  • Avoid KeyError during schema refresh when a keyspace is dropped +and TokenAwarePolicy is not in use

  • +
  • Avoid registering multiple atexit cleanup functions when the +asyncore event loop is restarted multiple times

  • +
  • Delay initialization of reactors in order to avoid problems +with shared state when using multiprocessing (PYTHON-60)

  • +
  • Add python-six to debian dependencies, move python-blist to recommends

  • +
  • Fix memory leak when libev connections are created and +destroyed (github #93)

  • +
  • Ensure token map is rebuilt when hosts are removed from the cluster

  • +
+
+
+
+

2.0.1

+

May 28, 2014

+
+

Bug Fixes

+
    +
  • Fix check for Cluster.is_shutdown in in @run_in_executor +decorator

  • +
+
+
+
+

2.0.0

+

May 28, 2014

+
+

Features

+
    +
  • Make libev C extension Python3-compatible (PYTHON-70)

  • +
  • Support v2 protocol authentication (PYTHON-73, github #125)

  • +
+
+
+

Bug Fixes

+
    +
  • Fix murmur3 C extension compilation under Python3.4 (github #124)

  • +
+
+
+

Merged From 1.x

+
+

Features

+
    +
  • Add Session.default_consistency_level (PYTHON-14)

  • +
+
+
+

Bug Fixes

+
    +
  • Don’t strip trailing underscores from column names when using the +named_tuple_factory (PYTHON-56)

  • +
  • Ensure replication factors are ints for NetworkTopologyStrategy +to avoid TypeErrors (github #120)

  • +
  • Pass WriteType instance to RetryPolicy.on_write_timeout() instead +of the string name of the write type. This caused write timeout +errors to always be rethrown instead of retrying. (github #123)

  • +
  • Avoid submitting tasks to the ThreadPoolExecutor after shutdown. With +retries enabled, this could cause Cluster.shutdown() to hang under +some circumstances.

  • +
  • Fix unintended rebuild of token replica map when keyspaces are +discovered (on startup), added, or updated and TokenAwarePolicy is not +in use.

  • +
  • Avoid rebuilding token metadata when cluster topology has not +actually changed

  • +
  • Avoid preparing queries for hosts that should be ignored (such as +remote hosts when using the DCAwareRoundRobinPolicy) (PYTHON-75)

  • +
+
+
+

Other

+
    +
  • Add 1 second timeout to join() call on event loop thread during +interpreter shutdown. This can help to prevent the process from +hanging during shutdown.

  • +
+
+
+
+
+

2.0.0b1

+

May 6, 2014

+
+

Upgrading from 1.x

+

Cluster.shutdown() should always be called when you are done with a +Cluster instance. If it is not called, there are no guarantees that the +driver will not hang. However, if you do have a reproduceable case +where Cluster.shutdown() is not called and the driver hangs, please +report it so that we can attempt to fix it.

+

If you’re using the 2.0 driver against Cassandra 1.2, you will need +to set your protocol version to 1. For example:

+
+

cluster = Cluster(…, protocol_version=1)

+
+
+
+

Features

+
    +
  • Support v2 of Cassandra’s native protocol, which includes the following +new features: automatic query paging support, protocol-level batch statements, +and lightweight transactions

  • +
  • Support for Python 3.3 and 3.4

  • +
  • Allow a default query timeout to be set per-Session

  • +
+
+
+

Bug Fixes

+
    +
  • Avoid errors during interpreter shutdown (the driver attempts to cleanup +daemonized worker threads before interpreter shutdown)

  • +
+
+
+

Deprecations

+

The following functions have moved from cassandra.decoder to cassandra.query. +The original functions have been left in place with a DeprecationWarning for +now:

+
    +
  • cassandra.decoder.tuple_factory has moved to cassandra.query.tuple_factory

  • +
  • cassandra.decoder.named_tuple_factory has moved to cassandra.query.named_tuple_factory

  • +
  • cassandra.decoder.dict_factory has moved to cassandra.query.dict_factory

  • +
  • cassandra.decoder.ordered_dict_factory has moved to cassandra.query.ordered_dict_factory

  • +
+

Exceptions that were in cassandra.decoder have been moved to cassandra.protocol. If +you handle any of these exceptions, you must adjust the code accordingly.

+
+
+
+

1.1.2

+

May 8, 2014

+
+

Features

+
    +
  • Allow a specific compression type to be requested for communications with +Cassandra and prefer lz4 if available

  • +
+
+
+

Bug Fixes

+
    +
  • Update token metadata (for TokenAware calculations) when a node is removed +from the ring

  • +
  • Fix file handle leak with gevent reactor due to blocking Greenlet kills when +closing excess connections

  • +
  • Avoid handling a node coming up multiple times due to a reconnection attempt +succeeding close to the same time that an UP notification is pushed

  • +
  • Fix duplicate node-up handling, which could result in multiple reconnectors +being started as well as the executor threads becoming deadlocked, preventing +future node up or node down handling from being executed.

  • +
  • Handle exhausted ReconnectionPolicy schedule correctly

  • +
+
+
+

Other

+
    +
  • Don’t log at ERROR when a connection is closed during the startup +communications

  • +
  • Mke scales, blist optional dependencies

  • +
+
+
+
+

1.1.1

+

April 16, 2014

+
+

Bug Fixes

+
    +
  • Fix unconditional import of nose in setup.py (github #111)

  • +
+
+
+
+

1.1.0

+

April 16, 2014

+
+

Features

+
    +
  • Gevent is now supported through monkey-patching the stdlib (PYTHON-7, +github issue #46)

  • +
  • Support static columns in schemas, which are available starting in +Cassandra 2.1. (github issue #91)

  • +
  • Add debian packaging (github issue #101)

  • +
  • Add utility methods for easy concurrent execution of statements. See +the new cassandra.concurrent module. (github issue #7)

  • +
+
+
+

Bug Fixes

+
    +
  • Correctly supply compaction and compression parameters in CREATE statements +for tables when working with Cassandra 2.0+

  • +
  • Lowercase boolean literals when generating schemas

  • +
  • Ignore SSL_ERROR_WANT_READ and SSL_ERROR_WANT_WRITE socket errors. Previously, +these resulted in the connection being defuncted, but they can safely be +ignored by the driver.

  • +
  • Don’t reconnect the control connection every time Cluster.connect() is +called

  • +
  • Avoid race condition that could leave ResponseFuture callbacks uncalled +if the callback was added outside of the event loop thread (github issue #95)

  • +
  • Properly escape keyspace name in Session.set_keyspace(). Previously, the +keyspace name was quoted, but any quotes in the string were not escaped.

  • +
  • Avoid adding hosts to the load balancing policy before their datacenter +and rack information has been set, if possible.

  • +
  • Avoid KeyError when updating metadata after droping a table (github issues +#97, #98)

  • +
  • Use tuples instead of sets for DCAwareLoadBalancingPolicy to ensure equal +distribution of requests

  • +
+
+
+

Other

+
    +
  • Don’t ignore column names when parsing typestrings. This is needed for +user-defined type support. (github issue #90)

  • +
  • Better error message when libevwrapper is not found

  • +
  • Only try to import scales when metrics are enabled (github issue #92)

  • +
  • Cut down on the number of queries executing when a new Cluster +connects and when the control connection has to reconnect (github issue #104, +PYTHON-59)

  • +
  • Issue warning log when schema versions do not match

  • +
+
+
+
+

1.0.2

+

March 4, 2014

+
+

Bug Fixes

+
    +
  • With asyncorereactor, correctly handle EAGAIN/EWOULDBLOCK when the message from +Cassandra is a multiple of the read buffer size. Previously, if no more data +became available to read on the socket, the message would never be processed, +resulting in an OperationTimedOut error.

  • +
  • Double quote keyspace, table and column names that require them (those using +uppercase characters or keywords) when generating CREATE statements through +KeyspaceMetadata and TableMetadata.

  • +
  • Decode TimestampType as DateType. (Cassandra replaced DateType with +TimestampType to fix sorting of pre-unix epoch dates in CASSANDRA-5723.)

  • +
  • Handle latest table options when parsing the schema and generating +CREATE statements.

  • +
  • Avoid ‘Set changed size during iteration’ during query plan generation +when hosts go up or down

  • +
+
+
+

Other

+
    +
  • Remove ignored tracing_enabled parameter for SimpleStatement. The +correct way to trace a query is by setting the trace argument to True +in Session.execute() and Session.execute_async().

  • +
  • Raise TypeError instead of cassandra.query.InvalidParameterTypeError when +a parameter for a prepared statement has the wrong type; remove +cassandra.query.InvalidParameterTypeError.

  • +
  • More consistent type checking for query parameters

  • +
  • Add option to a return special object for empty string values for non-string +columns

  • +
+
+
+
+

1.0.1

+

Feb 19, 2014

+
+

Bug Fixes

+
    +
  • Include table indexes in KeyspaceMetadata.export_as_string()

  • +
  • Fix broken token awareness on ByteOrderedPartitioner

  • +
  • Always close socket when defuncting error’ed connections to avoid a potential +file descriptor leak

  • +
  • Handle “custom” types (such as the replaced DateType) correctly

  • +
  • With libevreactor, correctly handle EAGAIN/EWOULDBLOCK when the message from +Cassandra is a multiple of the read buffer size. Previously, if no more data +became available to read on the socket, the message would never be processed, +resulting in an OperationTimedOut error.

  • +
  • Don’t break tracing when a Session’s row_factory is not the default +namedtuple_factory.

  • +
  • Handle data that is already utf8-encoded for UTF8Type values

  • +
  • Fix token-aware routing for tokens that fall before the first node token in +the ring and tokens that exactly match a node’s token

  • +
  • Tolerate null source_elapsed values for Trace events. These may not be +set when events complete after the main operation has already completed.

  • +
+
+
+

Other

+
    +
  • Skip sending OPTIONS message on connection creation if compression is +disabled or not available and a CQL version has not been explicitly +set

  • +
  • Add details about errors and the last queried host to OperationTimedOut

  • +
+
+
+
+

1.0.0 Final

+

Jan 29, 2014

+
+

Bug Fixes

+
    +
  • Prevent leak of Scheduler thread (even with proper shutdown)

  • +
  • Correctly handle ignored hosts, which are common with the +DCAwareRoundRobinPolicy

  • +
  • Hold strong reference to prepared statement while executing it to avoid +garbage collection

  • +
  • Add NullHandler logging handler to the cassandra package to avoid +warnings about there being no configured logger

  • +
  • Fix bad handling of nodes that have been removed from the cluster

  • +
  • Properly escape string types within cql collections

  • +
  • Handle setting the same keyspace twice in a row

  • +
  • Avoid race condition during schema agreement checks that could result +in schema update queries returning before all nodes had seen the change

  • +
  • Preserve millisecond-level precision in datetimes when performing inserts +with simple (non-prepared) statements

  • +
  • Properly defunct connections when libev reports an error by setting +errno instead of simply logging the error

  • +
  • Fix endless hanging of some requests when using the libev reactor

  • +
  • Always start a reconnection process when we fail to connect to +a newly bootstrapped node

  • +
  • Generators map to CQL lists, not key sequences

  • +
  • Always defunct connections when an internal operation fails

  • +
  • Correctly break from handle_write() if nothing was sent (asyncore +reactor only)

  • +
  • Avoid potential double-erroring of callbacks when a connection +becomes defunct

  • +
+
+
+

Features

+
    +
  • Add default query timeout to Session

  • +
  • Add timeout parameter to Session.execute()

  • +
  • Add WhiteListRoundRobinPolicy as a load balancing policy option

  • +
  • Support for consistency level LOCAL_ONE

  • +
  • Make the backoff for fetching traces exponentially increasing and +configurable

  • +
+
+
+

Other

+
    +
  • Raise Exception if TokenAwarePolicy is used against a cluster using the +Murmur3Partitioner if the murmur3 C extension has not been compiled

  • +
  • Add encoder mapping for OrderedDict

  • +
  • Use timeouts on all control connection queries

  • +
  • Benchmark improvements, including command line options and eay +multithreading support

  • +
  • Reduced lock contention when using the asyncore reactor

  • +
  • Warn when non-datetimes are used for ‘timestamp’ column values in +prepared statements

  • +
  • Add requirements.txt and test-requirements.txt

  • +
  • TravisCI integration for running unit tests against Python 2.6, +Python 2.7, and PyPy

  • +
+
+
+
+

1.0.0b7

+

Nov 12, 2013

+

This release makes many stability improvements, especially around +prepared statements and node failure handling. In particular, +several cases where a request would never be completed (and as a +result, leave the application hanging) have been resolved.

+
+

Features

+
    +
  • Add timeout kwarg to ResponseFuture.result()

  • +
  • Create connection pools to all hosts in parallel when initializing +new Sesssions.

  • +
+
+
+

Bug Fixes

+
    +
  • Properly set exception on ResponseFuture when a query fails +against all hosts

  • +
  • Improved cleanup and reconnection efforts when reconnection fails +on a node that has recently come up

  • +
  • Use correct consistency level when retrying failed operations +against a different host. (An invalid consistency level was being +used, causing the retry to fail.)

  • +
  • Better error messages for failed Session.prepare() opertaions

  • +
  • Prepare new statements against all hosts in parallel (formerly +sequential)

  • +
  • Fix failure to save the new current keyspace on connections. (This +could cause problems for prepared statements and lead to extra +operations to continuously re-set the keyspace.)

  • +
  • Avoid sharing LoadBalancingPolicies across Cluster instances. (When +a second Cluster was connected, it effectively mark nodes down for the +first Cluster.)

  • +
  • Better handling of failures during the re-preparation sequence for +unrecognized prepared statements

  • +
  • Throttle trashing of underutilized connections to avoid trashing newly +created connections

  • +
  • Fix race condition which could result in trashed connections being closed +before the last operations had completed

  • +
  • Avoid preparing statements on the event loop thread (which could lead to +deadlock)

  • +
  • Correctly mark up non-contact point nodes discovered by the control +connection. (This lead to prepared statements not being prepared +against those hosts, generating extra traffic later when the +statements were executed and unrecognized.)

  • +
  • Correctly handle large messages through libev

  • +
  • Add timeout to schema agreement check queries

  • +
  • More complete (and less contended) locking around manipulation of the +pending message deque for libev connections

  • +
+
+
+

Other

+
    +
  • Prepare statements in batches of 10. (When many prepared statements +are in use, this allows the driver to start utilizing nodes that +were restarted more quickly.)

  • +
  • Better debug logging around connection management

  • +
  • Don’t retain unreferenced prepared statements in the local cache. +(If many different prepared statements were created, this would +increase memory usage and greatly increase the amount of time +required to begin utilizing a node that was added or marked +up.)

  • +
+
+
+
+

1.0.0b6

+

Oct 22, 2013

+
+

Bug Fixes

+
    +
  • Use lazy string formatting when logging

  • +
  • Avoid several deadlock scenarios, especially when nodes go down

  • +
  • Avoid trashing newly created connections due to insufficient traffic

  • +
  • Gracefully handle un-handled Exceptions when erroring callbacks

  • +
+
+
+

Other

+
    +
  • Node state listeners (which are called when a node is added, removed, +goes down, or comes up) should now be registered through +Cluster.register_listener() instead of through a host’s HealthMonitor +(which has been removed)

  • +
+
+
+
+

1.0.0b5

+

Oct 10, 2013

+
+

Features

+
    +
  • SSL support

  • +
+
+
+

Bug Fixes

+
    +
  • Avoid KeyError when building replica map for NetworkTopologyStrategy

  • +
  • Work around python bug which causes deadlock when a thread imports +the utf8 module

  • +
  • Handle no blist library, which is not compatible with pypy

  • +
  • Avoid deadlock triggered by a keyspace being set on a connection (which +may happen automatically for new connections)

  • +
+
+
+

Other

+
    +
  • Switch packaging from Distribute to setuptools, improved C extension +support

  • +
  • Use PEP 386 compliant beta and post-release versions

  • +
+
+
+
+

1.0.0-beta4

+

Sep 24, 2013

+
+

Features

+
    +
  • Handle new blob syntax in Cassandra 2.0 by accepting bytearray +objects for blob values

  • +
  • Add cql_version kwarg to Cluster.__init__

  • +
+
+
+

Bug Fixes

+
    +
  • Fix KeyError when building token map with NetworkTopologyStrategy +keyspaces (this prevented a Cluster from successfully connecting +at all).

  • +
  • Don’t lose default consitency level from parent PreparedStatement +when creating BoundStatements

  • +
+
+
+
+

1.0.0-beta3

+

Sep 20, 2013

+
+

Features

+
    +
  • Support for LZ4 compression (Cassandra 2.0+)

  • +
  • Token-aware routing will now utilize all replicas for a query instead +of just the first replica

  • +
+
+
+

Bug Fixes

+
    +
  • Fix libev include path for CentOS

  • +
  • Fix varint packing of the value 0

  • +
  • Correctly pack unicode values

  • +
  • Don’t attempt to return failed connections to the pool when a final result +is set

  • +
  • Fix bad iteration of connection credentials

  • +
  • Use blist’s orderedset for set collections and OrderedDict for map +collections so that Cassandra’s ordering is preserved

  • +
  • Fix connection failure on Windows due to unavailability of inet_pton +and inet_ntop. (Note that IPv6 inet_address values are still not +supported on Windows.)

  • +
  • Boolean constants shouldn’t be surrounded by single quotes

  • +
  • Avoid a potential loss of precision on float constants due to string +formatting

  • +
  • Actually utilize non-standard ports set on Cluster objects

  • +
  • Fix export of schema as a set of CQL queries

  • +
+
+
+

Other

+
    +
  • Use cStringIO for connection buffer for better performance

  • +
  • Add __repr__ method for Statement classes

  • +
  • Raise InvalidTypeParameterError when parameters of the wrong +type are used with statements

  • +
  • Make all tests compatible with Python 2.6

  • +
  • Add 1s timeout for opening new connections

  • +
+
+
+
+

1.0.0-beta2

+

Aug 19, 2013

+
+

Bug Fixes

+
    +
  • Fix pip packaging

  • +
+
+
+
+

1.0.0-beta

+

Aug 16, 2013

+

Initial release

+
+
+ + +
+ + + + + +
+ + +
+
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.24.8-scylla/CNAME b/3.24.8-scylla/CNAME new file mode 100644 index 0000000000..9f3e01a070 --- /dev/null +++ b/3.24.8-scylla/CNAME @@ -0,0 +1 @@ +python-driver.docs.scylladb.com \ No newline at end of file diff --git a/3.24.8-scylla/_sources/CHANGELOG.rst.txt b/3.24.8-scylla/_sources/CHANGELOG.rst.txt new file mode 100644 index 0000000000..f6d642b27f --- /dev/null +++ b/3.24.8-scylla/_sources/CHANGELOG.rst.txt @@ -0,0 +1,7 @@ +:orphan: + +********* +CHANGELOG +********* + +.. include:: ../CHANGELOG.rst diff --git a/3.24.8-scylla/_sources/api/cassandra.rst.txt b/3.24.8-scylla/_sources/api/cassandra.rst.txt new file mode 100644 index 0000000000..d46aae56cb --- /dev/null +++ b/3.24.8-scylla/_sources/api/cassandra.rst.txt @@ -0,0 +1,77 @@ +:mod:`cassandra` - Exceptions and Enums +======================================= + +.. module:: cassandra + +.. data:: __version_info__ + + The version of the driver in a tuple format + +.. data:: __version__ + + The version of the driver in a string format + +.. autoclass:: ConsistencyLevel + :members: + +.. autoclass:: ProtocolVersion + :members: + +.. autoclass:: UserFunctionDescriptor + :members: + :inherited-members: + +.. autoclass:: UserAggregateDescriptor + :members: + :inherited-members: + +.. autoexception:: DriverException() + :members: + +.. autoexception:: RequestExecutionException() + :members: + +.. autoexception:: Unavailable() + :members: + +.. autoexception:: Timeout() + :members: + +.. autoexception:: ReadTimeout() + :members: + +.. autoexception:: WriteTimeout() + :members: + +.. autoexception:: CoordinationFailure() + :members: + +.. autoexception:: ReadFailure() + :members: + +.. autoexception:: WriteFailure() + :members: + +.. autoexception:: FunctionFailure() + :members: + +.. autoexception:: RequestValidationException() + :members: + +.. autoexception:: ConfigurationException() + :members: + +.. autoexception:: AlreadyExists() + :members: + +.. autoexception:: InvalidRequest() + :members: + +.. autoexception:: Unauthorized() + :members: + +.. autoexception:: AuthenticationFailed() + :members: + +.. autoexception:: OperationTimedOut() + :members: diff --git a/3.24.8-scylla/_sources/api/cassandra/auth.rst.txt b/3.24.8-scylla/_sources/api/cassandra/auth.rst.txt new file mode 100644 index 0000000000..58c964cf89 --- /dev/null +++ b/3.24.8-scylla/_sources/api/cassandra/auth.rst.txt @@ -0,0 +1,22 @@ +``cassandra.auth`` - Authentication +=================================== + +.. module:: cassandra.auth + +.. autoclass:: AuthProvider + :members: + +.. autoclass:: Authenticator + :members: + +.. autoclass:: PlainTextAuthProvider + :members: + +.. autoclass:: PlainTextAuthenticator + :members: + +.. autoclass:: SaslAuthProvider + :members: + +.. autoclass:: SaslAuthenticator + :members: diff --git a/3.24.8-scylla/_sources/api/cassandra/cluster.rst.txt b/3.24.8-scylla/_sources/api/cassandra/cluster.rst.txt new file mode 100644 index 0000000000..2b3d7828a8 --- /dev/null +++ b/3.24.8-scylla/_sources/api/cassandra/cluster.rst.txt @@ -0,0 +1,228 @@ +``cassandra.cluster`` - Clusters and Sessions +============================================= + +.. module:: cassandra.cluster + +.. autoclass:: Cluster ([contact_points=('127.0.0.1',)][, port=9042][, executor_threads=2], **attr_kwargs) + + .. autoattribute:: contact_points + + .. autoattribute:: port + + .. autoattribute:: cql_version + + .. autoattribute:: protocol_version + + .. autoattribute:: compression + + .. autoattribute:: auth_provider + + .. autoattribute:: load_balancing_policy + + .. autoattribute:: reconnection_policy + + .. autoattribute:: default_retry_policy + :annotation: = + + .. autoattribute:: conviction_policy_factory + + .. autoattribute:: address_translator + + .. autoattribute:: metrics_enabled + + .. autoattribute:: metrics + + .. autoattribute:: ssl_context + + .. autoattribute:: ssl_options + + .. autoattribute:: sockopts + + .. autoattribute:: max_schema_agreement_wait + + .. autoattribute:: metadata + + .. autoattribute:: connection_class + + .. autoattribute:: control_connection_timeout + + .. autoattribute:: idle_heartbeat_interval + + .. autoattribute:: idle_heartbeat_timeout + + .. autoattribute:: schema_event_refresh_window + + .. autoattribute:: topology_event_refresh_window + + .. autoattribute:: status_event_refresh_window + + .. autoattribute:: prepare_on_all_hosts + + .. autoattribute:: reprepare_on_up + + .. autoattribute:: connect_timeout + + .. autoattribute:: schema_metadata_enabled + :annotation: = True + + .. autoattribute:: token_metadata_enabled + :annotation: = True + + .. autoattribute:: timestamp_generator + + .. autoattribute:: endpoint_factory + + .. autoattribute:: cloud + + .. automethod:: connect + + .. automethod:: shutdown + + .. automethod:: register_user_type + + .. automethod:: register_listener + + .. automethod:: unregister_listener + + .. automethod:: add_execution_profile + + .. automethod:: set_max_requests_per_connection + + .. automethod:: get_max_requests_per_connection + + .. automethod:: set_min_requests_per_connection + + .. automethod:: get_min_requests_per_connection + + .. automethod:: get_core_connections_per_host + + .. automethod:: set_core_connections_per_host + + .. automethod:: get_max_connections_per_host + + .. automethod:: set_max_connections_per_host + + .. automethod:: get_control_connection_host + + .. automethod:: refresh_schema_metadata + + .. automethod:: refresh_keyspace_metadata + + .. automethod:: refresh_table_metadata + + .. automethod:: refresh_user_type_metadata + + .. automethod:: refresh_user_function_metadata + + .. automethod:: refresh_user_aggregate_metadata + + .. automethod:: refresh_nodes + + .. automethod:: set_meta_refresh_enabled + +.. autoclass:: ExecutionProfile (load_balancing_policy=, retry_policy=None, consistency_level=ConsistencyLevel.LOCAL_ONE, serial_consistency_level=None, request_timeout=10.0, row_factory=, speculative_execution_policy=None) + :members: + :exclude-members: consistency_level + + .. autoattribute:: consistency_level + :annotation: = LOCAL_ONE + +.. autoclass:: GraphExecutionProfile (load_balancing_policy=_NOT_SET, retry_policy=None, consistency_level=ConsistencyLevel.LOCAL_ONE, serial_consistency_level=None, request_timeout=30.0, row_factory=None, graph_options=None, continuous_paging_options=_NOT_SET) + :members: + +.. autoclass:: GraphAnalyticsExecutionProfile (load_balancing_policy=None, retry_policy=None, consistency_level=ConsistencyLevel.LOCAL_ONE, serial_consistency_level=None, request_timeout=3600. * 24. * 7., row_factory=None, graph_options=None) + :members: + +.. autodata:: EXEC_PROFILE_DEFAULT + :annotation: + +.. autodata:: EXEC_PROFILE_GRAPH_DEFAULT + :annotation: + +.. autodata:: EXEC_PROFILE_GRAPH_SYSTEM_DEFAULT + :annotation: + +.. autodata:: EXEC_PROFILE_GRAPH_ANALYTICS_DEFAULT + :annotation: + +.. autoclass:: Session () + + .. autoattribute:: default_timeout + :annotation: = 10.0 + + .. autoattribute:: default_consistency_level + :annotation: = LOCAL_ONE + + .. autoattribute:: default_serial_consistency_level + :annotation: = None + + .. autoattribute:: row_factory + :annotation: = + + .. autoattribute:: default_fetch_size + + .. autoattribute:: use_client_timestamp + + .. autoattribute:: timestamp_generator + + .. autoattribute:: encoder + + .. autoattribute:: client_protocol_handler + + .. automethod:: execute(statement[, parameters][, timeout][, trace][, custom_payload][, paging_state][, host][, execute_as]) + + .. automethod:: execute_async(statement[, parameters][, trace][, custom_payload][, paging_state][, host][, execute_as]) + + .. automethod:: execute_graph(statement[, parameters][, trace][, execution_profile=EXEC_PROFILE_GRAPH_DEFAULT][, execute_as]) + + .. automethod:: execute_graph_async(statement[, parameters][, trace][, execution_profile=EXEC_PROFILE_GRAPH_DEFAULT][, execute_as]) + + .. automethod:: prepare(statement) + + .. automethod:: shutdown() + + .. automethod:: set_keyspace(keyspace) + + .. automethod:: get_execution_profile + + .. automethod:: execution_profile_clone_update + + .. automethod:: add_request_init_listener + + .. automethod:: remove_request_init_listener + +.. autoclass:: ResponseFuture () + + .. autoattribute:: query + + .. automethod:: result() + + .. automethod:: get_query_trace() + + .. automethod:: get_all_query_traces() + + .. autoattribute:: custom_payload() + + .. autoattribute:: is_schema_agreed + + .. autoattribute:: has_more_pages + + .. autoattribute:: warnings + + .. automethod:: start_fetching_next_page() + + .. automethod:: add_callback(fn, *args, **kwargs) + + .. automethod:: add_errback(fn, *args, **kwargs) + + .. automethod:: add_callbacks(callback, errback, callback_args=(), callback_kwargs=None, errback_args=(), errback_args=None) + +.. autoclass:: ResultSet () + :members: + +.. autoexception:: QueryExhausted () + +.. autoexception:: NoHostAvailable () + :members: + +.. autoexception:: UserTypeDoesNotExist () diff --git a/3.24.8-scylla/_sources/api/cassandra/concurrent.rst.txt b/3.24.8-scylla/_sources/api/cassandra/concurrent.rst.txt new file mode 100644 index 0000000000..f4bab6f048 --- /dev/null +++ b/3.24.8-scylla/_sources/api/cassandra/concurrent.rst.txt @@ -0,0 +1,8 @@ +``cassandra.concurrent`` - Utilities for Concurrent Statement Execution +======================================================================= + +.. module:: cassandra.concurrent + +.. autofunction:: execute_concurrent + +.. autofunction:: execute_concurrent_with_args diff --git a/3.24.8-scylla/_sources/api/cassandra/connection.rst.txt b/3.24.8-scylla/_sources/api/cassandra/connection.rst.txt new file mode 100644 index 0000000000..32cca590c0 --- /dev/null +++ b/3.24.8-scylla/_sources/api/cassandra/connection.rst.txt @@ -0,0 +1,21 @@ +``cassandra.connection`` - Low Level Connection Info +==================================================== + +.. module:: cassandra.connection + +.. autoexception:: ConnectionException () +.. autoexception:: ConnectionShutdown () +.. autoexception:: ConnectionBusy () +.. autoexception:: ProtocolError () + +.. autoclass:: EndPoint + :members: + +.. autoclass:: EndPointFactory + :members: + +.. autoclass:: SniEndPoint + +.. autoclass:: SniEndPointFactory + +.. autoclass:: UnixSocketEndPoint diff --git a/3.24.8-scylla/_sources/api/cassandra/cqlengine/columns.rst.txt b/3.24.8-scylla/_sources/api/cassandra/cqlengine/columns.rst.txt new file mode 100644 index 0000000000..d44be8adb8 --- /dev/null +++ b/3.24.8-scylla/_sources/api/cassandra/cqlengine/columns.rst.txt @@ -0,0 +1,89 @@ +``cassandra.cqlengine.columns`` - Column types for object mapping models +======================================================================== + +.. module:: cassandra.cqlengine.columns + +Columns +------- + +Columns in your models map to columns in your CQL table. You define CQL columns by defining column attributes on your model classes. +For a model to be valid it needs at least one primary key column and one non-primary key column. + +Just as in CQL, the order you define your columns in is important, and is the same order they are defined in on a model's corresponding table. + +Each column on your model definitions needs to be an instance of a Column class. + +.. autoclass:: Column(**kwargs) + + .. autoattribute:: primary_key + + .. autoattribute:: partition_key + + .. autoattribute:: index + + .. autoattribute:: custom_index + + .. autoattribute:: db_field + + .. autoattribute:: default + + .. autoattribute:: required + + .. autoattribute:: clustering_order + + .. autoattribute:: discriminator_column + + .. autoattribute:: static + +Column Types +------------ + +Columns of all types are initialized by passing :class:`.Column` attributes to the constructor by keyword. + +.. autoclass:: Ascii(**kwargs) + +.. autoclass:: BigInt(**kwargs) + +.. autoclass:: Blob(**kwargs) + +.. autoclass:: Bytes(**kwargs) + +.. autoclass:: Boolean(**kwargs) + +.. autoclass:: Counter + +.. autoclass:: Date(**kwargs) + +.. autoclass:: DateTime(**kwargs) + + .. autoattribute:: truncate_microseconds + +.. autoclass:: Decimal(**kwargs) + +.. autoclass:: Double(**kwargs) + +.. autoclass:: Float + +.. autoclass:: Integer(**kwargs) + +.. autoclass:: List + +.. autoclass:: Map + +.. autoclass:: Set + +.. autoclass:: SmallInt(**kwargs) + +.. autoclass:: Text + +.. autoclass:: Time(**kwargs) + +.. autoclass:: TimeUUID(**kwargs) + +.. autoclass:: TinyInt(**kwargs) + +.. autoclass:: UserDefinedType + +.. autoclass:: UUID(**kwargs) + +.. autoclass:: VarInt(**kwargs) diff --git a/3.24.8-scylla/_sources/api/cassandra/cqlengine/connection.rst.txt b/3.24.8-scylla/_sources/api/cassandra/cqlengine/connection.rst.txt new file mode 100644 index 0000000000..0f584fcca2 --- /dev/null +++ b/3.24.8-scylla/_sources/api/cassandra/cqlengine/connection.rst.txt @@ -0,0 +1,16 @@ +``cassandra.cqlengine.connection`` - Connection management for cqlengine +======================================================================== + +.. module:: cassandra.cqlengine.connection + +.. autofunction:: default + +.. autofunction:: set_session + +.. autofunction:: setup + +.. autofunction:: register_connection + +.. autofunction:: unregister_connection + +.. autofunction:: set_default_connection diff --git a/3.24.8-scylla/_sources/api/cassandra/cqlengine/management.rst.txt b/3.24.8-scylla/_sources/api/cassandra/cqlengine/management.rst.txt new file mode 100644 index 0000000000..fb483abc81 --- /dev/null +++ b/3.24.8-scylla/_sources/api/cassandra/cqlengine/management.rst.txt @@ -0,0 +1,19 @@ +``cassandra.cqlengine.management`` - Schema management for cqlengine +======================================================================== + +.. module:: cassandra.cqlengine.management + +A collection of functions for managing keyspace and table schema. + +.. autofunction:: create_keyspace_simple + +.. autofunction:: create_keyspace_network_topology + +.. autofunction:: drop_keyspace + +.. autofunction:: sync_table + +.. autofunction:: sync_type + +.. autofunction:: drop_table + diff --git a/3.24.8-scylla/_sources/api/cassandra/cqlengine/models.rst.txt b/3.24.8-scylla/_sources/api/cassandra/cqlengine/models.rst.txt new file mode 100644 index 0000000000..60b1471184 --- /dev/null +++ b/3.24.8-scylla/_sources/api/cassandra/cqlengine/models.rst.txt @@ -0,0 +1,197 @@ +``cassandra.cqlengine.models`` - Table models for object mapping +================================================================ + +.. module:: cassandra.cqlengine.models + +Model +----- +.. autoclass:: Model(\*\*kwargs) + + The initializer creates an instance of the model. Pass in keyword arguments for columns you've defined on the model. + + .. code-block:: python + + class Person(Model): + id = columns.UUID(primary_key=True) + first_name = columns.Text() + last_name = columns.Text() + + person = Person(first_name='Blake', last_name='Eggleston') + person.first_name #returns 'Blake' + person.last_name #returns 'Eggleston' + + Model attributes define how the model maps to tables in the database. These are class variables that should be set + when defining Model deriviatives. + + .. autoattribute:: __abstract__ + :annotation: = False + + .. autoattribute:: __table_name__ + + .. autoattribute:: __table_name_case_sensitive__ + + .. autoattribute:: __keyspace__ + + .. autoattribute:: __connection__ + + .. attribute:: __default_ttl__ + :annotation: = None + + Will be deprecated in release 4.0. You can set the default ttl by configuring the table ``__options__``. See :ref:`ttl-change` for more details. + + .. autoattribute:: __discriminator_value__ + + See :ref:`model_inheritance` for usage examples. + + Each table can have its own set of configuration options, including compaction. Unspecified, these default to sensible values in + the server. To override defaults, set options using the model ``__options__`` attribute, which allows options specified a dict. + + When a table is synced, it will be altered to match the options set on your table. + This means that if you are changing settings manually they will be changed back on resync. + + Do not use the options settings of cqlengine if you want to manage your compaction settings manually. + + See the `list of supported table properties for more information + `_. + + .. attribute:: __options__ + + For example: + + .. code-block:: python + + class User(Model): + __options__ = {'compaction': {'class': 'LeveledCompactionStrategy', + 'sstable_size_in_mb': '64', + 'tombstone_threshold': '.2'}, + 'comment': 'User data stored here'} + + user_id = columns.UUID(primary_key=True) + name = columns.Text() + + or : + + .. code-block:: python + + class TimeData(Model): + __options__ = {'compaction': {'class': 'SizeTieredCompactionStrategy', + 'bucket_low': '.3', + 'bucket_high': '2', + 'min_threshold': '2', + 'max_threshold': '64', + 'tombstone_compaction_interval': '86400'}, + 'gc_grace_seconds': '0'} + + .. autoattribute:: __compute_routing_key__ + + + The base methods allow creating, storing, and querying modeled objects. + + .. automethod:: create + + .. method:: if_not_exists() + + Check the existence of an object before insertion. The existence of an + object is determined by its primary key(s). And please note using this flag + would incur performance cost. + + If the insertion isn't applied, a :class:`~cassandra.cqlengine.query.LWTException` is raised. + + .. code-block:: python + + try: + TestIfNotExistsModel.if_not_exists().create(id=id, count=9, text='111111111111') + except LWTException as e: + # handle failure case + print e.existing # dict containing LWT result fields + + This method is supported on Cassandra 2.0 or later. + + .. method:: if_exists() + + Check the existence of an object before an update or delete. The existence of an + object is determined by its primary key(s). And please note using this flag + would incur performance cost. + + If the update or delete isn't applied, a :class:`~cassandra.cqlengine.query.LWTException` is raised. + + .. code-block:: python + + try: + TestIfExistsModel.objects(id=id).if_exists().update(count=9, text='111111111111') + except LWTException as e: + # handle failure case + pass + + This method is supported on Cassandra 2.0 or later. + + .. automethod:: save + + .. automethod:: update + + .. method:: iff(**values) + + Checks to ensure that the values specified are correct on the Cassandra cluster. + Simply specify the column(s) and the expected value(s). As with if_not_exists, + this incurs a performance cost. + + If the insertion isn't applied, a :class:`~cassandra.cqlengine.query.LWTException` is raised. + + .. code-block:: python + + t = TestTransactionModel(text='some text', count=5) + try: + t.iff(count=5).update('other text') + except LWTException as e: + # handle failure case + print e.existing # existing object + + .. automethod:: get + + .. automethod:: filter + + .. automethod:: all + + .. automethod:: delete + + .. method:: batch(batch_object) + + Sets the batch object to run instance updates and inserts queries with. + + See :doc:`/cqlengine/batches` for usage examples + + .. automethod:: timeout + + .. method:: timestamp(timedelta_or_datetime) + + Sets the timestamp for the query + + .. method:: ttl(ttl_in_sec) + + Sets the ttl values to run instance updates and inserts queries with. + + .. method:: using(connection=None) + + Change the context on the fly of the model instance (keyspace, connection) + + .. automethod:: column_family_name + + Models also support dict-like access: + + .. method:: len(m) + + Returns the number of columns defined in the model + + .. method:: m[col_name] + + Returns the value of column ``col_name`` + + .. method:: m[col_name] = value + + Set ``m[col_name]`` to value + + .. automethod:: keys + + .. automethod:: values + + .. automethod:: items diff --git a/3.24.8-scylla/_sources/api/cassandra/cqlengine/query.rst.txt b/3.24.8-scylla/_sources/api/cassandra/cqlengine/query.rst.txt new file mode 100644 index 0000000000..ce8f764b6b --- /dev/null +++ b/3.24.8-scylla/_sources/api/cassandra/cqlengine/query.rst.txt @@ -0,0 +1,71 @@ +``cassandra.cqlengine.query`` - Query and filter model objects +================================================================= + +.. module:: cassandra.cqlengine.query + +QuerySet +-------- +QuerySet objects are typically obtained by calling :meth:`~.cassandra.cqlengine.models.Model.objects` on a model class. +The methods here are used to filter, order, and constrain results. + +.. autoclass:: ModelQuerySet + + .. automethod:: all + + .. automethod:: batch + + .. automethod:: consistency + + .. automethod:: count + + .. method:: len(queryset) + + Returns the number of rows matched by this query. This function uses :meth:`~.cassandra.cqlengine.query.ModelQuerySet.count` internally. + + *Note: This function executes a SELECT COUNT() and has a performance cost on large datasets* + + .. automethod:: distinct + + .. automethod:: filter + + .. automethod:: get + + .. automethod:: limit + + .. automethod:: fetch_size + + .. automethod:: if_not_exists + + .. automethod:: if_exists + + .. automethod:: order_by + + .. automethod:: allow_filtering + + .. automethod:: only + + .. automethod:: defer + + .. automethod:: timestamp + + .. automethod:: ttl + + .. automethod:: using + + .. _blind_updates: + + .. automethod:: update + +.. autoclass:: BatchQuery + :members: + + .. automethod:: add_query + .. automethod:: execute + +.. autoclass:: ContextQuery + +.. autoclass:: DoesNotExist + +.. autoclass:: MultipleObjectsReturned + +.. autoclass:: LWTException diff --git a/3.24.8-scylla/_sources/api/cassandra/cqlengine/usertype.rst.txt b/3.24.8-scylla/_sources/api/cassandra/cqlengine/usertype.rst.txt new file mode 100644 index 0000000000..ebed187da9 --- /dev/null +++ b/3.24.8-scylla/_sources/api/cassandra/cqlengine/usertype.rst.txt @@ -0,0 +1,10 @@ +``cassandra.cqlengine.usertype`` - Model classes for User Defined Types +======================================================================= + +.. module:: cassandra.cqlengine.usertype + +UserType +-------- +.. autoclass:: UserType + + .. autoattribute:: __type_name__ diff --git a/3.24.8-scylla/_sources/api/cassandra/datastax/graph/fluent/index.rst.txt b/3.24.8-scylla/_sources/api/cassandra/datastax/graph/fluent/index.rst.txt new file mode 100644 index 0000000000..5547e0fdd7 --- /dev/null +++ b/3.24.8-scylla/_sources/api/cassandra/datastax/graph/fluent/index.rst.txt @@ -0,0 +1,24 @@ +:mod:`cassandra.datastax.graph.fluent` +====================================== + +.. module:: cassandra.datastax.graph.fluent + +.. autoclass:: DseGraph + + .. autoattribute:: DSE_GRAPH_QUERY_LANGUAGE + + .. automethod:: create_execution_profile + + .. automethod:: query_from_traversal + + .. automethod:: traversal_source(session=None, graph_name=None, execution_profile=EXEC_PROFILE_GRAPH_DEFAULT, traversal_class=None) + + .. automethod:: batch(session=None, execution_profile=None) + +.. autoclass:: DSESessionRemoteGraphConnection(session[, graph_name, execution_profile]) + +.. autoclass:: BaseGraphRowFactory + +.. autoclass:: graph_traversal_row_factory + +.. autoclass:: graph_traversal_dse_object_row_factory diff --git a/3.24.8-scylla/_sources/api/cassandra/datastax/graph/fluent/predicates.rst.txt b/3.24.8-scylla/_sources/api/cassandra/datastax/graph/fluent/predicates.rst.txt new file mode 100644 index 0000000000..f6e86f6451 --- /dev/null +++ b/3.24.8-scylla/_sources/api/cassandra/datastax/graph/fluent/predicates.rst.txt @@ -0,0 +1,14 @@ +:mod:`cassandra.datastax.graph.fluent.predicates` +================================================= + +.. module:: cassandra.datastax.graph.fluent.predicates + + +.. autoclass:: Search + :members: + +.. autoclass:: CqlCollection + :members: + +.. autoclass:: Geo + :members: diff --git a/3.24.8-scylla/_sources/api/cassandra/datastax/graph/fluent/query.rst.txt b/3.24.8-scylla/_sources/api/cassandra/datastax/graph/fluent/query.rst.txt new file mode 100644 index 0000000000..3dd859f96e --- /dev/null +++ b/3.24.8-scylla/_sources/api/cassandra/datastax/graph/fluent/query.rst.txt @@ -0,0 +1,8 @@ +:mod:`cassandra.datastax.graph.fluent.query` +============================================ + +.. module:: cassandra.datastax.graph.fluent.query + + +.. autoclass:: TraversalBatch + :members: diff --git a/3.24.8-scylla/_sources/api/cassandra/datastax/graph/index.rst.txt b/3.24.8-scylla/_sources/api/cassandra/datastax/graph/index.rst.txt new file mode 100644 index 0000000000..dafd5f65fd --- /dev/null +++ b/3.24.8-scylla/_sources/api/cassandra/datastax/graph/index.rst.txt @@ -0,0 +1,121 @@ +``cassandra.datastax.graph`` - Graph Statements, Options, and Row Factories +=========================================================================== + +.. _api-datastax-graph: + +.. module:: cassandra.datastax.graph + +.. autofunction:: single_object_row_factory + +.. autofunction:: graph_result_row_factory + +.. autofunction:: graph_object_row_factory + +.. autofunction:: graph_graphson2_row_factory + +.. autofunction:: graph_graphson3_row_factory + +.. function:: to_int(value) + + Wraps a value to be explicitly serialized as a graphson Int. + +.. function:: to_bigint(value) + + Wraps a value to be explicitly serialized as a graphson Bigint. + +.. function:: to_smallint(value) + + Wraps a value to be explicitly serialized as a graphson Smallint. + +.. function:: to_float(value) + + Wraps a value to be explicitly serialized as a graphson Float. + +.. function:: to_double(value) + + Wraps a value to be explicitly serialized as a graphson Double. + +.. autoclass:: GraphProtocol + :members: + +.. autoclass:: GraphOptions + + .. autoattribute:: graph_name + + .. autoattribute:: graph_source + + .. autoattribute:: graph_language + + .. autoattribute:: graph_read_consistency_level + + .. autoattribute:: graph_write_consistency_level + + .. autoattribute:: is_default_source + + .. autoattribute:: is_analytics_source + + .. autoattribute:: is_graph_source + + .. automethod:: set_source_default + + .. automethod:: set_source_analytics + + .. automethod:: set_source_graph + + +.. autoclass:: SimpleGraphStatement + :members: + +.. autoclass:: Result + :members: + +.. autoclass:: Vertex + :members: + +.. autoclass:: VertexProperty + :members: + +.. autoclass:: Edge + :members: + +.. autoclass:: Path + :members: + +.. autoclass:: T + :members: + +.. autoclass:: GraphSON1Serializer + :members: + +.. autoclass:: GraphSON1Deserializer + + .. automethod:: deserialize_date + + .. automethod:: deserialize_timestamp + + .. automethod:: deserialize_time + + .. automethod:: deserialize_duration + + .. automethod:: deserialize_int + + .. automethod:: deserialize_bigint + + .. automethod:: deserialize_double + + .. automethod:: deserialize_float + + .. automethod:: deserialize_uuid + + .. automethod:: deserialize_blob + + .. automethod:: deserialize_decimal + + .. automethod:: deserialize_point + + .. automethod:: deserialize_linestring + + .. automethod:: deserialize_polygon + +.. autoclass:: GraphSON2Reader + :members: diff --git a/3.24.8-scylla/_sources/api/cassandra/decoder.rst.txt b/3.24.8-scylla/_sources/api/cassandra/decoder.rst.txt new file mode 100644 index 0000000000..e213cc6d74 --- /dev/null +++ b/3.24.8-scylla/_sources/api/cassandra/decoder.rst.txt @@ -0,0 +1,20 @@ +``cassandra.decoder`` - Data Return Formats +=========================================== + +.. module:: cassandra.decoder + +.. function:: tuple_factory + + **Deprecated in 2.0.0.** Use :meth:`cassandra.query.tuple_factory` + +.. function:: named_tuple_factory + + **Deprecated in 2.0.0.** Use :meth:`cassandra.query.named_tuple_factory` + +.. function:: dict_factory + + **Deprecated in 2.0.0.** Use :meth:`cassandra.query.dict_factory` + +.. function:: ordered_dict_factory + + **Deprecated in 2.0.0.** Use :meth:`cassandra.query.ordered_dict_factory` diff --git a/3.24.8-scylla/_sources/api/cassandra/encoder.rst.txt b/3.24.8-scylla/_sources/api/cassandra/encoder.rst.txt new file mode 100644 index 0000000000..de3b180510 --- /dev/null +++ b/3.24.8-scylla/_sources/api/cassandra/encoder.rst.txt @@ -0,0 +1,36 @@ +``cassandra.encoder`` - Encoders for non-prepared Statements +============================================================ + +.. module:: cassandra.encoder + +.. autoclass:: Encoder () + + .. autoattribute:: cassandra.encoder.Encoder.mapping + + .. automethod:: cassandra.encoder.Encoder.cql_encode_none () + + .. automethod:: cassandra.encoder.Encoder.cql_encode_object () + + .. automethod:: cassandra.encoder.Encoder.cql_encode_all_types () + + .. automethod:: cassandra.encoder.Encoder.cql_encode_sequence () + + .. automethod:: cassandra.encoder.Encoder.cql_encode_str () + + .. automethod:: cassandra.encoder.Encoder.cql_encode_unicode () + + .. automethod:: cassandra.encoder.Encoder.cql_encode_bytes () + + Converts strings, buffers, and bytearrays into CQL blob literals. + + .. automethod:: cassandra.encoder.Encoder.cql_encode_datetime () + + .. automethod:: cassandra.encoder.Encoder.cql_encode_date () + + .. automethod:: cassandra.encoder.Encoder.cql_encode_map_collection () + + .. automethod:: cassandra.encoder.Encoder.cql_encode_list_collection () + + .. automethod:: cassandra.encoder.Encoder.cql_encode_set_collection () + + .. automethod:: cql_encode_tuple () diff --git a/3.24.8-scylla/_sources/api/cassandra/graph.rst.txt b/3.24.8-scylla/_sources/api/cassandra/graph.rst.txt new file mode 100644 index 0000000000..43ddd3086c --- /dev/null +++ b/3.24.8-scylla/_sources/api/cassandra/graph.rst.txt @@ -0,0 +1,121 @@ +``cassandra.graph`` - Graph Statements, Options, and Row Factories +================================================================== + +.. note:: This module is only for backward compatibility for dse-driver users. Consider using :ref:`cassandra.datastax.graph `. + +.. module:: cassandra.graph + +.. autofunction:: single_object_row_factory + +.. autofunction:: graph_result_row_factory + +.. autofunction:: graph_object_row_factory + +.. autofunction:: graph_graphson2_row_factory + +.. autofunction:: graph_graphson3_row_factory + +.. function:: to_int(value) + + Wraps a value to be explicitly serialized as a graphson Int. + +.. function:: to_bigint(value) + + Wraps a value to be explicitly serialized as a graphson Bigint. + +.. function:: to_smallint(value) + + Wraps a value to be explicitly serialized as a graphson Smallint. + +.. function:: to_float(value) + + Wraps a value to be explicitly serialized as a graphson Float. + +.. function:: to_double(value) + + Wraps a value to be explicitly serialized as a graphson Double. + +.. autoclass:: GraphProtocol + :members: + +.. autoclass:: GraphOptions + + .. autoattribute:: graph_name + + .. autoattribute:: graph_source + + .. autoattribute:: graph_language + + .. autoattribute:: graph_read_consistency_level + + .. autoattribute:: graph_write_consistency_level + + .. autoattribute:: is_default_source + + .. autoattribute:: is_analytics_source + + .. autoattribute:: is_graph_source + + .. automethod:: set_source_default + + .. automethod:: set_source_analytics + + .. automethod:: set_source_graph + + +.. autoclass:: SimpleGraphStatement + :members: + +.. autoclass:: Result + :members: + +.. autoclass:: Vertex + :members: + +.. autoclass:: VertexProperty + :members: + +.. autoclass:: Edge + :members: + +.. autoclass:: Path + :members: + +.. autoclass:: GraphSON1Serializer + :members: + +.. autoclass:: GraphSON1Deserializer + + .. automethod:: deserialize_date + + .. automethod:: deserialize_timestamp + + .. automethod:: deserialize_time + + .. automethod:: deserialize_duration + + .. automethod:: deserialize_int + + .. automethod:: deserialize_bigint + + .. automethod:: deserialize_double + + .. automethod:: deserialize_float + + .. automethod:: deserialize_uuid + + .. automethod:: deserialize_blob + + .. automethod:: deserialize_decimal + + .. automethod:: deserialize_point + + .. automethod:: deserialize_linestring + + .. automethod:: deserialize_polygon + +.. autoclass:: GraphSON2Reader + :members: + +.. autoclass:: GraphSON3Reader + :members: diff --git a/3.24.8-scylla/_sources/api/cassandra/io/asyncioreactor.rst.txt b/3.24.8-scylla/_sources/api/cassandra/io/asyncioreactor.rst.txt new file mode 100644 index 0000000000..38ae63ca7f --- /dev/null +++ b/3.24.8-scylla/_sources/api/cassandra/io/asyncioreactor.rst.txt @@ -0,0 +1,7 @@ +``cassandra.io.asyncioreactor`` - ``asyncio`` Event Loop +===================================================================== + +.. module:: cassandra.io.asyncioreactor + +.. autoclass:: AsyncioConnection + :members: diff --git a/3.24.8-scylla/_sources/api/cassandra/io/asyncorereactor.rst.txt b/3.24.8-scylla/_sources/api/cassandra/io/asyncorereactor.rst.txt new file mode 100644 index 0000000000..ade7887e70 --- /dev/null +++ b/3.24.8-scylla/_sources/api/cassandra/io/asyncorereactor.rst.txt @@ -0,0 +1,7 @@ +``cassandra.io.asyncorereactor`` - ``asyncore`` Event Loop +========================================================== + +.. module:: cassandra.io.asyncorereactor + +.. autoclass:: AsyncoreConnection + :members: diff --git a/3.24.8-scylla/_sources/api/cassandra/io/eventletreactor.rst.txt b/3.24.8-scylla/_sources/api/cassandra/io/eventletreactor.rst.txt new file mode 100644 index 0000000000..1ba742c7e9 --- /dev/null +++ b/3.24.8-scylla/_sources/api/cassandra/io/eventletreactor.rst.txt @@ -0,0 +1,7 @@ +``cassandra.io.eventletreactor`` - ``eventlet``-compatible Connection +===================================================================== + +.. module:: cassandra.io.eventletreactor + +.. autoclass:: EventletConnection + :members: diff --git a/3.24.8-scylla/_sources/api/cassandra/io/geventreactor.rst.txt b/3.24.8-scylla/_sources/api/cassandra/io/geventreactor.rst.txt new file mode 100644 index 0000000000..603affe140 --- /dev/null +++ b/3.24.8-scylla/_sources/api/cassandra/io/geventreactor.rst.txt @@ -0,0 +1,7 @@ +``cassandra.io.geventreactor`` - ``gevent``-compatible Event Loop +================================================================= + +.. module:: cassandra.io.geventreactor + +.. autoclass:: GeventConnection + :members: diff --git a/3.24.8-scylla/_sources/api/cassandra/io/libevreactor.rst.txt b/3.24.8-scylla/_sources/api/cassandra/io/libevreactor.rst.txt new file mode 100644 index 0000000000..5b7288edf2 --- /dev/null +++ b/3.24.8-scylla/_sources/api/cassandra/io/libevreactor.rst.txt @@ -0,0 +1,6 @@ +``cassandra.io.libevreactor`` - ``libev`` Event Loop +==================================================== + +.. module:: cassandra.io.libevreactor + +.. autoclass:: LibevConnection diff --git a/3.24.8-scylla/_sources/api/cassandra/io/twistedreactor.rst.txt b/3.24.8-scylla/_sources/api/cassandra/io/twistedreactor.rst.txt new file mode 100644 index 0000000000..24e93bd432 --- /dev/null +++ b/3.24.8-scylla/_sources/api/cassandra/io/twistedreactor.rst.txt @@ -0,0 +1,9 @@ +``cassandra.io.twistedreactor`` - Twisted Event Loop +==================================================== + +.. module:: cassandra.io.twistedreactor + +.. class:: TwistedConnection + + An implementation of :class:`~cassandra.io.connection.Connection` that uses + Twisted's reactor as its event loop. diff --git a/3.24.8-scylla/_sources/api/cassandra/metadata.rst.txt b/3.24.8-scylla/_sources/api/cassandra/metadata.rst.txt new file mode 100644 index 0000000000..7c1280bcf7 --- /dev/null +++ b/3.24.8-scylla/_sources/api/cassandra/metadata.rst.txt @@ -0,0 +1,93 @@ +``cassandra.metadata`` - Schema and Ring Topology +================================================= + +.. module:: cassandra.metadata + +.. autodata:: cql_keywords + :annotation: + +.. autodata:: cql_keywords_unreserved + :annotation: + +.. autodata:: cql_keywords_reserved + :annotation: + +.. autoclass:: Metadata () + :members: + :exclude-members: rebuild_schema, rebuild_token_map, add_host, remove_host + +Schemas +------- + +.. autoclass:: KeyspaceMetadata () + :members: + +.. autoclass:: UserType () + :members: + +.. autoclass:: Function () + :members: + +.. autoclass:: Aggregate () + :members: + +.. autoclass:: TableMetadata () + :members: + +.. autoclass:: TableMetadataV3 () + :members: + +.. autoclass:: TableMetadataDSE68 () + :members: + +.. autoclass:: ColumnMetadata () + :members: + +.. autoclass:: IndexMetadata () + :members: + +.. autoclass:: MaterializedViewMetadata () + :members: + +.. autoclass:: VertexMetadata () + :members: + +.. autoclass:: EdgeMetadata () + :members: + +Tokens and Ring Topology +------------------------ + +.. autoclass:: TokenMap () + :members: + +.. autoclass:: Token () + :members: + +.. autoclass:: Murmur3Token + :members: + +.. autoclass:: MD5Token + :members: + +.. autoclass:: BytesToken + :members: + +.. autoclass:: ReplicationStrategy + :members: + +.. autoclass:: ReplicationFactor + :members: + :exclude-members: create + +.. autoclass:: SimpleStrategy + :members: + +.. autoclass:: NetworkTopologyStrategy + :members: + +.. autoclass:: LocalStrategy + :members: + +.. autofunction:: group_keys_by_replica + diff --git a/3.24.8-scylla/_sources/api/cassandra/metrics.rst.txt b/3.24.8-scylla/_sources/api/cassandra/metrics.rst.txt new file mode 100644 index 0000000000..0df7f8b5b9 --- /dev/null +++ b/3.24.8-scylla/_sources/api/cassandra/metrics.rst.txt @@ -0,0 +1,7 @@ +``cassandra.metrics`` - Performance Metrics +=========================================== + +.. module:: cassandra.metrics + +.. autoclass:: cassandra.metrics.Metrics () + :members: diff --git a/3.24.8-scylla/_sources/api/cassandra/policies.rst.txt b/3.24.8-scylla/_sources/api/cassandra/policies.rst.txt new file mode 100644 index 0000000000..387b19ed95 --- /dev/null +++ b/3.24.8-scylla/_sources/api/cassandra/policies.rst.txt @@ -0,0 +1,96 @@ +``cassandra.policies`` - Load balancing and Failure Handling Policies +===================================================================== + +.. module:: cassandra.policies + +Load Balancing +-------------- + +.. autoclass:: HostDistance + :members: + +.. autoclass:: LoadBalancingPolicy + :members: + +.. autoclass:: RoundRobinPolicy + :members: + +.. autoclass:: DCAwareRoundRobinPolicy + :members: + +.. autoclass:: WhiteListRoundRobinPolicy + :members: + +.. autoclass:: TokenAwarePolicy + :members: + +.. autoclass:: HostFilterPolicy + + .. we document these methods manually so we can specify a param to predicate + + .. automethod:: predicate(host) + .. automethod:: distance + .. automethod:: make_query_plan + +.. autoclass:: DefaultLoadBalancingPolicy + :members: + +.. autoclass:: DSELoadBalancingPolicy + :members: + +Translating Server Node Addresses +--------------------------------- + +.. autoclass:: AddressTranslator + :members: + +.. autoclass:: IdentityTranslator + :members: + +.. autoclass:: EC2MultiRegionTranslator + :members: + +Marking Hosts Up or Down +------------------------ + +.. autoclass:: ConvictionPolicy + :members: + +.. autoclass:: SimpleConvictionPolicy + :members: + +Reconnecting to Dead Hosts +-------------------------- + +.. autoclass:: ReconnectionPolicy + :members: + +.. autoclass:: ConstantReconnectionPolicy + :members: + +.. autoclass:: ExponentialReconnectionPolicy + :members: + +Retrying Failed Operations +-------------------------- + +.. autoclass:: WriteType + :members: + +.. autoclass:: RetryPolicy + :members: + +.. autoclass:: FallthroughRetryPolicy + :members: + +.. autoclass:: DowngradingConsistencyRetryPolicy + :members: + +Retrying Idempotent Operations +------------------------------ + +.. autoclass:: SpeculativeExecutionPolicy + :members: + +.. autoclass:: ConstantSpeculativeExecutionPolicy + :members: diff --git a/3.24.8-scylla/_sources/api/cassandra/pool.rst.txt b/3.24.8-scylla/_sources/api/cassandra/pool.rst.txt new file mode 100644 index 0000000000..b14d30e19c --- /dev/null +++ b/3.24.8-scylla/_sources/api/cassandra/pool.rst.txt @@ -0,0 +1,11 @@ +``cassandra.pool`` - Hosts and Connection Pools +=============================================== + +.. automodule:: cassandra.pool + +.. autoclass:: Host () + :members: + :exclude-members: set_location_info, get_and_set_reconnection_handler + +.. autoexception:: NoConnectionsAvailable + :members: diff --git a/3.24.8-scylla/_sources/api/cassandra/protocol.rst.txt b/3.24.8-scylla/_sources/api/cassandra/protocol.rst.txt new file mode 100644 index 0000000000..f615ab1a70 --- /dev/null +++ b/3.24.8-scylla/_sources/api/cassandra/protocol.rst.txt @@ -0,0 +1,55 @@ +``cassandra.protocol`` - Protocol Features +===================================================================== + +.. module:: cassandra.protocol + +.. _custom_payload: + +Custom Payloads +--------------- +Native protocol version 4+ allows for a custom payload to be sent between clients +and custom query handlers. The payload is specified as a string:binary_type dict +holding custom key/value pairs. + +By default these are ignored by the server. They can be useful for servers implementing +a custom QueryHandler. + +See :meth:`.Session.execute`, ::meth:`.Session.execute_async`, :attr:`.ResponseFuture.custom_payload`. + +.. autoclass:: _ProtocolHandler + + .. autoattribute:: message_types_by_opcode + :annotation: = {default mapping} + + .. automethod:: encode_message + + .. automethod:: decode_message + +.. _faster_deser: + +Faster Deserialization +---------------------- +When python-driver is compiled with Cython, it uses a Cython-based deserialization path +to deserialize messages. By default, the driver will use a Cython-based parser that returns +lists of rows similar to the pure-Python version. In addition, there are two additional +ProtocolHandler classes that can be used to deserialize response messages: ``LazyProtocolHandler`` +and ``NumpyProtocolHandler``. They can be used as follows: + +.. code:: python + + from cassandra.protocol import NumpyProtocolHandler, LazyProtocolHandler + from cassandra.query import tuple_factory + s.client_protocol_handler = LazyProtocolHandler # for a result iterator + s.row_factory = tuple_factory #required for Numpy results + s.client_protocol_handler = NumpyProtocolHandler # for a dict of NumPy arrays as result + +These protocol handlers comprise different parsers, and return results as described below: + +- ProtocolHandler: this default implementation is a drop-in replacement for the pure-Python version. + The rows are all parsed upfront, before results are returned. + +- LazyProtocolHandler: near drop-in replacement for the above, except that it returns an iterator over rows, + lazily decoded into the default row format (this is more efficient since all decoded results are not materialized at once) + +- NumpyProtocolHander: deserializes results directly into NumPy arrays. This facilitates efficient integration with + analysis toolkits such as Pandas. diff --git a/3.24.8-scylla/_sources/api/cassandra/query.rst.txt b/3.24.8-scylla/_sources/api/cassandra/query.rst.txt new file mode 100644 index 0000000000..fcd79739b9 --- /dev/null +++ b/3.24.8-scylla/_sources/api/cassandra/query.rst.txt @@ -0,0 +1,59 @@ +``cassandra.query`` - Prepared Statements, Batch Statements, Tracing, and Row Factories +======================================================================================= + +.. module:: cassandra.query + +.. autofunction:: tuple_factory + +.. autofunction:: named_tuple_factory + +.. autofunction:: dict_factory + +.. autofunction:: ordered_dict_factory + +.. autoclass:: SimpleStatement + :members: + +.. autoclass:: PreparedStatement () + :members: + +.. autoclass:: BoundStatement + :members: + +.. autoclass:: Statement () + :members: + +.. autodata:: UNSET_VALUE + :annotation: + +.. autoclass:: BatchStatement (batch_type=BatchType.LOGGED, retry_policy=None, consistency_level=None) + :members: + +.. autoclass:: BatchType () + + .. autoattribute:: LOGGED + + .. autoattribute:: UNLOGGED + + .. autoattribute:: COUNTER + +.. autoclass:: cassandra.query.ValueSequence + + A wrapper class that is used to specify that a sequence of values should + be treated as a CQL list of values instead of a single column collection when used + as part of the `parameters` argument for :meth:`.Session.execute()`. + + This is typically needed when supplying a list of keys to select. + For example:: + + >>> my_user_ids = ('alice', 'bob', 'charles') + >>> query = "SELECT * FROM users WHERE user_id IN %s" + >>> session.execute(query, parameters=[ValueSequence(my_user_ids)]) + +.. autoclass:: QueryTrace () + :members: + +.. autoclass:: TraceEvent () + :members: + +.. autoexception:: TraceUnavailable diff --git a/3.24.8-scylla/_sources/api/cassandra/timestamps.rst.txt b/3.24.8-scylla/_sources/api/cassandra/timestamps.rst.txt new file mode 100644 index 0000000000..00d25b06d9 --- /dev/null +++ b/3.24.8-scylla/_sources/api/cassandra/timestamps.rst.txt @@ -0,0 +1,14 @@ +``cassandra.timestamps`` - Timestamp Generation +=============================================== + +.. module:: cassandra.timestamps + +.. autoclass:: MonotonicTimestampGenerator (warn_on_drift=True, warning_threshold=0, warning_interval=0) + + .. autoattribute:: warn_on_drift + + .. autoattribute:: warning_threshold + + .. autoattribute:: warning_interval + + .. automethod:: _next_timestamp diff --git a/3.24.8-scylla/_sources/api/cassandra/util.rst.txt b/3.24.8-scylla/_sources/api/cassandra/util.rst.txt new file mode 100644 index 0000000000..848d4d5fc2 --- /dev/null +++ b/3.24.8-scylla/_sources/api/cassandra/util.rst.txt @@ -0,0 +1,5 @@ +``cassandra.util`` - Utilities +=================================== + +.. automodule:: cassandra.util + :members: diff --git a/3.24.8-scylla/_sources/api/index.rst.txt b/3.24.8-scylla/_sources/api/index.rst.txt new file mode 100644 index 0000000000..9e778d508c --- /dev/null +++ b/3.24.8-scylla/_sources/api/index.rst.txt @@ -0,0 +1,54 @@ +API Documentation +================= + +Core Driver +----------- +.. toctree:: + :maxdepth: 2 + + cassandra + cassandra/cluster + cassandra/policies + cassandra/auth + cassandra/graph + cassandra/metadata + cassandra/metrics + cassandra/query + cassandra/pool + cassandra/protocol + cassandra/encoder + cassandra/decoder + cassandra/concurrent + cassandra/connection + cassandra/util + cassandra/timestamps + cassandra/io/asyncioreactor + cassandra/io/asyncorereactor + cassandra/io/eventletreactor + cassandra/io/libevreactor + cassandra/io/geventreactor + cassandra/io/twistedreactor + +.. _om_api: + +Object Mapper +------------- +.. toctree:: + :maxdepth: 1 + + cassandra/cqlengine/models + cassandra/cqlengine/columns + cassandra/cqlengine/query + cassandra/cqlengine/connection + cassandra/cqlengine/management + cassandra/cqlengine/usertype + +DataStax Graph +-------------- +.. toctree:: + :maxdepth: 1 + + cassandra/datastax/graph/index + cassandra/datastax/graph/fluent/index + cassandra/datastax/graph/fluent/query + cassandra/datastax/graph/fluent/predicates diff --git a/3.24.8-scylla/_sources/cqlengine/batches.rst.txt b/3.24.8-scylla/_sources/cqlengine/batches.rst.txt new file mode 100644 index 0000000000..306e7d01a6 --- /dev/null +++ b/3.24.8-scylla/_sources/cqlengine/batches.rst.txt @@ -0,0 +1,108 @@ +============= +Batch Queries +============= + +cqlengine supports batch queries using the BatchQuery class. Batch queries can be started and stopped manually, or within a context manager. To add queries to the batch object, you just need to precede the create/save/delete call with a call to batch, and pass in the batch object. + + +Batch Query General Use Pattern +=============================== + +You can only create, update, and delete rows with a batch query, attempting to read rows out of the database with a batch query will fail. + +.. code-block:: python + + from cassandra.cqlengine.query import BatchQuery + + #using a context manager + with BatchQuery() as b: + now = datetime.now() + em1 = ExampleModel.batch(b).create(example_type=0, description="1", created_at=now) + em2 = ExampleModel.batch(b).create(example_type=0, description="2", created_at=now) + em3 = ExampleModel.batch(b).create(example_type=0, description="3", created_at=now) + + # -- or -- + + #manually + b = BatchQuery() + now = datetime.now() + em1 = ExampleModel.batch(b).create(example_type=0, description="1", created_at=now) + em2 = ExampleModel.batch(b).create(example_type=0, description="2", created_at=now) + em3 = ExampleModel.batch(b).create(example_type=0, description="3", created_at=now) + b.execute() + + # updating in a batch + + b = BatchQuery() + em1.description = "new description" + em1.batch(b).save() + em2.description = "another new description" + em2.batch(b).save() + b.execute() + + # deleting in a batch + b = BatchQuery() + ExampleModel.objects(id=some_id).batch(b).delete() + ExampleModel.objects(id=some_id2).batch(b).delete() + b.execute() + + +Typically you will not want the block to execute if an exception occurs inside the `with` block. However, in the case that this is desirable, it's achievable by using the following syntax: + +.. code-block:: python + + with BatchQuery(execute_on_exception=True) as b: + LogEntry.batch(b).create(k=1, v=1) + mystery_function() # exception thrown in here + LogEntry.batch(b).create(k=1, v=2) # this code is never reached due to the exception, but anything leading up to here will execute in the batch. + +If an exception is thrown somewhere in the block, any statements that have been added to the batch will still be executed. This is useful for some logging situations. + +Batch Query Execution Callbacks +=============================== + +In order to allow secondary tasks to be chained to the end of batch, BatchQuery instances allow callbacks to be +registered with the batch, to be executed immediately after the batch executes. + +Multiple callbacks can be attached to same BatchQuery instance, they are executed in the same order that they +are added to the batch. + +The callbacks attached to a given batch instance are executed only if the batch executes. If the batch is used as a +context manager and an exception is raised, the queued up callbacks will not be run. + +.. code-block:: python + + def my_callback(*args, **kwargs): + pass + + batch = BatchQuery() + + batch.add_callback(my_callback) + batch.add_callback(my_callback, 'positional arg', named_arg='named arg value') + + # if you need reference to the batch within the callback, + # just trap it in the arguments to be passed to the callback: + batch.add_callback(my_callback, cqlengine_batch=batch) + + # once the batch executes... + batch.execute() + + # the effect of the above scheduled callbacks will be similar to + my_callback() + my_callback('positional arg', named_arg='named arg value') + my_callback(cqlengine_batch=batch) + +Failure in any of the callbacks does not affect the batch's execution, as the callbacks are started after the execution +of the batch is complete. + +Logged vs Unlogged Batches +--------------------------- +By default, queries in cqlengine are LOGGED, which carries additional overhead from UNLOGGED. To explicitly state which batch type to use, simply: + + +.. code-block:: python + + from cassandra.cqlengine.query import BatchType + with BatchQuery(batch_type=BatchType.Unlogged) as b: + LogEntry.batch(b).create(k=1, v=1) + LogEntry.batch(b).create(k=1, v=2) diff --git a/3.24.8-scylla/_sources/cqlengine/connections.rst.txt b/3.24.8-scylla/_sources/cqlengine/connections.rst.txt new file mode 100644 index 0000000000..03ade27521 --- /dev/null +++ b/3.24.8-scylla/_sources/cqlengine/connections.rst.txt @@ -0,0 +1,137 @@ +=========== +Connections +=========== + +Connections aim to ease the use of multiple sessions with cqlengine. Connections can be set on a model class, per query or using a context manager. + + +Register a new connection +========================= + +To use cqlengine, you need at least a default connection. If you initialize cqlengine's connections with with :func:`connection.setup <.connection.setup>`, a connection will be created automatically. If you want to use another cluster/session, you need to register a new cqlengine connection. You register a connection with :func:`~.connection.register_connection`: + +.. code-block:: python + + from cassandra.cqlengine import connection + + connection.setup(['127.0.0.1') + connection.register_connection('cluster2', ['127.0.0.2']) + +:func:`~.connection.register_connection` can take a list of hosts, as shown above, in which case it will create a connection with a new session. It can also take a `session` argument if you've already created a session: + +.. code-block:: python + + from cassandra.cqlengine import connection + from cassandra.cluster import Cluster + + session = Cluster(['127.0.0.1']).connect() + connection.register_connection('cluster3', session=session) + + +Change the default connection +============================= + +You can change the default cqlengine connection on registration: + +.. code-block:: python + + from cassandra.cqlengine import connection + + connection.register_connection('cluster2', ['127.0.0.2'] default=True) + +or on the fly using :func:`~.connection.set_default_connection` + +.. code-block:: python + + connection.set_default_connection('cluster2') + +Unregister a connection +======================= + +You can unregister a connection using :func:`~.connection.unregister_connection`: + +.. code-block:: python + + connection.unregister_connection('cluster2') + +Management +========== + +When using multiples connections, you also need to sync your models on all connections (and keyspaces) that you need operate on. Management commands have been improved to ease this part. Here is an example: + +.. code-block:: python + + from cassandra.cqlengine import management + + keyspaces = ['ks1', 'ks2'] + conns = ['cluster1', 'cluster2'] + + # registers your connections + # ... + + # create all keyspaces on all connections + for ks in keyspaces: + management.create_simple_keyspace(ks, connections=conns) + + # define your Automobile model + # ... + + # sync your models + management.sync_table(Automobile, keyspaces=keyspaces, connections=conns) + + +Connection Selection +==================== + +cqlengine will select the default connection, unless your specify a connection using one of the following methods. + +Default Model Connection +------------------------ + +You can specify a default connection per model: + +.. code-block:: python + + class Automobile(Model): + __keyspace__ = 'test' + __connection__ = 'cluster2' + manufacturer = columns.Text(primary_key=True) + year = columns.Integer(primary_key=True) + model = columns.Text(primary_key=True) + + print len(Automobile.objects.all()) # executed on the connection 'cluster2' + +QuerySet and model instance +--------------------------- + +You can use the :attr:`using() <.query.ModelQuerySet.using>` method to select a connection (or keyspace): + +.. code-block:: python + + Automobile.objects.using(connection='cluster1').create(manufacturer='honda', year=2010, model='civic') + q = Automobile.objects.filter(manufacturer='Tesla') + autos = q.using(keyspace='ks2', connection='cluster2').all() + + for auto in autos: + auto.using(connection='cluster1').save() + +Context Manager +--------------- + +You can use the ContextQuery as well to select a connection: + +.. code-block:: python + + with ContextQuery(Automobile, connection='cluster1') as A: + A.objects.filter(manufacturer='honda').all() # executed on 'cluster1' + + +BatchQuery +---------- + +With a BatchQuery, you can select the connection with the context manager. Note that all operations in the batch need to use the same connection. + +.. code-block:: python + + with BatchQuery(connection='cluster1') as b: + Automobile.objects.batch(b).create(manufacturer='honda', year=2010, model='civic') diff --git a/3.24.8-scylla/_sources/cqlengine/faq.rst.txt b/3.24.8-scylla/_sources/cqlengine/faq.rst.txt new file mode 100644 index 0000000000..6c056d02ea --- /dev/null +++ b/3.24.8-scylla/_sources/cqlengine/faq.rst.txt @@ -0,0 +1,67 @@ +========================== +Frequently Asked Questions +========================== + +Why don't updates work correctly on models instantiated as Model(field=value, field2=value2)? +------------------------------------------------------------------------------------------------ + +The recommended way to create new rows is with the models .create method. The values passed into a model's init method are interpreted by the model as the values as they were read from a row. This allows the model to "know" which rows have changed since the row was read out of cassandra, and create suitable update statements. + +How to preserve ordering in batch query? +------------------------------------------- + +Statement Ordering is not supported by CQL3 batches. Therefore, +once cassandra needs resolving conflict(Updating the same column in one batch), +The algorithm below would be used. + +* If timestamps are different, pick the column with the largest timestamp (the value being a regular column or a tombstone) +* If timestamps are the same, and one of the columns in a tombstone ('null') - pick the tombstone +* If timestamps are the same, and none of the columns are tombstones, pick the column with the largest value + +Below is an example to show this scenario. + +.. code-block:: python + + class MyMode(Model): + id = columns.Integer(primary_key=True) + count = columns.Integer() + text = columns.Text() + + with BatchQuery() as b: + MyModel.batch(b).create(id=1, count=2, text='123') + MyModel.batch(b).create(id=1, count=3, text='111') + + assert MyModel.objects(id=1).first().count == 3 + assert MyModel.objects(id=1).first().text == '123' + +The largest value of count is 3, and the largest value of text would be '123'. + +The workaround is applying timestamp to each statement, then Cassandra would +resolve to the statement with the lastest timestamp. + +.. code-block:: python + + with BatchQuery() as b: + MyModel.timestamp(datetime.now()).batch(b).create(id=1, count=2, text='123') + MyModel.timestamp(datetime.now()).batch(b).create(id=1, count=3, text='111') + + assert MyModel.objects(id=1).first().count == 3 + assert MyModel.objects(id=1).first().text == '111' + +How can I delete individual values from a row? +------------------------------------------------- + +When inserting with CQLEngine, ``None`` is equivalent to CQL ``NULL`` or to +issuing a ``DELETE`` on that column. For example: + +.. code-block:: python + + class MyModel(Model): + id = columns.Integer(primary_key=True) + text = columns.Text() + + m = MyModel.create(id=1, text='We can delete this with None') + assert MyModel.objects(id=1).first().text is not None + + m.update(text=None) + assert MyModel.objects(id=1).first().text is None diff --git a/3.24.8-scylla/_sources/cqlengine/models.rst.txt b/3.24.8-scylla/_sources/cqlengine/models.rst.txt new file mode 100644 index 0000000000..c0ba390119 --- /dev/null +++ b/3.24.8-scylla/_sources/cqlengine/models.rst.txt @@ -0,0 +1,218 @@ +====== +Models +====== + +.. module:: cqlengine.models + +A model is a python class representing a CQL table. Models derive from :class:`Model`, and +define basic table properties and columns for a table. + +Columns in your models map to columns in your CQL table. You define CQL columns by defining column attributes on your model classes. +For a model to be valid it needs at least one primary key column and one non-primary key column. Just as in CQL, the order you define +your columns in is important, and is the same order they are defined in on a model's corresponding table. + +Some basic examples defining models are shown below. Consult the :doc:`Model API docs ` and :doc:`Column API docs ` for complete details. + +Example Definitions +=================== + +This example defines a ``Person`` table, with the columns ``first_name`` and ``last_name`` + +.. code-block:: python + + from cassandra.cqlengine import columns + from cassandra.cqlengine.models import Model + + class Person(Model): + id = columns.UUID(primary_key=True) + first_name = columns.Text() + last_name = columns.Text() + + +The Person model would create this CQL table: + +.. code-block:: sql + + CREATE TABLE cqlengine.person ( + id uuid, + first_name text, + last_name text, + PRIMARY KEY (id) + ); + +Here's an example of a comment table created with clustering keys, in descending order: + +.. code-block:: python + + from cassandra.cqlengine import columns + from cassandra.cqlengine.models import Model + + class Comment(Model): + photo_id = columns.UUID(primary_key=True) + comment_id = columns.TimeUUID(primary_key=True, clustering_order="DESC") + comment = columns.Text() + +The Comment model's ``create table`` would look like the following: + +.. code-block:: sql + + CREATE TABLE comment ( + photo_id uuid, + comment_id timeuuid, + comment text, + PRIMARY KEY (photo_id, comment_id) + ) WITH CLUSTERING ORDER BY (comment_id DESC); + +To sync the models to the database, you may do the following*: + +.. code-block:: python + + from cassandra.cqlengine.management import sync_table + sync_table(Person) + sync_table(Comment) + +\*Note: synchronizing models causes schema changes, and should be done with caution. +Please see the discussion in :doc:`/api/cassandra/cqlengine/management` for considerations. + +For examples on manipulating data and creating queries, see :doc:`queryset` + +Manipulating model instances as dictionaries +============================================ + +Model instances can be accessed like dictionaries. + +.. code-block:: python + + class Person(Model): + first_name = columns.Text() + last_name = columns.Text() + + kevin = Person.create(first_name="Kevin", last_name="Deldycke") + dict(kevin) # returns {'first_name': 'Kevin', 'last_name': 'Deldycke'} + kevin['first_name'] # returns 'Kevin' + kevin.keys() # returns ['first_name', 'last_name'] + kevin.values() # returns ['Kevin', 'Deldycke'] + kevin.items() # returns [('first_name', 'Kevin'), ('last_name', 'Deldycke')] + + kevin['first_name'] = 'KEVIN5000' # changes the models first name + +Extending Model Validation +========================== + +Each time you save a model instance in cqlengine, the data in the model is validated against the schema you've defined +for your model. Most of the validation is fairly straightforward, it basically checks that you're not trying to do +something like save text into an integer column, and it enforces the ``required`` flag set on column definitions. +It also performs any transformations needed to save the data properly. + +However, there are often additional constraints or transformations you want to impose on your data, beyond simply +making sure that Cassandra won't complain when you try to insert it. To define additional validation on a model, +extend the model's validation method: + +.. code-block:: python + + class Member(Model): + person_id = UUID(primary_key=True) + name = Text(required=True) + + def validate(self): + super(Member, self).validate() + if self.name == 'jon': + raise ValidationError('no jon\'s allowed') + +*Note*: while not required, the convention is to raise a ``ValidationError`` (``from cassandra.cqlengine import ValidationError``) +if validation fails. + +.. _model_inheritance: + +Model Inheritance +================= +It is possible to save and load different model classes using a single CQL table. +This is useful in situations where you have different object types that you want to store in a single cassandra row. + +For instance, suppose you want a table that stores rows of pets owned by an owner: + +.. code-block:: python + + class Pet(Model): + __table_name__ = 'pet' + owner_id = UUID(primary_key=True) + pet_id = UUID(primary_key=True) + pet_type = Text(discriminator_column=True) + name = Text() + + def eat(self, food): + pass + + def sleep(self, time): + pass + + class Cat(Pet): + __discriminator_value__ = 'cat' + cuteness = Float() + + def tear_up_couch(self): + pass + + class Dog(Pet): + __discriminator_value__ = 'dog' + fierceness = Float() + + def bark_all_night(self): + pass + +After calling ``sync_table`` on each of these tables, the columns defined in each model will be added to the +``pet`` table. Additionally, saving ``Cat`` and ``Dog`` models will save the meta data needed to identify each row +as either a cat or dog. + +To setup a model structure with inheritance, follow these steps + +1. Create a base model with a column set as the distriminator (``distriminator_column=True`` in the column definition) +2. Create subclass models, and define a unique ``__discriminator_value__`` value on each +3. Run ``sync_table`` on each of the sub tables + +**About the discriminator value** + +The discriminator value is what cqlengine uses under the covers to map logical cql rows to the appropriate model type. The +base model maintains a map of discriminator values to subclasses. When a specialized model is saved, its discriminator value is +automatically saved into the discriminator column. The discriminator column may be any column type except counter and container types. +Additionally, if you set ``index=True`` on your discriminator column, you can execute queries against specialized subclasses, and a +``WHERE`` clause will be automatically added to your query, returning only rows of that type. Note that you must +define a unique ``__discriminator_value__`` to each subclass, and that you can only assign a single discriminator column per model. + +.. _user_types: + +User Defined Types +================== +cqlengine models User Defined Types (UDTs) much like tables, with fields defined by column type attributes. However, UDT instances +are only created, presisted, and queried via table Models. A short example to introduce the pattern:: + + from cassandra.cqlengine.columns import * + from cassandra.cqlengine.models import Model + from cassandra.cqlengine.usertype import UserType + + class address(UserType): + street = Text() + zipcode = Integer() + + class users(Model): + __keyspace__ = 'account' + name = Text(primary_key=True) + addr = UserDefinedType(address) + + users.create(name="Joe", addr=address(street="Easy St.", zipcode=99999)) + user = users.objects(name="Joe")[0] + print user.name, user.addr + # Joe address(street=u'Easy St.', zipcode=99999) + +UDTs are modeled by inheriting :class:`~.usertype.UserType`, and setting column type attributes. Types are then used in defining +models by declaring a column of type :class:`~.columns.UserDefinedType`, with the ``UserType`` class as a parameter. + +``sync_table`` will implicitly +synchronize any types contained in the table. Alternatively :func:`~.management.sync_type` can be used to create/alter types +explicitly. + +Upon declaration, types are automatically registered with the driver, so query results return instances of your ``UserType`` +class*. + +***Note**: UDTs were not added to the native protocol until v3. When setting up the cqlengine connection, be sure to specify +``protocol_version=3``. If using an earlier version, UDT queries will still work, but the returned type will be a namedtuple. diff --git a/3.24.8-scylla/_sources/cqlengine/queryset.rst.txt b/3.24.8-scylla/_sources/cqlengine/queryset.rst.txt new file mode 100644 index 0000000000..375ea22316 --- /dev/null +++ b/3.24.8-scylla/_sources/cqlengine/queryset.rst.txt @@ -0,0 +1,419 @@ +============== +Making Queries +============== + +.. module:: cqlengine.queryset + +Retrieving objects +================== +Once you've populated Cassandra with data, you'll probably want to retrieve some of it. This is accomplished with QuerySet objects. This section will describe how to use QuerySet objects to retrieve the data you're looking for. + +Retrieving all objects +---------------------- +The simplest query you can make is to return all objects from a table. + +This is accomplished with the ``.all()`` method, which returns a QuerySet of all objects in a table + +Using the Person example model, we would get all Person objects like this: + +.. code-block:: python + + all_objects = Person.objects.all() + +.. _retrieving-objects-with-filters: + +Retrieving objects with filters +------------------------------- +Typically, you'll want to query only a subset of the records in your database. + +That can be accomplished with the QuerySet's ``.filter(\*\*)`` method. + +For example, given the model definition: + +.. code-block:: python + + class Automobile(Model): + manufacturer = columns.Text(primary_key=True) + year = columns.Integer(primary_key=True) + model = columns.Text() + price = columns.Decimal() + options = columns.Set(columns.Text) + +...and assuming the Automobile table contains a record of every car model manufactured in the last 20 years or so, we can retrieve only the cars made by a single manufacturer like this: + + +.. code-block:: python + + q = Automobile.objects.filter(manufacturer='Tesla') + +You can also use the more convenient syntax: + +.. code-block:: python + + q = Automobile.objects(Automobile.manufacturer == 'Tesla') + +We can then further filter our query with another call to **.filter** + +.. code-block:: python + + q = q.filter(year=2012) + +*Note: all queries involving any filtering MUST define either an '=' or an 'in' relation to either a primary key column, or an indexed column.* + +Accessing objects in a QuerySet +=============================== + +There are several methods for getting objects out of a queryset + +* iterating over the queryset + .. code-block:: python + + for car in Automobile.objects.all(): + #...do something to the car instance + pass + +* list index + .. code-block:: python + + q = Automobile.objects.all() + q[0] #returns the first result + q[1] #returns the second result + + .. note:: + + * CQL does not support specifying a start position in it's queries. Therefore, accessing elements using array indexing will load every result up to the index value requested + * Using negative indices requires a "SELECT COUNT()" to be executed. This has a performance cost on large datasets. + +* list slicing + .. code-block:: python + + q = Automobile.objects.all() + q[1:] #returns all results except the first + q[1:9] #returns a slice of the results + + .. note:: + + * CQL does not support specifying a start position in it's queries. Therefore, accessing elements using array slicing will load every result up to the index value requested + * Using negative indices requires a "SELECT COUNT()" to be executed. This has a performance cost on large datasets. + +* calling :attr:`get() ` on the queryset + .. code-block:: python + + q = Automobile.objects.filter(manufacturer='Tesla') + q = q.filter(year=2012) + car = q.get() + + this returns the object matching the queryset + +* calling :attr:`first() ` on the queryset + .. code-block:: python + + q = Automobile.objects.filter(manufacturer='Tesla') + q = q.filter(year=2012) + car = q.first() + + this returns the first value in the queryset + +.. _query-filtering-operators: + +Filtering Operators +=================== + +:attr:`Equal To ` + +The default filtering operator. + +.. code-block:: python + + q = Automobile.objects.filter(manufacturer='Tesla') + q = q.filter(year=2012) #year == 2012 + +In addition to simple equal to queries, cqlengine also supports querying with other operators by appending a ``__`` to the field name on the filtering call + +:attr:`in (__in) ` + +.. code-block:: python + + q = Automobile.objects.filter(manufacturer='Tesla') + q = q.filter(year__in=[2011, 2012]) + + +:attr:`> (__gt) ` + +.. code-block:: python + + q = Automobile.objects.filter(manufacturer='Tesla') + q = q.filter(year__gt=2010) # year > 2010 + + # or the nicer syntax + + q.filter(Automobile.year > 2010) + +:attr:`>= (__gte) ` + +.. code-block:: python + + q = Automobile.objects.filter(manufacturer='Tesla') + q = q.filter(year__gte=2010) # year >= 2010 + + # or the nicer syntax + + q.filter(Automobile.year >= 2010) + +:attr:`< (__lt) ` + +.. code-block:: python + + q = Automobile.objects.filter(manufacturer='Tesla') + q = q.filter(year__lt=2012) # year < 2012 + + # or... + + q.filter(Automobile.year < 2012) + +:attr:`<= (__lte) ` + +.. code-block:: python + + q = Automobile.objects.filter(manufacturer='Tesla') + q = q.filter(year__lte=2012) # year <= 2012 + + q.filter(Automobile.year <= 2012) + +:attr:`CONTAINS (__contains) ` + +The CONTAINS operator is available for all collection types (List, Set, Map). + +.. code-block:: python + + q = Automobile.objects.filter(manufacturer='Tesla') + q.filter(options__contains='backup camera').allow_filtering() + +Note that we need to use allow_filtering() since the *options* column has no secondary index. + +:attr:`LIKE (__like) ` + +The LIKE operator is available for text columns that have a SASI secondary index. + +.. code-block:: python + + q = Automobile.objects.filter(model__like='%Civic%').allow_filtering() + +:attr:`IS NOT NULL (IsNotNull(column_name)) ` + +The IS NOT NULL operator is not yet supported for C*. + +.. code-block:: python + + q = Automobile.objects.filter(IsNotNull('model')) + +Limitations: + +- Currently, cqlengine does not support SASI index creation. To use this feature, you need to create the SASI index using the core driver. +- Queries using LIKE must use allow_filtering() since the *model* column has no standard secondary index. Note that the server will use the SASI index properly when executing the query. + +TimeUUID Functions +================== + +In addition to querying using regular values, there are two functions you can pass in when querying TimeUUID columns to help make filtering by them easier. Note that these functions don't actually return a value, but instruct the cql interpreter to use the functions in it's query. + +.. class:: MinTimeUUID(datetime) + + returns the minimum time uuid value possible for the given datetime + +.. class:: MaxTimeUUID(datetime) + + returns the maximum time uuid value possible for the given datetime + +*Example* + +.. code-block:: python + + class DataStream(Model): + id = columns.UUID(partition_key=True) + time = columns.TimeUUID(primary_key=True) + data = columns.Bytes() + + min_time = datetime(1982, 1, 1) + max_time = datetime(1982, 3, 9) + + DataStream.filter(time__gt=functions.MinTimeUUID(min_time), time__lt=functions.MaxTimeUUID(max_time)) + +Token Function +============== + +Token functon may be used only on special, virtual column pk__token, representing token of partition key (it also works for composite partition keys). +Cassandra orders returned items by value of partition key token, so using cqlengine.Token we can easy paginate through all table rows. + +See http://cassandra.apache.org/doc/cql3/CQL-3.0.html#tokenFun + +*Example* + +.. code-block:: python + + class Items(Model): + id = columns.Text(primary_key=True) + data = columns.Bytes() + + query = Items.objects.all().limit(10) + + first_page = list(query); + last = first_page[-1] + next_page = list(query.filter(pk__token__gt=cqlengine.Token(last.pk))) + +QuerySets are immutable +======================= + +When calling any method that changes a queryset, the method does not actually change the queryset object it's called on, but returns a new queryset object with the attributes of the original queryset, plus the attributes added in the method call. + +*Example* + +.. code-block:: python + + #this produces 3 different querysets + #q does not change after it's initial definition + q = Automobiles.objects.filter(year=2012) + tesla2012 = q.filter(manufacturer='Tesla') + honda2012 = q.filter(manufacturer='Honda') + +Ordering QuerySets +================== + +Since Cassandra is essentially a distributed hash table on steroids, the order you get records back in will not be particularly predictable. + +However, you can set a column to order on with the ``.order_by(column_name)`` method. + +*Example* + +.. code-block:: python + + #sort ascending + q = Automobiles.objects.all().order_by('year') + #sort descending + q = Automobiles.objects.all().order_by('-year') + +*Note: Cassandra only supports ordering on a clustering key. In other words, to support ordering results, your model must have more than one primary key, and you must order on a primary key, excluding the first one.* + +*For instance, given our Automobile model, year is the only column we can order on.* + +Values Lists +============ + +There is a special QuerySet's method ``.values_list()`` - when called, QuerySet returns lists of values instead of model instances. It may significantly speedup things with lower memory footprint for large responses. +Each tuple contains the value from the respective field passed into the ``values_list()`` call — so the first item is the first field, etc. For example: + +.. code-block:: python + + items = list(range(20)) + random.shuffle(items) + for i in items: + TestModel.create(id=1, clustering_key=i) + + values = list(TestModel.objects.values_list('clustering_key', flat=True)) + # [19L, 18L, 17L, 16L, 15L, 14L, 13L, 12L, 11L, 10L, 9L, 8L, 7L, 6L, 5L, 4L, 3L, 2L, 1L, 0L] + +Per Query Timeouts +=================== + +By default all queries are executed with the timeout defined in `~cqlengine.connection.setup()` +The examples below show how to specify a per-query timeout. +A timeout is specified in seconds and can be an int, float or None. +None means no timeout. + + +.. code-block:: python + + class Row(Model): + id = columns.Integer(primary_key=True) + name = columns.Text() + + +Fetch all objects with a timeout of 5 seconds + +.. code-block:: python + + Row.objects().timeout(5).all() + +Create a single row with a 50ms timeout + +.. code-block:: python + + Row(id=1, name='Jon').timeout(0.05).create() + +Delete a single row with no timeout + +.. code-block:: python + + Row(id=1).timeout(None).delete() + +Update a single row with no timeout + +.. code-block:: python + + Row(id=1).timeout(None).update(name='Blake') + +Batch query timeouts + +.. code-block:: python + + with BatchQuery(timeout=10) as b: + Row(id=1, name='Jon').create() + + +NOTE: You cannot set both timeout and batch at the same time, batch will use the timeout defined in it's constructor. +Setting the timeout on the model is meaningless and will raise an AssertionError. + + +.. _ttl-change: + +Default TTL and Per Query TTL +============================= + +Model default TTL now relies on the *default_time_to_live* feature, introduced in Cassandra 2.0. It is not handled anymore in the CQLEngine Model (scylla-driver >=3.6). You can set the default TTL of a table like this: + +Example: + +.. code-block:: python + + class User(Model): + __options__ = {'default_time_to_live': 20} + + user_id = columns.UUID(primary_key=True) + ... + +You can set TTL per-query if needed. Here are a some examples: + +Example: + +.. code-block:: python + + class User(Model): + __options__ = {'default_time_to_live': 20} + + user_id = columns.UUID(primary_key=True) + ... + + user = User.objects.create(user_id=1) # Default TTL 20 will be set automatically on the server + + user.ttl(30).update(age=21) # Update the TTL to 30 + User.objects.ttl(10).create(user_id=1) # TTL 10 + User(user_id=1, age=21).ttl(10).save() # TTL 10 + + +Named Tables +=================== + +Named tables are a way of querying a table without creating an class. They're useful for querying system tables or exploring an unfamiliar database. + + +.. code-block:: python + + from cassandra.cqlengine.connection import setup + setup("127.0.0.1", "cqlengine_test") + + from cassandra.cqlengine.named import NamedTable + user = NamedTable("cqlengine_test", "user") + user.objects() + user.objects()[0] + + # {u'pk': 1, u't': datetime.datetime(2014, 6, 26, 17, 10, 31, 774000)} diff --git a/3.24.8-scylla/_sources/cqlengine/third_party.rst.txt b/3.24.8-scylla/_sources/cqlengine/third_party.rst.txt new file mode 100644 index 0000000000..20c26df304 --- /dev/null +++ b/3.24.8-scylla/_sources/cqlengine/third_party.rst.txt @@ -0,0 +1,64 @@ +======================== +Third party integrations +======================== + + +Celery +------ + +Here's how, in substance, CQLengine can be plugged to `Celery +`_: + +.. code-block:: python + + from celery import Celery + from celery.signals import worker_process_init, beat_init + from cassandra.cqlengine import connection + from cassandra.cqlengine.connection import ( + cluster as cql_cluster, session as cql_session) + + def cassandra_init(**kwargs): + """ Initialize a clean Cassandra connection. """ + if cql_cluster is not None: + cql_cluster.shutdown() + if cql_session is not None: + cql_session.shutdown() + connection.setup() + + # Initialize worker context for both standard and periodic tasks. + worker_process_init.connect(cassandra_init) + beat_init.connect(cassandra_init) + + app = Celery() + + +uWSGI +----- + +This is the code required for proper connection handling of CQLengine for a +`uWSGI `_-run application: + +.. code-block:: python + + from cassandra.cqlengine import connection + from cassandra.cqlengine.connection import ( + cluster as cql_cluster, session as cql_session) + + try: + from uwsgidecorators import postfork + except ImportError: + # We're not in a uWSGI context, no need to hook Cassandra session + # initialization to the postfork event. + pass + else: + @postfork + def cassandra_init(**kwargs): + """ Initialize a new Cassandra session in the context. + + Ensures that a new session is returned for every new request. + """ + if cql_cluster is not None: + cql_cluster.shutdown() + if cql_session is not None: + cql_session.shutdown() + connection.setup() diff --git a/3.24.8-scylla/_sources/cqlengine/upgrade_guide.rst.txt b/3.24.8-scylla/_sources/cqlengine/upgrade_guide.rst.txt new file mode 100644 index 0000000000..5a10ebb757 --- /dev/null +++ b/3.24.8-scylla/_sources/cqlengine/upgrade_guide.rst.txt @@ -0,0 +1,155 @@ +======================== +Upgrade Guide +======================== + +This is an overview of things that changed as the cqlengine project was merged into +scylla-driver. While efforts were taken to preserve the API and most functionality exactly, +conversion to this package will still require certain minimal updates (namely, imports). + +**THERE IS ONE FUNCTIONAL CHANGE**, described in the first section below. + +Functional Changes +================== +List Prepend Reversing +---------------------- +Legacy cqlengine included a workaround for a Cassandra bug in which prepended list segments were +reversed (`CASSANDRA-8733 `_). As of +this integration, this workaround is removed. The first released integrated version emits +a warning when prepend is used. Subsequent versions will have this warning removed. + +Date Column Type +---------------- +The Date column type in legacy cqlengine used a ``timestamp`` CQL type and truncated the time. +Going forward, the :class:`~.columns.Date` type represents a ``date`` for Cassandra 2.2+ +(`PYTHON-245 `_). +Users of the legacy functionality should convert models to use :class:`~.columns.DateTime` (which +uses ``timestamp`` internally), and use the build-in ``datetime.date`` for input values. + +Remove cqlengine +================ +To avoid confusion or mistakes using the legacy package in your application, it +is prudent to remove the cqlengine package when upgrading to the integrated version. + +The driver setup script will warn if the legacy package is detected during install, +but it will not prevent side-by-side installation. + +Organization +============ +Imports +------- +cqlengine is now integrated as a sub-package of the driver base package 'cassandra'. +Upgrading will require adjusting imports to cqlengine. For example:: + + from cassandra.cqlengine import columns + +is now:: + + from cassandra.cqlengine import columns + +Package-Level Aliases +--------------------- +Legacy cqlengine defined a number of aliases at the package level, which became redundant +when the package was integrated for a driver. These have been removed in favor of absolute +imports, and referring to cannonical definitions. For example, ``cqlengine.ONE`` was an alias +of ``cassandra.ConsistencyLevel.ONE``. In the integrated package, only the +:class:`cassandra.ConsistencyLevel` remains. + +Additionally, submodule aliases are removed from cqlengine in favor of absolute imports. + +These aliases are removed, and not deprecated because they should be straightforward to iron out +at module load time. + +Exceptions +---------- +The legacy cqlengine.exceptions module had a number of Exception classes that were variously +common to the package, or only used in specific modules. Common exceptions were relocated to +cqlengine, and specialized exceptions were placed in the module that raises them. Below is a +listing of updated locations: + +============================ ========== +Exception class New module +============================ ========== +CQLEngineException cassandra.cqlengine +ModelException cassandra.cqlengine.models +ValidationError cassandra.cqlengine +UndefinedKeyspaceException cassandra.cqlengine.connection +LWTException cassandra.cqlengine.query +IfNotExistsWithCounterColumn cassandra.cqlengine.query +============================ ========== + +UnicodeMixin Consolidation +-------------------------- +``class UnicodeMixin`` was defined in several cqlengine modules. This has been consolidated +to a single definition in the cqlengine package init file. This is not technically part of +the API, but noted here for completeness. + +API Deprecations +================ +This upgrade served as a good juncture to deprecate certain API features and invite users to upgrade +to new ones. The first released version does not change functionality -- only introduces deprecation +warnings. Future releases will remove these features in favor of the alternatives. + +Float/Double Overload +--------------------- +Previously there was no ``Double`` column type. Doubles were modeled by specifying ``Float(double_precision=True)``. +This inititializer parameter is now deprecated. Applications should use :class:`~.columns.Double` for CQL ``double``, and :class:`~.columns.Float` +for CQL ``float``. + +Schema Management +----------------- +``cassandra.cqlengine.management.create_keyspace`` is deprecated. Instead, use the new replication-strategy-specific +functions that accept explicit options for known strategies: + +- :func:`~.create_keyspace_simple` +- :func:`~.create_keyspace_network_topology` + +``cassandra.cqlengine.management.delete_keyspace`` is deprecated in favor of a new function, :func:`~.drop_keyspace`. The +intent is simply to make the function match the CQL verb it invokes. + +Model Inheritance +----------------- +The names for class attributes controlling model inheritance are changing. Changes are as follows: + +- Replace 'polymorphic_key' in the base class Column definition with :attr:`~.discriminator_column` +- Replace the '__polymorphic_key__' class attribute the derived classes with :attr:`~.__discriminator_value__` + +The functionality is unchanged -- the intent here is to make the names and language around these attributes more precise. +For now, the old names are just deprecated, and the mapper will emit warnings if they are used. The old names +will be removed in a future version. + +The example below shows a simple translation: + +Before:: + + class Pet(Model): + __table_name__ = 'pet' + owner_id = UUID(primary_key=True) + pet_id = UUID(primary_key=True) + pet_type = Text(polymorphic_key=True) + name = Text() + + class Cat(Pet): + __polymorphic_key__ = 'cat' + + class Dog(Pet): + __polymorphic_key__ = 'dog' + +After:: + + class Pet(models.Model): + __table_name__ = 'pet' + owner_id = UUID(primary_key=True) + pet_id = UUID(primary_key=True) + pet_type = Text(discriminator_column=True) + name = Text() + + class Cat(Pet): + __discriminator_value__ = 'cat' + + class Dog(Pet): + __discriminator_value__ = 'dog' + + +TimeUUID.from_datetime +---------------------- +This function is deprecated in favor of the core utility function :func:`~.uuid_from_time`. diff --git a/3.24.8-scylla/_sources/dates_and_times.rst.txt b/3.24.8-scylla/_sources/dates_and_times.rst.txt new file mode 100644 index 0000000000..7a89f77437 --- /dev/null +++ b/3.24.8-scylla/_sources/dates_and_times.rst.txt @@ -0,0 +1,87 @@ +Working with Dates and Times +============================ + +This document is meant to provide on overview of the assumptions and limitations of the driver time handling, the +reasoning behind it, and describe approaches to working with these types. + +timestamps (Cassandra DateType) +------------------------------- + +Timestamps in Cassandra are timezone-naive timestamps encoded as millseconds since UNIX epoch. Clients working with +timestamps in this database usually find it easiest to reason about them if they are always assumed to be UTC. To quote the +pytz documentation, "The preferred way of dealing with times is to always work in UTC, converting to localtime only when +generating output to be read by humans." The driver adheres to this tenant, and assumes UTC is always in the database. The +driver attempts to make this correct on the way in, and assumes no timezone on the way out. + +Write Path +~~~~~~~~~~ +When inserting timestamps, the driver handles serialization for the write path as follows: + +If the input is a ``datetime.datetime``, the serialization is normalized by starting with the ``utctimetuple()`` of the +value. + +- If the ``datetime`` object is timezone-aware, the timestamp is shifted, and represents the UTC timestamp equivalent. +- If the ``datetime`` object is timezone-naive, this results in no shift -- any ``datetime`` with no timezone information is assumed to be UTC + +Note the second point above applies even to "local" times created using ``now()``:: + + >>> d = datetime.now() + + >>> print(d.tzinfo) + None + + +These do not contain timezone information intrinsically, so they will be assumed to be UTC and not shifted. When generating +timestamps in the application, it is clearer to use ``datetime.utcnow()`` to be explicit about it. + +If the input for a timestamp is numeric, it is assumed to be a epoch-relative millisecond timestamp, as specified in the +CQL spec -- no scaling or conversion is done. + +Read Path +~~~~~~~~~ +The driver always assumes persisted timestamps are UTC and makes no attempt to localize them. Returned values are +timezone-naive ``datetime.datetime``. We follow this approach because the datetime API has deficiencies around daylight +saving time, and the defacto package for handling this is a third-party package (we try to minimize external dependencies +and not make decisions for the integrator). + +The decision for how to handle timezones is left to the application. For the most part it is straightforward to apply +localization to the ``datetime``\s returned by queries. One prevalent method is to use pytz for localization:: + + import pytz + user_tz = pytz.timezone('US/Central') + timestamp_naive = row.ts + timestamp_utc = pytz.utc.localize(timestamp_naive) + timestamp_presented = timestamp_utc.astimezone(user_tz) + +This is the most robust approach (likely refactored into a function). If it is deemed too cumbersome to apply for all call +sites in the application, it is possible to patch the driver with custom deserialization for this type. However, doing +this depends depends some on internal APIs and what extensions are present, so we will only mention the possibility, and +not spell it out here. + +date, time (Cassandra DateType) +------------------------------- +Date and time in Cassandra are idealized markers, much like ``datetime.date`` and ``datetime.time`` in the Python standard +library. Unlike these Python implementations, the Cassandra encoding supports much wider ranges. To accommodate these +ranges without overflow, this driver returns these data in custom types: :class:`.util.Date` and :class:`.util.Time`. + +Write Path +~~~~~~~~~~ +For simple (not prepared) statements, the input values for each of these can be either a string literal or an encoded +integer. See `Working with dates `_ +or `Working with time `_ for details +on the encoding or string formats. + +For prepared statements, the driver accepts anything that can be used to construct the :class:`.util.Date` or +:class:`.util.Time` classes. See the linked API docs for details. + +Read Path +~~~~~~~~~ +The driver always returns custom types for ``date`` and ``time``. + +The driver returns :class:`.util.Date` for ``date`` in order to accommodate the wider range of values without overflow. +For applications working within the supported range of [``datetime.MINYEAR``, ``datetime.MAXYEAR``], these are easily +converted to standard ``datetime.date`` insances using :meth:`.Date.date`. + +The driver returns :class:`.util.Time` for ``time`` in order to retain nanosecond precision stored in the database. +For applications not concerned with this level of precision, these are easily converted to standard ``datetime.time`` +insances using :meth:`.Time.time`. diff --git a/3.24.8-scylla/_sources/execution_profiles.rst.txt b/3.24.8-scylla/_sources/execution_profiles.rst.txt new file mode 100644 index 0000000000..7be1a85e3f --- /dev/null +++ b/3.24.8-scylla/_sources/execution_profiles.rst.txt @@ -0,0 +1,156 @@ +Execution Profiles +================== + +Execution profiles aim at making it easier to execute requests in different ways within +a single connected ``Session``. Execution profiles are being introduced to deal with the exploding number of +configuration options, especially as the database platform evolves more complex workloads. + +The legacy configuration remains intact, but legacy and Execution Profile APIs +cannot be used simultaneously on the same client ``Cluster``. Legacy configuration +will be removed in the next major release (4.0). + +An execution profile and its parameters should be unique across ``Cluster`` instances. +For example, an execution profile and its ``LoadBalancingPolicy`` should +not be applied to more than one ``Cluster`` instance. + +This document explains how Execution Profiles relate to existing settings, and shows how to use the new profiles for +request execution. + +Mapping Legacy Parameters to Profiles +------------------------------------- + +Execution profiles can inherit from :class:`.cluster.ExecutionProfile`, and currently provide the following options, +previously input from the noted attributes: + +- load_balancing_policy - :attr:`.Cluster.load_balancing_policy` +- request_timeout - :attr:`.Session.default_timeout`, optional :meth:`.Session.execute` parameter +- retry_policy - :attr:`.Cluster.default_retry_policy`, optional :attr:`.Statement.retry_policy` attribute +- consistency_level - :attr:`.Session.default_consistency_level`, optional :attr:`.Statement.consistency_level` attribute +- serial_consistency_level - :attr:`.Session.default_serial_consistency_level`, optional :attr:`.Statement.serial_consistency_level` attribute +- row_factory - :attr:`.Session.row_factory` attribute + +When using the new API, these parameters can be defined by instances of :class:`.cluster.ExecutionProfile`. + +Using Execution Profiles +------------------------ +Default +~~~~~~~ + +.. code:: python + + from cassandra.cluster import Cluster + cluster = Cluster() + session = cluster.connect() + local_query = 'SELECT rpc_address FROM system.local' + for _ in cluster.metadata.all_hosts(): + print session.execute(local_query)[0] + + +.. parsed-literal:: + + Row(rpc_address='127.0.0.2') + Row(rpc_address='127.0.0.1') + + +The default execution profile is built from Cluster parameters and default Session attributes. This profile matches existing default +parameters. + +Initializing cluster with profiles +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. code:: python + + from cassandra.cluster import ExecutionProfile + from cassandra.policies import WhiteListRoundRobinPolicy + + node1_profile = ExecutionProfile(load_balancing_policy=WhiteListRoundRobinPolicy(['127.0.0.1'])) + node2_profile = ExecutionProfile(load_balancing_policy=WhiteListRoundRobinPolicy(['127.0.0.2'])) + + profiles = {'node1': node1_profile, 'node2': node2_profile} + session = Cluster(execution_profiles=profiles).connect() + for _ in cluster.metadata.all_hosts(): + print session.execute(local_query, execution_profile='node1')[0] + + +.. parsed-literal:: + + Row(rpc_address='127.0.0.1') + Row(rpc_address='127.0.0.1') + + +.. code:: python + + for _ in cluster.metadata.all_hosts(): + print session.execute(local_query, execution_profile='node2')[0] + + +.. parsed-literal:: + + Row(rpc_address='127.0.0.2') + Row(rpc_address='127.0.0.2') + + +.. code:: python + + for _ in cluster.metadata.all_hosts(): + print session.execute(local_query)[0] + + +.. parsed-literal:: + + Row(rpc_address='127.0.0.2') + Row(rpc_address='127.0.0.1') + +Note that, even when custom profiles are injected, the default ``TokenAwarePolicy(DCAwareRoundRobinPolicy())`` is still +present. To override the default, specify a policy with the :data:`~.cluster.EXEC_PROFILE_DEFAULT` key. + +.. code:: python + + from cassandra.cluster import EXEC_PROFILE_DEFAULT + profile = ExecutionProfile(request_timeout=30) + cluster = Cluster(execution_profiles={EXEC_PROFILE_DEFAULT: profile}) + + +Adding named profiles +~~~~~~~~~~~~~~~~~~~~~ + +New profiles can be added constructing from scratch, or deriving from default: + +.. code:: python + + locked_execution = ExecutionProfile(load_balancing_policy=WhiteListRoundRobinPolicy(['127.0.0.1'])) + node1_profile = 'node1_whitelist' + cluster.add_execution_profile(node1_profile, locked_execution) + + for _ in cluster.metadata.all_hosts(): + print session.execute(local_query, execution_profile=node1_profile)[0] + + +.. parsed-literal:: + + Row(rpc_address='127.0.0.1') + Row(rpc_address='127.0.0.1') + +See :meth:`.Cluster.add_execution_profile` for details and optional parameters. + +Passing a profile instance without mapping +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +We also have the ability to pass profile instances to be used for execution, but not added to the mapping: + +.. code:: python + + from cassandra.query import tuple_factory + + tmp = session.execution_profile_clone_update('node1', request_timeout=100, row_factory=tuple_factory) + + print session.execute(local_query, execution_profile=tmp)[0] + print session.execute(local_query, execution_profile='node1')[0] + +.. parsed-literal:: + + ('127.0.0.1',) + Row(rpc_address='127.0.0.1') + +The new profile is a shallow copy, so the ``tmp`` profile shares a load balancing policy with one managed by the cluster. +If reference objects are to be updated in the clone, one would typically set those attributes to a new instance. diff --git a/3.24.8-scylla/_sources/faq.rst.txt b/3.24.8-scylla/_sources/faq.rst.txt new file mode 100644 index 0000000000..56cb648a24 --- /dev/null +++ b/3.24.8-scylla/_sources/faq.rst.txt @@ -0,0 +1,83 @@ +Frequently Asked Questions +========================== + +See also :doc:`cqlengine FAQ ` + +Why do connections or IO operations timeout in my WSGI application? +------------------------------------------------------------------- +Depending on your application process model, it may be forking after driver Session is created. Most IO reactors do not handle this, and problems will manifest as timeouts. + +To avoid this, make sure to create sessions per process, after the fork. Using uWSGI and Flask for example: + +.. code-block:: python + + from flask import Flask + from uwsgidecorators import postfork + from cassandra.cluster import Cluster + + session = None + prepared = None + + @postfork + def connect(): + global session, prepared + session = Cluster().connect() + prepared = session.prepare("SELECT release_version FROM system.local WHERE key=?") + + app = Flask(__name__) + + @app.route('/') + def server_version(): + row = session.execute(prepared, ('local',))[0] + return row.release_version + +uWSGI provides a ``postfork`` hook you can use to create sessions and prepared statements after the child process forks. + +How do I trace a request? +------------------------- +Request tracing can be turned on for any request by setting ``trace=True`` in :meth:`.Session.execute_async`. View the results by waiting on the future, then :meth:`.ResponseFuture.get_query_trace`. +Since tracing is done asynchronously to the request, this method polls until the trace is complete before querying data. + +.. code-block:: python + + >>> future = session.execute_async("SELECT * FROM system.local", trace=True) + >>> result = future.result() + >>> trace = future.get_query_trace() + >>> for e in trace.events: + >>> print e.source_elapsed, e.description + + 0:00:00.000077 Parsing select * from system.local + 0:00:00.000153 Preparing statement + 0:00:00.000309 Computing ranges to query + 0:00:00.000368 Submitting range requests on 1 ranges with a concurrency of 1 (279.77142 rows per range expected) + 0:00:00.000422 Submitted 1 concurrent range requests covering 1 ranges + 0:00:00.000480 Executing seq scan across 1 sstables for (min(-9223372036854775808), min(-9223372036854775808)) + 0:00:00.000669 Read 1 live and 0 tombstone cells + 0:00:00.000755 Scanned 1 rows and matched 1 + +``trace`` is a :class:`QueryTrace` object. + +How do I determine the replicas for a query? +---------------------------------------------- +With prepared statements, the replicas are obtained by ``routing_key``, based on current cluster token metadata: + +.. code-block:: python + + >>> prepared = session.prepare("SELECT * FROM example.t WHERE key=?") + >>> bound = prepared.bind((1,)) + >>> replicas = cluster.metadata.get_replicas(bound.keyspace, bound.routing_key) + >>> for h in replicas: + >>> print h.address + 127.0.0.1 + 127.0.0.2 + +``replicas`` is a list of :class:`Host` objects. + +How does the driver manage request retries? +------------------------------------------- +By default, retries are managed by the :attr:`.Cluster.default_retry_policy` set on the session Cluster. It can also +be specialized per statement by setting :attr:`.Statement.retry_policy`. + +Retries are presently attempted on the same coordinator, but this may change in the future. + +Please see :class:`.policies.RetryPolicy` for further details. diff --git a/3.24.8-scylla/_sources/getting_started.rst.txt b/3.24.8-scylla/_sources/getting_started.rst.txt new file mode 100644 index 0000000000..8cb86a5504 --- /dev/null +++ b/3.24.8-scylla/_sources/getting_started.rst.txt @@ -0,0 +1,473 @@ +Getting Started +=============== + +First, make sure you have the driver properly :doc:`installed `. + +Connecting to Cassandra +----------------------- +Before we can start executing any queries against a Cassandra cluster we need to setup +an instance of :class:`~.Cluster`. As the name suggests, you will typically have one +instance of :class:`~.Cluster` for each Cassandra cluster you want to interact +with. + +The simplest way to create a :class:`~.Cluster` is like this: +First, make sure you have the Cassandra driver properly :doc:`installed `. + +.. code-block:: python + + from cassandra.cluster import Cluster + + cluster = Cluster() + +This will attempt to connection to a Cassandra instance on your +local machine (127.0.0.1). You can also specify a list of IP +addresses for nodes in your cluster: + +.. code-block:: python + + from cassandra.cluster import Cluster + + cluster = Cluster(['192.168.0.1', '192.168.0.2']) + +The set of IP addresses we pass to the :class:`~.Cluster` is simply +an initial set of contact points. After the driver connects to one +of these nodes it will *automatically discover* the rest of the +nodes in the cluster and connect to them, so you don't need to list +every node in your cluster. + +If you need to use a non-standard port, use SSL, or customize the driver's +behavior in some other way, this is the place to do it: + +.. code-block:: python + + from cassandra.cluster import Cluster + cluster = Cluster(['192.168.0.1', '192.168.0.2'], port=..., ssl_context=...) + +Instantiating a :class:`~.Cluster` does not actually connect us to any nodes. +To establish connections and begin executing queries we need a +:class:`~.Session`, which is created by calling :meth:`.Cluster.connect()`: + +.. code-block:: python + + cluster = Cluster() + session = cluster.connect() + +The :meth:`~.Cluster.connect()` method takes an optional ``keyspace`` argument +which sets the default keyspace for all queries made through that :class:`~.Session`: + +.. code-block:: python + + cluster = Cluster() + session = cluster.connect('mykeyspace') + + +You can always change a Session's keyspace using :meth:`~.Session.set_keyspace` or +by executing a ``USE `` query: + +.. code-block:: python + + session.set_keyspace('users') + # or you can do this instead + session.execute('USE users') + +Profiles are passed in by ``execution_profiles`` dict. + +In this case we can construct the base ``ExecutionProfile`` passing all attributes: + +.. code-block:: python + + from cassandra.cluster import Cluster, ExecutionProfile, EXEC_PROFILE_DEFAULT + from cassandra.policies import WhiteListRoundRobinPolicy, DowngradingConsistencyRetryPolicy + from cassandra.query import tuple_factory + + profile = ExecutionProfile( + load_balancing_policy=WhiteListRoundRobinPolicy(['127.0.0.1']), + retry_policy=DowngradingConsistencyRetryPolicy(), + consistency_level=ConsistencyLevel.LOCAL_QUORUM, + serial_consistency_level=ConsistencyLevel.LOCAL_SERIAL, + request_timeout=15, + row_factory=tuple_factory + ) + cluster = Cluster(execution_profiles={EXEC_PROFILE_DEFAULT: profile}) + session = cluster.connect() + + print(session.execute("SELECT release_version FROM system.local").one()) + +Users are free to setup additional profiles to be used by name: + +.. code-block:: python + + profile_long = ExecutionProfile(request_timeout=30) + cluster = Cluster(execution_profiles={'long': profile_long}) + session = cluster.connect() + session.execute(statement, execution_profile='long') + +Also, parameters passed to ``Session.execute`` or attached to ``Statement``\s are still honored as before. + +Executing Queries +----------------- +Now that we have a :class:`.Session` we can begin to execute queries. The simplest +way to execute a query is to use :meth:`~.Session.execute()`: + +.. code-block:: python + + rows = session.execute('SELECT name, age, email FROM users') + for user_row in rows: + print user_row.name, user_row.age, user_row.email + +This will transparently pick a Cassandra node to execute the query against +and handle any retries that are necessary if the operation fails. + +By default, each row in the result set will be a +`namedtuple `_. +Each row will have a matching attribute for each column defined in the schema, +such as ``name``, ``age``, and so on. You can also treat them as normal tuples +by unpacking them or accessing fields by position. The following three +examples are equivalent: + +.. code-block:: python + + rows = session.execute('SELECT name, age, email FROM users') + for row in rows: + print row.name, row.age, row.email + +.. code-block:: python + + rows = session.execute('SELECT name, age, email FROM users') + for (name, age, email) in rows: + print name, age, email + +.. code-block:: python + + rows = session.execute('SELECT name, age, email FROM users') + for row in rows: + print row[0], row[1], row[2] + +If you prefer another result format, such as a ``dict`` per row, you +can change the :attr:`~.Session.row_factory` attribute. + +As mentioned in our `Drivers Best Practices Guide `_, +it is highly recommended to use `Prepared statements <#prepared-statement>`_ for your +frequently run queries. + +.. _prepared-statement: + +Prepared Statements +------------------- +Prepared statements are queries that are parsed by Cassandra and then saved +for later use. When the driver uses a prepared statement, it only needs to +send the values of parameters to bind. This lowers network traffic +and CPU utilization within Cassandra because Cassandra does not have to +re-parse the query each time. + +To prepare a query, use :meth:`.Session.prepare()`: + +.. code-block:: python + + user_lookup_stmt = session.prepare("SELECT * FROM users WHERE user_id=?") + + users = [] + for user_id in user_ids_to_query: + user = session.execute(user_lookup_stmt, [user_id]) + users.append(user) + +:meth:`~.Session.prepare()` returns a :class:`~.PreparedStatement` instance +which can be used in place of :class:`~.SimpleStatement` instances or literal +string queries. It is automatically prepared against all nodes, and the driver +handles re-preparing against new nodes and restarted nodes when necessary. + +Note that the placeholders for prepared statements are ``?`` characters. This +is different than for simple, non-prepared statements (although future versions +of the driver may use the same placeholders for both). + +Passing Parameters to CQL Queries +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Althought it is not recommended, you can also pass parameters to non-prepared +statements. The driver supports two forms of parameter place-holders: positional +and named. + +Positional parameters are used with a ``%s`` placeholder. For example, +when you execute: + +.. code-block:: python + + session.execute( + """ + INSERT INTO users (name, credits, user_id) + VALUES (%s, %s, %s) + """, + ("John O'Reilly", 42, uuid.uuid1()) + ) + +It is translated to the following CQL query:: + + INSERT INTO users (name, credits, user_id) + VALUES ('John O''Reilly', 42, 2644bada-852c-11e3-89fb-e0b9a54a6d93) + +Note that you should use ``%s`` for all types of arguments, not just strings. +For example, this would be **wrong**: + +.. code-block:: python + + session.execute("INSERT INTO USERS (name, age) VALUES (%s, %d)", ("bob", 42)) # wrong + +Instead, use ``%s`` for the age placeholder. + +If you need to use a literal ``%`` character, use ``%%``. + +**Note**: you must always use a sequence for the second argument, even if you are +only passing in a single variable: + +.. code-block:: python + + session.execute("INSERT INTO foo (bar) VALUES (%s)", "blah") # wrong + session.execute("INSERT INTO foo (bar) VALUES (%s)", ("blah")) # wrong + session.execute("INSERT INTO foo (bar) VALUES (%s)", ("blah", )) # right + session.execute("INSERT INTO foo (bar) VALUES (%s)", ["blah"]) # right + + +Note that the second line is incorrect because in Python, single-element tuples +require a comma. + +Named place-holders use the ``%(name)s`` form: + +.. code-block:: python + + session.execute( + """ + INSERT INTO users (name, credits, user_id, username) + VALUES (%(name)s, %(credits)s, %(user_id)s, %(name)s) + """, + {'name': "John O'Reilly", 'credits': 42, 'user_id': uuid.uuid1()} + ) + +Note that you can repeat placeholders with the same name, such as ``%(name)s`` +in the above example. + +Only data values should be supplied this way. Other items, such as keyspaces, +table names, and column names should be set ahead of time (typically using +normal string formatting). + +.. _type-conversions: + +Type Conversions +^^^^^^^^^^^^^^^^ +For non-prepared statements, Python types are cast to CQL literals in the +following way: + +.. table:: + + +--------------------+-------------------------+ + | Python Type | CQL Literal Type | + +====================+=========================+ + | ``None`` | ``NULL`` | + +--------------------+-------------------------+ + | ``bool`` | ``boolean`` | + +--------------------+-------------------------+ + | ``float`` | | ``float`` | + | | | ``double`` | + +--------------------+-------------------------+ + | | ``int`` | | ``int`` | + | | ``long`` | | ``bigint`` | + | | | ``varint`` | + | | | ``smallint`` | + | | | ``tinyint`` | + | | | ``counter`` | + +--------------------+-------------------------+ + | ``decimal.Decimal``| ``decimal`` | + +--------------------+-------------------------+ + | | ``str`` | | ``ascii`` | + | | ``unicode`` | | ``varchar`` | + | | | ``text`` | + +--------------------+-------------------------+ + | | ``buffer`` | ``blob`` | + | | ``bytearray`` | | + +--------------------+-------------------------+ + | ``date`` | ``date`` | + +--------------------+-------------------------+ + | ``datetime`` | ``timestamp`` | + +--------------------+-------------------------+ + | ``time`` | ``time`` | + +--------------------+-------------------------+ + | | ``list`` | ``list`` | + | | ``tuple`` | | + | | generator | | + +--------------------+-------------------------+ + | | ``set`` | ``set`` | + | | ``frozenset`` | | + +--------------------+-------------------------+ + | | ``dict`` | ``map`` | + | | ``OrderedDict`` | | + +--------------------+-------------------------+ + | ``uuid.UUID`` | | ``timeuuid`` | + | | | ``uuid`` | + +--------------------+-------------------------+ + + +Asynchronous Queries +^^^^^^^^^^^^^^^^^^^^ +The driver supports asynchronous query execution through +:meth:`~.Session.execute_async()`. Instead of waiting for the query to +complete and returning rows directly, this method almost immediately +returns a :class:`~.ResponseFuture` object. There are two ways of +getting the final result from this object. + +The first is by calling :meth:`~.ResponseFuture.result()` on it. If +the query has not yet completed, this will block until it has and +then return the result or raise an Exception if an error occurred. +For example: + +.. code-block:: python + + from cassandra import ReadTimeout + + query = "SELECT * FROM users WHERE user_id=%s" + future = session.execute_async(query, [user_id]) + + # ... do some other work + + try: + rows = future.result() + user = rows[0] + print user.name, user.age + except ReadTimeout: + log.exception("Query timed out:") + +This works well for executing many queries concurrently: + +.. code-block:: python + + # build a list of futures + futures = [] + query = "SELECT * FROM users WHERE user_id=%s" + for user_id in ids_to_fetch: + futures.append(session.execute_async(query, [user_id]) + + # wait for them to complete and use the results + for future in futures: + rows = future.result() + print rows[0].name + +Alternatively, instead of calling :meth:`~.ResponseFuture.result()`, +you can attach callback and errback functions through the +:meth:`~.ResponseFuture.add_callback()`, +:meth:`~.ResponseFuture.add_errback()`, and +:meth:`~.ResponseFuture.add_callbacks()`, methods. If you have used +Twisted Python before, this is designed to be a lightweight version of +that: + +.. code-block:: python + + def handle_success(rows): + user = rows[0] + try: + process_user(user.name, user.age, user.id) + except Exception: + log.error("Failed to process user %s", user.id) + # don't re-raise errors in the callback + + def handle_error(exception): + log.error("Failed to fetch user info: %s", exception) + + + future = session.execute_async(query) + future.add_callbacks(handle_success, handle_error) + +There are a few important things to remember when working with callbacks: + * **Exceptions that are raised inside the callback functions will be logged and then ignored.** + * Your callback will be run on the event loop thread, so any long-running + operations will prevent other requests from being handled + + +Setting a Consistency Level +--------------------------- +The consistency level used for a query determines how many of the +replicas of the data you are interacting with need to respond for +the query to be considered a success. + +By default, :attr:`.ConsistencyLevel.LOCAL_ONE` will be used for all queries. +You can specify a different default by setting the :attr:`.ExecutionProfile.consistency_level` +for the execution profile with key :data:`~.cluster.EXEC_PROFILE_DEFAULT`. +To specify a different consistency level per request, wrap queries +in a :class:`~.SimpleStatement`: + +.. code-block:: python + + from cassandra import ConsistencyLevel + from cassandra.query import SimpleStatement + + query = SimpleStatement( + "INSERT INTO users (name, age) VALUES (%s, %s)", + consistency_level=ConsistencyLevel.QUORUM) + session.execute(query, ('John', 42)) + +Setting a Consistency Level with Prepared Statements +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +To specify a consistency level for prepared statements, you have two options. + +The first is to set a default consistency level for every execution of the +prepared statement: + +.. code-block:: python + + from cassandra import ConsistencyLevel + + cluster = Cluster() + session = cluster.connect("mykeyspace") + user_lookup_stmt = session.prepare("SELECT * FROM users WHERE user_id=?") + user_lookup_stmt.consistency_level = ConsistencyLevel.QUORUM + + # these will both use QUORUM + user1 = session.execute(user_lookup_stmt, [user_id1])[0] + user2 = session.execute(user_lookup_stmt, [user_id2])[0] + +The second option is to create a :class:`~.BoundStatement` from the +:class:`~.PreparedStatement` and binding parameters and set a consistency +level on that: + +.. code-block:: python + + # override the QUORUM default + user3_lookup = user_lookup_stmt.bind([user_id3]) + user3_lookup.consistency_level = ConsistencyLevel.ALL + user3 = session.execute(user3_lookup) + +Speculative Execution +^^^^^^^^^^^^^^^^^^^^^ + +Speculative execution is a way to minimize latency by preemptively executing several +instances of the same query against different nodes. For more details about this +technique, see `Speculative Execution with DataStax Drivers `_. + +To enable speculative execution: + +* Configure a :class:`~.policies.SpeculativeExecutionPolicy` with the ExecutionProfile +* Mark your query as idempotent, which mean it can be applied multiple + times without changing the result of the initial application. + See `Query Idempotence `_ for more details. + + +Example: + +.. code-block:: python + + from cassandra.cluster import Cluster, ExecutionProfile, EXEC_PROFILE_DEFAULT + from cassandra.policies import ConstantSpeculativeExecutionPolicy + from cassandra.query import SimpleStatement + + # Configure the speculative execution policy + ep = ExecutionProfile( + speculative_execution_policy=ConstantSpeculativeExecutionPolicy(delay=.5, max_attempts=10) + ) + cluster = Cluster(..., execution_profiles={EXEC_PROFILE_DEFAULT: ep}) + session = cluster.connect() + + # Mark the query idempotent + query = SimpleStatement( + "UPDATE my_table SET list_col = [1] WHERE pk = 1", + is_idempotent=True + ) + + # Execute. A new query will be sent to the server every 0.5 second + # until we receive a response, for a max number attempts of 10. + session.execute(query) diff --git a/3.24.8-scylla/_sources/index.rst.txt b/3.24.8-scylla/_sources/index.rst.txt new file mode 100644 index 0000000000..2fda976914 --- /dev/null +++ b/3.24.8-scylla/_sources/index.rst.txt @@ -0,0 +1,105 @@ +Python Driver for Scylla and Apache Cassandra® +============================================== +A Python client driver for `Scylla `_. +This driver works exclusively with the Cassandra Query Language v3 (CQL3) +and Cassandra's native protocol. + +The driver supports Python 2.7, 3.4, 3.5, 3.6, 3.7 and 3.8. + +This driver is open source under the +`Apache v2 License `_. +The source code for this driver can be found on `GitHub `_. + +Scylla Driver is a fork from `DataStax Python Driver `_, including some non-breaking changes for Scylla optimization, with more updates planned. + +Contents +-------- +:doc:`installation` + How to install the driver. + +:doc:`getting_started` + A guide through the first steps of connecting to Scylla and executing queries + +:doc:`scylla_specific` + A list of feature available only on ``scylla-driver`` + +:doc:`execution_profiles` + An introduction to a more flexible way of configuring request execution + +:doc:`lwt` + Working with results of conditional requests + +:doc:`object_mapper` + Introduction to the integrated object mapper, cqlengine + +:doc:`performance` + Tips for getting good performance. + +:doc:`query_paging` + Notes on paging large query results + +:doc:`security` + An overview of the security features of the driver + +:doc:`upgrading` + A guide to upgrading versions of the driver + +:doc:`user_defined_types` + Working with Scylla's user-defined types (UDT) + +:doc:`dates_and_times` + Some discussion on the driver's approach to working with timestamp, date, time types + +:doc:`scylla_cloud` + Connect to Scylla Cloud + +:doc:`CHANGELOG` + Log of changes to the driver, organized by version. + +:doc:`faq` + A collection of Frequently Asked Questions + +:doc:`api/index` + The API documentation. + +.. toctree:: + :hidden: + + api/index + installation + getting_started + scylla_specific + upgrading + execution_profiles + performance + query_paging + lwt + security + user_defined_types + object_mapper + dates_and_times + scylla_cloud + faq + +Getting Help +------------ +Visit the :doc:`FAQ section ` in this documentation. + +Please send questions to the Scylla `user list `_. + + +Reporting Issues +---------------- + +Please report any bugs and make any feature requests on the `Github project issues `_ + + +Copyright +--------- + +© 2013-2017 DataStax + +© 2016, The Apache Software Foundation. +Apache®, Apache Cassandra®, Cassandra®, the Apache feather logo and the Apache Cassandra® Eye logo are either registered trademarks or trademarks of the Apache Software Foundation in the United States and/or other countries. No endorsement by The Apache Software Foundation is implied by the use of these marks. + + diff --git a/3.24.8-scylla/_sources/installation.rst.txt b/3.24.8-scylla/_sources/installation.rst.txt new file mode 100644 index 0000000000..be6aacd9b3 --- /dev/null +++ b/3.24.8-scylla/_sources/installation.rst.txt @@ -0,0 +1,234 @@ +Installation +============ + +Supported Platforms +------------------- +Python 2.7, 3.4, 3.5, 3.6, 3.7 and 3.8 are supported. Both CPython (the standard Python +implementation) and `PyPy `_ are supported and tested. + +Linux, OSX, and Windows are supported. + +Installation through pip +------------------------ +`pip `_ is the suggested tool for installing +packages. It will handle installing all Python dependencies for the driver at +the same time as the driver itself. To install the driver*:: + + pip install scylla-driver + +You can use ``pip install --pre scylla-driver`` if you need to install a beta version. + +***Note**: if intending to use optional extensions, install the `dependencies <#optional-non-python-dependencies>`_ first. The driver may need to be reinstalled if dependencies are added after the initial installation. + +Verifying your Installation +--------------------------- +To check if the installation was successful, you can run:: + + python -c 'import cassandra; print cassandra.__version__' + +It should print something like "3.22.0". + +.. _installation-datastax-graph: + +(*Optional*) Graph +--------------------------- +The driver provides an optional fluent graph API that depends on Apache TinkerPop (gremlinpython). It is +not installed by default. To be able to build Gremlin traversals, you need to install +the `graph` requirements:: + + pip install scylla-driver[graph] + +(*Optional*) Compression Support +-------------------------------- +Compression can optionally be used for communication between the driver and +Cassandra. There are currently two supported compression algorithms: +snappy (in Cassandra 1.2+) and LZ4 (only in Cassandra 2.0+). If either is +available for the driver and Cassandra also supports it, it will +be used automatically. + +For lz4 support:: + + pip install lz4 + +For snappy support:: + + pip install python-snappy + +(If using a Debian Linux derivative such as Ubuntu, it may be easier to +just run ``apt-get install python-snappy``.) + +(*Optional*) Metrics Support +---------------------------- +The driver has built-in support for capturing :attr:`.Cluster.metrics` about +the queries you run. However, the ``scales`` library is required to +support this:: + + pip install scales + + +Speeding Up Installation +^^^^^^^^^^^^^^^^^^^^^^^^ + +By default, installing the driver through ``pip`` uses a pre-compiled, platform-specific wheel when available. +If using a source distribution rather than a wheel, Cython is used to compile certain parts of the driver. +This makes those hot paths faster at runtime, but the Cython compilation +process can take a long time -- as long as 10 minutes in some environments. + +In environments where performance is less important, it may be worth it to +:ref:`disable Cython as documented below `. +You can also use ``CASS_DRIVER_BUILD_CONCURRENCY`` to increase the number of +threads used to build the driver and any C extensions: + +.. code-block:: bash + + $ # installing from source + $ CASS_DRIVER_BUILD_CONCURRENCY=8 python setup.py install + $ # installing from pip + $ CASS_DRIVER_BUILD_CONCURRENCY=8 pip install scylla-driver + +OSX Installation Error +^^^^^^^^^^^^^^^^^^^^^^ +If you're installing on OSX and have XCode 5.1 installed, you may see an error like this:: + + clang: error: unknown argument: '-mno-fused-madd' [-Wunused-command-line-argument-hard-error-in-future] + +To fix this, re-run the installation with an extra compilation flag: + +.. code-block:: bash + + ARCHFLAGS=-Wno-error=unused-command-line-argument-hard-error-in-future pip install scylla-driver + +.. _windows_build: + +Windows Installation Notes +-------------------------- +Installing the driver with extensions in Windows sometimes presents some challenges. A few notes about common +hang-ups: + +Setup requires a compiler. When using Python 2, this is as simple as installing `this package `_ +(this link is also emitted during install if setuptools is unable to find the resources it needs). Depending on your +system settings, this package may install as a user-specific application. Make sure to install for everyone, or at least +as the user that will be building the Python environment. + +It is also possible to run the build with your compiler of choice. Just make sure to have your environment setup with +the proper paths. Make sure the compiler target architecture matches the bitness of your Python runtime. +Perhaps the easiest way to do this is to run the build/install from a Visual Studio Command Prompt (a +shortcut installed with Visual Studio that sources the appropriate environment and presents a shell). + +Manual Installation +------------------- +You can always install the driver directly from a source checkout or tarball. +When installing manually, ensure the python dependencies are already +installed. You can find the list of dependencies in +`requirements.txt `_. + +Once the dependencies are installed, simply run:: + + python setup.py install + + +(*Optional*) Non-python Dependencies +------------------------------------ +The driver has several **optional** features that have non-Python dependencies. + +C Extensions +^^^^^^^^^^^^ +By default, a number of extensions are compiled, providing faster hashing +for token-aware routing with the ``Murmur3Partitioner``, +`libev `_ event loop integration, +and Cython optimized extensions. + +When installing manually through setup.py, you can disable both with +the ``--no-extensions`` option, or selectively disable them with +with ``--no-murmur3``, ``--no-libev``, or ``--no-cython``. + +To compile the extensions, ensure that GCC and the Python headers are available. + +On Ubuntu and Debian, this can be accomplished by running:: + + $ sudo apt-get install gcc python-dev + +On RedHat and RedHat-based systems like CentOS and Fedora:: + + $ sudo yum install gcc python-devel + +On OS X, homebrew installations of Python should provide the necessary headers. + +See :ref:`windows_build` for notes on configuring the build environment on Windows. + +.. _cython-extensions: + +Cython-based Extensions +~~~~~~~~~~~~~~~~~~~~~~~ +By default, this package uses `Cython `_ to optimize core modules and build custom extensions. +This is not a hard requirement, but is engaged by default to build extensions offering better performance than the +pure Python implementation. + +This is a costly build phase, especially in clean environments where the Cython compiler must be built +This build phase can be avoided using the build switch, or an environment variable:: + + python setup.py install --no-cython + +Alternatively, an environment variable can be used to switch this option regardless of +context:: + + CASS_DRIVER_NO_CYTHON=1 + - or, to disable all extensions: + CASS_DRIVER_NO_EXTENSIONS=1 + +This method is required when using pip, which provides no other way of injecting user options in a single command:: + + CASS_DRIVER_NO_CYTHON=1 pip install scylla-driver + CASS_DRIVER_NO_CYTHON=1 sudo -E pip install ~/python-driver + +The environment variable is the preferred option because it spans all invocations of setup.py, and will +prevent Cython from being materialized as a setup requirement. + +If your sudo configuration does not allow SETENV, you must push the option flag down via pip. However, pip +applies these options to all dependencies (which break on the custom flag). Therefore, you must first install +dependencies, then use install-option:: + + sudo pip install six futures + sudo pip install --install-option="--no-cython" + + +libev support +^^^^^^^^^^^^^ +The driver currently uses Python's ``asyncore`` module for its default +event loop. For better performance, ``libev`` is also supported through +a C extension. + +If you're on Linux, you should be able to install libev +through a package manager. For example, on Debian/Ubuntu:: + + $ sudo apt-get install libev4 libev-dev + +On RHEL/CentOS/Fedora:: + + $ sudo yum install libev libev-devel + +If you're on Mac OS X, you should be able to install libev +through `Homebrew `_. For example, on Mac OS X:: + + $ brew install libev + +The libev extension is not built for Windows (the build process is complex, and the Windows implementation uses +select anyway). + +If successful, you should be able to build and install the extension +(just using ``setup.py build`` or ``setup.py install``) and then use +the libev event loop by doing the following: + +.. code-block:: python + + >>> from cassandra.io.libevreactor import LibevConnection + >>> from cassandra.cluster import Cluster + + >>> cluster = Cluster() + >>> cluster.connection_class = LibevConnection + >>> session = cluster.connect() + +(*Optional*) Configuring SSL +----------------------------- +Andrew Mussey has published a thorough guide on +`Using SSL with the DataStax Python driver `_. diff --git a/3.24.8-scylla/_sources/lwt.rst.txt b/3.24.8-scylla/_sources/lwt.rst.txt new file mode 100644 index 0000000000..2cc272f350 --- /dev/null +++ b/3.24.8-scylla/_sources/lwt.rst.txt @@ -0,0 +1,91 @@ +Lightweight Transactions (Compare-and-set) +========================================== + +Lightweight Transactions (LWTs) are mostly pass-through CQL for the driver. However, +the server returns some specialized results indicating the outcome and optional state +preceding the transaction. + +For pertinent execution parameters, see :attr:`.Statement.serial_consistency_level`. + +This section discusses working with specialized result sets returned by the server for LWTs, +and how to work with them using the driver. + + +Specialized Results +------------------- +The result returned from a LWT request is always a single row result. It will always have +prepended a special column named ``[applied]``. How this value appears in your results depends +on the row factory in use. See below for examples. + +The value of this ``[applied]`` column is boolean value indicating whether or not the transaction was applied. +If ``True``, it is the only column in the result. If ``False``, the additional columns depend on the LWT operation being +executed: + +- When using a ``UPDATE ... IF "col" = ...`` clause, the result will contain the ``[applied]`` column, plus the existing columns + and values for any columns in the ``IF`` clause (and thus the value that caused the transaction to fail). + +- When using ``INSERT ... IF NOT EXISTS``, the result will contain the ``[applied]`` column, plus all columns and values + of the existing row that rejected the transaction. + +- ``UPDATE .. IF EXISTS`` never has additional columns, regardless of ``[applied]`` status. + +How the ``[applied]`` column manifests depends on the row factory in use. Considering the following (initially empty) table:: + + CREATE TABLE test.t ( + k int PRIMARY KEY, + v int, + x int + ) + +... the following sections show the expected result for a number of example statements, using the three base row factories. + +named_tuple_factory (default) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +The name ``[applied]`` is not a valid Python identifier, so the square brackets are actually removed +from the attribute for the resulting ``namedtuple``. The row always has a boolean column ``applied`` in position 0:: + + >>> session.execute("INSERT INTO t (k,v) VALUES (0,0) IF NOT EXISTS") + Row(applied=True) + + >>> session.execute("INSERT INTO t (k,v) VALUES (0,0) IF NOT EXISTS") + Row(applied=False, k=0, v=0, x=None) + + >>> session.execute("UPDATE t SET v = 1, x = 2 WHERE k = 0 IF v =0") + Row(applied=True) + + >>> session.execute("UPDATE t SET v = 1, x = 2 WHERE k = 0 IF v =0 AND x = 1") + Row(applied=False, v=1, x=2) + +tuple_factory +~~~~~~~~~~~~~ +This return type does not refer to names, but the boolean value ``applied`` is always present in position 0:: + + >>> session.execute("INSERT INTO t (k,v) VALUES (0,0) IF NOT EXISTS") + (True,) + + >>> session.execute("INSERT INTO t (k,v) VALUES (0,0) IF NOT EXISTS") + (False, 0, 0, None) + + >>> session.execute("UPDATE t SET v = 1, x = 2 WHERE k = 0 IF v =0") + (True,) + + >>> session.execute("UPDATE t SET v = 1, x = 2 WHERE k = 0 IF v =0 AND x = 1") + (False, 1, 2) + +dict_factory +~~~~~~~~~~~~ +The retuned ``dict`` contains the ``[applied]`` key:: + + >>> session.execute("INSERT INTO t (k,v) VALUES (0,0) IF NOT EXISTS") + {u'[applied]': True} + + >>> session.execute("INSERT INTO t (k,v) VALUES (0,0) IF NOT EXISTS") + {u'x': 2, u'[applied]': False, u'v': 1} + + >>> session.execute("UPDATE t SET v = 1, x = 2 WHERE k = 0 IF v =0") + {u'x': None, u'[applied]': False, u'k': 0, u'v': 0} + + >>> session.execute("UPDATE t SET v = 1, x = 2 WHERE k = 0 IF v =0 AND x = 1") + {u'[applied]': True} + + diff --git a/3.24.8-scylla/_sources/object_mapper.rst.txt b/3.24.8-scylla/_sources/object_mapper.rst.txt new file mode 100644 index 0000000000..50d3cbf320 --- /dev/null +++ b/3.24.8-scylla/_sources/object_mapper.rst.txt @@ -0,0 +1,105 @@ +Object Mapper +============= + +cqlengine is the Cassandra CQL 3 Object Mapper packaged with this driver + +:ref:`Jump to Getting Started ` + +Contents +-------- +:doc:`cqlengine/upgrade_guide` + For migrating projects from legacy cqlengine, to the integrated product + +:doc:`cqlengine/models` + Examples defining models, and mapping them to tables + +:doc:`cqlengine/queryset` + Overview of query sets and filtering + +:doc:`cqlengine/batches` + Working with batch mutations + +:doc:`cqlengine/connections` + Working with multiple sessions + +:ref:`API Documentation ` + Index of API documentation + +:doc:`cqlengine/third_party` + High-level examples in Celery and uWSGI + +:doc:`cqlengine/faq` + +.. toctree:: + :hidden: + + cqlengine/upgrade_guide + cqlengine/models + cqlengine/queryset + cqlengine/batches + cqlengine/connections + cqlengine/third_party + cqlengine/faq + +.. _getting-started: + +Getting Started +--------------- + +.. code-block:: python + + import uuid + from cassandra.cqlengine import columns + from cassandra.cqlengine import connection + from datetime import datetime + from cassandra.cqlengine.management import sync_table + from cassandra.cqlengine.models import Model + + #first, define a model + class ExampleModel(Model): + example_id = columns.UUID(primary_key=True, default=uuid.uuid4) + example_type = columns.Integer(index=True) + created_at = columns.DateTime() + description = columns.Text(required=False) + + #next, setup the connection to your cassandra server(s)... + # see http://datastax.github.io/python-driver/api/cassandra/cluster.html for options + # the list of hosts will be passed to create a Cluster() instance + connection.setup(['127.0.0.1'], "cqlengine", protocol_version=3) + + #...and create your CQL table + >>> sync_table(ExampleModel) + + #now we can create some rows: + >>> em1 = ExampleModel.create(example_type=0, description="example1", created_at=datetime.now()) + >>> em2 = ExampleModel.create(example_type=0, description="example2", created_at=datetime.now()) + >>> em3 = ExampleModel.create(example_type=0, description="example3", created_at=datetime.now()) + >>> em4 = ExampleModel.create(example_type=0, description="example4", created_at=datetime.now()) + >>> em5 = ExampleModel.create(example_type=1, description="example5", created_at=datetime.now()) + >>> em6 = ExampleModel.create(example_type=1, description="example6", created_at=datetime.now()) + >>> em7 = ExampleModel.create(example_type=1, description="example7", created_at=datetime.now()) + >>> em8 = ExampleModel.create(example_type=1, description="example8", created_at=datetime.now()) + + #and now we can run some queries against our table + >>> ExampleModel.objects.count() + 8 + >>> q = ExampleModel.objects(example_type=1) + >>> q.count() + 4 + >>> for instance in q: + >>> print instance.description + example5 + example6 + example7 + example8 + + #here we are applying additional filtering to an existing query + #query objects are immutable, so calling filter returns a new + #query object + >>> q2 = q.filter(example_id=em5.example_id) + + >>> q2.count() + 1 + >>> for instance in q2: + >>> print instance.description + example5 diff --git a/3.24.8-scylla/_sources/performance.rst.txt b/3.24.8-scylla/_sources/performance.rst.txt new file mode 100644 index 0000000000..f7a3f49e0f --- /dev/null +++ b/3.24.8-scylla/_sources/performance.rst.txt @@ -0,0 +1,45 @@ +Performance Notes +================= +The Python driver for Cassandra offers several methods for executing queries. +You can synchronously block for queries to complete using +:meth:`.Session.execute()`, you can obtain asynchronous request futures through +:meth:`.Session.execute_async()`, and you can attach a callback to the future +with :meth:`.ResponseFuture.add_callback()`. + +Examples of multiple request patterns can be found in the benchmark scripts included in the driver project. + +The choice of execution pattern will depend on the application context. For applications dealing with multiple +requests in a given context, the recommended pattern is to use concurrent asynchronous +requests with callbacks. For many use cases, you don't need to implement this pattern yourself. +:meth:`cassandra.concurrent.execute_concurrent` and :meth:`cassandra.concurrent.execute_concurrent_with_args` +provide this pattern with a synchronous API and tunable concurrency. + +Due to the GIL and limited concurrency, the driver can become CPU-bound pretty quickly. The sections below +discuss further runtime and design considerations for mitigating this limitation. + +PyPy +---- +`PyPy `_ is an alternative Python runtime which uses a JIT compiler to +reduce CPU consumption. This leads to a huge improvement in the driver performance, +more than doubling throughput for many workloads. + +Cython Extensions +----------------- +`Cython `_ is an optimizing compiler and language that can be used to compile the core files and +optional extensions for the driver. Cython is not a strict dependency, but the extensions will be built by default. + +See :doc:`installation` for details on controlling this build. + +multiprocessing +--------------- +All of the patterns discussed above may be used over multiple processes using the +`multiprocessing `_ +module. Multiple processes will scale better than multiple threads, so if high throughput is your goal, +consider this option. + +Be sure to **never share any** :class:`~.Cluster`, :class:`~.Session`, +**or** :class:`~.ResponseFuture` **objects across multiple processes**. These +objects should all be created after forking the process, not before. + +For further discussion and simple examples using the driver with ``multiprocessing``, +see `this blog post `_. diff --git a/3.24.8-scylla/_sources/query_paging.rst.txt b/3.24.8-scylla/_sources/query_paging.rst.txt new file mode 100644 index 0000000000..23ee2c1129 --- /dev/null +++ b/3.24.8-scylla/_sources/query_paging.rst.txt @@ -0,0 +1,95 @@ +.. _query-paging: + +Paging Large Queries +==================== +Cassandra 2.0+ offers support for automatic query paging. Starting with +version 2.0 of the driver, if :attr:`~.Cluster.protocol_version` is greater than +:const:`2` (it is by default), queries returning large result sets will be +automatically paged. + +Controlling the Page Size +------------------------- +By default, :attr:`.Session.default_fetch_size` controls how many rows will +be fetched per page. This can be overridden per-query by setting +:attr:`~.fetch_size` on a :class:`~.Statement`. By default, each page +will contain at most 5000 rows. + +Handling Paged Results +---------------------- +Whenever the number of result rows for are query exceed the page size, an +instance of :class:`~.PagedResult` will be returned instead of a normal +list. This class implements the iterator interface, so you can treat +it like a normal iterator over rows:: + + from cassandra.query import SimpleStatement + query = "SELECT * FROM users" # users contains 100 rows + statement = SimpleStatement(query, fetch_size=10) + for user_row in session.execute(statement): + process_user(user_row) + +Whenever there are no more rows in the current page, the next page will +be fetched transparently. However, note that it *is* possible for +an :class:`Exception` to be raised while fetching the next page, just +like you might see on a normal call to ``session.execute()``. + +If you use :meth:`.Session.execute_async()` along with, +:meth:`.ResponseFuture.result()`, the first page will be fetched before +:meth:`~.ResponseFuture.result()` returns, but latter pages will be +transparently fetched synchronously while iterating the result. + +Handling Paged Results with Callbacks +------------------------------------- +If callbacks are attached to a query that returns a paged result, +the callback will be called once per page with a normal list of rows. + +Use :attr:`.ResponseFuture.has_more_pages` and +:meth:`.ResponseFuture.start_fetching_next_page()` to continue fetching +pages. For example:: + + class PagedResultHandler(object): + + def __init__(self, future): + self.error = None + self.finished_event = Event() + self.future = future + self.future.add_callbacks( + callback=self.handle_page, + errback=self.handle_err) + + def handle_page(self, rows): + for row in rows: + process_row(row) + + if self.future.has_more_pages: + self.future.start_fetching_next_page() + else: + self.finished_event.set() + + def handle_error(self, exc): + self.error = exc + self.finished_event.set() + + future = session.execute_async("SELECT * FROM users") + handler = PagedResultHandler(future) + handler.finished_event.wait() + if handler.error: + raise handler.error + +Resume Paged Results +-------------------- + +You can resume the pagination when executing a new query by using the :attr:`.ResultSet.paging_state`. This can be useful if you want to provide some stateless pagination capabilities to your application (ie. via http). For example:: + + from cassandra.query import SimpleStatement + query = "SELECT * FROM users" + statement = SimpleStatement(query, fetch_size=10) + results = session.execute(statement) + + # save the paging_state somewhere and return current results + web_session['paging_state'] = results.paging_state + + + # resume the pagination sometime later... + statement = SimpleStatement(query, fetch_size=10) + ps = web_session['paging_state'] + results = session.execute(statement, paging_state=ps) diff --git a/3.24.8-scylla/_sources/scylla_cloud.rst.txt b/3.24.8-scylla/_sources/scylla_cloud.rst.txt new file mode 100644 index 0000000000..62aaf76433 --- /dev/null +++ b/3.24.8-scylla/_sources/scylla_cloud.rst.txt @@ -0,0 +1,5 @@ +Scylla Cloud +------------ + +To connect to a `Scylla Cloud `_ cluster, go to the Cluster Connect page, Python example. +For best performance, make sure to use the Scylla Driver. diff --git a/3.24.8-scylla/_sources/scylla_specific.rst.txt b/3.24.8-scylla/_sources/scylla_specific.rst.txt new file mode 100644 index 0000000000..366628e59b --- /dev/null +++ b/3.24.8-scylla/_sources/scylla_specific.rst.txt @@ -0,0 +1,84 @@ +Scylla Specific Features +======================== + +Shard Awareness +--------------- + +**scylla-driver** is shard aware and contains extensions that work with the TokenAwarePolicy supported by Scylla 2.3 and onwards. Using this policy, the driver can select a connection to a particular shard based on the shard's token. +As a result, latency is significantly reduced because there is no need to pass data between the shards. + +Details on the scylla cql protocol extensions +https://github.com/scylladb/scylla/blob/master/docs/design-notes/protocol-extensions.md + +For using it you only need to enable ``TokenAwarePolicy`` on the ``Cluster`` + +.. code:: python + + from cassandra.cluster import Cluster + from cassandra.policies import TokenAwarePolicy, RoundRobinPolicy + + cluster = Cluster(load_balancing_policy=TokenAwarePolicy(RoundRobinPolicy())) + + +New Cluster Helpers +------------------- + +* ``cluster.is_shard_aware()`` + + New method available on ``Cluster`` allowing to check whether the remote cluster supports shard awareness (bool) + +.. code:: python + + from cassandra.cluster import Cluster + + cluster = Cluster() + session = cluster.connect() + + if cluster.is_shard_aware(): + print("connected to a scylla cluster") + +* ``cluster.shard_aware_stats()`` + + New method available on ``Cluster`` allowing to check the status of shard aware connections to all available hosts (dict) + +.. code:: python + + from cassandra.cluster import Cluster + + cluster = Cluster() + session = cluster.connect() + + stats = cluster.shard_aware_stats() + if all([v["shards_count"] == v["connected"] for v in stats.values()]): + print("successfully connected to all shards of all scylla nodes") + + +New Table Attributes +-------------------- + +* ``in_memory`` flag + + New flag available on ``TableMetadata.options`` to indicate that it is an `In Memory `_ table + +.. note:: in memory tables is a feature existing only in Scylla Enterprise + +.. code:: python + + from cassandra.cluster import Cluster + + cluster = Cluster() + session = cluster.connect() + session.execute(""" + CREATE KEYSPACE IF NOT EXISTS keyspace1 + WITH replication = {'class': 'SimpleStrategy', 'replication_factor': '1'}; + """) + + session.execute(""" + CREATE TABLE IF NOT EXISTS keyspace1.standard1 ( + key blob PRIMARY KEY, + "C0" blob + ) WITH in_memory=true AND compaction={'class': 'InMemoryCompactionStrategy'} + """) + + cluster.refresh_table_metadata("keyspace1", "standard1") + assert cluster.metadata.keyspaces["keyspace1"].tables["standard1"].options["in_memory"] == True diff --git a/3.24.8-scylla/_sources/security.rst.txt b/3.24.8-scylla/_sources/security.rst.txt new file mode 100644 index 0000000000..0276f6fc51 --- /dev/null +++ b/3.24.8-scylla/_sources/security.rst.txt @@ -0,0 +1,421 @@ +.. _security: + +Security +======== +The two main security components you will use with the +Python driver are Authentication and SSL. + +Authentication +-------------- +Versions 2.0 and higher of the driver support a SASL-based +authentication mechanism when :attr:`~.Cluster.protocol_version` +is set to 2 or higher. To use this authentication, set +:attr:`~.Cluster.auth_provider` to an instance of a subclass +of :class:`~cassandra.auth.AuthProvider`. When working +with Cassandra's ``PasswordAuthenticator``, you can use +the :class:`~cassandra.auth.PlainTextAuthProvider` class. + +For example, suppose Cassandra is setup with its default +'cassandra' user with a password of 'cassandra': + +.. code-block:: python + + from cassandra.cluster import Cluster + from cassandra.auth import PlainTextAuthProvider + + auth_provider = PlainTextAuthProvider(username='cassandra', password='cassandra') + cluster = Cluster(auth_provider=auth_provider, protocol_version=2) + + + +Custom Authenticators +^^^^^^^^^^^^^^^^^^^^^ +If you're using something other than Cassandra's ``PasswordAuthenticator``, +:class:`~.SaslAuthProvider` is provided for generic SASL authentication mechanisms, +utilizing the ``pure-sasl`` package. +If these do not suit your needs, you may need to create your own subclasses of +:class:`~.AuthProvider` and :class:`~.Authenticator`. You can use the Sasl classes +as example implementations. + +Protocol v1 Authentication +^^^^^^^^^^^^^^^^^^^^^^^^^^ +When working with Cassandra 1.2 (or a higher version with +:attr:`~.Cluster.protocol_version` set to ``1``), you will not pass in +an :class:`~.AuthProvider` instance. Instead, you should pass in a +function that takes one argument, the IP address of a host, and returns +a dict of credentials with a ``username`` and ``password`` key: + +.. code-block:: python + + from cassandra.cluster import Cluster + + def get_credentials(host_address): + return {'username': 'joe', 'password': '1234'} + + cluster = Cluster(auth_provider=get_credentials, protocol_version=1) + +SSL +--- +SSL should be used when client encryption is enabled in Cassandra. + +To give you as much control as possible over your SSL configuration, our SSL +API takes a user-created `SSLContext` instance from the Python standard library. +These docs will include some examples for how to achieve common configurations, +but the `ssl.SSLContext `_ documentation +gives a more complete description of what is possible. + +To enable SSL with version 3.17.0 and higher, you will need to set :attr:`.Cluster.ssl_context` to a +``ssl.SSLContext`` instance to enable SSL. Optionally, you can also set :attr:`.Cluster.ssl_options` +to a dict of options. These will be passed as kwargs to ``ssl.SSLContext.wrap_socket()`` +when new sockets are created. + +If you create your SSLContext using `ssl.create_default_context `_, +be aware that SSLContext.check_hostname is set to True by default, so the hostname validation will be done +by Python and not the driver. For this reason, we need to set the server_hostname at best effort, which is the +resolved ip address. If this validation needs to be done against the FQDN, consider enabling it using the ssl_options +as described in the following examples or implement your own :class:`~.connection.EndPoint` and +:class:`~.connection.EndPointFactory`. + + +The following examples assume you have generated your Cassandra certificate and +keystore files with these intructions: + +* `Setup SSL Cert `_ + +It might be also useful to learn about the different levels of identity verification to understand the examples: + +* `Using SSL in DSE drivers `_ + +SSL with Twisted or Eventlet +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Twisted and Eventlet both use an alternative SSL implementation called pyOpenSSL, so if your `Cluster`'s connection class is +:class:`~cassandra.io.twistedreactor.TwistedConnection` or :class:`~cassandra.io.eventletreactor.EventletConnection`, you must pass a +`pyOpenSSL context `_ instead. +An example is provided in these docs, and more details can be found in the +`documentation `_. +pyOpenSSL is not installed by the driver and must be installed separately. + +SSL Configuration Examples +^^^^^^^^^^^^^^^^^^^^^^^^^^ +Here, we'll describe the server and driver configuration necessary to set up SSL to meet various goals, such as the client verifying the server and the server verifying the client. We'll also include Python code demonstrating how to use servers and drivers configured in these ways. + +.. _ssl-no-identify-verification: + +No identity verification +++++++++++++++++++++++++ + +No identity verification at all. Note that this is not recommended for for production deployments. + +The Cassandra configuration:: + + client_encryption_options: + enabled: true + keystore: /path/to/127.0.0.1.keystore + keystore_password: myStorePass + require_client_auth: false + +The driver configuration: + +.. code-block:: python + + from cassandra.cluster import Cluster, Session + from ssl import SSLContext, PROTOCOL_TLSv1 + + ssl_context = SSLContext(PROTOCOL_TLSv1) + + cluster = Cluster(['127.0.0.1'], ssl_context=ssl_context) + session = cluster.connect() + +.. _ssl-client-verifies-server: + +Client verifies server +++++++++++++++++++++++ + +Ensure the python driver verifies the identity of the server. + +The Cassandra configuration:: + + client_encryption_options: + enabled: true + keystore: /path/to/127.0.0.1.keystore + keystore_password: myStorePass + require_client_auth: false + +For the driver configuration, it's very important to set `ssl_context.verify_mode` +to `CERT_REQUIRED`. Otherwise, the loaded verify certificate will have no effect: + +.. code-block:: python + + from cassandra.cluster import Cluster, Session + from ssl import SSLContext, PROTOCOL_TLSv1, CERT_REQUIRED + + ssl_context = SSLContext(PROTOCOL_TLSv1) + ssl_context.load_verify_locations('/path/to/rootca.crt') + ssl_context.verify_mode = CERT_REQUIRED + + cluster = Cluster(['127.0.0.1'], ssl_context=ssl_context) + session = cluster.connect() + +Additionally, you can also force the driver to verify the `hostname` of the server by passing additional options to `ssl_context.wrap_socket` via the `ssl_options` kwarg: + +.. code-block:: python + + from cassandra.cluster import Cluster, Session + from ssl import SSLContext, PROTOCOL_TLSv1, CERT_REQUIRED + + ssl_context = SSLContext(PROTOCOL_TLSv1) + ssl_context.load_verify_locations('/path/to/rootca.crt') + ssl_context.verify_mode = CERT_REQUIRED + ssl_context.check_hostname = True + ssl_options = {'server_hostname': '127.0.0.1'} + + cluster = Cluster(['127.0.0.1'], ssl_context=ssl_context, ssl_options=ssl_options) + session = cluster.connect() + +.. _ssl-server-verifies-client: + +Server verifies client +++++++++++++++++++++++ + +If Cassandra is configured to verify clients (``require_client_auth``), you need to generate +SSL key and certificate files. + +The cassandra configuration:: + + client_encryption_options: + enabled: true + keystore: /path/to/127.0.0.1.keystore + keystore_password: myStorePass + require_client_auth: true + truststore: /path/to/dse-truststore.jks + truststore_password: myStorePass + +The Python ``ssl`` APIs require the certificate in PEM format. First, create a certificate +conf file: + +.. code-block:: bash + + cat > gen_client_cert.conf <`__ +for more details about ``SSLContext`` configuration. + +**Server verifies client and client verifies server using Twisted and pyOpenSSL** + +.. code-block:: python + + from OpenSSL import SSL, crypto + from cassandra.cluster import Cluster + from cassandra.io.twistedreactor import TwistedConnection + + ssl_context = SSL.Context(SSL.TLSv1_METHOD) + ssl_context.set_verify(SSL.VERIFY_PEER, callback=lambda _1, _2, _3, _4, ok: ok) + ssl_context.use_certificate_file('/path/to/client.crt_signed') + ssl_context.use_privatekey_file('/path/to/client.key') + ssl_context.load_verify_locations('/path/to/rootca.crt') + + cluster = Cluster( + contact_points=['127.0.0.1'], + connection_class=TwistedConnection, + ssl_context=ssl_context, + ssl_options={'check_hostname': True} + ) + session = cluster.connect() + + +Connecting using Eventlet would look similar except instead of importing and using ``TwistedConnection``, you would +import and use ``EventletConnection``, including the appropriate monkey-patching. + +Versions 3.16.0 and lower +^^^^^^^^^^^^^^^^^^^^^^^^^ + +To enable SSL you will need to set :attr:`.Cluster.ssl_options` to a +dict of options. These will be passed as kwargs to ``ssl.wrap_socket()`` +when new sockets are created. Note that this use of ssl_options will be +deprecated in the next major release. + +By default, a ``ca_certs`` value should be supplied (the value should be +a string pointing to the location of the CA certs file), and you probably +want to specify ``ssl_version`` as ``ssl.PROTOCOL_TLSv1`` to match +Cassandra's default protocol. + +For example: + +.. code-block:: python + + from cassandra.cluster import Cluster + from ssl import PROTOCOL_TLSv1, CERT_REQUIRED + + ssl_opts = { + 'ca_certs': '/path/to/my/ca.certs', + 'ssl_version': PROTOCOL_TLSv1, + 'cert_reqs': CERT_REQUIRED # Certificates are required and validated + } + cluster = Cluster(ssl_options=ssl_opts) + +This is only an example to show how to pass the ssl parameters. Consider reading +the `python ssl documentation `__ for +your configuration. For further reading, Andrew Mussey has published a thorough guide on +`Using SSL with the DataStax Python driver `_. + +SSL with Twisted +++++++++++++++++ + +In case the twisted event loop is used pyOpenSSL must be installed or an exception will be risen. Also +to set the ``ssl_version`` and ``cert_reqs`` in ``ssl_opts`` the appropriate constants from pyOpenSSL are expected. + +DSE Authentication +------------------ +When authenticating against DSE, the Cassandra driver provides two auth providers that work both with legacy kerberos and Cassandra authenticators, +as well as the new DSE Unified Authentication. This allows client to configure this auth provider independently, +and in advance of any server upgrade. These auth providers are configured in the same way as any previous implementation:: + + from cassandra.auth import DSEGSSAPIAuthProvider + auth_provider = DSEGSSAPIAuthProvider(service='dse', qops=["auth"]) + cluster = Cluster(auth_provider=auth_provider) + session = cluster.connect() + +Implementations are :attr:`.DSEPlainTextAuthProvider`, :class:`.DSEGSSAPIAuthProvider` and :class:`.SaslAuthProvider`. + +DSE Unified Authentication +^^^^^^^^^^^^^^^^^^^^^^^^^^ + +With DSE (>=5.1), unified Authentication allows you to: + +* Proxy Login: Authenticate using a fixed set of authentication credentials but allow authorization of resources based another user id. +* Proxy Execute: Authenticate using a fixed set of authentication credentials but execute requests based on another user id. + +Proxy Login ++++++++++++ + +Proxy login allows you to authenticate with a user but act as another one. You need to ensure the authenticated user has the permission to use the authorization of resources of the other user. ie. this example will allow the `server` user to authenticate as usual but use the authorization of `user1`: + +.. code-block:: text + + GRANT PROXY.LOGIN on role user1 to server + +then you can do the proxy authentication.... + +.. code-block:: python + + from cassandra.cluster import Cluster + from cassandra.auth import SaslAuthProvider + + sasl_kwargs = { + "service": 'dse', + "mechanism":"PLAIN", + "username": 'server', + 'password': 'server', + 'authorization_id': 'user1' + } + + auth_provider = SaslAuthProvider(**sasl_kwargs) + c = Cluster(auth_provider=auth_provider) + s = c.connect() + s.execute(...) # all requests will be executed as 'user1' + +If you are using kerberos, you can use directly :class:`.DSEGSSAPIAuthProvider` and pass the authorization_id, like this: + +.. code-block:: python + + from cassandra.cluster import Cluster + from cassandra.auth import DSEGSSAPIAuthProvider + + # Ensure the kerberos ticket of the server user is set with the kinit utility. + auth_provider = DSEGSSAPIAuthProvider(service='dse', qops=["auth"], principal="server@DATASTAX.COM", + authorization_id='user1@DATASTAX.COM') + c = Cluster(auth_provider=auth_provider) + s = c.connect() + s.execute(...) # all requests will be executed as 'user1' + + +Proxy Execute ++++++++++++++ + +Proxy execute allows you to execute requests as another user than the authenticated one. You need to ensure the authenticated user has the permission to use the authorization of resources of the specified user. ie. this example will allow the `server` user to execute requests as `user1`: + +.. code-block:: text + + GRANT PROXY.EXECUTE on role user1 to server + +then you can do a proxy execute... + +.. code-block:: python + + from cassandra.cluster import Cluster + from cassandra.auth import DSEPlainTextAuthProvider, + + auth_provider = DSEPlainTextAuthProvider('server', 'server') + + c = Cluster(auth_provider=auth_provider) + s = c.connect() + s.execute('select * from k.t;', execute_as='user1') # the request will be executed as 'user1' + +Please see the `official documentation `_ for more details on the feature and configuration process. diff --git a/3.24.8-scylla/_sources/upgrading.rst.txt b/3.24.8-scylla/_sources/upgrading.rst.txt new file mode 100644 index 0000000000..9559fa3579 --- /dev/null +++ b/3.24.8-scylla/_sources/upgrading.rst.txt @@ -0,0 +1,388 @@ +Upgrading +========= + +.. toctree:: + :maxdepth: 1 + +Upgrading from dse-driver +------------------------- + +Since 3.21.0, scylla-driver fully supports DataStax products. dse-driver and +dse-graph users should now migrate to scylla-driver to benefit from latest bug fixes +and new features. The upgrade to this new unified driver version is straightforward +with no major API changes. + +Installation +^^^^^^^^^^^^ + +Only the `scylla-driver` package should be installed. `dse-driver` and `dse-graph` +are not required anymore:: + + pip install scylla-driver + +If you need the Graph *Fluent* API (features provided by dse-graph):: + + pip install scylla-driver[graph] + +See :doc:`installation` for more details. + +Import from the cassandra module +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +There is no `dse` module, so you should import from the `cassandra` module. You +need to change only the first module of your import statements, not the submodules. + +.. code-block:: python + + from dse.cluster import Cluster, EXEC_PROFILE_GRAPH_DEFAULT + from dse.auth import PlainTextAuthProvider + from dse.policies import WhiteListRoundRobinPolicy + + # becomes + + from cassandra.cluster import Cluster, EXEC_PROFILE_GRAPH_DEFAULT + from cassandra.auth import PlainTextAuthProvider + from cassandra.policies import WhiteListRoundRobinPolicy + +Also note that the cassandra.hosts module doesn't exist in scylla-driver. This +module is named cassandra.pool. + +dse-graph +^^^^^^^^^ + +dse-graph features are now built into scylla-driver. The only change you need +to do is your import statements: + +.. code-block:: python + + from dse_graph import .. + from dse_graph.query import .. + + # becomes + + from cassandra.datastax.graph.fluent import .. + from cassandra.datastax.graph.fluent.query import .. + +See :mod:`~.datastax.graph.fluent`. + +Session.execute and Session.execute_async API +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Although it is not common to use this API with positional arguments, it is +important to be aware that the `host` and `execute_as` parameters have had +their positional order swapped. This is only because `execute_as` was added +in dse-driver before `host`. + +See :meth:`.Session.execute`. + +Deprecations +^^^^^^^^^^^^ + +These changes are optional, but recommended: + +* Importing from `cassandra.graph` is deprecated. Consider importing from `cassandra.datastax.graph`. +* Use :class:`~.policies.DefaultLoadBalancingPolicy` instead of DSELoadBalancingPolicy. + +Upgrading to 3.0 +---------------- +Version 3.0 of the DataStax Python driver for Apache Cassandra +adds support for Cassandra 3.0 while maintaining support for +previously supported versions. In addition to substantial internal rework, +there are several updates to the API that integrators will need +to consider: + +Default consistency is now ``LOCAL_ONE`` +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Previous value was ``ONE``. The new value is introduced to mesh with the default +DC-aware load balancing policy and to match other drivers. + +Execution API Updates +^^^^^^^^^^^^^^^^^^^^^ +Result return normalization +~~~~~~~~~~~~~~~~~~~~~~~~~~~ +`PYTHON-368 `_ + +Previously results would be returned as a ``list`` of rows for result rows +up to ``fetch_size``, and ``PagedResult`` afterward. This could break +application code that assumed one type and got another. + +Now, all results are returned as an iterable :class:`~.ResultSet`. + +The preferred way to consume results of unknown size is to iterate through +them, letting automatic paging occur as they are consumed. + +.. code-block:: python + + results = session.execute("SELECT * FROM system.local") + for row in results: + process(row) + +If the expected size of the results is known, it is still possible to +materialize a list using the iterator: + +.. code-block:: python + + results = session.execute("SELECT * FROM system.local") + row_list = list(results) + +For backward compatibility, :class:`~.ResultSet` supports indexing. When +accessed at an index, a `~.ResultSet` object will materialize all its pages: + +.. code-block:: python + + results = session.execute("SELECT * FROM system.local") + first_result = results[0] # materializes results, fetching all pages + +This can send requests and load (possibly large) results into memory, so +`~.ResultSet` will log a warning on implicit materialization. + +Trace information is not attached to executed Statements +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +`PYTHON-318 `_ + +Previously trace data was attached to Statements if tracing was enabled. This +could lead to confusion if the same statement was used for multiple executions. + +Now, trace data is associated with the ``ResponseFuture`` and ``ResultSet`` +returned for each query: + +:meth:`.ResponseFuture.get_query_trace()` + +:meth:`.ResponseFuture.get_all_query_traces()` + +:meth:`.ResultSet.get_query_trace()` + +:meth:`.ResultSet.get_all_query_traces()` + +Binding named parameters now ignores extra names +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +`PYTHON-178 `_ + +Previously, :meth:`.BoundStatement.bind()` would raise if a mapping +was passed with extra names not found in the prepared statement. + +Behavior in 3.0+ is to ignore extra names. + +blist removed as soft dependency +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +`PYTHON-385 `_ + +Previously the driver had a soft dependency on ``blist sortedset``, using +that where available and using an internal fallback where possible. + +Now, the driver never chooses the ``blist`` variant, instead returning the +internal :class:`.util.SortedSet` for all ``set`` results. The class implements +all standard set operations, so no integration code should need to change unless +it explicitly checks for ``sortedset`` type. + +Metadata API Updates +^^^^^^^^^^^^^^^^^^^^ +`PYTHON-276 `_, `PYTHON-408 `_, `PYTHON-400 `_, `PYTHON-422 `_ + +Cassandra 3.0 brought a substantial overhaul to the internal schema metadata representation. +This version of the driver supports that metadata in addition to the legacy version. Doing so +also brought some changes to the metadata model. + +The present API is documented: :any:`cassandra.metadata`. Changes highlighted below: + +* All types are now exposed as CQL types instead of types derived from the internal server implementation +* Some metadata attributes have changed names to match current nomenclature (for example, :attr:`.Index.kind` in place of ``Index.type``). +* Some metadata attributes removed + + * ``TableMetadata.keyspace`` reference replaced with :attr:`.TableMetadata.keyspace_name` + * ``ColumnMetadata.index`` is removed table- and keyspace-level mappings are still maintained + +Several deprecated features are removed +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +`PYTHON-292 `_ + +* ``ResponseFuture.result`` timeout parameter is removed, use ``Session.execute`` timeout instead (`031ebb0 `_) +* ``Cluster.refresh_schema`` removed, use ``Cluster.refresh_*_metadata`` instead (`419fcdf `_) +* ``Cluster.submit_schema_refresh`` removed (`574266d `_) +* ``cqltypes`` time/date functions removed, use ``util`` entry points instead (`bb984ee `_) +* ``decoder`` module removed (`e16a073 `_) +* ``TableMetadata.keyspace`` attribute replaced with ``keyspace_name`` (`cc94073 `_) +* ``cqlengine.columns.TimeUUID.from_datetime`` removed, use ``util`` variant instead (`96489cc `_) +* ``cqlengine.columns.Float(double_precision)`` parameter removed, use ``columns.Double`` instead (`a2d3a98 `_) +* ``cqlengine`` keyspace management functions are removed in favor of the strategy-specific entry points (`4bd5909 `_) +* ``cqlengine.Model.__polymorphic_*__`` attributes removed, use ``__discriminator*`` attributes instead (`9d98c8e `_) +* ``cqlengine.statements`` will no longer warn about list list prepend behavior (`79efe97 `_) + + +Upgrading to 2.1 from 2.0 +------------------------- +Version 2.1 of the DataStax Python driver for Apache Cassandra +adds support for Cassandra 2.1 and version 3 of the native protocol. + +Cassandra 1.2, 2.0, and 2.1 are all supported. However, 1.2 only +supports protocol version 1, and 2.0 only supports versions 1 and +2, so some features may not be available. + +Using the v3 Native Protocol +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +By default, the driver will attempt to use version 2 of the +native protocol. To use version 3, you must explicitly +set the :attr:`~.Cluster.protocol_version`: + +.. code-block:: python + + from cassandra.cluster import Cluster + + cluster = Cluster(protocol_version=3) + +Note that protocol version 3 is only supported by Cassandra 2.1+. + +In future releases, the driver may default to using protocol version +3. + +Working with User-Defined Types +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Cassandra 2.1 introduced the ability to define new types:: + + USE KEYSPACE mykeyspace; + + CREATE TYPE address (street text, city text, zip int); + +The driver generally expects you to use instances of a specific +class to represent column values of this type. You can let the +driver know what class to use with :meth:`.Cluster.register_user_type`: + +.. code-block:: python + + cluster = Cluster() + + class Address(object): + + def __init__(self, street, city, zipcode): + self.street = street + self.city = text + self.zipcode = zipcode + + cluster.register_user_type('mykeyspace', 'address', Address) + +When inserting data for ``address`` columns, you should pass in +instances of ``Address``. When querying data, ``address`` column +values will be instances of ``Address``. + +If no class is registered for a user-defined type, query results +will use a ``namedtuple`` class and data may only be inserted +though prepared statements. + +See :ref:`udts` for more details. + +Customizing Encoders for Non-prepared Statements +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Starting with version 2.1 of the driver, it is possible to customize +how Python types are converted to CQL literals when working with +non-prepared statements. This is done on a per-:class:`~.Session` +basis through :attr:`.Session.encoder`: + +.. code-block:: python + + cluster = Cluster() + session = cluster.connect() + session.encoder.mapping[tuple] = session.encoder.cql_encode_tuple + +See :ref:`type-conversions` for the table of default CQL literal conversions. + +Using Client-Side Protocol-Level Timestamps +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +With version 3 of the native protocol, timestamps may be supplied by the +client at the protocol level. (Normally, if they are not specified within +the CQL query itself, a timestamp is generated server-side.) + +When :attr:`~.Cluster.protocol_version` is set to 3 or higher, the driver +will automatically use client-side timestamps with microsecond precision +unless :attr:`.Session.use_client_timestamp` is changed to :const:`False`. +If a timestamp is specified within the CQL query, it will override the +timestamp generated by the driver. + +Upgrading to 2.0 from 1.x +------------------------- +Version 2.0 of the DataStax Python driver for Apache Cassandra +includes some notable improvements over version 1.x. This version +of the driver supports Cassandra 1.2, 2.0, and 2.1. However, not +all features may be used with Cassandra 1.2, and some new features +in 2.1 are not yet supported. + +Using the v2 Native Protocol +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +By default, the driver will attempt to use version 2 of Cassandra's +native protocol. You can explicitly set the protocol version to +2, though: + +.. code-block:: python + + from cassandra.cluster import Cluster + + cluster = Cluster(protocol_version=2) + +When working with Cassandra 1.2, you will need to +explicitly set the :attr:`~.Cluster.protocol_version` to 1: + +.. code-block:: python + + from cassandra.cluster import Cluster + + cluster = Cluster(protocol_version=1) + +Automatic Query Paging +^^^^^^^^^^^^^^^^^^^^^^ +Version 2 of the native protocol adds support for automatic query +paging, which can make dealing with large result sets much simpler. + +See :ref:`query-paging` for full details. + +Protocol-Level Batch Statements +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +With version 1 of the native protocol, batching of statements required +using a `BATCH cql query `_. +With version 2 of the native protocol, you can now batch statements at +the protocol level. This allows you to use many different prepared +statements within a single batch. + +See :class:`~.query.BatchStatement` for details and usage examples. + +SASL-based Authentication +^^^^^^^^^^^^^^^^^^^^^^^^^ +Also new in version 2 of the native protocol is SASL-based authentication. +See the section on :ref:`security` for details and examples. + +Lightweight Transactions +^^^^^^^^^^^^^^^^^^^^^^^^ +`Lightweight transactions `_ are another new feature. To use lightweight transactions, add ``IF`` clauses +to your CQL queries and set the :attr:`~.Statement.serial_consistency_level` +on your statements. + +Calling Cluster.shutdown() +^^^^^^^^^^^^^^^^^^^^^^^^^^ +In order to fix some issues around garbage collection and unclean interpreter +shutdowns, version 2.0 of the driver requires you to call :meth:`.Cluster.shutdown()` +on your :class:`~.Cluster` objects when you are through with them. +This helps to guarantee a clean shutdown. + +Deprecations +^^^^^^^^^^^^ +The following functions have moved from ``cassandra.decoder`` to ``cassandra.query``. +The original functions have been left in place with a :exc:`DeprecationWarning` for +now: + +* :attr:`cassandra.decoder.tuple_factory` has moved to + :attr:`cassandra.query.tuple_factory` +* :attr:`cassandra.decoder.named_tuple_factory` has moved to + :attr:`cassandra.query.named_tuple_factory` +* :attr:`cassandra.decoder.dict_factory` has moved to + :attr:`cassandra.query.dict_factory` +* :attr:`cassandra.decoder.ordered_dict_factory` has moved to + :attr:`cassandra.query.ordered_dict_factory` + +Dependency Changes +^^^^^^^^^^^^^^^^^^ +The following dependencies have officially been made optional: + +* ``scales`` +* ``blist`` + +And one new dependency has been added (to enable Python 3 support): + +* ``six`` diff --git a/3.24.8-scylla/_sources/user_defined_types.rst.txt b/3.24.8-scylla/_sources/user_defined_types.rst.txt new file mode 100644 index 0000000000..32c03e37e8 --- /dev/null +++ b/3.24.8-scylla/_sources/user_defined_types.rst.txt @@ -0,0 +1,118 @@ +.. _udts: + +User Defined Types +================== +Cassandra 2.1 introduced user-defined types (UDTs). You can create a +new type through ``CREATE TYPE`` statements in CQL:: + + CREATE TYPE address (street text, zip int); + +Version 2.1 of the Python driver adds support for user-defined types. + +Registering a UDT +----------------- +You can tell the Python driver to return columns of a specific UDT as +instances of a class or a dict by registering them with your :class:`~.Cluster` +instance through :meth:`.Cluster.register_user_type`: + + +Map a Class to a UDT +++++++++++++++++++++ + +.. code-block:: python + + cluster = Cluster(protocol_version=3) + session = cluster.connect() + session.set_keyspace('mykeyspace') + session.execute("CREATE TYPE address (street text, zipcode int)") + session.execute("CREATE TABLE users (id int PRIMARY KEY, location frozen
)") + + # create a class to map to the "address" UDT + class Address(object): + + def __init__(self, street, zipcode): + self.street = street + self.zipcode = zipcode + + cluster.register_user_type('mykeyspace', 'address', Address) + + # insert a row using an instance of Address + session.execute("INSERT INTO users (id, location) VALUES (%s, %s)", + (0, Address("123 Main St.", 78723))) + + # results will include Address instances + results = session.execute("SELECT * FROM users") + row = results[0] + print(row.id, row.location.street, row.location.zipcode) + +Map a dict to a UDT ++++++++++++++++++++ + +.. code-block:: python + + cluster = Cluster(protocol_version=3) + session = cluster.connect() + session.set_keyspace('mykeyspace') + session.execute("CREATE TYPE address (street text, zipcode int)") + session.execute("CREATE TABLE users (id int PRIMARY KEY, location frozen
)") + + cluster.register_user_type('mykeyspace', 'address', dict) + + # insert a row using a prepared statement and a tuple + insert_statement = session.prepare("INSERT INTO mykeyspace.users (id, location) VALUES (?, ?)") + session.execute(insert_statement, [0, ("123 Main St.", 78723)]) + + # results will include dict instances + results = session.execute("SELECT * FROM users") + row = results[0] + print(row.id, row.location['street'], row.location['zipcode']) + +Using UDTs Without Registering Them +----------------------------------- +Although it is recommended to register your types with +:meth:`.Cluster.register_user_type`, the driver gives you some options +for working with unregistered UDTS. + +When you use prepared statements, the driver knows what data types to +expect for each placeholder. This allows you to pass any object you +want for a UDT, as long as it has attributes that match the field names +for the UDT: + +.. code-block:: python + + cluster = Cluster(protocol_version=3) + session = cluster.connect() + session.set_keyspace('mykeyspace') + session.execute("CREATE TYPE address (street text, zipcode int)") + session.execute("CREATE TABLE users (id int PRIMARY KEY, location frozen
)") + + class Foo(object): + + def __init__(self, street, zipcode, otherstuff): + self.street = street + self.zipcode = zipcode + self.otherstuff = otherstuff + + insert_statement = session.prepare("INSERT INTO users (id, location) VALUES (?, ?)") + + # since we're using a prepared statement, we don't *have* to register + # a class to map to the UDT to insert data. The object just needs to have + # "street" and "zipcode" attributes (which Foo does): + session.execute(insert_statement, [0, Foo("123 Main St.", 78723, "some other stuff")]) + + # when we query data, UDT columns that don't have a class registered + # will be returned as namedtuples: + results = session.execute("SELECT * FROM users") + first_row = results[0] + address = first_row.location + print(address) # prints "Address(street='123 Main St.', zipcode=78723)" + street = address.street + zipcode = address.street + +As shown in the code example, inserting data for UDT columns without registering +a class works fine for prepared statements. However, **you must register a +class to insert UDT columns with unprepared statements**.\* You can still query +UDT columns without registered classes using unprepared statements, they will +simply return ``namedtuple`` instances (just like prepared statements do). + +\* this applies to *parameterized* unprepared statements, in which the driver will be formatting parameters -- not statements with interpolated UDT literals. diff --git a/3.24.8-scylla/_static/basic.css b/3.24.8-scylla/_static/basic.css new file mode 100644 index 0000000000..603f6a8798 --- /dev/null +++ b/3.24.8-scylla/_static/basic.css @@ -0,0 +1,905 @@ +/* + * basic.css + * ~~~~~~~~~ + * + * Sphinx stylesheet -- basic theme. + * + * :copyright: Copyright 2007-2021 by the Sphinx team, see AUTHORS. + * :license: BSD, see LICENSE for details. + * + */ + +/* -- main layout ----------------------------------------------------------- */ + +div.clearer { + clear: both; +} + +div.section::after { + display: block; + content: ''; + clear: left; +} + +/* -- relbar ---------------------------------------------------------------- */ + +div.related { + width: 100%; + font-size: 90%; +} + +div.related h3 { + display: none; +} + +div.related ul { + margin: 0; + padding: 0 0 0 10px; + list-style: none; +} + +div.related li { + display: inline; +} + +div.related li.right { + float: right; + margin-right: 5px; +} + +/* -- sidebar --------------------------------------------------------------- */ + +div.sphinxsidebarwrapper { + padding: 10px 5px 0 10px; +} + +div.sphinxsidebar { + float: left; + width: 230px; + margin-left: -100%; + font-size: 90%; + word-wrap: break-word; + overflow-wrap : break-word; +} + +div.sphinxsidebar ul { + list-style: none; +} + +div.sphinxsidebar ul ul, +div.sphinxsidebar ul.want-points { + margin-left: 20px; + list-style: square; +} + +div.sphinxsidebar ul ul { + margin-top: 0; + margin-bottom: 0; +} + +div.sphinxsidebar form { + margin-top: 10px; +} + +div.sphinxsidebar input { + border: 1px solid #98dbcc; + font-family: sans-serif; + font-size: 1em; +} + +div.sphinxsidebar #searchbox form.search { + overflow: hidden; +} + +div.sphinxsidebar #searchbox input[type="text"] { + float: left; + width: 80%; + padding: 0.25em; + box-sizing: border-box; +} + +div.sphinxsidebar #searchbox input[type="submit"] { + float: left; + width: 20%; + border-left: none; + padding: 0.25em; + box-sizing: border-box; +} + + +img { + border: 0; + max-width: 100%; +} + +/* -- search page ----------------------------------------------------------- */ + +ul.search { + margin: 10px 0 0 20px; + padding: 0; +} + +ul.search li { + padding: 5px 0 5px 20px; + background-image: url(file.png); + background-repeat: no-repeat; + background-position: 0 7px; +} + +ul.search li a { + font-weight: bold; +} + +ul.search li p.context { + color: #888; + margin: 2px 0 0 30px; + text-align: left; +} + +ul.keywordmatches li.goodmatch a { + font-weight: bold; +} + +/* -- index page ------------------------------------------------------------ */ + +table.contentstable { + width: 90%; + margin-left: auto; + margin-right: auto; +} + +table.contentstable p.biglink { + line-height: 150%; +} + +a.biglink { + font-size: 1.3em; +} + +span.linkdescr { + font-style: italic; + padding-top: 5px; + font-size: 90%; +} + +/* -- general index --------------------------------------------------------- */ + +table.indextable { + width: 100%; +} + +table.indextable td { + text-align: left; + vertical-align: top; +} + +table.indextable ul { + margin-top: 0; + margin-bottom: 0; + list-style-type: none; +} + +table.indextable > tbody > tr > td > ul { + padding-left: 0em; +} + +table.indextable tr.pcap { + height: 10px; +} + +table.indextable tr.cap { + margin-top: 10px; + background-color: #f2f2f2; +} + +img.toggler { + margin-right: 3px; + margin-top: 3px; + cursor: pointer; +} + +div.modindex-jumpbox { + border-top: 1px solid #ddd; + border-bottom: 1px solid #ddd; + margin: 1em 0 1em 0; + padding: 0.4em; +} + +div.genindex-jumpbox { + border-top: 1px solid #ddd; + border-bottom: 1px solid #ddd; + margin: 1em 0 1em 0; + padding: 0.4em; +} + +/* -- domain module index --------------------------------------------------- */ + +table.modindextable td { + padding: 2px; + border-collapse: collapse; +} + +/* -- general body styles --------------------------------------------------- */ + +div.body { + min-width: 450px; + max-width: 800px; +} + +div.body p, div.body dd, div.body li, div.body blockquote { + -moz-hyphens: auto; + -ms-hyphens: auto; + -webkit-hyphens: auto; + hyphens: auto; +} + +a.headerlink { + visibility: hidden; +} + +a.brackets:before, +span.brackets > a:before{ + content: "["; +} + +a.brackets:after, +span.brackets > a:after { + content: "]"; +} + +h1:hover > a.headerlink, +h2:hover > a.headerlink, +h3:hover > a.headerlink, +h4:hover > a.headerlink, +h5:hover > a.headerlink, +h6:hover > a.headerlink, +dt:hover > a.headerlink, +caption:hover > a.headerlink, +p.caption:hover > a.headerlink, +div.code-block-caption:hover > a.headerlink { + visibility: visible; +} + +div.body p.caption { + text-align: inherit; +} + +div.body td { + text-align: left; +} + +.first { + margin-top: 0 !important; +} + +p.rubric { + margin-top: 30px; + font-weight: bold; +} + +img.align-left, figure.align-left, .figure.align-left, object.align-left { + clear: left; + float: left; + margin-right: 1em; +} + +img.align-right, figure.align-right, .figure.align-right, object.align-right { + clear: right; + float: right; + margin-left: 1em; +} + +img.align-center, figure.align-center, .figure.align-center, object.align-center { + display: block; + margin-left: auto; + margin-right: auto; +} + +img.align-default, figure.align-default, .figure.align-default { + display: block; + margin-left: auto; + margin-right: auto; +} + +.align-left { + text-align: left; +} + +.align-center { + text-align: center; +} + +.align-default { + text-align: center; +} + +.align-right { + text-align: right; +} + +/* -- sidebars -------------------------------------------------------------- */ + +div.sidebar, +aside.sidebar { + margin: 0 0 0.5em 1em; + border: 1px solid #ddb; + padding: 7px; + background-color: #ffe; + width: 40%; + float: right; + clear: right; + overflow-x: auto; +} + +p.sidebar-title { + font-weight: bold; +} + +div.admonition, div.topic, blockquote { + clear: left; +} + +/* -- topics ---------------------------------------------------------------- */ + +div.topic { + border: 1px solid #ccc; + padding: 7px; + margin: 10px 0 10px 0; +} + +p.topic-title { + font-size: 1.1em; + font-weight: bold; + margin-top: 10px; +} + +/* -- admonitions ----------------------------------------------------------- */ + +div.admonition { + margin-top: 10px; + margin-bottom: 10px; + padding: 7px; +} + +div.admonition dt { + font-weight: bold; +} + +p.admonition-title { + margin: 0px 10px 5px 0px; + font-weight: bold; +} + +div.body p.centered { + text-align: center; + margin-top: 25px; +} + +/* -- content of sidebars/topics/admonitions -------------------------------- */ + +div.sidebar > :last-child, +aside.sidebar > :last-child, +div.topic > :last-child, +div.admonition > :last-child { + margin-bottom: 0; +} + +div.sidebar::after, +aside.sidebar::after, +div.topic::after, +div.admonition::after, +blockquote::after { + display: block; + content: ''; + clear: both; +} + +/* -- tables ---------------------------------------------------------------- */ + +table.docutils { + margin-top: 10px; + margin-bottom: 10px; + border: 0; + border-collapse: collapse; +} + +table.align-center { + margin-left: auto; + margin-right: auto; +} + +table.align-default { + margin-left: auto; + margin-right: auto; +} + +table caption span.caption-number { + font-style: italic; +} + +table caption span.caption-text { +} + +table.docutils td, table.docutils th { + padding: 1px 8px 1px 5px; + border-top: 0; + border-left: 0; + border-right: 0; + border-bottom: 1px solid #aaa; +} + +table.footnote td, table.footnote th { + border: 0 !important; +} + +th { + text-align: left; + padding-right: 5px; +} + +table.citation { + border-left: solid 1px gray; + margin-left: 1px; +} + +table.citation td { + border-bottom: none; +} + +th > :first-child, +td > :first-child { + margin-top: 0px; +} + +th > :last-child, +td > :last-child { + margin-bottom: 0px; +} + +/* -- figures --------------------------------------------------------------- */ + +div.figure, figure { + margin: 0.5em; + padding: 0.5em; +} + +div.figure p.caption, figcaption { + padding: 0.3em; +} + +div.figure p.caption span.caption-number, +figcaption span.caption-number { + font-style: italic; +} + +div.figure p.caption span.caption-text, +figcaption span.caption-text { +} + +/* -- field list styles ----------------------------------------------------- */ + +table.field-list td, table.field-list th { + border: 0 !important; +} + +.field-list ul { + margin: 0; + padding-left: 1em; +} + +.field-list p { + margin: 0; +} + +.field-name { + -moz-hyphens: manual; + -ms-hyphens: manual; + -webkit-hyphens: manual; + hyphens: manual; +} + +/* -- hlist styles ---------------------------------------------------------- */ + +table.hlist { + margin: 1em 0; +} + +table.hlist td { + vertical-align: top; +} + +/* -- object description styles --------------------------------------------- */ + +.sig { + font-family: 'Consolas', 'Menlo', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace; +} + +.sig-name, code.descname { + background-color: transparent; + font-weight: bold; +} + +.sig-name { + font-size: 1.1em; +} + +code.descname { + font-size: 1.2em; +} + +.sig-prename, code.descclassname { + background-color: transparent; +} + +.optional { + font-size: 1.3em; +} + +.sig-paren { + font-size: larger; +} + +.sig-param.n { + font-style: italic; +} + +/* C++ specific styling */ + +.sig-inline.c-texpr, +.sig-inline.cpp-texpr { + font-family: unset; +} + +.sig.c .k, .sig.c .kt, +.sig.cpp .k, .sig.cpp .kt { + color: #0033B3; +} + +.sig.c .m, +.sig.cpp .m { + color: #1750EB; +} + +.sig.c .s, .sig.c .sc, +.sig.cpp .s, .sig.cpp .sc { + color: #067D17; +} + + +/* -- other body styles ----------------------------------------------------- */ + +ol.arabic { + list-style: decimal; +} + +ol.loweralpha { + list-style: lower-alpha; +} + +ol.upperalpha { + list-style: upper-alpha; +} + +ol.lowerroman { + list-style: lower-roman; +} + +ol.upperroman { + list-style: upper-roman; +} + +:not(li) > ol > li:first-child > :first-child, +:not(li) > ul > li:first-child > :first-child { + margin-top: 0px; +} + +:not(li) > ol > li:last-child > :last-child, +:not(li) > ul > li:last-child > :last-child { + margin-bottom: 0px; +} + +ol.simple ol p, +ol.simple ul p, +ul.simple ol p, +ul.simple ul p { + margin-top: 0; +} + +ol.simple > li:not(:first-child) > p, +ul.simple > li:not(:first-child) > p { + margin-top: 0; +} + +ol.simple p, +ul.simple p { + margin-bottom: 0; +} + +dl.footnote > dt, +dl.citation > dt { + float: left; + margin-right: 0.5em; +} + +dl.footnote > dd, +dl.citation > dd { + margin-bottom: 0em; +} + +dl.footnote > dd:after, +dl.citation > dd:after { + content: ""; + clear: both; +} + +dl.field-list { + display: grid; + grid-template-columns: fit-content(30%) auto; +} + +dl.field-list > dt { + font-weight: bold; + word-break: break-word; + padding-left: 0.5em; + padding-right: 5px; +} + +dl.field-list > dt:after { + content: ":"; +} + +dl.field-list > dd { + padding-left: 0.5em; + margin-top: 0em; + margin-left: 0em; + margin-bottom: 0em; +} + +dl { + margin-bottom: 15px; +} + +dd > :first-child { + margin-top: 0px; +} + +dd ul, dd table { + margin-bottom: 10px; +} + +dd { + margin-top: 3px; + margin-bottom: 10px; + margin-left: 30px; +} + +dl > dd:last-child, +dl > dd:last-child > :last-child { + margin-bottom: 0; +} + +dt:target, span.highlighted { + background-color: #fbe54e; +} + +rect.highlighted { + fill: #fbe54e; +} + +dl.glossary dt { + font-weight: bold; + font-size: 1.1em; +} + +.versionmodified { + font-style: italic; +} + +.system-message { + background-color: #fda; + padding: 5px; + border: 3px solid red; +} + +.footnote:target { + background-color: #ffa; +} + +.line-block { + display: block; + margin-top: 1em; + margin-bottom: 1em; +} + +.line-block .line-block { + margin-top: 0; + margin-bottom: 0; + margin-left: 1.5em; +} + +.guilabel, .menuselection { + font-family: sans-serif; +} + +.accelerator { + text-decoration: underline; +} + +.classifier { + font-style: oblique; +} + +.classifier:before { + font-style: normal; + margin: 0 0.5em; + content: ":"; + display: inline-block; +} + +abbr, acronym { + border-bottom: dotted 1px; + cursor: help; +} + +/* -- code displays --------------------------------------------------------- */ + +pre { + overflow: auto; + overflow-y: hidden; /* fixes display issues on Chrome browsers */ +} + +pre, div[class*="highlight-"] { + clear: both; +} + +span.pre { + -moz-hyphens: none; + -ms-hyphens: none; + -webkit-hyphens: none; + hyphens: none; +} + +div[class*="highlight-"] { + margin: 1em 0; +} + +td.linenos pre { + border: 0; + background-color: transparent; + color: #aaa; +} + +table.highlighttable { + display: block; +} + +table.highlighttable tbody { + display: block; +} + +table.highlighttable tr { + display: flex; +} + +table.highlighttable td { + margin: 0; + padding: 0; +} + +table.highlighttable td.linenos { + padding-right: 0.5em; +} + +table.highlighttable td.code { + flex: 1; + overflow: hidden; +} + +.highlight .hll { + display: block; +} + +div.highlight pre, +table.highlighttable pre { + margin: 0; +} + +div.code-block-caption + div { + margin-top: 0; +} + +div.code-block-caption { + margin-top: 1em; + padding: 2px 5px; + font-size: small; +} + +div.code-block-caption code { + background-color: transparent; +} + +table.highlighttable td.linenos, +span.linenos, +div.highlight span.gp { /* gp: Generic.Prompt */ + user-select: none; + -webkit-user-select: text; /* Safari fallback only */ + -webkit-user-select: none; /* Chrome/Safari */ + -moz-user-select: none; /* Firefox */ + -ms-user-select: none; /* IE10+ */ +} + +div.code-block-caption span.caption-number { + padding: 0.1em 0.3em; + font-style: italic; +} + +div.code-block-caption span.caption-text { +} + +div.literal-block-wrapper { + margin: 1em 0; +} + +code.xref, a code { + background-color: transparent; + font-weight: bold; +} + +h1 code, h2 code, h3 code, h4 code, h5 code, h6 code { + background-color: transparent; +} + +.viewcode-link { + float: right; +} + +.viewcode-back { + float: right; + font-family: sans-serif; +} + +div.viewcode-block:target { + margin: -1px -10px; + padding: 0 10px; +} + +/* -- math display ---------------------------------------------------------- */ + +img.math { + vertical-align: middle; +} + +div.body div.math p { + text-align: center; +} + +span.eqno { + float: right; +} + +span.eqno a.headerlink { + position: absolute; + z-index: 1; +} + +div.math:hover a.headerlink { + visibility: visible; +} + +/* -- printout stylesheet --------------------------------------------------- */ + +@media print { + div.document, + div.documentwrapper, + div.bodywrapper { + margin: 0 !important; + width: 100%; + } + + div.sphinxsidebar, + div.related, + div.footer, + #top-link { + display: none; + } +} \ No newline at end of file diff --git a/3.24.8-scylla/_static/check-solid.svg b/3.24.8-scylla/_static/check-solid.svg new file mode 100644 index 0000000000..92fad4b5c0 --- /dev/null +++ b/3.24.8-scylla/_static/check-solid.svg @@ -0,0 +1,4 @@ + + + + diff --git a/3.24.8-scylla/_static/clipboard.min.js b/3.24.8-scylla/_static/clipboard.min.js new file mode 100644 index 0000000000..54b3c46381 --- /dev/null +++ b/3.24.8-scylla/_static/clipboard.min.js @@ -0,0 +1,7 @@ +/*! + * clipboard.js v2.0.8 + * https://clipboardjs.com/ + * + * Licensed MIT © Zeno Rocha + */ +!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?exports.ClipboardJS=e():t.ClipboardJS=e()}(this,function(){return n={686:function(t,e,n){"use strict";n.d(e,{default:function(){return o}});var e=n(279),i=n.n(e),e=n(370),u=n.n(e),e=n(817),c=n.n(e);function a(t){try{return document.execCommand(t)}catch(t){return}}var f=function(t){t=c()(t);return a("cut"),t};var l=function(t){var e,n,o,r=1 + + + + diff --git a/3.24.8-scylla/_static/copybutton.css b/3.24.8-scylla/_static/copybutton.css new file mode 100644 index 0000000000..f1916ec7d1 --- /dev/null +++ b/3.24.8-scylla/_static/copybutton.css @@ -0,0 +1,94 @@ +/* Copy buttons */ +button.copybtn { + position: absolute; + display: flex; + top: .3em; + right: .3em; + width: 1.7em; + height: 1.7em; + opacity: 0; + transition: opacity 0.3s, border .3s, background-color .3s; + user-select: none; + padding: 0; + border: none; + outline: none; + border-radius: 0.4em; + /* The colors that GitHub uses */ + border: #1b1f2426 1px solid; + background-color: #f6f8fa; + color: #57606a; +} + +button.copybtn.success { + border-color: #22863a; + color: #22863a; +} + +button.copybtn svg { + stroke: currentColor; + width: 1.5em; + height: 1.5em; + padding: 0.1em; +} + +div.highlight { + position: relative; +} + +/* Show the copybutton */ +.highlight:hover button.copybtn, button.copybtn.success { + opacity: 1; +} + +.highlight button.copybtn:hover { + background-color: rgb(235, 235, 235); +} + +.highlight button.copybtn:active { + background-color: rgb(187, 187, 187); +} + +/** + * A minimal CSS-only tooltip copied from: + * https://codepen.io/mildrenben/pen/rVBrpK + * + * To use, write HTML like the following: + * + *

Short

+ */ + .o-tooltip--left { + position: relative; + } + + .o-tooltip--left:after { + opacity: 0; + visibility: hidden; + position: absolute; + content: attr(data-tooltip); + padding: .2em; + font-size: .8em; + left: -.2em; + background: grey; + color: white; + white-space: nowrap; + z-index: 2; + border-radius: 2px; + transform: translateX(-102%) translateY(0); + transition: opacity 0.2s cubic-bezier(0.64, 0.09, 0.08, 1), transform 0.2s cubic-bezier(0.64, 0.09, 0.08, 1); +} + +.o-tooltip--left:hover:after { + display: block; + opacity: 1; + visibility: visible; + transform: translateX(-100%) translateY(0); + transition: opacity 0.2s cubic-bezier(0.64, 0.09, 0.08, 1), transform 0.2s cubic-bezier(0.64, 0.09, 0.08, 1); + transition-delay: .5s; +} + +/* By default the copy button shouldn't show up when printing a page */ +@media print { + button.copybtn { + display: none; + } +} diff --git a/3.24.8-scylla/_static/copybutton.js b/3.24.8-scylla/_static/copybutton.js new file mode 100644 index 0000000000..2ea7ff3e21 --- /dev/null +++ b/3.24.8-scylla/_static/copybutton.js @@ -0,0 +1,248 @@ +// Localization support +const messages = { + 'en': { + 'copy': 'Copy', + 'copy_to_clipboard': 'Copy to clipboard', + 'copy_success': 'Copied!', + 'copy_failure': 'Failed to copy', + }, + 'es' : { + 'copy': 'Copiar', + 'copy_to_clipboard': 'Copiar al portapapeles', + 'copy_success': '¡Copiado!', + 'copy_failure': 'Error al copiar', + }, + 'de' : { + 'copy': 'Kopieren', + 'copy_to_clipboard': 'In die Zwischenablage kopieren', + 'copy_success': 'Kopiert!', + 'copy_failure': 'Fehler beim Kopieren', + }, + 'fr' : { + 'copy': 'Copier', + 'copy_to_clipboard': 'Copier dans le presse-papier', + 'copy_success': 'Copié !', + 'copy_failure': 'Échec de la copie', + }, + 'ru': { + 'copy': 'Скопировать', + 'copy_to_clipboard': 'Скопировать в буфер', + 'copy_success': 'Скопировано!', + 'copy_failure': 'Не удалось скопировать', + }, + 'zh-CN': { + 'copy': '复制', + 'copy_to_clipboard': '复制到剪贴板', + 'copy_success': '复制成功!', + 'copy_failure': '复制失败', + }, + 'it' : { + 'copy': 'Copiare', + 'copy_to_clipboard': 'Copiato negli appunti', + 'copy_success': 'Copiato!', + 'copy_failure': 'Errore durante la copia', + } +} + +let locale = 'en' +if( document.documentElement.lang !== undefined + && messages[document.documentElement.lang] !== undefined ) { + locale = document.documentElement.lang +} + +let doc_url_root = DOCUMENTATION_OPTIONS.URL_ROOT; +if (doc_url_root == '#') { + doc_url_root = ''; +} + +/** + * SVG files for our copy buttons + */ +let iconCheck = ` + ${messages[locale]['copy_success']} + + +` + +// If the user specified their own SVG use that, otherwise use the default +let iconCopy = ``; +if (!iconCopy) { + iconCopy = ` + ${messages[locale]['copy_to_clipboard']} + + + +` +} + +/** + * Set up copy/paste for code blocks + */ + +const runWhenDOMLoaded = cb => { + if (document.readyState != 'loading') { + cb() + } else if (document.addEventListener) { + document.addEventListener('DOMContentLoaded', cb) + } else { + document.attachEvent('onreadystatechange', function() { + if (document.readyState == 'complete') cb() + }) + } +} + +const codeCellId = index => `codecell${index}` + +// Clears selected text since ClipboardJS will select the text when copying +const clearSelection = () => { + if (window.getSelection) { + window.getSelection().removeAllRanges() + } else if (document.selection) { + document.selection.empty() + } +} + +// Changes tooltip text for a moment, then changes it back +// We want the timeout of our `success` class to be a bit shorter than the +// tooltip and icon change, so that we can hide the icon before changing back. +var timeoutIcon = 2000; +var timeoutSuccessClass = 1500; + +const temporarilyChangeTooltip = (el, oldText, newText) => { + el.setAttribute('data-tooltip', newText) + el.classList.add('success') + // Remove success a little bit sooner than we change the tooltip + // So that we can use CSS to hide the copybutton first + setTimeout(() => el.classList.remove('success'), timeoutSuccessClass) + setTimeout(() => el.setAttribute('data-tooltip', oldText), timeoutIcon) +} + +// Changes the copy button icon for two seconds, then changes it back +const temporarilyChangeIcon = (el) => { + el.innerHTML = iconCheck; + setTimeout(() => {el.innerHTML = iconCopy}, timeoutIcon) +} + +const addCopyButtonToCodeCells = () => { + // If ClipboardJS hasn't loaded, wait a bit and try again. This + // happens because we load ClipboardJS asynchronously. + if (window.ClipboardJS === undefined) { + setTimeout(addCopyButtonToCodeCells, 250) + return + } + + // Add copybuttons to all of our code cells + const COPYBUTTON_SELECTOR = 'div.highlight pre'; + const codeCells = document.querySelectorAll(COPYBUTTON_SELECTOR) + codeCells.forEach((codeCell, index) => { + const id = codeCellId(index) + codeCell.setAttribute('id', id) + + const clipboardButton = id => + `` + codeCell.insertAdjacentHTML('afterend', clipboardButton(id)) + }) + +function escapeRegExp(string) { + return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string +} + +/** + * Removes excluded text from a Node. + * + * @param {Node} target Node to filter. + * @param {string} exclude CSS selector of nodes to exclude. + * @returns {DOMString} Text from `target` with text removed. + */ +function filterText(target, exclude) { + const clone = target.cloneNode(true); // clone as to not modify the live DOM + if (exclude) { + // remove excluded nodes + clone.querySelectorAll(exclude).forEach(node => node.remove()); + } + return clone.innerText; +} + +// Callback when a copy button is clicked. Will be passed the node that was clicked +// should then grab the text and replace pieces of text that shouldn't be used in output +function formatCopyText(textContent, copybuttonPromptText, isRegexp = false, onlyCopyPromptLines = true, removePrompts = true, copyEmptyLines = true, lineContinuationChar = "", hereDocDelim = "") { + var regexp; + var match; + + // Do we check for line continuation characters and "HERE-documents"? + var useLineCont = !!lineContinuationChar + var useHereDoc = !!hereDocDelim + + // create regexp to capture prompt and remaining line + if (isRegexp) { + regexp = new RegExp('^(' + copybuttonPromptText + ')(.*)') + } else { + regexp = new RegExp('^(' + escapeRegExp(copybuttonPromptText) + ')(.*)') + } + + const outputLines = []; + var promptFound = false; + var gotLineCont = false; + var gotHereDoc = false; + const lineGotPrompt = []; + for (const line of textContent.split('\n')) { + match = line.match(regexp) + if (match || gotLineCont || gotHereDoc) { + promptFound = regexp.test(line) + lineGotPrompt.push(promptFound) + if (removePrompts && promptFound) { + outputLines.push(match[2]) + } else { + outputLines.push(line) + } + gotLineCont = line.endsWith(lineContinuationChar) & useLineCont + if (line.includes(hereDocDelim) & useHereDoc) + gotHereDoc = !gotHereDoc + } else if (!onlyCopyPromptLines) { + outputLines.push(line) + } else if (copyEmptyLines && line.trim() === '') { + outputLines.push(line) + } + } + + // If no lines with the prompt were found then just use original lines + if (lineGotPrompt.some(v => v === true)) { + textContent = outputLines.join('\n'); + } + + // Remove a trailing newline to avoid auto-running when pasting + if (textContent.endsWith("\n")) { + textContent = textContent.slice(0, -1) + } + return textContent +} + + +var copyTargetText = (trigger) => { + var target = document.querySelector(trigger.attributes['data-clipboard-target'].value); + + // get filtered text + let exclude = '.linenos'; + + let text = filterText(target, exclude); + return formatCopyText(text, '', false, true, true, true, '', '') +} + + // Initialize with a callback so we can modify the text before copy + const clipboard = new ClipboardJS('.copybtn', {text: copyTargetText}) + + // Update UI with error/success messages + clipboard.on('success', event => { + clearSelection() + temporarilyChangeTooltip(event.trigger, messages[locale]['copy'], messages[locale]['copy_success']) + temporarilyChangeIcon(event.trigger) + }) + + clipboard.on('error', event => { + temporarilyChangeTooltip(event.trigger, messages[locale]['copy'], messages[locale]['copy_failure']) + }) +} + +runWhenDOMLoaded(addCopyButtonToCodeCells) \ No newline at end of file diff --git a/3.24.8-scylla/_static/copybutton_funcs.js b/3.24.8-scylla/_static/copybutton_funcs.js new file mode 100644 index 0000000000..dbe1aaad79 --- /dev/null +++ b/3.24.8-scylla/_static/copybutton_funcs.js @@ -0,0 +1,73 @@ +function escapeRegExp(string) { + return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string +} + +/** + * Removes excluded text from a Node. + * + * @param {Node} target Node to filter. + * @param {string} exclude CSS selector of nodes to exclude. + * @returns {DOMString} Text from `target` with text removed. + */ +export function filterText(target, exclude) { + const clone = target.cloneNode(true); // clone as to not modify the live DOM + if (exclude) { + // remove excluded nodes + clone.querySelectorAll(exclude).forEach(node => node.remove()); + } + return clone.innerText; +} + +// Callback when a copy button is clicked. Will be passed the node that was clicked +// should then grab the text and replace pieces of text that shouldn't be used in output +export function formatCopyText(textContent, copybuttonPromptText, isRegexp = false, onlyCopyPromptLines = true, removePrompts = true, copyEmptyLines = true, lineContinuationChar = "", hereDocDelim = "") { + var regexp; + var match; + + // Do we check for line continuation characters and "HERE-documents"? + var useLineCont = !!lineContinuationChar + var useHereDoc = !!hereDocDelim + + // create regexp to capture prompt and remaining line + if (isRegexp) { + regexp = new RegExp('^(' + copybuttonPromptText + ')(.*)') + } else { + regexp = new RegExp('^(' + escapeRegExp(copybuttonPromptText) + ')(.*)') + } + + const outputLines = []; + var promptFound = false; + var gotLineCont = false; + var gotHereDoc = false; + const lineGotPrompt = []; + for (const line of textContent.split('\n')) { + match = line.match(regexp) + if (match || gotLineCont || gotHereDoc) { + promptFound = regexp.test(line) + lineGotPrompt.push(promptFound) + if (removePrompts && promptFound) { + outputLines.push(match[2]) + } else { + outputLines.push(line) + } + gotLineCont = line.endsWith(lineContinuationChar) & useLineCont + if (line.includes(hereDocDelim) & useHereDoc) + gotHereDoc = !gotHereDoc + } else if (!onlyCopyPromptLines) { + outputLines.push(line) + } else if (copyEmptyLines && line.trim() === '') { + outputLines.push(line) + } + } + + // If no lines with the prompt were found then just use original lines + if (lineGotPrompt.some(v => v === true)) { + textContent = outputLines.join('\n'); + } + + // Remove a trailing newline to avoid auto-running when pasting + if (textContent.endsWith("\n")) { + textContent = textContent.slice(0, -1) + } + return textContent +} diff --git a/3.24.8-scylla/_static/css/main.css b/3.24.8-scylla/_static/css/main.css new file mode 100644 index 0000000000..4ac0174528 --- /dev/null +++ b/3.24.8-scylla/_static/css/main.css @@ -0,0 +1 @@ +@media print,screen and (min-width:40em){.reveal,.reveal.large,.reveal.small,.reveal.tiny{left:auto;margin:0 auto;right:auto}}/*! normalize.css v8.0.0 | MIT License | github.com/necolas/normalize.css */html{-webkit-text-size-adjust:100%;line-height:1.15}h1{font-size:2em;margin:.67em 0}hr{-webkit-box-sizing:content-box;box-sizing:content-box;overflow:visible}pre{font-family:monospace,monospace;font-size:1em}a{background-color:transparent}abbr[title]{border-bottom:0;-webkit-text-decoration:underline dotted;text-decoration:underline dotted}b,strong{font-weight:bolder}code,kbd,samp{font-family:monospace,monospace;font-size:1em}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}img{border-style:none}button,input,optgroup,select,textarea{font-size:100%;line-height:1.15;margin:0}button,input{overflow:visible}button,select{text-transform:none}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button}[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner,button::-moz-focus-inner{border-style:none;padding:0}[type=button]:-moz-focusring,[type=reset]:-moz-focusring,[type=submit]:-moz-focusring,button:-moz-focusring{outline:1px dotted ButtonText}fieldset{padding:.35em .75em .625em}legend{-webkit-box-sizing:border-box;box-sizing:border-box;color:inherit;display:table;padding:0;white-space:normal}progress{vertical-align:baseline}textarea{overflow:auto}[type=checkbox],[type=radio]{-webkit-box-sizing:border-box;box-sizing:border-box;padding:0}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}details{display:block}summary{display:list-item}template{display:none}[hidden]{display:none}[data-whatinput=mouse] *,[data-whatinput=mouse] :focus,[data-whatinput=touch] *,[data-whatinput=touch] :focus,[data-whatintent=mouse] *,[data-whatintent=mouse] :focus,[data-whatintent=touch] *,[data-whatintent=touch] :focus{outline:0}[draggable=false]{-webkit-touch-callout:none;-webkit-user-select:none}.foundation-mq{font-family:"small=0em&medium=40em&large=64em&xlarge=75em&xxlarge=90em"}html{-webkit-box-sizing:border-box;font-size:100%}*,:after,:before{-webkit-box-sizing:inherit}body{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;background:#fefefe;color:#0a0a0a;font-family:Helvetica Neue,Helvetica,Roboto,Arial,sans-serif;font-weight:400;line-height:1.5;margin:0;padding:0}img{-ms-interpolation-mode:bicubic;display:inline-block;height:auto;vertical-align:middle}textarea{border-radius:0;height:auto;min-height:50px}select{-webkit-box-sizing:border-box;box-sizing:border-box;width:100%}.map_canvas embed,.map_canvas img,.map_canvas object,.mqa-display embed,.mqa-display img,.mqa-display object{max-width:none!important}button{-webkit-appearance:none;-moz-appearance:none;appearance:none;background:0 0;border:0;border-radius:0;cursor:auto;line-height:1;padding:0}[data-whatinput=mouse] button{outline:0}pre{-webkit-overflow-scrolling:touch;overflow:auto}button,input,optgroup,select,textarea{font-family:inherit}.is-visible{display:block!important}.is-hidden{display:none!important}[type=color],[type=date],[type=datetime-local],[type=datetime],[type=email],[type=month],[type=number],[type=password],[type=search],[type=tel],[type=text],[type=time],[type=url],[type=week],textarea{-webkit-appearance:none;-moz-appearance:none;appearance:none;background-color:#fefefe;border:1px solid #cacaca;border-radius:0;-webkit-box-shadow:inset 0 1px 2px hsla(0,0%,4%,.1);box-shadow:inset 0 1px 2px hsla(0,0%,4%,.1);-webkit-box-sizing:border-box;box-sizing:border-box;color:#0a0a0a;display:block;font-family:inherit;font-size:1rem;font-weight:400;height:2.4375rem;line-height:1.5;margin:0 0 1rem;padding:.5rem;-webkit-transition:border-color .25s ease-in-out,-webkit-box-shadow .5s;transition:border-color .25s ease-in-out,-webkit-box-shadow .5s;transition:box-shadow .5s,border-color .25s ease-in-out;transition:box-shadow .5s,border-color .25s ease-in-out,-webkit-box-shadow .5s;width:100%}[type=color]:focus,[type=date]:focus,[type=datetime-local]:focus,[type=datetime]:focus,[type=email]:focus,[type=month]:focus,[type=number]:focus,[type=password]:focus,[type=search]:focus,[type=tel]:focus,[type=text]:focus,[type=time]:focus,[type=url]:focus,[type=week]:focus,textarea:focus{background-color:#fefefe;border:1px solid #8a8a8a;-webkit-box-shadow:0 0 5px #cacaca;box-shadow:0 0 5px #cacaca;outline:0;-webkit-transition:border-color .25s ease-in-out,-webkit-box-shadow .5s;transition:border-color .25s ease-in-out,-webkit-box-shadow .5s;transition:box-shadow .5s,border-color .25s ease-in-out;transition:box-shadow .5s,border-color .25s ease-in-out,-webkit-box-shadow .5s}textarea{max-width:100%}textarea[rows]{height:auto}input:disabled,input[readonly],textarea:disabled,textarea[readonly]{background-color:#e6e6e6;cursor:not-allowed}[type=button],[type=submit]{-webkit-appearance:none;-moz-appearance:none;appearance:none;border-radius:0}input[type=search]{-webkit-box-sizing:border-box;box-sizing:border-box}::-webkit-input-placeholder{color:#cacaca}::-moz-placeholder{color:#cacaca}:-ms-input-placeholder{color:#cacaca}::-ms-input-placeholder{color:#cacaca}::placeholder{color:#cacaca}[type=checkbox],[type=file],[type=radio]{margin:0 0 1rem}[type=checkbox]+label,[type=radio]+label{display:inline-block;margin-bottom:0;margin-left:.5rem;margin-right:1rem;vertical-align:baseline}[type=checkbox]+label[for],[type=radio]+label[for]{cursor:pointer}label>[type=checkbox],label>[type=radio]{margin-right:.5rem}[type=file]{width:100%}label{color:#0a0a0a;display:block;font-size:.875rem;font-weight:400;line-height:1.8;margin:0}label.middle{line-height:1.5;margin:0 0 1rem;padding:.5625rem 0}.help-text{color:#0a0a0a;font-size:.8125rem;font-style:italic;margin-top:-.5rem}.input-group{-webkit-box-align:stretch;-ms-flex-align:stretch;-webkit-align-items:stretch;align-items:stretch;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;margin-bottom:1rem;width:100%}.input-group>:first-child,.input-group>:first-child.input-group-button>*{border-radius:0}.input-group>:last-child,.input-group>:last-child.input-group-button>*{border-radius:0}.input-group-button,.input-group-button a,.input-group-button button,.input-group-button input,.input-group-button label,.input-group-field,.input-group-label{margin:0;white-space:nowrap}.input-group-label{-webkit-box-flex:0;-webkit-box-align:center;-ms-flex-align:center;-webkit-align-items:center;align-items:center;background:#e6e6e6;border:1px solid #cacaca;color:#0a0a0a;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto;padding:0 1rem;text-align:center;white-space:nowrap}.input-group-label:first-child{border-right:0}.input-group-label:last-child{border-left:0}.input-group-field{-webkit-box-flex:1;border-radius:0;-webkit-flex:1 1 0px;-ms-flex:1 1 0px;flex:1 1 0px;min-width:0}.input-group-button{-webkit-box-flex:0;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto;padding-bottom:0;padding-top:0;text-align:center}.input-group-button a,.input-group-button button,.input-group-button input,.input-group-button label{-ms-flex-item-align:stretch;-webkit-align-self:stretch;align-self:stretch;font-size:1rem;height:auto;padding-bottom:0;padding-top:0}fieldset{border:0;margin:0;padding:0}legend{margin-bottom:.5rem;max-width:100%}.fieldset{border:1px solid #cacaca;margin:1.125rem 0;padding:1.25rem}.fieldset legend{margin:0 0 0 -.1875rem;padding:0 .1875rem}select{-webkit-appearance:none;-moz-appearance:none;appearance:none;background-color:#fefefe;background-image:url('data:image/svg+xml;utf8,');background-origin:content-box;background-position:right -1rem center;background-repeat:no-repeat;background-size:9px 6px;border:1px solid #cacaca;border-radius:0;color:#0a0a0a;font-family:inherit;font-size:1rem;font-weight:400;height:2.4375rem;line-height:1.5;margin:0 0 1rem;padding:.5rem 1.5rem .5rem .5rem;-webkit-transition:border-color .25s ease-in-out,-webkit-box-shadow .5s;transition:border-color .25s ease-in-out,-webkit-box-shadow .5s;transition:box-shadow .5s,border-color .25s ease-in-out;transition:box-shadow .5s,border-color .25s ease-in-out,-webkit-box-shadow .5s}@media screen and (min-width:0\0){select{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAYCAYAAACbU/80AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAIpJREFUeNrEkckNgDAMBBfRkEt0ObRBBdsGXUDgmQfK4XhH2m8czQAAy27R3tsw4Qfe2x8uOO6oYLb6GlOor3GF+swURAOmUJ+RwtEJs9WvTGEYxBXqI1MQAZhCfUQKRzDMVj+TwrAIV6jvSUEkYAr1LSkcyTBb/V+KYfX7xAeusq3sLDtGH3kEGACPWIflNZfhRQAAAABJRU5ErkJggg==)}}select:focus{background-color:#fefefe;border:1px solid #8a8a8a;-webkit-box-shadow:0 0 5px #cacaca;box-shadow:0 0 5px #cacaca;outline:0;-webkit-transition:border-color .25s ease-in-out,-webkit-box-shadow .5s;transition:border-color .25s ease-in-out,-webkit-box-shadow .5s;transition:box-shadow .5s,border-color .25s ease-in-out;transition:box-shadow .5s,border-color .25s ease-in-out,-webkit-box-shadow .5s}select:disabled{background-color:#e6e6e6;cursor:not-allowed}select::-ms-expand{display:none}select[multiple]{background-image:none;height:auto}select:not([multiple]){padding-bottom:0;padding-top:0}.is-invalid-input:not(:focus){background-color:#f9ecea;border-color:#cc4b37}.is-invalid-input:not(:focus)::-webkit-input-placeholder{color:#cc4b37}.is-invalid-input:not(:focus)::-moz-placeholder{color:#cc4b37}.is-invalid-input:not(:focus):-ms-input-placeholder{color:#cc4b37}.is-invalid-input:not(:focus)::-ms-input-placeholder{color:#cc4b37}.is-invalid-input:not(:focus)::placeholder{color:#cc4b37}.form-error,.is-invalid-label{color:#cc4b37}.form-error{display:none;font-size:.75rem;font-weight:700;margin-bottom:1rem;margin-top:-.5rem}.form-error.is-visible{display:block}blockquote,dd,div,dl,dt,form,h1,h2,h3,h4,h5,h6,li,ol,p,pre,td,th,ul{margin:0;padding:0}p{text-rendering:optimizeLegibility;font-size:inherit;line-height:1.6;margin-bottom:1rem}em,i{font-style:italic}b,em,i,strong{line-height:inherit}b,strong{font-weight:700}small{font-size:80%;line-height:inherit}.h1,.h2,.h3,.h4,.h5,.h6,h1,h2,h3,h4,h5,h6{text-rendering:optimizeLegibility;color:inherit;font-family:Helvetica Neue,Helvetica,Roboto,Arial,sans-serif;font-style:normal;font-weight:400}.h1 small,.h2 small,.h3 small,.h4 small,.h5 small,.h6 small,h1 small,h2 small,h3 small,h4 small,h5 small,h6 small{color:#cacaca;line-height:0}.h1,h1{font-size:1.5rem}.h1,.h2,h1,h2{line-height:1.4;margin-bottom:.5rem;margin-top:0}.h2,h2{font-size:1.25rem}.h3,h3{font-size:1.1875rem}.h3,.h4,h3,h4{line-height:1.4;margin-bottom:.5rem;margin-top:0}.h4,h4{font-size:1.125rem}.h5,h5{font-size:1.0625rem}.h5,.h6,h5,h6{line-height:1.4;margin-bottom:.5rem;margin-top:0}.h6,h6{font-size:1rem}@media print,screen and (min-width:40em){.h1,h1{font-size:3rem}.h2,h2{font-size:2.5rem}.h3,h3{font-size:1.9375rem}.h4,h4{font-size:1.5625rem}.h5,h5{font-size:1.25rem}.h6,h6{font-size:1rem}}a{color:#1779ba;cursor:pointer;line-height:inherit;text-decoration:none}a:focus,a:hover{color:#1468a0}a img,hr{border:0}hr{border-bottom:1px solid #cacaca;clear:both;height:0;margin:1.25rem auto;max-width:75rem}dl,ol,ul{line-height:1.6;list-style-position:outside;margin-bottom:1rem}li{font-size:inherit}ul{list-style-type:disc}ol,ul{margin-left:1.25rem}ol ol,ol ul,ul ol,ul ul{margin-bottom:0;margin-left:1.25rem}dl{margin-bottom:1rem}dl dt{font-weight:700;margin-bottom:.3rem}blockquote{border-left:1px solid #cacaca;margin:0 0 1rem;padding:.5625rem 1.25rem 0 1.1875rem}blockquote,blockquote p{color:#8a8a8a;line-height:1.6}abbr,abbr[title]{border-bottom:1px dotted #0a0a0a;cursor:help;text-decoration:none}figure,kbd{margin:0}kbd{background-color:#e6e6e6;color:#0a0a0a;font-family:Consolas,Liberation Mono,Courier,monospace;padding:.125rem .25rem 0}.subheader{color:#8a8a8a;font-weight:400;line-height:1.4;margin-bottom:.5rem;margin-top:.2rem}.lead{font-size:125%;line-height:1.6}.stat{font-size:2.5rem;line-height:1}p+.stat{margin-top:-1rem}ol.no-bullet,ul.no-bullet{list-style:none;margin-left:0}.cite-block,cite{color:#8a8a8a;display:block;font-size:.8125rem}.cite-block:before,cite:before{content:"— "}.code-inline,code{word-wrap:break-word;display:inline;max-width:100%;padding:.125rem .3125rem .0625rem}.code-block,.code-inline,code{background-color:#e6e6e6;border:1px solid #cacaca;color:#0a0a0a;font-family:Consolas,Liberation Mono,Courier,monospace;font-weight:400}.code-block{display:block;margin-bottom:1.5rem;overflow:auto;padding:1rem;white-space:pre}.text-left{text-align:left}.text-right{text-align:right}.text-center{text-align:center}.text-justify{text-align:justify}@media print,screen and (min-width:40em){.medium-text-left{text-align:left}.medium-text-right{text-align:right}.medium-text-center{text-align:center}.medium-text-justify{text-align:justify}}@media print,screen and (min-width:64em){.large-text-left{text-align:left}.large-text-right{text-align:right}.large-text-center{text-align:center}.large-text-justify{text-align:justify}}.show-for-print{display:none!important}@media print{*{-webkit-print-color-adjust:economy;background:0 0!important;-webkit-box-shadow:none!important;box-shadow:none!important;color:#000!important;color-adjust:economy;text-shadow:none!important}.show-for-print{display:block!important}.hide-for-print{display:none!important}table.show-for-print{display:table!important}thead.show-for-print{display:table-header-group!important}tbody.show-for-print{display:table-row-group!important}tr.show-for-print{display:table-row!important}td.show-for-print,th.show-for-print{display:table-cell!important}a,a:visited{text-decoration:underline}a[href]:after{content:" (" attr(href) ")"}.ir a:after,a[href^="#"]:after,a[href^="javascript:"]:after{content:""}abbr[title]:after{content:" (" attr(title) ")"}blockquote,pre{border:1px solid #8a8a8a;page-break-inside:avoid}thead{display:table-header-group}img,tr{page-break-inside:avoid}img{max-width:100%!important}@page{margin:.5cm}h2,h3,p{orphans:3;widows:3}h2,h3{page-break-after:avoid}.print-break-inside{page-break-inside:auto}}.grid-container{margin-left:auto;margin-right:auto;max-width:75rem;padding-left:.625rem;padding-right:.625rem}@media print,screen and (min-width:40em){.grid-container{padding-left:.9375rem;padding-right:.9375rem}}.grid-container.fluid{margin-left:auto;margin-right:auto;max-width:100%;padding-left:.625rem;padding-right:.625rem}@media print,screen and (min-width:40em){.grid-container.fluid{padding-left:.9375rem;padding-right:.9375rem}}.grid-container.full{margin-left:auto;margin-right:auto;max-width:100%;padding-left:0;padding-right:0}.grid-x{-webkit-box-orient:horizontal;-webkit-box-direction:normal;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-flow:row wrap;-ms-flex-flow:row wrap;flex-flow:row wrap}.cell{-webkit-box-flex:0;-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto;min-height:0;min-width:0;width:100%}.cell.auto{-webkit-box-flex:1;-webkit-flex:1 1 0;-ms-flex:1 1 0px;flex:1 1 0}.cell.shrink{-webkit-box-flex:0;-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto}.grid-x>.auto{width:auto}.grid-x>.shrink{width:auto}.grid-x>.small-1,.grid-x>.small-2,.grid-x>.small-3,.grid-x>.small-4,.grid-x>.small-5,.grid-x>.small-6,.grid-x>.small-7,.grid-x>.small-8,.grid-x>.small-9,.grid-x>.small-10,.grid-x>.small-11,.grid-x>.small-12,.grid-x>.small-full,.grid-x>.small-shrink{-ms-flex-preferred-size:auto;-webkit-flex-basis:auto;flex-basis:auto}@media print,screen and (min-width:40em){.grid-x>.medium-1,.grid-x>.medium-2,.grid-x>.medium-3,.grid-x>.medium-4,.grid-x>.medium-5,.grid-x>.medium-6,.grid-x>.medium-7,.grid-x>.medium-8,.grid-x>.medium-9,.grid-x>.medium-10,.grid-x>.medium-11,.grid-x>.medium-12,.grid-x>.medium-full,.grid-x>.medium-shrink{-ms-flex-preferred-size:auto;-webkit-flex-basis:auto;flex-basis:auto}}@media print,screen and (min-width:64em){.grid-x>.large-1,.grid-x>.large-2,.grid-x>.large-3,.grid-x>.large-4,.grid-x>.large-5,.grid-x>.large-6,.grid-x>.large-7,.grid-x>.large-8,.grid-x>.large-9,.grid-x>.large-10,.grid-x>.large-11,.grid-x>.large-12,.grid-x>.large-full,.grid-x>.large-shrink{-ms-flex-preferred-size:auto;-webkit-flex-basis:auto;flex-basis:auto}}.grid-x>.small-1,.grid-x>.small-2,.grid-x>.small-3,.grid-x>.small-4,.grid-x>.small-5,.grid-x>.small-6,.grid-x>.small-7,.grid-x>.small-8,.grid-x>.small-9,.grid-x>.small-10,.grid-x>.small-11,.grid-x>.small-12{-webkit-box-flex:0;-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto}.grid-x>.small-1{width:8.33333%}.grid-x>.small-2{width:16.66667%}.grid-x>.small-3{width:25%}.grid-x>.small-4{width:33.33333%}.grid-x>.small-5{width:41.66667%}.grid-x>.small-6{width:50%}.grid-x>.small-7{width:58.33333%}.grid-x>.small-8{width:66.66667%}.grid-x>.small-9{width:75%}.grid-x>.small-10{width:83.33333%}.grid-x>.small-11{width:91.66667%}.grid-x>.small-12{width:100%}@media print,screen and (min-width:40em){.grid-x>.medium-auto{-webkit-box-flex:1;-webkit-flex:1 1 0;-ms-flex:1 1 0px;flex:1 1 0;width:auto}.grid-x>.medium-1,.grid-x>.medium-2,.grid-x>.medium-3,.grid-x>.medium-4,.grid-x>.medium-5,.grid-x>.medium-6,.grid-x>.medium-7,.grid-x>.medium-8,.grid-x>.medium-9,.grid-x>.medium-10,.grid-x>.medium-11,.grid-x>.medium-12,.grid-x>.medium-shrink{-webkit-box-flex:0;-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto}.grid-x>.medium-shrink{width:auto}.grid-x>.medium-1{width:8.33333%}.grid-x>.medium-2{width:16.66667%}.grid-x>.medium-3{width:25%}.grid-x>.medium-4{width:33.33333%}.grid-x>.medium-5{width:41.66667%}.grid-x>.medium-6{width:50%}.grid-x>.medium-7{width:58.33333%}.grid-x>.medium-8{width:66.66667%}.grid-x>.medium-9{width:75%}.grid-x>.medium-10{width:83.33333%}.grid-x>.medium-11{width:91.66667%}.grid-x>.medium-12{width:100%}}@media print,screen and (min-width:64em){.grid-x>.large-auto{-webkit-box-flex:1;-webkit-flex:1 1 0;-ms-flex:1 1 0px;flex:1 1 0;width:auto}.grid-x>.large-1,.grid-x>.large-2,.grid-x>.large-3,.grid-x>.large-4,.grid-x>.large-5,.grid-x>.large-6,.grid-x>.large-7,.grid-x>.large-8,.grid-x>.large-9,.grid-x>.large-10,.grid-x>.large-11,.grid-x>.large-12,.grid-x>.large-shrink{-webkit-box-flex:0;-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto}.grid-x>.large-shrink{width:auto}.grid-x>.large-1{width:8.33333%}.grid-x>.large-2{width:16.66667%}.grid-x>.large-3{width:25%}.grid-x>.large-4{width:33.33333%}.grid-x>.large-5{width:41.66667%}.grid-x>.large-6{width:50%}.grid-x>.large-7{width:58.33333%}.grid-x>.large-8{width:66.66667%}.grid-x>.large-9{width:75%}.grid-x>.large-10{width:83.33333%}.grid-x>.large-11{width:91.66667%}.grid-x>.large-12{width:100%}}.grid-margin-x:not(.grid-x)>.cell{width:auto}.grid-margin-y:not(.grid-y)>.cell{height:auto}.grid-margin-x{margin-left:-.625rem;margin-right:-.625rem}@media print,screen and (min-width:40em){.grid-margin-x{margin-left:-.9375rem;margin-right:-.9375rem}}.grid-margin-x>.cell{margin-left:.625rem;margin-right:.625rem;width:calc(100% - 1.25rem)}@media print,screen and (min-width:40em){.grid-margin-x>.cell{margin-left:.9375rem;margin-right:.9375rem;width:calc(100% - 1.875rem)}}.grid-margin-x>.auto{width:auto}.grid-margin-x>.shrink{width:auto}.grid-margin-x>.small-1{width:calc(8.33333% - 1.25rem)}.grid-margin-x>.small-2{width:calc(16.66667% - 1.25rem)}.grid-margin-x>.small-3{width:calc(25% - 1.25rem)}.grid-margin-x>.small-4{width:calc(33.33333% - 1.25rem)}.grid-margin-x>.small-5{width:calc(41.66667% - 1.25rem)}.grid-margin-x>.small-6{width:calc(50% - 1.25rem)}.grid-margin-x>.small-7{width:calc(58.33333% - 1.25rem)}.grid-margin-x>.small-8{width:calc(66.66667% - 1.25rem)}.grid-margin-x>.small-9{width:calc(75% - 1.25rem)}.grid-margin-x>.small-10{width:calc(83.33333% - 1.25rem)}.grid-margin-x>.small-11{width:calc(91.66667% - 1.25rem)}.grid-margin-x>.small-12{width:calc(100% - 1.25rem)}@media print,screen and (min-width:40em){.grid-margin-x>.auto{width:auto}.grid-margin-x>.shrink{width:auto}.grid-margin-x>.small-1{width:calc(8.33333% - 1.875rem)}.grid-margin-x>.small-2{width:calc(16.66667% - 1.875rem)}.grid-margin-x>.small-3{width:calc(25% - 1.875rem)}.grid-margin-x>.small-4{width:calc(33.33333% - 1.875rem)}.grid-margin-x>.small-5{width:calc(41.66667% - 1.875rem)}.grid-margin-x>.small-6{width:calc(50% - 1.875rem)}.grid-margin-x>.small-7{width:calc(58.33333% - 1.875rem)}.grid-margin-x>.small-8{width:calc(66.66667% - 1.875rem)}.grid-margin-x>.small-9{width:calc(75% - 1.875rem)}.grid-margin-x>.small-10{width:calc(83.33333% - 1.875rem)}.grid-margin-x>.small-11{width:calc(91.66667% - 1.875rem)}.grid-margin-x>.small-12{width:calc(100% - 1.875rem)}.grid-margin-x>.medium-auto{width:auto}.grid-margin-x>.medium-shrink{width:auto}.grid-margin-x>.medium-1{width:calc(8.33333% - 1.875rem)}.grid-margin-x>.medium-2{width:calc(16.66667% - 1.875rem)}.grid-margin-x>.medium-3{width:calc(25% - 1.875rem)}.grid-margin-x>.medium-4{width:calc(33.33333% - 1.875rem)}.grid-margin-x>.medium-5{width:calc(41.66667% - 1.875rem)}.grid-margin-x>.medium-6{width:calc(50% - 1.875rem)}.grid-margin-x>.medium-7{width:calc(58.33333% - 1.875rem)}.grid-margin-x>.medium-8{width:calc(66.66667% - 1.875rem)}.grid-margin-x>.medium-9{width:calc(75% - 1.875rem)}.grid-margin-x>.medium-10{width:calc(83.33333% - 1.875rem)}.grid-margin-x>.medium-11{width:calc(91.66667% - 1.875rem)}.grid-margin-x>.medium-12{width:calc(100% - 1.875rem)}}@media print,screen and (min-width:64em){.grid-margin-x>.large-auto{width:auto}.grid-margin-x>.large-shrink{width:auto}.grid-margin-x>.large-1{width:calc(8.33333% - 1.875rem)}.grid-margin-x>.large-2{width:calc(16.66667% - 1.875rem)}.grid-margin-x>.large-3{width:calc(25% - 1.875rem)}.grid-margin-x>.large-4{width:calc(33.33333% - 1.875rem)}.grid-margin-x>.large-5{width:calc(41.66667% - 1.875rem)}.grid-margin-x>.large-6{width:calc(50% - 1.875rem)}.grid-margin-x>.large-7{width:calc(58.33333% - 1.875rem)}.grid-margin-x>.large-8{width:calc(66.66667% - 1.875rem)}.grid-margin-x>.large-9{width:calc(75% - 1.875rem)}.grid-margin-x>.large-10{width:calc(83.33333% - 1.875rem)}.grid-margin-x>.large-11{width:calc(91.66667% - 1.875rem)}.grid-margin-x>.large-12{width:calc(100% - 1.875rem)}}.grid-padding-x .grid-padding-x{margin-left:-.625rem;margin-right:-.625rem}@media print,screen and (min-width:40em){.grid-padding-x .grid-padding-x{margin-left:-.9375rem;margin-right:-.9375rem}}.grid-container:not(.full)>.grid-padding-x{margin-left:-.625rem;margin-right:-.625rem}@media print,screen and (min-width:40em){.grid-container:not(.full)>.grid-padding-x{margin-left:-.9375rem;margin-right:-.9375rem}}.grid-padding-x>.cell{padding-left:.625rem;padding-right:.625rem}@media print,screen and (min-width:40em){.grid-padding-x>.cell{padding-left:.9375rem;padding-right:.9375rem}}.small-up-1>.cell{width:100%}.small-up-2>.cell{width:50%}.small-up-3>.cell{width:33.33333%}.small-up-4>.cell{width:25%}.small-up-5>.cell{width:20%}.small-up-6>.cell{width:16.66667%}.small-up-7>.cell{width:14.28571%}.small-up-8>.cell{width:12.5%}@media print,screen and (min-width:40em){.medium-up-1>.cell{width:100%}.medium-up-2>.cell{width:50%}.medium-up-3>.cell{width:33.33333%}.medium-up-4>.cell{width:25%}.medium-up-5>.cell{width:20%}.medium-up-6>.cell{width:16.66667%}.medium-up-7>.cell{width:14.28571%}.medium-up-8>.cell{width:12.5%}}@media print,screen and (min-width:64em){.large-up-1>.cell{width:100%}.large-up-2>.cell{width:50%}.large-up-3>.cell{width:33.33333%}.large-up-4>.cell{width:25%}.large-up-5>.cell{width:20%}.large-up-6>.cell{width:16.66667%}.large-up-7>.cell{width:14.28571%}.large-up-8>.cell{width:12.5%}}.grid-margin-x.small-up-1>.cell{width:calc(100% - 1.25rem)}.grid-margin-x.small-up-2>.cell{width:calc(50% - 1.25rem)}.grid-margin-x.small-up-3>.cell{width:calc(33.33333% - 1.25rem)}.grid-margin-x.small-up-4>.cell{width:calc(25% - 1.25rem)}.grid-margin-x.small-up-5>.cell{width:calc(20% - 1.25rem)}.grid-margin-x.small-up-6>.cell{width:calc(16.66667% - 1.25rem)}.grid-margin-x.small-up-7>.cell{width:calc(14.28571% - 1.25rem)}.grid-margin-x.small-up-8>.cell{width:calc(12.5% - 1.25rem)}@media print,screen and (min-width:40em){.grid-margin-x.small-up-1>.cell{width:calc(100% - 1.875rem)}.grid-margin-x.small-up-2>.cell{width:calc(50% - 1.875rem)}.grid-margin-x.small-up-3>.cell{width:calc(33.33333% - 1.875rem)}.grid-margin-x.small-up-4>.cell{width:calc(25% - 1.875rem)}.grid-margin-x.small-up-5>.cell{width:calc(20% - 1.875rem)}.grid-margin-x.small-up-6>.cell{width:calc(16.66667% - 1.875rem)}.grid-margin-x.small-up-7>.cell{width:calc(14.28571% - 1.875rem)}.grid-margin-x.small-up-8>.cell{width:calc(12.5% - 1.875rem)}.grid-margin-x.medium-up-1>.cell{width:calc(100% - 1.875rem)}.grid-margin-x.medium-up-2>.cell{width:calc(50% - 1.875rem)}.grid-margin-x.medium-up-3>.cell{width:calc(33.33333% - 1.875rem)}.grid-margin-x.medium-up-4>.cell{width:calc(25% - 1.875rem)}.grid-margin-x.medium-up-5>.cell{width:calc(20% - 1.875rem)}.grid-margin-x.medium-up-6>.cell{width:calc(16.66667% - 1.875rem)}.grid-margin-x.medium-up-7>.cell{width:calc(14.28571% - 1.875rem)}.grid-margin-x.medium-up-8>.cell{width:calc(12.5% - 1.875rem)}}@media print,screen and (min-width:64em){.grid-margin-x.large-up-1>.cell{width:calc(100% - 1.875rem)}.grid-margin-x.large-up-2>.cell{width:calc(50% - 1.875rem)}.grid-margin-x.large-up-3>.cell{width:calc(33.33333% - 1.875rem)}.grid-margin-x.large-up-4>.cell{width:calc(25% - 1.875rem)}.grid-margin-x.large-up-5>.cell{width:calc(20% - 1.875rem)}.grid-margin-x.large-up-6>.cell{width:calc(16.66667% - 1.875rem)}.grid-margin-x.large-up-7>.cell{width:calc(14.28571% - 1.875rem)}.grid-margin-x.large-up-8>.cell{width:calc(12.5% - 1.875rem)}}.small-margin-collapse{margin-left:0;margin-right:0}.small-margin-collapse>.cell{margin-left:0;margin-right:0}.small-margin-collapse>.small-1{width:8.33333%}.small-margin-collapse>.small-2{width:16.66667%}.small-margin-collapse>.small-3{width:25%}.small-margin-collapse>.small-4{width:33.33333%}.small-margin-collapse>.small-5{width:41.66667%}.small-margin-collapse>.small-6{width:50%}.small-margin-collapse>.small-7{width:58.33333%}.small-margin-collapse>.small-8{width:66.66667%}.small-margin-collapse>.small-9{width:75%}.small-margin-collapse>.small-10{width:83.33333%}.small-margin-collapse>.small-11{width:91.66667%}.small-margin-collapse>.small-12{width:100%}@media print,screen and (min-width:40em){.small-margin-collapse>.medium-1{width:8.33333%}.small-margin-collapse>.medium-2{width:16.66667%}.small-margin-collapse>.medium-3{width:25%}.small-margin-collapse>.medium-4{width:33.33333%}.small-margin-collapse>.medium-5{width:41.66667%}.small-margin-collapse>.medium-6{width:50%}.small-margin-collapse>.medium-7{width:58.33333%}.small-margin-collapse>.medium-8{width:66.66667%}.small-margin-collapse>.medium-9{width:75%}.small-margin-collapse>.medium-10{width:83.33333%}.small-margin-collapse>.medium-11{width:91.66667%}.small-margin-collapse>.medium-12{width:100%}}@media print,screen and (min-width:64em){.small-margin-collapse>.large-1{width:8.33333%}.small-margin-collapse>.large-2{width:16.66667%}.small-margin-collapse>.large-3{width:25%}.small-margin-collapse>.large-4{width:33.33333%}.small-margin-collapse>.large-5{width:41.66667%}.small-margin-collapse>.large-6{width:50%}.small-margin-collapse>.large-7{width:58.33333%}.small-margin-collapse>.large-8{width:66.66667%}.small-margin-collapse>.large-9{width:75%}.small-margin-collapse>.large-10{width:83.33333%}.small-margin-collapse>.large-11{width:91.66667%}.small-margin-collapse>.large-12{width:100%}}.small-padding-collapse{margin-left:0;margin-right:0}.small-padding-collapse>.cell{padding-left:0;padding-right:0}@media print,screen and (min-width:40em){.medium-margin-collapse{margin-left:0;margin-right:0}.medium-margin-collapse>.cell{margin-left:0;margin-right:0}}@media print,screen and (min-width:40em){.medium-margin-collapse>.small-1{width:8.33333%}.medium-margin-collapse>.small-2{width:16.66667%}.medium-margin-collapse>.small-3{width:25%}.medium-margin-collapse>.small-4{width:33.33333%}.medium-margin-collapse>.small-5{width:41.66667%}.medium-margin-collapse>.small-6{width:50%}.medium-margin-collapse>.small-7{width:58.33333%}.medium-margin-collapse>.small-8{width:66.66667%}.medium-margin-collapse>.small-9{width:75%}.medium-margin-collapse>.small-10{width:83.33333%}.medium-margin-collapse>.small-11{width:91.66667%}.medium-margin-collapse>.small-12{width:100%}}@media print,screen and (min-width:40em){.medium-margin-collapse>.medium-1{width:8.33333%}.medium-margin-collapse>.medium-2{width:16.66667%}.medium-margin-collapse>.medium-3{width:25%}.medium-margin-collapse>.medium-4{width:33.33333%}.medium-margin-collapse>.medium-5{width:41.66667%}.medium-margin-collapse>.medium-6{width:50%}.medium-margin-collapse>.medium-7{width:58.33333%}.medium-margin-collapse>.medium-8{width:66.66667%}.medium-margin-collapse>.medium-9{width:75%}.medium-margin-collapse>.medium-10{width:83.33333%}.medium-margin-collapse>.medium-11{width:91.66667%}.medium-margin-collapse>.medium-12{width:100%}}@media print,screen and (min-width:64em){.medium-margin-collapse>.large-1{width:8.33333%}.medium-margin-collapse>.large-2{width:16.66667%}.medium-margin-collapse>.large-3{width:25%}.medium-margin-collapse>.large-4{width:33.33333%}.medium-margin-collapse>.large-5{width:41.66667%}.medium-margin-collapse>.large-6{width:50%}.medium-margin-collapse>.large-7{width:58.33333%}.medium-margin-collapse>.large-8{width:66.66667%}.medium-margin-collapse>.large-9{width:75%}.medium-margin-collapse>.large-10{width:83.33333%}.medium-margin-collapse>.large-11{width:91.66667%}.medium-margin-collapse>.large-12{width:100%}}@media print,screen and (min-width:40em){.medium-padding-collapse{margin-left:0;margin-right:0}.medium-padding-collapse>.cell{padding-left:0;padding-right:0}}@media print,screen and (min-width:64em){.large-margin-collapse{margin-left:0;margin-right:0}.large-margin-collapse>.cell{margin-left:0;margin-right:0}}@media print,screen and (min-width:64em){.large-margin-collapse>.small-1{width:8.33333%}.large-margin-collapse>.small-2{width:16.66667%}.large-margin-collapse>.small-3{width:25%}.large-margin-collapse>.small-4{width:33.33333%}.large-margin-collapse>.small-5{width:41.66667%}.large-margin-collapse>.small-6{width:50%}.large-margin-collapse>.small-7{width:58.33333%}.large-margin-collapse>.small-8{width:66.66667%}.large-margin-collapse>.small-9{width:75%}.large-margin-collapse>.small-10{width:83.33333%}.large-margin-collapse>.small-11{width:91.66667%}.large-margin-collapse>.small-12{width:100%}}@media print,screen and (min-width:64em){.large-margin-collapse>.medium-1{width:8.33333%}.large-margin-collapse>.medium-2{width:16.66667%}.large-margin-collapse>.medium-3{width:25%}.large-margin-collapse>.medium-4{width:33.33333%}.large-margin-collapse>.medium-5{width:41.66667%}.large-margin-collapse>.medium-6{width:50%}.large-margin-collapse>.medium-7{width:58.33333%}.large-margin-collapse>.medium-8{width:66.66667%}.large-margin-collapse>.medium-9{width:75%}.large-margin-collapse>.medium-10{width:83.33333%}.large-margin-collapse>.medium-11{width:91.66667%}.large-margin-collapse>.medium-12{width:100%}}@media print,screen and (min-width:64em){.large-margin-collapse>.large-1{width:8.33333%}.large-margin-collapse>.large-2{width:16.66667%}.large-margin-collapse>.large-3{width:25%}.large-margin-collapse>.large-4{width:33.33333%}.large-margin-collapse>.large-5{width:41.66667%}.large-margin-collapse>.large-6{width:50%}.large-margin-collapse>.large-7{width:58.33333%}.large-margin-collapse>.large-8{width:66.66667%}.large-margin-collapse>.large-9{width:75%}.large-margin-collapse>.large-10{width:83.33333%}.large-margin-collapse>.large-11{width:91.66667%}.large-margin-collapse>.large-12{width:100%}}@media print,screen and (min-width:64em){.large-padding-collapse{margin-left:0;margin-right:0}.large-padding-collapse>.cell{padding-left:0;padding-right:0}}.small-offset-0{margin-left:0}.grid-margin-x>.small-offset-0{margin-left:.625rem}.small-offset-1{margin-left:8.33333%}.grid-margin-x>.small-offset-1{margin-left:calc(8.33333% + .625rem)}.small-offset-2{margin-left:16.66667%}.grid-margin-x>.small-offset-2{margin-left:calc(16.66667% + .625rem)}.small-offset-3{margin-left:25%}.grid-margin-x>.small-offset-3{margin-left:calc(25% + .625rem)}.small-offset-4{margin-left:33.33333%}.grid-margin-x>.small-offset-4{margin-left:calc(33.33333% + .625rem)}.small-offset-5{margin-left:41.66667%}.grid-margin-x>.small-offset-5{margin-left:calc(41.66667% + .625rem)}.small-offset-6{margin-left:50%}.grid-margin-x>.small-offset-6{margin-left:calc(50% + .625rem)}.small-offset-7{margin-left:58.33333%}.grid-margin-x>.small-offset-7{margin-left:calc(58.33333% + .625rem)}.small-offset-8{margin-left:66.66667%}.grid-margin-x>.small-offset-8{margin-left:calc(66.66667% + .625rem)}.small-offset-9{margin-left:75%}.grid-margin-x>.small-offset-9{margin-left:calc(75% + .625rem)}.small-offset-10{margin-left:83.33333%}.grid-margin-x>.small-offset-10{margin-left:calc(83.33333% + .625rem)}.small-offset-11{margin-left:91.66667%}.grid-margin-x>.small-offset-11{margin-left:calc(91.66667% + .625rem)}@media print,screen and (min-width:40em){.medium-offset-0{margin-left:0}.grid-margin-x>.medium-offset-0{margin-left:.9375rem}.medium-offset-1{margin-left:8.33333%}.grid-margin-x>.medium-offset-1{margin-left:calc(8.33333% + .9375rem)}.medium-offset-2{margin-left:16.66667%}.grid-margin-x>.medium-offset-2{margin-left:calc(16.66667% + .9375rem)}.medium-offset-3{margin-left:25%}.grid-margin-x>.medium-offset-3{margin-left:calc(25% + .9375rem)}.medium-offset-4{margin-left:33.33333%}.grid-margin-x>.medium-offset-4{margin-left:calc(33.33333% + .9375rem)}.medium-offset-5{margin-left:41.66667%}.grid-margin-x>.medium-offset-5{margin-left:calc(41.66667% + .9375rem)}.medium-offset-6{margin-left:50%}.grid-margin-x>.medium-offset-6{margin-left:calc(50% + .9375rem)}.medium-offset-7{margin-left:58.33333%}.grid-margin-x>.medium-offset-7{margin-left:calc(58.33333% + .9375rem)}.medium-offset-8{margin-left:66.66667%}.grid-margin-x>.medium-offset-8{margin-left:calc(66.66667% + .9375rem)}.medium-offset-9{margin-left:75%}.grid-margin-x>.medium-offset-9{margin-left:calc(75% + .9375rem)}.medium-offset-10{margin-left:83.33333%}.grid-margin-x>.medium-offset-10{margin-left:calc(83.33333% + .9375rem)}.medium-offset-11{margin-left:91.66667%}.grid-margin-x>.medium-offset-11{margin-left:calc(91.66667% + .9375rem)}}@media print,screen and (min-width:64em){.large-offset-0{margin-left:0}.grid-margin-x>.large-offset-0{margin-left:.9375rem}.large-offset-1{margin-left:8.33333%}.grid-margin-x>.large-offset-1{margin-left:calc(8.33333% + .9375rem)}.large-offset-2{margin-left:16.66667%}.grid-margin-x>.large-offset-2{margin-left:calc(16.66667% + .9375rem)}.large-offset-3{margin-left:25%}.grid-margin-x>.large-offset-3{margin-left:calc(25% + .9375rem)}.large-offset-4{margin-left:33.33333%}.grid-margin-x>.large-offset-4{margin-left:calc(33.33333% + .9375rem)}.large-offset-5{margin-left:41.66667%}.grid-margin-x>.large-offset-5{margin-left:calc(41.66667% + .9375rem)}.large-offset-6{margin-left:50%}.grid-margin-x>.large-offset-6{margin-left:calc(50% + .9375rem)}.large-offset-7{margin-left:58.33333%}.grid-margin-x>.large-offset-7{margin-left:calc(58.33333% + .9375rem)}.large-offset-8{margin-left:66.66667%}.grid-margin-x>.large-offset-8{margin-left:calc(66.66667% + .9375rem)}.large-offset-9{margin-left:75%}.grid-margin-x>.large-offset-9{margin-left:calc(75% + .9375rem)}.large-offset-10{margin-left:83.33333%}.grid-margin-x>.large-offset-10{margin-left:calc(83.33333% + .9375rem)}.large-offset-11{margin-left:91.66667%}.grid-margin-x>.large-offset-11{margin-left:calc(91.66667% + .9375rem)}}.grid-y{-webkit-box-orient:vertical;-webkit-box-direction:normal;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-flow:column nowrap;-ms-flex-flow:column nowrap;flex-flow:column nowrap}.grid-y>.cell{height:auto;max-height:none}.grid-y>.auto{height:auto}.grid-y>.shrink{height:auto}.grid-y>.small-1,.grid-y>.small-2,.grid-y>.small-3,.grid-y>.small-4,.grid-y>.small-5,.grid-y>.small-6,.grid-y>.small-7,.grid-y>.small-8,.grid-y>.small-9,.grid-y>.small-10,.grid-y>.small-11,.grid-y>.small-12,.grid-y>.small-full,.grid-y>.small-shrink{-ms-flex-preferred-size:auto;-webkit-flex-basis:auto;flex-basis:auto}@media print,screen and (min-width:40em){.grid-y>.medium-1,.grid-y>.medium-2,.grid-y>.medium-3,.grid-y>.medium-4,.grid-y>.medium-5,.grid-y>.medium-6,.grid-y>.medium-7,.grid-y>.medium-8,.grid-y>.medium-9,.grid-y>.medium-10,.grid-y>.medium-11,.grid-y>.medium-12,.grid-y>.medium-full,.grid-y>.medium-shrink{-ms-flex-preferred-size:auto;-webkit-flex-basis:auto;flex-basis:auto}}@media print,screen and (min-width:64em){.grid-y>.large-1,.grid-y>.large-2,.grid-y>.large-3,.grid-y>.large-4,.grid-y>.large-5,.grid-y>.large-6,.grid-y>.large-7,.grid-y>.large-8,.grid-y>.large-9,.grid-y>.large-10,.grid-y>.large-11,.grid-y>.large-12,.grid-y>.large-full,.grid-y>.large-shrink{-ms-flex-preferred-size:auto;-webkit-flex-basis:auto;flex-basis:auto}}.grid-y>.small-1,.grid-y>.small-2,.grid-y>.small-3,.grid-y>.small-4,.grid-y>.small-5,.grid-y>.small-6,.grid-y>.small-7,.grid-y>.small-8,.grid-y>.small-9,.grid-y>.small-10,.grid-y>.small-11,.grid-y>.small-12{-webkit-box-flex:0;-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto}.grid-y>.small-1{height:8.33333%}.grid-y>.small-2{height:16.66667%}.grid-y>.small-3{height:25%}.grid-y>.small-4{height:33.33333%}.grid-y>.small-5{height:41.66667%}.grid-y>.small-6{height:50%}.grid-y>.small-7{height:58.33333%}.grid-y>.small-8{height:66.66667%}.grid-y>.small-9{height:75%}.grid-y>.small-10{height:83.33333%}.grid-y>.small-11{height:91.66667%}.grid-y>.small-12{height:100%}@media print,screen and (min-width:40em){.grid-y>.medium-auto{-webkit-box-flex:1;-webkit-flex:1 1 0;-ms-flex:1 1 0px;flex:1 1 0;height:auto}.grid-y>.medium-1,.grid-y>.medium-2,.grid-y>.medium-3,.grid-y>.medium-4,.grid-y>.medium-5,.grid-y>.medium-6,.grid-y>.medium-7,.grid-y>.medium-8,.grid-y>.medium-9,.grid-y>.medium-10,.grid-y>.medium-11,.grid-y>.medium-12,.grid-y>.medium-shrink{-webkit-box-flex:0;-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto}.grid-y>.medium-shrink{height:auto}.grid-y>.medium-1{height:8.33333%}.grid-y>.medium-2{height:16.66667%}.grid-y>.medium-3{height:25%}.grid-y>.medium-4{height:33.33333%}.grid-y>.medium-5{height:41.66667%}.grid-y>.medium-6{height:50%}.grid-y>.medium-7{height:58.33333%}.grid-y>.medium-8{height:66.66667%}.grid-y>.medium-9{height:75%}.grid-y>.medium-10{height:83.33333%}.grid-y>.medium-11{height:91.66667%}.grid-y>.medium-12{height:100%}}@media print,screen and (min-width:64em){.grid-y>.large-auto{-webkit-box-flex:1;-webkit-flex:1 1 0;-ms-flex:1 1 0px;flex:1 1 0;height:auto}.grid-y>.large-1,.grid-y>.large-2,.grid-y>.large-3,.grid-y>.large-4,.grid-y>.large-5,.grid-y>.large-6,.grid-y>.large-7,.grid-y>.large-8,.grid-y>.large-9,.grid-y>.large-10,.grid-y>.large-11,.grid-y>.large-12,.grid-y>.large-shrink{-webkit-box-flex:0;-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto}.grid-y>.large-shrink{height:auto}.grid-y>.large-1{height:8.33333%}.grid-y>.large-2{height:16.66667%}.grid-y>.large-3{height:25%}.grid-y>.large-4{height:33.33333%}.grid-y>.large-5{height:41.66667%}.grid-y>.large-6{height:50%}.grid-y>.large-7{height:58.33333%}.grid-y>.large-8{height:66.66667%}.grid-y>.large-9{height:75%}.grid-y>.large-10{height:83.33333%}.grid-y>.large-11{height:91.66667%}.grid-y>.large-12{height:100%}}.grid-padding-y .grid-padding-y{margin-bottom:-.625rem;margin-top:-.625rem}@media print,screen and (min-width:40em){.grid-padding-y .grid-padding-y{margin-bottom:-.9375rem;margin-top:-.9375rem}}.grid-padding-y>.cell{padding-bottom:.625rem;padding-top:.625rem}@media print,screen and (min-width:40em){.grid-padding-y>.cell{padding-bottom:.9375rem;padding-top:.9375rem}}.grid-frame{-webkit-box-align:stretch;-ms-flex-align:stretch;-webkit-align-items:stretch;align-items:stretch;-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap;overflow:hidden;position:relative;width:100vw}.cell .grid-frame{width:100%}.cell-block{max-width:100%;overflow-x:auto}.cell-block,.cell-block-y{-webkit-overflow-scrolling:touch;-ms-overflow-style:-ms-autohiding-scrollbar}.cell-block-y{max-height:100%;min-height:100%;overflow-y:auto}.cell-block-container{-webkit-box-orient:vertical;-webkit-box-direction:normal;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;max-height:100%}.cell-block-container>.grid-x{-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap;max-height:100%}@media print,screen and (min-width:40em){.medium-grid-frame{-webkit-box-align:stretch;-ms-flex-align:stretch;-webkit-align-items:stretch;align-items:stretch;-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap;overflow:hidden;position:relative;width:100vw}.cell .medium-grid-frame{width:100%}.medium-cell-block{-webkit-overflow-scrolling:touch;-ms-overflow-style:-ms-autohiding-scrollbar;max-width:100%;overflow-x:auto}.medium-cell-block-container{-webkit-box-orient:vertical;-webkit-box-direction:normal;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;max-height:100%}.medium-cell-block-container>.grid-x{-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap;max-height:100%}.medium-cell-block-y{-webkit-overflow-scrolling:touch;-ms-overflow-style:-ms-autohiding-scrollbar;max-height:100%;min-height:100%;overflow-y:auto}}@media print,screen and (min-width:64em){.large-grid-frame{-webkit-box-align:stretch;-ms-flex-align:stretch;-webkit-align-items:stretch;align-items:stretch;-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap;overflow:hidden;position:relative;width:100vw}.cell .large-grid-frame{width:100%}.large-cell-block{-webkit-overflow-scrolling:touch;-ms-overflow-style:-ms-autohiding-scrollbar;max-width:100%;overflow-x:auto}.large-cell-block-container{-webkit-box-orient:vertical;-webkit-box-direction:normal;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;max-height:100%}.large-cell-block-container>.grid-x{-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap;max-height:100%}.large-cell-block-y{-webkit-overflow-scrolling:touch;-ms-overflow-style:-ms-autohiding-scrollbar;max-height:100%;min-height:100%;overflow-y:auto}}.grid-y.grid-frame{-webkit-box-align:stretch;-ms-flex-align:stretch;-webkit-align-items:stretch;align-items:stretch;-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap;height:100vh;overflow:hidden;position:relative;width:auto}@media print,screen and (min-width:40em){.grid-y.medium-grid-frame{-webkit-box-align:stretch;-ms-flex-align:stretch;-webkit-align-items:stretch;align-items:stretch;-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap;height:100vh;overflow:hidden;position:relative;width:auto}}@media print,screen and (min-width:64em){.grid-y.large-grid-frame{-webkit-box-align:stretch;-ms-flex-align:stretch;-webkit-align-items:stretch;align-items:stretch;-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap;height:100vh;overflow:hidden;position:relative;width:auto}}.cell .grid-y.grid-frame{height:100%}@media print,screen and (min-width:40em){.cell .grid-y.medium-grid-frame{height:100%}}@media print,screen and (min-width:64em){.cell .grid-y.large-grid-frame{height:100%}}.grid-margin-y{margin-bottom:-.625rem;margin-top:-.625rem}@media print,screen and (min-width:40em){.grid-margin-y{margin-bottom:-.9375rem;margin-top:-.9375rem}}.grid-margin-y>.cell{height:calc(100% - 1.25rem);margin-bottom:.625rem;margin-top:.625rem}@media print,screen and (min-width:40em){.grid-margin-y>.cell{height:calc(100% - 1.875rem);margin-bottom:.9375rem;margin-top:.9375rem}}.grid-margin-y>.auto{height:auto}.grid-margin-y>.shrink{height:auto}.grid-margin-y>.small-1{height:calc(8.33333% - 1.25rem)}.grid-margin-y>.small-2{height:calc(16.66667% - 1.25rem)}.grid-margin-y>.small-3{height:calc(25% - 1.25rem)}.grid-margin-y>.small-4{height:calc(33.33333% - 1.25rem)}.grid-margin-y>.small-5{height:calc(41.66667% - 1.25rem)}.grid-margin-y>.small-6{height:calc(50% - 1.25rem)}.grid-margin-y>.small-7{height:calc(58.33333% - 1.25rem)}.grid-margin-y>.small-8{height:calc(66.66667% - 1.25rem)}.grid-margin-y>.small-9{height:calc(75% - 1.25rem)}.grid-margin-y>.small-10{height:calc(83.33333% - 1.25rem)}.grid-margin-y>.small-11{height:calc(91.66667% - 1.25rem)}.grid-margin-y>.small-12{height:calc(100% - 1.25rem)}@media print,screen and (min-width:40em){.grid-margin-y>.auto{height:auto}.grid-margin-y>.shrink{height:auto}.grid-margin-y>.small-1{height:calc(8.33333% - 1.875rem)}.grid-margin-y>.small-2{height:calc(16.66667% - 1.875rem)}.grid-margin-y>.small-3{height:calc(25% - 1.875rem)}.grid-margin-y>.small-4{height:calc(33.33333% - 1.875rem)}.grid-margin-y>.small-5{height:calc(41.66667% - 1.875rem)}.grid-margin-y>.small-6{height:calc(50% - 1.875rem)}.grid-margin-y>.small-7{height:calc(58.33333% - 1.875rem)}.grid-margin-y>.small-8{height:calc(66.66667% - 1.875rem)}.grid-margin-y>.small-9{height:calc(75% - 1.875rem)}.grid-margin-y>.small-10{height:calc(83.33333% - 1.875rem)}.grid-margin-y>.small-11{height:calc(91.66667% - 1.875rem)}.grid-margin-y>.small-12{height:calc(100% - 1.875rem)}.grid-margin-y>.medium-auto{height:auto}.grid-margin-y>.medium-shrink{height:auto}.grid-margin-y>.medium-1{height:calc(8.33333% - 1.875rem)}.grid-margin-y>.medium-2{height:calc(16.66667% - 1.875rem)}.grid-margin-y>.medium-3{height:calc(25% - 1.875rem)}.grid-margin-y>.medium-4{height:calc(33.33333% - 1.875rem)}.grid-margin-y>.medium-5{height:calc(41.66667% - 1.875rem)}.grid-margin-y>.medium-6{height:calc(50% - 1.875rem)}.grid-margin-y>.medium-7{height:calc(58.33333% - 1.875rem)}.grid-margin-y>.medium-8{height:calc(66.66667% - 1.875rem)}.grid-margin-y>.medium-9{height:calc(75% - 1.875rem)}.grid-margin-y>.medium-10{height:calc(83.33333% - 1.875rem)}.grid-margin-y>.medium-11{height:calc(91.66667% - 1.875rem)}.grid-margin-y>.medium-12{height:calc(100% - 1.875rem)}}@media print,screen and (min-width:64em){.grid-margin-y>.large-auto{height:auto}.grid-margin-y>.large-shrink{height:auto}.grid-margin-y>.large-1{height:calc(8.33333% - 1.875rem)}.grid-margin-y>.large-2{height:calc(16.66667% - 1.875rem)}.grid-margin-y>.large-3{height:calc(25% - 1.875rem)}.grid-margin-y>.large-4{height:calc(33.33333% - 1.875rem)}.grid-margin-y>.large-5{height:calc(41.66667% - 1.875rem)}.grid-margin-y>.large-6{height:calc(50% - 1.875rem)}.grid-margin-y>.large-7{height:calc(58.33333% - 1.875rem)}.grid-margin-y>.large-8{height:calc(66.66667% - 1.875rem)}.grid-margin-y>.large-9{height:calc(75% - 1.875rem)}.grid-margin-y>.large-10{height:calc(83.33333% - 1.875rem)}.grid-margin-y>.large-11{height:calc(91.66667% - 1.875rem)}.grid-margin-y>.large-12{height:calc(100% - 1.875rem)}}.grid-frame.grid-margin-y{height:calc(100vh + 1.25rem)}@media print,screen and (min-width:40em){.grid-frame.grid-margin-y{height:calc(100vh + 1.875rem)}}@media print,screen and (min-width:64em){.grid-frame.grid-margin-y{height:calc(100vh + 1.875rem)}}@media print,screen and (min-width:40em){.grid-margin-y.medium-grid-frame{height:calc(100vh + 1.875rem)}}@media print,screen and (min-width:64em){.grid-margin-y.large-grid-frame{height:calc(100vh + 1.875rem)}}.button{-webkit-appearance:none;border:1px solid transparent;border-radius:0;cursor:pointer;display:inline-block;font-family:inherit;font-size:.9rem;line-height:1;margin:0 0 1rem;padding:.85em 1em;text-align:center;-webkit-transition:background-color .25s ease-out,color .25s ease-out;transition:background-color .25s ease-out,color .25s ease-out;vertical-align:middle}[data-whatinput=mouse] .button{outline:0}.button.tiny{font-size:.6rem}.button.small{font-size:.75rem}.button.large{font-size:1.25rem}.button.expanded{display:block;margin-left:0;margin-right:0;width:100%}.button,.button.disabled,.button.disabled:focus,.button.disabled:hover,.button[disabled],.button[disabled]:focus,.button[disabled]:hover{background-color:#1779ba;color:#fefefe}.button:focus,.button:hover{background-color:#14679e;color:#fefefe}.button.primary,.button.primary.disabled,.button.primary.disabled:focus,.button.primary.disabled:hover,.button.primary[disabled],.button.primary[disabled]:focus,.button.primary[disabled]:hover{background-color:#1779ba;color:#fefefe}.button.primary:focus,.button.primary:hover{background-color:#126195;color:#fefefe}.button.secondary,.button.secondary.disabled,.button.secondary.disabled:focus,.button.secondary.disabled:hover,.button.secondary[disabled],.button.secondary[disabled]:focus,.button.secondary[disabled]:hover{background-color:#767676;color:#fefefe}.button.secondary:focus,.button.secondary:hover{background-color:#5e5e5e;color:#fefefe}.button.success,.button.success.disabled,.button.success.disabled:focus,.button.success.disabled:hover,.button.success[disabled],.button.success[disabled]:focus,.button.success[disabled]:hover{background-color:#3adb76;color:#0a0a0a}.button.success:focus,.button.success:hover{background-color:#22bb5b;color:#0a0a0a}.button.warning,.button.warning.disabled,.button.warning.disabled:focus,.button.warning.disabled:hover,.button.warning[disabled],.button.warning[disabled]:focus,.button.warning[disabled]:hover{background-color:#ffae00;color:#0a0a0a}.button.warning:focus,.button.warning:hover{background-color:#cc8b00;color:#0a0a0a}.button.alert,.button.alert.disabled,.button.alert.disabled:focus,.button.alert.disabled:hover,.button.alert[disabled],.button.alert[disabled]:focus,.button.alert[disabled]:hover{background-color:#cc4b37;color:#fefefe}.button.alert:focus,.button.alert:hover{background-color:#a53b2a;color:#fefefe}.button.hollow,.button.hollow.disabled,.button.hollow.disabled:focus,.button.hollow.disabled:hover,.button.hollow:focus,.button.hollow:hover,.button.hollow[disabled],.button.hollow[disabled]:focus,.button.hollow[disabled]:hover{background-color:transparent}.button.hollow,.button.hollow.disabled,.button.hollow.disabled:focus,.button.hollow.disabled:hover,.button.hollow[disabled],.button.hollow[disabled]:focus,.button.hollow[disabled]:hover{border:1px solid #1779ba;color:#1779ba}.button.hollow:focus,.button.hollow:hover{border-color:#0c3d5d;color:#0c3d5d}.button.hollow.primary,.button.hollow.primary.disabled,.button.hollow.primary.disabled:focus,.button.hollow.primary.disabled:hover,.button.hollow.primary[disabled],.button.hollow.primary[disabled]:focus,.button.hollow.primary[disabled]:hover{border:1px solid #1779ba;color:#1779ba}.button.hollow.primary:focus,.button.hollow.primary:hover{border-color:#0c3d5d;color:#0c3d5d}.button.hollow.secondary,.button.hollow.secondary.disabled,.button.hollow.secondary.disabled:focus,.button.hollow.secondary.disabled:hover,.button.hollow.secondary[disabled],.button.hollow.secondary[disabled]:focus,.button.hollow.secondary[disabled]:hover{border:1px solid #767676;color:#767676}.button.hollow.secondary:focus,.button.hollow.secondary:hover{border-color:#3b3b3b;color:#3b3b3b}.button.hollow.success,.button.hollow.success.disabled,.button.hollow.success.disabled:focus,.button.hollow.success.disabled:hover,.button.hollow.success[disabled],.button.hollow.success[disabled]:focus,.button.hollow.success[disabled]:hover{border:1px solid #3adb76;color:#3adb76}.button.hollow.success:focus,.button.hollow.success:hover{border-color:#157539;color:#157539}.button.hollow.warning,.button.hollow.warning.disabled,.button.hollow.warning.disabled:focus,.button.hollow.warning.disabled:hover,.button.hollow.warning[disabled],.button.hollow.warning[disabled]:focus,.button.hollow.warning[disabled]:hover{border:1px solid #ffae00;color:#ffae00}.button.hollow.warning:focus,.button.hollow.warning:hover{border-color:#805700;color:#805700}.button.hollow.alert,.button.hollow.alert.disabled,.button.hollow.alert.disabled:focus,.button.hollow.alert.disabled:hover,.button.hollow.alert[disabled],.button.hollow.alert[disabled]:focus,.button.hollow.alert[disabled]:hover{border:1px solid #cc4b37;color:#cc4b37}.button.hollow.alert:focus,.button.hollow.alert:hover{border-color:#67251a;color:#67251a}.button.clear,.button.clear.disabled,.button.clear.disabled:focus,.button.clear.disabled:hover,.button.clear:focus,.button.clear:hover,.button.clear[disabled],.button.clear[disabled]:focus,.button.clear[disabled]:hover{background-color:transparent;border-color:transparent}.button.clear,.button.clear.disabled,.button.clear.disabled:focus,.button.clear.disabled:hover,.button.clear[disabled],.button.clear[disabled]:focus,.button.clear[disabled]:hover{color:#1779ba}.button.clear:focus,.button.clear:hover{color:#0c3d5d}.button.clear.primary,.button.clear.primary.disabled,.button.clear.primary.disabled:focus,.button.clear.primary.disabled:hover,.button.clear.primary[disabled],.button.clear.primary[disabled]:focus,.button.clear.primary[disabled]:hover{color:#1779ba}.button.clear.primary:focus,.button.clear.primary:hover{color:#0c3d5d}.button.clear.secondary,.button.clear.secondary.disabled,.button.clear.secondary.disabled:focus,.button.clear.secondary.disabled:hover,.button.clear.secondary[disabled],.button.clear.secondary[disabled]:focus,.button.clear.secondary[disabled]:hover{color:#767676}.button.clear.secondary:focus,.button.clear.secondary:hover{color:#3b3b3b}.button.clear.success,.button.clear.success.disabled,.button.clear.success.disabled:focus,.button.clear.success.disabled:hover,.button.clear.success[disabled],.button.clear.success[disabled]:focus,.button.clear.success[disabled]:hover{color:#3adb76}.button.clear.success:focus,.button.clear.success:hover{color:#157539}.button.clear.warning,.button.clear.warning.disabled,.button.clear.warning.disabled:focus,.button.clear.warning.disabled:hover,.button.clear.warning[disabled],.button.clear.warning[disabled]:focus,.button.clear.warning[disabled]:hover{color:#ffae00}.button.clear.warning:focus,.button.clear.warning:hover{color:#805700}.button.clear.alert,.button.clear.alert.disabled,.button.clear.alert.disabled:focus,.button.clear.alert.disabled:hover,.button.clear.alert[disabled],.button.clear.alert[disabled]:focus,.button.clear.alert[disabled]:hover{color:#cc4b37}.button.clear.alert:focus,.button.clear.alert:hover{color:#67251a}.button.disabled,.button[disabled]{cursor:not-allowed;opacity:.25}.button.dropdown:after{border-color:#fefefe transparent transparent;border-style:solid;border-width:.4em .4em 0;content:"";display:block;display:inline-block;float:right;height:0;margin-left:1em;position:relative;top:.4em;width:0}.button.dropdown.clear:after,.button.dropdown.hollow:after{border-top-color:#1779ba}.button.dropdown.clear.primary:after,.button.dropdown.hollow.primary:after{border-top-color:#1779ba}.button.dropdown.clear.secondary:after,.button.dropdown.hollow.secondary:after{border-top-color:#767676}.button.dropdown.clear.success:after,.button.dropdown.hollow.success:after{border-top-color:#3adb76}.button.dropdown.clear.warning:after,.button.dropdown.hollow.warning:after{border-top-color:#ffae00}.button.dropdown.clear.alert:after,.button.dropdown.hollow.alert:after{border-top-color:#cc4b37}.button.arrow-only:after{float:none;margin-left:0;top:-.1em}a.button:focus,a.button:hover{text-decoration:none}.button-group{-webkit-box-align:stretch;-ms-flex-align:stretch;-webkit-box-flex:1;-ms-flex-positive:1;-webkit-align-items:stretch;align-items:stretch;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-grow:1;flex-grow:1;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;margin-bottom:1rem}.button-group:after,.button-group:before{-ms-flex-preferred-size:0;-webkit-box-ordinal-group:2;-ms-flex-order:1;content:" ";display:table;-webkit-flex-basis:0;flex-basis:0;-webkit-order:1;order:1}.button-group:after{clear:both}.button-group:after,.button-group:before{display:none}.button-group .button{-webkit-box-flex:0;-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto;font-size:.9rem;margin:0 1px 1px 0}.button-group .button:last-child{margin-right:0}.button-group.tiny .button{font-size:.6rem}.button-group.small .button{font-size:.75rem}.button-group.large .button{font-size:1.25rem}.button-group.expanded .button{-webkit-box-flex:1;-webkit-flex:1 1 0px;-ms-flex:1 1 0px;flex:1 1 0px}.button-group.primary .button,.button-group.primary .button.disabled,.button-group.primary .button.disabled:focus,.button-group.primary .button.disabled:hover,.button-group.primary .button[disabled],.button-group.primary .button[disabled]:focus,.button-group.primary .button[disabled]:hover{background-color:#1779ba;color:#fefefe}.button-group.primary .button:focus,.button-group.primary .button:hover{background-color:#126195;color:#fefefe}.button-group.secondary .button,.button-group.secondary .button.disabled,.button-group.secondary .button.disabled:focus,.button-group.secondary .button.disabled:hover,.button-group.secondary .button[disabled],.button-group.secondary .button[disabled]:focus,.button-group.secondary .button[disabled]:hover{background-color:#767676;color:#fefefe}.button-group.secondary .button:focus,.button-group.secondary .button:hover{background-color:#5e5e5e;color:#fefefe}.button-group.success .button,.button-group.success .button.disabled,.button-group.success .button.disabled:focus,.button-group.success .button.disabled:hover,.button-group.success .button[disabled],.button-group.success .button[disabled]:focus,.button-group.success .button[disabled]:hover{background-color:#3adb76;color:#0a0a0a}.button-group.success .button:focus,.button-group.success .button:hover{background-color:#22bb5b;color:#0a0a0a}.button-group.warning .button,.button-group.warning .button.disabled,.button-group.warning .button.disabled:focus,.button-group.warning .button.disabled:hover,.button-group.warning .button[disabled],.button-group.warning .button[disabled]:focus,.button-group.warning .button[disabled]:hover{background-color:#ffae00;color:#0a0a0a}.button-group.warning .button:focus,.button-group.warning .button:hover{background-color:#cc8b00;color:#0a0a0a}.button-group.alert .button,.button-group.alert .button.disabled,.button-group.alert .button.disabled:focus,.button-group.alert .button.disabled:hover,.button-group.alert .button[disabled],.button-group.alert .button[disabled]:focus,.button-group.alert .button[disabled]:hover{background-color:#cc4b37;color:#fefefe}.button-group.alert .button:focus,.button-group.alert .button:hover{background-color:#a53b2a;color:#fefefe}.button-group.hollow .button,.button-group.hollow .button.disabled,.button-group.hollow .button.disabled:focus,.button-group.hollow .button.disabled:hover,.button-group.hollow .button:focus,.button-group.hollow .button:hover,.button-group.hollow .button[disabled],.button-group.hollow .button[disabled]:focus,.button-group.hollow .button[disabled]:hover{background-color:transparent}.button-group.hollow .button,.button-group.hollow .button.disabled,.button-group.hollow .button.disabled:focus,.button-group.hollow .button.disabled:hover,.button-group.hollow .button[disabled],.button-group.hollow .button[disabled]:focus,.button-group.hollow .button[disabled]:hover{border:1px solid #1779ba;color:#1779ba}.button-group.hollow .button:focus,.button-group.hollow .button:hover{border-color:#0c3d5d;color:#0c3d5d}.button-group.hollow .button.primary,.button-group.hollow .button.primary.disabled,.button-group.hollow .button.primary.disabled:focus,.button-group.hollow .button.primary.disabled:hover,.button-group.hollow .button.primary[disabled],.button-group.hollow .button.primary[disabled]:focus,.button-group.hollow .button.primary[disabled]:hover,.button-group.hollow.primary .button,.button-group.hollow.primary .button.disabled,.button-group.hollow.primary .button.disabled:focus,.button-group.hollow.primary .button.disabled:hover,.button-group.hollow.primary .button[disabled],.button-group.hollow.primary .button[disabled]:focus,.button-group.hollow.primary .button[disabled]:hover{border:1px solid #1779ba;color:#1779ba}.button-group.hollow .button.primary:focus,.button-group.hollow .button.primary:hover,.button-group.hollow.primary .button:focus,.button-group.hollow.primary .button:hover{border-color:#0c3d5d;color:#0c3d5d}.button-group.hollow .button.secondary,.button-group.hollow .button.secondary.disabled,.button-group.hollow .button.secondary.disabled:focus,.button-group.hollow .button.secondary.disabled:hover,.button-group.hollow .button.secondary[disabled],.button-group.hollow .button.secondary[disabled]:focus,.button-group.hollow .button.secondary[disabled]:hover,.button-group.hollow.secondary .button,.button-group.hollow.secondary .button.disabled,.button-group.hollow.secondary .button.disabled:focus,.button-group.hollow.secondary .button.disabled:hover,.button-group.hollow.secondary .button[disabled],.button-group.hollow.secondary .button[disabled]:focus,.button-group.hollow.secondary .button[disabled]:hover{border:1px solid #767676;color:#767676}.button-group.hollow .button.secondary:focus,.button-group.hollow .button.secondary:hover,.button-group.hollow.secondary .button:focus,.button-group.hollow.secondary .button:hover{border-color:#3b3b3b;color:#3b3b3b}.button-group.hollow .button.success,.button-group.hollow .button.success.disabled,.button-group.hollow .button.success.disabled:focus,.button-group.hollow .button.success.disabled:hover,.button-group.hollow .button.success[disabled],.button-group.hollow .button.success[disabled]:focus,.button-group.hollow .button.success[disabled]:hover,.button-group.hollow.success .button,.button-group.hollow.success .button.disabled,.button-group.hollow.success .button.disabled:focus,.button-group.hollow.success .button.disabled:hover,.button-group.hollow.success .button[disabled],.button-group.hollow.success .button[disabled]:focus,.button-group.hollow.success .button[disabled]:hover{border:1px solid #3adb76;color:#3adb76}.button-group.hollow .button.success:focus,.button-group.hollow .button.success:hover,.button-group.hollow.success .button:focus,.button-group.hollow.success .button:hover{border-color:#157539;color:#157539}.button-group.hollow .button.warning,.button-group.hollow .button.warning.disabled,.button-group.hollow .button.warning.disabled:focus,.button-group.hollow .button.warning.disabled:hover,.button-group.hollow .button.warning[disabled],.button-group.hollow .button.warning[disabled]:focus,.button-group.hollow .button.warning[disabled]:hover,.button-group.hollow.warning .button,.button-group.hollow.warning .button.disabled,.button-group.hollow.warning .button.disabled:focus,.button-group.hollow.warning .button.disabled:hover,.button-group.hollow.warning .button[disabled],.button-group.hollow.warning .button[disabled]:focus,.button-group.hollow.warning .button[disabled]:hover{border:1px solid #ffae00;color:#ffae00}.button-group.hollow .button.warning:focus,.button-group.hollow .button.warning:hover,.button-group.hollow.warning .button:focus,.button-group.hollow.warning .button:hover{border-color:#805700;color:#805700}.button-group.hollow.alert .button,.button-group.hollow.alert .button.disabled,.button-group.hollow.alert .button.disabled:focus,.button-group.hollow.alert .button.disabled:hover,.button-group.hollow.alert .button[disabled],.button-group.hollow.alert .button[disabled]:focus,.button-group.hollow.alert .button[disabled]:hover,.button-group.hollow .button.alert,.button-group.hollow .button.alert.disabled,.button-group.hollow .button.alert.disabled:focus,.button-group.hollow .button.alert.disabled:hover,.button-group.hollow .button.alert[disabled],.button-group.hollow .button.alert[disabled]:focus,.button-group.hollow .button.alert[disabled]:hover{border:1px solid #cc4b37;color:#cc4b37}.button-group.hollow.alert .button:focus,.button-group.hollow.alert .button:hover,.button-group.hollow .button.alert:focus,.button-group.hollow .button.alert:hover{border-color:#67251a;color:#67251a}.button-group.clear .button,.button-group.clear .button.disabled,.button-group.clear .button.disabled:focus,.button-group.clear .button.disabled:hover,.button-group.clear .button:focus,.button-group.clear .button:hover,.button-group.clear .button[disabled],.button-group.clear .button[disabled]:focus,.button-group.clear .button[disabled]:hover{background-color:transparent;border-color:transparent}.button-group.clear .button,.button-group.clear .button.disabled,.button-group.clear .button.disabled:focus,.button-group.clear .button.disabled:hover,.button-group.clear .button[disabled],.button-group.clear .button[disabled]:focus,.button-group.clear .button[disabled]:hover{color:#1779ba}.button-group.clear .button:focus,.button-group.clear .button:hover{color:#0c3d5d}.button-group.clear .button.primary,.button-group.clear .button.primary.disabled,.button-group.clear .button.primary.disabled:focus,.button-group.clear .button.primary.disabled:hover,.button-group.clear .button.primary[disabled],.button-group.clear .button.primary[disabled]:focus,.button-group.clear .button.primary[disabled]:hover,.button-group.clear.primary .button,.button-group.clear.primary .button.disabled,.button-group.clear.primary .button.disabled:focus,.button-group.clear.primary .button.disabled:hover,.button-group.clear.primary .button[disabled],.button-group.clear.primary .button[disabled]:focus,.button-group.clear.primary .button[disabled]:hover{color:#1779ba}.button-group.clear .button.primary:focus,.button-group.clear .button.primary:hover,.button-group.clear.primary .button:focus,.button-group.clear.primary .button:hover{color:#0c3d5d}.button-group.clear .button.secondary,.button-group.clear .button.secondary.disabled,.button-group.clear .button.secondary.disabled:focus,.button-group.clear .button.secondary.disabled:hover,.button-group.clear .button.secondary[disabled],.button-group.clear .button.secondary[disabled]:focus,.button-group.clear .button.secondary[disabled]:hover,.button-group.clear.secondary .button,.button-group.clear.secondary .button.disabled,.button-group.clear.secondary .button.disabled:focus,.button-group.clear.secondary .button.disabled:hover,.button-group.clear.secondary .button[disabled],.button-group.clear.secondary .button[disabled]:focus,.button-group.clear.secondary .button[disabled]:hover{color:#767676}.button-group.clear .button.secondary:focus,.button-group.clear .button.secondary:hover,.button-group.clear.secondary .button:focus,.button-group.clear.secondary .button:hover{color:#3b3b3b}.button-group.clear .button.success,.button-group.clear .button.success.disabled,.button-group.clear .button.success.disabled:focus,.button-group.clear .button.success.disabled:hover,.button-group.clear .button.success[disabled],.button-group.clear .button.success[disabled]:focus,.button-group.clear .button.success[disabled]:hover,.button-group.clear.success .button,.button-group.clear.success .button.disabled,.button-group.clear.success .button.disabled:focus,.button-group.clear.success .button.disabled:hover,.button-group.clear.success .button[disabled],.button-group.clear.success .button[disabled]:focus,.button-group.clear.success .button[disabled]:hover{color:#3adb76}.button-group.clear .button.success:focus,.button-group.clear .button.success:hover,.button-group.clear.success .button:focus,.button-group.clear.success .button:hover{color:#157539}.button-group.clear .button.warning,.button-group.clear .button.warning.disabled,.button-group.clear .button.warning.disabled:focus,.button-group.clear .button.warning.disabled:hover,.button-group.clear .button.warning[disabled],.button-group.clear .button.warning[disabled]:focus,.button-group.clear .button.warning[disabled]:hover,.button-group.clear.warning .button,.button-group.clear.warning .button.disabled,.button-group.clear.warning .button.disabled:focus,.button-group.clear.warning .button.disabled:hover,.button-group.clear.warning .button[disabled],.button-group.clear.warning .button[disabled]:focus,.button-group.clear.warning .button[disabled]:hover{color:#ffae00}.button-group.clear .button.warning:focus,.button-group.clear .button.warning:hover,.button-group.clear.warning .button:focus,.button-group.clear.warning .button:hover{color:#805700}.button-group.clear.alert .button,.button-group.clear.alert .button.disabled,.button-group.clear.alert .button.disabled:focus,.button-group.clear.alert .button.disabled:hover,.button-group.clear.alert .button[disabled],.button-group.clear.alert .button[disabled]:focus,.button-group.clear.alert .button[disabled]:hover,.button-group.clear .button.alert,.button-group.clear .button.alert.disabled,.button-group.clear .button.alert.disabled:focus,.button-group.clear .button.alert.disabled:hover,.button-group.clear .button.alert[disabled],.button-group.clear .button.alert[disabled]:focus,.button-group.clear .button.alert[disabled]:hover{color:#cc4b37}.button-group.clear.alert .button:focus,.button-group.clear.alert .button:hover,.button-group.clear .button.alert:focus,.button-group.clear .button.alert:hover{color:#67251a}.button-group.no-gaps .button{margin-right:-.0625rem}.button-group.no-gaps .button+.button{border-left-color:transparent}.button-group.stacked,.button-group.stacked-for-medium,.button-group.stacked-for-small{-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap}.button-group.stacked-for-medium .button,.button-group.stacked-for-small .button,.button-group.stacked .button{-webkit-box-flex:0;-webkit-flex:0 0 100%;-ms-flex:0 0 100%;flex:0 0 100%}.button-group.stacked-for-medium .button:last-child,.button-group.stacked-for-small .button:last-child,.button-group.stacked .button:last-child{margin-bottom:0}.button-group.stacked-for-medium.expanded .button,.button-group.stacked-for-small.expanded .button,.button-group.stacked.expanded .button{-webkit-box-flex:1;-webkit-flex:1 1 0px;-ms-flex:1 1 0px;flex:1 1 0px}@media print,screen and (min-width:40em){.button-group.stacked-for-small .button{-webkit-box-flex:0;-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto;margin-bottom:0}}@media print,screen and (min-width:64em){.button-group.stacked-for-medium .button{-webkit-box-flex:0;-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto;margin-bottom:0}}@media print,screen and (max-width:39.99875em){.button-group.stacked-for-small.expanded{display:block}.button-group.stacked-for-small.expanded .button{display:block;margin-right:0}}@media print,screen and (max-width:63.99875em){.button-group.stacked-for-medium.expanded{display:block}.button-group.stacked-for-medium.expanded .button{display:block;margin-right:0}}.close-button{color:#8a8a8a;cursor:pointer;position:absolute;z-index:10}[data-whatinput=mouse] .close-button{outline:0}.close-button:focus,.close-button:hover{color:#0a0a0a}.close-button.small{font-size:1.5em;line-height:1;right:.66rem;top:.33em}.close-button,.close-button.medium{font-size:2em;line-height:1;right:1rem;top:.5rem}.label{border-radius:0;cursor:default;display:inline-block;font-size:.8rem;line-height:1;padding:.33333rem .5rem;white-space:nowrap}.label,.label.primary{background:#1779ba;color:#fefefe}.label.secondary{background:#767676;color:#fefefe}.label.success{background:#3adb76;color:#0a0a0a}.label.warning{background:#ffae00;color:#0a0a0a}.label.alert{background:#cc4b37;color:#fefefe}.progress{background-color:#cacaca;border-radius:0;height:1rem;margin-bottom:1rem}.progress.primary .progress-meter{background-color:#1779ba}.progress.secondary .progress-meter{background-color:#767676}.progress.success .progress-meter{background-color:#3adb76}.progress.warning .progress-meter{background-color:#ffae00}.progress.alert .progress-meter{background-color:#cc4b37}.progress-meter{background-color:#1779ba;display:block;height:100%;position:relative;width:0}.progress-meter-text{color:#fefefe;font-size:.75rem;font-weight:700;left:50%;margin:0;position:absolute;top:50%;-webkit-transform:translate(-50%,-50%);-ms-transform:translate(-50%,-50%);transform:translate(-50%,-50%);white-space:nowrap}.slider{background-color:#e6e6e6;cursor:pointer;height:.5rem;margin-bottom:2.25rem;margin-top:1.25rem;position:relative;-ms-touch-action:none;touch-action:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.slider-fill{background-color:#cacaca;display:inline-block;height:.5rem;left:0;max-width:100%;position:absolute;top:0;-webkit-transition:all .2s ease-in-out;transition:all .2s ease-in-out}.slider-fill.is-dragging{-webkit-transition:all 0s linear;transition:all 0s linear}.slider-handle{background-color:#1779ba;border-radius:0;cursor:-webkit-grab;cursor:grab;display:inline-block;height:1.4rem;left:0;position:absolute;top:50%;-ms-touch-action:manipulation;touch-action:manipulation;-webkit-transform:translateY(-50%);-ms-transform:translateY(-50%);transform:translateY(-50%);-webkit-transition:all .2s ease-in-out;transition:all .2s ease-in-out;width:1.4rem;z-index:1}[data-whatinput=mouse] .slider-handle{outline:0}.slider-handle:hover{background-color:#14679e}.slider-handle.is-dragging{cursor:-webkit-grabbing;cursor:grabbing;-webkit-transition:all 0s linear;transition:all 0s linear}.slider.disabled,.slider[disabled]{cursor:not-allowed;opacity:.25}.slider.vertical{display:inline-block;height:12.5rem;margin:0 1.25rem;-webkit-transform:scaleY(-1);-ms-transform:scaleY(-1);transform:scaleY(-1);width:.5rem}.slider.vertical .slider-fill{max-height:100%;top:0;width:.5rem}.slider.vertical .slider-handle{height:1.4rem;left:50%;position:absolute;top:0;-webkit-transform:translateX(-50%);-ms-transform:translateX(-50%);transform:translateX(-50%);width:1.4rem}.switch{color:#fefefe;font-size:.875rem;font-weight:700;height:2rem;margin-bottom:1rem;outline:0;position:relative;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.switch-input{margin-bottom:0;opacity:0;position:absolute}.switch-paddle{background:#cacaca;border-radius:0;color:inherit;cursor:pointer;display:block;font-weight:inherit;height:2rem;position:relative;-webkit-transition:all .25s ease-out;transition:all .25s ease-out;width:4rem}input+.switch-paddle{margin:0}.switch-paddle:after{background:#fefefe;border-radius:0;content:"";display:block;height:1.5rem;left:.25rem;position:absolute;top:.25rem;-webkit-transform:translateZ(0);transform:translateZ(0);-webkit-transition:all .25s ease-out;transition:all .25s ease-out;width:1.5rem}input:checked~.switch-paddle{background:#1779ba}input:checked~.switch-paddle:after{left:2.25rem}input:disabled~.switch-paddle{cursor:not-allowed;opacity:.5}[data-whatinput=mouse] input:focus~.switch-paddle{outline:0}.switch-active,.switch-inactive{position:absolute;top:50%;-webkit-transform:translateY(-50%);-ms-transform:translateY(-50%);transform:translateY(-50%)}.switch-active{display:none;left:8%}input:checked+label>.switch-active{display:block}.switch-inactive{right:15%}input:checked+label>.switch-inactive{display:none}.switch.tiny{height:1.5rem}.switch.tiny .switch-paddle{font-size:.625rem;height:1.5rem;width:3rem}.switch.tiny .switch-paddle:after{height:1rem;left:.25rem;top:.25rem;width:1rem}.switch.tiny input:checked~.switch-paddle:after{left:1.75rem}.switch.small{height:1.75rem}.switch.small .switch-paddle{font-size:.75rem;height:1.75rem;width:3.5rem}.switch.small .switch-paddle:after{height:1.25rem;left:.25rem;top:.25rem;width:1.25rem}.switch.small input:checked~.switch-paddle:after{left:2rem}.switch.large{height:2.5rem}.switch.large .switch-paddle{font-size:1rem;height:2.5rem;width:5rem}.switch.large .switch-paddle:after{height:2rem;left:.25rem;top:.25rem;width:2rem}.switch.large input:checked~.switch-paddle:after{left:2.75rem}table{border-collapse:collapse;border-radius:0;margin-bottom:1rem;width:100%}tbody,tfoot,thead{background-color:#fefefe;border:1px solid #f1f1f1}caption{font-weight:700;padding:.5rem .625rem .625rem}thead{background:#f8f8f8}tfoot,thead{color:#0a0a0a}tfoot{background:#f1f1f1}tfoot tr,thead tr{background:0 0}tfoot td,tfoot th,thead td,thead th{font-weight:700;padding:.5rem .625rem .625rem;text-align:left}tbody td,tbody th{padding:.5rem .625rem .625rem}tbody tr:nth-child(2n){background-color:#f1f1f1;border-bottom:0}table.unstriped tbody{background-color:#fefefe}table.unstriped tbody tr{background-color:#fefefe;border-bottom:1px solid #f1f1f1}@media print,screen and (max-width:63.99875em){table.stack tfoot,table.stack thead{display:none}table.stack td,table.stack th,table.stack tr{display:block}table.stack td{border-top:0}}table.scroll{display:block;overflow-x:auto;width:100%}table.hover thead tr:hover{background-color:#f3f3f3}table.hover tfoot tr:hover{background-color:#ececec}table.hover tbody tr:hover{background-color:#f9f9f9}table.hover:not(.unstriped) tr:nth-of-type(2n):hover{background-color:#ececec}.table-scroll{overflow-x:auto}.badge{border-radius:50%;display:inline-block;font-size:.6rem;min-width:2.1em;padding:.3em;text-align:center}.badge,.badge.primary{background:#1779ba;color:#fefefe}.badge.secondary{background:#767676;color:#fefefe}.badge.success{background:#3adb76;color:#0a0a0a}.badge.warning{background:#ffae00;color:#0a0a0a}.badge.alert{background:#cc4b37;color:#fefefe}.breadcrumbs{list-style:none;margin:0 0 1rem}.breadcrumbs:after,.breadcrumbs:before{-ms-flex-preferred-size:0;-webkit-box-ordinal-group:2;-ms-flex-order:1;content:" ";display:table;-webkit-flex-basis:0;flex-basis:0;-webkit-order:1;order:1}.breadcrumbs:after{clear:both}.breadcrumbs li{color:#0a0a0a;cursor:default;float:left;font-size:.6875rem;text-transform:uppercase}.breadcrumbs li:not(:last-child):after{color:#cacaca;content:"/";margin:0 .75rem;opacity:1;position:relative}.breadcrumbs a{color:#1779ba}.breadcrumbs a:hover{text-decoration:underline}.breadcrumbs .disabled{color:#cacaca;cursor:not-allowed}.callout{background-color:#fff;border:1px solid hsla(0,0%,4%,.25);border-radius:0;color:#0a0a0a;margin:0 0 1rem;padding:1rem;position:relative}.callout>:first-child{margin-top:0}.callout>:last-child{margin-bottom:0}.callout.primary{background-color:#d7ecfa;color:#0a0a0a}.callout.secondary{background-color:#eaeaea;color:#0a0a0a}.callout.success{background-color:#e1faea;color:#0a0a0a}.callout.warning{background-color:#fff3d9;color:#0a0a0a}.callout.alert{background-color:#f7e4e1;color:#0a0a0a}.callout.small{padding:.5rem}.callout.large{padding:3rem}.card{-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-box-flex:1;-ms-flex-positive:1;background:#fefefe;border:1px solid #e6e6e6;border-radius:0;-webkit-box-shadow:none;box-shadow:none;color:#0a0a0a;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;-webkit-flex-grow:1;flex-grow:1;margin-bottom:1rem;overflow:hidden}.card>:last-child{margin-bottom:0}.card-divider{-webkit-box-flex:0;background:#e6e6e6;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex:0 1 auto;-ms-flex:0 1 auto;flex:0 1 auto;padding:1rem}.card-divider>:last-child{margin-bottom:0}.card-section{-webkit-box-flex:1;-webkit-flex:1 0 auto;-ms-flex:1 0 auto;flex:1 0 auto;padding:1rem}.card-section>:last-child{margin-bottom:0}.card-image{min-height:1px}.dropdown-pane{background-color:#fefefe;border:1px solid #cacaca;border-radius:0;display:none;font-size:1rem;padding:1rem;position:absolute;visibility:hidden;width:300px;z-index:10}.dropdown-pane.is-opening{display:block}.dropdown-pane.is-open{display:block;visibility:visible}.dropdown-pane.tiny{width:100px}.dropdown-pane.small{width:200px}.dropdown-pane.large{width:400px}.pagination{margin-bottom:1rem;margin-left:0}.pagination:after,.pagination:before{-ms-flex-preferred-size:0;-webkit-box-ordinal-group:2;-ms-flex-order:1;content:" ";display:table;-webkit-flex-basis:0;flex-basis:0;-webkit-order:1;order:1}.pagination:after{clear:both}.pagination li{border-radius:0;display:none;font-size:.875rem;margin-right:.0625rem}.pagination li:first-child,.pagination li:last-child{display:inline-block}@media print,screen and (min-width:40em){.pagination li{display:inline-block}}.pagination a,.pagination button{border-radius:0;color:#0a0a0a;display:block;padding:.1875rem .625rem}.pagination a:hover,.pagination button:hover{background:#e6e6e6}.pagination .current{background:#1779ba;color:#fefefe;cursor:default;padding:.1875rem .625rem}.pagination .disabled{color:#cacaca;cursor:not-allowed;padding:.1875rem .625rem}.pagination .disabled:hover{background:0 0}.pagination .ellipsis:after{color:#0a0a0a;content:"…";padding:.1875rem .625rem}.pagination-previous.disabled:before,.pagination-previous a:before{content:"«";display:inline-block;margin-right:.5rem}.pagination-next.disabled:after,.pagination-next a:after{content:"»";display:inline-block;margin-left:.5rem}.has-tip{border-bottom:1px dotted #8a8a8a;cursor:help;display:inline-block;font-weight:700;position:relative}.tooltip{background-color:#0a0a0a;border-radius:0;color:#fefefe;font-size:80%;max-width:10rem;padding:.75rem;position:absolute;top:calc(100% + .6495rem);z-index:1200}.tooltip:before{position:absolute}.tooltip.bottom:before{border-color:transparent transparent #0a0a0a;border-style:solid;border-width:0 .75rem .75rem;bottom:100%;content:"";display:block;height:0;width:0}.tooltip.bottom.align-center:before{left:50%;-webkit-transform:translateX(-50%);-ms-transform:translateX(-50%);transform:translateX(-50%)}.tooltip.top:before{border-color:#0a0a0a transparent transparent;border-style:solid;border-width:.75rem .75rem 0;bottom:auto;content:"";display:block;height:0;top:100%;width:0}.tooltip.top.align-center:before{left:50%;-webkit-transform:translateX(-50%);-ms-transform:translateX(-50%);transform:translateX(-50%)}.tooltip.left:before{border-color:transparent transparent transparent #0a0a0a;border-style:solid;border-width:.75rem 0 .75rem .75rem;content:"";display:block;height:0;left:100%;width:0}.tooltip.left.align-center:before{bottom:auto;top:50%;-webkit-transform:translateY(-50%);-ms-transform:translateY(-50%);transform:translateY(-50%)}.tooltip.right:before{border-color:transparent #0a0a0a transparent transparent;border-style:solid;border-width:.75rem .75rem .75rem 0;content:"";display:block;height:0;left:auto;right:100%;width:0}.tooltip.right.align-center:before{bottom:auto;top:50%;-webkit-transform:translateY(-50%);-ms-transform:translateY(-50%);transform:translateY(-50%)}.tooltip.align-top:before{bottom:auto;top:10%}.tooltip.align-bottom:before{bottom:10%;top:auto}.tooltip.align-left:before{left:10%;right:auto}.tooltip.align-right:before{left:auto;right:10%}.accordion{background:#fefefe;list-style-type:none;margin-left:0}.accordion[disabled] .accordion-title{cursor:not-allowed}.accordion-item:first-child>:first-child{border-radius:0}.accordion-item:last-child>:last-child{border-radius:0}.accordion-title{border:1px solid #e6e6e6;border-bottom:0;color:#1779ba;display:block;font-size:.75rem;line-height:1;padding:1.25rem 1rem;position:relative}:last-child:not(.is-active)>.accordion-title{border-bottom:1px solid #e6e6e6;border-radius:0}.accordion-title:focus,.accordion-title:hover{background-color:#e6e6e6}.accordion-title:before{content:"+";margin-top:-.5rem;position:absolute;right:1rem;top:50%}.is-active>.accordion-title:before{content:"–"}.accordion-content{background-color:#fefefe;border:1px solid #e6e6e6;border-bottom:0;color:#0a0a0a;display:none;padding:1rem}:last-child>.accordion-content:last-child{border-bottom:1px solid #e6e6e6}.media-object{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap;margin-bottom:1rem}.media-object img{max-width:none}@media print,screen and (max-width:39.99875em){.media-object.stack-for-small{-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap}}.media-object-section{-webkit-box-flex:0;-webkit-flex:0 1 auto;-ms-flex:0 1 auto;flex:0 1 auto}.media-object-section:first-child{padding-right:1rem}.media-object-section:last-child:not(:nth-child(2)){padding-left:1rem}.media-object-section>:last-child{margin-bottom:0}@media print,screen and (max-width:39.99875em){.stack-for-small .media-object-section{-ms-flex-preferred-size:100%;-webkit-flex-basis:100%;flex-basis:100%;max-width:100%;padding:0 0 1rem}.stack-for-small .media-object-section img{width:100%}}.media-object-section.main-section{-webkit-box-flex:1;-webkit-flex:1 1 0px;-ms-flex:1 1 0px;flex:1 1 0px}.orbit,.orbit-container{position:relative}.orbit-container{height:0;list-style:none;margin:0;overflow:hidden}.orbit-slide{position:absolute;width:100%}.orbit-slide.no-motionui.is-active{left:0;top:0}.orbit-figure{margin:0}.orbit-image{margin:0;max-width:100%;width:100%}.orbit-caption{background-color:hsla(0,0%,4%,.5);bottom:0;margin-bottom:0;width:100%}.orbit-caption,.orbit-next,.orbit-previous{color:#fefefe;padding:1rem;position:absolute}.orbit-next,.orbit-previous{top:50%;-webkit-transform:translateY(-50%);-ms-transform:translateY(-50%);transform:translateY(-50%);z-index:10}[data-whatinput=mouse] .orbit-next,[data-whatinput=mouse] .orbit-previous{outline:0}.orbit-next:active,.orbit-next:focus,.orbit-next:hover,.orbit-previous:active,.orbit-previous:focus,.orbit-previous:hover{background-color:hsla(0,0%,4%,.5)}.orbit-previous{left:0}.orbit-next{left:auto;right:0}.orbit-bullets{margin-bottom:.8rem;margin-top:.8rem;position:relative;text-align:center}[data-whatinput=mouse] .orbit-bullets{outline:0}.orbit-bullets button{background-color:#cacaca;border-radius:50%;height:1.2rem;margin:.1rem;width:1.2rem}.orbit-bullets button:hover{background-color:#8a8a8a}.orbit-bullets button.is-active{background-color:#8a8a8a}.flex-video,.responsive-embed{height:0;margin-bottom:1rem;overflow:hidden;padding-bottom:75%;position:relative}.flex-video embed,.flex-video iframe,.flex-video object,.flex-video video,.responsive-embed embed,.responsive-embed iframe,.responsive-embed object,.responsive-embed video{height:100%;left:0;position:absolute;top:0;width:100%}.flex-video.widescreen,.responsive-embed.widescreen{padding-bottom:56.25%}.tabs{background:#fefefe;border:1px solid #e6e6e6;list-style-type:none;margin:0}.tabs:after,.tabs:before{-ms-flex-preferred-size:0;-webkit-box-ordinal-group:2;-ms-flex-order:1;content:" ";display:table;-webkit-flex-basis:0;flex-basis:0;-webkit-order:1;order:1}.tabs:after{clear:both}.tabs.vertical>li{display:block;float:none;width:auto}.tabs.simple>li>a{padding:0}.tabs.simple>li>a:hover{background:0 0}.tabs.primary{background:#1779ba}.tabs.primary>li>a{color:#fefefe}.tabs.primary>li>a:focus,.tabs.primary>li>a:hover{background:#1673b1}.tabs-title{float:left}.tabs-title>a{color:#1779ba;display:block;font-size:.75rem;line-height:1;padding:1.25rem 1.5rem}[data-whatinput=mouse] .tabs-title>a{outline:0}.tabs-title>a:hover{background:#fefefe;color:#1468a0}.tabs-title>a:focus,.tabs-title>a[aria-selected=true]{background:#e6e6e6;color:#1779ba}.tabs-content{background:#fefefe;border:1px solid #e6e6e6;border-top:0;color:#0a0a0a;-webkit-transition:all .5s ease;transition:all .5s ease}.tabs-content.vertical{border:1px solid #e6e6e6;border-left:0}.tabs-panel{display:none;padding:1rem}.tabs-panel.is-active{display:block}.thumbnail{border:4px solid #fefefe;border-radius:0;-webkit-box-shadow:0 0 0 1px hsla(0,0%,4%,.2);box-shadow:0 0 0 1px hsla(0,0%,4%,.2);display:inline-block;line-height:0;margin-bottom:1rem;max-width:100%}a.thumbnail{-webkit-transition:-webkit-box-shadow .2s ease-out;transition:-webkit-box-shadow .2s ease-out;transition:box-shadow .2s ease-out;transition:box-shadow .2s ease-out,-webkit-box-shadow .2s ease-out}a.thumbnail:focus,a.thumbnail:hover{-webkit-box-shadow:0 0 6px 1px rgba(23,121,186,.5);box-shadow:0 0 6px 1px rgba(23,121,186,.5)}a.thumbnail image{-webkit-box-shadow:none;box-shadow:none}.menu{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;list-style:none;margin:0;padding:0;position:relative}[data-whatinput=mouse] .menu li{outline:0}.menu .button,.menu a{display:block;line-height:1;padding:.7rem 1rem;text-decoration:none}.menu a,.menu button,.menu input,.menu select{margin-bottom:0}.menu input{display:inline-block}.menu,.menu.horizontal{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap}.menu.vertical{-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap}.menu.vertical.icon-bottom li a i,.menu.vertical.icon-bottom li a img,.menu.vertical.icon-bottom li a svg,.menu.vertical.icon-top li a i,.menu.vertical.icon-top li a img,.menu.vertical.icon-top li a svg{text-align:left}.menu.expanded li{-webkit-box-flex:1;-webkit-flex:1 1 0px;-ms-flex:1 1 0px;flex:1 1 0px}.menu.expanded.icon-bottom li a i,.menu.expanded.icon-bottom li a img,.menu.expanded.icon-bottom li a svg,.menu.expanded.icon-top li a i,.menu.expanded.icon-top li a img,.menu.expanded.icon-top li a svg{text-align:left}.menu.simple{-webkit-box-align:center;-ms-flex-align:center;-webkit-align-items:center;align-items:center}.menu.simple li+li{margin-left:1rem}.menu.simple a{padding:0}@media print,screen and (min-width:40em){.menu.medium-horizontal{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap}.menu.medium-vertical{-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap}.menu.medium-expanded li,.menu.medium-simple li{-webkit-box-flex:1;-webkit-flex:1 1 0px;-ms-flex:1 1 0px;flex:1 1 0px}}@media print,screen and (min-width:64em){.menu.large-horizontal{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap}.menu.large-vertical{-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap}.menu.large-expanded li,.menu.large-simple li{-webkit-box-flex:1;-webkit-flex:1 1 0px;-ms-flex:1 1 0px;flex:1 1 0px}}.menu.nested{margin-left:1rem;margin-right:0}.menu.icon-bottom a,.menu.icon-left a,.menu.icon-right a,.menu.icon-top a,.menu.icons a{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex}.menu.icon-left li a,.menu.nested.icon-left li a{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-flow:row nowrap;-ms-flex-flow:row nowrap;flex-flow:row nowrap}.menu.icon-left li a i,.menu.icon-left li a img,.menu.icon-left li a svg,.menu.nested.icon-left li a i,.menu.nested.icon-left li a img,.menu.nested.icon-left li a svg{margin-right:.25rem}.menu.icon-right li a,.menu.nested.icon-right li a{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-flow:row nowrap;-ms-flex-flow:row nowrap;flex-flow:row nowrap}.menu.icon-right li a i,.menu.icon-right li a img,.menu.icon-right li a svg,.menu.nested.icon-right li a i,.menu.nested.icon-right li a img,.menu.nested.icon-right li a svg{margin-left:.25rem}.menu.icon-top li a,.menu.nested.icon-top li a{-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-flow:column nowrap;-ms-flex-flow:column nowrap;flex-flow:column nowrap}.menu.icon-top li a i,.menu.icon-top li a img,.menu.icon-top li a svg,.menu.nested.icon-top li a i,.menu.nested.icon-top li a img,.menu.nested.icon-top li a svg{-ms-flex-item-align:stretch;-webkit-align-self:stretch;align-self:stretch;margin-bottom:.25rem;text-align:center}.menu.icon-bottom li a,.menu.nested.icon-bottom li a{-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-flow:column nowrap;-ms-flex-flow:column nowrap;flex-flow:column nowrap}.menu.icon-bottom li a i,.menu.icon-bottom li a img,.menu.icon-bottom li a svg,.menu.nested.icon-bottom li a i,.menu.nested.icon-bottom li a img,.menu.nested.icon-bottom li a svg{-ms-flex-item-align:stretch;-webkit-align-self:stretch;align-self:stretch;margin-bottom:.25rem;text-align:center}.menu .is-active>a{background:#1779ba;color:#fefefe}.menu .active>a{background:#1779ba;color:#fefefe}.menu.align-left{-webkit-box-pack:start;-ms-flex-pack:start;-webkit-justify-content:flex-start;justify-content:flex-start}.menu.align-right li{-webkit-box-pack:end;-ms-flex-pack:end;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-justify-content:flex-end;justify-content:flex-end}.menu.align-right li .submenu li{-webkit-box-pack:start;-ms-flex-pack:start;-webkit-justify-content:flex-start;justify-content:flex-start}.menu.align-right.vertical li{display:block;text-align:right}.menu.align-right.icon-bottom li a i,.menu.align-right.icon-bottom li a img,.menu.align-right.icon-bottom li a svg,.menu.align-right.icon-top li a i,.menu.align-right.icon-top li a img,.menu.align-right.icon-top li a svg,.menu.align-right.vertical li .submenu li{text-align:right}.menu.align-right .nested{margin-left:0;margin-right:1rem}.menu.align-center li{-webkit-box-pack:center;-ms-flex-pack:center;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-justify-content:center;justify-content:center}.menu.align-center li .submenu li{-webkit-box-pack:start;-ms-flex-pack:start;-webkit-justify-content:flex-start;justify-content:flex-start}.menu .menu-text{color:inherit;font-weight:700;line-height:1;padding:.7rem 1rem}.menu-centered>.menu{-webkit-box-pack:center;-ms-flex-pack:center;-webkit-justify-content:center;justify-content:center}.menu-centered>.menu li{-webkit-box-pack:center;-ms-flex-pack:center;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-justify-content:center;justify-content:center}.menu-centered>.menu li .submenu li{-webkit-box-pack:start;-ms-flex-pack:start;-webkit-justify-content:flex-start;justify-content:flex-start}.no-js [data-responsive-menu] ul{display:none}.menu-icon{cursor:pointer;display:inline-block;height:16px;position:relative;vertical-align:middle;width:20px}.menu-icon:after{background:#fefefe;-webkit-box-shadow:0 7px 0 #fefefe,0 14px 0 #fefefe;box-shadow:0 7px 0 #fefefe,0 14px 0 #fefefe;content:"";display:block;height:2px;left:0;position:absolute;top:0;width:100%}.menu-icon:hover:after{background:#cacaca;-webkit-box-shadow:0 7px 0 #cacaca,0 14px 0 #cacaca;box-shadow:0 7px 0 #cacaca,0 14px 0 #cacaca}.menu-icon.dark{cursor:pointer;display:inline-block;height:16px;position:relative;vertical-align:middle;width:20px}.menu-icon.dark:after{background:#0a0a0a;-webkit-box-shadow:0 7px 0 #0a0a0a,0 14px 0 #0a0a0a;box-shadow:0 7px 0 #0a0a0a,0 14px 0 #0a0a0a;content:"";display:block;height:2px;left:0;position:absolute;top:0;width:100%}.menu-icon.dark:hover:after{background:#8a8a8a;-webkit-box-shadow:0 7px 0 #8a8a8a,0 14px 0 #8a8a8a;box-shadow:0 7px 0 #8a8a8a,0 14px 0 #8a8a8a}.accordion-menu li{width:100%}.accordion-menu .is-accordion-submenu a,.accordion-menu a{padding:.7rem 1rem}.accordion-menu .nested.is-accordion-submenu{margin-left:1rem;margin-right:0}.accordion-menu.align-right .nested.is-accordion-submenu{margin-left:0;margin-right:1rem}.accordion-menu .is-accordion-submenu-parent:not(.has-submenu-toggle)>a{position:relative}.accordion-menu .is-accordion-submenu-parent:not(.has-submenu-toggle)>a:after{border-color:#1779ba transparent transparent;border-style:solid;border-width:6px 6px 0;content:"";display:block;height:0;margin-top:-3px;position:absolute;right:1rem;top:50%;width:0}.accordion-menu.align-left .is-accordion-submenu-parent>a:after{left:auto;right:1rem}.accordion-menu.align-right .is-accordion-submenu-parent>a:after{left:1rem;right:auto}.accordion-menu .is-accordion-submenu-parent[aria-expanded=true]>a:after{-webkit-transform:rotate(180deg);-ms-transform:rotate(180deg);transform:rotate(180deg);-webkit-transform-origin:50% 50%;-ms-transform-origin:50% 50%;transform-origin:50% 50%}.is-accordion-submenu-parent{position:relative}.has-submenu-toggle>a{margin-right:40px}.submenu-toggle{cursor:pointer;height:40px;position:absolute;right:0;top:0;width:40px}.submenu-toggle:after{border-color:#1779ba transparent transparent;border-style:solid;border-width:6px 6px 0;bottom:0;content:"";display:block;height:0;margin:auto;top:0;width:0}.submenu-toggle[aria-expanded=true]:after{-webkit-transform:scaleY(-1);-ms-transform:scaleY(-1);transform:scaleY(-1);-webkit-transform-origin:50% 50%;-ms-transform-origin:50% 50%;transform-origin:50% 50%}.submenu-toggle-text{clip:rect(0,0,0,0)!important;border:0!important;height:1px!important;overflow:hidden!important;padding:0!important;position:absolute!important;white-space:nowrap!important;width:1px!important}.is-drilldown{overflow:hidden;position:relative}.is-drilldown li{display:block}.is-drilldown.animate-height{-webkit-transition:height .5s;transition:height .5s}.drilldown a{background:#fefefe;padding:.7rem 1rem}.drilldown .is-drilldown-submenu{background:#fefefe;left:100%;position:absolute;top:0;-webkit-transition:-webkit-transform .15s linear;transition:-webkit-transform .15s linear;transition:transform .15s linear;transition:transform .15s linear,-webkit-transform .15s linear;width:100%;z-index:-1}.drilldown .is-drilldown-submenu.is-active{display:block;-webkit-transform:translateX(-100%);-ms-transform:translateX(-100%);transform:translateX(-100%);z-index:1}.drilldown .is-drilldown-submenu.is-closing{-webkit-transform:translateX(100%);-ms-transform:translateX(100%);transform:translateX(100%)}.drilldown .is-drilldown-submenu a{padding:.7rem 1rem}.drilldown .nested.is-drilldown-submenu{margin-left:0;margin-right:0}.drilldown .drilldown-submenu-cover-previous{min-height:100%}.drilldown .is-drilldown-submenu-parent>a{position:relative}.drilldown .is-drilldown-submenu-parent>a:after{border-color:transparent transparent transparent #1779ba;border-style:solid;border-width:6px 0 6px 6px;content:"";display:block;height:0;margin-top:-6px;position:absolute;right:1rem;top:50%;width:0}.drilldown.align-left .is-drilldown-submenu-parent>a:after{border-color:transparent transparent transparent #1779ba;border-style:solid;border-width:6px 0 6px 6px;content:"";display:block;height:0;left:auto;right:1rem;width:0}.drilldown.align-right .is-drilldown-submenu-parent>a:after{border-color:transparent #1779ba transparent transparent;border-style:solid;border-width:6px 6px 6px 0;content:"";display:block;height:0;left:1rem;right:auto;width:0}.drilldown .js-drilldown-back>a:before{border-color:transparent #1779ba transparent transparent;border-style:solid;border-width:6px 6px 6px 0;content:"";display:block;display:inline-block;height:0;margin-right:.75rem;vertical-align:middle;width:0}.dropdown.menu>li.opens-left>.is-dropdown-submenu{left:auto;right:0;top:100%}.dropdown.menu>li.opens-right>.is-dropdown-submenu{left:0;right:auto;top:100%}.dropdown.menu>li.is-dropdown-submenu-parent>a{padding-right:1.5rem;position:relative}.dropdown.menu>li.is-dropdown-submenu-parent>a:after{border-color:#1779ba transparent transparent;border-style:solid;border-width:6px 6px 0;content:"";display:block;height:0;left:auto;margin-top:-3px;right:5px;width:0}[data-whatinput=mouse] .dropdown.menu a{outline:0}.dropdown.menu>li>a{padding:.7rem 1rem}.dropdown.menu>li.is-active>a{background:0 0;color:#1779ba}.no-js .dropdown.menu ul{display:none}.dropdown.menu .nested.is-dropdown-submenu{margin-left:0;margin-right:0}.dropdown.menu.vertical>li .is-dropdown-submenu{top:0}.dropdown.menu.vertical>li.opens-left>.is-dropdown-submenu{left:auto;right:100%;top:0}.dropdown.menu.vertical>li.opens-right>.is-dropdown-submenu{left:100%;right:auto}.dropdown.menu.vertical>li>a:after{right:14px}.dropdown.menu.vertical>li.opens-left>a:after{border-color:transparent #1779ba transparent transparent;border-style:solid;border-width:6px 6px 6px 0;content:"";display:block;height:0;left:5px;right:auto;width:0}.dropdown.menu.vertical>li.opens-right>a:after{border-color:transparent transparent transparent #1779ba;border-style:solid;border-width:6px 0 6px 6px;content:"";display:block;height:0;width:0}@media print,screen and (min-width:40em){.dropdown.menu.medium-horizontal>li.opens-left>.is-dropdown-submenu{left:auto;right:0;top:100%}.dropdown.menu.medium-horizontal>li.opens-right>.is-dropdown-submenu{left:0;right:auto;top:100%}.dropdown.menu.medium-horizontal>li.is-dropdown-submenu-parent>a{padding-right:1.5rem;position:relative}.dropdown.menu.medium-horizontal>li.is-dropdown-submenu-parent>a:after{border-color:#1779ba transparent transparent;border-style:solid;border-width:6px 6px 0;content:"";display:block;height:0;left:auto;margin-top:-3px;right:5px;width:0}.dropdown.menu.medium-vertical>li .is-dropdown-submenu{top:0}.dropdown.menu.medium-vertical>li.opens-left>.is-dropdown-submenu{left:auto;right:100%;top:0}.dropdown.menu.medium-vertical>li.opens-right>.is-dropdown-submenu{left:100%;right:auto}.dropdown.menu.medium-vertical>li>a:after{right:14px}.dropdown.menu.medium-vertical>li.opens-left>a:after{border-color:transparent #1779ba transparent transparent;border-style:solid;border-width:6px 6px 6px 0;content:"";display:block;height:0;left:5px;right:auto;width:0}.dropdown.menu.medium-vertical>li.opens-right>a:after{border-color:transparent transparent transparent #1779ba;border-style:solid;border-width:6px 0 6px 6px;content:"";display:block;height:0;width:0}}@media print,screen and (min-width:64em){.dropdown.menu.large-horizontal>li.opens-left>.is-dropdown-submenu{left:auto;right:0;top:100%}.dropdown.menu.large-horizontal>li.opens-right>.is-dropdown-submenu{left:0;right:auto;top:100%}.dropdown.menu.large-horizontal>li.is-dropdown-submenu-parent>a{padding-right:1.5rem;position:relative}.dropdown.menu.large-horizontal>li.is-dropdown-submenu-parent>a:after{border-color:#1779ba transparent transparent;border-style:solid;border-width:6px 6px 0;content:"";display:block;height:0;left:auto;margin-top:-3px;right:5px;width:0}.dropdown.menu.large-vertical>li .is-dropdown-submenu{top:0}.dropdown.menu.large-vertical>li.opens-left>.is-dropdown-submenu{left:auto;right:100%;top:0}.dropdown.menu.large-vertical>li.opens-right>.is-dropdown-submenu{left:100%;right:auto}.dropdown.menu.large-vertical>li>a:after{right:14px}.dropdown.menu.large-vertical>li.opens-left>a:after{border-color:transparent #1779ba transparent transparent;border-style:solid;border-width:6px 6px 6px 0;content:"";display:block;height:0;left:5px;right:auto;width:0}.dropdown.menu.large-vertical>li.opens-right>a:after{border-color:transparent transparent transparent #1779ba;border-style:solid;border-width:6px 0 6px 6px;content:"";display:block;height:0;width:0}}.dropdown.menu.align-right .is-dropdown-submenu.first-sub{left:auto;right:0;top:100%}.is-dropdown-menu.vertical{width:100px}.is-dropdown-menu.vertical.align-right{float:right}.is-dropdown-submenu-parent{position:relative}.is-dropdown-submenu-parent a:after{left:auto;margin-top:-6px;position:absolute;right:5px;top:50%}.is-dropdown-submenu-parent.opens-inner>.is-dropdown-submenu{left:auto;top:100%}.is-dropdown-submenu-parent.opens-left>.is-dropdown-submenu{left:auto;right:100%}.is-dropdown-submenu-parent.opens-right>.is-dropdown-submenu{left:100%;right:auto}.is-dropdown-submenu{background:#fefefe;border:1px solid #cacaca;display:none;left:100%;min-width:200px;position:absolute;top:0;z-index:1}.dropdown .is-dropdown-submenu a{padding:.7rem 1rem}.is-dropdown-submenu .is-dropdown-submenu-parent>a:after{right:14px}.is-dropdown-submenu .is-dropdown-submenu-parent.opens-left>a:after{border-color:transparent #1779ba transparent transparent;border-style:solid;border-width:6px 6px 6px 0;content:"";display:block;height:0;left:5px;right:auto;width:0}.is-dropdown-submenu .is-dropdown-submenu-parent.opens-right>a:after{border-color:transparent transparent transparent #1779ba;border-style:solid;border-width:6px 0 6px 6px;content:"";display:block;height:0;width:0}.is-dropdown-submenu .is-dropdown-submenu{margin-top:-1px}.is-dropdown-submenu>li{width:100%}.is-dropdown-submenu.js-dropdown-active{display:block}.is-off-canvas-open{overflow:hidden}.js-off-canvas-overlay{background:hsla(0,0%,100%,.25);height:100%;left:0;opacity:0;overflow:hidden;position:absolute;top:0;-webkit-transition:opacity .5s ease,visibility .5s ease;transition:opacity .5s ease,visibility .5s ease;visibility:hidden;width:100%;z-index:11}.js-off-canvas-overlay.is-visible{opacity:1;visibility:visible}.js-off-canvas-overlay.is-closable{cursor:pointer}.js-off-canvas-overlay.is-overlay-absolute{position:absolute}.js-off-canvas-overlay.is-overlay-fixed{position:fixed}.off-canvas-wrapper{overflow:hidden;position:relative}.off-canvas{-webkit-backface-visibility:hidden;backface-visibility:hidden;background:#e6e6e6;position:fixed;-webkit-transition:-webkit-transform .5s ease;transition:-webkit-transform .5s ease;transition:transform .5s ease;transition:transform .5s ease,-webkit-transform .5s ease;z-index:12}[data-whatinput=mouse] .off-canvas{outline:0}.off-canvas.is-transition-push{z-index:12}.off-canvas.is-closed{visibility:hidden}.off-canvas.is-transition-overlap{z-index:13}.off-canvas.is-transition-overlap.is-open{-webkit-box-shadow:0 0 10px hsla(0,0%,4%,.7);box-shadow:0 0 10px hsla(0,0%,4%,.7)}.off-canvas.is-open{-webkit-transform:translate(0);-ms-transform:translate(0);transform:translate(0)}.off-canvas-absolute{-webkit-backface-visibility:hidden;backface-visibility:hidden;background:#e6e6e6;position:absolute;-webkit-transition:-webkit-transform .5s ease;transition:-webkit-transform .5s ease;transition:transform .5s ease;transition:transform .5s ease,-webkit-transform .5s ease;z-index:12}[data-whatinput=mouse] .off-canvas-absolute{outline:0}.off-canvas-absolute.is-transition-push{z-index:12}.off-canvas-absolute.is-closed{visibility:hidden}.off-canvas-absolute.is-transition-overlap{z-index:13}.off-canvas-absolute.is-transition-overlap.is-open{-webkit-box-shadow:0 0 10px hsla(0,0%,4%,.7);box-shadow:0 0 10px hsla(0,0%,4%,.7)}.off-canvas-absolute.is-open{-webkit-transform:translate(0);-ms-transform:translate(0);transform:translate(0)}.position-left{-webkit-overflow-scrolling:touch;height:100%;left:0;overflow-y:auto;top:0;width:250px}.off-canvas-content .off-canvas.position-left,.position-left{-webkit-transform:translateX(-250px);-ms-transform:translateX(-250px);transform:translateX(-250px)}.off-canvas-content .off-canvas.position-left.is-transition-overlap.is-open{-webkit-transform:translate(0);-ms-transform:translate(0);transform:translate(0)}.off-canvas-content.is-open-left.has-transition-push{-webkit-transform:translateX(250px);-ms-transform:translateX(250px);transform:translateX(250px)}.position-left.is-transition-push{-webkit-box-shadow:inset -13px 0 20px -13px hsla(0,0%,4%,.25);box-shadow:inset -13px 0 20px -13px hsla(0,0%,4%,.25)}.position-right{-webkit-overflow-scrolling:touch;height:100%;overflow-y:auto;right:0;top:0;width:250px}.off-canvas-content .off-canvas.position-right,.position-right{-webkit-transform:translateX(250px);-ms-transform:translateX(250px);transform:translateX(250px)}.off-canvas-content .off-canvas.position-right.is-transition-overlap.is-open{-webkit-transform:translate(0);-ms-transform:translate(0);transform:translate(0)}.off-canvas-content.is-open-right.has-transition-push{-webkit-transform:translateX(-250px);-ms-transform:translateX(-250px);transform:translateX(-250px)}.position-right.is-transition-push{-webkit-box-shadow:inset 13px 0 20px -13px hsla(0,0%,4%,.25);box-shadow:inset 13px 0 20px -13px hsla(0,0%,4%,.25)}.position-top{-webkit-overflow-scrolling:touch;height:250px;left:0;overflow-x:auto;top:0;width:100%}.off-canvas-content .off-canvas.position-top,.position-top{-webkit-transform:translateY(-250px);-ms-transform:translateY(-250px);transform:translateY(-250px)}.off-canvas-content .off-canvas.position-top.is-transition-overlap.is-open{-webkit-transform:translate(0);-ms-transform:translate(0);transform:translate(0)}.off-canvas-content.is-open-top.has-transition-push{-webkit-transform:translateY(250px);-ms-transform:translateY(250px);transform:translateY(250px)}.position-top.is-transition-push{-webkit-box-shadow:inset 0 -13px 20px -13px hsla(0,0%,4%,.25);box-shadow:inset 0 -13px 20px -13px hsla(0,0%,4%,.25)}.position-bottom{-webkit-overflow-scrolling:touch;bottom:0;height:250px;left:0;overflow-x:auto;width:100%}.off-canvas-content .off-canvas.position-bottom,.position-bottom{-webkit-transform:translateY(250px);-ms-transform:translateY(250px);transform:translateY(250px)}.off-canvas-content .off-canvas.position-bottom.is-transition-overlap.is-open{-webkit-transform:translate(0);-ms-transform:translate(0);transform:translate(0)}.off-canvas-content.is-open-bottom.has-transition-push{-webkit-transform:translateY(-250px);-ms-transform:translateY(-250px);transform:translateY(-250px)}.position-bottom.is-transition-push{-webkit-box-shadow:inset 0 13px 20px -13px hsla(0,0%,4%,.25);box-shadow:inset 0 13px 20px -13px hsla(0,0%,4%,.25)}.off-canvas-content{-webkit-backface-visibility:hidden;backface-visibility:hidden;-webkit-transform:none;-ms-transform:none;transform:none}.off-canvas-content.has-transition-overlap,.off-canvas-content.has-transition-push{-webkit-transition:-webkit-transform .5s ease;transition:-webkit-transform .5s ease;transition:transform .5s ease;transition:transform .5s ease,-webkit-transform .5s ease}.off-canvas-content.has-transition-push,.off-canvas-content .off-canvas.is-open{-webkit-transform:translate(0);-ms-transform:translate(0);transform:translate(0)}@media print,screen and (min-width:40em){.position-left.reveal-for-medium{-webkit-transform:none;-ms-transform:none;transform:none;-webkit-transition:none;transition:none;visibility:visible;z-index:12}.position-left.reveal-for-medium .close-button{display:none}.off-canvas-content .position-left.reveal-for-medium{-webkit-transform:none;-ms-transform:none;transform:none}.off-canvas-content.has-reveal-left{margin-left:250px}.position-left.reveal-for-medium~.off-canvas-content{margin-left:250px}.position-right.reveal-for-medium{-webkit-transform:none;-ms-transform:none;transform:none;-webkit-transition:none;transition:none;visibility:visible;z-index:12}.position-right.reveal-for-medium .close-button{display:none}.off-canvas-content .position-right.reveal-for-medium{-webkit-transform:none;-ms-transform:none;transform:none}.off-canvas-content.has-reveal-right{margin-right:250px}.position-right.reveal-for-medium~.off-canvas-content{margin-right:250px}.position-top.reveal-for-medium{-webkit-transform:none;-ms-transform:none;transform:none;-webkit-transition:none;transition:none;visibility:visible;z-index:12}.position-top.reveal-for-medium .close-button{display:none}.off-canvas-content .position-top.reveal-for-medium{-webkit-transform:none;-ms-transform:none;transform:none}.off-canvas-content.has-reveal-top{margin-top:250px}.position-top.reveal-for-medium~.off-canvas-content{margin-top:250px}.position-bottom.reveal-for-medium{-webkit-transform:none;-ms-transform:none;transform:none;-webkit-transition:none;transition:none;visibility:visible;z-index:12}.position-bottom.reveal-for-medium .close-button{display:none}.off-canvas-content .position-bottom.reveal-for-medium{-webkit-transform:none;-ms-transform:none;transform:none}.off-canvas-content.has-reveal-bottom{margin-bottom:250px}.position-bottom.reveal-for-medium~.off-canvas-content{margin-bottom:250px}}@media print,screen and (min-width:64em){.position-left.reveal-for-large{-webkit-transform:none;-ms-transform:none;transform:none;-webkit-transition:none;transition:none;visibility:visible;z-index:12}.position-left.reveal-for-large .close-button{display:none}.off-canvas-content .position-left.reveal-for-large{-webkit-transform:none;-ms-transform:none;transform:none}.off-canvas-content.has-reveal-left{margin-left:250px}.position-left.reveal-for-large~.off-canvas-content{margin-left:250px}.position-right.reveal-for-large{-webkit-transform:none;-ms-transform:none;transform:none;-webkit-transition:none;transition:none;visibility:visible;z-index:12}.position-right.reveal-for-large .close-button{display:none}.off-canvas-content .position-right.reveal-for-large{-webkit-transform:none;-ms-transform:none;transform:none}.off-canvas-content.has-reveal-right{margin-right:250px}.position-right.reveal-for-large~.off-canvas-content{margin-right:250px}.position-top.reveal-for-large{-webkit-transform:none;-ms-transform:none;transform:none;-webkit-transition:none;transition:none;visibility:visible;z-index:12}.position-top.reveal-for-large .close-button{display:none}.off-canvas-content .position-top.reveal-for-large{-webkit-transform:none;-ms-transform:none;transform:none}.off-canvas-content.has-reveal-top{margin-top:250px}.position-top.reveal-for-large~.off-canvas-content{margin-top:250px}.position-bottom.reveal-for-large{-webkit-transform:none;-ms-transform:none;transform:none;-webkit-transition:none;transition:none;visibility:visible;z-index:12}.position-bottom.reveal-for-large .close-button{display:none}.off-canvas-content .position-bottom.reveal-for-large{-webkit-transform:none;-ms-transform:none;transform:none}.off-canvas-content.has-reveal-bottom{margin-bottom:250px}.position-bottom.reveal-for-large~.off-canvas-content{margin-bottom:250px}}@media print,screen and (min-width:40em){.off-canvas.in-canvas-for-medium{background:0 0;height:auto;overflow:visible;position:static;-webkit-transition:none;transition:none;visibility:visible;width:auto}.off-canvas.in-canvas-for-medium.position-bottom,.off-canvas.in-canvas-for-medium.position-left,.off-canvas.in-canvas-for-medium.position-right,.off-canvas.in-canvas-for-medium.position-top{-webkit-box-shadow:none;box-shadow:none;-webkit-transform:none;-ms-transform:none;transform:none}.off-canvas.in-canvas-for-medium .close-button{display:none}}@media print,screen and (min-width:64em){.off-canvas.in-canvas-for-large{background:0 0;height:auto;overflow:visible;position:static;-webkit-transition:none;transition:none;visibility:visible;width:auto}.off-canvas.in-canvas-for-large.position-bottom,.off-canvas.in-canvas-for-large.position-left,.off-canvas.in-canvas-for-large.position-right,.off-canvas.in-canvas-for-large.position-top{-webkit-box-shadow:none;box-shadow:none;-webkit-transform:none;-ms-transform:none;transform:none}.off-canvas.in-canvas-for-large .close-button{display:none}}html.is-reveal-open{overflow-y:hidden;position:fixed;width:100%}html.is-reveal-open.zf-has-scroll{-webkit-overflow-scrolling:touch;overflow-y:scroll}html.is-reveal-open body{overflow-y:hidden}.reveal-overlay{background-color:hsla(0,0%,4%,.45);bottom:0;left:0;position:fixed;right:0;top:0;z-index:1005}.reveal,.reveal-overlay{-webkit-overflow-scrolling:touch;display:none;overflow-y:auto}.reveal{-webkit-backface-visibility:hidden;backface-visibility:hidden;background-color:#fefefe;border:1px solid #cacaca;border-radius:0;margin-left:auto;margin-right:auto;padding:1rem;position:relative;top:100px;z-index:1006}[data-whatinput=mouse] .reveal{outline:0}@media print,screen and (min-width:40em){.reveal{min-height:0}}.reveal .column{min-width:0}.reveal>:last-child{margin-bottom:0}@media print,screen and (min-width:40em){.reveal{max-width:75rem;width:600px}}.reveal.collapse{padding:0}@media print,screen and (min-width:40em){.reveal.tiny{max-width:75rem;width:30%}.reveal.small{max-width:75rem;width:50%}.reveal.large{max-width:75rem;width:90%}}.reveal.full{border:0;border-radius:0;bottom:0;height:100%;left:0;margin-left:0;max-width:none;min-height:100%;right:0;top:0;width:100%}@media print,screen and (max-width:39.99875em){.reveal{border:0;border-radius:0;bottom:0;height:100%;left:0;margin-left:0;max-width:none;min-height:100%;right:0;top:0;width:100%}}.reveal.without-overlay{position:fixed}.sticky,.sticky-container{position:relative}.sticky{-webkit-transform:translateZ(0);transform:translateZ(0);z-index:0}.sticky.is-stuck{position:fixed;width:100%;z-index:5}.sticky.is-stuck.is-at-top{top:0}.sticky.is-stuck.is-at-bottom{bottom:0}.sticky.is-anchored{left:auto;position:relative;right:auto}.sticky.is-anchored.is-at-bottom{bottom:0}.title-bar{-webkit-box-pack:start;-ms-flex-pack:start;-webkit-box-align:center;-ms-flex-align:center;-webkit-align-items:center;align-items:center;background:#0a0a0a;color:#fefefe;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-justify-content:flex-start;justify-content:flex-start;padding:.5rem}.title-bar .menu-icon{margin-left:.25rem;margin-right:.25rem}.title-bar-left,.title-bar-right{-webkit-box-flex:1;-webkit-flex:1 1 0px;-ms-flex:1 1 0px;flex:1 1 0px}.title-bar-right{text-align:right}.title-bar-title{display:inline-block;font-weight:700;vertical-align:middle}.top-bar{-webkit-box-pack:justify;-ms-flex-pack:justify;-webkit-box-align:center;-ms-flex-align:center;-webkit-align-items:center;align-items:center;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;-webkit-justify-content:space-between;justify-content:space-between;padding:.5rem}.top-bar,.top-bar ul{background-color:#e6e6e6}.top-bar input{margin-right:1rem;max-width:200px}.top-bar .input-group-field{margin-right:0;width:100%}.top-bar input.button{width:auto}.top-bar .top-bar-left,.top-bar .top-bar-right{-webkit-box-flex:0;-webkit-flex:0 0 100%;-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}@media print,screen and (min-width:40em){.top-bar{-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap}.top-bar .top-bar-left{-webkit-box-flex:1;-webkit-flex:1 1 auto;-ms-flex:1 1 auto;flex:1 1 auto;margin-right:auto}.top-bar .top-bar-right{-webkit-box-flex:0;-webkit-flex:0 1 auto;-ms-flex:0 1 auto;flex:0 1 auto;margin-left:auto}}@media print,screen and (max-width:63.99875em){.top-bar.stacked-for-medium{-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap}.top-bar.stacked-for-medium .top-bar-left,.top-bar.stacked-for-medium .top-bar-right{-webkit-box-flex:0;-webkit-flex:0 0 100%;-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}}@media print,screen and (max-width:74.99875em){.top-bar.stacked-for-large{-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap}.top-bar.stacked-for-large .top-bar-left,.top-bar.stacked-for-large .top-bar-right{-webkit-box-flex:0;-webkit-flex:0 0 100%;-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}}.top-bar-title{margin:.5rem 1rem .5rem 0}.top-bar-left,.top-bar-right,.top-bar-title{-webkit-box-flex:0;-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto}.float-left{float:left!important}.float-right{float:right!important}.float-center{display:block;margin-left:auto;margin-right:auto}.clearfix:after,.clearfix:before{-ms-flex-preferred-size:0;-webkit-box-ordinal-group:2;-ms-flex-order:1;content:" ";display:table;-webkit-flex-basis:0;flex-basis:0;-webkit-order:1;order:1}.clearfix:after{clear:both}.align-left{-webkit-box-pack:start;-ms-flex-pack:start;-webkit-justify-content:flex-start;justify-content:flex-start}.align-right{-webkit-box-pack:end;-ms-flex-pack:end;-webkit-justify-content:flex-end;justify-content:flex-end}.align-center{-webkit-box-pack:center;-ms-flex-pack:center;-webkit-justify-content:center;justify-content:center}.align-justify{-webkit-box-pack:justify;-ms-flex-pack:justify;-webkit-justify-content:space-between;justify-content:space-between}.align-spaced{-ms-flex-pack:distribute;-webkit-justify-content:space-around;justify-content:space-around}.align-left.vertical.menu>li>a{-webkit-box-pack:start;-ms-flex-pack:start;-webkit-justify-content:flex-start;justify-content:flex-start}.align-right.vertical.menu>li>a{-webkit-box-pack:end;-ms-flex-pack:end;-webkit-justify-content:flex-end;justify-content:flex-end}.align-center.vertical.menu>li>a{-webkit-box-pack:center;-ms-flex-pack:center;-webkit-justify-content:center;justify-content:center}.align-top{-webkit-box-align:start;-ms-flex-align:start;-webkit-align-items:flex-start;align-items:flex-start}.align-self-top{-ms-flex-item-align:start;-webkit-align-self:flex-start;align-self:flex-start}.align-bottom{-webkit-box-align:end;-ms-flex-align:end;-webkit-align-items:flex-end;align-items:flex-end}.align-self-bottom{-ms-flex-item-align:end;-webkit-align-self:flex-end;align-self:flex-end}.align-middle{-webkit-box-align:center;-ms-flex-align:center;-webkit-align-items:center;align-items:center}.align-self-middle{-ms-flex-item-align:center;-webkit-align-self:center;align-self:center}.align-stretch{-webkit-box-align:stretch;-ms-flex-align:stretch;-webkit-align-items:stretch;align-items:stretch}.align-self-stretch{-ms-flex-item-align:stretch;-webkit-align-self:stretch;align-self:stretch}.align-center-middle{-webkit-box-pack:center;-ms-flex-pack:center;-webkit-box-align:center;-ms-flex-align:center;-ms-flex-line-pack:center;-webkit-align-content:center;align-content:center;-webkit-align-items:center;align-items:center;-webkit-justify-content:center;justify-content:center}.small-order-1{-webkit-box-ordinal-group:2;-ms-flex-order:1;-webkit-order:1;order:1}.small-order-2{-webkit-box-ordinal-group:3;-ms-flex-order:2;-webkit-order:2;order:2}.small-order-3{-webkit-box-ordinal-group:4;-ms-flex-order:3;-webkit-order:3;order:3}.small-order-4{-webkit-box-ordinal-group:5;-ms-flex-order:4;-webkit-order:4;order:4}.small-order-5{-webkit-box-ordinal-group:6;-ms-flex-order:5;-webkit-order:5;order:5}.small-order-6{-webkit-box-ordinal-group:7;-ms-flex-order:6;-webkit-order:6;order:6}@media print,screen and (min-width:40em){.medium-order-1{-webkit-box-ordinal-group:2;-ms-flex-order:1;-webkit-order:1;order:1}.medium-order-2{-webkit-box-ordinal-group:3;-ms-flex-order:2;-webkit-order:2;order:2}.medium-order-3{-webkit-box-ordinal-group:4;-ms-flex-order:3;-webkit-order:3;order:3}.medium-order-4{-webkit-box-ordinal-group:5;-ms-flex-order:4;-webkit-order:4;order:4}.medium-order-5{-webkit-box-ordinal-group:6;-ms-flex-order:5;-webkit-order:5;order:5}.medium-order-6{-webkit-box-ordinal-group:7;-ms-flex-order:6;-webkit-order:6;order:6}}@media print,screen and (min-width:64em){.large-order-1{-webkit-box-ordinal-group:2;-ms-flex-order:1;-webkit-order:1;order:1}.large-order-2{-webkit-box-ordinal-group:3;-ms-flex-order:2;-webkit-order:2;order:2}.large-order-3{-webkit-box-ordinal-group:4;-ms-flex-order:3;-webkit-order:3;order:3}.large-order-4{-webkit-box-ordinal-group:5;-ms-flex-order:4;-webkit-order:4;order:4}.large-order-5{-webkit-box-ordinal-group:6;-ms-flex-order:5;-webkit-order:5;order:5}.large-order-6{-webkit-box-ordinal-group:7;-ms-flex-order:6;-webkit-order:6;order:6}}.flex-container{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex}.flex-child-auto{-webkit-box-flex:1;-webkit-flex:1 1 auto;-ms-flex:1 1 auto;flex:1 1 auto}.flex-child-grow{-webkit-box-flex:1;-webkit-flex:1 0 auto;-ms-flex:1 0 auto;flex:1 0 auto}.flex-child-shrink{-webkit-box-flex:0;-webkit-flex:0 1 auto;-ms-flex:0 1 auto;flex:0 1 auto}.flex-dir-row{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row}.flex-dir-row-reverse{-webkit-box-orient:horizontal;-webkit-box-direction:reverse;-webkit-flex-direction:row-reverse;-ms-flex-direction:row-reverse;flex-direction:row-reverse}.flex-dir-column{-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column}.flex-dir-column-reverse{-webkit-box-orient:vertical;-webkit-box-direction:reverse;-webkit-flex-direction:column-reverse;-ms-flex-direction:column-reverse;flex-direction:column-reverse}@media print,screen and (min-width:40em){.medium-flex-container{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex}.medium-flex-child-auto{-webkit-box-flex:1;-webkit-flex:1 1 auto;-ms-flex:1 1 auto;flex:1 1 auto}.medium-flex-child-grow{-webkit-box-flex:1;-webkit-flex:1 0 auto;-ms-flex:1 0 auto;flex:1 0 auto}.medium-flex-child-shrink{-webkit-box-flex:0;-webkit-flex:0 1 auto;-ms-flex:0 1 auto;flex:0 1 auto}.medium-flex-dir-row{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row}.medium-flex-dir-row-reverse{-webkit-box-orient:horizontal;-webkit-box-direction:reverse;-webkit-flex-direction:row-reverse;-ms-flex-direction:row-reverse;flex-direction:row-reverse}.medium-flex-dir-column{-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column}.medium-flex-dir-column-reverse{-webkit-box-orient:vertical;-webkit-box-direction:reverse;-webkit-flex-direction:column-reverse;-ms-flex-direction:column-reverse;flex-direction:column-reverse}}@media print,screen and (min-width:64em){.large-flex-container{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex}.large-flex-child-auto{-webkit-box-flex:1;-webkit-flex:1 1 auto;-ms-flex:1 1 auto;flex:1 1 auto}.large-flex-child-grow{-webkit-box-flex:1;-webkit-flex:1 0 auto;-ms-flex:1 0 auto;flex:1 0 auto}.large-flex-child-shrink{-webkit-box-flex:0;-webkit-flex:0 1 auto;-ms-flex:0 1 auto;flex:0 1 auto}.large-flex-dir-row{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row}.large-flex-dir-row-reverse{-webkit-box-orient:horizontal;-webkit-box-direction:reverse;-webkit-flex-direction:row-reverse;-ms-flex-direction:row-reverse;flex-direction:row-reverse}.large-flex-dir-column{-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column}.large-flex-dir-column-reverse{-webkit-box-orient:vertical;-webkit-box-direction:reverse;-webkit-flex-direction:column-reverse;-ms-flex-direction:column-reverse;flex-direction:column-reverse}}.hide{display:none!important}.invisible{visibility:hidden}.visible{visibility:visible}@media print,screen and (max-width:39.99875em){.hide-for-small-only{display:none!important}}@media screen and (max-width:0em),screen and (min-width:40em){.show-for-small-only{display:none!important}}@media print,screen and (min-width:40em){.hide-for-medium{display:none!important}}@media screen and (max-width:39.99875em){.show-for-medium{display:none!important}}@media print,screen and (min-width:40em)and (max-width:63.99875em){.hide-for-medium-only{display:none!important}}@media screen and (max-width:39.99875em),screen and (min-width:64em){.show-for-medium-only{display:none!important}}@media print,screen and (min-width:64em){.hide-for-large{display:none!important}}@media screen and (max-width:63.99875em){.show-for-large{display:none!important}}@media print,screen and (min-width:64em)and (max-width:74.99875em){.hide-for-large-only{display:none!important}}@media screen and (max-width:63.99875em),screen and (min-width:75em){.show-for-large-only{display:none!important}}.show-for-sr,.show-on-focus{clip:rect(0,0,0,0)!important;border:0!important;height:1px!important;overflow:hidden!important;padding:0!important;position:absolute!important;white-space:nowrap!important;width:1px!important}.show-on-focus:active,.show-on-focus:focus{clip:auto!important;height:auto!important;overflow:visible!important;position:static!important;white-space:normal!important;width:auto!important}.hide-for-portrait,.show-for-landscape{display:block!important}@media screen and (orientation:landscape){.hide-for-portrait,.show-for-landscape{display:block!important}}@media screen and (orientation:portrait){.hide-for-portrait,.show-for-landscape{display:none!important}}.hide-for-landscape,.show-for-portrait{display:none!important}@media screen and (orientation:landscape){.hide-for-landscape,.show-for-portrait{display:none!important}}@media screen and (orientation:portrait){.hide-for-landscape,.show-for-portrait{display:block!important}}.show-for-dark-mode{display:none}.hide-for-dark-mode{display:block}@media screen and (prefers-color-scheme:dark){.show-for-dark-mode{display:block!important}.hide-for-dark-mode{display:none!important}}.show-for-ie{display:none}@media (-ms-high-contrast:active),(-ms-high-contrast:none){.show-for-ie{display:block!important}.hide-for-ie{display:none!important}}.show-for-sticky{display:none}.is-stuck .show-for-sticky{display:block}.is-stuck .hide-for-sticky{display:none}@font-face{font-display:"swap";font-family:FontAwesome}html{box-sizing:border-box}body{font-family:Roboto,sans-serif;font-size:16px;line-height:1}*,:after,:before{box-sizing:inherit}a{color:#3c4fe0}a.reference:after{font-family:FontAwesome;font-size:12px;padding:0 4px}a.reference.external:after{content:""}a.reference.download:after{content:""}a:hover{color:#3c4fe0;font-weight:500}.headerlink{margin-left:5px;visibility:hidden}.toc-backref:hover{color:#23263b}h1,h2,h3,h4,h5,h6{font-family:Roboto,sans-serif;font-size:16px;font-weight:500;letter-spacing:.2px;line-height:24px;margin-bottom:16px}h1:hover>a.headerlink,h2:hover>a.headerlink,h3:hover>a.headerlink,h4:hover>a.headerlink,h5:hover>a.headerlink,h6:hover>a.headerlink{visibility:visible}h1 a,h2 a,h3 a,h4 a,h5 a,h6 a{color:inherit}h1{font-size:32px;font-weight:700;line-height:40px;margin-bottom:28px}h2{font-size:24px;line-height:32px}h3{font-size:20px}h4{font-size:18px}h5{font-size:16px}h6{font-weight:400}img{max-width:100%}button:focus{outline:0}blockquote{border:0;margin:0;padding:0}blockquote,blockquote p,cite{color:inherit}cite{display:inline;font-size:inherit}cite:before{content:""}.show{display:block!important}.centered{display:block;margin:0 auto}.break{flex-basis:100%;height:0}@media screen and (min-width:1024px){h1{font-size:36px}}.admonition-title:before,.contents.local>ul>li a:before,.scylla-icon,.secondary-side-nav__content li a:before{background-repeat:no-repeat;background-size:contain;display:inline-block;filter:brightness(0);vertical-align:middle}.scylla-icon--about-team{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMSwuY2xzLTJ7ZmlsbDpub25lO3N0cm9rZTpncmF5O3N0cm9rZS1taXRlcmxpbWl0OjEwfS5jbHMtMntzdHJva2UtbGluZWNhcDpyb3VuZH08L3N0eWxlPjwvZGVmcz48ZyBpZD0iQ2FscXVlXzQiIGRhdGEtbmFtZT0iQ2FscXVlIDQiPjxwYXRoIGNsYXNzPSJjbHMtMSIgZD0iTTQuNjYgOS44MSAyLjYzIDExYTIuMDggMi4wOCAwIDAgMC0xLjEzIDEuODN2Ny44MWMuMTkgMS4xMS41IDEuNTMgMS41IDEuNDdNNy4wNiA5Ljk0bDEuNDQuOTQiLz48cGF0aCBjbGFzcz0iY2xzLTIiIGQ9Ik0zLjUgMTguNXY1LjM0TTkuNSAxOC41djUuMzRNOC41NCAxOC40MnY1LjMzTTE1LjUgMTguNXY1LjM0TTE2LjUgMTguNXY1LjM0TTMuMzMgMjAuNTNoNS4wOE0xMS40NSA4Ljg0bC4wNi4wNmExLjY1IDEuNjUgMCAwIDAgMi4zNCAwaDAiLz48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Ik0xMi40MiA3LjVhMS44MSAxLjgxIDAgMCAxLTEuOTItMS43N1Y1YTEuOTQgMS45NCAwIDAgMSAxLjkyLTIgMi4wNyAyLjA3IDAgMCAxIDIuMDggMnYuNzdhMiAyIDAgMCAxLTIuMDggMS43M1pNMTEuNDIgOC43NCA5LjYzIDkuOWEyLjA3IDIuMDcgMCAwIDAtMS4xMyAxLjg1djcuODJBMS40NyAxLjQ3IDAgMCAwIDEwIDIxTTEzLjc1IDkuMThsMiAuNjVjLjcuMzUuNzYgMS4wNi43NiAxLjg0djcuOWMwIC43Ny0uMjMgMS4yNC0xIDEuMjQiLz48cGF0aCBjbGFzcz0iY2xzLTIiIGQ9Ik05LjkzIDE5LjVoNS40Ii8+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNMTkuNDIgOS4xMmEyLjA3IDIuMDcgMCAwIDAgMi4wOC0xLjkzdi0uNzdhMi4wNyAyLjA3IDAgMCAwLTIuMDgtMS45MiAxLjkzIDEuOTMgMCAwIDAtMS45MiAxLjkydi43N2ExLjk0IDEuOTQgMCAwIDAgMS45MiAxLjkzWk01LjU5IDkuMTJhMS45MyAxLjkzIDAgMCAwIDEuOTItMS45M3YtLjc3QTEuOTMgMS45MyAwIDAgMCA1LjU5IDQuNSAyLjA4IDIuMDggMCAwIDAgMy41IDYuNDJ2Ljc3YTIuMDggMi4wOCAwIDAgMCAyLjA5IDEuOTNaTTIwLjQ0IDkuODFsMiAxLjE3YTIuMDYgMi4wNiAwIDAgMSAxLjEzIDEuODV2Ny44MWMtLjE4IDEuMTEtLjQ3IDEuNTMtMS40NyAxLjQ3TTE4LjA0IDkuOTRsLTEuNDQuOTMiLz48cGF0aCBjbGFzcz0iY2xzLTIiIGQ9Ik0yMS42IDE4LjV2NS4zNE0yMS43NyAyMC41M2gtNS4wOCIvPjwvZz48L3N2Zz4=)}.scylla-icon--about-us{background-image:url(data:image/svg+xml;base64,PHN2ZyBpZD0iTGF5ZXJfMyIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB2aWV3Qm94PSIwIDAgMjAgMjAiPjxkZWZzPjxzdHlsZT4uY2xzLTF7ZmlsbDpub25lO3N0cm9rZTojMDAwO3N0cm9rZS1saW5lY2FwOnJvdW5kO3N0cm9rZS1saW5lam9pbjpyb3VuZDtzdHJva2Utd2lkdGg6LjhweH08L3N0eWxlPjwvZGVmcz48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Ik02LjI4IDE5LjQ4Yy0uMTIuMDgtLjA4LjA3LS4yMy4xLS41OC4wOS0xLjEyLS4yOC0xLjI1LS44NCAwIDAtMi4zLTkuMTgtMi4zLTExLjExQzIuNSAzLjYgNS44OC40NCAxMC4zOC40NFMxNy41IDMuNDggMTcuNSA3LjVjMCAxLjkzLTEuMzIgMTEuMjMtMS4zMiAxMS4yMy0uMTMuNTYtLjY3Ljk0LTEuMjUuODQtLjEyLS4wMi0uMTMgMC0uMjMtLjA3Ii8+PHBhdGggZD0iTTE1Ljc1IDE1Ljc1Yy0uMTcgMS4xNS0uMjIgMi4zNC0uNTUgMy40Ni0uMzcuODUtMS42MyAxLjA2LTIuMjIuMzMtLjI1LS4yOC4xOS0uNjguNDQtLjQuNDMuNDYgMS4yNC4xOCAxLjMxLS40NGwuMDYtLjM0Yy4xOS0uODkuMzUtMS43OS41Ny0yLjY4LjA1LS4yNC40Mi0uMTcuMzkuMDdaIi8+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNMTEuNSA3YzAgMS45LTEuNTYgMy41LTMuNDYgMy41UzQuNSA4LjkgNC41IDdzMS42NC0zLjUgMy41NC0zLjVTMTEuNSA1LjEgMTEuNSA3WiIvPjxwYXRoIGQ9Ik04LjU1IDQuNzVjLS41OS4xMi0uNzEgMS40Mi0uMzYgMS43OC4yMy4yMy43MS4zMS43MS40N3MtLjQ4LjI0LS43MS40N2MtLjM2LjM2LS4yNCAxLjY2LjM2IDEuNzguNzEuMTQgMS43OC0uNzEgMS43OC0yLjI1UzkuMjYgNC42MSA4LjU1IDQuNzVaTTYuNTEgMTIuMmMyLjEyLjMxIDQuMzQtLjIgNS42OC0xLjk2LjMyLS40MS45Ni4xMS42Mi41MS0uNzYuOS0xLjc4IDEuNjMtMi45MyAxLjk1LTEuMTQuMzMtMi4zMy4zMS0zLjQ2LjE2YS4zNC4zNCAwIDAgMS0uMjktLjM4Yy4wMi0uMTguMTktLjMxLjM3LS4yOVpNNy45NyAxOS41OWMtLjk5Ljk2LTIuMzYuMDgtMi4zNi0xLjE1LS4xMi0uOS0uMjctMS43OS0uMzctMi42OS0uMDEtLjExLjA3LS4yMS4xOC0uMjIuMS0uMDEuMTkuMDYuMjEuMTUuMjIuODguMzggMS43Ny41NiAyLjY2LjAxLjc4LjY4IDEuMzggMS4zNS44My4yNy0uMjcuNjkuMTYuNDIuNDNaIi8+PHBhdGggZD0iTTkuNzUgMTkuMjdjLS40Mi45LTEuOC45Ni0yLjMyLjExLS41LTEuMTMtLjMxLTIuNS0uNDctMy43MiAwLS4xMS4wOC0uMi4xOS0uMjEuMSAwIC4xOS4wNy4yMS4xNy4xNy45NS4yOCAxLjkxLjQyIDIuODcuMDEuNDUuMjMuNzQuNTcuODUuMzMuMS43MS0uMDUuODgtLjM2LjE4LS4zNC43MS0uMDUuNTIuMjlaTTE0LjAzIDE1LjY2Yy0uMTYgMS4yMy4wMyAyLjU3LS40NiAzLjcyLS41Mi44Ni0xLjkxLjc5LTIuMzItLjExLS4xNy0uMzQuMzUtLjYxLjUzLS4yOC40Mi43MSAxLjQ4LjM4IDEuNDUtLjQ5LjE0LS45Ni4yNS0xLjkyLjQyLTIuODcuMDQtLjI0LjQxLS4yLjQuMDRaIi8+PHBhdGggZD0iTTExLjg1IDE1LjU0Yy4wMi43OS4wMSAxLjU4LjAxIDIuMzctLjAyLjQxLjA3LjktLjE0IDEuMjktLjQzIDEuMDItMi4wMSAxLjAyLTIuNDUgMC0uMjEtLjM5LS4xMy0uODktLjE0LTEuMjkgMC0uNzkgMC0xLjU4LjAxLTIuMzcgMC0uMTEuMS0uMi4yMS0uMTkuMSAwIC4xOC4wOC4xOS4xOC4wNy43OS4xIDEuNTguMTUgMi4zNy4wMy4yNyAwIC44Mi4xMyAxLjA0LjEzLjI2LjQuNDMuNjguNDIuNDYgMCAuNzktLjQuNzctLjg3bC4wMy0uNTljLjA0LS43OS4wOC0xLjU4LjE1LTIuMzcuMDItLjI0LjQtLjIzLjQuMDFaIi8+PC9zdmc+)}.scylla-icon--about-us-m{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNi4zOCAzMi40MyI+PHBhdGggZD0iTTYuNTUgMzEuNjRjLS4yLjEzLS40My4yMi0uNjkuMjZhMS44MSAxLjgxIDAgMCAxLTIuMDYtMS4zOVMuNDkgMTQuOTkuNDkgMTEuODJDLjUgNS4xOSA1Ljc3LjUgMTMuMTkuNXMxMi42OSA0LjY5IDEyLjY5IDExLjMyYzAgMy4xOC0zLjMxIDE4LjY5LTMuMzEgMTguNjlhMS44MSAxLjgxIDAgMCAxLTIuNjIgMS4yIiBzdHlsZT0iZmlsbDpub25lO3N0cm9rZTojMDAwO3N0cm9rZS1saW5lY2FwOnJvdW5kO3N0cm9rZS1saW5lam9pbjpyb3VuZCIvPjxwYXRoIGQ9Ik0yMS44NiAyNS4zNmMtLjI4IDEuOS0uMzcgMy44Ni0uOTEgNS43MS0uNjEgMS40MS0yLjY4IDEuNzUtMy42Ni41NS0uNDEtLjQ3LjMxLTEuMTEuNzMtLjY2LjcxLjc2IDIuMDQuMjkgMi4xNi0uNzMuMzItMS42Ni42NS0zLjMzIDEuMDQtNC45OC4wOS0uMzkuNy0uMjguNjUuMTFaIi8+PHBhdGggZD0iTTE0LjggMTAuNTdjMCAzLjEzLTIuNTMgNS42Ni01LjY2IDUuNjZzLTUuNDctMi41My01LjQ3LTUuNjYgMi4zNC01LjY2IDUuNDctNS42NiA1LjY2IDIuNTMgNS42NiA1LjY2WiIgc3R5bGU9InN0cm9rZS13aWR0aDouOXB4O2ZpbGw6bm9uZTtzdHJva2U6IzAwMDtzdHJva2UtbGluZWNhcDpyb3VuZDtzdHJva2UtbGluZWpvaW46cm91bmQiLz48cGF0aCBkPSJNMTAuMzEgNi44NmMtLjk4LjItMS4xNyAyLjM0LS41OSAyLjkzLjM4LjM4IDEuMTcuNTEgMS4xNy43OHMtLjc5LjQtMS4xNy43OGMtLjU5LjU5LS4zOSAyLjczLjU5IDIuOTMgMS4xNi4yMyAyLjkzLTEuMTcgMi45My0zLjcxcy0xLjc2LTMuOTQtMi45My0zLjcxWk02LjgyIDE4LjUxYzMuNDkuODkgNi45Ny0uNSA5LjUxLTIuOTMuNDctLjQ0IDEuMTYuMzEuNjguNzQtMS4zOCAxLjIzLTIuOTggMi4yOS00Ljc5IDIuODctMS44LjU5LTMuNzcuNTgtNS41OC4xNGEuNDIxLjQyMSAwIDAgMS0uMzEtLjVjLjA1LS4yMi4yOC0uMzYuNS0uMzFaIi8+PHBhdGggZD0iTTE2LjczIDE2LjY3Yy0uMTItLjQ2LS41MS0uODMtLjk5LS44My0uNzUtLjAyLS41OS0xLjE3LjE0LS45OS44MS4xNiAxLjQzLjg1IDEuNSAxLjY2LjA4LjQtLjU0LjU0LS42NS4xNVpNOS4wMyAzMS43Yy0xLjI2IDEuMzYtMy42Mi40NS0zLjgtMS4zNWwtLjA5LS41NWMtLjIxLTEuNDgtLjQ1LTIuOTUtLjYtNC40NC0uMDItLjE4LjExLS4zNC4yOS0uMzYuMTctLjAyLjMyLjA5LjM1LjI1LjM5IDEuNjMuNzEgMy4yOCAxLjAzIDQuOTMuMDkgMS4wMiAxLjM4IDEuNTQgMi4xMi44MS40NS0uNDQgMS4xNC4yNi42OS43WiIvPjxwYXRoIGQ9Ik0xMS45NiAzMS4xNmMtMSAxLjk4LTQuMDQgMS4zLTQuMjEtLjg4LS4xNS0xLjY5LS4zLTMuMzgtLjM5LTUuMDcgMC0uMTguMTMtLjM0LjMxLS4zNC4xNyAwIC4zMS4xMS4zNC4yNy4yOCAxLjY3LjUgMy4zNS43MiA1LjAzLjA5IDEuMiAxLjc3IDEuNTkgMi4zNi41MS4zMS0uNTYgMS4xNi0uMDkuODcuNDdaTTE5LjAzIDI1LjIxYy0uMDggMS42OS0uMjQgMy4zOC0uMzkgNS4wNy0uMDQuMzctLjE3Ljc1LS4zOCAxLjA2LS44NiAxLjQtMy4xMSAxLjMxLTMuODMtLjE3LS4zLS41Ni41NS0xLjAzLjg2LS40OC41OSAxLjA4IDIuMjcuNjkgMi4zNS0uNTIuMjItMS42OC40My0zLjM2LjcyLTUuMDMuMDYtLjQuNjgtLjMzLjY1LjA3WiIvPjxwYXRoIGQ9Ik0xNS40MyAyNS4wMmMuMDQgMS4zMS4wMiAyLjYxLjAyIDMuOTEtLjAzLjY3LjExIDEuNDgtLjIzIDIuMTMtLjc0IDEuNjktMy4yOSAxLjY5LTQuMDMgMC0uMzQtLjY1LS4yMS0xLjQ3LS4yNC0yLjEzIDAtMS4zLS4wMi0yLjYxLjAyLTMuOTEgMC0uMTguMTYtLjMyLjM0LS4zMi4xNyAwIC4zLjE0LjMyLjMuMTEgMS4zLjE3IDIuNi4yNCAzLjkxLjA1LjQ1IDAgMS4zNS4yMSAxLjcyLjIxLjQzLjY2LjcxIDEuMTIuNy40Ni4wMi45MS0uMjcgMS4xMi0uNjkuMjItLjM2LjE2LTEuMjguMjEtMS43Mi4wNy0xLjMuMTMtMi42MS4yNC0zLjkxLjAyLS40LjY2LS4zOC42Ni4wMloiLz48L3N2Zz4=)}.scylla-icon--alternator{background-image:url(data:image/svg+xml;base64,PHN2ZyBpZD0iTGF5ZXJfMyIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB2aWV3Qm94PSIwIDAgMjAgMjAiPjxkZWZzPjxzdHlsZT4uY2xzLTF7ZmlsbDpub25lO3N0cm9rZTojMDAwO3N0cm9rZS1saW5lY2FwOnJvdW5kO3N0cm9rZS1saW5lam9pbjpyb3VuZH08L3N0eWxlPjwvZGVmcz48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Ik0xNy41IDIuOTFjMCAxLjI4LTMuNjcgMi41OS04IDIuNTlzLTgtMS4zMS04LTIuNTlTNS4wOS41IDkuNDIuNXM4LjA4IDEuMTMgOC4wOCAyLjQxWk0xNy41IDcuNjZjMCAxLjI4LTMuNjMgMi44LTcuOTYgMi44UzEuNSA4LjkzIDEuNSA3LjY2TTE3LjUgMTIuNDdjMCAxLjI4LTMuNjcgMy4wMy04IDMuMDNzLTgtMS43NS04LTMuMDNNMTcuNSAxNy4yOWMwIDEuMjgtMy43NSAyLjMtOC4wOCAyLjNzLTcuOTItMS4wMy03LjkyLTIuM00xLjUgMTcuMTlWMi45MU0xNy41IDE3LjE5VjIuOTEiLz48L3N2Zz4=)}.scylla-icon--apps{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyMSAxOSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOm5vbmU7c3Ryb2tlOiM0ZDRkNGQ7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJDYWxxdWVfNCIgZGF0YS1uYW1lPSJDYWxxdWUgNCI+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNLjUgMS41aDIwdjE0SC41ek03LjUgMTUuNzR2Mi44OU0xMi44MyAxNS42M3YyLjMyTTUuNSAxOC41aDkuMTQiLz48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Im0zLjY0IDUuNTYgNC41OCAyLjkxLTQuNTggMi45Mk05LjEgMTIuMDhoNC4zMiIvPjwvZz48L3N2Zz4=)}.scylla-icon--architecture{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMSwuY2xzLTIsLmNscy01e2ZpbGw6bm9uZTtzdHJva2U6Z3JheX0uY2xzLTF7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfS5jbHMtMiwuY2xzLTV7c3Ryb2tlLW1pdGVybGltaXQ6MTB9LmNscy0ye3N0cm9rZS13aWR0aDouOThweH0uY2xzLTV7c3Ryb2tlLXdpZHRoOi45OXB4fTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJDYWxxdWVfMiIgZGF0YS1uYW1lPSJDYWxxdWUgMiI+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNMS45IDEwLjI3YTEwLjgzIDEwLjgzIDAgMCAxIDguNzMtOC4zOE0xMC41MSAyMy4wOEExMC43OSAxMC43OSAwIDAgMSAxLjc3IDE0TTIzLjIzIDE0YTEwLjgxIDEwLjgxIDAgMCAxLTkgOS4xMU0xNC4yNyAxLjg4YTEwLjgxIDEwLjgxIDAgMCAxIDguODMgOC4zNyIvPjxjaXJjbGUgY2xhc3M9ImNscy0yIiBjeD0iMTIuMjUiIGN5PSIxLjc1IiByPSIxLjc1Ii8+PGNpcmNsZSBjbGFzcz0iY2xzLTIiIGN4PSIxMi4yNSIgY3k9IjIyLjc1IiByPSIxLjc1Ii8+PGNpcmNsZSBjeD0iNC45MiIgY3k9IjQuNzUiIHI9IjEuNzUiIHN0eWxlPSJzdHJva2Utd2lkdGg6Ljk5cHg7ZmlsbDpncmF5O3N0cm9rZS1taXRlcmxpbWl0OjEwO3N0cm9rZTpncmF5Ii8+PGNpcmNsZSBjeD0iMjAuMDkiIGN5PSIxOS45MSIgcj0iMS43NSIgc3R5bGU9InN0cm9rZS13aWR0aDouOTlweDtmaWxsOmdyYXk7c3Ryb2tlLW1pdGVybGltaXQ6MTA7c3Ryb2tlOmdyYXkiLz48Y2lyY2xlIGNsYXNzPSJjbHMtNSIgY3g9IjEuNzUiIGN5PSIxMi4yNSIgcj0iMS43NSIvPjxjaXJjbGUgY2xhc3M9ImNscy01IiBjeD0iMjMuMjUiIGN5PSIxMi4yNSIgcj0iMS43NSIvPjxjaXJjbGUgY3g9IjQuNzUiIGN5PSIxOS42NCIgcj0iMS43NSIgc3R5bGU9InN0cm9rZS13aWR0aDouOTlweDtmaWxsOmdyYXk7c3Ryb2tlLW1pdGVybGltaXQ6MTA7c3Ryb2tlOmdyYXkiLz48Y2lyY2xlIGN4PSIxOS45MSIgY3k9IjQuNDgiIHI9IjEuNzUiIHN0eWxlPSJzdHJva2Utd2lkdGg6Ljk5cHg7ZmlsbDpncmF5O3N0cm9rZS1taXRlcmxpbWl0OjEwO3N0cm9rZTpncmF5Ii8+PC9nPjwvc3ZnPg==)}.scylla-icon--benchmarks{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVqb2luOnJvdW5kO3N0cm9rZS13aWR0aDozcHh9PC9zdHlsZT48L2RlZnM+PGcgaWQ9IkNhbHF1ZV8yIiBkYXRhLW5hbWU9IkNhbHF1ZSAyIj48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Ik01LjUxIDI0Ljkxdi01Ljg1TTEyLjU3IDI0Ljkxdi05Ljc0TTE5LjYyIDI0LjkxVjEwLjE1Ii8+PHBhdGggc3R5bGU9InN0cm9rZS1saW5lY2FwOnJvdW5kO2ZpbGw6bm9uZTtzdHJva2U6Z3JheTtzdHJva2UtbGluZWpvaW46cm91bmQiIGQ9Im0uOTEgMTQuOTggNS4xMy03Ljk0IDYuMjUgNS44OEwyNCAxIi8+PHBhdGggc3R5bGU9ImZpbGw6Z3JheSIgZD0ibTI1IDUtNS01aDV2NXoiLz48L2c+PC9zdmc+)}.scylla-icon--blog{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJDYWxxdWVfNCIgZGF0YS1uYW1lPSJDYWxxdWUgNCI+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJtOSAxNS0yLjUtMS41IDgtMTJMMTcgMyA5IDE1eiIvPjxwYXRoIHN0eWxlPSJmaWxsOmdyYXk7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kIiBkPSJtNi41IDEzLjUtLjUgM0w5IDE1bC0yLjUtMS41eiIvPjxwYXRoIGNsYXNzPSJjbHMtMSIgZD0iTTE5LjI1IDIuNWg0LjI1djE2aC0xM3Y0LjE3TDYuNDYgMTguNWwtNC45Ni0uMDRWMi41aDguMzFNMTQuNSAyLjVsMS42NyAxLjMzIi8+PC9nPjwvc3ZnPg==)}.scylla-icon--careers{background-image:url(data:image/svg+xml;base64,PHN2ZyBpZD0iQ2FscXVlXzEiIGRhdGEtbmFtZT0iQ2FscXVlIDEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmlld0JveD0iMCAwIDI1IDI1Ij48ZGVmcz48c3R5bGU+LmNscy0xe2ZpbGw6bm9uZTtzdHJva2U6Z3JheTtzdHJva2UtbGluZWNhcDpyb3VuZDtzdHJva2UtbGluZWpvaW46cm91bmR9PC9zdHlsZT48L2RlZnM+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNMS41IDExLjU1djhjMCAuNTYgMS4wNyAyIDIgMmgxOGMuODkgMCAyLTEuNDQgMi0ydi04Ii8+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNMjMuMzEgMy41SDEuODFjLS40OCAwLTEuMzEuNTUtMS4zMSAxdjZsMTAgMmE4LjQ1IDguNDUgMCAwIDAgNCAwbDEwLTJ2LTZjMC0uNDUtLjcyLTEtMS4xOS0xWk0xNS42MiAzLjV2LTFjMC0uNzYtLjYxLTEtMS4zOC0xaC0zLjQ1Yy0uNzYgMC0xLjM4LjI0LTEuMzggMXYxIi8+PHJlY3QgeD0iMTAiIHk9IjExIiB3aWR0aD0iNSIgaGVpZ2h0PSIzLjk5IiByeD0iLjU1IiByeT0iLjU1IiBzdHlsZT0iZmlsbDpncmF5Ii8+PC9zdmc+)}.scylla-icon--chevron-left{background-image:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTAiIGhlaWdodD0iMTYiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZD0iTTguMDkyIDE2IDEwIDE0LjExMyAzLjgxNyA4IDEwIDEuODg3IDguMDkyIDAgMCA4bDguMDkyIDhaIiBmaWxsPSIjMDAwIi8+PC9zdmc+)}.contents.local>ul>li a:before,.scylla-icon--chevron-right,.secondary-side-nav__content li a:before{background-image:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTAiIGhlaWdodD0iMTYiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZD0iTTEuOTA4IDAgMCAxLjg4NyA2LjE4MyA4IDAgMTQuMTEzIDEuOTA4IDE2IDEwIDggMS45MDggMFoiIGZpbGw9IiMwMDAiLz48L3N2Zz4=)}.scylla-icon--circe{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAzOCAzMCI+PGRlZnM+PHN0eWxlPi5jbHMtMiwuY2xzLTN7ZmlsbDpub25lO3N0cm9rZTojNGQ0ZDRkO3N0cm9rZS1saW5lY2FwOnJvdW5kO3N0cm9rZS1saW5lam9pbjpyb3VuZH0uY2xzLTN7c3Ryb2tlLXdpZHRoOjEuMTFweH08L3N0eWxlPjwvZGVmcz48ZyBpZD0iQ2FscXVlXzQiIGRhdGEtbmFtZT0iQ2FscXVlIDQiPjxwYXRoIGQ9Ik0yMi4xIDEyaC02LjE2YTEuMDYgMS4wNiAwIDAgMS0uOTQtMS4wNy45My45MyAwIDAgMSAuOTQtLjkzaDYuMTZhLjkzLjkzIDAgMCAxIC45NC45M0ExLjA2IDEuMDYgMCAwIDEgMjIuMSAxMloiIHN0eWxlPSJmaWxsOiM0ZDRkNGQiLz48cGF0aCBjbGFzcz0iY2xzLTIiIGQ9Ik0xMy40NCA0LjQ5SDkuNTF2MjRoMTl2LTI0SDI0LjUiLz48cGF0aCBjbGFzcz0iY2xzLTMiIGQ9Ik0xMyAzLjQ5SDguNWwtLjA4IDI2LjFIMjkuNVYzLjM5SDI1Ii8+PHBhdGggY2xhc3M9ImNscy0yIiBkPSJNMTIuNSAxOC4zOGgxM00xMi41IDE1LjQ5aDEzTTEyLjUgMjEuNDNoMTNNMTIuNSAyNC40N2gxM00xMy41IDIuNWgxMXYzLjk4aC0xMXoiLz48cGF0aCBjbGFzcz0iY2xzLTMiIGQ9Ik0yMS41LjVoLTUuMDR2MS45NWw1LjA0LjA1di0yeiIvPjwvZz48L3N2Zz4=)}.scylla-icon--clock{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyMSAxOSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOm5vbmU7c3Ryb2tlOiM0ZDRkNGQ7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJDYWxxdWVfNCIgZGF0YS1uYW1lPSJDYWxxdWUgNCI+PGNpcmNsZSBjbGFzcz0iY2xzLTEiIGN4PSIxMC41IiBjeT0iOS41IiByPSI5Ii8+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNMTAuNSAzLjV2NmwzLjA2IDMiLz48L2c+PC9zdmc+)}.scylla-icon--close{background-image:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMzQiIGhlaWdodD0iMzQiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGcgY2xpcC1wYXRoPSJ1cmwoI2EpIiBmaWxsPSIjZmZmIj48cGF0aCBkPSJNMTEuNjcgMjIuMTNhLjU2NC41NjQgMCAwIDEtLjM5OC0uOTYybDkuODk2LTkuODk2YS41NjMuNTYzIDAgMSAxIC43OTcuNzk3bC05Ljg5NiA5Ljg5NmEuNTU5LjU1OSAwIDAgMS0uMzk5LjE2NVoiLz48cGF0aCBkPSJNMjEuNTY2IDIyLjEzYS41NTkuNTU5IDAgMCAxLS4zOTgtLjE2NWwtOS44OTYtOS44OTZhLjU2My41NjMgMCAxIDEgLjc5Ny0uNzk3bDkuODk2IDkuODk1YS41NjQuNTY0IDAgMCAxLS4zOTkuOTYzWiIvPjxwYXRoIGQ9Ik0xNi42MTkgMzMuMjM3QzcuNDU1IDMzLjIzNyAwIDI1Ljc4MiAwIDE2LjYxOSAwIDcuNDU2IDcuNDU1IDAgMTYuNjE5IDBzMTYuNjE5IDcuNDU1IDE2LjYxOSAxNi42MTktNy40NTYgMTYuNjE4LTE2LjYyIDE2LjYxOFptMC0zMi4xMWMtOC41NDIgMC0xNS40OTIgNi45NS0xNS40OTIgMTUuNDkyIDAgOC41NDIgNi45NSAxNS40OTIgMTUuNDkyIDE1LjQ5MiA4LjU0MiAwIDE1LjQ5Mi02Ljk1IDE1LjQ5Mi0xNS40OTIgMC04LjU0Mi02Ljk1LTE1LjQ5Mi0xNS40OTItMTUuNDkyWiIvPjwvZz48ZGVmcz48Y2xpcFBhdGggaWQ9ImEiPjxwYXRoIGZpbGw9IiNmZmYiIGQ9Ik0wIDBoMzMuMjM3djMzLjIzN0gweiIvPjwvY2xpcFBhdGg+PC9kZWZzPjwvc3ZnPg==)}.scylla-icon--cloud{background-image:url(data:image/svg+xml;base64,PHN2ZyBpZD0iTGF5ZXJfMiIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB2aWV3Qm94PSIwIDAgNDMuMDQgMzIuMDMiPjxkZWZzPjxzdHlsZT4uY2xzLTF7ZmlsbDpub25lO3N0cm9rZTojMWQxZDFiO3N0cm9rZS1saW5lY2FwOnJvdW5kO3N0cm9rZS1saW5lam9pbjpyb3VuZH08L3N0eWxlPjwvZGVmcz48ZyBpZD0iTGF5ZXJfMyI+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNNDIuNTQgNC4wNmMwIDEuNjgtMy42MyAyLjQ0LTkgMi40NHMtMTAtLjczLTEwLTIuNFMyNy42Ny41IDMzLjA0LjVzOS41IDEuODkgOS41IDMuNTZaTTQyLjU0IDkuNjNjMCAxLjY4LTMuNzYgMi45MS05LjEyIDIuOTFzLTkuODQtMS4yMy05Ljg0LTIuOTFNNDIuNTQgMTUuMzRjMCAxLjY4LTMuNjggMy4yNS05LjA0IDMuMjUtNCAwLTcuNi0uOTYtOS4wOS0yLjA0TTQyLjU0IDIwLjY1YzAgMS42OC0zLjcyIDIuOTctOS4wOCAyLjk3TTIzLjU0IDE1LjQ2VjQuMU00Mi41NCAyMC43N1Y0LjEiLz48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Ik0yOC4xMSAyMS4wOGMtLjg3IDAtMS42Ny4yMy0yLjM5LjYxIDAtLjA3LjAxLS4xNC4wMS0uMjEgMC00Ljg1LTMuODMtOC45LTguNjgtOC45cy04Ljg4IDQuMDUtOC44OCA4LjljMCAuMTcuMDIuMzQuMDMuNTEtLjg0LS41Ny0xLjg1LS45MS0yLjk1LS45MS0yLjg4IDAtNC43NCAyLjU3LTQuNzQgNS40NnMxLjg2IDQuOTkgNC43NCA0Ljk5aDIyLjg2YzIuODggMCA1LjUyLTIuMjcgNS41Mi01LjE2cy0yLjYzLTUuMjktNS41Mi01LjI5WiIvPjwvZz48L3N2Zz4=)}.scylla-icon--cloud-docs{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyMSAxOSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOm5vbmU7c3Ryb2tlOiM0ZDRkNGQ7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJDYWxxdWVfNCIgZGF0YS1uYW1lPSJDYWxxdWUgNCI+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNNi41IDExLjVoOHYxaC04ek0xNS42NSA2LjU1YTMuNDIgMy40MiAwIDAgMC0zLjE1IDIiLz48cGF0aCBkPSJNMTAuMDYgMi44QTUuMTcgNS4xNyAwIDAgMSAxNSA2LjM1aC4yNGE0Ljg0IDQuODQgMCAwIDEgMCA5LjY3aC0xMWEzLjQ1IDMuNDUgMCAwIDEgMC02LjlBMy4xNyAzLjE3IDAgMCAxIDUgOS4yIDUuMzMgNS4zMyAwIDAgMSA0Ljg2IDhhNS4yIDUuMiAwIDAgMSA1LjItNS4ybTAtLjhhNiA2IDAgMCAwLTYgNnYuMzFhNC4yNSA0LjI1IDAgMCAwIC4xOCA4LjQ5aDExYTUuNjMgNS42MyAwIDAgMCAuMy0xMS4yNkE2IDYgMCAwIDAgMTAuMDYgMloiIHN0eWxlPSJmaWxsOiM0ZDRkNGQiLz48L2c+PC9zdmc+)}.scylla-icon--comparison{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMSwuY2xzLTIsLmNscy00e2ZpbGw6bm9uZTtzdHJva2U6Z3JheX0uY2xzLTEsLmNscy0ye3N0cm9rZS1taXRlcmxpbWl0OjEwfS5jbHMtMiwuY2xzLTR7c3Ryb2tlLWxpbmVjYXA6cm91bmR9LmNscy00e3N0cm9rZS1saW5lam9pbjpyb3VuZH08L3N0eWxlPjwvZGVmcz48ZyBpZD0iQ2FscXVlXzQiIGRhdGEtbmFtZT0iQ2FscXVlIDQiPjxwYXRoIGNsYXNzPSJjbHMtMSIgZD0iTTQuNSAxMy42M3YyLjg4aDYuMDZNMjAuNSAxMy41NHYyLjk2bC01LjUuMDEiLz48cGF0aCBjbGFzcz0iY2xzLTIiIGQ9Ik0xMi41IDE4LjV2Mi43Mk03LjUgMjEuNWgxMCIvPjxjaXJjbGUgY3g9IjEyLjUiIGN5PSIxNi41IiByPSIyIiBzdHlsZT0iZmlsbDpncmF5O3N0cm9rZS13aWR0aDouOTVweDtzdHJva2UtbWl0ZXJsaW1pdDoxMDtzdHJva2U6Z3JheSIvPjxwYXRoIGNsYXNzPSJjbHMtNCIgZD0iTTUuMDYgMTMuNThIMy44OEEzLjEgMy4xIDAgMCAxIC41IDEwLjVoOGEzLjE2IDMuMTYgMCAwIDEtMy40NCAzLjA4Wk0yMSAxMy41OGgtMS4xN2EzLjA5IDMuMDkgMCAwIDEtMy4zNy0zLjA3aDhBMy4xNiAzLjE2IDAgMCAxIDIxIDEzLjU4Wk03LjQ2IDUuMTJjMCAuNTctMS4xLjQ2LTIuNzkuNDZTMS41OCA1LjYgMS41OCA1IDMgNC40IDQuNjkgNC40czIuNzcuMTYgMi43Ny43MlpNMS41IDkuODVWNS4zMU03LjUgMTAuMzVWNS44MU0yMy41IDUuMTJjMCAuNTctMS4xLjQ2LTIuNzkuNDZzLTMuMDkgMC0zLjA5LS41NFMxOSA0LjQgMjAuNzMgNC40czIuNzcuMTYgMi43Ny43MlpNMTcuNTQgOS44NVY1LjMxTTIzLjU0IDEwLjM1VjUuODEiLz48L2c+PC9zdmc+)}.scylla-icon--contact-us{background-image:url(data:image/svg+xml;base64,PHN2ZyBpZD0iQ2FscXVlXzEiIGRhdGEtbmFtZT0iQ2FscXVlIDEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmlld0JveD0iMCAwIDI1IDI1Ij48ZGVmcz48c3R5bGU+LmNscy0xe2ZpbGw6bm9uZTtzdHJva2U6Z3JheTtzdHJva2UtbGluZWNhcDpyb3VuZDtzdHJva2UtbGluZWpvaW46cm91bmQ7c3Ryb2tlLXdpZHRoOjEuMDZweH08L3N0eWxlPjwvZGVmcz48cGF0aCBjbGFzcz0iY2xzLTEiIHRyYW5zZm9ybT0icm90YXRlKC0yNy40OSAxNS41NTIgMTEuMDgzKSIgZD0iTTcuNzYgNi4wMWgxNS41OXYxMC4xM0g3Ljc2eiIvPjxwYXRoIGNsYXNzPSJjbHMtMSIgZD0ibTYuMyAxMC4xOCA4LjYzIDEuNTZhMS40MiAxLjQyIDAgMCAwIDEuNTMtLjc0bDMuNjctOE0xMS4wMiAxOS4wM2wxLjc0LTVNMjQuNTkgMTEuOTdsLTUuMDktMS40NU03LjA5IDE3LjU4IDMuOSAxOS4zNE02LjA2IDE1LjQxLjU0IDE4LjM2Ii8+PC9zdmc+)}.scylla-icon--developers-blog{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOmdyYXl9PC9zdHlsZT48L2RlZnM+PGcgaWQ9IkNhbHF1ZV80IiBkYXRhLW5hbWU9IkNhbHF1ZSA0Ij48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Im02LjQ4IDEwLjU5LS41LjE3LjUuMTZMMTEgMTIuMTZWMTRsLTctMi40OVYxMGw3LTIuNXYxLjgzWk0xNCA5LjMyVjcuNWw3IDIuNXYxLjU0TDE0IDE0di0xLjgzbDQuMTQtMS4zLjQ0LS4xMy0uNDMtLjE0WiIvPjxwYXRoIHN0eWxlPSJmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kO3N0cm9rZS13aWR0aDouOThweCIgZD0iTTEuNSAyLjVoMjJ2MTZoLTEzdjQuMTdMNi40NiAxOC41bC00Ljk2LS4wNFYyLjV6Ii8+PC9nPjwvc3ZnPg==)}.scylla-icon--docs{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfS5jbHMtMntmaWxsOmdyYXl9PC9zdHlsZT48L2RlZnM+PGcgaWQ9IkNhbHF1ZV80IiBkYXRhLW5hbWU9IkNhbHF1ZSA0Ij48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Ik0zLjUgMi41MWgxNi45NHYyMC45MUgzLjV6Ii8+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJtMjIuNDUgMjEuNS4wNS0yMWgtMTdhMi4xNiAyLjE2IDAgMCAwLTIgMiIvPjxwYXRoIGNsYXNzPSJjbHMtMiIgZD0iTTYgNmg3djJINnpNNiA5aDExdjJINnoiLz48L2c+PC9zdmc+)}.scylla-icon--enterprise{background-image:url(data:image/svg+xml;base64,PHN2ZyBpZD0iTGF5ZXJfMyIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB2aWV3Qm94PSIwIDAgMjAgMjAiPjxkZWZzPjxzdHlsZT4uY2xzLTEsLmNscy0ye2ZpbGw6bm9uZTtzdHJva2U6IzAwMDtzdHJva2UtbGluZWNhcDpyb3VuZDtzdHJva2UtbGluZWpvaW46cm91bmR9LmNscy0ye3N0cm9rZS13aWR0aDoxLjA3cHh9PC9zdHlsZT48L2RlZnM+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJtMTMuNjIgNy41IDEuODgtMS4wOCAyIDIuMDh2N2gxTTE1LjUgMTUuNXYtNSIvPjxwYXRoIGNsYXNzPSJjbHMtMiIgZD0iTTUuNSAxNS41di0xMmw0LTIgNCAydjEyTTkuNSAxNS41VjEuNk03LjUgNS41djEwTTExLjUgNS41djEwIi8+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNNS41IDguNTQgMy40NiA3LjVsLTEuOTYuOTZ2Ny4wNGgtMU0zLjUgMTAuNXY1TS41IDE3LjVoMTgiLz48L3N2Zz4=)}.scylla-icon--enterprise-m{background-image:url(data:image/svg+xml;base64,PHN2ZyB2ZXJzaW9uPSIxLjEiIGlkPSJMYXllcl8yXzAwMDAwMDE2NzY4MDY2MDE5MjYzMjMyNzcwMDAwMDA1NDc1ODA5NTExODI4NjY2MDM2XyIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4PSIwIiB5PSIwIiB2aWV3Qm94PSIwIDAgNDMgMzEiIHN0eWxlPSJlbmFibGUtYmFja2dyb3VuZDpuZXcgMCAwIDQzIDMxIiB4bWw6c3BhY2U9InByZXNlcnZlIj48c3R5bGU+LnN0MHtmaWxsOm5vbmU7c3Ryb2tlOiMxZDFkMWI7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfTwvc3R5bGU+PGcgaWQ9IkxheWVyXzMiPjxwYXRoIGNsYXNzPSJzdDAiIGQ9Im0yOS42IDkuNSA0LTIgNi45IDQuMXYxNS45aDJNMzMuNiAyNy41VjcuNk0xNC42IDI3LjVWNC44TDIyLjUuNSAyOS42IDV2MjIuNU0yMi41IDI3LjVWMU0yNC41IDUuNmwzIDJNMjQuNSA5LjZsMyAyTTI0LjUgMTMuNmwzIDJNMjQuNSAxNy41bDMgMk0yNC41IDIxLjVsMyAyTTM1LjQgMTEuNmwzIDJNMzUuNCAxNS42bDMgMS45TTM1LjQgMTkuNWwzIDJNMzUuNCAyMy41bDMgMS45TTE4LjUgNS44djIxLjdNMTQuNiA5LjdsLTQuMS0yLjUtOCA0LjR2MTUuOWgtMk0xMC41IDI3LjVWNy4yTTEyLjUgMTEuNmwyIDFNMTIuNSAxNS42bDIgLjlNMTIuNSAxOS41bDIgMU0xMi41IDIzLjVsMi4xIDFNNi40IDEyLjR2MTUuMU0uNSAzMC41aDQyIi8+PC9nPjwvc3ZnPg==)}.scylla-icon--events{background-image:url(data:image/svg+xml;base64,PHN2ZyBpZD0iQ2FscXVlXzEiIGRhdGEtbmFtZT0iQ2FscXVlIDEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmlld0JveD0iMCAwIDI1IDI1Ij48ZGVmcz48c3R5bGU+LmNscy0xe2ZpbGw6bm9uZTtzdHJva2U6Z3JheTtzdHJva2UtbGluZWNhcDpyb3VuZDtzdHJva2UtbGluZWpvaW46cm91bmR9LmNscy0ye2ZpbGw6Z3JheX08L3N0eWxlPjwvZGVmcz48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Ik0yMi41IDIzLjVoLTIxdi0yMGgyMnYxNS4yMSIvPjxwYXRoIGNsYXNzPSJjbHMtMSIgZD0iTTQuNDIgMy41YzAtMS4zNiAxLjA5LTIgMi40NS0yYTIuNDYgMi40NiAwIDEgMSAwIDQuOTEgMi42MSAyLjYxIDAgMCAxLTEtLjIxTTEwLjY3IDMuNWMwLTEuMzYgMS4xLTIgMi40Ni0yYTIuNDYgMi40NiAwIDAgMSAwIDQuOTEgMi42MSAyLjYxIDAgMCAxLTEtLjIxTTE2LjkzIDMuNWMwLTEuMzYgMS4xLTIgMi40NS0yYTIuNDYgMi40NiAwIDEgMSAwIDQuOTEgMi41MiAyLjUyIDAgMCAxLTEtLjIxIi8+PHBhdGggY2xhc3M9ImNscy0yIiBkPSJNNyA5aDN2M0g3ek0xMiA5aDN2M2gtM3pNMTcgOWgzdjNoLTN6TTcgMTRoM3YzSDd6TTEyIDE0aDN2M2gtM3pNMTcgMTRoM3YzaC0zeiIvPjxwYXRoIGNsYXNzPSJjbHMtMSIgZD0iTTMuNSAzLjY3djE2LjY2TTMuNSAyMC40M2MwIDEuMjkuNDQgMi4zMyAxLjczIDIuMzNzMi4zMy0xLjkgMi4zMy0zLjE5bDE2Ljk0LS4wN2MwIDEuMjktLjU1IDMuMTItMS44MyAzLjEySDYuMyIvPjwvc3ZnPg==)}.admonition.note .admonition-title:before,.admonition.tip .admonition-title:before,.scylla-icon--exclamation{background-image:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PG1hc2sgaWQ9ImEiIG1hc2stdHlwZT0iYWxwaGEiIG1hc2tVbml0cz0idXNlclNwYWNlT25Vc2UiIHg9IjEiIHk9IjEiIHdpZHRoPSIyMiIgaGVpZ2h0PSIyMiI+PHBhdGggZD0iTTEyIDIzQzUuOSAyMyAxIDE4LjEgMSAxMlM1LjkgMSAxMiAxczExIDQuOSAxMSAxMS00LjkgMTEtMTEgMTFabTAtMjBjLTUgMC05IDQtOSA5czQgOSA5IDkgOS00IDktOS00LTktOS05WiIgZmlsbD0iI2ZmZiIvPjxwYXRoIGQ9Ik0xMiAxM2MtLjYgMC0xLS40LTEtMVY4YzAtLjYuNC0xIDEtMXMxIC40IDEgMXY0YzAgLjYtLjQgMS0xIDFaTTEyIDE3Yy0uMyAwLS41LS4xLS43LS4zLS4yLS4yLS4zLS40LS4zLS43IDAtLjEgMC0uMy4xLS40LjEtLjEuMS0uMi4yLS4zLjMtLjMuNy0uNCAxLjEtLjIuMSAwIC4xIDAgLjIuMSAwIDAgLjEuMS4yLjEuMS4xLjIuMi4yLjN2LjRjMCAuMSAwIC4zLS4xLjQtLjEuMS0uMS4yLS4yLjMtLjIuMi0uNC4zLS43LjNaIiBmaWxsPSIjZmZmIi8+PC9tYXNrPjxnIG1hc2s9InVybCgjYSkiPjxwYXRoIGZpbGw9IiNmZmYiIGQ9Ik0wIDBoMjR2MjRIMHoiLz48L2c+PC9zdmc+)}.collapsible-button i,.scylla-icon--expand{background-image:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYuMDAxIiBoZWlnaHQ9IjE2IiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjxwYXRoIGQ9Ik01IDEzYTEgMSAwIDAgMS0uNzEtLjI5bC00LTRhMSAxIDAgMCAxIDAtMS40MWw0LTRhMSAxIDAgMCAxIDEuNDIgMS40MUwyLjQxIDhsMy4yOSAzLjI5QTEgMSAwIDAgMSA1IDEzeiIvPjxwYXRoIGQ9Ik0xMSA5SDFhMSAxIDAgMCAxIDAtMmgxMGExIDEgMCAwIDEgMCAyek0xNSAxNmExIDEgMCAwIDEtMS0xVjFhMSAxIDAgMCAxIDIgMHYxNGExIDEgMCAwIDEtMSAxeiIvPjwvc3ZnPg==)}.scylla-icon--forum{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSJjdXJyZW50Q29sb3IiIHN0cm9rZS13aWR0aD0iMS41IiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiIGNsYXNzPSJmZWF0aGVyIGZlYXRoZXItdXNlcnMiPjxwYXRoIGQ9Ik0xNyAyMXYtMmE0IDQgMCAwIDAtNC00SDVhNCA0IDAgMCAwLTQgNHYyIi8+PGNpcmNsZSBjeD0iOSIgY3k9IjciIHI9IjQiLz48cGF0aCBkPSJNMjMgMjF2LTJhNCA0IDAgMCAwLTMtMy44N00xNiAzLjEzYTQgNCAwIDAgMSAwIDcuNzUiLz48L3N2Zz4=)}.scylla-icon--home{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyMSAxOSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOm5vbmU7c3Ryb2tlOiM0ZDRkNGQ7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJMYXllcl81IiBkYXRhLW5hbWU9IkxheWVyIDUiPjxwYXRoIGNsYXNzPSJjbHMtMSIgZD0iTTMuNSA2LjE0djExYTEuMzggMS4zOCAwIDAgMCAxLjM3IDEuMzZoMTEuMjZhMS4zOCAxLjM4IDAgMCAwIDEuMzctMS4zN3YtMTEiLz48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Im0xOS41IDcuNS04LTYuMjVhMS41OSAxLjU5IDAgMCAwLTEuOTQgMEwxLjUgNy41TTEyLjczIDE4LjAydi03LjIxSDguMjd2Ny4yMSIvPjwvZz48L3N2Zz4=)}.scylla-icon--getting-started{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyMSAxOSI+PGcgZGF0YS1uYW1lPSJDYWxxdWUgNCI+PHBhdGggc3R5bGU9ImZpbGw6IzRkNGQ0ZCIgZD0ibTcgNC41IDguNTEgNS4wNUw3IDE0LjV2LTEweiIvPjxyZWN0IHg9IjEuNSIgeT0iLjUiIHdpZHRoPSIxOCIgaGVpZ2h0PSIxOCIgcng9IjIuNDMiIHN0eWxlPSJmaWxsOm5vbmU7c3Ryb2tlOiM0ZDRkNGQ7c3Ryb2tlLW1pdGVybGltaXQ6MTAiLz48L2c+PC9zdmc+)}.scylla-icon--glossary{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyMSAxOSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOm5vbmU7c3Ryb2tlOiM0ZDRkNGQ7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJDYWxxdWVfNCIgZGF0YS1uYW1lPSJDYWxxdWUgNCI+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNMi41IDIuNWgxM3YxNmgtMTN6Ii8+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNMTUuNTggMTcuMjFoMS45MlYuNWgtMTNhMi4zNCAyLjM0IDAgMCAwLTIgMiIvPjxwYXRoIGQ9Ik00LjggMTMuOTNhMSAxIDAgMCAwIC43NS0uNDMgNiA2IDAgMCAwIC41Mi0xLjA4bDIuODctNy4wN2guMzZsMi44OCA2Ljc5YTguOTIgOC45MiAwIDAgMCAuNzIgMS40Ny43Ni43NiAwIDAgMCAuNjguMzJ2LjMySDkuNHYtLjMyYTMuMjQgMy4yNCAwIDAgMCAuODMtLjExYy4xMy0uMDYuMi0uMTkuMi0uNDJhMS41OSAxLjU5IDAgMCAwLS4xLS40NmMwLS4xMi0uMS0uMjctLjE3LS40NGwtLjMzLS43OGgtMi45Yy0uMTkuNTEtLjMxLjg1LS4zNiAxYTIuMzggMi4zOCAwIDAgMC0uMTcuNzNjMCAuMTguMTIuMzIuMzcuNGEyLjU2IDIuNTYgMCAwIDAgLjY2LjA4di4zMkg0LjhabTQuODQtMi43Mi0xLjI0LTNoLS4xMWwtMS4xNiAzWiIgc3R5bGU9ImZpbGw6IzRkNGQ0ZCIvPjwvZz48L3N2Zz4=)}.scylla-icon--infoworld{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLW1pdGVybGltaXQ6MTB9PC9zdHlsZT48L2RlZnM+PGcgaWQ9IkNhbHF1ZV80IiBkYXRhLW5hbWU9IkNhbHF1ZSA0Ij48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Ik0xMiAyLjVINi41VjZjMCAzIC41NSA3LjE3IDUgOS41djQiLz48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Ik02LjQgNC40NGgtNFMyLjU2IDExIDguNSAxM00xOC41IDQuNWw0LS4wNnMtLjA2IDYuNTYtNiA4LjU2Ii8+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNMTIgMi41aDYuNVY2YzAgMi45NC0uNCA3LjA4LTUgOS41djRNOS41IDE5LjVoNnYyaC02eiIvPjxwYXRoIHN0eWxlPSJmaWxsOmdyYXk7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLW1pdGVybGltaXQ6MTAiIGQ9Ik03LjUgMjEuNWgxMHYxaC0xMHoiLz48L2c+PC9zdmc+)}.scylla-icon--integrations{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOm5vbmU7c3Ryb2tlOiM0ZDRkNGQ7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJDYWxxdWVfNCIgZGF0YS1uYW1lPSJDYWxxdWUgNCI+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJtMTQuNTYgMTIuNy0xLjI1LTEuNTctMS4zMS43NmE2IDYgMCAwIDAtMS42NS0xbC4wOC0xLjQ5LTItLjQtLjUzIDEuNDRhNS43MyA1LjczIDAgMCAwLTEuODcuMzFsLS44OC0xLjE5LTEuNzcgMUwzLjkyIDEyYTYuMyA2LjMgMCAwIDAtMS4yMiAxLjQxbC0xLjUtLjM1LS43NCAxLjg3IDEuMzguOGE2LjIzIDYuMjMgMCAwIDAgMCAxLjgzbC0xLjQxLjcyLjY0IDEuOTEgMS41OS0uMjhhNy42MyA3LjYzIDAgMCAwIC40OC42OCA1Ljg2IDUuODYgMCAwIDAgLjY3LjczbC0uNjIgMS40NiAxLjcyIDEgMS0xLjI0YTYuNDYgNi40NiAwIDAgMCAxLjc5LjM1bC40NiAxLjUyIDItLjN2LTEuNmE2LjQzIDYuNDMgMCAwIDAgMS42Mi0uODlsMS4zLjg1TDE0LjQzIDIxbC0xLTEuMmE2LjI0IDYuMjQgMCAwIDAgLjY4LTEuNzVsMS41MS0uMTkuMDUtMi0xLjUxLS4yNmE2LjA3IDYuMDcgMCAwIDAtLjYyLTEuODFabS01LjM1IDUuNTFhMS45MyAxLjkzIDAgMSAxIC4zMS0yLjcxIDEuOTIgMS45MiAwIDAgMS0uMzEgMi43MVoiLz48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Im0yNC4zMSA4LjA1LS4xMy0xLjY1LTEuMjUtLjA5YTUuMjYgNS4yNiAwIDAgMC0uNjctMS40NGwuNzUtMS0xLjE2LTEuMTctMSAuNzRhNS4xOCA1LjE4IDAgMCAwLTEuNDMtLjY2bC0uMDYtMS4yNC0xLjY1LS4xNy0uMzIgMS4yNWE1Ljc3IDUuNzcgMCAwIDAtMS41Mi4zOEwxNSAyLjFsLTEuMzcuOS41OCAxLjE4YTQuODggNC44OCAwIDAgMC0uODYgMS4yNWwtMS4zLS4xNi0uNDUgMS42IDEuMjIuNTVhNS4xNyA1LjE3IDAgMCAwIDAgLjY4QTQuMjggNC4yOCAwIDAgMCAxMyA5bC0xLjExLjcyLjY5IDEuNTEgMS4yOC0uMzdhNC45NCA0Ljk0IDAgMCAwIDEuMDcgMS4wN2wtLjM5IDEuMjYgMS41LjcxLjc0LTEuMDlhNS4wNyA1LjA3IDAgMCAwIDEuNTIuMTRsLjUgMS4xOSAxLjYxLS40MS0uMTMtMS4yOWE1LjE0IDUuMTQgMCAwIDAgMS4yNy0uODhsMS4xMi41NyAxLTEuMzUtLjkxLS44OGE0LjkgNC45IDAgMCAwIC40Mi0xLjUyWm0tNi4yIDEuNDNhMS43NCAxLjc0IDAgMSAxIDEuNi0xLjg2IDEuNzQgMS43NCAwIDAgMS0xLjYgMS44NloiLz48L2c+PC9zdmc+)}.scylla-icon--knowledge-base{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyMSAxOSI+PGRlZnM+PHN0eWxlPi5jbHMtMSwuY2xzLTJ7ZmlsbDpub25lO3N0cm9rZTojNGQ0ZDRkfS5jbHMtMXtzdHJva2UtbGluZWNhcDpyb3VuZDtzdHJva2UtbGluZWpvaW46cm91bmR9LmNscy0ye3N0cm9rZS1taXRlcmxpbWl0OjEwfTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJMYXllcl81IiBkYXRhLW5hbWU9IkxheWVyIDUiPjxwYXRoIGNsYXNzPSJjbHMtMSIgZD0iTTE2LjIxIDYuMzhhNS4zNiA1LjM2IDAgMCAxLTEuNTEgMy43MyA1IDUgMCAwIDAtMS40NSAzLjMxSDguNDdhNS40MSA1LjQxIDAgMCAwLTEuMjgtMy4xMSA1LjM3IDUuMzcgMCAxIDEgOS0zLjkzWk0xMy4yMyAxNS42N0g4LjQ1Ii8+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNMTMuMjQgMTMuNGgtNC44djQuMTZhLjcuNyAwIDAgMCAuNzEuN2gzLjM4YS43LjcgMCAwIDAgLjcxLS43WiIvPjxwYXRoIGNsYXNzPSJjbHMtMiIgZD0iTTEwLjg0IDguMjFhMS42NSAxLjY1IDAgMSAxIDEuNjQtMS42NSAxLjY1IDEuNjUgMCAwIDEtMS42NCAxLjY1Wk0xMC44NCA4LjY3djQuNjQiLz48L2c+PC9zdmc+)}.scylla-icon--less{background-image:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTciIGhlaWdodD0iMTciIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHJlY3Qgd2lkdGg9IjE3IiBoZWlnaHQ9IjE3IiByeD0iMSIgZmlsbD0iI0IzQkFDNSIvPjxwYXRoIGQ9Ik0xMyA4LjVhMSAxIDAgMCAxLTEgMUg1YTEgMSAwIDAgMSAwLTJoN2ExIDEgMCAwIDEgMSAxWiIgZmlsbD0iI2ZmZiIvPjxwYXRoIGQ9Ik0xMyA4LjVhMSAxIDAgMCAxLTEgMUg1YTEgMSAwIDAgMSAwLTJoN2ExIDEgMCAwIDEgMSAxWiIgZmlsbD0iI2ZmZiIvPjxwYXRoIGQ9Ik0xMyA4LjVhMSAxIDAgMCAxLTEgMUg1YTEgMSAwIDAgMSAwLTJoN2ExIDEgMCAwIDEgMSAxWiIgZmlsbD0iI2ZmZiIvPjxwYXRoIGQ9Ik0xMyA4LjVhMSAxIDAgMCAxLTEgMUg1YTEgMSAwIDAgMSAwLTJoN2ExIDEgMCAwIDEgMSAxWiIgZmlsbD0iI2ZmZiIvPjxwYXRoIGQ9Ik0xMyA4LjVhMSAxIDAgMCAxLTEgMUg1YTEgMSAwIDAgMSAwLTJoN2ExIDEgMCAwIDEgMSAxWiIgZmlsbD0iI2ZmZiIvPjwvc3ZnPg==);filter:none}.scylla-icon--live-test{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtNntmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLW1pdGVybGltaXQ6MTA7c3Ryb2tlLWxpbmVjYXA6cm91bmR9PC9zdHlsZT48L2RlZnM+PGcgaWQ9IkNhbHF1ZV80IiBkYXRhLW5hbWU9IkNhbHF1ZSA0Ij48Y2lyY2xlIGN4PSIxMi41IiBjeT0iMTUiIHI9IjkuNSIgc3R5bGU9InN0cm9rZS13aWR0aDoxLjVweDtzdHJva2UtbWl0ZXJsaW1pdDoxMDtmaWxsOm5vbmU7c3Ryb2tlOmdyYXkiLz48cGF0aCBzdHlsZT0ic3Ryb2tlLXdpZHRoOjEuMXB4O3N0cm9rZS1saW5lam9pbjpyb3VuZDtzdHJva2UtbGluZWNhcDpyb3VuZDtmaWxsOm5vbmU7c3Ryb2tlOmdyYXkiIGQ9Ik0xMCAuNWg1djJoLTV6Ii8+PHBhdGggc3R5bGU9InN0cm9rZS13aWR0aDoxLjExcHg7c3Ryb2tlLWxpbmVqb2luOnJvdW5kO3N0cm9rZS1saW5lY2FwOnJvdW5kO2ZpbGw6bm9uZTtzdHJva2U6Z3JheSIgZD0iTTUuOCA4LjIgNC4xMyA2LjUzbDEuOC0xLjgxTDcuNiA2LjQiLz48cGF0aCBzdHlsZT0ic3Ryb2tlLXdpZHRoOjEuMTNweDtzdHJva2UtbWl0ZXJsaW1pdDoxMDtmaWxsOm5vbmU7c3Ryb2tlOmdyYXkiIGQ9Ik0xMiA2VjIuNSIvPjxwYXRoIHN0eWxlPSJzdHJva2Utd2lkdGg6MS4wOHB4O3N0cm9rZS1taXRlcmxpbWl0OjEwO2ZpbGw6bm9uZTtzdHJva2U6Z3JheSIgZD0iTTEzIDZWMi41Ii8+PHBhdGggY2xhc3M9ImNscy02IiBkPSJNMTIuNSA4LjA2VjEwTTEyLjUgMjAuMDR2MS44OE03LjEzIDEwLjA4bDEuNzkgMS44OE0xNi4wNCAxNy4wOGwyIDEuODhNNyAxOC45MmwxLjg4LTEuODhNMTYuMTMgMTEuOTZsMS43OS0xLjgzIi8+PGVsbGlwc2UgY3g9IjEyLjUiIGN5PSIxNC4zNiIgcng9IjEuNSIgcnk9IjEuMzYiIHN0eWxlPSJmaWxsOmdyYXkiLz48cGF0aCBjbGFzcz0iY2xzLTYiIGQ9Im0xMi42MyAxNC41NCAyLjUgNi4zOCIvPjwvZz48L3N2Zz4=)}.scylla-icon--mail-list{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSJjdXJyZW50Q29sb3IiIHN0cm9rZS13aWR0aD0iMS41IiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiIGNsYXNzPSJmZWF0aGVyIGZlYXRoZXItbWFpbCI+PHBhdGggZD0iTTQgNGgxNmMxLjEgMCAyIC45IDIgMnYxMmMwIDEuMS0uOSAyLTIgMkg0Yy0xLjEgMC0yLS45LTItMlY2YzAtMS4xLjktMiAyLTJ6Ii8+PHBhdGggZD0ibTIyIDYtMTAgN0wyIDYiLz48L3N2Zz4=)}.scylla-icon--manager{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtM3tmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kO3N0cm9rZS13aWR0aDouOTdweH0uY2xzLTR7ZmlsbDpncmF5fTwvc3R5bGU+PC9kZWZzPjxwYXRoIHN0eWxlPSJmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kIiBkPSJNMTggMmg1djIySDNWMmg0LjkyIiBpZD0iQ2FscXVlXzIiIGRhdGEtbmFtZT0iQ2FscXVlIDIiLz48ZyBpZD0iQ2FscXVlXzQiIGRhdGEtbmFtZT0iQ2FscXVlIDQiPjxwYXRoIHN0eWxlPSJzdHJva2Utd2lkdGg6MS4wN3B4O2ZpbGw6bm9uZTtzdHJva2U6Z3JheTtzdHJva2UtbGluZWNhcDpyb3VuZDtzdHJva2UtbGluZWpvaW46cm91bmQiIGQ9Ik04IDBoMTB2NEg4eiIvPjxwYXRoIGNsYXNzPSJjbHMtMyIgZD0iTTcgOWgzdjNIN3pNNyAxNmgzdjNIN3oiLz48cGF0aCBjbGFzcz0iY2xzLTQiIGQ9Ik0xMi41IDkuNWg3djJoLTd6TTEyLjUgMTYuNWg3djJoLTd6Ii8+PC9nPjwvc3ZnPg==)}.scylla-icon--memory-management{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMSwuY2xzLTJ7ZmlsbDpub25lO3N0cm9rZTpncmF5O3N0cm9rZS1saW5lY2FwOnJvdW5kO3N0cm9rZS1saW5lam9pbjpyb3VuZH0uY2xzLTJ7c3Ryb2tlLXdpZHRoOjEuMTNweH08L3N0eWxlPjwvZGVmcz48ZyBpZD0iQ2FscXVlXzQiIGRhdGEtbmFtZT0iQ2FscXVlIDQiPjxyZWN0IGNsYXNzPSJjbHMtMSIgeD0iNS41IiB5PSI1LjUiIHdpZHRoPSIxNSIgaGVpZ2h0PSIxNSIgcng9IjIuNzQiIHJ5PSIyLjc0Ii8+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNOS41IDkuNWg3djdoLTd6Ii8+PHBhdGggY2xhc3M9ImNscy0yIiBkPSJNOC41IDUuNXYtNE0xMS41IDUuNXYtNE0xNC41IDUuNXYtNE0xNy41IDUuNXYtNE04LjUgMjQuNXYtNE0xMS41IDI0LjV2LTRNMTQuNSAyNC41di00TTE3LjUgMjQuNXYtNE0yMC41IDguNWg0TTIwLjUgMTEuNWg0TTIwLjUgMTQuNWg0TTIwLjUgMTcuNWg0TTEuNSA4LjVoNE0xLjUgMTEuNWg0TTEuNSAxNC41aDRNMS41IDE3LjVoNCIvPjwvZz48L3N2Zz4=)}.scylla-icon--monitoring{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGcgZGF0YS1uYW1lPSJDYWxxdWUgNCI+PHBhdGggZD0iTTUuNTUgMTAuODlhMy44MyAzLjgzIDAgMCAxLS4xNS0zLjc2IiBzdHlsZT0ic3Ryb2tlLWxpbmVqb2luOnJvdW5kO3N0cm9rZS1saW5lY2FwOnJvdW5kO3N0cm9rZTpncmF5O2ZpbGw6bm9uZSIvPjxyZWN0IHg9IjE3LjYzIiB5PSIxNC4wMSIgd2lkdGg9IjMuMDUiIGhlaWdodD0iMTAuOCIgcng9Ii41NyIgcnk9Ii41NyIgdHJhbnNmb3JtPSJyb3RhdGUoLTQ1IDE5LjE1OCAxOS40MDUpIiBzdHlsZT0ic3Ryb2tlLW1pdGVybGltaXQ6MTA7ZmlsbDpncmF5O3N0cm9rZS13aWR0aDouOTVweDtzdHJva2U6Z3JheSIvPjxjaXJjbGUgY3g9IjguNSIgY3k9IjkiIHI9IjciIHN0eWxlPSJzdHJva2Utd2lkdGg6MnB4O3N0cm9rZS1taXRlcmxpbWl0OjEwO3N0cm9rZTpncmF5O2ZpbGw6bm9uZSIvPjxwYXRoIHN0eWxlPSJzdHJva2UtbWl0ZXJsaW1pdDoxMDtzdHJva2UtbGluZWNhcDpyb3VuZDtzdHJva2U6Z3JheTtmaWxsOm5vbmUiIGQ9Im0xNi4wNSAxNi4zOS0yLjI4LTIuMjgiLz48L2c+PC9zdmc+)}.scylla-icon--networking{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMntmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLW1pdGVybGltaXQ6MTB9PC9zdHlsZT48L2RlZnM+PGcgaWQ9IkNhbHF1ZV80IiBkYXRhLW5hbWU9IkNhbHF1ZSA0Ij48Y2lyY2xlIGN4PSIxMi41IiBjeT0iMTIuNSIgcj0iNCIgc3R5bGU9InN0cm9rZS13aWR0aDouOTRweDtmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLW1pdGVybGltaXQ6MTAiLz48Y2lyY2xlIGNsYXNzPSJjbHMtMiIgY3g9IjUiIGN5PSIzIiByPSIyLjUiLz48Y2lyY2xlIGNsYXNzPSJjbHMtMiIgY3g9IjE5IiBjeT0iMjAiIHI9IjIuNSIvPjxjaXJjbGUgY2xhc3M9ImNscy0yIiBjeD0iMjIiIGN5PSI2LjYiIHI9IjIuNSIvPjxjaXJjbGUgY2xhc3M9ImNscy0yIiBjeD0iNC41IiBjeT0iMjIiIHI9IjIuNSIvPjxwYXRoIGNsYXNzPSJjbHMtMiIgZD0ibTYuODMgNS41IDMuMjUgNC4zM00yMC4yMyA3Ljg1IDE1LjMzIDExTTkuODMgMTUuMDhsLTQuMDkgNS44NE0xNC41OCAxNS4zM2wzIDMuMDkiLz48Y2lyY2xlIGN4PSIxMi41IiBjeT0iMTIuNSIgcj0iMS41IiBzdHlsZT0iZmlsbDpncmF5Ii8+PC9nPjwvc3ZnPg==)}.scylla-icon--news{background-image:url(data:image/svg+xml;base64,PHN2ZyBpZD0iQ2FscXVlXzEiIGRhdGEtbmFtZT0iQ2FscXVlIDEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmlld0JveD0iMCAwIDI1IDI1Ij48ZGVmcz48c3R5bGU+LmNscy0xe2ZpbGw6bm9uZTtzdHJva2U6Z3JheTtzdHJva2UtbGluZWNhcDpyb3VuZDtzdHJva2UtbGluZWpvaW46cm91bmR9PC9zdHlsZT48L2RlZnM+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNMyAxNS4xNyAxNi4zMSAzLjgyYTEuNDggMS40OCAwIDAgMSAyLjIyLjQ2bDUuMTUgOS42NWExLjQ2IDEuNDYgMCAwIDEtLjkzIDIuMTJMNS42OSAxOS45Wk04LjcxIDE5LjMzbC43NiAyLjIyYTEuNTEgMS41MSAwIDAgMCAxLjg1IDFsMy41OC0xLjA2YTEuNSAxLjUgMCAwIDAgMS0xLjg2TDE1LjQ1IDE4TTUuNTQgMjBsLTEuODMgMWEuOTIuOTIgMCAwIDEtMS4yNS0uMzdMLjYxIDE3LjQ5QS45Mi45MiAwIDAgMSAxIDE2LjI0bDEuODMtMU04LjUgMTRsNy4zOC01LjUiLz48L3N2Zz4=)}.scylla-icon--newsletter{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMSwuY2xzLTJ7ZmlsbDpub25lO3N0cm9rZTpncmF5O3N0cm9rZS1taXRlcmxpbWl0OjEwfS5jbHMtMntzdHJva2UtbGluZWNhcDpyb3VuZH08L3N0eWxlPjwvZGVmcz48ZyBpZD0iQ2FscXVlXzQiIGRhdGEtbmFtZT0iQ2FscXVlIDQiPjxwYXRoIGNsYXNzPSJjbHMtMSIgZD0iTTE5LjUgOS41aDN2MTJoLTIwdi0xMmgzIi8+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJtMi42NSA5Ljg0IDkuODUgNi44OCA4LjYzLTYuODgiLz48cGF0aCBjbGFzcz0iY2xzLTIiIGQ9Im01LjUgNy41LTMgMk0xNC4zNSAzLjg2bC0xLjQ2LTEuMDktMS40NyAxLjA5TTIxLjUgOS41bC0yLTJNMTkuNSAxMS41di03aC0xNHY3LjQ3Ii8+PC9nPjwvc3ZnPg==)}.scylla-icon--nsql-guides{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGcgZGF0YS1uYW1lPSJDYWxxdWUgNCI+PHJlY3QgeD0iNC4zNyIgeT0iMTMuNzEiIHdpZHRoPSIxLjE1IiBoZWlnaHQ9IjkuNzIiIHJ4PSIuNTQiIHJ5PSIuNTQiIHRyYW5zZm9ybT0icm90YXRlKDQ1IDQuOTQ4IDE4LjU3KSIgc3R5bGU9InN0cm9rZTpncmF5O3N0cm9rZS1taXRlcmxpbWl0OjEwO2ZpbGw6Z3JheTtzdHJva2Utd2lkdGg6MS4wOXB4Ii8+PGNpcmNsZSBjeD0iMTIuMjUiIGN5PSIxMi4yNSIgcj0iNC43NSIgc3R5bGU9InN0cm9rZS13aWR0aDoxLjVweDtmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLW1pdGVybGltaXQ6MTAiLz48cGF0aCBzdHlsZT0ic3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLXdpZHRoOjEuMDZweDtmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLW1pdGVybGltaXQ6MTAiIGQ9Ik04LjUgMjAuNXYzaDE1di0yMWgtMTV2MiIvPjwvZz48L3N2Zz4=)}.scylla-icon--open-source{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfS5jbHMtMntmaWxsOmdyYXl9PC9zdHlsZT48L2RlZnM+PGcgaWQ9IkNhbHF1ZV80IiBkYXRhLW5hbWU9IkNhbHF1ZSA0Ij48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Ik0uMzEgMjEuNTEgNSAxOS42OWEyLjM3IDIuMzcgMCAwIDEgMS44OC4xOWw1LjI0IDEuNjhhMi4yMyAyLjIzIDAgMCAwIDItLjEybDkuNS00Ljc1Yy44LS40NCAxLjY0LTEuMzEgMS4xMy0xLjkxYTIuMzQgMi4zNCAwIDAgMC0yLjY0LS40MkwxOCAxNi4wOSIvPjxwYXRoIGNsYXNzPSJjbHMtMSIgZD0ibS4yNSAxNS42OSA0Ljg4LTEuMjFjMS4yNS0uMyAyLjE3LS42MyAzLjQ0LS4xM2ExNS4yMSAxNS4yMSAwIDAgMCA0IDEuMWg0LjUyYy44NSAwIC45NS41NC45NSAxLjEzYTEgMSAwIDAgMS0xLjA4IDEgNjUuODYgNjUuODYgMCAwIDEtNy0uMzEiLz48cGF0aCBjbGFzcz0iY2xzLTIiIGQ9Ik04LjU2IDkuNjh2LS44MWMwLS45MS0uMzgtMS4yMS0xLjI5LTEuMjFIN1Y2LjNoLjMxYy45MSAwIDEuMjktLjMgMS4yOS0xLjIxdi0uODFjMC0xLjIuNjYtMS45MiAyLjgyLTIuM3YxLjE2Yy0xLjI0LjM1LTEuNDMuNjgtMS40MyAxLjR2Ljg3QTEuNTIgMS41MiAwIDAgMSA4Ljc1IDcgMS41MiAxLjUyIDAgMCAxIDEwIDguNTZ2Ljg3YzAgLjcxLjE5IDEgMS40MyAxLjRWMTJjLTIuMjEtLjM1LTIuODctMS4xMi0yLjg3LTIuMzJaTTE3LjQzIDQuM3YuODFjMCAuOTEuMzcgMS4yMSAxLjI5IDEuMjFIMTl2MS4zNmgtLjMxYy0uOTIgMC0xLjI5LjMtMS4yOSAxLjIxdi44MWMwIDEuMi0uNjUgMi0yLjgxIDIuMzV2LTEuMmMxLjI1LS4zNiAxLjQ0LS42OSAxLjQ0LTEuNHYtLjg3QTEuNTMgMS41MyAwIDAgMSAxNy4yNSA3IDEuNTMgMS41MyAwIDAgMSAxNiA1LjQzdi0uODdjMC0uNzItLjE5LTEtMS40NC0xLjRWMmMyLjIyLjM4IDIuODcgMS4xIDIuODcgMi4zWiIvPjwvZz48L3N2Zz4=)}.scylla-icon--operator{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjQuODEgMS4wMSAyOC4zMiAyNy42NCI+PHBhdGggZD0iTTMyLjUyIDE4cy0uMDkgMC0uMDktLjA1LS4wOCAwLS4xNyAwYTIuMTkgMi4xOSAwIDAgMC0uNTEgMCAuNDcuNDcgMCAwIDEtLjI2LS4wNSA5LjI5IDkuMjkgMCAwIDEtMS40OS0uMzIuNTQuNTQgMCAwIDEtLjMtLjMxbC0uMzQtLjA4YTExLjI1IDExLjI1IDAgMCAwLS4xOC0zLjc5IDExLjU1IDExLjU1IDAgMCAwLTEuNS0zLjUybC4yNi0uMjZhLjU5LjU5IDAgMCAxIC4xMy0uMzkgNy43MyA3LjczIDAgMCAxIDEuMi0uODZsLjI2LS4xMy40Ny0uM3MuMDkgMCAuMTMtLjA4IDAtLjA1IDAtLjA5YS44NC44NCAwIDAgMCAuMTctMS4yLjc4Ljc4IDAgMCAwLS42LS4zIDEgMSAwIDAgMC0uNi4yMWMtLjA1LjA1LS4wOS4wOS0uMTMuMDlhMy4wOCAzLjA4IDAgMCAwLS4zNS4zOWMwIC4wOC0uMTMuMTMtLjE3LjE3YTUuNjQgNS42NCAwIDAgMS0xLjA3Ljk0LjU4LjU4IDAgMCAxLS4yNi4wOS4yNS4yNSAwIDAgMS0uMTcgMGgtLjA1bC0uMzQuMjEtMS4wOC0xYTExIDExIDAgMCAwLTUuNjUtMi4yN3YtLjM0YS42LjYgMCAwIDEtLjIyLS4zNEE4LjE4IDguMTggMCAwIDEgMTkuNjYgM3YtLjI1YzAtLjA4LjA1LS4zNS4wOS0uNTJ2LS4zMWEuODIuODIgMCAwIDAtMS40Ni0uNi44Ni44NiAwIDAgMC0uMjYuNnYuMjJhMS44MiAxLjgyIDAgMCAwIC4wOS41MS41OS41OSAwIDAgMSAwIC4yNlYzYTguODIgOC44MiAwIDAgMSAuMDggMS40Ny41OS41OSAwIDAgMS0uMjEuMzRWNS4yNGMtLjQ4IDAtMSAuMTMtMS40Ny4yMmExMC4xNiAxMC4xNiAwIDAgMC01LjI4IDNMMTEgOC4yNGgtLjE3YS43My43MyAwIDAgMS0uMjYtLjA5IDcuOCA3LjggMCAwIDEtMS4wNy0xYzAtLjA4LS4xMy0uMTMtLjE3LS4xN3MtLjI1LS4yLS4zMy0uMzMtLjA4IDAtLjEzLS4wOHYtLjA1YTEgMSAwIDAgMC0uNi0uMjEuNjQuNjQgMCAwIDAtLjYuMy45MS45MSAwIDAgMCAuMTcgMS4yczAgLjA1IDAgLjA1LjA5LjA4LjEzLjA4YTUgNSAwIDAgMCAuNDcuMjZsLjI2LjEzYTYuNjEgNi42MSAwIDAgMSAxLjIxLjg2LjQ3LjQ3IDAgMCAxIC4xMy4zOXYtLjA1bC4yNS4yNmEyLjUzIDIuNTMgMCAwIDEtLjEzLjIyIDEwLjIgMTAuMiAwIDAgMC0xLjUgN2wtLjM1LjA5YzAgLjEzLS4xNy4yMS0uMy4zYTguNTYgOC41NiAwIDAgMS0xLjQ2LjI2LjU5LjU5IDAgMCAwLS4yNiAwaC0uNTJjLS4xOCAwLS4wOC4wNS0uMTcuMDVoLS4wOGEuODQuODQgMCAwIDAtLjY5IDEgLjc5Ljc5IDAgMCAwIC44Ni42LjM5LjM5IDAgMCAwIC4yMSAwSDYuMTJhMy42MSAzLjYxIDAgMCAwIC40Ny0uMTcuNjUuNjUgMCAwIDEgLjI2LS4wOCA3LjY1IDcuNjUgMCAwIDEgMS40Mi0uMzkuNDkuNDkgMCAwIDEgLjM1LjEzaC4zOWExMC4zMiAxMC4zMiAwIDAgMCAzLjUzIDUgNi4zMSA2LjMxIDAgMCAwIDEuMTYuNzdsLS4yMi4zYS41MS41MSAwIDAgMSAwIC40MyA2LjU0IDYuNTQgMCAwIDEtLjY5IDEuMjR2LjA1YS43OC43OCAwIDAgMS0uMTcuMjFjLS4wOS4wOS0uMTcuMjYtLjMuNDNzMCAuMDktLjA5LjEzIDAgLjA1IDAgLjA1YS44OC44OCAwIDAgMCAuMzQgMS4xNi45LjkgMCAwIDAgLjMuMDggMSAxIDAgMCAwIC44Mi0uNTFzMC0uMDguMDktLjEzLjEzLS4zLjE3LS40N2wuMDktLjI2YTcuMDcgNy4wNyAwIDAgMSAuNTYtMS4zMy42Mi42MiAwIDAgMSAuMzQtLjI2bC4xNy0uMzVhMTAuMDUgMTAuMDUgMCAwIDAgMy43NS42OSA4LjQ1IDguNDUgMCAwIDAgMi4zMi0uMyAxMS40NiAxMS40NiAwIDAgMCAxLjM3LS4zOWwuMTguMzFhLjYyLjYyIDAgMCAxIC4zNC4yNiA3LjA3IDcuMDcgMCAwIDEgLjU2IDEuMzNsLjA5LjI2YTEuMzEgMS4zMSAwIDAgMCAuMTcuNDdjMCAuMDUgMCAuMDkuMDkuMTNhMSAxIDAgMCAwIC44Mi41MSAxLjA1IDEuMDUgMCAwIDAgLjM0LS4wOC43Ni43NiAwIDAgMCAuMzktLjQ4IDEuMDggMS4wOCAwIDAgMC0uMDUtLjY0LjIuMiAwIDAgMC0uMDgtLjEzIDEuNTMgMS41MyAwIDAgMC0uMzEtLjQzLjY1LjY1IDAgMCAwLS4xNy0uMjJ2LS4wOWE1LjIyIDUuMjIgMCAwIDEtLjY5LTEuMjQuNTEuNTEgMCAwIDEgLjA1LS40M2wtLjEzLS4zNEExMC42OCAxMC42OCAwIDAgMCAyOSAxOC44MmwuMzQuMDV2LS4wNWEuNTQuNTQgMCAwIDEgLjM1LS4xMyA3LjgyIDcuODIgMCAwIDEgMS4zOC4zOS42Mi42MiAwIDAgMCAuMjYuMDkgMi40MiAyLjQyIDAgMCAwIC40Ny4yMXMuMDkgMCAuMTcgMGguMDlhLjM5LjM5IDAgMCAwIC4yMSAwIC45NC45NCAwIDAgMCAuODYtLjYgMSAxIDAgMCAwLS43Ny0uOVptLTEyLjQzLTEuMzMtMS4xNi41Ni0xLjE2LS41Ni0uMy0xLjI1LjgxLTFoMS4yOWwuODIgMVptNy0yLjc5YTggOCAwIDAgMSAuMTcgMi43MWwtNC4xNS0uNzVjLS4zOC0uMDgtLjY4LS45LS43MS0xLjIyYTQgNCAwIDAgMSAuMjEtLjc0bDMuNDUtMi41NGE4LjU4IDguNTggMCAwIDEgMS4wNCAyLjU0Wm0tMi4zMS00LjEzLTMuMjIgMi42OWExLjI4IDEuMjggMCAwIDEtMS4yNS0uMzdjLS4wOS0uMDktLjM3LS4yNS0uMzctLjM4VjcuNDNhOC4wNyA4LjA3IDAgMCAxIDQuODYgMi4zMlpNMTcgNy41NmwxLS4xOC0uMDYgNC4zMWMwIC4zOC0uNjQuNjgtMSAuNjhhMS4xMSAxLjExIDAgMCAxLS4zNS0uMDhMMTMgOS43NWE4LjQxIDguNDEgMCAwIDEgNC0yLjE5Wm0tNS4yNCAzLjc4IDMuMzcgMi40Ny4zMi41M2ExLjE0IDEuMTQgMCAwIDEtLjI1IDEgLjc4Ljc4IDAgMCAxLS4zOC4zMWwtNC4zMS45YTkgOSAwIDAgMSAxLjI0LTUuMjFaTTExIDE4LjYxbDQuMS0xLjIzYy4zNSAwIC44NC43MS44OSAxLjA2YS41MS41MSAwIDAgMS0uMDUuNDNsLTEuNjMgMy45NUE4LjQxIDguNDEgMCAwIDEgMTEgMTguNjFabTkuNzYgNS4zM2E4LjY3IDguNjcgMCAwIDEtMS44NS4yMSA5LjU5IDkuNTkgMCAwIDEtMi43MS0uNDNsMS42Ni00Yy4yMS0uMjYgMS0uMiAxLjMxIDBhMi40OCAyLjQ4IDAgMCAxIC4zNC4zbDIuMDcgMy43NGE1LjcyIDUuNzIgMCAwIDAtLjguMThaTTI2IDIwLjJhOC4zNiA4LjM2IDAgMCAxLTIuNTggMi41OGwtMS45Mi0zLjcyYTEuMTUgMS4xNSAwIDAgMSAuNDEtMWMuMjEtLjI1LjU5LS41OS43MS0uNTlsNC4yMiAxLjA2QTYuMjcgNi4yNyAwIDAgMSAyNiAyMC4yWiIgc3R5bGU9ImZpbGw6IzRkNGQ0ZCIgZGF0YS1uYW1lPSJDYWxxdWUgMiIvPjwvc3ZnPg==)}.scylla-icon--overview{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJDYWxxdWVfNCIgZGF0YS1uYW1lPSJDYWxxdWUgNCI+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNMjIuNjEgMy40NUMyMi42MSA1LjA2IDE4IDYuNSAxMi41IDYuNXMtMTAtMS40NC0xMC0zIDQuNS0zIDEwLTMgMTAuMTEgMS4zMyAxMC4xMSAyLjk1Wk0yMi42MSA5LjQ0YzAgMS42MS00LjY0IDMuMDYtMTAuMTEgMy4wNnMtMTAtMS40NS0xMC0zLjA2TTIyLjYxIDE1LjUxYzAgMS42Mi00LjY0IDMtMTAuMTEgM3MtMTAtMS4zNy0xMC0zTTIyLjYxIDIxLjU5YzAgMS42Mi00LjY0IDIuOTEtMTAuMTEgMi45MXMtMTAtMS4yOS0xMC0yLjkxTTIuNSAyMS40N1YzLjQ1TTIyLjUgMjEuNDdWMy40NSIvPjwvZz48L3N2Zz4=)}.scylla-icon--partners{background-image:url(data:image/svg+xml;base64,PHN2ZyBpZD0iQ2FscXVlXzEiIGRhdGEtbmFtZT0iQ2FscXVlIDEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmlld0JveD0iMCAwIDI1IDI1Ij48ZGVmcz48c3R5bGU+LmNscy0xe2ZpbGw6bm9uZTtzdHJva2U6Z3JheTtzdHJva2UtbGluZWNhcDpyb3VuZDtzdHJva2UtbGluZWpvaW46cm91bmR9PC9zdHlsZT48L2RlZnM+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNMTguNSA4LjI2aC00LjcybC0xLjIzIDEuMjdNMi4zOSAxNS4wOS4xNSAxMy43NGw0Ljg3LTguNDIgMi4yNCAxLjM0LTQuODcgOC40M3pNMjIuNTkgMTUuMDlsMi4yNC0xLjM1LTQuODYtOC40Mi0yLjI0IDEuMzQgNC44NiA4LjQzek0xMC43MSAxNS4yNmwtMi45MyAyLjIxTTEyLjE4IDE2LjRsLTIuOTMgMi4yMU0xMy42OCAxNy41M2wtMi45MyAyLjIyIi8+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNNi4zOCA4LjNoMy43OGEyLjI3IDIuMjcgMCAwIDEgMS4zNy40N2MxLjI2IDEgNC4wOSAzLjE4IDQuNDggMy41NnMtMS4xNCAxLjY4LTIuMjcgMS4xYTE4LjM0IDE4LjM0IDAgMCAwLTIuMTEtLjkyLjU3LjU3IDAgMCAwLS41Ni4wOWwtNC43OSAzLjg5TDEyLjMzIDIxbDkuNDYtNy4wOU0zLjI0IDE0LjIybDMuNCAxLjg1Ii8+PC9zdmc+)}.scylla-icon--plus{background-image:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTciIGhlaWdodD0iMTciIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHJlY3Qgd2lkdGg9IjE3IiBoZWlnaHQ9IjE3IiByeD0iMSIgZmlsbD0iI0IzQkFDNSIvPjxwYXRoIGZpbGwtcnVsZT0iZXZlbm9kZCIgY2xpcC1ydWxlPSJldmVub2RkIiBkPSJNOS41IDVhMSAxIDAgMSAwLTIgMHYyLjVINWExIDEgMCAxIDAgMCAyaDIuNVYxMmExIDEgMCAxIDAgMiAwVjkuNUgxMmExIDEgMCAxIDAgMC0ySDkuNVY1WiIgZmlsbD0iI2ZmZiIvPjxwYXRoIGZpbGwtcnVsZT0iZXZlbm9kZCIgY2xpcC1ydWxlPSJldmVub2RkIiBkPSJNOS41IDVhMSAxIDAgMSAwLTIgMHYyLjVINWExIDEgMCAxIDAgMCAyaDIuNVYxMmExIDEgMCAxIDAgMiAwVjkuNUgxMmExIDEgMCAxIDAgMC0ySDkuNVY1WiIgZmlsbD0iI2ZmZiIvPjxwYXRoIGZpbGwtcnVsZT0iZXZlbm9kZCIgY2xpcC1ydWxlPSJldmVub2RkIiBkPSJNOS41IDVhMSAxIDAgMSAwLTIgMHYyLjVINWExIDEgMCAxIDAgMCAyaDIuNVYxMmExIDEgMCAxIDAgMiAwVjkuNUgxMmExIDEgMCAxIDAgMC0ySDkuNVY1WiIgZmlsbD0iI2ZmZiIvPjxwYXRoIGZpbGwtcnVsZT0iZXZlbm9kZCIgY2xpcC1ydWxlPSJldmVub2RkIiBkPSJNOS41IDVhMSAxIDAgMSAwLTIgMHYyLjVINWExIDEgMCAxIDAgMCAyaDIuNVYxMmExIDEgMCAxIDAgMiAwVjkuNUgxMmExIDEgMCAxIDAgMC0ySDkuNVY1WiIgZmlsbD0iI2ZmZiIvPjxwYXRoIGZpbGwtcnVsZT0iZXZlbm9kZCIgY2xpcC1ydWxlPSJldmVub2RkIiBkPSJNOS41IDVhMSAxIDAgMSAwLTIgMHYyLjVINWExIDEgMCAxIDAgMCAyaDIuNVYxMmExIDEgMCAxIDAgMiAwVjkuNUgxMmExIDEgMCAxIDAgMC0ySDkuNVY1WiIgZmlsbD0iI2ZmZiIvPjwvc3ZnPg==);filter:none}.scylla-icon--pricing{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJDYWxxdWVfMiIgZGF0YS1uYW1lPSJDYWxxdWUgMiI+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJtMjEuNzMgNy0yLjQxLTUuMTJhMi41MiAyLjUyIDAgMCAwLTIuODItMWwtNi4wOCAyLjA0QTEuNjkgMS42OSAwIDAgMCA5LjUxIDRMMy45MyAxOS4yOWExLjA2IDEuMDYgMCAwIDAgLjY0IDEuMTdsMTAuMzQgMy43NmExIDEgMCAwIDAgMS4yMi0uNDNsNS41OC0xNS4zM0ExLjg3IDEuODcgMCAwIDAgMjEuNzMgN1oiLz48Y2lyY2xlIGNsYXNzPSJjbHMtMSIgY3g9IjE1LjczIiBjeT0iNS44OSIgcj0iMiIvPjx0ZXh0IHRyYW5zZm9ybT0icm90YXRlKDIwIC00OC4yNDQgMzAuNjcpIiBzdHlsZT0iZm9udC1zaXplOjEycHg7ZmlsbDpncmF5O2ZvbnQtZmFtaWx5OlJvYm90by1NZWRpdW0sUm9ib3RvIj4kPC90ZXh0PjwvZz48L3N2Zz4=)}.scylla-icon--release-note{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMntmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kO3N0cm9rZS13aWR0aDouOTFweH08L3N0eWxlPjwvZGVmcz48ZyBpZD0iQ2FscXVlXzIiIGRhdGEtbmFtZT0iQ2FscXVlIDIiPjxwYXRoIHN0eWxlPSJzdHJva2Utd2lkdGg6LjlweDtmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kIiBkPSJNMjEuNSAyNC41aC0xN1Y1LjdMOC45NS41NCAyMS41LjV2MjR6Ii8+PHBhdGggY2xhc3M9ImNscy0yIiBkPSJNNC42NSA1LjVIOS41VjFNNy41IDguNWgxMU03LjUgMTEuNWgxMU03LjUgMTQuNWgxMU03LjUgMTcuNWgxMU03LjUgMjAuNWgxMSIvPjwvZz48L3N2Zz4=)}.scylla-icon--resource-center{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfS5jbHMtMntmaWxsOmdyYXl9PC9zdHlsZT48L2RlZnM+PGcgaWQ9IkNhbHF1ZV80IiBkYXRhLW5hbWU9IkNhbHF1ZSA0Ij48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Ik01LjUgMi41aDYuOTFsLjA5IDIwaC03di0yMHoiLz48cGF0aCBjbGFzcz0iY2xzLTIiIGQ9Ik04IDRoMnYxMC45N0w4IDE1VjR6Ii8+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNNS4zNiAyLjI5IDIuNSAzLjV2MThsMi43OSAxLjE0Ii8+PHBhdGggc3R5bGU9InN0cm9rZS13aWR0aDouNjhweDtmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kIiBkPSJtMTIuNTcgMjEuODYgMS41Ny43NSIvPjxwYXRoIHN0eWxlPSJzdHJva2Utd2lkdGg6Ljg1cHg7ZmlsbDpub25lO3N0cm9rZTpncmF5O3N0cm9rZS1saW5lY2FwOnJvdW5kO3N0cm9rZS1saW5lam9pbjpyb3VuZCIgZD0ibTE0LjExIDIuNS0xLjU0LjU3Ii8+PGNpcmNsZSBjbGFzcz0iY2xzLTIiIGN4PSI5IiBjeT0iMTkiIHI9IjEiLz48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Ik0xNC41IDIuNWg2Ljk0bC4wNiAyMGgtN3YtMjB6Ii8+PHBhdGggY2xhc3M9ImNscy0yIiBkPSJNMTcgNGgydjEwLjk3TDE3IDE1VjR6Ii8+PGNpcmNsZSBjbGFzcz0iY2xzLTIiIGN4PSIxOCIgY3k9IjE5IiByPSIxIi8+PHBhdGggY2xhc3M9ImNscy0yIiBkPSJNMTIuNiAyLjczaDEuNjdWMjIuNkgxMi42ek0yLjU4IDIxLjVsMi43NSAxLjFWMi43M2wtMi42Ni45NC0uMDkgMTcuODN6Ii8+PC9nPjwvc3ZnPg==)}.scylla-icon--roadmap{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMSwuY2xzLTJ7ZmlsbDpub25lO3N0cm9rZTpncmF5fS5jbHMtMXtzdHJva2UtbGluZWNhcDpyb3VuZDtzdHJva2UtbGluZWpvaW46cm91bmQ7c3Ryb2tlLXdpZHRoOi45OHB4fS5jbHMtMntzdHJva2UtbWl0ZXJsaW1pdDoxMH0uY2xzLTN7ZmlsbDpncmF5fTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJDYWxxdWVfNCIgZGF0YS1uYW1lPSJDYWxxdWUgNCI+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJtLjUgNC41IDgtMyA4IDQgOC0zdjE3bC04IDMtOC00LTggM3YtMTd6TTguNSAxLjVWMThNMTYuNSA1LjVWMjIiLz48cGF0aCBjbGFzcz0iY2xzLTIiIGQ9Ik0yLjUgMTMgNyAxNi41TTcgMTJsLTQuNSA1LjVNMTguNSA4bDQuNSAzLjVNMjMgN2wtNC41IDUuNSIvPjxwYXRoIGNsYXNzPSJjbHMtMyIgZD0iTTEwIDEzaDF2MWgtMXpNMTIgMTJoMXYxaC0xek0xNCAxMWgxdjFoLTF6Ii8+PC9nPjwvc3ZnPg==)}.scylla-icon--search{background-image:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZD0iTTEwLjUgMThhNy41IDcuNSAwIDEgMCAwLTE1IDcuNSA3LjUgMCAwIDAgMCAxNVpNMjEgMjFsLTUuMi01LjIiIHN0cm9rZT0iIzAwMCIgc3Ryb2tlLXdpZHRoPSIyIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiLz48L3N2Zz4=)}.scylla-icon--slack{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0NDggNTEyIj48IS0tISBGb250IEF3ZXNvbWUgUHJvIDYuMC4wIGJ5IEBmb250YXdlc29tZSAtIGh0dHBzOi8vZm9udGF3ZXNvbWUuY29tIExpY2Vuc2UgLSBodHRwczovL2ZvbnRhd2Vzb21lLmNvbS9saWNlbnNlIChDb21tZXJjaWFsIExpY2Vuc2UpIENvcHlyaWdodCAyMDIyIEZvbnRpY29ucywgSW5jLi0tPjxwYXRoIGQ9Ik05NC4xMiAzMTUuMWMwIDI1LjktMjEuMTYgNDcuMDYtNDcuMDYgNDcuMDZTMCAzNDEgMCAzMTUuMWMwLTI1LjkgMjEuMTYtNDcuMDYgNDcuMDYtNDcuMDZoNDcuMDZ2NDcuMDZ6bTIzLjcyIDBjMC0yNS45IDIxLjE2LTQ3LjA2IDQ3LjA2LTQ3LjA2czQ3LjA2IDIxLjE2IDQ3LjA2IDQ3LjA2djExNy44NGMwIDI1LjktMjEuMTYgNDcuMDYtNDcuMDYgNDcuMDZzLTQ3LjA2LTIxLjE2LTQ3LjA2LTQ3LjA2VjMxNS4xem00Ny4wNi0xODguOThjLTI1LjkgMC00Ny4wNi0yMS4xNi00Ny4wNi00Ny4wNlMxMzkgMzIgMTY0LjkgMzJzNDcuMDYgMjEuMTYgNDcuMDYgNDcuMDZ2NDcuMDZIMTY0Ljl6bTAgMjMuNzJjMjUuOSAwIDQ3LjA2IDIxLjE2IDQ3LjA2IDQ3LjA2cy0yMS4xNiA0Ny4wNi00Ny4wNiA0Ny4wNkg0Ny4wNkMyMS4xNiAyNDMuOTYgMCAyMjIuOCAwIDE5Ni45czIxLjE2LTQ3LjA2IDQ3LjA2LTQ3LjA2SDE2NC45em0xODguOTggNDcuMDZjMC0yNS45IDIxLjE2LTQ3LjA2IDQ3LjA2LTQ3LjA2IDI1LjkgMCA0Ny4wNiAyMS4xNiA0Ny4wNiA0Ny4wNnMtMjEuMTYgNDcuMDYtNDcuMDYgNDcuMDZoLTQ3LjA2VjE5Ni45em0tMjMuNzIgMGMwIDI1LjktMjEuMTYgNDcuMDYtNDcuMDYgNDcuMDYtMjUuOSAwLTQ3LjA2LTIxLjE2LTQ3LjA2LTQ3LjA2Vjc5LjA2YzAtMjUuOSAyMS4xNi00Ny4wNiA0Ny4wNi00Ny4wNiAyNS45IDAgNDcuMDYgMjEuMTYgNDcuMDYgNDcuMDZWMTk2Ljl6TTI4My4xIDM4NS44OGMyNS45IDAgNDcuMDYgMjEuMTYgNDcuMDYgNDcuMDYgMCAyNS45LTIxLjE2IDQ3LjA2LTQ3LjA2IDQ3LjA2LTI1LjkgMC00Ny4wNi0yMS4xNi00Ny4wNi00Ny4wNnYtNDcuMDZoNDcuMDZ6bTAtMjMuNzJjLTI1LjkgMC00Ny4wNi0yMS4xNi00Ny4wNi00Ny4wNiAwLTI1LjkgMjEuMTYtNDcuMDYgNDcuMDYtNDcuMDZoMTE3Ljg0YzI1LjkgMCA0Ny4wNiAyMS4xNiA0Ny4wNiA0Ny4wNiAwIDI1LjktMjEuMTYgNDcuMDYtNDcuMDYgNDcuMDZIMjgzLjF6Ii8+PC9zdmc+)}.scylla-icon--stack-overflow{background-image:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjQiIGhlaWdodD0iMzEiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Im0yMS45NDkuMTEzIDIuMDQzIDExLjY3LTIuNTE0LjQzMkwxOS40MzUuNTQ1IDIxLjk1LjExNFptLTE3Ljk3MyAyNiAxMS45NDUtLjAwNS0uMDAyLTIuNTMtMTEuOTQ0LjAwNi4wMDEgMi41M1ptMTIuMjMyLTUuNzc3TDQuMzE1IDE5LjI1bC0uMjM1IDIuNTIgMTEuODk0IDEuMDg1LjIzNC0yLjUxOVptLTEwLjc1LTYuMzc1IDExLjUzNSAzLjA3NC0uNjYyIDIuNDQzLTExLjUzNS0zLjA3NS42NjItMi40NDJabTEzLjA0LjE4TDguMjEyIDguMTI2bC0xLjI5NyAyLjE3OCAxMC4yODkgNi4wMTcgMS4yOTYtMi4xNzhabS00LjIwNi0xMS41NiA2LjczIDkuNzg3LTIuMTA4IDEuNDI0LTYuNzMtOS43ODUgMi4xMDgtMS40MjVaIiBmaWxsPSIjMDAwIi8+PHBhdGggZD0iTTE3Ljk1IDE3Ljc4OVYyOC4xM0gyLjI4MlYxNy43ODlILjI0M3YxMi4zMjZIMTkuOThWMTcuNzg5aC0yLjAzWiIgZmlsbD0iIzAwMCIvPjwvc3ZnPg==)}.scylla-icon--summit{background-image:url(data:image/svg+xml;base64,PHN2ZyBpZD0iQ2FscXVlXzEiIGRhdGEtbmFtZT0iQ2FscXVlIDEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmlld0JveD0iMCAwIDI1IDI1Ij48ZGVmcz48c3R5bGU+LmNscy0xe2ZpbGw6bm9uZTtzdHJva2U6IzRkNGQ0ZDtzdHJva2UtbGluZWNhcDpyb3VuZDtzdHJva2UtbGluZWpvaW46cm91bmR9PC9zdHlsZT48L2RlZnM+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJtMTYuNSAyMiAxLTYuNS0xMCAuMDMgMSA2LjQzIi8+PHBhdGggZD0iTTMuNDYgMTJBNS42OSA1LjY5IDAgMCAxIDUgNy41IiBzdHlsZT0ic3Ryb2tlLXdpZHRoOjEuMXB4O3N0cm9rZTojNGQ0ZDRkO3N0cm9rZS1saW5lY2FwOnJvdW5kO3N0cm9rZS1saW5lam9pbjpyb3VuZDtmaWxsOm5vbmUiLz48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Ik0xNC42MiA1YTIuMzMgMi4zMyAwIDAgMS0yLjI1IDIuNWMtMS4zMyAwLTItMS4xMi0xLjk1LTIuNDRzLjctMi41IDItMi40OEEyLjI3IDIuMjcgMCAwIDEgMTQuNjIgNVpNMTcuNTggMTJhMy4yMyAzLjIzIDAgMCAwLTMuNDYtMy41SDExQTMuMjYgMy4yNiAwIDAgMCA3LjUgMTIiLz48Y2lyY2xlIGN4PSI0Ljk0IiBjeT0iNi45NiIgcj0iMS4wMSIgc3R5bGU9ImZpbGw6IzRkNGQ0ZDtzdHJva2Utd2lkdGg6MS4xcHg7c3Ryb2tlOiM0ZDRkNGQ7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kIi8+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNNy41NCAxOC41SDQuNWwtMi02aDIwbC0yIDZoLTMiLz48L3N2Zz4=)}.scylla-icon--support{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJDYWxxdWVfNCIgZGF0YS1uYW1lPSJDYWxxdWUgNCI+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNMTguMTkgNy41YTEwIDEwIDAgMCAxIC4yMSAyLjA3YzAgNC4zNi0yLjYzIDYuOTMtNS45IDYuOTNzLTUuOTQtMi41Ny01Ljk0LTYuOTNhMTAuNTEgMTAuNTEgMCAwIDEgLjIyLTIuMTIiLz48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Ik03LjY3IDIuMjNBNi41OCA2LjU4IDAgMCAxIDEyLjUuNWE1LjY1IDUuNjUgMCAwIDEgNC4yOSAxLjdjMS45MyAxLjk0IDIuMzUgNS4wNyAyLjQzIDYuNzJhMS40OSAxLjQ5IDAgMCAwLS43OS4wNSA4LjY4IDguNjggMCAwIDAtLjA4LTEuMTZoMGE1LjUzIDUuNTMgMCAwIDEtMS43Ny0yLjM0TDE2LjQ5IDVsLS4zOC4yMkExOSAxOSAwIDAgMSA2LjggNy4zOGEuNTIuNTIgMCAwIDAtLjQyLjE2Yy0uMjMuMjQtLjE1LjY1LS4wNyAxLjA4IDAgLjExIDAgLjIyLjA1LjMyYTEuNCAxLjQgMCAwIDAtLjU4IDBjLS4xLTEuNDUtLjA2LTQuNjggMS44OS02LjcxWk02LjM4IDljLS42NS0uMDgtMSAuMS0xLjE0Ljc5YTIuMDYgMi4wNiAwIDAgMCAxLjM3IDIuMjlNMTguNTYgOWMuNjUtLjA4IDEuMDUuMSAxLjE0Ljc5YTIuMDYgMi4wNiAwIDAgMS0xLjM3IDIuMjlNOS41IDE4LjIzVjE1LjVNMTUuNSAxNS41djIuNzNNMi41IDI0LjE2Yy4yNC0yIC41OS0zLjYzIDIuNDMtNC40OWEyNC4yOSAyNC4yOSAwIDAgMSA0LjgyLTEuMzdNMjIuNSAyNC4zM2MtLjI0LTItLjQyLTMuOC0yLjI2LTQuNjZhMjQuMjkgMjQuMjkgMCAwIDAtNC44Mi0xLjM3Ii8+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNMTUuMzkgMTguMzlhNC4zNyA0LjM3IDAgMCAxLTIuOTEgMS4wNyA0LjQyIDQuNDIgMCAwIDEtMi44OS0xLjA1Ii8+PHBhdGggc3R5bGU9ImZpbGw6Z3JheSIgZD0iTTExIDEzaDN2MmgtM3oiLz48cGF0aCBkPSJNMTguMDcgMTJhOS4yMSA5LjIxIDAgMCAxLTUuNTMgMi4wNyIgc3R5bGU9InN0cm9rZS1taXRlcmxpbWl0OjEwO2ZpbGw6bm9uZTtzdHJva2U6Z3JheSIvPjwvZz48L3N2Zz4=)}.scylla-icon--tech-talks{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJDYWxxdWVfNCIgZGF0YS1uYW1lPSJDYWxxdWUgNCI+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNOC4zOSA0LjVIMjMuNXYxM2gtMTUiLz48Y2lyY2xlIGN4PSI0LjUiIGN5PSI2LjUiIHI9IjIiIHN0eWxlPSJzdHJva2UtbWl0ZXJsaW1pdDoxMDtmaWxsOm5vbmU7c3Ryb2tlOmdyYXkiLz48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Ik0xLjUgOS41aDJsLjguODYuNy0uODZoNS41OGExIDEgMCAxIDEgMCAySDYuNXYxMC44OGExIDEgMCAwIDEtMSAxLjEyIDEgMSAwIDAgMS0xLTEgMSAxIDAgMCAxLTEgMSAuOTMuOTMgMCAwIDEtMS0xdi02Yy0uNzggMC0yLS40Ny0yLTF2LTVhMSAxIDAgMCAxIDEtMVoiLz48L2c+PC9zdmc+)}.scylla-icon--testing{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJDYWxxdWVfNCIgZGF0YS1uYW1lPSJDYWxxdWUgNCI+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNNi41IDYuNWgxMnYxMmgtMTJ6Ii8+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNNC41IDQuNWgxNnYxNmgtMTZ6Ii8+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJtOC41IDEwLjUgNSA1IDExLTEyIi8+PC9nPjwvc3ZnPg==)}.scylla-icon--thumbs-up{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSJjdXJyZW50Q29sb3IiIHN0cm9rZS13aWR0aD0iMiIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIiBjbGFzcz0iZmVhdGhlciBmZWF0aGVyLXRodW1icy11cCI+PHBhdGggZD0iTTE0IDlWNWEzIDMgMCAwIDAtMy0zbC00IDl2MTFoMTEuMjhhMiAyIDAgMCAwIDItMS43bDEuMzgtOWEyIDIgMCAwIDAtMi0yLjN6TTcgMjJINGEyIDIgMCAwIDEtMi0ydi03YTIgMiAwIDAgMSAyLTJoMyIvPjwvc3ZnPg==)}.scylla-icon--thumbs-down{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSJjdXJyZW50Q29sb3IiIHN0cm9rZS13aWR0aD0iMiIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIiBjbGFzcz0iZmVhdGhlciBmZWF0aGVyLXRodW1icy1kb3duIj48cGF0aCBkPSJNMTAgMTV2NGEzIDMgMCAwIDAgMyAzbDQtOVYySDUuNzJhMiAyIDAgMCAwLTIgMS43bC0xLjM4IDlhMiAyIDAgMCAwIDIgMi4zem03LTEzaDIuNjdBMi4zMSAyLjMxIDAgMCAxIDIyIDR2N2EyLjMxIDIuMzEgMCAwIDEtMi4zMyAySDE3Ii8+PC9zdmc+)}.scylla-icon--tip{background-image:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZD0iTTEyIDI0QzUuNCAyNCAwIDE4LjYgMCAxMlM1LjQgMCAxMiAwczEyIDUuNCAxMiAxMi01LjQgMTItMTIgMTJabTAtMjJDNi41IDIgMiA2LjUgMiAxMnM0LjUgMTAgMTAgMTAgMTAtNC41IDEwLTEwUzE3LjUgMiAxMiAyWiIgZmlsbD0iI2ZmZiIvPjxwYXRoIGQ9Ik0xMSAxNmMtLjMgMC0uNS0uMS0uNy0uM2wtMy0zYy0uNC0uNC0uNC0xIDAtMS40LjQtLjQgMS0uNCAxLjQgMGwzIDNjLjQuNC40IDEgMCAxLjQtLjIuMi0uNC4zLS43LjNaIiBmaWxsPSIjZmZmIi8+PHBhdGggZD0iTTExIDE2Yy0uMyAwLS41LS4xLS43LS4zLS40LS40LS40LTEgMC0xLjRsNi02Yy40LS40IDEtLjQgMS40IDAgLjQuNC40IDEgMCAxLjRsLTYgNmMtLjIuMi0uNC4zLS43LjNaIiBmaWxsPSIjZmZmIi8+PC9zdmc+)}.scylla-icon--training{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJDYWxxdWVfMiIgZGF0YS1uYW1lPSJDYWxxdWUgMiI+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNMTcuNSAxNS41SC41di0xM2gxOE01LjUgMjVsNC00LjMgNCA0LjMiLz48Y2lyY2xlIGN4PSIyMSIgY3k9IjQiIHI9IjIuNSIgc3R5bGU9InN0cm9rZS1taXRlcmxpbWl0OjEwO2ZpbGw6bm9uZTtzdHJva2U6Z3JheSIvPjxwYXRoIGNsYXNzPSJjbHMtMSIgZD0iTTIzLjQxIDcuNWgtMS41MkwyMSA5bC0uOS0xLjVIMTNBMS44IDEuOCAwIDAgMCAxMS41IDlhMS44IDEuOCAwIDAgMCAxLjUgMS41aDQuNXYxMy4yNEExLjQxIDEuNDEgMCAwIDAgMTkgMjVhMS40MiAxLjQyIDAgMCAwIDEuNS0xLjIyIDEuNTMgMS41MyAwIDAgMCAzIDB2LTcuMTFhMS4xMSAxLjExIDAgMCAwIDEuMDktMS4xOFY4LjY3YTEuMTggMS4xOCAwIDAgMC0xLjE4LTEuMTdaTTkuNSAxNS40NHY1LjM4Ii8+PC9nPjwvc3ZnPg==)}.collapsible-button .side-nav__content .toctree-checkbox:checked~label i,.collapsible-button .side-nav__content i,.scylla-icon--triangle-down,.side-nav__content .collapsible-button i,.side-nav__content .scylla-icon--expand,.side-nav__content .toctree-checkbox:checked~label .collapsible-button i,.side-nav__content .toctree-checkbox:checked~label .scylla-icon--expand{background-image:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTAiIGhlaWdodD0iNSIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cGF0aCBmaWxsLXJ1bGU9ImV2ZW5vZGQiIGNsaXAtcnVsZT0iZXZlbm9kZCIgZD0ibTAgMCA1IDUgNS01SDBaIiBmaWxsPSIjM0EyRDU1Ii8+PC9zdmc+)}.scylla-icon--university{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJDYWxxdWVfNCIgZGF0YS1uYW1lPSJDYWxxdWUgNCI+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJtMS41IDguNSAxMS00IDExIDR2M2wtMTEgNC0xMS00di0zeiIvPjxwYXRoIGNsYXNzPSJjbHMtMSIgZD0iTTUuNSAxMi41djVhMTIuNDYgMTIuNDYgMCAwIDAgNyAyIDExLjIgMTEuMiAwIDAgMCA3LTJ2LTUiLz48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Im0xMy41IDkuNSA4IDEuMjN2OC43N00yMi41IDE2LjV2MyIvPjwvZz48L3N2Zz4=)}.scylla-icon--users-blog{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMntmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJDYWxxdWVfNCIgZGF0YS1uYW1lPSJDYWxxdWUgNCI+PHBhdGggc3R5bGU9InN0cm9rZS13aWR0aDouOThweDtmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kIiBkPSJNMjMuNSAyLjVoLTIydjE2aDEzdjQuMTdsNC4wNC00LjE3IDQuOTYtLjA0VjIuNXoiLz48cGF0aCBjbGFzcz0iY2xzLTIiIGQ9Ik0xMC44NSA4QTEwLjM4IDEwLjM4IDAgMCAxIDExIDkuNWMwIDIuNDctMS4yMSA0LTMgNHMtMy41LTItMy41LTQuNWE0LjE4IDQuMTggMCAwIDEgMC0xIi8+PHBhdGggY2xhc3M9ImNscy0yIiBkPSJNNS4yIDUuMDdhMy4yMiAzLjIyIDAgMCAxIDIuNS0xIDMuMTYgMy4xNiAwIDAgMSAyLjQgMSA2LjIyIDYuMjIgMCAwIDEgMS4zIDMuODEuNzQuNzQgMCAwIDAtLjQyIDBjMC0uMjQgMC0uNDQtLjA1LS42NmgwQTMgMyAwIDAgMSAxMCA2Ljl2LS4yNGwtLjIxLjEyQTkuNjIgOS42MiAwIDAgMSA0LjczIDhhLjI1LjI1IDAgMCAwLS4yMi4wOWMtLjEzLjE0LS4wOS4zNyAwIC42MXYuMThhLjg1Ljg1IDAgMCAwLS4zMiAwQTUuMzcgNS4zNyAwIDAgMSA1LjIgNS4wN1pNNC41MSA4LjkzYy0uMzUgMC0uNTcuMDUtLjYxLjQ0YTEuMTcgMS4xNyAwIDAgMCAuNzMgMS4zTTExIDguOTNjLjM2IDAgLjU3LjA1LjYyLjQ0YTEuMTcgMS4xNyAwIDAgMS0uNzQgMS4zTTYuMzEgMTQuMTN2LS44NE05LjI1IDEzLjE5di45NE0yLjQyIDE4Yy4xMy0xLjE1LjU4LTIuNTIgMS41OC0zYTE0LjcxIDE0LjcxIDAgMCAxIDIuMzEtLjgyTTEzLjUgMThjLS4xMy0xLjE1LS41MS0yLjUyLTEuNS0zcy0yLjUtMS0yLjUtMSIvPjxwYXRoIGNsYXNzPSJjbHMtMiIgZD0iTTkuMzQgMTQuMjJhMi4yMyAyLjIzIDAgMCAxLTEuNTYuNjEgMi4zMiAyLjMyIDAgMCAxLTEuNTUtLjU5TTIxLjUgNi41aC03TTIxLjUgOS41aC03TTE4LjUgMTIuNWgtNCIvPjwvZz48L3N2Zz4=)}.admonition.caution .admonition-title:before,.admonition.warning .admonition-title:before,.scylla-icon--warning{background-image:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PG1hc2sgaWQ9ImEiIG1hc2stdHlwZT0iYWxwaGEiIG1hc2tVbml0cz0idXNlclNwYWNlT25Vc2UiIHg9IjAiIHk9IjEiIHdpZHRoPSIyNCIgaGVpZ2h0PSIyMSI+PHBhdGggZD0iTTMuNSAyMmMtLjUgMC0xLS4xLTEuNS0uNEMuNiAyMC44LjEgMTguOS45IDE3LjVMOS40IDMuM2MuMy0uNC42LS44IDEtMSAuNy0uNCAxLjUtLjUgMi4zLS4zLjguMiAxLjQuNyAxLjkgMS40TDIzIDE3LjVjLjMuNS40IDEgLjQgMS41IDAgLjgtLjMgMS42LS45IDIuMS0uNS42LTEuMi45LTIgLjloLTE3Wm03LjYtMTcuNkwyLjcgMTguNWMtLjMuNS0uMSAxLjEuNCAxLjQuMS4xLjMuMS40LjFoMTYuOWMuMyAwIC41LS4xLjctLjMuMi0uMi4zLS40LjMtLjcgMC0uMiAwLS4zLS4xLS41TDEyLjkgNC40Yy0uMy0uNS0uOS0uNi0xLjQtLjQtLjIuMS0uMy4yLS40LjRaIiBmaWxsPSIjMDYxOTM4Ii8+PHBhdGggZD0iTTEyIDE0Yy0uNiAwLTEtLjQtMS0xVjljMC0uNi40LTEgMS0xczEgLjQgMSAxdjRjMCAuNi0uNCAxLTEgMVpNMTIgMThjLS4zIDAtLjUtLjEtLjctLjMtLjItLjItLjMtLjQtLjMtLjcgMC0uMSAwLS4zLjEtLjQuMS0uMS4xLS4yLjItLjMuMS0uMS4yLS4yLjMtLjIuMi0uMS40LS4xLjYtLjEuMSAwIC4xIDAgLjIuMS4xIDAgLjEgMCAuMi4xIDAgMCAuMS4xLjIuMS4xLjEuMi4yLjIuMyAwIC4xLjEuMy4xLjQgMCAuMy0uMS41LS4zLjctLjMuMi0uNS4zLS44LjNaIiBmaWxsPSIjMDYxOTM4Ii8+PC9tYXNrPjxnIG1hc2s9InVybCgjYSkiPjxwYXRoIGZpbGw9IiMwNjE5MzgiIGQ9Ik0wIDBoMjR2MjRIMHoiLz48L2c+PC9zdmc+)}.scylla-icon--webinars{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMntmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJDYWxxdWVfNCIgZGF0YS1uYW1lPSJDYWxxdWUgNCI+PHBhdGggc3R5bGU9InN0cm9rZS1taXRlcmxpbWl0OjEwO2ZpbGw6bm9uZTtzdHJva2U6Z3JheSIgZD0iTTEuNSA1LjVoMjJ2MTRoLTIyeiIvPjxwYXRoIGNsYXNzPSJjbHMtMiIgZD0iTTkuNDcgMjAuNXYxLjg4TTE1LjUgMjAuNXYyTTYuNSAyMi41aDEyIi8+PHBhdGggc3R5bGU9ImZpbGw6Z3JheSIgZD0ibTkgOSA3LjUgMy41M0w5IDE2Vjl6Ii8+PC9nPjwvc3ZnPg==)}.scylla-icon--whitepapers{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMntmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJDYWxxdWVfNCIgZGF0YS1uYW1lPSJDYWxxdWUgNCI+PHBhdGggc3R5bGU9ImZpbGw6Z3JheSIgZD0iTTggOWg4djJIOHoiLz48cGF0aCBjbGFzcz0iY2xzLTIiIGQ9Ik0xNC4wNiAxLjUgMy41IDEuNTJWMjMuNWgxN1Y3bC02LjQ0LTUuNXoiLz48cGF0aCBkPSJNMTQuMzIgMS40MnYzLjM3YTIuMDYgMi4wNiAwIDAgMCAyLjA4IDIuMWgzLjY3IiBzdHlsZT0ic3Ryb2tlLW1pdGVybGltaXQ6MTA7ZmlsbDpub25lO3N0cm9rZTpncmF5Ii8+PHBhdGggY2xhc3M9ImNscy0yIiBkPSJNNi41IDE5LjVoNE0xMy41IDE5LjVoNE02LjUgMTYuNWg0TTEzLjUgMTYuNWg0TTYuNSAxMy41aDRNMTMuNSAxMy41aDQiLz48L2c+PC9zdmc+)}.scylla-icon--workshop{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMSwuY2xzLTJ7ZmlsbDpub25lO3N0cm9rZTojNGQ0ZDRkfS5jbHMtMXtzdHJva2UtbWl0ZXJsaW1pdDoxMH0uY2xzLTJ7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJDYWxxdWVfNCIgZGF0YS1uYW1lPSJDYWxxdWUgNCI+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNMS41IDUuNWgyMnYxNGgtMjJ6Ii8+PHBhdGggY2xhc3M9ImNscy0yIiBkPSJtOS41IDE5LjUtLjAzIDIuODhNMTUuNSAxOS41djNNNi41IDIyLjVoMTIiLz48cGF0aCBzdHlsZT0iZmlsbDojNGQ0ZDRkIiBkPSJtNCA4IDIgOCAuOTctMy45NUwxMSAxMiA0IDh6Ii8+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJtNi40NyAxMS4zNCAzLjM3IDQuMjgiLz48L2c+PC9zdmc+)}.button{background:transparent;border:1px solid #3a2d55;border-radius:4px;color:#3a2d55;display:inline;font-size:14px;letter-spacing:1px;line-height:21px;margin:0;padding:12px 14px}.button:focus,.button:hover{background:transparent;color:#3a2d55;text-decoration:none}.button--reverse{background:#fff;border:0}.button--reverse:focus,.button--reverse:hover{background:#fff}.tooltip{background-color:rgba(0,0,0,.56);border-radius:4px;font-size:12px;padding:6px}.tooltip:before{display:none!important}.tooltip:empty{display:none!important}.has-tip{border:0;cursor:pointer}.scylla-dropdown{color:#23263b;font-size:14px;line-height:20px}.scylla-dropdown a,.scylla-dropdown a:focus,.scylla-dropdown a:hover{color:#23263b!important;padding:0!important}.scylla-dropdown__item{font-size:16px;padding:15px}.scylla-dropdown__title{align-items:center;display:flex!important;position:static!important}.scylla-dropdown__title:after{display:none!important}.scylla-dropdown__title .chevron{min-height:5px;width:10px}.scylla-dropdown__content{background:#fff;border:0;border-radius:8px;box-shadow:0 4px 25px rgba(0,0,0,.15);font-size:16px;list-style:none;margin-top:15px;overflow:hidden;padding:16px 0;width:max-content}.scylla-dropdown__content li{padding:7px 16px}.scylla-dropdown__content .contents.local>ul>li a:before,.scylla-dropdown__content .secondary-side-nav__content li a:before,.scylla-dropdown__content li .admonition-title:before,.scylla-dropdown__content li .scylla-icon,.secondary-side-nav__content .scylla-dropdown__content li a:before{margin-right:10px}.enlarge-image{cursor:zoom-in}.enlarge-image-reveal{background:transparent;border:none;cursor:zoom-out;padding:0;text-align:center;width:fit-content}.enlarge-image-reveal img{background-color:#fff;padding:15px}.header{background-color:#fff;box-shadow:0 2px 22px rgba(74,93,166,.15);justify-content:space-between;padding:12.75px 0;position:fixed;width:100%;z-index:99}.header,.header-logo{align-items:center;display:flex}.header-logo{margin-left:20px;width:auto}.header-logo__img{width:110px}.header-logo__bar{background-color:#3a2d55;border-left:1px solid #3a2d55;height:11.56px;margin:0 7.5px;width:0}.header-logo__text{color:#3a2d55;font-size:10.11px;letter-spacing:.722408px;line-height:12px;text-transform:uppercase}.header-navigation{display:none}.header-button{display:none;margin-left:15px;text-transform:uppercase}.header-search-box{display:none;margin-right:20px;width:200px}.scylla-dropdown--header .scylla-dropdown__item{font-size:14px}.scylla-dropdown--header .scylla-dropdown__title{text-transform:uppercase}.scylla-dropdown--header .scylla-dropdown__title .chevron{margin-left:10px}.contents.local>ul>li .scylla-dropdown--header .scylla-dropdown__content a:before,.scylla-dropdown--header .scylla-dropdown__content .admonition-title:before,.scylla-dropdown--header .scylla-dropdown__content .contents.local>ul>li a:before,.scylla-dropdown--header .scylla-dropdown__content .scylla-icon,.scylla-dropdown--header .scylla-dropdown__content .secondary-side-nav__content li a:before,.secondary-side-nav__content li .scylla-dropdown--header .scylla-dropdown__content a:before{min-height:20px;width:20px}@media screen and (min-width:1024px){.header{padding:18px 0}.header-logo__img{width:152px}.header-logo__bar{height:16px;margin:0 10px}.header-logo__text{font-size:14px;letter-spacing:.722408px;line-height:12px;text-transform:uppercase}.header-navigation{align-items:center;display:flex;justify-content:center}.header-search-box{display:block}}@media screen and (min-width:1200px){.header-logo{margin-left:30px;width:357px}.header-search-box{margin-right:30px;max-width:20%;width:318px}.header-button{display:block}}.side-nav{background:#fff;display:none;height:100vh;left:0;line-height:24px;max-height:calc(100vh - 50px);overflow-y:auto;padding:20px 20px 0;position:fixed;top:50px;width:100%;z-index:100}.side-nav__title{font-weight:700;margin-bottom:20px}.side-nav__content{max-width:90%;overflow-wrap:break-word}.side-nav__content label,.side-nav__content label i{margin:0;padding:0}.side-nav__content label{font-size:inherit;line-height:1;margin-left:5px;max-height:5px}.collapsible-button .side-nav__content i,.side-nav__content .collapsible-button i,.side-nav__content .scylla-icon--expand{height:5px;vertical-align:top;width:10px}.side-nav__content .toctree-checkbox{display:none;position:absolute;right:20px}.side-nav__content .toctree-checkbox~ul{display:none;margin-right:20px}.side-nav__content .toctree-checkbox:checked~ul{display:block}.side-nav__content ul{margin:0}.side-nav__content a{color:#23263b}.side-nav__content a:hover{color:#3c4fe0;font-weight:400}.side-nav__content li{list-style:none;padding:0 0 24px}.side-nav__content li.has-children{align-items:center;display:flex;flex-wrap:wrap}.side-nav__content li.has-children>a{max-width:calc(100% - 15px)}.side-nav__content li.has-children.current{padding-bottom:20px}.side-nav__content li.has-children:hover>a{color:#3c4fe0}.side-nav__content li.has-children:hover>.toctree-checkbox~label i{filter:invert(38%) sepia(71%) saturate(6789%) hue-rotate(231deg) brightness(90%) contrast(95%)}.side-nav__content li.current-page>a{color:#3c4fe0}.side-nav__content li.current-page>.toctree-checkbox:checked~label i{filter:invert(38%) sepia(71%) saturate(6789%) hue-rotate(231deg) brightness(90%) contrast(95%)}.side-nav__content li ul{margin-top:18px;width:100%}.side-nav__content li ul li{border-left:1px solid #3c4fe0;padding:4px 0 4px 13px}.side-nav__content li ul ul{margin-left:0}.side-nav__content li .label{display:none}.side-nav__versions{max-width:90%}.side-nav__search,.side-nav__versions .dropdown{margin-bottom:20px}.collapsible-button{background:#fff;background-color:#fff;border:0;border-radius:8px;border-radius:50%;bottom:10px;box-shadow:0 4px 25px rgba(0,0,0,.15);cursor:pointer;display:none;font-size:0;left:300px;overflow:hidden;padding:13.5px;position:fixed}.collapsible-button i{height:16px;margin:0;width:16px}.side-nav--collapsed .collapsible-button{border-radius:0 20px 20px 0;left:-10px}.side-nav--collapsed .collapsible-button i{transform:rotate(180deg)}.layout--has-banner .side-nav{max-height:calc(100vh - 92.5px)}@media screen and (min-width:1024px){.side-nav{background-color:#f6f8ff;display:block;height:100%;left:auto;max-height:100vh;max-height:calc(100vh - 80px);padding:30px 40px;top:80px;width:286px;z-index:25}.side-nav__content{max-width:100%;padding-bottom:180px}.side-nav__search{display:none}.side-nav__versions{max-width:100%}.toctree-checkbox{right:40px}.layout--has-banner .side-nav{max-height:calc(100vh - 150px)}}@media screen and (min-width:1200px){.side-nav{width:357px}.side-nav--collapsed{background-color:transparent;padding-left:0;padding-right:0;width:126px}.side-nav--collapsed .side-nav-content{display:none}.collapsible-button{display:block}}.side-nav-toggle{cursor:pointer;display:block;margin-right:20px;position:relative;z-index:300}@media screen and (min-width:1024px){.side-nav-toggle{display:none}}.secondary-side-nav{display:none;height:100%;line-height:24px;padding:20px;width:100%}.secondary-side-nav__content{overflow-wrap:break-word}.secondary-side-nav__content ul{list-style:none;margin:0}.secondary-side-nav__content li{border-bottom:1px solid rgba(90,94,154,.1);display:none;padding:10px 0;word-break:break-word}.secondary-side-nav__content li:last-child{border:0}.secondary-side-nav__content li .label{display:none}.secondary-side-nav__content li a{align-items:baseline;color:#b3bac5;display:flex;font-size:14px}.secondary-side-nav__content li a:before{content:"";filter:invert(40%) sepia(11%) saturate(2157%) hue-rotate(198deg) brightness(89%) contrast(87%)!important;flex-shrink:0;margin-right:10px;min-height:10px;opacity:.5;width:6px}.secondary-side-nav__content li a.current,.secondary-side-nav__content li a:hover{color:#23263b;font-weight:400}.secondary-side-nav__content li a.current:before,.secondary-side-nav__content li a:hover:before{filter:brightness(0);opacity:1}.secondary-side-nav__content li a.current{font-weight:700}.secondary-side-nav__content>ul>li>ul>li{display:block}.secondary-side-nav__content>ul>li{border:0;display:block}.secondary-side-nav__content>ul>li>a{display:none}@media screen and (min-width:1200px){.secondary-side-nav{display:block;max-height:100vh;max-height:calc(100vh - 80px);overflow-y:auto;padding:60px 60px 60px 20px;position:fixed;top:80px;width:286px}.secondary-side-nav__content{padding-bottom:180px}.layout--has-banner .secondary-side-nav{max-height:calc(100vh - 150px)}}.layout{display:flex}.pre-content{align-items:center;display:flex;justify-content:space-between;margin-bottom:20px}.content{margin-top:50px;max-width:1440px;overflow-wrap:break-word;padding:20px;scroll-margin-top:50px;width:100%}.content .line-block,.content p{line-height:28px;margin-bottom:20px}.content ul{list-style:none}.content ul li:before{color:#b3bac5;content:"•";float:left;font-family:FontAwesome;font-size:20px;font-weight:700;margin-left:-1em;margin-top:-2px;width:1em}.content ul ul{list-style:circle}.content ul ul li:before{content:""}.content ol ol{list-style:lower-latin}.content img{margin-bottom:30px}.content section{margin-top:-50px;padding-top:50px}.content .inline-icon.fa-check{color:#42c4e6}.layout--full-width .content{max-width:100%;padding:0;width:100%}.layout--full-width .content .hero-wrapper,.layout--full-width .content .topics-grid{max-width:1190px}.layout--full-width .content.content--collapsed{margin-left:0}.layout--full-width:not(.layout--sidebar) .content{margin-left:0}.layout--has-banner .content{scroll-margin-top:92.5px}.layout--has-banner .content section{margin-top:-92.5px;padding-top:92.5px}.landing__content{padding:0 16px}@media screen and (min-width:1024px){.content{margin-left:286px;margin-top:80px;min-height:calc(100vh - 260px);padding-bottom:100px;scroll-margin-top:80px;width:calc(100% - 286px)}.content section{margin-top:-80px;padding-top:80px}}@media screen and (min-width:1200px){.content{margin-left:357px;padding:60px 40px 40px;width:calc(100% - 643px)}.content--collapsed{margin-left:126px;width:calc(100% - 412px)}.pre-content{margin-bottom:10px}.layout--has-banner .content{scroll-margin-top:150px}.layout--has-banner .content section{margin-top:-150px;padding-top:150px}.landing__content{padding:0 60px}.landing--floating .landing__content{position:relative;top:-70px}}.contents.local>ul{margin-bottom:30px;margin-left:0}.contents.local>ul>li{border-bottom:1px solid rgba(90,94,154,.1);padding:10px 0;word-break:break-word}.contents.local>ul>li:before{content:""}.contents.local>ul>li:last-child{border:0}.contents.local>ul>li ul{display:none}.contents.local>ul>li p{margin:0}.contents.local>ul>li a{font-size:14px}.contents.local>ul>li a:before{content:"";filter:invert(40%) sepia(11%) saturate(2157%) hue-rotate(198deg) brightness(89%) contrast(87%)!important;margin-right:10px;min-height:10px;opacity:.5;width:10px}.contents.local>ul>li a.current:before,.contents.local>ul>li a:hover:before{filter:brightness(0);opacity:1}.topic-title{color:rgba(35,38,59,.75);font-size:10px;letter-spacing:1.5px;margin-bottom:0;text-transform:uppercase}.notice{margin-top:40px}.footer{background-color:#fff;box-shadow:0 -4px 10px hsla(0,0%,82%,.25);padding:30px 0;position:relative;width:100%;z-index:50}.footer-group{margin:0 auto;max-width:1030px;padding:0 20px}.footer-top{align-items:center;border-bottom:1px solid rgba(0,0,0,.1);display:flex;flex-wrap:wrap;justify-content:space-between;padding-bottom:8px;text-align:center}.footer-logo{margin-bottom:30px;width:100%}.footer-logo img{float:left;height:36px}.footer-links{text-align:left}.footer-links__link{color:#333;font-size:12px;font-weight:500;letter-spacing:2.4px;margin-right:16px;text-transform:uppercase}.footer-actions{align-items:center;display:flex;justify-content:space-between;width:90px}.footer-actions__link{color:#000}.footer-actions__link img{height:23px}.footer-bottom{color:#979797;display:flex;flex-wrap:wrap;font-size:12px;font-style:normal;font-weight:400;justify-content:center;letter-spacing:1.4px;line-height:23px;padding:20px 0 10px;text-align:center;text-transform:uppercase}@media screen and (max-width:510px){.footer-links{margin-bottom:20px}}@media screen and (min-width:1024px){.footer{padding:30px 0}.footer-group{padding:0}.footer-top{padding-bottom:30px}.footer-logo{margin:0;width:auto}.footer-links{padding:0 40px}.footer-links__link{font-size:14px;margin-right:28px}.footer-actions{width:110px}.footer-actions__link img{height:28px}.footer-bottom .footer-bottom__copyright,.footer-bottom .footer-bottom__last-updated,.footer-bottom .footer-bottom__version{padding:0 10px}.footer-bottom .footer-bottom__copyright{border-left:none}}.not-found{background-color:#f6f8ff;height:100%;overflow:hidden}.not-found__icon{display:block;margin:40px auto;max-width:300px}.not-found__text{text-align:center}.not-found__text h1{font-size:60px;line-height:1}.not-found__text p{margin:30px 0;width:100%}.not-found__button{text-transform:uppercase}.admonition{border-radius:4px;box-shadow:0 4px 4px rgba(0,0,0,.12);color:rgba(0,0,0,.56);font-size:14px;line-height:20px;margin-bottom:30px;overflow:auto;padding:20px;position:relative}.admonition:before{bottom:0;content:" ";left:0;position:absolute;right:0;top:0;z-index:-1}.admonition-title{color:#23263b;margin-bottom:0!important}.admonition-title:before{content:"";margin-right:8px;min-height:24px;width:24px}.admonition p:not(.admonition-title){margin-bottom:0!important;margin-left:32px}.admonition.tip{border:1px solid #43a047}.admonition.tip:before{border-left:8px solid rgba(67,160,71,.4)}.admonition.tip .admonition-title:before{filter:invert(47%) sepia(11%) saturate(2286%) hue-rotate(73deg) brightness(109%) contrast(88%)}.admonition.note{border:1px solid #1976d2}.admonition.note:before{border-left:8px solid rgba(25,118,210,.4)}.admonition.note .admonition-title:before{filter:invert(44%) sepia(55%) saturate(2310%) hue-rotate(191deg) brightness(81%) contrast(103%)}.admonition.caution{border:1px solid #ffab00}.admonition.caution:before{border-left:8px solid rgba(255,171,0,.4)}.admonition.caution .admonition-title:before{filter:invert(77%) sepia(56%) saturate(3332%) hue-rotate(357deg) brightness(98%) contrast(108%)}.admonition.warning{border:1px solid #e74c3c}.admonition.warning:before{border-left:8px solid rgba(231,76,60,.4)}.admonition.warning .admonition-title:before{filter:invert(41%) sepia(42%) saturate(6427%) hue-rotate(343deg) brightness(99%) contrast(83%)}.breadcrumbs{margin-bottom:0;text-transform:uppercase}.breadcrumbs .bread__item,.breadcrumbs .bread__item:not(.bread__item--last):after,.breadcrumbs a{color:#23263b;font-size:12px;font-weight:400;letter-spacing:1.5px;line-height:2;margin:0;padding:0}.breadcrumbs .bread__item:before{display:none}.breadcrumbs .bread__item:not(.bread__item--last):after{content:"/";margin:0 5px;opacity:1;position:relative}.breadcrumbs .bread__highlight{color:#3c4fe0}.breadcrumbs .bread__highlight:hover{font-weight:700;text-decoration:none}code{background-color:#f7f8f9;border:none;border-radius:4px;color:#23263b;font-size:14px}code.download{background:none;color:#23263b}.highlight{background:transparent!important}.highlight pre{background-color:#f7f8f9;border-radius:8px;color:#23263b;font-size:14px;line-height:26px;margin-bottom:30px;overflow:auto;padding:16px}.highlight a.copybtn{right:1em;top:1em}.highlighttable{background-color:#f7f8f9;border-radius:16px;box-shadow:none}.highlighttable tbody{background-color:transparent;border:0}.highlighttable tbody td{padding:15px!important}.highlighttable tbody tr{border-top:none}.highlighttable .linenos{background-color:#f7f8f9;color:#5a7184;width:50px}.highlighttable .linenos span{line-height:26px}.highlighttable .highlight pre{background-color:transparent;margin:0;padding:0}.highlighttable .highlight a.copybtn{right:.2em;top:.2em}.hide-copy-button .copybtn{display:none}.sphinx_collapse__label{display:flex!important;flex-direction:row-reverse;font-size:medium;font-weight:700;justify-content:flex-end;margin-left:0!important}.sphinx_collapse__icon{margin-left:5px;margin-right:0}.sphinx_collapse__input:checked~.sphinx_collapse__label,.sphinx_collapse__label:hover{color:#3c4fe0}.sphinx_collapse__input:checked~.sphinx_collapse__label .sphinx_collapse__icon,.sphinx_collapse__label:hover .sphinx_collapse__icon{border-top-color:#3c4fe0}.sphinx_collapse__content{margin-top:10px}.contribute{margin:0 0 20px}.contribute__item{font-size:14px;list-style:none;padding-bottom:10px}.contribute__item .icon{margin-right:5px}.content-navigation{display:flex;justify-content:space-between;margin-top:40px}.navigation{max-width:50%;word-break:break-word}.navigation,.navigation__link{display:flex}.navigation__title{word-wrap:break-word;color:#23263b;font-size:12px;font-weight:500;letter-spacing:1.5px;line-height:24px;text-transform:uppercase}.navigation__title .colored{color:#42c4e6}.navigation__button{background:#fff;background-color:#fff;border:0;border-radius:8px;box-shadow:0 4px 25px rgba(0,0,0,.15);cursor:pointer;display:none;font-size:0;height:fit-content;overflow:hidden;padding:13.5px 16.5px}.navigation__button i{height:16px;margin:0;width:10px}.navigation--prev .navigation__title{margin-left:15px}.navigation--next .navigation__title{margin-right:15px;text-align:right}@media screen and (min-width:1200px){.navigation__title{display:inline-block}.navigation__button{display:block}.navigation--next .navigation__title{text-align:left}}.scylla-dropdown--versions .scylla-dropdown__item{background:#fff;border-radius:8px;box-shadow:0 28px 32px rgba(0,0,0,.06);width:100%}.scylla-dropdown--versions .scylla-dropdown__title{align-items:center;display:flex;justify-content:space-between}.scylla-dropdown--versions .scylla-dropdown__title .chevron{min-height:12px;transform:rotate(90deg);width:8px}@media screen and (min-width:1024px){.scylla-dropdown--versions .scylla-dropdown__item{box-shadow:none}}.feedback-container{font-size:16px;margin-top:40px;text-align:left}.feedback-container__title{font-weight:700;margin-bottom:5px!important}.feedback-container__button{background:#fff;border:0;border-radius:8px;box-shadow:0 4px 25px rgba(0,0,0,.15);cursor:pointer;margin:4px;overflow:hidden;padding:8px}.feedback-container__button.active{border:1px solid #3c4fe0}.feedback-container__icon{height:20px;width:20px}.feedback-container__message{font-size:16px;margin-top:10px}.hero{background:#f6f8ff;margin-bottom:30px;overflow:hidden;padding:30px 16px;text-align:left}.hero__title{font-size:28px;font-weight:500;line-height:38px;margin-bottom:14px;max-width:229px}.hero__text{font-size:16px;line-height:26px;max-width:343px}.hero__text a{border-bottom:1px dotted #23263b;color:#23263b}.hero__text p{margin-bottom:0!important}.hero__img{position:absolute;right:-18px;top:20px}.hero__img img{margin-bottom:0!important;width:124px}.hero__button{margin-top:20px;text-transform:uppercase}.hero__button .icon{margin-right:5px}.hero__search-box{box-shadow:0 4px 25px rgba(0,0,0,.02);margin-top:20px}.hero-wrapper{align-items:center;display:flex;justify-content:space-between;margin:0 auto;position:relative}@media screen and (min-width:640px){.hero{padding:60px 16px}.hero__title{font-size:32px;line-height:42px;max-width:482px}.hero__text{font-size:18px;line-height:26px;max-width:482px}.hero__img{display:block;position:static}.hero__img img{height:100%;width:295px}.hero .hero-wrapper{flex-direction:row-reverse}.hero .landing--floating .hero{padding:30px 16px 100px}}@media screen and (min-width:1024px){.hero{padding:60px}}.label{background-color:#23263b;border:0;border-radius:4px;color:#fff;font-size:inherit}.label--note{background-color:#1976d2}.label--tip{background-color:#43a047}.label--caution{background-color:#ffab00}.label--warning{background-color:#e74c3c}.last-updated{color:#4458a3;font-size:12px;letter-spacing:1.5px;margin:10px 0;text-transform:uppercase}.last-updated__icon{font-size:14px}@media screen and (min-width:1024px){.last-updated{float:right;margin:0}}.panel{border:0;border-radius:4px;margin-bottom:30px}.promo-banner{background-color:#4458a3;background-image:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTQ0MCIgaGVpZ2h0PSI3MCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48bWFzayBpZD0iYSIgbWFzay10eXBlPSJhbHBoYSIgbWFza1VuaXRzPSJ1c2VyU3BhY2VPblVzZSIgeD0iMCIgeT0iMCIgd2lkdGg9IjE0NDAiIGhlaWdodD0iNzAiPjxwYXRoIGZpbGw9IiM0NDU4QTMiIGQ9Ik0wIDBoMTQ0MHY3MEgweiIvPjwvbWFzaz48ZyBtYXNrPSJ1cmwoI2EpIiBmaWxsPSIjNTA2NEFFIj48cGF0aCBkPSJNLTE5MyAyMDEuODg0IDEuNS0xMzUgMzU3LjQzNiA3MC41bC0xOTQuNSAzMzYuODg0ek0xMDkyLjkyLTM4LjAwOSA5NzIuODAzLTI0Ni4wNTcgNDAyLjk5NiA4Mi45MiA1MjMuMTEzIDI5MC45N3oiLz48cGF0aCBkPSJtMTAzOC0zOC4wMDkgMTIwLjExNy0yMDguMDQ5IDU2OS44MDcgMzI4Ljk3OS0xMjAuMTE3IDIwOC4wNDl6Ii8+PC9nPjwvc3ZnPg==);background-position:50%;background-repeat:no-repeat;background-size:cover;display:none;overflow:hidden;position:fixed;top:0;width:100%;z-index:900}.promo-banner__icon{margin-right:15px}.promo-banner__icon img{height:40px}.promo-banner__title{color:#fff;font-size:12px;line-height:16px;margin-right:15px}.promo-banner__button{background:#fff;border-radius:4px;font-size:12px;min-width:max-content;padding:5px}.promo-banner__close{display:none;position:absolute;right:16px;top:16px}.contents.local>ul>li .promo-banner__close a:before,.promo-banner__close .admonition-title:before,.promo-banner__close .contents.local>ul>li a:before,.promo-banner__close .scylla-icon,.promo-banner__close .secondary-side-nav__content li a:before,.secondary-side-nav__content li .promo-banner__close a:before{filter:brightness(100%);height:34px;width:34px}.promo-banner__close:hover{cursor:pointer;filter:opacity(.8)}.promo-banner-wrapper{align-items:center;display:flex;justify-content:center;padding:5.85px 20px}@media(min-width:1024px){.promo-banner__title{font-size:18px;line-height:23px}.promo-banner__button{font-size:14px;padding:8.5px}.promo-banner__close{display:block}.promo-banner-wrapper{flex-direction:unset;padding:16px}}.custom-scroll-bar::-webkit-scrollbar{background-color:transparent;width:5px}.custom-scroll-bar::-webkit-scrollbar-thumb{background-color:#b3bac5;-webkit-border-radius:8px;border-radius:8px}.search-box{background:#f7f8f9;border-radius:4px;display:flex;padding:10px 15px}.search-box--hero{background-color:#fff;padding:12px 14px}.search-box:before{background-image:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZD0iTTEwLjUgMThhNy41IDcuNSAwIDEgMCAwLTE1IDcuNSA3LjUgMCAwIDAgMCAxNVpNMjEgMjFsLTUuMi01LjIiIHN0cm9rZT0iIzAwMCIgc3Ryb2tlLXdpZHRoPSIyIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiLz48L3N2Zz4=);background-repeat:no-repeat;background-size:contain;content:"";display:inline-block;filter:brightness(0);margin-top:2px;min-height:18px;min-width:18px;vertical-align:middle;width:20px}.search-box .er-dummy-search,.search-box .er-dummy-search-box,.search-box .er-search-form,.search-box ci-search,.search-box input{margin:0!important;width:100%!important}.search-box input{background:transparent!important;color:rgba(80,80,80,.5)!important;font-size:14px!important;padding:0!important}.search-box input::placeholder{color:rgba(80,80,80,.5)!important;opacity:1!important}.search-box button{display:none!important}.er_search_suggestions{background:#fff;border:0;border:0!important;border-radius:8px;box-shadow:0 4px 25px rgba(0,0,0,.15);overflow:hidden}.er_search_suggestions .er-search-result-box{border-width:1px!important;padding-bottom:10px!important;padding-top:10px!important}.er_search_suggestions .er-search-result-box:hover{background:#f7f8f9!important}.er_search_suggestions .er_more_result_btn{cursor:pointer}.er_search_suggestions h3{font-size:16px!important}.er-search-content{padding:20px!important}#er_search_results .er-search-result-box{display:block!important;margin:10px auto 0!important;width:100%!important}#er_search_results .text,#er_search_results .title a,#er_search_results .url a{max-width:100%!important}#search-result-input-form{max-width:800px!important}#er_search_button{text-align:center}#er_clear_input{right:0!important;top:0!important}.er-facet-header{background-color:transparent!important;border:0!important;padding:0 0 8px!important}.er-facet-val{padding:5px 2px!important}.er-facet-val input{display:block!important;margin:0}#er_search_pagination{margin-top:20px!important}#er_search_pagination li.er-paginator-list.er-active{border-bottom:0!important;font-weight:700}.er-suggestion-sm .er_search_input_dummy{margin:0!important}.er-suggestion-sm .er_search_button_dummy{border:0!important}#er_gcs_mobile_model_container .er-facet-values .er-facet-val{align-items:baseline}@media screen and (min-width:640px){.er-facets{display:none;max-width:300px!important;min-width:auto!important;width:auto!important}}@media screen and (min-width:1024px){.er-suggestions{left:15px!important}}@media screen and (min-width:1200px){.er-facets{display:block;position:fixed!important}.er-facet-count{display:none}}.sphinx-tabs{margin-bottom:30px}.sphinx-tabs-tab{border-bottom:1px solid rgba(0,0,0,.56);color:rgba(0,0,0,.56);cursor:pointer;font-size:14px;font-weight:500;line-height:13px;padding:20px 25px}.sphinx-tabs-tab[aria-selected=true]{border-bottom:2px solid #2196f3;color:#2196f3;padding-bottom:19px}.sphinx-tabs-panel{margin:30px 0}.table-wrapper{border:1px solid #e0e0e0;border-radius:4px;box-shadow:0 1px 2px rgba(0,0,0,.25);display:block;margin-bottom:30px;max-width:100%;overflow-x:auto}table{color:#000;font-size:14px;line-height:24px;margin:0;overflow:hidden}table p{margin:0!important}table caption{background:#f6f8ff;border-bottom:1px solid #e0e0e0;color:#23263b;padding:10px 25px}table thead{background:#f6f8ff;border:0;border-bottom:1px solid #4458a3}table thead th{color:#23263b;font-size:14px;font-weight:700}table td,table thead th{padding:20px 25px}table tbody tr{background-color:transparent!important;border-top:1px solid #e0e0e0;line-height:18px}table:not(.highlighttable) tbody tr:first-child{border-top:1px solid #4458a3}table.thead-border thead .row-odd th{color:#23263b}table.thead-border thead .row-even th{font-weight:400}table.thead-border thead th{border:1px solid #e0e0e0}table.thead-border thead tr:first-child th{border-top:none}table.thead-border thead tr:last-child th{border-bottom:none}table.thead-border thead tr th:first-child{border-left:none}table.thead-border thead tr th:last-child{border-right:none}.topics-grid{display:block;margin:0 auto 30px}.topics-grid__title{color:#23263b;font-size:24px;font-weight:700;line-height:32px;margin-bottom:6px}.topics-grid__text{color:#4458a3;font-size:18px;line-height:24px}.topics-grid--scrollable .hs{-ms-overflow-style:none;display:grid;grid-auto-flow:column;overflow-x:scroll;padding:20px 10px;scrollbar-width:none}.topics-grid--scrollable .hs::-webkit-scrollbar{display:none}.topics-grid--scrollable .hs .topic-box:last-child:after{content:"";width:20px}.topic-box{align-items:stretch;display:flex}.topic-box .card{background:#fff;border:1px solid transparent;border-radius:8px;box-shadow:0 4px 25px rgba(0,0,0,.15);display:flex;flex-direction:column;font-size:18px;margin:0 auto 30px;overflow:hidden;padding:20px;position:relative}.topic-box .card:hover{border:1px solid #4458a3;color:#23263b;font-weight:400}.topic-box__title{color:#23263b;font-size:16px;font-weight:700;line-height:24px;margin-bottom:0}.topic-box__title img{bottom:0;opacity:.3;position:absolute;right:0;top:0}.topic-box__body{color:#000;display:flex;flex-direction:column;flex-grow:1;max-width:80%}.topic-box__body .container{flex-grow:1;margin:0;padding:0}.topic-box__body .line-block,.topic-box__body p{font-size:16px;line-height:19px;margin-top:10px}.topic-box__anchor{color:#42c4e6;font-size:14px;font-weight:700;line-height:24px}.topic-box__icon{display:block;font-size:50px;margin-bottom:20px}.topic-box__icon i{filter:brightness(0);min-height:50px;width:100%}.topic-box__icon img{bottom:-12px;display:none;height:140px;margin:0;opacity:.3;position:absolute;right:-5px}.topic-box--product .card{box-shadow:none;padding:20px;text-align:center}.topic-box--product .card .topic-box__title{color:#23263b;font-size:14px}.topic-box--product .card .topic-box__body{display:flex;flex-direction:column;max-width:100%}.topic-box--product .card .topic-box__body .line-block,.topic-box--product .card .topic-box__body p{font-size:12px}.topic-box--product .card .topic-box__icon img{display:inline-block;max-height:84px;opacity:1;position:static}.topic-box--product .card:hover{background:#fff;border:0;border-radius:8px;box-shadow:0 4px 25px rgba(0,0,0,.15);overflow:hidden}@media screen and (max-width:1024px){.topics-grid--scrollable .topic-box{width:280px!important}.topic-box--product:nth-last-child(-n+2) .card{margin-bottom:0}}@media screen and (min-width:1024px){.topics-grid{margin-bottom:10px}.topics-grid__text{font-size:16px}.topics-grid--scrollable .hs{display:flex;overflow-x:initial;padding:0}.topics-grid--scrollable .hs .topic-box:last-child:after{display:none}.topic-box .card{margin-bottom:60px;padding:45px 30px}.topic-box__title{font-size:20px;line-height:32px}.topic-box__body .line-block,.topic-box__body p{font-size:18px;line-height:26px}.topic-box__anchor{font-size:20px;line-height:26px}.topic-box .topic-box__icon img{display:inline-block}.topic-box--product .card{padding:20px}.topic-box--product .card .topic-box__title{font-size:18px;line-height:24px}.topic-box--product .card .topic-box__body .line-block,.topic-box--product .card .topic-box__body p{font-size:14px}.topic-box--product .card .topic-box__icon img{max-height:111px}.landing .topics-grid--products{margin-bottom:40px}} \ No newline at end of file diff --git a/3.24.8-scylla/_static/doctools.js b/3.24.8-scylla/_static/doctools.js new file mode 100644 index 0000000000..8cbf1b161a --- /dev/null +++ b/3.24.8-scylla/_static/doctools.js @@ -0,0 +1,323 @@ +/* + * doctools.js + * ~~~~~~~~~~~ + * + * Sphinx JavaScript utilities for all documentation. + * + * :copyright: Copyright 2007-2021 by the Sphinx team, see AUTHORS. + * :license: BSD, see LICENSE for details. + * + */ + +/** + * select a different prefix for underscore + */ +$u = _.noConflict(); + +/** + * make the code below compatible with browsers without + * an installed firebug like debugger +if (!window.console || !console.firebug) { + var names = ["log", "debug", "info", "warn", "error", "assert", "dir", + "dirxml", "group", "groupEnd", "time", "timeEnd", "count", "trace", + "profile", "profileEnd"]; + window.console = {}; + for (var i = 0; i < names.length; ++i) + window.console[names[i]] = function() {}; +} + */ + +/** + * small helper function to urldecode strings + * + * See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/decodeURIComponent#Decoding_query_parameters_from_a_URL + */ +jQuery.urldecode = function(x) { + if (!x) { + return x + } + return decodeURIComponent(x.replace(/\+/g, ' ')); +}; + +/** + * small helper function to urlencode strings + */ +jQuery.urlencode = encodeURIComponent; + +/** + * This function returns the parsed url parameters of the + * current request. Multiple values per key are supported, + * it will always return arrays of strings for the value parts. + */ +jQuery.getQueryParameters = function(s) { + if (typeof s === 'undefined') + s = document.location.search; + var parts = s.substr(s.indexOf('?') + 1).split('&'); + var result = {}; + for (var i = 0; i < parts.length; i++) { + var tmp = parts[i].split('=', 2); + var key = jQuery.urldecode(tmp[0]); + var value = jQuery.urldecode(tmp[1]); + if (key in result) + result[key].push(value); + else + result[key] = [value]; + } + return result; +}; + +/** + * highlight a given string on a jquery object by wrapping it in + * span elements with the given class name. + */ +jQuery.fn.highlightText = function(text, className) { + function highlight(node, addItems) { + if (node.nodeType === 3) { + var val = node.nodeValue; + var pos = val.toLowerCase().indexOf(text); + if (pos >= 0 && + !jQuery(node.parentNode).hasClass(className) && + !jQuery(node.parentNode).hasClass("nohighlight")) { + var span; + var isInSVG = jQuery(node).closest("body, svg, foreignObject").is("svg"); + if (isInSVG) { + span = document.createElementNS("http://www.w3.org/2000/svg", "tspan"); + } else { + span = document.createElement("span"); + span.className = className; + } + span.appendChild(document.createTextNode(val.substr(pos, text.length))); + node.parentNode.insertBefore(span, node.parentNode.insertBefore( + document.createTextNode(val.substr(pos + text.length)), + node.nextSibling)); + node.nodeValue = val.substr(0, pos); + if (isInSVG) { + var rect = document.createElementNS("http://www.w3.org/2000/svg", "rect"); + var bbox = node.parentElement.getBBox(); + rect.x.baseVal.value = bbox.x; + rect.y.baseVal.value = bbox.y; + rect.width.baseVal.value = bbox.width; + rect.height.baseVal.value = bbox.height; + rect.setAttribute('class', className); + addItems.push({ + "parent": node.parentNode, + "target": rect}); + } + } + } + else if (!jQuery(node).is("button, select, textarea")) { + jQuery.each(node.childNodes, function() { + highlight(this, addItems); + }); + } + } + var addItems = []; + var result = this.each(function() { + highlight(this, addItems); + }); + for (var i = 0; i < addItems.length; ++i) { + jQuery(addItems[i].parent).before(addItems[i].target); + } + return result; +}; + +/* + * backward compatibility for jQuery.browser + * This will be supported until firefox bug is fixed. + */ +if (!jQuery.browser) { + jQuery.uaMatch = function(ua) { + ua = ua.toLowerCase(); + + var match = /(chrome)[ \/]([\w.]+)/.exec(ua) || + /(webkit)[ \/]([\w.]+)/.exec(ua) || + /(opera)(?:.*version|)[ \/]([\w.]+)/.exec(ua) || + /(msie) ([\w.]+)/.exec(ua) || + ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec(ua) || + []; + + return { + browser: match[ 1 ] || "", + version: match[ 2 ] || "0" + }; + }; + jQuery.browser = {}; + jQuery.browser[jQuery.uaMatch(navigator.userAgent).browser] = true; +} + +/** + * Small JavaScript module for the documentation. + */ +var Documentation = { + + init : function() { + this.fixFirefoxAnchorBug(); + this.highlightSearchWords(); + this.initIndexTable(); + if (DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS) { + this.initOnKeyListeners(); + } + }, + + /** + * i18n support + */ + TRANSLATIONS : {}, + PLURAL_EXPR : function(n) { return n === 1 ? 0 : 1; }, + LOCALE : 'unknown', + + // gettext and ngettext don't access this so that the functions + // can safely bound to a different name (_ = Documentation.gettext) + gettext : function(string) { + var translated = Documentation.TRANSLATIONS[string]; + if (typeof translated === 'undefined') + return string; + return (typeof translated === 'string') ? translated : translated[0]; + }, + + ngettext : function(singular, plural, n) { + var translated = Documentation.TRANSLATIONS[singular]; + if (typeof translated === 'undefined') + return (n == 1) ? singular : plural; + return translated[Documentation.PLURALEXPR(n)]; + }, + + addTranslations : function(catalog) { + for (var key in catalog.messages) + this.TRANSLATIONS[key] = catalog.messages[key]; + this.PLURAL_EXPR = new Function('n', 'return +(' + catalog.plural_expr + ')'); + this.LOCALE = catalog.locale; + }, + + /** + * add context elements like header anchor links + */ + addContextElements : function() { + $('div[id] > :header:first').each(function() { + $('\u00B6'). + attr('href', '#' + this.id). + attr('title', _('Permalink to this headline')). + appendTo(this); + }); + $('dt[id]').each(function() { + $('\u00B6'). + attr('href', '#' + this.id). + attr('title', _('Permalink to this definition')). + appendTo(this); + }); + }, + + /** + * workaround a firefox stupidity + * see: https://bugzilla.mozilla.org/show_bug.cgi?id=645075 + */ + fixFirefoxAnchorBug : function() { + if (document.location.hash && $.browser.mozilla) + window.setTimeout(function() { + document.location.href += ''; + }, 10); + }, + + /** + * highlight the search words provided in the url in the text + */ + highlightSearchWords : function() { + var params = $.getQueryParameters(); + var terms = (params.highlight) ? params.highlight[0].split(/\s+/) : []; + if (terms.length) { + var body = $('div.body'); + if (!body.length) { + body = $('body'); + } + window.setTimeout(function() { + $.each(terms, function() { + body.highlightText(this.toLowerCase(), 'highlighted'); + }); + }, 10); + $('') + .appendTo($('#searchbox')); + } + }, + + /** + * init the domain index toggle buttons + */ + initIndexTable : function() { + var togglers = $('img.toggler').click(function() { + var src = $(this).attr('src'); + var idnum = $(this).attr('id').substr(7); + $('tr.cg-' + idnum).toggle(); + if (src.substr(-9) === 'minus.png') + $(this).attr('src', src.substr(0, src.length-9) + 'plus.png'); + else + $(this).attr('src', src.substr(0, src.length-8) + 'minus.png'); + }).css('display', ''); + if (DOCUMENTATION_OPTIONS.COLLAPSE_INDEX) { + togglers.click(); + } + }, + + /** + * helper function to hide the search marks again + */ + hideSearchWords : function() { + $('#searchbox .highlight-link').fadeOut(300); + $('span.highlighted').removeClass('highlighted'); + }, + + /** + * make the url absolute + */ + makeURL : function(relativeURL) { + return DOCUMENTATION_OPTIONS.URL_ROOT + '/' + relativeURL; + }, + + /** + * get the current relative url + */ + getCurrentURL : function() { + var path = document.location.pathname; + var parts = path.split(/\//); + $.each(DOCUMENTATION_OPTIONS.URL_ROOT.split(/\//), function() { + if (this === '..') + parts.pop(); + }); + var url = parts.join('/'); + return path.substring(url.lastIndexOf('/') + 1, path.length - 1); + }, + + initOnKeyListeners: function() { + $(document).keydown(function(event) { + var activeElementType = document.activeElement.tagName; + // don't navigate when in search box, textarea, dropdown or button + if (activeElementType !== 'TEXTAREA' && activeElementType !== 'INPUT' && activeElementType !== 'SELECT' + && activeElementType !== 'BUTTON' && !event.altKey && !event.ctrlKey && !event.metaKey + && !event.shiftKey) { + switch (event.keyCode) { + case 37: // left + var prevHref = $('link[rel="prev"]').prop('href'); + if (prevHref) { + window.location.href = prevHref; + return false; + } + break; + case 39: // right + var nextHref = $('link[rel="next"]').prop('href'); + if (nextHref) { + window.location.href = nextHref; + return false; + } + break; + } + } + }); + } +}; + +// quick alias for translations +_ = Documentation.gettext; + +$(document).ready(function() { + Documentation.init(); +}); diff --git a/3.24.8-scylla/_static/documentation_options.js b/3.24.8-scylla/_static/documentation_options.js new file mode 100644 index 0000000000..49f4b69a38 --- /dev/null +++ b/3.24.8-scylla/_static/documentation_options.js @@ -0,0 +1,12 @@ +var DOCUMENTATION_OPTIONS = { + URL_ROOT: document.getElementById("documentation_options").getAttribute('data-url_root'), + VERSION: '3.24.8', + LANGUAGE: 'None', + COLLAPSE_INDEX: false, + BUILDER: 'html', + FILE_SUFFIX: '.html', + LINK_SUFFIX: '.html', + HAS_SOURCE: true, + SOURCELINK_SUFFIX: '.txt', + NAVIGATION_WITH_KEYS: false +}; \ No newline at end of file diff --git a/3.24.8-scylla/_static/file.png b/3.24.8-scylla/_static/file.png new file mode 100644 index 0000000000..a858a410e4 Binary files /dev/null and b/3.24.8-scylla/_static/file.png differ diff --git a/3.24.8-scylla/_static/img/banner-background.svg b/3.24.8-scylla/_static/img/banner-background.svg new file mode 100644 index 0000000000..f8520d5b3e --- /dev/null +++ b/3.24.8-scylla/_static/img/banner-background.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/3.24.8-scylla/_static/img/favicon-228x228.png b/3.24.8-scylla/_static/img/favicon-228x228.png new file mode 100644 index 0000000000..f30770c7ed Binary files /dev/null and b/3.24.8-scylla/_static/img/favicon-228x228.png differ diff --git a/3.24.8-scylla/_static/img/favicon-32x32.png b/3.24.8-scylla/_static/img/favicon-32x32.png new file mode 100644 index 0000000000..aae1708f26 Binary files /dev/null and b/3.24.8-scylla/_static/img/favicon-32x32.png differ diff --git a/3.24.8-scylla/_static/img/favicon.ico b/3.24.8-scylla/_static/img/favicon.ico new file mode 100644 index 0000000000..6c7484f082 Binary files /dev/null and b/3.24.8-scylla/_static/img/favicon.ico differ diff --git a/3.24.8-scylla/_static/img/icons/icon-about-team.svg b/3.24.8-scylla/_static/img/icons/icon-about-team.svg new file mode 100644 index 0000000000..5448c7f007 --- /dev/null +++ b/3.24.8-scylla/_static/img/icons/icon-about-team.svg @@ -0,0 +1 @@ +icon-about-team diff --git a/3.24.8-scylla/_static/img/icons/icon-about-us-m.svg b/3.24.8-scylla/_static/img/icons/icon-about-us-m.svg new file mode 100644 index 0000000000..09107d9520 --- /dev/null +++ b/3.24.8-scylla/_static/img/icons/icon-about-us-m.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/3.24.8-scylla/_static/img/icons/icon-about-us.svg b/3.24.8-scylla/_static/img/icons/icon-about-us.svg new file mode 100644 index 0000000000..1b1fcc83e3 --- /dev/null +++ b/3.24.8-scylla/_static/img/icons/icon-about-us.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/3.24.8-scylla/_static/img/icons/icon-alternator.svg b/3.24.8-scylla/_static/img/icons/icon-alternator.svg new file mode 100644 index 0000000000..7c2b4ebae0 --- /dev/null +++ b/3.24.8-scylla/_static/img/icons/icon-alternator.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/3.24.8-scylla/_static/img/icons/icon-apps.svg b/3.24.8-scylla/_static/img/icons/icon-apps.svg new file mode 100644 index 0000000000..7e93612026 --- /dev/null +++ b/3.24.8-scylla/_static/img/icons/icon-apps.svg @@ -0,0 +1 @@ + diff --git a/3.24.8-scylla/_static/img/icons/icon-architecture.svg b/3.24.8-scylla/_static/img/icons/icon-architecture.svg new file mode 100644 index 0000000000..67ebbc2f38 --- /dev/null +++ b/3.24.8-scylla/_static/img/icons/icon-architecture.svg @@ -0,0 +1 @@ +icon-architecture diff --git a/3.24.8-scylla/_static/img/icons/icon-benchmarks.svg b/3.24.8-scylla/_static/img/icons/icon-benchmarks.svg new file mode 100644 index 0000000000..e1ce2c1d78 --- /dev/null +++ b/3.24.8-scylla/_static/img/icons/icon-benchmarks.svg @@ -0,0 +1 @@ +icon-benchmarks diff --git a/3.24.8-scylla/_static/img/icons/icon-blog.svg b/3.24.8-scylla/_static/img/icons/icon-blog.svg new file mode 100644 index 0000000000..f4096cbf11 --- /dev/null +++ b/3.24.8-scylla/_static/img/icons/icon-blog.svg @@ -0,0 +1 @@ +icon-blog2 diff --git a/3.24.8-scylla/_static/img/icons/icon-careers.svg b/3.24.8-scylla/_static/img/icons/icon-careers.svg new file mode 100644 index 0000000000..2a7c6ea0b7 --- /dev/null +++ b/3.24.8-scylla/_static/img/icons/icon-careers.svg @@ -0,0 +1 @@ +icon-careers diff --git a/3.24.8-scylla/_static/img/icons/icon-chevron-left.svg b/3.24.8-scylla/_static/img/icons/icon-chevron-left.svg new file mode 100644 index 0000000000..3afa25c481 --- /dev/null +++ b/3.24.8-scylla/_static/img/icons/icon-chevron-left.svg @@ -0,0 +1,3 @@ + + + diff --git a/3.24.8-scylla/_static/img/icons/icon-chevron-right.svg b/3.24.8-scylla/_static/img/icons/icon-chevron-right.svg new file mode 100644 index 0000000000..44eb829cdc --- /dev/null +++ b/3.24.8-scylla/_static/img/icons/icon-chevron-right.svg @@ -0,0 +1,3 @@ + + + diff --git a/3.24.8-scylla/_static/img/icons/icon-circe.svg b/3.24.8-scylla/_static/img/icons/icon-circe.svg new file mode 100644 index 0000000000..875e421670 --- /dev/null +++ b/3.24.8-scylla/_static/img/icons/icon-circe.svg @@ -0,0 +1 @@ + diff --git a/3.24.8-scylla/_static/img/icons/icon-clock.svg b/3.24.8-scylla/_static/img/icons/icon-clock.svg new file mode 100644 index 0000000000..8c92469808 --- /dev/null +++ b/3.24.8-scylla/_static/img/icons/icon-clock.svg @@ -0,0 +1 @@ + diff --git a/3.24.8-scylla/_static/img/icons/icon-close.svg b/3.24.8-scylla/_static/img/icons/icon-close.svg new file mode 100644 index 0000000000..d1162b73e7 --- /dev/null +++ b/3.24.8-scylla/_static/img/icons/icon-close.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/3.24.8-scylla/_static/img/icons/icon-cloud-docs.svg b/3.24.8-scylla/_static/img/icons/icon-cloud-docs.svg new file mode 100644 index 0000000000..a9069bb6e5 --- /dev/null +++ b/3.24.8-scylla/_static/img/icons/icon-cloud-docs.svg @@ -0,0 +1 @@ + diff --git a/3.24.8-scylla/_static/img/icons/icon-cloud.svg b/3.24.8-scylla/_static/img/icons/icon-cloud.svg new file mode 100644 index 0000000000..cfb2318dae --- /dev/null +++ b/3.24.8-scylla/_static/img/icons/icon-cloud.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/3.24.8-scylla/_static/img/icons/icon-comparison.svg b/3.24.8-scylla/_static/img/icons/icon-comparison.svg new file mode 100644 index 0000000000..49d809a5df --- /dev/null +++ b/3.24.8-scylla/_static/img/icons/icon-comparison.svg @@ -0,0 +1 @@ +icon-comparison diff --git a/3.24.8-scylla/_static/img/icons/icon-contact-us.svg b/3.24.8-scylla/_static/img/icons/icon-contact-us.svg new file mode 100644 index 0000000000..9df3145dd2 --- /dev/null +++ b/3.24.8-scylla/_static/img/icons/icon-contact-us.svg @@ -0,0 +1 @@ +icon-contact-us diff --git a/3.24.8-scylla/_static/img/icons/icon-developers-blog.svg b/3.24.8-scylla/_static/img/icons/icon-developers-blog.svg new file mode 100644 index 0000000000..ee804197a0 --- /dev/null +++ b/3.24.8-scylla/_static/img/icons/icon-developers-blog.svg @@ -0,0 +1 @@ +icon-developers-blog diff --git a/3.24.8-scylla/_static/img/icons/icon-docs.svg b/3.24.8-scylla/_static/img/icons/icon-docs.svg new file mode 100644 index 0000000000..5501492f3e --- /dev/null +++ b/3.24.8-scylla/_static/img/icons/icon-docs.svg @@ -0,0 +1 @@ +icon-docs diff --git a/3.24.8-scylla/_static/img/icons/icon-enterprise-m.svg b/3.24.8-scylla/_static/img/icons/icon-enterprise-m.svg new file mode 100644 index 0000000000..97be900b50 --- /dev/null +++ b/3.24.8-scylla/_static/img/icons/icon-enterprise-m.svg @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/3.24.8-scylla/_static/img/icons/icon-enterprise.svg b/3.24.8-scylla/_static/img/icons/icon-enterprise.svg new file mode 100644 index 0000000000..ee1ac26283 --- /dev/null +++ b/3.24.8-scylla/_static/img/icons/icon-enterprise.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/3.24.8-scylla/_static/img/icons/icon-events.svg b/3.24.8-scylla/_static/img/icons/icon-events.svg new file mode 100644 index 0000000000..ba5f211864 --- /dev/null +++ b/3.24.8-scylla/_static/img/icons/icon-events.svg @@ -0,0 +1 @@ +icon-events diff --git a/3.24.8-scylla/_static/img/icons/icon-exclamation.svg b/3.24.8-scylla/_static/img/icons/icon-exclamation.svg new file mode 100644 index 0000000000..a7eb4b77a4 --- /dev/null +++ b/3.24.8-scylla/_static/img/icons/icon-exclamation.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/3.24.8-scylla/_static/img/icons/icon-expand.svg b/3.24.8-scylla/_static/img/icons/icon-expand.svg new file mode 100644 index 0000000000..3806565367 --- /dev/null +++ b/3.24.8-scylla/_static/img/icons/icon-expand.svg @@ -0,0 +1,50 @@ + + + + + + + + + diff --git a/3.24.8-scylla/_static/img/icons/icon-forum.svg b/3.24.8-scylla/_static/img/icons/icon-forum.svg new file mode 100644 index 0000000000..37a709f7a8 --- /dev/null +++ b/3.24.8-scylla/_static/img/icons/icon-forum.svg @@ -0,0 +1 @@ + diff --git a/3.24.8-scylla/_static/img/icons/icon-getting-started.svg b/3.24.8-scylla/_static/img/icons/icon-getting-started.svg new file mode 100644 index 0000000000..702500be40 --- /dev/null +++ b/3.24.8-scylla/_static/img/icons/icon-getting-started.svg @@ -0,0 +1 @@ + diff --git a/3.24.8-scylla/_static/img/icons/icon-glossary.svg b/3.24.8-scylla/_static/img/icons/icon-glossary.svg new file mode 100644 index 0000000000..e8329c2afe --- /dev/null +++ b/3.24.8-scylla/_static/img/icons/icon-glossary.svg @@ -0,0 +1 @@ + diff --git a/3.24.8-scylla/_static/img/icons/icon-home.svg b/3.24.8-scylla/_static/img/icons/icon-home.svg new file mode 100644 index 0000000000..f0b9c25419 --- /dev/null +++ b/3.24.8-scylla/_static/img/icons/icon-home.svg @@ -0,0 +1 @@ + diff --git a/3.24.8-scylla/_static/img/icons/icon-infoworld.svg b/3.24.8-scylla/_static/img/icons/icon-infoworld.svg new file mode 100644 index 0000000000..906e87279c --- /dev/null +++ b/3.24.8-scylla/_static/img/icons/icon-infoworld.svg @@ -0,0 +1 @@ +icon-infoworld diff --git a/3.24.8-scylla/_static/img/icons/icon-integrations.svg b/3.24.8-scylla/_static/img/icons/icon-integrations.svg new file mode 100644 index 0000000000..1ef0920d49 --- /dev/null +++ b/3.24.8-scylla/_static/img/icons/icon-integrations.svg @@ -0,0 +1 @@ + diff --git a/3.24.8-scylla/_static/img/icons/icon-knowledge-base.svg b/3.24.8-scylla/_static/img/icons/icon-knowledge-base.svg new file mode 100644 index 0000000000..884451270d --- /dev/null +++ b/3.24.8-scylla/_static/img/icons/icon-knowledge-base.svg @@ -0,0 +1 @@ + diff --git a/3.24.8-scylla/_static/img/icons/icon-less.svg b/3.24.8-scylla/_static/img/icons/icon-less.svg new file mode 100644 index 0000000000..3094127dec --- /dev/null +++ b/3.24.8-scylla/_static/img/icons/icon-less.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/3.24.8-scylla/_static/img/icons/icon-live-test.svg b/3.24.8-scylla/_static/img/icons/icon-live-test.svg new file mode 100644 index 0000000000..dcb5916c26 --- /dev/null +++ b/3.24.8-scylla/_static/img/icons/icon-live-test.svg @@ -0,0 +1 @@ +icon-live-test diff --git a/3.24.8-scylla/_static/img/icons/icon-mail-list.svg b/3.24.8-scylla/_static/img/icons/icon-mail-list.svg new file mode 100644 index 0000000000..0e6192a352 --- /dev/null +++ b/3.24.8-scylla/_static/img/icons/icon-mail-list.svg @@ -0,0 +1 @@ + diff --git a/3.24.8-scylla/_static/img/icons/icon-manager.svg b/3.24.8-scylla/_static/img/icons/icon-manager.svg new file mode 100644 index 0000000000..02b4e425be --- /dev/null +++ b/3.24.8-scylla/_static/img/icons/icon-manager.svg @@ -0,0 +1 @@ +icon-manager diff --git a/3.24.8-scylla/_static/img/icons/icon-memory-management.svg b/3.24.8-scylla/_static/img/icons/icon-memory-management.svg new file mode 100644 index 0000000000..e34eb4504f --- /dev/null +++ b/3.24.8-scylla/_static/img/icons/icon-memory-management.svg @@ -0,0 +1 @@ +icon-memory-management diff --git a/3.24.8-scylla/_static/img/icons/icon-modeling.svg b/3.24.8-scylla/_static/img/icons/icon-modeling.svg new file mode 100644 index 0000000000..97fa3a0e21 --- /dev/null +++ b/3.24.8-scylla/_static/img/icons/icon-modeling.svg @@ -0,0 +1 @@ + diff --git a/3.24.8-scylla/_static/img/icons/icon-monitoring.svg b/3.24.8-scylla/_static/img/icons/icon-monitoring.svg new file mode 100644 index 0000000000..80b3787f66 --- /dev/null +++ b/3.24.8-scylla/_static/img/icons/icon-monitoring.svg @@ -0,0 +1 @@ +icon-monitoring diff --git a/3.24.8-scylla/_static/img/icons/icon-networking.svg b/3.24.8-scylla/_static/img/icons/icon-networking.svg new file mode 100644 index 0000000000..40a3fd5f6f --- /dev/null +++ b/3.24.8-scylla/_static/img/icons/icon-networking.svg @@ -0,0 +1 @@ +icon-networking diff --git a/3.24.8-scylla/_static/img/icons/icon-news.svg b/3.24.8-scylla/_static/img/icons/icon-news.svg new file mode 100644 index 0000000000..a952b59937 --- /dev/null +++ b/3.24.8-scylla/_static/img/icons/icon-news.svg @@ -0,0 +1 @@ +icon-news diff --git a/3.24.8-scylla/_static/img/icons/icon-newsletter.svg b/3.24.8-scylla/_static/img/icons/icon-newsletter.svg new file mode 100644 index 0000000000..5b8d47eb15 --- /dev/null +++ b/3.24.8-scylla/_static/img/icons/icon-newsletter.svg @@ -0,0 +1 @@ +icon-newsletter diff --git a/3.24.8-scylla/_static/img/icons/icon-nsql-guides.svg b/3.24.8-scylla/_static/img/icons/icon-nsql-guides.svg new file mode 100644 index 0000000000..60ebab3795 --- /dev/null +++ b/3.24.8-scylla/_static/img/icons/icon-nsql-guides.svg @@ -0,0 +1 @@ +icon-nsql-guides diff --git a/3.24.8-scylla/_static/img/icons/icon-open-source.svg b/3.24.8-scylla/_static/img/icons/icon-open-source.svg new file mode 100644 index 0000000000..98c2ea7d5b --- /dev/null +++ b/3.24.8-scylla/_static/img/icons/icon-open-source.svg @@ -0,0 +1 @@ +icon-open-source diff --git a/3.24.8-scylla/_static/img/icons/icon-operator.svg b/3.24.8-scylla/_static/img/icons/icon-operator.svg new file mode 100644 index 0000000000..bb7d8d3ea8 --- /dev/null +++ b/3.24.8-scylla/_static/img/icons/icon-operator.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/3.24.8-scylla/_static/img/icons/icon-overview.svg b/3.24.8-scylla/_static/img/icons/icon-overview.svg new file mode 100644 index 0000000000..515c1528a2 --- /dev/null +++ b/3.24.8-scylla/_static/img/icons/icon-overview.svg @@ -0,0 +1 @@ +icon-overview diff --git a/3.24.8-scylla/_static/img/icons/icon-partners.svg b/3.24.8-scylla/_static/img/icons/icon-partners.svg new file mode 100644 index 0000000000..d0146fc497 --- /dev/null +++ b/3.24.8-scylla/_static/img/icons/icon-partners.svg @@ -0,0 +1 @@ +icon-partners diff --git a/3.24.8-scylla/_static/img/icons/icon-plus.svg b/3.24.8-scylla/_static/img/icons/icon-plus.svg new file mode 100644 index 0000000000..5757435085 --- /dev/null +++ b/3.24.8-scylla/_static/img/icons/icon-plus.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/3.24.8-scylla/_static/img/icons/icon-pricing.svg b/3.24.8-scylla/_static/img/icons/icon-pricing.svg new file mode 100644 index 0000000000..74b01db168 --- /dev/null +++ b/3.24.8-scylla/_static/img/icons/icon-pricing.svg @@ -0,0 +1 @@ +icon-pricing$ diff --git a/3.24.8-scylla/_static/img/icons/icon-release-notes.svg b/3.24.8-scylla/_static/img/icons/icon-release-notes.svg new file mode 100644 index 0000000000..80c490c7b0 --- /dev/null +++ b/3.24.8-scylla/_static/img/icons/icon-release-notes.svg @@ -0,0 +1 @@ +icon-release-notes diff --git a/3.24.8-scylla/_static/img/icons/icon-resource-center.svg b/3.24.8-scylla/_static/img/icons/icon-resource-center.svg new file mode 100644 index 0000000000..6e3ab08e79 --- /dev/null +++ b/3.24.8-scylla/_static/img/icons/icon-resource-center.svg @@ -0,0 +1 @@ +icon-ressource-center diff --git a/3.24.8-scylla/_static/img/icons/icon-roadmap.svg b/3.24.8-scylla/_static/img/icons/icon-roadmap.svg new file mode 100644 index 0000000000..c8cbf67c8c --- /dev/null +++ b/3.24.8-scylla/_static/img/icons/icon-roadmap.svg @@ -0,0 +1 @@ +icon-roadmap-4 diff --git a/3.24.8-scylla/_static/img/icons/icon-search.svg b/3.24.8-scylla/_static/img/icons/icon-search.svg new file mode 100644 index 0000000000..81aae93eef --- /dev/null +++ b/3.24.8-scylla/_static/img/icons/icon-search.svg @@ -0,0 +1,4 @@ + + + + diff --git a/3.24.8-scylla/_static/img/icons/icon-slack.svg b/3.24.8-scylla/_static/img/icons/icon-slack.svg new file mode 100644 index 0000000000..fc164ea1e7 --- /dev/null +++ b/3.24.8-scylla/_static/img/icons/icon-slack.svg @@ -0,0 +1 @@ + diff --git a/3.24.8-scylla/_static/img/icons/icon-stack-overflow.svg b/3.24.8-scylla/_static/img/icons/icon-stack-overflow.svg new file mode 100644 index 0000000000..bebe9b8274 --- /dev/null +++ b/3.24.8-scylla/_static/img/icons/icon-stack-overflow.svg @@ -0,0 +1,4 @@ + + + + diff --git a/3.24.8-scylla/_static/img/icons/icon-summit.svg b/3.24.8-scylla/_static/img/icons/icon-summit.svg new file mode 100644 index 0000000000..4b900bd0c0 --- /dev/null +++ b/3.24.8-scylla/_static/img/icons/icon-summit.svg @@ -0,0 +1 @@ + diff --git a/3.24.8-scylla/_static/img/icons/icon-support.svg b/3.24.8-scylla/_static/img/icons/icon-support.svg new file mode 100644 index 0000000000..a4228b34e8 --- /dev/null +++ b/3.24.8-scylla/_static/img/icons/icon-support.svg @@ -0,0 +1 @@ +icon-support diff --git a/3.24.8-scylla/_static/img/icons/icon-tech-talks.svg b/3.24.8-scylla/_static/img/icons/icon-tech-talks.svg new file mode 100644 index 0000000000..df42b5522b --- /dev/null +++ b/3.24.8-scylla/_static/img/icons/icon-tech-talks.svg @@ -0,0 +1 @@ +icon-tech-talks diff --git a/3.24.8-scylla/_static/img/icons/icon-testing.svg b/3.24.8-scylla/_static/img/icons/icon-testing.svg new file mode 100644 index 0000000000..2fe54efdbc --- /dev/null +++ b/3.24.8-scylla/_static/img/icons/icon-testing.svg @@ -0,0 +1 @@ +icon-testing diff --git a/3.24.8-scylla/_static/img/icons/icon-thumbs-down.svg b/3.24.8-scylla/_static/img/icons/icon-thumbs-down.svg new file mode 100644 index 0000000000..3e7bcd6d90 --- /dev/null +++ b/3.24.8-scylla/_static/img/icons/icon-thumbs-down.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/3.24.8-scylla/_static/img/icons/icon-thumbs-up.svg b/3.24.8-scylla/_static/img/icons/icon-thumbs-up.svg new file mode 100644 index 0000000000..226c44d853 --- /dev/null +++ b/3.24.8-scylla/_static/img/icons/icon-thumbs-up.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/3.24.8-scylla/_static/img/icons/icon-tip.svg b/3.24.8-scylla/_static/img/icons/icon-tip.svg new file mode 100644 index 0000000000..bf7aa6af84 --- /dev/null +++ b/3.24.8-scylla/_static/img/icons/icon-tip.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/3.24.8-scylla/_static/img/icons/icon-training.svg b/3.24.8-scylla/_static/img/icons/icon-training.svg new file mode 100644 index 0000000000..08b95a88ed --- /dev/null +++ b/3.24.8-scylla/_static/img/icons/icon-training.svg @@ -0,0 +1 @@ +icon-training diff --git a/3.24.8-scylla/_static/img/icons/icon-triangle-down.svg b/3.24.8-scylla/_static/img/icons/icon-triangle-down.svg new file mode 100644 index 0000000000..e8ae088106 --- /dev/null +++ b/3.24.8-scylla/_static/img/icons/icon-triangle-down.svg @@ -0,0 +1,3 @@ + + + diff --git a/3.24.8-scylla/_static/img/icons/icon-university.svg b/3.24.8-scylla/_static/img/icons/icon-university.svg new file mode 100644 index 0000000000..f7547ab959 --- /dev/null +++ b/3.24.8-scylla/_static/img/icons/icon-university.svg @@ -0,0 +1 @@ +icon-university diff --git a/3.24.8-scylla/_static/img/icons/icon-users-blog.svg b/3.24.8-scylla/_static/img/icons/icon-users-blog.svg new file mode 100644 index 0000000000..47e56cddcf --- /dev/null +++ b/3.24.8-scylla/_static/img/icons/icon-users-blog.svg @@ -0,0 +1 @@ +icon-users-blog diff --git a/3.24.8-scylla/_static/img/icons/icon-warning.svg b/3.24.8-scylla/_static/img/icons/icon-warning.svg new file mode 100644 index 0000000000..e4b1d40331 --- /dev/null +++ b/3.24.8-scylla/_static/img/icons/icon-warning.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/3.24.8-scylla/_static/img/icons/icon-webinars.svg b/3.24.8-scylla/_static/img/icons/icon-webinars.svg new file mode 100644 index 0000000000..5e9f5cd427 --- /dev/null +++ b/3.24.8-scylla/_static/img/icons/icon-webinars.svg @@ -0,0 +1 @@ +icon-webinars diff --git a/3.24.8-scylla/_static/img/icons/icon-whitepapers.svg b/3.24.8-scylla/_static/img/icons/icon-whitepapers.svg new file mode 100644 index 0000000000..3351e51d23 --- /dev/null +++ b/3.24.8-scylla/_static/img/icons/icon-whitepapers.svg @@ -0,0 +1 @@ +icon-whitepapers diff --git a/3.24.8-scylla/_static/img/icons/icon-workshop.svg b/3.24.8-scylla/_static/img/icons/icon-workshop.svg new file mode 100644 index 0000000000..5206e58e98 --- /dev/null +++ b/3.24.8-scylla/_static/img/icons/icon-workshop.svg @@ -0,0 +1 @@ + diff --git a/3.24.8-scylla/_static/img/logo-docs.svg b/3.24.8-scylla/_static/img/logo-docs.svg new file mode 100644 index 0000000000..4fff669cb6 --- /dev/null +++ b/3.24.8-scylla/_static/img/logo-docs.svg @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/3.24.8-scylla/_static/img/logo-scylla-horizontal-RGB.svg b/3.24.8-scylla/_static/img/logo-scylla-horizontal-RGB.svg new file mode 100644 index 0000000000..b5022d7c4d --- /dev/null +++ b/3.24.8-scylla/_static/img/logo-scylla-horizontal-RGB.svg @@ -0,0 +1,74 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/3.24.8-scylla/_static/img/mascots/404.jpg b/3.24.8-scylla/_static/img/mascots/404.jpg new file mode 100644 index 0000000000..769fa0889f Binary files /dev/null and b/3.24.8-scylla/_static/img/mascots/404.jpg differ diff --git a/3.24.8-scylla/_static/img/mascots/scylla-3monsters.png b/3.24.8-scylla/_static/img/mascots/scylla-3monsters.png new file mode 100644 index 0000000000..7c06d01674 Binary files /dev/null and b/3.24.8-scylla/_static/img/mascots/scylla-3monsters.png differ diff --git a/3.24.8-scylla/_static/img/mascots/scylla-advisor-crystal.png b/3.24.8-scylla/_static/img/mascots/scylla-advisor-crystal.png new file mode 100644 index 0000000000..d33fddd62f Binary files /dev/null and b/3.24.8-scylla/_static/img/mascots/scylla-advisor-crystal.png differ diff --git a/3.24.8-scylla/_static/img/mascots/scylla-alternator.svg b/3.24.8-scylla/_static/img/mascots/scylla-alternator.svg new file mode 100644 index 0000000000..0462f893d5 --- /dev/null +++ b/3.24.8-scylla/_static/img/mascots/scylla-alternator.svg @@ -0,0 +1 @@ +scylla-alternator diff --git a/3.24.8-scylla/_static/img/mascots/scylla-cloud.svg b/3.24.8-scylla/_static/img/mascots/scylla-cloud.svg new file mode 100644 index 0000000000..a6c6a26fc9 --- /dev/null +++ b/3.24.8-scylla/_static/img/mascots/scylla-cloud.svg @@ -0,0 +1 @@ +scylla-cloud diff --git a/3.24.8-scylla/_static/img/mascots/scylla-computer-3-monsters.png b/3.24.8-scylla/_static/img/mascots/scylla-computer-3-monsters.png new file mode 100644 index 0000000000..d0368a7027 Binary files /dev/null and b/3.24.8-scylla/_static/img/mascots/scylla-computer-3-monsters.png differ diff --git a/3.24.8-scylla/_static/img/mascots/scylla-computer-headset.png b/3.24.8-scylla/_static/img/mascots/scylla-computer-headset.png new file mode 100644 index 0000000000..0cdadaa216 Binary files /dev/null and b/3.24.8-scylla/_static/img/mascots/scylla-computer-headset.png differ diff --git a/3.24.8-scylla/_static/img/mascots/scylla-cup-number-one.png b/3.24.8-scylla/_static/img/mascots/scylla-cup-number-one.png new file mode 100644 index 0000000000..e889f4e368 Binary files /dev/null and b/3.24.8-scylla/_static/img/mascots/scylla-cup-number-one.png differ diff --git a/3.24.8-scylla/_static/img/mascots/scylla-docs.svg b/3.24.8-scylla/_static/img/mascots/scylla-docs.svg new file mode 100644 index 0000000000..a5bce950c2 --- /dev/null +++ b/3.24.8-scylla/_static/img/mascots/scylla-docs.svg @@ -0,0 +1 @@ +scylla-docs diff --git a/3.24.8-scylla/_static/img/mascots/scylla-drivers.svg b/3.24.8-scylla/_static/img/mascots/scylla-drivers.svg new file mode 100644 index 0000000000..6012e71679 --- /dev/null +++ b/3.24.8-scylla/_static/img/mascots/scylla-drivers.svg @@ -0,0 +1 @@ +scylla-manager diff --git a/3.24.8-scylla/_static/img/mascots/scylla-enterprise.svg b/3.24.8-scylla/_static/img/mascots/scylla-enterprise.svg new file mode 100644 index 0000000000..a1aa0b46ac --- /dev/null +++ b/3.24.8-scylla/_static/img/mascots/scylla-enterprise.svg @@ -0,0 +1 @@ +scylla-enterprise diff --git a/3.24.8-scylla/_static/img/mascots/scylla-forklift-boxes.png b/3.24.8-scylla/_static/img/mascots/scylla-forklift-boxes.png new file mode 100644 index 0000000000..f64c29e6c7 Binary files /dev/null and b/3.24.8-scylla/_static/img/mascots/scylla-forklift-boxes.png differ diff --git a/3.24.8-scylla/_static/img/mascots/scylla-forklift-migration.png b/3.24.8-scylla/_static/img/mascots/scylla-forklift-migration.png new file mode 100644 index 0000000000..d2f645c645 Binary files /dev/null and b/3.24.8-scylla/_static/img/mascots/scylla-forklift-migration.png differ diff --git a/3.24.8-scylla/_static/img/mascots/scylla-gear.png b/3.24.8-scylla/_static/img/mascots/scylla-gear.png new file mode 100644 index 0000000000..0f53b26afa Binary files /dev/null and b/3.24.8-scylla/_static/img/mascots/scylla-gear.png differ diff --git a/3.24.8-scylla/_static/img/mascots/scylla-hardhat.png b/3.24.8-scylla/_static/img/mascots/scylla-hardhat.png new file mode 100644 index 0000000000..630f2d9094 Binary files /dev/null and b/3.24.8-scylla/_static/img/mascots/scylla-hardhat.png differ diff --git a/3.24.8-scylla/_static/img/mascots/scylla-headband.png b/3.24.8-scylla/_static/img/mascots/scylla-headband.png new file mode 100644 index 0000000000..c87abe684d Binary files /dev/null and b/3.24.8-scylla/_static/img/mascots/scylla-headband.png differ diff --git a/3.24.8-scylla/_static/img/mascots/scylla-headset.png b/3.24.8-scylla/_static/img/mascots/scylla-headset.png new file mode 100644 index 0000000000..ba52cd223d Binary files /dev/null and b/3.24.8-scylla/_static/img/mascots/scylla-headset.png differ diff --git a/3.24.8-scylla/_static/img/mascots/scylla-hearts.png b/3.24.8-scylla/_static/img/mascots/scylla-hearts.png new file mode 100644 index 0000000000..cef08c8654 Binary files /dev/null and b/3.24.8-scylla/_static/img/mascots/scylla-hearts.png differ diff --git a/3.24.8-scylla/_static/img/mascots/scylla-looking-down.png b/3.24.8-scylla/_static/img/mascots/scylla-looking-down.png new file mode 100644 index 0000000000..75cccbfdf1 Binary files /dev/null and b/3.24.8-scylla/_static/img/mascots/scylla-looking-down.png differ diff --git a/3.24.8-scylla/_static/img/mascots/scylla-looking-up.png b/3.24.8-scylla/_static/img/mascots/scylla-looking-up.png new file mode 100644 index 0000000000..6f10405f21 Binary files /dev/null and b/3.24.8-scylla/_static/img/mascots/scylla-looking-up.png differ diff --git a/3.24.8-scylla/_static/img/mascots/scylla-magnifying-glass-fronting.png b/3.24.8-scylla/_static/img/mascots/scylla-magnifying-glass-fronting.png new file mode 100644 index 0000000000..e368cae169 Binary files /dev/null and b/3.24.8-scylla/_static/img/mascots/scylla-magnifying-glass-fronting.png differ diff --git a/3.24.8-scylla/_static/img/mascots/scylla-magnifying-glass.png b/3.24.8-scylla/_static/img/mascots/scylla-magnifying-glass.png new file mode 100644 index 0000000000..74ad669500 Binary files /dev/null and b/3.24.8-scylla/_static/img/mascots/scylla-magnifying-glass.png differ diff --git a/3.24.8-scylla/_static/img/mascots/scylla-manager.svg b/3.24.8-scylla/_static/img/mascots/scylla-manager.svg new file mode 100644 index 0000000000..6ba9ed937c --- /dev/null +++ b/3.24.8-scylla/_static/img/mascots/scylla-manager.svg @@ -0,0 +1 @@ +scylla-manager-2 diff --git a/3.24.8-scylla/_static/img/mascots/scylla-monitor.svg b/3.24.8-scylla/_static/img/mascots/scylla-monitor.svg new file mode 100644 index 0000000000..48bec7dde3 --- /dev/null +++ b/3.24.8-scylla/_static/img/mascots/scylla-monitor.svg @@ -0,0 +1 @@ +scylla-monitor diff --git a/3.24.8-scylla/_static/img/mascots/scylla-movement-fast.png b/3.24.8-scylla/_static/img/mascots/scylla-movement-fast.png new file mode 100644 index 0000000000..956d1dd0e2 Binary files /dev/null and b/3.24.8-scylla/_static/img/mascots/scylla-movement-fast.png differ diff --git a/3.24.8-scylla/_static/img/mascots/scylla-movement.png b/3.24.8-scylla/_static/img/mascots/scylla-movement.png new file mode 100644 index 0000000000..7ee2b04338 Binary files /dev/null and b/3.24.8-scylla/_static/img/mascots/scylla-movement.png differ diff --git a/3.24.8-scylla/_static/img/mascots/scylla-onpremise.png b/3.24.8-scylla/_static/img/mascots/scylla-onpremise.png new file mode 100644 index 0000000000..3b2dc8f1a2 Binary files /dev/null and b/3.24.8-scylla/_static/img/mascots/scylla-onpremise.png differ diff --git a/3.24.8-scylla/_static/img/mascots/scylla-opensource.svg b/3.24.8-scylla/_static/img/mascots/scylla-opensource.svg new file mode 100644 index 0000000000..299e9cb995 --- /dev/null +++ b/3.24.8-scylla/_static/img/mascots/scylla-opensource.svg @@ -0,0 +1 @@ +Plan de travail 1 diff --git a/3.24.8-scylla/_static/img/mascots/scylla-operator.svg b/3.24.8-scylla/_static/img/mascots/scylla-operator.svg new file mode 100644 index 0000000000..655a450b2a --- /dev/null +++ b/3.24.8-scylla/_static/img/mascots/scylla-operator.svg @@ -0,0 +1 @@ +scylla-operator diff --git a/3.24.8-scylla/_static/img/mascots/scylla-plugin.png b/3.24.8-scylla/_static/img/mascots/scylla-plugin.png new file mode 100644 index 0000000000..b28dc857cc Binary files /dev/null and b/3.24.8-scylla/_static/img/mascots/scylla-plugin.png differ diff --git a/3.24.8-scylla/_static/img/mascots/scylla-release-mascot.png b/3.24.8-scylla/_static/img/mascots/scylla-release-mascot.png new file mode 100644 index 0000000000..09342ac687 Binary files /dev/null and b/3.24.8-scylla/_static/img/mascots/scylla-release-mascot.png differ diff --git a/3.24.8-scylla/_static/img/mascots/scylla-repair.png b/3.24.8-scylla/_static/img/mascots/scylla-repair.png new file mode 100644 index 0000000000..9b4c613e70 Binary files /dev/null and b/3.24.8-scylla/_static/img/mascots/scylla-repair.png differ diff --git a/3.24.8-scylla/_static/img/mascots/scylla-server.png b/3.24.8-scylla/_static/img/mascots/scylla-server.png new file mode 100644 index 0000000000..96dc785298 Binary files /dev/null and b/3.24.8-scylla/_static/img/mascots/scylla-server.png differ diff --git a/3.24.8-scylla/_static/img/mascots/scylla-sleeping.png b/3.24.8-scylla/_static/img/mascots/scylla-sleeping.png new file mode 100644 index 0000000000..f88598e05a Binary files /dev/null and b/3.24.8-scylla/_static/img/mascots/scylla-sleeping.png differ diff --git a/3.24.8-scylla/_static/img/mascots/scylla-tall-measure.png b/3.24.8-scylla/_static/img/mascots/scylla-tall-measure.png new file mode 100644 index 0000000000..6f0ca146c0 Binary files /dev/null and b/3.24.8-scylla/_static/img/mascots/scylla-tall-measure.png differ diff --git a/3.24.8-scylla/_static/img/mascots/scylla-university.png b/3.24.8-scylla/_static/img/mascots/scylla-university.png new file mode 100644 index 0000000000..b3d0621193 Binary files /dev/null and b/3.24.8-scylla/_static/img/mascots/scylla-university.png differ diff --git a/3.24.8-scylla/_static/img/mascots/scylla-weights.png b/3.24.8-scylla/_static/img/mascots/scylla-weights.png new file mode 100644 index 0000000000..b070bb022c Binary files /dev/null and b/3.24.8-scylla/_static/img/mascots/scylla-weights.png differ diff --git a/3.24.8-scylla/_static/img/mascots/scylla-window-cleaning.png b/3.24.8-scylla/_static/img/mascots/scylla-window-cleaning.png new file mode 100644 index 0000000000..6a8b16a6b4 Binary files /dev/null and b/3.24.8-scylla/_static/img/mascots/scylla-window-cleaning.png differ diff --git a/3.24.8-scylla/_static/img/mascots/scylla-with-computer-2.png b/3.24.8-scylla/_static/img/mascots/scylla-with-computer-2.png new file mode 100644 index 0000000000..f3b8b2984f Binary files /dev/null and b/3.24.8-scylla/_static/img/mascots/scylla-with-computer-2.png differ diff --git a/3.24.8-scylla/_static/img/mascots/scylla-with-computer.png b/3.24.8-scylla/_static/img/mascots/scylla-with-computer.png new file mode 100644 index 0000000000..b38a6fbbe0 Binary files /dev/null and b/3.24.8-scylla/_static/img/mascots/scylla-with-computer.png differ diff --git a/3.24.8-scylla/_static/img/mascots/scylla-with-linux.png b/3.24.8-scylla/_static/img/mascots/scylla-with-linux.png new file mode 100644 index 0000000000..954bf13bc2 Binary files /dev/null and b/3.24.8-scylla/_static/img/mascots/scylla-with-linux.png differ diff --git a/3.24.8-scylla/_static/img/mascots/scylla-writting.png b/3.24.8-scylla/_static/img/mascots/scylla-writting.png new file mode 100644 index 0000000000..d35a13d380 Binary files /dev/null and b/3.24.8-scylla/_static/img/mascots/scylla-writting.png differ diff --git a/3.24.8-scylla/_static/img/menu.svg b/3.24.8-scylla/_static/img/menu.svg new file mode 100644 index 0000000000..30ea1d901e --- /dev/null +++ b/3.24.8-scylla/_static/img/menu.svg @@ -0,0 +1,3 @@ + + + diff --git a/3.24.8-scylla/_static/jquery-3.5.1.js b/3.24.8-scylla/_static/jquery-3.5.1.js new file mode 100644 index 0000000000..50937333b9 --- /dev/null +++ b/3.24.8-scylla/_static/jquery-3.5.1.js @@ -0,0 +1,10872 @@ +/*! + * jQuery JavaScript Library v3.5.1 + * https://jquery.com/ + * + * Includes Sizzle.js + * https://sizzlejs.com/ + * + * Copyright JS Foundation and other contributors + * Released under the MIT license + * https://jquery.org/license + * + * Date: 2020-05-04T22:49Z + */ +( function( global, factory ) { + + "use strict"; + + if ( typeof module === "object" && typeof module.exports === "object" ) { + + // For CommonJS and CommonJS-like environments where a proper `window` + // is present, execute the factory and get jQuery. + // For environments that do not have a `window` with a `document` + // (such as Node.js), expose a factory as module.exports. + // This accentuates the need for the creation of a real `window`. + // e.g. var jQuery = require("jquery")(window); + // See ticket #14549 for more info. + module.exports = global.document ? + factory( global, true ) : + function( w ) { + if ( !w.document ) { + throw new Error( "jQuery requires a window with a document" ); + } + return factory( w ); + }; + } else { + factory( global ); + } + +// Pass this if window is not defined yet +} )( typeof window !== "undefined" ? window : this, function( window, noGlobal ) { + +// Edge <= 12 - 13+, Firefox <=18 - 45+, IE 10 - 11, Safari 5.1 - 9+, iOS 6 - 9.1 +// throw exceptions when non-strict code (e.g., ASP.NET 4.5) accesses strict mode +// arguments.callee.caller (trac-13335). But as of jQuery 3.0 (2016), strict mode should be common +// enough that all such attempts are guarded in a try block. +"use strict"; + +var arr = []; + +var getProto = Object.getPrototypeOf; + +var slice = arr.slice; + +var flat = arr.flat ? function( array ) { + return arr.flat.call( array ); +} : function( array ) { + return arr.concat.apply( [], array ); +}; + + +var push = arr.push; + +var indexOf = arr.indexOf; + +var class2type = {}; + +var toString = class2type.toString; + +var hasOwn = class2type.hasOwnProperty; + +var fnToString = hasOwn.toString; + +var ObjectFunctionString = fnToString.call( Object ); + +var support = {}; + +var isFunction = function isFunction( obj ) { + + // Support: Chrome <=57, Firefox <=52 + // In some browsers, typeof returns "function" for HTML elements + // (i.e., `typeof document.createElement( "object" ) === "function"`). + // We don't want to classify *any* DOM node as a function. + return typeof obj === "function" && typeof obj.nodeType !== "number"; + }; + + +var isWindow = function isWindow( obj ) { + return obj != null && obj === obj.window; + }; + + +var document = window.document; + + + + var preservedScriptAttributes = { + type: true, + src: true, + nonce: true, + noModule: true + }; + + function DOMEval( code, node, doc ) { + doc = doc || document; + + var i, val, + script = doc.createElement( "script" ); + + script.text = code; + if ( node ) { + for ( i in preservedScriptAttributes ) { + + // Support: Firefox 64+, Edge 18+ + // Some browsers don't support the "nonce" property on scripts. + // On the other hand, just using `getAttribute` is not enough as + // the `nonce` attribute is reset to an empty string whenever it + // becomes browsing-context connected. + // See https://github.com/whatwg/html/issues/2369 + // See https://html.spec.whatwg.org/#nonce-attributes + // The `node.getAttribute` check was added for the sake of + // `jQuery.globalEval` so that it can fake a nonce-containing node + // via an object. + val = node[ i ] || node.getAttribute && node.getAttribute( i ); + if ( val ) { + script.setAttribute( i, val ); + } + } + } + doc.head.appendChild( script ).parentNode.removeChild( script ); + } + + +function toType( obj ) { + if ( obj == null ) { + return obj + ""; + } + + // Support: Android <=2.3 only (functionish RegExp) + return typeof obj === "object" || typeof obj === "function" ? + class2type[ toString.call( obj ) ] || "object" : + typeof obj; +} +/* global Symbol */ +// Defining this global in .eslintrc.json would create a danger of using the global +// unguarded in another place, it seems safer to define global only for this module + + + +var + version = "3.5.1", + + // Define a local copy of jQuery + jQuery = function( selector, context ) { + + // The jQuery object is actually just the init constructor 'enhanced' + // Need init if jQuery is called (just allow error to be thrown if not included) + return new jQuery.fn.init( selector, context ); + }; + +jQuery.fn = jQuery.prototype = { + + // The current version of jQuery being used + jquery: version, + + constructor: jQuery, + + // The default length of a jQuery object is 0 + length: 0, + + toArray: function() { + return slice.call( this ); + }, + + // Get the Nth element in the matched element set OR + // Get the whole matched element set as a clean array + get: function( num ) { + + // Return all the elements in a clean array + if ( num == null ) { + return slice.call( this ); + } + + // Return just the one element from the set + return num < 0 ? this[ num + this.length ] : this[ num ]; + }, + + // Take an array of elements and push it onto the stack + // (returning the new matched element set) + pushStack: function( elems ) { + + // Build a new jQuery matched element set + var ret = jQuery.merge( this.constructor(), elems ); + + // Add the old object onto the stack (as a reference) + ret.prevObject = this; + + // Return the newly-formed element set + return ret; + }, + + // Execute a callback for every element in the matched set. + each: function( callback ) { + return jQuery.each( this, callback ); + }, + + map: function( callback ) { + return this.pushStack( jQuery.map( this, function( elem, i ) { + return callback.call( elem, i, elem ); + } ) ); + }, + + slice: function() { + return this.pushStack( slice.apply( this, arguments ) ); + }, + + first: function() { + return this.eq( 0 ); + }, + + last: function() { + return this.eq( -1 ); + }, + + even: function() { + return this.pushStack( jQuery.grep( this, function( _elem, i ) { + return ( i + 1 ) % 2; + } ) ); + }, + + odd: function() { + return this.pushStack( jQuery.grep( this, function( _elem, i ) { + return i % 2; + } ) ); + }, + + eq: function( i ) { + var len = this.length, + j = +i + ( i < 0 ? len : 0 ); + return this.pushStack( j >= 0 && j < len ? [ this[ j ] ] : [] ); + }, + + end: function() { + return this.prevObject || this.constructor(); + }, + + // For internal use only. + // Behaves like an Array's method, not like a jQuery method. + push: push, + sort: arr.sort, + splice: arr.splice +}; + +jQuery.extend = jQuery.fn.extend = function() { + var options, name, src, copy, copyIsArray, clone, + target = arguments[ 0 ] || {}, + i = 1, + length = arguments.length, + deep = false; + + // Handle a deep copy situation + if ( typeof target === "boolean" ) { + deep = target; + + // Skip the boolean and the target + target = arguments[ i ] || {}; + i++; + } + + // Handle case when target is a string or something (possible in deep copy) + if ( typeof target !== "object" && !isFunction( target ) ) { + target = {}; + } + + // Extend jQuery itself if only one argument is passed + if ( i === length ) { + target = this; + i--; + } + + for ( ; i < length; i++ ) { + + // Only deal with non-null/undefined values + if ( ( options = arguments[ i ] ) != null ) { + + // Extend the base object + for ( name in options ) { + copy = options[ name ]; + + // Prevent Object.prototype pollution + // Prevent never-ending loop + if ( name === "__proto__" || target === copy ) { + continue; + } + + // Recurse if we're merging plain objects or arrays + if ( deep && copy && ( jQuery.isPlainObject( copy ) || + ( copyIsArray = Array.isArray( copy ) ) ) ) { + src = target[ name ]; + + // Ensure proper type for the source value + if ( copyIsArray && !Array.isArray( src ) ) { + clone = []; + } else if ( !copyIsArray && !jQuery.isPlainObject( src ) ) { + clone = {}; + } else { + clone = src; + } + copyIsArray = false; + + // Never move original objects, clone them + target[ name ] = jQuery.extend( deep, clone, copy ); + + // Don't bring in undefined values + } else if ( copy !== undefined ) { + target[ name ] = copy; + } + } + } + } + + // Return the modified object + return target; +}; + +jQuery.extend( { + + // Unique for each copy of jQuery on the page + expando: "jQuery" + ( version + Math.random() ).replace( /\D/g, "" ), + + // Assume jQuery is ready without the ready module + isReady: true, + + error: function( msg ) { + throw new Error( msg ); + }, + + noop: function() {}, + + isPlainObject: function( obj ) { + var proto, Ctor; + + // Detect obvious negatives + // Use toString instead of jQuery.type to catch host objects + if ( !obj || toString.call( obj ) !== "[object Object]" ) { + return false; + } + + proto = getProto( obj ); + + // Objects with no prototype (e.g., `Object.create( null )`) are plain + if ( !proto ) { + return true; + } + + // Objects with prototype are plain iff they were constructed by a global Object function + Ctor = hasOwn.call( proto, "constructor" ) && proto.constructor; + return typeof Ctor === "function" && fnToString.call( Ctor ) === ObjectFunctionString; + }, + + isEmptyObject: function( obj ) { + var name; + + for ( name in obj ) { + return false; + } + return true; + }, + + // Evaluates a script in a provided context; falls back to the global one + // if not specified. + globalEval: function( code, options, doc ) { + DOMEval( code, { nonce: options && options.nonce }, doc ); + }, + + each: function( obj, callback ) { + var length, i = 0; + + if ( isArrayLike( obj ) ) { + length = obj.length; + for ( ; i < length; i++ ) { + if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) { + break; + } + } + } else { + for ( i in obj ) { + if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) { + break; + } + } + } + + return obj; + }, + + // results is for internal usage only + makeArray: function( arr, results ) { + var ret = results || []; + + if ( arr != null ) { + if ( isArrayLike( Object( arr ) ) ) { + jQuery.merge( ret, + typeof arr === "string" ? + [ arr ] : arr + ); + } else { + push.call( ret, arr ); + } + } + + return ret; + }, + + inArray: function( elem, arr, i ) { + return arr == null ? -1 : indexOf.call( arr, elem, i ); + }, + + // Support: Android <=4.0 only, PhantomJS 1 only + // push.apply(_, arraylike) throws on ancient WebKit + merge: function( first, second ) { + var len = +second.length, + j = 0, + i = first.length; + + for ( ; j < len; j++ ) { + first[ i++ ] = second[ j ]; + } + + first.length = i; + + return first; + }, + + grep: function( elems, callback, invert ) { + var callbackInverse, + matches = [], + i = 0, + length = elems.length, + callbackExpect = !invert; + + // Go through the array, only saving the items + // that pass the validator function + for ( ; i < length; i++ ) { + callbackInverse = !callback( elems[ i ], i ); + if ( callbackInverse !== callbackExpect ) { + matches.push( elems[ i ] ); + } + } + + return matches; + }, + + // arg is for internal usage only + map: function( elems, callback, arg ) { + var length, value, + i = 0, + ret = []; + + // Go through the array, translating each of the items to their new values + if ( isArrayLike( elems ) ) { + length = elems.length; + for ( ; i < length; i++ ) { + value = callback( elems[ i ], i, arg ); + + if ( value != null ) { + ret.push( value ); + } + } + + // Go through every key on the object, + } else { + for ( i in elems ) { + value = callback( elems[ i ], i, arg ); + + if ( value != null ) { + ret.push( value ); + } + } + } + + // Flatten any nested arrays + return flat( ret ); + }, + + // A global GUID counter for objects + guid: 1, + + // jQuery.support is not used in Core but other projects attach their + // properties to it so it needs to exist. + support: support +} ); + +if ( typeof Symbol === "function" ) { + jQuery.fn[ Symbol.iterator ] = arr[ Symbol.iterator ]; +} + +// Populate the class2type map +jQuery.each( "Boolean Number String Function Array Date RegExp Object Error Symbol".split( " " ), +function( _i, name ) { + class2type[ "[object " + name + "]" ] = name.toLowerCase(); +} ); + +function isArrayLike( obj ) { + + // Support: real iOS 8.2 only (not reproducible in simulator) + // `in` check used to prevent JIT error (gh-2145) + // hasOwn isn't used here due to false negatives + // regarding Nodelist length in IE + var length = !!obj && "length" in obj && obj.length, + type = toType( obj ); + + if ( isFunction( obj ) || isWindow( obj ) ) { + return false; + } + + return type === "array" || length === 0 || + typeof length === "number" && length > 0 && ( length - 1 ) in obj; +} +var Sizzle = +/*! + * Sizzle CSS Selector Engine v2.3.5 + * https://sizzlejs.com/ + * + * Copyright JS Foundation and other contributors + * Released under the MIT license + * https://js.foundation/ + * + * Date: 2020-03-14 + */ +( function( window ) { +var i, + support, + Expr, + getText, + isXML, + tokenize, + compile, + select, + outermostContext, + sortInput, + hasDuplicate, + + // Local document vars + setDocument, + document, + docElem, + documentIsHTML, + rbuggyQSA, + rbuggyMatches, + matches, + contains, + + // Instance-specific data + expando = "sizzle" + 1 * new Date(), + preferredDoc = window.document, + dirruns = 0, + done = 0, + classCache = createCache(), + tokenCache = createCache(), + compilerCache = createCache(), + nonnativeSelectorCache = createCache(), + sortOrder = function( a, b ) { + if ( a === b ) { + hasDuplicate = true; + } + return 0; + }, + + // Instance methods + hasOwn = ( {} ).hasOwnProperty, + arr = [], + pop = arr.pop, + pushNative = arr.push, + push = arr.push, + slice = arr.slice, + + // Use a stripped-down indexOf as it's faster than native + // https://jsperf.com/thor-indexof-vs-for/5 + indexOf = function( list, elem ) { + var i = 0, + len = list.length; + for ( ; i < len; i++ ) { + if ( list[ i ] === elem ) { + return i; + } + } + return -1; + }, + + booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|" + + "ismap|loop|multiple|open|readonly|required|scoped", + + // Regular expressions + + // http://www.w3.org/TR/css3-selectors/#whitespace + whitespace = "[\\x20\\t\\r\\n\\f]", + + // https://www.w3.org/TR/css-syntax-3/#ident-token-diagram + identifier = "(?:\\\\[\\da-fA-F]{1,6}" + whitespace + + "?|\\\\[^\\r\\n\\f]|[\\w-]|[^\0-\\x7f])+", + + // Attribute selectors: http://www.w3.org/TR/selectors/#attribute-selectors + attributes = "\\[" + whitespace + "*(" + identifier + ")(?:" + whitespace + + + // Operator (capture 2) + "*([*^$|!~]?=)" + whitespace + + + // "Attribute values must be CSS identifiers [capture 5] + // or strings [capture 3 or capture 4]" + "*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|(" + identifier + "))|)" + + whitespace + "*\\]", + + pseudos = ":(" + identifier + ")(?:\\((" + + + // To reduce the number of selectors needing tokenize in the preFilter, prefer arguments: + // 1. quoted (capture 3; capture 4 or capture 5) + "('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|" + + + // 2. simple (capture 6) + "((?:\\\\.|[^\\\\()[\\]]|" + attributes + ")*)|" + + + // 3. anything else (capture 2) + ".*" + + ")\\)|)", + + // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter + rwhitespace = new RegExp( whitespace + "+", "g" ), + rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + + whitespace + "+$", "g" ), + + rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ), + rcombinators = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + + "*" ), + rdescend = new RegExp( whitespace + "|>" ), + + rpseudo = new RegExp( pseudos ), + ridentifier = new RegExp( "^" + identifier + "$" ), + + matchExpr = { + "ID": new RegExp( "^#(" + identifier + ")" ), + "CLASS": new RegExp( "^\\.(" + identifier + ")" ), + "TAG": new RegExp( "^(" + identifier + "|[*])" ), + "ATTR": new RegExp( "^" + attributes ), + "PSEUDO": new RegExp( "^" + pseudos ), + "CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + + whitespace + "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + + whitespace + "*(\\d+)|))" + whitespace + "*\\)|)", "i" ), + "bool": new RegExp( "^(?:" + booleans + ")$", "i" ), + + // For use in libraries implementing .is() + // We use this for POS matching in `select` + "needsContext": new RegExp( "^" + whitespace + + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" + whitespace + + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" ) + }, + + rhtml = /HTML$/i, + rinputs = /^(?:input|select|textarea|button)$/i, + rheader = /^h\d$/i, + + rnative = /^[^{]+\{\s*\[native \w/, + + // Easily-parseable/retrievable ID or TAG or CLASS selectors + rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/, + + rsibling = /[+~]/, + + // CSS escapes + // http://www.w3.org/TR/CSS21/syndata.html#escaped-characters + runescape = new RegExp( "\\\\[\\da-fA-F]{1,6}" + whitespace + "?|\\\\([^\\r\\n\\f])", "g" ), + funescape = function( escape, nonHex ) { + var high = "0x" + escape.slice( 1 ) - 0x10000; + + return nonHex ? + + // Strip the backslash prefix from a non-hex escape sequence + nonHex : + + // Replace a hexadecimal escape sequence with the encoded Unicode code point + // Support: IE <=11+ + // For values outside the Basic Multilingual Plane (BMP), manually construct a + // surrogate pair + high < 0 ? + String.fromCharCode( high + 0x10000 ) : + String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 ); + }, + + // CSS string/identifier serialization + // https://drafts.csswg.org/cssom/#common-serializing-idioms + rcssescape = /([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g, + fcssescape = function( ch, asCodePoint ) { + if ( asCodePoint ) { + + // U+0000 NULL becomes U+FFFD REPLACEMENT CHARACTER + if ( ch === "\0" ) { + return "\uFFFD"; + } + + // Control characters and (dependent upon position) numbers get escaped as code points + return ch.slice( 0, -1 ) + "\\" + + ch.charCodeAt( ch.length - 1 ).toString( 16 ) + " "; + } + + // Other potentially-special ASCII characters get backslash-escaped + return "\\" + ch; + }, + + // Used for iframes + // See setDocument() + // Removing the function wrapper causes a "Permission Denied" + // error in IE + unloadHandler = function() { + setDocument(); + }, + + inDisabledFieldset = addCombinator( + function( elem ) { + return elem.disabled === true && elem.nodeName.toLowerCase() === "fieldset"; + }, + { dir: "parentNode", next: "legend" } + ); + +// Optimize for push.apply( _, NodeList ) +try { + push.apply( + ( arr = slice.call( preferredDoc.childNodes ) ), + preferredDoc.childNodes + ); + + // Support: Android<4.0 + // Detect silently failing push.apply + // eslint-disable-next-line no-unused-expressions + arr[ preferredDoc.childNodes.length ].nodeType; +} catch ( e ) { + push = { apply: arr.length ? + + // Leverage slice if possible + function( target, els ) { + pushNative.apply( target, slice.call( els ) ); + } : + + // Support: IE<9 + // Otherwise append directly + function( target, els ) { + var j = target.length, + i = 0; + + // Can't trust NodeList.length + while ( ( target[ j++ ] = els[ i++ ] ) ) {} + target.length = j - 1; + } + }; +} + +function Sizzle( selector, context, results, seed ) { + var m, i, elem, nid, match, groups, newSelector, + newContext = context && context.ownerDocument, + + // nodeType defaults to 9, since context defaults to document + nodeType = context ? context.nodeType : 9; + + results = results || []; + + // Return early from calls with invalid selector or context + if ( typeof selector !== "string" || !selector || + nodeType !== 1 && nodeType !== 9 && nodeType !== 11 ) { + + return results; + } + + // Try to shortcut find operations (as opposed to filters) in HTML documents + if ( !seed ) { + setDocument( context ); + context = context || document; + + if ( documentIsHTML ) { + + // If the selector is sufficiently simple, try using a "get*By*" DOM method + // (excepting DocumentFragment context, where the methods don't exist) + if ( nodeType !== 11 && ( match = rquickExpr.exec( selector ) ) ) { + + // ID selector + if ( ( m = match[ 1 ] ) ) { + + // Document context + if ( nodeType === 9 ) { + if ( ( elem = context.getElementById( m ) ) ) { + + // Support: IE, Opera, Webkit + // TODO: identify versions + // getElementById can match elements by name instead of ID + if ( elem.id === m ) { + results.push( elem ); + return results; + } + } else { + return results; + } + + // Element context + } else { + + // Support: IE, Opera, Webkit + // TODO: identify versions + // getElementById can match elements by name instead of ID + if ( newContext && ( elem = newContext.getElementById( m ) ) && + contains( context, elem ) && + elem.id === m ) { + + results.push( elem ); + return results; + } + } + + // Type selector + } else if ( match[ 2 ] ) { + push.apply( results, context.getElementsByTagName( selector ) ); + return results; + + // Class selector + } else if ( ( m = match[ 3 ] ) && support.getElementsByClassName && + context.getElementsByClassName ) { + + push.apply( results, context.getElementsByClassName( m ) ); + return results; + } + } + + // Take advantage of querySelectorAll + if ( support.qsa && + !nonnativeSelectorCache[ selector + " " ] && + ( !rbuggyQSA || !rbuggyQSA.test( selector ) ) && + + // Support: IE 8 only + // Exclude object elements + ( nodeType !== 1 || context.nodeName.toLowerCase() !== "object" ) ) { + + newSelector = selector; + newContext = context; + + // qSA considers elements outside a scoping root when evaluating child or + // descendant combinators, which is not what we want. + // In such cases, we work around the behavior by prefixing every selector in the + // list with an ID selector referencing the scope context. + // The technique has to be used as well when a leading combinator is used + // as such selectors are not recognized by querySelectorAll. + // Thanks to Andrew Dupont for this technique. + if ( nodeType === 1 && + ( rdescend.test( selector ) || rcombinators.test( selector ) ) ) { + + // Expand context for sibling selectors + newContext = rsibling.test( selector ) && testContext( context.parentNode ) || + context; + + // We can use :scope instead of the ID hack if the browser + // supports it & if we're not changing the context. + if ( newContext !== context || !support.scope ) { + + // Capture the context ID, setting it first if necessary + if ( ( nid = context.getAttribute( "id" ) ) ) { + nid = nid.replace( rcssescape, fcssescape ); + } else { + context.setAttribute( "id", ( nid = expando ) ); + } + } + + // Prefix every selector in the list + groups = tokenize( selector ); + i = groups.length; + while ( i-- ) { + groups[ i ] = ( nid ? "#" + nid : ":scope" ) + " " + + toSelector( groups[ i ] ); + } + newSelector = groups.join( "," ); + } + + try { + push.apply( results, + newContext.querySelectorAll( newSelector ) + ); + return results; + } catch ( qsaError ) { + nonnativeSelectorCache( selector, true ); + } finally { + if ( nid === expando ) { + context.removeAttribute( "id" ); + } + } + } + } + } + + // All others + return select( selector.replace( rtrim, "$1" ), context, results, seed ); +} + +/** + * Create key-value caches of limited size + * @returns {function(string, object)} Returns the Object data after storing it on itself with + * property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength) + * deleting the oldest entry + */ +function createCache() { + var keys = []; + + function cache( key, value ) { + + // Use (key + " ") to avoid collision with native prototype properties (see Issue #157) + if ( keys.push( key + " " ) > Expr.cacheLength ) { + + // Only keep the most recent entries + delete cache[ keys.shift() ]; + } + return ( cache[ key + " " ] = value ); + } + return cache; +} + +/** + * Mark a function for special use by Sizzle + * @param {Function} fn The function to mark + */ +function markFunction( fn ) { + fn[ expando ] = true; + return fn; +} + +/** + * Support testing using an element + * @param {Function} fn Passed the created element and returns a boolean result + */ +function assert( fn ) { + var el = document.createElement( "fieldset" ); + + try { + return !!fn( el ); + } catch ( e ) { + return false; + } finally { + + // Remove from its parent by default + if ( el.parentNode ) { + el.parentNode.removeChild( el ); + } + + // release memory in IE + el = null; + } +} + +/** + * Adds the same handler for all of the specified attrs + * @param {String} attrs Pipe-separated list of attributes + * @param {Function} handler The method that will be applied + */ +function addHandle( attrs, handler ) { + var arr = attrs.split( "|" ), + i = arr.length; + + while ( i-- ) { + Expr.attrHandle[ arr[ i ] ] = handler; + } +} + +/** + * Checks document order of two siblings + * @param {Element} a + * @param {Element} b + * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b + */ +function siblingCheck( a, b ) { + var cur = b && a, + diff = cur && a.nodeType === 1 && b.nodeType === 1 && + a.sourceIndex - b.sourceIndex; + + // Use IE sourceIndex if available on both nodes + if ( diff ) { + return diff; + } + + // Check if b follows a + if ( cur ) { + while ( ( cur = cur.nextSibling ) ) { + if ( cur === b ) { + return -1; + } + } + } + + return a ? 1 : -1; +} + +/** + * Returns a function to use in pseudos for input types + * @param {String} type + */ +function createInputPseudo( type ) { + return function( elem ) { + var name = elem.nodeName.toLowerCase(); + return name === "input" && elem.type === type; + }; +} + +/** + * Returns a function to use in pseudos for buttons + * @param {String} type + */ +function createButtonPseudo( type ) { + return function( elem ) { + var name = elem.nodeName.toLowerCase(); + return ( name === "input" || name === "button" ) && elem.type === type; + }; +} + +/** + * Returns a function to use in pseudos for :enabled/:disabled + * @param {Boolean} disabled true for :disabled; false for :enabled + */ +function createDisabledPseudo( disabled ) { + + // Known :disabled false positives: fieldset[disabled] > legend:nth-of-type(n+2) :can-disable + return function( elem ) { + + // Only certain elements can match :enabled or :disabled + // https://html.spec.whatwg.org/multipage/scripting.html#selector-enabled + // https://html.spec.whatwg.org/multipage/scripting.html#selector-disabled + if ( "form" in elem ) { + + // Check for inherited disabledness on relevant non-disabled elements: + // * listed form-associated elements in a disabled fieldset + // https://html.spec.whatwg.org/multipage/forms.html#category-listed + // https://html.spec.whatwg.org/multipage/forms.html#concept-fe-disabled + // * option elements in a disabled optgroup + // https://html.spec.whatwg.org/multipage/forms.html#concept-option-disabled + // All such elements have a "form" property. + if ( elem.parentNode && elem.disabled === false ) { + + // Option elements defer to a parent optgroup if present + if ( "label" in elem ) { + if ( "label" in elem.parentNode ) { + return elem.parentNode.disabled === disabled; + } else { + return elem.disabled === disabled; + } + } + + // Support: IE 6 - 11 + // Use the isDisabled shortcut property to check for disabled fieldset ancestors + return elem.isDisabled === disabled || + + // Where there is no isDisabled, check manually + /* jshint -W018 */ + elem.isDisabled !== !disabled && + inDisabledFieldset( elem ) === disabled; + } + + return elem.disabled === disabled; + + // Try to winnow out elements that can't be disabled before trusting the disabled property. + // Some victims get caught in our net (label, legend, menu, track), but it shouldn't + // even exist on them, let alone have a boolean value. + } else if ( "label" in elem ) { + return elem.disabled === disabled; + } + + // Remaining elements are neither :enabled nor :disabled + return false; + }; +} + +/** + * Returns a function to use in pseudos for positionals + * @param {Function} fn + */ +function createPositionalPseudo( fn ) { + return markFunction( function( argument ) { + argument = +argument; + return markFunction( function( seed, matches ) { + var j, + matchIndexes = fn( [], seed.length, argument ), + i = matchIndexes.length; + + // Match elements found at the specified indexes + while ( i-- ) { + if ( seed[ ( j = matchIndexes[ i ] ) ] ) { + seed[ j ] = !( matches[ j ] = seed[ j ] ); + } + } + } ); + } ); +} + +/** + * Checks a node for validity as a Sizzle context + * @param {Element|Object=} context + * @returns {Element|Object|Boolean} The input node if acceptable, otherwise a falsy value + */ +function testContext( context ) { + return context && typeof context.getElementsByTagName !== "undefined" && context; +} + +// Expose support vars for convenience +support = Sizzle.support = {}; + +/** + * Detects XML nodes + * @param {Element|Object} elem An element or a document + * @returns {Boolean} True iff elem is a non-HTML XML node + */ +isXML = Sizzle.isXML = function( elem ) { + var namespace = elem.namespaceURI, + docElem = ( elem.ownerDocument || elem ).documentElement; + + // Support: IE <=8 + // Assume HTML when documentElement doesn't yet exist, such as inside loading iframes + // https://bugs.jquery.com/ticket/4833 + return !rhtml.test( namespace || docElem && docElem.nodeName || "HTML" ); +}; + +/** + * Sets document-related variables once based on the current document + * @param {Element|Object} [doc] An element or document object to use to set the document + * @returns {Object} Returns the current document + */ +setDocument = Sizzle.setDocument = function( node ) { + var hasCompare, subWindow, + doc = node ? node.ownerDocument || node : preferredDoc; + + // Return early if doc is invalid or already selected + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( doc == document || doc.nodeType !== 9 || !doc.documentElement ) { + return document; + } + + // Update global variables + document = doc; + docElem = document.documentElement; + documentIsHTML = !isXML( document ); + + // Support: IE 9 - 11+, Edge 12 - 18+ + // Accessing iframe documents after unload throws "permission denied" errors (jQuery #13936) + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( preferredDoc != document && + ( subWindow = document.defaultView ) && subWindow.top !== subWindow ) { + + // Support: IE 11, Edge + if ( subWindow.addEventListener ) { + subWindow.addEventListener( "unload", unloadHandler, false ); + + // Support: IE 9 - 10 only + } else if ( subWindow.attachEvent ) { + subWindow.attachEvent( "onunload", unloadHandler ); + } + } + + // Support: IE 8 - 11+, Edge 12 - 18+, Chrome <=16 - 25 only, Firefox <=3.6 - 31 only, + // Safari 4 - 5 only, Opera <=11.6 - 12.x only + // IE/Edge & older browsers don't support the :scope pseudo-class. + // Support: Safari 6.0 only + // Safari 6.0 supports :scope but it's an alias of :root there. + support.scope = assert( function( el ) { + docElem.appendChild( el ).appendChild( document.createElement( "div" ) ); + return typeof el.querySelectorAll !== "undefined" && + !el.querySelectorAll( ":scope fieldset div" ).length; + } ); + + /* Attributes + ---------------------------------------------------------------------- */ + + // Support: IE<8 + // Verify that getAttribute really returns attributes and not properties + // (excepting IE8 booleans) + support.attributes = assert( function( el ) { + el.className = "i"; + return !el.getAttribute( "className" ); + } ); + + /* getElement(s)By* + ---------------------------------------------------------------------- */ + + // Check if getElementsByTagName("*") returns only elements + support.getElementsByTagName = assert( function( el ) { + el.appendChild( document.createComment( "" ) ); + return !el.getElementsByTagName( "*" ).length; + } ); + + // Support: IE<9 + support.getElementsByClassName = rnative.test( document.getElementsByClassName ); + + // Support: IE<10 + // Check if getElementById returns elements by name + // The broken getElementById methods don't pick up programmatically-set names, + // so use a roundabout getElementsByName test + support.getById = assert( function( el ) { + docElem.appendChild( el ).id = expando; + return !document.getElementsByName || !document.getElementsByName( expando ).length; + } ); + + // ID filter and find + if ( support.getById ) { + Expr.filter[ "ID" ] = function( id ) { + var attrId = id.replace( runescape, funescape ); + return function( elem ) { + return elem.getAttribute( "id" ) === attrId; + }; + }; + Expr.find[ "ID" ] = function( id, context ) { + if ( typeof context.getElementById !== "undefined" && documentIsHTML ) { + var elem = context.getElementById( id ); + return elem ? [ elem ] : []; + } + }; + } else { + Expr.filter[ "ID" ] = function( id ) { + var attrId = id.replace( runescape, funescape ); + return function( elem ) { + var node = typeof elem.getAttributeNode !== "undefined" && + elem.getAttributeNode( "id" ); + return node && node.value === attrId; + }; + }; + + // Support: IE 6 - 7 only + // getElementById is not reliable as a find shortcut + Expr.find[ "ID" ] = function( id, context ) { + if ( typeof context.getElementById !== "undefined" && documentIsHTML ) { + var node, i, elems, + elem = context.getElementById( id ); + + if ( elem ) { + + // Verify the id attribute + node = elem.getAttributeNode( "id" ); + if ( node && node.value === id ) { + return [ elem ]; + } + + // Fall back on getElementsByName + elems = context.getElementsByName( id ); + i = 0; + while ( ( elem = elems[ i++ ] ) ) { + node = elem.getAttributeNode( "id" ); + if ( node && node.value === id ) { + return [ elem ]; + } + } + } + + return []; + } + }; + } + + // Tag + Expr.find[ "TAG" ] = support.getElementsByTagName ? + function( tag, context ) { + if ( typeof context.getElementsByTagName !== "undefined" ) { + return context.getElementsByTagName( tag ); + + // DocumentFragment nodes don't have gEBTN + } else if ( support.qsa ) { + return context.querySelectorAll( tag ); + } + } : + + function( tag, context ) { + var elem, + tmp = [], + i = 0, + + // By happy coincidence, a (broken) gEBTN appears on DocumentFragment nodes too + results = context.getElementsByTagName( tag ); + + // Filter out possible comments + if ( tag === "*" ) { + while ( ( elem = results[ i++ ] ) ) { + if ( elem.nodeType === 1 ) { + tmp.push( elem ); + } + } + + return tmp; + } + return results; + }; + + // Class + Expr.find[ "CLASS" ] = support.getElementsByClassName && function( className, context ) { + if ( typeof context.getElementsByClassName !== "undefined" && documentIsHTML ) { + return context.getElementsByClassName( className ); + } + }; + + /* QSA/matchesSelector + ---------------------------------------------------------------------- */ + + // QSA and matchesSelector support + + // matchesSelector(:active) reports false when true (IE9/Opera 11.5) + rbuggyMatches = []; + + // qSa(:focus) reports false when true (Chrome 21) + // We allow this because of a bug in IE8/9 that throws an error + // whenever `document.activeElement` is accessed on an iframe + // So, we allow :focus to pass through QSA all the time to avoid the IE error + // See https://bugs.jquery.com/ticket/13378 + rbuggyQSA = []; + + if ( ( support.qsa = rnative.test( document.querySelectorAll ) ) ) { + + // Build QSA regex + // Regex strategy adopted from Diego Perini + assert( function( el ) { + + var input; + + // Select is set to empty string on purpose + // This is to test IE's treatment of not explicitly + // setting a boolean content attribute, + // since its presence should be enough + // https://bugs.jquery.com/ticket/12359 + docElem.appendChild( el ).innerHTML = "" + + ""; + + // Support: IE8, Opera 11-12.16 + // Nothing should be selected when empty strings follow ^= or $= or *= + // The test attribute must be unknown in Opera but "safe" for WinRT + // https://msdn.microsoft.com/en-us/library/ie/hh465388.aspx#attribute_section + if ( el.querySelectorAll( "[msallowcapture^='']" ).length ) { + rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:''|\"\")" ); + } + + // Support: IE8 + // Boolean attributes and "value" are not treated correctly + if ( !el.querySelectorAll( "[selected]" ).length ) { + rbuggyQSA.push( "\\[" + whitespace + "*(?:value|" + booleans + ")" ); + } + + // Support: Chrome<29, Android<4.4, Safari<7.0+, iOS<7.0+, PhantomJS<1.9.8+ + if ( !el.querySelectorAll( "[id~=" + expando + "-]" ).length ) { + rbuggyQSA.push( "~=" ); + } + + // Support: IE 11+, Edge 15 - 18+ + // IE 11/Edge don't find elements on a `[name='']` query in some cases. + // Adding a temporary attribute to the document before the selection works + // around the issue. + // Interestingly, IE 10 & older don't seem to have the issue. + input = document.createElement( "input" ); + input.setAttribute( "name", "" ); + el.appendChild( input ); + if ( !el.querySelectorAll( "[name='']" ).length ) { + rbuggyQSA.push( "\\[" + whitespace + "*name" + whitespace + "*=" + + whitespace + "*(?:''|\"\")" ); + } + + // Webkit/Opera - :checked should return selected option elements + // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked + // IE8 throws error here and will not see later tests + if ( !el.querySelectorAll( ":checked" ).length ) { + rbuggyQSA.push( ":checked" ); + } + + // Support: Safari 8+, iOS 8+ + // https://bugs.webkit.org/show_bug.cgi?id=136851 + // In-page `selector#id sibling-combinator selector` fails + if ( !el.querySelectorAll( "a#" + expando + "+*" ).length ) { + rbuggyQSA.push( ".#.+[+~]" ); + } + + // Support: Firefox <=3.6 - 5 only + // Old Firefox doesn't throw on a badly-escaped identifier. + el.querySelectorAll( "\\\f" ); + rbuggyQSA.push( "[\\r\\n\\f]" ); + } ); + + assert( function( el ) { + el.innerHTML = "" + + ""; + + // Support: Windows 8 Native Apps + // The type and name attributes are restricted during .innerHTML assignment + var input = document.createElement( "input" ); + input.setAttribute( "type", "hidden" ); + el.appendChild( input ).setAttribute( "name", "D" ); + + // Support: IE8 + // Enforce case-sensitivity of name attribute + if ( el.querySelectorAll( "[name=d]" ).length ) { + rbuggyQSA.push( "name" + whitespace + "*[*^$|!~]?=" ); + } + + // FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled) + // IE8 throws error here and will not see later tests + if ( el.querySelectorAll( ":enabled" ).length !== 2 ) { + rbuggyQSA.push( ":enabled", ":disabled" ); + } + + // Support: IE9-11+ + // IE's :disabled selector does not pick up the children of disabled fieldsets + docElem.appendChild( el ).disabled = true; + if ( el.querySelectorAll( ":disabled" ).length !== 2 ) { + rbuggyQSA.push( ":enabled", ":disabled" ); + } + + // Support: Opera 10 - 11 only + // Opera 10-11 does not throw on post-comma invalid pseudos + el.querySelectorAll( "*,:x" ); + rbuggyQSA.push( ",.*:" ); + } ); + } + + if ( ( support.matchesSelector = rnative.test( ( matches = docElem.matches || + docElem.webkitMatchesSelector || + docElem.mozMatchesSelector || + docElem.oMatchesSelector || + docElem.msMatchesSelector ) ) ) ) { + + assert( function( el ) { + + // Check to see if it's possible to do matchesSelector + // on a disconnected node (IE 9) + support.disconnectedMatch = matches.call( el, "*" ); + + // This should fail with an exception + // Gecko does not error, returns false instead + matches.call( el, "[s!='']:x" ); + rbuggyMatches.push( "!=", pseudos ); + } ); + } + + rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join( "|" ) ); + rbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join( "|" ) ); + + /* Contains + ---------------------------------------------------------------------- */ + hasCompare = rnative.test( docElem.compareDocumentPosition ); + + // Element contains another + // Purposefully self-exclusive + // As in, an element does not contain itself + contains = hasCompare || rnative.test( docElem.contains ) ? + function( a, b ) { + var adown = a.nodeType === 9 ? a.documentElement : a, + bup = b && b.parentNode; + return a === bup || !!( bup && bup.nodeType === 1 && ( + adown.contains ? + adown.contains( bup ) : + a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16 + ) ); + } : + function( a, b ) { + if ( b ) { + while ( ( b = b.parentNode ) ) { + if ( b === a ) { + return true; + } + } + } + return false; + }; + + /* Sorting + ---------------------------------------------------------------------- */ + + // Document order sorting + sortOrder = hasCompare ? + function( a, b ) { + + // Flag for duplicate removal + if ( a === b ) { + hasDuplicate = true; + return 0; + } + + // Sort on method existence if only one input has compareDocumentPosition + var compare = !a.compareDocumentPosition - !b.compareDocumentPosition; + if ( compare ) { + return compare; + } + + // Calculate position if both inputs belong to the same document + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + compare = ( a.ownerDocument || a ) == ( b.ownerDocument || b ) ? + a.compareDocumentPosition( b ) : + + // Otherwise we know they are disconnected + 1; + + // Disconnected nodes + if ( compare & 1 || + ( !support.sortDetached && b.compareDocumentPosition( a ) === compare ) ) { + + // Choose the first element that is related to our preferred document + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( a == document || a.ownerDocument == preferredDoc && + contains( preferredDoc, a ) ) { + return -1; + } + + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( b == document || b.ownerDocument == preferredDoc && + contains( preferredDoc, b ) ) { + return 1; + } + + // Maintain original order + return sortInput ? + ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) : + 0; + } + + return compare & 4 ? -1 : 1; + } : + function( a, b ) { + + // Exit early if the nodes are identical + if ( a === b ) { + hasDuplicate = true; + return 0; + } + + var cur, + i = 0, + aup = a.parentNode, + bup = b.parentNode, + ap = [ a ], + bp = [ b ]; + + // Parentless nodes are either documents or disconnected + if ( !aup || !bup ) { + + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + /* eslint-disable eqeqeq */ + return a == document ? -1 : + b == document ? 1 : + /* eslint-enable eqeqeq */ + aup ? -1 : + bup ? 1 : + sortInput ? + ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) : + 0; + + // If the nodes are siblings, we can do a quick check + } else if ( aup === bup ) { + return siblingCheck( a, b ); + } + + // Otherwise we need full lists of their ancestors for comparison + cur = a; + while ( ( cur = cur.parentNode ) ) { + ap.unshift( cur ); + } + cur = b; + while ( ( cur = cur.parentNode ) ) { + bp.unshift( cur ); + } + + // Walk down the tree looking for a discrepancy + while ( ap[ i ] === bp[ i ] ) { + i++; + } + + return i ? + + // Do a sibling check if the nodes have a common ancestor + siblingCheck( ap[ i ], bp[ i ] ) : + + // Otherwise nodes in our document sort first + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + /* eslint-disable eqeqeq */ + ap[ i ] == preferredDoc ? -1 : + bp[ i ] == preferredDoc ? 1 : + /* eslint-enable eqeqeq */ + 0; + }; + + return document; +}; + +Sizzle.matches = function( expr, elements ) { + return Sizzle( expr, null, null, elements ); +}; + +Sizzle.matchesSelector = function( elem, expr ) { + setDocument( elem ); + + if ( support.matchesSelector && documentIsHTML && + !nonnativeSelectorCache[ expr + " " ] && + ( !rbuggyMatches || !rbuggyMatches.test( expr ) ) && + ( !rbuggyQSA || !rbuggyQSA.test( expr ) ) ) { + + try { + var ret = matches.call( elem, expr ); + + // IE 9's matchesSelector returns false on disconnected nodes + if ( ret || support.disconnectedMatch || + + // As well, disconnected nodes are said to be in a document + // fragment in IE 9 + elem.document && elem.document.nodeType !== 11 ) { + return ret; + } + } catch ( e ) { + nonnativeSelectorCache( expr, true ); + } + } + + return Sizzle( expr, document, null, [ elem ] ).length > 0; +}; + +Sizzle.contains = function( context, elem ) { + + // Set document vars if needed + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( ( context.ownerDocument || context ) != document ) { + setDocument( context ); + } + return contains( context, elem ); +}; + +Sizzle.attr = function( elem, name ) { + + // Set document vars if needed + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( ( elem.ownerDocument || elem ) != document ) { + setDocument( elem ); + } + + var fn = Expr.attrHandle[ name.toLowerCase() ], + + // Don't get fooled by Object.prototype properties (jQuery #13807) + val = fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ? + fn( elem, name, !documentIsHTML ) : + undefined; + + return val !== undefined ? + val : + support.attributes || !documentIsHTML ? + elem.getAttribute( name ) : + ( val = elem.getAttributeNode( name ) ) && val.specified ? + val.value : + null; +}; + +Sizzle.escape = function( sel ) { + return ( sel + "" ).replace( rcssescape, fcssescape ); +}; + +Sizzle.error = function( msg ) { + throw new Error( "Syntax error, unrecognized expression: " + msg ); +}; + +/** + * Document sorting and removing duplicates + * @param {ArrayLike} results + */ +Sizzle.uniqueSort = function( results ) { + var elem, + duplicates = [], + j = 0, + i = 0; + + // Unless we *know* we can detect duplicates, assume their presence + hasDuplicate = !support.detectDuplicates; + sortInput = !support.sortStable && results.slice( 0 ); + results.sort( sortOrder ); + + if ( hasDuplicate ) { + while ( ( elem = results[ i++ ] ) ) { + if ( elem === results[ i ] ) { + j = duplicates.push( i ); + } + } + while ( j-- ) { + results.splice( duplicates[ j ], 1 ); + } + } + + // Clear input after sorting to release objects + // See https://github.com/jquery/sizzle/pull/225 + sortInput = null; + + return results; +}; + +/** + * Utility function for retrieving the text value of an array of DOM nodes + * @param {Array|Element} elem + */ +getText = Sizzle.getText = function( elem ) { + var node, + ret = "", + i = 0, + nodeType = elem.nodeType; + + if ( !nodeType ) { + + // If no nodeType, this is expected to be an array + while ( ( node = elem[ i++ ] ) ) { + + // Do not traverse comment nodes + ret += getText( node ); + } + } else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) { + + // Use textContent for elements + // innerText usage removed for consistency of new lines (jQuery #11153) + if ( typeof elem.textContent === "string" ) { + return elem.textContent; + } else { + + // Traverse its children + for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { + ret += getText( elem ); + } + } + } else if ( nodeType === 3 || nodeType === 4 ) { + return elem.nodeValue; + } + + // Do not include comment or processing instruction nodes + + return ret; +}; + +Expr = Sizzle.selectors = { + + // Can be adjusted by the user + cacheLength: 50, + + createPseudo: markFunction, + + match: matchExpr, + + attrHandle: {}, + + find: {}, + + relative: { + ">": { dir: "parentNode", first: true }, + " ": { dir: "parentNode" }, + "+": { dir: "previousSibling", first: true }, + "~": { dir: "previousSibling" } + }, + + preFilter: { + "ATTR": function( match ) { + match[ 1 ] = match[ 1 ].replace( runescape, funescape ); + + // Move the given value to match[3] whether quoted or unquoted + match[ 3 ] = ( match[ 3 ] || match[ 4 ] || + match[ 5 ] || "" ).replace( runescape, funescape ); + + if ( match[ 2 ] === "~=" ) { + match[ 3 ] = " " + match[ 3 ] + " "; + } + + return match.slice( 0, 4 ); + }, + + "CHILD": function( match ) { + + /* matches from matchExpr["CHILD"] + 1 type (only|nth|...) + 2 what (child|of-type) + 3 argument (even|odd|\d*|\d*n([+-]\d+)?|...) + 4 xn-component of xn+y argument ([+-]?\d*n|) + 5 sign of xn-component + 6 x of xn-component + 7 sign of y-component + 8 y of y-component + */ + match[ 1 ] = match[ 1 ].toLowerCase(); + + if ( match[ 1 ].slice( 0, 3 ) === "nth" ) { + + // nth-* requires argument + if ( !match[ 3 ] ) { + Sizzle.error( match[ 0 ] ); + } + + // numeric x and y parameters for Expr.filter.CHILD + // remember that false/true cast respectively to 0/1 + match[ 4 ] = +( match[ 4 ] ? + match[ 5 ] + ( match[ 6 ] || 1 ) : + 2 * ( match[ 3 ] === "even" || match[ 3 ] === "odd" ) ); + match[ 5 ] = +( ( match[ 7 ] + match[ 8 ] ) || match[ 3 ] === "odd" ); + + // other types prohibit arguments + } else if ( match[ 3 ] ) { + Sizzle.error( match[ 0 ] ); + } + + return match; + }, + + "PSEUDO": function( match ) { + var excess, + unquoted = !match[ 6 ] && match[ 2 ]; + + if ( matchExpr[ "CHILD" ].test( match[ 0 ] ) ) { + return null; + } + + // Accept quoted arguments as-is + if ( match[ 3 ] ) { + match[ 2 ] = match[ 4 ] || match[ 5 ] || ""; + + // Strip excess characters from unquoted arguments + } else if ( unquoted && rpseudo.test( unquoted ) && + + // Get excess from tokenize (recursively) + ( excess = tokenize( unquoted, true ) ) && + + // advance to the next closing parenthesis + ( excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length ) ) { + + // excess is a negative index + match[ 0 ] = match[ 0 ].slice( 0, excess ); + match[ 2 ] = unquoted.slice( 0, excess ); + } + + // Return only captures needed by the pseudo filter method (type and argument) + return match.slice( 0, 3 ); + } + }, + + filter: { + + "TAG": function( nodeNameSelector ) { + var nodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase(); + return nodeNameSelector === "*" ? + function() { + return true; + } : + function( elem ) { + return elem.nodeName && elem.nodeName.toLowerCase() === nodeName; + }; + }, + + "CLASS": function( className ) { + var pattern = classCache[ className + " " ]; + + return pattern || + ( pattern = new RegExp( "(^|" + whitespace + + ")" + className + "(" + whitespace + "|$)" ) ) && classCache( + className, function( elem ) { + return pattern.test( + typeof elem.className === "string" && elem.className || + typeof elem.getAttribute !== "undefined" && + elem.getAttribute( "class" ) || + "" + ); + } ); + }, + + "ATTR": function( name, operator, check ) { + return function( elem ) { + var result = Sizzle.attr( elem, name ); + + if ( result == null ) { + return operator === "!="; + } + if ( !operator ) { + return true; + } + + result += ""; + + /* eslint-disable max-len */ + + return operator === "=" ? result === check : + operator === "!=" ? result !== check : + operator === "^=" ? check && result.indexOf( check ) === 0 : + operator === "*=" ? check && result.indexOf( check ) > -1 : + operator === "$=" ? check && result.slice( -check.length ) === check : + operator === "~=" ? ( " " + result.replace( rwhitespace, " " ) + " " ).indexOf( check ) > -1 : + operator === "|=" ? result === check || result.slice( 0, check.length + 1 ) === check + "-" : + false; + /* eslint-enable max-len */ + + }; + }, + + "CHILD": function( type, what, _argument, first, last ) { + var simple = type.slice( 0, 3 ) !== "nth", + forward = type.slice( -4 ) !== "last", + ofType = what === "of-type"; + + return first === 1 && last === 0 ? + + // Shortcut for :nth-*(n) + function( elem ) { + return !!elem.parentNode; + } : + + function( elem, _context, xml ) { + var cache, uniqueCache, outerCache, node, nodeIndex, start, + dir = simple !== forward ? "nextSibling" : "previousSibling", + parent = elem.parentNode, + name = ofType && elem.nodeName.toLowerCase(), + useCache = !xml && !ofType, + diff = false; + + if ( parent ) { + + // :(first|last|only)-(child|of-type) + if ( simple ) { + while ( dir ) { + node = elem; + while ( ( node = node[ dir ] ) ) { + if ( ofType ? + node.nodeName.toLowerCase() === name : + node.nodeType === 1 ) { + + return false; + } + } + + // Reverse direction for :only-* (if we haven't yet done so) + start = dir = type === "only" && !start && "nextSibling"; + } + return true; + } + + start = [ forward ? parent.firstChild : parent.lastChild ]; + + // non-xml :nth-child(...) stores cache data on `parent` + if ( forward && useCache ) { + + // Seek `elem` from a previously-cached index + + // ...in a gzip-friendly way + node = parent; + outerCache = node[ expando ] || ( node[ expando ] = {} ); + + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ node.uniqueID ] || + ( outerCache[ node.uniqueID ] = {} ); + + cache = uniqueCache[ type ] || []; + nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ]; + diff = nodeIndex && cache[ 2 ]; + node = nodeIndex && parent.childNodes[ nodeIndex ]; + + while ( ( node = ++nodeIndex && node && node[ dir ] || + + // Fallback to seeking `elem` from the start + ( diff = nodeIndex = 0 ) || start.pop() ) ) { + + // When found, cache indexes on `parent` and break + if ( node.nodeType === 1 && ++diff && node === elem ) { + uniqueCache[ type ] = [ dirruns, nodeIndex, diff ]; + break; + } + } + + } else { + + // Use previously-cached element index if available + if ( useCache ) { + + // ...in a gzip-friendly way + node = elem; + outerCache = node[ expando ] || ( node[ expando ] = {} ); + + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ node.uniqueID ] || + ( outerCache[ node.uniqueID ] = {} ); + + cache = uniqueCache[ type ] || []; + nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ]; + diff = nodeIndex; + } + + // xml :nth-child(...) + // or :nth-last-child(...) or :nth(-last)?-of-type(...) + if ( diff === false ) { + + // Use the same loop as above to seek `elem` from the start + while ( ( node = ++nodeIndex && node && node[ dir ] || + ( diff = nodeIndex = 0 ) || start.pop() ) ) { + + if ( ( ofType ? + node.nodeName.toLowerCase() === name : + node.nodeType === 1 ) && + ++diff ) { + + // Cache the index of each encountered element + if ( useCache ) { + outerCache = node[ expando ] || + ( node[ expando ] = {} ); + + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ node.uniqueID ] || + ( outerCache[ node.uniqueID ] = {} ); + + uniqueCache[ type ] = [ dirruns, diff ]; + } + + if ( node === elem ) { + break; + } + } + } + } + } + + // Incorporate the offset, then check against cycle size + diff -= last; + return diff === first || ( diff % first === 0 && diff / first >= 0 ); + } + }; + }, + + "PSEUDO": function( pseudo, argument ) { + + // pseudo-class names are case-insensitive + // http://www.w3.org/TR/selectors/#pseudo-classes + // Prioritize by case sensitivity in case custom pseudos are added with uppercase letters + // Remember that setFilters inherits from pseudos + var args, + fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] || + Sizzle.error( "unsupported pseudo: " + pseudo ); + + // The user may use createPseudo to indicate that + // arguments are needed to create the filter function + // just as Sizzle does + if ( fn[ expando ] ) { + return fn( argument ); + } + + // But maintain support for old signatures + if ( fn.length > 1 ) { + args = [ pseudo, pseudo, "", argument ]; + return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ? + markFunction( function( seed, matches ) { + var idx, + matched = fn( seed, argument ), + i = matched.length; + while ( i-- ) { + idx = indexOf( seed, matched[ i ] ); + seed[ idx ] = !( matches[ idx ] = matched[ i ] ); + } + } ) : + function( elem ) { + return fn( elem, 0, args ); + }; + } + + return fn; + } + }, + + pseudos: { + + // Potentially complex pseudos + "not": markFunction( function( selector ) { + + // Trim the selector passed to compile + // to avoid treating leading and trailing + // spaces as combinators + var input = [], + results = [], + matcher = compile( selector.replace( rtrim, "$1" ) ); + + return matcher[ expando ] ? + markFunction( function( seed, matches, _context, xml ) { + var elem, + unmatched = matcher( seed, null, xml, [] ), + i = seed.length; + + // Match elements unmatched by `matcher` + while ( i-- ) { + if ( ( elem = unmatched[ i ] ) ) { + seed[ i ] = !( matches[ i ] = elem ); + } + } + } ) : + function( elem, _context, xml ) { + input[ 0 ] = elem; + matcher( input, null, xml, results ); + + // Don't keep the element (issue #299) + input[ 0 ] = null; + return !results.pop(); + }; + } ), + + "has": markFunction( function( selector ) { + return function( elem ) { + return Sizzle( selector, elem ).length > 0; + }; + } ), + + "contains": markFunction( function( text ) { + text = text.replace( runescape, funescape ); + return function( elem ) { + return ( elem.textContent || getText( elem ) ).indexOf( text ) > -1; + }; + } ), + + // "Whether an element is represented by a :lang() selector + // is based solely on the element's language value + // being equal to the identifier C, + // or beginning with the identifier C immediately followed by "-". + // The matching of C against the element's language value is performed case-insensitively. + // The identifier C does not have to be a valid language name." + // http://www.w3.org/TR/selectors/#lang-pseudo + "lang": markFunction( function( lang ) { + + // lang value must be a valid identifier + if ( !ridentifier.test( lang || "" ) ) { + Sizzle.error( "unsupported lang: " + lang ); + } + lang = lang.replace( runescape, funescape ).toLowerCase(); + return function( elem ) { + var elemLang; + do { + if ( ( elemLang = documentIsHTML ? + elem.lang : + elem.getAttribute( "xml:lang" ) || elem.getAttribute( "lang" ) ) ) { + + elemLang = elemLang.toLowerCase(); + return elemLang === lang || elemLang.indexOf( lang + "-" ) === 0; + } + } while ( ( elem = elem.parentNode ) && elem.nodeType === 1 ); + return false; + }; + } ), + + // Miscellaneous + "target": function( elem ) { + var hash = window.location && window.location.hash; + return hash && hash.slice( 1 ) === elem.id; + }, + + "root": function( elem ) { + return elem === docElem; + }, + + "focus": function( elem ) { + return elem === document.activeElement && + ( !document.hasFocus || document.hasFocus() ) && + !!( elem.type || elem.href || ~elem.tabIndex ); + }, + + // Boolean properties + "enabled": createDisabledPseudo( false ), + "disabled": createDisabledPseudo( true ), + + "checked": function( elem ) { + + // In CSS3, :checked should return both checked and selected elements + // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked + var nodeName = elem.nodeName.toLowerCase(); + return ( nodeName === "input" && !!elem.checked ) || + ( nodeName === "option" && !!elem.selected ); + }, + + "selected": function( elem ) { + + // Accessing this property makes selected-by-default + // options in Safari work properly + if ( elem.parentNode ) { + // eslint-disable-next-line no-unused-expressions + elem.parentNode.selectedIndex; + } + + return elem.selected === true; + }, + + // Contents + "empty": function( elem ) { + + // http://www.w3.org/TR/selectors/#empty-pseudo + // :empty is negated by element (1) or content nodes (text: 3; cdata: 4; entity ref: 5), + // but not by others (comment: 8; processing instruction: 7; etc.) + // nodeType < 6 works because attributes (2) do not appear as children + for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { + if ( elem.nodeType < 6 ) { + return false; + } + } + return true; + }, + + "parent": function( elem ) { + return !Expr.pseudos[ "empty" ]( elem ); + }, + + // Element/input types + "header": function( elem ) { + return rheader.test( elem.nodeName ); + }, + + "input": function( elem ) { + return rinputs.test( elem.nodeName ); + }, + + "button": function( elem ) { + var name = elem.nodeName.toLowerCase(); + return name === "input" && elem.type === "button" || name === "button"; + }, + + "text": function( elem ) { + var attr; + return elem.nodeName.toLowerCase() === "input" && + elem.type === "text" && + + // Support: IE<8 + // New HTML5 attribute values (e.g., "search") appear with elem.type === "text" + ( ( attr = elem.getAttribute( "type" ) ) == null || + attr.toLowerCase() === "text" ); + }, + + // Position-in-collection + "first": createPositionalPseudo( function() { + return [ 0 ]; + } ), + + "last": createPositionalPseudo( function( _matchIndexes, length ) { + return [ length - 1 ]; + } ), + + "eq": createPositionalPseudo( function( _matchIndexes, length, argument ) { + return [ argument < 0 ? argument + length : argument ]; + } ), + + "even": createPositionalPseudo( function( matchIndexes, length ) { + var i = 0; + for ( ; i < length; i += 2 ) { + matchIndexes.push( i ); + } + return matchIndexes; + } ), + + "odd": createPositionalPseudo( function( matchIndexes, length ) { + var i = 1; + for ( ; i < length; i += 2 ) { + matchIndexes.push( i ); + } + return matchIndexes; + } ), + + "lt": createPositionalPseudo( function( matchIndexes, length, argument ) { + var i = argument < 0 ? + argument + length : + argument > length ? + length : + argument; + for ( ; --i >= 0; ) { + matchIndexes.push( i ); + } + return matchIndexes; + } ), + + "gt": createPositionalPseudo( function( matchIndexes, length, argument ) { + var i = argument < 0 ? argument + length : argument; + for ( ; ++i < length; ) { + matchIndexes.push( i ); + } + return matchIndexes; + } ) + } +}; + +Expr.pseudos[ "nth" ] = Expr.pseudos[ "eq" ]; + +// Add button/input type pseudos +for ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) { + Expr.pseudos[ i ] = createInputPseudo( i ); +} +for ( i in { submit: true, reset: true } ) { + Expr.pseudos[ i ] = createButtonPseudo( i ); +} + +// Easy API for creating new setFilters +function setFilters() {} +setFilters.prototype = Expr.filters = Expr.pseudos; +Expr.setFilters = new setFilters(); + +tokenize = Sizzle.tokenize = function( selector, parseOnly ) { + var matched, match, tokens, type, + soFar, groups, preFilters, + cached = tokenCache[ selector + " " ]; + + if ( cached ) { + return parseOnly ? 0 : cached.slice( 0 ); + } + + soFar = selector; + groups = []; + preFilters = Expr.preFilter; + + while ( soFar ) { + + // Comma and first run + if ( !matched || ( match = rcomma.exec( soFar ) ) ) { + if ( match ) { + + // Don't consume trailing commas as valid + soFar = soFar.slice( match[ 0 ].length ) || soFar; + } + groups.push( ( tokens = [] ) ); + } + + matched = false; + + // Combinators + if ( ( match = rcombinators.exec( soFar ) ) ) { + matched = match.shift(); + tokens.push( { + value: matched, + + // Cast descendant combinators to space + type: match[ 0 ].replace( rtrim, " " ) + } ); + soFar = soFar.slice( matched.length ); + } + + // Filters + for ( type in Expr.filter ) { + if ( ( match = matchExpr[ type ].exec( soFar ) ) && ( !preFilters[ type ] || + ( match = preFilters[ type ]( match ) ) ) ) { + matched = match.shift(); + tokens.push( { + value: matched, + type: type, + matches: match + } ); + soFar = soFar.slice( matched.length ); + } + } + + if ( !matched ) { + break; + } + } + + // Return the length of the invalid excess + // if we're just parsing + // Otherwise, throw an error or return tokens + return parseOnly ? + soFar.length : + soFar ? + Sizzle.error( selector ) : + + // Cache the tokens + tokenCache( selector, groups ).slice( 0 ); +}; + +function toSelector( tokens ) { + var i = 0, + len = tokens.length, + selector = ""; + for ( ; i < len; i++ ) { + selector += tokens[ i ].value; + } + return selector; +} + +function addCombinator( matcher, combinator, base ) { + var dir = combinator.dir, + skip = combinator.next, + key = skip || dir, + checkNonElements = base && key === "parentNode", + doneName = done++; + + return combinator.first ? + + // Check against closest ancestor/preceding element + function( elem, context, xml ) { + while ( ( elem = elem[ dir ] ) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + return matcher( elem, context, xml ); + } + } + return false; + } : + + // Check against all ancestor/preceding elements + function( elem, context, xml ) { + var oldCache, uniqueCache, outerCache, + newCache = [ dirruns, doneName ]; + + // We can't set arbitrary data on XML nodes, so they don't benefit from combinator caching + if ( xml ) { + while ( ( elem = elem[ dir ] ) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + if ( matcher( elem, context, xml ) ) { + return true; + } + } + } + } else { + while ( ( elem = elem[ dir ] ) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + outerCache = elem[ expando ] || ( elem[ expando ] = {} ); + + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ elem.uniqueID ] || + ( outerCache[ elem.uniqueID ] = {} ); + + if ( skip && skip === elem.nodeName.toLowerCase() ) { + elem = elem[ dir ] || elem; + } else if ( ( oldCache = uniqueCache[ key ] ) && + oldCache[ 0 ] === dirruns && oldCache[ 1 ] === doneName ) { + + // Assign to newCache so results back-propagate to previous elements + return ( newCache[ 2 ] = oldCache[ 2 ] ); + } else { + + // Reuse newcache so results back-propagate to previous elements + uniqueCache[ key ] = newCache; + + // A match means we're done; a fail means we have to keep checking + if ( ( newCache[ 2 ] = matcher( elem, context, xml ) ) ) { + return true; + } + } + } + } + } + return false; + }; +} + +function elementMatcher( matchers ) { + return matchers.length > 1 ? + function( elem, context, xml ) { + var i = matchers.length; + while ( i-- ) { + if ( !matchers[ i ]( elem, context, xml ) ) { + return false; + } + } + return true; + } : + matchers[ 0 ]; +} + +function multipleContexts( selector, contexts, results ) { + var i = 0, + len = contexts.length; + for ( ; i < len; i++ ) { + Sizzle( selector, contexts[ i ], results ); + } + return results; +} + +function condense( unmatched, map, filter, context, xml ) { + var elem, + newUnmatched = [], + i = 0, + len = unmatched.length, + mapped = map != null; + + for ( ; i < len; i++ ) { + if ( ( elem = unmatched[ i ] ) ) { + if ( !filter || filter( elem, context, xml ) ) { + newUnmatched.push( elem ); + if ( mapped ) { + map.push( i ); + } + } + } + } + + return newUnmatched; +} + +function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) { + if ( postFilter && !postFilter[ expando ] ) { + postFilter = setMatcher( postFilter ); + } + if ( postFinder && !postFinder[ expando ] ) { + postFinder = setMatcher( postFinder, postSelector ); + } + return markFunction( function( seed, results, context, xml ) { + var temp, i, elem, + preMap = [], + postMap = [], + preexisting = results.length, + + // Get initial elements from seed or context + elems = seed || multipleContexts( + selector || "*", + context.nodeType ? [ context ] : context, + [] + ), + + // Prefilter to get matcher input, preserving a map for seed-results synchronization + matcherIn = preFilter && ( seed || !selector ) ? + condense( elems, preMap, preFilter, context, xml ) : + elems, + + matcherOut = matcher ? + + // If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results, + postFinder || ( seed ? preFilter : preexisting || postFilter ) ? + + // ...intermediate processing is necessary + [] : + + // ...otherwise use results directly + results : + matcherIn; + + // Find primary matches + if ( matcher ) { + matcher( matcherIn, matcherOut, context, xml ); + } + + // Apply postFilter + if ( postFilter ) { + temp = condense( matcherOut, postMap ); + postFilter( temp, [], context, xml ); + + // Un-match failing elements by moving them back to matcherIn + i = temp.length; + while ( i-- ) { + if ( ( elem = temp[ i ] ) ) { + matcherOut[ postMap[ i ] ] = !( matcherIn[ postMap[ i ] ] = elem ); + } + } + } + + if ( seed ) { + if ( postFinder || preFilter ) { + if ( postFinder ) { + + // Get the final matcherOut by condensing this intermediate into postFinder contexts + temp = []; + i = matcherOut.length; + while ( i-- ) { + if ( ( elem = matcherOut[ i ] ) ) { + + // Restore matcherIn since elem is not yet a final match + temp.push( ( matcherIn[ i ] = elem ) ); + } + } + postFinder( null, ( matcherOut = [] ), temp, xml ); + } + + // Move matched elements from seed to results to keep them synchronized + i = matcherOut.length; + while ( i-- ) { + if ( ( elem = matcherOut[ i ] ) && + ( temp = postFinder ? indexOf( seed, elem ) : preMap[ i ] ) > -1 ) { + + seed[ temp ] = !( results[ temp ] = elem ); + } + } + } + + // Add elements to results, through postFinder if defined + } else { + matcherOut = condense( + matcherOut === results ? + matcherOut.splice( preexisting, matcherOut.length ) : + matcherOut + ); + if ( postFinder ) { + postFinder( null, results, matcherOut, xml ); + } else { + push.apply( results, matcherOut ); + } + } + } ); +} + +function matcherFromTokens( tokens ) { + var checkContext, matcher, j, + len = tokens.length, + leadingRelative = Expr.relative[ tokens[ 0 ].type ], + implicitRelative = leadingRelative || Expr.relative[ " " ], + i = leadingRelative ? 1 : 0, + + // The foundational matcher ensures that elements are reachable from top-level context(s) + matchContext = addCombinator( function( elem ) { + return elem === checkContext; + }, implicitRelative, true ), + matchAnyContext = addCombinator( function( elem ) { + return indexOf( checkContext, elem ) > -1; + }, implicitRelative, true ), + matchers = [ function( elem, context, xml ) { + var ret = ( !leadingRelative && ( xml || context !== outermostContext ) ) || ( + ( checkContext = context ).nodeType ? + matchContext( elem, context, xml ) : + matchAnyContext( elem, context, xml ) ); + + // Avoid hanging onto element (issue #299) + checkContext = null; + return ret; + } ]; + + for ( ; i < len; i++ ) { + if ( ( matcher = Expr.relative[ tokens[ i ].type ] ) ) { + matchers = [ addCombinator( elementMatcher( matchers ), matcher ) ]; + } else { + matcher = Expr.filter[ tokens[ i ].type ].apply( null, tokens[ i ].matches ); + + // Return special upon seeing a positional matcher + if ( matcher[ expando ] ) { + + // Find the next relative operator (if any) for proper handling + j = ++i; + for ( ; j < len; j++ ) { + if ( Expr.relative[ tokens[ j ].type ] ) { + break; + } + } + return setMatcher( + i > 1 && elementMatcher( matchers ), + i > 1 && toSelector( + + // If the preceding token was a descendant combinator, insert an implicit any-element `*` + tokens + .slice( 0, i - 1 ) + .concat( { value: tokens[ i - 2 ].type === " " ? "*" : "" } ) + ).replace( rtrim, "$1" ), + matcher, + i < j && matcherFromTokens( tokens.slice( i, j ) ), + j < len && matcherFromTokens( ( tokens = tokens.slice( j ) ) ), + j < len && toSelector( tokens ) + ); + } + matchers.push( matcher ); + } + } + + return elementMatcher( matchers ); +} + +function matcherFromGroupMatchers( elementMatchers, setMatchers ) { + var bySet = setMatchers.length > 0, + byElement = elementMatchers.length > 0, + superMatcher = function( seed, context, xml, results, outermost ) { + var elem, j, matcher, + matchedCount = 0, + i = "0", + unmatched = seed && [], + setMatched = [], + contextBackup = outermostContext, + + // We must always have either seed elements or outermost context + elems = seed || byElement && Expr.find[ "TAG" ]( "*", outermost ), + + // Use integer dirruns iff this is the outermost matcher + dirrunsUnique = ( dirruns += contextBackup == null ? 1 : Math.random() || 0.1 ), + len = elems.length; + + if ( outermost ) { + + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + outermostContext = context == document || context || outermost; + } + + // Add elements passing elementMatchers directly to results + // Support: IE<9, Safari + // Tolerate NodeList properties (IE: "length"; Safari: ) matching elements by id + for ( ; i !== len && ( elem = elems[ i ] ) != null; i++ ) { + if ( byElement && elem ) { + j = 0; + + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( !context && elem.ownerDocument != document ) { + setDocument( elem ); + xml = !documentIsHTML; + } + while ( ( matcher = elementMatchers[ j++ ] ) ) { + if ( matcher( elem, context || document, xml ) ) { + results.push( elem ); + break; + } + } + if ( outermost ) { + dirruns = dirrunsUnique; + } + } + + // Track unmatched elements for set filters + if ( bySet ) { + + // They will have gone through all possible matchers + if ( ( elem = !matcher && elem ) ) { + matchedCount--; + } + + // Lengthen the array for every element, matched or not + if ( seed ) { + unmatched.push( elem ); + } + } + } + + // `i` is now the count of elements visited above, and adding it to `matchedCount` + // makes the latter nonnegative. + matchedCount += i; + + // Apply set filters to unmatched elements + // NOTE: This can be skipped if there are no unmatched elements (i.e., `matchedCount` + // equals `i`), unless we didn't visit _any_ elements in the above loop because we have + // no element matchers and no seed. + // Incrementing an initially-string "0" `i` allows `i` to remain a string only in that + // case, which will result in a "00" `matchedCount` that differs from `i` but is also + // numerically zero. + if ( bySet && i !== matchedCount ) { + j = 0; + while ( ( matcher = setMatchers[ j++ ] ) ) { + matcher( unmatched, setMatched, context, xml ); + } + + if ( seed ) { + + // Reintegrate element matches to eliminate the need for sorting + if ( matchedCount > 0 ) { + while ( i-- ) { + if ( !( unmatched[ i ] || setMatched[ i ] ) ) { + setMatched[ i ] = pop.call( results ); + } + } + } + + // Discard index placeholder values to get only actual matches + setMatched = condense( setMatched ); + } + + // Add matches to results + push.apply( results, setMatched ); + + // Seedless set matches succeeding multiple successful matchers stipulate sorting + if ( outermost && !seed && setMatched.length > 0 && + ( matchedCount + setMatchers.length ) > 1 ) { + + Sizzle.uniqueSort( results ); + } + } + + // Override manipulation of globals by nested matchers + if ( outermost ) { + dirruns = dirrunsUnique; + outermostContext = contextBackup; + } + + return unmatched; + }; + + return bySet ? + markFunction( superMatcher ) : + superMatcher; +} + +compile = Sizzle.compile = function( selector, match /* Internal Use Only */ ) { + var i, + setMatchers = [], + elementMatchers = [], + cached = compilerCache[ selector + " " ]; + + if ( !cached ) { + + // Generate a function of recursive functions that can be used to check each element + if ( !match ) { + match = tokenize( selector ); + } + i = match.length; + while ( i-- ) { + cached = matcherFromTokens( match[ i ] ); + if ( cached[ expando ] ) { + setMatchers.push( cached ); + } else { + elementMatchers.push( cached ); + } + } + + // Cache the compiled function + cached = compilerCache( + selector, + matcherFromGroupMatchers( elementMatchers, setMatchers ) + ); + + // Save selector and tokenization + cached.selector = selector; + } + return cached; +}; + +/** + * A low-level selection function that works with Sizzle's compiled + * selector functions + * @param {String|Function} selector A selector or a pre-compiled + * selector function built with Sizzle.compile + * @param {Element} context + * @param {Array} [results] + * @param {Array} [seed] A set of elements to match against + */ +select = Sizzle.select = function( selector, context, results, seed ) { + var i, tokens, token, type, find, + compiled = typeof selector === "function" && selector, + match = !seed && tokenize( ( selector = compiled.selector || selector ) ); + + results = results || []; + + // Try to minimize operations if there is only one selector in the list and no seed + // (the latter of which guarantees us context) + if ( match.length === 1 ) { + + // Reduce context if the leading compound selector is an ID + tokens = match[ 0 ] = match[ 0 ].slice( 0 ); + if ( tokens.length > 2 && ( token = tokens[ 0 ] ).type === "ID" && + context.nodeType === 9 && documentIsHTML && Expr.relative[ tokens[ 1 ].type ] ) { + + context = ( Expr.find[ "ID" ]( token.matches[ 0 ] + .replace( runescape, funescape ), context ) || [] )[ 0 ]; + if ( !context ) { + return results; + + // Precompiled matchers will still verify ancestry, so step up a level + } else if ( compiled ) { + context = context.parentNode; + } + + selector = selector.slice( tokens.shift().value.length ); + } + + // Fetch a seed set for right-to-left matching + i = matchExpr[ "needsContext" ].test( selector ) ? 0 : tokens.length; + while ( i-- ) { + token = tokens[ i ]; + + // Abort if we hit a combinator + if ( Expr.relative[ ( type = token.type ) ] ) { + break; + } + if ( ( find = Expr.find[ type ] ) ) { + + // Search, expanding context for leading sibling combinators + if ( ( seed = find( + token.matches[ 0 ].replace( runescape, funescape ), + rsibling.test( tokens[ 0 ].type ) && testContext( context.parentNode ) || + context + ) ) ) { + + // If seed is empty or no tokens remain, we can return early + tokens.splice( i, 1 ); + selector = seed.length && toSelector( tokens ); + if ( !selector ) { + push.apply( results, seed ); + return results; + } + + break; + } + } + } + } + + // Compile and execute a filtering function if one is not provided + // Provide `match` to avoid retokenization if we modified the selector above + ( compiled || compile( selector, match ) )( + seed, + context, + !documentIsHTML, + results, + !context || rsibling.test( selector ) && testContext( context.parentNode ) || context + ); + return results; +}; + +// One-time assignments + +// Sort stability +support.sortStable = expando.split( "" ).sort( sortOrder ).join( "" ) === expando; + +// Support: Chrome 14-35+ +// Always assume duplicates if they aren't passed to the comparison function +support.detectDuplicates = !!hasDuplicate; + +// Initialize against the default document +setDocument(); + +// Support: Webkit<537.32 - Safari 6.0.3/Chrome 25 (fixed in Chrome 27) +// Detached nodes confoundingly follow *each other* +support.sortDetached = assert( function( el ) { + + // Should return 1, but returns 4 (following) + return el.compareDocumentPosition( document.createElement( "fieldset" ) ) & 1; +} ); + +// Support: IE<8 +// Prevent attribute/property "interpolation" +// https://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx +if ( !assert( function( el ) { + el.innerHTML = ""; + return el.firstChild.getAttribute( "href" ) === "#"; +} ) ) { + addHandle( "type|href|height|width", function( elem, name, isXML ) { + if ( !isXML ) { + return elem.getAttribute( name, name.toLowerCase() === "type" ? 1 : 2 ); + } + } ); +} + +// Support: IE<9 +// Use defaultValue in place of getAttribute("value") +if ( !support.attributes || !assert( function( el ) { + el.innerHTML = ""; + el.firstChild.setAttribute( "value", "" ); + return el.firstChild.getAttribute( "value" ) === ""; +} ) ) { + addHandle( "value", function( elem, _name, isXML ) { + if ( !isXML && elem.nodeName.toLowerCase() === "input" ) { + return elem.defaultValue; + } + } ); +} + +// Support: IE<9 +// Use getAttributeNode to fetch booleans when getAttribute lies +if ( !assert( function( el ) { + return el.getAttribute( "disabled" ) == null; +} ) ) { + addHandle( booleans, function( elem, name, isXML ) { + var val; + if ( !isXML ) { + return elem[ name ] === true ? name.toLowerCase() : + ( val = elem.getAttributeNode( name ) ) && val.specified ? + val.value : + null; + } + } ); +} + +return Sizzle; + +} )( window ); + + + +jQuery.find = Sizzle; +jQuery.expr = Sizzle.selectors; + +// Deprecated +jQuery.expr[ ":" ] = jQuery.expr.pseudos; +jQuery.uniqueSort = jQuery.unique = Sizzle.uniqueSort; +jQuery.text = Sizzle.getText; +jQuery.isXMLDoc = Sizzle.isXML; +jQuery.contains = Sizzle.contains; +jQuery.escapeSelector = Sizzle.escape; + + + + +var dir = function( elem, dir, until ) { + var matched = [], + truncate = until !== undefined; + + while ( ( elem = elem[ dir ] ) && elem.nodeType !== 9 ) { + if ( elem.nodeType === 1 ) { + if ( truncate && jQuery( elem ).is( until ) ) { + break; + } + matched.push( elem ); + } + } + return matched; +}; + + +var siblings = function( n, elem ) { + var matched = []; + + for ( ; n; n = n.nextSibling ) { + if ( n.nodeType === 1 && n !== elem ) { + matched.push( n ); + } + } + + return matched; +}; + + +var rneedsContext = jQuery.expr.match.needsContext; + + + +function nodeName( elem, name ) { + + return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase(); + +}; +var rsingleTag = ( /^<([a-z][^\/\0>:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i ); + + + +// Implement the identical functionality for filter and not +function winnow( elements, qualifier, not ) { + if ( isFunction( qualifier ) ) { + return jQuery.grep( elements, function( elem, i ) { + return !!qualifier.call( elem, i, elem ) !== not; + } ); + } + + // Single element + if ( qualifier.nodeType ) { + return jQuery.grep( elements, function( elem ) { + return ( elem === qualifier ) !== not; + } ); + } + + // Arraylike of elements (jQuery, arguments, Array) + if ( typeof qualifier !== "string" ) { + return jQuery.grep( elements, function( elem ) { + return ( indexOf.call( qualifier, elem ) > -1 ) !== not; + } ); + } + + // Filtered directly for both simple and complex selectors + return jQuery.filter( qualifier, elements, not ); +} + +jQuery.filter = function( expr, elems, not ) { + var elem = elems[ 0 ]; + + if ( not ) { + expr = ":not(" + expr + ")"; + } + + if ( elems.length === 1 && elem.nodeType === 1 ) { + return jQuery.find.matchesSelector( elem, expr ) ? [ elem ] : []; + } + + return jQuery.find.matches( expr, jQuery.grep( elems, function( elem ) { + return elem.nodeType === 1; + } ) ); +}; + +jQuery.fn.extend( { + find: function( selector ) { + var i, ret, + len = this.length, + self = this; + + if ( typeof selector !== "string" ) { + return this.pushStack( jQuery( selector ).filter( function() { + for ( i = 0; i < len; i++ ) { + if ( jQuery.contains( self[ i ], this ) ) { + return true; + } + } + } ) ); + } + + ret = this.pushStack( [] ); + + for ( i = 0; i < len; i++ ) { + jQuery.find( selector, self[ i ], ret ); + } + + return len > 1 ? jQuery.uniqueSort( ret ) : ret; + }, + filter: function( selector ) { + return this.pushStack( winnow( this, selector || [], false ) ); + }, + not: function( selector ) { + return this.pushStack( winnow( this, selector || [], true ) ); + }, + is: function( selector ) { + return !!winnow( + this, + + // If this is a positional/relative selector, check membership in the returned set + // so $("p:first").is("p:last") won't return true for a doc with two "p". + typeof selector === "string" && rneedsContext.test( selector ) ? + jQuery( selector ) : + selector || [], + false + ).length; + } +} ); + + +// Initialize a jQuery object + + +// A central reference to the root jQuery(document) +var rootjQuery, + + // A simple way to check for HTML strings + // Prioritize #id over to avoid XSS via location.hash (#9521) + // Strict HTML recognition (#11290: must start with <) + // Shortcut simple #id case for speed + rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]+))$/, + + init = jQuery.fn.init = function( selector, context, root ) { + var match, elem; + + // HANDLE: $(""), $(null), $(undefined), $(false) + if ( !selector ) { + return this; + } + + // Method init() accepts an alternate rootjQuery + // so migrate can support jQuery.sub (gh-2101) + root = root || rootjQuery; + + // Handle HTML strings + if ( typeof selector === "string" ) { + if ( selector[ 0 ] === "<" && + selector[ selector.length - 1 ] === ">" && + selector.length >= 3 ) { + + // Assume that strings that start and end with <> are HTML and skip the regex check + match = [ null, selector, null ]; + + } else { + match = rquickExpr.exec( selector ); + } + + // Match html or make sure no context is specified for #id + if ( match && ( match[ 1 ] || !context ) ) { + + // HANDLE: $(html) -> $(array) + if ( match[ 1 ] ) { + context = context instanceof jQuery ? context[ 0 ] : context; + + // Option to run scripts is true for back-compat + // Intentionally let the error be thrown if parseHTML is not present + jQuery.merge( this, jQuery.parseHTML( + match[ 1 ], + context && context.nodeType ? context.ownerDocument || context : document, + true + ) ); + + // HANDLE: $(html, props) + if ( rsingleTag.test( match[ 1 ] ) && jQuery.isPlainObject( context ) ) { + for ( match in context ) { + + // Properties of context are called as methods if possible + if ( isFunction( this[ match ] ) ) { + this[ match ]( context[ match ] ); + + // ...and otherwise set as attributes + } else { + this.attr( match, context[ match ] ); + } + } + } + + return this; + + // HANDLE: $(#id) + } else { + elem = document.getElementById( match[ 2 ] ); + + if ( elem ) { + + // Inject the element directly into the jQuery object + this[ 0 ] = elem; + this.length = 1; + } + return this; + } + + // HANDLE: $(expr, $(...)) + } else if ( !context || context.jquery ) { + return ( context || root ).find( selector ); + + // HANDLE: $(expr, context) + // (which is just equivalent to: $(context).find(expr) + } else { + return this.constructor( context ).find( selector ); + } + + // HANDLE: $(DOMElement) + } else if ( selector.nodeType ) { + this[ 0 ] = selector; + this.length = 1; + return this; + + // HANDLE: $(function) + // Shortcut for document ready + } else if ( isFunction( selector ) ) { + return root.ready !== undefined ? + root.ready( selector ) : + + // Execute immediately if ready is not present + selector( jQuery ); + } + + return jQuery.makeArray( selector, this ); + }; + +// Give the init function the jQuery prototype for later instantiation +init.prototype = jQuery.fn; + +// Initialize central reference +rootjQuery = jQuery( document ); + + +var rparentsprev = /^(?:parents|prev(?:Until|All))/, + + // Methods guaranteed to produce a unique set when starting from a unique set + guaranteedUnique = { + children: true, + contents: true, + next: true, + prev: true + }; + +jQuery.fn.extend( { + has: function( target ) { + var targets = jQuery( target, this ), + l = targets.length; + + return this.filter( function() { + var i = 0; + for ( ; i < l; i++ ) { + if ( jQuery.contains( this, targets[ i ] ) ) { + return true; + } + } + } ); + }, + + closest: function( selectors, context ) { + var cur, + i = 0, + l = this.length, + matched = [], + targets = typeof selectors !== "string" && jQuery( selectors ); + + // Positional selectors never match, since there's no _selection_ context + if ( !rneedsContext.test( selectors ) ) { + for ( ; i < l; i++ ) { + for ( cur = this[ i ]; cur && cur !== context; cur = cur.parentNode ) { + + // Always skip document fragments + if ( cur.nodeType < 11 && ( targets ? + targets.index( cur ) > -1 : + + // Don't pass non-elements to Sizzle + cur.nodeType === 1 && + jQuery.find.matchesSelector( cur, selectors ) ) ) { + + matched.push( cur ); + break; + } + } + } + } + + return this.pushStack( matched.length > 1 ? jQuery.uniqueSort( matched ) : matched ); + }, + + // Determine the position of an element within the set + index: function( elem ) { + + // No argument, return index in parent + if ( !elem ) { + return ( this[ 0 ] && this[ 0 ].parentNode ) ? this.first().prevAll().length : -1; + } + + // Index in selector + if ( typeof elem === "string" ) { + return indexOf.call( jQuery( elem ), this[ 0 ] ); + } + + // Locate the position of the desired element + return indexOf.call( this, + + // If it receives a jQuery object, the first element is used + elem.jquery ? elem[ 0 ] : elem + ); + }, + + add: function( selector, context ) { + return this.pushStack( + jQuery.uniqueSort( + jQuery.merge( this.get(), jQuery( selector, context ) ) + ) + ); + }, + + addBack: function( selector ) { + return this.add( selector == null ? + this.prevObject : this.prevObject.filter( selector ) + ); + } +} ); + +function sibling( cur, dir ) { + while ( ( cur = cur[ dir ] ) && cur.nodeType !== 1 ) {} + return cur; +} + +jQuery.each( { + parent: function( elem ) { + var parent = elem.parentNode; + return parent && parent.nodeType !== 11 ? parent : null; + }, + parents: function( elem ) { + return dir( elem, "parentNode" ); + }, + parentsUntil: function( elem, _i, until ) { + return dir( elem, "parentNode", until ); + }, + next: function( elem ) { + return sibling( elem, "nextSibling" ); + }, + prev: function( elem ) { + return sibling( elem, "previousSibling" ); + }, + nextAll: function( elem ) { + return dir( elem, "nextSibling" ); + }, + prevAll: function( elem ) { + return dir( elem, "previousSibling" ); + }, + nextUntil: function( elem, _i, until ) { + return dir( elem, "nextSibling", until ); + }, + prevUntil: function( elem, _i, until ) { + return dir( elem, "previousSibling", until ); + }, + siblings: function( elem ) { + return siblings( ( elem.parentNode || {} ).firstChild, elem ); + }, + children: function( elem ) { + return siblings( elem.firstChild ); + }, + contents: function( elem ) { + if ( elem.contentDocument != null && + + // Support: IE 11+ + // elements with no `data` attribute has an object + // `contentDocument` with a `null` prototype. + getProto( elem.contentDocument ) ) { + + return elem.contentDocument; + } + + // Support: IE 9 - 11 only, iOS 7 only, Android Browser <=4.3 only + // Treat the template element as a regular one in browsers that + // don't support it. + if ( nodeName( elem, "template" ) ) { + elem = elem.content || elem; + } + + return jQuery.merge( [], elem.childNodes ); + } +}, function( name, fn ) { + jQuery.fn[ name ] = function( until, selector ) { + var matched = jQuery.map( this, fn, until ); + + if ( name.slice( -5 ) !== "Until" ) { + selector = until; + } + + if ( selector && typeof selector === "string" ) { + matched = jQuery.filter( selector, matched ); + } + + if ( this.length > 1 ) { + + // Remove duplicates + if ( !guaranteedUnique[ name ] ) { + jQuery.uniqueSort( matched ); + } + + // Reverse order for parents* and prev-derivatives + if ( rparentsprev.test( name ) ) { + matched.reverse(); + } + } + + return this.pushStack( matched ); + }; +} ); +var rnothtmlwhite = ( /[^\x20\t\r\n\f]+/g ); + + + +// Convert String-formatted options into Object-formatted ones +function createOptions( options ) { + var object = {}; + jQuery.each( options.match( rnothtmlwhite ) || [], function( _, flag ) { + object[ flag ] = true; + } ); + return object; +} + +/* + * Create a callback list using the following parameters: + * + * options: an optional list of space-separated options that will change how + * the callback list behaves or a more traditional option object + * + * By default a callback list will act like an event callback list and can be + * "fired" multiple times. + * + * Possible options: + * + * once: will ensure the callback list can only be fired once (like a Deferred) + * + * memory: will keep track of previous values and will call any callback added + * after the list has been fired right away with the latest "memorized" + * values (like a Deferred) + * + * unique: will ensure a callback can only be added once (no duplicate in the list) + * + * stopOnFalse: interrupt callings when a callback returns false + * + */ +jQuery.Callbacks = function( options ) { + + // Convert options from String-formatted to Object-formatted if needed + // (we check in cache first) + options = typeof options === "string" ? + createOptions( options ) : + jQuery.extend( {}, options ); + + var // Flag to know if list is currently firing + firing, + + // Last fire value for non-forgettable lists + memory, + + // Flag to know if list was already fired + fired, + + // Flag to prevent firing + locked, + + // Actual callback list + list = [], + + // Queue of execution data for repeatable lists + queue = [], + + // Index of currently firing callback (modified by add/remove as needed) + firingIndex = -1, + + // Fire callbacks + fire = function() { + + // Enforce single-firing + locked = locked || options.once; + + // Execute callbacks for all pending executions, + // respecting firingIndex overrides and runtime changes + fired = firing = true; + for ( ; queue.length; firingIndex = -1 ) { + memory = queue.shift(); + while ( ++firingIndex < list.length ) { + + // Run callback and check for early termination + if ( list[ firingIndex ].apply( memory[ 0 ], memory[ 1 ] ) === false && + options.stopOnFalse ) { + + // Jump to end and forget the data so .add doesn't re-fire + firingIndex = list.length; + memory = false; + } + } + } + + // Forget the data if we're done with it + if ( !options.memory ) { + memory = false; + } + + firing = false; + + // Clean up if we're done firing for good + if ( locked ) { + + // Keep an empty list if we have data for future add calls + if ( memory ) { + list = []; + + // Otherwise, this object is spent + } else { + list = ""; + } + } + }, + + // Actual Callbacks object + self = { + + // Add a callback or a collection of callbacks to the list + add: function() { + if ( list ) { + + // If we have memory from a past run, we should fire after adding + if ( memory && !firing ) { + firingIndex = list.length - 1; + queue.push( memory ); + } + + ( function add( args ) { + jQuery.each( args, function( _, arg ) { + if ( isFunction( arg ) ) { + if ( !options.unique || !self.has( arg ) ) { + list.push( arg ); + } + } else if ( arg && arg.length && toType( arg ) !== "string" ) { + + // Inspect recursively + add( arg ); + } + } ); + } )( arguments ); + + if ( memory && !firing ) { + fire(); + } + } + return this; + }, + + // Remove a callback from the list + remove: function() { + jQuery.each( arguments, function( _, arg ) { + var index; + while ( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) { + list.splice( index, 1 ); + + // Handle firing indexes + if ( index <= firingIndex ) { + firingIndex--; + } + } + } ); + return this; + }, + + // Check if a given callback is in the list. + // If no argument is given, return whether or not list has callbacks attached. + has: function( fn ) { + return fn ? + jQuery.inArray( fn, list ) > -1 : + list.length > 0; + }, + + // Remove all callbacks from the list + empty: function() { + if ( list ) { + list = []; + } + return this; + }, + + // Disable .fire and .add + // Abort any current/pending executions + // Clear all callbacks and values + disable: function() { + locked = queue = []; + list = memory = ""; + return this; + }, + disabled: function() { + return !list; + }, + + // Disable .fire + // Also disable .add unless we have memory (since it would have no effect) + // Abort any pending executions + lock: function() { + locked = queue = []; + if ( !memory && !firing ) { + list = memory = ""; + } + return this; + }, + locked: function() { + return !!locked; + }, + + // Call all callbacks with the given context and arguments + fireWith: function( context, args ) { + if ( !locked ) { + args = args || []; + args = [ context, args.slice ? args.slice() : args ]; + queue.push( args ); + if ( !firing ) { + fire(); + } + } + return this; + }, + + // Call all the callbacks with the given arguments + fire: function() { + self.fireWith( this, arguments ); + return this; + }, + + // To know if the callbacks have already been called at least once + fired: function() { + return !!fired; + } + }; + + return self; +}; + + +function Identity( v ) { + return v; +} +function Thrower( ex ) { + throw ex; +} + +function adoptValue( value, resolve, reject, noValue ) { + var method; + + try { + + // Check for promise aspect first to privilege synchronous behavior + if ( value && isFunction( ( method = value.promise ) ) ) { + method.call( value ).done( resolve ).fail( reject ); + + // Other thenables + } else if ( value && isFunction( ( method = value.then ) ) ) { + method.call( value, resolve, reject ); + + // Other non-thenables + } else { + + // Control `resolve` arguments by letting Array#slice cast boolean `noValue` to integer: + // * false: [ value ].slice( 0 ) => resolve( value ) + // * true: [ value ].slice( 1 ) => resolve() + resolve.apply( undefined, [ value ].slice( noValue ) ); + } + + // For Promises/A+, convert exceptions into rejections + // Since jQuery.when doesn't unwrap thenables, we can skip the extra checks appearing in + // Deferred#then to conditionally suppress rejection. + } catch ( value ) { + + // Support: Android 4.0 only + // Strict mode functions invoked without .call/.apply get global-object context + reject.apply( undefined, [ value ] ); + } +} + +jQuery.extend( { + + Deferred: function( func ) { + var tuples = [ + + // action, add listener, callbacks, + // ... .then handlers, argument index, [final state] + [ "notify", "progress", jQuery.Callbacks( "memory" ), + jQuery.Callbacks( "memory" ), 2 ], + [ "resolve", "done", jQuery.Callbacks( "once memory" ), + jQuery.Callbacks( "once memory" ), 0, "resolved" ], + [ "reject", "fail", jQuery.Callbacks( "once memory" ), + jQuery.Callbacks( "once memory" ), 1, "rejected" ] + ], + state = "pending", + promise = { + state: function() { + return state; + }, + always: function() { + deferred.done( arguments ).fail( arguments ); + return this; + }, + "catch": function( fn ) { + return promise.then( null, fn ); + }, + + // Keep pipe for back-compat + pipe: function( /* fnDone, fnFail, fnProgress */ ) { + var fns = arguments; + + return jQuery.Deferred( function( newDefer ) { + jQuery.each( tuples, function( _i, tuple ) { + + // Map tuples (progress, done, fail) to arguments (done, fail, progress) + var fn = isFunction( fns[ tuple[ 4 ] ] ) && fns[ tuple[ 4 ] ]; + + // deferred.progress(function() { bind to newDefer or newDefer.notify }) + // deferred.done(function() { bind to newDefer or newDefer.resolve }) + // deferred.fail(function() { bind to newDefer or newDefer.reject }) + deferred[ tuple[ 1 ] ]( function() { + var returned = fn && fn.apply( this, arguments ); + if ( returned && isFunction( returned.promise ) ) { + returned.promise() + .progress( newDefer.notify ) + .done( newDefer.resolve ) + .fail( newDefer.reject ); + } else { + newDefer[ tuple[ 0 ] + "With" ]( + this, + fn ? [ returned ] : arguments + ); + } + } ); + } ); + fns = null; + } ).promise(); + }, + then: function( onFulfilled, onRejected, onProgress ) { + var maxDepth = 0; + function resolve( depth, deferred, handler, special ) { + return function() { + var that = this, + args = arguments, + mightThrow = function() { + var returned, then; + + // Support: Promises/A+ section 2.3.3.3.3 + // https://promisesaplus.com/#point-59 + // Ignore double-resolution attempts + if ( depth < maxDepth ) { + return; + } + + returned = handler.apply( that, args ); + + // Support: Promises/A+ section 2.3.1 + // https://promisesaplus.com/#point-48 + if ( returned === deferred.promise() ) { + throw new TypeError( "Thenable self-resolution" ); + } + + // Support: Promises/A+ sections 2.3.3.1, 3.5 + // https://promisesaplus.com/#point-54 + // https://promisesaplus.com/#point-75 + // Retrieve `then` only once + then = returned && + + // Support: Promises/A+ section 2.3.4 + // https://promisesaplus.com/#point-64 + // Only check objects and functions for thenability + ( typeof returned === "object" || + typeof returned === "function" ) && + returned.then; + + // Handle a returned thenable + if ( isFunction( then ) ) { + + // Special processors (notify) just wait for resolution + if ( special ) { + then.call( + returned, + resolve( maxDepth, deferred, Identity, special ), + resolve( maxDepth, deferred, Thrower, special ) + ); + + // Normal processors (resolve) also hook into progress + } else { + + // ...and disregard older resolution values + maxDepth++; + + then.call( + returned, + resolve( maxDepth, deferred, Identity, special ), + resolve( maxDepth, deferred, Thrower, special ), + resolve( maxDepth, deferred, Identity, + deferred.notifyWith ) + ); + } + + // Handle all other returned values + } else { + + // Only substitute handlers pass on context + // and multiple values (non-spec behavior) + if ( handler !== Identity ) { + that = undefined; + args = [ returned ]; + } + + // Process the value(s) + // Default process is resolve + ( special || deferred.resolveWith )( that, args ); + } + }, + + // Only normal processors (resolve) catch and reject exceptions + process = special ? + mightThrow : + function() { + try { + mightThrow(); + } catch ( e ) { + + if ( jQuery.Deferred.exceptionHook ) { + jQuery.Deferred.exceptionHook( e, + process.stackTrace ); + } + + // Support: Promises/A+ section 2.3.3.3.4.1 + // https://promisesaplus.com/#point-61 + // Ignore post-resolution exceptions + if ( depth + 1 >= maxDepth ) { + + // Only substitute handlers pass on context + // and multiple values (non-spec behavior) + if ( handler !== Thrower ) { + that = undefined; + args = [ e ]; + } + + deferred.rejectWith( that, args ); + } + } + }; + + // Support: Promises/A+ section 2.3.3.3.1 + // https://promisesaplus.com/#point-57 + // Re-resolve promises immediately to dodge false rejection from + // subsequent errors + if ( depth ) { + process(); + } else { + + // Call an optional hook to record the stack, in case of exception + // since it's otherwise lost when execution goes async + if ( jQuery.Deferred.getStackHook ) { + process.stackTrace = jQuery.Deferred.getStackHook(); + } + window.setTimeout( process ); + } + }; + } + + return jQuery.Deferred( function( newDefer ) { + + // progress_handlers.add( ... ) + tuples[ 0 ][ 3 ].add( + resolve( + 0, + newDefer, + isFunction( onProgress ) ? + onProgress : + Identity, + newDefer.notifyWith + ) + ); + + // fulfilled_handlers.add( ... ) + tuples[ 1 ][ 3 ].add( + resolve( + 0, + newDefer, + isFunction( onFulfilled ) ? + onFulfilled : + Identity + ) + ); + + // rejected_handlers.add( ... ) + tuples[ 2 ][ 3 ].add( + resolve( + 0, + newDefer, + isFunction( onRejected ) ? + onRejected : + Thrower + ) + ); + } ).promise(); + }, + + // Get a promise for this deferred + // If obj is provided, the promise aspect is added to the object + promise: function( obj ) { + return obj != null ? jQuery.extend( obj, promise ) : promise; + } + }, + deferred = {}; + + // Add list-specific methods + jQuery.each( tuples, function( i, tuple ) { + var list = tuple[ 2 ], + stateString = tuple[ 5 ]; + + // promise.progress = list.add + // promise.done = list.add + // promise.fail = list.add + promise[ tuple[ 1 ] ] = list.add; + + // Handle state + if ( stateString ) { + list.add( + function() { + + // state = "resolved" (i.e., fulfilled) + // state = "rejected" + state = stateString; + }, + + // rejected_callbacks.disable + // fulfilled_callbacks.disable + tuples[ 3 - i ][ 2 ].disable, + + // rejected_handlers.disable + // fulfilled_handlers.disable + tuples[ 3 - i ][ 3 ].disable, + + // progress_callbacks.lock + tuples[ 0 ][ 2 ].lock, + + // progress_handlers.lock + tuples[ 0 ][ 3 ].lock + ); + } + + // progress_handlers.fire + // fulfilled_handlers.fire + // rejected_handlers.fire + list.add( tuple[ 3 ].fire ); + + // deferred.notify = function() { deferred.notifyWith(...) } + // deferred.resolve = function() { deferred.resolveWith(...) } + // deferred.reject = function() { deferred.rejectWith(...) } + deferred[ tuple[ 0 ] ] = function() { + deferred[ tuple[ 0 ] + "With" ]( this === deferred ? undefined : this, arguments ); + return this; + }; + + // deferred.notifyWith = list.fireWith + // deferred.resolveWith = list.fireWith + // deferred.rejectWith = list.fireWith + deferred[ tuple[ 0 ] + "With" ] = list.fireWith; + } ); + + // Make the deferred a promise + promise.promise( deferred ); + + // Call given func if any + if ( func ) { + func.call( deferred, deferred ); + } + + // All done! + return deferred; + }, + + // Deferred helper + when: function( singleValue ) { + var + + // count of uncompleted subordinates + remaining = arguments.length, + + // count of unprocessed arguments + i = remaining, + + // subordinate fulfillment data + resolveContexts = Array( i ), + resolveValues = slice.call( arguments ), + + // the master Deferred + master = jQuery.Deferred(), + + // subordinate callback factory + updateFunc = function( i ) { + return function( value ) { + resolveContexts[ i ] = this; + resolveValues[ i ] = arguments.length > 1 ? slice.call( arguments ) : value; + if ( !( --remaining ) ) { + master.resolveWith( resolveContexts, resolveValues ); + } + }; + }; + + // Single- and empty arguments are adopted like Promise.resolve + if ( remaining <= 1 ) { + adoptValue( singleValue, master.done( updateFunc( i ) ).resolve, master.reject, + !remaining ); + + // Use .then() to unwrap secondary thenables (cf. gh-3000) + if ( master.state() === "pending" || + isFunction( resolveValues[ i ] && resolveValues[ i ].then ) ) { + + return master.then(); + } + } + + // Multiple arguments are aggregated like Promise.all array elements + while ( i-- ) { + adoptValue( resolveValues[ i ], updateFunc( i ), master.reject ); + } + + return master.promise(); + } +} ); + + +// These usually indicate a programmer mistake during development, +// warn about them ASAP rather than swallowing them by default. +var rerrorNames = /^(Eval|Internal|Range|Reference|Syntax|Type|URI)Error$/; + +jQuery.Deferred.exceptionHook = function( error, stack ) { + + // Support: IE 8 - 9 only + // Console exists when dev tools are open, which can happen at any time + if ( window.console && window.console.warn && error && rerrorNames.test( error.name ) ) { + window.console.warn( "jQuery.Deferred exception: " + error.message, error.stack, stack ); + } +}; + + + + +jQuery.readyException = function( error ) { + window.setTimeout( function() { + throw error; + } ); +}; + + + + +// The deferred used on DOM ready +var readyList = jQuery.Deferred(); + +jQuery.fn.ready = function( fn ) { + + readyList + .then( fn ) + + // Wrap jQuery.readyException in a function so that the lookup + // happens at the time of error handling instead of callback + // registration. + .catch( function( error ) { + jQuery.readyException( error ); + } ); + + return this; +}; + +jQuery.extend( { + + // Is the DOM ready to be used? Set to true once it occurs. + isReady: false, + + // A counter to track how many items to wait for before + // the ready event fires. See #6781 + readyWait: 1, + + // Handle when the DOM is ready + ready: function( wait ) { + + // Abort if there are pending holds or we're already ready + if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) { + return; + } + + // Remember that the DOM is ready + jQuery.isReady = true; + + // If a normal DOM Ready event fired, decrement, and wait if need be + if ( wait !== true && --jQuery.readyWait > 0 ) { + return; + } + + // If there are functions bound, to execute + readyList.resolveWith( document, [ jQuery ] ); + } +} ); + +jQuery.ready.then = readyList.then; + +// The ready event handler and self cleanup method +function completed() { + document.removeEventListener( "DOMContentLoaded", completed ); + window.removeEventListener( "load", completed ); + jQuery.ready(); +} + +// Catch cases where $(document).ready() is called +// after the browser event has already occurred. +// Support: IE <=9 - 10 only +// Older IE sometimes signals "interactive" too soon +if ( document.readyState === "complete" || + ( document.readyState !== "loading" && !document.documentElement.doScroll ) ) { + + // Handle it asynchronously to allow scripts the opportunity to delay ready + window.setTimeout( jQuery.ready ); + +} else { + + // Use the handy event callback + document.addEventListener( "DOMContentLoaded", completed ); + + // A fallback to window.onload, that will always work + window.addEventListener( "load", completed ); +} + + + + +// Multifunctional method to get and set values of a collection +// The value/s can optionally be executed if it's a function +var access = function( elems, fn, key, value, chainable, emptyGet, raw ) { + var i = 0, + len = elems.length, + bulk = key == null; + + // Sets many values + if ( toType( key ) === "object" ) { + chainable = true; + for ( i in key ) { + access( elems, fn, i, key[ i ], true, emptyGet, raw ); + } + + // Sets one value + } else if ( value !== undefined ) { + chainable = true; + + if ( !isFunction( value ) ) { + raw = true; + } + + if ( bulk ) { + + // Bulk operations run against the entire set + if ( raw ) { + fn.call( elems, value ); + fn = null; + + // ...except when executing function values + } else { + bulk = fn; + fn = function( elem, _key, value ) { + return bulk.call( jQuery( elem ), value ); + }; + } + } + + if ( fn ) { + for ( ; i < len; i++ ) { + fn( + elems[ i ], key, raw ? + value : + value.call( elems[ i ], i, fn( elems[ i ], key ) ) + ); + } + } + } + + if ( chainable ) { + return elems; + } + + // Gets + if ( bulk ) { + return fn.call( elems ); + } + + return len ? fn( elems[ 0 ], key ) : emptyGet; +}; + + +// Matches dashed string for camelizing +var rmsPrefix = /^-ms-/, + rdashAlpha = /-([a-z])/g; + +// Used by camelCase as callback to replace() +function fcamelCase( _all, letter ) { + return letter.toUpperCase(); +} + +// Convert dashed to camelCase; used by the css and data modules +// Support: IE <=9 - 11, Edge 12 - 15 +// Microsoft forgot to hump their vendor prefix (#9572) +function camelCase( string ) { + return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase ); +} +var acceptData = function( owner ) { + + // Accepts only: + // - Node + // - Node.ELEMENT_NODE + // - Node.DOCUMENT_NODE + // - Object + // - Any + return owner.nodeType === 1 || owner.nodeType === 9 || !( +owner.nodeType ); +}; + + + + +function Data() { + this.expando = jQuery.expando + Data.uid++; +} + +Data.uid = 1; + +Data.prototype = { + + cache: function( owner ) { + + // Check if the owner object already has a cache + var value = owner[ this.expando ]; + + // If not, create one + if ( !value ) { + value = {}; + + // We can accept data for non-element nodes in modern browsers, + // but we should not, see #8335. + // Always return an empty object. + if ( acceptData( owner ) ) { + + // If it is a node unlikely to be stringify-ed or looped over + // use plain assignment + if ( owner.nodeType ) { + owner[ this.expando ] = value; + + // Otherwise secure it in a non-enumerable property + // configurable must be true to allow the property to be + // deleted when data is removed + } else { + Object.defineProperty( owner, this.expando, { + value: value, + configurable: true + } ); + } + } + } + + return value; + }, + set: function( owner, data, value ) { + var prop, + cache = this.cache( owner ); + + // Handle: [ owner, key, value ] args + // Always use camelCase key (gh-2257) + if ( typeof data === "string" ) { + cache[ camelCase( data ) ] = value; + + // Handle: [ owner, { properties } ] args + } else { + + // Copy the properties one-by-one to the cache object + for ( prop in data ) { + cache[ camelCase( prop ) ] = data[ prop ]; + } + } + return cache; + }, + get: function( owner, key ) { + return key === undefined ? + this.cache( owner ) : + + // Always use camelCase key (gh-2257) + owner[ this.expando ] && owner[ this.expando ][ camelCase( key ) ]; + }, + access: function( owner, key, value ) { + + // In cases where either: + // + // 1. No key was specified + // 2. A string key was specified, but no value provided + // + // Take the "read" path and allow the get method to determine + // which value to return, respectively either: + // + // 1. The entire cache object + // 2. The data stored at the key + // + if ( key === undefined || + ( ( key && typeof key === "string" ) && value === undefined ) ) { + + return this.get( owner, key ); + } + + // When the key is not a string, or both a key and value + // are specified, set or extend (existing objects) with either: + // + // 1. An object of properties + // 2. A key and value + // + this.set( owner, key, value ); + + // Since the "set" path can have two possible entry points + // return the expected data based on which path was taken[*] + return value !== undefined ? value : key; + }, + remove: function( owner, key ) { + var i, + cache = owner[ this.expando ]; + + if ( cache === undefined ) { + return; + } + + if ( key !== undefined ) { + + // Support array or space separated string of keys + if ( Array.isArray( key ) ) { + + // If key is an array of keys... + // We always set camelCase keys, so remove that. + key = key.map( camelCase ); + } else { + key = camelCase( key ); + + // If a key with the spaces exists, use it. + // Otherwise, create an array by matching non-whitespace + key = key in cache ? + [ key ] : + ( key.match( rnothtmlwhite ) || [] ); + } + + i = key.length; + + while ( i-- ) { + delete cache[ key[ i ] ]; + } + } + + // Remove the expando if there's no more data + if ( key === undefined || jQuery.isEmptyObject( cache ) ) { + + // Support: Chrome <=35 - 45 + // Webkit & Blink performance suffers when deleting properties + // from DOM nodes, so set to undefined instead + // https://bugs.chromium.org/p/chromium/issues/detail?id=378607 (bug restricted) + if ( owner.nodeType ) { + owner[ this.expando ] = undefined; + } else { + delete owner[ this.expando ]; + } + } + }, + hasData: function( owner ) { + var cache = owner[ this.expando ]; + return cache !== undefined && !jQuery.isEmptyObject( cache ); + } +}; +var dataPriv = new Data(); + +var dataUser = new Data(); + + + +// Implementation Summary +// +// 1. Enforce API surface and semantic compatibility with 1.9.x branch +// 2. Improve the module's maintainability by reducing the storage +// paths to a single mechanism. +// 3. Use the same single mechanism to support "private" and "user" data. +// 4. _Never_ expose "private" data to user code (TODO: Drop _data, _removeData) +// 5. Avoid exposing implementation details on user objects (eg. expando properties) +// 6. Provide a clear path for implementation upgrade to WeakMap in 2014 + +var rbrace = /^(?:\{[\w\W]*\}|\[[\w\W]*\])$/, + rmultiDash = /[A-Z]/g; + +function getData( data ) { + if ( data === "true" ) { + return true; + } + + if ( data === "false" ) { + return false; + } + + if ( data === "null" ) { + return null; + } + + // Only convert to a number if it doesn't change the string + if ( data === +data + "" ) { + return +data; + } + + if ( rbrace.test( data ) ) { + return JSON.parse( data ); + } + + return data; +} + +function dataAttr( elem, key, data ) { + var name; + + // If nothing was found internally, try to fetch any + // data from the HTML5 data-* attribute + if ( data === undefined && elem.nodeType === 1 ) { + name = "data-" + key.replace( rmultiDash, "-$&" ).toLowerCase(); + data = elem.getAttribute( name ); + + if ( typeof data === "string" ) { + try { + data = getData( data ); + } catch ( e ) {} + + // Make sure we set the data so it isn't changed later + dataUser.set( elem, key, data ); + } else { + data = undefined; + } + } + return data; +} + +jQuery.extend( { + hasData: function( elem ) { + return dataUser.hasData( elem ) || dataPriv.hasData( elem ); + }, + + data: function( elem, name, data ) { + return dataUser.access( elem, name, data ); + }, + + removeData: function( elem, name ) { + dataUser.remove( elem, name ); + }, + + // TODO: Now that all calls to _data and _removeData have been replaced + // with direct calls to dataPriv methods, these can be deprecated. + _data: function( elem, name, data ) { + return dataPriv.access( elem, name, data ); + }, + + _removeData: function( elem, name ) { + dataPriv.remove( elem, name ); + } +} ); + +jQuery.fn.extend( { + data: function( key, value ) { + var i, name, data, + elem = this[ 0 ], + attrs = elem && elem.attributes; + + // Gets all values + if ( key === undefined ) { + if ( this.length ) { + data = dataUser.get( elem ); + + if ( elem.nodeType === 1 && !dataPriv.get( elem, "hasDataAttrs" ) ) { + i = attrs.length; + while ( i-- ) { + + // Support: IE 11 only + // The attrs elements can be null (#14894) + if ( attrs[ i ] ) { + name = attrs[ i ].name; + if ( name.indexOf( "data-" ) === 0 ) { + name = camelCase( name.slice( 5 ) ); + dataAttr( elem, name, data[ name ] ); + } + } + } + dataPriv.set( elem, "hasDataAttrs", true ); + } + } + + return data; + } + + // Sets multiple values + if ( typeof key === "object" ) { + return this.each( function() { + dataUser.set( this, key ); + } ); + } + + return access( this, function( value ) { + var data; + + // The calling jQuery object (element matches) is not empty + // (and therefore has an element appears at this[ 0 ]) and the + // `value` parameter was not undefined. An empty jQuery object + // will result in `undefined` for elem = this[ 0 ] which will + // throw an exception if an attempt to read a data cache is made. + if ( elem && value === undefined ) { + + // Attempt to get data from the cache + // The key will always be camelCased in Data + data = dataUser.get( elem, key ); + if ( data !== undefined ) { + return data; + } + + // Attempt to "discover" the data in + // HTML5 custom data-* attrs + data = dataAttr( elem, key ); + if ( data !== undefined ) { + return data; + } + + // We tried really hard, but the data doesn't exist. + return; + } + + // Set the data... + this.each( function() { + + // We always store the camelCased key + dataUser.set( this, key, value ); + } ); + }, null, value, arguments.length > 1, null, true ); + }, + + removeData: function( key ) { + return this.each( function() { + dataUser.remove( this, key ); + } ); + } +} ); + + +jQuery.extend( { + queue: function( elem, type, data ) { + var queue; + + if ( elem ) { + type = ( type || "fx" ) + "queue"; + queue = dataPriv.get( elem, type ); + + // Speed up dequeue by getting out quickly if this is just a lookup + if ( data ) { + if ( !queue || Array.isArray( data ) ) { + queue = dataPriv.access( elem, type, jQuery.makeArray( data ) ); + } else { + queue.push( data ); + } + } + return queue || []; + } + }, + + dequeue: function( elem, type ) { + type = type || "fx"; + + var queue = jQuery.queue( elem, type ), + startLength = queue.length, + fn = queue.shift(), + hooks = jQuery._queueHooks( elem, type ), + next = function() { + jQuery.dequeue( elem, type ); + }; + + // If the fx queue is dequeued, always remove the progress sentinel + if ( fn === "inprogress" ) { + fn = queue.shift(); + startLength--; + } + + if ( fn ) { + + // Add a progress sentinel to prevent the fx queue from being + // automatically dequeued + if ( type === "fx" ) { + queue.unshift( "inprogress" ); + } + + // Clear up the last queue stop function + delete hooks.stop; + fn.call( elem, next, hooks ); + } + + if ( !startLength && hooks ) { + hooks.empty.fire(); + } + }, + + // Not public - generate a queueHooks object, or return the current one + _queueHooks: function( elem, type ) { + var key = type + "queueHooks"; + return dataPriv.get( elem, key ) || dataPriv.access( elem, key, { + empty: jQuery.Callbacks( "once memory" ).add( function() { + dataPriv.remove( elem, [ type + "queue", key ] ); + } ) + } ); + } +} ); + +jQuery.fn.extend( { + queue: function( type, data ) { + var setter = 2; + + if ( typeof type !== "string" ) { + data = type; + type = "fx"; + setter--; + } + + if ( arguments.length < setter ) { + return jQuery.queue( this[ 0 ], type ); + } + + return data === undefined ? + this : + this.each( function() { + var queue = jQuery.queue( this, type, data ); + + // Ensure a hooks for this queue + jQuery._queueHooks( this, type ); + + if ( type === "fx" && queue[ 0 ] !== "inprogress" ) { + jQuery.dequeue( this, type ); + } + } ); + }, + dequeue: function( type ) { + return this.each( function() { + jQuery.dequeue( this, type ); + } ); + }, + clearQueue: function( type ) { + return this.queue( type || "fx", [] ); + }, + + // Get a promise resolved when queues of a certain type + // are emptied (fx is the type by default) + promise: function( type, obj ) { + var tmp, + count = 1, + defer = jQuery.Deferred(), + elements = this, + i = this.length, + resolve = function() { + if ( !( --count ) ) { + defer.resolveWith( elements, [ elements ] ); + } + }; + + if ( typeof type !== "string" ) { + obj = type; + type = undefined; + } + type = type || "fx"; + + while ( i-- ) { + tmp = dataPriv.get( elements[ i ], type + "queueHooks" ); + if ( tmp && tmp.empty ) { + count++; + tmp.empty.add( resolve ); + } + } + resolve(); + return defer.promise( obj ); + } +} ); +var pnum = ( /[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/ ).source; + +var rcssNum = new RegExp( "^(?:([+-])=|)(" + pnum + ")([a-z%]*)$", "i" ); + + +var cssExpand = [ "Top", "Right", "Bottom", "Left" ]; + +var documentElement = document.documentElement; + + + + var isAttached = function( elem ) { + return jQuery.contains( elem.ownerDocument, elem ); + }, + composed = { composed: true }; + + // Support: IE 9 - 11+, Edge 12 - 18+, iOS 10.0 - 10.2 only + // Check attachment across shadow DOM boundaries when possible (gh-3504) + // Support: iOS 10.0-10.2 only + // Early iOS 10 versions support `attachShadow` but not `getRootNode`, + // leading to errors. We need to check for `getRootNode`. + if ( documentElement.getRootNode ) { + isAttached = function( elem ) { + return jQuery.contains( elem.ownerDocument, elem ) || + elem.getRootNode( composed ) === elem.ownerDocument; + }; + } +var isHiddenWithinTree = function( elem, el ) { + + // isHiddenWithinTree might be called from jQuery#filter function; + // in that case, element will be second argument + elem = el || elem; + + // Inline style trumps all + return elem.style.display === "none" || + elem.style.display === "" && + + // Otherwise, check computed style + // Support: Firefox <=43 - 45 + // Disconnected elements can have computed display: none, so first confirm that elem is + // in the document. + isAttached( elem ) && + + jQuery.css( elem, "display" ) === "none"; + }; + + + +function adjustCSS( elem, prop, valueParts, tween ) { + var adjusted, scale, + maxIterations = 20, + currentValue = tween ? + function() { + return tween.cur(); + } : + function() { + return jQuery.css( elem, prop, "" ); + }, + initial = currentValue(), + unit = valueParts && valueParts[ 3 ] || ( jQuery.cssNumber[ prop ] ? "" : "px" ), + + // Starting value computation is required for potential unit mismatches + initialInUnit = elem.nodeType && + ( jQuery.cssNumber[ prop ] || unit !== "px" && +initial ) && + rcssNum.exec( jQuery.css( elem, prop ) ); + + if ( initialInUnit && initialInUnit[ 3 ] !== unit ) { + + // Support: Firefox <=54 + // Halve the iteration target value to prevent interference from CSS upper bounds (gh-2144) + initial = initial / 2; + + // Trust units reported by jQuery.css + unit = unit || initialInUnit[ 3 ]; + + // Iteratively approximate from a nonzero starting point + initialInUnit = +initial || 1; + + while ( maxIterations-- ) { + + // Evaluate and update our best guess (doubling guesses that zero out). + // Finish if the scale equals or crosses 1 (making the old*new product non-positive). + jQuery.style( elem, prop, initialInUnit + unit ); + if ( ( 1 - scale ) * ( 1 - ( scale = currentValue() / initial || 0.5 ) ) <= 0 ) { + maxIterations = 0; + } + initialInUnit = initialInUnit / scale; + + } + + initialInUnit = initialInUnit * 2; + jQuery.style( elem, prop, initialInUnit + unit ); + + // Make sure we update the tween properties later on + valueParts = valueParts || []; + } + + if ( valueParts ) { + initialInUnit = +initialInUnit || +initial || 0; + + // Apply relative offset (+=/-=) if specified + adjusted = valueParts[ 1 ] ? + initialInUnit + ( valueParts[ 1 ] + 1 ) * valueParts[ 2 ] : + +valueParts[ 2 ]; + if ( tween ) { + tween.unit = unit; + tween.start = initialInUnit; + tween.end = adjusted; + } + } + return adjusted; +} + + +var defaultDisplayMap = {}; + +function getDefaultDisplay( elem ) { + var temp, + doc = elem.ownerDocument, + nodeName = elem.nodeName, + display = defaultDisplayMap[ nodeName ]; + + if ( display ) { + return display; + } + + temp = doc.body.appendChild( doc.createElement( nodeName ) ); + display = jQuery.css( temp, "display" ); + + temp.parentNode.removeChild( temp ); + + if ( display === "none" ) { + display = "block"; + } + defaultDisplayMap[ nodeName ] = display; + + return display; +} + +function showHide( elements, show ) { + var display, elem, + values = [], + index = 0, + length = elements.length; + + // Determine new display value for elements that need to change + for ( ; index < length; index++ ) { + elem = elements[ index ]; + if ( !elem.style ) { + continue; + } + + display = elem.style.display; + if ( show ) { + + // Since we force visibility upon cascade-hidden elements, an immediate (and slow) + // check is required in this first loop unless we have a nonempty display value (either + // inline or about-to-be-restored) + if ( display === "none" ) { + values[ index ] = dataPriv.get( elem, "display" ) || null; + if ( !values[ index ] ) { + elem.style.display = ""; + } + } + if ( elem.style.display === "" && isHiddenWithinTree( elem ) ) { + values[ index ] = getDefaultDisplay( elem ); + } + } else { + if ( display !== "none" ) { + values[ index ] = "none"; + + // Remember what we're overwriting + dataPriv.set( elem, "display", display ); + } + } + } + + // Set the display of the elements in a second loop to avoid constant reflow + for ( index = 0; index < length; index++ ) { + if ( values[ index ] != null ) { + elements[ index ].style.display = values[ index ]; + } + } + + return elements; +} + +jQuery.fn.extend( { + show: function() { + return showHide( this, true ); + }, + hide: function() { + return showHide( this ); + }, + toggle: function( state ) { + if ( typeof state === "boolean" ) { + return state ? this.show() : this.hide(); + } + + return this.each( function() { + if ( isHiddenWithinTree( this ) ) { + jQuery( this ).show(); + } else { + jQuery( this ).hide(); + } + } ); + } +} ); +var rcheckableType = ( /^(?:checkbox|radio)$/i ); + +var rtagName = ( /<([a-z][^\/\0>\x20\t\r\n\f]*)/i ); + +var rscriptType = ( /^$|^module$|\/(?:java|ecma)script/i ); + + + +( function() { + var fragment = document.createDocumentFragment(), + div = fragment.appendChild( document.createElement( "div" ) ), + input = document.createElement( "input" ); + + // Support: Android 4.0 - 4.3 only + // Check state lost if the name is set (#11217) + // Support: Windows Web Apps (WWA) + // `name` and `type` must use .setAttribute for WWA (#14901) + input.setAttribute( "type", "radio" ); + input.setAttribute( "checked", "checked" ); + input.setAttribute( "name", "t" ); + + div.appendChild( input ); + + // Support: Android <=4.1 only + // Older WebKit doesn't clone checked state correctly in fragments + support.checkClone = div.cloneNode( true ).cloneNode( true ).lastChild.checked; + + // Support: IE <=11 only + // Make sure textarea (and checkbox) defaultValue is properly cloned + div.innerHTML = ""; + support.noCloneChecked = !!div.cloneNode( true ).lastChild.defaultValue; + + // Support: IE <=9 only + // IE <=9 replaces "; + support.option = !!div.lastChild; +} )(); + + +// We have to close these tags to support XHTML (#13200) +var wrapMap = { + + // XHTML parsers do not magically insert elements in the + // same way that tag soup parsers do. So we cannot shorten + // this by omitting or other required elements. + thead: [ 1, "", "
" ], + col: [ 2, "", "
" ], + tr: [ 2, "", "
" ], + td: [ 3, "", "
" ], + + _default: [ 0, "", "" ] +}; + +wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; +wrapMap.th = wrapMap.td; + +// Support: IE <=9 only +if ( !support.option ) { + wrapMap.optgroup = wrapMap.option = [ 1, "" ]; +} + + +function getAll( context, tag ) { + + // Support: IE <=9 - 11 only + // Use typeof to avoid zero-argument method invocation on host objects (#15151) + var ret; + + if ( typeof context.getElementsByTagName !== "undefined" ) { + ret = context.getElementsByTagName( tag || "*" ); + + } else if ( typeof context.querySelectorAll !== "undefined" ) { + ret = context.querySelectorAll( tag || "*" ); + + } else { + ret = []; + } + + if ( tag === undefined || tag && nodeName( context, tag ) ) { + return jQuery.merge( [ context ], ret ); + } + + return ret; +} + + +// Mark scripts as having already been evaluated +function setGlobalEval( elems, refElements ) { + var i = 0, + l = elems.length; + + for ( ; i < l; i++ ) { + dataPriv.set( + elems[ i ], + "globalEval", + !refElements || dataPriv.get( refElements[ i ], "globalEval" ) + ); + } +} + + +var rhtml = /<|&#?\w+;/; + +function buildFragment( elems, context, scripts, selection, ignored ) { + var elem, tmp, tag, wrap, attached, j, + fragment = context.createDocumentFragment(), + nodes = [], + i = 0, + l = elems.length; + + for ( ; i < l; i++ ) { + elem = elems[ i ]; + + if ( elem || elem === 0 ) { + + // Add nodes directly + if ( toType( elem ) === "object" ) { + + // Support: Android <=4.0 only, PhantomJS 1 only + // push.apply(_, arraylike) throws on ancient WebKit + jQuery.merge( nodes, elem.nodeType ? [ elem ] : elem ); + + // Convert non-html into a text node + } else if ( !rhtml.test( elem ) ) { + nodes.push( context.createTextNode( elem ) ); + + // Convert html into DOM nodes + } else { + tmp = tmp || fragment.appendChild( context.createElement( "div" ) ); + + // Deserialize a standard representation + tag = ( rtagName.exec( elem ) || [ "", "" ] )[ 1 ].toLowerCase(); + wrap = wrapMap[ tag ] || wrapMap._default; + tmp.innerHTML = wrap[ 1 ] + jQuery.htmlPrefilter( elem ) + wrap[ 2 ]; + + // Descend through wrappers to the right content + j = wrap[ 0 ]; + while ( j-- ) { + tmp = tmp.lastChild; + } + + // Support: Android <=4.0 only, PhantomJS 1 only + // push.apply(_, arraylike) throws on ancient WebKit + jQuery.merge( nodes, tmp.childNodes ); + + // Remember the top-level container + tmp = fragment.firstChild; + + // Ensure the created nodes are orphaned (#12392) + tmp.textContent = ""; + } + } + } + + // Remove wrapper from fragment + fragment.textContent = ""; + + i = 0; + while ( ( elem = nodes[ i++ ] ) ) { + + // Skip elements already in the context collection (trac-4087) + if ( selection && jQuery.inArray( elem, selection ) > -1 ) { + if ( ignored ) { + ignored.push( elem ); + } + continue; + } + + attached = isAttached( elem ); + + // Append to fragment + tmp = getAll( fragment.appendChild( elem ), "script" ); + + // Preserve script evaluation history + if ( attached ) { + setGlobalEval( tmp ); + } + + // Capture executables + if ( scripts ) { + j = 0; + while ( ( elem = tmp[ j++ ] ) ) { + if ( rscriptType.test( elem.type || "" ) ) { + scripts.push( elem ); + } + } + } + } + + return fragment; +} + + +var + rkeyEvent = /^key/, + rmouseEvent = /^(?:mouse|pointer|contextmenu|drag|drop)|click/, + rtypenamespace = /^([^.]*)(?:\.(.+)|)/; + +function returnTrue() { + return true; +} + +function returnFalse() { + return false; +} + +// Support: IE <=9 - 11+ +// focus() and blur() are asynchronous, except when they are no-op. +// So expect focus to be synchronous when the element is already active, +// and blur to be synchronous when the element is not already active. +// (focus and blur are always synchronous in other supported browsers, +// this just defines when we can count on it). +function expectSync( elem, type ) { + return ( elem === safeActiveElement() ) === ( type === "focus" ); +} + +// Support: IE <=9 only +// Accessing document.activeElement can throw unexpectedly +// https://bugs.jquery.com/ticket/13393 +function safeActiveElement() { + try { + return document.activeElement; + } catch ( err ) { } +} + +function on( elem, types, selector, data, fn, one ) { + var origFn, type; + + // Types can be a map of types/handlers + if ( typeof types === "object" ) { + + // ( types-Object, selector, data ) + if ( typeof selector !== "string" ) { + + // ( types-Object, data ) + data = data || selector; + selector = undefined; + } + for ( type in types ) { + on( elem, type, selector, data, types[ type ], one ); + } + return elem; + } + + if ( data == null && fn == null ) { + + // ( types, fn ) + fn = selector; + data = selector = undefined; + } else if ( fn == null ) { + if ( typeof selector === "string" ) { + + // ( types, selector, fn ) + fn = data; + data = undefined; + } else { + + // ( types, data, fn ) + fn = data; + data = selector; + selector = undefined; + } + } + if ( fn === false ) { + fn = returnFalse; + } else if ( !fn ) { + return elem; + } + + if ( one === 1 ) { + origFn = fn; + fn = function( event ) { + + // Can use an empty set, since event contains the info + jQuery().off( event ); + return origFn.apply( this, arguments ); + }; + + // Use same guid so caller can remove using origFn + fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ ); + } + return elem.each( function() { + jQuery.event.add( this, types, fn, data, selector ); + } ); +} + +/* + * Helper functions for managing events -- not part of the public interface. + * Props to Dean Edwards' addEvent library for many of the ideas. + */ +jQuery.event = { + + global: {}, + + add: function( elem, types, handler, data, selector ) { + + var handleObjIn, eventHandle, tmp, + events, t, handleObj, + special, handlers, type, namespaces, origType, + elemData = dataPriv.get( elem ); + + // Only attach events to objects that accept data + if ( !acceptData( elem ) ) { + return; + } + + // Caller can pass in an object of custom data in lieu of the handler + if ( handler.handler ) { + handleObjIn = handler; + handler = handleObjIn.handler; + selector = handleObjIn.selector; + } + + // Ensure that invalid selectors throw exceptions at attach time + // Evaluate against documentElement in case elem is a non-element node (e.g., document) + if ( selector ) { + jQuery.find.matchesSelector( documentElement, selector ); + } + + // Make sure that the handler has a unique ID, used to find/remove it later + if ( !handler.guid ) { + handler.guid = jQuery.guid++; + } + + // Init the element's event structure and main handler, if this is the first + if ( !( events = elemData.events ) ) { + events = elemData.events = Object.create( null ); + } + if ( !( eventHandle = elemData.handle ) ) { + eventHandle = elemData.handle = function( e ) { + + // Discard the second event of a jQuery.event.trigger() and + // when an event is called after a page has unloaded + return typeof jQuery !== "undefined" && jQuery.event.triggered !== e.type ? + jQuery.event.dispatch.apply( elem, arguments ) : undefined; + }; + } + + // Handle multiple events separated by a space + types = ( types || "" ).match( rnothtmlwhite ) || [ "" ]; + t = types.length; + while ( t-- ) { + tmp = rtypenamespace.exec( types[ t ] ) || []; + type = origType = tmp[ 1 ]; + namespaces = ( tmp[ 2 ] || "" ).split( "." ).sort(); + + // There *must* be a type, no attaching namespace-only handlers + if ( !type ) { + continue; + } + + // If event changes its type, use the special event handlers for the changed type + special = jQuery.event.special[ type ] || {}; + + // If selector defined, determine special event api type, otherwise given type + type = ( selector ? special.delegateType : special.bindType ) || type; + + // Update special based on newly reset type + special = jQuery.event.special[ type ] || {}; + + // handleObj is passed to all event handlers + handleObj = jQuery.extend( { + type: type, + origType: origType, + data: data, + handler: handler, + guid: handler.guid, + selector: selector, + needsContext: selector && jQuery.expr.match.needsContext.test( selector ), + namespace: namespaces.join( "." ) + }, handleObjIn ); + + // Init the event handler queue if we're the first + if ( !( handlers = events[ type ] ) ) { + handlers = events[ type ] = []; + handlers.delegateCount = 0; + + // Only use addEventListener if the special events handler returns false + if ( !special.setup || + special.setup.call( elem, data, namespaces, eventHandle ) === false ) { + + if ( elem.addEventListener ) { + elem.addEventListener( type, eventHandle ); + } + } + } + + if ( special.add ) { + special.add.call( elem, handleObj ); + + if ( !handleObj.handler.guid ) { + handleObj.handler.guid = handler.guid; + } + } + + // Add to the element's handler list, delegates in front + if ( selector ) { + handlers.splice( handlers.delegateCount++, 0, handleObj ); + } else { + handlers.push( handleObj ); + } + + // Keep track of which events have ever been used, for event optimization + jQuery.event.global[ type ] = true; + } + + }, + + // Detach an event or set of events from an element + remove: function( elem, types, handler, selector, mappedTypes ) { + + var j, origCount, tmp, + events, t, handleObj, + special, handlers, type, namespaces, origType, + elemData = dataPriv.hasData( elem ) && dataPriv.get( elem ); + + if ( !elemData || !( events = elemData.events ) ) { + return; + } + + // Once for each type.namespace in types; type may be omitted + types = ( types || "" ).match( rnothtmlwhite ) || [ "" ]; + t = types.length; + while ( t-- ) { + tmp = rtypenamespace.exec( types[ t ] ) || []; + type = origType = tmp[ 1 ]; + namespaces = ( tmp[ 2 ] || "" ).split( "." ).sort(); + + // Unbind all events (on this namespace, if provided) for the element + if ( !type ) { + for ( type in events ) { + jQuery.event.remove( elem, type + types[ t ], handler, selector, true ); + } + continue; + } + + special = jQuery.event.special[ type ] || {}; + type = ( selector ? special.delegateType : special.bindType ) || type; + handlers = events[ type ] || []; + tmp = tmp[ 2 ] && + new RegExp( "(^|\\.)" + namespaces.join( "\\.(?:.*\\.|)" ) + "(\\.|$)" ); + + // Remove matching events + origCount = j = handlers.length; + while ( j-- ) { + handleObj = handlers[ j ]; + + if ( ( mappedTypes || origType === handleObj.origType ) && + ( !handler || handler.guid === handleObj.guid ) && + ( !tmp || tmp.test( handleObj.namespace ) ) && + ( !selector || selector === handleObj.selector || + selector === "**" && handleObj.selector ) ) { + handlers.splice( j, 1 ); + + if ( handleObj.selector ) { + handlers.delegateCount--; + } + if ( special.remove ) { + special.remove.call( elem, handleObj ); + } + } + } + + // Remove generic event handler if we removed something and no more handlers exist + // (avoids potential for endless recursion during removal of special event handlers) + if ( origCount && !handlers.length ) { + if ( !special.teardown || + special.teardown.call( elem, namespaces, elemData.handle ) === false ) { + + jQuery.removeEvent( elem, type, elemData.handle ); + } + + delete events[ type ]; + } + } + + // Remove data and the expando if it's no longer used + if ( jQuery.isEmptyObject( events ) ) { + dataPriv.remove( elem, "handle events" ); + } + }, + + dispatch: function( nativeEvent ) { + + var i, j, ret, matched, handleObj, handlerQueue, + args = new Array( arguments.length ), + + // Make a writable jQuery.Event from the native event object + event = jQuery.event.fix( nativeEvent ), + + handlers = ( + dataPriv.get( this, "events" ) || Object.create( null ) + )[ event.type ] || [], + special = jQuery.event.special[ event.type ] || {}; + + // Use the fix-ed jQuery.Event rather than the (read-only) native event + args[ 0 ] = event; + + for ( i = 1; i < arguments.length; i++ ) { + args[ i ] = arguments[ i ]; + } + + event.delegateTarget = this; + + // Call the preDispatch hook for the mapped type, and let it bail if desired + if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) { + return; + } + + // Determine handlers + handlerQueue = jQuery.event.handlers.call( this, event, handlers ); + + // Run delegates first; they may want to stop propagation beneath us + i = 0; + while ( ( matched = handlerQueue[ i++ ] ) && !event.isPropagationStopped() ) { + event.currentTarget = matched.elem; + + j = 0; + while ( ( handleObj = matched.handlers[ j++ ] ) && + !event.isImmediatePropagationStopped() ) { + + // If the event is namespaced, then each handler is only invoked if it is + // specially universal or its namespaces are a superset of the event's. + if ( !event.rnamespace || handleObj.namespace === false || + event.rnamespace.test( handleObj.namespace ) ) { + + event.handleObj = handleObj; + event.data = handleObj.data; + + ret = ( ( jQuery.event.special[ handleObj.origType ] || {} ).handle || + handleObj.handler ).apply( matched.elem, args ); + + if ( ret !== undefined ) { + if ( ( event.result = ret ) === false ) { + event.preventDefault(); + event.stopPropagation(); + } + } + } + } + } + + // Call the postDispatch hook for the mapped type + if ( special.postDispatch ) { + special.postDispatch.call( this, event ); + } + + return event.result; + }, + + handlers: function( event, handlers ) { + var i, handleObj, sel, matchedHandlers, matchedSelectors, + handlerQueue = [], + delegateCount = handlers.delegateCount, + cur = event.target; + + // Find delegate handlers + if ( delegateCount && + + // Support: IE <=9 + // Black-hole SVG instance trees (trac-13180) + cur.nodeType && + + // Support: Firefox <=42 + // Suppress spec-violating clicks indicating a non-primary pointer button (trac-3861) + // https://www.w3.org/TR/DOM-Level-3-Events/#event-type-click + // Support: IE 11 only + // ...but not arrow key "clicks" of radio inputs, which can have `button` -1 (gh-2343) + !( event.type === "click" && event.button >= 1 ) ) { + + for ( ; cur !== this; cur = cur.parentNode || this ) { + + // Don't check non-elements (#13208) + // Don't process clicks on disabled elements (#6911, #8165, #11382, #11764) + if ( cur.nodeType === 1 && !( event.type === "click" && cur.disabled === true ) ) { + matchedHandlers = []; + matchedSelectors = {}; + for ( i = 0; i < delegateCount; i++ ) { + handleObj = handlers[ i ]; + + // Don't conflict with Object.prototype properties (#13203) + sel = handleObj.selector + " "; + + if ( matchedSelectors[ sel ] === undefined ) { + matchedSelectors[ sel ] = handleObj.needsContext ? + jQuery( sel, this ).index( cur ) > -1 : + jQuery.find( sel, this, null, [ cur ] ).length; + } + if ( matchedSelectors[ sel ] ) { + matchedHandlers.push( handleObj ); + } + } + if ( matchedHandlers.length ) { + handlerQueue.push( { elem: cur, handlers: matchedHandlers } ); + } + } + } + } + + // Add the remaining (directly-bound) handlers + cur = this; + if ( delegateCount < handlers.length ) { + handlerQueue.push( { elem: cur, handlers: handlers.slice( delegateCount ) } ); + } + + return handlerQueue; + }, + + addProp: function( name, hook ) { + Object.defineProperty( jQuery.Event.prototype, name, { + enumerable: true, + configurable: true, + + get: isFunction( hook ) ? + function() { + if ( this.originalEvent ) { + return hook( this.originalEvent ); + } + } : + function() { + if ( this.originalEvent ) { + return this.originalEvent[ name ]; + } + }, + + set: function( value ) { + Object.defineProperty( this, name, { + enumerable: true, + configurable: true, + writable: true, + value: value + } ); + } + } ); + }, + + fix: function( originalEvent ) { + return originalEvent[ jQuery.expando ] ? + originalEvent : + new jQuery.Event( originalEvent ); + }, + + special: { + load: { + + // Prevent triggered image.load events from bubbling to window.load + noBubble: true + }, + click: { + + // Utilize native event to ensure correct state for checkable inputs + setup: function( data ) { + + // For mutual compressibility with _default, replace `this` access with a local var. + // `|| data` is dead code meant only to preserve the variable through minification. + var el = this || data; + + // Claim the first handler + if ( rcheckableType.test( el.type ) && + el.click && nodeName( el, "input" ) ) { + + // dataPriv.set( el, "click", ... ) + leverageNative( el, "click", returnTrue ); + } + + // Return false to allow normal processing in the caller + return false; + }, + trigger: function( data ) { + + // For mutual compressibility with _default, replace `this` access with a local var. + // `|| data` is dead code meant only to preserve the variable through minification. + var el = this || data; + + // Force setup before triggering a click + if ( rcheckableType.test( el.type ) && + el.click && nodeName( el, "input" ) ) { + + leverageNative( el, "click" ); + } + + // Return non-false to allow normal event-path propagation + return true; + }, + + // For cross-browser consistency, suppress native .click() on links + // Also prevent it if we're currently inside a leveraged native-event stack + _default: function( event ) { + var target = event.target; + return rcheckableType.test( target.type ) && + target.click && nodeName( target, "input" ) && + dataPriv.get( target, "click" ) || + nodeName( target, "a" ); + } + }, + + beforeunload: { + postDispatch: function( event ) { + + // Support: Firefox 20+ + // Firefox doesn't alert if the returnValue field is not set. + if ( event.result !== undefined && event.originalEvent ) { + event.originalEvent.returnValue = event.result; + } + } + } + } +}; + +// Ensure the presence of an event listener that handles manually-triggered +// synthetic events by interrupting progress until reinvoked in response to +// *native* events that it fires directly, ensuring that state changes have +// already occurred before other listeners are invoked. +function leverageNative( el, type, expectSync ) { + + // Missing expectSync indicates a trigger call, which must force setup through jQuery.event.add + if ( !expectSync ) { + if ( dataPriv.get( el, type ) === undefined ) { + jQuery.event.add( el, type, returnTrue ); + } + return; + } + + // Register the controller as a special universal handler for all event namespaces + dataPriv.set( el, type, false ); + jQuery.event.add( el, type, { + namespace: false, + handler: function( event ) { + var notAsync, result, + saved = dataPriv.get( this, type ); + + if ( ( event.isTrigger & 1 ) && this[ type ] ) { + + // Interrupt processing of the outer synthetic .trigger()ed event + // Saved data should be false in such cases, but might be a leftover capture object + // from an async native handler (gh-4350) + if ( !saved.length ) { + + // Store arguments for use when handling the inner native event + // There will always be at least one argument (an event object), so this array + // will not be confused with a leftover capture object. + saved = slice.call( arguments ); + dataPriv.set( this, type, saved ); + + // Trigger the native event and capture its result + // Support: IE <=9 - 11+ + // focus() and blur() are asynchronous + notAsync = expectSync( this, type ); + this[ type ](); + result = dataPriv.get( this, type ); + if ( saved !== result || notAsync ) { + dataPriv.set( this, type, false ); + } else { + result = {}; + } + if ( saved !== result ) { + + // Cancel the outer synthetic event + event.stopImmediatePropagation(); + event.preventDefault(); + return result.value; + } + + // If this is an inner synthetic event for an event with a bubbling surrogate + // (focus or blur), assume that the surrogate already propagated from triggering the + // native event and prevent that from happening again here. + // This technically gets the ordering wrong w.r.t. to `.trigger()` (in which the + // bubbling surrogate propagates *after* the non-bubbling base), but that seems + // less bad than duplication. + } else if ( ( jQuery.event.special[ type ] || {} ).delegateType ) { + event.stopPropagation(); + } + + // If this is a native event triggered above, everything is now in order + // Fire an inner synthetic event with the original arguments + } else if ( saved.length ) { + + // ...and capture the result + dataPriv.set( this, type, { + value: jQuery.event.trigger( + + // Support: IE <=9 - 11+ + // Extend with the prototype to reset the above stopImmediatePropagation() + jQuery.extend( saved[ 0 ], jQuery.Event.prototype ), + saved.slice( 1 ), + this + ) + } ); + + // Abort handling of the native event + event.stopImmediatePropagation(); + } + } + } ); +} + +jQuery.removeEvent = function( elem, type, handle ) { + + // This "if" is needed for plain objects + if ( elem.removeEventListener ) { + elem.removeEventListener( type, handle ); + } +}; + +jQuery.Event = function( src, props ) { + + // Allow instantiation without the 'new' keyword + if ( !( this instanceof jQuery.Event ) ) { + return new jQuery.Event( src, props ); + } + + // Event object + if ( src && src.type ) { + this.originalEvent = src; + this.type = src.type; + + // Events bubbling up the document may have been marked as prevented + // by a handler lower down the tree; reflect the correct value. + this.isDefaultPrevented = src.defaultPrevented || + src.defaultPrevented === undefined && + + // Support: Android <=2.3 only + src.returnValue === false ? + returnTrue : + returnFalse; + + // Create target properties + // Support: Safari <=6 - 7 only + // Target should not be a text node (#504, #13143) + this.target = ( src.target && src.target.nodeType === 3 ) ? + src.target.parentNode : + src.target; + + this.currentTarget = src.currentTarget; + this.relatedTarget = src.relatedTarget; + + // Event type + } else { + this.type = src; + } + + // Put explicitly provided properties onto the event object + if ( props ) { + jQuery.extend( this, props ); + } + + // Create a timestamp if incoming event doesn't have one + this.timeStamp = src && src.timeStamp || Date.now(); + + // Mark it as fixed + this[ jQuery.expando ] = true; +}; + +// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding +// https://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html +jQuery.Event.prototype = { + constructor: jQuery.Event, + isDefaultPrevented: returnFalse, + isPropagationStopped: returnFalse, + isImmediatePropagationStopped: returnFalse, + isSimulated: false, + + preventDefault: function() { + var e = this.originalEvent; + + this.isDefaultPrevented = returnTrue; + + if ( e && !this.isSimulated ) { + e.preventDefault(); + } + }, + stopPropagation: function() { + var e = this.originalEvent; + + this.isPropagationStopped = returnTrue; + + if ( e && !this.isSimulated ) { + e.stopPropagation(); + } + }, + stopImmediatePropagation: function() { + var e = this.originalEvent; + + this.isImmediatePropagationStopped = returnTrue; + + if ( e && !this.isSimulated ) { + e.stopImmediatePropagation(); + } + + this.stopPropagation(); + } +}; + +// Includes all common event props including KeyEvent and MouseEvent specific props +jQuery.each( { + altKey: true, + bubbles: true, + cancelable: true, + changedTouches: true, + ctrlKey: true, + detail: true, + eventPhase: true, + metaKey: true, + pageX: true, + pageY: true, + shiftKey: true, + view: true, + "char": true, + code: true, + charCode: true, + key: true, + keyCode: true, + button: true, + buttons: true, + clientX: true, + clientY: true, + offsetX: true, + offsetY: true, + pointerId: true, + pointerType: true, + screenX: true, + screenY: true, + targetTouches: true, + toElement: true, + touches: true, + + which: function( event ) { + var button = event.button; + + // Add which for key events + if ( event.which == null && rkeyEvent.test( event.type ) ) { + return event.charCode != null ? event.charCode : event.keyCode; + } + + // Add which for click: 1 === left; 2 === middle; 3 === right + if ( !event.which && button !== undefined && rmouseEvent.test( event.type ) ) { + if ( button & 1 ) { + return 1; + } + + if ( button & 2 ) { + return 3; + } + + if ( button & 4 ) { + return 2; + } + + return 0; + } + + return event.which; + } +}, jQuery.event.addProp ); + +jQuery.each( { focus: "focusin", blur: "focusout" }, function( type, delegateType ) { + jQuery.event.special[ type ] = { + + // Utilize native event if possible so blur/focus sequence is correct + setup: function() { + + // Claim the first handler + // dataPriv.set( this, "focus", ... ) + // dataPriv.set( this, "blur", ... ) + leverageNative( this, type, expectSync ); + + // Return false to allow normal processing in the caller + return false; + }, + trigger: function() { + + // Force setup before trigger + leverageNative( this, type ); + + // Return non-false to allow normal event-path propagation + return true; + }, + + delegateType: delegateType + }; +} ); + +// Create mouseenter/leave events using mouseover/out and event-time checks +// so that event delegation works in jQuery. +// Do the same for pointerenter/pointerleave and pointerover/pointerout +// +// Support: Safari 7 only +// Safari sends mouseenter too often; see: +// https://bugs.chromium.org/p/chromium/issues/detail?id=470258 +// for the description of the bug (it existed in older Chrome versions as well). +jQuery.each( { + mouseenter: "mouseover", + mouseleave: "mouseout", + pointerenter: "pointerover", + pointerleave: "pointerout" +}, function( orig, fix ) { + jQuery.event.special[ orig ] = { + delegateType: fix, + bindType: fix, + + handle: function( event ) { + var ret, + target = this, + related = event.relatedTarget, + handleObj = event.handleObj; + + // For mouseenter/leave call the handler if related is outside the target. + // NB: No relatedTarget if the mouse left/entered the browser window + if ( !related || ( related !== target && !jQuery.contains( target, related ) ) ) { + event.type = handleObj.origType; + ret = handleObj.handler.apply( this, arguments ); + event.type = fix; + } + return ret; + } + }; +} ); + +jQuery.fn.extend( { + + on: function( types, selector, data, fn ) { + return on( this, types, selector, data, fn ); + }, + one: function( types, selector, data, fn ) { + return on( this, types, selector, data, fn, 1 ); + }, + off: function( types, selector, fn ) { + var handleObj, type; + if ( types && types.preventDefault && types.handleObj ) { + + // ( event ) dispatched jQuery.Event + handleObj = types.handleObj; + jQuery( types.delegateTarget ).off( + handleObj.namespace ? + handleObj.origType + "." + handleObj.namespace : + handleObj.origType, + handleObj.selector, + handleObj.handler + ); + return this; + } + if ( typeof types === "object" ) { + + // ( types-object [, selector] ) + for ( type in types ) { + this.off( type, selector, types[ type ] ); + } + return this; + } + if ( selector === false || typeof selector === "function" ) { + + // ( types [, fn] ) + fn = selector; + selector = undefined; + } + if ( fn === false ) { + fn = returnFalse; + } + return this.each( function() { + jQuery.event.remove( this, types, fn, selector ); + } ); + } +} ); + + +var + + // Support: IE <=10 - 11, Edge 12 - 13 only + // In IE/Edge using regex groups here causes severe slowdowns. + // See https://connect.microsoft.com/IE/feedback/details/1736512/ + rnoInnerhtml = /\s*$/g; + +// Prefer a tbody over its parent table for containing new rows +function manipulationTarget( elem, content ) { + if ( nodeName( elem, "table" ) && + nodeName( content.nodeType !== 11 ? content : content.firstChild, "tr" ) ) { + + return jQuery( elem ).children( "tbody" )[ 0 ] || elem; + } + + return elem; +} + +// Replace/restore the type attribute of script elements for safe DOM manipulation +function disableScript( elem ) { + elem.type = ( elem.getAttribute( "type" ) !== null ) + "/" + elem.type; + return elem; +} +function restoreScript( elem ) { + if ( ( elem.type || "" ).slice( 0, 5 ) === "true/" ) { + elem.type = elem.type.slice( 5 ); + } else { + elem.removeAttribute( "type" ); + } + + return elem; +} + +function cloneCopyEvent( src, dest ) { + var i, l, type, pdataOld, udataOld, udataCur, events; + + if ( dest.nodeType !== 1 ) { + return; + } + + // 1. Copy private data: events, handlers, etc. + if ( dataPriv.hasData( src ) ) { + pdataOld = dataPriv.get( src ); + events = pdataOld.events; + + if ( events ) { + dataPriv.remove( dest, "handle events" ); + + for ( type in events ) { + for ( i = 0, l = events[ type ].length; i < l; i++ ) { + jQuery.event.add( dest, type, events[ type ][ i ] ); + } + } + } + } + + // 2. Copy user data + if ( dataUser.hasData( src ) ) { + udataOld = dataUser.access( src ); + udataCur = jQuery.extend( {}, udataOld ); + + dataUser.set( dest, udataCur ); + } +} + +// Fix IE bugs, see support tests +function fixInput( src, dest ) { + var nodeName = dest.nodeName.toLowerCase(); + + // Fails to persist the checked state of a cloned checkbox or radio button. + if ( nodeName === "input" && rcheckableType.test( src.type ) ) { + dest.checked = src.checked; + + // Fails to return the selected option to the default selected state when cloning options + } else if ( nodeName === "input" || nodeName === "textarea" ) { + dest.defaultValue = src.defaultValue; + } +} + +function domManip( collection, args, callback, ignored ) { + + // Flatten any nested arrays + args = flat( args ); + + var fragment, first, scripts, hasScripts, node, doc, + i = 0, + l = collection.length, + iNoClone = l - 1, + value = args[ 0 ], + valueIsFunction = isFunction( value ); + + // We can't cloneNode fragments that contain checked, in WebKit + if ( valueIsFunction || + ( l > 1 && typeof value === "string" && + !support.checkClone && rchecked.test( value ) ) ) { + return collection.each( function( index ) { + var self = collection.eq( index ); + if ( valueIsFunction ) { + args[ 0 ] = value.call( this, index, self.html() ); + } + domManip( self, args, callback, ignored ); + } ); + } + + if ( l ) { + fragment = buildFragment( args, collection[ 0 ].ownerDocument, false, collection, ignored ); + first = fragment.firstChild; + + if ( fragment.childNodes.length === 1 ) { + fragment = first; + } + + // Require either new content or an interest in ignored elements to invoke the callback + if ( first || ignored ) { + scripts = jQuery.map( getAll( fragment, "script" ), disableScript ); + hasScripts = scripts.length; + + // Use the original fragment for the last item + // instead of the first because it can end up + // being emptied incorrectly in certain situations (#8070). + for ( ; i < l; i++ ) { + node = fragment; + + if ( i !== iNoClone ) { + node = jQuery.clone( node, true, true ); + + // Keep references to cloned scripts for later restoration + if ( hasScripts ) { + + // Support: Android <=4.0 only, PhantomJS 1 only + // push.apply(_, arraylike) throws on ancient WebKit + jQuery.merge( scripts, getAll( node, "script" ) ); + } + } + + callback.call( collection[ i ], node, i ); + } + + if ( hasScripts ) { + doc = scripts[ scripts.length - 1 ].ownerDocument; + + // Reenable scripts + jQuery.map( scripts, restoreScript ); + + // Evaluate executable scripts on first document insertion + for ( i = 0; i < hasScripts; i++ ) { + node = scripts[ i ]; + if ( rscriptType.test( node.type || "" ) && + !dataPriv.access( node, "globalEval" ) && + jQuery.contains( doc, node ) ) { + + if ( node.src && ( node.type || "" ).toLowerCase() !== "module" ) { + + // Optional AJAX dependency, but won't run scripts if not present + if ( jQuery._evalUrl && !node.noModule ) { + jQuery._evalUrl( node.src, { + nonce: node.nonce || node.getAttribute( "nonce" ) + }, doc ); + } + } else { + DOMEval( node.textContent.replace( rcleanScript, "" ), node, doc ); + } + } + } + } + } + } + + return collection; +} + +function remove( elem, selector, keepData ) { + var node, + nodes = selector ? jQuery.filter( selector, elem ) : elem, + i = 0; + + for ( ; ( node = nodes[ i ] ) != null; i++ ) { + if ( !keepData && node.nodeType === 1 ) { + jQuery.cleanData( getAll( node ) ); + } + + if ( node.parentNode ) { + if ( keepData && isAttached( node ) ) { + setGlobalEval( getAll( node, "script" ) ); + } + node.parentNode.removeChild( node ); + } + } + + return elem; +} + +jQuery.extend( { + htmlPrefilter: function( html ) { + return html; + }, + + clone: function( elem, dataAndEvents, deepDataAndEvents ) { + var i, l, srcElements, destElements, + clone = elem.cloneNode( true ), + inPage = isAttached( elem ); + + // Fix IE cloning issues + if ( !support.noCloneChecked && ( elem.nodeType === 1 || elem.nodeType === 11 ) && + !jQuery.isXMLDoc( elem ) ) { + + // We eschew Sizzle here for performance reasons: https://jsperf.com/getall-vs-sizzle/2 + destElements = getAll( clone ); + srcElements = getAll( elem ); + + for ( i = 0, l = srcElements.length; i < l; i++ ) { + fixInput( srcElements[ i ], destElements[ i ] ); + } + } + + // Copy the events from the original to the clone + if ( dataAndEvents ) { + if ( deepDataAndEvents ) { + srcElements = srcElements || getAll( elem ); + destElements = destElements || getAll( clone ); + + for ( i = 0, l = srcElements.length; i < l; i++ ) { + cloneCopyEvent( srcElements[ i ], destElements[ i ] ); + } + } else { + cloneCopyEvent( elem, clone ); + } + } + + // Preserve script evaluation history + destElements = getAll( clone, "script" ); + if ( destElements.length > 0 ) { + setGlobalEval( destElements, !inPage && getAll( elem, "script" ) ); + } + + // Return the cloned set + return clone; + }, + + cleanData: function( elems ) { + var data, elem, type, + special = jQuery.event.special, + i = 0; + + for ( ; ( elem = elems[ i ] ) !== undefined; i++ ) { + if ( acceptData( elem ) ) { + if ( ( data = elem[ dataPriv.expando ] ) ) { + if ( data.events ) { + for ( type in data.events ) { + if ( special[ type ] ) { + jQuery.event.remove( elem, type ); + + // This is a shortcut to avoid jQuery.event.remove's overhead + } else { + jQuery.removeEvent( elem, type, data.handle ); + } + } + } + + // Support: Chrome <=35 - 45+ + // Assign undefined instead of using delete, see Data#remove + elem[ dataPriv.expando ] = undefined; + } + if ( elem[ dataUser.expando ] ) { + + // Support: Chrome <=35 - 45+ + // Assign undefined instead of using delete, see Data#remove + elem[ dataUser.expando ] = undefined; + } + } + } + } +} ); + +jQuery.fn.extend( { + detach: function( selector ) { + return remove( this, selector, true ); + }, + + remove: function( selector ) { + return remove( this, selector ); + }, + + text: function( value ) { + return access( this, function( value ) { + return value === undefined ? + jQuery.text( this ) : + this.empty().each( function() { + if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { + this.textContent = value; + } + } ); + }, null, value, arguments.length ); + }, + + append: function() { + return domManip( this, arguments, function( elem ) { + if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { + var target = manipulationTarget( this, elem ); + target.appendChild( elem ); + } + } ); + }, + + prepend: function() { + return domManip( this, arguments, function( elem ) { + if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { + var target = manipulationTarget( this, elem ); + target.insertBefore( elem, target.firstChild ); + } + } ); + }, + + before: function() { + return domManip( this, arguments, function( elem ) { + if ( this.parentNode ) { + this.parentNode.insertBefore( elem, this ); + } + } ); + }, + + after: function() { + return domManip( this, arguments, function( elem ) { + if ( this.parentNode ) { + this.parentNode.insertBefore( elem, this.nextSibling ); + } + } ); + }, + + empty: function() { + var elem, + i = 0; + + for ( ; ( elem = this[ i ] ) != null; i++ ) { + if ( elem.nodeType === 1 ) { + + // Prevent memory leaks + jQuery.cleanData( getAll( elem, false ) ); + + // Remove any remaining nodes + elem.textContent = ""; + } + } + + return this; + }, + + clone: function( dataAndEvents, deepDataAndEvents ) { + dataAndEvents = dataAndEvents == null ? false : dataAndEvents; + deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents; + + return this.map( function() { + return jQuery.clone( this, dataAndEvents, deepDataAndEvents ); + } ); + }, + + html: function( value ) { + return access( this, function( value ) { + var elem = this[ 0 ] || {}, + i = 0, + l = this.length; + + if ( value === undefined && elem.nodeType === 1 ) { + return elem.innerHTML; + } + + // See if we can take a shortcut and just use innerHTML + if ( typeof value === "string" && !rnoInnerhtml.test( value ) && + !wrapMap[ ( rtagName.exec( value ) || [ "", "" ] )[ 1 ].toLowerCase() ] ) { + + value = jQuery.htmlPrefilter( value ); + + try { + for ( ; i < l; i++ ) { + elem = this[ i ] || {}; + + // Remove element nodes and prevent memory leaks + if ( elem.nodeType === 1 ) { + jQuery.cleanData( getAll( elem, false ) ); + elem.innerHTML = value; + } + } + + elem = 0; + + // If using innerHTML throws an exception, use the fallback method + } catch ( e ) {} + } + + if ( elem ) { + this.empty().append( value ); + } + }, null, value, arguments.length ); + }, + + replaceWith: function() { + var ignored = []; + + // Make the changes, replacing each non-ignored context element with the new content + return domManip( this, arguments, function( elem ) { + var parent = this.parentNode; + + if ( jQuery.inArray( this, ignored ) < 0 ) { + jQuery.cleanData( getAll( this ) ); + if ( parent ) { + parent.replaceChild( elem, this ); + } + } + + // Force callback invocation + }, ignored ); + } +} ); + +jQuery.each( { + appendTo: "append", + prependTo: "prepend", + insertBefore: "before", + insertAfter: "after", + replaceAll: "replaceWith" +}, function( name, original ) { + jQuery.fn[ name ] = function( selector ) { + var elems, + ret = [], + insert = jQuery( selector ), + last = insert.length - 1, + i = 0; + + for ( ; i <= last; i++ ) { + elems = i === last ? this : this.clone( true ); + jQuery( insert[ i ] )[ original ]( elems ); + + // Support: Android <=4.0 only, PhantomJS 1 only + // .get() because push.apply(_, arraylike) throws on ancient WebKit + push.apply( ret, elems.get() ); + } + + return this.pushStack( ret ); + }; +} ); +var rnumnonpx = new RegExp( "^(" + pnum + ")(?!px)[a-z%]+$", "i" ); + +var getStyles = function( elem ) { + + // Support: IE <=11 only, Firefox <=30 (#15098, #14150) + // IE throws on elements created in popups + // FF meanwhile throws on frame elements through "defaultView.getComputedStyle" + var view = elem.ownerDocument.defaultView; + + if ( !view || !view.opener ) { + view = window; + } + + return view.getComputedStyle( elem ); + }; + +var swap = function( elem, options, callback ) { + var ret, name, + old = {}; + + // Remember the old values, and insert the new ones + for ( name in options ) { + old[ name ] = elem.style[ name ]; + elem.style[ name ] = options[ name ]; + } + + ret = callback.call( elem ); + + // Revert the old values + for ( name in options ) { + elem.style[ name ] = old[ name ]; + } + + return ret; +}; + + +var rboxStyle = new RegExp( cssExpand.join( "|" ), "i" ); + + + +( function() { + + // Executing both pixelPosition & boxSizingReliable tests require only one layout + // so they're executed at the same time to save the second computation. + function computeStyleTests() { + + // This is a singleton, we need to execute it only once + if ( !div ) { + return; + } + + container.style.cssText = "position:absolute;left:-11111px;width:60px;" + + "margin-top:1px;padding:0;border:0"; + div.style.cssText = + "position:relative;display:block;box-sizing:border-box;overflow:scroll;" + + "margin:auto;border:1px;padding:1px;" + + "width:60%;top:1%"; + documentElement.appendChild( container ).appendChild( div ); + + var divStyle = window.getComputedStyle( div ); + pixelPositionVal = divStyle.top !== "1%"; + + // Support: Android 4.0 - 4.3 only, Firefox <=3 - 44 + reliableMarginLeftVal = roundPixelMeasures( divStyle.marginLeft ) === 12; + + // Support: Android 4.0 - 4.3 only, Safari <=9.1 - 10.1, iOS <=7.0 - 9.3 + // Some styles come back with percentage values, even though they shouldn't + div.style.right = "60%"; + pixelBoxStylesVal = roundPixelMeasures( divStyle.right ) === 36; + + // Support: IE 9 - 11 only + // Detect misreporting of content dimensions for box-sizing:border-box elements + boxSizingReliableVal = roundPixelMeasures( divStyle.width ) === 36; + + // Support: IE 9 only + // Detect overflow:scroll screwiness (gh-3699) + // Support: Chrome <=64 + // Don't get tricked when zoom affects offsetWidth (gh-4029) + div.style.position = "absolute"; + scrollboxSizeVal = roundPixelMeasures( div.offsetWidth / 3 ) === 12; + + documentElement.removeChild( container ); + + // Nullify the div so it wouldn't be stored in the memory and + // it will also be a sign that checks already performed + div = null; + } + + function roundPixelMeasures( measure ) { + return Math.round( parseFloat( measure ) ); + } + + var pixelPositionVal, boxSizingReliableVal, scrollboxSizeVal, pixelBoxStylesVal, + reliableTrDimensionsVal, reliableMarginLeftVal, + container = document.createElement( "div" ), + div = document.createElement( "div" ); + + // Finish early in limited (non-browser) environments + if ( !div.style ) { + return; + } + + // Support: IE <=9 - 11 only + // Style of cloned element affects source element cloned (#8908) + div.style.backgroundClip = "content-box"; + div.cloneNode( true ).style.backgroundClip = ""; + support.clearCloneStyle = div.style.backgroundClip === "content-box"; + + jQuery.extend( support, { + boxSizingReliable: function() { + computeStyleTests(); + return boxSizingReliableVal; + }, + pixelBoxStyles: function() { + computeStyleTests(); + return pixelBoxStylesVal; + }, + pixelPosition: function() { + computeStyleTests(); + return pixelPositionVal; + }, + reliableMarginLeft: function() { + computeStyleTests(); + return reliableMarginLeftVal; + }, + scrollboxSize: function() { + computeStyleTests(); + return scrollboxSizeVal; + }, + + // Support: IE 9 - 11+, Edge 15 - 18+ + // IE/Edge misreport `getComputedStyle` of table rows with width/height + // set in CSS while `offset*` properties report correct values. + // Behavior in IE 9 is more subtle than in newer versions & it passes + // some versions of this test; make sure not to make it pass there! + reliableTrDimensions: function() { + var table, tr, trChild, trStyle; + if ( reliableTrDimensionsVal == null ) { + table = document.createElement( "table" ); + tr = document.createElement( "tr" ); + trChild = document.createElement( "div" ); + + table.style.cssText = "position:absolute;left:-11111px"; + tr.style.height = "1px"; + trChild.style.height = "9px"; + + documentElement + .appendChild( table ) + .appendChild( tr ) + .appendChild( trChild ); + + trStyle = window.getComputedStyle( tr ); + reliableTrDimensionsVal = parseInt( trStyle.height ) > 3; + + documentElement.removeChild( table ); + } + return reliableTrDimensionsVal; + } + } ); +} )(); + + +function curCSS( elem, name, computed ) { + var width, minWidth, maxWidth, ret, + + // Support: Firefox 51+ + // Retrieving style before computed somehow + // fixes an issue with getting wrong values + // on detached elements + style = elem.style; + + computed = computed || getStyles( elem ); + + // getPropertyValue is needed for: + // .css('filter') (IE 9 only, #12537) + // .css('--customProperty) (#3144) + if ( computed ) { + ret = computed.getPropertyValue( name ) || computed[ name ]; + + if ( ret === "" && !isAttached( elem ) ) { + ret = jQuery.style( elem, name ); + } + + // A tribute to the "awesome hack by Dean Edwards" + // Android Browser returns percentage for some values, + // but width seems to be reliably pixels. + // This is against the CSSOM draft spec: + // https://drafts.csswg.org/cssom/#resolved-values + if ( !support.pixelBoxStyles() && rnumnonpx.test( ret ) && rboxStyle.test( name ) ) { + + // Remember the original values + width = style.width; + minWidth = style.minWidth; + maxWidth = style.maxWidth; + + // Put in the new values to get a computed value out + style.minWidth = style.maxWidth = style.width = ret; + ret = computed.width; + + // Revert the changed values + style.width = width; + style.minWidth = minWidth; + style.maxWidth = maxWidth; + } + } + + return ret !== undefined ? + + // Support: IE <=9 - 11 only + // IE returns zIndex value as an integer. + ret + "" : + ret; +} + + +function addGetHookIf( conditionFn, hookFn ) { + + // Define the hook, we'll check on the first run if it's really needed. + return { + get: function() { + if ( conditionFn() ) { + + // Hook not needed (or it's not possible to use it due + // to missing dependency), remove it. + delete this.get; + return; + } + + // Hook needed; redefine it so that the support test is not executed again. + return ( this.get = hookFn ).apply( this, arguments ); + } + }; +} + + +var cssPrefixes = [ "Webkit", "Moz", "ms" ], + emptyStyle = document.createElement( "div" ).style, + vendorProps = {}; + +// Return a vendor-prefixed property or undefined +function vendorPropName( name ) { + + // Check for vendor prefixed names + var capName = name[ 0 ].toUpperCase() + name.slice( 1 ), + i = cssPrefixes.length; + + while ( i-- ) { + name = cssPrefixes[ i ] + capName; + if ( name in emptyStyle ) { + return name; + } + } +} + +// Return a potentially-mapped jQuery.cssProps or vendor prefixed property +function finalPropName( name ) { + var final = jQuery.cssProps[ name ] || vendorProps[ name ]; + + if ( final ) { + return final; + } + if ( name in emptyStyle ) { + return name; + } + return vendorProps[ name ] = vendorPropName( name ) || name; +} + + +var + + // Swappable if display is none or starts with table + // except "table", "table-cell", or "table-caption" + // See here for display values: https://developer.mozilla.org/en-US/docs/CSS/display + rdisplayswap = /^(none|table(?!-c[ea]).+)/, + rcustomProp = /^--/, + cssShow = { position: "absolute", visibility: "hidden", display: "block" }, + cssNormalTransform = { + letterSpacing: "0", + fontWeight: "400" + }; + +function setPositiveNumber( _elem, value, subtract ) { + + // Any relative (+/-) values have already been + // normalized at this point + var matches = rcssNum.exec( value ); + return matches ? + + // Guard against undefined "subtract", e.g., when used as in cssHooks + Math.max( 0, matches[ 2 ] - ( subtract || 0 ) ) + ( matches[ 3 ] || "px" ) : + value; +} + +function boxModelAdjustment( elem, dimension, box, isBorderBox, styles, computedVal ) { + var i = dimension === "width" ? 1 : 0, + extra = 0, + delta = 0; + + // Adjustment may not be necessary + if ( box === ( isBorderBox ? "border" : "content" ) ) { + return 0; + } + + for ( ; i < 4; i += 2 ) { + + // Both box models exclude margin + if ( box === "margin" ) { + delta += jQuery.css( elem, box + cssExpand[ i ], true, styles ); + } + + // If we get here with a content-box, we're seeking "padding" or "border" or "margin" + if ( !isBorderBox ) { + + // Add padding + delta += jQuery.css( elem, "padding" + cssExpand[ i ], true, styles ); + + // For "border" or "margin", add border + if ( box !== "padding" ) { + delta += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); + + // But still keep track of it otherwise + } else { + extra += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); + } + + // If we get here with a border-box (content + padding + border), we're seeking "content" or + // "padding" or "margin" + } else { + + // For "content", subtract padding + if ( box === "content" ) { + delta -= jQuery.css( elem, "padding" + cssExpand[ i ], true, styles ); + } + + // For "content" or "padding", subtract border + if ( box !== "margin" ) { + delta -= jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); + } + } + } + + // Account for positive content-box scroll gutter when requested by providing computedVal + if ( !isBorderBox && computedVal >= 0 ) { + + // offsetWidth/offsetHeight is a rounded sum of content, padding, scroll gutter, and border + // Assuming integer scroll gutter, subtract the rest and round down + delta += Math.max( 0, Math.ceil( + elem[ "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ) ] - + computedVal - + delta - + extra - + 0.5 + + // If offsetWidth/offsetHeight is unknown, then we can't determine content-box scroll gutter + // Use an explicit zero to avoid NaN (gh-3964) + ) ) || 0; + } + + return delta; +} + +function getWidthOrHeight( elem, dimension, extra ) { + + // Start with computed style + var styles = getStyles( elem ), + + // To avoid forcing a reflow, only fetch boxSizing if we need it (gh-4322). + // Fake content-box until we know it's needed to know the true value. + boxSizingNeeded = !support.boxSizingReliable() || extra, + isBorderBox = boxSizingNeeded && + jQuery.css( elem, "boxSizing", false, styles ) === "border-box", + valueIsBorderBox = isBorderBox, + + val = curCSS( elem, dimension, styles ), + offsetProp = "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ); + + // Support: Firefox <=54 + // Return a confounding non-pixel value or feign ignorance, as appropriate. + if ( rnumnonpx.test( val ) ) { + if ( !extra ) { + return val; + } + val = "auto"; + } + + + // Support: IE 9 - 11 only + // Use offsetWidth/offsetHeight for when box sizing is unreliable. + // In those cases, the computed value can be trusted to be border-box. + if ( ( !support.boxSizingReliable() && isBorderBox || + + // Support: IE 10 - 11+, Edge 15 - 18+ + // IE/Edge misreport `getComputedStyle` of table rows with width/height + // set in CSS while `offset*` properties report correct values. + // Interestingly, in some cases IE 9 doesn't suffer from this issue. + !support.reliableTrDimensions() && nodeName( elem, "tr" ) || + + // Fall back to offsetWidth/offsetHeight when value is "auto" + // This happens for inline elements with no explicit setting (gh-3571) + val === "auto" || + + // Support: Android <=4.1 - 4.3 only + // Also use offsetWidth/offsetHeight for misreported inline dimensions (gh-3602) + !parseFloat( val ) && jQuery.css( elem, "display", false, styles ) === "inline" ) && + + // Make sure the element is visible & connected + elem.getClientRects().length ) { + + isBorderBox = jQuery.css( elem, "boxSizing", false, styles ) === "border-box"; + + // Where available, offsetWidth/offsetHeight approximate border box dimensions. + // Where not available (e.g., SVG), assume unreliable box-sizing and interpret the + // retrieved value as a content box dimension. + valueIsBorderBox = offsetProp in elem; + if ( valueIsBorderBox ) { + val = elem[ offsetProp ]; + } + } + + // Normalize "" and auto + val = parseFloat( val ) || 0; + + // Adjust for the element's box model + return ( val + + boxModelAdjustment( + elem, + dimension, + extra || ( isBorderBox ? "border" : "content" ), + valueIsBorderBox, + styles, + + // Provide the current computed size to request scroll gutter calculation (gh-3589) + val + ) + ) + "px"; +} + +jQuery.extend( { + + // Add in style property hooks for overriding the default + // behavior of getting and setting a style property + cssHooks: { + opacity: { + get: function( elem, computed ) { + if ( computed ) { + + // We should always get a number back from opacity + var ret = curCSS( elem, "opacity" ); + return ret === "" ? "1" : ret; + } + } + } + }, + + // Don't automatically add "px" to these possibly-unitless properties + cssNumber: { + "animationIterationCount": true, + "columnCount": true, + "fillOpacity": true, + "flexGrow": true, + "flexShrink": true, + "fontWeight": true, + "gridArea": true, + "gridColumn": true, + "gridColumnEnd": true, + "gridColumnStart": true, + "gridRow": true, + "gridRowEnd": true, + "gridRowStart": true, + "lineHeight": true, + "opacity": true, + "order": true, + "orphans": true, + "widows": true, + "zIndex": true, + "zoom": true + }, + + // Add in properties whose names you wish to fix before + // setting or getting the value + cssProps: {}, + + // Get and set the style property on a DOM Node + style: function( elem, name, value, extra ) { + + // Don't set styles on text and comment nodes + if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) { + return; + } + + // Make sure that we're working with the right name + var ret, type, hooks, + origName = camelCase( name ), + isCustomProp = rcustomProp.test( name ), + style = elem.style; + + // Make sure that we're working with the right name. We don't + // want to query the value if it is a CSS custom property + // since they are user-defined. + if ( !isCustomProp ) { + name = finalPropName( origName ); + } + + // Gets hook for the prefixed version, then unprefixed version + hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ]; + + // Check if we're setting a value + if ( value !== undefined ) { + type = typeof value; + + // Convert "+=" or "-=" to relative numbers (#7345) + if ( type === "string" && ( ret = rcssNum.exec( value ) ) && ret[ 1 ] ) { + value = adjustCSS( elem, name, ret ); + + // Fixes bug #9237 + type = "number"; + } + + // Make sure that null and NaN values aren't set (#7116) + if ( value == null || value !== value ) { + return; + } + + // If a number was passed in, add the unit (except for certain CSS properties) + // The isCustomProp check can be removed in jQuery 4.0 when we only auto-append + // "px" to a few hardcoded values. + if ( type === "number" && !isCustomProp ) { + value += ret && ret[ 3 ] || ( jQuery.cssNumber[ origName ] ? "" : "px" ); + } + + // background-* props affect original clone's values + if ( !support.clearCloneStyle && value === "" && name.indexOf( "background" ) === 0 ) { + style[ name ] = "inherit"; + } + + // If a hook was provided, use that value, otherwise just set the specified value + if ( !hooks || !( "set" in hooks ) || + ( value = hooks.set( elem, value, extra ) ) !== undefined ) { + + if ( isCustomProp ) { + style.setProperty( name, value ); + } else { + style[ name ] = value; + } + } + + } else { + + // If a hook was provided get the non-computed value from there + if ( hooks && "get" in hooks && + ( ret = hooks.get( elem, false, extra ) ) !== undefined ) { + + return ret; + } + + // Otherwise just get the value from the style object + return style[ name ]; + } + }, + + css: function( elem, name, extra, styles ) { + var val, num, hooks, + origName = camelCase( name ), + isCustomProp = rcustomProp.test( name ); + + // Make sure that we're working with the right name. We don't + // want to modify the value if it is a CSS custom property + // since they are user-defined. + if ( !isCustomProp ) { + name = finalPropName( origName ); + } + + // Try prefixed name followed by the unprefixed name + hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ]; + + // If a hook was provided get the computed value from there + if ( hooks && "get" in hooks ) { + val = hooks.get( elem, true, extra ); + } + + // Otherwise, if a way to get the computed value exists, use that + if ( val === undefined ) { + val = curCSS( elem, name, styles ); + } + + // Convert "normal" to computed value + if ( val === "normal" && name in cssNormalTransform ) { + val = cssNormalTransform[ name ]; + } + + // Make numeric if forced or a qualifier was provided and val looks numeric + if ( extra === "" || extra ) { + num = parseFloat( val ); + return extra === true || isFinite( num ) ? num || 0 : val; + } + + return val; + } +} ); + +jQuery.each( [ "height", "width" ], function( _i, dimension ) { + jQuery.cssHooks[ dimension ] = { + get: function( elem, computed, extra ) { + if ( computed ) { + + // Certain elements can have dimension info if we invisibly show them + // but it must have a current display style that would benefit + return rdisplayswap.test( jQuery.css( elem, "display" ) ) && + + // Support: Safari 8+ + // Table columns in Safari have non-zero offsetWidth & zero + // getBoundingClientRect().width unless display is changed. + // Support: IE <=11 only + // Running getBoundingClientRect on a disconnected node + // in IE throws an error. + ( !elem.getClientRects().length || !elem.getBoundingClientRect().width ) ? + swap( elem, cssShow, function() { + return getWidthOrHeight( elem, dimension, extra ); + } ) : + getWidthOrHeight( elem, dimension, extra ); + } + }, + + set: function( elem, value, extra ) { + var matches, + styles = getStyles( elem ), + + // Only read styles.position if the test has a chance to fail + // to avoid forcing a reflow. + scrollboxSizeBuggy = !support.scrollboxSize() && + styles.position === "absolute", + + // To avoid forcing a reflow, only fetch boxSizing if we need it (gh-3991) + boxSizingNeeded = scrollboxSizeBuggy || extra, + isBorderBox = boxSizingNeeded && + jQuery.css( elem, "boxSizing", false, styles ) === "border-box", + subtract = extra ? + boxModelAdjustment( + elem, + dimension, + extra, + isBorderBox, + styles + ) : + 0; + + // Account for unreliable border-box dimensions by comparing offset* to computed and + // faking a content-box to get border and padding (gh-3699) + if ( isBorderBox && scrollboxSizeBuggy ) { + subtract -= Math.ceil( + elem[ "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ) ] - + parseFloat( styles[ dimension ] ) - + boxModelAdjustment( elem, dimension, "border", false, styles ) - + 0.5 + ); + } + + // Convert to pixels if value adjustment is needed + if ( subtract && ( matches = rcssNum.exec( value ) ) && + ( matches[ 3 ] || "px" ) !== "px" ) { + + elem.style[ dimension ] = value; + value = jQuery.css( elem, dimension ); + } + + return setPositiveNumber( elem, value, subtract ); + } + }; +} ); + +jQuery.cssHooks.marginLeft = addGetHookIf( support.reliableMarginLeft, + function( elem, computed ) { + if ( computed ) { + return ( parseFloat( curCSS( elem, "marginLeft" ) ) || + elem.getBoundingClientRect().left - + swap( elem, { marginLeft: 0 }, function() { + return elem.getBoundingClientRect().left; + } ) + ) + "px"; + } + } +); + +// These hooks are used by animate to expand properties +jQuery.each( { + margin: "", + padding: "", + border: "Width" +}, function( prefix, suffix ) { + jQuery.cssHooks[ prefix + suffix ] = { + expand: function( value ) { + var i = 0, + expanded = {}, + + // Assumes a single number if not a string + parts = typeof value === "string" ? value.split( " " ) : [ value ]; + + for ( ; i < 4; i++ ) { + expanded[ prefix + cssExpand[ i ] + suffix ] = + parts[ i ] || parts[ i - 2 ] || parts[ 0 ]; + } + + return expanded; + } + }; + + if ( prefix !== "margin" ) { + jQuery.cssHooks[ prefix + suffix ].set = setPositiveNumber; + } +} ); + +jQuery.fn.extend( { + css: function( name, value ) { + return access( this, function( elem, name, value ) { + var styles, len, + map = {}, + i = 0; + + if ( Array.isArray( name ) ) { + styles = getStyles( elem ); + len = name.length; + + for ( ; i < len; i++ ) { + map[ name[ i ] ] = jQuery.css( elem, name[ i ], false, styles ); + } + + return map; + } + + return value !== undefined ? + jQuery.style( elem, name, value ) : + jQuery.css( elem, name ); + }, name, value, arguments.length > 1 ); + } +} ); + + +function Tween( elem, options, prop, end, easing ) { + return new Tween.prototype.init( elem, options, prop, end, easing ); +} +jQuery.Tween = Tween; + +Tween.prototype = { + constructor: Tween, + init: function( elem, options, prop, end, easing, unit ) { + this.elem = elem; + this.prop = prop; + this.easing = easing || jQuery.easing._default; + this.options = options; + this.start = this.now = this.cur(); + this.end = end; + this.unit = unit || ( jQuery.cssNumber[ prop ] ? "" : "px" ); + }, + cur: function() { + var hooks = Tween.propHooks[ this.prop ]; + + return hooks && hooks.get ? + hooks.get( this ) : + Tween.propHooks._default.get( this ); + }, + run: function( percent ) { + var eased, + hooks = Tween.propHooks[ this.prop ]; + + if ( this.options.duration ) { + this.pos = eased = jQuery.easing[ this.easing ]( + percent, this.options.duration * percent, 0, 1, this.options.duration + ); + } else { + this.pos = eased = percent; + } + this.now = ( this.end - this.start ) * eased + this.start; + + if ( this.options.step ) { + this.options.step.call( this.elem, this.now, this ); + } + + if ( hooks && hooks.set ) { + hooks.set( this ); + } else { + Tween.propHooks._default.set( this ); + } + return this; + } +}; + +Tween.prototype.init.prototype = Tween.prototype; + +Tween.propHooks = { + _default: { + get: function( tween ) { + var result; + + // Use a property on the element directly when it is not a DOM element, + // or when there is no matching style property that exists. + if ( tween.elem.nodeType !== 1 || + tween.elem[ tween.prop ] != null && tween.elem.style[ tween.prop ] == null ) { + return tween.elem[ tween.prop ]; + } + + // Passing an empty string as a 3rd parameter to .css will automatically + // attempt a parseFloat and fallback to a string if the parse fails. + // Simple values such as "10px" are parsed to Float; + // complex values such as "rotate(1rad)" are returned as-is. + result = jQuery.css( tween.elem, tween.prop, "" ); + + // Empty strings, null, undefined and "auto" are converted to 0. + return !result || result === "auto" ? 0 : result; + }, + set: function( tween ) { + + // Use step hook for back compat. + // Use cssHook if its there. + // Use .style if available and use plain properties where available. + if ( jQuery.fx.step[ tween.prop ] ) { + jQuery.fx.step[ tween.prop ]( tween ); + } else if ( tween.elem.nodeType === 1 && ( + jQuery.cssHooks[ tween.prop ] || + tween.elem.style[ finalPropName( tween.prop ) ] != null ) ) { + jQuery.style( tween.elem, tween.prop, tween.now + tween.unit ); + } else { + tween.elem[ tween.prop ] = tween.now; + } + } + } +}; + +// Support: IE <=9 only +// Panic based approach to setting things on disconnected nodes +Tween.propHooks.scrollTop = Tween.propHooks.scrollLeft = { + set: function( tween ) { + if ( tween.elem.nodeType && tween.elem.parentNode ) { + tween.elem[ tween.prop ] = tween.now; + } + } +}; + +jQuery.easing = { + linear: function( p ) { + return p; + }, + swing: function( p ) { + return 0.5 - Math.cos( p * Math.PI ) / 2; + }, + _default: "swing" +}; + +jQuery.fx = Tween.prototype.init; + +// Back compat <1.8 extension point +jQuery.fx.step = {}; + + + + +var + fxNow, inProgress, + rfxtypes = /^(?:toggle|show|hide)$/, + rrun = /queueHooks$/; + +function schedule() { + if ( inProgress ) { + if ( document.hidden === false && window.requestAnimationFrame ) { + window.requestAnimationFrame( schedule ); + } else { + window.setTimeout( schedule, jQuery.fx.interval ); + } + + jQuery.fx.tick(); + } +} + +// Animations created synchronously will run synchronously +function createFxNow() { + window.setTimeout( function() { + fxNow = undefined; + } ); + return ( fxNow = Date.now() ); +} + +// Generate parameters to create a standard animation +function genFx( type, includeWidth ) { + var which, + i = 0, + attrs = { height: type }; + + // If we include width, step value is 1 to do all cssExpand values, + // otherwise step value is 2 to skip over Left and Right + includeWidth = includeWidth ? 1 : 0; + for ( ; i < 4; i += 2 - includeWidth ) { + which = cssExpand[ i ]; + attrs[ "margin" + which ] = attrs[ "padding" + which ] = type; + } + + if ( includeWidth ) { + attrs.opacity = attrs.width = type; + } + + return attrs; +} + +function createTween( value, prop, animation ) { + var tween, + collection = ( Animation.tweeners[ prop ] || [] ).concat( Animation.tweeners[ "*" ] ), + index = 0, + length = collection.length; + for ( ; index < length; index++ ) { + if ( ( tween = collection[ index ].call( animation, prop, value ) ) ) { + + // We're done with this property + return tween; + } + } +} + +function defaultPrefilter( elem, props, opts ) { + var prop, value, toggle, hooks, oldfire, propTween, restoreDisplay, display, + isBox = "width" in props || "height" in props, + anim = this, + orig = {}, + style = elem.style, + hidden = elem.nodeType && isHiddenWithinTree( elem ), + dataShow = dataPriv.get( elem, "fxshow" ); + + // Queue-skipping animations hijack the fx hooks + if ( !opts.queue ) { + hooks = jQuery._queueHooks( elem, "fx" ); + if ( hooks.unqueued == null ) { + hooks.unqueued = 0; + oldfire = hooks.empty.fire; + hooks.empty.fire = function() { + if ( !hooks.unqueued ) { + oldfire(); + } + }; + } + hooks.unqueued++; + + anim.always( function() { + + // Ensure the complete handler is called before this completes + anim.always( function() { + hooks.unqueued--; + if ( !jQuery.queue( elem, "fx" ).length ) { + hooks.empty.fire(); + } + } ); + } ); + } + + // Detect show/hide animations + for ( prop in props ) { + value = props[ prop ]; + if ( rfxtypes.test( value ) ) { + delete props[ prop ]; + toggle = toggle || value === "toggle"; + if ( value === ( hidden ? "hide" : "show" ) ) { + + // Pretend to be hidden if this is a "show" and + // there is still data from a stopped show/hide + if ( value === "show" && dataShow && dataShow[ prop ] !== undefined ) { + hidden = true; + + // Ignore all other no-op show/hide data + } else { + continue; + } + } + orig[ prop ] = dataShow && dataShow[ prop ] || jQuery.style( elem, prop ); + } + } + + // Bail out if this is a no-op like .hide().hide() + propTween = !jQuery.isEmptyObject( props ); + if ( !propTween && jQuery.isEmptyObject( orig ) ) { + return; + } + + // Restrict "overflow" and "display" styles during box animations + if ( isBox && elem.nodeType === 1 ) { + + // Support: IE <=9 - 11, Edge 12 - 15 + // Record all 3 overflow attributes because IE does not infer the shorthand + // from identically-valued overflowX and overflowY and Edge just mirrors + // the overflowX value there. + opts.overflow = [ style.overflow, style.overflowX, style.overflowY ]; + + // Identify a display type, preferring old show/hide data over the CSS cascade + restoreDisplay = dataShow && dataShow.display; + if ( restoreDisplay == null ) { + restoreDisplay = dataPriv.get( elem, "display" ); + } + display = jQuery.css( elem, "display" ); + if ( display === "none" ) { + if ( restoreDisplay ) { + display = restoreDisplay; + } else { + + // Get nonempty value(s) by temporarily forcing visibility + showHide( [ elem ], true ); + restoreDisplay = elem.style.display || restoreDisplay; + display = jQuery.css( elem, "display" ); + showHide( [ elem ] ); + } + } + + // Animate inline elements as inline-block + if ( display === "inline" || display === "inline-block" && restoreDisplay != null ) { + if ( jQuery.css( elem, "float" ) === "none" ) { + + // Restore the original display value at the end of pure show/hide animations + if ( !propTween ) { + anim.done( function() { + style.display = restoreDisplay; + } ); + if ( restoreDisplay == null ) { + display = style.display; + restoreDisplay = display === "none" ? "" : display; + } + } + style.display = "inline-block"; + } + } + } + + if ( opts.overflow ) { + style.overflow = "hidden"; + anim.always( function() { + style.overflow = opts.overflow[ 0 ]; + style.overflowX = opts.overflow[ 1 ]; + style.overflowY = opts.overflow[ 2 ]; + } ); + } + + // Implement show/hide animations + propTween = false; + for ( prop in orig ) { + + // General show/hide setup for this element animation + if ( !propTween ) { + if ( dataShow ) { + if ( "hidden" in dataShow ) { + hidden = dataShow.hidden; + } + } else { + dataShow = dataPriv.access( elem, "fxshow", { display: restoreDisplay } ); + } + + // Store hidden/visible for toggle so `.stop().toggle()` "reverses" + if ( toggle ) { + dataShow.hidden = !hidden; + } + + // Show elements before animating them + if ( hidden ) { + showHide( [ elem ], true ); + } + + /* eslint-disable no-loop-func */ + + anim.done( function() { + + /* eslint-enable no-loop-func */ + + // The final step of a "hide" animation is actually hiding the element + if ( !hidden ) { + showHide( [ elem ] ); + } + dataPriv.remove( elem, "fxshow" ); + for ( prop in orig ) { + jQuery.style( elem, prop, orig[ prop ] ); + } + } ); + } + + // Per-property setup + propTween = createTween( hidden ? dataShow[ prop ] : 0, prop, anim ); + if ( !( prop in dataShow ) ) { + dataShow[ prop ] = propTween.start; + if ( hidden ) { + propTween.end = propTween.start; + propTween.start = 0; + } + } + } +} + +function propFilter( props, specialEasing ) { + var index, name, easing, value, hooks; + + // camelCase, specialEasing and expand cssHook pass + for ( index in props ) { + name = camelCase( index ); + easing = specialEasing[ name ]; + value = props[ index ]; + if ( Array.isArray( value ) ) { + easing = value[ 1 ]; + value = props[ index ] = value[ 0 ]; + } + + if ( index !== name ) { + props[ name ] = value; + delete props[ index ]; + } + + hooks = jQuery.cssHooks[ name ]; + if ( hooks && "expand" in hooks ) { + value = hooks.expand( value ); + delete props[ name ]; + + // Not quite $.extend, this won't overwrite existing keys. + // Reusing 'index' because we have the correct "name" + for ( index in value ) { + if ( !( index in props ) ) { + props[ index ] = value[ index ]; + specialEasing[ index ] = easing; + } + } + } else { + specialEasing[ name ] = easing; + } + } +} + +function Animation( elem, properties, options ) { + var result, + stopped, + index = 0, + length = Animation.prefilters.length, + deferred = jQuery.Deferred().always( function() { + + // Don't match elem in the :animated selector + delete tick.elem; + } ), + tick = function() { + if ( stopped ) { + return false; + } + var currentTime = fxNow || createFxNow(), + remaining = Math.max( 0, animation.startTime + animation.duration - currentTime ), + + // Support: Android 2.3 only + // Archaic crash bug won't allow us to use `1 - ( 0.5 || 0 )` (#12497) + temp = remaining / animation.duration || 0, + percent = 1 - temp, + index = 0, + length = animation.tweens.length; + + for ( ; index < length; index++ ) { + animation.tweens[ index ].run( percent ); + } + + deferred.notifyWith( elem, [ animation, percent, remaining ] ); + + // If there's more to do, yield + if ( percent < 1 && length ) { + return remaining; + } + + // If this was an empty animation, synthesize a final progress notification + if ( !length ) { + deferred.notifyWith( elem, [ animation, 1, 0 ] ); + } + + // Resolve the animation and report its conclusion + deferred.resolveWith( elem, [ animation ] ); + return false; + }, + animation = deferred.promise( { + elem: elem, + props: jQuery.extend( {}, properties ), + opts: jQuery.extend( true, { + specialEasing: {}, + easing: jQuery.easing._default + }, options ), + originalProperties: properties, + originalOptions: options, + startTime: fxNow || createFxNow(), + duration: options.duration, + tweens: [], + createTween: function( prop, end ) { + var tween = jQuery.Tween( elem, animation.opts, prop, end, + animation.opts.specialEasing[ prop ] || animation.opts.easing ); + animation.tweens.push( tween ); + return tween; + }, + stop: function( gotoEnd ) { + var index = 0, + + // If we are going to the end, we want to run all the tweens + // otherwise we skip this part + length = gotoEnd ? animation.tweens.length : 0; + if ( stopped ) { + return this; + } + stopped = true; + for ( ; index < length; index++ ) { + animation.tweens[ index ].run( 1 ); + } + + // Resolve when we played the last frame; otherwise, reject + if ( gotoEnd ) { + deferred.notifyWith( elem, [ animation, 1, 0 ] ); + deferred.resolveWith( elem, [ animation, gotoEnd ] ); + } else { + deferred.rejectWith( elem, [ animation, gotoEnd ] ); + } + return this; + } + } ), + props = animation.props; + + propFilter( props, animation.opts.specialEasing ); + + for ( ; index < length; index++ ) { + result = Animation.prefilters[ index ].call( animation, elem, props, animation.opts ); + if ( result ) { + if ( isFunction( result.stop ) ) { + jQuery._queueHooks( animation.elem, animation.opts.queue ).stop = + result.stop.bind( result ); + } + return result; + } + } + + jQuery.map( props, createTween, animation ); + + if ( isFunction( animation.opts.start ) ) { + animation.opts.start.call( elem, animation ); + } + + // Attach callbacks from options + animation + .progress( animation.opts.progress ) + .done( animation.opts.done, animation.opts.complete ) + .fail( animation.opts.fail ) + .always( animation.opts.always ); + + jQuery.fx.timer( + jQuery.extend( tick, { + elem: elem, + anim: animation, + queue: animation.opts.queue + } ) + ); + + return animation; +} + +jQuery.Animation = jQuery.extend( Animation, { + + tweeners: { + "*": [ function( prop, value ) { + var tween = this.createTween( prop, value ); + adjustCSS( tween.elem, prop, rcssNum.exec( value ), tween ); + return tween; + } ] + }, + + tweener: function( props, callback ) { + if ( isFunction( props ) ) { + callback = props; + props = [ "*" ]; + } else { + props = props.match( rnothtmlwhite ); + } + + var prop, + index = 0, + length = props.length; + + for ( ; index < length; index++ ) { + prop = props[ index ]; + Animation.tweeners[ prop ] = Animation.tweeners[ prop ] || []; + Animation.tweeners[ prop ].unshift( callback ); + } + }, + + prefilters: [ defaultPrefilter ], + + prefilter: function( callback, prepend ) { + if ( prepend ) { + Animation.prefilters.unshift( callback ); + } else { + Animation.prefilters.push( callback ); + } + } +} ); + +jQuery.speed = function( speed, easing, fn ) { + var opt = speed && typeof speed === "object" ? jQuery.extend( {}, speed ) : { + complete: fn || !fn && easing || + isFunction( speed ) && speed, + duration: speed, + easing: fn && easing || easing && !isFunction( easing ) && easing + }; + + // Go to the end state if fx are off + if ( jQuery.fx.off ) { + opt.duration = 0; + + } else { + if ( typeof opt.duration !== "number" ) { + if ( opt.duration in jQuery.fx.speeds ) { + opt.duration = jQuery.fx.speeds[ opt.duration ]; + + } else { + opt.duration = jQuery.fx.speeds._default; + } + } + } + + // Normalize opt.queue - true/undefined/null -> "fx" + if ( opt.queue == null || opt.queue === true ) { + opt.queue = "fx"; + } + + // Queueing + opt.old = opt.complete; + + opt.complete = function() { + if ( isFunction( opt.old ) ) { + opt.old.call( this ); + } + + if ( opt.queue ) { + jQuery.dequeue( this, opt.queue ); + } + }; + + return opt; +}; + +jQuery.fn.extend( { + fadeTo: function( speed, to, easing, callback ) { + + // Show any hidden elements after setting opacity to 0 + return this.filter( isHiddenWithinTree ).css( "opacity", 0 ).show() + + // Animate to the value specified + .end().animate( { opacity: to }, speed, easing, callback ); + }, + animate: function( prop, speed, easing, callback ) { + var empty = jQuery.isEmptyObject( prop ), + optall = jQuery.speed( speed, easing, callback ), + doAnimation = function() { + + // Operate on a copy of prop so per-property easing won't be lost + var anim = Animation( this, jQuery.extend( {}, prop ), optall ); + + // Empty animations, or finishing resolves immediately + if ( empty || dataPriv.get( this, "finish" ) ) { + anim.stop( true ); + } + }; + doAnimation.finish = doAnimation; + + return empty || optall.queue === false ? + this.each( doAnimation ) : + this.queue( optall.queue, doAnimation ); + }, + stop: function( type, clearQueue, gotoEnd ) { + var stopQueue = function( hooks ) { + var stop = hooks.stop; + delete hooks.stop; + stop( gotoEnd ); + }; + + if ( typeof type !== "string" ) { + gotoEnd = clearQueue; + clearQueue = type; + type = undefined; + } + if ( clearQueue ) { + this.queue( type || "fx", [] ); + } + + return this.each( function() { + var dequeue = true, + index = type != null && type + "queueHooks", + timers = jQuery.timers, + data = dataPriv.get( this ); + + if ( index ) { + if ( data[ index ] && data[ index ].stop ) { + stopQueue( data[ index ] ); + } + } else { + for ( index in data ) { + if ( data[ index ] && data[ index ].stop && rrun.test( index ) ) { + stopQueue( data[ index ] ); + } + } + } + + for ( index = timers.length; index--; ) { + if ( timers[ index ].elem === this && + ( type == null || timers[ index ].queue === type ) ) { + + timers[ index ].anim.stop( gotoEnd ); + dequeue = false; + timers.splice( index, 1 ); + } + } + + // Start the next in the queue if the last step wasn't forced. + // Timers currently will call their complete callbacks, which + // will dequeue but only if they were gotoEnd. + if ( dequeue || !gotoEnd ) { + jQuery.dequeue( this, type ); + } + } ); + }, + finish: function( type ) { + if ( type !== false ) { + type = type || "fx"; + } + return this.each( function() { + var index, + data = dataPriv.get( this ), + queue = data[ type + "queue" ], + hooks = data[ type + "queueHooks" ], + timers = jQuery.timers, + length = queue ? queue.length : 0; + + // Enable finishing flag on private data + data.finish = true; + + // Empty the queue first + jQuery.queue( this, type, [] ); + + if ( hooks && hooks.stop ) { + hooks.stop.call( this, true ); + } + + // Look for any active animations, and finish them + for ( index = timers.length; index--; ) { + if ( timers[ index ].elem === this && timers[ index ].queue === type ) { + timers[ index ].anim.stop( true ); + timers.splice( index, 1 ); + } + } + + // Look for any animations in the old queue and finish them + for ( index = 0; index < length; index++ ) { + if ( queue[ index ] && queue[ index ].finish ) { + queue[ index ].finish.call( this ); + } + } + + // Turn off finishing flag + delete data.finish; + } ); + } +} ); + +jQuery.each( [ "toggle", "show", "hide" ], function( _i, name ) { + var cssFn = jQuery.fn[ name ]; + jQuery.fn[ name ] = function( speed, easing, callback ) { + return speed == null || typeof speed === "boolean" ? + cssFn.apply( this, arguments ) : + this.animate( genFx( name, true ), speed, easing, callback ); + }; +} ); + +// Generate shortcuts for custom animations +jQuery.each( { + slideDown: genFx( "show" ), + slideUp: genFx( "hide" ), + slideToggle: genFx( "toggle" ), + fadeIn: { opacity: "show" }, + fadeOut: { opacity: "hide" }, + fadeToggle: { opacity: "toggle" } +}, function( name, props ) { + jQuery.fn[ name ] = function( speed, easing, callback ) { + return this.animate( props, speed, easing, callback ); + }; +} ); + +jQuery.timers = []; +jQuery.fx.tick = function() { + var timer, + i = 0, + timers = jQuery.timers; + + fxNow = Date.now(); + + for ( ; i < timers.length; i++ ) { + timer = timers[ i ]; + + // Run the timer and safely remove it when done (allowing for external removal) + if ( !timer() && timers[ i ] === timer ) { + timers.splice( i--, 1 ); + } + } + + if ( !timers.length ) { + jQuery.fx.stop(); + } + fxNow = undefined; +}; + +jQuery.fx.timer = function( timer ) { + jQuery.timers.push( timer ); + jQuery.fx.start(); +}; + +jQuery.fx.interval = 13; +jQuery.fx.start = function() { + if ( inProgress ) { + return; + } + + inProgress = true; + schedule(); +}; + +jQuery.fx.stop = function() { + inProgress = null; +}; + +jQuery.fx.speeds = { + slow: 600, + fast: 200, + + // Default speed + _default: 400 +}; + + +// Based off of the plugin by Clint Helfers, with permission. +// https://web.archive.org/web/20100324014747/http://blindsignals.com/index.php/2009/07/jquery-delay/ +jQuery.fn.delay = function( time, type ) { + time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time; + type = type || "fx"; + + return this.queue( type, function( next, hooks ) { + var timeout = window.setTimeout( next, time ); + hooks.stop = function() { + window.clearTimeout( timeout ); + }; + } ); +}; + + +( function() { + var input = document.createElement( "input" ), + select = document.createElement( "select" ), + opt = select.appendChild( document.createElement( "option" ) ); + + input.type = "checkbox"; + + // Support: Android <=4.3 only + // Default value for a checkbox should be "on" + support.checkOn = input.value !== ""; + + // Support: IE <=11 only + // Must access selectedIndex to make default options select + support.optSelected = opt.selected; + + // Support: IE <=11 only + // An input loses its value after becoming a radio + input = document.createElement( "input" ); + input.value = "t"; + input.type = "radio"; + support.radioValue = input.value === "t"; +} )(); + + +var boolHook, + attrHandle = jQuery.expr.attrHandle; + +jQuery.fn.extend( { + attr: function( name, value ) { + return access( this, jQuery.attr, name, value, arguments.length > 1 ); + }, + + removeAttr: function( name ) { + return this.each( function() { + jQuery.removeAttr( this, name ); + } ); + } +} ); + +jQuery.extend( { + attr: function( elem, name, value ) { + var ret, hooks, + nType = elem.nodeType; + + // Don't get/set attributes on text, comment and attribute nodes + if ( nType === 3 || nType === 8 || nType === 2 ) { + return; + } + + // Fallback to prop when attributes are not supported + if ( typeof elem.getAttribute === "undefined" ) { + return jQuery.prop( elem, name, value ); + } + + // Attribute hooks are determined by the lowercase version + // Grab necessary hook if one is defined + if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) { + hooks = jQuery.attrHooks[ name.toLowerCase() ] || + ( jQuery.expr.match.bool.test( name ) ? boolHook : undefined ); + } + + if ( value !== undefined ) { + if ( value === null ) { + jQuery.removeAttr( elem, name ); + return; + } + + if ( hooks && "set" in hooks && + ( ret = hooks.set( elem, value, name ) ) !== undefined ) { + return ret; + } + + elem.setAttribute( name, value + "" ); + return value; + } + + if ( hooks && "get" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) { + return ret; + } + + ret = jQuery.find.attr( elem, name ); + + // Non-existent attributes return null, we normalize to undefined + return ret == null ? undefined : ret; + }, + + attrHooks: { + type: { + set: function( elem, value ) { + if ( !support.radioValue && value === "radio" && + nodeName( elem, "input" ) ) { + var val = elem.value; + elem.setAttribute( "type", value ); + if ( val ) { + elem.value = val; + } + return value; + } + } + } + }, + + removeAttr: function( elem, value ) { + var name, + i = 0, + + // Attribute names can contain non-HTML whitespace characters + // https://html.spec.whatwg.org/multipage/syntax.html#attributes-2 + attrNames = value && value.match( rnothtmlwhite ); + + if ( attrNames && elem.nodeType === 1 ) { + while ( ( name = attrNames[ i++ ] ) ) { + elem.removeAttribute( name ); + } + } + } +} ); + +// Hooks for boolean attributes +boolHook = { + set: function( elem, value, name ) { + if ( value === false ) { + + // Remove boolean attributes when set to false + jQuery.removeAttr( elem, name ); + } else { + elem.setAttribute( name, name ); + } + return name; + } +}; + +jQuery.each( jQuery.expr.match.bool.source.match( /\w+/g ), function( _i, name ) { + var getter = attrHandle[ name ] || jQuery.find.attr; + + attrHandle[ name ] = function( elem, name, isXML ) { + var ret, handle, + lowercaseName = name.toLowerCase(); + + if ( !isXML ) { + + // Avoid an infinite loop by temporarily removing this function from the getter + handle = attrHandle[ lowercaseName ]; + attrHandle[ lowercaseName ] = ret; + ret = getter( elem, name, isXML ) != null ? + lowercaseName : + null; + attrHandle[ lowercaseName ] = handle; + } + return ret; + }; +} ); + + + + +var rfocusable = /^(?:input|select|textarea|button)$/i, + rclickable = /^(?:a|area)$/i; + +jQuery.fn.extend( { + prop: function( name, value ) { + return access( this, jQuery.prop, name, value, arguments.length > 1 ); + }, + + removeProp: function( name ) { + return this.each( function() { + delete this[ jQuery.propFix[ name ] || name ]; + } ); + } +} ); + +jQuery.extend( { + prop: function( elem, name, value ) { + var ret, hooks, + nType = elem.nodeType; + + // Don't get/set properties on text, comment and attribute nodes + if ( nType === 3 || nType === 8 || nType === 2 ) { + return; + } + + if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) { + + // Fix name and attach hooks + name = jQuery.propFix[ name ] || name; + hooks = jQuery.propHooks[ name ]; + } + + if ( value !== undefined ) { + if ( hooks && "set" in hooks && + ( ret = hooks.set( elem, value, name ) ) !== undefined ) { + return ret; + } + + return ( elem[ name ] = value ); + } + + if ( hooks && "get" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) { + return ret; + } + + return elem[ name ]; + }, + + propHooks: { + tabIndex: { + get: function( elem ) { + + // Support: IE <=9 - 11 only + // elem.tabIndex doesn't always return the + // correct value when it hasn't been explicitly set + // https://web.archive.org/web/20141116233347/http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/ + // Use proper attribute retrieval(#12072) + var tabindex = jQuery.find.attr( elem, "tabindex" ); + + if ( tabindex ) { + return parseInt( tabindex, 10 ); + } + + if ( + rfocusable.test( elem.nodeName ) || + rclickable.test( elem.nodeName ) && + elem.href + ) { + return 0; + } + + return -1; + } + } + }, + + propFix: { + "for": "htmlFor", + "class": "className" + } +} ); + +// Support: IE <=11 only +// Accessing the selectedIndex property +// forces the browser to respect setting selected +// on the option +// The getter ensures a default option is selected +// when in an optgroup +// eslint rule "no-unused-expressions" is disabled for this code +// since it considers such accessions noop +if ( !support.optSelected ) { + jQuery.propHooks.selected = { + get: function( elem ) { + + /* eslint no-unused-expressions: "off" */ + + var parent = elem.parentNode; + if ( parent && parent.parentNode ) { + parent.parentNode.selectedIndex; + } + return null; + }, + set: function( elem ) { + + /* eslint no-unused-expressions: "off" */ + + var parent = elem.parentNode; + if ( parent ) { + parent.selectedIndex; + + if ( parent.parentNode ) { + parent.parentNode.selectedIndex; + } + } + } + }; +} + +jQuery.each( [ + "tabIndex", + "readOnly", + "maxLength", + "cellSpacing", + "cellPadding", + "rowSpan", + "colSpan", + "useMap", + "frameBorder", + "contentEditable" +], function() { + jQuery.propFix[ this.toLowerCase() ] = this; +} ); + + + + + // Strip and collapse whitespace according to HTML spec + // https://infra.spec.whatwg.org/#strip-and-collapse-ascii-whitespace + function stripAndCollapse( value ) { + var tokens = value.match( rnothtmlwhite ) || []; + return tokens.join( " " ); + } + + +function getClass( elem ) { + return elem.getAttribute && elem.getAttribute( "class" ) || ""; +} + +function classesToArray( value ) { + if ( Array.isArray( value ) ) { + return value; + } + if ( typeof value === "string" ) { + return value.match( rnothtmlwhite ) || []; + } + return []; +} + +jQuery.fn.extend( { + addClass: function( value ) { + var classes, elem, cur, curValue, clazz, j, finalValue, + i = 0; + + if ( isFunction( value ) ) { + return this.each( function( j ) { + jQuery( this ).addClass( value.call( this, j, getClass( this ) ) ); + } ); + } + + classes = classesToArray( value ); + + if ( classes.length ) { + while ( ( elem = this[ i++ ] ) ) { + curValue = getClass( elem ); + cur = elem.nodeType === 1 && ( " " + stripAndCollapse( curValue ) + " " ); + + if ( cur ) { + j = 0; + while ( ( clazz = classes[ j++ ] ) ) { + if ( cur.indexOf( " " + clazz + " " ) < 0 ) { + cur += clazz + " "; + } + } + + // Only assign if different to avoid unneeded rendering. + finalValue = stripAndCollapse( cur ); + if ( curValue !== finalValue ) { + elem.setAttribute( "class", finalValue ); + } + } + } + } + + return this; + }, + + removeClass: function( value ) { + var classes, elem, cur, curValue, clazz, j, finalValue, + i = 0; + + if ( isFunction( value ) ) { + return this.each( function( j ) { + jQuery( this ).removeClass( value.call( this, j, getClass( this ) ) ); + } ); + } + + if ( !arguments.length ) { + return this.attr( "class", "" ); + } + + classes = classesToArray( value ); + + if ( classes.length ) { + while ( ( elem = this[ i++ ] ) ) { + curValue = getClass( elem ); + + // This expression is here for better compressibility (see addClass) + cur = elem.nodeType === 1 && ( " " + stripAndCollapse( curValue ) + " " ); + + if ( cur ) { + j = 0; + while ( ( clazz = classes[ j++ ] ) ) { + + // Remove *all* instances + while ( cur.indexOf( " " + clazz + " " ) > -1 ) { + cur = cur.replace( " " + clazz + " ", " " ); + } + } + + // Only assign if different to avoid unneeded rendering. + finalValue = stripAndCollapse( cur ); + if ( curValue !== finalValue ) { + elem.setAttribute( "class", finalValue ); + } + } + } + } + + return this; + }, + + toggleClass: function( value, stateVal ) { + var type = typeof value, + isValidValue = type === "string" || Array.isArray( value ); + + if ( typeof stateVal === "boolean" && isValidValue ) { + return stateVal ? this.addClass( value ) : this.removeClass( value ); + } + + if ( isFunction( value ) ) { + return this.each( function( i ) { + jQuery( this ).toggleClass( + value.call( this, i, getClass( this ), stateVal ), + stateVal + ); + } ); + } + + return this.each( function() { + var className, i, self, classNames; + + if ( isValidValue ) { + + // Toggle individual class names + i = 0; + self = jQuery( this ); + classNames = classesToArray( value ); + + while ( ( className = classNames[ i++ ] ) ) { + + // Check each className given, space separated list + if ( self.hasClass( className ) ) { + self.removeClass( className ); + } else { + self.addClass( className ); + } + } + + // Toggle whole class name + } else if ( value === undefined || type === "boolean" ) { + className = getClass( this ); + if ( className ) { + + // Store className if set + dataPriv.set( this, "__className__", className ); + } + + // If the element has a class name or if we're passed `false`, + // then remove the whole classname (if there was one, the above saved it). + // Otherwise bring back whatever was previously saved (if anything), + // falling back to the empty string if nothing was stored. + if ( this.setAttribute ) { + this.setAttribute( "class", + className || value === false ? + "" : + dataPriv.get( this, "__className__" ) || "" + ); + } + } + } ); + }, + + hasClass: function( selector ) { + var className, elem, + i = 0; + + className = " " + selector + " "; + while ( ( elem = this[ i++ ] ) ) { + if ( elem.nodeType === 1 && + ( " " + stripAndCollapse( getClass( elem ) ) + " " ).indexOf( className ) > -1 ) { + return true; + } + } + + return false; + } +} ); + + + + +var rreturn = /\r/g; + +jQuery.fn.extend( { + val: function( value ) { + var hooks, ret, valueIsFunction, + elem = this[ 0 ]; + + if ( !arguments.length ) { + if ( elem ) { + hooks = jQuery.valHooks[ elem.type ] || + jQuery.valHooks[ elem.nodeName.toLowerCase() ]; + + if ( hooks && + "get" in hooks && + ( ret = hooks.get( elem, "value" ) ) !== undefined + ) { + return ret; + } + + ret = elem.value; + + // Handle most common string cases + if ( typeof ret === "string" ) { + return ret.replace( rreturn, "" ); + } + + // Handle cases where value is null/undef or number + return ret == null ? "" : ret; + } + + return; + } + + valueIsFunction = isFunction( value ); + + return this.each( function( i ) { + var val; + + if ( this.nodeType !== 1 ) { + return; + } + + if ( valueIsFunction ) { + val = value.call( this, i, jQuery( this ).val() ); + } else { + val = value; + } + + // Treat null/undefined as ""; convert numbers to string + if ( val == null ) { + val = ""; + + } else if ( typeof val === "number" ) { + val += ""; + + } else if ( Array.isArray( val ) ) { + val = jQuery.map( val, function( value ) { + return value == null ? "" : value + ""; + } ); + } + + hooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ]; + + // If set returns undefined, fall back to normal setting + if ( !hooks || !( "set" in hooks ) || hooks.set( this, val, "value" ) === undefined ) { + this.value = val; + } + } ); + } +} ); + +jQuery.extend( { + valHooks: { + option: { + get: function( elem ) { + + var val = jQuery.find.attr( elem, "value" ); + return val != null ? + val : + + // Support: IE <=10 - 11 only + // option.text throws exceptions (#14686, #14858) + // Strip and collapse whitespace + // https://html.spec.whatwg.org/#strip-and-collapse-whitespace + stripAndCollapse( jQuery.text( elem ) ); + } + }, + select: { + get: function( elem ) { + var value, option, i, + options = elem.options, + index = elem.selectedIndex, + one = elem.type === "select-one", + values = one ? null : [], + max = one ? index + 1 : options.length; + + if ( index < 0 ) { + i = max; + + } else { + i = one ? index : 0; + } + + // Loop through all the selected options + for ( ; i < max; i++ ) { + option = options[ i ]; + + // Support: IE <=9 only + // IE8-9 doesn't update selected after form reset (#2551) + if ( ( option.selected || i === index ) && + + // Don't return options that are disabled or in a disabled optgroup + !option.disabled && + ( !option.parentNode.disabled || + !nodeName( option.parentNode, "optgroup" ) ) ) { + + // Get the specific value for the option + value = jQuery( option ).val(); + + // We don't need an array for one selects + if ( one ) { + return value; + } + + // Multi-Selects return an array + values.push( value ); + } + } + + return values; + }, + + set: function( elem, value ) { + var optionSet, option, + options = elem.options, + values = jQuery.makeArray( value ), + i = options.length; + + while ( i-- ) { + option = options[ i ]; + + /* eslint-disable no-cond-assign */ + + if ( option.selected = + jQuery.inArray( jQuery.valHooks.option.get( option ), values ) > -1 + ) { + optionSet = true; + } + + /* eslint-enable no-cond-assign */ + } + + // Force browsers to behave consistently when non-matching value is set + if ( !optionSet ) { + elem.selectedIndex = -1; + } + return values; + } + } + } +} ); + +// Radios and checkboxes getter/setter +jQuery.each( [ "radio", "checkbox" ], function() { + jQuery.valHooks[ this ] = { + set: function( elem, value ) { + if ( Array.isArray( value ) ) { + return ( elem.checked = jQuery.inArray( jQuery( elem ).val(), value ) > -1 ); + } + } + }; + if ( !support.checkOn ) { + jQuery.valHooks[ this ].get = function( elem ) { + return elem.getAttribute( "value" ) === null ? "on" : elem.value; + }; + } +} ); + + + + +// Return jQuery for attributes-only inclusion + + +support.focusin = "onfocusin" in window; + + +var rfocusMorph = /^(?:focusinfocus|focusoutblur)$/, + stopPropagationCallback = function( e ) { + e.stopPropagation(); + }; + +jQuery.extend( jQuery.event, { + + trigger: function( event, data, elem, onlyHandlers ) { + + var i, cur, tmp, bubbleType, ontype, handle, special, lastElement, + eventPath = [ elem || document ], + type = hasOwn.call( event, "type" ) ? event.type : event, + namespaces = hasOwn.call( event, "namespace" ) ? event.namespace.split( "." ) : []; + + cur = lastElement = tmp = elem = elem || document; + + // Don't do events on text and comment nodes + if ( elem.nodeType === 3 || elem.nodeType === 8 ) { + return; + } + + // focus/blur morphs to focusin/out; ensure we're not firing them right now + if ( rfocusMorph.test( type + jQuery.event.triggered ) ) { + return; + } + + if ( type.indexOf( "." ) > -1 ) { + + // Namespaced trigger; create a regexp to match event type in handle() + namespaces = type.split( "." ); + type = namespaces.shift(); + namespaces.sort(); + } + ontype = type.indexOf( ":" ) < 0 && "on" + type; + + // Caller can pass in a jQuery.Event object, Object, or just an event type string + event = event[ jQuery.expando ] ? + event : + new jQuery.Event( type, typeof event === "object" && event ); + + // Trigger bitmask: & 1 for native handlers; & 2 for jQuery (always true) + event.isTrigger = onlyHandlers ? 2 : 3; + event.namespace = namespaces.join( "." ); + event.rnamespace = event.namespace ? + new RegExp( "(^|\\.)" + namespaces.join( "\\.(?:.*\\.|)" ) + "(\\.|$)" ) : + null; + + // Clean up the event in case it is being reused + event.result = undefined; + if ( !event.target ) { + event.target = elem; + } + + // Clone any incoming data and prepend the event, creating the handler arg list + data = data == null ? + [ event ] : + jQuery.makeArray( data, [ event ] ); + + // Allow special events to draw outside the lines + special = jQuery.event.special[ type ] || {}; + if ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) { + return; + } + + // Determine event propagation path in advance, per W3C events spec (#9951) + // Bubble up to document, then to window; watch for a global ownerDocument var (#9724) + if ( !onlyHandlers && !special.noBubble && !isWindow( elem ) ) { + + bubbleType = special.delegateType || type; + if ( !rfocusMorph.test( bubbleType + type ) ) { + cur = cur.parentNode; + } + for ( ; cur; cur = cur.parentNode ) { + eventPath.push( cur ); + tmp = cur; + } + + // Only add window if we got to document (e.g., not plain obj or detached DOM) + if ( tmp === ( elem.ownerDocument || document ) ) { + eventPath.push( tmp.defaultView || tmp.parentWindow || window ); + } + } + + // Fire handlers on the event path + i = 0; + while ( ( cur = eventPath[ i++ ] ) && !event.isPropagationStopped() ) { + lastElement = cur; + event.type = i > 1 ? + bubbleType : + special.bindType || type; + + // jQuery handler + handle = ( + dataPriv.get( cur, "events" ) || Object.create( null ) + )[ event.type ] && + dataPriv.get( cur, "handle" ); + if ( handle ) { + handle.apply( cur, data ); + } + + // Native handler + handle = ontype && cur[ ontype ]; + if ( handle && handle.apply && acceptData( cur ) ) { + event.result = handle.apply( cur, data ); + if ( event.result === false ) { + event.preventDefault(); + } + } + } + event.type = type; + + // If nobody prevented the default action, do it now + if ( !onlyHandlers && !event.isDefaultPrevented() ) { + + if ( ( !special._default || + special._default.apply( eventPath.pop(), data ) === false ) && + acceptData( elem ) ) { + + // Call a native DOM method on the target with the same name as the event. + // Don't do default actions on window, that's where global variables be (#6170) + if ( ontype && isFunction( elem[ type ] ) && !isWindow( elem ) ) { + + // Don't re-trigger an onFOO event when we call its FOO() method + tmp = elem[ ontype ]; + + if ( tmp ) { + elem[ ontype ] = null; + } + + // Prevent re-triggering of the same event, since we already bubbled it above + jQuery.event.triggered = type; + + if ( event.isPropagationStopped() ) { + lastElement.addEventListener( type, stopPropagationCallback ); + } + + elem[ type ](); + + if ( event.isPropagationStopped() ) { + lastElement.removeEventListener( type, stopPropagationCallback ); + } + + jQuery.event.triggered = undefined; + + if ( tmp ) { + elem[ ontype ] = tmp; + } + } + } + } + + return event.result; + }, + + // Piggyback on a donor event to simulate a different one + // Used only for `focus(in | out)` events + simulate: function( type, elem, event ) { + var e = jQuery.extend( + new jQuery.Event(), + event, + { + type: type, + isSimulated: true + } + ); + + jQuery.event.trigger( e, null, elem ); + } + +} ); + +jQuery.fn.extend( { + + trigger: function( type, data ) { + return this.each( function() { + jQuery.event.trigger( type, data, this ); + } ); + }, + triggerHandler: function( type, data ) { + var elem = this[ 0 ]; + if ( elem ) { + return jQuery.event.trigger( type, data, elem, true ); + } + } +} ); + + +// Support: Firefox <=44 +// Firefox doesn't have focus(in | out) events +// Related ticket - https://bugzilla.mozilla.org/show_bug.cgi?id=687787 +// +// Support: Chrome <=48 - 49, Safari <=9.0 - 9.1 +// focus(in | out) events fire after focus & blur events, +// which is spec violation - http://www.w3.org/TR/DOM-Level-3-Events/#events-focusevent-event-order +// Related ticket - https://bugs.chromium.org/p/chromium/issues/detail?id=449857 +if ( !support.focusin ) { + jQuery.each( { focus: "focusin", blur: "focusout" }, function( orig, fix ) { + + // Attach a single capturing handler on the document while someone wants focusin/focusout + var handler = function( event ) { + jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ) ); + }; + + jQuery.event.special[ fix ] = { + setup: function() { + + // Handle: regular nodes (via `this.ownerDocument`), window + // (via `this.document`) & document (via `this`). + var doc = this.ownerDocument || this.document || this, + attaches = dataPriv.access( doc, fix ); + + if ( !attaches ) { + doc.addEventListener( orig, handler, true ); + } + dataPriv.access( doc, fix, ( attaches || 0 ) + 1 ); + }, + teardown: function() { + var doc = this.ownerDocument || this.document || this, + attaches = dataPriv.access( doc, fix ) - 1; + + if ( !attaches ) { + doc.removeEventListener( orig, handler, true ); + dataPriv.remove( doc, fix ); + + } else { + dataPriv.access( doc, fix, attaches ); + } + } + }; + } ); +} +var location = window.location; + +var nonce = { guid: Date.now() }; + +var rquery = ( /\?/ ); + + + +// Cross-browser xml parsing +jQuery.parseXML = function( data ) { + var xml; + if ( !data || typeof data !== "string" ) { + return null; + } + + // Support: IE 9 - 11 only + // IE throws on parseFromString with invalid input. + try { + xml = ( new window.DOMParser() ).parseFromString( data, "text/xml" ); + } catch ( e ) { + xml = undefined; + } + + if ( !xml || xml.getElementsByTagName( "parsererror" ).length ) { + jQuery.error( "Invalid XML: " + data ); + } + return xml; +}; + + +var + rbracket = /\[\]$/, + rCRLF = /\r?\n/g, + rsubmitterTypes = /^(?:submit|button|image|reset|file)$/i, + rsubmittable = /^(?:input|select|textarea|keygen)/i; + +function buildParams( prefix, obj, traditional, add ) { + var name; + + if ( Array.isArray( obj ) ) { + + // Serialize array item. + jQuery.each( obj, function( i, v ) { + if ( traditional || rbracket.test( prefix ) ) { + + // Treat each array item as a scalar. + add( prefix, v ); + + } else { + + // Item is non-scalar (array or object), encode its numeric index. + buildParams( + prefix + "[" + ( typeof v === "object" && v != null ? i : "" ) + "]", + v, + traditional, + add + ); + } + } ); + + } else if ( !traditional && toType( obj ) === "object" ) { + + // Serialize object item. + for ( name in obj ) { + buildParams( prefix + "[" + name + "]", obj[ name ], traditional, add ); + } + + } else { + + // Serialize scalar item. + add( prefix, obj ); + } +} + +// Serialize an array of form elements or a set of +// key/values into a query string +jQuery.param = function( a, traditional ) { + var prefix, + s = [], + add = function( key, valueOrFunction ) { + + // If value is a function, invoke it and use its return value + var value = isFunction( valueOrFunction ) ? + valueOrFunction() : + valueOrFunction; + + s[ s.length ] = encodeURIComponent( key ) + "=" + + encodeURIComponent( value == null ? "" : value ); + }; + + if ( a == null ) { + return ""; + } + + // If an array was passed in, assume that it is an array of form elements. + if ( Array.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) { + + // Serialize the form elements + jQuery.each( a, function() { + add( this.name, this.value ); + } ); + + } else { + + // If traditional, encode the "old" way (the way 1.3.2 or older + // did it), otherwise encode params recursively. + for ( prefix in a ) { + buildParams( prefix, a[ prefix ], traditional, add ); + } + } + + // Return the resulting serialization + return s.join( "&" ); +}; + +jQuery.fn.extend( { + serialize: function() { + return jQuery.param( this.serializeArray() ); + }, + serializeArray: function() { + return this.map( function() { + + // Can add propHook for "elements" to filter or add form elements + var elements = jQuery.prop( this, "elements" ); + return elements ? jQuery.makeArray( elements ) : this; + } ) + .filter( function() { + var type = this.type; + + // Use .is( ":disabled" ) so that fieldset[disabled] works + return this.name && !jQuery( this ).is( ":disabled" ) && + rsubmittable.test( this.nodeName ) && !rsubmitterTypes.test( type ) && + ( this.checked || !rcheckableType.test( type ) ); + } ) + .map( function( _i, elem ) { + var val = jQuery( this ).val(); + + if ( val == null ) { + return null; + } + + if ( Array.isArray( val ) ) { + return jQuery.map( val, function( val ) { + return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) }; + } ); + } + + return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) }; + } ).get(); + } +} ); + + +var + r20 = /%20/g, + rhash = /#.*$/, + rantiCache = /([?&])_=[^&]*/, + rheaders = /^(.*?):[ \t]*([^\r\n]*)$/mg, + + // #7653, #8125, #8152: local protocol detection + rlocalProtocol = /^(?:about|app|app-storage|.+-extension|file|res|widget):$/, + rnoContent = /^(?:GET|HEAD)$/, + rprotocol = /^\/\//, + + /* Prefilters + * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example) + * 2) These are called: + * - BEFORE asking for a transport + * - AFTER param serialization (s.data is a string if s.processData is true) + * 3) key is the dataType + * 4) the catchall symbol "*" can be used + * 5) execution will start with transport dataType and THEN continue down to "*" if needed + */ + prefilters = {}, + + /* Transports bindings + * 1) key is the dataType + * 2) the catchall symbol "*" can be used + * 3) selection will start with transport dataType and THEN go to "*" if needed + */ + transports = {}, + + // Avoid comment-prolog char sequence (#10098); must appease lint and evade compression + allTypes = "*/".concat( "*" ), + + // Anchor tag for parsing the document origin + originAnchor = document.createElement( "a" ); + originAnchor.href = location.href; + +// Base "constructor" for jQuery.ajaxPrefilter and jQuery.ajaxTransport +function addToPrefiltersOrTransports( structure ) { + + // dataTypeExpression is optional and defaults to "*" + return function( dataTypeExpression, func ) { + + if ( typeof dataTypeExpression !== "string" ) { + func = dataTypeExpression; + dataTypeExpression = "*"; + } + + var dataType, + i = 0, + dataTypes = dataTypeExpression.toLowerCase().match( rnothtmlwhite ) || []; + + if ( isFunction( func ) ) { + + // For each dataType in the dataTypeExpression + while ( ( dataType = dataTypes[ i++ ] ) ) { + + // Prepend if requested + if ( dataType[ 0 ] === "+" ) { + dataType = dataType.slice( 1 ) || "*"; + ( structure[ dataType ] = structure[ dataType ] || [] ).unshift( func ); + + // Otherwise append + } else { + ( structure[ dataType ] = structure[ dataType ] || [] ).push( func ); + } + } + } + }; +} + +// Base inspection function for prefilters and transports +function inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR ) { + + var inspected = {}, + seekingTransport = ( structure === transports ); + + function inspect( dataType ) { + var selected; + inspected[ dataType ] = true; + jQuery.each( structure[ dataType ] || [], function( _, prefilterOrFactory ) { + var dataTypeOrTransport = prefilterOrFactory( options, originalOptions, jqXHR ); + if ( typeof dataTypeOrTransport === "string" && + !seekingTransport && !inspected[ dataTypeOrTransport ] ) { + + options.dataTypes.unshift( dataTypeOrTransport ); + inspect( dataTypeOrTransport ); + return false; + } else if ( seekingTransport ) { + return !( selected = dataTypeOrTransport ); + } + } ); + return selected; + } + + return inspect( options.dataTypes[ 0 ] ) || !inspected[ "*" ] && inspect( "*" ); +} + +// A special extend for ajax options +// that takes "flat" options (not to be deep extended) +// Fixes #9887 +function ajaxExtend( target, src ) { + var key, deep, + flatOptions = jQuery.ajaxSettings.flatOptions || {}; + + for ( key in src ) { + if ( src[ key ] !== undefined ) { + ( flatOptions[ key ] ? target : ( deep || ( deep = {} ) ) )[ key ] = src[ key ]; + } + } + if ( deep ) { + jQuery.extend( true, target, deep ); + } + + return target; +} + +/* Handles responses to an ajax request: + * - finds the right dataType (mediates between content-type and expected dataType) + * - returns the corresponding response + */ +function ajaxHandleResponses( s, jqXHR, responses ) { + + var ct, type, finalDataType, firstDataType, + contents = s.contents, + dataTypes = s.dataTypes; + + // Remove auto dataType and get content-type in the process + while ( dataTypes[ 0 ] === "*" ) { + dataTypes.shift(); + if ( ct === undefined ) { + ct = s.mimeType || jqXHR.getResponseHeader( "Content-Type" ); + } + } + + // Check if we're dealing with a known content-type + if ( ct ) { + for ( type in contents ) { + if ( contents[ type ] && contents[ type ].test( ct ) ) { + dataTypes.unshift( type ); + break; + } + } + } + + // Check to see if we have a response for the expected dataType + if ( dataTypes[ 0 ] in responses ) { + finalDataType = dataTypes[ 0 ]; + } else { + + // Try convertible dataTypes + for ( type in responses ) { + if ( !dataTypes[ 0 ] || s.converters[ type + " " + dataTypes[ 0 ] ] ) { + finalDataType = type; + break; + } + if ( !firstDataType ) { + firstDataType = type; + } + } + + // Or just use first one + finalDataType = finalDataType || firstDataType; + } + + // If we found a dataType + // We add the dataType to the list if needed + // and return the corresponding response + if ( finalDataType ) { + if ( finalDataType !== dataTypes[ 0 ] ) { + dataTypes.unshift( finalDataType ); + } + return responses[ finalDataType ]; + } +} + +/* Chain conversions given the request and the original response + * Also sets the responseXXX fields on the jqXHR instance + */ +function ajaxConvert( s, response, jqXHR, isSuccess ) { + var conv2, current, conv, tmp, prev, + converters = {}, + + // Work with a copy of dataTypes in case we need to modify it for conversion + dataTypes = s.dataTypes.slice(); + + // Create converters map with lowercased keys + if ( dataTypes[ 1 ] ) { + for ( conv in s.converters ) { + converters[ conv.toLowerCase() ] = s.converters[ conv ]; + } + } + + current = dataTypes.shift(); + + // Convert to each sequential dataType + while ( current ) { + + if ( s.responseFields[ current ] ) { + jqXHR[ s.responseFields[ current ] ] = response; + } + + // Apply the dataFilter if provided + if ( !prev && isSuccess && s.dataFilter ) { + response = s.dataFilter( response, s.dataType ); + } + + prev = current; + current = dataTypes.shift(); + + if ( current ) { + + // There's only work to do if current dataType is non-auto + if ( current === "*" ) { + + current = prev; + + // Convert response if prev dataType is non-auto and differs from current + } else if ( prev !== "*" && prev !== current ) { + + // Seek a direct converter + conv = converters[ prev + " " + current ] || converters[ "* " + current ]; + + // If none found, seek a pair + if ( !conv ) { + for ( conv2 in converters ) { + + // If conv2 outputs current + tmp = conv2.split( " " ); + if ( tmp[ 1 ] === current ) { + + // If prev can be converted to accepted input + conv = converters[ prev + " " + tmp[ 0 ] ] || + converters[ "* " + tmp[ 0 ] ]; + if ( conv ) { + + // Condense equivalence converters + if ( conv === true ) { + conv = converters[ conv2 ]; + + // Otherwise, insert the intermediate dataType + } else if ( converters[ conv2 ] !== true ) { + current = tmp[ 0 ]; + dataTypes.unshift( tmp[ 1 ] ); + } + break; + } + } + } + } + + // Apply converter (if not an equivalence) + if ( conv !== true ) { + + // Unless errors are allowed to bubble, catch and return them + if ( conv && s.throws ) { + response = conv( response ); + } else { + try { + response = conv( response ); + } catch ( e ) { + return { + state: "parsererror", + error: conv ? e : "No conversion from " + prev + " to " + current + }; + } + } + } + } + } + } + + return { state: "success", data: response }; +} + +jQuery.extend( { + + // Counter for holding the number of active queries + active: 0, + + // Last-Modified header cache for next request + lastModified: {}, + etag: {}, + + ajaxSettings: { + url: location.href, + type: "GET", + isLocal: rlocalProtocol.test( location.protocol ), + global: true, + processData: true, + async: true, + contentType: "application/x-www-form-urlencoded; charset=UTF-8", + + /* + timeout: 0, + data: null, + dataType: null, + username: null, + password: null, + cache: null, + throws: false, + traditional: false, + headers: {}, + */ + + accepts: { + "*": allTypes, + text: "text/plain", + html: "text/html", + xml: "application/xml, text/xml", + json: "application/json, text/javascript" + }, + + contents: { + xml: /\bxml\b/, + html: /\bhtml/, + json: /\bjson\b/ + }, + + responseFields: { + xml: "responseXML", + text: "responseText", + json: "responseJSON" + }, + + // Data converters + // Keys separate source (or catchall "*") and destination types with a single space + converters: { + + // Convert anything to text + "* text": String, + + // Text to html (true = no transformation) + "text html": true, + + // Evaluate text as a json expression + "text json": JSON.parse, + + // Parse text as xml + "text xml": jQuery.parseXML + }, + + // For options that shouldn't be deep extended: + // you can add your own custom options here if + // and when you create one that shouldn't be + // deep extended (see ajaxExtend) + flatOptions: { + url: true, + context: true + } + }, + + // Creates a full fledged settings object into target + // with both ajaxSettings and settings fields. + // If target is omitted, writes into ajaxSettings. + ajaxSetup: function( target, settings ) { + return settings ? + + // Building a settings object + ajaxExtend( ajaxExtend( target, jQuery.ajaxSettings ), settings ) : + + // Extending ajaxSettings + ajaxExtend( jQuery.ajaxSettings, target ); + }, + + ajaxPrefilter: addToPrefiltersOrTransports( prefilters ), + ajaxTransport: addToPrefiltersOrTransports( transports ), + + // Main method + ajax: function( url, options ) { + + // If url is an object, simulate pre-1.5 signature + if ( typeof url === "object" ) { + options = url; + url = undefined; + } + + // Force options to be an object + options = options || {}; + + var transport, + + // URL without anti-cache param + cacheURL, + + // Response headers + responseHeadersString, + responseHeaders, + + // timeout handle + timeoutTimer, + + // Url cleanup var + urlAnchor, + + // Request state (becomes false upon send and true upon completion) + completed, + + // To know if global events are to be dispatched + fireGlobals, + + // Loop variable + i, + + // uncached part of the url + uncached, + + // Create the final options object + s = jQuery.ajaxSetup( {}, options ), + + // Callbacks context + callbackContext = s.context || s, + + // Context for global events is callbackContext if it is a DOM node or jQuery collection + globalEventContext = s.context && + ( callbackContext.nodeType || callbackContext.jquery ) ? + jQuery( callbackContext ) : + jQuery.event, + + // Deferreds + deferred = jQuery.Deferred(), + completeDeferred = jQuery.Callbacks( "once memory" ), + + // Status-dependent callbacks + statusCode = s.statusCode || {}, + + // Headers (they are sent all at once) + requestHeaders = {}, + requestHeadersNames = {}, + + // Default abort message + strAbort = "canceled", + + // Fake xhr + jqXHR = { + readyState: 0, + + // Builds headers hashtable if needed + getResponseHeader: function( key ) { + var match; + if ( completed ) { + if ( !responseHeaders ) { + responseHeaders = {}; + while ( ( match = rheaders.exec( responseHeadersString ) ) ) { + responseHeaders[ match[ 1 ].toLowerCase() + " " ] = + ( responseHeaders[ match[ 1 ].toLowerCase() + " " ] || [] ) + .concat( match[ 2 ] ); + } + } + match = responseHeaders[ key.toLowerCase() + " " ]; + } + return match == null ? null : match.join( ", " ); + }, + + // Raw string + getAllResponseHeaders: function() { + return completed ? responseHeadersString : null; + }, + + // Caches the header + setRequestHeader: function( name, value ) { + if ( completed == null ) { + name = requestHeadersNames[ name.toLowerCase() ] = + requestHeadersNames[ name.toLowerCase() ] || name; + requestHeaders[ name ] = value; + } + return this; + }, + + // Overrides response content-type header + overrideMimeType: function( type ) { + if ( completed == null ) { + s.mimeType = type; + } + return this; + }, + + // Status-dependent callbacks + statusCode: function( map ) { + var code; + if ( map ) { + if ( completed ) { + + // Execute the appropriate callbacks + jqXHR.always( map[ jqXHR.status ] ); + } else { + + // Lazy-add the new callbacks in a way that preserves old ones + for ( code in map ) { + statusCode[ code ] = [ statusCode[ code ], map[ code ] ]; + } + } + } + return this; + }, + + // Cancel the request + abort: function( statusText ) { + var finalText = statusText || strAbort; + if ( transport ) { + transport.abort( finalText ); + } + done( 0, finalText ); + return this; + } + }; + + // Attach deferreds + deferred.promise( jqXHR ); + + // Add protocol if not provided (prefilters might expect it) + // Handle falsy url in the settings object (#10093: consistency with old signature) + // We also use the url parameter if available + s.url = ( ( url || s.url || location.href ) + "" ) + .replace( rprotocol, location.protocol + "//" ); + + // Alias method option to type as per ticket #12004 + s.type = options.method || options.type || s.method || s.type; + + // Extract dataTypes list + s.dataTypes = ( s.dataType || "*" ).toLowerCase().match( rnothtmlwhite ) || [ "" ]; + + // A cross-domain request is in order when the origin doesn't match the current origin. + if ( s.crossDomain == null ) { + urlAnchor = document.createElement( "a" ); + + // Support: IE <=8 - 11, Edge 12 - 15 + // IE throws exception on accessing the href property if url is malformed, + // e.g. http://example.com:80x/ + try { + urlAnchor.href = s.url; + + // Support: IE <=8 - 11 only + // Anchor's host property isn't correctly set when s.url is relative + urlAnchor.href = urlAnchor.href; + s.crossDomain = originAnchor.protocol + "//" + originAnchor.host !== + urlAnchor.protocol + "//" + urlAnchor.host; + } catch ( e ) { + + // If there is an error parsing the URL, assume it is crossDomain, + // it can be rejected by the transport if it is invalid + s.crossDomain = true; + } + } + + // Convert data if not already a string + if ( s.data && s.processData && typeof s.data !== "string" ) { + s.data = jQuery.param( s.data, s.traditional ); + } + + // Apply prefilters + inspectPrefiltersOrTransports( prefilters, s, options, jqXHR ); + + // If request was aborted inside a prefilter, stop there + if ( completed ) { + return jqXHR; + } + + // We can fire global events as of now if asked to + // Don't fire events if jQuery.event is undefined in an AMD-usage scenario (#15118) + fireGlobals = jQuery.event && s.global; + + // Watch for a new set of requests + if ( fireGlobals && jQuery.active++ === 0 ) { + jQuery.event.trigger( "ajaxStart" ); + } + + // Uppercase the type + s.type = s.type.toUpperCase(); + + // Determine if request has content + s.hasContent = !rnoContent.test( s.type ); + + // Save the URL in case we're toying with the If-Modified-Since + // and/or If-None-Match header later on + // Remove hash to simplify url manipulation + cacheURL = s.url.replace( rhash, "" ); + + // More options handling for requests with no content + if ( !s.hasContent ) { + + // Remember the hash so we can put it back + uncached = s.url.slice( cacheURL.length ); + + // If data is available and should be processed, append data to url + if ( s.data && ( s.processData || typeof s.data === "string" ) ) { + cacheURL += ( rquery.test( cacheURL ) ? "&" : "?" ) + s.data; + + // #9682: remove data so that it's not used in an eventual retry + delete s.data; + } + + // Add or update anti-cache param if needed + if ( s.cache === false ) { + cacheURL = cacheURL.replace( rantiCache, "$1" ); + uncached = ( rquery.test( cacheURL ) ? "&" : "?" ) + "_=" + ( nonce.guid++ ) + + uncached; + } + + // Put hash and anti-cache on the URL that will be requested (gh-1732) + s.url = cacheURL + uncached; + + // Change '%20' to '+' if this is encoded form body content (gh-2658) + } else if ( s.data && s.processData && + ( s.contentType || "" ).indexOf( "application/x-www-form-urlencoded" ) === 0 ) { + s.data = s.data.replace( r20, "+" ); + } + + // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode. + if ( s.ifModified ) { + if ( jQuery.lastModified[ cacheURL ] ) { + jqXHR.setRequestHeader( "If-Modified-Since", jQuery.lastModified[ cacheURL ] ); + } + if ( jQuery.etag[ cacheURL ] ) { + jqXHR.setRequestHeader( "If-None-Match", jQuery.etag[ cacheURL ] ); + } + } + + // Set the correct header, if data is being sent + if ( s.data && s.hasContent && s.contentType !== false || options.contentType ) { + jqXHR.setRequestHeader( "Content-Type", s.contentType ); + } + + // Set the Accepts header for the server, depending on the dataType + jqXHR.setRequestHeader( + "Accept", + s.dataTypes[ 0 ] && s.accepts[ s.dataTypes[ 0 ] ] ? + s.accepts[ s.dataTypes[ 0 ] ] + + ( s.dataTypes[ 0 ] !== "*" ? ", " + allTypes + "; q=0.01" : "" ) : + s.accepts[ "*" ] + ); + + // Check for headers option + for ( i in s.headers ) { + jqXHR.setRequestHeader( i, s.headers[ i ] ); + } + + // Allow custom headers/mimetypes and early abort + if ( s.beforeSend && + ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || completed ) ) { + + // Abort if not done already and return + return jqXHR.abort(); + } + + // Aborting is no longer a cancellation + strAbort = "abort"; + + // Install callbacks on deferreds + completeDeferred.add( s.complete ); + jqXHR.done( s.success ); + jqXHR.fail( s.error ); + + // Get transport + transport = inspectPrefiltersOrTransports( transports, s, options, jqXHR ); + + // If no transport, we auto-abort + if ( !transport ) { + done( -1, "No Transport" ); + } else { + jqXHR.readyState = 1; + + // Send global event + if ( fireGlobals ) { + globalEventContext.trigger( "ajaxSend", [ jqXHR, s ] ); + } + + // If request was aborted inside ajaxSend, stop there + if ( completed ) { + return jqXHR; + } + + // Timeout + if ( s.async && s.timeout > 0 ) { + timeoutTimer = window.setTimeout( function() { + jqXHR.abort( "timeout" ); + }, s.timeout ); + } + + try { + completed = false; + transport.send( requestHeaders, done ); + } catch ( e ) { + + // Rethrow post-completion exceptions + if ( completed ) { + throw e; + } + + // Propagate others as results + done( -1, e ); + } + } + + // Callback for when everything is done + function done( status, nativeStatusText, responses, headers ) { + var isSuccess, success, error, response, modified, + statusText = nativeStatusText; + + // Ignore repeat invocations + if ( completed ) { + return; + } + + completed = true; + + // Clear timeout if it exists + if ( timeoutTimer ) { + window.clearTimeout( timeoutTimer ); + } + + // Dereference transport for early garbage collection + // (no matter how long the jqXHR object will be used) + transport = undefined; + + // Cache response headers + responseHeadersString = headers || ""; + + // Set readyState + jqXHR.readyState = status > 0 ? 4 : 0; + + // Determine if successful + isSuccess = status >= 200 && status < 300 || status === 304; + + // Get response data + if ( responses ) { + response = ajaxHandleResponses( s, jqXHR, responses ); + } + + // Use a noop converter for missing script + if ( !isSuccess && jQuery.inArray( "script", s.dataTypes ) > -1 ) { + s.converters[ "text script" ] = function() {}; + } + + // Convert no matter what (that way responseXXX fields are always set) + response = ajaxConvert( s, response, jqXHR, isSuccess ); + + // If successful, handle type chaining + if ( isSuccess ) { + + // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode. + if ( s.ifModified ) { + modified = jqXHR.getResponseHeader( "Last-Modified" ); + if ( modified ) { + jQuery.lastModified[ cacheURL ] = modified; + } + modified = jqXHR.getResponseHeader( "etag" ); + if ( modified ) { + jQuery.etag[ cacheURL ] = modified; + } + } + + // if no content + if ( status === 204 || s.type === "HEAD" ) { + statusText = "nocontent"; + + // if not modified + } else if ( status === 304 ) { + statusText = "notmodified"; + + // If we have data, let's convert it + } else { + statusText = response.state; + success = response.data; + error = response.error; + isSuccess = !error; + } + } else { + + // Extract error from statusText and normalize for non-aborts + error = statusText; + if ( status || !statusText ) { + statusText = "error"; + if ( status < 0 ) { + status = 0; + } + } + } + + // Set data for the fake xhr object + jqXHR.status = status; + jqXHR.statusText = ( nativeStatusText || statusText ) + ""; + + // Success/Error + if ( isSuccess ) { + deferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] ); + } else { + deferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] ); + } + + // Status-dependent callbacks + jqXHR.statusCode( statusCode ); + statusCode = undefined; + + if ( fireGlobals ) { + globalEventContext.trigger( isSuccess ? "ajaxSuccess" : "ajaxError", + [ jqXHR, s, isSuccess ? success : error ] ); + } + + // Complete + completeDeferred.fireWith( callbackContext, [ jqXHR, statusText ] ); + + if ( fireGlobals ) { + globalEventContext.trigger( "ajaxComplete", [ jqXHR, s ] ); + + // Handle the global AJAX counter + if ( !( --jQuery.active ) ) { + jQuery.event.trigger( "ajaxStop" ); + } + } + } + + return jqXHR; + }, + + getJSON: function( url, data, callback ) { + return jQuery.get( url, data, callback, "json" ); + }, + + getScript: function( url, callback ) { + return jQuery.get( url, undefined, callback, "script" ); + } +} ); + +jQuery.each( [ "get", "post" ], function( _i, method ) { + jQuery[ method ] = function( url, data, callback, type ) { + + // Shift arguments if data argument was omitted + if ( isFunction( data ) ) { + type = type || callback; + callback = data; + data = undefined; + } + + // The url can be an options object (which then must have .url) + return jQuery.ajax( jQuery.extend( { + url: url, + type: method, + dataType: type, + data: data, + success: callback + }, jQuery.isPlainObject( url ) && url ) ); + }; +} ); + +jQuery.ajaxPrefilter( function( s ) { + var i; + for ( i in s.headers ) { + if ( i.toLowerCase() === "content-type" ) { + s.contentType = s.headers[ i ] || ""; + } + } +} ); + + +jQuery._evalUrl = function( url, options, doc ) { + return jQuery.ajax( { + url: url, + + // Make this explicit, since user can override this through ajaxSetup (#11264) + type: "GET", + dataType: "script", + cache: true, + async: false, + global: false, + + // Only evaluate the response if it is successful (gh-4126) + // dataFilter is not invoked for failure responses, so using it instead + // of the default converter is kludgy but it works. + converters: { + "text script": function() {} + }, + dataFilter: function( response ) { + jQuery.globalEval( response, options, doc ); + } + } ); +}; + + +jQuery.fn.extend( { + wrapAll: function( html ) { + var wrap; + + if ( this[ 0 ] ) { + if ( isFunction( html ) ) { + html = html.call( this[ 0 ] ); + } + + // The elements to wrap the target around + wrap = jQuery( html, this[ 0 ].ownerDocument ).eq( 0 ).clone( true ); + + if ( this[ 0 ].parentNode ) { + wrap.insertBefore( this[ 0 ] ); + } + + wrap.map( function() { + var elem = this; + + while ( elem.firstElementChild ) { + elem = elem.firstElementChild; + } + + return elem; + } ).append( this ); + } + + return this; + }, + + wrapInner: function( html ) { + if ( isFunction( html ) ) { + return this.each( function( i ) { + jQuery( this ).wrapInner( html.call( this, i ) ); + } ); + } + + return this.each( function() { + var self = jQuery( this ), + contents = self.contents(); + + if ( contents.length ) { + contents.wrapAll( html ); + + } else { + self.append( html ); + } + } ); + }, + + wrap: function( html ) { + var htmlIsFunction = isFunction( html ); + + return this.each( function( i ) { + jQuery( this ).wrapAll( htmlIsFunction ? html.call( this, i ) : html ); + } ); + }, + + unwrap: function( selector ) { + this.parent( selector ).not( "body" ).each( function() { + jQuery( this ).replaceWith( this.childNodes ); + } ); + return this; + } +} ); + + +jQuery.expr.pseudos.hidden = function( elem ) { + return !jQuery.expr.pseudos.visible( elem ); +}; +jQuery.expr.pseudos.visible = function( elem ) { + return !!( elem.offsetWidth || elem.offsetHeight || elem.getClientRects().length ); +}; + + + + +jQuery.ajaxSettings.xhr = function() { + try { + return new window.XMLHttpRequest(); + } catch ( e ) {} +}; + +var xhrSuccessStatus = { + + // File protocol always yields status code 0, assume 200 + 0: 200, + + // Support: IE <=9 only + // #1450: sometimes IE returns 1223 when it should be 204 + 1223: 204 + }, + xhrSupported = jQuery.ajaxSettings.xhr(); + +support.cors = !!xhrSupported && ( "withCredentials" in xhrSupported ); +support.ajax = xhrSupported = !!xhrSupported; + +jQuery.ajaxTransport( function( options ) { + var callback, errorCallback; + + // Cross domain only allowed if supported through XMLHttpRequest + if ( support.cors || xhrSupported && !options.crossDomain ) { + return { + send: function( headers, complete ) { + var i, + xhr = options.xhr(); + + xhr.open( + options.type, + options.url, + options.async, + options.username, + options.password + ); + + // Apply custom fields if provided + if ( options.xhrFields ) { + for ( i in options.xhrFields ) { + xhr[ i ] = options.xhrFields[ i ]; + } + } + + // Override mime type if needed + if ( options.mimeType && xhr.overrideMimeType ) { + xhr.overrideMimeType( options.mimeType ); + } + + // X-Requested-With header + // For cross-domain requests, seeing as conditions for a preflight are + // akin to a jigsaw puzzle, we simply never set it to be sure. + // (it can always be set on a per-request basis or even using ajaxSetup) + // For same-domain requests, won't change header if already provided. + if ( !options.crossDomain && !headers[ "X-Requested-With" ] ) { + headers[ "X-Requested-With" ] = "XMLHttpRequest"; + } + + // Set headers + for ( i in headers ) { + xhr.setRequestHeader( i, headers[ i ] ); + } + + // Callback + callback = function( type ) { + return function() { + if ( callback ) { + callback = errorCallback = xhr.onload = + xhr.onerror = xhr.onabort = xhr.ontimeout = + xhr.onreadystatechange = null; + + if ( type === "abort" ) { + xhr.abort(); + } else if ( type === "error" ) { + + // Support: IE <=9 only + // On a manual native abort, IE9 throws + // errors on any property access that is not readyState + if ( typeof xhr.status !== "number" ) { + complete( 0, "error" ); + } else { + complete( + + // File: protocol always yields status 0; see #8605, #14207 + xhr.status, + xhr.statusText + ); + } + } else { + complete( + xhrSuccessStatus[ xhr.status ] || xhr.status, + xhr.statusText, + + // Support: IE <=9 only + // IE9 has no XHR2 but throws on binary (trac-11426) + // For XHR2 non-text, let the caller handle it (gh-2498) + ( xhr.responseType || "text" ) !== "text" || + typeof xhr.responseText !== "string" ? + { binary: xhr.response } : + { text: xhr.responseText }, + xhr.getAllResponseHeaders() + ); + } + } + }; + }; + + // Listen to events + xhr.onload = callback(); + errorCallback = xhr.onerror = xhr.ontimeout = callback( "error" ); + + // Support: IE 9 only + // Use onreadystatechange to replace onabort + // to handle uncaught aborts + if ( xhr.onabort !== undefined ) { + xhr.onabort = errorCallback; + } else { + xhr.onreadystatechange = function() { + + // Check readyState before timeout as it changes + if ( xhr.readyState === 4 ) { + + // Allow onerror to be called first, + // but that will not handle a native abort + // Also, save errorCallback to a variable + // as xhr.onerror cannot be accessed + window.setTimeout( function() { + if ( callback ) { + errorCallback(); + } + } ); + } + }; + } + + // Create the abort callback + callback = callback( "abort" ); + + try { + + // Do send the request (this may raise an exception) + xhr.send( options.hasContent && options.data || null ); + } catch ( e ) { + + // #14683: Only rethrow if this hasn't been notified as an error yet + if ( callback ) { + throw e; + } + } + }, + + abort: function() { + if ( callback ) { + callback(); + } + } + }; + } +} ); + + + + +// Prevent auto-execution of scripts when no explicit dataType was provided (See gh-2432) +jQuery.ajaxPrefilter( function( s ) { + if ( s.crossDomain ) { + s.contents.script = false; + } +} ); + +// Install script dataType +jQuery.ajaxSetup( { + accepts: { + script: "text/javascript, application/javascript, " + + "application/ecmascript, application/x-ecmascript" + }, + contents: { + script: /\b(?:java|ecma)script\b/ + }, + converters: { + "text script": function( text ) { + jQuery.globalEval( text ); + return text; + } + } +} ); + +// Handle cache's special case and crossDomain +jQuery.ajaxPrefilter( "script", function( s ) { + if ( s.cache === undefined ) { + s.cache = false; + } + if ( s.crossDomain ) { + s.type = "GET"; + } +} ); + +// Bind script tag hack transport +jQuery.ajaxTransport( "script", function( s ) { + + // This transport only deals with cross domain or forced-by-attrs requests + if ( s.crossDomain || s.scriptAttrs ) { + var script, callback; + return { + send: function( _, complete ) { + script = jQuery( " + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra - Exceptions and Enums

+
+
+cassandra.__version_info__
+

The version of the driver in a tuple format

+
+ +
+
+cassandra.__version__
+

The version of the driver in a string format

+
+ +
+
+class cassandra.ConsistencyLevel
+

Spcifies how many replicas must respond for an operation to be considered +a success. By default, ONE is used for all operations.

+
+
+ANY = 0
+

Only requires that one replica receives the write or the coordinator +stores a hint to replay later. Valid only for writes.

+
+ +
+
+ONE = 1
+

Only one replica needs to respond to consider the operation a success

+
+ +
+
+TWO = 2
+

Two replicas must respond to consider the operation a success

+
+ +
+
+THREE = 3
+

Three replicas must respond to consider the operation a success

+
+ +
+
+QUORUM = 4
+

ceil(RF/2) + 1 replicas must respond to consider the operation a success

+
+ +
+
+ALL = 5
+

All replicas must respond to consider the operation a success

+
+ +
+
+LOCAL_QUORUM = 6
+

Requires a quorum of replicas in the local datacenter

+
+ +
+
+EACH_QUORUM = 7
+

Requires a quorum of replicas in each datacenter

+
+ +
+
+SERIAL = 8
+

For conditional inserts/updates that utilize Cassandra’s lightweight +transactions, this requires consensus among all replicas for the +modified data.

+
+ +
+
+LOCAL_SERIAL = 9
+

Like SERIAL, but only requires consensus +among replicas in the local datacenter.

+
+ +
+
+LOCAL_ONE = 10
+

Sends a request only to replicas in the local datacenter and waits for +one response.

+
+ +
+ +
+
+class cassandra.ProtocolVersion
+

Defines native protocol versions supported by this driver.

+
+
+V1 = 1
+

v1, supported in Cassandra 1.2–>2.2

+
+ +
+
+V2 = 2
+

v2, supported in Cassandra 2.0–>2.2; +added support for lightweight transactions, batch operations, and automatic query paging.

+
+ +
+
+V3 = 3
+

v3, supported in Cassandra 2.1–>3.x+; +added support for protocol-level client-side timestamps (see Session.use_client_timestamp), +serial consistency levels for BatchStatement, and an improved connection pool.

+
+ +
+
+V4 = 4
+

v4, supported in Cassandra 2.2–>3.x+; +added a number of new types, server warnings, new failure messages, and custom payloads. Details in the +project docs

+
+ +
+
+V5 = 5
+

v5, in beta from 3.x+. Finalised in 4.0-beta5

+
+ +
+
+V6 = 6
+

v6, in beta from 4.0-beta5

+
+ +
+
+DSE_V1 = 65
+

DSE private protocol v1, supported in DSE 5.1+

+
+ +
+
+DSE_V2 = 66
+

DSE private protocol v2, supported in DSE 6.0+

+
+ +
+
+SUPPORTED_VERSIONS = (66, 65, 6, 5, 4, 3, 2, 1)
+

A tuple of all supported protocol versions

+
+ +
+
+BETA_VERSIONS = (6,)
+

A tuple of all beta protocol versions

+
+ +
+
+MIN_SUPPORTED = 1
+

Minimum protocol version supported by this driver.

+
+ +
+
+MAX_SUPPORTED = 66
+

Maximum protocol version supported by this driver.

+
+ +
+
+classmethod get_lower_supported(previous_version)
+

Return the lower supported protocol version. Beta versions are omitted.

+
+ +
+ +
+
+class cassandra.UserFunctionDescriptor(name, argument_types)
+

Describes a User function by name and argument signature

+
+
+name = None
+

name of the function

+
+ +
+
+argument_types = None
+

Ordered list of CQL argument type names comprising the type signature

+
+ +
+
+property signature
+

function signature string in the form ‘name([type0[,type1[…]]])’

+

can be used to uniquely identify overloaded function names within a keyspace

+
+ +
+ +
+
+class cassandra.UserAggregateDescriptor(name, argument_types)
+

Describes a User aggregate function by name and argument signature

+
+
+name = None
+

name of the aggregate

+
+ +
+
+argument_types = None
+

Ordered list of CQL argument type names comprising the type signature

+
+ +
+
+property signature
+

function signature string in the form ‘name([type0[,type1[…]]])’

+

can be used to uniquely identify overloaded function names within a keyspace

+
+ +
+ +
+
+exception cassandra.DriverException
+

Base for all exceptions explicitly raised by the driver.

+
+ +
+
+exception cassandra.RequestExecutionException
+

Base for request execution exceptions returned from the server.

+
+ +
+
+exception cassandra.Unavailable
+

There were not enough live replicas to satisfy the requested consistency +level, so the coordinator node immediately failed the request without +forwarding it to any replicas.

+
+
+consistency = None
+

The requested ConsistencyLevel

+
+ +
+
+required_replicas = None
+

The number of replicas that needed to be live to complete the operation

+
+ +
+
+alive_replicas = None
+

The number of replicas that were actually alive

+
+ +
+ +
+
+exception cassandra.Timeout
+

Replicas failed to respond to the coordinator node before timing out.

+
+
+consistency = None
+

The requested ConsistencyLevel

+
+ +
+
+required_responses = None
+

The number of required replica responses

+
+ +
+
+received_responses = None
+

The number of replicas that responded before the coordinator timed out +the operation

+
+ +
+ +
+
+exception cassandra.ReadTimeout
+

A subclass of Timeout for read operations.

+

This indicates that the replicas failed to respond to the coordinator +node before the configured timeout. This timeout is configured in +cassandra.yaml with the read_request_timeout_in_ms +and range_request_timeout_in_ms options.

+
+
+data_retrieved = None
+

A boolean indicating whether the requested data was retrieved +by the coordinator from any replicas before it timed out the +operation

+
+ +
+ +
+
+exception cassandra.WriteTimeout
+

A subclass of Timeout for write operations.

+

This indicates that the replicas failed to respond to the coordinator +node before the configured timeout. This timeout is configured in +cassandra.yaml with the write_request_timeout_in_ms +option.

+
+
+write_type = None
+

The type of write operation, enum on WriteType

+
+ +
+ +
+
+exception cassandra.CoordinationFailure
+

Replicas sent a failure to the coordinator.

+
+
+consistency = None
+

The requested ConsistencyLevel

+
+ +
+
+required_responses = None
+

The number of required replica responses

+
+ +
+
+received_responses = None
+

The number of replicas that responded before the coordinator timed out +the operation

+
+ +
+
+failures = None
+

The number of replicas that sent a failure message

+
+ +
+
+error_code_map = None
+

A map of inet addresses to error codes representing replicas that sent +a failure message. Only set when protocol_version is 5 or higher.

+
+ +
+ +
+
+exception cassandra.ReadFailure
+

A subclass of CoordinationFailure for read operations.

+

This indicates that the replicas sent a failure message to the coordinator.

+
+
+data_retrieved = None
+

A boolean indicating whether the requested data was retrieved +by the coordinator from any replicas before it timed out the +operation

+
+ +
+ +
+
+exception cassandra.WriteFailure
+

A subclass of CoordinationFailure for write operations.

+

This indicates that the replicas sent a failure message to the coordinator.

+
+
+write_type = None
+

The type of write operation, enum on WriteType

+
+ +
+ +
+
+exception cassandra.FunctionFailure
+

User Defined Function failed during execution

+
+
+keyspace = None
+

Keyspace of the function

+
+ +
+
+function = None
+

Name of the function

+
+ +
+
+arg_types = None
+

List of argument type names of the function

+
+ +
+ +
+
+exception cassandra.RequestValidationException
+

Server request validation failed

+
+ +
+
+exception cassandra.ConfigurationException
+

Server indicated request errro due to current configuration

+
+ +
+
+exception cassandra.AlreadyExists
+

An attempt was made to create a keyspace or table that already exists.

+
+
+keyspace = None
+

The name of the keyspace that already exists, or, if an attempt was +made to create a new table, the keyspace that the table is in.

+
+ +
+
+table = None
+

The name of the table that already exists, or, if an attempt was +make to create a keyspace, None.

+
+ +
+ +
+
+exception cassandra.InvalidRequest
+

A query was made that was invalid for some reason, such as trying to set +the keyspace for a connection to a nonexistent keyspace.

+
+ +
+
+exception cassandra.Unauthorized
+

The current user is not authorized to perform the requested operation.

+
+ +
+
+exception cassandra.AuthenticationFailed
+

Failed to authenticate.

+
+ +
+
+exception cassandra.OperationTimedOut
+

The operation took longer than the specified (client-side) timeout +to complete. This is not an error generated by Cassandra, only +the driver.

+
+
+errors = None
+

A dict of errors keyed by the Host against which they occurred.

+
+ +
+
+last_host = None
+

The last Host this operation was attempted against.

+
+ +
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.24.8-scylla/api/cassandra/auth.html b/3.24.8-scylla/api/cassandra/auth.html new file mode 100644 index 0000000000..79131a51c5 --- /dev/null +++ b/3.24.8-scylla/api/cassandra/auth.html @@ -0,0 +1,806 @@ + + + + + + + + + + + + + cassandra.auth - Authentication | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.auth - Authentication

+
+
+class cassandra.auth.AuthProvider
+

An abstract class that defines the interface that will be used for +creating Authenticator instances when opening new +connections to Cassandra.

+
+

New in version 2.0.0.

+
+
+
+new_authenticator(host)
+

Implementations of this class should return a new instance +of Authenticator or one of its subclasses.

+
+ +
+ +
+
+class cassandra.auth.Authenticator
+

An abstract class that handles SASL authentication with Cassandra servers.

+

Each time a new connection is created and the server requires authentication, +a new instance of this class will be created by the corresponding +AuthProvider to handler that authentication. The lifecycle of the +new Authenticator will the be:

+

1) The initial_response() method will be called. The return +value will be sent to the server to initiate the handshake.

+

2) The server will respond to each client response by either issuing a +challenge or indicating that the authentication is complete (successful or not). +If a new challenge is issued, evaluate_challenge() +will be called to produce a response that will be sent to the +server. This challenge/response negotiation will continue until the server +responds that authentication is successful (or an AuthenticationFailed +is raised).

+

3) When the server indicates that authentication is successful, +on_authentication_success() will be called a token string that +that the server may optionally have sent.

+

The exact nature of the negotiation between the client and server is specific +to the authentication mechanism configured server-side.

+
+

New in version 2.0.0.

+
+
+
+server_authenticator_class = None
+

Set during the connection AUTHENTICATE phase

+
+ +
+
+initial_response()
+

Returns an message to send to the server to initiate the SASL handshake. +None may be returned to send an empty message.

+
+ +
+
+evaluate_challenge(challenge)
+

Called when the server sends a challenge message. Generally, this method +should return None when authentication is complete from a +client perspective. Otherwise, a string should be returned.

+
+ +
+
+on_authentication_success(token)
+

Called when the server indicates that authentication was successful. +Depending on the authentication mechanism, token may be None +or a string.

+
+ +
+ +
+
+class cassandra.auth.PlainTextAuthProvider(username, password)
+

An AuthProvider that works with Cassandra’s PasswordAuthenticator.

+

Example usage:

+
from cassandra.cluster import Cluster
+from cassandra.auth import PlainTextAuthProvider
+
+auth_provider = PlainTextAuthProvider(
+        username='cassandra', password='cassandra')
+cluster = Cluster(auth_provider=auth_provider)
+
+
+
+

New in version 2.0.0.

+
+
+
+new_authenticator(host)
+

Implementations of this class should return a new instance +of Authenticator or one of its subclasses.

+
+ +
+ +
+
+class cassandra.auth.PlainTextAuthenticator(username, password)
+
+
+evaluate_challenge(challenge)
+

Called when the server sends a challenge message. Generally, this method +should return None when authentication is complete from a +client perspective. Otherwise, a string should be returned.

+
+ +
+ +
+
+class cassandra.auth.SaslAuthProvider(**sasl_kwargs)
+

An AuthProvider supporting general SASL auth mechanisms

+

Suitable for GSSAPI or other SASL mechanisms

+

Example usage:

+
from cassandra.cluster import Cluster
+from cassandra.auth import SaslAuthProvider
+
+sasl_kwargs = {'service': 'something',
+               'mechanism': 'GSSAPI',
+               'qops': 'auth'.split(',')}
+auth_provider = SaslAuthProvider(**sasl_kwargs)
+cluster = Cluster(auth_provider=auth_provider)
+
+
+
+

New in version 2.1.4.

+
+
+
+new_authenticator(host)
+

Implementations of this class should return a new instance +of Authenticator or one of its subclasses.

+
+ +
+ +
+
+class cassandra.auth.SaslAuthenticator(host, service, mechanism='GSSAPI', **sasl_kwargs)
+

A pass-through Authenticator using the third party package +‘pure-sasl’ for authentication

+
+

New in version 2.1.4.

+
+
+
+initial_response()
+

Returns an message to send to the server to initiate the SASL handshake. +None may be returned to send an empty message.

+
+ +
+
+evaluate_challenge(challenge)
+

Called when the server sends a challenge message. Generally, this method +should return None when authentication is complete from a +client perspective. Otherwise, a string should be returned.

+
+ +
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.24.8-scylla/api/cassandra/cluster.html b/3.24.8-scylla/api/cassandra/cluster.html new file mode 100644 index 0000000000..946bb1af69 --- /dev/null +++ b/3.24.8-scylla/api/cassandra/cluster.html @@ -0,0 +1,1778 @@ + + + + + + + + + + + + + cassandra.cluster - Clusters and Sessions | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.cluster - Clusters and Sessions

+
+
+class cassandra.cluster.Cluster([contact_points=('127.0.0.1',)][, port=9042][, executor_threads=2], **attr_kwargs)
+

The main class to use when interacting with a Cassandra cluster. +Typically, one instance of this class will be created for each +separate Cassandra cluster that your application interacts with.

+

Example usage:

+
>>> from cassandra.cluster import Cluster
+>>> cluster = Cluster(['192.168.1.1', '192.168.1.2'])
+>>> session = cluster.connect()
+>>> session.execute("CREATE KEYSPACE ...")
+>>> ...
+>>> cluster.shutdown()
+
+
+

Cluster and Session also provide context management functions +which implicitly handle shutdown when leaving scope.

+

executor_threads defines the number of threads in a pool for handling asynchronous tasks such as +extablishing connection pools or refreshing metadata.

+

Any of the mutable Cluster attributes may be set as keyword arguments to the constructor.

+
+
+contact_points = ['127.0.0.1']
+
+ +
+
+port = 9042
+
+ +
+
+cql_version = None
+
+ +
+
+protocol_version = 66
+
+ +
+
+compression = True
+
+ +
+
+auth_provider
+

When protocol_version is 2 or higher, this should +be an instance of a subclass of AuthProvider, +such as PlainTextAuthProvider.

+

When protocol_version is 1, this should be +a function that accepts one argument, the IP address of a node, +and returns a dict of credentials for that node.

+

When not using authentication, this should be left as None.

+
+ +
+
+load_balancing_policy
+

An instance of policies.LoadBalancingPolicy or +one of its subclasses.

+
+

Changed in version 2.6.0.

+
+

Defaults to TokenAwarePolicy (DCAwareRoundRobinPolicy). +when using CPython (where the murmur3 extension is available). DCAwareRoundRobinPolicy +otherwise. Default local DC will be chosen from contact points.

+

Please see DCAwareRoundRobinPolicy for a discussion on default behavior with respect to +DC locality and remote nodes.

+
+ +
+
+reconnection_policy = <cassandra.policies.ExponentialReconnectionPolicy object>
+
+ +
+
+default_retry_policy = <cassandra.policies.RetryPolicy object>
+

A default policies.RetryPolicy instance to use for all +Statement objects which do not have a retry_policy +explicitly set.

+
+ +
+
+conviction_policy_factory = <class 'cassandra.policies.SimpleConvictionPolicy'>
+
+ +
+
+address_translator = <cassandra.policies.IdentityTranslator object>
+
+ +
+
+metrics_enabled = False
+
+ +
+
+metrics = None
+
+ +
+
+ssl_context = None
+
+ +
+
+ssl_options = None
+
+ +
+
+sockopts = None
+
+ +
+
+max_schema_agreement_wait = 10
+
+ +
+
+metadata = None
+
+ +
+
+connection_class = <class 'cassandra.io.libevreactor.LibevConnection'>
+
+ +
+
+control_connection_timeout = 2.0
+
+ +
+
+idle_heartbeat_interval = 30
+
+ +
+
+idle_heartbeat_timeout = 30
+
+ +
+
+schema_event_refresh_window = 2
+
+ +
+
+topology_event_refresh_window = 10
+
+ +
+
+status_event_refresh_window = 2
+
+ +
+
+prepare_on_all_hosts = True
+
+ +
+
+reprepare_on_up = True
+
+ +
+
+connect_timeout = 5
+
+ +
+
+schema_metadata_enabled = True
+

Flag indicating whether internal schema metadata is updated.

+

When disabled, the driver does not populate Cluster.metadata.keyspaces on connect, or on schema change events. This +can be used to speed initial connection, and reduce load on client and server during operation. Turning this off +gives away token aware request routing, and programmatic inspection of the metadata model.

+
+ +
+
+token_metadata_enabled = True
+

Flag indicating whether internal token metadata is updated.

+

When disabled, the driver does not query node token information on connect, or on topology change events. This +can be used to speed initial connection, and reduce load on client and server during operation. It is most useful +in large clusters using vnodes, where the token map can be expensive to compute. Turning this off +gives away token aware request routing, and programmatic inspection of the token ring.

+
+ +
+
+timestamp_generator = None
+
+ +
+
+endpoint_factory = None
+
+ +
+
+cloud = None
+
+ +
+
+connect(keyspace=None, wait_for_all_pools=False)
+

Creates and returns a new Session object.

+

If keyspace is specified, that keyspace will be the default keyspace for +operations on the Session.

+

wait_for_all_pools specifies whether this call should wait for all connection pools to be +established or attempted. Default is False, which means it will return when the first +successful connection is established. Remaining pools are added asynchronously.

+
+ +
+
+shutdown()
+

Closes all sessions and connection associated with this Cluster. +To ensure all connections are properly closed, you should always +call shutdown() on a Cluster instance when you are done with it.

+

Once shutdown, a Cluster should not be used for any purpose.

+
+ +
+
+register_user_type(keyspace, user_type, klass)
+

Registers a class to use to represent a particular user-defined type. +Query parameters for this user-defined type will be assumed to be +instances of klass. Result sets for this user-defined type will +be instances of klass. If no class is registered for a user-defined +type, a namedtuple will be used for result sets, and non-prepared +statements may not encode parameters for this type correctly.

+

keyspace is the name of the keyspace that the UDT is defined in.

+

user_type is the string name of the UDT to register the mapping +for.

+

klass should be a class with attributes whose names match the +fields of the user-defined type. The constructor must accepts kwargs +for each of the fields in the UDT.

+

This method should only be called after the type has been created +within Cassandra.

+

Example:

+
cluster = Cluster(protocol_version=3)
+session = cluster.connect()
+session.set_keyspace('mykeyspace')
+session.execute("CREATE TYPE address (street text, zipcode int)")
+session.execute("CREATE TABLE users (id int PRIMARY KEY, location address)")
+
+# create a class to map to the "address" UDT
+class Address(object):
+
+    def __init__(self, street, zipcode):
+        self.street = street
+        self.zipcode = zipcode
+
+cluster.register_user_type('mykeyspace', 'address', Address)
+
+# insert a row using an instance of Address
+session.execute("INSERT INTO users (id, location) VALUES (%s, %s)",
+                (0, Address("123 Main St.", 78723)))
+
+# results will include Address instances
+results = session.execute("SELECT * FROM users")
+row = results[0]
+print row.id, row.location.street, row.location.zipcode
+
+
+
+ +
+
+register_listener(listener)
+

Adds a cassandra.policies.HostStateListener subclass instance to +the list of listeners to be notified when a host is added, removed, +marked up, or marked down.

+
+ +
+
+unregister_listener(listener)
+

Removes a registered listener.

+
+ +
+
+add_execution_profile(name, profile, pool_wait_timeout=5)
+

Adds an ExecutionProfile to the cluster. This makes it available for use by name in Session.execute() +and Session.execute_async(). This method will raise if the profile already exists.

+

Normally profiles will be injected at cluster initialization via Cluster(execution_profiles). This method +provides a way of adding them dynamically.

+

Adding a new profile updates the connection pools according to the specified load_balancing_policy. By default, +this method will wait up to five seconds for the pool creation to complete, so the profile can be used immediately +upon return. This behavior can be controlled using pool_wait_timeout (see +concurrent.futures.wait +for timeout semantics).

+
+ +
+
+set_max_requests_per_connection(host_distance, max_requests)
+

Sets a threshold for concurrent requests per connection, above which new +connections will be created to a host (up to max connections; +see set_max_connections_per_host()).

+

Pertains to connection pool management in protocol versions {1,2}.

+
+ +
+
+get_max_requests_per_connection(host_distance)
+
+ +
+
+set_min_requests_per_connection(host_distance, min_requests)
+

Sets a threshold for concurrent requests per connection, below which +connections will be considered for disposal (down to core connections; +see set_core_connections_per_host()).

+

Pertains to connection pool management in protocol versions {1,2}.

+
+ +
+
+get_min_requests_per_connection(host_distance)
+
+ +
+
+get_core_connections_per_host(host_distance)
+

Gets the minimum number of connections per Session that will be opened +for each host with HostDistance equal to host_distance. +The default is 2 for LOCAL and 1 for +REMOTE.

+

This property is ignored if protocol_version is +3 or higher.

+
+ +
+
+set_core_connections_per_host(host_distance, core_connections)
+

Sets the minimum number of connections per Session that will be opened +for each host with HostDistance equal to host_distance. +The default is 2 for LOCAL and 1 for +REMOTE.

+

Protocol version 1 and 2 are limited in the number of concurrent +requests they can send per connection. The driver implements connection +pooling to support higher levels of concurrency.

+

If protocol_version is set to 3 or higher, this +is not supported (there is always one connection per host, unless +the host is remote and connect_to_remote_hosts is False) +and using this will result in an UnsupportedOperation.

+
+ +
+
+get_max_connections_per_host(host_distance)
+

Gets the maximum number of connections per Session that will be opened +for each host with HostDistance equal to host_distance. +The default is 8 for LOCAL and 2 for +REMOTE.

+

This property is ignored if protocol_version is +3 or higher.

+
+ +
+
+set_max_connections_per_host(host_distance, max_connections)
+

Sets the maximum number of connections per Session that will be opened +for each host with HostDistance equal to host_distance. +The default is 2 for LOCAL and 1 for +REMOTE.

+

If protocol_version is set to 3 or higher, this +is not supported (there is always one connection per host, unless +the host is remote and connect_to_remote_hosts is False) +and using this will result in an UnsupportedOperation.

+
+ +
+
+get_control_connection_host()
+

Returns the control connection host metadata.

+
+ +
+
+refresh_schema_metadata(max_schema_agreement_wait=None)
+

Synchronously refresh all schema metadata.

+

By default, the timeout for this operation is governed by max_schema_agreement_wait +and control_connection_timeout.

+

Passing max_schema_agreement_wait here overrides max_schema_agreement_wait.

+

Setting max_schema_agreement_wait <= 0 will bypass schema agreement and refresh schema immediately.

+

An Exception is raised if schema refresh fails for any reason.

+
+ +
+
+refresh_keyspace_metadata(keyspace, max_schema_agreement_wait=None)
+

Synchronously refresh keyspace metadata. This applies to keyspace-level information such as replication +and durability settings. It does not refresh tables, types, etc. contained in the keyspace.

+

See refresh_schema_metadata() for description of max_schema_agreement_wait behavior

+
+ +
+
+refresh_table_metadata(keyspace, table, max_schema_agreement_wait=None)
+

Synchronously refresh table metadata. This applies to a table, and any triggers or indexes attached +to the table.

+

See refresh_schema_metadata() for description of max_schema_agreement_wait behavior

+
+ +
+
+refresh_user_type_metadata(keyspace, user_type, max_schema_agreement_wait=None)
+

Synchronously refresh user defined type metadata.

+

See refresh_schema_metadata() for description of max_schema_agreement_wait behavior

+
+ +
+
+refresh_user_function_metadata(keyspace, function, max_schema_agreement_wait=None)
+

Synchronously refresh user defined function metadata.

+

function is a cassandra.UserFunctionDescriptor.

+

See refresh_schema_metadata() for description of max_schema_agreement_wait behavior

+
+ +
+
+refresh_user_aggregate_metadata(keyspace, aggregate, max_schema_agreement_wait=None)
+

Synchronously refresh user defined aggregate metadata.

+

aggregate is a cassandra.UserAggregateDescriptor.

+

See refresh_schema_metadata() for description of max_schema_agreement_wait behavior

+
+ +
+
+refresh_nodes(force_token_rebuild=False)
+

Synchronously refresh the node list and token metadata

+

force_token_rebuild can be used to rebuild the token map metadata, even if no new nodes are discovered.

+

An Exception is raised if node refresh fails for any reason.

+
+ +
+
+set_meta_refresh_enabled(enabled)
+

Deprecated: set schema_metadata_enabled token_metadata_enabled instead

+

Sets a flag to enable (True) or disable (False) all metadata refresh queries. +This applies to both schema and node topology.

+

Disabling this is useful to minimize refreshes during multiple changes.

+

Meta refresh must be enabled for the driver to become aware of any cluster +topology changes or schema updates.

+
+ +
+ +
+
+class cassandra.cluster.ExecutionProfile(load_balancing_policy=<object object>, retry_policy=None, consistency_level=ConsistencyLevel.LOCAL_ONE, serial_consistency_level=None, request_timeout=10.0, row_factory=<function named_tuple_factory>, speculative_execution_policy=None)
+
+
+consistency_level = LOCAL_ONE
+
+ +
+
+static row_factory(colnames, rows)
+

Returns each row as a namedtuple. +This is the default row factory.

+

Example:

+
>>> from cassandra.query import named_tuple_factory
+>>> session = cluster.connect('mykeyspace')
+>>> session.row_factory = named_tuple_factory
+>>> rows = session.execute("SELECT name, age FROM users LIMIT 1")
+>>> user = rows[0]
+
+>>> # you can access field by their name:
+>>> print "name: %s, age: %d" % (user.name, user.age)
+name: Bob, age: 42
+
+>>> # or you can access fields by their position (like a tuple)
+>>> name, age = user
+>>> print "name: %s, age: %d" % (name, age)
+name: Bob, age: 42
+>>> name = user[0]
+>>> age = user[1]
+>>> print "name: %s, age: %d" % (name, age)
+name: Bob, age: 42
+
+
+
+

Changed in version 2.0.0: moved from cassandra.decoder to cassandra.query

+
+
+ +
+ +
+
+class cassandra.cluster.GraphExecutionProfile(load_balancing_policy=_NOT_SET, retry_policy=None, consistency_level=ConsistencyLevel.LOCAL_ONE, serial_consistency_level=None, request_timeout=30.0, row_factory=None, graph_options=None, continuous_paging_options=_NOT_SET)
+

Default execution profile for graph execution.

+

See ExecutionProfile for base attributes. Note that if not explicitly set, +the row_factory and graph_options.graph_protocol are resolved during the query execution. +These options will resolve to graph_graphson3_row_factory and GraphProtocol.GRAPHSON_3_0 +for the core graph engine (DSE 6.8+), otherwise graph_object_row_factory and GraphProtocol.GRAPHSON_1_0

+

In addition to default parameters shown in the signature, this profile also defaults retry_policy to +cassandra.policies.NeverRetryPolicy.

+
+ +
+
+class cassandra.cluster.GraphAnalyticsExecutionProfile(load_balancing_policy=None, retry_policy=None, consistency_level=ConsistencyLevel.LOCAL_ONE, serial_consistency_level=None, request_timeout=3600.0 * 24.0 * 7.0, row_factory=None, graph_options=None)
+

Execution profile with timeout and load balancing appropriate for graph analytics queries.

+

See also GraphExecutionPolicy.

+

In addition to default parameters shown in the signature, this profile also defaults retry_policy to +cassandra.policies.NeverRetryPolicy, and load_balancing_policy to one that targets the current Spark +master.

+

Note: The graph_options.graph_source is set automatically to b’a’ (analytics) +when using GraphAnalyticsExecutionProfile. This is mandatory to target analytics nodes.

+
+ +
+
+cassandra.cluster.EXEC_PROFILE_DEFAULT
+

The most base type

+
+ +
+
+cassandra.cluster.EXEC_PROFILE_GRAPH_DEFAULT
+

The most base type

+
+ +
+
+cassandra.cluster.EXEC_PROFILE_GRAPH_SYSTEM_DEFAULT
+

The most base type

+
+ +
+
+cassandra.cluster.EXEC_PROFILE_GRAPH_ANALYTICS_DEFAULT
+

The most base type

+
+ +
+
+class cassandra.cluster.Session
+

A collection of connection pools for each host in the cluster. +Instances of this class should not be created directly, only +using Cluster.connect().

+

Queries and statements can be executed through Session instances +using the execute() and execute_async() +methods.

+

Example usage:

+
>>> session = cluster.connect()
+>>> session.set_keyspace("mykeyspace")
+>>> session.execute("SELECT * FROM mycf")
+
+
+
+
+default_timeout = 10.0
+

A default timeout, measured in seconds, for queries executed through +execute() or execute_async(). This default may be +overridden with the timeout parameter for either of those methods.

+

Setting this to None will cause no timeouts to be set by default.

+

Please see ResponseFuture.result() for details on the scope and +effect of this timeout.

+
+

New in version 2.0.0.

+
+
+ +
+
+default_consistency_level = LOCAL_ONE
+

Deprecated: use execution profiles instead +The default ConsistencyLevel for operations executed through +this session. This default may be overridden by setting the +consistency_level on individual statements.

+
+

New in version 1.2.0.

+
+
+

Changed in version 3.0.0: default changed from ONE to LOCAL_ONE

+
+
+ +
+
+default_serial_consistency_level = None
+

The default ConsistencyLevel for serial phase of conditional updates executed through +this session. This default may be overridden by setting the +serial_consistency_level on individual statements.

+

Only valid for protocol_version >= 2.

+
+ +
+
+row_factory = <function named_tuple_factory>
+

The format to return row results in. By default, each +returned row will be a named tuple. You can alternatively +use any of the following:

+ +
+ +
+
+default_fetch_size = 5000
+
+ +
+
+use_client_timestamp = True
+
+ +
+
+timestamp_generator = None
+
+ +
+
+encoder = None
+
+ +
+
+client_protocol_handler = <class 'cassandra.protocol.cython_protocol_handler.<locals>.CythonProtocolHandler'>
+
+ +
+
+execute(statement[, parameters][, timeout][, trace][, custom_payload][, paging_state][, host][, execute_as])
+

Execute the given query and synchronously wait for the response.

+

If an error is encountered while executing the query, an Exception +will be raised.

+

query may be a query string or an instance of cassandra.query.Statement.

+

parameters may be a sequence or dict of parameters to bind. If a +sequence is used, %s should be used the placeholder for each +argument. If a dict is used, %(name)s style placeholders must +be used.

+

timeout should specify a floating-point timeout (in seconds) after +which an OperationTimedOut exception will be raised if the query +has not completed. If not set, the timeout defaults to the request_timeout of the selected execution_profile. +If set to None, there is no timeout. Please see ResponseFuture.result() for details on +the scope and effect of this timeout.

+

If trace is set to True, the query will be sent with tracing enabled. +The trace details can be obtained using the returned ResultSet object.

+

custom_payload is a Custom Payloads dict to be passed to the server. +If query is a Statement with its own custom_payload. The message payload +will be a union of the two, with the values specified here taking precedence.

+

execution_profile is the execution profile to use for this request. It can be a key to a profile configured +via Cluster.add_execution_profile() or an instance (from Session.execution_profile_clone_update(), +for example

+

paging_state is an optional paging state, reused from a previous ResultSet.

+

host is the cassandra.pool.Host that should handle the query. If the host specified is down or +not yet connected, the query will fail with NoHostAvailable. Using this is +discouraged except in a few cases, e.g., querying node-local tables and applying schema changes.

+

execute_as the user that will be used on the server to execute the request. This is only available +on a DSE cluster.

+
+ +
+
+execute_async(statement[, parameters][, trace][, custom_payload][, paging_state][, host][, execute_as])
+

Execute the given query and return a ResponseFuture object +which callbacks may be attached to for asynchronous response +delivery. You may also call result() +on the ResponseFuture to synchronously block for results at +any time.

+

See Session.execute() for parameter definitions.

+

Example usage:

+
>>> session = cluster.connect()
+>>> future = session.execute_async("SELECT * FROM mycf")
+
+>>> def log_results(results):
+...     for row in results:
+...         log.info("Results: %s", row)
+
+>>> def log_error(exc):
+>>>     log.error("Operation failed: %s", exc)
+
+>>> future.add_callbacks(log_results, log_error)
+
+
+

Async execution with blocking wait for results:

+
>>> future = session.execute_async("SELECT * FROM mycf")
+>>> # do other stuff...
+
+>>> try:
+...     results = future.result()
+... except Exception:
+...     log.exception("Operation failed:")
+
+
+
+ +
+
+execute_graph(statement[, parameters][, trace][, execution_profile=EXEC_PROFILE_GRAPH_DEFAULT][, execute_as])
+

Executes a Gremlin query string or GraphStatement synchronously, +and returns a ResultSet from this execution.

+

parameters is dict of named parameters to bind. The values must be +JSON-serializable.

+

execution_profile: Selects an execution profile for the request.

+

execute_as the user that will be used on the server to execute the request.

+
+ +
+
+execute_graph_async(statement[, parameters][, trace][, execution_profile=EXEC_PROFILE_GRAPH_DEFAULT][, execute_as])
+

Execute the graph query and return a ResponseFuture +object which callbacks may be attached to for asynchronous response delivery. You may also call ResponseFuture.result() to synchronously block for +results at any time.

+
+ +
+
+prepare(statement)
+

Prepares a query string, returning a PreparedStatement +instance which can be used as follows:

+
>>> session = cluster.connect("mykeyspace")
+>>> query = "INSERT INTO users (id, name, age) VALUES (?, ?, ?)"
+>>> prepared = session.prepare(query)
+>>> session.execute(prepared, (user.id, user.name, user.age))
+
+
+

Or you may bind values to the prepared statement ahead of time:

+
>>> prepared = session.prepare(query)
+>>> bound_stmt = prepared.bind((user.id, user.name, user.age))
+>>> session.execute(bound_stmt)
+
+
+

Of course, prepared statements may (and should) be reused:

+
>>> prepared = session.prepare(query)
+>>> for user in users:
+...     bound = prepared.bind((user.id, user.name, user.age))
+...     session.execute(bound)
+
+
+

Alternatively, if protocol_version is 5 or higher +(requires Cassandra 4.0+), the keyspace can be specified as a +parameter. This will allow you to avoid specifying the keyspace in the +query without specifying a keyspace in connect(). It +even will let you prepare and use statements against a keyspace other +than the one originally specified on connection:

+
>>> analyticskeyspace_prepared = session.prepare(
+...     "INSERT INTO user_activity id, last_activity VALUES (?, ?)",
+...     keyspace="analyticskeyspace")  # note the different keyspace
+
+
+

Important: PreparedStatements should be prepared only once. +Preparing the same query more than once will likely affect performance.

+

custom_payload is a key value map to be passed along with the prepare +message. See Custom Payloads.

+
+ +
+
+shutdown()
+

Close all connections. Session instances should not be used +for any purpose after being shutdown.

+
+ +
+
+set_keyspace(keyspace)
+

Set the default keyspace for all queries made through this Session. +This operation blocks until complete.

+
+ +
+
+get_execution_profile(name)
+

Returns the execution profile associated with the provided name.

+
+
Parameters
+

name – The name (or key) of the execution profile.

+
+
+
+ +
+
+execution_profile_clone_update(ep, **kwargs)
+

Returns a clone of the ep profile. kwargs can be specified to update attributes +of the returned profile.

+

This is a shallow clone, so any objects referenced by the profile are shared. This means Load Balancing Policy +is maintained by inclusion in the active profiles. It also means updating any other rich objects will be seen +by the active profile. In cases where this is not desirable, be sure to replace the instance instead of manipulating +the shared object.

+
+ +
+
+add_request_init_listener(fn, *args, **kwargs)
+

Adds a callback with arguments to be called when any request is created.

+

It will be invoked as fn(response_future, *args, **kwargs) after each client request is created, +and before the request is sent. This can be used to create extensions by adding result callbacks to the +response future.

+

response_future is the ResponseFuture for the request.

+

Note that the init callback is done on the client thread creating the request, so you may need to consider +synchronization if you have multiple threads. Any callbacks added to the response future will be executed +on the event loop thread, so the normal advice about minimizing cycles and avoiding blocking apply (see Note in +ResponseFuture.add_callbacks().

+

See this example in the +source tree for an example.

+
+ +
+
+remove_request_init_listener(fn, *args, **kwargs)
+

Removes a callback and arguments from the list.

+

See Session.add_request_init_listener().

+
+ +
+ +
+
+class cassandra.cluster.ResponseFuture
+

An asynchronous response delivery mechanism that is returned from calls +to Session.execute_async().

+
+
There are two ways for results to be delivered:
+
+
+
+
+query = None
+
+ +
+
+result()
+

Return the final result or raise an Exception if errors were +encountered. If the final result or error has not been set +yet, this method will block until it is set, or the timeout +set for the request expires.

+

Timeout is specified in the Session request execution functions. +If the timeout is exceeded, an cassandra.OperationTimedOut will be raised. +This is a client-side timeout. For more information +about server-side coordinator timeouts, see policies.RetryPolicy.

+

Example usage:

+
>>> future = session.execute_async("SELECT * FROM mycf")
+>>> # do other stuff...
+
+>>> try:
+...     rows = future.result()
+...     for row in rows:
+...         ... # process results
+... except Exception:
+...     log.exception("Operation failed:")
+
+
+
+ +
+
+get_query_trace()
+

Fetches and returns the query trace of the last response, or None if tracing was +not enabled.

+

Note that this may raise an exception if there are problems retrieving the trace +details from Cassandra. If the trace is not available after max_wait, +cassandra.query.TraceUnavailable will be raised.

+

If the ResponseFuture is not done (async execution) and you try to retrieve the trace, +cassandra.query.TraceUnavailable will be raised.

+

query_cl is the consistency level used to poll the trace tables.

+
+ +
+
+get_all_query_traces()
+

Fetches and returns the query traces for all query pages, if tracing was enabled.

+

See note in get_query_trace() regarding possible exceptions.

+
+ +
+
+custom_payload
+

The custom payload returned from the server, if any. This will only be +set by Cassandra servers implementing a custom QueryHandler, and only +for protocol_version 4+.

+

Ensure the future is complete before trying to access this property +(call result(), or after callback is invoked). +Otherwise it may throw if the response has not been received.

+
+
Returns
+

Custom Payloads.

+
+
+
+ +
+
+is_schema_agreed = True
+
+ +
+
+has_more_pages
+

Returns True if there are more pages left in the +query results, False otherwise. This should only +be checked after the first page has been returned.

+
+

New in version 2.0.0.

+
+
+ +
+
+warnings
+

Warnings returned from the server, if any. This will only be +set for protocol_version 4+.

+

Warnings may be returned for such things as oversized batches, +or too many tombstones in slice queries.

+

Ensure the future is complete before trying to access this property +(call result(), or after callback is invoked). +Otherwise it may throw if the response has not been received.

+
+ +
+
+start_fetching_next_page()
+

If there are more pages left in the query result, this asynchronously +starts fetching the next page. If there are no pages left, QueryExhausted +is raised. Also see has_more_pages.

+

This should only be called after the first page has been returned.

+
+

New in version 2.0.0.

+
+
+ +
+
+add_callback(fn, *args, **kwargs)
+

Attaches a callback function to be called when the final results arrive.

+

By default, fn will be called with the results as the first and only +argument. If *args or **kwargs are supplied, they will be passed +through as additional positional or keyword arguments to fn.

+

If an error is hit while executing the operation, a callback attached +here will not be called. Use add_errback() or add_callbacks() +if you wish to handle that case.

+

If the final result has already been seen when this method is called, +the callback will be called immediately (before this method returns).

+

Note: in the case that the result is not available when the callback is added, +the callback is executed by IO event thread. This means that the callback +should not block or attempt further synchronous requests, because no further +IO will be processed until the callback returns.

+

Important: if the callback you attach results in an exception being +raised, the exception will be ignored, so please ensure your +callback handles all error cases that you care about.

+

Usage example:

+
>>> session = cluster.connect("mykeyspace")
+
+>>> def handle_results(rows, start_time, should_log=False):
+...     if should_log:
+...         log.info("Total time: %f", time.time() - start_time)
+...     ...
+
+>>> future = session.execute_async("SELECT * FROM users")
+>>> future.add_callback(handle_results, time.time(), should_log=True)
+
+
+
+ +
+
+add_errback(fn, *args, **kwargs)
+

Like add_callback(), but handles error cases. +An Exception instance will be passed as the first positional argument +to fn.

+
+ +
+
+ResponseFuture.add_callbacks(callback, errback, callback_args=(), callback_kwargs=None, errback_args=(), errback_args=None)
+

A convenient combination of add_callback() and +add_errback().

+

Example usage:

+
>>> session = cluster.connect()
+>>> query = "SELECT * FROM mycf"
+>>> future = session.execute_async(query)
+
+>>> def log_results(results, level='debug'):
+...     for row in results:
+...         log.log(level, "Result: %s", row)
+
+>>> def log_error(exc, query):
+...     log.error("Query '%s' failed: %s", query, exc)
+
+>>> future.add_callbacks(
+...     callback=log_results, callback_kwargs={'level': 'info'},
+...     errback=log_error, errback_args=(query,))
+
+
+
+ +
+ +
+
+class cassandra.cluster.ResultSet
+

An iterator over the rows from a query result. Also supplies basic equality +and indexing methods for backward-compatability. These methods materialize +the entire result set (loading all pages), and should only be used if the +total result size is understood. Warnings are emitted when paged results +are materialized in this fashion.

+

You can treat this as a normal iterator over rows:

+
>>> from cassandra.query import SimpleStatement
+>>> statement = SimpleStatement("SELECT * FROM users", fetch_size=10)
+>>> for user_row in session.execute(statement):
+...     process_user(user_row)
+
+
+

Whenever there are no more rows in the current page, the next page will +be fetched transparently. However, note that it is possible for +an Exception to be raised while fetching the next page, just +like you might see on a normal call to session.execute().

+
+
+all()
+

Returns all the remaining rows as a list. This is basically +a convenient shortcut to list(result_set).

+

This function is not recommended for queries that return a large number of elements.

+
+ +
+
+property current_rows
+

The list of current page rows. May be empty if the result was empty, +or this is the last page.

+
+ +
+
+fetch_next_page()
+

Manually, synchronously fetch the next page. Supplied for manually retrieving pages +and inspecting current_page(). It is not necessary to call this when iterating +through results; paging happens implicitly in iteration.

+
+ +
+
+get_all_query_traces(max_wait_sec_per=None)
+

Gets all query traces from the associated future. +See ResponseFuture.get_all_query_traces() for details.

+
+ +
+
+get_query_trace(max_wait_sec=None)
+

Gets the last query trace from the associated future. +See ResponseFuture.get_query_trace() for details.

+
+ +
+
+property has_more_pages
+

True if the last response indicated more pages; False otherwise

+
+ +
+
+one()
+

Return a single row of the results or None if empty. This is basically +a shortcut to result_set.current_rows[0] and should only be used when +you know a query returns a single row. Consider using an iterator if the +ResultSet contains more than one row.

+
+ +
+
+property paging_state
+

Server paging state of the query. Can be None if the query was not paged.

+

The driver treats paging state as opaque, but it may contain primary key data, so applications may want to +avoid sending this to untrusted parties.

+
+ +
+
+property was_applied
+

For LWT results, returns whether the transaction was applied.

+

Result is indeterminate if called on a result that was not an LWT request or on +a query.BatchStatement containing LWT. In the latter case either all the batch +succeeds or fails.

+

Only valid when one of the of the internal row factories is in use.

+
+ +
+ +
+
+exception cassandra.cluster.QueryExhausted
+

Raised when ResponseFuture.start_fetching_next_page() is called and +there are no more pages. You can check ResponseFuture.has_more_pages +before calling to avoid this.

+
+

New in version 2.0.0.

+
+
+ +
+
+exception cassandra.cluster.NoHostAvailable
+

Raised when an operation is attempted but all connections are +busy, defunct, closed, or resulted in errors when used.

+
+ +
+
+exception cassandra.cluster.UserTypeDoesNotExist
+

An attempt was made to use a user-defined type that does not exist.

+
+

New in version 2.1.0.

+
+
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.24.8-scylla/api/cassandra/concurrent.html b/3.24.8-scylla/api/cassandra/concurrent.html new file mode 100644 index 0000000000..29d4e4aa9a --- /dev/null +++ b/3.24.8-scylla/api/cassandra/concurrent.html @@ -0,0 +1,710 @@ + + + + + + + + + + + + + cassandra.concurrent - Utilities for Concurrent Statement Execution | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.concurrent - Utilities for Concurrent Statement Execution

+
+
+cassandra.concurrent.execute_concurrent(session, statements_and_parameters, concurrency=100, raise_on_first_error=True, results_generator=False, execution_profile=<object object>)
+

Executes a sequence of (statement, parameters) tuples concurrently. Each +parameters item must be a sequence or None.

+

The concurrency parameter controls how many statements will be executed +concurrently. When Cluster.protocol_version is set to 1 or 2, +it is recommended that this be kept below 100 times the number of +core connections per host times the number of connected hosts (see +Cluster.set_core_connections_per_host()). If that amount is exceeded, +the event loop thread may attempt to block on new connection creation, +substantially impacting throughput. If protocol_version +is 3 or higher, you can safely experiment with higher levels of concurrency.

+

If raise_on_first_error is left as True, execution will stop +after the first failed statement and the corresponding exception will be +raised.

+

results_generator controls how the results are returned.

+
    +
  • If False, the results are returned only after all requests have completed.

  • +
  • If True, a generator expression is returned. Using a generator results in a constrained +memory footprint when the results set will be large – results are yielded +as they return instead of materializing the entire list at once. The trade for lower memory +footprint is marginal CPU overhead (more thread coordination and sorting out-of-order results +on-the-fly).

  • +
+

execution_profile argument is the execution profile to use for this +request, it is passed directly to Session.execute_async().

+

A sequence of ExecutionResult(success, result_or_exc) namedtuples is returned +in the same order that the statements were passed in. If success is False, +there was an error executing the statement, and result_or_exc will be +an Exception. If success is True, result_or_exc +will be the query result.

+

Example usage:

+
select_statement = session.prepare("SELECT * FROM users WHERE id=?")
+
+statements_and_params = []
+for user_id in user_ids:
+    params = (user_id, )
+    statements_and_params.append((select_statement, params))
+
+results = execute_concurrent(
+    session, statements_and_params, raise_on_first_error=False)
+
+for (success, result) in results:
+    if not success:
+        handle_error(result)  # result will be an Exception
+    else:
+        process_user(result[0])  # result will be a list of rows
+
+
+

Note: in the case that generators are used, it is important to ensure the consumers do not +block or attempt further synchronous requests, because no further IO will be processed until +the consumer returns. This may also produce a deadlock in the IO event thread.

+
+ +
+
+cassandra.concurrent.execute_concurrent_with_args(session, statement, parameters, *args, **kwargs)
+

Like execute_concurrent(), but takes a single +statement and a sequence of parameters. Each item in parameters +should be a sequence or None.

+

Example usage:

+
statement = session.prepare("INSERT INTO mytable (a, b) VALUES (1, ?)")
+parameters = [(x,) for x in range(1000)]
+execute_concurrent_with_args(session, statement, parameters, concurrency=50)
+
+
+
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.24.8-scylla/api/cassandra/connection.html b/3.24.8-scylla/api/cassandra/connection.html new file mode 100644 index 0000000000..ad921211f0 --- /dev/null +++ b/3.24.8-scylla/api/cassandra/connection.html @@ -0,0 +1,738 @@ + + + + + + + + + + + + + cassandra.connection - Low Level Connection Info | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.connection - Low Level Connection Info

+
+
+exception cassandra.connection.ConnectionException
+

An unrecoverable error was hit when attempting to use a connection, +or the connection was already closed or defunct.

+
+ +
+
+exception cassandra.connection.ConnectionShutdown
+

Raised when a connection has been marked as defunct or has been closed.

+
+ +
+
+exception cassandra.connection.ConnectionBusy
+

An attempt was made to send a message through a Connection that +was already at the max number of in-flight operations.

+
+ +
+
+exception cassandra.connection.ProtocolError
+

Communication did not match the protocol that this driver expects.

+
+ +
+
+class cassandra.connection.EndPoint
+

Represents the information to connect to a cassandra node.

+
+
+property address
+

The IP address of the node. This is the RPC address the driver uses when connecting to the node

+
+ +
+
+property port
+

The port of the node.

+
+ +
+
+resolve()
+

Resolve the endpoint to an address/port. This is called +only on socket connection.

+
+ +
+
+property socket_family
+

The socket family of the endpoint.

+
+ +
+
+property ssl_options
+

SSL options specific to this endpoint.

+
+ +
+ +
+
+class cassandra.connection.EndPointFactory
+
+
+configure(cluster)
+

This is called by the cluster during its initialization.

+
+ +
+
+create(row)
+

Create an EndPoint from a system.peers row.

+
+ +
+ +
+
+class cassandra.connection.SniEndPoint(proxy_address, server_name, port=9042)
+

SNI Proxy EndPoint implementation.

+
+ +
+
+class cassandra.connection.SniEndPointFactory(proxy_address, port, node_domain=None)
+
+ +
+
+class cassandra.connection.UnixSocketEndPoint(unix_socket_path)
+

Unix Socket EndPoint implementation.

+
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.24.8-scylla/api/cassandra/cqlengine/columns.html b/3.24.8-scylla/api/cassandra/cqlengine/columns.html new file mode 100644 index 0000000000..bb9b4ddd7f --- /dev/null +++ b/3.24.8-scylla/api/cassandra/cqlengine/columns.html @@ -0,0 +1,956 @@ + + + + + + + + + + + + + cassandra.cqlengine.columns - Column types for object mapping models | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.cqlengine.columns - Column types for object mapping models

+
+

Columns

+

Columns in your models map to columns in your CQL table. You define CQL columns by defining column attributes on your model classes. +For a model to be valid it needs at least one primary key column and one non-primary key column.

+

Just as in CQL, the order you define your columns in is important, and is the same order they are defined in on a model’s corresponding table.

+

Each column on your model definitions needs to be an instance of a Column class.

+
+
+class cassandra.cqlengine.columns.Column(**kwargs)
+
+
+primary_key = False
+

bool flag, indicates this column is a primary key. The first primary key defined +on a model is the partition key (unless partition keys are set), all others are cluster keys

+
+ +
+
+partition_key = False
+

indicates that this column should be the partition key, defining +more than one partition key column creates a compound partition key

+
+ +
+
+index = False
+

bool flag, indicates an index should be created for this column

+
+ +
+
+custom_index = False
+

bool flag, indicates an index is managed outside of cqlengine. This is +useful if you want to do filter queries on fields that have custom +indexes.

+
+ +
+
+db_field = None
+

the fieldname this field will map to in the database

+
+ +
+
+default = None
+

the default value, can be a value or a callable (no args)

+
+ +
+
+required = False
+

boolean, is the field required? Model validation will raise and +exception if required is set to True and there is a None value assigned

+
+ +
+
+clustering_order = None
+

only applicable on clustering keys (primary keys that are not partition keys) +determines the order that the clustering keys are sorted on disk

+
+ +
+
+discriminator_column = False
+

boolean, if set to True, this column will be used for discriminating records +of inherited models.

+

Should only be set on a column of an abstract model being used for inheritance.

+

There may only be one discriminator column per model. See __discriminator_value__ +for how to specify the value of this column on specialized models.

+
+ +
+
+static = False
+

boolean, if set to True, this is a static column, with a single value per partition

+
+ +
+ +
+
+

Column Types

+

Columns of all types are initialized by passing Column attributes to the constructor by keyword.

+
+
+class cassandra.cqlengine.columns.Ascii(**kwargs)
+

Stores a US-ASCII character string

+
+
Parameters
+
    +
  • min_length (int) – Sets the minimum length of this string, for validation purposes. +Defaults to 1 if this is a required column. Otherwise, None.

  • +
  • max_length (int) – Sets the maximum length of this string, for validation purposes.

  • +
+
+
+
+ +
+
+class cassandra.cqlengine.columns.BigInt(**kwargs)
+

Stores a 64-bit signed integer value

+
+ +
+
+class cassandra.cqlengine.columns.Blob(**kwargs)
+

Stores a raw binary value

+
+ +
+
+cassandra.cqlengine.columns.Bytes
+

alias of cassandra.cqlengine.columns.Blob

+
+ +
+
+class cassandra.cqlengine.columns.Boolean(**kwargs)
+

Stores a boolean True or False value

+
+ +
+
+class cassandra.cqlengine.columns.Counter(index=False, db_field=None, required=False)
+

Stores a counter that can be incremented and decremented

+
+ +
+
+class cassandra.cqlengine.columns.Date(**kwargs)
+

Stores a simple date, with no time-of-day

+
+

Changed in version 2.6.0: removed overload of Date and DateTime. DateTime is a drop-in replacement for legacy models

+
+

requires C* 2.2+ and protocol v4+

+
+ +
+
+class cassandra.cqlengine.columns.DateTime(**kwargs)
+

Stores a datetime value

+
+
+truncate_microseconds = False
+

Set this True to have model instances truncate the date, quantizing it in the same way it will be in the database. +This allows equality comparison between assigned values and values read back from the database:

+
DateTime.truncate_microseconds = True
+assert Model.create(id=0, d=datetime.utcnow()) == Model.objects(id=0).first()
+
+
+

Defaults to False to preserve legacy behavior. May change in the future.

+
+ +
+ +
+
+class cassandra.cqlengine.columns.Decimal(**kwargs)
+

Stores a variable precision decimal value

+
+ +
+
+class cassandra.cqlengine.columns.Double(**kwargs)
+

Stores a double-precision floating-point value

+
+ +
+
+class cassandra.cqlengine.columns.Float(primary_key=False, partition_key=False, index=False, db_field=None, default=None, required=False, clustering_order=None, discriminator_column=False, static=False, custom_index=False)
+

Stores a single-precision floating-point value

+
+ +
+
+class cassandra.cqlengine.columns.Integer(**kwargs)
+

Stores a 32-bit signed integer value

+
+ +
+
+class cassandra.cqlengine.columns.List(value_type, default=<class 'list'>, **kwargs)
+

Stores a list of ordered values

+

http://www.datastax.com/documentation/cql/3.1/cql/cql_using/use_list_t.html

+
+
Parameters
+

value_type – a column class indicating the types of the value

+
+
+
+ +
+
+class cassandra.cqlengine.columns.Map(key_type, value_type, default=<class 'dict'>, **kwargs)
+

Stores a key -> value map (dictionary)

+

https://docs.datastax.com/en/dse/6.7/cql/cql/cql_using/useMap.html

+
+
Parameters
+
    +
  • key_type – a column class indicating the types of the key

  • +
  • value_type – a column class indicating the types of the value

  • +
+
+
+
+ +
+
+class cassandra.cqlengine.columns.Set(value_type, strict=True, default=<class 'set'>, **kwargs)
+

Stores a set of unordered, unique values

+

http://www.datastax.com/documentation/cql/3.1/cql/cql_using/use_set_t.html

+
+
Parameters
+
    +
  • value_type – a column class indicating the types of the value

  • +
  • strict – sets whether non set values will be coerced to set +type on validation, or raise a validation error, defaults to True

  • +
+
+
+
+ +
+
+class cassandra.cqlengine.columns.SmallInt(**kwargs)
+

Stores a 16-bit signed integer value

+
+

New in version 2.6.0.

+
+

requires C* 2.2+ and protocol v4+

+
+ +
+
+class cassandra.cqlengine.columns.Text(min_length=None, max_length=None, **kwargs)
+

Stores a UTF-8 encoded string

+
+
Parameters
+
    +
  • min_length (int) – Sets the minimum length of this string, for validation purposes. +Defaults to 1 if this is a required column. Otherwise, None.

  • +
  • max_length (int) – Sets the maximum length of this string, for validation purposes.

  • +
+
+
+
+ +
+
+class cassandra.cqlengine.columns.Time(**kwargs)
+

Stores a timezone-naive time-of-day, with nanosecond precision

+
+

New in version 2.6.0.

+
+

requires C* 2.2+ and protocol v4+

+
+ +
+
+class cassandra.cqlengine.columns.TimeUUID(**kwargs)
+

UUID containing timestamp

+
+ +
+
+class cassandra.cqlengine.columns.TinyInt(**kwargs)
+

Stores an 8-bit signed integer value

+
+

New in version 2.6.0.

+
+

requires C* 2.2+ and protocol v4+

+
+ +
+
+class cassandra.cqlengine.columns.UserDefinedType(user_type, **kwargs)
+

User Defined Type column

+

http://www.datastax.com/documentation/cql/3.1/cql/cql_using/cqlUseUDT.html

+

These columns are represented by a specialization of cassandra.cqlengine.usertype.UserType.

+

Please see User Defined Types for examples and discussion.

+
+
Parameters
+

user_type (type) – specifies the UserType model of the column

+
+
+
+ +
+
+class cassandra.cqlengine.columns.UUID(**kwargs)
+

Stores a type 1 or 4 UUID

+
+ +
+
+class cassandra.cqlengine.columns.VarInt(**kwargs)
+

Stores an arbitrary-precision integer

+
+ +
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.24.8-scylla/api/cassandra/cqlengine/connection.html b/3.24.8-scylla/api/cassandra/cqlengine/connection.html new file mode 100644 index 0000000000..d43fdb2fe4 --- /dev/null +++ b/3.24.8-scylla/api/cassandra/cqlengine/connection.html @@ -0,0 +1,717 @@ + + + + + + + + + + + + + cassandra.cqlengine.connection - Connection management for cqlengine | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.cqlengine.connection - Connection management for cqlengine

+
+
+cassandra.cqlengine.connection.default()
+

Configures the default connection to localhost, using the driver defaults +(except for row_factory)

+
+ +
+
+cassandra.cqlengine.connection.set_session(s)
+

Configures the default connection with a preexisting cassandra.cluster.Session

+

Note: the mapper presently requires a Session cassandra.cluster.Session.row_factory set to dict_factory. +This may be relaxed in the future

+
+ +
+
+cassandra.cqlengine.connection.setup(hosts, default_keyspace, consistency=None, lazy_connect=False, retry_connect=False, **kwargs)
+

Setup a the driver connection used by the mapper

+
+
Parameters
+
    +
  • hosts (list) – list of hosts, (contact_points for cassandra.cluster.Cluster)

  • +
  • default_keyspace (str) – The default keyspace to use

  • +
  • consistency (int) – The global default ConsistencyLevel - default is the same as Session.default_consistency_level

  • +
  • lazy_connect (bool) – True if should not connect until first use

  • +
  • retry_connect (bool) – True if we should retry to connect even if there was a connection failure initially

  • +
  • **kwargs – Pass-through keyword arguments for cassandra.cluster.Cluster

  • +
+
+
+
+ +
+
+cassandra.cqlengine.connection.register_connection(name, hosts=None, consistency=None, lazy_connect=False, retry_connect=False, cluster_options=None, default=False, session=None)
+

Add a connection to the connection registry. hosts and session are +mutually exclusive, and consistency, lazy_connect, +retry_connect, and cluster_options only work with hosts. Using +hosts will create a new cassandra.cluster.Cluster and +cassandra.cluster.Session.

+
+
Parameters
+
    +
  • hosts (list) – list of hosts, (contact_points for cassandra.cluster.Cluster).

  • +
  • consistency (int) – The default ConsistencyLevel for the +registered connection’s new session. Default is the same as +Session.default_consistency_level. For use with hosts only; +will fail when used with session.

  • +
  • lazy_connect (bool) – True if should not connect until first use. For +use with hosts only; will fail when used with session.

  • +
  • retry_connect (bool) – True if we should retry to connect even if there +was a connection failure initially. For use with hosts only; will +fail when used with session.

  • +
  • cluster_options (dict) – A dict of options to be used as keyword +arguments to cassandra.cluster.Cluster. For use with hosts +only; will fail when used with session.

  • +
  • default (bool) – If True, set the new connection as the cqlengine +default

  • +
  • session (Session) – A cassandra.cluster.Session to be used in +the created connection.

  • +
+
+
+
+ +
+
+cassandra.cqlengine.connection.unregister_connection(name)
+
+ +
+
+cassandra.cqlengine.connection.set_default_connection(name)
+
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.24.8-scylla/api/cassandra/cqlengine/management.html b/3.24.8-scylla/api/cassandra/cqlengine/management.html new file mode 100644 index 0000000000..2fe9eaddc0 --- /dev/null +++ b/3.24.8-scylla/api/cassandra/cqlengine/management.html @@ -0,0 +1,739 @@ + + + + + + + + + + + + + cassandra.cqlengine.management - Schema management for cqlengine | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.cqlengine.management - Schema management for cqlengine

+

A collection of functions for managing keyspace and table schema.

+
+
+cassandra.cqlengine.management.create_keyspace_simple(name, replication_factor, durable_writes=True, connections=None)
+

Creates a keyspace with SimpleStrategy for replica placement

+

If the keyspace already exists, it will not be modified.

+

This function should be used with caution, especially in production environments. +Take care to execute schema modifications in a single context (i.e. not concurrently with other clients).

+

There are plans to guard schema-modifying functions with an environment-driven conditional.

+
+
Parameters
+
    +
  • name (str) – name of keyspace to create

  • +
  • replication_factor (int) – keyspace replication factor, used with SimpleStrategy

  • +
  • durable_writes (bool) – Write log is bypassed if set to False

  • +
  • connections (list) – List of connection names

  • +
+
+
+
+ +
+
+cassandra.cqlengine.management.create_keyspace_network_topology(name, dc_replication_map, durable_writes=True, connections=None)
+

Creates a keyspace with NetworkTopologyStrategy for replica placement

+

If the keyspace already exists, it will not be modified.

+

This function should be used with caution, especially in production environments. +Take care to execute schema modifications in a single context (i.e. not concurrently with other clients).

+

There are plans to guard schema-modifying functions with an environment-driven conditional.

+
+
Parameters
+
    +
  • name (str) – name of keyspace to create

  • +
  • dc_replication_map (dict) – map of dc_names: replication_factor

  • +
  • durable_writes (bool) – Write log is bypassed if set to False

  • +
  • connections (list) – List of connection names

  • +
+
+
+
+ +
+
+cassandra.cqlengine.management.drop_keyspace(name, connections=None)
+

Drops a keyspace, if it exists.

+

There are plans to guard schema-modifying functions with an environment-driven conditional.

+

This function should be used with caution, especially in production environments. +Take care to execute schema modifications in a single context (i.e. not concurrently with other clients).

+
+
Parameters
+
    +
  • name (str) – name of keyspace to drop

  • +
  • connections (list) – List of connection names

  • +
+
+
+
+ +
+
+cassandra.cqlengine.management.sync_table(model, keyspaces=None, connections=None)
+

Inspects the model and creates / updates the corresponding table and columns.

+

If keyspaces is specified, the table will be synched for all specified keyspaces. +Note that the Model.__keyspace__ is ignored in that case.

+

If connections is specified, the table will be synched for all specified connections. Note that the Model.__connection__ is ignored in that case. +If not specified, it will try to get the connection from the Model.

+

Any User Defined Types used in the table are implicitly synchronized.

+

This function can only add fields that are not part of the primary key.

+

Note that the attributes removed from the model are not deleted on the database. +They become effectively ignored by (will not show up on) the model.

+

This function should be used with caution, especially in production environments. +Take care to execute schema modifications in a single context (i.e. not concurrently with other clients).

+

There are plans to guard schema-modifying functions with an environment-driven conditional.

+
+ +
+
+cassandra.cqlengine.management.sync_type(ks_name, type_model, connection=None)
+

Inspects the type_model and creates / updates the corresponding type.

+

Note that the attributes removed from the type_model are not deleted on the database (this operation is not supported). +They become effectively ignored by (will not show up on) the type_model.

+

This function should be used with caution, especially in production environments. +Take care to execute schema modifications in a single context (i.e. not concurrently with other clients).

+

There are plans to guard schema-modifying functions with an environment-driven conditional.

+
+ +
+
+cassandra.cqlengine.management.drop_table(model, keyspaces=None, connections=None)
+

Drops the table indicated by the model, if it exists.

+

If keyspaces is specified, the table will be dropped for all specified keyspaces. Note that the Model.__keyspace__ is ignored in that case.

+

If connections is specified, the table will be synched for all specified connections. Note that the Model.__connection__ is ignored in that case. +If not specified, it will try to get the connection from the Model.

+

This function should be used with caution, especially in production environments. +Take care to execute schema modifications in a single context (i.e. not concurrently with other clients).

+

There are plans to guard schema-modifying functions with an environment-driven conditional.

+
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.24.8-scylla/api/cassandra/cqlengine/models.html b/3.24.8-scylla/api/cassandra/cqlengine/models.html new file mode 100644 index 0000000000..b4ee175f2e --- /dev/null +++ b/3.24.8-scylla/api/cassandra/cqlengine/models.html @@ -0,0 +1,944 @@ + + + + + + + + + + + + + cassandra.cqlengine.models - Table models for object mapping | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.cqlengine.models - Table models for object mapping

+
+

Model

+
+
+class cassandra.cqlengine.models.Model(\*\*kwargs)
+

The initializer creates an instance of the model. Pass in keyword arguments for columns you’ve defined on the model.

+
class Person(Model):
+    id = columns.UUID(primary_key=True)
+    first_name  = columns.Text()
+    last_name = columns.Text()
+
+person = Person(first_name='Blake', last_name='Eggleston')
+person.first_name  #returns 'Blake'
+person.last_name  #returns 'Eggleston'
+
+
+

Model attributes define how the model maps to tables in the database. These are class variables that should be set +when defining Model deriviatives.

+
+
+__abstract__ = False
+

Optional. Indicates that this model is only intended to be used as a base class for other models. +You can’t create tables for abstract models, but checks around schema validity are skipped during class construction.

+
+ +
+
+__table_name__ = None
+

Optional. Sets the name of the CQL table for this model. If left blank, the table name will be the name of the model, with it’s module name as it’s prefix. Manually defined table names are not inherited.

+
+ +
+
+__table_name_case_sensitive__ = False
+

Optional. By default, __table_name__ is case insensitive. Set this to True if you want to preserve the case sensitivity.

+
+ +
+
+__keyspace__ = None
+

Sets the name of the keyspace used by this model.

+
+ +
+
+__connection__ = None
+

Sets the name of the default connection used by this model.

+
+ +
+
+__default_ttl__ = None
+

Will be deprecated in release 4.0. You can set the default ttl by configuring the table __options__. See Default TTL and Per Query TTL for more details.

+
+ +
+
+__discriminator_value__ = None
+

Optional Specifies a value for the discriminator column when using model inheritance.

+

See Model Inheritance for usage examples.

+
+ +

Each table can have its own set of configuration options, including compaction. Unspecified, these default to sensible values in +the server. To override defaults, set options using the model __options__ attribute, which allows options specified a dict.

+

When a table is synced, it will be altered to match the options set on your table. +This means that if you are changing settings manually they will be changed back on resync.

+

Do not use the options settings of cqlengine if you want to manage your compaction settings manually.

+

See the list of supported table properties for more information.

+
+
+__options__
+

For example:

+
class User(Model):
+    __options__ = {'compaction': {'class': 'LeveledCompactionStrategy',
+                                  'sstable_size_in_mb': '64',
+                                  'tombstone_threshold': '.2'},
+                   'comment': 'User data stored here'}
+
+    user_id = columns.UUID(primary_key=True)
+    name = columns.Text()
+
+
+

or :

+
class TimeData(Model):
+    __options__ = {'compaction': {'class': 'SizeTieredCompactionStrategy',
+                                  'bucket_low': '.3',
+                                  'bucket_high': '2',
+                                  'min_threshold': '2',
+                                  'max_threshold': '64',
+                                  'tombstone_compaction_interval': '86400'},
+                   'gc_grace_seconds': '0'}
+
+
+
+ +
+
+__compute_routing_key__ = True
+

Optional Setting False disables computing the routing key for TokenAwareRouting

+
+ +

The base methods allow creating, storing, and querying modeled objects.

+
+
+classmethod create(**kwargs)
+

Create an instance of this model in the database.

+

Takes the model column values as keyword arguments. Setting a value to +None is equivalent to running a CQL DELETE on that column.

+

Returns the instance.

+
+ +
+
+if_not_exists()
+

Check the existence of an object before insertion. The existence of an +object is determined by its primary key(s). And please note using this flag +would incur performance cost.

+

If the insertion isn’t applied, a LWTException is raised.

+
try:
+    TestIfNotExistsModel.if_not_exists().create(id=id, count=9, text='111111111111')
+except LWTException as e:
+    # handle failure case
+    print e.existing  # dict containing LWT result fields
+
+
+

This method is supported on Cassandra 2.0 or later.

+
+ +
+
+if_exists()
+

Check the existence of an object before an update or delete. The existence of an +object is determined by its primary key(s). And please note using this flag +would incur performance cost.

+

If the update or delete isn’t applied, a LWTException is raised.

+
try:
+    TestIfExistsModel.objects(id=id).if_exists().update(count=9, text='111111111111')
+except LWTException as e:
+    # handle failure case
+    pass
+
+
+

This method is supported on Cassandra 2.0 or later.

+
+ +
+
+save()
+

Saves an object to the database.

+
#create a person instance
+person = Person(first_name='Kimberly', last_name='Eggleston')
+#saves it to Cassandra
+person.save()
+
+
+
+ +
+
+update(**values)
+

Performs an update on the model instance. You can pass in values to set on the model +for updating, or you can call without values to execute an update against any modified +fields. If no fields on the model have been modified since loading, no query will be +performed. Model validation is performed normally. Setting a value to None is +equivalent to running a CQL DELETE on that column.

+

It is possible to do a blind update, that is, to update a field without having first selected the object out of the database. +See Blind Updates

+
+ +
+
+iff(**values)
+

Checks to ensure that the values specified are correct on the Cassandra cluster. +Simply specify the column(s) and the expected value(s). As with if_not_exists, +this incurs a performance cost.

+

If the insertion isn’t applied, a LWTException is raised.

+
t = TestTransactionModel(text='some text', count=5)
+try:
+     t.iff(count=5).update('other text')
+except LWTException as e:
+    # handle failure case
+    print e.existing # existing object
+
+
+
+ +
+
+classmethod get(*args, **kwargs)
+

Returns a single object based on the passed filter constraints.

+

This is a pass-through to the model objects().:method:~cqlengine.queries.get.

+
+ +
+
+classmethod filter(*args, **kwargs)
+

Returns a queryset based on filter parameters.

+

This is a pass-through to the model objects().:method:~cqlengine.queries.filter.

+
+ +
+
+classmethod all()
+

Returns a queryset representing all stored objects

+

This is a pass-through to the model objects().all()

+
+ +
+
+delete()
+

Deletes the object from the database

+
+ +
+
+batch(batch_object)
+

Sets the batch object to run instance updates and inserts queries with.

+

See Batch Queries for usage examples

+
+ +
+
+timeout(timeout)
+

Sets a timeout for use in save(), update(), and delete() +operations

+
+ +
+
+timestamp(timedelta_or_datetime)
+

Sets the timestamp for the query

+
+ +
+
+ttl(ttl_in_sec)
+

Sets the ttl values to run instance updates and inserts queries with.

+
+ +
+
+using(connection=None)
+

Change the context on the fly of the model instance (keyspace, connection)

+
+ +
+
+classmethod column_family_name(include_keyspace=True)
+

Returns the column family name if it’s been defined +otherwise, it creates it from the module and class name

+
+ +

Models also support dict-like access:

+
+
+len(m)
+

Returns the number of columns defined in the model

+
+ +
+
+m[col_name]
+

Returns the value of column col_name

+
+ +
+
+m[col_name] = value
+

Set m[col_name] to value

+
+ +
+
+keys()
+

Returns a list of column IDs.

+
+ +
+
+values()
+

Returns list of column values.

+
+ +
+
+items()
+

Returns a list of column ID/value tuples.

+
+ +
+ +
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.24.8-scylla/api/cassandra/cqlengine/query.html b/3.24.8-scylla/api/cassandra/cqlengine/query.html new file mode 100644 index 0000000000..16468f10b5 --- /dev/null +++ b/3.24.8-scylla/api/cassandra/cqlengine/query.html @@ -0,0 +1,1040 @@ + + + + + + + + + + + + + cassandra.cqlengine.query - Query and filter model objects | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.cqlengine.query - Query and filter model objects

+
+

QuerySet

+

QuerySet objects are typically obtained by calling objects() on a model class. +The methods here are used to filter, order, and constrain results.

+
+
+class cassandra.cqlengine.query.ModelQuerySet(model)
+
+
+all()
+

Returns a queryset matching all rows

+
for user in User.objects().all():
+    print(user)
+
+
+
+ +
+
+batch(batch_obj)
+

Set a batch object to run the query on.

+

Note: running a select query with a batch object will raise an exception

+
+ +
+
+consistency(consistency)
+

Sets the consistency level for the operation. See ConsistencyLevel.

+
for user in User.objects(id=3).consistency(CL.ONE):
+    print(user)
+
+
+
+ +
+
+count()
+

Returns the number of rows matched by this query.

+

Note: This function executes a SELECT COUNT() and has a performance cost on large datasets

+
+ +
+
+len(queryset)
+

Returns the number of rows matched by this query. This function uses count() internally.

+

Note: This function executes a SELECT COUNT() and has a performance cost on large datasets

+
+ +
+
+distinct(distinct_fields=None)
+

Returns the DISTINCT rows matched by this query.

+

distinct_fields default to the partition key fields if not specified.

+

Note: distinct_fields must be a partition key or a static column

+
class Automobile(Model):
+    manufacturer = columns.Text(partition_key=True)
+    year = columns.Integer(primary_key=True)
+    model = columns.Text(primary_key=True)
+    price = columns.Decimal()
+
+sync_table(Automobile)
+
+# create rows
+
+Automobile.objects.distinct()
+
+# or
+
+Automobile.objects.distinct(['manufacturer'])
+
+
+
+ +
+
+filter(*args, **kwargs)
+

Adds WHERE arguments to the queryset, returning a new queryset

+

See Retrieving objects with filters

+

Returns a QuerySet filtered on the keyword arguments

+
+ +
+
+get(*args, **kwargs)
+

Returns a single instance matching this query, optionally with additional filter kwargs.

+

See Retrieving objects with filters

+

Returns a single object matching the QuerySet.

+
user = User.get(id=1)
+
+
+

If no objects are matched, a DoesNotExist exception is raised.

+

If more than one object is found, a MultipleObjectsReturned exception is raised.

+
+ +
+
+limit(v)
+

Limits the number of results returned by Cassandra. Use 0 or None to disable.

+

Note that CQL’s default limit is 10,000, so all queries without a limit set explicitly will have an implicit limit of 10,000

+
# Fetch 100 users
+for user in User.objects().limit(100):
+    print(user)
+
+# Fetch all users
+for user in User.objects().limit(None):
+    print(user)
+
+
+
+ +
+
+fetch_size(v)
+

Sets the number of rows that are fetched at a time.

+

Note that driver’s default fetch size is 5000.

+
for user in User.objects().fetch_size(500):
+    print(user)
+
+
+
+ +
+
+if_not_exists()
+

Check the existence of an object before insertion.

+

If the insertion isn’t applied, a LWTException is raised.

+
+ +
+
+if_exists()
+

Check the existence of an object before an update or delete.

+

If the update or delete isn’t applied, a LWTException is raised.

+
+ +
+
+order_by(*colnames)
+

Sets the column(s) to be used for ordering

+

Default order is ascending, prepend a ‘-’ to any column name for descending

+

Note: column names must be a clustering key

+
from uuid import uuid1,uuid4
+
+class Comment(Model):
+    photo_id = UUID(primary_key=True)
+    comment_id = TimeUUID(primary_key=True, default=uuid1) # second primary key component is a clustering key
+    comment = Text()
+
+sync_table(Comment)
+
+u = uuid4()
+for x in range(5):
+    Comment.create(photo_id=u, comment="test %d" % x)
+
+print("Normal")
+for comment in Comment.objects(photo_id=u):
+    print comment.comment_id
+
+print("Reversed")
+for comment in Comment.objects(photo_id=u).order_by("-comment_id"):
+    print comment.comment_id
+
+
+
+ +
+
+allow_filtering()
+

Enables the (usually) unwise practive of querying on a clustering key without also defining a partition key

+
+ +
+
+only(fields)
+

Load only these fields for the returned query

+
+ +
+
+defer(fields)
+

Don’t load these fields for the returned query

+
+ +
+
+timestamp(timestamp)
+

Allows for custom timestamps to be saved with the record.

+
+ +
+
+ttl(ttl)
+

Sets the ttl (in seconds) for modified data.

+

Note that running a select query with a ttl value will raise an exception

+
+ +
+
+using(keyspace=None, connection=None)
+

Change the context on-the-fly of the Model class (keyspace, connection)

+
+ +
+
+update(**values)
+

Performs an update on the row selected by the queryset. Include values to update in the +update like so:

+
Model.objects(key=n).update(value='x')
+
+
+

Passing in updates for columns which are not part of the model will raise a ValidationError.

+

Per column validation will be performed, but instance level validation will not +(i.e., Model.validate is not called). This is sometimes referred to as a blind update.

+

For example:

+
class User(Model):
+    id = Integer(primary_key=True)
+    name = Text()
+
+setup(["localhost"], "test")
+sync_table(User)
+
+u = User.create(id=1, name="jon")
+
+User.objects(id=1).update(name="Steve")
+
+# sets name to null
+User.objects(id=1).update(name=None)
+
+
+

Also supported is blindly adding and removing elements from container columns, +without loading a model instance from Cassandra.

+

Using the syntax .update(column_name={x, y, z}) will overwrite the contents of the container, like updating a +non container column. However, adding __<operation> to the end of the keyword arg, makes the update call add +or remove items from the collection, without overwriting then entire column.

+

Given the model below, here are the operations that can be performed on the different container columns:

+
class Row(Model):
+    row_id      = columns.Integer(primary_key=True)
+    set_column  = columns.Set(Integer)
+    list_column = columns.List(Integer)
+    map_column  = columns.Map(Integer, Integer)
+
+
+

Set

+
    +
  • add: adds the elements of the given set to the column

  • +
  • remove: removes the elements of the given set to the column

  • +
+
# add elements to a set
+Row.objects(row_id=5).update(set_column__add={6})
+
+# remove elements to a set
+Row.objects(row_id=5).update(set_column__remove={4})
+
+
+

List

+
    +
  • append: appends the elements of the given list to the end of the column

  • +
  • prepend: prepends the elements of the given list to the beginning of the column

  • +
+
# append items to a list
+Row.objects(row_id=5).update(list_column__append=[6, 7])
+
+# prepend items to a list
+Row.objects(row_id=5).update(list_column__prepend=[1, 2])
+
+
+

Map

+
    +
  • update: adds the given keys/values to the columns, creating new entries if they didn’t exist, and overwriting old ones if they did

  • +
+
# add items to a map
+Row.objects(row_id=5).update(map_column__update={1: 2, 3: 4})
+
+# remove items from a map
+Row.objects(row_id=5).update(map_column__remove={1, 2})
+
+
+
+ +
+ +
+
+class cassandra.cqlengine.query.BatchQuery(batch_type=None, timestamp=None, consistency=None, execute_on_exception=False, timeout=<object object>, connection=None)
+

Handles the batching of queries

+

http://docs.datastax.com/en/cql/3.0/cql/cql_reference/batch_r.html

+

See Batch Queries for more details.

+
+
Parameters
+
    +
  • batch_type (BatchType, str or None) – (optional) One of batch type values available through BatchType enum

  • +
  • timestamp (datetime or timedelta or None) – (optional) A datetime or timedelta object with desired timestamp to be applied +to the batch conditional.

  • +
  • consistency (The ConsistencyLevel to be used for the batch query, or None.) – (optional) One of consistency values (“ANY”, “ONE”, “QUORUM” etc)

  • +
  • execute_on_exception (bool) – (Defaults to False) Indicates that when the BatchQuery instance is used +as a context manager the queries accumulated within the context must be executed despite +encountering an error within the context. By default, any exception raised from within +the context scope will cause the batched queries not to be executed.

  • +
  • timeout (float or None) – (optional) Timeout for the entire batch (in seconds), if not specified fallback +to default session timeout

  • +
  • connection (str) – Connection name to use for the batch execution

  • +
+
+
+
+
+add_query(query)
+
+ +
+
+execute()
+
+ +
+
+add_callback(fn, *args, **kwargs)
+

Add a function and arguments to be passed to it to be executed after the batch executes.

+

A batch can support multiple callbacks.

+

Note, that if the batch does not execute, the callbacks are not executed. +A callback, thus, is an “on batch success” handler.

+
+
Parameters
+
    +
  • fn (callable) – Callable object

  • +
  • *args – Positional arguments to be passed to the callback at the time of execution

  • +
  • **kwargs – Named arguments to be passed to the callback at the time of execution

  • +
+
+
+
+ +
+ +
+
+class cassandra.cqlengine.query.ContextQuery(*args, **kwargs)
+

A Context manager to allow a Model to switch context easily. Presently, the context only +specifies a keyspace for model IO.

+
+
Parameters
+
    +
  • *args – One or more models. A model should be a class type, not an instance.

  • +
  • **kwargs – (optional) Context parameters: can be keyspace or connection

  • +
+
+
+

For example:

+
with ContextQuery(Automobile, keyspace='test2') as A:
+    A.objects.create(manufacturer='honda', year=2008, model='civic')
+    print len(A.objects.all())  # 1 result
+
+with ContextQuery(Automobile, keyspace='test4') as A:
+    print len(A.objects.all())  # 0 result
+
+# Multiple models
+with ContextQuery(Automobile, Automobile2, connection='cluster2') as (A, A2):
+    print len(A.objects.all())
+    print len(A2.objects.all())
+
+
+
+ +
+
+class cassandra.cqlengine.query.DoesNotExist
+
+ +
+
+class cassandra.cqlengine.query.MultipleObjectsReturned
+
+ +
+
+class cassandra.cqlengine.query.LWTException(existing)
+

Lightweight conditional exception.

+

This exception will be raised when a write using an IF clause could not be +applied due to existing data violating the condition. The existing data is +available through the existing attribute.

+
+
Parameters
+

existing – The current state of the data which prevented the write.

+
+
+
+ +
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.24.8-scylla/api/cassandra/cqlengine/usertype.html b/3.24.8-scylla/api/cassandra/cqlengine/usertype.html new file mode 100644 index 0000000000..f41b602670 --- /dev/null +++ b/3.24.8-scylla/api/cassandra/cqlengine/usertype.html @@ -0,0 +1,683 @@ + + + + + + + + + + + + + cassandra.cqlengine.usertype - Model classes for User Defined Types | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.cqlengine.usertype - Model classes for User Defined Types

+
+

UserType

+
+
+class cassandra.cqlengine.usertype.UserType(**values)
+

This class is used to model User Defined Types. To define a type, declare a class inheriting from this, +and assign field types as class attributes:

+
# connect with default keyspace ...
+
+from cassandra.cqlengine.columns import Text, Integer
+from cassandra.cqlengine.usertype import UserType
+
+class address(UserType):
+    street = Text()
+    zipcode = Integer()
+
+from cassandra.cqlengine import management
+management.sync_type(address)
+
+
+

Please see User Defined Types for a complete example and discussion.

+
+
+__type_name__ = None
+

Optional. Sets the name of the CQL type for this type.

+

If not specified, the type name will be the name of the class, with it’s module name as it’s prefix.

+
+ +
+ +
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.24.8-scylla/api/cassandra/datastax/graph/fluent/index.html b/3.24.8-scylla/api/cassandra/datastax/graph/fluent/index.html new file mode 100644 index 0000000000..a948132cbd --- /dev/null +++ b/3.24.8-scylla/api/cassandra/datastax/graph/fluent/index.html @@ -0,0 +1,757 @@ + + + + + + + + + + + + + cassandra.datastax.graph.fluent | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.datastax.graph.fluent

+
+
+class cassandra.datastax.graph.fluent.DseGraph
+

Dse Graph utility class for GraphTraversal construction and execution.

+
+
+DSE_GRAPH_QUERY_LANGUAGE = 'bytecode-json'
+

Graph query language, Default is ‘bytecode-json’ (GraphSON).

+
+ +
+
+static create_execution_profile(graph_name, graph_protocol=b'graphson-2.0', **kwargs)
+

Creates an ExecutionProfile for GraphTraversal execution. You need to register that execution profile to the +cluster by using cluster.add_execution_profile.

+
+
Parameters
+
    +
  • graph_name – The graph name

  • +
  • graph_protocol – (Optional) The graph protocol, default is DSE_GRAPH_QUERY_PROTOCOL.

  • +
+
+
+
+ +
+
+static query_from_traversal(traversal, graph_protocol=b'graphson-2.0', context=None)
+

From a GraphTraversal, return a query string based on the language specified in DseGraph.DSE_GRAPH_QUERY_LANGUAGE.

+
+
Parameters
+
    +
  • traversal – The GraphTraversal object

  • +
  • graph_protocol – The graph protocol. Default is DseGraph.DSE_GRAPH_QUERY_PROTOCOL.

  • +
  • context – The dict of the serialization context, needed for GraphSON3 (tuple, udt). +e.g: {‘cluster’: cluster, ‘graph_name’: name}

  • +
+
+
+
+ +
+
+static traversal_source(session=None, graph_name=None, execution_profile=EXEC_PROFILE_GRAPH_DEFAULT, traversal_class=None)
+

Returns a TinkerPop GraphTraversalSource binded to the session and graph_name if provided.

+
+
Parameters
+
    +
  • session – (Optional) A DSE session

  • +
  • graph_name – (Optional) DSE Graph name

  • +
  • execution_profile – (Optional) Execution profile for traversal queries. Default is set to EXEC_PROFILE_GRAPH_DEFAULT.

  • +
  • traversal_class – (Optional) The GraphTraversalSource class to use (DSL).

  • +
+
+
+
from cassandra.cluster import Cluster
+from cassandra.datastax.graph.fluent import DseGraph
+
+c = Cluster()
+session = c.connect()
+
+g = DseGraph.traversal_source(session, 'my_graph')
+print g.V().valueMap().toList()
+
+
+
+ +
+
+static batch(session=None, execution_profile=None)
+

Returns the cassandra.datastax.graph.fluent.query.TraversalBatch object allowing to +execute multiple traversals in the same transaction.

+
+ +
+ +
+
+class cassandra.datastax.graph.fluent.DSESessionRemoteGraphConnection(session[, graph_name, execution_profile])
+

A Tinkerpop RemoteConnection to execute traversal queries on DSE.

+
+
Parameters
+
    +
  • session – A DSE session

  • +
  • graph_name – (Optional) DSE Graph name.

  • +
  • execution_profile – (Optional) Execution profile for traversal queries. Default is set to EXEC_PROFILE_GRAPH_DEFAULT.

  • +
+
+
+
+ +
+
+class cassandra.datastax.graph.fluent.BaseGraphRowFactory(cluster)
+

Base row factory for graph traversal. This class basically wraps a +graphson reader function to handle additional features of Gremlin/DSE +and is callable as a normal row factory.

+
+
Currently supported:
    +
  • bulk results

  • +
+
+
+
+ +
+
+cassandra.datastax.graph.fluent.graph_traversal_row_factory
+

alias of cassandra.datastax.graph.fluent._GremlinGraphSON2RowFactory

+
+ +
+
+cassandra.datastax.graph.fluent.graph_traversal_dse_object_row_factory
+

alias of cassandra.datastax.graph.fluent._DseGraphSON2RowFactory

+
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.24.8-scylla/api/cassandra/datastax/graph/fluent/predicates.html b/3.24.8-scylla/api/cassandra/datastax/graph/fluent/predicates.html new file mode 100644 index 0000000000..cb415eca59 --- /dev/null +++ b/3.24.8-scylla/api/cassandra/datastax/graph/fluent/predicates.html @@ -0,0 +1,753 @@ + + + + + + + + + + + + + cassandra.datastax.graph.fluent.predicates | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.datastax.graph.fluent.predicates

+
+
+class cassandra.datastax.graph.fluent.predicates.Search
+
+
+static token(value)
+

Search any instance of a certain token within the text property targeted. +:param value: the value to look for.

+
+ +
+
+static token_prefix(value)
+

Search any instance of a certain token prefix withing the text property targeted. +:param value: the value to look for.

+
+ +
+
+static token_regex(value)
+

Search any instance of the provided regular expression for the targeted property. +:param value: the value to look for.

+
+ +
+
+static prefix(value)
+

Search for a specific prefix at the beginning of the text property targeted. +:param value: the value to look for.

+
+ +
+
+static regex(value)
+

Search for this regular expression inside the text property targeted. +:param value: the value to look for.

+
+ +
+
+static fuzzy(value, distance)
+

Search for a fuzzy string inside the text property targeted. +:param value: the value to look for. +:param distance: The distance for the fuzzy search. ie. 1, to allow a one-letter misspellings.

+
+ +
+
+static token_fuzzy(value, distance)
+

Search for a token fuzzy inside the text property targeted. +:param value: the value to look for. +:param distance: The distance for the token fuzzy search. ie. 1, to allow a one-letter misspellings.

+
+ +
+
+static phrase(value, proximity)
+

Search for a phrase inside the text property targeted. +:param value: the value to look for. +:param proximity: The proximity for the phrase search. ie. phrase(‘David Felcey’, 2).. to find ‘David Felcey’ with up to two middle names.

+
+ +
+ +
+
+class cassandra.datastax.graph.fluent.predicates.CqlCollection
+
+
+static contains(value)
+

Search for a value inside a cql list/set column. +:param value: the value to look for.

+
+ +
+
+static contains_value(value)
+

Search for a map value. +:param value: the value to look for.

+
+ +
+
+static contains_key(value)
+

Search for a map key. +:param value: the value to look for.

+
+ +
+
+static entry_eq(value)
+

Search for a map entry. +:param value: the value to look for.

+
+ +
+ +
+
+class cassandra.datastax.graph.fluent.predicates.Geo
+
+
+static inside(value, units=1)
+

Search any instance of geometry inside the Distance targeted. +:param value: A Distance to look for. +:param units: The units for value. See GeoUnit enum. (Can also +provide an integer to use as a multiplier to convert value to +degrees.)

+
+ +
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.24.8-scylla/api/cassandra/datastax/graph/fluent/query.html b/3.24.8-scylla/api/cassandra/datastax/graph/fluent/query.html new file mode 100644 index 0000000000..ded836c2d0 --- /dev/null +++ b/3.24.8-scylla/api/cassandra/datastax/graph/fluent/query.html @@ -0,0 +1,704 @@ + + + + + + + + + + + + + cassandra.datastax.graph.fluent.query | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.datastax.graph.fluent.query

+
+
+class cassandra.datastax.graph.fluent.query.TraversalBatch(session=None, execution_profile=None)
+

A TraversalBatch is used to execute multiple graph traversals in a +single transaction. If any traversal in the batch fails, the entire +batch will fail to apply.

+

If a TraversalBatch is bounded to a DSE session, it can be executed using +traversal_batch.execute().

+
+
Parameters
+
    +
  • session – (Optional) A DSE session

  • +
  • execution_profile – (Optional) The execution profile to use for the batch execution

  • +
+
+
+
+
+add(traversal)
+

Add a traversal to the batch.

+
+
Parameters
+

traversal – A gremlin GraphTraversal

+
+
+
+ +
+
+add_all(traversals)
+

Adds a sequence of traversals to the batch.

+
+
Parameters
+

traversals – A sequence of gremlin GraphTraversal

+
+
+
+ +
+
+execute()
+

Execute the traversal batch if bounded to a DSE Session.

+
+ +
+
+as_graph_statement(graph_protocol=b'graphson-2.0')
+

Return the traversal batch as GraphStatement.

+
+
Parameters
+

graph_protocol – The graph protocol for the GraphSONWriter. Default is GraphProtocol.GRAPHSON_2_0.

+
+
+
+ +
+
+clear()
+

Clear a traversal batch for reuse.

+
+ +
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.24.8-scylla/api/cassandra/datastax/graph/index.html b/3.24.8-scylla/api/cassandra/datastax/graph/index.html new file mode 100644 index 0000000000..daac5c8b3c --- /dev/null +++ b/3.24.8-scylla/api/cassandra/datastax/graph/index.html @@ -0,0 +1,1035 @@ + + + + + + + + + + + + + cassandra.datastax.graph - Graph Statements, Options, and Row Factories | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.datastax.graph - Graph Statements, Options, and Row Factories

+
+
+cassandra.datastax.graph.single_object_row_factory(column_names, rows)
+

returns the JSON string value of graph results

+
+ +
+
+cassandra.datastax.graph.graph_result_row_factory(column_names, rows)
+

Returns a Result object that can load graph results and produce specific types. +The Result JSON is deserialized and unpacked from the top-level ‘result’ dict.

+
+ +
+
+cassandra.datastax.graph.graph_object_row_factory(column_names, rows)
+

Like graph_result_row_factory(), except known element types (Vertex, Edge) are +converted to their simplified objects. Some low-level metadata is shed in this conversion. Unknown result types are +still returned as Result.

+
+ +
+
+cassandra.datastax.graph.graph_graphson2_row_factory(cluster)
+

Row factory to deserialize GraphSON2 results.

+
+ +
+
+cassandra.datastax.graph.graph_graphson3_row_factory(cluster)
+

Row factory to deserialize GraphSON3 results.

+
+ +
+
+cassandra.datastax.graph.to_int(value)
+

Wraps a value to be explicitly serialized as a graphson Int.

+
+ +
+
+cassandra.datastax.graph.to_bigint(value)
+

Wraps a value to be explicitly serialized as a graphson Bigint.

+
+ +
+
+cassandra.datastax.graph.to_smallint(value)
+

Wraps a value to be explicitly serialized as a graphson Smallint.

+
+ +
+
+cassandra.datastax.graph.to_float(value)
+

Wraps a value to be explicitly serialized as a graphson Float.

+
+ +
+
+cassandra.datastax.graph.to_double(value)
+

Wraps a value to be explicitly serialized as a graphson Double.

+
+ +
+
+class cassandra.datastax.graph.GraphProtocol
+
+
+GRAPHSON_1_0 = b'graphson-1.0'
+

GraphSON1

+
+ +
+
+GRAPHSON_2_0 = b'graphson-2.0'
+

GraphSON2

+
+ +
+
+GRAPHSON_3_0 = b'graphson-3.0'
+

GraphSON3

+
+ +
+ +
+
+class cassandra.datastax.graph.GraphOptions(**kwargs)
+

Options for DSE Graph Query handler.

+
+
+graph_name
+

name of the targeted graph.

+
+ +
+
+graph_source
+

choose the graph traversal source, configured on the server side.

+
+ +
+
+graph_language
+

the language used in the queries (default “gremlin-groovy”)

+
+ +
+
+graph_read_consistency_level
+

read cassandra.ConsistencyLevel for graph queries (if distinct from session default). +Setting this overrides the native Statement.consistency_level for read operations from Cassandra persistence

+
+ +
+
+graph_write_consistency_level
+

write cassandra.ConsistencyLevel for graph queries (if distinct from session default). +Setting this overrides the native Statement.consistency_level for write operations to Cassandra persistence.

+
+ +
+
+is_default_source
+
+ +
+
+is_analytics_source
+

True if graph_source is set to the server-defined analytics traversal source (‘a’)

+
+ +
+
+is_graph_source
+

True if graph_source is set to the server-defined graph traversal source (‘g’)

+
+ +
+
+set_source_default()
+

Sets graph_source to the server-defined default traversal source (‘default’)

+
+ +
+
+set_source_analytics()
+

Sets graph_source to the server-defined analytic traversal source (‘a’)

+
+ +
+
+set_source_graph()
+

Sets graph_source to the server-defined graph traversal source (‘g’)

+
+ +
+ +
+
+class cassandra.datastax.graph.SimpleGraphStatement(query_string, retry_policy=None, consistency_level=None, routing_key=None, serial_consistency_level=None, fetch_size=<object object>, keyspace=None, custom_payload=None, is_idempotent=False)
+

Simple graph statement for Session.execute_graph(). +Takes the same parameters as SimpleStatement.

+

query_string should be a literal CQL statement with the exception +of parameter placeholders that will be filled through the +parameters argument of Session.execute().

+

See Statement attributes for a description of the other parameters.

+
+ +
+
+class cassandra.datastax.graph.Result(value)
+

Represents deserialized graph results. +Property and item getters are provided for convenience.

+
+
+value = None
+

Deserialized value from the result

+
+ +
+
+as_vertex()
+

Return a Vertex parsed from this result

+

Raises TypeError if parsing fails (i.e. the result structure is not valid).

+
+ +
+
+as_edge()
+

Return a Edge parsed from this result

+

Raises TypeError if parsing fails (i.e. the result structure is not valid).

+
+ +
+
+as_path()
+

Return a Path parsed from this result

+

Raises TypeError if parsing fails (i.e. the result structure is not valid).

+
+ +
+ +
+
+class cassandra.datastax.graph.Vertex(id, label, type, properties)
+

Represents a Vertex element from a graph query.

+

Vertex properties are extracted into a dict of property names to list of VertexProperty (list +because they are always encoded that way, and sometimes have multiple cardinality; VertexProperty because sometimes +the properties themselves have property maps).

+
+ +
+
+class cassandra.datastax.graph.VertexProperty(label, value, properties=None)
+

Vertex properties have a top-level value and an optional dict of properties.

+
+
+label = None
+

label of the property

+
+ +
+
+value = None
+

Value of the property

+
+ +
+
+properties = None
+

dict of properties attached to the property

+
+ +
+ +
+
+class cassandra.datastax.graph.Edge(id, label, type, properties, inV, inVLabel, outV, outVLabel)
+

Represents an Edge element from a graph query.

+

Attributes match initializer parameters.

+
+ +
+
+class cassandra.datastax.graph.Path(labels, objects)
+

Represents a graph path.

+

Labels list is taken verbatim from the results.

+

Objects are either Result or Vertex/Edge for recognized types

+
+
+labels = None
+

List of labels in the path

+
+ +
+
+objects = None
+

List of objects in the path

+
+ +
+ +
+
+class cassandra.datastax.graph.T(name, val)
+

Represents a collection of tokens for more concise Traversal definitions.

+
+
+id = T.id
+
+ +
+
+key = T.key
+
+ +
+
+label = T.label
+
+ +
+
+value = T.value
+
+ +
+ +
+
+class cassandra.datastax.graph.GraphSON1Serializer
+

Serialize python objects to graphson types.

+
+ +
+
+class cassandra.datastax.graph.GraphSON1Deserializer
+

Deserialize graphson1 types to python objects.

+
+
+classmethod deserialize_date(value)
+
+ +
+
+classmethod deserialize_timestamp(value)
+
+ +
+
+classmethod deserialize_time(value)
+
+ +
+
+classmethod deserialize_duration(value)
+
+ +
+
+classmethod deserialize_int(value)
+
+ +
+
+classmethod deserialize_bigint(value)
+
+ +
+
+classmethod deserialize_double(value)
+
+ +
+
+classmethod deserialize_float(value)
+
+ +
+
+classmethod deserialize_uuid(value)
+
+ +
+
+classmethod deserialize_blob(value)
+
+ +
+
+classmethod deserialize_decimal(value)
+
+ +
+
+classmethod deserialize_point(value)
+
+ +
+
+classmethod deserialize_linestring(value)
+
+ +
+
+classmethod deserialize_polygon(value)
+
+ +
+ +
+
+class cassandra.datastax.graph.GraphSON2Reader(context, extra_deserializer_map=None)
+

GraphSON2 Reader that parse json and deserialize to python objects.

+
+
Parameters
+

extra_deserializer_map – map from GraphSON type tag to deserializer instance implementing deserialize

+
+
+
+
+read(json_data)
+

Read and deserialize json_data.

+
+ +
+
+deserialize(obj)
+

Deserialize GraphSON type-tagged dict values into objects mapped in self.deserializers

+
+ +
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.24.8-scylla/api/cassandra/decoder.html b/3.24.8-scylla/api/cassandra/decoder.html new file mode 100644 index 0000000000..d4bb950a85 --- /dev/null +++ b/3.24.8-scylla/api/cassandra/decoder.html @@ -0,0 +1,665 @@ + + + + + + + + + + + + + cassandra.decoder - Data Return Formats | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.decoder - Data Return Formats

+
+
+cassandra.decoder.tuple_factory()
+

Deprecated in 2.0.0. Use cassandra.query.tuple_factory()

+
+ +
+
+cassandra.decoder.named_tuple_factory()
+

Deprecated in 2.0.0. Use cassandra.query.named_tuple_factory()

+
+ +
+
+cassandra.decoder.dict_factory()
+

Deprecated in 2.0.0. Use cassandra.query.dict_factory()

+
+ +
+
+cassandra.decoder.ordered_dict_factory()
+

Deprecated in 2.0.0. Use cassandra.query.ordered_dict_factory()

+
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.24.8-scylla/api/cassandra/encoder.html b/3.24.8-scylla/api/cassandra/encoder.html new file mode 100644 index 0000000000..42414cc389 --- /dev/null +++ b/3.24.8-scylla/api/cassandra/encoder.html @@ -0,0 +1,742 @@ + + + + + + + + + + + + + cassandra.encoder - Encoders for non-prepared Statements | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.encoder - Encoders for non-prepared Statements

+
+
+class cassandra.encoder.Encoder
+

A container for mapping python types to CQL string literals when working +with non-prepared statements. The type mapping can be +directly customized by users.

+
+
+mapping = None
+

A map of python types to encoder functions.

+
+ +
+
+cql_encode_none()
+

Converts None to the string ‘NULL’.

+
+ +
+
+cql_encode_object()
+

Default encoder for all objects that do not have a specific encoder function +registered. This function simply calls str() on the object.

+
+ +
+
+cql_encode_all_types()
+

Converts any type into a CQL string, defaulting to cql_encode_object +if mapping does not contain an entry for the type.

+
+ +
+
+cql_encode_sequence()
+

Converts a sequence to a string of the form (item1, item2, ...). This +is suitable for IN value lists.

+
+ +
+
+cql_encode_str()
+

Escapes quotes in str objects.

+
+ +
+
+cql_encode_unicode()
+

Converts unicode objects to UTF-8 encoded strings with quote escaping.

+
+ +
+
+cql_encode_bytes()
+

Converts strings, buffers, and bytearrays into CQL blob literals.

+
+ +
+
+cql_encode_datetime()
+

Converts a datetime.datetime object to a (string) integer timestamp +with millisecond precision.

+
+ +
+
+cql_encode_date()
+

Converts a datetime.date object to a string with format +YYYY-MM-DD.

+
+ +
+
+cql_encode_map_collection()
+

Converts a dict into a string of the form {key1: val1, key2: val2, ...}. +This is suitable for map type columns.

+
+ +
+
+cql_encode_list_collection()
+

Converts a sequence to a string of the form [item1, item2, ...]. This +is suitable for list type columns.

+
+ +
+
+cql_encode_set_collection()
+

Converts a sequence to a string of the form {item1, item2, ...}. This +is suitable for set type columns.

+
+ +
+
+cql_encode_tuple()
+

Converts a sequence to a string of the form (item1, item2, ...). This +is suitable for tuple type columns.

+
+ +
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.24.8-scylla/api/cassandra/graph.html b/3.24.8-scylla/api/cassandra/graph.html new file mode 100644 index 0000000000..e78d94c7bd --- /dev/null +++ b/3.24.8-scylla/api/cassandra/graph.html @@ -0,0 +1,1028 @@ + + + + + + + + + + + + + cassandra.graph - Graph Statements, Options, and Row Factories | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.graph - Graph Statements, Options, and Row Factories

+
+

Note

+

This module is only for backward compatibility for dse-driver users. Consider using cassandra.datastax.graph.

+
+
+
+cassandra.graph.single_object_row_factory(column_names, rows)
+

returns the JSON string value of graph results

+
+ +
+
+cassandra.graph.graph_result_row_factory(column_names, rows)
+

Returns a Result object that can load graph results and produce specific types. +The Result JSON is deserialized and unpacked from the top-level ‘result’ dict.

+
+ +
+
+cassandra.graph.graph_object_row_factory(column_names, rows)
+

Like graph_result_row_factory(), except known element types (Vertex, Edge) are +converted to their simplified objects. Some low-level metadata is shed in this conversion. Unknown result types are +still returned as Result.

+
+ +
+
+cassandra.graph.graph_graphson2_row_factory(cluster)
+

Row factory to deserialize GraphSON2 results.

+
+ +
+
+cassandra.graph.graph_graphson3_row_factory(cluster)
+

Row factory to deserialize GraphSON3 results.

+
+ +
+
+cassandra.graph.to_int(value)
+

Wraps a value to be explicitly serialized as a graphson Int.

+
+ +
+
+cassandra.graph.to_bigint(value)
+

Wraps a value to be explicitly serialized as a graphson Bigint.

+
+ +
+
+cassandra.graph.to_smallint(value)
+

Wraps a value to be explicitly serialized as a graphson Smallint.

+
+ +
+
+cassandra.graph.to_float(value)
+

Wraps a value to be explicitly serialized as a graphson Float.

+
+ +
+
+cassandra.graph.to_double(value)
+

Wraps a value to be explicitly serialized as a graphson Double.

+
+ +
+
+class cassandra.graph.GraphProtocol
+
+
+GRAPHSON_1_0 = b'graphson-1.0'
+

GraphSON1

+
+ +
+
+GRAPHSON_2_0 = b'graphson-2.0'
+

GraphSON2

+
+ +
+
+GRAPHSON_3_0 = b'graphson-3.0'
+

GraphSON3

+
+ +
+ +
+
+class cassandra.graph.GraphOptions(**kwargs)
+

Options for DSE Graph Query handler.

+
+
+graph_name
+

name of the targeted graph.

+
+ +
+
+graph_source
+

choose the graph traversal source, configured on the server side.

+
+ +
+
+graph_language
+

the language used in the queries (default “gremlin-groovy”)

+
+ +
+
+graph_read_consistency_level
+

read cassandra.ConsistencyLevel for graph queries (if distinct from session default). +Setting this overrides the native Statement.consistency_level for read operations from Cassandra persistence

+
+ +
+
+graph_write_consistency_level
+

write cassandra.ConsistencyLevel for graph queries (if distinct from session default). +Setting this overrides the native Statement.consistency_level for write operations to Cassandra persistence.

+
+ +
+
+is_default_source
+
+ +
+
+is_analytics_source
+

True if graph_source is set to the server-defined analytics traversal source (‘a’)

+
+ +
+
+is_graph_source
+

True if graph_source is set to the server-defined graph traversal source (‘g’)

+
+ +
+
+set_source_default()
+

Sets graph_source to the server-defined default traversal source (‘default’)

+
+ +
+
+set_source_analytics()
+

Sets graph_source to the server-defined analytic traversal source (‘a’)

+
+ +
+
+set_source_graph()
+

Sets graph_source to the server-defined graph traversal source (‘g’)

+
+ +
+ +
+
+class cassandra.graph.SimpleGraphStatement(query_string, retry_policy=None, consistency_level=None, routing_key=None, serial_consistency_level=None, fetch_size=<object object>, keyspace=None, custom_payload=None, is_idempotent=False)
+

Simple graph statement for Session.execute_graph(). +Takes the same parameters as SimpleStatement.

+

query_string should be a literal CQL statement with the exception +of parameter placeholders that will be filled through the +parameters argument of Session.execute().

+

See Statement attributes for a description of the other parameters.

+
+ +
+
+class cassandra.graph.Result(value)
+

Represents deserialized graph results. +Property and item getters are provided for convenience.

+
+
+value = None
+

Deserialized value from the result

+
+ +
+
+as_vertex()
+

Return a Vertex parsed from this result

+

Raises TypeError if parsing fails (i.e. the result structure is not valid).

+
+ +
+
+as_edge()
+

Return a Edge parsed from this result

+

Raises TypeError if parsing fails (i.e. the result structure is not valid).

+
+ +
+
+as_path()
+

Return a Path parsed from this result

+

Raises TypeError if parsing fails (i.e. the result structure is not valid).

+
+ +
+ +
+
+class cassandra.graph.Vertex(id, label, type, properties)
+

Represents a Vertex element from a graph query.

+

Vertex properties are extracted into a dict of property names to list of VertexProperty (list +because they are always encoded that way, and sometimes have multiple cardinality; VertexProperty because sometimes +the properties themselves have property maps).

+
+ +
+
+class cassandra.graph.VertexProperty(label, value, properties=None)
+

Vertex properties have a top-level value and an optional dict of properties.

+
+
+label = None
+

label of the property

+
+ +
+
+value = None
+

Value of the property

+
+ +
+
+properties = None
+

dict of properties attached to the property

+
+ +
+ +
+
+class cassandra.graph.Edge(id, label, type, properties, inV, inVLabel, outV, outVLabel)
+

Represents an Edge element from a graph query.

+

Attributes match initializer parameters.

+
+ +
+
+class cassandra.graph.Path(labels, objects)
+

Represents a graph path.

+

Labels list is taken verbatim from the results.

+

Objects are either Result or Vertex/Edge for recognized types

+
+
+labels = None
+

List of labels in the path

+
+ +
+
+objects = None
+

List of objects in the path

+
+ +
+ +
+
+class cassandra.graph.GraphSON1Serializer
+

Serialize python objects to graphson types.

+
+ +
+
+class cassandra.graph.GraphSON1Deserializer
+

Deserialize graphson1 types to python objects.

+
+
+classmethod deserialize_date(value)
+
+ +
+
+classmethod deserialize_timestamp(value)
+
+ +
+
+classmethod deserialize_time(value)
+
+ +
+
+classmethod deserialize_duration(value)
+
+ +
+
+classmethod deserialize_int(value)
+
+ +
+
+classmethod deserialize_bigint(value)
+
+ +
+
+classmethod deserialize_double(value)
+
+ +
+
+classmethod deserialize_float(value)
+
+ +
+
+classmethod deserialize_uuid(value)
+
+ +
+
+classmethod deserialize_blob(value)
+
+ +
+
+classmethod deserialize_decimal(value)
+
+ +
+
+classmethod deserialize_point(value)
+
+ +
+
+classmethod deserialize_linestring(value)
+
+ +
+
+classmethod deserialize_polygon(value)
+
+ +
+ +
+
+class cassandra.graph.GraphSON2Reader(context, extra_deserializer_map=None)
+

GraphSON2 Reader that parse json and deserialize to python objects.

+
+
Parameters
+

extra_deserializer_map – map from GraphSON type tag to deserializer instance implementing deserialize

+
+
+
+
+read(json_data)
+

Read and deserialize json_data.

+
+ +
+
+deserialize(obj)
+

Deserialize GraphSON type-tagged dict values into objects mapped in self.deserializers

+
+ +
+ +
+
+class cassandra.graph.GraphSON3Reader(context, extra_deserializer_map=None)
+

GraphSON3 Reader that parse json and deserialize to python objects.

+
+
Parameters
+
    +
  • context – A dict of the context, mostly used as context for udt deserialization.

  • +
  • extra_deserializer_map – map from GraphSON type tag to deserializer instance implementing deserialize

  • +
+
+
+
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.24.8-scylla/api/cassandra/io/asyncioreactor.html b/3.24.8-scylla/api/cassandra/io/asyncioreactor.html new file mode 100644 index 0000000000..25b8bb0ff2 --- /dev/null +++ b/3.24.8-scylla/api/cassandra/io/asyncioreactor.html @@ -0,0 +1,657 @@ + + + + + + + + + + + + + cassandra.io.asyncioreactor - asyncio Event Loop | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.io.asyncioreactor - asyncio Event Loop

+
+
+class cassandra.io.asyncioreactor.AsyncioConnection(*args, **kwargs)
+

An experimental implementation of Connection that uses the +asyncio module in the Python standard library for its event loop.

+

Note that it requires asyncio features that were only introduced in the +3.4 line in 3.4.6, and in the 3.5 line in 3.5.1.

+
+
+classmethod initialize_reactor()
+

Called once by Cluster.connect(). This should be used by implementations +to set up any resources that will be shared across connections.

+
+ +
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.24.8-scylla/api/cassandra/io/asyncorereactor.html b/3.24.8-scylla/api/cassandra/io/asyncorereactor.html new file mode 100644 index 0000000000..de9327958f --- /dev/null +++ b/3.24.8-scylla/api/cassandra/io/asyncorereactor.html @@ -0,0 +1,662 @@ + + + + + + + + + + + + + cassandra.io.asyncorereactor - asyncore Event Loop | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.io.asyncorereactor - asyncore Event Loop

+
+
+class cassandra.io.asyncorereactor.AsyncoreConnection(*args, **kwargs)
+

An implementation of Connection that uses the asyncore +module in the Python standard library for its event loop.

+
+
+classmethod initialize_reactor()
+

Called once by Cluster.connect(). This should be used by implementations +to set up any resources that will be shared across connections.

+
+ +
+
+classmethod handle_fork()
+

Called after a forking. This should cleanup any remaining reactor state +from the parent process.

+
+ +
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.24.8-scylla/api/cassandra/io/eventletreactor.html b/3.24.8-scylla/api/cassandra/io/eventletreactor.html new file mode 100644 index 0000000000..8c8e79376a --- /dev/null +++ b/3.24.8-scylla/api/cassandra/io/eventletreactor.html @@ -0,0 +1,664 @@ + + + + + + + + + + + + + cassandra.io.eventletreactor - eventlet-compatible Connection | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.io.eventletreactor - eventlet-compatible Connection

+
+
+class cassandra.io.eventletreactor.EventletConnection(*args, **kwargs)
+

An implementation of Connection that utilizes eventlet.

+

This implementation assumes all eventlet monkey patching is active. It is not tested with partial patching.

+
+
+classmethod initialize_reactor()
+

Called once by Cluster.connect(). This should be used by implementations +to set up any resources that will be shared across connections.

+
+ +
+
+classmethod service_timeouts()
+

cls._timeout_watcher runs in this loop forever. +It is usually waiting for the next timeout on the cls._new_timer Event. +When new timers are added, that event is set so that the watcher can +wake up and possibly set an earlier timeout.

+
+ +
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.24.8-scylla/api/cassandra/io/geventreactor.html b/3.24.8-scylla/api/cassandra/io/geventreactor.html new file mode 100644 index 0000000000..bb70e540b9 --- /dev/null +++ b/3.24.8-scylla/api/cassandra/io/geventreactor.html @@ -0,0 +1,655 @@ + + + + + + + + + + + + + cassandra.io.geventreactor - gevent-compatible Event Loop | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.io.geventreactor - gevent-compatible Event Loop

+
+
+class cassandra.io.geventreactor.GeventConnection(*args, **kwargs)
+

An implementation of Connection that utilizes gevent.

+

This implementation assumes all gevent monkey patching is active. It is not tested with partial patching.

+
+
+classmethod initialize_reactor()
+

Called once by Cluster.connect(). This should be used by implementations +to set up any resources that will be shared across connections.

+
+ +
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.24.8-scylla/api/cassandra/io/libevreactor.html b/3.24.8-scylla/api/cassandra/io/libevreactor.html new file mode 100644 index 0000000000..9730ac8577 --- /dev/null +++ b/3.24.8-scylla/api/cassandra/io/libevreactor.html @@ -0,0 +1,647 @@ + + + + + + + + + + + + + cassandra.io.libevreactor - libev Event Loop | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.io.libevreactor - libev Event Loop

+
+
+class cassandra.io.libevreactor.LibevConnection(*args, **kwargs)
+

An implementation of Connection that uses libev for its event loop.

+
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.24.8-scylla/api/cassandra/io/twistedreactor.html b/3.24.8-scylla/api/cassandra/io/twistedreactor.html new file mode 100644 index 0000000000..87ee0333c4 --- /dev/null +++ b/3.24.8-scylla/api/cassandra/io/twistedreactor.html @@ -0,0 +1,648 @@ + + + + + + + + + + + + + cassandra.io.twistedreactor - Twisted Event Loop | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.io.twistedreactor - Twisted Event Loop

+
+
+class cassandra.io.twistedreactor.TwistedConnection
+

An implementation of Connection that uses +Twisted’s reactor as its event loop.

+
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.24.8-scylla/api/cassandra/metadata.html b/3.24.8-scylla/api/cassandra/metadata.html new file mode 100644 index 0000000000..f21be61d5f --- /dev/null +++ b/3.24.8-scylla/api/cassandra/metadata.html @@ -0,0 +1,1032 @@ + + + + + + + + + + + + + cassandra.metadata - Schema and Ring Topology | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.metadata - Schema and Ring Topology

+
+
+cassandra.metadata.cql_keywords
+

set() -> new empty set object +set(iterable) -> new set object

+

Build an unordered collection of unique elements.

+
+ +
+
+cassandra.metadata.cql_keywords_unreserved
+

set() -> new empty set object +set(iterable) -> new set object

+

Build an unordered collection of unique elements.

+
+ +
+
+cassandra.metadata.cql_keywords_reserved
+

set() -> new empty set object +set(iterable) -> new set object

+

Build an unordered collection of unique elements.

+
+ +
+
+class cassandra.metadata.Metadata
+

Holds a representation of the cluster schema and topology.

+
+
+add_or_return_host(host)
+

Returns a tuple (host, new), where host is a Host +instance, and new is a bool indicating whether +the host was newly added.

+
+ +
+
+all_hosts()
+

Returns a list of all known Host instances in the cluster.

+
+ +
+
+export_schema_as_string()
+

Returns a string that can be executed as a query in order to recreate +the entire schema. The string is formatted to be human readable.

+
+ +
+
+get_host(endpoint_or_address, port=None)
+

Find a host in the metadata for a specific endpoint. If a string inet address and port are passed, +iterate all hosts to match the broadcast_rpc_address and +broadcast_rpc_port attributes.

+
+ +
+
+get_host_by_host_id(host_id)
+

Same as get_host() but use host_id for lookup.

+
+ +
+
+get_replicas(keyspace, key)
+

Returns a list of Host instances that are replicas for a given +partition key.

+
+ +
+ +
+

Schemas

+
+
+class cassandra.metadata.KeyspaceMetadata
+

A representation of the schema for a single keyspace.

+
+
+as_cql_query()
+

Returns a CQL query string that can be used to recreate just this keyspace, +not including user-defined types and tables.

+
+ +
+
+export_as_string()
+

Returns a CQL query string that can be used to recreate the entire keyspace, +including user-defined types and tables.

+
+ +
+ +
+
+class cassandra.metadata.UserType
+

A user defined type, as created by CREATE TYPE statements.

+

User-defined types were introduced in Cassandra 2.1.

+
+

New in version 2.1.0.

+
+
+
+as_cql_query(formatted=False)
+

Returns a CQL query that can be used to recreate this type. +If formatted is set to True, extra whitespace will +be added to make the query more readable.

+
+ +
+ +
+
+class cassandra.metadata.Function
+

A user defined function, as created by CREATE FUNCTION statements.

+

User-defined functions were introduced in Cassandra 2.2

+
+

New in version 2.6.0.

+
+
+
+as_cql_query(formatted=False)
+

Returns a CQL query that can be used to recreate this function. +If formatted is set to True, extra whitespace will +be added to make the query more readable.

+
+ +
+ +
+
+class cassandra.metadata.Aggregate
+

A user defined aggregate function, as created by CREATE AGGREGATE statements.

+

Aggregate functions were introduced in Cassandra 2.2

+
+

New in version 2.6.0.

+
+
+
+as_cql_query(formatted=False)
+

Returns a CQL query that can be used to recreate this aggregate. +If formatted is set to True, extra whitespace will +be added to make the query more readable.

+
+ +
+ +
+
+class cassandra.metadata.TableMetadata
+

A representation of the schema for a single table.

+
+
+as_cql_query(formatted=False)
+

Returns a CQL query that can be used to recreate this table (index +creations are not included). If formatted is set to True, +extra whitespace will be added to make the query human readable.

+
+ +
+
+export_as_string()
+

Returns a string of CQL queries that can be used to recreate this table +along with all indexes on it. The returned string is formatted to +be human readable.

+
+ +
+
+property is_cql_compatible
+

A boolean indicating if this table can be represented as CQL in export

+
+ +
+
+property primary_key
+

A list of ColumnMetadata representing the components of +the primary key for this table.

+
+ +
+ +
+
+class cassandra.metadata.TableMetadataV3
+

For C* 3.0+. option_maps take a superset of map names, so if nothing +changes structurally, new option maps can just be appended to the list.

+
+
+property is_cql_compatible
+

A boolean indicating if this table can be represented as CQL in export

+
+ +
+ +
+
+class cassandra.metadata.TableMetadataDSE68
+
+
+as_cql_query(formatted=False)
+

Returns a CQL query that can be used to recreate this table (index +creations are not included). If formatted is set to True, +extra whitespace will be added to make the query human readable.

+
+ +
+ +
+
+class cassandra.metadata.ColumnMetadata
+

A representation of a single column in a table.

+
+ +
+
+class cassandra.metadata.IndexMetadata
+

A representation of a secondary index on a column.

+
+
+as_cql_query()
+

Returns a CQL query that can be used to recreate this index.

+
+ +
+
+export_as_string()
+

Returns a CQL query string that can be used to recreate this index.

+
+ +
+ +
+
+class cassandra.metadata.MaterializedViewMetadata
+

A representation of a materialized view on a table

+
+
+as_cql_query(formatted=False)
+

Returns a CQL query that can be used to recreate this function. +If formatted is set to True, extra whitespace will +be added to make the query more readable.

+
+ +
+ +
+
+class cassandra.metadata.VertexMetadata
+

A representation of a vertex on a table

+
+ +
+
+class cassandra.metadata.EdgeMetadata
+

A representation of an edge on a table

+
+ +
+
+

Tokens and Ring Topology

+
+
+class cassandra.metadata.TokenMap
+

Information about the layout of the ring.

+
+
+get_replicas(keyspace, token)
+

Get a set of Host instances representing all of the +replica nodes for a given Token.

+
+ +
+ +
+
+class cassandra.metadata.Token
+

Abstract class representing a token.

+
+ +
+
+class cassandra.metadata.Murmur3Token(token)
+

A token for Murmur3Partitioner.

+

token is an int or string representing the token.

+
+ +
+
+class cassandra.metadata.MD5Token(token)
+

A token for RandomPartitioner.

+
+ +
+
+class cassandra.metadata.BytesToken(token)
+

A token for ByteOrderedPartitioner.

+
+
+classmethod from_string(token_string)
+

token_string should be the string representation from the server.

+
+ +
+ +
+
+cassandra.metadata.ReplicationStrategy
+

alias of cassandra.metadata._ReplicationStrategy

+
+ +
+
+class cassandra.metadata.ReplicationFactor(all_replicas, transient_replicas=None)
+

Represent the replication factor of a keyspace.

+
+ +
+
+class cassandra.metadata.SimpleStrategy(options_map)
+
+
+export_for_schema()
+

Returns a string version of these replication options which are +suitable for use in a CREATE KEYSPACE statement.

+
+ +
+
+property replication_factor
+

The replication factor for this keyspace.

+

For backward compatibility, this returns the +cassandra.metadata.ReplicationFactor.full_replicas value of +cassandra.metadata.SimpleStrategy.replication_factor_info.

+
+ +
+ +
+
+class cassandra.metadata.NetworkTopologyStrategy(dc_replication_factors)
+
+
+export_for_schema()
+

Returns a string version of these replication options which are +suitable for use in a CREATE KEYSPACE statement.

+
+ +
+ +
+
+class cassandra.metadata.LocalStrategy(options_map)
+
+
+export_for_schema()
+

Returns a string version of these replication options which are +suitable for use in a CREATE KEYSPACE statement.

+
+ +
+ +
+
+cassandra.metadata.group_keys_by_replica(session, keyspace, table, keys)
+

Returns a dict with the keys grouped per host. This can be +used to more accurately group by IN clause or to batch the keys per host.

+

If a valid replica is not found for a particular key it will be grouped under +NO_VALID_REPLICA

+

Example usage:

+
>>> result = group_keys_by_replica(
+...     session, "system", "peers",
+...     (("127.0.0.1", ), ("127.0.0.2", )))
+
+
+
+ +
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.24.8-scylla/api/cassandra/metrics.html b/3.24.8-scylla/api/cassandra/metrics.html new file mode 100644 index 0000000000..e0ad31596b --- /dev/null +++ b/3.24.8-scylla/api/cassandra/metrics.html @@ -0,0 +1,755 @@ + + + + + + + + + + + + + cassandra.metrics - Performance Metrics | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.metrics - Performance Metrics

+
+
+class cassandra.metrics.Metrics
+

A collection of timers and counters for various performance metrics.

+

Timer metrics are represented as floating point seconds.

+
+
+request_timer = None
+

A greplin.scales.PmfStat timer for requests. This is a dict-like +object with the following keys:

+
    +
  • count - number of requests that have been timed

  • +
  • min - min latency

  • +
  • max - max latency

  • +
  • mean - mean latency

  • +
  • stddev - standard deviation for latencies

  • +
  • median - median latency

  • +
  • 75percentile - 75th percentile latencies

  • +
  • 95percentile - 95th percentile latencies

  • +
  • 98percentile - 98th percentile latencies

  • +
  • 99percentile - 99th percentile latencies

  • +
  • 999percentile - 99.9th percentile latencies

  • +
+
+ +
+
+connection_errors = None
+

A greplin.scales.IntStat count of the number of times that a +request to a Cassandra node has failed due to a connection problem.

+
+ +
+
+write_timeouts = None
+

A greplin.scales.IntStat count of write requests that resulted +in a timeout.

+
+ +
+
+read_timeouts = None
+

A greplin.scales.IntStat count of read requests that resulted +in a timeout.

+
+ +
+
+unavailables = None
+

A greplin.scales.IntStat count of write or read requests that +failed due to an insufficient number of replicas being alive to meet +the requested ConsistencyLevel.

+
+ +
+
+other_errors = None
+

A greplin.scales.IntStat count of all other request failures, +including failures caused by invalid requests, bootstrapping nodes, +overloaded nodes, etc.

+
+ +
+
+retries = None
+

A greplin.scales.IntStat count of the number of times a +request was retried based on the RetryPolicy decision.

+
+ +
+
+ignores = None
+

A greplin.scales.IntStat count of the number of times a +failed request was ignored based on the RetryPolicy decision.

+
+ +
+
+known_hosts = None
+

A greplin.scales.IntStat count of the number of nodes in +the cluster that the driver is aware of, regardless of whether any +connections are opened to those nodes.

+
+ +
+
+connected_to = None
+

A greplin.scales.IntStat count of the number of nodes that +the driver currently has at least one connection open to.

+
+ +
+
+open_connections = None
+

A greplin.scales.IntStat count of the number connections +the driver currently has open.

+
+ +
+
+get_stats()
+

Returns the metrics for the registered cluster instance.

+
+ +
+
+set_stats_name(stats_name)
+

Set the metrics stats name. +The stats_name is a string used to access the metris through scales: scales.getStats()[<stats_name>] +Default is ‘cassandra-<num>’.

+
+ +
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.24.8-scylla/api/cassandra/policies.html b/3.24.8-scylla/api/cassandra/policies.html new file mode 100644 index 0000000000..b364cab4cc --- /dev/null +++ b/3.24.8-scylla/api/cassandra/policies.html @@ -0,0 +1,1742 @@ + + + + + + + + + + + + + cassandra.policies - Load balancing and Failure Handling Policies | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.policies - Load balancing and Failure Handling Policies

+
+

Load Balancing

+
+
+class cassandra.policies.HostDistance
+

A measure of how “distant” a node is from the client, which +may influence how the load balancer distributes requests +and how many connections are opened to the node.

+
+
+IGNORED = -1
+

A node with this distance should never be queried or have +connections opened to it.

+
+ +
+
+LOCAL = 0
+

Nodes with LOCAL distance will be preferred for operations +under some load balancing policies (such as DCAwareRoundRobinPolicy) +and will have a greater number of connections opened against +them by default.

+

This distance is typically used for nodes within the same +datacenter as the client.

+
+ +
+
+REMOTE = 1
+

Nodes with REMOTE distance will be treated as a last resort +by some load balancing policies (such as DCAwareRoundRobinPolicy) +and will have a smaller number of connections opened against +them by default.

+

This distance is typically used for nodes outside of the +datacenter that the client is running in.

+
+ +
+ +
+
+class cassandra.policies.LoadBalancingPolicy
+

Load balancing policies are used to decide how to distribute +requests among all possible coordinator nodes in the cluster.

+

In particular, they may focus on querying “near” nodes (those +in a local datacenter) or on querying nodes who happen to +be replicas for the requested data.

+

You may also use subclasses of LoadBalancingPolicy for +custom behavior.

+
+
+distance(host)
+

Returns a measure of how remote a Host is in +terms of the HostDistance enums.

+
+ +
+
+populate(cluster, hosts)
+

This method is called to initialize the load balancing +policy with a set of Host instances before its +first use. The cluster parameter is an instance of +Cluster.

+
+ +
+
+make_query_plan(working_keyspace=None, query=None)
+

Given a Statement instance, return a iterable +of Host instances which should be queried in that +order. A generator may work well for custom implementations +of this method.

+

Note that the query argument may be None when preparing +statements.

+

working_keyspace should be the string name of the current keyspace, +as set through Session.set_keyspace() or with a USE +statement.

+
+ +
+
+check_supported()
+

This will be called after the cluster Metadata has been initialized. +If the load balancing policy implementation cannot be supported for +some reason (such as a missing C extension), this is the point at +which it should raise an exception.

+
+ +
+ +
+
+class cassandra.policies.RoundRobinPolicy
+

A subclass of LoadBalancingPolicy which evenly +distributes queries across all nodes in the cluster, +regardless of what datacenter the nodes may be in.

+
+
+populate(cluster, hosts)
+

This method is called to initialize the load balancing +policy with a set of Host instances before its +first use. The cluster parameter is an instance of +Cluster.

+
+ +
+
+distance(host)
+

Returns a measure of how remote a Host is in +terms of the HostDistance enums.

+
+ +
+
+make_query_plan(working_keyspace=None, query=None)
+

Given a Statement instance, return a iterable +of Host instances which should be queried in that +order. A generator may work well for custom implementations +of this method.

+

Note that the query argument may be None when preparing +statements.

+

working_keyspace should be the string name of the current keyspace, +as set through Session.set_keyspace() or with a USE +statement.

+
+ +
+
+on_up(host)
+

Called when a node is marked up.

+
+ +
+
+on_down(host)
+

Called when a node is marked down.

+
+ +
+
+on_add(host)
+

Called when a node is added to the cluster. The newly added node +should be considered up.

+
+ +
+
+on_remove(host)
+

Called when a node is removed from the cluster.

+
+ +
+ +
+
+class cassandra.policies.DCAwareRoundRobinPolicy(local_dc='', used_hosts_per_remote_dc=0)
+

Similar to RoundRobinPolicy, but prefers hosts +in the local datacenter and only uses nodes in remote +datacenters as a last resort.

+

The local_dc parameter should be the name of the datacenter +(such as is reported by nodetool ring) that should +be considered local. If not specified, the driver will choose +a local_dc based on the first host among Cluster.contact_points +having a valid DC. If relying on this mechanism, all specified +contact points should be nodes in a single, local DC.

+

used_hosts_per_remote_dc controls how many nodes in +each remote datacenter will have connections opened +against them. In other words, used_hosts_per_remote_dc hosts +will be considered REMOTE and the +rest will be considered IGNORED. +By default, all remote hosts are ignored.

+
+
+populate(cluster, hosts)
+

This method is called to initialize the load balancing +policy with a set of Host instances before its +first use. The cluster parameter is an instance of +Cluster.

+
+ +
+
+distance(host)
+

Returns a measure of how remote a Host is in +terms of the HostDistance enums.

+
+ +
+
+make_query_plan(working_keyspace=None, query=None)
+

Given a Statement instance, return a iterable +of Host instances which should be queried in that +order. A generator may work well for custom implementations +of this method.

+

Note that the query argument may be None when preparing +statements.

+

working_keyspace should be the string name of the current keyspace, +as set through Session.set_keyspace() or with a USE +statement.

+
+ +
+
+on_up(host)
+

Called when a node is marked up.

+
+ +
+
+on_down(host)
+

Called when a node is marked down.

+
+ +
+
+on_add(host)
+

Called when a node is added to the cluster. The newly added node +should be considered up.

+
+ +
+
+on_remove(host)
+

Called when a node is removed from the cluster.

+
+ +
+ +
+
+class cassandra.policies.WhiteListRoundRobinPolicy(hosts)
+

A subclass of RoundRobinPolicy which evenly +distributes queries across all nodes in the cluster, +regardless of what datacenter the nodes may be in, but +only if that node exists in the list of allowed nodes

+

This policy is addresses the issue described in +https://datastax-oss.atlassian.net/browse/JAVA-145 +Where connection errors occur when connection +attempts are made to private IP addresses remotely

+

The hosts parameter should be a sequence of hosts to permit +connections to.

+
+
+populate(cluster, hosts)
+

This method is called to initialize the load balancing +policy with a set of Host instances before its +first use. The cluster parameter is an instance of +Cluster.

+
+ +
+
+distance(host)
+

Returns a measure of how remote a Host is in +terms of the HostDistance enums.

+
+ +
+
+on_up(host)
+

Called when a node is marked up.

+
+ +
+
+on_add(host)
+

Called when a node is added to the cluster. The newly added node +should be considered up.

+
+ +
+ +
+
+class cassandra.policies.TokenAwarePolicy(child_policy, shuffle_replicas=False)
+

A LoadBalancingPolicy wrapper that adds token awareness to +a child policy.

+

This alters the child policy’s behavior so that it first attempts to +send queries to LOCAL replicas (as determined +by the child policy) based on the Statement’s +routing_key. If shuffle_replicas is +truthy, these replicas will be yielded in a random order. Once those +hosts are exhausted, the remaining hosts in the child policy’s query +plan will be used in the order provided by the child policy.

+

If no routing_key is set on the query, the child +policy’s query plan will be used as is.

+
+
+shuffle_replicas = False
+

Yield local replicas in a random order.

+
+ +
+
+populate(cluster, hosts)
+

This method is called to initialize the load balancing +policy with a set of Host instances before its +first use. The cluster parameter is an instance of +Cluster.

+
+ +
+
+check_supported()
+

This will be called after the cluster Metadata has been initialized. +If the load balancing policy implementation cannot be supported for +some reason (such as a missing C extension), this is the point at +which it should raise an exception.

+
+ +
+
+distance(*args, **kwargs)
+

Returns a measure of how remote a Host is in +terms of the HostDistance enums.

+
+ +
+
+make_query_plan(working_keyspace=None, query=None)
+

Given a Statement instance, return a iterable +of Host instances which should be queried in that +order. A generator may work well for custom implementations +of this method.

+

Note that the query argument may be None when preparing +statements.

+

working_keyspace should be the string name of the current keyspace, +as set through Session.set_keyspace() or with a USE +statement.

+
+ +
+
+on_up(*args, **kwargs)
+

Called when a node is marked up.

+
+ +
+
+on_down(*args, **kwargs)
+

Called when a node is marked down.

+
+ +
+
+on_add(*args, **kwargs)
+

Called when a node is added to the cluster. The newly added node +should be considered up.

+
+ +
+
+on_remove(*args, **kwargs)
+

Called when a node is removed from the cluster.

+
+ +
+ +
+
+class cassandra.policies.HostFilterPolicy(child_policy, predicate)
+

A LoadBalancingPolicy subclass configured with a child policy, +and a single-argument predicate. This policy defers to the child policy for +hosts where predicate(host) is truthy. Hosts for which +predicate(host) is falsey will be considered IGNORED, and will +not be used in a query plan.

+

This can be used in the cases where you need a whitelist or blacklist +policy, e.g. to prepare for decommissioning nodes or for testing:

+
def address_is_ignored(host):
+    return host.address in [ignored_address0, ignored_address1]
+
+blacklist_filter_policy = HostFilterPolicy(
+    child_policy=RoundRobinPolicy(),
+    predicate=address_is_ignored
+)
+
+cluster = Cluster(
+    primary_host,
+    load_balancing_policy=blacklist_filter_policy,
+)
+
+
+

See the note in the make_query_plan() documentation for a caveat on +how wrapping ordering polices (e.g. RoundRobinPolicy) may break +desirable properties of the wrapped policy.

+

Please note that whitelist and blacklist policies are not recommended for +general, day-to-day use. You probably want something like +DCAwareRoundRobinPolicy, which prefers a local DC but has +fallbacks, over a brute-force method like whitelisting or blacklisting.

+
+
Parameters
+
    +
  • child_policy – an instantiated LoadBalancingPolicy +that this one will defer to.

  • +
  • predicate – a one-parameter function that takes a Host. +If it returns a falsey value, the Host will +be IGNORED and not returned in query plans.

  • +
+
+
+
+
+predicate(host)
+

A predicate, set on object initialization, that takes a Host +and returns a value. If the value is falsy, the Host is +IGNORED. If the value is truthy, +HostFilterPolicy defers to the child policy to determine the +host’s distance.

+

This is a read-only value set in __init__, implemented as a +property.

+
+ +
+
+distance(host)
+

Checks if predicate(host), then returns +IGNORED if falsey, and defers to the child policy +otherwise.

+
+ +
+
+make_query_plan(working_keyspace=None, query=None)
+

Defers to the child policy’s +LoadBalancingPolicy.make_query_plan() and filters the results.

+

Note that this filtering may break desirable properties of the wrapped +policy in some cases. For instance, imagine if you configure this +policy to filter out host2, and to wrap a round-robin policy that +rotates through three hosts in the order host1, host2, host3, +host2, host3, host1, host3, host1, host2, repeating. This +policy will yield host1, host3, host3, host1, host3, host1, +disproportionately favoring host3.

+
+ +
+ +
+
+class cassandra.policies.DefaultLoadBalancingPolicy(child_policy)
+

A LoadBalancingPolicy wrapper that adds the ability to target a specific host first.

+

If no host is set on the query, the child policy’s query plan will be used as is.

+
+
+populate(cluster, hosts)
+

This method is called to initialize the load balancing +policy with a set of Host instances before its +first use. The cluster parameter is an instance of +Cluster.

+
+ +
+
+make_query_plan(working_keyspace=None, query=None)
+

Given a Statement instance, return a iterable +of Host instances which should be queried in that +order. A generator may work well for custom implementations +of this method.

+

Note that the query argument may be None when preparing +statements.

+

working_keyspace should be the string name of the current keyspace, +as set through Session.set_keyspace() or with a USE +statement.

+
+ +
+ +
+
+class cassandra.policies.DSELoadBalancingPolicy(*args, **kwargs)
+

Deprecated: This will be removed in the next major release, +consider using DefaultLoadBalancingPolicy.

+
+ +
+
+

Translating Server Node Addresses

+
+
+class cassandra.policies.AddressTranslator
+

Interface for translating cluster-defined endpoints.

+

The driver discovers nodes using server metadata and topology change events. Normally, +the endpoint defined by the server is the right way to connect to a node. In some environments, +these addresses may not be reachable, or not preferred (public vs. private IPs in cloud environments, +suboptimal routing, etc). This interface allows for translating from server defined endpoints to +preferred addresses for driver connections.

+

Note: contact_points provided while creating the Cluster instance are not +translated using this mechanism – only addresses received from Cassandra nodes are.

+
+
+translate(addr)
+

Accepts the node ip address, and returns a translated address to be used connecting to this node.

+
+ +
+ +
+
+class cassandra.policies.IdentityTranslator
+

Returns the endpoint with no translation

+
+
+translate(addr)
+

Accepts the node ip address, and returns a translated address to be used connecting to this node.

+
+ +
+ +
+
+class cassandra.policies.EC2MultiRegionTranslator
+

Resolves private ips of the hosts in the same datacenter as the client, and public ips of hosts in other datacenters.

+
+
+translate(addr)
+

Reverse DNS the public broadcast_address, then lookup that hostname to get the AWS-resolved IP, which +will point to the private IP address within the same datacenter.

+
+ +
+ +
+
+

Marking Hosts Up or Down

+
+
+class cassandra.policies.ConvictionPolicy(host)
+

A policy which decides when hosts should be considered down +based on the types of failures and the number of failures.

+

If custom behavior is needed, this class may be subclassed.

+

host is an instance of Host.

+
+
+add_failure(connection_exc)
+

Implementations should return True if the host should be +convicted, False otherwise.

+
+ +
+
+reset()
+

Implementations should clear out any convictions or state regarding +the host.

+
+ +
+ +
+
+class cassandra.policies.SimpleConvictionPolicy(host)
+

The default implementation of ConvictionPolicy, +which simply marks a host as down after the first failure +of any kind.

+

host is an instance of Host.

+
+
+add_failure(connection_exc)
+

Implementations should return True if the host should be +convicted, False otherwise.

+
+ +
+
+reset()
+

Implementations should clear out any convictions or state regarding +the host.

+
+ +
+ +
+
+

Reconnecting to Dead Hosts

+
+
+class cassandra.policies.ReconnectionPolicy
+

This class and its subclasses govern how frequently an attempt is made +to reconnect to nodes that are marked as dead.

+

If custom behavior is needed, this class may be subclassed.

+
+
+new_schedule()
+

This should return a finite or infinite iterable of delays (each as a +floating point number of seconds) inbetween each failed reconnection +attempt. Note that if the iterable is finite, reconnection attempts +will cease once the iterable is exhausted.

+
+ +
+ +
+
+class cassandra.policies.ConstantReconnectionPolicy(delay, max_attempts=64)
+

A ReconnectionPolicy subclass which sleeps for a fixed delay +inbetween each reconnection attempt.

+

delay should be a floating point number of seconds to wait inbetween +each attempt.

+

max_attempts should be a total number of attempts to be made before +giving up, or None to continue reconnection attempts forever. +The default is 64.

+
+
+new_schedule()
+

This should return a finite or infinite iterable of delays (each as a +floating point number of seconds) inbetween each failed reconnection +attempt. Note that if the iterable is finite, reconnection attempts +will cease once the iterable is exhausted.

+
+ +
+ +
+
+class cassandra.policies.ExponentialReconnectionPolicy(base_delay, max_delay, max_attempts=64)
+

A ReconnectionPolicy subclass which exponentially increases +the length of the delay inbetween each reconnection attempt up to +a set maximum delay.

+

A random amount of jitter (+/- 15%) will be added to the pure exponential +delay value to avoid the situations where many reconnection handlers are +trying to reconnect at exactly the same time.

+

base_delay and max_delay should be in floating point units of +seconds.

+

max_attempts should be a total number of attempts to be made before +giving up, or None to continue reconnection attempts forever. +The default is 64.

+
+
+new_schedule()
+

This should return a finite or infinite iterable of delays (each as a +floating point number of seconds) inbetween each failed reconnection +attempt. Note that if the iterable is finite, reconnection attempts +will cease once the iterable is exhausted.

+
+ +
+ +
+
+

Retrying Failed Operations

+
+
+class cassandra.policies.WriteType
+

For usage with RetryPolicy, this describe a type +of write operation.

+
+
+SIMPLE = 0
+

A write to a single partition key. Such writes are guaranteed to be atomic +and isolated.

+
+ +
+
+BATCH = 1
+

A write to multiple partition keys that used the distributed batch log to +ensure atomicity.

+
+ +
+
+UNLOGGED_BATCH = 2
+

A write to multiple partition keys that did not use the distributed batch +log. Atomicity for such writes is not guaranteed.

+
+ +
+
+COUNTER = 3
+

A counter write (for one or multiple partition keys). Such writes should +not be replayed in order to avoid overcount.

+
+ +
+
+BATCH_LOG = 4
+

The initial write to the distributed batch log that Cassandra performs +internally before a BATCH write.

+
+ +
+
+CAS = 5
+

A lighweight-transaction write, such as “DELETE … IF EXISTS”.

+
+ +
+
+VIEW = 6
+

This WriteType is only seen in results for requests that were unable to +complete MV operations.

+
+ +
+
+CDC = 7
+

This WriteType is only seen in results for requests that were unable to +complete CDC operations.

+
+ +
+ +
+
+class cassandra.policies.RetryPolicy
+

A policy that describes whether to retry, rethrow, or ignore coordinator +timeout and unavailable failures. These are failures reported from the +server side. Timeouts are configured by +settings in cassandra.yaml. +Unavailable failures occur when the coordinator cannot acheive the consistency +level for a request. For further information see the method descriptions +below.

+

To specify a default retry policy, set the +Cluster.default_retry_policy attribute to an instance of this +class or one of its subclasses.

+

To specify a retry policy per query, set the Statement.retry_policy +attribute to an instance of this class or one of its subclasses.

+

If custom behavior is needed for retrying certain operations, +this class may be subclassed.

+
+
+RETRY = 0
+

This should be returned from the below methods if the operation +should be retried on the same connection.

+
+ +
+
+RETHROW = 1
+

This should be returned from the below methods if the failure +should be propagated and no more retries attempted.

+
+ +
+
+IGNORE = 2
+

This should be returned from the below methods if the failure +should be ignored but no more retries should be attempted.

+
+ +
+
+RETRY_NEXT_HOST = 3
+

This should be returned from the below methods if the operation +should be retried on another connection.

+
+ +
+
+on_read_timeout(query, consistency, required_responses, received_responses, data_retrieved, retry_num)
+

This is called when a read operation times out from the coordinator’s +perspective (i.e. a replica did not respond to the coordinator in time). +It should return a tuple with two items: one of the class enums (such +as RETRY) and a ConsistencyLevel to retry the +operation at or None to keep the same consistency level.

+

query is the Statement that timed out.

+

consistency is the ConsistencyLevel that the operation was +attempted at.

+

The required_responses and received_responses parameters describe +how many replicas needed to respond to meet the requested consistency +level and how many actually did respond before the coordinator timed +out the request. data_retrieved is a boolean indicating whether +any of those responses contained data (as opposed to just a digest).

+

retry_num counts how many times the operation has been retried, so +the first time this method is called, retry_num will be 0.

+

By default, operations will be retried at most once, and only if +a sufficient number of replicas responded (with data digests).

+
+ +
+
+on_write_timeout(query, consistency, write_type, required_responses, received_responses, retry_num)
+

This is called when a write operation times out from the coordinator’s +perspective (i.e. a replica did not respond to the coordinator in time).

+

query is the Statement that timed out.

+

consistency is the ConsistencyLevel that the operation was +attempted at.

+

write_type is one of the WriteType enums describing the +type of write operation.

+

The required_responses and received_responses parameters describe +how many replicas needed to acknowledge the write to meet the requested +consistency level and how many replicas actually did acknowledge the +write before the coordinator timed out the request.

+

retry_num counts how many times the operation has been retried, so +the first time this method is called, retry_num will be 0.

+

By default, failed write operations will retried at most once, and +they will only be retried if the write_type was +BATCH_LOG.

+
+ +
+
+on_unavailable(query, consistency, required_replicas, alive_replicas, retry_num)
+

This is called when the coordinator node determines that a read or +write operation cannot be successful because the number of live +replicas are too low to meet the requested ConsistencyLevel. +This means that the read or write operation was never forwarded to +any replicas.

+

query is the Statement that failed.

+

consistency is the ConsistencyLevel that the operation was +attempted at.

+

required_replicas is the number of replicas that would have needed to +acknowledge the operation to meet the requested consistency level. +alive_replicas is the number of replicas that the coordinator +considered alive at the time of the request.

+

retry_num counts how many times the operation has been retried, so +the first time this method is called, retry_num will be 0.

+

By default, if this is the first retry, it triggers a retry on the next +host in the query plan with the same consistency level. If this is not the +first retry, no retries will be attempted and the error will be re-raised.

+
+ +
+
+on_request_error(query, consistency, error, retry_num)
+

This is called when an unexpected error happens. This can be in the +following situations:

+
    +
  • On a connection error

  • +
  • On server errors: overloaded, isBootstrapping, serverError, etc.

  • +
+

query is the Statement that timed out.

+

consistency is the ConsistencyLevel that the operation was +attempted at.

+

error the instance of the exception.

+

retry_num counts how many times the operation has been retried, so +the first time this method is called, retry_num will be 0.

+

The default, it triggers a retry on the next host in the query plan +with the same consistency level.

+
+ +
+ +
+
+class cassandra.policies.FallthroughRetryPolicy
+

A retry policy that never retries and always propagates failures to +the application.

+
+
+on_read_timeout(*args, **kwargs)
+

This is called when a read operation times out from the coordinator’s +perspective (i.e. a replica did not respond to the coordinator in time). +It should return a tuple with two items: one of the class enums (such +as RETRY) and a ConsistencyLevel to retry the +operation at or None to keep the same consistency level.

+

query is the Statement that timed out.

+

consistency is the ConsistencyLevel that the operation was +attempted at.

+

The required_responses and received_responses parameters describe +how many replicas needed to respond to meet the requested consistency +level and how many actually did respond before the coordinator timed +out the request. data_retrieved is a boolean indicating whether +any of those responses contained data (as opposed to just a digest).

+

retry_num counts how many times the operation has been retried, so +the first time this method is called, retry_num will be 0.

+

By default, operations will be retried at most once, and only if +a sufficient number of replicas responded (with data digests).

+
+ +
+
+on_write_timeout(*args, **kwargs)
+

This is called when a write operation times out from the coordinator’s +perspective (i.e. a replica did not respond to the coordinator in time).

+

query is the Statement that timed out.

+

consistency is the ConsistencyLevel that the operation was +attempted at.

+

write_type is one of the WriteType enums describing the +type of write operation.

+

The required_responses and received_responses parameters describe +how many replicas needed to acknowledge the write to meet the requested +consistency level and how many replicas actually did acknowledge the +write before the coordinator timed out the request.

+

retry_num counts how many times the operation has been retried, so +the first time this method is called, retry_num will be 0.

+

By default, failed write operations will retried at most once, and +they will only be retried if the write_type was +BATCH_LOG.

+
+ +
+
+on_unavailable(*args, **kwargs)
+

This is called when the coordinator node determines that a read or +write operation cannot be successful because the number of live +replicas are too low to meet the requested ConsistencyLevel. +This means that the read or write operation was never forwarded to +any replicas.

+

query is the Statement that failed.

+

consistency is the ConsistencyLevel that the operation was +attempted at.

+

required_replicas is the number of replicas that would have needed to +acknowledge the operation to meet the requested consistency level. +alive_replicas is the number of replicas that the coordinator +considered alive at the time of the request.

+

retry_num counts how many times the operation has been retried, so +the first time this method is called, retry_num will be 0.

+

By default, if this is the first retry, it triggers a retry on the next +host in the query plan with the same consistency level. If this is not the +first retry, no retries will be attempted and the error will be re-raised.

+
+ +
+
+on_request_error(*args, **kwargs)
+

This is called when an unexpected error happens. This can be in the +following situations:

+
    +
  • On a connection error

  • +
  • On server errors: overloaded, isBootstrapping, serverError, etc.

  • +
+

query is the Statement that timed out.

+

consistency is the ConsistencyLevel that the operation was +attempted at.

+

error the instance of the exception.

+

retry_num counts how many times the operation has been retried, so +the first time this method is called, retry_num will be 0.

+

The default, it triggers a retry on the next host in the query plan +with the same consistency level.

+
+ +
+ +
+
+class cassandra.policies.DowngradingConsistencyRetryPolicy(*args, **kwargs)
+

Deprecated: This retry policy will be removed in the next major release.

+

A retry policy that sometimes retries with a lower consistency level than +the one initially requested.

+

BEWARE: This policy may retry queries using a lower consistency +level than the one initially requested. By doing so, it may break +consistency guarantees. In other words, if you use this retry policy, +there are cases (documented below) where a read at QUORUM +may not see a preceding write at QUORUM. Do not use this +policy unless you have understood the cases where this can happen and +are ok with that. It is also recommended to subclass this class so +that queries that required a consistency level downgrade can be +recorded (so that repairs can be made later, etc).

+

This policy implements the same retries as RetryPolicy, +but on top of that, it also retries in the following cases:

+
    +
  • On a read timeout: if the number of replicas that responded is +greater than one but lower than is required by the requested +consistency level, the operation is retried at a lower consistency +level.

  • +
  • On a write timeout: if the operation is an UNLOGGED_BATCH +and at least one replica acknowledged the write, the operation is +retried at a lower consistency level. Furthermore, for other +write types, if at least one replica acknowledged the write, the +timeout is ignored.

  • +
  • On an unavailable exception: if at least one replica is alive, the +operation is retried at a lower consistency level.

  • +
+

The reasoning behind this retry policy is as follows: if, based +on the information the Cassandra coordinator node returns, retrying the +operation with the initially requested consistency has a chance to +succeed, do it. Otherwise, if based on that information we know the +initially requested consistency level cannot be achieved currently, then:

+
    +
  • For writes, ignore the exception (thus silently failing the +consistency requirement) if we know the write has been persisted on at +least one replica.

  • +
  • For reads, try reading at a lower consistency level (thus silently +failing the consistency requirement).

  • +
+

In other words, this policy implements the idea that if the requested +consistency level cannot be achieved, the next best thing for writes is +to make sure the data is persisted, and that reading something is better +than reading nothing, even if there is a risk of reading stale data.

+
+
+on_read_timeout(query, consistency, required_responses, received_responses, data_retrieved, retry_num)
+

This is called when a read operation times out from the coordinator’s +perspective (i.e. a replica did not respond to the coordinator in time). +It should return a tuple with two items: one of the class enums (such +as RETRY) and a ConsistencyLevel to retry the +operation at or None to keep the same consistency level.

+

query is the Statement that timed out.

+

consistency is the ConsistencyLevel that the operation was +attempted at.

+

The required_responses and received_responses parameters describe +how many replicas needed to respond to meet the requested consistency +level and how many actually did respond before the coordinator timed +out the request. data_retrieved is a boolean indicating whether +any of those responses contained data (as opposed to just a digest).

+

retry_num counts how many times the operation has been retried, so +the first time this method is called, retry_num will be 0.

+

By default, operations will be retried at most once, and only if +a sufficient number of replicas responded (with data digests).

+
+ +
+
+on_write_timeout(query, consistency, write_type, required_responses, received_responses, retry_num)
+

This is called when a write operation times out from the coordinator’s +perspective (i.e. a replica did not respond to the coordinator in time).

+

query is the Statement that timed out.

+

consistency is the ConsistencyLevel that the operation was +attempted at.

+

write_type is one of the WriteType enums describing the +type of write operation.

+

The required_responses and received_responses parameters describe +how many replicas needed to acknowledge the write to meet the requested +consistency level and how many replicas actually did acknowledge the +write before the coordinator timed out the request.

+

retry_num counts how many times the operation has been retried, so +the first time this method is called, retry_num will be 0.

+

By default, failed write operations will retried at most once, and +they will only be retried if the write_type was +BATCH_LOG.

+
+ +
+
+on_unavailable(query, consistency, required_replicas, alive_replicas, retry_num)
+

This is called when the coordinator node determines that a read or +write operation cannot be successful because the number of live +replicas are too low to meet the requested ConsistencyLevel. +This means that the read or write operation was never forwarded to +any replicas.

+

query is the Statement that failed.

+

consistency is the ConsistencyLevel that the operation was +attempted at.

+

required_replicas is the number of replicas that would have needed to +acknowledge the operation to meet the requested consistency level. +alive_replicas is the number of replicas that the coordinator +considered alive at the time of the request.

+

retry_num counts how many times the operation has been retried, so +the first time this method is called, retry_num will be 0.

+

By default, if this is the first retry, it triggers a retry on the next +host in the query plan with the same consistency level. If this is not the +first retry, no retries will be attempted and the error will be re-raised.

+
+ +
+ +
+
+

Retrying Idempotent Operations

+
+
+class cassandra.policies.SpeculativeExecutionPolicy
+

Interface for specifying speculative execution plans

+
+
+new_plan(keyspace, statement)
+

Returns

+
+
Parameters
+
    +
  • keyspace

  • +
  • statement

  • +
+
+
Returns
+

+
+
+
+ +
+ +
+
+class cassandra.policies.ConstantSpeculativeExecutionPolicy(delay, max_attempts)
+

A speculative execution policy that sends a new query every X seconds (delay) for a maximum of Y attempts (max_attempts).

+
+
+new_plan(keyspace, statement)
+

Returns

+
+
Parameters
+
    +
  • keyspace

  • +
  • statement

  • +
+
+
Returns
+

+
+
+
+ +
+ +
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.24.8-scylla/api/cassandra/pool.html b/3.24.8-scylla/api/cassandra/pool.html new file mode 100644 index 0000000000..9706709636 --- /dev/null +++ b/3.24.8-scylla/api/cassandra/pool.html @@ -0,0 +1,673 @@ + + + + + + + + + + + + + cassandra.pool - Hosts and Connection Pools | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.pool - Hosts and Connection Pools

+

Connection pooling and host management.

+
+
+class cassandra.pool.Host
+

Represents a single Cassandra node.

+
+
+property address
+

The IP address of the endpoint. This is the RPC address the driver uses when connecting to the node.

+
+ +
+
+property datacenter
+

The datacenter the node is in.

+
+ +
+
+property rack
+

The rack the node is in.

+
+ +
+ +
+
+exception cassandra.pool.NoConnectionsAvailable
+

All existing connections to a given host are busy, or there are +no open connections.

+
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.24.8-scylla/api/cassandra/protocol.html b/3.24.8-scylla/api/cassandra/protocol.html new file mode 100644 index 0000000000..e09ab6feab --- /dev/null +++ b/3.24.8-scylla/api/cassandra/protocol.html @@ -0,0 +1,739 @@ + + + + + + + + + + + + + cassandra.protocol - Protocol Features | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.protocol - Protocol Features

+
+

Custom Payloads

+

Native protocol version 4+ allows for a custom payload to be sent between clients +and custom query handlers. The payload is specified as a string:binary_type dict +holding custom key/value pairs.

+

By default these are ignored by the server. They can be useful for servers implementing +a custom QueryHandler.

+

See Session.execute(), :Session.execute_async(), ResponseFuture.custom_payload.

+
+
+class cassandra.protocol._ProtocolHandler
+

_ProtocolHander handles encoding and decoding messages.

+

This class can be specialized to compose Handlers which implement alternative +result decoding or type deserialization. Class definitions are passed to cassandra.cluster.Cluster +on initialization.

+

Contracted class methods are _ProtocolHandler.encode_message() and _ProtocolHandler.decode_message().

+
+
+message_types_by_opcode = {default mapping}
+
+ +
+
+classmethod encode_message(msg, stream_id, protocol_version, compressor, allow_beta_protocol_version)
+

Encodes a message using the specified frame parameters, and compressor

+
+
Parameters
+
    +
  • msg – the message, typically of cassandra.protocol._MessageType, generated by the driver

  • +
  • stream_id – protocol stream id for the frame header

  • +
  • protocol_version – version for the frame header, and used encoding contents

  • +
  • compressor – optional compression function to be used on the body

  • +
+
+
+
+ +
+
+classmethod decode_message(protocol_version, user_type_map, stream_id, flags, opcode, body, decompressor, result_metadata)
+

Decodes a native protocol message body

+
+
Parameters
+
    +
  • protocol_version – version to use decoding contents

  • +
  • user_type_map – map[keyspace name] = map[type name] = custom type to instantiate when deserializing this type

  • +
  • stream_id – native protocol stream id from the frame header

  • +
  • flags – native protocol flags bitmap from the header

  • +
  • opcode – native protocol opcode from the header

  • +
  • body – frame body

  • +
  • decompressor – optional decompression function to inflate the body

  • +
+
+
Returns
+

a message decoded from the body and frame attributes

+
+
+
+ +
+ +
+
+

Faster Deserialization

+

When python-driver is compiled with Cython, it uses a Cython-based deserialization path +to deserialize messages. By default, the driver will use a Cython-based parser that returns +lists of rows similar to the pure-Python version. In addition, there are two additional +ProtocolHandler classes that can be used to deserialize response messages: LazyProtocolHandler +and NumpyProtocolHandler. They can be used as follows:

+
from cassandra.protocol import NumpyProtocolHandler, LazyProtocolHandler
+from cassandra.query import tuple_factory
+s.client_protocol_handler = LazyProtocolHandler   # for a result iterator
+s.row_factory = tuple_factory  #required for Numpy results
+s.client_protocol_handler = NumpyProtocolHandler  # for a dict of NumPy arrays as result
+
+
+

These protocol handlers comprise different parsers, and return results as described below:

+
    +
  • ProtocolHandler: this default implementation is a drop-in replacement for the pure-Python version. +The rows are all parsed upfront, before results are returned.

  • +
  • LazyProtocolHandler: near drop-in replacement for the above, except that it returns an iterator over rows, +lazily decoded into the default row format (this is more efficient since all decoded results are not materialized at once)

  • +
  • NumpyProtocolHander: deserializes results directly into NumPy arrays. This facilitates efficient integration with +analysis toolkits such as Pandas.

  • +
+
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.24.8-scylla/api/cassandra/query.html b/3.24.8-scylla/api/cassandra/query.html new file mode 100644 index 0000000000..635684b192 --- /dev/null +++ b/3.24.8-scylla/api/cassandra/query.html @@ -0,0 +1,1002 @@ + + + + + + + + + + + + + cassandra.query - Prepared Statements, Batch Statements, Tracing, and Row Factories | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.query - Prepared Statements, Batch Statements, Tracing, and Row Factories

+
+
+cassandra.query.tuple_factory(colnames, rows)
+

Returns each row as a tuple

+

Example:

+
>>> from cassandra.query import tuple_factory
+>>> session = cluster.connect('mykeyspace')
+>>> session.row_factory = tuple_factory
+>>> rows = session.execute("SELECT name, age FROM users LIMIT 1")
+>>> print rows[0]
+('Bob', 42)
+
+
+
+

Changed in version 2.0.0: moved from cassandra.decoder to cassandra.query

+
+
+ +
+
+cassandra.query.named_tuple_factory(colnames, rows)
+

Returns each row as a namedtuple. +This is the default row factory.

+

Example:

+
>>> from cassandra.query import named_tuple_factory
+>>> session = cluster.connect('mykeyspace')
+>>> session.row_factory = named_tuple_factory
+>>> rows = session.execute("SELECT name, age FROM users LIMIT 1")
+>>> user = rows[0]
+
+>>> # you can access field by their name:
+>>> print "name: %s, age: %d" % (user.name, user.age)
+name: Bob, age: 42
+
+>>> # or you can access fields by their position (like a tuple)
+>>> name, age = user
+>>> print "name: %s, age: %d" % (name, age)
+name: Bob, age: 42
+>>> name = user[0]
+>>> age = user[1]
+>>> print "name: %s, age: %d" % (name, age)
+name: Bob, age: 42
+
+
+
+

Changed in version 2.0.0: moved from cassandra.decoder to cassandra.query

+
+
+ +
+
+cassandra.query.dict_factory(colnames, rows)
+

Returns each row as a dict.

+

Example:

+
>>> from cassandra.query import dict_factory
+>>> session = cluster.connect('mykeyspace')
+>>> session.row_factory = dict_factory
+>>> rows = session.execute("SELECT name, age FROM users LIMIT 1")
+>>> print rows[0]
+{u'age': 42, u'name': u'Bob'}
+
+
+
+

Changed in version 2.0.0: moved from cassandra.decoder to cassandra.query

+
+
+ +
+
+cassandra.query.ordered_dict_factory(colnames, rows)
+

Like dict_factory(), but returns each row as an OrderedDict, +so the order of the columns is preserved.

+
+

Changed in version 2.0.0: moved from cassandra.decoder to cassandra.query

+
+
+ +
+
+class cassandra.query.SimpleStatement(query_string, retry_policy=None, consistency_level=None, routing_key=None, serial_consistency_level=None, fetch_size=<object object>, keyspace=None, custom_payload=None, is_idempotent=False)
+

A simple, un-prepared query.

+

query_string should be a literal CQL statement with the exception +of parameter placeholders that will be filled through the +parameters argument of Session.execute().

+

See Statement attributes for a description of the other parameters.

+
+ +
+
+class cassandra.query.PreparedStatement
+

A statement that has been prepared against at least one Cassandra node. +Instances of this class should not be created directly, but through +Session.prepare().

+

A PreparedStatement should be prepared only once. Re-preparing a statement +may affect performance (as the operation requires a network roundtrip).

+

A note about * in prepared statements: Do not use * in prepared statements if you might +change the schema of the table being queried. The driver and server each +maintain a map between metadata for a schema and statements that were +prepared against that schema. When a user changes a schema, e.g. by adding +or removing a column, the server invalidates its mappings involving that +schema. However, there is currently no way to propagate that invalidation +to drivers. Thus, after a schema change, the driver will incorrectly +interpret the results of SELECT * queries prepared before the schema +change. This is currently being addressed in CASSANDRA-10786.

+
+
+bind(values)
+

Creates and returns a BoundStatement instance using values.

+

See BoundStatement.bind() for rules on input values.

+
+ +
+ +
+
+class cassandra.query.BoundStatement(prepared_statement, retry_policy=None, consistency_level=None, routing_key=None, serial_consistency_level=None, fetch_size=<object object>, keyspace=None, custom_payload=None)
+

A prepared statement that has been bound to a particular set of values. +These may be created directly or through PreparedStatement.bind().

+

prepared_statement should be an instance of PreparedStatement.

+

See Statement attributes for a description of the other parameters.

+
+
+bind(values)
+

Binds a sequence of values for the prepared statement parameters +and returns this instance. Note that values must be:

+
    +
  • a sequence, even if you are only binding one value, or

  • +
  • a dict that relates 1-to-1 between dict keys and columns

  • +
+
+

Changed in version 2.6.0: UNSET_VALUE was introduced. These can be bound as positional parameters +in a sequence, or by name in a dict. Additionally, when using protocol v4+:

+
    +
  • short sequences will be extended to match bind parameters with UNSET_VALUE

  • +
  • names may be omitted from a dict with UNSET_VALUE implied.

  • +
+
+
+

Changed in version 3.0.0: method will not throw if extra keys are present in bound dict (PYTHON-178)

+
+
+ +
+
+property routing_key
+

The partition_key portion of the primary key, +which can be used to determine which nodes are replicas for the query.

+

If the partition key is a composite, a list or tuple must be passed in. +Each key component should be in its packed (binary) format, so all +components should be strings.

+
+ +
+ +
+
+class cassandra.query.Statement
+

An abstract class representing a single query. There are three subclasses: +SimpleStatement, BoundStatement, and BatchStatement. +These can be passed to Session.execute().

+
+
+property routing_key
+

The partition_key portion of the primary key, +which can be used to determine which nodes are replicas for the query.

+

If the partition key is a composite, a list or tuple must be passed in. +Each key component should be in its packed (binary) format, so all +components should be strings.

+
+ +
+
+property serial_consistency_level
+

The serial consistency level is only used by conditional updates +(INSERT, UPDATE and DELETE with an IF condition). For +those, the serial_consistency_level defines the consistency level of +the serial phase (or “paxos” phase) while the normal +consistency_level defines the consistency for the “learn” phase, +i.e. what type of reads will be guaranteed to see the update right away. +For example, if a conditional write has a consistency_level of +QUORUM (and is successful), then a +QUORUM read is guaranteed to see that write. +But if the regular consistency_level of that write is +ANY, then only a read with a +consistency_level of SERIAL is +guaranteed to see it (even a read with consistency +ALL is not guaranteed to be enough).

+

The serial consistency can only be one of SERIAL +or LOCAL_SERIAL. While SERIAL guarantees full +linearizability (with other SERIAL updates), LOCAL_SERIAL only +guarantees it in the local data center.

+

The serial consistency level is ignored for any query that is not a +conditional update. Serial reads should use the regular +consistency_level.

+

Serial consistency levels may only be used against Cassandra 2.0+ +and the protocol_version must be set to 2 or higher.

+

See Lightweight Transactions (Compare-and-set) for a discussion on how to work with results returned from +conditional statements.

+
+

New in version 2.0.0.

+
+
+ +
+ +
+
+cassandra.query.UNSET_VALUE
+

The most base type

+
+ +
+
+class cassandra.query.BatchStatement(batch_type=BatchType.LOGGED, retry_policy=None, consistency_level=None)
+

A protocol-level batch of operations which are applied atomically +by default.

+
+

New in version 2.0.0.

+
+

batch_type specifies The BatchType for the batch operation. +Defaults to BatchType.LOGGED.

+

retry_policy should be a RetryPolicy instance for +controlling retries on the operation.

+

consistency_level should be a ConsistencyLevel value +to be used for all operations in the batch.

+

custom_payload is a Custom Payloads passed to the server. +Note: as Statement objects are added to the batch, this map is +updated with any values found in their custom payloads. These are +only allowed when using protocol version 4 or higher.

+

Example usage:

+
insert_user = session.prepare("INSERT INTO users (name, age) VALUES (?, ?)")
+batch = BatchStatement(consistency_level=ConsistencyLevel.QUORUM)
+
+for (name, age) in users_to_insert:
+    batch.add(insert_user, (name, age))
+
+session.execute(batch)
+
+
+

You can also mix different types of operations within a batch:

+
batch = BatchStatement()
+batch.add(SimpleStatement("INSERT INTO users (name, age) VALUES (%s, %s)"), (name, age))
+batch.add(SimpleStatement("DELETE FROM pending_users WHERE name=%s"), (name,))
+session.execute(batch)
+
+
+
+

New in version 2.0.0.

+
+
+

Changed in version 2.1.0: Added serial_consistency_level as a parameter

+
+
+

Changed in version 2.6.0: Added custom_payload as a parameter

+
+
+
+add(statement, parameters=None)
+

Adds a Statement and optional sequence of parameters +to be used with the statement to the batch.

+

Like with other statements, parameters must be a sequence, even +if there is only one item.

+
+ +
+
+add_all(statements, parameters)
+

Adds a sequence of Statement objects and a matching sequence +of parameters to the batch. Statement and parameter sequences must be of equal length or +one will be truncated. None can be used in the parameters position where are needed.

+
+ +
+
+clear()
+

This is a convenience method to clear a batch statement for reuse.

+

Note: it should not be used concurrently with uncompleted execution futures executing the same +BatchStatement.

+
+ +
+
+serial_consistency_level = None
+
+ +
+ +
+
+class cassandra.query.BatchType
+

A BatchType is used with BatchStatement instances to control +the atomicity of the batch operation.

+
+

New in version 2.0.0.

+
+
+
+LOGGED = BatchType.LOGGED
+
+ +
+
+UNLOGGED = BatchType.UNLOGGED
+
+ +
+
+COUNTER = BatchType.COUNTER
+
+ +
+ +
+
+class cassandra.query.ValueSequence(iterable=(), /)
+

A wrapper class that is used to specify that a sequence of values should +be treated as a CQL list of values instead of a single column collection when used +as part of the parameters argument for Session.execute().

+

This is typically needed when supplying a list of keys to select. +For example:

+
>>> my_user_ids = ('alice', 'bob', 'charles')
+>>> query = "SELECT * FROM users WHERE user_id IN %s"
+>>> session.execute(query, parameters=[ValueSequence(my_user_ids)])
+
+
+
+ +
+
+class cassandra.query.QueryTrace
+

A trace of the duration and events that occurred when executing +an operation.

+
+
+populate(max_wait=2.0, wait_for_complete=True, query_cl=None)
+

Retrieves the actual tracing details from Cassandra and populates the +attributes of this instance. Because tracing details are stored +asynchronously by Cassandra, this may need to retry the session +detail fetch. If the trace is still not available after max_wait +seconds, TraceUnavailable will be raised; if max_wait is +None, this will retry forever.

+

wait_for_complete=False bypasses the wait for duration to be populated. +This can be used to query events from partial sessions.

+

query_cl specifies a consistency level to use for polling the trace tables, +if it should be different than the session default.

+
+ +
+ +
+
+class cassandra.query.TraceEvent
+

Representation of a single event within a query trace.

+
+ +
+
+exception cassandra.query.TraceUnavailable
+

Raised when complete trace details cannot be fetched from Cassandra.

+
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.24.8-scylla/api/cassandra/timestamps.html b/3.24.8-scylla/api/cassandra/timestamps.html new file mode 100644 index 0000000000..1980e54616 --- /dev/null +++ b/3.24.8-scylla/api/cassandra/timestamps.html @@ -0,0 +1,695 @@ + + + + + + + + + + + + + cassandra.timestamps - Timestamp Generation | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.timestamps - Timestamp Generation

+
+
+class cassandra.timestamps.MonotonicTimestampGenerator(warn_on_drift=True, warning_threshold=0, warning_interval=0)
+

An object that, when called, returns int(time.time() * 1e6) when +possible, but, if the value returned by time.time doesn’t increase, +drifts into the future and logs warnings. +Exposed configuration attributes can be configured with arguments to +__init__ or by changing attributes on an initialized object.

+
+

New in version 3.8.0.

+
+
+
+warn_on_drift = True
+

If true, log warnings when timestamps drift into the future as allowed by +warning_threshold and warning_interval.

+
+ +
+
+warning_threshold = 1
+

This object will only issue warnings when the returned timestamp drifts +more than warning_threshold seconds into the future. +Defaults to 1 second.

+
+ +
+
+warning_interval = 1
+

This object will only issue warnings every warning_interval seconds. +Defaults to 1 second.

+
+ +
+
+_next_timestamp(now, last)
+

Returns the timestamp that should be used if now is the current +time and last is the last timestamp returned by this object. +Intended for internal and testing use only; to generate timestamps, +call an instantiated MonotonicTimestampGenerator object.

+
+
Parameters
+
    +
  • now (int) – an integer to be used as the current time, typically +representing the current time in microseconds since the UNIX epoch

  • +
  • last (int) – an integer representing the last timestamp returned by +this object

  • +
+
+
+
+ +
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.24.8-scylla/api/cassandra/util.html b/3.24.8-scylla/api/cassandra/util.html new file mode 100644 index 0000000000..0357c69543 --- /dev/null +++ b/3.24.8-scylla/api/cassandra/util.html @@ -0,0 +1,1030 @@ + + + + + + + + + + + + + cassandra.util - Utilities | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.util - Utilities

+
+
+class cassandra.util.Date(value)
+

Idealized date: year, month, day

+

Offers wider year range than datetime.date. For Dates that cannot be represented +as a datetime.date (because datetime.MINYEAR, datetime.MAXYEAR), this type falls back +to printing days_from_epoch offset.

+

Initializer value can be:

+
    +
  • integer_type: absolute days from epoch (1970, 1, 1). Can be negative.

  • +
  • datetime.date: built-in date

  • +
  • string_type: a string time of the form “yyyy-mm-dd”

  • +
+
+
+date()
+

Return a built-in datetime.date for Dates falling in the years [datetime.MINYEAR, datetime.MAXYEAR]

+

ValueError is raised for Dates outside this range.

+
+ +
+
+property seconds
+

Absolute seconds from epoch (can be negative)

+
+ +
+ +
+
+class cassandra.util.DateRange(lower_bound=None, upper_bound=None, value=None)
+

DSE DateRange Type

+
+
+lower_bound
+

DateRangeBound representing the lower bound of a bounded range.

+
+ +
+
+upper_bound
+

DateRangeBound representing the upper bound of a bounded range.

+
+ +
+
+value
+

DateRangeBound representing the value of a single-value range.

+
+ +

As noted in its documentation, DateRangeBound uses a millisecond +offset from the UNIX epoch to allow DateRange to represent values +datetime.datetime cannot. For such values, string representions will show +this offset rather than the CQL representation.

+
+
Parameters
+
+
+
+
+ +
+
+class cassandra.util.DateRangeBound(value, precision)
+

Represents a single date value and its precision for DateRange.

+
+
+milliseconds
+

Integer representing milliseconds since the UNIX epoch. May be negative.

+
+ +
+
+precision
+

String representing the precision of a bound. Must be a valid +DateRangePrecision member.

+
+ +

DateRangeBound uses a millisecond offset from the UNIX epoch to +allow DateRange to represent values datetime.datetime cannot. +For such values, string representions will show this offset rather than the +CQL representation.

+
+
Parameters
+
    +
  • value – a value representing ms since the epoch. Accepts an +integer or a datetime.

  • +
  • precision – a string representing precision

  • +
+
+
+
+
+datetime()
+

Return milliseconds as a datetime.datetime if possible. +Raises an OverflowError if the value is out of range.

+
+ +
+
+classmethod from_value(value)
+

Construct a new DateRangeBound from a given value. If +possible, use the value[‘milliseconds’] and value[‘precision’] keys +of the argument. Otherwise, use the argument as a (milliseconds, +precision) iterable.

+
+
Parameters
+

value – a dictlike or iterable object

+
+
+
+ +
+ +
+
+class cassandra.util.DateRangePrecision
+

An “enum” representing the valid values for DateRange.precision.

+
+ +
+
+class cassandra.util.Distance(x=nan, y=nan, radius=nan)
+

Represents a Distance geometry for DSE

+
+
+static from_wkt(s)
+

Parse a Distance geometry from a wkt string and return a new Distance object.

+
+ +
+ +
+
+class cassandra.util.Duration(months=0, days=0, nanoseconds=0)
+

Cassandra Duration Type

+
+ +
+
+class cassandra.util.LineString(coords=())
+

Represents a linestring geometry for DSE

+

‘coords`: a sequence of (x, y) coordinates of points in the linestring

+
+
+static from_wkt(s)
+

Parse a LineString geometry from a wkt string and return a new LineString object.

+
+ +
+ +
+
+class cassandra.util.OrderedMap(*args, **kwargs)
+

An ordered map that accepts non-hashable types for keys. It also maintains the +insertion order of items, behaving as OrderedDict in that regard. These maps +are constructed and read just as normal mapping types, except that they may +contain arbitrary collections and other non-hashable items as keys:

+
>>> od = OrderedMap([({'one': 1, 'two': 2}, 'value'),
+...                  ({'three': 3, 'four': 4}, 'value2')])
+>>> list(od.keys())
+[{'two': 2, 'one': 1}, {'three': 3, 'four': 4}]
+>>> list(od.values())
+['value', 'value2']
+
+
+

These constructs are needed to support nested collections in Cassandra 2.1.3+, +where frozen collections can be specified as parameters to others:

+
CREATE TABLE example (
+    ...
+    value map<frozen<map<int, int>>, double>
+    ...
+)
+
+
+

This class derives from the (immutable) Mapping API. Objects in these maps +are not intended be modified.

+
+ +
+
+class cassandra.util.OrderedMapSerializedKey(cass_type, protocol_version)
+
+ +
+
+class cassandra.util.Point(x=nan, y=nan)
+

Represents a point geometry for DSE

+
+
+static from_wkt(s)
+

Parse a Point geometry from a wkt string and return a new Point object.

+
+ +
+ +
+
+class cassandra.util.Polygon(exterior=(), interiors=None)
+

Represents a polygon geometry for DSE

+

‘exterior`: a sequence of (x, y) coordinates of points in the linestring +interiors: None, or a sequence of sequences or (x, y) coordinates of points describing interior linear rings

+
+
+static from_wkt(s)
+

Parse a Polygon geometry from a wkt string and return a new Polygon object.

+
+ +
+ +
+
+class cassandra.util.SortedSet(iterable=())
+

A sorted set based on sorted list

+

A sorted set implementation is used in this case because it does not +require its elements to be immutable/hashable.

+

#Not implemented: update functions, inplace operators

+
+ +
+
+class cassandra.util.Time(value)
+

Idealized time, independent of day.

+

Up to nanosecond resolution

+

Initializer value can be:

+
    +
  • integer_type: absolute nanoseconds in the day

  • +
  • datetime.time: built-in time

  • +
  • string_type: a string time of the form “HH:MM:SS[.mmmuuunnn]”

  • +
+
+
+property hour
+

The hour component of this time (0-23)

+
+ +
+
+property minute
+

The minute component of this time (0-59)

+
+ +
+
+property nanosecond
+

The fractional seconds component of the time, in nanoseconds

+
+ +
+
+property second
+

The second component of this time (0-59)

+
+ +
+
+time()
+

Return a built-in datetime.time (nanosecond precision truncated to micros).

+
+ +
+ +
+
+class cassandra.util.Version(version)
+

Internal minimalist class to compare versions. +A valid version is: <int>.<int>.<int>.<int or str>.

+

TODO: when python2 support is removed, use packaging.version.

+
+ +
+
+cassandra.util.datetime_from_timestamp(timestamp)
+

Creates a timezone-agnostic datetime from timestamp (in seconds) in a consistent manner. +Works around a Windows issue with large negative timestamps (PYTHON-119), +and rounding differences in Python 3.4 (PYTHON-340).

+
+
Parameters
+

timestamp – a unix timestamp, in seconds

+
+
+
+ +
+
+cassandra.util.datetime_from_uuid1(uuid_arg)
+

Creates a timezone-agnostic datetime from the timestamp in the +specified type-1 UUID.

+
+
Parameters
+

uuid_arg – a version 1 UUID

+
+
+
+ +
+
+cassandra.util.max_uuid_from_time(timestamp)
+

Generates the maximum TimeUUID (type 1) for a given timestamp, as compared by Cassandra.

+

See uuid_from_time() for argument and return types.

+
+ +
+
+cassandra.util.min_uuid_from_time(timestamp)
+

Generates the minimum TimeUUID (type 1) for a given timestamp, as compared by Cassandra.

+

See uuid_from_time() for argument and return types.

+
+ +
+
+cassandra.util.ms_timestamp_from_datetime(dt)
+

Converts a datetime to a timestamp expressed in milliseconds.

+
+
Parameters
+

dt – a datetime.datetime

+
+
+
+ +
+
+cassandra.util.sortedset
+

alias of cassandra.util.SortedSet

+
+ +
+
+cassandra.util.unix_time_from_uuid1(uuid_arg)
+

Converts a version 1 uuid.UUID to a timestamp with the same precision +as time.time() returns. This is useful for examining the +results of queries returning a v1 UUID.

+
+
Parameters
+

uuid_arg – a version 1 UUID

+
+
+
+ +
+
+cassandra.util.utc_datetime_from_ms_timestamp(timestamp)
+

Creates a UTC datetime from a timestamp in milliseconds. See +datetime_from_timestamp().

+

Raises an OverflowError if the timestamp is out of range for +datetime.

+
+
Parameters
+

timestamp – timestamp, in milliseconds

+
+
+
+ +
+
+cassandra.util.uuid_from_time(time_arg, node=None, clock_seq=None)
+

Converts a datetime or timestamp to a type 1 uuid.UUID.

+
+
Parameters
+
    +
  • time_arg – The time to use for the timestamp portion of the UUID. +This can either be a datetime object or a timestamp +in seconds (as returned from time.time()).

  • +
  • node (long) – None integer for the UUID (up to 48 bits). If not specified, this +field is randomized.

  • +
  • clock_seq (int) – Clock sequence field for the UUID (up to 14 bits). If not specified, +a random sequence is generated.

  • +
+
+
Return type
+

uuid.UUID

+
+
+
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.24.8-scylla/api/index.html b/3.24.8-scylla/api/index.html new file mode 100644 index 0000000000..9286ec142f --- /dev/null +++ b/3.24.8-scylla/api/index.html @@ -0,0 +1,716 @@ + + + + + + + + + + + + + API Documentation | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

API Documentation

+
+

Core Driver

+ +
+
+

Object Mapper

+ +
+
+

DataStax Graph

+ +
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.24.8-scylla/cqlengine/batches.html b/3.24.8-scylla/cqlengine/batches.html new file mode 100644 index 0000000000..39299914e4 --- /dev/null +++ b/3.24.8-scylla/cqlengine/batches.html @@ -0,0 +1,746 @@ + + + + + + + + + + + + + Batch Queries | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + + + +
+

Batch Queries

+

cqlengine supports batch queries using the BatchQuery class. Batch queries can be started and stopped manually, or within a context manager. To add queries to the batch object, you just need to precede the create/save/delete call with a call to batch, and pass in the batch object.

+
+

Batch Query General Use Pattern

+

You can only create, update, and delete rows with a batch query, attempting to read rows out of the database with a batch query will fail.

+
from cassandra.cqlengine.query import BatchQuery
+
+#using a context manager
+with BatchQuery() as b:
+    now = datetime.now()
+    em1 = ExampleModel.batch(b).create(example_type=0, description="1", created_at=now)
+    em2 = ExampleModel.batch(b).create(example_type=0, description="2", created_at=now)
+    em3 = ExampleModel.batch(b).create(example_type=0, description="3", created_at=now)
+
+# -- or --
+
+#manually
+b = BatchQuery()
+now = datetime.now()
+em1 = ExampleModel.batch(b).create(example_type=0, description="1", created_at=now)
+em2 = ExampleModel.batch(b).create(example_type=0, description="2", created_at=now)
+em3 = ExampleModel.batch(b).create(example_type=0, description="3", created_at=now)
+b.execute()
+
+# updating in a batch
+
+b = BatchQuery()
+em1.description = "new description"
+em1.batch(b).save()
+em2.description = "another new description"
+em2.batch(b).save()
+b.execute()
+
+# deleting in a batch
+b = BatchQuery()
+ExampleModel.objects(id=some_id).batch(b).delete()
+ExampleModel.objects(id=some_id2).batch(b).delete()
+b.execute()
+
+
+

Typically you will not want the block to execute if an exception occurs inside the with block. However, in the case that this is desirable, it’s achievable by using the following syntax:

+
with BatchQuery(execute_on_exception=True) as b:
+    LogEntry.batch(b).create(k=1, v=1)
+    mystery_function() # exception thrown in here
+    LogEntry.batch(b).create(k=1, v=2) # this code is never reached due to the exception, but anything leading up to here will execute in the batch.
+
+
+

If an exception is thrown somewhere in the block, any statements that have been added to the batch will still be executed. This is useful for some logging situations.

+
+
+

Batch Query Execution Callbacks

+

In order to allow secondary tasks to be chained to the end of batch, BatchQuery instances allow callbacks to be +registered with the batch, to be executed immediately after the batch executes.

+

Multiple callbacks can be attached to same BatchQuery instance, they are executed in the same order that they +are added to the batch.

+

The callbacks attached to a given batch instance are executed only if the batch executes. If the batch is used as a +context manager and an exception is raised, the queued up callbacks will not be run.

+
def my_callback(*args, **kwargs):
+    pass
+
+batch = BatchQuery()
+
+batch.add_callback(my_callback)
+batch.add_callback(my_callback, 'positional arg', named_arg='named arg value')
+
+# if you need reference to the batch within the callback,
+# just trap it in the arguments to be passed to the callback:
+batch.add_callback(my_callback, cqlengine_batch=batch)
+
+# once the batch executes...
+batch.execute()
+
+# the effect of the above scheduled callbacks will be similar to
+my_callback()
+my_callback('positional arg', named_arg='named arg value')
+my_callback(cqlengine_batch=batch)
+
+
+

Failure in any of the callbacks does not affect the batch’s execution, as the callbacks are started after the execution +of the batch is complete.

+
+

Logged vs Unlogged Batches

+

By default, queries in cqlengine are LOGGED, which carries additional overhead from UNLOGGED. To explicitly state which batch type to use, simply:

+
from cassandra.cqlengine.query import BatchType
+with BatchQuery(batch_type=BatchType.Unlogged) as b:
+    LogEntry.batch(b).create(k=1, v=1)
+    LogEntry.batch(b).create(k=1, v=2)
+
+
+
+
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.24.8-scylla/cqlengine/connections.html b/3.24.8-scylla/cqlengine/connections.html new file mode 100644 index 0000000000..1af60deefd --- /dev/null +++ b/3.24.8-scylla/cqlengine/connections.html @@ -0,0 +1,770 @@ + + + + + + + + + + + + + Connections | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + + + +
+

Connections

+

Connections aim to ease the use of multiple sessions with cqlengine. Connections can be set on a model class, per query or using a context manager.

+
+

Register a new connection

+

To use cqlengine, you need at least a default connection. If you initialize cqlengine’s connections with with connection.setup, a connection will be created automatically. If you want to use another cluster/session, you need to register a new cqlengine connection. You register a connection with register_connection():

+
from cassandra.cqlengine import connection
+
+connection.setup(['127.0.0.1')
+connection.register_connection('cluster2', ['127.0.0.2'])
+
+
+

register_connection() can take a list of hosts, as shown above, in which case it will create a connection with a new session. It can also take a session argument if you’ve already created a session:

+
from cassandra.cqlengine import connection
+from cassandra.cluster import Cluster
+
+session = Cluster(['127.0.0.1']).connect()
+connection.register_connection('cluster3', session=session)
+
+
+
+
+

Change the default connection

+

You can change the default cqlengine connection on registration:

+
from cassandra.cqlengine import connection
+
+connection.register_connection('cluster2', ['127.0.0.2'] default=True)
+
+
+

or on the fly using set_default_connection()

+
connection.set_default_connection('cluster2')
+
+
+
+
+

Unregister a connection

+

You can unregister a connection using unregister_connection():

+
connection.unregister_connection('cluster2')
+
+
+
+
+

Management

+

When using multiples connections, you also need to sync your models on all connections (and keyspaces) that you need operate on. Management commands have been improved to ease this part. Here is an example:

+
from cassandra.cqlengine import management
+
+keyspaces = ['ks1', 'ks2']
+conns = ['cluster1', 'cluster2']
+
+# registers your connections
+# ...
+
+# create all keyspaces on all connections
+for ks in keyspaces:
+    management.create_simple_keyspace(ks, connections=conns)
+
+# define your Automobile model
+# ...
+
+# sync your models
+management.sync_table(Automobile, keyspaces=keyspaces, connections=conns)
+
+
+
+
+

Connection Selection

+

cqlengine will select the default connection, unless your specify a connection using one of the following methods.

+
+

Default Model Connection

+

You can specify a default connection per model:

+
class Automobile(Model):
+    __keyspace__ = 'test'
+    __connection__ = 'cluster2'
+    manufacturer = columns.Text(primary_key=True)
+    year = columns.Integer(primary_key=True)
+    model = columns.Text(primary_key=True)
+
+print len(Automobile.objects.all())  # executed on the connection 'cluster2'
+
+
+
+
+

QuerySet and model instance

+

You can use the using() method to select a connection (or keyspace):

+
Automobile.objects.using(connection='cluster1').create(manufacturer='honda', year=2010, model='civic')
+q = Automobile.objects.filter(manufacturer='Tesla')
+autos = q.using(keyspace='ks2', connection='cluster2').all()
+
+for auto in autos:
+    auto.using(connection='cluster1').save()
+
+
+
+
+

Context Manager

+

You can use the ContextQuery as well to select a connection:

+
with ContextQuery(Automobile, connection='cluster1') as A:
+    A.objects.filter(manufacturer='honda').all()  # executed on 'cluster1'
+
+
+
+
+

BatchQuery

+

With a BatchQuery, you can select the connection with the context manager. Note that all operations in the batch need to use the same connection.

+
with BatchQuery(connection='cluster1') as b:
+    Automobile.objects.batch(b).create(manufacturer='honda', year=2010, model='civic')
+
+
+
+
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.24.8-scylla/cqlengine/faq.html b/3.24.8-scylla/cqlengine/faq.html new file mode 100644 index 0000000000..4b2041c0c6 --- /dev/null +++ b/3.24.8-scylla/cqlengine/faq.html @@ -0,0 +1,710 @@ + + + + + + + + + + + + + Frequently Asked Questions | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

Frequently Asked Questions

+
+

Why don’t updates work correctly on models instantiated as Model(field=value, field2=value2)?

+

The recommended way to create new rows is with the models .create method. The values passed into a model’s init method are interpreted by the model as the values as they were read from a row. This allows the model to “know” which rows have changed since the row was read out of cassandra, and create suitable update statements.

+
+
+

How to preserve ordering in batch query?

+

Statement Ordering is not supported by CQL3 batches. Therefore, +once cassandra needs resolving conflict(Updating the same column in one batch), +The algorithm below would be used.

+
    +
  • If timestamps are different, pick the column with the largest timestamp (the value being a regular column or a tombstone)

  • +
  • If timestamps are the same, and one of the columns in a tombstone (‘null’) - pick the tombstone

  • +
  • If timestamps are the same, and none of the columns are tombstones, pick the column with the largest value

  • +
+

Below is an example to show this scenario.

+
class MyMode(Model):
+    id    = columns.Integer(primary_key=True)
+    count = columns.Integer()
+    text  = columns.Text()
+
+with BatchQuery() as b:
+   MyModel.batch(b).create(id=1, count=2, text='123')
+   MyModel.batch(b).create(id=1, count=3, text='111')
+
+assert MyModel.objects(id=1).first().count == 3
+assert MyModel.objects(id=1).first().text  == '123'
+
+
+

The largest value of count is 3, and the largest value of text would be ‘123’.

+

The workaround is applying timestamp to each statement, then Cassandra would +resolve to the statement with the lastest timestamp.

+
with BatchQuery() as b:
+    MyModel.timestamp(datetime.now()).batch(b).create(id=1, count=2, text='123')
+    MyModel.timestamp(datetime.now()).batch(b).create(id=1, count=3, text='111')
+
+assert MyModel.objects(id=1).first().count == 3
+assert MyModel.objects(id=1).first().text  == '111'
+
+
+
+
+

How can I delete individual values from a row?

+

When inserting with CQLEngine, None is equivalent to CQL NULL or to +issuing a DELETE on that column. For example:

+
class MyModel(Model):
+    id    = columns.Integer(primary_key=True)
+    text  = columns.Text()
+
+m = MyModel.create(id=1, text='We can delete this with None')
+assert MyModel.objects(id=1).first().text is not None
+
+m.update(text=None)
+assert MyModel.objects(id=1).first().text is None
+
+
+
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.24.8-scylla/cqlengine/models.html b/3.24.8-scylla/cqlengine/models.html new file mode 100644 index 0000000000..06ac33a109 --- /dev/null +++ b/3.24.8-scylla/cqlengine/models.html @@ -0,0 +1,835 @@ + + + + + + + + + + + + + Models | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + + + +
+

Models

+

A model is a python class representing a CQL table. Models derive from Model, and +define basic table properties and columns for a table.

+

Columns in your models map to columns in your CQL table. You define CQL columns by defining column attributes on your model classes. +For a model to be valid it needs at least one primary key column and one non-primary key column. Just as in CQL, the order you define +your columns in is important, and is the same order they are defined in on a model’s corresponding table.

+

Some basic examples defining models are shown below. Consult the Model API docs and Column API docs for complete details.

+
+

Example Definitions

+

This example defines a Person table, with the columns first_name and last_name

+
from cassandra.cqlengine import columns
+from cassandra.cqlengine.models import Model
+
+ class Person(Model):
+     id = columns.UUID(primary_key=True)
+     first_name  = columns.Text()
+     last_name = columns.Text()
+
+
+

The Person model would create this CQL table:

+
CREATE TABLE cqlengine.person (
+    id uuid,
+    first_name text,
+    last_name text,
+    PRIMARY KEY (id)
+);
+
+
+

Here’s an example of a comment table created with clustering keys, in descending order:

+
from cassandra.cqlengine import columns
+from cassandra.cqlengine.models import Model
+
+class Comment(Model):
+    photo_id = columns.UUID(primary_key=True)
+    comment_id = columns.TimeUUID(primary_key=True, clustering_order="DESC")
+    comment = columns.Text()
+
+
+

The Comment model’s create table would look like the following:

+
CREATE TABLE comment (
+  photo_id uuid,
+  comment_id timeuuid,
+  comment text,
+  PRIMARY KEY (photo_id, comment_id)
+) WITH CLUSTERING ORDER BY (comment_id DESC);
+
+
+

To sync the models to the database, you may do the following*:

+
from cassandra.cqlengine.management import sync_table
+sync_table(Person)
+sync_table(Comment)
+
+
+

*Note: synchronizing models causes schema changes, and should be done with caution. +Please see the discussion in cassandra.cqlengine.management - Schema management for cqlengine for considerations.

+

For examples on manipulating data and creating queries, see Making Queries

+
+
+

Manipulating model instances as dictionaries

+

Model instances can be accessed like dictionaries.

+
class Person(Model):
+    first_name  = columns.Text()
+    last_name = columns.Text()
+
+kevin = Person.create(first_name="Kevin", last_name="Deldycke")
+dict(kevin)  # returns {'first_name': 'Kevin', 'last_name': 'Deldycke'}
+kevin['first_name']  # returns 'Kevin'
+kevin.keys()  # returns ['first_name', 'last_name']
+kevin.values()  # returns ['Kevin', 'Deldycke']
+kevin.items()  # returns [('first_name', 'Kevin'), ('last_name', 'Deldycke')]
+
+kevin['first_name'] = 'KEVIN5000'  # changes the models first name
+
+
+
+
+

Extending Model Validation

+

Each time you save a model instance in cqlengine, the data in the model is validated against the schema you’ve defined +for your model. Most of the validation is fairly straightforward, it basically checks that you’re not trying to do +something like save text into an integer column, and it enforces the required flag set on column definitions. +It also performs any transformations needed to save the data properly.

+

However, there are often additional constraints or transformations you want to impose on your data, beyond simply +making sure that Cassandra won’t complain when you try to insert it. To define additional validation on a model, +extend the model’s validation method:

+
class Member(Model):
+    person_id = UUID(primary_key=True)
+    name = Text(required=True)
+
+    def validate(self):
+        super(Member, self).validate()
+        if self.name == 'jon':
+            raise ValidationError('no jon\'s allowed')
+
+
+

Note: while not required, the convention is to raise a ValidationError (from cassandra.cqlengine import ValidationError) +if validation fails.

+
+
+

Model Inheritance

+

It is possible to save and load different model classes using a single CQL table. +This is useful in situations where you have different object types that you want to store in a single cassandra row.

+

For instance, suppose you want a table that stores rows of pets owned by an owner:

+
class Pet(Model):
+    __table_name__ = 'pet'
+    owner_id = UUID(primary_key=True)
+    pet_id = UUID(primary_key=True)
+    pet_type = Text(discriminator_column=True)
+    name = Text()
+
+    def eat(self, food):
+        pass
+
+    def sleep(self, time):
+        pass
+
+class Cat(Pet):
+    __discriminator_value__ = 'cat'
+    cuteness = Float()
+
+    def tear_up_couch(self):
+        pass
+
+class Dog(Pet):
+    __discriminator_value__ = 'dog'
+    fierceness = Float()
+
+    def bark_all_night(self):
+        pass
+
+
+

After calling sync_table on each of these tables, the columns defined in each model will be added to the +pet table. Additionally, saving Cat and Dog models will save the meta data needed to identify each row +as either a cat or dog.

+

To setup a model structure with inheritance, follow these steps

+
    +
  1. Create a base model with a column set as the distriminator (distriminator_column=True in the column definition)

  2. +
  3. Create subclass models, and define a unique __discriminator_value__ value on each

  4. +
  5. Run sync_table on each of the sub tables

  6. +
+

About the discriminator value

+

The discriminator value is what cqlengine uses under the covers to map logical cql rows to the appropriate model type. The +base model maintains a map of discriminator values to subclasses. When a specialized model is saved, its discriminator value is +automatically saved into the discriminator column. The discriminator column may be any column type except counter and container types. +Additionally, if you set index=True on your discriminator column, you can execute queries against specialized subclasses, and a +WHERE clause will be automatically added to your query, returning only rows of that type. Note that you must +define a unique __discriminator_value__ to each subclass, and that you can only assign a single discriminator column per model.

+
+
+

User Defined Types

+

cqlengine models User Defined Types (UDTs) much like tables, with fields defined by column type attributes. However, UDT instances +are only created, presisted, and queried via table Models. A short example to introduce the pattern:

+
from cassandra.cqlengine.columns import *
+from cassandra.cqlengine.models import Model
+from cassandra.cqlengine.usertype import UserType
+
+class address(UserType):
+    street = Text()
+    zipcode = Integer()
+
+class users(Model):
+    __keyspace__ = 'account'
+    name = Text(primary_key=True)
+    addr = UserDefinedType(address)
+
+users.create(name="Joe", addr=address(street="Easy St.", zipcode=99999))
+user = users.objects(name="Joe")[0]
+print user.name, user.addr
+# Joe address(street=u'Easy St.', zipcode=99999)
+
+
+

UDTs are modeled by inheriting UserType, and setting column type attributes. Types are then used in defining +models by declaring a column of type UserDefinedType, with the UserType class as a parameter.

+

sync_table will implicitly +synchronize any types contained in the table. Alternatively sync_type() can be used to create/alter types +explicitly.

+

Upon declaration, types are automatically registered with the driver, so query results return instances of your UserType +class*.

+

*Note: UDTs were not added to the native protocol until v3. When setting up the cqlengine connection, be sure to specify +protocol_version=3. If using an earlier version, UDT queries will still work, but the returned type will be a namedtuple.

+
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.24.8-scylla/cqlengine/queryset.html b/3.24.8-scylla/cqlengine/queryset.html new file mode 100644 index 0000000000..4df9e832ec --- /dev/null +++ b/3.24.8-scylla/cqlengine/queryset.html @@ -0,0 +1,1007 @@ + + + + + + + + + + + + + Making Queries | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

Making Queries

+
+

Retrieving objects

+

Once you’ve populated Cassandra with data, you’ll probably want to retrieve some of it. This is accomplished with QuerySet objects. This section will describe how to use QuerySet objects to retrieve the data you’re looking for.

+
+

Retrieving all objects

+

The simplest query you can make is to return all objects from a table.

+

This is accomplished with the .all() method, which returns a QuerySet of all objects in a table

+

Using the Person example model, we would get all Person objects like this:

+
all_objects = Person.objects.all()
+
+
+
+
+

Retrieving objects with filters

+

Typically, you’ll want to query only a subset of the records in your database.

+

That can be accomplished with the QuerySet’s .filter(\*\*) method.

+

For example, given the model definition:

+
class Automobile(Model):
+    manufacturer = columns.Text(primary_key=True)
+    year = columns.Integer(primary_key=True)
+    model = columns.Text()
+    price = columns.Decimal()
+    options = columns.Set(columns.Text)
+
+
+

…and assuming the Automobile table contains a record of every car model manufactured in the last 20 years or so, we can retrieve only the cars made by a single manufacturer like this:

+
q = Automobile.objects.filter(manufacturer='Tesla')
+
+
+

You can also use the more convenient syntax:

+
q = Automobile.objects(Automobile.manufacturer == 'Tesla')
+
+
+

We can then further filter our query with another call to .filter

+
q = q.filter(year=2012)
+
+
+

Note: all queries involving any filtering MUST define either an ‘=’ or an ‘in’ relation to either a primary key column, or an indexed column.

+
+
+
+

Accessing objects in a QuerySet

+

There are several methods for getting objects out of a queryset

+
    +
  • +
    iterating over the queryset
    for car in Automobile.objects.all():
    +    #...do something to the car instance
    +    pass
    +
    +
    +
    +
    +
  • +
  • +
    list index
    q = Automobile.objects.all()
    +q[0] #returns the first result
    +q[1] #returns the second result
    +
    +
    +
    +

    Note

    +
      +
    • CQL does not support specifying a start position in it’s queries. Therefore, accessing elements using array indexing will load every result up to the index value requested

    • +
    • Using negative indices requires a “SELECT COUNT()” to be executed. This has a performance cost on large datasets.

    • +
    +
    +
    +
    +
  • +
  • +
    list slicing
    q = Automobile.objects.all()
    +q[1:] #returns all results except the first
    +q[1:9] #returns a slice of the results
    +
    +
    +
    +

    Note

    +
      +
    • CQL does not support specifying a start position in it’s queries. Therefore, accessing elements using array slicing will load every result up to the index value requested

    • +
    • Using negative indices requires a “SELECT COUNT()” to be executed. This has a performance cost on large datasets.

    • +
    +
    +
    +
    +
  • +
  • +
    calling get() on the queryset
    q = Automobile.objects.filter(manufacturer='Tesla')
    +q = q.filter(year=2012)
    +car = q.get()
    +
    +
    +

    this returns the object matching the queryset

    +
    +
    +
  • +
  • +
    calling first() on the queryset
    q = Automobile.objects.filter(manufacturer='Tesla')
    +q = q.filter(year=2012)
    +car = q.first()
    +
    +
    +

    this returns the first value in the queryset

    +
    +
    +
  • +
+
+
+

Filtering Operators

+

Equal To

+

The default filtering operator.

+
q = Automobile.objects.filter(manufacturer='Tesla')
+q = q.filter(year=2012)  #year == 2012
+
+
+

In addition to simple equal to queries, cqlengine also supports querying with other operators by appending a __<op> to the field name on the filtering call

+

in (__in)

+
q = Automobile.objects.filter(manufacturer='Tesla')
+q = q.filter(year__in=[2011, 2012])
+
+
+

> (__gt)

+
q = Automobile.objects.filter(manufacturer='Tesla')
+q = q.filter(year__gt=2010)  # year > 2010
+
+# or the nicer syntax
+
+q.filter(Automobile.year > 2010)
+
+
+

>= (__gte)

+
q = Automobile.objects.filter(manufacturer='Tesla')
+q = q.filter(year__gte=2010)  # year >= 2010
+
+# or the nicer syntax
+
+q.filter(Automobile.year >= 2010)
+
+
+

< (__lt)

+
q = Automobile.objects.filter(manufacturer='Tesla')
+q = q.filter(year__lt=2012)  # year < 2012
+
+# or...
+
+q.filter(Automobile.year < 2012)
+
+
+

<= (__lte)

+
q = Automobile.objects.filter(manufacturer='Tesla')
+q = q.filter(year__lte=2012)  # year <= 2012
+
+q.filter(Automobile.year <= 2012)
+
+
+

CONTAINS (__contains)

+

The CONTAINS operator is available for all collection types (List, Set, Map).

+
q = Automobile.objects.filter(manufacturer='Tesla')
+q.filter(options__contains='backup camera').allow_filtering()
+
+
+

Note that we need to use allow_filtering() since the options column has no secondary index.

+

LIKE (__like)

+

The LIKE operator is available for text columns that have a SASI secondary index.

+
q = Automobile.objects.filter(model__like='%Civic%').allow_filtering()
+
+
+

IS NOT NULL (IsNotNull(column_name))

+

The IS NOT NULL operator is not yet supported for C*.

+
q = Automobile.objects.filter(IsNotNull('model'))
+
+
+

Limitations:

+
    +
  • Currently, cqlengine does not support SASI index creation. To use this feature, you need to create the SASI index using the core driver.

  • +
  • Queries using LIKE must use allow_filtering() since the model column has no standard secondary index. Note that the server will use the SASI index properly when executing the query.

  • +
+
+
+

TimeUUID Functions

+

In addition to querying using regular values, there are two functions you can pass in when querying TimeUUID columns to help make filtering by them easier. Note that these functions don’t actually return a value, but instruct the cql interpreter to use the functions in it’s query.

+
+
+class cqlengine.queryset.MinTimeUUID(datetime)
+

returns the minimum time uuid value possible for the given datetime

+
+ +
+
+class cqlengine.queryset.MaxTimeUUID(datetime)
+

returns the maximum time uuid value possible for the given datetime

+
+ +

Example

+
class DataStream(Model):
+    id      = columns.UUID(partition_key=True)
+    time    = columns.TimeUUID(primary_key=True)
+    data    = columns.Bytes()
+
+min_time = datetime(1982, 1, 1)
+max_time = datetime(1982, 3, 9)
+
+DataStream.filter(time__gt=functions.MinTimeUUID(min_time), time__lt=functions.MaxTimeUUID(max_time))
+
+
+
+
+

Token Function

+

Token functon may be used only on special, virtual column pk__token, representing token of partition key (it also works for composite partition keys). +Cassandra orders returned items by value of partition key token, so using cqlengine.Token we can easy paginate through all table rows.

+

See http://cassandra.apache.org/doc/cql3/CQL-3.0.html#tokenFun

+

Example

+
class Items(Model):
+    id      = columns.Text(primary_key=True)
+    data    = columns.Bytes()
+
+query = Items.objects.all().limit(10)
+
+first_page = list(query);
+last = first_page[-1]
+next_page = list(query.filter(pk__token__gt=cqlengine.Token(last.pk)))
+
+
+
+
+

QuerySets are immutable

+

When calling any method that changes a queryset, the method does not actually change the queryset object it’s called on, but returns a new queryset object with the attributes of the original queryset, plus the attributes added in the method call.

+

Example

+
#this produces 3 different querysets
+#q does not change after it's initial definition
+q = Automobiles.objects.filter(year=2012)
+tesla2012 = q.filter(manufacturer='Tesla')
+honda2012 = q.filter(manufacturer='Honda')
+
+
+
+
+

Ordering QuerySets

+

Since Cassandra is essentially a distributed hash table on steroids, the order you get records back in will not be particularly predictable.

+

However, you can set a column to order on with the .order_by(column_name) method.

+

Example

+
#sort ascending
+q = Automobiles.objects.all().order_by('year')
+#sort descending
+q = Automobiles.objects.all().order_by('-year')
+
+
+

Note: Cassandra only supports ordering on a clustering key. In other words, to support ordering results, your model must have more than one primary key, and you must order on a primary key, excluding the first one.

+

For instance, given our Automobile model, year is the only column we can order on.

+
+
+

Values Lists

+

There is a special QuerySet’s method .values_list() - when called, QuerySet returns lists of values instead of model instances. It may significantly speedup things with lower memory footprint for large responses. +Each tuple contains the value from the respective field passed into the values_list() call — so the first item is the first field, etc. For example:

+
items = list(range(20))
+random.shuffle(items)
+for i in items:
+    TestModel.create(id=1, clustering_key=i)
+
+values = list(TestModel.objects.values_list('clustering_key', flat=True))
+# [19L, 18L, 17L, 16L, 15L, 14L, 13L, 12L, 11L, 10L, 9L, 8L, 7L, 6L, 5L, 4L, 3L, 2L, 1L, 0L]
+
+
+
+
+

Per Query Timeouts

+

By default all queries are executed with the timeout defined in ~cqlengine.connection.setup() +The examples below show how to specify a per-query timeout. +A timeout is specified in seconds and can be an int, float or None. +None means no timeout.

+
class Row(Model):
+    id = columns.Integer(primary_key=True)
+    name = columns.Text()
+
+
+

Fetch all objects with a timeout of 5 seconds

+
Row.objects().timeout(5).all()
+
+
+

Create a single row with a 50ms timeout

+
Row(id=1, name='Jon').timeout(0.05).create()
+
+
+

Delete a single row with no timeout

+
Row(id=1).timeout(None).delete()
+
+
+

Update a single row with no timeout

+
Row(id=1).timeout(None).update(name='Blake')
+
+
+

Batch query timeouts

+
with BatchQuery(timeout=10) as b:
+    Row(id=1, name='Jon').create()
+
+
+

NOTE: You cannot set both timeout and batch at the same time, batch will use the timeout defined in it’s constructor. +Setting the timeout on the model is meaningless and will raise an AssertionError.

+
+
+

Default TTL and Per Query TTL

+

Model default TTL now relies on the default_time_to_live feature, introduced in Cassandra 2.0. It is not handled anymore in the CQLEngine Model (scylla-driver >=3.6). You can set the default TTL of a table like this:

+

Example:

+
class User(Model):
+    __options__ = {'default_time_to_live': 20}
+
+    user_id = columns.UUID(primary_key=True)
+    ...
+
+
+

You can set TTL per-query if needed. Here are a some examples:

+

Example:

+
class User(Model):
+    __options__ = {'default_time_to_live': 20}
+
+    user_id = columns.UUID(primary_key=True)
+    ...
+
+user = User.objects.create(user_id=1)  # Default TTL 20 will be set automatically on the server
+
+user.ttl(30).update(age=21)            # Update the TTL to 30
+User.objects.ttl(10).create(user_id=1)  # TTL 10
+User(user_id=1, age=21).ttl(10).save()  # TTL 10
+
+
+
+
+

Named Tables

+

Named tables are a way of querying a table without creating an class. They’re useful for querying system tables or exploring an unfamiliar database.

+
from cassandra.cqlengine.connection import setup
+setup("127.0.0.1", "cqlengine_test")
+
+from cassandra.cqlengine.named import NamedTable
+user = NamedTable("cqlengine_test", "user")
+user.objects()
+user.objects()[0]
+
+# {u'pk': 1, u't': datetime.datetime(2014, 6, 26, 17, 10, 31, 774000)}
+
+
+
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.24.8-scylla/cqlengine/third_party.html b/3.24.8-scylla/cqlengine/third_party.html new file mode 100644 index 0000000000..97ba1501c4 --- /dev/null +++ b/3.24.8-scylla/cqlengine/third_party.html @@ -0,0 +1,707 @@ + + + + + + + + + + + + + Third party integrations | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

Third party integrations

+
+

Celery

+

Here’s how, in substance, CQLengine can be plugged to Celery:

+
from celery import Celery
+from celery.signals import worker_process_init, beat_init
+from cassandra.cqlengine import connection
+from cassandra.cqlengine.connection import (
+    cluster as cql_cluster, session as cql_session)
+
+def cassandra_init(**kwargs):
+    """ Initialize a clean Cassandra connection. """
+    if cql_cluster is not None:
+        cql_cluster.shutdown()
+    if cql_session is not None:
+        cql_session.shutdown()
+    connection.setup()
+
+# Initialize worker context for both standard and periodic tasks.
+worker_process_init.connect(cassandra_init)
+beat_init.connect(cassandra_init)
+
+app = Celery()
+
+
+
+
+

uWSGI

+

This is the code required for proper connection handling of CQLengine for a +uWSGI-run application:

+
from cassandra.cqlengine import connection
+from cassandra.cqlengine.connection import (
+    cluster as cql_cluster, session as cql_session)
+
+try:
+    from uwsgidecorators import postfork
+except ImportError:
+    # We're not in a uWSGI context, no need to hook Cassandra session
+    # initialization to the postfork event.
+    pass
+else:
+    @postfork
+    def cassandra_init(**kwargs):
+        """ Initialize a new Cassandra session in the context.
+
+        Ensures that a new session is returned for every new request.
+        """
+        if cql_cluster is not None:
+            cql_cluster.shutdown()
+        if cql_session is not None:
+            cql_session.shutdown()
+        connection.setup()
+
+
+
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.24.8-scylla/cqlengine/upgrade_guide.html b/3.24.8-scylla/cqlengine/upgrade_guide.html new file mode 100644 index 0000000000..c12412981e --- /dev/null +++ b/3.24.8-scylla/cqlengine/upgrade_guide.html @@ -0,0 +1,839 @@ + + + + + + + + + + + + + Upgrade Guide | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + + + +
+

Upgrade Guide

+

This is an overview of things that changed as the cqlengine project was merged into +scylla-driver. While efforts were taken to preserve the API and most functionality exactly, +conversion to this package will still require certain minimal updates (namely, imports).

+

THERE IS ONE FUNCTIONAL CHANGE, described in the first section below.

+
+

Functional Changes

+
+

List Prepend Reversing

+

Legacy cqlengine included a workaround for a Cassandra bug in which prepended list segments were +reversed (CASSANDRA-8733). As of +this integration, this workaround is removed. The first released integrated version emits +a warning when prepend is used. Subsequent versions will have this warning removed.

+
+
+

Date Column Type

+

The Date column type in legacy cqlengine used a timestamp CQL type and truncated the time. +Going forward, the Date type represents a date for Cassandra 2.2+ +(PYTHON-245). +Users of the legacy functionality should convert models to use DateTime (which +uses timestamp internally), and use the build-in datetime.date for input values.

+
+
+
+

Remove cqlengine

+

To avoid confusion or mistakes using the legacy package in your application, it +is prudent to remove the cqlengine package when upgrading to the integrated version.

+

The driver setup script will warn if the legacy package is detected during install, +but it will not prevent side-by-side installation.

+
+
+

Organization

+
+

Imports

+

cqlengine is now integrated as a sub-package of the driver base package ‘cassandra’. +Upgrading will require adjusting imports to cqlengine. For example:

+
from cassandra.cqlengine import columns
+
+
+

is now:

+
from cassandra.cqlengine import columns
+
+
+
+
+

Package-Level Aliases

+

Legacy cqlengine defined a number of aliases at the package level, which became redundant +when the package was integrated for a driver. These have been removed in favor of absolute +imports, and referring to cannonical definitions. For example, cqlengine.ONE was an alias +of cassandra.ConsistencyLevel.ONE. In the integrated package, only the +cassandra.ConsistencyLevel remains.

+

Additionally, submodule aliases are removed from cqlengine in favor of absolute imports.

+

These aliases are removed, and not deprecated because they should be straightforward to iron out +at module load time.

+
+
+

Exceptions

+

The legacy cqlengine.exceptions module had a number of Exception classes that were variously +common to the package, or only used in specific modules. Common exceptions were relocated to +cqlengine, and specialized exceptions were placed in the module that raises them. Below is a +listing of updated locations:

+ ++++ + + + + + + + + + + + + + + + + + + + + + + + + + +

Exception class

New module

CQLEngineException

cassandra.cqlengine

ModelException

cassandra.cqlengine.models

ValidationError

cassandra.cqlengine

UndefinedKeyspaceException

cassandra.cqlengine.connection

LWTException

cassandra.cqlengine.query

IfNotExistsWithCounterColumn

cassandra.cqlengine.query

+
+
+

UnicodeMixin Consolidation

+

class UnicodeMixin was defined in several cqlengine modules. This has been consolidated +to a single definition in the cqlengine package init file. This is not technically part of +the API, but noted here for completeness.

+
+
+
+

API Deprecations

+

This upgrade served as a good juncture to deprecate certain API features and invite users to upgrade +to new ones. The first released version does not change functionality – only introduces deprecation +warnings. Future releases will remove these features in favor of the alternatives.

+
+

Float/Double Overload

+

Previously there was no Double column type. Doubles were modeled by specifying Float(double_precision=True). +This inititializer parameter is now deprecated. Applications should use Double for CQL double, and Float +for CQL float.

+
+
+

Schema Management

+

cassandra.cqlengine.management.create_keyspace is deprecated. Instead, use the new replication-strategy-specific +functions that accept explicit options for known strategies:

+ +

cassandra.cqlengine.management.delete_keyspace is deprecated in favor of a new function, drop_keyspace(). The +intent is simply to make the function match the CQL verb it invokes.

+
+
+

Model Inheritance

+

The names for class attributes controlling model inheritance are changing. Changes are as follows:

+ +

The functionality is unchanged – the intent here is to make the names and language around these attributes more precise. +For now, the old names are just deprecated, and the mapper will emit warnings if they are used. The old names +will be removed in a future version.

+

The example below shows a simple translation:

+

Before:

+
class Pet(Model):
+    __table_name__ = 'pet'
+    owner_id = UUID(primary_key=True)
+    pet_id = UUID(primary_key=True)
+    pet_type = Text(polymorphic_key=True)
+    name = Text()
+
+class Cat(Pet):
+    __polymorphic_key__ = 'cat'
+
+class Dog(Pet):
+    __polymorphic_key__ = 'dog'
+
+
+

After:

+
class Pet(models.Model):
+    __table_name__ = 'pet'
+    owner_id = UUID(primary_key=True)
+    pet_id = UUID(primary_key=True)
+    pet_type = Text(discriminator_column=True)
+    name = Text()
+
+class Cat(Pet):
+    __discriminator_value__ = 'cat'
+
+class Dog(Pet):
+    __discriminator_value__ = 'dog'
+
+
+
+
+

TimeUUID.from_datetime

+

This function is deprecated in favor of the core utility function uuid_from_time().

+
+
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.24.8-scylla/dates_and_times.html b/3.24.8-scylla/dates_and_times.html new file mode 100644 index 0000000000..12d03f6733 --- /dev/null +++ b/3.24.8-scylla/dates_and_times.html @@ -0,0 +1,731 @@ + + + + + + + + + + + + + Working with Dates and Times | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

Working with Dates and Times

+

This document is meant to provide on overview of the assumptions and limitations of the driver time handling, the +reasoning behind it, and describe approaches to working with these types.

+
+

timestamps (Cassandra DateType)

+

Timestamps in Cassandra are timezone-naive timestamps encoded as millseconds since UNIX epoch. Clients working with +timestamps in this database usually find it easiest to reason about them if they are always assumed to be UTC. To quote the +pytz documentation, “The preferred way of dealing with times is to always work in UTC, converting to localtime only when +generating output to be read by humans.” The driver adheres to this tenant, and assumes UTC is always in the database. The +driver attempts to make this correct on the way in, and assumes no timezone on the way out.

+
+

Write Path

+

When inserting timestamps, the driver handles serialization for the write path as follows:

+

If the input is a datetime.datetime, the serialization is normalized by starting with the utctimetuple() of the +value.

+
    +
  • If the datetime object is timezone-aware, the timestamp is shifted, and represents the UTC timestamp equivalent.

  • +
  • If the datetime object is timezone-naive, this results in no shift – any datetime with no timezone information is assumed to be UTC

  • +
+

Note the second point above applies even to “local” times created using now():

+
>>> d = datetime.now()
+
+>>> print(d.tzinfo)
+None
+
+
+

These do not contain timezone information intrinsically, so they will be assumed to be UTC and not shifted. When generating +timestamps in the application, it is clearer to use datetime.utcnow() to be explicit about it.

+

If the input for a timestamp is numeric, it is assumed to be a epoch-relative millisecond timestamp, as specified in the +CQL spec – no scaling or conversion is done.

+
+
+

Read Path

+

The driver always assumes persisted timestamps are UTC and makes no attempt to localize them. Returned values are +timezone-naive datetime.datetime. We follow this approach because the datetime API has deficiencies around daylight +saving time, and the defacto package for handling this is a third-party package (we try to minimize external dependencies +and not make decisions for the integrator).

+

The decision for how to handle timezones is left to the application. For the most part it is straightforward to apply +localization to the datetimes returned by queries. One prevalent method is to use pytz for localization:

+
import pytz
+user_tz = pytz.timezone('US/Central')
+timestamp_naive = row.ts
+timestamp_utc = pytz.utc.localize(timestamp_naive)
+timestamp_presented = timestamp_utc.astimezone(user_tz)
+
+
+

This is the most robust approach (likely refactored into a function). If it is deemed too cumbersome to apply for all call +sites in the application, it is possible to patch the driver with custom deserialization for this type. However, doing +this depends depends some on internal APIs and what extensions are present, so we will only mention the possibility, and +not spell it out here.

+
+
+
+

date, time (Cassandra DateType)

+

Date and time in Cassandra are idealized markers, much like datetime.date and datetime.time in the Python standard +library. Unlike these Python implementations, the Cassandra encoding supports much wider ranges. To accommodate these +ranges without overflow, this driver returns these data in custom types: util.Date and util.Time.

+
+

Write Path

+

For simple (not prepared) statements, the input values for each of these can be either a string literal or an encoded +integer. See Working with dates +or Working with time for details +on the encoding or string formats.

+

For prepared statements, the driver accepts anything that can be used to construct the util.Date or +util.Time classes. See the linked API docs for details.

+
+
+

Read Path

+

The driver always returns custom types for date and time.

+

The driver returns util.Date for date in order to accommodate the wider range of values without overflow. +For applications working within the supported range of [datetime.MINYEAR, datetime.MAXYEAR], these are easily +converted to standard datetime.date insances using Date.date().

+

The driver returns util.Time for time in order to retain nanosecond precision stored in the database. +For applications not concerned with this level of precision, these are easily converted to standard datetime.time +insances using Time.time().

+
+
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.24.8-scylla/execution_profiles.html b/3.24.8-scylla/execution_profiles.html new file mode 100644 index 0000000000..77a9cc94d7 --- /dev/null +++ b/3.24.8-scylla/execution_profiles.html @@ -0,0 +1,775 @@ + + + + + + + + + + + + + Execution Profiles | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

Execution Profiles

+

Execution profiles aim at making it easier to execute requests in different ways within +a single connected Session. Execution profiles are being introduced to deal with the exploding number of +configuration options, especially as the database platform evolves more complex workloads.

+

The legacy configuration remains intact, but legacy and Execution Profile APIs +cannot be used simultaneously on the same client Cluster. Legacy configuration +will be removed in the next major release (4.0).

+

An execution profile and its parameters should be unique across Cluster instances. +For example, an execution profile and its LoadBalancingPolicy should +not be applied to more than one Cluster instance.

+

This document explains how Execution Profiles relate to existing settings, and shows how to use the new profiles for +request execution.

+
+

Mapping Legacy Parameters to Profiles

+

Execution profiles can inherit from cluster.ExecutionProfile, and currently provide the following options, +previously input from the noted attributes:

+ +

When using the new API, these parameters can be defined by instances of cluster.ExecutionProfile.

+
+
+

Using Execution Profiles

+
+

Default

+
from cassandra.cluster import Cluster
+cluster = Cluster()
+session = cluster.connect()
+local_query = 'SELECT rpc_address FROM system.local'
+for _ in cluster.metadata.all_hosts():
+    print session.execute(local_query)[0]
+
+
+
Row(rpc_address='127.0.0.2')
+Row(rpc_address='127.0.0.1')
+
+
+

The default execution profile is built from Cluster parameters and default Session attributes. This profile matches existing default +parameters.

+
+
+

Initializing cluster with profiles

+
from cassandra.cluster import ExecutionProfile
+from cassandra.policies import WhiteListRoundRobinPolicy
+
+node1_profile = ExecutionProfile(load_balancing_policy=WhiteListRoundRobinPolicy(['127.0.0.1']))
+node2_profile = ExecutionProfile(load_balancing_policy=WhiteListRoundRobinPolicy(['127.0.0.2']))
+
+profiles = {'node1': node1_profile, 'node2': node2_profile}
+session = Cluster(execution_profiles=profiles).connect()
+for _ in cluster.metadata.all_hosts():
+    print session.execute(local_query, execution_profile='node1')[0]
+
+
+
Row(rpc_address='127.0.0.1')
+Row(rpc_address='127.0.0.1')
+
+
+
for _ in cluster.metadata.all_hosts():
+    print session.execute(local_query, execution_profile='node2')[0]
+
+
+
Row(rpc_address='127.0.0.2')
+Row(rpc_address='127.0.0.2')
+
+
+
for _ in cluster.metadata.all_hosts():
+    print session.execute(local_query)[0]
+
+
+
Row(rpc_address='127.0.0.2')
+Row(rpc_address='127.0.0.1')
+
+
+

Note that, even when custom profiles are injected, the default TokenAwarePolicy(DCAwareRoundRobinPolicy()) is still +present. To override the default, specify a policy with the EXEC_PROFILE_DEFAULT key.

+
from cassandra.cluster import EXEC_PROFILE_DEFAULT
+profile = ExecutionProfile(request_timeout=30)
+cluster = Cluster(execution_profiles={EXEC_PROFILE_DEFAULT: profile})
+
+
+
+
+

Adding named profiles

+

New profiles can be added constructing from scratch, or deriving from default:

+
locked_execution = ExecutionProfile(load_balancing_policy=WhiteListRoundRobinPolicy(['127.0.0.1']))
+node1_profile = 'node1_whitelist'
+cluster.add_execution_profile(node1_profile, locked_execution)
+
+for _ in cluster.metadata.all_hosts():
+    print session.execute(local_query, execution_profile=node1_profile)[0]
+
+
+
Row(rpc_address='127.0.0.1')
+Row(rpc_address='127.0.0.1')
+
+
+

See Cluster.add_execution_profile() for details and optional parameters.

+
+
+

Passing a profile instance without mapping

+

We also have the ability to pass profile instances to be used for execution, but not added to the mapping:

+
from cassandra.query import tuple_factory
+
+tmp = session.execution_profile_clone_update('node1', request_timeout=100, row_factory=tuple_factory)
+
+print session.execute(local_query, execution_profile=tmp)[0]
+print session.execute(local_query, execution_profile='node1')[0]
+
+
+
('127.0.0.1',)
+Row(rpc_address='127.0.0.1')
+
+
+

The new profile is a shallow copy, so the tmp profile shares a load balancing policy with one managed by the cluster. +If reference objects are to be updated in the clone, one would typically set those attributes to a new instance.

+
+
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.24.8-scylla/faq.html b/3.24.8-scylla/faq.html new file mode 100644 index 0000000000..c9854e45d7 --- /dev/null +++ b/3.24.8-scylla/faq.html @@ -0,0 +1,711 @@ + + + + + + + + + + + + + Frequently Asked Questions | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

Frequently Asked Questions

+

See also cqlengine FAQ

+
+

Why do connections or IO operations timeout in my WSGI application?

+

Depending on your application process model, it may be forking after driver Session is created. Most IO reactors do not handle this, and problems will manifest as timeouts.

+

To avoid this, make sure to create sessions per process, after the fork. Using uWSGI and Flask for example:

+
from flask import Flask
+from uwsgidecorators import postfork
+from cassandra.cluster import Cluster
+
+session = None
+prepared = None
+
+@postfork
+def connect():
+    global session, prepared
+    session = Cluster().connect()
+    prepared = session.prepare("SELECT release_version FROM system.local WHERE key=?")
+
+app = Flask(__name__)
+
+@app.route('/')
+def server_version():
+    row = session.execute(prepared, ('local',))[0]
+    return row.release_version
+
+
+

uWSGI provides a postfork hook you can use to create sessions and prepared statements after the child process forks.

+
+
+

How do I trace a request?

+

Request tracing can be turned on for any request by setting trace=True in Session.execute_async(). View the results by waiting on the future, then ResponseFuture.get_query_trace(). +Since tracing is done asynchronously to the request, this method polls until the trace is complete before querying data.

+
>>> future = session.execute_async("SELECT * FROM system.local", trace=True)
+>>> result = future.result()
+>>> trace = future.get_query_trace()
+>>> for e in trace.events:
+>>>     print e.source_elapsed, e.description
+
+0:00:00.000077 Parsing select * from system.local
+0:00:00.000153 Preparing statement
+0:00:00.000309 Computing ranges to query
+0:00:00.000368 Submitting range requests on 1 ranges with a concurrency of 1 (279.77142 rows per range expected)
+0:00:00.000422 Submitted 1 concurrent range requests covering 1 ranges
+0:00:00.000480 Executing seq scan across 1 sstables for (min(-9223372036854775808), min(-9223372036854775808))
+0:00:00.000669 Read 1 live and 0 tombstone cells
+0:00:00.000755 Scanned 1 rows and matched 1
+
+
+

trace is a QueryTrace object.

+
+
+

How do I determine the replicas for a query?

+

With prepared statements, the replicas are obtained by routing_key, based on current cluster token metadata:

+
>>> prepared = session.prepare("SELECT * FROM example.t WHERE key=?")
+>>> bound = prepared.bind((1,))
+>>> replicas = cluster.metadata.get_replicas(bound.keyspace, bound.routing_key)
+>>> for h in replicas:
+>>>   print h.address
+127.0.0.1
+127.0.0.2
+
+
+

replicas is a list of Host objects.

+
+
+

How does the driver manage request retries?

+

By default, retries are managed by the Cluster.default_retry_policy set on the session Cluster. It can also +be specialized per statement by setting Statement.retry_policy.

+

Retries are presently attempted on the same coordinator, but this may change in the future.

+

Please see policies.RetryPolicy for further details.

+
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.24.8-scylla/getting_started.html b/3.24.8-scylla/getting_started.html new file mode 100644 index 0000000000..a0a9da7091 --- /dev/null +++ b/3.24.8-scylla/getting_started.html @@ -0,0 +1,1116 @@ + + + + + + + + + + + + + Getting Started | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

Getting Started

+

First, make sure you have the driver properly installed.

+
+

Connecting to Cassandra

+

Before we can start executing any queries against a Cassandra cluster we need to setup +an instance of Cluster. As the name suggests, you will typically have one +instance of Cluster for each Cassandra cluster you want to interact +with.

+

The simplest way to create a Cluster is like this: +First, make sure you have the Cassandra driver properly installed.

+
from cassandra.cluster import Cluster
+
+cluster = Cluster()
+
+
+

This will attempt to connection to a Cassandra instance on your +local machine (127.0.0.1). You can also specify a list of IP +addresses for nodes in your cluster:

+
from cassandra.cluster import Cluster
+
+cluster = Cluster(['192.168.0.1', '192.168.0.2'])
+
+
+

The set of IP addresses we pass to the Cluster is simply +an initial set of contact points. After the driver connects to one +of these nodes it will automatically discover the rest of the +nodes in the cluster and connect to them, so you don’t need to list +every node in your cluster.

+

If you need to use a non-standard port, use SSL, or customize the driver’s +behavior in some other way, this is the place to do it:

+
from cassandra.cluster import Cluster
+cluster = Cluster(['192.168.0.1', '192.168.0.2'], port=..., ssl_context=...)
+
+
+

Instantiating a Cluster does not actually connect us to any nodes. +To establish connections and begin executing queries we need a +Session, which is created by calling Cluster.connect():

+
cluster = Cluster()
+session = cluster.connect()
+
+
+

The connect() method takes an optional keyspace argument +which sets the default keyspace for all queries made through that Session:

+
cluster = Cluster()
+session = cluster.connect('mykeyspace')
+
+
+

You can always change a Session’s keyspace using set_keyspace() or +by executing a USE <keyspace> query:

+
session.set_keyspace('users')
+# or you can do this instead
+session.execute('USE users')
+
+
+

Profiles are passed in by execution_profiles dict.

+

In this case we can construct the base ExecutionProfile passing all attributes:

+
from cassandra.cluster import Cluster, ExecutionProfile, EXEC_PROFILE_DEFAULT
+from cassandra.policies import WhiteListRoundRobinPolicy, DowngradingConsistencyRetryPolicy
+from cassandra.query import tuple_factory
+
+profile = ExecutionProfile(
+    load_balancing_policy=WhiteListRoundRobinPolicy(['127.0.0.1']),
+    retry_policy=DowngradingConsistencyRetryPolicy(),
+    consistency_level=ConsistencyLevel.LOCAL_QUORUM,
+    serial_consistency_level=ConsistencyLevel.LOCAL_SERIAL,
+    request_timeout=15,
+    row_factory=tuple_factory
+)
+cluster = Cluster(execution_profiles={EXEC_PROFILE_DEFAULT: profile})
+session = cluster.connect()
+
+print(session.execute("SELECT release_version FROM system.local").one())
+
+
+

Users are free to setup additional profiles to be used by name:

+
profile_long = ExecutionProfile(request_timeout=30)
+cluster = Cluster(execution_profiles={'long': profile_long})
+session = cluster.connect()
+session.execute(statement, execution_profile='long')
+
+
+

Also, parameters passed to Session.execute or attached to Statements are still honored as before.

+
+
+

Executing Queries

+

Now that we have a Session we can begin to execute queries. The simplest +way to execute a query is to use execute():

+
rows = session.execute('SELECT name, age, email FROM users')
+for user_row in rows:
+    print user_row.name, user_row.age, user_row.email
+
+
+

This will transparently pick a Cassandra node to execute the query against +and handle any retries that are necessary if the operation fails.

+

By default, each row in the result set will be a +namedtuple. +Each row will have a matching attribute for each column defined in the schema, +such as name, age, and so on. You can also treat them as normal tuples +by unpacking them or accessing fields by position. The following three +examples are equivalent:

+
rows = session.execute('SELECT name, age, email FROM users')
+for row in rows:
+    print row.name, row.age, row.email
+
+
+
rows = session.execute('SELECT name, age, email FROM users')
+for (name, age, email) in rows:
+    print name, age, email
+
+
+
rows = session.execute('SELECT name, age, email FROM users')
+for row in rows:
+    print row[0], row[1], row[2]
+
+
+

If you prefer another result format, such as a dict per row, you +can change the row_factory attribute.

+

As mentioned in our Drivers Best Practices Guide, +it is highly recommended to use Prepared statements for your +frequently run queries.

+
+
+

Prepared Statements

+

Prepared statements are queries that are parsed by Cassandra and then saved +for later use. When the driver uses a prepared statement, it only needs to +send the values of parameters to bind. This lowers network traffic +and CPU utilization within Cassandra because Cassandra does not have to +re-parse the query each time.

+

To prepare a query, use Session.prepare():

+
user_lookup_stmt = session.prepare("SELECT * FROM users WHERE user_id=?")
+
+users = []
+for user_id in user_ids_to_query:
+    user = session.execute(user_lookup_stmt, [user_id])
+    users.append(user)
+
+
+

prepare() returns a PreparedStatement instance +which can be used in place of SimpleStatement instances or literal +string queries. It is automatically prepared against all nodes, and the driver +handles re-preparing against new nodes and restarted nodes when necessary.

+

Note that the placeholders for prepared statements are ? characters. This +is different than for simple, non-prepared statements (although future versions +of the driver may use the same placeholders for both).

+
+

Passing Parameters to CQL Queries

+

Althought it is not recommended, you can also pass parameters to non-prepared +statements. The driver supports two forms of parameter place-holders: positional +and named.

+

Positional parameters are used with a %s placeholder. For example, +when you execute:

+
session.execute(
+    """
+    INSERT INTO users (name, credits, user_id)
+    VALUES (%s, %s, %s)
+    """,
+    ("John O'Reilly", 42, uuid.uuid1())
+)
+
+
+

It is translated to the following CQL query:

+
INSERT INTO users (name, credits, user_id)
+VALUES ('John O''Reilly', 42, 2644bada-852c-11e3-89fb-e0b9a54a6d93)
+
+
+

Note that you should use %s for all types of arguments, not just strings. +For example, this would be wrong:

+
session.execute("INSERT INTO USERS (name, age) VALUES (%s, %d)", ("bob", 42))  # wrong
+
+
+

Instead, use %s for the age placeholder.

+

If you need to use a literal % character, use %%.

+

Note: you must always use a sequence for the second argument, even if you are +only passing in a single variable:

+
session.execute("INSERT INTO foo (bar) VALUES (%s)", "blah")  # wrong
+session.execute("INSERT INTO foo (bar) VALUES (%s)", ("blah"))  # wrong
+session.execute("INSERT INTO foo (bar) VALUES (%s)", ("blah", ))  # right
+session.execute("INSERT INTO foo (bar) VALUES (%s)", ["blah"])  # right
+
+
+

Note that the second line is incorrect because in Python, single-element tuples +require a comma.

+

Named place-holders use the %(name)s form:

+
session.execute(
+    """
+    INSERT INTO users (name, credits, user_id, username)
+    VALUES (%(name)s, %(credits)s, %(user_id)s, %(name)s)
+    """,
+    {'name': "John O'Reilly", 'credits': 42, 'user_id': uuid.uuid1()}
+)
+
+
+

Note that you can repeat placeholders with the same name, such as %(name)s +in the above example.

+

Only data values should be supplied this way. Other items, such as keyspaces, +table names, and column names should be set ahead of time (typically using +normal string formatting).

+
+
+

Type Conversions

+

For non-prepared statements, Python types are cast to CQL literals in the +following way:

+ ++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Python Type

CQL Literal Type

None

NULL

bool

boolean

float

+
float
+
double
+
+
+
int
+
long
+
+
+
int
+
bigint
+
varint
+
smallint
+
tinyint
+
counter
+
+

decimal.Decimal

decimal

+
str
+
unicode
+
+
+
ascii
+
varchar
+
text
+
+
+
buffer
+
bytearray
+
+

blob

date

date

datetime

timestamp

time

time

+
list
+
tuple
+
generator
+
+

list

+
set
+
frozenset
+
+

set

+
dict
+
OrderedDict
+
+

map

uuid.UUID

+
timeuuid
+
uuid
+
+
+
+
+

Asynchronous Queries

+

The driver supports asynchronous query execution through +execute_async(). Instead of waiting for the query to +complete and returning rows directly, this method almost immediately +returns a ResponseFuture object. There are two ways of +getting the final result from this object.

+

The first is by calling result() on it. If +the query has not yet completed, this will block until it has and +then return the result or raise an Exception if an error occurred. +For example:

+
from cassandra import ReadTimeout
+
+query = "SELECT * FROM users WHERE user_id=%s"
+future = session.execute_async(query, [user_id])
+
+# ... do some other work
+
+try:
+    rows = future.result()
+    user = rows[0]
+    print user.name, user.age
+except ReadTimeout:
+    log.exception("Query timed out:")
+
+
+

This works well for executing many queries concurrently:

+
# build a list of futures
+futures = []
+query = "SELECT * FROM users WHERE user_id=%s"
+for user_id in ids_to_fetch:
+    futures.append(session.execute_async(query, [user_id])
+
+# wait for them to complete and use the results
+for future in futures:
+    rows = future.result()
+    print rows[0].name
+
+
+

Alternatively, instead of calling result(), +you can attach callback and errback functions through the +add_callback(), +add_errback(), and +add_callbacks(), methods. If you have used +Twisted Python before, this is designed to be a lightweight version of +that:

+
def handle_success(rows):
+    user = rows[0]
+    try:
+        process_user(user.name, user.age, user.id)
+    except Exception:
+        log.error("Failed to process user %s", user.id)
+        # don't re-raise errors in the callback
+
+def handle_error(exception):
+    log.error("Failed to fetch user info: %s", exception)
+
+
+future = session.execute_async(query)
+future.add_callbacks(handle_success, handle_error)
+
+
+
+
There are a few important things to remember when working with callbacks:
    +
  • Exceptions that are raised inside the callback functions will be logged and then ignored.

  • +
  • Your callback will be run on the event loop thread, so any long-running +operations will prevent other requests from being handled

  • +
+
+
+
+
+
+

Setting a Consistency Level

+

The consistency level used for a query determines how many of the +replicas of the data you are interacting with need to respond for +the query to be considered a success.

+

By default, ConsistencyLevel.LOCAL_ONE will be used for all queries. +You can specify a different default by setting the ExecutionProfile.consistency_level +for the execution profile with key EXEC_PROFILE_DEFAULT. +To specify a different consistency level per request, wrap queries +in a SimpleStatement:

+
from cassandra import ConsistencyLevel
+from cassandra.query import SimpleStatement
+
+query = SimpleStatement(
+    "INSERT INTO users (name, age) VALUES (%s, %s)",
+    consistency_level=ConsistencyLevel.QUORUM)
+session.execute(query, ('John', 42))
+
+
+
+

Setting a Consistency Level with Prepared Statements

+

To specify a consistency level for prepared statements, you have two options.

+

The first is to set a default consistency level for every execution of the +prepared statement:

+
from cassandra import ConsistencyLevel
+
+cluster = Cluster()
+session = cluster.connect("mykeyspace")
+user_lookup_stmt = session.prepare("SELECT * FROM users WHERE user_id=?")
+user_lookup_stmt.consistency_level = ConsistencyLevel.QUORUM
+
+# these will both use QUORUM
+user1 = session.execute(user_lookup_stmt, [user_id1])[0]
+user2 = session.execute(user_lookup_stmt, [user_id2])[0]
+
+
+

The second option is to create a BoundStatement from the +PreparedStatement and binding parameters and set a consistency +level on that:

+
# override the QUORUM default
+user3_lookup = user_lookup_stmt.bind([user_id3])
+user3_lookup.consistency_level = ConsistencyLevel.ALL
+user3 = session.execute(user3_lookup)
+
+
+
+
+

Speculative Execution

+

Speculative execution is a way to minimize latency by preemptively executing several +instances of the same query against different nodes. For more details about this +technique, see Speculative Execution with DataStax Drivers.

+

To enable speculative execution:

+
    +
  • Configure a SpeculativeExecutionPolicy with the ExecutionProfile

  • +
  • Mark your query as idempotent, which mean it can be applied multiple +times without changing the result of the initial application. +See Query Idempotence for more details.

  • +
+

Example:

+
from cassandra.cluster import Cluster, ExecutionProfile, EXEC_PROFILE_DEFAULT
+from cassandra.policies import ConstantSpeculativeExecutionPolicy
+from cassandra.query import SimpleStatement
+
+# Configure the speculative execution policy
+ep = ExecutionProfile(
+    speculative_execution_policy=ConstantSpeculativeExecutionPolicy(delay=.5, max_attempts=10)
+)
+cluster = Cluster(..., execution_profiles={EXEC_PROFILE_DEFAULT: ep})
+session = cluster.connect()
+
+# Mark the query idempotent
+query = SimpleStatement(
+    "UPDATE my_table SET list_col = [1] WHERE pk = 1",
+    is_idempotent=True
+)
+
+# Execute. A new query will be sent to the server every 0.5 second
+# until we receive a response, for a max number attempts of 10.
+session.execute(query)
+
+
+
+
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.24.8-scylla/index.html b/3.24.8-scylla/index.html new file mode 100644 index 0000000000..5df3605d06 --- /dev/null +++ b/3.24.8-scylla/index.html @@ -0,0 +1,701 @@ + + + + + + + + + + + + + Python Driver for Scylla and Apache Cassandra® | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

Python Driver for Scylla and Apache Cassandra®

+

A Python client driver for Scylla. +This driver works exclusively with the Cassandra Query Language v3 (CQL3) +and Cassandra’s native protocol.

+

The driver supports Python 2.7, 3.4, 3.5, 3.6, 3.7 and 3.8.

+

This driver is open source under the +Apache v2 License. +The source code for this driver can be found on GitHub.

+

Scylla Driver is a fork from DataStax Python Driver, including some non-breaking changes for Scylla optimization, with more updates planned.

+
+

Contents

+
+
Installation

How to install the driver.

+
+
Getting Started

A guide through the first steps of connecting to Scylla and executing queries

+
+
Scylla Specific Features

A list of feature available only on scylla-driver

+
+
Execution Profiles

An introduction to a more flexible way of configuring request execution

+
+
Lightweight Transactions (Compare-and-set)

Working with results of conditional requests

+
+
Object Mapper

Introduction to the integrated object mapper, cqlengine

+
+
Performance Notes

Tips for getting good performance.

+
+
Paging Large Queries

Notes on paging large query results

+
+
Security

An overview of the security features of the driver

+
+
Upgrading

A guide to upgrading versions of the driver

+
+
User Defined Types

Working with Scylla’s user-defined types (UDT)

+
+
Working with Dates and Times

Some discussion on the driver’s approach to working with timestamp, date, time types

+
+
Scylla Cloud

Connect to Scylla Cloud

+
+
CHANGELOG

Log of changes to the driver, organized by version.

+
+
Frequently Asked Questions

A collection of Frequently Asked Questions

+
+
API Documentation

The API documentation.

+
+
+
+
+
+
+

Getting Help

+

Visit the FAQ section in this documentation.

+

Please send questions to the Scylla user list.

+
+
+

Reporting Issues

+

Please report any bugs and make any feature requests on the Github project issues

+
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.24.8-scylla/installation.html b/3.24.8-scylla/installation.html new file mode 100644 index 0000000000..61562a754a --- /dev/null +++ b/3.24.8-scylla/installation.html @@ -0,0 +1,874 @@ + + + + + + + + + + + + + Installation | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

Installation

+
+

Supported Platforms

+

Python 2.7, 3.4, 3.5, 3.6, 3.7 and 3.8 are supported. Both CPython (the standard Python +implementation) and PyPy are supported and tested.

+

Linux, OSX, and Windows are supported.

+
+
+

Installation through pip

+

pip is the suggested tool for installing +packages. It will handle installing all Python dependencies for the driver at +the same time as the driver itself. To install the driver*:

+
pip install scylla-driver
+
+
+

You can use pip install --pre scylla-driver if you need to install a beta version.

+

*Note: if intending to use optional extensions, install the dependencies first. The driver may need to be reinstalled if dependencies are added after the initial installation.

+
+
+

Verifying your Installation

+

To check if the installation was successful, you can run:

+
python -c 'import cassandra; print cassandra.__version__'
+
+
+

It should print something like “3.22.0”.

+
+
+

(Optional) Graph

+

The driver provides an optional fluent graph API that depends on Apache TinkerPop (gremlinpython). It is +not installed by default. To be able to build Gremlin traversals, you need to install +the graph requirements:

+
pip install scylla-driver[graph]
+
+
+
+
+

(Optional) Compression Support

+

Compression can optionally be used for communication between the driver and +Cassandra. There are currently two supported compression algorithms: +snappy (in Cassandra 1.2+) and LZ4 (only in Cassandra 2.0+). If either is +available for the driver and Cassandra also supports it, it will +be used automatically.

+

For lz4 support:

+
pip install lz4
+
+
+

For snappy support:

+
pip install python-snappy
+
+
+

(If using a Debian Linux derivative such as Ubuntu, it may be easier to +just run apt-get install python-snappy.)

+
+
+

(Optional) Metrics Support

+

The driver has built-in support for capturing Cluster.metrics about +the queries you run. However, the scales library is required to +support this:

+
pip install scales
+
+
+
+

Speeding Up Installation

+

By default, installing the driver through pip uses a pre-compiled, platform-specific wheel when available. +If using a source distribution rather than a wheel, Cython is used to compile certain parts of the driver. +This makes those hot paths faster at runtime, but the Cython compilation +process can take a long time – as long as 10 minutes in some environments.

+

In environments where performance is less important, it may be worth it to +disable Cython as documented below. +You can also use CASS_DRIVER_BUILD_CONCURRENCY to increase the number of +threads used to build the driver and any C extensions:

+
$ # installing from source
+$ CASS_DRIVER_BUILD_CONCURRENCY=8 python setup.py install
+$ # installing from pip
+$ CASS_DRIVER_BUILD_CONCURRENCY=8 pip install scylla-driver
+
+
+
+
+

OSX Installation Error

+

If you’re installing on OSX and have XCode 5.1 installed, you may see an error like this:

+
clang: error: unknown argument: '-mno-fused-madd' [-Wunused-command-line-argument-hard-error-in-future]
+
+
+

To fix this, re-run the installation with an extra compilation flag:

+
ARCHFLAGS=-Wno-error=unused-command-line-argument-hard-error-in-future pip install scylla-driver
+
+
+
+
+
+

Windows Installation Notes

+

Installing the driver with extensions in Windows sometimes presents some challenges. A few notes about common +hang-ups:

+

Setup requires a compiler. When using Python 2, this is as simple as installing this package +(this link is also emitted during install if setuptools is unable to find the resources it needs). Depending on your +system settings, this package may install as a user-specific application. Make sure to install for everyone, or at least +as the user that will be building the Python environment.

+

It is also possible to run the build with your compiler of choice. Just make sure to have your environment setup with +the proper paths. Make sure the compiler target architecture matches the bitness of your Python runtime. +Perhaps the easiest way to do this is to run the build/install from a Visual Studio Command Prompt (a +shortcut installed with Visual Studio that sources the appropriate environment and presents a shell).

+
+
+

Manual Installation

+

You can always install the driver directly from a source checkout or tarball. +When installing manually, ensure the python dependencies are already +installed. You can find the list of dependencies in +requirements.txt.

+

Once the dependencies are installed, simply run:

+
python setup.py install
+
+
+
+
+

(Optional) Non-python Dependencies

+

The driver has several optional features that have non-Python dependencies.

+
+

C Extensions

+

By default, a number of extensions are compiled, providing faster hashing +for token-aware routing with the Murmur3Partitioner, +libev event loop integration, +and Cython optimized extensions.

+

When installing manually through setup.py, you can disable both with +the --no-extensions option, or selectively disable them with +with --no-murmur3, --no-libev, or --no-cython.

+

To compile the extensions, ensure that GCC and the Python headers are available.

+

On Ubuntu and Debian, this can be accomplished by running:

+
$ sudo apt-get install gcc python-dev
+
+
+

On RedHat and RedHat-based systems like CentOS and Fedora:

+
$ sudo yum install gcc python-devel
+
+
+

On OS X, homebrew installations of Python should provide the necessary headers.

+

See Windows Installation Notes for notes on configuring the build environment on Windows.

+
+

Cython-based Extensions

+

By default, this package uses Cython to optimize core modules and build custom extensions. +This is not a hard requirement, but is engaged by default to build extensions offering better performance than the +pure Python implementation.

+

This is a costly build phase, especially in clean environments where the Cython compiler must be built +This build phase can be avoided using the build switch, or an environment variable:

+
python setup.py install --no-cython
+
+
+

Alternatively, an environment variable can be used to switch this option regardless of +context:

+
CASS_DRIVER_NO_CYTHON=1 <your script here>
+- or, to disable all extensions:
+CASS_DRIVER_NO_EXTENSIONS=1 <your script here>
+
+
+

This method is required when using pip, which provides no other way of injecting user options in a single command:

+
CASS_DRIVER_NO_CYTHON=1 pip install scylla-driver
+CASS_DRIVER_NO_CYTHON=1 sudo -E pip install ~/python-driver
+
+
+

The environment variable is the preferred option because it spans all invocations of setup.py, and will +prevent Cython from being materialized as a setup requirement.

+

If your sudo configuration does not allow SETENV, you must push the option flag down via pip. However, pip +applies these options to all dependencies (which break on the custom flag). Therefore, you must first install +dependencies, then use install-option:

+
sudo pip install six futures
+sudo pip install --install-option="--no-cython"
+
+
+
+
+
+

libev support

+

The driver currently uses Python’s asyncore module for its default +event loop. For better performance, libev is also supported through +a C extension.

+

If you’re on Linux, you should be able to install libev +through a package manager. For example, on Debian/Ubuntu:

+
$ sudo apt-get install libev4 libev-dev
+
+
+

On RHEL/CentOS/Fedora:

+
$ sudo yum install libev libev-devel
+
+
+

If you’re on Mac OS X, you should be able to install libev +through Homebrew. For example, on Mac OS X:

+
$ brew install libev
+
+
+

The libev extension is not built for Windows (the build process is complex, and the Windows implementation uses +select anyway).

+

If successful, you should be able to build and install the extension +(just using setup.py build or setup.py install) and then use +the libev event loop by doing the following:

+
>>> from cassandra.io.libevreactor import LibevConnection
+>>> from cassandra.cluster import Cluster
+
+>>> cluster = Cluster()
+>>> cluster.connection_class = LibevConnection
+>>> session = cluster.connect()
+
+
+
+
+
+

(Optional) Configuring SSL

+

Andrew Mussey has published a thorough guide on +Using SSL with the DataStax Python driver.

+
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.24.8-scylla/lwt.html b/3.24.8-scylla/lwt.html new file mode 100644 index 0000000000..e957622535 --- /dev/null +++ b/3.24.8-scylla/lwt.html @@ -0,0 +1,734 @@ + + + + + + + + + + + + + Lightweight Transactions (Compare-and-set) | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

Lightweight Transactions (Compare-and-set)

+

Lightweight Transactions (LWTs) are mostly pass-through CQL for the driver. However, +the server returns some specialized results indicating the outcome and optional state +preceding the transaction.

+

For pertinent execution parameters, see Statement.serial_consistency_level.

+

This section discusses working with specialized result sets returned by the server for LWTs, +and how to work with them using the driver.

+
+

Specialized Results

+

The result returned from a LWT request is always a single row result. It will always have +prepended a special column named [applied]. How this value appears in your results depends +on the row factory in use. See below for examples.

+

The value of this [applied] column is boolean value indicating whether or not the transaction was applied. +If True, it is the only column in the result. If False, the additional columns depend on the LWT operation being +executed:

+
    +
  • When using a UPDATE ... IF "col" = ... clause, the result will contain the [applied] column, plus the existing columns +and values for any columns in the IF clause (and thus the value that caused the transaction to fail).

  • +
  • When using INSERT ... IF NOT EXISTS, the result will contain the [applied] column, plus all columns and values +of the existing row that rejected the transaction.

  • +
  • UPDATE .. IF EXISTS never has additional columns, regardless of [applied] status.

  • +
+

How the [applied] column manifests depends on the row factory in use. Considering the following (initially empty) table:

+
CREATE TABLE test.t (
+    k int PRIMARY KEY,
+    v int,
+    x int
+)
+
+
+

… the following sections show the expected result for a number of example statements, using the three base row factories.

+
+

named_tuple_factory (default)

+

The name [applied] is not a valid Python identifier, so the square brackets are actually removed +from the attribute for the resulting namedtuple. The row always has a boolean column applied in position 0:

+
>>> session.execute("INSERT INTO t (k,v) VALUES (0,0) IF NOT EXISTS")
+Row(applied=True)
+
+>>> session.execute("INSERT INTO t (k,v) VALUES (0,0) IF NOT EXISTS")
+Row(applied=False, k=0, v=0, x=None)
+
+>>> session.execute("UPDATE t SET v = 1, x = 2 WHERE k = 0 IF v =0")
+Row(applied=True)
+
+>>> session.execute("UPDATE t SET v = 1, x = 2 WHERE k = 0 IF v =0 AND x = 1")
+Row(applied=False, v=1, x=2)
+
+
+
+
+

tuple_factory

+

This return type does not refer to names, but the boolean value applied is always present in position 0:

+
>>> session.execute("INSERT INTO t (k,v) VALUES (0,0) IF NOT EXISTS")
+(True,)
+
+>>> session.execute("INSERT INTO t (k,v) VALUES (0,0) IF NOT EXISTS")
+(False, 0, 0, None)
+
+>>> session.execute("UPDATE t SET v = 1, x = 2 WHERE k = 0 IF v =0")
+(True,)
+
+>>> session.execute("UPDATE t SET v = 1, x = 2 WHERE k = 0 IF v =0 AND x = 1")
+(False, 1, 2)
+
+
+
+
+

dict_factory

+

The retuned dict contains the [applied] key:

+
>>> session.execute("INSERT INTO t (k,v) VALUES (0,0) IF NOT EXISTS")
+{u'[applied]': True}
+
+>>> session.execute("INSERT INTO t (k,v) VALUES (0,0) IF NOT EXISTS")
+{u'x': 2, u'[applied]': False, u'v': 1}
+
+>>> session.execute("UPDATE t SET v = 1, x = 2 WHERE k = 0 IF v =0")
+{u'x': None, u'[applied]': False, u'k': 0, u'v': 0}
+
+>>> session.execute("UPDATE t SET v = 1, x = 2 WHERE k = 0 IF v =0 AND x = 1")
+{u'[applied]': True}
+
+
+
+
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.24.8-scylla/object_mapper.html b/3.24.8-scylla/object_mapper.html new file mode 100644 index 0000000000..ebfa91a88f --- /dev/null +++ b/3.24.8-scylla/object_mapper.html @@ -0,0 +1,731 @@ + + + + + + + + + + + + + Object Mapper | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

Object Mapper

+

cqlengine is the Cassandra CQL 3 Object Mapper packaged with this driver

+

Jump to Getting Started

+
+

Contents

+
+
Upgrade Guide

For migrating projects from legacy cqlengine, to the integrated product

+
+
Models

Examples defining models, and mapping them to tables

+
+
Making Queries

Overview of query sets and filtering

+
+
Batch Queries

Working with batch mutations

+
+
Connections

Working with multiple sessions

+
+
API Documentation

Index of API documentation

+
+
Third party integrations

High-level examples in Celery and uWSGI

+
+
+

Frequently Asked Questions

+
+
+
+
+

Getting Started

+
import uuid
+from cassandra.cqlengine import columns
+from cassandra.cqlengine import connection
+from datetime import datetime
+from cassandra.cqlengine.management import sync_table
+from cassandra.cqlengine.models import Model
+
+#first, define a model
+class ExampleModel(Model):
+    example_id      = columns.UUID(primary_key=True, default=uuid.uuid4)
+    example_type    = columns.Integer(index=True)
+    created_at      = columns.DateTime()
+    description     = columns.Text(required=False)
+
+#next, setup the connection to your cassandra server(s)...
+# see http://datastax.github.io/python-driver/api/cassandra/cluster.html for options
+# the list of hosts will be passed to create a Cluster() instance
+connection.setup(['127.0.0.1'], "cqlengine", protocol_version=3)
+
+#...and create your CQL table
+>>> sync_table(ExampleModel)
+
+#now we can create some rows:
+>>> em1 = ExampleModel.create(example_type=0, description="example1", created_at=datetime.now())
+>>> em2 = ExampleModel.create(example_type=0, description="example2", created_at=datetime.now())
+>>> em3 = ExampleModel.create(example_type=0, description="example3", created_at=datetime.now())
+>>> em4 = ExampleModel.create(example_type=0, description="example4", created_at=datetime.now())
+>>> em5 = ExampleModel.create(example_type=1, description="example5", created_at=datetime.now())
+>>> em6 = ExampleModel.create(example_type=1, description="example6", created_at=datetime.now())
+>>> em7 = ExampleModel.create(example_type=1, description="example7", created_at=datetime.now())
+>>> em8 = ExampleModel.create(example_type=1, description="example8", created_at=datetime.now())
+
+#and now we can run some queries against our table
+>>> ExampleModel.objects.count()
+8
+>>> q = ExampleModel.objects(example_type=1)
+>>> q.count()
+4
+>>> for instance in q:
+>>>     print instance.description
+example5
+example6
+example7
+example8
+
+#here we are applying additional filtering to an existing query
+#query objects are immutable, so calling filter returns a new
+#query object
+>>> q2 = q.filter(example_id=em5.example_id)
+
+>>> q2.count()
+1
+>>> for instance in q2:
+>>>     print instance.description
+example5
+
+
+
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.24.8-scylla/objects.inv b/3.24.8-scylla/objects.inv new file mode 100644 index 0000000000..e502ea236f Binary files /dev/null and b/3.24.8-scylla/objects.inv differ diff --git a/3.24.8-scylla/performance.html b/3.24.8-scylla/performance.html new file mode 100644 index 0000000000..f9a5e8f341 --- /dev/null +++ b/3.24.8-scylla/performance.html @@ -0,0 +1,685 @@ + + + + + + + + + + + + + Performance Notes | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

Performance Notes

+

The Python driver for Cassandra offers several methods for executing queries. +You can synchronously block for queries to complete using +Session.execute(), you can obtain asynchronous request futures through +Session.execute_async(), and you can attach a callback to the future +with ResponseFuture.add_callback().

+

Examples of multiple request patterns can be found in the benchmark scripts included in the driver project.

+

The choice of execution pattern will depend on the application context. For applications dealing with multiple +requests in a given context, the recommended pattern is to use concurrent asynchronous +requests with callbacks. For many use cases, you don’t need to implement this pattern yourself. +cassandra.concurrent.execute_concurrent() and cassandra.concurrent.execute_concurrent_with_args() +provide this pattern with a synchronous API and tunable concurrency.

+

Due to the GIL and limited concurrency, the driver can become CPU-bound pretty quickly. The sections below +discuss further runtime and design considerations for mitigating this limitation.

+
+

PyPy

+

PyPy is an alternative Python runtime which uses a JIT compiler to +reduce CPU consumption. This leads to a huge improvement in the driver performance, +more than doubling throughput for many workloads.

+
+
+

Cython Extensions

+

Cython is an optimizing compiler and language that can be used to compile the core files and +optional extensions for the driver. Cython is not a strict dependency, but the extensions will be built by default.

+

See Installation for details on controlling this build.

+
+
+

multiprocessing

+

All of the patterns discussed above may be used over multiple processes using the +multiprocessing +module. Multiple processes will scale better than multiple threads, so if high throughput is your goal, +consider this option.

+

Be sure to never share any Cluster, Session, +or ResponseFuture objects across multiple processes. These +objects should all be created after forking the process, not before.

+

For further discussion and simple examples using the driver with multiprocessing, +see this blog post.

+
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.24.8-scylla/py-modindex.html b/3.24.8-scylla/py-modindex.html new file mode 100644 index 0000000000..4f452f644d --- /dev/null +++ b/3.24.8-scylla/py-modindex.html @@ -0,0 +1,618 @@ + + + + + + + + + + + + + Python Module Index | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ + + +
+ + + + + +
+ + +
+
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.24.8-scylla/query_paging.html b/3.24.8-scylla/query_paging.html new file mode 100644 index 0000000000..72252bcc1c --- /dev/null +++ b/3.24.8-scylla/query_paging.html @@ -0,0 +1,739 @@ + + + + + + + + + + + + + Paging Large Queries | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

Paging Large Queries

+

Cassandra 2.0+ offers support for automatic query paging. Starting with +version 2.0 of the driver, if protocol_version is greater than +2 (it is by default), queries returning large result sets will be +automatically paged.

+
+

Controlling the Page Size

+

By default, Session.default_fetch_size controls how many rows will +be fetched per page. This can be overridden per-query by setting +fetch_size on a Statement. By default, each page +will contain at most 5000 rows.

+
+
+

Handling Paged Results

+

Whenever the number of result rows for are query exceed the page size, an +instance of PagedResult will be returned instead of a normal +list. This class implements the iterator interface, so you can treat +it like a normal iterator over rows:

+
from cassandra.query import SimpleStatement
+query = "SELECT * FROM users"  # users contains 100 rows
+statement = SimpleStatement(query, fetch_size=10)
+for user_row in session.execute(statement):
+    process_user(user_row)
+
+
+

Whenever there are no more rows in the current page, the next page will +be fetched transparently. However, note that it is possible for +an Exception to be raised while fetching the next page, just +like you might see on a normal call to session.execute().

+

If you use Session.execute_async() along with, +ResponseFuture.result(), the first page will be fetched before +result() returns, but latter pages will be +transparently fetched synchronously while iterating the result.

+
+
+

Handling Paged Results with Callbacks

+

If callbacks are attached to a query that returns a paged result, +the callback will be called once per page with a normal list of rows.

+

Use ResponseFuture.has_more_pages and +ResponseFuture.start_fetching_next_page() to continue fetching +pages. For example:

+
class PagedResultHandler(object):
+
+    def __init__(self, future):
+        self.error = None
+        self.finished_event = Event()
+        self.future = future
+        self.future.add_callbacks(
+            callback=self.handle_page,
+            errback=self.handle_err)
+
+    def handle_page(self, rows):
+        for row in rows:
+            process_row(row)
+
+        if self.future.has_more_pages:
+            self.future.start_fetching_next_page()
+        else:
+            self.finished_event.set()
+
+    def handle_error(self, exc):
+        self.error = exc
+        self.finished_event.set()
+
+future = session.execute_async("SELECT * FROM users")
+handler = PagedResultHandler(future)
+handler.finished_event.wait()
+if handler.error:
+    raise handler.error
+
+
+
+
+

Resume Paged Results

+

You can resume the pagination when executing a new query by using the ResultSet.paging_state. This can be useful if you want to provide some stateless pagination capabilities to your application (ie. via http). For example:

+
from cassandra.query import SimpleStatement
+query = "SELECT * FROM users"
+statement = SimpleStatement(query, fetch_size=10)
+results = session.execute(statement)
+
+# save the paging_state somewhere and return current results
+web_session['paging_state'] = results.paging_state
+
+
+# resume the pagination sometime later...
+statement = SimpleStatement(query, fetch_size=10)
+ps = web_session['paging_state']
+results = session.execute(statement, paging_state=ps)
+
+
+
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.24.8-scylla/scylla_cloud.html b/3.24.8-scylla/scylla_cloud.html new file mode 100644 index 0000000000..2a0fe39c2e --- /dev/null +++ b/3.24.8-scylla/scylla_cloud.html @@ -0,0 +1,637 @@ + + + + + + + + + + + + + Scylla Cloud | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

Scylla Cloud

+

To connect to a Scylla Cloud cluster, go to the Cluster Connect page, Python example. +For best performance, make sure to use the Scylla Driver.

+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.24.8-scylla/scylla_specific.html b/3.24.8-scylla/scylla_specific.html new file mode 100644 index 0000000000..a891be9cdb --- /dev/null +++ b/3.24.8-scylla/scylla_specific.html @@ -0,0 +1,726 @@ + + + + + + + + + + + + + Scylla Specific Features | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

Scylla Specific Features

+
+

Shard Awareness

+

scylla-driver is shard aware and contains extensions that work with the TokenAwarePolicy supported by Scylla 2.3 and onwards. Using this policy, the driver can select a connection to a particular shard based on the shard’s token. +As a result, latency is significantly reduced because there is no need to pass data between the shards.

+

Details on the scylla cql protocol extensions +https://github.com/scylladb/scylla/blob/master/docs/design-notes/protocol-extensions.md

+

For using it you only need to enable TokenAwarePolicy on the Cluster

+
from cassandra.cluster import Cluster
+from cassandra.policies import TokenAwarePolicy, RoundRobinPolicy
+
+cluster = Cluster(load_balancing_policy=TokenAwarePolicy(RoundRobinPolicy()))
+
+
+
+
+

New Cluster Helpers

+
    +
  • cluster.is_shard_aware()

    +

    New method available on Cluster allowing to check whether the remote cluster supports shard awareness (bool)

    +
  • +
+
from cassandra.cluster import Cluster
+
+cluster = Cluster()
+session = cluster.connect()
+
+if cluster.is_shard_aware():
+    print("connected to a scylla cluster")
+
+
+
    +
  • cluster.shard_aware_stats()

    +

    New method available on Cluster allowing to check the status of shard aware connections to all available hosts (dict)

    +
  • +
+
from cassandra.cluster import Cluster
+
+cluster = Cluster()
+session = cluster.connect()
+
+stats = cluster.shard_aware_stats()
+if all([v["shards_count"] == v["connected"] for v in stats.values()]):
+    print("successfully connected to all shards of all scylla nodes")
+
+
+
+
+

New Table Attributes

+
    +
  • in_memory flag

    +

    New flag available on TableMetadata.options to indicate that it is an In Memory table

    +
  • +
+
+

Note

+

in memory tables is a feature existing only in Scylla Enterprise

+
+
from cassandra.cluster import Cluster
+
+cluster = Cluster()
+session = cluster.connect()
+session.execute("""
+    CREATE KEYSPACE IF NOT EXISTS keyspace1
+    WITH replication = {'class': 'SimpleStrategy', 'replication_factor': '1'};
+""")
+
+session.execute("""
+    CREATE TABLE IF NOT EXISTS keyspace1.standard1 (
+        key blob PRIMARY KEY,
+        "C0" blob
+    ) WITH in_memory=true AND compaction={'class': 'InMemoryCompactionStrategy'}
+""")
+
+cluster.refresh_table_metadata("keyspace1", "standard1")
+assert cluster.metadata.keyspaces["keyspace1"].tables["standard1"].options["in_memory"] == True
+
+
+
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.24.8-scylla/search.html b/3.24.8-scylla/search.html new file mode 100644 index 0000000000..a49d2b0c3a --- /dev/null +++ b/3.24.8-scylla/search.html @@ -0,0 +1,621 @@ + + + + + + + + + + + + + Search | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + + + + + +
+ + + + + +
+ + +
+
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.24.8-scylla/searchindex.js b/3.24.8-scylla/searchindex.js new file mode 100644 index 0000000000..69e2845ba3 --- /dev/null +++ b/3.24.8-scylla/searchindex.js @@ -0,0 +1 @@ +Search.setIndex({docnames:["CHANGELOG","api/cassandra","api/cassandra/auth","api/cassandra/cluster","api/cassandra/concurrent","api/cassandra/connection","api/cassandra/cqlengine/columns","api/cassandra/cqlengine/connection","api/cassandra/cqlengine/management","api/cassandra/cqlengine/models","api/cassandra/cqlengine/query","api/cassandra/cqlengine/usertype","api/cassandra/datastax/graph/fluent/index","api/cassandra/datastax/graph/fluent/predicates","api/cassandra/datastax/graph/fluent/query","api/cassandra/datastax/graph/index","api/cassandra/decoder","api/cassandra/encoder","api/cassandra/graph","api/cassandra/io/asyncioreactor","api/cassandra/io/asyncorereactor","api/cassandra/io/eventletreactor","api/cassandra/io/geventreactor","api/cassandra/io/libevreactor","api/cassandra/io/twistedreactor","api/cassandra/metadata","api/cassandra/metrics","api/cassandra/policies","api/cassandra/pool","api/cassandra/protocol","api/cassandra/query","api/cassandra/timestamps","api/cassandra/util","api/index","cqlengine/batches","cqlengine/connections","cqlengine/faq","cqlengine/models","cqlengine/queryset","cqlengine/third_party","cqlengine/upgrade_guide","dates_and_times","execution_profiles","faq","getting_started","index","installation","lwt","object_mapper","performance","query_paging","scylla_cloud","scylla_specific","security","upgrading","user_defined_types"],envversion:{"sphinx.domains.c":2,"sphinx.domains.changeset":1,"sphinx.domains.citation":1,"sphinx.domains.cpp":4,"sphinx.domains.index":1,"sphinx.domains.javascript":2,"sphinx.domains.math":2,"sphinx.domains.python":3,"sphinx.domains.rst":2,"sphinx.domains.std":2,"sphinx.ext.todo":2,sphinx:56},filenames:["CHANGELOG.rst","api/cassandra.rst","api/cassandra/auth.rst","api/cassandra/cluster.rst","api/cassandra/concurrent.rst","api/cassandra/connection.rst","api/cassandra/cqlengine/columns.rst","api/cassandra/cqlengine/connection.rst","api/cassandra/cqlengine/management.rst","api/cassandra/cqlengine/models.rst","api/cassandra/cqlengine/query.rst","api/cassandra/cqlengine/usertype.rst","api/cassandra/datastax/graph/fluent/index.rst","api/cassandra/datastax/graph/fluent/predicates.rst","api/cassandra/datastax/graph/fluent/query.rst","api/cassandra/datastax/graph/index.rst","api/cassandra/decoder.rst","api/cassandra/encoder.rst","api/cassandra/graph.rst","api/cassandra/io/asyncioreactor.rst","api/cassandra/io/asyncorereactor.rst","api/cassandra/io/eventletreactor.rst","api/cassandra/io/geventreactor.rst","api/cassandra/io/libevreactor.rst","api/cassandra/io/twistedreactor.rst","api/cassandra/metadata.rst","api/cassandra/metrics.rst","api/cassandra/policies.rst","api/cassandra/pool.rst","api/cassandra/protocol.rst","api/cassandra/query.rst","api/cassandra/timestamps.rst","api/cassandra/util.rst","api/index.rst","cqlengine/batches.rst","cqlengine/connections.rst","cqlengine/faq.rst","cqlengine/models.rst","cqlengine/queryset.rst","cqlengine/third_party.rst","cqlengine/upgrade_guide.rst","dates_and_times.rst","execution_profiles.rst","faq.rst","getting_started.rst","index.rst","installation.rst","lwt.rst","object_mapper.rst","performance.rst","query_paging.rst","scylla_cloud.rst","scylla_specific.rst","security.rst","upgrading.rst","user_defined_types.rst"],objects:{"":[[1,0,0,"-","cassandra"]],"cassandra.AlreadyExists":[[1,2,1,"","keyspace"],[1,2,1,"","table"]],"cassandra.ConsistencyLevel":[[1,2,1,"","ALL"],[1,2,1,"","ANY"],[1,2,1,"","EACH_QUORUM"],[1,2,1,"","LOCAL_ONE"],[1,2,1,"","LOCAL_QUORUM"],[1,2,1,"","LOCAL_SERIAL"],[1,2,1,"","ONE"],[1,2,1,"","QUORUM"],[1,2,1,"","SERIAL"],[1,2,1,"","THREE"],[1,2,1,"","TWO"]],"cassandra.CoordinationFailure":[[1,2,1,"","consistency"],[1,2,1,"","error_code_map"],[1,2,1,"","failures"],[1,2,1,"","received_responses"],[1,2,1,"","required_responses"]],"cassandra.FunctionFailure":[[1,2,1,"","arg_types"],[1,2,1,"","function"],[1,2,1,"","keyspace"]],"cassandra.OperationTimedOut":[[1,2,1,"","errors"],[1,2,1,"","last_host"]],"cassandra.ProtocolVersion":[[1,2,1,"","BETA_VERSIONS"],[1,2,1,"","DSE_V1"],[1,2,1,"","DSE_V2"],[1,2,1,"","MAX_SUPPORTED"],[1,2,1,"","MIN_SUPPORTED"],[1,2,1,"","SUPPORTED_VERSIONS"],[1,2,1,"","V1"],[1,2,1,"","V2"],[1,2,1,"","V3"],[1,2,1,"","V4"],[1,2,1,"","V5"],[1,2,1,"","V6"],[1,4,1,"","get_lower_supported"]],"cassandra.ReadFailure":[[1,2,1,"","data_retrieved"]],"cassandra.ReadTimeout":[[1,2,1,"","data_retrieved"]],"cassandra.Timeout":[[1,2,1,"","consistency"],[1,2,1,"","received_responses"],[1,2,1,"","required_responses"]],"cassandra.Unavailable":[[1,2,1,"","alive_replicas"],[1,2,1,"","consistency"],[1,2,1,"","required_replicas"]],"cassandra.UserAggregateDescriptor":[[1,2,1,"","argument_types"],[1,2,1,"","name"],[1,5,1,"","signature"]],"cassandra.UserFunctionDescriptor":[[1,2,1,"","argument_types"],[1,2,1,"","name"],[1,5,1,"","signature"]],"cassandra.WriteFailure":[[1,2,1,"","write_type"]],"cassandra.WriteTimeout":[[1,2,1,"","write_type"]],"cassandra.auth":[[2,3,1,"","AuthProvider"],[2,3,1,"","Authenticator"],[2,3,1,"","PlainTextAuthProvider"],[2,3,1,"","PlainTextAuthenticator"],[2,3,1,"","SaslAuthProvider"],[2,3,1,"","SaslAuthenticator"]],"cassandra.auth.AuthProvider":[[2,4,1,"","new_authenticator"]],"cassandra.auth.Authenticator":[[2,4,1,"","evaluate_challenge"],[2,4,1,"","initial_response"],[2,4,1,"","on_authentication_success"],[2,2,1,"","server_authenticator_class"]],"cassandra.auth.PlainTextAuthProvider":[[2,4,1,"","new_authenticator"]],"cassandra.auth.PlainTextAuthenticator":[[2,4,1,"","evaluate_challenge"]],"cassandra.auth.SaslAuthProvider":[[2,4,1,"","new_authenticator"]],"cassandra.auth.SaslAuthenticator":[[2,4,1,"","evaluate_challenge"],[2,4,1,"","initial_response"]],"cassandra.cluster":[[3,3,1,"","Cluster"],[3,6,1,"","EXEC_PROFILE_DEFAULT"],[3,6,1,"","EXEC_PROFILE_GRAPH_ANALYTICS_DEFAULT"],[3,6,1,"","EXEC_PROFILE_GRAPH_DEFAULT"],[3,6,1,"","EXEC_PROFILE_GRAPH_SYSTEM_DEFAULT"],[3,3,1,"","ExecutionProfile"],[3,3,1,"","GraphAnalyticsExecutionProfile"],[3,3,1,"","GraphExecutionProfile"],[3,1,1,"","NoHostAvailable"],[3,1,1,"","QueryExhausted"],[3,3,1,"","ResponseFuture"],[3,3,1,"","ResultSet"],[3,3,1,"","Session"],[3,1,1,"","UserTypeDoesNotExist"]],"cassandra.cluster.Cluster":[[3,4,1,"","add_execution_profile"],[3,2,1,"","address_translator"],[3,2,1,"","auth_provider"],[3,2,1,"","cloud"],[3,2,1,"","compression"],[3,4,1,"","connect"],[3,2,1,"","connect_timeout"],[3,2,1,"","connection_class"],[3,2,1,"","contact_points"],[3,2,1,"","control_connection_timeout"],[3,2,1,"","conviction_policy_factory"],[3,2,1,"","cql_version"],[3,2,1,"","default_retry_policy"],[3,2,1,"","endpoint_factory"],[3,4,1,"","get_control_connection_host"],[3,4,1,"","get_core_connections_per_host"],[3,4,1,"","get_max_connections_per_host"],[3,4,1,"","get_max_requests_per_connection"],[3,4,1,"","get_min_requests_per_connection"],[3,2,1,"","idle_heartbeat_interval"],[3,2,1,"","idle_heartbeat_timeout"],[3,2,1,"","load_balancing_policy"],[3,2,1,"","max_schema_agreement_wait"],[3,2,1,"","metadata"],[3,2,1,"","metrics"],[3,2,1,"","metrics_enabled"],[3,2,1,"","port"],[3,2,1,"","prepare_on_all_hosts"],[3,2,1,"","protocol_version"],[3,2,1,"","reconnection_policy"],[3,4,1,"","refresh_keyspace_metadata"],[3,4,1,"","refresh_nodes"],[3,4,1,"","refresh_schema_metadata"],[3,4,1,"","refresh_table_metadata"],[3,4,1,"","refresh_user_aggregate_metadata"],[3,4,1,"","refresh_user_function_metadata"],[3,4,1,"","refresh_user_type_metadata"],[3,4,1,"","register_listener"],[3,4,1,"","register_user_type"],[3,2,1,"","reprepare_on_up"],[3,2,1,"","schema_event_refresh_window"],[3,2,1,"","schema_metadata_enabled"],[3,4,1,"","set_core_connections_per_host"],[3,4,1,"","set_max_connections_per_host"],[3,4,1,"","set_max_requests_per_connection"],[3,4,1,"","set_meta_refresh_enabled"],[3,4,1,"","set_min_requests_per_connection"],[3,4,1,"","shutdown"],[3,2,1,"","sockopts"],[3,2,1,"","ssl_context"],[3,2,1,"","ssl_options"],[3,2,1,"","status_event_refresh_window"],[3,2,1,"","timestamp_generator"],[3,2,1,"","token_metadata_enabled"],[3,2,1,"","topology_event_refresh_window"],[3,4,1,"","unregister_listener"]],"cassandra.cluster.ExecutionProfile":[[3,2,1,"","consistency_level"],[3,4,1,"","row_factory"]],"cassandra.cluster.ResponseFuture":[[3,4,1,"","add_callback"],[3,4,1,"","add_errback"],[3,2,1,"","custom_payload"],[3,4,1,"","get_all_query_traces"],[3,4,1,"","get_query_trace"],[3,2,1,"","has_more_pages"],[3,2,1,"","is_schema_agreed"],[3,2,1,"","query"],[3,4,1,"","result"],[3,4,1,"","start_fetching_next_page"],[3,2,1,"","warnings"]],"cassandra.cluster.ResultSet":[[3,4,1,"","all"],[3,5,1,"","current_rows"],[3,4,1,"","fetch_next_page"],[3,4,1,"","get_all_query_traces"],[3,4,1,"","get_query_trace"],[3,5,1,"","has_more_pages"],[3,4,1,"","one"],[3,5,1,"","paging_state"],[3,5,1,"","was_applied"]],"cassandra.cluster.Session":[[3,4,1,"","add_request_init_listener"],[3,2,1,"","client_protocol_handler"],[3,2,1,"","default_consistency_level"],[3,2,1,"","default_fetch_size"],[3,2,1,"","default_serial_consistency_level"],[3,2,1,"","default_timeout"],[3,2,1,"","encoder"],[3,4,1,"","execute"],[3,4,1,"","execute_async"],[3,4,1,"","execute_graph"],[3,4,1,"","execute_graph_async"],[3,4,1,"","execution_profile_clone_update"],[3,4,1,"","get_execution_profile"],[3,4,1,"","prepare"],[3,4,1,"","remove_request_init_listener"],[3,2,1,"","row_factory"],[3,4,1,"","set_keyspace"],[3,4,1,"","shutdown"],[3,2,1,"","timestamp_generator"],[3,2,1,"","use_client_timestamp"]],"cassandra.concurrent":[[4,7,1,"","execute_concurrent"],[4,7,1,"","execute_concurrent_with_args"]],"cassandra.connection":[[5,1,1,"","ConnectionBusy"],[5,1,1,"","ConnectionException"],[5,1,1,"","ConnectionShutdown"],[5,3,1,"","EndPoint"],[5,3,1,"","EndPointFactory"],[5,1,1,"","ProtocolError"],[5,3,1,"","SniEndPoint"],[5,3,1,"","SniEndPointFactory"],[5,3,1,"","UnixSocketEndPoint"]],"cassandra.connection.EndPoint":[[5,5,1,"","address"],[5,5,1,"","port"],[5,4,1,"","resolve"],[5,5,1,"","socket_family"],[5,5,1,"","ssl_options"]],"cassandra.connection.EndPointFactory":[[5,4,1,"","configure"],[5,4,1,"","create"]],"cassandra.cqlengine":[[6,0,0,"-","columns"],[7,0,0,"-","connection"],[8,0,0,"-","management"],[9,0,0,"-","models"],[10,0,0,"-","query"],[11,0,0,"-","usertype"]],"cassandra.cqlengine.columns":[[6,3,1,"","Ascii"],[6,3,1,"","BigInt"],[6,3,1,"","Blob"],[6,3,1,"","Boolean"],[6,2,1,"","Bytes"],[6,3,1,"","Column"],[6,3,1,"","Counter"],[6,3,1,"","Date"],[6,3,1,"","DateTime"],[6,3,1,"","Decimal"],[6,3,1,"","Double"],[6,3,1,"","Float"],[6,3,1,"","Integer"],[6,3,1,"","List"],[6,3,1,"","Map"],[6,3,1,"","Set"],[6,3,1,"","SmallInt"],[6,3,1,"","Text"],[6,3,1,"","Time"],[6,3,1,"","TimeUUID"],[6,3,1,"","TinyInt"],[6,3,1,"","UUID"],[6,3,1,"","UserDefinedType"],[6,3,1,"","VarInt"]],"cassandra.cqlengine.columns.Column":[[6,2,1,"","clustering_order"],[6,2,1,"","custom_index"],[6,2,1,"","db_field"],[6,2,1,"","default"],[6,2,1,"","discriminator_column"],[6,2,1,"","index"],[6,2,1,"","partition_key"],[6,2,1,"","primary_key"],[6,2,1,"","required"],[6,2,1,"","static"]],"cassandra.cqlengine.columns.DateTime":[[6,2,1,"","truncate_microseconds"]],"cassandra.cqlengine.connection":[[7,7,1,"","default"],[7,7,1,"","register_connection"],[7,7,1,"","set_default_connection"],[7,7,1,"","set_session"],[7,7,1,"","setup"],[7,7,1,"","unregister_connection"]],"cassandra.cqlengine.management":[[8,7,1,"","create_keyspace_network_topology"],[8,7,1,"","create_keyspace_simple"],[8,7,1,"","drop_keyspace"],[8,7,1,"","drop_table"],[8,7,1,"","sync_table"],[8,7,1,"","sync_type"]],"cassandra.cqlengine.models":[[9,3,1,"","Model"]],"cassandra.cqlengine.models.Model":[[9,2,1,"","__abstract__"],[9,2,1,"","__compute_routing_key__"],[9,2,1,"","__connection__"],[9,2,1,"","__default_ttl__"],[9,2,1,"","__discriminator_value__"],[9,2,1,"","__keyspace__"],[9,2,1,"","__options__"],[9,2,1,"","__table_name__"],[9,2,1,"","__table_name_case_sensitive__"],[9,4,1,"","all"],[9,4,1,"","batch"],[9,4,1,"","column_family_name"],[9,4,1,"","create"],[9,4,1,"","delete"],[9,4,1,"","filter"],[9,4,1,"","get"],[9,4,1,"","if_exists"],[9,4,1,"","if_not_exists"],[9,4,1,"","iff"],[9,4,1,"","items"],[9,4,1,"","keys"],[9,4,1,"","len"],[9,4,1,"","save"],[9,4,1,"","timeout"],[9,4,1,"","timestamp"],[9,4,1,"","ttl"],[9,4,1,"","update"],[9,4,1,"","using"],[9,4,1,"","values"]],"cassandra.cqlengine.query":[[10,3,1,"","BatchQuery"],[10,3,1,"","ContextQuery"],[10,3,1,"","DoesNotExist"],[10,3,1,"","LWTException"],[10,3,1,"","ModelQuerySet"],[10,3,1,"","MultipleObjectsReturned"]],"cassandra.cqlengine.query.BatchQuery":[[10,4,1,"","add_callback"],[10,4,1,"","add_query"],[10,4,1,"","execute"]],"cassandra.cqlengine.query.ModelQuerySet":[[10,4,1,"","all"],[10,4,1,"","allow_filtering"],[10,4,1,"","batch"],[10,4,1,"","consistency"],[10,4,1,"","count"],[10,4,1,"","defer"],[10,4,1,"","distinct"],[10,4,1,"","fetch_size"],[10,4,1,"","filter"],[10,4,1,"","get"],[10,4,1,"","if_exists"],[10,4,1,"","if_not_exists"],[10,4,1,"","len"],[10,4,1,"","limit"],[10,4,1,"","only"],[10,4,1,"","order_by"],[10,4,1,"","timestamp"],[10,4,1,"","ttl"],[10,4,1,"","update"],[10,4,1,"","using"]],"cassandra.cqlengine.usertype":[[11,3,1,"","UserType"]],"cassandra.cqlengine.usertype.UserType":[[11,2,1,"","__type_name__"]],"cassandra.datastax":[[15,0,0,"-","graph"]],"cassandra.datastax.graph":[[15,3,1,"","Edge"],[15,3,1,"","GraphOptions"],[15,3,1,"","GraphProtocol"],[15,3,1,"","GraphSON1Deserializer"],[15,3,1,"","GraphSON1Serializer"],[15,3,1,"","GraphSON2Reader"],[15,3,1,"","Path"],[15,3,1,"","Result"],[15,3,1,"","SimpleGraphStatement"],[15,3,1,"","T"],[15,3,1,"","Vertex"],[15,3,1,"","VertexProperty"],[12,0,0,"-","fluent"],[15,7,1,"","graph_graphson2_row_factory"],[15,7,1,"","graph_graphson3_row_factory"],[15,7,1,"","graph_object_row_factory"],[15,7,1,"","graph_result_row_factory"],[15,7,1,"","single_object_row_factory"],[15,7,1,"","to_bigint"],[15,7,1,"","to_double"],[15,7,1,"","to_float"],[15,7,1,"","to_int"],[15,7,1,"","to_smallint"]],"cassandra.datastax.graph.GraphOptions":[[15,2,1,"","graph_language"],[15,2,1,"","graph_name"],[15,2,1,"","graph_read_consistency_level"],[15,2,1,"","graph_source"],[15,2,1,"","graph_write_consistency_level"],[15,2,1,"","is_analytics_source"],[15,2,1,"","is_default_source"],[15,2,1,"","is_graph_source"],[15,4,1,"","set_source_analytics"],[15,4,1,"","set_source_default"],[15,4,1,"","set_source_graph"]],"cassandra.datastax.graph.GraphProtocol":[[15,2,1,"","GRAPHSON_1_0"],[15,2,1,"","GRAPHSON_2_0"],[15,2,1,"","GRAPHSON_3_0"]],"cassandra.datastax.graph.GraphSON1Deserializer":[[15,4,1,"","deserialize_bigint"],[15,4,1,"","deserialize_blob"],[15,4,1,"","deserialize_date"],[15,4,1,"","deserialize_decimal"],[15,4,1,"","deserialize_double"],[15,4,1,"","deserialize_duration"],[15,4,1,"","deserialize_float"],[15,4,1,"","deserialize_int"],[15,4,1,"","deserialize_linestring"],[15,4,1,"","deserialize_point"],[15,4,1,"","deserialize_polygon"],[15,4,1,"","deserialize_time"],[15,4,1,"","deserialize_timestamp"],[15,4,1,"","deserialize_uuid"]],"cassandra.datastax.graph.GraphSON2Reader":[[15,4,1,"","deserialize"],[15,4,1,"","read"]],"cassandra.datastax.graph.Path":[[15,2,1,"","labels"],[15,2,1,"","objects"]],"cassandra.datastax.graph.Result":[[15,4,1,"","as_edge"],[15,4,1,"","as_path"],[15,4,1,"","as_vertex"],[15,2,1,"","value"]],"cassandra.datastax.graph.T":[[15,2,1,"","id"],[15,2,1,"","key"],[15,2,1,"","label"],[15,2,1,"","value"]],"cassandra.datastax.graph.VertexProperty":[[15,2,1,"","label"],[15,2,1,"","properties"],[15,2,1,"","value"]],"cassandra.datastax.graph.fluent":[[12,3,1,"","BaseGraphRowFactory"],[12,3,1,"","DSESessionRemoteGraphConnection"],[12,3,1,"","DseGraph"],[12,2,1,"","graph_traversal_dse_object_row_factory"],[12,2,1,"","graph_traversal_row_factory"],[13,0,0,"-","predicates"],[14,0,0,"-","query"]],"cassandra.datastax.graph.fluent.DseGraph":[[12,2,1,"","DSE_GRAPH_QUERY_LANGUAGE"],[12,4,1,"","batch"],[12,4,1,"","create_execution_profile"],[12,4,1,"","query_from_traversal"],[12,4,1,"","traversal_source"]],"cassandra.datastax.graph.fluent.predicates":[[13,3,1,"","CqlCollection"],[13,3,1,"","Geo"],[13,3,1,"","Search"]],"cassandra.datastax.graph.fluent.predicates.CqlCollection":[[13,4,1,"","contains"],[13,4,1,"","contains_key"],[13,4,1,"","contains_value"],[13,4,1,"","entry_eq"]],"cassandra.datastax.graph.fluent.predicates.Geo":[[13,4,1,"","inside"]],"cassandra.datastax.graph.fluent.predicates.Search":[[13,4,1,"","fuzzy"],[13,4,1,"","phrase"],[13,4,1,"","prefix"],[13,4,1,"","regex"],[13,4,1,"","token"],[13,4,1,"","token_fuzzy"],[13,4,1,"","token_prefix"],[13,4,1,"","token_regex"]],"cassandra.datastax.graph.fluent.query":[[14,3,1,"","TraversalBatch"]],"cassandra.datastax.graph.fluent.query.TraversalBatch":[[14,4,1,"","add"],[14,4,1,"","add_all"],[14,4,1,"","as_graph_statement"],[14,4,1,"","clear"],[14,4,1,"","execute"]],"cassandra.decoder":[[16,7,1,"","dict_factory"],[16,7,1,"","named_tuple_factory"],[16,7,1,"","ordered_dict_factory"],[16,7,1,"","tuple_factory"]],"cassandra.encoder":[[17,3,1,"","Encoder"]],"cassandra.encoder.Encoder":[[17,4,1,"","cql_encode_all_types"],[17,4,1,"","cql_encode_bytes"],[17,4,1,"","cql_encode_date"],[17,4,1,"","cql_encode_datetime"],[17,4,1,"","cql_encode_list_collection"],[17,4,1,"","cql_encode_map_collection"],[17,4,1,"","cql_encode_none"],[17,4,1,"","cql_encode_object"],[17,4,1,"","cql_encode_sequence"],[17,4,1,"","cql_encode_set_collection"],[17,4,1,"","cql_encode_str"],[17,4,1,"","cql_encode_tuple"],[17,4,1,"","cql_encode_unicode"],[17,2,1,"","mapping"]],"cassandra.graph":[[18,3,1,"","Edge"],[18,3,1,"","GraphOptions"],[18,3,1,"","GraphProtocol"],[18,3,1,"","GraphSON1Deserializer"],[18,3,1,"","GraphSON1Serializer"],[18,3,1,"","GraphSON2Reader"],[18,3,1,"","GraphSON3Reader"],[18,3,1,"","Path"],[18,3,1,"","Result"],[18,3,1,"","SimpleGraphStatement"],[18,3,1,"","Vertex"],[18,3,1,"","VertexProperty"],[18,7,1,"","graph_graphson2_row_factory"],[18,7,1,"","graph_graphson3_row_factory"],[18,7,1,"","graph_object_row_factory"],[18,7,1,"","graph_result_row_factory"],[18,7,1,"","single_object_row_factory"],[18,7,1,"","to_bigint"],[18,7,1,"","to_double"],[18,7,1,"","to_float"],[18,7,1,"","to_int"],[18,7,1,"","to_smallint"]],"cassandra.graph.GraphOptions":[[18,2,1,"","graph_language"],[18,2,1,"","graph_name"],[18,2,1,"","graph_read_consistency_level"],[18,2,1,"","graph_source"],[18,2,1,"","graph_write_consistency_level"],[18,2,1,"","is_analytics_source"],[18,2,1,"","is_default_source"],[18,2,1,"","is_graph_source"],[18,4,1,"","set_source_analytics"],[18,4,1,"","set_source_default"],[18,4,1,"","set_source_graph"]],"cassandra.graph.GraphProtocol":[[18,2,1,"","GRAPHSON_1_0"],[18,2,1,"","GRAPHSON_2_0"],[18,2,1,"","GRAPHSON_3_0"]],"cassandra.graph.GraphSON1Deserializer":[[18,4,1,"","deserialize_bigint"],[18,4,1,"","deserialize_blob"],[18,4,1,"","deserialize_date"],[18,4,1,"","deserialize_decimal"],[18,4,1,"","deserialize_double"],[18,4,1,"","deserialize_duration"],[18,4,1,"","deserialize_float"],[18,4,1,"","deserialize_int"],[18,4,1,"","deserialize_linestring"],[18,4,1,"","deserialize_point"],[18,4,1,"","deserialize_polygon"],[18,4,1,"","deserialize_time"],[18,4,1,"","deserialize_timestamp"],[18,4,1,"","deserialize_uuid"]],"cassandra.graph.GraphSON2Reader":[[18,4,1,"","deserialize"],[18,4,1,"","read"]],"cassandra.graph.Path":[[18,2,1,"","labels"],[18,2,1,"","objects"]],"cassandra.graph.Result":[[18,4,1,"","as_edge"],[18,4,1,"","as_path"],[18,4,1,"","as_vertex"],[18,2,1,"","value"]],"cassandra.graph.VertexProperty":[[18,2,1,"","label"],[18,2,1,"","properties"],[18,2,1,"","value"]],"cassandra.io":[[19,0,0,"-","asyncioreactor"],[20,0,0,"-","asyncorereactor"],[21,0,0,"-","eventletreactor"],[22,0,0,"-","geventreactor"],[23,0,0,"-","libevreactor"],[24,0,0,"-","twistedreactor"]],"cassandra.io.asyncioreactor":[[19,3,1,"","AsyncioConnection"]],"cassandra.io.asyncioreactor.AsyncioConnection":[[19,4,1,"","initialize_reactor"]],"cassandra.io.asyncorereactor":[[20,3,1,"","AsyncoreConnection"]],"cassandra.io.asyncorereactor.AsyncoreConnection":[[20,4,1,"","handle_fork"],[20,4,1,"","initialize_reactor"]],"cassandra.io.eventletreactor":[[21,3,1,"","EventletConnection"]],"cassandra.io.eventletreactor.EventletConnection":[[21,4,1,"","initialize_reactor"],[21,4,1,"","service_timeouts"]],"cassandra.io.geventreactor":[[22,3,1,"","GeventConnection"]],"cassandra.io.geventreactor.GeventConnection":[[22,4,1,"","initialize_reactor"]],"cassandra.io.libevreactor":[[23,3,1,"","LibevConnection"]],"cassandra.io.twistedreactor":[[24,3,1,"","TwistedConnection"]],"cassandra.metadata":[[25,3,1,"","Aggregate"],[25,3,1,"","BytesToken"],[25,3,1,"","ColumnMetadata"],[25,3,1,"","EdgeMetadata"],[25,3,1,"","Function"],[25,3,1,"","IndexMetadata"],[25,3,1,"","KeyspaceMetadata"],[25,3,1,"","LocalStrategy"],[25,3,1,"","MD5Token"],[25,3,1,"","MaterializedViewMetadata"],[25,3,1,"","Metadata"],[25,3,1,"","Murmur3Token"],[25,3,1,"","NetworkTopologyStrategy"],[25,3,1,"","ReplicationFactor"],[25,2,1,"","ReplicationStrategy"],[25,3,1,"","SimpleStrategy"],[25,3,1,"","TableMetadata"],[25,3,1,"","TableMetadataDSE68"],[25,3,1,"","TableMetadataV3"],[25,3,1,"","Token"],[25,3,1,"","TokenMap"],[25,3,1,"","UserType"],[25,3,1,"","VertexMetadata"],[25,6,1,"","cql_keywords"],[25,6,1,"","cql_keywords_reserved"],[25,6,1,"","cql_keywords_unreserved"],[25,7,1,"","group_keys_by_replica"]],"cassandra.metadata.Aggregate":[[25,4,1,"","as_cql_query"]],"cassandra.metadata.BytesToken":[[25,4,1,"","from_string"]],"cassandra.metadata.Function":[[25,4,1,"","as_cql_query"]],"cassandra.metadata.IndexMetadata":[[25,4,1,"","as_cql_query"],[25,4,1,"","export_as_string"]],"cassandra.metadata.KeyspaceMetadata":[[25,4,1,"","as_cql_query"],[25,4,1,"","export_as_string"]],"cassandra.metadata.LocalStrategy":[[25,4,1,"","export_for_schema"]],"cassandra.metadata.MaterializedViewMetadata":[[25,4,1,"","as_cql_query"]],"cassandra.metadata.Metadata":[[25,4,1,"","add_or_return_host"],[25,4,1,"","all_hosts"],[25,4,1,"","export_schema_as_string"],[25,4,1,"","get_host"],[25,4,1,"","get_host_by_host_id"],[25,4,1,"","get_replicas"]],"cassandra.metadata.NetworkTopologyStrategy":[[25,4,1,"","export_for_schema"]],"cassandra.metadata.SimpleStrategy":[[25,4,1,"","export_for_schema"],[25,5,1,"","replication_factor"]],"cassandra.metadata.TableMetadata":[[25,4,1,"","as_cql_query"],[25,4,1,"","export_as_string"],[25,5,1,"","is_cql_compatible"],[25,5,1,"","primary_key"]],"cassandra.metadata.TableMetadataDSE68":[[25,4,1,"","as_cql_query"]],"cassandra.metadata.TableMetadataV3":[[25,5,1,"","is_cql_compatible"]],"cassandra.metadata.TokenMap":[[25,4,1,"","get_replicas"]],"cassandra.metadata.UserType":[[25,4,1,"","as_cql_query"]],"cassandra.metrics":[[26,3,1,"","Metrics"]],"cassandra.metrics.Metrics":[[26,2,1,"","connected_to"],[26,2,1,"","connection_errors"],[26,4,1,"","get_stats"],[26,2,1,"","ignores"],[26,2,1,"","known_hosts"],[26,2,1,"","open_connections"],[26,2,1,"","other_errors"],[26,2,1,"","read_timeouts"],[26,2,1,"","request_timer"],[26,2,1,"","retries"],[26,4,1,"","set_stats_name"],[26,2,1,"","unavailables"],[26,2,1,"","write_timeouts"]],"cassandra.policies":[[27,3,1,"","AddressTranslator"],[27,3,1,"","ConstantReconnectionPolicy"],[27,3,1,"","ConstantSpeculativeExecutionPolicy"],[27,3,1,"","ConvictionPolicy"],[27,3,1,"","DCAwareRoundRobinPolicy"],[27,3,1,"","DSELoadBalancingPolicy"],[27,3,1,"","DefaultLoadBalancingPolicy"],[27,3,1,"","DowngradingConsistencyRetryPolicy"],[27,3,1,"","EC2MultiRegionTranslator"],[27,3,1,"","ExponentialReconnectionPolicy"],[27,3,1,"","FallthroughRetryPolicy"],[27,3,1,"","HostDistance"],[27,3,1,"","HostFilterPolicy"],[27,3,1,"","IdentityTranslator"],[27,3,1,"","LoadBalancingPolicy"],[27,3,1,"","ReconnectionPolicy"],[27,3,1,"","RetryPolicy"],[27,3,1,"","RoundRobinPolicy"],[27,3,1,"","SimpleConvictionPolicy"],[27,3,1,"","SpeculativeExecutionPolicy"],[27,3,1,"","TokenAwarePolicy"],[27,3,1,"","WhiteListRoundRobinPolicy"],[27,3,1,"","WriteType"]],"cassandra.policies.AddressTranslator":[[27,4,1,"","translate"]],"cassandra.policies.ConstantReconnectionPolicy":[[27,4,1,"","new_schedule"]],"cassandra.policies.ConstantSpeculativeExecutionPolicy":[[27,4,1,"","new_plan"]],"cassandra.policies.ConvictionPolicy":[[27,4,1,"","add_failure"],[27,4,1,"","reset"]],"cassandra.policies.DCAwareRoundRobinPolicy":[[27,4,1,"","distance"],[27,4,1,"","make_query_plan"],[27,4,1,"","on_add"],[27,4,1,"","on_down"],[27,4,1,"","on_remove"],[27,4,1,"","on_up"],[27,4,1,"","populate"]],"cassandra.policies.DefaultLoadBalancingPolicy":[[27,4,1,"","make_query_plan"],[27,4,1,"","populate"]],"cassandra.policies.DowngradingConsistencyRetryPolicy":[[27,4,1,"","on_read_timeout"],[27,4,1,"","on_unavailable"],[27,4,1,"","on_write_timeout"]],"cassandra.policies.EC2MultiRegionTranslator":[[27,4,1,"","translate"]],"cassandra.policies.ExponentialReconnectionPolicy":[[27,4,1,"","new_schedule"]],"cassandra.policies.FallthroughRetryPolicy":[[27,4,1,"","on_read_timeout"],[27,4,1,"","on_request_error"],[27,4,1,"","on_unavailable"],[27,4,1,"","on_write_timeout"]],"cassandra.policies.HostDistance":[[27,2,1,"","IGNORED"],[27,2,1,"","LOCAL"],[27,2,1,"","REMOTE"]],"cassandra.policies.HostFilterPolicy":[[27,4,1,"","distance"],[27,4,1,"","make_query_plan"],[27,4,1,"","predicate"]],"cassandra.policies.IdentityTranslator":[[27,4,1,"","translate"]],"cassandra.policies.LoadBalancingPolicy":[[27,4,1,"","check_supported"],[27,4,1,"","distance"],[27,4,1,"","make_query_plan"],[27,4,1,"","populate"]],"cassandra.policies.ReconnectionPolicy":[[27,4,1,"","new_schedule"]],"cassandra.policies.RetryPolicy":[[27,2,1,"","IGNORE"],[27,2,1,"","RETHROW"],[27,2,1,"","RETRY"],[27,2,1,"","RETRY_NEXT_HOST"],[27,4,1,"","on_read_timeout"],[27,4,1,"","on_request_error"],[27,4,1,"","on_unavailable"],[27,4,1,"","on_write_timeout"]],"cassandra.policies.RoundRobinPolicy":[[27,4,1,"","distance"],[27,4,1,"","make_query_plan"],[27,4,1,"","on_add"],[27,4,1,"","on_down"],[27,4,1,"","on_remove"],[27,4,1,"","on_up"],[27,4,1,"","populate"]],"cassandra.policies.SimpleConvictionPolicy":[[27,4,1,"","add_failure"],[27,4,1,"","reset"]],"cassandra.policies.SpeculativeExecutionPolicy":[[27,4,1,"","new_plan"]],"cassandra.policies.TokenAwarePolicy":[[27,4,1,"","check_supported"],[27,4,1,"","distance"],[27,4,1,"","make_query_plan"],[27,4,1,"","on_add"],[27,4,1,"","on_down"],[27,4,1,"","on_remove"],[27,4,1,"","on_up"],[27,4,1,"","populate"],[27,2,1,"","shuffle_replicas"]],"cassandra.policies.WhiteListRoundRobinPolicy":[[27,4,1,"","distance"],[27,4,1,"","on_add"],[27,4,1,"","on_up"],[27,4,1,"","populate"]],"cassandra.policies.WriteType":[[27,2,1,"","BATCH"],[27,2,1,"","BATCH_LOG"],[27,2,1,"","CAS"],[27,2,1,"","CDC"],[27,2,1,"","COUNTER"],[27,2,1,"","SIMPLE"],[27,2,1,"","UNLOGGED_BATCH"],[27,2,1,"","VIEW"]],"cassandra.pool":[[28,3,1,"","Host"],[28,1,1,"","NoConnectionsAvailable"]],"cassandra.pool.Host":[[28,5,1,"","address"],[28,5,1,"","datacenter"],[28,5,1,"","rack"]],"cassandra.protocol":[[29,3,1,"","_ProtocolHandler"]],"cassandra.protocol._ProtocolHandler":[[29,4,1,"","decode_message"],[29,4,1,"","encode_message"],[29,2,1,"","message_types_by_opcode"]],"cassandra.query":[[30,3,1,"","BatchStatement"],[30,3,1,"","BatchType"],[30,3,1,"","BoundStatement"],[30,3,1,"","PreparedStatement"],[30,3,1,"","QueryTrace"],[30,3,1,"","SimpleStatement"],[30,3,1,"","Statement"],[30,3,1,"","TraceEvent"],[30,1,1,"","TraceUnavailable"],[30,6,1,"","UNSET_VALUE"],[30,3,1,"","ValueSequence"],[30,7,1,"","dict_factory"],[30,7,1,"","named_tuple_factory"],[30,7,1,"","ordered_dict_factory"],[30,7,1,"","tuple_factory"]],"cassandra.query.BatchStatement":[[30,4,1,"","add"],[30,4,1,"","add_all"],[30,4,1,"","clear"],[30,2,1,"","serial_consistency_level"]],"cassandra.query.BatchType":[[30,2,1,"","COUNTER"],[30,2,1,"","LOGGED"],[30,2,1,"","UNLOGGED"]],"cassandra.query.BoundStatement":[[30,4,1,"","bind"],[30,5,1,"","routing_key"]],"cassandra.query.PreparedStatement":[[30,4,1,"","bind"]],"cassandra.query.QueryTrace":[[30,4,1,"","populate"]],"cassandra.query.Statement":[[30,5,1,"","routing_key"],[30,5,1,"","serial_consistency_level"]],"cassandra.timestamps":[[31,3,1,"","MonotonicTimestampGenerator"]],"cassandra.timestamps.MonotonicTimestampGenerator":[[31,4,1,"","_next_timestamp"],[31,2,1,"","warn_on_drift"],[31,2,1,"","warning_interval"],[31,2,1,"","warning_threshold"]],"cassandra.util":[[32,3,1,"","Date"],[32,3,1,"","DateRange"],[32,3,1,"","DateRangeBound"],[32,3,1,"","DateRangePrecision"],[32,3,1,"","Distance"],[32,3,1,"","Duration"],[32,3,1,"","LineString"],[32,3,1,"","OrderedMap"],[32,3,1,"","OrderedMapSerializedKey"],[32,3,1,"","Point"],[32,3,1,"","Polygon"],[32,3,1,"","SortedSet"],[32,3,1,"","Time"],[32,3,1,"","Version"],[32,7,1,"","datetime_from_timestamp"],[32,7,1,"","datetime_from_uuid1"],[32,7,1,"","max_uuid_from_time"],[32,7,1,"","min_uuid_from_time"],[32,7,1,"","ms_timestamp_from_datetime"],[32,2,1,"","sortedset"],[32,7,1,"","unix_time_from_uuid1"],[32,7,1,"","utc_datetime_from_ms_timestamp"],[32,7,1,"","uuid_from_time"]],"cassandra.util.Date":[[32,4,1,"","date"],[32,5,1,"","seconds"]],"cassandra.util.DateRange":[[32,2,1,"","lower_bound"],[32,2,1,"","upper_bound"],[32,2,1,"","value"]],"cassandra.util.DateRangeBound":[[32,4,1,"","datetime"],[32,4,1,"","from_value"],[32,2,1,"","milliseconds"],[32,2,1,"","precision"]],"cassandra.util.Distance":[[32,4,1,"","from_wkt"]],"cassandra.util.LineString":[[32,4,1,"","from_wkt"]],"cassandra.util.Point":[[32,4,1,"","from_wkt"]],"cassandra.util.Polygon":[[32,4,1,"","from_wkt"]],"cassandra.util.Time":[[32,5,1,"","hour"],[32,5,1,"","minute"],[32,5,1,"","nanosecond"],[32,5,1,"","second"],[32,4,1,"","time"]],"cqlengine.queryset":[[38,3,1,"","MaxTimeUUID"],[38,3,1,"","MinTimeUUID"]],cassandra:[[1,1,1,"","AlreadyExists"],[1,1,1,"","AuthenticationFailed"],[1,1,1,"","ConfigurationException"],[1,3,1,"","ConsistencyLevel"],[1,1,1,"","CoordinationFailure"],[1,1,1,"","DriverException"],[1,1,1,"","FunctionFailure"],[1,1,1,"","InvalidRequest"],[1,1,1,"","OperationTimedOut"],[1,3,1,"","ProtocolVersion"],[1,1,1,"","ReadFailure"],[1,1,1,"","ReadTimeout"],[1,1,1,"","RequestExecutionException"],[1,1,1,"","RequestValidationException"],[1,1,1,"","Timeout"],[1,1,1,"","Unauthorized"],[1,1,1,"","Unavailable"],[1,3,1,"","UserAggregateDescriptor"],[1,3,1,"","UserFunctionDescriptor"],[1,1,1,"","WriteFailure"],[1,1,1,"","WriteTimeout"],[1,6,1,"","__version__"],[1,6,1,"","__version_info__"],[2,0,0,"-","auth"],[3,0,0,"-","cluster"],[4,0,0,"-","concurrent"],[5,0,0,"-","connection"],[16,0,0,"-","decoder"],[17,0,0,"-","encoder"],[18,0,0,"-","graph"],[25,0,0,"-","metadata"],[26,0,0,"-","metrics"],[27,0,0,"-","policies"],[28,0,0,"-","pool"],[29,0,0,"-","protocol"],[30,0,0,"-","query"],[31,0,0,"-","timestamps"],[32,0,0,"-","util"]],cqlengine:[[37,0,0,"-","models"],[38,0,0,"-","queryset"]]},objnames:{"0":["py","module","Python module"],"1":["py","exception","Python exception"],"2":["py","attribute","Python attribute"],"3":["py","class","Python class"],"4":["py","method","Python method"],"5":["py","property","Python property"],"6":["py","data","Python data"],"7":["py","function","Python function"]},objtypes:{"0":"py:module","1":"py:exception","2":"py:attribute","3":"py:class","4":"py:method","5":"py:property","6":"py:data","7":"py:function"},terms:{"0":[1,2,3,4,6,9,10,12,14,15,16,18,25,27,30,31,32,34,35,37,38,42,43,44,46,47,48,50,55],"00":43,"000":10,"000077":43,"000153":43,"000309":43,"000368":43,"000422":43,"000480":43,"000669":43,"000755":43,"031ebb0":54,"04":0,"05":38,"0l":38,"0m":0,"1":[1,2,3,4,6,10,13,15,18,19,25,27,30,31,32,34,35,36,38,42,43,44,46,47,48,52,53,55],"10":[1,3,10,38,44,46,50],"100":[0,4,10,42,50],"1000":[0,4],"1004":0,"1005":0,"1006":0,"1007":0,"1008":0,"1009":0,"101":0,"1012":0,"1013":0,"1015":0,"1016":0,"1017":0,"1018":0,"1019":0,"1020":0,"1021":0,"1023":0,"1024":0,"1026":0,"1027":0,"103":0,"1031":0,"1033":0,"1036":0,"1039":0,"104":0,"1042":0,"1044":0,"1045":0,"1047":0,"1048":0,"105":0,"1051":0,"1054":0,"1056":0,"1057":0,"106":0,"1060":0,"1064":0,"1065":0,"1067":0,"1068":0,"1074":0,"10786":30,"1079":0,"108":0,"1081":0,"1082":0,"1087":0,"1089":0,"109":0,"1090":0,"1091":0,"1093":0,"10l":38,"110":0,"1100":0,"1104":0,"1105":0,"111":[0,36],"111111111111":9,"1117":0,"1118":0,"1119":0,"112":0,"1121":0,"1122":0,"1123":0,"1124":0,"1127":0,"1129":0,"1130":0,"1140":0,"1158":0,"116":0,"1161":0,"1162":0,"1163":0,"1166":0,"1172":0,"1174":0,"1177":0,"1181":0,"1183":0,"1185":0,"1186":0,"1187":0,"1189":0,"119":[0,32],"1192":0,"11e3":44,"11l":38,"120":0,"1203":0,"1204":0,"1205":0,"1207":0,"1212":0,"122":0,"1228":0,"123":[0,3,36,55],"1233":0,"1234":53,"1237":0,"1238":0,"1239":0,"124":0,"1240":0,"1241":0,"1243":0,"1244":0,"1245":0,"1248":0,"125":0,"126":0,"127":[3,25,35,38,42,43,44,48,53],"12l":38,"135":0,"138":0,"13l":38,"14":32,"141":0,"143":0,"144":0,"145":27,"147":0,"148":0,"14l":38,"15":[27,44],"150":0,"151":0,"155":0,"157":0,"159":0,"15l":38,"16":6,"160":0,"163":0,"164":0,"165":0,"166":0,"167":0,"168":[3,44],"16l":38,"17":[38,53],"173":0,"174":0,"175":0,"178":[0,30,54],"179":0,"17l":38,"180":0,"181":0,"182":0,"184":0,"185":0,"186":0,"187":0,"189":0,"18l":38,"190":0,"191":0,"192":[0,3,44],"194":0,"195":0,"196":0,"197":0,"1970":32,"198":0,"1982":38,"19l":38,"1e6":31,"1l":38,"1s":0,"2":[1,2,3,4,6,9,10,12,13,14,15,16,18,25,27,30,32,34,35,36,38,40,42,43,44,45,46,47,50,52,53,55],"20":38,"200":0,"2008":10,"2010":[35,38],"2011":38,"2012":38,"2013":[0,45],"2014":[0,38],"2015":0,"2016":[0,45],"2017":[0,45],"2018":0,"2019":0,"202":0,"2020":0,"204":0,"2048":53,"205":0,"206":0,"207":0,"208":0,"21":[38,54],"210":0,"211":0,"212":0,"213":0,"215":0,"218":0,"219":0,"22":46,"220":0,"222":0,"226":0,"229":0,"23":32,"230":0,"231":0,"234":0,"235":0,"238":0,"239":0,"24":3,"240":0,"241":0,"243":0,"244":0,"245":[0,40],"246":0,"249":0,"25":0,"255":0,"258":0,"26":[0,38],"260":0,"2644bada":44,"266":0,"27":0,"272":0,"273":0,"276":[0,54],"277":0,"278":0,"279":43,"28":0,"280":0,"282":0,"283":0,"284":0,"285":0,"286":0,"288":0,"289":0,"29":0,"291":0,"292":[0,54],"294":0,"295":0,"296":0,"297":0,"298":0,"299":0,"2l":38,"3":[1,2,3,4,6,9,10,15,18,19,25,27,30,31,32,34,36,37,38,45,46,48,52,55],"30":[0,3,38,42,44],"300":0,"301":0,"302":0,"303":0,"305":0,"306":0,"309":0,"31":[0,38],"310":0,"311":0,"313":0,"315":0,"317":0,"318":[0,54],"319":0,"32":6,"322":0,"323":0,"324":0,"325":0,"327":0,"329":0,"331":0,"332":0,"333":0,"334":0,"335":0,"336":0,"337":0,"338":0,"340":32,"341":0,"342":0,"343":0,"344":0,"345":0,"346":0,"347":0,"348":0,"349":0,"351":0,"352":0,"353":0,"354":0,"357":0,"358":0,"360":0,"3600":3,"361":0,"362":0,"363":0,"365":0,"368":[0,54],"370":0,"371":0,"375":0,"377":0,"378":0,"379":0,"381":0,"385":[0,54],"386":0,"392":0,"393":0,"394":0,"395":0,"396":0,"397":0,"398":0,"3l":38,"4":[1,2,3,6,9,10,19,27,29,30,32,42,45,46,48],"400":[0,54],"405":0,"407":0,"408":[0,54],"409":0,"412":0,"413":0,"415":0,"416":0,"419fcdf":54,"42":[3,30,44],"422":[0,54],"429":0,"430":0,"432":0,"433":0,"434":0,"435":0,"438":0,"439":0,"442":0,"443":0,"444":0,"445":0,"447":0,"450":0,"451":0,"452":0,"454":0,"458":0,"459":0,"46":0,"464":0,"466":0,"467":0,"468":0,"469":0,"470":0,"471":0,"473":0,"475":0,"476":0,"477":0,"478":0,"479":0,"48":32,"480":0,"481":0,"482":0,"486":0,"487":0,"489":0,"495":0,"498":0,"4bd5909":54,"4l":38,"4th":0,"5":[1,3,9,10,19,27,38,44,45,46,53],"50":4,"500":10,"5000":[3,10,50],"501":0,"502":0,"503":0,"505":0,"507":0,"508":0,"509":0,"50m":38,"510":0,"512":0,"514":0,"520":0,"521":0,"522":0,"527":0,"528":0,"530":0,"531":0,"532":0,"533":0,"535":0,"537":0,"538":0,"542":0,"547":0,"548":0,"549":0,"550":0,"551":0,"553":0,"555":0,"556":0,"557":0,"559":0,"56":0,"560":0,"561":0,"562":0,"565":0,"566":0,"568":0,"569":0,"570":0,"572":0,"5723":0,"573":0,"574":0,"574266d":54,"576":0,"577":0,"578":0,"579":0,"580":0,"583":0,"584":0,"585":0,"589":0,"59":[0,32],"591":0,"593":0,"595":0,"596":0,"598":0,"599":0,"5l":38,"6":[1,3,6,10,19,25,27,30,38,45,46],"60":0,"600":0,"606":0,"607":0,"608":0,"609":0,"613":0,"614":0,"616":0,"617":0,"618":0,"619":0,"621":0,"622":0,"623":0,"626":0,"628":0,"630":0,"631":0,"636":0,"64":[6,9,27],"640":0,"642":0,"643":0,"644":0,"645":0,"646":0,"647":0,"648":0,"649":0,"65":1,"650":0,"653":0,"655":0,"656":0,"657":0,"66":[1,3],"665":0,"668":0,"669":0,"673":0,"676":0,"678":0,"682":0,"684":0,"686":0,"688":0,"69":0,"690":0,"692":0,"694":0,"697":0,"6l":38,"7":[1,3,6,10,27,45,46],"70":0,"700":0,"705":0,"706":0,"707":0,"708":0,"709":0,"71":0,"710":0,"714":0,"717":0,"719":0,"720":0,"721":0,"723":0,"724":0,"727":0,"728":0,"729":0,"73":0,"730":0,"732":0,"733":0,"734":0,"735":0,"736":0,"737":0,"739":0,"740":0,"741":0,"742":0,"743":0,"746":0,"747":0,"749":0,"75":0,"750":0,"751":0,"752":0,"754":0,"755":0,"759":0,"75percentil":26,"75th":26,"76":0,"761":0,"762":0,"763":0,"767":0,"768":0,"769":0,"77142":43,"772":0,"773":0,"774":0,"774000":38,"775":0,"778":0,"781":0,"782":0,"785":0,"7857":0,"78723":[3,55],"788":0,"789":0,"79":0,"793":0,"794":0,"798":0,"799":0,"79efe97":54,"7l":38,"8":[1,3,6,17,31,45,46,48],"80":0,"804dea3":0,"805":0,"808":0,"81":0,"810":0,"812":0,"813":0,"814":0,"819":0,"82":0,"827":0,"829":0,"831":0,"833":0,"836":0,"837":0,"838":0,"839":0,"84":0,"840":0,"843":0,"846":0,"848":0,"852c":44,"853":0,"86":0,"860":0,"861":0,"862":0,"863":0,"86400":9,"865":0,"868":0,"872":0,"8733":40,"877":0,"88":0,"885":0,"888":0,"89":0,"891":0,"892":0,"893":0,"894":0,"895":0,"897":0,"89fb":44,"8l":38,"9":[1,9,38],"90":0,"900":0,"901":0,"903":0,"9042":[3,5],"91":0,"910":0,"915":0,"916":0,"92":0,"9223372036854775808":43,"93":0,"932":0,"934":0,"937":0,"940":0,"941":0,"944":0,"945":0,"946":0,"947":0,"95":0,"953":0,"955":0,"95percentil":26,"95th":26,"96":0,"963":0,"96489cc":54,"966":0,"968":0,"97":0,"973":0,"978":0,"98":0,"98percentil":26,"98th":26,"99":[0,26],"992":0,"993":0,"995":0,"996":0,"998":0,"99999":37,"999percentil":26,"99percentil":26,"99th":26,"9d98c8e":54,"9l":38,"9th":26,"abstract":[0,2,6,9,25,30],"boolean":[0,1,6,25,27,44,47],"break":[0,27,45,46,54],"byte":[0,6,38],"case":[0,3,4,8,9,27,32,34,35,44,49,53],"catch":0,"char":0,"class":[0,1,2,3,5,6,9,10,12,13,14,15,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,40,41,48,50,52,53,54],"default":[0,1,3,6,7,9,10,11,12,14,15,17,18,26,27,29,30,31,34,43,44,46,48,49,50,53],"do":[0,3,4,6,9,17,27,30,37,38,41,44,46,53,54,55],"enum":[10,13,27,32,33],"export":[0,25],"final":[3,44,53],"float":[0,3,6,10,15,18,26,27,37,38,44,54],"function":[0,1,3,8,10,12,17,25,27,29,32,41,44,53,54],"import":[0,2,3,4,6,10,11,12,29,30,34,35,37,38,39,41,42,43,44,46,48,50,52,53],"int":[0,3,6,7,8,15,18,25,31,32,38,44,47,54,55],"long":[0,32,44,46,55],"new":[0,1,2,3,4,6,7,10,21,25,27,30,31,32,34,36,38,39,40,42,44,48,50,53,54,55],"null":[0,10,17,36,38,44],"public":27,"return":[0,1,2,3,4,9,10,12,14,15,18,25,26,27,29,30,31,32,33,37,38,39,41,43,44,47,48,50,53,55],"short":[0,30,37],"static":[0,3,6,10,12,13,32],"super":37,"switch":[0,10,46],"throw":[0,3,30],"transient":0,"true":[0,3,4,6,7,8,9,10,15,18,25,27,30,31,34,35,36,37,38,40,43,44,47,48,52,53],"try":[0,1,3,8,9,27,37,39,41,44],"while":[0,3,27,30,37,40,50,54],A:[0,1,2,3,4,7,8,10,12,13,14,17,18,25,26,27,30,32,35,37,38,44,45,46],AND:[47,52],And:[9,53,54],As:[9,32,40,44,52,55],BY:37,Be:49,But:30,By:[1,3,9,10,27,29,34,38,43,44,46,50,53,54],For:[0,1,3,6,7,9,10,25,27,30,32,36,37,38,40,41,42,44,46,47,48,49,50,51,52,53,54],IF:[0,10,27,30,47,52,54],IN:[17,25,30],INTO:[3,4,30,44,47,55],IS:[0,38,40],If:[0,2,3,4,7,8,9,10,11,14,25,27,30,31,32,34,35,36,37,41,42,44,46,47,50,53,54],In:[0,3,27,29,34,38,40,44,46,52,53,54],It:[0,3,9,21,22,27,32,35,37,38,43,44,46,47,53],NOT:[0,38,47,52],No:45,Not:[0,32],ONE:[1,3,10,40,54],Of:3,On:[0,27,46],One:[10,41],Or:3,Such:27,THERE:40,That:38,The:[0,1,2,3,4,5,6,7,9,10,12,13,14,15,17,18,25,26,27,28,29,30,32,34,36,37,38,40,41,42,44,45,46,47,49,53,54,55],Then:53,There:[1,3,6,8,30,38,44,46,54],These:[0,3,6,9,27,29,30,32,40,41,49,53,54],To:[3,9,11,27,34,35,37,38,40,41,42,43,44,46,51,53,54],WITH:[37,52],Will:9,With:[0,35,43,53,54],_1:53,_2:53,_3:53,_4:53,_:42,__:[10,38,54],__abstract__:9,__compute_routing_key__:9,__connection__:[8,9,35],__contain:38,__default_ttl__:9,__del__:0,__discrimin:54,__discriminator_value__:[6,9,37,40],__ge__:0,__gt:38,__gte:38,__in:[0,38],__init__:[0,3,27,31,50,54,55],__keyspace__:[8,9,35,37],__le__:0,__len__:0,__like:38,__lt:38,__lte:38,__name__:43,__ne__:0,__options__:[9,38],__polymorphic_:54,__polymorphic_key__:40,__repr__:0,__table_name__:[9,37,40],__table_name_case_sensitive__:9,__type_name__:11,__version__:[1,46],__version_info__:1,_connect:0,_dsegraphson2rowfactori:12,_gremlingraphson2rowfactori:12,_messagetyp:29,_metadata:54,_new_tim:21,_next_timestamp:31,_not_set:3,_protocolhand:29,_protocolhandl:29,_replicationstrategi:25,_set_final_except:0,_set_result:0,_timeout_watch:21,a2:10,a2d3a98:54,abil:[0,27,42,54],abl:46,about:[0,3,25,30,37,41,44,46,53,54],abov:[3,29,34,35,41,44,49],absolut:[32,40],accept:[0,3,27,32,40,41],access:[0,3,9,26,30,37,44,54],accommod:[0,41],accomplish:[38,46],accord:[0,3],accordingli:0,account:[0,37],accumul:10,accur:25,acheiv:27,achiev:[27,34,53],acknowledg:27,across:[0,19,20,21,22,27,42,43,49],act:53,activ:[0,3,21,22],actual:[0,1,27,30,38,44,47],ad:[0,1,3,10,21,25,27,30,34,37,38,46,54],add:[0,3,7,8,10,14,27,30,34,54,55],add_al:[14,30],add_callback:[3,10,34,44,49,50],add_collback:0,add_errback:[3,44],add_execution_profil:[3,12,42],add_failur:27,add_or_return_host:25,add_queri:10,add_request_init_listen:3,add_tim:0,addit:[0,3,10,12,29,34,37,38,44,47,48,53,54],addition:[30,37,40,53],additional_write_polici:0,addr:[27,37],address:[0,1,3,5,11,25,28,30,33,37,43,44,53,54,55],address_is_ignor:27,address_transl:3,addresstransl:[0,27],adher:41,adjust:[0,40],advanc:53,advic:3,affect:[3,30,34],after:[0,3,4,10,20,27,30,34,37,38,40,43,44,46,49],afterward:54,ag:[3,30,38,44],against:[0,1,3,9,27,30,37,44,48,53],aggreg:[0,1,3,25],agnost:32,agre:0,agreement:[0,3],ahead:[3,44],aim:[35,42],algorithm:[36,46],alia:[6,12,25,32,40],alias:0,alic:30,align:0,aliv:[1,26,27],alive_replica:[1,27],all:[0,1,3,4,6,8,9,10,17,21,22,25,26,27,28,29,30,35,41,44,46,47,49,52,53,54],all_host:[25,42],all_object:38,all_replica:25,allow:[0,3,6,9,10,12,13,27,29,30,31,32,34,36,37,46,52,53,54,55],allow_beta_protocol_vers:29,allow_filt:[10,38],almost:44,along:[3,25,50],alpha:0,alphanumer:0,alreadi:[0,1,3,5,8,35,46],alreadyexist:1,also:[0,3,4,9,10,13,27,30,32,35,37,38,42,43,44,46,53,54],alter:[9,27,37],altern:[3,29,37,40,44,46,49,53],although:[44,54,55],althought:44,alwai:[0,3,15,18,27,41,44,46,47],ambigu:0,among:[1,27],amount:[0,4,27],an:[0,1,2,3,4,5,6,8,9,10,12,13,15,17,18,19,20,21,22,23,24,25,26,27,29,30,31,32,34,35,36,37,38,40,41,42,44,45,46,48,49,50,52,53,54,55],analysi:29,analyt:[0,3,15,18],analyticskeyspac:3,analyticskeyspace_prepar:3,andrew:[46,53],ani:[0,1,3,8,9,10,13,14,17,19,20,21,22,26,27,30,34,37,38,41,43,44,45,46,47,49,53,55],anomali:0,anoth:[27,34,35,38,44,53,54],anymor:[38,54],anyth:[34,41],anywai:46,apach:[38,46,54],api:[0,32,37,41,42,45,46,48,49,53],app:[39,43],appear:47,append:[4,10,25,38,44],appli:[0,3,9,10,14,30,36,41,42,44,46,47,48,55],applic:[0,3,6,27,39,40,41,44,46,49,50,54],approach:[41,45],appropri:[3,37,46,53],april:0,apt:46,ar:[0,1,3,4,6,7,8,9,10,15,18,21,25,26,27,28,29,30,32,34,36,37,40,41,42,43,44,45,46,47,48,50,53],arbitrari:[6,32],archflag:46,architectur:46,arg:[3,4,6,9,10,19,20,21,22,23,27,32,34],arg_typ:1,argument:[0,1,3,4,7,9,10,15,18,27,30,31,32,34,35,44,46,53,54],argument_typ:1,arm:0,around:[0,9,32,40,41,54],arrai:[29,38],arriv:3,as_cql_queri:[0,25],as_edg:[15,18],as_graph_stat:14,as_path:[15,18],as_vertex:[15,18],ascend:[10,38],ascii:[0,6,44],ask:[45,48],assert:[6,36,52],assertionerror:38,assign:[0,6,11,37],associ:[0,3,54],assum:[3,21,22,38,41,53,54],assumpt:41,astimezon:41,astra:0,async:3,asynchron:[0,3,30,43,49],asyncio:[0,33],asyncioconnect:19,asyncioreactor:33,asyncor:[0,33,46],asyncoreconnect:[0,20],asyncorereactor:[0,33],atexit:0,atlassian:27,atom:[27,30],attach:[0,3,15,18,34,44,49,50],attempt:[0,1,3,4,5,27,34,41,43,44,54],attr_kwarg:3,attribut:[0,3,6,8,9,10,11,15,18,25,27,29,30,31,37,38,40,42,44,47,54,55],attributeerror:0,aug:0,august:0,auth:[0,33,53,54],auth_provid:[2,3,53],authent:[0,1,3,33],authenticationfail:[1,2],author:[1,53],authorization_id:53,authprovid:[0,2,3,53],auto:35,automat:[0,1,3,35,37,38,44,46,50],automobil:[10,35,38],automobile2:10,avail:[0,3,10,30,38,45,46,52,54],avoid:[0,3,27,40,43,46],aw:27,awai:[3,30],awar:[0,3,26,27,41,46,53,54],ayncoreconnect:0,b:[3,4,12,14,15,18,34,35,36,38],back:[0,6,9,32,38],backoff:0,backpressur:0,backup:38,backward:[3,18,25,54],bad:0,badli:0,balanc:[0,3,33,42,54],bar:44,bark_all_night:37,base:[0,1,3,9,12,26,27,29,30,32,37,40,43,44,47,52,53],base_delai:27,basegraphrowfactori:12,basi:[0,54],basic:[0,3,12,37],batch:[0,1,3,9,10,12,14,25,27,33,35,38,48],batch_log:27,batch_obj:10,batch_object:9,batch_r:10,batch_typ:[10,30,34],batchqueri:[0,10,34,36,38],batchstat:[0,1,3,30,54],batchtyp:[0,10,30,34],bb984ee:54,beat_init:39,becam:[0,40],becaus:[0,3,4,15,18,27,30,32,40,41,44,46,52,54],becom:[0,3,8,49,54],been:[0,3,5,9,26,27,30,34,35,40,54],befor:[0,1,3,9,10,27,29,30,40,43,44,49,50,54],begin:[0,10,13,44],behav:32,behavior:[0,3,6,27,44,54],behind:[27,41],being:[0,3,6,26,30,36,42,44,46,47],below:[3,4,10,27,29,36,37,38,40,46,47,49,54],benchmark:[0,49],benefit:54,best:[27,44,51,53],beta5:1,beta:[1,46],beta_vers:1,better:[0,27,46,49],between:[0,2,6,29,30,46,52],bewar:27,beyond:37,big:0,bigint:[6,15,18,44],binari:[0,6,30],binary_typ:29,bind:[0,3,12,30,43,44],bit:[6,32,46],bitmap:29,blacklist:27,blacklist_filter_polici:27,blah:44,blake:[9,38],blank:9,blind:[9,10],blindli:10,blist:0,blob:[0,6,17,44,52],block:[0,3,4,34,44,49],blog:49,bob:[3,30,44],bodi:[0,29],bool:[6,7,8,10,25,44,52],bootstrap:[0,26],bop:0,borrow_connect:0,both:[0,3,38,39,44,46,53],bound:[3,14,30,32,43,49],bound_stmt:3,boundstat:[0,30,44,54],bracket:47,brew:46,broadcast_address:27,broadcast_rpc_address:25,broadcast_rpc_port:25,broken:0,brought:54,brows:27,brute:27,bu:0,bucket_high:9,bucket_low:9,buffer:[0,17,44],bug:[40,45,54],build:[0,25,40,44,46,49],built:[0,32,42,46,49,54],bulk:12,bulkset:0,bump:0,busi:[3,28],bypass:[0,3,8,30],bytearrai:[0,17,44],bytebuff:0,bytecod:12,byteorderedpartition:[0,25],bytesio:0,bytestoken:25,c0:52,c:[0,6,12,25,27,38,53],ca:[0,27,53],ca_cert:53,cach:0,cacreateseri:53,cakei:53,calcul:0,call:[0,2,3,5,9,10,17,19,20,21,22,27,31,34,37,38,41,44,48,50,53],callabl:[6,10,12],callback:[0,3,10,44,49,53],callback_arg:3,callback_kwarg:3,camera:38,can:[0,1,3,4,6,8,9,10,13,14,15,17,18,21,25,27,29,30,31,32,34,35,37,38,39,41,42,43,44,45,46,48,49,50,52,53,54,55],cancel:0,cannon:40,cannot:[0,27,30,32,38,42],capabl:50,captur:[0,46],car:38,cardin:[15,18],care:[3,8],carri:34,cass_driver_build_concurr:46,cass_driver_no_cython:46,cass_driver_no_extens:46,cass_server_vers:0,cass_typ:32,cassandra:[0,33,34,35,36,37,38,39,40,42,43,46,48,49,50,52,53,55],cassandra_init:39,cassandra_vers:0,cast:44,cat:[37,40,53],caus:[0,3,10,26,37,47],caution:[8,37],caveat:27,cc94073:54,cdc:[0,27],cdef:0,ceas:27,ceil:1,celeri:48,cell:43,center:30,cento:[0,46],central:41,cert:53,cert_countri:53,cert_org_nam:53,cert_ou:53,cert_req:53,cert_requir:53,cert_valid:53,certain:[13,27,40,46],certfil:53,certif:[0,53],chain:34,challeng:[2,46],chanc:27,chang:[0,3,6,9,10,25,27,30,31,36,37,38,43,44,45],changelog:45,charact:[0,6,44],charl:30,check:[0,3,9,10,27,37,46,52,54],check_hostnam:[0,53],check_support:27,checkout:46,child:[0,27,43],child_polici:27,choic:[46,49],choos:[15,18,27,54],chosen:3,chunk:0,circuit:0,circumst:0,citi:54,civic:[10,35,38],cl:[0,10,21],clang:46,classic:0,classmethod:[1,9,15,18,19,20,21,22,25,29,32],claus:[0,10,25,37,47,54],clean:[0,39,46,54],cleanup:[0,20],clear:[0,14,27,30],clearer:41,client:[0,1,2,3,8,27,29,41,42,45],client_encryption_opt:53,client_protocol_handl:[3,29],clock:32,clock_seq:32,clone:[3,42],close:[0,3,5],closur:0,cloud:[0,3,27,45],cluster1:35,cluster2:[10,35],cluster3:35,cluster:[0,2,4,5,6,7,9,10,12,15,18,19,20,21,22,25,26,27,29,30,33,35,37,38,39,43,44,46,48,49,51,53,55],cluster_opt:7,clustering_kei:38,clustering_ord:[6,37],clustertest:0,cn:53,code:[0,1,34,39,45,53,54,55],codebas:0,coerc:6,coincid:0,col:[0,47],col_nam:9,collect:[0,3,8,10,15,25,26,30,32,38,45,54],collis:0,colnam:[3,10,30],column:[0,8,9,10,11,13,17,25,30,33,35,36,37,38,44,47,48,54,55],column_family_nam:9,column_nam:[10,15,18,38],columnmetadata:[25,54],com:[6,10,52,53],combin:[0,3],come:0,comma:44,command:[0,35,46],comment:[9,10,37],comment_id:[10,37],common:[0,40,46,53,54],commun:[0,5,46],compact:[0,9,52],compar:[0,30,32,45],comparison:[0,6],compat:[0,3,18,25,33,54],compil:[0,29,46,49],complain:37,complet:[0,1,2,3,4,11,27,30,34,37,40,43,44,49,53],complex:[0,42,46],compliant:0,compon:[0,10,25,30,32,53],compos:29,composit:[0,30,38],compositetyp:0,compound:6,compress:[0,3,29],compressor:29,compris:[1,29],comput:[0,3,9,43],concern:41,concis:15,concurr:[0,3,8,30,33,43,44,49],condit:[0,1,3,8,10,30,45],conf:53,config:[0,53],configur:[0,1,2,3,5,7,9,15,18,27,31,42,44,45],configurationexcept:1,confirm:0,conflict:36,confus:[40,54],conn:35,connect:[0,1,2,3,4,8,9,10,11,12,19,20,22,23,24,26,27,30,33,37,38,39,40,42,45,46,48,51,52,53,54,55],connect_timeout:[0,3],connect_to_remote_host:3,connected_to:26,connection_class:[3,46,53],connection_error:26,connection_exc:27,connectionbusi:5,connectionexcept:[0,5],connectionshutdown:5,consensu:1,consid:[0,1,3,18,27,44,47,49,53,54],consider:[37,49],consist:[0,1,3,7,10,27,30,32],consistency_level:[3,15,18,30,42,44],consistencylevel:[0,1,3,7,10,15,18,26,27,30,40,44],consit:0,constant:[0,53],constantreconnectionpolici:[0,27],constantspeculativeexecutionpolici:[0,27,44],constrain:[4,10],constraint:[9,37],construct:[0,9,12,32,41,42,44],constructor:[0,3,6,38],consult:37,consum:[0,4,54],consumpt:[0,49],contact:[0,3,27,44],contact_point:[0,3,7,27,53],contain:[0,3,6,9,10,13,17,27,32,37,38,41,47,50,52],contains_kei:13,contains_valu:13,contend:0,content:[0,10,29],context:[0,3,8,9,10,12,15,18,34,39,46,49,53],contextqueri:[0,10,35],contin:0,continu:[0,2,27,50],continuous_paging_opt:3,contract:[0,29],control:[0,3,4,27,30,40,49,53],control_connection_timeout:3,conveni:[3,15,18,30,38],convent:37,convers:[15,18,40,41,54],convert:[0,13,15,17,18,32,40,41,54],convict:27,conviction_policy_factori:3,convictionpolici:27,coord:32,coordin:[1,3,4,27,32,43],coordinationfailur:1,copi:42,copyright:0,core:[0,3,4,38,40,46,49],core_connect:3,correct:[0,9,41],correctli:[0,3],correspond:[2,4,6,8,37],cost:[0,9,10,38],costli:46,could:[0,10,54],count:[0,9,10,26,27,36,38,48],counter:[0,6,26,27,30,37,44],countri:45,cours:3,cover:[37,43],coverag:0,cpu:[0,4,44,49],cpython:[0,3,46],cql3:[36,38,45],cql:[0,1,6,9,10,11,13,15,17,18,25,30,32,36,37,38,40,41,47,48,52,54,55],cql_cluster:39,cql_encode_all_typ:17,cql_encode_byt:17,cql_encode_d:17,cql_encode_datetim:17,cql_encode_list_collect:17,cql_encode_map_collect:17,cql_encode_non:17,cql_encode_object:17,cql_encode_sequ:17,cql_encode_set_collect:17,cql_encode_str:17,cql_encode_tupl:[17,54],cql_encode_unicod:17,cql_keyword:25,cql_keywords_reserv:25,cql_keywords_unreserv:25,cql_refer:10,cql_session:39,cql_use:6,cql_version:[0,3],cqlcollect:13,cqle:0,cqlengin:[0,33,34,35,36,37,38,39,43,45,48,54],cqlengine_batch:34,cqlengine_test:38,cqlengineexcept:[0,40],cqltype:54,cqluseudt:6,crash:0,creat:[0,1,2,3,5,6,7,8,9,10,12,25,27,30,32,34,35,36,37,38,41,43,44,47,48,49,52,53,54,55],create_default_context:53,create_execution_profil:12,create_keyspac:40,create_keyspace_network_topolog:[8,40],create_keyspace_simpl:[8,40],create_simple_keyspac:35,created_at:[34,48],creation:[0,3,4,25,38],credenti:[0,3,53],credit:44,crt:53,crt_sign:53,crypto:53,csr:53,cstringio:0,cumbersom:41,current:[0,1,3,10,12,26,27,30,31,38,42,43,46,50,54],current_pag:3,current_row:3,custom:[0,1,3,6,10,17,27,30,33,41,42,44,46],custom_index:6,custom_payload:[3,15,18,29,30],cut:0,cute:37,cycl:3,cython:[0,29],cython_protocol_handl:3,cythonprotocolhandl:3,d:[3,6,10,30,41,44],daemon:0,dai:[6,27,32,53],dash:0,data:[0,1,3,9,10,27,30,33,37,38,41,43,44,52,54,55],data_retriev:[1,27],databas:[6,8,9,34,37,38,41,42],datacent:[0,1,27,28],dataset:[0,10,38],datastax:[0,6,10,18,27,44,45,46,48,53,54],datastream:38,datatyp:0,date:[0,6,17,32,44,45,54],daterang:[0,32],daterangebound:32,daterangeprecis:32,datetim:[0,6,10,17,32,34,36,38,40,41,44,48],datetime_from_timestamp:32,datetime_from_uuid1:32,datetyp:0,david:13,daylight:41,days_from_epoch:32,db:0,db_field:[0,6],dc:[0,3,27,54],dc_name:8,dc_replication_factor:25,dc_replication_map:8,dcawar:0,dcawareloadbalancingpolici:0,dcawareroundrobinpolici:[0,3,27,42],dclocal_read_repair_ch:0,dct:0,dd:[17,32],ddl:0,dead:33,deadlock:[0,4],deal:[0,41,42,49,54],debian:[0,46],debug:[0,3],decemb:0,decid:27,decim:[0,6,10,38,44],decimaltyp:0,decis:[0,26,41],declar:[11,37],decod:[0,3,29,30,33,54],decode_messag:29,decomiss:0,decommiss:[0,27],decompress:29,decompressor:29,decor:0,decrement:6,deem:41,def:[3,27,34,37,39,43,44,50,53,54,55],defacto:41,default_bit:53,default_consistency_level:[0,3,7,42],default_fetch_s:[3,50],default_keyspac:[0,7],default_retry_polici:[3,27,42,43],default_serial_consistency_level:[0,3,42],default_time_to_l:[0,38],default_timeout:[3,42],defaultloadbalancingpolici:[0,27,54],defer:[0,10,27],defici:41,defin:[0,1,2,3,6,8,9,10,15,18,25,27,30,33,35,38,40,42,44,45,48],definit:[0,3,6,15,29,38,40],defunct:[0,3,5],degre:13,delai:[0,27,44],deldyck:37,delet:[0,8,9,10,27,30,34,38],delete_keyspac:40,deliv:3,deliveri:3,demand:0,demonstr:53,dep:0,depend:[0,2,41,43,47,49],deploy:53,deprec:[3,9,16,27,53],deprecationwarn:[0,54],depth:0,dequ:0,deriv:[32,37,40,42,46,54],derivi:9,desc:37,descend:[10,37,38],describ:[1,27,29,32,38,40,41,53],descript:[0,3,15,18,27,30,34,43,48,53],descriptor:0,deseri:[0,15,18,33,41],deserialize_bigint:[15,18],deserialize_blob:[15,18],deserialize_d:[15,18],deserialize_decim:[15,18],deserialize_doubl:[15,18],deserialize_dur:[15,18],deserialize_float:[15,18],deserialize_int:[15,18],deserialize_linestr:[15,18],deserialize_point:[15,18],deserialize_polygon:[15,18],deserialize_tim:[15,18],deserialize_timestamp:[15,18],deserialize_uuid:[15,18],design:[44,49,52],desir:[3,10,27,34],despit:10,destroi:0,detail:[0,1,3,9,10,30,37,41,42,43,44,49,52,53,54],detect:[0,40],determin:[6,9,27,30,44],determinist:0,dev:46,devel:46,deviat:26,devic:0,dict:[0,1,3,6,7,8,9,12,15,17,18,25,26,29,30,37,44,47,52,53],dict_factori:[0,3,7,16,30,54],dictionari:[0,6],dictlik:32,did:[5,10,27],didn:10,differ:[0,3,10,29,30,32,36,37,38,42,44,53,54],digest:27,dir:0,directli:[3,4,17,29,30,44,46,53],disabl:[0,3,9,10,46],discontinu:0,discourag:3,discov:[0,3,27,44],discoveri:0,discrimin:[6,9,37],discriminator_column:[6,37,40],discuss:[3,6,11,30,37,45,47,49],disentangl:0,disk:6,dispos:3,disproportion:27,distanc:[13,27,32],distant:27,distinct:[0,10,15,18],distinct_field:10,distinguish:0,distinguished_nam:53,distribut:[0,27,38,46],distrimin:37,distriminator_column:37,dll:0,dn:27,doc:[0,1,6,10,37,38,41,52,53],document:[0,6,27,32,41,42,45,46,48,53,54],doe:[0,3,10,17,32,34,38,40,44,46,47,55],doesn:[0,31,54],doesnotexist:[0,10],dog:[37,40],dollar:0,don:[0,10,38,44,49,55],done:[0,3,37,41,43,53,54],dont:0,doubl:[0,6,15,18,32,44,49,54],double_precis:[40,54],down:[0,3,33,46],downgrad:[0,27],downgradingconsistencyretrypolici:[0,27,44],drain:0,drift:31,driven:8,driver:[0,1,3,5,7,10,18,26,27,28,29,30,37,38,40,41,44,46,47,48,49,50,51,52,53,55],driverexcept:1,drop:[0,6,8,29],drop_keyspac:[8,40],drop_tabl:8,drope:0,dsa:0,dse:[0,1,3,6,12,14,15,18,32],dse_graph:54,dse_graph_query_languag:12,dse_graph_query_protocol:12,dse_v1:[0,1],dse_v2:1,dsegraph:12,dsegssapiauthprovid:[0,53],dseloadbalancingpolici:[0,27,54],dseplaintextauthprovid:53,dsesessionremotegraphconnect:12,dsl:12,dt:32,due:[0,1,10,26,34,49],duplic:0,durabl:3,durable_writ:8,durat:[0,30,32],durationtyp:0,dure:[0,1,2,3,5,9,40,46],dynam:[0,3],dynamiccompositetyp:0,e0b9a54a6d93:44,e16a073:54,e:[3,8,9,10,12,15,18,27,30,43,46],each:[1,2,3,4,6,9,27,30,36,37,38,41,44,50,54,55],each_quorum:1,eagain:0,eai:0,earlier:[0,21,37],eas:35,easi:[0,37,38],easier:[38,42,46],easiest:[41,46],easili:[0,10,41],eat:37,ec2:0,ec2multiregiontransl:27,ed:0,edg:[0,15,18,25],edgemetadata:25,effect:[0,3,8,34,53],effici:[0,29],effort:[0,40,53],eggleston:9,either:[2,3,15,18,32,37,38,41,45,46],element:[0,3,10,15,18,25,32,38,44],elementmap:0,els:[4,39,50],em1:[34,48],em2:[34,48],em3:[34,48],em4:48,em5:48,em6:48,em7:48,em8:48,email:44,emit:[3,40,46],empti:[0,2,3,25,47],en:[6,10],enabl:[0,3,10,44,52,53,54],encod:[0,3,6,15,18,29,33,41],encode_messag:29,encount:[0,3,10],encrypt:[0,53],end:[0,10,34],endian:0,endless:0,endors:45,endpoint:[5,25,27,28,53],endpoint_factori:3,endpoint_or_address:25,endpointfactori:[5,53],enforc:[0,37],engag:46,engin:[0,3],enough:[1,30],ensur:[0,3,4,9,27,39,46,53],enterpris:52,entir:[0,3,4,10,14,25],entiti:0,entri:[10,13,17,54],entry_eq:13,environ:[8,27,46],eof:53,ep:[3,44],epoch:[0,31,32,41],eq:0,equal:[0,3,6,30,38],equival:[9,36,41,44],errback:[0,3,44,50],errback_arg:3,errno:0,error:[0,1,3,4,5,6,10,27,44,50],error_code_map:1,errro:1,escap:[0,17],especi:[0,8,42,46],essenti:38,establish:[3,44],etc:[3,10,26,27,38],evaluate_challeng:2,even:[0,3,7,27,30,41,42,44],evenli:27,event:[0,3,4,21,27,30,33,39,43,44,46,50,53],eventlet:[0,33],eventletconnect:[21,53],eventletreactor:33,everi:[0,27,31,38,39,44],everyon:46,evict:0,evolv:42,ewouldblock:0,exact:2,exactli:[0,27,40],examin:32,exampl:[0,2,3,4,6,9,10,11,25,30,32,35,36,38,40,42,43,44,46,47,48,49,50,51,54,55],example1:48,example2:48,example3:48,example4:48,example5:48,example6:48,example7:48,example8:48,example_id:48,example_mapp:0,example_typ:[34,48],examplemodel:[34,48],exc:[3,50],exce:[0,50],exceed:[3,4],except:[0,3,4,5,6,7,9,10,15,18,27,28,29,30,32,33,34,37,38,39,44,50,53],excess:0,exclud:38,exclus:[7,32,45],exec_profile_default:[3,42,44],exec_profile_graph_analytics_default:3,exec_profile_graph_default:[3,12,54],exec_profile_graph_system_default:3,exect:0,execut:[0,1,3,8,9,10,12,14,15,18,25,27,29,30,33,35,37,38,43,45,47,49,50,52,55],execute_a:[3,53,54],execute_async:[0,3,4,29,43,44,49,50],execute_concurr:[0,4,49],execute_concurrent_with_arg:[4,49],execute_graph:[3,15,18],execute_graph_async:3,execute_on_except:[10,34],execution_profil:[3,4,12,14,42,44],execution_profile_clone_upd:[3,42],executionprofil:[0,3,12,42,44],executionresult:4,executor:0,executor_thread:3,exhaust:[0,27],exist:[0,1,3,8,9,10,27,28,42,47,48,52,54],exit:0,expand:0,expect:[0,5,9,43,47,53,54,55],expens:3,experi:4,experiment:[0,19],expir:3,explain:[0,42],explicit:[0,40,41],explicitli:[0,1,3,10,15,18,34,37,54],explod:42,explor:38,exponenti:[0,27],exponentialreconnectionpolici:[0,3,27],export_as_str:[0,25],export_for_schema:[0,25],export_schema_as_str:25,expos:[0,31,54],express:[4,13,32],extablish:3,extend:30,extens:[0,3,27,41,52],exterior:32,extern:41,extra:[0,25,30,46],extra_deserializer_map:[15,18],extract:[15,18],ey:45,f:3,facilit:29,factor:[0,8,25],factori:[3,12,33,47],fail:[0,1,3,4,7,14,15,18,26,33,34,37,44,47],failur:[0,1,7,9,26,33,34],fairli:37,fall:[0,32],fallback:[10,27,54],fallthroughretrypolici:27,fals:[3,4,6,7,8,9,10,15,18,25,27,30,47,48,53,54],falsei:27,falsi:27,famili:[0,5,9],faq:[43,45],fashion:3,faster:[0,33,46],favor:[27,40,54],feather:45,featur:[12,19,33,38,40,45,46,53],feb:0,februari:0,fedora:46,feedback:0,felcei:13,fetch:[0,3,10,30,38,44,50,54],fetch_next_pag:3,fetch_siz:[0,3,10,15,18,30,50,54],few:[3,44,46],field:[0,3,6,8,9,10,11,30,32,37,38,44,55],fieldnam:6,fierc:37,file:[0,40,49,53],fill:[15,18,30],filter:[0,6,9,27,33,35,48],finalis:1,find:[13,25,41,46],fine:55,finished_ev:50,finit:27,first:[0,3,4,6,7,9,27,36,37,38,40,44,45,46,48,50,53,54],first_nam:[9,37],first_pag:38,first_result:54,first_row:55,five:3,fix:[27,46,53,54],flag:[0,3,6,9,29,37,46,52],flake:0,flask:43,flat:38,flexibl:[0,45],flight:[0,5],flow:0,fluent:[0,33,46,54],fly:[0,4,9,10,35],fn:[3,10],focu:27,follow:[0,3,26,27,29,34,35,37,40,41,42,44,46,47,53,54],foo:[44,55],food:37,footprint:[4,38],forc:[0,27,53],force_token_rebuild:3,forev:[21,27,30],fork:[0,20,43,45,49],form:[1,17,32,44],format:[0,1,3,17,25,29,30,33,41,44,53,55],formerli:0,forward:[1,27,40],found:[0,10,25,30,45,49,53,54],foundat:45,four:32,fqdn:[0,53],fraction:32,frame:29,free:44,frequent:[27,44,45,48],from:[1,2,3,4,5,6,8,9,10,11,12,15,18,20,25,27,29,30,32,34,35,37,38,39,40,42,43,44,45,46,47,48,50,52,53,55],from_datetim:54,from_kei:0,from_str:25,from_valu:32,from_wkt:32,frozen:[0,32,55],frozenset:44,full:[0,30,54],full_replica:25,fulli:54,functionfailur:1,functon:38,further:[3,4,27,38,43,49,53],furthermor:27,fuse:46,futur:[0,3,6,7,30,31,40,43,44,46,49,50,54],fuzzi:13,g:[0,3,12,15,18,27,30],garbag:[0,54],gc:0,gc_grace_second:9,gcc:46,gen_client_cert:53,gener:[0,1,2,4,27,29,32,33,41,44,53,54],geo:[0,13],geom:0,geomet:0,geometri:[13,32],geospati:0,geounit:13,get:[0,3,8,9,10,25,27,38,46],get_all_query_trac:[3,54],get_control_connection_host:3,get_core_connections_per_host:3,get_credenti:53,get_execution_profil:[0,3],get_host:[0,25],get_host_by_host_id:25,get_lower_support:1,get_max_connections_per_host:3,get_max_requests_per_connect:3,get_min_requests_per_connect:3,get_query_trac:[0,3,43,54],get_replica:[0,25,43],get_stat:26,getstat:26,getter:[15,18],gevent:[0,33],geventconnect:[0,22],geventreactor:[0,33],gil:[0,49],github:[0,45,48,52],give:[3,27,53,55],given:[0,3,10,25,27,28,32,34,38,49],global:[0,7,43],go:[0,40,51],goal:[49,53],goe:0,good:[40,45],got:54,govern:[3,27],gracefulli:0,grant:53,graph:[0,3],graph_graphson2_row_factori:[15,18],graph_graphson3_row_factori:[3,15,18],graph_languag:[15,18],graph_nam:[12,15,18],graph_object_row_factori:[3,15,18],graph_opt:[0,3],graph_protocol:[3,12,14],graph_read_consistency_level:[15,18],graph_result_row_factori:[15,18],graph_sourc:[0,3,15,18],graph_traversal_dse_object_row_factori:12,graph_traversal_row_factori:12,graph_write_consistency_level:[15,18],graphanalyticsexecutionprofil:3,graphexecutionpolici:3,graphexecutionprofil:3,graphopt:[0,15,18],graphprotocol:[3,14,15,18],graphson1:[15,18],graphson1deseri:[15,18],graphson1seri:[15,18],graphson2:[0,15,18],graphson2read:[15,18],graphson3:[0,12,15,18],graphson3read:18,graphson:[0,12,14,15,18],graphson_1_0:[3,15,18],graphson_2_0:[14,15,18],graphson_3_0:[3,15,18],graphsonwrit:14,graphstat:[0,3,14],graphtravers:[12,14],graphtraversalsourc:12,greater:[27,50],greatli:0,greenlet:0,gremlin:[0,3,12,14,15,18,46],gremlinpython:[0,46],greplin:[0,26],groovi:[15,18],group:25,group_keys_by_replica:25,grow:0,gssapi:2,guarante:[0,27,30,54],guard:8,guid:[0,44,45,46,48,53],gx:0,h:[0,43],ha:[0,3,5,10,26,27,30,38,40,41,44,46,47,53,54,55],had:[0,40,54],handl:[0,2,3,9,10,12,29,33,38,39,41,43,44,46],handle_err:50,handle_error:[4,44,50],handle_fork:20,handle_pag:50,handle_result:3,handle_success:44,handle_writ:0,handler:[0,2,10,15,18,27,29,50],handshak:2,hang:[0,46],happen:[0,3,27],hard:46,has_more_pag:[0,3,50],hash:[0,38,46],hashabl:[0,32],hasn:0,have:[0,2,3,4,6,9,10,15,17,18,26,27,34,35,36,37,38,40,42,44,46,47,53,54,55],header:[0,29,46],healthmonitor:0,heap:0,heartbeat:0,help:[0,38,54],here:[3,9,10,34,35,37,38,39,40,41,46,48,53],hex:0,hh:32,high:[0,48,49],higher:[1,3,4,30,53,54],highli:44,highlight:54,hint:1,hit:[3,5],hold:[0,25,29],holder:44,homebrew:[0,46],honda2012:38,honda:[10,35,38],honor:[0,44],hook:[39,43],host1:27,host2:27,host3:27,host:[0,1,2,3,4,7,25,33,35,43,48,52,53,54],host_address:53,host_dist:3,host_id:25,hostconnect:0,hostdist:[0,3,27],hostfilterpolici:[0,27],hostnam:[0,27,53],hoststatelisten:3,hot:46,hour:32,how:[0,1,4,6,9,27,30,38,39,41,42,44,45,47,50,53,54],howev:[0,3,10,30,34,37,38,41,46,47,50,54,55],html:[6,10,38,48],http:[6,10,27,38,48,50,52],huge:49,human:[25,41],i:[8,10,15,18,27,30,38],id:[0,3,4,6,9,10,15,18,29,34,36,37,38,44,53,55],idea:27,ideal:[32,41],idempot:[33,44],identifi:[0,1,37,47],identitytransl:[3,27],idl:0,idle_heartbeat_interv:3,idle_heartbeat_timeout:[0,3],ids_to_fetch:44,ie:[13,50,53],if_exist:[9,10],if_not_exist:[9,10],iff:9,ifnotexistswithcountercolumn:40,ignor:[0,3,8,26,27,29,30,44],ignored_address0:27,ignored_address1:27,imagin:27,immedi:[1,3,34,44],immut:[0,32,48],impact:4,implement:[0,2,3,5,15,18,19,20,21,22,23,24,27,29,32,41,46,49,50,53,54],impli:[30,45],implicit:[0,10,54],implicitli:[3,8,37],importerror:39,impos:37,improv:[0,1,35,49,54],in_memori:52,inbetween:27,includ:[0,3,9,10,25,26,40,45,49,53,54,55],include_keyspac:9,inclus:3,incomplet:0,inconsist:0,incorrect:[0,44],incorrectli:[0,30],increas:[0,27,31,46],increment:6,incur:9,indefinit:0,independ:[32,53],indetermin:3,index:[0,3,6,25,37,38,48,54],indexmetadata:25,indic:[0,1,2,3,6,8,9,10,25,27,38,47,52],individu:3,inet:[0,1,25],inet_address:0,inet_ntop:0,inet_pton:0,infin:0,infinit:[0,27],inflat:29,influenc:27,info:[0,3,33,44],inform:[0,3,5,9,25,27,41],inherit:[0,6,9,11,42],init:[0,3,36,40],initi:[0,2,3,5,6,7,9,15,18,27,29,31,32,35,38,39,44,46,47,53],initial_respons:2,initialize_reactor:[19,20,21,22],inititi:40,inject:[3,42,46],inmemorycompactionstrategi:52,inplac:32,input:[0,30,40,41,42],insanc:41,insensit:9,insert:[0,1,3,4,9,10,30,32,36,37,41,44,47,54,55],insert_stat:55,insert_us:30,insid:[13,34,44],insight:0,inspect:[3,8],instal:[0,40,44,45,49,53],instanc:[0,2,3,6,9,10,13,15,18,25,26,27,30,34,38,44,48,50,53,54,55],instanti:[0,27,29,31,44],instead:[0,3,4,30,38,40,44,50,53,54],instruct:38,insuffici:[0,26],intact:42,integ:[0,6,10,11,13,17,31,32,35,36,37,38,41,48],integer_typ:32,integr:[0,29,40,41,45,46,48,54],intend:[9,31,32,46],intent:40,interact:[3,44],interfac:[0,2,27,50],interior:32,intern:[0,3,10,27,31,32,40,41,54],interpol:55,interpret:[0,30,36,38,54],intrins:41,introduc:[0,19,25,30,37,38,40,42,54,55],introduct:45,intruct:53,intstat:26,inupt:0,inv:[15,18],invalid:[0,1,26,30],invalidparametertypeerror:0,invalidrequest:1,invalidtypeparametererror:0,invit:40,invlabel:[15,18],invoc:46,invok:[0,3,40],involv:[30,38],io:[0,3,4,10,33,46,48,53],ip:[0,3,5,27,28,44,53],ipv4address:0,ipv6:0,ipv6address:0,irc:0,iron:40,is_analytics_sourc:[15,18],is_cql_compat:25,is_default_sourc:[15,18],is_graph_sourc:[15,18],is_idempot:[0,15,18,30,44],is_schema_agre:3,is_seri:0,is_shard_awar:52,is_shutdown:0,is_up:0,isbootstrap:27,isn:[0,9,10],isnotnul:38,isoformat:0,isol:27,issu:[0,2,27,31,32,36,54],item1:17,item2:17,item:[0,4,9,10,15,18,27,30,32,37,38,44],iter:[0,3,25,27,29,30,32,38,50,54],its:[0,2,3,5,9,19,20,23,24,27,30,32,37,42,46,53,54],itself:[46,54],jan:0,januari:0,java:27,jit:49,jitter:[0,27],jk:53,joe:[37,53],john:44,join:0,jon:[10,37,38],json:[3,12,15,18],json_data:[15,18],juli:0,jump:48,junctur:40,june:0,just:[0,3,6,25,27,32,34,37,40,44,46,50,55],k:[34,47,53],keep:[0,27],keepal:0,kei:[0,1,3,6,8,9,10,13,15,25,26,27,29,30,32,37,38,42,43,44,47,52,53,55],kept:4,kerbero:[0,53],kevin5000:37,kevin:37,key1:17,key2:17,key_typ:6,keyerror:0,keyfil:53,keyout:53,keyspac:[0,1,3,7,8,9,10,11,15,18,25,27,29,30,35,43,44,52,54],keyspace1:52,keyspace_nam:54,keyspacemetadata:[0,25],keystor:53,keystore_password:53,keyword:[0,3,6,7,9,10],kill:0,kimberli:9,kind:[0,27,54],kinit:53,klass:3,know:[3,27,36,54,55],known:[0,15,18,25,40,54],known_host:26,ks1:35,ks2:35,ks:35,ks_name:8,kwarg:[0,3,4,6,7,9,10,12,15,18,19,20,21,22,23,27,32,34,39,53],label:[15,18],lambda:53,languag:[12,15,18,40,45,49],larg:[0,3,4,10,32,38,45,54],largest:36,last:[0,1,3,27,31,38],last_act:3,last_host:1,last_nam:[9,37],lastest:36,latenc:[26,44,52],later:[0,1,9,27,44,50],latest:[0,54],latter:[3,50],layout:25,lazi:0,lazili:29,lazy_connect:[0,7],lazyprotocolhandl:29,lbp:0,lead:[0,34,49,54],leak:0,learn:[30,53],least:[6,26,27,30,35,37,46],leav:[0,3],left:[0,3,4,9,41,54],legaci:[0,6,40,48,53,54],len:[0,9,10,35],length:[6,27,30],less:[0,46],let:[0,3,54],letter:13,level:[0,1,3,4,10,15,18,27,30,33,41,48,53],leveledcompactionstrategi:9,lib:0,libev4:46,libev:[0,33],libevconnect:[3,23,46],libevreactor:[0,3,33,46],libevwrapp:0,librari:[0,19,20,41,46,53],licens:45,lifecycl:2,lightweight:[0,1,10,30,44,45],lighweight:27,like:[0,1,3,4,9,10,15,18,26,27,30,37,38,41,44,46,50,53,55],limit:[0,3,10,30,38,41,49],line:[0,19,44,46],linear:32,lineariz:30,linestr:32,link:[0,41,46],linux:46,list:[0,1,3,4,6,7,8,9,10,13,15,17,18,25,27,29,30,32,35,43,44,45,46,48,50,54],list_col:44,list_column:10,list_column__append:10,list_column__prepend:10,listen:[0,3],listen_address:0,liter:[0,15,17,18,30,41,44,54,55],live:[1,27,43],ll:[38,53],load:[0,3,9,10,15,18,33,37,38,40,42,53,54],load_balancing_polici:[3,27,42,44,52],load_cert_chain:53,load_verify_loc:53,loadbalancingpolici:[0,3,27,42],local:[0,1,3,27,30,41,42,43,44,54],local_dc:[0,27],local_on:[0,1,3,44],local_queri:42,local_quorum:[0,1,44],local_seri:[1,30,44],localhost:[7,10],localstrategi:25,localtim:41,locat:[3,40,53,55],lock:0,locked_execut:42,log:[0,3,8,27,30,31,44,45,54],log_error:3,log_result:3,logentri:34,logger:0,logic:[0,37],logo:45,longer:[0,1,54],look:[13,37,38,53],lookup:[0,25,27],loop:[0,3,4,21,33,44,46,53],lose:0,loss:0,lot:0,low:[15,18,27,33],lower:[1,4,27,32,38,44],lower_bound:32,lowercas:0,lwt:[0,3,9,47],lwtexcept:[0,9,10,40],lz4:[0,46],m:[9,36],mac:[0,46],machin:44,madd:46,made:[1,3,5,27,38,44,54],mai:[0,2,3,4,6,7,27,30,32,37,38,43,44,46,49,53,54],main:[0,3,53,55],maintain:[0,3,30,32,37,54],major:[0,27,42,53,54],make:[0,1,3,10,25,27,37,40,41,42,43,44,45,46,48,51,53,54],make_query_plan:27,make_token_replica_map:0,manag:[0,3,6,9,10,11,28,33,34,37,42,46,48,54],mandatori:[0,3],mani:[0,1,3,4,27,44,49,50,53,54],manifest:[0,43,47],manipul:[0,3],manner:32,manual:[3,9,34],manufactur:[10,35,38],map:[0,1,3,8,10,13,15,17,18,25,29,30,32,33,37,38,44,48,54],map_column:10,map_column__remov:10,map_column__upd:10,mapper:[0,7,40,45],march:0,margin:4,mark:[0,3,5,33,44,45],marker:41,master:[0,3,52],match:[0,3,5,9,10,15,18,25,30,38,40,42,43,44,46,53,54,55],materi:[0,3,4,25,29,46,54],materializedviewmetadata:25,math:0,max:[0,3,5,26,44],max_attempt:[27,44],max_connect:3,max_delai:27,max_length:6,max_request:3,max_schema_agreement_wait:3,max_support:1,max_threshold:9,max_tim:38,max_uuid_from_tim:32,max_wait:[3,30],max_wait_sec:3,max_wait_sec_p:3,maximum:[1,3,6,27,32,38],maxtimeuuid:38,maxyear:[32,41],md5token:25,md:52,mean:[3,9,26,27,38,44],meaningless:38,meant:41,measur:[3,27],mechan:[2,3,27,53],median:26,meet:[26,27,53],member:[32,37],memori:[0,4,38,52,54],mention:[0,41,44],merg:40,mesh:54,messag:[0,1,2,3,5,29],message_types_by_opcod:29,meta:[0,3,37],metadata:[0,3,15,18,27,30,33,42,43,52],method:[0,2,3,9,10,27,29,30,35,36,37,38,41,43,44,46,49,52],metri:26,metric:[0,3,33],metrics_en:3,micro:32,microsecond:[0,31,54],middl:13,might:[0,3,30,50,53],migrat:[48,54],millisecond:[0,17,32,41],millsecond:41,min:[0,26,43],min_length:[0,6],min_request:3,min_support:1,min_threshold:9,min_tim:38,min_uuid_from_tim:32,minim:[3,40,41,44],minimalist:32,minimum:[1,3,6,32,38],mintimeuuid:38,minut:[0,32,46],minyear:[32,41],mismatch:0,misplac:0,miss:[0,27],misspel:13,mistak:40,mitig:49,mix:[0,30],mke:0,mm:[17,32],mmmuuunnn:32,mno:46,mock:0,mode:0,model:[0,3,8,33,38,43,48,54],model__lik:38,modelexcept:40,modelqueryset:10,modern:0,modif:8,modifi:[0,1,8,9,10,32],modul:[0,9,11,18,19,20,40,46,49],monkei:[0,21,22,53],monkey_patch_loop:0,monoton:0,monotonictimestampgener:31,month:32,montonictimestampgener:0,more:[0,3,4,6,9,10,15,25,27,29,31,38,40,42,44,45,49,50,53,54],most:[3,27,30,37,40,41,43,50],mostli:[18,47],move:[0,3,30,54],ms:32,ms_timestamp_from_datetim:32,msg:29,much:[37,41,53,54],multipl:[0,3,10,12,14,15,18,27,34,35,44,48,49,54],multipleobjectsreturn:[0,10],multipli:13,multiprocess:0,multithread:0,murmur3:[0,3,46],murmur3partition:[0,25,46],murmur3token:[0,25],mussei:[46,53],must:[0,1,3,4,10,30,32,37,38,44,46,53,54,55],mutabl:3,mutat:48,mutual:[7,32],mv:27,my:53,my_callback:34,my_graph:12,my_tabl:44,my_user_id:30,mycf:3,mykeyspac:[3,30,44,54,55],mymod:36,mymodel:36,mystery_funct:34,mystorepass:53,mytabl:4,n:10,naiv:[6,41],name:[0,1,3,7,8,9,10,11,12,13,15,18,25,26,27,29,30,34,37,40,44,47,55],named_arg:34,named_tuple_factori:[0,3,16,30,54],namedt:38,namedtupl:[0,3,4,30,37,44,47,54,55],namedtuple_factori:0,nan:[0,32],nanosecond:[6,32,41],nativ:[0,1,15,18,29,37,45],native_transport_address:0,natur:2,necessari:[3,44,46,53],need:[0,1,3,6,12,27,30,32,34,35,36,37,38,39,44,46,49,52,53,54,55],neg:[0,32,38],negoti:2,nest:[0,32],net:27,network:[0,30,44],networktopologystrategi:[0,8,25],never:[0,27,34,47,49,54],neverretrypolici:3,new_authent:2,new_nod:0,new_plan:27,new_schedul:27,newkei:53,newli:[0,25,27],next:[0,3,21,27,42,48,50,53],next_pag:38,ngdg:0,nice:0,nicer:38,no_compact:0,no_valid_replica:25,noconnectionsavail:28,node1:42,node1_profil:42,node1_whitelist:42,node2:42,node2_profil:42,node:[0,1,3,5,25,26,28,30,32,33,44,52,53],node_domain:5,nodesync:0,nodetool:27,nohostavail:[0,3],nomenclatur:54,non:[0,3,6,10,32,33,37,44,45],nonblock:0,none:[0,1,2,3,4,5,6,7,8,9,10,11,12,14,15,17,18,25,26,27,30,32,36,38,39,41,43,44,47,50],nonetyp:0,nonexist:[0,1],normal:[0,3,9,10,12,27,30,32,41,44,50],nose:0,notabl:54,note:[0,3,4,7,8,9,10,19,27,30,32,35,37,38,40,41,42,44,45,50,52,53,54],noth:[0,25,27],notic:0,notif:0,notifi:3,nov:0,novemb:0,now:[0,31,34,36,38,40,41,44,48],nt:0,nullhandl:0,num:26,number:[0,1,3,4,5,9,10,26,27,40,42,44,46,47,50],numer:[0,41],numpi:29,numpyprotocolhand:29,numpyprotocolhandl:[0,29],o:[44,53],obj:[15,18],object:[0,3,4,12,15,17,18,25,26,27,30,31,32,34,35,36,37,41,42,43,44,45,49,50,54,55],obtain:[3,10,43,49],occur:[1,27,30,34,44,54],oct:0,octob:0,od:32,off:3,offer:[32,46,49,50],offici:[53,54],offset:32,often:37,ok:[27,53],old:[0,10,40],omit:[1,30],on_add:27,on_authentication_success:2,on_down:27,on_read_timeout:27,on_remov:27,on_request_error:[0,27],on_unavail:27,on_up:[0,27],on_write_timeout:[0,27],onc:[3,4,19,20,21,22,27,29,30,34,36,38,46,50],one:[0,1,2,3,6,10,13,26,27,30,32,35,36,37,38,42,44,53,54],ones:[10,40],onli:[0,1,3,4,5,6,7,8,9,10,18,19,27,30,31,34,37,38,40,41,44,45,46,47,52,53,54],onward:52,op:38,opaqu:3,opcod:29,open:[0,2,3,26,27,28,32,45],open_connect:26,openssl:53,oper:[0,1,3,5,8,9,10,15,18,30,32,33,35,44,47,54],operationtimedout:[0,1,3],opertaion:0,oppos:27,optim:[0,45,46,49],option:[0,1,2,3,5,7,9,10,11,12,14,25,29,30,33,38,40,42,44,47,48,49,52,53,54,55],option_map:25,options__contain:38,options_map:25,order:[0,1,4,6,10,25,27,30,32,34,37,41,54],order_bi:[10,38],ordered_dict_factori:[0,3,16,30,54],ordereddict:[0,3,30,32,44],orderedmap:[0,32],orderedmapserializedkei:32,orderedset:0,org:38,organ:45,origin:[0,3,38,54],os:46,oss:[0,27],other:[2,3,6,8,9,15,18,26,27,30,32,38,44,45,46,53,54,55],other_error:26,otherstuff:55,otherwis:[2,3,6,9,27,32,53],ou:53,our:[38,44,48,53],out:[0,1,4,9,27,32,34,36,38,40,41,44,53],outcom:47,output:[0,41],output_password:53,outsid:[0,6,27,32],outv:[15,18],outvlabel:[15,18],over:[3,27,29,38,49,50,53,54],overcount:27,overflow:[0,41],overflowerror:[0,32],overhaul:54,overhead:[0,4,34],overload:[0,1,6,26,27],overrid:[0,3,9,15,18,42,44,54],overridden:[0,3,50],overriden:0,overs:3,overview:[40,41,45,48],overwrit:10,own:[3,9,37,53],owner:37,owner_id:[37,40],pack:[0,30],packag:[0,2,32,41,46,48,53,54],page:[0,1,3,45,51],pagedresult:[0,50,54],pagedresulthandl:50,pagin:[0,38,50],paging_st:[3,50],pair:[0,29],panda:29,parallel:0,param:[0,4,13],paramet:[0,3,4,6,7,8,9,10,12,14,15,18,27,29,30,31,32,37,40,47,53,55],parameter:55,parent:[0,20],pars:[0,15,18,29,32,43,44],parser:[0,29],part:[0,8,10,30,35,40,41,46],parti:[2,3,41,48],partial:[0,21,22,30],particular:[0,3,25,27,30,52],particularli:38,partit:[0,6,10,25,27,30,38],partition:0,partition_kei:[6,10,30,38],pass:[0,2,3,4,6,7,9,10,25,29,30,34,36,37,38,39,47,48,52,53,54,55],passin:53,password:[2,53],passwordauthent:[2,53],patch:[0,21,22,41,53],path:[0,15,18,29,46,53],pattern:[37,49],paxo:30,payload:[0,1,3,30,33],peer:[0,5,25],peers_v2:0,pem:53,pend:0,pending_us:30,pep:0,per:[0,3,4,6,9,10,25,27,35,37,43,44,50,54],percentil:26,perform:[0,1,3,9,10,27,30,33,37,38,45,46,51],perhap:46,period:39,permiss:53,permit:27,persist:[0,15,18,27,41],person:[9,37,38],person_id:37,perspect:[2,27],pertain:3,pertin:47,pet:[37,40],pet_id:[37,40],pet_typ:[37,40],phase:[2,3,30,46],photo_id:[10,37],phrase:13,pick:[36,44],pip:[0,54],pk:[38,44],pk__token:[0,38],pk__token__gt:[0,38],place:[0,40,44,54],placehold:[3,15,18,30,44,55],placement:[0,8],plai:0,plain:53,plaintextauthent:2,plaintextauthprovid:[0,2,3,53,54],plan:[0,8,27,45],platform:[0,42],pleas:[0,3,6,9,11,27,37,43,45,53],plu:[38,47],plug:39,pluggabl:0,pmfstat:26,point:[0,3,6,26,27,32,41,44,53,54],polic:27,polici:[0,3,33,42,43,44,52,54],poll:[3,30,43],polygon:32,polymorphic_kei:40,pool:[0,1,3,33,54],pool_wait_timeout:3,popul:[0,3,27,30,38],port:[0,3,5,25,44],portion:[30,32],posit:[3,10,30,34,38,44,47,54],possibl:[0,3,9,21,27,31,32,37,38,41,46,50,53,54],post:[0,49],postfork:[39,43],potenti:0,pr:0,practic:44,practiv:10,pre:[0,46],preced:[3,27,34,47],precis:[0,6,17,32,40,41,54],predic:[0,27,33],predict:38,preemptiv:44,preexist:7,prefer:[0,27,41,44,46,54],prefix:[9,11,13],prematur:0,prepar:[0,3,4,27,33,41,43,53,55],prepare_on_all_host:3,prepared_stat:30,preparedstat:[0,3,30,44],preparemessag:0,prepend:[10,47,54],present:[0,7,10,30,41,42,43,46,47,54],preserv:[0,6,9,30,40],presist:37,pretti:49,preval:41,prevent:[0,10,40,44,46],previou:[0,3,53,54],previous:[0,40,42,54],previous_vers:1,price:[10,38],primari:[0,3,6,8,9,10,25,30,37,38,47,52,55],primary_host:27,primary_kei:[6,9,10,25,35,36,37,38,40,48],princip:[0,53],print:[3,9,10,12,30,32,35,37,41,42,43,44,46,48,52,55],prior:0,privat:[0,1,27],probabl:[27,38,53],problem:[0,3,26,43],process:[0,3,4,20,43,44,46,49,53,54],process_row:50,process_us:[3,4,44,50],produc:[2,4,15,18,38],product:[8,48,53,54],profil:[0,3,4,12,14,44,45],profile_long:44,programmat:3,project:[1,40,45,48,49],prompt:[46,53],proof:0,propag:[0,27,30],proper:[0,39,46],properli:[0,3,37,38,44],properti:[0,1,3,5,9,13,15,18,25,27,28,30,32,37],protect:0,protocol:[0,1,3,5,6,12,14,30,33,37,45,52],protocol_tlsv1:53,protocol_vers:[0,1,3,4,29,30,32,37,48,50,53,54,55],protocolerror:5,protocolhandl:[0,29],protocolvers:1,provid:[0,3,12,13,15,18,27,41,42,43,46,49,50,53,54],proxi:5,proxim:13,proxy_address:5,prudent:40,ps:50,publish:[0,46,53],pure:[0,2,27,29,46,53],purpos:[3,6],push:[0,46],py:[0,46],pyopenssl:[0,53],pypi:[0,46],python2:32,python3:0,python:[0,15,17,18,19,20,29,30,32,37,40,41,44,47,48,49,51,53,54,55],pyton:0,pytz:41,q2:48,q:[35,38,48],qop:[2,53],quadrat:0,quantiz:6,queri:[0,1,3,4,6,9,12,15,16,18,25,27,29,32,33,35,37,40,41,42,45,46,48,49,55],query_cl:[3,30],query_from_travers:12,query_str:[15,18,30],queryexhaust:3,queryhandl:[3,29],queryoper:0,queryset:[0,9],querytrac:[0,30,43],question:[45,48],queu:34,quickli:[0,49],quorum:[1,10,27,30,44],quot:[0,17,41],race:0,rack:[0,28],radiu:32,rais:[0,1,2,3,4,5,6,9,10,15,18,27,30,32,34,37,38,40,44,50,54],raise_on_first_error:4,random:[0,27,32,38],randompartition:25,rang:[0,4,10,32,38,41,43],range_request_timeout_in_m:1,rare:0,rather:[0,32,46],raw:6,re:[0,27,30,37,38,39,44,46,53,55],reach:34,reachabl:27,reactor:[0,20,24,43],read:[0,1,6,15,18,26,27,30,32,34,36,43,53],read_inet:0,read_repair:0,read_repair_ch:0,read_request_timeout_in_m:1,read_timeout:26,readabl:25,reader:[12,15,18],readfailur:1,readm:0,readtimeout:[1,44],reason:[1,3,27,41,53],rebuild:[0,3],rebuilt:0,receiv:[0,1,3,27,44],received_respons:[1,27],recent:0,recogn:[15,18],recommend:[0,3,4,27,36,44,49,53,54,55],reconnect:[0,33],reconnection_polici:3,reconnectionpolici:[0,27],reconnector:0,record:[0,6,10,27,38],recreat:[0,25],recurs:0,redhat:46,reduc:[0,3,49,52],redund:40,reevalu:0,ref:0,refactor:[0,41],refer:[0,10,34,40,42,47,54],referenc:3,refresh:[0,3],refresh_:54,refresh_keyspace_metadata:3,refresh_nod:[0,3],refresh_schema:[0,54],refresh_schema_metadata:3,refresh_table_metadata:[3,52],refresh_user_aggregate_metadata:3,refresh_user_function_metadata:3,refresh_user_type_metadata:3,regard:[3,27,32],regardless:[26,27,46,47],regex:13,regist:[0,3,7,12,17,26,34,37,45,54],register_connect:[0,7,35],register_listen:[0,3],register_user_typ:[3,54,55],registr:35,registri:7,regress:0,regular:[13,30,36,38],reilli:44,reinstal:46,reject:47,rel:41,relat:[0,30,38,42],relax:7,releas:[0,9,27,40,42,53,54],release_vers:[43,44],reli:[27,38],reloc:40,remain:[3,20,27,40,42],rememb:44,remot:[0,3,27,52],remoteconnect:12,remov:[0,3,6,8,10,27,30,32,42,47],remove_request_init_listen:3,repair:27,repeat:[27,44],replac:[0,3,6,29,40,53,54],replai:[1,27],replic:[0,3,8,25,40,52],replica:[0,1,8,25,26,27,30,44],replication_factor:[8,25,52],replication_factor_info:25,replicationfactor:25,replicationstrategi:25,report:[0,27],reprepar:0,reprepare_on_up:3,repres:[1,3,5,6,9,15,18,25,26,28,30,31,32,37,38,40,41,54],represent:[0,25,30,32,54],reproduc:0,req:53,req_distinguished_nam:53,request:[0,1,3,4,26,27,38,39,42,44,45,47,49,53,54],request_id:0,request_tim:[0,26],request_timeout:[3,42,44],requestexecutionexcept:1,requestvalidationexcept:1,requir:[0,1,2,3,6,7,19,27,29,30,32,37,38,39,40,44,46,48,53,54],require_client_auth:53,required_replica:[1,27],required_respons:[1,27],reset:27,resolut:[0,32],resolv:[0,3,5,27,36,53],resort:27,resourc:[19,20,21,22,46,53],respect:[0,3,38],respond:[1,2,27,44],respons:[0,1,2,3,27,29,38,44],response_futur:3,responsefutur:[0,3,29,43,44,49,50,54],rest:[27,44],restart:[0,44],resulset:0,result:[0,3,4,9,10,12,15,18,25,26,27,29,30,32,37,38,41,43,44,45,52,55],result_cach:0,result_metadata:29,result_or_exc:4,result_set:3,results_gener:4,results_metadata:0,resultset:[0,3,50,54],resync:9,retain:[0,41],rethrow:27,rethrown:0,retri:[0,7,26,30,33,44],retriev:[1,3,10,30],retry_connect:7,retry_next_host:27,retry_num:27,retry_polici:[0,3,15,18,27,30,42,43,44],retrypolici:[0,3,26,27,30,43],retun:47,reus:[3,14,30],revers:[10,27],review:0,rework:54,rf:[0,1],rhel:46,rich:3,right:[27,30,44],ring:[0,3,27,32,33],risen:53,risk:27,rlac:0,robin:27,robust:[0,41],role:53,root:53,root_ca_base_nam:53,root_cert_pass:53,rootca:53,rotat:27,round:[0,27,32],roundrobinpolici:[27,52],roundtrip:30,rout:[0,3,9,27,43,46],routing_kei:[15,18,27,30,43],row:[0,3,4,5,10,12,29,33,34,37,38,41,42,43,44,47,48,50,54,55],row_factori:[0,3,7,29,30,42,44],row_id:10,row_list:54,rpc:[5,28],rpc_addr:0,rpc_address:[0,42],rsa:53,rule:30,run:[0,9,10,21,27,34,37,39,44,46,48],run_in_executor:0,runtim:[0,46,49],runtimeerror:0,s:[0,1,2,3,6,7,9,10,11,24,27,29,30,32,34,35,36,37,38,39,41,44,45,46,48,52,53,54,55],safe:[0,4],safeti:0,same:[0,3,4,6,7,12,15,18,25,27,30,32,34,35,36,37,38,42,43,44,46,53,54],sasi:38,sasl:[0,2,53],sasl_kwarg:[2,53],saslauthent:[0,2],saslauthprovid:[0,2,53],saslclient:0,satisfi:1,save:[0,9,10,34,35,37,38,41,44,50],scale:[0,26,41,46,49,54],scan:43,scenario:[0,36],schedul:[0,34],schema:[0,3,9,30,33,37,44,54],schema_event_refresh_window:3,schema_metadata_en:3,schema_trigg:0,schemapars:0,scope:[0,3,10],scratch:42,script:[0,40,46,49],scylla:[38,40,46,54],scylladb:52,search:13,second:[0,3,10,26,27,30,31,32,38,41,44],secondari:[0,25,34,38],section:[0,38,40,45,47,49,53,54],secur:[45,54],see:[0,1,3,4,6,9,10,11,13,15,18,27,29,30,32,37,38,41,42,43,44,46,47,48,49,50,53,54],seen:[0,3,27],segment:40,select:[0,3,4,9,10,30,38,42,43,44,46,50,52,53,54,55],select_stat:4,self:[3,15,18,37,50,54,55],semant:[0,3],send:[0,1,2,3,5,27,44,45,54],sensibl:9,sensit:[0,9],sent:[0,1,2,3,29,44],sep:0,separ:[3,53],septemb:0,seq:43,sequenc:[0,3,4,14,17,27,30,32,44],sequenti:0,serd:0,serial:[0,1,3,12,15,18,30,41],serial_consistency_level:[3,15,18,30,42,44,47,54],serializ:3,serv:40,server:[0,1,2,3,9,15,18,25,29,30,33,38,44,47,48,54],server_authenticator_class:2,server_hostnam:53,server_nam:5,server_vers:43,servererror:27,servic:[2,53],service_timeout:21,session:[0,1,4,7,10,12,14,15,18,25,27,29,30,33,35,39,42,43,44,46,47,48,49,50,52,53,55],sesssion:0,set:[0,1,2,3,4,6,7,8,9,10,11,12,13,15,17,18,19,20,21,22,25,26,27,30,32,35,37,38,42,43,45,46,48,50,53,54],set_column:10,set_column__add:10,set_column__remov:10,set_core_connections_per_host:[3,4],set_default_connect:[7,35],set_keyspac:[0,3,27,44,55],set_max_connections_per_host:3,set_max_requests_per_connect:3,set_meta_refresh_en:3,set_min_requests_per_connect:3,set_sess:[0,7],set_source_analyt:[15,18],set_source_default:[15,18],set_source_graph:[15,18],set_stats_nam:26,set_verifi:53,setenv:46,setup:[0,7,10,35,37,38,39,40,44,46,48,53],setuptool:[0,46],sever:[0,38,40,44,46,49],shallow:[3,42],shard_aware_stat:52,shards_count:52,share:[0,3,19,20,21,22,42,49],shed:[15,18],shell:46,shift:41,shortcut:[3,46],should:[0,2,3,4,6,7,8,9,10,15,18,19,20,21,22,25,27,30,31,37,40,42,44,46,49,53,54],should_log:3,shouldn:0,show:[0,8,32,36,38,40,42,47,53],shown:[3,35,37,55],shuffl:38,shuffle_replica:27,shutdown:[0,3,39],side:[0,1,2,3,15,18,27,40],sign:[6,53],signal:39,signatur:[1,3],significantli:[38,52],silent:27,similar:[27,29,34,53],simpl:[0,6,15,18,27,30,38,40,41,44,46,49],simpleconvictionpolici:[3,27],simplegraphstat:[15,18],simpler:54,simplest:[38,44],simplestat:[0,3,15,18,30,44,50],simplestrategi:[8,25,52],simpli:[0,9,17,27,34,37,40,44,46,55],simplifi:[15,18],simultan:42,sinc:[0,9,29,31,32,36,38,41,43,54,55],singl:[0,3,4,6,8,9,10,14,25,27,28,30,32,37,38,40,42,44,46,47,54],single_object_row_factori:[15,18],site:[0,41],situat:[27,34,37],six:[0,46,54],size:[0,3,10,54],sizeti:0,sizetieredcompactionstrategi:9,skip:[0,9],slack:0,sleep:[27,37],slice:[0,3,38],slightli:0,slow:0,smaller:27,smallint:[0,6,15,18,44],smoke:0,snappi:46,snapshot:0,sni:5,sniendpoint:5,sniendpointfactori:5,so:[0,1,3,10,21,25,27,30,37,38,41,42,44,47,48,49,50,53,54],socket:[0,5,53],socket_famili:5,sockopt:3,soft:0,softwar:45,some:[0,1,9,15,18,27,34,37,38,41,44,45,46,47,48,50,53,54,55],some_id2:34,some_id:34,someth:[2,27,37,38,46,53],sometim:[0,10,15,18,27,46,50],somewher:[34,50],sort:[0,4,6,32,38],sortedset:[0,32,54],sourc:[0,3,15,18,45,46],source_elaps:[0,43],span:46,spark:[0,3],spcifi:1,spec:41,special:[0,6,29,37,38,40,43],specif:[0,2,5,13,15,17,18,25,27,40,45,46,54,55],specifi:[0,1,3,6,8,9,10,11,12,27,29,30,32,35,37,38,40,41,42,44,53,54],specul:[0,27],speculative_execution_polici:[3,44],speculativeexecutionpolici:[27,44],speed:3,speedup:38,spell:41,spin:0,split:2,squar:47,ss:32,ssl:[0,5,44],ssl_context:[0,3,44,53],ssl_error_want_read:0,ssl_error_want_writ:0,ssl_opt:53,ssl_option:[0,3,5,53],ssl_version:53,sslcontext:[0,53],sstabl:43,sstable_size_in_mb:9,st:[3,37,55],stabil:0,stabl:0,stale:27,stall:0,standard1:52,standard:[0,19,20,26,38,39,41,44,46,53,54],start:[0,3,34,38,41,45,50,54],start_fetching_next_pag:[3,50],start_tim:3,startup:0,stat:[0,26,52],state:[0,3,10,20,27,34,45,47],stateless:50,statement:[0,3,25,27,33,34,36,41,42,43,47,50,55],statements_and_param:4,statements_and_paramet:4,stats_nam:26,statu:[47,52],status_event_refresh_window:3,stddev:26,stdlib:0,step:[37,45],steroid:38,steve:10,still:[0,15,18,30,34,37,40,42,44,54,55],stmt:0,stop:[4,34],store:[0,1,6,9,30,37,41],str:[7,8,10,17,32,44],straightforward:[37,40,41,54],strategi:[0,40,54],stream:[0,29],stream_id:29,street:[3,11,37,54,55],stress:0,strict:[6,49],strictli:0,string:[0,1,2,3,6,12,13,15,17,18,25,26,27,29,30,32,41,44,53],string_typ:32,strip:0,strong:0,structur:[15,18,25,37],studio:46,stuff:[3,55],style:3,sub:[37,40],subclass:[0,1,2,3,27,30,37,53],submit:[0,43],submit_schema_refresh:54,submodul:[40,54],suboptim:27,subsequ:40,subset:38,substanc:39,substanti:[4,54],succe:[3,27],succeed:0,success:[0,1,2,3,4,10,27,30,44,46],successfulli:[0,52],sudo:46,suffici:27,suggest:[44,46],suit:[0,53],suitabl:[2,17,25,36],superset:25,suppli:[0,3,30,44,53,54],support:[0,1,2,3,8,9,10,12,27,32,34,36,38,41,44,45,50,52,53,54,55],supported_vers:1,suppos:[0,37,53],sure:[0,3,27,37,43,44,46,49,51,53],surfac:0,surround:0,swap:54,sy:0,sync:[9,35,37],sync_schema:0,sync_tabl:[0,8,10,35,37,48],sync_typ:[8,11,37],synch:8,synchron:[0,3,4,8,37,49,50],syntax:[0,10,34,38],syntaxexcept:0,system:[0,5,25,38,42,43,44,46,54],t:[0,9,10,15,31,37,38,43,44,47,49,53,54,55],tabl:[0,1,3,6,8,25,30,32,33,37,44,47,48,54,55],tablemetadata:[0,25,52,54],tablemetadatadse68:25,tablemetadatav3:25,tag:[0,15,18],take:[0,3,4,8,9,15,18,25,27,35,44,46,53],taken:[15,18,40],tarbal:46,target:[0,3,13,15,18,27,46],task:[0,3,34,39],tcp:0,tear_up_couch:37,technic:40,techniqu:44,tell:55,tenant:41,term:27,tesla2012:38,tesla:[35,38],test2:10,test4:10,test:[0,10,21,22,27,31,35,46,47],test_clone_shared_lbp:0,test_clust:0,test_set_keyspace_twic:0,testifexistsmodel:9,testifnotexistsmodel:9,testmodel:38,testtransactionmodel:9,text:[0,3,6,9,10,11,13,35,36,37,38,40,44,48,54,55],than:[0,1,3,6,10,27,30,31,32,38,42,44,46,49,50,53],thei:[0,1,3,4,6,8,9,10,15,18,27,29,32,34,36,37,38,40,41,54,55],them:[0,3,27,38,40,41,44,46,47,48,54],themselv:[15,18],therefor:[36,38,46],thi:[0,1,2,3,4,5,6,7,8,9,10,11,12,13,15,17,18,19,20,21,22,25,26,27,28,29,30,31,32,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,52,53,54,55],thing:[3,27,38,40,44],third:[2,41,48],thorough:[46,53],those:[0,3,26,27,30,42,46],though:54,thread:[0,3,4,44,46,49],threadpoolexecutor:0,three:[1,27,30,32,44,47],threshold:[0,3],thrift:0,throttl:0,through:[0,2,3,5,7,9,10,15,18,26,27,30,38,44,45,47,49,54,55],throughput:[0,4,49],thrown:34,thu:[10,27,30,47],ticket:53,time:[0,1,2,3,4,6,10,26,27,31,32,37,38,40,44,45,46,54],time__gt:38,time__lt:38,time_arg:32,timedata:9,timedelta:10,timedelta_or_datetim:9,timeout:[0,1,3,9,10,21,26,27,54],timer:[0,21,26],timestamp:[0,1,6,9,10,17,32,33,36,40,44,45],timestamp_gener:3,timestamp_na:41,timestamp_pres:41,timestamp_utc:41,timestamptyp:0,timeuuid:[0,6,10,32,37,44,54],timezon:[0,6,32,41],tinkerpop:[12,46],tinyint:[0,6,44],tip:45,tlsv1_method:53,tmp:42,to_bigint:[15,18],to_doubl:[15,18],to_float:[15,18],to_int:[15,18],to_python:0,to_smallint:[15,18],todo:32,token:[0,2,3,13,15,27,33,43,46,52],token_fuzzi:13,token_map:0,token_metadata_en:3,token_prefix:13,token_regex:13,token_str:25,tokenawar:0,tokenawarepolici:[0,3,27,42,52],tokenawarerout:9,tokenfun:38,tokenmap:[0,25],toler:0,tolist:12,tombston:[3,36,43],tombstone_compaction_interv:9,tombstone_threshold:9,too:[0,3,27,41],took:1,tool:46,toolkit:29,top:[15,18,27],topo:0,topolog:[0,3,27,33],topology_event_refresh_window:3,total:[3,27],trace:[0,3,33],traceev:30,traceunavail:[3,30],tracing_en:0,track:0,trade:4,trademark:45,traffic:[0,44],trail:0,transact:[0,1,3,12,14,27,30,45],transform:37,transient_replica:25,transit:0,translat:[33,40,44],transpar:[3,44,50],trap:34,trash:0,travers:[0,12,14,15,18,46],traversal_batch:14,traversal_class:12,traversal_sourc:12,traversalbatch:[12,14],traversalmetr:0,travisci:0,treat:[3,27,30,44,50],tree:3,tri:0,trigger:[0,3,27],truncat:[6,30,32,40],truncate_microsecond:6,truststor:53,truststore_password:53,truthi:27,ts:41,ttl:[0,9,10],ttl_in_sec:9,tunabl:49,tune:0,tupl:[0,1,3,4,9,12,17,25,27,30,38,44,54,55],tuple_factori:[0,3,16,29,30,42,44,54],turn:[3,43],twice:0,twist:[0,33,44],twistedconnect:[24,53],twistedreactor:[33,53],two:[0,1,3,13,27,29,32,38,44,46,53],txt:[0,46],type0:1,type1:1,type:[0,1,3,8,10,15,17,18,25,27,29,30,32,33,34,38,41,45,47],type_model:8,typeerror:[0,15,18],typestr:0,typic:[3,10,27,29,30,31,34,38,42,44],typo:0,tzinfo:41,u:[10,30,37,38,47],ubuntu:[0,46],uda:0,udf:0,udt:[0,3,12,18,37,45],un:[0,30],unabl:[0,27,46],unauthor:[0,1],unavail:[0,1,26,27],uncal:0,unchang:40,unclean:54,uncompar:0,uncomplet:30,uncondit:0,undefinedkeyspaceexcept:40,under:[0,25,27,37,45],underscor:0,understand:53,understood:[3,27],underutil:0,unexpect:27,unexpectedli:0,unfamiliar:38,unhexlifi:0,unicod:[0,17,44],unicodedecodeerror:0,unif:0,unifi:[0,54],unintend:0,union:3,uniqu:[1,6,25,37,42],unit:[0,13,27,45],unix:[0,5,31,32,41],unix_socket_path:5,unix_time_from_uuid1:32,unixsocketendpoint:5,unknown:[0,15,18,46,54],unless:[3,6,27,35,54],unlik:41,unlog:30,unlogged_batch:27,unord:[6,25],unorder:0,unpack:[0,15,18,44],unprepar:55,unrecogn:0,unrecover:5,unreferenc:0,unregist:[0,55],unregister_connect:[7,35],unregister_listen:3,unset:0,unset_valu:30,unspecifi:[0,9],unsupport:0,unsupportedoper:3,until:[0,2,3,4,7,37,43,44],untrust:3,unus:[0,46],unwis:10,up:[0,3,8,13,19,20,21,22,32,33,34,37,38,53,54],updat:[0,1,3,8,9,10,30,32,34,38,40,42,44,45,47],update_view_metadata:0,updatestat:0,upfront:29,upgrad:[45,48,53],upon:[3,37],upper:32,upper_bound:32,uppercas:0,us:[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,35,36,37,38,40,41,43,44,45,46,47,49,50,51,52,53],usag:[0,2,3,4,9,25,27,30,54],use_certificate_fil:53,use_client_timestamp:[0,1,3,54],use_default_tempdir:0,use_list_t:6,use_privatekey_fil:53,use_set_t:6,used_hosts_per_remote_dc:27,usemap:6,user1:[44,53],user2:44,user3:44,user3_lookup:44,user:[0,1,3,4,6,8,9,10,17,18,25,30,33,38,40,44,45,46,50,53],user_act:3,user_id1:44,user_id2:44,user_id3:44,user_id:[4,9,30,38,44],user_ids_to_queri:44,user_lookup_stmt:44,user_row:[3,44,50],user_typ:[3,6],user_type_map:29,user_tz:41,useraggregatedescriptor:[1,3],userdefinedtyp:[0,6,37],userfunctiondescriptor:[1,3],usernam:[2,44,53],users_to_insert:30,usertyp:[0,6,25,33,37],usertypedoesnotexist:3,usual:[10,21,41,53],utc:[32,41],utc_datetime_from_ms_timestamp:32,utcfromtim:0,utcnow:[6,41],utctimetupl:41,utf8:0,utf8typ:0,utf:[0,6,17],util:[0,1,12,21,22,33,40,41,44,53,54],uuid1:[10,44],uuid4:[10,48],uuid:[0,6,9,10,32,37,38,40,44,48],uuid_arg:32,uuid_from_tim:[32,40],uwsgi:[43,48],uwsgidecor:[39,43],v1:[0,1,32],v2:[0,1,45],v3:[0,1,37,45],v4:[0,1,6,30],v5:[0,1],v6:1,v:[10,12,34,47,52],val1:17,val2:17,val:15,valid:[0,1,3,6,9,10,15,18,25,27,32,47,53],validationerror:[10,37,40],valu:[0,2,3,4,6,9,10,11,13,15,17,18,25,27,29,30,31,32,34,37,40,41,44,47,52,53,54,55],value2:32,value_typ:6,valueerror:[0,32],valuemap:12,values_list:[0,38],valuesequ:30,varchar:44,variabl:[0,6,9,44,46,53],variant:54,varint:[0,6,44],variou:[26,53],various:40,ve:[9,35,37,38],verb:40,verbatim:[15,18],veri:53,verif:0,verifi:0,verify_mod:53,verify_p:53,version:[0,1,2,3,6,25,29,30,31,32,37,40,44,45,46,50,54,55],vertex:[15,18,25],vertexmetadata:25,vertexproperti:[15,18],via:[0,3,37,46,50,53],view:[0,25,27,43],violat:10,virtual:[0,38],visit:45,visual:46,vnode:3,vs:[0,27],wa:[0,1,2,3,4,5,7,25,26,27,30,36,40,46,47,54],wai:[0,3,6,15,18,27,30,36,38,41,42,44,45,46,53,54],wait:[0,1,3,21,27,30,43,44,50],wait_for_all_pool:3,wait_for_complet:30,wake:21,want:[0,3,6,9,27,34,35,37,38,44,50,53,55],warn:[0,1,3,31,40,54],warn_on_drift:31,warning_interv:31,warning_threshold:31,was_appli:[0,3],watcher:21,we:[0,7,27,36,38,39,41,42,44,48,53,55],weakref:0,web_sess:50,well:[0,27,35,44,53],were:[0,1,3,4,19,25,27,30,36,37,40],what:[27,30,37,41,53,54,55],wheel:[0,46],when:[0,1,2,3,4,5,7,9,10,17,21,27,28,29,30,31,32,35,36,37,38,40,41,42,44,46,47,50,53,54,55],whenev:[3,50],where:[0,3,4,10,25,27,30,32,37,43,44,46,47,54],whether:[1,3,6,25,26,27,47,52],which:[0,1,3,9,10,25,27,29,30,34,35,36,38,40,44,46,49,53,54,55],whilst:0,whitelist:27,whitelistroundrobinpolici:[0,27,42,44,54],whitespac:25,who:27,whose:3,wider:[32,41],window:[0,32],wish:3,within:[0,1,3,10,13,27,30,34,41,42,44,54],withing:13,without:[0,1,3,9,10,38,41,44],wkt:[0,32],wno:46,won:37,word:[27,38],work:[0,2,7,17,27,30,32,37,38,44,45,47,48,52,53,55],workaround:[0,36,40],worker:[0,39],worker_process_init:39,working_keyspac:27,workload:[0,42,49],worth:46,would:[0,9,27,36,37,38,42,44,53,54],wrap:[12,15,18,27,44],wrap_socket:53,wrapper:[0,27,30],write:[0,1,8,10,15,18,26,27,30],write_request_timeout_in_m:1,write_timeout:26,write_typ:[1,27],writefailur:1,writetimeout:[0,1],writetyp:[0,1,27],written:0,wrong:[0,44],wunus:46,www:6,x509:53,x:[1,4,10,27,32,46,47],xcode:46,xrang:0,y:[0,10,27,32],yaml:[1,27],year:[10,32,35,38],year__gt:38,year__in:38,year__lt:38,yet:[3,38,44,54],yield:[4,27],you:[0,3,4,6,9,12,27,30,34,35,37,38,43,44,46,49,50,52,53,54,55],your:[0,3,6,9,35,37,38,40,43,44,47,48,49,50,53,54,55],yourself:49,yum:46,yyyi:[17,32],z:10,zero:0,zip:[54,55],zipcod:[3,11,37,54,55]},titles:["CHANGELOG","cassandra - Exceptions and Enums","cassandra.auth - Authentication","cassandra.cluster - Clusters and Sessions","cassandra.concurrent - Utilities for Concurrent Statement Execution","cassandra.connection - Low Level Connection Info","cassandra.cqlengine.columns - Column types for object mapping models","cassandra.cqlengine.connection - Connection management for cqlengine","cassandra.cqlengine.management - Schema management for cqlengine","cassandra.cqlengine.models - Table models for object mapping","cassandra.cqlengine.query - Query and filter model objects","cassandra.cqlengine.usertype - Model classes for User Defined Types","cassandra.datastax.graph.fluent","cassandra.datastax.graph.fluent.predicates","cassandra.datastax.graph.fluent.query","cassandra.datastax.graph - Graph Statements, Options, and Row Factories","cassandra.decoder - Data Return Formats","cassandra.encoder - Encoders for non-prepared Statements","cassandra.graph - Graph Statements, Options, and Row Factories","cassandra.io.asyncioreactor - asyncio Event Loop","cassandra.io.asyncorereactor - asyncore Event Loop","cassandra.io.eventletreactor - eventlet-compatible Connection","cassandra.io.geventreactor - gevent-compatible Event Loop","cassandra.io.libevreactor - libev Event Loop","cassandra.io.twistedreactor - Twisted Event Loop","cassandra.metadata - Schema and Ring Topology","cassandra.metrics - Performance Metrics","cassandra.policies - Load balancing and Failure Handling Policies","cassandra.pool - Hosts and Connection Pools","cassandra.protocol - Protocol Features","cassandra.query - Prepared Statements, Batch Statements, Tracing, and Row Factories","cassandra.timestamps - Timestamp Generation","cassandra.util - Utilities","API Documentation","Batch Queries","Connections","Frequently Asked Questions","Models","Making Queries","Third party integrations","Upgrade Guide","Working with Dates and Times","Execution Profiles","Frequently Asked Questions","Getting Started","Python Driver for Scylla and Apache Cassandra\u00ae","Installation","Lightweight Transactions (Compare-and-set)","Object Mapper","Performance Notes","Paging Large Queries","Scylla Cloud","Scylla Specific Features","Security","Upgrading","User Defined Types"],titleterms:{"0":[0,53,54],"0b1":0,"0b5":0,"0b6":0,"0b7":0,"0c1":0,"0c2":0,"0rc1":0,"1":[0,54],"10":0,"11":0,"12":0,"13":0,"14":0,"15":0,"16":[0,53],"17":0,"18":0,"19":0,"2":[0,54],"20":0,"21":0,"22":0,"23":0,"24":0,"3":[0,53,54],"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"class":[11,55],"default":[35,38,42,47,54],"do":43,"enum":1,"final":0,"float":40,"function":[38,40],"import":[40,54],"new":[35,52],"return":[16,54],No:53,access:38,ad:42,address:27,alias:40,all:38,apach:45,api:[33,40,54],applic:43,ar:[38,54],ask:[36,43],asynchron:44,asyncio:19,asyncioreactor:19,asyncor:20,asyncorereactor:20,attach:54,attribut:52,auth:2,authent:[2,53,54],automat:54,awar:52,balanc:27,base:[46,54],batch:[30,34,36,54],batchqueri:35,beta2:0,beta3:0,beta4:0,beta:0,bind:54,blist:54,bug:0,c:46,call:54,callback:[34,50],can:36,cassandra:[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,41,44,45,54],celeri:39,chang:[35,40,54],changelog:0,client:[53,54],cloud:51,cluster:[3,42,52,54],column:[6,40],compar:47,compat:[21,22],compress:46,concurr:4,configur:[46,53],connect:[5,7,21,28,35,43,44],consist:[44,54],consolid:40,content:[45,48],context:35,control:50,convers:44,copyright:45,core:33,correctli:36,cql:44,cqlengin:[6,7,8,9,10,11,40],custom:[29,53,54],cython:[46,49],data:16,datastax:[12,13,14,15,33],date:[40,41],datetyp:41,dead:27,decod:16,defin:[11,37,54,55],definit:37,delet:36,depend:[46,54],deprec:[0,40,54],deseri:29,determin:43,dict:55,dict_factori:47,dictionari:37,document:33,doe:43,don:36,doubl:40,down:27,driver:[33,43,45,54],dse:[53,54],encod:[17,54],error:46,event:[19,20,22,23,24],eventlet:[21,53],eventletreactor:21,exampl:[37,53],except:[1,40],execut:[4,34,42,44,53,54],execute_async:54,extend:37,extens:[46,49],extra:54,factori:[15,18,30],fail:27,failur:27,faster:29,featur:[0,29,52,54],field2:36,field:36,filter:[10,38],fix:0,fluent:[12,13,14],format:16,frequent:[36,43],from:[0,36,54],from_datetim:40,gener:[31,34],get:[44,45,48],gevent:22,geventreactor:22,graph:[12,13,14,15,18,33,46,54],guid:40,handl:[27,50],help:45,helper:52,host:[27,28],how:[36,43],i:[36,43],idempot:27,ident:53,ignor:54,immut:38,individu:36,info:5,inform:54,inherit:[37,40],initi:42,instal:[46,54],instanc:[35,37,42],instanti:36,integr:39,io:[19,20,21,22,23,24,43],issu:45,larg:50,legaci:42,level:[5,40,44,54],libev:[23,46],libevreactor:23,lightweight:[47,54],list:[38,40],load:27,local_on:54,log:34,login:53,loop:[19,20,22,23,24],low:5,lower:53,make:38,manag:[7,8,35,40,43],manipul:37,manual:46,map:[6,9,42,55],mapper:[33,48],mark:27,merg:0,metadata:[25,54],metric:[26,46],model:[6,9,10,11,35,36,37,40],modul:54,multiprocess:49,my:43,name:[38,42,54],named_tuple_factori:47,nativ:54,node:27,non:[17,46,54],normal:54,note:[46,49],now:54,object:[6,9,10,33,38,48],oper:[27,38,43],option:[15,18,46],order:[36,38],organ:40,osx:46,other:0,overload:40,packag:40,page:[50,54],paramet:[42,44,54],parti:39,pass:[42,44],path:41,pattern:34,payload:29,per:38,perform:[26,49],pip:46,platform:46,polici:27,pool:28,predic:13,prepar:[17,30,44,54],prepend:40,preserv:36,profil:42,protocol:[29,53,54],proxi:53,pypi:49,python:[45,46],queri:[10,14,30,34,36,38,43,44,50,54],queryset:[10,35,38],question:[36,43],read:41,reconnect:27,regist:[35,55],remov:[40,54],replica:43,report:45,request:43,result:[47,50,54],resum:50,retri:[27,43],retriev:38,revers:40,ring:25,row:[15,18,30,36],sasl:54,schema:[8,25,40],scylla:[45,51,52],secur:53,select:35,server:[27,53],session:[3,54],set:[44,47],sever:54,shard:52,shutdown:54,side:54,size:50,soft:54,special:47,specif:52,specul:44,speed:46,ssl:[46,53],start:[44,48],statement:[4,15,17,18,30,44,54],support:46,t:36,tabl:[9,38,52],them:55,third:39,through:46,time:41,timeout:[38,43],timestamp:[31,41,54],timeuuid:[38,40],token:[25,38],topolog:25,trace:[30,43,54],transact:[47,54],translat:27,ttl:38,tuple_factori:47,twist:[24,53],twistedreactor:24,type:[6,11,37,40,44,54,55],udt:55,unicodemixin:40,unifi:53,unlog:34,unregist:35,up:[27,46],updat:[36,54],upgrad:[0,40,54],us:[34,42,54,55],user:[11,37,54,55],usertyp:11,util:[4,32],uwsgi:39,v1:53,v2:54,v3:54,valid:37,valu:[36,38],value2:36,verif:53,verifi:[46,53],version:53,vs:34,why:[36,43],window:46,without:[42,55],work:[36,41,54],write:41,wsgi:43,x:[0,54],your:46}}) \ No newline at end of file diff --git a/3.24.8-scylla/security.html b/3.24.8-scylla/security.html new file mode 100644 index 0000000000..89ddcaf37c --- /dev/null +++ b/3.24.8-scylla/security.html @@ -0,0 +1,1029 @@ + + + + + + + + + + + + + Security | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

Security

+

The two main security components you will use with the +Python driver are Authentication and SSL.

+
+

Authentication

+

Versions 2.0 and higher of the driver support a SASL-based +authentication mechanism when protocol_version +is set to 2 or higher. To use this authentication, set +auth_provider to an instance of a subclass +of AuthProvider. When working +with Cassandra’s PasswordAuthenticator, you can use +the PlainTextAuthProvider class.

+

For example, suppose Cassandra is setup with its default +‘cassandra’ user with a password of ‘cassandra’:

+
from cassandra.cluster import Cluster
+from cassandra.auth import PlainTextAuthProvider
+
+auth_provider = PlainTextAuthProvider(username='cassandra', password='cassandra')
+cluster = Cluster(auth_provider=auth_provider, protocol_version=2)
+
+
+
+

Custom Authenticators

+

If you’re using something other than Cassandra’s PasswordAuthenticator, +SaslAuthProvider is provided for generic SASL authentication mechanisms, +utilizing the pure-sasl package. +If these do not suit your needs, you may need to create your own subclasses of +AuthProvider and Authenticator. You can use the Sasl classes +as example implementations.

+
+
+

Protocol v1 Authentication

+

When working with Cassandra 1.2 (or a higher version with +protocol_version set to 1), you will not pass in +an AuthProvider instance. Instead, you should pass in a +function that takes one argument, the IP address of a host, and returns +a dict of credentials with a username and password key:

+
from cassandra.cluster import Cluster
+
+def get_credentials(host_address):
+    return {'username': 'joe', 'password': '1234'}
+
+cluster = Cluster(auth_provider=get_credentials, protocol_version=1)
+
+
+
+
+
+

SSL

+

SSL should be used when client encryption is enabled in Cassandra.

+

To give you as much control as possible over your SSL configuration, our SSL +API takes a user-created SSLContext instance from the Python standard library. +These docs will include some examples for how to achieve common configurations, +but the ssl.SSLContext documentation +gives a more complete description of what is possible.

+

To enable SSL with version 3.17.0 and higher, you will need to set Cluster.ssl_context to a +ssl.SSLContext instance to enable SSL. Optionally, you can also set Cluster.ssl_options +to a dict of options. These will be passed as kwargs to ssl.SSLContext.wrap_socket() +when new sockets are created.

+

If you create your SSLContext using ssl.create_default_context, +be aware that SSLContext.check_hostname is set to True by default, so the hostname validation will be done +by Python and not the driver. For this reason, we need to set the server_hostname at best effort, which is the +resolved ip address. If this validation needs to be done against the FQDN, consider enabling it using the ssl_options +as described in the following examples or implement your own EndPoint and +EndPointFactory.

+

The following examples assume you have generated your Cassandra certificate and +keystore files with these intructions:

+ +

It might be also useful to learn about the different levels of identity verification to understand the examples:

+ +
+

SSL with Twisted or Eventlet

+

Twisted and Eventlet both use an alternative SSL implementation called pyOpenSSL, so if your Cluster’s connection class is +TwistedConnection or EventletConnection, you must pass a +pyOpenSSL context instead. +An example is provided in these docs, and more details can be found in the +documentation. +pyOpenSSL is not installed by the driver and must be installed separately.

+
+
+

SSL Configuration Examples

+

Here, we’ll describe the server and driver configuration necessary to set up SSL to meet various goals, such as the client verifying the server and the server verifying the client. We’ll also include Python code demonstrating how to use servers and drivers configured in these ways.

+
+

No identity verification

+

No identity verification at all. Note that this is not recommended for for production deployments.

+

The Cassandra configuration:

+
client_encryption_options:
+  enabled: true
+  keystore: /path/to/127.0.0.1.keystore
+  keystore_password: myStorePass
+  require_client_auth: false
+
+
+

The driver configuration:

+
from cassandra.cluster import Cluster, Session
+from ssl import SSLContext, PROTOCOL_TLSv1
+
+ssl_context = SSLContext(PROTOCOL_TLSv1)
+
+cluster = Cluster(['127.0.0.1'], ssl_context=ssl_context)
+session = cluster.connect()
+
+
+
+
+

Client verifies server

+

Ensure the python driver verifies the identity of the server.

+

The Cassandra configuration:

+
client_encryption_options:
+  enabled: true
+  keystore: /path/to/127.0.0.1.keystore
+  keystore_password: myStorePass
+  require_client_auth: false
+
+
+

For the driver configuration, it’s very important to set ssl_context.verify_mode +to CERT_REQUIRED. Otherwise, the loaded verify certificate will have no effect:

+
from cassandra.cluster import Cluster, Session
+from ssl import SSLContext, PROTOCOL_TLSv1, CERT_REQUIRED
+
+ssl_context = SSLContext(PROTOCOL_TLSv1)
+ssl_context.load_verify_locations('/path/to/rootca.crt')
+ssl_context.verify_mode = CERT_REQUIRED
+
+cluster = Cluster(['127.0.0.1'], ssl_context=ssl_context)
+session = cluster.connect()
+
+
+

Additionally, you can also force the driver to verify the hostname of the server by passing additional options to ssl_context.wrap_socket via the ssl_options kwarg:

+
from cassandra.cluster import Cluster, Session
+from ssl import SSLContext, PROTOCOL_TLSv1, CERT_REQUIRED
+
+ssl_context = SSLContext(PROTOCOL_TLSv1)
+ssl_context.load_verify_locations('/path/to/rootca.crt')
+ssl_context.verify_mode = CERT_REQUIRED
+ssl_context.check_hostname = True
+ssl_options = {'server_hostname': '127.0.0.1'}
+
+cluster = Cluster(['127.0.0.1'], ssl_context=ssl_context, ssl_options=ssl_options)
+session = cluster.connect()
+
+
+
+
+

Server verifies client

+

If Cassandra is configured to verify clients (require_client_auth), you need to generate +SSL key and certificate files.

+

The cassandra configuration:

+
client_encryption_options:
+  enabled: true
+  keystore: /path/to/127.0.0.1.keystore
+  keystore_password: myStorePass
+  require_client_auth: true
+  truststore: /path/to/dse-truststore.jks
+  truststore_password: myStorePass
+
+
+

The Python ssl APIs require the certificate in PEM format. First, create a certificate +conf file:

+
cat > gen_client_cert.conf <<EOF
+[ req ]
+distinguished_name = req_distinguished_name
+prompt = no
+output_password = ${ROOT_CERT_PASS}
+default_bits = 2048
+
+[ req_distinguished_name ]
+C = ${CERT_COUNTRY}
+O = ${CERT_ORG_NAME}
+OU = ${CERT_OU}
+CN = client
+EOF
+
+
+

Make sure you replaced the variables with the same values you used for the initial +root CA certificate. Then, generate the key:

+
openssl req -newkey rsa:2048 -nodes -keyout client.key -out client.csr -config gen_client_cert.conf
+
+
+

And generate the client signed certificate:

+
openssl x509 -req -CA ${ROOT_CA_BASE_NAME}.crt -CAkey ${ROOT_CA_BASE_NAME}.key -passin pass:${ROOT_CERT_PASS} \
+    -in client.csr -out client.crt_signed -days ${CERT_VALIDITY} -CAcreateserial
+
+
+

Finally, you can use that configuration with the following driver code:

+
from cassandra.cluster import Cluster, Session
+from ssl import SSLContext, PROTOCOL_TLSv1
+
+ssl_context = SSLContext(PROTOCOL_TLSv1)
+ssl_context.load_cert_chain(
+    certfile='/path/to/client.crt_signed',
+    keyfile='/path/to/client.key')
+
+cluster = Cluster(['127.0.0.1'], ssl_context=ssl_context)
+session = cluster.connect()
+
+
+
+
+

Server verifies client and client verifies server

+

See the previous section for examples of Cassandra configuration and preparing +the client certificates.

+

The following driver code specifies that the connection should use two-way verification:

+
from cassandra.cluster import Cluster, Session
+from ssl import SSLContext, PROTOCOL_TLSv1, CERT_REQUIRED
+
+ssl_context = SSLContext(PROTOCOL_TLSv1)
+ssl_context.load_verify_locations('/path/to/rootca.crt')
+ssl_context.verify_mode = CERT_REQUIRED
+ssl_context.load_cert_chain(
+    certfile='/path/to/client.crt_signed',
+    keyfile='/path/to/client.key')
+
+cluster = Cluster(['127.0.0.1'], ssl_context=ssl_context)
+session = cluster.connect()
+
+
+

The driver uses SSLContext directly to give you many other options in configuring SSL. Consider reading the Python SSL documentation +for more details about SSLContext configuration.

+

Server verifies client and client verifies server using Twisted and pyOpenSSL

+
from OpenSSL import SSL, crypto
+from cassandra.cluster import Cluster
+from cassandra.io.twistedreactor import TwistedConnection
+
+ssl_context = SSL.Context(SSL.TLSv1_METHOD)
+ssl_context.set_verify(SSL.VERIFY_PEER, callback=lambda _1, _2, _3, _4, ok: ok)
+ssl_context.use_certificate_file('/path/to/client.crt_signed')
+ssl_context.use_privatekey_file('/path/to/client.key')
+ssl_context.load_verify_locations('/path/to/rootca.crt')
+
+cluster = Cluster(
+    contact_points=['127.0.0.1'],
+    connection_class=TwistedConnection,
+    ssl_context=ssl_context,
+    ssl_options={'check_hostname': True}
+)
+session = cluster.connect()
+
+
+

Connecting using Eventlet would look similar except instead of importing and using TwistedConnection, you would +import and use EventletConnection, including the appropriate monkey-patching.

+
+
+
+

Versions 3.16.0 and lower

+

To enable SSL you will need to set Cluster.ssl_options to a +dict of options. These will be passed as kwargs to ssl.wrap_socket() +when new sockets are created. Note that this use of ssl_options will be +deprecated in the next major release.

+

By default, a ca_certs value should be supplied (the value should be +a string pointing to the location of the CA certs file), and you probably +want to specify ssl_version as ssl.PROTOCOL_TLSv1 to match +Cassandra’s default protocol.

+

For example:

+
from cassandra.cluster import Cluster
+from ssl import PROTOCOL_TLSv1, CERT_REQUIRED
+
+ssl_opts = {
+    'ca_certs': '/path/to/my/ca.certs',
+    'ssl_version': PROTOCOL_TLSv1,
+    'cert_reqs': CERT_REQUIRED  # Certificates are required and validated
+}
+cluster = Cluster(ssl_options=ssl_opts)
+
+
+

This is only an example to show how to pass the ssl parameters. Consider reading +the python ssl documentation for +your configuration. For further reading, Andrew Mussey has published a thorough guide on +Using SSL with the DataStax Python driver.

+
+

SSL with Twisted

+

In case the twisted event loop is used pyOpenSSL must be installed or an exception will be risen. Also +to set the ssl_version and cert_reqs in ssl_opts the appropriate constants from pyOpenSSL are expected.

+
+
+
+
+

DSE Authentication

+

When authenticating against DSE, the Cassandra driver provides two auth providers that work both with legacy kerberos and Cassandra authenticators, +as well as the new DSE Unified Authentication. This allows client to configure this auth provider independently, +and in advance of any server upgrade. These auth providers are configured in the same way as any previous implementation:

+
from cassandra.auth import DSEGSSAPIAuthProvider
+auth_provider = DSEGSSAPIAuthProvider(service='dse', qops=["auth"])
+cluster = Cluster(auth_provider=auth_provider)
+session = cluster.connect()
+
+
+

Implementations are DSEPlainTextAuthProvider, DSEGSSAPIAuthProvider and SaslAuthProvider.

+
+

DSE Unified Authentication

+

With DSE (>=5.1), unified Authentication allows you to:

+
    +
  • Proxy Login: Authenticate using a fixed set of authentication credentials but allow authorization of resources based another user id.

  • +
  • Proxy Execute: Authenticate using a fixed set of authentication credentials but execute requests based on another user id.

  • +
+
+

Proxy Login

+

Proxy login allows you to authenticate with a user but act as another one. You need to ensure the authenticated user has the permission to use the authorization of resources of the other user. ie. this example will allow the server user to authenticate as usual but use the authorization of user1:

+
GRANT PROXY.LOGIN on role user1 to server
+
+
+

then you can do the proxy authentication….

+
from cassandra.cluster import Cluster
+from cassandra.auth import SaslAuthProvider
+
+sasl_kwargs = {
+  "service": 'dse',
+  "mechanism":"PLAIN",
+  "username": 'server',
+  'password': 'server',
+  'authorization_id': 'user1'
+}
+
+auth_provider = SaslAuthProvider(**sasl_kwargs)
+c = Cluster(auth_provider=auth_provider)
+s = c.connect()
+s.execute(...)  # all requests will be executed as 'user1'
+
+
+

If you are using kerberos, you can use directly DSEGSSAPIAuthProvider and pass the authorization_id, like this:

+
from cassandra.cluster import Cluster
+from cassandra.auth import DSEGSSAPIAuthProvider
+
+# Ensure the kerberos ticket of the server user is set with the kinit utility.
+auth_provider = DSEGSSAPIAuthProvider(service='dse', qops=["auth"], principal="server@DATASTAX.COM",
+                                      authorization_id='user1@DATASTAX.COM')
+c = Cluster(auth_provider=auth_provider)
+s = c.connect()
+s.execute(...)  # all requests will be executed as 'user1'
+
+
+
+
+

Proxy Execute

+

Proxy execute allows you to execute requests as another user than the authenticated one. You need to ensure the authenticated user has the permission to use the authorization of resources of the specified user. ie. this example will allow the server user to execute requests as user1:

+
GRANT PROXY.EXECUTE on role user1 to server
+
+
+

then you can do a proxy execute…

+
from cassandra.cluster import Cluster
+from cassandra.auth import DSEPlainTextAuthProvider,
+
+auth_provider = DSEPlainTextAuthProvider('server', 'server')
+
+c = Cluster(auth_provider=auth_provider)
+s = c.connect()
+s.execute('select * from k.t;', execute_as='user1')  # the request will be executed as 'user1'
+
+
+

Please see the official documentation for more details on the feature and configuration process.

+
+
+
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.24.8-scylla/sitemap.xml b/3.24.8-scylla/sitemap.xml new file mode 100644 index 0000000000..f03cce40f2 --- /dev/null +++ b/3.24.8-scylla/sitemap.xml @@ -0,0 +1,2 @@ + +https://python-driver.docs.scylladb.com/stable/CHANGELOG.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/auth.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/cluster.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/concurrent.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/connection.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/cqlengine/columns.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/cqlengine/connection.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/cqlengine/management.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/cqlengine/models.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/cqlengine/query.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/cqlengine/usertype.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/datastax/graph/fluent/index.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/datastax/graph/fluent/predicates.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/datastax/graph/fluent/query.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/datastax/graph/index.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/decoder.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/encoder.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/graph.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/io/asyncioreactor.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/io/asyncorereactor.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/io/eventletreactor.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/io/geventreactor.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/io/libevreactor.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/io/twistedreactor.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/metadata.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/metrics.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/policies.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/pool.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/protocol.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/query.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/timestamps.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/util.htmlhttps://python-driver.docs.scylladb.com/stable/api/index.htmlhttps://python-driver.docs.scylladb.com/stable/cqlengine/batches.htmlhttps://python-driver.docs.scylladb.com/stable/cqlengine/connections.htmlhttps://python-driver.docs.scylladb.com/stable/cqlengine/faq.htmlhttps://python-driver.docs.scylladb.com/stable/cqlengine/models.htmlhttps://python-driver.docs.scylladb.com/stable/cqlengine/queryset.htmlhttps://python-driver.docs.scylladb.com/stable/cqlengine/third_party.htmlhttps://python-driver.docs.scylladb.com/stable/cqlengine/upgrade_guide.htmlhttps://python-driver.docs.scylladb.com/stable/dates_and_times.htmlhttps://python-driver.docs.scylladb.com/stable/execution_profiles.htmlhttps://python-driver.docs.scylladb.com/stable/faq.htmlhttps://python-driver.docs.scylladb.com/stable/getting_started.htmlhttps://python-driver.docs.scylladb.com/stable/index.htmlhttps://python-driver.docs.scylladb.com/stable/installation.htmlhttps://python-driver.docs.scylladb.com/stable/lwt.htmlhttps://python-driver.docs.scylladb.com/stable/object_mapper.htmlhttps://python-driver.docs.scylladb.com/stable/performance.htmlhttps://python-driver.docs.scylladb.com/stable/query_paging.htmlhttps://python-driver.docs.scylladb.com/stable/scylla_cloud.htmlhttps://python-driver.docs.scylladb.com/stable/scylla_specific.htmlhttps://python-driver.docs.scylladb.com/stable/security.htmlhttps://python-driver.docs.scylladb.com/stable/upgrading.htmlhttps://python-driver.docs.scylladb.com/stable/user_defined_types.htmlhttps://python-driver.docs.scylladb.com/stable/py-modindex.htmlhttps://python-driver.docs.scylladb.com/stable/404.htmlhttps://python-driver.docs.scylladb.com/stable/search.html \ No newline at end of file diff --git a/3.24.8-scylla/upgrading.html b/3.24.8-scylla/upgrading.html new file mode 100644 index 0000000000..d00cb8d050 --- /dev/null +++ b/3.24.8-scylla/upgrading.html @@ -0,0 +1,1028 @@ + + + + + + + + + + + + + Upgrading | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

Upgrading

+
+
+
+

Upgrading from dse-driver

+

Since 3.21.0, scylla-driver fully supports DataStax products. dse-driver and +dse-graph users should now migrate to scylla-driver to benefit from latest bug fixes +and new features. The upgrade to this new unified driver version is straightforward +with no major API changes.

+
+

Installation

+

Only the scylla-driver package should be installed. dse-driver and dse-graph +are not required anymore:

+
pip install scylla-driver
+
+
+

If you need the Graph Fluent API (features provided by dse-graph):

+
pip install scylla-driver[graph]
+
+
+

See Installation for more details.

+
+
+

Import from the cassandra module

+

There is no dse module, so you should import from the cassandra module. You +need to change only the first module of your import statements, not the submodules.

+
from dse.cluster import Cluster, EXEC_PROFILE_GRAPH_DEFAULT
+from dse.auth import PlainTextAuthProvider
+from dse.policies import WhiteListRoundRobinPolicy
+
+# becomes
+
+from cassandra.cluster import Cluster, EXEC_PROFILE_GRAPH_DEFAULT
+from cassandra.auth import PlainTextAuthProvider
+from cassandra.policies import WhiteListRoundRobinPolicy
+
+
+

Also note that the cassandra.hosts module doesn’t exist in scylla-driver. This +module is named cassandra.pool.

+
+
+

dse-graph

+

dse-graph features are now built into scylla-driver. The only change you need +to do is your import statements:

+
from dse_graph import ..
+from dse_graph.query import ..
+
+# becomes
+
+from cassandra.datastax.graph.fluent import ..
+from cassandra.datastax.graph.fluent.query import ..
+
+
+

See fluent.

+
+
+

Session.execute and Session.execute_async API

+

Although it is not common to use this API with positional arguments, it is +important to be aware that the host and execute_as parameters have had +their positional order swapped. This is only because execute_as was added +in dse-driver before host.

+

See Session.execute().

+
+
+

Deprecations

+

These changes are optional, but recommended:

+
    +
  • Importing from cassandra.graph is deprecated. Consider importing from cassandra.datastax.graph.

  • +
  • Use DefaultLoadBalancingPolicy instead of DSELoadBalancingPolicy.

  • +
+
+
+
+

Upgrading to 3.0

+

Version 3.0 of the DataStax Python driver for Apache Cassandra +adds support for Cassandra 3.0 while maintaining support for +previously supported versions. In addition to substantial internal rework, +there are several updates to the API that integrators will need +to consider:

+
+

Default consistency is now LOCAL_ONE

+

Previous value was ONE. The new value is introduced to mesh with the default +DC-aware load balancing policy and to match other drivers.

+
+
+

Execution API Updates

+
+

Result return normalization

+

PYTHON-368

+

Previously results would be returned as a list of rows for result rows +up to fetch_size, and PagedResult afterward. This could break +application code that assumed one type and got another.

+

Now, all results are returned as an iterable ResultSet.

+

The preferred way to consume results of unknown size is to iterate through +them, letting automatic paging occur as they are consumed.

+
results = session.execute("SELECT * FROM system.local")
+for row in results:
+    process(row)
+
+
+

If the expected size of the results is known, it is still possible to +materialize a list using the iterator:

+
results = session.execute("SELECT * FROM system.local")
+row_list = list(results)
+
+
+

For backward compatibility, ResultSet supports indexing. When +accessed at an index, a ~.ResultSet object will materialize all its pages:

+
results = session.execute("SELECT * FROM system.local")
+first_result = results[0]  # materializes results, fetching all pages
+
+
+

This can send requests and load (possibly large) results into memory, so +~.ResultSet will log a warning on implicit materialization.

+
+
+

Trace information is not attached to executed Statements

+

PYTHON-318

+

Previously trace data was attached to Statements if tracing was enabled. This +could lead to confusion if the same statement was used for multiple executions.

+

Now, trace data is associated with the ResponseFuture and ResultSet +returned for each query:

+

ResponseFuture.get_query_trace()

+

ResponseFuture.get_all_query_traces()

+

ResultSet.get_query_trace()

+

ResultSet.get_all_query_traces()

+
+
+

Binding named parameters now ignores extra names

+

PYTHON-178

+

Previously, BoundStatement.bind() would raise if a mapping +was passed with extra names not found in the prepared statement.

+

Behavior in 3.0+ is to ignore extra names.

+
+
+
+

blist removed as soft dependency

+

PYTHON-385

+

Previously the driver had a soft dependency on blist sortedset, using +that where available and using an internal fallback where possible.

+

Now, the driver never chooses the blist variant, instead returning the +internal util.SortedSet for all set results. The class implements +all standard set operations, so no integration code should need to change unless +it explicitly checks for sortedset type.

+
+
+

Metadata API Updates

+

PYTHON-276, PYTHON-408, PYTHON-400, PYTHON-422

+

Cassandra 3.0 brought a substantial overhaul to the internal schema metadata representation. +This version of the driver supports that metadata in addition to the legacy version. Doing so +also brought some changes to the metadata model.

+

The present API is documented: cassandra.metadata. Changes highlighted below:

+
    +
  • All types are now exposed as CQL types instead of types derived from the internal server implementation

  • +
  • Some metadata attributes have changed names to match current nomenclature (for example, Index.kind in place of Index.type).

  • +
  • Some metadata attributes removed

    +
      +
    • TableMetadata.keyspace reference replaced with TableMetadata.keyspace_name

    • +
    • ColumnMetadata.index is removed table- and keyspace-level mappings are still maintained

    • +
    +
  • +
+
+
+

Several deprecated features are removed

+

PYTHON-292

+
    +
  • ResponseFuture.result timeout parameter is removed, use Session.execute timeout instead (031ebb0)

  • +
  • Cluster.refresh_schema removed, use Cluster.refresh_*_metadata instead (419fcdf)

  • +
  • Cluster.submit_schema_refresh removed (574266d)

  • +
  • cqltypes time/date functions removed, use util entry points instead (bb984ee)

  • +
  • decoder module removed (e16a073)

  • +
  • TableMetadata.keyspace attribute replaced with keyspace_name (cc94073)

  • +
  • cqlengine.columns.TimeUUID.from_datetime removed, use util variant instead (96489cc)

  • +
  • cqlengine.columns.Float(double_precision) parameter removed, use columns.Double instead (a2d3a98)

  • +
  • cqlengine keyspace management functions are removed in favor of the strategy-specific entry points (4bd5909)

  • +
  • cqlengine.Model.__polymorphic_*__ attributes removed, use __discriminator* attributes instead (9d98c8e)

  • +
  • cqlengine.statements will no longer warn about list list prepend behavior (79efe97)

  • +
+
+
+
+

Upgrading to 2.1 from 2.0

+

Version 2.1 of the DataStax Python driver for Apache Cassandra +adds support for Cassandra 2.1 and version 3 of the native protocol.

+

Cassandra 1.2, 2.0, and 2.1 are all supported. However, 1.2 only +supports protocol version 1, and 2.0 only supports versions 1 and +2, so some features may not be available.

+
+

Using the v3 Native Protocol

+

By default, the driver will attempt to use version 2 of the +native protocol. To use version 3, you must explicitly +set the protocol_version:

+
from cassandra.cluster import Cluster
+
+cluster = Cluster(protocol_version=3)
+
+
+

Note that protocol version 3 is only supported by Cassandra 2.1+.

+

In future releases, the driver may default to using protocol version +3.

+
+
+

Working with User-Defined Types

+

Cassandra 2.1 introduced the ability to define new types:

+
USE KEYSPACE mykeyspace;
+
+CREATE TYPE address (street text, city text, zip int);
+
+
+

The driver generally expects you to use instances of a specific +class to represent column values of this type. You can let the +driver know what class to use with Cluster.register_user_type():

+
cluster = Cluster()
+
+class Address(object):
+
+    def __init__(self, street, city, zipcode):
+        self.street = street
+        self.city = text
+        self.zipcode = zipcode
+
+cluster.register_user_type('mykeyspace', 'address', Address)
+
+
+

When inserting data for address columns, you should pass in +instances of Address. When querying data, address column +values will be instances of Address.

+

If no class is registered for a user-defined type, query results +will use a namedtuple class and data may only be inserted +though prepared statements.

+

See User Defined Types for more details.

+
+
+

Customizing Encoders for Non-prepared Statements

+

Starting with version 2.1 of the driver, it is possible to customize +how Python types are converted to CQL literals when working with +non-prepared statements. This is done on a per-Session +basis through Session.encoder:

+
cluster = Cluster()
+session = cluster.connect()
+session.encoder.mapping[tuple] = session.encoder.cql_encode_tuple
+
+
+

See Type Conversions for the table of default CQL literal conversions.

+
+
+

Using Client-Side Protocol-Level Timestamps

+

With version 3 of the native protocol, timestamps may be supplied by the +client at the protocol level. (Normally, if they are not specified within +the CQL query itself, a timestamp is generated server-side.)

+

When protocol_version is set to 3 or higher, the driver +will automatically use client-side timestamps with microsecond precision +unless Session.use_client_timestamp is changed to False. +If a timestamp is specified within the CQL query, it will override the +timestamp generated by the driver.

+
+
+
+

Upgrading to 2.0 from 1.x

+

Version 2.0 of the DataStax Python driver for Apache Cassandra +includes some notable improvements over version 1.x. This version +of the driver supports Cassandra 1.2, 2.0, and 2.1. However, not +all features may be used with Cassandra 1.2, and some new features +in 2.1 are not yet supported.

+
+

Using the v2 Native Protocol

+

By default, the driver will attempt to use version 2 of Cassandra’s +native protocol. You can explicitly set the protocol version to +2, though:

+
from cassandra.cluster import Cluster
+
+cluster = Cluster(protocol_version=2)
+
+
+

When working with Cassandra 1.2, you will need to +explicitly set the protocol_version to 1:

+
from cassandra.cluster import Cluster
+
+cluster = Cluster(protocol_version=1)
+
+
+
+
+

Automatic Query Paging

+

Version 2 of the native protocol adds support for automatic query +paging, which can make dealing with large result sets much simpler.

+

See Paging Large Queries for full details.

+
+
+

Protocol-Level Batch Statements

+

With version 1 of the native protocol, batching of statements required +using a BATCH cql query. +With version 2 of the native protocol, you can now batch statements at +the protocol level. This allows you to use many different prepared +statements within a single batch.

+

See BatchStatement for details and usage examples.

+
+
+

SASL-based Authentication

+

Also new in version 2 of the native protocol is SASL-based authentication. +See the section on Security for details and examples.

+
+
+

Lightweight Transactions

+

Lightweight transactions are another new feature. To use lightweight transactions, add IF clauses +to your CQL queries and set the serial_consistency_level +on your statements.

+
+
+

Calling Cluster.shutdown()

+

In order to fix some issues around garbage collection and unclean interpreter +shutdowns, version 2.0 of the driver requires you to call Cluster.shutdown() +on your Cluster objects when you are through with them. +This helps to guarantee a clean shutdown.

+
+
+

Deprecations

+

The following functions have moved from cassandra.decoder to cassandra.query. +The original functions have been left in place with a DeprecationWarning for +now:

+ +
+
+

Dependency Changes

+

The following dependencies have officially been made optional:

+
    +
  • scales

  • +
  • blist

  • +
+

And one new dependency has been added (to enable Python 3 support):

+
    +
  • six

  • +
+
+
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.24.8-scylla/user_defined_types.html b/3.24.8-scylla/user_defined_types.html new file mode 100644 index 0000000000..26c5b6c4e5 --- /dev/null +++ b/3.24.8-scylla/user_defined_types.html @@ -0,0 +1,758 @@ + + + + + + + + + + + + + User Defined Types | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

User Defined Types

+

Cassandra 2.1 introduced user-defined types (UDTs). You can create a +new type through CREATE TYPE statements in CQL:

+
CREATE TYPE address (street text, zip int);
+
+
+

Version 2.1 of the Python driver adds support for user-defined types.

+
+

Registering a UDT

+

You can tell the Python driver to return columns of a specific UDT as +instances of a class or a dict by registering them with your Cluster +instance through Cluster.register_user_type():

+
+

Map a Class to a UDT

+
cluster = Cluster(protocol_version=3)
+session = cluster.connect()
+session.set_keyspace('mykeyspace')
+session.execute("CREATE TYPE address (street text, zipcode int)")
+session.execute("CREATE TABLE users (id int PRIMARY KEY, location frozen<address>)")
+
+# create a class to map to the "address" UDT
+class Address(object):
+
+    def __init__(self, street, zipcode):
+        self.street = street
+        self.zipcode = zipcode
+
+cluster.register_user_type('mykeyspace', 'address', Address)
+
+# insert a row using an instance of Address
+session.execute("INSERT INTO users (id, location) VALUES (%s, %s)",
+                (0, Address("123 Main St.", 78723)))
+
+# results will include Address instances
+results = session.execute("SELECT * FROM users")
+row = results[0]
+print(row.id, row.location.street, row.location.zipcode)
+
+
+
+
+

Map a dict to a UDT

+
cluster = Cluster(protocol_version=3)
+session = cluster.connect()
+session.set_keyspace('mykeyspace')
+session.execute("CREATE TYPE address (street text, zipcode int)")
+session.execute("CREATE TABLE users (id int PRIMARY KEY, location frozen<address>)")
+
+cluster.register_user_type('mykeyspace', 'address', dict)
+
+# insert a row using a prepared statement and a tuple
+insert_statement = session.prepare("INSERT INTO mykeyspace.users (id, location) VALUES (?, ?)")
+session.execute(insert_statement, [0, ("123 Main St.", 78723)])
+
+# results will include dict instances
+results = session.execute("SELECT * FROM users")
+row = results[0]
+print(row.id, row.location['street'], row.location['zipcode'])
+
+
+
+
+
+

Using UDTs Without Registering Them

+

Although it is recommended to register your types with +Cluster.register_user_type(), the driver gives you some options +for working with unregistered UDTS.

+

When you use prepared statements, the driver knows what data types to +expect for each placeholder. This allows you to pass any object you +want for a UDT, as long as it has attributes that match the field names +for the UDT:

+
cluster = Cluster(protocol_version=3)
+session = cluster.connect()
+session.set_keyspace('mykeyspace')
+session.execute("CREATE TYPE address (street text, zipcode int)")
+session.execute("CREATE TABLE users (id int PRIMARY KEY, location frozen<address>)")
+
+class Foo(object):
+
+    def __init__(self, street, zipcode, otherstuff):
+        self.street = street
+        self.zipcode = zipcode
+        self.otherstuff = otherstuff
+
+insert_statement = session.prepare("INSERT INTO users (id, location) VALUES (?, ?)")
+
+# since we're using a prepared statement, we don't *have* to register
+# a class to map to the UDT to insert data.  The object just needs to have
+# "street" and "zipcode" attributes (which Foo does):
+session.execute(insert_statement, [0, Foo("123 Main St.", 78723, "some other stuff")])
+
+# when we query data, UDT columns that don't have a class registered
+# will be returned as namedtuples:
+results = session.execute("SELECT * FROM users")
+first_row = results[0]
+address = first_row.location
+print(address)  # prints "Address(street='123 Main St.', zipcode=78723)"
+street = address.street
+zipcode = address.street
+
+
+

As shown in the code example, inserting data for UDT columns without registering +a class works fine for prepared statements. However, you must register a +class to insert UDT columns with unprepared statements.* You can still query +UDT columns without registered classes using unprepared statements, they will +simply return namedtuple instances (just like prepared statements do).

+

* this applies to parameterized unprepared statements, in which the driver will be formatting parameters – not statements with interpolated UDT literals.

+
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.25.11-scylla/.buildinfo b/3.25.11-scylla/.buildinfo new file mode 100644 index 0000000000..c90b789fb3 --- /dev/null +++ b/3.25.11-scylla/.buildinfo @@ -0,0 +1,4 @@ +# Sphinx build info version 1 +# This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done. +config: bac531fd68ea0d61267faeb5555727af +tags: 645f666f9bcd5a90fca523b33c5a78b7 diff --git a/3.25.11-scylla/.doctrees/CHANGELOG.doctree b/3.25.11-scylla/.doctrees/CHANGELOG.doctree new file mode 100644 index 0000000000..183de77529 Binary files /dev/null and b/3.25.11-scylla/.doctrees/CHANGELOG.doctree differ diff --git a/3.25.11-scylla/.doctrees/api/cassandra.doctree b/3.25.11-scylla/.doctrees/api/cassandra.doctree new file mode 100644 index 0000000000..82ddb4993b Binary files /dev/null and b/3.25.11-scylla/.doctrees/api/cassandra.doctree differ diff --git a/3.25.11-scylla/.doctrees/api/cassandra/auth.doctree b/3.25.11-scylla/.doctrees/api/cassandra/auth.doctree new file mode 100644 index 0000000000..48c980752b Binary files /dev/null and b/3.25.11-scylla/.doctrees/api/cassandra/auth.doctree differ diff --git a/3.25.11-scylla/.doctrees/api/cassandra/cluster.doctree b/3.25.11-scylla/.doctrees/api/cassandra/cluster.doctree new file mode 100644 index 0000000000..7e4ecd4524 Binary files /dev/null and b/3.25.11-scylla/.doctrees/api/cassandra/cluster.doctree differ diff --git a/3.25.11-scylla/.doctrees/api/cassandra/concurrent.doctree b/3.25.11-scylla/.doctrees/api/cassandra/concurrent.doctree new file mode 100644 index 0000000000..e3f8d8b110 Binary files /dev/null and b/3.25.11-scylla/.doctrees/api/cassandra/concurrent.doctree differ diff --git a/3.25.11-scylla/.doctrees/api/cassandra/connection.doctree b/3.25.11-scylla/.doctrees/api/cassandra/connection.doctree new file mode 100644 index 0000000000..8c94bf2d86 Binary files /dev/null and b/3.25.11-scylla/.doctrees/api/cassandra/connection.doctree differ diff --git a/3.25.11-scylla/.doctrees/api/cassandra/cqlengine/columns.doctree b/3.25.11-scylla/.doctrees/api/cassandra/cqlengine/columns.doctree new file mode 100644 index 0000000000..97616c010d Binary files /dev/null and b/3.25.11-scylla/.doctrees/api/cassandra/cqlengine/columns.doctree differ diff --git a/3.25.11-scylla/.doctrees/api/cassandra/cqlengine/connection.doctree b/3.25.11-scylla/.doctrees/api/cassandra/cqlengine/connection.doctree new file mode 100644 index 0000000000..ae8968acfb Binary files /dev/null and b/3.25.11-scylla/.doctrees/api/cassandra/cqlengine/connection.doctree differ diff --git a/3.25.11-scylla/.doctrees/api/cassandra/cqlengine/management.doctree b/3.25.11-scylla/.doctrees/api/cassandra/cqlengine/management.doctree new file mode 100644 index 0000000000..6ecd91279e Binary files /dev/null and b/3.25.11-scylla/.doctrees/api/cassandra/cqlengine/management.doctree differ diff --git a/3.25.11-scylla/.doctrees/api/cassandra/cqlengine/models.doctree b/3.25.11-scylla/.doctrees/api/cassandra/cqlengine/models.doctree new file mode 100644 index 0000000000..92d3d4e532 Binary files /dev/null and b/3.25.11-scylla/.doctrees/api/cassandra/cqlengine/models.doctree differ diff --git a/3.25.11-scylla/.doctrees/api/cassandra/cqlengine/query.doctree b/3.25.11-scylla/.doctrees/api/cassandra/cqlengine/query.doctree new file mode 100644 index 0000000000..b16f752bda Binary files /dev/null and b/3.25.11-scylla/.doctrees/api/cassandra/cqlengine/query.doctree differ diff --git a/3.25.11-scylla/.doctrees/api/cassandra/cqlengine/usertype.doctree b/3.25.11-scylla/.doctrees/api/cassandra/cqlengine/usertype.doctree new file mode 100644 index 0000000000..ed7c274ad1 Binary files /dev/null and b/3.25.11-scylla/.doctrees/api/cassandra/cqlengine/usertype.doctree differ diff --git a/3.25.11-scylla/.doctrees/api/cassandra/datastax/graph/fluent/index.doctree b/3.25.11-scylla/.doctrees/api/cassandra/datastax/graph/fluent/index.doctree new file mode 100644 index 0000000000..e0308223ea Binary files /dev/null and b/3.25.11-scylla/.doctrees/api/cassandra/datastax/graph/fluent/index.doctree differ diff --git a/3.25.11-scylla/.doctrees/api/cassandra/datastax/graph/fluent/predicates.doctree b/3.25.11-scylla/.doctrees/api/cassandra/datastax/graph/fluent/predicates.doctree new file mode 100644 index 0000000000..4f2e1cca3f Binary files /dev/null and b/3.25.11-scylla/.doctrees/api/cassandra/datastax/graph/fluent/predicates.doctree differ diff --git a/3.25.11-scylla/.doctrees/api/cassandra/datastax/graph/fluent/query.doctree b/3.25.11-scylla/.doctrees/api/cassandra/datastax/graph/fluent/query.doctree new file mode 100644 index 0000000000..5609876991 Binary files /dev/null and b/3.25.11-scylla/.doctrees/api/cassandra/datastax/graph/fluent/query.doctree differ diff --git a/3.25.11-scylla/.doctrees/api/cassandra/datastax/graph/index.doctree b/3.25.11-scylla/.doctrees/api/cassandra/datastax/graph/index.doctree new file mode 100644 index 0000000000..7901528a79 Binary files /dev/null and b/3.25.11-scylla/.doctrees/api/cassandra/datastax/graph/index.doctree differ diff --git a/3.25.11-scylla/.doctrees/api/cassandra/decoder.doctree b/3.25.11-scylla/.doctrees/api/cassandra/decoder.doctree new file mode 100644 index 0000000000..a3b26ebf7c Binary files /dev/null and b/3.25.11-scylla/.doctrees/api/cassandra/decoder.doctree differ diff --git a/3.25.11-scylla/.doctrees/api/cassandra/encoder.doctree b/3.25.11-scylla/.doctrees/api/cassandra/encoder.doctree new file mode 100644 index 0000000000..7e31a8676a Binary files /dev/null and b/3.25.11-scylla/.doctrees/api/cassandra/encoder.doctree differ diff --git a/3.25.11-scylla/.doctrees/api/cassandra/graph.doctree b/3.25.11-scylla/.doctrees/api/cassandra/graph.doctree new file mode 100644 index 0000000000..fda40670d9 Binary files /dev/null and b/3.25.11-scylla/.doctrees/api/cassandra/graph.doctree differ diff --git a/3.25.11-scylla/.doctrees/api/cassandra/io/asyncioreactor.doctree b/3.25.11-scylla/.doctrees/api/cassandra/io/asyncioreactor.doctree new file mode 100644 index 0000000000..4ea41bef58 Binary files /dev/null and b/3.25.11-scylla/.doctrees/api/cassandra/io/asyncioreactor.doctree differ diff --git a/3.25.11-scylla/.doctrees/api/cassandra/io/asyncorereactor.doctree b/3.25.11-scylla/.doctrees/api/cassandra/io/asyncorereactor.doctree new file mode 100644 index 0000000000..e505f5a991 Binary files /dev/null and b/3.25.11-scylla/.doctrees/api/cassandra/io/asyncorereactor.doctree differ diff --git a/3.25.11-scylla/.doctrees/api/cassandra/io/eventletreactor.doctree b/3.25.11-scylla/.doctrees/api/cassandra/io/eventletreactor.doctree new file mode 100644 index 0000000000..cb01941313 Binary files /dev/null and b/3.25.11-scylla/.doctrees/api/cassandra/io/eventletreactor.doctree differ diff --git a/3.25.11-scylla/.doctrees/api/cassandra/io/geventreactor.doctree b/3.25.11-scylla/.doctrees/api/cassandra/io/geventreactor.doctree new file mode 100644 index 0000000000..504208147f Binary files /dev/null and b/3.25.11-scylla/.doctrees/api/cassandra/io/geventreactor.doctree differ diff --git a/3.25.11-scylla/.doctrees/api/cassandra/io/libevreactor.doctree b/3.25.11-scylla/.doctrees/api/cassandra/io/libevreactor.doctree new file mode 100644 index 0000000000..a17580b9ec Binary files /dev/null and b/3.25.11-scylla/.doctrees/api/cassandra/io/libevreactor.doctree differ diff --git a/3.25.11-scylla/.doctrees/api/cassandra/io/twistedreactor.doctree b/3.25.11-scylla/.doctrees/api/cassandra/io/twistedreactor.doctree new file mode 100644 index 0000000000..0f277e90b1 Binary files /dev/null and b/3.25.11-scylla/.doctrees/api/cassandra/io/twistedreactor.doctree differ diff --git a/3.25.11-scylla/.doctrees/api/cassandra/metadata.doctree b/3.25.11-scylla/.doctrees/api/cassandra/metadata.doctree new file mode 100644 index 0000000000..72389fd544 Binary files /dev/null and b/3.25.11-scylla/.doctrees/api/cassandra/metadata.doctree differ diff --git a/3.25.11-scylla/.doctrees/api/cassandra/metrics.doctree b/3.25.11-scylla/.doctrees/api/cassandra/metrics.doctree new file mode 100644 index 0000000000..69ee15d22b Binary files /dev/null and b/3.25.11-scylla/.doctrees/api/cassandra/metrics.doctree differ diff --git a/3.25.11-scylla/.doctrees/api/cassandra/policies.doctree b/3.25.11-scylla/.doctrees/api/cassandra/policies.doctree new file mode 100644 index 0000000000..0930143295 Binary files /dev/null and b/3.25.11-scylla/.doctrees/api/cassandra/policies.doctree differ diff --git a/3.25.11-scylla/.doctrees/api/cassandra/pool.doctree b/3.25.11-scylla/.doctrees/api/cassandra/pool.doctree new file mode 100644 index 0000000000..3f1d9b93ff Binary files /dev/null and b/3.25.11-scylla/.doctrees/api/cassandra/pool.doctree differ diff --git a/3.25.11-scylla/.doctrees/api/cassandra/protocol.doctree b/3.25.11-scylla/.doctrees/api/cassandra/protocol.doctree new file mode 100644 index 0000000000..7566a2cec5 Binary files /dev/null and b/3.25.11-scylla/.doctrees/api/cassandra/protocol.doctree differ diff --git a/3.25.11-scylla/.doctrees/api/cassandra/query.doctree b/3.25.11-scylla/.doctrees/api/cassandra/query.doctree new file mode 100644 index 0000000000..00db544849 Binary files /dev/null and b/3.25.11-scylla/.doctrees/api/cassandra/query.doctree differ diff --git a/3.25.11-scylla/.doctrees/api/cassandra/timestamps.doctree b/3.25.11-scylla/.doctrees/api/cassandra/timestamps.doctree new file mode 100644 index 0000000000..b12cd40dcf Binary files /dev/null and b/3.25.11-scylla/.doctrees/api/cassandra/timestamps.doctree differ diff --git a/3.25.11-scylla/.doctrees/api/cassandra/util.doctree b/3.25.11-scylla/.doctrees/api/cassandra/util.doctree new file mode 100644 index 0000000000..eae38fcce9 Binary files /dev/null and b/3.25.11-scylla/.doctrees/api/cassandra/util.doctree differ diff --git a/3.25.11-scylla/.doctrees/api/index.doctree b/3.25.11-scylla/.doctrees/api/index.doctree new file mode 100644 index 0000000000..70f18058ed Binary files /dev/null and b/3.25.11-scylla/.doctrees/api/index.doctree differ diff --git a/3.25.11-scylla/.doctrees/cqlengine/batches.doctree b/3.25.11-scylla/.doctrees/cqlengine/batches.doctree new file mode 100644 index 0000000000..a1cb29adbd Binary files /dev/null and b/3.25.11-scylla/.doctrees/cqlengine/batches.doctree differ diff --git a/3.25.11-scylla/.doctrees/cqlengine/connections.doctree b/3.25.11-scylla/.doctrees/cqlengine/connections.doctree new file mode 100644 index 0000000000..a6940d9e2d Binary files /dev/null and b/3.25.11-scylla/.doctrees/cqlengine/connections.doctree differ diff --git a/3.25.11-scylla/.doctrees/cqlengine/faq.doctree b/3.25.11-scylla/.doctrees/cqlengine/faq.doctree new file mode 100644 index 0000000000..b9210802e1 Binary files /dev/null and b/3.25.11-scylla/.doctrees/cqlengine/faq.doctree differ diff --git a/3.25.11-scylla/.doctrees/cqlengine/models.doctree b/3.25.11-scylla/.doctrees/cqlengine/models.doctree new file mode 100644 index 0000000000..ab03d82f5f Binary files /dev/null and b/3.25.11-scylla/.doctrees/cqlengine/models.doctree differ diff --git a/3.25.11-scylla/.doctrees/cqlengine/queryset.doctree b/3.25.11-scylla/.doctrees/cqlengine/queryset.doctree new file mode 100644 index 0000000000..6f0b4d8654 Binary files /dev/null and b/3.25.11-scylla/.doctrees/cqlengine/queryset.doctree differ diff --git a/3.25.11-scylla/.doctrees/cqlengine/third_party.doctree b/3.25.11-scylla/.doctrees/cqlengine/third_party.doctree new file mode 100644 index 0000000000..571788cdae Binary files /dev/null and b/3.25.11-scylla/.doctrees/cqlengine/third_party.doctree differ diff --git a/3.25.11-scylla/.doctrees/cqlengine/upgrade_guide.doctree b/3.25.11-scylla/.doctrees/cqlengine/upgrade_guide.doctree new file mode 100644 index 0000000000..e730ada941 Binary files /dev/null and b/3.25.11-scylla/.doctrees/cqlengine/upgrade_guide.doctree differ diff --git a/3.25.11-scylla/.doctrees/dates_and_times.doctree b/3.25.11-scylla/.doctrees/dates_and_times.doctree new file mode 100644 index 0000000000..3f96e923d5 Binary files /dev/null and b/3.25.11-scylla/.doctrees/dates_and_times.doctree differ diff --git a/3.25.11-scylla/.doctrees/environment.pickle b/3.25.11-scylla/.doctrees/environment.pickle new file mode 100644 index 0000000000..1093690458 Binary files /dev/null and b/3.25.11-scylla/.doctrees/environment.pickle differ diff --git a/3.25.11-scylla/.doctrees/execution_profiles.doctree b/3.25.11-scylla/.doctrees/execution_profiles.doctree new file mode 100644 index 0000000000..5060d3f743 Binary files /dev/null and b/3.25.11-scylla/.doctrees/execution_profiles.doctree differ diff --git a/3.25.11-scylla/.doctrees/faq.doctree b/3.25.11-scylla/.doctrees/faq.doctree new file mode 100644 index 0000000000..b42d6fe592 Binary files /dev/null and b/3.25.11-scylla/.doctrees/faq.doctree differ diff --git a/3.25.11-scylla/.doctrees/getting_started.doctree b/3.25.11-scylla/.doctrees/getting_started.doctree new file mode 100644 index 0000000000..3c495680b7 Binary files /dev/null and b/3.25.11-scylla/.doctrees/getting_started.doctree differ diff --git a/3.25.11-scylla/.doctrees/index.doctree b/3.25.11-scylla/.doctrees/index.doctree new file mode 100644 index 0000000000..c46877496d Binary files /dev/null and b/3.25.11-scylla/.doctrees/index.doctree differ diff --git a/3.25.11-scylla/.doctrees/installation.doctree b/3.25.11-scylla/.doctrees/installation.doctree new file mode 100644 index 0000000000..005f0a63c3 Binary files /dev/null and b/3.25.11-scylla/.doctrees/installation.doctree differ diff --git a/3.25.11-scylla/.doctrees/lwt.doctree b/3.25.11-scylla/.doctrees/lwt.doctree new file mode 100644 index 0000000000..acab81baf0 Binary files /dev/null and b/3.25.11-scylla/.doctrees/lwt.doctree differ diff --git a/3.25.11-scylla/.doctrees/object_mapper.doctree b/3.25.11-scylla/.doctrees/object_mapper.doctree new file mode 100644 index 0000000000..2c67b659f0 Binary files /dev/null and b/3.25.11-scylla/.doctrees/object_mapper.doctree differ diff --git a/3.25.11-scylla/.doctrees/performance.doctree b/3.25.11-scylla/.doctrees/performance.doctree new file mode 100644 index 0000000000..e2b7bfd344 Binary files /dev/null and b/3.25.11-scylla/.doctrees/performance.doctree differ diff --git a/3.25.11-scylla/.doctrees/query_paging.doctree b/3.25.11-scylla/.doctrees/query_paging.doctree new file mode 100644 index 0000000000..e4463da9df Binary files /dev/null and b/3.25.11-scylla/.doctrees/query_paging.doctree differ diff --git a/3.25.11-scylla/.doctrees/scylla_cloud.doctree b/3.25.11-scylla/.doctrees/scylla_cloud.doctree new file mode 100644 index 0000000000..3b520f2987 Binary files /dev/null and b/3.25.11-scylla/.doctrees/scylla_cloud.doctree differ diff --git a/3.25.11-scylla/.doctrees/scylla_specific.doctree b/3.25.11-scylla/.doctrees/scylla_specific.doctree new file mode 100644 index 0000000000..fc60aab519 Binary files /dev/null and b/3.25.11-scylla/.doctrees/scylla_specific.doctree differ diff --git a/3.25.11-scylla/.doctrees/security.doctree b/3.25.11-scylla/.doctrees/security.doctree new file mode 100644 index 0000000000..51e9e0c0ad Binary files /dev/null and b/3.25.11-scylla/.doctrees/security.doctree differ diff --git a/3.25.11-scylla/.doctrees/upgrading.doctree b/3.25.11-scylla/.doctrees/upgrading.doctree new file mode 100644 index 0000000000..da89c68f7d Binary files /dev/null and b/3.25.11-scylla/.doctrees/upgrading.doctree differ diff --git a/3.25.11-scylla/.doctrees/user_defined_types.doctree b/3.25.11-scylla/.doctrees/user_defined_types.doctree new file mode 100644 index 0000000000..33b2c75b08 Binary files /dev/null and b/3.25.11-scylla/.doctrees/user_defined_types.doctree differ diff --git a/3.25.11-scylla/.nojekyll b/3.25.11-scylla/.nojekyll new file mode 100644 index 0000000000..e69de29bb2 diff --git a/3.25.11-scylla/404.html b/3.25.11-scylla/404.html new file mode 100644 index 0000000000..d60936cbfe --- /dev/null +++ b/3.25.11-scylla/404.html @@ -0,0 +1,31 @@ + + + + + + + + + ScyllaDB + + + + + + + + + + + +
+

404

+

The ScyllaDB monster ate your page!

+

+ Home +

+
+ + + \ No newline at end of file diff --git a/3.25.11-scylla/CHANGELOG.html b/3.25.11-scylla/CHANGELOG.html new file mode 100644 index 0000000000..0769beb2dc --- /dev/null +++ b/3.25.11-scylla/CHANGELOG.html @@ -0,0 +1,2918 @@ + + + + + + + + + + + + + CHANGELOG | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

CHANGELOG

+
+

3.25.0

+

March 18, 2021

+
+

Features

+
    +
  • Ensure the driver can connect when invalid peer hosts are in system.peers (PYTHON-1260)

  • +
  • Implement protocol v5 checksumming (PYTHON-1258)

  • +
  • Fix the default cqlengine connection mechanism to work with Astra (PYTHON-1265)

  • +
+
+
+

Bug Fixes

+
    +
  • Asyncore race condition cause logging exception on shutdown (PYTHON-1266)

  • +
  • Update list of reserved keywords (PYTHON-1269)

  • +
+
+
+

Others

+
    +
  • Drop Python 3.4 support (PYTHON-1220)

  • +
  • Update security documentation and examples to use PROTOCOL_TLS (PYTHON-1264)

  • +
+
+
+
+

3.24.0

+

June 18, 2020

+
+

Features

+
    +
  • Make geomet an optional dependency at runtime (PYTHON-1237)

  • +
  • Add use_default_tempdir cloud config options (PYTHON-1245)

  • +
  • Tcp flow control for libevreactor (PYTHON-1248)

  • +
+
+
+

Bug Fixes

+
    +
  • Unable to connect to a cloud cluster using Ubuntu 20.04 (PYTHON-1238)

  • +
  • PlainTextAuthProvider fails with unicode chars and Python3 (PYTHON-1241)

  • +
  • [GRAPH] Graph execution profiles consistency level are not set to LOCAL_QUORUM with a cloud cluster (PYTHON-1240)

  • +
  • [GRAPH] Can’t write data in a Boolean field using the Fluent API (PYTHON-1239)

  • +
  • [GRAPH] Fix elementMap() result deserialization (PYTHON-1233)

  • +
+
+
+

Others

+
    +
  • Bump geomet dependency version to 0.2 (PYTHON-1243)

  • +
  • Bump gremlinpython dependency version to 3.4.6 (PYTHON-1212)

  • +
  • Improve fluent graph documentation for core graphs (PYTHON-1244)

  • +
+
+
+
+

3.23.0

+

April 6, 2020

+
+

Features

+
    +
  • Transient Replication Support (PYTHON-1207)

  • +
  • Support system.peers_v2 and port discovery for C* 4.0 (PYTHON-700)

  • +
+
+
+

Bug Fixes

+
    +
  • Asyncore logging exception on shutdown (PYTHON-1228)

  • +
+
+
+
+

3.22.0

+

February 26, 2020

+
+

Features

+
    +
  • Add all() function to the ResultSet API (PYTHON-1203)

  • +
  • Parse new schema metadata in NGDG and generate table edges CQL syntax (PYTHON-996)

  • +
  • Add GraphSON3 support (PYTHON-788)

  • +
  • Use GraphSON3 as default for Native graphs (PYTHON-1004)

  • +
  • Add Tuple and UDT types for native graph (PYTHON-1005)

  • +
  • Add Duration type for native graph (PYTHON-1000)

  • +
  • Add gx:ByteBuffer graphson type support for Blob field (PYTHON-1027)

  • +
  • Enable Paging Through DSE Driver for Gremlin Traversals (PYTHON-1045)

  • +
  • Provide numerical wrappers to ensure proper graphson schema definition (PYTHON-1051)

  • +
  • Resolve the row_factory automatically for native graphs (PYTHON-1056)

  • +
  • Add g:TraversalMetrics/g:Metrics graph deserializers (PYTHON-1057)

  • +
  • Add g:BulkSet graph deserializers (PYTHON-1060)

  • +
  • Update Graph Engine names and the way to create a Classic/Native Graph (PYTHON-1090)

  • +
  • Update Native to Core Graph Engine

  • +
  • Add graphson3 and native graph support (PYTHON-1039)

  • +
  • Enable Paging Through DSE Driver for Gremlin Traversals (PYTHON-1045)

  • +
  • Expose filter predicates for cql collections (PYTHON-1019)

  • +
  • Add g:TraversalMetrics/Metrics deserializers (PYTHON-1057)

  • +
  • Make graph metadata handling more robust (PYTHON-1204)

  • +
+
+
+

Bug Fixes

+
    +
  • Make sure to only query the native_transport_address column with DSE (PYTHON-1205)

  • +
+
+
+
+

3.21.0

+

January 15, 2020

+
+

Features

+
    +
  • Unified driver: merge core and DSE drivers into a single package (PYTHON-1130)

  • +
  • Add Python 3.8 support (PYTHON-1189)

  • +
  • Allow passing ssl context for Twisted (PYTHON-1161)

  • +
  • Ssl context and cloud support for Eventlet (PYTHON-1162)

  • +
  • Cloud Twisted support (PYTHON-1163)

  • +
  • Add additional_write_policy and read_repair to system schema parsing (PYTHON-1048)

  • +
  • Flexible version parsing (PYTHON-1174)

  • +
  • Support NULL in collection deserializer (PYTHON-1123)

  • +
  • [GRAPH] Ability to execute Fluent Graph queries asynchronously (PYTHON-1129)

  • +
+
+
+

Bug Fixes

+
    +
  • Handle prepared id mismatch when repreparing on the fly (PYTHON-1124)

  • +
  • re-raising the CQLEngineException will fail on Python 3 (PYTHON-1166)

  • +
  • asyncio message chunks can be processed discontinuously (PYTHON-1185)

  • +
  • Reconnect attempts persist after downed node removed from peers (PYTHON-1181)

  • +
  • Connection fails to validate ssl certificate hostname when SSLContext.check_hostname is set (PYTHON-1186)

  • +
  • ResponseFuture._set_result crashes on connection error when used with PrepareMessage (PYTHON-1187)

  • +
  • Insights fail to serialize the startup message when the SSL Context is from PyOpenSSL (PYTHON-1192)

  • +
+
+
+

Others

+
    +
  • The driver has a new dependency: geomet. It comes from the dse-driver unification and +is used to support DSE geo types.

  • +
  • Remove *read_repair_chance table options (PYTHON-1140)

  • +
  • Avoid warnings about unspecified load balancing policy when connecting to a cloud cluster (PYTHON-1177)

  • +
  • Add new DSE CQL keywords (PYTHON-1122)

  • +
  • Publish binary wheel distributions (PYTHON-1013)

  • +
+
+
+

Deprecations

+
    +
  • DSELoadBalancingPolicy will be removed in the next major, consider using +the DefaultLoadBalancingPolicy.

  • +
+

Merged from dse-driver:

+
+
+

Features

+
    +
  • Insights integration (PYTHON-1047)

  • +
  • Graph execution profiles should preserve their graph_source when graph_options is overridden (PYTHON-1021)

  • +
  • Add NodeSync metadata (PYTHON-799)

  • +
  • Add new NodeSync failure values (PYTHON-934)

  • +
  • DETERMINISTIC and MONOTONIC Clauses for Functions and Aggregates (PYTHON-955)

  • +
  • GraphOptions should show a warning for unknown parameters (PYTHON-819)

  • +
  • DSE protocol version 2 and continous paging backpressure (PYTHON-798)

  • +
  • GraphSON2 Serialization/Deserialization Support (PYTHON-775)

  • +
  • Add graph-results payload option for GraphSON format (PYTHON-773)

  • +
  • Create an AuthProvider for the DSE transitional mode (PYTHON-831)

  • +
  • Implement serializers for the Graph String API (PYTHON-778)

  • +
  • Provide deserializers for GraphSON types (PYTHON-782)

  • +
  • Add Graph DurationType support (PYTHON-607)

  • +
  • Support DSE DateRange type (PYTHON-668)

  • +
  • RLAC CQL output for materialized views (PYTHON-682)

  • +
  • Add Geom Types wkt deserializer

  • +
  • DSE Graph Client timeouts in custom payload (PYTHON-589)

  • +
  • Make DSEGSSAPIAuthProvider accept principal name (PYTHON-574)

  • +
  • Add config profiles to DSE graph execution (PYTHON-570)

  • +
  • DSE Driver version checking (PYTHON-568)

  • +
  • Distinct default timeout for graph queries (PYTHON-477)

  • +
  • Graph result parsing for known types (PYTHON-479,487)

  • +
  • Distinct read/write CL for graph execution (PYTHON-509)

  • +
  • Target graph analytics query to spark master when available (PYTHON-510)

  • +
+
+
+

Bug Fixes

+
    +
  • Continuous paging sessions raise RuntimeError when results are not entirely consumed (PYTHON-1054)

  • +
  • GraphSON Property deserializer should return a dict instead of a set (PYTHON-1033)

  • +
  • ResponseFuture.has_more_pages may hold the wrong value (PYTHON-946)

  • +
  • DETERMINISTIC clause in AGGREGATE misplaced in CQL generation (PYTHON-963)

  • +
  • graph module import cause a DLL issue on Windows due to its cythonizing failure (PYTHON-900)

  • +
  • Update date serialization to isoformat in graph (PYTHON-805)

  • +
  • DateRange Parse Error (PYTHON-729)

  • +
  • MontonicTimestampGenerator.__init__ ignores class defaults (PYTHON-728)

  • +
  • metadata.get_host returning None unexpectedly (PYTHON-709)

  • +
  • Sockets associated with sessions not getting cleaned up on session.shutdown() (PYTHON-673)

  • +
  • Resolve FQDN from ip address and use that as host passed to SASLClient (PYTHON-566)

  • +
  • Geospatial type implementations don’t handle ‘EMPTY’ values. (PYTHON-481)

  • +
  • Correctly handle other types in geo type equality (PYTHON-508)

  • +
+
+
+

Other

+
    +
  • Add tests around cqlengine and continuous paging (PYTHON-872)

  • +
  • Add an abstract GraphStatement to handle different graph statements (PYTHON-789)

  • +
  • Write documentation examples for DSE 2.0 features (PYTHON-732)

  • +
  • DSE_V1 protocol should not include all of protocol v5 (PYTHON-694)

  • +
+
+
+
+

3.20.2

+

November 19, 2019

+
+

Bug Fixes

+
    +
  • Fix import error for old python installation without SSLContext (PYTHON-1183)

  • +
+
+
+
+

3.20.1

+

November 6, 2019

+
+

Bug Fixes

+
    +
  • ValueError: too many values to unpack (expected 2)” when there are two dashes in server version number (PYTHON-1172)

  • +
+
+
+
+

3.20.0

+

October 28, 2019

+
+

Features

+
    +
  • DataStax Astra Support (PYTHON-1074)

  • +
  • Use 4.0 schema parser in 4 alpha and snapshot builds (PYTHON-1158)

  • +
+
+
+

Bug Fixes

+
    +
  • Connection setup methods prevent using ExecutionProfile in cqlengine (PYTHON-1009)

  • +
  • Driver deadlock if all connections dropped by heartbeat whilst request in flight and request times out (PYTHON-1044)

  • +
  • Exception when use pk__token__gt filter In python 3.7 (PYTHON-1121)

  • +
+
+
+
+

3.19.0

+

August 26, 2019

+
+

Features

+
    +
  • Add Python 3.7 support (PYTHON-1016)

  • +
  • Future-proof Mapping imports (PYTHON-1023)

  • +
  • Include param values in cqlengine logging (PYTHON-1105)

  • +
  • NTS Token Replica Map Generation is slow (PYTHON-622)

  • +
+
+
+

Bug Fixes

+
    +
  • as_cql_query UDF/UDA parameters incorrectly includes “frozen” if arguments are collections (PYTHON-1031)

  • +
  • cqlengine does not currently support combining TTL and TIMESTAMP on INSERT (PYTHON-1093)

  • +
  • Fix incorrect metadata for compact counter tables (PYTHON-1100)

  • +
  • Call ConnectionException with correct kwargs (PYTHON-1117)

  • +
  • Can’t connect to clusters built from source because version parsing doesn’t handle ‘x.y-SNAPSHOT’ (PYTHON-1118)

  • +
  • Discovered node doesn´t honor the configured Cluster port on connection (PYTHON-1127)

  • +
  • Exception when use pk__token__gt filter In python 3.7 (PYTHON-1121)

  • +
+
+
+

Other

+
    +
  • Remove invalid warning in set_session when we initialize a default connection (PYTHON-1104)

  • +
  • Set the proper default ExecutionProfile.row_factory value (PYTHON-1119)

  • +
+
+
+
+

3.18.0

+

May 27, 2019

+
+

Features

+
    +
  • Abstract Host Connection information (PYTHON-1079)

  • +
  • Improve version parsing to support a non-integer 4th component (PYTHON-1091)

  • +
  • Expose on_request_error method in the RetryPolicy (PYTHON-1064)

  • +
  • Add jitter to ExponentialReconnectionPolicy (PYTHON-1065)

  • +
+
+
+

Bug Fixes

+
    +
  • Fix error when preparing queries with beta protocol v5 (PYTHON-1081)

  • +
  • Accept legacy empty strings as column names (PYTHON-1082)

  • +
  • Let util.SortedSet handle uncomparable elements (PYTHON-1087)

  • +
+
+
+
+

3.17.1

+

May 2, 2019

+
+

Bug Fixes

+
    +
  • Socket errors EAGAIN/EWOULDBLOCK are not handled properly and cause timeouts (PYTHON-1089)

  • +
+
+
+
+

3.17.0

+

February 19, 2019

+
+

Features

+
    +
  • Send driver name and version in startup message (PYTHON-1068)

  • +
  • Add Cluster ssl_context option to enable SSL (PYTHON-995)

  • +
  • Allow encrypted private keys for 2-way SSL cluster connections (PYTHON-995)

  • +
  • Introduce new method ConsistencyLevel.is_serial (PYTHON-1067)

  • +
  • Add Session.get_execution_profile (PYTHON-932)

  • +
  • Add host kwarg to Session.execute/execute_async APIs to send a query to a specific node (PYTHON-993)

  • +
+
+
+

Bug Fixes

+
    +
  • NoHostAvailable when all hosts are up and connectable (PYTHON-891)

  • +
  • Serial consistency level is not used (PYTHON-1007)

  • +
+
+
+

Other

+
    +
  • Fail faster on incorrect lz4 import (PYTHON-1042)

  • +
  • Bump Cython dependency version to 0.29 (PYTHON-1036)

  • +
  • Expand Driver SSL Documentation (PYTHON-740)

  • +
+
+
+

Deprecations

+
    +
  • Using Cluster.ssl_options to enable SSL is deprecated and will be removed in +the next major release, use ssl_context.

  • +
  • DowngradingConsistencyRetryPolicy is deprecated and will be +removed in the next major release. (PYTHON-937)

  • +
+
+
+
+

3.16.0

+

November 12, 2018

+
+

Bug Fixes

+
    +
  • Improve and fix socket error-catching code in nonblocking-socket reactors (PYTHON-1024)

  • +
  • Non-ASCII characters in schema break CQL string generation (PYTHON-1008)

  • +
  • Fix OSS driver’s virtual table support against DSE 6.0.X and future server releases (PYTHON-1020)

  • +
  • ResultSet.one() fails if the row_factory is using a generator (PYTHON-1026)

  • +
  • Log profile name on attempt to create existing profile (PYTHON-944)

  • +
  • Cluster instantiation fails if any contact points’ hostname resolution fails (PYTHON-895)

  • +
+
+
+

Other

+
    +
  • Fix tests when RF is not maintained if we decomission a node (PYTHON-1017)

  • +
  • Fix wrong use of ResultSet indexing (PYTHON-1015)

  • +
+
+
+
+

3.15.1

+

September 6, 2018

+
+

Bug Fixes

+
    +
  • C* 4.0 schema-parsing logic breaks running against DSE 6.0.X (PYTHON-1018)

  • +
+
+
+
+

3.15.0

+

August 30, 2018

+
+

Features

+
    +
  • Parse Virtual Keyspace Metadata (PYTHON-992)

  • +
+
+
+

Bug Fixes

+
    +
  • Tokenmap.get_replicas returns the wrong value if token coincides with the end of the range (PYTHON-978)

  • +
  • Python Driver fails with “more than 255 arguments” python exception when > 255 columns specified in query response (PYTHON-893)

  • +
  • Hang in integration.standard.test_cluster.ClusterTests.test_set_keyspace_twice (PYTHON-998)

  • +
  • Asyncore reactors should use a global variable instead of a class variable for the event loop (PYTHON-697)

  • +
+
+
+

Other

+
    +
  • Use global variable for libev loops so it can be subclassed (PYTHON-973)

  • +
  • Update SchemaParser for V4 (PYTHON-1006)

  • +
  • Bump Cython dependency version to 0.28 (PYTHON-1012)

  • +
+
+
+
+

3.14.0

+

April 17, 2018

+
+

Features

+
    +
  • Add one() function to the ResultSet API (PYTHON-947)

  • +
  • Create an utility function to fetch concurrently many keys from the same replica (PYTHON-647)

  • +
  • Allow filter queries with fields that have an index managed outside of cqlengine (PYTHON-966)

  • +
  • Twisted SSL Support (PYTHON-343)

  • +
  • Support IS NOT NULL operator in cqlengine (PYTHON-968)

  • +
+
+
+

Other

+
    +
  • Fix Broken Links in Docs (PYTHON-916)

  • +
  • Reevaluate MONKEY_PATCH_LOOP in test codebase (PYTHON-903)

  • +
  • Remove CASS_SERVER_VERSION and replace it for CASSANDRA_VERSION in tests (PYTHON-910)

  • +
  • Refactor CASSANDRA_VERSION to a some kind of version object (PYTHON-915)

  • +
  • Log warning when driver configures an authenticator, but server does not request authentication (PYTHON-940)

  • +
  • Warn users when using the deprecated Session.default_consistency_level (PYTHON-953)

  • +
  • Add DSE smoke test to OSS driver tests (PYTHON-894)

  • +
  • Document long compilation times and workarounds (PYTHON-868)

  • +
  • Improve error for batch WriteTimeouts (PYTHON-941)

  • +
  • Deprecate ResultSet indexing (PYTHON-945)

  • +
+
+
+
+

3.13.0

+

January 30, 2018

+
+

Features

+
    +
  • cqlengine: LIKE filter operator (PYTHON-512)

  • +
  • Support cassandra.query.BatchType with cqlengine BatchQuery (PYTHON-888)

  • +
+
+
+

Bug Fixes

+
    +
  • AttributeError: ‘NoneType’ object has no attribute ‘add_timer’ (PYTHON-862)

  • +
  • Support retry_policy in PreparedStatement (PYTHON-861)

  • +
  • __del__ method in Session is throwing an exception (PYTHON-813)

  • +
  • LZ4 import issue with recent versions (PYTHON-897)

  • +
  • ResponseFuture._connection can be None when returning request_id (PYTHON-853)

  • +
  • ResultSet.was_applied doesn’t support batch with LWT statements (PYTHON-848)

  • +
+
+
+

Other

+
    +
  • cqlengine: avoid warning when unregistering connection on shutdown (PYTHON-865)

  • +
  • Fix DeprecationWarning of log.warn (PYTHON-846)

  • +
  • Fix example_mapper.py for python3 (PYTHON-860)

  • +
  • Possible deadlock on cassandra.concurrent.execute_concurrent (PYTHON-768)

  • +
  • Add some known deprecated warnings for 4.x (PYTHON-877)

  • +
  • Remove copyright dates from copyright notices (PYTHON-863)

  • +
  • Remove “Experimental” tag from execution profiles documentation (PYTHON-840)

  • +
  • request_timer metrics descriptions are slightly incorrect (PYTHON-885)

  • +
  • Remove “Experimental” tag from cqlengine connections documentation (PYTHON-892)

  • +
  • Set in documentation default consistency for operations is LOCAL_ONE (PYTHON-901)

  • +
+
+
+
+

3.12.0

+

November 6, 2017

+
+

Features

+
    +
  • Send keyspace in QUERY, PREPARE, and BATCH messages (PYTHON-678)

  • +
  • Add IPv4Address/IPv6Address support for inet types (PYTHON-751)

  • +
  • WriteType.CDC and VIEW missing (PYTHON-794)

  • +
  • Warn on Cluster init if contact points are specified but LBP isn’t (legacy mode) (PYTHON-812)

  • +
  • Warn on Cluster init if contact points are specified but LBP isn’t (exection profile mode) (PYTHON-838)

  • +
  • Include hash of result set metadata in prepared stmt id (PYTHON-808)

  • +
  • Add NO_COMPACT startup option (PYTHON-839)

  • +
  • Add new exception type for CDC (PYTHON-837)

  • +
  • Allow 0ms in ConstantSpeculativeExecutionPolicy (PYTHON-836)

  • +
  • Add asyncio reactor (PYTHON-507)

  • +
+
+
+

Bug Fixes

+
    +
  • Both _set_final_exception/result called for the same ResponseFuture (PYTHON-630)

  • +
  • Use of DCAwareRoundRobinPolicy raises NoHostAvailable exception (PYTHON-781)

  • +
  • Not create two sessions by default in CQLEngine (PYTHON-814)

  • +
  • Bug when subclassing AyncoreConnection (PYTHON-827)

  • +
  • Error at cleanup when closing the asyncore connections (PYTHON-829)

  • +
  • Fix sites where sessions can change during iteration (PYTHON-793)

  • +
  • cqlengine: allow min_length=0 for Ascii and Text column types (PYTHON-735)

  • +
  • Rare exception when “sys.exit(0)” after query timeouts (PYTHON-752)

  • +
  • Dont set the session keyspace when preparing statements (PYTHON-843)

  • +
  • Use of DCAwareRoundRobinPolicy raises NoHostAvailable exception (PYTHON-781)

  • +
+
+
+

Other

+
    +
  • Remove DeprecationWarning when using WhiteListRoundRobinPolicy (PYTHON-810)

  • +
  • Bump Cython dependency version to 0.27 (PYTHON-833)

  • +
+
+
+
+

3.11.0

+

July 24, 2017

+
+

Features

+
    +
  • Add idle_heartbeat_timeout cluster option to tune how long to wait for heartbeat responses. (PYTHON-762)

  • +
  • Add HostFilterPolicy (PYTHON-761)

  • +
+
+
+

Bug Fixes

+
    +
  • is_idempotent flag is not propagated from PreparedStatement to BoundStatement (PYTHON-736)

  • +
  • Fix asyncore hang on exit (PYTHON-767)

  • +
  • Driver takes several minutes to remove a bad host from session (PYTHON-762)

  • +
  • Installation doesn’t always fall back to no cython in Windows (PYTHON-763)

  • +
  • Avoid to replace a connection that is supposed to shutdown (PYTHON-772)

  • +
  • request_ids may not be returned to the pool (PYTHON-739)

  • +
  • Fix murmur3 on big-endian systems (PYTHON-653)

  • +
  • Ensure unused connections are closed if a Session is deleted by the GC (PYTHON-774)

  • +
  • Fix .values_list by using db names internally (cqlengine) (PYTHON-785)

  • +
+
+
+

Other

+
    +
  • Bump Cython dependency version to 0.25.2 (PYTHON-754)

  • +
  • Fix DeprecationWarning when using lz4 (PYTHON-769)

  • +
  • Deprecate WhiteListRoundRobinPolicy (PYTHON-759)

  • +
  • Improve upgrade guide for materializing pages (PYTHON-464)

  • +
  • Documentation for time/date specifies timestamp inupt as microseconds (PYTHON-717)

  • +
  • Point to DSA Slack, not IRC, in docs index

  • +
+
+
+
+

3.10.0

+

May 24, 2017

+
+

Features

+
    +
  • Add Duration type to cqlengine (PYTHON-750)

  • +
  • Community PR review: Raise error on primary key update only if its value changed (PYTHON-705)

  • +
  • get_query_trace() contract is ambiguous (PYTHON-196)

  • +
+
+
+

Bug Fixes

+
    +
  • Queries using speculative execution policy timeout prematurely (PYTHON-755)

  • +
  • Fix map where results are not consumed (PYTHON-749)

  • +
  • Driver fails to encode Duration’s with large values (PYTHON-747)

  • +
  • UDT values are not updated correctly in CQLEngine (PYTHON-743)

  • +
  • UDT types are not validated in CQLEngine (PYTHON-742)

  • +
  • to_python is not implemented for types columns.Type and columns.Date in CQLEngine (PYTHON-741)

  • +
  • Clients spin infinitely trying to connect to a host that is drained (PYTHON-734)

  • +
  • Resulset.get_query_trace returns empty trace sometimes (PYTHON-730)

  • +
  • Memory grows and doesn’t get removed (PYTHON-720)

  • +
  • Fix RuntimeError caused by change dict size during iteration (PYTHON-708)

  • +
  • fix ExponentialReconnectionPolicy may throw OverflowError problem (PYTHON-707)

  • +
  • Avoid using nonexistent prepared statement in ResponseFuture (PYTHON-706)

  • +
+
+
+

Other

+
    +
  • Update README (PYTHON-746)

  • +
  • Test python versions 3.5 and 3.6 (PYTHON-737)

  • +
  • Docs Warning About Prepare select * (PYTHON-626)

  • +
  • Increase Coverage in CqlEngine Test Suite (PYTHON-505)

  • +
  • Example SSL connection code does not verify server certificates (PYTHON-469)

  • +
+
+
+
+

3.9.0

+
+

Features

+
    +
  • cqlengine: remove elements by key from a map (PYTHON-688)

  • +
+
+
+

Bug Fixes

+
    +
  • improve error handling when connecting to non-existent keyspace (PYTHON-665)

  • +
  • Sockets associated with sessions not getting cleaned up on session.shutdown() (PYTHON-673)

  • +
  • rare flake on integration.standard.test_cluster.ClusterTests.test_clone_shared_lbp (PYTHON-727)

  • +
  • MontonicTimestampGenerator.__init__ ignores class defaults (PYTHON-728)

  • +
  • race where callback or errback for request may not be called (PYTHON-733)

  • +
  • cqlengine: model.update() should not update columns with a default value that hasn’t changed (PYTHON-657)

  • +
  • cqlengine: field value manager’s explicit flag is True when queried back from cassandra (PYTHON-719)

  • +
+
+
+

Other

+
    +
  • Connection not closed in example_mapper (PYTHON-723)

  • +
  • Remove mention of pre-2.0 C* versions from OSS 3.0+ docs (PYTHON-710)

  • +
+
+
+
+

3.8.1

+

March 16, 2017

+
+

Bug Fixes

+
    +
  • implement __le__/__ge__/__ne__ on some custom types (PYTHON-714)

  • +
  • Fix bug in eventlet and gevent reactors that could cause hangs (PYTHON-721)

  • +
  • Fix DecimalType regression (PYTHON-724)

  • +
+
+
+
+

3.8.0

+
+

Features

+
    +
  • Quote index names in metadata CQL generation (PYTHON-616)

  • +
  • On column deserialization failure, keep error message consistent between python and cython (PYTHON-631)

  • +
  • TokenAwarePolicy always sends requests to the same replica for a given key (PYTHON-643)

  • +
  • Added cql types to result set (PYTHON-648)

  • +
  • Add __len__ to BatchStatement (PYTHON-650)

  • +
  • Duration Type for Cassandra (PYTHON-655)

  • +
  • Send flags with PREPARE message in v5 (PYTHON-684)

  • +
+
+
+

Bug Fixes

+
    +
  • Potential Timing issue if application exits prior to session pool initialization (PYTHON-636)

  • +
  • “Host X.X.X.X has been marked down” without any exceptions (PYTHON-640)

  • +
  • NoHostAvailable or OperationTimedOut when using execute_concurrent with a generator that inserts into more than one table (PYTHON-642)

  • +
  • ResponseFuture creates Timers and don’t cancel them even when result is received which leads to memory leaks (PYTHON-644)

  • +
  • Driver cannot connect to Cassandra version > 3 (PYTHON-646)

  • +
  • Unable to import model using UserType without setuping connection since 3.7 (PYTHON-649)

  • +
  • Don’t prepare queries on ignored hosts on_up (PYTHON-669)

  • +
  • Sockets associated with sessions not getting cleaned up on session.shutdown() (PYTHON-673)

  • +
  • Make client timestamps strictly monotonic (PYTHON-676)

  • +
  • cassandra.cqlengine.connection.register_connection broken when hosts=None (PYTHON-692)

  • +
+
+
+

Other

+
    +
  • Create a cqlengine doc section explaining None semantics (PYTHON-623)

  • +
  • Resolve warnings in documentation generation (PYTHON-645)

  • +
  • Cython dependency (PYTHON-686)

  • +
  • Drop Support for Python 2.6 (PYTHON-690)

  • +
+
+
+
+

3.7.1

+

October 26, 2016

+
+

Bug Fixes

+
    +
  • Cython upgrade has broken stable version of cassandra-driver (PYTHON-656)

  • +
+
+
+
+

3.7.0

+

September 13, 2016

+
+

Features

+
    +
  • Add v5 protocol failure map (PYTHON-619)

  • +
  • Don’t return from initial connect on first error (PYTHON-617)

  • +
  • Indicate failed column when deserialization fails (PYTHON-361)

  • +
  • Let Cluster.refresh_nodes force a token map rebuild (PYTHON-349)

  • +
  • Refresh UDTs after “keyspace updated” event with v1/v2 protocol (PYTHON-106)

  • +
  • EC2 Address Resolver (PYTHON-198)

  • +
  • Speculative query retries (PYTHON-218)

  • +
  • Expose paging state in API (PYTHON-200)

  • +
  • Don’t mark host down while one connection is active (PYTHON-498)

  • +
  • Query request size information (PYTHON-284)

  • +
  • Avoid quadratic ring processing with invalid replication factors (PYTHON-379)

  • +
  • Improve Connection/Pool creation concurrency on startup (PYTHON-82)

  • +
  • Add beta version native protocol flag (PYTHON-614)

  • +
  • cqlengine: Connections: support of multiple keyspaces and sessions (PYTHON-613)

  • +
+
+
+

Bug Fixes

+
    +
  • Race when adding a pool while setting keyspace (PYTHON-628)

  • +
  • Update results_metadata when prepared statement is reprepared (PYTHON-621)

  • +
  • CQL Export for Thrift Tables (PYTHON-213)

  • +
  • cqlengine: default value not applied to UserDefinedType (PYTHON-606)

  • +
  • cqlengine: columns are no longer hashable (PYTHON-618)

  • +
  • cqlengine: remove clustering keys from where clause when deleting only static columns (PYTHON-608)

  • +
+
+
+
+

3.6.0

+

August 1, 2016

+
+

Features

+
    +
  • Handle null values in NumpyProtocolHandler (PYTHON-553)

  • +
  • Collect greplin scales stats per cluster (PYTHON-561)

  • +
  • Update mock unit test dependency requirement (PYTHON-591)

  • +
  • Handle Missing CompositeType metadata following C* upgrade (PYTHON-562)

  • +
  • Improve Host.is_up state for HostDistance.IGNORED hosts (PYTHON-551)

  • +
  • Utilize v2 protocol’s ability to skip result set metadata for prepared statement execution (PYTHON-71)

  • +
  • Return from Cluster.connect() when first contact point connection(pool) is opened (PYTHON-105)

  • +
  • cqlengine: Add ContextQuery to allow cqlengine models to switch the keyspace context easily (PYTHON-598)

  • +
  • Standardize Validation between Ascii and Text types in Cqlengine (PYTHON-609)

  • +
+
+
+

Bug Fixes

+
    +
  • Fix geventreactor with SSL support (PYTHON-600)

  • +
  • Don’t downgrade protocol version if explicitly set (PYTHON-537)

  • +
  • Nonexistent contact point tries to connect indefinitely (PYTHON-549)

  • +
  • Execute_concurrent can exceed max recursion depth in failure mode (PYTHON-585)

  • +
  • Libev loop shutdown race (PYTHON-578)

  • +
  • Include aliases in DCT type string (PYTHON-579)

  • +
  • cqlengine: Comparison operators for Columns (PYTHON-595)

  • +
  • cqlengine: disentangle default_time_to_live table option from model query default TTL (PYTHON-538)

  • +
  • cqlengine: pk__token column name issue with the equality operator (PYTHON-584)

  • +
  • cqlengine: Fix “__in” filtering operator converts True to string “True” automatically (PYTHON-596)

  • +
  • cqlengine: Avoid LWTExceptions when updating columns that are part of the condition (PYTHON-580)

  • +
  • cqlengine: Cannot execute a query when the filter contains all columns (PYTHON-599)

  • +
  • cqlengine: routing key computation issue when a primary key column is overriden by model inheritance (PYTHON-576)

  • +
+
+
+
+

3.5.0

+

June 27, 2016

+
+

Features

+
    +
  • Optional Execution Profiles for the core driver (PYTHON-569)

  • +
  • API to get the host metadata associated with the control connection node (PYTHON-583)

  • +
  • Expose CDC option in table metadata CQL (PYTHON-593)

  • +
+
+
+

Bug Fixes

+
    +
  • Clean up Asyncore socket map when fork is detected (PYTHON-577)

  • +
  • cqlengine: QuerySet only() is not respected when there are deferred fields (PYTHON-560)

  • +
+
+
+
+

3.4.1

+

May 26, 2016

+
+

Bug Fixes

+
    +
  • Gevent connection closes on IO timeout (PYTHON-573)

  • +
  • “dictionary changed size during iteration” with Python 3 (PYTHON-572)

  • +
+
+
+
+

3.4.0

+

May 24, 2016

+
+

Features

+
    +
  • Include DSE version and workload in Host data (PYTHON-555)

  • +
  • Add a context manager to Cluster and Session (PYTHON-521)

  • +
  • Better Error Message for Unsupported Protocol Version (PYTHON-157)

  • +
  • Make the error message explicitly state when an error comes from the server (PYTHON-412)

  • +
  • Short Circuit meta refresh on topo change if NEW_NODE already exists (PYTHON-557)

  • +
  • Show warning when the wrong config is passed to SimpleStatement (PYTHON-219)

  • +
  • Return namedtuple result pairs from execute_concurrent (PYTHON-362)

  • +
  • BatchStatement should enforce batch size limit in a better way (PYTHON-151)

  • +
  • Validate min/max request thresholds for connection pool scaling (PYTHON-220)

  • +
  • Handle or warn about multiple hosts with the same rpc_address (PYTHON-365)

  • +
  • Write docs around working with datetime and timezones (PYTHON-394)

  • +
+
+
+

Bug Fixes

+
    +
  • High CPU utilization when using asyncore event loop (PYTHON-239)

  • +
  • Fix CQL Export for non-ASCII Identifiers (PYTHON-447)

  • +
  • Make stress scripts Python 2.6 compatible (PYTHON-434)

  • +
  • UnicodeDecodeError when unicode characters in key in BOP (PYTHON-559)

  • +
  • WhiteListRoundRobinPolicy should resolve hosts (PYTHON-565)

  • +
  • Cluster and Session do not GC after leaving scope (PYTHON-135)

  • +
  • Don’t wait for schema agreement on ignored nodes (PYTHON-531)

  • +
  • Reprepare on_up with many clients causes node overload (PYTHON-556)

  • +
  • None inserted into host map when control connection node is decommissioned (PYTHON-548)

  • +
  • weakref.ref does not accept keyword arguments (github #585)

  • +
+
+
+
+

3.3.0

+

May 2, 2016

+
+

Features

+
    +
  • Add an AddressTranslator interface (PYTHON-69)

  • +
  • New Retry Policy Decision - try next host (PYTHON-285)

  • +
  • Don’t mark host down on timeout (PYTHON-286)

  • +
  • SSL hostname verification (PYTHON-296)

  • +
  • Add C* version to metadata or cluster objects (PYTHON-301)

  • +
  • Options to Disable Schema, Token Metadata Processing (PYTHON-327)

  • +
  • Expose listen_address of node we get ring information from (PYTHON-332)

  • +
  • Use A-record with multiple IPs for contact points (PYTHON-415)

  • +
  • Custom consistency level for populating query traces (PYTHON-435)

  • +
  • Normalize Server Exception Types (PYTHON-443)

  • +
  • Propagate exception message when DDL schema agreement fails (PYTHON-444)

  • +
  • Specialized exceptions for metadata refresh methods failure (PYTHON-527)

  • +
+
+
+

Bug Fixes

+
    +
  • Resolve contact point hostnames to avoid duplicate hosts (PYTHON-103)

  • +
  • GeventConnection stalls requests when read is a multiple of the input buffer size (PYTHON-429)

  • +
  • named_tuple_factory breaks with duplicate “cleaned” col names (PYTHON-467)

  • +
  • Connection leak if Cluster.shutdown() happens during reconnection (PYTHON-482)

  • +
  • HostConnection.borrow_connection does not block when all request ids are used (PYTHON-514)

  • +
  • Empty field not being handled by the NumpyProtocolHandler (PYTHON-550)

  • +
+
+
+
+

3.2.2

+

April 19, 2016

+
    +
  • Fix counter save-after-no-update (PYTHON-547)

  • +
+
+
+

3.2.1

+

April 13, 2016

+
    +
  • Introduced an update to allow deserializer compilation with recently released Cython 0.24 (PYTHON-542)

  • +
+
+
+

3.2.0

+

April 12, 2016

+
+

Features

+
    +
  • cqlengine: Warn on sync_schema type mismatch (PYTHON-260)

  • +
  • cqlengine: Automatically defer fields with the ‘=’ operator (and immutable values) in select queries (PYTHON-520)

  • +
  • cqlengine: support non-equal conditions for LWT (PYTHON-528)

  • +
  • cqlengine: sync_table should validate the primary key composition (PYTHON-532)

  • +
  • cqlengine: token-aware routing for mapper statements (PYTHON-535)

  • +
+
+
+

Bug Fixes

+
    +
  • Deleting a column in a lightweight transaction raises a SyntaxException #325 (PYTHON-249)

  • +
  • cqlengine: make Token function works with named tables/columns #86 (PYTHON-272)

  • +
  • comparing models with datetime fields fail #79 (PYTHON-273)

  • +
  • cython date deserializer integer math should be aligned with CPython (PYTHON-480)

  • +
  • db_field is not always respected with UpdateStatement (PYTHON-530)

  • +
  • Sync_table fails on column.Set with secondary index (PYTHON-533)

  • +
+
+
+
+

3.1.1

+

March 14, 2016

+
+

Bug Fixes

+
    +
  • cqlengine: Fix performance issue related to additional “COUNT” queries (PYTHON-522)

  • +
+
+
+
+

3.1.0

+

March 10, 2016

+
+

Features

+
    +
  • Pass name of server auth class to AuthProvider (PYTHON-454)

  • +
  • Surface schema agreed flag for DDL statements (PYTHON-458)

  • +
  • Automatically convert float and int to Decimal on serialization (PYTHON-468)

  • +
  • Eventlet Reactor IO improvement (PYTHON-495)

  • +
  • Make pure Python ProtocolHandler available even when Cython is present (PYTHON-501)

  • +
  • Optional Cython deserializer for bytes as bytearray (PYTHON-503)

  • +
  • Add Session.default_serial_consistency_level (github #510)

  • +
  • cqlengine: Expose prior state information via cqlengine LWTException (github #343, PYTHON-336)

  • +
  • cqlengine: Collection datatype “contains” operators support (Cassandra 2.1) #278 (PYTHON-258)

  • +
  • cqlengine: Add DISTINCT query operator (PYTHON-266)

  • +
  • cqlengine: Tuple cqlengine api (PYTHON-306)

  • +
  • cqlengine: Add support for UPDATE/DELETE … IF EXISTS statements (PYTHON-432)

  • +
  • cqlengine: Allow nested container types (PYTHON-478)

  • +
  • cqlengine: Add ability to set query’s fetch_size and limit (PYTHON-323)

  • +
  • cqlengine: Internalize default keyspace from successive set_session (PYTHON-486)

  • +
  • cqlengine: Warn when Model.create() on Counters (to be deprecated) (PYTHON-333)

  • +
+
+
+

Bug Fixes

+
    +
  • Bus error (alignment issues) when running cython on some ARM platforms (PYTHON-450)

  • +
  • Overflow when decoding large collections (cython) (PYTHON-459)

  • +
  • Timer heap comparison issue with Python 3 (github #466)

  • +
  • Cython deserializer date overflow at 2^31 - 1 (PYTHON-452)

  • +
  • Decode error encountered when cython deserializing large map results (PYTHON-459)

  • +
  • Don’t require Cython for build if compiler or Python header not present (PYTHON-471)

  • +
  • Unorderable types in task scheduling with Python 3 (h(PYTHON-473)

  • +
  • cqlengine: Fix crash when updating a UDT column with a None value (github #467)

  • +
  • cqlengine: Race condition in ..connection.execute with lazy_connect (PYTHON-310)

  • +
  • cqlengine: doesn’t support case sensitive column family names (PYTHON-337)

  • +
  • cqlengine: UserDefinedType mandatory in create or update (PYTHON-344)

  • +
  • cqlengine: db_field breaks UserType (PYTHON-346)

  • +
  • cqlengine: UDT badly quoted (PYTHON-347)

  • +
  • cqlengine: Use of db_field on primary key prevents querying except while tracing. (PYTHON-351)

  • +
  • cqlengine: DateType.deserialize being called with one argument vs two (PYTHON-354)

  • +
  • cqlengine: Querying without setting up connection now throws AttributeError and not CQLEngineException (PYTHON-395)

  • +
  • cqlengine: BatchQuery multiple time executing execute statements. (PYTHON-445)

  • +
  • cqlengine: Better error for management functions when no connection set (PYTHON-451)

  • +
  • cqlengine: Handle None values for UDT attributes in cqlengine (PYTHON-470)

  • +
  • cqlengine: Fix inserting None for model save (PYTHON-475)

  • +
  • cqlengine: EQ doesn’t map to a QueryOperator (setup race condition) (PYTHON-476)

  • +
  • cqlengine: class.MultipleObjectsReturned has DoesNotExist as base class (PYTHON-489)

  • +
  • cqlengine: Typo in cqlengine UserType __len__ breaks attribute assignment (PYTHON-502)

  • +
+
+
+

Other

+
    +
  • cqlengine: a major improvement on queryset has been introduced. It +is a lot more efficient to iterate large datasets: the rows are +now fetched on demand using the driver pagination.

  • +
  • cqlengine: the queryset len() and count() behaviors have changed. It +now executes a “SELECT COUNT(*)” of the query rather than returning +the size of the internal result_cache (loaded rows). On large +queryset, you might want to avoid using them due to the performance +cost. Note that trying to access objects using list index/slicing +with negative indices also requires a count to be +executed.

  • +
+
+
+
+

3.0.0

+

November 24, 2015

+
+

Features

+
    +
  • Support datetime.date objects as a DateType (PYTHON-212)

  • +
  • Add Cluster.update_view_metadata (PYTHON-407)

  • +
  • QueryTrace option to populate partial trace sessions (PYTHON-438)

  • +
  • Attach column names to ResultSet (PYTHON-439)

  • +
  • Change default consistency level to LOCAL_ONE

  • +
+
+
+

Bug Fixes

+
    +
  • Properly SerDes nested collections when protocol_version < 3 (PYTHON-215)

  • +
  • Evict UDTs from UserType cache on change (PYTHON-226)

  • +
  • Make sure query strings are always encoded UTF-8 (PYTHON-334)

  • +
  • Track previous value of columns at instantiation in CQLengine (PYTHON-348)

  • +
  • UDT CQL encoding does not work for unicode values (PYTHON-353)

  • +
  • NetworkTopologyStrategy#make_token_replica_map does not account for multiple racks in a DC (PYTHON-378)

  • +
  • Cython integer overflow on decimal type deserialization (PYTHON-433)

  • +
  • Query trace: if session hasn’t been logged, query trace can throw exception (PYTHON-442)

  • +
+
+
+
+

3.0.0rc1

+

November 9, 2015

+
+

Features

+
    +
  • Process Modernized Schema Tables for Cassandra 3.0 (PYTHON-276, PYTHON-408, PYTHON-400, PYTHON-422)

  • +
  • Remove deprecated features (PYTHON-292)

  • +
  • Don’t assign trace data to Statements (PYTHON-318)

  • +
  • Normalize results return (PYTHON-368)

  • +
  • Process Materialized View Metadata/Events (PYTHON-371)

  • +
  • Remove blist as soft dependency (PYTHON-385)

  • +
  • Change default consistency level to LOCAL_QUORUM (PYTHON-416)

  • +
  • Normalize CQL query/export in metadata model (PYTHON-405)

  • +
+
+
+

Bug Fixes

+
    +
  • Implementation of named arguments bind is non-pythonic (PYTHON-178)

  • +
  • CQL encoding is incorrect for NaN and Infinity floats (PYTHON-282)

  • +
  • Protocol downgrade issue with C* 2.0.x, 2.1.x, and python3, with non-default logging (PYTHON-409)

  • +
  • ValueError when accessing usertype with non-alphanumeric field names (PYTHON-413)

  • +
  • NumpyProtocolHandler does not play well with PagedResult (PYTHON-430)

  • +
+
+
+
+

2.7.2

+

September 14, 2015

+
+

Bug Fixes

+
    +
  • Resolve CQL export error for UDF with zero parameters (PYTHON-392)

  • +
  • Remove futures dep. for Python 3 (PYTHON-393)

  • +
  • Avoid Python closure in cdef (supports earlier Cython compiler) (PYTHON-396)

  • +
  • Unit test runtime issues (PYTHON-397,398)

  • +
+
+
+
+

2.7.1

+

August 25, 2015

+
+

Bug Fixes

+
    +
  • Explicitly include extension source files in Manifest

  • +
+
+
+
+

2.7.0

+

August 25, 2015

+

Cython is introduced, providing compiled extensions for core modules, and +extensions for optimized results deserialization.

+
+

Features

+
    +
  • General Performance Improvements for Throughput (PYTHON-283)

  • +
  • Improve synchronous request performance with Timers (PYTHON-108)

  • +
  • Enable C Extensions for PyPy Runtime (PYTHON-357)

  • +
  • Refactor SerDes functionality for pluggable interface (PYTHON-313)

  • +
  • Cython SerDes Extension (PYTHON-377)

  • +
  • Accept iterators/generators for execute_concurrent() (PYTHON-123)

  • +
  • cythonize existing modules (PYTHON-342)

  • +
  • Pure Python murmur3 implementation (PYTHON-363)

  • +
  • Make driver tolerant of inconsistent metadata (PYTHON-370)

  • +
+
+
+

Bug Fixes

+
    +
  • Drop Events out-of-order Cause KeyError on Processing (PYTHON-358)

  • +
  • DowngradingConsistencyRetryPolicy doesn’t check response count on write timeouts (PYTHON-338)

  • +
  • Blocking connect does not use connect_timeout (PYTHON-381)

  • +
  • Properly protect partition key in CQL export (PYTHON-375)

  • +
  • Trigger error callbacks on timeout (PYTHON-294)

  • +
+
+
+
+

2.6.0

+

July 20, 2015

+
+

Bug Fixes

+
    +
  • Output proper CQL for compact tables with no clustering columns (PYTHON-360)

  • +
+
+
+
+

2.6.0c2

+

June 24, 2015

+
+

Features

+
    +
  • Automatic Protocol Version Downgrade (PYTHON-240)

  • +
  • cqlengine Python 2.6 compatibility (PYTHON-288)

  • +
  • Double-dollar string quote UDF body (PYTHON-345)

  • +
  • Set models.DEFAULT_KEYSPACE when calling set_session (github #352)

  • +
+
+
+

Bug Fixes

+
    +
  • Avoid stall while connecting to mixed version cluster (PYTHON-303)

  • +
  • Make SSL work with AsyncoreConnection in python 2.6.9 (PYTHON-322)

  • +
  • Fix Murmur3Token.from_key() on Windows (PYTHON-331)

  • +
  • Fix cqlengine TimeUUID rounding error for Windows (PYTHON-341)

  • +
  • Avoid invalid compaction options in CQL export for non-SizeTiered (PYTHON-352)

  • +
+
+
+
+

2.6.0c1

+

June 4, 2015

+

This release adds support for Cassandra 2.2 features, including version +4 of the native protocol.

+
+

Features

+
    +
  • Default load balancing policy to TokenAware(DCAware) (PYTHON-160)

  • +
  • Configuration option for connection timeout (PYTHON-206)

  • +
  • Support User Defined Function and Aggregate metadata in C* 2.2 (PYTHON-211)

  • +
  • Surface request client in QueryTrace for C* 2.2+ (PYTHON-235)

  • +
  • Implement new request failure messages in protocol v4+ (PYTHON-238)

  • +
  • Metadata model now maps index meta by index name (PYTHON-241)

  • +
  • Support new types in C* 2.2: date, time, smallint, tinyint (PYTHON-245, 295)

  • +
  • cqle: add Double column type and remove Float overload (PYTHON-246)

  • +
  • Use partition key column information in prepared response for protocol v4+ (PYTHON-277)

  • +
  • Support message custom payloads in protocol v4+ (PYTHON-280, PYTHON-329)

  • +
  • Deprecate refresh_schema and replace with functions for specific entities (PYTHON-291)

  • +
  • Save trace id even when trace complete times out (PYTHON-302)

  • +
  • Warn when registering client UDT class for protocol < v3 (PYTHON-305)

  • +
  • Support client warnings returned with messages in protocol v4+ (PYTHON-315)

  • +
  • Ability to distinguish between NULL and UNSET values in protocol v4+ (PYTHON-317)

  • +
  • Expose CQL keywords in API (PYTHON-324)

  • +
+
+
+

Bug Fixes

+
    +
  • IPv6 address support on Windows (PYTHON-20)

  • +
  • Convert exceptions during automatic re-preparation to nice exceptions (PYTHON-207)

  • +
  • cqle: Quote keywords properly in table management functions (PYTHON-244)

  • +
  • Don’t default to GeventConnection when gevent is loaded, but not monkey-patched (PYTHON-289)

  • +
  • Pass dynamic host from SaslAuthProvider to SaslAuthenticator (PYTHON-300)

  • +
  • Make protocol read_inet work for Windows (PYTHON-309)

  • +
  • cqle: Correct encoding for nested types (PYTHON-311)

  • +
  • Update list of CQL keywords used quoting identifiers (PYTHON-319)

  • +
  • Make ConstantReconnectionPolicy work with infinite retries (github #327, PYTHON-325)

  • +
  • Accept UUIDs with uppercase hex as valid in cqlengine (github #335)

  • +
+
+
+
+

2.5.1

+

April 23, 2015

+
+

Bug Fixes

+
    +
  • Fix thread safety in DC-aware load balancing policy (PYTHON-297)

  • +
  • Fix race condition in node/token rebuild (PYTHON-298)

  • +
  • Set and send serial consistency parameter (PYTHON-299)

  • +
+
+
+
+

2.5.0

+

March 30, 2015

+
+

Features

+
    +
  • Integrated cqlengine object mapping package

  • +
  • Utility functions for converting timeuuids and datetime (PYTHON-99)

  • +
  • Schema metadata fetch window randomized, config options added (PYTHON-202)

  • +
  • Support for new Date and Time Cassandra types (PYTHON-190)

  • +
+
+
+

Bug Fixes

+
    +
  • Fix index target for collection indexes (full(), keys()) (PYTHON-222)

  • +
  • Thread exception during GIL cleanup (PYTHON-229)

  • +
  • Workaround for rounding anomaly in datetime.utcfromtime (Python 3.4) (PYTHON-230)

  • +
  • Normalize text serialization for lookup in OrderedMap (PYTHON-231)

  • +
  • Support reading CompositeType data (PYTHON-234)

  • +
  • Preserve float precision in CQL encoding (PYTHON-243)

  • +
+
+
+
+

2.1.4

+

January 26, 2015

+
+

Features

+
    +
  • SaslAuthenticator for Kerberos support (PYTHON-109)

  • +
  • Heartbeat for network device keepalive and detecting failures on idle connections (PYTHON-197)

  • +
  • Support nested, frozen collections for Cassandra 2.1.3+ (PYTHON-186)

  • +
  • Schema agreement wait bypass config, new call for synchronous schema refresh (PYTHON-205)

  • +
  • Add eventlet connection support (PYTHON-194)

  • +
+
+
+

Bug Fixes

+
    +
  • Schema meta fix for complex thrift tables (PYTHON-191)

  • +
  • Support for ‘unknown’ replica placement strategies in schema meta (PYTHON-192)

  • +
  • Resolve stream ID leak on set_keyspace (PYTHON-195)

  • +
  • Remove implicit timestamp scaling on serialization of numeric timestamps (PYTHON-204)

  • +
  • Resolve stream id collision when using SASL auth (PYTHON-210)

  • +
  • Correct unhexlify usage for user defined type meta in Python3 (PYTHON-208)

  • +
+
+
+
+

2.1.3

+

December 16, 2014

+
+

Features

+
    +
  • INFO-level log confirmation that a connection was opened to a node that was marked up (PYTHON-116)

  • +
  • Avoid connecting to peer with incomplete metadata (PYTHON-163)

  • +
  • Add SSL support to gevent reactor (PYTHON-174)

  • +
  • Use control connection timeout in wait for schema agreement (PYTHON-175)

  • +
  • Better consistency level representation in unavailable+timeout exceptions (PYTHON-180)

  • +
  • Update schema metadata processing to accommodate coming schema modernization (PYTHON-185)

  • +
+
+
+

Bug Fixes

+
    +
  • Support large negative timestamps on Windows (PYTHON-119)

  • +
  • Fix schema agreement for clusters with peer rpc_addres 0.0.0.0 (PYTHON-166)

  • +
  • Retain table metadata following keyspace meta refresh (PYTHON-173)

  • +
  • Use a timeout when preparing a statement for all nodes (PYTHON-179)

  • +
  • Make TokenAware routing tolerant of statements with no keyspace (PYTHON-181)

  • +
  • Update add_collback to store/invoke multiple callbacks (PYTHON-182)

  • +
  • Correct routing key encoding for composite keys (PYTHON-184)

  • +
  • Include compression option in schema export string when disabled (PYTHON-187)

  • +
+
+
+
+

2.1.2

+

October 16, 2014

+
+

Features

+
    +
  • Allow DCAwareRoundRobinPolicy to be constructed without a local_dc, defaulting +instead to the DC of a contact_point (PYTHON-126)

  • +
  • Set routing key in BatchStatement.add() if none specified in batch (PYTHON-148)

  • +
  • Improved feedback on ValueError using named_tuple_factory with invalid column names (PYTHON-122)

  • +
+
+
+

Bug Fixes

+
    +
  • Make execute_concurrent compatible with Python 2.6 (PYTHON-159)

  • +
  • Handle Unauthorized message on schema_triggers query (PYTHON-155)

  • +
  • Pure Python sorted set in support of UDTs nested in collections (PYTON-167)

  • +
  • Support CUSTOM index metadata and string export (PYTHON-165)

  • +
+
+
+
+

2.1.1

+

September 11, 2014

+
+

Features

+
    +
  • Detect triggers and include them in CQL queries generated to recreate +the schema (github-189)

  • +
  • Support IPv6 addresses (PYTHON-144) (note: basic functionality added; Windows +platform not addressed (PYTHON-20))

  • +
+
+
+

Bug Fixes

+
    +
  • Fix NetworkTopologyStrategy.export_for_schema (PYTHON-120)

  • +
  • Keep timeout for paged results (PYTHON-150)

  • +
+
+
+

Other

+
    +
  • Add frozen<> type modifier to UDTs and tuples to handle CASSANDRA-7857

  • +
+
+
+
+

2.1.0

+

August 7, 2014

+
+

Bug Fixes

+
    +
  • Correctly serialize and deserialize null values in tuples and +user-defined types (PYTHON-110)

  • +
  • Include additional header and lib dirs, allowing libevwrapper to build +against Homebrew and Mac Ports installs of libev (PYTHON-112 and 804dea3)

  • +
+
+
+
+

2.1.0c1

+

July 25, 2014

+
+

Bug Fixes

+
    +
  • Properly specify UDTs for columns in CREATE TABLE statements

  • +
  • Avoid moving retries to a new host when using request ID zero (PYTHON-88)

  • +
  • Don’t ignore fetch_size arguments to Statement constructors (github-151)

  • +
  • Allow disabling automatic paging on a per-statement basis when it’s +enabled by default for the session (PYTHON-93)

  • +
  • Raise ValueError when tuple query parameters for prepared statements +have extra items (PYTHON-98)

  • +
  • Correctly encode nested tuples and UDTs for non-prepared statements (PYTHON-100)

  • +
  • Raise TypeError when a string is used for contact_points (github #164)

  • +
  • Include User Defined Types in KeyspaceMetadata.export_as_string() (PYTHON-96)

  • +
+
+
+

Other

+
    +
  • Return list collection columns as python lists instead of tuples +now that tuples are a specific Cassandra type

  • +
+
+
+
+

2.1.0b1

+

July 11, 2014

+

This release adds support for Cassandra 2.1 features, including version +3 of the native protocol.

+
+

Features

+
    +
  • When using the v3 protocol, only one connection is opened per-host, and +throughput is improved due to reduced pooling overhead and lock contention.

  • +
  • Support for user-defined types (Cassandra 2.1+)

  • +
  • Support for tuple type in (limited usage Cassandra 2.0.9, full usage +in Cassandra 2.1)

  • +
  • Protocol-level client-side timestamps (see Session.use_client_timestamp)

  • +
  • Overridable type encoding for non-prepared statements (see Session.encoders)

  • +
  • Configurable serial consistency levels for batch statements

  • +
  • Use io.BytesIO for reduced CPU consumption (github #143)

  • +
  • Support Twisted as a reactor. Note that a Twisted-compatible +API is not exposed (so no Deferreds), this is just a reactor +implementation. (github #135, PYTHON-8)

  • +
+
+
+

Bug Fixes

+
    +
  • Fix references to xrange that do not go through “six” in libevreactor and +geventreactor (github #138)

  • +
  • Make BoundStatements inherit fetch_size from their parent +PreparedStatement (PYTHON-80)

  • +
  • Clear reactor state in child process after forking to prevent errors with +multiprocessing when the parent process has connected a Cluster before +forking (github #141)

  • +
  • Don’t share prepared statement lock across Cluster instances

  • +
  • Format CompositeType and DynamicCompositeType columns correctly in +CREATE TABLE statements.

  • +
  • Fix cassandra.concurrent behavior when dealing with automatic paging +(PYTHON-81)

  • +
  • Properly defunct connections after protocol errors

  • +
  • Avoid UnicodeDecodeError when query string is unicode (PYTHON-76)

  • +
  • Correctly capture dclocal_read_repair_chance for tables and +use it when generating CREATE TABLE statements (PYTHON-84)

  • +
  • Avoid race condition with AsyncoreConnection that may cause messages +to fail to be written until a new message is pushed

  • +
  • Make sure cluster.metadata.partitioner and cluster.metadata.token_map +are populated when all nodes in the cluster are included in the +contact points (PYTHON-90)

  • +
  • Make Murmur3 hash match Cassandra’s hash for all values (PYTHON-89, +github #147)

  • +
  • Don’t attempt to reconnect to hosts that should be ignored (according +to the load balancing policy) when a notification is received that the +host is down.

  • +
  • Add CAS WriteType, avoiding KeyError on CAS write timeout (PYTHON-91)

  • +
+
+
+
+

2.0.2

+

June 10, 2014

+
+

Bug Fixes

+
    +
  • Add six to requirements.txt

  • +
  • Avoid KeyError during schema refresh when a keyspace is dropped +and TokenAwarePolicy is not in use

  • +
  • Avoid registering multiple atexit cleanup functions when the +asyncore event loop is restarted multiple times

  • +
  • Delay initialization of reactors in order to avoid problems +with shared state when using multiprocessing (PYTHON-60)

  • +
  • Add python-six to debian dependencies, move python-blist to recommends

  • +
  • Fix memory leak when libev connections are created and +destroyed (github #93)

  • +
  • Ensure token map is rebuilt when hosts are removed from the cluster

  • +
+
+
+
+

2.0.1

+

May 28, 2014

+
+

Bug Fixes

+
    +
  • Fix check for Cluster.is_shutdown in in @run_in_executor +decorator

  • +
+
+
+
+

2.0.0

+

May 28, 2014

+
+

Features

+
    +
  • Make libev C extension Python3-compatible (PYTHON-70)

  • +
  • Support v2 protocol authentication (PYTHON-73, github #125)

  • +
+
+
+

Bug Fixes

+
    +
  • Fix murmur3 C extension compilation under Python3.4 (github #124)

  • +
+
+
+

Merged From 1.x

+
+

Features

+
    +
  • Add Session.default_consistency_level (PYTHON-14)

  • +
+
+
+

Bug Fixes

+
    +
  • Don’t strip trailing underscores from column names when using the +named_tuple_factory (PYTHON-56)

  • +
  • Ensure replication factors are ints for NetworkTopologyStrategy +to avoid TypeErrors (github #120)

  • +
  • Pass WriteType instance to RetryPolicy.on_write_timeout() instead +of the string name of the write type. This caused write timeout +errors to always be rethrown instead of retrying. (github #123)

  • +
  • Avoid submitting tasks to the ThreadPoolExecutor after shutdown. With +retries enabled, this could cause Cluster.shutdown() to hang under +some circumstances.

  • +
  • Fix unintended rebuild of token replica map when keyspaces are +discovered (on startup), added, or updated and TokenAwarePolicy is not +in use.

  • +
  • Avoid rebuilding token metadata when cluster topology has not +actually changed

  • +
  • Avoid preparing queries for hosts that should be ignored (such as +remote hosts when using the DCAwareRoundRobinPolicy) (PYTHON-75)

  • +
+
+
+

Other

+
    +
  • Add 1 second timeout to join() call on event loop thread during +interpreter shutdown. This can help to prevent the process from +hanging during shutdown.

  • +
+
+
+
+
+

2.0.0b1

+

May 6, 2014

+
+

Upgrading from 1.x

+

Cluster.shutdown() should always be called when you are done with a +Cluster instance. If it is not called, there are no guarantees that the +driver will not hang. However, if you do have a reproduceable case +where Cluster.shutdown() is not called and the driver hangs, please +report it so that we can attempt to fix it.

+

If you’re using the 2.0 driver against Cassandra 1.2, you will need +to set your protocol version to 1. For example:

+
+

cluster = Cluster(…, protocol_version=1)

+
+
+
+

Features

+
    +
  • Support v2 of Cassandra’s native protocol, which includes the following +new features: automatic query paging support, protocol-level batch statements, +and lightweight transactions

  • +
  • Support for Python 3.3 and 3.4

  • +
  • Allow a default query timeout to be set per-Session

  • +
+
+
+

Bug Fixes

+
    +
  • Avoid errors during interpreter shutdown (the driver attempts to cleanup +daemonized worker threads before interpreter shutdown)

  • +
+
+
+

Deprecations

+

The following functions have moved from cassandra.decoder to cassandra.query. +The original functions have been left in place with a DeprecationWarning for +now:

+
    +
  • cassandra.decoder.tuple_factory has moved to cassandra.query.tuple_factory

  • +
  • cassandra.decoder.named_tuple_factory has moved to cassandra.query.named_tuple_factory

  • +
  • cassandra.decoder.dict_factory has moved to cassandra.query.dict_factory

  • +
  • cassandra.decoder.ordered_dict_factory has moved to cassandra.query.ordered_dict_factory

  • +
+

Exceptions that were in cassandra.decoder have been moved to cassandra.protocol. If +you handle any of these exceptions, you must adjust the code accordingly.

+
+
+
+

1.1.2

+

May 8, 2014

+
+

Features

+
    +
  • Allow a specific compression type to be requested for communications with +Cassandra and prefer lz4 if available

  • +
+
+
+

Bug Fixes

+
    +
  • Update token metadata (for TokenAware calculations) when a node is removed +from the ring

  • +
  • Fix file handle leak with gevent reactor due to blocking Greenlet kills when +closing excess connections

  • +
  • Avoid handling a node coming up multiple times due to a reconnection attempt +succeeding close to the same time that an UP notification is pushed

  • +
  • Fix duplicate node-up handling, which could result in multiple reconnectors +being started as well as the executor threads becoming deadlocked, preventing +future node up or node down handling from being executed.

  • +
  • Handle exhausted ReconnectionPolicy schedule correctly

  • +
+
+
+

Other

+
    +
  • Don’t log at ERROR when a connection is closed during the startup +communications

  • +
  • Mke scales, blist optional dependencies

  • +
+
+
+
+

1.1.1

+

April 16, 2014

+
+

Bug Fixes

+
    +
  • Fix unconditional import of nose in setup.py (github #111)

  • +
+
+
+
+

1.1.0

+

April 16, 2014

+
+

Features

+
    +
  • Gevent is now supported through monkey-patching the stdlib (PYTHON-7, +github issue #46)

  • +
  • Support static columns in schemas, which are available starting in +Cassandra 2.1. (github issue #91)

  • +
  • Add debian packaging (github issue #101)

  • +
  • Add utility methods for easy concurrent execution of statements. See +the new cassandra.concurrent module. (github issue #7)

  • +
+
+
+

Bug Fixes

+
    +
  • Correctly supply compaction and compression parameters in CREATE statements +for tables when working with Cassandra 2.0+

  • +
  • Lowercase boolean literals when generating schemas

  • +
  • Ignore SSL_ERROR_WANT_READ and SSL_ERROR_WANT_WRITE socket errors. Previously, +these resulted in the connection being defuncted, but they can safely be +ignored by the driver.

  • +
  • Don’t reconnect the control connection every time Cluster.connect() is +called

  • +
  • Avoid race condition that could leave ResponseFuture callbacks uncalled +if the callback was added outside of the event loop thread (github issue #95)

  • +
  • Properly escape keyspace name in Session.set_keyspace(). Previously, the +keyspace name was quoted, but any quotes in the string were not escaped.

  • +
  • Avoid adding hosts to the load balancing policy before their datacenter +and rack information has been set, if possible.

  • +
  • Avoid KeyError when updating metadata after droping a table (github issues +#97, #98)

  • +
  • Use tuples instead of sets for DCAwareLoadBalancingPolicy to ensure equal +distribution of requests

  • +
+
+
+

Other

+
    +
  • Don’t ignore column names when parsing typestrings. This is needed for +user-defined type support. (github issue #90)

  • +
  • Better error message when libevwrapper is not found

  • +
  • Only try to import scales when metrics are enabled (github issue #92)

  • +
  • Cut down on the number of queries executing when a new Cluster +connects and when the control connection has to reconnect (github issue #104, +PYTHON-59)

  • +
  • Issue warning log when schema versions do not match

  • +
+
+
+
+

1.0.2

+

March 4, 2014

+
+

Bug Fixes

+
    +
  • With asyncorereactor, correctly handle EAGAIN/EWOULDBLOCK when the message from +Cassandra is a multiple of the read buffer size. Previously, if no more data +became available to read on the socket, the message would never be processed, +resulting in an OperationTimedOut error.

  • +
  • Double quote keyspace, table and column names that require them (those using +uppercase characters or keywords) when generating CREATE statements through +KeyspaceMetadata and TableMetadata.

  • +
  • Decode TimestampType as DateType. (Cassandra replaced DateType with +TimestampType to fix sorting of pre-unix epoch dates in CASSANDRA-5723.)

  • +
  • Handle latest table options when parsing the schema and generating +CREATE statements.

  • +
  • Avoid ‘Set changed size during iteration’ during query plan generation +when hosts go up or down

  • +
+
+
+

Other

+
    +
  • Remove ignored tracing_enabled parameter for SimpleStatement. The +correct way to trace a query is by setting the trace argument to True +in Session.execute() and Session.execute_async().

  • +
  • Raise TypeError instead of cassandra.query.InvalidParameterTypeError when +a parameter for a prepared statement has the wrong type; remove +cassandra.query.InvalidParameterTypeError.

  • +
  • More consistent type checking for query parameters

  • +
  • Add option to a return special object for empty string values for non-string +columns

  • +
+
+
+
+

1.0.1

+

Feb 19, 2014

+
+

Bug Fixes

+
    +
  • Include table indexes in KeyspaceMetadata.export_as_string()

  • +
  • Fix broken token awareness on ByteOrderedPartitioner

  • +
  • Always close socket when defuncting error’ed connections to avoid a potential +file descriptor leak

  • +
  • Handle “custom” types (such as the replaced DateType) correctly

  • +
  • With libevreactor, correctly handle EAGAIN/EWOULDBLOCK when the message from +Cassandra is a multiple of the read buffer size. Previously, if no more data +became available to read on the socket, the message would never be processed, +resulting in an OperationTimedOut error.

  • +
  • Don’t break tracing when a Session’s row_factory is not the default +namedtuple_factory.

  • +
  • Handle data that is already utf8-encoded for UTF8Type values

  • +
  • Fix token-aware routing for tokens that fall before the first node token in +the ring and tokens that exactly match a node’s token

  • +
  • Tolerate null source_elapsed values for Trace events. These may not be +set when events complete after the main operation has already completed.

  • +
+
+
+

Other

+
    +
  • Skip sending OPTIONS message on connection creation if compression is +disabled or not available and a CQL version has not been explicitly +set

  • +
  • Add details about errors and the last queried host to OperationTimedOut

  • +
+
+
+
+

1.0.0 Final

+

Jan 29, 2014

+
+

Bug Fixes

+
    +
  • Prevent leak of Scheduler thread (even with proper shutdown)

  • +
  • Correctly handle ignored hosts, which are common with the +DCAwareRoundRobinPolicy

  • +
  • Hold strong reference to prepared statement while executing it to avoid +garbage collection

  • +
  • Add NullHandler logging handler to the cassandra package to avoid +warnings about there being no configured logger

  • +
  • Fix bad handling of nodes that have been removed from the cluster

  • +
  • Properly escape string types within cql collections

  • +
  • Handle setting the same keyspace twice in a row

  • +
  • Avoid race condition during schema agreement checks that could result +in schema update queries returning before all nodes had seen the change

  • +
  • Preserve millisecond-level precision in datetimes when performing inserts +with simple (non-prepared) statements

  • +
  • Properly defunct connections when libev reports an error by setting +errno instead of simply logging the error

  • +
  • Fix endless hanging of some requests when using the libev reactor

  • +
  • Always start a reconnection process when we fail to connect to +a newly bootstrapped node

  • +
  • Generators map to CQL lists, not key sequences

  • +
  • Always defunct connections when an internal operation fails

  • +
  • Correctly break from handle_write() if nothing was sent (asyncore +reactor only)

  • +
  • Avoid potential double-erroring of callbacks when a connection +becomes defunct

  • +
+
+
+

Features

+
    +
  • Add default query timeout to Session

  • +
  • Add timeout parameter to Session.execute()

  • +
  • Add WhiteListRoundRobinPolicy as a load balancing policy option

  • +
  • Support for consistency level LOCAL_ONE

  • +
  • Make the backoff for fetching traces exponentially increasing and +configurable

  • +
+
+
+

Other

+
    +
  • Raise Exception if TokenAwarePolicy is used against a cluster using the +Murmur3Partitioner if the murmur3 C extension has not been compiled

  • +
  • Add encoder mapping for OrderedDict

  • +
  • Use timeouts on all control connection queries

  • +
  • Benchmark improvements, including command line options and eay +multithreading support

  • +
  • Reduced lock contention when using the asyncore reactor

  • +
  • Warn when non-datetimes are used for ‘timestamp’ column values in +prepared statements

  • +
  • Add requirements.txt and test-requirements.txt

  • +
  • TravisCI integration for running unit tests against Python 2.6, +Python 2.7, and PyPy

  • +
+
+
+
+

1.0.0b7

+

Nov 12, 2013

+

This release makes many stability improvements, especially around +prepared statements and node failure handling. In particular, +several cases where a request would never be completed (and as a +result, leave the application hanging) have been resolved.

+
+

Features

+
    +
  • Add timeout kwarg to ResponseFuture.result()

  • +
  • Create connection pools to all hosts in parallel when initializing +new Sesssions.

  • +
+
+
+

Bug Fixes

+
    +
  • Properly set exception on ResponseFuture when a query fails +against all hosts

  • +
  • Improved cleanup and reconnection efforts when reconnection fails +on a node that has recently come up

  • +
  • Use correct consistency level when retrying failed operations +against a different host. (An invalid consistency level was being +used, causing the retry to fail.)

  • +
  • Better error messages for failed Session.prepare() opertaions

  • +
  • Prepare new statements against all hosts in parallel (formerly +sequential)

  • +
  • Fix failure to save the new current keyspace on connections. (This +could cause problems for prepared statements and lead to extra +operations to continuously re-set the keyspace.)

  • +
  • Avoid sharing LoadBalancingPolicies across Cluster instances. (When +a second Cluster was connected, it effectively mark nodes down for the +first Cluster.)

  • +
  • Better handling of failures during the re-preparation sequence for +unrecognized prepared statements

  • +
  • Throttle trashing of underutilized connections to avoid trashing newly +created connections

  • +
  • Fix race condition which could result in trashed connections being closed +before the last operations had completed

  • +
  • Avoid preparing statements on the event loop thread (which could lead to +deadlock)

  • +
  • Correctly mark up non-contact point nodes discovered by the control +connection. (This lead to prepared statements not being prepared +against those hosts, generating extra traffic later when the +statements were executed and unrecognized.)

  • +
  • Correctly handle large messages through libev

  • +
  • Add timeout to schema agreement check queries

  • +
  • More complete (and less contended) locking around manipulation of the +pending message deque for libev connections

  • +
+
+
+

Other

+
    +
  • Prepare statements in batches of 10. (When many prepared statements +are in use, this allows the driver to start utilizing nodes that +were restarted more quickly.)

  • +
  • Better debug logging around connection management

  • +
  • Don’t retain unreferenced prepared statements in the local cache. +(If many different prepared statements were created, this would +increase memory usage and greatly increase the amount of time +required to begin utilizing a node that was added or marked +up.)

  • +
+
+
+
+

1.0.0b6

+

Oct 22, 2013

+
+

Bug Fixes

+
    +
  • Use lazy string formatting when logging

  • +
  • Avoid several deadlock scenarios, especially when nodes go down

  • +
  • Avoid trashing newly created connections due to insufficient traffic

  • +
  • Gracefully handle un-handled Exceptions when erroring callbacks

  • +
+
+
+

Other

+
    +
  • Node state listeners (which are called when a node is added, removed, +goes down, or comes up) should now be registered through +Cluster.register_listener() instead of through a host’s HealthMonitor +(which has been removed)

  • +
+
+
+
+

1.0.0b5

+

Oct 10, 2013

+
+

Features

+
    +
  • SSL support

  • +
+
+
+

Bug Fixes

+
    +
  • Avoid KeyError when building replica map for NetworkTopologyStrategy

  • +
  • Work around python bug which causes deadlock when a thread imports +the utf8 module

  • +
  • Handle no blist library, which is not compatible with pypy

  • +
  • Avoid deadlock triggered by a keyspace being set on a connection (which +may happen automatically for new connections)

  • +
+
+
+

Other

+
    +
  • Switch packaging from Distribute to setuptools, improved C extension +support

  • +
  • Use PEP 386 compliant beta and post-release versions

  • +
+
+
+
+

1.0.0-beta4

+

Sep 24, 2013

+
+

Features

+
    +
  • Handle new blob syntax in Cassandra 2.0 by accepting bytearray +objects for blob values

  • +
  • Add cql_version kwarg to Cluster.__init__

  • +
+
+
+

Bug Fixes

+
    +
  • Fix KeyError when building token map with NetworkTopologyStrategy +keyspaces (this prevented a Cluster from successfully connecting +at all).

  • +
  • Don’t lose default consitency level from parent PreparedStatement +when creating BoundStatements

  • +
+
+
+
+

1.0.0-beta3

+

Sep 20, 2013

+
+

Features

+
    +
  • Support for LZ4 compression (Cassandra 2.0+)

  • +
  • Token-aware routing will now utilize all replicas for a query instead +of just the first replica

  • +
+
+
+

Bug Fixes

+
    +
  • Fix libev include path for CentOS

  • +
  • Fix varint packing of the value 0

  • +
  • Correctly pack unicode values

  • +
  • Don’t attempt to return failed connections to the pool when a final result +is set

  • +
  • Fix bad iteration of connection credentials

  • +
  • Use blist’s orderedset for set collections and OrderedDict for map +collections so that Cassandra’s ordering is preserved

  • +
  • Fix connection failure on Windows due to unavailability of inet_pton +and inet_ntop. (Note that IPv6 inet_address values are still not +supported on Windows.)

  • +
  • Boolean constants shouldn’t be surrounded by single quotes

  • +
  • Avoid a potential loss of precision on float constants due to string +formatting

  • +
  • Actually utilize non-standard ports set on Cluster objects

  • +
  • Fix export of schema as a set of CQL queries

  • +
+
+
+

Other

+
    +
  • Use cStringIO for connection buffer for better performance

  • +
  • Add __repr__ method for Statement classes

  • +
  • Raise InvalidTypeParameterError when parameters of the wrong +type are used with statements

  • +
  • Make all tests compatible with Python 2.6

  • +
  • Add 1s timeout for opening new connections

  • +
+
+
+
+

1.0.0-beta2

+

Aug 19, 2013

+
+

Bug Fixes

+
    +
  • Fix pip packaging

  • +
+
+
+
+

1.0.0-beta

+

Aug 16, 2013

+

Initial release

+
+
+ + +
+ + + + + +
+ + +
+
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.25.11-scylla/CNAME b/3.25.11-scylla/CNAME new file mode 100644 index 0000000000..9f3e01a070 --- /dev/null +++ b/3.25.11-scylla/CNAME @@ -0,0 +1 @@ +python-driver.docs.scylladb.com \ No newline at end of file diff --git a/3.25.11-scylla/_sources/CHANGELOG.rst.txt b/3.25.11-scylla/_sources/CHANGELOG.rst.txt new file mode 100644 index 0000000000..f6d642b27f --- /dev/null +++ b/3.25.11-scylla/_sources/CHANGELOG.rst.txt @@ -0,0 +1,7 @@ +:orphan: + +********* +CHANGELOG +********* + +.. include:: ../CHANGELOG.rst diff --git a/3.25.11-scylla/_sources/api/cassandra.rst.txt b/3.25.11-scylla/_sources/api/cassandra.rst.txt new file mode 100644 index 0000000000..d46aae56cb --- /dev/null +++ b/3.25.11-scylla/_sources/api/cassandra.rst.txt @@ -0,0 +1,77 @@ +:mod:`cassandra` - Exceptions and Enums +======================================= + +.. module:: cassandra + +.. data:: __version_info__ + + The version of the driver in a tuple format + +.. data:: __version__ + + The version of the driver in a string format + +.. autoclass:: ConsistencyLevel + :members: + +.. autoclass:: ProtocolVersion + :members: + +.. autoclass:: UserFunctionDescriptor + :members: + :inherited-members: + +.. autoclass:: UserAggregateDescriptor + :members: + :inherited-members: + +.. autoexception:: DriverException() + :members: + +.. autoexception:: RequestExecutionException() + :members: + +.. autoexception:: Unavailable() + :members: + +.. autoexception:: Timeout() + :members: + +.. autoexception:: ReadTimeout() + :members: + +.. autoexception:: WriteTimeout() + :members: + +.. autoexception:: CoordinationFailure() + :members: + +.. autoexception:: ReadFailure() + :members: + +.. autoexception:: WriteFailure() + :members: + +.. autoexception:: FunctionFailure() + :members: + +.. autoexception:: RequestValidationException() + :members: + +.. autoexception:: ConfigurationException() + :members: + +.. autoexception:: AlreadyExists() + :members: + +.. autoexception:: InvalidRequest() + :members: + +.. autoexception:: Unauthorized() + :members: + +.. autoexception:: AuthenticationFailed() + :members: + +.. autoexception:: OperationTimedOut() + :members: diff --git a/3.25.11-scylla/_sources/api/cassandra/auth.rst.txt b/3.25.11-scylla/_sources/api/cassandra/auth.rst.txt new file mode 100644 index 0000000000..58c964cf89 --- /dev/null +++ b/3.25.11-scylla/_sources/api/cassandra/auth.rst.txt @@ -0,0 +1,22 @@ +``cassandra.auth`` - Authentication +=================================== + +.. module:: cassandra.auth + +.. autoclass:: AuthProvider + :members: + +.. autoclass:: Authenticator + :members: + +.. autoclass:: PlainTextAuthProvider + :members: + +.. autoclass:: PlainTextAuthenticator + :members: + +.. autoclass:: SaslAuthProvider + :members: + +.. autoclass:: SaslAuthenticator + :members: diff --git a/3.25.11-scylla/_sources/api/cassandra/cluster.rst.txt b/3.25.11-scylla/_sources/api/cassandra/cluster.rst.txt new file mode 100644 index 0000000000..2b3d7828a8 --- /dev/null +++ b/3.25.11-scylla/_sources/api/cassandra/cluster.rst.txt @@ -0,0 +1,228 @@ +``cassandra.cluster`` - Clusters and Sessions +============================================= + +.. module:: cassandra.cluster + +.. autoclass:: Cluster ([contact_points=('127.0.0.1',)][, port=9042][, executor_threads=2], **attr_kwargs) + + .. autoattribute:: contact_points + + .. autoattribute:: port + + .. autoattribute:: cql_version + + .. autoattribute:: protocol_version + + .. autoattribute:: compression + + .. autoattribute:: auth_provider + + .. autoattribute:: load_balancing_policy + + .. autoattribute:: reconnection_policy + + .. autoattribute:: default_retry_policy + :annotation: = + + .. autoattribute:: conviction_policy_factory + + .. autoattribute:: address_translator + + .. autoattribute:: metrics_enabled + + .. autoattribute:: metrics + + .. autoattribute:: ssl_context + + .. autoattribute:: ssl_options + + .. autoattribute:: sockopts + + .. autoattribute:: max_schema_agreement_wait + + .. autoattribute:: metadata + + .. autoattribute:: connection_class + + .. autoattribute:: control_connection_timeout + + .. autoattribute:: idle_heartbeat_interval + + .. autoattribute:: idle_heartbeat_timeout + + .. autoattribute:: schema_event_refresh_window + + .. autoattribute:: topology_event_refresh_window + + .. autoattribute:: status_event_refresh_window + + .. autoattribute:: prepare_on_all_hosts + + .. autoattribute:: reprepare_on_up + + .. autoattribute:: connect_timeout + + .. autoattribute:: schema_metadata_enabled + :annotation: = True + + .. autoattribute:: token_metadata_enabled + :annotation: = True + + .. autoattribute:: timestamp_generator + + .. autoattribute:: endpoint_factory + + .. autoattribute:: cloud + + .. automethod:: connect + + .. automethod:: shutdown + + .. automethod:: register_user_type + + .. automethod:: register_listener + + .. automethod:: unregister_listener + + .. automethod:: add_execution_profile + + .. automethod:: set_max_requests_per_connection + + .. automethod:: get_max_requests_per_connection + + .. automethod:: set_min_requests_per_connection + + .. automethod:: get_min_requests_per_connection + + .. automethod:: get_core_connections_per_host + + .. automethod:: set_core_connections_per_host + + .. automethod:: get_max_connections_per_host + + .. automethod:: set_max_connections_per_host + + .. automethod:: get_control_connection_host + + .. automethod:: refresh_schema_metadata + + .. automethod:: refresh_keyspace_metadata + + .. automethod:: refresh_table_metadata + + .. automethod:: refresh_user_type_metadata + + .. automethod:: refresh_user_function_metadata + + .. automethod:: refresh_user_aggregate_metadata + + .. automethod:: refresh_nodes + + .. automethod:: set_meta_refresh_enabled + +.. autoclass:: ExecutionProfile (load_balancing_policy=, retry_policy=None, consistency_level=ConsistencyLevel.LOCAL_ONE, serial_consistency_level=None, request_timeout=10.0, row_factory=, speculative_execution_policy=None) + :members: + :exclude-members: consistency_level + + .. autoattribute:: consistency_level + :annotation: = LOCAL_ONE + +.. autoclass:: GraphExecutionProfile (load_balancing_policy=_NOT_SET, retry_policy=None, consistency_level=ConsistencyLevel.LOCAL_ONE, serial_consistency_level=None, request_timeout=30.0, row_factory=None, graph_options=None, continuous_paging_options=_NOT_SET) + :members: + +.. autoclass:: GraphAnalyticsExecutionProfile (load_balancing_policy=None, retry_policy=None, consistency_level=ConsistencyLevel.LOCAL_ONE, serial_consistency_level=None, request_timeout=3600. * 24. * 7., row_factory=None, graph_options=None) + :members: + +.. autodata:: EXEC_PROFILE_DEFAULT + :annotation: + +.. autodata:: EXEC_PROFILE_GRAPH_DEFAULT + :annotation: + +.. autodata:: EXEC_PROFILE_GRAPH_SYSTEM_DEFAULT + :annotation: + +.. autodata:: EXEC_PROFILE_GRAPH_ANALYTICS_DEFAULT + :annotation: + +.. autoclass:: Session () + + .. autoattribute:: default_timeout + :annotation: = 10.0 + + .. autoattribute:: default_consistency_level + :annotation: = LOCAL_ONE + + .. autoattribute:: default_serial_consistency_level + :annotation: = None + + .. autoattribute:: row_factory + :annotation: = + + .. autoattribute:: default_fetch_size + + .. autoattribute:: use_client_timestamp + + .. autoattribute:: timestamp_generator + + .. autoattribute:: encoder + + .. autoattribute:: client_protocol_handler + + .. automethod:: execute(statement[, parameters][, timeout][, trace][, custom_payload][, paging_state][, host][, execute_as]) + + .. automethod:: execute_async(statement[, parameters][, trace][, custom_payload][, paging_state][, host][, execute_as]) + + .. automethod:: execute_graph(statement[, parameters][, trace][, execution_profile=EXEC_PROFILE_GRAPH_DEFAULT][, execute_as]) + + .. automethod:: execute_graph_async(statement[, parameters][, trace][, execution_profile=EXEC_PROFILE_GRAPH_DEFAULT][, execute_as]) + + .. automethod:: prepare(statement) + + .. automethod:: shutdown() + + .. automethod:: set_keyspace(keyspace) + + .. automethod:: get_execution_profile + + .. automethod:: execution_profile_clone_update + + .. automethod:: add_request_init_listener + + .. automethod:: remove_request_init_listener + +.. autoclass:: ResponseFuture () + + .. autoattribute:: query + + .. automethod:: result() + + .. automethod:: get_query_trace() + + .. automethod:: get_all_query_traces() + + .. autoattribute:: custom_payload() + + .. autoattribute:: is_schema_agreed + + .. autoattribute:: has_more_pages + + .. autoattribute:: warnings + + .. automethod:: start_fetching_next_page() + + .. automethod:: add_callback(fn, *args, **kwargs) + + .. automethod:: add_errback(fn, *args, **kwargs) + + .. automethod:: add_callbacks(callback, errback, callback_args=(), callback_kwargs=None, errback_args=(), errback_args=None) + +.. autoclass:: ResultSet () + :members: + +.. autoexception:: QueryExhausted () + +.. autoexception:: NoHostAvailable () + :members: + +.. autoexception:: UserTypeDoesNotExist () diff --git a/3.25.11-scylla/_sources/api/cassandra/concurrent.rst.txt b/3.25.11-scylla/_sources/api/cassandra/concurrent.rst.txt new file mode 100644 index 0000000000..f4bab6f048 --- /dev/null +++ b/3.25.11-scylla/_sources/api/cassandra/concurrent.rst.txt @@ -0,0 +1,8 @@ +``cassandra.concurrent`` - Utilities for Concurrent Statement Execution +======================================================================= + +.. module:: cassandra.concurrent + +.. autofunction:: execute_concurrent + +.. autofunction:: execute_concurrent_with_args diff --git a/3.25.11-scylla/_sources/api/cassandra/connection.rst.txt b/3.25.11-scylla/_sources/api/cassandra/connection.rst.txt new file mode 100644 index 0000000000..32cca590c0 --- /dev/null +++ b/3.25.11-scylla/_sources/api/cassandra/connection.rst.txt @@ -0,0 +1,21 @@ +``cassandra.connection`` - Low Level Connection Info +==================================================== + +.. module:: cassandra.connection + +.. autoexception:: ConnectionException () +.. autoexception:: ConnectionShutdown () +.. autoexception:: ConnectionBusy () +.. autoexception:: ProtocolError () + +.. autoclass:: EndPoint + :members: + +.. autoclass:: EndPointFactory + :members: + +.. autoclass:: SniEndPoint + +.. autoclass:: SniEndPointFactory + +.. autoclass:: UnixSocketEndPoint diff --git a/3.25.11-scylla/_sources/api/cassandra/cqlengine/columns.rst.txt b/3.25.11-scylla/_sources/api/cassandra/cqlengine/columns.rst.txt new file mode 100644 index 0000000000..d44be8adb8 --- /dev/null +++ b/3.25.11-scylla/_sources/api/cassandra/cqlengine/columns.rst.txt @@ -0,0 +1,89 @@ +``cassandra.cqlengine.columns`` - Column types for object mapping models +======================================================================== + +.. module:: cassandra.cqlengine.columns + +Columns +------- + +Columns in your models map to columns in your CQL table. You define CQL columns by defining column attributes on your model classes. +For a model to be valid it needs at least one primary key column and one non-primary key column. + +Just as in CQL, the order you define your columns in is important, and is the same order they are defined in on a model's corresponding table. + +Each column on your model definitions needs to be an instance of a Column class. + +.. autoclass:: Column(**kwargs) + + .. autoattribute:: primary_key + + .. autoattribute:: partition_key + + .. autoattribute:: index + + .. autoattribute:: custom_index + + .. autoattribute:: db_field + + .. autoattribute:: default + + .. autoattribute:: required + + .. autoattribute:: clustering_order + + .. autoattribute:: discriminator_column + + .. autoattribute:: static + +Column Types +------------ + +Columns of all types are initialized by passing :class:`.Column` attributes to the constructor by keyword. + +.. autoclass:: Ascii(**kwargs) + +.. autoclass:: BigInt(**kwargs) + +.. autoclass:: Blob(**kwargs) + +.. autoclass:: Bytes(**kwargs) + +.. autoclass:: Boolean(**kwargs) + +.. autoclass:: Counter + +.. autoclass:: Date(**kwargs) + +.. autoclass:: DateTime(**kwargs) + + .. autoattribute:: truncate_microseconds + +.. autoclass:: Decimal(**kwargs) + +.. autoclass:: Double(**kwargs) + +.. autoclass:: Float + +.. autoclass:: Integer(**kwargs) + +.. autoclass:: List + +.. autoclass:: Map + +.. autoclass:: Set + +.. autoclass:: SmallInt(**kwargs) + +.. autoclass:: Text + +.. autoclass:: Time(**kwargs) + +.. autoclass:: TimeUUID(**kwargs) + +.. autoclass:: TinyInt(**kwargs) + +.. autoclass:: UserDefinedType + +.. autoclass:: UUID(**kwargs) + +.. autoclass:: VarInt(**kwargs) diff --git a/3.25.11-scylla/_sources/api/cassandra/cqlengine/connection.rst.txt b/3.25.11-scylla/_sources/api/cassandra/cqlengine/connection.rst.txt new file mode 100644 index 0000000000..0f584fcca2 --- /dev/null +++ b/3.25.11-scylla/_sources/api/cassandra/cqlengine/connection.rst.txt @@ -0,0 +1,16 @@ +``cassandra.cqlengine.connection`` - Connection management for cqlengine +======================================================================== + +.. module:: cassandra.cqlengine.connection + +.. autofunction:: default + +.. autofunction:: set_session + +.. autofunction:: setup + +.. autofunction:: register_connection + +.. autofunction:: unregister_connection + +.. autofunction:: set_default_connection diff --git a/3.25.11-scylla/_sources/api/cassandra/cqlengine/management.rst.txt b/3.25.11-scylla/_sources/api/cassandra/cqlengine/management.rst.txt new file mode 100644 index 0000000000..fb483abc81 --- /dev/null +++ b/3.25.11-scylla/_sources/api/cassandra/cqlengine/management.rst.txt @@ -0,0 +1,19 @@ +``cassandra.cqlengine.management`` - Schema management for cqlengine +======================================================================== + +.. module:: cassandra.cqlengine.management + +A collection of functions for managing keyspace and table schema. + +.. autofunction:: create_keyspace_simple + +.. autofunction:: create_keyspace_network_topology + +.. autofunction:: drop_keyspace + +.. autofunction:: sync_table + +.. autofunction:: sync_type + +.. autofunction:: drop_table + diff --git a/3.25.11-scylla/_sources/api/cassandra/cqlengine/models.rst.txt b/3.25.11-scylla/_sources/api/cassandra/cqlengine/models.rst.txt new file mode 100644 index 0000000000..60b1471184 --- /dev/null +++ b/3.25.11-scylla/_sources/api/cassandra/cqlengine/models.rst.txt @@ -0,0 +1,197 @@ +``cassandra.cqlengine.models`` - Table models for object mapping +================================================================ + +.. module:: cassandra.cqlengine.models + +Model +----- +.. autoclass:: Model(\*\*kwargs) + + The initializer creates an instance of the model. Pass in keyword arguments for columns you've defined on the model. + + .. code-block:: python + + class Person(Model): + id = columns.UUID(primary_key=True) + first_name = columns.Text() + last_name = columns.Text() + + person = Person(first_name='Blake', last_name='Eggleston') + person.first_name #returns 'Blake' + person.last_name #returns 'Eggleston' + + Model attributes define how the model maps to tables in the database. These are class variables that should be set + when defining Model deriviatives. + + .. autoattribute:: __abstract__ + :annotation: = False + + .. autoattribute:: __table_name__ + + .. autoattribute:: __table_name_case_sensitive__ + + .. autoattribute:: __keyspace__ + + .. autoattribute:: __connection__ + + .. attribute:: __default_ttl__ + :annotation: = None + + Will be deprecated in release 4.0. You can set the default ttl by configuring the table ``__options__``. See :ref:`ttl-change` for more details. + + .. autoattribute:: __discriminator_value__ + + See :ref:`model_inheritance` for usage examples. + + Each table can have its own set of configuration options, including compaction. Unspecified, these default to sensible values in + the server. To override defaults, set options using the model ``__options__`` attribute, which allows options specified a dict. + + When a table is synced, it will be altered to match the options set on your table. + This means that if you are changing settings manually they will be changed back on resync. + + Do not use the options settings of cqlengine if you want to manage your compaction settings manually. + + See the `list of supported table properties for more information + `_. + + .. attribute:: __options__ + + For example: + + .. code-block:: python + + class User(Model): + __options__ = {'compaction': {'class': 'LeveledCompactionStrategy', + 'sstable_size_in_mb': '64', + 'tombstone_threshold': '.2'}, + 'comment': 'User data stored here'} + + user_id = columns.UUID(primary_key=True) + name = columns.Text() + + or : + + .. code-block:: python + + class TimeData(Model): + __options__ = {'compaction': {'class': 'SizeTieredCompactionStrategy', + 'bucket_low': '.3', + 'bucket_high': '2', + 'min_threshold': '2', + 'max_threshold': '64', + 'tombstone_compaction_interval': '86400'}, + 'gc_grace_seconds': '0'} + + .. autoattribute:: __compute_routing_key__ + + + The base methods allow creating, storing, and querying modeled objects. + + .. automethod:: create + + .. method:: if_not_exists() + + Check the existence of an object before insertion. The existence of an + object is determined by its primary key(s). And please note using this flag + would incur performance cost. + + If the insertion isn't applied, a :class:`~cassandra.cqlengine.query.LWTException` is raised. + + .. code-block:: python + + try: + TestIfNotExistsModel.if_not_exists().create(id=id, count=9, text='111111111111') + except LWTException as e: + # handle failure case + print e.existing # dict containing LWT result fields + + This method is supported on Cassandra 2.0 or later. + + .. method:: if_exists() + + Check the existence of an object before an update or delete. The existence of an + object is determined by its primary key(s). And please note using this flag + would incur performance cost. + + If the update or delete isn't applied, a :class:`~cassandra.cqlengine.query.LWTException` is raised. + + .. code-block:: python + + try: + TestIfExistsModel.objects(id=id).if_exists().update(count=9, text='111111111111') + except LWTException as e: + # handle failure case + pass + + This method is supported on Cassandra 2.0 or later. + + .. automethod:: save + + .. automethod:: update + + .. method:: iff(**values) + + Checks to ensure that the values specified are correct on the Cassandra cluster. + Simply specify the column(s) and the expected value(s). As with if_not_exists, + this incurs a performance cost. + + If the insertion isn't applied, a :class:`~cassandra.cqlengine.query.LWTException` is raised. + + .. code-block:: python + + t = TestTransactionModel(text='some text', count=5) + try: + t.iff(count=5).update('other text') + except LWTException as e: + # handle failure case + print e.existing # existing object + + .. automethod:: get + + .. automethod:: filter + + .. automethod:: all + + .. automethod:: delete + + .. method:: batch(batch_object) + + Sets the batch object to run instance updates and inserts queries with. + + See :doc:`/cqlengine/batches` for usage examples + + .. automethod:: timeout + + .. method:: timestamp(timedelta_or_datetime) + + Sets the timestamp for the query + + .. method:: ttl(ttl_in_sec) + + Sets the ttl values to run instance updates and inserts queries with. + + .. method:: using(connection=None) + + Change the context on the fly of the model instance (keyspace, connection) + + .. automethod:: column_family_name + + Models also support dict-like access: + + .. method:: len(m) + + Returns the number of columns defined in the model + + .. method:: m[col_name] + + Returns the value of column ``col_name`` + + .. method:: m[col_name] = value + + Set ``m[col_name]`` to value + + .. automethod:: keys + + .. automethod:: values + + .. automethod:: items diff --git a/3.25.11-scylla/_sources/api/cassandra/cqlengine/query.rst.txt b/3.25.11-scylla/_sources/api/cassandra/cqlengine/query.rst.txt new file mode 100644 index 0000000000..ce8f764b6b --- /dev/null +++ b/3.25.11-scylla/_sources/api/cassandra/cqlengine/query.rst.txt @@ -0,0 +1,71 @@ +``cassandra.cqlengine.query`` - Query and filter model objects +================================================================= + +.. module:: cassandra.cqlengine.query + +QuerySet +-------- +QuerySet objects are typically obtained by calling :meth:`~.cassandra.cqlengine.models.Model.objects` on a model class. +The methods here are used to filter, order, and constrain results. + +.. autoclass:: ModelQuerySet + + .. automethod:: all + + .. automethod:: batch + + .. automethod:: consistency + + .. automethod:: count + + .. method:: len(queryset) + + Returns the number of rows matched by this query. This function uses :meth:`~.cassandra.cqlengine.query.ModelQuerySet.count` internally. + + *Note: This function executes a SELECT COUNT() and has a performance cost on large datasets* + + .. automethod:: distinct + + .. automethod:: filter + + .. automethod:: get + + .. automethod:: limit + + .. automethod:: fetch_size + + .. automethod:: if_not_exists + + .. automethod:: if_exists + + .. automethod:: order_by + + .. automethod:: allow_filtering + + .. automethod:: only + + .. automethod:: defer + + .. automethod:: timestamp + + .. automethod:: ttl + + .. automethod:: using + + .. _blind_updates: + + .. automethod:: update + +.. autoclass:: BatchQuery + :members: + + .. automethod:: add_query + .. automethod:: execute + +.. autoclass:: ContextQuery + +.. autoclass:: DoesNotExist + +.. autoclass:: MultipleObjectsReturned + +.. autoclass:: LWTException diff --git a/3.25.11-scylla/_sources/api/cassandra/cqlengine/usertype.rst.txt b/3.25.11-scylla/_sources/api/cassandra/cqlengine/usertype.rst.txt new file mode 100644 index 0000000000..ebed187da9 --- /dev/null +++ b/3.25.11-scylla/_sources/api/cassandra/cqlengine/usertype.rst.txt @@ -0,0 +1,10 @@ +``cassandra.cqlengine.usertype`` - Model classes for User Defined Types +======================================================================= + +.. module:: cassandra.cqlengine.usertype + +UserType +-------- +.. autoclass:: UserType + + .. autoattribute:: __type_name__ diff --git a/3.25.11-scylla/_sources/api/cassandra/datastax/graph/fluent/index.rst.txt b/3.25.11-scylla/_sources/api/cassandra/datastax/graph/fluent/index.rst.txt new file mode 100644 index 0000000000..5547e0fdd7 --- /dev/null +++ b/3.25.11-scylla/_sources/api/cassandra/datastax/graph/fluent/index.rst.txt @@ -0,0 +1,24 @@ +:mod:`cassandra.datastax.graph.fluent` +====================================== + +.. module:: cassandra.datastax.graph.fluent + +.. autoclass:: DseGraph + + .. autoattribute:: DSE_GRAPH_QUERY_LANGUAGE + + .. automethod:: create_execution_profile + + .. automethod:: query_from_traversal + + .. automethod:: traversal_source(session=None, graph_name=None, execution_profile=EXEC_PROFILE_GRAPH_DEFAULT, traversal_class=None) + + .. automethod:: batch(session=None, execution_profile=None) + +.. autoclass:: DSESessionRemoteGraphConnection(session[, graph_name, execution_profile]) + +.. autoclass:: BaseGraphRowFactory + +.. autoclass:: graph_traversal_row_factory + +.. autoclass:: graph_traversal_dse_object_row_factory diff --git a/3.25.11-scylla/_sources/api/cassandra/datastax/graph/fluent/predicates.rst.txt b/3.25.11-scylla/_sources/api/cassandra/datastax/graph/fluent/predicates.rst.txt new file mode 100644 index 0000000000..f6e86f6451 --- /dev/null +++ b/3.25.11-scylla/_sources/api/cassandra/datastax/graph/fluent/predicates.rst.txt @@ -0,0 +1,14 @@ +:mod:`cassandra.datastax.graph.fluent.predicates` +================================================= + +.. module:: cassandra.datastax.graph.fluent.predicates + + +.. autoclass:: Search + :members: + +.. autoclass:: CqlCollection + :members: + +.. autoclass:: Geo + :members: diff --git a/3.25.11-scylla/_sources/api/cassandra/datastax/graph/fluent/query.rst.txt b/3.25.11-scylla/_sources/api/cassandra/datastax/graph/fluent/query.rst.txt new file mode 100644 index 0000000000..3dd859f96e --- /dev/null +++ b/3.25.11-scylla/_sources/api/cassandra/datastax/graph/fluent/query.rst.txt @@ -0,0 +1,8 @@ +:mod:`cassandra.datastax.graph.fluent.query` +============================================ + +.. module:: cassandra.datastax.graph.fluent.query + + +.. autoclass:: TraversalBatch + :members: diff --git a/3.25.11-scylla/_sources/api/cassandra/datastax/graph/index.rst.txt b/3.25.11-scylla/_sources/api/cassandra/datastax/graph/index.rst.txt new file mode 100644 index 0000000000..a9b41cbdc2 --- /dev/null +++ b/3.25.11-scylla/_sources/api/cassandra/datastax/graph/index.rst.txt @@ -0,0 +1,133 @@ +``cassandra.datastax.graph`` - Graph Statements, Options, and Row Factories +=========================================================================== + +.. _api-datastax-graph: + +.. module:: cassandra.datastax.graph + +.. autofunction:: single_object_row_factory + +.. autofunction:: graph_result_row_factory + +.. autofunction:: graph_object_row_factory + +.. autofunction:: graph_graphson2_row_factory + +.. autofunction:: graph_graphson3_row_factory + +.. function:: to_int(value) + + Wraps a value to be explicitly serialized as a graphson Int. + +.. function:: to_bigint(value) + + Wraps a value to be explicitly serialized as a graphson Bigint. + +.. function:: to_smallint(value) + + Wraps a value to be explicitly serialized as a graphson Smallint. + +.. function:: to_float(value) + + Wraps a value to be explicitly serialized as a graphson Float. + +.. function:: to_double(value) + + Wraps a value to be explicitly serialized as a graphson Double. + +.. autoclass:: GraphProtocol + :members: + :noindex: + +.. autoclass:: GraphOptions + :noindex: + + .. autoattribute:: graph_name + + .. autoattribute:: graph_source + + .. autoattribute:: graph_language + + .. autoattribute:: graph_read_consistency_level + + .. autoattribute:: graph_write_consistency_level + + .. autoattribute:: is_default_source + + .. autoattribute:: is_analytics_source + + .. autoattribute:: is_graph_source + + .. automethod:: set_source_default + + .. automethod:: set_source_analytics + + .. automethod:: set_source_graph + + +.. autoclass:: SimpleGraphStatement + :members: + :noindex: + +.. autoclass:: Result + :members: + :noindex: + +.. autoclass:: Vertex + :members: + :noindex: + +.. autoclass:: VertexProperty + :members: + :noindex: + +.. autoclass:: Edge + :members: + :noindex: + +.. autoclass:: Path + :members: + :noindex: + +.. autoclass:: T + :members: + :noindex: + +.. autoclass:: GraphSON1Serializer + :members: + :noindex: + +.. autoclass:: GraphSON1Deserializer + :noindex: + + .. automethod:: deserialize_date + + .. automethod:: deserialize_timestamp + + .. automethod:: deserialize_time + + .. automethod:: deserialize_duration + + .. automethod:: deserialize_int + + .. automethod:: deserialize_bigint + + .. automethod:: deserialize_double + + .. automethod:: deserialize_float + + .. automethod:: deserialize_uuid + + .. automethod:: deserialize_blob + + .. automethod:: deserialize_decimal + + .. automethod:: deserialize_point + + .. automethod:: deserialize_linestring + + .. automethod:: deserialize_polygon + +.. autoclass:: GraphSON2Reader + :members: + :noindex: diff --git a/3.25.11-scylla/_sources/api/cassandra/decoder.rst.txt b/3.25.11-scylla/_sources/api/cassandra/decoder.rst.txt new file mode 100644 index 0000000000..e213cc6d74 --- /dev/null +++ b/3.25.11-scylla/_sources/api/cassandra/decoder.rst.txt @@ -0,0 +1,20 @@ +``cassandra.decoder`` - Data Return Formats +=========================================== + +.. module:: cassandra.decoder + +.. function:: tuple_factory + + **Deprecated in 2.0.0.** Use :meth:`cassandra.query.tuple_factory` + +.. function:: named_tuple_factory + + **Deprecated in 2.0.0.** Use :meth:`cassandra.query.named_tuple_factory` + +.. function:: dict_factory + + **Deprecated in 2.0.0.** Use :meth:`cassandra.query.dict_factory` + +.. function:: ordered_dict_factory + + **Deprecated in 2.0.0.** Use :meth:`cassandra.query.ordered_dict_factory` diff --git a/3.25.11-scylla/_sources/api/cassandra/encoder.rst.txt b/3.25.11-scylla/_sources/api/cassandra/encoder.rst.txt new file mode 100644 index 0000000000..de3b180510 --- /dev/null +++ b/3.25.11-scylla/_sources/api/cassandra/encoder.rst.txt @@ -0,0 +1,36 @@ +``cassandra.encoder`` - Encoders for non-prepared Statements +============================================================ + +.. module:: cassandra.encoder + +.. autoclass:: Encoder () + + .. autoattribute:: cassandra.encoder.Encoder.mapping + + .. automethod:: cassandra.encoder.Encoder.cql_encode_none () + + .. automethod:: cassandra.encoder.Encoder.cql_encode_object () + + .. automethod:: cassandra.encoder.Encoder.cql_encode_all_types () + + .. automethod:: cassandra.encoder.Encoder.cql_encode_sequence () + + .. automethod:: cassandra.encoder.Encoder.cql_encode_str () + + .. automethod:: cassandra.encoder.Encoder.cql_encode_unicode () + + .. automethod:: cassandra.encoder.Encoder.cql_encode_bytes () + + Converts strings, buffers, and bytearrays into CQL blob literals. + + .. automethod:: cassandra.encoder.Encoder.cql_encode_datetime () + + .. automethod:: cassandra.encoder.Encoder.cql_encode_date () + + .. automethod:: cassandra.encoder.Encoder.cql_encode_map_collection () + + .. automethod:: cassandra.encoder.Encoder.cql_encode_list_collection () + + .. automethod:: cassandra.encoder.Encoder.cql_encode_set_collection () + + .. automethod:: cql_encode_tuple () diff --git a/3.25.11-scylla/_sources/api/cassandra/graph.rst.txt b/3.25.11-scylla/_sources/api/cassandra/graph.rst.txt new file mode 100644 index 0000000000..43ddd3086c --- /dev/null +++ b/3.25.11-scylla/_sources/api/cassandra/graph.rst.txt @@ -0,0 +1,121 @@ +``cassandra.graph`` - Graph Statements, Options, and Row Factories +================================================================== + +.. note:: This module is only for backward compatibility for dse-driver users. Consider using :ref:`cassandra.datastax.graph `. + +.. module:: cassandra.graph + +.. autofunction:: single_object_row_factory + +.. autofunction:: graph_result_row_factory + +.. autofunction:: graph_object_row_factory + +.. autofunction:: graph_graphson2_row_factory + +.. autofunction:: graph_graphson3_row_factory + +.. function:: to_int(value) + + Wraps a value to be explicitly serialized as a graphson Int. + +.. function:: to_bigint(value) + + Wraps a value to be explicitly serialized as a graphson Bigint. + +.. function:: to_smallint(value) + + Wraps a value to be explicitly serialized as a graphson Smallint. + +.. function:: to_float(value) + + Wraps a value to be explicitly serialized as a graphson Float. + +.. function:: to_double(value) + + Wraps a value to be explicitly serialized as a graphson Double. + +.. autoclass:: GraphProtocol + :members: + +.. autoclass:: GraphOptions + + .. autoattribute:: graph_name + + .. autoattribute:: graph_source + + .. autoattribute:: graph_language + + .. autoattribute:: graph_read_consistency_level + + .. autoattribute:: graph_write_consistency_level + + .. autoattribute:: is_default_source + + .. autoattribute:: is_analytics_source + + .. autoattribute:: is_graph_source + + .. automethod:: set_source_default + + .. automethod:: set_source_analytics + + .. automethod:: set_source_graph + + +.. autoclass:: SimpleGraphStatement + :members: + +.. autoclass:: Result + :members: + +.. autoclass:: Vertex + :members: + +.. autoclass:: VertexProperty + :members: + +.. autoclass:: Edge + :members: + +.. autoclass:: Path + :members: + +.. autoclass:: GraphSON1Serializer + :members: + +.. autoclass:: GraphSON1Deserializer + + .. automethod:: deserialize_date + + .. automethod:: deserialize_timestamp + + .. automethod:: deserialize_time + + .. automethod:: deserialize_duration + + .. automethod:: deserialize_int + + .. automethod:: deserialize_bigint + + .. automethod:: deserialize_double + + .. automethod:: deserialize_float + + .. automethod:: deserialize_uuid + + .. automethod:: deserialize_blob + + .. automethod:: deserialize_decimal + + .. automethod:: deserialize_point + + .. automethod:: deserialize_linestring + + .. automethod:: deserialize_polygon + +.. autoclass:: GraphSON2Reader + :members: + +.. autoclass:: GraphSON3Reader + :members: diff --git a/3.25.11-scylla/_sources/api/cassandra/io/asyncioreactor.rst.txt b/3.25.11-scylla/_sources/api/cassandra/io/asyncioreactor.rst.txt new file mode 100644 index 0000000000..38ae63ca7f --- /dev/null +++ b/3.25.11-scylla/_sources/api/cassandra/io/asyncioreactor.rst.txt @@ -0,0 +1,7 @@ +``cassandra.io.asyncioreactor`` - ``asyncio`` Event Loop +===================================================================== + +.. module:: cassandra.io.asyncioreactor + +.. autoclass:: AsyncioConnection + :members: diff --git a/3.25.11-scylla/_sources/api/cassandra/io/asyncorereactor.rst.txt b/3.25.11-scylla/_sources/api/cassandra/io/asyncorereactor.rst.txt new file mode 100644 index 0000000000..ade7887e70 --- /dev/null +++ b/3.25.11-scylla/_sources/api/cassandra/io/asyncorereactor.rst.txt @@ -0,0 +1,7 @@ +``cassandra.io.asyncorereactor`` - ``asyncore`` Event Loop +========================================================== + +.. module:: cassandra.io.asyncorereactor + +.. autoclass:: AsyncoreConnection + :members: diff --git a/3.25.11-scylla/_sources/api/cassandra/io/eventletreactor.rst.txt b/3.25.11-scylla/_sources/api/cassandra/io/eventletreactor.rst.txt new file mode 100644 index 0000000000..1ba742c7e9 --- /dev/null +++ b/3.25.11-scylla/_sources/api/cassandra/io/eventletreactor.rst.txt @@ -0,0 +1,7 @@ +``cassandra.io.eventletreactor`` - ``eventlet``-compatible Connection +===================================================================== + +.. module:: cassandra.io.eventletreactor + +.. autoclass:: EventletConnection + :members: diff --git a/3.25.11-scylla/_sources/api/cassandra/io/geventreactor.rst.txt b/3.25.11-scylla/_sources/api/cassandra/io/geventreactor.rst.txt new file mode 100644 index 0000000000..603affe140 --- /dev/null +++ b/3.25.11-scylla/_sources/api/cassandra/io/geventreactor.rst.txt @@ -0,0 +1,7 @@ +``cassandra.io.geventreactor`` - ``gevent``-compatible Event Loop +================================================================= + +.. module:: cassandra.io.geventreactor + +.. autoclass:: GeventConnection + :members: diff --git a/3.25.11-scylla/_sources/api/cassandra/io/libevreactor.rst.txt b/3.25.11-scylla/_sources/api/cassandra/io/libevreactor.rst.txt new file mode 100644 index 0000000000..5b7288edf2 --- /dev/null +++ b/3.25.11-scylla/_sources/api/cassandra/io/libevreactor.rst.txt @@ -0,0 +1,6 @@ +``cassandra.io.libevreactor`` - ``libev`` Event Loop +==================================================== + +.. module:: cassandra.io.libevreactor + +.. autoclass:: LibevConnection diff --git a/3.25.11-scylla/_sources/api/cassandra/io/twistedreactor.rst.txt b/3.25.11-scylla/_sources/api/cassandra/io/twistedreactor.rst.txt new file mode 100644 index 0000000000..24e93bd432 --- /dev/null +++ b/3.25.11-scylla/_sources/api/cassandra/io/twistedreactor.rst.txt @@ -0,0 +1,9 @@ +``cassandra.io.twistedreactor`` - Twisted Event Loop +==================================================== + +.. module:: cassandra.io.twistedreactor + +.. class:: TwistedConnection + + An implementation of :class:`~cassandra.io.connection.Connection` that uses + Twisted's reactor as its event loop. diff --git a/3.25.11-scylla/_sources/api/cassandra/metadata.rst.txt b/3.25.11-scylla/_sources/api/cassandra/metadata.rst.txt new file mode 100644 index 0000000000..7c1280bcf7 --- /dev/null +++ b/3.25.11-scylla/_sources/api/cassandra/metadata.rst.txt @@ -0,0 +1,93 @@ +``cassandra.metadata`` - Schema and Ring Topology +================================================= + +.. module:: cassandra.metadata + +.. autodata:: cql_keywords + :annotation: + +.. autodata:: cql_keywords_unreserved + :annotation: + +.. autodata:: cql_keywords_reserved + :annotation: + +.. autoclass:: Metadata () + :members: + :exclude-members: rebuild_schema, rebuild_token_map, add_host, remove_host + +Schemas +------- + +.. autoclass:: KeyspaceMetadata () + :members: + +.. autoclass:: UserType () + :members: + +.. autoclass:: Function () + :members: + +.. autoclass:: Aggregate () + :members: + +.. autoclass:: TableMetadata () + :members: + +.. autoclass:: TableMetadataV3 () + :members: + +.. autoclass:: TableMetadataDSE68 () + :members: + +.. autoclass:: ColumnMetadata () + :members: + +.. autoclass:: IndexMetadata () + :members: + +.. autoclass:: MaterializedViewMetadata () + :members: + +.. autoclass:: VertexMetadata () + :members: + +.. autoclass:: EdgeMetadata () + :members: + +Tokens and Ring Topology +------------------------ + +.. autoclass:: TokenMap () + :members: + +.. autoclass:: Token () + :members: + +.. autoclass:: Murmur3Token + :members: + +.. autoclass:: MD5Token + :members: + +.. autoclass:: BytesToken + :members: + +.. autoclass:: ReplicationStrategy + :members: + +.. autoclass:: ReplicationFactor + :members: + :exclude-members: create + +.. autoclass:: SimpleStrategy + :members: + +.. autoclass:: NetworkTopologyStrategy + :members: + +.. autoclass:: LocalStrategy + :members: + +.. autofunction:: group_keys_by_replica + diff --git a/3.25.11-scylla/_sources/api/cassandra/metrics.rst.txt b/3.25.11-scylla/_sources/api/cassandra/metrics.rst.txt new file mode 100644 index 0000000000..0df7f8b5b9 --- /dev/null +++ b/3.25.11-scylla/_sources/api/cassandra/metrics.rst.txt @@ -0,0 +1,7 @@ +``cassandra.metrics`` - Performance Metrics +=========================================== + +.. module:: cassandra.metrics + +.. autoclass:: cassandra.metrics.Metrics () + :members: diff --git a/3.25.11-scylla/_sources/api/cassandra/policies.rst.txt b/3.25.11-scylla/_sources/api/cassandra/policies.rst.txt new file mode 100644 index 0000000000..387b19ed95 --- /dev/null +++ b/3.25.11-scylla/_sources/api/cassandra/policies.rst.txt @@ -0,0 +1,96 @@ +``cassandra.policies`` - Load balancing and Failure Handling Policies +===================================================================== + +.. module:: cassandra.policies + +Load Balancing +-------------- + +.. autoclass:: HostDistance + :members: + +.. autoclass:: LoadBalancingPolicy + :members: + +.. autoclass:: RoundRobinPolicy + :members: + +.. autoclass:: DCAwareRoundRobinPolicy + :members: + +.. autoclass:: WhiteListRoundRobinPolicy + :members: + +.. autoclass:: TokenAwarePolicy + :members: + +.. autoclass:: HostFilterPolicy + + .. we document these methods manually so we can specify a param to predicate + + .. automethod:: predicate(host) + .. automethod:: distance + .. automethod:: make_query_plan + +.. autoclass:: DefaultLoadBalancingPolicy + :members: + +.. autoclass:: DSELoadBalancingPolicy + :members: + +Translating Server Node Addresses +--------------------------------- + +.. autoclass:: AddressTranslator + :members: + +.. autoclass:: IdentityTranslator + :members: + +.. autoclass:: EC2MultiRegionTranslator + :members: + +Marking Hosts Up or Down +------------------------ + +.. autoclass:: ConvictionPolicy + :members: + +.. autoclass:: SimpleConvictionPolicy + :members: + +Reconnecting to Dead Hosts +-------------------------- + +.. autoclass:: ReconnectionPolicy + :members: + +.. autoclass:: ConstantReconnectionPolicy + :members: + +.. autoclass:: ExponentialReconnectionPolicy + :members: + +Retrying Failed Operations +-------------------------- + +.. autoclass:: WriteType + :members: + +.. autoclass:: RetryPolicy + :members: + +.. autoclass:: FallthroughRetryPolicy + :members: + +.. autoclass:: DowngradingConsistencyRetryPolicy + :members: + +Retrying Idempotent Operations +------------------------------ + +.. autoclass:: SpeculativeExecutionPolicy + :members: + +.. autoclass:: ConstantSpeculativeExecutionPolicy + :members: diff --git a/3.25.11-scylla/_sources/api/cassandra/pool.rst.txt b/3.25.11-scylla/_sources/api/cassandra/pool.rst.txt new file mode 100644 index 0000000000..b14d30e19c --- /dev/null +++ b/3.25.11-scylla/_sources/api/cassandra/pool.rst.txt @@ -0,0 +1,11 @@ +``cassandra.pool`` - Hosts and Connection Pools +=============================================== + +.. automodule:: cassandra.pool + +.. autoclass:: Host () + :members: + :exclude-members: set_location_info, get_and_set_reconnection_handler + +.. autoexception:: NoConnectionsAvailable + :members: diff --git a/3.25.11-scylla/_sources/api/cassandra/protocol.rst.txt b/3.25.11-scylla/_sources/api/cassandra/protocol.rst.txt new file mode 100644 index 0000000000..f615ab1a70 --- /dev/null +++ b/3.25.11-scylla/_sources/api/cassandra/protocol.rst.txt @@ -0,0 +1,55 @@ +``cassandra.protocol`` - Protocol Features +===================================================================== + +.. module:: cassandra.protocol + +.. _custom_payload: + +Custom Payloads +--------------- +Native protocol version 4+ allows for a custom payload to be sent between clients +and custom query handlers. The payload is specified as a string:binary_type dict +holding custom key/value pairs. + +By default these are ignored by the server. They can be useful for servers implementing +a custom QueryHandler. + +See :meth:`.Session.execute`, ::meth:`.Session.execute_async`, :attr:`.ResponseFuture.custom_payload`. + +.. autoclass:: _ProtocolHandler + + .. autoattribute:: message_types_by_opcode + :annotation: = {default mapping} + + .. automethod:: encode_message + + .. automethod:: decode_message + +.. _faster_deser: + +Faster Deserialization +---------------------- +When python-driver is compiled with Cython, it uses a Cython-based deserialization path +to deserialize messages. By default, the driver will use a Cython-based parser that returns +lists of rows similar to the pure-Python version. In addition, there are two additional +ProtocolHandler classes that can be used to deserialize response messages: ``LazyProtocolHandler`` +and ``NumpyProtocolHandler``. They can be used as follows: + +.. code:: python + + from cassandra.protocol import NumpyProtocolHandler, LazyProtocolHandler + from cassandra.query import tuple_factory + s.client_protocol_handler = LazyProtocolHandler # for a result iterator + s.row_factory = tuple_factory #required for Numpy results + s.client_protocol_handler = NumpyProtocolHandler # for a dict of NumPy arrays as result + +These protocol handlers comprise different parsers, and return results as described below: + +- ProtocolHandler: this default implementation is a drop-in replacement for the pure-Python version. + The rows are all parsed upfront, before results are returned. + +- LazyProtocolHandler: near drop-in replacement for the above, except that it returns an iterator over rows, + lazily decoded into the default row format (this is more efficient since all decoded results are not materialized at once) + +- NumpyProtocolHander: deserializes results directly into NumPy arrays. This facilitates efficient integration with + analysis toolkits such as Pandas. diff --git a/3.25.11-scylla/_sources/api/cassandra/query.rst.txt b/3.25.11-scylla/_sources/api/cassandra/query.rst.txt new file mode 100644 index 0000000000..fcd79739b9 --- /dev/null +++ b/3.25.11-scylla/_sources/api/cassandra/query.rst.txt @@ -0,0 +1,59 @@ +``cassandra.query`` - Prepared Statements, Batch Statements, Tracing, and Row Factories +======================================================================================= + +.. module:: cassandra.query + +.. autofunction:: tuple_factory + +.. autofunction:: named_tuple_factory + +.. autofunction:: dict_factory + +.. autofunction:: ordered_dict_factory + +.. autoclass:: SimpleStatement + :members: + +.. autoclass:: PreparedStatement () + :members: + +.. autoclass:: BoundStatement + :members: + +.. autoclass:: Statement () + :members: + +.. autodata:: UNSET_VALUE + :annotation: + +.. autoclass:: BatchStatement (batch_type=BatchType.LOGGED, retry_policy=None, consistency_level=None) + :members: + +.. autoclass:: BatchType () + + .. autoattribute:: LOGGED + + .. autoattribute:: UNLOGGED + + .. autoattribute:: COUNTER + +.. autoclass:: cassandra.query.ValueSequence + + A wrapper class that is used to specify that a sequence of values should + be treated as a CQL list of values instead of a single column collection when used + as part of the `parameters` argument for :meth:`.Session.execute()`. + + This is typically needed when supplying a list of keys to select. + For example:: + + >>> my_user_ids = ('alice', 'bob', 'charles') + >>> query = "SELECT * FROM users WHERE user_id IN %s" + >>> session.execute(query, parameters=[ValueSequence(my_user_ids)]) + +.. autoclass:: QueryTrace () + :members: + +.. autoclass:: TraceEvent () + :members: + +.. autoexception:: TraceUnavailable diff --git a/3.25.11-scylla/_sources/api/cassandra/timestamps.rst.txt b/3.25.11-scylla/_sources/api/cassandra/timestamps.rst.txt new file mode 100644 index 0000000000..00d25b06d9 --- /dev/null +++ b/3.25.11-scylla/_sources/api/cassandra/timestamps.rst.txt @@ -0,0 +1,14 @@ +``cassandra.timestamps`` - Timestamp Generation +=============================================== + +.. module:: cassandra.timestamps + +.. autoclass:: MonotonicTimestampGenerator (warn_on_drift=True, warning_threshold=0, warning_interval=0) + + .. autoattribute:: warn_on_drift + + .. autoattribute:: warning_threshold + + .. autoattribute:: warning_interval + + .. automethod:: _next_timestamp diff --git a/3.25.11-scylla/_sources/api/cassandra/util.rst.txt b/3.25.11-scylla/_sources/api/cassandra/util.rst.txt new file mode 100644 index 0000000000..848d4d5fc2 --- /dev/null +++ b/3.25.11-scylla/_sources/api/cassandra/util.rst.txt @@ -0,0 +1,5 @@ +``cassandra.util`` - Utilities +=================================== + +.. automodule:: cassandra.util + :members: diff --git a/3.25.11-scylla/_sources/api/index.rst.txt b/3.25.11-scylla/_sources/api/index.rst.txt new file mode 100644 index 0000000000..9e778d508c --- /dev/null +++ b/3.25.11-scylla/_sources/api/index.rst.txt @@ -0,0 +1,54 @@ +API Documentation +================= + +Core Driver +----------- +.. toctree:: + :maxdepth: 2 + + cassandra + cassandra/cluster + cassandra/policies + cassandra/auth + cassandra/graph + cassandra/metadata + cassandra/metrics + cassandra/query + cassandra/pool + cassandra/protocol + cassandra/encoder + cassandra/decoder + cassandra/concurrent + cassandra/connection + cassandra/util + cassandra/timestamps + cassandra/io/asyncioreactor + cassandra/io/asyncorereactor + cassandra/io/eventletreactor + cassandra/io/libevreactor + cassandra/io/geventreactor + cassandra/io/twistedreactor + +.. _om_api: + +Object Mapper +------------- +.. toctree:: + :maxdepth: 1 + + cassandra/cqlengine/models + cassandra/cqlengine/columns + cassandra/cqlengine/query + cassandra/cqlengine/connection + cassandra/cqlengine/management + cassandra/cqlengine/usertype + +DataStax Graph +-------------- +.. toctree:: + :maxdepth: 1 + + cassandra/datastax/graph/index + cassandra/datastax/graph/fluent/index + cassandra/datastax/graph/fluent/query + cassandra/datastax/graph/fluent/predicates diff --git a/3.25.11-scylla/_sources/cqlengine/batches.rst.txt b/3.25.11-scylla/_sources/cqlengine/batches.rst.txt new file mode 100644 index 0000000000..306e7d01a6 --- /dev/null +++ b/3.25.11-scylla/_sources/cqlengine/batches.rst.txt @@ -0,0 +1,108 @@ +============= +Batch Queries +============= + +cqlengine supports batch queries using the BatchQuery class. Batch queries can be started and stopped manually, or within a context manager. To add queries to the batch object, you just need to precede the create/save/delete call with a call to batch, and pass in the batch object. + + +Batch Query General Use Pattern +=============================== + +You can only create, update, and delete rows with a batch query, attempting to read rows out of the database with a batch query will fail. + +.. code-block:: python + + from cassandra.cqlengine.query import BatchQuery + + #using a context manager + with BatchQuery() as b: + now = datetime.now() + em1 = ExampleModel.batch(b).create(example_type=0, description="1", created_at=now) + em2 = ExampleModel.batch(b).create(example_type=0, description="2", created_at=now) + em3 = ExampleModel.batch(b).create(example_type=0, description="3", created_at=now) + + # -- or -- + + #manually + b = BatchQuery() + now = datetime.now() + em1 = ExampleModel.batch(b).create(example_type=0, description="1", created_at=now) + em2 = ExampleModel.batch(b).create(example_type=0, description="2", created_at=now) + em3 = ExampleModel.batch(b).create(example_type=0, description="3", created_at=now) + b.execute() + + # updating in a batch + + b = BatchQuery() + em1.description = "new description" + em1.batch(b).save() + em2.description = "another new description" + em2.batch(b).save() + b.execute() + + # deleting in a batch + b = BatchQuery() + ExampleModel.objects(id=some_id).batch(b).delete() + ExampleModel.objects(id=some_id2).batch(b).delete() + b.execute() + + +Typically you will not want the block to execute if an exception occurs inside the `with` block. However, in the case that this is desirable, it's achievable by using the following syntax: + +.. code-block:: python + + with BatchQuery(execute_on_exception=True) as b: + LogEntry.batch(b).create(k=1, v=1) + mystery_function() # exception thrown in here + LogEntry.batch(b).create(k=1, v=2) # this code is never reached due to the exception, but anything leading up to here will execute in the batch. + +If an exception is thrown somewhere in the block, any statements that have been added to the batch will still be executed. This is useful for some logging situations. + +Batch Query Execution Callbacks +=============================== + +In order to allow secondary tasks to be chained to the end of batch, BatchQuery instances allow callbacks to be +registered with the batch, to be executed immediately after the batch executes. + +Multiple callbacks can be attached to same BatchQuery instance, they are executed in the same order that they +are added to the batch. + +The callbacks attached to a given batch instance are executed only if the batch executes. If the batch is used as a +context manager and an exception is raised, the queued up callbacks will not be run. + +.. code-block:: python + + def my_callback(*args, **kwargs): + pass + + batch = BatchQuery() + + batch.add_callback(my_callback) + batch.add_callback(my_callback, 'positional arg', named_arg='named arg value') + + # if you need reference to the batch within the callback, + # just trap it in the arguments to be passed to the callback: + batch.add_callback(my_callback, cqlengine_batch=batch) + + # once the batch executes... + batch.execute() + + # the effect of the above scheduled callbacks will be similar to + my_callback() + my_callback('positional arg', named_arg='named arg value') + my_callback(cqlengine_batch=batch) + +Failure in any of the callbacks does not affect the batch's execution, as the callbacks are started after the execution +of the batch is complete. + +Logged vs Unlogged Batches +--------------------------- +By default, queries in cqlengine are LOGGED, which carries additional overhead from UNLOGGED. To explicitly state which batch type to use, simply: + + +.. code-block:: python + + from cassandra.cqlengine.query import BatchType + with BatchQuery(batch_type=BatchType.Unlogged) as b: + LogEntry.batch(b).create(k=1, v=1) + LogEntry.batch(b).create(k=1, v=2) diff --git a/3.25.11-scylla/_sources/cqlengine/connections.rst.txt b/3.25.11-scylla/_sources/cqlengine/connections.rst.txt new file mode 100644 index 0000000000..03ade27521 --- /dev/null +++ b/3.25.11-scylla/_sources/cqlengine/connections.rst.txt @@ -0,0 +1,137 @@ +=========== +Connections +=========== + +Connections aim to ease the use of multiple sessions with cqlengine. Connections can be set on a model class, per query or using a context manager. + + +Register a new connection +========================= + +To use cqlengine, you need at least a default connection. If you initialize cqlengine's connections with with :func:`connection.setup <.connection.setup>`, a connection will be created automatically. If you want to use another cluster/session, you need to register a new cqlengine connection. You register a connection with :func:`~.connection.register_connection`: + +.. code-block:: python + + from cassandra.cqlengine import connection + + connection.setup(['127.0.0.1') + connection.register_connection('cluster2', ['127.0.0.2']) + +:func:`~.connection.register_connection` can take a list of hosts, as shown above, in which case it will create a connection with a new session. It can also take a `session` argument if you've already created a session: + +.. code-block:: python + + from cassandra.cqlengine import connection + from cassandra.cluster import Cluster + + session = Cluster(['127.0.0.1']).connect() + connection.register_connection('cluster3', session=session) + + +Change the default connection +============================= + +You can change the default cqlengine connection on registration: + +.. code-block:: python + + from cassandra.cqlengine import connection + + connection.register_connection('cluster2', ['127.0.0.2'] default=True) + +or on the fly using :func:`~.connection.set_default_connection` + +.. code-block:: python + + connection.set_default_connection('cluster2') + +Unregister a connection +======================= + +You can unregister a connection using :func:`~.connection.unregister_connection`: + +.. code-block:: python + + connection.unregister_connection('cluster2') + +Management +========== + +When using multiples connections, you also need to sync your models on all connections (and keyspaces) that you need operate on. Management commands have been improved to ease this part. Here is an example: + +.. code-block:: python + + from cassandra.cqlengine import management + + keyspaces = ['ks1', 'ks2'] + conns = ['cluster1', 'cluster2'] + + # registers your connections + # ... + + # create all keyspaces on all connections + for ks in keyspaces: + management.create_simple_keyspace(ks, connections=conns) + + # define your Automobile model + # ... + + # sync your models + management.sync_table(Automobile, keyspaces=keyspaces, connections=conns) + + +Connection Selection +==================== + +cqlengine will select the default connection, unless your specify a connection using one of the following methods. + +Default Model Connection +------------------------ + +You can specify a default connection per model: + +.. code-block:: python + + class Automobile(Model): + __keyspace__ = 'test' + __connection__ = 'cluster2' + manufacturer = columns.Text(primary_key=True) + year = columns.Integer(primary_key=True) + model = columns.Text(primary_key=True) + + print len(Automobile.objects.all()) # executed on the connection 'cluster2' + +QuerySet and model instance +--------------------------- + +You can use the :attr:`using() <.query.ModelQuerySet.using>` method to select a connection (or keyspace): + +.. code-block:: python + + Automobile.objects.using(connection='cluster1').create(manufacturer='honda', year=2010, model='civic') + q = Automobile.objects.filter(manufacturer='Tesla') + autos = q.using(keyspace='ks2', connection='cluster2').all() + + for auto in autos: + auto.using(connection='cluster1').save() + +Context Manager +--------------- + +You can use the ContextQuery as well to select a connection: + +.. code-block:: python + + with ContextQuery(Automobile, connection='cluster1') as A: + A.objects.filter(manufacturer='honda').all() # executed on 'cluster1' + + +BatchQuery +---------- + +With a BatchQuery, you can select the connection with the context manager. Note that all operations in the batch need to use the same connection. + +.. code-block:: python + + with BatchQuery(connection='cluster1') as b: + Automobile.objects.batch(b).create(manufacturer='honda', year=2010, model='civic') diff --git a/3.25.11-scylla/_sources/cqlengine/faq.rst.txt b/3.25.11-scylla/_sources/cqlengine/faq.rst.txt new file mode 100644 index 0000000000..6c056d02ea --- /dev/null +++ b/3.25.11-scylla/_sources/cqlengine/faq.rst.txt @@ -0,0 +1,67 @@ +========================== +Frequently Asked Questions +========================== + +Why don't updates work correctly on models instantiated as Model(field=value, field2=value2)? +------------------------------------------------------------------------------------------------ + +The recommended way to create new rows is with the models .create method. The values passed into a model's init method are interpreted by the model as the values as they were read from a row. This allows the model to "know" which rows have changed since the row was read out of cassandra, and create suitable update statements. + +How to preserve ordering in batch query? +------------------------------------------- + +Statement Ordering is not supported by CQL3 batches. Therefore, +once cassandra needs resolving conflict(Updating the same column in one batch), +The algorithm below would be used. + +* If timestamps are different, pick the column with the largest timestamp (the value being a regular column or a tombstone) +* If timestamps are the same, and one of the columns in a tombstone ('null') - pick the tombstone +* If timestamps are the same, and none of the columns are tombstones, pick the column with the largest value + +Below is an example to show this scenario. + +.. code-block:: python + + class MyMode(Model): + id = columns.Integer(primary_key=True) + count = columns.Integer() + text = columns.Text() + + with BatchQuery() as b: + MyModel.batch(b).create(id=1, count=2, text='123') + MyModel.batch(b).create(id=1, count=3, text='111') + + assert MyModel.objects(id=1).first().count == 3 + assert MyModel.objects(id=1).first().text == '123' + +The largest value of count is 3, and the largest value of text would be '123'. + +The workaround is applying timestamp to each statement, then Cassandra would +resolve to the statement with the lastest timestamp. + +.. code-block:: python + + with BatchQuery() as b: + MyModel.timestamp(datetime.now()).batch(b).create(id=1, count=2, text='123') + MyModel.timestamp(datetime.now()).batch(b).create(id=1, count=3, text='111') + + assert MyModel.objects(id=1).first().count == 3 + assert MyModel.objects(id=1).first().text == '111' + +How can I delete individual values from a row? +------------------------------------------------- + +When inserting with CQLEngine, ``None`` is equivalent to CQL ``NULL`` or to +issuing a ``DELETE`` on that column. For example: + +.. code-block:: python + + class MyModel(Model): + id = columns.Integer(primary_key=True) + text = columns.Text() + + m = MyModel.create(id=1, text='We can delete this with None') + assert MyModel.objects(id=1).first().text is not None + + m.update(text=None) + assert MyModel.objects(id=1).first().text is None diff --git a/3.25.11-scylla/_sources/cqlengine/models.rst.txt b/3.25.11-scylla/_sources/cqlengine/models.rst.txt new file mode 100644 index 0000000000..c0ba390119 --- /dev/null +++ b/3.25.11-scylla/_sources/cqlengine/models.rst.txt @@ -0,0 +1,218 @@ +====== +Models +====== + +.. module:: cqlengine.models + +A model is a python class representing a CQL table. Models derive from :class:`Model`, and +define basic table properties and columns for a table. + +Columns in your models map to columns in your CQL table. You define CQL columns by defining column attributes on your model classes. +For a model to be valid it needs at least one primary key column and one non-primary key column. Just as in CQL, the order you define +your columns in is important, and is the same order they are defined in on a model's corresponding table. + +Some basic examples defining models are shown below. Consult the :doc:`Model API docs ` and :doc:`Column API docs ` for complete details. + +Example Definitions +=================== + +This example defines a ``Person`` table, with the columns ``first_name`` and ``last_name`` + +.. code-block:: python + + from cassandra.cqlengine import columns + from cassandra.cqlengine.models import Model + + class Person(Model): + id = columns.UUID(primary_key=True) + first_name = columns.Text() + last_name = columns.Text() + + +The Person model would create this CQL table: + +.. code-block:: sql + + CREATE TABLE cqlengine.person ( + id uuid, + first_name text, + last_name text, + PRIMARY KEY (id) + ); + +Here's an example of a comment table created with clustering keys, in descending order: + +.. code-block:: python + + from cassandra.cqlengine import columns + from cassandra.cqlengine.models import Model + + class Comment(Model): + photo_id = columns.UUID(primary_key=True) + comment_id = columns.TimeUUID(primary_key=True, clustering_order="DESC") + comment = columns.Text() + +The Comment model's ``create table`` would look like the following: + +.. code-block:: sql + + CREATE TABLE comment ( + photo_id uuid, + comment_id timeuuid, + comment text, + PRIMARY KEY (photo_id, comment_id) + ) WITH CLUSTERING ORDER BY (comment_id DESC); + +To sync the models to the database, you may do the following*: + +.. code-block:: python + + from cassandra.cqlengine.management import sync_table + sync_table(Person) + sync_table(Comment) + +\*Note: synchronizing models causes schema changes, and should be done with caution. +Please see the discussion in :doc:`/api/cassandra/cqlengine/management` for considerations. + +For examples on manipulating data and creating queries, see :doc:`queryset` + +Manipulating model instances as dictionaries +============================================ + +Model instances can be accessed like dictionaries. + +.. code-block:: python + + class Person(Model): + first_name = columns.Text() + last_name = columns.Text() + + kevin = Person.create(first_name="Kevin", last_name="Deldycke") + dict(kevin) # returns {'first_name': 'Kevin', 'last_name': 'Deldycke'} + kevin['first_name'] # returns 'Kevin' + kevin.keys() # returns ['first_name', 'last_name'] + kevin.values() # returns ['Kevin', 'Deldycke'] + kevin.items() # returns [('first_name', 'Kevin'), ('last_name', 'Deldycke')] + + kevin['first_name'] = 'KEVIN5000' # changes the models first name + +Extending Model Validation +========================== + +Each time you save a model instance in cqlengine, the data in the model is validated against the schema you've defined +for your model. Most of the validation is fairly straightforward, it basically checks that you're not trying to do +something like save text into an integer column, and it enforces the ``required`` flag set on column definitions. +It also performs any transformations needed to save the data properly. + +However, there are often additional constraints or transformations you want to impose on your data, beyond simply +making sure that Cassandra won't complain when you try to insert it. To define additional validation on a model, +extend the model's validation method: + +.. code-block:: python + + class Member(Model): + person_id = UUID(primary_key=True) + name = Text(required=True) + + def validate(self): + super(Member, self).validate() + if self.name == 'jon': + raise ValidationError('no jon\'s allowed') + +*Note*: while not required, the convention is to raise a ``ValidationError`` (``from cassandra.cqlengine import ValidationError``) +if validation fails. + +.. _model_inheritance: + +Model Inheritance +================= +It is possible to save and load different model classes using a single CQL table. +This is useful in situations where you have different object types that you want to store in a single cassandra row. + +For instance, suppose you want a table that stores rows of pets owned by an owner: + +.. code-block:: python + + class Pet(Model): + __table_name__ = 'pet' + owner_id = UUID(primary_key=True) + pet_id = UUID(primary_key=True) + pet_type = Text(discriminator_column=True) + name = Text() + + def eat(self, food): + pass + + def sleep(self, time): + pass + + class Cat(Pet): + __discriminator_value__ = 'cat' + cuteness = Float() + + def tear_up_couch(self): + pass + + class Dog(Pet): + __discriminator_value__ = 'dog' + fierceness = Float() + + def bark_all_night(self): + pass + +After calling ``sync_table`` on each of these tables, the columns defined in each model will be added to the +``pet`` table. Additionally, saving ``Cat`` and ``Dog`` models will save the meta data needed to identify each row +as either a cat or dog. + +To setup a model structure with inheritance, follow these steps + +1. Create a base model with a column set as the distriminator (``distriminator_column=True`` in the column definition) +2. Create subclass models, and define a unique ``__discriminator_value__`` value on each +3. Run ``sync_table`` on each of the sub tables + +**About the discriminator value** + +The discriminator value is what cqlengine uses under the covers to map logical cql rows to the appropriate model type. The +base model maintains a map of discriminator values to subclasses. When a specialized model is saved, its discriminator value is +automatically saved into the discriminator column. The discriminator column may be any column type except counter and container types. +Additionally, if you set ``index=True`` on your discriminator column, you can execute queries against specialized subclasses, and a +``WHERE`` clause will be automatically added to your query, returning only rows of that type. Note that you must +define a unique ``__discriminator_value__`` to each subclass, and that you can only assign a single discriminator column per model. + +.. _user_types: + +User Defined Types +================== +cqlengine models User Defined Types (UDTs) much like tables, with fields defined by column type attributes. However, UDT instances +are only created, presisted, and queried via table Models. A short example to introduce the pattern:: + + from cassandra.cqlengine.columns import * + from cassandra.cqlengine.models import Model + from cassandra.cqlengine.usertype import UserType + + class address(UserType): + street = Text() + zipcode = Integer() + + class users(Model): + __keyspace__ = 'account' + name = Text(primary_key=True) + addr = UserDefinedType(address) + + users.create(name="Joe", addr=address(street="Easy St.", zipcode=99999)) + user = users.objects(name="Joe")[0] + print user.name, user.addr + # Joe address(street=u'Easy St.', zipcode=99999) + +UDTs are modeled by inheriting :class:`~.usertype.UserType`, and setting column type attributes. Types are then used in defining +models by declaring a column of type :class:`~.columns.UserDefinedType`, with the ``UserType`` class as a parameter. + +``sync_table`` will implicitly +synchronize any types contained in the table. Alternatively :func:`~.management.sync_type` can be used to create/alter types +explicitly. + +Upon declaration, types are automatically registered with the driver, so query results return instances of your ``UserType`` +class*. + +***Note**: UDTs were not added to the native protocol until v3. When setting up the cqlengine connection, be sure to specify +``protocol_version=3``. If using an earlier version, UDT queries will still work, but the returned type will be a namedtuple. diff --git a/3.25.11-scylla/_sources/cqlengine/queryset.rst.txt b/3.25.11-scylla/_sources/cqlengine/queryset.rst.txt new file mode 100644 index 0000000000..375ea22316 --- /dev/null +++ b/3.25.11-scylla/_sources/cqlengine/queryset.rst.txt @@ -0,0 +1,419 @@ +============== +Making Queries +============== + +.. module:: cqlengine.queryset + +Retrieving objects +================== +Once you've populated Cassandra with data, you'll probably want to retrieve some of it. This is accomplished with QuerySet objects. This section will describe how to use QuerySet objects to retrieve the data you're looking for. + +Retrieving all objects +---------------------- +The simplest query you can make is to return all objects from a table. + +This is accomplished with the ``.all()`` method, which returns a QuerySet of all objects in a table + +Using the Person example model, we would get all Person objects like this: + +.. code-block:: python + + all_objects = Person.objects.all() + +.. _retrieving-objects-with-filters: + +Retrieving objects with filters +------------------------------- +Typically, you'll want to query only a subset of the records in your database. + +That can be accomplished with the QuerySet's ``.filter(\*\*)`` method. + +For example, given the model definition: + +.. code-block:: python + + class Automobile(Model): + manufacturer = columns.Text(primary_key=True) + year = columns.Integer(primary_key=True) + model = columns.Text() + price = columns.Decimal() + options = columns.Set(columns.Text) + +...and assuming the Automobile table contains a record of every car model manufactured in the last 20 years or so, we can retrieve only the cars made by a single manufacturer like this: + + +.. code-block:: python + + q = Automobile.objects.filter(manufacturer='Tesla') + +You can also use the more convenient syntax: + +.. code-block:: python + + q = Automobile.objects(Automobile.manufacturer == 'Tesla') + +We can then further filter our query with another call to **.filter** + +.. code-block:: python + + q = q.filter(year=2012) + +*Note: all queries involving any filtering MUST define either an '=' or an 'in' relation to either a primary key column, or an indexed column.* + +Accessing objects in a QuerySet +=============================== + +There are several methods for getting objects out of a queryset + +* iterating over the queryset + .. code-block:: python + + for car in Automobile.objects.all(): + #...do something to the car instance + pass + +* list index + .. code-block:: python + + q = Automobile.objects.all() + q[0] #returns the first result + q[1] #returns the second result + + .. note:: + + * CQL does not support specifying a start position in it's queries. Therefore, accessing elements using array indexing will load every result up to the index value requested + * Using negative indices requires a "SELECT COUNT()" to be executed. This has a performance cost on large datasets. + +* list slicing + .. code-block:: python + + q = Automobile.objects.all() + q[1:] #returns all results except the first + q[1:9] #returns a slice of the results + + .. note:: + + * CQL does not support specifying a start position in it's queries. Therefore, accessing elements using array slicing will load every result up to the index value requested + * Using negative indices requires a "SELECT COUNT()" to be executed. This has a performance cost on large datasets. + +* calling :attr:`get() ` on the queryset + .. code-block:: python + + q = Automobile.objects.filter(manufacturer='Tesla') + q = q.filter(year=2012) + car = q.get() + + this returns the object matching the queryset + +* calling :attr:`first() ` on the queryset + .. code-block:: python + + q = Automobile.objects.filter(manufacturer='Tesla') + q = q.filter(year=2012) + car = q.first() + + this returns the first value in the queryset + +.. _query-filtering-operators: + +Filtering Operators +=================== + +:attr:`Equal To ` + +The default filtering operator. + +.. code-block:: python + + q = Automobile.objects.filter(manufacturer='Tesla') + q = q.filter(year=2012) #year == 2012 + +In addition to simple equal to queries, cqlengine also supports querying with other operators by appending a ``__`` to the field name on the filtering call + +:attr:`in (__in) ` + +.. code-block:: python + + q = Automobile.objects.filter(manufacturer='Tesla') + q = q.filter(year__in=[2011, 2012]) + + +:attr:`> (__gt) ` + +.. code-block:: python + + q = Automobile.objects.filter(manufacturer='Tesla') + q = q.filter(year__gt=2010) # year > 2010 + + # or the nicer syntax + + q.filter(Automobile.year > 2010) + +:attr:`>= (__gte) ` + +.. code-block:: python + + q = Automobile.objects.filter(manufacturer='Tesla') + q = q.filter(year__gte=2010) # year >= 2010 + + # or the nicer syntax + + q.filter(Automobile.year >= 2010) + +:attr:`< (__lt) ` + +.. code-block:: python + + q = Automobile.objects.filter(manufacturer='Tesla') + q = q.filter(year__lt=2012) # year < 2012 + + # or... + + q.filter(Automobile.year < 2012) + +:attr:`<= (__lte) ` + +.. code-block:: python + + q = Automobile.objects.filter(manufacturer='Tesla') + q = q.filter(year__lte=2012) # year <= 2012 + + q.filter(Automobile.year <= 2012) + +:attr:`CONTAINS (__contains) ` + +The CONTAINS operator is available for all collection types (List, Set, Map). + +.. code-block:: python + + q = Automobile.objects.filter(manufacturer='Tesla') + q.filter(options__contains='backup camera').allow_filtering() + +Note that we need to use allow_filtering() since the *options* column has no secondary index. + +:attr:`LIKE (__like) ` + +The LIKE operator is available for text columns that have a SASI secondary index. + +.. code-block:: python + + q = Automobile.objects.filter(model__like='%Civic%').allow_filtering() + +:attr:`IS NOT NULL (IsNotNull(column_name)) ` + +The IS NOT NULL operator is not yet supported for C*. + +.. code-block:: python + + q = Automobile.objects.filter(IsNotNull('model')) + +Limitations: + +- Currently, cqlengine does not support SASI index creation. To use this feature, you need to create the SASI index using the core driver. +- Queries using LIKE must use allow_filtering() since the *model* column has no standard secondary index. Note that the server will use the SASI index properly when executing the query. + +TimeUUID Functions +================== + +In addition to querying using regular values, there are two functions you can pass in when querying TimeUUID columns to help make filtering by them easier. Note that these functions don't actually return a value, but instruct the cql interpreter to use the functions in it's query. + +.. class:: MinTimeUUID(datetime) + + returns the minimum time uuid value possible for the given datetime + +.. class:: MaxTimeUUID(datetime) + + returns the maximum time uuid value possible for the given datetime + +*Example* + +.. code-block:: python + + class DataStream(Model): + id = columns.UUID(partition_key=True) + time = columns.TimeUUID(primary_key=True) + data = columns.Bytes() + + min_time = datetime(1982, 1, 1) + max_time = datetime(1982, 3, 9) + + DataStream.filter(time__gt=functions.MinTimeUUID(min_time), time__lt=functions.MaxTimeUUID(max_time)) + +Token Function +============== + +Token functon may be used only on special, virtual column pk__token, representing token of partition key (it also works for composite partition keys). +Cassandra orders returned items by value of partition key token, so using cqlengine.Token we can easy paginate through all table rows. + +See http://cassandra.apache.org/doc/cql3/CQL-3.0.html#tokenFun + +*Example* + +.. code-block:: python + + class Items(Model): + id = columns.Text(primary_key=True) + data = columns.Bytes() + + query = Items.objects.all().limit(10) + + first_page = list(query); + last = first_page[-1] + next_page = list(query.filter(pk__token__gt=cqlengine.Token(last.pk))) + +QuerySets are immutable +======================= + +When calling any method that changes a queryset, the method does not actually change the queryset object it's called on, but returns a new queryset object with the attributes of the original queryset, plus the attributes added in the method call. + +*Example* + +.. code-block:: python + + #this produces 3 different querysets + #q does not change after it's initial definition + q = Automobiles.objects.filter(year=2012) + tesla2012 = q.filter(manufacturer='Tesla') + honda2012 = q.filter(manufacturer='Honda') + +Ordering QuerySets +================== + +Since Cassandra is essentially a distributed hash table on steroids, the order you get records back in will not be particularly predictable. + +However, you can set a column to order on with the ``.order_by(column_name)`` method. + +*Example* + +.. code-block:: python + + #sort ascending + q = Automobiles.objects.all().order_by('year') + #sort descending + q = Automobiles.objects.all().order_by('-year') + +*Note: Cassandra only supports ordering on a clustering key. In other words, to support ordering results, your model must have more than one primary key, and you must order on a primary key, excluding the first one.* + +*For instance, given our Automobile model, year is the only column we can order on.* + +Values Lists +============ + +There is a special QuerySet's method ``.values_list()`` - when called, QuerySet returns lists of values instead of model instances. It may significantly speedup things with lower memory footprint for large responses. +Each tuple contains the value from the respective field passed into the ``values_list()`` call — so the first item is the first field, etc. For example: + +.. code-block:: python + + items = list(range(20)) + random.shuffle(items) + for i in items: + TestModel.create(id=1, clustering_key=i) + + values = list(TestModel.objects.values_list('clustering_key', flat=True)) + # [19L, 18L, 17L, 16L, 15L, 14L, 13L, 12L, 11L, 10L, 9L, 8L, 7L, 6L, 5L, 4L, 3L, 2L, 1L, 0L] + +Per Query Timeouts +=================== + +By default all queries are executed with the timeout defined in `~cqlengine.connection.setup()` +The examples below show how to specify a per-query timeout. +A timeout is specified in seconds and can be an int, float or None. +None means no timeout. + + +.. code-block:: python + + class Row(Model): + id = columns.Integer(primary_key=True) + name = columns.Text() + + +Fetch all objects with a timeout of 5 seconds + +.. code-block:: python + + Row.objects().timeout(5).all() + +Create a single row with a 50ms timeout + +.. code-block:: python + + Row(id=1, name='Jon').timeout(0.05).create() + +Delete a single row with no timeout + +.. code-block:: python + + Row(id=1).timeout(None).delete() + +Update a single row with no timeout + +.. code-block:: python + + Row(id=1).timeout(None).update(name='Blake') + +Batch query timeouts + +.. code-block:: python + + with BatchQuery(timeout=10) as b: + Row(id=1, name='Jon').create() + + +NOTE: You cannot set both timeout and batch at the same time, batch will use the timeout defined in it's constructor. +Setting the timeout on the model is meaningless and will raise an AssertionError. + + +.. _ttl-change: + +Default TTL and Per Query TTL +============================= + +Model default TTL now relies on the *default_time_to_live* feature, introduced in Cassandra 2.0. It is not handled anymore in the CQLEngine Model (scylla-driver >=3.6). You can set the default TTL of a table like this: + +Example: + +.. code-block:: python + + class User(Model): + __options__ = {'default_time_to_live': 20} + + user_id = columns.UUID(primary_key=True) + ... + +You can set TTL per-query if needed. Here are a some examples: + +Example: + +.. code-block:: python + + class User(Model): + __options__ = {'default_time_to_live': 20} + + user_id = columns.UUID(primary_key=True) + ... + + user = User.objects.create(user_id=1) # Default TTL 20 will be set automatically on the server + + user.ttl(30).update(age=21) # Update the TTL to 30 + User.objects.ttl(10).create(user_id=1) # TTL 10 + User(user_id=1, age=21).ttl(10).save() # TTL 10 + + +Named Tables +=================== + +Named tables are a way of querying a table without creating an class. They're useful for querying system tables or exploring an unfamiliar database. + + +.. code-block:: python + + from cassandra.cqlengine.connection import setup + setup("127.0.0.1", "cqlengine_test") + + from cassandra.cqlengine.named import NamedTable + user = NamedTable("cqlengine_test", "user") + user.objects() + user.objects()[0] + + # {u'pk': 1, u't': datetime.datetime(2014, 6, 26, 17, 10, 31, 774000)} diff --git a/3.25.11-scylla/_sources/cqlengine/third_party.rst.txt b/3.25.11-scylla/_sources/cqlengine/third_party.rst.txt new file mode 100644 index 0000000000..20c26df304 --- /dev/null +++ b/3.25.11-scylla/_sources/cqlengine/third_party.rst.txt @@ -0,0 +1,64 @@ +======================== +Third party integrations +======================== + + +Celery +------ + +Here's how, in substance, CQLengine can be plugged to `Celery +`_: + +.. code-block:: python + + from celery import Celery + from celery.signals import worker_process_init, beat_init + from cassandra.cqlengine import connection + from cassandra.cqlengine.connection import ( + cluster as cql_cluster, session as cql_session) + + def cassandra_init(**kwargs): + """ Initialize a clean Cassandra connection. """ + if cql_cluster is not None: + cql_cluster.shutdown() + if cql_session is not None: + cql_session.shutdown() + connection.setup() + + # Initialize worker context for both standard and periodic tasks. + worker_process_init.connect(cassandra_init) + beat_init.connect(cassandra_init) + + app = Celery() + + +uWSGI +----- + +This is the code required for proper connection handling of CQLengine for a +`uWSGI `_-run application: + +.. code-block:: python + + from cassandra.cqlengine import connection + from cassandra.cqlengine.connection import ( + cluster as cql_cluster, session as cql_session) + + try: + from uwsgidecorators import postfork + except ImportError: + # We're not in a uWSGI context, no need to hook Cassandra session + # initialization to the postfork event. + pass + else: + @postfork + def cassandra_init(**kwargs): + """ Initialize a new Cassandra session in the context. + + Ensures that a new session is returned for every new request. + """ + if cql_cluster is not None: + cql_cluster.shutdown() + if cql_session is not None: + cql_session.shutdown() + connection.setup() diff --git a/3.25.11-scylla/_sources/cqlengine/upgrade_guide.rst.txt b/3.25.11-scylla/_sources/cqlengine/upgrade_guide.rst.txt new file mode 100644 index 0000000000..5a10ebb757 --- /dev/null +++ b/3.25.11-scylla/_sources/cqlengine/upgrade_guide.rst.txt @@ -0,0 +1,155 @@ +======================== +Upgrade Guide +======================== + +This is an overview of things that changed as the cqlengine project was merged into +scylla-driver. While efforts were taken to preserve the API and most functionality exactly, +conversion to this package will still require certain minimal updates (namely, imports). + +**THERE IS ONE FUNCTIONAL CHANGE**, described in the first section below. + +Functional Changes +================== +List Prepend Reversing +---------------------- +Legacy cqlengine included a workaround for a Cassandra bug in which prepended list segments were +reversed (`CASSANDRA-8733 `_). As of +this integration, this workaround is removed. The first released integrated version emits +a warning when prepend is used. Subsequent versions will have this warning removed. + +Date Column Type +---------------- +The Date column type in legacy cqlengine used a ``timestamp`` CQL type and truncated the time. +Going forward, the :class:`~.columns.Date` type represents a ``date`` for Cassandra 2.2+ +(`PYTHON-245 `_). +Users of the legacy functionality should convert models to use :class:`~.columns.DateTime` (which +uses ``timestamp`` internally), and use the build-in ``datetime.date`` for input values. + +Remove cqlengine +================ +To avoid confusion or mistakes using the legacy package in your application, it +is prudent to remove the cqlengine package when upgrading to the integrated version. + +The driver setup script will warn if the legacy package is detected during install, +but it will not prevent side-by-side installation. + +Organization +============ +Imports +------- +cqlengine is now integrated as a sub-package of the driver base package 'cassandra'. +Upgrading will require adjusting imports to cqlengine. For example:: + + from cassandra.cqlengine import columns + +is now:: + + from cassandra.cqlengine import columns + +Package-Level Aliases +--------------------- +Legacy cqlengine defined a number of aliases at the package level, which became redundant +when the package was integrated for a driver. These have been removed in favor of absolute +imports, and referring to cannonical definitions. For example, ``cqlengine.ONE`` was an alias +of ``cassandra.ConsistencyLevel.ONE``. In the integrated package, only the +:class:`cassandra.ConsistencyLevel` remains. + +Additionally, submodule aliases are removed from cqlengine in favor of absolute imports. + +These aliases are removed, and not deprecated because they should be straightforward to iron out +at module load time. + +Exceptions +---------- +The legacy cqlengine.exceptions module had a number of Exception classes that were variously +common to the package, or only used in specific modules. Common exceptions were relocated to +cqlengine, and specialized exceptions were placed in the module that raises them. Below is a +listing of updated locations: + +============================ ========== +Exception class New module +============================ ========== +CQLEngineException cassandra.cqlengine +ModelException cassandra.cqlengine.models +ValidationError cassandra.cqlengine +UndefinedKeyspaceException cassandra.cqlengine.connection +LWTException cassandra.cqlengine.query +IfNotExistsWithCounterColumn cassandra.cqlengine.query +============================ ========== + +UnicodeMixin Consolidation +-------------------------- +``class UnicodeMixin`` was defined in several cqlengine modules. This has been consolidated +to a single definition in the cqlengine package init file. This is not technically part of +the API, but noted here for completeness. + +API Deprecations +================ +This upgrade served as a good juncture to deprecate certain API features and invite users to upgrade +to new ones. The first released version does not change functionality -- only introduces deprecation +warnings. Future releases will remove these features in favor of the alternatives. + +Float/Double Overload +--------------------- +Previously there was no ``Double`` column type. Doubles were modeled by specifying ``Float(double_precision=True)``. +This inititializer parameter is now deprecated. Applications should use :class:`~.columns.Double` for CQL ``double``, and :class:`~.columns.Float` +for CQL ``float``. + +Schema Management +----------------- +``cassandra.cqlengine.management.create_keyspace`` is deprecated. Instead, use the new replication-strategy-specific +functions that accept explicit options for known strategies: + +- :func:`~.create_keyspace_simple` +- :func:`~.create_keyspace_network_topology` + +``cassandra.cqlengine.management.delete_keyspace`` is deprecated in favor of a new function, :func:`~.drop_keyspace`. The +intent is simply to make the function match the CQL verb it invokes. + +Model Inheritance +----------------- +The names for class attributes controlling model inheritance are changing. Changes are as follows: + +- Replace 'polymorphic_key' in the base class Column definition with :attr:`~.discriminator_column` +- Replace the '__polymorphic_key__' class attribute the derived classes with :attr:`~.__discriminator_value__` + +The functionality is unchanged -- the intent here is to make the names and language around these attributes more precise. +For now, the old names are just deprecated, and the mapper will emit warnings if they are used. The old names +will be removed in a future version. + +The example below shows a simple translation: + +Before:: + + class Pet(Model): + __table_name__ = 'pet' + owner_id = UUID(primary_key=True) + pet_id = UUID(primary_key=True) + pet_type = Text(polymorphic_key=True) + name = Text() + + class Cat(Pet): + __polymorphic_key__ = 'cat' + + class Dog(Pet): + __polymorphic_key__ = 'dog' + +After:: + + class Pet(models.Model): + __table_name__ = 'pet' + owner_id = UUID(primary_key=True) + pet_id = UUID(primary_key=True) + pet_type = Text(discriminator_column=True) + name = Text() + + class Cat(Pet): + __discriminator_value__ = 'cat' + + class Dog(Pet): + __discriminator_value__ = 'dog' + + +TimeUUID.from_datetime +---------------------- +This function is deprecated in favor of the core utility function :func:`~.uuid_from_time`. diff --git a/3.25.11-scylla/_sources/dates_and_times.rst.txt b/3.25.11-scylla/_sources/dates_and_times.rst.txt new file mode 100644 index 0000000000..7a89f77437 --- /dev/null +++ b/3.25.11-scylla/_sources/dates_and_times.rst.txt @@ -0,0 +1,87 @@ +Working with Dates and Times +============================ + +This document is meant to provide on overview of the assumptions and limitations of the driver time handling, the +reasoning behind it, and describe approaches to working with these types. + +timestamps (Cassandra DateType) +------------------------------- + +Timestamps in Cassandra are timezone-naive timestamps encoded as millseconds since UNIX epoch. Clients working with +timestamps in this database usually find it easiest to reason about them if they are always assumed to be UTC. To quote the +pytz documentation, "The preferred way of dealing with times is to always work in UTC, converting to localtime only when +generating output to be read by humans." The driver adheres to this tenant, and assumes UTC is always in the database. The +driver attempts to make this correct on the way in, and assumes no timezone on the way out. + +Write Path +~~~~~~~~~~ +When inserting timestamps, the driver handles serialization for the write path as follows: + +If the input is a ``datetime.datetime``, the serialization is normalized by starting with the ``utctimetuple()`` of the +value. + +- If the ``datetime`` object is timezone-aware, the timestamp is shifted, and represents the UTC timestamp equivalent. +- If the ``datetime`` object is timezone-naive, this results in no shift -- any ``datetime`` with no timezone information is assumed to be UTC + +Note the second point above applies even to "local" times created using ``now()``:: + + >>> d = datetime.now() + + >>> print(d.tzinfo) + None + + +These do not contain timezone information intrinsically, so they will be assumed to be UTC and not shifted. When generating +timestamps in the application, it is clearer to use ``datetime.utcnow()`` to be explicit about it. + +If the input for a timestamp is numeric, it is assumed to be a epoch-relative millisecond timestamp, as specified in the +CQL spec -- no scaling or conversion is done. + +Read Path +~~~~~~~~~ +The driver always assumes persisted timestamps are UTC and makes no attempt to localize them. Returned values are +timezone-naive ``datetime.datetime``. We follow this approach because the datetime API has deficiencies around daylight +saving time, and the defacto package for handling this is a third-party package (we try to minimize external dependencies +and not make decisions for the integrator). + +The decision for how to handle timezones is left to the application. For the most part it is straightforward to apply +localization to the ``datetime``\s returned by queries. One prevalent method is to use pytz for localization:: + + import pytz + user_tz = pytz.timezone('US/Central') + timestamp_naive = row.ts + timestamp_utc = pytz.utc.localize(timestamp_naive) + timestamp_presented = timestamp_utc.astimezone(user_tz) + +This is the most robust approach (likely refactored into a function). If it is deemed too cumbersome to apply for all call +sites in the application, it is possible to patch the driver with custom deserialization for this type. However, doing +this depends depends some on internal APIs and what extensions are present, so we will only mention the possibility, and +not spell it out here. + +date, time (Cassandra DateType) +------------------------------- +Date and time in Cassandra are idealized markers, much like ``datetime.date`` and ``datetime.time`` in the Python standard +library. Unlike these Python implementations, the Cassandra encoding supports much wider ranges. To accommodate these +ranges without overflow, this driver returns these data in custom types: :class:`.util.Date` and :class:`.util.Time`. + +Write Path +~~~~~~~~~~ +For simple (not prepared) statements, the input values for each of these can be either a string literal or an encoded +integer. See `Working with dates `_ +or `Working with time `_ for details +on the encoding or string formats. + +For prepared statements, the driver accepts anything that can be used to construct the :class:`.util.Date` or +:class:`.util.Time` classes. See the linked API docs for details. + +Read Path +~~~~~~~~~ +The driver always returns custom types for ``date`` and ``time``. + +The driver returns :class:`.util.Date` for ``date`` in order to accommodate the wider range of values without overflow. +For applications working within the supported range of [``datetime.MINYEAR``, ``datetime.MAXYEAR``], these are easily +converted to standard ``datetime.date`` insances using :meth:`.Date.date`. + +The driver returns :class:`.util.Time` for ``time`` in order to retain nanosecond precision stored in the database. +For applications not concerned with this level of precision, these are easily converted to standard ``datetime.time`` +insances using :meth:`.Time.time`. diff --git a/3.25.11-scylla/_sources/execution_profiles.rst.txt b/3.25.11-scylla/_sources/execution_profiles.rst.txt new file mode 100644 index 0000000000..7be1a85e3f --- /dev/null +++ b/3.25.11-scylla/_sources/execution_profiles.rst.txt @@ -0,0 +1,156 @@ +Execution Profiles +================== + +Execution profiles aim at making it easier to execute requests in different ways within +a single connected ``Session``. Execution profiles are being introduced to deal with the exploding number of +configuration options, especially as the database platform evolves more complex workloads. + +The legacy configuration remains intact, but legacy and Execution Profile APIs +cannot be used simultaneously on the same client ``Cluster``. Legacy configuration +will be removed in the next major release (4.0). + +An execution profile and its parameters should be unique across ``Cluster`` instances. +For example, an execution profile and its ``LoadBalancingPolicy`` should +not be applied to more than one ``Cluster`` instance. + +This document explains how Execution Profiles relate to existing settings, and shows how to use the new profiles for +request execution. + +Mapping Legacy Parameters to Profiles +------------------------------------- + +Execution profiles can inherit from :class:`.cluster.ExecutionProfile`, and currently provide the following options, +previously input from the noted attributes: + +- load_balancing_policy - :attr:`.Cluster.load_balancing_policy` +- request_timeout - :attr:`.Session.default_timeout`, optional :meth:`.Session.execute` parameter +- retry_policy - :attr:`.Cluster.default_retry_policy`, optional :attr:`.Statement.retry_policy` attribute +- consistency_level - :attr:`.Session.default_consistency_level`, optional :attr:`.Statement.consistency_level` attribute +- serial_consistency_level - :attr:`.Session.default_serial_consistency_level`, optional :attr:`.Statement.serial_consistency_level` attribute +- row_factory - :attr:`.Session.row_factory` attribute + +When using the new API, these parameters can be defined by instances of :class:`.cluster.ExecutionProfile`. + +Using Execution Profiles +------------------------ +Default +~~~~~~~ + +.. code:: python + + from cassandra.cluster import Cluster + cluster = Cluster() + session = cluster.connect() + local_query = 'SELECT rpc_address FROM system.local' + for _ in cluster.metadata.all_hosts(): + print session.execute(local_query)[0] + + +.. parsed-literal:: + + Row(rpc_address='127.0.0.2') + Row(rpc_address='127.0.0.1') + + +The default execution profile is built from Cluster parameters and default Session attributes. This profile matches existing default +parameters. + +Initializing cluster with profiles +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. code:: python + + from cassandra.cluster import ExecutionProfile + from cassandra.policies import WhiteListRoundRobinPolicy + + node1_profile = ExecutionProfile(load_balancing_policy=WhiteListRoundRobinPolicy(['127.0.0.1'])) + node2_profile = ExecutionProfile(load_balancing_policy=WhiteListRoundRobinPolicy(['127.0.0.2'])) + + profiles = {'node1': node1_profile, 'node2': node2_profile} + session = Cluster(execution_profiles=profiles).connect() + for _ in cluster.metadata.all_hosts(): + print session.execute(local_query, execution_profile='node1')[0] + + +.. parsed-literal:: + + Row(rpc_address='127.0.0.1') + Row(rpc_address='127.0.0.1') + + +.. code:: python + + for _ in cluster.metadata.all_hosts(): + print session.execute(local_query, execution_profile='node2')[0] + + +.. parsed-literal:: + + Row(rpc_address='127.0.0.2') + Row(rpc_address='127.0.0.2') + + +.. code:: python + + for _ in cluster.metadata.all_hosts(): + print session.execute(local_query)[0] + + +.. parsed-literal:: + + Row(rpc_address='127.0.0.2') + Row(rpc_address='127.0.0.1') + +Note that, even when custom profiles are injected, the default ``TokenAwarePolicy(DCAwareRoundRobinPolicy())`` is still +present. To override the default, specify a policy with the :data:`~.cluster.EXEC_PROFILE_DEFAULT` key. + +.. code:: python + + from cassandra.cluster import EXEC_PROFILE_DEFAULT + profile = ExecutionProfile(request_timeout=30) + cluster = Cluster(execution_profiles={EXEC_PROFILE_DEFAULT: profile}) + + +Adding named profiles +~~~~~~~~~~~~~~~~~~~~~ + +New profiles can be added constructing from scratch, or deriving from default: + +.. code:: python + + locked_execution = ExecutionProfile(load_balancing_policy=WhiteListRoundRobinPolicy(['127.0.0.1'])) + node1_profile = 'node1_whitelist' + cluster.add_execution_profile(node1_profile, locked_execution) + + for _ in cluster.metadata.all_hosts(): + print session.execute(local_query, execution_profile=node1_profile)[0] + + +.. parsed-literal:: + + Row(rpc_address='127.0.0.1') + Row(rpc_address='127.0.0.1') + +See :meth:`.Cluster.add_execution_profile` for details and optional parameters. + +Passing a profile instance without mapping +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +We also have the ability to pass profile instances to be used for execution, but not added to the mapping: + +.. code:: python + + from cassandra.query import tuple_factory + + tmp = session.execution_profile_clone_update('node1', request_timeout=100, row_factory=tuple_factory) + + print session.execute(local_query, execution_profile=tmp)[0] + print session.execute(local_query, execution_profile='node1')[0] + +.. parsed-literal:: + + ('127.0.0.1',) + Row(rpc_address='127.0.0.1') + +The new profile is a shallow copy, so the ``tmp`` profile shares a load balancing policy with one managed by the cluster. +If reference objects are to be updated in the clone, one would typically set those attributes to a new instance. diff --git a/3.25.11-scylla/_sources/faq.rst.txt b/3.25.11-scylla/_sources/faq.rst.txt new file mode 100644 index 0000000000..56cb648a24 --- /dev/null +++ b/3.25.11-scylla/_sources/faq.rst.txt @@ -0,0 +1,83 @@ +Frequently Asked Questions +========================== + +See also :doc:`cqlengine FAQ ` + +Why do connections or IO operations timeout in my WSGI application? +------------------------------------------------------------------- +Depending on your application process model, it may be forking after driver Session is created. Most IO reactors do not handle this, and problems will manifest as timeouts. + +To avoid this, make sure to create sessions per process, after the fork. Using uWSGI and Flask for example: + +.. code-block:: python + + from flask import Flask + from uwsgidecorators import postfork + from cassandra.cluster import Cluster + + session = None + prepared = None + + @postfork + def connect(): + global session, prepared + session = Cluster().connect() + prepared = session.prepare("SELECT release_version FROM system.local WHERE key=?") + + app = Flask(__name__) + + @app.route('/') + def server_version(): + row = session.execute(prepared, ('local',))[0] + return row.release_version + +uWSGI provides a ``postfork`` hook you can use to create sessions and prepared statements after the child process forks. + +How do I trace a request? +------------------------- +Request tracing can be turned on for any request by setting ``trace=True`` in :meth:`.Session.execute_async`. View the results by waiting on the future, then :meth:`.ResponseFuture.get_query_trace`. +Since tracing is done asynchronously to the request, this method polls until the trace is complete before querying data. + +.. code-block:: python + + >>> future = session.execute_async("SELECT * FROM system.local", trace=True) + >>> result = future.result() + >>> trace = future.get_query_trace() + >>> for e in trace.events: + >>> print e.source_elapsed, e.description + + 0:00:00.000077 Parsing select * from system.local + 0:00:00.000153 Preparing statement + 0:00:00.000309 Computing ranges to query + 0:00:00.000368 Submitting range requests on 1 ranges with a concurrency of 1 (279.77142 rows per range expected) + 0:00:00.000422 Submitted 1 concurrent range requests covering 1 ranges + 0:00:00.000480 Executing seq scan across 1 sstables for (min(-9223372036854775808), min(-9223372036854775808)) + 0:00:00.000669 Read 1 live and 0 tombstone cells + 0:00:00.000755 Scanned 1 rows and matched 1 + +``trace`` is a :class:`QueryTrace` object. + +How do I determine the replicas for a query? +---------------------------------------------- +With prepared statements, the replicas are obtained by ``routing_key``, based on current cluster token metadata: + +.. code-block:: python + + >>> prepared = session.prepare("SELECT * FROM example.t WHERE key=?") + >>> bound = prepared.bind((1,)) + >>> replicas = cluster.metadata.get_replicas(bound.keyspace, bound.routing_key) + >>> for h in replicas: + >>> print h.address + 127.0.0.1 + 127.0.0.2 + +``replicas`` is a list of :class:`Host` objects. + +How does the driver manage request retries? +------------------------------------------- +By default, retries are managed by the :attr:`.Cluster.default_retry_policy` set on the session Cluster. It can also +be specialized per statement by setting :attr:`.Statement.retry_policy`. + +Retries are presently attempted on the same coordinator, but this may change in the future. + +Please see :class:`.policies.RetryPolicy` for further details. diff --git a/3.25.11-scylla/_sources/getting_started.rst.txt b/3.25.11-scylla/_sources/getting_started.rst.txt new file mode 100644 index 0000000000..59a2acbd04 --- /dev/null +++ b/3.25.11-scylla/_sources/getting_started.rst.txt @@ -0,0 +1,479 @@ +Getting Started +=============== + +First, make sure you have the driver properly :doc:`installed `. + +Connecting to a Cluster +----------------------- +Before we can start executing any queries against a Cassandra cluster we need to setup +an instance of :class:`~.Cluster`. As the name suggests, you will typically have one +instance of :class:`~.Cluster` for each Cassandra cluster you want to interact +with. + +First, make sure you have the Cassandra driver properly :doc:`installed `. + +Connecting to Cassandra ++++++++++++++++++++++++ +The simplest way to create a :class:`~.Cluster` is like this: + +.. code-block:: python + + from cassandra.cluster import Cluster + + cluster = Cluster() + +This will attempt to connection to a Cassandra instance on your +local machine (127.0.0.1). You can also specify a list of IP +addresses for nodes in your cluster: + +.. code-block:: python + + from cassandra.cluster import Cluster + + cluster = Cluster(['192.168.0.1', '192.168.0.2']) + +The set of IP addresses we pass to the :class:`~.Cluster` is simply +an initial set of contact points. After the driver connects to one +of these nodes it will *automatically discover* the rest of the +nodes in the cluster and connect to them, so you don't need to list +every node in your cluster. + +If you need to use a non-standard port, use SSL, or customize the driver's +behavior in some other way, this is the place to do it: + +.. code-block:: python + + from cassandra.cluster import Cluster + cluster = Cluster(['192.168.0.1', '192.168.0.2'], port=..., ssl_context=...) + +Instantiating a :class:`~.Cluster` does not actually connect us to any nodes. +To establish connections and begin executing queries we need a +:class:`~.Session`, which is created by calling :meth:`.Cluster.connect()`: + +.. code-block:: python + + cluster = Cluster() + session = cluster.connect() + +Session Keyspace +---------------- +The :meth:`~.Cluster.connect()` method takes an optional ``keyspace`` argument +which sets the default keyspace for all queries made through that :class:`~.Session`: + +.. code-block:: python + + cluster = Cluster() + session = cluster.connect('mykeyspace') + +You can always change a Session's keyspace using :meth:`~.Session.set_keyspace` or +by executing a ``USE `` query: + +.. code-block:: python + + session.set_keyspace('users') + # or you can do this instead + session.execute('USE users') + +Execution Profiles +------------------ +Profiles are passed in by ``execution_profiles`` dict. + +In this case we can construct the base ``ExecutionProfile`` passing all attributes: + +.. code-block:: python + + from cassandra.cluster import Cluster, ExecutionProfile, EXEC_PROFILE_DEFAULT + from cassandra.policies import WhiteListRoundRobinPolicy, DowngradingConsistencyRetryPolicy + from cassandra.query import tuple_factory + + profile = ExecutionProfile( + load_balancing_policy=WhiteListRoundRobinPolicy(['127.0.0.1']), + retry_policy=DowngradingConsistencyRetryPolicy(), + consistency_level=ConsistencyLevel.LOCAL_QUORUM, + serial_consistency_level=ConsistencyLevel.LOCAL_SERIAL, + request_timeout=15, + row_factory=tuple_factory + ) + cluster = Cluster(execution_profiles={EXEC_PROFILE_DEFAULT: profile}) + session = cluster.connect() + + print(session.execute("SELECT release_version FROM system.local").one()) + +Users are free to setup additional profiles to be used by name: + +.. code-block:: python + + profile_long = ExecutionProfile(request_timeout=30) + cluster = Cluster(execution_profiles={'long': profile_long}) + session = cluster.connect() + session.execute(statement, execution_profile='long') + +Also, parameters passed to ``Session.execute`` or attached to ``Statement``\s are still honored as before. + +Executing Queries +----------------- +Now that we have a :class:`.Session` we can begin to execute queries. The simplest +way to execute a query is to use :meth:`~.Session.execute()`: + +.. code-block:: python + + rows = session.execute('SELECT name, age, email FROM users') + for user_row in rows: + print user_row.name, user_row.age, user_row.email + +This will transparently pick a Cassandra node to execute the query against +and handle any retries that are necessary if the operation fails. + +By default, each row in the result set will be a +`namedtuple `_. +Each row will have a matching attribute for each column defined in the schema, +such as ``name``, ``age``, and so on. You can also treat them as normal tuples +by unpacking them or accessing fields by position. The following three +examples are equivalent: + +.. code-block:: python + + rows = session.execute('SELECT name, age, email FROM users') + for row in rows: + print row.name, row.age, row.email + +.. code-block:: python + + rows = session.execute('SELECT name, age, email FROM users') + for (name, age, email) in rows: + print name, age, email + +.. code-block:: python + + rows = session.execute('SELECT name, age, email FROM users') + for row in rows: + print row[0], row[1], row[2] + +If you prefer another result format, such as a ``dict`` per row, you +can change the :attr:`~.Session.row_factory` attribute. + +As mentioned in our `Drivers Best Practices Guide `_, +it is highly recommended to use `Prepared statements <#prepared-statement>`_ for your +frequently run queries. + +.. _prepared-statement: + +Prepared Statements +------------------- +Prepared statements are queries that are parsed by Cassandra and then saved +for later use. When the driver uses a prepared statement, it only needs to +send the values of parameters to bind. This lowers network traffic +and CPU utilization within Cassandra because Cassandra does not have to +re-parse the query each time. + +To prepare a query, use :meth:`.Session.prepare()`: + +.. code-block:: python + + user_lookup_stmt = session.prepare("SELECT * FROM users WHERE user_id=?") + + users = [] + for user_id in user_ids_to_query: + user = session.execute(user_lookup_stmt, [user_id]) + users.append(user) + +:meth:`~.Session.prepare()` returns a :class:`~.PreparedStatement` instance +which can be used in place of :class:`~.SimpleStatement` instances or literal +string queries. It is automatically prepared against all nodes, and the driver +handles re-preparing against new nodes and restarted nodes when necessary. + +Note that the placeholders for prepared statements are ``?`` characters. This +is different than for simple, non-prepared statements (although future versions +of the driver may use the same placeholders for both). + +Passing Parameters to CQL Queries +--------------------------------- +Althought it is not recommended, you can also pass parameters to non-prepared +statements. The driver supports two forms of parameter place-holders: positional +and named. + +Positional parameters are used with a ``%s`` placeholder. For example, +when you execute: + +.. code-block:: python + + session.execute( + """ + INSERT INTO users (name, credits, user_id) + VALUES (%s, %s, %s) + """, + ("John O'Reilly", 42, uuid.uuid1()) + ) + +It is translated to the following CQL query:: + + INSERT INTO users (name, credits, user_id) + VALUES ('John O''Reilly', 42, 2644bada-852c-11e3-89fb-e0b9a54a6d93) + +Note that you should use ``%s`` for all types of arguments, not just strings. +For example, this would be **wrong**: + +.. code-block:: python + + session.execute("INSERT INTO USERS (name, age) VALUES (%s, %d)", ("bob", 42)) # wrong + +Instead, use ``%s`` for the age placeholder. + +If you need to use a literal ``%`` character, use ``%%``. + +**Note**: you must always use a sequence for the second argument, even if you are +only passing in a single variable: + +.. code-block:: python + + session.execute("INSERT INTO foo (bar) VALUES (%s)", "blah") # wrong + session.execute("INSERT INTO foo (bar) VALUES (%s)", ("blah")) # wrong + session.execute("INSERT INTO foo (bar) VALUES (%s)", ("blah", )) # right + session.execute("INSERT INTO foo (bar) VALUES (%s)", ["blah"]) # right + + +Note that the second line is incorrect because in Python, single-element tuples +require a comma. + +Named place-holders use the ``%(name)s`` form: + +.. code-block:: python + + session.execute( + """ + INSERT INTO users (name, credits, user_id, username) + VALUES (%(name)s, %(credits)s, %(user_id)s, %(name)s) + """, + {'name': "John O'Reilly", 'credits': 42, 'user_id': uuid.uuid1()} + ) + +Note that you can repeat placeholders with the same name, such as ``%(name)s`` +in the above example. + +Only data values should be supplied this way. Other items, such as keyspaces, +table names, and column names should be set ahead of time (typically using +normal string formatting). + +.. _type-conversions: + +Type Conversions +---------------- +For non-prepared statements, Python types are cast to CQL literals in the +following way: + +.. table:: + + +--------------------+-------------------------+ + | Python Type | CQL Literal Type | + +====================+=========================+ + | ``None`` | ``NULL`` | + +--------------------+-------------------------+ + | ``bool`` | ``boolean`` | + +--------------------+-------------------------+ + | ``float`` | | ``float`` | + | | | ``double`` | + +--------------------+-------------------------+ + | | ``int`` | | ``int`` | + | | ``long`` | | ``bigint`` | + | | | ``varint`` | + | | | ``smallint`` | + | | | ``tinyint`` | + | | | ``counter`` | + +--------------------+-------------------------+ + | ``decimal.Decimal``| ``decimal`` | + +--------------------+-------------------------+ + | | ``str`` | | ``ascii`` | + | | ``unicode`` | | ``varchar`` | + | | | ``text`` | + +--------------------+-------------------------+ + | | ``buffer`` | ``blob`` | + | | ``bytearray`` | | + +--------------------+-------------------------+ + | ``date`` | ``date`` | + +--------------------+-------------------------+ + | ``datetime`` | ``timestamp`` | + +--------------------+-------------------------+ + | ``time`` | ``time`` | + +--------------------+-------------------------+ + | | ``list`` | ``list`` | + | | ``tuple`` | | + | | generator | | + +--------------------+-------------------------+ + | | ``set`` | ``set`` | + | | ``frozenset`` | | + +--------------------+-------------------------+ + | | ``dict`` | ``map`` | + | | ``OrderedDict`` | | + +--------------------+-------------------------+ + | ``uuid.UUID`` | | ``timeuuid`` | + | | | ``uuid`` | + +--------------------+-------------------------+ + + +Asynchronous Queries +-------------------- +The driver supports asynchronous query execution through +:meth:`~.Session.execute_async()`. Instead of waiting for the query to +complete and returning rows directly, this method almost immediately +returns a :class:`~.ResponseFuture` object. There are two ways of +getting the final result from this object. + +The first is by calling :meth:`~.ResponseFuture.result()` on it. If +the query has not yet completed, this will block until it has and +then return the result or raise an Exception if an error occurred. +For example: + +.. code-block:: python + + from cassandra import ReadTimeout + + query = "SELECT * FROM users WHERE user_id=%s" + future = session.execute_async(query, [user_id]) + + # ... do some other work + + try: + rows = future.result() + user = rows[0] + print user.name, user.age + except ReadTimeout: + log.exception("Query timed out:") + +This works well for executing many queries concurrently: + +.. code-block:: python + + # build a list of futures + futures = [] + query = "SELECT * FROM users WHERE user_id=%s" + for user_id in ids_to_fetch: + futures.append(session.execute_async(query, [user_id]) + + # wait for them to complete and use the results + for future in futures: + rows = future.result() + print rows[0].name + +Alternatively, instead of calling :meth:`~.ResponseFuture.result()`, +you can attach callback and errback functions through the +:meth:`~.ResponseFuture.add_callback()`, +:meth:`~.ResponseFuture.add_errback()`, and +:meth:`~.ResponseFuture.add_callbacks()`, methods. If you have used +Twisted Python before, this is designed to be a lightweight version of +that: + +.. code-block:: python + + def handle_success(rows): + user = rows[0] + try: + process_user(user.name, user.age, user.id) + except Exception: + log.error("Failed to process user %s", user.id) + # don't re-raise errors in the callback + + def handle_error(exception): + log.error("Failed to fetch user info: %s", exception) + + + future = session.execute_async(query) + future.add_callbacks(handle_success, handle_error) + +There are a few important things to remember when working with callbacks: + * **Exceptions that are raised inside the callback functions will be logged and then ignored.** + * Your callback will be run on the event loop thread, so any long-running + operations will prevent other requests from being handled + + +Setting a Consistency Level +--------------------------- +The consistency level used for a query determines how many of the +replicas of the data you are interacting with need to respond for +the query to be considered a success. + +By default, :attr:`.ConsistencyLevel.LOCAL_ONE` will be used for all queries. +You can specify a different default by setting the :attr:`.ExecutionProfile.consistency_level` +for the execution profile with key :data:`~.cluster.EXEC_PROFILE_DEFAULT`. +To specify a different consistency level per request, wrap queries +in a :class:`~.SimpleStatement`: + +.. code-block:: python + + from cassandra import ConsistencyLevel + from cassandra.query import SimpleStatement + + query = SimpleStatement( + "INSERT INTO users (name, age) VALUES (%s, %s)", + consistency_level=ConsistencyLevel.QUORUM) + session.execute(query, ('John', 42)) + +Setting a Consistency Level with Prepared Statements +---------------------------------------------------- +To specify a consistency level for prepared statements, you have two options. + +The first is to set a default consistency level for every execution of the +prepared statement: + +.. code-block:: python + + from cassandra import ConsistencyLevel + + cluster = Cluster() + session = cluster.connect("mykeyspace") + user_lookup_stmt = session.prepare("SELECT * FROM users WHERE user_id=?") + user_lookup_stmt.consistency_level = ConsistencyLevel.QUORUM + + # these will both use QUORUM + user1 = session.execute(user_lookup_stmt, [user_id1])[0] + user2 = session.execute(user_lookup_stmt, [user_id2])[0] + +The second option is to create a :class:`~.BoundStatement` from the +:class:`~.PreparedStatement` and binding parameters and set a consistency +level on that: + +.. code-block:: python + + # override the QUORUM default + user3_lookup = user_lookup_stmt.bind([user_id3]) + user3_lookup.consistency_level = ConsistencyLevel.ALL + user3 = session.execute(user3_lookup) + +Speculative Execution +--------------------- + +Speculative execution is a way to minimize latency by preemptively executing several +instances of the same query against different nodes. For more details about this +technique, see `Speculative Execution with DataStax Drivers `_. + +To enable speculative execution: + +* Configure a :class:`~.policies.SpeculativeExecutionPolicy` with the ExecutionProfile +* Mark your query as idempotent, which mean it can be applied multiple + times without changing the result of the initial application. + See `Query Idempotence `_ for more details. + + +Example: + +.. code-block:: python + + from cassandra.cluster import Cluster, ExecutionProfile, EXEC_PROFILE_DEFAULT + from cassandra.policies import ConstantSpeculativeExecutionPolicy + from cassandra.query import SimpleStatement + + # Configure the speculative execution policy + ep = ExecutionProfile( + speculative_execution_policy=ConstantSpeculativeExecutionPolicy(delay=.5, max_attempts=10) + ) + cluster = Cluster(..., execution_profiles={EXEC_PROFILE_DEFAULT: ep}) + session = cluster.connect() + + # Mark the query idempotent + query = SimpleStatement( + "UPDATE my_table SET list_col = [1] WHERE pk = 1", + is_idempotent=True + ) + + # Execute. A new query will be sent to the server every 0.5 second + # until we receive a response, for a max number attempts of 10. + session.execute(query) diff --git a/3.25.11-scylla/_sources/index.rst.txt b/3.25.11-scylla/_sources/index.rst.txt new file mode 100644 index 0000000000..db6d0880d0 --- /dev/null +++ b/3.25.11-scylla/_sources/index.rst.txt @@ -0,0 +1,103 @@ +Python Driver for Scylla and Apache Cassandra® +============================================== +A Python client driver for `Scylla `_. +This driver works exclusively with the Cassandra Query Language v3 (CQL3) +and Cassandra's native protocol. + +The driver supports Python 2.7, 3.5, 3.6, 3.7 and 3.8. + +This driver is open source under the +`Apache v2 License `_. +The source code for this driver can be found on `GitHub `_. + +Scylla Driver is a fork from `DataStax Python Driver `_, including some non-breaking changes for Scylla optimization, with more updates planned. + +Contents +-------- +:doc:`installation` + How to install the driver. + +:doc:`getting_started` + A guide through the first steps of connecting to Scylla and executing queries + +:doc:`scylla_specific` + A list of feature available only on ``scylla-driver`` + +:doc:`execution_profiles` + An introduction to a more flexible way of configuring request execution + +:doc:`lwt` + Working with results of conditional requests + +:doc:`object_mapper` + Introduction to the integrated object mapper, cqlengine + +:doc:`performance` + Tips for getting good performance. + +:doc:`query_paging` + Notes on paging large query results + +:doc:`security` + An overview of the security features of the driver + +:doc:`upgrading` + A guide to upgrading versions of the driver + +:doc:`user_defined_types` + Working with Scylla's user-defined types (UDT) + +:doc:`dates_and_times` + Some discussion on the driver's approach to working with timestamp, date, time types + +:doc:`scylla_cloud` + Connect to Scylla Cloud + +:doc:`CHANGELOG` + Log of changes to the driver, organized by version. + +:doc:`faq` + A collection of Frequently Asked Questions + +:doc:`api/index` + The API documentation. + +.. toctree:: + :hidden: + + api/index + installation + getting_started + scylla_specific + upgrading + execution_profiles + performance + query_paging + lwt + security + user_defined_types + object_mapper + dates_and_times + scylla_cloud + faq + +Getting Help +------------ +Visit the :doc:`FAQ section ` in this documentation. + +Please send questions to the Scylla `user list `_. + + +Reporting Issues +---------------- + +Please report any bugs and make any feature requests on the `Github project issues `_ + + +Copyright +--------- + +© 2013-2017 DataStax + +© 2016, The Apache Software Foundation. +Apache®, Apache Cassandra®, Cassandra®, the Apache feather logo and the Apache Cassandra® Eye logo are either registered trademarks or trademarks of the Apache Software Foundation in the United States and/or other countries. No endorsement by The Apache Software Foundation is implied by the use of these marks. diff --git a/3.25.11-scylla/_sources/installation.rst.txt b/3.25.11-scylla/_sources/installation.rst.txt new file mode 100644 index 0000000000..4996a02c1b --- /dev/null +++ b/3.25.11-scylla/_sources/installation.rst.txt @@ -0,0 +1,234 @@ +Installation +============ + +Supported Platforms +------------------- +Python 2.7, 3.5, 3.6, 3.7 and 3.8 are supported. Both CPython (the standard Python +implementation) and `PyPy `_ are supported and tested. + +Linux, OSX, and Windows are supported. + +Installation through pip +------------------------ +`pip `_ is the suggested tool for installing +packages. It will handle installing all Python dependencies for the driver at +the same time as the driver itself. To install the driver*:: + + pip install scylla-driver + +You can use ``pip install --pre scylla-driver`` if you need to install a beta version. + +***Note**: if intending to use optional extensions, install the `dependencies <#optional-non-python-dependencies>`_ first. The driver may need to be reinstalled if dependencies are added after the initial installation. + +Verifying your Installation +--------------------------- +To check if the installation was successful, you can run:: + + python -c 'import cassandra; print cassandra.__version__' + +It should print something like "3.22.0". + +.. _installation-datastax-graph: + +(*Optional*) Graph +--------------------------- +The driver provides an optional fluent graph API that depends on Apache TinkerPop (gremlinpython). It is +not installed by default. To be able to build Gremlin traversals, you need to install +the `graph` requirements:: + + pip install scylla-driver[graph] + +(*Optional*) Compression Support +-------------------------------- +Compression can optionally be used for communication between the driver and +Cassandra. There are currently two supported compression algorithms: +snappy (in Cassandra 1.2+) and LZ4 (only in Cassandra 2.0+). If either is +available for the driver and Cassandra also supports it, it will +be used automatically. + +For lz4 support:: + + pip install lz4 + +For snappy support:: + + pip install python-snappy + +(If using a Debian Linux derivative such as Ubuntu, it may be easier to +just run ``apt-get install python-snappy``.) + +(*Optional*) Metrics Support +---------------------------- +The driver has built-in support for capturing :attr:`.Cluster.metrics` about +the queries you run. However, the ``scales`` library is required to +support this:: + + pip install scales + + +Speeding Up Installation +^^^^^^^^^^^^^^^^^^^^^^^^ + +By default, installing the driver through ``pip`` uses a pre-compiled, platform-specific wheel when available. +If using a source distribution rather than a wheel, Cython is used to compile certain parts of the driver. +This makes those hot paths faster at runtime, but the Cython compilation +process can take a long time -- as long as 10 minutes in some environments. + +In environments where performance is less important, it may be worth it to +:ref:`disable Cython as documented below `. +You can also use ``CASS_DRIVER_BUILD_CONCURRENCY`` to increase the number of +threads used to build the driver and any C extensions: + +.. code-block:: bash + + $ # installing from source + $ CASS_DRIVER_BUILD_CONCURRENCY=8 python setup.py install + $ # installing from pip + $ CASS_DRIVER_BUILD_CONCURRENCY=8 pip install scylla-driver + +OSX Installation Error +^^^^^^^^^^^^^^^^^^^^^^ +If you're installing on OSX and have XCode 5.1 installed, you may see an error like this:: + + clang: error: unknown argument: '-mno-fused-madd' [-Wunused-command-line-argument-hard-error-in-future] + +To fix this, re-run the installation with an extra compilation flag: + +.. code-block:: bash + + ARCHFLAGS=-Wno-error=unused-command-line-argument-hard-error-in-future pip install scylla-driver + +.. _windows_build: + +Windows Installation Notes +-------------------------- +Installing the driver with extensions in Windows sometimes presents some challenges. A few notes about common +hang-ups: + +Setup requires a compiler. When using Python 2, this is as simple as installing `this package `_ +(this link is also emitted during install if setuptools is unable to find the resources it needs). Depending on your +system settings, this package may install as a user-specific application. Make sure to install for everyone, or at least +as the user that will be building the Python environment. + +It is also possible to run the build with your compiler of choice. Just make sure to have your environment setup with +the proper paths. Make sure the compiler target architecture matches the bitness of your Python runtime. +Perhaps the easiest way to do this is to run the build/install from a Visual Studio Command Prompt (a +shortcut installed with Visual Studio that sources the appropriate environment and presents a shell). + +Manual Installation +------------------- +You can always install the driver directly from a source checkout or tarball. +When installing manually, ensure the python dependencies are already +installed. You can find the list of dependencies in +`requirements.txt `_. + +Once the dependencies are installed, simply run:: + + python setup.py install + + +(*Optional*) Non-python Dependencies +------------------------------------ +The driver has several **optional** features that have non-Python dependencies. + +C Extensions +^^^^^^^^^^^^ +By default, a number of extensions are compiled, providing faster hashing +for token-aware routing with the ``Murmur3Partitioner``, +`libev `_ event loop integration, +and Cython optimized extensions. + +When installing manually through setup.py, you can disable both with +the ``--no-extensions`` option, or selectively disable them with +with ``--no-murmur3``, ``--no-libev``, or ``--no-cython``. + +To compile the extensions, ensure that GCC and the Python headers are available. + +On Ubuntu and Debian, this can be accomplished by running:: + + $ sudo apt-get install gcc python-dev + +On RedHat and RedHat-based systems like CentOS and Fedora:: + + $ sudo yum install gcc python-devel + +On OS X, homebrew installations of Python should provide the necessary headers. + +See :ref:`windows_build` for notes on configuring the build environment on Windows. + +.. _cython-extensions: + +Cython-based Extensions +~~~~~~~~~~~~~~~~~~~~~~~ +By default, this package uses `Cython `_ to optimize core modules and build custom extensions. +This is not a hard requirement, but is engaged by default to build extensions offering better performance than the +pure Python implementation. + +This is a costly build phase, especially in clean environments where the Cython compiler must be built +This build phase can be avoided using the build switch, or an environment variable:: + + python setup.py install --no-cython + +Alternatively, an environment variable can be used to switch this option regardless of +context:: + + CASS_DRIVER_NO_CYTHON=1 + - or, to disable all extensions: + CASS_DRIVER_NO_EXTENSIONS=1 + +This method is required when using pip, which provides no other way of injecting user options in a single command:: + + CASS_DRIVER_NO_CYTHON=1 pip install scylla-driver + CASS_DRIVER_NO_CYTHON=1 sudo -E pip install ~/python-driver + +The environment variable is the preferred option because it spans all invocations of setup.py, and will +prevent Cython from being materialized as a setup requirement. + +If your sudo configuration does not allow SETENV, you must push the option flag down via pip. However, pip +applies these options to all dependencies (which break on the custom flag). Therefore, you must first install +dependencies, then use install-option:: + + sudo pip install six futures + sudo pip install --install-option="--no-cython" + + +libev support +^^^^^^^^^^^^^ +The driver currently uses Python's ``asyncore`` module for its default +event loop. For better performance, ``libev`` is also supported through +a C extension. + +If you're on Linux, you should be able to install libev +through a package manager. For example, on Debian/Ubuntu:: + + $ sudo apt-get install libev4 libev-dev + +On RHEL/CentOS/Fedora:: + + $ sudo yum install libev libev-devel + +If you're on Mac OS X, you should be able to install libev +through `Homebrew `_. For example, on Mac OS X:: + + $ brew install libev + +The libev extension is not built for Windows (the build process is complex, and the Windows implementation uses +select anyway). + +If successful, you should be able to build and install the extension +(just using ``setup.py build`` or ``setup.py install``) and then use +the libev event loop by doing the following: + +.. code-block:: python + + >>> from cassandra.io.libevreactor import LibevConnection + >>> from cassandra.cluster import Cluster + + >>> cluster = Cluster() + >>> cluster.connection_class = LibevConnection + >>> session = cluster.connect() + +(*Optional*) Configuring SSL +----------------------------- +Andrew Mussey has published a thorough guide on +`Using SSL with the DataStax Python driver `_. diff --git a/3.25.11-scylla/_sources/lwt.rst.txt b/3.25.11-scylla/_sources/lwt.rst.txt new file mode 100644 index 0000000000..2cc272f350 --- /dev/null +++ b/3.25.11-scylla/_sources/lwt.rst.txt @@ -0,0 +1,91 @@ +Lightweight Transactions (Compare-and-set) +========================================== + +Lightweight Transactions (LWTs) are mostly pass-through CQL for the driver. However, +the server returns some specialized results indicating the outcome and optional state +preceding the transaction. + +For pertinent execution parameters, see :attr:`.Statement.serial_consistency_level`. + +This section discusses working with specialized result sets returned by the server for LWTs, +and how to work with them using the driver. + + +Specialized Results +------------------- +The result returned from a LWT request is always a single row result. It will always have +prepended a special column named ``[applied]``. How this value appears in your results depends +on the row factory in use. See below for examples. + +The value of this ``[applied]`` column is boolean value indicating whether or not the transaction was applied. +If ``True``, it is the only column in the result. If ``False``, the additional columns depend on the LWT operation being +executed: + +- When using a ``UPDATE ... IF "col" = ...`` clause, the result will contain the ``[applied]`` column, plus the existing columns + and values for any columns in the ``IF`` clause (and thus the value that caused the transaction to fail). + +- When using ``INSERT ... IF NOT EXISTS``, the result will contain the ``[applied]`` column, plus all columns and values + of the existing row that rejected the transaction. + +- ``UPDATE .. IF EXISTS`` never has additional columns, regardless of ``[applied]`` status. + +How the ``[applied]`` column manifests depends on the row factory in use. Considering the following (initially empty) table:: + + CREATE TABLE test.t ( + k int PRIMARY KEY, + v int, + x int + ) + +... the following sections show the expected result for a number of example statements, using the three base row factories. + +named_tuple_factory (default) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +The name ``[applied]`` is not a valid Python identifier, so the square brackets are actually removed +from the attribute for the resulting ``namedtuple``. The row always has a boolean column ``applied`` in position 0:: + + >>> session.execute("INSERT INTO t (k,v) VALUES (0,0) IF NOT EXISTS") + Row(applied=True) + + >>> session.execute("INSERT INTO t (k,v) VALUES (0,0) IF NOT EXISTS") + Row(applied=False, k=0, v=0, x=None) + + >>> session.execute("UPDATE t SET v = 1, x = 2 WHERE k = 0 IF v =0") + Row(applied=True) + + >>> session.execute("UPDATE t SET v = 1, x = 2 WHERE k = 0 IF v =0 AND x = 1") + Row(applied=False, v=1, x=2) + +tuple_factory +~~~~~~~~~~~~~ +This return type does not refer to names, but the boolean value ``applied`` is always present in position 0:: + + >>> session.execute("INSERT INTO t (k,v) VALUES (0,0) IF NOT EXISTS") + (True,) + + >>> session.execute("INSERT INTO t (k,v) VALUES (0,0) IF NOT EXISTS") + (False, 0, 0, None) + + >>> session.execute("UPDATE t SET v = 1, x = 2 WHERE k = 0 IF v =0") + (True,) + + >>> session.execute("UPDATE t SET v = 1, x = 2 WHERE k = 0 IF v =0 AND x = 1") + (False, 1, 2) + +dict_factory +~~~~~~~~~~~~ +The retuned ``dict`` contains the ``[applied]`` key:: + + >>> session.execute("INSERT INTO t (k,v) VALUES (0,0) IF NOT EXISTS") + {u'[applied]': True} + + >>> session.execute("INSERT INTO t (k,v) VALUES (0,0) IF NOT EXISTS") + {u'x': 2, u'[applied]': False, u'v': 1} + + >>> session.execute("UPDATE t SET v = 1, x = 2 WHERE k = 0 IF v =0") + {u'x': None, u'[applied]': False, u'k': 0, u'v': 0} + + >>> session.execute("UPDATE t SET v = 1, x = 2 WHERE k = 0 IF v =0 AND x = 1") + {u'[applied]': True} + + diff --git a/3.25.11-scylla/_sources/object_mapper.rst.txt b/3.25.11-scylla/_sources/object_mapper.rst.txt new file mode 100644 index 0000000000..50d3cbf320 --- /dev/null +++ b/3.25.11-scylla/_sources/object_mapper.rst.txt @@ -0,0 +1,105 @@ +Object Mapper +============= + +cqlengine is the Cassandra CQL 3 Object Mapper packaged with this driver + +:ref:`Jump to Getting Started ` + +Contents +-------- +:doc:`cqlengine/upgrade_guide` + For migrating projects from legacy cqlengine, to the integrated product + +:doc:`cqlengine/models` + Examples defining models, and mapping them to tables + +:doc:`cqlengine/queryset` + Overview of query sets and filtering + +:doc:`cqlengine/batches` + Working with batch mutations + +:doc:`cqlengine/connections` + Working with multiple sessions + +:ref:`API Documentation ` + Index of API documentation + +:doc:`cqlengine/third_party` + High-level examples in Celery and uWSGI + +:doc:`cqlengine/faq` + +.. toctree:: + :hidden: + + cqlengine/upgrade_guide + cqlengine/models + cqlengine/queryset + cqlengine/batches + cqlengine/connections + cqlengine/third_party + cqlengine/faq + +.. _getting-started: + +Getting Started +--------------- + +.. code-block:: python + + import uuid + from cassandra.cqlengine import columns + from cassandra.cqlengine import connection + from datetime import datetime + from cassandra.cqlengine.management import sync_table + from cassandra.cqlengine.models import Model + + #first, define a model + class ExampleModel(Model): + example_id = columns.UUID(primary_key=True, default=uuid.uuid4) + example_type = columns.Integer(index=True) + created_at = columns.DateTime() + description = columns.Text(required=False) + + #next, setup the connection to your cassandra server(s)... + # see http://datastax.github.io/python-driver/api/cassandra/cluster.html for options + # the list of hosts will be passed to create a Cluster() instance + connection.setup(['127.0.0.1'], "cqlengine", protocol_version=3) + + #...and create your CQL table + >>> sync_table(ExampleModel) + + #now we can create some rows: + >>> em1 = ExampleModel.create(example_type=0, description="example1", created_at=datetime.now()) + >>> em2 = ExampleModel.create(example_type=0, description="example2", created_at=datetime.now()) + >>> em3 = ExampleModel.create(example_type=0, description="example3", created_at=datetime.now()) + >>> em4 = ExampleModel.create(example_type=0, description="example4", created_at=datetime.now()) + >>> em5 = ExampleModel.create(example_type=1, description="example5", created_at=datetime.now()) + >>> em6 = ExampleModel.create(example_type=1, description="example6", created_at=datetime.now()) + >>> em7 = ExampleModel.create(example_type=1, description="example7", created_at=datetime.now()) + >>> em8 = ExampleModel.create(example_type=1, description="example8", created_at=datetime.now()) + + #and now we can run some queries against our table + >>> ExampleModel.objects.count() + 8 + >>> q = ExampleModel.objects(example_type=1) + >>> q.count() + 4 + >>> for instance in q: + >>> print instance.description + example5 + example6 + example7 + example8 + + #here we are applying additional filtering to an existing query + #query objects are immutable, so calling filter returns a new + #query object + >>> q2 = q.filter(example_id=em5.example_id) + + >>> q2.count() + 1 + >>> for instance in q2: + >>> print instance.description + example5 diff --git a/3.25.11-scylla/_sources/performance.rst.txt b/3.25.11-scylla/_sources/performance.rst.txt new file mode 100644 index 0000000000..f7a3f49e0f --- /dev/null +++ b/3.25.11-scylla/_sources/performance.rst.txt @@ -0,0 +1,45 @@ +Performance Notes +================= +The Python driver for Cassandra offers several methods for executing queries. +You can synchronously block for queries to complete using +:meth:`.Session.execute()`, you can obtain asynchronous request futures through +:meth:`.Session.execute_async()`, and you can attach a callback to the future +with :meth:`.ResponseFuture.add_callback()`. + +Examples of multiple request patterns can be found in the benchmark scripts included in the driver project. + +The choice of execution pattern will depend on the application context. For applications dealing with multiple +requests in a given context, the recommended pattern is to use concurrent asynchronous +requests with callbacks. For many use cases, you don't need to implement this pattern yourself. +:meth:`cassandra.concurrent.execute_concurrent` and :meth:`cassandra.concurrent.execute_concurrent_with_args` +provide this pattern with a synchronous API and tunable concurrency. + +Due to the GIL and limited concurrency, the driver can become CPU-bound pretty quickly. The sections below +discuss further runtime and design considerations for mitigating this limitation. + +PyPy +---- +`PyPy `_ is an alternative Python runtime which uses a JIT compiler to +reduce CPU consumption. This leads to a huge improvement in the driver performance, +more than doubling throughput for many workloads. + +Cython Extensions +----------------- +`Cython `_ is an optimizing compiler and language that can be used to compile the core files and +optional extensions for the driver. Cython is not a strict dependency, but the extensions will be built by default. + +See :doc:`installation` for details on controlling this build. + +multiprocessing +--------------- +All of the patterns discussed above may be used over multiple processes using the +`multiprocessing `_ +module. Multiple processes will scale better than multiple threads, so if high throughput is your goal, +consider this option. + +Be sure to **never share any** :class:`~.Cluster`, :class:`~.Session`, +**or** :class:`~.ResponseFuture` **objects across multiple processes**. These +objects should all be created after forking the process, not before. + +For further discussion and simple examples using the driver with ``multiprocessing``, +see `this blog post `_. diff --git a/3.25.11-scylla/_sources/query_paging.rst.txt b/3.25.11-scylla/_sources/query_paging.rst.txt new file mode 100644 index 0000000000..23ee2c1129 --- /dev/null +++ b/3.25.11-scylla/_sources/query_paging.rst.txt @@ -0,0 +1,95 @@ +.. _query-paging: + +Paging Large Queries +==================== +Cassandra 2.0+ offers support for automatic query paging. Starting with +version 2.0 of the driver, if :attr:`~.Cluster.protocol_version` is greater than +:const:`2` (it is by default), queries returning large result sets will be +automatically paged. + +Controlling the Page Size +------------------------- +By default, :attr:`.Session.default_fetch_size` controls how many rows will +be fetched per page. This can be overridden per-query by setting +:attr:`~.fetch_size` on a :class:`~.Statement`. By default, each page +will contain at most 5000 rows. + +Handling Paged Results +---------------------- +Whenever the number of result rows for are query exceed the page size, an +instance of :class:`~.PagedResult` will be returned instead of a normal +list. This class implements the iterator interface, so you can treat +it like a normal iterator over rows:: + + from cassandra.query import SimpleStatement + query = "SELECT * FROM users" # users contains 100 rows + statement = SimpleStatement(query, fetch_size=10) + for user_row in session.execute(statement): + process_user(user_row) + +Whenever there are no more rows in the current page, the next page will +be fetched transparently. However, note that it *is* possible for +an :class:`Exception` to be raised while fetching the next page, just +like you might see on a normal call to ``session.execute()``. + +If you use :meth:`.Session.execute_async()` along with, +:meth:`.ResponseFuture.result()`, the first page will be fetched before +:meth:`~.ResponseFuture.result()` returns, but latter pages will be +transparently fetched synchronously while iterating the result. + +Handling Paged Results with Callbacks +------------------------------------- +If callbacks are attached to a query that returns a paged result, +the callback will be called once per page with a normal list of rows. + +Use :attr:`.ResponseFuture.has_more_pages` and +:meth:`.ResponseFuture.start_fetching_next_page()` to continue fetching +pages. For example:: + + class PagedResultHandler(object): + + def __init__(self, future): + self.error = None + self.finished_event = Event() + self.future = future + self.future.add_callbacks( + callback=self.handle_page, + errback=self.handle_err) + + def handle_page(self, rows): + for row in rows: + process_row(row) + + if self.future.has_more_pages: + self.future.start_fetching_next_page() + else: + self.finished_event.set() + + def handle_error(self, exc): + self.error = exc + self.finished_event.set() + + future = session.execute_async("SELECT * FROM users") + handler = PagedResultHandler(future) + handler.finished_event.wait() + if handler.error: + raise handler.error + +Resume Paged Results +-------------------- + +You can resume the pagination when executing a new query by using the :attr:`.ResultSet.paging_state`. This can be useful if you want to provide some stateless pagination capabilities to your application (ie. via http). For example:: + + from cassandra.query import SimpleStatement + query = "SELECT * FROM users" + statement = SimpleStatement(query, fetch_size=10) + results = session.execute(statement) + + # save the paging_state somewhere and return current results + web_session['paging_state'] = results.paging_state + + + # resume the pagination sometime later... + statement = SimpleStatement(query, fetch_size=10) + ps = web_session['paging_state'] + results = session.execute(statement, paging_state=ps) diff --git a/3.25.11-scylla/_sources/scylla_cloud.rst.txt b/3.25.11-scylla/_sources/scylla_cloud.rst.txt new file mode 100644 index 0000000000..62aaf76433 --- /dev/null +++ b/3.25.11-scylla/_sources/scylla_cloud.rst.txt @@ -0,0 +1,5 @@ +Scylla Cloud +------------ + +To connect to a `Scylla Cloud `_ cluster, go to the Cluster Connect page, Python example. +For best performance, make sure to use the Scylla Driver. diff --git a/3.25.11-scylla/_sources/scylla_specific.rst.txt b/3.25.11-scylla/_sources/scylla_specific.rst.txt new file mode 100644 index 0000000000..101ddb534b --- /dev/null +++ b/3.25.11-scylla/_sources/scylla_specific.rst.txt @@ -0,0 +1,106 @@ +Scylla Specific Features +======================== + +Shard Awareness +--------------- + +**scylla-driver** is shard aware and contains extensions that work with the TokenAwarePolicy supported by Scylla 2.3 and onwards. Using this policy, the driver can select a connection to a particular shard based on the shard's token. +As a result, latency is significantly reduced because there is no need to pass data between the shards. + +Details on the scylla cql protocol extensions +https://github.com/scylladb/scylla/blob/master/docs/dev/protocol-extensions.md#intranode-sharding + +For using it you only need to enable ``TokenAwarePolicy`` on the ``Cluster`` + +See the configuration of ``native_shard_aware_transport_port`` and ``native_shard_aware_transport_port_ssl`` on scylla.yaml: +https://github.com/scylladb/scylla/blob/master/docs/dev/protocols.md#cql-client-protocol + +.. code:: python + + from cassandra.cluster import Cluster + from cassandra.policies import TokenAwarePolicy, RoundRobinPolicy + + cluster = Cluster(load_balancing_policy=TokenAwarePolicy(RoundRobinPolicy())) + + +New Cluster Helpers +------------------- + +* ``shard_aware_options`` + + Setting it to ``dict(disable=True)`` would disable the shard aware functionally, for cases favoring once connection per host (example, lots of processes connecting from one client host, generating a big load of connections + + Other option is to configure scylla by setting ``enable_shard_aware_drivers: false`` on scylla.yaml. + +.. code:: python + + from cassandra.cluster import Cluster + + cluster = Cluster(shard_aware_options=dict(disable=True)) + session = cluster.connect() + + assert not cluster.is_shard_aware(), "Shard aware should be disabled" + + # or just disable the shard aware port logic + cluster = Cluster(shard_aware_options=dict(disable_shardaware_port=True)) + session = cluster.connect() + +* ``cluster.is_shard_aware()`` + + New method available on ``Cluster`` allowing to check whether the remote cluster supports shard awareness (bool) + +.. code:: python + + from cassandra.cluster import Cluster + + cluster = Cluster() + session = cluster.connect() + + if cluster.is_shard_aware(): + print("connected to a scylla cluster") + +* ``cluster.shard_aware_stats()`` + + New method available on ``Cluster`` allowing to check the status of shard aware connections to all available hosts (dict) + +.. code:: python + + from cassandra.cluster import Cluster + + cluster = Cluster() + session = cluster.connect() + + stats = cluster.shard_aware_stats() + if all([v["shards_count"] == v["connected"] for v in stats.values()]): + print("successfully connected to all shards of all scylla nodes") + + +New Table Attributes +-------------------- + +* ``in_memory`` flag + + New flag available on ``TableMetadata.options`` to indicate that it is an `In Memory `_ table + +.. note:: in memory tables is a feature existing only in Scylla Enterprise + +.. code:: python + + from cassandra.cluster import Cluster + + cluster = Cluster() + session = cluster.connect() + session.execute(""" + CREATE KEYSPACE IF NOT EXISTS keyspace1 + WITH replication = {'class': 'SimpleStrategy', 'replication_factor': '1'}; + """) + + session.execute(""" + CREATE TABLE IF NOT EXISTS keyspace1.standard1 ( + key blob PRIMARY KEY, + "C0" blob + ) WITH in_memory=true AND compaction={'class': 'InMemoryCompactionStrategy'} + """) + + cluster.refresh_table_metadata("keyspace1", "standard1") + assert cluster.metadata.keyspaces["keyspace1"].tables["standard1"].options["in_memory"] == True diff --git a/3.25.11-scylla/_sources/security.rst.txt b/3.25.11-scylla/_sources/security.rst.txt new file mode 100644 index 0000000000..c30189562f --- /dev/null +++ b/3.25.11-scylla/_sources/security.rst.txt @@ -0,0 +1,421 @@ +.. _security: + +Security +======== +The two main security components you will use with the +Python driver are Authentication and SSL. + +Authentication +-------------- +Versions 2.0 and higher of the driver support a SASL-based +authentication mechanism when :attr:`~.Cluster.protocol_version` +is set to 2 or higher. To use this authentication, set +:attr:`~.Cluster.auth_provider` to an instance of a subclass +of :class:`~cassandra.auth.AuthProvider`. When working +with Cassandra's ``PasswordAuthenticator``, you can use +the :class:`~cassandra.auth.PlainTextAuthProvider` class. + +For example, suppose Cassandra is setup with its default +'cassandra' user with a password of 'cassandra': + +.. code-block:: python + + from cassandra.cluster import Cluster + from cassandra.auth import PlainTextAuthProvider + + auth_provider = PlainTextAuthProvider(username='cassandra', password='cassandra') + cluster = Cluster(auth_provider=auth_provider, protocol_version=2) + + + +Custom Authenticators +^^^^^^^^^^^^^^^^^^^^^ +If you're using something other than Cassandra's ``PasswordAuthenticator``, +:class:`~.SaslAuthProvider` is provided for generic SASL authentication mechanisms, +utilizing the ``pure-sasl`` package. +If these do not suit your needs, you may need to create your own subclasses of +:class:`~.AuthProvider` and :class:`~.Authenticator`. You can use the Sasl classes +as example implementations. + +Protocol v1 Authentication +^^^^^^^^^^^^^^^^^^^^^^^^^^ +When working with Cassandra 1.2 (or a higher version with +:attr:`~.Cluster.protocol_version` set to ``1``), you will not pass in +an :class:`~.AuthProvider` instance. Instead, you should pass in a +function that takes one argument, the IP address of a host, and returns +a dict of credentials with a ``username`` and ``password`` key: + +.. code-block:: python + + from cassandra.cluster import Cluster + + def get_credentials(host_address): + return {'username': 'joe', 'password': '1234'} + + cluster = Cluster(auth_provider=get_credentials, protocol_version=1) + +SSL +--- +SSL should be used when client encryption is enabled in Cassandra. + +To give you as much control as possible over your SSL configuration, our SSL +API takes a user-created `SSLContext` instance from the Python standard library. +These docs will include some examples for how to achieve common configurations, +but the `ssl.SSLContext `_ documentation +gives a more complete description of what is possible. + +To enable SSL with version 3.17.0 and higher, you will need to set :attr:`.Cluster.ssl_context` to a +``ssl.SSLContext`` instance to enable SSL. Optionally, you can also set :attr:`.Cluster.ssl_options` +to a dict of options. These will be passed as kwargs to ``ssl.SSLContext.wrap_socket()`` +when new sockets are created. + +If you create your SSLContext using `ssl.create_default_context `_, +be aware that SSLContext.check_hostname is set to True by default, so the hostname validation will be done +by Python and not the driver. For this reason, we need to set the server_hostname at best effort, which is the +resolved ip address. If this validation needs to be done against the FQDN, consider enabling it using the ssl_options +as described in the following examples or implement your own :class:`~.connection.EndPoint` and +:class:`~.connection.EndPointFactory`. + + +The following examples assume you have generated your Cassandra certificate and +keystore files with these intructions: + +* `Setup SSL Cert `_ + +It might be also useful to learn about the different levels of identity verification to understand the examples: + +* `Using SSL in DSE drivers `_ + +SSL with Twisted or Eventlet +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Twisted and Eventlet both use an alternative SSL implementation called pyOpenSSL, so if your `Cluster`'s connection class is +:class:`~cassandra.io.twistedreactor.TwistedConnection` or :class:`~cassandra.io.eventletreactor.EventletConnection`, you must pass a +`pyOpenSSL context `_ instead. +An example is provided in these docs, and more details can be found in the +`documentation `_. +pyOpenSSL is not installed by the driver and must be installed separately. + +SSL Configuration Examples +^^^^^^^^^^^^^^^^^^^^^^^^^^ +Here, we'll describe the server and driver configuration necessary to set up SSL to meet various goals, such as the client verifying the server and the server verifying the client. We'll also include Python code demonstrating how to use servers and drivers configured in these ways. + +.. _ssl-no-identify-verification: + +No identity verification +++++++++++++++++++++++++ + +No identity verification at all. Note that this is not recommended for for production deployments. + +The Cassandra configuration:: + + client_encryption_options: + enabled: true + keystore: /path/to/127.0.0.1.keystore + keystore_password: myStorePass + require_client_auth: false + +The driver configuration: + +.. code-block:: python + + from cassandra.cluster import Cluster, Session + from ssl import SSLContext, PROTOCOL_TLS + + ssl_context = SSLContext(PROTOCOL_TLS) + + cluster = Cluster(['127.0.0.1'], ssl_context=ssl_context) + session = cluster.connect() + +.. _ssl-client-verifies-server: + +Client verifies server +++++++++++++++++++++++ + +Ensure the python driver verifies the identity of the server. + +The Cassandra configuration:: + + client_encryption_options: + enabled: true + keystore: /path/to/127.0.0.1.keystore + keystore_password: myStorePass + require_client_auth: false + +For the driver configuration, it's very important to set `ssl_context.verify_mode` +to `CERT_REQUIRED`. Otherwise, the loaded verify certificate will have no effect: + +.. code-block:: python + + from cassandra.cluster import Cluster, Session + from ssl import SSLContext, PROTOCOL_TLS, CERT_REQUIRED + + ssl_context = SSLContext(PROTOCOL_TLS) + ssl_context.load_verify_locations('/path/to/rootca.crt') + ssl_context.verify_mode = CERT_REQUIRED + + cluster = Cluster(['127.0.0.1'], ssl_context=ssl_context) + session = cluster.connect() + +Additionally, you can also force the driver to verify the `hostname` of the server by passing additional options to `ssl_context.wrap_socket` via the `ssl_options` kwarg: + +.. code-block:: python + + from cassandra.cluster import Cluster, Session + from ssl import SSLContext, PROTOCOL_TLS, CERT_REQUIRED + + ssl_context = SSLContext(PROTOCOL_TLS) + ssl_context.load_verify_locations('/path/to/rootca.crt') + ssl_context.verify_mode = CERT_REQUIRED + ssl_context.check_hostname = True + ssl_options = {'server_hostname': '127.0.0.1'} + + cluster = Cluster(['127.0.0.1'], ssl_context=ssl_context, ssl_options=ssl_options) + session = cluster.connect() + +.. _ssl-server-verifies-client: + +Server verifies client +++++++++++++++++++++++ + +If Cassandra is configured to verify clients (``require_client_auth``), you need to generate +SSL key and certificate files. + +The cassandra configuration:: + + client_encryption_options: + enabled: true + keystore: /path/to/127.0.0.1.keystore + keystore_password: myStorePass + require_client_auth: true + truststore: /path/to/dse-truststore.jks + truststore_password: myStorePass + +The Python ``ssl`` APIs require the certificate in PEM format. First, create a certificate +conf file: + +.. code-block:: bash + + cat > gen_client_cert.conf <`__ +for more details about ``SSLContext`` configuration. + +**Server verifies client and client verifies server using Twisted and pyOpenSSL** + +.. code-block:: python + + from OpenSSL import SSL, crypto + from cassandra.cluster import Cluster + from cassandra.io.twistedreactor import TwistedConnection + + ssl_context = SSL.Context(SSL.TLSv1_2_METHOD) + ssl_context.set_verify(SSL.VERIFY_PEER, callback=lambda _1, _2, _3, _4, ok: ok) + ssl_context.use_certificate_file('/path/to/client.crt_signed') + ssl_context.use_privatekey_file('/path/to/client.key') + ssl_context.load_verify_locations('/path/to/rootca.crt') + + cluster = Cluster( + contact_points=['127.0.0.1'], + connection_class=TwistedConnection, + ssl_context=ssl_context, + ssl_options={'check_hostname': True} + ) + session = cluster.connect() + + +Connecting using Eventlet would look similar except instead of importing and using ``TwistedConnection``, you would +import and use ``EventletConnection``, including the appropriate monkey-patching. + +Versions 3.16.0 and lower +^^^^^^^^^^^^^^^^^^^^^^^^^ + +To enable SSL you will need to set :attr:`.Cluster.ssl_options` to a +dict of options. These will be passed as kwargs to ``ssl.wrap_socket()`` +when new sockets are created. Note that this use of ssl_options will be +deprecated in the next major release. + +By default, a ``ca_certs`` value should be supplied (the value should be +a string pointing to the location of the CA certs file), and you probably +want to specify ``ssl_version`` as ``ssl.PROTOCOL_TLS`` to match +Cassandra's default protocol. + +For example: + +.. code-block:: python + + from cassandra.cluster import Cluster + from ssl import PROTOCOL_TLS, CERT_REQUIRED + + ssl_opts = { + 'ca_certs': '/path/to/my/ca.certs', + 'ssl_version': PROTOCOL_TLS, + 'cert_reqs': CERT_REQUIRED # Certificates are required and validated + } + cluster = Cluster(ssl_options=ssl_opts) + +This is only an example to show how to pass the ssl parameters. Consider reading +the `python ssl documentation `__ for +your configuration. For further reading, Andrew Mussey has published a thorough guide on +`Using SSL with the DataStax Python driver `_. + +SSL with Twisted +++++++++++++++++ + +In case the twisted event loop is used pyOpenSSL must be installed or an exception will be risen. Also +to set the ``ssl_version`` and ``cert_reqs`` in ``ssl_opts`` the appropriate constants from pyOpenSSL are expected. + +DSE Authentication +------------------ +When authenticating against DSE, the Cassandra driver provides two auth providers that work both with legacy kerberos and Cassandra authenticators, +as well as the new DSE Unified Authentication. This allows client to configure this auth provider independently, +and in advance of any server upgrade. These auth providers are configured in the same way as any previous implementation:: + + from cassandra.auth import DSEGSSAPIAuthProvider + auth_provider = DSEGSSAPIAuthProvider(service='dse', qops=["auth"]) + cluster = Cluster(auth_provider=auth_provider) + session = cluster.connect() + +Implementations are :attr:`.DSEPlainTextAuthProvider`, :class:`.DSEGSSAPIAuthProvider` and :class:`.SaslAuthProvider`. + +DSE Unified Authentication +^^^^^^^^^^^^^^^^^^^^^^^^^^ + +With DSE (>=5.1), unified Authentication allows you to: + +* Proxy Login: Authenticate using a fixed set of authentication credentials but allow authorization of resources based another user id. +* Proxy Execute: Authenticate using a fixed set of authentication credentials but execute requests based on another user id. + +Proxy Login ++++++++++++ + +Proxy login allows you to authenticate with a user but act as another one. You need to ensure the authenticated user has the permission to use the authorization of resources of the other user. ie. this example will allow the `server` user to authenticate as usual but use the authorization of `user1`: + +.. code-block:: text + + GRANT PROXY.LOGIN on role user1 to server + +then you can do the proxy authentication.... + +.. code-block:: python + + from cassandra.cluster import Cluster + from cassandra.auth import SaslAuthProvider + + sasl_kwargs = { + "service": 'dse', + "mechanism":"PLAIN", + "username": 'server', + 'password': 'server', + 'authorization_id': 'user1' + } + + auth_provider = SaslAuthProvider(**sasl_kwargs) + c = Cluster(auth_provider=auth_provider) + s = c.connect() + s.execute(...) # all requests will be executed as 'user1' + +If you are using kerberos, you can use directly :class:`.DSEGSSAPIAuthProvider` and pass the authorization_id, like this: + +.. code-block:: python + + from cassandra.cluster import Cluster + from cassandra.auth import DSEGSSAPIAuthProvider + + # Ensure the kerberos ticket of the server user is set with the kinit utility. + auth_provider = DSEGSSAPIAuthProvider(service='dse', qops=["auth"], principal="server@DATASTAX.COM", + authorization_id='user1@DATASTAX.COM') + c = Cluster(auth_provider=auth_provider) + s = c.connect() + s.execute(...) # all requests will be executed as 'user1' + + +Proxy Execute ++++++++++++++ + +Proxy execute allows you to execute requests as another user than the authenticated one. You need to ensure the authenticated user has the permission to use the authorization of resources of the specified user. ie. this example will allow the `server` user to execute requests as `user1`: + +.. code-block:: text + + GRANT PROXY.EXECUTE on role user1 to server + +then you can do a proxy execute... + +.. code-block:: python + + from cassandra.cluster import Cluster + from cassandra.auth import DSEPlainTextAuthProvider, + + auth_provider = DSEPlainTextAuthProvider('server', 'server') + + c = Cluster(auth_provider=auth_provider) + s = c.connect() + s.execute('select * from k.t;', execute_as='user1') # the request will be executed as 'user1' + +Please see the `official documentation `_ for more details on the feature and configuration process. diff --git a/3.25.11-scylla/_sources/upgrading.rst.txt b/3.25.11-scylla/_sources/upgrading.rst.txt new file mode 100644 index 0000000000..9559fa3579 --- /dev/null +++ b/3.25.11-scylla/_sources/upgrading.rst.txt @@ -0,0 +1,388 @@ +Upgrading +========= + +.. toctree:: + :maxdepth: 1 + +Upgrading from dse-driver +------------------------- + +Since 3.21.0, scylla-driver fully supports DataStax products. dse-driver and +dse-graph users should now migrate to scylla-driver to benefit from latest bug fixes +and new features. The upgrade to this new unified driver version is straightforward +with no major API changes. + +Installation +^^^^^^^^^^^^ + +Only the `scylla-driver` package should be installed. `dse-driver` and `dse-graph` +are not required anymore:: + + pip install scylla-driver + +If you need the Graph *Fluent* API (features provided by dse-graph):: + + pip install scylla-driver[graph] + +See :doc:`installation` for more details. + +Import from the cassandra module +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +There is no `dse` module, so you should import from the `cassandra` module. You +need to change only the first module of your import statements, not the submodules. + +.. code-block:: python + + from dse.cluster import Cluster, EXEC_PROFILE_GRAPH_DEFAULT + from dse.auth import PlainTextAuthProvider + from dse.policies import WhiteListRoundRobinPolicy + + # becomes + + from cassandra.cluster import Cluster, EXEC_PROFILE_GRAPH_DEFAULT + from cassandra.auth import PlainTextAuthProvider + from cassandra.policies import WhiteListRoundRobinPolicy + +Also note that the cassandra.hosts module doesn't exist in scylla-driver. This +module is named cassandra.pool. + +dse-graph +^^^^^^^^^ + +dse-graph features are now built into scylla-driver. The only change you need +to do is your import statements: + +.. code-block:: python + + from dse_graph import .. + from dse_graph.query import .. + + # becomes + + from cassandra.datastax.graph.fluent import .. + from cassandra.datastax.graph.fluent.query import .. + +See :mod:`~.datastax.graph.fluent`. + +Session.execute and Session.execute_async API +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Although it is not common to use this API with positional arguments, it is +important to be aware that the `host` and `execute_as` parameters have had +their positional order swapped. This is only because `execute_as` was added +in dse-driver before `host`. + +See :meth:`.Session.execute`. + +Deprecations +^^^^^^^^^^^^ + +These changes are optional, but recommended: + +* Importing from `cassandra.graph` is deprecated. Consider importing from `cassandra.datastax.graph`. +* Use :class:`~.policies.DefaultLoadBalancingPolicy` instead of DSELoadBalancingPolicy. + +Upgrading to 3.0 +---------------- +Version 3.0 of the DataStax Python driver for Apache Cassandra +adds support for Cassandra 3.0 while maintaining support for +previously supported versions. In addition to substantial internal rework, +there are several updates to the API that integrators will need +to consider: + +Default consistency is now ``LOCAL_ONE`` +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Previous value was ``ONE``. The new value is introduced to mesh with the default +DC-aware load balancing policy and to match other drivers. + +Execution API Updates +^^^^^^^^^^^^^^^^^^^^^ +Result return normalization +~~~~~~~~~~~~~~~~~~~~~~~~~~~ +`PYTHON-368 `_ + +Previously results would be returned as a ``list`` of rows for result rows +up to ``fetch_size``, and ``PagedResult`` afterward. This could break +application code that assumed one type and got another. + +Now, all results are returned as an iterable :class:`~.ResultSet`. + +The preferred way to consume results of unknown size is to iterate through +them, letting automatic paging occur as they are consumed. + +.. code-block:: python + + results = session.execute("SELECT * FROM system.local") + for row in results: + process(row) + +If the expected size of the results is known, it is still possible to +materialize a list using the iterator: + +.. code-block:: python + + results = session.execute("SELECT * FROM system.local") + row_list = list(results) + +For backward compatibility, :class:`~.ResultSet` supports indexing. When +accessed at an index, a `~.ResultSet` object will materialize all its pages: + +.. code-block:: python + + results = session.execute("SELECT * FROM system.local") + first_result = results[0] # materializes results, fetching all pages + +This can send requests and load (possibly large) results into memory, so +`~.ResultSet` will log a warning on implicit materialization. + +Trace information is not attached to executed Statements +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +`PYTHON-318 `_ + +Previously trace data was attached to Statements if tracing was enabled. This +could lead to confusion if the same statement was used for multiple executions. + +Now, trace data is associated with the ``ResponseFuture`` and ``ResultSet`` +returned for each query: + +:meth:`.ResponseFuture.get_query_trace()` + +:meth:`.ResponseFuture.get_all_query_traces()` + +:meth:`.ResultSet.get_query_trace()` + +:meth:`.ResultSet.get_all_query_traces()` + +Binding named parameters now ignores extra names +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +`PYTHON-178 `_ + +Previously, :meth:`.BoundStatement.bind()` would raise if a mapping +was passed with extra names not found in the prepared statement. + +Behavior in 3.0+ is to ignore extra names. + +blist removed as soft dependency +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +`PYTHON-385 `_ + +Previously the driver had a soft dependency on ``blist sortedset``, using +that where available and using an internal fallback where possible. + +Now, the driver never chooses the ``blist`` variant, instead returning the +internal :class:`.util.SortedSet` for all ``set`` results. The class implements +all standard set operations, so no integration code should need to change unless +it explicitly checks for ``sortedset`` type. + +Metadata API Updates +^^^^^^^^^^^^^^^^^^^^ +`PYTHON-276 `_, `PYTHON-408 `_, `PYTHON-400 `_, `PYTHON-422 `_ + +Cassandra 3.0 brought a substantial overhaul to the internal schema metadata representation. +This version of the driver supports that metadata in addition to the legacy version. Doing so +also brought some changes to the metadata model. + +The present API is documented: :any:`cassandra.metadata`. Changes highlighted below: + +* All types are now exposed as CQL types instead of types derived from the internal server implementation +* Some metadata attributes have changed names to match current nomenclature (for example, :attr:`.Index.kind` in place of ``Index.type``). +* Some metadata attributes removed + + * ``TableMetadata.keyspace`` reference replaced with :attr:`.TableMetadata.keyspace_name` + * ``ColumnMetadata.index`` is removed table- and keyspace-level mappings are still maintained + +Several deprecated features are removed +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +`PYTHON-292 `_ + +* ``ResponseFuture.result`` timeout parameter is removed, use ``Session.execute`` timeout instead (`031ebb0 `_) +* ``Cluster.refresh_schema`` removed, use ``Cluster.refresh_*_metadata`` instead (`419fcdf `_) +* ``Cluster.submit_schema_refresh`` removed (`574266d `_) +* ``cqltypes`` time/date functions removed, use ``util`` entry points instead (`bb984ee `_) +* ``decoder`` module removed (`e16a073 `_) +* ``TableMetadata.keyspace`` attribute replaced with ``keyspace_name`` (`cc94073 `_) +* ``cqlengine.columns.TimeUUID.from_datetime`` removed, use ``util`` variant instead (`96489cc `_) +* ``cqlengine.columns.Float(double_precision)`` parameter removed, use ``columns.Double`` instead (`a2d3a98 `_) +* ``cqlengine`` keyspace management functions are removed in favor of the strategy-specific entry points (`4bd5909 `_) +* ``cqlengine.Model.__polymorphic_*__`` attributes removed, use ``__discriminator*`` attributes instead (`9d98c8e `_) +* ``cqlengine.statements`` will no longer warn about list list prepend behavior (`79efe97 `_) + + +Upgrading to 2.1 from 2.0 +------------------------- +Version 2.1 of the DataStax Python driver for Apache Cassandra +adds support for Cassandra 2.1 and version 3 of the native protocol. + +Cassandra 1.2, 2.0, and 2.1 are all supported. However, 1.2 only +supports protocol version 1, and 2.0 only supports versions 1 and +2, so some features may not be available. + +Using the v3 Native Protocol +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +By default, the driver will attempt to use version 2 of the +native protocol. To use version 3, you must explicitly +set the :attr:`~.Cluster.protocol_version`: + +.. code-block:: python + + from cassandra.cluster import Cluster + + cluster = Cluster(protocol_version=3) + +Note that protocol version 3 is only supported by Cassandra 2.1+. + +In future releases, the driver may default to using protocol version +3. + +Working with User-Defined Types +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Cassandra 2.1 introduced the ability to define new types:: + + USE KEYSPACE mykeyspace; + + CREATE TYPE address (street text, city text, zip int); + +The driver generally expects you to use instances of a specific +class to represent column values of this type. You can let the +driver know what class to use with :meth:`.Cluster.register_user_type`: + +.. code-block:: python + + cluster = Cluster() + + class Address(object): + + def __init__(self, street, city, zipcode): + self.street = street + self.city = text + self.zipcode = zipcode + + cluster.register_user_type('mykeyspace', 'address', Address) + +When inserting data for ``address`` columns, you should pass in +instances of ``Address``. When querying data, ``address`` column +values will be instances of ``Address``. + +If no class is registered for a user-defined type, query results +will use a ``namedtuple`` class and data may only be inserted +though prepared statements. + +See :ref:`udts` for more details. + +Customizing Encoders for Non-prepared Statements +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Starting with version 2.1 of the driver, it is possible to customize +how Python types are converted to CQL literals when working with +non-prepared statements. This is done on a per-:class:`~.Session` +basis through :attr:`.Session.encoder`: + +.. code-block:: python + + cluster = Cluster() + session = cluster.connect() + session.encoder.mapping[tuple] = session.encoder.cql_encode_tuple + +See :ref:`type-conversions` for the table of default CQL literal conversions. + +Using Client-Side Protocol-Level Timestamps +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +With version 3 of the native protocol, timestamps may be supplied by the +client at the protocol level. (Normally, if they are not specified within +the CQL query itself, a timestamp is generated server-side.) + +When :attr:`~.Cluster.protocol_version` is set to 3 or higher, the driver +will automatically use client-side timestamps with microsecond precision +unless :attr:`.Session.use_client_timestamp` is changed to :const:`False`. +If a timestamp is specified within the CQL query, it will override the +timestamp generated by the driver. + +Upgrading to 2.0 from 1.x +------------------------- +Version 2.0 of the DataStax Python driver for Apache Cassandra +includes some notable improvements over version 1.x. This version +of the driver supports Cassandra 1.2, 2.0, and 2.1. However, not +all features may be used with Cassandra 1.2, and some new features +in 2.1 are not yet supported. + +Using the v2 Native Protocol +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +By default, the driver will attempt to use version 2 of Cassandra's +native protocol. You can explicitly set the protocol version to +2, though: + +.. code-block:: python + + from cassandra.cluster import Cluster + + cluster = Cluster(protocol_version=2) + +When working with Cassandra 1.2, you will need to +explicitly set the :attr:`~.Cluster.protocol_version` to 1: + +.. code-block:: python + + from cassandra.cluster import Cluster + + cluster = Cluster(protocol_version=1) + +Automatic Query Paging +^^^^^^^^^^^^^^^^^^^^^^ +Version 2 of the native protocol adds support for automatic query +paging, which can make dealing with large result sets much simpler. + +See :ref:`query-paging` for full details. + +Protocol-Level Batch Statements +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +With version 1 of the native protocol, batching of statements required +using a `BATCH cql query `_. +With version 2 of the native protocol, you can now batch statements at +the protocol level. This allows you to use many different prepared +statements within a single batch. + +See :class:`~.query.BatchStatement` for details and usage examples. + +SASL-based Authentication +^^^^^^^^^^^^^^^^^^^^^^^^^ +Also new in version 2 of the native protocol is SASL-based authentication. +See the section on :ref:`security` for details and examples. + +Lightweight Transactions +^^^^^^^^^^^^^^^^^^^^^^^^ +`Lightweight transactions `_ are another new feature. To use lightweight transactions, add ``IF`` clauses +to your CQL queries and set the :attr:`~.Statement.serial_consistency_level` +on your statements. + +Calling Cluster.shutdown() +^^^^^^^^^^^^^^^^^^^^^^^^^^ +In order to fix some issues around garbage collection and unclean interpreter +shutdowns, version 2.0 of the driver requires you to call :meth:`.Cluster.shutdown()` +on your :class:`~.Cluster` objects when you are through with them. +This helps to guarantee a clean shutdown. + +Deprecations +^^^^^^^^^^^^ +The following functions have moved from ``cassandra.decoder`` to ``cassandra.query``. +The original functions have been left in place with a :exc:`DeprecationWarning` for +now: + +* :attr:`cassandra.decoder.tuple_factory` has moved to + :attr:`cassandra.query.tuple_factory` +* :attr:`cassandra.decoder.named_tuple_factory` has moved to + :attr:`cassandra.query.named_tuple_factory` +* :attr:`cassandra.decoder.dict_factory` has moved to + :attr:`cassandra.query.dict_factory` +* :attr:`cassandra.decoder.ordered_dict_factory` has moved to + :attr:`cassandra.query.ordered_dict_factory` + +Dependency Changes +^^^^^^^^^^^^^^^^^^ +The following dependencies have officially been made optional: + +* ``scales`` +* ``blist`` + +And one new dependency has been added (to enable Python 3 support): + +* ``six`` diff --git a/3.25.11-scylla/_sources/user_defined_types.rst.txt b/3.25.11-scylla/_sources/user_defined_types.rst.txt new file mode 100644 index 0000000000..32c03e37e8 --- /dev/null +++ b/3.25.11-scylla/_sources/user_defined_types.rst.txt @@ -0,0 +1,118 @@ +.. _udts: + +User Defined Types +================== +Cassandra 2.1 introduced user-defined types (UDTs). You can create a +new type through ``CREATE TYPE`` statements in CQL:: + + CREATE TYPE address (street text, zip int); + +Version 2.1 of the Python driver adds support for user-defined types. + +Registering a UDT +----------------- +You can tell the Python driver to return columns of a specific UDT as +instances of a class or a dict by registering them with your :class:`~.Cluster` +instance through :meth:`.Cluster.register_user_type`: + + +Map a Class to a UDT +++++++++++++++++++++ + +.. code-block:: python + + cluster = Cluster(protocol_version=3) + session = cluster.connect() + session.set_keyspace('mykeyspace') + session.execute("CREATE TYPE address (street text, zipcode int)") + session.execute("CREATE TABLE users (id int PRIMARY KEY, location frozen
)") + + # create a class to map to the "address" UDT + class Address(object): + + def __init__(self, street, zipcode): + self.street = street + self.zipcode = zipcode + + cluster.register_user_type('mykeyspace', 'address', Address) + + # insert a row using an instance of Address + session.execute("INSERT INTO users (id, location) VALUES (%s, %s)", + (0, Address("123 Main St.", 78723))) + + # results will include Address instances + results = session.execute("SELECT * FROM users") + row = results[0] + print(row.id, row.location.street, row.location.zipcode) + +Map a dict to a UDT ++++++++++++++++++++ + +.. code-block:: python + + cluster = Cluster(protocol_version=3) + session = cluster.connect() + session.set_keyspace('mykeyspace') + session.execute("CREATE TYPE address (street text, zipcode int)") + session.execute("CREATE TABLE users (id int PRIMARY KEY, location frozen
)") + + cluster.register_user_type('mykeyspace', 'address', dict) + + # insert a row using a prepared statement and a tuple + insert_statement = session.prepare("INSERT INTO mykeyspace.users (id, location) VALUES (?, ?)") + session.execute(insert_statement, [0, ("123 Main St.", 78723)]) + + # results will include dict instances + results = session.execute("SELECT * FROM users") + row = results[0] + print(row.id, row.location['street'], row.location['zipcode']) + +Using UDTs Without Registering Them +----------------------------------- +Although it is recommended to register your types with +:meth:`.Cluster.register_user_type`, the driver gives you some options +for working with unregistered UDTS. + +When you use prepared statements, the driver knows what data types to +expect for each placeholder. This allows you to pass any object you +want for a UDT, as long as it has attributes that match the field names +for the UDT: + +.. code-block:: python + + cluster = Cluster(protocol_version=3) + session = cluster.connect() + session.set_keyspace('mykeyspace') + session.execute("CREATE TYPE address (street text, zipcode int)") + session.execute("CREATE TABLE users (id int PRIMARY KEY, location frozen
)") + + class Foo(object): + + def __init__(self, street, zipcode, otherstuff): + self.street = street + self.zipcode = zipcode + self.otherstuff = otherstuff + + insert_statement = session.prepare("INSERT INTO users (id, location) VALUES (?, ?)") + + # since we're using a prepared statement, we don't *have* to register + # a class to map to the UDT to insert data. The object just needs to have + # "street" and "zipcode" attributes (which Foo does): + session.execute(insert_statement, [0, Foo("123 Main St.", 78723, "some other stuff")]) + + # when we query data, UDT columns that don't have a class registered + # will be returned as namedtuples: + results = session.execute("SELECT * FROM users") + first_row = results[0] + address = first_row.location + print(address) # prints "Address(street='123 Main St.', zipcode=78723)" + street = address.street + zipcode = address.street + +As shown in the code example, inserting data for UDT columns without registering +a class works fine for prepared statements. However, **you must register a +class to insert UDT columns with unprepared statements**.\* You can still query +UDT columns without registered classes using unprepared statements, they will +simply return ``namedtuple`` instances (just like prepared statements do). + +\* this applies to *parameterized* unprepared statements, in which the driver will be formatting parameters -- not statements with interpolated UDT literals. diff --git a/3.25.11-scylla/_static/basic.css b/3.25.11-scylla/_static/basic.css new file mode 100644 index 0000000000..603f6a8798 --- /dev/null +++ b/3.25.11-scylla/_static/basic.css @@ -0,0 +1,905 @@ +/* + * basic.css + * ~~~~~~~~~ + * + * Sphinx stylesheet -- basic theme. + * + * :copyright: Copyright 2007-2021 by the Sphinx team, see AUTHORS. + * :license: BSD, see LICENSE for details. + * + */ + +/* -- main layout ----------------------------------------------------------- */ + +div.clearer { + clear: both; +} + +div.section::after { + display: block; + content: ''; + clear: left; +} + +/* -- relbar ---------------------------------------------------------------- */ + +div.related { + width: 100%; + font-size: 90%; +} + +div.related h3 { + display: none; +} + +div.related ul { + margin: 0; + padding: 0 0 0 10px; + list-style: none; +} + +div.related li { + display: inline; +} + +div.related li.right { + float: right; + margin-right: 5px; +} + +/* -- sidebar --------------------------------------------------------------- */ + +div.sphinxsidebarwrapper { + padding: 10px 5px 0 10px; +} + +div.sphinxsidebar { + float: left; + width: 230px; + margin-left: -100%; + font-size: 90%; + word-wrap: break-word; + overflow-wrap : break-word; +} + +div.sphinxsidebar ul { + list-style: none; +} + +div.sphinxsidebar ul ul, +div.sphinxsidebar ul.want-points { + margin-left: 20px; + list-style: square; +} + +div.sphinxsidebar ul ul { + margin-top: 0; + margin-bottom: 0; +} + +div.sphinxsidebar form { + margin-top: 10px; +} + +div.sphinxsidebar input { + border: 1px solid #98dbcc; + font-family: sans-serif; + font-size: 1em; +} + +div.sphinxsidebar #searchbox form.search { + overflow: hidden; +} + +div.sphinxsidebar #searchbox input[type="text"] { + float: left; + width: 80%; + padding: 0.25em; + box-sizing: border-box; +} + +div.sphinxsidebar #searchbox input[type="submit"] { + float: left; + width: 20%; + border-left: none; + padding: 0.25em; + box-sizing: border-box; +} + + +img { + border: 0; + max-width: 100%; +} + +/* -- search page ----------------------------------------------------------- */ + +ul.search { + margin: 10px 0 0 20px; + padding: 0; +} + +ul.search li { + padding: 5px 0 5px 20px; + background-image: url(file.png); + background-repeat: no-repeat; + background-position: 0 7px; +} + +ul.search li a { + font-weight: bold; +} + +ul.search li p.context { + color: #888; + margin: 2px 0 0 30px; + text-align: left; +} + +ul.keywordmatches li.goodmatch a { + font-weight: bold; +} + +/* -- index page ------------------------------------------------------------ */ + +table.contentstable { + width: 90%; + margin-left: auto; + margin-right: auto; +} + +table.contentstable p.biglink { + line-height: 150%; +} + +a.biglink { + font-size: 1.3em; +} + +span.linkdescr { + font-style: italic; + padding-top: 5px; + font-size: 90%; +} + +/* -- general index --------------------------------------------------------- */ + +table.indextable { + width: 100%; +} + +table.indextable td { + text-align: left; + vertical-align: top; +} + +table.indextable ul { + margin-top: 0; + margin-bottom: 0; + list-style-type: none; +} + +table.indextable > tbody > tr > td > ul { + padding-left: 0em; +} + +table.indextable tr.pcap { + height: 10px; +} + +table.indextable tr.cap { + margin-top: 10px; + background-color: #f2f2f2; +} + +img.toggler { + margin-right: 3px; + margin-top: 3px; + cursor: pointer; +} + +div.modindex-jumpbox { + border-top: 1px solid #ddd; + border-bottom: 1px solid #ddd; + margin: 1em 0 1em 0; + padding: 0.4em; +} + +div.genindex-jumpbox { + border-top: 1px solid #ddd; + border-bottom: 1px solid #ddd; + margin: 1em 0 1em 0; + padding: 0.4em; +} + +/* -- domain module index --------------------------------------------------- */ + +table.modindextable td { + padding: 2px; + border-collapse: collapse; +} + +/* -- general body styles --------------------------------------------------- */ + +div.body { + min-width: 450px; + max-width: 800px; +} + +div.body p, div.body dd, div.body li, div.body blockquote { + -moz-hyphens: auto; + -ms-hyphens: auto; + -webkit-hyphens: auto; + hyphens: auto; +} + +a.headerlink { + visibility: hidden; +} + +a.brackets:before, +span.brackets > a:before{ + content: "["; +} + +a.brackets:after, +span.brackets > a:after { + content: "]"; +} + +h1:hover > a.headerlink, +h2:hover > a.headerlink, +h3:hover > a.headerlink, +h4:hover > a.headerlink, +h5:hover > a.headerlink, +h6:hover > a.headerlink, +dt:hover > a.headerlink, +caption:hover > a.headerlink, +p.caption:hover > a.headerlink, +div.code-block-caption:hover > a.headerlink { + visibility: visible; +} + +div.body p.caption { + text-align: inherit; +} + +div.body td { + text-align: left; +} + +.first { + margin-top: 0 !important; +} + +p.rubric { + margin-top: 30px; + font-weight: bold; +} + +img.align-left, figure.align-left, .figure.align-left, object.align-left { + clear: left; + float: left; + margin-right: 1em; +} + +img.align-right, figure.align-right, .figure.align-right, object.align-right { + clear: right; + float: right; + margin-left: 1em; +} + +img.align-center, figure.align-center, .figure.align-center, object.align-center { + display: block; + margin-left: auto; + margin-right: auto; +} + +img.align-default, figure.align-default, .figure.align-default { + display: block; + margin-left: auto; + margin-right: auto; +} + +.align-left { + text-align: left; +} + +.align-center { + text-align: center; +} + +.align-default { + text-align: center; +} + +.align-right { + text-align: right; +} + +/* -- sidebars -------------------------------------------------------------- */ + +div.sidebar, +aside.sidebar { + margin: 0 0 0.5em 1em; + border: 1px solid #ddb; + padding: 7px; + background-color: #ffe; + width: 40%; + float: right; + clear: right; + overflow-x: auto; +} + +p.sidebar-title { + font-weight: bold; +} + +div.admonition, div.topic, blockquote { + clear: left; +} + +/* -- topics ---------------------------------------------------------------- */ + +div.topic { + border: 1px solid #ccc; + padding: 7px; + margin: 10px 0 10px 0; +} + +p.topic-title { + font-size: 1.1em; + font-weight: bold; + margin-top: 10px; +} + +/* -- admonitions ----------------------------------------------------------- */ + +div.admonition { + margin-top: 10px; + margin-bottom: 10px; + padding: 7px; +} + +div.admonition dt { + font-weight: bold; +} + +p.admonition-title { + margin: 0px 10px 5px 0px; + font-weight: bold; +} + +div.body p.centered { + text-align: center; + margin-top: 25px; +} + +/* -- content of sidebars/topics/admonitions -------------------------------- */ + +div.sidebar > :last-child, +aside.sidebar > :last-child, +div.topic > :last-child, +div.admonition > :last-child { + margin-bottom: 0; +} + +div.sidebar::after, +aside.sidebar::after, +div.topic::after, +div.admonition::after, +blockquote::after { + display: block; + content: ''; + clear: both; +} + +/* -- tables ---------------------------------------------------------------- */ + +table.docutils { + margin-top: 10px; + margin-bottom: 10px; + border: 0; + border-collapse: collapse; +} + +table.align-center { + margin-left: auto; + margin-right: auto; +} + +table.align-default { + margin-left: auto; + margin-right: auto; +} + +table caption span.caption-number { + font-style: italic; +} + +table caption span.caption-text { +} + +table.docutils td, table.docutils th { + padding: 1px 8px 1px 5px; + border-top: 0; + border-left: 0; + border-right: 0; + border-bottom: 1px solid #aaa; +} + +table.footnote td, table.footnote th { + border: 0 !important; +} + +th { + text-align: left; + padding-right: 5px; +} + +table.citation { + border-left: solid 1px gray; + margin-left: 1px; +} + +table.citation td { + border-bottom: none; +} + +th > :first-child, +td > :first-child { + margin-top: 0px; +} + +th > :last-child, +td > :last-child { + margin-bottom: 0px; +} + +/* -- figures --------------------------------------------------------------- */ + +div.figure, figure { + margin: 0.5em; + padding: 0.5em; +} + +div.figure p.caption, figcaption { + padding: 0.3em; +} + +div.figure p.caption span.caption-number, +figcaption span.caption-number { + font-style: italic; +} + +div.figure p.caption span.caption-text, +figcaption span.caption-text { +} + +/* -- field list styles ----------------------------------------------------- */ + +table.field-list td, table.field-list th { + border: 0 !important; +} + +.field-list ul { + margin: 0; + padding-left: 1em; +} + +.field-list p { + margin: 0; +} + +.field-name { + -moz-hyphens: manual; + -ms-hyphens: manual; + -webkit-hyphens: manual; + hyphens: manual; +} + +/* -- hlist styles ---------------------------------------------------------- */ + +table.hlist { + margin: 1em 0; +} + +table.hlist td { + vertical-align: top; +} + +/* -- object description styles --------------------------------------------- */ + +.sig { + font-family: 'Consolas', 'Menlo', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace; +} + +.sig-name, code.descname { + background-color: transparent; + font-weight: bold; +} + +.sig-name { + font-size: 1.1em; +} + +code.descname { + font-size: 1.2em; +} + +.sig-prename, code.descclassname { + background-color: transparent; +} + +.optional { + font-size: 1.3em; +} + +.sig-paren { + font-size: larger; +} + +.sig-param.n { + font-style: italic; +} + +/* C++ specific styling */ + +.sig-inline.c-texpr, +.sig-inline.cpp-texpr { + font-family: unset; +} + +.sig.c .k, .sig.c .kt, +.sig.cpp .k, .sig.cpp .kt { + color: #0033B3; +} + +.sig.c .m, +.sig.cpp .m { + color: #1750EB; +} + +.sig.c .s, .sig.c .sc, +.sig.cpp .s, .sig.cpp .sc { + color: #067D17; +} + + +/* -- other body styles ----------------------------------------------------- */ + +ol.arabic { + list-style: decimal; +} + +ol.loweralpha { + list-style: lower-alpha; +} + +ol.upperalpha { + list-style: upper-alpha; +} + +ol.lowerroman { + list-style: lower-roman; +} + +ol.upperroman { + list-style: upper-roman; +} + +:not(li) > ol > li:first-child > :first-child, +:not(li) > ul > li:first-child > :first-child { + margin-top: 0px; +} + +:not(li) > ol > li:last-child > :last-child, +:not(li) > ul > li:last-child > :last-child { + margin-bottom: 0px; +} + +ol.simple ol p, +ol.simple ul p, +ul.simple ol p, +ul.simple ul p { + margin-top: 0; +} + +ol.simple > li:not(:first-child) > p, +ul.simple > li:not(:first-child) > p { + margin-top: 0; +} + +ol.simple p, +ul.simple p { + margin-bottom: 0; +} + +dl.footnote > dt, +dl.citation > dt { + float: left; + margin-right: 0.5em; +} + +dl.footnote > dd, +dl.citation > dd { + margin-bottom: 0em; +} + +dl.footnote > dd:after, +dl.citation > dd:after { + content: ""; + clear: both; +} + +dl.field-list { + display: grid; + grid-template-columns: fit-content(30%) auto; +} + +dl.field-list > dt { + font-weight: bold; + word-break: break-word; + padding-left: 0.5em; + padding-right: 5px; +} + +dl.field-list > dt:after { + content: ":"; +} + +dl.field-list > dd { + padding-left: 0.5em; + margin-top: 0em; + margin-left: 0em; + margin-bottom: 0em; +} + +dl { + margin-bottom: 15px; +} + +dd > :first-child { + margin-top: 0px; +} + +dd ul, dd table { + margin-bottom: 10px; +} + +dd { + margin-top: 3px; + margin-bottom: 10px; + margin-left: 30px; +} + +dl > dd:last-child, +dl > dd:last-child > :last-child { + margin-bottom: 0; +} + +dt:target, span.highlighted { + background-color: #fbe54e; +} + +rect.highlighted { + fill: #fbe54e; +} + +dl.glossary dt { + font-weight: bold; + font-size: 1.1em; +} + +.versionmodified { + font-style: italic; +} + +.system-message { + background-color: #fda; + padding: 5px; + border: 3px solid red; +} + +.footnote:target { + background-color: #ffa; +} + +.line-block { + display: block; + margin-top: 1em; + margin-bottom: 1em; +} + +.line-block .line-block { + margin-top: 0; + margin-bottom: 0; + margin-left: 1.5em; +} + +.guilabel, .menuselection { + font-family: sans-serif; +} + +.accelerator { + text-decoration: underline; +} + +.classifier { + font-style: oblique; +} + +.classifier:before { + font-style: normal; + margin: 0 0.5em; + content: ":"; + display: inline-block; +} + +abbr, acronym { + border-bottom: dotted 1px; + cursor: help; +} + +/* -- code displays --------------------------------------------------------- */ + +pre { + overflow: auto; + overflow-y: hidden; /* fixes display issues on Chrome browsers */ +} + +pre, div[class*="highlight-"] { + clear: both; +} + +span.pre { + -moz-hyphens: none; + -ms-hyphens: none; + -webkit-hyphens: none; + hyphens: none; +} + +div[class*="highlight-"] { + margin: 1em 0; +} + +td.linenos pre { + border: 0; + background-color: transparent; + color: #aaa; +} + +table.highlighttable { + display: block; +} + +table.highlighttable tbody { + display: block; +} + +table.highlighttable tr { + display: flex; +} + +table.highlighttable td { + margin: 0; + padding: 0; +} + +table.highlighttable td.linenos { + padding-right: 0.5em; +} + +table.highlighttable td.code { + flex: 1; + overflow: hidden; +} + +.highlight .hll { + display: block; +} + +div.highlight pre, +table.highlighttable pre { + margin: 0; +} + +div.code-block-caption + div { + margin-top: 0; +} + +div.code-block-caption { + margin-top: 1em; + padding: 2px 5px; + font-size: small; +} + +div.code-block-caption code { + background-color: transparent; +} + +table.highlighttable td.linenos, +span.linenos, +div.highlight span.gp { /* gp: Generic.Prompt */ + user-select: none; + -webkit-user-select: text; /* Safari fallback only */ + -webkit-user-select: none; /* Chrome/Safari */ + -moz-user-select: none; /* Firefox */ + -ms-user-select: none; /* IE10+ */ +} + +div.code-block-caption span.caption-number { + padding: 0.1em 0.3em; + font-style: italic; +} + +div.code-block-caption span.caption-text { +} + +div.literal-block-wrapper { + margin: 1em 0; +} + +code.xref, a code { + background-color: transparent; + font-weight: bold; +} + +h1 code, h2 code, h3 code, h4 code, h5 code, h6 code { + background-color: transparent; +} + +.viewcode-link { + float: right; +} + +.viewcode-back { + float: right; + font-family: sans-serif; +} + +div.viewcode-block:target { + margin: -1px -10px; + padding: 0 10px; +} + +/* -- math display ---------------------------------------------------------- */ + +img.math { + vertical-align: middle; +} + +div.body div.math p { + text-align: center; +} + +span.eqno { + float: right; +} + +span.eqno a.headerlink { + position: absolute; + z-index: 1; +} + +div.math:hover a.headerlink { + visibility: visible; +} + +/* -- printout stylesheet --------------------------------------------------- */ + +@media print { + div.document, + div.documentwrapper, + div.bodywrapper { + margin: 0 !important; + width: 100%; + } + + div.sphinxsidebar, + div.related, + div.footer, + #top-link { + display: none; + } +} \ No newline at end of file diff --git a/3.25.11-scylla/_static/check-solid.svg b/3.25.11-scylla/_static/check-solid.svg new file mode 100644 index 0000000000..92fad4b5c0 --- /dev/null +++ b/3.25.11-scylla/_static/check-solid.svg @@ -0,0 +1,4 @@ + + + + diff --git a/3.25.11-scylla/_static/clipboard.min.js b/3.25.11-scylla/_static/clipboard.min.js new file mode 100644 index 0000000000..54b3c46381 --- /dev/null +++ b/3.25.11-scylla/_static/clipboard.min.js @@ -0,0 +1,7 @@ +/*! + * clipboard.js v2.0.8 + * https://clipboardjs.com/ + * + * Licensed MIT © Zeno Rocha + */ +!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?exports.ClipboardJS=e():t.ClipboardJS=e()}(this,function(){return n={686:function(t,e,n){"use strict";n.d(e,{default:function(){return o}});var e=n(279),i=n.n(e),e=n(370),u=n.n(e),e=n(817),c=n.n(e);function a(t){try{return document.execCommand(t)}catch(t){return}}var f=function(t){t=c()(t);return a("cut"),t};var l=function(t){var e,n,o,r=1 + + + + diff --git a/3.25.11-scylla/_static/copybutton.css b/3.25.11-scylla/_static/copybutton.css new file mode 100644 index 0000000000..f1916ec7d1 --- /dev/null +++ b/3.25.11-scylla/_static/copybutton.css @@ -0,0 +1,94 @@ +/* Copy buttons */ +button.copybtn { + position: absolute; + display: flex; + top: .3em; + right: .3em; + width: 1.7em; + height: 1.7em; + opacity: 0; + transition: opacity 0.3s, border .3s, background-color .3s; + user-select: none; + padding: 0; + border: none; + outline: none; + border-radius: 0.4em; + /* The colors that GitHub uses */ + border: #1b1f2426 1px solid; + background-color: #f6f8fa; + color: #57606a; +} + +button.copybtn.success { + border-color: #22863a; + color: #22863a; +} + +button.copybtn svg { + stroke: currentColor; + width: 1.5em; + height: 1.5em; + padding: 0.1em; +} + +div.highlight { + position: relative; +} + +/* Show the copybutton */ +.highlight:hover button.copybtn, button.copybtn.success { + opacity: 1; +} + +.highlight button.copybtn:hover { + background-color: rgb(235, 235, 235); +} + +.highlight button.copybtn:active { + background-color: rgb(187, 187, 187); +} + +/** + * A minimal CSS-only tooltip copied from: + * https://codepen.io/mildrenben/pen/rVBrpK + * + * To use, write HTML like the following: + * + *

Short

+ */ + .o-tooltip--left { + position: relative; + } + + .o-tooltip--left:after { + opacity: 0; + visibility: hidden; + position: absolute; + content: attr(data-tooltip); + padding: .2em; + font-size: .8em; + left: -.2em; + background: grey; + color: white; + white-space: nowrap; + z-index: 2; + border-radius: 2px; + transform: translateX(-102%) translateY(0); + transition: opacity 0.2s cubic-bezier(0.64, 0.09, 0.08, 1), transform 0.2s cubic-bezier(0.64, 0.09, 0.08, 1); +} + +.o-tooltip--left:hover:after { + display: block; + opacity: 1; + visibility: visible; + transform: translateX(-100%) translateY(0); + transition: opacity 0.2s cubic-bezier(0.64, 0.09, 0.08, 1), transform 0.2s cubic-bezier(0.64, 0.09, 0.08, 1); + transition-delay: .5s; +} + +/* By default the copy button shouldn't show up when printing a page */ +@media print { + button.copybtn { + display: none; + } +} diff --git a/3.25.11-scylla/_static/copybutton.js b/3.25.11-scylla/_static/copybutton.js new file mode 100644 index 0000000000..2ea7ff3e21 --- /dev/null +++ b/3.25.11-scylla/_static/copybutton.js @@ -0,0 +1,248 @@ +// Localization support +const messages = { + 'en': { + 'copy': 'Copy', + 'copy_to_clipboard': 'Copy to clipboard', + 'copy_success': 'Copied!', + 'copy_failure': 'Failed to copy', + }, + 'es' : { + 'copy': 'Copiar', + 'copy_to_clipboard': 'Copiar al portapapeles', + 'copy_success': '¡Copiado!', + 'copy_failure': 'Error al copiar', + }, + 'de' : { + 'copy': 'Kopieren', + 'copy_to_clipboard': 'In die Zwischenablage kopieren', + 'copy_success': 'Kopiert!', + 'copy_failure': 'Fehler beim Kopieren', + }, + 'fr' : { + 'copy': 'Copier', + 'copy_to_clipboard': 'Copier dans le presse-papier', + 'copy_success': 'Copié !', + 'copy_failure': 'Échec de la copie', + }, + 'ru': { + 'copy': 'Скопировать', + 'copy_to_clipboard': 'Скопировать в буфер', + 'copy_success': 'Скопировано!', + 'copy_failure': 'Не удалось скопировать', + }, + 'zh-CN': { + 'copy': '复制', + 'copy_to_clipboard': '复制到剪贴板', + 'copy_success': '复制成功!', + 'copy_failure': '复制失败', + }, + 'it' : { + 'copy': 'Copiare', + 'copy_to_clipboard': 'Copiato negli appunti', + 'copy_success': 'Copiato!', + 'copy_failure': 'Errore durante la copia', + } +} + +let locale = 'en' +if( document.documentElement.lang !== undefined + && messages[document.documentElement.lang] !== undefined ) { + locale = document.documentElement.lang +} + +let doc_url_root = DOCUMENTATION_OPTIONS.URL_ROOT; +if (doc_url_root == '#') { + doc_url_root = ''; +} + +/** + * SVG files for our copy buttons + */ +let iconCheck = ` + ${messages[locale]['copy_success']} + + +` + +// If the user specified their own SVG use that, otherwise use the default +let iconCopy = ``; +if (!iconCopy) { + iconCopy = ` + ${messages[locale]['copy_to_clipboard']} + + + +` +} + +/** + * Set up copy/paste for code blocks + */ + +const runWhenDOMLoaded = cb => { + if (document.readyState != 'loading') { + cb() + } else if (document.addEventListener) { + document.addEventListener('DOMContentLoaded', cb) + } else { + document.attachEvent('onreadystatechange', function() { + if (document.readyState == 'complete') cb() + }) + } +} + +const codeCellId = index => `codecell${index}` + +// Clears selected text since ClipboardJS will select the text when copying +const clearSelection = () => { + if (window.getSelection) { + window.getSelection().removeAllRanges() + } else if (document.selection) { + document.selection.empty() + } +} + +// Changes tooltip text for a moment, then changes it back +// We want the timeout of our `success` class to be a bit shorter than the +// tooltip and icon change, so that we can hide the icon before changing back. +var timeoutIcon = 2000; +var timeoutSuccessClass = 1500; + +const temporarilyChangeTooltip = (el, oldText, newText) => { + el.setAttribute('data-tooltip', newText) + el.classList.add('success') + // Remove success a little bit sooner than we change the tooltip + // So that we can use CSS to hide the copybutton first + setTimeout(() => el.classList.remove('success'), timeoutSuccessClass) + setTimeout(() => el.setAttribute('data-tooltip', oldText), timeoutIcon) +} + +// Changes the copy button icon for two seconds, then changes it back +const temporarilyChangeIcon = (el) => { + el.innerHTML = iconCheck; + setTimeout(() => {el.innerHTML = iconCopy}, timeoutIcon) +} + +const addCopyButtonToCodeCells = () => { + // If ClipboardJS hasn't loaded, wait a bit and try again. This + // happens because we load ClipboardJS asynchronously. + if (window.ClipboardJS === undefined) { + setTimeout(addCopyButtonToCodeCells, 250) + return + } + + // Add copybuttons to all of our code cells + const COPYBUTTON_SELECTOR = 'div.highlight pre'; + const codeCells = document.querySelectorAll(COPYBUTTON_SELECTOR) + codeCells.forEach((codeCell, index) => { + const id = codeCellId(index) + codeCell.setAttribute('id', id) + + const clipboardButton = id => + `` + codeCell.insertAdjacentHTML('afterend', clipboardButton(id)) + }) + +function escapeRegExp(string) { + return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string +} + +/** + * Removes excluded text from a Node. + * + * @param {Node} target Node to filter. + * @param {string} exclude CSS selector of nodes to exclude. + * @returns {DOMString} Text from `target` with text removed. + */ +function filterText(target, exclude) { + const clone = target.cloneNode(true); // clone as to not modify the live DOM + if (exclude) { + // remove excluded nodes + clone.querySelectorAll(exclude).forEach(node => node.remove()); + } + return clone.innerText; +} + +// Callback when a copy button is clicked. Will be passed the node that was clicked +// should then grab the text and replace pieces of text that shouldn't be used in output +function formatCopyText(textContent, copybuttonPromptText, isRegexp = false, onlyCopyPromptLines = true, removePrompts = true, copyEmptyLines = true, lineContinuationChar = "", hereDocDelim = "") { + var regexp; + var match; + + // Do we check for line continuation characters and "HERE-documents"? + var useLineCont = !!lineContinuationChar + var useHereDoc = !!hereDocDelim + + // create regexp to capture prompt and remaining line + if (isRegexp) { + regexp = new RegExp('^(' + copybuttonPromptText + ')(.*)') + } else { + regexp = new RegExp('^(' + escapeRegExp(copybuttonPromptText) + ')(.*)') + } + + const outputLines = []; + var promptFound = false; + var gotLineCont = false; + var gotHereDoc = false; + const lineGotPrompt = []; + for (const line of textContent.split('\n')) { + match = line.match(regexp) + if (match || gotLineCont || gotHereDoc) { + promptFound = regexp.test(line) + lineGotPrompt.push(promptFound) + if (removePrompts && promptFound) { + outputLines.push(match[2]) + } else { + outputLines.push(line) + } + gotLineCont = line.endsWith(lineContinuationChar) & useLineCont + if (line.includes(hereDocDelim) & useHereDoc) + gotHereDoc = !gotHereDoc + } else if (!onlyCopyPromptLines) { + outputLines.push(line) + } else if (copyEmptyLines && line.trim() === '') { + outputLines.push(line) + } + } + + // If no lines with the prompt were found then just use original lines + if (lineGotPrompt.some(v => v === true)) { + textContent = outputLines.join('\n'); + } + + // Remove a trailing newline to avoid auto-running when pasting + if (textContent.endsWith("\n")) { + textContent = textContent.slice(0, -1) + } + return textContent +} + + +var copyTargetText = (trigger) => { + var target = document.querySelector(trigger.attributes['data-clipboard-target'].value); + + // get filtered text + let exclude = '.linenos'; + + let text = filterText(target, exclude); + return formatCopyText(text, '', false, true, true, true, '', '') +} + + // Initialize with a callback so we can modify the text before copy + const clipboard = new ClipboardJS('.copybtn', {text: copyTargetText}) + + // Update UI with error/success messages + clipboard.on('success', event => { + clearSelection() + temporarilyChangeTooltip(event.trigger, messages[locale]['copy'], messages[locale]['copy_success']) + temporarilyChangeIcon(event.trigger) + }) + + clipboard.on('error', event => { + temporarilyChangeTooltip(event.trigger, messages[locale]['copy'], messages[locale]['copy_failure']) + }) +} + +runWhenDOMLoaded(addCopyButtonToCodeCells) \ No newline at end of file diff --git a/3.25.11-scylla/_static/copybutton_funcs.js b/3.25.11-scylla/_static/copybutton_funcs.js new file mode 100644 index 0000000000..dbe1aaad79 --- /dev/null +++ b/3.25.11-scylla/_static/copybutton_funcs.js @@ -0,0 +1,73 @@ +function escapeRegExp(string) { + return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string +} + +/** + * Removes excluded text from a Node. + * + * @param {Node} target Node to filter. + * @param {string} exclude CSS selector of nodes to exclude. + * @returns {DOMString} Text from `target` with text removed. + */ +export function filterText(target, exclude) { + const clone = target.cloneNode(true); // clone as to not modify the live DOM + if (exclude) { + // remove excluded nodes + clone.querySelectorAll(exclude).forEach(node => node.remove()); + } + return clone.innerText; +} + +// Callback when a copy button is clicked. Will be passed the node that was clicked +// should then grab the text and replace pieces of text that shouldn't be used in output +export function formatCopyText(textContent, copybuttonPromptText, isRegexp = false, onlyCopyPromptLines = true, removePrompts = true, copyEmptyLines = true, lineContinuationChar = "", hereDocDelim = "") { + var regexp; + var match; + + // Do we check for line continuation characters and "HERE-documents"? + var useLineCont = !!lineContinuationChar + var useHereDoc = !!hereDocDelim + + // create regexp to capture prompt and remaining line + if (isRegexp) { + regexp = new RegExp('^(' + copybuttonPromptText + ')(.*)') + } else { + regexp = new RegExp('^(' + escapeRegExp(copybuttonPromptText) + ')(.*)') + } + + const outputLines = []; + var promptFound = false; + var gotLineCont = false; + var gotHereDoc = false; + const lineGotPrompt = []; + for (const line of textContent.split('\n')) { + match = line.match(regexp) + if (match || gotLineCont || gotHereDoc) { + promptFound = regexp.test(line) + lineGotPrompt.push(promptFound) + if (removePrompts && promptFound) { + outputLines.push(match[2]) + } else { + outputLines.push(line) + } + gotLineCont = line.endsWith(lineContinuationChar) & useLineCont + if (line.includes(hereDocDelim) & useHereDoc) + gotHereDoc = !gotHereDoc + } else if (!onlyCopyPromptLines) { + outputLines.push(line) + } else if (copyEmptyLines && line.trim() === '') { + outputLines.push(line) + } + } + + // If no lines with the prompt were found then just use original lines + if (lineGotPrompt.some(v => v === true)) { + textContent = outputLines.join('\n'); + } + + // Remove a trailing newline to avoid auto-running when pasting + if (textContent.endsWith("\n")) { + textContent = textContent.slice(0, -1) + } + return textContent +} diff --git a/3.25.11-scylla/_static/css/main.css b/3.25.11-scylla/_static/css/main.css new file mode 100644 index 0000000000..4ac0174528 --- /dev/null +++ b/3.25.11-scylla/_static/css/main.css @@ -0,0 +1 @@ +@media print,screen and (min-width:40em){.reveal,.reveal.large,.reveal.small,.reveal.tiny{left:auto;margin:0 auto;right:auto}}/*! normalize.css v8.0.0 | MIT License | github.com/necolas/normalize.css */html{-webkit-text-size-adjust:100%;line-height:1.15}h1{font-size:2em;margin:.67em 0}hr{-webkit-box-sizing:content-box;box-sizing:content-box;overflow:visible}pre{font-family:monospace,monospace;font-size:1em}a{background-color:transparent}abbr[title]{border-bottom:0;-webkit-text-decoration:underline dotted;text-decoration:underline dotted}b,strong{font-weight:bolder}code,kbd,samp{font-family:monospace,monospace;font-size:1em}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}img{border-style:none}button,input,optgroup,select,textarea{font-size:100%;line-height:1.15;margin:0}button,input{overflow:visible}button,select{text-transform:none}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button}[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner,button::-moz-focus-inner{border-style:none;padding:0}[type=button]:-moz-focusring,[type=reset]:-moz-focusring,[type=submit]:-moz-focusring,button:-moz-focusring{outline:1px dotted ButtonText}fieldset{padding:.35em .75em .625em}legend{-webkit-box-sizing:border-box;box-sizing:border-box;color:inherit;display:table;padding:0;white-space:normal}progress{vertical-align:baseline}textarea{overflow:auto}[type=checkbox],[type=radio]{-webkit-box-sizing:border-box;box-sizing:border-box;padding:0}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}details{display:block}summary{display:list-item}template{display:none}[hidden]{display:none}[data-whatinput=mouse] *,[data-whatinput=mouse] :focus,[data-whatinput=touch] *,[data-whatinput=touch] :focus,[data-whatintent=mouse] *,[data-whatintent=mouse] :focus,[data-whatintent=touch] *,[data-whatintent=touch] :focus{outline:0}[draggable=false]{-webkit-touch-callout:none;-webkit-user-select:none}.foundation-mq{font-family:"small=0em&medium=40em&large=64em&xlarge=75em&xxlarge=90em"}html{-webkit-box-sizing:border-box;font-size:100%}*,:after,:before{-webkit-box-sizing:inherit}body{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;background:#fefefe;color:#0a0a0a;font-family:Helvetica Neue,Helvetica,Roboto,Arial,sans-serif;font-weight:400;line-height:1.5;margin:0;padding:0}img{-ms-interpolation-mode:bicubic;display:inline-block;height:auto;vertical-align:middle}textarea{border-radius:0;height:auto;min-height:50px}select{-webkit-box-sizing:border-box;box-sizing:border-box;width:100%}.map_canvas embed,.map_canvas img,.map_canvas object,.mqa-display embed,.mqa-display img,.mqa-display object{max-width:none!important}button{-webkit-appearance:none;-moz-appearance:none;appearance:none;background:0 0;border:0;border-radius:0;cursor:auto;line-height:1;padding:0}[data-whatinput=mouse] button{outline:0}pre{-webkit-overflow-scrolling:touch;overflow:auto}button,input,optgroup,select,textarea{font-family:inherit}.is-visible{display:block!important}.is-hidden{display:none!important}[type=color],[type=date],[type=datetime-local],[type=datetime],[type=email],[type=month],[type=number],[type=password],[type=search],[type=tel],[type=text],[type=time],[type=url],[type=week],textarea{-webkit-appearance:none;-moz-appearance:none;appearance:none;background-color:#fefefe;border:1px solid #cacaca;border-radius:0;-webkit-box-shadow:inset 0 1px 2px hsla(0,0%,4%,.1);box-shadow:inset 0 1px 2px hsla(0,0%,4%,.1);-webkit-box-sizing:border-box;box-sizing:border-box;color:#0a0a0a;display:block;font-family:inherit;font-size:1rem;font-weight:400;height:2.4375rem;line-height:1.5;margin:0 0 1rem;padding:.5rem;-webkit-transition:border-color .25s ease-in-out,-webkit-box-shadow .5s;transition:border-color .25s ease-in-out,-webkit-box-shadow .5s;transition:box-shadow .5s,border-color .25s ease-in-out;transition:box-shadow .5s,border-color .25s ease-in-out,-webkit-box-shadow .5s;width:100%}[type=color]:focus,[type=date]:focus,[type=datetime-local]:focus,[type=datetime]:focus,[type=email]:focus,[type=month]:focus,[type=number]:focus,[type=password]:focus,[type=search]:focus,[type=tel]:focus,[type=text]:focus,[type=time]:focus,[type=url]:focus,[type=week]:focus,textarea:focus{background-color:#fefefe;border:1px solid #8a8a8a;-webkit-box-shadow:0 0 5px #cacaca;box-shadow:0 0 5px #cacaca;outline:0;-webkit-transition:border-color .25s ease-in-out,-webkit-box-shadow .5s;transition:border-color .25s ease-in-out,-webkit-box-shadow .5s;transition:box-shadow .5s,border-color .25s ease-in-out;transition:box-shadow .5s,border-color .25s ease-in-out,-webkit-box-shadow .5s}textarea{max-width:100%}textarea[rows]{height:auto}input:disabled,input[readonly],textarea:disabled,textarea[readonly]{background-color:#e6e6e6;cursor:not-allowed}[type=button],[type=submit]{-webkit-appearance:none;-moz-appearance:none;appearance:none;border-radius:0}input[type=search]{-webkit-box-sizing:border-box;box-sizing:border-box}::-webkit-input-placeholder{color:#cacaca}::-moz-placeholder{color:#cacaca}:-ms-input-placeholder{color:#cacaca}::-ms-input-placeholder{color:#cacaca}::placeholder{color:#cacaca}[type=checkbox],[type=file],[type=radio]{margin:0 0 1rem}[type=checkbox]+label,[type=radio]+label{display:inline-block;margin-bottom:0;margin-left:.5rem;margin-right:1rem;vertical-align:baseline}[type=checkbox]+label[for],[type=radio]+label[for]{cursor:pointer}label>[type=checkbox],label>[type=radio]{margin-right:.5rem}[type=file]{width:100%}label{color:#0a0a0a;display:block;font-size:.875rem;font-weight:400;line-height:1.8;margin:0}label.middle{line-height:1.5;margin:0 0 1rem;padding:.5625rem 0}.help-text{color:#0a0a0a;font-size:.8125rem;font-style:italic;margin-top:-.5rem}.input-group{-webkit-box-align:stretch;-ms-flex-align:stretch;-webkit-align-items:stretch;align-items:stretch;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;margin-bottom:1rem;width:100%}.input-group>:first-child,.input-group>:first-child.input-group-button>*{border-radius:0}.input-group>:last-child,.input-group>:last-child.input-group-button>*{border-radius:0}.input-group-button,.input-group-button a,.input-group-button button,.input-group-button input,.input-group-button label,.input-group-field,.input-group-label{margin:0;white-space:nowrap}.input-group-label{-webkit-box-flex:0;-webkit-box-align:center;-ms-flex-align:center;-webkit-align-items:center;align-items:center;background:#e6e6e6;border:1px solid #cacaca;color:#0a0a0a;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto;padding:0 1rem;text-align:center;white-space:nowrap}.input-group-label:first-child{border-right:0}.input-group-label:last-child{border-left:0}.input-group-field{-webkit-box-flex:1;border-radius:0;-webkit-flex:1 1 0px;-ms-flex:1 1 0px;flex:1 1 0px;min-width:0}.input-group-button{-webkit-box-flex:0;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto;padding-bottom:0;padding-top:0;text-align:center}.input-group-button a,.input-group-button button,.input-group-button input,.input-group-button label{-ms-flex-item-align:stretch;-webkit-align-self:stretch;align-self:stretch;font-size:1rem;height:auto;padding-bottom:0;padding-top:0}fieldset{border:0;margin:0;padding:0}legend{margin-bottom:.5rem;max-width:100%}.fieldset{border:1px solid #cacaca;margin:1.125rem 0;padding:1.25rem}.fieldset legend{margin:0 0 0 -.1875rem;padding:0 .1875rem}select{-webkit-appearance:none;-moz-appearance:none;appearance:none;background-color:#fefefe;background-image:url('data:image/svg+xml;utf8,');background-origin:content-box;background-position:right -1rem center;background-repeat:no-repeat;background-size:9px 6px;border:1px solid #cacaca;border-radius:0;color:#0a0a0a;font-family:inherit;font-size:1rem;font-weight:400;height:2.4375rem;line-height:1.5;margin:0 0 1rem;padding:.5rem 1.5rem .5rem .5rem;-webkit-transition:border-color .25s ease-in-out,-webkit-box-shadow .5s;transition:border-color .25s ease-in-out,-webkit-box-shadow .5s;transition:box-shadow .5s,border-color .25s ease-in-out;transition:box-shadow .5s,border-color .25s ease-in-out,-webkit-box-shadow .5s}@media screen and (min-width:0\0){select{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAYCAYAAACbU/80AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAIpJREFUeNrEkckNgDAMBBfRkEt0ObRBBdsGXUDgmQfK4XhH2m8czQAAy27R3tsw4Qfe2x8uOO6oYLb6GlOor3GF+swURAOmUJ+RwtEJs9WvTGEYxBXqI1MQAZhCfUQKRzDMVj+TwrAIV6jvSUEkYAr1LSkcyTBb/V+KYfX7xAeusq3sLDtGH3kEGACPWIflNZfhRQAAAABJRU5ErkJggg==)}}select:focus{background-color:#fefefe;border:1px solid #8a8a8a;-webkit-box-shadow:0 0 5px #cacaca;box-shadow:0 0 5px #cacaca;outline:0;-webkit-transition:border-color .25s ease-in-out,-webkit-box-shadow .5s;transition:border-color .25s ease-in-out,-webkit-box-shadow .5s;transition:box-shadow .5s,border-color .25s ease-in-out;transition:box-shadow .5s,border-color .25s ease-in-out,-webkit-box-shadow .5s}select:disabled{background-color:#e6e6e6;cursor:not-allowed}select::-ms-expand{display:none}select[multiple]{background-image:none;height:auto}select:not([multiple]){padding-bottom:0;padding-top:0}.is-invalid-input:not(:focus){background-color:#f9ecea;border-color:#cc4b37}.is-invalid-input:not(:focus)::-webkit-input-placeholder{color:#cc4b37}.is-invalid-input:not(:focus)::-moz-placeholder{color:#cc4b37}.is-invalid-input:not(:focus):-ms-input-placeholder{color:#cc4b37}.is-invalid-input:not(:focus)::-ms-input-placeholder{color:#cc4b37}.is-invalid-input:not(:focus)::placeholder{color:#cc4b37}.form-error,.is-invalid-label{color:#cc4b37}.form-error{display:none;font-size:.75rem;font-weight:700;margin-bottom:1rem;margin-top:-.5rem}.form-error.is-visible{display:block}blockquote,dd,div,dl,dt,form,h1,h2,h3,h4,h5,h6,li,ol,p,pre,td,th,ul{margin:0;padding:0}p{text-rendering:optimizeLegibility;font-size:inherit;line-height:1.6;margin-bottom:1rem}em,i{font-style:italic}b,em,i,strong{line-height:inherit}b,strong{font-weight:700}small{font-size:80%;line-height:inherit}.h1,.h2,.h3,.h4,.h5,.h6,h1,h2,h3,h4,h5,h6{text-rendering:optimizeLegibility;color:inherit;font-family:Helvetica Neue,Helvetica,Roboto,Arial,sans-serif;font-style:normal;font-weight:400}.h1 small,.h2 small,.h3 small,.h4 small,.h5 small,.h6 small,h1 small,h2 small,h3 small,h4 small,h5 small,h6 small{color:#cacaca;line-height:0}.h1,h1{font-size:1.5rem}.h1,.h2,h1,h2{line-height:1.4;margin-bottom:.5rem;margin-top:0}.h2,h2{font-size:1.25rem}.h3,h3{font-size:1.1875rem}.h3,.h4,h3,h4{line-height:1.4;margin-bottom:.5rem;margin-top:0}.h4,h4{font-size:1.125rem}.h5,h5{font-size:1.0625rem}.h5,.h6,h5,h6{line-height:1.4;margin-bottom:.5rem;margin-top:0}.h6,h6{font-size:1rem}@media print,screen and (min-width:40em){.h1,h1{font-size:3rem}.h2,h2{font-size:2.5rem}.h3,h3{font-size:1.9375rem}.h4,h4{font-size:1.5625rem}.h5,h5{font-size:1.25rem}.h6,h6{font-size:1rem}}a{color:#1779ba;cursor:pointer;line-height:inherit;text-decoration:none}a:focus,a:hover{color:#1468a0}a img,hr{border:0}hr{border-bottom:1px solid #cacaca;clear:both;height:0;margin:1.25rem auto;max-width:75rem}dl,ol,ul{line-height:1.6;list-style-position:outside;margin-bottom:1rem}li{font-size:inherit}ul{list-style-type:disc}ol,ul{margin-left:1.25rem}ol ol,ol ul,ul ol,ul ul{margin-bottom:0;margin-left:1.25rem}dl{margin-bottom:1rem}dl dt{font-weight:700;margin-bottom:.3rem}blockquote{border-left:1px solid #cacaca;margin:0 0 1rem;padding:.5625rem 1.25rem 0 1.1875rem}blockquote,blockquote p{color:#8a8a8a;line-height:1.6}abbr,abbr[title]{border-bottom:1px dotted #0a0a0a;cursor:help;text-decoration:none}figure,kbd{margin:0}kbd{background-color:#e6e6e6;color:#0a0a0a;font-family:Consolas,Liberation Mono,Courier,monospace;padding:.125rem .25rem 0}.subheader{color:#8a8a8a;font-weight:400;line-height:1.4;margin-bottom:.5rem;margin-top:.2rem}.lead{font-size:125%;line-height:1.6}.stat{font-size:2.5rem;line-height:1}p+.stat{margin-top:-1rem}ol.no-bullet,ul.no-bullet{list-style:none;margin-left:0}.cite-block,cite{color:#8a8a8a;display:block;font-size:.8125rem}.cite-block:before,cite:before{content:"— "}.code-inline,code{word-wrap:break-word;display:inline;max-width:100%;padding:.125rem .3125rem .0625rem}.code-block,.code-inline,code{background-color:#e6e6e6;border:1px solid #cacaca;color:#0a0a0a;font-family:Consolas,Liberation Mono,Courier,monospace;font-weight:400}.code-block{display:block;margin-bottom:1.5rem;overflow:auto;padding:1rem;white-space:pre}.text-left{text-align:left}.text-right{text-align:right}.text-center{text-align:center}.text-justify{text-align:justify}@media print,screen and (min-width:40em){.medium-text-left{text-align:left}.medium-text-right{text-align:right}.medium-text-center{text-align:center}.medium-text-justify{text-align:justify}}@media print,screen and (min-width:64em){.large-text-left{text-align:left}.large-text-right{text-align:right}.large-text-center{text-align:center}.large-text-justify{text-align:justify}}.show-for-print{display:none!important}@media print{*{-webkit-print-color-adjust:economy;background:0 0!important;-webkit-box-shadow:none!important;box-shadow:none!important;color:#000!important;color-adjust:economy;text-shadow:none!important}.show-for-print{display:block!important}.hide-for-print{display:none!important}table.show-for-print{display:table!important}thead.show-for-print{display:table-header-group!important}tbody.show-for-print{display:table-row-group!important}tr.show-for-print{display:table-row!important}td.show-for-print,th.show-for-print{display:table-cell!important}a,a:visited{text-decoration:underline}a[href]:after{content:" (" attr(href) ")"}.ir a:after,a[href^="#"]:after,a[href^="javascript:"]:after{content:""}abbr[title]:after{content:" (" attr(title) ")"}blockquote,pre{border:1px solid #8a8a8a;page-break-inside:avoid}thead{display:table-header-group}img,tr{page-break-inside:avoid}img{max-width:100%!important}@page{margin:.5cm}h2,h3,p{orphans:3;widows:3}h2,h3{page-break-after:avoid}.print-break-inside{page-break-inside:auto}}.grid-container{margin-left:auto;margin-right:auto;max-width:75rem;padding-left:.625rem;padding-right:.625rem}@media print,screen and (min-width:40em){.grid-container{padding-left:.9375rem;padding-right:.9375rem}}.grid-container.fluid{margin-left:auto;margin-right:auto;max-width:100%;padding-left:.625rem;padding-right:.625rem}@media print,screen and (min-width:40em){.grid-container.fluid{padding-left:.9375rem;padding-right:.9375rem}}.grid-container.full{margin-left:auto;margin-right:auto;max-width:100%;padding-left:0;padding-right:0}.grid-x{-webkit-box-orient:horizontal;-webkit-box-direction:normal;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-flow:row wrap;-ms-flex-flow:row wrap;flex-flow:row wrap}.cell{-webkit-box-flex:0;-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto;min-height:0;min-width:0;width:100%}.cell.auto{-webkit-box-flex:1;-webkit-flex:1 1 0;-ms-flex:1 1 0px;flex:1 1 0}.cell.shrink{-webkit-box-flex:0;-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto}.grid-x>.auto{width:auto}.grid-x>.shrink{width:auto}.grid-x>.small-1,.grid-x>.small-2,.grid-x>.small-3,.grid-x>.small-4,.grid-x>.small-5,.grid-x>.small-6,.grid-x>.small-7,.grid-x>.small-8,.grid-x>.small-9,.grid-x>.small-10,.grid-x>.small-11,.grid-x>.small-12,.grid-x>.small-full,.grid-x>.small-shrink{-ms-flex-preferred-size:auto;-webkit-flex-basis:auto;flex-basis:auto}@media print,screen and (min-width:40em){.grid-x>.medium-1,.grid-x>.medium-2,.grid-x>.medium-3,.grid-x>.medium-4,.grid-x>.medium-5,.grid-x>.medium-6,.grid-x>.medium-7,.grid-x>.medium-8,.grid-x>.medium-9,.grid-x>.medium-10,.grid-x>.medium-11,.grid-x>.medium-12,.grid-x>.medium-full,.grid-x>.medium-shrink{-ms-flex-preferred-size:auto;-webkit-flex-basis:auto;flex-basis:auto}}@media print,screen and (min-width:64em){.grid-x>.large-1,.grid-x>.large-2,.grid-x>.large-3,.grid-x>.large-4,.grid-x>.large-5,.grid-x>.large-6,.grid-x>.large-7,.grid-x>.large-8,.grid-x>.large-9,.grid-x>.large-10,.grid-x>.large-11,.grid-x>.large-12,.grid-x>.large-full,.grid-x>.large-shrink{-ms-flex-preferred-size:auto;-webkit-flex-basis:auto;flex-basis:auto}}.grid-x>.small-1,.grid-x>.small-2,.grid-x>.small-3,.grid-x>.small-4,.grid-x>.small-5,.grid-x>.small-6,.grid-x>.small-7,.grid-x>.small-8,.grid-x>.small-9,.grid-x>.small-10,.grid-x>.small-11,.grid-x>.small-12{-webkit-box-flex:0;-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto}.grid-x>.small-1{width:8.33333%}.grid-x>.small-2{width:16.66667%}.grid-x>.small-3{width:25%}.grid-x>.small-4{width:33.33333%}.grid-x>.small-5{width:41.66667%}.grid-x>.small-6{width:50%}.grid-x>.small-7{width:58.33333%}.grid-x>.small-8{width:66.66667%}.grid-x>.small-9{width:75%}.grid-x>.small-10{width:83.33333%}.grid-x>.small-11{width:91.66667%}.grid-x>.small-12{width:100%}@media print,screen and (min-width:40em){.grid-x>.medium-auto{-webkit-box-flex:1;-webkit-flex:1 1 0;-ms-flex:1 1 0px;flex:1 1 0;width:auto}.grid-x>.medium-1,.grid-x>.medium-2,.grid-x>.medium-3,.grid-x>.medium-4,.grid-x>.medium-5,.grid-x>.medium-6,.grid-x>.medium-7,.grid-x>.medium-8,.grid-x>.medium-9,.grid-x>.medium-10,.grid-x>.medium-11,.grid-x>.medium-12,.grid-x>.medium-shrink{-webkit-box-flex:0;-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto}.grid-x>.medium-shrink{width:auto}.grid-x>.medium-1{width:8.33333%}.grid-x>.medium-2{width:16.66667%}.grid-x>.medium-3{width:25%}.grid-x>.medium-4{width:33.33333%}.grid-x>.medium-5{width:41.66667%}.grid-x>.medium-6{width:50%}.grid-x>.medium-7{width:58.33333%}.grid-x>.medium-8{width:66.66667%}.grid-x>.medium-9{width:75%}.grid-x>.medium-10{width:83.33333%}.grid-x>.medium-11{width:91.66667%}.grid-x>.medium-12{width:100%}}@media print,screen and (min-width:64em){.grid-x>.large-auto{-webkit-box-flex:1;-webkit-flex:1 1 0;-ms-flex:1 1 0px;flex:1 1 0;width:auto}.grid-x>.large-1,.grid-x>.large-2,.grid-x>.large-3,.grid-x>.large-4,.grid-x>.large-5,.grid-x>.large-6,.grid-x>.large-7,.grid-x>.large-8,.grid-x>.large-9,.grid-x>.large-10,.grid-x>.large-11,.grid-x>.large-12,.grid-x>.large-shrink{-webkit-box-flex:0;-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto}.grid-x>.large-shrink{width:auto}.grid-x>.large-1{width:8.33333%}.grid-x>.large-2{width:16.66667%}.grid-x>.large-3{width:25%}.grid-x>.large-4{width:33.33333%}.grid-x>.large-5{width:41.66667%}.grid-x>.large-6{width:50%}.grid-x>.large-7{width:58.33333%}.grid-x>.large-8{width:66.66667%}.grid-x>.large-9{width:75%}.grid-x>.large-10{width:83.33333%}.grid-x>.large-11{width:91.66667%}.grid-x>.large-12{width:100%}}.grid-margin-x:not(.grid-x)>.cell{width:auto}.grid-margin-y:not(.grid-y)>.cell{height:auto}.grid-margin-x{margin-left:-.625rem;margin-right:-.625rem}@media print,screen and (min-width:40em){.grid-margin-x{margin-left:-.9375rem;margin-right:-.9375rem}}.grid-margin-x>.cell{margin-left:.625rem;margin-right:.625rem;width:calc(100% - 1.25rem)}@media print,screen and (min-width:40em){.grid-margin-x>.cell{margin-left:.9375rem;margin-right:.9375rem;width:calc(100% - 1.875rem)}}.grid-margin-x>.auto{width:auto}.grid-margin-x>.shrink{width:auto}.grid-margin-x>.small-1{width:calc(8.33333% - 1.25rem)}.grid-margin-x>.small-2{width:calc(16.66667% - 1.25rem)}.grid-margin-x>.small-3{width:calc(25% - 1.25rem)}.grid-margin-x>.small-4{width:calc(33.33333% - 1.25rem)}.grid-margin-x>.small-5{width:calc(41.66667% - 1.25rem)}.grid-margin-x>.small-6{width:calc(50% - 1.25rem)}.grid-margin-x>.small-7{width:calc(58.33333% - 1.25rem)}.grid-margin-x>.small-8{width:calc(66.66667% - 1.25rem)}.grid-margin-x>.small-9{width:calc(75% - 1.25rem)}.grid-margin-x>.small-10{width:calc(83.33333% - 1.25rem)}.grid-margin-x>.small-11{width:calc(91.66667% - 1.25rem)}.grid-margin-x>.small-12{width:calc(100% - 1.25rem)}@media print,screen and (min-width:40em){.grid-margin-x>.auto{width:auto}.grid-margin-x>.shrink{width:auto}.grid-margin-x>.small-1{width:calc(8.33333% - 1.875rem)}.grid-margin-x>.small-2{width:calc(16.66667% - 1.875rem)}.grid-margin-x>.small-3{width:calc(25% - 1.875rem)}.grid-margin-x>.small-4{width:calc(33.33333% - 1.875rem)}.grid-margin-x>.small-5{width:calc(41.66667% - 1.875rem)}.grid-margin-x>.small-6{width:calc(50% - 1.875rem)}.grid-margin-x>.small-7{width:calc(58.33333% - 1.875rem)}.grid-margin-x>.small-8{width:calc(66.66667% - 1.875rem)}.grid-margin-x>.small-9{width:calc(75% - 1.875rem)}.grid-margin-x>.small-10{width:calc(83.33333% - 1.875rem)}.grid-margin-x>.small-11{width:calc(91.66667% - 1.875rem)}.grid-margin-x>.small-12{width:calc(100% - 1.875rem)}.grid-margin-x>.medium-auto{width:auto}.grid-margin-x>.medium-shrink{width:auto}.grid-margin-x>.medium-1{width:calc(8.33333% - 1.875rem)}.grid-margin-x>.medium-2{width:calc(16.66667% - 1.875rem)}.grid-margin-x>.medium-3{width:calc(25% - 1.875rem)}.grid-margin-x>.medium-4{width:calc(33.33333% - 1.875rem)}.grid-margin-x>.medium-5{width:calc(41.66667% - 1.875rem)}.grid-margin-x>.medium-6{width:calc(50% - 1.875rem)}.grid-margin-x>.medium-7{width:calc(58.33333% - 1.875rem)}.grid-margin-x>.medium-8{width:calc(66.66667% - 1.875rem)}.grid-margin-x>.medium-9{width:calc(75% - 1.875rem)}.grid-margin-x>.medium-10{width:calc(83.33333% - 1.875rem)}.grid-margin-x>.medium-11{width:calc(91.66667% - 1.875rem)}.grid-margin-x>.medium-12{width:calc(100% - 1.875rem)}}@media print,screen and (min-width:64em){.grid-margin-x>.large-auto{width:auto}.grid-margin-x>.large-shrink{width:auto}.grid-margin-x>.large-1{width:calc(8.33333% - 1.875rem)}.grid-margin-x>.large-2{width:calc(16.66667% - 1.875rem)}.grid-margin-x>.large-3{width:calc(25% - 1.875rem)}.grid-margin-x>.large-4{width:calc(33.33333% - 1.875rem)}.grid-margin-x>.large-5{width:calc(41.66667% - 1.875rem)}.grid-margin-x>.large-6{width:calc(50% - 1.875rem)}.grid-margin-x>.large-7{width:calc(58.33333% - 1.875rem)}.grid-margin-x>.large-8{width:calc(66.66667% - 1.875rem)}.grid-margin-x>.large-9{width:calc(75% - 1.875rem)}.grid-margin-x>.large-10{width:calc(83.33333% - 1.875rem)}.grid-margin-x>.large-11{width:calc(91.66667% - 1.875rem)}.grid-margin-x>.large-12{width:calc(100% - 1.875rem)}}.grid-padding-x .grid-padding-x{margin-left:-.625rem;margin-right:-.625rem}@media print,screen and (min-width:40em){.grid-padding-x .grid-padding-x{margin-left:-.9375rem;margin-right:-.9375rem}}.grid-container:not(.full)>.grid-padding-x{margin-left:-.625rem;margin-right:-.625rem}@media print,screen and (min-width:40em){.grid-container:not(.full)>.grid-padding-x{margin-left:-.9375rem;margin-right:-.9375rem}}.grid-padding-x>.cell{padding-left:.625rem;padding-right:.625rem}@media print,screen and (min-width:40em){.grid-padding-x>.cell{padding-left:.9375rem;padding-right:.9375rem}}.small-up-1>.cell{width:100%}.small-up-2>.cell{width:50%}.small-up-3>.cell{width:33.33333%}.small-up-4>.cell{width:25%}.small-up-5>.cell{width:20%}.small-up-6>.cell{width:16.66667%}.small-up-7>.cell{width:14.28571%}.small-up-8>.cell{width:12.5%}@media print,screen and (min-width:40em){.medium-up-1>.cell{width:100%}.medium-up-2>.cell{width:50%}.medium-up-3>.cell{width:33.33333%}.medium-up-4>.cell{width:25%}.medium-up-5>.cell{width:20%}.medium-up-6>.cell{width:16.66667%}.medium-up-7>.cell{width:14.28571%}.medium-up-8>.cell{width:12.5%}}@media print,screen and (min-width:64em){.large-up-1>.cell{width:100%}.large-up-2>.cell{width:50%}.large-up-3>.cell{width:33.33333%}.large-up-4>.cell{width:25%}.large-up-5>.cell{width:20%}.large-up-6>.cell{width:16.66667%}.large-up-7>.cell{width:14.28571%}.large-up-8>.cell{width:12.5%}}.grid-margin-x.small-up-1>.cell{width:calc(100% - 1.25rem)}.grid-margin-x.small-up-2>.cell{width:calc(50% - 1.25rem)}.grid-margin-x.small-up-3>.cell{width:calc(33.33333% - 1.25rem)}.grid-margin-x.small-up-4>.cell{width:calc(25% - 1.25rem)}.grid-margin-x.small-up-5>.cell{width:calc(20% - 1.25rem)}.grid-margin-x.small-up-6>.cell{width:calc(16.66667% - 1.25rem)}.grid-margin-x.small-up-7>.cell{width:calc(14.28571% - 1.25rem)}.grid-margin-x.small-up-8>.cell{width:calc(12.5% - 1.25rem)}@media print,screen and (min-width:40em){.grid-margin-x.small-up-1>.cell{width:calc(100% - 1.875rem)}.grid-margin-x.small-up-2>.cell{width:calc(50% - 1.875rem)}.grid-margin-x.small-up-3>.cell{width:calc(33.33333% - 1.875rem)}.grid-margin-x.small-up-4>.cell{width:calc(25% - 1.875rem)}.grid-margin-x.small-up-5>.cell{width:calc(20% - 1.875rem)}.grid-margin-x.small-up-6>.cell{width:calc(16.66667% - 1.875rem)}.grid-margin-x.small-up-7>.cell{width:calc(14.28571% - 1.875rem)}.grid-margin-x.small-up-8>.cell{width:calc(12.5% - 1.875rem)}.grid-margin-x.medium-up-1>.cell{width:calc(100% - 1.875rem)}.grid-margin-x.medium-up-2>.cell{width:calc(50% - 1.875rem)}.grid-margin-x.medium-up-3>.cell{width:calc(33.33333% - 1.875rem)}.grid-margin-x.medium-up-4>.cell{width:calc(25% - 1.875rem)}.grid-margin-x.medium-up-5>.cell{width:calc(20% - 1.875rem)}.grid-margin-x.medium-up-6>.cell{width:calc(16.66667% - 1.875rem)}.grid-margin-x.medium-up-7>.cell{width:calc(14.28571% - 1.875rem)}.grid-margin-x.medium-up-8>.cell{width:calc(12.5% - 1.875rem)}}@media print,screen and (min-width:64em){.grid-margin-x.large-up-1>.cell{width:calc(100% - 1.875rem)}.grid-margin-x.large-up-2>.cell{width:calc(50% - 1.875rem)}.grid-margin-x.large-up-3>.cell{width:calc(33.33333% - 1.875rem)}.grid-margin-x.large-up-4>.cell{width:calc(25% - 1.875rem)}.grid-margin-x.large-up-5>.cell{width:calc(20% - 1.875rem)}.grid-margin-x.large-up-6>.cell{width:calc(16.66667% - 1.875rem)}.grid-margin-x.large-up-7>.cell{width:calc(14.28571% - 1.875rem)}.grid-margin-x.large-up-8>.cell{width:calc(12.5% - 1.875rem)}}.small-margin-collapse{margin-left:0;margin-right:0}.small-margin-collapse>.cell{margin-left:0;margin-right:0}.small-margin-collapse>.small-1{width:8.33333%}.small-margin-collapse>.small-2{width:16.66667%}.small-margin-collapse>.small-3{width:25%}.small-margin-collapse>.small-4{width:33.33333%}.small-margin-collapse>.small-5{width:41.66667%}.small-margin-collapse>.small-6{width:50%}.small-margin-collapse>.small-7{width:58.33333%}.small-margin-collapse>.small-8{width:66.66667%}.small-margin-collapse>.small-9{width:75%}.small-margin-collapse>.small-10{width:83.33333%}.small-margin-collapse>.small-11{width:91.66667%}.small-margin-collapse>.small-12{width:100%}@media print,screen and (min-width:40em){.small-margin-collapse>.medium-1{width:8.33333%}.small-margin-collapse>.medium-2{width:16.66667%}.small-margin-collapse>.medium-3{width:25%}.small-margin-collapse>.medium-4{width:33.33333%}.small-margin-collapse>.medium-5{width:41.66667%}.small-margin-collapse>.medium-6{width:50%}.small-margin-collapse>.medium-7{width:58.33333%}.small-margin-collapse>.medium-8{width:66.66667%}.small-margin-collapse>.medium-9{width:75%}.small-margin-collapse>.medium-10{width:83.33333%}.small-margin-collapse>.medium-11{width:91.66667%}.small-margin-collapse>.medium-12{width:100%}}@media print,screen and (min-width:64em){.small-margin-collapse>.large-1{width:8.33333%}.small-margin-collapse>.large-2{width:16.66667%}.small-margin-collapse>.large-3{width:25%}.small-margin-collapse>.large-4{width:33.33333%}.small-margin-collapse>.large-5{width:41.66667%}.small-margin-collapse>.large-6{width:50%}.small-margin-collapse>.large-7{width:58.33333%}.small-margin-collapse>.large-8{width:66.66667%}.small-margin-collapse>.large-9{width:75%}.small-margin-collapse>.large-10{width:83.33333%}.small-margin-collapse>.large-11{width:91.66667%}.small-margin-collapse>.large-12{width:100%}}.small-padding-collapse{margin-left:0;margin-right:0}.small-padding-collapse>.cell{padding-left:0;padding-right:0}@media print,screen and (min-width:40em){.medium-margin-collapse{margin-left:0;margin-right:0}.medium-margin-collapse>.cell{margin-left:0;margin-right:0}}@media print,screen and (min-width:40em){.medium-margin-collapse>.small-1{width:8.33333%}.medium-margin-collapse>.small-2{width:16.66667%}.medium-margin-collapse>.small-3{width:25%}.medium-margin-collapse>.small-4{width:33.33333%}.medium-margin-collapse>.small-5{width:41.66667%}.medium-margin-collapse>.small-6{width:50%}.medium-margin-collapse>.small-7{width:58.33333%}.medium-margin-collapse>.small-8{width:66.66667%}.medium-margin-collapse>.small-9{width:75%}.medium-margin-collapse>.small-10{width:83.33333%}.medium-margin-collapse>.small-11{width:91.66667%}.medium-margin-collapse>.small-12{width:100%}}@media print,screen and (min-width:40em){.medium-margin-collapse>.medium-1{width:8.33333%}.medium-margin-collapse>.medium-2{width:16.66667%}.medium-margin-collapse>.medium-3{width:25%}.medium-margin-collapse>.medium-4{width:33.33333%}.medium-margin-collapse>.medium-5{width:41.66667%}.medium-margin-collapse>.medium-6{width:50%}.medium-margin-collapse>.medium-7{width:58.33333%}.medium-margin-collapse>.medium-8{width:66.66667%}.medium-margin-collapse>.medium-9{width:75%}.medium-margin-collapse>.medium-10{width:83.33333%}.medium-margin-collapse>.medium-11{width:91.66667%}.medium-margin-collapse>.medium-12{width:100%}}@media print,screen and (min-width:64em){.medium-margin-collapse>.large-1{width:8.33333%}.medium-margin-collapse>.large-2{width:16.66667%}.medium-margin-collapse>.large-3{width:25%}.medium-margin-collapse>.large-4{width:33.33333%}.medium-margin-collapse>.large-5{width:41.66667%}.medium-margin-collapse>.large-6{width:50%}.medium-margin-collapse>.large-7{width:58.33333%}.medium-margin-collapse>.large-8{width:66.66667%}.medium-margin-collapse>.large-9{width:75%}.medium-margin-collapse>.large-10{width:83.33333%}.medium-margin-collapse>.large-11{width:91.66667%}.medium-margin-collapse>.large-12{width:100%}}@media print,screen and (min-width:40em){.medium-padding-collapse{margin-left:0;margin-right:0}.medium-padding-collapse>.cell{padding-left:0;padding-right:0}}@media print,screen and (min-width:64em){.large-margin-collapse{margin-left:0;margin-right:0}.large-margin-collapse>.cell{margin-left:0;margin-right:0}}@media print,screen and (min-width:64em){.large-margin-collapse>.small-1{width:8.33333%}.large-margin-collapse>.small-2{width:16.66667%}.large-margin-collapse>.small-3{width:25%}.large-margin-collapse>.small-4{width:33.33333%}.large-margin-collapse>.small-5{width:41.66667%}.large-margin-collapse>.small-6{width:50%}.large-margin-collapse>.small-7{width:58.33333%}.large-margin-collapse>.small-8{width:66.66667%}.large-margin-collapse>.small-9{width:75%}.large-margin-collapse>.small-10{width:83.33333%}.large-margin-collapse>.small-11{width:91.66667%}.large-margin-collapse>.small-12{width:100%}}@media print,screen and (min-width:64em){.large-margin-collapse>.medium-1{width:8.33333%}.large-margin-collapse>.medium-2{width:16.66667%}.large-margin-collapse>.medium-3{width:25%}.large-margin-collapse>.medium-4{width:33.33333%}.large-margin-collapse>.medium-5{width:41.66667%}.large-margin-collapse>.medium-6{width:50%}.large-margin-collapse>.medium-7{width:58.33333%}.large-margin-collapse>.medium-8{width:66.66667%}.large-margin-collapse>.medium-9{width:75%}.large-margin-collapse>.medium-10{width:83.33333%}.large-margin-collapse>.medium-11{width:91.66667%}.large-margin-collapse>.medium-12{width:100%}}@media print,screen and (min-width:64em){.large-margin-collapse>.large-1{width:8.33333%}.large-margin-collapse>.large-2{width:16.66667%}.large-margin-collapse>.large-3{width:25%}.large-margin-collapse>.large-4{width:33.33333%}.large-margin-collapse>.large-5{width:41.66667%}.large-margin-collapse>.large-6{width:50%}.large-margin-collapse>.large-7{width:58.33333%}.large-margin-collapse>.large-8{width:66.66667%}.large-margin-collapse>.large-9{width:75%}.large-margin-collapse>.large-10{width:83.33333%}.large-margin-collapse>.large-11{width:91.66667%}.large-margin-collapse>.large-12{width:100%}}@media print,screen and (min-width:64em){.large-padding-collapse{margin-left:0;margin-right:0}.large-padding-collapse>.cell{padding-left:0;padding-right:0}}.small-offset-0{margin-left:0}.grid-margin-x>.small-offset-0{margin-left:.625rem}.small-offset-1{margin-left:8.33333%}.grid-margin-x>.small-offset-1{margin-left:calc(8.33333% + .625rem)}.small-offset-2{margin-left:16.66667%}.grid-margin-x>.small-offset-2{margin-left:calc(16.66667% + .625rem)}.small-offset-3{margin-left:25%}.grid-margin-x>.small-offset-3{margin-left:calc(25% + .625rem)}.small-offset-4{margin-left:33.33333%}.grid-margin-x>.small-offset-4{margin-left:calc(33.33333% + .625rem)}.small-offset-5{margin-left:41.66667%}.grid-margin-x>.small-offset-5{margin-left:calc(41.66667% + .625rem)}.small-offset-6{margin-left:50%}.grid-margin-x>.small-offset-6{margin-left:calc(50% + .625rem)}.small-offset-7{margin-left:58.33333%}.grid-margin-x>.small-offset-7{margin-left:calc(58.33333% + .625rem)}.small-offset-8{margin-left:66.66667%}.grid-margin-x>.small-offset-8{margin-left:calc(66.66667% + .625rem)}.small-offset-9{margin-left:75%}.grid-margin-x>.small-offset-9{margin-left:calc(75% + .625rem)}.small-offset-10{margin-left:83.33333%}.grid-margin-x>.small-offset-10{margin-left:calc(83.33333% + .625rem)}.small-offset-11{margin-left:91.66667%}.grid-margin-x>.small-offset-11{margin-left:calc(91.66667% + .625rem)}@media print,screen and (min-width:40em){.medium-offset-0{margin-left:0}.grid-margin-x>.medium-offset-0{margin-left:.9375rem}.medium-offset-1{margin-left:8.33333%}.grid-margin-x>.medium-offset-1{margin-left:calc(8.33333% + .9375rem)}.medium-offset-2{margin-left:16.66667%}.grid-margin-x>.medium-offset-2{margin-left:calc(16.66667% + .9375rem)}.medium-offset-3{margin-left:25%}.grid-margin-x>.medium-offset-3{margin-left:calc(25% + .9375rem)}.medium-offset-4{margin-left:33.33333%}.grid-margin-x>.medium-offset-4{margin-left:calc(33.33333% + .9375rem)}.medium-offset-5{margin-left:41.66667%}.grid-margin-x>.medium-offset-5{margin-left:calc(41.66667% + .9375rem)}.medium-offset-6{margin-left:50%}.grid-margin-x>.medium-offset-6{margin-left:calc(50% + .9375rem)}.medium-offset-7{margin-left:58.33333%}.grid-margin-x>.medium-offset-7{margin-left:calc(58.33333% + .9375rem)}.medium-offset-8{margin-left:66.66667%}.grid-margin-x>.medium-offset-8{margin-left:calc(66.66667% + .9375rem)}.medium-offset-9{margin-left:75%}.grid-margin-x>.medium-offset-9{margin-left:calc(75% + .9375rem)}.medium-offset-10{margin-left:83.33333%}.grid-margin-x>.medium-offset-10{margin-left:calc(83.33333% + .9375rem)}.medium-offset-11{margin-left:91.66667%}.grid-margin-x>.medium-offset-11{margin-left:calc(91.66667% + .9375rem)}}@media print,screen and (min-width:64em){.large-offset-0{margin-left:0}.grid-margin-x>.large-offset-0{margin-left:.9375rem}.large-offset-1{margin-left:8.33333%}.grid-margin-x>.large-offset-1{margin-left:calc(8.33333% + .9375rem)}.large-offset-2{margin-left:16.66667%}.grid-margin-x>.large-offset-2{margin-left:calc(16.66667% + .9375rem)}.large-offset-3{margin-left:25%}.grid-margin-x>.large-offset-3{margin-left:calc(25% + .9375rem)}.large-offset-4{margin-left:33.33333%}.grid-margin-x>.large-offset-4{margin-left:calc(33.33333% + .9375rem)}.large-offset-5{margin-left:41.66667%}.grid-margin-x>.large-offset-5{margin-left:calc(41.66667% + .9375rem)}.large-offset-6{margin-left:50%}.grid-margin-x>.large-offset-6{margin-left:calc(50% + .9375rem)}.large-offset-7{margin-left:58.33333%}.grid-margin-x>.large-offset-7{margin-left:calc(58.33333% + .9375rem)}.large-offset-8{margin-left:66.66667%}.grid-margin-x>.large-offset-8{margin-left:calc(66.66667% + .9375rem)}.large-offset-9{margin-left:75%}.grid-margin-x>.large-offset-9{margin-left:calc(75% + .9375rem)}.large-offset-10{margin-left:83.33333%}.grid-margin-x>.large-offset-10{margin-left:calc(83.33333% + .9375rem)}.large-offset-11{margin-left:91.66667%}.grid-margin-x>.large-offset-11{margin-left:calc(91.66667% + .9375rem)}}.grid-y{-webkit-box-orient:vertical;-webkit-box-direction:normal;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-flow:column nowrap;-ms-flex-flow:column nowrap;flex-flow:column nowrap}.grid-y>.cell{height:auto;max-height:none}.grid-y>.auto{height:auto}.grid-y>.shrink{height:auto}.grid-y>.small-1,.grid-y>.small-2,.grid-y>.small-3,.grid-y>.small-4,.grid-y>.small-5,.grid-y>.small-6,.grid-y>.small-7,.grid-y>.small-8,.grid-y>.small-9,.grid-y>.small-10,.grid-y>.small-11,.grid-y>.small-12,.grid-y>.small-full,.grid-y>.small-shrink{-ms-flex-preferred-size:auto;-webkit-flex-basis:auto;flex-basis:auto}@media print,screen and (min-width:40em){.grid-y>.medium-1,.grid-y>.medium-2,.grid-y>.medium-3,.grid-y>.medium-4,.grid-y>.medium-5,.grid-y>.medium-6,.grid-y>.medium-7,.grid-y>.medium-8,.grid-y>.medium-9,.grid-y>.medium-10,.grid-y>.medium-11,.grid-y>.medium-12,.grid-y>.medium-full,.grid-y>.medium-shrink{-ms-flex-preferred-size:auto;-webkit-flex-basis:auto;flex-basis:auto}}@media print,screen and (min-width:64em){.grid-y>.large-1,.grid-y>.large-2,.grid-y>.large-3,.grid-y>.large-4,.grid-y>.large-5,.grid-y>.large-6,.grid-y>.large-7,.grid-y>.large-8,.grid-y>.large-9,.grid-y>.large-10,.grid-y>.large-11,.grid-y>.large-12,.grid-y>.large-full,.grid-y>.large-shrink{-ms-flex-preferred-size:auto;-webkit-flex-basis:auto;flex-basis:auto}}.grid-y>.small-1,.grid-y>.small-2,.grid-y>.small-3,.grid-y>.small-4,.grid-y>.small-5,.grid-y>.small-6,.grid-y>.small-7,.grid-y>.small-8,.grid-y>.small-9,.grid-y>.small-10,.grid-y>.small-11,.grid-y>.small-12{-webkit-box-flex:0;-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto}.grid-y>.small-1{height:8.33333%}.grid-y>.small-2{height:16.66667%}.grid-y>.small-3{height:25%}.grid-y>.small-4{height:33.33333%}.grid-y>.small-5{height:41.66667%}.grid-y>.small-6{height:50%}.grid-y>.small-7{height:58.33333%}.grid-y>.small-8{height:66.66667%}.grid-y>.small-9{height:75%}.grid-y>.small-10{height:83.33333%}.grid-y>.small-11{height:91.66667%}.grid-y>.small-12{height:100%}@media print,screen and (min-width:40em){.grid-y>.medium-auto{-webkit-box-flex:1;-webkit-flex:1 1 0;-ms-flex:1 1 0px;flex:1 1 0;height:auto}.grid-y>.medium-1,.grid-y>.medium-2,.grid-y>.medium-3,.grid-y>.medium-4,.grid-y>.medium-5,.grid-y>.medium-6,.grid-y>.medium-7,.grid-y>.medium-8,.grid-y>.medium-9,.grid-y>.medium-10,.grid-y>.medium-11,.grid-y>.medium-12,.grid-y>.medium-shrink{-webkit-box-flex:0;-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto}.grid-y>.medium-shrink{height:auto}.grid-y>.medium-1{height:8.33333%}.grid-y>.medium-2{height:16.66667%}.grid-y>.medium-3{height:25%}.grid-y>.medium-4{height:33.33333%}.grid-y>.medium-5{height:41.66667%}.grid-y>.medium-6{height:50%}.grid-y>.medium-7{height:58.33333%}.grid-y>.medium-8{height:66.66667%}.grid-y>.medium-9{height:75%}.grid-y>.medium-10{height:83.33333%}.grid-y>.medium-11{height:91.66667%}.grid-y>.medium-12{height:100%}}@media print,screen and (min-width:64em){.grid-y>.large-auto{-webkit-box-flex:1;-webkit-flex:1 1 0;-ms-flex:1 1 0px;flex:1 1 0;height:auto}.grid-y>.large-1,.grid-y>.large-2,.grid-y>.large-3,.grid-y>.large-4,.grid-y>.large-5,.grid-y>.large-6,.grid-y>.large-7,.grid-y>.large-8,.grid-y>.large-9,.grid-y>.large-10,.grid-y>.large-11,.grid-y>.large-12,.grid-y>.large-shrink{-webkit-box-flex:0;-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto}.grid-y>.large-shrink{height:auto}.grid-y>.large-1{height:8.33333%}.grid-y>.large-2{height:16.66667%}.grid-y>.large-3{height:25%}.grid-y>.large-4{height:33.33333%}.grid-y>.large-5{height:41.66667%}.grid-y>.large-6{height:50%}.grid-y>.large-7{height:58.33333%}.grid-y>.large-8{height:66.66667%}.grid-y>.large-9{height:75%}.grid-y>.large-10{height:83.33333%}.grid-y>.large-11{height:91.66667%}.grid-y>.large-12{height:100%}}.grid-padding-y .grid-padding-y{margin-bottom:-.625rem;margin-top:-.625rem}@media print,screen and (min-width:40em){.grid-padding-y .grid-padding-y{margin-bottom:-.9375rem;margin-top:-.9375rem}}.grid-padding-y>.cell{padding-bottom:.625rem;padding-top:.625rem}@media print,screen and (min-width:40em){.grid-padding-y>.cell{padding-bottom:.9375rem;padding-top:.9375rem}}.grid-frame{-webkit-box-align:stretch;-ms-flex-align:stretch;-webkit-align-items:stretch;align-items:stretch;-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap;overflow:hidden;position:relative;width:100vw}.cell .grid-frame{width:100%}.cell-block{max-width:100%;overflow-x:auto}.cell-block,.cell-block-y{-webkit-overflow-scrolling:touch;-ms-overflow-style:-ms-autohiding-scrollbar}.cell-block-y{max-height:100%;min-height:100%;overflow-y:auto}.cell-block-container{-webkit-box-orient:vertical;-webkit-box-direction:normal;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;max-height:100%}.cell-block-container>.grid-x{-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap;max-height:100%}@media print,screen and (min-width:40em){.medium-grid-frame{-webkit-box-align:stretch;-ms-flex-align:stretch;-webkit-align-items:stretch;align-items:stretch;-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap;overflow:hidden;position:relative;width:100vw}.cell .medium-grid-frame{width:100%}.medium-cell-block{-webkit-overflow-scrolling:touch;-ms-overflow-style:-ms-autohiding-scrollbar;max-width:100%;overflow-x:auto}.medium-cell-block-container{-webkit-box-orient:vertical;-webkit-box-direction:normal;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;max-height:100%}.medium-cell-block-container>.grid-x{-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap;max-height:100%}.medium-cell-block-y{-webkit-overflow-scrolling:touch;-ms-overflow-style:-ms-autohiding-scrollbar;max-height:100%;min-height:100%;overflow-y:auto}}@media print,screen and (min-width:64em){.large-grid-frame{-webkit-box-align:stretch;-ms-flex-align:stretch;-webkit-align-items:stretch;align-items:stretch;-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap;overflow:hidden;position:relative;width:100vw}.cell .large-grid-frame{width:100%}.large-cell-block{-webkit-overflow-scrolling:touch;-ms-overflow-style:-ms-autohiding-scrollbar;max-width:100%;overflow-x:auto}.large-cell-block-container{-webkit-box-orient:vertical;-webkit-box-direction:normal;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;max-height:100%}.large-cell-block-container>.grid-x{-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap;max-height:100%}.large-cell-block-y{-webkit-overflow-scrolling:touch;-ms-overflow-style:-ms-autohiding-scrollbar;max-height:100%;min-height:100%;overflow-y:auto}}.grid-y.grid-frame{-webkit-box-align:stretch;-ms-flex-align:stretch;-webkit-align-items:stretch;align-items:stretch;-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap;height:100vh;overflow:hidden;position:relative;width:auto}@media print,screen and (min-width:40em){.grid-y.medium-grid-frame{-webkit-box-align:stretch;-ms-flex-align:stretch;-webkit-align-items:stretch;align-items:stretch;-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap;height:100vh;overflow:hidden;position:relative;width:auto}}@media print,screen and (min-width:64em){.grid-y.large-grid-frame{-webkit-box-align:stretch;-ms-flex-align:stretch;-webkit-align-items:stretch;align-items:stretch;-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap;height:100vh;overflow:hidden;position:relative;width:auto}}.cell .grid-y.grid-frame{height:100%}@media print,screen and (min-width:40em){.cell .grid-y.medium-grid-frame{height:100%}}@media print,screen and (min-width:64em){.cell .grid-y.large-grid-frame{height:100%}}.grid-margin-y{margin-bottom:-.625rem;margin-top:-.625rem}@media print,screen and (min-width:40em){.grid-margin-y{margin-bottom:-.9375rem;margin-top:-.9375rem}}.grid-margin-y>.cell{height:calc(100% - 1.25rem);margin-bottom:.625rem;margin-top:.625rem}@media print,screen and (min-width:40em){.grid-margin-y>.cell{height:calc(100% - 1.875rem);margin-bottom:.9375rem;margin-top:.9375rem}}.grid-margin-y>.auto{height:auto}.grid-margin-y>.shrink{height:auto}.grid-margin-y>.small-1{height:calc(8.33333% - 1.25rem)}.grid-margin-y>.small-2{height:calc(16.66667% - 1.25rem)}.grid-margin-y>.small-3{height:calc(25% - 1.25rem)}.grid-margin-y>.small-4{height:calc(33.33333% - 1.25rem)}.grid-margin-y>.small-5{height:calc(41.66667% - 1.25rem)}.grid-margin-y>.small-6{height:calc(50% - 1.25rem)}.grid-margin-y>.small-7{height:calc(58.33333% - 1.25rem)}.grid-margin-y>.small-8{height:calc(66.66667% - 1.25rem)}.grid-margin-y>.small-9{height:calc(75% - 1.25rem)}.grid-margin-y>.small-10{height:calc(83.33333% - 1.25rem)}.grid-margin-y>.small-11{height:calc(91.66667% - 1.25rem)}.grid-margin-y>.small-12{height:calc(100% - 1.25rem)}@media print,screen and (min-width:40em){.grid-margin-y>.auto{height:auto}.grid-margin-y>.shrink{height:auto}.grid-margin-y>.small-1{height:calc(8.33333% - 1.875rem)}.grid-margin-y>.small-2{height:calc(16.66667% - 1.875rem)}.grid-margin-y>.small-3{height:calc(25% - 1.875rem)}.grid-margin-y>.small-4{height:calc(33.33333% - 1.875rem)}.grid-margin-y>.small-5{height:calc(41.66667% - 1.875rem)}.grid-margin-y>.small-6{height:calc(50% - 1.875rem)}.grid-margin-y>.small-7{height:calc(58.33333% - 1.875rem)}.grid-margin-y>.small-8{height:calc(66.66667% - 1.875rem)}.grid-margin-y>.small-9{height:calc(75% - 1.875rem)}.grid-margin-y>.small-10{height:calc(83.33333% - 1.875rem)}.grid-margin-y>.small-11{height:calc(91.66667% - 1.875rem)}.grid-margin-y>.small-12{height:calc(100% - 1.875rem)}.grid-margin-y>.medium-auto{height:auto}.grid-margin-y>.medium-shrink{height:auto}.grid-margin-y>.medium-1{height:calc(8.33333% - 1.875rem)}.grid-margin-y>.medium-2{height:calc(16.66667% - 1.875rem)}.grid-margin-y>.medium-3{height:calc(25% - 1.875rem)}.grid-margin-y>.medium-4{height:calc(33.33333% - 1.875rem)}.grid-margin-y>.medium-5{height:calc(41.66667% - 1.875rem)}.grid-margin-y>.medium-6{height:calc(50% - 1.875rem)}.grid-margin-y>.medium-7{height:calc(58.33333% - 1.875rem)}.grid-margin-y>.medium-8{height:calc(66.66667% - 1.875rem)}.grid-margin-y>.medium-9{height:calc(75% - 1.875rem)}.grid-margin-y>.medium-10{height:calc(83.33333% - 1.875rem)}.grid-margin-y>.medium-11{height:calc(91.66667% - 1.875rem)}.grid-margin-y>.medium-12{height:calc(100% - 1.875rem)}}@media print,screen and (min-width:64em){.grid-margin-y>.large-auto{height:auto}.grid-margin-y>.large-shrink{height:auto}.grid-margin-y>.large-1{height:calc(8.33333% - 1.875rem)}.grid-margin-y>.large-2{height:calc(16.66667% - 1.875rem)}.grid-margin-y>.large-3{height:calc(25% - 1.875rem)}.grid-margin-y>.large-4{height:calc(33.33333% - 1.875rem)}.grid-margin-y>.large-5{height:calc(41.66667% - 1.875rem)}.grid-margin-y>.large-6{height:calc(50% - 1.875rem)}.grid-margin-y>.large-7{height:calc(58.33333% - 1.875rem)}.grid-margin-y>.large-8{height:calc(66.66667% - 1.875rem)}.grid-margin-y>.large-9{height:calc(75% - 1.875rem)}.grid-margin-y>.large-10{height:calc(83.33333% - 1.875rem)}.grid-margin-y>.large-11{height:calc(91.66667% - 1.875rem)}.grid-margin-y>.large-12{height:calc(100% - 1.875rem)}}.grid-frame.grid-margin-y{height:calc(100vh + 1.25rem)}@media print,screen and (min-width:40em){.grid-frame.grid-margin-y{height:calc(100vh + 1.875rem)}}@media print,screen and (min-width:64em){.grid-frame.grid-margin-y{height:calc(100vh + 1.875rem)}}@media print,screen and (min-width:40em){.grid-margin-y.medium-grid-frame{height:calc(100vh + 1.875rem)}}@media print,screen and (min-width:64em){.grid-margin-y.large-grid-frame{height:calc(100vh + 1.875rem)}}.button{-webkit-appearance:none;border:1px solid transparent;border-radius:0;cursor:pointer;display:inline-block;font-family:inherit;font-size:.9rem;line-height:1;margin:0 0 1rem;padding:.85em 1em;text-align:center;-webkit-transition:background-color .25s ease-out,color .25s ease-out;transition:background-color .25s ease-out,color .25s ease-out;vertical-align:middle}[data-whatinput=mouse] .button{outline:0}.button.tiny{font-size:.6rem}.button.small{font-size:.75rem}.button.large{font-size:1.25rem}.button.expanded{display:block;margin-left:0;margin-right:0;width:100%}.button,.button.disabled,.button.disabled:focus,.button.disabled:hover,.button[disabled],.button[disabled]:focus,.button[disabled]:hover{background-color:#1779ba;color:#fefefe}.button:focus,.button:hover{background-color:#14679e;color:#fefefe}.button.primary,.button.primary.disabled,.button.primary.disabled:focus,.button.primary.disabled:hover,.button.primary[disabled],.button.primary[disabled]:focus,.button.primary[disabled]:hover{background-color:#1779ba;color:#fefefe}.button.primary:focus,.button.primary:hover{background-color:#126195;color:#fefefe}.button.secondary,.button.secondary.disabled,.button.secondary.disabled:focus,.button.secondary.disabled:hover,.button.secondary[disabled],.button.secondary[disabled]:focus,.button.secondary[disabled]:hover{background-color:#767676;color:#fefefe}.button.secondary:focus,.button.secondary:hover{background-color:#5e5e5e;color:#fefefe}.button.success,.button.success.disabled,.button.success.disabled:focus,.button.success.disabled:hover,.button.success[disabled],.button.success[disabled]:focus,.button.success[disabled]:hover{background-color:#3adb76;color:#0a0a0a}.button.success:focus,.button.success:hover{background-color:#22bb5b;color:#0a0a0a}.button.warning,.button.warning.disabled,.button.warning.disabled:focus,.button.warning.disabled:hover,.button.warning[disabled],.button.warning[disabled]:focus,.button.warning[disabled]:hover{background-color:#ffae00;color:#0a0a0a}.button.warning:focus,.button.warning:hover{background-color:#cc8b00;color:#0a0a0a}.button.alert,.button.alert.disabled,.button.alert.disabled:focus,.button.alert.disabled:hover,.button.alert[disabled],.button.alert[disabled]:focus,.button.alert[disabled]:hover{background-color:#cc4b37;color:#fefefe}.button.alert:focus,.button.alert:hover{background-color:#a53b2a;color:#fefefe}.button.hollow,.button.hollow.disabled,.button.hollow.disabled:focus,.button.hollow.disabled:hover,.button.hollow:focus,.button.hollow:hover,.button.hollow[disabled],.button.hollow[disabled]:focus,.button.hollow[disabled]:hover{background-color:transparent}.button.hollow,.button.hollow.disabled,.button.hollow.disabled:focus,.button.hollow.disabled:hover,.button.hollow[disabled],.button.hollow[disabled]:focus,.button.hollow[disabled]:hover{border:1px solid #1779ba;color:#1779ba}.button.hollow:focus,.button.hollow:hover{border-color:#0c3d5d;color:#0c3d5d}.button.hollow.primary,.button.hollow.primary.disabled,.button.hollow.primary.disabled:focus,.button.hollow.primary.disabled:hover,.button.hollow.primary[disabled],.button.hollow.primary[disabled]:focus,.button.hollow.primary[disabled]:hover{border:1px solid #1779ba;color:#1779ba}.button.hollow.primary:focus,.button.hollow.primary:hover{border-color:#0c3d5d;color:#0c3d5d}.button.hollow.secondary,.button.hollow.secondary.disabled,.button.hollow.secondary.disabled:focus,.button.hollow.secondary.disabled:hover,.button.hollow.secondary[disabled],.button.hollow.secondary[disabled]:focus,.button.hollow.secondary[disabled]:hover{border:1px solid #767676;color:#767676}.button.hollow.secondary:focus,.button.hollow.secondary:hover{border-color:#3b3b3b;color:#3b3b3b}.button.hollow.success,.button.hollow.success.disabled,.button.hollow.success.disabled:focus,.button.hollow.success.disabled:hover,.button.hollow.success[disabled],.button.hollow.success[disabled]:focus,.button.hollow.success[disabled]:hover{border:1px solid #3adb76;color:#3adb76}.button.hollow.success:focus,.button.hollow.success:hover{border-color:#157539;color:#157539}.button.hollow.warning,.button.hollow.warning.disabled,.button.hollow.warning.disabled:focus,.button.hollow.warning.disabled:hover,.button.hollow.warning[disabled],.button.hollow.warning[disabled]:focus,.button.hollow.warning[disabled]:hover{border:1px solid #ffae00;color:#ffae00}.button.hollow.warning:focus,.button.hollow.warning:hover{border-color:#805700;color:#805700}.button.hollow.alert,.button.hollow.alert.disabled,.button.hollow.alert.disabled:focus,.button.hollow.alert.disabled:hover,.button.hollow.alert[disabled],.button.hollow.alert[disabled]:focus,.button.hollow.alert[disabled]:hover{border:1px solid #cc4b37;color:#cc4b37}.button.hollow.alert:focus,.button.hollow.alert:hover{border-color:#67251a;color:#67251a}.button.clear,.button.clear.disabled,.button.clear.disabled:focus,.button.clear.disabled:hover,.button.clear:focus,.button.clear:hover,.button.clear[disabled],.button.clear[disabled]:focus,.button.clear[disabled]:hover{background-color:transparent;border-color:transparent}.button.clear,.button.clear.disabled,.button.clear.disabled:focus,.button.clear.disabled:hover,.button.clear[disabled],.button.clear[disabled]:focus,.button.clear[disabled]:hover{color:#1779ba}.button.clear:focus,.button.clear:hover{color:#0c3d5d}.button.clear.primary,.button.clear.primary.disabled,.button.clear.primary.disabled:focus,.button.clear.primary.disabled:hover,.button.clear.primary[disabled],.button.clear.primary[disabled]:focus,.button.clear.primary[disabled]:hover{color:#1779ba}.button.clear.primary:focus,.button.clear.primary:hover{color:#0c3d5d}.button.clear.secondary,.button.clear.secondary.disabled,.button.clear.secondary.disabled:focus,.button.clear.secondary.disabled:hover,.button.clear.secondary[disabled],.button.clear.secondary[disabled]:focus,.button.clear.secondary[disabled]:hover{color:#767676}.button.clear.secondary:focus,.button.clear.secondary:hover{color:#3b3b3b}.button.clear.success,.button.clear.success.disabled,.button.clear.success.disabled:focus,.button.clear.success.disabled:hover,.button.clear.success[disabled],.button.clear.success[disabled]:focus,.button.clear.success[disabled]:hover{color:#3adb76}.button.clear.success:focus,.button.clear.success:hover{color:#157539}.button.clear.warning,.button.clear.warning.disabled,.button.clear.warning.disabled:focus,.button.clear.warning.disabled:hover,.button.clear.warning[disabled],.button.clear.warning[disabled]:focus,.button.clear.warning[disabled]:hover{color:#ffae00}.button.clear.warning:focus,.button.clear.warning:hover{color:#805700}.button.clear.alert,.button.clear.alert.disabled,.button.clear.alert.disabled:focus,.button.clear.alert.disabled:hover,.button.clear.alert[disabled],.button.clear.alert[disabled]:focus,.button.clear.alert[disabled]:hover{color:#cc4b37}.button.clear.alert:focus,.button.clear.alert:hover{color:#67251a}.button.disabled,.button[disabled]{cursor:not-allowed;opacity:.25}.button.dropdown:after{border-color:#fefefe transparent transparent;border-style:solid;border-width:.4em .4em 0;content:"";display:block;display:inline-block;float:right;height:0;margin-left:1em;position:relative;top:.4em;width:0}.button.dropdown.clear:after,.button.dropdown.hollow:after{border-top-color:#1779ba}.button.dropdown.clear.primary:after,.button.dropdown.hollow.primary:after{border-top-color:#1779ba}.button.dropdown.clear.secondary:after,.button.dropdown.hollow.secondary:after{border-top-color:#767676}.button.dropdown.clear.success:after,.button.dropdown.hollow.success:after{border-top-color:#3adb76}.button.dropdown.clear.warning:after,.button.dropdown.hollow.warning:after{border-top-color:#ffae00}.button.dropdown.clear.alert:after,.button.dropdown.hollow.alert:after{border-top-color:#cc4b37}.button.arrow-only:after{float:none;margin-left:0;top:-.1em}a.button:focus,a.button:hover{text-decoration:none}.button-group{-webkit-box-align:stretch;-ms-flex-align:stretch;-webkit-box-flex:1;-ms-flex-positive:1;-webkit-align-items:stretch;align-items:stretch;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-grow:1;flex-grow:1;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;margin-bottom:1rem}.button-group:after,.button-group:before{-ms-flex-preferred-size:0;-webkit-box-ordinal-group:2;-ms-flex-order:1;content:" ";display:table;-webkit-flex-basis:0;flex-basis:0;-webkit-order:1;order:1}.button-group:after{clear:both}.button-group:after,.button-group:before{display:none}.button-group .button{-webkit-box-flex:0;-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto;font-size:.9rem;margin:0 1px 1px 0}.button-group .button:last-child{margin-right:0}.button-group.tiny .button{font-size:.6rem}.button-group.small .button{font-size:.75rem}.button-group.large .button{font-size:1.25rem}.button-group.expanded .button{-webkit-box-flex:1;-webkit-flex:1 1 0px;-ms-flex:1 1 0px;flex:1 1 0px}.button-group.primary .button,.button-group.primary .button.disabled,.button-group.primary .button.disabled:focus,.button-group.primary .button.disabled:hover,.button-group.primary .button[disabled],.button-group.primary .button[disabled]:focus,.button-group.primary .button[disabled]:hover{background-color:#1779ba;color:#fefefe}.button-group.primary .button:focus,.button-group.primary .button:hover{background-color:#126195;color:#fefefe}.button-group.secondary .button,.button-group.secondary .button.disabled,.button-group.secondary .button.disabled:focus,.button-group.secondary .button.disabled:hover,.button-group.secondary .button[disabled],.button-group.secondary .button[disabled]:focus,.button-group.secondary .button[disabled]:hover{background-color:#767676;color:#fefefe}.button-group.secondary .button:focus,.button-group.secondary .button:hover{background-color:#5e5e5e;color:#fefefe}.button-group.success .button,.button-group.success .button.disabled,.button-group.success .button.disabled:focus,.button-group.success .button.disabled:hover,.button-group.success .button[disabled],.button-group.success .button[disabled]:focus,.button-group.success .button[disabled]:hover{background-color:#3adb76;color:#0a0a0a}.button-group.success .button:focus,.button-group.success .button:hover{background-color:#22bb5b;color:#0a0a0a}.button-group.warning .button,.button-group.warning .button.disabled,.button-group.warning .button.disabled:focus,.button-group.warning .button.disabled:hover,.button-group.warning .button[disabled],.button-group.warning .button[disabled]:focus,.button-group.warning .button[disabled]:hover{background-color:#ffae00;color:#0a0a0a}.button-group.warning .button:focus,.button-group.warning .button:hover{background-color:#cc8b00;color:#0a0a0a}.button-group.alert .button,.button-group.alert .button.disabled,.button-group.alert .button.disabled:focus,.button-group.alert .button.disabled:hover,.button-group.alert .button[disabled],.button-group.alert .button[disabled]:focus,.button-group.alert .button[disabled]:hover{background-color:#cc4b37;color:#fefefe}.button-group.alert .button:focus,.button-group.alert .button:hover{background-color:#a53b2a;color:#fefefe}.button-group.hollow .button,.button-group.hollow .button.disabled,.button-group.hollow .button.disabled:focus,.button-group.hollow .button.disabled:hover,.button-group.hollow .button:focus,.button-group.hollow .button:hover,.button-group.hollow .button[disabled],.button-group.hollow .button[disabled]:focus,.button-group.hollow .button[disabled]:hover{background-color:transparent}.button-group.hollow .button,.button-group.hollow .button.disabled,.button-group.hollow .button.disabled:focus,.button-group.hollow .button.disabled:hover,.button-group.hollow .button[disabled],.button-group.hollow .button[disabled]:focus,.button-group.hollow .button[disabled]:hover{border:1px solid #1779ba;color:#1779ba}.button-group.hollow .button:focus,.button-group.hollow .button:hover{border-color:#0c3d5d;color:#0c3d5d}.button-group.hollow .button.primary,.button-group.hollow .button.primary.disabled,.button-group.hollow .button.primary.disabled:focus,.button-group.hollow .button.primary.disabled:hover,.button-group.hollow .button.primary[disabled],.button-group.hollow .button.primary[disabled]:focus,.button-group.hollow .button.primary[disabled]:hover,.button-group.hollow.primary .button,.button-group.hollow.primary .button.disabled,.button-group.hollow.primary .button.disabled:focus,.button-group.hollow.primary .button.disabled:hover,.button-group.hollow.primary .button[disabled],.button-group.hollow.primary .button[disabled]:focus,.button-group.hollow.primary .button[disabled]:hover{border:1px solid #1779ba;color:#1779ba}.button-group.hollow .button.primary:focus,.button-group.hollow .button.primary:hover,.button-group.hollow.primary .button:focus,.button-group.hollow.primary .button:hover{border-color:#0c3d5d;color:#0c3d5d}.button-group.hollow .button.secondary,.button-group.hollow .button.secondary.disabled,.button-group.hollow .button.secondary.disabled:focus,.button-group.hollow .button.secondary.disabled:hover,.button-group.hollow .button.secondary[disabled],.button-group.hollow .button.secondary[disabled]:focus,.button-group.hollow .button.secondary[disabled]:hover,.button-group.hollow.secondary .button,.button-group.hollow.secondary .button.disabled,.button-group.hollow.secondary .button.disabled:focus,.button-group.hollow.secondary .button.disabled:hover,.button-group.hollow.secondary .button[disabled],.button-group.hollow.secondary .button[disabled]:focus,.button-group.hollow.secondary .button[disabled]:hover{border:1px solid #767676;color:#767676}.button-group.hollow .button.secondary:focus,.button-group.hollow .button.secondary:hover,.button-group.hollow.secondary .button:focus,.button-group.hollow.secondary .button:hover{border-color:#3b3b3b;color:#3b3b3b}.button-group.hollow .button.success,.button-group.hollow .button.success.disabled,.button-group.hollow .button.success.disabled:focus,.button-group.hollow .button.success.disabled:hover,.button-group.hollow .button.success[disabled],.button-group.hollow .button.success[disabled]:focus,.button-group.hollow .button.success[disabled]:hover,.button-group.hollow.success .button,.button-group.hollow.success .button.disabled,.button-group.hollow.success .button.disabled:focus,.button-group.hollow.success .button.disabled:hover,.button-group.hollow.success .button[disabled],.button-group.hollow.success .button[disabled]:focus,.button-group.hollow.success .button[disabled]:hover{border:1px solid #3adb76;color:#3adb76}.button-group.hollow .button.success:focus,.button-group.hollow .button.success:hover,.button-group.hollow.success .button:focus,.button-group.hollow.success .button:hover{border-color:#157539;color:#157539}.button-group.hollow .button.warning,.button-group.hollow .button.warning.disabled,.button-group.hollow .button.warning.disabled:focus,.button-group.hollow .button.warning.disabled:hover,.button-group.hollow .button.warning[disabled],.button-group.hollow .button.warning[disabled]:focus,.button-group.hollow .button.warning[disabled]:hover,.button-group.hollow.warning .button,.button-group.hollow.warning .button.disabled,.button-group.hollow.warning .button.disabled:focus,.button-group.hollow.warning .button.disabled:hover,.button-group.hollow.warning .button[disabled],.button-group.hollow.warning .button[disabled]:focus,.button-group.hollow.warning .button[disabled]:hover{border:1px solid #ffae00;color:#ffae00}.button-group.hollow .button.warning:focus,.button-group.hollow .button.warning:hover,.button-group.hollow.warning .button:focus,.button-group.hollow.warning .button:hover{border-color:#805700;color:#805700}.button-group.hollow.alert .button,.button-group.hollow.alert .button.disabled,.button-group.hollow.alert .button.disabled:focus,.button-group.hollow.alert .button.disabled:hover,.button-group.hollow.alert .button[disabled],.button-group.hollow.alert .button[disabled]:focus,.button-group.hollow.alert .button[disabled]:hover,.button-group.hollow .button.alert,.button-group.hollow .button.alert.disabled,.button-group.hollow .button.alert.disabled:focus,.button-group.hollow .button.alert.disabled:hover,.button-group.hollow .button.alert[disabled],.button-group.hollow .button.alert[disabled]:focus,.button-group.hollow .button.alert[disabled]:hover{border:1px solid #cc4b37;color:#cc4b37}.button-group.hollow.alert .button:focus,.button-group.hollow.alert .button:hover,.button-group.hollow .button.alert:focus,.button-group.hollow .button.alert:hover{border-color:#67251a;color:#67251a}.button-group.clear .button,.button-group.clear .button.disabled,.button-group.clear .button.disabled:focus,.button-group.clear .button.disabled:hover,.button-group.clear .button:focus,.button-group.clear .button:hover,.button-group.clear .button[disabled],.button-group.clear .button[disabled]:focus,.button-group.clear .button[disabled]:hover{background-color:transparent;border-color:transparent}.button-group.clear .button,.button-group.clear .button.disabled,.button-group.clear .button.disabled:focus,.button-group.clear .button.disabled:hover,.button-group.clear .button[disabled],.button-group.clear .button[disabled]:focus,.button-group.clear .button[disabled]:hover{color:#1779ba}.button-group.clear .button:focus,.button-group.clear .button:hover{color:#0c3d5d}.button-group.clear .button.primary,.button-group.clear .button.primary.disabled,.button-group.clear .button.primary.disabled:focus,.button-group.clear .button.primary.disabled:hover,.button-group.clear .button.primary[disabled],.button-group.clear .button.primary[disabled]:focus,.button-group.clear .button.primary[disabled]:hover,.button-group.clear.primary .button,.button-group.clear.primary .button.disabled,.button-group.clear.primary .button.disabled:focus,.button-group.clear.primary .button.disabled:hover,.button-group.clear.primary .button[disabled],.button-group.clear.primary .button[disabled]:focus,.button-group.clear.primary .button[disabled]:hover{color:#1779ba}.button-group.clear .button.primary:focus,.button-group.clear .button.primary:hover,.button-group.clear.primary .button:focus,.button-group.clear.primary .button:hover{color:#0c3d5d}.button-group.clear .button.secondary,.button-group.clear .button.secondary.disabled,.button-group.clear .button.secondary.disabled:focus,.button-group.clear .button.secondary.disabled:hover,.button-group.clear .button.secondary[disabled],.button-group.clear .button.secondary[disabled]:focus,.button-group.clear .button.secondary[disabled]:hover,.button-group.clear.secondary .button,.button-group.clear.secondary .button.disabled,.button-group.clear.secondary .button.disabled:focus,.button-group.clear.secondary .button.disabled:hover,.button-group.clear.secondary .button[disabled],.button-group.clear.secondary .button[disabled]:focus,.button-group.clear.secondary .button[disabled]:hover{color:#767676}.button-group.clear .button.secondary:focus,.button-group.clear .button.secondary:hover,.button-group.clear.secondary .button:focus,.button-group.clear.secondary .button:hover{color:#3b3b3b}.button-group.clear .button.success,.button-group.clear .button.success.disabled,.button-group.clear .button.success.disabled:focus,.button-group.clear .button.success.disabled:hover,.button-group.clear .button.success[disabled],.button-group.clear .button.success[disabled]:focus,.button-group.clear .button.success[disabled]:hover,.button-group.clear.success .button,.button-group.clear.success .button.disabled,.button-group.clear.success .button.disabled:focus,.button-group.clear.success .button.disabled:hover,.button-group.clear.success .button[disabled],.button-group.clear.success .button[disabled]:focus,.button-group.clear.success .button[disabled]:hover{color:#3adb76}.button-group.clear .button.success:focus,.button-group.clear .button.success:hover,.button-group.clear.success .button:focus,.button-group.clear.success .button:hover{color:#157539}.button-group.clear .button.warning,.button-group.clear .button.warning.disabled,.button-group.clear .button.warning.disabled:focus,.button-group.clear .button.warning.disabled:hover,.button-group.clear .button.warning[disabled],.button-group.clear .button.warning[disabled]:focus,.button-group.clear .button.warning[disabled]:hover,.button-group.clear.warning .button,.button-group.clear.warning .button.disabled,.button-group.clear.warning .button.disabled:focus,.button-group.clear.warning .button.disabled:hover,.button-group.clear.warning .button[disabled],.button-group.clear.warning .button[disabled]:focus,.button-group.clear.warning .button[disabled]:hover{color:#ffae00}.button-group.clear .button.warning:focus,.button-group.clear .button.warning:hover,.button-group.clear.warning .button:focus,.button-group.clear.warning .button:hover{color:#805700}.button-group.clear.alert .button,.button-group.clear.alert .button.disabled,.button-group.clear.alert .button.disabled:focus,.button-group.clear.alert .button.disabled:hover,.button-group.clear.alert .button[disabled],.button-group.clear.alert .button[disabled]:focus,.button-group.clear.alert .button[disabled]:hover,.button-group.clear .button.alert,.button-group.clear .button.alert.disabled,.button-group.clear .button.alert.disabled:focus,.button-group.clear .button.alert.disabled:hover,.button-group.clear .button.alert[disabled],.button-group.clear .button.alert[disabled]:focus,.button-group.clear .button.alert[disabled]:hover{color:#cc4b37}.button-group.clear.alert .button:focus,.button-group.clear.alert .button:hover,.button-group.clear .button.alert:focus,.button-group.clear .button.alert:hover{color:#67251a}.button-group.no-gaps .button{margin-right:-.0625rem}.button-group.no-gaps .button+.button{border-left-color:transparent}.button-group.stacked,.button-group.stacked-for-medium,.button-group.stacked-for-small{-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap}.button-group.stacked-for-medium .button,.button-group.stacked-for-small .button,.button-group.stacked .button{-webkit-box-flex:0;-webkit-flex:0 0 100%;-ms-flex:0 0 100%;flex:0 0 100%}.button-group.stacked-for-medium .button:last-child,.button-group.stacked-for-small .button:last-child,.button-group.stacked .button:last-child{margin-bottom:0}.button-group.stacked-for-medium.expanded .button,.button-group.stacked-for-small.expanded .button,.button-group.stacked.expanded .button{-webkit-box-flex:1;-webkit-flex:1 1 0px;-ms-flex:1 1 0px;flex:1 1 0px}@media print,screen and (min-width:40em){.button-group.stacked-for-small .button{-webkit-box-flex:0;-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto;margin-bottom:0}}@media print,screen and (min-width:64em){.button-group.stacked-for-medium .button{-webkit-box-flex:0;-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto;margin-bottom:0}}@media print,screen and (max-width:39.99875em){.button-group.stacked-for-small.expanded{display:block}.button-group.stacked-for-small.expanded .button{display:block;margin-right:0}}@media print,screen and (max-width:63.99875em){.button-group.stacked-for-medium.expanded{display:block}.button-group.stacked-for-medium.expanded .button{display:block;margin-right:0}}.close-button{color:#8a8a8a;cursor:pointer;position:absolute;z-index:10}[data-whatinput=mouse] .close-button{outline:0}.close-button:focus,.close-button:hover{color:#0a0a0a}.close-button.small{font-size:1.5em;line-height:1;right:.66rem;top:.33em}.close-button,.close-button.medium{font-size:2em;line-height:1;right:1rem;top:.5rem}.label{border-radius:0;cursor:default;display:inline-block;font-size:.8rem;line-height:1;padding:.33333rem .5rem;white-space:nowrap}.label,.label.primary{background:#1779ba;color:#fefefe}.label.secondary{background:#767676;color:#fefefe}.label.success{background:#3adb76;color:#0a0a0a}.label.warning{background:#ffae00;color:#0a0a0a}.label.alert{background:#cc4b37;color:#fefefe}.progress{background-color:#cacaca;border-radius:0;height:1rem;margin-bottom:1rem}.progress.primary .progress-meter{background-color:#1779ba}.progress.secondary .progress-meter{background-color:#767676}.progress.success .progress-meter{background-color:#3adb76}.progress.warning .progress-meter{background-color:#ffae00}.progress.alert .progress-meter{background-color:#cc4b37}.progress-meter{background-color:#1779ba;display:block;height:100%;position:relative;width:0}.progress-meter-text{color:#fefefe;font-size:.75rem;font-weight:700;left:50%;margin:0;position:absolute;top:50%;-webkit-transform:translate(-50%,-50%);-ms-transform:translate(-50%,-50%);transform:translate(-50%,-50%);white-space:nowrap}.slider{background-color:#e6e6e6;cursor:pointer;height:.5rem;margin-bottom:2.25rem;margin-top:1.25rem;position:relative;-ms-touch-action:none;touch-action:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.slider-fill{background-color:#cacaca;display:inline-block;height:.5rem;left:0;max-width:100%;position:absolute;top:0;-webkit-transition:all .2s ease-in-out;transition:all .2s ease-in-out}.slider-fill.is-dragging{-webkit-transition:all 0s linear;transition:all 0s linear}.slider-handle{background-color:#1779ba;border-radius:0;cursor:-webkit-grab;cursor:grab;display:inline-block;height:1.4rem;left:0;position:absolute;top:50%;-ms-touch-action:manipulation;touch-action:manipulation;-webkit-transform:translateY(-50%);-ms-transform:translateY(-50%);transform:translateY(-50%);-webkit-transition:all .2s ease-in-out;transition:all .2s ease-in-out;width:1.4rem;z-index:1}[data-whatinput=mouse] .slider-handle{outline:0}.slider-handle:hover{background-color:#14679e}.slider-handle.is-dragging{cursor:-webkit-grabbing;cursor:grabbing;-webkit-transition:all 0s linear;transition:all 0s linear}.slider.disabled,.slider[disabled]{cursor:not-allowed;opacity:.25}.slider.vertical{display:inline-block;height:12.5rem;margin:0 1.25rem;-webkit-transform:scaleY(-1);-ms-transform:scaleY(-1);transform:scaleY(-1);width:.5rem}.slider.vertical .slider-fill{max-height:100%;top:0;width:.5rem}.slider.vertical .slider-handle{height:1.4rem;left:50%;position:absolute;top:0;-webkit-transform:translateX(-50%);-ms-transform:translateX(-50%);transform:translateX(-50%);width:1.4rem}.switch{color:#fefefe;font-size:.875rem;font-weight:700;height:2rem;margin-bottom:1rem;outline:0;position:relative;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.switch-input{margin-bottom:0;opacity:0;position:absolute}.switch-paddle{background:#cacaca;border-radius:0;color:inherit;cursor:pointer;display:block;font-weight:inherit;height:2rem;position:relative;-webkit-transition:all .25s ease-out;transition:all .25s ease-out;width:4rem}input+.switch-paddle{margin:0}.switch-paddle:after{background:#fefefe;border-radius:0;content:"";display:block;height:1.5rem;left:.25rem;position:absolute;top:.25rem;-webkit-transform:translateZ(0);transform:translateZ(0);-webkit-transition:all .25s ease-out;transition:all .25s ease-out;width:1.5rem}input:checked~.switch-paddle{background:#1779ba}input:checked~.switch-paddle:after{left:2.25rem}input:disabled~.switch-paddle{cursor:not-allowed;opacity:.5}[data-whatinput=mouse] input:focus~.switch-paddle{outline:0}.switch-active,.switch-inactive{position:absolute;top:50%;-webkit-transform:translateY(-50%);-ms-transform:translateY(-50%);transform:translateY(-50%)}.switch-active{display:none;left:8%}input:checked+label>.switch-active{display:block}.switch-inactive{right:15%}input:checked+label>.switch-inactive{display:none}.switch.tiny{height:1.5rem}.switch.tiny .switch-paddle{font-size:.625rem;height:1.5rem;width:3rem}.switch.tiny .switch-paddle:after{height:1rem;left:.25rem;top:.25rem;width:1rem}.switch.tiny input:checked~.switch-paddle:after{left:1.75rem}.switch.small{height:1.75rem}.switch.small .switch-paddle{font-size:.75rem;height:1.75rem;width:3.5rem}.switch.small .switch-paddle:after{height:1.25rem;left:.25rem;top:.25rem;width:1.25rem}.switch.small input:checked~.switch-paddle:after{left:2rem}.switch.large{height:2.5rem}.switch.large .switch-paddle{font-size:1rem;height:2.5rem;width:5rem}.switch.large .switch-paddle:after{height:2rem;left:.25rem;top:.25rem;width:2rem}.switch.large input:checked~.switch-paddle:after{left:2.75rem}table{border-collapse:collapse;border-radius:0;margin-bottom:1rem;width:100%}tbody,tfoot,thead{background-color:#fefefe;border:1px solid #f1f1f1}caption{font-weight:700;padding:.5rem .625rem .625rem}thead{background:#f8f8f8}tfoot,thead{color:#0a0a0a}tfoot{background:#f1f1f1}tfoot tr,thead tr{background:0 0}tfoot td,tfoot th,thead td,thead th{font-weight:700;padding:.5rem .625rem .625rem;text-align:left}tbody td,tbody th{padding:.5rem .625rem .625rem}tbody tr:nth-child(2n){background-color:#f1f1f1;border-bottom:0}table.unstriped tbody{background-color:#fefefe}table.unstriped tbody tr{background-color:#fefefe;border-bottom:1px solid #f1f1f1}@media print,screen and (max-width:63.99875em){table.stack tfoot,table.stack thead{display:none}table.stack td,table.stack th,table.stack tr{display:block}table.stack td{border-top:0}}table.scroll{display:block;overflow-x:auto;width:100%}table.hover thead tr:hover{background-color:#f3f3f3}table.hover tfoot tr:hover{background-color:#ececec}table.hover tbody tr:hover{background-color:#f9f9f9}table.hover:not(.unstriped) tr:nth-of-type(2n):hover{background-color:#ececec}.table-scroll{overflow-x:auto}.badge{border-radius:50%;display:inline-block;font-size:.6rem;min-width:2.1em;padding:.3em;text-align:center}.badge,.badge.primary{background:#1779ba;color:#fefefe}.badge.secondary{background:#767676;color:#fefefe}.badge.success{background:#3adb76;color:#0a0a0a}.badge.warning{background:#ffae00;color:#0a0a0a}.badge.alert{background:#cc4b37;color:#fefefe}.breadcrumbs{list-style:none;margin:0 0 1rem}.breadcrumbs:after,.breadcrumbs:before{-ms-flex-preferred-size:0;-webkit-box-ordinal-group:2;-ms-flex-order:1;content:" ";display:table;-webkit-flex-basis:0;flex-basis:0;-webkit-order:1;order:1}.breadcrumbs:after{clear:both}.breadcrumbs li{color:#0a0a0a;cursor:default;float:left;font-size:.6875rem;text-transform:uppercase}.breadcrumbs li:not(:last-child):after{color:#cacaca;content:"/";margin:0 .75rem;opacity:1;position:relative}.breadcrumbs a{color:#1779ba}.breadcrumbs a:hover{text-decoration:underline}.breadcrumbs .disabled{color:#cacaca;cursor:not-allowed}.callout{background-color:#fff;border:1px solid hsla(0,0%,4%,.25);border-radius:0;color:#0a0a0a;margin:0 0 1rem;padding:1rem;position:relative}.callout>:first-child{margin-top:0}.callout>:last-child{margin-bottom:0}.callout.primary{background-color:#d7ecfa;color:#0a0a0a}.callout.secondary{background-color:#eaeaea;color:#0a0a0a}.callout.success{background-color:#e1faea;color:#0a0a0a}.callout.warning{background-color:#fff3d9;color:#0a0a0a}.callout.alert{background-color:#f7e4e1;color:#0a0a0a}.callout.small{padding:.5rem}.callout.large{padding:3rem}.card{-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-box-flex:1;-ms-flex-positive:1;background:#fefefe;border:1px solid #e6e6e6;border-radius:0;-webkit-box-shadow:none;box-shadow:none;color:#0a0a0a;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;-webkit-flex-grow:1;flex-grow:1;margin-bottom:1rem;overflow:hidden}.card>:last-child{margin-bottom:0}.card-divider{-webkit-box-flex:0;background:#e6e6e6;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex:0 1 auto;-ms-flex:0 1 auto;flex:0 1 auto;padding:1rem}.card-divider>:last-child{margin-bottom:0}.card-section{-webkit-box-flex:1;-webkit-flex:1 0 auto;-ms-flex:1 0 auto;flex:1 0 auto;padding:1rem}.card-section>:last-child{margin-bottom:0}.card-image{min-height:1px}.dropdown-pane{background-color:#fefefe;border:1px solid #cacaca;border-radius:0;display:none;font-size:1rem;padding:1rem;position:absolute;visibility:hidden;width:300px;z-index:10}.dropdown-pane.is-opening{display:block}.dropdown-pane.is-open{display:block;visibility:visible}.dropdown-pane.tiny{width:100px}.dropdown-pane.small{width:200px}.dropdown-pane.large{width:400px}.pagination{margin-bottom:1rem;margin-left:0}.pagination:after,.pagination:before{-ms-flex-preferred-size:0;-webkit-box-ordinal-group:2;-ms-flex-order:1;content:" ";display:table;-webkit-flex-basis:0;flex-basis:0;-webkit-order:1;order:1}.pagination:after{clear:both}.pagination li{border-radius:0;display:none;font-size:.875rem;margin-right:.0625rem}.pagination li:first-child,.pagination li:last-child{display:inline-block}@media print,screen and (min-width:40em){.pagination li{display:inline-block}}.pagination a,.pagination button{border-radius:0;color:#0a0a0a;display:block;padding:.1875rem .625rem}.pagination a:hover,.pagination button:hover{background:#e6e6e6}.pagination .current{background:#1779ba;color:#fefefe;cursor:default;padding:.1875rem .625rem}.pagination .disabled{color:#cacaca;cursor:not-allowed;padding:.1875rem .625rem}.pagination .disabled:hover{background:0 0}.pagination .ellipsis:after{color:#0a0a0a;content:"…";padding:.1875rem .625rem}.pagination-previous.disabled:before,.pagination-previous a:before{content:"«";display:inline-block;margin-right:.5rem}.pagination-next.disabled:after,.pagination-next a:after{content:"»";display:inline-block;margin-left:.5rem}.has-tip{border-bottom:1px dotted #8a8a8a;cursor:help;display:inline-block;font-weight:700;position:relative}.tooltip{background-color:#0a0a0a;border-radius:0;color:#fefefe;font-size:80%;max-width:10rem;padding:.75rem;position:absolute;top:calc(100% + .6495rem);z-index:1200}.tooltip:before{position:absolute}.tooltip.bottom:before{border-color:transparent transparent #0a0a0a;border-style:solid;border-width:0 .75rem .75rem;bottom:100%;content:"";display:block;height:0;width:0}.tooltip.bottom.align-center:before{left:50%;-webkit-transform:translateX(-50%);-ms-transform:translateX(-50%);transform:translateX(-50%)}.tooltip.top:before{border-color:#0a0a0a transparent transparent;border-style:solid;border-width:.75rem .75rem 0;bottom:auto;content:"";display:block;height:0;top:100%;width:0}.tooltip.top.align-center:before{left:50%;-webkit-transform:translateX(-50%);-ms-transform:translateX(-50%);transform:translateX(-50%)}.tooltip.left:before{border-color:transparent transparent transparent #0a0a0a;border-style:solid;border-width:.75rem 0 .75rem .75rem;content:"";display:block;height:0;left:100%;width:0}.tooltip.left.align-center:before{bottom:auto;top:50%;-webkit-transform:translateY(-50%);-ms-transform:translateY(-50%);transform:translateY(-50%)}.tooltip.right:before{border-color:transparent #0a0a0a transparent transparent;border-style:solid;border-width:.75rem .75rem .75rem 0;content:"";display:block;height:0;left:auto;right:100%;width:0}.tooltip.right.align-center:before{bottom:auto;top:50%;-webkit-transform:translateY(-50%);-ms-transform:translateY(-50%);transform:translateY(-50%)}.tooltip.align-top:before{bottom:auto;top:10%}.tooltip.align-bottom:before{bottom:10%;top:auto}.tooltip.align-left:before{left:10%;right:auto}.tooltip.align-right:before{left:auto;right:10%}.accordion{background:#fefefe;list-style-type:none;margin-left:0}.accordion[disabled] .accordion-title{cursor:not-allowed}.accordion-item:first-child>:first-child{border-radius:0}.accordion-item:last-child>:last-child{border-radius:0}.accordion-title{border:1px solid #e6e6e6;border-bottom:0;color:#1779ba;display:block;font-size:.75rem;line-height:1;padding:1.25rem 1rem;position:relative}:last-child:not(.is-active)>.accordion-title{border-bottom:1px solid #e6e6e6;border-radius:0}.accordion-title:focus,.accordion-title:hover{background-color:#e6e6e6}.accordion-title:before{content:"+";margin-top:-.5rem;position:absolute;right:1rem;top:50%}.is-active>.accordion-title:before{content:"–"}.accordion-content{background-color:#fefefe;border:1px solid #e6e6e6;border-bottom:0;color:#0a0a0a;display:none;padding:1rem}:last-child>.accordion-content:last-child{border-bottom:1px solid #e6e6e6}.media-object{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap;margin-bottom:1rem}.media-object img{max-width:none}@media print,screen and (max-width:39.99875em){.media-object.stack-for-small{-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap}}.media-object-section{-webkit-box-flex:0;-webkit-flex:0 1 auto;-ms-flex:0 1 auto;flex:0 1 auto}.media-object-section:first-child{padding-right:1rem}.media-object-section:last-child:not(:nth-child(2)){padding-left:1rem}.media-object-section>:last-child{margin-bottom:0}@media print,screen and (max-width:39.99875em){.stack-for-small .media-object-section{-ms-flex-preferred-size:100%;-webkit-flex-basis:100%;flex-basis:100%;max-width:100%;padding:0 0 1rem}.stack-for-small .media-object-section img{width:100%}}.media-object-section.main-section{-webkit-box-flex:1;-webkit-flex:1 1 0px;-ms-flex:1 1 0px;flex:1 1 0px}.orbit,.orbit-container{position:relative}.orbit-container{height:0;list-style:none;margin:0;overflow:hidden}.orbit-slide{position:absolute;width:100%}.orbit-slide.no-motionui.is-active{left:0;top:0}.orbit-figure{margin:0}.orbit-image{margin:0;max-width:100%;width:100%}.orbit-caption{background-color:hsla(0,0%,4%,.5);bottom:0;margin-bottom:0;width:100%}.orbit-caption,.orbit-next,.orbit-previous{color:#fefefe;padding:1rem;position:absolute}.orbit-next,.orbit-previous{top:50%;-webkit-transform:translateY(-50%);-ms-transform:translateY(-50%);transform:translateY(-50%);z-index:10}[data-whatinput=mouse] .orbit-next,[data-whatinput=mouse] .orbit-previous{outline:0}.orbit-next:active,.orbit-next:focus,.orbit-next:hover,.orbit-previous:active,.orbit-previous:focus,.orbit-previous:hover{background-color:hsla(0,0%,4%,.5)}.orbit-previous{left:0}.orbit-next{left:auto;right:0}.orbit-bullets{margin-bottom:.8rem;margin-top:.8rem;position:relative;text-align:center}[data-whatinput=mouse] .orbit-bullets{outline:0}.orbit-bullets button{background-color:#cacaca;border-radius:50%;height:1.2rem;margin:.1rem;width:1.2rem}.orbit-bullets button:hover{background-color:#8a8a8a}.orbit-bullets button.is-active{background-color:#8a8a8a}.flex-video,.responsive-embed{height:0;margin-bottom:1rem;overflow:hidden;padding-bottom:75%;position:relative}.flex-video embed,.flex-video iframe,.flex-video object,.flex-video video,.responsive-embed embed,.responsive-embed iframe,.responsive-embed object,.responsive-embed video{height:100%;left:0;position:absolute;top:0;width:100%}.flex-video.widescreen,.responsive-embed.widescreen{padding-bottom:56.25%}.tabs{background:#fefefe;border:1px solid #e6e6e6;list-style-type:none;margin:0}.tabs:after,.tabs:before{-ms-flex-preferred-size:0;-webkit-box-ordinal-group:2;-ms-flex-order:1;content:" ";display:table;-webkit-flex-basis:0;flex-basis:0;-webkit-order:1;order:1}.tabs:after{clear:both}.tabs.vertical>li{display:block;float:none;width:auto}.tabs.simple>li>a{padding:0}.tabs.simple>li>a:hover{background:0 0}.tabs.primary{background:#1779ba}.tabs.primary>li>a{color:#fefefe}.tabs.primary>li>a:focus,.tabs.primary>li>a:hover{background:#1673b1}.tabs-title{float:left}.tabs-title>a{color:#1779ba;display:block;font-size:.75rem;line-height:1;padding:1.25rem 1.5rem}[data-whatinput=mouse] .tabs-title>a{outline:0}.tabs-title>a:hover{background:#fefefe;color:#1468a0}.tabs-title>a:focus,.tabs-title>a[aria-selected=true]{background:#e6e6e6;color:#1779ba}.tabs-content{background:#fefefe;border:1px solid #e6e6e6;border-top:0;color:#0a0a0a;-webkit-transition:all .5s ease;transition:all .5s ease}.tabs-content.vertical{border:1px solid #e6e6e6;border-left:0}.tabs-panel{display:none;padding:1rem}.tabs-panel.is-active{display:block}.thumbnail{border:4px solid #fefefe;border-radius:0;-webkit-box-shadow:0 0 0 1px hsla(0,0%,4%,.2);box-shadow:0 0 0 1px hsla(0,0%,4%,.2);display:inline-block;line-height:0;margin-bottom:1rem;max-width:100%}a.thumbnail{-webkit-transition:-webkit-box-shadow .2s ease-out;transition:-webkit-box-shadow .2s ease-out;transition:box-shadow .2s ease-out;transition:box-shadow .2s ease-out,-webkit-box-shadow .2s ease-out}a.thumbnail:focus,a.thumbnail:hover{-webkit-box-shadow:0 0 6px 1px rgba(23,121,186,.5);box-shadow:0 0 6px 1px rgba(23,121,186,.5)}a.thumbnail image{-webkit-box-shadow:none;box-shadow:none}.menu{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;list-style:none;margin:0;padding:0;position:relative}[data-whatinput=mouse] .menu li{outline:0}.menu .button,.menu a{display:block;line-height:1;padding:.7rem 1rem;text-decoration:none}.menu a,.menu button,.menu input,.menu select{margin-bottom:0}.menu input{display:inline-block}.menu,.menu.horizontal{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap}.menu.vertical{-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap}.menu.vertical.icon-bottom li a i,.menu.vertical.icon-bottom li a img,.menu.vertical.icon-bottom li a svg,.menu.vertical.icon-top li a i,.menu.vertical.icon-top li a img,.menu.vertical.icon-top li a svg{text-align:left}.menu.expanded li{-webkit-box-flex:1;-webkit-flex:1 1 0px;-ms-flex:1 1 0px;flex:1 1 0px}.menu.expanded.icon-bottom li a i,.menu.expanded.icon-bottom li a img,.menu.expanded.icon-bottom li a svg,.menu.expanded.icon-top li a i,.menu.expanded.icon-top li a img,.menu.expanded.icon-top li a svg{text-align:left}.menu.simple{-webkit-box-align:center;-ms-flex-align:center;-webkit-align-items:center;align-items:center}.menu.simple li+li{margin-left:1rem}.menu.simple a{padding:0}@media print,screen and (min-width:40em){.menu.medium-horizontal{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap}.menu.medium-vertical{-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap}.menu.medium-expanded li,.menu.medium-simple li{-webkit-box-flex:1;-webkit-flex:1 1 0px;-ms-flex:1 1 0px;flex:1 1 0px}}@media print,screen and (min-width:64em){.menu.large-horizontal{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap}.menu.large-vertical{-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap}.menu.large-expanded li,.menu.large-simple li{-webkit-box-flex:1;-webkit-flex:1 1 0px;-ms-flex:1 1 0px;flex:1 1 0px}}.menu.nested{margin-left:1rem;margin-right:0}.menu.icon-bottom a,.menu.icon-left a,.menu.icon-right a,.menu.icon-top a,.menu.icons a{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex}.menu.icon-left li a,.menu.nested.icon-left li a{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-flow:row nowrap;-ms-flex-flow:row nowrap;flex-flow:row nowrap}.menu.icon-left li a i,.menu.icon-left li a img,.menu.icon-left li a svg,.menu.nested.icon-left li a i,.menu.nested.icon-left li a img,.menu.nested.icon-left li a svg{margin-right:.25rem}.menu.icon-right li a,.menu.nested.icon-right li a{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-flow:row nowrap;-ms-flex-flow:row nowrap;flex-flow:row nowrap}.menu.icon-right li a i,.menu.icon-right li a img,.menu.icon-right li a svg,.menu.nested.icon-right li a i,.menu.nested.icon-right li a img,.menu.nested.icon-right li a svg{margin-left:.25rem}.menu.icon-top li a,.menu.nested.icon-top li a{-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-flow:column nowrap;-ms-flex-flow:column nowrap;flex-flow:column nowrap}.menu.icon-top li a i,.menu.icon-top li a img,.menu.icon-top li a svg,.menu.nested.icon-top li a i,.menu.nested.icon-top li a img,.menu.nested.icon-top li a svg{-ms-flex-item-align:stretch;-webkit-align-self:stretch;align-self:stretch;margin-bottom:.25rem;text-align:center}.menu.icon-bottom li a,.menu.nested.icon-bottom li a{-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-flow:column nowrap;-ms-flex-flow:column nowrap;flex-flow:column nowrap}.menu.icon-bottom li a i,.menu.icon-bottom li a img,.menu.icon-bottom li a svg,.menu.nested.icon-bottom li a i,.menu.nested.icon-bottom li a img,.menu.nested.icon-bottom li a svg{-ms-flex-item-align:stretch;-webkit-align-self:stretch;align-self:stretch;margin-bottom:.25rem;text-align:center}.menu .is-active>a{background:#1779ba;color:#fefefe}.menu .active>a{background:#1779ba;color:#fefefe}.menu.align-left{-webkit-box-pack:start;-ms-flex-pack:start;-webkit-justify-content:flex-start;justify-content:flex-start}.menu.align-right li{-webkit-box-pack:end;-ms-flex-pack:end;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-justify-content:flex-end;justify-content:flex-end}.menu.align-right li .submenu li{-webkit-box-pack:start;-ms-flex-pack:start;-webkit-justify-content:flex-start;justify-content:flex-start}.menu.align-right.vertical li{display:block;text-align:right}.menu.align-right.icon-bottom li a i,.menu.align-right.icon-bottom li a img,.menu.align-right.icon-bottom li a svg,.menu.align-right.icon-top li a i,.menu.align-right.icon-top li a img,.menu.align-right.icon-top li a svg,.menu.align-right.vertical li .submenu li{text-align:right}.menu.align-right .nested{margin-left:0;margin-right:1rem}.menu.align-center li{-webkit-box-pack:center;-ms-flex-pack:center;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-justify-content:center;justify-content:center}.menu.align-center li .submenu li{-webkit-box-pack:start;-ms-flex-pack:start;-webkit-justify-content:flex-start;justify-content:flex-start}.menu .menu-text{color:inherit;font-weight:700;line-height:1;padding:.7rem 1rem}.menu-centered>.menu{-webkit-box-pack:center;-ms-flex-pack:center;-webkit-justify-content:center;justify-content:center}.menu-centered>.menu li{-webkit-box-pack:center;-ms-flex-pack:center;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-justify-content:center;justify-content:center}.menu-centered>.menu li .submenu li{-webkit-box-pack:start;-ms-flex-pack:start;-webkit-justify-content:flex-start;justify-content:flex-start}.no-js [data-responsive-menu] ul{display:none}.menu-icon{cursor:pointer;display:inline-block;height:16px;position:relative;vertical-align:middle;width:20px}.menu-icon:after{background:#fefefe;-webkit-box-shadow:0 7px 0 #fefefe,0 14px 0 #fefefe;box-shadow:0 7px 0 #fefefe,0 14px 0 #fefefe;content:"";display:block;height:2px;left:0;position:absolute;top:0;width:100%}.menu-icon:hover:after{background:#cacaca;-webkit-box-shadow:0 7px 0 #cacaca,0 14px 0 #cacaca;box-shadow:0 7px 0 #cacaca,0 14px 0 #cacaca}.menu-icon.dark{cursor:pointer;display:inline-block;height:16px;position:relative;vertical-align:middle;width:20px}.menu-icon.dark:after{background:#0a0a0a;-webkit-box-shadow:0 7px 0 #0a0a0a,0 14px 0 #0a0a0a;box-shadow:0 7px 0 #0a0a0a,0 14px 0 #0a0a0a;content:"";display:block;height:2px;left:0;position:absolute;top:0;width:100%}.menu-icon.dark:hover:after{background:#8a8a8a;-webkit-box-shadow:0 7px 0 #8a8a8a,0 14px 0 #8a8a8a;box-shadow:0 7px 0 #8a8a8a,0 14px 0 #8a8a8a}.accordion-menu li{width:100%}.accordion-menu .is-accordion-submenu a,.accordion-menu a{padding:.7rem 1rem}.accordion-menu .nested.is-accordion-submenu{margin-left:1rem;margin-right:0}.accordion-menu.align-right .nested.is-accordion-submenu{margin-left:0;margin-right:1rem}.accordion-menu .is-accordion-submenu-parent:not(.has-submenu-toggle)>a{position:relative}.accordion-menu .is-accordion-submenu-parent:not(.has-submenu-toggle)>a:after{border-color:#1779ba transparent transparent;border-style:solid;border-width:6px 6px 0;content:"";display:block;height:0;margin-top:-3px;position:absolute;right:1rem;top:50%;width:0}.accordion-menu.align-left .is-accordion-submenu-parent>a:after{left:auto;right:1rem}.accordion-menu.align-right .is-accordion-submenu-parent>a:after{left:1rem;right:auto}.accordion-menu .is-accordion-submenu-parent[aria-expanded=true]>a:after{-webkit-transform:rotate(180deg);-ms-transform:rotate(180deg);transform:rotate(180deg);-webkit-transform-origin:50% 50%;-ms-transform-origin:50% 50%;transform-origin:50% 50%}.is-accordion-submenu-parent{position:relative}.has-submenu-toggle>a{margin-right:40px}.submenu-toggle{cursor:pointer;height:40px;position:absolute;right:0;top:0;width:40px}.submenu-toggle:after{border-color:#1779ba transparent transparent;border-style:solid;border-width:6px 6px 0;bottom:0;content:"";display:block;height:0;margin:auto;top:0;width:0}.submenu-toggle[aria-expanded=true]:after{-webkit-transform:scaleY(-1);-ms-transform:scaleY(-1);transform:scaleY(-1);-webkit-transform-origin:50% 50%;-ms-transform-origin:50% 50%;transform-origin:50% 50%}.submenu-toggle-text{clip:rect(0,0,0,0)!important;border:0!important;height:1px!important;overflow:hidden!important;padding:0!important;position:absolute!important;white-space:nowrap!important;width:1px!important}.is-drilldown{overflow:hidden;position:relative}.is-drilldown li{display:block}.is-drilldown.animate-height{-webkit-transition:height .5s;transition:height .5s}.drilldown a{background:#fefefe;padding:.7rem 1rem}.drilldown .is-drilldown-submenu{background:#fefefe;left:100%;position:absolute;top:0;-webkit-transition:-webkit-transform .15s linear;transition:-webkit-transform .15s linear;transition:transform .15s linear;transition:transform .15s linear,-webkit-transform .15s linear;width:100%;z-index:-1}.drilldown .is-drilldown-submenu.is-active{display:block;-webkit-transform:translateX(-100%);-ms-transform:translateX(-100%);transform:translateX(-100%);z-index:1}.drilldown .is-drilldown-submenu.is-closing{-webkit-transform:translateX(100%);-ms-transform:translateX(100%);transform:translateX(100%)}.drilldown .is-drilldown-submenu a{padding:.7rem 1rem}.drilldown .nested.is-drilldown-submenu{margin-left:0;margin-right:0}.drilldown .drilldown-submenu-cover-previous{min-height:100%}.drilldown .is-drilldown-submenu-parent>a{position:relative}.drilldown .is-drilldown-submenu-parent>a:after{border-color:transparent transparent transparent #1779ba;border-style:solid;border-width:6px 0 6px 6px;content:"";display:block;height:0;margin-top:-6px;position:absolute;right:1rem;top:50%;width:0}.drilldown.align-left .is-drilldown-submenu-parent>a:after{border-color:transparent transparent transparent #1779ba;border-style:solid;border-width:6px 0 6px 6px;content:"";display:block;height:0;left:auto;right:1rem;width:0}.drilldown.align-right .is-drilldown-submenu-parent>a:after{border-color:transparent #1779ba transparent transparent;border-style:solid;border-width:6px 6px 6px 0;content:"";display:block;height:0;left:1rem;right:auto;width:0}.drilldown .js-drilldown-back>a:before{border-color:transparent #1779ba transparent transparent;border-style:solid;border-width:6px 6px 6px 0;content:"";display:block;display:inline-block;height:0;margin-right:.75rem;vertical-align:middle;width:0}.dropdown.menu>li.opens-left>.is-dropdown-submenu{left:auto;right:0;top:100%}.dropdown.menu>li.opens-right>.is-dropdown-submenu{left:0;right:auto;top:100%}.dropdown.menu>li.is-dropdown-submenu-parent>a{padding-right:1.5rem;position:relative}.dropdown.menu>li.is-dropdown-submenu-parent>a:after{border-color:#1779ba transparent transparent;border-style:solid;border-width:6px 6px 0;content:"";display:block;height:0;left:auto;margin-top:-3px;right:5px;width:0}[data-whatinput=mouse] .dropdown.menu a{outline:0}.dropdown.menu>li>a{padding:.7rem 1rem}.dropdown.menu>li.is-active>a{background:0 0;color:#1779ba}.no-js .dropdown.menu ul{display:none}.dropdown.menu .nested.is-dropdown-submenu{margin-left:0;margin-right:0}.dropdown.menu.vertical>li .is-dropdown-submenu{top:0}.dropdown.menu.vertical>li.opens-left>.is-dropdown-submenu{left:auto;right:100%;top:0}.dropdown.menu.vertical>li.opens-right>.is-dropdown-submenu{left:100%;right:auto}.dropdown.menu.vertical>li>a:after{right:14px}.dropdown.menu.vertical>li.opens-left>a:after{border-color:transparent #1779ba transparent transparent;border-style:solid;border-width:6px 6px 6px 0;content:"";display:block;height:0;left:5px;right:auto;width:0}.dropdown.menu.vertical>li.opens-right>a:after{border-color:transparent transparent transparent #1779ba;border-style:solid;border-width:6px 0 6px 6px;content:"";display:block;height:0;width:0}@media print,screen and (min-width:40em){.dropdown.menu.medium-horizontal>li.opens-left>.is-dropdown-submenu{left:auto;right:0;top:100%}.dropdown.menu.medium-horizontal>li.opens-right>.is-dropdown-submenu{left:0;right:auto;top:100%}.dropdown.menu.medium-horizontal>li.is-dropdown-submenu-parent>a{padding-right:1.5rem;position:relative}.dropdown.menu.medium-horizontal>li.is-dropdown-submenu-parent>a:after{border-color:#1779ba transparent transparent;border-style:solid;border-width:6px 6px 0;content:"";display:block;height:0;left:auto;margin-top:-3px;right:5px;width:0}.dropdown.menu.medium-vertical>li .is-dropdown-submenu{top:0}.dropdown.menu.medium-vertical>li.opens-left>.is-dropdown-submenu{left:auto;right:100%;top:0}.dropdown.menu.medium-vertical>li.opens-right>.is-dropdown-submenu{left:100%;right:auto}.dropdown.menu.medium-vertical>li>a:after{right:14px}.dropdown.menu.medium-vertical>li.opens-left>a:after{border-color:transparent #1779ba transparent transparent;border-style:solid;border-width:6px 6px 6px 0;content:"";display:block;height:0;left:5px;right:auto;width:0}.dropdown.menu.medium-vertical>li.opens-right>a:after{border-color:transparent transparent transparent #1779ba;border-style:solid;border-width:6px 0 6px 6px;content:"";display:block;height:0;width:0}}@media print,screen and (min-width:64em){.dropdown.menu.large-horizontal>li.opens-left>.is-dropdown-submenu{left:auto;right:0;top:100%}.dropdown.menu.large-horizontal>li.opens-right>.is-dropdown-submenu{left:0;right:auto;top:100%}.dropdown.menu.large-horizontal>li.is-dropdown-submenu-parent>a{padding-right:1.5rem;position:relative}.dropdown.menu.large-horizontal>li.is-dropdown-submenu-parent>a:after{border-color:#1779ba transparent transparent;border-style:solid;border-width:6px 6px 0;content:"";display:block;height:0;left:auto;margin-top:-3px;right:5px;width:0}.dropdown.menu.large-vertical>li .is-dropdown-submenu{top:0}.dropdown.menu.large-vertical>li.opens-left>.is-dropdown-submenu{left:auto;right:100%;top:0}.dropdown.menu.large-vertical>li.opens-right>.is-dropdown-submenu{left:100%;right:auto}.dropdown.menu.large-vertical>li>a:after{right:14px}.dropdown.menu.large-vertical>li.opens-left>a:after{border-color:transparent #1779ba transparent transparent;border-style:solid;border-width:6px 6px 6px 0;content:"";display:block;height:0;left:5px;right:auto;width:0}.dropdown.menu.large-vertical>li.opens-right>a:after{border-color:transparent transparent transparent #1779ba;border-style:solid;border-width:6px 0 6px 6px;content:"";display:block;height:0;width:0}}.dropdown.menu.align-right .is-dropdown-submenu.first-sub{left:auto;right:0;top:100%}.is-dropdown-menu.vertical{width:100px}.is-dropdown-menu.vertical.align-right{float:right}.is-dropdown-submenu-parent{position:relative}.is-dropdown-submenu-parent a:after{left:auto;margin-top:-6px;position:absolute;right:5px;top:50%}.is-dropdown-submenu-parent.opens-inner>.is-dropdown-submenu{left:auto;top:100%}.is-dropdown-submenu-parent.opens-left>.is-dropdown-submenu{left:auto;right:100%}.is-dropdown-submenu-parent.opens-right>.is-dropdown-submenu{left:100%;right:auto}.is-dropdown-submenu{background:#fefefe;border:1px solid #cacaca;display:none;left:100%;min-width:200px;position:absolute;top:0;z-index:1}.dropdown .is-dropdown-submenu a{padding:.7rem 1rem}.is-dropdown-submenu .is-dropdown-submenu-parent>a:after{right:14px}.is-dropdown-submenu .is-dropdown-submenu-parent.opens-left>a:after{border-color:transparent #1779ba transparent transparent;border-style:solid;border-width:6px 6px 6px 0;content:"";display:block;height:0;left:5px;right:auto;width:0}.is-dropdown-submenu .is-dropdown-submenu-parent.opens-right>a:after{border-color:transparent transparent transparent #1779ba;border-style:solid;border-width:6px 0 6px 6px;content:"";display:block;height:0;width:0}.is-dropdown-submenu .is-dropdown-submenu{margin-top:-1px}.is-dropdown-submenu>li{width:100%}.is-dropdown-submenu.js-dropdown-active{display:block}.is-off-canvas-open{overflow:hidden}.js-off-canvas-overlay{background:hsla(0,0%,100%,.25);height:100%;left:0;opacity:0;overflow:hidden;position:absolute;top:0;-webkit-transition:opacity .5s ease,visibility .5s ease;transition:opacity .5s ease,visibility .5s ease;visibility:hidden;width:100%;z-index:11}.js-off-canvas-overlay.is-visible{opacity:1;visibility:visible}.js-off-canvas-overlay.is-closable{cursor:pointer}.js-off-canvas-overlay.is-overlay-absolute{position:absolute}.js-off-canvas-overlay.is-overlay-fixed{position:fixed}.off-canvas-wrapper{overflow:hidden;position:relative}.off-canvas{-webkit-backface-visibility:hidden;backface-visibility:hidden;background:#e6e6e6;position:fixed;-webkit-transition:-webkit-transform .5s ease;transition:-webkit-transform .5s ease;transition:transform .5s ease;transition:transform .5s ease,-webkit-transform .5s ease;z-index:12}[data-whatinput=mouse] .off-canvas{outline:0}.off-canvas.is-transition-push{z-index:12}.off-canvas.is-closed{visibility:hidden}.off-canvas.is-transition-overlap{z-index:13}.off-canvas.is-transition-overlap.is-open{-webkit-box-shadow:0 0 10px hsla(0,0%,4%,.7);box-shadow:0 0 10px hsla(0,0%,4%,.7)}.off-canvas.is-open{-webkit-transform:translate(0);-ms-transform:translate(0);transform:translate(0)}.off-canvas-absolute{-webkit-backface-visibility:hidden;backface-visibility:hidden;background:#e6e6e6;position:absolute;-webkit-transition:-webkit-transform .5s ease;transition:-webkit-transform .5s ease;transition:transform .5s ease;transition:transform .5s ease,-webkit-transform .5s ease;z-index:12}[data-whatinput=mouse] .off-canvas-absolute{outline:0}.off-canvas-absolute.is-transition-push{z-index:12}.off-canvas-absolute.is-closed{visibility:hidden}.off-canvas-absolute.is-transition-overlap{z-index:13}.off-canvas-absolute.is-transition-overlap.is-open{-webkit-box-shadow:0 0 10px hsla(0,0%,4%,.7);box-shadow:0 0 10px hsla(0,0%,4%,.7)}.off-canvas-absolute.is-open{-webkit-transform:translate(0);-ms-transform:translate(0);transform:translate(0)}.position-left{-webkit-overflow-scrolling:touch;height:100%;left:0;overflow-y:auto;top:0;width:250px}.off-canvas-content .off-canvas.position-left,.position-left{-webkit-transform:translateX(-250px);-ms-transform:translateX(-250px);transform:translateX(-250px)}.off-canvas-content .off-canvas.position-left.is-transition-overlap.is-open{-webkit-transform:translate(0);-ms-transform:translate(0);transform:translate(0)}.off-canvas-content.is-open-left.has-transition-push{-webkit-transform:translateX(250px);-ms-transform:translateX(250px);transform:translateX(250px)}.position-left.is-transition-push{-webkit-box-shadow:inset -13px 0 20px -13px hsla(0,0%,4%,.25);box-shadow:inset -13px 0 20px -13px hsla(0,0%,4%,.25)}.position-right{-webkit-overflow-scrolling:touch;height:100%;overflow-y:auto;right:0;top:0;width:250px}.off-canvas-content .off-canvas.position-right,.position-right{-webkit-transform:translateX(250px);-ms-transform:translateX(250px);transform:translateX(250px)}.off-canvas-content .off-canvas.position-right.is-transition-overlap.is-open{-webkit-transform:translate(0);-ms-transform:translate(0);transform:translate(0)}.off-canvas-content.is-open-right.has-transition-push{-webkit-transform:translateX(-250px);-ms-transform:translateX(-250px);transform:translateX(-250px)}.position-right.is-transition-push{-webkit-box-shadow:inset 13px 0 20px -13px hsla(0,0%,4%,.25);box-shadow:inset 13px 0 20px -13px hsla(0,0%,4%,.25)}.position-top{-webkit-overflow-scrolling:touch;height:250px;left:0;overflow-x:auto;top:0;width:100%}.off-canvas-content .off-canvas.position-top,.position-top{-webkit-transform:translateY(-250px);-ms-transform:translateY(-250px);transform:translateY(-250px)}.off-canvas-content .off-canvas.position-top.is-transition-overlap.is-open{-webkit-transform:translate(0);-ms-transform:translate(0);transform:translate(0)}.off-canvas-content.is-open-top.has-transition-push{-webkit-transform:translateY(250px);-ms-transform:translateY(250px);transform:translateY(250px)}.position-top.is-transition-push{-webkit-box-shadow:inset 0 -13px 20px -13px hsla(0,0%,4%,.25);box-shadow:inset 0 -13px 20px -13px hsla(0,0%,4%,.25)}.position-bottom{-webkit-overflow-scrolling:touch;bottom:0;height:250px;left:0;overflow-x:auto;width:100%}.off-canvas-content .off-canvas.position-bottom,.position-bottom{-webkit-transform:translateY(250px);-ms-transform:translateY(250px);transform:translateY(250px)}.off-canvas-content .off-canvas.position-bottom.is-transition-overlap.is-open{-webkit-transform:translate(0);-ms-transform:translate(0);transform:translate(0)}.off-canvas-content.is-open-bottom.has-transition-push{-webkit-transform:translateY(-250px);-ms-transform:translateY(-250px);transform:translateY(-250px)}.position-bottom.is-transition-push{-webkit-box-shadow:inset 0 13px 20px -13px hsla(0,0%,4%,.25);box-shadow:inset 0 13px 20px -13px hsla(0,0%,4%,.25)}.off-canvas-content{-webkit-backface-visibility:hidden;backface-visibility:hidden;-webkit-transform:none;-ms-transform:none;transform:none}.off-canvas-content.has-transition-overlap,.off-canvas-content.has-transition-push{-webkit-transition:-webkit-transform .5s ease;transition:-webkit-transform .5s ease;transition:transform .5s ease;transition:transform .5s ease,-webkit-transform .5s ease}.off-canvas-content.has-transition-push,.off-canvas-content .off-canvas.is-open{-webkit-transform:translate(0);-ms-transform:translate(0);transform:translate(0)}@media print,screen and (min-width:40em){.position-left.reveal-for-medium{-webkit-transform:none;-ms-transform:none;transform:none;-webkit-transition:none;transition:none;visibility:visible;z-index:12}.position-left.reveal-for-medium .close-button{display:none}.off-canvas-content .position-left.reveal-for-medium{-webkit-transform:none;-ms-transform:none;transform:none}.off-canvas-content.has-reveal-left{margin-left:250px}.position-left.reveal-for-medium~.off-canvas-content{margin-left:250px}.position-right.reveal-for-medium{-webkit-transform:none;-ms-transform:none;transform:none;-webkit-transition:none;transition:none;visibility:visible;z-index:12}.position-right.reveal-for-medium .close-button{display:none}.off-canvas-content .position-right.reveal-for-medium{-webkit-transform:none;-ms-transform:none;transform:none}.off-canvas-content.has-reveal-right{margin-right:250px}.position-right.reveal-for-medium~.off-canvas-content{margin-right:250px}.position-top.reveal-for-medium{-webkit-transform:none;-ms-transform:none;transform:none;-webkit-transition:none;transition:none;visibility:visible;z-index:12}.position-top.reveal-for-medium .close-button{display:none}.off-canvas-content .position-top.reveal-for-medium{-webkit-transform:none;-ms-transform:none;transform:none}.off-canvas-content.has-reveal-top{margin-top:250px}.position-top.reveal-for-medium~.off-canvas-content{margin-top:250px}.position-bottom.reveal-for-medium{-webkit-transform:none;-ms-transform:none;transform:none;-webkit-transition:none;transition:none;visibility:visible;z-index:12}.position-bottom.reveal-for-medium .close-button{display:none}.off-canvas-content .position-bottom.reveal-for-medium{-webkit-transform:none;-ms-transform:none;transform:none}.off-canvas-content.has-reveal-bottom{margin-bottom:250px}.position-bottom.reveal-for-medium~.off-canvas-content{margin-bottom:250px}}@media print,screen and (min-width:64em){.position-left.reveal-for-large{-webkit-transform:none;-ms-transform:none;transform:none;-webkit-transition:none;transition:none;visibility:visible;z-index:12}.position-left.reveal-for-large .close-button{display:none}.off-canvas-content .position-left.reveal-for-large{-webkit-transform:none;-ms-transform:none;transform:none}.off-canvas-content.has-reveal-left{margin-left:250px}.position-left.reveal-for-large~.off-canvas-content{margin-left:250px}.position-right.reveal-for-large{-webkit-transform:none;-ms-transform:none;transform:none;-webkit-transition:none;transition:none;visibility:visible;z-index:12}.position-right.reveal-for-large .close-button{display:none}.off-canvas-content .position-right.reveal-for-large{-webkit-transform:none;-ms-transform:none;transform:none}.off-canvas-content.has-reveal-right{margin-right:250px}.position-right.reveal-for-large~.off-canvas-content{margin-right:250px}.position-top.reveal-for-large{-webkit-transform:none;-ms-transform:none;transform:none;-webkit-transition:none;transition:none;visibility:visible;z-index:12}.position-top.reveal-for-large .close-button{display:none}.off-canvas-content .position-top.reveal-for-large{-webkit-transform:none;-ms-transform:none;transform:none}.off-canvas-content.has-reveal-top{margin-top:250px}.position-top.reveal-for-large~.off-canvas-content{margin-top:250px}.position-bottom.reveal-for-large{-webkit-transform:none;-ms-transform:none;transform:none;-webkit-transition:none;transition:none;visibility:visible;z-index:12}.position-bottom.reveal-for-large .close-button{display:none}.off-canvas-content .position-bottom.reveal-for-large{-webkit-transform:none;-ms-transform:none;transform:none}.off-canvas-content.has-reveal-bottom{margin-bottom:250px}.position-bottom.reveal-for-large~.off-canvas-content{margin-bottom:250px}}@media print,screen and (min-width:40em){.off-canvas.in-canvas-for-medium{background:0 0;height:auto;overflow:visible;position:static;-webkit-transition:none;transition:none;visibility:visible;width:auto}.off-canvas.in-canvas-for-medium.position-bottom,.off-canvas.in-canvas-for-medium.position-left,.off-canvas.in-canvas-for-medium.position-right,.off-canvas.in-canvas-for-medium.position-top{-webkit-box-shadow:none;box-shadow:none;-webkit-transform:none;-ms-transform:none;transform:none}.off-canvas.in-canvas-for-medium .close-button{display:none}}@media print,screen and (min-width:64em){.off-canvas.in-canvas-for-large{background:0 0;height:auto;overflow:visible;position:static;-webkit-transition:none;transition:none;visibility:visible;width:auto}.off-canvas.in-canvas-for-large.position-bottom,.off-canvas.in-canvas-for-large.position-left,.off-canvas.in-canvas-for-large.position-right,.off-canvas.in-canvas-for-large.position-top{-webkit-box-shadow:none;box-shadow:none;-webkit-transform:none;-ms-transform:none;transform:none}.off-canvas.in-canvas-for-large .close-button{display:none}}html.is-reveal-open{overflow-y:hidden;position:fixed;width:100%}html.is-reveal-open.zf-has-scroll{-webkit-overflow-scrolling:touch;overflow-y:scroll}html.is-reveal-open body{overflow-y:hidden}.reveal-overlay{background-color:hsla(0,0%,4%,.45);bottom:0;left:0;position:fixed;right:0;top:0;z-index:1005}.reveal,.reveal-overlay{-webkit-overflow-scrolling:touch;display:none;overflow-y:auto}.reveal{-webkit-backface-visibility:hidden;backface-visibility:hidden;background-color:#fefefe;border:1px solid #cacaca;border-radius:0;margin-left:auto;margin-right:auto;padding:1rem;position:relative;top:100px;z-index:1006}[data-whatinput=mouse] .reveal{outline:0}@media print,screen and (min-width:40em){.reveal{min-height:0}}.reveal .column{min-width:0}.reveal>:last-child{margin-bottom:0}@media print,screen and (min-width:40em){.reveal{max-width:75rem;width:600px}}.reveal.collapse{padding:0}@media print,screen and (min-width:40em){.reveal.tiny{max-width:75rem;width:30%}.reveal.small{max-width:75rem;width:50%}.reveal.large{max-width:75rem;width:90%}}.reveal.full{border:0;border-radius:0;bottom:0;height:100%;left:0;margin-left:0;max-width:none;min-height:100%;right:0;top:0;width:100%}@media print,screen and (max-width:39.99875em){.reveal{border:0;border-radius:0;bottom:0;height:100%;left:0;margin-left:0;max-width:none;min-height:100%;right:0;top:0;width:100%}}.reveal.without-overlay{position:fixed}.sticky,.sticky-container{position:relative}.sticky{-webkit-transform:translateZ(0);transform:translateZ(0);z-index:0}.sticky.is-stuck{position:fixed;width:100%;z-index:5}.sticky.is-stuck.is-at-top{top:0}.sticky.is-stuck.is-at-bottom{bottom:0}.sticky.is-anchored{left:auto;position:relative;right:auto}.sticky.is-anchored.is-at-bottom{bottom:0}.title-bar{-webkit-box-pack:start;-ms-flex-pack:start;-webkit-box-align:center;-ms-flex-align:center;-webkit-align-items:center;align-items:center;background:#0a0a0a;color:#fefefe;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-justify-content:flex-start;justify-content:flex-start;padding:.5rem}.title-bar .menu-icon{margin-left:.25rem;margin-right:.25rem}.title-bar-left,.title-bar-right{-webkit-box-flex:1;-webkit-flex:1 1 0px;-ms-flex:1 1 0px;flex:1 1 0px}.title-bar-right{text-align:right}.title-bar-title{display:inline-block;font-weight:700;vertical-align:middle}.top-bar{-webkit-box-pack:justify;-ms-flex-pack:justify;-webkit-box-align:center;-ms-flex-align:center;-webkit-align-items:center;align-items:center;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;-webkit-justify-content:space-between;justify-content:space-between;padding:.5rem}.top-bar,.top-bar ul{background-color:#e6e6e6}.top-bar input{margin-right:1rem;max-width:200px}.top-bar .input-group-field{margin-right:0;width:100%}.top-bar input.button{width:auto}.top-bar .top-bar-left,.top-bar .top-bar-right{-webkit-box-flex:0;-webkit-flex:0 0 100%;-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}@media print,screen and (min-width:40em){.top-bar{-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap}.top-bar .top-bar-left{-webkit-box-flex:1;-webkit-flex:1 1 auto;-ms-flex:1 1 auto;flex:1 1 auto;margin-right:auto}.top-bar .top-bar-right{-webkit-box-flex:0;-webkit-flex:0 1 auto;-ms-flex:0 1 auto;flex:0 1 auto;margin-left:auto}}@media print,screen and (max-width:63.99875em){.top-bar.stacked-for-medium{-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap}.top-bar.stacked-for-medium .top-bar-left,.top-bar.stacked-for-medium .top-bar-right{-webkit-box-flex:0;-webkit-flex:0 0 100%;-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}}@media print,screen and (max-width:74.99875em){.top-bar.stacked-for-large{-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap}.top-bar.stacked-for-large .top-bar-left,.top-bar.stacked-for-large .top-bar-right{-webkit-box-flex:0;-webkit-flex:0 0 100%;-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}}.top-bar-title{margin:.5rem 1rem .5rem 0}.top-bar-left,.top-bar-right,.top-bar-title{-webkit-box-flex:0;-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto}.float-left{float:left!important}.float-right{float:right!important}.float-center{display:block;margin-left:auto;margin-right:auto}.clearfix:after,.clearfix:before{-ms-flex-preferred-size:0;-webkit-box-ordinal-group:2;-ms-flex-order:1;content:" ";display:table;-webkit-flex-basis:0;flex-basis:0;-webkit-order:1;order:1}.clearfix:after{clear:both}.align-left{-webkit-box-pack:start;-ms-flex-pack:start;-webkit-justify-content:flex-start;justify-content:flex-start}.align-right{-webkit-box-pack:end;-ms-flex-pack:end;-webkit-justify-content:flex-end;justify-content:flex-end}.align-center{-webkit-box-pack:center;-ms-flex-pack:center;-webkit-justify-content:center;justify-content:center}.align-justify{-webkit-box-pack:justify;-ms-flex-pack:justify;-webkit-justify-content:space-between;justify-content:space-between}.align-spaced{-ms-flex-pack:distribute;-webkit-justify-content:space-around;justify-content:space-around}.align-left.vertical.menu>li>a{-webkit-box-pack:start;-ms-flex-pack:start;-webkit-justify-content:flex-start;justify-content:flex-start}.align-right.vertical.menu>li>a{-webkit-box-pack:end;-ms-flex-pack:end;-webkit-justify-content:flex-end;justify-content:flex-end}.align-center.vertical.menu>li>a{-webkit-box-pack:center;-ms-flex-pack:center;-webkit-justify-content:center;justify-content:center}.align-top{-webkit-box-align:start;-ms-flex-align:start;-webkit-align-items:flex-start;align-items:flex-start}.align-self-top{-ms-flex-item-align:start;-webkit-align-self:flex-start;align-self:flex-start}.align-bottom{-webkit-box-align:end;-ms-flex-align:end;-webkit-align-items:flex-end;align-items:flex-end}.align-self-bottom{-ms-flex-item-align:end;-webkit-align-self:flex-end;align-self:flex-end}.align-middle{-webkit-box-align:center;-ms-flex-align:center;-webkit-align-items:center;align-items:center}.align-self-middle{-ms-flex-item-align:center;-webkit-align-self:center;align-self:center}.align-stretch{-webkit-box-align:stretch;-ms-flex-align:stretch;-webkit-align-items:stretch;align-items:stretch}.align-self-stretch{-ms-flex-item-align:stretch;-webkit-align-self:stretch;align-self:stretch}.align-center-middle{-webkit-box-pack:center;-ms-flex-pack:center;-webkit-box-align:center;-ms-flex-align:center;-ms-flex-line-pack:center;-webkit-align-content:center;align-content:center;-webkit-align-items:center;align-items:center;-webkit-justify-content:center;justify-content:center}.small-order-1{-webkit-box-ordinal-group:2;-ms-flex-order:1;-webkit-order:1;order:1}.small-order-2{-webkit-box-ordinal-group:3;-ms-flex-order:2;-webkit-order:2;order:2}.small-order-3{-webkit-box-ordinal-group:4;-ms-flex-order:3;-webkit-order:3;order:3}.small-order-4{-webkit-box-ordinal-group:5;-ms-flex-order:4;-webkit-order:4;order:4}.small-order-5{-webkit-box-ordinal-group:6;-ms-flex-order:5;-webkit-order:5;order:5}.small-order-6{-webkit-box-ordinal-group:7;-ms-flex-order:6;-webkit-order:6;order:6}@media print,screen and (min-width:40em){.medium-order-1{-webkit-box-ordinal-group:2;-ms-flex-order:1;-webkit-order:1;order:1}.medium-order-2{-webkit-box-ordinal-group:3;-ms-flex-order:2;-webkit-order:2;order:2}.medium-order-3{-webkit-box-ordinal-group:4;-ms-flex-order:3;-webkit-order:3;order:3}.medium-order-4{-webkit-box-ordinal-group:5;-ms-flex-order:4;-webkit-order:4;order:4}.medium-order-5{-webkit-box-ordinal-group:6;-ms-flex-order:5;-webkit-order:5;order:5}.medium-order-6{-webkit-box-ordinal-group:7;-ms-flex-order:6;-webkit-order:6;order:6}}@media print,screen and (min-width:64em){.large-order-1{-webkit-box-ordinal-group:2;-ms-flex-order:1;-webkit-order:1;order:1}.large-order-2{-webkit-box-ordinal-group:3;-ms-flex-order:2;-webkit-order:2;order:2}.large-order-3{-webkit-box-ordinal-group:4;-ms-flex-order:3;-webkit-order:3;order:3}.large-order-4{-webkit-box-ordinal-group:5;-ms-flex-order:4;-webkit-order:4;order:4}.large-order-5{-webkit-box-ordinal-group:6;-ms-flex-order:5;-webkit-order:5;order:5}.large-order-6{-webkit-box-ordinal-group:7;-ms-flex-order:6;-webkit-order:6;order:6}}.flex-container{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex}.flex-child-auto{-webkit-box-flex:1;-webkit-flex:1 1 auto;-ms-flex:1 1 auto;flex:1 1 auto}.flex-child-grow{-webkit-box-flex:1;-webkit-flex:1 0 auto;-ms-flex:1 0 auto;flex:1 0 auto}.flex-child-shrink{-webkit-box-flex:0;-webkit-flex:0 1 auto;-ms-flex:0 1 auto;flex:0 1 auto}.flex-dir-row{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row}.flex-dir-row-reverse{-webkit-box-orient:horizontal;-webkit-box-direction:reverse;-webkit-flex-direction:row-reverse;-ms-flex-direction:row-reverse;flex-direction:row-reverse}.flex-dir-column{-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column}.flex-dir-column-reverse{-webkit-box-orient:vertical;-webkit-box-direction:reverse;-webkit-flex-direction:column-reverse;-ms-flex-direction:column-reverse;flex-direction:column-reverse}@media print,screen and (min-width:40em){.medium-flex-container{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex}.medium-flex-child-auto{-webkit-box-flex:1;-webkit-flex:1 1 auto;-ms-flex:1 1 auto;flex:1 1 auto}.medium-flex-child-grow{-webkit-box-flex:1;-webkit-flex:1 0 auto;-ms-flex:1 0 auto;flex:1 0 auto}.medium-flex-child-shrink{-webkit-box-flex:0;-webkit-flex:0 1 auto;-ms-flex:0 1 auto;flex:0 1 auto}.medium-flex-dir-row{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row}.medium-flex-dir-row-reverse{-webkit-box-orient:horizontal;-webkit-box-direction:reverse;-webkit-flex-direction:row-reverse;-ms-flex-direction:row-reverse;flex-direction:row-reverse}.medium-flex-dir-column{-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column}.medium-flex-dir-column-reverse{-webkit-box-orient:vertical;-webkit-box-direction:reverse;-webkit-flex-direction:column-reverse;-ms-flex-direction:column-reverse;flex-direction:column-reverse}}@media print,screen and (min-width:64em){.large-flex-container{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex}.large-flex-child-auto{-webkit-box-flex:1;-webkit-flex:1 1 auto;-ms-flex:1 1 auto;flex:1 1 auto}.large-flex-child-grow{-webkit-box-flex:1;-webkit-flex:1 0 auto;-ms-flex:1 0 auto;flex:1 0 auto}.large-flex-child-shrink{-webkit-box-flex:0;-webkit-flex:0 1 auto;-ms-flex:0 1 auto;flex:0 1 auto}.large-flex-dir-row{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row}.large-flex-dir-row-reverse{-webkit-box-orient:horizontal;-webkit-box-direction:reverse;-webkit-flex-direction:row-reverse;-ms-flex-direction:row-reverse;flex-direction:row-reverse}.large-flex-dir-column{-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column}.large-flex-dir-column-reverse{-webkit-box-orient:vertical;-webkit-box-direction:reverse;-webkit-flex-direction:column-reverse;-ms-flex-direction:column-reverse;flex-direction:column-reverse}}.hide{display:none!important}.invisible{visibility:hidden}.visible{visibility:visible}@media print,screen and (max-width:39.99875em){.hide-for-small-only{display:none!important}}@media screen and (max-width:0em),screen and (min-width:40em){.show-for-small-only{display:none!important}}@media print,screen and (min-width:40em){.hide-for-medium{display:none!important}}@media screen and (max-width:39.99875em){.show-for-medium{display:none!important}}@media print,screen and (min-width:40em)and (max-width:63.99875em){.hide-for-medium-only{display:none!important}}@media screen and (max-width:39.99875em),screen and (min-width:64em){.show-for-medium-only{display:none!important}}@media print,screen and (min-width:64em){.hide-for-large{display:none!important}}@media screen and (max-width:63.99875em){.show-for-large{display:none!important}}@media print,screen and (min-width:64em)and (max-width:74.99875em){.hide-for-large-only{display:none!important}}@media screen and (max-width:63.99875em),screen and (min-width:75em){.show-for-large-only{display:none!important}}.show-for-sr,.show-on-focus{clip:rect(0,0,0,0)!important;border:0!important;height:1px!important;overflow:hidden!important;padding:0!important;position:absolute!important;white-space:nowrap!important;width:1px!important}.show-on-focus:active,.show-on-focus:focus{clip:auto!important;height:auto!important;overflow:visible!important;position:static!important;white-space:normal!important;width:auto!important}.hide-for-portrait,.show-for-landscape{display:block!important}@media screen and (orientation:landscape){.hide-for-portrait,.show-for-landscape{display:block!important}}@media screen and (orientation:portrait){.hide-for-portrait,.show-for-landscape{display:none!important}}.hide-for-landscape,.show-for-portrait{display:none!important}@media screen and (orientation:landscape){.hide-for-landscape,.show-for-portrait{display:none!important}}@media screen and (orientation:portrait){.hide-for-landscape,.show-for-portrait{display:block!important}}.show-for-dark-mode{display:none}.hide-for-dark-mode{display:block}@media screen and (prefers-color-scheme:dark){.show-for-dark-mode{display:block!important}.hide-for-dark-mode{display:none!important}}.show-for-ie{display:none}@media (-ms-high-contrast:active),(-ms-high-contrast:none){.show-for-ie{display:block!important}.hide-for-ie{display:none!important}}.show-for-sticky{display:none}.is-stuck .show-for-sticky{display:block}.is-stuck .hide-for-sticky{display:none}@font-face{font-display:"swap";font-family:FontAwesome}html{box-sizing:border-box}body{font-family:Roboto,sans-serif;font-size:16px;line-height:1}*,:after,:before{box-sizing:inherit}a{color:#3c4fe0}a.reference:after{font-family:FontAwesome;font-size:12px;padding:0 4px}a.reference.external:after{content:""}a.reference.download:after{content:""}a:hover{color:#3c4fe0;font-weight:500}.headerlink{margin-left:5px;visibility:hidden}.toc-backref:hover{color:#23263b}h1,h2,h3,h4,h5,h6{font-family:Roboto,sans-serif;font-size:16px;font-weight:500;letter-spacing:.2px;line-height:24px;margin-bottom:16px}h1:hover>a.headerlink,h2:hover>a.headerlink,h3:hover>a.headerlink,h4:hover>a.headerlink,h5:hover>a.headerlink,h6:hover>a.headerlink{visibility:visible}h1 a,h2 a,h3 a,h4 a,h5 a,h6 a{color:inherit}h1{font-size:32px;font-weight:700;line-height:40px;margin-bottom:28px}h2{font-size:24px;line-height:32px}h3{font-size:20px}h4{font-size:18px}h5{font-size:16px}h6{font-weight:400}img{max-width:100%}button:focus{outline:0}blockquote{border:0;margin:0;padding:0}blockquote,blockquote p,cite{color:inherit}cite{display:inline;font-size:inherit}cite:before{content:""}.show{display:block!important}.centered{display:block;margin:0 auto}.break{flex-basis:100%;height:0}@media screen and (min-width:1024px){h1{font-size:36px}}.admonition-title:before,.contents.local>ul>li a:before,.scylla-icon,.secondary-side-nav__content li a:before{background-repeat:no-repeat;background-size:contain;display:inline-block;filter:brightness(0);vertical-align:middle}.scylla-icon--about-team{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMSwuY2xzLTJ7ZmlsbDpub25lO3N0cm9rZTpncmF5O3N0cm9rZS1taXRlcmxpbWl0OjEwfS5jbHMtMntzdHJva2UtbGluZWNhcDpyb3VuZH08L3N0eWxlPjwvZGVmcz48ZyBpZD0iQ2FscXVlXzQiIGRhdGEtbmFtZT0iQ2FscXVlIDQiPjxwYXRoIGNsYXNzPSJjbHMtMSIgZD0iTTQuNjYgOS44MSAyLjYzIDExYTIuMDggMi4wOCAwIDAgMC0xLjEzIDEuODN2Ny44MWMuMTkgMS4xMS41IDEuNTMgMS41IDEuNDdNNy4wNiA5Ljk0bDEuNDQuOTQiLz48cGF0aCBjbGFzcz0iY2xzLTIiIGQ9Ik0zLjUgMTguNXY1LjM0TTkuNSAxOC41djUuMzRNOC41NCAxOC40MnY1LjMzTTE1LjUgMTguNXY1LjM0TTE2LjUgMTguNXY1LjM0TTMuMzMgMjAuNTNoNS4wOE0xMS40NSA4Ljg0bC4wNi4wNmExLjY1IDEuNjUgMCAwIDAgMi4zNCAwaDAiLz48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Ik0xMi40MiA3LjVhMS44MSAxLjgxIDAgMCAxLTEuOTItMS43N1Y1YTEuOTQgMS45NCAwIDAgMSAxLjkyLTIgMi4wNyAyLjA3IDAgMCAxIDIuMDggMnYuNzdhMiAyIDAgMCAxLTIuMDggMS43M1pNMTEuNDIgOC43NCA5LjYzIDkuOWEyLjA3IDIuMDcgMCAwIDAtMS4xMyAxLjg1djcuODJBMS40NyAxLjQ3IDAgMCAwIDEwIDIxTTEzLjc1IDkuMThsMiAuNjVjLjcuMzUuNzYgMS4wNi43NiAxLjg0djcuOWMwIC43Ny0uMjMgMS4yNC0xIDEuMjQiLz48cGF0aCBjbGFzcz0iY2xzLTIiIGQ9Ik05LjkzIDE5LjVoNS40Ii8+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNMTkuNDIgOS4xMmEyLjA3IDIuMDcgMCAwIDAgMi4wOC0xLjkzdi0uNzdhMi4wNyAyLjA3IDAgMCAwLTIuMDgtMS45MiAxLjkzIDEuOTMgMCAwIDAtMS45MiAxLjkydi43N2ExLjk0IDEuOTQgMCAwIDAgMS45MiAxLjkzWk01LjU5IDkuMTJhMS45MyAxLjkzIDAgMCAwIDEuOTItMS45M3YtLjc3QTEuOTMgMS45MyAwIDAgMCA1LjU5IDQuNSAyLjA4IDIuMDggMCAwIDAgMy41IDYuNDJ2Ljc3YTIuMDggMi4wOCAwIDAgMCAyLjA5IDEuOTNaTTIwLjQ0IDkuODFsMiAxLjE3YTIuMDYgMi4wNiAwIDAgMSAxLjEzIDEuODV2Ny44MWMtLjE4IDEuMTEtLjQ3IDEuNTMtMS40NyAxLjQ3TTE4LjA0IDkuOTRsLTEuNDQuOTMiLz48cGF0aCBjbGFzcz0iY2xzLTIiIGQ9Ik0yMS42IDE4LjV2NS4zNE0yMS43NyAyMC41M2gtNS4wOCIvPjwvZz48L3N2Zz4=)}.scylla-icon--about-us{background-image:url(data:image/svg+xml;base64,PHN2ZyBpZD0iTGF5ZXJfMyIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB2aWV3Qm94PSIwIDAgMjAgMjAiPjxkZWZzPjxzdHlsZT4uY2xzLTF7ZmlsbDpub25lO3N0cm9rZTojMDAwO3N0cm9rZS1saW5lY2FwOnJvdW5kO3N0cm9rZS1saW5lam9pbjpyb3VuZDtzdHJva2Utd2lkdGg6LjhweH08L3N0eWxlPjwvZGVmcz48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Ik02LjI4IDE5LjQ4Yy0uMTIuMDgtLjA4LjA3LS4yMy4xLS41OC4wOS0xLjEyLS4yOC0xLjI1LS44NCAwIDAtMi4zLTkuMTgtMi4zLTExLjExQzIuNSAzLjYgNS44OC40NCAxMC4zOC40NFMxNy41IDMuNDggMTcuNSA3LjVjMCAxLjkzLTEuMzIgMTEuMjMtMS4zMiAxMS4yMy0uMTMuNTYtLjY3Ljk0LTEuMjUuODQtLjEyLS4wMi0uMTMgMC0uMjMtLjA3Ii8+PHBhdGggZD0iTTE1Ljc1IDE1Ljc1Yy0uMTcgMS4xNS0uMjIgMi4zNC0uNTUgMy40Ni0uMzcuODUtMS42MyAxLjA2LTIuMjIuMzMtLjI1LS4yOC4xOS0uNjguNDQtLjQuNDMuNDYgMS4yNC4xOCAxLjMxLS40NGwuMDYtLjM0Yy4xOS0uODkuMzUtMS43OS41Ny0yLjY4LjA1LS4yNC40Mi0uMTcuMzkuMDdaIi8+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNMTEuNSA3YzAgMS45LTEuNTYgMy41LTMuNDYgMy41UzQuNSA4LjkgNC41IDdzMS42NC0zLjUgMy41NC0zLjVTMTEuNSA1LjEgMTEuNSA3WiIvPjxwYXRoIGQ9Ik04LjU1IDQuNzVjLS41OS4xMi0uNzEgMS40Mi0uMzYgMS43OC4yMy4yMy43MS4zMS43MS40N3MtLjQ4LjI0LS43MS40N2MtLjM2LjM2LS4yNCAxLjY2LjM2IDEuNzguNzEuMTQgMS43OC0uNzEgMS43OC0yLjI1UzkuMjYgNC42MSA4LjU1IDQuNzVaTTYuNTEgMTIuMmMyLjEyLjMxIDQuMzQtLjIgNS42OC0xLjk2LjMyLS40MS45Ni4xMS42Mi41MS0uNzYuOS0xLjc4IDEuNjMtMi45MyAxLjk1LTEuMTQuMzMtMi4zMy4zMS0zLjQ2LjE2YS4zNC4zNCAwIDAgMS0uMjktLjM4Yy4wMi0uMTguMTktLjMxLjM3LS4yOVpNNy45NyAxOS41OWMtLjk5Ljk2LTIuMzYuMDgtMi4zNi0xLjE1LS4xMi0uOS0uMjctMS43OS0uMzctMi42OS0uMDEtLjExLjA3LS4yMS4xOC0uMjIuMS0uMDEuMTkuMDYuMjEuMTUuMjIuODguMzggMS43Ny41NiAyLjY2LjAxLjc4LjY4IDEuMzggMS4zNS44My4yNy0uMjcuNjkuMTYuNDIuNDNaIi8+PHBhdGggZD0iTTkuNzUgMTkuMjdjLS40Mi45LTEuOC45Ni0yLjMyLjExLS41LTEuMTMtLjMxLTIuNS0uNDctMy43MiAwLS4xMS4wOC0uMi4xOS0uMjEuMSAwIC4xOS4wNy4yMS4xNy4xNy45NS4yOCAxLjkxLjQyIDIuODcuMDEuNDUuMjMuNzQuNTcuODUuMzMuMS43MS0uMDUuODgtLjM2LjE4LS4zNC43MS0uMDUuNTIuMjlaTTE0LjAzIDE1LjY2Yy0uMTYgMS4yMy4wMyAyLjU3LS40NiAzLjcyLS41Mi44Ni0xLjkxLjc5LTIuMzItLjExLS4xNy0uMzQuMzUtLjYxLjUzLS4yOC40Mi43MSAxLjQ4LjM4IDEuNDUtLjQ5LjE0LS45Ni4yNS0xLjkyLjQyLTIuODcuMDQtLjI0LjQxLS4yLjQuMDRaIi8+PHBhdGggZD0iTTExLjg1IDE1LjU0Yy4wMi43OS4wMSAxLjU4LjAxIDIuMzctLjAyLjQxLjA3LjktLjE0IDEuMjktLjQzIDEuMDItMi4wMSAxLjAyLTIuNDUgMC0uMjEtLjM5LS4xMy0uODktLjE0LTEuMjkgMC0uNzkgMC0xLjU4LjAxLTIuMzcgMC0uMTEuMS0uMi4yMS0uMTkuMSAwIC4xOC4wOC4xOS4xOC4wNy43OS4xIDEuNTguMTUgMi4zNy4wMy4yNyAwIC44Mi4xMyAxLjA0LjEzLjI2LjQuNDMuNjguNDIuNDYgMCAuNzktLjQuNzctLjg3bC4wMy0uNTljLjA0LS43OS4wOC0xLjU4LjE1LTIuMzcuMDItLjI0LjQtLjIzLjQuMDFaIi8+PC9zdmc+)}.scylla-icon--about-us-m{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNi4zOCAzMi40MyI+PHBhdGggZD0iTTYuNTUgMzEuNjRjLS4yLjEzLS40My4yMi0uNjkuMjZhMS44MSAxLjgxIDAgMCAxLTIuMDYtMS4zOVMuNDkgMTQuOTkuNDkgMTEuODJDLjUgNS4xOSA1Ljc3LjUgMTMuMTkuNXMxMi42OSA0LjY5IDEyLjY5IDExLjMyYzAgMy4xOC0zLjMxIDE4LjY5LTMuMzEgMTguNjlhMS44MSAxLjgxIDAgMCAxLTIuNjIgMS4yIiBzdHlsZT0iZmlsbDpub25lO3N0cm9rZTojMDAwO3N0cm9rZS1saW5lY2FwOnJvdW5kO3N0cm9rZS1saW5lam9pbjpyb3VuZCIvPjxwYXRoIGQ9Ik0yMS44NiAyNS4zNmMtLjI4IDEuOS0uMzcgMy44Ni0uOTEgNS43MS0uNjEgMS40MS0yLjY4IDEuNzUtMy42Ni41NS0uNDEtLjQ3LjMxLTEuMTEuNzMtLjY2LjcxLjc2IDIuMDQuMjkgMi4xNi0uNzMuMzItMS42Ni42NS0zLjMzIDEuMDQtNC45OC4wOS0uMzkuNy0uMjguNjUuMTFaIi8+PHBhdGggZD0iTTE0LjggMTAuNTdjMCAzLjEzLTIuNTMgNS42Ni01LjY2IDUuNjZzLTUuNDctMi41My01LjQ3LTUuNjYgMi4zNC01LjY2IDUuNDctNS42NiA1LjY2IDIuNTMgNS42NiA1LjY2WiIgc3R5bGU9InN0cm9rZS13aWR0aDouOXB4O2ZpbGw6bm9uZTtzdHJva2U6IzAwMDtzdHJva2UtbGluZWNhcDpyb3VuZDtzdHJva2UtbGluZWpvaW46cm91bmQiLz48cGF0aCBkPSJNMTAuMzEgNi44NmMtLjk4LjItMS4xNyAyLjM0LS41OSAyLjkzLjM4LjM4IDEuMTcuNTEgMS4xNy43OHMtLjc5LjQtMS4xNy43OGMtLjU5LjU5LS4zOSAyLjczLjU5IDIuOTMgMS4xNi4yMyAyLjkzLTEuMTcgMi45My0zLjcxcy0xLjc2LTMuOTQtMi45My0zLjcxWk02LjgyIDE4LjUxYzMuNDkuODkgNi45Ny0uNSA5LjUxLTIuOTMuNDctLjQ0IDEuMTYuMzEuNjguNzQtMS4zOCAxLjIzLTIuOTggMi4yOS00Ljc5IDIuODctMS44LjU5LTMuNzcuNTgtNS41OC4xNGEuNDIxLjQyMSAwIDAgMS0uMzEtLjVjLjA1LS4yMi4yOC0uMzYuNS0uMzFaIi8+PHBhdGggZD0iTTE2LjczIDE2LjY3Yy0uMTItLjQ2LS41MS0uODMtLjk5LS44My0uNzUtLjAyLS41OS0xLjE3LjE0LS45OS44MS4xNiAxLjQzLjg1IDEuNSAxLjY2LjA4LjQtLjU0LjU0LS42NS4xNVpNOS4wMyAzMS43Yy0xLjI2IDEuMzYtMy42Mi40NS0zLjgtMS4zNWwtLjA5LS41NWMtLjIxLTEuNDgtLjQ1LTIuOTUtLjYtNC40NC0uMDItLjE4LjExLS4zNC4yOS0uMzYuMTctLjAyLjMyLjA5LjM1LjI1LjM5IDEuNjMuNzEgMy4yOCAxLjAzIDQuOTMuMDkgMS4wMiAxLjM4IDEuNTQgMi4xMi44MS40NS0uNDQgMS4xNC4yNi42OS43WiIvPjxwYXRoIGQ9Ik0xMS45NiAzMS4xNmMtMSAxLjk4LTQuMDQgMS4zLTQuMjEtLjg4LS4xNS0xLjY5LS4zLTMuMzgtLjM5LTUuMDcgMC0uMTguMTMtLjM0LjMxLS4zNC4xNyAwIC4zMS4xMS4zNC4yNy4yOCAxLjY3LjUgMy4zNS43MiA1LjAzLjA5IDEuMiAxLjc3IDEuNTkgMi4zNi41MS4zMS0uNTYgMS4xNi0uMDkuODcuNDdaTTE5LjAzIDI1LjIxYy0uMDggMS42OS0uMjQgMy4zOC0uMzkgNS4wNy0uMDQuMzctLjE3Ljc1LS4zOCAxLjA2LS44NiAxLjQtMy4xMSAxLjMxLTMuODMtLjE3LS4zLS41Ni41NS0xLjAzLjg2LS40OC41OSAxLjA4IDIuMjcuNjkgMi4zNS0uNTIuMjItMS42OC40My0zLjM2LjcyLTUuMDMuMDYtLjQuNjgtLjMzLjY1LjA3WiIvPjxwYXRoIGQ9Ik0xNS40MyAyNS4wMmMuMDQgMS4zMS4wMiAyLjYxLjAyIDMuOTEtLjAzLjY3LjExIDEuNDgtLjIzIDIuMTMtLjc0IDEuNjktMy4yOSAxLjY5LTQuMDMgMC0uMzQtLjY1LS4yMS0xLjQ3LS4yNC0yLjEzIDAtMS4zLS4wMi0yLjYxLjAyLTMuOTEgMC0uMTguMTYtLjMyLjM0LS4zMi4xNyAwIC4zLjE0LjMyLjMuMTEgMS4zLjE3IDIuNi4yNCAzLjkxLjA1LjQ1IDAgMS4zNS4yMSAxLjcyLjIxLjQzLjY2LjcxIDEuMTIuNy40Ni4wMi45MS0uMjcgMS4xMi0uNjkuMjItLjM2LjE2LTEuMjguMjEtMS43Mi4wNy0xLjMuMTMtMi42MS4yNC0zLjkxLjAyLS40LjY2LS4zOC42Ni4wMloiLz48L3N2Zz4=)}.scylla-icon--alternator{background-image:url(data:image/svg+xml;base64,PHN2ZyBpZD0iTGF5ZXJfMyIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB2aWV3Qm94PSIwIDAgMjAgMjAiPjxkZWZzPjxzdHlsZT4uY2xzLTF7ZmlsbDpub25lO3N0cm9rZTojMDAwO3N0cm9rZS1saW5lY2FwOnJvdW5kO3N0cm9rZS1saW5lam9pbjpyb3VuZH08L3N0eWxlPjwvZGVmcz48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Ik0xNy41IDIuOTFjMCAxLjI4LTMuNjcgMi41OS04IDIuNTlzLTgtMS4zMS04LTIuNTlTNS4wOS41IDkuNDIuNXM4LjA4IDEuMTMgOC4wOCAyLjQxWk0xNy41IDcuNjZjMCAxLjI4LTMuNjMgMi44LTcuOTYgMi44UzEuNSA4LjkzIDEuNSA3LjY2TTE3LjUgMTIuNDdjMCAxLjI4LTMuNjcgMy4wMy04IDMuMDNzLTgtMS43NS04LTMuMDNNMTcuNSAxNy4yOWMwIDEuMjgtMy43NSAyLjMtOC4wOCAyLjNzLTcuOTItMS4wMy03LjkyLTIuM00xLjUgMTcuMTlWMi45MU0xNy41IDE3LjE5VjIuOTEiLz48L3N2Zz4=)}.scylla-icon--apps{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyMSAxOSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOm5vbmU7c3Ryb2tlOiM0ZDRkNGQ7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJDYWxxdWVfNCIgZGF0YS1uYW1lPSJDYWxxdWUgNCI+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNLjUgMS41aDIwdjE0SC41ek03LjUgMTUuNzR2Mi44OU0xMi44MyAxNS42M3YyLjMyTTUuNSAxOC41aDkuMTQiLz48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Im0zLjY0IDUuNTYgNC41OCAyLjkxLTQuNTggMi45Mk05LjEgMTIuMDhoNC4zMiIvPjwvZz48L3N2Zz4=)}.scylla-icon--architecture{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMSwuY2xzLTIsLmNscy01e2ZpbGw6bm9uZTtzdHJva2U6Z3JheX0uY2xzLTF7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfS5jbHMtMiwuY2xzLTV7c3Ryb2tlLW1pdGVybGltaXQ6MTB9LmNscy0ye3N0cm9rZS13aWR0aDouOThweH0uY2xzLTV7c3Ryb2tlLXdpZHRoOi45OXB4fTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJDYWxxdWVfMiIgZGF0YS1uYW1lPSJDYWxxdWUgMiI+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNMS45IDEwLjI3YTEwLjgzIDEwLjgzIDAgMCAxIDguNzMtOC4zOE0xMC41MSAyMy4wOEExMC43OSAxMC43OSAwIDAgMSAxLjc3IDE0TTIzLjIzIDE0YTEwLjgxIDEwLjgxIDAgMCAxLTkgOS4xMU0xNC4yNyAxLjg4YTEwLjgxIDEwLjgxIDAgMCAxIDguODMgOC4zNyIvPjxjaXJjbGUgY2xhc3M9ImNscy0yIiBjeD0iMTIuMjUiIGN5PSIxLjc1IiByPSIxLjc1Ii8+PGNpcmNsZSBjbGFzcz0iY2xzLTIiIGN4PSIxMi4yNSIgY3k9IjIyLjc1IiByPSIxLjc1Ii8+PGNpcmNsZSBjeD0iNC45MiIgY3k9IjQuNzUiIHI9IjEuNzUiIHN0eWxlPSJzdHJva2Utd2lkdGg6Ljk5cHg7ZmlsbDpncmF5O3N0cm9rZS1taXRlcmxpbWl0OjEwO3N0cm9rZTpncmF5Ii8+PGNpcmNsZSBjeD0iMjAuMDkiIGN5PSIxOS45MSIgcj0iMS43NSIgc3R5bGU9InN0cm9rZS13aWR0aDouOTlweDtmaWxsOmdyYXk7c3Ryb2tlLW1pdGVybGltaXQ6MTA7c3Ryb2tlOmdyYXkiLz48Y2lyY2xlIGNsYXNzPSJjbHMtNSIgY3g9IjEuNzUiIGN5PSIxMi4yNSIgcj0iMS43NSIvPjxjaXJjbGUgY2xhc3M9ImNscy01IiBjeD0iMjMuMjUiIGN5PSIxMi4yNSIgcj0iMS43NSIvPjxjaXJjbGUgY3g9IjQuNzUiIGN5PSIxOS42NCIgcj0iMS43NSIgc3R5bGU9InN0cm9rZS13aWR0aDouOTlweDtmaWxsOmdyYXk7c3Ryb2tlLW1pdGVybGltaXQ6MTA7c3Ryb2tlOmdyYXkiLz48Y2lyY2xlIGN4PSIxOS45MSIgY3k9IjQuNDgiIHI9IjEuNzUiIHN0eWxlPSJzdHJva2Utd2lkdGg6Ljk5cHg7ZmlsbDpncmF5O3N0cm9rZS1taXRlcmxpbWl0OjEwO3N0cm9rZTpncmF5Ii8+PC9nPjwvc3ZnPg==)}.scylla-icon--benchmarks{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVqb2luOnJvdW5kO3N0cm9rZS13aWR0aDozcHh9PC9zdHlsZT48L2RlZnM+PGcgaWQ9IkNhbHF1ZV8yIiBkYXRhLW5hbWU9IkNhbHF1ZSAyIj48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Ik01LjUxIDI0Ljkxdi01Ljg1TTEyLjU3IDI0Ljkxdi05Ljc0TTE5LjYyIDI0LjkxVjEwLjE1Ii8+PHBhdGggc3R5bGU9InN0cm9rZS1saW5lY2FwOnJvdW5kO2ZpbGw6bm9uZTtzdHJva2U6Z3JheTtzdHJva2UtbGluZWpvaW46cm91bmQiIGQ9Im0uOTEgMTQuOTggNS4xMy03Ljk0IDYuMjUgNS44OEwyNCAxIi8+PHBhdGggc3R5bGU9ImZpbGw6Z3JheSIgZD0ibTI1IDUtNS01aDV2NXoiLz48L2c+PC9zdmc+)}.scylla-icon--blog{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJDYWxxdWVfNCIgZGF0YS1uYW1lPSJDYWxxdWUgNCI+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJtOSAxNS0yLjUtMS41IDgtMTJMMTcgMyA5IDE1eiIvPjxwYXRoIHN0eWxlPSJmaWxsOmdyYXk7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kIiBkPSJtNi41IDEzLjUtLjUgM0w5IDE1bC0yLjUtMS41eiIvPjxwYXRoIGNsYXNzPSJjbHMtMSIgZD0iTTE5LjI1IDIuNWg0LjI1djE2aC0xM3Y0LjE3TDYuNDYgMTguNWwtNC45Ni0uMDRWMi41aDguMzFNMTQuNSAyLjVsMS42NyAxLjMzIi8+PC9nPjwvc3ZnPg==)}.scylla-icon--careers{background-image:url(data:image/svg+xml;base64,PHN2ZyBpZD0iQ2FscXVlXzEiIGRhdGEtbmFtZT0iQ2FscXVlIDEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmlld0JveD0iMCAwIDI1IDI1Ij48ZGVmcz48c3R5bGU+LmNscy0xe2ZpbGw6bm9uZTtzdHJva2U6Z3JheTtzdHJva2UtbGluZWNhcDpyb3VuZDtzdHJva2UtbGluZWpvaW46cm91bmR9PC9zdHlsZT48L2RlZnM+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNMS41IDExLjU1djhjMCAuNTYgMS4wNyAyIDIgMmgxOGMuODkgMCAyLTEuNDQgMi0ydi04Ii8+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNMjMuMzEgMy41SDEuODFjLS40OCAwLTEuMzEuNTUtMS4zMSAxdjZsMTAgMmE4LjQ1IDguNDUgMCAwIDAgNCAwbDEwLTJ2LTZjMC0uNDUtLjcyLTEtMS4xOS0xWk0xNS42MiAzLjV2LTFjMC0uNzYtLjYxLTEtMS4zOC0xaC0zLjQ1Yy0uNzYgMC0xLjM4LjI0LTEuMzggMXYxIi8+PHJlY3QgeD0iMTAiIHk9IjExIiB3aWR0aD0iNSIgaGVpZ2h0PSIzLjk5IiByeD0iLjU1IiByeT0iLjU1IiBzdHlsZT0iZmlsbDpncmF5Ii8+PC9zdmc+)}.scylla-icon--chevron-left{background-image:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTAiIGhlaWdodD0iMTYiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZD0iTTguMDkyIDE2IDEwIDE0LjExMyAzLjgxNyA4IDEwIDEuODg3IDguMDkyIDAgMCA4bDguMDkyIDhaIiBmaWxsPSIjMDAwIi8+PC9zdmc+)}.contents.local>ul>li a:before,.scylla-icon--chevron-right,.secondary-side-nav__content li a:before{background-image:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTAiIGhlaWdodD0iMTYiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZD0iTTEuOTA4IDAgMCAxLjg4NyA2LjE4MyA4IDAgMTQuMTEzIDEuOTA4IDE2IDEwIDggMS45MDggMFoiIGZpbGw9IiMwMDAiLz48L3N2Zz4=)}.scylla-icon--circe{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAzOCAzMCI+PGRlZnM+PHN0eWxlPi5jbHMtMiwuY2xzLTN7ZmlsbDpub25lO3N0cm9rZTojNGQ0ZDRkO3N0cm9rZS1saW5lY2FwOnJvdW5kO3N0cm9rZS1saW5lam9pbjpyb3VuZH0uY2xzLTN7c3Ryb2tlLXdpZHRoOjEuMTFweH08L3N0eWxlPjwvZGVmcz48ZyBpZD0iQ2FscXVlXzQiIGRhdGEtbmFtZT0iQ2FscXVlIDQiPjxwYXRoIGQ9Ik0yMi4xIDEyaC02LjE2YTEuMDYgMS4wNiAwIDAgMS0uOTQtMS4wNy45My45MyAwIDAgMSAuOTQtLjkzaDYuMTZhLjkzLjkzIDAgMCAxIC45NC45M0ExLjA2IDEuMDYgMCAwIDEgMjIuMSAxMloiIHN0eWxlPSJmaWxsOiM0ZDRkNGQiLz48cGF0aCBjbGFzcz0iY2xzLTIiIGQ9Ik0xMy40NCA0LjQ5SDkuNTF2MjRoMTl2LTI0SDI0LjUiLz48cGF0aCBjbGFzcz0iY2xzLTMiIGQ9Ik0xMyAzLjQ5SDguNWwtLjA4IDI2LjFIMjkuNVYzLjM5SDI1Ii8+PHBhdGggY2xhc3M9ImNscy0yIiBkPSJNMTIuNSAxOC4zOGgxM00xMi41IDE1LjQ5aDEzTTEyLjUgMjEuNDNoMTNNMTIuNSAyNC40N2gxM00xMy41IDIuNWgxMXYzLjk4aC0xMXoiLz48cGF0aCBjbGFzcz0iY2xzLTMiIGQ9Ik0yMS41LjVoLTUuMDR2MS45NWw1LjA0LjA1di0yeiIvPjwvZz48L3N2Zz4=)}.scylla-icon--clock{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyMSAxOSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOm5vbmU7c3Ryb2tlOiM0ZDRkNGQ7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJDYWxxdWVfNCIgZGF0YS1uYW1lPSJDYWxxdWUgNCI+PGNpcmNsZSBjbGFzcz0iY2xzLTEiIGN4PSIxMC41IiBjeT0iOS41IiByPSI5Ii8+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNMTAuNSAzLjV2NmwzLjA2IDMiLz48L2c+PC9zdmc+)}.scylla-icon--close{background-image:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMzQiIGhlaWdodD0iMzQiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGcgY2xpcC1wYXRoPSJ1cmwoI2EpIiBmaWxsPSIjZmZmIj48cGF0aCBkPSJNMTEuNjcgMjIuMTNhLjU2NC41NjQgMCAwIDEtLjM5OC0uOTYybDkuODk2LTkuODk2YS41NjMuNTYzIDAgMSAxIC43OTcuNzk3bC05Ljg5NiA5Ljg5NmEuNTU5LjU1OSAwIDAgMS0uMzk5LjE2NVoiLz48cGF0aCBkPSJNMjEuNTY2IDIyLjEzYS41NTkuNTU5IDAgMCAxLS4zOTgtLjE2NWwtOS44OTYtOS44OTZhLjU2My41NjMgMCAxIDEgLjc5Ny0uNzk3bDkuODk2IDkuODk1YS41NjQuNTY0IDAgMCAxLS4zOTkuOTYzWiIvPjxwYXRoIGQ9Ik0xNi42MTkgMzMuMjM3QzcuNDU1IDMzLjIzNyAwIDI1Ljc4MiAwIDE2LjYxOSAwIDcuNDU2IDcuNDU1IDAgMTYuNjE5IDBzMTYuNjE5IDcuNDU1IDE2LjYxOSAxNi42MTktNy40NTYgMTYuNjE4LTE2LjYyIDE2LjYxOFptMC0zMi4xMWMtOC41NDIgMC0xNS40OTIgNi45NS0xNS40OTIgMTUuNDkyIDAgOC41NDIgNi45NSAxNS40OTIgMTUuNDkyIDE1LjQ5MiA4LjU0MiAwIDE1LjQ5Mi02Ljk1IDE1LjQ5Mi0xNS40OTIgMC04LjU0Mi02Ljk1LTE1LjQ5Mi0xNS40OTItMTUuNDkyWiIvPjwvZz48ZGVmcz48Y2xpcFBhdGggaWQ9ImEiPjxwYXRoIGZpbGw9IiNmZmYiIGQ9Ik0wIDBoMzMuMjM3djMzLjIzN0gweiIvPjwvY2xpcFBhdGg+PC9kZWZzPjwvc3ZnPg==)}.scylla-icon--cloud{background-image:url(data:image/svg+xml;base64,PHN2ZyBpZD0iTGF5ZXJfMiIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB2aWV3Qm94PSIwIDAgNDMuMDQgMzIuMDMiPjxkZWZzPjxzdHlsZT4uY2xzLTF7ZmlsbDpub25lO3N0cm9rZTojMWQxZDFiO3N0cm9rZS1saW5lY2FwOnJvdW5kO3N0cm9rZS1saW5lam9pbjpyb3VuZH08L3N0eWxlPjwvZGVmcz48ZyBpZD0iTGF5ZXJfMyI+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNNDIuNTQgNC4wNmMwIDEuNjgtMy42MyAyLjQ0LTkgMi40NHMtMTAtLjczLTEwLTIuNFMyNy42Ny41IDMzLjA0LjVzOS41IDEuODkgOS41IDMuNTZaTTQyLjU0IDkuNjNjMCAxLjY4LTMuNzYgMi45MS05LjEyIDIuOTFzLTkuODQtMS4yMy05Ljg0LTIuOTFNNDIuNTQgMTUuMzRjMCAxLjY4LTMuNjggMy4yNS05LjA0IDMuMjUtNCAwLTcuNi0uOTYtOS4wOS0yLjA0TTQyLjU0IDIwLjY1YzAgMS42OC0zLjcyIDIuOTctOS4wOCAyLjk3TTIzLjU0IDE1LjQ2VjQuMU00Mi41NCAyMC43N1Y0LjEiLz48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Ik0yOC4xMSAyMS4wOGMtLjg3IDAtMS42Ny4yMy0yLjM5LjYxIDAtLjA3LjAxLS4xNC4wMS0uMjEgMC00Ljg1LTMuODMtOC45LTguNjgtOC45cy04Ljg4IDQuMDUtOC44OCA4LjljMCAuMTcuMDIuMzQuMDMuNTEtLjg0LS41Ny0xLjg1LS45MS0yLjk1LS45MS0yLjg4IDAtNC43NCAyLjU3LTQuNzQgNS40NnMxLjg2IDQuOTkgNC43NCA0Ljk5aDIyLjg2YzIuODggMCA1LjUyLTIuMjcgNS41Mi01LjE2cy0yLjYzLTUuMjktNS41Mi01LjI5WiIvPjwvZz48L3N2Zz4=)}.scylla-icon--cloud-docs{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyMSAxOSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOm5vbmU7c3Ryb2tlOiM0ZDRkNGQ7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJDYWxxdWVfNCIgZGF0YS1uYW1lPSJDYWxxdWUgNCI+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNNi41IDExLjVoOHYxaC04ek0xNS42NSA2LjU1YTMuNDIgMy40MiAwIDAgMC0zLjE1IDIiLz48cGF0aCBkPSJNMTAuMDYgMi44QTUuMTcgNS4xNyAwIDAgMSAxNSA2LjM1aC4yNGE0Ljg0IDQuODQgMCAwIDEgMCA5LjY3aC0xMWEzLjQ1IDMuNDUgMCAwIDEgMC02LjlBMy4xNyAzLjE3IDAgMCAxIDUgOS4yIDUuMzMgNS4zMyAwIDAgMSA0Ljg2IDhhNS4yIDUuMiAwIDAgMSA1LjItNS4ybTAtLjhhNiA2IDAgMCAwLTYgNnYuMzFhNC4yNSA0LjI1IDAgMCAwIC4xOCA4LjQ5aDExYTUuNjMgNS42MyAwIDAgMCAuMy0xMS4yNkE2IDYgMCAwIDAgMTAuMDYgMloiIHN0eWxlPSJmaWxsOiM0ZDRkNGQiLz48L2c+PC9zdmc+)}.scylla-icon--comparison{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMSwuY2xzLTIsLmNscy00e2ZpbGw6bm9uZTtzdHJva2U6Z3JheX0uY2xzLTEsLmNscy0ye3N0cm9rZS1taXRlcmxpbWl0OjEwfS5jbHMtMiwuY2xzLTR7c3Ryb2tlLWxpbmVjYXA6cm91bmR9LmNscy00e3N0cm9rZS1saW5lam9pbjpyb3VuZH08L3N0eWxlPjwvZGVmcz48ZyBpZD0iQ2FscXVlXzQiIGRhdGEtbmFtZT0iQ2FscXVlIDQiPjxwYXRoIGNsYXNzPSJjbHMtMSIgZD0iTTQuNSAxMy42M3YyLjg4aDYuMDZNMjAuNSAxMy41NHYyLjk2bC01LjUuMDEiLz48cGF0aCBjbGFzcz0iY2xzLTIiIGQ9Ik0xMi41IDE4LjV2Mi43Mk03LjUgMjEuNWgxMCIvPjxjaXJjbGUgY3g9IjEyLjUiIGN5PSIxNi41IiByPSIyIiBzdHlsZT0iZmlsbDpncmF5O3N0cm9rZS13aWR0aDouOTVweDtzdHJva2UtbWl0ZXJsaW1pdDoxMDtzdHJva2U6Z3JheSIvPjxwYXRoIGNsYXNzPSJjbHMtNCIgZD0iTTUuMDYgMTMuNThIMy44OEEzLjEgMy4xIDAgMCAxIC41IDEwLjVoOGEzLjE2IDMuMTYgMCAwIDEtMy40NCAzLjA4Wk0yMSAxMy41OGgtMS4xN2EzLjA5IDMuMDkgMCAwIDEtMy4zNy0zLjA3aDhBMy4xNiAzLjE2IDAgMCAxIDIxIDEzLjU4Wk03LjQ2IDUuMTJjMCAuNTctMS4xLjQ2LTIuNzkuNDZTMS41OCA1LjYgMS41OCA1IDMgNC40IDQuNjkgNC40czIuNzcuMTYgMi43Ny43MlpNMS41IDkuODVWNS4zMU03LjUgMTAuMzVWNS44MU0yMy41IDUuMTJjMCAuNTctMS4xLjQ2LTIuNzkuNDZzLTMuMDkgMC0zLjA5LS41NFMxOSA0LjQgMjAuNzMgNC40czIuNzcuMTYgMi43Ny43MlpNMTcuNTQgOS44NVY1LjMxTTIzLjU0IDEwLjM1VjUuODEiLz48L2c+PC9zdmc+)}.scylla-icon--contact-us{background-image:url(data:image/svg+xml;base64,PHN2ZyBpZD0iQ2FscXVlXzEiIGRhdGEtbmFtZT0iQ2FscXVlIDEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmlld0JveD0iMCAwIDI1IDI1Ij48ZGVmcz48c3R5bGU+LmNscy0xe2ZpbGw6bm9uZTtzdHJva2U6Z3JheTtzdHJva2UtbGluZWNhcDpyb3VuZDtzdHJva2UtbGluZWpvaW46cm91bmQ7c3Ryb2tlLXdpZHRoOjEuMDZweH08L3N0eWxlPjwvZGVmcz48cGF0aCBjbGFzcz0iY2xzLTEiIHRyYW5zZm9ybT0icm90YXRlKC0yNy40OSAxNS41NTIgMTEuMDgzKSIgZD0iTTcuNzYgNi4wMWgxNS41OXYxMC4xM0g3Ljc2eiIvPjxwYXRoIGNsYXNzPSJjbHMtMSIgZD0ibTYuMyAxMC4xOCA4LjYzIDEuNTZhMS40MiAxLjQyIDAgMCAwIDEuNTMtLjc0bDMuNjctOE0xMS4wMiAxOS4wM2wxLjc0LTVNMjQuNTkgMTEuOTdsLTUuMDktMS40NU03LjA5IDE3LjU4IDMuOSAxOS4zNE02LjA2IDE1LjQxLjU0IDE4LjM2Ii8+PC9zdmc+)}.scylla-icon--developers-blog{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOmdyYXl9PC9zdHlsZT48L2RlZnM+PGcgaWQ9IkNhbHF1ZV80IiBkYXRhLW5hbWU9IkNhbHF1ZSA0Ij48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Im02LjQ4IDEwLjU5LS41LjE3LjUuMTZMMTEgMTIuMTZWMTRsLTctMi40OVYxMGw3LTIuNXYxLjgzWk0xNCA5LjMyVjcuNWw3IDIuNXYxLjU0TDE0IDE0di0xLjgzbDQuMTQtMS4zLjQ0LS4xMy0uNDMtLjE0WiIvPjxwYXRoIHN0eWxlPSJmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kO3N0cm9rZS13aWR0aDouOThweCIgZD0iTTEuNSAyLjVoMjJ2MTZoLTEzdjQuMTdMNi40NiAxOC41bC00Ljk2LS4wNFYyLjV6Ii8+PC9nPjwvc3ZnPg==)}.scylla-icon--docs{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfS5jbHMtMntmaWxsOmdyYXl9PC9zdHlsZT48L2RlZnM+PGcgaWQ9IkNhbHF1ZV80IiBkYXRhLW5hbWU9IkNhbHF1ZSA0Ij48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Ik0zLjUgMi41MWgxNi45NHYyMC45MUgzLjV6Ii8+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJtMjIuNDUgMjEuNS4wNS0yMWgtMTdhMi4xNiAyLjE2IDAgMCAwLTIgMiIvPjxwYXRoIGNsYXNzPSJjbHMtMiIgZD0iTTYgNmg3djJINnpNNiA5aDExdjJINnoiLz48L2c+PC9zdmc+)}.scylla-icon--enterprise{background-image:url(data:image/svg+xml;base64,PHN2ZyBpZD0iTGF5ZXJfMyIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB2aWV3Qm94PSIwIDAgMjAgMjAiPjxkZWZzPjxzdHlsZT4uY2xzLTEsLmNscy0ye2ZpbGw6bm9uZTtzdHJva2U6IzAwMDtzdHJva2UtbGluZWNhcDpyb3VuZDtzdHJva2UtbGluZWpvaW46cm91bmR9LmNscy0ye3N0cm9rZS13aWR0aDoxLjA3cHh9PC9zdHlsZT48L2RlZnM+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJtMTMuNjIgNy41IDEuODgtMS4wOCAyIDIuMDh2N2gxTTE1LjUgMTUuNXYtNSIvPjxwYXRoIGNsYXNzPSJjbHMtMiIgZD0iTTUuNSAxNS41di0xMmw0LTIgNCAydjEyTTkuNSAxNS41VjEuNk03LjUgNS41djEwTTExLjUgNS41djEwIi8+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNNS41IDguNTQgMy40NiA3LjVsLTEuOTYuOTZ2Ny4wNGgtMU0zLjUgMTAuNXY1TS41IDE3LjVoMTgiLz48L3N2Zz4=)}.scylla-icon--enterprise-m{background-image:url(data:image/svg+xml;base64,PHN2ZyB2ZXJzaW9uPSIxLjEiIGlkPSJMYXllcl8yXzAwMDAwMDE2NzY4MDY2MDE5MjYzMjMyNzcwMDAwMDA1NDc1ODA5NTExODI4NjY2MDM2XyIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4PSIwIiB5PSIwIiB2aWV3Qm94PSIwIDAgNDMgMzEiIHN0eWxlPSJlbmFibGUtYmFja2dyb3VuZDpuZXcgMCAwIDQzIDMxIiB4bWw6c3BhY2U9InByZXNlcnZlIj48c3R5bGU+LnN0MHtmaWxsOm5vbmU7c3Ryb2tlOiMxZDFkMWI7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfTwvc3R5bGU+PGcgaWQ9IkxheWVyXzMiPjxwYXRoIGNsYXNzPSJzdDAiIGQ9Im0yOS42IDkuNSA0LTIgNi45IDQuMXYxNS45aDJNMzMuNiAyNy41VjcuNk0xNC42IDI3LjVWNC44TDIyLjUuNSAyOS42IDV2MjIuNU0yMi41IDI3LjVWMU0yNC41IDUuNmwzIDJNMjQuNSA5LjZsMyAyTTI0LjUgMTMuNmwzIDJNMjQuNSAxNy41bDMgMk0yNC41IDIxLjVsMyAyTTM1LjQgMTEuNmwzIDJNMzUuNCAxNS42bDMgMS45TTM1LjQgMTkuNWwzIDJNMzUuNCAyMy41bDMgMS45TTE4LjUgNS44djIxLjdNMTQuNiA5LjdsLTQuMS0yLjUtOCA0LjR2MTUuOWgtMk0xMC41IDI3LjVWNy4yTTEyLjUgMTEuNmwyIDFNMTIuNSAxNS42bDIgLjlNMTIuNSAxOS41bDIgMU0xMi41IDIzLjVsMi4xIDFNNi40IDEyLjR2MTUuMU0uNSAzMC41aDQyIi8+PC9nPjwvc3ZnPg==)}.scylla-icon--events{background-image:url(data:image/svg+xml;base64,PHN2ZyBpZD0iQ2FscXVlXzEiIGRhdGEtbmFtZT0iQ2FscXVlIDEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmlld0JveD0iMCAwIDI1IDI1Ij48ZGVmcz48c3R5bGU+LmNscy0xe2ZpbGw6bm9uZTtzdHJva2U6Z3JheTtzdHJva2UtbGluZWNhcDpyb3VuZDtzdHJva2UtbGluZWpvaW46cm91bmR9LmNscy0ye2ZpbGw6Z3JheX08L3N0eWxlPjwvZGVmcz48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Ik0yMi41IDIzLjVoLTIxdi0yMGgyMnYxNS4yMSIvPjxwYXRoIGNsYXNzPSJjbHMtMSIgZD0iTTQuNDIgMy41YzAtMS4zNiAxLjA5LTIgMi40NS0yYTIuNDYgMi40NiAwIDEgMSAwIDQuOTEgMi42MSAyLjYxIDAgMCAxLTEtLjIxTTEwLjY3IDMuNWMwLTEuMzYgMS4xLTIgMi40Ni0yYTIuNDYgMi40NiAwIDAgMSAwIDQuOTEgMi42MSAyLjYxIDAgMCAxLTEtLjIxTTE2LjkzIDMuNWMwLTEuMzYgMS4xLTIgMi40NS0yYTIuNDYgMi40NiAwIDEgMSAwIDQuOTEgMi41MiAyLjUyIDAgMCAxLTEtLjIxIi8+PHBhdGggY2xhc3M9ImNscy0yIiBkPSJNNyA5aDN2M0g3ek0xMiA5aDN2M2gtM3pNMTcgOWgzdjNoLTN6TTcgMTRoM3YzSDd6TTEyIDE0aDN2M2gtM3pNMTcgMTRoM3YzaC0zeiIvPjxwYXRoIGNsYXNzPSJjbHMtMSIgZD0iTTMuNSAzLjY3djE2LjY2TTMuNSAyMC40M2MwIDEuMjkuNDQgMi4zMyAxLjczIDIuMzNzMi4zMy0xLjkgMi4zMy0zLjE5bDE2Ljk0LS4wN2MwIDEuMjktLjU1IDMuMTItMS44MyAzLjEySDYuMyIvPjwvc3ZnPg==)}.admonition.note .admonition-title:before,.admonition.tip .admonition-title:before,.scylla-icon--exclamation{background-image:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PG1hc2sgaWQ9ImEiIG1hc2stdHlwZT0iYWxwaGEiIG1hc2tVbml0cz0idXNlclNwYWNlT25Vc2UiIHg9IjEiIHk9IjEiIHdpZHRoPSIyMiIgaGVpZ2h0PSIyMiI+PHBhdGggZD0iTTEyIDIzQzUuOSAyMyAxIDE4LjEgMSAxMlM1LjkgMSAxMiAxczExIDQuOSAxMSAxMS00LjkgMTEtMTEgMTFabTAtMjBjLTUgMC05IDQtOSA5czQgOSA5IDkgOS00IDktOS00LTktOS05WiIgZmlsbD0iI2ZmZiIvPjxwYXRoIGQ9Ik0xMiAxM2MtLjYgMC0xLS40LTEtMVY4YzAtLjYuNC0xIDEtMXMxIC40IDEgMXY0YzAgLjYtLjQgMS0xIDFaTTEyIDE3Yy0uMyAwLS41LS4xLS43LS4zLS4yLS4yLS4zLS40LS4zLS43IDAtLjEgMC0uMy4xLS40LjEtLjEuMS0uMi4yLS4zLjMtLjMuNy0uNCAxLjEtLjIuMSAwIC4xIDAgLjIuMSAwIDAgLjEuMS4yLjEuMS4xLjIuMi4yLjN2LjRjMCAuMSAwIC4zLS4xLjQtLjEuMS0uMS4yLS4yLjMtLjIuMi0uNC4zLS43LjNaIiBmaWxsPSIjZmZmIi8+PC9tYXNrPjxnIG1hc2s9InVybCgjYSkiPjxwYXRoIGZpbGw9IiNmZmYiIGQ9Ik0wIDBoMjR2MjRIMHoiLz48L2c+PC9zdmc+)}.collapsible-button i,.scylla-icon--expand{background-image:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYuMDAxIiBoZWlnaHQ9IjE2IiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjxwYXRoIGQ9Ik01IDEzYTEgMSAwIDAgMS0uNzEtLjI5bC00LTRhMSAxIDAgMCAxIDAtMS40MWw0LTRhMSAxIDAgMCAxIDEuNDIgMS40MUwyLjQxIDhsMy4yOSAzLjI5QTEgMSAwIDAgMSA1IDEzeiIvPjxwYXRoIGQ9Ik0xMSA5SDFhMSAxIDAgMCAxIDAtMmgxMGExIDEgMCAwIDEgMCAyek0xNSAxNmExIDEgMCAwIDEtMS0xVjFhMSAxIDAgMCAxIDIgMHYxNGExIDEgMCAwIDEtMSAxeiIvPjwvc3ZnPg==)}.scylla-icon--forum{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSJjdXJyZW50Q29sb3IiIHN0cm9rZS13aWR0aD0iMS41IiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiIGNsYXNzPSJmZWF0aGVyIGZlYXRoZXItdXNlcnMiPjxwYXRoIGQ9Ik0xNyAyMXYtMmE0IDQgMCAwIDAtNC00SDVhNCA0IDAgMCAwLTQgNHYyIi8+PGNpcmNsZSBjeD0iOSIgY3k9IjciIHI9IjQiLz48cGF0aCBkPSJNMjMgMjF2LTJhNCA0IDAgMCAwLTMtMy44N00xNiAzLjEzYTQgNCAwIDAgMSAwIDcuNzUiLz48L3N2Zz4=)}.scylla-icon--home{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyMSAxOSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOm5vbmU7c3Ryb2tlOiM0ZDRkNGQ7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJMYXllcl81IiBkYXRhLW5hbWU9IkxheWVyIDUiPjxwYXRoIGNsYXNzPSJjbHMtMSIgZD0iTTMuNSA2LjE0djExYTEuMzggMS4zOCAwIDAgMCAxLjM3IDEuMzZoMTEuMjZhMS4zOCAxLjM4IDAgMCAwIDEuMzctMS4zN3YtMTEiLz48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Im0xOS41IDcuNS04LTYuMjVhMS41OSAxLjU5IDAgMCAwLTEuOTQgMEwxLjUgNy41TTEyLjczIDE4LjAydi03LjIxSDguMjd2Ny4yMSIvPjwvZz48L3N2Zz4=)}.scylla-icon--getting-started{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyMSAxOSI+PGcgZGF0YS1uYW1lPSJDYWxxdWUgNCI+PHBhdGggc3R5bGU9ImZpbGw6IzRkNGQ0ZCIgZD0ibTcgNC41IDguNTEgNS4wNUw3IDE0LjV2LTEweiIvPjxyZWN0IHg9IjEuNSIgeT0iLjUiIHdpZHRoPSIxOCIgaGVpZ2h0PSIxOCIgcng9IjIuNDMiIHN0eWxlPSJmaWxsOm5vbmU7c3Ryb2tlOiM0ZDRkNGQ7c3Ryb2tlLW1pdGVybGltaXQ6MTAiLz48L2c+PC9zdmc+)}.scylla-icon--glossary{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyMSAxOSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOm5vbmU7c3Ryb2tlOiM0ZDRkNGQ7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJDYWxxdWVfNCIgZGF0YS1uYW1lPSJDYWxxdWUgNCI+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNMi41IDIuNWgxM3YxNmgtMTN6Ii8+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNMTUuNTggMTcuMjFoMS45MlYuNWgtMTNhMi4zNCAyLjM0IDAgMCAwLTIgMiIvPjxwYXRoIGQ9Ik00LjggMTMuOTNhMSAxIDAgMCAwIC43NS0uNDMgNiA2IDAgMCAwIC41Mi0xLjA4bDIuODctNy4wN2guMzZsMi44OCA2Ljc5YTguOTIgOC45MiAwIDAgMCAuNzIgMS40Ny43Ni43NiAwIDAgMCAuNjguMzJ2LjMySDkuNHYtLjMyYTMuMjQgMy4yNCAwIDAgMCAuODMtLjExYy4xMy0uMDYuMi0uMTkuMi0uNDJhMS41OSAxLjU5IDAgMCAwLS4xLS40NmMwLS4xMi0uMS0uMjctLjE3LS40NGwtLjMzLS43OGgtMi45Yy0uMTkuNTEtLjMxLjg1LS4zNiAxYTIuMzggMi4zOCAwIDAgMC0uMTcuNzNjMCAuMTguMTIuMzIuMzcuNGEyLjU2IDIuNTYgMCAwIDAgLjY2LjA4di4zMkg0LjhabTQuODQtMi43Mi0xLjI0LTNoLS4xMWwtMS4xNiAzWiIgc3R5bGU9ImZpbGw6IzRkNGQ0ZCIvPjwvZz48L3N2Zz4=)}.scylla-icon--infoworld{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLW1pdGVybGltaXQ6MTB9PC9zdHlsZT48L2RlZnM+PGcgaWQ9IkNhbHF1ZV80IiBkYXRhLW5hbWU9IkNhbHF1ZSA0Ij48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Ik0xMiAyLjVINi41VjZjMCAzIC41NSA3LjE3IDUgOS41djQiLz48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Ik02LjQgNC40NGgtNFMyLjU2IDExIDguNSAxM00xOC41IDQuNWw0LS4wNnMtLjA2IDYuNTYtNiA4LjU2Ii8+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNMTIgMi41aDYuNVY2YzAgMi45NC0uNCA3LjA4LTUgOS41djRNOS41IDE5LjVoNnYyaC02eiIvPjxwYXRoIHN0eWxlPSJmaWxsOmdyYXk7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLW1pdGVybGltaXQ6MTAiIGQ9Ik03LjUgMjEuNWgxMHYxaC0xMHoiLz48L2c+PC9zdmc+)}.scylla-icon--integrations{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOm5vbmU7c3Ryb2tlOiM0ZDRkNGQ7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJDYWxxdWVfNCIgZGF0YS1uYW1lPSJDYWxxdWUgNCI+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJtMTQuNTYgMTIuNy0xLjI1LTEuNTctMS4zMS43NmE2IDYgMCAwIDAtMS42NS0xbC4wOC0xLjQ5LTItLjQtLjUzIDEuNDRhNS43MyA1LjczIDAgMCAwLTEuODcuMzFsLS44OC0xLjE5LTEuNzcgMUwzLjkyIDEyYTYuMyA2LjMgMCAwIDAtMS4yMiAxLjQxbC0xLjUtLjM1LS43NCAxLjg3IDEuMzguOGE2LjIzIDYuMjMgMCAwIDAgMCAxLjgzbC0xLjQxLjcyLjY0IDEuOTEgMS41OS0uMjhhNy42MyA3LjYzIDAgMCAwIC40OC42OCA1Ljg2IDUuODYgMCAwIDAgLjY3LjczbC0uNjIgMS40NiAxLjcyIDEgMS0xLjI0YTYuNDYgNi40NiAwIDAgMCAxLjc5LjM1bC40NiAxLjUyIDItLjN2LTEuNmE2LjQzIDYuNDMgMCAwIDAgMS42Mi0uODlsMS4zLjg1TDE0LjQzIDIxbC0xLTEuMmE2LjI0IDYuMjQgMCAwIDAgLjY4LTEuNzVsMS41MS0uMTkuMDUtMi0xLjUxLS4yNmE2LjA3IDYuMDcgMCAwIDAtLjYyLTEuODFabS01LjM1IDUuNTFhMS45MyAxLjkzIDAgMSAxIC4zMS0yLjcxIDEuOTIgMS45MiAwIDAgMS0uMzEgMi43MVoiLz48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Im0yNC4zMSA4LjA1LS4xMy0xLjY1LTEuMjUtLjA5YTUuMjYgNS4yNiAwIDAgMC0uNjctMS40NGwuNzUtMS0xLjE2LTEuMTctMSAuNzRhNS4xOCA1LjE4IDAgMCAwLTEuNDMtLjY2bC0uMDYtMS4yNC0xLjY1LS4xNy0uMzIgMS4yNWE1Ljc3IDUuNzcgMCAwIDAtMS41Mi4zOEwxNSAyLjFsLTEuMzcuOS41OCAxLjE4YTQuODggNC44OCAwIDAgMC0uODYgMS4yNWwtMS4zLS4xNi0uNDUgMS42IDEuMjIuNTVhNS4xNyA1LjE3IDAgMCAwIDAgLjY4QTQuMjggNC4yOCAwIDAgMCAxMyA5bC0xLjExLjcyLjY5IDEuNTEgMS4yOC0uMzdhNC45NCA0Ljk0IDAgMCAwIDEuMDcgMS4wN2wtLjM5IDEuMjYgMS41LjcxLjc0LTEuMDlhNS4wNyA1LjA3IDAgMCAwIDEuNTIuMTRsLjUgMS4xOSAxLjYxLS40MS0uMTMtMS4yOWE1LjE0IDUuMTQgMCAwIDAgMS4yNy0uODhsMS4xMi41NyAxLTEuMzUtLjkxLS44OGE0LjkgNC45IDAgMCAwIC40Mi0xLjUyWm0tNi4yIDEuNDNhMS43NCAxLjc0IDAgMSAxIDEuNi0xLjg2IDEuNzQgMS43NCAwIDAgMS0xLjYgMS44NloiLz48L2c+PC9zdmc+)}.scylla-icon--knowledge-base{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyMSAxOSI+PGRlZnM+PHN0eWxlPi5jbHMtMSwuY2xzLTJ7ZmlsbDpub25lO3N0cm9rZTojNGQ0ZDRkfS5jbHMtMXtzdHJva2UtbGluZWNhcDpyb3VuZDtzdHJva2UtbGluZWpvaW46cm91bmR9LmNscy0ye3N0cm9rZS1taXRlcmxpbWl0OjEwfTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJMYXllcl81IiBkYXRhLW5hbWU9IkxheWVyIDUiPjxwYXRoIGNsYXNzPSJjbHMtMSIgZD0iTTE2LjIxIDYuMzhhNS4zNiA1LjM2IDAgMCAxLTEuNTEgMy43MyA1IDUgMCAwIDAtMS40NSAzLjMxSDguNDdhNS40MSA1LjQxIDAgMCAwLTEuMjgtMy4xMSA1LjM3IDUuMzcgMCAxIDEgOS0zLjkzWk0xMy4yMyAxNS42N0g4LjQ1Ii8+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNMTMuMjQgMTMuNGgtNC44djQuMTZhLjcuNyAwIDAgMCAuNzEuN2gzLjM4YS43LjcgMCAwIDAgLjcxLS43WiIvPjxwYXRoIGNsYXNzPSJjbHMtMiIgZD0iTTEwLjg0IDguMjFhMS42NSAxLjY1IDAgMSAxIDEuNjQtMS42NSAxLjY1IDEuNjUgMCAwIDEtMS42NCAxLjY1Wk0xMC44NCA4LjY3djQuNjQiLz48L2c+PC9zdmc+)}.scylla-icon--less{background-image:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTciIGhlaWdodD0iMTciIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHJlY3Qgd2lkdGg9IjE3IiBoZWlnaHQ9IjE3IiByeD0iMSIgZmlsbD0iI0IzQkFDNSIvPjxwYXRoIGQ9Ik0xMyA4LjVhMSAxIDAgMCAxLTEgMUg1YTEgMSAwIDAgMSAwLTJoN2ExIDEgMCAwIDEgMSAxWiIgZmlsbD0iI2ZmZiIvPjxwYXRoIGQ9Ik0xMyA4LjVhMSAxIDAgMCAxLTEgMUg1YTEgMSAwIDAgMSAwLTJoN2ExIDEgMCAwIDEgMSAxWiIgZmlsbD0iI2ZmZiIvPjxwYXRoIGQ9Ik0xMyA4LjVhMSAxIDAgMCAxLTEgMUg1YTEgMSAwIDAgMSAwLTJoN2ExIDEgMCAwIDEgMSAxWiIgZmlsbD0iI2ZmZiIvPjxwYXRoIGQ9Ik0xMyA4LjVhMSAxIDAgMCAxLTEgMUg1YTEgMSAwIDAgMSAwLTJoN2ExIDEgMCAwIDEgMSAxWiIgZmlsbD0iI2ZmZiIvPjxwYXRoIGQ9Ik0xMyA4LjVhMSAxIDAgMCAxLTEgMUg1YTEgMSAwIDAgMSAwLTJoN2ExIDEgMCAwIDEgMSAxWiIgZmlsbD0iI2ZmZiIvPjwvc3ZnPg==);filter:none}.scylla-icon--live-test{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtNntmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLW1pdGVybGltaXQ6MTA7c3Ryb2tlLWxpbmVjYXA6cm91bmR9PC9zdHlsZT48L2RlZnM+PGcgaWQ9IkNhbHF1ZV80IiBkYXRhLW5hbWU9IkNhbHF1ZSA0Ij48Y2lyY2xlIGN4PSIxMi41IiBjeT0iMTUiIHI9IjkuNSIgc3R5bGU9InN0cm9rZS13aWR0aDoxLjVweDtzdHJva2UtbWl0ZXJsaW1pdDoxMDtmaWxsOm5vbmU7c3Ryb2tlOmdyYXkiLz48cGF0aCBzdHlsZT0ic3Ryb2tlLXdpZHRoOjEuMXB4O3N0cm9rZS1saW5lam9pbjpyb3VuZDtzdHJva2UtbGluZWNhcDpyb3VuZDtmaWxsOm5vbmU7c3Ryb2tlOmdyYXkiIGQ9Ik0xMCAuNWg1djJoLTV6Ii8+PHBhdGggc3R5bGU9InN0cm9rZS13aWR0aDoxLjExcHg7c3Ryb2tlLWxpbmVqb2luOnJvdW5kO3N0cm9rZS1saW5lY2FwOnJvdW5kO2ZpbGw6bm9uZTtzdHJva2U6Z3JheSIgZD0iTTUuOCA4LjIgNC4xMyA2LjUzbDEuOC0xLjgxTDcuNiA2LjQiLz48cGF0aCBzdHlsZT0ic3Ryb2tlLXdpZHRoOjEuMTNweDtzdHJva2UtbWl0ZXJsaW1pdDoxMDtmaWxsOm5vbmU7c3Ryb2tlOmdyYXkiIGQ9Ik0xMiA2VjIuNSIvPjxwYXRoIHN0eWxlPSJzdHJva2Utd2lkdGg6MS4wOHB4O3N0cm9rZS1taXRlcmxpbWl0OjEwO2ZpbGw6bm9uZTtzdHJva2U6Z3JheSIgZD0iTTEzIDZWMi41Ii8+PHBhdGggY2xhc3M9ImNscy02IiBkPSJNMTIuNSA4LjA2VjEwTTEyLjUgMjAuMDR2MS44OE03LjEzIDEwLjA4bDEuNzkgMS44OE0xNi4wNCAxNy4wOGwyIDEuODhNNyAxOC45MmwxLjg4LTEuODhNMTYuMTMgMTEuOTZsMS43OS0xLjgzIi8+PGVsbGlwc2UgY3g9IjEyLjUiIGN5PSIxNC4zNiIgcng9IjEuNSIgcnk9IjEuMzYiIHN0eWxlPSJmaWxsOmdyYXkiLz48cGF0aCBjbGFzcz0iY2xzLTYiIGQ9Im0xMi42MyAxNC41NCAyLjUgNi4zOCIvPjwvZz48L3N2Zz4=)}.scylla-icon--mail-list{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSJjdXJyZW50Q29sb3IiIHN0cm9rZS13aWR0aD0iMS41IiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiIGNsYXNzPSJmZWF0aGVyIGZlYXRoZXItbWFpbCI+PHBhdGggZD0iTTQgNGgxNmMxLjEgMCAyIC45IDIgMnYxMmMwIDEuMS0uOSAyLTIgMkg0Yy0xLjEgMC0yLS45LTItMlY2YzAtMS4xLjktMiAyLTJ6Ii8+PHBhdGggZD0ibTIyIDYtMTAgN0wyIDYiLz48L3N2Zz4=)}.scylla-icon--manager{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtM3tmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kO3N0cm9rZS13aWR0aDouOTdweH0uY2xzLTR7ZmlsbDpncmF5fTwvc3R5bGU+PC9kZWZzPjxwYXRoIHN0eWxlPSJmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kIiBkPSJNMTggMmg1djIySDNWMmg0LjkyIiBpZD0iQ2FscXVlXzIiIGRhdGEtbmFtZT0iQ2FscXVlIDIiLz48ZyBpZD0iQ2FscXVlXzQiIGRhdGEtbmFtZT0iQ2FscXVlIDQiPjxwYXRoIHN0eWxlPSJzdHJva2Utd2lkdGg6MS4wN3B4O2ZpbGw6bm9uZTtzdHJva2U6Z3JheTtzdHJva2UtbGluZWNhcDpyb3VuZDtzdHJva2UtbGluZWpvaW46cm91bmQiIGQ9Ik04IDBoMTB2NEg4eiIvPjxwYXRoIGNsYXNzPSJjbHMtMyIgZD0iTTcgOWgzdjNIN3pNNyAxNmgzdjNIN3oiLz48cGF0aCBjbGFzcz0iY2xzLTQiIGQ9Ik0xMi41IDkuNWg3djJoLTd6TTEyLjUgMTYuNWg3djJoLTd6Ii8+PC9nPjwvc3ZnPg==)}.scylla-icon--memory-management{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMSwuY2xzLTJ7ZmlsbDpub25lO3N0cm9rZTpncmF5O3N0cm9rZS1saW5lY2FwOnJvdW5kO3N0cm9rZS1saW5lam9pbjpyb3VuZH0uY2xzLTJ7c3Ryb2tlLXdpZHRoOjEuMTNweH08L3N0eWxlPjwvZGVmcz48ZyBpZD0iQ2FscXVlXzQiIGRhdGEtbmFtZT0iQ2FscXVlIDQiPjxyZWN0IGNsYXNzPSJjbHMtMSIgeD0iNS41IiB5PSI1LjUiIHdpZHRoPSIxNSIgaGVpZ2h0PSIxNSIgcng9IjIuNzQiIHJ5PSIyLjc0Ii8+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNOS41IDkuNWg3djdoLTd6Ii8+PHBhdGggY2xhc3M9ImNscy0yIiBkPSJNOC41IDUuNXYtNE0xMS41IDUuNXYtNE0xNC41IDUuNXYtNE0xNy41IDUuNXYtNE04LjUgMjQuNXYtNE0xMS41IDI0LjV2LTRNMTQuNSAyNC41di00TTE3LjUgMjQuNXYtNE0yMC41IDguNWg0TTIwLjUgMTEuNWg0TTIwLjUgMTQuNWg0TTIwLjUgMTcuNWg0TTEuNSA4LjVoNE0xLjUgMTEuNWg0TTEuNSAxNC41aDRNMS41IDE3LjVoNCIvPjwvZz48L3N2Zz4=)}.scylla-icon--monitoring{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGcgZGF0YS1uYW1lPSJDYWxxdWUgNCI+PHBhdGggZD0iTTUuNTUgMTAuODlhMy44MyAzLjgzIDAgMCAxLS4xNS0zLjc2IiBzdHlsZT0ic3Ryb2tlLWxpbmVqb2luOnJvdW5kO3N0cm9rZS1saW5lY2FwOnJvdW5kO3N0cm9rZTpncmF5O2ZpbGw6bm9uZSIvPjxyZWN0IHg9IjE3LjYzIiB5PSIxNC4wMSIgd2lkdGg9IjMuMDUiIGhlaWdodD0iMTAuOCIgcng9Ii41NyIgcnk9Ii41NyIgdHJhbnNmb3JtPSJyb3RhdGUoLTQ1IDE5LjE1OCAxOS40MDUpIiBzdHlsZT0ic3Ryb2tlLW1pdGVybGltaXQ6MTA7ZmlsbDpncmF5O3N0cm9rZS13aWR0aDouOTVweDtzdHJva2U6Z3JheSIvPjxjaXJjbGUgY3g9IjguNSIgY3k9IjkiIHI9IjciIHN0eWxlPSJzdHJva2Utd2lkdGg6MnB4O3N0cm9rZS1taXRlcmxpbWl0OjEwO3N0cm9rZTpncmF5O2ZpbGw6bm9uZSIvPjxwYXRoIHN0eWxlPSJzdHJva2UtbWl0ZXJsaW1pdDoxMDtzdHJva2UtbGluZWNhcDpyb3VuZDtzdHJva2U6Z3JheTtmaWxsOm5vbmUiIGQ9Im0xNi4wNSAxNi4zOS0yLjI4LTIuMjgiLz48L2c+PC9zdmc+)}.scylla-icon--networking{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMntmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLW1pdGVybGltaXQ6MTB9PC9zdHlsZT48L2RlZnM+PGcgaWQ9IkNhbHF1ZV80IiBkYXRhLW5hbWU9IkNhbHF1ZSA0Ij48Y2lyY2xlIGN4PSIxMi41IiBjeT0iMTIuNSIgcj0iNCIgc3R5bGU9InN0cm9rZS13aWR0aDouOTRweDtmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLW1pdGVybGltaXQ6MTAiLz48Y2lyY2xlIGNsYXNzPSJjbHMtMiIgY3g9IjUiIGN5PSIzIiByPSIyLjUiLz48Y2lyY2xlIGNsYXNzPSJjbHMtMiIgY3g9IjE5IiBjeT0iMjAiIHI9IjIuNSIvPjxjaXJjbGUgY2xhc3M9ImNscy0yIiBjeD0iMjIiIGN5PSI2LjYiIHI9IjIuNSIvPjxjaXJjbGUgY2xhc3M9ImNscy0yIiBjeD0iNC41IiBjeT0iMjIiIHI9IjIuNSIvPjxwYXRoIGNsYXNzPSJjbHMtMiIgZD0ibTYuODMgNS41IDMuMjUgNC4zM00yMC4yMyA3Ljg1IDE1LjMzIDExTTkuODMgMTUuMDhsLTQuMDkgNS44NE0xNC41OCAxNS4zM2wzIDMuMDkiLz48Y2lyY2xlIGN4PSIxMi41IiBjeT0iMTIuNSIgcj0iMS41IiBzdHlsZT0iZmlsbDpncmF5Ii8+PC9nPjwvc3ZnPg==)}.scylla-icon--news{background-image:url(data:image/svg+xml;base64,PHN2ZyBpZD0iQ2FscXVlXzEiIGRhdGEtbmFtZT0iQ2FscXVlIDEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmlld0JveD0iMCAwIDI1IDI1Ij48ZGVmcz48c3R5bGU+LmNscy0xe2ZpbGw6bm9uZTtzdHJva2U6Z3JheTtzdHJva2UtbGluZWNhcDpyb3VuZDtzdHJva2UtbGluZWpvaW46cm91bmR9PC9zdHlsZT48L2RlZnM+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNMyAxNS4xNyAxNi4zMSAzLjgyYTEuNDggMS40OCAwIDAgMSAyLjIyLjQ2bDUuMTUgOS42NWExLjQ2IDEuNDYgMCAwIDEtLjkzIDIuMTJMNS42OSAxOS45Wk04LjcxIDE5LjMzbC43NiAyLjIyYTEuNTEgMS41MSAwIDAgMCAxLjg1IDFsMy41OC0xLjA2YTEuNSAxLjUgMCAwIDAgMS0xLjg2TDE1LjQ1IDE4TTUuNTQgMjBsLTEuODMgMWEuOTIuOTIgMCAwIDEtMS4yNS0uMzdMLjYxIDE3LjQ5QS45Mi45MiAwIDAgMSAxIDE2LjI0bDEuODMtMU04LjUgMTRsNy4zOC01LjUiLz48L3N2Zz4=)}.scylla-icon--newsletter{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMSwuY2xzLTJ7ZmlsbDpub25lO3N0cm9rZTpncmF5O3N0cm9rZS1taXRlcmxpbWl0OjEwfS5jbHMtMntzdHJva2UtbGluZWNhcDpyb3VuZH08L3N0eWxlPjwvZGVmcz48ZyBpZD0iQ2FscXVlXzQiIGRhdGEtbmFtZT0iQ2FscXVlIDQiPjxwYXRoIGNsYXNzPSJjbHMtMSIgZD0iTTE5LjUgOS41aDN2MTJoLTIwdi0xMmgzIi8+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJtMi42NSA5Ljg0IDkuODUgNi44OCA4LjYzLTYuODgiLz48cGF0aCBjbGFzcz0iY2xzLTIiIGQ9Im01LjUgNy41LTMgMk0xNC4zNSAzLjg2bC0xLjQ2LTEuMDktMS40NyAxLjA5TTIxLjUgOS41bC0yLTJNMTkuNSAxMS41di03aC0xNHY3LjQ3Ii8+PC9nPjwvc3ZnPg==)}.scylla-icon--nsql-guides{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGcgZGF0YS1uYW1lPSJDYWxxdWUgNCI+PHJlY3QgeD0iNC4zNyIgeT0iMTMuNzEiIHdpZHRoPSIxLjE1IiBoZWlnaHQ9IjkuNzIiIHJ4PSIuNTQiIHJ5PSIuNTQiIHRyYW5zZm9ybT0icm90YXRlKDQ1IDQuOTQ4IDE4LjU3KSIgc3R5bGU9InN0cm9rZTpncmF5O3N0cm9rZS1taXRlcmxpbWl0OjEwO2ZpbGw6Z3JheTtzdHJva2Utd2lkdGg6MS4wOXB4Ii8+PGNpcmNsZSBjeD0iMTIuMjUiIGN5PSIxMi4yNSIgcj0iNC43NSIgc3R5bGU9InN0cm9rZS13aWR0aDoxLjVweDtmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLW1pdGVybGltaXQ6MTAiLz48cGF0aCBzdHlsZT0ic3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLXdpZHRoOjEuMDZweDtmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLW1pdGVybGltaXQ6MTAiIGQ9Ik04LjUgMjAuNXYzaDE1di0yMWgtMTV2MiIvPjwvZz48L3N2Zz4=)}.scylla-icon--open-source{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfS5jbHMtMntmaWxsOmdyYXl9PC9zdHlsZT48L2RlZnM+PGcgaWQ9IkNhbHF1ZV80IiBkYXRhLW5hbWU9IkNhbHF1ZSA0Ij48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Ik0uMzEgMjEuNTEgNSAxOS42OWEyLjM3IDIuMzcgMCAwIDEgMS44OC4xOWw1LjI0IDEuNjhhMi4yMyAyLjIzIDAgMCAwIDItLjEybDkuNS00Ljc1Yy44LS40NCAxLjY0LTEuMzEgMS4xMy0xLjkxYTIuMzQgMi4zNCAwIDAgMC0yLjY0LS40MkwxOCAxNi4wOSIvPjxwYXRoIGNsYXNzPSJjbHMtMSIgZD0ibS4yNSAxNS42OSA0Ljg4LTEuMjFjMS4yNS0uMyAyLjE3LS42MyAzLjQ0LS4xM2ExNS4yMSAxNS4yMSAwIDAgMCA0IDEuMWg0LjUyYy44NSAwIC45NS41NC45NSAxLjEzYTEgMSAwIDAgMS0xLjA4IDEgNjUuODYgNjUuODYgMCAwIDEtNy0uMzEiLz48cGF0aCBjbGFzcz0iY2xzLTIiIGQ9Ik04LjU2IDkuNjh2LS44MWMwLS45MS0uMzgtMS4yMS0xLjI5LTEuMjFIN1Y2LjNoLjMxYy45MSAwIDEuMjktLjMgMS4yOS0xLjIxdi0uODFjMC0xLjIuNjYtMS45MiAyLjgyLTIuM3YxLjE2Yy0xLjI0LjM1LTEuNDMuNjgtMS40MyAxLjR2Ljg3QTEuNTIgMS41MiAwIDAgMSA4Ljc1IDcgMS41MiAxLjUyIDAgMCAxIDEwIDguNTZ2Ljg3YzAgLjcxLjE5IDEgMS40MyAxLjRWMTJjLTIuMjEtLjM1LTIuODctMS4xMi0yLjg3LTIuMzJaTTE3LjQzIDQuM3YuODFjMCAuOTEuMzcgMS4yMSAxLjI5IDEuMjFIMTl2MS4zNmgtLjMxYy0uOTIgMC0xLjI5LjMtMS4yOSAxLjIxdi44MWMwIDEuMi0uNjUgMi0yLjgxIDIuMzV2LTEuMmMxLjI1LS4zNiAxLjQ0LS42OSAxLjQ0LTEuNHYtLjg3QTEuNTMgMS41MyAwIDAgMSAxNy4yNSA3IDEuNTMgMS41MyAwIDAgMSAxNiA1LjQzdi0uODdjMC0uNzItLjE5LTEtMS40NC0xLjRWMmMyLjIyLjM4IDIuODcgMS4xIDIuODcgMi4zWiIvPjwvZz48L3N2Zz4=)}.scylla-icon--operator{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjQuODEgMS4wMSAyOC4zMiAyNy42NCI+PHBhdGggZD0iTTMyLjUyIDE4cy0uMDkgMC0uMDktLjA1LS4wOCAwLS4xNyAwYTIuMTkgMi4xOSAwIDAgMC0uNTEgMCAuNDcuNDcgMCAwIDEtLjI2LS4wNSA5LjI5IDkuMjkgMCAwIDEtMS40OS0uMzIuNTQuNTQgMCAwIDEtLjMtLjMxbC0uMzQtLjA4YTExLjI1IDExLjI1IDAgMCAwLS4xOC0zLjc5IDExLjU1IDExLjU1IDAgMCAwLTEuNS0zLjUybC4yNi0uMjZhLjU5LjU5IDAgMCAxIC4xMy0uMzkgNy43MyA3LjczIDAgMCAxIDEuMi0uODZsLjI2LS4xMy40Ny0uM3MuMDkgMCAuMTMtLjA4IDAtLjA1IDAtLjA5YS44NC44NCAwIDAgMCAuMTctMS4yLjc4Ljc4IDAgMCAwLS42LS4zIDEgMSAwIDAgMC0uNi4yMWMtLjA1LjA1LS4wOS4wOS0uMTMuMDlhMy4wOCAzLjA4IDAgMCAwLS4zNS4zOWMwIC4wOC0uMTMuMTMtLjE3LjE3YTUuNjQgNS42NCAwIDAgMS0xLjA3Ljk0LjU4LjU4IDAgMCAxLS4yNi4wOS4yNS4yNSAwIDAgMS0uMTcgMGgtLjA1bC0uMzQuMjEtMS4wOC0xYTExIDExIDAgMCAwLTUuNjUtMi4yN3YtLjM0YS42LjYgMCAwIDEtLjIyLS4zNEE4LjE4IDguMTggMCAwIDEgMTkuNjYgM3YtLjI1YzAtLjA4LjA1LS4zNS4wOS0uNTJ2LS4zMWEuODIuODIgMCAwIDAtMS40Ni0uNi44Ni44NiAwIDAgMC0uMjYuNnYuMjJhMS44MiAxLjgyIDAgMCAwIC4wOS41MS41OS41OSAwIDAgMSAwIC4yNlYzYTguODIgOC44MiAwIDAgMSAuMDggMS40Ny41OS41OSAwIDAgMS0uMjEuMzRWNS4yNGMtLjQ4IDAtMSAuMTMtMS40Ny4yMmExMC4xNiAxMC4xNiAwIDAgMC01LjI4IDNMMTEgOC4yNGgtLjE3YS43My43MyAwIDAgMS0uMjYtLjA5IDcuOCA3LjggMCAwIDEtMS4wNy0xYzAtLjA4LS4xMy0uMTMtLjE3LS4xN3MtLjI1LS4yLS4zMy0uMzMtLjA4IDAtLjEzLS4wOHYtLjA1YTEgMSAwIDAgMC0uNi0uMjEuNjQuNjQgMCAwIDAtLjYuMy45MS45MSAwIDAgMCAuMTcgMS4yczAgLjA1IDAgLjA1LjA5LjA4LjEzLjA4YTUgNSAwIDAgMCAuNDcuMjZsLjI2LjEzYTYuNjEgNi42MSAwIDAgMSAxLjIxLjg2LjQ3LjQ3IDAgMCAxIC4xMy4zOXYtLjA1bC4yNS4yNmEyLjUzIDIuNTMgMCAwIDEtLjEzLjIyIDEwLjIgMTAuMiAwIDAgMC0xLjUgN2wtLjM1LjA5YzAgLjEzLS4xNy4yMS0uMy4zYTguNTYgOC41NiAwIDAgMS0xLjQ2LjI2LjU5LjU5IDAgMCAwLS4yNiAwaC0uNTJjLS4xOCAwLS4wOC4wNS0uMTcuMDVoLS4wOGEuODQuODQgMCAwIDAtLjY5IDEgLjc5Ljc5IDAgMCAwIC44Ni42LjM5LjM5IDAgMCAwIC4yMSAwSDYuMTJhMy42MSAzLjYxIDAgMCAwIC40Ny0uMTcuNjUuNjUgMCAwIDEgLjI2LS4wOCA3LjY1IDcuNjUgMCAwIDEgMS40Mi0uMzkuNDkuNDkgMCAwIDEgLjM1LjEzaC4zOWExMC4zMiAxMC4zMiAwIDAgMCAzLjUzIDUgNi4zMSA2LjMxIDAgMCAwIDEuMTYuNzdsLS4yMi4zYS41MS41MSAwIDAgMSAwIC40MyA2LjU0IDYuNTQgMCAwIDEtLjY5IDEuMjR2LjA1YS43OC43OCAwIDAgMS0uMTcuMjFjLS4wOS4wOS0uMTcuMjYtLjMuNDNzMCAuMDktLjA5LjEzIDAgLjA1IDAgLjA1YS44OC44OCAwIDAgMCAuMzQgMS4xNi45LjkgMCAwIDAgLjMuMDggMSAxIDAgMCAwIC44Mi0uNTFzMC0uMDguMDktLjEzLjEzLS4zLjE3LS40N2wuMDktLjI2YTcuMDcgNy4wNyAwIDAgMSAuNTYtMS4zMy42Mi42MiAwIDAgMSAuMzQtLjI2bC4xNy0uMzVhMTAuMDUgMTAuMDUgMCAwIDAgMy43NS42OSA4LjQ1IDguNDUgMCAwIDAgMi4zMi0uMyAxMS40NiAxMS40NiAwIDAgMCAxLjM3LS4zOWwuMTguMzFhLjYyLjYyIDAgMCAxIC4zNC4yNiA3LjA3IDcuMDcgMCAwIDEgLjU2IDEuMzNsLjA5LjI2YTEuMzEgMS4zMSAwIDAgMCAuMTcuNDdjMCAuMDUgMCAuMDkuMDkuMTNhMSAxIDAgMCAwIC44Mi41MSAxLjA1IDEuMDUgMCAwIDAgLjM0LS4wOC43Ni43NiAwIDAgMCAuMzktLjQ4IDEuMDggMS4wOCAwIDAgMC0uMDUtLjY0LjIuMiAwIDAgMC0uMDgtLjEzIDEuNTMgMS41MyAwIDAgMC0uMzEtLjQzLjY1LjY1IDAgMCAwLS4xNy0uMjJ2LS4wOWE1LjIyIDUuMjIgMCAwIDEtLjY5LTEuMjQuNTEuNTEgMCAwIDEgLjA1LS40M2wtLjEzLS4zNEExMC42OCAxMC42OCAwIDAgMCAyOSAxOC44MmwuMzQuMDV2LS4wNWEuNTQuNTQgMCAwIDEgLjM1LS4xMyA3LjgyIDcuODIgMCAwIDEgMS4zOC4zOS42Mi42MiAwIDAgMCAuMjYuMDkgMi40MiAyLjQyIDAgMCAwIC40Ny4yMXMuMDkgMCAuMTcgMGguMDlhLjM5LjM5IDAgMCAwIC4yMSAwIC45NC45NCAwIDAgMCAuODYtLjYgMSAxIDAgMCAwLS43Ny0uOVptLTEyLjQzLTEuMzMtMS4xNi41Ni0xLjE2LS41Ni0uMy0xLjI1LjgxLTFoMS4yOWwuODIgMVptNy0yLjc5YTggOCAwIDAgMSAuMTcgMi43MWwtNC4xNS0uNzVjLS4zOC0uMDgtLjY4LS45LS43MS0xLjIyYTQgNCAwIDAgMSAuMjEtLjc0bDMuNDUtMi41NGE4LjU4IDguNTggMCAwIDEgMS4wNCAyLjU0Wm0tMi4zMS00LjEzLTMuMjIgMi42OWExLjI4IDEuMjggMCAwIDEtMS4yNS0uMzdjLS4wOS0uMDktLjM3LS4yNS0uMzctLjM4VjcuNDNhOC4wNyA4LjA3IDAgMCAxIDQuODYgMi4zMlpNMTcgNy41NmwxLS4xOC0uMDYgNC4zMWMwIC4zOC0uNjQuNjgtMSAuNjhhMS4xMSAxLjExIDAgMCAxLS4zNS0uMDhMMTMgOS43NWE4LjQxIDguNDEgMCAwIDEgNC0yLjE5Wm0tNS4yNCAzLjc4IDMuMzcgMi40Ny4zMi41M2ExLjE0IDEuMTQgMCAwIDEtLjI1IDEgLjc4Ljc4IDAgMCAxLS4zOC4zMWwtNC4zMS45YTkgOSAwIDAgMSAxLjI0LTUuMjFaTTExIDE4LjYxbDQuMS0xLjIzYy4zNSAwIC44NC43MS44OSAxLjA2YS41MS41MSAwIDAgMS0uMDUuNDNsLTEuNjMgMy45NUE4LjQxIDguNDEgMCAwIDEgMTEgMTguNjFabTkuNzYgNS4zM2E4LjY3IDguNjcgMCAwIDEtMS44NS4yMSA5LjU5IDkuNTkgMCAwIDEtMi43MS0uNDNsMS42Ni00Yy4yMS0uMjYgMS0uMiAxLjMxIDBhMi40OCAyLjQ4IDAgMCAxIC4zNC4zbDIuMDcgMy43NGE1LjcyIDUuNzIgMCAwIDAtLjguMThaTTI2IDIwLjJhOC4zNiA4LjM2IDAgMCAxLTIuNTggMi41OGwtMS45Mi0zLjcyYTEuMTUgMS4xNSAwIDAgMSAuNDEtMWMuMjEtLjI1LjU5LS41OS43MS0uNTlsNC4yMiAxLjA2QTYuMjcgNi4yNyAwIDAgMSAyNiAyMC4yWiIgc3R5bGU9ImZpbGw6IzRkNGQ0ZCIgZGF0YS1uYW1lPSJDYWxxdWUgMiIvPjwvc3ZnPg==)}.scylla-icon--overview{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJDYWxxdWVfNCIgZGF0YS1uYW1lPSJDYWxxdWUgNCI+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNMjIuNjEgMy40NUMyMi42MSA1LjA2IDE4IDYuNSAxMi41IDYuNXMtMTAtMS40NC0xMC0zIDQuNS0zIDEwLTMgMTAuMTEgMS4zMyAxMC4xMSAyLjk1Wk0yMi42MSA5LjQ0YzAgMS42MS00LjY0IDMuMDYtMTAuMTEgMy4wNnMtMTAtMS40NS0xMC0zLjA2TTIyLjYxIDE1LjUxYzAgMS42Mi00LjY0IDMtMTAuMTEgM3MtMTAtMS4zNy0xMC0zTTIyLjYxIDIxLjU5YzAgMS42Mi00LjY0IDIuOTEtMTAuMTEgMi45MXMtMTAtMS4yOS0xMC0yLjkxTTIuNSAyMS40N1YzLjQ1TTIyLjUgMjEuNDdWMy40NSIvPjwvZz48L3N2Zz4=)}.scylla-icon--partners{background-image:url(data:image/svg+xml;base64,PHN2ZyBpZD0iQ2FscXVlXzEiIGRhdGEtbmFtZT0iQ2FscXVlIDEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmlld0JveD0iMCAwIDI1IDI1Ij48ZGVmcz48c3R5bGU+LmNscy0xe2ZpbGw6bm9uZTtzdHJva2U6Z3JheTtzdHJva2UtbGluZWNhcDpyb3VuZDtzdHJva2UtbGluZWpvaW46cm91bmR9PC9zdHlsZT48L2RlZnM+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNMTguNSA4LjI2aC00LjcybC0xLjIzIDEuMjdNMi4zOSAxNS4wOS4xNSAxMy43NGw0Ljg3LTguNDIgMi4yNCAxLjM0LTQuODcgOC40M3pNMjIuNTkgMTUuMDlsMi4yNC0xLjM1LTQuODYtOC40Mi0yLjI0IDEuMzQgNC44NiA4LjQzek0xMC43MSAxNS4yNmwtMi45MyAyLjIxTTEyLjE4IDE2LjRsLTIuOTMgMi4yMU0xMy42OCAxNy41M2wtMi45MyAyLjIyIi8+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNNi4zOCA4LjNoMy43OGEyLjI3IDIuMjcgMCAwIDEgMS4zNy40N2MxLjI2IDEgNC4wOSAzLjE4IDQuNDggMy41NnMtMS4xNCAxLjY4LTIuMjcgMS4xYTE4LjM0IDE4LjM0IDAgMCAwLTIuMTEtLjkyLjU3LjU3IDAgMCAwLS41Ni4wOWwtNC43OSAzLjg5TDEyLjMzIDIxbDkuNDYtNy4wOU0zLjI0IDE0LjIybDMuNCAxLjg1Ii8+PC9zdmc+)}.scylla-icon--plus{background-image:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTciIGhlaWdodD0iMTciIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHJlY3Qgd2lkdGg9IjE3IiBoZWlnaHQ9IjE3IiByeD0iMSIgZmlsbD0iI0IzQkFDNSIvPjxwYXRoIGZpbGwtcnVsZT0iZXZlbm9kZCIgY2xpcC1ydWxlPSJldmVub2RkIiBkPSJNOS41IDVhMSAxIDAgMSAwLTIgMHYyLjVINWExIDEgMCAxIDAgMCAyaDIuNVYxMmExIDEgMCAxIDAgMiAwVjkuNUgxMmExIDEgMCAxIDAgMC0ySDkuNVY1WiIgZmlsbD0iI2ZmZiIvPjxwYXRoIGZpbGwtcnVsZT0iZXZlbm9kZCIgY2xpcC1ydWxlPSJldmVub2RkIiBkPSJNOS41IDVhMSAxIDAgMSAwLTIgMHYyLjVINWExIDEgMCAxIDAgMCAyaDIuNVYxMmExIDEgMCAxIDAgMiAwVjkuNUgxMmExIDEgMCAxIDAgMC0ySDkuNVY1WiIgZmlsbD0iI2ZmZiIvPjxwYXRoIGZpbGwtcnVsZT0iZXZlbm9kZCIgY2xpcC1ydWxlPSJldmVub2RkIiBkPSJNOS41IDVhMSAxIDAgMSAwLTIgMHYyLjVINWExIDEgMCAxIDAgMCAyaDIuNVYxMmExIDEgMCAxIDAgMiAwVjkuNUgxMmExIDEgMCAxIDAgMC0ySDkuNVY1WiIgZmlsbD0iI2ZmZiIvPjxwYXRoIGZpbGwtcnVsZT0iZXZlbm9kZCIgY2xpcC1ydWxlPSJldmVub2RkIiBkPSJNOS41IDVhMSAxIDAgMSAwLTIgMHYyLjVINWExIDEgMCAxIDAgMCAyaDIuNVYxMmExIDEgMCAxIDAgMiAwVjkuNUgxMmExIDEgMCAxIDAgMC0ySDkuNVY1WiIgZmlsbD0iI2ZmZiIvPjxwYXRoIGZpbGwtcnVsZT0iZXZlbm9kZCIgY2xpcC1ydWxlPSJldmVub2RkIiBkPSJNOS41IDVhMSAxIDAgMSAwLTIgMHYyLjVINWExIDEgMCAxIDAgMCAyaDIuNVYxMmExIDEgMCAxIDAgMiAwVjkuNUgxMmExIDEgMCAxIDAgMC0ySDkuNVY1WiIgZmlsbD0iI2ZmZiIvPjwvc3ZnPg==);filter:none}.scylla-icon--pricing{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJDYWxxdWVfMiIgZGF0YS1uYW1lPSJDYWxxdWUgMiI+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJtMjEuNzMgNy0yLjQxLTUuMTJhMi41MiAyLjUyIDAgMCAwLTIuODItMWwtNi4wOCAyLjA0QTEuNjkgMS42OSAwIDAgMCA5LjUxIDRMMy45MyAxOS4yOWExLjA2IDEuMDYgMCAwIDAgLjY0IDEuMTdsMTAuMzQgMy43NmExIDEgMCAwIDAgMS4yMi0uNDNsNS41OC0xNS4zM0ExLjg3IDEuODcgMCAwIDAgMjEuNzMgN1oiLz48Y2lyY2xlIGNsYXNzPSJjbHMtMSIgY3g9IjE1LjczIiBjeT0iNS44OSIgcj0iMiIvPjx0ZXh0IHRyYW5zZm9ybT0icm90YXRlKDIwIC00OC4yNDQgMzAuNjcpIiBzdHlsZT0iZm9udC1zaXplOjEycHg7ZmlsbDpncmF5O2ZvbnQtZmFtaWx5OlJvYm90by1NZWRpdW0sUm9ib3RvIj4kPC90ZXh0PjwvZz48L3N2Zz4=)}.scylla-icon--release-note{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMntmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kO3N0cm9rZS13aWR0aDouOTFweH08L3N0eWxlPjwvZGVmcz48ZyBpZD0iQ2FscXVlXzIiIGRhdGEtbmFtZT0iQ2FscXVlIDIiPjxwYXRoIHN0eWxlPSJzdHJva2Utd2lkdGg6LjlweDtmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kIiBkPSJNMjEuNSAyNC41aC0xN1Y1LjdMOC45NS41NCAyMS41LjV2MjR6Ii8+PHBhdGggY2xhc3M9ImNscy0yIiBkPSJNNC42NSA1LjVIOS41VjFNNy41IDguNWgxMU03LjUgMTEuNWgxMU03LjUgMTQuNWgxMU03LjUgMTcuNWgxMU03LjUgMjAuNWgxMSIvPjwvZz48L3N2Zz4=)}.scylla-icon--resource-center{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfS5jbHMtMntmaWxsOmdyYXl9PC9zdHlsZT48L2RlZnM+PGcgaWQ9IkNhbHF1ZV80IiBkYXRhLW5hbWU9IkNhbHF1ZSA0Ij48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Ik01LjUgMi41aDYuOTFsLjA5IDIwaC03di0yMHoiLz48cGF0aCBjbGFzcz0iY2xzLTIiIGQ9Ik04IDRoMnYxMC45N0w4IDE1VjR6Ii8+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNNS4zNiAyLjI5IDIuNSAzLjV2MThsMi43OSAxLjE0Ii8+PHBhdGggc3R5bGU9InN0cm9rZS13aWR0aDouNjhweDtmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kIiBkPSJtMTIuNTcgMjEuODYgMS41Ny43NSIvPjxwYXRoIHN0eWxlPSJzdHJva2Utd2lkdGg6Ljg1cHg7ZmlsbDpub25lO3N0cm9rZTpncmF5O3N0cm9rZS1saW5lY2FwOnJvdW5kO3N0cm9rZS1saW5lam9pbjpyb3VuZCIgZD0ibTE0LjExIDIuNS0xLjU0LjU3Ii8+PGNpcmNsZSBjbGFzcz0iY2xzLTIiIGN4PSI5IiBjeT0iMTkiIHI9IjEiLz48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Ik0xNC41IDIuNWg2Ljk0bC4wNiAyMGgtN3YtMjB6Ii8+PHBhdGggY2xhc3M9ImNscy0yIiBkPSJNMTcgNGgydjEwLjk3TDE3IDE1VjR6Ii8+PGNpcmNsZSBjbGFzcz0iY2xzLTIiIGN4PSIxOCIgY3k9IjE5IiByPSIxIi8+PHBhdGggY2xhc3M9ImNscy0yIiBkPSJNMTIuNiAyLjczaDEuNjdWMjIuNkgxMi42ek0yLjU4IDIxLjVsMi43NSAxLjFWMi43M2wtMi42Ni45NC0uMDkgMTcuODN6Ii8+PC9nPjwvc3ZnPg==)}.scylla-icon--roadmap{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMSwuY2xzLTJ7ZmlsbDpub25lO3N0cm9rZTpncmF5fS5jbHMtMXtzdHJva2UtbGluZWNhcDpyb3VuZDtzdHJva2UtbGluZWpvaW46cm91bmQ7c3Ryb2tlLXdpZHRoOi45OHB4fS5jbHMtMntzdHJva2UtbWl0ZXJsaW1pdDoxMH0uY2xzLTN7ZmlsbDpncmF5fTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJDYWxxdWVfNCIgZGF0YS1uYW1lPSJDYWxxdWUgNCI+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJtLjUgNC41IDgtMyA4IDQgOC0zdjE3bC04IDMtOC00LTggM3YtMTd6TTguNSAxLjVWMThNMTYuNSA1LjVWMjIiLz48cGF0aCBjbGFzcz0iY2xzLTIiIGQ9Ik0yLjUgMTMgNyAxNi41TTcgMTJsLTQuNSA1LjVNMTguNSA4bDQuNSAzLjVNMjMgN2wtNC41IDUuNSIvPjxwYXRoIGNsYXNzPSJjbHMtMyIgZD0iTTEwIDEzaDF2MWgtMXpNMTIgMTJoMXYxaC0xek0xNCAxMWgxdjFoLTF6Ii8+PC9nPjwvc3ZnPg==)}.scylla-icon--search{background-image:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZD0iTTEwLjUgMThhNy41IDcuNSAwIDEgMCAwLTE1IDcuNSA3LjUgMCAwIDAgMCAxNVpNMjEgMjFsLTUuMi01LjIiIHN0cm9rZT0iIzAwMCIgc3Ryb2tlLXdpZHRoPSIyIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiLz48L3N2Zz4=)}.scylla-icon--slack{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0NDggNTEyIj48IS0tISBGb250IEF3ZXNvbWUgUHJvIDYuMC4wIGJ5IEBmb250YXdlc29tZSAtIGh0dHBzOi8vZm9udGF3ZXNvbWUuY29tIExpY2Vuc2UgLSBodHRwczovL2ZvbnRhd2Vzb21lLmNvbS9saWNlbnNlIChDb21tZXJjaWFsIExpY2Vuc2UpIENvcHlyaWdodCAyMDIyIEZvbnRpY29ucywgSW5jLi0tPjxwYXRoIGQ9Ik05NC4xMiAzMTUuMWMwIDI1LjktMjEuMTYgNDcuMDYtNDcuMDYgNDcuMDZTMCAzNDEgMCAzMTUuMWMwLTI1LjkgMjEuMTYtNDcuMDYgNDcuMDYtNDcuMDZoNDcuMDZ2NDcuMDZ6bTIzLjcyIDBjMC0yNS45IDIxLjE2LTQ3LjA2IDQ3LjA2LTQ3LjA2czQ3LjA2IDIxLjE2IDQ3LjA2IDQ3LjA2djExNy44NGMwIDI1LjktMjEuMTYgNDcuMDYtNDcuMDYgNDcuMDZzLTQ3LjA2LTIxLjE2LTQ3LjA2LTQ3LjA2VjMxNS4xem00Ny4wNi0xODguOThjLTI1LjkgMC00Ny4wNi0yMS4xNi00Ny4wNi00Ny4wNlMxMzkgMzIgMTY0LjkgMzJzNDcuMDYgMjEuMTYgNDcuMDYgNDcuMDZ2NDcuMDZIMTY0Ljl6bTAgMjMuNzJjMjUuOSAwIDQ3LjA2IDIxLjE2IDQ3LjA2IDQ3LjA2cy0yMS4xNiA0Ny4wNi00Ny4wNiA0Ny4wNkg0Ny4wNkMyMS4xNiAyNDMuOTYgMCAyMjIuOCAwIDE5Ni45czIxLjE2LTQ3LjA2IDQ3LjA2LTQ3LjA2SDE2NC45em0xODguOTggNDcuMDZjMC0yNS45IDIxLjE2LTQ3LjA2IDQ3LjA2LTQ3LjA2IDI1LjkgMCA0Ny4wNiAyMS4xNiA0Ny4wNiA0Ny4wNnMtMjEuMTYgNDcuMDYtNDcuMDYgNDcuMDZoLTQ3LjA2VjE5Ni45em0tMjMuNzIgMGMwIDI1LjktMjEuMTYgNDcuMDYtNDcuMDYgNDcuMDYtMjUuOSAwLTQ3LjA2LTIxLjE2LTQ3LjA2LTQ3LjA2Vjc5LjA2YzAtMjUuOSAyMS4xNi00Ny4wNiA0Ny4wNi00Ny4wNiAyNS45IDAgNDcuMDYgMjEuMTYgNDcuMDYgNDcuMDZWMTk2Ljl6TTI4My4xIDM4NS44OGMyNS45IDAgNDcuMDYgMjEuMTYgNDcuMDYgNDcuMDYgMCAyNS45LTIxLjE2IDQ3LjA2LTQ3LjA2IDQ3LjA2LTI1LjkgMC00Ny4wNi0yMS4xNi00Ny4wNi00Ny4wNnYtNDcuMDZoNDcuMDZ6bTAtMjMuNzJjLTI1LjkgMC00Ny4wNi0yMS4xNi00Ny4wNi00Ny4wNiAwLTI1LjkgMjEuMTYtNDcuMDYgNDcuMDYtNDcuMDZoMTE3Ljg0YzI1LjkgMCA0Ny4wNiAyMS4xNiA0Ny4wNiA0Ny4wNiAwIDI1LjktMjEuMTYgNDcuMDYtNDcuMDYgNDcuMDZIMjgzLjF6Ii8+PC9zdmc+)}.scylla-icon--stack-overflow{background-image:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjQiIGhlaWdodD0iMzEiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Im0yMS45NDkuMTEzIDIuMDQzIDExLjY3LTIuNTE0LjQzMkwxOS40MzUuNTQ1IDIxLjk1LjExNFptLTE3Ljk3MyAyNiAxMS45NDUtLjAwNS0uMDAyLTIuNTMtMTEuOTQ0LjAwNi4wMDEgMi41M1ptMTIuMjMyLTUuNzc3TDQuMzE1IDE5LjI1bC0uMjM1IDIuNTIgMTEuODk0IDEuMDg1LjIzNC0yLjUxOVptLTEwLjc1LTYuMzc1IDExLjUzNSAzLjA3NC0uNjYyIDIuNDQzLTExLjUzNS0zLjA3NS42NjItMi40NDJabTEzLjA0LjE4TDguMjEyIDguMTI2bC0xLjI5NyAyLjE3OCAxMC4yODkgNi4wMTcgMS4yOTYtMi4xNzhabS00LjIwNi0xMS41NiA2LjczIDkuNzg3LTIuMTA4IDEuNDI0LTYuNzMtOS43ODUgMi4xMDgtMS40MjVaIiBmaWxsPSIjMDAwIi8+PHBhdGggZD0iTTE3Ljk1IDE3Ljc4OVYyOC4xM0gyLjI4MlYxNy43ODlILjI0M3YxMi4zMjZIMTkuOThWMTcuNzg5aC0yLjAzWiIgZmlsbD0iIzAwMCIvPjwvc3ZnPg==)}.scylla-icon--summit{background-image:url(data:image/svg+xml;base64,PHN2ZyBpZD0iQ2FscXVlXzEiIGRhdGEtbmFtZT0iQ2FscXVlIDEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmlld0JveD0iMCAwIDI1IDI1Ij48ZGVmcz48c3R5bGU+LmNscy0xe2ZpbGw6bm9uZTtzdHJva2U6IzRkNGQ0ZDtzdHJva2UtbGluZWNhcDpyb3VuZDtzdHJva2UtbGluZWpvaW46cm91bmR9PC9zdHlsZT48L2RlZnM+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJtMTYuNSAyMiAxLTYuNS0xMCAuMDMgMSA2LjQzIi8+PHBhdGggZD0iTTMuNDYgMTJBNS42OSA1LjY5IDAgMCAxIDUgNy41IiBzdHlsZT0ic3Ryb2tlLXdpZHRoOjEuMXB4O3N0cm9rZTojNGQ0ZDRkO3N0cm9rZS1saW5lY2FwOnJvdW5kO3N0cm9rZS1saW5lam9pbjpyb3VuZDtmaWxsOm5vbmUiLz48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Ik0xNC42MiA1YTIuMzMgMi4zMyAwIDAgMS0yLjI1IDIuNWMtMS4zMyAwLTItMS4xMi0xLjk1LTIuNDRzLjctMi41IDItMi40OEEyLjI3IDIuMjcgMCAwIDEgMTQuNjIgNVpNMTcuNTggMTJhMy4yMyAzLjIzIDAgMCAwLTMuNDYtMy41SDExQTMuMjYgMy4yNiAwIDAgMCA3LjUgMTIiLz48Y2lyY2xlIGN4PSI0Ljk0IiBjeT0iNi45NiIgcj0iMS4wMSIgc3R5bGU9ImZpbGw6IzRkNGQ0ZDtzdHJva2Utd2lkdGg6MS4xcHg7c3Ryb2tlOiM0ZDRkNGQ7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kIi8+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNNy41NCAxOC41SDQuNWwtMi02aDIwbC0yIDZoLTMiLz48L3N2Zz4=)}.scylla-icon--support{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJDYWxxdWVfNCIgZGF0YS1uYW1lPSJDYWxxdWUgNCI+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNMTguMTkgNy41YTEwIDEwIDAgMCAxIC4yMSAyLjA3YzAgNC4zNi0yLjYzIDYuOTMtNS45IDYuOTNzLTUuOTQtMi41Ny01Ljk0LTYuOTNhMTAuNTEgMTAuNTEgMCAwIDEgLjIyLTIuMTIiLz48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Ik03LjY3IDIuMjNBNi41OCA2LjU4IDAgMCAxIDEyLjUuNWE1LjY1IDUuNjUgMCAwIDEgNC4yOSAxLjdjMS45MyAxLjk0IDIuMzUgNS4wNyAyLjQzIDYuNzJhMS40OSAxLjQ5IDAgMCAwLS43OS4wNSA4LjY4IDguNjggMCAwIDAtLjA4LTEuMTZoMGE1LjUzIDUuNTMgMCAwIDEtMS43Ny0yLjM0TDE2LjQ5IDVsLS4zOC4yMkExOSAxOSAwIDAgMSA2LjggNy4zOGEuNTIuNTIgMCAwIDAtLjQyLjE2Yy0uMjMuMjQtLjE1LjY1LS4wNyAxLjA4IDAgLjExIDAgLjIyLjA1LjMyYTEuNCAxLjQgMCAwIDAtLjU4IDBjLS4xLTEuNDUtLjA2LTQuNjggMS44OS02LjcxWk02LjM4IDljLS42NS0uMDgtMSAuMS0xLjE0Ljc5YTIuMDYgMi4wNiAwIDAgMCAxLjM3IDIuMjlNMTguNTYgOWMuNjUtLjA4IDEuMDUuMSAxLjE0Ljc5YTIuMDYgMi4wNiAwIDAgMS0xLjM3IDIuMjlNOS41IDE4LjIzVjE1LjVNMTUuNSAxNS41djIuNzNNMi41IDI0LjE2Yy4yNC0yIC41OS0zLjYzIDIuNDMtNC40OWEyNC4yOSAyNC4yOSAwIDAgMSA0LjgyLTEuMzdNMjIuNSAyNC4zM2MtLjI0LTItLjQyLTMuOC0yLjI2LTQuNjZhMjQuMjkgMjQuMjkgMCAwIDAtNC44Mi0xLjM3Ii8+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNMTUuMzkgMTguMzlhNC4zNyA0LjM3IDAgMCAxLTIuOTEgMS4wNyA0LjQyIDQuNDIgMCAwIDEtMi44OS0xLjA1Ii8+PHBhdGggc3R5bGU9ImZpbGw6Z3JheSIgZD0iTTExIDEzaDN2MmgtM3oiLz48cGF0aCBkPSJNMTguMDcgMTJhOS4yMSA5LjIxIDAgMCAxLTUuNTMgMi4wNyIgc3R5bGU9InN0cm9rZS1taXRlcmxpbWl0OjEwO2ZpbGw6bm9uZTtzdHJva2U6Z3JheSIvPjwvZz48L3N2Zz4=)}.scylla-icon--tech-talks{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJDYWxxdWVfNCIgZGF0YS1uYW1lPSJDYWxxdWUgNCI+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNOC4zOSA0LjVIMjMuNXYxM2gtMTUiLz48Y2lyY2xlIGN4PSI0LjUiIGN5PSI2LjUiIHI9IjIiIHN0eWxlPSJzdHJva2UtbWl0ZXJsaW1pdDoxMDtmaWxsOm5vbmU7c3Ryb2tlOmdyYXkiLz48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Ik0xLjUgOS41aDJsLjguODYuNy0uODZoNS41OGExIDEgMCAxIDEgMCAySDYuNXYxMC44OGExIDEgMCAwIDEtMSAxLjEyIDEgMSAwIDAgMS0xLTEgMSAxIDAgMCAxLTEgMSAuOTMuOTMgMCAwIDEtMS0xdi02Yy0uNzggMC0yLS40Ny0yLTF2LTVhMSAxIDAgMCAxIDEtMVoiLz48L2c+PC9zdmc+)}.scylla-icon--testing{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJDYWxxdWVfNCIgZGF0YS1uYW1lPSJDYWxxdWUgNCI+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNNi41IDYuNWgxMnYxMmgtMTJ6Ii8+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNNC41IDQuNWgxNnYxNmgtMTZ6Ii8+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJtOC41IDEwLjUgNSA1IDExLTEyIi8+PC9nPjwvc3ZnPg==)}.scylla-icon--thumbs-up{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSJjdXJyZW50Q29sb3IiIHN0cm9rZS13aWR0aD0iMiIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIiBjbGFzcz0iZmVhdGhlciBmZWF0aGVyLXRodW1icy11cCI+PHBhdGggZD0iTTE0IDlWNWEzIDMgMCAwIDAtMy0zbC00IDl2MTFoMTEuMjhhMiAyIDAgMCAwIDItMS43bDEuMzgtOWEyIDIgMCAwIDAtMi0yLjN6TTcgMjJINGEyIDIgMCAwIDEtMi0ydi03YTIgMiAwIDAgMSAyLTJoMyIvPjwvc3ZnPg==)}.scylla-icon--thumbs-down{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSJjdXJyZW50Q29sb3IiIHN0cm9rZS13aWR0aD0iMiIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIiBjbGFzcz0iZmVhdGhlciBmZWF0aGVyLXRodW1icy1kb3duIj48cGF0aCBkPSJNMTAgMTV2NGEzIDMgMCAwIDAgMyAzbDQtOVYySDUuNzJhMiAyIDAgMCAwLTIgMS43bC0xLjM4IDlhMiAyIDAgMCAwIDIgMi4zem03LTEzaDIuNjdBMi4zMSAyLjMxIDAgMCAxIDIyIDR2N2EyLjMxIDIuMzEgMCAwIDEtMi4zMyAySDE3Ii8+PC9zdmc+)}.scylla-icon--tip{background-image:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZD0iTTEyIDI0QzUuNCAyNCAwIDE4LjYgMCAxMlM1LjQgMCAxMiAwczEyIDUuNCAxMiAxMi01LjQgMTItMTIgMTJabTAtMjJDNi41IDIgMiA2LjUgMiAxMnM0LjUgMTAgMTAgMTAgMTAtNC41IDEwLTEwUzE3LjUgMiAxMiAyWiIgZmlsbD0iI2ZmZiIvPjxwYXRoIGQ9Ik0xMSAxNmMtLjMgMC0uNS0uMS0uNy0uM2wtMy0zYy0uNC0uNC0uNC0xIDAtMS40LjQtLjQgMS0uNCAxLjQgMGwzIDNjLjQuNC40IDEgMCAxLjQtLjIuMi0uNC4zLS43LjNaIiBmaWxsPSIjZmZmIi8+PHBhdGggZD0iTTExIDE2Yy0uMyAwLS41LS4xLS43LS4zLS40LS40LS40LTEgMC0xLjRsNi02Yy40LS40IDEtLjQgMS40IDAgLjQuNC40IDEgMCAxLjRsLTYgNmMtLjIuMi0uNC4zLS43LjNaIiBmaWxsPSIjZmZmIi8+PC9zdmc+)}.scylla-icon--training{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJDYWxxdWVfMiIgZGF0YS1uYW1lPSJDYWxxdWUgMiI+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNMTcuNSAxNS41SC41di0xM2gxOE01LjUgMjVsNC00LjMgNCA0LjMiLz48Y2lyY2xlIGN4PSIyMSIgY3k9IjQiIHI9IjIuNSIgc3R5bGU9InN0cm9rZS1taXRlcmxpbWl0OjEwO2ZpbGw6bm9uZTtzdHJva2U6Z3JheSIvPjxwYXRoIGNsYXNzPSJjbHMtMSIgZD0iTTIzLjQxIDcuNWgtMS41MkwyMSA5bC0uOS0xLjVIMTNBMS44IDEuOCAwIDAgMCAxMS41IDlhMS44IDEuOCAwIDAgMCAxLjUgMS41aDQuNXYxMy4yNEExLjQxIDEuNDEgMCAwIDAgMTkgMjVhMS40MiAxLjQyIDAgMCAwIDEuNS0xLjIyIDEuNTMgMS41MyAwIDAgMCAzIDB2LTcuMTFhMS4xMSAxLjExIDAgMCAwIDEuMDktMS4xOFY4LjY3YTEuMTggMS4xOCAwIDAgMC0xLjE4LTEuMTdaTTkuNSAxNS40NHY1LjM4Ii8+PC9nPjwvc3ZnPg==)}.collapsible-button .side-nav__content .toctree-checkbox:checked~label i,.collapsible-button .side-nav__content i,.scylla-icon--triangle-down,.side-nav__content .collapsible-button i,.side-nav__content .scylla-icon--expand,.side-nav__content .toctree-checkbox:checked~label .collapsible-button i,.side-nav__content .toctree-checkbox:checked~label .scylla-icon--expand{background-image:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTAiIGhlaWdodD0iNSIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cGF0aCBmaWxsLXJ1bGU9ImV2ZW5vZGQiIGNsaXAtcnVsZT0iZXZlbm9kZCIgZD0ibTAgMCA1IDUgNS01SDBaIiBmaWxsPSIjM0EyRDU1Ii8+PC9zdmc+)}.scylla-icon--university{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJDYWxxdWVfNCIgZGF0YS1uYW1lPSJDYWxxdWUgNCI+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJtMS41IDguNSAxMS00IDExIDR2M2wtMTEgNC0xMS00di0zeiIvPjxwYXRoIGNsYXNzPSJjbHMtMSIgZD0iTTUuNSAxMi41djVhMTIuNDYgMTIuNDYgMCAwIDAgNyAyIDExLjIgMTEuMiAwIDAgMCA3LTJ2LTUiLz48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Im0xMy41IDkuNSA4IDEuMjN2OC43N00yMi41IDE2LjV2MyIvPjwvZz48L3N2Zz4=)}.scylla-icon--users-blog{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMntmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJDYWxxdWVfNCIgZGF0YS1uYW1lPSJDYWxxdWUgNCI+PHBhdGggc3R5bGU9InN0cm9rZS13aWR0aDouOThweDtmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kIiBkPSJNMjMuNSAyLjVoLTIydjE2aDEzdjQuMTdsNC4wNC00LjE3IDQuOTYtLjA0VjIuNXoiLz48cGF0aCBjbGFzcz0iY2xzLTIiIGQ9Ik0xMC44NSA4QTEwLjM4IDEwLjM4IDAgMCAxIDExIDkuNWMwIDIuNDctMS4yMSA0LTMgNHMtMy41LTItMy41LTQuNWE0LjE4IDQuMTggMCAwIDEgMC0xIi8+PHBhdGggY2xhc3M9ImNscy0yIiBkPSJNNS4yIDUuMDdhMy4yMiAzLjIyIDAgMCAxIDIuNS0xIDMuMTYgMy4xNiAwIDAgMSAyLjQgMSA2LjIyIDYuMjIgMCAwIDEgMS4zIDMuODEuNzQuNzQgMCAwIDAtLjQyIDBjMC0uMjQgMC0uNDQtLjA1LS42NmgwQTMgMyAwIDAgMSAxMCA2Ljl2LS4yNGwtLjIxLjEyQTkuNjIgOS42MiAwIDAgMSA0LjczIDhhLjI1LjI1IDAgMCAwLS4yMi4wOWMtLjEzLjE0LS4wOS4zNyAwIC42MXYuMThhLjg1Ljg1IDAgMCAwLS4zMiAwQTUuMzcgNS4zNyAwIDAgMSA1LjIgNS4wN1pNNC41MSA4LjkzYy0uMzUgMC0uNTcuMDUtLjYxLjQ0YTEuMTcgMS4xNyAwIDAgMCAuNzMgMS4zTTExIDguOTNjLjM2IDAgLjU3LjA1LjYyLjQ0YTEuMTcgMS4xNyAwIDAgMS0uNzQgMS4zTTYuMzEgMTQuMTN2LS44NE05LjI1IDEzLjE5di45NE0yLjQyIDE4Yy4xMy0xLjE1LjU4LTIuNTIgMS41OC0zYTE0LjcxIDE0LjcxIDAgMCAxIDIuMzEtLjgyTTEzLjUgMThjLS4xMy0xLjE1LS41MS0yLjUyLTEuNS0zcy0yLjUtMS0yLjUtMSIvPjxwYXRoIGNsYXNzPSJjbHMtMiIgZD0iTTkuMzQgMTQuMjJhMi4yMyAyLjIzIDAgMCAxLTEuNTYuNjEgMi4zMiAyLjMyIDAgMCAxLTEuNTUtLjU5TTIxLjUgNi41aC03TTIxLjUgOS41aC03TTE4LjUgMTIuNWgtNCIvPjwvZz48L3N2Zz4=)}.admonition.caution .admonition-title:before,.admonition.warning .admonition-title:before,.scylla-icon--warning{background-image:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PG1hc2sgaWQ9ImEiIG1hc2stdHlwZT0iYWxwaGEiIG1hc2tVbml0cz0idXNlclNwYWNlT25Vc2UiIHg9IjAiIHk9IjEiIHdpZHRoPSIyNCIgaGVpZ2h0PSIyMSI+PHBhdGggZD0iTTMuNSAyMmMtLjUgMC0xLS4xLTEuNS0uNEMuNiAyMC44LjEgMTguOS45IDE3LjVMOS40IDMuM2MuMy0uNC42LS44IDEtMSAuNy0uNCAxLjUtLjUgMi4zLS4zLjguMiAxLjQuNyAxLjkgMS40TDIzIDE3LjVjLjMuNS40IDEgLjQgMS41IDAgLjgtLjMgMS42LS45IDIuMS0uNS42LTEuMi45LTIgLjloLTE3Wm03LjYtMTcuNkwyLjcgMTguNWMtLjMuNS0uMSAxLjEuNCAxLjQuMS4xLjMuMS40LjFoMTYuOWMuMyAwIC41LS4xLjctLjMuMi0uMi4zLS40LjMtLjcgMC0uMiAwLS4zLS4xLS41TDEyLjkgNC40Yy0uMy0uNS0uOS0uNi0xLjQtLjQtLjIuMS0uMy4yLS40LjRaIiBmaWxsPSIjMDYxOTM4Ii8+PHBhdGggZD0iTTEyIDE0Yy0uNiAwLTEtLjQtMS0xVjljMC0uNi40LTEgMS0xczEgLjQgMSAxdjRjMCAuNi0uNCAxLTEgMVpNMTIgMThjLS4zIDAtLjUtLjEtLjctLjMtLjItLjItLjMtLjQtLjMtLjcgMC0uMSAwLS4zLjEtLjQuMS0uMS4xLS4yLjItLjMuMS0uMS4yLS4yLjMtLjIuMi0uMS40LS4xLjYtLjEuMSAwIC4xIDAgLjIuMS4xIDAgLjEgMCAuMi4xIDAgMCAuMS4xLjIuMS4xLjEuMi4yLjIuMyAwIC4xLjEuMy4xLjQgMCAuMy0uMS41LS4zLjctLjMuMi0uNS4zLS44LjNaIiBmaWxsPSIjMDYxOTM4Ii8+PC9tYXNrPjxnIG1hc2s9InVybCgjYSkiPjxwYXRoIGZpbGw9IiMwNjE5MzgiIGQ9Ik0wIDBoMjR2MjRIMHoiLz48L2c+PC9zdmc+)}.scylla-icon--webinars{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMntmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJDYWxxdWVfNCIgZGF0YS1uYW1lPSJDYWxxdWUgNCI+PHBhdGggc3R5bGU9InN0cm9rZS1taXRlcmxpbWl0OjEwO2ZpbGw6bm9uZTtzdHJva2U6Z3JheSIgZD0iTTEuNSA1LjVoMjJ2MTRoLTIyeiIvPjxwYXRoIGNsYXNzPSJjbHMtMiIgZD0iTTkuNDcgMjAuNXYxLjg4TTE1LjUgMjAuNXYyTTYuNSAyMi41aDEyIi8+PHBhdGggc3R5bGU9ImZpbGw6Z3JheSIgZD0ibTkgOSA3LjUgMy41M0w5IDE2Vjl6Ii8+PC9nPjwvc3ZnPg==)}.scylla-icon--whitepapers{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMntmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJDYWxxdWVfNCIgZGF0YS1uYW1lPSJDYWxxdWUgNCI+PHBhdGggc3R5bGU9ImZpbGw6Z3JheSIgZD0iTTggOWg4djJIOHoiLz48cGF0aCBjbGFzcz0iY2xzLTIiIGQ9Ik0xNC4wNiAxLjUgMy41IDEuNTJWMjMuNWgxN1Y3bC02LjQ0LTUuNXoiLz48cGF0aCBkPSJNMTQuMzIgMS40MnYzLjM3YTIuMDYgMi4wNiAwIDAgMCAyLjA4IDIuMWgzLjY3IiBzdHlsZT0ic3Ryb2tlLW1pdGVybGltaXQ6MTA7ZmlsbDpub25lO3N0cm9rZTpncmF5Ii8+PHBhdGggY2xhc3M9ImNscy0yIiBkPSJNNi41IDE5LjVoNE0xMy41IDE5LjVoNE02LjUgMTYuNWg0TTEzLjUgMTYuNWg0TTYuNSAxMy41aDRNMTMuNSAxMy41aDQiLz48L2c+PC9zdmc+)}.scylla-icon--workshop{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMSwuY2xzLTJ7ZmlsbDpub25lO3N0cm9rZTojNGQ0ZDRkfS5jbHMtMXtzdHJva2UtbWl0ZXJsaW1pdDoxMH0uY2xzLTJ7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJDYWxxdWVfNCIgZGF0YS1uYW1lPSJDYWxxdWUgNCI+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNMS41IDUuNWgyMnYxNGgtMjJ6Ii8+PHBhdGggY2xhc3M9ImNscy0yIiBkPSJtOS41IDE5LjUtLjAzIDIuODhNMTUuNSAxOS41djNNNi41IDIyLjVoMTIiLz48cGF0aCBzdHlsZT0iZmlsbDojNGQ0ZDRkIiBkPSJtNCA4IDIgOCAuOTctMy45NUwxMSAxMiA0IDh6Ii8+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJtNi40NyAxMS4zNCAzLjM3IDQuMjgiLz48L2c+PC9zdmc+)}.button{background:transparent;border:1px solid #3a2d55;border-radius:4px;color:#3a2d55;display:inline;font-size:14px;letter-spacing:1px;line-height:21px;margin:0;padding:12px 14px}.button:focus,.button:hover{background:transparent;color:#3a2d55;text-decoration:none}.button--reverse{background:#fff;border:0}.button--reverse:focus,.button--reverse:hover{background:#fff}.tooltip{background-color:rgba(0,0,0,.56);border-radius:4px;font-size:12px;padding:6px}.tooltip:before{display:none!important}.tooltip:empty{display:none!important}.has-tip{border:0;cursor:pointer}.scylla-dropdown{color:#23263b;font-size:14px;line-height:20px}.scylla-dropdown a,.scylla-dropdown a:focus,.scylla-dropdown a:hover{color:#23263b!important;padding:0!important}.scylla-dropdown__item{font-size:16px;padding:15px}.scylla-dropdown__title{align-items:center;display:flex!important;position:static!important}.scylla-dropdown__title:after{display:none!important}.scylla-dropdown__title .chevron{min-height:5px;width:10px}.scylla-dropdown__content{background:#fff;border:0;border-radius:8px;box-shadow:0 4px 25px rgba(0,0,0,.15);font-size:16px;list-style:none;margin-top:15px;overflow:hidden;padding:16px 0;width:max-content}.scylla-dropdown__content li{padding:7px 16px}.scylla-dropdown__content .contents.local>ul>li a:before,.scylla-dropdown__content .secondary-side-nav__content li a:before,.scylla-dropdown__content li .admonition-title:before,.scylla-dropdown__content li .scylla-icon,.secondary-side-nav__content .scylla-dropdown__content li a:before{margin-right:10px}.enlarge-image{cursor:zoom-in}.enlarge-image-reveal{background:transparent;border:none;cursor:zoom-out;padding:0;text-align:center;width:fit-content}.enlarge-image-reveal img{background-color:#fff;padding:15px}.header{background-color:#fff;box-shadow:0 2px 22px rgba(74,93,166,.15);justify-content:space-between;padding:12.75px 0;position:fixed;width:100%;z-index:99}.header,.header-logo{align-items:center;display:flex}.header-logo{margin-left:20px;width:auto}.header-logo__img{width:110px}.header-logo__bar{background-color:#3a2d55;border-left:1px solid #3a2d55;height:11.56px;margin:0 7.5px;width:0}.header-logo__text{color:#3a2d55;font-size:10.11px;letter-spacing:.722408px;line-height:12px;text-transform:uppercase}.header-navigation{display:none}.header-button{display:none;margin-left:15px;text-transform:uppercase}.header-search-box{display:none;margin-right:20px;width:200px}.scylla-dropdown--header .scylla-dropdown__item{font-size:14px}.scylla-dropdown--header .scylla-dropdown__title{text-transform:uppercase}.scylla-dropdown--header .scylla-dropdown__title .chevron{margin-left:10px}.contents.local>ul>li .scylla-dropdown--header .scylla-dropdown__content a:before,.scylla-dropdown--header .scylla-dropdown__content .admonition-title:before,.scylla-dropdown--header .scylla-dropdown__content .contents.local>ul>li a:before,.scylla-dropdown--header .scylla-dropdown__content .scylla-icon,.scylla-dropdown--header .scylla-dropdown__content .secondary-side-nav__content li a:before,.secondary-side-nav__content li .scylla-dropdown--header .scylla-dropdown__content a:before{min-height:20px;width:20px}@media screen and (min-width:1024px){.header{padding:18px 0}.header-logo__img{width:152px}.header-logo__bar{height:16px;margin:0 10px}.header-logo__text{font-size:14px;letter-spacing:.722408px;line-height:12px;text-transform:uppercase}.header-navigation{align-items:center;display:flex;justify-content:center}.header-search-box{display:block}}@media screen and (min-width:1200px){.header-logo{margin-left:30px;width:357px}.header-search-box{margin-right:30px;max-width:20%;width:318px}.header-button{display:block}}.side-nav{background:#fff;display:none;height:100vh;left:0;line-height:24px;max-height:calc(100vh - 50px);overflow-y:auto;padding:20px 20px 0;position:fixed;top:50px;width:100%;z-index:100}.side-nav__title{font-weight:700;margin-bottom:20px}.side-nav__content{max-width:90%;overflow-wrap:break-word}.side-nav__content label,.side-nav__content label i{margin:0;padding:0}.side-nav__content label{font-size:inherit;line-height:1;margin-left:5px;max-height:5px}.collapsible-button .side-nav__content i,.side-nav__content .collapsible-button i,.side-nav__content .scylla-icon--expand{height:5px;vertical-align:top;width:10px}.side-nav__content .toctree-checkbox{display:none;position:absolute;right:20px}.side-nav__content .toctree-checkbox~ul{display:none;margin-right:20px}.side-nav__content .toctree-checkbox:checked~ul{display:block}.side-nav__content ul{margin:0}.side-nav__content a{color:#23263b}.side-nav__content a:hover{color:#3c4fe0;font-weight:400}.side-nav__content li{list-style:none;padding:0 0 24px}.side-nav__content li.has-children{align-items:center;display:flex;flex-wrap:wrap}.side-nav__content li.has-children>a{max-width:calc(100% - 15px)}.side-nav__content li.has-children.current{padding-bottom:20px}.side-nav__content li.has-children:hover>a{color:#3c4fe0}.side-nav__content li.has-children:hover>.toctree-checkbox~label i{filter:invert(38%) sepia(71%) saturate(6789%) hue-rotate(231deg) brightness(90%) contrast(95%)}.side-nav__content li.current-page>a{color:#3c4fe0}.side-nav__content li.current-page>.toctree-checkbox:checked~label i{filter:invert(38%) sepia(71%) saturate(6789%) hue-rotate(231deg) brightness(90%) contrast(95%)}.side-nav__content li ul{margin-top:18px;width:100%}.side-nav__content li ul li{border-left:1px solid #3c4fe0;padding:4px 0 4px 13px}.side-nav__content li ul ul{margin-left:0}.side-nav__content li .label{display:none}.side-nav__versions{max-width:90%}.side-nav__search,.side-nav__versions .dropdown{margin-bottom:20px}.collapsible-button{background:#fff;background-color:#fff;border:0;border-radius:8px;border-radius:50%;bottom:10px;box-shadow:0 4px 25px rgba(0,0,0,.15);cursor:pointer;display:none;font-size:0;left:300px;overflow:hidden;padding:13.5px;position:fixed}.collapsible-button i{height:16px;margin:0;width:16px}.side-nav--collapsed .collapsible-button{border-radius:0 20px 20px 0;left:-10px}.side-nav--collapsed .collapsible-button i{transform:rotate(180deg)}.layout--has-banner .side-nav{max-height:calc(100vh - 92.5px)}@media screen and (min-width:1024px){.side-nav{background-color:#f6f8ff;display:block;height:100%;left:auto;max-height:100vh;max-height:calc(100vh - 80px);padding:30px 40px;top:80px;width:286px;z-index:25}.side-nav__content{max-width:100%;padding-bottom:180px}.side-nav__search{display:none}.side-nav__versions{max-width:100%}.toctree-checkbox{right:40px}.layout--has-banner .side-nav{max-height:calc(100vh - 150px)}}@media screen and (min-width:1200px){.side-nav{width:357px}.side-nav--collapsed{background-color:transparent;padding-left:0;padding-right:0;width:126px}.side-nav--collapsed .side-nav-content{display:none}.collapsible-button{display:block}}.side-nav-toggle{cursor:pointer;display:block;margin-right:20px;position:relative;z-index:300}@media screen and (min-width:1024px){.side-nav-toggle{display:none}}.secondary-side-nav{display:none;height:100%;line-height:24px;padding:20px;width:100%}.secondary-side-nav__content{overflow-wrap:break-word}.secondary-side-nav__content ul{list-style:none;margin:0}.secondary-side-nav__content li{border-bottom:1px solid rgba(90,94,154,.1);display:none;padding:10px 0;word-break:break-word}.secondary-side-nav__content li:last-child{border:0}.secondary-side-nav__content li .label{display:none}.secondary-side-nav__content li a{align-items:baseline;color:#b3bac5;display:flex;font-size:14px}.secondary-side-nav__content li a:before{content:"";filter:invert(40%) sepia(11%) saturate(2157%) hue-rotate(198deg) brightness(89%) contrast(87%)!important;flex-shrink:0;margin-right:10px;min-height:10px;opacity:.5;width:6px}.secondary-side-nav__content li a.current,.secondary-side-nav__content li a:hover{color:#23263b;font-weight:400}.secondary-side-nav__content li a.current:before,.secondary-side-nav__content li a:hover:before{filter:brightness(0);opacity:1}.secondary-side-nav__content li a.current{font-weight:700}.secondary-side-nav__content>ul>li>ul>li{display:block}.secondary-side-nav__content>ul>li{border:0;display:block}.secondary-side-nav__content>ul>li>a{display:none}@media screen and (min-width:1200px){.secondary-side-nav{display:block;max-height:100vh;max-height:calc(100vh - 80px);overflow-y:auto;padding:60px 60px 60px 20px;position:fixed;top:80px;width:286px}.secondary-side-nav__content{padding-bottom:180px}.layout--has-banner .secondary-side-nav{max-height:calc(100vh - 150px)}}.layout{display:flex}.pre-content{align-items:center;display:flex;justify-content:space-between;margin-bottom:20px}.content{margin-top:50px;max-width:1440px;overflow-wrap:break-word;padding:20px;scroll-margin-top:50px;width:100%}.content .line-block,.content p{line-height:28px;margin-bottom:20px}.content ul{list-style:none}.content ul li:before{color:#b3bac5;content:"•";float:left;font-family:FontAwesome;font-size:20px;font-weight:700;margin-left:-1em;margin-top:-2px;width:1em}.content ul ul{list-style:circle}.content ul ul li:before{content:""}.content ol ol{list-style:lower-latin}.content img{margin-bottom:30px}.content section{margin-top:-50px;padding-top:50px}.content .inline-icon.fa-check{color:#42c4e6}.layout--full-width .content{max-width:100%;padding:0;width:100%}.layout--full-width .content .hero-wrapper,.layout--full-width .content .topics-grid{max-width:1190px}.layout--full-width .content.content--collapsed{margin-left:0}.layout--full-width:not(.layout--sidebar) .content{margin-left:0}.layout--has-banner .content{scroll-margin-top:92.5px}.layout--has-banner .content section{margin-top:-92.5px;padding-top:92.5px}.landing__content{padding:0 16px}@media screen and (min-width:1024px){.content{margin-left:286px;margin-top:80px;min-height:calc(100vh - 260px);padding-bottom:100px;scroll-margin-top:80px;width:calc(100% - 286px)}.content section{margin-top:-80px;padding-top:80px}}@media screen and (min-width:1200px){.content{margin-left:357px;padding:60px 40px 40px;width:calc(100% - 643px)}.content--collapsed{margin-left:126px;width:calc(100% - 412px)}.pre-content{margin-bottom:10px}.layout--has-banner .content{scroll-margin-top:150px}.layout--has-banner .content section{margin-top:-150px;padding-top:150px}.landing__content{padding:0 60px}.landing--floating .landing__content{position:relative;top:-70px}}.contents.local>ul{margin-bottom:30px;margin-left:0}.contents.local>ul>li{border-bottom:1px solid rgba(90,94,154,.1);padding:10px 0;word-break:break-word}.contents.local>ul>li:before{content:""}.contents.local>ul>li:last-child{border:0}.contents.local>ul>li ul{display:none}.contents.local>ul>li p{margin:0}.contents.local>ul>li a{font-size:14px}.contents.local>ul>li a:before{content:"";filter:invert(40%) sepia(11%) saturate(2157%) hue-rotate(198deg) brightness(89%) contrast(87%)!important;margin-right:10px;min-height:10px;opacity:.5;width:10px}.contents.local>ul>li a.current:before,.contents.local>ul>li a:hover:before{filter:brightness(0);opacity:1}.topic-title{color:rgba(35,38,59,.75);font-size:10px;letter-spacing:1.5px;margin-bottom:0;text-transform:uppercase}.notice{margin-top:40px}.footer{background-color:#fff;box-shadow:0 -4px 10px hsla(0,0%,82%,.25);padding:30px 0;position:relative;width:100%;z-index:50}.footer-group{margin:0 auto;max-width:1030px;padding:0 20px}.footer-top{align-items:center;border-bottom:1px solid rgba(0,0,0,.1);display:flex;flex-wrap:wrap;justify-content:space-between;padding-bottom:8px;text-align:center}.footer-logo{margin-bottom:30px;width:100%}.footer-logo img{float:left;height:36px}.footer-links{text-align:left}.footer-links__link{color:#333;font-size:12px;font-weight:500;letter-spacing:2.4px;margin-right:16px;text-transform:uppercase}.footer-actions{align-items:center;display:flex;justify-content:space-between;width:90px}.footer-actions__link{color:#000}.footer-actions__link img{height:23px}.footer-bottom{color:#979797;display:flex;flex-wrap:wrap;font-size:12px;font-style:normal;font-weight:400;justify-content:center;letter-spacing:1.4px;line-height:23px;padding:20px 0 10px;text-align:center;text-transform:uppercase}@media screen and (max-width:510px){.footer-links{margin-bottom:20px}}@media screen and (min-width:1024px){.footer{padding:30px 0}.footer-group{padding:0}.footer-top{padding-bottom:30px}.footer-logo{margin:0;width:auto}.footer-links{padding:0 40px}.footer-links__link{font-size:14px;margin-right:28px}.footer-actions{width:110px}.footer-actions__link img{height:28px}.footer-bottom .footer-bottom__copyright,.footer-bottom .footer-bottom__last-updated,.footer-bottom .footer-bottom__version{padding:0 10px}.footer-bottom .footer-bottom__copyright{border-left:none}}.not-found{background-color:#f6f8ff;height:100%;overflow:hidden}.not-found__icon{display:block;margin:40px auto;max-width:300px}.not-found__text{text-align:center}.not-found__text h1{font-size:60px;line-height:1}.not-found__text p{margin:30px 0;width:100%}.not-found__button{text-transform:uppercase}.admonition{border-radius:4px;box-shadow:0 4px 4px rgba(0,0,0,.12);color:rgba(0,0,0,.56);font-size:14px;line-height:20px;margin-bottom:30px;overflow:auto;padding:20px;position:relative}.admonition:before{bottom:0;content:" ";left:0;position:absolute;right:0;top:0;z-index:-1}.admonition-title{color:#23263b;margin-bottom:0!important}.admonition-title:before{content:"";margin-right:8px;min-height:24px;width:24px}.admonition p:not(.admonition-title){margin-bottom:0!important;margin-left:32px}.admonition.tip{border:1px solid #43a047}.admonition.tip:before{border-left:8px solid rgba(67,160,71,.4)}.admonition.tip .admonition-title:before{filter:invert(47%) sepia(11%) saturate(2286%) hue-rotate(73deg) brightness(109%) contrast(88%)}.admonition.note{border:1px solid #1976d2}.admonition.note:before{border-left:8px solid rgba(25,118,210,.4)}.admonition.note .admonition-title:before{filter:invert(44%) sepia(55%) saturate(2310%) hue-rotate(191deg) brightness(81%) contrast(103%)}.admonition.caution{border:1px solid #ffab00}.admonition.caution:before{border-left:8px solid rgba(255,171,0,.4)}.admonition.caution .admonition-title:before{filter:invert(77%) sepia(56%) saturate(3332%) hue-rotate(357deg) brightness(98%) contrast(108%)}.admonition.warning{border:1px solid #e74c3c}.admonition.warning:before{border-left:8px solid rgba(231,76,60,.4)}.admonition.warning .admonition-title:before{filter:invert(41%) sepia(42%) saturate(6427%) hue-rotate(343deg) brightness(99%) contrast(83%)}.breadcrumbs{margin-bottom:0;text-transform:uppercase}.breadcrumbs .bread__item,.breadcrumbs .bread__item:not(.bread__item--last):after,.breadcrumbs a{color:#23263b;font-size:12px;font-weight:400;letter-spacing:1.5px;line-height:2;margin:0;padding:0}.breadcrumbs .bread__item:before{display:none}.breadcrumbs .bread__item:not(.bread__item--last):after{content:"/";margin:0 5px;opacity:1;position:relative}.breadcrumbs .bread__highlight{color:#3c4fe0}.breadcrumbs .bread__highlight:hover{font-weight:700;text-decoration:none}code{background-color:#f7f8f9;border:none;border-radius:4px;color:#23263b;font-size:14px}code.download{background:none;color:#23263b}.highlight{background:transparent!important}.highlight pre{background-color:#f7f8f9;border-radius:8px;color:#23263b;font-size:14px;line-height:26px;margin-bottom:30px;overflow:auto;padding:16px}.highlight a.copybtn{right:1em;top:1em}.highlighttable{background-color:#f7f8f9;border-radius:16px;box-shadow:none}.highlighttable tbody{background-color:transparent;border:0}.highlighttable tbody td{padding:15px!important}.highlighttable tbody tr{border-top:none}.highlighttable .linenos{background-color:#f7f8f9;color:#5a7184;width:50px}.highlighttable .linenos span{line-height:26px}.highlighttable .highlight pre{background-color:transparent;margin:0;padding:0}.highlighttable .highlight a.copybtn{right:.2em;top:.2em}.hide-copy-button .copybtn{display:none}.sphinx_collapse__label{display:flex!important;flex-direction:row-reverse;font-size:medium;font-weight:700;justify-content:flex-end;margin-left:0!important}.sphinx_collapse__icon{margin-left:5px;margin-right:0}.sphinx_collapse__input:checked~.sphinx_collapse__label,.sphinx_collapse__label:hover{color:#3c4fe0}.sphinx_collapse__input:checked~.sphinx_collapse__label .sphinx_collapse__icon,.sphinx_collapse__label:hover .sphinx_collapse__icon{border-top-color:#3c4fe0}.sphinx_collapse__content{margin-top:10px}.contribute{margin:0 0 20px}.contribute__item{font-size:14px;list-style:none;padding-bottom:10px}.contribute__item .icon{margin-right:5px}.content-navigation{display:flex;justify-content:space-between;margin-top:40px}.navigation{max-width:50%;word-break:break-word}.navigation,.navigation__link{display:flex}.navigation__title{word-wrap:break-word;color:#23263b;font-size:12px;font-weight:500;letter-spacing:1.5px;line-height:24px;text-transform:uppercase}.navigation__title .colored{color:#42c4e6}.navigation__button{background:#fff;background-color:#fff;border:0;border-radius:8px;box-shadow:0 4px 25px rgba(0,0,0,.15);cursor:pointer;display:none;font-size:0;height:fit-content;overflow:hidden;padding:13.5px 16.5px}.navigation__button i{height:16px;margin:0;width:10px}.navigation--prev .navigation__title{margin-left:15px}.navigation--next .navigation__title{margin-right:15px;text-align:right}@media screen and (min-width:1200px){.navigation__title{display:inline-block}.navigation__button{display:block}.navigation--next .navigation__title{text-align:left}}.scylla-dropdown--versions .scylla-dropdown__item{background:#fff;border-radius:8px;box-shadow:0 28px 32px rgba(0,0,0,.06);width:100%}.scylla-dropdown--versions .scylla-dropdown__title{align-items:center;display:flex;justify-content:space-between}.scylla-dropdown--versions .scylla-dropdown__title .chevron{min-height:12px;transform:rotate(90deg);width:8px}@media screen and (min-width:1024px){.scylla-dropdown--versions .scylla-dropdown__item{box-shadow:none}}.feedback-container{font-size:16px;margin-top:40px;text-align:left}.feedback-container__title{font-weight:700;margin-bottom:5px!important}.feedback-container__button{background:#fff;border:0;border-radius:8px;box-shadow:0 4px 25px rgba(0,0,0,.15);cursor:pointer;margin:4px;overflow:hidden;padding:8px}.feedback-container__button.active{border:1px solid #3c4fe0}.feedback-container__icon{height:20px;width:20px}.feedback-container__message{font-size:16px;margin-top:10px}.hero{background:#f6f8ff;margin-bottom:30px;overflow:hidden;padding:30px 16px;text-align:left}.hero__title{font-size:28px;font-weight:500;line-height:38px;margin-bottom:14px;max-width:229px}.hero__text{font-size:16px;line-height:26px;max-width:343px}.hero__text a{border-bottom:1px dotted #23263b;color:#23263b}.hero__text p{margin-bottom:0!important}.hero__img{position:absolute;right:-18px;top:20px}.hero__img img{margin-bottom:0!important;width:124px}.hero__button{margin-top:20px;text-transform:uppercase}.hero__button .icon{margin-right:5px}.hero__search-box{box-shadow:0 4px 25px rgba(0,0,0,.02);margin-top:20px}.hero-wrapper{align-items:center;display:flex;justify-content:space-between;margin:0 auto;position:relative}@media screen and (min-width:640px){.hero{padding:60px 16px}.hero__title{font-size:32px;line-height:42px;max-width:482px}.hero__text{font-size:18px;line-height:26px;max-width:482px}.hero__img{display:block;position:static}.hero__img img{height:100%;width:295px}.hero .hero-wrapper{flex-direction:row-reverse}.hero .landing--floating .hero{padding:30px 16px 100px}}@media screen and (min-width:1024px){.hero{padding:60px}}.label{background-color:#23263b;border:0;border-radius:4px;color:#fff;font-size:inherit}.label--note{background-color:#1976d2}.label--tip{background-color:#43a047}.label--caution{background-color:#ffab00}.label--warning{background-color:#e74c3c}.last-updated{color:#4458a3;font-size:12px;letter-spacing:1.5px;margin:10px 0;text-transform:uppercase}.last-updated__icon{font-size:14px}@media screen and (min-width:1024px){.last-updated{float:right;margin:0}}.panel{border:0;border-radius:4px;margin-bottom:30px}.promo-banner{background-color:#4458a3;background-image:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTQ0MCIgaGVpZ2h0PSI3MCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48bWFzayBpZD0iYSIgbWFzay10eXBlPSJhbHBoYSIgbWFza1VuaXRzPSJ1c2VyU3BhY2VPblVzZSIgeD0iMCIgeT0iMCIgd2lkdGg9IjE0NDAiIGhlaWdodD0iNzAiPjxwYXRoIGZpbGw9IiM0NDU4QTMiIGQ9Ik0wIDBoMTQ0MHY3MEgweiIvPjwvbWFzaz48ZyBtYXNrPSJ1cmwoI2EpIiBmaWxsPSIjNTA2NEFFIj48cGF0aCBkPSJNLTE5MyAyMDEuODg0IDEuNS0xMzUgMzU3LjQzNiA3MC41bC0xOTQuNSAzMzYuODg0ek0xMDkyLjkyLTM4LjAwOSA5NzIuODAzLTI0Ni4wNTcgNDAyLjk5NiA4Mi45MiA1MjMuMTEzIDI5MC45N3oiLz48cGF0aCBkPSJtMTAzOC0zOC4wMDkgMTIwLjExNy0yMDguMDQ5IDU2OS44MDcgMzI4Ljk3OS0xMjAuMTE3IDIwOC4wNDl6Ii8+PC9nPjwvc3ZnPg==);background-position:50%;background-repeat:no-repeat;background-size:cover;display:none;overflow:hidden;position:fixed;top:0;width:100%;z-index:900}.promo-banner__icon{margin-right:15px}.promo-banner__icon img{height:40px}.promo-banner__title{color:#fff;font-size:12px;line-height:16px;margin-right:15px}.promo-banner__button{background:#fff;border-radius:4px;font-size:12px;min-width:max-content;padding:5px}.promo-banner__close{display:none;position:absolute;right:16px;top:16px}.contents.local>ul>li .promo-banner__close a:before,.promo-banner__close .admonition-title:before,.promo-banner__close .contents.local>ul>li a:before,.promo-banner__close .scylla-icon,.promo-banner__close .secondary-side-nav__content li a:before,.secondary-side-nav__content li .promo-banner__close a:before{filter:brightness(100%);height:34px;width:34px}.promo-banner__close:hover{cursor:pointer;filter:opacity(.8)}.promo-banner-wrapper{align-items:center;display:flex;justify-content:center;padding:5.85px 20px}@media(min-width:1024px){.promo-banner__title{font-size:18px;line-height:23px}.promo-banner__button{font-size:14px;padding:8.5px}.promo-banner__close{display:block}.promo-banner-wrapper{flex-direction:unset;padding:16px}}.custom-scroll-bar::-webkit-scrollbar{background-color:transparent;width:5px}.custom-scroll-bar::-webkit-scrollbar-thumb{background-color:#b3bac5;-webkit-border-radius:8px;border-radius:8px}.search-box{background:#f7f8f9;border-radius:4px;display:flex;padding:10px 15px}.search-box--hero{background-color:#fff;padding:12px 14px}.search-box:before{background-image:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZD0iTTEwLjUgMThhNy41IDcuNSAwIDEgMCAwLTE1IDcuNSA3LjUgMCAwIDAgMCAxNVpNMjEgMjFsLTUuMi01LjIiIHN0cm9rZT0iIzAwMCIgc3Ryb2tlLXdpZHRoPSIyIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiLz48L3N2Zz4=);background-repeat:no-repeat;background-size:contain;content:"";display:inline-block;filter:brightness(0);margin-top:2px;min-height:18px;min-width:18px;vertical-align:middle;width:20px}.search-box .er-dummy-search,.search-box .er-dummy-search-box,.search-box .er-search-form,.search-box ci-search,.search-box input{margin:0!important;width:100%!important}.search-box input{background:transparent!important;color:rgba(80,80,80,.5)!important;font-size:14px!important;padding:0!important}.search-box input::placeholder{color:rgba(80,80,80,.5)!important;opacity:1!important}.search-box button{display:none!important}.er_search_suggestions{background:#fff;border:0;border:0!important;border-radius:8px;box-shadow:0 4px 25px rgba(0,0,0,.15);overflow:hidden}.er_search_suggestions .er-search-result-box{border-width:1px!important;padding-bottom:10px!important;padding-top:10px!important}.er_search_suggestions .er-search-result-box:hover{background:#f7f8f9!important}.er_search_suggestions .er_more_result_btn{cursor:pointer}.er_search_suggestions h3{font-size:16px!important}.er-search-content{padding:20px!important}#er_search_results .er-search-result-box{display:block!important;margin:10px auto 0!important;width:100%!important}#er_search_results .text,#er_search_results .title a,#er_search_results .url a{max-width:100%!important}#search-result-input-form{max-width:800px!important}#er_search_button{text-align:center}#er_clear_input{right:0!important;top:0!important}.er-facet-header{background-color:transparent!important;border:0!important;padding:0 0 8px!important}.er-facet-val{padding:5px 2px!important}.er-facet-val input{display:block!important;margin:0}#er_search_pagination{margin-top:20px!important}#er_search_pagination li.er-paginator-list.er-active{border-bottom:0!important;font-weight:700}.er-suggestion-sm .er_search_input_dummy{margin:0!important}.er-suggestion-sm .er_search_button_dummy{border:0!important}#er_gcs_mobile_model_container .er-facet-values .er-facet-val{align-items:baseline}@media screen and (min-width:640px){.er-facets{display:none;max-width:300px!important;min-width:auto!important;width:auto!important}}@media screen and (min-width:1024px){.er-suggestions{left:15px!important}}@media screen and (min-width:1200px){.er-facets{display:block;position:fixed!important}.er-facet-count{display:none}}.sphinx-tabs{margin-bottom:30px}.sphinx-tabs-tab{border-bottom:1px solid rgba(0,0,0,.56);color:rgba(0,0,0,.56);cursor:pointer;font-size:14px;font-weight:500;line-height:13px;padding:20px 25px}.sphinx-tabs-tab[aria-selected=true]{border-bottom:2px solid #2196f3;color:#2196f3;padding-bottom:19px}.sphinx-tabs-panel{margin:30px 0}.table-wrapper{border:1px solid #e0e0e0;border-radius:4px;box-shadow:0 1px 2px rgba(0,0,0,.25);display:block;margin-bottom:30px;max-width:100%;overflow-x:auto}table{color:#000;font-size:14px;line-height:24px;margin:0;overflow:hidden}table p{margin:0!important}table caption{background:#f6f8ff;border-bottom:1px solid #e0e0e0;color:#23263b;padding:10px 25px}table thead{background:#f6f8ff;border:0;border-bottom:1px solid #4458a3}table thead th{color:#23263b;font-size:14px;font-weight:700}table td,table thead th{padding:20px 25px}table tbody tr{background-color:transparent!important;border-top:1px solid #e0e0e0;line-height:18px}table:not(.highlighttable) tbody tr:first-child{border-top:1px solid #4458a3}table.thead-border thead .row-odd th{color:#23263b}table.thead-border thead .row-even th{font-weight:400}table.thead-border thead th{border:1px solid #e0e0e0}table.thead-border thead tr:first-child th{border-top:none}table.thead-border thead tr:last-child th{border-bottom:none}table.thead-border thead tr th:first-child{border-left:none}table.thead-border thead tr th:last-child{border-right:none}.topics-grid{display:block;margin:0 auto 30px}.topics-grid__title{color:#23263b;font-size:24px;font-weight:700;line-height:32px;margin-bottom:6px}.topics-grid__text{color:#4458a3;font-size:18px;line-height:24px}.topics-grid--scrollable .hs{-ms-overflow-style:none;display:grid;grid-auto-flow:column;overflow-x:scroll;padding:20px 10px;scrollbar-width:none}.topics-grid--scrollable .hs::-webkit-scrollbar{display:none}.topics-grid--scrollable .hs .topic-box:last-child:after{content:"";width:20px}.topic-box{align-items:stretch;display:flex}.topic-box .card{background:#fff;border:1px solid transparent;border-radius:8px;box-shadow:0 4px 25px rgba(0,0,0,.15);display:flex;flex-direction:column;font-size:18px;margin:0 auto 30px;overflow:hidden;padding:20px;position:relative}.topic-box .card:hover{border:1px solid #4458a3;color:#23263b;font-weight:400}.topic-box__title{color:#23263b;font-size:16px;font-weight:700;line-height:24px;margin-bottom:0}.topic-box__title img{bottom:0;opacity:.3;position:absolute;right:0;top:0}.topic-box__body{color:#000;display:flex;flex-direction:column;flex-grow:1;max-width:80%}.topic-box__body .container{flex-grow:1;margin:0;padding:0}.topic-box__body .line-block,.topic-box__body p{font-size:16px;line-height:19px;margin-top:10px}.topic-box__anchor{color:#42c4e6;font-size:14px;font-weight:700;line-height:24px}.topic-box__icon{display:block;font-size:50px;margin-bottom:20px}.topic-box__icon i{filter:brightness(0);min-height:50px;width:100%}.topic-box__icon img{bottom:-12px;display:none;height:140px;margin:0;opacity:.3;position:absolute;right:-5px}.topic-box--product .card{box-shadow:none;padding:20px;text-align:center}.topic-box--product .card .topic-box__title{color:#23263b;font-size:14px}.topic-box--product .card .topic-box__body{display:flex;flex-direction:column;max-width:100%}.topic-box--product .card .topic-box__body .line-block,.topic-box--product .card .topic-box__body p{font-size:12px}.topic-box--product .card .topic-box__icon img{display:inline-block;max-height:84px;opacity:1;position:static}.topic-box--product .card:hover{background:#fff;border:0;border-radius:8px;box-shadow:0 4px 25px rgba(0,0,0,.15);overflow:hidden}@media screen and (max-width:1024px){.topics-grid--scrollable .topic-box{width:280px!important}.topic-box--product:nth-last-child(-n+2) .card{margin-bottom:0}}@media screen and (min-width:1024px){.topics-grid{margin-bottom:10px}.topics-grid__text{font-size:16px}.topics-grid--scrollable .hs{display:flex;overflow-x:initial;padding:0}.topics-grid--scrollable .hs .topic-box:last-child:after{display:none}.topic-box .card{margin-bottom:60px;padding:45px 30px}.topic-box__title{font-size:20px;line-height:32px}.topic-box__body .line-block,.topic-box__body p{font-size:18px;line-height:26px}.topic-box__anchor{font-size:20px;line-height:26px}.topic-box .topic-box__icon img{display:inline-block}.topic-box--product .card{padding:20px}.topic-box--product .card .topic-box__title{font-size:18px;line-height:24px}.topic-box--product .card .topic-box__body .line-block,.topic-box--product .card .topic-box__body p{font-size:14px}.topic-box--product .card .topic-box__icon img{max-height:111px}.landing .topics-grid--products{margin-bottom:40px}} \ No newline at end of file diff --git a/3.25.11-scylla/_static/doctools.js b/3.25.11-scylla/_static/doctools.js new file mode 100644 index 0000000000..8cbf1b161a --- /dev/null +++ b/3.25.11-scylla/_static/doctools.js @@ -0,0 +1,323 @@ +/* + * doctools.js + * ~~~~~~~~~~~ + * + * Sphinx JavaScript utilities for all documentation. + * + * :copyright: Copyright 2007-2021 by the Sphinx team, see AUTHORS. + * :license: BSD, see LICENSE for details. + * + */ + +/** + * select a different prefix for underscore + */ +$u = _.noConflict(); + +/** + * make the code below compatible with browsers without + * an installed firebug like debugger +if (!window.console || !console.firebug) { + var names = ["log", "debug", "info", "warn", "error", "assert", "dir", + "dirxml", "group", "groupEnd", "time", "timeEnd", "count", "trace", + "profile", "profileEnd"]; + window.console = {}; + for (var i = 0; i < names.length; ++i) + window.console[names[i]] = function() {}; +} + */ + +/** + * small helper function to urldecode strings + * + * See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/decodeURIComponent#Decoding_query_parameters_from_a_URL + */ +jQuery.urldecode = function(x) { + if (!x) { + return x + } + return decodeURIComponent(x.replace(/\+/g, ' ')); +}; + +/** + * small helper function to urlencode strings + */ +jQuery.urlencode = encodeURIComponent; + +/** + * This function returns the parsed url parameters of the + * current request. Multiple values per key are supported, + * it will always return arrays of strings for the value parts. + */ +jQuery.getQueryParameters = function(s) { + if (typeof s === 'undefined') + s = document.location.search; + var parts = s.substr(s.indexOf('?') + 1).split('&'); + var result = {}; + for (var i = 0; i < parts.length; i++) { + var tmp = parts[i].split('=', 2); + var key = jQuery.urldecode(tmp[0]); + var value = jQuery.urldecode(tmp[1]); + if (key in result) + result[key].push(value); + else + result[key] = [value]; + } + return result; +}; + +/** + * highlight a given string on a jquery object by wrapping it in + * span elements with the given class name. + */ +jQuery.fn.highlightText = function(text, className) { + function highlight(node, addItems) { + if (node.nodeType === 3) { + var val = node.nodeValue; + var pos = val.toLowerCase().indexOf(text); + if (pos >= 0 && + !jQuery(node.parentNode).hasClass(className) && + !jQuery(node.parentNode).hasClass("nohighlight")) { + var span; + var isInSVG = jQuery(node).closest("body, svg, foreignObject").is("svg"); + if (isInSVG) { + span = document.createElementNS("http://www.w3.org/2000/svg", "tspan"); + } else { + span = document.createElement("span"); + span.className = className; + } + span.appendChild(document.createTextNode(val.substr(pos, text.length))); + node.parentNode.insertBefore(span, node.parentNode.insertBefore( + document.createTextNode(val.substr(pos + text.length)), + node.nextSibling)); + node.nodeValue = val.substr(0, pos); + if (isInSVG) { + var rect = document.createElementNS("http://www.w3.org/2000/svg", "rect"); + var bbox = node.parentElement.getBBox(); + rect.x.baseVal.value = bbox.x; + rect.y.baseVal.value = bbox.y; + rect.width.baseVal.value = bbox.width; + rect.height.baseVal.value = bbox.height; + rect.setAttribute('class', className); + addItems.push({ + "parent": node.parentNode, + "target": rect}); + } + } + } + else if (!jQuery(node).is("button, select, textarea")) { + jQuery.each(node.childNodes, function() { + highlight(this, addItems); + }); + } + } + var addItems = []; + var result = this.each(function() { + highlight(this, addItems); + }); + for (var i = 0; i < addItems.length; ++i) { + jQuery(addItems[i].parent).before(addItems[i].target); + } + return result; +}; + +/* + * backward compatibility for jQuery.browser + * This will be supported until firefox bug is fixed. + */ +if (!jQuery.browser) { + jQuery.uaMatch = function(ua) { + ua = ua.toLowerCase(); + + var match = /(chrome)[ \/]([\w.]+)/.exec(ua) || + /(webkit)[ \/]([\w.]+)/.exec(ua) || + /(opera)(?:.*version|)[ \/]([\w.]+)/.exec(ua) || + /(msie) ([\w.]+)/.exec(ua) || + ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec(ua) || + []; + + return { + browser: match[ 1 ] || "", + version: match[ 2 ] || "0" + }; + }; + jQuery.browser = {}; + jQuery.browser[jQuery.uaMatch(navigator.userAgent).browser] = true; +} + +/** + * Small JavaScript module for the documentation. + */ +var Documentation = { + + init : function() { + this.fixFirefoxAnchorBug(); + this.highlightSearchWords(); + this.initIndexTable(); + if (DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS) { + this.initOnKeyListeners(); + } + }, + + /** + * i18n support + */ + TRANSLATIONS : {}, + PLURAL_EXPR : function(n) { return n === 1 ? 0 : 1; }, + LOCALE : 'unknown', + + // gettext and ngettext don't access this so that the functions + // can safely bound to a different name (_ = Documentation.gettext) + gettext : function(string) { + var translated = Documentation.TRANSLATIONS[string]; + if (typeof translated === 'undefined') + return string; + return (typeof translated === 'string') ? translated : translated[0]; + }, + + ngettext : function(singular, plural, n) { + var translated = Documentation.TRANSLATIONS[singular]; + if (typeof translated === 'undefined') + return (n == 1) ? singular : plural; + return translated[Documentation.PLURALEXPR(n)]; + }, + + addTranslations : function(catalog) { + for (var key in catalog.messages) + this.TRANSLATIONS[key] = catalog.messages[key]; + this.PLURAL_EXPR = new Function('n', 'return +(' + catalog.plural_expr + ')'); + this.LOCALE = catalog.locale; + }, + + /** + * add context elements like header anchor links + */ + addContextElements : function() { + $('div[id] > :header:first').each(function() { + $('\u00B6'). + attr('href', '#' + this.id). + attr('title', _('Permalink to this headline')). + appendTo(this); + }); + $('dt[id]').each(function() { + $('\u00B6'). + attr('href', '#' + this.id). + attr('title', _('Permalink to this definition')). + appendTo(this); + }); + }, + + /** + * workaround a firefox stupidity + * see: https://bugzilla.mozilla.org/show_bug.cgi?id=645075 + */ + fixFirefoxAnchorBug : function() { + if (document.location.hash && $.browser.mozilla) + window.setTimeout(function() { + document.location.href += ''; + }, 10); + }, + + /** + * highlight the search words provided in the url in the text + */ + highlightSearchWords : function() { + var params = $.getQueryParameters(); + var terms = (params.highlight) ? params.highlight[0].split(/\s+/) : []; + if (terms.length) { + var body = $('div.body'); + if (!body.length) { + body = $('body'); + } + window.setTimeout(function() { + $.each(terms, function() { + body.highlightText(this.toLowerCase(), 'highlighted'); + }); + }, 10); + $('') + .appendTo($('#searchbox')); + } + }, + + /** + * init the domain index toggle buttons + */ + initIndexTable : function() { + var togglers = $('img.toggler').click(function() { + var src = $(this).attr('src'); + var idnum = $(this).attr('id').substr(7); + $('tr.cg-' + idnum).toggle(); + if (src.substr(-9) === 'minus.png') + $(this).attr('src', src.substr(0, src.length-9) + 'plus.png'); + else + $(this).attr('src', src.substr(0, src.length-8) + 'minus.png'); + }).css('display', ''); + if (DOCUMENTATION_OPTIONS.COLLAPSE_INDEX) { + togglers.click(); + } + }, + + /** + * helper function to hide the search marks again + */ + hideSearchWords : function() { + $('#searchbox .highlight-link').fadeOut(300); + $('span.highlighted').removeClass('highlighted'); + }, + + /** + * make the url absolute + */ + makeURL : function(relativeURL) { + return DOCUMENTATION_OPTIONS.URL_ROOT + '/' + relativeURL; + }, + + /** + * get the current relative url + */ + getCurrentURL : function() { + var path = document.location.pathname; + var parts = path.split(/\//); + $.each(DOCUMENTATION_OPTIONS.URL_ROOT.split(/\//), function() { + if (this === '..') + parts.pop(); + }); + var url = parts.join('/'); + return path.substring(url.lastIndexOf('/') + 1, path.length - 1); + }, + + initOnKeyListeners: function() { + $(document).keydown(function(event) { + var activeElementType = document.activeElement.tagName; + // don't navigate when in search box, textarea, dropdown or button + if (activeElementType !== 'TEXTAREA' && activeElementType !== 'INPUT' && activeElementType !== 'SELECT' + && activeElementType !== 'BUTTON' && !event.altKey && !event.ctrlKey && !event.metaKey + && !event.shiftKey) { + switch (event.keyCode) { + case 37: // left + var prevHref = $('link[rel="prev"]').prop('href'); + if (prevHref) { + window.location.href = prevHref; + return false; + } + break; + case 39: // right + var nextHref = $('link[rel="next"]').prop('href'); + if (nextHref) { + window.location.href = nextHref; + return false; + } + break; + } + } + }); + } +}; + +// quick alias for translations +_ = Documentation.gettext; + +$(document).ready(function() { + Documentation.init(); +}); diff --git a/3.25.11-scylla/_static/documentation_options.js b/3.25.11-scylla/_static/documentation_options.js new file mode 100644 index 0000000000..334804c7af --- /dev/null +++ b/3.25.11-scylla/_static/documentation_options.js @@ -0,0 +1,12 @@ +var DOCUMENTATION_OPTIONS = { + URL_ROOT: document.getElementById("documentation_options").getAttribute('data-url_root'), + VERSION: '3.25.11', + LANGUAGE: 'None', + COLLAPSE_INDEX: false, + BUILDER: 'html', + FILE_SUFFIX: '.html', + LINK_SUFFIX: '.html', + HAS_SOURCE: true, + SOURCELINK_SUFFIX: '.txt', + NAVIGATION_WITH_KEYS: false +}; \ No newline at end of file diff --git a/3.25.11-scylla/_static/file.png b/3.25.11-scylla/_static/file.png new file mode 100644 index 0000000000..a858a410e4 Binary files /dev/null and b/3.25.11-scylla/_static/file.png differ diff --git a/3.25.11-scylla/_static/img/banner-background.svg b/3.25.11-scylla/_static/img/banner-background.svg new file mode 100644 index 0000000000..f8520d5b3e --- /dev/null +++ b/3.25.11-scylla/_static/img/banner-background.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/3.25.11-scylla/_static/img/favicon-228x228.png b/3.25.11-scylla/_static/img/favicon-228x228.png new file mode 100644 index 0000000000..f30770c7ed Binary files /dev/null and b/3.25.11-scylla/_static/img/favicon-228x228.png differ diff --git a/3.25.11-scylla/_static/img/favicon-32x32.png b/3.25.11-scylla/_static/img/favicon-32x32.png new file mode 100644 index 0000000000..aae1708f26 Binary files /dev/null and b/3.25.11-scylla/_static/img/favicon-32x32.png differ diff --git a/3.25.11-scylla/_static/img/favicon.ico b/3.25.11-scylla/_static/img/favicon.ico new file mode 100644 index 0000000000..6c7484f082 Binary files /dev/null and b/3.25.11-scylla/_static/img/favicon.ico differ diff --git a/3.25.11-scylla/_static/img/icons/icon-about-team.svg b/3.25.11-scylla/_static/img/icons/icon-about-team.svg new file mode 100644 index 0000000000..5448c7f007 --- /dev/null +++ b/3.25.11-scylla/_static/img/icons/icon-about-team.svg @@ -0,0 +1 @@ +icon-about-team diff --git a/3.25.11-scylla/_static/img/icons/icon-about-us-m.svg b/3.25.11-scylla/_static/img/icons/icon-about-us-m.svg new file mode 100644 index 0000000000..09107d9520 --- /dev/null +++ b/3.25.11-scylla/_static/img/icons/icon-about-us-m.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/3.25.11-scylla/_static/img/icons/icon-about-us.svg b/3.25.11-scylla/_static/img/icons/icon-about-us.svg new file mode 100644 index 0000000000..1b1fcc83e3 --- /dev/null +++ b/3.25.11-scylla/_static/img/icons/icon-about-us.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/3.25.11-scylla/_static/img/icons/icon-alternator.svg b/3.25.11-scylla/_static/img/icons/icon-alternator.svg new file mode 100644 index 0000000000..7c2b4ebae0 --- /dev/null +++ b/3.25.11-scylla/_static/img/icons/icon-alternator.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/3.25.11-scylla/_static/img/icons/icon-apps.svg b/3.25.11-scylla/_static/img/icons/icon-apps.svg new file mode 100644 index 0000000000..7e93612026 --- /dev/null +++ b/3.25.11-scylla/_static/img/icons/icon-apps.svg @@ -0,0 +1 @@ + diff --git a/3.25.11-scylla/_static/img/icons/icon-architecture.svg b/3.25.11-scylla/_static/img/icons/icon-architecture.svg new file mode 100644 index 0000000000..67ebbc2f38 --- /dev/null +++ b/3.25.11-scylla/_static/img/icons/icon-architecture.svg @@ -0,0 +1 @@ +icon-architecture diff --git a/3.25.11-scylla/_static/img/icons/icon-benchmarks.svg b/3.25.11-scylla/_static/img/icons/icon-benchmarks.svg new file mode 100644 index 0000000000..e1ce2c1d78 --- /dev/null +++ b/3.25.11-scylla/_static/img/icons/icon-benchmarks.svg @@ -0,0 +1 @@ +icon-benchmarks diff --git a/3.25.11-scylla/_static/img/icons/icon-blog.svg b/3.25.11-scylla/_static/img/icons/icon-blog.svg new file mode 100644 index 0000000000..f4096cbf11 --- /dev/null +++ b/3.25.11-scylla/_static/img/icons/icon-blog.svg @@ -0,0 +1 @@ +icon-blog2 diff --git a/3.25.11-scylla/_static/img/icons/icon-careers.svg b/3.25.11-scylla/_static/img/icons/icon-careers.svg new file mode 100644 index 0000000000..2a7c6ea0b7 --- /dev/null +++ b/3.25.11-scylla/_static/img/icons/icon-careers.svg @@ -0,0 +1 @@ +icon-careers diff --git a/3.25.11-scylla/_static/img/icons/icon-chevron-left.svg b/3.25.11-scylla/_static/img/icons/icon-chevron-left.svg new file mode 100644 index 0000000000..3afa25c481 --- /dev/null +++ b/3.25.11-scylla/_static/img/icons/icon-chevron-left.svg @@ -0,0 +1,3 @@ + + + diff --git a/3.25.11-scylla/_static/img/icons/icon-chevron-right.svg b/3.25.11-scylla/_static/img/icons/icon-chevron-right.svg new file mode 100644 index 0000000000..44eb829cdc --- /dev/null +++ b/3.25.11-scylla/_static/img/icons/icon-chevron-right.svg @@ -0,0 +1,3 @@ + + + diff --git a/3.25.11-scylla/_static/img/icons/icon-circe.svg b/3.25.11-scylla/_static/img/icons/icon-circe.svg new file mode 100644 index 0000000000..875e421670 --- /dev/null +++ b/3.25.11-scylla/_static/img/icons/icon-circe.svg @@ -0,0 +1 @@ + diff --git a/3.25.11-scylla/_static/img/icons/icon-clock.svg b/3.25.11-scylla/_static/img/icons/icon-clock.svg new file mode 100644 index 0000000000..8c92469808 --- /dev/null +++ b/3.25.11-scylla/_static/img/icons/icon-clock.svg @@ -0,0 +1 @@ + diff --git a/3.25.11-scylla/_static/img/icons/icon-close.svg b/3.25.11-scylla/_static/img/icons/icon-close.svg new file mode 100644 index 0000000000..d1162b73e7 --- /dev/null +++ b/3.25.11-scylla/_static/img/icons/icon-close.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/3.25.11-scylla/_static/img/icons/icon-cloud-docs.svg b/3.25.11-scylla/_static/img/icons/icon-cloud-docs.svg new file mode 100644 index 0000000000..a9069bb6e5 --- /dev/null +++ b/3.25.11-scylla/_static/img/icons/icon-cloud-docs.svg @@ -0,0 +1 @@ + diff --git a/3.25.11-scylla/_static/img/icons/icon-cloud.svg b/3.25.11-scylla/_static/img/icons/icon-cloud.svg new file mode 100644 index 0000000000..cfb2318dae --- /dev/null +++ b/3.25.11-scylla/_static/img/icons/icon-cloud.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/3.25.11-scylla/_static/img/icons/icon-comparison.svg b/3.25.11-scylla/_static/img/icons/icon-comparison.svg new file mode 100644 index 0000000000..49d809a5df --- /dev/null +++ b/3.25.11-scylla/_static/img/icons/icon-comparison.svg @@ -0,0 +1 @@ +icon-comparison diff --git a/3.25.11-scylla/_static/img/icons/icon-contact-us.svg b/3.25.11-scylla/_static/img/icons/icon-contact-us.svg new file mode 100644 index 0000000000..9df3145dd2 --- /dev/null +++ b/3.25.11-scylla/_static/img/icons/icon-contact-us.svg @@ -0,0 +1 @@ +icon-contact-us diff --git a/3.25.11-scylla/_static/img/icons/icon-developers-blog.svg b/3.25.11-scylla/_static/img/icons/icon-developers-blog.svg new file mode 100644 index 0000000000..ee804197a0 --- /dev/null +++ b/3.25.11-scylla/_static/img/icons/icon-developers-blog.svg @@ -0,0 +1 @@ +icon-developers-blog diff --git a/3.25.11-scylla/_static/img/icons/icon-docs.svg b/3.25.11-scylla/_static/img/icons/icon-docs.svg new file mode 100644 index 0000000000..5501492f3e --- /dev/null +++ b/3.25.11-scylla/_static/img/icons/icon-docs.svg @@ -0,0 +1 @@ +icon-docs diff --git a/3.25.11-scylla/_static/img/icons/icon-enterprise-m.svg b/3.25.11-scylla/_static/img/icons/icon-enterprise-m.svg new file mode 100644 index 0000000000..97be900b50 --- /dev/null +++ b/3.25.11-scylla/_static/img/icons/icon-enterprise-m.svg @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/3.25.11-scylla/_static/img/icons/icon-enterprise.svg b/3.25.11-scylla/_static/img/icons/icon-enterprise.svg new file mode 100644 index 0000000000..ee1ac26283 --- /dev/null +++ b/3.25.11-scylla/_static/img/icons/icon-enterprise.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/3.25.11-scylla/_static/img/icons/icon-events.svg b/3.25.11-scylla/_static/img/icons/icon-events.svg new file mode 100644 index 0000000000..ba5f211864 --- /dev/null +++ b/3.25.11-scylla/_static/img/icons/icon-events.svg @@ -0,0 +1 @@ +icon-events diff --git a/3.25.11-scylla/_static/img/icons/icon-exclamation.svg b/3.25.11-scylla/_static/img/icons/icon-exclamation.svg new file mode 100644 index 0000000000..a7eb4b77a4 --- /dev/null +++ b/3.25.11-scylla/_static/img/icons/icon-exclamation.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/3.25.11-scylla/_static/img/icons/icon-expand.svg b/3.25.11-scylla/_static/img/icons/icon-expand.svg new file mode 100644 index 0000000000..3806565367 --- /dev/null +++ b/3.25.11-scylla/_static/img/icons/icon-expand.svg @@ -0,0 +1,50 @@ + + + + + + + + + diff --git a/3.25.11-scylla/_static/img/icons/icon-forum.svg b/3.25.11-scylla/_static/img/icons/icon-forum.svg new file mode 100644 index 0000000000..37a709f7a8 --- /dev/null +++ b/3.25.11-scylla/_static/img/icons/icon-forum.svg @@ -0,0 +1 @@ + diff --git a/3.25.11-scylla/_static/img/icons/icon-getting-started.svg b/3.25.11-scylla/_static/img/icons/icon-getting-started.svg new file mode 100644 index 0000000000..702500be40 --- /dev/null +++ b/3.25.11-scylla/_static/img/icons/icon-getting-started.svg @@ -0,0 +1 @@ + diff --git a/3.25.11-scylla/_static/img/icons/icon-glossary.svg b/3.25.11-scylla/_static/img/icons/icon-glossary.svg new file mode 100644 index 0000000000..e8329c2afe --- /dev/null +++ b/3.25.11-scylla/_static/img/icons/icon-glossary.svg @@ -0,0 +1 @@ + diff --git a/3.25.11-scylla/_static/img/icons/icon-home.svg b/3.25.11-scylla/_static/img/icons/icon-home.svg new file mode 100644 index 0000000000..f0b9c25419 --- /dev/null +++ b/3.25.11-scylla/_static/img/icons/icon-home.svg @@ -0,0 +1 @@ + diff --git a/3.25.11-scylla/_static/img/icons/icon-infoworld.svg b/3.25.11-scylla/_static/img/icons/icon-infoworld.svg new file mode 100644 index 0000000000..906e87279c --- /dev/null +++ b/3.25.11-scylla/_static/img/icons/icon-infoworld.svg @@ -0,0 +1 @@ +icon-infoworld diff --git a/3.25.11-scylla/_static/img/icons/icon-integrations.svg b/3.25.11-scylla/_static/img/icons/icon-integrations.svg new file mode 100644 index 0000000000..1ef0920d49 --- /dev/null +++ b/3.25.11-scylla/_static/img/icons/icon-integrations.svg @@ -0,0 +1 @@ + diff --git a/3.25.11-scylla/_static/img/icons/icon-knowledge-base.svg b/3.25.11-scylla/_static/img/icons/icon-knowledge-base.svg new file mode 100644 index 0000000000..884451270d --- /dev/null +++ b/3.25.11-scylla/_static/img/icons/icon-knowledge-base.svg @@ -0,0 +1 @@ + diff --git a/3.25.11-scylla/_static/img/icons/icon-less.svg b/3.25.11-scylla/_static/img/icons/icon-less.svg new file mode 100644 index 0000000000..3094127dec --- /dev/null +++ b/3.25.11-scylla/_static/img/icons/icon-less.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/3.25.11-scylla/_static/img/icons/icon-live-test.svg b/3.25.11-scylla/_static/img/icons/icon-live-test.svg new file mode 100644 index 0000000000..dcb5916c26 --- /dev/null +++ b/3.25.11-scylla/_static/img/icons/icon-live-test.svg @@ -0,0 +1 @@ +icon-live-test diff --git a/3.25.11-scylla/_static/img/icons/icon-mail-list.svg b/3.25.11-scylla/_static/img/icons/icon-mail-list.svg new file mode 100644 index 0000000000..0e6192a352 --- /dev/null +++ b/3.25.11-scylla/_static/img/icons/icon-mail-list.svg @@ -0,0 +1 @@ + diff --git a/3.25.11-scylla/_static/img/icons/icon-manager.svg b/3.25.11-scylla/_static/img/icons/icon-manager.svg new file mode 100644 index 0000000000..02b4e425be --- /dev/null +++ b/3.25.11-scylla/_static/img/icons/icon-manager.svg @@ -0,0 +1 @@ +icon-manager diff --git a/3.25.11-scylla/_static/img/icons/icon-memory-management.svg b/3.25.11-scylla/_static/img/icons/icon-memory-management.svg new file mode 100644 index 0000000000..e34eb4504f --- /dev/null +++ b/3.25.11-scylla/_static/img/icons/icon-memory-management.svg @@ -0,0 +1 @@ +icon-memory-management diff --git a/3.25.11-scylla/_static/img/icons/icon-modeling.svg b/3.25.11-scylla/_static/img/icons/icon-modeling.svg new file mode 100644 index 0000000000..97fa3a0e21 --- /dev/null +++ b/3.25.11-scylla/_static/img/icons/icon-modeling.svg @@ -0,0 +1 @@ + diff --git a/3.25.11-scylla/_static/img/icons/icon-monitoring.svg b/3.25.11-scylla/_static/img/icons/icon-monitoring.svg new file mode 100644 index 0000000000..80b3787f66 --- /dev/null +++ b/3.25.11-scylla/_static/img/icons/icon-monitoring.svg @@ -0,0 +1 @@ +icon-monitoring diff --git a/3.25.11-scylla/_static/img/icons/icon-networking.svg b/3.25.11-scylla/_static/img/icons/icon-networking.svg new file mode 100644 index 0000000000..40a3fd5f6f --- /dev/null +++ b/3.25.11-scylla/_static/img/icons/icon-networking.svg @@ -0,0 +1 @@ +icon-networking diff --git a/3.25.11-scylla/_static/img/icons/icon-news.svg b/3.25.11-scylla/_static/img/icons/icon-news.svg new file mode 100644 index 0000000000..a952b59937 --- /dev/null +++ b/3.25.11-scylla/_static/img/icons/icon-news.svg @@ -0,0 +1 @@ +icon-news diff --git a/3.25.11-scylla/_static/img/icons/icon-newsletter.svg b/3.25.11-scylla/_static/img/icons/icon-newsletter.svg new file mode 100644 index 0000000000..5b8d47eb15 --- /dev/null +++ b/3.25.11-scylla/_static/img/icons/icon-newsletter.svg @@ -0,0 +1 @@ +icon-newsletter diff --git a/3.25.11-scylla/_static/img/icons/icon-nsql-guides.svg b/3.25.11-scylla/_static/img/icons/icon-nsql-guides.svg new file mode 100644 index 0000000000..60ebab3795 --- /dev/null +++ b/3.25.11-scylla/_static/img/icons/icon-nsql-guides.svg @@ -0,0 +1 @@ +icon-nsql-guides diff --git a/3.25.11-scylla/_static/img/icons/icon-open-source.svg b/3.25.11-scylla/_static/img/icons/icon-open-source.svg new file mode 100644 index 0000000000..98c2ea7d5b --- /dev/null +++ b/3.25.11-scylla/_static/img/icons/icon-open-source.svg @@ -0,0 +1 @@ +icon-open-source diff --git a/3.25.11-scylla/_static/img/icons/icon-operator.svg b/3.25.11-scylla/_static/img/icons/icon-operator.svg new file mode 100644 index 0000000000..bb7d8d3ea8 --- /dev/null +++ b/3.25.11-scylla/_static/img/icons/icon-operator.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/3.25.11-scylla/_static/img/icons/icon-overview.svg b/3.25.11-scylla/_static/img/icons/icon-overview.svg new file mode 100644 index 0000000000..515c1528a2 --- /dev/null +++ b/3.25.11-scylla/_static/img/icons/icon-overview.svg @@ -0,0 +1 @@ +icon-overview diff --git a/3.25.11-scylla/_static/img/icons/icon-partners.svg b/3.25.11-scylla/_static/img/icons/icon-partners.svg new file mode 100644 index 0000000000..d0146fc497 --- /dev/null +++ b/3.25.11-scylla/_static/img/icons/icon-partners.svg @@ -0,0 +1 @@ +icon-partners diff --git a/3.25.11-scylla/_static/img/icons/icon-plus.svg b/3.25.11-scylla/_static/img/icons/icon-plus.svg new file mode 100644 index 0000000000..5757435085 --- /dev/null +++ b/3.25.11-scylla/_static/img/icons/icon-plus.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/3.25.11-scylla/_static/img/icons/icon-pricing.svg b/3.25.11-scylla/_static/img/icons/icon-pricing.svg new file mode 100644 index 0000000000..74b01db168 --- /dev/null +++ b/3.25.11-scylla/_static/img/icons/icon-pricing.svg @@ -0,0 +1 @@ +icon-pricing$ diff --git a/3.25.11-scylla/_static/img/icons/icon-release-notes.svg b/3.25.11-scylla/_static/img/icons/icon-release-notes.svg new file mode 100644 index 0000000000..80c490c7b0 --- /dev/null +++ b/3.25.11-scylla/_static/img/icons/icon-release-notes.svg @@ -0,0 +1 @@ +icon-release-notes diff --git a/3.25.11-scylla/_static/img/icons/icon-resource-center.svg b/3.25.11-scylla/_static/img/icons/icon-resource-center.svg new file mode 100644 index 0000000000..6e3ab08e79 --- /dev/null +++ b/3.25.11-scylla/_static/img/icons/icon-resource-center.svg @@ -0,0 +1 @@ +icon-ressource-center diff --git a/3.25.11-scylla/_static/img/icons/icon-roadmap.svg b/3.25.11-scylla/_static/img/icons/icon-roadmap.svg new file mode 100644 index 0000000000..c8cbf67c8c --- /dev/null +++ b/3.25.11-scylla/_static/img/icons/icon-roadmap.svg @@ -0,0 +1 @@ +icon-roadmap-4 diff --git a/3.25.11-scylla/_static/img/icons/icon-search.svg b/3.25.11-scylla/_static/img/icons/icon-search.svg new file mode 100644 index 0000000000..81aae93eef --- /dev/null +++ b/3.25.11-scylla/_static/img/icons/icon-search.svg @@ -0,0 +1,4 @@ + + + + diff --git a/3.25.11-scylla/_static/img/icons/icon-slack.svg b/3.25.11-scylla/_static/img/icons/icon-slack.svg new file mode 100644 index 0000000000..fc164ea1e7 --- /dev/null +++ b/3.25.11-scylla/_static/img/icons/icon-slack.svg @@ -0,0 +1 @@ + diff --git a/3.25.11-scylla/_static/img/icons/icon-stack-overflow.svg b/3.25.11-scylla/_static/img/icons/icon-stack-overflow.svg new file mode 100644 index 0000000000..bebe9b8274 --- /dev/null +++ b/3.25.11-scylla/_static/img/icons/icon-stack-overflow.svg @@ -0,0 +1,4 @@ + + + + diff --git a/3.25.11-scylla/_static/img/icons/icon-summit.svg b/3.25.11-scylla/_static/img/icons/icon-summit.svg new file mode 100644 index 0000000000..4b900bd0c0 --- /dev/null +++ b/3.25.11-scylla/_static/img/icons/icon-summit.svg @@ -0,0 +1 @@ + diff --git a/3.25.11-scylla/_static/img/icons/icon-support.svg b/3.25.11-scylla/_static/img/icons/icon-support.svg new file mode 100644 index 0000000000..a4228b34e8 --- /dev/null +++ b/3.25.11-scylla/_static/img/icons/icon-support.svg @@ -0,0 +1 @@ +icon-support diff --git a/3.25.11-scylla/_static/img/icons/icon-tech-talks.svg b/3.25.11-scylla/_static/img/icons/icon-tech-talks.svg new file mode 100644 index 0000000000..df42b5522b --- /dev/null +++ b/3.25.11-scylla/_static/img/icons/icon-tech-talks.svg @@ -0,0 +1 @@ +icon-tech-talks diff --git a/3.25.11-scylla/_static/img/icons/icon-testing.svg b/3.25.11-scylla/_static/img/icons/icon-testing.svg new file mode 100644 index 0000000000..2fe54efdbc --- /dev/null +++ b/3.25.11-scylla/_static/img/icons/icon-testing.svg @@ -0,0 +1 @@ +icon-testing diff --git a/3.25.11-scylla/_static/img/icons/icon-thumbs-down.svg b/3.25.11-scylla/_static/img/icons/icon-thumbs-down.svg new file mode 100644 index 0000000000..3e7bcd6d90 --- /dev/null +++ b/3.25.11-scylla/_static/img/icons/icon-thumbs-down.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/3.25.11-scylla/_static/img/icons/icon-thumbs-up.svg b/3.25.11-scylla/_static/img/icons/icon-thumbs-up.svg new file mode 100644 index 0000000000..226c44d853 --- /dev/null +++ b/3.25.11-scylla/_static/img/icons/icon-thumbs-up.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/3.25.11-scylla/_static/img/icons/icon-tip.svg b/3.25.11-scylla/_static/img/icons/icon-tip.svg new file mode 100644 index 0000000000..bf7aa6af84 --- /dev/null +++ b/3.25.11-scylla/_static/img/icons/icon-tip.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/3.25.11-scylla/_static/img/icons/icon-training.svg b/3.25.11-scylla/_static/img/icons/icon-training.svg new file mode 100644 index 0000000000..08b95a88ed --- /dev/null +++ b/3.25.11-scylla/_static/img/icons/icon-training.svg @@ -0,0 +1 @@ +icon-training diff --git a/3.25.11-scylla/_static/img/icons/icon-triangle-down.svg b/3.25.11-scylla/_static/img/icons/icon-triangle-down.svg new file mode 100644 index 0000000000..e8ae088106 --- /dev/null +++ b/3.25.11-scylla/_static/img/icons/icon-triangle-down.svg @@ -0,0 +1,3 @@ + + + diff --git a/3.25.11-scylla/_static/img/icons/icon-university.svg b/3.25.11-scylla/_static/img/icons/icon-university.svg new file mode 100644 index 0000000000..f7547ab959 --- /dev/null +++ b/3.25.11-scylla/_static/img/icons/icon-university.svg @@ -0,0 +1 @@ +icon-university diff --git a/3.25.11-scylla/_static/img/icons/icon-users-blog.svg b/3.25.11-scylla/_static/img/icons/icon-users-blog.svg new file mode 100644 index 0000000000..47e56cddcf --- /dev/null +++ b/3.25.11-scylla/_static/img/icons/icon-users-blog.svg @@ -0,0 +1 @@ +icon-users-blog diff --git a/3.25.11-scylla/_static/img/icons/icon-warning.svg b/3.25.11-scylla/_static/img/icons/icon-warning.svg new file mode 100644 index 0000000000..e4b1d40331 --- /dev/null +++ b/3.25.11-scylla/_static/img/icons/icon-warning.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/3.25.11-scylla/_static/img/icons/icon-webinars.svg b/3.25.11-scylla/_static/img/icons/icon-webinars.svg new file mode 100644 index 0000000000..5e9f5cd427 --- /dev/null +++ b/3.25.11-scylla/_static/img/icons/icon-webinars.svg @@ -0,0 +1 @@ +icon-webinars diff --git a/3.25.11-scylla/_static/img/icons/icon-whitepapers.svg b/3.25.11-scylla/_static/img/icons/icon-whitepapers.svg new file mode 100644 index 0000000000..3351e51d23 --- /dev/null +++ b/3.25.11-scylla/_static/img/icons/icon-whitepapers.svg @@ -0,0 +1 @@ +icon-whitepapers diff --git a/3.25.11-scylla/_static/img/icons/icon-workshop.svg b/3.25.11-scylla/_static/img/icons/icon-workshop.svg new file mode 100644 index 0000000000..5206e58e98 --- /dev/null +++ b/3.25.11-scylla/_static/img/icons/icon-workshop.svg @@ -0,0 +1 @@ + diff --git a/3.25.11-scylla/_static/img/logo-docs.svg b/3.25.11-scylla/_static/img/logo-docs.svg new file mode 100644 index 0000000000..4fff669cb6 --- /dev/null +++ b/3.25.11-scylla/_static/img/logo-docs.svg @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/3.25.11-scylla/_static/img/logo-scylla-horizontal-RGB.svg b/3.25.11-scylla/_static/img/logo-scylla-horizontal-RGB.svg new file mode 100644 index 0000000000..b5022d7c4d --- /dev/null +++ b/3.25.11-scylla/_static/img/logo-scylla-horizontal-RGB.svg @@ -0,0 +1,74 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/3.25.11-scylla/_static/img/mascots/404.jpg b/3.25.11-scylla/_static/img/mascots/404.jpg new file mode 100644 index 0000000000..769fa0889f Binary files /dev/null and b/3.25.11-scylla/_static/img/mascots/404.jpg differ diff --git a/3.25.11-scylla/_static/img/mascots/scylla-3monsters.png b/3.25.11-scylla/_static/img/mascots/scylla-3monsters.png new file mode 100644 index 0000000000..7c06d01674 Binary files /dev/null and b/3.25.11-scylla/_static/img/mascots/scylla-3monsters.png differ diff --git a/3.25.11-scylla/_static/img/mascots/scylla-advisor-crystal.png b/3.25.11-scylla/_static/img/mascots/scylla-advisor-crystal.png new file mode 100644 index 0000000000..d33fddd62f Binary files /dev/null and b/3.25.11-scylla/_static/img/mascots/scylla-advisor-crystal.png differ diff --git a/3.25.11-scylla/_static/img/mascots/scylla-alternator.svg b/3.25.11-scylla/_static/img/mascots/scylla-alternator.svg new file mode 100644 index 0000000000..0462f893d5 --- /dev/null +++ b/3.25.11-scylla/_static/img/mascots/scylla-alternator.svg @@ -0,0 +1 @@ +scylla-alternator diff --git a/3.25.11-scylla/_static/img/mascots/scylla-cloud.svg b/3.25.11-scylla/_static/img/mascots/scylla-cloud.svg new file mode 100644 index 0000000000..a6c6a26fc9 --- /dev/null +++ b/3.25.11-scylla/_static/img/mascots/scylla-cloud.svg @@ -0,0 +1 @@ +scylla-cloud diff --git a/3.25.11-scylla/_static/img/mascots/scylla-computer-3-monsters.png b/3.25.11-scylla/_static/img/mascots/scylla-computer-3-monsters.png new file mode 100644 index 0000000000..d0368a7027 Binary files /dev/null and b/3.25.11-scylla/_static/img/mascots/scylla-computer-3-monsters.png differ diff --git a/3.25.11-scylla/_static/img/mascots/scylla-computer-headset.png b/3.25.11-scylla/_static/img/mascots/scylla-computer-headset.png new file mode 100644 index 0000000000..0cdadaa216 Binary files /dev/null and b/3.25.11-scylla/_static/img/mascots/scylla-computer-headset.png differ diff --git a/3.25.11-scylla/_static/img/mascots/scylla-cup-number-one.png b/3.25.11-scylla/_static/img/mascots/scylla-cup-number-one.png new file mode 100644 index 0000000000..e889f4e368 Binary files /dev/null and b/3.25.11-scylla/_static/img/mascots/scylla-cup-number-one.png differ diff --git a/3.25.11-scylla/_static/img/mascots/scylla-docs.svg b/3.25.11-scylla/_static/img/mascots/scylla-docs.svg new file mode 100644 index 0000000000..a5bce950c2 --- /dev/null +++ b/3.25.11-scylla/_static/img/mascots/scylla-docs.svg @@ -0,0 +1 @@ +scylla-docs diff --git a/3.25.11-scylla/_static/img/mascots/scylla-drivers.svg b/3.25.11-scylla/_static/img/mascots/scylla-drivers.svg new file mode 100644 index 0000000000..6012e71679 --- /dev/null +++ b/3.25.11-scylla/_static/img/mascots/scylla-drivers.svg @@ -0,0 +1 @@ +scylla-manager diff --git a/3.25.11-scylla/_static/img/mascots/scylla-enterprise.svg b/3.25.11-scylla/_static/img/mascots/scylla-enterprise.svg new file mode 100644 index 0000000000..a1aa0b46ac --- /dev/null +++ b/3.25.11-scylla/_static/img/mascots/scylla-enterprise.svg @@ -0,0 +1 @@ +scylla-enterprise diff --git a/3.25.11-scylla/_static/img/mascots/scylla-forklift-boxes.png b/3.25.11-scylla/_static/img/mascots/scylla-forklift-boxes.png new file mode 100644 index 0000000000..f64c29e6c7 Binary files /dev/null and b/3.25.11-scylla/_static/img/mascots/scylla-forklift-boxes.png differ diff --git a/3.25.11-scylla/_static/img/mascots/scylla-forklift-migration.png b/3.25.11-scylla/_static/img/mascots/scylla-forklift-migration.png new file mode 100644 index 0000000000..d2f645c645 Binary files /dev/null and b/3.25.11-scylla/_static/img/mascots/scylla-forklift-migration.png differ diff --git a/3.25.11-scylla/_static/img/mascots/scylla-gear.png b/3.25.11-scylla/_static/img/mascots/scylla-gear.png new file mode 100644 index 0000000000..0f53b26afa Binary files /dev/null and b/3.25.11-scylla/_static/img/mascots/scylla-gear.png differ diff --git a/3.25.11-scylla/_static/img/mascots/scylla-hardhat.png b/3.25.11-scylla/_static/img/mascots/scylla-hardhat.png new file mode 100644 index 0000000000..630f2d9094 Binary files /dev/null and b/3.25.11-scylla/_static/img/mascots/scylla-hardhat.png differ diff --git a/3.25.11-scylla/_static/img/mascots/scylla-headband.png b/3.25.11-scylla/_static/img/mascots/scylla-headband.png new file mode 100644 index 0000000000..c87abe684d Binary files /dev/null and b/3.25.11-scylla/_static/img/mascots/scylla-headband.png differ diff --git a/3.25.11-scylla/_static/img/mascots/scylla-headset.png b/3.25.11-scylla/_static/img/mascots/scylla-headset.png new file mode 100644 index 0000000000..ba52cd223d Binary files /dev/null and b/3.25.11-scylla/_static/img/mascots/scylla-headset.png differ diff --git a/3.25.11-scylla/_static/img/mascots/scylla-hearts.png b/3.25.11-scylla/_static/img/mascots/scylla-hearts.png new file mode 100644 index 0000000000..cef08c8654 Binary files /dev/null and b/3.25.11-scylla/_static/img/mascots/scylla-hearts.png differ diff --git a/3.25.11-scylla/_static/img/mascots/scylla-looking-down.png b/3.25.11-scylla/_static/img/mascots/scylla-looking-down.png new file mode 100644 index 0000000000..75cccbfdf1 Binary files /dev/null and b/3.25.11-scylla/_static/img/mascots/scylla-looking-down.png differ diff --git a/3.25.11-scylla/_static/img/mascots/scylla-looking-up.png b/3.25.11-scylla/_static/img/mascots/scylla-looking-up.png new file mode 100644 index 0000000000..6f10405f21 Binary files /dev/null and b/3.25.11-scylla/_static/img/mascots/scylla-looking-up.png differ diff --git a/3.25.11-scylla/_static/img/mascots/scylla-magnifying-glass-fronting.png b/3.25.11-scylla/_static/img/mascots/scylla-magnifying-glass-fronting.png new file mode 100644 index 0000000000..e368cae169 Binary files /dev/null and b/3.25.11-scylla/_static/img/mascots/scylla-magnifying-glass-fronting.png differ diff --git a/3.25.11-scylla/_static/img/mascots/scylla-magnifying-glass.png b/3.25.11-scylla/_static/img/mascots/scylla-magnifying-glass.png new file mode 100644 index 0000000000..74ad669500 Binary files /dev/null and b/3.25.11-scylla/_static/img/mascots/scylla-magnifying-glass.png differ diff --git a/3.25.11-scylla/_static/img/mascots/scylla-manager.svg b/3.25.11-scylla/_static/img/mascots/scylla-manager.svg new file mode 100644 index 0000000000..6ba9ed937c --- /dev/null +++ b/3.25.11-scylla/_static/img/mascots/scylla-manager.svg @@ -0,0 +1 @@ +scylla-manager-2 diff --git a/3.25.11-scylla/_static/img/mascots/scylla-monitor.svg b/3.25.11-scylla/_static/img/mascots/scylla-monitor.svg new file mode 100644 index 0000000000..48bec7dde3 --- /dev/null +++ b/3.25.11-scylla/_static/img/mascots/scylla-monitor.svg @@ -0,0 +1 @@ +scylla-monitor diff --git a/3.25.11-scylla/_static/img/mascots/scylla-movement-fast.png b/3.25.11-scylla/_static/img/mascots/scylla-movement-fast.png new file mode 100644 index 0000000000..956d1dd0e2 Binary files /dev/null and b/3.25.11-scylla/_static/img/mascots/scylla-movement-fast.png differ diff --git a/3.25.11-scylla/_static/img/mascots/scylla-movement.png b/3.25.11-scylla/_static/img/mascots/scylla-movement.png new file mode 100644 index 0000000000..7ee2b04338 Binary files /dev/null and b/3.25.11-scylla/_static/img/mascots/scylla-movement.png differ diff --git a/3.25.11-scylla/_static/img/mascots/scylla-onpremise.png b/3.25.11-scylla/_static/img/mascots/scylla-onpremise.png new file mode 100644 index 0000000000..3b2dc8f1a2 Binary files /dev/null and b/3.25.11-scylla/_static/img/mascots/scylla-onpremise.png differ diff --git a/3.25.11-scylla/_static/img/mascots/scylla-opensource.svg b/3.25.11-scylla/_static/img/mascots/scylla-opensource.svg new file mode 100644 index 0000000000..299e9cb995 --- /dev/null +++ b/3.25.11-scylla/_static/img/mascots/scylla-opensource.svg @@ -0,0 +1 @@ +Plan de travail 1 diff --git a/3.25.11-scylla/_static/img/mascots/scylla-operator.svg b/3.25.11-scylla/_static/img/mascots/scylla-operator.svg new file mode 100644 index 0000000000..655a450b2a --- /dev/null +++ b/3.25.11-scylla/_static/img/mascots/scylla-operator.svg @@ -0,0 +1 @@ +scylla-operator diff --git a/3.25.11-scylla/_static/img/mascots/scylla-plugin.png b/3.25.11-scylla/_static/img/mascots/scylla-plugin.png new file mode 100644 index 0000000000..b28dc857cc Binary files /dev/null and b/3.25.11-scylla/_static/img/mascots/scylla-plugin.png differ diff --git a/3.25.11-scylla/_static/img/mascots/scylla-release-mascot.png b/3.25.11-scylla/_static/img/mascots/scylla-release-mascot.png new file mode 100644 index 0000000000..09342ac687 Binary files /dev/null and b/3.25.11-scylla/_static/img/mascots/scylla-release-mascot.png differ diff --git a/3.25.11-scylla/_static/img/mascots/scylla-repair.png b/3.25.11-scylla/_static/img/mascots/scylla-repair.png new file mode 100644 index 0000000000..9b4c613e70 Binary files /dev/null and b/3.25.11-scylla/_static/img/mascots/scylla-repair.png differ diff --git a/3.25.11-scylla/_static/img/mascots/scylla-server.png b/3.25.11-scylla/_static/img/mascots/scylla-server.png new file mode 100644 index 0000000000..96dc785298 Binary files /dev/null and b/3.25.11-scylla/_static/img/mascots/scylla-server.png differ diff --git a/3.25.11-scylla/_static/img/mascots/scylla-sleeping.png b/3.25.11-scylla/_static/img/mascots/scylla-sleeping.png new file mode 100644 index 0000000000..f88598e05a Binary files /dev/null and b/3.25.11-scylla/_static/img/mascots/scylla-sleeping.png differ diff --git a/3.25.11-scylla/_static/img/mascots/scylla-tall-measure.png b/3.25.11-scylla/_static/img/mascots/scylla-tall-measure.png new file mode 100644 index 0000000000..6f0ca146c0 Binary files /dev/null and b/3.25.11-scylla/_static/img/mascots/scylla-tall-measure.png differ diff --git a/3.25.11-scylla/_static/img/mascots/scylla-university.png b/3.25.11-scylla/_static/img/mascots/scylla-university.png new file mode 100644 index 0000000000..b3d0621193 Binary files /dev/null and b/3.25.11-scylla/_static/img/mascots/scylla-university.png differ diff --git a/3.25.11-scylla/_static/img/mascots/scylla-weights.png b/3.25.11-scylla/_static/img/mascots/scylla-weights.png new file mode 100644 index 0000000000..b070bb022c Binary files /dev/null and b/3.25.11-scylla/_static/img/mascots/scylla-weights.png differ diff --git a/3.25.11-scylla/_static/img/mascots/scylla-window-cleaning.png b/3.25.11-scylla/_static/img/mascots/scylla-window-cleaning.png new file mode 100644 index 0000000000..6a8b16a6b4 Binary files /dev/null and b/3.25.11-scylla/_static/img/mascots/scylla-window-cleaning.png differ diff --git a/3.25.11-scylla/_static/img/mascots/scylla-with-computer-2.png b/3.25.11-scylla/_static/img/mascots/scylla-with-computer-2.png new file mode 100644 index 0000000000..f3b8b2984f Binary files /dev/null and b/3.25.11-scylla/_static/img/mascots/scylla-with-computer-2.png differ diff --git a/3.25.11-scylla/_static/img/mascots/scylla-with-computer.png b/3.25.11-scylla/_static/img/mascots/scylla-with-computer.png new file mode 100644 index 0000000000..b38a6fbbe0 Binary files /dev/null and b/3.25.11-scylla/_static/img/mascots/scylla-with-computer.png differ diff --git a/3.25.11-scylla/_static/img/mascots/scylla-with-linux.png b/3.25.11-scylla/_static/img/mascots/scylla-with-linux.png new file mode 100644 index 0000000000..954bf13bc2 Binary files /dev/null and b/3.25.11-scylla/_static/img/mascots/scylla-with-linux.png differ diff --git a/3.25.11-scylla/_static/img/mascots/scylla-writting.png b/3.25.11-scylla/_static/img/mascots/scylla-writting.png new file mode 100644 index 0000000000..d35a13d380 Binary files /dev/null and b/3.25.11-scylla/_static/img/mascots/scylla-writting.png differ diff --git a/3.25.11-scylla/_static/img/menu.svg b/3.25.11-scylla/_static/img/menu.svg new file mode 100644 index 0000000000..30ea1d901e --- /dev/null +++ b/3.25.11-scylla/_static/img/menu.svg @@ -0,0 +1,3 @@ + + + diff --git a/3.25.11-scylla/_static/jquery-3.5.1.js b/3.25.11-scylla/_static/jquery-3.5.1.js new file mode 100644 index 0000000000..50937333b9 --- /dev/null +++ b/3.25.11-scylla/_static/jquery-3.5.1.js @@ -0,0 +1,10872 @@ +/*! + * jQuery JavaScript Library v3.5.1 + * https://jquery.com/ + * + * Includes Sizzle.js + * https://sizzlejs.com/ + * + * Copyright JS Foundation and other contributors + * Released under the MIT license + * https://jquery.org/license + * + * Date: 2020-05-04T22:49Z + */ +( function( global, factory ) { + + "use strict"; + + if ( typeof module === "object" && typeof module.exports === "object" ) { + + // For CommonJS and CommonJS-like environments where a proper `window` + // is present, execute the factory and get jQuery. + // For environments that do not have a `window` with a `document` + // (such as Node.js), expose a factory as module.exports. + // This accentuates the need for the creation of a real `window`. + // e.g. var jQuery = require("jquery")(window); + // See ticket #14549 for more info. + module.exports = global.document ? + factory( global, true ) : + function( w ) { + if ( !w.document ) { + throw new Error( "jQuery requires a window with a document" ); + } + return factory( w ); + }; + } else { + factory( global ); + } + +// Pass this if window is not defined yet +} )( typeof window !== "undefined" ? window : this, function( window, noGlobal ) { + +// Edge <= 12 - 13+, Firefox <=18 - 45+, IE 10 - 11, Safari 5.1 - 9+, iOS 6 - 9.1 +// throw exceptions when non-strict code (e.g., ASP.NET 4.5) accesses strict mode +// arguments.callee.caller (trac-13335). But as of jQuery 3.0 (2016), strict mode should be common +// enough that all such attempts are guarded in a try block. +"use strict"; + +var arr = []; + +var getProto = Object.getPrototypeOf; + +var slice = arr.slice; + +var flat = arr.flat ? function( array ) { + return arr.flat.call( array ); +} : function( array ) { + return arr.concat.apply( [], array ); +}; + + +var push = arr.push; + +var indexOf = arr.indexOf; + +var class2type = {}; + +var toString = class2type.toString; + +var hasOwn = class2type.hasOwnProperty; + +var fnToString = hasOwn.toString; + +var ObjectFunctionString = fnToString.call( Object ); + +var support = {}; + +var isFunction = function isFunction( obj ) { + + // Support: Chrome <=57, Firefox <=52 + // In some browsers, typeof returns "function" for HTML elements + // (i.e., `typeof document.createElement( "object" ) === "function"`). + // We don't want to classify *any* DOM node as a function. + return typeof obj === "function" && typeof obj.nodeType !== "number"; + }; + + +var isWindow = function isWindow( obj ) { + return obj != null && obj === obj.window; + }; + + +var document = window.document; + + + + var preservedScriptAttributes = { + type: true, + src: true, + nonce: true, + noModule: true + }; + + function DOMEval( code, node, doc ) { + doc = doc || document; + + var i, val, + script = doc.createElement( "script" ); + + script.text = code; + if ( node ) { + for ( i in preservedScriptAttributes ) { + + // Support: Firefox 64+, Edge 18+ + // Some browsers don't support the "nonce" property on scripts. + // On the other hand, just using `getAttribute` is not enough as + // the `nonce` attribute is reset to an empty string whenever it + // becomes browsing-context connected. + // See https://github.com/whatwg/html/issues/2369 + // See https://html.spec.whatwg.org/#nonce-attributes + // The `node.getAttribute` check was added for the sake of + // `jQuery.globalEval` so that it can fake a nonce-containing node + // via an object. + val = node[ i ] || node.getAttribute && node.getAttribute( i ); + if ( val ) { + script.setAttribute( i, val ); + } + } + } + doc.head.appendChild( script ).parentNode.removeChild( script ); + } + + +function toType( obj ) { + if ( obj == null ) { + return obj + ""; + } + + // Support: Android <=2.3 only (functionish RegExp) + return typeof obj === "object" || typeof obj === "function" ? + class2type[ toString.call( obj ) ] || "object" : + typeof obj; +} +/* global Symbol */ +// Defining this global in .eslintrc.json would create a danger of using the global +// unguarded in another place, it seems safer to define global only for this module + + + +var + version = "3.5.1", + + // Define a local copy of jQuery + jQuery = function( selector, context ) { + + // The jQuery object is actually just the init constructor 'enhanced' + // Need init if jQuery is called (just allow error to be thrown if not included) + return new jQuery.fn.init( selector, context ); + }; + +jQuery.fn = jQuery.prototype = { + + // The current version of jQuery being used + jquery: version, + + constructor: jQuery, + + // The default length of a jQuery object is 0 + length: 0, + + toArray: function() { + return slice.call( this ); + }, + + // Get the Nth element in the matched element set OR + // Get the whole matched element set as a clean array + get: function( num ) { + + // Return all the elements in a clean array + if ( num == null ) { + return slice.call( this ); + } + + // Return just the one element from the set + return num < 0 ? this[ num + this.length ] : this[ num ]; + }, + + // Take an array of elements and push it onto the stack + // (returning the new matched element set) + pushStack: function( elems ) { + + // Build a new jQuery matched element set + var ret = jQuery.merge( this.constructor(), elems ); + + // Add the old object onto the stack (as a reference) + ret.prevObject = this; + + // Return the newly-formed element set + return ret; + }, + + // Execute a callback for every element in the matched set. + each: function( callback ) { + return jQuery.each( this, callback ); + }, + + map: function( callback ) { + return this.pushStack( jQuery.map( this, function( elem, i ) { + return callback.call( elem, i, elem ); + } ) ); + }, + + slice: function() { + return this.pushStack( slice.apply( this, arguments ) ); + }, + + first: function() { + return this.eq( 0 ); + }, + + last: function() { + return this.eq( -1 ); + }, + + even: function() { + return this.pushStack( jQuery.grep( this, function( _elem, i ) { + return ( i + 1 ) % 2; + } ) ); + }, + + odd: function() { + return this.pushStack( jQuery.grep( this, function( _elem, i ) { + return i % 2; + } ) ); + }, + + eq: function( i ) { + var len = this.length, + j = +i + ( i < 0 ? len : 0 ); + return this.pushStack( j >= 0 && j < len ? [ this[ j ] ] : [] ); + }, + + end: function() { + return this.prevObject || this.constructor(); + }, + + // For internal use only. + // Behaves like an Array's method, not like a jQuery method. + push: push, + sort: arr.sort, + splice: arr.splice +}; + +jQuery.extend = jQuery.fn.extend = function() { + var options, name, src, copy, copyIsArray, clone, + target = arguments[ 0 ] || {}, + i = 1, + length = arguments.length, + deep = false; + + // Handle a deep copy situation + if ( typeof target === "boolean" ) { + deep = target; + + // Skip the boolean and the target + target = arguments[ i ] || {}; + i++; + } + + // Handle case when target is a string or something (possible in deep copy) + if ( typeof target !== "object" && !isFunction( target ) ) { + target = {}; + } + + // Extend jQuery itself if only one argument is passed + if ( i === length ) { + target = this; + i--; + } + + for ( ; i < length; i++ ) { + + // Only deal with non-null/undefined values + if ( ( options = arguments[ i ] ) != null ) { + + // Extend the base object + for ( name in options ) { + copy = options[ name ]; + + // Prevent Object.prototype pollution + // Prevent never-ending loop + if ( name === "__proto__" || target === copy ) { + continue; + } + + // Recurse if we're merging plain objects or arrays + if ( deep && copy && ( jQuery.isPlainObject( copy ) || + ( copyIsArray = Array.isArray( copy ) ) ) ) { + src = target[ name ]; + + // Ensure proper type for the source value + if ( copyIsArray && !Array.isArray( src ) ) { + clone = []; + } else if ( !copyIsArray && !jQuery.isPlainObject( src ) ) { + clone = {}; + } else { + clone = src; + } + copyIsArray = false; + + // Never move original objects, clone them + target[ name ] = jQuery.extend( deep, clone, copy ); + + // Don't bring in undefined values + } else if ( copy !== undefined ) { + target[ name ] = copy; + } + } + } + } + + // Return the modified object + return target; +}; + +jQuery.extend( { + + // Unique for each copy of jQuery on the page + expando: "jQuery" + ( version + Math.random() ).replace( /\D/g, "" ), + + // Assume jQuery is ready without the ready module + isReady: true, + + error: function( msg ) { + throw new Error( msg ); + }, + + noop: function() {}, + + isPlainObject: function( obj ) { + var proto, Ctor; + + // Detect obvious negatives + // Use toString instead of jQuery.type to catch host objects + if ( !obj || toString.call( obj ) !== "[object Object]" ) { + return false; + } + + proto = getProto( obj ); + + // Objects with no prototype (e.g., `Object.create( null )`) are plain + if ( !proto ) { + return true; + } + + // Objects with prototype are plain iff they were constructed by a global Object function + Ctor = hasOwn.call( proto, "constructor" ) && proto.constructor; + return typeof Ctor === "function" && fnToString.call( Ctor ) === ObjectFunctionString; + }, + + isEmptyObject: function( obj ) { + var name; + + for ( name in obj ) { + return false; + } + return true; + }, + + // Evaluates a script in a provided context; falls back to the global one + // if not specified. + globalEval: function( code, options, doc ) { + DOMEval( code, { nonce: options && options.nonce }, doc ); + }, + + each: function( obj, callback ) { + var length, i = 0; + + if ( isArrayLike( obj ) ) { + length = obj.length; + for ( ; i < length; i++ ) { + if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) { + break; + } + } + } else { + for ( i in obj ) { + if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) { + break; + } + } + } + + return obj; + }, + + // results is for internal usage only + makeArray: function( arr, results ) { + var ret = results || []; + + if ( arr != null ) { + if ( isArrayLike( Object( arr ) ) ) { + jQuery.merge( ret, + typeof arr === "string" ? + [ arr ] : arr + ); + } else { + push.call( ret, arr ); + } + } + + return ret; + }, + + inArray: function( elem, arr, i ) { + return arr == null ? -1 : indexOf.call( arr, elem, i ); + }, + + // Support: Android <=4.0 only, PhantomJS 1 only + // push.apply(_, arraylike) throws on ancient WebKit + merge: function( first, second ) { + var len = +second.length, + j = 0, + i = first.length; + + for ( ; j < len; j++ ) { + first[ i++ ] = second[ j ]; + } + + first.length = i; + + return first; + }, + + grep: function( elems, callback, invert ) { + var callbackInverse, + matches = [], + i = 0, + length = elems.length, + callbackExpect = !invert; + + // Go through the array, only saving the items + // that pass the validator function + for ( ; i < length; i++ ) { + callbackInverse = !callback( elems[ i ], i ); + if ( callbackInverse !== callbackExpect ) { + matches.push( elems[ i ] ); + } + } + + return matches; + }, + + // arg is for internal usage only + map: function( elems, callback, arg ) { + var length, value, + i = 0, + ret = []; + + // Go through the array, translating each of the items to their new values + if ( isArrayLike( elems ) ) { + length = elems.length; + for ( ; i < length; i++ ) { + value = callback( elems[ i ], i, arg ); + + if ( value != null ) { + ret.push( value ); + } + } + + // Go through every key on the object, + } else { + for ( i in elems ) { + value = callback( elems[ i ], i, arg ); + + if ( value != null ) { + ret.push( value ); + } + } + } + + // Flatten any nested arrays + return flat( ret ); + }, + + // A global GUID counter for objects + guid: 1, + + // jQuery.support is not used in Core but other projects attach their + // properties to it so it needs to exist. + support: support +} ); + +if ( typeof Symbol === "function" ) { + jQuery.fn[ Symbol.iterator ] = arr[ Symbol.iterator ]; +} + +// Populate the class2type map +jQuery.each( "Boolean Number String Function Array Date RegExp Object Error Symbol".split( " " ), +function( _i, name ) { + class2type[ "[object " + name + "]" ] = name.toLowerCase(); +} ); + +function isArrayLike( obj ) { + + // Support: real iOS 8.2 only (not reproducible in simulator) + // `in` check used to prevent JIT error (gh-2145) + // hasOwn isn't used here due to false negatives + // regarding Nodelist length in IE + var length = !!obj && "length" in obj && obj.length, + type = toType( obj ); + + if ( isFunction( obj ) || isWindow( obj ) ) { + return false; + } + + return type === "array" || length === 0 || + typeof length === "number" && length > 0 && ( length - 1 ) in obj; +} +var Sizzle = +/*! + * Sizzle CSS Selector Engine v2.3.5 + * https://sizzlejs.com/ + * + * Copyright JS Foundation and other contributors + * Released under the MIT license + * https://js.foundation/ + * + * Date: 2020-03-14 + */ +( function( window ) { +var i, + support, + Expr, + getText, + isXML, + tokenize, + compile, + select, + outermostContext, + sortInput, + hasDuplicate, + + // Local document vars + setDocument, + document, + docElem, + documentIsHTML, + rbuggyQSA, + rbuggyMatches, + matches, + contains, + + // Instance-specific data + expando = "sizzle" + 1 * new Date(), + preferredDoc = window.document, + dirruns = 0, + done = 0, + classCache = createCache(), + tokenCache = createCache(), + compilerCache = createCache(), + nonnativeSelectorCache = createCache(), + sortOrder = function( a, b ) { + if ( a === b ) { + hasDuplicate = true; + } + return 0; + }, + + // Instance methods + hasOwn = ( {} ).hasOwnProperty, + arr = [], + pop = arr.pop, + pushNative = arr.push, + push = arr.push, + slice = arr.slice, + + // Use a stripped-down indexOf as it's faster than native + // https://jsperf.com/thor-indexof-vs-for/5 + indexOf = function( list, elem ) { + var i = 0, + len = list.length; + for ( ; i < len; i++ ) { + if ( list[ i ] === elem ) { + return i; + } + } + return -1; + }, + + booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|" + + "ismap|loop|multiple|open|readonly|required|scoped", + + // Regular expressions + + // http://www.w3.org/TR/css3-selectors/#whitespace + whitespace = "[\\x20\\t\\r\\n\\f]", + + // https://www.w3.org/TR/css-syntax-3/#ident-token-diagram + identifier = "(?:\\\\[\\da-fA-F]{1,6}" + whitespace + + "?|\\\\[^\\r\\n\\f]|[\\w-]|[^\0-\\x7f])+", + + // Attribute selectors: http://www.w3.org/TR/selectors/#attribute-selectors + attributes = "\\[" + whitespace + "*(" + identifier + ")(?:" + whitespace + + + // Operator (capture 2) + "*([*^$|!~]?=)" + whitespace + + + // "Attribute values must be CSS identifiers [capture 5] + // or strings [capture 3 or capture 4]" + "*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|(" + identifier + "))|)" + + whitespace + "*\\]", + + pseudos = ":(" + identifier + ")(?:\\((" + + + // To reduce the number of selectors needing tokenize in the preFilter, prefer arguments: + // 1. quoted (capture 3; capture 4 or capture 5) + "('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|" + + + // 2. simple (capture 6) + "((?:\\\\.|[^\\\\()[\\]]|" + attributes + ")*)|" + + + // 3. anything else (capture 2) + ".*" + + ")\\)|)", + + // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter + rwhitespace = new RegExp( whitespace + "+", "g" ), + rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + + whitespace + "+$", "g" ), + + rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ), + rcombinators = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + + "*" ), + rdescend = new RegExp( whitespace + "|>" ), + + rpseudo = new RegExp( pseudos ), + ridentifier = new RegExp( "^" + identifier + "$" ), + + matchExpr = { + "ID": new RegExp( "^#(" + identifier + ")" ), + "CLASS": new RegExp( "^\\.(" + identifier + ")" ), + "TAG": new RegExp( "^(" + identifier + "|[*])" ), + "ATTR": new RegExp( "^" + attributes ), + "PSEUDO": new RegExp( "^" + pseudos ), + "CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + + whitespace + "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + + whitespace + "*(\\d+)|))" + whitespace + "*\\)|)", "i" ), + "bool": new RegExp( "^(?:" + booleans + ")$", "i" ), + + // For use in libraries implementing .is() + // We use this for POS matching in `select` + "needsContext": new RegExp( "^" + whitespace + + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" + whitespace + + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" ) + }, + + rhtml = /HTML$/i, + rinputs = /^(?:input|select|textarea|button)$/i, + rheader = /^h\d$/i, + + rnative = /^[^{]+\{\s*\[native \w/, + + // Easily-parseable/retrievable ID or TAG or CLASS selectors + rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/, + + rsibling = /[+~]/, + + // CSS escapes + // http://www.w3.org/TR/CSS21/syndata.html#escaped-characters + runescape = new RegExp( "\\\\[\\da-fA-F]{1,6}" + whitespace + "?|\\\\([^\\r\\n\\f])", "g" ), + funescape = function( escape, nonHex ) { + var high = "0x" + escape.slice( 1 ) - 0x10000; + + return nonHex ? + + // Strip the backslash prefix from a non-hex escape sequence + nonHex : + + // Replace a hexadecimal escape sequence with the encoded Unicode code point + // Support: IE <=11+ + // For values outside the Basic Multilingual Plane (BMP), manually construct a + // surrogate pair + high < 0 ? + String.fromCharCode( high + 0x10000 ) : + String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 ); + }, + + // CSS string/identifier serialization + // https://drafts.csswg.org/cssom/#common-serializing-idioms + rcssescape = /([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g, + fcssescape = function( ch, asCodePoint ) { + if ( asCodePoint ) { + + // U+0000 NULL becomes U+FFFD REPLACEMENT CHARACTER + if ( ch === "\0" ) { + return "\uFFFD"; + } + + // Control characters and (dependent upon position) numbers get escaped as code points + return ch.slice( 0, -1 ) + "\\" + + ch.charCodeAt( ch.length - 1 ).toString( 16 ) + " "; + } + + // Other potentially-special ASCII characters get backslash-escaped + return "\\" + ch; + }, + + // Used for iframes + // See setDocument() + // Removing the function wrapper causes a "Permission Denied" + // error in IE + unloadHandler = function() { + setDocument(); + }, + + inDisabledFieldset = addCombinator( + function( elem ) { + return elem.disabled === true && elem.nodeName.toLowerCase() === "fieldset"; + }, + { dir: "parentNode", next: "legend" } + ); + +// Optimize for push.apply( _, NodeList ) +try { + push.apply( + ( arr = slice.call( preferredDoc.childNodes ) ), + preferredDoc.childNodes + ); + + // Support: Android<4.0 + // Detect silently failing push.apply + // eslint-disable-next-line no-unused-expressions + arr[ preferredDoc.childNodes.length ].nodeType; +} catch ( e ) { + push = { apply: arr.length ? + + // Leverage slice if possible + function( target, els ) { + pushNative.apply( target, slice.call( els ) ); + } : + + // Support: IE<9 + // Otherwise append directly + function( target, els ) { + var j = target.length, + i = 0; + + // Can't trust NodeList.length + while ( ( target[ j++ ] = els[ i++ ] ) ) {} + target.length = j - 1; + } + }; +} + +function Sizzle( selector, context, results, seed ) { + var m, i, elem, nid, match, groups, newSelector, + newContext = context && context.ownerDocument, + + // nodeType defaults to 9, since context defaults to document + nodeType = context ? context.nodeType : 9; + + results = results || []; + + // Return early from calls with invalid selector or context + if ( typeof selector !== "string" || !selector || + nodeType !== 1 && nodeType !== 9 && nodeType !== 11 ) { + + return results; + } + + // Try to shortcut find operations (as opposed to filters) in HTML documents + if ( !seed ) { + setDocument( context ); + context = context || document; + + if ( documentIsHTML ) { + + // If the selector is sufficiently simple, try using a "get*By*" DOM method + // (excepting DocumentFragment context, where the methods don't exist) + if ( nodeType !== 11 && ( match = rquickExpr.exec( selector ) ) ) { + + // ID selector + if ( ( m = match[ 1 ] ) ) { + + // Document context + if ( nodeType === 9 ) { + if ( ( elem = context.getElementById( m ) ) ) { + + // Support: IE, Opera, Webkit + // TODO: identify versions + // getElementById can match elements by name instead of ID + if ( elem.id === m ) { + results.push( elem ); + return results; + } + } else { + return results; + } + + // Element context + } else { + + // Support: IE, Opera, Webkit + // TODO: identify versions + // getElementById can match elements by name instead of ID + if ( newContext && ( elem = newContext.getElementById( m ) ) && + contains( context, elem ) && + elem.id === m ) { + + results.push( elem ); + return results; + } + } + + // Type selector + } else if ( match[ 2 ] ) { + push.apply( results, context.getElementsByTagName( selector ) ); + return results; + + // Class selector + } else if ( ( m = match[ 3 ] ) && support.getElementsByClassName && + context.getElementsByClassName ) { + + push.apply( results, context.getElementsByClassName( m ) ); + return results; + } + } + + // Take advantage of querySelectorAll + if ( support.qsa && + !nonnativeSelectorCache[ selector + " " ] && + ( !rbuggyQSA || !rbuggyQSA.test( selector ) ) && + + // Support: IE 8 only + // Exclude object elements + ( nodeType !== 1 || context.nodeName.toLowerCase() !== "object" ) ) { + + newSelector = selector; + newContext = context; + + // qSA considers elements outside a scoping root when evaluating child or + // descendant combinators, which is not what we want. + // In such cases, we work around the behavior by prefixing every selector in the + // list with an ID selector referencing the scope context. + // The technique has to be used as well when a leading combinator is used + // as such selectors are not recognized by querySelectorAll. + // Thanks to Andrew Dupont for this technique. + if ( nodeType === 1 && + ( rdescend.test( selector ) || rcombinators.test( selector ) ) ) { + + // Expand context for sibling selectors + newContext = rsibling.test( selector ) && testContext( context.parentNode ) || + context; + + // We can use :scope instead of the ID hack if the browser + // supports it & if we're not changing the context. + if ( newContext !== context || !support.scope ) { + + // Capture the context ID, setting it first if necessary + if ( ( nid = context.getAttribute( "id" ) ) ) { + nid = nid.replace( rcssescape, fcssescape ); + } else { + context.setAttribute( "id", ( nid = expando ) ); + } + } + + // Prefix every selector in the list + groups = tokenize( selector ); + i = groups.length; + while ( i-- ) { + groups[ i ] = ( nid ? "#" + nid : ":scope" ) + " " + + toSelector( groups[ i ] ); + } + newSelector = groups.join( "," ); + } + + try { + push.apply( results, + newContext.querySelectorAll( newSelector ) + ); + return results; + } catch ( qsaError ) { + nonnativeSelectorCache( selector, true ); + } finally { + if ( nid === expando ) { + context.removeAttribute( "id" ); + } + } + } + } + } + + // All others + return select( selector.replace( rtrim, "$1" ), context, results, seed ); +} + +/** + * Create key-value caches of limited size + * @returns {function(string, object)} Returns the Object data after storing it on itself with + * property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength) + * deleting the oldest entry + */ +function createCache() { + var keys = []; + + function cache( key, value ) { + + // Use (key + " ") to avoid collision with native prototype properties (see Issue #157) + if ( keys.push( key + " " ) > Expr.cacheLength ) { + + // Only keep the most recent entries + delete cache[ keys.shift() ]; + } + return ( cache[ key + " " ] = value ); + } + return cache; +} + +/** + * Mark a function for special use by Sizzle + * @param {Function} fn The function to mark + */ +function markFunction( fn ) { + fn[ expando ] = true; + return fn; +} + +/** + * Support testing using an element + * @param {Function} fn Passed the created element and returns a boolean result + */ +function assert( fn ) { + var el = document.createElement( "fieldset" ); + + try { + return !!fn( el ); + } catch ( e ) { + return false; + } finally { + + // Remove from its parent by default + if ( el.parentNode ) { + el.parentNode.removeChild( el ); + } + + // release memory in IE + el = null; + } +} + +/** + * Adds the same handler for all of the specified attrs + * @param {String} attrs Pipe-separated list of attributes + * @param {Function} handler The method that will be applied + */ +function addHandle( attrs, handler ) { + var arr = attrs.split( "|" ), + i = arr.length; + + while ( i-- ) { + Expr.attrHandle[ arr[ i ] ] = handler; + } +} + +/** + * Checks document order of two siblings + * @param {Element} a + * @param {Element} b + * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b + */ +function siblingCheck( a, b ) { + var cur = b && a, + diff = cur && a.nodeType === 1 && b.nodeType === 1 && + a.sourceIndex - b.sourceIndex; + + // Use IE sourceIndex if available on both nodes + if ( diff ) { + return diff; + } + + // Check if b follows a + if ( cur ) { + while ( ( cur = cur.nextSibling ) ) { + if ( cur === b ) { + return -1; + } + } + } + + return a ? 1 : -1; +} + +/** + * Returns a function to use in pseudos for input types + * @param {String} type + */ +function createInputPseudo( type ) { + return function( elem ) { + var name = elem.nodeName.toLowerCase(); + return name === "input" && elem.type === type; + }; +} + +/** + * Returns a function to use in pseudos for buttons + * @param {String} type + */ +function createButtonPseudo( type ) { + return function( elem ) { + var name = elem.nodeName.toLowerCase(); + return ( name === "input" || name === "button" ) && elem.type === type; + }; +} + +/** + * Returns a function to use in pseudos for :enabled/:disabled + * @param {Boolean} disabled true for :disabled; false for :enabled + */ +function createDisabledPseudo( disabled ) { + + // Known :disabled false positives: fieldset[disabled] > legend:nth-of-type(n+2) :can-disable + return function( elem ) { + + // Only certain elements can match :enabled or :disabled + // https://html.spec.whatwg.org/multipage/scripting.html#selector-enabled + // https://html.spec.whatwg.org/multipage/scripting.html#selector-disabled + if ( "form" in elem ) { + + // Check for inherited disabledness on relevant non-disabled elements: + // * listed form-associated elements in a disabled fieldset + // https://html.spec.whatwg.org/multipage/forms.html#category-listed + // https://html.spec.whatwg.org/multipage/forms.html#concept-fe-disabled + // * option elements in a disabled optgroup + // https://html.spec.whatwg.org/multipage/forms.html#concept-option-disabled + // All such elements have a "form" property. + if ( elem.parentNode && elem.disabled === false ) { + + // Option elements defer to a parent optgroup if present + if ( "label" in elem ) { + if ( "label" in elem.parentNode ) { + return elem.parentNode.disabled === disabled; + } else { + return elem.disabled === disabled; + } + } + + // Support: IE 6 - 11 + // Use the isDisabled shortcut property to check for disabled fieldset ancestors + return elem.isDisabled === disabled || + + // Where there is no isDisabled, check manually + /* jshint -W018 */ + elem.isDisabled !== !disabled && + inDisabledFieldset( elem ) === disabled; + } + + return elem.disabled === disabled; + + // Try to winnow out elements that can't be disabled before trusting the disabled property. + // Some victims get caught in our net (label, legend, menu, track), but it shouldn't + // even exist on them, let alone have a boolean value. + } else if ( "label" in elem ) { + return elem.disabled === disabled; + } + + // Remaining elements are neither :enabled nor :disabled + return false; + }; +} + +/** + * Returns a function to use in pseudos for positionals + * @param {Function} fn + */ +function createPositionalPseudo( fn ) { + return markFunction( function( argument ) { + argument = +argument; + return markFunction( function( seed, matches ) { + var j, + matchIndexes = fn( [], seed.length, argument ), + i = matchIndexes.length; + + // Match elements found at the specified indexes + while ( i-- ) { + if ( seed[ ( j = matchIndexes[ i ] ) ] ) { + seed[ j ] = !( matches[ j ] = seed[ j ] ); + } + } + } ); + } ); +} + +/** + * Checks a node for validity as a Sizzle context + * @param {Element|Object=} context + * @returns {Element|Object|Boolean} The input node if acceptable, otherwise a falsy value + */ +function testContext( context ) { + return context && typeof context.getElementsByTagName !== "undefined" && context; +} + +// Expose support vars for convenience +support = Sizzle.support = {}; + +/** + * Detects XML nodes + * @param {Element|Object} elem An element or a document + * @returns {Boolean} True iff elem is a non-HTML XML node + */ +isXML = Sizzle.isXML = function( elem ) { + var namespace = elem.namespaceURI, + docElem = ( elem.ownerDocument || elem ).documentElement; + + // Support: IE <=8 + // Assume HTML when documentElement doesn't yet exist, such as inside loading iframes + // https://bugs.jquery.com/ticket/4833 + return !rhtml.test( namespace || docElem && docElem.nodeName || "HTML" ); +}; + +/** + * Sets document-related variables once based on the current document + * @param {Element|Object} [doc] An element or document object to use to set the document + * @returns {Object} Returns the current document + */ +setDocument = Sizzle.setDocument = function( node ) { + var hasCompare, subWindow, + doc = node ? node.ownerDocument || node : preferredDoc; + + // Return early if doc is invalid or already selected + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( doc == document || doc.nodeType !== 9 || !doc.documentElement ) { + return document; + } + + // Update global variables + document = doc; + docElem = document.documentElement; + documentIsHTML = !isXML( document ); + + // Support: IE 9 - 11+, Edge 12 - 18+ + // Accessing iframe documents after unload throws "permission denied" errors (jQuery #13936) + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( preferredDoc != document && + ( subWindow = document.defaultView ) && subWindow.top !== subWindow ) { + + // Support: IE 11, Edge + if ( subWindow.addEventListener ) { + subWindow.addEventListener( "unload", unloadHandler, false ); + + // Support: IE 9 - 10 only + } else if ( subWindow.attachEvent ) { + subWindow.attachEvent( "onunload", unloadHandler ); + } + } + + // Support: IE 8 - 11+, Edge 12 - 18+, Chrome <=16 - 25 only, Firefox <=3.6 - 31 only, + // Safari 4 - 5 only, Opera <=11.6 - 12.x only + // IE/Edge & older browsers don't support the :scope pseudo-class. + // Support: Safari 6.0 only + // Safari 6.0 supports :scope but it's an alias of :root there. + support.scope = assert( function( el ) { + docElem.appendChild( el ).appendChild( document.createElement( "div" ) ); + return typeof el.querySelectorAll !== "undefined" && + !el.querySelectorAll( ":scope fieldset div" ).length; + } ); + + /* Attributes + ---------------------------------------------------------------------- */ + + // Support: IE<8 + // Verify that getAttribute really returns attributes and not properties + // (excepting IE8 booleans) + support.attributes = assert( function( el ) { + el.className = "i"; + return !el.getAttribute( "className" ); + } ); + + /* getElement(s)By* + ---------------------------------------------------------------------- */ + + // Check if getElementsByTagName("*") returns only elements + support.getElementsByTagName = assert( function( el ) { + el.appendChild( document.createComment( "" ) ); + return !el.getElementsByTagName( "*" ).length; + } ); + + // Support: IE<9 + support.getElementsByClassName = rnative.test( document.getElementsByClassName ); + + // Support: IE<10 + // Check if getElementById returns elements by name + // The broken getElementById methods don't pick up programmatically-set names, + // so use a roundabout getElementsByName test + support.getById = assert( function( el ) { + docElem.appendChild( el ).id = expando; + return !document.getElementsByName || !document.getElementsByName( expando ).length; + } ); + + // ID filter and find + if ( support.getById ) { + Expr.filter[ "ID" ] = function( id ) { + var attrId = id.replace( runescape, funescape ); + return function( elem ) { + return elem.getAttribute( "id" ) === attrId; + }; + }; + Expr.find[ "ID" ] = function( id, context ) { + if ( typeof context.getElementById !== "undefined" && documentIsHTML ) { + var elem = context.getElementById( id ); + return elem ? [ elem ] : []; + } + }; + } else { + Expr.filter[ "ID" ] = function( id ) { + var attrId = id.replace( runescape, funescape ); + return function( elem ) { + var node = typeof elem.getAttributeNode !== "undefined" && + elem.getAttributeNode( "id" ); + return node && node.value === attrId; + }; + }; + + // Support: IE 6 - 7 only + // getElementById is not reliable as a find shortcut + Expr.find[ "ID" ] = function( id, context ) { + if ( typeof context.getElementById !== "undefined" && documentIsHTML ) { + var node, i, elems, + elem = context.getElementById( id ); + + if ( elem ) { + + // Verify the id attribute + node = elem.getAttributeNode( "id" ); + if ( node && node.value === id ) { + return [ elem ]; + } + + // Fall back on getElementsByName + elems = context.getElementsByName( id ); + i = 0; + while ( ( elem = elems[ i++ ] ) ) { + node = elem.getAttributeNode( "id" ); + if ( node && node.value === id ) { + return [ elem ]; + } + } + } + + return []; + } + }; + } + + // Tag + Expr.find[ "TAG" ] = support.getElementsByTagName ? + function( tag, context ) { + if ( typeof context.getElementsByTagName !== "undefined" ) { + return context.getElementsByTagName( tag ); + + // DocumentFragment nodes don't have gEBTN + } else if ( support.qsa ) { + return context.querySelectorAll( tag ); + } + } : + + function( tag, context ) { + var elem, + tmp = [], + i = 0, + + // By happy coincidence, a (broken) gEBTN appears on DocumentFragment nodes too + results = context.getElementsByTagName( tag ); + + // Filter out possible comments + if ( tag === "*" ) { + while ( ( elem = results[ i++ ] ) ) { + if ( elem.nodeType === 1 ) { + tmp.push( elem ); + } + } + + return tmp; + } + return results; + }; + + // Class + Expr.find[ "CLASS" ] = support.getElementsByClassName && function( className, context ) { + if ( typeof context.getElementsByClassName !== "undefined" && documentIsHTML ) { + return context.getElementsByClassName( className ); + } + }; + + /* QSA/matchesSelector + ---------------------------------------------------------------------- */ + + // QSA and matchesSelector support + + // matchesSelector(:active) reports false when true (IE9/Opera 11.5) + rbuggyMatches = []; + + // qSa(:focus) reports false when true (Chrome 21) + // We allow this because of a bug in IE8/9 that throws an error + // whenever `document.activeElement` is accessed on an iframe + // So, we allow :focus to pass through QSA all the time to avoid the IE error + // See https://bugs.jquery.com/ticket/13378 + rbuggyQSA = []; + + if ( ( support.qsa = rnative.test( document.querySelectorAll ) ) ) { + + // Build QSA regex + // Regex strategy adopted from Diego Perini + assert( function( el ) { + + var input; + + // Select is set to empty string on purpose + // This is to test IE's treatment of not explicitly + // setting a boolean content attribute, + // since its presence should be enough + // https://bugs.jquery.com/ticket/12359 + docElem.appendChild( el ).innerHTML = "" + + ""; + + // Support: IE8, Opera 11-12.16 + // Nothing should be selected when empty strings follow ^= or $= or *= + // The test attribute must be unknown in Opera but "safe" for WinRT + // https://msdn.microsoft.com/en-us/library/ie/hh465388.aspx#attribute_section + if ( el.querySelectorAll( "[msallowcapture^='']" ).length ) { + rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:''|\"\")" ); + } + + // Support: IE8 + // Boolean attributes and "value" are not treated correctly + if ( !el.querySelectorAll( "[selected]" ).length ) { + rbuggyQSA.push( "\\[" + whitespace + "*(?:value|" + booleans + ")" ); + } + + // Support: Chrome<29, Android<4.4, Safari<7.0+, iOS<7.0+, PhantomJS<1.9.8+ + if ( !el.querySelectorAll( "[id~=" + expando + "-]" ).length ) { + rbuggyQSA.push( "~=" ); + } + + // Support: IE 11+, Edge 15 - 18+ + // IE 11/Edge don't find elements on a `[name='']` query in some cases. + // Adding a temporary attribute to the document before the selection works + // around the issue. + // Interestingly, IE 10 & older don't seem to have the issue. + input = document.createElement( "input" ); + input.setAttribute( "name", "" ); + el.appendChild( input ); + if ( !el.querySelectorAll( "[name='']" ).length ) { + rbuggyQSA.push( "\\[" + whitespace + "*name" + whitespace + "*=" + + whitespace + "*(?:''|\"\")" ); + } + + // Webkit/Opera - :checked should return selected option elements + // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked + // IE8 throws error here and will not see later tests + if ( !el.querySelectorAll( ":checked" ).length ) { + rbuggyQSA.push( ":checked" ); + } + + // Support: Safari 8+, iOS 8+ + // https://bugs.webkit.org/show_bug.cgi?id=136851 + // In-page `selector#id sibling-combinator selector` fails + if ( !el.querySelectorAll( "a#" + expando + "+*" ).length ) { + rbuggyQSA.push( ".#.+[+~]" ); + } + + // Support: Firefox <=3.6 - 5 only + // Old Firefox doesn't throw on a badly-escaped identifier. + el.querySelectorAll( "\\\f" ); + rbuggyQSA.push( "[\\r\\n\\f]" ); + } ); + + assert( function( el ) { + el.innerHTML = "" + + ""; + + // Support: Windows 8 Native Apps + // The type and name attributes are restricted during .innerHTML assignment + var input = document.createElement( "input" ); + input.setAttribute( "type", "hidden" ); + el.appendChild( input ).setAttribute( "name", "D" ); + + // Support: IE8 + // Enforce case-sensitivity of name attribute + if ( el.querySelectorAll( "[name=d]" ).length ) { + rbuggyQSA.push( "name" + whitespace + "*[*^$|!~]?=" ); + } + + // FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled) + // IE8 throws error here and will not see later tests + if ( el.querySelectorAll( ":enabled" ).length !== 2 ) { + rbuggyQSA.push( ":enabled", ":disabled" ); + } + + // Support: IE9-11+ + // IE's :disabled selector does not pick up the children of disabled fieldsets + docElem.appendChild( el ).disabled = true; + if ( el.querySelectorAll( ":disabled" ).length !== 2 ) { + rbuggyQSA.push( ":enabled", ":disabled" ); + } + + // Support: Opera 10 - 11 only + // Opera 10-11 does not throw on post-comma invalid pseudos + el.querySelectorAll( "*,:x" ); + rbuggyQSA.push( ",.*:" ); + } ); + } + + if ( ( support.matchesSelector = rnative.test( ( matches = docElem.matches || + docElem.webkitMatchesSelector || + docElem.mozMatchesSelector || + docElem.oMatchesSelector || + docElem.msMatchesSelector ) ) ) ) { + + assert( function( el ) { + + // Check to see if it's possible to do matchesSelector + // on a disconnected node (IE 9) + support.disconnectedMatch = matches.call( el, "*" ); + + // This should fail with an exception + // Gecko does not error, returns false instead + matches.call( el, "[s!='']:x" ); + rbuggyMatches.push( "!=", pseudos ); + } ); + } + + rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join( "|" ) ); + rbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join( "|" ) ); + + /* Contains + ---------------------------------------------------------------------- */ + hasCompare = rnative.test( docElem.compareDocumentPosition ); + + // Element contains another + // Purposefully self-exclusive + // As in, an element does not contain itself + contains = hasCompare || rnative.test( docElem.contains ) ? + function( a, b ) { + var adown = a.nodeType === 9 ? a.documentElement : a, + bup = b && b.parentNode; + return a === bup || !!( bup && bup.nodeType === 1 && ( + adown.contains ? + adown.contains( bup ) : + a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16 + ) ); + } : + function( a, b ) { + if ( b ) { + while ( ( b = b.parentNode ) ) { + if ( b === a ) { + return true; + } + } + } + return false; + }; + + /* Sorting + ---------------------------------------------------------------------- */ + + // Document order sorting + sortOrder = hasCompare ? + function( a, b ) { + + // Flag for duplicate removal + if ( a === b ) { + hasDuplicate = true; + return 0; + } + + // Sort on method existence if only one input has compareDocumentPosition + var compare = !a.compareDocumentPosition - !b.compareDocumentPosition; + if ( compare ) { + return compare; + } + + // Calculate position if both inputs belong to the same document + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + compare = ( a.ownerDocument || a ) == ( b.ownerDocument || b ) ? + a.compareDocumentPosition( b ) : + + // Otherwise we know they are disconnected + 1; + + // Disconnected nodes + if ( compare & 1 || + ( !support.sortDetached && b.compareDocumentPosition( a ) === compare ) ) { + + // Choose the first element that is related to our preferred document + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( a == document || a.ownerDocument == preferredDoc && + contains( preferredDoc, a ) ) { + return -1; + } + + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( b == document || b.ownerDocument == preferredDoc && + contains( preferredDoc, b ) ) { + return 1; + } + + // Maintain original order + return sortInput ? + ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) : + 0; + } + + return compare & 4 ? -1 : 1; + } : + function( a, b ) { + + // Exit early if the nodes are identical + if ( a === b ) { + hasDuplicate = true; + return 0; + } + + var cur, + i = 0, + aup = a.parentNode, + bup = b.parentNode, + ap = [ a ], + bp = [ b ]; + + // Parentless nodes are either documents or disconnected + if ( !aup || !bup ) { + + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + /* eslint-disable eqeqeq */ + return a == document ? -1 : + b == document ? 1 : + /* eslint-enable eqeqeq */ + aup ? -1 : + bup ? 1 : + sortInput ? + ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) : + 0; + + // If the nodes are siblings, we can do a quick check + } else if ( aup === bup ) { + return siblingCheck( a, b ); + } + + // Otherwise we need full lists of their ancestors for comparison + cur = a; + while ( ( cur = cur.parentNode ) ) { + ap.unshift( cur ); + } + cur = b; + while ( ( cur = cur.parentNode ) ) { + bp.unshift( cur ); + } + + // Walk down the tree looking for a discrepancy + while ( ap[ i ] === bp[ i ] ) { + i++; + } + + return i ? + + // Do a sibling check if the nodes have a common ancestor + siblingCheck( ap[ i ], bp[ i ] ) : + + // Otherwise nodes in our document sort first + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + /* eslint-disable eqeqeq */ + ap[ i ] == preferredDoc ? -1 : + bp[ i ] == preferredDoc ? 1 : + /* eslint-enable eqeqeq */ + 0; + }; + + return document; +}; + +Sizzle.matches = function( expr, elements ) { + return Sizzle( expr, null, null, elements ); +}; + +Sizzle.matchesSelector = function( elem, expr ) { + setDocument( elem ); + + if ( support.matchesSelector && documentIsHTML && + !nonnativeSelectorCache[ expr + " " ] && + ( !rbuggyMatches || !rbuggyMatches.test( expr ) ) && + ( !rbuggyQSA || !rbuggyQSA.test( expr ) ) ) { + + try { + var ret = matches.call( elem, expr ); + + // IE 9's matchesSelector returns false on disconnected nodes + if ( ret || support.disconnectedMatch || + + // As well, disconnected nodes are said to be in a document + // fragment in IE 9 + elem.document && elem.document.nodeType !== 11 ) { + return ret; + } + } catch ( e ) { + nonnativeSelectorCache( expr, true ); + } + } + + return Sizzle( expr, document, null, [ elem ] ).length > 0; +}; + +Sizzle.contains = function( context, elem ) { + + // Set document vars if needed + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( ( context.ownerDocument || context ) != document ) { + setDocument( context ); + } + return contains( context, elem ); +}; + +Sizzle.attr = function( elem, name ) { + + // Set document vars if needed + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( ( elem.ownerDocument || elem ) != document ) { + setDocument( elem ); + } + + var fn = Expr.attrHandle[ name.toLowerCase() ], + + // Don't get fooled by Object.prototype properties (jQuery #13807) + val = fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ? + fn( elem, name, !documentIsHTML ) : + undefined; + + return val !== undefined ? + val : + support.attributes || !documentIsHTML ? + elem.getAttribute( name ) : + ( val = elem.getAttributeNode( name ) ) && val.specified ? + val.value : + null; +}; + +Sizzle.escape = function( sel ) { + return ( sel + "" ).replace( rcssescape, fcssescape ); +}; + +Sizzle.error = function( msg ) { + throw new Error( "Syntax error, unrecognized expression: " + msg ); +}; + +/** + * Document sorting and removing duplicates + * @param {ArrayLike} results + */ +Sizzle.uniqueSort = function( results ) { + var elem, + duplicates = [], + j = 0, + i = 0; + + // Unless we *know* we can detect duplicates, assume their presence + hasDuplicate = !support.detectDuplicates; + sortInput = !support.sortStable && results.slice( 0 ); + results.sort( sortOrder ); + + if ( hasDuplicate ) { + while ( ( elem = results[ i++ ] ) ) { + if ( elem === results[ i ] ) { + j = duplicates.push( i ); + } + } + while ( j-- ) { + results.splice( duplicates[ j ], 1 ); + } + } + + // Clear input after sorting to release objects + // See https://github.com/jquery/sizzle/pull/225 + sortInput = null; + + return results; +}; + +/** + * Utility function for retrieving the text value of an array of DOM nodes + * @param {Array|Element} elem + */ +getText = Sizzle.getText = function( elem ) { + var node, + ret = "", + i = 0, + nodeType = elem.nodeType; + + if ( !nodeType ) { + + // If no nodeType, this is expected to be an array + while ( ( node = elem[ i++ ] ) ) { + + // Do not traverse comment nodes + ret += getText( node ); + } + } else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) { + + // Use textContent for elements + // innerText usage removed for consistency of new lines (jQuery #11153) + if ( typeof elem.textContent === "string" ) { + return elem.textContent; + } else { + + // Traverse its children + for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { + ret += getText( elem ); + } + } + } else if ( nodeType === 3 || nodeType === 4 ) { + return elem.nodeValue; + } + + // Do not include comment or processing instruction nodes + + return ret; +}; + +Expr = Sizzle.selectors = { + + // Can be adjusted by the user + cacheLength: 50, + + createPseudo: markFunction, + + match: matchExpr, + + attrHandle: {}, + + find: {}, + + relative: { + ">": { dir: "parentNode", first: true }, + " ": { dir: "parentNode" }, + "+": { dir: "previousSibling", first: true }, + "~": { dir: "previousSibling" } + }, + + preFilter: { + "ATTR": function( match ) { + match[ 1 ] = match[ 1 ].replace( runescape, funescape ); + + // Move the given value to match[3] whether quoted or unquoted + match[ 3 ] = ( match[ 3 ] || match[ 4 ] || + match[ 5 ] || "" ).replace( runescape, funescape ); + + if ( match[ 2 ] === "~=" ) { + match[ 3 ] = " " + match[ 3 ] + " "; + } + + return match.slice( 0, 4 ); + }, + + "CHILD": function( match ) { + + /* matches from matchExpr["CHILD"] + 1 type (only|nth|...) + 2 what (child|of-type) + 3 argument (even|odd|\d*|\d*n([+-]\d+)?|...) + 4 xn-component of xn+y argument ([+-]?\d*n|) + 5 sign of xn-component + 6 x of xn-component + 7 sign of y-component + 8 y of y-component + */ + match[ 1 ] = match[ 1 ].toLowerCase(); + + if ( match[ 1 ].slice( 0, 3 ) === "nth" ) { + + // nth-* requires argument + if ( !match[ 3 ] ) { + Sizzle.error( match[ 0 ] ); + } + + // numeric x and y parameters for Expr.filter.CHILD + // remember that false/true cast respectively to 0/1 + match[ 4 ] = +( match[ 4 ] ? + match[ 5 ] + ( match[ 6 ] || 1 ) : + 2 * ( match[ 3 ] === "even" || match[ 3 ] === "odd" ) ); + match[ 5 ] = +( ( match[ 7 ] + match[ 8 ] ) || match[ 3 ] === "odd" ); + + // other types prohibit arguments + } else if ( match[ 3 ] ) { + Sizzle.error( match[ 0 ] ); + } + + return match; + }, + + "PSEUDO": function( match ) { + var excess, + unquoted = !match[ 6 ] && match[ 2 ]; + + if ( matchExpr[ "CHILD" ].test( match[ 0 ] ) ) { + return null; + } + + // Accept quoted arguments as-is + if ( match[ 3 ] ) { + match[ 2 ] = match[ 4 ] || match[ 5 ] || ""; + + // Strip excess characters from unquoted arguments + } else if ( unquoted && rpseudo.test( unquoted ) && + + // Get excess from tokenize (recursively) + ( excess = tokenize( unquoted, true ) ) && + + // advance to the next closing parenthesis + ( excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length ) ) { + + // excess is a negative index + match[ 0 ] = match[ 0 ].slice( 0, excess ); + match[ 2 ] = unquoted.slice( 0, excess ); + } + + // Return only captures needed by the pseudo filter method (type and argument) + return match.slice( 0, 3 ); + } + }, + + filter: { + + "TAG": function( nodeNameSelector ) { + var nodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase(); + return nodeNameSelector === "*" ? + function() { + return true; + } : + function( elem ) { + return elem.nodeName && elem.nodeName.toLowerCase() === nodeName; + }; + }, + + "CLASS": function( className ) { + var pattern = classCache[ className + " " ]; + + return pattern || + ( pattern = new RegExp( "(^|" + whitespace + + ")" + className + "(" + whitespace + "|$)" ) ) && classCache( + className, function( elem ) { + return pattern.test( + typeof elem.className === "string" && elem.className || + typeof elem.getAttribute !== "undefined" && + elem.getAttribute( "class" ) || + "" + ); + } ); + }, + + "ATTR": function( name, operator, check ) { + return function( elem ) { + var result = Sizzle.attr( elem, name ); + + if ( result == null ) { + return operator === "!="; + } + if ( !operator ) { + return true; + } + + result += ""; + + /* eslint-disable max-len */ + + return operator === "=" ? result === check : + operator === "!=" ? result !== check : + operator === "^=" ? check && result.indexOf( check ) === 0 : + operator === "*=" ? check && result.indexOf( check ) > -1 : + operator === "$=" ? check && result.slice( -check.length ) === check : + operator === "~=" ? ( " " + result.replace( rwhitespace, " " ) + " " ).indexOf( check ) > -1 : + operator === "|=" ? result === check || result.slice( 0, check.length + 1 ) === check + "-" : + false; + /* eslint-enable max-len */ + + }; + }, + + "CHILD": function( type, what, _argument, first, last ) { + var simple = type.slice( 0, 3 ) !== "nth", + forward = type.slice( -4 ) !== "last", + ofType = what === "of-type"; + + return first === 1 && last === 0 ? + + // Shortcut for :nth-*(n) + function( elem ) { + return !!elem.parentNode; + } : + + function( elem, _context, xml ) { + var cache, uniqueCache, outerCache, node, nodeIndex, start, + dir = simple !== forward ? "nextSibling" : "previousSibling", + parent = elem.parentNode, + name = ofType && elem.nodeName.toLowerCase(), + useCache = !xml && !ofType, + diff = false; + + if ( parent ) { + + // :(first|last|only)-(child|of-type) + if ( simple ) { + while ( dir ) { + node = elem; + while ( ( node = node[ dir ] ) ) { + if ( ofType ? + node.nodeName.toLowerCase() === name : + node.nodeType === 1 ) { + + return false; + } + } + + // Reverse direction for :only-* (if we haven't yet done so) + start = dir = type === "only" && !start && "nextSibling"; + } + return true; + } + + start = [ forward ? parent.firstChild : parent.lastChild ]; + + // non-xml :nth-child(...) stores cache data on `parent` + if ( forward && useCache ) { + + // Seek `elem` from a previously-cached index + + // ...in a gzip-friendly way + node = parent; + outerCache = node[ expando ] || ( node[ expando ] = {} ); + + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ node.uniqueID ] || + ( outerCache[ node.uniqueID ] = {} ); + + cache = uniqueCache[ type ] || []; + nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ]; + diff = nodeIndex && cache[ 2 ]; + node = nodeIndex && parent.childNodes[ nodeIndex ]; + + while ( ( node = ++nodeIndex && node && node[ dir ] || + + // Fallback to seeking `elem` from the start + ( diff = nodeIndex = 0 ) || start.pop() ) ) { + + // When found, cache indexes on `parent` and break + if ( node.nodeType === 1 && ++diff && node === elem ) { + uniqueCache[ type ] = [ dirruns, nodeIndex, diff ]; + break; + } + } + + } else { + + // Use previously-cached element index if available + if ( useCache ) { + + // ...in a gzip-friendly way + node = elem; + outerCache = node[ expando ] || ( node[ expando ] = {} ); + + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ node.uniqueID ] || + ( outerCache[ node.uniqueID ] = {} ); + + cache = uniqueCache[ type ] || []; + nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ]; + diff = nodeIndex; + } + + // xml :nth-child(...) + // or :nth-last-child(...) or :nth(-last)?-of-type(...) + if ( diff === false ) { + + // Use the same loop as above to seek `elem` from the start + while ( ( node = ++nodeIndex && node && node[ dir ] || + ( diff = nodeIndex = 0 ) || start.pop() ) ) { + + if ( ( ofType ? + node.nodeName.toLowerCase() === name : + node.nodeType === 1 ) && + ++diff ) { + + // Cache the index of each encountered element + if ( useCache ) { + outerCache = node[ expando ] || + ( node[ expando ] = {} ); + + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ node.uniqueID ] || + ( outerCache[ node.uniqueID ] = {} ); + + uniqueCache[ type ] = [ dirruns, diff ]; + } + + if ( node === elem ) { + break; + } + } + } + } + } + + // Incorporate the offset, then check against cycle size + diff -= last; + return diff === first || ( diff % first === 0 && diff / first >= 0 ); + } + }; + }, + + "PSEUDO": function( pseudo, argument ) { + + // pseudo-class names are case-insensitive + // http://www.w3.org/TR/selectors/#pseudo-classes + // Prioritize by case sensitivity in case custom pseudos are added with uppercase letters + // Remember that setFilters inherits from pseudos + var args, + fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] || + Sizzle.error( "unsupported pseudo: " + pseudo ); + + // The user may use createPseudo to indicate that + // arguments are needed to create the filter function + // just as Sizzle does + if ( fn[ expando ] ) { + return fn( argument ); + } + + // But maintain support for old signatures + if ( fn.length > 1 ) { + args = [ pseudo, pseudo, "", argument ]; + return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ? + markFunction( function( seed, matches ) { + var idx, + matched = fn( seed, argument ), + i = matched.length; + while ( i-- ) { + idx = indexOf( seed, matched[ i ] ); + seed[ idx ] = !( matches[ idx ] = matched[ i ] ); + } + } ) : + function( elem ) { + return fn( elem, 0, args ); + }; + } + + return fn; + } + }, + + pseudos: { + + // Potentially complex pseudos + "not": markFunction( function( selector ) { + + // Trim the selector passed to compile + // to avoid treating leading and trailing + // spaces as combinators + var input = [], + results = [], + matcher = compile( selector.replace( rtrim, "$1" ) ); + + return matcher[ expando ] ? + markFunction( function( seed, matches, _context, xml ) { + var elem, + unmatched = matcher( seed, null, xml, [] ), + i = seed.length; + + // Match elements unmatched by `matcher` + while ( i-- ) { + if ( ( elem = unmatched[ i ] ) ) { + seed[ i ] = !( matches[ i ] = elem ); + } + } + } ) : + function( elem, _context, xml ) { + input[ 0 ] = elem; + matcher( input, null, xml, results ); + + // Don't keep the element (issue #299) + input[ 0 ] = null; + return !results.pop(); + }; + } ), + + "has": markFunction( function( selector ) { + return function( elem ) { + return Sizzle( selector, elem ).length > 0; + }; + } ), + + "contains": markFunction( function( text ) { + text = text.replace( runescape, funescape ); + return function( elem ) { + return ( elem.textContent || getText( elem ) ).indexOf( text ) > -1; + }; + } ), + + // "Whether an element is represented by a :lang() selector + // is based solely on the element's language value + // being equal to the identifier C, + // or beginning with the identifier C immediately followed by "-". + // The matching of C against the element's language value is performed case-insensitively. + // The identifier C does not have to be a valid language name." + // http://www.w3.org/TR/selectors/#lang-pseudo + "lang": markFunction( function( lang ) { + + // lang value must be a valid identifier + if ( !ridentifier.test( lang || "" ) ) { + Sizzle.error( "unsupported lang: " + lang ); + } + lang = lang.replace( runescape, funescape ).toLowerCase(); + return function( elem ) { + var elemLang; + do { + if ( ( elemLang = documentIsHTML ? + elem.lang : + elem.getAttribute( "xml:lang" ) || elem.getAttribute( "lang" ) ) ) { + + elemLang = elemLang.toLowerCase(); + return elemLang === lang || elemLang.indexOf( lang + "-" ) === 0; + } + } while ( ( elem = elem.parentNode ) && elem.nodeType === 1 ); + return false; + }; + } ), + + // Miscellaneous + "target": function( elem ) { + var hash = window.location && window.location.hash; + return hash && hash.slice( 1 ) === elem.id; + }, + + "root": function( elem ) { + return elem === docElem; + }, + + "focus": function( elem ) { + return elem === document.activeElement && + ( !document.hasFocus || document.hasFocus() ) && + !!( elem.type || elem.href || ~elem.tabIndex ); + }, + + // Boolean properties + "enabled": createDisabledPseudo( false ), + "disabled": createDisabledPseudo( true ), + + "checked": function( elem ) { + + // In CSS3, :checked should return both checked and selected elements + // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked + var nodeName = elem.nodeName.toLowerCase(); + return ( nodeName === "input" && !!elem.checked ) || + ( nodeName === "option" && !!elem.selected ); + }, + + "selected": function( elem ) { + + // Accessing this property makes selected-by-default + // options in Safari work properly + if ( elem.parentNode ) { + // eslint-disable-next-line no-unused-expressions + elem.parentNode.selectedIndex; + } + + return elem.selected === true; + }, + + // Contents + "empty": function( elem ) { + + // http://www.w3.org/TR/selectors/#empty-pseudo + // :empty is negated by element (1) or content nodes (text: 3; cdata: 4; entity ref: 5), + // but not by others (comment: 8; processing instruction: 7; etc.) + // nodeType < 6 works because attributes (2) do not appear as children + for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { + if ( elem.nodeType < 6 ) { + return false; + } + } + return true; + }, + + "parent": function( elem ) { + return !Expr.pseudos[ "empty" ]( elem ); + }, + + // Element/input types + "header": function( elem ) { + return rheader.test( elem.nodeName ); + }, + + "input": function( elem ) { + return rinputs.test( elem.nodeName ); + }, + + "button": function( elem ) { + var name = elem.nodeName.toLowerCase(); + return name === "input" && elem.type === "button" || name === "button"; + }, + + "text": function( elem ) { + var attr; + return elem.nodeName.toLowerCase() === "input" && + elem.type === "text" && + + // Support: IE<8 + // New HTML5 attribute values (e.g., "search") appear with elem.type === "text" + ( ( attr = elem.getAttribute( "type" ) ) == null || + attr.toLowerCase() === "text" ); + }, + + // Position-in-collection + "first": createPositionalPseudo( function() { + return [ 0 ]; + } ), + + "last": createPositionalPseudo( function( _matchIndexes, length ) { + return [ length - 1 ]; + } ), + + "eq": createPositionalPseudo( function( _matchIndexes, length, argument ) { + return [ argument < 0 ? argument + length : argument ]; + } ), + + "even": createPositionalPseudo( function( matchIndexes, length ) { + var i = 0; + for ( ; i < length; i += 2 ) { + matchIndexes.push( i ); + } + return matchIndexes; + } ), + + "odd": createPositionalPseudo( function( matchIndexes, length ) { + var i = 1; + for ( ; i < length; i += 2 ) { + matchIndexes.push( i ); + } + return matchIndexes; + } ), + + "lt": createPositionalPseudo( function( matchIndexes, length, argument ) { + var i = argument < 0 ? + argument + length : + argument > length ? + length : + argument; + for ( ; --i >= 0; ) { + matchIndexes.push( i ); + } + return matchIndexes; + } ), + + "gt": createPositionalPseudo( function( matchIndexes, length, argument ) { + var i = argument < 0 ? argument + length : argument; + for ( ; ++i < length; ) { + matchIndexes.push( i ); + } + return matchIndexes; + } ) + } +}; + +Expr.pseudos[ "nth" ] = Expr.pseudos[ "eq" ]; + +// Add button/input type pseudos +for ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) { + Expr.pseudos[ i ] = createInputPseudo( i ); +} +for ( i in { submit: true, reset: true } ) { + Expr.pseudos[ i ] = createButtonPseudo( i ); +} + +// Easy API for creating new setFilters +function setFilters() {} +setFilters.prototype = Expr.filters = Expr.pseudos; +Expr.setFilters = new setFilters(); + +tokenize = Sizzle.tokenize = function( selector, parseOnly ) { + var matched, match, tokens, type, + soFar, groups, preFilters, + cached = tokenCache[ selector + " " ]; + + if ( cached ) { + return parseOnly ? 0 : cached.slice( 0 ); + } + + soFar = selector; + groups = []; + preFilters = Expr.preFilter; + + while ( soFar ) { + + // Comma and first run + if ( !matched || ( match = rcomma.exec( soFar ) ) ) { + if ( match ) { + + // Don't consume trailing commas as valid + soFar = soFar.slice( match[ 0 ].length ) || soFar; + } + groups.push( ( tokens = [] ) ); + } + + matched = false; + + // Combinators + if ( ( match = rcombinators.exec( soFar ) ) ) { + matched = match.shift(); + tokens.push( { + value: matched, + + // Cast descendant combinators to space + type: match[ 0 ].replace( rtrim, " " ) + } ); + soFar = soFar.slice( matched.length ); + } + + // Filters + for ( type in Expr.filter ) { + if ( ( match = matchExpr[ type ].exec( soFar ) ) && ( !preFilters[ type ] || + ( match = preFilters[ type ]( match ) ) ) ) { + matched = match.shift(); + tokens.push( { + value: matched, + type: type, + matches: match + } ); + soFar = soFar.slice( matched.length ); + } + } + + if ( !matched ) { + break; + } + } + + // Return the length of the invalid excess + // if we're just parsing + // Otherwise, throw an error or return tokens + return parseOnly ? + soFar.length : + soFar ? + Sizzle.error( selector ) : + + // Cache the tokens + tokenCache( selector, groups ).slice( 0 ); +}; + +function toSelector( tokens ) { + var i = 0, + len = tokens.length, + selector = ""; + for ( ; i < len; i++ ) { + selector += tokens[ i ].value; + } + return selector; +} + +function addCombinator( matcher, combinator, base ) { + var dir = combinator.dir, + skip = combinator.next, + key = skip || dir, + checkNonElements = base && key === "parentNode", + doneName = done++; + + return combinator.first ? + + // Check against closest ancestor/preceding element + function( elem, context, xml ) { + while ( ( elem = elem[ dir ] ) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + return matcher( elem, context, xml ); + } + } + return false; + } : + + // Check against all ancestor/preceding elements + function( elem, context, xml ) { + var oldCache, uniqueCache, outerCache, + newCache = [ dirruns, doneName ]; + + // We can't set arbitrary data on XML nodes, so they don't benefit from combinator caching + if ( xml ) { + while ( ( elem = elem[ dir ] ) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + if ( matcher( elem, context, xml ) ) { + return true; + } + } + } + } else { + while ( ( elem = elem[ dir ] ) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + outerCache = elem[ expando ] || ( elem[ expando ] = {} ); + + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ elem.uniqueID ] || + ( outerCache[ elem.uniqueID ] = {} ); + + if ( skip && skip === elem.nodeName.toLowerCase() ) { + elem = elem[ dir ] || elem; + } else if ( ( oldCache = uniqueCache[ key ] ) && + oldCache[ 0 ] === dirruns && oldCache[ 1 ] === doneName ) { + + // Assign to newCache so results back-propagate to previous elements + return ( newCache[ 2 ] = oldCache[ 2 ] ); + } else { + + // Reuse newcache so results back-propagate to previous elements + uniqueCache[ key ] = newCache; + + // A match means we're done; a fail means we have to keep checking + if ( ( newCache[ 2 ] = matcher( elem, context, xml ) ) ) { + return true; + } + } + } + } + } + return false; + }; +} + +function elementMatcher( matchers ) { + return matchers.length > 1 ? + function( elem, context, xml ) { + var i = matchers.length; + while ( i-- ) { + if ( !matchers[ i ]( elem, context, xml ) ) { + return false; + } + } + return true; + } : + matchers[ 0 ]; +} + +function multipleContexts( selector, contexts, results ) { + var i = 0, + len = contexts.length; + for ( ; i < len; i++ ) { + Sizzle( selector, contexts[ i ], results ); + } + return results; +} + +function condense( unmatched, map, filter, context, xml ) { + var elem, + newUnmatched = [], + i = 0, + len = unmatched.length, + mapped = map != null; + + for ( ; i < len; i++ ) { + if ( ( elem = unmatched[ i ] ) ) { + if ( !filter || filter( elem, context, xml ) ) { + newUnmatched.push( elem ); + if ( mapped ) { + map.push( i ); + } + } + } + } + + return newUnmatched; +} + +function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) { + if ( postFilter && !postFilter[ expando ] ) { + postFilter = setMatcher( postFilter ); + } + if ( postFinder && !postFinder[ expando ] ) { + postFinder = setMatcher( postFinder, postSelector ); + } + return markFunction( function( seed, results, context, xml ) { + var temp, i, elem, + preMap = [], + postMap = [], + preexisting = results.length, + + // Get initial elements from seed or context + elems = seed || multipleContexts( + selector || "*", + context.nodeType ? [ context ] : context, + [] + ), + + // Prefilter to get matcher input, preserving a map for seed-results synchronization + matcherIn = preFilter && ( seed || !selector ) ? + condense( elems, preMap, preFilter, context, xml ) : + elems, + + matcherOut = matcher ? + + // If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results, + postFinder || ( seed ? preFilter : preexisting || postFilter ) ? + + // ...intermediate processing is necessary + [] : + + // ...otherwise use results directly + results : + matcherIn; + + // Find primary matches + if ( matcher ) { + matcher( matcherIn, matcherOut, context, xml ); + } + + // Apply postFilter + if ( postFilter ) { + temp = condense( matcherOut, postMap ); + postFilter( temp, [], context, xml ); + + // Un-match failing elements by moving them back to matcherIn + i = temp.length; + while ( i-- ) { + if ( ( elem = temp[ i ] ) ) { + matcherOut[ postMap[ i ] ] = !( matcherIn[ postMap[ i ] ] = elem ); + } + } + } + + if ( seed ) { + if ( postFinder || preFilter ) { + if ( postFinder ) { + + // Get the final matcherOut by condensing this intermediate into postFinder contexts + temp = []; + i = matcherOut.length; + while ( i-- ) { + if ( ( elem = matcherOut[ i ] ) ) { + + // Restore matcherIn since elem is not yet a final match + temp.push( ( matcherIn[ i ] = elem ) ); + } + } + postFinder( null, ( matcherOut = [] ), temp, xml ); + } + + // Move matched elements from seed to results to keep them synchronized + i = matcherOut.length; + while ( i-- ) { + if ( ( elem = matcherOut[ i ] ) && + ( temp = postFinder ? indexOf( seed, elem ) : preMap[ i ] ) > -1 ) { + + seed[ temp ] = !( results[ temp ] = elem ); + } + } + } + + // Add elements to results, through postFinder if defined + } else { + matcherOut = condense( + matcherOut === results ? + matcherOut.splice( preexisting, matcherOut.length ) : + matcherOut + ); + if ( postFinder ) { + postFinder( null, results, matcherOut, xml ); + } else { + push.apply( results, matcherOut ); + } + } + } ); +} + +function matcherFromTokens( tokens ) { + var checkContext, matcher, j, + len = tokens.length, + leadingRelative = Expr.relative[ tokens[ 0 ].type ], + implicitRelative = leadingRelative || Expr.relative[ " " ], + i = leadingRelative ? 1 : 0, + + // The foundational matcher ensures that elements are reachable from top-level context(s) + matchContext = addCombinator( function( elem ) { + return elem === checkContext; + }, implicitRelative, true ), + matchAnyContext = addCombinator( function( elem ) { + return indexOf( checkContext, elem ) > -1; + }, implicitRelative, true ), + matchers = [ function( elem, context, xml ) { + var ret = ( !leadingRelative && ( xml || context !== outermostContext ) ) || ( + ( checkContext = context ).nodeType ? + matchContext( elem, context, xml ) : + matchAnyContext( elem, context, xml ) ); + + // Avoid hanging onto element (issue #299) + checkContext = null; + return ret; + } ]; + + for ( ; i < len; i++ ) { + if ( ( matcher = Expr.relative[ tokens[ i ].type ] ) ) { + matchers = [ addCombinator( elementMatcher( matchers ), matcher ) ]; + } else { + matcher = Expr.filter[ tokens[ i ].type ].apply( null, tokens[ i ].matches ); + + // Return special upon seeing a positional matcher + if ( matcher[ expando ] ) { + + // Find the next relative operator (if any) for proper handling + j = ++i; + for ( ; j < len; j++ ) { + if ( Expr.relative[ tokens[ j ].type ] ) { + break; + } + } + return setMatcher( + i > 1 && elementMatcher( matchers ), + i > 1 && toSelector( + + // If the preceding token was a descendant combinator, insert an implicit any-element `*` + tokens + .slice( 0, i - 1 ) + .concat( { value: tokens[ i - 2 ].type === " " ? "*" : "" } ) + ).replace( rtrim, "$1" ), + matcher, + i < j && matcherFromTokens( tokens.slice( i, j ) ), + j < len && matcherFromTokens( ( tokens = tokens.slice( j ) ) ), + j < len && toSelector( tokens ) + ); + } + matchers.push( matcher ); + } + } + + return elementMatcher( matchers ); +} + +function matcherFromGroupMatchers( elementMatchers, setMatchers ) { + var bySet = setMatchers.length > 0, + byElement = elementMatchers.length > 0, + superMatcher = function( seed, context, xml, results, outermost ) { + var elem, j, matcher, + matchedCount = 0, + i = "0", + unmatched = seed && [], + setMatched = [], + contextBackup = outermostContext, + + // We must always have either seed elements or outermost context + elems = seed || byElement && Expr.find[ "TAG" ]( "*", outermost ), + + // Use integer dirruns iff this is the outermost matcher + dirrunsUnique = ( dirruns += contextBackup == null ? 1 : Math.random() || 0.1 ), + len = elems.length; + + if ( outermost ) { + + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + outermostContext = context == document || context || outermost; + } + + // Add elements passing elementMatchers directly to results + // Support: IE<9, Safari + // Tolerate NodeList properties (IE: "length"; Safari: ) matching elements by id + for ( ; i !== len && ( elem = elems[ i ] ) != null; i++ ) { + if ( byElement && elem ) { + j = 0; + + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( !context && elem.ownerDocument != document ) { + setDocument( elem ); + xml = !documentIsHTML; + } + while ( ( matcher = elementMatchers[ j++ ] ) ) { + if ( matcher( elem, context || document, xml ) ) { + results.push( elem ); + break; + } + } + if ( outermost ) { + dirruns = dirrunsUnique; + } + } + + // Track unmatched elements for set filters + if ( bySet ) { + + // They will have gone through all possible matchers + if ( ( elem = !matcher && elem ) ) { + matchedCount--; + } + + // Lengthen the array for every element, matched or not + if ( seed ) { + unmatched.push( elem ); + } + } + } + + // `i` is now the count of elements visited above, and adding it to `matchedCount` + // makes the latter nonnegative. + matchedCount += i; + + // Apply set filters to unmatched elements + // NOTE: This can be skipped if there are no unmatched elements (i.e., `matchedCount` + // equals `i`), unless we didn't visit _any_ elements in the above loop because we have + // no element matchers and no seed. + // Incrementing an initially-string "0" `i` allows `i` to remain a string only in that + // case, which will result in a "00" `matchedCount` that differs from `i` but is also + // numerically zero. + if ( bySet && i !== matchedCount ) { + j = 0; + while ( ( matcher = setMatchers[ j++ ] ) ) { + matcher( unmatched, setMatched, context, xml ); + } + + if ( seed ) { + + // Reintegrate element matches to eliminate the need for sorting + if ( matchedCount > 0 ) { + while ( i-- ) { + if ( !( unmatched[ i ] || setMatched[ i ] ) ) { + setMatched[ i ] = pop.call( results ); + } + } + } + + // Discard index placeholder values to get only actual matches + setMatched = condense( setMatched ); + } + + // Add matches to results + push.apply( results, setMatched ); + + // Seedless set matches succeeding multiple successful matchers stipulate sorting + if ( outermost && !seed && setMatched.length > 0 && + ( matchedCount + setMatchers.length ) > 1 ) { + + Sizzle.uniqueSort( results ); + } + } + + // Override manipulation of globals by nested matchers + if ( outermost ) { + dirruns = dirrunsUnique; + outermostContext = contextBackup; + } + + return unmatched; + }; + + return bySet ? + markFunction( superMatcher ) : + superMatcher; +} + +compile = Sizzle.compile = function( selector, match /* Internal Use Only */ ) { + var i, + setMatchers = [], + elementMatchers = [], + cached = compilerCache[ selector + " " ]; + + if ( !cached ) { + + // Generate a function of recursive functions that can be used to check each element + if ( !match ) { + match = tokenize( selector ); + } + i = match.length; + while ( i-- ) { + cached = matcherFromTokens( match[ i ] ); + if ( cached[ expando ] ) { + setMatchers.push( cached ); + } else { + elementMatchers.push( cached ); + } + } + + // Cache the compiled function + cached = compilerCache( + selector, + matcherFromGroupMatchers( elementMatchers, setMatchers ) + ); + + // Save selector and tokenization + cached.selector = selector; + } + return cached; +}; + +/** + * A low-level selection function that works with Sizzle's compiled + * selector functions + * @param {String|Function} selector A selector or a pre-compiled + * selector function built with Sizzle.compile + * @param {Element} context + * @param {Array} [results] + * @param {Array} [seed] A set of elements to match against + */ +select = Sizzle.select = function( selector, context, results, seed ) { + var i, tokens, token, type, find, + compiled = typeof selector === "function" && selector, + match = !seed && tokenize( ( selector = compiled.selector || selector ) ); + + results = results || []; + + // Try to minimize operations if there is only one selector in the list and no seed + // (the latter of which guarantees us context) + if ( match.length === 1 ) { + + // Reduce context if the leading compound selector is an ID + tokens = match[ 0 ] = match[ 0 ].slice( 0 ); + if ( tokens.length > 2 && ( token = tokens[ 0 ] ).type === "ID" && + context.nodeType === 9 && documentIsHTML && Expr.relative[ tokens[ 1 ].type ] ) { + + context = ( Expr.find[ "ID" ]( token.matches[ 0 ] + .replace( runescape, funescape ), context ) || [] )[ 0 ]; + if ( !context ) { + return results; + + // Precompiled matchers will still verify ancestry, so step up a level + } else if ( compiled ) { + context = context.parentNode; + } + + selector = selector.slice( tokens.shift().value.length ); + } + + // Fetch a seed set for right-to-left matching + i = matchExpr[ "needsContext" ].test( selector ) ? 0 : tokens.length; + while ( i-- ) { + token = tokens[ i ]; + + // Abort if we hit a combinator + if ( Expr.relative[ ( type = token.type ) ] ) { + break; + } + if ( ( find = Expr.find[ type ] ) ) { + + // Search, expanding context for leading sibling combinators + if ( ( seed = find( + token.matches[ 0 ].replace( runescape, funescape ), + rsibling.test( tokens[ 0 ].type ) && testContext( context.parentNode ) || + context + ) ) ) { + + // If seed is empty or no tokens remain, we can return early + tokens.splice( i, 1 ); + selector = seed.length && toSelector( tokens ); + if ( !selector ) { + push.apply( results, seed ); + return results; + } + + break; + } + } + } + } + + // Compile and execute a filtering function if one is not provided + // Provide `match` to avoid retokenization if we modified the selector above + ( compiled || compile( selector, match ) )( + seed, + context, + !documentIsHTML, + results, + !context || rsibling.test( selector ) && testContext( context.parentNode ) || context + ); + return results; +}; + +// One-time assignments + +// Sort stability +support.sortStable = expando.split( "" ).sort( sortOrder ).join( "" ) === expando; + +// Support: Chrome 14-35+ +// Always assume duplicates if they aren't passed to the comparison function +support.detectDuplicates = !!hasDuplicate; + +// Initialize against the default document +setDocument(); + +// Support: Webkit<537.32 - Safari 6.0.3/Chrome 25 (fixed in Chrome 27) +// Detached nodes confoundingly follow *each other* +support.sortDetached = assert( function( el ) { + + // Should return 1, but returns 4 (following) + return el.compareDocumentPosition( document.createElement( "fieldset" ) ) & 1; +} ); + +// Support: IE<8 +// Prevent attribute/property "interpolation" +// https://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx +if ( !assert( function( el ) { + el.innerHTML = ""; + return el.firstChild.getAttribute( "href" ) === "#"; +} ) ) { + addHandle( "type|href|height|width", function( elem, name, isXML ) { + if ( !isXML ) { + return elem.getAttribute( name, name.toLowerCase() === "type" ? 1 : 2 ); + } + } ); +} + +// Support: IE<9 +// Use defaultValue in place of getAttribute("value") +if ( !support.attributes || !assert( function( el ) { + el.innerHTML = ""; + el.firstChild.setAttribute( "value", "" ); + return el.firstChild.getAttribute( "value" ) === ""; +} ) ) { + addHandle( "value", function( elem, _name, isXML ) { + if ( !isXML && elem.nodeName.toLowerCase() === "input" ) { + return elem.defaultValue; + } + } ); +} + +// Support: IE<9 +// Use getAttributeNode to fetch booleans when getAttribute lies +if ( !assert( function( el ) { + return el.getAttribute( "disabled" ) == null; +} ) ) { + addHandle( booleans, function( elem, name, isXML ) { + var val; + if ( !isXML ) { + return elem[ name ] === true ? name.toLowerCase() : + ( val = elem.getAttributeNode( name ) ) && val.specified ? + val.value : + null; + } + } ); +} + +return Sizzle; + +} )( window ); + + + +jQuery.find = Sizzle; +jQuery.expr = Sizzle.selectors; + +// Deprecated +jQuery.expr[ ":" ] = jQuery.expr.pseudos; +jQuery.uniqueSort = jQuery.unique = Sizzle.uniqueSort; +jQuery.text = Sizzle.getText; +jQuery.isXMLDoc = Sizzle.isXML; +jQuery.contains = Sizzle.contains; +jQuery.escapeSelector = Sizzle.escape; + + + + +var dir = function( elem, dir, until ) { + var matched = [], + truncate = until !== undefined; + + while ( ( elem = elem[ dir ] ) && elem.nodeType !== 9 ) { + if ( elem.nodeType === 1 ) { + if ( truncate && jQuery( elem ).is( until ) ) { + break; + } + matched.push( elem ); + } + } + return matched; +}; + + +var siblings = function( n, elem ) { + var matched = []; + + for ( ; n; n = n.nextSibling ) { + if ( n.nodeType === 1 && n !== elem ) { + matched.push( n ); + } + } + + return matched; +}; + + +var rneedsContext = jQuery.expr.match.needsContext; + + + +function nodeName( elem, name ) { + + return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase(); + +}; +var rsingleTag = ( /^<([a-z][^\/\0>:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i ); + + + +// Implement the identical functionality for filter and not +function winnow( elements, qualifier, not ) { + if ( isFunction( qualifier ) ) { + return jQuery.grep( elements, function( elem, i ) { + return !!qualifier.call( elem, i, elem ) !== not; + } ); + } + + // Single element + if ( qualifier.nodeType ) { + return jQuery.grep( elements, function( elem ) { + return ( elem === qualifier ) !== not; + } ); + } + + // Arraylike of elements (jQuery, arguments, Array) + if ( typeof qualifier !== "string" ) { + return jQuery.grep( elements, function( elem ) { + return ( indexOf.call( qualifier, elem ) > -1 ) !== not; + } ); + } + + // Filtered directly for both simple and complex selectors + return jQuery.filter( qualifier, elements, not ); +} + +jQuery.filter = function( expr, elems, not ) { + var elem = elems[ 0 ]; + + if ( not ) { + expr = ":not(" + expr + ")"; + } + + if ( elems.length === 1 && elem.nodeType === 1 ) { + return jQuery.find.matchesSelector( elem, expr ) ? [ elem ] : []; + } + + return jQuery.find.matches( expr, jQuery.grep( elems, function( elem ) { + return elem.nodeType === 1; + } ) ); +}; + +jQuery.fn.extend( { + find: function( selector ) { + var i, ret, + len = this.length, + self = this; + + if ( typeof selector !== "string" ) { + return this.pushStack( jQuery( selector ).filter( function() { + for ( i = 0; i < len; i++ ) { + if ( jQuery.contains( self[ i ], this ) ) { + return true; + } + } + } ) ); + } + + ret = this.pushStack( [] ); + + for ( i = 0; i < len; i++ ) { + jQuery.find( selector, self[ i ], ret ); + } + + return len > 1 ? jQuery.uniqueSort( ret ) : ret; + }, + filter: function( selector ) { + return this.pushStack( winnow( this, selector || [], false ) ); + }, + not: function( selector ) { + return this.pushStack( winnow( this, selector || [], true ) ); + }, + is: function( selector ) { + return !!winnow( + this, + + // If this is a positional/relative selector, check membership in the returned set + // so $("p:first").is("p:last") won't return true for a doc with two "p". + typeof selector === "string" && rneedsContext.test( selector ) ? + jQuery( selector ) : + selector || [], + false + ).length; + } +} ); + + +// Initialize a jQuery object + + +// A central reference to the root jQuery(document) +var rootjQuery, + + // A simple way to check for HTML strings + // Prioritize #id over to avoid XSS via location.hash (#9521) + // Strict HTML recognition (#11290: must start with <) + // Shortcut simple #id case for speed + rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]+))$/, + + init = jQuery.fn.init = function( selector, context, root ) { + var match, elem; + + // HANDLE: $(""), $(null), $(undefined), $(false) + if ( !selector ) { + return this; + } + + // Method init() accepts an alternate rootjQuery + // so migrate can support jQuery.sub (gh-2101) + root = root || rootjQuery; + + // Handle HTML strings + if ( typeof selector === "string" ) { + if ( selector[ 0 ] === "<" && + selector[ selector.length - 1 ] === ">" && + selector.length >= 3 ) { + + // Assume that strings that start and end with <> are HTML and skip the regex check + match = [ null, selector, null ]; + + } else { + match = rquickExpr.exec( selector ); + } + + // Match html or make sure no context is specified for #id + if ( match && ( match[ 1 ] || !context ) ) { + + // HANDLE: $(html) -> $(array) + if ( match[ 1 ] ) { + context = context instanceof jQuery ? context[ 0 ] : context; + + // Option to run scripts is true for back-compat + // Intentionally let the error be thrown if parseHTML is not present + jQuery.merge( this, jQuery.parseHTML( + match[ 1 ], + context && context.nodeType ? context.ownerDocument || context : document, + true + ) ); + + // HANDLE: $(html, props) + if ( rsingleTag.test( match[ 1 ] ) && jQuery.isPlainObject( context ) ) { + for ( match in context ) { + + // Properties of context are called as methods if possible + if ( isFunction( this[ match ] ) ) { + this[ match ]( context[ match ] ); + + // ...and otherwise set as attributes + } else { + this.attr( match, context[ match ] ); + } + } + } + + return this; + + // HANDLE: $(#id) + } else { + elem = document.getElementById( match[ 2 ] ); + + if ( elem ) { + + // Inject the element directly into the jQuery object + this[ 0 ] = elem; + this.length = 1; + } + return this; + } + + // HANDLE: $(expr, $(...)) + } else if ( !context || context.jquery ) { + return ( context || root ).find( selector ); + + // HANDLE: $(expr, context) + // (which is just equivalent to: $(context).find(expr) + } else { + return this.constructor( context ).find( selector ); + } + + // HANDLE: $(DOMElement) + } else if ( selector.nodeType ) { + this[ 0 ] = selector; + this.length = 1; + return this; + + // HANDLE: $(function) + // Shortcut for document ready + } else if ( isFunction( selector ) ) { + return root.ready !== undefined ? + root.ready( selector ) : + + // Execute immediately if ready is not present + selector( jQuery ); + } + + return jQuery.makeArray( selector, this ); + }; + +// Give the init function the jQuery prototype for later instantiation +init.prototype = jQuery.fn; + +// Initialize central reference +rootjQuery = jQuery( document ); + + +var rparentsprev = /^(?:parents|prev(?:Until|All))/, + + // Methods guaranteed to produce a unique set when starting from a unique set + guaranteedUnique = { + children: true, + contents: true, + next: true, + prev: true + }; + +jQuery.fn.extend( { + has: function( target ) { + var targets = jQuery( target, this ), + l = targets.length; + + return this.filter( function() { + var i = 0; + for ( ; i < l; i++ ) { + if ( jQuery.contains( this, targets[ i ] ) ) { + return true; + } + } + } ); + }, + + closest: function( selectors, context ) { + var cur, + i = 0, + l = this.length, + matched = [], + targets = typeof selectors !== "string" && jQuery( selectors ); + + // Positional selectors never match, since there's no _selection_ context + if ( !rneedsContext.test( selectors ) ) { + for ( ; i < l; i++ ) { + for ( cur = this[ i ]; cur && cur !== context; cur = cur.parentNode ) { + + // Always skip document fragments + if ( cur.nodeType < 11 && ( targets ? + targets.index( cur ) > -1 : + + // Don't pass non-elements to Sizzle + cur.nodeType === 1 && + jQuery.find.matchesSelector( cur, selectors ) ) ) { + + matched.push( cur ); + break; + } + } + } + } + + return this.pushStack( matched.length > 1 ? jQuery.uniqueSort( matched ) : matched ); + }, + + // Determine the position of an element within the set + index: function( elem ) { + + // No argument, return index in parent + if ( !elem ) { + return ( this[ 0 ] && this[ 0 ].parentNode ) ? this.first().prevAll().length : -1; + } + + // Index in selector + if ( typeof elem === "string" ) { + return indexOf.call( jQuery( elem ), this[ 0 ] ); + } + + // Locate the position of the desired element + return indexOf.call( this, + + // If it receives a jQuery object, the first element is used + elem.jquery ? elem[ 0 ] : elem + ); + }, + + add: function( selector, context ) { + return this.pushStack( + jQuery.uniqueSort( + jQuery.merge( this.get(), jQuery( selector, context ) ) + ) + ); + }, + + addBack: function( selector ) { + return this.add( selector == null ? + this.prevObject : this.prevObject.filter( selector ) + ); + } +} ); + +function sibling( cur, dir ) { + while ( ( cur = cur[ dir ] ) && cur.nodeType !== 1 ) {} + return cur; +} + +jQuery.each( { + parent: function( elem ) { + var parent = elem.parentNode; + return parent && parent.nodeType !== 11 ? parent : null; + }, + parents: function( elem ) { + return dir( elem, "parentNode" ); + }, + parentsUntil: function( elem, _i, until ) { + return dir( elem, "parentNode", until ); + }, + next: function( elem ) { + return sibling( elem, "nextSibling" ); + }, + prev: function( elem ) { + return sibling( elem, "previousSibling" ); + }, + nextAll: function( elem ) { + return dir( elem, "nextSibling" ); + }, + prevAll: function( elem ) { + return dir( elem, "previousSibling" ); + }, + nextUntil: function( elem, _i, until ) { + return dir( elem, "nextSibling", until ); + }, + prevUntil: function( elem, _i, until ) { + return dir( elem, "previousSibling", until ); + }, + siblings: function( elem ) { + return siblings( ( elem.parentNode || {} ).firstChild, elem ); + }, + children: function( elem ) { + return siblings( elem.firstChild ); + }, + contents: function( elem ) { + if ( elem.contentDocument != null && + + // Support: IE 11+ + // elements with no `data` attribute has an object + // `contentDocument` with a `null` prototype. + getProto( elem.contentDocument ) ) { + + return elem.contentDocument; + } + + // Support: IE 9 - 11 only, iOS 7 only, Android Browser <=4.3 only + // Treat the template element as a regular one in browsers that + // don't support it. + if ( nodeName( elem, "template" ) ) { + elem = elem.content || elem; + } + + return jQuery.merge( [], elem.childNodes ); + } +}, function( name, fn ) { + jQuery.fn[ name ] = function( until, selector ) { + var matched = jQuery.map( this, fn, until ); + + if ( name.slice( -5 ) !== "Until" ) { + selector = until; + } + + if ( selector && typeof selector === "string" ) { + matched = jQuery.filter( selector, matched ); + } + + if ( this.length > 1 ) { + + // Remove duplicates + if ( !guaranteedUnique[ name ] ) { + jQuery.uniqueSort( matched ); + } + + // Reverse order for parents* and prev-derivatives + if ( rparentsprev.test( name ) ) { + matched.reverse(); + } + } + + return this.pushStack( matched ); + }; +} ); +var rnothtmlwhite = ( /[^\x20\t\r\n\f]+/g ); + + + +// Convert String-formatted options into Object-formatted ones +function createOptions( options ) { + var object = {}; + jQuery.each( options.match( rnothtmlwhite ) || [], function( _, flag ) { + object[ flag ] = true; + } ); + return object; +} + +/* + * Create a callback list using the following parameters: + * + * options: an optional list of space-separated options that will change how + * the callback list behaves or a more traditional option object + * + * By default a callback list will act like an event callback list and can be + * "fired" multiple times. + * + * Possible options: + * + * once: will ensure the callback list can only be fired once (like a Deferred) + * + * memory: will keep track of previous values and will call any callback added + * after the list has been fired right away with the latest "memorized" + * values (like a Deferred) + * + * unique: will ensure a callback can only be added once (no duplicate in the list) + * + * stopOnFalse: interrupt callings when a callback returns false + * + */ +jQuery.Callbacks = function( options ) { + + // Convert options from String-formatted to Object-formatted if needed + // (we check in cache first) + options = typeof options === "string" ? + createOptions( options ) : + jQuery.extend( {}, options ); + + var // Flag to know if list is currently firing + firing, + + // Last fire value for non-forgettable lists + memory, + + // Flag to know if list was already fired + fired, + + // Flag to prevent firing + locked, + + // Actual callback list + list = [], + + // Queue of execution data for repeatable lists + queue = [], + + // Index of currently firing callback (modified by add/remove as needed) + firingIndex = -1, + + // Fire callbacks + fire = function() { + + // Enforce single-firing + locked = locked || options.once; + + // Execute callbacks for all pending executions, + // respecting firingIndex overrides and runtime changes + fired = firing = true; + for ( ; queue.length; firingIndex = -1 ) { + memory = queue.shift(); + while ( ++firingIndex < list.length ) { + + // Run callback and check for early termination + if ( list[ firingIndex ].apply( memory[ 0 ], memory[ 1 ] ) === false && + options.stopOnFalse ) { + + // Jump to end and forget the data so .add doesn't re-fire + firingIndex = list.length; + memory = false; + } + } + } + + // Forget the data if we're done with it + if ( !options.memory ) { + memory = false; + } + + firing = false; + + // Clean up if we're done firing for good + if ( locked ) { + + // Keep an empty list if we have data for future add calls + if ( memory ) { + list = []; + + // Otherwise, this object is spent + } else { + list = ""; + } + } + }, + + // Actual Callbacks object + self = { + + // Add a callback or a collection of callbacks to the list + add: function() { + if ( list ) { + + // If we have memory from a past run, we should fire after adding + if ( memory && !firing ) { + firingIndex = list.length - 1; + queue.push( memory ); + } + + ( function add( args ) { + jQuery.each( args, function( _, arg ) { + if ( isFunction( arg ) ) { + if ( !options.unique || !self.has( arg ) ) { + list.push( arg ); + } + } else if ( arg && arg.length && toType( arg ) !== "string" ) { + + // Inspect recursively + add( arg ); + } + } ); + } )( arguments ); + + if ( memory && !firing ) { + fire(); + } + } + return this; + }, + + // Remove a callback from the list + remove: function() { + jQuery.each( arguments, function( _, arg ) { + var index; + while ( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) { + list.splice( index, 1 ); + + // Handle firing indexes + if ( index <= firingIndex ) { + firingIndex--; + } + } + } ); + return this; + }, + + // Check if a given callback is in the list. + // If no argument is given, return whether or not list has callbacks attached. + has: function( fn ) { + return fn ? + jQuery.inArray( fn, list ) > -1 : + list.length > 0; + }, + + // Remove all callbacks from the list + empty: function() { + if ( list ) { + list = []; + } + return this; + }, + + // Disable .fire and .add + // Abort any current/pending executions + // Clear all callbacks and values + disable: function() { + locked = queue = []; + list = memory = ""; + return this; + }, + disabled: function() { + return !list; + }, + + // Disable .fire + // Also disable .add unless we have memory (since it would have no effect) + // Abort any pending executions + lock: function() { + locked = queue = []; + if ( !memory && !firing ) { + list = memory = ""; + } + return this; + }, + locked: function() { + return !!locked; + }, + + // Call all callbacks with the given context and arguments + fireWith: function( context, args ) { + if ( !locked ) { + args = args || []; + args = [ context, args.slice ? args.slice() : args ]; + queue.push( args ); + if ( !firing ) { + fire(); + } + } + return this; + }, + + // Call all the callbacks with the given arguments + fire: function() { + self.fireWith( this, arguments ); + return this; + }, + + // To know if the callbacks have already been called at least once + fired: function() { + return !!fired; + } + }; + + return self; +}; + + +function Identity( v ) { + return v; +} +function Thrower( ex ) { + throw ex; +} + +function adoptValue( value, resolve, reject, noValue ) { + var method; + + try { + + // Check for promise aspect first to privilege synchronous behavior + if ( value && isFunction( ( method = value.promise ) ) ) { + method.call( value ).done( resolve ).fail( reject ); + + // Other thenables + } else if ( value && isFunction( ( method = value.then ) ) ) { + method.call( value, resolve, reject ); + + // Other non-thenables + } else { + + // Control `resolve` arguments by letting Array#slice cast boolean `noValue` to integer: + // * false: [ value ].slice( 0 ) => resolve( value ) + // * true: [ value ].slice( 1 ) => resolve() + resolve.apply( undefined, [ value ].slice( noValue ) ); + } + + // For Promises/A+, convert exceptions into rejections + // Since jQuery.when doesn't unwrap thenables, we can skip the extra checks appearing in + // Deferred#then to conditionally suppress rejection. + } catch ( value ) { + + // Support: Android 4.0 only + // Strict mode functions invoked without .call/.apply get global-object context + reject.apply( undefined, [ value ] ); + } +} + +jQuery.extend( { + + Deferred: function( func ) { + var tuples = [ + + // action, add listener, callbacks, + // ... .then handlers, argument index, [final state] + [ "notify", "progress", jQuery.Callbacks( "memory" ), + jQuery.Callbacks( "memory" ), 2 ], + [ "resolve", "done", jQuery.Callbacks( "once memory" ), + jQuery.Callbacks( "once memory" ), 0, "resolved" ], + [ "reject", "fail", jQuery.Callbacks( "once memory" ), + jQuery.Callbacks( "once memory" ), 1, "rejected" ] + ], + state = "pending", + promise = { + state: function() { + return state; + }, + always: function() { + deferred.done( arguments ).fail( arguments ); + return this; + }, + "catch": function( fn ) { + return promise.then( null, fn ); + }, + + // Keep pipe for back-compat + pipe: function( /* fnDone, fnFail, fnProgress */ ) { + var fns = arguments; + + return jQuery.Deferred( function( newDefer ) { + jQuery.each( tuples, function( _i, tuple ) { + + // Map tuples (progress, done, fail) to arguments (done, fail, progress) + var fn = isFunction( fns[ tuple[ 4 ] ] ) && fns[ tuple[ 4 ] ]; + + // deferred.progress(function() { bind to newDefer or newDefer.notify }) + // deferred.done(function() { bind to newDefer or newDefer.resolve }) + // deferred.fail(function() { bind to newDefer or newDefer.reject }) + deferred[ tuple[ 1 ] ]( function() { + var returned = fn && fn.apply( this, arguments ); + if ( returned && isFunction( returned.promise ) ) { + returned.promise() + .progress( newDefer.notify ) + .done( newDefer.resolve ) + .fail( newDefer.reject ); + } else { + newDefer[ tuple[ 0 ] + "With" ]( + this, + fn ? [ returned ] : arguments + ); + } + } ); + } ); + fns = null; + } ).promise(); + }, + then: function( onFulfilled, onRejected, onProgress ) { + var maxDepth = 0; + function resolve( depth, deferred, handler, special ) { + return function() { + var that = this, + args = arguments, + mightThrow = function() { + var returned, then; + + // Support: Promises/A+ section 2.3.3.3.3 + // https://promisesaplus.com/#point-59 + // Ignore double-resolution attempts + if ( depth < maxDepth ) { + return; + } + + returned = handler.apply( that, args ); + + // Support: Promises/A+ section 2.3.1 + // https://promisesaplus.com/#point-48 + if ( returned === deferred.promise() ) { + throw new TypeError( "Thenable self-resolution" ); + } + + // Support: Promises/A+ sections 2.3.3.1, 3.5 + // https://promisesaplus.com/#point-54 + // https://promisesaplus.com/#point-75 + // Retrieve `then` only once + then = returned && + + // Support: Promises/A+ section 2.3.4 + // https://promisesaplus.com/#point-64 + // Only check objects and functions for thenability + ( typeof returned === "object" || + typeof returned === "function" ) && + returned.then; + + // Handle a returned thenable + if ( isFunction( then ) ) { + + // Special processors (notify) just wait for resolution + if ( special ) { + then.call( + returned, + resolve( maxDepth, deferred, Identity, special ), + resolve( maxDepth, deferred, Thrower, special ) + ); + + // Normal processors (resolve) also hook into progress + } else { + + // ...and disregard older resolution values + maxDepth++; + + then.call( + returned, + resolve( maxDepth, deferred, Identity, special ), + resolve( maxDepth, deferred, Thrower, special ), + resolve( maxDepth, deferred, Identity, + deferred.notifyWith ) + ); + } + + // Handle all other returned values + } else { + + // Only substitute handlers pass on context + // and multiple values (non-spec behavior) + if ( handler !== Identity ) { + that = undefined; + args = [ returned ]; + } + + // Process the value(s) + // Default process is resolve + ( special || deferred.resolveWith )( that, args ); + } + }, + + // Only normal processors (resolve) catch and reject exceptions + process = special ? + mightThrow : + function() { + try { + mightThrow(); + } catch ( e ) { + + if ( jQuery.Deferred.exceptionHook ) { + jQuery.Deferred.exceptionHook( e, + process.stackTrace ); + } + + // Support: Promises/A+ section 2.3.3.3.4.1 + // https://promisesaplus.com/#point-61 + // Ignore post-resolution exceptions + if ( depth + 1 >= maxDepth ) { + + // Only substitute handlers pass on context + // and multiple values (non-spec behavior) + if ( handler !== Thrower ) { + that = undefined; + args = [ e ]; + } + + deferred.rejectWith( that, args ); + } + } + }; + + // Support: Promises/A+ section 2.3.3.3.1 + // https://promisesaplus.com/#point-57 + // Re-resolve promises immediately to dodge false rejection from + // subsequent errors + if ( depth ) { + process(); + } else { + + // Call an optional hook to record the stack, in case of exception + // since it's otherwise lost when execution goes async + if ( jQuery.Deferred.getStackHook ) { + process.stackTrace = jQuery.Deferred.getStackHook(); + } + window.setTimeout( process ); + } + }; + } + + return jQuery.Deferred( function( newDefer ) { + + // progress_handlers.add( ... ) + tuples[ 0 ][ 3 ].add( + resolve( + 0, + newDefer, + isFunction( onProgress ) ? + onProgress : + Identity, + newDefer.notifyWith + ) + ); + + // fulfilled_handlers.add( ... ) + tuples[ 1 ][ 3 ].add( + resolve( + 0, + newDefer, + isFunction( onFulfilled ) ? + onFulfilled : + Identity + ) + ); + + // rejected_handlers.add( ... ) + tuples[ 2 ][ 3 ].add( + resolve( + 0, + newDefer, + isFunction( onRejected ) ? + onRejected : + Thrower + ) + ); + } ).promise(); + }, + + // Get a promise for this deferred + // If obj is provided, the promise aspect is added to the object + promise: function( obj ) { + return obj != null ? jQuery.extend( obj, promise ) : promise; + } + }, + deferred = {}; + + // Add list-specific methods + jQuery.each( tuples, function( i, tuple ) { + var list = tuple[ 2 ], + stateString = tuple[ 5 ]; + + // promise.progress = list.add + // promise.done = list.add + // promise.fail = list.add + promise[ tuple[ 1 ] ] = list.add; + + // Handle state + if ( stateString ) { + list.add( + function() { + + // state = "resolved" (i.e., fulfilled) + // state = "rejected" + state = stateString; + }, + + // rejected_callbacks.disable + // fulfilled_callbacks.disable + tuples[ 3 - i ][ 2 ].disable, + + // rejected_handlers.disable + // fulfilled_handlers.disable + tuples[ 3 - i ][ 3 ].disable, + + // progress_callbacks.lock + tuples[ 0 ][ 2 ].lock, + + // progress_handlers.lock + tuples[ 0 ][ 3 ].lock + ); + } + + // progress_handlers.fire + // fulfilled_handlers.fire + // rejected_handlers.fire + list.add( tuple[ 3 ].fire ); + + // deferred.notify = function() { deferred.notifyWith(...) } + // deferred.resolve = function() { deferred.resolveWith(...) } + // deferred.reject = function() { deferred.rejectWith(...) } + deferred[ tuple[ 0 ] ] = function() { + deferred[ tuple[ 0 ] + "With" ]( this === deferred ? undefined : this, arguments ); + return this; + }; + + // deferred.notifyWith = list.fireWith + // deferred.resolveWith = list.fireWith + // deferred.rejectWith = list.fireWith + deferred[ tuple[ 0 ] + "With" ] = list.fireWith; + } ); + + // Make the deferred a promise + promise.promise( deferred ); + + // Call given func if any + if ( func ) { + func.call( deferred, deferred ); + } + + // All done! + return deferred; + }, + + // Deferred helper + when: function( singleValue ) { + var + + // count of uncompleted subordinates + remaining = arguments.length, + + // count of unprocessed arguments + i = remaining, + + // subordinate fulfillment data + resolveContexts = Array( i ), + resolveValues = slice.call( arguments ), + + // the master Deferred + master = jQuery.Deferred(), + + // subordinate callback factory + updateFunc = function( i ) { + return function( value ) { + resolveContexts[ i ] = this; + resolveValues[ i ] = arguments.length > 1 ? slice.call( arguments ) : value; + if ( !( --remaining ) ) { + master.resolveWith( resolveContexts, resolveValues ); + } + }; + }; + + // Single- and empty arguments are adopted like Promise.resolve + if ( remaining <= 1 ) { + adoptValue( singleValue, master.done( updateFunc( i ) ).resolve, master.reject, + !remaining ); + + // Use .then() to unwrap secondary thenables (cf. gh-3000) + if ( master.state() === "pending" || + isFunction( resolveValues[ i ] && resolveValues[ i ].then ) ) { + + return master.then(); + } + } + + // Multiple arguments are aggregated like Promise.all array elements + while ( i-- ) { + adoptValue( resolveValues[ i ], updateFunc( i ), master.reject ); + } + + return master.promise(); + } +} ); + + +// These usually indicate a programmer mistake during development, +// warn about them ASAP rather than swallowing them by default. +var rerrorNames = /^(Eval|Internal|Range|Reference|Syntax|Type|URI)Error$/; + +jQuery.Deferred.exceptionHook = function( error, stack ) { + + // Support: IE 8 - 9 only + // Console exists when dev tools are open, which can happen at any time + if ( window.console && window.console.warn && error && rerrorNames.test( error.name ) ) { + window.console.warn( "jQuery.Deferred exception: " + error.message, error.stack, stack ); + } +}; + + + + +jQuery.readyException = function( error ) { + window.setTimeout( function() { + throw error; + } ); +}; + + + + +// The deferred used on DOM ready +var readyList = jQuery.Deferred(); + +jQuery.fn.ready = function( fn ) { + + readyList + .then( fn ) + + // Wrap jQuery.readyException in a function so that the lookup + // happens at the time of error handling instead of callback + // registration. + .catch( function( error ) { + jQuery.readyException( error ); + } ); + + return this; +}; + +jQuery.extend( { + + // Is the DOM ready to be used? Set to true once it occurs. + isReady: false, + + // A counter to track how many items to wait for before + // the ready event fires. See #6781 + readyWait: 1, + + // Handle when the DOM is ready + ready: function( wait ) { + + // Abort if there are pending holds or we're already ready + if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) { + return; + } + + // Remember that the DOM is ready + jQuery.isReady = true; + + // If a normal DOM Ready event fired, decrement, and wait if need be + if ( wait !== true && --jQuery.readyWait > 0 ) { + return; + } + + // If there are functions bound, to execute + readyList.resolveWith( document, [ jQuery ] ); + } +} ); + +jQuery.ready.then = readyList.then; + +// The ready event handler and self cleanup method +function completed() { + document.removeEventListener( "DOMContentLoaded", completed ); + window.removeEventListener( "load", completed ); + jQuery.ready(); +} + +// Catch cases where $(document).ready() is called +// after the browser event has already occurred. +// Support: IE <=9 - 10 only +// Older IE sometimes signals "interactive" too soon +if ( document.readyState === "complete" || + ( document.readyState !== "loading" && !document.documentElement.doScroll ) ) { + + // Handle it asynchronously to allow scripts the opportunity to delay ready + window.setTimeout( jQuery.ready ); + +} else { + + // Use the handy event callback + document.addEventListener( "DOMContentLoaded", completed ); + + // A fallback to window.onload, that will always work + window.addEventListener( "load", completed ); +} + + + + +// Multifunctional method to get and set values of a collection +// The value/s can optionally be executed if it's a function +var access = function( elems, fn, key, value, chainable, emptyGet, raw ) { + var i = 0, + len = elems.length, + bulk = key == null; + + // Sets many values + if ( toType( key ) === "object" ) { + chainable = true; + for ( i in key ) { + access( elems, fn, i, key[ i ], true, emptyGet, raw ); + } + + // Sets one value + } else if ( value !== undefined ) { + chainable = true; + + if ( !isFunction( value ) ) { + raw = true; + } + + if ( bulk ) { + + // Bulk operations run against the entire set + if ( raw ) { + fn.call( elems, value ); + fn = null; + + // ...except when executing function values + } else { + bulk = fn; + fn = function( elem, _key, value ) { + return bulk.call( jQuery( elem ), value ); + }; + } + } + + if ( fn ) { + for ( ; i < len; i++ ) { + fn( + elems[ i ], key, raw ? + value : + value.call( elems[ i ], i, fn( elems[ i ], key ) ) + ); + } + } + } + + if ( chainable ) { + return elems; + } + + // Gets + if ( bulk ) { + return fn.call( elems ); + } + + return len ? fn( elems[ 0 ], key ) : emptyGet; +}; + + +// Matches dashed string for camelizing +var rmsPrefix = /^-ms-/, + rdashAlpha = /-([a-z])/g; + +// Used by camelCase as callback to replace() +function fcamelCase( _all, letter ) { + return letter.toUpperCase(); +} + +// Convert dashed to camelCase; used by the css and data modules +// Support: IE <=9 - 11, Edge 12 - 15 +// Microsoft forgot to hump their vendor prefix (#9572) +function camelCase( string ) { + return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase ); +} +var acceptData = function( owner ) { + + // Accepts only: + // - Node + // - Node.ELEMENT_NODE + // - Node.DOCUMENT_NODE + // - Object + // - Any + return owner.nodeType === 1 || owner.nodeType === 9 || !( +owner.nodeType ); +}; + + + + +function Data() { + this.expando = jQuery.expando + Data.uid++; +} + +Data.uid = 1; + +Data.prototype = { + + cache: function( owner ) { + + // Check if the owner object already has a cache + var value = owner[ this.expando ]; + + // If not, create one + if ( !value ) { + value = {}; + + // We can accept data for non-element nodes in modern browsers, + // but we should not, see #8335. + // Always return an empty object. + if ( acceptData( owner ) ) { + + // If it is a node unlikely to be stringify-ed or looped over + // use plain assignment + if ( owner.nodeType ) { + owner[ this.expando ] = value; + + // Otherwise secure it in a non-enumerable property + // configurable must be true to allow the property to be + // deleted when data is removed + } else { + Object.defineProperty( owner, this.expando, { + value: value, + configurable: true + } ); + } + } + } + + return value; + }, + set: function( owner, data, value ) { + var prop, + cache = this.cache( owner ); + + // Handle: [ owner, key, value ] args + // Always use camelCase key (gh-2257) + if ( typeof data === "string" ) { + cache[ camelCase( data ) ] = value; + + // Handle: [ owner, { properties } ] args + } else { + + // Copy the properties one-by-one to the cache object + for ( prop in data ) { + cache[ camelCase( prop ) ] = data[ prop ]; + } + } + return cache; + }, + get: function( owner, key ) { + return key === undefined ? + this.cache( owner ) : + + // Always use camelCase key (gh-2257) + owner[ this.expando ] && owner[ this.expando ][ camelCase( key ) ]; + }, + access: function( owner, key, value ) { + + // In cases where either: + // + // 1. No key was specified + // 2. A string key was specified, but no value provided + // + // Take the "read" path and allow the get method to determine + // which value to return, respectively either: + // + // 1. The entire cache object + // 2. The data stored at the key + // + if ( key === undefined || + ( ( key && typeof key === "string" ) && value === undefined ) ) { + + return this.get( owner, key ); + } + + // When the key is not a string, or both a key and value + // are specified, set or extend (existing objects) with either: + // + // 1. An object of properties + // 2. A key and value + // + this.set( owner, key, value ); + + // Since the "set" path can have two possible entry points + // return the expected data based on which path was taken[*] + return value !== undefined ? value : key; + }, + remove: function( owner, key ) { + var i, + cache = owner[ this.expando ]; + + if ( cache === undefined ) { + return; + } + + if ( key !== undefined ) { + + // Support array or space separated string of keys + if ( Array.isArray( key ) ) { + + // If key is an array of keys... + // We always set camelCase keys, so remove that. + key = key.map( camelCase ); + } else { + key = camelCase( key ); + + // If a key with the spaces exists, use it. + // Otherwise, create an array by matching non-whitespace + key = key in cache ? + [ key ] : + ( key.match( rnothtmlwhite ) || [] ); + } + + i = key.length; + + while ( i-- ) { + delete cache[ key[ i ] ]; + } + } + + // Remove the expando if there's no more data + if ( key === undefined || jQuery.isEmptyObject( cache ) ) { + + // Support: Chrome <=35 - 45 + // Webkit & Blink performance suffers when deleting properties + // from DOM nodes, so set to undefined instead + // https://bugs.chromium.org/p/chromium/issues/detail?id=378607 (bug restricted) + if ( owner.nodeType ) { + owner[ this.expando ] = undefined; + } else { + delete owner[ this.expando ]; + } + } + }, + hasData: function( owner ) { + var cache = owner[ this.expando ]; + return cache !== undefined && !jQuery.isEmptyObject( cache ); + } +}; +var dataPriv = new Data(); + +var dataUser = new Data(); + + + +// Implementation Summary +// +// 1. Enforce API surface and semantic compatibility with 1.9.x branch +// 2. Improve the module's maintainability by reducing the storage +// paths to a single mechanism. +// 3. Use the same single mechanism to support "private" and "user" data. +// 4. _Never_ expose "private" data to user code (TODO: Drop _data, _removeData) +// 5. Avoid exposing implementation details on user objects (eg. expando properties) +// 6. Provide a clear path for implementation upgrade to WeakMap in 2014 + +var rbrace = /^(?:\{[\w\W]*\}|\[[\w\W]*\])$/, + rmultiDash = /[A-Z]/g; + +function getData( data ) { + if ( data === "true" ) { + return true; + } + + if ( data === "false" ) { + return false; + } + + if ( data === "null" ) { + return null; + } + + // Only convert to a number if it doesn't change the string + if ( data === +data + "" ) { + return +data; + } + + if ( rbrace.test( data ) ) { + return JSON.parse( data ); + } + + return data; +} + +function dataAttr( elem, key, data ) { + var name; + + // If nothing was found internally, try to fetch any + // data from the HTML5 data-* attribute + if ( data === undefined && elem.nodeType === 1 ) { + name = "data-" + key.replace( rmultiDash, "-$&" ).toLowerCase(); + data = elem.getAttribute( name ); + + if ( typeof data === "string" ) { + try { + data = getData( data ); + } catch ( e ) {} + + // Make sure we set the data so it isn't changed later + dataUser.set( elem, key, data ); + } else { + data = undefined; + } + } + return data; +} + +jQuery.extend( { + hasData: function( elem ) { + return dataUser.hasData( elem ) || dataPriv.hasData( elem ); + }, + + data: function( elem, name, data ) { + return dataUser.access( elem, name, data ); + }, + + removeData: function( elem, name ) { + dataUser.remove( elem, name ); + }, + + // TODO: Now that all calls to _data and _removeData have been replaced + // with direct calls to dataPriv methods, these can be deprecated. + _data: function( elem, name, data ) { + return dataPriv.access( elem, name, data ); + }, + + _removeData: function( elem, name ) { + dataPriv.remove( elem, name ); + } +} ); + +jQuery.fn.extend( { + data: function( key, value ) { + var i, name, data, + elem = this[ 0 ], + attrs = elem && elem.attributes; + + // Gets all values + if ( key === undefined ) { + if ( this.length ) { + data = dataUser.get( elem ); + + if ( elem.nodeType === 1 && !dataPriv.get( elem, "hasDataAttrs" ) ) { + i = attrs.length; + while ( i-- ) { + + // Support: IE 11 only + // The attrs elements can be null (#14894) + if ( attrs[ i ] ) { + name = attrs[ i ].name; + if ( name.indexOf( "data-" ) === 0 ) { + name = camelCase( name.slice( 5 ) ); + dataAttr( elem, name, data[ name ] ); + } + } + } + dataPriv.set( elem, "hasDataAttrs", true ); + } + } + + return data; + } + + // Sets multiple values + if ( typeof key === "object" ) { + return this.each( function() { + dataUser.set( this, key ); + } ); + } + + return access( this, function( value ) { + var data; + + // The calling jQuery object (element matches) is not empty + // (and therefore has an element appears at this[ 0 ]) and the + // `value` parameter was not undefined. An empty jQuery object + // will result in `undefined` for elem = this[ 0 ] which will + // throw an exception if an attempt to read a data cache is made. + if ( elem && value === undefined ) { + + // Attempt to get data from the cache + // The key will always be camelCased in Data + data = dataUser.get( elem, key ); + if ( data !== undefined ) { + return data; + } + + // Attempt to "discover" the data in + // HTML5 custom data-* attrs + data = dataAttr( elem, key ); + if ( data !== undefined ) { + return data; + } + + // We tried really hard, but the data doesn't exist. + return; + } + + // Set the data... + this.each( function() { + + // We always store the camelCased key + dataUser.set( this, key, value ); + } ); + }, null, value, arguments.length > 1, null, true ); + }, + + removeData: function( key ) { + return this.each( function() { + dataUser.remove( this, key ); + } ); + } +} ); + + +jQuery.extend( { + queue: function( elem, type, data ) { + var queue; + + if ( elem ) { + type = ( type || "fx" ) + "queue"; + queue = dataPriv.get( elem, type ); + + // Speed up dequeue by getting out quickly if this is just a lookup + if ( data ) { + if ( !queue || Array.isArray( data ) ) { + queue = dataPriv.access( elem, type, jQuery.makeArray( data ) ); + } else { + queue.push( data ); + } + } + return queue || []; + } + }, + + dequeue: function( elem, type ) { + type = type || "fx"; + + var queue = jQuery.queue( elem, type ), + startLength = queue.length, + fn = queue.shift(), + hooks = jQuery._queueHooks( elem, type ), + next = function() { + jQuery.dequeue( elem, type ); + }; + + // If the fx queue is dequeued, always remove the progress sentinel + if ( fn === "inprogress" ) { + fn = queue.shift(); + startLength--; + } + + if ( fn ) { + + // Add a progress sentinel to prevent the fx queue from being + // automatically dequeued + if ( type === "fx" ) { + queue.unshift( "inprogress" ); + } + + // Clear up the last queue stop function + delete hooks.stop; + fn.call( elem, next, hooks ); + } + + if ( !startLength && hooks ) { + hooks.empty.fire(); + } + }, + + // Not public - generate a queueHooks object, or return the current one + _queueHooks: function( elem, type ) { + var key = type + "queueHooks"; + return dataPriv.get( elem, key ) || dataPriv.access( elem, key, { + empty: jQuery.Callbacks( "once memory" ).add( function() { + dataPriv.remove( elem, [ type + "queue", key ] ); + } ) + } ); + } +} ); + +jQuery.fn.extend( { + queue: function( type, data ) { + var setter = 2; + + if ( typeof type !== "string" ) { + data = type; + type = "fx"; + setter--; + } + + if ( arguments.length < setter ) { + return jQuery.queue( this[ 0 ], type ); + } + + return data === undefined ? + this : + this.each( function() { + var queue = jQuery.queue( this, type, data ); + + // Ensure a hooks for this queue + jQuery._queueHooks( this, type ); + + if ( type === "fx" && queue[ 0 ] !== "inprogress" ) { + jQuery.dequeue( this, type ); + } + } ); + }, + dequeue: function( type ) { + return this.each( function() { + jQuery.dequeue( this, type ); + } ); + }, + clearQueue: function( type ) { + return this.queue( type || "fx", [] ); + }, + + // Get a promise resolved when queues of a certain type + // are emptied (fx is the type by default) + promise: function( type, obj ) { + var tmp, + count = 1, + defer = jQuery.Deferred(), + elements = this, + i = this.length, + resolve = function() { + if ( !( --count ) ) { + defer.resolveWith( elements, [ elements ] ); + } + }; + + if ( typeof type !== "string" ) { + obj = type; + type = undefined; + } + type = type || "fx"; + + while ( i-- ) { + tmp = dataPriv.get( elements[ i ], type + "queueHooks" ); + if ( tmp && tmp.empty ) { + count++; + tmp.empty.add( resolve ); + } + } + resolve(); + return defer.promise( obj ); + } +} ); +var pnum = ( /[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/ ).source; + +var rcssNum = new RegExp( "^(?:([+-])=|)(" + pnum + ")([a-z%]*)$", "i" ); + + +var cssExpand = [ "Top", "Right", "Bottom", "Left" ]; + +var documentElement = document.documentElement; + + + + var isAttached = function( elem ) { + return jQuery.contains( elem.ownerDocument, elem ); + }, + composed = { composed: true }; + + // Support: IE 9 - 11+, Edge 12 - 18+, iOS 10.0 - 10.2 only + // Check attachment across shadow DOM boundaries when possible (gh-3504) + // Support: iOS 10.0-10.2 only + // Early iOS 10 versions support `attachShadow` but not `getRootNode`, + // leading to errors. We need to check for `getRootNode`. + if ( documentElement.getRootNode ) { + isAttached = function( elem ) { + return jQuery.contains( elem.ownerDocument, elem ) || + elem.getRootNode( composed ) === elem.ownerDocument; + }; + } +var isHiddenWithinTree = function( elem, el ) { + + // isHiddenWithinTree might be called from jQuery#filter function; + // in that case, element will be second argument + elem = el || elem; + + // Inline style trumps all + return elem.style.display === "none" || + elem.style.display === "" && + + // Otherwise, check computed style + // Support: Firefox <=43 - 45 + // Disconnected elements can have computed display: none, so first confirm that elem is + // in the document. + isAttached( elem ) && + + jQuery.css( elem, "display" ) === "none"; + }; + + + +function adjustCSS( elem, prop, valueParts, tween ) { + var adjusted, scale, + maxIterations = 20, + currentValue = tween ? + function() { + return tween.cur(); + } : + function() { + return jQuery.css( elem, prop, "" ); + }, + initial = currentValue(), + unit = valueParts && valueParts[ 3 ] || ( jQuery.cssNumber[ prop ] ? "" : "px" ), + + // Starting value computation is required for potential unit mismatches + initialInUnit = elem.nodeType && + ( jQuery.cssNumber[ prop ] || unit !== "px" && +initial ) && + rcssNum.exec( jQuery.css( elem, prop ) ); + + if ( initialInUnit && initialInUnit[ 3 ] !== unit ) { + + // Support: Firefox <=54 + // Halve the iteration target value to prevent interference from CSS upper bounds (gh-2144) + initial = initial / 2; + + // Trust units reported by jQuery.css + unit = unit || initialInUnit[ 3 ]; + + // Iteratively approximate from a nonzero starting point + initialInUnit = +initial || 1; + + while ( maxIterations-- ) { + + // Evaluate and update our best guess (doubling guesses that zero out). + // Finish if the scale equals or crosses 1 (making the old*new product non-positive). + jQuery.style( elem, prop, initialInUnit + unit ); + if ( ( 1 - scale ) * ( 1 - ( scale = currentValue() / initial || 0.5 ) ) <= 0 ) { + maxIterations = 0; + } + initialInUnit = initialInUnit / scale; + + } + + initialInUnit = initialInUnit * 2; + jQuery.style( elem, prop, initialInUnit + unit ); + + // Make sure we update the tween properties later on + valueParts = valueParts || []; + } + + if ( valueParts ) { + initialInUnit = +initialInUnit || +initial || 0; + + // Apply relative offset (+=/-=) if specified + adjusted = valueParts[ 1 ] ? + initialInUnit + ( valueParts[ 1 ] + 1 ) * valueParts[ 2 ] : + +valueParts[ 2 ]; + if ( tween ) { + tween.unit = unit; + tween.start = initialInUnit; + tween.end = adjusted; + } + } + return adjusted; +} + + +var defaultDisplayMap = {}; + +function getDefaultDisplay( elem ) { + var temp, + doc = elem.ownerDocument, + nodeName = elem.nodeName, + display = defaultDisplayMap[ nodeName ]; + + if ( display ) { + return display; + } + + temp = doc.body.appendChild( doc.createElement( nodeName ) ); + display = jQuery.css( temp, "display" ); + + temp.parentNode.removeChild( temp ); + + if ( display === "none" ) { + display = "block"; + } + defaultDisplayMap[ nodeName ] = display; + + return display; +} + +function showHide( elements, show ) { + var display, elem, + values = [], + index = 0, + length = elements.length; + + // Determine new display value for elements that need to change + for ( ; index < length; index++ ) { + elem = elements[ index ]; + if ( !elem.style ) { + continue; + } + + display = elem.style.display; + if ( show ) { + + // Since we force visibility upon cascade-hidden elements, an immediate (and slow) + // check is required in this first loop unless we have a nonempty display value (either + // inline or about-to-be-restored) + if ( display === "none" ) { + values[ index ] = dataPriv.get( elem, "display" ) || null; + if ( !values[ index ] ) { + elem.style.display = ""; + } + } + if ( elem.style.display === "" && isHiddenWithinTree( elem ) ) { + values[ index ] = getDefaultDisplay( elem ); + } + } else { + if ( display !== "none" ) { + values[ index ] = "none"; + + // Remember what we're overwriting + dataPriv.set( elem, "display", display ); + } + } + } + + // Set the display of the elements in a second loop to avoid constant reflow + for ( index = 0; index < length; index++ ) { + if ( values[ index ] != null ) { + elements[ index ].style.display = values[ index ]; + } + } + + return elements; +} + +jQuery.fn.extend( { + show: function() { + return showHide( this, true ); + }, + hide: function() { + return showHide( this ); + }, + toggle: function( state ) { + if ( typeof state === "boolean" ) { + return state ? this.show() : this.hide(); + } + + return this.each( function() { + if ( isHiddenWithinTree( this ) ) { + jQuery( this ).show(); + } else { + jQuery( this ).hide(); + } + } ); + } +} ); +var rcheckableType = ( /^(?:checkbox|radio)$/i ); + +var rtagName = ( /<([a-z][^\/\0>\x20\t\r\n\f]*)/i ); + +var rscriptType = ( /^$|^module$|\/(?:java|ecma)script/i ); + + + +( function() { + var fragment = document.createDocumentFragment(), + div = fragment.appendChild( document.createElement( "div" ) ), + input = document.createElement( "input" ); + + // Support: Android 4.0 - 4.3 only + // Check state lost if the name is set (#11217) + // Support: Windows Web Apps (WWA) + // `name` and `type` must use .setAttribute for WWA (#14901) + input.setAttribute( "type", "radio" ); + input.setAttribute( "checked", "checked" ); + input.setAttribute( "name", "t" ); + + div.appendChild( input ); + + // Support: Android <=4.1 only + // Older WebKit doesn't clone checked state correctly in fragments + support.checkClone = div.cloneNode( true ).cloneNode( true ).lastChild.checked; + + // Support: IE <=11 only + // Make sure textarea (and checkbox) defaultValue is properly cloned + div.innerHTML = ""; + support.noCloneChecked = !!div.cloneNode( true ).lastChild.defaultValue; + + // Support: IE <=9 only + // IE <=9 replaces "; + support.option = !!div.lastChild; +} )(); + + +// We have to close these tags to support XHTML (#13200) +var wrapMap = { + + // XHTML parsers do not magically insert elements in the + // same way that tag soup parsers do. So we cannot shorten + // this by omitting or other required elements. + thead: [ 1, "", "
" ], + col: [ 2, "", "
" ], + tr: [ 2, "", "
" ], + td: [ 3, "", "
" ], + + _default: [ 0, "", "" ] +}; + +wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; +wrapMap.th = wrapMap.td; + +// Support: IE <=9 only +if ( !support.option ) { + wrapMap.optgroup = wrapMap.option = [ 1, "" ]; +} + + +function getAll( context, tag ) { + + // Support: IE <=9 - 11 only + // Use typeof to avoid zero-argument method invocation on host objects (#15151) + var ret; + + if ( typeof context.getElementsByTagName !== "undefined" ) { + ret = context.getElementsByTagName( tag || "*" ); + + } else if ( typeof context.querySelectorAll !== "undefined" ) { + ret = context.querySelectorAll( tag || "*" ); + + } else { + ret = []; + } + + if ( tag === undefined || tag && nodeName( context, tag ) ) { + return jQuery.merge( [ context ], ret ); + } + + return ret; +} + + +// Mark scripts as having already been evaluated +function setGlobalEval( elems, refElements ) { + var i = 0, + l = elems.length; + + for ( ; i < l; i++ ) { + dataPriv.set( + elems[ i ], + "globalEval", + !refElements || dataPriv.get( refElements[ i ], "globalEval" ) + ); + } +} + + +var rhtml = /<|&#?\w+;/; + +function buildFragment( elems, context, scripts, selection, ignored ) { + var elem, tmp, tag, wrap, attached, j, + fragment = context.createDocumentFragment(), + nodes = [], + i = 0, + l = elems.length; + + for ( ; i < l; i++ ) { + elem = elems[ i ]; + + if ( elem || elem === 0 ) { + + // Add nodes directly + if ( toType( elem ) === "object" ) { + + // Support: Android <=4.0 only, PhantomJS 1 only + // push.apply(_, arraylike) throws on ancient WebKit + jQuery.merge( nodes, elem.nodeType ? [ elem ] : elem ); + + // Convert non-html into a text node + } else if ( !rhtml.test( elem ) ) { + nodes.push( context.createTextNode( elem ) ); + + // Convert html into DOM nodes + } else { + tmp = tmp || fragment.appendChild( context.createElement( "div" ) ); + + // Deserialize a standard representation + tag = ( rtagName.exec( elem ) || [ "", "" ] )[ 1 ].toLowerCase(); + wrap = wrapMap[ tag ] || wrapMap._default; + tmp.innerHTML = wrap[ 1 ] + jQuery.htmlPrefilter( elem ) + wrap[ 2 ]; + + // Descend through wrappers to the right content + j = wrap[ 0 ]; + while ( j-- ) { + tmp = tmp.lastChild; + } + + // Support: Android <=4.0 only, PhantomJS 1 only + // push.apply(_, arraylike) throws on ancient WebKit + jQuery.merge( nodes, tmp.childNodes ); + + // Remember the top-level container + tmp = fragment.firstChild; + + // Ensure the created nodes are orphaned (#12392) + tmp.textContent = ""; + } + } + } + + // Remove wrapper from fragment + fragment.textContent = ""; + + i = 0; + while ( ( elem = nodes[ i++ ] ) ) { + + // Skip elements already in the context collection (trac-4087) + if ( selection && jQuery.inArray( elem, selection ) > -1 ) { + if ( ignored ) { + ignored.push( elem ); + } + continue; + } + + attached = isAttached( elem ); + + // Append to fragment + tmp = getAll( fragment.appendChild( elem ), "script" ); + + // Preserve script evaluation history + if ( attached ) { + setGlobalEval( tmp ); + } + + // Capture executables + if ( scripts ) { + j = 0; + while ( ( elem = tmp[ j++ ] ) ) { + if ( rscriptType.test( elem.type || "" ) ) { + scripts.push( elem ); + } + } + } + } + + return fragment; +} + + +var + rkeyEvent = /^key/, + rmouseEvent = /^(?:mouse|pointer|contextmenu|drag|drop)|click/, + rtypenamespace = /^([^.]*)(?:\.(.+)|)/; + +function returnTrue() { + return true; +} + +function returnFalse() { + return false; +} + +// Support: IE <=9 - 11+ +// focus() and blur() are asynchronous, except when they are no-op. +// So expect focus to be synchronous when the element is already active, +// and blur to be synchronous when the element is not already active. +// (focus and blur are always synchronous in other supported browsers, +// this just defines when we can count on it). +function expectSync( elem, type ) { + return ( elem === safeActiveElement() ) === ( type === "focus" ); +} + +// Support: IE <=9 only +// Accessing document.activeElement can throw unexpectedly +// https://bugs.jquery.com/ticket/13393 +function safeActiveElement() { + try { + return document.activeElement; + } catch ( err ) { } +} + +function on( elem, types, selector, data, fn, one ) { + var origFn, type; + + // Types can be a map of types/handlers + if ( typeof types === "object" ) { + + // ( types-Object, selector, data ) + if ( typeof selector !== "string" ) { + + // ( types-Object, data ) + data = data || selector; + selector = undefined; + } + for ( type in types ) { + on( elem, type, selector, data, types[ type ], one ); + } + return elem; + } + + if ( data == null && fn == null ) { + + // ( types, fn ) + fn = selector; + data = selector = undefined; + } else if ( fn == null ) { + if ( typeof selector === "string" ) { + + // ( types, selector, fn ) + fn = data; + data = undefined; + } else { + + // ( types, data, fn ) + fn = data; + data = selector; + selector = undefined; + } + } + if ( fn === false ) { + fn = returnFalse; + } else if ( !fn ) { + return elem; + } + + if ( one === 1 ) { + origFn = fn; + fn = function( event ) { + + // Can use an empty set, since event contains the info + jQuery().off( event ); + return origFn.apply( this, arguments ); + }; + + // Use same guid so caller can remove using origFn + fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ ); + } + return elem.each( function() { + jQuery.event.add( this, types, fn, data, selector ); + } ); +} + +/* + * Helper functions for managing events -- not part of the public interface. + * Props to Dean Edwards' addEvent library for many of the ideas. + */ +jQuery.event = { + + global: {}, + + add: function( elem, types, handler, data, selector ) { + + var handleObjIn, eventHandle, tmp, + events, t, handleObj, + special, handlers, type, namespaces, origType, + elemData = dataPriv.get( elem ); + + // Only attach events to objects that accept data + if ( !acceptData( elem ) ) { + return; + } + + // Caller can pass in an object of custom data in lieu of the handler + if ( handler.handler ) { + handleObjIn = handler; + handler = handleObjIn.handler; + selector = handleObjIn.selector; + } + + // Ensure that invalid selectors throw exceptions at attach time + // Evaluate against documentElement in case elem is a non-element node (e.g., document) + if ( selector ) { + jQuery.find.matchesSelector( documentElement, selector ); + } + + // Make sure that the handler has a unique ID, used to find/remove it later + if ( !handler.guid ) { + handler.guid = jQuery.guid++; + } + + // Init the element's event structure and main handler, if this is the first + if ( !( events = elemData.events ) ) { + events = elemData.events = Object.create( null ); + } + if ( !( eventHandle = elemData.handle ) ) { + eventHandle = elemData.handle = function( e ) { + + // Discard the second event of a jQuery.event.trigger() and + // when an event is called after a page has unloaded + return typeof jQuery !== "undefined" && jQuery.event.triggered !== e.type ? + jQuery.event.dispatch.apply( elem, arguments ) : undefined; + }; + } + + // Handle multiple events separated by a space + types = ( types || "" ).match( rnothtmlwhite ) || [ "" ]; + t = types.length; + while ( t-- ) { + tmp = rtypenamespace.exec( types[ t ] ) || []; + type = origType = tmp[ 1 ]; + namespaces = ( tmp[ 2 ] || "" ).split( "." ).sort(); + + // There *must* be a type, no attaching namespace-only handlers + if ( !type ) { + continue; + } + + // If event changes its type, use the special event handlers for the changed type + special = jQuery.event.special[ type ] || {}; + + // If selector defined, determine special event api type, otherwise given type + type = ( selector ? special.delegateType : special.bindType ) || type; + + // Update special based on newly reset type + special = jQuery.event.special[ type ] || {}; + + // handleObj is passed to all event handlers + handleObj = jQuery.extend( { + type: type, + origType: origType, + data: data, + handler: handler, + guid: handler.guid, + selector: selector, + needsContext: selector && jQuery.expr.match.needsContext.test( selector ), + namespace: namespaces.join( "." ) + }, handleObjIn ); + + // Init the event handler queue if we're the first + if ( !( handlers = events[ type ] ) ) { + handlers = events[ type ] = []; + handlers.delegateCount = 0; + + // Only use addEventListener if the special events handler returns false + if ( !special.setup || + special.setup.call( elem, data, namespaces, eventHandle ) === false ) { + + if ( elem.addEventListener ) { + elem.addEventListener( type, eventHandle ); + } + } + } + + if ( special.add ) { + special.add.call( elem, handleObj ); + + if ( !handleObj.handler.guid ) { + handleObj.handler.guid = handler.guid; + } + } + + // Add to the element's handler list, delegates in front + if ( selector ) { + handlers.splice( handlers.delegateCount++, 0, handleObj ); + } else { + handlers.push( handleObj ); + } + + // Keep track of which events have ever been used, for event optimization + jQuery.event.global[ type ] = true; + } + + }, + + // Detach an event or set of events from an element + remove: function( elem, types, handler, selector, mappedTypes ) { + + var j, origCount, tmp, + events, t, handleObj, + special, handlers, type, namespaces, origType, + elemData = dataPriv.hasData( elem ) && dataPriv.get( elem ); + + if ( !elemData || !( events = elemData.events ) ) { + return; + } + + // Once for each type.namespace in types; type may be omitted + types = ( types || "" ).match( rnothtmlwhite ) || [ "" ]; + t = types.length; + while ( t-- ) { + tmp = rtypenamespace.exec( types[ t ] ) || []; + type = origType = tmp[ 1 ]; + namespaces = ( tmp[ 2 ] || "" ).split( "." ).sort(); + + // Unbind all events (on this namespace, if provided) for the element + if ( !type ) { + for ( type in events ) { + jQuery.event.remove( elem, type + types[ t ], handler, selector, true ); + } + continue; + } + + special = jQuery.event.special[ type ] || {}; + type = ( selector ? special.delegateType : special.bindType ) || type; + handlers = events[ type ] || []; + tmp = tmp[ 2 ] && + new RegExp( "(^|\\.)" + namespaces.join( "\\.(?:.*\\.|)" ) + "(\\.|$)" ); + + // Remove matching events + origCount = j = handlers.length; + while ( j-- ) { + handleObj = handlers[ j ]; + + if ( ( mappedTypes || origType === handleObj.origType ) && + ( !handler || handler.guid === handleObj.guid ) && + ( !tmp || tmp.test( handleObj.namespace ) ) && + ( !selector || selector === handleObj.selector || + selector === "**" && handleObj.selector ) ) { + handlers.splice( j, 1 ); + + if ( handleObj.selector ) { + handlers.delegateCount--; + } + if ( special.remove ) { + special.remove.call( elem, handleObj ); + } + } + } + + // Remove generic event handler if we removed something and no more handlers exist + // (avoids potential for endless recursion during removal of special event handlers) + if ( origCount && !handlers.length ) { + if ( !special.teardown || + special.teardown.call( elem, namespaces, elemData.handle ) === false ) { + + jQuery.removeEvent( elem, type, elemData.handle ); + } + + delete events[ type ]; + } + } + + // Remove data and the expando if it's no longer used + if ( jQuery.isEmptyObject( events ) ) { + dataPriv.remove( elem, "handle events" ); + } + }, + + dispatch: function( nativeEvent ) { + + var i, j, ret, matched, handleObj, handlerQueue, + args = new Array( arguments.length ), + + // Make a writable jQuery.Event from the native event object + event = jQuery.event.fix( nativeEvent ), + + handlers = ( + dataPriv.get( this, "events" ) || Object.create( null ) + )[ event.type ] || [], + special = jQuery.event.special[ event.type ] || {}; + + // Use the fix-ed jQuery.Event rather than the (read-only) native event + args[ 0 ] = event; + + for ( i = 1; i < arguments.length; i++ ) { + args[ i ] = arguments[ i ]; + } + + event.delegateTarget = this; + + // Call the preDispatch hook for the mapped type, and let it bail if desired + if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) { + return; + } + + // Determine handlers + handlerQueue = jQuery.event.handlers.call( this, event, handlers ); + + // Run delegates first; they may want to stop propagation beneath us + i = 0; + while ( ( matched = handlerQueue[ i++ ] ) && !event.isPropagationStopped() ) { + event.currentTarget = matched.elem; + + j = 0; + while ( ( handleObj = matched.handlers[ j++ ] ) && + !event.isImmediatePropagationStopped() ) { + + // If the event is namespaced, then each handler is only invoked if it is + // specially universal or its namespaces are a superset of the event's. + if ( !event.rnamespace || handleObj.namespace === false || + event.rnamespace.test( handleObj.namespace ) ) { + + event.handleObj = handleObj; + event.data = handleObj.data; + + ret = ( ( jQuery.event.special[ handleObj.origType ] || {} ).handle || + handleObj.handler ).apply( matched.elem, args ); + + if ( ret !== undefined ) { + if ( ( event.result = ret ) === false ) { + event.preventDefault(); + event.stopPropagation(); + } + } + } + } + } + + // Call the postDispatch hook for the mapped type + if ( special.postDispatch ) { + special.postDispatch.call( this, event ); + } + + return event.result; + }, + + handlers: function( event, handlers ) { + var i, handleObj, sel, matchedHandlers, matchedSelectors, + handlerQueue = [], + delegateCount = handlers.delegateCount, + cur = event.target; + + // Find delegate handlers + if ( delegateCount && + + // Support: IE <=9 + // Black-hole SVG instance trees (trac-13180) + cur.nodeType && + + // Support: Firefox <=42 + // Suppress spec-violating clicks indicating a non-primary pointer button (trac-3861) + // https://www.w3.org/TR/DOM-Level-3-Events/#event-type-click + // Support: IE 11 only + // ...but not arrow key "clicks" of radio inputs, which can have `button` -1 (gh-2343) + !( event.type === "click" && event.button >= 1 ) ) { + + for ( ; cur !== this; cur = cur.parentNode || this ) { + + // Don't check non-elements (#13208) + // Don't process clicks on disabled elements (#6911, #8165, #11382, #11764) + if ( cur.nodeType === 1 && !( event.type === "click" && cur.disabled === true ) ) { + matchedHandlers = []; + matchedSelectors = {}; + for ( i = 0; i < delegateCount; i++ ) { + handleObj = handlers[ i ]; + + // Don't conflict with Object.prototype properties (#13203) + sel = handleObj.selector + " "; + + if ( matchedSelectors[ sel ] === undefined ) { + matchedSelectors[ sel ] = handleObj.needsContext ? + jQuery( sel, this ).index( cur ) > -1 : + jQuery.find( sel, this, null, [ cur ] ).length; + } + if ( matchedSelectors[ sel ] ) { + matchedHandlers.push( handleObj ); + } + } + if ( matchedHandlers.length ) { + handlerQueue.push( { elem: cur, handlers: matchedHandlers } ); + } + } + } + } + + // Add the remaining (directly-bound) handlers + cur = this; + if ( delegateCount < handlers.length ) { + handlerQueue.push( { elem: cur, handlers: handlers.slice( delegateCount ) } ); + } + + return handlerQueue; + }, + + addProp: function( name, hook ) { + Object.defineProperty( jQuery.Event.prototype, name, { + enumerable: true, + configurable: true, + + get: isFunction( hook ) ? + function() { + if ( this.originalEvent ) { + return hook( this.originalEvent ); + } + } : + function() { + if ( this.originalEvent ) { + return this.originalEvent[ name ]; + } + }, + + set: function( value ) { + Object.defineProperty( this, name, { + enumerable: true, + configurable: true, + writable: true, + value: value + } ); + } + } ); + }, + + fix: function( originalEvent ) { + return originalEvent[ jQuery.expando ] ? + originalEvent : + new jQuery.Event( originalEvent ); + }, + + special: { + load: { + + // Prevent triggered image.load events from bubbling to window.load + noBubble: true + }, + click: { + + // Utilize native event to ensure correct state for checkable inputs + setup: function( data ) { + + // For mutual compressibility with _default, replace `this` access with a local var. + // `|| data` is dead code meant only to preserve the variable through minification. + var el = this || data; + + // Claim the first handler + if ( rcheckableType.test( el.type ) && + el.click && nodeName( el, "input" ) ) { + + // dataPriv.set( el, "click", ... ) + leverageNative( el, "click", returnTrue ); + } + + // Return false to allow normal processing in the caller + return false; + }, + trigger: function( data ) { + + // For mutual compressibility with _default, replace `this` access with a local var. + // `|| data` is dead code meant only to preserve the variable through minification. + var el = this || data; + + // Force setup before triggering a click + if ( rcheckableType.test( el.type ) && + el.click && nodeName( el, "input" ) ) { + + leverageNative( el, "click" ); + } + + // Return non-false to allow normal event-path propagation + return true; + }, + + // For cross-browser consistency, suppress native .click() on links + // Also prevent it if we're currently inside a leveraged native-event stack + _default: function( event ) { + var target = event.target; + return rcheckableType.test( target.type ) && + target.click && nodeName( target, "input" ) && + dataPriv.get( target, "click" ) || + nodeName( target, "a" ); + } + }, + + beforeunload: { + postDispatch: function( event ) { + + // Support: Firefox 20+ + // Firefox doesn't alert if the returnValue field is not set. + if ( event.result !== undefined && event.originalEvent ) { + event.originalEvent.returnValue = event.result; + } + } + } + } +}; + +// Ensure the presence of an event listener that handles manually-triggered +// synthetic events by interrupting progress until reinvoked in response to +// *native* events that it fires directly, ensuring that state changes have +// already occurred before other listeners are invoked. +function leverageNative( el, type, expectSync ) { + + // Missing expectSync indicates a trigger call, which must force setup through jQuery.event.add + if ( !expectSync ) { + if ( dataPriv.get( el, type ) === undefined ) { + jQuery.event.add( el, type, returnTrue ); + } + return; + } + + // Register the controller as a special universal handler for all event namespaces + dataPriv.set( el, type, false ); + jQuery.event.add( el, type, { + namespace: false, + handler: function( event ) { + var notAsync, result, + saved = dataPriv.get( this, type ); + + if ( ( event.isTrigger & 1 ) && this[ type ] ) { + + // Interrupt processing of the outer synthetic .trigger()ed event + // Saved data should be false in such cases, but might be a leftover capture object + // from an async native handler (gh-4350) + if ( !saved.length ) { + + // Store arguments for use when handling the inner native event + // There will always be at least one argument (an event object), so this array + // will not be confused with a leftover capture object. + saved = slice.call( arguments ); + dataPriv.set( this, type, saved ); + + // Trigger the native event and capture its result + // Support: IE <=9 - 11+ + // focus() and blur() are asynchronous + notAsync = expectSync( this, type ); + this[ type ](); + result = dataPriv.get( this, type ); + if ( saved !== result || notAsync ) { + dataPriv.set( this, type, false ); + } else { + result = {}; + } + if ( saved !== result ) { + + // Cancel the outer synthetic event + event.stopImmediatePropagation(); + event.preventDefault(); + return result.value; + } + + // If this is an inner synthetic event for an event with a bubbling surrogate + // (focus or blur), assume that the surrogate already propagated from triggering the + // native event and prevent that from happening again here. + // This technically gets the ordering wrong w.r.t. to `.trigger()` (in which the + // bubbling surrogate propagates *after* the non-bubbling base), but that seems + // less bad than duplication. + } else if ( ( jQuery.event.special[ type ] || {} ).delegateType ) { + event.stopPropagation(); + } + + // If this is a native event triggered above, everything is now in order + // Fire an inner synthetic event with the original arguments + } else if ( saved.length ) { + + // ...and capture the result + dataPriv.set( this, type, { + value: jQuery.event.trigger( + + // Support: IE <=9 - 11+ + // Extend with the prototype to reset the above stopImmediatePropagation() + jQuery.extend( saved[ 0 ], jQuery.Event.prototype ), + saved.slice( 1 ), + this + ) + } ); + + // Abort handling of the native event + event.stopImmediatePropagation(); + } + } + } ); +} + +jQuery.removeEvent = function( elem, type, handle ) { + + // This "if" is needed for plain objects + if ( elem.removeEventListener ) { + elem.removeEventListener( type, handle ); + } +}; + +jQuery.Event = function( src, props ) { + + // Allow instantiation without the 'new' keyword + if ( !( this instanceof jQuery.Event ) ) { + return new jQuery.Event( src, props ); + } + + // Event object + if ( src && src.type ) { + this.originalEvent = src; + this.type = src.type; + + // Events bubbling up the document may have been marked as prevented + // by a handler lower down the tree; reflect the correct value. + this.isDefaultPrevented = src.defaultPrevented || + src.defaultPrevented === undefined && + + // Support: Android <=2.3 only + src.returnValue === false ? + returnTrue : + returnFalse; + + // Create target properties + // Support: Safari <=6 - 7 only + // Target should not be a text node (#504, #13143) + this.target = ( src.target && src.target.nodeType === 3 ) ? + src.target.parentNode : + src.target; + + this.currentTarget = src.currentTarget; + this.relatedTarget = src.relatedTarget; + + // Event type + } else { + this.type = src; + } + + // Put explicitly provided properties onto the event object + if ( props ) { + jQuery.extend( this, props ); + } + + // Create a timestamp if incoming event doesn't have one + this.timeStamp = src && src.timeStamp || Date.now(); + + // Mark it as fixed + this[ jQuery.expando ] = true; +}; + +// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding +// https://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html +jQuery.Event.prototype = { + constructor: jQuery.Event, + isDefaultPrevented: returnFalse, + isPropagationStopped: returnFalse, + isImmediatePropagationStopped: returnFalse, + isSimulated: false, + + preventDefault: function() { + var e = this.originalEvent; + + this.isDefaultPrevented = returnTrue; + + if ( e && !this.isSimulated ) { + e.preventDefault(); + } + }, + stopPropagation: function() { + var e = this.originalEvent; + + this.isPropagationStopped = returnTrue; + + if ( e && !this.isSimulated ) { + e.stopPropagation(); + } + }, + stopImmediatePropagation: function() { + var e = this.originalEvent; + + this.isImmediatePropagationStopped = returnTrue; + + if ( e && !this.isSimulated ) { + e.stopImmediatePropagation(); + } + + this.stopPropagation(); + } +}; + +// Includes all common event props including KeyEvent and MouseEvent specific props +jQuery.each( { + altKey: true, + bubbles: true, + cancelable: true, + changedTouches: true, + ctrlKey: true, + detail: true, + eventPhase: true, + metaKey: true, + pageX: true, + pageY: true, + shiftKey: true, + view: true, + "char": true, + code: true, + charCode: true, + key: true, + keyCode: true, + button: true, + buttons: true, + clientX: true, + clientY: true, + offsetX: true, + offsetY: true, + pointerId: true, + pointerType: true, + screenX: true, + screenY: true, + targetTouches: true, + toElement: true, + touches: true, + + which: function( event ) { + var button = event.button; + + // Add which for key events + if ( event.which == null && rkeyEvent.test( event.type ) ) { + return event.charCode != null ? event.charCode : event.keyCode; + } + + // Add which for click: 1 === left; 2 === middle; 3 === right + if ( !event.which && button !== undefined && rmouseEvent.test( event.type ) ) { + if ( button & 1 ) { + return 1; + } + + if ( button & 2 ) { + return 3; + } + + if ( button & 4 ) { + return 2; + } + + return 0; + } + + return event.which; + } +}, jQuery.event.addProp ); + +jQuery.each( { focus: "focusin", blur: "focusout" }, function( type, delegateType ) { + jQuery.event.special[ type ] = { + + // Utilize native event if possible so blur/focus sequence is correct + setup: function() { + + // Claim the first handler + // dataPriv.set( this, "focus", ... ) + // dataPriv.set( this, "blur", ... ) + leverageNative( this, type, expectSync ); + + // Return false to allow normal processing in the caller + return false; + }, + trigger: function() { + + // Force setup before trigger + leverageNative( this, type ); + + // Return non-false to allow normal event-path propagation + return true; + }, + + delegateType: delegateType + }; +} ); + +// Create mouseenter/leave events using mouseover/out and event-time checks +// so that event delegation works in jQuery. +// Do the same for pointerenter/pointerleave and pointerover/pointerout +// +// Support: Safari 7 only +// Safari sends mouseenter too often; see: +// https://bugs.chromium.org/p/chromium/issues/detail?id=470258 +// for the description of the bug (it existed in older Chrome versions as well). +jQuery.each( { + mouseenter: "mouseover", + mouseleave: "mouseout", + pointerenter: "pointerover", + pointerleave: "pointerout" +}, function( orig, fix ) { + jQuery.event.special[ orig ] = { + delegateType: fix, + bindType: fix, + + handle: function( event ) { + var ret, + target = this, + related = event.relatedTarget, + handleObj = event.handleObj; + + // For mouseenter/leave call the handler if related is outside the target. + // NB: No relatedTarget if the mouse left/entered the browser window + if ( !related || ( related !== target && !jQuery.contains( target, related ) ) ) { + event.type = handleObj.origType; + ret = handleObj.handler.apply( this, arguments ); + event.type = fix; + } + return ret; + } + }; +} ); + +jQuery.fn.extend( { + + on: function( types, selector, data, fn ) { + return on( this, types, selector, data, fn ); + }, + one: function( types, selector, data, fn ) { + return on( this, types, selector, data, fn, 1 ); + }, + off: function( types, selector, fn ) { + var handleObj, type; + if ( types && types.preventDefault && types.handleObj ) { + + // ( event ) dispatched jQuery.Event + handleObj = types.handleObj; + jQuery( types.delegateTarget ).off( + handleObj.namespace ? + handleObj.origType + "." + handleObj.namespace : + handleObj.origType, + handleObj.selector, + handleObj.handler + ); + return this; + } + if ( typeof types === "object" ) { + + // ( types-object [, selector] ) + for ( type in types ) { + this.off( type, selector, types[ type ] ); + } + return this; + } + if ( selector === false || typeof selector === "function" ) { + + // ( types [, fn] ) + fn = selector; + selector = undefined; + } + if ( fn === false ) { + fn = returnFalse; + } + return this.each( function() { + jQuery.event.remove( this, types, fn, selector ); + } ); + } +} ); + + +var + + // Support: IE <=10 - 11, Edge 12 - 13 only + // In IE/Edge using regex groups here causes severe slowdowns. + // See https://connect.microsoft.com/IE/feedback/details/1736512/ + rnoInnerhtml = /\s*$/g; + +// Prefer a tbody over its parent table for containing new rows +function manipulationTarget( elem, content ) { + if ( nodeName( elem, "table" ) && + nodeName( content.nodeType !== 11 ? content : content.firstChild, "tr" ) ) { + + return jQuery( elem ).children( "tbody" )[ 0 ] || elem; + } + + return elem; +} + +// Replace/restore the type attribute of script elements for safe DOM manipulation +function disableScript( elem ) { + elem.type = ( elem.getAttribute( "type" ) !== null ) + "/" + elem.type; + return elem; +} +function restoreScript( elem ) { + if ( ( elem.type || "" ).slice( 0, 5 ) === "true/" ) { + elem.type = elem.type.slice( 5 ); + } else { + elem.removeAttribute( "type" ); + } + + return elem; +} + +function cloneCopyEvent( src, dest ) { + var i, l, type, pdataOld, udataOld, udataCur, events; + + if ( dest.nodeType !== 1 ) { + return; + } + + // 1. Copy private data: events, handlers, etc. + if ( dataPriv.hasData( src ) ) { + pdataOld = dataPriv.get( src ); + events = pdataOld.events; + + if ( events ) { + dataPriv.remove( dest, "handle events" ); + + for ( type in events ) { + for ( i = 0, l = events[ type ].length; i < l; i++ ) { + jQuery.event.add( dest, type, events[ type ][ i ] ); + } + } + } + } + + // 2. Copy user data + if ( dataUser.hasData( src ) ) { + udataOld = dataUser.access( src ); + udataCur = jQuery.extend( {}, udataOld ); + + dataUser.set( dest, udataCur ); + } +} + +// Fix IE bugs, see support tests +function fixInput( src, dest ) { + var nodeName = dest.nodeName.toLowerCase(); + + // Fails to persist the checked state of a cloned checkbox or radio button. + if ( nodeName === "input" && rcheckableType.test( src.type ) ) { + dest.checked = src.checked; + + // Fails to return the selected option to the default selected state when cloning options + } else if ( nodeName === "input" || nodeName === "textarea" ) { + dest.defaultValue = src.defaultValue; + } +} + +function domManip( collection, args, callback, ignored ) { + + // Flatten any nested arrays + args = flat( args ); + + var fragment, first, scripts, hasScripts, node, doc, + i = 0, + l = collection.length, + iNoClone = l - 1, + value = args[ 0 ], + valueIsFunction = isFunction( value ); + + // We can't cloneNode fragments that contain checked, in WebKit + if ( valueIsFunction || + ( l > 1 && typeof value === "string" && + !support.checkClone && rchecked.test( value ) ) ) { + return collection.each( function( index ) { + var self = collection.eq( index ); + if ( valueIsFunction ) { + args[ 0 ] = value.call( this, index, self.html() ); + } + domManip( self, args, callback, ignored ); + } ); + } + + if ( l ) { + fragment = buildFragment( args, collection[ 0 ].ownerDocument, false, collection, ignored ); + first = fragment.firstChild; + + if ( fragment.childNodes.length === 1 ) { + fragment = first; + } + + // Require either new content or an interest in ignored elements to invoke the callback + if ( first || ignored ) { + scripts = jQuery.map( getAll( fragment, "script" ), disableScript ); + hasScripts = scripts.length; + + // Use the original fragment for the last item + // instead of the first because it can end up + // being emptied incorrectly in certain situations (#8070). + for ( ; i < l; i++ ) { + node = fragment; + + if ( i !== iNoClone ) { + node = jQuery.clone( node, true, true ); + + // Keep references to cloned scripts for later restoration + if ( hasScripts ) { + + // Support: Android <=4.0 only, PhantomJS 1 only + // push.apply(_, arraylike) throws on ancient WebKit + jQuery.merge( scripts, getAll( node, "script" ) ); + } + } + + callback.call( collection[ i ], node, i ); + } + + if ( hasScripts ) { + doc = scripts[ scripts.length - 1 ].ownerDocument; + + // Reenable scripts + jQuery.map( scripts, restoreScript ); + + // Evaluate executable scripts on first document insertion + for ( i = 0; i < hasScripts; i++ ) { + node = scripts[ i ]; + if ( rscriptType.test( node.type || "" ) && + !dataPriv.access( node, "globalEval" ) && + jQuery.contains( doc, node ) ) { + + if ( node.src && ( node.type || "" ).toLowerCase() !== "module" ) { + + // Optional AJAX dependency, but won't run scripts if not present + if ( jQuery._evalUrl && !node.noModule ) { + jQuery._evalUrl( node.src, { + nonce: node.nonce || node.getAttribute( "nonce" ) + }, doc ); + } + } else { + DOMEval( node.textContent.replace( rcleanScript, "" ), node, doc ); + } + } + } + } + } + } + + return collection; +} + +function remove( elem, selector, keepData ) { + var node, + nodes = selector ? jQuery.filter( selector, elem ) : elem, + i = 0; + + for ( ; ( node = nodes[ i ] ) != null; i++ ) { + if ( !keepData && node.nodeType === 1 ) { + jQuery.cleanData( getAll( node ) ); + } + + if ( node.parentNode ) { + if ( keepData && isAttached( node ) ) { + setGlobalEval( getAll( node, "script" ) ); + } + node.parentNode.removeChild( node ); + } + } + + return elem; +} + +jQuery.extend( { + htmlPrefilter: function( html ) { + return html; + }, + + clone: function( elem, dataAndEvents, deepDataAndEvents ) { + var i, l, srcElements, destElements, + clone = elem.cloneNode( true ), + inPage = isAttached( elem ); + + // Fix IE cloning issues + if ( !support.noCloneChecked && ( elem.nodeType === 1 || elem.nodeType === 11 ) && + !jQuery.isXMLDoc( elem ) ) { + + // We eschew Sizzle here for performance reasons: https://jsperf.com/getall-vs-sizzle/2 + destElements = getAll( clone ); + srcElements = getAll( elem ); + + for ( i = 0, l = srcElements.length; i < l; i++ ) { + fixInput( srcElements[ i ], destElements[ i ] ); + } + } + + // Copy the events from the original to the clone + if ( dataAndEvents ) { + if ( deepDataAndEvents ) { + srcElements = srcElements || getAll( elem ); + destElements = destElements || getAll( clone ); + + for ( i = 0, l = srcElements.length; i < l; i++ ) { + cloneCopyEvent( srcElements[ i ], destElements[ i ] ); + } + } else { + cloneCopyEvent( elem, clone ); + } + } + + // Preserve script evaluation history + destElements = getAll( clone, "script" ); + if ( destElements.length > 0 ) { + setGlobalEval( destElements, !inPage && getAll( elem, "script" ) ); + } + + // Return the cloned set + return clone; + }, + + cleanData: function( elems ) { + var data, elem, type, + special = jQuery.event.special, + i = 0; + + for ( ; ( elem = elems[ i ] ) !== undefined; i++ ) { + if ( acceptData( elem ) ) { + if ( ( data = elem[ dataPriv.expando ] ) ) { + if ( data.events ) { + for ( type in data.events ) { + if ( special[ type ] ) { + jQuery.event.remove( elem, type ); + + // This is a shortcut to avoid jQuery.event.remove's overhead + } else { + jQuery.removeEvent( elem, type, data.handle ); + } + } + } + + // Support: Chrome <=35 - 45+ + // Assign undefined instead of using delete, see Data#remove + elem[ dataPriv.expando ] = undefined; + } + if ( elem[ dataUser.expando ] ) { + + // Support: Chrome <=35 - 45+ + // Assign undefined instead of using delete, see Data#remove + elem[ dataUser.expando ] = undefined; + } + } + } + } +} ); + +jQuery.fn.extend( { + detach: function( selector ) { + return remove( this, selector, true ); + }, + + remove: function( selector ) { + return remove( this, selector ); + }, + + text: function( value ) { + return access( this, function( value ) { + return value === undefined ? + jQuery.text( this ) : + this.empty().each( function() { + if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { + this.textContent = value; + } + } ); + }, null, value, arguments.length ); + }, + + append: function() { + return domManip( this, arguments, function( elem ) { + if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { + var target = manipulationTarget( this, elem ); + target.appendChild( elem ); + } + } ); + }, + + prepend: function() { + return domManip( this, arguments, function( elem ) { + if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { + var target = manipulationTarget( this, elem ); + target.insertBefore( elem, target.firstChild ); + } + } ); + }, + + before: function() { + return domManip( this, arguments, function( elem ) { + if ( this.parentNode ) { + this.parentNode.insertBefore( elem, this ); + } + } ); + }, + + after: function() { + return domManip( this, arguments, function( elem ) { + if ( this.parentNode ) { + this.parentNode.insertBefore( elem, this.nextSibling ); + } + } ); + }, + + empty: function() { + var elem, + i = 0; + + for ( ; ( elem = this[ i ] ) != null; i++ ) { + if ( elem.nodeType === 1 ) { + + // Prevent memory leaks + jQuery.cleanData( getAll( elem, false ) ); + + // Remove any remaining nodes + elem.textContent = ""; + } + } + + return this; + }, + + clone: function( dataAndEvents, deepDataAndEvents ) { + dataAndEvents = dataAndEvents == null ? false : dataAndEvents; + deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents; + + return this.map( function() { + return jQuery.clone( this, dataAndEvents, deepDataAndEvents ); + } ); + }, + + html: function( value ) { + return access( this, function( value ) { + var elem = this[ 0 ] || {}, + i = 0, + l = this.length; + + if ( value === undefined && elem.nodeType === 1 ) { + return elem.innerHTML; + } + + // See if we can take a shortcut and just use innerHTML + if ( typeof value === "string" && !rnoInnerhtml.test( value ) && + !wrapMap[ ( rtagName.exec( value ) || [ "", "" ] )[ 1 ].toLowerCase() ] ) { + + value = jQuery.htmlPrefilter( value ); + + try { + for ( ; i < l; i++ ) { + elem = this[ i ] || {}; + + // Remove element nodes and prevent memory leaks + if ( elem.nodeType === 1 ) { + jQuery.cleanData( getAll( elem, false ) ); + elem.innerHTML = value; + } + } + + elem = 0; + + // If using innerHTML throws an exception, use the fallback method + } catch ( e ) {} + } + + if ( elem ) { + this.empty().append( value ); + } + }, null, value, arguments.length ); + }, + + replaceWith: function() { + var ignored = []; + + // Make the changes, replacing each non-ignored context element with the new content + return domManip( this, arguments, function( elem ) { + var parent = this.parentNode; + + if ( jQuery.inArray( this, ignored ) < 0 ) { + jQuery.cleanData( getAll( this ) ); + if ( parent ) { + parent.replaceChild( elem, this ); + } + } + + // Force callback invocation + }, ignored ); + } +} ); + +jQuery.each( { + appendTo: "append", + prependTo: "prepend", + insertBefore: "before", + insertAfter: "after", + replaceAll: "replaceWith" +}, function( name, original ) { + jQuery.fn[ name ] = function( selector ) { + var elems, + ret = [], + insert = jQuery( selector ), + last = insert.length - 1, + i = 0; + + for ( ; i <= last; i++ ) { + elems = i === last ? this : this.clone( true ); + jQuery( insert[ i ] )[ original ]( elems ); + + // Support: Android <=4.0 only, PhantomJS 1 only + // .get() because push.apply(_, arraylike) throws on ancient WebKit + push.apply( ret, elems.get() ); + } + + return this.pushStack( ret ); + }; +} ); +var rnumnonpx = new RegExp( "^(" + pnum + ")(?!px)[a-z%]+$", "i" ); + +var getStyles = function( elem ) { + + // Support: IE <=11 only, Firefox <=30 (#15098, #14150) + // IE throws on elements created in popups + // FF meanwhile throws on frame elements through "defaultView.getComputedStyle" + var view = elem.ownerDocument.defaultView; + + if ( !view || !view.opener ) { + view = window; + } + + return view.getComputedStyle( elem ); + }; + +var swap = function( elem, options, callback ) { + var ret, name, + old = {}; + + // Remember the old values, and insert the new ones + for ( name in options ) { + old[ name ] = elem.style[ name ]; + elem.style[ name ] = options[ name ]; + } + + ret = callback.call( elem ); + + // Revert the old values + for ( name in options ) { + elem.style[ name ] = old[ name ]; + } + + return ret; +}; + + +var rboxStyle = new RegExp( cssExpand.join( "|" ), "i" ); + + + +( function() { + + // Executing both pixelPosition & boxSizingReliable tests require only one layout + // so they're executed at the same time to save the second computation. + function computeStyleTests() { + + // This is a singleton, we need to execute it only once + if ( !div ) { + return; + } + + container.style.cssText = "position:absolute;left:-11111px;width:60px;" + + "margin-top:1px;padding:0;border:0"; + div.style.cssText = + "position:relative;display:block;box-sizing:border-box;overflow:scroll;" + + "margin:auto;border:1px;padding:1px;" + + "width:60%;top:1%"; + documentElement.appendChild( container ).appendChild( div ); + + var divStyle = window.getComputedStyle( div ); + pixelPositionVal = divStyle.top !== "1%"; + + // Support: Android 4.0 - 4.3 only, Firefox <=3 - 44 + reliableMarginLeftVal = roundPixelMeasures( divStyle.marginLeft ) === 12; + + // Support: Android 4.0 - 4.3 only, Safari <=9.1 - 10.1, iOS <=7.0 - 9.3 + // Some styles come back with percentage values, even though they shouldn't + div.style.right = "60%"; + pixelBoxStylesVal = roundPixelMeasures( divStyle.right ) === 36; + + // Support: IE 9 - 11 only + // Detect misreporting of content dimensions for box-sizing:border-box elements + boxSizingReliableVal = roundPixelMeasures( divStyle.width ) === 36; + + // Support: IE 9 only + // Detect overflow:scroll screwiness (gh-3699) + // Support: Chrome <=64 + // Don't get tricked when zoom affects offsetWidth (gh-4029) + div.style.position = "absolute"; + scrollboxSizeVal = roundPixelMeasures( div.offsetWidth / 3 ) === 12; + + documentElement.removeChild( container ); + + // Nullify the div so it wouldn't be stored in the memory and + // it will also be a sign that checks already performed + div = null; + } + + function roundPixelMeasures( measure ) { + return Math.round( parseFloat( measure ) ); + } + + var pixelPositionVal, boxSizingReliableVal, scrollboxSizeVal, pixelBoxStylesVal, + reliableTrDimensionsVal, reliableMarginLeftVal, + container = document.createElement( "div" ), + div = document.createElement( "div" ); + + // Finish early in limited (non-browser) environments + if ( !div.style ) { + return; + } + + // Support: IE <=9 - 11 only + // Style of cloned element affects source element cloned (#8908) + div.style.backgroundClip = "content-box"; + div.cloneNode( true ).style.backgroundClip = ""; + support.clearCloneStyle = div.style.backgroundClip === "content-box"; + + jQuery.extend( support, { + boxSizingReliable: function() { + computeStyleTests(); + return boxSizingReliableVal; + }, + pixelBoxStyles: function() { + computeStyleTests(); + return pixelBoxStylesVal; + }, + pixelPosition: function() { + computeStyleTests(); + return pixelPositionVal; + }, + reliableMarginLeft: function() { + computeStyleTests(); + return reliableMarginLeftVal; + }, + scrollboxSize: function() { + computeStyleTests(); + return scrollboxSizeVal; + }, + + // Support: IE 9 - 11+, Edge 15 - 18+ + // IE/Edge misreport `getComputedStyle` of table rows with width/height + // set in CSS while `offset*` properties report correct values. + // Behavior in IE 9 is more subtle than in newer versions & it passes + // some versions of this test; make sure not to make it pass there! + reliableTrDimensions: function() { + var table, tr, trChild, trStyle; + if ( reliableTrDimensionsVal == null ) { + table = document.createElement( "table" ); + tr = document.createElement( "tr" ); + trChild = document.createElement( "div" ); + + table.style.cssText = "position:absolute;left:-11111px"; + tr.style.height = "1px"; + trChild.style.height = "9px"; + + documentElement + .appendChild( table ) + .appendChild( tr ) + .appendChild( trChild ); + + trStyle = window.getComputedStyle( tr ); + reliableTrDimensionsVal = parseInt( trStyle.height ) > 3; + + documentElement.removeChild( table ); + } + return reliableTrDimensionsVal; + } + } ); +} )(); + + +function curCSS( elem, name, computed ) { + var width, minWidth, maxWidth, ret, + + // Support: Firefox 51+ + // Retrieving style before computed somehow + // fixes an issue with getting wrong values + // on detached elements + style = elem.style; + + computed = computed || getStyles( elem ); + + // getPropertyValue is needed for: + // .css('filter') (IE 9 only, #12537) + // .css('--customProperty) (#3144) + if ( computed ) { + ret = computed.getPropertyValue( name ) || computed[ name ]; + + if ( ret === "" && !isAttached( elem ) ) { + ret = jQuery.style( elem, name ); + } + + // A tribute to the "awesome hack by Dean Edwards" + // Android Browser returns percentage for some values, + // but width seems to be reliably pixels. + // This is against the CSSOM draft spec: + // https://drafts.csswg.org/cssom/#resolved-values + if ( !support.pixelBoxStyles() && rnumnonpx.test( ret ) && rboxStyle.test( name ) ) { + + // Remember the original values + width = style.width; + minWidth = style.minWidth; + maxWidth = style.maxWidth; + + // Put in the new values to get a computed value out + style.minWidth = style.maxWidth = style.width = ret; + ret = computed.width; + + // Revert the changed values + style.width = width; + style.minWidth = minWidth; + style.maxWidth = maxWidth; + } + } + + return ret !== undefined ? + + // Support: IE <=9 - 11 only + // IE returns zIndex value as an integer. + ret + "" : + ret; +} + + +function addGetHookIf( conditionFn, hookFn ) { + + // Define the hook, we'll check on the first run if it's really needed. + return { + get: function() { + if ( conditionFn() ) { + + // Hook not needed (or it's not possible to use it due + // to missing dependency), remove it. + delete this.get; + return; + } + + // Hook needed; redefine it so that the support test is not executed again. + return ( this.get = hookFn ).apply( this, arguments ); + } + }; +} + + +var cssPrefixes = [ "Webkit", "Moz", "ms" ], + emptyStyle = document.createElement( "div" ).style, + vendorProps = {}; + +// Return a vendor-prefixed property or undefined +function vendorPropName( name ) { + + // Check for vendor prefixed names + var capName = name[ 0 ].toUpperCase() + name.slice( 1 ), + i = cssPrefixes.length; + + while ( i-- ) { + name = cssPrefixes[ i ] + capName; + if ( name in emptyStyle ) { + return name; + } + } +} + +// Return a potentially-mapped jQuery.cssProps or vendor prefixed property +function finalPropName( name ) { + var final = jQuery.cssProps[ name ] || vendorProps[ name ]; + + if ( final ) { + return final; + } + if ( name in emptyStyle ) { + return name; + } + return vendorProps[ name ] = vendorPropName( name ) || name; +} + + +var + + // Swappable if display is none or starts with table + // except "table", "table-cell", or "table-caption" + // See here for display values: https://developer.mozilla.org/en-US/docs/CSS/display + rdisplayswap = /^(none|table(?!-c[ea]).+)/, + rcustomProp = /^--/, + cssShow = { position: "absolute", visibility: "hidden", display: "block" }, + cssNormalTransform = { + letterSpacing: "0", + fontWeight: "400" + }; + +function setPositiveNumber( _elem, value, subtract ) { + + // Any relative (+/-) values have already been + // normalized at this point + var matches = rcssNum.exec( value ); + return matches ? + + // Guard against undefined "subtract", e.g., when used as in cssHooks + Math.max( 0, matches[ 2 ] - ( subtract || 0 ) ) + ( matches[ 3 ] || "px" ) : + value; +} + +function boxModelAdjustment( elem, dimension, box, isBorderBox, styles, computedVal ) { + var i = dimension === "width" ? 1 : 0, + extra = 0, + delta = 0; + + // Adjustment may not be necessary + if ( box === ( isBorderBox ? "border" : "content" ) ) { + return 0; + } + + for ( ; i < 4; i += 2 ) { + + // Both box models exclude margin + if ( box === "margin" ) { + delta += jQuery.css( elem, box + cssExpand[ i ], true, styles ); + } + + // If we get here with a content-box, we're seeking "padding" or "border" or "margin" + if ( !isBorderBox ) { + + // Add padding + delta += jQuery.css( elem, "padding" + cssExpand[ i ], true, styles ); + + // For "border" or "margin", add border + if ( box !== "padding" ) { + delta += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); + + // But still keep track of it otherwise + } else { + extra += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); + } + + // If we get here with a border-box (content + padding + border), we're seeking "content" or + // "padding" or "margin" + } else { + + // For "content", subtract padding + if ( box === "content" ) { + delta -= jQuery.css( elem, "padding" + cssExpand[ i ], true, styles ); + } + + // For "content" or "padding", subtract border + if ( box !== "margin" ) { + delta -= jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); + } + } + } + + // Account for positive content-box scroll gutter when requested by providing computedVal + if ( !isBorderBox && computedVal >= 0 ) { + + // offsetWidth/offsetHeight is a rounded sum of content, padding, scroll gutter, and border + // Assuming integer scroll gutter, subtract the rest and round down + delta += Math.max( 0, Math.ceil( + elem[ "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ) ] - + computedVal - + delta - + extra - + 0.5 + + // If offsetWidth/offsetHeight is unknown, then we can't determine content-box scroll gutter + // Use an explicit zero to avoid NaN (gh-3964) + ) ) || 0; + } + + return delta; +} + +function getWidthOrHeight( elem, dimension, extra ) { + + // Start with computed style + var styles = getStyles( elem ), + + // To avoid forcing a reflow, only fetch boxSizing if we need it (gh-4322). + // Fake content-box until we know it's needed to know the true value. + boxSizingNeeded = !support.boxSizingReliable() || extra, + isBorderBox = boxSizingNeeded && + jQuery.css( elem, "boxSizing", false, styles ) === "border-box", + valueIsBorderBox = isBorderBox, + + val = curCSS( elem, dimension, styles ), + offsetProp = "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ); + + // Support: Firefox <=54 + // Return a confounding non-pixel value or feign ignorance, as appropriate. + if ( rnumnonpx.test( val ) ) { + if ( !extra ) { + return val; + } + val = "auto"; + } + + + // Support: IE 9 - 11 only + // Use offsetWidth/offsetHeight for when box sizing is unreliable. + // In those cases, the computed value can be trusted to be border-box. + if ( ( !support.boxSizingReliable() && isBorderBox || + + // Support: IE 10 - 11+, Edge 15 - 18+ + // IE/Edge misreport `getComputedStyle` of table rows with width/height + // set in CSS while `offset*` properties report correct values. + // Interestingly, in some cases IE 9 doesn't suffer from this issue. + !support.reliableTrDimensions() && nodeName( elem, "tr" ) || + + // Fall back to offsetWidth/offsetHeight when value is "auto" + // This happens for inline elements with no explicit setting (gh-3571) + val === "auto" || + + // Support: Android <=4.1 - 4.3 only + // Also use offsetWidth/offsetHeight for misreported inline dimensions (gh-3602) + !parseFloat( val ) && jQuery.css( elem, "display", false, styles ) === "inline" ) && + + // Make sure the element is visible & connected + elem.getClientRects().length ) { + + isBorderBox = jQuery.css( elem, "boxSizing", false, styles ) === "border-box"; + + // Where available, offsetWidth/offsetHeight approximate border box dimensions. + // Where not available (e.g., SVG), assume unreliable box-sizing and interpret the + // retrieved value as a content box dimension. + valueIsBorderBox = offsetProp in elem; + if ( valueIsBorderBox ) { + val = elem[ offsetProp ]; + } + } + + // Normalize "" and auto + val = parseFloat( val ) || 0; + + // Adjust for the element's box model + return ( val + + boxModelAdjustment( + elem, + dimension, + extra || ( isBorderBox ? "border" : "content" ), + valueIsBorderBox, + styles, + + // Provide the current computed size to request scroll gutter calculation (gh-3589) + val + ) + ) + "px"; +} + +jQuery.extend( { + + // Add in style property hooks for overriding the default + // behavior of getting and setting a style property + cssHooks: { + opacity: { + get: function( elem, computed ) { + if ( computed ) { + + // We should always get a number back from opacity + var ret = curCSS( elem, "opacity" ); + return ret === "" ? "1" : ret; + } + } + } + }, + + // Don't automatically add "px" to these possibly-unitless properties + cssNumber: { + "animationIterationCount": true, + "columnCount": true, + "fillOpacity": true, + "flexGrow": true, + "flexShrink": true, + "fontWeight": true, + "gridArea": true, + "gridColumn": true, + "gridColumnEnd": true, + "gridColumnStart": true, + "gridRow": true, + "gridRowEnd": true, + "gridRowStart": true, + "lineHeight": true, + "opacity": true, + "order": true, + "orphans": true, + "widows": true, + "zIndex": true, + "zoom": true + }, + + // Add in properties whose names you wish to fix before + // setting or getting the value + cssProps: {}, + + // Get and set the style property on a DOM Node + style: function( elem, name, value, extra ) { + + // Don't set styles on text and comment nodes + if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) { + return; + } + + // Make sure that we're working with the right name + var ret, type, hooks, + origName = camelCase( name ), + isCustomProp = rcustomProp.test( name ), + style = elem.style; + + // Make sure that we're working with the right name. We don't + // want to query the value if it is a CSS custom property + // since they are user-defined. + if ( !isCustomProp ) { + name = finalPropName( origName ); + } + + // Gets hook for the prefixed version, then unprefixed version + hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ]; + + // Check if we're setting a value + if ( value !== undefined ) { + type = typeof value; + + // Convert "+=" or "-=" to relative numbers (#7345) + if ( type === "string" && ( ret = rcssNum.exec( value ) ) && ret[ 1 ] ) { + value = adjustCSS( elem, name, ret ); + + // Fixes bug #9237 + type = "number"; + } + + // Make sure that null and NaN values aren't set (#7116) + if ( value == null || value !== value ) { + return; + } + + // If a number was passed in, add the unit (except for certain CSS properties) + // The isCustomProp check can be removed in jQuery 4.0 when we only auto-append + // "px" to a few hardcoded values. + if ( type === "number" && !isCustomProp ) { + value += ret && ret[ 3 ] || ( jQuery.cssNumber[ origName ] ? "" : "px" ); + } + + // background-* props affect original clone's values + if ( !support.clearCloneStyle && value === "" && name.indexOf( "background" ) === 0 ) { + style[ name ] = "inherit"; + } + + // If a hook was provided, use that value, otherwise just set the specified value + if ( !hooks || !( "set" in hooks ) || + ( value = hooks.set( elem, value, extra ) ) !== undefined ) { + + if ( isCustomProp ) { + style.setProperty( name, value ); + } else { + style[ name ] = value; + } + } + + } else { + + // If a hook was provided get the non-computed value from there + if ( hooks && "get" in hooks && + ( ret = hooks.get( elem, false, extra ) ) !== undefined ) { + + return ret; + } + + // Otherwise just get the value from the style object + return style[ name ]; + } + }, + + css: function( elem, name, extra, styles ) { + var val, num, hooks, + origName = camelCase( name ), + isCustomProp = rcustomProp.test( name ); + + // Make sure that we're working with the right name. We don't + // want to modify the value if it is a CSS custom property + // since they are user-defined. + if ( !isCustomProp ) { + name = finalPropName( origName ); + } + + // Try prefixed name followed by the unprefixed name + hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ]; + + // If a hook was provided get the computed value from there + if ( hooks && "get" in hooks ) { + val = hooks.get( elem, true, extra ); + } + + // Otherwise, if a way to get the computed value exists, use that + if ( val === undefined ) { + val = curCSS( elem, name, styles ); + } + + // Convert "normal" to computed value + if ( val === "normal" && name in cssNormalTransform ) { + val = cssNormalTransform[ name ]; + } + + // Make numeric if forced or a qualifier was provided and val looks numeric + if ( extra === "" || extra ) { + num = parseFloat( val ); + return extra === true || isFinite( num ) ? num || 0 : val; + } + + return val; + } +} ); + +jQuery.each( [ "height", "width" ], function( _i, dimension ) { + jQuery.cssHooks[ dimension ] = { + get: function( elem, computed, extra ) { + if ( computed ) { + + // Certain elements can have dimension info if we invisibly show them + // but it must have a current display style that would benefit + return rdisplayswap.test( jQuery.css( elem, "display" ) ) && + + // Support: Safari 8+ + // Table columns in Safari have non-zero offsetWidth & zero + // getBoundingClientRect().width unless display is changed. + // Support: IE <=11 only + // Running getBoundingClientRect on a disconnected node + // in IE throws an error. + ( !elem.getClientRects().length || !elem.getBoundingClientRect().width ) ? + swap( elem, cssShow, function() { + return getWidthOrHeight( elem, dimension, extra ); + } ) : + getWidthOrHeight( elem, dimension, extra ); + } + }, + + set: function( elem, value, extra ) { + var matches, + styles = getStyles( elem ), + + // Only read styles.position if the test has a chance to fail + // to avoid forcing a reflow. + scrollboxSizeBuggy = !support.scrollboxSize() && + styles.position === "absolute", + + // To avoid forcing a reflow, only fetch boxSizing if we need it (gh-3991) + boxSizingNeeded = scrollboxSizeBuggy || extra, + isBorderBox = boxSizingNeeded && + jQuery.css( elem, "boxSizing", false, styles ) === "border-box", + subtract = extra ? + boxModelAdjustment( + elem, + dimension, + extra, + isBorderBox, + styles + ) : + 0; + + // Account for unreliable border-box dimensions by comparing offset* to computed and + // faking a content-box to get border and padding (gh-3699) + if ( isBorderBox && scrollboxSizeBuggy ) { + subtract -= Math.ceil( + elem[ "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ) ] - + parseFloat( styles[ dimension ] ) - + boxModelAdjustment( elem, dimension, "border", false, styles ) - + 0.5 + ); + } + + // Convert to pixels if value adjustment is needed + if ( subtract && ( matches = rcssNum.exec( value ) ) && + ( matches[ 3 ] || "px" ) !== "px" ) { + + elem.style[ dimension ] = value; + value = jQuery.css( elem, dimension ); + } + + return setPositiveNumber( elem, value, subtract ); + } + }; +} ); + +jQuery.cssHooks.marginLeft = addGetHookIf( support.reliableMarginLeft, + function( elem, computed ) { + if ( computed ) { + return ( parseFloat( curCSS( elem, "marginLeft" ) ) || + elem.getBoundingClientRect().left - + swap( elem, { marginLeft: 0 }, function() { + return elem.getBoundingClientRect().left; + } ) + ) + "px"; + } + } +); + +// These hooks are used by animate to expand properties +jQuery.each( { + margin: "", + padding: "", + border: "Width" +}, function( prefix, suffix ) { + jQuery.cssHooks[ prefix + suffix ] = { + expand: function( value ) { + var i = 0, + expanded = {}, + + // Assumes a single number if not a string + parts = typeof value === "string" ? value.split( " " ) : [ value ]; + + for ( ; i < 4; i++ ) { + expanded[ prefix + cssExpand[ i ] + suffix ] = + parts[ i ] || parts[ i - 2 ] || parts[ 0 ]; + } + + return expanded; + } + }; + + if ( prefix !== "margin" ) { + jQuery.cssHooks[ prefix + suffix ].set = setPositiveNumber; + } +} ); + +jQuery.fn.extend( { + css: function( name, value ) { + return access( this, function( elem, name, value ) { + var styles, len, + map = {}, + i = 0; + + if ( Array.isArray( name ) ) { + styles = getStyles( elem ); + len = name.length; + + for ( ; i < len; i++ ) { + map[ name[ i ] ] = jQuery.css( elem, name[ i ], false, styles ); + } + + return map; + } + + return value !== undefined ? + jQuery.style( elem, name, value ) : + jQuery.css( elem, name ); + }, name, value, arguments.length > 1 ); + } +} ); + + +function Tween( elem, options, prop, end, easing ) { + return new Tween.prototype.init( elem, options, prop, end, easing ); +} +jQuery.Tween = Tween; + +Tween.prototype = { + constructor: Tween, + init: function( elem, options, prop, end, easing, unit ) { + this.elem = elem; + this.prop = prop; + this.easing = easing || jQuery.easing._default; + this.options = options; + this.start = this.now = this.cur(); + this.end = end; + this.unit = unit || ( jQuery.cssNumber[ prop ] ? "" : "px" ); + }, + cur: function() { + var hooks = Tween.propHooks[ this.prop ]; + + return hooks && hooks.get ? + hooks.get( this ) : + Tween.propHooks._default.get( this ); + }, + run: function( percent ) { + var eased, + hooks = Tween.propHooks[ this.prop ]; + + if ( this.options.duration ) { + this.pos = eased = jQuery.easing[ this.easing ]( + percent, this.options.duration * percent, 0, 1, this.options.duration + ); + } else { + this.pos = eased = percent; + } + this.now = ( this.end - this.start ) * eased + this.start; + + if ( this.options.step ) { + this.options.step.call( this.elem, this.now, this ); + } + + if ( hooks && hooks.set ) { + hooks.set( this ); + } else { + Tween.propHooks._default.set( this ); + } + return this; + } +}; + +Tween.prototype.init.prototype = Tween.prototype; + +Tween.propHooks = { + _default: { + get: function( tween ) { + var result; + + // Use a property on the element directly when it is not a DOM element, + // or when there is no matching style property that exists. + if ( tween.elem.nodeType !== 1 || + tween.elem[ tween.prop ] != null && tween.elem.style[ tween.prop ] == null ) { + return tween.elem[ tween.prop ]; + } + + // Passing an empty string as a 3rd parameter to .css will automatically + // attempt a parseFloat and fallback to a string if the parse fails. + // Simple values such as "10px" are parsed to Float; + // complex values such as "rotate(1rad)" are returned as-is. + result = jQuery.css( tween.elem, tween.prop, "" ); + + // Empty strings, null, undefined and "auto" are converted to 0. + return !result || result === "auto" ? 0 : result; + }, + set: function( tween ) { + + // Use step hook for back compat. + // Use cssHook if its there. + // Use .style if available and use plain properties where available. + if ( jQuery.fx.step[ tween.prop ] ) { + jQuery.fx.step[ tween.prop ]( tween ); + } else if ( tween.elem.nodeType === 1 && ( + jQuery.cssHooks[ tween.prop ] || + tween.elem.style[ finalPropName( tween.prop ) ] != null ) ) { + jQuery.style( tween.elem, tween.prop, tween.now + tween.unit ); + } else { + tween.elem[ tween.prop ] = tween.now; + } + } + } +}; + +// Support: IE <=9 only +// Panic based approach to setting things on disconnected nodes +Tween.propHooks.scrollTop = Tween.propHooks.scrollLeft = { + set: function( tween ) { + if ( tween.elem.nodeType && tween.elem.parentNode ) { + tween.elem[ tween.prop ] = tween.now; + } + } +}; + +jQuery.easing = { + linear: function( p ) { + return p; + }, + swing: function( p ) { + return 0.5 - Math.cos( p * Math.PI ) / 2; + }, + _default: "swing" +}; + +jQuery.fx = Tween.prototype.init; + +// Back compat <1.8 extension point +jQuery.fx.step = {}; + + + + +var + fxNow, inProgress, + rfxtypes = /^(?:toggle|show|hide)$/, + rrun = /queueHooks$/; + +function schedule() { + if ( inProgress ) { + if ( document.hidden === false && window.requestAnimationFrame ) { + window.requestAnimationFrame( schedule ); + } else { + window.setTimeout( schedule, jQuery.fx.interval ); + } + + jQuery.fx.tick(); + } +} + +// Animations created synchronously will run synchronously +function createFxNow() { + window.setTimeout( function() { + fxNow = undefined; + } ); + return ( fxNow = Date.now() ); +} + +// Generate parameters to create a standard animation +function genFx( type, includeWidth ) { + var which, + i = 0, + attrs = { height: type }; + + // If we include width, step value is 1 to do all cssExpand values, + // otherwise step value is 2 to skip over Left and Right + includeWidth = includeWidth ? 1 : 0; + for ( ; i < 4; i += 2 - includeWidth ) { + which = cssExpand[ i ]; + attrs[ "margin" + which ] = attrs[ "padding" + which ] = type; + } + + if ( includeWidth ) { + attrs.opacity = attrs.width = type; + } + + return attrs; +} + +function createTween( value, prop, animation ) { + var tween, + collection = ( Animation.tweeners[ prop ] || [] ).concat( Animation.tweeners[ "*" ] ), + index = 0, + length = collection.length; + for ( ; index < length; index++ ) { + if ( ( tween = collection[ index ].call( animation, prop, value ) ) ) { + + // We're done with this property + return tween; + } + } +} + +function defaultPrefilter( elem, props, opts ) { + var prop, value, toggle, hooks, oldfire, propTween, restoreDisplay, display, + isBox = "width" in props || "height" in props, + anim = this, + orig = {}, + style = elem.style, + hidden = elem.nodeType && isHiddenWithinTree( elem ), + dataShow = dataPriv.get( elem, "fxshow" ); + + // Queue-skipping animations hijack the fx hooks + if ( !opts.queue ) { + hooks = jQuery._queueHooks( elem, "fx" ); + if ( hooks.unqueued == null ) { + hooks.unqueued = 0; + oldfire = hooks.empty.fire; + hooks.empty.fire = function() { + if ( !hooks.unqueued ) { + oldfire(); + } + }; + } + hooks.unqueued++; + + anim.always( function() { + + // Ensure the complete handler is called before this completes + anim.always( function() { + hooks.unqueued--; + if ( !jQuery.queue( elem, "fx" ).length ) { + hooks.empty.fire(); + } + } ); + } ); + } + + // Detect show/hide animations + for ( prop in props ) { + value = props[ prop ]; + if ( rfxtypes.test( value ) ) { + delete props[ prop ]; + toggle = toggle || value === "toggle"; + if ( value === ( hidden ? "hide" : "show" ) ) { + + // Pretend to be hidden if this is a "show" and + // there is still data from a stopped show/hide + if ( value === "show" && dataShow && dataShow[ prop ] !== undefined ) { + hidden = true; + + // Ignore all other no-op show/hide data + } else { + continue; + } + } + orig[ prop ] = dataShow && dataShow[ prop ] || jQuery.style( elem, prop ); + } + } + + // Bail out if this is a no-op like .hide().hide() + propTween = !jQuery.isEmptyObject( props ); + if ( !propTween && jQuery.isEmptyObject( orig ) ) { + return; + } + + // Restrict "overflow" and "display" styles during box animations + if ( isBox && elem.nodeType === 1 ) { + + // Support: IE <=9 - 11, Edge 12 - 15 + // Record all 3 overflow attributes because IE does not infer the shorthand + // from identically-valued overflowX and overflowY and Edge just mirrors + // the overflowX value there. + opts.overflow = [ style.overflow, style.overflowX, style.overflowY ]; + + // Identify a display type, preferring old show/hide data over the CSS cascade + restoreDisplay = dataShow && dataShow.display; + if ( restoreDisplay == null ) { + restoreDisplay = dataPriv.get( elem, "display" ); + } + display = jQuery.css( elem, "display" ); + if ( display === "none" ) { + if ( restoreDisplay ) { + display = restoreDisplay; + } else { + + // Get nonempty value(s) by temporarily forcing visibility + showHide( [ elem ], true ); + restoreDisplay = elem.style.display || restoreDisplay; + display = jQuery.css( elem, "display" ); + showHide( [ elem ] ); + } + } + + // Animate inline elements as inline-block + if ( display === "inline" || display === "inline-block" && restoreDisplay != null ) { + if ( jQuery.css( elem, "float" ) === "none" ) { + + // Restore the original display value at the end of pure show/hide animations + if ( !propTween ) { + anim.done( function() { + style.display = restoreDisplay; + } ); + if ( restoreDisplay == null ) { + display = style.display; + restoreDisplay = display === "none" ? "" : display; + } + } + style.display = "inline-block"; + } + } + } + + if ( opts.overflow ) { + style.overflow = "hidden"; + anim.always( function() { + style.overflow = opts.overflow[ 0 ]; + style.overflowX = opts.overflow[ 1 ]; + style.overflowY = opts.overflow[ 2 ]; + } ); + } + + // Implement show/hide animations + propTween = false; + for ( prop in orig ) { + + // General show/hide setup for this element animation + if ( !propTween ) { + if ( dataShow ) { + if ( "hidden" in dataShow ) { + hidden = dataShow.hidden; + } + } else { + dataShow = dataPriv.access( elem, "fxshow", { display: restoreDisplay } ); + } + + // Store hidden/visible for toggle so `.stop().toggle()` "reverses" + if ( toggle ) { + dataShow.hidden = !hidden; + } + + // Show elements before animating them + if ( hidden ) { + showHide( [ elem ], true ); + } + + /* eslint-disable no-loop-func */ + + anim.done( function() { + + /* eslint-enable no-loop-func */ + + // The final step of a "hide" animation is actually hiding the element + if ( !hidden ) { + showHide( [ elem ] ); + } + dataPriv.remove( elem, "fxshow" ); + for ( prop in orig ) { + jQuery.style( elem, prop, orig[ prop ] ); + } + } ); + } + + // Per-property setup + propTween = createTween( hidden ? dataShow[ prop ] : 0, prop, anim ); + if ( !( prop in dataShow ) ) { + dataShow[ prop ] = propTween.start; + if ( hidden ) { + propTween.end = propTween.start; + propTween.start = 0; + } + } + } +} + +function propFilter( props, specialEasing ) { + var index, name, easing, value, hooks; + + // camelCase, specialEasing and expand cssHook pass + for ( index in props ) { + name = camelCase( index ); + easing = specialEasing[ name ]; + value = props[ index ]; + if ( Array.isArray( value ) ) { + easing = value[ 1 ]; + value = props[ index ] = value[ 0 ]; + } + + if ( index !== name ) { + props[ name ] = value; + delete props[ index ]; + } + + hooks = jQuery.cssHooks[ name ]; + if ( hooks && "expand" in hooks ) { + value = hooks.expand( value ); + delete props[ name ]; + + // Not quite $.extend, this won't overwrite existing keys. + // Reusing 'index' because we have the correct "name" + for ( index in value ) { + if ( !( index in props ) ) { + props[ index ] = value[ index ]; + specialEasing[ index ] = easing; + } + } + } else { + specialEasing[ name ] = easing; + } + } +} + +function Animation( elem, properties, options ) { + var result, + stopped, + index = 0, + length = Animation.prefilters.length, + deferred = jQuery.Deferred().always( function() { + + // Don't match elem in the :animated selector + delete tick.elem; + } ), + tick = function() { + if ( stopped ) { + return false; + } + var currentTime = fxNow || createFxNow(), + remaining = Math.max( 0, animation.startTime + animation.duration - currentTime ), + + // Support: Android 2.3 only + // Archaic crash bug won't allow us to use `1 - ( 0.5 || 0 )` (#12497) + temp = remaining / animation.duration || 0, + percent = 1 - temp, + index = 0, + length = animation.tweens.length; + + for ( ; index < length; index++ ) { + animation.tweens[ index ].run( percent ); + } + + deferred.notifyWith( elem, [ animation, percent, remaining ] ); + + // If there's more to do, yield + if ( percent < 1 && length ) { + return remaining; + } + + // If this was an empty animation, synthesize a final progress notification + if ( !length ) { + deferred.notifyWith( elem, [ animation, 1, 0 ] ); + } + + // Resolve the animation and report its conclusion + deferred.resolveWith( elem, [ animation ] ); + return false; + }, + animation = deferred.promise( { + elem: elem, + props: jQuery.extend( {}, properties ), + opts: jQuery.extend( true, { + specialEasing: {}, + easing: jQuery.easing._default + }, options ), + originalProperties: properties, + originalOptions: options, + startTime: fxNow || createFxNow(), + duration: options.duration, + tweens: [], + createTween: function( prop, end ) { + var tween = jQuery.Tween( elem, animation.opts, prop, end, + animation.opts.specialEasing[ prop ] || animation.opts.easing ); + animation.tweens.push( tween ); + return tween; + }, + stop: function( gotoEnd ) { + var index = 0, + + // If we are going to the end, we want to run all the tweens + // otherwise we skip this part + length = gotoEnd ? animation.tweens.length : 0; + if ( stopped ) { + return this; + } + stopped = true; + for ( ; index < length; index++ ) { + animation.tweens[ index ].run( 1 ); + } + + // Resolve when we played the last frame; otherwise, reject + if ( gotoEnd ) { + deferred.notifyWith( elem, [ animation, 1, 0 ] ); + deferred.resolveWith( elem, [ animation, gotoEnd ] ); + } else { + deferred.rejectWith( elem, [ animation, gotoEnd ] ); + } + return this; + } + } ), + props = animation.props; + + propFilter( props, animation.opts.specialEasing ); + + for ( ; index < length; index++ ) { + result = Animation.prefilters[ index ].call( animation, elem, props, animation.opts ); + if ( result ) { + if ( isFunction( result.stop ) ) { + jQuery._queueHooks( animation.elem, animation.opts.queue ).stop = + result.stop.bind( result ); + } + return result; + } + } + + jQuery.map( props, createTween, animation ); + + if ( isFunction( animation.opts.start ) ) { + animation.opts.start.call( elem, animation ); + } + + // Attach callbacks from options + animation + .progress( animation.opts.progress ) + .done( animation.opts.done, animation.opts.complete ) + .fail( animation.opts.fail ) + .always( animation.opts.always ); + + jQuery.fx.timer( + jQuery.extend( tick, { + elem: elem, + anim: animation, + queue: animation.opts.queue + } ) + ); + + return animation; +} + +jQuery.Animation = jQuery.extend( Animation, { + + tweeners: { + "*": [ function( prop, value ) { + var tween = this.createTween( prop, value ); + adjustCSS( tween.elem, prop, rcssNum.exec( value ), tween ); + return tween; + } ] + }, + + tweener: function( props, callback ) { + if ( isFunction( props ) ) { + callback = props; + props = [ "*" ]; + } else { + props = props.match( rnothtmlwhite ); + } + + var prop, + index = 0, + length = props.length; + + for ( ; index < length; index++ ) { + prop = props[ index ]; + Animation.tweeners[ prop ] = Animation.tweeners[ prop ] || []; + Animation.tweeners[ prop ].unshift( callback ); + } + }, + + prefilters: [ defaultPrefilter ], + + prefilter: function( callback, prepend ) { + if ( prepend ) { + Animation.prefilters.unshift( callback ); + } else { + Animation.prefilters.push( callback ); + } + } +} ); + +jQuery.speed = function( speed, easing, fn ) { + var opt = speed && typeof speed === "object" ? jQuery.extend( {}, speed ) : { + complete: fn || !fn && easing || + isFunction( speed ) && speed, + duration: speed, + easing: fn && easing || easing && !isFunction( easing ) && easing + }; + + // Go to the end state if fx are off + if ( jQuery.fx.off ) { + opt.duration = 0; + + } else { + if ( typeof opt.duration !== "number" ) { + if ( opt.duration in jQuery.fx.speeds ) { + opt.duration = jQuery.fx.speeds[ opt.duration ]; + + } else { + opt.duration = jQuery.fx.speeds._default; + } + } + } + + // Normalize opt.queue - true/undefined/null -> "fx" + if ( opt.queue == null || opt.queue === true ) { + opt.queue = "fx"; + } + + // Queueing + opt.old = opt.complete; + + opt.complete = function() { + if ( isFunction( opt.old ) ) { + opt.old.call( this ); + } + + if ( opt.queue ) { + jQuery.dequeue( this, opt.queue ); + } + }; + + return opt; +}; + +jQuery.fn.extend( { + fadeTo: function( speed, to, easing, callback ) { + + // Show any hidden elements after setting opacity to 0 + return this.filter( isHiddenWithinTree ).css( "opacity", 0 ).show() + + // Animate to the value specified + .end().animate( { opacity: to }, speed, easing, callback ); + }, + animate: function( prop, speed, easing, callback ) { + var empty = jQuery.isEmptyObject( prop ), + optall = jQuery.speed( speed, easing, callback ), + doAnimation = function() { + + // Operate on a copy of prop so per-property easing won't be lost + var anim = Animation( this, jQuery.extend( {}, prop ), optall ); + + // Empty animations, or finishing resolves immediately + if ( empty || dataPriv.get( this, "finish" ) ) { + anim.stop( true ); + } + }; + doAnimation.finish = doAnimation; + + return empty || optall.queue === false ? + this.each( doAnimation ) : + this.queue( optall.queue, doAnimation ); + }, + stop: function( type, clearQueue, gotoEnd ) { + var stopQueue = function( hooks ) { + var stop = hooks.stop; + delete hooks.stop; + stop( gotoEnd ); + }; + + if ( typeof type !== "string" ) { + gotoEnd = clearQueue; + clearQueue = type; + type = undefined; + } + if ( clearQueue ) { + this.queue( type || "fx", [] ); + } + + return this.each( function() { + var dequeue = true, + index = type != null && type + "queueHooks", + timers = jQuery.timers, + data = dataPriv.get( this ); + + if ( index ) { + if ( data[ index ] && data[ index ].stop ) { + stopQueue( data[ index ] ); + } + } else { + for ( index in data ) { + if ( data[ index ] && data[ index ].stop && rrun.test( index ) ) { + stopQueue( data[ index ] ); + } + } + } + + for ( index = timers.length; index--; ) { + if ( timers[ index ].elem === this && + ( type == null || timers[ index ].queue === type ) ) { + + timers[ index ].anim.stop( gotoEnd ); + dequeue = false; + timers.splice( index, 1 ); + } + } + + // Start the next in the queue if the last step wasn't forced. + // Timers currently will call their complete callbacks, which + // will dequeue but only if they were gotoEnd. + if ( dequeue || !gotoEnd ) { + jQuery.dequeue( this, type ); + } + } ); + }, + finish: function( type ) { + if ( type !== false ) { + type = type || "fx"; + } + return this.each( function() { + var index, + data = dataPriv.get( this ), + queue = data[ type + "queue" ], + hooks = data[ type + "queueHooks" ], + timers = jQuery.timers, + length = queue ? queue.length : 0; + + // Enable finishing flag on private data + data.finish = true; + + // Empty the queue first + jQuery.queue( this, type, [] ); + + if ( hooks && hooks.stop ) { + hooks.stop.call( this, true ); + } + + // Look for any active animations, and finish them + for ( index = timers.length; index--; ) { + if ( timers[ index ].elem === this && timers[ index ].queue === type ) { + timers[ index ].anim.stop( true ); + timers.splice( index, 1 ); + } + } + + // Look for any animations in the old queue and finish them + for ( index = 0; index < length; index++ ) { + if ( queue[ index ] && queue[ index ].finish ) { + queue[ index ].finish.call( this ); + } + } + + // Turn off finishing flag + delete data.finish; + } ); + } +} ); + +jQuery.each( [ "toggle", "show", "hide" ], function( _i, name ) { + var cssFn = jQuery.fn[ name ]; + jQuery.fn[ name ] = function( speed, easing, callback ) { + return speed == null || typeof speed === "boolean" ? + cssFn.apply( this, arguments ) : + this.animate( genFx( name, true ), speed, easing, callback ); + }; +} ); + +// Generate shortcuts for custom animations +jQuery.each( { + slideDown: genFx( "show" ), + slideUp: genFx( "hide" ), + slideToggle: genFx( "toggle" ), + fadeIn: { opacity: "show" }, + fadeOut: { opacity: "hide" }, + fadeToggle: { opacity: "toggle" } +}, function( name, props ) { + jQuery.fn[ name ] = function( speed, easing, callback ) { + return this.animate( props, speed, easing, callback ); + }; +} ); + +jQuery.timers = []; +jQuery.fx.tick = function() { + var timer, + i = 0, + timers = jQuery.timers; + + fxNow = Date.now(); + + for ( ; i < timers.length; i++ ) { + timer = timers[ i ]; + + // Run the timer and safely remove it when done (allowing for external removal) + if ( !timer() && timers[ i ] === timer ) { + timers.splice( i--, 1 ); + } + } + + if ( !timers.length ) { + jQuery.fx.stop(); + } + fxNow = undefined; +}; + +jQuery.fx.timer = function( timer ) { + jQuery.timers.push( timer ); + jQuery.fx.start(); +}; + +jQuery.fx.interval = 13; +jQuery.fx.start = function() { + if ( inProgress ) { + return; + } + + inProgress = true; + schedule(); +}; + +jQuery.fx.stop = function() { + inProgress = null; +}; + +jQuery.fx.speeds = { + slow: 600, + fast: 200, + + // Default speed + _default: 400 +}; + + +// Based off of the plugin by Clint Helfers, with permission. +// https://web.archive.org/web/20100324014747/http://blindsignals.com/index.php/2009/07/jquery-delay/ +jQuery.fn.delay = function( time, type ) { + time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time; + type = type || "fx"; + + return this.queue( type, function( next, hooks ) { + var timeout = window.setTimeout( next, time ); + hooks.stop = function() { + window.clearTimeout( timeout ); + }; + } ); +}; + + +( function() { + var input = document.createElement( "input" ), + select = document.createElement( "select" ), + opt = select.appendChild( document.createElement( "option" ) ); + + input.type = "checkbox"; + + // Support: Android <=4.3 only + // Default value for a checkbox should be "on" + support.checkOn = input.value !== ""; + + // Support: IE <=11 only + // Must access selectedIndex to make default options select + support.optSelected = opt.selected; + + // Support: IE <=11 only + // An input loses its value after becoming a radio + input = document.createElement( "input" ); + input.value = "t"; + input.type = "radio"; + support.radioValue = input.value === "t"; +} )(); + + +var boolHook, + attrHandle = jQuery.expr.attrHandle; + +jQuery.fn.extend( { + attr: function( name, value ) { + return access( this, jQuery.attr, name, value, arguments.length > 1 ); + }, + + removeAttr: function( name ) { + return this.each( function() { + jQuery.removeAttr( this, name ); + } ); + } +} ); + +jQuery.extend( { + attr: function( elem, name, value ) { + var ret, hooks, + nType = elem.nodeType; + + // Don't get/set attributes on text, comment and attribute nodes + if ( nType === 3 || nType === 8 || nType === 2 ) { + return; + } + + // Fallback to prop when attributes are not supported + if ( typeof elem.getAttribute === "undefined" ) { + return jQuery.prop( elem, name, value ); + } + + // Attribute hooks are determined by the lowercase version + // Grab necessary hook if one is defined + if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) { + hooks = jQuery.attrHooks[ name.toLowerCase() ] || + ( jQuery.expr.match.bool.test( name ) ? boolHook : undefined ); + } + + if ( value !== undefined ) { + if ( value === null ) { + jQuery.removeAttr( elem, name ); + return; + } + + if ( hooks && "set" in hooks && + ( ret = hooks.set( elem, value, name ) ) !== undefined ) { + return ret; + } + + elem.setAttribute( name, value + "" ); + return value; + } + + if ( hooks && "get" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) { + return ret; + } + + ret = jQuery.find.attr( elem, name ); + + // Non-existent attributes return null, we normalize to undefined + return ret == null ? undefined : ret; + }, + + attrHooks: { + type: { + set: function( elem, value ) { + if ( !support.radioValue && value === "radio" && + nodeName( elem, "input" ) ) { + var val = elem.value; + elem.setAttribute( "type", value ); + if ( val ) { + elem.value = val; + } + return value; + } + } + } + }, + + removeAttr: function( elem, value ) { + var name, + i = 0, + + // Attribute names can contain non-HTML whitespace characters + // https://html.spec.whatwg.org/multipage/syntax.html#attributes-2 + attrNames = value && value.match( rnothtmlwhite ); + + if ( attrNames && elem.nodeType === 1 ) { + while ( ( name = attrNames[ i++ ] ) ) { + elem.removeAttribute( name ); + } + } + } +} ); + +// Hooks for boolean attributes +boolHook = { + set: function( elem, value, name ) { + if ( value === false ) { + + // Remove boolean attributes when set to false + jQuery.removeAttr( elem, name ); + } else { + elem.setAttribute( name, name ); + } + return name; + } +}; + +jQuery.each( jQuery.expr.match.bool.source.match( /\w+/g ), function( _i, name ) { + var getter = attrHandle[ name ] || jQuery.find.attr; + + attrHandle[ name ] = function( elem, name, isXML ) { + var ret, handle, + lowercaseName = name.toLowerCase(); + + if ( !isXML ) { + + // Avoid an infinite loop by temporarily removing this function from the getter + handle = attrHandle[ lowercaseName ]; + attrHandle[ lowercaseName ] = ret; + ret = getter( elem, name, isXML ) != null ? + lowercaseName : + null; + attrHandle[ lowercaseName ] = handle; + } + return ret; + }; +} ); + + + + +var rfocusable = /^(?:input|select|textarea|button)$/i, + rclickable = /^(?:a|area)$/i; + +jQuery.fn.extend( { + prop: function( name, value ) { + return access( this, jQuery.prop, name, value, arguments.length > 1 ); + }, + + removeProp: function( name ) { + return this.each( function() { + delete this[ jQuery.propFix[ name ] || name ]; + } ); + } +} ); + +jQuery.extend( { + prop: function( elem, name, value ) { + var ret, hooks, + nType = elem.nodeType; + + // Don't get/set properties on text, comment and attribute nodes + if ( nType === 3 || nType === 8 || nType === 2 ) { + return; + } + + if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) { + + // Fix name and attach hooks + name = jQuery.propFix[ name ] || name; + hooks = jQuery.propHooks[ name ]; + } + + if ( value !== undefined ) { + if ( hooks && "set" in hooks && + ( ret = hooks.set( elem, value, name ) ) !== undefined ) { + return ret; + } + + return ( elem[ name ] = value ); + } + + if ( hooks && "get" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) { + return ret; + } + + return elem[ name ]; + }, + + propHooks: { + tabIndex: { + get: function( elem ) { + + // Support: IE <=9 - 11 only + // elem.tabIndex doesn't always return the + // correct value when it hasn't been explicitly set + // https://web.archive.org/web/20141116233347/http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/ + // Use proper attribute retrieval(#12072) + var tabindex = jQuery.find.attr( elem, "tabindex" ); + + if ( tabindex ) { + return parseInt( tabindex, 10 ); + } + + if ( + rfocusable.test( elem.nodeName ) || + rclickable.test( elem.nodeName ) && + elem.href + ) { + return 0; + } + + return -1; + } + } + }, + + propFix: { + "for": "htmlFor", + "class": "className" + } +} ); + +// Support: IE <=11 only +// Accessing the selectedIndex property +// forces the browser to respect setting selected +// on the option +// The getter ensures a default option is selected +// when in an optgroup +// eslint rule "no-unused-expressions" is disabled for this code +// since it considers such accessions noop +if ( !support.optSelected ) { + jQuery.propHooks.selected = { + get: function( elem ) { + + /* eslint no-unused-expressions: "off" */ + + var parent = elem.parentNode; + if ( parent && parent.parentNode ) { + parent.parentNode.selectedIndex; + } + return null; + }, + set: function( elem ) { + + /* eslint no-unused-expressions: "off" */ + + var parent = elem.parentNode; + if ( parent ) { + parent.selectedIndex; + + if ( parent.parentNode ) { + parent.parentNode.selectedIndex; + } + } + } + }; +} + +jQuery.each( [ + "tabIndex", + "readOnly", + "maxLength", + "cellSpacing", + "cellPadding", + "rowSpan", + "colSpan", + "useMap", + "frameBorder", + "contentEditable" +], function() { + jQuery.propFix[ this.toLowerCase() ] = this; +} ); + + + + + // Strip and collapse whitespace according to HTML spec + // https://infra.spec.whatwg.org/#strip-and-collapse-ascii-whitespace + function stripAndCollapse( value ) { + var tokens = value.match( rnothtmlwhite ) || []; + return tokens.join( " " ); + } + + +function getClass( elem ) { + return elem.getAttribute && elem.getAttribute( "class" ) || ""; +} + +function classesToArray( value ) { + if ( Array.isArray( value ) ) { + return value; + } + if ( typeof value === "string" ) { + return value.match( rnothtmlwhite ) || []; + } + return []; +} + +jQuery.fn.extend( { + addClass: function( value ) { + var classes, elem, cur, curValue, clazz, j, finalValue, + i = 0; + + if ( isFunction( value ) ) { + return this.each( function( j ) { + jQuery( this ).addClass( value.call( this, j, getClass( this ) ) ); + } ); + } + + classes = classesToArray( value ); + + if ( classes.length ) { + while ( ( elem = this[ i++ ] ) ) { + curValue = getClass( elem ); + cur = elem.nodeType === 1 && ( " " + stripAndCollapse( curValue ) + " " ); + + if ( cur ) { + j = 0; + while ( ( clazz = classes[ j++ ] ) ) { + if ( cur.indexOf( " " + clazz + " " ) < 0 ) { + cur += clazz + " "; + } + } + + // Only assign if different to avoid unneeded rendering. + finalValue = stripAndCollapse( cur ); + if ( curValue !== finalValue ) { + elem.setAttribute( "class", finalValue ); + } + } + } + } + + return this; + }, + + removeClass: function( value ) { + var classes, elem, cur, curValue, clazz, j, finalValue, + i = 0; + + if ( isFunction( value ) ) { + return this.each( function( j ) { + jQuery( this ).removeClass( value.call( this, j, getClass( this ) ) ); + } ); + } + + if ( !arguments.length ) { + return this.attr( "class", "" ); + } + + classes = classesToArray( value ); + + if ( classes.length ) { + while ( ( elem = this[ i++ ] ) ) { + curValue = getClass( elem ); + + // This expression is here for better compressibility (see addClass) + cur = elem.nodeType === 1 && ( " " + stripAndCollapse( curValue ) + " " ); + + if ( cur ) { + j = 0; + while ( ( clazz = classes[ j++ ] ) ) { + + // Remove *all* instances + while ( cur.indexOf( " " + clazz + " " ) > -1 ) { + cur = cur.replace( " " + clazz + " ", " " ); + } + } + + // Only assign if different to avoid unneeded rendering. + finalValue = stripAndCollapse( cur ); + if ( curValue !== finalValue ) { + elem.setAttribute( "class", finalValue ); + } + } + } + } + + return this; + }, + + toggleClass: function( value, stateVal ) { + var type = typeof value, + isValidValue = type === "string" || Array.isArray( value ); + + if ( typeof stateVal === "boolean" && isValidValue ) { + return stateVal ? this.addClass( value ) : this.removeClass( value ); + } + + if ( isFunction( value ) ) { + return this.each( function( i ) { + jQuery( this ).toggleClass( + value.call( this, i, getClass( this ), stateVal ), + stateVal + ); + } ); + } + + return this.each( function() { + var className, i, self, classNames; + + if ( isValidValue ) { + + // Toggle individual class names + i = 0; + self = jQuery( this ); + classNames = classesToArray( value ); + + while ( ( className = classNames[ i++ ] ) ) { + + // Check each className given, space separated list + if ( self.hasClass( className ) ) { + self.removeClass( className ); + } else { + self.addClass( className ); + } + } + + // Toggle whole class name + } else if ( value === undefined || type === "boolean" ) { + className = getClass( this ); + if ( className ) { + + // Store className if set + dataPriv.set( this, "__className__", className ); + } + + // If the element has a class name or if we're passed `false`, + // then remove the whole classname (if there was one, the above saved it). + // Otherwise bring back whatever was previously saved (if anything), + // falling back to the empty string if nothing was stored. + if ( this.setAttribute ) { + this.setAttribute( "class", + className || value === false ? + "" : + dataPriv.get( this, "__className__" ) || "" + ); + } + } + } ); + }, + + hasClass: function( selector ) { + var className, elem, + i = 0; + + className = " " + selector + " "; + while ( ( elem = this[ i++ ] ) ) { + if ( elem.nodeType === 1 && + ( " " + stripAndCollapse( getClass( elem ) ) + " " ).indexOf( className ) > -1 ) { + return true; + } + } + + return false; + } +} ); + + + + +var rreturn = /\r/g; + +jQuery.fn.extend( { + val: function( value ) { + var hooks, ret, valueIsFunction, + elem = this[ 0 ]; + + if ( !arguments.length ) { + if ( elem ) { + hooks = jQuery.valHooks[ elem.type ] || + jQuery.valHooks[ elem.nodeName.toLowerCase() ]; + + if ( hooks && + "get" in hooks && + ( ret = hooks.get( elem, "value" ) ) !== undefined + ) { + return ret; + } + + ret = elem.value; + + // Handle most common string cases + if ( typeof ret === "string" ) { + return ret.replace( rreturn, "" ); + } + + // Handle cases where value is null/undef or number + return ret == null ? "" : ret; + } + + return; + } + + valueIsFunction = isFunction( value ); + + return this.each( function( i ) { + var val; + + if ( this.nodeType !== 1 ) { + return; + } + + if ( valueIsFunction ) { + val = value.call( this, i, jQuery( this ).val() ); + } else { + val = value; + } + + // Treat null/undefined as ""; convert numbers to string + if ( val == null ) { + val = ""; + + } else if ( typeof val === "number" ) { + val += ""; + + } else if ( Array.isArray( val ) ) { + val = jQuery.map( val, function( value ) { + return value == null ? "" : value + ""; + } ); + } + + hooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ]; + + // If set returns undefined, fall back to normal setting + if ( !hooks || !( "set" in hooks ) || hooks.set( this, val, "value" ) === undefined ) { + this.value = val; + } + } ); + } +} ); + +jQuery.extend( { + valHooks: { + option: { + get: function( elem ) { + + var val = jQuery.find.attr( elem, "value" ); + return val != null ? + val : + + // Support: IE <=10 - 11 only + // option.text throws exceptions (#14686, #14858) + // Strip and collapse whitespace + // https://html.spec.whatwg.org/#strip-and-collapse-whitespace + stripAndCollapse( jQuery.text( elem ) ); + } + }, + select: { + get: function( elem ) { + var value, option, i, + options = elem.options, + index = elem.selectedIndex, + one = elem.type === "select-one", + values = one ? null : [], + max = one ? index + 1 : options.length; + + if ( index < 0 ) { + i = max; + + } else { + i = one ? index : 0; + } + + // Loop through all the selected options + for ( ; i < max; i++ ) { + option = options[ i ]; + + // Support: IE <=9 only + // IE8-9 doesn't update selected after form reset (#2551) + if ( ( option.selected || i === index ) && + + // Don't return options that are disabled or in a disabled optgroup + !option.disabled && + ( !option.parentNode.disabled || + !nodeName( option.parentNode, "optgroup" ) ) ) { + + // Get the specific value for the option + value = jQuery( option ).val(); + + // We don't need an array for one selects + if ( one ) { + return value; + } + + // Multi-Selects return an array + values.push( value ); + } + } + + return values; + }, + + set: function( elem, value ) { + var optionSet, option, + options = elem.options, + values = jQuery.makeArray( value ), + i = options.length; + + while ( i-- ) { + option = options[ i ]; + + /* eslint-disable no-cond-assign */ + + if ( option.selected = + jQuery.inArray( jQuery.valHooks.option.get( option ), values ) > -1 + ) { + optionSet = true; + } + + /* eslint-enable no-cond-assign */ + } + + // Force browsers to behave consistently when non-matching value is set + if ( !optionSet ) { + elem.selectedIndex = -1; + } + return values; + } + } + } +} ); + +// Radios and checkboxes getter/setter +jQuery.each( [ "radio", "checkbox" ], function() { + jQuery.valHooks[ this ] = { + set: function( elem, value ) { + if ( Array.isArray( value ) ) { + return ( elem.checked = jQuery.inArray( jQuery( elem ).val(), value ) > -1 ); + } + } + }; + if ( !support.checkOn ) { + jQuery.valHooks[ this ].get = function( elem ) { + return elem.getAttribute( "value" ) === null ? "on" : elem.value; + }; + } +} ); + + + + +// Return jQuery for attributes-only inclusion + + +support.focusin = "onfocusin" in window; + + +var rfocusMorph = /^(?:focusinfocus|focusoutblur)$/, + stopPropagationCallback = function( e ) { + e.stopPropagation(); + }; + +jQuery.extend( jQuery.event, { + + trigger: function( event, data, elem, onlyHandlers ) { + + var i, cur, tmp, bubbleType, ontype, handle, special, lastElement, + eventPath = [ elem || document ], + type = hasOwn.call( event, "type" ) ? event.type : event, + namespaces = hasOwn.call( event, "namespace" ) ? event.namespace.split( "." ) : []; + + cur = lastElement = tmp = elem = elem || document; + + // Don't do events on text and comment nodes + if ( elem.nodeType === 3 || elem.nodeType === 8 ) { + return; + } + + // focus/blur morphs to focusin/out; ensure we're not firing them right now + if ( rfocusMorph.test( type + jQuery.event.triggered ) ) { + return; + } + + if ( type.indexOf( "." ) > -1 ) { + + // Namespaced trigger; create a regexp to match event type in handle() + namespaces = type.split( "." ); + type = namespaces.shift(); + namespaces.sort(); + } + ontype = type.indexOf( ":" ) < 0 && "on" + type; + + // Caller can pass in a jQuery.Event object, Object, or just an event type string + event = event[ jQuery.expando ] ? + event : + new jQuery.Event( type, typeof event === "object" && event ); + + // Trigger bitmask: & 1 for native handlers; & 2 for jQuery (always true) + event.isTrigger = onlyHandlers ? 2 : 3; + event.namespace = namespaces.join( "." ); + event.rnamespace = event.namespace ? + new RegExp( "(^|\\.)" + namespaces.join( "\\.(?:.*\\.|)" ) + "(\\.|$)" ) : + null; + + // Clean up the event in case it is being reused + event.result = undefined; + if ( !event.target ) { + event.target = elem; + } + + // Clone any incoming data and prepend the event, creating the handler arg list + data = data == null ? + [ event ] : + jQuery.makeArray( data, [ event ] ); + + // Allow special events to draw outside the lines + special = jQuery.event.special[ type ] || {}; + if ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) { + return; + } + + // Determine event propagation path in advance, per W3C events spec (#9951) + // Bubble up to document, then to window; watch for a global ownerDocument var (#9724) + if ( !onlyHandlers && !special.noBubble && !isWindow( elem ) ) { + + bubbleType = special.delegateType || type; + if ( !rfocusMorph.test( bubbleType + type ) ) { + cur = cur.parentNode; + } + for ( ; cur; cur = cur.parentNode ) { + eventPath.push( cur ); + tmp = cur; + } + + // Only add window if we got to document (e.g., not plain obj or detached DOM) + if ( tmp === ( elem.ownerDocument || document ) ) { + eventPath.push( tmp.defaultView || tmp.parentWindow || window ); + } + } + + // Fire handlers on the event path + i = 0; + while ( ( cur = eventPath[ i++ ] ) && !event.isPropagationStopped() ) { + lastElement = cur; + event.type = i > 1 ? + bubbleType : + special.bindType || type; + + // jQuery handler + handle = ( + dataPriv.get( cur, "events" ) || Object.create( null ) + )[ event.type ] && + dataPriv.get( cur, "handle" ); + if ( handle ) { + handle.apply( cur, data ); + } + + // Native handler + handle = ontype && cur[ ontype ]; + if ( handle && handle.apply && acceptData( cur ) ) { + event.result = handle.apply( cur, data ); + if ( event.result === false ) { + event.preventDefault(); + } + } + } + event.type = type; + + // If nobody prevented the default action, do it now + if ( !onlyHandlers && !event.isDefaultPrevented() ) { + + if ( ( !special._default || + special._default.apply( eventPath.pop(), data ) === false ) && + acceptData( elem ) ) { + + // Call a native DOM method on the target with the same name as the event. + // Don't do default actions on window, that's where global variables be (#6170) + if ( ontype && isFunction( elem[ type ] ) && !isWindow( elem ) ) { + + // Don't re-trigger an onFOO event when we call its FOO() method + tmp = elem[ ontype ]; + + if ( tmp ) { + elem[ ontype ] = null; + } + + // Prevent re-triggering of the same event, since we already bubbled it above + jQuery.event.triggered = type; + + if ( event.isPropagationStopped() ) { + lastElement.addEventListener( type, stopPropagationCallback ); + } + + elem[ type ](); + + if ( event.isPropagationStopped() ) { + lastElement.removeEventListener( type, stopPropagationCallback ); + } + + jQuery.event.triggered = undefined; + + if ( tmp ) { + elem[ ontype ] = tmp; + } + } + } + } + + return event.result; + }, + + // Piggyback on a donor event to simulate a different one + // Used only for `focus(in | out)` events + simulate: function( type, elem, event ) { + var e = jQuery.extend( + new jQuery.Event(), + event, + { + type: type, + isSimulated: true + } + ); + + jQuery.event.trigger( e, null, elem ); + } + +} ); + +jQuery.fn.extend( { + + trigger: function( type, data ) { + return this.each( function() { + jQuery.event.trigger( type, data, this ); + } ); + }, + triggerHandler: function( type, data ) { + var elem = this[ 0 ]; + if ( elem ) { + return jQuery.event.trigger( type, data, elem, true ); + } + } +} ); + + +// Support: Firefox <=44 +// Firefox doesn't have focus(in | out) events +// Related ticket - https://bugzilla.mozilla.org/show_bug.cgi?id=687787 +// +// Support: Chrome <=48 - 49, Safari <=9.0 - 9.1 +// focus(in | out) events fire after focus & blur events, +// which is spec violation - http://www.w3.org/TR/DOM-Level-3-Events/#events-focusevent-event-order +// Related ticket - https://bugs.chromium.org/p/chromium/issues/detail?id=449857 +if ( !support.focusin ) { + jQuery.each( { focus: "focusin", blur: "focusout" }, function( orig, fix ) { + + // Attach a single capturing handler on the document while someone wants focusin/focusout + var handler = function( event ) { + jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ) ); + }; + + jQuery.event.special[ fix ] = { + setup: function() { + + // Handle: regular nodes (via `this.ownerDocument`), window + // (via `this.document`) & document (via `this`). + var doc = this.ownerDocument || this.document || this, + attaches = dataPriv.access( doc, fix ); + + if ( !attaches ) { + doc.addEventListener( orig, handler, true ); + } + dataPriv.access( doc, fix, ( attaches || 0 ) + 1 ); + }, + teardown: function() { + var doc = this.ownerDocument || this.document || this, + attaches = dataPriv.access( doc, fix ) - 1; + + if ( !attaches ) { + doc.removeEventListener( orig, handler, true ); + dataPriv.remove( doc, fix ); + + } else { + dataPriv.access( doc, fix, attaches ); + } + } + }; + } ); +} +var location = window.location; + +var nonce = { guid: Date.now() }; + +var rquery = ( /\?/ ); + + + +// Cross-browser xml parsing +jQuery.parseXML = function( data ) { + var xml; + if ( !data || typeof data !== "string" ) { + return null; + } + + // Support: IE 9 - 11 only + // IE throws on parseFromString with invalid input. + try { + xml = ( new window.DOMParser() ).parseFromString( data, "text/xml" ); + } catch ( e ) { + xml = undefined; + } + + if ( !xml || xml.getElementsByTagName( "parsererror" ).length ) { + jQuery.error( "Invalid XML: " + data ); + } + return xml; +}; + + +var + rbracket = /\[\]$/, + rCRLF = /\r?\n/g, + rsubmitterTypes = /^(?:submit|button|image|reset|file)$/i, + rsubmittable = /^(?:input|select|textarea|keygen)/i; + +function buildParams( prefix, obj, traditional, add ) { + var name; + + if ( Array.isArray( obj ) ) { + + // Serialize array item. + jQuery.each( obj, function( i, v ) { + if ( traditional || rbracket.test( prefix ) ) { + + // Treat each array item as a scalar. + add( prefix, v ); + + } else { + + // Item is non-scalar (array or object), encode its numeric index. + buildParams( + prefix + "[" + ( typeof v === "object" && v != null ? i : "" ) + "]", + v, + traditional, + add + ); + } + } ); + + } else if ( !traditional && toType( obj ) === "object" ) { + + // Serialize object item. + for ( name in obj ) { + buildParams( prefix + "[" + name + "]", obj[ name ], traditional, add ); + } + + } else { + + // Serialize scalar item. + add( prefix, obj ); + } +} + +// Serialize an array of form elements or a set of +// key/values into a query string +jQuery.param = function( a, traditional ) { + var prefix, + s = [], + add = function( key, valueOrFunction ) { + + // If value is a function, invoke it and use its return value + var value = isFunction( valueOrFunction ) ? + valueOrFunction() : + valueOrFunction; + + s[ s.length ] = encodeURIComponent( key ) + "=" + + encodeURIComponent( value == null ? "" : value ); + }; + + if ( a == null ) { + return ""; + } + + // If an array was passed in, assume that it is an array of form elements. + if ( Array.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) { + + // Serialize the form elements + jQuery.each( a, function() { + add( this.name, this.value ); + } ); + + } else { + + // If traditional, encode the "old" way (the way 1.3.2 or older + // did it), otherwise encode params recursively. + for ( prefix in a ) { + buildParams( prefix, a[ prefix ], traditional, add ); + } + } + + // Return the resulting serialization + return s.join( "&" ); +}; + +jQuery.fn.extend( { + serialize: function() { + return jQuery.param( this.serializeArray() ); + }, + serializeArray: function() { + return this.map( function() { + + // Can add propHook for "elements" to filter or add form elements + var elements = jQuery.prop( this, "elements" ); + return elements ? jQuery.makeArray( elements ) : this; + } ) + .filter( function() { + var type = this.type; + + // Use .is( ":disabled" ) so that fieldset[disabled] works + return this.name && !jQuery( this ).is( ":disabled" ) && + rsubmittable.test( this.nodeName ) && !rsubmitterTypes.test( type ) && + ( this.checked || !rcheckableType.test( type ) ); + } ) + .map( function( _i, elem ) { + var val = jQuery( this ).val(); + + if ( val == null ) { + return null; + } + + if ( Array.isArray( val ) ) { + return jQuery.map( val, function( val ) { + return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) }; + } ); + } + + return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) }; + } ).get(); + } +} ); + + +var + r20 = /%20/g, + rhash = /#.*$/, + rantiCache = /([?&])_=[^&]*/, + rheaders = /^(.*?):[ \t]*([^\r\n]*)$/mg, + + // #7653, #8125, #8152: local protocol detection + rlocalProtocol = /^(?:about|app|app-storage|.+-extension|file|res|widget):$/, + rnoContent = /^(?:GET|HEAD)$/, + rprotocol = /^\/\//, + + /* Prefilters + * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example) + * 2) These are called: + * - BEFORE asking for a transport + * - AFTER param serialization (s.data is a string if s.processData is true) + * 3) key is the dataType + * 4) the catchall symbol "*" can be used + * 5) execution will start with transport dataType and THEN continue down to "*" if needed + */ + prefilters = {}, + + /* Transports bindings + * 1) key is the dataType + * 2) the catchall symbol "*" can be used + * 3) selection will start with transport dataType and THEN go to "*" if needed + */ + transports = {}, + + // Avoid comment-prolog char sequence (#10098); must appease lint and evade compression + allTypes = "*/".concat( "*" ), + + // Anchor tag for parsing the document origin + originAnchor = document.createElement( "a" ); + originAnchor.href = location.href; + +// Base "constructor" for jQuery.ajaxPrefilter and jQuery.ajaxTransport +function addToPrefiltersOrTransports( structure ) { + + // dataTypeExpression is optional and defaults to "*" + return function( dataTypeExpression, func ) { + + if ( typeof dataTypeExpression !== "string" ) { + func = dataTypeExpression; + dataTypeExpression = "*"; + } + + var dataType, + i = 0, + dataTypes = dataTypeExpression.toLowerCase().match( rnothtmlwhite ) || []; + + if ( isFunction( func ) ) { + + // For each dataType in the dataTypeExpression + while ( ( dataType = dataTypes[ i++ ] ) ) { + + // Prepend if requested + if ( dataType[ 0 ] === "+" ) { + dataType = dataType.slice( 1 ) || "*"; + ( structure[ dataType ] = structure[ dataType ] || [] ).unshift( func ); + + // Otherwise append + } else { + ( structure[ dataType ] = structure[ dataType ] || [] ).push( func ); + } + } + } + }; +} + +// Base inspection function for prefilters and transports +function inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR ) { + + var inspected = {}, + seekingTransport = ( structure === transports ); + + function inspect( dataType ) { + var selected; + inspected[ dataType ] = true; + jQuery.each( structure[ dataType ] || [], function( _, prefilterOrFactory ) { + var dataTypeOrTransport = prefilterOrFactory( options, originalOptions, jqXHR ); + if ( typeof dataTypeOrTransport === "string" && + !seekingTransport && !inspected[ dataTypeOrTransport ] ) { + + options.dataTypes.unshift( dataTypeOrTransport ); + inspect( dataTypeOrTransport ); + return false; + } else if ( seekingTransport ) { + return !( selected = dataTypeOrTransport ); + } + } ); + return selected; + } + + return inspect( options.dataTypes[ 0 ] ) || !inspected[ "*" ] && inspect( "*" ); +} + +// A special extend for ajax options +// that takes "flat" options (not to be deep extended) +// Fixes #9887 +function ajaxExtend( target, src ) { + var key, deep, + flatOptions = jQuery.ajaxSettings.flatOptions || {}; + + for ( key in src ) { + if ( src[ key ] !== undefined ) { + ( flatOptions[ key ] ? target : ( deep || ( deep = {} ) ) )[ key ] = src[ key ]; + } + } + if ( deep ) { + jQuery.extend( true, target, deep ); + } + + return target; +} + +/* Handles responses to an ajax request: + * - finds the right dataType (mediates between content-type and expected dataType) + * - returns the corresponding response + */ +function ajaxHandleResponses( s, jqXHR, responses ) { + + var ct, type, finalDataType, firstDataType, + contents = s.contents, + dataTypes = s.dataTypes; + + // Remove auto dataType and get content-type in the process + while ( dataTypes[ 0 ] === "*" ) { + dataTypes.shift(); + if ( ct === undefined ) { + ct = s.mimeType || jqXHR.getResponseHeader( "Content-Type" ); + } + } + + // Check if we're dealing with a known content-type + if ( ct ) { + for ( type in contents ) { + if ( contents[ type ] && contents[ type ].test( ct ) ) { + dataTypes.unshift( type ); + break; + } + } + } + + // Check to see if we have a response for the expected dataType + if ( dataTypes[ 0 ] in responses ) { + finalDataType = dataTypes[ 0 ]; + } else { + + // Try convertible dataTypes + for ( type in responses ) { + if ( !dataTypes[ 0 ] || s.converters[ type + " " + dataTypes[ 0 ] ] ) { + finalDataType = type; + break; + } + if ( !firstDataType ) { + firstDataType = type; + } + } + + // Or just use first one + finalDataType = finalDataType || firstDataType; + } + + // If we found a dataType + // We add the dataType to the list if needed + // and return the corresponding response + if ( finalDataType ) { + if ( finalDataType !== dataTypes[ 0 ] ) { + dataTypes.unshift( finalDataType ); + } + return responses[ finalDataType ]; + } +} + +/* Chain conversions given the request and the original response + * Also sets the responseXXX fields on the jqXHR instance + */ +function ajaxConvert( s, response, jqXHR, isSuccess ) { + var conv2, current, conv, tmp, prev, + converters = {}, + + // Work with a copy of dataTypes in case we need to modify it for conversion + dataTypes = s.dataTypes.slice(); + + // Create converters map with lowercased keys + if ( dataTypes[ 1 ] ) { + for ( conv in s.converters ) { + converters[ conv.toLowerCase() ] = s.converters[ conv ]; + } + } + + current = dataTypes.shift(); + + // Convert to each sequential dataType + while ( current ) { + + if ( s.responseFields[ current ] ) { + jqXHR[ s.responseFields[ current ] ] = response; + } + + // Apply the dataFilter if provided + if ( !prev && isSuccess && s.dataFilter ) { + response = s.dataFilter( response, s.dataType ); + } + + prev = current; + current = dataTypes.shift(); + + if ( current ) { + + // There's only work to do if current dataType is non-auto + if ( current === "*" ) { + + current = prev; + + // Convert response if prev dataType is non-auto and differs from current + } else if ( prev !== "*" && prev !== current ) { + + // Seek a direct converter + conv = converters[ prev + " " + current ] || converters[ "* " + current ]; + + // If none found, seek a pair + if ( !conv ) { + for ( conv2 in converters ) { + + // If conv2 outputs current + tmp = conv2.split( " " ); + if ( tmp[ 1 ] === current ) { + + // If prev can be converted to accepted input + conv = converters[ prev + " " + tmp[ 0 ] ] || + converters[ "* " + tmp[ 0 ] ]; + if ( conv ) { + + // Condense equivalence converters + if ( conv === true ) { + conv = converters[ conv2 ]; + + // Otherwise, insert the intermediate dataType + } else if ( converters[ conv2 ] !== true ) { + current = tmp[ 0 ]; + dataTypes.unshift( tmp[ 1 ] ); + } + break; + } + } + } + } + + // Apply converter (if not an equivalence) + if ( conv !== true ) { + + // Unless errors are allowed to bubble, catch and return them + if ( conv && s.throws ) { + response = conv( response ); + } else { + try { + response = conv( response ); + } catch ( e ) { + return { + state: "parsererror", + error: conv ? e : "No conversion from " + prev + " to " + current + }; + } + } + } + } + } + } + + return { state: "success", data: response }; +} + +jQuery.extend( { + + // Counter for holding the number of active queries + active: 0, + + // Last-Modified header cache for next request + lastModified: {}, + etag: {}, + + ajaxSettings: { + url: location.href, + type: "GET", + isLocal: rlocalProtocol.test( location.protocol ), + global: true, + processData: true, + async: true, + contentType: "application/x-www-form-urlencoded; charset=UTF-8", + + /* + timeout: 0, + data: null, + dataType: null, + username: null, + password: null, + cache: null, + throws: false, + traditional: false, + headers: {}, + */ + + accepts: { + "*": allTypes, + text: "text/plain", + html: "text/html", + xml: "application/xml, text/xml", + json: "application/json, text/javascript" + }, + + contents: { + xml: /\bxml\b/, + html: /\bhtml/, + json: /\bjson\b/ + }, + + responseFields: { + xml: "responseXML", + text: "responseText", + json: "responseJSON" + }, + + // Data converters + // Keys separate source (or catchall "*") and destination types with a single space + converters: { + + // Convert anything to text + "* text": String, + + // Text to html (true = no transformation) + "text html": true, + + // Evaluate text as a json expression + "text json": JSON.parse, + + // Parse text as xml + "text xml": jQuery.parseXML + }, + + // For options that shouldn't be deep extended: + // you can add your own custom options here if + // and when you create one that shouldn't be + // deep extended (see ajaxExtend) + flatOptions: { + url: true, + context: true + } + }, + + // Creates a full fledged settings object into target + // with both ajaxSettings and settings fields. + // If target is omitted, writes into ajaxSettings. + ajaxSetup: function( target, settings ) { + return settings ? + + // Building a settings object + ajaxExtend( ajaxExtend( target, jQuery.ajaxSettings ), settings ) : + + // Extending ajaxSettings + ajaxExtend( jQuery.ajaxSettings, target ); + }, + + ajaxPrefilter: addToPrefiltersOrTransports( prefilters ), + ajaxTransport: addToPrefiltersOrTransports( transports ), + + // Main method + ajax: function( url, options ) { + + // If url is an object, simulate pre-1.5 signature + if ( typeof url === "object" ) { + options = url; + url = undefined; + } + + // Force options to be an object + options = options || {}; + + var transport, + + // URL without anti-cache param + cacheURL, + + // Response headers + responseHeadersString, + responseHeaders, + + // timeout handle + timeoutTimer, + + // Url cleanup var + urlAnchor, + + // Request state (becomes false upon send and true upon completion) + completed, + + // To know if global events are to be dispatched + fireGlobals, + + // Loop variable + i, + + // uncached part of the url + uncached, + + // Create the final options object + s = jQuery.ajaxSetup( {}, options ), + + // Callbacks context + callbackContext = s.context || s, + + // Context for global events is callbackContext if it is a DOM node or jQuery collection + globalEventContext = s.context && + ( callbackContext.nodeType || callbackContext.jquery ) ? + jQuery( callbackContext ) : + jQuery.event, + + // Deferreds + deferred = jQuery.Deferred(), + completeDeferred = jQuery.Callbacks( "once memory" ), + + // Status-dependent callbacks + statusCode = s.statusCode || {}, + + // Headers (they are sent all at once) + requestHeaders = {}, + requestHeadersNames = {}, + + // Default abort message + strAbort = "canceled", + + // Fake xhr + jqXHR = { + readyState: 0, + + // Builds headers hashtable if needed + getResponseHeader: function( key ) { + var match; + if ( completed ) { + if ( !responseHeaders ) { + responseHeaders = {}; + while ( ( match = rheaders.exec( responseHeadersString ) ) ) { + responseHeaders[ match[ 1 ].toLowerCase() + " " ] = + ( responseHeaders[ match[ 1 ].toLowerCase() + " " ] || [] ) + .concat( match[ 2 ] ); + } + } + match = responseHeaders[ key.toLowerCase() + " " ]; + } + return match == null ? null : match.join( ", " ); + }, + + // Raw string + getAllResponseHeaders: function() { + return completed ? responseHeadersString : null; + }, + + // Caches the header + setRequestHeader: function( name, value ) { + if ( completed == null ) { + name = requestHeadersNames[ name.toLowerCase() ] = + requestHeadersNames[ name.toLowerCase() ] || name; + requestHeaders[ name ] = value; + } + return this; + }, + + // Overrides response content-type header + overrideMimeType: function( type ) { + if ( completed == null ) { + s.mimeType = type; + } + return this; + }, + + // Status-dependent callbacks + statusCode: function( map ) { + var code; + if ( map ) { + if ( completed ) { + + // Execute the appropriate callbacks + jqXHR.always( map[ jqXHR.status ] ); + } else { + + // Lazy-add the new callbacks in a way that preserves old ones + for ( code in map ) { + statusCode[ code ] = [ statusCode[ code ], map[ code ] ]; + } + } + } + return this; + }, + + // Cancel the request + abort: function( statusText ) { + var finalText = statusText || strAbort; + if ( transport ) { + transport.abort( finalText ); + } + done( 0, finalText ); + return this; + } + }; + + // Attach deferreds + deferred.promise( jqXHR ); + + // Add protocol if not provided (prefilters might expect it) + // Handle falsy url in the settings object (#10093: consistency with old signature) + // We also use the url parameter if available + s.url = ( ( url || s.url || location.href ) + "" ) + .replace( rprotocol, location.protocol + "//" ); + + // Alias method option to type as per ticket #12004 + s.type = options.method || options.type || s.method || s.type; + + // Extract dataTypes list + s.dataTypes = ( s.dataType || "*" ).toLowerCase().match( rnothtmlwhite ) || [ "" ]; + + // A cross-domain request is in order when the origin doesn't match the current origin. + if ( s.crossDomain == null ) { + urlAnchor = document.createElement( "a" ); + + // Support: IE <=8 - 11, Edge 12 - 15 + // IE throws exception on accessing the href property if url is malformed, + // e.g. http://example.com:80x/ + try { + urlAnchor.href = s.url; + + // Support: IE <=8 - 11 only + // Anchor's host property isn't correctly set when s.url is relative + urlAnchor.href = urlAnchor.href; + s.crossDomain = originAnchor.protocol + "//" + originAnchor.host !== + urlAnchor.protocol + "//" + urlAnchor.host; + } catch ( e ) { + + // If there is an error parsing the URL, assume it is crossDomain, + // it can be rejected by the transport if it is invalid + s.crossDomain = true; + } + } + + // Convert data if not already a string + if ( s.data && s.processData && typeof s.data !== "string" ) { + s.data = jQuery.param( s.data, s.traditional ); + } + + // Apply prefilters + inspectPrefiltersOrTransports( prefilters, s, options, jqXHR ); + + // If request was aborted inside a prefilter, stop there + if ( completed ) { + return jqXHR; + } + + // We can fire global events as of now if asked to + // Don't fire events if jQuery.event is undefined in an AMD-usage scenario (#15118) + fireGlobals = jQuery.event && s.global; + + // Watch for a new set of requests + if ( fireGlobals && jQuery.active++ === 0 ) { + jQuery.event.trigger( "ajaxStart" ); + } + + // Uppercase the type + s.type = s.type.toUpperCase(); + + // Determine if request has content + s.hasContent = !rnoContent.test( s.type ); + + // Save the URL in case we're toying with the If-Modified-Since + // and/or If-None-Match header later on + // Remove hash to simplify url manipulation + cacheURL = s.url.replace( rhash, "" ); + + // More options handling for requests with no content + if ( !s.hasContent ) { + + // Remember the hash so we can put it back + uncached = s.url.slice( cacheURL.length ); + + // If data is available and should be processed, append data to url + if ( s.data && ( s.processData || typeof s.data === "string" ) ) { + cacheURL += ( rquery.test( cacheURL ) ? "&" : "?" ) + s.data; + + // #9682: remove data so that it's not used in an eventual retry + delete s.data; + } + + // Add or update anti-cache param if needed + if ( s.cache === false ) { + cacheURL = cacheURL.replace( rantiCache, "$1" ); + uncached = ( rquery.test( cacheURL ) ? "&" : "?" ) + "_=" + ( nonce.guid++ ) + + uncached; + } + + // Put hash and anti-cache on the URL that will be requested (gh-1732) + s.url = cacheURL + uncached; + + // Change '%20' to '+' if this is encoded form body content (gh-2658) + } else if ( s.data && s.processData && + ( s.contentType || "" ).indexOf( "application/x-www-form-urlencoded" ) === 0 ) { + s.data = s.data.replace( r20, "+" ); + } + + // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode. + if ( s.ifModified ) { + if ( jQuery.lastModified[ cacheURL ] ) { + jqXHR.setRequestHeader( "If-Modified-Since", jQuery.lastModified[ cacheURL ] ); + } + if ( jQuery.etag[ cacheURL ] ) { + jqXHR.setRequestHeader( "If-None-Match", jQuery.etag[ cacheURL ] ); + } + } + + // Set the correct header, if data is being sent + if ( s.data && s.hasContent && s.contentType !== false || options.contentType ) { + jqXHR.setRequestHeader( "Content-Type", s.contentType ); + } + + // Set the Accepts header for the server, depending on the dataType + jqXHR.setRequestHeader( + "Accept", + s.dataTypes[ 0 ] && s.accepts[ s.dataTypes[ 0 ] ] ? + s.accepts[ s.dataTypes[ 0 ] ] + + ( s.dataTypes[ 0 ] !== "*" ? ", " + allTypes + "; q=0.01" : "" ) : + s.accepts[ "*" ] + ); + + // Check for headers option + for ( i in s.headers ) { + jqXHR.setRequestHeader( i, s.headers[ i ] ); + } + + // Allow custom headers/mimetypes and early abort + if ( s.beforeSend && + ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || completed ) ) { + + // Abort if not done already and return + return jqXHR.abort(); + } + + // Aborting is no longer a cancellation + strAbort = "abort"; + + // Install callbacks on deferreds + completeDeferred.add( s.complete ); + jqXHR.done( s.success ); + jqXHR.fail( s.error ); + + // Get transport + transport = inspectPrefiltersOrTransports( transports, s, options, jqXHR ); + + // If no transport, we auto-abort + if ( !transport ) { + done( -1, "No Transport" ); + } else { + jqXHR.readyState = 1; + + // Send global event + if ( fireGlobals ) { + globalEventContext.trigger( "ajaxSend", [ jqXHR, s ] ); + } + + // If request was aborted inside ajaxSend, stop there + if ( completed ) { + return jqXHR; + } + + // Timeout + if ( s.async && s.timeout > 0 ) { + timeoutTimer = window.setTimeout( function() { + jqXHR.abort( "timeout" ); + }, s.timeout ); + } + + try { + completed = false; + transport.send( requestHeaders, done ); + } catch ( e ) { + + // Rethrow post-completion exceptions + if ( completed ) { + throw e; + } + + // Propagate others as results + done( -1, e ); + } + } + + // Callback for when everything is done + function done( status, nativeStatusText, responses, headers ) { + var isSuccess, success, error, response, modified, + statusText = nativeStatusText; + + // Ignore repeat invocations + if ( completed ) { + return; + } + + completed = true; + + // Clear timeout if it exists + if ( timeoutTimer ) { + window.clearTimeout( timeoutTimer ); + } + + // Dereference transport for early garbage collection + // (no matter how long the jqXHR object will be used) + transport = undefined; + + // Cache response headers + responseHeadersString = headers || ""; + + // Set readyState + jqXHR.readyState = status > 0 ? 4 : 0; + + // Determine if successful + isSuccess = status >= 200 && status < 300 || status === 304; + + // Get response data + if ( responses ) { + response = ajaxHandleResponses( s, jqXHR, responses ); + } + + // Use a noop converter for missing script + if ( !isSuccess && jQuery.inArray( "script", s.dataTypes ) > -1 ) { + s.converters[ "text script" ] = function() {}; + } + + // Convert no matter what (that way responseXXX fields are always set) + response = ajaxConvert( s, response, jqXHR, isSuccess ); + + // If successful, handle type chaining + if ( isSuccess ) { + + // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode. + if ( s.ifModified ) { + modified = jqXHR.getResponseHeader( "Last-Modified" ); + if ( modified ) { + jQuery.lastModified[ cacheURL ] = modified; + } + modified = jqXHR.getResponseHeader( "etag" ); + if ( modified ) { + jQuery.etag[ cacheURL ] = modified; + } + } + + // if no content + if ( status === 204 || s.type === "HEAD" ) { + statusText = "nocontent"; + + // if not modified + } else if ( status === 304 ) { + statusText = "notmodified"; + + // If we have data, let's convert it + } else { + statusText = response.state; + success = response.data; + error = response.error; + isSuccess = !error; + } + } else { + + // Extract error from statusText and normalize for non-aborts + error = statusText; + if ( status || !statusText ) { + statusText = "error"; + if ( status < 0 ) { + status = 0; + } + } + } + + // Set data for the fake xhr object + jqXHR.status = status; + jqXHR.statusText = ( nativeStatusText || statusText ) + ""; + + // Success/Error + if ( isSuccess ) { + deferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] ); + } else { + deferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] ); + } + + // Status-dependent callbacks + jqXHR.statusCode( statusCode ); + statusCode = undefined; + + if ( fireGlobals ) { + globalEventContext.trigger( isSuccess ? "ajaxSuccess" : "ajaxError", + [ jqXHR, s, isSuccess ? success : error ] ); + } + + // Complete + completeDeferred.fireWith( callbackContext, [ jqXHR, statusText ] ); + + if ( fireGlobals ) { + globalEventContext.trigger( "ajaxComplete", [ jqXHR, s ] ); + + // Handle the global AJAX counter + if ( !( --jQuery.active ) ) { + jQuery.event.trigger( "ajaxStop" ); + } + } + } + + return jqXHR; + }, + + getJSON: function( url, data, callback ) { + return jQuery.get( url, data, callback, "json" ); + }, + + getScript: function( url, callback ) { + return jQuery.get( url, undefined, callback, "script" ); + } +} ); + +jQuery.each( [ "get", "post" ], function( _i, method ) { + jQuery[ method ] = function( url, data, callback, type ) { + + // Shift arguments if data argument was omitted + if ( isFunction( data ) ) { + type = type || callback; + callback = data; + data = undefined; + } + + // The url can be an options object (which then must have .url) + return jQuery.ajax( jQuery.extend( { + url: url, + type: method, + dataType: type, + data: data, + success: callback + }, jQuery.isPlainObject( url ) && url ) ); + }; +} ); + +jQuery.ajaxPrefilter( function( s ) { + var i; + for ( i in s.headers ) { + if ( i.toLowerCase() === "content-type" ) { + s.contentType = s.headers[ i ] || ""; + } + } +} ); + + +jQuery._evalUrl = function( url, options, doc ) { + return jQuery.ajax( { + url: url, + + // Make this explicit, since user can override this through ajaxSetup (#11264) + type: "GET", + dataType: "script", + cache: true, + async: false, + global: false, + + // Only evaluate the response if it is successful (gh-4126) + // dataFilter is not invoked for failure responses, so using it instead + // of the default converter is kludgy but it works. + converters: { + "text script": function() {} + }, + dataFilter: function( response ) { + jQuery.globalEval( response, options, doc ); + } + } ); +}; + + +jQuery.fn.extend( { + wrapAll: function( html ) { + var wrap; + + if ( this[ 0 ] ) { + if ( isFunction( html ) ) { + html = html.call( this[ 0 ] ); + } + + // The elements to wrap the target around + wrap = jQuery( html, this[ 0 ].ownerDocument ).eq( 0 ).clone( true ); + + if ( this[ 0 ].parentNode ) { + wrap.insertBefore( this[ 0 ] ); + } + + wrap.map( function() { + var elem = this; + + while ( elem.firstElementChild ) { + elem = elem.firstElementChild; + } + + return elem; + } ).append( this ); + } + + return this; + }, + + wrapInner: function( html ) { + if ( isFunction( html ) ) { + return this.each( function( i ) { + jQuery( this ).wrapInner( html.call( this, i ) ); + } ); + } + + return this.each( function() { + var self = jQuery( this ), + contents = self.contents(); + + if ( contents.length ) { + contents.wrapAll( html ); + + } else { + self.append( html ); + } + } ); + }, + + wrap: function( html ) { + var htmlIsFunction = isFunction( html ); + + return this.each( function( i ) { + jQuery( this ).wrapAll( htmlIsFunction ? html.call( this, i ) : html ); + } ); + }, + + unwrap: function( selector ) { + this.parent( selector ).not( "body" ).each( function() { + jQuery( this ).replaceWith( this.childNodes ); + } ); + return this; + } +} ); + + +jQuery.expr.pseudos.hidden = function( elem ) { + return !jQuery.expr.pseudos.visible( elem ); +}; +jQuery.expr.pseudos.visible = function( elem ) { + return !!( elem.offsetWidth || elem.offsetHeight || elem.getClientRects().length ); +}; + + + + +jQuery.ajaxSettings.xhr = function() { + try { + return new window.XMLHttpRequest(); + } catch ( e ) {} +}; + +var xhrSuccessStatus = { + + // File protocol always yields status code 0, assume 200 + 0: 200, + + // Support: IE <=9 only + // #1450: sometimes IE returns 1223 when it should be 204 + 1223: 204 + }, + xhrSupported = jQuery.ajaxSettings.xhr(); + +support.cors = !!xhrSupported && ( "withCredentials" in xhrSupported ); +support.ajax = xhrSupported = !!xhrSupported; + +jQuery.ajaxTransport( function( options ) { + var callback, errorCallback; + + // Cross domain only allowed if supported through XMLHttpRequest + if ( support.cors || xhrSupported && !options.crossDomain ) { + return { + send: function( headers, complete ) { + var i, + xhr = options.xhr(); + + xhr.open( + options.type, + options.url, + options.async, + options.username, + options.password + ); + + // Apply custom fields if provided + if ( options.xhrFields ) { + for ( i in options.xhrFields ) { + xhr[ i ] = options.xhrFields[ i ]; + } + } + + // Override mime type if needed + if ( options.mimeType && xhr.overrideMimeType ) { + xhr.overrideMimeType( options.mimeType ); + } + + // X-Requested-With header + // For cross-domain requests, seeing as conditions for a preflight are + // akin to a jigsaw puzzle, we simply never set it to be sure. + // (it can always be set on a per-request basis or even using ajaxSetup) + // For same-domain requests, won't change header if already provided. + if ( !options.crossDomain && !headers[ "X-Requested-With" ] ) { + headers[ "X-Requested-With" ] = "XMLHttpRequest"; + } + + // Set headers + for ( i in headers ) { + xhr.setRequestHeader( i, headers[ i ] ); + } + + // Callback + callback = function( type ) { + return function() { + if ( callback ) { + callback = errorCallback = xhr.onload = + xhr.onerror = xhr.onabort = xhr.ontimeout = + xhr.onreadystatechange = null; + + if ( type === "abort" ) { + xhr.abort(); + } else if ( type === "error" ) { + + // Support: IE <=9 only + // On a manual native abort, IE9 throws + // errors on any property access that is not readyState + if ( typeof xhr.status !== "number" ) { + complete( 0, "error" ); + } else { + complete( + + // File: protocol always yields status 0; see #8605, #14207 + xhr.status, + xhr.statusText + ); + } + } else { + complete( + xhrSuccessStatus[ xhr.status ] || xhr.status, + xhr.statusText, + + // Support: IE <=9 only + // IE9 has no XHR2 but throws on binary (trac-11426) + // For XHR2 non-text, let the caller handle it (gh-2498) + ( xhr.responseType || "text" ) !== "text" || + typeof xhr.responseText !== "string" ? + { binary: xhr.response } : + { text: xhr.responseText }, + xhr.getAllResponseHeaders() + ); + } + } + }; + }; + + // Listen to events + xhr.onload = callback(); + errorCallback = xhr.onerror = xhr.ontimeout = callback( "error" ); + + // Support: IE 9 only + // Use onreadystatechange to replace onabort + // to handle uncaught aborts + if ( xhr.onabort !== undefined ) { + xhr.onabort = errorCallback; + } else { + xhr.onreadystatechange = function() { + + // Check readyState before timeout as it changes + if ( xhr.readyState === 4 ) { + + // Allow onerror to be called first, + // but that will not handle a native abort + // Also, save errorCallback to a variable + // as xhr.onerror cannot be accessed + window.setTimeout( function() { + if ( callback ) { + errorCallback(); + } + } ); + } + }; + } + + // Create the abort callback + callback = callback( "abort" ); + + try { + + // Do send the request (this may raise an exception) + xhr.send( options.hasContent && options.data || null ); + } catch ( e ) { + + // #14683: Only rethrow if this hasn't been notified as an error yet + if ( callback ) { + throw e; + } + } + }, + + abort: function() { + if ( callback ) { + callback(); + } + } + }; + } +} ); + + + + +// Prevent auto-execution of scripts when no explicit dataType was provided (See gh-2432) +jQuery.ajaxPrefilter( function( s ) { + if ( s.crossDomain ) { + s.contents.script = false; + } +} ); + +// Install script dataType +jQuery.ajaxSetup( { + accepts: { + script: "text/javascript, application/javascript, " + + "application/ecmascript, application/x-ecmascript" + }, + contents: { + script: /\b(?:java|ecma)script\b/ + }, + converters: { + "text script": function( text ) { + jQuery.globalEval( text ); + return text; + } + } +} ); + +// Handle cache's special case and crossDomain +jQuery.ajaxPrefilter( "script", function( s ) { + if ( s.cache === undefined ) { + s.cache = false; + } + if ( s.crossDomain ) { + s.type = "GET"; + } +} ); + +// Bind script tag hack transport +jQuery.ajaxTransport( "script", function( s ) { + + // This transport only deals with cross domain or forced-by-attrs requests + if ( s.crossDomain || s.scriptAttrs ) { + var script, callback; + return { + send: function( _, complete ) { + script = jQuery( " + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra - Exceptions and Enums

+
+
+cassandra.__version_info__
+

The version of the driver in a tuple format

+
+ +
+
+cassandra.__version__
+

The version of the driver in a string format

+
+ +
+
+class cassandra.ConsistencyLevel
+

Spcifies how many replicas must respond for an operation to be considered +a success. By default, ONE is used for all operations.

+
+
+ANY = 0
+

Only requires that one replica receives the write or the coordinator +stores a hint to replay later. Valid only for writes.

+
+ +
+
+ONE = 1
+

Only one replica needs to respond to consider the operation a success

+
+ +
+
+TWO = 2
+

Two replicas must respond to consider the operation a success

+
+ +
+
+THREE = 3
+

Three replicas must respond to consider the operation a success

+
+ +
+
+QUORUM = 4
+

ceil(RF/2) + 1 replicas must respond to consider the operation a success

+
+ +
+
+ALL = 5
+

All replicas must respond to consider the operation a success

+
+ +
+
+LOCAL_QUORUM = 6
+

Requires a quorum of replicas in the local datacenter

+
+ +
+
+EACH_QUORUM = 7
+

Requires a quorum of replicas in each datacenter

+
+ +
+
+SERIAL = 8
+

For conditional inserts/updates that utilize Cassandra’s lightweight +transactions, this requires consensus among all replicas for the +modified data.

+
+ +
+
+LOCAL_SERIAL = 9
+

Like SERIAL, but only requires consensus +among replicas in the local datacenter.

+
+ +
+
+LOCAL_ONE = 10
+

Sends a request only to replicas in the local datacenter and waits for +one response.

+
+ +
+ +
+
+class cassandra.ProtocolVersion
+

Defines native protocol versions supported by this driver.

+
+
+V1 = 1
+

v1, supported in Cassandra 1.2–>2.2

+
+ +
+
+V2 = 2
+

v2, supported in Cassandra 2.0–>2.2; +added support for lightweight transactions, batch operations, and automatic query paging.

+
+ +
+
+V3 = 3
+

v3, supported in Cassandra 2.1–>3.x+; +added support for protocol-level client-side timestamps (see Session.use_client_timestamp), +serial consistency levels for BatchStatement, and an improved connection pool.

+
+ +
+
+V4 = 4
+

v4, supported in Cassandra 2.2–>3.x+; +added a number of new types, server warnings, new failure messages, and custom payloads. Details in the +project docs

+
+ +
+
+V5 = 5
+

v5, in beta from 3.x+. Finalised in 4.0-beta5

+
+ +
+
+V6 = 6
+

v6, in beta from 4.0-beta5

+
+ +
+
+DSE_V1 = 65
+

DSE private protocol v1, supported in DSE 5.1+

+
+ +
+
+DSE_V2 = 66
+

DSE private protocol v2, supported in DSE 6.0+

+
+ +
+
+SUPPORTED_VERSIONS = (66, 65, 6, 5, 4, 3, 2, 1)
+

A tuple of all supported protocol versions

+
+ +
+
+BETA_VERSIONS = (6,)
+

A tuple of all beta protocol versions

+
+ +
+
+MIN_SUPPORTED = 1
+

Minimum protocol version supported by this driver.

+
+ +
+
+MAX_SUPPORTED = 66
+

Maximum protocol version supported by this driver.

+
+ +
+
+classmethod get_lower_supported(previous_version)
+

Return the lower supported protocol version. Beta versions are omitted.

+
+ +
+ +
+
+class cassandra.UserFunctionDescriptor(name, argument_types)
+

Describes a User function by name and argument signature

+
+
+name = None
+

name of the function

+
+ +
+
+argument_types = None
+

Ordered list of CQL argument type names comprising the type signature

+
+ +
+
+property signature
+

function signature string in the form ‘name([type0[,type1[…]]])’

+

can be used to uniquely identify overloaded function names within a keyspace

+
+ +
+ +
+
+class cassandra.UserAggregateDescriptor(name, argument_types)
+

Describes a User aggregate function by name and argument signature

+
+
+name = None
+

name of the aggregate

+
+ +
+
+argument_types = None
+

Ordered list of CQL argument type names comprising the type signature

+
+ +
+
+property signature
+

function signature string in the form ‘name([type0[,type1[…]]])’

+

can be used to uniquely identify overloaded function names within a keyspace

+
+ +
+ +
+
+exception cassandra.DriverException
+

Base for all exceptions explicitly raised by the driver.

+
+ +
+
+exception cassandra.RequestExecutionException
+

Base for request execution exceptions returned from the server.

+
+ +
+
+exception cassandra.Unavailable
+

There were not enough live replicas to satisfy the requested consistency +level, so the coordinator node immediately failed the request without +forwarding it to any replicas.

+
+
+consistency = None
+

The requested ConsistencyLevel

+
+ +
+
+required_replicas = None
+

The number of replicas that needed to be live to complete the operation

+
+ +
+
+alive_replicas = None
+

The number of replicas that were actually alive

+
+ +
+ +
+
+exception cassandra.Timeout
+

Replicas failed to respond to the coordinator node before timing out.

+
+
+consistency = None
+

The requested ConsistencyLevel

+
+ +
+
+required_responses = None
+

The number of required replica responses

+
+ +
+
+received_responses = None
+

The number of replicas that responded before the coordinator timed out +the operation

+
+ +
+ +
+
+exception cassandra.ReadTimeout
+

A subclass of Timeout for read operations.

+

This indicates that the replicas failed to respond to the coordinator +node before the configured timeout. This timeout is configured in +cassandra.yaml with the read_request_timeout_in_ms +and range_request_timeout_in_ms options.

+
+
+data_retrieved = None
+

A boolean indicating whether the requested data was retrieved +by the coordinator from any replicas before it timed out the +operation

+
+ +
+ +
+
+exception cassandra.WriteTimeout
+

A subclass of Timeout for write operations.

+

This indicates that the replicas failed to respond to the coordinator +node before the configured timeout. This timeout is configured in +cassandra.yaml with the write_request_timeout_in_ms +option.

+
+
+write_type = None
+

The type of write operation, enum on WriteType

+
+ +
+ +
+
+exception cassandra.CoordinationFailure
+

Replicas sent a failure to the coordinator.

+
+
+consistency = None
+

The requested ConsistencyLevel

+
+ +
+
+required_responses = None
+

The number of required replica responses

+
+ +
+
+received_responses = None
+

The number of replicas that responded before the coordinator timed out +the operation

+
+ +
+
+failures = None
+

The number of replicas that sent a failure message

+
+ +
+
+error_code_map = None
+

A map of inet addresses to error codes representing replicas that sent +a failure message. Only set when protocol_version is 5 or higher.

+
+ +
+ +
+
+exception cassandra.ReadFailure
+

A subclass of CoordinationFailure for read operations.

+

This indicates that the replicas sent a failure message to the coordinator.

+
+
+data_retrieved = None
+

A boolean indicating whether the requested data was retrieved +by the coordinator from any replicas before it timed out the +operation

+
+ +
+ +
+
+exception cassandra.WriteFailure
+

A subclass of CoordinationFailure for write operations.

+

This indicates that the replicas sent a failure message to the coordinator.

+
+
+write_type = None
+

The type of write operation, enum on WriteType

+
+ +
+ +
+
+exception cassandra.FunctionFailure
+

User Defined Function failed during execution

+
+
+keyspace = None
+

Keyspace of the function

+
+ +
+
+function = None
+

Name of the function

+
+ +
+
+arg_types = None
+

List of argument type names of the function

+
+ +
+ +
+
+exception cassandra.RequestValidationException
+

Server request validation failed

+
+ +
+
+exception cassandra.ConfigurationException
+

Server indicated request errro due to current configuration

+
+ +
+
+exception cassandra.AlreadyExists
+

An attempt was made to create a keyspace or table that already exists.

+
+
+keyspace = None
+

The name of the keyspace that already exists, or, if an attempt was +made to create a new table, the keyspace that the table is in.

+
+ +
+
+table = None
+

The name of the table that already exists, or, if an attempt was +make to create a keyspace, None.

+
+ +
+ +
+
+exception cassandra.InvalidRequest
+

A query was made that was invalid for some reason, such as trying to set +the keyspace for a connection to a nonexistent keyspace.

+
+ +
+
+exception cassandra.Unauthorized
+

The current user is not authorized to perform the requested operation.

+
+ +
+
+exception cassandra.AuthenticationFailed
+

Failed to authenticate.

+
+ +
+
+exception cassandra.OperationTimedOut
+

The operation took longer than the specified (client-side) timeout +to complete. This is not an error generated by Cassandra, only +the driver.

+
+
+errors = None
+

A dict of errors keyed by the Host against which they occurred.

+
+ +
+
+last_host = None
+

The last Host this operation was attempted against.

+
+ +
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.25.11-scylla/api/cassandra/auth.html b/3.25.11-scylla/api/cassandra/auth.html new file mode 100644 index 0000000000..9b730e4d6c --- /dev/null +++ b/3.25.11-scylla/api/cassandra/auth.html @@ -0,0 +1,806 @@ + + + + + + + + + + + + + cassandra.auth - Authentication | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.auth - Authentication

+
+
+class cassandra.auth.AuthProvider
+

An abstract class that defines the interface that will be used for +creating Authenticator instances when opening new +connections to Cassandra.

+
+

New in version 2.0.0.

+
+
+
+new_authenticator(host)
+

Implementations of this class should return a new instance +of Authenticator or one of its subclasses.

+
+ +
+ +
+
+class cassandra.auth.Authenticator
+

An abstract class that handles SASL authentication with Cassandra servers.

+

Each time a new connection is created and the server requires authentication, +a new instance of this class will be created by the corresponding +AuthProvider to handler that authentication. The lifecycle of the +new Authenticator will the be:

+

1) The initial_response() method will be called. The return +value will be sent to the server to initiate the handshake.

+

2) The server will respond to each client response by either issuing a +challenge or indicating that the authentication is complete (successful or not). +If a new challenge is issued, evaluate_challenge() +will be called to produce a response that will be sent to the +server. This challenge/response negotiation will continue until the server +responds that authentication is successful (or an AuthenticationFailed +is raised).

+

3) When the server indicates that authentication is successful, +on_authentication_success() will be called a token string that +that the server may optionally have sent.

+

The exact nature of the negotiation between the client and server is specific +to the authentication mechanism configured server-side.

+
+

New in version 2.0.0.

+
+
+
+server_authenticator_class = None
+

Set during the connection AUTHENTICATE phase

+
+ +
+
+initial_response()
+

Returns an message to send to the server to initiate the SASL handshake. +None may be returned to send an empty message.

+
+ +
+
+evaluate_challenge(challenge)
+

Called when the server sends a challenge message. Generally, this method +should return None when authentication is complete from a +client perspective. Otherwise, a string should be returned.

+
+ +
+
+on_authentication_success(token)
+

Called when the server indicates that authentication was successful. +Depending on the authentication mechanism, token may be None +or a string.

+
+ +
+ +
+
+class cassandra.auth.PlainTextAuthProvider(username, password)
+

An AuthProvider that works with Cassandra’s PasswordAuthenticator.

+

Example usage:

+
from cassandra.cluster import Cluster
+from cassandra.auth import PlainTextAuthProvider
+
+auth_provider = PlainTextAuthProvider(
+        username='cassandra', password='cassandra')
+cluster = Cluster(auth_provider=auth_provider)
+
+
+
+

New in version 2.0.0.

+
+
+
+new_authenticator(host)
+

Implementations of this class should return a new instance +of Authenticator or one of its subclasses.

+
+ +
+ +
+
+class cassandra.auth.PlainTextAuthenticator(username, password)
+
+
+evaluate_challenge(challenge)
+

Called when the server sends a challenge message. Generally, this method +should return None when authentication is complete from a +client perspective. Otherwise, a string should be returned.

+
+ +
+ +
+
+class cassandra.auth.SaslAuthProvider(**sasl_kwargs)
+

An AuthProvider supporting general SASL auth mechanisms

+

Suitable for GSSAPI or other SASL mechanisms

+

Example usage:

+
from cassandra.cluster import Cluster
+from cassandra.auth import SaslAuthProvider
+
+sasl_kwargs = {'service': 'something',
+               'mechanism': 'GSSAPI',
+               'qops': 'auth'.split(',')}
+auth_provider = SaslAuthProvider(**sasl_kwargs)
+cluster = Cluster(auth_provider=auth_provider)
+
+
+
+

New in version 2.1.4.

+
+
+
+new_authenticator(host)
+

Implementations of this class should return a new instance +of Authenticator or one of its subclasses.

+
+ +
+ +
+
+class cassandra.auth.SaslAuthenticator(host, service, mechanism='GSSAPI', **sasl_kwargs)
+

A pass-through Authenticator using the third party package +‘pure-sasl’ for authentication

+
+

New in version 2.1.4.

+
+
+
+initial_response()
+

Returns an message to send to the server to initiate the SASL handshake. +None may be returned to send an empty message.

+
+ +
+
+evaluate_challenge(challenge)
+

Called when the server sends a challenge message. Generally, this method +should return None when authentication is complete from a +client perspective. Otherwise, a string should be returned.

+
+ +
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.25.11-scylla/api/cassandra/cluster.html b/3.25.11-scylla/api/cassandra/cluster.html new file mode 100644 index 0000000000..e6ee6f7f57 --- /dev/null +++ b/3.25.11-scylla/api/cassandra/cluster.html @@ -0,0 +1,1778 @@ + + + + + + + + + + + + + cassandra.cluster - Clusters and Sessions | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.cluster - Clusters and Sessions

+
+
+class cassandra.cluster.Cluster([contact_points=('127.0.0.1',)][, port=9042][, executor_threads=2], **attr_kwargs)
+

The main class to use when interacting with a Cassandra cluster. +Typically, one instance of this class will be created for each +separate Cassandra cluster that your application interacts with.

+

Example usage:

+
>>> from cassandra.cluster import Cluster
+>>> cluster = Cluster(['192.168.1.1', '192.168.1.2'])
+>>> session = cluster.connect()
+>>> session.execute("CREATE KEYSPACE ...")
+>>> ...
+>>> cluster.shutdown()
+
+
+

Cluster and Session also provide context management functions +which implicitly handle shutdown when leaving scope.

+

executor_threads defines the number of threads in a pool for handling asynchronous tasks such as +extablishing connection pools or refreshing metadata.

+

Any of the mutable Cluster attributes may be set as keyword arguments to the constructor.

+
+
+contact_points = ['127.0.0.1']
+
+ +
+
+port = 9042
+
+ +
+
+cql_version = None
+
+ +
+
+protocol_version = 66
+
+ +
+
+compression = True
+
+ +
+
+auth_provider
+

When protocol_version is 2 or higher, this should +be an instance of a subclass of AuthProvider, +such as PlainTextAuthProvider.

+

When protocol_version is 1, this should be +a function that accepts one argument, the IP address of a node, +and returns a dict of credentials for that node.

+

When not using authentication, this should be left as None.

+
+ +
+
+load_balancing_policy
+

An instance of policies.LoadBalancingPolicy or +one of its subclasses.

+
+

Changed in version 2.6.0.

+
+

Defaults to TokenAwarePolicy (DCAwareRoundRobinPolicy). +when using CPython (where the murmur3 extension is available). DCAwareRoundRobinPolicy +otherwise. Default local DC will be chosen from contact points.

+

Please see DCAwareRoundRobinPolicy for a discussion on default behavior with respect to +DC locality and remote nodes.

+
+ +
+
+reconnection_policy = <cassandra.policies.ExponentialReconnectionPolicy object>
+
+ +
+
+default_retry_policy = <cassandra.policies.RetryPolicy object>
+

A default policies.RetryPolicy instance to use for all +Statement objects which do not have a retry_policy +explicitly set.

+
+ +
+
+conviction_policy_factory = <class 'cassandra.policies.SimpleConvictionPolicy'>
+
+ +
+
+address_translator = <cassandra.policies.IdentityTranslator object>
+
+ +
+
+metrics_enabled = False
+
+ +
+
+metrics = None
+
+ +
+
+ssl_context = None
+
+ +
+
+ssl_options = None
+
+ +
+
+sockopts = None
+
+ +
+
+max_schema_agreement_wait = 10
+
+ +
+
+metadata = None
+
+ +
+
+connection_class = <class 'cassandra.io.libevreactor.LibevConnection'>
+
+ +
+
+control_connection_timeout = 2.0
+
+ +
+
+idle_heartbeat_interval = 30
+
+ +
+
+idle_heartbeat_timeout = 30
+
+ +
+
+schema_event_refresh_window = 2
+
+ +
+
+topology_event_refresh_window = 10
+
+ +
+
+status_event_refresh_window = 2
+
+ +
+
+prepare_on_all_hosts = True
+
+ +
+
+reprepare_on_up = True
+
+ +
+
+connect_timeout = 5
+
+ +
+
+schema_metadata_enabled = True
+

Flag indicating whether internal schema metadata is updated.

+

When disabled, the driver does not populate Cluster.metadata.keyspaces on connect, or on schema change events. This +can be used to speed initial connection, and reduce load on client and server during operation. Turning this off +gives away token aware request routing, and programmatic inspection of the metadata model.

+
+ +
+
+token_metadata_enabled = True
+

Flag indicating whether internal token metadata is updated.

+

When disabled, the driver does not query node token information on connect, or on topology change events. This +can be used to speed initial connection, and reduce load on client and server during operation. It is most useful +in large clusters using vnodes, where the token map can be expensive to compute. Turning this off +gives away token aware request routing, and programmatic inspection of the token ring.

+
+ +
+
+timestamp_generator = None
+
+ +
+
+endpoint_factory = None
+
+ +
+
+cloud = None
+
+ +
+
+connect(keyspace=None, wait_for_all_pools=False)
+

Creates and returns a new Session object.

+

If keyspace is specified, that keyspace will be the default keyspace for +operations on the Session.

+

wait_for_all_pools specifies whether this call should wait for all connection pools to be +established or attempted. Default is False, which means it will return when the first +successful connection is established. Remaining pools are added asynchronously.

+
+ +
+
+shutdown()
+

Closes all sessions and connection associated with this Cluster. +To ensure all connections are properly closed, you should always +call shutdown() on a Cluster instance when you are done with it.

+

Once shutdown, a Cluster should not be used for any purpose.

+
+ +
+
+register_user_type(keyspace, user_type, klass)
+

Registers a class to use to represent a particular user-defined type. +Query parameters for this user-defined type will be assumed to be +instances of klass. Result sets for this user-defined type will +be instances of klass. If no class is registered for a user-defined +type, a namedtuple will be used for result sets, and non-prepared +statements may not encode parameters for this type correctly.

+

keyspace is the name of the keyspace that the UDT is defined in.

+

user_type is the string name of the UDT to register the mapping +for.

+

klass should be a class with attributes whose names match the +fields of the user-defined type. The constructor must accepts kwargs +for each of the fields in the UDT.

+

This method should only be called after the type has been created +within Cassandra.

+

Example:

+
cluster = Cluster(protocol_version=3)
+session = cluster.connect()
+session.set_keyspace('mykeyspace')
+session.execute("CREATE TYPE address (street text, zipcode int)")
+session.execute("CREATE TABLE users (id int PRIMARY KEY, location address)")
+
+# create a class to map to the "address" UDT
+class Address(object):
+
+    def __init__(self, street, zipcode):
+        self.street = street
+        self.zipcode = zipcode
+
+cluster.register_user_type('mykeyspace', 'address', Address)
+
+# insert a row using an instance of Address
+session.execute("INSERT INTO users (id, location) VALUES (%s, %s)",
+                (0, Address("123 Main St.", 78723)))
+
+# results will include Address instances
+results = session.execute("SELECT * FROM users")
+row = results[0]
+print row.id, row.location.street, row.location.zipcode
+
+
+
+ +
+
+register_listener(listener)
+

Adds a cassandra.policies.HostStateListener subclass instance to +the list of listeners to be notified when a host is added, removed, +marked up, or marked down.

+
+ +
+
+unregister_listener(listener)
+

Removes a registered listener.

+
+ +
+
+add_execution_profile(name, profile, pool_wait_timeout=5)
+

Adds an ExecutionProfile to the cluster. This makes it available for use by name in Session.execute() +and Session.execute_async(). This method will raise if the profile already exists.

+

Normally profiles will be injected at cluster initialization via Cluster(execution_profiles). This method +provides a way of adding them dynamically.

+

Adding a new profile updates the connection pools according to the specified load_balancing_policy. By default, +this method will wait up to five seconds for the pool creation to complete, so the profile can be used immediately +upon return. This behavior can be controlled using pool_wait_timeout (see +concurrent.futures.wait +for timeout semantics).

+
+ +
+
+set_max_requests_per_connection(host_distance, max_requests)
+

Sets a threshold for concurrent requests per connection, above which new +connections will be created to a host (up to max connections; +see set_max_connections_per_host()).

+

Pertains to connection pool management in protocol versions {1,2}.

+
+ +
+
+get_max_requests_per_connection(host_distance)
+
+ +
+
+set_min_requests_per_connection(host_distance, min_requests)
+

Sets a threshold for concurrent requests per connection, below which +connections will be considered for disposal (down to core connections; +see set_core_connections_per_host()).

+

Pertains to connection pool management in protocol versions {1,2}.

+
+ +
+
+get_min_requests_per_connection(host_distance)
+
+ +
+
+get_core_connections_per_host(host_distance)
+

Gets the minimum number of connections per Session that will be opened +for each host with HostDistance equal to host_distance. +The default is 2 for LOCAL and 1 for +REMOTE.

+

This property is ignored if protocol_version is +3 or higher.

+
+ +
+
+set_core_connections_per_host(host_distance, core_connections)
+

Sets the minimum number of connections per Session that will be opened +for each host with HostDistance equal to host_distance. +The default is 2 for LOCAL and 1 for +REMOTE.

+

Protocol version 1 and 2 are limited in the number of concurrent +requests they can send per connection. The driver implements connection +pooling to support higher levels of concurrency.

+

If protocol_version is set to 3 or higher, this +is not supported (there is always one connection per host, unless +the host is remote and connect_to_remote_hosts is False) +and using this will result in an UnsupportedOperation.

+
+ +
+
+get_max_connections_per_host(host_distance)
+

Gets the maximum number of connections per Session that will be opened +for each host with HostDistance equal to host_distance. +The default is 8 for LOCAL and 2 for +REMOTE.

+

This property is ignored if protocol_version is +3 or higher.

+
+ +
+
+set_max_connections_per_host(host_distance, max_connections)
+

Sets the maximum number of connections per Session that will be opened +for each host with HostDistance equal to host_distance. +The default is 2 for LOCAL and 1 for +REMOTE.

+

If protocol_version is set to 3 or higher, this +is not supported (there is always one connection per host, unless +the host is remote and connect_to_remote_hosts is False) +and using this will result in an UnsupportedOperation.

+
+ +
+
+get_control_connection_host()
+

Returns the control connection host metadata.

+
+ +
+
+refresh_schema_metadata(max_schema_agreement_wait=None)
+

Synchronously refresh all schema metadata.

+

By default, the timeout for this operation is governed by max_schema_agreement_wait +and control_connection_timeout.

+

Passing max_schema_agreement_wait here overrides max_schema_agreement_wait.

+

Setting max_schema_agreement_wait <= 0 will bypass schema agreement and refresh schema immediately.

+

An Exception is raised if schema refresh fails for any reason.

+
+ +
+
+refresh_keyspace_metadata(keyspace, max_schema_agreement_wait=None)
+

Synchronously refresh keyspace metadata. This applies to keyspace-level information such as replication +and durability settings. It does not refresh tables, types, etc. contained in the keyspace.

+

See refresh_schema_metadata() for description of max_schema_agreement_wait behavior

+
+ +
+
+refresh_table_metadata(keyspace, table, max_schema_agreement_wait=None)
+

Synchronously refresh table metadata. This applies to a table, and any triggers or indexes attached +to the table.

+

See refresh_schema_metadata() for description of max_schema_agreement_wait behavior

+
+ +
+
+refresh_user_type_metadata(keyspace, user_type, max_schema_agreement_wait=None)
+

Synchronously refresh user defined type metadata.

+

See refresh_schema_metadata() for description of max_schema_agreement_wait behavior

+
+ +
+
+refresh_user_function_metadata(keyspace, function, max_schema_agreement_wait=None)
+

Synchronously refresh user defined function metadata.

+

function is a cassandra.UserFunctionDescriptor.

+

See refresh_schema_metadata() for description of max_schema_agreement_wait behavior

+
+ +
+
+refresh_user_aggregate_metadata(keyspace, aggregate, max_schema_agreement_wait=None)
+

Synchronously refresh user defined aggregate metadata.

+

aggregate is a cassandra.UserAggregateDescriptor.

+

See refresh_schema_metadata() for description of max_schema_agreement_wait behavior

+
+ +
+
+refresh_nodes(force_token_rebuild=False)
+

Synchronously refresh the node list and token metadata

+

force_token_rebuild can be used to rebuild the token map metadata, even if no new nodes are discovered.

+

An Exception is raised if node refresh fails for any reason.

+
+ +
+
+set_meta_refresh_enabled(enabled)
+

Deprecated: set schema_metadata_enabled token_metadata_enabled instead

+

Sets a flag to enable (True) or disable (False) all metadata refresh queries. +This applies to both schema and node topology.

+

Disabling this is useful to minimize refreshes during multiple changes.

+

Meta refresh must be enabled for the driver to become aware of any cluster +topology changes or schema updates.

+
+ +
+ +
+
+class cassandra.cluster.ExecutionProfile(load_balancing_policy=<object object>, retry_policy=None, consistency_level=ConsistencyLevel.LOCAL_ONE, serial_consistency_level=None, request_timeout=10.0, row_factory=<function named_tuple_factory>, speculative_execution_policy=None)
+
+
+consistency_level = LOCAL_ONE
+
+ +
+
+static row_factory(colnames, rows)
+

Returns each row as a namedtuple. +This is the default row factory.

+

Example:

+
>>> from cassandra.query import named_tuple_factory
+>>> session = cluster.connect('mykeyspace')
+>>> session.row_factory = named_tuple_factory
+>>> rows = session.execute("SELECT name, age FROM users LIMIT 1")
+>>> user = rows[0]
+
+>>> # you can access field by their name:
+>>> print "name: %s, age: %d" % (user.name, user.age)
+name: Bob, age: 42
+
+>>> # or you can access fields by their position (like a tuple)
+>>> name, age = user
+>>> print "name: %s, age: %d" % (name, age)
+name: Bob, age: 42
+>>> name = user[0]
+>>> age = user[1]
+>>> print "name: %s, age: %d" % (name, age)
+name: Bob, age: 42
+
+
+
+

Changed in version 2.0.0: moved from cassandra.decoder to cassandra.query

+
+
+ +
+ +
+
+class cassandra.cluster.GraphExecutionProfile(load_balancing_policy=_NOT_SET, retry_policy=None, consistency_level=ConsistencyLevel.LOCAL_ONE, serial_consistency_level=None, request_timeout=30.0, row_factory=None, graph_options=None, continuous_paging_options=_NOT_SET)
+

Default execution profile for graph execution.

+

See ExecutionProfile for base attributes. Note that if not explicitly set, +the row_factory and graph_options.graph_protocol are resolved during the query execution. +These options will resolve to graph_graphson3_row_factory and GraphProtocol.GRAPHSON_3_0 +for the core graph engine (DSE 6.8+), otherwise graph_object_row_factory and GraphProtocol.GRAPHSON_1_0

+

In addition to default parameters shown in the signature, this profile also defaults retry_policy to +cassandra.policies.NeverRetryPolicy.

+
+ +
+
+class cassandra.cluster.GraphAnalyticsExecutionProfile(load_balancing_policy=None, retry_policy=None, consistency_level=ConsistencyLevel.LOCAL_ONE, serial_consistency_level=None, request_timeout=3600.0 * 24.0 * 7.0, row_factory=None, graph_options=None)
+

Execution profile with timeout and load balancing appropriate for graph analytics queries.

+

See also GraphExecutionPolicy.

+

In addition to default parameters shown in the signature, this profile also defaults retry_policy to +cassandra.policies.NeverRetryPolicy, and load_balancing_policy to one that targets the current Spark +master.

+

Note: The graph_options.graph_source is set automatically to b’a’ (analytics) +when using GraphAnalyticsExecutionProfile. This is mandatory to target analytics nodes.

+
+ +
+
+cassandra.cluster.EXEC_PROFILE_DEFAULT
+

The most base type

+
+ +
+
+cassandra.cluster.EXEC_PROFILE_GRAPH_DEFAULT
+

The most base type

+
+ +
+
+cassandra.cluster.EXEC_PROFILE_GRAPH_SYSTEM_DEFAULT
+

The most base type

+
+ +
+
+cassandra.cluster.EXEC_PROFILE_GRAPH_ANALYTICS_DEFAULT
+

The most base type

+
+ +
+
+class cassandra.cluster.Session
+

A collection of connection pools for each host in the cluster. +Instances of this class should not be created directly, only +using Cluster.connect().

+

Queries and statements can be executed through Session instances +using the execute() and execute_async() +methods.

+

Example usage:

+
>>> session = cluster.connect()
+>>> session.set_keyspace("mykeyspace")
+>>> session.execute("SELECT * FROM mycf")
+
+
+
+
+default_timeout = 10.0
+

A default timeout, measured in seconds, for queries executed through +execute() or execute_async(). This default may be +overridden with the timeout parameter for either of those methods.

+

Setting this to None will cause no timeouts to be set by default.

+

Please see ResponseFuture.result() for details on the scope and +effect of this timeout.

+
+

New in version 2.0.0.

+
+
+ +
+
+default_consistency_level = LOCAL_ONE
+

Deprecated: use execution profiles instead +The default ConsistencyLevel for operations executed through +this session. This default may be overridden by setting the +consistency_level on individual statements.

+
+

New in version 1.2.0.

+
+
+

Changed in version 3.0.0: default changed from ONE to LOCAL_ONE

+
+
+ +
+
+default_serial_consistency_level = None
+

The default ConsistencyLevel for serial phase of conditional updates executed through +this session. This default may be overridden by setting the +serial_consistency_level on individual statements.

+

Only valid for protocol_version >= 2.

+
+ +
+
+row_factory = <function named_tuple_factory>
+

The format to return row results in. By default, each +returned row will be a named tuple. You can alternatively +use any of the following:

+ +
+ +
+
+default_fetch_size = 5000
+
+ +
+
+use_client_timestamp = True
+
+ +
+
+timestamp_generator = None
+
+ +
+
+encoder = None
+
+ +
+
+client_protocol_handler = <class 'cassandra.protocol.cython_protocol_handler.<locals>.CythonProtocolHandler'>
+
+ +
+
+execute(statement[, parameters][, timeout][, trace][, custom_payload][, paging_state][, host][, execute_as])
+

Execute the given query and synchronously wait for the response.

+

If an error is encountered while executing the query, an Exception +will be raised.

+

query may be a query string or an instance of cassandra.query.Statement.

+

parameters may be a sequence or dict of parameters to bind. If a +sequence is used, %s should be used the placeholder for each +argument. If a dict is used, %(name)s style placeholders must +be used.

+

timeout should specify a floating-point timeout (in seconds) after +which an OperationTimedOut exception will be raised if the query +has not completed. If not set, the timeout defaults to the request_timeout of the selected execution_profile. +If set to None, there is no timeout. Please see ResponseFuture.result() for details on +the scope and effect of this timeout.

+

If trace is set to True, the query will be sent with tracing enabled. +The trace details can be obtained using the returned ResultSet object.

+

custom_payload is a Custom Payloads dict to be passed to the server. +If query is a Statement with its own custom_payload. The message payload +will be a union of the two, with the values specified here taking precedence.

+

execution_profile is the execution profile to use for this request. It can be a key to a profile configured +via Cluster.add_execution_profile() or an instance (from Session.execution_profile_clone_update(), +for example

+

paging_state is an optional paging state, reused from a previous ResultSet.

+

host is the cassandra.pool.Host that should handle the query. If the host specified is down or +not yet connected, the query will fail with NoHostAvailable. Using this is +discouraged except in a few cases, e.g., querying node-local tables and applying schema changes.

+

execute_as the user that will be used on the server to execute the request. This is only available +on a DSE cluster.

+
+ +
+
+execute_async(statement[, parameters][, trace][, custom_payload][, paging_state][, host][, execute_as])
+

Execute the given query and return a ResponseFuture object +which callbacks may be attached to for asynchronous response +delivery. You may also call result() +on the ResponseFuture to synchronously block for results at +any time.

+

See Session.execute() for parameter definitions.

+

Example usage:

+
>>> session = cluster.connect()
+>>> future = session.execute_async("SELECT * FROM mycf")
+
+>>> def log_results(results):
+...     for row in results:
+...         log.info("Results: %s", row)
+
+>>> def log_error(exc):
+>>>     log.error("Operation failed: %s", exc)
+
+>>> future.add_callbacks(log_results, log_error)
+
+
+

Async execution with blocking wait for results:

+
>>> future = session.execute_async("SELECT * FROM mycf")
+>>> # do other stuff...
+
+>>> try:
+...     results = future.result()
+... except Exception:
+...     log.exception("Operation failed:")
+
+
+
+ +
+
+execute_graph(statement[, parameters][, trace][, execution_profile=EXEC_PROFILE_GRAPH_DEFAULT][, execute_as])
+

Executes a Gremlin query string or GraphStatement synchronously, +and returns a ResultSet from this execution.

+

parameters is dict of named parameters to bind. The values must be +JSON-serializable.

+

execution_profile: Selects an execution profile for the request.

+

execute_as the user that will be used on the server to execute the request.

+
+ +
+
+execute_graph_async(statement[, parameters][, trace][, execution_profile=EXEC_PROFILE_GRAPH_DEFAULT][, execute_as])
+

Execute the graph query and return a ResponseFuture +object which callbacks may be attached to for asynchronous response delivery. You may also call ResponseFuture.result() to synchronously block for +results at any time.

+
+ +
+
+prepare(statement)
+

Prepares a query string, returning a PreparedStatement +instance which can be used as follows:

+
>>> session = cluster.connect("mykeyspace")
+>>> query = "INSERT INTO users (id, name, age) VALUES (?, ?, ?)"
+>>> prepared = session.prepare(query)
+>>> session.execute(prepared, (user.id, user.name, user.age))
+
+
+

Or you may bind values to the prepared statement ahead of time:

+
>>> prepared = session.prepare(query)
+>>> bound_stmt = prepared.bind((user.id, user.name, user.age))
+>>> session.execute(bound_stmt)
+
+
+

Of course, prepared statements may (and should) be reused:

+
>>> prepared = session.prepare(query)
+>>> for user in users:
+...     bound = prepared.bind((user.id, user.name, user.age))
+...     session.execute(bound)
+
+
+

Alternatively, if protocol_version is 5 or higher +(requires Cassandra 4.0+), the keyspace can be specified as a +parameter. This will allow you to avoid specifying the keyspace in the +query without specifying a keyspace in connect(). It +even will let you prepare and use statements against a keyspace other +than the one originally specified on connection:

+
>>> analyticskeyspace_prepared = session.prepare(
+...     "INSERT INTO user_activity id, last_activity VALUES (?, ?)",
+...     keyspace="analyticskeyspace")  # note the different keyspace
+
+
+

Important: PreparedStatements should be prepared only once. +Preparing the same query more than once will likely affect performance.

+

custom_payload is a key value map to be passed along with the prepare +message. See Custom Payloads.

+
+ +
+
+shutdown()
+

Close all connections. Session instances should not be used +for any purpose after being shutdown.

+
+ +
+
+set_keyspace(keyspace)
+

Set the default keyspace for all queries made through this Session. +This operation blocks until complete.

+
+ +
+
+get_execution_profile(name)
+

Returns the execution profile associated with the provided name.

+
+
Parameters
+

name – The name (or key) of the execution profile.

+
+
+
+ +
+
+execution_profile_clone_update(ep, **kwargs)
+

Returns a clone of the ep profile. kwargs can be specified to update attributes +of the returned profile.

+

This is a shallow clone, so any objects referenced by the profile are shared. This means Load Balancing Policy +is maintained by inclusion in the active profiles. It also means updating any other rich objects will be seen +by the active profile. In cases where this is not desirable, be sure to replace the instance instead of manipulating +the shared object.

+
+ +
+
+add_request_init_listener(fn, *args, **kwargs)
+

Adds a callback with arguments to be called when any request is created.

+

It will be invoked as fn(response_future, *args, **kwargs) after each client request is created, +and before the request is sent. This can be used to create extensions by adding result callbacks to the +response future.

+

response_future is the ResponseFuture for the request.

+

Note that the init callback is done on the client thread creating the request, so you may need to consider +synchronization if you have multiple threads. Any callbacks added to the response future will be executed +on the event loop thread, so the normal advice about minimizing cycles and avoiding blocking apply (see Note in +ResponseFuture.add_callbacks().

+

See this example in the +source tree for an example.

+
+ +
+
+remove_request_init_listener(fn, *args, **kwargs)
+

Removes a callback and arguments from the list.

+

See Session.add_request_init_listener().

+
+ +
+ +
+
+class cassandra.cluster.ResponseFuture
+

An asynchronous response delivery mechanism that is returned from calls +to Session.execute_async().

+
+
There are two ways for results to be delivered:
+
+
+
+
+query = None
+
+ +
+
+result()
+

Return the final result or raise an Exception if errors were +encountered. If the final result or error has not been set +yet, this method will block until it is set, or the timeout +set for the request expires.

+

Timeout is specified in the Session request execution functions. +If the timeout is exceeded, an cassandra.OperationTimedOut will be raised. +This is a client-side timeout. For more information +about server-side coordinator timeouts, see policies.RetryPolicy.

+

Example usage:

+
>>> future = session.execute_async("SELECT * FROM mycf")
+>>> # do other stuff...
+
+>>> try:
+...     rows = future.result()
+...     for row in rows:
+...         ... # process results
+... except Exception:
+...     log.exception("Operation failed:")
+
+
+
+ +
+
+get_query_trace()
+

Fetches and returns the query trace of the last response, or None if tracing was +not enabled.

+

Note that this may raise an exception if there are problems retrieving the trace +details from Cassandra. If the trace is not available after max_wait, +cassandra.query.TraceUnavailable will be raised.

+

If the ResponseFuture is not done (async execution) and you try to retrieve the trace, +cassandra.query.TraceUnavailable will be raised.

+

query_cl is the consistency level used to poll the trace tables.

+
+ +
+
+get_all_query_traces()
+

Fetches and returns the query traces for all query pages, if tracing was enabled.

+

See note in get_query_trace() regarding possible exceptions.

+
+ +
+
+custom_payload
+

The custom payload returned from the server, if any. This will only be +set by Cassandra servers implementing a custom QueryHandler, and only +for protocol_version 4+.

+

Ensure the future is complete before trying to access this property +(call result(), or after callback is invoked). +Otherwise it may throw if the response has not been received.

+
+
Returns
+

Custom Payloads.

+
+
+
+ +
+
+is_schema_agreed = True
+
+ +
+
+has_more_pages
+

Returns True if there are more pages left in the +query results, False otherwise. This should only +be checked after the first page has been returned.

+
+

New in version 2.0.0.

+
+
+ +
+
+warnings
+

Warnings returned from the server, if any. This will only be +set for protocol_version 4+.

+

Warnings may be returned for such things as oversized batches, +or too many tombstones in slice queries.

+

Ensure the future is complete before trying to access this property +(call result(), or after callback is invoked). +Otherwise it may throw if the response has not been received.

+
+ +
+
+start_fetching_next_page()
+

If there are more pages left in the query result, this asynchronously +starts fetching the next page. If there are no pages left, QueryExhausted +is raised. Also see has_more_pages.

+

This should only be called after the first page has been returned.

+
+

New in version 2.0.0.

+
+
+ +
+
+add_callback(fn, *args, **kwargs)
+

Attaches a callback function to be called when the final results arrive.

+

By default, fn will be called with the results as the first and only +argument. If *args or **kwargs are supplied, they will be passed +through as additional positional or keyword arguments to fn.

+

If an error is hit while executing the operation, a callback attached +here will not be called. Use add_errback() or add_callbacks() +if you wish to handle that case.

+

If the final result has already been seen when this method is called, +the callback will be called immediately (before this method returns).

+

Note: in the case that the result is not available when the callback is added, +the callback is executed by IO event thread. This means that the callback +should not block or attempt further synchronous requests, because no further +IO will be processed until the callback returns.

+

Important: if the callback you attach results in an exception being +raised, the exception will be ignored, so please ensure your +callback handles all error cases that you care about.

+

Usage example:

+
>>> session = cluster.connect("mykeyspace")
+
+>>> def handle_results(rows, start_time, should_log=False):
+...     if should_log:
+...         log.info("Total time: %f", time.time() - start_time)
+...     ...
+
+>>> future = session.execute_async("SELECT * FROM users")
+>>> future.add_callback(handle_results, time.time(), should_log=True)
+
+
+
+ +
+
+add_errback(fn, *args, **kwargs)
+

Like add_callback(), but handles error cases. +An Exception instance will be passed as the first positional argument +to fn.

+
+ +
+
+ResponseFuture.add_callbacks(callback, errback, callback_args=(), callback_kwargs=None, errback_args=(), errback_args=None)
+

A convenient combination of add_callback() and +add_errback().

+

Example usage:

+
>>> session = cluster.connect()
+>>> query = "SELECT * FROM mycf"
+>>> future = session.execute_async(query)
+
+>>> def log_results(results, level='debug'):
+...     for row in results:
+...         log.log(level, "Result: %s", row)
+
+>>> def log_error(exc, query):
+...     log.error("Query '%s' failed: %s", query, exc)
+
+>>> future.add_callbacks(
+...     callback=log_results, callback_kwargs={'level': 'info'},
+...     errback=log_error, errback_args=(query,))
+
+
+
+ +
+ +
+
+class cassandra.cluster.ResultSet
+

An iterator over the rows from a query result. Also supplies basic equality +and indexing methods for backward-compatability. These methods materialize +the entire result set (loading all pages), and should only be used if the +total result size is understood. Warnings are emitted when paged results +are materialized in this fashion.

+

You can treat this as a normal iterator over rows:

+
>>> from cassandra.query import SimpleStatement
+>>> statement = SimpleStatement("SELECT * FROM users", fetch_size=10)
+>>> for user_row in session.execute(statement):
+...     process_user(user_row)
+
+
+

Whenever there are no more rows in the current page, the next page will +be fetched transparently. However, note that it is possible for +an Exception to be raised while fetching the next page, just +like you might see on a normal call to session.execute().

+
+
+all()
+

Returns all the remaining rows as a list. This is basically +a convenient shortcut to list(result_set).

+

This function is not recommended for queries that return a large number of elements.

+
+ +
+
+property current_rows
+

The list of current page rows. May be empty if the result was empty, +or this is the last page.

+
+ +
+
+fetch_next_page()
+

Manually, synchronously fetch the next page. Supplied for manually retrieving pages +and inspecting current_page(). It is not necessary to call this when iterating +through results; paging happens implicitly in iteration.

+
+ +
+
+get_all_query_traces(max_wait_sec_per=None)
+

Gets all query traces from the associated future. +See ResponseFuture.get_all_query_traces() for details.

+
+ +
+
+get_query_trace(max_wait_sec=None)
+

Gets the last query trace from the associated future. +See ResponseFuture.get_query_trace() for details.

+
+ +
+
+property has_more_pages
+

True if the last response indicated more pages; False otherwise

+
+ +
+
+one()
+

Return a single row of the results or None if empty. This is basically +a shortcut to result_set.current_rows[0] and should only be used when +you know a query returns a single row. Consider using an iterator if the +ResultSet contains more than one row.

+
+ +
+
+property paging_state
+

Server paging state of the query. Can be None if the query was not paged.

+

The driver treats paging state as opaque, but it may contain primary key data, so applications may want to +avoid sending this to untrusted parties.

+
+ +
+
+property was_applied
+

For LWT results, returns whether the transaction was applied.

+

Result is indeterminate if called on a result that was not an LWT request or on +a query.BatchStatement containing LWT. In the latter case either all the batch +succeeds or fails.

+

Only valid when one of the of the internal row factories is in use.

+
+ +
+ +
+
+exception cassandra.cluster.QueryExhausted
+

Raised when ResponseFuture.start_fetching_next_page() is called and +there are no more pages. You can check ResponseFuture.has_more_pages +before calling to avoid this.

+
+

New in version 2.0.0.

+
+
+ +
+
+exception cassandra.cluster.NoHostAvailable
+

Raised when an operation is attempted but all connections are +busy, defunct, closed, or resulted in errors when used.

+
+ +
+
+exception cassandra.cluster.UserTypeDoesNotExist
+

An attempt was made to use a user-defined type that does not exist.

+
+

New in version 2.1.0.

+
+
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.25.11-scylla/api/cassandra/concurrent.html b/3.25.11-scylla/api/cassandra/concurrent.html new file mode 100644 index 0000000000..8f83ba6137 --- /dev/null +++ b/3.25.11-scylla/api/cassandra/concurrent.html @@ -0,0 +1,710 @@ + + + + + + + + + + + + + cassandra.concurrent - Utilities for Concurrent Statement Execution | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.concurrent - Utilities for Concurrent Statement Execution

+
+
+cassandra.concurrent.execute_concurrent(session, statements_and_parameters, concurrency=100, raise_on_first_error=True, results_generator=False, execution_profile=<object object>)
+

Executes a sequence of (statement, parameters) tuples concurrently. Each +parameters item must be a sequence or None.

+

The concurrency parameter controls how many statements will be executed +concurrently. When Cluster.protocol_version is set to 1 or 2, +it is recommended that this be kept below 100 times the number of +core connections per host times the number of connected hosts (see +Cluster.set_core_connections_per_host()). If that amount is exceeded, +the event loop thread may attempt to block on new connection creation, +substantially impacting throughput. If protocol_version +is 3 or higher, you can safely experiment with higher levels of concurrency.

+

If raise_on_first_error is left as True, execution will stop +after the first failed statement and the corresponding exception will be +raised.

+

results_generator controls how the results are returned.

+
    +
  • If False, the results are returned only after all requests have completed.

  • +
  • If True, a generator expression is returned. Using a generator results in a constrained +memory footprint when the results set will be large – results are yielded +as they return instead of materializing the entire list at once. The trade for lower memory +footprint is marginal CPU overhead (more thread coordination and sorting out-of-order results +on-the-fly).

  • +
+

execution_profile argument is the execution profile to use for this +request, it is passed directly to Session.execute_async().

+

A sequence of ExecutionResult(success, result_or_exc) namedtuples is returned +in the same order that the statements were passed in. If success is False, +there was an error executing the statement, and result_or_exc will be +an Exception. If success is True, result_or_exc +will be the query result.

+

Example usage:

+
select_statement = session.prepare("SELECT * FROM users WHERE id=?")
+
+statements_and_params = []
+for user_id in user_ids:
+    params = (user_id, )
+    statements_and_params.append((select_statement, params))
+
+results = execute_concurrent(
+    session, statements_and_params, raise_on_first_error=False)
+
+for (success, result) in results:
+    if not success:
+        handle_error(result)  # result will be an Exception
+    else:
+        process_user(result[0])  # result will be a list of rows
+
+
+

Note: in the case that generators are used, it is important to ensure the consumers do not +block or attempt further synchronous requests, because no further IO will be processed until +the consumer returns. This may also produce a deadlock in the IO event thread.

+
+ +
+
+cassandra.concurrent.execute_concurrent_with_args(session, statement, parameters, *args, **kwargs)
+

Like execute_concurrent(), but takes a single +statement and a sequence of parameters. Each item in parameters +should be a sequence or None.

+

Example usage:

+
statement = session.prepare("INSERT INTO mytable (a, b) VALUES (1, ?)")
+parameters = [(x,) for x in range(1000)]
+execute_concurrent_with_args(session, statement, parameters, concurrency=50)
+
+
+
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.25.11-scylla/api/cassandra/connection.html b/3.25.11-scylla/api/cassandra/connection.html new file mode 100644 index 0000000000..ab6b61fe20 --- /dev/null +++ b/3.25.11-scylla/api/cassandra/connection.html @@ -0,0 +1,738 @@ + + + + + + + + + + + + + cassandra.connection - Low Level Connection Info | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.connection - Low Level Connection Info

+
+
+exception cassandra.connection.ConnectionException
+

An unrecoverable error was hit when attempting to use a connection, +or the connection was already closed or defunct.

+
+ +
+
+exception cassandra.connection.ConnectionShutdown
+

Raised when a connection has been marked as defunct or has been closed.

+
+ +
+
+exception cassandra.connection.ConnectionBusy
+

An attempt was made to send a message through a Connection that +was already at the max number of in-flight operations.

+
+ +
+
+exception cassandra.connection.ProtocolError
+

Communication did not match the protocol that this driver expects.

+
+ +
+
+class cassandra.connection.EndPoint
+

Represents the information to connect to a cassandra node.

+
+
+property address
+

The IP address of the node. This is the RPC address the driver uses when connecting to the node

+
+ +
+
+property port
+

The port of the node.

+
+ +
+
+resolve()
+

Resolve the endpoint to an address/port. This is called +only on socket connection.

+
+ +
+
+property socket_family
+

The socket family of the endpoint.

+
+ +
+
+property ssl_options
+

SSL options specific to this endpoint.

+
+ +
+ +
+
+class cassandra.connection.EndPointFactory
+
+
+configure(cluster)
+

This is called by the cluster during its initialization.

+
+ +
+
+create(row)
+

Create an EndPoint from a system.peers row.

+
+ +
+ +
+
+class cassandra.connection.SniEndPoint(proxy_address, server_name, port=9042)
+

SNI Proxy EndPoint implementation.

+
+ +
+
+class cassandra.connection.SniEndPointFactory(proxy_address, port, node_domain=None)
+
+ +
+
+class cassandra.connection.UnixSocketEndPoint(unix_socket_path)
+

Unix Socket EndPoint implementation.

+
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.25.11-scylla/api/cassandra/cqlengine/columns.html b/3.25.11-scylla/api/cassandra/cqlengine/columns.html new file mode 100644 index 0000000000..d7544df0a6 --- /dev/null +++ b/3.25.11-scylla/api/cassandra/cqlengine/columns.html @@ -0,0 +1,956 @@ + + + + + + + + + + + + + cassandra.cqlengine.columns - Column types for object mapping models | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.cqlengine.columns - Column types for object mapping models

+
+

Columns

+

Columns in your models map to columns in your CQL table. You define CQL columns by defining column attributes on your model classes. +For a model to be valid it needs at least one primary key column and one non-primary key column.

+

Just as in CQL, the order you define your columns in is important, and is the same order they are defined in on a model’s corresponding table.

+

Each column on your model definitions needs to be an instance of a Column class.

+
+
+class cassandra.cqlengine.columns.Column(**kwargs)
+
+
+primary_key = False
+

bool flag, indicates this column is a primary key. The first primary key defined +on a model is the partition key (unless partition keys are set), all others are cluster keys

+
+ +
+
+partition_key = False
+

indicates that this column should be the partition key, defining +more than one partition key column creates a compound partition key

+
+ +
+
+index = False
+

bool flag, indicates an index should be created for this column

+
+ +
+
+custom_index = False
+

bool flag, indicates an index is managed outside of cqlengine. This is +useful if you want to do filter queries on fields that have custom +indexes.

+
+ +
+
+db_field = None
+

the fieldname this field will map to in the database

+
+ +
+
+default = None
+

the default value, can be a value or a callable (no args)

+
+ +
+
+required = False
+

boolean, is the field required? Model validation will raise and +exception if required is set to True and there is a None value assigned

+
+ +
+
+clustering_order = None
+

only applicable on clustering keys (primary keys that are not partition keys) +determines the order that the clustering keys are sorted on disk

+
+ +
+
+discriminator_column = False
+

boolean, if set to True, this column will be used for discriminating records +of inherited models.

+

Should only be set on a column of an abstract model being used for inheritance.

+

There may only be one discriminator column per model. See __discriminator_value__ +for how to specify the value of this column on specialized models.

+
+ +
+
+static = False
+

boolean, if set to True, this is a static column, with a single value per partition

+
+ +
+ +
+
+

Column Types

+

Columns of all types are initialized by passing Column attributes to the constructor by keyword.

+
+
+class cassandra.cqlengine.columns.Ascii(**kwargs)
+

Stores a US-ASCII character string

+
+
Parameters
+
    +
  • min_length (int) – Sets the minimum length of this string, for validation purposes. +Defaults to 1 if this is a required column. Otherwise, None.

  • +
  • max_length (int) – Sets the maximum length of this string, for validation purposes.

  • +
+
+
+
+ +
+
+class cassandra.cqlengine.columns.BigInt(**kwargs)
+

Stores a 64-bit signed integer value

+
+ +
+
+class cassandra.cqlengine.columns.Blob(**kwargs)
+

Stores a raw binary value

+
+ +
+
+cassandra.cqlengine.columns.Bytes
+

alias of cassandra.cqlengine.columns.Blob

+
+ +
+
+class cassandra.cqlengine.columns.Boolean(**kwargs)
+

Stores a boolean True or False value

+
+ +
+
+class cassandra.cqlengine.columns.Counter(index=False, db_field=None, required=False)
+

Stores a counter that can be incremented and decremented

+
+ +
+
+class cassandra.cqlengine.columns.Date(**kwargs)
+

Stores a simple date, with no time-of-day

+
+

Changed in version 2.6.0: removed overload of Date and DateTime. DateTime is a drop-in replacement for legacy models

+
+

requires C* 2.2+ and protocol v4+

+
+ +
+
+class cassandra.cqlengine.columns.DateTime(**kwargs)
+

Stores a datetime value

+
+
+truncate_microseconds = False
+

Set this True to have model instances truncate the date, quantizing it in the same way it will be in the database. +This allows equality comparison between assigned values and values read back from the database:

+
DateTime.truncate_microseconds = True
+assert Model.create(id=0, d=datetime.utcnow()) == Model.objects(id=0).first()
+
+
+

Defaults to False to preserve legacy behavior. May change in the future.

+
+ +
+ +
+
+class cassandra.cqlengine.columns.Decimal(**kwargs)
+

Stores a variable precision decimal value

+
+ +
+
+class cassandra.cqlengine.columns.Double(**kwargs)
+

Stores a double-precision floating-point value

+
+ +
+
+class cassandra.cqlengine.columns.Float(primary_key=False, partition_key=False, index=False, db_field=None, default=None, required=False, clustering_order=None, discriminator_column=False, static=False, custom_index=False)
+

Stores a single-precision floating-point value

+
+ +
+
+class cassandra.cqlengine.columns.Integer(**kwargs)
+

Stores a 32-bit signed integer value

+
+ +
+
+class cassandra.cqlengine.columns.List(value_type, default=<class 'list'>, **kwargs)
+

Stores a list of ordered values

+

http://www.datastax.com/documentation/cql/3.1/cql/cql_using/use_list_t.html

+
+
Parameters
+

value_type – a column class indicating the types of the value

+
+
+
+ +
+
+class cassandra.cqlengine.columns.Map(key_type, value_type, default=<class 'dict'>, **kwargs)
+

Stores a key -> value map (dictionary)

+

https://docs.datastax.com/en/dse/6.7/cql/cql/cql_using/useMap.html

+
+
Parameters
+
    +
  • key_type – a column class indicating the types of the key

  • +
  • value_type – a column class indicating the types of the value

  • +
+
+
+
+ +
+
+class cassandra.cqlengine.columns.Set(value_type, strict=True, default=<class 'set'>, **kwargs)
+

Stores a set of unordered, unique values

+

http://www.datastax.com/documentation/cql/3.1/cql/cql_using/use_set_t.html

+
+
Parameters
+
    +
  • value_type – a column class indicating the types of the value

  • +
  • strict – sets whether non set values will be coerced to set +type on validation, or raise a validation error, defaults to True

  • +
+
+
+
+ +
+
+class cassandra.cqlengine.columns.SmallInt(**kwargs)
+

Stores a 16-bit signed integer value

+
+

New in version 2.6.0.

+
+

requires C* 2.2+ and protocol v4+

+
+ +
+
+class cassandra.cqlengine.columns.Text(min_length=None, max_length=None, **kwargs)
+

Stores a UTF-8 encoded string

+
+
Parameters
+
    +
  • min_length (int) – Sets the minimum length of this string, for validation purposes. +Defaults to 1 if this is a required column. Otherwise, None.

  • +
  • max_length (int) – Sets the maximum length of this string, for validation purposes.

  • +
+
+
+
+ +
+
+class cassandra.cqlengine.columns.Time(**kwargs)
+

Stores a timezone-naive time-of-day, with nanosecond precision

+
+

New in version 2.6.0.

+
+

requires C* 2.2+ and protocol v4+

+
+ +
+
+class cassandra.cqlengine.columns.TimeUUID(**kwargs)
+

UUID containing timestamp

+
+ +
+
+class cassandra.cqlengine.columns.TinyInt(**kwargs)
+

Stores an 8-bit signed integer value

+
+

New in version 2.6.0.

+
+

requires C* 2.2+ and protocol v4+

+
+ +
+
+class cassandra.cqlengine.columns.UserDefinedType(user_type, **kwargs)
+

User Defined Type column

+

http://www.datastax.com/documentation/cql/3.1/cql/cql_using/cqlUseUDT.html

+

These columns are represented by a specialization of cassandra.cqlengine.usertype.UserType.

+

Please see User Defined Types for examples and discussion.

+
+
Parameters
+

user_type (type) – specifies the UserType model of the column

+
+
+
+ +
+
+class cassandra.cqlengine.columns.UUID(**kwargs)
+

Stores a type 1 or 4 UUID

+
+ +
+
+class cassandra.cqlengine.columns.VarInt(**kwargs)
+

Stores an arbitrary-precision integer

+
+ +
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.25.11-scylla/api/cassandra/cqlengine/connection.html b/3.25.11-scylla/api/cassandra/cqlengine/connection.html new file mode 100644 index 0000000000..0ac2f8fc99 --- /dev/null +++ b/3.25.11-scylla/api/cassandra/cqlengine/connection.html @@ -0,0 +1,717 @@ + + + + + + + + + + + + + cassandra.cqlengine.connection - Connection management for cqlengine | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.cqlengine.connection - Connection management for cqlengine

+
+
+cassandra.cqlengine.connection.default()
+

Configures the default connection to localhost, using the driver defaults +(except for row_factory)

+
+ +
+
+cassandra.cqlengine.connection.set_session(s)
+

Configures the default connection with a preexisting cassandra.cluster.Session

+

Note: the mapper presently requires a Session cassandra.cluster.Session.row_factory set to dict_factory. +This may be relaxed in the future

+
+ +
+
+cassandra.cqlengine.connection.setup(hosts, default_keyspace, consistency=None, lazy_connect=False, retry_connect=False, **kwargs)
+

Setup a the driver connection used by the mapper

+
+
Parameters
+
    +
  • hosts (list) – list of hosts, (contact_points for cassandra.cluster.Cluster)

  • +
  • default_keyspace (str) – The default keyspace to use

  • +
  • consistency (int) – The global default ConsistencyLevel - default is the same as Session.default_consistency_level

  • +
  • lazy_connect (bool) – True if should not connect until first use

  • +
  • retry_connect (bool) – True if we should retry to connect even if there was a connection failure initially

  • +
  • **kwargs – Pass-through keyword arguments for cassandra.cluster.Cluster

  • +
+
+
+
+ +
+
+cassandra.cqlengine.connection.register_connection(name, hosts=None, consistency=None, lazy_connect=False, retry_connect=False, cluster_options=None, default=False, session=None)
+

Add a connection to the connection registry. hosts and session are +mutually exclusive, and consistency, lazy_connect, +retry_connect, and cluster_options only work with hosts. Using +hosts will create a new cassandra.cluster.Cluster and +cassandra.cluster.Session.

+
+
Parameters
+
    +
  • hosts (list) – list of hosts, (contact_points for cassandra.cluster.Cluster).

  • +
  • consistency (int) – The default ConsistencyLevel for the +registered connection’s new session. Default is the same as +Session.default_consistency_level. For use with hosts only; +will fail when used with session.

  • +
  • lazy_connect (bool) – True if should not connect until first use. For +use with hosts only; will fail when used with session.

  • +
  • retry_connect (bool) – True if we should retry to connect even if there +was a connection failure initially. For use with hosts only; will +fail when used with session.

  • +
  • cluster_options (dict) – A dict of options to be used as keyword +arguments to cassandra.cluster.Cluster. For use with hosts +only; will fail when used with session.

  • +
  • default (bool) – If True, set the new connection as the cqlengine +default

  • +
  • session (Session) – A cassandra.cluster.Session to be used in +the created connection.

  • +
+
+
+
+ +
+
+cassandra.cqlengine.connection.unregister_connection(name)
+
+ +
+
+cassandra.cqlengine.connection.set_default_connection(name)
+
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.25.11-scylla/api/cassandra/cqlengine/management.html b/3.25.11-scylla/api/cassandra/cqlengine/management.html new file mode 100644 index 0000000000..02a60cf4e7 --- /dev/null +++ b/3.25.11-scylla/api/cassandra/cqlengine/management.html @@ -0,0 +1,739 @@ + + + + + + + + + + + + + cassandra.cqlengine.management - Schema management for cqlengine | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.cqlengine.management - Schema management for cqlengine

+

A collection of functions for managing keyspace and table schema.

+
+
+cassandra.cqlengine.management.create_keyspace_simple(name, replication_factor, durable_writes=True, connections=None)
+

Creates a keyspace with SimpleStrategy for replica placement

+

If the keyspace already exists, it will not be modified.

+

This function should be used with caution, especially in production environments. +Take care to execute schema modifications in a single context (i.e. not concurrently with other clients).

+

There are plans to guard schema-modifying functions with an environment-driven conditional.

+
+
Parameters
+
    +
  • name (str) – name of keyspace to create

  • +
  • replication_factor (int) – keyspace replication factor, used with SimpleStrategy

  • +
  • durable_writes (bool) – Write log is bypassed if set to False

  • +
  • connections (list) – List of connection names

  • +
+
+
+
+ +
+
+cassandra.cqlengine.management.create_keyspace_network_topology(name, dc_replication_map, durable_writes=True, connections=None)
+

Creates a keyspace with NetworkTopologyStrategy for replica placement

+

If the keyspace already exists, it will not be modified.

+

This function should be used with caution, especially in production environments. +Take care to execute schema modifications in a single context (i.e. not concurrently with other clients).

+

There are plans to guard schema-modifying functions with an environment-driven conditional.

+
+
Parameters
+
    +
  • name (str) – name of keyspace to create

  • +
  • dc_replication_map (dict) – map of dc_names: replication_factor

  • +
  • durable_writes (bool) – Write log is bypassed if set to False

  • +
  • connections (list) – List of connection names

  • +
+
+
+
+ +
+
+cassandra.cqlengine.management.drop_keyspace(name, connections=None)
+

Drops a keyspace, if it exists.

+

There are plans to guard schema-modifying functions with an environment-driven conditional.

+

This function should be used with caution, especially in production environments. +Take care to execute schema modifications in a single context (i.e. not concurrently with other clients).

+
+
Parameters
+
    +
  • name (str) – name of keyspace to drop

  • +
  • connections (list) – List of connection names

  • +
+
+
+
+ +
+
+cassandra.cqlengine.management.sync_table(model, keyspaces=None, connections=None)
+

Inspects the model and creates / updates the corresponding table and columns.

+

If keyspaces is specified, the table will be synched for all specified keyspaces. +Note that the Model.__keyspace__ is ignored in that case.

+

If connections is specified, the table will be synched for all specified connections. Note that the Model.__connection__ is ignored in that case. +If not specified, it will try to get the connection from the Model.

+

Any User Defined Types used in the table are implicitly synchronized.

+

This function can only add fields that are not part of the primary key.

+

Note that the attributes removed from the model are not deleted on the database. +They become effectively ignored by (will not show up on) the model.

+

This function should be used with caution, especially in production environments. +Take care to execute schema modifications in a single context (i.e. not concurrently with other clients).

+

There are plans to guard schema-modifying functions with an environment-driven conditional.

+
+ +
+
+cassandra.cqlengine.management.sync_type(ks_name, type_model, connection=None)
+

Inspects the type_model and creates / updates the corresponding type.

+

Note that the attributes removed from the type_model are not deleted on the database (this operation is not supported). +They become effectively ignored by (will not show up on) the type_model.

+

This function should be used with caution, especially in production environments. +Take care to execute schema modifications in a single context (i.e. not concurrently with other clients).

+

There are plans to guard schema-modifying functions with an environment-driven conditional.

+
+ +
+
+cassandra.cqlengine.management.drop_table(model, keyspaces=None, connections=None)
+

Drops the table indicated by the model, if it exists.

+

If keyspaces is specified, the table will be dropped for all specified keyspaces. Note that the Model.__keyspace__ is ignored in that case.

+

If connections is specified, the table will be synched for all specified connections. Note that the Model.__connection__ is ignored in that case. +If not specified, it will try to get the connection from the Model.

+

This function should be used with caution, especially in production environments. +Take care to execute schema modifications in a single context (i.e. not concurrently with other clients).

+

There are plans to guard schema-modifying functions with an environment-driven conditional.

+
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.25.11-scylla/api/cassandra/cqlengine/models.html b/3.25.11-scylla/api/cassandra/cqlengine/models.html new file mode 100644 index 0000000000..6f5b6c646c --- /dev/null +++ b/3.25.11-scylla/api/cassandra/cqlengine/models.html @@ -0,0 +1,944 @@ + + + + + + + + + + + + + cassandra.cqlengine.models - Table models for object mapping | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.cqlengine.models - Table models for object mapping

+
+

Model

+
+
+class cassandra.cqlengine.models.Model(\*\*kwargs)
+

The initializer creates an instance of the model. Pass in keyword arguments for columns you’ve defined on the model.

+
class Person(Model):
+    id = columns.UUID(primary_key=True)
+    first_name  = columns.Text()
+    last_name = columns.Text()
+
+person = Person(first_name='Blake', last_name='Eggleston')
+person.first_name  #returns 'Blake'
+person.last_name  #returns 'Eggleston'
+
+
+

Model attributes define how the model maps to tables in the database. These are class variables that should be set +when defining Model deriviatives.

+
+
+__abstract__ = False
+

Optional. Indicates that this model is only intended to be used as a base class for other models. +You can’t create tables for abstract models, but checks around schema validity are skipped during class construction.

+
+ +
+
+__table_name__ = None
+

Optional. Sets the name of the CQL table for this model. If left blank, the table name will be the name of the model, with it’s module name as it’s prefix. Manually defined table names are not inherited.

+
+ +
+
+__table_name_case_sensitive__ = False
+

Optional. By default, __table_name__ is case insensitive. Set this to True if you want to preserve the case sensitivity.

+
+ +
+
+__keyspace__ = None
+

Sets the name of the keyspace used by this model.

+
+ +
+
+__connection__ = None
+

Sets the name of the default connection used by this model.

+
+ +
+
+__default_ttl__ = None
+

Will be deprecated in release 4.0. You can set the default ttl by configuring the table __options__. See Default TTL and Per Query TTL for more details.

+
+ +
+
+__discriminator_value__ = None
+

Optional Specifies a value for the discriminator column when using model inheritance.

+

See Model Inheritance for usage examples.

+
+ +

Each table can have its own set of configuration options, including compaction. Unspecified, these default to sensible values in +the server. To override defaults, set options using the model __options__ attribute, which allows options specified a dict.

+

When a table is synced, it will be altered to match the options set on your table. +This means that if you are changing settings manually they will be changed back on resync.

+

Do not use the options settings of cqlengine if you want to manage your compaction settings manually.

+

See the list of supported table properties for more information.

+
+
+__options__
+

For example:

+
class User(Model):
+    __options__ = {'compaction': {'class': 'LeveledCompactionStrategy',
+                                  'sstable_size_in_mb': '64',
+                                  'tombstone_threshold': '.2'},
+                   'comment': 'User data stored here'}
+
+    user_id = columns.UUID(primary_key=True)
+    name = columns.Text()
+
+
+

or :

+
class TimeData(Model):
+    __options__ = {'compaction': {'class': 'SizeTieredCompactionStrategy',
+                                  'bucket_low': '.3',
+                                  'bucket_high': '2',
+                                  'min_threshold': '2',
+                                  'max_threshold': '64',
+                                  'tombstone_compaction_interval': '86400'},
+                   'gc_grace_seconds': '0'}
+
+
+
+ +
+
+__compute_routing_key__ = True
+

Optional Setting False disables computing the routing key for TokenAwareRouting

+
+ +

The base methods allow creating, storing, and querying modeled objects.

+
+
+classmethod create(**kwargs)
+

Create an instance of this model in the database.

+

Takes the model column values as keyword arguments. Setting a value to +None is equivalent to running a CQL DELETE on that column.

+

Returns the instance.

+
+ +
+
+if_not_exists()
+

Check the existence of an object before insertion. The existence of an +object is determined by its primary key(s). And please note using this flag +would incur performance cost.

+

If the insertion isn’t applied, a LWTException is raised.

+
try:
+    TestIfNotExistsModel.if_not_exists().create(id=id, count=9, text='111111111111')
+except LWTException as e:
+    # handle failure case
+    print e.existing  # dict containing LWT result fields
+
+
+

This method is supported on Cassandra 2.0 or later.

+
+ +
+
+if_exists()
+

Check the existence of an object before an update or delete. The existence of an +object is determined by its primary key(s). And please note using this flag +would incur performance cost.

+

If the update or delete isn’t applied, a LWTException is raised.

+
try:
+    TestIfExistsModel.objects(id=id).if_exists().update(count=9, text='111111111111')
+except LWTException as e:
+    # handle failure case
+    pass
+
+
+

This method is supported on Cassandra 2.0 or later.

+
+ +
+
+save()
+

Saves an object to the database.

+
#create a person instance
+person = Person(first_name='Kimberly', last_name='Eggleston')
+#saves it to Cassandra
+person.save()
+
+
+
+ +
+
+update(**values)
+

Performs an update on the model instance. You can pass in values to set on the model +for updating, or you can call without values to execute an update against any modified +fields. If no fields on the model have been modified since loading, no query will be +performed. Model validation is performed normally. Setting a value to None is +equivalent to running a CQL DELETE on that column.

+

It is possible to do a blind update, that is, to update a field without having first selected the object out of the database. +See Blind Updates

+
+ +
+
+iff(**values)
+

Checks to ensure that the values specified are correct on the Cassandra cluster. +Simply specify the column(s) and the expected value(s). As with if_not_exists, +this incurs a performance cost.

+

If the insertion isn’t applied, a LWTException is raised.

+
t = TestTransactionModel(text='some text', count=5)
+try:
+     t.iff(count=5).update('other text')
+except LWTException as e:
+    # handle failure case
+    print e.existing # existing object
+
+
+
+ +
+
+classmethod get(*args, **kwargs)
+

Returns a single object based on the passed filter constraints.

+

This is a pass-through to the model objects().:method:~cqlengine.queries.get.

+
+ +
+
+classmethod filter(*args, **kwargs)
+

Returns a queryset based on filter parameters.

+

This is a pass-through to the model objects().:method:~cqlengine.queries.filter.

+
+ +
+
+classmethod all()
+

Returns a queryset representing all stored objects

+

This is a pass-through to the model objects().all()

+
+ +
+
+delete()
+

Deletes the object from the database

+
+ +
+
+batch(batch_object)
+

Sets the batch object to run instance updates and inserts queries with.

+

See Batch Queries for usage examples

+
+ +
+
+timeout(timeout)
+

Sets a timeout for use in save(), update(), and delete() +operations

+
+ +
+
+timestamp(timedelta_or_datetime)
+

Sets the timestamp for the query

+
+ +
+
+ttl(ttl_in_sec)
+

Sets the ttl values to run instance updates and inserts queries with.

+
+ +
+
+using(connection=None)
+

Change the context on the fly of the model instance (keyspace, connection)

+
+ +
+
+classmethod column_family_name(include_keyspace=True)
+

Returns the column family name if it’s been defined +otherwise, it creates it from the module and class name

+
+ +

Models also support dict-like access:

+
+
+len(m)
+

Returns the number of columns defined in the model

+
+ +
+
+m[col_name]
+

Returns the value of column col_name

+
+ +
+
+m[col_name] = value
+

Set m[col_name] to value

+
+ +
+
+keys()
+

Returns a list of column IDs.

+
+ +
+
+values()
+

Returns list of column values.

+
+ +
+
+items()
+

Returns a list of column ID/value tuples.

+
+ +
+ +
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.25.11-scylla/api/cassandra/cqlengine/query.html b/3.25.11-scylla/api/cassandra/cqlengine/query.html new file mode 100644 index 0000000000..7fe0a4529e --- /dev/null +++ b/3.25.11-scylla/api/cassandra/cqlengine/query.html @@ -0,0 +1,1040 @@ + + + + + + + + + + + + + cassandra.cqlengine.query - Query and filter model objects | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.cqlengine.query - Query and filter model objects

+
+

QuerySet

+

QuerySet objects are typically obtained by calling objects() on a model class. +The methods here are used to filter, order, and constrain results.

+
+
+class cassandra.cqlengine.query.ModelQuerySet(model)
+
+
+all()
+

Returns a queryset matching all rows

+
for user in User.objects().all():
+    print(user)
+
+
+
+ +
+
+batch(batch_obj)
+

Set a batch object to run the query on.

+

Note: running a select query with a batch object will raise an exception

+
+ +
+
+consistency(consistency)
+

Sets the consistency level for the operation. See ConsistencyLevel.

+
for user in User.objects(id=3).consistency(CL.ONE):
+    print(user)
+
+
+
+ +
+
+count()
+

Returns the number of rows matched by this query.

+

Note: This function executes a SELECT COUNT() and has a performance cost on large datasets

+
+ +
+
+len(queryset)
+

Returns the number of rows matched by this query. This function uses count() internally.

+

Note: This function executes a SELECT COUNT() and has a performance cost on large datasets

+
+ +
+
+distinct(distinct_fields=None)
+

Returns the DISTINCT rows matched by this query.

+

distinct_fields default to the partition key fields if not specified.

+

Note: distinct_fields must be a partition key or a static column

+
class Automobile(Model):
+    manufacturer = columns.Text(partition_key=True)
+    year = columns.Integer(primary_key=True)
+    model = columns.Text(primary_key=True)
+    price = columns.Decimal()
+
+sync_table(Automobile)
+
+# create rows
+
+Automobile.objects.distinct()
+
+# or
+
+Automobile.objects.distinct(['manufacturer'])
+
+
+
+ +
+
+filter(*args, **kwargs)
+

Adds WHERE arguments to the queryset, returning a new queryset

+

See Retrieving objects with filters

+

Returns a QuerySet filtered on the keyword arguments

+
+ +
+
+get(*args, **kwargs)
+

Returns a single instance matching this query, optionally with additional filter kwargs.

+

See Retrieving objects with filters

+

Returns a single object matching the QuerySet.

+
user = User.get(id=1)
+
+
+

If no objects are matched, a DoesNotExist exception is raised.

+

If more than one object is found, a MultipleObjectsReturned exception is raised.

+
+ +
+
+limit(v)
+

Limits the number of results returned by Cassandra. Use 0 or None to disable.

+

Note that CQL’s default limit is 10,000, so all queries without a limit set explicitly will have an implicit limit of 10,000

+
# Fetch 100 users
+for user in User.objects().limit(100):
+    print(user)
+
+# Fetch all users
+for user in User.objects().limit(None):
+    print(user)
+
+
+
+ +
+
+fetch_size(v)
+

Sets the number of rows that are fetched at a time.

+

Note that driver’s default fetch size is 5000.

+
for user in User.objects().fetch_size(500):
+    print(user)
+
+
+
+ +
+
+if_not_exists()
+

Check the existence of an object before insertion.

+

If the insertion isn’t applied, a LWTException is raised.

+
+ +
+
+if_exists()
+

Check the existence of an object before an update or delete.

+

If the update or delete isn’t applied, a LWTException is raised.

+
+ +
+
+order_by(*colnames)
+

Sets the column(s) to be used for ordering

+

Default order is ascending, prepend a ‘-’ to any column name for descending

+

Note: column names must be a clustering key

+
from uuid import uuid1,uuid4
+
+class Comment(Model):
+    photo_id = UUID(primary_key=True)
+    comment_id = TimeUUID(primary_key=True, default=uuid1) # second primary key component is a clustering key
+    comment = Text()
+
+sync_table(Comment)
+
+u = uuid4()
+for x in range(5):
+    Comment.create(photo_id=u, comment="test %d" % x)
+
+print("Normal")
+for comment in Comment.objects(photo_id=u):
+    print comment.comment_id
+
+print("Reversed")
+for comment in Comment.objects(photo_id=u).order_by("-comment_id"):
+    print comment.comment_id
+
+
+
+ +
+
+allow_filtering()
+

Enables the (usually) unwise practive of querying on a clustering key without also defining a partition key

+
+ +
+
+only(fields)
+

Load only these fields for the returned query

+
+ +
+
+defer(fields)
+

Don’t load these fields for the returned query

+
+ +
+
+timestamp(timestamp)
+

Allows for custom timestamps to be saved with the record.

+
+ +
+
+ttl(ttl)
+

Sets the ttl (in seconds) for modified data.

+

Note that running a select query with a ttl value will raise an exception

+
+ +
+
+using(keyspace=None, connection=None)
+

Change the context on-the-fly of the Model class (keyspace, connection)

+
+ +
+
+update(**values)
+

Performs an update on the row selected by the queryset. Include values to update in the +update like so:

+
Model.objects(key=n).update(value='x')
+
+
+

Passing in updates for columns which are not part of the model will raise a ValidationError.

+

Per column validation will be performed, but instance level validation will not +(i.e., Model.validate is not called). This is sometimes referred to as a blind update.

+

For example:

+
class User(Model):
+    id = Integer(primary_key=True)
+    name = Text()
+
+setup(["localhost"], "test")
+sync_table(User)
+
+u = User.create(id=1, name="jon")
+
+User.objects(id=1).update(name="Steve")
+
+# sets name to null
+User.objects(id=1).update(name=None)
+
+
+

Also supported is blindly adding and removing elements from container columns, +without loading a model instance from Cassandra.

+

Using the syntax .update(column_name={x, y, z}) will overwrite the contents of the container, like updating a +non container column. However, adding __<operation> to the end of the keyword arg, makes the update call add +or remove items from the collection, without overwriting then entire column.

+

Given the model below, here are the operations that can be performed on the different container columns:

+
class Row(Model):
+    row_id      = columns.Integer(primary_key=True)
+    set_column  = columns.Set(Integer)
+    list_column = columns.List(Integer)
+    map_column  = columns.Map(Integer, Integer)
+
+
+

Set

+
    +
  • add: adds the elements of the given set to the column

  • +
  • remove: removes the elements of the given set to the column

  • +
+
# add elements to a set
+Row.objects(row_id=5).update(set_column__add={6})
+
+# remove elements to a set
+Row.objects(row_id=5).update(set_column__remove={4})
+
+
+

List

+
    +
  • append: appends the elements of the given list to the end of the column

  • +
  • prepend: prepends the elements of the given list to the beginning of the column

  • +
+
# append items to a list
+Row.objects(row_id=5).update(list_column__append=[6, 7])
+
+# prepend items to a list
+Row.objects(row_id=5).update(list_column__prepend=[1, 2])
+
+
+

Map

+
    +
  • update: adds the given keys/values to the columns, creating new entries if they didn’t exist, and overwriting old ones if they did

  • +
+
# add items to a map
+Row.objects(row_id=5).update(map_column__update={1: 2, 3: 4})
+
+# remove items from a map
+Row.objects(row_id=5).update(map_column__remove={1, 2})
+
+
+
+ +
+ +
+
+class cassandra.cqlengine.query.BatchQuery(batch_type=None, timestamp=None, consistency=None, execute_on_exception=False, timeout=<object object>, connection=None)
+

Handles the batching of queries

+

http://docs.datastax.com/en/cql/3.0/cql/cql_reference/batch_r.html

+

See Batch Queries for more details.

+
+
Parameters
+
    +
  • batch_type (BatchType, str or None) – (optional) One of batch type values available through BatchType enum

  • +
  • timestamp (datetime or timedelta or None) – (optional) A datetime or timedelta object with desired timestamp to be applied +to the batch conditional.

  • +
  • consistency (The ConsistencyLevel to be used for the batch query, or None.) – (optional) One of consistency values (“ANY”, “ONE”, “QUORUM” etc)

  • +
  • execute_on_exception (bool) – (Defaults to False) Indicates that when the BatchQuery instance is used +as a context manager the queries accumulated within the context must be executed despite +encountering an error within the context. By default, any exception raised from within +the context scope will cause the batched queries not to be executed.

  • +
  • timeout (float or None) – (optional) Timeout for the entire batch (in seconds), if not specified fallback +to default session timeout

  • +
  • connection (str) – Connection name to use for the batch execution

  • +
+
+
+
+
+add_query(query)
+
+ +
+
+execute()
+
+ +
+
+add_callback(fn, *args, **kwargs)
+

Add a function and arguments to be passed to it to be executed after the batch executes.

+

A batch can support multiple callbacks.

+

Note, that if the batch does not execute, the callbacks are not executed. +A callback, thus, is an “on batch success” handler.

+
+
Parameters
+
    +
  • fn (callable) – Callable object

  • +
  • *args – Positional arguments to be passed to the callback at the time of execution

  • +
  • **kwargs – Named arguments to be passed to the callback at the time of execution

  • +
+
+
+
+ +
+ +
+
+class cassandra.cqlengine.query.ContextQuery(*args, **kwargs)
+

A Context manager to allow a Model to switch context easily. Presently, the context only +specifies a keyspace for model IO.

+
+
Parameters
+
    +
  • *args – One or more models. A model should be a class type, not an instance.

  • +
  • **kwargs – (optional) Context parameters: can be keyspace or connection

  • +
+
+
+

For example:

+
with ContextQuery(Automobile, keyspace='test2') as A:
+    A.objects.create(manufacturer='honda', year=2008, model='civic')
+    print len(A.objects.all())  # 1 result
+
+with ContextQuery(Automobile, keyspace='test4') as A:
+    print len(A.objects.all())  # 0 result
+
+# Multiple models
+with ContextQuery(Automobile, Automobile2, connection='cluster2') as (A, A2):
+    print len(A.objects.all())
+    print len(A2.objects.all())
+
+
+
+ +
+
+class cassandra.cqlengine.query.DoesNotExist
+
+ +
+
+class cassandra.cqlengine.query.MultipleObjectsReturned
+
+ +
+
+class cassandra.cqlengine.query.LWTException(existing)
+

Lightweight conditional exception.

+

This exception will be raised when a write using an IF clause could not be +applied due to existing data violating the condition. The existing data is +available through the existing attribute.

+
+
Parameters
+

existing – The current state of the data which prevented the write.

+
+
+
+ +
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.25.11-scylla/api/cassandra/cqlengine/usertype.html b/3.25.11-scylla/api/cassandra/cqlengine/usertype.html new file mode 100644 index 0000000000..bcef8e0d6d --- /dev/null +++ b/3.25.11-scylla/api/cassandra/cqlengine/usertype.html @@ -0,0 +1,683 @@ + + + + + + + + + + + + + cassandra.cqlengine.usertype - Model classes for User Defined Types | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.cqlengine.usertype - Model classes for User Defined Types

+
+

UserType

+
+
+class cassandra.cqlengine.usertype.UserType(**values)
+

This class is used to model User Defined Types. To define a type, declare a class inheriting from this, +and assign field types as class attributes:

+
# connect with default keyspace ...
+
+from cassandra.cqlengine.columns import Text, Integer
+from cassandra.cqlengine.usertype import UserType
+
+class address(UserType):
+    street = Text()
+    zipcode = Integer()
+
+from cassandra.cqlengine import management
+management.sync_type(address)
+
+
+

Please see User Defined Types for a complete example and discussion.

+
+
+__type_name__ = None
+

Optional. Sets the name of the CQL type for this type.

+

If not specified, the type name will be the name of the class, with it’s module name as it’s prefix.

+
+ +
+ +
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.25.11-scylla/api/cassandra/datastax/graph/fluent/index.html b/3.25.11-scylla/api/cassandra/datastax/graph/fluent/index.html new file mode 100644 index 0000000000..68c273f617 --- /dev/null +++ b/3.25.11-scylla/api/cassandra/datastax/graph/fluent/index.html @@ -0,0 +1,757 @@ + + + + + + + + + + + + + cassandra.datastax.graph.fluent | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.datastax.graph.fluent

+
+
+class cassandra.datastax.graph.fluent.DseGraph
+

Dse Graph utility class for GraphTraversal construction and execution.

+
+
+DSE_GRAPH_QUERY_LANGUAGE = 'bytecode-json'
+

Graph query language, Default is ‘bytecode-json’ (GraphSON).

+
+ +
+
+static create_execution_profile(graph_name, graph_protocol=b'graphson-2.0', **kwargs)
+

Creates an ExecutionProfile for GraphTraversal execution. You need to register that execution profile to the +cluster by using cluster.add_execution_profile.

+
+
Parameters
+
    +
  • graph_name – The graph name

  • +
  • graph_protocol – (Optional) The graph protocol, default is DSE_GRAPH_QUERY_PROTOCOL.

  • +
+
+
+
+ +
+
+static query_from_traversal(traversal, graph_protocol=b'graphson-2.0', context=None)
+

From a GraphTraversal, return a query string based on the language specified in DseGraph.DSE_GRAPH_QUERY_LANGUAGE.

+
+
Parameters
+
    +
  • traversal – The GraphTraversal object

  • +
  • graph_protocol – The graph protocol. Default is DseGraph.DSE_GRAPH_QUERY_PROTOCOL.

  • +
  • context – The dict of the serialization context, needed for GraphSON3 (tuple, udt). +e.g: {‘cluster’: cluster, ‘graph_name’: name}

  • +
+
+
+
+ +
+
+static traversal_source(session=None, graph_name=None, execution_profile=EXEC_PROFILE_GRAPH_DEFAULT, traversal_class=None)
+

Returns a TinkerPop GraphTraversalSource binded to the session and graph_name if provided.

+
+
Parameters
+
    +
  • session – (Optional) A DSE session

  • +
  • graph_name – (Optional) DSE Graph name

  • +
  • execution_profile – (Optional) Execution profile for traversal queries. Default is set to EXEC_PROFILE_GRAPH_DEFAULT.

  • +
  • traversal_class – (Optional) The GraphTraversalSource class to use (DSL).

  • +
+
+
+
from cassandra.cluster import Cluster
+from cassandra.datastax.graph.fluent import DseGraph
+
+c = Cluster()
+session = c.connect()
+
+g = DseGraph.traversal_source(session, 'my_graph')
+print g.V().valueMap().toList()
+
+
+
+ +
+
+static batch(session=None, execution_profile=None)
+

Returns the cassandra.datastax.graph.fluent.query.TraversalBatch object allowing to +execute multiple traversals in the same transaction.

+
+ +
+ +
+
+class cassandra.datastax.graph.fluent.DSESessionRemoteGraphConnection(session[, graph_name, execution_profile])
+

A Tinkerpop RemoteConnection to execute traversal queries on DSE.

+
+
Parameters
+
    +
  • session – A DSE session

  • +
  • graph_name – (Optional) DSE Graph name.

  • +
  • execution_profile – (Optional) Execution profile for traversal queries. Default is set to EXEC_PROFILE_GRAPH_DEFAULT.

  • +
+
+
+
+ +
+
+class cassandra.datastax.graph.fluent.BaseGraphRowFactory(cluster)
+

Base row factory for graph traversal. This class basically wraps a +graphson reader function to handle additional features of Gremlin/DSE +and is callable as a normal row factory.

+
+
Currently supported:
    +
  • bulk results

  • +
+
+
+
+ +
+
+cassandra.datastax.graph.fluent.graph_traversal_row_factory
+

alias of cassandra.datastax.graph.fluent._GremlinGraphSON2RowFactory

+
+ +
+
+cassandra.datastax.graph.fluent.graph_traversal_dse_object_row_factory
+

alias of cassandra.datastax.graph.fluent._DseGraphSON2RowFactory

+
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.25.11-scylla/api/cassandra/datastax/graph/fluent/predicates.html b/3.25.11-scylla/api/cassandra/datastax/graph/fluent/predicates.html new file mode 100644 index 0000000000..3632810dd2 --- /dev/null +++ b/3.25.11-scylla/api/cassandra/datastax/graph/fluent/predicates.html @@ -0,0 +1,753 @@ + + + + + + + + + + + + + cassandra.datastax.graph.fluent.predicates | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.datastax.graph.fluent.predicates

+
+
+class cassandra.datastax.graph.fluent.predicates.Search
+
+
+static token(value)
+

Search any instance of a certain token within the text property targeted. +:param value: the value to look for.

+
+ +
+
+static token_prefix(value)
+

Search any instance of a certain token prefix withing the text property targeted. +:param value: the value to look for.

+
+ +
+
+static token_regex(value)
+

Search any instance of the provided regular expression for the targeted property. +:param value: the value to look for.

+
+ +
+
+static prefix(value)
+

Search for a specific prefix at the beginning of the text property targeted. +:param value: the value to look for.

+
+ +
+
+static regex(value)
+

Search for this regular expression inside the text property targeted. +:param value: the value to look for.

+
+ +
+
+static fuzzy(value, distance)
+

Search for a fuzzy string inside the text property targeted. +:param value: the value to look for. +:param distance: The distance for the fuzzy search. ie. 1, to allow a one-letter misspellings.

+
+ +
+
+static token_fuzzy(value, distance)
+

Search for a token fuzzy inside the text property targeted. +:param value: the value to look for. +:param distance: The distance for the token fuzzy search. ie. 1, to allow a one-letter misspellings.

+
+ +
+
+static phrase(value, proximity)
+

Search for a phrase inside the text property targeted. +:param value: the value to look for. +:param proximity: The proximity for the phrase search. ie. phrase(‘David Felcey’, 2).. to find ‘David Felcey’ with up to two middle names.

+
+ +
+ +
+
+class cassandra.datastax.graph.fluent.predicates.CqlCollection
+
+
+static contains(value)
+

Search for a value inside a cql list/set column. +:param value: the value to look for.

+
+ +
+
+static contains_value(value)
+

Search for a map value. +:param value: the value to look for.

+
+ +
+
+static contains_key(value)
+

Search for a map key. +:param value: the value to look for.

+
+ +
+
+static entry_eq(value)
+

Search for a map entry. +:param value: the value to look for.

+
+ +
+ +
+
+class cassandra.datastax.graph.fluent.predicates.Geo
+
+
+static inside(value, units=1)
+

Search any instance of geometry inside the Distance targeted. +:param value: A Distance to look for. +:param units: The units for value. See GeoUnit enum. (Can also +provide an integer to use as a multiplier to convert value to +degrees.)

+
+ +
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.25.11-scylla/api/cassandra/datastax/graph/fluent/query.html b/3.25.11-scylla/api/cassandra/datastax/graph/fluent/query.html new file mode 100644 index 0000000000..0053c0212d --- /dev/null +++ b/3.25.11-scylla/api/cassandra/datastax/graph/fluent/query.html @@ -0,0 +1,704 @@ + + + + + + + + + + + + + cassandra.datastax.graph.fluent.query | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.datastax.graph.fluent.query

+
+
+class cassandra.datastax.graph.fluent.query.TraversalBatch(session=None, execution_profile=None)
+

A TraversalBatch is used to execute multiple graph traversals in a +single transaction. If any traversal in the batch fails, the entire +batch will fail to apply.

+

If a TraversalBatch is bounded to a DSE session, it can be executed using +traversal_batch.execute().

+
+
Parameters
+
    +
  • session – (Optional) A DSE session

  • +
  • execution_profile – (Optional) The execution profile to use for the batch execution

  • +
+
+
+
+
+add(traversal)
+

Add a traversal to the batch.

+
+
Parameters
+

traversal – A gremlin GraphTraversal

+
+
+
+ +
+
+add_all(traversals)
+

Adds a sequence of traversals to the batch.

+
+
Parameters
+

traversals – A sequence of gremlin GraphTraversal

+
+
+
+ +
+
+execute()
+

Execute the traversal batch if bounded to a DSE Session.

+
+ +
+
+as_graph_statement(graph_protocol=b'graphson-2.0')
+

Return the traversal batch as GraphStatement.

+
+
Parameters
+

graph_protocol – The graph protocol for the GraphSONWriter. Default is GraphProtocol.GRAPHSON_2_0.

+
+
+
+ +
+
+clear()
+

Clear a traversal batch for reuse.

+
+ +
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.25.11-scylla/api/cassandra/datastax/graph/index.html b/3.25.11-scylla/api/cassandra/datastax/graph/index.html new file mode 100644 index 0000000000..0138fd8043 --- /dev/null +++ b/3.25.11-scylla/api/cassandra/datastax/graph/index.html @@ -0,0 +1,1035 @@ + + + + + + + + + + + + + cassandra.datastax.graph - Graph Statements, Options, and Row Factories | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.datastax.graph - Graph Statements, Options, and Row Factories

+
+
+cassandra.datastax.graph.single_object_row_factory(column_names, rows)
+

returns the JSON string value of graph results

+
+ +
+
+cassandra.datastax.graph.graph_result_row_factory(column_names, rows)
+

Returns a Result object that can load graph results and produce specific types. +The Result JSON is deserialized and unpacked from the top-level ‘result’ dict.

+
+ +
+
+cassandra.datastax.graph.graph_object_row_factory(column_names, rows)
+

Like graph_result_row_factory(), except known element types (Vertex, Edge) are +converted to their simplified objects. Some low-level metadata is shed in this conversion. Unknown result types are +still returned as Result.

+
+ +
+
+cassandra.datastax.graph.graph_graphson2_row_factory(cluster)
+

Row factory to deserialize GraphSON2 results.

+
+ +
+
+cassandra.datastax.graph.graph_graphson3_row_factory(cluster)
+

Row factory to deserialize GraphSON3 results.

+
+ +
+
+cassandra.datastax.graph.to_int(value)
+

Wraps a value to be explicitly serialized as a graphson Int.

+
+ +
+
+cassandra.datastax.graph.to_bigint(value)
+

Wraps a value to be explicitly serialized as a graphson Bigint.

+
+ +
+
+cassandra.datastax.graph.to_smallint(value)
+

Wraps a value to be explicitly serialized as a graphson Smallint.

+
+ +
+
+cassandra.datastax.graph.to_float(value)
+

Wraps a value to be explicitly serialized as a graphson Float.

+
+ +
+
+cassandra.datastax.graph.to_double(value)
+

Wraps a value to be explicitly serialized as a graphson Double.

+
+ +
+
+class cassandra.datastax.graph.GraphProtocol
+
+
+GRAPHSON_1_0 = b'graphson-1.0'
+

GraphSON1

+
+ +
+
+GRAPHSON_2_0 = b'graphson-2.0'
+

GraphSON2

+
+ +
+
+GRAPHSON_3_0 = b'graphson-3.0'
+

GraphSON3

+
+ +
+ +
+
+class cassandra.datastax.graph.GraphOptions(**kwargs)
+

Options for DSE Graph Query handler.

+
+
+graph_name
+

name of the targeted graph.

+
+ +
+
+graph_source
+

choose the graph traversal source, configured on the server side.

+
+ +
+
+graph_language
+

the language used in the queries (default “gremlin-groovy”)

+
+ +
+
+graph_read_consistency_level
+

read cassandra.ConsistencyLevel for graph queries (if distinct from session default). +Setting this overrides the native Statement.consistency_level for read operations from Cassandra persistence

+
+ +
+
+graph_write_consistency_level
+

write cassandra.ConsistencyLevel for graph queries (if distinct from session default). +Setting this overrides the native Statement.consistency_level for write operations to Cassandra persistence.

+
+ +
+
+is_default_source
+
+ +
+
+is_analytics_source
+

True if graph_source is set to the server-defined analytics traversal source (‘a’)

+
+ +
+
+is_graph_source
+

True if graph_source is set to the server-defined graph traversal source (‘g’)

+
+ +
+
+set_source_default()
+

Sets graph_source to the server-defined default traversal source (‘default’)

+
+ +
+
+set_source_analytics()
+

Sets graph_source to the server-defined analytic traversal source (‘a’)

+
+ +
+
+set_source_graph()
+

Sets graph_source to the server-defined graph traversal source (‘g’)

+
+ +
+ +
+
+class cassandra.datastax.graph.SimpleGraphStatement(query_string, retry_policy=None, consistency_level=None, routing_key=None, serial_consistency_level=None, fetch_size=<object object>, keyspace=None, custom_payload=None, is_idempotent=False)
+

Simple graph statement for Session.execute_graph(). +Takes the same parameters as SimpleStatement.

+

query_string should be a literal CQL statement with the exception +of parameter placeholders that will be filled through the +parameters argument of Session.execute().

+

See Statement attributes for a description of the other parameters.

+
+ +
+
+class cassandra.datastax.graph.Result(value)
+

Represents deserialized graph results. +Property and item getters are provided for convenience.

+
+
+value = None
+

Deserialized value from the result

+
+ +
+
+as_vertex()
+

Return a Vertex parsed from this result

+

Raises TypeError if parsing fails (i.e. the result structure is not valid).

+
+ +
+
+as_edge()
+

Return a Edge parsed from this result

+

Raises TypeError if parsing fails (i.e. the result structure is not valid).

+
+ +
+
+as_path()
+

Return a Path parsed from this result

+

Raises TypeError if parsing fails (i.e. the result structure is not valid).

+
+ +
+ +
+
+class cassandra.datastax.graph.Vertex(id, label, type, properties)
+

Represents a Vertex element from a graph query.

+

Vertex properties are extracted into a dict of property names to list of VertexProperty (list +because they are always encoded that way, and sometimes have multiple cardinality; VertexProperty because sometimes +the properties themselves have property maps).

+
+ +
+
+class cassandra.datastax.graph.VertexProperty(label, value, properties=None)
+

Vertex properties have a top-level value and an optional dict of properties.

+
+
+label = None
+

label of the property

+
+ +
+
+value = None
+

Value of the property

+
+ +
+
+properties = None
+

dict of properties attached to the property

+
+ +
+ +
+
+class cassandra.datastax.graph.Edge(id, label, type, properties, inV, inVLabel, outV, outVLabel)
+

Represents an Edge element from a graph query.

+

Attributes match initializer parameters.

+
+ +
+
+class cassandra.datastax.graph.Path(labels, objects)
+

Represents a graph path.

+

Labels list is taken verbatim from the results.

+

Objects are either Result or Vertex/Edge for recognized types

+
+
+labels = None
+

List of labels in the path

+
+ +
+
+objects = None
+

List of objects in the path

+
+ +
+ +
+
+class cassandra.datastax.graph.T(name, val)
+

Represents a collection of tokens for more concise Traversal definitions.

+
+
+id = T.id
+
+ +
+
+key = T.key
+
+ +
+
+label = T.label
+
+ +
+
+value = T.value
+
+ +
+ +
+
+class cassandra.datastax.graph.GraphSON1Serializer
+

Serialize python objects to graphson types.

+
+ +
+
+class cassandra.datastax.graph.GraphSON1Deserializer
+

Deserialize graphson1 types to python objects.

+
+
+classmethod deserialize_date(value)
+
+ +
+
+classmethod deserialize_timestamp(value)
+
+ +
+
+classmethod deserialize_time(value)
+
+ +
+
+classmethod deserialize_duration(value)
+
+ +
+
+classmethod deserialize_int(value)
+
+ +
+
+classmethod deserialize_bigint(value)
+
+ +
+
+classmethod deserialize_double(value)
+
+ +
+
+classmethod deserialize_float(value)
+
+ +
+
+classmethod deserialize_uuid(value)
+
+ +
+
+classmethod deserialize_blob(value)
+
+ +
+
+classmethod deserialize_decimal(value)
+
+ +
+
+classmethod deserialize_point(value)
+
+ +
+
+classmethod deserialize_linestring(value)
+
+ +
+
+classmethod deserialize_polygon(value)
+
+ +
+ +
+
+class cassandra.datastax.graph.GraphSON2Reader(context, extra_deserializer_map=None)
+

GraphSON2 Reader that parse json and deserialize to python objects.

+
+
Parameters
+

extra_deserializer_map – map from GraphSON type tag to deserializer instance implementing deserialize

+
+
+
+
+read(json_data)
+

Read and deserialize json_data.

+
+ +
+
+deserialize(obj)
+

Deserialize GraphSON type-tagged dict values into objects mapped in self.deserializers

+
+ +
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.25.11-scylla/api/cassandra/decoder.html b/3.25.11-scylla/api/cassandra/decoder.html new file mode 100644 index 0000000000..99d9002528 --- /dev/null +++ b/3.25.11-scylla/api/cassandra/decoder.html @@ -0,0 +1,665 @@ + + + + + + + + + + + + + cassandra.decoder - Data Return Formats | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.decoder - Data Return Formats

+
+
+cassandra.decoder.tuple_factory()
+

Deprecated in 2.0.0. Use cassandra.query.tuple_factory()

+
+ +
+
+cassandra.decoder.named_tuple_factory()
+

Deprecated in 2.0.0. Use cassandra.query.named_tuple_factory()

+
+ +
+
+cassandra.decoder.dict_factory()
+

Deprecated in 2.0.0. Use cassandra.query.dict_factory()

+
+ +
+
+cassandra.decoder.ordered_dict_factory()
+

Deprecated in 2.0.0. Use cassandra.query.ordered_dict_factory()

+
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.25.11-scylla/api/cassandra/encoder.html b/3.25.11-scylla/api/cassandra/encoder.html new file mode 100644 index 0000000000..cb14b0f187 --- /dev/null +++ b/3.25.11-scylla/api/cassandra/encoder.html @@ -0,0 +1,742 @@ + + + + + + + + + + + + + cassandra.encoder - Encoders for non-prepared Statements | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.encoder - Encoders for non-prepared Statements

+
+
+class cassandra.encoder.Encoder
+

A container for mapping python types to CQL string literals when working +with non-prepared statements. The type mapping can be +directly customized by users.

+
+
+mapping = None
+

A map of python types to encoder functions.

+
+ +
+
+cql_encode_none()
+

Converts None to the string ‘NULL’.

+
+ +
+
+cql_encode_object()
+

Default encoder for all objects that do not have a specific encoder function +registered. This function simply calls str() on the object.

+
+ +
+
+cql_encode_all_types()
+

Converts any type into a CQL string, defaulting to cql_encode_object +if mapping does not contain an entry for the type.

+
+ +
+
+cql_encode_sequence()
+

Converts a sequence to a string of the form (item1, item2, ...). This +is suitable for IN value lists.

+
+ +
+
+cql_encode_str()
+

Escapes quotes in str objects.

+
+ +
+
+cql_encode_unicode()
+

Converts unicode objects to UTF-8 encoded strings with quote escaping.

+
+ +
+
+cql_encode_bytes()
+

Converts strings, buffers, and bytearrays into CQL blob literals.

+
+ +
+
+cql_encode_datetime()
+

Converts a datetime.datetime object to a (string) integer timestamp +with millisecond precision.

+
+ +
+
+cql_encode_date()
+

Converts a datetime.date object to a string with format +YYYY-MM-DD.

+
+ +
+
+cql_encode_map_collection()
+

Converts a dict into a string of the form {key1: val1, key2: val2, ...}. +This is suitable for map type columns.

+
+ +
+
+cql_encode_list_collection()
+

Converts a sequence to a string of the form [item1, item2, ...]. This +is suitable for list type columns.

+
+ +
+
+cql_encode_set_collection()
+

Converts a sequence to a string of the form {item1, item2, ...}. This +is suitable for set type columns.

+
+ +
+
+cql_encode_tuple()
+

Converts a sequence to a string of the form (item1, item2, ...). This +is suitable for tuple type columns.

+
+ +
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.25.11-scylla/api/cassandra/graph.html b/3.25.11-scylla/api/cassandra/graph.html new file mode 100644 index 0000000000..3ec4e91860 --- /dev/null +++ b/3.25.11-scylla/api/cassandra/graph.html @@ -0,0 +1,1028 @@ + + + + + + + + + + + + + cassandra.graph - Graph Statements, Options, and Row Factories | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.graph - Graph Statements, Options, and Row Factories

+
+

Note

+

This module is only for backward compatibility for dse-driver users. Consider using cassandra.datastax.graph.

+
+
+
+cassandra.graph.single_object_row_factory(column_names, rows)
+

returns the JSON string value of graph results

+
+ +
+
+cassandra.graph.graph_result_row_factory(column_names, rows)
+

Returns a Result object that can load graph results and produce specific types. +The Result JSON is deserialized and unpacked from the top-level ‘result’ dict.

+
+ +
+
+cassandra.graph.graph_object_row_factory(column_names, rows)
+

Like graph_result_row_factory(), except known element types (Vertex, Edge) are +converted to their simplified objects. Some low-level metadata is shed in this conversion. Unknown result types are +still returned as Result.

+
+ +
+
+cassandra.graph.graph_graphson2_row_factory(cluster)
+

Row factory to deserialize GraphSON2 results.

+
+ +
+
+cassandra.graph.graph_graphson3_row_factory(cluster)
+

Row factory to deserialize GraphSON3 results.

+
+ +
+
+cassandra.graph.to_int(value)
+

Wraps a value to be explicitly serialized as a graphson Int.

+
+ +
+
+cassandra.graph.to_bigint(value)
+

Wraps a value to be explicitly serialized as a graphson Bigint.

+
+ +
+
+cassandra.graph.to_smallint(value)
+

Wraps a value to be explicitly serialized as a graphson Smallint.

+
+ +
+
+cassandra.graph.to_float(value)
+

Wraps a value to be explicitly serialized as a graphson Float.

+
+ +
+
+cassandra.graph.to_double(value)
+

Wraps a value to be explicitly serialized as a graphson Double.

+
+ +
+
+class cassandra.graph.GraphProtocol
+
+
+GRAPHSON_1_0 = b'graphson-1.0'
+

GraphSON1

+
+ +
+
+GRAPHSON_2_0 = b'graphson-2.0'
+

GraphSON2

+
+ +
+
+GRAPHSON_3_0 = b'graphson-3.0'
+

GraphSON3

+
+ +
+ +
+
+class cassandra.graph.GraphOptions(**kwargs)
+

Options for DSE Graph Query handler.

+
+
+graph_name
+

name of the targeted graph.

+
+ +
+
+graph_source
+

choose the graph traversal source, configured on the server side.

+
+ +
+
+graph_language
+

the language used in the queries (default “gremlin-groovy”)

+
+ +
+
+graph_read_consistency_level
+

read cassandra.ConsistencyLevel for graph queries (if distinct from session default). +Setting this overrides the native Statement.consistency_level for read operations from Cassandra persistence

+
+ +
+
+graph_write_consistency_level
+

write cassandra.ConsistencyLevel for graph queries (if distinct from session default). +Setting this overrides the native Statement.consistency_level for write operations to Cassandra persistence.

+
+ +
+
+is_default_source
+
+ +
+
+is_analytics_source
+

True if graph_source is set to the server-defined analytics traversal source (‘a’)

+
+ +
+
+is_graph_source
+

True if graph_source is set to the server-defined graph traversal source (‘g’)

+
+ +
+
+set_source_default()
+

Sets graph_source to the server-defined default traversal source (‘default’)

+
+ +
+
+set_source_analytics()
+

Sets graph_source to the server-defined analytic traversal source (‘a’)

+
+ +
+
+set_source_graph()
+

Sets graph_source to the server-defined graph traversal source (‘g’)

+
+ +
+ +
+
+class cassandra.graph.SimpleGraphStatement(query_string, retry_policy=None, consistency_level=None, routing_key=None, serial_consistency_level=None, fetch_size=<object object>, keyspace=None, custom_payload=None, is_idempotent=False)
+

Simple graph statement for Session.execute_graph(). +Takes the same parameters as SimpleStatement.

+

query_string should be a literal CQL statement with the exception +of parameter placeholders that will be filled through the +parameters argument of Session.execute().

+

See Statement attributes for a description of the other parameters.

+
+ +
+
+class cassandra.graph.Result(value)
+

Represents deserialized graph results. +Property and item getters are provided for convenience.

+
+
+value = None
+

Deserialized value from the result

+
+ +
+
+as_vertex()
+

Return a Vertex parsed from this result

+

Raises TypeError if parsing fails (i.e. the result structure is not valid).

+
+ +
+
+as_edge()
+

Return a Edge parsed from this result

+

Raises TypeError if parsing fails (i.e. the result structure is not valid).

+
+ +
+
+as_path()
+

Return a Path parsed from this result

+

Raises TypeError if parsing fails (i.e. the result structure is not valid).

+
+ +
+ +
+
+class cassandra.graph.Vertex(id, label, type, properties)
+

Represents a Vertex element from a graph query.

+

Vertex properties are extracted into a dict of property names to list of VertexProperty (list +because they are always encoded that way, and sometimes have multiple cardinality; VertexProperty because sometimes +the properties themselves have property maps).

+
+ +
+
+class cassandra.graph.VertexProperty(label, value, properties=None)
+

Vertex properties have a top-level value and an optional dict of properties.

+
+
+label = None
+

label of the property

+
+ +
+
+value = None
+

Value of the property

+
+ +
+
+properties = None
+

dict of properties attached to the property

+
+ +
+ +
+
+class cassandra.graph.Edge(id, label, type, properties, inV, inVLabel, outV, outVLabel)
+

Represents an Edge element from a graph query.

+

Attributes match initializer parameters.

+
+ +
+
+class cassandra.graph.Path(labels, objects)
+

Represents a graph path.

+

Labels list is taken verbatim from the results.

+

Objects are either Result or Vertex/Edge for recognized types

+
+
+labels = None
+

List of labels in the path

+
+ +
+
+objects = None
+

List of objects in the path

+
+ +
+ +
+
+class cassandra.graph.GraphSON1Serializer
+

Serialize python objects to graphson types.

+
+ +
+
+class cassandra.graph.GraphSON1Deserializer
+

Deserialize graphson1 types to python objects.

+
+
+classmethod deserialize_date(value)
+
+ +
+
+classmethod deserialize_timestamp(value)
+
+ +
+
+classmethod deserialize_time(value)
+
+ +
+
+classmethod deserialize_duration(value)
+
+ +
+
+classmethod deserialize_int(value)
+
+ +
+
+classmethod deserialize_bigint(value)
+
+ +
+
+classmethod deserialize_double(value)
+
+ +
+
+classmethod deserialize_float(value)
+
+ +
+
+classmethod deserialize_uuid(value)
+
+ +
+
+classmethod deserialize_blob(value)
+
+ +
+
+classmethod deserialize_decimal(value)
+
+ +
+
+classmethod deserialize_point(value)
+
+ +
+
+classmethod deserialize_linestring(value)
+
+ +
+
+classmethod deserialize_polygon(value)
+
+ +
+ +
+
+class cassandra.graph.GraphSON2Reader(context, extra_deserializer_map=None)
+

GraphSON2 Reader that parse json and deserialize to python objects.

+
+
Parameters
+

extra_deserializer_map – map from GraphSON type tag to deserializer instance implementing deserialize

+
+
+
+
+read(json_data)
+

Read and deserialize json_data.

+
+ +
+
+deserialize(obj)
+

Deserialize GraphSON type-tagged dict values into objects mapped in self.deserializers

+
+ +
+ +
+
+class cassandra.graph.GraphSON3Reader(context, extra_deserializer_map=None)
+

GraphSON3 Reader that parse json and deserialize to python objects.

+
+
Parameters
+
    +
  • context – A dict of the context, mostly used as context for udt deserialization.

  • +
  • extra_deserializer_map – map from GraphSON type tag to deserializer instance implementing deserialize

  • +
+
+
+
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.25.11-scylla/api/cassandra/io/asyncioreactor.html b/3.25.11-scylla/api/cassandra/io/asyncioreactor.html new file mode 100644 index 0000000000..5a9e6f59b6 --- /dev/null +++ b/3.25.11-scylla/api/cassandra/io/asyncioreactor.html @@ -0,0 +1,657 @@ + + + + + + + + + + + + + cassandra.io.asyncioreactor - asyncio Event Loop | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.io.asyncioreactor - asyncio Event Loop

+
+
+class cassandra.io.asyncioreactor.AsyncioConnection(*args, **kwargs)
+

An experimental implementation of Connection that uses the +asyncio module in the Python standard library for its event loop.

+

Note that it requires asyncio features that were only introduced in the +3.4 line in 3.4.6, and in the 3.5 line in 3.5.1.

+
+
+classmethod initialize_reactor()
+

Called once by Cluster.connect(). This should be used by implementations +to set up any resources that will be shared across connections.

+
+ +
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.25.11-scylla/api/cassandra/io/asyncorereactor.html b/3.25.11-scylla/api/cassandra/io/asyncorereactor.html new file mode 100644 index 0000000000..e2f7878edd --- /dev/null +++ b/3.25.11-scylla/api/cassandra/io/asyncorereactor.html @@ -0,0 +1,662 @@ + + + + + + + + + + + + + cassandra.io.asyncorereactor - asyncore Event Loop | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.io.asyncorereactor - asyncore Event Loop

+
+
+class cassandra.io.asyncorereactor.AsyncoreConnection(*args, **kwargs)
+

An implementation of Connection that uses the asyncore +module in the Python standard library for its event loop.

+
+
+classmethod initialize_reactor()
+

Called once by Cluster.connect(). This should be used by implementations +to set up any resources that will be shared across connections.

+
+ +
+
+classmethod handle_fork()
+

Called after a forking. This should cleanup any remaining reactor state +from the parent process.

+
+ +
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.25.11-scylla/api/cassandra/io/eventletreactor.html b/3.25.11-scylla/api/cassandra/io/eventletreactor.html new file mode 100644 index 0000000000..c40e9659cf --- /dev/null +++ b/3.25.11-scylla/api/cassandra/io/eventletreactor.html @@ -0,0 +1,664 @@ + + + + + + + + + + + + + cassandra.io.eventletreactor - eventlet-compatible Connection | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.io.eventletreactor - eventlet-compatible Connection

+
+
+class cassandra.io.eventletreactor.EventletConnection(*args, **kwargs)
+

An implementation of Connection that utilizes eventlet.

+

This implementation assumes all eventlet monkey patching is active. It is not tested with partial patching.

+
+
+classmethod initialize_reactor()
+

Called once by Cluster.connect(). This should be used by implementations +to set up any resources that will be shared across connections.

+
+ +
+
+classmethod service_timeouts()
+

cls._timeout_watcher runs in this loop forever. +It is usually waiting for the next timeout on the cls._new_timer Event. +When new timers are added, that event is set so that the watcher can +wake up and possibly set an earlier timeout.

+
+ +
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.25.11-scylla/api/cassandra/io/geventreactor.html b/3.25.11-scylla/api/cassandra/io/geventreactor.html new file mode 100644 index 0000000000..07f996389f --- /dev/null +++ b/3.25.11-scylla/api/cassandra/io/geventreactor.html @@ -0,0 +1,655 @@ + + + + + + + + + + + + + cassandra.io.geventreactor - gevent-compatible Event Loop | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.io.geventreactor - gevent-compatible Event Loop

+
+
+class cassandra.io.geventreactor.GeventConnection(*args, **kwargs)
+

An implementation of Connection that utilizes gevent.

+

This implementation assumes all gevent monkey patching is active. It is not tested with partial patching.

+
+
+classmethod initialize_reactor()
+

Called once by Cluster.connect(). This should be used by implementations +to set up any resources that will be shared across connections.

+
+ +
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.25.11-scylla/api/cassandra/io/libevreactor.html b/3.25.11-scylla/api/cassandra/io/libevreactor.html new file mode 100644 index 0000000000..67d710884f --- /dev/null +++ b/3.25.11-scylla/api/cassandra/io/libevreactor.html @@ -0,0 +1,647 @@ + + + + + + + + + + + + + cassandra.io.libevreactor - libev Event Loop | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.io.libevreactor - libev Event Loop

+
+
+class cassandra.io.libevreactor.LibevConnection(*args, **kwargs)
+

An implementation of Connection that uses libev for its event loop.

+
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.25.11-scylla/api/cassandra/io/twistedreactor.html b/3.25.11-scylla/api/cassandra/io/twistedreactor.html new file mode 100644 index 0000000000..cba1c62c73 --- /dev/null +++ b/3.25.11-scylla/api/cassandra/io/twistedreactor.html @@ -0,0 +1,648 @@ + + + + + + + + + + + + + cassandra.io.twistedreactor - Twisted Event Loop | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.io.twistedreactor - Twisted Event Loop

+
+
+class cassandra.io.twistedreactor.TwistedConnection
+

An implementation of Connection that uses +Twisted’s reactor as its event loop.

+
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.25.11-scylla/api/cassandra/metadata.html b/3.25.11-scylla/api/cassandra/metadata.html new file mode 100644 index 0000000000..13cdf2ba64 --- /dev/null +++ b/3.25.11-scylla/api/cassandra/metadata.html @@ -0,0 +1,1032 @@ + + + + + + + + + + + + + cassandra.metadata - Schema and Ring Topology | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.metadata - Schema and Ring Topology

+
+
+cassandra.metadata.cql_keywords
+

set() -> new empty set object +set(iterable) -> new set object

+

Build an unordered collection of unique elements.

+
+ +
+
+cassandra.metadata.cql_keywords_unreserved
+

set() -> new empty set object +set(iterable) -> new set object

+

Build an unordered collection of unique elements.

+
+ +
+
+cassandra.metadata.cql_keywords_reserved
+

set() -> new empty set object +set(iterable) -> new set object

+

Build an unordered collection of unique elements.

+
+ +
+
+class cassandra.metadata.Metadata
+

Holds a representation of the cluster schema and topology.

+
+
+add_or_return_host(host)
+

Returns a tuple (host, new), where host is a Host +instance, and new is a bool indicating whether +the host was newly added.

+
+ +
+
+all_hosts()
+

Returns a list of all known Host instances in the cluster.

+
+ +
+
+export_schema_as_string()
+

Returns a string that can be executed as a query in order to recreate +the entire schema. The string is formatted to be human readable.

+
+ +
+
+get_host(endpoint_or_address, port=None)
+

Find a host in the metadata for a specific endpoint. If a string inet address and port are passed, +iterate all hosts to match the broadcast_rpc_address and +broadcast_rpc_port attributes.

+
+ +
+
+get_host_by_host_id(host_id)
+

Same as get_host() but use host_id for lookup.

+
+ +
+
+get_replicas(keyspace, key)
+

Returns a list of Host instances that are replicas for a given +partition key.

+
+ +
+ +
+

Schemas

+
+
+class cassandra.metadata.KeyspaceMetadata
+

A representation of the schema for a single keyspace.

+
+
+as_cql_query()
+

Returns a CQL query string that can be used to recreate just this keyspace, +not including user-defined types and tables.

+
+ +
+
+export_as_string()
+

Returns a CQL query string that can be used to recreate the entire keyspace, +including user-defined types and tables.

+
+ +
+ +
+
+class cassandra.metadata.UserType
+

A user defined type, as created by CREATE TYPE statements.

+

User-defined types were introduced in Cassandra 2.1.

+
+

New in version 2.1.0.

+
+
+
+as_cql_query(formatted=False)
+

Returns a CQL query that can be used to recreate this type. +If formatted is set to True, extra whitespace will +be added to make the query more readable.

+
+ +
+ +
+
+class cassandra.metadata.Function
+

A user defined function, as created by CREATE FUNCTION statements.

+

User-defined functions were introduced in Cassandra 2.2

+
+

New in version 2.6.0.

+
+
+
+as_cql_query(formatted=False)
+

Returns a CQL query that can be used to recreate this function. +If formatted is set to True, extra whitespace will +be added to make the query more readable.

+
+ +
+ +
+
+class cassandra.metadata.Aggregate
+

A user defined aggregate function, as created by CREATE AGGREGATE statements.

+

Aggregate functions were introduced in Cassandra 2.2

+
+

New in version 2.6.0.

+
+
+
+as_cql_query(formatted=False)
+

Returns a CQL query that can be used to recreate this aggregate. +If formatted is set to True, extra whitespace will +be added to make the query more readable.

+
+ +
+ +
+
+class cassandra.metadata.TableMetadata
+

A representation of the schema for a single table.

+
+
+as_cql_query(formatted=False)
+

Returns a CQL query that can be used to recreate this table (index +creations are not included). If formatted is set to True, +extra whitespace will be added to make the query human readable.

+
+ +
+
+export_as_string()
+

Returns a string of CQL queries that can be used to recreate this table +along with all indexes on it. The returned string is formatted to +be human readable.

+
+ +
+
+property is_cql_compatible
+

A boolean indicating if this table can be represented as CQL in export

+
+ +
+
+property primary_key
+

A list of ColumnMetadata representing the components of +the primary key for this table.

+
+ +
+ +
+
+class cassandra.metadata.TableMetadataV3
+

For C* 3.0+. option_maps take a superset of map names, so if nothing +changes structurally, new option maps can just be appended to the list.

+
+
+property is_cql_compatible
+

A boolean indicating if this table can be represented as CQL in export

+
+ +
+ +
+
+class cassandra.metadata.TableMetadataDSE68
+
+
+as_cql_query(formatted=False)
+

Returns a CQL query that can be used to recreate this table (index +creations are not included). If formatted is set to True, +extra whitespace will be added to make the query human readable.

+
+ +
+ +
+
+class cassandra.metadata.ColumnMetadata
+

A representation of a single column in a table.

+
+ +
+
+class cassandra.metadata.IndexMetadata
+

A representation of a secondary index on a column.

+
+
+as_cql_query()
+

Returns a CQL query that can be used to recreate this index.

+
+ +
+
+export_as_string()
+

Returns a CQL query string that can be used to recreate this index.

+
+ +
+ +
+
+class cassandra.metadata.MaterializedViewMetadata
+

A representation of a materialized view on a table

+
+
+as_cql_query(formatted=False)
+

Returns a CQL query that can be used to recreate this function. +If formatted is set to True, extra whitespace will +be added to make the query more readable.

+
+ +
+ +
+
+class cassandra.metadata.VertexMetadata
+

A representation of a vertex on a table

+
+ +
+
+class cassandra.metadata.EdgeMetadata
+

A representation of an edge on a table

+
+ +
+
+

Tokens and Ring Topology

+
+
+class cassandra.metadata.TokenMap
+

Information about the layout of the ring.

+
+
+get_replicas(keyspace, token)
+

Get a set of Host instances representing all of the +replica nodes for a given Token.

+
+ +
+ +
+
+class cassandra.metadata.Token
+

Abstract class representing a token.

+
+ +
+
+class cassandra.metadata.Murmur3Token(token)
+

A token for Murmur3Partitioner.

+

token is an int or string representing the token.

+
+ +
+
+class cassandra.metadata.MD5Token(token)
+

A token for RandomPartitioner.

+
+ +
+
+class cassandra.metadata.BytesToken(token)
+

A token for ByteOrderedPartitioner.

+
+
+classmethod from_string(token_string)
+

token_string should be the string representation from the server.

+
+ +
+ +
+
+cassandra.metadata.ReplicationStrategy
+

alias of cassandra.metadata._ReplicationStrategy

+
+ +
+
+class cassandra.metadata.ReplicationFactor(all_replicas, transient_replicas=None)
+

Represent the replication factor of a keyspace.

+
+ +
+
+class cassandra.metadata.SimpleStrategy(options_map)
+
+
+export_for_schema()
+

Returns a string version of these replication options which are +suitable for use in a CREATE KEYSPACE statement.

+
+ +
+
+property replication_factor
+

The replication factor for this keyspace.

+

For backward compatibility, this returns the +cassandra.metadata.ReplicationFactor.full_replicas value of +cassandra.metadata.SimpleStrategy.replication_factor_info.

+
+ +
+ +
+
+class cassandra.metadata.NetworkTopologyStrategy(dc_replication_factors)
+
+
+export_for_schema()
+

Returns a string version of these replication options which are +suitable for use in a CREATE KEYSPACE statement.

+
+ +
+ +
+
+class cassandra.metadata.LocalStrategy(options_map)
+
+
+export_for_schema()
+

Returns a string version of these replication options which are +suitable for use in a CREATE KEYSPACE statement.

+
+ +
+ +
+
+cassandra.metadata.group_keys_by_replica(session, keyspace, table, keys)
+

Returns a dict with the keys grouped per host. This can be +used to more accurately group by IN clause or to batch the keys per host.

+

If a valid replica is not found for a particular key it will be grouped under +NO_VALID_REPLICA

+

Example usage:

+
>>> result = group_keys_by_replica(
+...     session, "system", "peers",
+...     (("127.0.0.1", ), ("127.0.0.2", )))
+
+
+
+ +
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.25.11-scylla/api/cassandra/metrics.html b/3.25.11-scylla/api/cassandra/metrics.html new file mode 100644 index 0000000000..e553c4a03c --- /dev/null +++ b/3.25.11-scylla/api/cassandra/metrics.html @@ -0,0 +1,755 @@ + + + + + + + + + + + + + cassandra.metrics - Performance Metrics | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.metrics - Performance Metrics

+
+
+class cassandra.metrics.Metrics
+

A collection of timers and counters for various performance metrics.

+

Timer metrics are represented as floating point seconds.

+
+
+request_timer = None
+

A greplin.scales.PmfStat timer for requests. This is a dict-like +object with the following keys:

+
    +
  • count - number of requests that have been timed

  • +
  • min - min latency

  • +
  • max - max latency

  • +
  • mean - mean latency

  • +
  • stddev - standard deviation for latencies

  • +
  • median - median latency

  • +
  • 75percentile - 75th percentile latencies

  • +
  • 95percentile - 95th percentile latencies

  • +
  • 98percentile - 98th percentile latencies

  • +
  • 99percentile - 99th percentile latencies

  • +
  • 999percentile - 99.9th percentile latencies

  • +
+
+ +
+
+connection_errors = None
+

A greplin.scales.IntStat count of the number of times that a +request to a Cassandra node has failed due to a connection problem.

+
+ +
+
+write_timeouts = None
+

A greplin.scales.IntStat count of write requests that resulted +in a timeout.

+
+ +
+
+read_timeouts = None
+

A greplin.scales.IntStat count of read requests that resulted +in a timeout.

+
+ +
+
+unavailables = None
+

A greplin.scales.IntStat count of write or read requests that +failed due to an insufficient number of replicas being alive to meet +the requested ConsistencyLevel.

+
+ +
+
+other_errors = None
+

A greplin.scales.IntStat count of all other request failures, +including failures caused by invalid requests, bootstrapping nodes, +overloaded nodes, etc.

+
+ +
+
+retries = None
+

A greplin.scales.IntStat count of the number of times a +request was retried based on the RetryPolicy decision.

+
+ +
+
+ignores = None
+

A greplin.scales.IntStat count of the number of times a +failed request was ignored based on the RetryPolicy decision.

+
+ +
+
+known_hosts = None
+

A greplin.scales.IntStat count of the number of nodes in +the cluster that the driver is aware of, regardless of whether any +connections are opened to those nodes.

+
+ +
+
+connected_to = None
+

A greplin.scales.IntStat count of the number of nodes that +the driver currently has at least one connection open to.

+
+ +
+
+open_connections = None
+

A greplin.scales.IntStat count of the number connections +the driver currently has open.

+
+ +
+
+get_stats()
+

Returns the metrics for the registered cluster instance.

+
+ +
+
+set_stats_name(stats_name)
+

Set the metrics stats name. +The stats_name is a string used to access the metris through scales: scales.getStats()[<stats_name>] +Default is ‘cassandra-<num>’.

+
+ +
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.25.11-scylla/api/cassandra/policies.html b/3.25.11-scylla/api/cassandra/policies.html new file mode 100644 index 0000000000..3e2cc82a26 --- /dev/null +++ b/3.25.11-scylla/api/cassandra/policies.html @@ -0,0 +1,1742 @@ + + + + + + + + + + + + + cassandra.policies - Load balancing and Failure Handling Policies | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.policies - Load balancing and Failure Handling Policies

+
+

Load Balancing

+
+
+class cassandra.policies.HostDistance
+

A measure of how “distant” a node is from the client, which +may influence how the load balancer distributes requests +and how many connections are opened to the node.

+
+
+IGNORED = -1
+

A node with this distance should never be queried or have +connections opened to it.

+
+ +
+
+LOCAL = 0
+

Nodes with LOCAL distance will be preferred for operations +under some load balancing policies (such as DCAwareRoundRobinPolicy) +and will have a greater number of connections opened against +them by default.

+

This distance is typically used for nodes within the same +datacenter as the client.

+
+ +
+
+REMOTE = 1
+

Nodes with REMOTE distance will be treated as a last resort +by some load balancing policies (such as DCAwareRoundRobinPolicy) +and will have a smaller number of connections opened against +them by default.

+

This distance is typically used for nodes outside of the +datacenter that the client is running in.

+
+ +
+ +
+
+class cassandra.policies.LoadBalancingPolicy
+

Load balancing policies are used to decide how to distribute +requests among all possible coordinator nodes in the cluster.

+

In particular, they may focus on querying “near” nodes (those +in a local datacenter) or on querying nodes who happen to +be replicas for the requested data.

+

You may also use subclasses of LoadBalancingPolicy for +custom behavior.

+
+
+distance(host)
+

Returns a measure of how remote a Host is in +terms of the HostDistance enums.

+
+ +
+
+populate(cluster, hosts)
+

This method is called to initialize the load balancing +policy with a set of Host instances before its +first use. The cluster parameter is an instance of +Cluster.

+
+ +
+
+make_query_plan(working_keyspace=None, query=None)
+

Given a Statement instance, return a iterable +of Host instances which should be queried in that +order. A generator may work well for custom implementations +of this method.

+

Note that the query argument may be None when preparing +statements.

+

working_keyspace should be the string name of the current keyspace, +as set through Session.set_keyspace() or with a USE +statement.

+
+ +
+
+check_supported()
+

This will be called after the cluster Metadata has been initialized. +If the load balancing policy implementation cannot be supported for +some reason (such as a missing C extension), this is the point at +which it should raise an exception.

+
+ +
+ +
+
+class cassandra.policies.RoundRobinPolicy
+

A subclass of LoadBalancingPolicy which evenly +distributes queries across all nodes in the cluster, +regardless of what datacenter the nodes may be in.

+
+
+populate(cluster, hosts)
+

This method is called to initialize the load balancing +policy with a set of Host instances before its +first use. The cluster parameter is an instance of +Cluster.

+
+ +
+
+distance(host)
+

Returns a measure of how remote a Host is in +terms of the HostDistance enums.

+
+ +
+
+make_query_plan(working_keyspace=None, query=None)
+

Given a Statement instance, return a iterable +of Host instances which should be queried in that +order. A generator may work well for custom implementations +of this method.

+

Note that the query argument may be None when preparing +statements.

+

working_keyspace should be the string name of the current keyspace, +as set through Session.set_keyspace() or with a USE +statement.

+
+ +
+
+on_up(host)
+

Called when a node is marked up.

+
+ +
+
+on_down(host)
+

Called when a node is marked down.

+
+ +
+
+on_add(host)
+

Called when a node is added to the cluster. The newly added node +should be considered up.

+
+ +
+
+on_remove(host)
+

Called when a node is removed from the cluster.

+
+ +
+ +
+
+class cassandra.policies.DCAwareRoundRobinPolicy(local_dc='', used_hosts_per_remote_dc=0)
+

Similar to RoundRobinPolicy, but prefers hosts +in the local datacenter and only uses nodes in remote +datacenters as a last resort.

+

The local_dc parameter should be the name of the datacenter +(such as is reported by nodetool ring) that should +be considered local. If not specified, the driver will choose +a local_dc based on the first host among Cluster.contact_points +having a valid DC. If relying on this mechanism, all specified +contact points should be nodes in a single, local DC.

+

used_hosts_per_remote_dc controls how many nodes in +each remote datacenter will have connections opened +against them. In other words, used_hosts_per_remote_dc hosts +will be considered REMOTE and the +rest will be considered IGNORED. +By default, all remote hosts are ignored.

+
+
+populate(cluster, hosts)
+

This method is called to initialize the load balancing +policy with a set of Host instances before its +first use. The cluster parameter is an instance of +Cluster.

+
+ +
+
+distance(host)
+

Returns a measure of how remote a Host is in +terms of the HostDistance enums.

+
+ +
+
+make_query_plan(working_keyspace=None, query=None)
+

Given a Statement instance, return a iterable +of Host instances which should be queried in that +order. A generator may work well for custom implementations +of this method.

+

Note that the query argument may be None when preparing +statements.

+

working_keyspace should be the string name of the current keyspace, +as set through Session.set_keyspace() or with a USE +statement.

+
+ +
+
+on_up(host)
+

Called when a node is marked up.

+
+ +
+
+on_down(host)
+

Called when a node is marked down.

+
+ +
+
+on_add(host)
+

Called when a node is added to the cluster. The newly added node +should be considered up.

+
+ +
+
+on_remove(host)
+

Called when a node is removed from the cluster.

+
+ +
+ +
+
+class cassandra.policies.WhiteListRoundRobinPolicy(hosts)
+

A subclass of RoundRobinPolicy which evenly +distributes queries across all nodes in the cluster, +regardless of what datacenter the nodes may be in, but +only if that node exists in the list of allowed nodes

+

This policy is addresses the issue described in +https://datastax-oss.atlassian.net/browse/JAVA-145 +Where connection errors occur when connection +attempts are made to private IP addresses remotely

+

The hosts parameter should be a sequence of hosts to permit +connections to.

+
+
+populate(cluster, hosts)
+

This method is called to initialize the load balancing +policy with a set of Host instances before its +first use. The cluster parameter is an instance of +Cluster.

+
+ +
+
+distance(host)
+

Returns a measure of how remote a Host is in +terms of the HostDistance enums.

+
+ +
+
+on_up(host)
+

Called when a node is marked up.

+
+ +
+
+on_add(host)
+

Called when a node is added to the cluster. The newly added node +should be considered up.

+
+ +
+ +
+
+class cassandra.policies.TokenAwarePolicy(child_policy, shuffle_replicas=False)
+

A LoadBalancingPolicy wrapper that adds token awareness to +a child policy.

+

This alters the child policy’s behavior so that it first attempts to +send queries to LOCAL replicas (as determined +by the child policy) based on the Statement’s +routing_key. If shuffle_replicas is +truthy, these replicas will be yielded in a random order. Once those +hosts are exhausted, the remaining hosts in the child policy’s query +plan will be used in the order provided by the child policy.

+

If no routing_key is set on the query, the child +policy’s query plan will be used as is.

+
+
+shuffle_replicas = False
+

Yield local replicas in a random order.

+
+ +
+
+populate(cluster, hosts)
+

This method is called to initialize the load balancing +policy with a set of Host instances before its +first use. The cluster parameter is an instance of +Cluster.

+
+ +
+
+check_supported()
+

This will be called after the cluster Metadata has been initialized. +If the load balancing policy implementation cannot be supported for +some reason (such as a missing C extension), this is the point at +which it should raise an exception.

+
+ +
+
+distance(*args, **kwargs)
+

Returns a measure of how remote a Host is in +terms of the HostDistance enums.

+
+ +
+
+make_query_plan(working_keyspace=None, query=None)
+

Given a Statement instance, return a iterable +of Host instances which should be queried in that +order. A generator may work well for custom implementations +of this method.

+

Note that the query argument may be None when preparing +statements.

+

working_keyspace should be the string name of the current keyspace, +as set through Session.set_keyspace() or with a USE +statement.

+
+ +
+
+on_up(*args, **kwargs)
+

Called when a node is marked up.

+
+ +
+
+on_down(*args, **kwargs)
+

Called when a node is marked down.

+
+ +
+
+on_add(*args, **kwargs)
+

Called when a node is added to the cluster. The newly added node +should be considered up.

+
+ +
+
+on_remove(*args, **kwargs)
+

Called when a node is removed from the cluster.

+
+ +
+ +
+
+class cassandra.policies.HostFilterPolicy(child_policy, predicate)
+

A LoadBalancingPolicy subclass configured with a child policy, +and a single-argument predicate. This policy defers to the child policy for +hosts where predicate(host) is truthy. Hosts for which +predicate(host) is falsey will be considered IGNORED, and will +not be used in a query plan.

+

This can be used in the cases where you need a whitelist or blacklist +policy, e.g. to prepare for decommissioning nodes or for testing:

+
def address_is_ignored(host):
+    return host.address in [ignored_address0, ignored_address1]
+
+blacklist_filter_policy = HostFilterPolicy(
+    child_policy=RoundRobinPolicy(),
+    predicate=address_is_ignored
+)
+
+cluster = Cluster(
+    primary_host,
+    load_balancing_policy=blacklist_filter_policy,
+)
+
+
+

See the note in the make_query_plan() documentation for a caveat on +how wrapping ordering polices (e.g. RoundRobinPolicy) may break +desirable properties of the wrapped policy.

+

Please note that whitelist and blacklist policies are not recommended for +general, day-to-day use. You probably want something like +DCAwareRoundRobinPolicy, which prefers a local DC but has +fallbacks, over a brute-force method like whitelisting or blacklisting.

+
+
Parameters
+
    +
  • child_policy – an instantiated LoadBalancingPolicy +that this one will defer to.

  • +
  • predicate – a one-parameter function that takes a Host. +If it returns a falsey value, the Host will +be IGNORED and not returned in query plans.

  • +
+
+
+
+
+predicate(host)
+

A predicate, set on object initialization, that takes a Host +and returns a value. If the value is falsy, the Host is +IGNORED. If the value is truthy, +HostFilterPolicy defers to the child policy to determine the +host’s distance.

+

This is a read-only value set in __init__, implemented as a +property.

+
+ +
+
+distance(host)
+

Checks if predicate(host), then returns +IGNORED if falsey, and defers to the child policy +otherwise.

+
+ +
+
+make_query_plan(working_keyspace=None, query=None)
+

Defers to the child policy’s +LoadBalancingPolicy.make_query_plan() and filters the results.

+

Note that this filtering may break desirable properties of the wrapped +policy in some cases. For instance, imagine if you configure this +policy to filter out host2, and to wrap a round-robin policy that +rotates through three hosts in the order host1, host2, host3, +host2, host3, host1, host3, host1, host2, repeating. This +policy will yield host1, host3, host3, host1, host3, host1, +disproportionately favoring host3.

+
+ +
+ +
+
+class cassandra.policies.DefaultLoadBalancingPolicy(child_policy)
+

A LoadBalancingPolicy wrapper that adds the ability to target a specific host first.

+

If no host is set on the query, the child policy’s query plan will be used as is.

+
+
+populate(cluster, hosts)
+

This method is called to initialize the load balancing +policy with a set of Host instances before its +first use. The cluster parameter is an instance of +Cluster.

+
+ +
+
+make_query_plan(working_keyspace=None, query=None)
+

Given a Statement instance, return a iterable +of Host instances which should be queried in that +order. A generator may work well for custom implementations +of this method.

+

Note that the query argument may be None when preparing +statements.

+

working_keyspace should be the string name of the current keyspace, +as set through Session.set_keyspace() or with a USE +statement.

+
+ +
+ +
+
+class cassandra.policies.DSELoadBalancingPolicy(*args, **kwargs)
+

Deprecated: This will be removed in the next major release, +consider using DefaultLoadBalancingPolicy.

+
+ +
+
+

Translating Server Node Addresses

+
+
+class cassandra.policies.AddressTranslator
+

Interface for translating cluster-defined endpoints.

+

The driver discovers nodes using server metadata and topology change events. Normally, +the endpoint defined by the server is the right way to connect to a node. In some environments, +these addresses may not be reachable, or not preferred (public vs. private IPs in cloud environments, +suboptimal routing, etc). This interface allows for translating from server defined endpoints to +preferred addresses for driver connections.

+

Note: contact_points provided while creating the Cluster instance are not +translated using this mechanism – only addresses received from Cassandra nodes are.

+
+
+translate(addr)
+

Accepts the node ip address, and returns a translated address to be used connecting to this node.

+
+ +
+ +
+
+class cassandra.policies.IdentityTranslator
+

Returns the endpoint with no translation

+
+
+translate(addr)
+

Accepts the node ip address, and returns a translated address to be used connecting to this node.

+
+ +
+ +
+
+class cassandra.policies.EC2MultiRegionTranslator
+

Resolves private ips of the hosts in the same datacenter as the client, and public ips of hosts in other datacenters.

+
+
+translate(addr)
+

Reverse DNS the public broadcast_address, then lookup that hostname to get the AWS-resolved IP, which +will point to the private IP address within the same datacenter.

+
+ +
+ +
+
+

Marking Hosts Up or Down

+
+
+class cassandra.policies.ConvictionPolicy(host)
+

A policy which decides when hosts should be considered down +based on the types of failures and the number of failures.

+

If custom behavior is needed, this class may be subclassed.

+

host is an instance of Host.

+
+
+add_failure(connection_exc)
+

Implementations should return True if the host should be +convicted, False otherwise.

+
+ +
+
+reset()
+

Implementations should clear out any convictions or state regarding +the host.

+
+ +
+ +
+
+class cassandra.policies.SimpleConvictionPolicy(host)
+

The default implementation of ConvictionPolicy, +which simply marks a host as down after the first failure +of any kind.

+

host is an instance of Host.

+
+
+add_failure(connection_exc)
+

Implementations should return True if the host should be +convicted, False otherwise.

+
+ +
+
+reset()
+

Implementations should clear out any convictions or state regarding +the host.

+
+ +
+ +
+
+

Reconnecting to Dead Hosts

+
+
+class cassandra.policies.ReconnectionPolicy
+

This class and its subclasses govern how frequently an attempt is made +to reconnect to nodes that are marked as dead.

+

If custom behavior is needed, this class may be subclassed.

+
+
+new_schedule()
+

This should return a finite or infinite iterable of delays (each as a +floating point number of seconds) inbetween each failed reconnection +attempt. Note that if the iterable is finite, reconnection attempts +will cease once the iterable is exhausted.

+
+ +
+ +
+
+class cassandra.policies.ConstantReconnectionPolicy(delay, max_attempts=64)
+

A ReconnectionPolicy subclass which sleeps for a fixed delay +inbetween each reconnection attempt.

+

delay should be a floating point number of seconds to wait inbetween +each attempt.

+

max_attempts should be a total number of attempts to be made before +giving up, or None to continue reconnection attempts forever. +The default is 64.

+
+
+new_schedule()
+

This should return a finite or infinite iterable of delays (each as a +floating point number of seconds) inbetween each failed reconnection +attempt. Note that if the iterable is finite, reconnection attempts +will cease once the iterable is exhausted.

+
+ +
+ +
+
+class cassandra.policies.ExponentialReconnectionPolicy(base_delay, max_delay, max_attempts=64)
+

A ReconnectionPolicy subclass which exponentially increases +the length of the delay inbetween each reconnection attempt up to +a set maximum delay.

+

A random amount of jitter (+/- 15%) will be added to the pure exponential +delay value to avoid the situations where many reconnection handlers are +trying to reconnect at exactly the same time.

+

base_delay and max_delay should be in floating point units of +seconds.

+

max_attempts should be a total number of attempts to be made before +giving up, or None to continue reconnection attempts forever. +The default is 64.

+
+
+new_schedule()
+

This should return a finite or infinite iterable of delays (each as a +floating point number of seconds) inbetween each failed reconnection +attempt. Note that if the iterable is finite, reconnection attempts +will cease once the iterable is exhausted.

+
+ +
+ +
+
+

Retrying Failed Operations

+
+
+class cassandra.policies.WriteType
+

For usage with RetryPolicy, this describe a type +of write operation.

+
+
+SIMPLE = 0
+

A write to a single partition key. Such writes are guaranteed to be atomic +and isolated.

+
+ +
+
+BATCH = 1
+

A write to multiple partition keys that used the distributed batch log to +ensure atomicity.

+
+ +
+
+UNLOGGED_BATCH = 2
+

A write to multiple partition keys that did not use the distributed batch +log. Atomicity for such writes is not guaranteed.

+
+ +
+
+COUNTER = 3
+

A counter write (for one or multiple partition keys). Such writes should +not be replayed in order to avoid overcount.

+
+ +
+
+BATCH_LOG = 4
+

The initial write to the distributed batch log that Cassandra performs +internally before a BATCH write.

+
+ +
+
+CAS = 5
+

A lighweight-transaction write, such as “DELETE … IF EXISTS”.

+
+ +
+
+VIEW = 6
+

This WriteType is only seen in results for requests that were unable to +complete MV operations.

+
+ +
+
+CDC = 7
+

This WriteType is only seen in results for requests that were unable to +complete CDC operations.

+
+ +
+ +
+
+class cassandra.policies.RetryPolicy
+

A policy that describes whether to retry, rethrow, or ignore coordinator +timeout and unavailable failures. These are failures reported from the +server side. Timeouts are configured by +settings in cassandra.yaml. +Unavailable failures occur when the coordinator cannot acheive the consistency +level for a request. For further information see the method descriptions +below.

+

To specify a default retry policy, set the +Cluster.default_retry_policy attribute to an instance of this +class or one of its subclasses.

+

To specify a retry policy per query, set the Statement.retry_policy +attribute to an instance of this class or one of its subclasses.

+

If custom behavior is needed for retrying certain operations, +this class may be subclassed.

+
+
+RETRY = 0
+

This should be returned from the below methods if the operation +should be retried on the same connection.

+
+ +
+
+RETHROW = 1
+

This should be returned from the below methods if the failure +should be propagated and no more retries attempted.

+
+ +
+
+IGNORE = 2
+

This should be returned from the below methods if the failure +should be ignored but no more retries should be attempted.

+
+ +
+
+RETRY_NEXT_HOST = 3
+

This should be returned from the below methods if the operation +should be retried on another connection.

+
+ +
+
+on_read_timeout(query, consistency, required_responses, received_responses, data_retrieved, retry_num)
+

This is called when a read operation times out from the coordinator’s +perspective (i.e. a replica did not respond to the coordinator in time). +It should return a tuple with two items: one of the class enums (such +as RETRY) and a ConsistencyLevel to retry the +operation at or None to keep the same consistency level.

+

query is the Statement that timed out.

+

consistency is the ConsistencyLevel that the operation was +attempted at.

+

The required_responses and received_responses parameters describe +how many replicas needed to respond to meet the requested consistency +level and how many actually did respond before the coordinator timed +out the request. data_retrieved is a boolean indicating whether +any of those responses contained data (as opposed to just a digest).

+

retry_num counts how many times the operation has been retried, so +the first time this method is called, retry_num will be 0.

+

By default, operations will be retried at most once, and only if +a sufficient number of replicas responded (with data digests).

+
+ +
+
+on_write_timeout(query, consistency, write_type, required_responses, received_responses, retry_num)
+

This is called when a write operation times out from the coordinator’s +perspective (i.e. a replica did not respond to the coordinator in time).

+

query is the Statement that timed out.

+

consistency is the ConsistencyLevel that the operation was +attempted at.

+

write_type is one of the WriteType enums describing the +type of write operation.

+

The required_responses and received_responses parameters describe +how many replicas needed to acknowledge the write to meet the requested +consistency level and how many replicas actually did acknowledge the +write before the coordinator timed out the request.

+

retry_num counts how many times the operation has been retried, so +the first time this method is called, retry_num will be 0.

+

By default, failed write operations will retried at most once, and +they will only be retried if the write_type was +BATCH_LOG.

+
+ +
+
+on_unavailable(query, consistency, required_replicas, alive_replicas, retry_num)
+

This is called when the coordinator node determines that a read or +write operation cannot be successful because the number of live +replicas are too low to meet the requested ConsistencyLevel. +This means that the read or write operation was never forwarded to +any replicas.

+

query is the Statement that failed.

+

consistency is the ConsistencyLevel that the operation was +attempted at.

+

required_replicas is the number of replicas that would have needed to +acknowledge the operation to meet the requested consistency level. +alive_replicas is the number of replicas that the coordinator +considered alive at the time of the request.

+

retry_num counts how many times the operation has been retried, so +the first time this method is called, retry_num will be 0.

+

By default, if this is the first retry, it triggers a retry on the next +host in the query plan with the same consistency level. If this is not the +first retry, no retries will be attempted and the error will be re-raised.

+
+ +
+
+on_request_error(query, consistency, error, retry_num)
+

This is called when an unexpected error happens. This can be in the +following situations:

+
    +
  • On a connection error

  • +
  • On server errors: overloaded, isBootstrapping, serverError, etc.

  • +
+

query is the Statement that timed out.

+

consistency is the ConsistencyLevel that the operation was +attempted at.

+

error the instance of the exception.

+

retry_num counts how many times the operation has been retried, so +the first time this method is called, retry_num will be 0.

+

The default, it triggers a retry on the next host in the query plan +with the same consistency level.

+
+ +
+ +
+
+class cassandra.policies.FallthroughRetryPolicy
+

A retry policy that never retries and always propagates failures to +the application.

+
+
+on_read_timeout(*args, **kwargs)
+

This is called when a read operation times out from the coordinator’s +perspective (i.e. a replica did not respond to the coordinator in time). +It should return a tuple with two items: one of the class enums (such +as RETRY) and a ConsistencyLevel to retry the +operation at or None to keep the same consistency level.

+

query is the Statement that timed out.

+

consistency is the ConsistencyLevel that the operation was +attempted at.

+

The required_responses and received_responses parameters describe +how many replicas needed to respond to meet the requested consistency +level and how many actually did respond before the coordinator timed +out the request. data_retrieved is a boolean indicating whether +any of those responses contained data (as opposed to just a digest).

+

retry_num counts how many times the operation has been retried, so +the first time this method is called, retry_num will be 0.

+

By default, operations will be retried at most once, and only if +a sufficient number of replicas responded (with data digests).

+
+ +
+
+on_write_timeout(*args, **kwargs)
+

This is called when a write operation times out from the coordinator’s +perspective (i.e. a replica did not respond to the coordinator in time).

+

query is the Statement that timed out.

+

consistency is the ConsistencyLevel that the operation was +attempted at.

+

write_type is one of the WriteType enums describing the +type of write operation.

+

The required_responses and received_responses parameters describe +how many replicas needed to acknowledge the write to meet the requested +consistency level and how many replicas actually did acknowledge the +write before the coordinator timed out the request.

+

retry_num counts how many times the operation has been retried, so +the first time this method is called, retry_num will be 0.

+

By default, failed write operations will retried at most once, and +they will only be retried if the write_type was +BATCH_LOG.

+
+ +
+
+on_unavailable(*args, **kwargs)
+

This is called when the coordinator node determines that a read or +write operation cannot be successful because the number of live +replicas are too low to meet the requested ConsistencyLevel. +This means that the read or write operation was never forwarded to +any replicas.

+

query is the Statement that failed.

+

consistency is the ConsistencyLevel that the operation was +attempted at.

+

required_replicas is the number of replicas that would have needed to +acknowledge the operation to meet the requested consistency level. +alive_replicas is the number of replicas that the coordinator +considered alive at the time of the request.

+

retry_num counts how many times the operation has been retried, so +the first time this method is called, retry_num will be 0.

+

By default, if this is the first retry, it triggers a retry on the next +host in the query plan with the same consistency level. If this is not the +first retry, no retries will be attempted and the error will be re-raised.

+
+ +
+
+on_request_error(*args, **kwargs)
+

This is called when an unexpected error happens. This can be in the +following situations:

+
    +
  • On a connection error

  • +
  • On server errors: overloaded, isBootstrapping, serverError, etc.

  • +
+

query is the Statement that timed out.

+

consistency is the ConsistencyLevel that the operation was +attempted at.

+

error the instance of the exception.

+

retry_num counts how many times the operation has been retried, so +the first time this method is called, retry_num will be 0.

+

The default, it triggers a retry on the next host in the query plan +with the same consistency level.

+
+ +
+ +
+
+class cassandra.policies.DowngradingConsistencyRetryPolicy(*args, **kwargs)
+

Deprecated: This retry policy will be removed in the next major release.

+

A retry policy that sometimes retries with a lower consistency level than +the one initially requested.

+

BEWARE: This policy may retry queries using a lower consistency +level than the one initially requested. By doing so, it may break +consistency guarantees. In other words, if you use this retry policy, +there are cases (documented below) where a read at QUORUM +may not see a preceding write at QUORUM. Do not use this +policy unless you have understood the cases where this can happen and +are ok with that. It is also recommended to subclass this class so +that queries that required a consistency level downgrade can be +recorded (so that repairs can be made later, etc).

+

This policy implements the same retries as RetryPolicy, +but on top of that, it also retries in the following cases:

+
    +
  • On a read timeout: if the number of replicas that responded is +greater than one but lower than is required by the requested +consistency level, the operation is retried at a lower consistency +level.

  • +
  • On a write timeout: if the operation is an UNLOGGED_BATCH +and at least one replica acknowledged the write, the operation is +retried at a lower consistency level. Furthermore, for other +write types, if at least one replica acknowledged the write, the +timeout is ignored.

  • +
  • On an unavailable exception: if at least one replica is alive, the +operation is retried at a lower consistency level.

  • +
+

The reasoning behind this retry policy is as follows: if, based +on the information the Cassandra coordinator node returns, retrying the +operation with the initially requested consistency has a chance to +succeed, do it. Otherwise, if based on that information we know the +initially requested consistency level cannot be achieved currently, then:

+
    +
  • For writes, ignore the exception (thus silently failing the +consistency requirement) if we know the write has been persisted on at +least one replica.

  • +
  • For reads, try reading at a lower consistency level (thus silently +failing the consistency requirement).

  • +
+

In other words, this policy implements the idea that if the requested +consistency level cannot be achieved, the next best thing for writes is +to make sure the data is persisted, and that reading something is better +than reading nothing, even if there is a risk of reading stale data.

+
+
+on_read_timeout(query, consistency, required_responses, received_responses, data_retrieved, retry_num)
+

This is called when a read operation times out from the coordinator’s +perspective (i.e. a replica did not respond to the coordinator in time). +It should return a tuple with two items: one of the class enums (such +as RETRY) and a ConsistencyLevel to retry the +operation at or None to keep the same consistency level.

+

query is the Statement that timed out.

+

consistency is the ConsistencyLevel that the operation was +attempted at.

+

The required_responses and received_responses parameters describe +how many replicas needed to respond to meet the requested consistency +level and how many actually did respond before the coordinator timed +out the request. data_retrieved is a boolean indicating whether +any of those responses contained data (as opposed to just a digest).

+

retry_num counts how many times the operation has been retried, so +the first time this method is called, retry_num will be 0.

+

By default, operations will be retried at most once, and only if +a sufficient number of replicas responded (with data digests).

+
+ +
+
+on_write_timeout(query, consistency, write_type, required_responses, received_responses, retry_num)
+

This is called when a write operation times out from the coordinator’s +perspective (i.e. a replica did not respond to the coordinator in time).

+

query is the Statement that timed out.

+

consistency is the ConsistencyLevel that the operation was +attempted at.

+

write_type is one of the WriteType enums describing the +type of write operation.

+

The required_responses and received_responses parameters describe +how many replicas needed to acknowledge the write to meet the requested +consistency level and how many replicas actually did acknowledge the +write before the coordinator timed out the request.

+

retry_num counts how many times the operation has been retried, so +the first time this method is called, retry_num will be 0.

+

By default, failed write operations will retried at most once, and +they will only be retried if the write_type was +BATCH_LOG.

+
+ +
+
+on_unavailable(query, consistency, required_replicas, alive_replicas, retry_num)
+

This is called when the coordinator node determines that a read or +write operation cannot be successful because the number of live +replicas are too low to meet the requested ConsistencyLevel. +This means that the read or write operation was never forwarded to +any replicas.

+

query is the Statement that failed.

+

consistency is the ConsistencyLevel that the operation was +attempted at.

+

required_replicas is the number of replicas that would have needed to +acknowledge the operation to meet the requested consistency level. +alive_replicas is the number of replicas that the coordinator +considered alive at the time of the request.

+

retry_num counts how many times the operation has been retried, so +the first time this method is called, retry_num will be 0.

+

By default, if this is the first retry, it triggers a retry on the next +host in the query plan with the same consistency level. If this is not the +first retry, no retries will be attempted and the error will be re-raised.

+
+ +
+ +
+
+

Retrying Idempotent Operations

+
+
+class cassandra.policies.SpeculativeExecutionPolicy
+

Interface for specifying speculative execution plans

+
+
+new_plan(keyspace, statement)
+

Returns

+
+
Parameters
+
    +
  • keyspace

  • +
  • statement

  • +
+
+
Returns
+

+
+
+
+ +
+ +
+
+class cassandra.policies.ConstantSpeculativeExecutionPolicy(delay, max_attempts)
+

A speculative execution policy that sends a new query every X seconds (delay) for a maximum of Y attempts (max_attempts).

+
+
+new_plan(keyspace, statement)
+

Returns

+
+
Parameters
+
    +
  • keyspace

  • +
  • statement

  • +
+
+
Returns
+

+
+
+
+ +
+ +
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.25.11-scylla/api/cassandra/pool.html b/3.25.11-scylla/api/cassandra/pool.html new file mode 100644 index 0000000000..7140f48d8c --- /dev/null +++ b/3.25.11-scylla/api/cassandra/pool.html @@ -0,0 +1,673 @@ + + + + + + + + + + + + + cassandra.pool - Hosts and Connection Pools | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.pool - Hosts and Connection Pools

+

Connection pooling and host management.

+
+
+class cassandra.pool.Host
+

Represents a single Cassandra node.

+
+
+property address
+

The IP address of the endpoint. This is the RPC address the driver uses when connecting to the node.

+
+ +
+
+property datacenter
+

The datacenter the node is in.

+
+ +
+
+property rack
+

The rack the node is in.

+
+ +
+ +
+
+exception cassandra.pool.NoConnectionsAvailable
+

All existing connections to a given host are busy, or there are +no open connections.

+
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.25.11-scylla/api/cassandra/protocol.html b/3.25.11-scylla/api/cassandra/protocol.html new file mode 100644 index 0000000000..66f5180372 --- /dev/null +++ b/3.25.11-scylla/api/cassandra/protocol.html @@ -0,0 +1,739 @@ + + + + + + + + + + + + + cassandra.protocol - Protocol Features | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.protocol - Protocol Features

+
+

Custom Payloads

+

Native protocol version 4+ allows for a custom payload to be sent between clients +and custom query handlers. The payload is specified as a string:binary_type dict +holding custom key/value pairs.

+

By default these are ignored by the server. They can be useful for servers implementing +a custom QueryHandler.

+

See Session.execute(), :Session.execute_async(), ResponseFuture.custom_payload.

+
+
+class cassandra.protocol._ProtocolHandler
+

_ProtocolHander handles encoding and decoding messages.

+

This class can be specialized to compose Handlers which implement alternative +result decoding or type deserialization. Class definitions are passed to cassandra.cluster.Cluster +on initialization.

+

Contracted class methods are _ProtocolHandler.encode_message() and _ProtocolHandler.decode_message().

+
+
+message_types_by_opcode = {default mapping}
+
+ +
+
+classmethod encode_message(msg, stream_id, protocol_version, compressor, allow_beta_protocol_version)
+

Encodes a message using the specified frame parameters, and compressor

+
+
Parameters
+
    +
  • msg – the message, typically of cassandra.protocol._MessageType, generated by the driver

  • +
  • stream_id – protocol stream id for the frame header

  • +
  • protocol_version – version for the frame header, and used encoding contents

  • +
  • compressor – optional compression function to be used on the body

  • +
+
+
+
+ +
+
+classmethod decode_message(protocol_version, user_type_map, stream_id, flags, opcode, body, decompressor, result_metadata)
+

Decodes a native protocol message body

+
+
Parameters
+
    +
  • protocol_version – version to use decoding contents

  • +
  • user_type_map – map[keyspace name] = map[type name] = custom type to instantiate when deserializing this type

  • +
  • stream_id – native protocol stream id from the frame header

  • +
  • flags – native protocol flags bitmap from the header

  • +
  • opcode – native protocol opcode from the header

  • +
  • body – frame body

  • +
  • decompressor – optional decompression function to inflate the body

  • +
+
+
Returns
+

a message decoded from the body and frame attributes

+
+
+
+ +
+ +
+
+

Faster Deserialization

+

When python-driver is compiled with Cython, it uses a Cython-based deserialization path +to deserialize messages. By default, the driver will use a Cython-based parser that returns +lists of rows similar to the pure-Python version. In addition, there are two additional +ProtocolHandler classes that can be used to deserialize response messages: LazyProtocolHandler +and NumpyProtocolHandler. They can be used as follows:

+
from cassandra.protocol import NumpyProtocolHandler, LazyProtocolHandler
+from cassandra.query import tuple_factory
+s.client_protocol_handler = LazyProtocolHandler   # for a result iterator
+s.row_factory = tuple_factory  #required for Numpy results
+s.client_protocol_handler = NumpyProtocolHandler  # for a dict of NumPy arrays as result
+
+
+

These protocol handlers comprise different parsers, and return results as described below:

+
    +
  • ProtocolHandler: this default implementation is a drop-in replacement for the pure-Python version. +The rows are all parsed upfront, before results are returned.

  • +
  • LazyProtocolHandler: near drop-in replacement for the above, except that it returns an iterator over rows, +lazily decoded into the default row format (this is more efficient since all decoded results are not materialized at once)

  • +
  • NumpyProtocolHander: deserializes results directly into NumPy arrays. This facilitates efficient integration with +analysis toolkits such as Pandas.

  • +
+
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.25.11-scylla/api/cassandra/query.html b/3.25.11-scylla/api/cassandra/query.html new file mode 100644 index 0000000000..2b4c8b04dc --- /dev/null +++ b/3.25.11-scylla/api/cassandra/query.html @@ -0,0 +1,1002 @@ + + + + + + + + + + + + + cassandra.query - Prepared Statements, Batch Statements, Tracing, and Row Factories | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.query - Prepared Statements, Batch Statements, Tracing, and Row Factories

+
+
+cassandra.query.tuple_factory(colnames, rows)
+

Returns each row as a tuple

+

Example:

+
>>> from cassandra.query import tuple_factory
+>>> session = cluster.connect('mykeyspace')
+>>> session.row_factory = tuple_factory
+>>> rows = session.execute("SELECT name, age FROM users LIMIT 1")
+>>> print rows[0]
+('Bob', 42)
+
+
+
+

Changed in version 2.0.0: moved from cassandra.decoder to cassandra.query

+
+
+ +
+
+cassandra.query.named_tuple_factory(colnames, rows)
+

Returns each row as a namedtuple. +This is the default row factory.

+

Example:

+
>>> from cassandra.query import named_tuple_factory
+>>> session = cluster.connect('mykeyspace')
+>>> session.row_factory = named_tuple_factory
+>>> rows = session.execute("SELECT name, age FROM users LIMIT 1")
+>>> user = rows[0]
+
+>>> # you can access field by their name:
+>>> print "name: %s, age: %d" % (user.name, user.age)
+name: Bob, age: 42
+
+>>> # or you can access fields by their position (like a tuple)
+>>> name, age = user
+>>> print "name: %s, age: %d" % (name, age)
+name: Bob, age: 42
+>>> name = user[0]
+>>> age = user[1]
+>>> print "name: %s, age: %d" % (name, age)
+name: Bob, age: 42
+
+
+
+

Changed in version 2.0.0: moved from cassandra.decoder to cassandra.query

+
+
+ +
+
+cassandra.query.dict_factory(colnames, rows)
+

Returns each row as a dict.

+

Example:

+
>>> from cassandra.query import dict_factory
+>>> session = cluster.connect('mykeyspace')
+>>> session.row_factory = dict_factory
+>>> rows = session.execute("SELECT name, age FROM users LIMIT 1")
+>>> print rows[0]
+{u'age': 42, u'name': u'Bob'}
+
+
+
+

Changed in version 2.0.0: moved from cassandra.decoder to cassandra.query

+
+
+ +
+
+cassandra.query.ordered_dict_factory(colnames, rows)
+

Like dict_factory(), but returns each row as an OrderedDict, +so the order of the columns is preserved.

+
+

Changed in version 2.0.0: moved from cassandra.decoder to cassandra.query

+
+
+ +
+
+class cassandra.query.SimpleStatement(query_string, retry_policy=None, consistency_level=None, routing_key=None, serial_consistency_level=None, fetch_size=<object object>, keyspace=None, custom_payload=None, is_idempotent=False)
+

A simple, un-prepared query.

+

query_string should be a literal CQL statement with the exception +of parameter placeholders that will be filled through the +parameters argument of Session.execute().

+

See Statement attributes for a description of the other parameters.

+
+ +
+
+class cassandra.query.PreparedStatement
+

A statement that has been prepared against at least one Cassandra node. +Instances of this class should not be created directly, but through +Session.prepare().

+

A PreparedStatement should be prepared only once. Re-preparing a statement +may affect performance (as the operation requires a network roundtrip).

+

A note about * in prepared statements: Do not use * in prepared statements if you might +change the schema of the table being queried. The driver and server each +maintain a map between metadata for a schema and statements that were +prepared against that schema. When a user changes a schema, e.g. by adding +or removing a column, the server invalidates its mappings involving that +schema. However, there is currently no way to propagate that invalidation +to drivers. Thus, after a schema change, the driver will incorrectly +interpret the results of SELECT * queries prepared before the schema +change. This is currently being addressed in CASSANDRA-10786.

+
+
+bind(values)
+

Creates and returns a BoundStatement instance using values.

+

See BoundStatement.bind() for rules on input values.

+
+ +
+ +
+
+class cassandra.query.BoundStatement(prepared_statement, retry_policy=None, consistency_level=None, routing_key=None, serial_consistency_level=None, fetch_size=<object object>, keyspace=None, custom_payload=None)
+

A prepared statement that has been bound to a particular set of values. +These may be created directly or through PreparedStatement.bind().

+

prepared_statement should be an instance of PreparedStatement.

+

See Statement attributes for a description of the other parameters.

+
+
+bind(values)
+

Binds a sequence of values for the prepared statement parameters +and returns this instance. Note that values must be:

+
    +
  • a sequence, even if you are only binding one value, or

  • +
  • a dict that relates 1-to-1 between dict keys and columns

  • +
+
+

Changed in version 2.6.0: UNSET_VALUE was introduced. These can be bound as positional parameters +in a sequence, or by name in a dict. Additionally, when using protocol v4+:

+
    +
  • short sequences will be extended to match bind parameters with UNSET_VALUE

  • +
  • names may be omitted from a dict with UNSET_VALUE implied.

  • +
+
+
+

Changed in version 3.0.0: method will not throw if extra keys are present in bound dict (PYTHON-178)

+
+
+ +
+
+property routing_key
+

The partition_key portion of the primary key, +which can be used to determine which nodes are replicas for the query.

+

If the partition key is a composite, a list or tuple must be passed in. +Each key component should be in its packed (binary) format, so all +components should be strings.

+
+ +
+ +
+
+class cassandra.query.Statement
+

An abstract class representing a single query. There are three subclasses: +SimpleStatement, BoundStatement, and BatchStatement. +These can be passed to Session.execute().

+
+
+property routing_key
+

The partition_key portion of the primary key, +which can be used to determine which nodes are replicas for the query.

+

If the partition key is a composite, a list or tuple must be passed in. +Each key component should be in its packed (binary) format, so all +components should be strings.

+
+ +
+
+property serial_consistency_level
+

The serial consistency level is only used by conditional updates +(INSERT, UPDATE and DELETE with an IF condition). For +those, the serial_consistency_level defines the consistency level of +the serial phase (or “paxos” phase) while the normal +consistency_level defines the consistency for the “learn” phase, +i.e. what type of reads will be guaranteed to see the update right away. +For example, if a conditional write has a consistency_level of +QUORUM (and is successful), then a +QUORUM read is guaranteed to see that write. +But if the regular consistency_level of that write is +ANY, then only a read with a +consistency_level of SERIAL is +guaranteed to see it (even a read with consistency +ALL is not guaranteed to be enough).

+

The serial consistency can only be one of SERIAL +or LOCAL_SERIAL. While SERIAL guarantees full +linearizability (with other SERIAL updates), LOCAL_SERIAL only +guarantees it in the local data center.

+

The serial consistency level is ignored for any query that is not a +conditional update. Serial reads should use the regular +consistency_level.

+

Serial consistency levels may only be used against Cassandra 2.0+ +and the protocol_version must be set to 2 or higher.

+

See Lightweight Transactions (Compare-and-set) for a discussion on how to work with results returned from +conditional statements.

+
+

New in version 2.0.0.

+
+
+ +
+ +
+
+cassandra.query.UNSET_VALUE
+

The most base type

+
+ +
+
+class cassandra.query.BatchStatement(batch_type=BatchType.LOGGED, retry_policy=None, consistency_level=None)
+

A protocol-level batch of operations which are applied atomically +by default.

+
+

New in version 2.0.0.

+
+

batch_type specifies The BatchType for the batch operation. +Defaults to BatchType.LOGGED.

+

retry_policy should be a RetryPolicy instance for +controlling retries on the operation.

+

consistency_level should be a ConsistencyLevel value +to be used for all operations in the batch.

+

custom_payload is a Custom Payloads passed to the server. +Note: as Statement objects are added to the batch, this map is +updated with any values found in their custom payloads. These are +only allowed when using protocol version 4 or higher.

+

Example usage:

+
insert_user = session.prepare("INSERT INTO users (name, age) VALUES (?, ?)")
+batch = BatchStatement(consistency_level=ConsistencyLevel.QUORUM)
+
+for (name, age) in users_to_insert:
+    batch.add(insert_user, (name, age))
+
+session.execute(batch)
+
+
+

You can also mix different types of operations within a batch:

+
batch = BatchStatement()
+batch.add(SimpleStatement("INSERT INTO users (name, age) VALUES (%s, %s)"), (name, age))
+batch.add(SimpleStatement("DELETE FROM pending_users WHERE name=%s"), (name,))
+session.execute(batch)
+
+
+
+

New in version 2.0.0.

+
+
+

Changed in version 2.1.0: Added serial_consistency_level as a parameter

+
+
+

Changed in version 2.6.0: Added custom_payload as a parameter

+
+
+
+add(statement, parameters=None)
+

Adds a Statement and optional sequence of parameters +to be used with the statement to the batch.

+

Like with other statements, parameters must be a sequence, even +if there is only one item.

+
+ +
+
+add_all(statements, parameters)
+

Adds a sequence of Statement objects and a matching sequence +of parameters to the batch. Statement and parameter sequences must be of equal length or +one will be truncated. None can be used in the parameters position where are needed.

+
+ +
+
+clear()
+

This is a convenience method to clear a batch statement for reuse.

+

Note: it should not be used concurrently with uncompleted execution futures executing the same +BatchStatement.

+
+ +
+
+serial_consistency_level = None
+
+ +
+ +
+
+class cassandra.query.BatchType
+

A BatchType is used with BatchStatement instances to control +the atomicity of the batch operation.

+
+

New in version 2.0.0.

+
+
+
+LOGGED = BatchType.LOGGED
+
+ +
+
+UNLOGGED = BatchType.UNLOGGED
+
+ +
+
+COUNTER = BatchType.COUNTER
+
+ +
+ +
+
+class cassandra.query.ValueSequence(iterable=(), /)
+

A wrapper class that is used to specify that a sequence of values should +be treated as a CQL list of values instead of a single column collection when used +as part of the parameters argument for Session.execute().

+

This is typically needed when supplying a list of keys to select. +For example:

+
>>> my_user_ids = ('alice', 'bob', 'charles')
+>>> query = "SELECT * FROM users WHERE user_id IN %s"
+>>> session.execute(query, parameters=[ValueSequence(my_user_ids)])
+
+
+
+ +
+
+class cassandra.query.QueryTrace
+

A trace of the duration and events that occurred when executing +an operation.

+
+
+populate(max_wait=2.0, wait_for_complete=True, query_cl=None)
+

Retrieves the actual tracing details from Cassandra and populates the +attributes of this instance. Because tracing details are stored +asynchronously by Cassandra, this may need to retry the session +detail fetch. If the trace is still not available after max_wait +seconds, TraceUnavailable will be raised; if max_wait is +None, this will retry forever.

+

wait_for_complete=False bypasses the wait for duration to be populated. +This can be used to query events from partial sessions.

+

query_cl specifies a consistency level to use for polling the trace tables, +if it should be different than the session default.

+
+ +
+ +
+
+class cassandra.query.TraceEvent
+

Representation of a single event within a query trace.

+
+ +
+
+exception cassandra.query.TraceUnavailable
+

Raised when complete trace details cannot be fetched from Cassandra.

+
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.25.11-scylla/api/cassandra/timestamps.html b/3.25.11-scylla/api/cassandra/timestamps.html new file mode 100644 index 0000000000..5ccfb3222a --- /dev/null +++ b/3.25.11-scylla/api/cassandra/timestamps.html @@ -0,0 +1,695 @@ + + + + + + + + + + + + + cassandra.timestamps - Timestamp Generation | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.timestamps - Timestamp Generation

+
+
+class cassandra.timestamps.MonotonicTimestampGenerator(warn_on_drift=True, warning_threshold=0, warning_interval=0)
+

An object that, when called, returns int(time.time() * 1e6) when +possible, but, if the value returned by time.time doesn’t increase, +drifts into the future and logs warnings. +Exposed configuration attributes can be configured with arguments to +__init__ or by changing attributes on an initialized object.

+
+

New in version 3.8.0.

+
+
+
+warn_on_drift = True
+

If true, log warnings when timestamps drift into the future as allowed by +warning_threshold and warning_interval.

+
+ +
+
+warning_threshold = 1
+

This object will only issue warnings when the returned timestamp drifts +more than warning_threshold seconds into the future. +Defaults to 1 second.

+
+ +
+
+warning_interval = 1
+

This object will only issue warnings every warning_interval seconds. +Defaults to 1 second.

+
+ +
+
+_next_timestamp(now, last)
+

Returns the timestamp that should be used if now is the current +time and last is the last timestamp returned by this object. +Intended for internal and testing use only; to generate timestamps, +call an instantiated MonotonicTimestampGenerator object.

+
+
Parameters
+
    +
  • now (int) – an integer to be used as the current time, typically +representing the current time in microseconds since the UNIX epoch

  • +
  • last (int) – an integer representing the last timestamp returned by +this object

  • +
+
+
+
+ +
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.25.11-scylla/api/cassandra/util.html b/3.25.11-scylla/api/cassandra/util.html new file mode 100644 index 0000000000..8e147330fd --- /dev/null +++ b/3.25.11-scylla/api/cassandra/util.html @@ -0,0 +1,1030 @@ + + + + + + + + + + + + + cassandra.util - Utilities | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.util - Utilities

+
+
+class cassandra.util.Date(value)
+

Idealized date: year, month, day

+

Offers wider year range than datetime.date. For Dates that cannot be represented +as a datetime.date (because datetime.MINYEAR, datetime.MAXYEAR), this type falls back +to printing days_from_epoch offset.

+

Initializer value can be:

+
    +
  • integer_type: absolute days from epoch (1970, 1, 1). Can be negative.

  • +
  • datetime.date: built-in date

  • +
  • string_type: a string time of the form “yyyy-mm-dd”

  • +
+
+
+date()
+

Return a built-in datetime.date for Dates falling in the years [datetime.MINYEAR, datetime.MAXYEAR]

+

ValueError is raised for Dates outside this range.

+
+ +
+
+property seconds
+

Absolute seconds from epoch (can be negative)

+
+ +
+ +
+
+class cassandra.util.DateRange(lower_bound=None, upper_bound=None, value=None)
+

DSE DateRange Type

+
+
+lower_bound
+

DateRangeBound representing the lower bound of a bounded range.

+
+ +
+
+upper_bound
+

DateRangeBound representing the upper bound of a bounded range.

+
+ +
+
+value
+

DateRangeBound representing the value of a single-value range.

+
+ +

As noted in its documentation, DateRangeBound uses a millisecond +offset from the UNIX epoch to allow DateRange to represent values +datetime.datetime cannot. For such values, string representions will show +this offset rather than the CQL representation.

+
+
Parameters
+
+
+
+
+ +
+
+class cassandra.util.DateRangeBound(value, precision)
+

Represents a single date value and its precision for DateRange.

+
+
+milliseconds
+

Integer representing milliseconds since the UNIX epoch. May be negative.

+
+ +
+
+precision
+

String representing the precision of a bound. Must be a valid +DateRangePrecision member.

+
+ +

DateRangeBound uses a millisecond offset from the UNIX epoch to +allow DateRange to represent values datetime.datetime cannot. +For such values, string representions will show this offset rather than the +CQL representation.

+
+
Parameters
+
    +
  • value – a value representing ms since the epoch. Accepts an +integer or a datetime.

  • +
  • precision – a string representing precision

  • +
+
+
+
+
+datetime()
+

Return milliseconds as a datetime.datetime if possible. +Raises an OverflowError if the value is out of range.

+
+ +
+
+classmethod from_value(value)
+

Construct a new DateRangeBound from a given value. If +possible, use the value[‘milliseconds’] and value[‘precision’] keys +of the argument. Otherwise, use the argument as a (milliseconds, +precision) iterable.

+
+
Parameters
+

value – a dictlike or iterable object

+
+
+
+ +
+ +
+
+class cassandra.util.DateRangePrecision
+

An “enum” representing the valid values for DateRange.precision.

+
+ +
+
+class cassandra.util.Distance(x=nan, y=nan, radius=nan)
+

Represents a Distance geometry for DSE

+
+
+static from_wkt(s)
+

Parse a Distance geometry from a wkt string and return a new Distance object.

+
+ +
+ +
+
+class cassandra.util.Duration(months=0, days=0, nanoseconds=0)
+

Cassandra Duration Type

+
+ +
+
+class cassandra.util.LineString(coords=())
+

Represents a linestring geometry for DSE

+

‘coords`: a sequence of (x, y) coordinates of points in the linestring

+
+
+static from_wkt(s)
+

Parse a LineString geometry from a wkt string and return a new LineString object.

+
+ +
+ +
+
+class cassandra.util.OrderedMap(*args, **kwargs)
+

An ordered map that accepts non-hashable types for keys. It also maintains the +insertion order of items, behaving as OrderedDict in that regard. These maps +are constructed and read just as normal mapping types, except that they may +contain arbitrary collections and other non-hashable items as keys:

+
>>> od = OrderedMap([({'one': 1, 'two': 2}, 'value'),
+...                  ({'three': 3, 'four': 4}, 'value2')])
+>>> list(od.keys())
+[{'two': 2, 'one': 1}, {'three': 3, 'four': 4}]
+>>> list(od.values())
+['value', 'value2']
+
+
+

These constructs are needed to support nested collections in Cassandra 2.1.3+, +where frozen collections can be specified as parameters to others:

+
CREATE TABLE example (
+    ...
+    value map<frozen<map<int, int>>, double>
+    ...
+)
+
+
+

This class derives from the (immutable) Mapping API. Objects in these maps +are not intended be modified.

+
+ +
+
+class cassandra.util.OrderedMapSerializedKey(cass_type, protocol_version)
+
+ +
+
+class cassandra.util.Point(x=nan, y=nan)
+

Represents a point geometry for DSE

+
+
+static from_wkt(s)
+

Parse a Point geometry from a wkt string and return a new Point object.

+
+ +
+ +
+
+class cassandra.util.Polygon(exterior=(), interiors=None)
+

Represents a polygon geometry for DSE

+

‘exterior`: a sequence of (x, y) coordinates of points in the linestring +interiors: None, or a sequence of sequences or (x, y) coordinates of points describing interior linear rings

+
+
+static from_wkt(s)
+

Parse a Polygon geometry from a wkt string and return a new Polygon object.

+
+ +
+ +
+
+class cassandra.util.SortedSet(iterable=())
+

A sorted set based on sorted list

+

A sorted set implementation is used in this case because it does not +require its elements to be immutable/hashable.

+

#Not implemented: update functions, inplace operators

+
+ +
+
+class cassandra.util.Time(value)
+

Idealized time, independent of day.

+

Up to nanosecond resolution

+

Initializer value can be:

+
    +
  • integer_type: absolute nanoseconds in the day

  • +
  • datetime.time: built-in time

  • +
  • string_type: a string time of the form “HH:MM:SS[.mmmuuunnn]”

  • +
+
+
+property hour
+

The hour component of this time (0-23)

+
+ +
+
+property minute
+

The minute component of this time (0-59)

+
+ +
+
+property nanosecond
+

The fractional seconds component of the time, in nanoseconds

+
+ +
+
+property second
+

The second component of this time (0-59)

+
+ +
+
+time()
+

Return a built-in datetime.time (nanosecond precision truncated to micros).

+
+ +
+ +
+
+class cassandra.util.Version(version)
+

Internal minimalist class to compare versions. +A valid version is: <int>.<int>.<int>.<int or str>.

+

TODO: when python2 support is removed, use packaging.version.

+
+ +
+
+cassandra.util.datetime_from_timestamp(timestamp)
+

Creates a timezone-agnostic datetime from timestamp (in seconds) in a consistent manner. +Works around a Windows issue with large negative timestamps (PYTHON-119), +and rounding differences in Python 3.4 (PYTHON-340).

+
+
Parameters
+

timestamp – a unix timestamp, in seconds

+
+
+
+ +
+
+cassandra.util.datetime_from_uuid1(uuid_arg)
+

Creates a timezone-agnostic datetime from the timestamp in the +specified type-1 UUID.

+
+
Parameters
+

uuid_arg – a version 1 UUID

+
+
+
+ +
+
+cassandra.util.max_uuid_from_time(timestamp)
+

Generates the maximum TimeUUID (type 1) for a given timestamp, as compared by Cassandra.

+

See uuid_from_time() for argument and return types.

+
+ +
+
+cassandra.util.min_uuid_from_time(timestamp)
+

Generates the minimum TimeUUID (type 1) for a given timestamp, as compared by Cassandra.

+

See uuid_from_time() for argument and return types.

+
+ +
+
+cassandra.util.ms_timestamp_from_datetime(dt)
+

Converts a datetime to a timestamp expressed in milliseconds.

+
+
Parameters
+

dt – a datetime.datetime

+
+
+
+ +
+
+cassandra.util.sortedset
+

alias of cassandra.util.SortedSet

+
+ +
+
+cassandra.util.unix_time_from_uuid1(uuid_arg)
+

Converts a version 1 uuid.UUID to a timestamp with the same precision +as time.time() returns. This is useful for examining the +results of queries returning a v1 UUID.

+
+
Parameters
+

uuid_arg – a version 1 UUID

+
+
+
+ +
+
+cassandra.util.utc_datetime_from_ms_timestamp(timestamp)
+

Creates a UTC datetime from a timestamp in milliseconds. See +datetime_from_timestamp().

+

Raises an OverflowError if the timestamp is out of range for +datetime.

+
+
Parameters
+

timestamp – timestamp, in milliseconds

+
+
+
+ +
+
+cassandra.util.uuid_from_time(time_arg, node=None, clock_seq=None)
+

Converts a datetime or timestamp to a type 1 uuid.UUID.

+
+
Parameters
+
    +
  • time_arg – The time to use for the timestamp portion of the UUID. +This can either be a datetime object or a timestamp +in seconds (as returned from time.time()).

  • +
  • node (long) – None integer for the UUID (up to 48 bits). If not specified, this +field is randomized.

  • +
  • clock_seq (int) – Clock sequence field for the UUID (up to 14 bits). If not specified, +a random sequence is generated.

  • +
+
+
Return type
+

uuid.UUID

+
+
+
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.25.11-scylla/api/index.html b/3.25.11-scylla/api/index.html new file mode 100644 index 0000000000..abd9c69e34 --- /dev/null +++ b/3.25.11-scylla/api/index.html @@ -0,0 +1,716 @@ + + + + + + + + + + + + + API Documentation | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

API Documentation

+
+

Core Driver

+ +
+
+

Object Mapper

+ +
+
+

DataStax Graph

+ +
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.25.11-scylla/cqlengine/batches.html b/3.25.11-scylla/cqlengine/batches.html new file mode 100644 index 0000000000..d7c872b7d9 --- /dev/null +++ b/3.25.11-scylla/cqlengine/batches.html @@ -0,0 +1,746 @@ + + + + + + + + + + + + + Batch Queries | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + + + +
+

Batch Queries

+

cqlengine supports batch queries using the BatchQuery class. Batch queries can be started and stopped manually, or within a context manager. To add queries to the batch object, you just need to precede the create/save/delete call with a call to batch, and pass in the batch object.

+
+

Batch Query General Use Pattern

+

You can only create, update, and delete rows with a batch query, attempting to read rows out of the database with a batch query will fail.

+
from cassandra.cqlengine.query import BatchQuery
+
+#using a context manager
+with BatchQuery() as b:
+    now = datetime.now()
+    em1 = ExampleModel.batch(b).create(example_type=0, description="1", created_at=now)
+    em2 = ExampleModel.batch(b).create(example_type=0, description="2", created_at=now)
+    em3 = ExampleModel.batch(b).create(example_type=0, description="3", created_at=now)
+
+# -- or --
+
+#manually
+b = BatchQuery()
+now = datetime.now()
+em1 = ExampleModel.batch(b).create(example_type=0, description="1", created_at=now)
+em2 = ExampleModel.batch(b).create(example_type=0, description="2", created_at=now)
+em3 = ExampleModel.batch(b).create(example_type=0, description="3", created_at=now)
+b.execute()
+
+# updating in a batch
+
+b = BatchQuery()
+em1.description = "new description"
+em1.batch(b).save()
+em2.description = "another new description"
+em2.batch(b).save()
+b.execute()
+
+# deleting in a batch
+b = BatchQuery()
+ExampleModel.objects(id=some_id).batch(b).delete()
+ExampleModel.objects(id=some_id2).batch(b).delete()
+b.execute()
+
+
+

Typically you will not want the block to execute if an exception occurs inside the with block. However, in the case that this is desirable, it’s achievable by using the following syntax:

+
with BatchQuery(execute_on_exception=True) as b:
+    LogEntry.batch(b).create(k=1, v=1)
+    mystery_function() # exception thrown in here
+    LogEntry.batch(b).create(k=1, v=2) # this code is never reached due to the exception, but anything leading up to here will execute in the batch.
+
+
+

If an exception is thrown somewhere in the block, any statements that have been added to the batch will still be executed. This is useful for some logging situations.

+
+
+

Batch Query Execution Callbacks

+

In order to allow secondary tasks to be chained to the end of batch, BatchQuery instances allow callbacks to be +registered with the batch, to be executed immediately after the batch executes.

+

Multiple callbacks can be attached to same BatchQuery instance, they are executed in the same order that they +are added to the batch.

+

The callbacks attached to a given batch instance are executed only if the batch executes. If the batch is used as a +context manager and an exception is raised, the queued up callbacks will not be run.

+
def my_callback(*args, **kwargs):
+    pass
+
+batch = BatchQuery()
+
+batch.add_callback(my_callback)
+batch.add_callback(my_callback, 'positional arg', named_arg='named arg value')
+
+# if you need reference to the batch within the callback,
+# just trap it in the arguments to be passed to the callback:
+batch.add_callback(my_callback, cqlengine_batch=batch)
+
+# once the batch executes...
+batch.execute()
+
+# the effect of the above scheduled callbacks will be similar to
+my_callback()
+my_callback('positional arg', named_arg='named arg value')
+my_callback(cqlengine_batch=batch)
+
+
+

Failure in any of the callbacks does not affect the batch’s execution, as the callbacks are started after the execution +of the batch is complete.

+
+

Logged vs Unlogged Batches

+

By default, queries in cqlengine are LOGGED, which carries additional overhead from UNLOGGED. To explicitly state which batch type to use, simply:

+
from cassandra.cqlengine.query import BatchType
+with BatchQuery(batch_type=BatchType.Unlogged) as b:
+    LogEntry.batch(b).create(k=1, v=1)
+    LogEntry.batch(b).create(k=1, v=2)
+
+
+
+
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.25.11-scylla/cqlengine/connections.html b/3.25.11-scylla/cqlengine/connections.html new file mode 100644 index 0000000000..22ba046ddb --- /dev/null +++ b/3.25.11-scylla/cqlengine/connections.html @@ -0,0 +1,770 @@ + + + + + + + + + + + + + Connections | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + + + +
+

Connections

+

Connections aim to ease the use of multiple sessions with cqlengine. Connections can be set on a model class, per query or using a context manager.

+
+

Register a new connection

+

To use cqlengine, you need at least a default connection. If you initialize cqlengine’s connections with with connection.setup, a connection will be created automatically. If you want to use another cluster/session, you need to register a new cqlengine connection. You register a connection with register_connection():

+
from cassandra.cqlengine import connection
+
+connection.setup(['127.0.0.1')
+connection.register_connection('cluster2', ['127.0.0.2'])
+
+
+

register_connection() can take a list of hosts, as shown above, in which case it will create a connection with a new session. It can also take a session argument if you’ve already created a session:

+
from cassandra.cqlengine import connection
+from cassandra.cluster import Cluster
+
+session = Cluster(['127.0.0.1']).connect()
+connection.register_connection('cluster3', session=session)
+
+
+
+
+

Change the default connection

+

You can change the default cqlengine connection on registration:

+
from cassandra.cqlengine import connection
+
+connection.register_connection('cluster2', ['127.0.0.2'] default=True)
+
+
+

or on the fly using set_default_connection()

+
connection.set_default_connection('cluster2')
+
+
+
+
+

Unregister a connection

+

You can unregister a connection using unregister_connection():

+
connection.unregister_connection('cluster2')
+
+
+
+
+

Management

+

When using multiples connections, you also need to sync your models on all connections (and keyspaces) that you need operate on. Management commands have been improved to ease this part. Here is an example:

+
from cassandra.cqlengine import management
+
+keyspaces = ['ks1', 'ks2']
+conns = ['cluster1', 'cluster2']
+
+# registers your connections
+# ...
+
+# create all keyspaces on all connections
+for ks in keyspaces:
+    management.create_simple_keyspace(ks, connections=conns)
+
+# define your Automobile model
+# ...
+
+# sync your models
+management.sync_table(Automobile, keyspaces=keyspaces, connections=conns)
+
+
+
+
+

Connection Selection

+

cqlengine will select the default connection, unless your specify a connection using one of the following methods.

+
+

Default Model Connection

+

You can specify a default connection per model:

+
class Automobile(Model):
+    __keyspace__ = 'test'
+    __connection__ = 'cluster2'
+    manufacturer = columns.Text(primary_key=True)
+    year = columns.Integer(primary_key=True)
+    model = columns.Text(primary_key=True)
+
+print len(Automobile.objects.all())  # executed on the connection 'cluster2'
+
+
+
+
+

QuerySet and model instance

+

You can use the using() method to select a connection (or keyspace):

+
Automobile.objects.using(connection='cluster1').create(manufacturer='honda', year=2010, model='civic')
+q = Automobile.objects.filter(manufacturer='Tesla')
+autos = q.using(keyspace='ks2', connection='cluster2').all()
+
+for auto in autos:
+    auto.using(connection='cluster1').save()
+
+
+
+
+

Context Manager

+

You can use the ContextQuery as well to select a connection:

+
with ContextQuery(Automobile, connection='cluster1') as A:
+    A.objects.filter(manufacturer='honda').all()  # executed on 'cluster1'
+
+
+
+
+

BatchQuery

+

With a BatchQuery, you can select the connection with the context manager. Note that all operations in the batch need to use the same connection.

+
with BatchQuery(connection='cluster1') as b:
+    Automobile.objects.batch(b).create(manufacturer='honda', year=2010, model='civic')
+
+
+
+
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.25.11-scylla/cqlengine/faq.html b/3.25.11-scylla/cqlengine/faq.html new file mode 100644 index 0000000000..f2af09247f --- /dev/null +++ b/3.25.11-scylla/cqlengine/faq.html @@ -0,0 +1,710 @@ + + + + + + + + + + + + + Frequently Asked Questions | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

Frequently Asked Questions

+
+

Why don’t updates work correctly on models instantiated as Model(field=value, field2=value2)?

+

The recommended way to create new rows is with the models .create method. The values passed into a model’s init method are interpreted by the model as the values as they were read from a row. This allows the model to “know” which rows have changed since the row was read out of cassandra, and create suitable update statements.

+
+
+

How to preserve ordering in batch query?

+

Statement Ordering is not supported by CQL3 batches. Therefore, +once cassandra needs resolving conflict(Updating the same column in one batch), +The algorithm below would be used.

+
    +
  • If timestamps are different, pick the column with the largest timestamp (the value being a regular column or a tombstone)

  • +
  • If timestamps are the same, and one of the columns in a tombstone (‘null’) - pick the tombstone

  • +
  • If timestamps are the same, and none of the columns are tombstones, pick the column with the largest value

  • +
+

Below is an example to show this scenario.

+
class MyMode(Model):
+    id    = columns.Integer(primary_key=True)
+    count = columns.Integer()
+    text  = columns.Text()
+
+with BatchQuery() as b:
+   MyModel.batch(b).create(id=1, count=2, text='123')
+   MyModel.batch(b).create(id=1, count=3, text='111')
+
+assert MyModel.objects(id=1).first().count == 3
+assert MyModel.objects(id=1).first().text  == '123'
+
+
+

The largest value of count is 3, and the largest value of text would be ‘123’.

+

The workaround is applying timestamp to each statement, then Cassandra would +resolve to the statement with the lastest timestamp.

+
with BatchQuery() as b:
+    MyModel.timestamp(datetime.now()).batch(b).create(id=1, count=2, text='123')
+    MyModel.timestamp(datetime.now()).batch(b).create(id=1, count=3, text='111')
+
+assert MyModel.objects(id=1).first().count == 3
+assert MyModel.objects(id=1).first().text  == '111'
+
+
+
+
+

How can I delete individual values from a row?

+

When inserting with CQLEngine, None is equivalent to CQL NULL or to +issuing a DELETE on that column. For example:

+
class MyModel(Model):
+    id    = columns.Integer(primary_key=True)
+    text  = columns.Text()
+
+m = MyModel.create(id=1, text='We can delete this with None')
+assert MyModel.objects(id=1).first().text is not None
+
+m.update(text=None)
+assert MyModel.objects(id=1).first().text is None
+
+
+
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.25.11-scylla/cqlengine/models.html b/3.25.11-scylla/cqlengine/models.html new file mode 100644 index 0000000000..f2f5a56f1d --- /dev/null +++ b/3.25.11-scylla/cqlengine/models.html @@ -0,0 +1,835 @@ + + + + + + + + + + + + + Models | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + + + +
+

Models

+

A model is a python class representing a CQL table. Models derive from Model, and +define basic table properties and columns for a table.

+

Columns in your models map to columns in your CQL table. You define CQL columns by defining column attributes on your model classes. +For a model to be valid it needs at least one primary key column and one non-primary key column. Just as in CQL, the order you define +your columns in is important, and is the same order they are defined in on a model’s corresponding table.

+

Some basic examples defining models are shown below. Consult the Model API docs and Column API docs for complete details.

+
+

Example Definitions

+

This example defines a Person table, with the columns first_name and last_name

+
from cassandra.cqlengine import columns
+from cassandra.cqlengine.models import Model
+
+ class Person(Model):
+     id = columns.UUID(primary_key=True)
+     first_name  = columns.Text()
+     last_name = columns.Text()
+
+
+

The Person model would create this CQL table:

+
CREATE TABLE cqlengine.person (
+    id uuid,
+    first_name text,
+    last_name text,
+    PRIMARY KEY (id)
+);
+
+
+

Here’s an example of a comment table created with clustering keys, in descending order:

+
from cassandra.cqlengine import columns
+from cassandra.cqlengine.models import Model
+
+class Comment(Model):
+    photo_id = columns.UUID(primary_key=True)
+    comment_id = columns.TimeUUID(primary_key=True, clustering_order="DESC")
+    comment = columns.Text()
+
+
+

The Comment model’s create table would look like the following:

+
CREATE TABLE comment (
+  photo_id uuid,
+  comment_id timeuuid,
+  comment text,
+  PRIMARY KEY (photo_id, comment_id)
+) WITH CLUSTERING ORDER BY (comment_id DESC);
+
+
+

To sync the models to the database, you may do the following*:

+
from cassandra.cqlengine.management import sync_table
+sync_table(Person)
+sync_table(Comment)
+
+
+

*Note: synchronizing models causes schema changes, and should be done with caution. +Please see the discussion in cassandra.cqlengine.management - Schema management for cqlengine for considerations.

+

For examples on manipulating data and creating queries, see Making Queries

+
+
+

Manipulating model instances as dictionaries

+

Model instances can be accessed like dictionaries.

+
class Person(Model):
+    first_name  = columns.Text()
+    last_name = columns.Text()
+
+kevin = Person.create(first_name="Kevin", last_name="Deldycke")
+dict(kevin)  # returns {'first_name': 'Kevin', 'last_name': 'Deldycke'}
+kevin['first_name']  # returns 'Kevin'
+kevin.keys()  # returns ['first_name', 'last_name']
+kevin.values()  # returns ['Kevin', 'Deldycke']
+kevin.items()  # returns [('first_name', 'Kevin'), ('last_name', 'Deldycke')]
+
+kevin['first_name'] = 'KEVIN5000'  # changes the models first name
+
+
+
+
+

Extending Model Validation

+

Each time you save a model instance in cqlengine, the data in the model is validated against the schema you’ve defined +for your model. Most of the validation is fairly straightforward, it basically checks that you’re not trying to do +something like save text into an integer column, and it enforces the required flag set on column definitions. +It also performs any transformations needed to save the data properly.

+

However, there are often additional constraints or transformations you want to impose on your data, beyond simply +making sure that Cassandra won’t complain when you try to insert it. To define additional validation on a model, +extend the model’s validation method:

+
class Member(Model):
+    person_id = UUID(primary_key=True)
+    name = Text(required=True)
+
+    def validate(self):
+        super(Member, self).validate()
+        if self.name == 'jon':
+            raise ValidationError('no jon\'s allowed')
+
+
+

Note: while not required, the convention is to raise a ValidationError (from cassandra.cqlengine import ValidationError) +if validation fails.

+
+
+

Model Inheritance

+

It is possible to save and load different model classes using a single CQL table. +This is useful in situations where you have different object types that you want to store in a single cassandra row.

+

For instance, suppose you want a table that stores rows of pets owned by an owner:

+
class Pet(Model):
+    __table_name__ = 'pet'
+    owner_id = UUID(primary_key=True)
+    pet_id = UUID(primary_key=True)
+    pet_type = Text(discriminator_column=True)
+    name = Text()
+
+    def eat(self, food):
+        pass
+
+    def sleep(self, time):
+        pass
+
+class Cat(Pet):
+    __discriminator_value__ = 'cat'
+    cuteness = Float()
+
+    def tear_up_couch(self):
+        pass
+
+class Dog(Pet):
+    __discriminator_value__ = 'dog'
+    fierceness = Float()
+
+    def bark_all_night(self):
+        pass
+
+
+

After calling sync_table on each of these tables, the columns defined in each model will be added to the +pet table. Additionally, saving Cat and Dog models will save the meta data needed to identify each row +as either a cat or dog.

+

To setup a model structure with inheritance, follow these steps

+
    +
  1. Create a base model with a column set as the distriminator (distriminator_column=True in the column definition)

  2. +
  3. Create subclass models, and define a unique __discriminator_value__ value on each

  4. +
  5. Run sync_table on each of the sub tables

  6. +
+

About the discriminator value

+

The discriminator value is what cqlengine uses under the covers to map logical cql rows to the appropriate model type. The +base model maintains a map of discriminator values to subclasses. When a specialized model is saved, its discriminator value is +automatically saved into the discriminator column. The discriminator column may be any column type except counter and container types. +Additionally, if you set index=True on your discriminator column, you can execute queries against specialized subclasses, and a +WHERE clause will be automatically added to your query, returning only rows of that type. Note that you must +define a unique __discriminator_value__ to each subclass, and that you can only assign a single discriminator column per model.

+
+
+

User Defined Types

+

cqlengine models User Defined Types (UDTs) much like tables, with fields defined by column type attributes. However, UDT instances +are only created, presisted, and queried via table Models. A short example to introduce the pattern:

+
from cassandra.cqlengine.columns import *
+from cassandra.cqlengine.models import Model
+from cassandra.cqlengine.usertype import UserType
+
+class address(UserType):
+    street = Text()
+    zipcode = Integer()
+
+class users(Model):
+    __keyspace__ = 'account'
+    name = Text(primary_key=True)
+    addr = UserDefinedType(address)
+
+users.create(name="Joe", addr=address(street="Easy St.", zipcode=99999))
+user = users.objects(name="Joe")[0]
+print user.name, user.addr
+# Joe address(street=u'Easy St.', zipcode=99999)
+
+
+

UDTs are modeled by inheriting UserType, and setting column type attributes. Types are then used in defining +models by declaring a column of type UserDefinedType, with the UserType class as a parameter.

+

sync_table will implicitly +synchronize any types contained in the table. Alternatively sync_type() can be used to create/alter types +explicitly.

+

Upon declaration, types are automatically registered with the driver, so query results return instances of your UserType +class*.

+

*Note: UDTs were not added to the native protocol until v3. When setting up the cqlengine connection, be sure to specify +protocol_version=3. If using an earlier version, UDT queries will still work, but the returned type will be a namedtuple.

+
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.25.11-scylla/cqlengine/queryset.html b/3.25.11-scylla/cqlengine/queryset.html new file mode 100644 index 0000000000..49b668b0fa --- /dev/null +++ b/3.25.11-scylla/cqlengine/queryset.html @@ -0,0 +1,1007 @@ + + + + + + + + + + + + + Making Queries | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

Making Queries

+
+

Retrieving objects

+

Once you’ve populated Cassandra with data, you’ll probably want to retrieve some of it. This is accomplished with QuerySet objects. This section will describe how to use QuerySet objects to retrieve the data you’re looking for.

+
+

Retrieving all objects

+

The simplest query you can make is to return all objects from a table.

+

This is accomplished with the .all() method, which returns a QuerySet of all objects in a table

+

Using the Person example model, we would get all Person objects like this:

+
all_objects = Person.objects.all()
+
+
+
+
+

Retrieving objects with filters

+

Typically, you’ll want to query only a subset of the records in your database.

+

That can be accomplished with the QuerySet’s .filter(\*\*) method.

+

For example, given the model definition:

+
class Automobile(Model):
+    manufacturer = columns.Text(primary_key=True)
+    year = columns.Integer(primary_key=True)
+    model = columns.Text()
+    price = columns.Decimal()
+    options = columns.Set(columns.Text)
+
+
+

…and assuming the Automobile table contains a record of every car model manufactured in the last 20 years or so, we can retrieve only the cars made by a single manufacturer like this:

+
q = Automobile.objects.filter(manufacturer='Tesla')
+
+
+

You can also use the more convenient syntax:

+
q = Automobile.objects(Automobile.manufacturer == 'Tesla')
+
+
+

We can then further filter our query with another call to .filter

+
q = q.filter(year=2012)
+
+
+

Note: all queries involving any filtering MUST define either an ‘=’ or an ‘in’ relation to either a primary key column, or an indexed column.

+
+
+
+

Accessing objects in a QuerySet

+

There are several methods for getting objects out of a queryset

+
    +
  • +
    iterating over the queryset
    for car in Automobile.objects.all():
    +    #...do something to the car instance
    +    pass
    +
    +
    +
    +
    +
  • +
  • +
    list index
    q = Automobile.objects.all()
    +q[0] #returns the first result
    +q[1] #returns the second result
    +
    +
    +
    +

    Note

    +
      +
    • CQL does not support specifying a start position in it’s queries. Therefore, accessing elements using array indexing will load every result up to the index value requested

    • +
    • Using negative indices requires a “SELECT COUNT()” to be executed. This has a performance cost on large datasets.

    • +
    +
    +
    +
    +
  • +
  • +
    list slicing
    q = Automobile.objects.all()
    +q[1:] #returns all results except the first
    +q[1:9] #returns a slice of the results
    +
    +
    +
    +

    Note

    +
      +
    • CQL does not support specifying a start position in it’s queries. Therefore, accessing elements using array slicing will load every result up to the index value requested

    • +
    • Using negative indices requires a “SELECT COUNT()” to be executed. This has a performance cost on large datasets.

    • +
    +
    +
    +
    +
  • +
  • +
    calling get() on the queryset
    q = Automobile.objects.filter(manufacturer='Tesla')
    +q = q.filter(year=2012)
    +car = q.get()
    +
    +
    +

    this returns the object matching the queryset

    +
    +
    +
  • +
  • +
    calling first() on the queryset
    q = Automobile.objects.filter(manufacturer='Tesla')
    +q = q.filter(year=2012)
    +car = q.first()
    +
    +
    +

    this returns the first value in the queryset

    +
    +
    +
  • +
+
+
+

Filtering Operators

+

Equal To

+

The default filtering operator.

+
q = Automobile.objects.filter(manufacturer='Tesla')
+q = q.filter(year=2012)  #year == 2012
+
+
+

In addition to simple equal to queries, cqlengine also supports querying with other operators by appending a __<op> to the field name on the filtering call

+

in (__in)

+
q = Automobile.objects.filter(manufacturer='Tesla')
+q = q.filter(year__in=[2011, 2012])
+
+
+

> (__gt)

+
q = Automobile.objects.filter(manufacturer='Tesla')
+q = q.filter(year__gt=2010)  # year > 2010
+
+# or the nicer syntax
+
+q.filter(Automobile.year > 2010)
+
+
+

>= (__gte)

+
q = Automobile.objects.filter(manufacturer='Tesla')
+q = q.filter(year__gte=2010)  # year >= 2010
+
+# or the nicer syntax
+
+q.filter(Automobile.year >= 2010)
+
+
+

< (__lt)

+
q = Automobile.objects.filter(manufacturer='Tesla')
+q = q.filter(year__lt=2012)  # year < 2012
+
+# or...
+
+q.filter(Automobile.year < 2012)
+
+
+

<= (__lte)

+
q = Automobile.objects.filter(manufacturer='Tesla')
+q = q.filter(year__lte=2012)  # year <= 2012
+
+q.filter(Automobile.year <= 2012)
+
+
+

CONTAINS (__contains)

+

The CONTAINS operator is available for all collection types (List, Set, Map).

+
q = Automobile.objects.filter(manufacturer='Tesla')
+q.filter(options__contains='backup camera').allow_filtering()
+
+
+

Note that we need to use allow_filtering() since the options column has no secondary index.

+

LIKE (__like)

+

The LIKE operator is available for text columns that have a SASI secondary index.

+
q = Automobile.objects.filter(model__like='%Civic%').allow_filtering()
+
+
+

IS NOT NULL (IsNotNull(column_name))

+

The IS NOT NULL operator is not yet supported for C*.

+
q = Automobile.objects.filter(IsNotNull('model'))
+
+
+

Limitations:

+
    +
  • Currently, cqlengine does not support SASI index creation. To use this feature, you need to create the SASI index using the core driver.

  • +
  • Queries using LIKE must use allow_filtering() since the model column has no standard secondary index. Note that the server will use the SASI index properly when executing the query.

  • +
+
+
+

TimeUUID Functions

+

In addition to querying using regular values, there are two functions you can pass in when querying TimeUUID columns to help make filtering by them easier. Note that these functions don’t actually return a value, but instruct the cql interpreter to use the functions in it’s query.

+
+
+class cqlengine.queryset.MinTimeUUID(datetime)
+

returns the minimum time uuid value possible for the given datetime

+
+ +
+
+class cqlengine.queryset.MaxTimeUUID(datetime)
+

returns the maximum time uuid value possible for the given datetime

+
+ +

Example

+
class DataStream(Model):
+    id      = columns.UUID(partition_key=True)
+    time    = columns.TimeUUID(primary_key=True)
+    data    = columns.Bytes()
+
+min_time = datetime(1982, 1, 1)
+max_time = datetime(1982, 3, 9)
+
+DataStream.filter(time__gt=functions.MinTimeUUID(min_time), time__lt=functions.MaxTimeUUID(max_time))
+
+
+
+
+

Token Function

+

Token functon may be used only on special, virtual column pk__token, representing token of partition key (it also works for composite partition keys). +Cassandra orders returned items by value of partition key token, so using cqlengine.Token we can easy paginate through all table rows.

+

See http://cassandra.apache.org/doc/cql3/CQL-3.0.html#tokenFun

+

Example

+
class Items(Model):
+    id      = columns.Text(primary_key=True)
+    data    = columns.Bytes()
+
+query = Items.objects.all().limit(10)
+
+first_page = list(query);
+last = first_page[-1]
+next_page = list(query.filter(pk__token__gt=cqlengine.Token(last.pk)))
+
+
+
+
+

QuerySets are immutable

+

When calling any method that changes a queryset, the method does not actually change the queryset object it’s called on, but returns a new queryset object with the attributes of the original queryset, plus the attributes added in the method call.

+

Example

+
#this produces 3 different querysets
+#q does not change after it's initial definition
+q = Automobiles.objects.filter(year=2012)
+tesla2012 = q.filter(manufacturer='Tesla')
+honda2012 = q.filter(manufacturer='Honda')
+
+
+
+
+

Ordering QuerySets

+

Since Cassandra is essentially a distributed hash table on steroids, the order you get records back in will not be particularly predictable.

+

However, you can set a column to order on with the .order_by(column_name) method.

+

Example

+
#sort ascending
+q = Automobiles.objects.all().order_by('year')
+#sort descending
+q = Automobiles.objects.all().order_by('-year')
+
+
+

Note: Cassandra only supports ordering on a clustering key. In other words, to support ordering results, your model must have more than one primary key, and you must order on a primary key, excluding the first one.

+

For instance, given our Automobile model, year is the only column we can order on.

+
+
+

Values Lists

+

There is a special QuerySet’s method .values_list() - when called, QuerySet returns lists of values instead of model instances. It may significantly speedup things with lower memory footprint for large responses. +Each tuple contains the value from the respective field passed into the values_list() call — so the first item is the first field, etc. For example:

+
items = list(range(20))
+random.shuffle(items)
+for i in items:
+    TestModel.create(id=1, clustering_key=i)
+
+values = list(TestModel.objects.values_list('clustering_key', flat=True))
+# [19L, 18L, 17L, 16L, 15L, 14L, 13L, 12L, 11L, 10L, 9L, 8L, 7L, 6L, 5L, 4L, 3L, 2L, 1L, 0L]
+
+
+
+
+

Per Query Timeouts

+

By default all queries are executed with the timeout defined in ~cqlengine.connection.setup() +The examples below show how to specify a per-query timeout. +A timeout is specified in seconds and can be an int, float or None. +None means no timeout.

+
class Row(Model):
+    id = columns.Integer(primary_key=True)
+    name = columns.Text()
+
+
+

Fetch all objects with a timeout of 5 seconds

+
Row.objects().timeout(5).all()
+
+
+

Create a single row with a 50ms timeout

+
Row(id=1, name='Jon').timeout(0.05).create()
+
+
+

Delete a single row with no timeout

+
Row(id=1).timeout(None).delete()
+
+
+

Update a single row with no timeout

+
Row(id=1).timeout(None).update(name='Blake')
+
+
+

Batch query timeouts

+
with BatchQuery(timeout=10) as b:
+    Row(id=1, name='Jon').create()
+
+
+

NOTE: You cannot set both timeout and batch at the same time, batch will use the timeout defined in it’s constructor. +Setting the timeout on the model is meaningless and will raise an AssertionError.

+
+
+

Default TTL and Per Query TTL

+

Model default TTL now relies on the default_time_to_live feature, introduced in Cassandra 2.0. It is not handled anymore in the CQLEngine Model (scylla-driver >=3.6). You can set the default TTL of a table like this:

+

Example:

+
class User(Model):
+    __options__ = {'default_time_to_live': 20}
+
+    user_id = columns.UUID(primary_key=True)
+    ...
+
+
+

You can set TTL per-query if needed. Here are a some examples:

+

Example:

+
class User(Model):
+    __options__ = {'default_time_to_live': 20}
+
+    user_id = columns.UUID(primary_key=True)
+    ...
+
+user = User.objects.create(user_id=1)  # Default TTL 20 will be set automatically on the server
+
+user.ttl(30).update(age=21)            # Update the TTL to 30
+User.objects.ttl(10).create(user_id=1)  # TTL 10
+User(user_id=1, age=21).ttl(10).save()  # TTL 10
+
+
+
+
+

Named Tables

+

Named tables are a way of querying a table without creating an class. They’re useful for querying system tables or exploring an unfamiliar database.

+
from cassandra.cqlengine.connection import setup
+setup("127.0.0.1", "cqlengine_test")
+
+from cassandra.cqlengine.named import NamedTable
+user = NamedTable("cqlengine_test", "user")
+user.objects()
+user.objects()[0]
+
+# {u'pk': 1, u't': datetime.datetime(2014, 6, 26, 17, 10, 31, 774000)}
+
+
+
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.25.11-scylla/cqlengine/third_party.html b/3.25.11-scylla/cqlengine/third_party.html new file mode 100644 index 0000000000..2b1a3990f1 --- /dev/null +++ b/3.25.11-scylla/cqlengine/third_party.html @@ -0,0 +1,707 @@ + + + + + + + + + + + + + Third party integrations | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

Third party integrations

+
+

Celery

+

Here’s how, in substance, CQLengine can be plugged to Celery:

+
from celery import Celery
+from celery.signals import worker_process_init, beat_init
+from cassandra.cqlengine import connection
+from cassandra.cqlengine.connection import (
+    cluster as cql_cluster, session as cql_session)
+
+def cassandra_init(**kwargs):
+    """ Initialize a clean Cassandra connection. """
+    if cql_cluster is not None:
+        cql_cluster.shutdown()
+    if cql_session is not None:
+        cql_session.shutdown()
+    connection.setup()
+
+# Initialize worker context for both standard and periodic tasks.
+worker_process_init.connect(cassandra_init)
+beat_init.connect(cassandra_init)
+
+app = Celery()
+
+
+
+
+

uWSGI

+

This is the code required for proper connection handling of CQLengine for a +uWSGI-run application:

+
from cassandra.cqlengine import connection
+from cassandra.cqlengine.connection import (
+    cluster as cql_cluster, session as cql_session)
+
+try:
+    from uwsgidecorators import postfork
+except ImportError:
+    # We're not in a uWSGI context, no need to hook Cassandra session
+    # initialization to the postfork event.
+    pass
+else:
+    @postfork
+    def cassandra_init(**kwargs):
+        """ Initialize a new Cassandra session in the context.
+
+        Ensures that a new session is returned for every new request.
+        """
+        if cql_cluster is not None:
+            cql_cluster.shutdown()
+        if cql_session is not None:
+            cql_session.shutdown()
+        connection.setup()
+
+
+
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.25.11-scylla/cqlengine/upgrade_guide.html b/3.25.11-scylla/cqlengine/upgrade_guide.html new file mode 100644 index 0000000000..0197171d5d --- /dev/null +++ b/3.25.11-scylla/cqlengine/upgrade_guide.html @@ -0,0 +1,839 @@ + + + + + + + + + + + + + Upgrade Guide | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + + + +
+

Upgrade Guide

+

This is an overview of things that changed as the cqlengine project was merged into +scylla-driver. While efforts were taken to preserve the API and most functionality exactly, +conversion to this package will still require certain minimal updates (namely, imports).

+

THERE IS ONE FUNCTIONAL CHANGE, described in the first section below.

+
+

Functional Changes

+
+

List Prepend Reversing

+

Legacy cqlengine included a workaround for a Cassandra bug in which prepended list segments were +reversed (CASSANDRA-8733). As of +this integration, this workaround is removed. The first released integrated version emits +a warning when prepend is used. Subsequent versions will have this warning removed.

+
+
+

Date Column Type

+

The Date column type in legacy cqlengine used a timestamp CQL type and truncated the time. +Going forward, the Date type represents a date for Cassandra 2.2+ +(PYTHON-245). +Users of the legacy functionality should convert models to use DateTime (which +uses timestamp internally), and use the build-in datetime.date for input values.

+
+
+
+

Remove cqlengine

+

To avoid confusion or mistakes using the legacy package in your application, it +is prudent to remove the cqlengine package when upgrading to the integrated version.

+

The driver setup script will warn if the legacy package is detected during install, +but it will not prevent side-by-side installation.

+
+
+

Organization

+
+

Imports

+

cqlengine is now integrated as a sub-package of the driver base package ‘cassandra’. +Upgrading will require adjusting imports to cqlengine. For example:

+
from cassandra.cqlengine import columns
+
+
+

is now:

+
from cassandra.cqlengine import columns
+
+
+
+
+

Package-Level Aliases

+

Legacy cqlengine defined a number of aliases at the package level, which became redundant +when the package was integrated for a driver. These have been removed in favor of absolute +imports, and referring to cannonical definitions. For example, cqlengine.ONE was an alias +of cassandra.ConsistencyLevel.ONE. In the integrated package, only the +cassandra.ConsistencyLevel remains.

+

Additionally, submodule aliases are removed from cqlengine in favor of absolute imports.

+

These aliases are removed, and not deprecated because they should be straightforward to iron out +at module load time.

+
+
+

Exceptions

+

The legacy cqlengine.exceptions module had a number of Exception classes that were variously +common to the package, or only used in specific modules. Common exceptions were relocated to +cqlengine, and specialized exceptions were placed in the module that raises them. Below is a +listing of updated locations:

+ ++++ + + + + + + + + + + + + + + + + + + + + + + + + + +

Exception class

New module

CQLEngineException

cassandra.cqlengine

ModelException

cassandra.cqlengine.models

ValidationError

cassandra.cqlengine

UndefinedKeyspaceException

cassandra.cqlengine.connection

LWTException

cassandra.cqlengine.query

IfNotExistsWithCounterColumn

cassandra.cqlengine.query

+
+
+

UnicodeMixin Consolidation

+

class UnicodeMixin was defined in several cqlengine modules. This has been consolidated +to a single definition in the cqlengine package init file. This is not technically part of +the API, but noted here for completeness.

+
+
+
+

API Deprecations

+

This upgrade served as a good juncture to deprecate certain API features and invite users to upgrade +to new ones. The first released version does not change functionality – only introduces deprecation +warnings. Future releases will remove these features in favor of the alternatives.

+
+

Float/Double Overload

+

Previously there was no Double column type. Doubles were modeled by specifying Float(double_precision=True). +This inititializer parameter is now deprecated. Applications should use Double for CQL double, and Float +for CQL float.

+
+
+

Schema Management

+

cassandra.cqlengine.management.create_keyspace is deprecated. Instead, use the new replication-strategy-specific +functions that accept explicit options for known strategies:

+ +

cassandra.cqlengine.management.delete_keyspace is deprecated in favor of a new function, drop_keyspace(). The +intent is simply to make the function match the CQL verb it invokes.

+
+
+

Model Inheritance

+

The names for class attributes controlling model inheritance are changing. Changes are as follows:

+ +

The functionality is unchanged – the intent here is to make the names and language around these attributes more precise. +For now, the old names are just deprecated, and the mapper will emit warnings if they are used. The old names +will be removed in a future version.

+

The example below shows a simple translation:

+

Before:

+
class Pet(Model):
+    __table_name__ = 'pet'
+    owner_id = UUID(primary_key=True)
+    pet_id = UUID(primary_key=True)
+    pet_type = Text(polymorphic_key=True)
+    name = Text()
+
+class Cat(Pet):
+    __polymorphic_key__ = 'cat'
+
+class Dog(Pet):
+    __polymorphic_key__ = 'dog'
+
+
+

After:

+
class Pet(models.Model):
+    __table_name__ = 'pet'
+    owner_id = UUID(primary_key=True)
+    pet_id = UUID(primary_key=True)
+    pet_type = Text(discriminator_column=True)
+    name = Text()
+
+class Cat(Pet):
+    __discriminator_value__ = 'cat'
+
+class Dog(Pet):
+    __discriminator_value__ = 'dog'
+
+
+
+
+

TimeUUID.from_datetime

+

This function is deprecated in favor of the core utility function uuid_from_time().

+
+
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.25.11-scylla/dates_and_times.html b/3.25.11-scylla/dates_and_times.html new file mode 100644 index 0000000000..0607710949 --- /dev/null +++ b/3.25.11-scylla/dates_and_times.html @@ -0,0 +1,731 @@ + + + + + + + + + + + + + Working with Dates and Times | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

Working with Dates and Times

+

This document is meant to provide on overview of the assumptions and limitations of the driver time handling, the +reasoning behind it, and describe approaches to working with these types.

+
+

timestamps (Cassandra DateType)

+

Timestamps in Cassandra are timezone-naive timestamps encoded as millseconds since UNIX epoch. Clients working with +timestamps in this database usually find it easiest to reason about them if they are always assumed to be UTC. To quote the +pytz documentation, “The preferred way of dealing with times is to always work in UTC, converting to localtime only when +generating output to be read by humans.” The driver adheres to this tenant, and assumes UTC is always in the database. The +driver attempts to make this correct on the way in, and assumes no timezone on the way out.

+
+

Write Path

+

When inserting timestamps, the driver handles serialization for the write path as follows:

+

If the input is a datetime.datetime, the serialization is normalized by starting with the utctimetuple() of the +value.

+
    +
  • If the datetime object is timezone-aware, the timestamp is shifted, and represents the UTC timestamp equivalent.

  • +
  • If the datetime object is timezone-naive, this results in no shift – any datetime with no timezone information is assumed to be UTC

  • +
+

Note the second point above applies even to “local” times created using now():

+
>>> d = datetime.now()
+
+>>> print(d.tzinfo)
+None
+
+
+

These do not contain timezone information intrinsically, so they will be assumed to be UTC and not shifted. When generating +timestamps in the application, it is clearer to use datetime.utcnow() to be explicit about it.

+

If the input for a timestamp is numeric, it is assumed to be a epoch-relative millisecond timestamp, as specified in the +CQL spec – no scaling or conversion is done.

+
+
+

Read Path

+

The driver always assumes persisted timestamps are UTC and makes no attempt to localize them. Returned values are +timezone-naive datetime.datetime. We follow this approach because the datetime API has deficiencies around daylight +saving time, and the defacto package for handling this is a third-party package (we try to minimize external dependencies +and not make decisions for the integrator).

+

The decision for how to handle timezones is left to the application. For the most part it is straightforward to apply +localization to the datetimes returned by queries. One prevalent method is to use pytz for localization:

+
import pytz
+user_tz = pytz.timezone('US/Central')
+timestamp_naive = row.ts
+timestamp_utc = pytz.utc.localize(timestamp_naive)
+timestamp_presented = timestamp_utc.astimezone(user_tz)
+
+
+

This is the most robust approach (likely refactored into a function). If it is deemed too cumbersome to apply for all call +sites in the application, it is possible to patch the driver with custom deserialization for this type. However, doing +this depends depends some on internal APIs and what extensions are present, so we will only mention the possibility, and +not spell it out here.

+
+
+
+

date, time (Cassandra DateType)

+

Date and time in Cassandra are idealized markers, much like datetime.date and datetime.time in the Python standard +library. Unlike these Python implementations, the Cassandra encoding supports much wider ranges. To accommodate these +ranges without overflow, this driver returns these data in custom types: util.Date and util.Time.

+
+

Write Path

+

For simple (not prepared) statements, the input values for each of these can be either a string literal or an encoded +integer. See Working with dates +or Working with time for details +on the encoding or string formats.

+

For prepared statements, the driver accepts anything that can be used to construct the util.Date or +util.Time classes. See the linked API docs for details.

+
+
+

Read Path

+

The driver always returns custom types for date and time.

+

The driver returns util.Date for date in order to accommodate the wider range of values without overflow. +For applications working within the supported range of [datetime.MINYEAR, datetime.MAXYEAR], these are easily +converted to standard datetime.date insances using Date.date().

+

The driver returns util.Time for time in order to retain nanosecond precision stored in the database. +For applications not concerned with this level of precision, these are easily converted to standard datetime.time +insances using Time.time().

+
+
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.25.11-scylla/execution_profiles.html b/3.25.11-scylla/execution_profiles.html new file mode 100644 index 0000000000..b416c2571d --- /dev/null +++ b/3.25.11-scylla/execution_profiles.html @@ -0,0 +1,775 @@ + + + + + + + + + + + + + Execution Profiles | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

Execution Profiles

+

Execution profiles aim at making it easier to execute requests in different ways within +a single connected Session. Execution profiles are being introduced to deal with the exploding number of +configuration options, especially as the database platform evolves more complex workloads.

+

The legacy configuration remains intact, but legacy and Execution Profile APIs +cannot be used simultaneously on the same client Cluster. Legacy configuration +will be removed in the next major release (4.0).

+

An execution profile and its parameters should be unique across Cluster instances. +For example, an execution profile and its LoadBalancingPolicy should +not be applied to more than one Cluster instance.

+

This document explains how Execution Profiles relate to existing settings, and shows how to use the new profiles for +request execution.

+
+

Mapping Legacy Parameters to Profiles

+

Execution profiles can inherit from cluster.ExecutionProfile, and currently provide the following options, +previously input from the noted attributes:

+ +

When using the new API, these parameters can be defined by instances of cluster.ExecutionProfile.

+
+
+

Using Execution Profiles

+
+

Default

+
from cassandra.cluster import Cluster
+cluster = Cluster()
+session = cluster.connect()
+local_query = 'SELECT rpc_address FROM system.local'
+for _ in cluster.metadata.all_hosts():
+    print session.execute(local_query)[0]
+
+
+
Row(rpc_address='127.0.0.2')
+Row(rpc_address='127.0.0.1')
+
+
+

The default execution profile is built from Cluster parameters and default Session attributes. This profile matches existing default +parameters.

+
+
+

Initializing cluster with profiles

+
from cassandra.cluster import ExecutionProfile
+from cassandra.policies import WhiteListRoundRobinPolicy
+
+node1_profile = ExecutionProfile(load_balancing_policy=WhiteListRoundRobinPolicy(['127.0.0.1']))
+node2_profile = ExecutionProfile(load_balancing_policy=WhiteListRoundRobinPolicy(['127.0.0.2']))
+
+profiles = {'node1': node1_profile, 'node2': node2_profile}
+session = Cluster(execution_profiles=profiles).connect()
+for _ in cluster.metadata.all_hosts():
+    print session.execute(local_query, execution_profile='node1')[0]
+
+
+
Row(rpc_address='127.0.0.1')
+Row(rpc_address='127.0.0.1')
+
+
+
for _ in cluster.metadata.all_hosts():
+    print session.execute(local_query, execution_profile='node2')[0]
+
+
+
Row(rpc_address='127.0.0.2')
+Row(rpc_address='127.0.0.2')
+
+
+
for _ in cluster.metadata.all_hosts():
+    print session.execute(local_query)[0]
+
+
+
Row(rpc_address='127.0.0.2')
+Row(rpc_address='127.0.0.1')
+
+
+

Note that, even when custom profiles are injected, the default TokenAwarePolicy(DCAwareRoundRobinPolicy()) is still +present. To override the default, specify a policy with the EXEC_PROFILE_DEFAULT key.

+
from cassandra.cluster import EXEC_PROFILE_DEFAULT
+profile = ExecutionProfile(request_timeout=30)
+cluster = Cluster(execution_profiles={EXEC_PROFILE_DEFAULT: profile})
+
+
+
+
+

Adding named profiles

+

New profiles can be added constructing from scratch, or deriving from default:

+
locked_execution = ExecutionProfile(load_balancing_policy=WhiteListRoundRobinPolicy(['127.0.0.1']))
+node1_profile = 'node1_whitelist'
+cluster.add_execution_profile(node1_profile, locked_execution)
+
+for _ in cluster.metadata.all_hosts():
+    print session.execute(local_query, execution_profile=node1_profile)[0]
+
+
+
Row(rpc_address='127.0.0.1')
+Row(rpc_address='127.0.0.1')
+
+
+

See Cluster.add_execution_profile() for details and optional parameters.

+
+
+

Passing a profile instance without mapping

+

We also have the ability to pass profile instances to be used for execution, but not added to the mapping:

+
from cassandra.query import tuple_factory
+
+tmp = session.execution_profile_clone_update('node1', request_timeout=100, row_factory=tuple_factory)
+
+print session.execute(local_query, execution_profile=tmp)[0]
+print session.execute(local_query, execution_profile='node1')[0]
+
+
+
('127.0.0.1',)
+Row(rpc_address='127.0.0.1')
+
+
+

The new profile is a shallow copy, so the tmp profile shares a load balancing policy with one managed by the cluster. +If reference objects are to be updated in the clone, one would typically set those attributes to a new instance.

+
+
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.25.11-scylla/faq.html b/3.25.11-scylla/faq.html new file mode 100644 index 0000000000..dde53b71b4 --- /dev/null +++ b/3.25.11-scylla/faq.html @@ -0,0 +1,711 @@ + + + + + + + + + + + + + Frequently Asked Questions | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

Frequently Asked Questions

+

See also cqlengine FAQ

+
+

Why do connections or IO operations timeout in my WSGI application?

+

Depending on your application process model, it may be forking after driver Session is created. Most IO reactors do not handle this, and problems will manifest as timeouts.

+

To avoid this, make sure to create sessions per process, after the fork. Using uWSGI and Flask for example:

+
from flask import Flask
+from uwsgidecorators import postfork
+from cassandra.cluster import Cluster
+
+session = None
+prepared = None
+
+@postfork
+def connect():
+    global session, prepared
+    session = Cluster().connect()
+    prepared = session.prepare("SELECT release_version FROM system.local WHERE key=?")
+
+app = Flask(__name__)
+
+@app.route('/')
+def server_version():
+    row = session.execute(prepared, ('local',))[0]
+    return row.release_version
+
+
+

uWSGI provides a postfork hook you can use to create sessions and prepared statements after the child process forks.

+
+
+

How do I trace a request?

+

Request tracing can be turned on for any request by setting trace=True in Session.execute_async(). View the results by waiting on the future, then ResponseFuture.get_query_trace(). +Since tracing is done asynchronously to the request, this method polls until the trace is complete before querying data.

+
>>> future = session.execute_async("SELECT * FROM system.local", trace=True)
+>>> result = future.result()
+>>> trace = future.get_query_trace()
+>>> for e in trace.events:
+>>>     print e.source_elapsed, e.description
+
+0:00:00.000077 Parsing select * from system.local
+0:00:00.000153 Preparing statement
+0:00:00.000309 Computing ranges to query
+0:00:00.000368 Submitting range requests on 1 ranges with a concurrency of 1 (279.77142 rows per range expected)
+0:00:00.000422 Submitted 1 concurrent range requests covering 1 ranges
+0:00:00.000480 Executing seq scan across 1 sstables for (min(-9223372036854775808), min(-9223372036854775808))
+0:00:00.000669 Read 1 live and 0 tombstone cells
+0:00:00.000755 Scanned 1 rows and matched 1
+
+
+

trace is a QueryTrace object.

+
+
+

How do I determine the replicas for a query?

+

With prepared statements, the replicas are obtained by routing_key, based on current cluster token metadata:

+
>>> prepared = session.prepare("SELECT * FROM example.t WHERE key=?")
+>>> bound = prepared.bind((1,))
+>>> replicas = cluster.metadata.get_replicas(bound.keyspace, bound.routing_key)
+>>> for h in replicas:
+>>>   print h.address
+127.0.0.1
+127.0.0.2
+
+
+

replicas is a list of Host objects.

+
+
+

How does the driver manage request retries?

+

By default, retries are managed by the Cluster.default_retry_policy set on the session Cluster. It can also +be specialized per statement by setting Statement.retry_policy.

+

Retries are presently attempted on the same coordinator, but this may change in the future.

+

Please see policies.RetryPolicy for further details.

+
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.25.11-scylla/getting_started.html b/3.25.11-scylla/getting_started.html new file mode 100644 index 0000000000..4b946ead5e --- /dev/null +++ b/3.25.11-scylla/getting_started.html @@ -0,0 +1,1126 @@ + + + + + + + + + + + + + Getting Started | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

Getting Started

+

First, make sure you have the driver properly installed.

+
+

Connecting to a Cluster

+

Before we can start executing any queries against a Cassandra cluster we need to setup +an instance of Cluster. As the name suggests, you will typically have one +instance of Cluster for each Cassandra cluster you want to interact +with.

+

First, make sure you have the Cassandra driver properly installed.

+
+

Connecting to Cassandra

+

The simplest way to create a Cluster is like this:

+
from cassandra.cluster import Cluster
+
+cluster = Cluster()
+
+
+

This will attempt to connection to a Cassandra instance on your +local machine (127.0.0.1). You can also specify a list of IP +addresses for nodes in your cluster:

+
from cassandra.cluster import Cluster
+
+cluster = Cluster(['192.168.0.1', '192.168.0.2'])
+
+
+

The set of IP addresses we pass to the Cluster is simply +an initial set of contact points. After the driver connects to one +of these nodes it will automatically discover the rest of the +nodes in the cluster and connect to them, so you don’t need to list +every node in your cluster.

+

If you need to use a non-standard port, use SSL, or customize the driver’s +behavior in some other way, this is the place to do it:

+
from cassandra.cluster import Cluster
+cluster = Cluster(['192.168.0.1', '192.168.0.2'], port=..., ssl_context=...)
+
+
+

Instantiating a Cluster does not actually connect us to any nodes. +To establish connections and begin executing queries we need a +Session, which is created by calling Cluster.connect():

+
cluster = Cluster()
+session = cluster.connect()
+
+
+
+
+
+

Session Keyspace

+

The connect() method takes an optional keyspace argument +which sets the default keyspace for all queries made through that Session:

+
cluster = Cluster()
+session = cluster.connect('mykeyspace')
+
+
+

You can always change a Session’s keyspace using set_keyspace() or +by executing a USE <keyspace> query:

+
session.set_keyspace('users')
+# or you can do this instead
+session.execute('USE users')
+
+
+
+
+

Execution Profiles

+

Profiles are passed in by execution_profiles dict.

+

In this case we can construct the base ExecutionProfile passing all attributes:

+
from cassandra.cluster import Cluster, ExecutionProfile, EXEC_PROFILE_DEFAULT
+from cassandra.policies import WhiteListRoundRobinPolicy, DowngradingConsistencyRetryPolicy
+from cassandra.query import tuple_factory
+
+profile = ExecutionProfile(
+    load_balancing_policy=WhiteListRoundRobinPolicy(['127.0.0.1']),
+    retry_policy=DowngradingConsistencyRetryPolicy(),
+    consistency_level=ConsistencyLevel.LOCAL_QUORUM,
+    serial_consistency_level=ConsistencyLevel.LOCAL_SERIAL,
+    request_timeout=15,
+    row_factory=tuple_factory
+)
+cluster = Cluster(execution_profiles={EXEC_PROFILE_DEFAULT: profile})
+session = cluster.connect()
+
+print(session.execute("SELECT release_version FROM system.local").one())
+
+
+

Users are free to setup additional profiles to be used by name:

+
profile_long = ExecutionProfile(request_timeout=30)
+cluster = Cluster(execution_profiles={'long': profile_long})
+session = cluster.connect()
+session.execute(statement, execution_profile='long')
+
+
+

Also, parameters passed to Session.execute or attached to Statements are still honored as before.

+
+
+

Executing Queries

+

Now that we have a Session we can begin to execute queries. The simplest +way to execute a query is to use execute():

+
rows = session.execute('SELECT name, age, email FROM users')
+for user_row in rows:
+    print user_row.name, user_row.age, user_row.email
+
+
+

This will transparently pick a Cassandra node to execute the query against +and handle any retries that are necessary if the operation fails.

+

By default, each row in the result set will be a +namedtuple. +Each row will have a matching attribute for each column defined in the schema, +such as name, age, and so on. You can also treat them as normal tuples +by unpacking them or accessing fields by position. The following three +examples are equivalent:

+
rows = session.execute('SELECT name, age, email FROM users')
+for row in rows:
+    print row.name, row.age, row.email
+
+
+
rows = session.execute('SELECT name, age, email FROM users')
+for (name, age, email) in rows:
+    print name, age, email
+
+
+
rows = session.execute('SELECT name, age, email FROM users')
+for row in rows:
+    print row[0], row[1], row[2]
+
+
+

If you prefer another result format, such as a dict per row, you +can change the row_factory attribute.

+

As mentioned in our Drivers Best Practices Guide, +it is highly recommended to use Prepared statements for your +frequently run queries.

+
+
+

Prepared Statements

+

Prepared statements are queries that are parsed by Cassandra and then saved +for later use. When the driver uses a prepared statement, it only needs to +send the values of parameters to bind. This lowers network traffic +and CPU utilization within Cassandra because Cassandra does not have to +re-parse the query each time.

+

To prepare a query, use Session.prepare():

+
user_lookup_stmt = session.prepare("SELECT * FROM users WHERE user_id=?")
+
+users = []
+for user_id in user_ids_to_query:
+    user = session.execute(user_lookup_stmt, [user_id])
+    users.append(user)
+
+
+

prepare() returns a PreparedStatement instance +which can be used in place of SimpleStatement instances or literal +string queries. It is automatically prepared against all nodes, and the driver +handles re-preparing against new nodes and restarted nodes when necessary.

+

Note that the placeholders for prepared statements are ? characters. This +is different than for simple, non-prepared statements (although future versions +of the driver may use the same placeholders for both).

+
+
+

Passing Parameters to CQL Queries

+

Althought it is not recommended, you can also pass parameters to non-prepared +statements. The driver supports two forms of parameter place-holders: positional +and named.

+

Positional parameters are used with a %s placeholder. For example, +when you execute:

+
session.execute(
+    """
+    INSERT INTO users (name, credits, user_id)
+    VALUES (%s, %s, %s)
+    """,
+    ("John O'Reilly", 42, uuid.uuid1())
+)
+
+
+

It is translated to the following CQL query:

+
INSERT INTO users (name, credits, user_id)
+VALUES ('John O''Reilly', 42, 2644bada-852c-11e3-89fb-e0b9a54a6d93)
+
+
+

Note that you should use %s for all types of arguments, not just strings. +For example, this would be wrong:

+
session.execute("INSERT INTO USERS (name, age) VALUES (%s, %d)", ("bob", 42))  # wrong
+
+
+

Instead, use %s for the age placeholder.

+

If you need to use a literal % character, use %%.

+

Note: you must always use a sequence for the second argument, even if you are +only passing in a single variable:

+
session.execute("INSERT INTO foo (bar) VALUES (%s)", "blah")  # wrong
+session.execute("INSERT INTO foo (bar) VALUES (%s)", ("blah"))  # wrong
+session.execute("INSERT INTO foo (bar) VALUES (%s)", ("blah", ))  # right
+session.execute("INSERT INTO foo (bar) VALUES (%s)", ["blah"])  # right
+
+
+

Note that the second line is incorrect because in Python, single-element tuples +require a comma.

+

Named place-holders use the %(name)s form:

+
session.execute(
+    """
+    INSERT INTO users (name, credits, user_id, username)
+    VALUES (%(name)s, %(credits)s, %(user_id)s, %(name)s)
+    """,
+    {'name': "John O'Reilly", 'credits': 42, 'user_id': uuid.uuid1()}
+)
+
+
+

Note that you can repeat placeholders with the same name, such as %(name)s +in the above example.

+

Only data values should be supplied this way. Other items, such as keyspaces, +table names, and column names should be set ahead of time (typically using +normal string formatting).

+
+
+

Type Conversions

+

For non-prepared statements, Python types are cast to CQL literals in the +following way:

+ ++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Python Type

CQL Literal Type

None

NULL

bool

boolean

float

+
float
+
double
+
+
+
int
+
long
+
+
+
int
+
bigint
+
varint
+
smallint
+
tinyint
+
counter
+
+

decimal.Decimal

decimal

+
str
+
unicode
+
+
+
ascii
+
varchar
+
text
+
+
+
buffer
+
bytearray
+
+

blob

date

date

datetime

timestamp

time

time

+
list
+
tuple
+
generator
+
+

list

+
set
+
frozenset
+
+

set

+
dict
+
OrderedDict
+
+

map

uuid.UUID

+
timeuuid
+
uuid
+
+
+
+
+

Asynchronous Queries

+

The driver supports asynchronous query execution through +execute_async(). Instead of waiting for the query to +complete and returning rows directly, this method almost immediately +returns a ResponseFuture object. There are two ways of +getting the final result from this object.

+

The first is by calling result() on it. If +the query has not yet completed, this will block until it has and +then return the result or raise an Exception if an error occurred. +For example:

+
from cassandra import ReadTimeout
+
+query = "SELECT * FROM users WHERE user_id=%s"
+future = session.execute_async(query, [user_id])
+
+# ... do some other work
+
+try:
+    rows = future.result()
+    user = rows[0]
+    print user.name, user.age
+except ReadTimeout:
+    log.exception("Query timed out:")
+
+
+

This works well for executing many queries concurrently:

+
# build a list of futures
+futures = []
+query = "SELECT * FROM users WHERE user_id=%s"
+for user_id in ids_to_fetch:
+    futures.append(session.execute_async(query, [user_id])
+
+# wait for them to complete and use the results
+for future in futures:
+    rows = future.result()
+    print rows[0].name
+
+
+

Alternatively, instead of calling result(), +you can attach callback and errback functions through the +add_callback(), +add_errback(), and +add_callbacks(), methods. If you have used +Twisted Python before, this is designed to be a lightweight version of +that:

+
def handle_success(rows):
+    user = rows[0]
+    try:
+        process_user(user.name, user.age, user.id)
+    except Exception:
+        log.error("Failed to process user %s", user.id)
+        # don't re-raise errors in the callback
+
+def handle_error(exception):
+    log.error("Failed to fetch user info: %s", exception)
+
+
+future = session.execute_async(query)
+future.add_callbacks(handle_success, handle_error)
+
+
+
+
There are a few important things to remember when working with callbacks:
    +
  • Exceptions that are raised inside the callback functions will be logged and then ignored.

  • +
  • Your callback will be run on the event loop thread, so any long-running +operations will prevent other requests from being handled

  • +
+
+
+
+
+

Setting a Consistency Level

+

The consistency level used for a query determines how many of the +replicas of the data you are interacting with need to respond for +the query to be considered a success.

+

By default, ConsistencyLevel.LOCAL_ONE will be used for all queries. +You can specify a different default by setting the ExecutionProfile.consistency_level +for the execution profile with key EXEC_PROFILE_DEFAULT. +To specify a different consistency level per request, wrap queries +in a SimpleStatement:

+
from cassandra import ConsistencyLevel
+from cassandra.query import SimpleStatement
+
+query = SimpleStatement(
+    "INSERT INTO users (name, age) VALUES (%s, %s)",
+    consistency_level=ConsistencyLevel.QUORUM)
+session.execute(query, ('John', 42))
+
+
+
+
+

Setting a Consistency Level with Prepared Statements

+

To specify a consistency level for prepared statements, you have two options.

+

The first is to set a default consistency level for every execution of the +prepared statement:

+
from cassandra import ConsistencyLevel
+
+cluster = Cluster()
+session = cluster.connect("mykeyspace")
+user_lookup_stmt = session.prepare("SELECT * FROM users WHERE user_id=?")
+user_lookup_stmt.consistency_level = ConsistencyLevel.QUORUM
+
+# these will both use QUORUM
+user1 = session.execute(user_lookup_stmt, [user_id1])[0]
+user2 = session.execute(user_lookup_stmt, [user_id2])[0]
+
+
+

The second option is to create a BoundStatement from the +PreparedStatement and binding parameters and set a consistency +level on that:

+
# override the QUORUM default
+user3_lookup = user_lookup_stmt.bind([user_id3])
+user3_lookup.consistency_level = ConsistencyLevel.ALL
+user3 = session.execute(user3_lookup)
+
+
+
+
+

Speculative Execution

+

Speculative execution is a way to minimize latency by preemptively executing several +instances of the same query against different nodes. For more details about this +technique, see Speculative Execution with DataStax Drivers.

+

To enable speculative execution:

+
    +
  • Configure a SpeculativeExecutionPolicy with the ExecutionProfile

  • +
  • Mark your query as idempotent, which mean it can be applied multiple +times without changing the result of the initial application. +See Query Idempotence for more details.

  • +
+

Example:

+
from cassandra.cluster import Cluster, ExecutionProfile, EXEC_PROFILE_DEFAULT
+from cassandra.policies import ConstantSpeculativeExecutionPolicy
+from cassandra.query import SimpleStatement
+
+# Configure the speculative execution policy
+ep = ExecutionProfile(
+    speculative_execution_policy=ConstantSpeculativeExecutionPolicy(delay=.5, max_attempts=10)
+)
+cluster = Cluster(..., execution_profiles={EXEC_PROFILE_DEFAULT: ep})
+session = cluster.connect()
+
+# Mark the query idempotent
+query = SimpleStatement(
+    "UPDATE my_table SET list_col = [1] WHERE pk = 1",
+    is_idempotent=True
+)
+
+# Execute. A new query will be sent to the server every 0.5 second
+# until we receive a response, for a max number attempts of 10.
+session.execute(query)
+
+
+
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.25.11-scylla/index.html b/3.25.11-scylla/index.html new file mode 100644 index 0000000000..5fd5d5cf9a --- /dev/null +++ b/3.25.11-scylla/index.html @@ -0,0 +1,701 @@ + + + + + + + + + + + + + Python Driver for Scylla and Apache Cassandra® | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

Python Driver for Scylla and Apache Cassandra®

+

A Python client driver for Scylla. +This driver works exclusively with the Cassandra Query Language v3 (CQL3) +and Cassandra’s native protocol.

+

The driver supports Python 2.7, 3.5, 3.6, 3.7 and 3.8.

+

This driver is open source under the +Apache v2 License. +The source code for this driver can be found on GitHub.

+

Scylla Driver is a fork from DataStax Python Driver, including some non-breaking changes for Scylla optimization, with more updates planned.

+
+

Contents

+
+
Installation

How to install the driver.

+
+
Getting Started

A guide through the first steps of connecting to Scylla and executing queries

+
+
Scylla Specific Features

A list of feature available only on scylla-driver

+
+
Execution Profiles

An introduction to a more flexible way of configuring request execution

+
+
Lightweight Transactions (Compare-and-set)

Working with results of conditional requests

+
+
Object Mapper

Introduction to the integrated object mapper, cqlengine

+
+
Performance Notes

Tips for getting good performance.

+
+
Paging Large Queries

Notes on paging large query results

+
+
Security

An overview of the security features of the driver

+
+
Upgrading

A guide to upgrading versions of the driver

+
+
User Defined Types

Working with Scylla’s user-defined types (UDT)

+
+
Working with Dates and Times

Some discussion on the driver’s approach to working with timestamp, date, time types

+
+
Scylla Cloud

Connect to Scylla Cloud

+
+
CHANGELOG

Log of changes to the driver, organized by version.

+
+
Frequently Asked Questions

A collection of Frequently Asked Questions

+
+
API Documentation

The API documentation.

+
+
+
+
+
+
+

Getting Help

+

Visit the FAQ section in this documentation.

+

Please send questions to the Scylla user list.

+
+
+

Reporting Issues

+

Please report any bugs and make any feature requests on the Github project issues

+
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.25.11-scylla/installation.html b/3.25.11-scylla/installation.html new file mode 100644 index 0000000000..16cb490dcb --- /dev/null +++ b/3.25.11-scylla/installation.html @@ -0,0 +1,874 @@ + + + + + + + + + + + + + Installation | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

Installation

+
+

Supported Platforms

+

Python 2.7, 3.5, 3.6, 3.7 and 3.8 are supported. Both CPython (the standard Python +implementation) and PyPy are supported and tested.

+

Linux, OSX, and Windows are supported.

+
+
+

Installation through pip

+

pip is the suggested tool for installing +packages. It will handle installing all Python dependencies for the driver at +the same time as the driver itself. To install the driver*:

+
pip install scylla-driver
+
+
+

You can use pip install --pre scylla-driver if you need to install a beta version.

+

*Note: if intending to use optional extensions, install the dependencies first. The driver may need to be reinstalled if dependencies are added after the initial installation.

+
+
+

Verifying your Installation

+

To check if the installation was successful, you can run:

+
python -c 'import cassandra; print cassandra.__version__'
+
+
+

It should print something like “3.22.0”.

+
+
+

(Optional) Graph

+

The driver provides an optional fluent graph API that depends on Apache TinkerPop (gremlinpython). It is +not installed by default. To be able to build Gremlin traversals, you need to install +the graph requirements:

+
pip install scylla-driver[graph]
+
+
+
+
+

(Optional) Compression Support

+

Compression can optionally be used for communication between the driver and +Cassandra. There are currently two supported compression algorithms: +snappy (in Cassandra 1.2+) and LZ4 (only in Cassandra 2.0+). If either is +available for the driver and Cassandra also supports it, it will +be used automatically.

+

For lz4 support:

+
pip install lz4
+
+
+

For snappy support:

+
pip install python-snappy
+
+
+

(If using a Debian Linux derivative such as Ubuntu, it may be easier to +just run apt-get install python-snappy.)

+
+
+

(Optional) Metrics Support

+

The driver has built-in support for capturing Cluster.metrics about +the queries you run. However, the scales library is required to +support this:

+
pip install scales
+
+
+
+

Speeding Up Installation

+

By default, installing the driver through pip uses a pre-compiled, platform-specific wheel when available. +If using a source distribution rather than a wheel, Cython is used to compile certain parts of the driver. +This makes those hot paths faster at runtime, but the Cython compilation +process can take a long time – as long as 10 minutes in some environments.

+

In environments where performance is less important, it may be worth it to +disable Cython as documented below. +You can also use CASS_DRIVER_BUILD_CONCURRENCY to increase the number of +threads used to build the driver and any C extensions:

+
$ # installing from source
+$ CASS_DRIVER_BUILD_CONCURRENCY=8 python setup.py install
+$ # installing from pip
+$ CASS_DRIVER_BUILD_CONCURRENCY=8 pip install scylla-driver
+
+
+
+
+

OSX Installation Error

+

If you’re installing on OSX and have XCode 5.1 installed, you may see an error like this:

+
clang: error: unknown argument: '-mno-fused-madd' [-Wunused-command-line-argument-hard-error-in-future]
+
+
+

To fix this, re-run the installation with an extra compilation flag:

+
ARCHFLAGS=-Wno-error=unused-command-line-argument-hard-error-in-future pip install scylla-driver
+
+
+
+
+
+

Windows Installation Notes

+

Installing the driver with extensions in Windows sometimes presents some challenges. A few notes about common +hang-ups:

+

Setup requires a compiler. When using Python 2, this is as simple as installing this package +(this link is also emitted during install if setuptools is unable to find the resources it needs). Depending on your +system settings, this package may install as a user-specific application. Make sure to install for everyone, or at least +as the user that will be building the Python environment.

+

It is also possible to run the build with your compiler of choice. Just make sure to have your environment setup with +the proper paths. Make sure the compiler target architecture matches the bitness of your Python runtime. +Perhaps the easiest way to do this is to run the build/install from a Visual Studio Command Prompt (a +shortcut installed with Visual Studio that sources the appropriate environment and presents a shell).

+
+
+

Manual Installation

+

You can always install the driver directly from a source checkout or tarball. +When installing manually, ensure the python dependencies are already +installed. You can find the list of dependencies in +requirements.txt.

+

Once the dependencies are installed, simply run:

+
python setup.py install
+
+
+
+
+

(Optional) Non-python Dependencies

+

The driver has several optional features that have non-Python dependencies.

+
+

C Extensions

+

By default, a number of extensions are compiled, providing faster hashing +for token-aware routing with the Murmur3Partitioner, +libev event loop integration, +and Cython optimized extensions.

+

When installing manually through setup.py, you can disable both with +the --no-extensions option, or selectively disable them with +with --no-murmur3, --no-libev, or --no-cython.

+

To compile the extensions, ensure that GCC and the Python headers are available.

+

On Ubuntu and Debian, this can be accomplished by running:

+
$ sudo apt-get install gcc python-dev
+
+
+

On RedHat and RedHat-based systems like CentOS and Fedora:

+
$ sudo yum install gcc python-devel
+
+
+

On OS X, homebrew installations of Python should provide the necessary headers.

+

See Windows Installation Notes for notes on configuring the build environment on Windows.

+
+

Cython-based Extensions

+

By default, this package uses Cython to optimize core modules and build custom extensions. +This is not a hard requirement, but is engaged by default to build extensions offering better performance than the +pure Python implementation.

+

This is a costly build phase, especially in clean environments where the Cython compiler must be built +This build phase can be avoided using the build switch, or an environment variable:

+
python setup.py install --no-cython
+
+
+

Alternatively, an environment variable can be used to switch this option regardless of +context:

+
CASS_DRIVER_NO_CYTHON=1 <your script here>
+- or, to disable all extensions:
+CASS_DRIVER_NO_EXTENSIONS=1 <your script here>
+
+
+

This method is required when using pip, which provides no other way of injecting user options in a single command:

+
CASS_DRIVER_NO_CYTHON=1 pip install scylla-driver
+CASS_DRIVER_NO_CYTHON=1 sudo -E pip install ~/python-driver
+
+
+

The environment variable is the preferred option because it spans all invocations of setup.py, and will +prevent Cython from being materialized as a setup requirement.

+

If your sudo configuration does not allow SETENV, you must push the option flag down via pip. However, pip +applies these options to all dependencies (which break on the custom flag). Therefore, you must first install +dependencies, then use install-option:

+
sudo pip install six futures
+sudo pip install --install-option="--no-cython"
+
+
+
+
+
+

libev support

+

The driver currently uses Python’s asyncore module for its default +event loop. For better performance, libev is also supported through +a C extension.

+

If you’re on Linux, you should be able to install libev +through a package manager. For example, on Debian/Ubuntu:

+
$ sudo apt-get install libev4 libev-dev
+
+
+

On RHEL/CentOS/Fedora:

+
$ sudo yum install libev libev-devel
+
+
+

If you’re on Mac OS X, you should be able to install libev +through Homebrew. For example, on Mac OS X:

+
$ brew install libev
+
+
+

The libev extension is not built for Windows (the build process is complex, and the Windows implementation uses +select anyway).

+

If successful, you should be able to build and install the extension +(just using setup.py build or setup.py install) and then use +the libev event loop by doing the following:

+
>>> from cassandra.io.libevreactor import LibevConnection
+>>> from cassandra.cluster import Cluster
+
+>>> cluster = Cluster()
+>>> cluster.connection_class = LibevConnection
+>>> session = cluster.connect()
+
+
+
+
+
+

(Optional) Configuring SSL

+

Andrew Mussey has published a thorough guide on +Using SSL with the DataStax Python driver.

+
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.25.11-scylla/lwt.html b/3.25.11-scylla/lwt.html new file mode 100644 index 0000000000..c5c8930f41 --- /dev/null +++ b/3.25.11-scylla/lwt.html @@ -0,0 +1,734 @@ + + + + + + + + + + + + + Lightweight Transactions (Compare-and-set) | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

Lightweight Transactions (Compare-and-set)

+

Lightweight Transactions (LWTs) are mostly pass-through CQL for the driver. However, +the server returns some specialized results indicating the outcome and optional state +preceding the transaction.

+

For pertinent execution parameters, see Statement.serial_consistency_level.

+

This section discusses working with specialized result sets returned by the server for LWTs, +and how to work with them using the driver.

+
+

Specialized Results

+

The result returned from a LWT request is always a single row result. It will always have +prepended a special column named [applied]. How this value appears in your results depends +on the row factory in use. See below for examples.

+

The value of this [applied] column is boolean value indicating whether or not the transaction was applied. +If True, it is the only column in the result. If False, the additional columns depend on the LWT operation being +executed:

+
    +
  • When using a UPDATE ... IF "col" = ... clause, the result will contain the [applied] column, plus the existing columns +and values for any columns in the IF clause (and thus the value that caused the transaction to fail).

  • +
  • When using INSERT ... IF NOT EXISTS, the result will contain the [applied] column, plus all columns and values +of the existing row that rejected the transaction.

  • +
  • UPDATE .. IF EXISTS never has additional columns, regardless of [applied] status.

  • +
+

How the [applied] column manifests depends on the row factory in use. Considering the following (initially empty) table:

+
CREATE TABLE test.t (
+    k int PRIMARY KEY,
+    v int,
+    x int
+)
+
+
+

… the following sections show the expected result for a number of example statements, using the three base row factories.

+
+

named_tuple_factory (default)

+

The name [applied] is not a valid Python identifier, so the square brackets are actually removed +from the attribute for the resulting namedtuple. The row always has a boolean column applied in position 0:

+
>>> session.execute("INSERT INTO t (k,v) VALUES (0,0) IF NOT EXISTS")
+Row(applied=True)
+
+>>> session.execute("INSERT INTO t (k,v) VALUES (0,0) IF NOT EXISTS")
+Row(applied=False, k=0, v=0, x=None)
+
+>>> session.execute("UPDATE t SET v = 1, x = 2 WHERE k = 0 IF v =0")
+Row(applied=True)
+
+>>> session.execute("UPDATE t SET v = 1, x = 2 WHERE k = 0 IF v =0 AND x = 1")
+Row(applied=False, v=1, x=2)
+
+
+
+
+

tuple_factory

+

This return type does not refer to names, but the boolean value applied is always present in position 0:

+
>>> session.execute("INSERT INTO t (k,v) VALUES (0,0) IF NOT EXISTS")
+(True,)
+
+>>> session.execute("INSERT INTO t (k,v) VALUES (0,0) IF NOT EXISTS")
+(False, 0, 0, None)
+
+>>> session.execute("UPDATE t SET v = 1, x = 2 WHERE k = 0 IF v =0")
+(True,)
+
+>>> session.execute("UPDATE t SET v = 1, x = 2 WHERE k = 0 IF v =0 AND x = 1")
+(False, 1, 2)
+
+
+
+
+

dict_factory

+

The retuned dict contains the [applied] key:

+
>>> session.execute("INSERT INTO t (k,v) VALUES (0,0) IF NOT EXISTS")
+{u'[applied]': True}
+
+>>> session.execute("INSERT INTO t (k,v) VALUES (0,0) IF NOT EXISTS")
+{u'x': 2, u'[applied]': False, u'v': 1}
+
+>>> session.execute("UPDATE t SET v = 1, x = 2 WHERE k = 0 IF v =0")
+{u'x': None, u'[applied]': False, u'k': 0, u'v': 0}
+
+>>> session.execute("UPDATE t SET v = 1, x = 2 WHERE k = 0 IF v =0 AND x = 1")
+{u'[applied]': True}
+
+
+
+
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.25.11-scylla/object_mapper.html b/3.25.11-scylla/object_mapper.html new file mode 100644 index 0000000000..310be6ba20 --- /dev/null +++ b/3.25.11-scylla/object_mapper.html @@ -0,0 +1,731 @@ + + + + + + + + + + + + + Object Mapper | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

Object Mapper

+

cqlengine is the Cassandra CQL 3 Object Mapper packaged with this driver

+

Jump to Getting Started

+
+

Contents

+
+
Upgrade Guide

For migrating projects from legacy cqlengine, to the integrated product

+
+
Models

Examples defining models, and mapping them to tables

+
+
Making Queries

Overview of query sets and filtering

+
+
Batch Queries

Working with batch mutations

+
+
Connections

Working with multiple sessions

+
+
API Documentation

Index of API documentation

+
+
Third party integrations

High-level examples in Celery and uWSGI

+
+
+

Frequently Asked Questions

+
+
+
+
+

Getting Started

+
import uuid
+from cassandra.cqlengine import columns
+from cassandra.cqlengine import connection
+from datetime import datetime
+from cassandra.cqlengine.management import sync_table
+from cassandra.cqlengine.models import Model
+
+#first, define a model
+class ExampleModel(Model):
+    example_id      = columns.UUID(primary_key=True, default=uuid.uuid4)
+    example_type    = columns.Integer(index=True)
+    created_at      = columns.DateTime()
+    description     = columns.Text(required=False)
+
+#next, setup the connection to your cassandra server(s)...
+# see http://datastax.github.io/python-driver/api/cassandra/cluster.html for options
+# the list of hosts will be passed to create a Cluster() instance
+connection.setup(['127.0.0.1'], "cqlengine", protocol_version=3)
+
+#...and create your CQL table
+>>> sync_table(ExampleModel)
+
+#now we can create some rows:
+>>> em1 = ExampleModel.create(example_type=0, description="example1", created_at=datetime.now())
+>>> em2 = ExampleModel.create(example_type=0, description="example2", created_at=datetime.now())
+>>> em3 = ExampleModel.create(example_type=0, description="example3", created_at=datetime.now())
+>>> em4 = ExampleModel.create(example_type=0, description="example4", created_at=datetime.now())
+>>> em5 = ExampleModel.create(example_type=1, description="example5", created_at=datetime.now())
+>>> em6 = ExampleModel.create(example_type=1, description="example6", created_at=datetime.now())
+>>> em7 = ExampleModel.create(example_type=1, description="example7", created_at=datetime.now())
+>>> em8 = ExampleModel.create(example_type=1, description="example8", created_at=datetime.now())
+
+#and now we can run some queries against our table
+>>> ExampleModel.objects.count()
+8
+>>> q = ExampleModel.objects(example_type=1)
+>>> q.count()
+4
+>>> for instance in q:
+>>>     print instance.description
+example5
+example6
+example7
+example8
+
+#here we are applying additional filtering to an existing query
+#query objects are immutable, so calling filter returns a new
+#query object
+>>> q2 = q.filter(example_id=em5.example_id)
+
+>>> q2.count()
+1
+>>> for instance in q2:
+>>>     print instance.description
+example5
+
+
+
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.25.11-scylla/objects.inv b/3.25.11-scylla/objects.inv new file mode 100644 index 0000000000..828bfc442d Binary files /dev/null and b/3.25.11-scylla/objects.inv differ diff --git a/3.25.11-scylla/performance.html b/3.25.11-scylla/performance.html new file mode 100644 index 0000000000..d1cc8c72bb --- /dev/null +++ b/3.25.11-scylla/performance.html @@ -0,0 +1,685 @@ + + + + + + + + + + + + + Performance Notes | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

Performance Notes

+

The Python driver for Cassandra offers several methods for executing queries. +You can synchronously block for queries to complete using +Session.execute(), you can obtain asynchronous request futures through +Session.execute_async(), and you can attach a callback to the future +with ResponseFuture.add_callback().

+

Examples of multiple request patterns can be found in the benchmark scripts included in the driver project.

+

The choice of execution pattern will depend on the application context. For applications dealing with multiple +requests in a given context, the recommended pattern is to use concurrent asynchronous +requests with callbacks. For many use cases, you don’t need to implement this pattern yourself. +cassandra.concurrent.execute_concurrent() and cassandra.concurrent.execute_concurrent_with_args() +provide this pattern with a synchronous API and tunable concurrency.

+

Due to the GIL and limited concurrency, the driver can become CPU-bound pretty quickly. The sections below +discuss further runtime and design considerations for mitigating this limitation.

+
+

PyPy

+

PyPy is an alternative Python runtime which uses a JIT compiler to +reduce CPU consumption. This leads to a huge improvement in the driver performance, +more than doubling throughput for many workloads.

+
+
+

Cython Extensions

+

Cython is an optimizing compiler and language that can be used to compile the core files and +optional extensions for the driver. Cython is not a strict dependency, but the extensions will be built by default.

+

See Installation for details on controlling this build.

+
+
+

multiprocessing

+

All of the patterns discussed above may be used over multiple processes using the +multiprocessing +module. Multiple processes will scale better than multiple threads, so if high throughput is your goal, +consider this option.

+

Be sure to never share any Cluster, Session, +or ResponseFuture objects across multiple processes. These +objects should all be created after forking the process, not before.

+

For further discussion and simple examples using the driver with multiprocessing, +see this blog post.

+
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.25.11-scylla/py-modindex.html b/3.25.11-scylla/py-modindex.html new file mode 100644 index 0000000000..3dd6fa4314 --- /dev/null +++ b/3.25.11-scylla/py-modindex.html @@ -0,0 +1,618 @@ + + + + + + + + + + + + + Python Module Index | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ + + +
+ + + + + +
+ + +
+
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.25.11-scylla/query_paging.html b/3.25.11-scylla/query_paging.html new file mode 100644 index 0000000000..050ccf0304 --- /dev/null +++ b/3.25.11-scylla/query_paging.html @@ -0,0 +1,739 @@ + + + + + + + + + + + + + Paging Large Queries | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

Paging Large Queries

+

Cassandra 2.0+ offers support for automatic query paging. Starting with +version 2.0 of the driver, if protocol_version is greater than +2 (it is by default), queries returning large result sets will be +automatically paged.

+
+

Controlling the Page Size

+

By default, Session.default_fetch_size controls how many rows will +be fetched per page. This can be overridden per-query by setting +fetch_size on a Statement. By default, each page +will contain at most 5000 rows.

+
+
+

Handling Paged Results

+

Whenever the number of result rows for are query exceed the page size, an +instance of PagedResult will be returned instead of a normal +list. This class implements the iterator interface, so you can treat +it like a normal iterator over rows:

+
from cassandra.query import SimpleStatement
+query = "SELECT * FROM users"  # users contains 100 rows
+statement = SimpleStatement(query, fetch_size=10)
+for user_row in session.execute(statement):
+    process_user(user_row)
+
+
+

Whenever there are no more rows in the current page, the next page will +be fetched transparently. However, note that it is possible for +an Exception to be raised while fetching the next page, just +like you might see on a normal call to session.execute().

+

If you use Session.execute_async() along with, +ResponseFuture.result(), the first page will be fetched before +result() returns, but latter pages will be +transparently fetched synchronously while iterating the result.

+
+
+

Handling Paged Results with Callbacks

+

If callbacks are attached to a query that returns a paged result, +the callback will be called once per page with a normal list of rows.

+

Use ResponseFuture.has_more_pages and +ResponseFuture.start_fetching_next_page() to continue fetching +pages. For example:

+
class PagedResultHandler(object):
+
+    def __init__(self, future):
+        self.error = None
+        self.finished_event = Event()
+        self.future = future
+        self.future.add_callbacks(
+            callback=self.handle_page,
+            errback=self.handle_err)
+
+    def handle_page(self, rows):
+        for row in rows:
+            process_row(row)
+
+        if self.future.has_more_pages:
+            self.future.start_fetching_next_page()
+        else:
+            self.finished_event.set()
+
+    def handle_error(self, exc):
+        self.error = exc
+        self.finished_event.set()
+
+future = session.execute_async("SELECT * FROM users")
+handler = PagedResultHandler(future)
+handler.finished_event.wait()
+if handler.error:
+    raise handler.error
+
+
+
+
+

Resume Paged Results

+

You can resume the pagination when executing a new query by using the ResultSet.paging_state. This can be useful if you want to provide some stateless pagination capabilities to your application (ie. via http). For example:

+
from cassandra.query import SimpleStatement
+query = "SELECT * FROM users"
+statement = SimpleStatement(query, fetch_size=10)
+results = session.execute(statement)
+
+# save the paging_state somewhere and return current results
+web_session['paging_state'] = results.paging_state
+
+
+# resume the pagination sometime later...
+statement = SimpleStatement(query, fetch_size=10)
+ps = web_session['paging_state']
+results = session.execute(statement, paging_state=ps)
+
+
+
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.25.11-scylla/scylla_cloud.html b/3.25.11-scylla/scylla_cloud.html new file mode 100644 index 0000000000..803ed9ad3c --- /dev/null +++ b/3.25.11-scylla/scylla_cloud.html @@ -0,0 +1,637 @@ + + + + + + + + + + + + + Scylla Cloud | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

Scylla Cloud

+

To connect to a Scylla Cloud cluster, go to the Cluster Connect page, Python example. +For best performance, make sure to use the Scylla Driver.

+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.25.11-scylla/scylla_specific.html b/3.25.11-scylla/scylla_specific.html new file mode 100644 index 0000000000..da3a944591 --- /dev/null +++ b/3.25.11-scylla/scylla_specific.html @@ -0,0 +1,746 @@ + + + + + + + + + + + + + Scylla Specific Features | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

Scylla Specific Features

+
+

Shard Awareness

+

scylla-driver is shard aware and contains extensions that work with the TokenAwarePolicy supported by Scylla 2.3 and onwards. Using this policy, the driver can select a connection to a particular shard based on the shard’s token. +As a result, latency is significantly reduced because there is no need to pass data between the shards.

+

Details on the scylla cql protocol extensions +https://github.com/scylladb/scylla/blob/master/docs/dev/protocol-extensions.md#intranode-sharding

+

For using it you only need to enable TokenAwarePolicy on the Cluster

+

See the configuration of native_shard_aware_transport_port and native_shard_aware_transport_port_ssl on scylla.yaml: +https://github.com/scylladb/scylla/blob/master/docs/dev/protocols.md#cql-client-protocol

+
from cassandra.cluster import Cluster
+from cassandra.policies import TokenAwarePolicy, RoundRobinPolicy
+
+cluster = Cluster(load_balancing_policy=TokenAwarePolicy(RoundRobinPolicy()))
+
+
+
+
+

New Cluster Helpers

+
    +
  • shard_aware_options

    +

    Setting it to dict(disable=True) would disable the shard aware functionally, for cases favoring once connection per host (example, lots of processes connecting from one client host, generating a big load of connections

    +

    Other option is to configure scylla by setting enable_shard_aware_drivers: false on scylla.yaml.

    +
  • +
+
from cassandra.cluster import Cluster
+
+cluster = Cluster(shard_aware_options=dict(disable=True))
+session = cluster.connect()
+
+assert not cluster.is_shard_aware(), "Shard aware should be disabled"
+
+# or just disable the shard aware port logic
+cluster = Cluster(shard_aware_options=dict(disable_shardaware_port=True))
+session = cluster.connect()
+
+
+
    +
  • cluster.is_shard_aware()

    +

    New method available on Cluster allowing to check whether the remote cluster supports shard awareness (bool)

    +
  • +
+
from cassandra.cluster import Cluster
+
+cluster = Cluster()
+session = cluster.connect()
+
+if cluster.is_shard_aware():
+    print("connected to a scylla cluster")
+
+
+
    +
  • cluster.shard_aware_stats()

    +

    New method available on Cluster allowing to check the status of shard aware connections to all available hosts (dict)

    +
  • +
+
from cassandra.cluster import Cluster
+
+cluster = Cluster()
+session = cluster.connect()
+
+stats = cluster.shard_aware_stats()
+if all([v["shards_count"] == v["connected"] for v in stats.values()]):
+    print("successfully connected to all shards of all scylla nodes")
+
+
+
+
+

New Table Attributes

+
    +
  • in_memory flag

    +

    New flag available on TableMetadata.options to indicate that it is an In Memory table

    +
  • +
+
+

Note

+

in memory tables is a feature existing only in Scylla Enterprise

+
+
from cassandra.cluster import Cluster
+
+cluster = Cluster()
+session = cluster.connect()
+session.execute("""
+    CREATE KEYSPACE IF NOT EXISTS keyspace1
+    WITH replication = {'class': 'SimpleStrategy', 'replication_factor': '1'};
+""")
+
+session.execute("""
+    CREATE TABLE IF NOT EXISTS keyspace1.standard1 (
+        key blob PRIMARY KEY,
+        "C0" blob
+    ) WITH in_memory=true AND compaction={'class': 'InMemoryCompactionStrategy'}
+""")
+
+cluster.refresh_table_metadata("keyspace1", "standard1")
+assert cluster.metadata.keyspaces["keyspace1"].tables["standard1"].options["in_memory"] == True
+
+
+
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.25.11-scylla/search.html b/3.25.11-scylla/search.html new file mode 100644 index 0000000000..a9b4afbdcb --- /dev/null +++ b/3.25.11-scylla/search.html @@ -0,0 +1,621 @@ + + + + + + + + + + + + + Search | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + + + + + +
+ + + + + +
+ + +
+
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.25.11-scylla/searchindex.js b/3.25.11-scylla/searchindex.js new file mode 100644 index 0000000000..5bb7fa47cd --- /dev/null +++ b/3.25.11-scylla/searchindex.js @@ -0,0 +1 @@ +Search.setIndex({docnames:["CHANGELOG","api/cassandra","api/cassandra/auth","api/cassandra/cluster","api/cassandra/concurrent","api/cassandra/connection","api/cassandra/cqlengine/columns","api/cassandra/cqlengine/connection","api/cassandra/cqlengine/management","api/cassandra/cqlengine/models","api/cassandra/cqlengine/query","api/cassandra/cqlengine/usertype","api/cassandra/datastax/graph/fluent/index","api/cassandra/datastax/graph/fluent/predicates","api/cassandra/datastax/graph/fluent/query","api/cassandra/datastax/graph/index","api/cassandra/decoder","api/cassandra/encoder","api/cassandra/graph","api/cassandra/io/asyncioreactor","api/cassandra/io/asyncorereactor","api/cassandra/io/eventletreactor","api/cassandra/io/geventreactor","api/cassandra/io/libevreactor","api/cassandra/io/twistedreactor","api/cassandra/metadata","api/cassandra/metrics","api/cassandra/policies","api/cassandra/pool","api/cassandra/protocol","api/cassandra/query","api/cassandra/timestamps","api/cassandra/util","api/index","cqlengine/batches","cqlengine/connections","cqlengine/faq","cqlengine/models","cqlengine/queryset","cqlengine/third_party","cqlengine/upgrade_guide","dates_and_times","execution_profiles","faq","getting_started","index","installation","lwt","object_mapper","performance","query_paging","scylla_cloud","scylla_specific","security","upgrading","user_defined_types"],envversion:{"sphinx.domains.c":2,"sphinx.domains.changeset":1,"sphinx.domains.citation":1,"sphinx.domains.cpp":4,"sphinx.domains.index":1,"sphinx.domains.javascript":2,"sphinx.domains.math":2,"sphinx.domains.python":3,"sphinx.domains.rst":2,"sphinx.domains.std":2,"sphinx.ext.todo":2,sphinx:56},filenames:["CHANGELOG.rst","api/cassandra.rst","api/cassandra/auth.rst","api/cassandra/cluster.rst","api/cassandra/concurrent.rst","api/cassandra/connection.rst","api/cassandra/cqlengine/columns.rst","api/cassandra/cqlengine/connection.rst","api/cassandra/cqlengine/management.rst","api/cassandra/cqlengine/models.rst","api/cassandra/cqlengine/query.rst","api/cassandra/cqlengine/usertype.rst","api/cassandra/datastax/graph/fluent/index.rst","api/cassandra/datastax/graph/fluent/predicates.rst","api/cassandra/datastax/graph/fluent/query.rst","api/cassandra/datastax/graph/index.rst","api/cassandra/decoder.rst","api/cassandra/encoder.rst","api/cassandra/graph.rst","api/cassandra/io/asyncioreactor.rst","api/cassandra/io/asyncorereactor.rst","api/cassandra/io/eventletreactor.rst","api/cassandra/io/geventreactor.rst","api/cassandra/io/libevreactor.rst","api/cassandra/io/twistedreactor.rst","api/cassandra/metadata.rst","api/cassandra/metrics.rst","api/cassandra/policies.rst","api/cassandra/pool.rst","api/cassandra/protocol.rst","api/cassandra/query.rst","api/cassandra/timestamps.rst","api/cassandra/util.rst","api/index.rst","cqlengine/batches.rst","cqlengine/connections.rst","cqlengine/faq.rst","cqlengine/models.rst","cqlengine/queryset.rst","cqlengine/third_party.rst","cqlengine/upgrade_guide.rst","dates_and_times.rst","execution_profiles.rst","faq.rst","getting_started.rst","index.rst","installation.rst","lwt.rst","object_mapper.rst","performance.rst","query_paging.rst","scylla_cloud.rst","scylla_specific.rst","security.rst","upgrading.rst","user_defined_types.rst"],objects:{"":[[1,0,0,"-","cassandra"]],"cassandra.AlreadyExists":[[1,2,1,"","keyspace"],[1,2,1,"","table"]],"cassandra.ConsistencyLevel":[[1,2,1,"","ALL"],[1,2,1,"","ANY"],[1,2,1,"","EACH_QUORUM"],[1,2,1,"","LOCAL_ONE"],[1,2,1,"","LOCAL_QUORUM"],[1,2,1,"","LOCAL_SERIAL"],[1,2,1,"","ONE"],[1,2,1,"","QUORUM"],[1,2,1,"","SERIAL"],[1,2,1,"","THREE"],[1,2,1,"","TWO"]],"cassandra.CoordinationFailure":[[1,2,1,"","consistency"],[1,2,1,"","error_code_map"],[1,2,1,"","failures"],[1,2,1,"","received_responses"],[1,2,1,"","required_responses"]],"cassandra.FunctionFailure":[[1,2,1,"","arg_types"],[1,2,1,"","function"],[1,2,1,"","keyspace"]],"cassandra.OperationTimedOut":[[1,2,1,"","errors"],[1,2,1,"","last_host"]],"cassandra.ProtocolVersion":[[1,2,1,"","BETA_VERSIONS"],[1,2,1,"","DSE_V1"],[1,2,1,"","DSE_V2"],[1,2,1,"","MAX_SUPPORTED"],[1,2,1,"","MIN_SUPPORTED"],[1,2,1,"","SUPPORTED_VERSIONS"],[1,2,1,"","V1"],[1,2,1,"","V2"],[1,2,1,"","V3"],[1,2,1,"","V4"],[1,2,1,"","V5"],[1,2,1,"","V6"],[1,4,1,"","get_lower_supported"]],"cassandra.ReadFailure":[[1,2,1,"","data_retrieved"]],"cassandra.ReadTimeout":[[1,2,1,"","data_retrieved"]],"cassandra.Timeout":[[1,2,1,"","consistency"],[1,2,1,"","received_responses"],[1,2,1,"","required_responses"]],"cassandra.Unavailable":[[1,2,1,"","alive_replicas"],[1,2,1,"","consistency"],[1,2,1,"","required_replicas"]],"cassandra.UserAggregateDescriptor":[[1,2,1,"","argument_types"],[1,2,1,"","name"],[1,5,1,"","signature"]],"cassandra.UserFunctionDescriptor":[[1,2,1,"","argument_types"],[1,2,1,"","name"],[1,5,1,"","signature"]],"cassandra.WriteFailure":[[1,2,1,"","write_type"]],"cassandra.WriteTimeout":[[1,2,1,"","write_type"]],"cassandra.auth":[[2,3,1,"","AuthProvider"],[2,3,1,"","Authenticator"],[2,3,1,"","PlainTextAuthProvider"],[2,3,1,"","PlainTextAuthenticator"],[2,3,1,"","SaslAuthProvider"],[2,3,1,"","SaslAuthenticator"]],"cassandra.auth.AuthProvider":[[2,4,1,"","new_authenticator"]],"cassandra.auth.Authenticator":[[2,4,1,"","evaluate_challenge"],[2,4,1,"","initial_response"],[2,4,1,"","on_authentication_success"],[2,2,1,"","server_authenticator_class"]],"cassandra.auth.PlainTextAuthProvider":[[2,4,1,"","new_authenticator"]],"cassandra.auth.PlainTextAuthenticator":[[2,4,1,"","evaluate_challenge"]],"cassandra.auth.SaslAuthProvider":[[2,4,1,"","new_authenticator"]],"cassandra.auth.SaslAuthenticator":[[2,4,1,"","evaluate_challenge"],[2,4,1,"","initial_response"]],"cassandra.cluster":[[3,3,1,"","Cluster"],[3,6,1,"","EXEC_PROFILE_DEFAULT"],[3,6,1,"","EXEC_PROFILE_GRAPH_ANALYTICS_DEFAULT"],[3,6,1,"","EXEC_PROFILE_GRAPH_DEFAULT"],[3,6,1,"","EXEC_PROFILE_GRAPH_SYSTEM_DEFAULT"],[3,3,1,"","ExecutionProfile"],[3,3,1,"","GraphAnalyticsExecutionProfile"],[3,3,1,"","GraphExecutionProfile"],[3,1,1,"","NoHostAvailable"],[3,1,1,"","QueryExhausted"],[3,3,1,"","ResponseFuture"],[3,3,1,"","ResultSet"],[3,3,1,"","Session"],[3,1,1,"","UserTypeDoesNotExist"]],"cassandra.cluster.Cluster":[[3,4,1,"","add_execution_profile"],[3,2,1,"","address_translator"],[3,2,1,"","auth_provider"],[3,2,1,"","cloud"],[3,2,1,"","compression"],[3,4,1,"","connect"],[3,2,1,"","connect_timeout"],[3,2,1,"","connection_class"],[3,2,1,"","contact_points"],[3,2,1,"","control_connection_timeout"],[3,2,1,"","conviction_policy_factory"],[3,2,1,"","cql_version"],[3,2,1,"","default_retry_policy"],[3,2,1,"","endpoint_factory"],[3,4,1,"","get_control_connection_host"],[3,4,1,"","get_core_connections_per_host"],[3,4,1,"","get_max_connections_per_host"],[3,4,1,"","get_max_requests_per_connection"],[3,4,1,"","get_min_requests_per_connection"],[3,2,1,"","idle_heartbeat_interval"],[3,2,1,"","idle_heartbeat_timeout"],[3,2,1,"","load_balancing_policy"],[3,2,1,"","max_schema_agreement_wait"],[3,2,1,"","metadata"],[3,2,1,"","metrics"],[3,2,1,"","metrics_enabled"],[3,2,1,"","port"],[3,2,1,"","prepare_on_all_hosts"],[3,2,1,"","protocol_version"],[3,2,1,"","reconnection_policy"],[3,4,1,"","refresh_keyspace_metadata"],[3,4,1,"","refresh_nodes"],[3,4,1,"","refresh_schema_metadata"],[3,4,1,"","refresh_table_metadata"],[3,4,1,"","refresh_user_aggregate_metadata"],[3,4,1,"","refresh_user_function_metadata"],[3,4,1,"","refresh_user_type_metadata"],[3,4,1,"","register_listener"],[3,4,1,"","register_user_type"],[3,2,1,"","reprepare_on_up"],[3,2,1,"","schema_event_refresh_window"],[3,2,1,"","schema_metadata_enabled"],[3,4,1,"","set_core_connections_per_host"],[3,4,1,"","set_max_connections_per_host"],[3,4,1,"","set_max_requests_per_connection"],[3,4,1,"","set_meta_refresh_enabled"],[3,4,1,"","set_min_requests_per_connection"],[3,4,1,"","shutdown"],[3,2,1,"","sockopts"],[3,2,1,"","ssl_context"],[3,2,1,"","ssl_options"],[3,2,1,"","status_event_refresh_window"],[3,2,1,"","timestamp_generator"],[3,2,1,"","token_metadata_enabled"],[3,2,1,"","topology_event_refresh_window"],[3,4,1,"","unregister_listener"]],"cassandra.cluster.ExecutionProfile":[[3,2,1,"","consistency_level"],[3,4,1,"","row_factory"]],"cassandra.cluster.ResponseFuture":[[3,4,1,"","add_callback"],[3,4,1,"","add_errback"],[3,2,1,"","custom_payload"],[3,4,1,"","get_all_query_traces"],[3,4,1,"","get_query_trace"],[3,2,1,"","has_more_pages"],[3,2,1,"","is_schema_agreed"],[3,2,1,"","query"],[3,4,1,"","result"],[3,4,1,"","start_fetching_next_page"],[3,2,1,"","warnings"]],"cassandra.cluster.ResultSet":[[3,4,1,"","all"],[3,5,1,"","current_rows"],[3,4,1,"","fetch_next_page"],[3,4,1,"","get_all_query_traces"],[3,4,1,"","get_query_trace"],[3,5,1,"","has_more_pages"],[3,4,1,"","one"],[3,5,1,"","paging_state"],[3,5,1,"","was_applied"]],"cassandra.cluster.Session":[[3,4,1,"","add_request_init_listener"],[3,2,1,"","client_protocol_handler"],[3,2,1,"","default_consistency_level"],[3,2,1,"","default_fetch_size"],[3,2,1,"","default_serial_consistency_level"],[3,2,1,"","default_timeout"],[3,2,1,"","encoder"],[3,4,1,"","execute"],[3,4,1,"","execute_async"],[3,4,1,"","execute_graph"],[3,4,1,"","execute_graph_async"],[3,4,1,"","execution_profile_clone_update"],[3,4,1,"","get_execution_profile"],[3,4,1,"","prepare"],[3,4,1,"","remove_request_init_listener"],[3,2,1,"","row_factory"],[3,4,1,"","set_keyspace"],[3,4,1,"","shutdown"],[3,2,1,"","timestamp_generator"],[3,2,1,"","use_client_timestamp"]],"cassandra.concurrent":[[4,7,1,"","execute_concurrent"],[4,7,1,"","execute_concurrent_with_args"]],"cassandra.connection":[[5,1,1,"","ConnectionBusy"],[5,1,1,"","ConnectionException"],[5,1,1,"","ConnectionShutdown"],[5,3,1,"","EndPoint"],[5,3,1,"","EndPointFactory"],[5,1,1,"","ProtocolError"],[5,3,1,"","SniEndPoint"],[5,3,1,"","SniEndPointFactory"],[5,3,1,"","UnixSocketEndPoint"]],"cassandra.connection.EndPoint":[[5,5,1,"","address"],[5,5,1,"","port"],[5,4,1,"","resolve"],[5,5,1,"","socket_family"],[5,5,1,"","ssl_options"]],"cassandra.connection.EndPointFactory":[[5,4,1,"","configure"],[5,4,1,"","create"]],"cassandra.cqlengine":[[6,0,0,"-","columns"],[7,0,0,"-","connection"],[8,0,0,"-","management"],[9,0,0,"-","models"],[10,0,0,"-","query"],[11,0,0,"-","usertype"]],"cassandra.cqlengine.columns":[[6,3,1,"","Ascii"],[6,3,1,"","BigInt"],[6,3,1,"","Blob"],[6,3,1,"","Boolean"],[6,2,1,"","Bytes"],[6,3,1,"","Column"],[6,3,1,"","Counter"],[6,3,1,"","Date"],[6,3,1,"","DateTime"],[6,3,1,"","Decimal"],[6,3,1,"","Double"],[6,3,1,"","Float"],[6,3,1,"","Integer"],[6,3,1,"","List"],[6,3,1,"","Map"],[6,3,1,"","Set"],[6,3,1,"","SmallInt"],[6,3,1,"","Text"],[6,3,1,"","Time"],[6,3,1,"","TimeUUID"],[6,3,1,"","TinyInt"],[6,3,1,"","UUID"],[6,3,1,"","UserDefinedType"],[6,3,1,"","VarInt"]],"cassandra.cqlengine.columns.Column":[[6,2,1,"","clustering_order"],[6,2,1,"","custom_index"],[6,2,1,"","db_field"],[6,2,1,"","default"],[6,2,1,"","discriminator_column"],[6,2,1,"","index"],[6,2,1,"","partition_key"],[6,2,1,"","primary_key"],[6,2,1,"","required"],[6,2,1,"","static"]],"cassandra.cqlengine.columns.DateTime":[[6,2,1,"","truncate_microseconds"]],"cassandra.cqlengine.connection":[[7,7,1,"","default"],[7,7,1,"","register_connection"],[7,7,1,"","set_default_connection"],[7,7,1,"","set_session"],[7,7,1,"","setup"],[7,7,1,"","unregister_connection"]],"cassandra.cqlengine.management":[[8,7,1,"","create_keyspace_network_topology"],[8,7,1,"","create_keyspace_simple"],[8,7,1,"","drop_keyspace"],[8,7,1,"","drop_table"],[8,7,1,"","sync_table"],[8,7,1,"","sync_type"]],"cassandra.cqlengine.models":[[9,3,1,"","Model"]],"cassandra.cqlengine.models.Model":[[9,2,1,"","__abstract__"],[9,2,1,"","__compute_routing_key__"],[9,2,1,"","__connection__"],[9,2,1,"","__default_ttl__"],[9,2,1,"","__discriminator_value__"],[9,2,1,"","__keyspace__"],[9,2,1,"","__options__"],[9,2,1,"","__table_name__"],[9,2,1,"","__table_name_case_sensitive__"],[9,4,1,"","all"],[9,4,1,"","batch"],[9,4,1,"","column_family_name"],[9,4,1,"","create"],[9,4,1,"","delete"],[9,4,1,"","filter"],[9,4,1,"","get"],[9,4,1,"","if_exists"],[9,4,1,"","if_not_exists"],[9,4,1,"","iff"],[9,4,1,"","items"],[9,4,1,"","keys"],[9,4,1,"","len"],[9,4,1,"","save"],[9,4,1,"","timeout"],[9,4,1,"","timestamp"],[9,4,1,"","ttl"],[9,4,1,"","update"],[9,4,1,"","using"],[9,4,1,"","values"]],"cassandra.cqlengine.query":[[10,3,1,"","BatchQuery"],[10,3,1,"","ContextQuery"],[10,3,1,"","DoesNotExist"],[10,3,1,"","LWTException"],[10,3,1,"","ModelQuerySet"],[10,3,1,"","MultipleObjectsReturned"]],"cassandra.cqlengine.query.BatchQuery":[[10,4,1,"","add_callback"],[10,4,1,"","add_query"],[10,4,1,"","execute"]],"cassandra.cqlengine.query.ModelQuerySet":[[10,4,1,"","all"],[10,4,1,"","allow_filtering"],[10,4,1,"","batch"],[10,4,1,"","consistency"],[10,4,1,"","count"],[10,4,1,"","defer"],[10,4,1,"","distinct"],[10,4,1,"","fetch_size"],[10,4,1,"","filter"],[10,4,1,"","get"],[10,4,1,"","if_exists"],[10,4,1,"","if_not_exists"],[10,4,1,"","len"],[10,4,1,"","limit"],[10,4,1,"","only"],[10,4,1,"","order_by"],[10,4,1,"","timestamp"],[10,4,1,"","ttl"],[10,4,1,"","update"],[10,4,1,"","using"]],"cassandra.cqlengine.usertype":[[11,3,1,"","UserType"]],"cassandra.cqlengine.usertype.UserType":[[11,2,1,"","__type_name__"]],"cassandra.datastax":[[15,0,0,"-","graph"]],"cassandra.datastax.graph":[[12,0,0,"-","fluent"],[15,7,1,"","graph_graphson2_row_factory"],[15,7,1,"","graph_graphson3_row_factory"],[15,7,1,"","graph_object_row_factory"],[15,7,1,"","graph_result_row_factory"],[15,7,1,"","single_object_row_factory"],[15,7,1,"","to_bigint"],[15,7,1,"","to_double"],[15,7,1,"","to_float"],[15,7,1,"","to_int"],[15,7,1,"","to_smallint"]],"cassandra.datastax.graph.GraphOptions":[[15,2,1,"","graph_language"],[15,2,1,"","graph_name"],[15,2,1,"","graph_read_consistency_level"],[15,2,1,"","graph_source"],[15,2,1,"","graph_write_consistency_level"],[15,2,1,"","is_analytics_source"],[15,2,1,"","is_default_source"],[15,2,1,"","is_graph_source"],[15,4,1,"","set_source_analytics"],[15,4,1,"","set_source_default"],[15,4,1,"","set_source_graph"]],"cassandra.datastax.graph.GraphSON1Deserializer":[[15,4,1,"","deserialize_bigint"],[15,4,1,"","deserialize_blob"],[15,4,1,"","deserialize_date"],[15,4,1,"","deserialize_decimal"],[15,4,1,"","deserialize_double"],[15,4,1,"","deserialize_duration"],[15,4,1,"","deserialize_float"],[15,4,1,"","deserialize_int"],[15,4,1,"","deserialize_linestring"],[15,4,1,"","deserialize_point"],[15,4,1,"","deserialize_polygon"],[15,4,1,"","deserialize_time"],[15,4,1,"","deserialize_timestamp"],[15,4,1,"","deserialize_uuid"]],"cassandra.datastax.graph.fluent":[[12,3,1,"","BaseGraphRowFactory"],[12,3,1,"","DSESessionRemoteGraphConnection"],[12,3,1,"","DseGraph"],[12,2,1,"","graph_traversal_dse_object_row_factory"],[12,2,1,"","graph_traversal_row_factory"],[13,0,0,"-","predicates"],[14,0,0,"-","query"]],"cassandra.datastax.graph.fluent.DseGraph":[[12,2,1,"","DSE_GRAPH_QUERY_LANGUAGE"],[12,4,1,"","batch"],[12,4,1,"","create_execution_profile"],[12,4,1,"","query_from_traversal"],[12,4,1,"","traversal_source"]],"cassandra.datastax.graph.fluent.predicates":[[13,3,1,"","CqlCollection"],[13,3,1,"","Geo"],[13,3,1,"","Search"]],"cassandra.datastax.graph.fluent.predicates.CqlCollection":[[13,4,1,"","contains"],[13,4,1,"","contains_key"],[13,4,1,"","contains_value"],[13,4,1,"","entry_eq"]],"cassandra.datastax.graph.fluent.predicates.Geo":[[13,4,1,"","inside"]],"cassandra.datastax.graph.fluent.predicates.Search":[[13,4,1,"","fuzzy"],[13,4,1,"","phrase"],[13,4,1,"","prefix"],[13,4,1,"","regex"],[13,4,1,"","token"],[13,4,1,"","token_fuzzy"],[13,4,1,"","token_prefix"],[13,4,1,"","token_regex"]],"cassandra.datastax.graph.fluent.query":[[14,3,1,"","TraversalBatch"]],"cassandra.datastax.graph.fluent.query.TraversalBatch":[[14,4,1,"","add"],[14,4,1,"","add_all"],[14,4,1,"","as_graph_statement"],[14,4,1,"","clear"],[14,4,1,"","execute"]],"cassandra.decoder":[[16,7,1,"","dict_factory"],[16,7,1,"","named_tuple_factory"],[16,7,1,"","ordered_dict_factory"],[16,7,1,"","tuple_factory"]],"cassandra.encoder":[[17,3,1,"","Encoder"]],"cassandra.encoder.Encoder":[[17,4,1,"","cql_encode_all_types"],[17,4,1,"","cql_encode_bytes"],[17,4,1,"","cql_encode_date"],[17,4,1,"","cql_encode_datetime"],[17,4,1,"","cql_encode_list_collection"],[17,4,1,"","cql_encode_map_collection"],[17,4,1,"","cql_encode_none"],[17,4,1,"","cql_encode_object"],[17,4,1,"","cql_encode_sequence"],[17,4,1,"","cql_encode_set_collection"],[17,4,1,"","cql_encode_str"],[17,4,1,"","cql_encode_tuple"],[17,4,1,"","cql_encode_unicode"],[17,2,1,"","mapping"]],"cassandra.graph":[[18,3,1,"","Edge"],[18,3,1,"","GraphOptions"],[18,3,1,"","GraphProtocol"],[18,3,1,"","GraphSON1Deserializer"],[18,3,1,"","GraphSON1Serializer"],[18,3,1,"","GraphSON2Reader"],[18,3,1,"","GraphSON3Reader"],[18,3,1,"","Path"],[18,3,1,"","Result"],[18,3,1,"","SimpleGraphStatement"],[18,3,1,"","Vertex"],[18,3,1,"","VertexProperty"],[18,7,1,"","graph_graphson2_row_factory"],[18,7,1,"","graph_graphson3_row_factory"],[18,7,1,"","graph_object_row_factory"],[18,7,1,"","graph_result_row_factory"],[18,7,1,"","single_object_row_factory"],[18,7,1,"","to_bigint"],[18,7,1,"","to_double"],[18,7,1,"","to_float"],[18,7,1,"","to_int"],[18,7,1,"","to_smallint"]],"cassandra.graph.GraphOptions":[[18,2,1,"","graph_language"],[18,2,1,"","graph_name"],[18,2,1,"","graph_read_consistency_level"],[18,2,1,"","graph_source"],[18,2,1,"","graph_write_consistency_level"],[18,2,1,"","is_analytics_source"],[18,2,1,"","is_default_source"],[18,2,1,"","is_graph_source"],[18,4,1,"","set_source_analytics"],[18,4,1,"","set_source_default"],[18,4,1,"","set_source_graph"]],"cassandra.graph.GraphProtocol":[[18,2,1,"","GRAPHSON_1_0"],[18,2,1,"","GRAPHSON_2_0"],[18,2,1,"","GRAPHSON_3_0"]],"cassandra.graph.GraphSON1Deserializer":[[18,4,1,"","deserialize_bigint"],[18,4,1,"","deserialize_blob"],[18,4,1,"","deserialize_date"],[18,4,1,"","deserialize_decimal"],[18,4,1,"","deserialize_double"],[18,4,1,"","deserialize_duration"],[18,4,1,"","deserialize_float"],[18,4,1,"","deserialize_int"],[18,4,1,"","deserialize_linestring"],[18,4,1,"","deserialize_point"],[18,4,1,"","deserialize_polygon"],[18,4,1,"","deserialize_time"],[18,4,1,"","deserialize_timestamp"],[18,4,1,"","deserialize_uuid"]],"cassandra.graph.GraphSON2Reader":[[18,4,1,"","deserialize"],[18,4,1,"","read"]],"cassandra.graph.Path":[[18,2,1,"","labels"],[18,2,1,"","objects"]],"cassandra.graph.Result":[[18,4,1,"","as_edge"],[18,4,1,"","as_path"],[18,4,1,"","as_vertex"],[18,2,1,"","value"]],"cassandra.graph.VertexProperty":[[18,2,1,"","label"],[18,2,1,"","properties"],[18,2,1,"","value"]],"cassandra.io":[[19,0,0,"-","asyncioreactor"],[20,0,0,"-","asyncorereactor"],[21,0,0,"-","eventletreactor"],[22,0,0,"-","geventreactor"],[23,0,0,"-","libevreactor"],[24,0,0,"-","twistedreactor"]],"cassandra.io.asyncioreactor":[[19,3,1,"","AsyncioConnection"]],"cassandra.io.asyncioreactor.AsyncioConnection":[[19,4,1,"","initialize_reactor"]],"cassandra.io.asyncorereactor":[[20,3,1,"","AsyncoreConnection"]],"cassandra.io.asyncorereactor.AsyncoreConnection":[[20,4,1,"","handle_fork"],[20,4,1,"","initialize_reactor"]],"cassandra.io.eventletreactor":[[21,3,1,"","EventletConnection"]],"cassandra.io.eventletreactor.EventletConnection":[[21,4,1,"","initialize_reactor"],[21,4,1,"","service_timeouts"]],"cassandra.io.geventreactor":[[22,3,1,"","GeventConnection"]],"cassandra.io.geventreactor.GeventConnection":[[22,4,1,"","initialize_reactor"]],"cassandra.io.libevreactor":[[23,3,1,"","LibevConnection"]],"cassandra.io.twistedreactor":[[24,3,1,"","TwistedConnection"]],"cassandra.metadata":[[25,3,1,"","Aggregate"],[25,3,1,"","BytesToken"],[25,3,1,"","ColumnMetadata"],[25,3,1,"","EdgeMetadata"],[25,3,1,"","Function"],[25,3,1,"","IndexMetadata"],[25,3,1,"","KeyspaceMetadata"],[25,3,1,"","LocalStrategy"],[25,3,1,"","MD5Token"],[25,3,1,"","MaterializedViewMetadata"],[25,3,1,"","Metadata"],[25,3,1,"","Murmur3Token"],[25,3,1,"","NetworkTopologyStrategy"],[25,3,1,"","ReplicationFactor"],[25,2,1,"","ReplicationStrategy"],[25,3,1,"","SimpleStrategy"],[25,3,1,"","TableMetadata"],[25,3,1,"","TableMetadataDSE68"],[25,3,1,"","TableMetadataV3"],[25,3,1,"","Token"],[25,3,1,"","TokenMap"],[25,3,1,"","UserType"],[25,3,1,"","VertexMetadata"],[25,6,1,"","cql_keywords"],[25,6,1,"","cql_keywords_reserved"],[25,6,1,"","cql_keywords_unreserved"],[25,7,1,"","group_keys_by_replica"]],"cassandra.metadata.Aggregate":[[25,4,1,"","as_cql_query"]],"cassandra.metadata.BytesToken":[[25,4,1,"","from_string"]],"cassandra.metadata.Function":[[25,4,1,"","as_cql_query"]],"cassandra.metadata.IndexMetadata":[[25,4,1,"","as_cql_query"],[25,4,1,"","export_as_string"]],"cassandra.metadata.KeyspaceMetadata":[[25,4,1,"","as_cql_query"],[25,4,1,"","export_as_string"]],"cassandra.metadata.LocalStrategy":[[25,4,1,"","export_for_schema"]],"cassandra.metadata.MaterializedViewMetadata":[[25,4,1,"","as_cql_query"]],"cassandra.metadata.Metadata":[[25,4,1,"","add_or_return_host"],[25,4,1,"","all_hosts"],[25,4,1,"","export_schema_as_string"],[25,4,1,"","get_host"],[25,4,1,"","get_host_by_host_id"],[25,4,1,"","get_replicas"]],"cassandra.metadata.NetworkTopologyStrategy":[[25,4,1,"","export_for_schema"]],"cassandra.metadata.SimpleStrategy":[[25,4,1,"","export_for_schema"],[25,5,1,"","replication_factor"]],"cassandra.metadata.TableMetadata":[[25,4,1,"","as_cql_query"],[25,4,1,"","export_as_string"],[25,5,1,"","is_cql_compatible"],[25,5,1,"","primary_key"]],"cassandra.metadata.TableMetadataDSE68":[[25,4,1,"","as_cql_query"]],"cassandra.metadata.TableMetadataV3":[[25,5,1,"","is_cql_compatible"]],"cassandra.metadata.TokenMap":[[25,4,1,"","get_replicas"]],"cassandra.metadata.UserType":[[25,4,1,"","as_cql_query"]],"cassandra.metrics":[[26,3,1,"","Metrics"]],"cassandra.metrics.Metrics":[[26,2,1,"","connected_to"],[26,2,1,"","connection_errors"],[26,4,1,"","get_stats"],[26,2,1,"","ignores"],[26,2,1,"","known_hosts"],[26,2,1,"","open_connections"],[26,2,1,"","other_errors"],[26,2,1,"","read_timeouts"],[26,2,1,"","request_timer"],[26,2,1,"","retries"],[26,4,1,"","set_stats_name"],[26,2,1,"","unavailables"],[26,2,1,"","write_timeouts"]],"cassandra.policies":[[27,3,1,"","AddressTranslator"],[27,3,1,"","ConstantReconnectionPolicy"],[27,3,1,"","ConstantSpeculativeExecutionPolicy"],[27,3,1,"","ConvictionPolicy"],[27,3,1,"","DCAwareRoundRobinPolicy"],[27,3,1,"","DSELoadBalancingPolicy"],[27,3,1,"","DefaultLoadBalancingPolicy"],[27,3,1,"","DowngradingConsistencyRetryPolicy"],[27,3,1,"","EC2MultiRegionTranslator"],[27,3,1,"","ExponentialReconnectionPolicy"],[27,3,1,"","FallthroughRetryPolicy"],[27,3,1,"","HostDistance"],[27,3,1,"","HostFilterPolicy"],[27,3,1,"","IdentityTranslator"],[27,3,1,"","LoadBalancingPolicy"],[27,3,1,"","ReconnectionPolicy"],[27,3,1,"","RetryPolicy"],[27,3,1,"","RoundRobinPolicy"],[27,3,1,"","SimpleConvictionPolicy"],[27,3,1,"","SpeculativeExecutionPolicy"],[27,3,1,"","TokenAwarePolicy"],[27,3,1,"","WhiteListRoundRobinPolicy"],[27,3,1,"","WriteType"]],"cassandra.policies.AddressTranslator":[[27,4,1,"","translate"]],"cassandra.policies.ConstantReconnectionPolicy":[[27,4,1,"","new_schedule"]],"cassandra.policies.ConstantSpeculativeExecutionPolicy":[[27,4,1,"","new_plan"]],"cassandra.policies.ConvictionPolicy":[[27,4,1,"","add_failure"],[27,4,1,"","reset"]],"cassandra.policies.DCAwareRoundRobinPolicy":[[27,4,1,"","distance"],[27,4,1,"","make_query_plan"],[27,4,1,"","on_add"],[27,4,1,"","on_down"],[27,4,1,"","on_remove"],[27,4,1,"","on_up"],[27,4,1,"","populate"]],"cassandra.policies.DefaultLoadBalancingPolicy":[[27,4,1,"","make_query_plan"],[27,4,1,"","populate"]],"cassandra.policies.DowngradingConsistencyRetryPolicy":[[27,4,1,"","on_read_timeout"],[27,4,1,"","on_unavailable"],[27,4,1,"","on_write_timeout"]],"cassandra.policies.EC2MultiRegionTranslator":[[27,4,1,"","translate"]],"cassandra.policies.ExponentialReconnectionPolicy":[[27,4,1,"","new_schedule"]],"cassandra.policies.FallthroughRetryPolicy":[[27,4,1,"","on_read_timeout"],[27,4,1,"","on_request_error"],[27,4,1,"","on_unavailable"],[27,4,1,"","on_write_timeout"]],"cassandra.policies.HostDistance":[[27,2,1,"","IGNORED"],[27,2,1,"","LOCAL"],[27,2,1,"","REMOTE"]],"cassandra.policies.HostFilterPolicy":[[27,4,1,"","distance"],[27,4,1,"","make_query_plan"],[27,4,1,"","predicate"]],"cassandra.policies.IdentityTranslator":[[27,4,1,"","translate"]],"cassandra.policies.LoadBalancingPolicy":[[27,4,1,"","check_supported"],[27,4,1,"","distance"],[27,4,1,"","make_query_plan"],[27,4,1,"","populate"]],"cassandra.policies.ReconnectionPolicy":[[27,4,1,"","new_schedule"]],"cassandra.policies.RetryPolicy":[[27,2,1,"","IGNORE"],[27,2,1,"","RETHROW"],[27,2,1,"","RETRY"],[27,2,1,"","RETRY_NEXT_HOST"],[27,4,1,"","on_read_timeout"],[27,4,1,"","on_request_error"],[27,4,1,"","on_unavailable"],[27,4,1,"","on_write_timeout"]],"cassandra.policies.RoundRobinPolicy":[[27,4,1,"","distance"],[27,4,1,"","make_query_plan"],[27,4,1,"","on_add"],[27,4,1,"","on_down"],[27,4,1,"","on_remove"],[27,4,1,"","on_up"],[27,4,1,"","populate"]],"cassandra.policies.SimpleConvictionPolicy":[[27,4,1,"","add_failure"],[27,4,1,"","reset"]],"cassandra.policies.SpeculativeExecutionPolicy":[[27,4,1,"","new_plan"]],"cassandra.policies.TokenAwarePolicy":[[27,4,1,"","check_supported"],[27,4,1,"","distance"],[27,4,1,"","make_query_plan"],[27,4,1,"","on_add"],[27,4,1,"","on_down"],[27,4,1,"","on_remove"],[27,4,1,"","on_up"],[27,4,1,"","populate"],[27,2,1,"","shuffle_replicas"]],"cassandra.policies.WhiteListRoundRobinPolicy":[[27,4,1,"","distance"],[27,4,1,"","on_add"],[27,4,1,"","on_up"],[27,4,1,"","populate"]],"cassandra.policies.WriteType":[[27,2,1,"","BATCH"],[27,2,1,"","BATCH_LOG"],[27,2,1,"","CAS"],[27,2,1,"","CDC"],[27,2,1,"","COUNTER"],[27,2,1,"","SIMPLE"],[27,2,1,"","UNLOGGED_BATCH"],[27,2,1,"","VIEW"]],"cassandra.pool":[[28,3,1,"","Host"],[28,1,1,"","NoConnectionsAvailable"]],"cassandra.pool.Host":[[28,5,1,"","address"],[28,5,1,"","datacenter"],[28,5,1,"","rack"]],"cassandra.protocol":[[29,3,1,"","_ProtocolHandler"]],"cassandra.protocol._ProtocolHandler":[[29,4,1,"","decode_message"],[29,4,1,"","encode_message"],[29,2,1,"","message_types_by_opcode"]],"cassandra.query":[[30,3,1,"","BatchStatement"],[30,3,1,"","BatchType"],[30,3,1,"","BoundStatement"],[30,3,1,"","PreparedStatement"],[30,3,1,"","QueryTrace"],[30,3,1,"","SimpleStatement"],[30,3,1,"","Statement"],[30,3,1,"","TraceEvent"],[30,1,1,"","TraceUnavailable"],[30,6,1,"","UNSET_VALUE"],[30,3,1,"","ValueSequence"],[30,7,1,"","dict_factory"],[30,7,1,"","named_tuple_factory"],[30,7,1,"","ordered_dict_factory"],[30,7,1,"","tuple_factory"]],"cassandra.query.BatchStatement":[[30,4,1,"","add"],[30,4,1,"","add_all"],[30,4,1,"","clear"],[30,2,1,"","serial_consistency_level"]],"cassandra.query.BatchType":[[30,2,1,"","COUNTER"],[30,2,1,"","LOGGED"],[30,2,1,"","UNLOGGED"]],"cassandra.query.BoundStatement":[[30,4,1,"","bind"],[30,5,1,"","routing_key"]],"cassandra.query.PreparedStatement":[[30,4,1,"","bind"]],"cassandra.query.QueryTrace":[[30,4,1,"","populate"]],"cassandra.query.Statement":[[30,5,1,"","routing_key"],[30,5,1,"","serial_consistency_level"]],"cassandra.timestamps":[[31,3,1,"","MonotonicTimestampGenerator"]],"cassandra.timestamps.MonotonicTimestampGenerator":[[31,4,1,"","_next_timestamp"],[31,2,1,"","warn_on_drift"],[31,2,1,"","warning_interval"],[31,2,1,"","warning_threshold"]],"cassandra.util":[[32,3,1,"","Date"],[32,3,1,"","DateRange"],[32,3,1,"","DateRangeBound"],[32,3,1,"","DateRangePrecision"],[32,3,1,"","Distance"],[32,3,1,"","Duration"],[32,3,1,"","LineString"],[32,3,1,"","OrderedMap"],[32,3,1,"","OrderedMapSerializedKey"],[32,3,1,"","Point"],[32,3,1,"","Polygon"],[32,3,1,"","SortedSet"],[32,3,1,"","Time"],[32,3,1,"","Version"],[32,7,1,"","datetime_from_timestamp"],[32,7,1,"","datetime_from_uuid1"],[32,7,1,"","max_uuid_from_time"],[32,7,1,"","min_uuid_from_time"],[32,7,1,"","ms_timestamp_from_datetime"],[32,2,1,"","sortedset"],[32,7,1,"","unix_time_from_uuid1"],[32,7,1,"","utc_datetime_from_ms_timestamp"],[32,7,1,"","uuid_from_time"]],"cassandra.util.Date":[[32,4,1,"","date"],[32,5,1,"","seconds"]],"cassandra.util.DateRange":[[32,2,1,"","lower_bound"],[32,2,1,"","upper_bound"],[32,2,1,"","value"]],"cassandra.util.DateRangeBound":[[32,4,1,"","datetime"],[32,4,1,"","from_value"],[32,2,1,"","milliseconds"],[32,2,1,"","precision"]],"cassandra.util.Distance":[[32,4,1,"","from_wkt"]],"cassandra.util.LineString":[[32,4,1,"","from_wkt"]],"cassandra.util.Point":[[32,4,1,"","from_wkt"]],"cassandra.util.Polygon":[[32,4,1,"","from_wkt"]],"cassandra.util.Time":[[32,5,1,"","hour"],[32,5,1,"","minute"],[32,5,1,"","nanosecond"],[32,5,1,"","second"],[32,4,1,"","time"]],"cqlengine.queryset":[[38,3,1,"","MaxTimeUUID"],[38,3,1,"","MinTimeUUID"]],cassandra:[[1,1,1,"","AlreadyExists"],[1,1,1,"","AuthenticationFailed"],[1,1,1,"","ConfigurationException"],[1,3,1,"","ConsistencyLevel"],[1,1,1,"","CoordinationFailure"],[1,1,1,"","DriverException"],[1,1,1,"","FunctionFailure"],[1,1,1,"","InvalidRequest"],[1,1,1,"","OperationTimedOut"],[1,3,1,"","ProtocolVersion"],[1,1,1,"","ReadFailure"],[1,1,1,"","ReadTimeout"],[1,1,1,"","RequestExecutionException"],[1,1,1,"","RequestValidationException"],[1,1,1,"","Timeout"],[1,1,1,"","Unauthorized"],[1,1,1,"","Unavailable"],[1,3,1,"","UserAggregateDescriptor"],[1,3,1,"","UserFunctionDescriptor"],[1,1,1,"","WriteFailure"],[1,1,1,"","WriteTimeout"],[1,6,1,"","__version__"],[1,6,1,"","__version_info__"],[2,0,0,"-","auth"],[3,0,0,"-","cluster"],[4,0,0,"-","concurrent"],[5,0,0,"-","connection"],[16,0,0,"-","decoder"],[17,0,0,"-","encoder"],[18,0,0,"-","graph"],[25,0,0,"-","metadata"],[26,0,0,"-","metrics"],[27,0,0,"-","policies"],[28,0,0,"-","pool"],[29,0,0,"-","protocol"],[30,0,0,"-","query"],[31,0,0,"-","timestamps"],[32,0,0,"-","util"]],cqlengine:[[37,0,0,"-","models"],[38,0,0,"-","queryset"]]},objnames:{"0":["py","module","Python module"],"1":["py","exception","Python exception"],"2":["py","attribute","Python attribute"],"3":["py","class","Python class"],"4":["py","method","Python method"],"5":["py","property","Python property"],"6":["py","data","Python data"],"7":["py","function","Python function"]},objtypes:{"0":"py:module","1":"py:exception","2":"py:attribute","3":"py:class","4":"py:method","5":"py:property","6":"py:data","7":"py:function"},terms:{"0":[1,2,3,4,6,9,10,12,14,15,16,18,25,27,30,31,32,34,35,37,38,42,43,44,46,47,48,50,55],"00":43,"000":10,"000077":43,"000153":43,"000309":43,"000368":43,"000422":43,"000480":43,"000669":43,"000755":43,"031ebb0":54,"04":0,"05":38,"0l":38,"0m":0,"1":[1,2,3,4,6,10,13,15,18,19,25,27,30,31,32,34,35,36,38,42,43,44,46,47,48,52,53,55],"10":[1,3,10,38,44,46,50],"100":[0,4,10,42,50],"1000":[0,4],"1004":0,"1005":0,"1006":0,"1007":0,"1008":0,"1009":0,"101":0,"1012":0,"1013":0,"1015":0,"1016":0,"1017":0,"1018":0,"1019":0,"1020":0,"1021":0,"1023":0,"1024":0,"1026":0,"1027":0,"103":0,"1031":0,"1033":0,"1036":0,"1039":0,"104":0,"1042":0,"1044":0,"1045":0,"1047":0,"1048":0,"105":0,"1051":0,"1054":0,"1056":0,"1057":0,"106":0,"1060":0,"1064":0,"1065":0,"1067":0,"1068":0,"1074":0,"10786":30,"1079":0,"108":0,"1081":0,"1082":0,"1087":0,"1089":0,"109":0,"1090":0,"1091":0,"1093":0,"10l":38,"110":0,"1100":0,"1104":0,"1105":0,"111":[0,36],"111111111111":9,"1117":0,"1118":0,"1119":0,"112":0,"1121":0,"1122":0,"1123":0,"1124":0,"1127":0,"1129":0,"1130":0,"1140":0,"1158":0,"116":0,"1161":0,"1162":0,"1163":0,"1166":0,"1172":0,"1174":0,"1177":0,"1181":0,"1183":0,"1185":0,"1186":0,"1187":0,"1189":0,"119":[0,32],"1192":0,"11e3":44,"11l":38,"120":0,"1203":0,"1204":0,"1205":0,"1207":0,"1212":0,"122":0,"1220":0,"1228":0,"123":[0,3,36,55],"1233":0,"1234":53,"1237":0,"1238":0,"1239":0,"124":0,"1240":0,"1241":0,"1243":0,"1244":0,"1245":0,"1248":0,"125":0,"1258":0,"126":0,"1260":0,"1264":0,"1265":0,"1266":0,"1269":0,"127":[3,25,35,38,42,43,44,48,53],"12l":38,"135":0,"138":0,"13l":38,"14":32,"141":0,"143":0,"144":0,"145":27,"147":0,"148":0,"14l":38,"15":[27,44],"150":0,"151":0,"155":0,"157":0,"159":0,"15l":38,"16":6,"160":0,"163":0,"164":0,"165":0,"166":0,"167":0,"168":[3,44],"16l":38,"17":[38,53],"173":0,"174":0,"175":0,"178":[0,30,54],"179":0,"17l":38,"180":0,"181":0,"182":0,"184":0,"185":0,"186":0,"187":0,"189":0,"18l":38,"190":0,"191":0,"192":[0,3,44],"194":0,"195":0,"196":0,"197":0,"1970":32,"198":0,"1982":38,"19l":38,"1e6":31,"1l":38,"1s":0,"2":[1,2,3,4,6,9,10,12,13,14,15,16,18,25,27,30,32,34,35,36,38,40,42,43,44,45,46,47,50,52,53,55],"20":38,"200":0,"2008":10,"2010":[35,38],"2011":38,"2012":38,"2013":[0,45],"2014":[0,38],"2015":0,"2016":[0,45],"2017":[0,45],"2018":0,"2019":0,"202":0,"2020":0,"2021":0,"204":0,"2048":53,"205":0,"206":0,"207":0,"208":0,"21":[38,54],"210":0,"211":0,"212":0,"213":0,"215":0,"218":0,"219":0,"22":46,"220":0,"222":0,"226":0,"229":0,"23":32,"230":0,"231":0,"234":0,"235":0,"238":0,"239":0,"24":3,"240":0,"241":0,"243":0,"244":0,"245":[0,40],"246":0,"249":0,"255":0,"258":0,"26":[0,38],"260":0,"2644bada":44,"266":0,"27":0,"272":0,"273":0,"276":[0,54],"277":0,"278":0,"279":43,"28":0,"280":0,"282":0,"283":0,"284":0,"285":0,"286":0,"288":0,"289":0,"29":0,"291":0,"292":[0,54],"294":0,"295":0,"296":0,"297":0,"298":0,"299":0,"2l":38,"3":[1,2,3,4,6,9,10,15,18,19,25,27,30,31,32,34,36,37,38,45,46,48,52,55],"30":[0,3,38,42,44],"300":0,"301":0,"302":0,"303":0,"305":0,"306":0,"309":0,"31":[0,38],"310":0,"311":0,"313":0,"315":0,"317":0,"318":[0,54],"319":0,"32":6,"322":0,"323":0,"324":0,"325":0,"327":0,"329":0,"331":0,"332":0,"333":0,"334":0,"335":0,"336":0,"337":0,"338":0,"340":32,"341":0,"342":0,"343":0,"344":0,"345":0,"346":0,"347":0,"348":0,"349":0,"351":0,"352":0,"353":0,"354":0,"357":0,"358":0,"360":0,"3600":3,"361":0,"362":0,"363":0,"365":0,"368":[0,54],"370":0,"371":0,"375":0,"377":0,"378":0,"379":0,"381":0,"385":[0,54],"386":0,"392":0,"393":0,"394":0,"395":0,"396":0,"397":0,"398":0,"3l":38,"4":[1,2,3,6,9,10,19,27,29,30,32,42,48],"400":[0,54],"405":0,"407":0,"408":[0,54],"409":0,"412":0,"413":0,"415":0,"416":0,"419fcdf":54,"42":[3,30,44],"422":[0,54],"429":0,"430":0,"432":0,"433":0,"434":0,"435":0,"438":0,"439":0,"442":0,"443":0,"444":0,"445":0,"447":0,"450":0,"451":0,"452":0,"454":0,"458":0,"459":0,"46":0,"464":0,"466":0,"467":0,"468":0,"469":0,"470":0,"471":0,"473":0,"475":0,"476":0,"477":0,"478":0,"479":0,"48":32,"480":0,"481":0,"482":0,"486":0,"487":0,"489":0,"495":0,"498":0,"4bd5909":54,"4l":38,"4th":0,"5":[1,3,9,10,19,27,38,44,45,46,53],"50":4,"500":10,"5000":[3,10,50],"501":0,"502":0,"503":0,"505":0,"507":0,"508":0,"509":0,"50m":38,"510":0,"512":0,"514":0,"520":0,"521":0,"522":0,"527":0,"528":0,"530":0,"531":0,"532":0,"533":0,"535":0,"537":0,"538":0,"542":0,"547":0,"548":0,"549":0,"550":0,"551":0,"553":0,"555":0,"556":0,"557":0,"559":0,"56":0,"560":0,"561":0,"562":0,"565":0,"566":0,"568":0,"569":0,"570":0,"572":0,"5723":0,"573":0,"574":0,"574266d":54,"576":0,"577":0,"578":0,"579":0,"580":0,"583":0,"584":0,"585":0,"589":0,"59":[0,32],"591":0,"593":0,"595":0,"596":0,"598":0,"599":0,"5l":38,"6":[1,3,6,10,19,25,27,30,38,45,46],"60":0,"600":0,"606":0,"607":0,"608":0,"609":0,"613":0,"614":0,"616":0,"617":0,"618":0,"619":0,"621":0,"622":0,"623":0,"626":0,"628":0,"630":0,"631":0,"636":0,"64":[6,9,27],"640":0,"642":0,"643":0,"644":0,"645":0,"646":0,"647":0,"648":0,"649":0,"65":1,"650":0,"653":0,"655":0,"656":0,"657":0,"66":[1,3],"665":0,"668":0,"669":0,"673":0,"676":0,"678":0,"682":0,"684":0,"686":0,"688":0,"69":0,"690":0,"692":0,"694":0,"697":0,"6l":38,"7":[1,3,6,10,27,45,46],"70":0,"700":0,"705":0,"706":0,"707":0,"708":0,"709":0,"71":0,"710":0,"714":0,"717":0,"719":0,"720":0,"721":0,"723":0,"724":0,"727":0,"728":0,"729":0,"73":0,"730":0,"732":0,"733":0,"734":0,"735":0,"736":0,"737":0,"739":0,"740":0,"741":0,"742":0,"743":0,"746":0,"747":0,"749":0,"75":0,"750":0,"751":0,"752":0,"754":0,"755":0,"759":0,"75percentil":26,"75th":26,"76":0,"761":0,"762":0,"763":0,"767":0,"768":0,"769":0,"77142":43,"772":0,"773":0,"774":0,"774000":38,"775":0,"778":0,"781":0,"782":0,"785":0,"7857":0,"78723":[3,55],"788":0,"789":0,"79":0,"793":0,"794":0,"798":0,"799":0,"79efe97":54,"7l":38,"8":[1,3,6,17,31,45,46,48],"80":0,"804dea3":0,"805":0,"808":0,"81":0,"810":0,"812":0,"813":0,"814":0,"819":0,"82":0,"827":0,"829":0,"831":0,"833":0,"836":0,"837":0,"838":0,"839":0,"84":0,"840":0,"843":0,"846":0,"848":0,"852c":44,"853":0,"86":0,"860":0,"861":0,"862":0,"863":0,"86400":9,"865":0,"868":0,"872":0,"8733":40,"877":0,"88":0,"885":0,"888":0,"89":0,"891":0,"892":0,"893":0,"894":0,"895":0,"897":0,"89fb":44,"8l":38,"9":[1,9,38],"90":0,"900":0,"901":0,"903":0,"9042":[3,5],"91":0,"910":0,"915":0,"916":0,"92":0,"9223372036854775808":43,"93":0,"932":0,"934":0,"937":0,"940":0,"941":0,"944":0,"945":0,"946":0,"947":0,"95":0,"953":0,"955":0,"95percentil":26,"95th":26,"96":0,"963":0,"96489cc":54,"966":0,"968":0,"97":0,"973":0,"978":0,"98":0,"98percentil":26,"98th":26,"99":[0,26],"992":0,"993":0,"995":0,"996":0,"998":0,"99999":37,"999percentil":26,"99percentil":26,"99th":26,"9d98c8e":54,"9l":38,"9th":26,"abstract":[0,2,6,9,25,30],"boolean":[0,1,6,25,27,44,47],"break":[0,27,45,46,54],"byte":[0,6,38],"case":[0,3,4,8,9,27,32,34,35,44,49,52,53],"catch":0,"char":0,"class":[0,1,2,3,5,6,9,10,12,13,14,15,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,40,41,48,50,52,53,54],"default":[0,1,3,6,7,9,10,11,12,14,15,17,18,26,27,29,30,31,34,43,44,46,48,49,50,53],"do":[0,3,4,6,9,17,27,30,37,38,41,44,46,53,54,55],"enum":[10,13,27,32,33],"export":[0,25],"final":[3,44,53],"float":[0,3,6,10,15,18,26,27,37,38,44,54],"function":[0,1,3,8,10,12,17,25,27,29,32,41,44,52,53,54],"import":[0,2,3,4,6,10,11,12,29,30,34,35,37,38,39,41,42,43,44,46,48,50,52,53],"int":[0,3,6,7,8,15,18,25,31,32,38,44,47,54,55],"long":[0,32,44,46,55],"new":[0,1,2,3,4,6,7,10,21,25,27,30,31,32,34,36,38,39,40,42,44,48,50,53,54,55],"null":[0,10,17,36,38,44],"public":27,"return":[0,1,2,3,4,9,10,12,14,15,18,25,26,27,29,30,31,32,33,37,38,39,41,43,44,47,48,50,53,55],"short":[0,30,37],"static":[0,3,6,10,12,13,32],"super":37,"switch":[0,10,46],"throw":[0,3,30],"transient":0,"true":[0,3,4,6,7,8,9,10,15,18,25,27,30,31,34,35,36,37,38,40,43,44,47,48,52,53],"try":[0,1,3,8,9,27,37,39,41,44],"while":[0,3,27,30,37,40,50,54],A:[0,1,2,3,4,7,8,10,12,13,14,17,18,25,26,27,30,32,35,37,38,44,45,46],AND:[47,52],And:[9,53,54],As:[9,32,40,44,52,55],BY:37,Be:49,But:30,By:[1,3,9,10,27,29,34,38,43,44,46,50,53,54],For:[0,1,3,6,7,9,10,25,27,30,32,36,37,38,40,41,42,44,46,47,48,49,50,51,52,53,54],IF:[0,10,27,30,47,52,54],IN:[17,25,30],INTO:[3,4,30,44,47,55],IS:[0,38,40],If:[0,2,3,4,7,8,9,10,11,14,25,27,30,31,32,34,35,36,37,41,42,44,46,47,50,53,54],In:[0,3,27,29,34,38,40,44,46,52,53,54],It:[0,3,9,21,22,27,32,35,37,38,43,44,46,47,53],NOT:[0,38,47,52],No:45,Not:[0,32],ONE:[1,3,10,40,54],Of:3,On:[0,27,46],One:[10,41],Or:3,Such:27,THERE:40,That:38,The:[0,1,2,3,4,5,6,7,9,10,12,13,14,15,17,18,25,26,27,28,29,30,32,34,36,37,38,40,41,42,44,45,46,47,49,53,54,55],Then:53,There:[1,3,6,8,30,38,44,46,54],These:[0,3,6,9,27,29,30,32,40,41,49,53,54],To:[3,9,11,27,34,35,37,38,40,41,42,43,44,46,51,53,54],WITH:[37,52],Will:9,With:[0,35,43,53,54],_1:53,_2:53,_3:53,_4:53,_:42,__:[10,38,54],__abstract__:9,__compute_routing_key__:9,__connection__:[8,9,35],__contain:38,__default_ttl__:9,__del__:0,__discrimin:54,__discriminator_value__:[6,9,37,40],__ge__:0,__gt:38,__gte:38,__in:[0,38],__init__:[0,3,27,31,50,54,55],__keyspace__:[8,9,35,37],__le__:0,__len__:0,__like:38,__lt:38,__lte:38,__name__:43,__ne__:0,__options__:[9,38],__polymorphic_:54,__polymorphic_key__:40,__repr__:0,__table_name__:[9,37,40],__table_name_case_sensitive__:9,__type_name__:11,__version__:[1,46],__version_info__:1,_connect:0,_dsegraphson2rowfactori:12,_gremlingraphson2rowfactori:12,_messagetyp:29,_metadata:54,_new_tim:21,_next_timestamp:31,_not_set:3,_protocolhand:29,_protocolhandl:29,_replicationstrategi:25,_set_final_except:0,_set_result:0,_timeout_watch:21,a2:10,a2d3a98:54,abil:[0,27,42,54],abl:46,about:[0,3,25,30,37,41,44,46,53,54],abov:[3,29,34,35,41,44,49],absolut:[32,40],accept:[0,3,27,32,40,41],access:[0,3,9,26,30,37,44,54],accommod:[0,41],accomplish:[38,46],accord:[0,3],accordingli:0,account:[0,37],accumul:10,accur:25,acheiv:27,achiev:[27,34,53],acknowledg:27,across:[0,19,20,21,22,27,42,43,49],act:53,activ:[0,3,21,22],actual:[0,1,27,30,38,44,47],ad:[0,1,3,10,21,25,27,30,34,37,38,46,54],add:[0,3,7,8,10,14,27,30,34,54,55],add_al:[14,30],add_callback:[3,10,34,44,49,50],add_collback:0,add_errback:[3,44],add_execution_profil:[3,12,42],add_failur:27,add_or_return_host:25,add_queri:10,add_request_init_listen:3,add_tim:0,addit:[0,3,10,12,29,34,37,38,44,47,48,53,54],addition:[30,37,40,53],additional_write_polici:0,addr:[27,37],address:[0,1,3,5,11,25,28,30,33,37,43,44,53,54,55],address_is_ignor:27,address_transl:3,addresstransl:[0,27],adher:41,adjust:[0,40],advanc:53,advic:3,affect:[3,30,34],after:[0,3,4,10,20,27,30,34,37,38,40,43,44,46,49],afterward:54,ag:[3,30,38,44],against:[0,1,3,9,27,30,37,44,48,53],aggreg:[0,1,3,25],agnost:32,agre:0,agreement:[0,3],ahead:[3,44],aim:[35,42],algorithm:[36,46],alia:[6,12,25,32,40],alias:0,alic:30,align:0,aliv:[1,26,27],alive_replica:[1,27],all:[0,1,3,4,6,8,9,10,17,21,22,25,26,27,28,29,30,35,41,44,46,47,49,52,53,54],all_host:[25,42],all_object:38,all_replica:25,allow:[0,3,6,9,10,12,13,27,29,30,31,32,34,36,37,46,52,53,54,55],allow_beta_protocol_vers:29,allow_filt:[10,38],almost:44,along:[3,25,50],alpha:0,alphanumer:0,alreadi:[0,1,3,5,8,35,46],alreadyexist:1,also:[0,3,4,9,10,13,27,30,32,35,37,38,42,43,44,46,53,54],alter:[9,27,37],altern:[3,29,37,40,44,46,49,53],although:[44,54,55],althought:44,alwai:[0,3,15,18,27,41,44,46,47],ambigu:0,among:[1,27],amount:[0,4,27],an:[0,1,2,3,4,5,6,8,9,10,12,13,15,17,18,19,20,21,22,23,24,25,26,27,29,30,31,32,34,35,36,37,38,40,41,42,44,45,46,48,49,50,52,53,54,55],analysi:29,analyt:[0,3,15,18],analyticskeyspac:3,analyticskeyspace_prepar:3,andrew:[46,53],ani:[0,1,3,8,9,10,13,14,17,19,20,21,22,26,27,30,34,37,38,41,43,44,45,46,47,49,53,55],anomali:0,anoth:[27,34,35,38,44,53,54],anymor:[38,54],anyth:[34,41],anywai:46,apach:[38,46,54],api:[0,32,37,41,42,45,46,48,49,53],app:[39,43],appear:47,append:[4,10,25,38,44],appli:[0,3,9,10,14,30,36,41,42,44,46,47,48,55],applic:[0,3,6,27,39,40,41,44,46,49,50,54],approach:[41,45],appropri:[3,37,46,53],april:0,apt:46,ar:[0,1,3,4,6,7,8,9,10,15,18,21,25,26,27,28,29,30,32,34,36,37,40,41,42,43,44,45,46,47,48,50,53],arbitrari:[6,32],archflag:46,architectur:46,arg:[3,4,6,9,10,19,20,21,22,23,27,32,34],arg_typ:1,argument:[0,1,3,4,7,9,10,15,18,27,30,31,32,34,35,44,46,53,54],argument_typ:1,arm:0,around:[0,9,32,40,41,54],arrai:[29,38],arriv:3,as_cql_queri:[0,25],as_edg:[15,18],as_graph_stat:14,as_path:[15,18],as_vertex:[15,18],ascend:[10,38],ascii:[0,6,44],ask:[45,48],assert:[6,36,52],assertionerror:38,assign:[0,6,11,37],associ:[0,3,54],assum:[3,21,22,38,41,53,54],assumpt:41,astimezon:41,astra:0,async:3,asynchron:[0,3,30,43,49],asyncio:[0,33],asyncioconnect:19,asyncioreactor:33,asyncor:[0,33,46],asyncoreconnect:[0,20],asyncorereactor:[0,33],atexit:0,atlassian:27,atom:[27,30],attach:[0,3,15,18,34,44,49,50],attempt:[0,1,3,4,5,27,34,41,43,44,54],attr_kwarg:3,attribut:[0,3,6,8,9,10,11,15,18,25,27,29,30,31,37,38,40,42,44,47,54,55],attributeerror:0,aug:0,august:0,auth:[0,33,53,54],auth_provid:[2,3,53],authent:[0,1,3,33],authenticationfail:[1,2],author:[1,53],authorization_id:53,authprovid:[0,2,3,53],auto:35,automat:[0,1,3,35,37,38,44,46,50],automobil:[10,35,38],automobile2:10,avail:[0,3,10,30,38,45,46,52,54],avoid:[0,3,27,40,43,46],aw:27,awai:[3,30],awar:[0,3,26,27,41,46,53,54],ayncoreconnect:0,b:[3,4,12,14,15,18,34,35,36,38],back:[0,6,9,32,38],backoff:0,backpressur:0,backup:38,backward:[3,18,25,54],bad:0,badli:0,balanc:[0,3,33,42,54],bar:44,bark_all_night:37,base:[0,1,3,9,12,26,27,29,30,32,37,40,43,44,47,52,53],base_delai:27,basegraphrowfactori:12,basi:[0,54],basic:[0,3,12,37],batch:[0,1,3,9,10,12,14,25,27,33,35,38,48],batch_log:27,batch_obj:10,batch_object:9,batch_r:10,batch_typ:[10,30,34],batchqueri:[0,10,34,36,38],batchstat:[0,1,3,30,54],batchtyp:[0,10,30,34],bb984ee:54,beat_init:39,becam:[0,40],becaus:[0,3,4,15,18,27,30,32,40,41,44,46,52,54],becom:[0,3,8,49,54],been:[0,3,5,9,26,27,30,34,35,40,54],befor:[0,1,3,9,10,27,29,30,40,43,44,49,50,54],begin:[0,10,13,44],behav:32,behavior:[0,3,6,27,44,54],behind:[27,41],being:[0,3,6,26,30,36,42,44,46,47],below:[3,4,10,27,29,36,37,38,40,46,47,49,54],benchmark:[0,49],benefit:54,best:[27,44,51,53],beta5:1,beta:[1,46],beta_vers:1,better:[0,27,46,49],between:[0,2,6,29,30,46,52],bewar:27,beyond:37,big:[0,52],bigint:[6,15,18,44],binari:[0,6,30],binary_typ:29,bind:[0,3,12,30,43,44],bit:[6,32,46],bitmap:29,blacklist:27,blacklist_filter_polici:27,blah:44,blake:[9,38],blank:9,blind:[9,10],blindli:10,blist:0,blob:[0,6,17,44,52],block:[0,3,4,34,44,49],blog:49,bob:[3,30,44],bodi:[0,29],bool:[6,7,8,10,25,44,52],bootstrap:[0,26],bop:0,borrow_connect:0,both:[0,3,38,39,44,46,53],bound:[3,14,30,32,43,49],bound_stmt:3,boundstat:[0,30,44,54],bracket:47,brew:46,broadcast_address:27,broadcast_rpc_address:25,broadcast_rpc_port:25,broken:0,brought:54,brows:27,brute:27,bu:0,bucket_high:9,bucket_low:9,buffer:[0,17,44],bug:[40,45,54],build:[0,25,40,44,46,49],built:[0,32,42,46,49,54],bulk:12,bulkset:0,bump:0,busi:[3,28],bypass:[0,3,8,30],bytearrai:[0,17,44],bytebuff:0,bytecod:12,byteorderedpartition:[0,25],bytesio:0,bytestoken:25,c0:52,c:[0,6,12,25,27,38,53],ca:[0,27,53],ca_cert:53,cach:0,cacreateseri:53,cakei:53,calcul:0,call:[0,2,3,5,9,10,17,19,20,21,22,27,31,34,37,38,41,44,48,50,53],callabl:[6,10,12],callback:[0,3,10,44,49,53],callback_arg:3,callback_kwarg:3,camera:38,can:[0,1,3,4,6,8,9,10,13,14,15,17,18,21,25,27,29,30,31,32,34,35,37,38,39,41,42,43,44,45,46,48,49,50,52,53,54,55],cancel:0,cannon:40,cannot:[0,27,30,32,38,42],capabl:50,captur:[0,46],car:38,cardin:[15,18],care:[3,8],carri:34,cass_driver_build_concurr:46,cass_driver_no_cython:46,cass_driver_no_extens:46,cass_server_vers:0,cass_typ:32,cassandra:[0,33,34,35,36,37,38,39,40,42,43,46,48,49,50,52,53,55],cassandra_init:39,cassandra_vers:0,cast:44,cat:[37,40,53],caus:[0,3,10,26,37,47],caution:[8,37],caveat:27,cc94073:54,cdc:[0,27],cdef:0,ceas:27,ceil:1,celeri:48,cell:43,center:30,cento:[0,46],central:41,cert:53,cert_countri:53,cert_org_nam:53,cert_ou:53,cert_req:53,cert_requir:53,cert_valid:53,certain:[13,27,40,46],certfil:53,certif:[0,53],chain:34,challeng:[2,46],chanc:27,chang:[0,3,6,9,10,25,27,30,31,36,37,38,43,44,45],changelog:45,charact:[0,6,44],charl:30,check:[0,3,9,10,27,37,46,52,54],check_hostnam:[0,53],check_support:27,checkout:46,checksum:0,child:[0,27,43],child_polici:27,choic:[46,49],choos:[15,18,27,54],chosen:3,chunk:0,circuit:0,circumst:0,citi:54,civic:[10,35,38],cl:[0,10,21],clang:46,classic:0,classmethod:[1,9,15,18,19,20,21,22,25,29,32],claus:[0,10,25,37,47,54],clean:[0,39,46,54],cleanup:[0,20],clear:[0,14,27,30],clearer:41,client:[0,1,2,3,8,27,29,41,42,45,52],client_encryption_opt:53,client_protocol_handl:[3,29],clock:32,clock_seq:32,clone:[3,42],close:[0,3,5],closur:0,cloud:[0,3,27,45],cluster1:35,cluster2:[10,35],cluster3:35,cluster:[0,2,4,5,6,7,9,10,12,15,18,19,20,21,22,25,26,27,29,30,33,35,37,38,39,43,46,48,49,51,53,55],cluster_opt:7,clustering_kei:38,clustering_ord:[6,37],clustertest:0,cn:53,code:[0,1,34,39,45,53,54,55],codebas:0,coerc:6,coincid:0,col:[0,47],col_nam:9,collect:[0,3,8,10,15,25,26,30,32,38,45,54],collis:0,colnam:[3,10,30],column:[0,8,9,10,11,13,17,25,30,33,35,36,37,38,44,47,48,54,55],column_family_nam:9,column_nam:[10,15,18,38],columnmetadata:[25,54],com:[6,10,52,53],combin:[0,3],come:0,comma:44,command:[0,35,46],comment:[9,10,37],comment_id:[10,37],common:[0,40,46,53,54],commun:[0,5,46],compact:[0,9,52],compar:[0,30,32,45],comparison:[0,6],compat:[0,3,18,25,33,54],compil:[0,29,46,49],complain:37,complet:[0,1,2,3,4,11,27,30,34,37,40,43,44,49,53],complex:[0,42,46],compliant:0,compon:[0,10,25,30,32,53],compos:29,composit:[0,30,38],compositetyp:0,compound:6,compress:[0,3,29],compressor:29,compris:[1,29],comput:[0,3,9,43],concern:41,concis:15,concurr:[0,3,8,30,33,43,44,49],condit:[0,1,3,8,10,30,45],conf:53,config:[0,53],configur:[0,1,2,3,5,7,9,15,18,27,31,42,44,45,52],configurationexcept:1,confirm:0,conflict:36,confus:[40,54],conn:35,connect:[0,1,2,3,4,8,9,10,11,12,19,20,22,23,24,26,27,30,33,37,38,39,40,42,45,46,48,51,52,53,54,55],connect_timeout:[0,3],connect_to_remote_host:3,connected_to:26,connection_class:[3,46,53],connection_error:26,connection_exc:27,connectionbusi:5,connectionexcept:[0,5],connectionshutdown:5,consensu:1,consid:[0,1,3,18,27,44,47,49,53,54],consider:[37,49],consist:[0,1,3,7,10,27,30,32],consistency_level:[3,15,18,30,42,44],consistencylevel:[0,1,3,7,10,15,18,26,27,30,40,44],consit:0,constant:[0,53],constantreconnectionpolici:[0,27],constantspeculativeexecutionpolici:[0,27,44],constrain:[4,10],constraint:[9,37],construct:[0,9,12,32,41,42,44],constructor:[0,3,6,38],consult:37,consum:[0,4,54],consumpt:[0,49],contact:[0,3,27,44],contact_point:[0,3,7,27,53],contain:[0,3,6,9,10,13,17,27,32,37,38,41,47,50,52],contains_kei:13,contains_valu:13,contend:0,content:[0,10,29],context:[0,3,8,9,10,12,15,18,34,39,46,49,53],contextqueri:[0,10,35],contin:0,continu:[0,2,27,50],continuous_paging_opt:3,contract:[0,29],control:[0,3,4,27,30,40,49,53],control_connection_timeout:3,conveni:[3,15,18,30,38],convent:37,convers:[15,18,40,41,54],convert:[0,13,15,17,18,32,40,41,54],convict:27,conviction_policy_factori:3,convictionpolici:27,coord:32,coordin:[1,3,4,27,32,43],coordinationfailur:1,copi:42,copyright:0,core:[0,3,4,38,40,46,49],core_connect:3,correct:[0,9,41],correctli:[0,3],correspond:[2,4,6,8,37],cost:[0,9,10,38],costli:46,could:[0,10,54],count:[0,9,10,26,27,36,38,48],counter:[0,6,26,27,30,37,44],countri:45,cours:3,cover:[37,43],coverag:0,cpu:[0,4,44,49],cpython:[0,3,46],cql3:[36,38,45],cql:[0,1,6,9,10,11,13,15,17,18,25,30,32,36,37,38,40,41,47,48,52,54,55],cql_cluster:39,cql_encode_all_typ:17,cql_encode_byt:17,cql_encode_d:17,cql_encode_datetim:17,cql_encode_list_collect:17,cql_encode_map_collect:17,cql_encode_non:17,cql_encode_object:17,cql_encode_sequ:17,cql_encode_set_collect:17,cql_encode_str:17,cql_encode_tupl:[17,54],cql_encode_unicod:17,cql_keyword:25,cql_keywords_reserv:25,cql_keywords_unreserv:25,cql_refer:10,cql_session:39,cql_use:6,cql_version:[0,3],cqlcollect:13,cqle:0,cqlengin:[0,33,34,35,36,37,38,39,43,45,48,54],cqlengine_batch:34,cqlengine_test:38,cqlengineexcept:[0,40],cqltype:54,cqluseudt:6,crash:0,creat:[0,1,2,3,5,6,7,8,9,10,12,25,27,30,32,34,35,36,37,38,41,43,44,47,48,49,52,53,54,55],create_default_context:53,create_execution_profil:12,create_keyspac:40,create_keyspace_network_topolog:[8,40],create_keyspace_simpl:[8,40],create_simple_keyspac:35,created_at:[34,48],creation:[0,3,4,25,38],credenti:[0,3,53],credit:44,crt:53,crt_sign:53,crypto:53,csr:53,cstringio:0,cumbersom:41,current:[0,1,3,10,12,26,27,30,31,38,42,43,46,50,54],current_pag:3,current_row:3,custom:[0,1,3,6,10,17,27,30,33,41,42,44,46],custom_index:6,custom_payload:[3,15,18,29,30],cut:0,cute:37,cycl:3,cython:[0,29],cython_protocol_handl:3,cythonprotocolhandl:3,d:[3,6,10,30,41,44],daemon:0,dai:[6,27,32,53],dash:0,data:[0,1,3,9,10,27,30,33,37,38,41,43,44,52,54,55],data_retriev:[1,27],databas:[6,8,9,34,37,38,41,42],datacent:[0,1,27,28],dataset:[0,10,38],datastax:[0,6,10,18,27,44,45,46,48,53,54],datastream:38,datatyp:0,date:[0,6,17,32,44,45,54],daterang:[0,32],daterangebound:32,daterangeprecis:32,datetim:[0,6,10,17,32,34,36,38,40,41,44,48],datetime_from_timestamp:32,datetime_from_uuid1:32,datetyp:0,david:13,daylight:41,days_from_epoch:32,db:0,db_field:[0,6],dc:[0,3,27,54],dc_name:8,dc_replication_factor:25,dc_replication_map:8,dcawar:0,dcawareloadbalancingpolici:0,dcawareroundrobinpolici:[0,3,27,42],dclocal_read_repair_ch:0,dct:0,dd:[17,32],ddl:0,dead:33,deadlock:[0,4],deal:[0,41,42,49,54],debian:[0,46],debug:[0,3],decemb:0,decid:27,decim:[0,6,10,38,44],decimaltyp:0,decis:[0,26,41],declar:[11,37],decod:[0,3,29,30,33,54],decode_messag:29,decomiss:0,decommiss:[0,27],decompress:29,decompressor:29,decor:0,decrement:6,deem:41,def:[3,27,34,37,39,43,44,50,53,54,55],defacto:41,default_bit:53,default_consistency_level:[0,3,7,42],default_fetch_s:[3,50],default_keyspac:[0,7],default_retry_polici:[3,27,42,43],default_serial_consistency_level:[0,3,42],default_time_to_l:[0,38],default_timeout:[3,42],defaultloadbalancingpolici:[0,27,54],defer:[0,10,27],defici:41,defin:[0,1,2,3,6,8,9,10,15,18,25,27,30,33,35,38,40,42,44,45,48],definit:[0,3,6,15,29,38,40],defunct:[0,3,5],degre:13,delai:[0,27,44],deldyck:37,delet:[0,8,9,10,27,30,34,38],delete_keyspac:40,deliv:3,deliveri:3,demand:0,demonstr:53,dep:0,depend:[0,2,41,43,47,49],deploy:53,deprec:[3,9,16,27,53],deprecationwarn:[0,54],depth:0,dequ:0,deriv:[32,37,40,42,46,54],derivi:9,desc:37,descend:[10,37,38],describ:[1,27,29,32,38,40,41,53],descript:[0,3,15,18,27,30,34,43,48,53],descriptor:0,deseri:[0,15,18,33,41],deserialize_bigint:[15,18],deserialize_blob:[15,18],deserialize_d:[15,18],deserialize_decim:[15,18],deserialize_doubl:[15,18],deserialize_dur:[15,18],deserialize_float:[15,18],deserialize_int:[15,18],deserialize_linestr:[15,18],deserialize_point:[15,18],deserialize_polygon:[15,18],deserialize_tim:[15,18],deserialize_timestamp:[15,18],deserialize_uuid:[15,18],design:[44,49],desir:[3,10,27,34],despit:10,destroi:0,detail:[0,1,3,9,10,30,37,41,42,43,44,49,52,53,54],detect:[0,40],determin:[6,9,27,30,44],determinist:0,dev:[46,52],devel:46,deviat:26,devic:0,dict:[0,1,3,6,7,8,9,12,15,17,18,25,26,29,30,37,44,47,52,53],dict_factori:[0,3,7,16,30,54],dictionari:[0,6],dictlik:32,did:[5,10,27],didn:10,differ:[0,3,10,29,30,32,36,37,38,42,44,53,54],digest:27,dir:0,directli:[3,4,17,29,30,44,46,53],disabl:[0,3,9,10,46,52],disable_shardaware_port:52,discontinu:0,discourag:3,discov:[0,3,27,44],discoveri:0,discrimin:[6,9,37],discriminator_column:[6,37,40],discuss:[3,6,11,30,37,45,47,49],disentangl:0,disk:6,dispos:3,disproportion:27,distanc:[13,27,32],distant:27,distinct:[0,10,15,18],distinct_field:10,distinguish:0,distinguished_nam:53,distribut:[0,27,38,46],distrimin:37,distriminator_column:37,dll:0,dn:27,doc:[0,1,6,10,37,38,41,52,53],document:[0,6,27,32,41,42,45,46,48,53,54],doe:[0,3,10,17,32,34,38,40,44,46,47,55],doesn:[0,31,54],doesnotexist:[0,10],dog:[37,40],dollar:0,don:[0,10,38,44,49,55],done:[0,3,37,41,43,53,54],dont:0,doubl:[0,6,15,18,32,44,49,54],double_precis:[40,54],down:[0,3,33,46],downgrad:[0,27],downgradingconsistencyretrypolici:[0,27,44],drain:0,drift:31,driven:8,driver:[0,1,3,5,7,10,18,26,27,28,29,30,37,38,40,41,44,46,47,48,49,50,51,52,53,55],driverexcept:1,drop:[0,6,8,29],drop_keyspac:[8,40],drop_tabl:8,drope:0,dsa:0,dse:[0,1,3,6,12,14,15,18,32],dse_graph:54,dse_graph_query_languag:12,dse_graph_query_protocol:12,dse_v1:[0,1],dse_v2:1,dsegraph:12,dsegssapiauthprovid:[0,53],dseloadbalancingpolici:[0,27,54],dseplaintextauthprovid:53,dsesessionremotegraphconnect:12,dsl:12,dt:32,due:[0,1,10,26,34,49],duplic:0,durabl:3,durable_writ:8,durat:[0,30,32],durationtyp:0,dure:[0,1,2,3,5,9,40,46],dynam:[0,3],dynamiccompositetyp:0,e0b9a54a6d93:44,e16a073:54,e:[3,8,9,10,12,15,18,27,30,43,46],each:[1,2,3,4,6,9,27,30,36,37,38,41,44,50,54,55],each_quorum:1,eagain:0,eai:0,earlier:[0,21,37],eas:35,easi:[0,37,38],easier:[38,42,46],easiest:[41,46],easili:[0,10,41],eat:37,ec2:0,ec2multiregiontransl:27,ed:0,edg:[0,15,18,25],edgemetadata:25,effect:[0,3,8,34,53],effici:[0,29],effort:[0,40,53],eggleston:9,either:[2,3,15,18,32,37,38,41,45,46],element:[0,3,10,15,18,25,32,38,44],elementmap:0,els:[4,39,50],em1:[34,48],em2:[34,48],em3:[34,48],em4:48,em5:48,em6:48,em7:48,em8:48,email:44,emit:[3,40,46],empti:[0,2,3,25,47],en:[6,10],enabl:[0,3,10,44,52,53,54],enable_shard_aware_driv:52,encod:[0,3,6,15,18,29,33,41],encode_messag:29,encount:[0,3,10],encrypt:[0,53],end:[0,10,34],endian:0,endless:0,endors:45,endpoint:[5,25,27,28,53],endpoint_factori:3,endpoint_or_address:25,endpointfactori:[5,53],enforc:[0,37],engag:46,engin:[0,3],enough:[1,30],ensur:[0,3,4,9,27,39,46,53],enterpris:52,entir:[0,3,4,10,14,25],entiti:0,entri:[10,13,17,54],entry_eq:13,environ:[8,27,46],eof:53,ep:[3,44],epoch:[0,31,32,41],eq:0,equal:[0,3,6,30,38],equival:[9,36,41,44],errback:[0,3,44,50],errback_arg:3,errno:0,error:[0,1,3,4,5,6,10,27,44,50],error_code_map:1,errro:1,escap:[0,17],especi:[0,8,42,46],essenti:38,establish:[3,44],etc:[3,10,26,27,38],evaluate_challeng:2,even:[0,3,7,27,30,41,42,44],evenli:27,event:[0,3,4,21,27,30,33,39,43,44,46,50,53],eventlet:[0,33],eventletconnect:[21,53],eventletreactor:33,everi:[0,27,31,38,39,44],everyon:46,evict:0,evolv:42,ewouldblock:0,exact:2,exactli:[0,27,40],examin:32,exampl:[0,2,3,4,6,9,10,11,25,30,32,35,36,38,40,42,43,44,46,47,48,49,50,51,52,54,55],example1:48,example2:48,example3:48,example4:48,example5:48,example6:48,example7:48,example8:48,example_id:48,example_mapp:0,example_typ:[34,48],examplemodel:[34,48],exc:[3,50],exce:[0,50],exceed:[3,4],except:[0,3,4,5,6,7,9,10,15,18,27,28,29,30,32,33,34,37,38,39,44,50,53],excess:0,exclud:38,exclus:[7,32,45],exec_profile_default:[3,42,44],exec_profile_graph_analytics_default:3,exec_profile_graph_default:[3,12,54],exec_profile_graph_system_default:3,exect:0,execut:[0,1,3,8,9,10,12,14,15,18,25,27,29,30,33,35,37,38,43,45,47,49,50,52,55],execute_a:[3,53,54],execute_async:[0,3,4,29,43,44,49,50],execute_concurr:[0,4,49],execute_concurrent_with_arg:[4,49],execute_graph:[3,15,18],execute_graph_async:3,execute_on_except:[10,34],execution_profil:[3,4,12,14,42,44],execution_profile_clone_upd:[3,42],executionprofil:[0,3,12,42,44],executionresult:4,executor:0,executor_thread:3,exhaust:[0,27],exist:[0,1,3,8,9,10,27,28,42,47,48,52,54],exit:0,expand:0,expect:[0,5,9,43,47,53,54,55],expens:3,experi:4,experiment:[0,19],expir:3,explain:[0,42],explicit:[0,40,41],explicitli:[0,1,3,10,15,18,34,37,54],explod:42,explor:38,exponenti:[0,27],exponentialreconnectionpolici:[0,3,27],export_as_str:[0,25],export_for_schema:[0,25],export_schema_as_str:25,expos:[0,31,54],express:[4,13,32],extablish:3,extend:30,extens:[0,3,27,41,52],exterior:32,extern:41,extra:[0,25,30,46],extra_deserializer_map:[15,18],extract:[15,18],ey:45,f:3,facilit:29,factor:[0,8,25],factori:[3,12,33,47],fail:[0,1,3,4,7,14,15,18,26,33,34,37,44,47],failur:[0,1,7,9,26,33,34],fairli:37,fall:[0,32],fallback:[10,27,54],fallthroughretrypolici:27,fals:[3,4,6,7,8,9,10,15,18,25,27,30,47,48,52,53,54],falsei:27,falsi:27,famili:[0,5,9],faq:[43,45],fashion:3,faster:[0,33,46],favor:[27,40,52,54],feather:45,featur:[12,19,33,38,40,45,46,53],feb:0,februari:0,fedora:46,feedback:0,felcei:13,fetch:[0,3,10,30,38,44,50,54],fetch_next_pag:3,fetch_siz:[0,3,10,15,18,30,50,54],few:[3,44,46],field:[0,3,6,8,9,10,11,30,32,37,38,44,55],fieldnam:6,fierc:37,file:[0,40,49,53],fill:[15,18,30],filter:[0,6,9,27,33,35,48],finalis:1,find:[13,25,41,46],fine:55,finished_ev:50,finit:27,first:[0,3,4,6,7,9,27,36,37,38,40,44,45,46,48,50,53,54],first_nam:[9,37],first_pag:38,first_result:54,first_row:55,five:3,fix:[27,46,53,54],flag:[0,3,6,9,29,37,46,52],flake:0,flask:43,flat:38,flexibl:[0,45],flight:[0,5],flow:0,fluent:[0,33,46,54],fly:[0,4,9,10,35],fn:[3,10],focu:27,follow:[0,3,26,27,29,34,35,37,40,41,42,44,46,47,53,54],foo:[44,55],food:37,footprint:[4,38],forc:[0,27,53],force_token_rebuild:3,forev:[21,27,30],fork:[0,20,43,45,49],form:[1,17,32,44],format:[0,1,3,17,25,29,30,33,41,44,53,55],formerli:0,forward:[1,27,40],found:[0,10,25,30,45,49,53,54],foundat:45,four:32,fqdn:[0,53],fraction:32,frame:29,free:44,frequent:[27,44,45,48],from:[1,2,3,4,5,6,8,9,10,11,12,15,18,20,25,27,29,30,32,34,35,37,38,39,40,42,43,44,45,46,47,48,50,52,53,55],from_datetim:54,from_kei:0,from_str:25,from_valu:32,from_wkt:32,frozen:[0,32,55],frozenset:44,full:[0,30,54],full_replica:25,fulli:54,functionfailur:1,functon:38,further:[3,4,27,38,43,49,53],furthermor:27,fuse:46,futur:[0,3,6,7,30,31,40,43,44,46,49,50,54],fuzzi:13,g:[0,3,12,15,18,27,30],garbag:[0,54],gc:0,gc_grace_second:9,gcc:46,gen_client_cert:53,gener:[0,1,2,4,27,29,32,33,41,44,52,53,54],geo:[0,13],geom:0,geomet:0,geometri:[13,32],geospati:0,geounit:13,get:[0,3,8,9,10,25,27,38,46],get_all_query_trac:[3,54],get_control_connection_host:3,get_core_connections_per_host:3,get_credenti:53,get_execution_profil:[0,3],get_host:[0,25],get_host_by_host_id:25,get_lower_support:1,get_max_connections_per_host:3,get_max_requests_per_connect:3,get_min_requests_per_connect:3,get_query_trac:[0,3,43,54],get_replica:[0,25,43],get_stat:26,getstat:26,getter:[15,18],gevent:[0,33],geventconnect:[0,22],geventreactor:[0,33],gil:[0,49],github:[0,45,48,52],give:[3,27,53,55],given:[0,3,10,25,27,28,32,34,38,49],global:[0,7,43],go:[0,40,51],goal:[49,53],goe:0,good:[40,45],got:54,govern:[3,27],gracefulli:0,grant:53,graph:[0,3],graph_graphson2_row_factori:[15,18],graph_graphson3_row_factori:[3,15,18],graph_languag:[15,18],graph_nam:[12,15,18],graph_object_row_factori:[3,15,18],graph_opt:[0,3],graph_protocol:[3,12,14],graph_read_consistency_level:[15,18],graph_result_row_factori:[15,18],graph_sourc:[0,3,15,18],graph_traversal_dse_object_row_factori:12,graph_traversal_row_factori:12,graph_write_consistency_level:[15,18],graphanalyticsexecutionprofil:3,graphexecutionpolici:3,graphexecutionprofil:3,graphopt:[0,15,18],graphprotocol:[3,14,15,18],graphson1:[15,18],graphson1deseri:[15,18],graphson1seri:[15,18],graphson2:[0,15,18],graphson2read:[15,18],graphson3:[0,12,15,18],graphson3read:18,graphson:[0,12,14,15,18],graphson_1_0:[3,15,18],graphson_2_0:[14,15,18],graphson_3_0:[3,15,18],graphsonwrit:14,graphstat:[0,3,14],graphtravers:[12,14],graphtraversalsourc:12,greater:[27,50],greatli:0,greenlet:0,gremlin:[0,3,12,14,15,18,46],gremlinpython:[0,46],greplin:[0,26],groovi:[15,18],group:25,group_keys_by_replica:25,grow:0,gssapi:2,guarante:[0,27,30,54],guard:8,guid:[0,44,45,46,48,53],gx:0,h:[0,43],ha:[0,3,5,10,26,27,30,38,40,41,44,46,47,53,54,55],had:[0,40,54],handl:[0,2,3,9,10,12,29,33,38,39,41,43,44,46],handle_err:50,handle_error:[4,44,50],handle_fork:20,handle_pag:50,handle_result:3,handle_success:44,handle_writ:0,handler:[0,2,10,15,18,27,29,50],handshak:2,hang:[0,46],happen:[0,3,27],hard:46,has_more_pag:[0,3,50],hash:[0,38,46],hashabl:[0,32],hasn:0,have:[0,2,3,4,6,9,10,15,17,18,26,27,34,35,36,37,38,40,42,44,46,47,53,54,55],header:[0,29,46],healthmonitor:0,heap:0,heartbeat:0,help:[0,38,54],here:[3,9,10,34,35,37,38,39,40,41,46,48,53],hex:0,hh:32,high:[0,48,49],higher:[1,3,4,30,53,54],highli:44,highlight:54,hint:1,hit:[3,5],hold:[0,25,29],holder:44,homebrew:[0,46],honda2012:38,honda:[10,35,38],honor:[0,44],hook:[39,43],host1:27,host2:27,host3:27,host:[0,1,2,3,4,7,25,33,35,43,48,52,53,54],host_address:53,host_dist:3,host_id:25,hostconnect:0,hostdist:[0,3,27],hostfilterpolici:[0,27],hostnam:[0,27,53],hoststatelisten:3,hot:46,hour:32,how:[0,1,4,6,9,27,30,38,39,41,42,44,45,47,50,53,54],howev:[0,3,10,30,34,37,38,41,46,47,50,54,55],html:[6,10,38,48],http:[6,10,27,38,48,50,52],huge:49,human:[25,41],i:[8,10,15,18,27,30,38],id:[0,3,4,6,9,10,15,18,29,34,36,37,38,44,53,55],idea:27,ideal:[32,41],idempot:[33,44],identifi:[0,1,37,47],identitytransl:[3,27],idl:0,idle_heartbeat_interv:3,idle_heartbeat_timeout:[0,3],ids_to_fetch:44,ie:[13,50,53],if_exist:[9,10],if_not_exist:[9,10],iff:9,ifnotexistswithcountercolumn:40,ignor:[0,3,8,26,27,29,30,44],ignored_address0:27,ignored_address1:27,imagin:27,immedi:[1,3,34,44],immut:[0,32,48],impact:4,implement:[0,2,3,5,15,18,19,20,21,22,23,24,27,29,32,41,46,49,50,53,54],impli:[30,45],implicit:[0,10,54],implicitli:[3,8,37],importerror:39,impos:37,improv:[0,1,35,49,54],in_memori:52,inbetween:27,includ:[0,3,9,10,25,26,40,45,49,53,54,55],include_keyspac:9,inclus:3,incomplet:0,inconsist:0,incorrect:[0,44],incorrectli:[0,30],increas:[0,27,31,46],increment:6,incur:9,indefinit:0,independ:[32,53],indetermin:3,index:[0,3,6,25,37,38,48,54],indexmetadata:25,indic:[0,1,2,3,6,8,9,10,25,27,38,47,52],individu:3,inet:[0,1,25],inet_address:0,inet_ntop:0,inet_pton:0,infin:0,infinit:[0,27],inflat:29,influenc:27,info:[0,3,33,44],inform:[0,3,5,9,25,27,41],inherit:[0,6,9,11,42],init:[0,3,36,40],initi:[0,2,3,5,6,7,9,15,18,27,29,31,32,35,38,39,44,46,47,53],initial_respons:2,initialize_reactor:[19,20,21,22],inititi:40,inject:[3,42,46],inmemorycompactionstrategi:52,inplac:32,input:[0,30,40,41,42],insanc:41,insensit:9,insert:[0,1,3,4,9,10,30,32,36,37,41,44,47,54,55],insert_stat:55,insert_us:30,insid:[13,34,44],insight:0,inspect:[3,8],instal:[0,40,44,45,49,53],instanc:[0,2,3,6,9,10,13,15,18,25,26,27,30,34,38,44,48,50,53,54,55],instanti:[0,27,29,31,44],instead:[0,3,4,30,38,40,44,50,53,54],instruct:38,insuffici:[0,26],intact:42,integ:[0,6,10,11,13,17,31,32,35,36,37,38,41,48],integer_typ:32,integr:[0,29,40,41,45,46,48,54],intend:[9,31,32,46],intent:40,interact:[3,44],interfac:[0,2,27,50],interior:32,intern:[0,3,10,27,31,32,40,41,54],interpol:55,interpret:[0,30,36,38,54],intranod:52,intrins:41,introduc:[0,19,25,30,37,38,40,42,54,55],introduct:45,intruct:53,intstat:26,inupt:0,inv:[15,18],invalid:[0,1,26,30],invalidparametertypeerror:0,invalidrequest:1,invalidtypeparametererror:0,invit:40,invlabel:[15,18],invoc:46,invok:[0,3,40],involv:[30,38],io:[0,3,4,10,33,46,48,53],ip:[0,3,5,27,28,44,53],ipv4address:0,ipv6:0,ipv6address:0,irc:0,iron:40,is_analytics_sourc:[15,18],is_cql_compat:25,is_default_sourc:[15,18],is_graph_sourc:[15,18],is_idempot:[0,15,18,30,44],is_schema_agre:3,is_seri:0,is_shard_awar:52,is_shutdown:0,is_up:0,isbootstrap:27,isn:[0,9,10],isnotnul:38,isoformat:0,isol:27,issu:[0,2,27,31,32,36,54],item1:17,item2:17,item:[0,4,9,10,15,18,27,30,32,37,38,44],iter:[0,3,25,27,29,30,32,38,50,54],its:[0,2,3,5,9,19,20,23,24,27,30,32,37,42,46,53,54],itself:[46,54],jan:0,januari:0,java:27,jit:49,jitter:[0,27],jk:53,joe:[37,53],john:44,join:0,jon:[10,37,38],json:[3,12,15,18],json_data:[15,18],juli:0,jump:48,junctur:40,june:0,just:[0,3,6,25,27,32,34,37,40,44,46,50,52,55],k:[34,47,53],keep:[0,27],keepal:0,kei:[0,1,3,6,8,9,10,13,15,25,26,27,29,30,32,37,38,42,43,44,47,52,53,55],kept:4,kerbero:[0,53],kevin5000:37,kevin:37,key1:17,key2:17,key_typ:6,keyerror:0,keyfil:53,keyout:53,keyspac:[0,1,3,7,8,9,10,11,15,18,25,27,29,30,35,43,52,54],keyspace1:52,keyspace_nam:54,keyspacemetadata:[0,25],keystor:53,keystore_password:53,keyword:[0,3,6,7,9,10],kill:0,kimberli:9,kind:[0,27,54],kinit:53,klass:3,know:[3,27,36,54,55],known:[0,15,18,25,40,54],known_host:26,ks1:35,ks2:35,ks:35,ks_name:8,kwarg:[0,3,4,6,7,9,10,12,15,18,19,20,21,22,23,27,32,34,39,53],label:[15,18],lambda:53,languag:[12,15,18,40,45,49],larg:[0,3,4,10,32,38,45,54],largest:36,last:[0,1,3,27,31,38],last_act:3,last_host:1,last_nam:[9,37],lastest:36,latenc:[26,44,52],later:[0,1,9,27,44,50],latest:[0,54],latter:[3,50],layout:25,lazi:0,lazili:29,lazy_connect:[0,7],lazyprotocolhandl:29,lbp:0,lead:[0,34,49,54],leak:0,learn:[30,53],least:[6,26,27,30,35,37,46],leav:[0,3],left:[0,3,4,9,41,54],legaci:[0,6,40,48,53,54],len:[0,9,10,35],length:[6,27,30],less:[0,46],let:[0,3,54],letter:13,level:[0,1,3,4,10,15,18,27,30,33,41,48,53],leveledcompactionstrategi:9,lib:0,libev4:46,libev:[0,33],libevconnect:[3,23,46],libevreactor:[0,3,33,46],libevwrapp:0,librari:[0,19,20,41,46,53],licens:45,lifecycl:2,lightweight:[0,1,10,30,44,45],lighweight:27,like:[0,1,3,4,9,10,15,18,26,27,30,37,38,41,44,46,50,53,55],limit:[0,3,10,30,38,41,49],line:[0,19,44,46],linear:32,lineariz:30,linestr:32,link:[0,41,46],linux:46,list:[0,1,3,4,6,7,8,9,10,13,15,17,18,25,27,29,30,32,35,43,44,45,46,48,50,54],list_col:44,list_column:10,list_column__append:10,list_column__prepend:10,listen:[0,3],listen_address:0,liter:[0,15,17,18,30,41,44,54,55],live:[1,27,43],ll:[38,53],load:[0,3,9,10,15,18,33,37,38,40,42,52,53,54],load_balancing_polici:[3,27,42,44,52],load_cert_chain:53,load_verify_loc:53,loadbalancingpolici:[0,3,27,42],local:[0,1,3,27,30,41,42,43,44,54],local_dc:[0,27],local_on:[0,1,3,44],local_queri:42,local_quorum:[0,1,44],local_seri:[1,30,44],localhost:[7,10],localstrategi:25,localtim:41,locat:[3,40,53,55],lock:0,locked_execut:42,log:[0,3,8,27,30,31,44,45,54],log_error:3,log_result:3,logentri:34,logger:0,logic:[0,37,52],logo:45,longer:[0,1,54],look:[13,37,38,53],lookup:[0,25,27],loop:[0,3,4,21,33,44,46,53],lose:0,loss:0,lot:[0,52],low:[15,18,27,33],lower:[1,4,27,32,38,44],lower_bound:32,lowercas:0,lwt:[0,3,9,47],lwtexcept:[0,9,10,40],lz4:[0,46],m:[9,36],mac:[0,46],machin:44,madd:46,made:[1,3,5,27,38,44,54],mai:[0,2,3,4,6,7,27,30,32,37,38,43,44,46,49,53,54],main:[0,3,53,55],maintain:[0,3,30,32,37,54],major:[0,27,42,53,54],make:[0,1,3,10,25,27,37,40,41,42,43,44,45,46,48,51,53,54],make_query_plan:27,make_token_replica_map:0,manag:[0,3,6,9,10,11,28,33,34,37,42,46,48,54],mandatori:[0,3],mani:[0,1,3,4,27,44,49,50,53,54],manifest:[0,43,47],manipul:[0,3],manner:32,manual:[3,9,34],manufactur:[10,35,38],map:[0,1,3,8,10,13,15,17,18,25,29,30,32,33,37,38,44,48,54],map_column:10,map_column__remov:10,map_column__upd:10,mapper:[0,7,40,45],march:0,margin:4,mark:[0,3,5,33,44,45],marker:41,master:[0,3,52],match:[0,3,5,9,10,15,18,25,30,38,40,42,43,44,46,53,54,55],materi:[0,3,4,25,29,46,54],materializedviewmetadata:25,math:0,max:[0,3,5,26,44],max_attempt:[27,44],max_connect:3,max_delai:27,max_length:6,max_request:3,max_schema_agreement_wait:3,max_support:1,max_threshold:9,max_tim:38,max_uuid_from_tim:32,max_wait:[3,30],max_wait_sec:3,max_wait_sec_p:3,maximum:[1,3,6,27,32,38],maxtimeuuid:38,maxyear:[32,41],md5token:25,md:52,mean:[3,9,26,27,38,44],meaningless:38,meant:41,measur:[3,27],mechan:[0,2,3,27,53],median:26,meet:[26,27,53],member:[32,37],memori:[0,4,38,52,54],mention:[0,41,44],merg:40,mesh:54,messag:[0,1,2,3,5,29],message_types_by_opcod:29,meta:[0,3,37],metadata:[0,3,15,18,27,30,33,42,43,52],method:[0,2,3,9,10,27,29,30,35,36,37,38,41,43,44,46,49,52],metri:26,metric:[0,3,33],metrics_en:3,micro:32,microsecond:[0,31,54],middl:13,might:[0,3,30,50,53],migrat:[48,54],millisecond:[0,17,32,41],millsecond:41,min:[0,26,43],min_length:[0,6],min_request:3,min_support:1,min_threshold:9,min_tim:38,min_uuid_from_tim:32,minim:[3,40,41,44],minimalist:32,minimum:[1,3,6,32,38],mintimeuuid:38,minut:[0,32,46],minyear:[32,41],mismatch:0,misplac:0,miss:[0,27],misspel:13,mistak:40,mitig:49,mix:[0,30],mke:0,mm:[17,32],mmmuuunnn:32,mno:46,mock:0,mode:0,model:[0,3,8,33,38,43,48,54],model__lik:38,modelexcept:40,modelqueryset:10,modern:0,modif:8,modifi:[0,1,8,9,10,32],modul:[0,9,11,18,19,20,40,46,49],monkei:[0,21,22,53],monkey_patch_loop:0,monoton:0,monotonictimestampgener:31,month:32,montonictimestampgener:0,more:[0,3,4,6,9,10,15,25,27,29,31,38,40,42,44,45,49,50,53,54],most:[3,27,30,37,40,41,43,50],mostli:[18,47],move:[0,3,30,54],ms:32,ms_timestamp_from_datetim:32,msg:29,much:[37,41,53,54],multipl:[0,3,10,12,14,15,18,27,34,35,44,48,49,54],multipleobjectsreturn:[0,10],multipli:13,multiprocess:0,multithread:0,murmur3:[0,3,46],murmur3partition:[0,25,46],murmur3token:[0,25],mussei:[46,53],must:[0,1,3,4,10,30,32,37,38,44,46,53,54,55],mutabl:3,mutat:48,mutual:[7,32],mv:27,my:53,my_callback:34,my_graph:12,my_tabl:44,my_user_id:30,mycf:3,mykeyspac:[3,30,44,54,55],mymod:36,mymodel:36,mystery_funct:34,mystorepass:53,mytabl:4,n:10,naiv:[6,41],name:[0,1,3,7,8,9,10,11,12,13,15,18,25,26,27,29,30,34,37,40,44,47,55],named_arg:34,named_tuple_factori:[0,3,16,30,54],namedt:38,namedtupl:[0,3,4,30,37,44,47,54,55],namedtuple_factori:0,nan:[0,32],nanosecond:[6,32,41],nativ:[0,1,15,18,29,37,45],native_shard_aware_transport_port:52,native_shard_aware_transport_port_ssl:52,native_transport_address:0,natur:2,necessari:[3,44,46,53],need:[0,1,3,6,12,27,30,32,34,35,36,37,38,39,44,46,49,52,53,54,55],neg:[0,32,38],negoti:2,nest:[0,32],net:27,network:[0,30,44],networktopologystrategi:[0,8,25],never:[0,27,34,47,49,54],neverretrypolici:3,new_authent:2,new_nod:0,new_plan:27,new_schedul:27,newkei:53,newli:[0,25,27],next:[0,3,21,27,42,48,50,53],next_pag:38,ngdg:0,nice:0,nicer:38,no_compact:0,no_valid_replica:25,noconnectionsavail:28,node1:42,node1_profil:42,node1_whitelist:42,node2:42,node2_profil:42,node:[0,1,3,5,25,26,28,30,32,33,44,52,53],node_domain:5,nodesync:0,nodetool:27,nohostavail:[0,3],nomenclatur:54,non:[0,3,6,10,32,33,37,44,45],nonblock:0,none:[0,1,2,3,4,5,6,7,8,9,10,11,12,14,15,17,18,25,26,27,30,32,36,38,39,41,43,44,47,50],nonetyp:0,nonexist:[0,1],normal:[0,3,9,10,12,27,30,32,41,44,50],nose:0,notabl:54,note:[0,3,4,7,8,9,10,19,27,30,32,35,37,38,40,41,42,44,45,50,53,54],noth:[0,25,27],notic:0,notif:0,notifi:3,nov:0,novemb:0,now:[0,31,34,36,38,40,41,44,48],nt:0,nullhandl:0,num:26,number:[0,1,3,4,5,9,10,26,27,40,42,44,46,47,50],numer:[0,41],numpi:29,numpyprotocolhand:29,numpyprotocolhandl:[0,29],o:[44,53],obj:[15,18],object:[0,3,4,12,15,17,18,25,26,27,30,31,32,34,35,36,37,41,42,43,44,45,49,50,54,55],obtain:[3,10,43,49],occur:[1,27,30,34,44,54],oct:0,octob:0,od:32,off:3,offer:[32,46,49,50],offici:[53,54],offset:32,often:37,ok:[27,53],old:[0,10,40],omit:[1,30],on_add:27,on_authentication_success:2,on_down:27,on_read_timeout:27,on_remov:27,on_request_error:[0,27],on_unavail:27,on_up:[0,27],on_write_timeout:[0,27],onc:[3,4,19,20,21,22,27,29,30,34,36,38,46,50,52],one:[0,1,2,3,6,10,13,26,27,30,32,35,36,37,38,42,44,52,53,54],ones:[10,40],onli:[0,1,3,4,5,6,7,8,9,10,18,19,27,30,31,34,37,38,40,41,44,45,46,47,52,53,54],onward:52,op:38,opaqu:3,opcod:29,open:[0,2,3,26,27,28,32,45],open_connect:26,openssl:53,oper:[0,1,3,5,8,9,10,15,18,30,32,33,35,44,47,54],operationtimedout:[0,1,3],opertaion:0,oppos:27,optim:[0,45,46,49],option:[0,1,2,3,5,7,9,10,11,12,14,25,29,30,33,38,40,42,44,47,48,49,52,53,54,55],option_map:25,options__contain:38,options_map:25,order:[0,1,4,6,10,25,27,30,32,34,37,41,54],order_bi:[10,38],ordered_dict_factori:[0,3,16,30,54],ordereddict:[0,3,30,32,44],orderedmap:[0,32],orderedmapserializedkei:32,orderedset:0,org:38,organ:45,origin:[0,3,38,54],os:46,oss:[0,27],other:[2,3,6,8,9,15,18,26,27,30,32,38,44,45,46,52,53,54,55],other_error:26,otherstuff:55,otherwis:[2,3,6,9,27,32,53],ou:53,our:[38,44,48,53],out:[0,1,4,9,27,32,34,36,38,40,41,44,53],outcom:47,output:[0,41],output_password:53,outsid:[0,6,27,32],outv:[15,18],outvlabel:[15,18],over:[3,27,29,38,49,50,53,54],overcount:27,overflow:[0,41],overflowerror:[0,32],overhaul:54,overhead:[0,4,34],overload:[0,1,6,26,27],overrid:[0,3,9,15,18,42,44,54],overridden:[0,3,50],overriden:0,overs:3,overview:[40,41,45,48],overwrit:10,own:[3,9,37,53],owner:37,owner_id:[37,40],pack:[0,30],packag:[0,2,32,41,46,48,53,54],page:[0,1,3,45,51],pagedresult:[0,50,54],pagedresulthandl:50,pagin:[0,38,50],paging_st:[3,50],pair:[0,29],panda:29,parallel:0,param:[0,4,13],paramet:[0,3,4,6,7,8,9,10,12,14,15,18,27,29,30,31,32,37,40,47,53,55],parameter:55,parent:[0,20],pars:[0,15,18,29,32,43,44],parser:[0,29],part:[0,8,10,30,35,40,41,46],parti:[2,3,41,48],partial:[0,21,22,30],particular:[0,3,25,27,30,52],particularli:38,partit:[0,6,10,25,27,30,38],partition:0,partition_kei:[6,10,30,38],pass:[0,2,3,4,6,7,9,10,25,29,30,34,36,37,38,39,47,48,52,53,54,55],passin:53,password:[2,53],passwordauthent:[2,53],patch:[0,21,22,41,53],path:[0,15,18,29,46,53],pattern:[37,49],paxo:30,payload:[0,1,3,30,33],peer:[0,5,25],peers_v2:0,pem:53,pend:0,pending_us:30,pep:0,per:[0,3,4,6,9,10,25,27,35,37,43,44,50,52,54],percentil:26,perform:[0,1,3,9,10,27,30,33,37,38,45,46,51],perhap:46,period:39,permiss:53,permit:27,persist:[0,15,18,27,41],person:[9,37,38],person_id:37,perspect:[2,27],pertain:3,pertin:47,pet:[37,40],pet_id:[37,40],pet_typ:[37,40],phase:[2,3,30,46],photo_id:[10,37],phrase:13,pick:[36,44],pip:[0,54],pk:[38,44],pk__token:[0,38],pk__token__gt:[0,38],place:[0,40,44,54],placehold:[3,15,18,30,44,55],placement:[0,8],plai:0,plain:53,plaintextauthent:2,plaintextauthprovid:[0,2,3,53,54],plan:[0,8,27,45],platform:[0,42],pleas:[0,3,6,9,11,27,37,43,45,53],plu:[38,47],plug:39,pluggabl:0,pmfstat:26,point:[0,3,6,26,27,32,41,44,53,54],polic:27,polici:[0,3,33,42,43,44,52,54],poll:[3,30,43],polygon:32,polymorphic_kei:40,pool:[0,1,3,33,54],pool_wait_timeout:3,popul:[0,3,27,30,38],port:[0,3,5,25,44,52],portion:[30,32],posit:[3,10,30,34,38,44,47,54],possibl:[0,3,9,21,27,31,32,37,38,41,46,50,53,54],post:[0,49],postfork:[39,43],potenti:0,pr:0,practic:44,practiv:10,pre:[0,46],preced:[3,27,34,47],precis:[0,6,17,32,40,41,54],predic:[0,27,33],predict:38,preemptiv:44,preexist:7,prefer:[0,27,41,44,46,54],prefix:[9,11,13],prematur:0,prepar:[0,3,4,27,33,41,43,53,55],prepare_on_all_host:3,prepared_stat:30,preparedstat:[0,3,30,44],preparemessag:0,prepend:[10,47,54],present:[0,7,10,30,41,42,43,46,47,54],preserv:[0,6,9,30,40],presist:37,pretti:49,preval:41,prevent:[0,10,40,44,46],previou:[0,3,53,54],previous:[0,40,42,54],previous_vers:1,price:[10,38],primari:[0,3,6,8,9,10,25,30,37,38,47,52,55],primary_host:27,primary_kei:[6,9,10,25,35,36,37,38,40,48],princip:[0,53],print:[3,9,10,12,30,32,35,37,41,42,43,44,46,48,52,55],prior:0,privat:[0,1,27],probabl:[27,38,53],problem:[0,3,26,43],process:[0,3,4,20,43,44,46,49,52,53,54],process_row:50,process_us:[3,4,44,50],produc:[2,4,15,18,38],product:[8,48,53,54],profil:[0,3,4,12,14,45],profile_long:44,programmat:3,project:[1,40,45,48,49],prompt:[46,53],proof:0,propag:[0,27,30],proper:[0,39,46],properli:[0,3,37,38,44],properti:[0,1,3,5,9,13,15,18,25,27,28,30,32,37],protect:0,protocol:[0,1,3,5,6,12,14,30,33,37,45,52],protocol_tl:[0,53],protocol_vers:[0,1,3,4,29,30,32,37,48,50,53,54,55],protocolerror:5,protocolhandl:[0,29],protocolvers:1,provid:[0,3,12,13,15,18,27,41,42,43,46,49,50,53,54],proxi:5,proxim:13,proxy_address:5,prudent:40,ps:50,publish:[0,46,53],pure:[0,2,27,29,46,53],purpos:[3,6],push:[0,46],py:[0,46],pyopenssl:[0,53],pypi:[0,46],python2:32,python3:0,python:[0,15,17,18,19,20,29,30,32,37,40,41,44,47,48,49,51,53,54,55],pyton:0,pytz:41,q2:48,q:[35,38,48],qop:[2,53],quadrat:0,quantiz:6,queri:[0,1,3,4,6,9,12,15,16,18,25,27,29,32,33,35,37,40,41,42,45,46,48,49,55],query_cl:[3,30],query_from_travers:12,query_str:[15,18,30],queryexhaust:3,queryhandl:[3,29],queryoper:0,queryset:[0,9],querytrac:[0,30,43],question:[45,48],queu:34,quickli:[0,49],quorum:[1,10,27,30,44],quot:[0,17,41],race:0,rack:[0,28],radiu:32,rais:[0,1,2,3,4,5,6,9,10,15,18,27,30,32,34,37,38,40,44,50,54],raise_on_first_error:4,random:[0,27,32,38],randompartition:25,rang:[0,4,10,32,38,41,43],range_request_timeout_in_m:1,rare:0,rather:[0,32,46],raw:6,re:[0,27,30,37,38,39,44,46,53,55],reach:34,reachabl:27,reactor:[0,20,24,43],read:[0,1,6,15,18,26,27,30,32,34,36,43,53],read_inet:0,read_repair:0,read_repair_ch:0,read_request_timeout_in_m:1,read_timeout:26,readabl:25,reader:[12,15,18],readfailur:1,readm:0,readtimeout:[1,44],reason:[1,3,27,41,53],rebuild:[0,3],rebuilt:0,receiv:[0,1,3,27,44],received_respons:[1,27],recent:0,recogn:[15,18],recommend:[0,3,4,27,36,44,49,53,54,55],reconnect:[0,33],reconnection_polici:3,reconnectionpolici:[0,27],reconnector:0,record:[0,6,10,27,38],recreat:[0,25],recurs:0,redhat:46,reduc:[0,3,49,52],redund:40,reevalu:0,ref:0,refactor:[0,41],refer:[0,10,34,40,42,47,54],referenc:3,refresh:[0,3],refresh_:54,refresh_keyspace_metadata:3,refresh_nod:[0,3],refresh_schema:[0,54],refresh_schema_metadata:3,refresh_table_metadata:[3,52],refresh_user_aggregate_metadata:3,refresh_user_function_metadata:3,refresh_user_type_metadata:3,regard:[3,27,32],regardless:[26,27,46,47],regex:13,regist:[0,3,7,12,17,26,34,37,45,54],register_connect:[0,7,35],register_listen:[0,3],register_user_typ:[3,54,55],registr:35,registri:7,regress:0,regular:[13,30,36,38],reilli:44,reinstal:46,reject:47,rel:41,relat:[0,30,38,42],relax:7,releas:[0,9,27,40,42,53,54],release_vers:[43,44],reli:[27,38],reloc:40,remain:[3,20,27,40,42],rememb:44,remot:[0,3,27,52],remoteconnect:12,remov:[0,3,6,8,10,27,30,32,42,47],remove_request_init_listen:3,repair:27,repeat:[27,44],replac:[0,3,6,29,40,53,54],replai:[1,27],replic:[0,3,8,25,40,52],replica:[0,1,8,25,26,27,30,44],replication_factor:[8,25,52],replication_factor_info:25,replicationfactor:25,replicationstrategi:25,report:[0,27],reprepar:0,reprepare_on_up:3,repres:[1,3,5,6,9,15,18,25,26,28,30,31,32,37,38,40,41,54],represent:[0,25,30,32,54],reproduc:0,req:53,req_distinguished_nam:53,request:[0,1,3,4,26,27,38,39,42,44,45,47,49,53,54],request_id:0,request_tim:[0,26],request_timeout:[3,42,44],requestexecutionexcept:1,requestvalidationexcept:1,requir:[0,1,2,3,6,7,19,27,29,30,32,37,38,39,40,44,46,48,53,54],require_client_auth:53,required_replica:[1,27],required_respons:[1,27],reserv:0,reset:27,resolut:[0,32],resolv:[0,3,5,27,36,53],resort:27,resourc:[19,20,21,22,46,53],respect:[0,3,38],respond:[1,2,27,44],respons:[0,1,2,3,27,29,38,44],response_futur:3,responsefutur:[0,3,29,43,44,49,50,54],rest:[27,44],restart:[0,44],resulset:0,result:[0,3,4,9,10,12,15,18,25,26,27,29,30,32,37,38,41,43,44,45,52,55],result_cach:0,result_metadata:29,result_or_exc:4,result_set:3,results_gener:4,results_metadata:0,resultset:[0,3,50,54],resync:9,retain:[0,41],rethrow:27,rethrown:0,retri:[0,7,26,30,33,44],retriev:[1,3,10,30],retry_connect:7,retry_next_host:27,retry_num:27,retry_polici:[0,3,15,18,27,30,42,43,44],retrypolici:[0,3,26,27,30,43],retun:47,reus:[3,14,30],revers:[10,27],review:0,rework:54,rf:[0,1],rhel:46,rich:3,right:[27,30,44],ring:[0,3,27,32,33],risen:53,risk:27,rlac:0,robin:27,robust:[0,41],role:53,root:53,root_ca_base_nam:53,root_cert_pass:53,rootca:53,rotat:27,round:[0,27,32],roundrobinpolici:[27,52],roundtrip:30,rout:[0,3,9,27,43,46],routing_kei:[15,18,27,30,43],row:[0,3,4,5,10,12,29,33,34,37,38,41,42,43,44,47,48,50,54,55],row_factori:[0,3,7,29,30,42,44],row_id:10,row_list:54,rpc:[5,28],rpc_addr:0,rpc_address:[0,42],rsa:53,rule:30,run:[0,9,10,21,27,34,37,39,44,46,48],run_in_executor:0,runtim:[0,46,49],runtimeerror:0,s:[0,1,2,3,6,7,9,10,11,24,27,29,30,32,34,35,36,37,38,39,41,44,45,46,48,52,53,54,55],safe:[0,4],safeti:0,same:[0,3,4,6,7,12,15,18,25,27,30,32,34,35,36,37,38,42,43,44,46,53,54],sasi:38,sasl:[0,2,53],sasl_kwarg:[2,53],saslauthent:[0,2],saslauthprovid:[0,2,53],saslclient:0,satisfi:1,save:[0,9,10,34,35,37,38,41,44,50],scale:[0,26,41,46,49,54],scan:43,scenario:[0,36],schedul:[0,34],schema:[0,3,9,30,33,37,44,54],schema_event_refresh_window:3,schema_metadata_en:3,schema_trigg:0,schemapars:0,scope:[0,3,10],scratch:42,script:[0,40,46,49],scylla:[38,40,46,54],scylladb:52,search:13,second:[0,3,10,26,27,30,31,32,38,41,44],secondari:[0,25,34,38],section:[0,38,40,45,47,49,53,54],secur:[0,45,54],see:[0,1,3,4,6,9,10,11,13,15,18,27,29,30,32,37,38,41,42,43,44,46,47,48,49,50,52,53,54],seen:[0,3,27],segment:40,select:[0,3,4,9,10,30,38,42,43,44,46,50,52,53,54,55],select_stat:4,self:[3,15,18,37,50,54,55],semant:[0,3],send:[0,1,2,3,5,27,44,45,54],sensibl:9,sensit:[0,9],sent:[0,1,2,3,29,44],sep:0,separ:[3,53],septemb:0,seq:43,sequenc:[0,3,4,14,17,27,30,32,44],sequenti:0,serd:0,serial:[0,1,3,12,15,18,30,41],serial_consistency_level:[3,15,18,30,42,44,47,54],serializ:3,serv:40,server:[0,1,2,3,9,15,18,25,29,30,33,38,44,47,48,54],server_authenticator_class:2,server_hostnam:53,server_nam:5,server_vers:43,servererror:27,servic:[2,53],service_timeout:21,session:[0,1,4,7,10,12,14,15,18,25,27,29,30,33,35,39,42,43,46,47,48,49,50,52,53,55],sesssion:0,set:[0,1,2,3,4,6,7,8,9,10,11,12,13,15,17,18,19,20,21,22,25,26,27,30,32,35,37,38,42,43,45,46,48,50,52,53,54],set_column:10,set_column__add:10,set_column__remov:10,set_core_connections_per_host:[3,4],set_default_connect:[7,35],set_keyspac:[0,3,27,44,55],set_max_connections_per_host:3,set_max_requests_per_connect:3,set_meta_refresh_en:3,set_min_requests_per_connect:3,set_sess:[0,7],set_source_analyt:[15,18],set_source_default:[15,18],set_source_graph:[15,18],set_stats_nam:26,set_verifi:53,setenv:46,setup:[0,7,10,35,37,38,39,40,44,46,48,53],setuptool:[0,46],sever:[0,38,40,44,46,49],shallow:[3,42],shard_aware_opt:52,shard_aware_stat:52,shards_count:52,share:[0,3,19,20,21,22,42,49],shed:[15,18],shell:46,shift:41,shortcut:[3,46],should:[0,2,3,4,6,7,8,9,10,15,18,19,20,21,22,25,27,30,31,37,40,42,44,46,49,52,53,54],should_log:3,shouldn:0,show:[0,8,32,36,38,40,42,47,53],shown:[3,35,37,55],shuffl:38,shuffle_replica:27,shutdown:[0,3,39],side:[0,1,2,3,15,18,27,40],sign:[6,53],signal:39,signatur:[1,3],significantli:[38,52],silent:27,similar:[27,29,34,53],simpl:[0,6,15,18,27,30,38,40,41,44,46,49],simpleconvictionpolici:[3,27],simplegraphstat:[15,18],simpler:54,simplest:[38,44],simplestat:[0,3,15,18,30,44,50],simplestrategi:[8,25,52],simpli:[0,9,17,27,34,37,40,44,46,55],simplifi:[15,18],simultan:42,sinc:[0,9,29,31,32,36,38,41,43,54,55],singl:[0,3,4,6,8,9,10,14,25,27,28,30,32,37,38,40,42,44,46,47,54],single_object_row_factori:[15,18],site:[0,41],situat:[27,34,37],six:[0,46,54],size:[0,3,10,54],sizeti:0,sizetieredcompactionstrategi:9,skip:[0,9],slack:0,sleep:[27,37],slice:[0,3,38],slightli:0,slow:0,smaller:27,smallint:[0,6,15,18,44],smoke:0,snappi:46,snapshot:0,sni:5,sniendpoint:5,sniendpointfactori:5,so:[0,1,3,10,21,25,27,30,37,38,41,42,44,47,48,49,50,53,54],socket:[0,5,53],socket_famili:5,sockopt:3,soft:0,softwar:45,some:[0,1,9,15,18,27,34,37,38,41,44,45,46,47,48,50,53,54,55],some_id2:34,some_id:34,someth:[2,27,37,38,46,53],sometim:[0,10,15,18,27,46,50],somewher:[34,50],sort:[0,4,6,32,38],sortedset:[0,32,54],sourc:[0,3,15,18,45,46],source_elaps:[0,43],span:46,spark:[0,3],spcifi:1,spec:41,special:[0,6,29,37,38,40,43],specif:[0,2,5,13,15,17,18,25,27,40,45,46,54,55],specifi:[0,1,3,6,8,9,10,11,12,27,29,30,32,35,37,38,40,41,42,44,53,54],specul:[0,27],speculative_execution_polici:[3,44],speculativeexecutionpolici:[27,44],speed:3,speedup:38,spell:41,spin:0,split:2,squar:47,ss:32,ssl:[0,5,44],ssl_context:[0,3,44,53],ssl_error_want_read:0,ssl_error_want_writ:0,ssl_opt:53,ssl_option:[0,3,5,53],ssl_version:53,sslcontext:[0,53],sstabl:43,sstable_size_in_mb:9,st:[3,37,55],stabil:0,stabl:0,stale:27,stall:0,standard1:52,standard:[0,19,20,26,38,39,41,44,46,53,54],start:[0,3,34,38,41,45,50,54],start_fetching_next_pag:[3,50],start_tim:3,startup:0,stat:[0,26,52],state:[0,3,10,20,27,34,45,47],stateless:50,statement:[0,3,25,27,33,34,36,41,42,43,47,50,55],statements_and_param:4,statements_and_paramet:4,stats_nam:26,statu:[47,52],status_event_refresh_window:3,stddev:26,stdlib:0,step:[37,45],steroid:38,steve:10,still:[0,15,18,30,34,37,40,42,44,54,55],stmt:0,stop:[4,34],store:[0,1,6,9,30,37,41],str:[7,8,10,17,32,44],straightforward:[37,40,41,54],strategi:[0,40,54],stream:[0,29],stream_id:29,street:[3,11,37,54,55],stress:0,strict:[6,49],strictli:0,string:[0,1,2,3,6,12,13,15,17,18,25,26,27,29,30,32,41,44,53],string_typ:32,strip:0,strong:0,structur:[15,18,25,37],studio:46,stuff:[3,55],style:3,sub:[37,40],subclass:[0,1,2,3,27,30,37,53],submit:[0,43],submit_schema_refresh:54,submodul:[40,54],suboptim:27,subsequ:40,subset:38,substanc:39,substanti:[4,54],succe:[3,27],succeed:0,success:[0,1,2,3,4,10,27,30,44,46],successfulli:[0,52],sudo:46,suffici:27,suggest:[44,46],suit:[0,53],suitabl:[2,17,25,36],superset:25,suppli:[0,3,30,44,53,54],support:[0,1,2,3,8,9,10,12,27,32,34,36,38,41,44,45,50,52,53,54,55],supported_vers:1,suppos:[0,37,53],sure:[0,3,27,37,43,44,46,49,51,53],surfac:0,surround:0,swap:54,sy:0,sync:[9,35,37],sync_schema:0,sync_tabl:[0,8,10,35,37,48],sync_typ:[8,11,37],synch:8,synchron:[0,3,4,8,37,49,50],syntax:[0,10,34,38],syntaxexcept:0,system:[0,5,25,38,42,43,44,46,54],t:[0,9,10,15,31,37,38,43,44,47,49,53,54,55],tabl:[0,1,3,6,8,25,30,32,33,37,44,47,48,54,55],tablemetadata:[0,25,52,54],tablemetadatadse68:25,tablemetadatav3:25,tag:[0,15,18],take:[0,3,4,8,9,15,18,25,27,35,44,46,53],taken:[15,18,40],tarbal:46,target:[0,3,13,15,18,27,46],task:[0,3,34,39],tcp:0,tear_up_couch:37,technic:40,techniqu:44,tell:55,tenant:41,term:27,tesla2012:38,tesla:[35,38],test2:10,test4:10,test:[0,10,21,22,27,31,35,46,47],test_clone_shared_lbp:0,test_clust:0,test_set_keyspace_twic:0,testifexistsmodel:9,testifnotexistsmodel:9,testmodel:38,testtransactionmodel:9,text:[0,3,6,9,10,11,13,35,36,37,38,40,44,48,54,55],than:[0,1,3,6,10,27,30,31,32,38,42,44,46,49,50,53],thei:[0,1,3,4,6,8,9,10,15,18,27,29,32,34,36,37,38,40,41,54,55],them:[0,3,27,38,40,41,44,46,47,48,54],themselv:[15,18],therefor:[36,38,46],thi:[0,1,2,3,4,5,6,7,8,9,10,11,12,13,15,17,18,19,20,21,22,25,26,27,28,29,30,31,32,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,52,53,54,55],thing:[3,27,38,40,44],third:[2,41,48],thorough:[46,53],those:[0,3,26,27,30,42,46],though:54,thread:[0,3,4,44,46,49],threadpoolexecutor:0,three:[1,27,30,32,44,47],threshold:[0,3],thrift:0,throttl:0,through:[0,2,3,5,7,9,10,15,18,26,27,30,38,44,45,47,49,54,55],throughput:[0,4,49],thrown:34,thu:[10,27,30,47],ticket:53,time:[0,1,2,3,4,6,10,26,27,31,32,37,38,40,44,45,46,54],time__gt:38,time__lt:38,time_arg:32,timedata:9,timedelta:10,timedelta_or_datetim:9,timeout:[0,1,3,9,10,21,26,27,54],timer:[0,21,26],timestamp:[0,1,6,9,10,17,32,33,36,40,44,45],timestamp_gener:3,timestamp_na:41,timestamp_pres:41,timestamp_utc:41,timestamptyp:0,timeuuid:[0,6,10,32,37,44,54],timezon:[0,6,32,41],tinkerpop:[12,46],tinyint:[0,6,44],tip:45,tlsv1_2_method:53,tmp:42,to_bigint:[15,18],to_doubl:[15,18],to_float:[15,18],to_int:[15,18],to_python:0,to_smallint:[15,18],todo:32,token:[0,2,3,13,15,27,33,43,46,52],token_fuzzi:13,token_map:0,token_metadata_en:3,token_prefix:13,token_regex:13,token_str:25,tokenawar:0,tokenawarepolici:[0,3,27,42,52],tokenawarerout:9,tokenfun:38,tokenmap:[0,25],toler:0,tolist:12,tombston:[3,36,43],tombstone_compaction_interv:9,tombstone_threshold:9,too:[0,3,27,41],took:1,tool:46,toolkit:29,top:[15,18,27],topo:0,topolog:[0,3,27,33],topology_event_refresh_window:3,total:[3,27],trace:[0,3,33],traceev:30,traceunavail:[3,30],tracing_en:0,track:0,trade:4,trademark:45,traffic:[0,44],trail:0,transact:[0,1,3,12,14,27,30,45],transform:37,transient_replica:25,transit:0,translat:[33,40,44],transpar:[3,44,50],trap:34,trash:0,travers:[0,12,14,15,18,46],traversal_batch:14,traversal_class:12,traversal_sourc:12,traversalbatch:[12,14],traversalmetr:0,travisci:0,treat:[3,27,30,44,50],tree:3,tri:0,trigger:[0,3,27],truncat:[6,30,32,40],truncate_microsecond:6,truststor:53,truststore_password:53,truthi:27,ts:41,ttl:[0,9,10],ttl_in_sec:9,tunabl:49,tune:0,tupl:[0,1,3,4,9,12,17,25,27,30,38,44,54,55],tuple_factori:[0,3,16,29,30,42,44,54],turn:[3,43],twice:0,twist:[0,33,44],twistedconnect:[24,53],twistedreactor:[33,53],two:[0,1,3,13,27,29,32,38,44,46,53],txt:[0,46],type0:1,type1:1,type:[0,1,3,8,10,15,17,18,25,27,29,30,32,33,34,38,41,45,47],type_model:8,typeerror:[0,15,18],typestr:0,typic:[3,10,27,29,30,31,34,38,42,44],typo:0,tzinfo:41,u:[10,30,37,38,47],ubuntu:[0,46],uda:0,udf:0,udt:[0,3,12,18,37,45],un:[0,30],unabl:[0,27,46],unauthor:[0,1],unavail:[0,1,26,27],uncal:0,unchang:40,unclean:54,uncompar:0,uncomplet:30,uncondit:0,undefinedkeyspaceexcept:40,under:[0,25,27,37,45],underscor:0,understand:53,understood:[3,27],underutil:0,unexpect:27,unexpectedli:0,unfamiliar:38,unhexlifi:0,unicod:[0,17,44],unicodedecodeerror:0,unif:0,unifi:[0,54],unintend:0,union:3,uniqu:[1,6,25,37,42],unit:[0,13,27,45],unix:[0,5,31,32,41],unix_socket_path:5,unix_time_from_uuid1:32,unixsocketendpoint:5,unknown:[0,15,18,46,54],unless:[3,6,27,35,54],unlik:41,unlog:30,unlogged_batch:27,unord:[6,25],unorder:0,unpack:[0,15,18,44],unprepar:55,unrecogn:0,unrecover:5,unreferenc:0,unregist:[0,55],unregister_connect:[7,35],unregister_listen:3,unset:0,unset_valu:30,unspecifi:[0,9],unsupport:0,unsupportedoper:3,until:[0,2,3,4,7,37,43,44],untrust:3,unus:[0,46],unwis:10,up:[0,3,8,13,19,20,21,22,32,33,34,37,38,53,54],updat:[0,1,3,8,9,10,30,32,34,38,40,42,44,45,47],update_view_metadata:0,updatestat:0,upfront:29,upgrad:[45,48,53],upon:[3,37],upper:32,upper_bound:32,uppercas:0,us:[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,35,36,37,38,40,41,43,44,45,46,47,49,50,51,52,53],usag:[0,2,3,4,9,25,27,30,54],use_certificate_fil:53,use_client_timestamp:[0,1,3,54],use_default_tempdir:0,use_list_t:6,use_privatekey_fil:53,use_set_t:6,used_hosts_per_remote_dc:27,usemap:6,user1:[44,53],user2:44,user3:44,user3_lookup:44,user:[0,1,3,4,6,8,9,10,17,18,25,30,33,38,40,44,45,46,50,53],user_act:3,user_id1:44,user_id2:44,user_id3:44,user_id:[4,9,30,38,44],user_ids_to_queri:44,user_lookup_stmt:44,user_row:[3,44,50],user_typ:[3,6],user_type_map:29,user_tz:41,useraggregatedescriptor:[1,3],userdefinedtyp:[0,6,37],userfunctiondescriptor:[1,3],usernam:[2,44,53],users_to_insert:30,usertyp:[0,6,25,33,37],usertypedoesnotexist:3,usual:[10,21,41,53],utc:[32,41],utc_datetime_from_ms_timestamp:32,utcfromtim:0,utcnow:[6,41],utctimetupl:41,utf8:0,utf8typ:0,utf:[0,6,17],util:[0,1,12,21,22,33,40,41,44,53,54],uuid1:[10,44],uuid4:[10,48],uuid:[0,6,9,10,32,37,38,40,44,48],uuid_arg:32,uuid_from_tim:[32,40],uwsgi:[43,48],uwsgidecor:[39,43],v1:[0,1,32],v2:[0,1,45],v3:[0,1,37,45],v4:[0,1,6,30],v5:[0,1],v6:1,v:[10,12,34,47,52],val1:17,val2:17,val:15,valid:[0,1,3,6,9,10,15,18,25,27,32,47,53],validationerror:[10,37,40],valu:[0,2,3,4,6,9,10,11,13,15,17,18,25,27,29,30,31,32,34,37,40,41,44,47,52,53,54,55],value2:32,value_typ:6,valueerror:[0,32],valuemap:12,values_list:[0,38],valuesequ:30,varchar:44,variabl:[0,6,9,44,46,53],variant:54,varint:[0,6,44],variou:[26,53],various:40,ve:[9,35,37,38],verb:40,verbatim:[15,18],veri:53,verif:0,verifi:0,verify_mod:53,verify_p:53,version:[0,1,2,3,6,25,29,30,31,32,37,40,44,45,46,50,54,55],vertex:[15,18,25],vertexmetadata:25,vertexproperti:[15,18],via:[0,3,37,46,50,53],view:[0,25,27,43],violat:10,virtual:[0,38],visit:45,visual:46,vnode:3,vs:[0,27],wa:[0,1,2,3,4,5,7,25,26,27,30,36,40,46,47,54],wai:[0,3,6,15,18,27,30,36,38,41,42,44,45,46,53,54],wait:[0,1,3,21,27,30,43,44,50],wait_for_all_pool:3,wait_for_complet:30,wake:21,want:[0,3,6,9,27,34,35,37,38,44,50,53,55],warn:[0,1,3,31,40,54],warn_on_drift:31,warning_interv:31,warning_threshold:31,was_appli:[0,3],watcher:21,we:[0,7,27,36,38,39,41,42,44,48,53,55],weakref:0,web_sess:50,well:[0,27,35,44,53],were:[0,1,3,4,19,25,27,30,36,37,40],what:[27,30,37,41,53,54,55],wheel:[0,46],when:[0,1,2,3,4,5,7,9,10,17,21,27,28,29,30,31,32,35,36,37,38,40,41,42,44,46,47,50,53,54,55],whenev:[3,50],where:[0,3,4,10,25,27,30,32,37,43,44,46,47,54],whether:[1,3,6,25,26,27,47,52],which:[0,1,3,9,10,25,27,29,30,34,35,36,38,40,44,46,49,53,54,55],whilst:0,whitelist:27,whitelistroundrobinpolici:[0,27,42,44,54],whitespac:25,who:27,whose:3,wider:[32,41],window:[0,32],wish:3,within:[0,1,3,10,13,27,30,34,41,42,44,54],withing:13,without:[0,1,3,9,10,38,41,44],wkt:[0,32],wno:46,won:37,word:[27,38],work:[0,2,7,17,27,30,32,37,38,44,45,47,48,52,53,55],workaround:[0,36,40],worker:[0,39],worker_process_init:39,working_keyspac:27,workload:[0,42,49],worth:46,would:[0,9,27,36,37,38,42,44,52,53,54],wrap:[12,15,18,27,44],wrap_socket:53,wrapper:[0,27,30],write:[0,1,8,10,15,18,26,27,30],write_request_timeout_in_m:1,write_timeout:26,write_typ:[1,27],writefailur:1,writetimeout:[0,1],writetyp:[0,1,27],written:0,wrong:[0,44],wunus:46,www:6,x509:53,x:[1,4,10,27,32,46,47],xcode:46,xrang:0,y:[0,10,27,32],yaml:[1,27,52],year:[10,32,35,38],year__gt:38,year__in:38,year__lt:38,yet:[3,38,44,54],yield:[4,27],you:[0,3,4,6,9,12,27,30,34,35,37,38,43,44,46,49,50,52,53,54,55],your:[0,3,6,9,35,37,38,40,43,44,47,48,49,50,53,54,55],yourself:49,yum:46,yyyi:[17,32],z:10,zero:0,zip:[54,55],zipcod:[3,11,37,54,55]},titles:["CHANGELOG","cassandra - Exceptions and Enums","cassandra.auth - Authentication","cassandra.cluster - Clusters and Sessions","cassandra.concurrent - Utilities for Concurrent Statement Execution","cassandra.connection - Low Level Connection Info","cassandra.cqlengine.columns - Column types for object mapping models","cassandra.cqlengine.connection - Connection management for cqlengine","cassandra.cqlengine.management - Schema management for cqlengine","cassandra.cqlengine.models - Table models for object mapping","cassandra.cqlengine.query - Query and filter model objects","cassandra.cqlengine.usertype - Model classes for User Defined Types","cassandra.datastax.graph.fluent","cassandra.datastax.graph.fluent.predicates","cassandra.datastax.graph.fluent.query","cassandra.datastax.graph - Graph Statements, Options, and Row Factories","cassandra.decoder - Data Return Formats","cassandra.encoder - Encoders for non-prepared Statements","cassandra.graph - Graph Statements, Options, and Row Factories","cassandra.io.asyncioreactor - asyncio Event Loop","cassandra.io.asyncorereactor - asyncore Event Loop","cassandra.io.eventletreactor - eventlet-compatible Connection","cassandra.io.geventreactor - gevent-compatible Event Loop","cassandra.io.libevreactor - libev Event Loop","cassandra.io.twistedreactor - Twisted Event Loop","cassandra.metadata - Schema and Ring Topology","cassandra.metrics - Performance Metrics","cassandra.policies - Load balancing and Failure Handling Policies","cassandra.pool - Hosts and Connection Pools","cassandra.protocol - Protocol Features","cassandra.query - Prepared Statements, Batch Statements, Tracing, and Row Factories","cassandra.timestamps - Timestamp Generation","cassandra.util - Utilities","API Documentation","Batch Queries","Connections","Frequently Asked Questions","Models","Making Queries","Third party integrations","Upgrade Guide","Working with Dates and Times","Execution Profiles","Frequently Asked Questions","Getting Started","Python Driver for Scylla and Apache Cassandra\u00ae","Installation","Lightweight Transactions (Compare-and-set)","Object Mapper","Performance Notes","Paging Large Queries","Scylla Cloud","Scylla Specific Features","Security","Upgrading","User Defined Types"],titleterms:{"0":[0,53,54],"0b1":0,"0b5":0,"0b6":0,"0b7":0,"0c1":0,"0c2":0,"0rc1":0,"1":[0,54],"10":0,"11":0,"12":0,"13":0,"14":0,"15":0,"16":[0,53],"17":0,"18":0,"19":0,"2":[0,54],"20":0,"21":0,"22":0,"23":0,"24":0,"25":0,"3":[0,53,54],"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"class":[11,55],"default":[35,38,42,47,54],"do":43,"enum":1,"final":0,"float":40,"function":[38,40],"import":[40,54],"new":[35,52],"return":[16,54],No:53,access:38,ad:42,address:27,alias:40,all:38,apach:45,api:[33,40,54],applic:43,ar:[38,54],ask:[36,43],asynchron:44,asyncio:19,asyncioreactor:19,asyncor:20,asyncorereactor:20,attach:54,attribut:52,auth:2,authent:[2,53,54],automat:54,awar:52,balanc:27,base:[46,54],batch:[30,34,36,54],batchqueri:35,beta2:0,beta3:0,beta4:0,beta:0,bind:54,blist:54,bug:0,c:46,call:54,callback:[34,50],can:36,cassandra:[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,41,44,45,54],celeri:39,chang:[35,40,54],changelog:0,client:[53,54],cloud:51,cluster:[3,42,44,52,54],column:[6,40],compar:47,compat:[21,22],compress:46,concurr:4,configur:[46,53],connect:[5,7,21,28,35,43,44],consist:[44,54],consolid:40,content:[45,48],context:35,control:50,convers:44,copyright:45,core:33,correctli:36,cql:44,cqlengin:[6,7,8,9,10,11,40],custom:[29,53,54],cython:[46,49],data:16,datastax:[12,13,14,15,33],date:[40,41],datetyp:41,dead:27,decod:16,defin:[11,37,54,55],definit:37,delet:36,depend:[46,54],deprec:[0,40,54],deseri:29,determin:43,dict:55,dict_factori:47,dictionari:37,document:33,doe:43,don:36,doubl:40,down:27,driver:[33,43,45,54],dse:[53,54],encod:[17,54],error:46,event:[19,20,22,23,24],eventlet:[21,53],eventletreactor:21,exampl:[37,53],except:[1,40],execut:[4,34,42,44,53,54],execute_async:54,extend:37,extens:[46,49],extra:54,factori:[15,18,30],fail:27,failur:27,faster:29,featur:[0,29,52,54],field2:36,field:36,filter:[10,38],fix:0,fluent:[12,13,14],format:16,frequent:[36,43],from:[0,36,54],from_datetim:40,gener:[31,34],get:[44,45,48],gevent:22,geventreactor:22,graph:[12,13,14,15,18,33,46,54],guid:40,handl:[27,50],help:45,helper:52,host:[27,28],how:[36,43],i:[36,43],idempot:27,ident:53,ignor:54,immut:38,individu:36,info:5,inform:54,inherit:[37,40],initi:42,instal:[46,54],instanc:[35,37,42],instanti:36,integr:39,io:[19,20,21,22,23,24,43],issu:45,keyspac:44,larg:50,legaci:42,level:[5,40,44,54],libev:[23,46],libevreactor:23,lightweight:[47,54],list:[38,40],load:27,local_on:54,log:34,login:53,loop:[19,20,22,23,24],low:5,lower:53,make:38,manag:[7,8,35,40,43],manipul:37,manual:46,map:[6,9,42,55],mapper:[33,48],mark:27,merg:0,metadata:[25,54],metric:[26,46],model:[6,9,10,11,35,36,37,40],modul:54,multiprocess:49,my:43,name:[38,42,54],named_tuple_factori:47,nativ:54,node:27,non:[17,46,54],normal:54,note:[46,49],now:54,object:[6,9,10,33,38,48],oper:[27,38,43],option:[15,18,46],order:[36,38],organ:40,osx:46,other:0,overload:40,packag:40,page:[50,54],paramet:[42,44,54],parti:39,pass:[42,44],path:41,pattern:34,payload:29,per:38,perform:[26,49],pip:46,platform:46,polici:27,pool:28,predic:13,prepar:[17,30,44,54],prepend:40,preserv:36,profil:[42,44],protocol:[29,53,54],proxi:53,pypi:49,python:[45,46],queri:[10,14,30,34,36,38,43,44,50,54],queryset:[10,35,38],question:[36,43],read:41,reconnect:27,regist:[35,55],remov:[40,54],replica:43,report:45,request:43,result:[47,50,54],resum:50,retri:[27,43],retriev:38,revers:40,ring:25,row:[15,18,30,36],sasl:54,schema:[8,25,40],scylla:[45,51,52],secur:53,select:35,server:[27,53],session:[3,44,54],set:[44,47],sever:54,shard:52,shutdown:54,side:54,size:50,soft:54,special:47,specif:52,specul:44,speed:46,ssl:[46,53],start:[44,48],statement:[4,15,17,18,30,44,54],support:46,t:36,tabl:[9,38,52],them:55,third:39,through:46,time:41,timeout:[38,43],timestamp:[31,41,54],timeuuid:[38,40],token:[25,38],topolog:25,trace:[30,43,54],transact:[47,54],translat:27,ttl:38,tuple_factori:47,twist:[24,53],twistedreactor:24,type:[6,11,37,40,44,54,55],udt:55,unicodemixin:40,unifi:53,unlog:34,unregist:35,up:[27,46],updat:[36,54],upgrad:[0,40,54],us:[34,42,54,55],user:[11,37,54,55],usertyp:11,util:[4,32],uwsgi:39,v1:53,v2:54,v3:54,valid:37,valu:[36,38],value2:36,verif:53,verifi:[46,53],version:53,vs:34,why:[36,43],window:46,without:[42,55],work:[36,41,54],write:41,wsgi:43,x:[0,54],your:46}}) \ No newline at end of file diff --git a/3.25.11-scylla/security.html b/3.25.11-scylla/security.html new file mode 100644 index 0000000000..df7a12beae --- /dev/null +++ b/3.25.11-scylla/security.html @@ -0,0 +1,1029 @@ + + + + + + + + + + + + + Security | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

Security

+

The two main security components you will use with the +Python driver are Authentication and SSL.

+
+

Authentication

+

Versions 2.0 and higher of the driver support a SASL-based +authentication mechanism when protocol_version +is set to 2 or higher. To use this authentication, set +auth_provider to an instance of a subclass +of AuthProvider. When working +with Cassandra’s PasswordAuthenticator, you can use +the PlainTextAuthProvider class.

+

For example, suppose Cassandra is setup with its default +‘cassandra’ user with a password of ‘cassandra’:

+
from cassandra.cluster import Cluster
+from cassandra.auth import PlainTextAuthProvider
+
+auth_provider = PlainTextAuthProvider(username='cassandra', password='cassandra')
+cluster = Cluster(auth_provider=auth_provider, protocol_version=2)
+
+
+
+

Custom Authenticators

+

If you’re using something other than Cassandra’s PasswordAuthenticator, +SaslAuthProvider is provided for generic SASL authentication mechanisms, +utilizing the pure-sasl package. +If these do not suit your needs, you may need to create your own subclasses of +AuthProvider and Authenticator. You can use the Sasl classes +as example implementations.

+
+
+

Protocol v1 Authentication

+

When working with Cassandra 1.2 (or a higher version with +protocol_version set to 1), you will not pass in +an AuthProvider instance. Instead, you should pass in a +function that takes one argument, the IP address of a host, and returns +a dict of credentials with a username and password key:

+
from cassandra.cluster import Cluster
+
+def get_credentials(host_address):
+    return {'username': 'joe', 'password': '1234'}
+
+cluster = Cluster(auth_provider=get_credentials, protocol_version=1)
+
+
+
+
+
+

SSL

+

SSL should be used when client encryption is enabled in Cassandra.

+

To give you as much control as possible over your SSL configuration, our SSL +API takes a user-created SSLContext instance from the Python standard library. +These docs will include some examples for how to achieve common configurations, +but the ssl.SSLContext documentation +gives a more complete description of what is possible.

+

To enable SSL with version 3.17.0 and higher, you will need to set Cluster.ssl_context to a +ssl.SSLContext instance to enable SSL. Optionally, you can also set Cluster.ssl_options +to a dict of options. These will be passed as kwargs to ssl.SSLContext.wrap_socket() +when new sockets are created.

+

If you create your SSLContext using ssl.create_default_context, +be aware that SSLContext.check_hostname is set to True by default, so the hostname validation will be done +by Python and not the driver. For this reason, we need to set the server_hostname at best effort, which is the +resolved ip address. If this validation needs to be done against the FQDN, consider enabling it using the ssl_options +as described in the following examples or implement your own EndPoint and +EndPointFactory.

+

The following examples assume you have generated your Cassandra certificate and +keystore files with these intructions:

+ +

It might be also useful to learn about the different levels of identity verification to understand the examples:

+ +
+

SSL with Twisted or Eventlet

+

Twisted and Eventlet both use an alternative SSL implementation called pyOpenSSL, so if your Cluster’s connection class is +TwistedConnection or EventletConnection, you must pass a +pyOpenSSL context instead. +An example is provided in these docs, and more details can be found in the +documentation. +pyOpenSSL is not installed by the driver and must be installed separately.

+
+
+

SSL Configuration Examples

+

Here, we’ll describe the server and driver configuration necessary to set up SSL to meet various goals, such as the client verifying the server and the server verifying the client. We’ll also include Python code demonstrating how to use servers and drivers configured in these ways.

+
+

No identity verification

+

No identity verification at all. Note that this is not recommended for for production deployments.

+

The Cassandra configuration:

+
client_encryption_options:
+  enabled: true
+  keystore: /path/to/127.0.0.1.keystore
+  keystore_password: myStorePass
+  require_client_auth: false
+
+
+

The driver configuration:

+
from cassandra.cluster import Cluster, Session
+from ssl import SSLContext, PROTOCOL_TLS
+
+ssl_context = SSLContext(PROTOCOL_TLS)
+
+cluster = Cluster(['127.0.0.1'], ssl_context=ssl_context)
+session = cluster.connect()
+
+
+
+
+

Client verifies server

+

Ensure the python driver verifies the identity of the server.

+

The Cassandra configuration:

+
client_encryption_options:
+  enabled: true
+  keystore: /path/to/127.0.0.1.keystore
+  keystore_password: myStorePass
+  require_client_auth: false
+
+
+

For the driver configuration, it’s very important to set ssl_context.verify_mode +to CERT_REQUIRED. Otherwise, the loaded verify certificate will have no effect:

+
from cassandra.cluster import Cluster, Session
+from ssl import SSLContext, PROTOCOL_TLS, CERT_REQUIRED
+
+ssl_context = SSLContext(PROTOCOL_TLS)
+ssl_context.load_verify_locations('/path/to/rootca.crt')
+ssl_context.verify_mode = CERT_REQUIRED
+
+cluster = Cluster(['127.0.0.1'], ssl_context=ssl_context)
+session = cluster.connect()
+
+
+

Additionally, you can also force the driver to verify the hostname of the server by passing additional options to ssl_context.wrap_socket via the ssl_options kwarg:

+
from cassandra.cluster import Cluster, Session
+from ssl import SSLContext, PROTOCOL_TLS, CERT_REQUIRED
+
+ssl_context = SSLContext(PROTOCOL_TLS)
+ssl_context.load_verify_locations('/path/to/rootca.crt')
+ssl_context.verify_mode = CERT_REQUIRED
+ssl_context.check_hostname = True
+ssl_options = {'server_hostname': '127.0.0.1'}
+
+cluster = Cluster(['127.0.0.1'], ssl_context=ssl_context, ssl_options=ssl_options)
+session = cluster.connect()
+
+
+
+
+

Server verifies client

+

If Cassandra is configured to verify clients (require_client_auth), you need to generate +SSL key and certificate files.

+

The cassandra configuration:

+
client_encryption_options:
+  enabled: true
+  keystore: /path/to/127.0.0.1.keystore
+  keystore_password: myStorePass
+  require_client_auth: true
+  truststore: /path/to/dse-truststore.jks
+  truststore_password: myStorePass
+
+
+

The Python ssl APIs require the certificate in PEM format. First, create a certificate +conf file:

+
cat > gen_client_cert.conf <<EOF
+[ req ]
+distinguished_name = req_distinguished_name
+prompt = no
+output_password = ${ROOT_CERT_PASS}
+default_bits = 2048
+
+[ req_distinguished_name ]
+C = ${CERT_COUNTRY}
+O = ${CERT_ORG_NAME}
+OU = ${CERT_OU}
+CN = client
+EOF
+
+
+

Make sure you replaced the variables with the same values you used for the initial +root CA certificate. Then, generate the key:

+
openssl req -newkey rsa:2048 -nodes -keyout client.key -out client.csr -config gen_client_cert.conf
+
+
+

And generate the client signed certificate:

+
openssl x509 -req -CA ${ROOT_CA_BASE_NAME}.crt -CAkey ${ROOT_CA_BASE_NAME}.key -passin pass:${ROOT_CERT_PASS} \
+    -in client.csr -out client.crt_signed -days ${CERT_VALIDITY} -CAcreateserial
+
+
+

Finally, you can use that configuration with the following driver code:

+
from cassandra.cluster import Cluster, Session
+from ssl import SSLContext, PROTOCOL_TLS
+
+ssl_context = SSLContext(PROTOCOL_TLS)
+ssl_context.load_cert_chain(
+    certfile='/path/to/client.crt_signed',
+    keyfile='/path/to/client.key')
+
+cluster = Cluster(['127.0.0.1'], ssl_context=ssl_context)
+session = cluster.connect()
+
+
+
+
+

Server verifies client and client verifies server

+

See the previous section for examples of Cassandra configuration and preparing +the client certificates.

+

The following driver code specifies that the connection should use two-way verification:

+
from cassandra.cluster import Cluster, Session
+from ssl import SSLContext, PROTOCOL_TLS, CERT_REQUIRED
+
+ssl_context = SSLContext(PROTOCOL_TLS)
+ssl_context.load_verify_locations('/path/to/rootca.crt')
+ssl_context.verify_mode = CERT_REQUIRED
+ssl_context.load_cert_chain(
+    certfile='/path/to/client.crt_signed',
+    keyfile='/path/to/client.key')
+
+cluster = Cluster(['127.0.0.1'], ssl_context=ssl_context)
+session = cluster.connect()
+
+
+

The driver uses SSLContext directly to give you many other options in configuring SSL. Consider reading the Python SSL documentation +for more details about SSLContext configuration.

+

Server verifies client and client verifies server using Twisted and pyOpenSSL

+
from OpenSSL import SSL, crypto
+from cassandra.cluster import Cluster
+from cassandra.io.twistedreactor import TwistedConnection
+
+ssl_context = SSL.Context(SSL.TLSv1_2_METHOD)
+ssl_context.set_verify(SSL.VERIFY_PEER, callback=lambda _1, _2, _3, _4, ok: ok)
+ssl_context.use_certificate_file('/path/to/client.crt_signed')
+ssl_context.use_privatekey_file('/path/to/client.key')
+ssl_context.load_verify_locations('/path/to/rootca.crt')
+
+cluster = Cluster(
+    contact_points=['127.0.0.1'],
+    connection_class=TwistedConnection,
+    ssl_context=ssl_context,
+    ssl_options={'check_hostname': True}
+)
+session = cluster.connect()
+
+
+

Connecting using Eventlet would look similar except instead of importing and using TwistedConnection, you would +import and use EventletConnection, including the appropriate monkey-patching.

+
+
+
+

Versions 3.16.0 and lower

+

To enable SSL you will need to set Cluster.ssl_options to a +dict of options. These will be passed as kwargs to ssl.wrap_socket() +when new sockets are created. Note that this use of ssl_options will be +deprecated in the next major release.

+

By default, a ca_certs value should be supplied (the value should be +a string pointing to the location of the CA certs file), and you probably +want to specify ssl_version as ssl.PROTOCOL_TLS to match +Cassandra’s default protocol.

+

For example:

+
from cassandra.cluster import Cluster
+from ssl import PROTOCOL_TLS, CERT_REQUIRED
+
+ssl_opts = {
+    'ca_certs': '/path/to/my/ca.certs',
+    'ssl_version': PROTOCOL_TLS,
+    'cert_reqs': CERT_REQUIRED  # Certificates are required and validated
+}
+cluster = Cluster(ssl_options=ssl_opts)
+
+
+

This is only an example to show how to pass the ssl parameters. Consider reading +the python ssl documentation for +your configuration. For further reading, Andrew Mussey has published a thorough guide on +Using SSL with the DataStax Python driver.

+
+

SSL with Twisted

+

In case the twisted event loop is used pyOpenSSL must be installed or an exception will be risen. Also +to set the ssl_version and cert_reqs in ssl_opts the appropriate constants from pyOpenSSL are expected.

+
+
+
+
+

DSE Authentication

+

When authenticating against DSE, the Cassandra driver provides two auth providers that work both with legacy kerberos and Cassandra authenticators, +as well as the new DSE Unified Authentication. This allows client to configure this auth provider independently, +and in advance of any server upgrade. These auth providers are configured in the same way as any previous implementation:

+
from cassandra.auth import DSEGSSAPIAuthProvider
+auth_provider = DSEGSSAPIAuthProvider(service='dse', qops=["auth"])
+cluster = Cluster(auth_provider=auth_provider)
+session = cluster.connect()
+
+
+

Implementations are DSEPlainTextAuthProvider, DSEGSSAPIAuthProvider and SaslAuthProvider.

+
+

DSE Unified Authentication

+

With DSE (>=5.1), unified Authentication allows you to:

+
    +
  • Proxy Login: Authenticate using a fixed set of authentication credentials but allow authorization of resources based another user id.

  • +
  • Proxy Execute: Authenticate using a fixed set of authentication credentials but execute requests based on another user id.

  • +
+
+

Proxy Login

+

Proxy login allows you to authenticate with a user but act as another one. You need to ensure the authenticated user has the permission to use the authorization of resources of the other user. ie. this example will allow the server user to authenticate as usual but use the authorization of user1:

+
GRANT PROXY.LOGIN on role user1 to server
+
+
+

then you can do the proxy authentication….

+
from cassandra.cluster import Cluster
+from cassandra.auth import SaslAuthProvider
+
+sasl_kwargs = {
+  "service": 'dse',
+  "mechanism":"PLAIN",
+  "username": 'server',
+  'password': 'server',
+  'authorization_id': 'user1'
+}
+
+auth_provider = SaslAuthProvider(**sasl_kwargs)
+c = Cluster(auth_provider=auth_provider)
+s = c.connect()
+s.execute(...)  # all requests will be executed as 'user1'
+
+
+

If you are using kerberos, you can use directly DSEGSSAPIAuthProvider and pass the authorization_id, like this:

+
from cassandra.cluster import Cluster
+from cassandra.auth import DSEGSSAPIAuthProvider
+
+# Ensure the kerberos ticket of the server user is set with the kinit utility.
+auth_provider = DSEGSSAPIAuthProvider(service='dse', qops=["auth"], principal="server@DATASTAX.COM",
+                                      authorization_id='user1@DATASTAX.COM')
+c = Cluster(auth_provider=auth_provider)
+s = c.connect()
+s.execute(...)  # all requests will be executed as 'user1'
+
+
+
+
+

Proxy Execute

+

Proxy execute allows you to execute requests as another user than the authenticated one. You need to ensure the authenticated user has the permission to use the authorization of resources of the specified user. ie. this example will allow the server user to execute requests as user1:

+
GRANT PROXY.EXECUTE on role user1 to server
+
+
+

then you can do a proxy execute…

+
from cassandra.cluster import Cluster
+from cassandra.auth import DSEPlainTextAuthProvider,
+
+auth_provider = DSEPlainTextAuthProvider('server', 'server')
+
+c = Cluster(auth_provider=auth_provider)
+s = c.connect()
+s.execute('select * from k.t;', execute_as='user1')  # the request will be executed as 'user1'
+
+
+

Please see the official documentation for more details on the feature and configuration process.

+
+
+
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.25.11-scylla/sitemap.xml b/3.25.11-scylla/sitemap.xml new file mode 100644 index 0000000000..f03cce40f2 --- /dev/null +++ b/3.25.11-scylla/sitemap.xml @@ -0,0 +1,2 @@ + +https://python-driver.docs.scylladb.com/stable/CHANGELOG.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/auth.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/cluster.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/concurrent.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/connection.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/cqlengine/columns.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/cqlengine/connection.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/cqlengine/management.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/cqlengine/models.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/cqlengine/query.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/cqlengine/usertype.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/datastax/graph/fluent/index.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/datastax/graph/fluent/predicates.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/datastax/graph/fluent/query.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/datastax/graph/index.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/decoder.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/encoder.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/graph.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/io/asyncioreactor.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/io/asyncorereactor.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/io/eventletreactor.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/io/geventreactor.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/io/libevreactor.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/io/twistedreactor.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/metadata.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/metrics.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/policies.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/pool.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/protocol.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/query.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/timestamps.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/util.htmlhttps://python-driver.docs.scylladb.com/stable/api/index.htmlhttps://python-driver.docs.scylladb.com/stable/cqlengine/batches.htmlhttps://python-driver.docs.scylladb.com/stable/cqlengine/connections.htmlhttps://python-driver.docs.scylladb.com/stable/cqlengine/faq.htmlhttps://python-driver.docs.scylladb.com/stable/cqlengine/models.htmlhttps://python-driver.docs.scylladb.com/stable/cqlengine/queryset.htmlhttps://python-driver.docs.scylladb.com/stable/cqlengine/third_party.htmlhttps://python-driver.docs.scylladb.com/stable/cqlengine/upgrade_guide.htmlhttps://python-driver.docs.scylladb.com/stable/dates_and_times.htmlhttps://python-driver.docs.scylladb.com/stable/execution_profiles.htmlhttps://python-driver.docs.scylladb.com/stable/faq.htmlhttps://python-driver.docs.scylladb.com/stable/getting_started.htmlhttps://python-driver.docs.scylladb.com/stable/index.htmlhttps://python-driver.docs.scylladb.com/stable/installation.htmlhttps://python-driver.docs.scylladb.com/stable/lwt.htmlhttps://python-driver.docs.scylladb.com/stable/object_mapper.htmlhttps://python-driver.docs.scylladb.com/stable/performance.htmlhttps://python-driver.docs.scylladb.com/stable/query_paging.htmlhttps://python-driver.docs.scylladb.com/stable/scylla_cloud.htmlhttps://python-driver.docs.scylladb.com/stable/scylla_specific.htmlhttps://python-driver.docs.scylladb.com/stable/security.htmlhttps://python-driver.docs.scylladb.com/stable/upgrading.htmlhttps://python-driver.docs.scylladb.com/stable/user_defined_types.htmlhttps://python-driver.docs.scylladb.com/stable/py-modindex.htmlhttps://python-driver.docs.scylladb.com/stable/404.htmlhttps://python-driver.docs.scylladb.com/stable/search.html \ No newline at end of file diff --git a/3.25.11-scylla/upgrading.html b/3.25.11-scylla/upgrading.html new file mode 100644 index 0000000000..4fc28fd127 --- /dev/null +++ b/3.25.11-scylla/upgrading.html @@ -0,0 +1,1028 @@ + + + + + + + + + + + + + Upgrading | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

Upgrading

+
+
+
+

Upgrading from dse-driver

+

Since 3.21.0, scylla-driver fully supports DataStax products. dse-driver and +dse-graph users should now migrate to scylla-driver to benefit from latest bug fixes +and new features. The upgrade to this new unified driver version is straightforward +with no major API changes.

+
+

Installation

+

Only the scylla-driver package should be installed. dse-driver and dse-graph +are not required anymore:

+
pip install scylla-driver
+
+
+

If you need the Graph Fluent API (features provided by dse-graph):

+
pip install scylla-driver[graph]
+
+
+

See Installation for more details.

+
+
+

Import from the cassandra module

+

There is no dse module, so you should import from the cassandra module. You +need to change only the first module of your import statements, not the submodules.

+
from dse.cluster import Cluster, EXEC_PROFILE_GRAPH_DEFAULT
+from dse.auth import PlainTextAuthProvider
+from dse.policies import WhiteListRoundRobinPolicy
+
+# becomes
+
+from cassandra.cluster import Cluster, EXEC_PROFILE_GRAPH_DEFAULT
+from cassandra.auth import PlainTextAuthProvider
+from cassandra.policies import WhiteListRoundRobinPolicy
+
+
+

Also note that the cassandra.hosts module doesn’t exist in scylla-driver. This +module is named cassandra.pool.

+
+
+

dse-graph

+

dse-graph features are now built into scylla-driver. The only change you need +to do is your import statements:

+
from dse_graph import ..
+from dse_graph.query import ..
+
+# becomes
+
+from cassandra.datastax.graph.fluent import ..
+from cassandra.datastax.graph.fluent.query import ..
+
+
+

See fluent.

+
+
+

Session.execute and Session.execute_async API

+

Although it is not common to use this API with positional arguments, it is +important to be aware that the host and execute_as parameters have had +their positional order swapped. This is only because execute_as was added +in dse-driver before host.

+

See Session.execute().

+
+
+

Deprecations

+

These changes are optional, but recommended:

+
    +
  • Importing from cassandra.graph is deprecated. Consider importing from cassandra.datastax.graph.

  • +
  • Use DefaultLoadBalancingPolicy instead of DSELoadBalancingPolicy.

  • +
+
+
+
+

Upgrading to 3.0

+

Version 3.0 of the DataStax Python driver for Apache Cassandra +adds support for Cassandra 3.0 while maintaining support for +previously supported versions. In addition to substantial internal rework, +there are several updates to the API that integrators will need +to consider:

+
+

Default consistency is now LOCAL_ONE

+

Previous value was ONE. The new value is introduced to mesh with the default +DC-aware load balancing policy and to match other drivers.

+
+
+

Execution API Updates

+
+

Result return normalization

+

PYTHON-368

+

Previously results would be returned as a list of rows for result rows +up to fetch_size, and PagedResult afterward. This could break +application code that assumed one type and got another.

+

Now, all results are returned as an iterable ResultSet.

+

The preferred way to consume results of unknown size is to iterate through +them, letting automatic paging occur as they are consumed.

+
results = session.execute("SELECT * FROM system.local")
+for row in results:
+    process(row)
+
+
+

If the expected size of the results is known, it is still possible to +materialize a list using the iterator:

+
results = session.execute("SELECT * FROM system.local")
+row_list = list(results)
+
+
+

For backward compatibility, ResultSet supports indexing. When +accessed at an index, a ~.ResultSet object will materialize all its pages:

+
results = session.execute("SELECT * FROM system.local")
+first_result = results[0]  # materializes results, fetching all pages
+
+
+

This can send requests and load (possibly large) results into memory, so +~.ResultSet will log a warning on implicit materialization.

+
+
+

Trace information is not attached to executed Statements

+

PYTHON-318

+

Previously trace data was attached to Statements if tracing was enabled. This +could lead to confusion if the same statement was used for multiple executions.

+

Now, trace data is associated with the ResponseFuture and ResultSet +returned for each query:

+

ResponseFuture.get_query_trace()

+

ResponseFuture.get_all_query_traces()

+

ResultSet.get_query_trace()

+

ResultSet.get_all_query_traces()

+
+
+

Binding named parameters now ignores extra names

+

PYTHON-178

+

Previously, BoundStatement.bind() would raise if a mapping +was passed with extra names not found in the prepared statement.

+

Behavior in 3.0+ is to ignore extra names.

+
+
+
+

blist removed as soft dependency

+

PYTHON-385

+

Previously the driver had a soft dependency on blist sortedset, using +that where available and using an internal fallback where possible.

+

Now, the driver never chooses the blist variant, instead returning the +internal util.SortedSet for all set results. The class implements +all standard set operations, so no integration code should need to change unless +it explicitly checks for sortedset type.

+
+
+

Metadata API Updates

+

PYTHON-276, PYTHON-408, PYTHON-400, PYTHON-422

+

Cassandra 3.0 brought a substantial overhaul to the internal schema metadata representation. +This version of the driver supports that metadata in addition to the legacy version. Doing so +also brought some changes to the metadata model.

+

The present API is documented: cassandra.metadata. Changes highlighted below:

+
    +
  • All types are now exposed as CQL types instead of types derived from the internal server implementation

  • +
  • Some metadata attributes have changed names to match current nomenclature (for example, Index.kind in place of Index.type).

  • +
  • Some metadata attributes removed

    +
      +
    • TableMetadata.keyspace reference replaced with TableMetadata.keyspace_name

    • +
    • ColumnMetadata.index is removed table- and keyspace-level mappings are still maintained

    • +
    +
  • +
+
+
+

Several deprecated features are removed

+

PYTHON-292

+
    +
  • ResponseFuture.result timeout parameter is removed, use Session.execute timeout instead (031ebb0)

  • +
  • Cluster.refresh_schema removed, use Cluster.refresh_*_metadata instead (419fcdf)

  • +
  • Cluster.submit_schema_refresh removed (574266d)

  • +
  • cqltypes time/date functions removed, use util entry points instead (bb984ee)

  • +
  • decoder module removed (e16a073)

  • +
  • TableMetadata.keyspace attribute replaced with keyspace_name (cc94073)

  • +
  • cqlengine.columns.TimeUUID.from_datetime removed, use util variant instead (96489cc)

  • +
  • cqlengine.columns.Float(double_precision) parameter removed, use columns.Double instead (a2d3a98)

  • +
  • cqlengine keyspace management functions are removed in favor of the strategy-specific entry points (4bd5909)

  • +
  • cqlengine.Model.__polymorphic_*__ attributes removed, use __discriminator* attributes instead (9d98c8e)

  • +
  • cqlengine.statements will no longer warn about list list prepend behavior (79efe97)

  • +
+
+
+
+

Upgrading to 2.1 from 2.0

+

Version 2.1 of the DataStax Python driver for Apache Cassandra +adds support for Cassandra 2.1 and version 3 of the native protocol.

+

Cassandra 1.2, 2.0, and 2.1 are all supported. However, 1.2 only +supports protocol version 1, and 2.0 only supports versions 1 and +2, so some features may not be available.

+
+

Using the v3 Native Protocol

+

By default, the driver will attempt to use version 2 of the +native protocol. To use version 3, you must explicitly +set the protocol_version:

+
from cassandra.cluster import Cluster
+
+cluster = Cluster(protocol_version=3)
+
+
+

Note that protocol version 3 is only supported by Cassandra 2.1+.

+

In future releases, the driver may default to using protocol version +3.

+
+
+

Working with User-Defined Types

+

Cassandra 2.1 introduced the ability to define new types:

+
USE KEYSPACE mykeyspace;
+
+CREATE TYPE address (street text, city text, zip int);
+
+
+

The driver generally expects you to use instances of a specific +class to represent column values of this type. You can let the +driver know what class to use with Cluster.register_user_type():

+
cluster = Cluster()
+
+class Address(object):
+
+    def __init__(self, street, city, zipcode):
+        self.street = street
+        self.city = text
+        self.zipcode = zipcode
+
+cluster.register_user_type('mykeyspace', 'address', Address)
+
+
+

When inserting data for address columns, you should pass in +instances of Address. When querying data, address column +values will be instances of Address.

+

If no class is registered for a user-defined type, query results +will use a namedtuple class and data may only be inserted +though prepared statements.

+

See User Defined Types for more details.

+
+
+

Customizing Encoders for Non-prepared Statements

+

Starting with version 2.1 of the driver, it is possible to customize +how Python types are converted to CQL literals when working with +non-prepared statements. This is done on a per-Session +basis through Session.encoder:

+
cluster = Cluster()
+session = cluster.connect()
+session.encoder.mapping[tuple] = session.encoder.cql_encode_tuple
+
+
+

See Type Conversions for the table of default CQL literal conversions.

+
+
+

Using Client-Side Protocol-Level Timestamps

+

With version 3 of the native protocol, timestamps may be supplied by the +client at the protocol level. (Normally, if they are not specified within +the CQL query itself, a timestamp is generated server-side.)

+

When protocol_version is set to 3 or higher, the driver +will automatically use client-side timestamps with microsecond precision +unless Session.use_client_timestamp is changed to False. +If a timestamp is specified within the CQL query, it will override the +timestamp generated by the driver.

+
+
+
+

Upgrading to 2.0 from 1.x

+

Version 2.0 of the DataStax Python driver for Apache Cassandra +includes some notable improvements over version 1.x. This version +of the driver supports Cassandra 1.2, 2.0, and 2.1. However, not +all features may be used with Cassandra 1.2, and some new features +in 2.1 are not yet supported.

+
+

Using the v2 Native Protocol

+

By default, the driver will attempt to use version 2 of Cassandra’s +native protocol. You can explicitly set the protocol version to +2, though:

+
from cassandra.cluster import Cluster
+
+cluster = Cluster(protocol_version=2)
+
+
+

When working with Cassandra 1.2, you will need to +explicitly set the protocol_version to 1:

+
from cassandra.cluster import Cluster
+
+cluster = Cluster(protocol_version=1)
+
+
+
+
+

Automatic Query Paging

+

Version 2 of the native protocol adds support for automatic query +paging, which can make dealing with large result sets much simpler.

+

See Paging Large Queries for full details.

+
+
+

Protocol-Level Batch Statements

+

With version 1 of the native protocol, batching of statements required +using a BATCH cql query. +With version 2 of the native protocol, you can now batch statements at +the protocol level. This allows you to use many different prepared +statements within a single batch.

+

See BatchStatement for details and usage examples.

+
+
+

SASL-based Authentication

+

Also new in version 2 of the native protocol is SASL-based authentication. +See the section on Security for details and examples.

+
+
+

Lightweight Transactions

+

Lightweight transactions are another new feature. To use lightweight transactions, add IF clauses +to your CQL queries and set the serial_consistency_level +on your statements.

+
+
+

Calling Cluster.shutdown()

+

In order to fix some issues around garbage collection and unclean interpreter +shutdowns, version 2.0 of the driver requires you to call Cluster.shutdown() +on your Cluster objects when you are through with them. +This helps to guarantee a clean shutdown.

+
+
+

Deprecations

+

The following functions have moved from cassandra.decoder to cassandra.query. +The original functions have been left in place with a DeprecationWarning for +now:

+ +
+
+

Dependency Changes

+

The following dependencies have officially been made optional:

+
    +
  • scales

  • +
  • blist

  • +
+

And one new dependency has been added (to enable Python 3 support):

+
    +
  • six

  • +
+
+
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.25.11-scylla/user_defined_types.html b/3.25.11-scylla/user_defined_types.html new file mode 100644 index 0000000000..af48dbe6f5 --- /dev/null +++ b/3.25.11-scylla/user_defined_types.html @@ -0,0 +1,758 @@ + + + + + + + + + + + + + User Defined Types | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

User Defined Types

+

Cassandra 2.1 introduced user-defined types (UDTs). You can create a +new type through CREATE TYPE statements in CQL:

+
CREATE TYPE address (street text, zip int);
+
+
+

Version 2.1 of the Python driver adds support for user-defined types.

+
+

Registering a UDT

+

You can tell the Python driver to return columns of a specific UDT as +instances of a class or a dict by registering them with your Cluster +instance through Cluster.register_user_type():

+
+

Map a Class to a UDT

+
cluster = Cluster(protocol_version=3)
+session = cluster.connect()
+session.set_keyspace('mykeyspace')
+session.execute("CREATE TYPE address (street text, zipcode int)")
+session.execute("CREATE TABLE users (id int PRIMARY KEY, location frozen<address>)")
+
+# create a class to map to the "address" UDT
+class Address(object):
+
+    def __init__(self, street, zipcode):
+        self.street = street
+        self.zipcode = zipcode
+
+cluster.register_user_type('mykeyspace', 'address', Address)
+
+# insert a row using an instance of Address
+session.execute("INSERT INTO users (id, location) VALUES (%s, %s)",
+                (0, Address("123 Main St.", 78723)))
+
+# results will include Address instances
+results = session.execute("SELECT * FROM users")
+row = results[0]
+print(row.id, row.location.street, row.location.zipcode)
+
+
+
+
+

Map a dict to a UDT

+
cluster = Cluster(protocol_version=3)
+session = cluster.connect()
+session.set_keyspace('mykeyspace')
+session.execute("CREATE TYPE address (street text, zipcode int)")
+session.execute("CREATE TABLE users (id int PRIMARY KEY, location frozen<address>)")
+
+cluster.register_user_type('mykeyspace', 'address', dict)
+
+# insert a row using a prepared statement and a tuple
+insert_statement = session.prepare("INSERT INTO mykeyspace.users (id, location) VALUES (?, ?)")
+session.execute(insert_statement, [0, ("123 Main St.", 78723)])
+
+# results will include dict instances
+results = session.execute("SELECT * FROM users")
+row = results[0]
+print(row.id, row.location['street'], row.location['zipcode'])
+
+
+
+
+
+

Using UDTs Without Registering Them

+

Although it is recommended to register your types with +Cluster.register_user_type(), the driver gives you some options +for working with unregistered UDTS.

+

When you use prepared statements, the driver knows what data types to +expect for each placeholder. This allows you to pass any object you +want for a UDT, as long as it has attributes that match the field names +for the UDT:

+
cluster = Cluster(protocol_version=3)
+session = cluster.connect()
+session.set_keyspace('mykeyspace')
+session.execute("CREATE TYPE address (street text, zipcode int)")
+session.execute("CREATE TABLE users (id int PRIMARY KEY, location frozen<address>)")
+
+class Foo(object):
+
+    def __init__(self, street, zipcode, otherstuff):
+        self.street = street
+        self.zipcode = zipcode
+        self.otherstuff = otherstuff
+
+insert_statement = session.prepare("INSERT INTO users (id, location) VALUES (?, ?)")
+
+# since we're using a prepared statement, we don't *have* to register
+# a class to map to the UDT to insert data.  The object just needs to have
+# "street" and "zipcode" attributes (which Foo does):
+session.execute(insert_statement, [0, Foo("123 Main St.", 78723, "some other stuff")])
+
+# when we query data, UDT columns that don't have a class registered
+# will be returned as namedtuples:
+results = session.execute("SELECT * FROM users")
+first_row = results[0]
+address = first_row.location
+print(address)  # prints "Address(street='123 Main St.', zipcode=78723)"
+street = address.street
+zipcode = address.street
+
+
+

As shown in the code example, inserting data for UDT columns without registering +a class works fine for prepared statements. However, you must register a +class to insert UDT columns with unprepared statements.* You can still query +UDT columns without registered classes using unprepared statements, they will +simply return namedtuple instances (just like prepared statements do).

+

* this applies to parameterized unprepared statements, in which the driver will be formatting parameters – not statements with interpolated UDT literals.

+
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.25.4-scylla/.buildinfo b/3.25.4-scylla/.buildinfo new file mode 100644 index 0000000000..9c68fb6cfc --- /dev/null +++ b/3.25.4-scylla/.buildinfo @@ -0,0 +1,4 @@ +# Sphinx build info version 1 +# This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done. +config: 908ba5439f2003aeae8100e820e37f07 +tags: 645f666f9bcd5a90fca523b33c5a78b7 diff --git a/3.25.4-scylla/.doctrees/CHANGELOG.doctree b/3.25.4-scylla/.doctrees/CHANGELOG.doctree new file mode 100644 index 0000000000..cd75182be9 Binary files /dev/null and b/3.25.4-scylla/.doctrees/CHANGELOG.doctree differ diff --git a/3.25.4-scylla/.doctrees/api/cassandra.doctree b/3.25.4-scylla/.doctrees/api/cassandra.doctree new file mode 100644 index 0000000000..8322e8b92f Binary files /dev/null and b/3.25.4-scylla/.doctrees/api/cassandra.doctree differ diff --git a/3.25.4-scylla/.doctrees/api/cassandra/auth.doctree b/3.25.4-scylla/.doctrees/api/cassandra/auth.doctree new file mode 100644 index 0000000000..a2b4e71835 Binary files /dev/null and b/3.25.4-scylla/.doctrees/api/cassandra/auth.doctree differ diff --git a/3.25.4-scylla/.doctrees/api/cassandra/cluster.doctree b/3.25.4-scylla/.doctrees/api/cassandra/cluster.doctree new file mode 100644 index 0000000000..545a911f9d Binary files /dev/null and b/3.25.4-scylla/.doctrees/api/cassandra/cluster.doctree differ diff --git a/3.25.4-scylla/.doctrees/api/cassandra/concurrent.doctree b/3.25.4-scylla/.doctrees/api/cassandra/concurrent.doctree new file mode 100644 index 0000000000..56a0d8635a Binary files /dev/null and b/3.25.4-scylla/.doctrees/api/cassandra/concurrent.doctree differ diff --git a/3.25.4-scylla/.doctrees/api/cassandra/connection.doctree b/3.25.4-scylla/.doctrees/api/cassandra/connection.doctree new file mode 100644 index 0000000000..4ee91a849b Binary files /dev/null and b/3.25.4-scylla/.doctrees/api/cassandra/connection.doctree differ diff --git a/3.25.4-scylla/.doctrees/api/cassandra/cqlengine/columns.doctree b/3.25.4-scylla/.doctrees/api/cassandra/cqlengine/columns.doctree new file mode 100644 index 0000000000..2799c90d83 Binary files /dev/null and b/3.25.4-scylla/.doctrees/api/cassandra/cqlengine/columns.doctree differ diff --git a/3.25.4-scylla/.doctrees/api/cassandra/cqlengine/connection.doctree b/3.25.4-scylla/.doctrees/api/cassandra/cqlengine/connection.doctree new file mode 100644 index 0000000000..dc41388b0b Binary files /dev/null and b/3.25.4-scylla/.doctrees/api/cassandra/cqlengine/connection.doctree differ diff --git a/3.25.4-scylla/.doctrees/api/cassandra/cqlengine/management.doctree b/3.25.4-scylla/.doctrees/api/cassandra/cqlengine/management.doctree new file mode 100644 index 0000000000..dd3684cade Binary files /dev/null and b/3.25.4-scylla/.doctrees/api/cassandra/cqlengine/management.doctree differ diff --git a/3.25.4-scylla/.doctrees/api/cassandra/cqlengine/models.doctree b/3.25.4-scylla/.doctrees/api/cassandra/cqlengine/models.doctree new file mode 100644 index 0000000000..fd373187de Binary files /dev/null and b/3.25.4-scylla/.doctrees/api/cassandra/cqlengine/models.doctree differ diff --git a/3.25.4-scylla/.doctrees/api/cassandra/cqlengine/query.doctree b/3.25.4-scylla/.doctrees/api/cassandra/cqlengine/query.doctree new file mode 100644 index 0000000000..1a7bab8ead Binary files /dev/null and b/3.25.4-scylla/.doctrees/api/cassandra/cqlengine/query.doctree differ diff --git a/3.25.4-scylla/.doctrees/api/cassandra/cqlengine/usertype.doctree b/3.25.4-scylla/.doctrees/api/cassandra/cqlengine/usertype.doctree new file mode 100644 index 0000000000..bc2c2ca37c Binary files /dev/null and b/3.25.4-scylla/.doctrees/api/cassandra/cqlengine/usertype.doctree differ diff --git a/3.25.4-scylla/.doctrees/api/cassandra/datastax/graph/fluent/index.doctree b/3.25.4-scylla/.doctrees/api/cassandra/datastax/graph/fluent/index.doctree new file mode 100644 index 0000000000..4356cc42f3 Binary files /dev/null and b/3.25.4-scylla/.doctrees/api/cassandra/datastax/graph/fluent/index.doctree differ diff --git a/3.25.4-scylla/.doctrees/api/cassandra/datastax/graph/fluent/predicates.doctree b/3.25.4-scylla/.doctrees/api/cassandra/datastax/graph/fluent/predicates.doctree new file mode 100644 index 0000000000..1db91f97ea Binary files /dev/null and b/3.25.4-scylla/.doctrees/api/cassandra/datastax/graph/fluent/predicates.doctree differ diff --git a/3.25.4-scylla/.doctrees/api/cassandra/datastax/graph/fluent/query.doctree b/3.25.4-scylla/.doctrees/api/cassandra/datastax/graph/fluent/query.doctree new file mode 100644 index 0000000000..bac0966359 Binary files /dev/null and b/3.25.4-scylla/.doctrees/api/cassandra/datastax/graph/fluent/query.doctree differ diff --git a/3.25.4-scylla/.doctrees/api/cassandra/datastax/graph/index.doctree b/3.25.4-scylla/.doctrees/api/cassandra/datastax/graph/index.doctree new file mode 100644 index 0000000000..9f1e7200ab Binary files /dev/null and b/3.25.4-scylla/.doctrees/api/cassandra/datastax/graph/index.doctree differ diff --git a/3.25.4-scylla/.doctrees/api/cassandra/decoder.doctree b/3.25.4-scylla/.doctrees/api/cassandra/decoder.doctree new file mode 100644 index 0000000000..ab40fd5f45 Binary files /dev/null and b/3.25.4-scylla/.doctrees/api/cassandra/decoder.doctree differ diff --git a/3.25.4-scylla/.doctrees/api/cassandra/encoder.doctree b/3.25.4-scylla/.doctrees/api/cassandra/encoder.doctree new file mode 100644 index 0000000000..4cef63b3ca Binary files /dev/null and b/3.25.4-scylla/.doctrees/api/cassandra/encoder.doctree differ diff --git a/3.25.4-scylla/.doctrees/api/cassandra/graph.doctree b/3.25.4-scylla/.doctrees/api/cassandra/graph.doctree new file mode 100644 index 0000000000..d891cf73e1 Binary files /dev/null and b/3.25.4-scylla/.doctrees/api/cassandra/graph.doctree differ diff --git a/3.25.4-scylla/.doctrees/api/cassandra/io/asyncioreactor.doctree b/3.25.4-scylla/.doctrees/api/cassandra/io/asyncioreactor.doctree new file mode 100644 index 0000000000..7ad5010979 Binary files /dev/null and b/3.25.4-scylla/.doctrees/api/cassandra/io/asyncioreactor.doctree differ diff --git a/3.25.4-scylla/.doctrees/api/cassandra/io/asyncorereactor.doctree b/3.25.4-scylla/.doctrees/api/cassandra/io/asyncorereactor.doctree new file mode 100644 index 0000000000..c3d28bb9e6 Binary files /dev/null and b/3.25.4-scylla/.doctrees/api/cassandra/io/asyncorereactor.doctree differ diff --git a/3.25.4-scylla/.doctrees/api/cassandra/io/eventletreactor.doctree b/3.25.4-scylla/.doctrees/api/cassandra/io/eventletreactor.doctree new file mode 100644 index 0000000000..ffd1262234 Binary files /dev/null and b/3.25.4-scylla/.doctrees/api/cassandra/io/eventletreactor.doctree differ diff --git a/3.25.4-scylla/.doctrees/api/cassandra/io/geventreactor.doctree b/3.25.4-scylla/.doctrees/api/cassandra/io/geventreactor.doctree new file mode 100644 index 0000000000..b318249bb2 Binary files /dev/null and b/3.25.4-scylla/.doctrees/api/cassandra/io/geventreactor.doctree differ diff --git a/3.25.4-scylla/.doctrees/api/cassandra/io/libevreactor.doctree b/3.25.4-scylla/.doctrees/api/cassandra/io/libevreactor.doctree new file mode 100644 index 0000000000..495ae6f7ef Binary files /dev/null and b/3.25.4-scylla/.doctrees/api/cassandra/io/libevreactor.doctree differ diff --git a/3.25.4-scylla/.doctrees/api/cassandra/io/twistedreactor.doctree b/3.25.4-scylla/.doctrees/api/cassandra/io/twistedreactor.doctree new file mode 100644 index 0000000000..c9d0b35299 Binary files /dev/null and b/3.25.4-scylla/.doctrees/api/cassandra/io/twistedreactor.doctree differ diff --git a/3.25.4-scylla/.doctrees/api/cassandra/metadata.doctree b/3.25.4-scylla/.doctrees/api/cassandra/metadata.doctree new file mode 100644 index 0000000000..0102fa8aa6 Binary files /dev/null and b/3.25.4-scylla/.doctrees/api/cassandra/metadata.doctree differ diff --git a/3.25.4-scylla/.doctrees/api/cassandra/metrics.doctree b/3.25.4-scylla/.doctrees/api/cassandra/metrics.doctree new file mode 100644 index 0000000000..aed135e64c Binary files /dev/null and b/3.25.4-scylla/.doctrees/api/cassandra/metrics.doctree differ diff --git a/3.25.4-scylla/.doctrees/api/cassandra/policies.doctree b/3.25.4-scylla/.doctrees/api/cassandra/policies.doctree new file mode 100644 index 0000000000..e530a1c53a Binary files /dev/null and b/3.25.4-scylla/.doctrees/api/cassandra/policies.doctree differ diff --git a/3.25.4-scylla/.doctrees/api/cassandra/pool.doctree b/3.25.4-scylla/.doctrees/api/cassandra/pool.doctree new file mode 100644 index 0000000000..3369e5700b Binary files /dev/null and b/3.25.4-scylla/.doctrees/api/cassandra/pool.doctree differ diff --git a/3.25.4-scylla/.doctrees/api/cassandra/protocol.doctree b/3.25.4-scylla/.doctrees/api/cassandra/protocol.doctree new file mode 100644 index 0000000000..ab9b43c163 Binary files /dev/null and b/3.25.4-scylla/.doctrees/api/cassandra/protocol.doctree differ diff --git a/3.25.4-scylla/.doctrees/api/cassandra/query.doctree b/3.25.4-scylla/.doctrees/api/cassandra/query.doctree new file mode 100644 index 0000000000..b38f493670 Binary files /dev/null and b/3.25.4-scylla/.doctrees/api/cassandra/query.doctree differ diff --git a/3.25.4-scylla/.doctrees/api/cassandra/timestamps.doctree b/3.25.4-scylla/.doctrees/api/cassandra/timestamps.doctree new file mode 100644 index 0000000000..25e02600c1 Binary files /dev/null and b/3.25.4-scylla/.doctrees/api/cassandra/timestamps.doctree differ diff --git a/3.25.4-scylla/.doctrees/api/cassandra/util.doctree b/3.25.4-scylla/.doctrees/api/cassandra/util.doctree new file mode 100644 index 0000000000..6d993b0aaa Binary files /dev/null and b/3.25.4-scylla/.doctrees/api/cassandra/util.doctree differ diff --git a/3.25.4-scylla/.doctrees/api/index.doctree b/3.25.4-scylla/.doctrees/api/index.doctree new file mode 100644 index 0000000000..516fdba852 Binary files /dev/null and b/3.25.4-scylla/.doctrees/api/index.doctree differ diff --git a/3.25.4-scylla/.doctrees/cqlengine/batches.doctree b/3.25.4-scylla/.doctrees/cqlengine/batches.doctree new file mode 100644 index 0000000000..5d67556dbe Binary files /dev/null and b/3.25.4-scylla/.doctrees/cqlengine/batches.doctree differ diff --git a/3.25.4-scylla/.doctrees/cqlengine/connections.doctree b/3.25.4-scylla/.doctrees/cqlengine/connections.doctree new file mode 100644 index 0000000000..391a6fe8ee Binary files /dev/null and b/3.25.4-scylla/.doctrees/cqlengine/connections.doctree differ diff --git a/3.25.4-scylla/.doctrees/cqlengine/faq.doctree b/3.25.4-scylla/.doctrees/cqlengine/faq.doctree new file mode 100644 index 0000000000..718efb9e0a Binary files /dev/null and b/3.25.4-scylla/.doctrees/cqlengine/faq.doctree differ diff --git a/3.25.4-scylla/.doctrees/cqlengine/models.doctree b/3.25.4-scylla/.doctrees/cqlengine/models.doctree new file mode 100644 index 0000000000..32496e246e Binary files /dev/null and b/3.25.4-scylla/.doctrees/cqlengine/models.doctree differ diff --git a/3.25.4-scylla/.doctrees/cqlengine/queryset.doctree b/3.25.4-scylla/.doctrees/cqlengine/queryset.doctree new file mode 100644 index 0000000000..408f69dd34 Binary files /dev/null and b/3.25.4-scylla/.doctrees/cqlengine/queryset.doctree differ diff --git a/3.25.4-scylla/.doctrees/cqlengine/third_party.doctree b/3.25.4-scylla/.doctrees/cqlengine/third_party.doctree new file mode 100644 index 0000000000..6a1b2b6db1 Binary files /dev/null and b/3.25.4-scylla/.doctrees/cqlengine/third_party.doctree differ diff --git a/3.25.4-scylla/.doctrees/cqlengine/upgrade_guide.doctree b/3.25.4-scylla/.doctrees/cqlengine/upgrade_guide.doctree new file mode 100644 index 0000000000..63c5909d55 Binary files /dev/null and b/3.25.4-scylla/.doctrees/cqlengine/upgrade_guide.doctree differ diff --git a/3.25.4-scylla/.doctrees/dates_and_times.doctree b/3.25.4-scylla/.doctrees/dates_and_times.doctree new file mode 100644 index 0000000000..cb4c3c3bf2 Binary files /dev/null and b/3.25.4-scylla/.doctrees/dates_and_times.doctree differ diff --git a/3.25.4-scylla/.doctrees/environment.pickle b/3.25.4-scylla/.doctrees/environment.pickle new file mode 100644 index 0000000000..43c3ba3873 Binary files /dev/null and b/3.25.4-scylla/.doctrees/environment.pickle differ diff --git a/3.25.4-scylla/.doctrees/execution_profiles.doctree b/3.25.4-scylla/.doctrees/execution_profiles.doctree new file mode 100644 index 0000000000..99b5930ab7 Binary files /dev/null and b/3.25.4-scylla/.doctrees/execution_profiles.doctree differ diff --git a/3.25.4-scylla/.doctrees/faq.doctree b/3.25.4-scylla/.doctrees/faq.doctree new file mode 100644 index 0000000000..c2ad9c0c9f Binary files /dev/null and b/3.25.4-scylla/.doctrees/faq.doctree differ diff --git a/3.25.4-scylla/.doctrees/getting_started.doctree b/3.25.4-scylla/.doctrees/getting_started.doctree new file mode 100644 index 0000000000..876473cfeb Binary files /dev/null and b/3.25.4-scylla/.doctrees/getting_started.doctree differ diff --git a/3.25.4-scylla/.doctrees/index.doctree b/3.25.4-scylla/.doctrees/index.doctree new file mode 100644 index 0000000000..10af6a681e Binary files /dev/null and b/3.25.4-scylla/.doctrees/index.doctree differ diff --git a/3.25.4-scylla/.doctrees/installation.doctree b/3.25.4-scylla/.doctrees/installation.doctree new file mode 100644 index 0000000000..5c4d43c2c3 Binary files /dev/null and b/3.25.4-scylla/.doctrees/installation.doctree differ diff --git a/3.25.4-scylla/.doctrees/lwt.doctree b/3.25.4-scylla/.doctrees/lwt.doctree new file mode 100644 index 0000000000..25635de0c7 Binary files /dev/null and b/3.25.4-scylla/.doctrees/lwt.doctree differ diff --git a/3.25.4-scylla/.doctrees/object_mapper.doctree b/3.25.4-scylla/.doctrees/object_mapper.doctree new file mode 100644 index 0000000000..ee4f5d510e Binary files /dev/null and b/3.25.4-scylla/.doctrees/object_mapper.doctree differ diff --git a/3.25.4-scylla/.doctrees/performance.doctree b/3.25.4-scylla/.doctrees/performance.doctree new file mode 100644 index 0000000000..053dce3021 Binary files /dev/null and b/3.25.4-scylla/.doctrees/performance.doctree differ diff --git a/3.25.4-scylla/.doctrees/query_paging.doctree b/3.25.4-scylla/.doctrees/query_paging.doctree new file mode 100644 index 0000000000..582a20d6c6 Binary files /dev/null and b/3.25.4-scylla/.doctrees/query_paging.doctree differ diff --git a/3.25.4-scylla/.doctrees/scylla_cloud.doctree b/3.25.4-scylla/.doctrees/scylla_cloud.doctree new file mode 100644 index 0000000000..5742eb6261 Binary files /dev/null and b/3.25.4-scylla/.doctrees/scylla_cloud.doctree differ diff --git a/3.25.4-scylla/.doctrees/scylla_specific.doctree b/3.25.4-scylla/.doctrees/scylla_specific.doctree new file mode 100644 index 0000000000..723bf5b2dd Binary files /dev/null and b/3.25.4-scylla/.doctrees/scylla_specific.doctree differ diff --git a/3.25.4-scylla/.doctrees/security.doctree b/3.25.4-scylla/.doctrees/security.doctree new file mode 100644 index 0000000000..69a997ade7 Binary files /dev/null and b/3.25.4-scylla/.doctrees/security.doctree differ diff --git a/3.25.4-scylla/.doctrees/upgrading.doctree b/3.25.4-scylla/.doctrees/upgrading.doctree new file mode 100644 index 0000000000..689c5e613d Binary files /dev/null and b/3.25.4-scylla/.doctrees/upgrading.doctree differ diff --git a/3.25.4-scylla/.doctrees/user_defined_types.doctree b/3.25.4-scylla/.doctrees/user_defined_types.doctree new file mode 100644 index 0000000000..b6f250621e Binary files /dev/null and b/3.25.4-scylla/.doctrees/user_defined_types.doctree differ diff --git a/3.25.4-scylla/.nojekyll b/3.25.4-scylla/.nojekyll new file mode 100644 index 0000000000..e69de29bb2 diff --git a/3.25.4-scylla/404.html b/3.25.4-scylla/404.html new file mode 100644 index 0000000000..d60936cbfe --- /dev/null +++ b/3.25.4-scylla/404.html @@ -0,0 +1,31 @@ + + + + + + + + + ScyllaDB + + + + + + + + + + + +
+

404

+

The ScyllaDB monster ate your page!

+

+ Home +

+
+ + + \ No newline at end of file diff --git a/3.25.4-scylla/CHANGELOG.html b/3.25.4-scylla/CHANGELOG.html new file mode 100644 index 0000000000..214e999bd0 --- /dev/null +++ b/3.25.4-scylla/CHANGELOG.html @@ -0,0 +1,2918 @@ + + + + + + + + + + + + + CHANGELOG | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

CHANGELOG

+
+

3.25.0

+

March 18, 2021

+
+

Features

+
    +
  • Ensure the driver can connect when invalid peer hosts are in system.peers (PYTHON-1260)

  • +
  • Implement protocol v5 checksumming (PYTHON-1258)

  • +
  • Fix the default cqlengine connection mechanism to work with Astra (PYTHON-1265)

  • +
+
+
+

Bug Fixes

+
    +
  • Asyncore race condition cause logging exception on shutdown (PYTHON-1266)

  • +
  • Update list of reserved keywords (PYTHON-1269)

  • +
+
+
+

Others

+
    +
  • Drop Python 3.4 support (PYTHON-1220)

  • +
  • Update security documentation and examples to use PROTOCOL_TLS (PYTHON-1264)

  • +
+
+
+
+

3.24.0

+

June 18, 2020

+
+

Features

+
    +
  • Make geomet an optional dependency at runtime (PYTHON-1237)

  • +
  • Add use_default_tempdir cloud config options (PYTHON-1245)

  • +
  • Tcp flow control for libevreactor (PYTHON-1248)

  • +
+
+
+

Bug Fixes

+
    +
  • Unable to connect to a cloud cluster using Ubuntu 20.04 (PYTHON-1238)

  • +
  • PlainTextAuthProvider fails with unicode chars and Python3 (PYTHON-1241)

  • +
  • [GRAPH] Graph execution profiles consistency level are not set to LOCAL_QUORUM with a cloud cluster (PYTHON-1240)

  • +
  • [GRAPH] Can’t write data in a Boolean field using the Fluent API (PYTHON-1239)

  • +
  • [GRAPH] Fix elementMap() result deserialization (PYTHON-1233)

  • +
+
+
+

Others

+
    +
  • Bump geomet dependency version to 0.2 (PYTHON-1243)

  • +
  • Bump gremlinpython dependency version to 3.4.6 (PYTHON-1212)

  • +
  • Improve fluent graph documentation for core graphs (PYTHON-1244)

  • +
+
+
+
+

3.23.0

+

April 6, 2020

+
+

Features

+
    +
  • Transient Replication Support (PYTHON-1207)

  • +
  • Support system.peers_v2 and port discovery for C* 4.0 (PYTHON-700)

  • +
+
+
+

Bug Fixes

+
    +
  • Asyncore logging exception on shutdown (PYTHON-1228)

  • +
+
+
+
+

3.22.0

+

February 26, 2020

+
+

Features

+
    +
  • Add all() function to the ResultSet API (PYTHON-1203)

  • +
  • Parse new schema metadata in NGDG and generate table edges CQL syntax (PYTHON-996)

  • +
  • Add GraphSON3 support (PYTHON-788)

  • +
  • Use GraphSON3 as default for Native graphs (PYTHON-1004)

  • +
  • Add Tuple and UDT types for native graph (PYTHON-1005)

  • +
  • Add Duration type for native graph (PYTHON-1000)

  • +
  • Add gx:ByteBuffer graphson type support for Blob field (PYTHON-1027)

  • +
  • Enable Paging Through DSE Driver for Gremlin Traversals (PYTHON-1045)

  • +
  • Provide numerical wrappers to ensure proper graphson schema definition (PYTHON-1051)

  • +
  • Resolve the row_factory automatically for native graphs (PYTHON-1056)

  • +
  • Add g:TraversalMetrics/g:Metrics graph deserializers (PYTHON-1057)

  • +
  • Add g:BulkSet graph deserializers (PYTHON-1060)

  • +
  • Update Graph Engine names and the way to create a Classic/Native Graph (PYTHON-1090)

  • +
  • Update Native to Core Graph Engine

  • +
  • Add graphson3 and native graph support (PYTHON-1039)

  • +
  • Enable Paging Through DSE Driver for Gremlin Traversals (PYTHON-1045)

  • +
  • Expose filter predicates for cql collections (PYTHON-1019)

  • +
  • Add g:TraversalMetrics/Metrics deserializers (PYTHON-1057)

  • +
  • Make graph metadata handling more robust (PYTHON-1204)

  • +
+
+
+

Bug Fixes

+
    +
  • Make sure to only query the native_transport_address column with DSE (PYTHON-1205)

  • +
+
+
+
+

3.21.0

+

January 15, 2020

+
+

Features

+
    +
  • Unified driver: merge core and DSE drivers into a single package (PYTHON-1130)

  • +
  • Add Python 3.8 support (PYTHON-1189)

  • +
  • Allow passing ssl context for Twisted (PYTHON-1161)

  • +
  • Ssl context and cloud support for Eventlet (PYTHON-1162)

  • +
  • Cloud Twisted support (PYTHON-1163)

  • +
  • Add additional_write_policy and read_repair to system schema parsing (PYTHON-1048)

  • +
  • Flexible version parsing (PYTHON-1174)

  • +
  • Support NULL in collection deserializer (PYTHON-1123)

  • +
  • [GRAPH] Ability to execute Fluent Graph queries asynchronously (PYTHON-1129)

  • +
+
+
+

Bug Fixes

+
    +
  • Handle prepared id mismatch when repreparing on the fly (PYTHON-1124)

  • +
  • re-raising the CQLEngineException will fail on Python 3 (PYTHON-1166)

  • +
  • asyncio message chunks can be processed discontinuously (PYTHON-1185)

  • +
  • Reconnect attempts persist after downed node removed from peers (PYTHON-1181)

  • +
  • Connection fails to validate ssl certificate hostname when SSLContext.check_hostname is set (PYTHON-1186)

  • +
  • ResponseFuture._set_result crashes on connection error when used with PrepareMessage (PYTHON-1187)

  • +
  • Insights fail to serialize the startup message when the SSL Context is from PyOpenSSL (PYTHON-1192)

  • +
+
+
+

Others

+
    +
  • The driver has a new dependency: geomet. It comes from the dse-driver unification and +is used to support DSE geo types.

  • +
  • Remove *read_repair_chance table options (PYTHON-1140)

  • +
  • Avoid warnings about unspecified load balancing policy when connecting to a cloud cluster (PYTHON-1177)

  • +
  • Add new DSE CQL keywords (PYTHON-1122)

  • +
  • Publish binary wheel distributions (PYTHON-1013)

  • +
+
+
+

Deprecations

+
    +
  • DSELoadBalancingPolicy will be removed in the next major, consider using +the DefaultLoadBalancingPolicy.

  • +
+

Merged from dse-driver:

+
+
+

Features

+
    +
  • Insights integration (PYTHON-1047)

  • +
  • Graph execution profiles should preserve their graph_source when graph_options is overridden (PYTHON-1021)

  • +
  • Add NodeSync metadata (PYTHON-799)

  • +
  • Add new NodeSync failure values (PYTHON-934)

  • +
  • DETERMINISTIC and MONOTONIC Clauses for Functions and Aggregates (PYTHON-955)

  • +
  • GraphOptions should show a warning for unknown parameters (PYTHON-819)

  • +
  • DSE protocol version 2 and continous paging backpressure (PYTHON-798)

  • +
  • GraphSON2 Serialization/Deserialization Support (PYTHON-775)

  • +
  • Add graph-results payload option for GraphSON format (PYTHON-773)

  • +
  • Create an AuthProvider for the DSE transitional mode (PYTHON-831)

  • +
  • Implement serializers for the Graph String API (PYTHON-778)

  • +
  • Provide deserializers for GraphSON types (PYTHON-782)

  • +
  • Add Graph DurationType support (PYTHON-607)

  • +
  • Support DSE DateRange type (PYTHON-668)

  • +
  • RLAC CQL output for materialized views (PYTHON-682)

  • +
  • Add Geom Types wkt deserializer

  • +
  • DSE Graph Client timeouts in custom payload (PYTHON-589)

  • +
  • Make DSEGSSAPIAuthProvider accept principal name (PYTHON-574)

  • +
  • Add config profiles to DSE graph execution (PYTHON-570)

  • +
  • DSE Driver version checking (PYTHON-568)

  • +
  • Distinct default timeout for graph queries (PYTHON-477)

  • +
  • Graph result parsing for known types (PYTHON-479,487)

  • +
  • Distinct read/write CL for graph execution (PYTHON-509)

  • +
  • Target graph analytics query to spark master when available (PYTHON-510)

  • +
+
+
+

Bug Fixes

+
    +
  • Continuous paging sessions raise RuntimeError when results are not entirely consumed (PYTHON-1054)

  • +
  • GraphSON Property deserializer should return a dict instead of a set (PYTHON-1033)

  • +
  • ResponseFuture.has_more_pages may hold the wrong value (PYTHON-946)

  • +
  • DETERMINISTIC clause in AGGREGATE misplaced in CQL generation (PYTHON-963)

  • +
  • graph module import cause a DLL issue on Windows due to its cythonizing failure (PYTHON-900)

  • +
  • Update date serialization to isoformat in graph (PYTHON-805)

  • +
  • DateRange Parse Error (PYTHON-729)

  • +
  • MontonicTimestampGenerator.__init__ ignores class defaults (PYTHON-728)

  • +
  • metadata.get_host returning None unexpectedly (PYTHON-709)

  • +
  • Sockets associated with sessions not getting cleaned up on session.shutdown() (PYTHON-673)

  • +
  • Resolve FQDN from ip address and use that as host passed to SASLClient (PYTHON-566)

  • +
  • Geospatial type implementations don’t handle ‘EMPTY’ values. (PYTHON-481)

  • +
  • Correctly handle other types in geo type equality (PYTHON-508)

  • +
+
+
+

Other

+
    +
  • Add tests around cqlengine and continuous paging (PYTHON-872)

  • +
  • Add an abstract GraphStatement to handle different graph statements (PYTHON-789)

  • +
  • Write documentation examples for DSE 2.0 features (PYTHON-732)

  • +
  • DSE_V1 protocol should not include all of protocol v5 (PYTHON-694)

  • +
+
+
+
+

3.20.2

+

November 19, 2019

+
+

Bug Fixes

+
    +
  • Fix import error for old python installation without SSLContext (PYTHON-1183)

  • +
+
+
+
+

3.20.1

+

November 6, 2019

+
+

Bug Fixes

+
    +
  • ValueError: too many values to unpack (expected 2)” when there are two dashes in server version number (PYTHON-1172)

  • +
+
+
+
+

3.20.0

+

October 28, 2019

+
+

Features

+
    +
  • DataStax Astra Support (PYTHON-1074)

  • +
  • Use 4.0 schema parser in 4 alpha and snapshot builds (PYTHON-1158)

  • +
+
+
+

Bug Fixes

+
    +
  • Connection setup methods prevent using ExecutionProfile in cqlengine (PYTHON-1009)

  • +
  • Driver deadlock if all connections dropped by heartbeat whilst request in flight and request times out (PYTHON-1044)

  • +
  • Exception when use pk__token__gt filter In python 3.7 (PYTHON-1121)

  • +
+
+
+
+

3.19.0

+

August 26, 2019

+
+

Features

+
    +
  • Add Python 3.7 support (PYTHON-1016)

  • +
  • Future-proof Mapping imports (PYTHON-1023)

  • +
  • Include param values in cqlengine logging (PYTHON-1105)

  • +
  • NTS Token Replica Map Generation is slow (PYTHON-622)

  • +
+
+
+

Bug Fixes

+
    +
  • as_cql_query UDF/UDA parameters incorrectly includes “frozen” if arguments are collections (PYTHON-1031)

  • +
  • cqlengine does not currently support combining TTL and TIMESTAMP on INSERT (PYTHON-1093)

  • +
  • Fix incorrect metadata for compact counter tables (PYTHON-1100)

  • +
  • Call ConnectionException with correct kwargs (PYTHON-1117)

  • +
  • Can’t connect to clusters built from source because version parsing doesn’t handle ‘x.y-SNAPSHOT’ (PYTHON-1118)

  • +
  • Discovered node doesn´t honor the configured Cluster port on connection (PYTHON-1127)

  • +
  • Exception when use pk__token__gt filter In python 3.7 (PYTHON-1121)

  • +
+
+
+

Other

+
    +
  • Remove invalid warning in set_session when we initialize a default connection (PYTHON-1104)

  • +
  • Set the proper default ExecutionProfile.row_factory value (PYTHON-1119)

  • +
+
+
+
+

3.18.0

+

May 27, 2019

+
+

Features

+
    +
  • Abstract Host Connection information (PYTHON-1079)

  • +
  • Improve version parsing to support a non-integer 4th component (PYTHON-1091)

  • +
  • Expose on_request_error method in the RetryPolicy (PYTHON-1064)

  • +
  • Add jitter to ExponentialReconnectionPolicy (PYTHON-1065)

  • +
+
+
+

Bug Fixes

+
    +
  • Fix error when preparing queries with beta protocol v5 (PYTHON-1081)

  • +
  • Accept legacy empty strings as column names (PYTHON-1082)

  • +
  • Let util.SortedSet handle uncomparable elements (PYTHON-1087)

  • +
+
+
+
+

3.17.1

+

May 2, 2019

+
+

Bug Fixes

+
    +
  • Socket errors EAGAIN/EWOULDBLOCK are not handled properly and cause timeouts (PYTHON-1089)

  • +
+
+
+
+

3.17.0

+

February 19, 2019

+
+

Features

+
    +
  • Send driver name and version in startup message (PYTHON-1068)

  • +
  • Add Cluster ssl_context option to enable SSL (PYTHON-995)

  • +
  • Allow encrypted private keys for 2-way SSL cluster connections (PYTHON-995)

  • +
  • Introduce new method ConsistencyLevel.is_serial (PYTHON-1067)

  • +
  • Add Session.get_execution_profile (PYTHON-932)

  • +
  • Add host kwarg to Session.execute/execute_async APIs to send a query to a specific node (PYTHON-993)

  • +
+
+
+

Bug Fixes

+
    +
  • NoHostAvailable when all hosts are up and connectable (PYTHON-891)

  • +
  • Serial consistency level is not used (PYTHON-1007)

  • +
+
+
+

Other

+
    +
  • Fail faster on incorrect lz4 import (PYTHON-1042)

  • +
  • Bump Cython dependency version to 0.29 (PYTHON-1036)

  • +
  • Expand Driver SSL Documentation (PYTHON-740)

  • +
+
+
+

Deprecations

+
    +
  • Using Cluster.ssl_options to enable SSL is deprecated and will be removed in +the next major release, use ssl_context.

  • +
  • DowngradingConsistencyRetryPolicy is deprecated and will be +removed in the next major release. (PYTHON-937)

  • +
+
+
+
+

3.16.0

+

November 12, 2018

+
+

Bug Fixes

+
    +
  • Improve and fix socket error-catching code in nonblocking-socket reactors (PYTHON-1024)

  • +
  • Non-ASCII characters in schema break CQL string generation (PYTHON-1008)

  • +
  • Fix OSS driver’s virtual table support against DSE 6.0.X and future server releases (PYTHON-1020)

  • +
  • ResultSet.one() fails if the row_factory is using a generator (PYTHON-1026)

  • +
  • Log profile name on attempt to create existing profile (PYTHON-944)

  • +
  • Cluster instantiation fails if any contact points’ hostname resolution fails (PYTHON-895)

  • +
+
+
+

Other

+
    +
  • Fix tests when RF is not maintained if we decomission a node (PYTHON-1017)

  • +
  • Fix wrong use of ResultSet indexing (PYTHON-1015)

  • +
+
+
+
+

3.15.1

+

September 6, 2018

+
+

Bug Fixes

+
    +
  • C* 4.0 schema-parsing logic breaks running against DSE 6.0.X (PYTHON-1018)

  • +
+
+
+
+

3.15.0

+

August 30, 2018

+
+

Features

+
    +
  • Parse Virtual Keyspace Metadata (PYTHON-992)

  • +
+
+
+

Bug Fixes

+
    +
  • Tokenmap.get_replicas returns the wrong value if token coincides with the end of the range (PYTHON-978)

  • +
  • Python Driver fails with “more than 255 arguments” python exception when > 255 columns specified in query response (PYTHON-893)

  • +
  • Hang in integration.standard.test_cluster.ClusterTests.test_set_keyspace_twice (PYTHON-998)

  • +
  • Asyncore reactors should use a global variable instead of a class variable for the event loop (PYTHON-697)

  • +
+
+
+

Other

+
    +
  • Use global variable for libev loops so it can be subclassed (PYTHON-973)

  • +
  • Update SchemaParser for V4 (PYTHON-1006)

  • +
  • Bump Cython dependency version to 0.28 (PYTHON-1012)

  • +
+
+
+
+

3.14.0

+

April 17, 2018

+
+

Features

+
    +
  • Add one() function to the ResultSet API (PYTHON-947)

  • +
  • Create an utility function to fetch concurrently many keys from the same replica (PYTHON-647)

  • +
  • Allow filter queries with fields that have an index managed outside of cqlengine (PYTHON-966)

  • +
  • Twisted SSL Support (PYTHON-343)

  • +
  • Support IS NOT NULL operator in cqlengine (PYTHON-968)

  • +
+
+
+

Other

+
    +
  • Fix Broken Links in Docs (PYTHON-916)

  • +
  • Reevaluate MONKEY_PATCH_LOOP in test codebase (PYTHON-903)

  • +
  • Remove CASS_SERVER_VERSION and replace it for CASSANDRA_VERSION in tests (PYTHON-910)

  • +
  • Refactor CASSANDRA_VERSION to a some kind of version object (PYTHON-915)

  • +
  • Log warning when driver configures an authenticator, but server does not request authentication (PYTHON-940)

  • +
  • Warn users when using the deprecated Session.default_consistency_level (PYTHON-953)

  • +
  • Add DSE smoke test to OSS driver tests (PYTHON-894)

  • +
  • Document long compilation times and workarounds (PYTHON-868)

  • +
  • Improve error for batch WriteTimeouts (PYTHON-941)

  • +
  • Deprecate ResultSet indexing (PYTHON-945)

  • +
+
+
+
+

3.13.0

+

January 30, 2018

+
+

Features

+
    +
  • cqlengine: LIKE filter operator (PYTHON-512)

  • +
  • Support cassandra.query.BatchType with cqlengine BatchQuery (PYTHON-888)

  • +
+
+
+

Bug Fixes

+
    +
  • AttributeError: ‘NoneType’ object has no attribute ‘add_timer’ (PYTHON-862)

  • +
  • Support retry_policy in PreparedStatement (PYTHON-861)

  • +
  • __del__ method in Session is throwing an exception (PYTHON-813)

  • +
  • LZ4 import issue with recent versions (PYTHON-897)

  • +
  • ResponseFuture._connection can be None when returning request_id (PYTHON-853)

  • +
  • ResultSet.was_applied doesn’t support batch with LWT statements (PYTHON-848)

  • +
+
+
+

Other

+
    +
  • cqlengine: avoid warning when unregistering connection on shutdown (PYTHON-865)

  • +
  • Fix DeprecationWarning of log.warn (PYTHON-846)

  • +
  • Fix example_mapper.py for python3 (PYTHON-860)

  • +
  • Possible deadlock on cassandra.concurrent.execute_concurrent (PYTHON-768)

  • +
  • Add some known deprecated warnings for 4.x (PYTHON-877)

  • +
  • Remove copyright dates from copyright notices (PYTHON-863)

  • +
  • Remove “Experimental” tag from execution profiles documentation (PYTHON-840)

  • +
  • request_timer metrics descriptions are slightly incorrect (PYTHON-885)

  • +
  • Remove “Experimental” tag from cqlengine connections documentation (PYTHON-892)

  • +
  • Set in documentation default consistency for operations is LOCAL_ONE (PYTHON-901)

  • +
+
+
+
+

3.12.0

+

November 6, 2017

+
+

Features

+
    +
  • Send keyspace in QUERY, PREPARE, and BATCH messages (PYTHON-678)

  • +
  • Add IPv4Address/IPv6Address support for inet types (PYTHON-751)

  • +
  • WriteType.CDC and VIEW missing (PYTHON-794)

  • +
  • Warn on Cluster init if contact points are specified but LBP isn’t (legacy mode) (PYTHON-812)

  • +
  • Warn on Cluster init if contact points are specified but LBP isn’t (exection profile mode) (PYTHON-838)

  • +
  • Include hash of result set metadata in prepared stmt id (PYTHON-808)

  • +
  • Add NO_COMPACT startup option (PYTHON-839)

  • +
  • Add new exception type for CDC (PYTHON-837)

  • +
  • Allow 0ms in ConstantSpeculativeExecutionPolicy (PYTHON-836)

  • +
  • Add asyncio reactor (PYTHON-507)

  • +
+
+
+

Bug Fixes

+
    +
  • Both _set_final_exception/result called for the same ResponseFuture (PYTHON-630)

  • +
  • Use of DCAwareRoundRobinPolicy raises NoHostAvailable exception (PYTHON-781)

  • +
  • Not create two sessions by default in CQLEngine (PYTHON-814)

  • +
  • Bug when subclassing AyncoreConnection (PYTHON-827)

  • +
  • Error at cleanup when closing the asyncore connections (PYTHON-829)

  • +
  • Fix sites where sessions can change during iteration (PYTHON-793)

  • +
  • cqlengine: allow min_length=0 for Ascii and Text column types (PYTHON-735)

  • +
  • Rare exception when “sys.exit(0)” after query timeouts (PYTHON-752)

  • +
  • Dont set the session keyspace when preparing statements (PYTHON-843)

  • +
  • Use of DCAwareRoundRobinPolicy raises NoHostAvailable exception (PYTHON-781)

  • +
+
+
+

Other

+
    +
  • Remove DeprecationWarning when using WhiteListRoundRobinPolicy (PYTHON-810)

  • +
  • Bump Cython dependency version to 0.27 (PYTHON-833)

  • +
+
+
+
+

3.11.0

+

July 24, 2017

+
+

Features

+
    +
  • Add idle_heartbeat_timeout cluster option to tune how long to wait for heartbeat responses. (PYTHON-762)

  • +
  • Add HostFilterPolicy (PYTHON-761)

  • +
+
+
+

Bug Fixes

+
    +
  • is_idempotent flag is not propagated from PreparedStatement to BoundStatement (PYTHON-736)

  • +
  • Fix asyncore hang on exit (PYTHON-767)

  • +
  • Driver takes several minutes to remove a bad host from session (PYTHON-762)

  • +
  • Installation doesn’t always fall back to no cython in Windows (PYTHON-763)

  • +
  • Avoid to replace a connection that is supposed to shutdown (PYTHON-772)

  • +
  • request_ids may not be returned to the pool (PYTHON-739)

  • +
  • Fix murmur3 on big-endian systems (PYTHON-653)

  • +
  • Ensure unused connections are closed if a Session is deleted by the GC (PYTHON-774)

  • +
  • Fix .values_list by using db names internally (cqlengine) (PYTHON-785)

  • +
+
+
+

Other

+
    +
  • Bump Cython dependency version to 0.25.2 (PYTHON-754)

  • +
  • Fix DeprecationWarning when using lz4 (PYTHON-769)

  • +
  • Deprecate WhiteListRoundRobinPolicy (PYTHON-759)

  • +
  • Improve upgrade guide for materializing pages (PYTHON-464)

  • +
  • Documentation for time/date specifies timestamp inupt as microseconds (PYTHON-717)

  • +
  • Point to DSA Slack, not IRC, in docs index

  • +
+
+
+
+

3.10.0

+

May 24, 2017

+
+

Features

+
    +
  • Add Duration type to cqlengine (PYTHON-750)

  • +
  • Community PR review: Raise error on primary key update only if its value changed (PYTHON-705)

  • +
  • get_query_trace() contract is ambiguous (PYTHON-196)

  • +
+
+
+

Bug Fixes

+
    +
  • Queries using speculative execution policy timeout prematurely (PYTHON-755)

  • +
  • Fix map where results are not consumed (PYTHON-749)

  • +
  • Driver fails to encode Duration’s with large values (PYTHON-747)

  • +
  • UDT values are not updated correctly in CQLEngine (PYTHON-743)

  • +
  • UDT types are not validated in CQLEngine (PYTHON-742)

  • +
  • to_python is not implemented for types columns.Type and columns.Date in CQLEngine (PYTHON-741)

  • +
  • Clients spin infinitely trying to connect to a host that is drained (PYTHON-734)

  • +
  • Resulset.get_query_trace returns empty trace sometimes (PYTHON-730)

  • +
  • Memory grows and doesn’t get removed (PYTHON-720)

  • +
  • Fix RuntimeError caused by change dict size during iteration (PYTHON-708)

  • +
  • fix ExponentialReconnectionPolicy may throw OverflowError problem (PYTHON-707)

  • +
  • Avoid using nonexistent prepared statement in ResponseFuture (PYTHON-706)

  • +
+
+
+

Other

+
    +
  • Update README (PYTHON-746)

  • +
  • Test python versions 3.5 and 3.6 (PYTHON-737)

  • +
  • Docs Warning About Prepare select * (PYTHON-626)

  • +
  • Increase Coverage in CqlEngine Test Suite (PYTHON-505)

  • +
  • Example SSL connection code does not verify server certificates (PYTHON-469)

  • +
+
+
+
+

3.9.0

+
+

Features

+
    +
  • cqlengine: remove elements by key from a map (PYTHON-688)

  • +
+
+
+

Bug Fixes

+
    +
  • improve error handling when connecting to non-existent keyspace (PYTHON-665)

  • +
  • Sockets associated with sessions not getting cleaned up on session.shutdown() (PYTHON-673)

  • +
  • rare flake on integration.standard.test_cluster.ClusterTests.test_clone_shared_lbp (PYTHON-727)

  • +
  • MontonicTimestampGenerator.__init__ ignores class defaults (PYTHON-728)

  • +
  • race where callback or errback for request may not be called (PYTHON-733)

  • +
  • cqlengine: model.update() should not update columns with a default value that hasn’t changed (PYTHON-657)

  • +
  • cqlengine: field value manager’s explicit flag is True when queried back from cassandra (PYTHON-719)

  • +
+
+
+

Other

+
    +
  • Connection not closed in example_mapper (PYTHON-723)

  • +
  • Remove mention of pre-2.0 C* versions from OSS 3.0+ docs (PYTHON-710)

  • +
+
+
+
+

3.8.1

+

March 16, 2017

+
+

Bug Fixes

+
    +
  • implement __le__/__ge__/__ne__ on some custom types (PYTHON-714)

  • +
  • Fix bug in eventlet and gevent reactors that could cause hangs (PYTHON-721)

  • +
  • Fix DecimalType regression (PYTHON-724)

  • +
+
+
+
+

3.8.0

+
+

Features

+
    +
  • Quote index names in metadata CQL generation (PYTHON-616)

  • +
  • On column deserialization failure, keep error message consistent between python and cython (PYTHON-631)

  • +
  • TokenAwarePolicy always sends requests to the same replica for a given key (PYTHON-643)

  • +
  • Added cql types to result set (PYTHON-648)

  • +
  • Add __len__ to BatchStatement (PYTHON-650)

  • +
  • Duration Type for Cassandra (PYTHON-655)

  • +
  • Send flags with PREPARE message in v5 (PYTHON-684)

  • +
+
+
+

Bug Fixes

+
    +
  • Potential Timing issue if application exits prior to session pool initialization (PYTHON-636)

  • +
  • “Host X.X.X.X has been marked down” without any exceptions (PYTHON-640)

  • +
  • NoHostAvailable or OperationTimedOut when using execute_concurrent with a generator that inserts into more than one table (PYTHON-642)

  • +
  • ResponseFuture creates Timers and don’t cancel them even when result is received which leads to memory leaks (PYTHON-644)

  • +
  • Driver cannot connect to Cassandra version > 3 (PYTHON-646)

  • +
  • Unable to import model using UserType without setuping connection since 3.7 (PYTHON-649)

  • +
  • Don’t prepare queries on ignored hosts on_up (PYTHON-669)

  • +
  • Sockets associated with sessions not getting cleaned up on session.shutdown() (PYTHON-673)

  • +
  • Make client timestamps strictly monotonic (PYTHON-676)

  • +
  • cassandra.cqlengine.connection.register_connection broken when hosts=None (PYTHON-692)

  • +
+
+
+

Other

+
    +
  • Create a cqlengine doc section explaining None semantics (PYTHON-623)

  • +
  • Resolve warnings in documentation generation (PYTHON-645)

  • +
  • Cython dependency (PYTHON-686)

  • +
  • Drop Support for Python 2.6 (PYTHON-690)

  • +
+
+
+
+

3.7.1

+

October 26, 2016

+
+

Bug Fixes

+
    +
  • Cython upgrade has broken stable version of cassandra-driver (PYTHON-656)

  • +
+
+
+
+

3.7.0

+

September 13, 2016

+
+

Features

+
    +
  • Add v5 protocol failure map (PYTHON-619)

  • +
  • Don’t return from initial connect on first error (PYTHON-617)

  • +
  • Indicate failed column when deserialization fails (PYTHON-361)

  • +
  • Let Cluster.refresh_nodes force a token map rebuild (PYTHON-349)

  • +
  • Refresh UDTs after “keyspace updated” event with v1/v2 protocol (PYTHON-106)

  • +
  • EC2 Address Resolver (PYTHON-198)

  • +
  • Speculative query retries (PYTHON-218)

  • +
  • Expose paging state in API (PYTHON-200)

  • +
  • Don’t mark host down while one connection is active (PYTHON-498)

  • +
  • Query request size information (PYTHON-284)

  • +
  • Avoid quadratic ring processing with invalid replication factors (PYTHON-379)

  • +
  • Improve Connection/Pool creation concurrency on startup (PYTHON-82)

  • +
  • Add beta version native protocol flag (PYTHON-614)

  • +
  • cqlengine: Connections: support of multiple keyspaces and sessions (PYTHON-613)

  • +
+
+
+

Bug Fixes

+
    +
  • Race when adding a pool while setting keyspace (PYTHON-628)

  • +
  • Update results_metadata when prepared statement is reprepared (PYTHON-621)

  • +
  • CQL Export for Thrift Tables (PYTHON-213)

  • +
  • cqlengine: default value not applied to UserDefinedType (PYTHON-606)

  • +
  • cqlengine: columns are no longer hashable (PYTHON-618)

  • +
  • cqlengine: remove clustering keys from where clause when deleting only static columns (PYTHON-608)

  • +
+
+
+
+

3.6.0

+

August 1, 2016

+
+

Features

+
    +
  • Handle null values in NumpyProtocolHandler (PYTHON-553)

  • +
  • Collect greplin scales stats per cluster (PYTHON-561)

  • +
  • Update mock unit test dependency requirement (PYTHON-591)

  • +
  • Handle Missing CompositeType metadata following C* upgrade (PYTHON-562)

  • +
  • Improve Host.is_up state for HostDistance.IGNORED hosts (PYTHON-551)

  • +
  • Utilize v2 protocol’s ability to skip result set metadata for prepared statement execution (PYTHON-71)

  • +
  • Return from Cluster.connect() when first contact point connection(pool) is opened (PYTHON-105)

  • +
  • cqlengine: Add ContextQuery to allow cqlengine models to switch the keyspace context easily (PYTHON-598)

  • +
  • Standardize Validation between Ascii and Text types in Cqlengine (PYTHON-609)

  • +
+
+
+

Bug Fixes

+
    +
  • Fix geventreactor with SSL support (PYTHON-600)

  • +
  • Don’t downgrade protocol version if explicitly set (PYTHON-537)

  • +
  • Nonexistent contact point tries to connect indefinitely (PYTHON-549)

  • +
  • Execute_concurrent can exceed max recursion depth in failure mode (PYTHON-585)

  • +
  • Libev loop shutdown race (PYTHON-578)

  • +
  • Include aliases in DCT type string (PYTHON-579)

  • +
  • cqlengine: Comparison operators for Columns (PYTHON-595)

  • +
  • cqlengine: disentangle default_time_to_live table option from model query default TTL (PYTHON-538)

  • +
  • cqlengine: pk__token column name issue with the equality operator (PYTHON-584)

  • +
  • cqlengine: Fix “__in” filtering operator converts True to string “True” automatically (PYTHON-596)

  • +
  • cqlengine: Avoid LWTExceptions when updating columns that are part of the condition (PYTHON-580)

  • +
  • cqlengine: Cannot execute a query when the filter contains all columns (PYTHON-599)

  • +
  • cqlengine: routing key computation issue when a primary key column is overriden by model inheritance (PYTHON-576)

  • +
+
+
+
+

3.5.0

+

June 27, 2016

+
+

Features

+
    +
  • Optional Execution Profiles for the core driver (PYTHON-569)

  • +
  • API to get the host metadata associated with the control connection node (PYTHON-583)

  • +
  • Expose CDC option in table metadata CQL (PYTHON-593)

  • +
+
+
+

Bug Fixes

+
    +
  • Clean up Asyncore socket map when fork is detected (PYTHON-577)

  • +
  • cqlengine: QuerySet only() is not respected when there are deferred fields (PYTHON-560)

  • +
+
+
+
+

3.4.1

+

May 26, 2016

+
+

Bug Fixes

+
    +
  • Gevent connection closes on IO timeout (PYTHON-573)

  • +
  • “dictionary changed size during iteration” with Python 3 (PYTHON-572)

  • +
+
+
+
+

3.4.0

+

May 24, 2016

+
+

Features

+
    +
  • Include DSE version and workload in Host data (PYTHON-555)

  • +
  • Add a context manager to Cluster and Session (PYTHON-521)

  • +
  • Better Error Message for Unsupported Protocol Version (PYTHON-157)

  • +
  • Make the error message explicitly state when an error comes from the server (PYTHON-412)

  • +
  • Short Circuit meta refresh on topo change if NEW_NODE already exists (PYTHON-557)

  • +
  • Show warning when the wrong config is passed to SimpleStatement (PYTHON-219)

  • +
  • Return namedtuple result pairs from execute_concurrent (PYTHON-362)

  • +
  • BatchStatement should enforce batch size limit in a better way (PYTHON-151)

  • +
  • Validate min/max request thresholds for connection pool scaling (PYTHON-220)

  • +
  • Handle or warn about multiple hosts with the same rpc_address (PYTHON-365)

  • +
  • Write docs around working with datetime and timezones (PYTHON-394)

  • +
+
+
+

Bug Fixes

+
    +
  • High CPU utilization when using asyncore event loop (PYTHON-239)

  • +
  • Fix CQL Export for non-ASCII Identifiers (PYTHON-447)

  • +
  • Make stress scripts Python 2.6 compatible (PYTHON-434)

  • +
  • UnicodeDecodeError when unicode characters in key in BOP (PYTHON-559)

  • +
  • WhiteListRoundRobinPolicy should resolve hosts (PYTHON-565)

  • +
  • Cluster and Session do not GC after leaving scope (PYTHON-135)

  • +
  • Don’t wait for schema agreement on ignored nodes (PYTHON-531)

  • +
  • Reprepare on_up with many clients causes node overload (PYTHON-556)

  • +
  • None inserted into host map when control connection node is decommissioned (PYTHON-548)

  • +
  • weakref.ref does not accept keyword arguments (github #585)

  • +
+
+
+
+

3.3.0

+

May 2, 2016

+
+

Features

+
    +
  • Add an AddressTranslator interface (PYTHON-69)

  • +
  • New Retry Policy Decision - try next host (PYTHON-285)

  • +
  • Don’t mark host down on timeout (PYTHON-286)

  • +
  • SSL hostname verification (PYTHON-296)

  • +
  • Add C* version to metadata or cluster objects (PYTHON-301)

  • +
  • Options to Disable Schema, Token Metadata Processing (PYTHON-327)

  • +
  • Expose listen_address of node we get ring information from (PYTHON-332)

  • +
  • Use A-record with multiple IPs for contact points (PYTHON-415)

  • +
  • Custom consistency level for populating query traces (PYTHON-435)

  • +
  • Normalize Server Exception Types (PYTHON-443)

  • +
  • Propagate exception message when DDL schema agreement fails (PYTHON-444)

  • +
  • Specialized exceptions for metadata refresh methods failure (PYTHON-527)

  • +
+
+
+

Bug Fixes

+
    +
  • Resolve contact point hostnames to avoid duplicate hosts (PYTHON-103)

  • +
  • GeventConnection stalls requests when read is a multiple of the input buffer size (PYTHON-429)

  • +
  • named_tuple_factory breaks with duplicate “cleaned” col names (PYTHON-467)

  • +
  • Connection leak if Cluster.shutdown() happens during reconnection (PYTHON-482)

  • +
  • HostConnection.borrow_connection does not block when all request ids are used (PYTHON-514)

  • +
  • Empty field not being handled by the NumpyProtocolHandler (PYTHON-550)

  • +
+
+
+
+

3.2.2

+

April 19, 2016

+
    +
  • Fix counter save-after-no-update (PYTHON-547)

  • +
+
+
+

3.2.1

+

April 13, 2016

+
    +
  • Introduced an update to allow deserializer compilation with recently released Cython 0.24 (PYTHON-542)

  • +
+
+
+

3.2.0

+

April 12, 2016

+
+

Features

+
    +
  • cqlengine: Warn on sync_schema type mismatch (PYTHON-260)

  • +
  • cqlengine: Automatically defer fields with the ‘=’ operator (and immutable values) in select queries (PYTHON-520)

  • +
  • cqlengine: support non-equal conditions for LWT (PYTHON-528)

  • +
  • cqlengine: sync_table should validate the primary key composition (PYTHON-532)

  • +
  • cqlengine: token-aware routing for mapper statements (PYTHON-535)

  • +
+
+
+

Bug Fixes

+
    +
  • Deleting a column in a lightweight transaction raises a SyntaxException #325 (PYTHON-249)

  • +
  • cqlengine: make Token function works with named tables/columns #86 (PYTHON-272)

  • +
  • comparing models with datetime fields fail #79 (PYTHON-273)

  • +
  • cython date deserializer integer math should be aligned with CPython (PYTHON-480)

  • +
  • db_field is not always respected with UpdateStatement (PYTHON-530)

  • +
  • Sync_table fails on column.Set with secondary index (PYTHON-533)

  • +
+
+
+
+

3.1.1

+

March 14, 2016

+
+

Bug Fixes

+
    +
  • cqlengine: Fix performance issue related to additional “COUNT” queries (PYTHON-522)

  • +
+
+
+
+

3.1.0

+

March 10, 2016

+
+

Features

+
    +
  • Pass name of server auth class to AuthProvider (PYTHON-454)

  • +
  • Surface schema agreed flag for DDL statements (PYTHON-458)

  • +
  • Automatically convert float and int to Decimal on serialization (PYTHON-468)

  • +
  • Eventlet Reactor IO improvement (PYTHON-495)

  • +
  • Make pure Python ProtocolHandler available even when Cython is present (PYTHON-501)

  • +
  • Optional Cython deserializer for bytes as bytearray (PYTHON-503)

  • +
  • Add Session.default_serial_consistency_level (github #510)

  • +
  • cqlengine: Expose prior state information via cqlengine LWTException (github #343, PYTHON-336)

  • +
  • cqlengine: Collection datatype “contains” operators support (Cassandra 2.1) #278 (PYTHON-258)

  • +
  • cqlengine: Add DISTINCT query operator (PYTHON-266)

  • +
  • cqlengine: Tuple cqlengine api (PYTHON-306)

  • +
  • cqlengine: Add support for UPDATE/DELETE … IF EXISTS statements (PYTHON-432)

  • +
  • cqlengine: Allow nested container types (PYTHON-478)

  • +
  • cqlengine: Add ability to set query’s fetch_size and limit (PYTHON-323)

  • +
  • cqlengine: Internalize default keyspace from successive set_session (PYTHON-486)

  • +
  • cqlengine: Warn when Model.create() on Counters (to be deprecated) (PYTHON-333)

  • +
+
+
+

Bug Fixes

+
    +
  • Bus error (alignment issues) when running cython on some ARM platforms (PYTHON-450)

  • +
  • Overflow when decoding large collections (cython) (PYTHON-459)

  • +
  • Timer heap comparison issue with Python 3 (github #466)

  • +
  • Cython deserializer date overflow at 2^31 - 1 (PYTHON-452)

  • +
  • Decode error encountered when cython deserializing large map results (PYTHON-459)

  • +
  • Don’t require Cython for build if compiler or Python header not present (PYTHON-471)

  • +
  • Unorderable types in task scheduling with Python 3 (h(PYTHON-473)

  • +
  • cqlengine: Fix crash when updating a UDT column with a None value (github #467)

  • +
  • cqlengine: Race condition in ..connection.execute with lazy_connect (PYTHON-310)

  • +
  • cqlengine: doesn’t support case sensitive column family names (PYTHON-337)

  • +
  • cqlengine: UserDefinedType mandatory in create or update (PYTHON-344)

  • +
  • cqlengine: db_field breaks UserType (PYTHON-346)

  • +
  • cqlengine: UDT badly quoted (PYTHON-347)

  • +
  • cqlengine: Use of db_field on primary key prevents querying except while tracing. (PYTHON-351)

  • +
  • cqlengine: DateType.deserialize being called with one argument vs two (PYTHON-354)

  • +
  • cqlengine: Querying without setting up connection now throws AttributeError and not CQLEngineException (PYTHON-395)

  • +
  • cqlengine: BatchQuery multiple time executing execute statements. (PYTHON-445)

  • +
  • cqlengine: Better error for management functions when no connection set (PYTHON-451)

  • +
  • cqlengine: Handle None values for UDT attributes in cqlengine (PYTHON-470)

  • +
  • cqlengine: Fix inserting None for model save (PYTHON-475)

  • +
  • cqlengine: EQ doesn’t map to a QueryOperator (setup race condition) (PYTHON-476)

  • +
  • cqlengine: class.MultipleObjectsReturned has DoesNotExist as base class (PYTHON-489)

  • +
  • cqlengine: Typo in cqlengine UserType __len__ breaks attribute assignment (PYTHON-502)

  • +
+
+
+

Other

+
    +
  • cqlengine: a major improvement on queryset has been introduced. It +is a lot more efficient to iterate large datasets: the rows are +now fetched on demand using the driver pagination.

  • +
  • cqlengine: the queryset len() and count() behaviors have changed. It +now executes a “SELECT COUNT(*)” of the query rather than returning +the size of the internal result_cache (loaded rows). On large +queryset, you might want to avoid using them due to the performance +cost. Note that trying to access objects using list index/slicing +with negative indices also requires a count to be +executed.

  • +
+
+
+
+

3.0.0

+

November 24, 2015

+
+

Features

+
    +
  • Support datetime.date objects as a DateType (PYTHON-212)

  • +
  • Add Cluster.update_view_metadata (PYTHON-407)

  • +
  • QueryTrace option to populate partial trace sessions (PYTHON-438)

  • +
  • Attach column names to ResultSet (PYTHON-439)

  • +
  • Change default consistency level to LOCAL_ONE

  • +
+
+
+

Bug Fixes

+
    +
  • Properly SerDes nested collections when protocol_version < 3 (PYTHON-215)

  • +
  • Evict UDTs from UserType cache on change (PYTHON-226)

  • +
  • Make sure query strings are always encoded UTF-8 (PYTHON-334)

  • +
  • Track previous value of columns at instantiation in CQLengine (PYTHON-348)

  • +
  • UDT CQL encoding does not work for unicode values (PYTHON-353)

  • +
  • NetworkTopologyStrategy#make_token_replica_map does not account for multiple racks in a DC (PYTHON-378)

  • +
  • Cython integer overflow on decimal type deserialization (PYTHON-433)

  • +
  • Query trace: if session hasn’t been logged, query trace can throw exception (PYTHON-442)

  • +
+
+
+
+

3.0.0rc1

+

November 9, 2015

+
+

Features

+
    +
  • Process Modernized Schema Tables for Cassandra 3.0 (PYTHON-276, PYTHON-408, PYTHON-400, PYTHON-422)

  • +
  • Remove deprecated features (PYTHON-292)

  • +
  • Don’t assign trace data to Statements (PYTHON-318)

  • +
  • Normalize results return (PYTHON-368)

  • +
  • Process Materialized View Metadata/Events (PYTHON-371)

  • +
  • Remove blist as soft dependency (PYTHON-385)

  • +
  • Change default consistency level to LOCAL_QUORUM (PYTHON-416)

  • +
  • Normalize CQL query/export in metadata model (PYTHON-405)

  • +
+
+
+

Bug Fixes

+
    +
  • Implementation of named arguments bind is non-pythonic (PYTHON-178)

  • +
  • CQL encoding is incorrect for NaN and Infinity floats (PYTHON-282)

  • +
  • Protocol downgrade issue with C* 2.0.x, 2.1.x, and python3, with non-default logging (PYTHON-409)

  • +
  • ValueError when accessing usertype with non-alphanumeric field names (PYTHON-413)

  • +
  • NumpyProtocolHandler does not play well with PagedResult (PYTHON-430)

  • +
+
+
+
+

2.7.2

+

September 14, 2015

+
+

Bug Fixes

+
    +
  • Resolve CQL export error for UDF with zero parameters (PYTHON-392)

  • +
  • Remove futures dep. for Python 3 (PYTHON-393)

  • +
  • Avoid Python closure in cdef (supports earlier Cython compiler) (PYTHON-396)

  • +
  • Unit test runtime issues (PYTHON-397,398)

  • +
+
+
+
+

2.7.1

+

August 25, 2015

+
+

Bug Fixes

+
    +
  • Explicitly include extension source files in Manifest

  • +
+
+
+
+

2.7.0

+

August 25, 2015

+

Cython is introduced, providing compiled extensions for core modules, and +extensions for optimized results deserialization.

+
+

Features

+
    +
  • General Performance Improvements for Throughput (PYTHON-283)

  • +
  • Improve synchronous request performance with Timers (PYTHON-108)

  • +
  • Enable C Extensions for PyPy Runtime (PYTHON-357)

  • +
  • Refactor SerDes functionality for pluggable interface (PYTHON-313)

  • +
  • Cython SerDes Extension (PYTHON-377)

  • +
  • Accept iterators/generators for execute_concurrent() (PYTHON-123)

  • +
  • cythonize existing modules (PYTHON-342)

  • +
  • Pure Python murmur3 implementation (PYTHON-363)

  • +
  • Make driver tolerant of inconsistent metadata (PYTHON-370)

  • +
+
+
+

Bug Fixes

+
    +
  • Drop Events out-of-order Cause KeyError on Processing (PYTHON-358)

  • +
  • DowngradingConsistencyRetryPolicy doesn’t check response count on write timeouts (PYTHON-338)

  • +
  • Blocking connect does not use connect_timeout (PYTHON-381)

  • +
  • Properly protect partition key in CQL export (PYTHON-375)

  • +
  • Trigger error callbacks on timeout (PYTHON-294)

  • +
+
+
+
+

2.6.0

+

July 20, 2015

+
+

Bug Fixes

+
    +
  • Output proper CQL for compact tables with no clustering columns (PYTHON-360)

  • +
+
+
+
+

2.6.0c2

+

June 24, 2015

+
+

Features

+
    +
  • Automatic Protocol Version Downgrade (PYTHON-240)

  • +
  • cqlengine Python 2.6 compatibility (PYTHON-288)

  • +
  • Double-dollar string quote UDF body (PYTHON-345)

  • +
  • Set models.DEFAULT_KEYSPACE when calling set_session (github #352)

  • +
+
+
+

Bug Fixes

+
    +
  • Avoid stall while connecting to mixed version cluster (PYTHON-303)

  • +
  • Make SSL work with AsyncoreConnection in python 2.6.9 (PYTHON-322)

  • +
  • Fix Murmur3Token.from_key() on Windows (PYTHON-331)

  • +
  • Fix cqlengine TimeUUID rounding error for Windows (PYTHON-341)

  • +
  • Avoid invalid compaction options in CQL export for non-SizeTiered (PYTHON-352)

  • +
+
+
+
+

2.6.0c1

+

June 4, 2015

+

This release adds support for Cassandra 2.2 features, including version +4 of the native protocol.

+
+

Features

+
    +
  • Default load balancing policy to TokenAware(DCAware) (PYTHON-160)

  • +
  • Configuration option for connection timeout (PYTHON-206)

  • +
  • Support User Defined Function and Aggregate metadata in C* 2.2 (PYTHON-211)

  • +
  • Surface request client in QueryTrace for C* 2.2+ (PYTHON-235)

  • +
  • Implement new request failure messages in protocol v4+ (PYTHON-238)

  • +
  • Metadata model now maps index meta by index name (PYTHON-241)

  • +
  • Support new types in C* 2.2: date, time, smallint, tinyint (PYTHON-245, 295)

  • +
  • cqle: add Double column type and remove Float overload (PYTHON-246)

  • +
  • Use partition key column information in prepared response for protocol v4+ (PYTHON-277)

  • +
  • Support message custom payloads in protocol v4+ (PYTHON-280, PYTHON-329)

  • +
  • Deprecate refresh_schema and replace with functions for specific entities (PYTHON-291)

  • +
  • Save trace id even when trace complete times out (PYTHON-302)

  • +
  • Warn when registering client UDT class for protocol < v3 (PYTHON-305)

  • +
  • Support client warnings returned with messages in protocol v4+ (PYTHON-315)

  • +
  • Ability to distinguish between NULL and UNSET values in protocol v4+ (PYTHON-317)

  • +
  • Expose CQL keywords in API (PYTHON-324)

  • +
+
+
+

Bug Fixes

+
    +
  • IPv6 address support on Windows (PYTHON-20)

  • +
  • Convert exceptions during automatic re-preparation to nice exceptions (PYTHON-207)

  • +
  • cqle: Quote keywords properly in table management functions (PYTHON-244)

  • +
  • Don’t default to GeventConnection when gevent is loaded, but not monkey-patched (PYTHON-289)

  • +
  • Pass dynamic host from SaslAuthProvider to SaslAuthenticator (PYTHON-300)

  • +
  • Make protocol read_inet work for Windows (PYTHON-309)

  • +
  • cqle: Correct encoding for nested types (PYTHON-311)

  • +
  • Update list of CQL keywords used quoting identifiers (PYTHON-319)

  • +
  • Make ConstantReconnectionPolicy work with infinite retries (github #327, PYTHON-325)

  • +
  • Accept UUIDs with uppercase hex as valid in cqlengine (github #335)

  • +
+
+
+
+

2.5.1

+

April 23, 2015

+
+

Bug Fixes

+
    +
  • Fix thread safety in DC-aware load balancing policy (PYTHON-297)

  • +
  • Fix race condition in node/token rebuild (PYTHON-298)

  • +
  • Set and send serial consistency parameter (PYTHON-299)

  • +
+
+
+
+

2.5.0

+

March 30, 2015

+
+

Features

+
    +
  • Integrated cqlengine object mapping package

  • +
  • Utility functions for converting timeuuids and datetime (PYTHON-99)

  • +
  • Schema metadata fetch window randomized, config options added (PYTHON-202)

  • +
  • Support for new Date and Time Cassandra types (PYTHON-190)

  • +
+
+
+

Bug Fixes

+
    +
  • Fix index target for collection indexes (full(), keys()) (PYTHON-222)

  • +
  • Thread exception during GIL cleanup (PYTHON-229)

  • +
  • Workaround for rounding anomaly in datetime.utcfromtime (Python 3.4) (PYTHON-230)

  • +
  • Normalize text serialization for lookup in OrderedMap (PYTHON-231)

  • +
  • Support reading CompositeType data (PYTHON-234)

  • +
  • Preserve float precision in CQL encoding (PYTHON-243)

  • +
+
+
+
+

2.1.4

+

January 26, 2015

+
+

Features

+
    +
  • SaslAuthenticator for Kerberos support (PYTHON-109)

  • +
  • Heartbeat for network device keepalive and detecting failures on idle connections (PYTHON-197)

  • +
  • Support nested, frozen collections for Cassandra 2.1.3+ (PYTHON-186)

  • +
  • Schema agreement wait bypass config, new call for synchronous schema refresh (PYTHON-205)

  • +
  • Add eventlet connection support (PYTHON-194)

  • +
+
+
+

Bug Fixes

+
    +
  • Schema meta fix for complex thrift tables (PYTHON-191)

  • +
  • Support for ‘unknown’ replica placement strategies in schema meta (PYTHON-192)

  • +
  • Resolve stream ID leak on set_keyspace (PYTHON-195)

  • +
  • Remove implicit timestamp scaling on serialization of numeric timestamps (PYTHON-204)

  • +
  • Resolve stream id collision when using SASL auth (PYTHON-210)

  • +
  • Correct unhexlify usage for user defined type meta in Python3 (PYTHON-208)

  • +
+
+
+
+

2.1.3

+

December 16, 2014

+
+

Features

+
    +
  • INFO-level log confirmation that a connection was opened to a node that was marked up (PYTHON-116)

  • +
  • Avoid connecting to peer with incomplete metadata (PYTHON-163)

  • +
  • Add SSL support to gevent reactor (PYTHON-174)

  • +
  • Use control connection timeout in wait for schema agreement (PYTHON-175)

  • +
  • Better consistency level representation in unavailable+timeout exceptions (PYTHON-180)

  • +
  • Update schema metadata processing to accommodate coming schema modernization (PYTHON-185)

  • +
+
+
+

Bug Fixes

+
    +
  • Support large negative timestamps on Windows (PYTHON-119)

  • +
  • Fix schema agreement for clusters with peer rpc_addres 0.0.0.0 (PYTHON-166)

  • +
  • Retain table metadata following keyspace meta refresh (PYTHON-173)

  • +
  • Use a timeout when preparing a statement for all nodes (PYTHON-179)

  • +
  • Make TokenAware routing tolerant of statements with no keyspace (PYTHON-181)

  • +
  • Update add_collback to store/invoke multiple callbacks (PYTHON-182)

  • +
  • Correct routing key encoding for composite keys (PYTHON-184)

  • +
  • Include compression option in schema export string when disabled (PYTHON-187)

  • +
+
+
+
+

2.1.2

+

October 16, 2014

+
+

Features

+
    +
  • Allow DCAwareRoundRobinPolicy to be constructed without a local_dc, defaulting +instead to the DC of a contact_point (PYTHON-126)

  • +
  • Set routing key in BatchStatement.add() if none specified in batch (PYTHON-148)

  • +
  • Improved feedback on ValueError using named_tuple_factory with invalid column names (PYTHON-122)

  • +
+
+
+

Bug Fixes

+
    +
  • Make execute_concurrent compatible with Python 2.6 (PYTHON-159)

  • +
  • Handle Unauthorized message on schema_triggers query (PYTHON-155)

  • +
  • Pure Python sorted set in support of UDTs nested in collections (PYTON-167)

  • +
  • Support CUSTOM index metadata and string export (PYTHON-165)

  • +
+
+
+
+

2.1.1

+

September 11, 2014

+
+

Features

+
    +
  • Detect triggers and include them in CQL queries generated to recreate +the schema (github-189)

  • +
  • Support IPv6 addresses (PYTHON-144) (note: basic functionality added; Windows +platform not addressed (PYTHON-20))

  • +
+
+
+

Bug Fixes

+
    +
  • Fix NetworkTopologyStrategy.export_for_schema (PYTHON-120)

  • +
  • Keep timeout for paged results (PYTHON-150)

  • +
+
+
+

Other

+
    +
  • Add frozen<> type modifier to UDTs and tuples to handle CASSANDRA-7857

  • +
+
+
+
+

2.1.0

+

August 7, 2014

+
+

Bug Fixes

+
    +
  • Correctly serialize and deserialize null values in tuples and +user-defined types (PYTHON-110)

  • +
  • Include additional header and lib dirs, allowing libevwrapper to build +against Homebrew and Mac Ports installs of libev (PYTHON-112 and 804dea3)

  • +
+
+
+
+

2.1.0c1

+

July 25, 2014

+
+

Bug Fixes

+
    +
  • Properly specify UDTs for columns in CREATE TABLE statements

  • +
  • Avoid moving retries to a new host when using request ID zero (PYTHON-88)

  • +
  • Don’t ignore fetch_size arguments to Statement constructors (github-151)

  • +
  • Allow disabling automatic paging on a per-statement basis when it’s +enabled by default for the session (PYTHON-93)

  • +
  • Raise ValueError when tuple query parameters for prepared statements +have extra items (PYTHON-98)

  • +
  • Correctly encode nested tuples and UDTs for non-prepared statements (PYTHON-100)

  • +
  • Raise TypeError when a string is used for contact_points (github #164)

  • +
  • Include User Defined Types in KeyspaceMetadata.export_as_string() (PYTHON-96)

  • +
+
+
+

Other

+
    +
  • Return list collection columns as python lists instead of tuples +now that tuples are a specific Cassandra type

  • +
+
+
+
+

2.1.0b1

+

July 11, 2014

+

This release adds support for Cassandra 2.1 features, including version +3 of the native protocol.

+
+

Features

+
    +
  • When using the v3 protocol, only one connection is opened per-host, and +throughput is improved due to reduced pooling overhead and lock contention.

  • +
  • Support for user-defined types (Cassandra 2.1+)

  • +
  • Support for tuple type in (limited usage Cassandra 2.0.9, full usage +in Cassandra 2.1)

  • +
  • Protocol-level client-side timestamps (see Session.use_client_timestamp)

  • +
  • Overridable type encoding for non-prepared statements (see Session.encoders)

  • +
  • Configurable serial consistency levels for batch statements

  • +
  • Use io.BytesIO for reduced CPU consumption (github #143)

  • +
  • Support Twisted as a reactor. Note that a Twisted-compatible +API is not exposed (so no Deferreds), this is just a reactor +implementation. (github #135, PYTHON-8)

  • +
+
+
+

Bug Fixes

+
    +
  • Fix references to xrange that do not go through “six” in libevreactor and +geventreactor (github #138)

  • +
  • Make BoundStatements inherit fetch_size from their parent +PreparedStatement (PYTHON-80)

  • +
  • Clear reactor state in child process after forking to prevent errors with +multiprocessing when the parent process has connected a Cluster before +forking (github #141)

  • +
  • Don’t share prepared statement lock across Cluster instances

  • +
  • Format CompositeType and DynamicCompositeType columns correctly in +CREATE TABLE statements.

  • +
  • Fix cassandra.concurrent behavior when dealing with automatic paging +(PYTHON-81)

  • +
  • Properly defunct connections after protocol errors

  • +
  • Avoid UnicodeDecodeError when query string is unicode (PYTHON-76)

  • +
  • Correctly capture dclocal_read_repair_chance for tables and +use it when generating CREATE TABLE statements (PYTHON-84)

  • +
  • Avoid race condition with AsyncoreConnection that may cause messages +to fail to be written until a new message is pushed

  • +
  • Make sure cluster.metadata.partitioner and cluster.metadata.token_map +are populated when all nodes in the cluster are included in the +contact points (PYTHON-90)

  • +
  • Make Murmur3 hash match Cassandra’s hash for all values (PYTHON-89, +github #147)

  • +
  • Don’t attempt to reconnect to hosts that should be ignored (according +to the load balancing policy) when a notification is received that the +host is down.

  • +
  • Add CAS WriteType, avoiding KeyError on CAS write timeout (PYTHON-91)

  • +
+
+
+
+

2.0.2

+

June 10, 2014

+
+

Bug Fixes

+
    +
  • Add six to requirements.txt

  • +
  • Avoid KeyError during schema refresh when a keyspace is dropped +and TokenAwarePolicy is not in use

  • +
  • Avoid registering multiple atexit cleanup functions when the +asyncore event loop is restarted multiple times

  • +
  • Delay initialization of reactors in order to avoid problems +with shared state when using multiprocessing (PYTHON-60)

  • +
  • Add python-six to debian dependencies, move python-blist to recommends

  • +
  • Fix memory leak when libev connections are created and +destroyed (github #93)

  • +
  • Ensure token map is rebuilt when hosts are removed from the cluster

  • +
+
+
+
+

2.0.1

+

May 28, 2014

+
+

Bug Fixes

+
    +
  • Fix check for Cluster.is_shutdown in in @run_in_executor +decorator

  • +
+
+
+
+

2.0.0

+

May 28, 2014

+
+

Features

+
    +
  • Make libev C extension Python3-compatible (PYTHON-70)

  • +
  • Support v2 protocol authentication (PYTHON-73, github #125)

  • +
+
+
+

Bug Fixes

+
    +
  • Fix murmur3 C extension compilation under Python3.4 (github #124)

  • +
+
+
+

Merged From 1.x

+
+

Features

+
    +
  • Add Session.default_consistency_level (PYTHON-14)

  • +
+
+
+

Bug Fixes

+
    +
  • Don’t strip trailing underscores from column names when using the +named_tuple_factory (PYTHON-56)

  • +
  • Ensure replication factors are ints for NetworkTopologyStrategy +to avoid TypeErrors (github #120)

  • +
  • Pass WriteType instance to RetryPolicy.on_write_timeout() instead +of the string name of the write type. This caused write timeout +errors to always be rethrown instead of retrying. (github #123)

  • +
  • Avoid submitting tasks to the ThreadPoolExecutor after shutdown. With +retries enabled, this could cause Cluster.shutdown() to hang under +some circumstances.

  • +
  • Fix unintended rebuild of token replica map when keyspaces are +discovered (on startup), added, or updated and TokenAwarePolicy is not +in use.

  • +
  • Avoid rebuilding token metadata when cluster topology has not +actually changed

  • +
  • Avoid preparing queries for hosts that should be ignored (such as +remote hosts when using the DCAwareRoundRobinPolicy) (PYTHON-75)

  • +
+
+
+

Other

+
    +
  • Add 1 second timeout to join() call on event loop thread during +interpreter shutdown. This can help to prevent the process from +hanging during shutdown.

  • +
+
+
+
+
+

2.0.0b1

+

May 6, 2014

+
+

Upgrading from 1.x

+

Cluster.shutdown() should always be called when you are done with a +Cluster instance. If it is not called, there are no guarantees that the +driver will not hang. However, if you do have a reproduceable case +where Cluster.shutdown() is not called and the driver hangs, please +report it so that we can attempt to fix it.

+

If you’re using the 2.0 driver against Cassandra 1.2, you will need +to set your protocol version to 1. For example:

+
+

cluster = Cluster(…, protocol_version=1)

+
+
+
+

Features

+
    +
  • Support v2 of Cassandra’s native protocol, which includes the following +new features: automatic query paging support, protocol-level batch statements, +and lightweight transactions

  • +
  • Support for Python 3.3 and 3.4

  • +
  • Allow a default query timeout to be set per-Session

  • +
+
+
+

Bug Fixes

+
    +
  • Avoid errors during interpreter shutdown (the driver attempts to cleanup +daemonized worker threads before interpreter shutdown)

  • +
+
+
+

Deprecations

+

The following functions have moved from cassandra.decoder to cassandra.query. +The original functions have been left in place with a DeprecationWarning for +now:

+
    +
  • cassandra.decoder.tuple_factory has moved to cassandra.query.tuple_factory

  • +
  • cassandra.decoder.named_tuple_factory has moved to cassandra.query.named_tuple_factory

  • +
  • cassandra.decoder.dict_factory has moved to cassandra.query.dict_factory

  • +
  • cassandra.decoder.ordered_dict_factory has moved to cassandra.query.ordered_dict_factory

  • +
+

Exceptions that were in cassandra.decoder have been moved to cassandra.protocol. If +you handle any of these exceptions, you must adjust the code accordingly.

+
+
+
+

1.1.2

+

May 8, 2014

+
+

Features

+
    +
  • Allow a specific compression type to be requested for communications with +Cassandra and prefer lz4 if available

  • +
+
+
+

Bug Fixes

+
    +
  • Update token metadata (for TokenAware calculations) when a node is removed +from the ring

  • +
  • Fix file handle leak with gevent reactor due to blocking Greenlet kills when +closing excess connections

  • +
  • Avoid handling a node coming up multiple times due to a reconnection attempt +succeeding close to the same time that an UP notification is pushed

  • +
  • Fix duplicate node-up handling, which could result in multiple reconnectors +being started as well as the executor threads becoming deadlocked, preventing +future node up or node down handling from being executed.

  • +
  • Handle exhausted ReconnectionPolicy schedule correctly

  • +
+
+
+

Other

+
    +
  • Don’t log at ERROR when a connection is closed during the startup +communications

  • +
  • Mke scales, blist optional dependencies

  • +
+
+
+
+

1.1.1

+

April 16, 2014

+
+

Bug Fixes

+
    +
  • Fix unconditional import of nose in setup.py (github #111)

  • +
+
+
+
+

1.1.0

+

April 16, 2014

+
+

Features

+
    +
  • Gevent is now supported through monkey-patching the stdlib (PYTHON-7, +github issue #46)

  • +
  • Support static columns in schemas, which are available starting in +Cassandra 2.1. (github issue #91)

  • +
  • Add debian packaging (github issue #101)

  • +
  • Add utility methods for easy concurrent execution of statements. See +the new cassandra.concurrent module. (github issue #7)

  • +
+
+
+

Bug Fixes

+
    +
  • Correctly supply compaction and compression parameters in CREATE statements +for tables when working with Cassandra 2.0+

  • +
  • Lowercase boolean literals when generating schemas

  • +
  • Ignore SSL_ERROR_WANT_READ and SSL_ERROR_WANT_WRITE socket errors. Previously, +these resulted in the connection being defuncted, but they can safely be +ignored by the driver.

  • +
  • Don’t reconnect the control connection every time Cluster.connect() is +called

  • +
  • Avoid race condition that could leave ResponseFuture callbacks uncalled +if the callback was added outside of the event loop thread (github issue #95)

  • +
  • Properly escape keyspace name in Session.set_keyspace(). Previously, the +keyspace name was quoted, but any quotes in the string were not escaped.

  • +
  • Avoid adding hosts to the load balancing policy before their datacenter +and rack information has been set, if possible.

  • +
  • Avoid KeyError when updating metadata after droping a table (github issues +#97, #98)

  • +
  • Use tuples instead of sets for DCAwareLoadBalancingPolicy to ensure equal +distribution of requests

  • +
+
+
+

Other

+
    +
  • Don’t ignore column names when parsing typestrings. This is needed for +user-defined type support. (github issue #90)

  • +
  • Better error message when libevwrapper is not found

  • +
  • Only try to import scales when metrics are enabled (github issue #92)

  • +
  • Cut down on the number of queries executing when a new Cluster +connects and when the control connection has to reconnect (github issue #104, +PYTHON-59)

  • +
  • Issue warning log when schema versions do not match

  • +
+
+
+
+

1.0.2

+

March 4, 2014

+
+

Bug Fixes

+
    +
  • With asyncorereactor, correctly handle EAGAIN/EWOULDBLOCK when the message from +Cassandra is a multiple of the read buffer size. Previously, if no more data +became available to read on the socket, the message would never be processed, +resulting in an OperationTimedOut error.

  • +
  • Double quote keyspace, table and column names that require them (those using +uppercase characters or keywords) when generating CREATE statements through +KeyspaceMetadata and TableMetadata.

  • +
  • Decode TimestampType as DateType. (Cassandra replaced DateType with +TimestampType to fix sorting of pre-unix epoch dates in CASSANDRA-5723.)

  • +
  • Handle latest table options when parsing the schema and generating +CREATE statements.

  • +
  • Avoid ‘Set changed size during iteration’ during query plan generation +when hosts go up or down

  • +
+
+
+

Other

+
    +
  • Remove ignored tracing_enabled parameter for SimpleStatement. The +correct way to trace a query is by setting the trace argument to True +in Session.execute() and Session.execute_async().

  • +
  • Raise TypeError instead of cassandra.query.InvalidParameterTypeError when +a parameter for a prepared statement has the wrong type; remove +cassandra.query.InvalidParameterTypeError.

  • +
  • More consistent type checking for query parameters

  • +
  • Add option to a return special object for empty string values for non-string +columns

  • +
+
+
+
+

1.0.1

+

Feb 19, 2014

+
+

Bug Fixes

+
    +
  • Include table indexes in KeyspaceMetadata.export_as_string()

  • +
  • Fix broken token awareness on ByteOrderedPartitioner

  • +
  • Always close socket when defuncting error’ed connections to avoid a potential +file descriptor leak

  • +
  • Handle “custom” types (such as the replaced DateType) correctly

  • +
  • With libevreactor, correctly handle EAGAIN/EWOULDBLOCK when the message from +Cassandra is a multiple of the read buffer size. Previously, if no more data +became available to read on the socket, the message would never be processed, +resulting in an OperationTimedOut error.

  • +
  • Don’t break tracing when a Session’s row_factory is not the default +namedtuple_factory.

  • +
  • Handle data that is already utf8-encoded for UTF8Type values

  • +
  • Fix token-aware routing for tokens that fall before the first node token in +the ring and tokens that exactly match a node’s token

  • +
  • Tolerate null source_elapsed values for Trace events. These may not be +set when events complete after the main operation has already completed.

  • +
+
+
+

Other

+
    +
  • Skip sending OPTIONS message on connection creation if compression is +disabled or not available and a CQL version has not been explicitly +set

  • +
  • Add details about errors and the last queried host to OperationTimedOut

  • +
+
+
+
+

1.0.0 Final

+

Jan 29, 2014

+
+

Bug Fixes

+
    +
  • Prevent leak of Scheduler thread (even with proper shutdown)

  • +
  • Correctly handle ignored hosts, which are common with the +DCAwareRoundRobinPolicy

  • +
  • Hold strong reference to prepared statement while executing it to avoid +garbage collection

  • +
  • Add NullHandler logging handler to the cassandra package to avoid +warnings about there being no configured logger

  • +
  • Fix bad handling of nodes that have been removed from the cluster

  • +
  • Properly escape string types within cql collections

  • +
  • Handle setting the same keyspace twice in a row

  • +
  • Avoid race condition during schema agreement checks that could result +in schema update queries returning before all nodes had seen the change

  • +
  • Preserve millisecond-level precision in datetimes when performing inserts +with simple (non-prepared) statements

  • +
  • Properly defunct connections when libev reports an error by setting +errno instead of simply logging the error

  • +
  • Fix endless hanging of some requests when using the libev reactor

  • +
  • Always start a reconnection process when we fail to connect to +a newly bootstrapped node

  • +
  • Generators map to CQL lists, not key sequences

  • +
  • Always defunct connections when an internal operation fails

  • +
  • Correctly break from handle_write() if nothing was sent (asyncore +reactor only)

  • +
  • Avoid potential double-erroring of callbacks when a connection +becomes defunct

  • +
+
+
+

Features

+
    +
  • Add default query timeout to Session

  • +
  • Add timeout parameter to Session.execute()

  • +
  • Add WhiteListRoundRobinPolicy as a load balancing policy option

  • +
  • Support for consistency level LOCAL_ONE

  • +
  • Make the backoff for fetching traces exponentially increasing and +configurable

  • +
+
+
+

Other

+
    +
  • Raise Exception if TokenAwarePolicy is used against a cluster using the +Murmur3Partitioner if the murmur3 C extension has not been compiled

  • +
  • Add encoder mapping for OrderedDict

  • +
  • Use timeouts on all control connection queries

  • +
  • Benchmark improvements, including command line options and eay +multithreading support

  • +
  • Reduced lock contention when using the asyncore reactor

  • +
  • Warn when non-datetimes are used for ‘timestamp’ column values in +prepared statements

  • +
  • Add requirements.txt and test-requirements.txt

  • +
  • TravisCI integration for running unit tests against Python 2.6, +Python 2.7, and PyPy

  • +
+
+
+
+

1.0.0b7

+

Nov 12, 2013

+

This release makes many stability improvements, especially around +prepared statements and node failure handling. In particular, +several cases where a request would never be completed (and as a +result, leave the application hanging) have been resolved.

+
+

Features

+
    +
  • Add timeout kwarg to ResponseFuture.result()

  • +
  • Create connection pools to all hosts in parallel when initializing +new Sesssions.

  • +
+
+
+

Bug Fixes

+
    +
  • Properly set exception on ResponseFuture when a query fails +against all hosts

  • +
  • Improved cleanup and reconnection efforts when reconnection fails +on a node that has recently come up

  • +
  • Use correct consistency level when retrying failed operations +against a different host. (An invalid consistency level was being +used, causing the retry to fail.)

  • +
  • Better error messages for failed Session.prepare() opertaions

  • +
  • Prepare new statements against all hosts in parallel (formerly +sequential)

  • +
  • Fix failure to save the new current keyspace on connections. (This +could cause problems for prepared statements and lead to extra +operations to continuously re-set the keyspace.)

  • +
  • Avoid sharing LoadBalancingPolicies across Cluster instances. (When +a second Cluster was connected, it effectively mark nodes down for the +first Cluster.)

  • +
  • Better handling of failures during the re-preparation sequence for +unrecognized prepared statements

  • +
  • Throttle trashing of underutilized connections to avoid trashing newly +created connections

  • +
  • Fix race condition which could result in trashed connections being closed +before the last operations had completed

  • +
  • Avoid preparing statements on the event loop thread (which could lead to +deadlock)

  • +
  • Correctly mark up non-contact point nodes discovered by the control +connection. (This lead to prepared statements not being prepared +against those hosts, generating extra traffic later when the +statements were executed and unrecognized.)

  • +
  • Correctly handle large messages through libev

  • +
  • Add timeout to schema agreement check queries

  • +
  • More complete (and less contended) locking around manipulation of the +pending message deque for libev connections

  • +
+
+
+

Other

+
    +
  • Prepare statements in batches of 10. (When many prepared statements +are in use, this allows the driver to start utilizing nodes that +were restarted more quickly.)

  • +
  • Better debug logging around connection management

  • +
  • Don’t retain unreferenced prepared statements in the local cache. +(If many different prepared statements were created, this would +increase memory usage and greatly increase the amount of time +required to begin utilizing a node that was added or marked +up.)

  • +
+
+
+
+

1.0.0b6

+

Oct 22, 2013

+
+

Bug Fixes

+
    +
  • Use lazy string formatting when logging

  • +
  • Avoid several deadlock scenarios, especially when nodes go down

  • +
  • Avoid trashing newly created connections due to insufficient traffic

  • +
  • Gracefully handle un-handled Exceptions when erroring callbacks

  • +
+
+
+

Other

+
    +
  • Node state listeners (which are called when a node is added, removed, +goes down, or comes up) should now be registered through +Cluster.register_listener() instead of through a host’s HealthMonitor +(which has been removed)

  • +
+
+
+
+

1.0.0b5

+

Oct 10, 2013

+
+

Features

+
    +
  • SSL support

  • +
+
+
+

Bug Fixes

+
    +
  • Avoid KeyError when building replica map for NetworkTopologyStrategy

  • +
  • Work around python bug which causes deadlock when a thread imports +the utf8 module

  • +
  • Handle no blist library, which is not compatible with pypy

  • +
  • Avoid deadlock triggered by a keyspace being set on a connection (which +may happen automatically for new connections)

  • +
+
+
+

Other

+
    +
  • Switch packaging from Distribute to setuptools, improved C extension +support

  • +
  • Use PEP 386 compliant beta and post-release versions

  • +
+
+
+
+

1.0.0-beta4

+

Sep 24, 2013

+
+

Features

+
    +
  • Handle new blob syntax in Cassandra 2.0 by accepting bytearray +objects for blob values

  • +
  • Add cql_version kwarg to Cluster.__init__

  • +
+
+
+

Bug Fixes

+
    +
  • Fix KeyError when building token map with NetworkTopologyStrategy +keyspaces (this prevented a Cluster from successfully connecting +at all).

  • +
  • Don’t lose default consitency level from parent PreparedStatement +when creating BoundStatements

  • +
+
+
+
+

1.0.0-beta3

+

Sep 20, 2013

+
+

Features

+
    +
  • Support for LZ4 compression (Cassandra 2.0+)

  • +
  • Token-aware routing will now utilize all replicas for a query instead +of just the first replica

  • +
+
+
+

Bug Fixes

+
    +
  • Fix libev include path for CentOS

  • +
  • Fix varint packing of the value 0

  • +
  • Correctly pack unicode values

  • +
  • Don’t attempt to return failed connections to the pool when a final result +is set

  • +
  • Fix bad iteration of connection credentials

  • +
  • Use blist’s orderedset for set collections and OrderedDict for map +collections so that Cassandra’s ordering is preserved

  • +
  • Fix connection failure on Windows due to unavailability of inet_pton +and inet_ntop. (Note that IPv6 inet_address values are still not +supported on Windows.)

  • +
  • Boolean constants shouldn’t be surrounded by single quotes

  • +
  • Avoid a potential loss of precision on float constants due to string +formatting

  • +
  • Actually utilize non-standard ports set on Cluster objects

  • +
  • Fix export of schema as a set of CQL queries

  • +
+
+
+

Other

+
    +
  • Use cStringIO for connection buffer for better performance

  • +
  • Add __repr__ method for Statement classes

  • +
  • Raise InvalidTypeParameterError when parameters of the wrong +type are used with statements

  • +
  • Make all tests compatible with Python 2.6

  • +
  • Add 1s timeout for opening new connections

  • +
+
+
+
+

1.0.0-beta2

+

Aug 19, 2013

+
+

Bug Fixes

+
    +
  • Fix pip packaging

  • +
+
+
+
+

1.0.0-beta

+

Aug 16, 2013

+

Initial release

+
+
+ + +
+ + + + + +
+ + +
+
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.25.4-scylla/CNAME b/3.25.4-scylla/CNAME new file mode 100644 index 0000000000..9f3e01a070 --- /dev/null +++ b/3.25.4-scylla/CNAME @@ -0,0 +1 @@ +python-driver.docs.scylladb.com \ No newline at end of file diff --git a/3.25.4-scylla/_sources/CHANGELOG.rst.txt b/3.25.4-scylla/_sources/CHANGELOG.rst.txt new file mode 100644 index 0000000000..f6d642b27f --- /dev/null +++ b/3.25.4-scylla/_sources/CHANGELOG.rst.txt @@ -0,0 +1,7 @@ +:orphan: + +********* +CHANGELOG +********* + +.. include:: ../CHANGELOG.rst diff --git a/3.25.4-scylla/_sources/api/cassandra.rst.txt b/3.25.4-scylla/_sources/api/cassandra.rst.txt new file mode 100644 index 0000000000..d46aae56cb --- /dev/null +++ b/3.25.4-scylla/_sources/api/cassandra.rst.txt @@ -0,0 +1,77 @@ +:mod:`cassandra` - Exceptions and Enums +======================================= + +.. module:: cassandra + +.. data:: __version_info__ + + The version of the driver in a tuple format + +.. data:: __version__ + + The version of the driver in a string format + +.. autoclass:: ConsistencyLevel + :members: + +.. autoclass:: ProtocolVersion + :members: + +.. autoclass:: UserFunctionDescriptor + :members: + :inherited-members: + +.. autoclass:: UserAggregateDescriptor + :members: + :inherited-members: + +.. autoexception:: DriverException() + :members: + +.. autoexception:: RequestExecutionException() + :members: + +.. autoexception:: Unavailable() + :members: + +.. autoexception:: Timeout() + :members: + +.. autoexception:: ReadTimeout() + :members: + +.. autoexception:: WriteTimeout() + :members: + +.. autoexception:: CoordinationFailure() + :members: + +.. autoexception:: ReadFailure() + :members: + +.. autoexception:: WriteFailure() + :members: + +.. autoexception:: FunctionFailure() + :members: + +.. autoexception:: RequestValidationException() + :members: + +.. autoexception:: ConfigurationException() + :members: + +.. autoexception:: AlreadyExists() + :members: + +.. autoexception:: InvalidRequest() + :members: + +.. autoexception:: Unauthorized() + :members: + +.. autoexception:: AuthenticationFailed() + :members: + +.. autoexception:: OperationTimedOut() + :members: diff --git a/3.25.4-scylla/_sources/api/cassandra/auth.rst.txt b/3.25.4-scylla/_sources/api/cassandra/auth.rst.txt new file mode 100644 index 0000000000..58c964cf89 --- /dev/null +++ b/3.25.4-scylla/_sources/api/cassandra/auth.rst.txt @@ -0,0 +1,22 @@ +``cassandra.auth`` - Authentication +=================================== + +.. module:: cassandra.auth + +.. autoclass:: AuthProvider + :members: + +.. autoclass:: Authenticator + :members: + +.. autoclass:: PlainTextAuthProvider + :members: + +.. autoclass:: PlainTextAuthenticator + :members: + +.. autoclass:: SaslAuthProvider + :members: + +.. autoclass:: SaslAuthenticator + :members: diff --git a/3.25.4-scylla/_sources/api/cassandra/cluster.rst.txt b/3.25.4-scylla/_sources/api/cassandra/cluster.rst.txt new file mode 100644 index 0000000000..2b3d7828a8 --- /dev/null +++ b/3.25.4-scylla/_sources/api/cassandra/cluster.rst.txt @@ -0,0 +1,228 @@ +``cassandra.cluster`` - Clusters and Sessions +============================================= + +.. module:: cassandra.cluster + +.. autoclass:: Cluster ([contact_points=('127.0.0.1',)][, port=9042][, executor_threads=2], **attr_kwargs) + + .. autoattribute:: contact_points + + .. autoattribute:: port + + .. autoattribute:: cql_version + + .. autoattribute:: protocol_version + + .. autoattribute:: compression + + .. autoattribute:: auth_provider + + .. autoattribute:: load_balancing_policy + + .. autoattribute:: reconnection_policy + + .. autoattribute:: default_retry_policy + :annotation: = + + .. autoattribute:: conviction_policy_factory + + .. autoattribute:: address_translator + + .. autoattribute:: metrics_enabled + + .. autoattribute:: metrics + + .. autoattribute:: ssl_context + + .. autoattribute:: ssl_options + + .. autoattribute:: sockopts + + .. autoattribute:: max_schema_agreement_wait + + .. autoattribute:: metadata + + .. autoattribute:: connection_class + + .. autoattribute:: control_connection_timeout + + .. autoattribute:: idle_heartbeat_interval + + .. autoattribute:: idle_heartbeat_timeout + + .. autoattribute:: schema_event_refresh_window + + .. autoattribute:: topology_event_refresh_window + + .. autoattribute:: status_event_refresh_window + + .. autoattribute:: prepare_on_all_hosts + + .. autoattribute:: reprepare_on_up + + .. autoattribute:: connect_timeout + + .. autoattribute:: schema_metadata_enabled + :annotation: = True + + .. autoattribute:: token_metadata_enabled + :annotation: = True + + .. autoattribute:: timestamp_generator + + .. autoattribute:: endpoint_factory + + .. autoattribute:: cloud + + .. automethod:: connect + + .. automethod:: shutdown + + .. automethod:: register_user_type + + .. automethod:: register_listener + + .. automethod:: unregister_listener + + .. automethod:: add_execution_profile + + .. automethod:: set_max_requests_per_connection + + .. automethod:: get_max_requests_per_connection + + .. automethod:: set_min_requests_per_connection + + .. automethod:: get_min_requests_per_connection + + .. automethod:: get_core_connections_per_host + + .. automethod:: set_core_connections_per_host + + .. automethod:: get_max_connections_per_host + + .. automethod:: set_max_connections_per_host + + .. automethod:: get_control_connection_host + + .. automethod:: refresh_schema_metadata + + .. automethod:: refresh_keyspace_metadata + + .. automethod:: refresh_table_metadata + + .. automethod:: refresh_user_type_metadata + + .. automethod:: refresh_user_function_metadata + + .. automethod:: refresh_user_aggregate_metadata + + .. automethod:: refresh_nodes + + .. automethod:: set_meta_refresh_enabled + +.. autoclass:: ExecutionProfile (load_balancing_policy=, retry_policy=None, consistency_level=ConsistencyLevel.LOCAL_ONE, serial_consistency_level=None, request_timeout=10.0, row_factory=, speculative_execution_policy=None) + :members: + :exclude-members: consistency_level + + .. autoattribute:: consistency_level + :annotation: = LOCAL_ONE + +.. autoclass:: GraphExecutionProfile (load_balancing_policy=_NOT_SET, retry_policy=None, consistency_level=ConsistencyLevel.LOCAL_ONE, serial_consistency_level=None, request_timeout=30.0, row_factory=None, graph_options=None, continuous_paging_options=_NOT_SET) + :members: + +.. autoclass:: GraphAnalyticsExecutionProfile (load_balancing_policy=None, retry_policy=None, consistency_level=ConsistencyLevel.LOCAL_ONE, serial_consistency_level=None, request_timeout=3600. * 24. * 7., row_factory=None, graph_options=None) + :members: + +.. autodata:: EXEC_PROFILE_DEFAULT + :annotation: + +.. autodata:: EXEC_PROFILE_GRAPH_DEFAULT + :annotation: + +.. autodata:: EXEC_PROFILE_GRAPH_SYSTEM_DEFAULT + :annotation: + +.. autodata:: EXEC_PROFILE_GRAPH_ANALYTICS_DEFAULT + :annotation: + +.. autoclass:: Session () + + .. autoattribute:: default_timeout + :annotation: = 10.0 + + .. autoattribute:: default_consistency_level + :annotation: = LOCAL_ONE + + .. autoattribute:: default_serial_consistency_level + :annotation: = None + + .. autoattribute:: row_factory + :annotation: = + + .. autoattribute:: default_fetch_size + + .. autoattribute:: use_client_timestamp + + .. autoattribute:: timestamp_generator + + .. autoattribute:: encoder + + .. autoattribute:: client_protocol_handler + + .. automethod:: execute(statement[, parameters][, timeout][, trace][, custom_payload][, paging_state][, host][, execute_as]) + + .. automethod:: execute_async(statement[, parameters][, trace][, custom_payload][, paging_state][, host][, execute_as]) + + .. automethod:: execute_graph(statement[, parameters][, trace][, execution_profile=EXEC_PROFILE_GRAPH_DEFAULT][, execute_as]) + + .. automethod:: execute_graph_async(statement[, parameters][, trace][, execution_profile=EXEC_PROFILE_GRAPH_DEFAULT][, execute_as]) + + .. automethod:: prepare(statement) + + .. automethod:: shutdown() + + .. automethod:: set_keyspace(keyspace) + + .. automethod:: get_execution_profile + + .. automethod:: execution_profile_clone_update + + .. automethod:: add_request_init_listener + + .. automethod:: remove_request_init_listener + +.. autoclass:: ResponseFuture () + + .. autoattribute:: query + + .. automethod:: result() + + .. automethod:: get_query_trace() + + .. automethod:: get_all_query_traces() + + .. autoattribute:: custom_payload() + + .. autoattribute:: is_schema_agreed + + .. autoattribute:: has_more_pages + + .. autoattribute:: warnings + + .. automethod:: start_fetching_next_page() + + .. automethod:: add_callback(fn, *args, **kwargs) + + .. automethod:: add_errback(fn, *args, **kwargs) + + .. automethod:: add_callbacks(callback, errback, callback_args=(), callback_kwargs=None, errback_args=(), errback_args=None) + +.. autoclass:: ResultSet () + :members: + +.. autoexception:: QueryExhausted () + +.. autoexception:: NoHostAvailable () + :members: + +.. autoexception:: UserTypeDoesNotExist () diff --git a/3.25.4-scylla/_sources/api/cassandra/concurrent.rst.txt b/3.25.4-scylla/_sources/api/cassandra/concurrent.rst.txt new file mode 100644 index 0000000000..f4bab6f048 --- /dev/null +++ b/3.25.4-scylla/_sources/api/cassandra/concurrent.rst.txt @@ -0,0 +1,8 @@ +``cassandra.concurrent`` - Utilities for Concurrent Statement Execution +======================================================================= + +.. module:: cassandra.concurrent + +.. autofunction:: execute_concurrent + +.. autofunction:: execute_concurrent_with_args diff --git a/3.25.4-scylla/_sources/api/cassandra/connection.rst.txt b/3.25.4-scylla/_sources/api/cassandra/connection.rst.txt new file mode 100644 index 0000000000..32cca590c0 --- /dev/null +++ b/3.25.4-scylla/_sources/api/cassandra/connection.rst.txt @@ -0,0 +1,21 @@ +``cassandra.connection`` - Low Level Connection Info +==================================================== + +.. module:: cassandra.connection + +.. autoexception:: ConnectionException () +.. autoexception:: ConnectionShutdown () +.. autoexception:: ConnectionBusy () +.. autoexception:: ProtocolError () + +.. autoclass:: EndPoint + :members: + +.. autoclass:: EndPointFactory + :members: + +.. autoclass:: SniEndPoint + +.. autoclass:: SniEndPointFactory + +.. autoclass:: UnixSocketEndPoint diff --git a/3.25.4-scylla/_sources/api/cassandra/cqlengine/columns.rst.txt b/3.25.4-scylla/_sources/api/cassandra/cqlengine/columns.rst.txt new file mode 100644 index 0000000000..d44be8adb8 --- /dev/null +++ b/3.25.4-scylla/_sources/api/cassandra/cqlengine/columns.rst.txt @@ -0,0 +1,89 @@ +``cassandra.cqlengine.columns`` - Column types for object mapping models +======================================================================== + +.. module:: cassandra.cqlengine.columns + +Columns +------- + +Columns in your models map to columns in your CQL table. You define CQL columns by defining column attributes on your model classes. +For a model to be valid it needs at least one primary key column and one non-primary key column. + +Just as in CQL, the order you define your columns in is important, and is the same order they are defined in on a model's corresponding table. + +Each column on your model definitions needs to be an instance of a Column class. + +.. autoclass:: Column(**kwargs) + + .. autoattribute:: primary_key + + .. autoattribute:: partition_key + + .. autoattribute:: index + + .. autoattribute:: custom_index + + .. autoattribute:: db_field + + .. autoattribute:: default + + .. autoattribute:: required + + .. autoattribute:: clustering_order + + .. autoattribute:: discriminator_column + + .. autoattribute:: static + +Column Types +------------ + +Columns of all types are initialized by passing :class:`.Column` attributes to the constructor by keyword. + +.. autoclass:: Ascii(**kwargs) + +.. autoclass:: BigInt(**kwargs) + +.. autoclass:: Blob(**kwargs) + +.. autoclass:: Bytes(**kwargs) + +.. autoclass:: Boolean(**kwargs) + +.. autoclass:: Counter + +.. autoclass:: Date(**kwargs) + +.. autoclass:: DateTime(**kwargs) + + .. autoattribute:: truncate_microseconds + +.. autoclass:: Decimal(**kwargs) + +.. autoclass:: Double(**kwargs) + +.. autoclass:: Float + +.. autoclass:: Integer(**kwargs) + +.. autoclass:: List + +.. autoclass:: Map + +.. autoclass:: Set + +.. autoclass:: SmallInt(**kwargs) + +.. autoclass:: Text + +.. autoclass:: Time(**kwargs) + +.. autoclass:: TimeUUID(**kwargs) + +.. autoclass:: TinyInt(**kwargs) + +.. autoclass:: UserDefinedType + +.. autoclass:: UUID(**kwargs) + +.. autoclass:: VarInt(**kwargs) diff --git a/3.25.4-scylla/_sources/api/cassandra/cqlengine/connection.rst.txt b/3.25.4-scylla/_sources/api/cassandra/cqlengine/connection.rst.txt new file mode 100644 index 0000000000..0f584fcca2 --- /dev/null +++ b/3.25.4-scylla/_sources/api/cassandra/cqlengine/connection.rst.txt @@ -0,0 +1,16 @@ +``cassandra.cqlengine.connection`` - Connection management for cqlengine +======================================================================== + +.. module:: cassandra.cqlengine.connection + +.. autofunction:: default + +.. autofunction:: set_session + +.. autofunction:: setup + +.. autofunction:: register_connection + +.. autofunction:: unregister_connection + +.. autofunction:: set_default_connection diff --git a/3.25.4-scylla/_sources/api/cassandra/cqlengine/management.rst.txt b/3.25.4-scylla/_sources/api/cassandra/cqlengine/management.rst.txt new file mode 100644 index 0000000000..fb483abc81 --- /dev/null +++ b/3.25.4-scylla/_sources/api/cassandra/cqlengine/management.rst.txt @@ -0,0 +1,19 @@ +``cassandra.cqlengine.management`` - Schema management for cqlengine +======================================================================== + +.. module:: cassandra.cqlengine.management + +A collection of functions for managing keyspace and table schema. + +.. autofunction:: create_keyspace_simple + +.. autofunction:: create_keyspace_network_topology + +.. autofunction:: drop_keyspace + +.. autofunction:: sync_table + +.. autofunction:: sync_type + +.. autofunction:: drop_table + diff --git a/3.25.4-scylla/_sources/api/cassandra/cqlengine/models.rst.txt b/3.25.4-scylla/_sources/api/cassandra/cqlengine/models.rst.txt new file mode 100644 index 0000000000..60b1471184 --- /dev/null +++ b/3.25.4-scylla/_sources/api/cassandra/cqlengine/models.rst.txt @@ -0,0 +1,197 @@ +``cassandra.cqlengine.models`` - Table models for object mapping +================================================================ + +.. module:: cassandra.cqlengine.models + +Model +----- +.. autoclass:: Model(\*\*kwargs) + + The initializer creates an instance of the model. Pass in keyword arguments for columns you've defined on the model. + + .. code-block:: python + + class Person(Model): + id = columns.UUID(primary_key=True) + first_name = columns.Text() + last_name = columns.Text() + + person = Person(first_name='Blake', last_name='Eggleston') + person.first_name #returns 'Blake' + person.last_name #returns 'Eggleston' + + Model attributes define how the model maps to tables in the database. These are class variables that should be set + when defining Model deriviatives. + + .. autoattribute:: __abstract__ + :annotation: = False + + .. autoattribute:: __table_name__ + + .. autoattribute:: __table_name_case_sensitive__ + + .. autoattribute:: __keyspace__ + + .. autoattribute:: __connection__ + + .. attribute:: __default_ttl__ + :annotation: = None + + Will be deprecated in release 4.0. You can set the default ttl by configuring the table ``__options__``. See :ref:`ttl-change` for more details. + + .. autoattribute:: __discriminator_value__ + + See :ref:`model_inheritance` for usage examples. + + Each table can have its own set of configuration options, including compaction. Unspecified, these default to sensible values in + the server. To override defaults, set options using the model ``__options__`` attribute, which allows options specified a dict. + + When a table is synced, it will be altered to match the options set on your table. + This means that if you are changing settings manually they will be changed back on resync. + + Do not use the options settings of cqlengine if you want to manage your compaction settings manually. + + See the `list of supported table properties for more information + `_. + + .. attribute:: __options__ + + For example: + + .. code-block:: python + + class User(Model): + __options__ = {'compaction': {'class': 'LeveledCompactionStrategy', + 'sstable_size_in_mb': '64', + 'tombstone_threshold': '.2'}, + 'comment': 'User data stored here'} + + user_id = columns.UUID(primary_key=True) + name = columns.Text() + + or : + + .. code-block:: python + + class TimeData(Model): + __options__ = {'compaction': {'class': 'SizeTieredCompactionStrategy', + 'bucket_low': '.3', + 'bucket_high': '2', + 'min_threshold': '2', + 'max_threshold': '64', + 'tombstone_compaction_interval': '86400'}, + 'gc_grace_seconds': '0'} + + .. autoattribute:: __compute_routing_key__ + + + The base methods allow creating, storing, and querying modeled objects. + + .. automethod:: create + + .. method:: if_not_exists() + + Check the existence of an object before insertion. The existence of an + object is determined by its primary key(s). And please note using this flag + would incur performance cost. + + If the insertion isn't applied, a :class:`~cassandra.cqlengine.query.LWTException` is raised. + + .. code-block:: python + + try: + TestIfNotExistsModel.if_not_exists().create(id=id, count=9, text='111111111111') + except LWTException as e: + # handle failure case + print e.existing # dict containing LWT result fields + + This method is supported on Cassandra 2.0 or later. + + .. method:: if_exists() + + Check the existence of an object before an update or delete. The existence of an + object is determined by its primary key(s). And please note using this flag + would incur performance cost. + + If the update or delete isn't applied, a :class:`~cassandra.cqlengine.query.LWTException` is raised. + + .. code-block:: python + + try: + TestIfExistsModel.objects(id=id).if_exists().update(count=9, text='111111111111') + except LWTException as e: + # handle failure case + pass + + This method is supported on Cassandra 2.0 or later. + + .. automethod:: save + + .. automethod:: update + + .. method:: iff(**values) + + Checks to ensure that the values specified are correct on the Cassandra cluster. + Simply specify the column(s) and the expected value(s). As with if_not_exists, + this incurs a performance cost. + + If the insertion isn't applied, a :class:`~cassandra.cqlengine.query.LWTException` is raised. + + .. code-block:: python + + t = TestTransactionModel(text='some text', count=5) + try: + t.iff(count=5).update('other text') + except LWTException as e: + # handle failure case + print e.existing # existing object + + .. automethod:: get + + .. automethod:: filter + + .. automethod:: all + + .. automethod:: delete + + .. method:: batch(batch_object) + + Sets the batch object to run instance updates and inserts queries with. + + See :doc:`/cqlengine/batches` for usage examples + + .. automethod:: timeout + + .. method:: timestamp(timedelta_or_datetime) + + Sets the timestamp for the query + + .. method:: ttl(ttl_in_sec) + + Sets the ttl values to run instance updates and inserts queries with. + + .. method:: using(connection=None) + + Change the context on the fly of the model instance (keyspace, connection) + + .. automethod:: column_family_name + + Models also support dict-like access: + + .. method:: len(m) + + Returns the number of columns defined in the model + + .. method:: m[col_name] + + Returns the value of column ``col_name`` + + .. method:: m[col_name] = value + + Set ``m[col_name]`` to value + + .. automethod:: keys + + .. automethod:: values + + .. automethod:: items diff --git a/3.25.4-scylla/_sources/api/cassandra/cqlengine/query.rst.txt b/3.25.4-scylla/_sources/api/cassandra/cqlengine/query.rst.txt new file mode 100644 index 0000000000..ce8f764b6b --- /dev/null +++ b/3.25.4-scylla/_sources/api/cassandra/cqlengine/query.rst.txt @@ -0,0 +1,71 @@ +``cassandra.cqlengine.query`` - Query and filter model objects +================================================================= + +.. module:: cassandra.cqlengine.query + +QuerySet +-------- +QuerySet objects are typically obtained by calling :meth:`~.cassandra.cqlengine.models.Model.objects` on a model class. +The methods here are used to filter, order, and constrain results. + +.. autoclass:: ModelQuerySet + + .. automethod:: all + + .. automethod:: batch + + .. automethod:: consistency + + .. automethod:: count + + .. method:: len(queryset) + + Returns the number of rows matched by this query. This function uses :meth:`~.cassandra.cqlengine.query.ModelQuerySet.count` internally. + + *Note: This function executes a SELECT COUNT() and has a performance cost on large datasets* + + .. automethod:: distinct + + .. automethod:: filter + + .. automethod:: get + + .. automethod:: limit + + .. automethod:: fetch_size + + .. automethod:: if_not_exists + + .. automethod:: if_exists + + .. automethod:: order_by + + .. automethod:: allow_filtering + + .. automethod:: only + + .. automethod:: defer + + .. automethod:: timestamp + + .. automethod:: ttl + + .. automethod:: using + + .. _blind_updates: + + .. automethod:: update + +.. autoclass:: BatchQuery + :members: + + .. automethod:: add_query + .. automethod:: execute + +.. autoclass:: ContextQuery + +.. autoclass:: DoesNotExist + +.. autoclass:: MultipleObjectsReturned + +.. autoclass:: LWTException diff --git a/3.25.4-scylla/_sources/api/cassandra/cqlengine/usertype.rst.txt b/3.25.4-scylla/_sources/api/cassandra/cqlengine/usertype.rst.txt new file mode 100644 index 0000000000..ebed187da9 --- /dev/null +++ b/3.25.4-scylla/_sources/api/cassandra/cqlengine/usertype.rst.txt @@ -0,0 +1,10 @@ +``cassandra.cqlengine.usertype`` - Model classes for User Defined Types +======================================================================= + +.. module:: cassandra.cqlengine.usertype + +UserType +-------- +.. autoclass:: UserType + + .. autoattribute:: __type_name__ diff --git a/3.25.4-scylla/_sources/api/cassandra/datastax/graph/fluent/index.rst.txt b/3.25.4-scylla/_sources/api/cassandra/datastax/graph/fluent/index.rst.txt new file mode 100644 index 0000000000..5547e0fdd7 --- /dev/null +++ b/3.25.4-scylla/_sources/api/cassandra/datastax/graph/fluent/index.rst.txt @@ -0,0 +1,24 @@ +:mod:`cassandra.datastax.graph.fluent` +====================================== + +.. module:: cassandra.datastax.graph.fluent + +.. autoclass:: DseGraph + + .. autoattribute:: DSE_GRAPH_QUERY_LANGUAGE + + .. automethod:: create_execution_profile + + .. automethod:: query_from_traversal + + .. automethod:: traversal_source(session=None, graph_name=None, execution_profile=EXEC_PROFILE_GRAPH_DEFAULT, traversal_class=None) + + .. automethod:: batch(session=None, execution_profile=None) + +.. autoclass:: DSESessionRemoteGraphConnection(session[, graph_name, execution_profile]) + +.. autoclass:: BaseGraphRowFactory + +.. autoclass:: graph_traversal_row_factory + +.. autoclass:: graph_traversal_dse_object_row_factory diff --git a/3.25.4-scylla/_sources/api/cassandra/datastax/graph/fluent/predicates.rst.txt b/3.25.4-scylla/_sources/api/cassandra/datastax/graph/fluent/predicates.rst.txt new file mode 100644 index 0000000000..f6e86f6451 --- /dev/null +++ b/3.25.4-scylla/_sources/api/cassandra/datastax/graph/fluent/predicates.rst.txt @@ -0,0 +1,14 @@ +:mod:`cassandra.datastax.graph.fluent.predicates` +================================================= + +.. module:: cassandra.datastax.graph.fluent.predicates + + +.. autoclass:: Search + :members: + +.. autoclass:: CqlCollection + :members: + +.. autoclass:: Geo + :members: diff --git a/3.25.4-scylla/_sources/api/cassandra/datastax/graph/fluent/query.rst.txt b/3.25.4-scylla/_sources/api/cassandra/datastax/graph/fluent/query.rst.txt new file mode 100644 index 0000000000..3dd859f96e --- /dev/null +++ b/3.25.4-scylla/_sources/api/cassandra/datastax/graph/fluent/query.rst.txt @@ -0,0 +1,8 @@ +:mod:`cassandra.datastax.graph.fluent.query` +============================================ + +.. module:: cassandra.datastax.graph.fluent.query + + +.. autoclass:: TraversalBatch + :members: diff --git a/3.25.4-scylla/_sources/api/cassandra/datastax/graph/index.rst.txt b/3.25.4-scylla/_sources/api/cassandra/datastax/graph/index.rst.txt new file mode 100644 index 0000000000..a9b41cbdc2 --- /dev/null +++ b/3.25.4-scylla/_sources/api/cassandra/datastax/graph/index.rst.txt @@ -0,0 +1,133 @@ +``cassandra.datastax.graph`` - Graph Statements, Options, and Row Factories +=========================================================================== + +.. _api-datastax-graph: + +.. module:: cassandra.datastax.graph + +.. autofunction:: single_object_row_factory + +.. autofunction:: graph_result_row_factory + +.. autofunction:: graph_object_row_factory + +.. autofunction:: graph_graphson2_row_factory + +.. autofunction:: graph_graphson3_row_factory + +.. function:: to_int(value) + + Wraps a value to be explicitly serialized as a graphson Int. + +.. function:: to_bigint(value) + + Wraps a value to be explicitly serialized as a graphson Bigint. + +.. function:: to_smallint(value) + + Wraps a value to be explicitly serialized as a graphson Smallint. + +.. function:: to_float(value) + + Wraps a value to be explicitly serialized as a graphson Float. + +.. function:: to_double(value) + + Wraps a value to be explicitly serialized as a graphson Double. + +.. autoclass:: GraphProtocol + :members: + :noindex: + +.. autoclass:: GraphOptions + :noindex: + + .. autoattribute:: graph_name + + .. autoattribute:: graph_source + + .. autoattribute:: graph_language + + .. autoattribute:: graph_read_consistency_level + + .. autoattribute:: graph_write_consistency_level + + .. autoattribute:: is_default_source + + .. autoattribute:: is_analytics_source + + .. autoattribute:: is_graph_source + + .. automethod:: set_source_default + + .. automethod:: set_source_analytics + + .. automethod:: set_source_graph + + +.. autoclass:: SimpleGraphStatement + :members: + :noindex: + +.. autoclass:: Result + :members: + :noindex: + +.. autoclass:: Vertex + :members: + :noindex: + +.. autoclass:: VertexProperty + :members: + :noindex: + +.. autoclass:: Edge + :members: + :noindex: + +.. autoclass:: Path + :members: + :noindex: + +.. autoclass:: T + :members: + :noindex: + +.. autoclass:: GraphSON1Serializer + :members: + :noindex: + +.. autoclass:: GraphSON1Deserializer + :noindex: + + .. automethod:: deserialize_date + + .. automethod:: deserialize_timestamp + + .. automethod:: deserialize_time + + .. automethod:: deserialize_duration + + .. automethod:: deserialize_int + + .. automethod:: deserialize_bigint + + .. automethod:: deserialize_double + + .. automethod:: deserialize_float + + .. automethod:: deserialize_uuid + + .. automethod:: deserialize_blob + + .. automethod:: deserialize_decimal + + .. automethod:: deserialize_point + + .. automethod:: deserialize_linestring + + .. automethod:: deserialize_polygon + +.. autoclass:: GraphSON2Reader + :members: + :noindex: diff --git a/3.25.4-scylla/_sources/api/cassandra/decoder.rst.txt b/3.25.4-scylla/_sources/api/cassandra/decoder.rst.txt new file mode 100644 index 0000000000..e213cc6d74 --- /dev/null +++ b/3.25.4-scylla/_sources/api/cassandra/decoder.rst.txt @@ -0,0 +1,20 @@ +``cassandra.decoder`` - Data Return Formats +=========================================== + +.. module:: cassandra.decoder + +.. function:: tuple_factory + + **Deprecated in 2.0.0.** Use :meth:`cassandra.query.tuple_factory` + +.. function:: named_tuple_factory + + **Deprecated in 2.0.0.** Use :meth:`cassandra.query.named_tuple_factory` + +.. function:: dict_factory + + **Deprecated in 2.0.0.** Use :meth:`cassandra.query.dict_factory` + +.. function:: ordered_dict_factory + + **Deprecated in 2.0.0.** Use :meth:`cassandra.query.ordered_dict_factory` diff --git a/3.25.4-scylla/_sources/api/cassandra/encoder.rst.txt b/3.25.4-scylla/_sources/api/cassandra/encoder.rst.txt new file mode 100644 index 0000000000..de3b180510 --- /dev/null +++ b/3.25.4-scylla/_sources/api/cassandra/encoder.rst.txt @@ -0,0 +1,36 @@ +``cassandra.encoder`` - Encoders for non-prepared Statements +============================================================ + +.. module:: cassandra.encoder + +.. autoclass:: Encoder () + + .. autoattribute:: cassandra.encoder.Encoder.mapping + + .. automethod:: cassandra.encoder.Encoder.cql_encode_none () + + .. automethod:: cassandra.encoder.Encoder.cql_encode_object () + + .. automethod:: cassandra.encoder.Encoder.cql_encode_all_types () + + .. automethod:: cassandra.encoder.Encoder.cql_encode_sequence () + + .. automethod:: cassandra.encoder.Encoder.cql_encode_str () + + .. automethod:: cassandra.encoder.Encoder.cql_encode_unicode () + + .. automethod:: cassandra.encoder.Encoder.cql_encode_bytes () + + Converts strings, buffers, and bytearrays into CQL blob literals. + + .. automethod:: cassandra.encoder.Encoder.cql_encode_datetime () + + .. automethod:: cassandra.encoder.Encoder.cql_encode_date () + + .. automethod:: cassandra.encoder.Encoder.cql_encode_map_collection () + + .. automethod:: cassandra.encoder.Encoder.cql_encode_list_collection () + + .. automethod:: cassandra.encoder.Encoder.cql_encode_set_collection () + + .. automethod:: cql_encode_tuple () diff --git a/3.25.4-scylla/_sources/api/cassandra/graph.rst.txt b/3.25.4-scylla/_sources/api/cassandra/graph.rst.txt new file mode 100644 index 0000000000..43ddd3086c --- /dev/null +++ b/3.25.4-scylla/_sources/api/cassandra/graph.rst.txt @@ -0,0 +1,121 @@ +``cassandra.graph`` - Graph Statements, Options, and Row Factories +================================================================== + +.. note:: This module is only for backward compatibility for dse-driver users. Consider using :ref:`cassandra.datastax.graph `. + +.. module:: cassandra.graph + +.. autofunction:: single_object_row_factory + +.. autofunction:: graph_result_row_factory + +.. autofunction:: graph_object_row_factory + +.. autofunction:: graph_graphson2_row_factory + +.. autofunction:: graph_graphson3_row_factory + +.. function:: to_int(value) + + Wraps a value to be explicitly serialized as a graphson Int. + +.. function:: to_bigint(value) + + Wraps a value to be explicitly serialized as a graphson Bigint. + +.. function:: to_smallint(value) + + Wraps a value to be explicitly serialized as a graphson Smallint. + +.. function:: to_float(value) + + Wraps a value to be explicitly serialized as a graphson Float. + +.. function:: to_double(value) + + Wraps a value to be explicitly serialized as a graphson Double. + +.. autoclass:: GraphProtocol + :members: + +.. autoclass:: GraphOptions + + .. autoattribute:: graph_name + + .. autoattribute:: graph_source + + .. autoattribute:: graph_language + + .. autoattribute:: graph_read_consistency_level + + .. autoattribute:: graph_write_consistency_level + + .. autoattribute:: is_default_source + + .. autoattribute:: is_analytics_source + + .. autoattribute:: is_graph_source + + .. automethod:: set_source_default + + .. automethod:: set_source_analytics + + .. automethod:: set_source_graph + + +.. autoclass:: SimpleGraphStatement + :members: + +.. autoclass:: Result + :members: + +.. autoclass:: Vertex + :members: + +.. autoclass:: VertexProperty + :members: + +.. autoclass:: Edge + :members: + +.. autoclass:: Path + :members: + +.. autoclass:: GraphSON1Serializer + :members: + +.. autoclass:: GraphSON1Deserializer + + .. automethod:: deserialize_date + + .. automethod:: deserialize_timestamp + + .. automethod:: deserialize_time + + .. automethod:: deserialize_duration + + .. automethod:: deserialize_int + + .. automethod:: deserialize_bigint + + .. automethod:: deserialize_double + + .. automethod:: deserialize_float + + .. automethod:: deserialize_uuid + + .. automethod:: deserialize_blob + + .. automethod:: deserialize_decimal + + .. automethod:: deserialize_point + + .. automethod:: deserialize_linestring + + .. automethod:: deserialize_polygon + +.. autoclass:: GraphSON2Reader + :members: + +.. autoclass:: GraphSON3Reader + :members: diff --git a/3.25.4-scylla/_sources/api/cassandra/io/asyncioreactor.rst.txt b/3.25.4-scylla/_sources/api/cassandra/io/asyncioreactor.rst.txt new file mode 100644 index 0000000000..38ae63ca7f --- /dev/null +++ b/3.25.4-scylla/_sources/api/cassandra/io/asyncioreactor.rst.txt @@ -0,0 +1,7 @@ +``cassandra.io.asyncioreactor`` - ``asyncio`` Event Loop +===================================================================== + +.. module:: cassandra.io.asyncioreactor + +.. autoclass:: AsyncioConnection + :members: diff --git a/3.25.4-scylla/_sources/api/cassandra/io/asyncorereactor.rst.txt b/3.25.4-scylla/_sources/api/cassandra/io/asyncorereactor.rst.txt new file mode 100644 index 0000000000..ade7887e70 --- /dev/null +++ b/3.25.4-scylla/_sources/api/cassandra/io/asyncorereactor.rst.txt @@ -0,0 +1,7 @@ +``cassandra.io.asyncorereactor`` - ``asyncore`` Event Loop +========================================================== + +.. module:: cassandra.io.asyncorereactor + +.. autoclass:: AsyncoreConnection + :members: diff --git a/3.25.4-scylla/_sources/api/cassandra/io/eventletreactor.rst.txt b/3.25.4-scylla/_sources/api/cassandra/io/eventletreactor.rst.txt new file mode 100644 index 0000000000..1ba742c7e9 --- /dev/null +++ b/3.25.4-scylla/_sources/api/cassandra/io/eventletreactor.rst.txt @@ -0,0 +1,7 @@ +``cassandra.io.eventletreactor`` - ``eventlet``-compatible Connection +===================================================================== + +.. module:: cassandra.io.eventletreactor + +.. autoclass:: EventletConnection + :members: diff --git a/3.25.4-scylla/_sources/api/cassandra/io/geventreactor.rst.txt b/3.25.4-scylla/_sources/api/cassandra/io/geventreactor.rst.txt new file mode 100644 index 0000000000..603affe140 --- /dev/null +++ b/3.25.4-scylla/_sources/api/cassandra/io/geventreactor.rst.txt @@ -0,0 +1,7 @@ +``cassandra.io.geventreactor`` - ``gevent``-compatible Event Loop +================================================================= + +.. module:: cassandra.io.geventreactor + +.. autoclass:: GeventConnection + :members: diff --git a/3.25.4-scylla/_sources/api/cassandra/io/libevreactor.rst.txt b/3.25.4-scylla/_sources/api/cassandra/io/libevreactor.rst.txt new file mode 100644 index 0000000000..5b7288edf2 --- /dev/null +++ b/3.25.4-scylla/_sources/api/cassandra/io/libevreactor.rst.txt @@ -0,0 +1,6 @@ +``cassandra.io.libevreactor`` - ``libev`` Event Loop +==================================================== + +.. module:: cassandra.io.libevreactor + +.. autoclass:: LibevConnection diff --git a/3.25.4-scylla/_sources/api/cassandra/io/twistedreactor.rst.txt b/3.25.4-scylla/_sources/api/cassandra/io/twistedreactor.rst.txt new file mode 100644 index 0000000000..24e93bd432 --- /dev/null +++ b/3.25.4-scylla/_sources/api/cassandra/io/twistedreactor.rst.txt @@ -0,0 +1,9 @@ +``cassandra.io.twistedreactor`` - Twisted Event Loop +==================================================== + +.. module:: cassandra.io.twistedreactor + +.. class:: TwistedConnection + + An implementation of :class:`~cassandra.io.connection.Connection` that uses + Twisted's reactor as its event loop. diff --git a/3.25.4-scylla/_sources/api/cassandra/metadata.rst.txt b/3.25.4-scylla/_sources/api/cassandra/metadata.rst.txt new file mode 100644 index 0000000000..7c1280bcf7 --- /dev/null +++ b/3.25.4-scylla/_sources/api/cassandra/metadata.rst.txt @@ -0,0 +1,93 @@ +``cassandra.metadata`` - Schema and Ring Topology +================================================= + +.. module:: cassandra.metadata + +.. autodata:: cql_keywords + :annotation: + +.. autodata:: cql_keywords_unreserved + :annotation: + +.. autodata:: cql_keywords_reserved + :annotation: + +.. autoclass:: Metadata () + :members: + :exclude-members: rebuild_schema, rebuild_token_map, add_host, remove_host + +Schemas +------- + +.. autoclass:: KeyspaceMetadata () + :members: + +.. autoclass:: UserType () + :members: + +.. autoclass:: Function () + :members: + +.. autoclass:: Aggregate () + :members: + +.. autoclass:: TableMetadata () + :members: + +.. autoclass:: TableMetadataV3 () + :members: + +.. autoclass:: TableMetadataDSE68 () + :members: + +.. autoclass:: ColumnMetadata () + :members: + +.. autoclass:: IndexMetadata () + :members: + +.. autoclass:: MaterializedViewMetadata () + :members: + +.. autoclass:: VertexMetadata () + :members: + +.. autoclass:: EdgeMetadata () + :members: + +Tokens and Ring Topology +------------------------ + +.. autoclass:: TokenMap () + :members: + +.. autoclass:: Token () + :members: + +.. autoclass:: Murmur3Token + :members: + +.. autoclass:: MD5Token + :members: + +.. autoclass:: BytesToken + :members: + +.. autoclass:: ReplicationStrategy + :members: + +.. autoclass:: ReplicationFactor + :members: + :exclude-members: create + +.. autoclass:: SimpleStrategy + :members: + +.. autoclass:: NetworkTopologyStrategy + :members: + +.. autoclass:: LocalStrategy + :members: + +.. autofunction:: group_keys_by_replica + diff --git a/3.25.4-scylla/_sources/api/cassandra/metrics.rst.txt b/3.25.4-scylla/_sources/api/cassandra/metrics.rst.txt new file mode 100644 index 0000000000..0df7f8b5b9 --- /dev/null +++ b/3.25.4-scylla/_sources/api/cassandra/metrics.rst.txt @@ -0,0 +1,7 @@ +``cassandra.metrics`` - Performance Metrics +=========================================== + +.. module:: cassandra.metrics + +.. autoclass:: cassandra.metrics.Metrics () + :members: diff --git a/3.25.4-scylla/_sources/api/cassandra/policies.rst.txt b/3.25.4-scylla/_sources/api/cassandra/policies.rst.txt new file mode 100644 index 0000000000..387b19ed95 --- /dev/null +++ b/3.25.4-scylla/_sources/api/cassandra/policies.rst.txt @@ -0,0 +1,96 @@ +``cassandra.policies`` - Load balancing and Failure Handling Policies +===================================================================== + +.. module:: cassandra.policies + +Load Balancing +-------------- + +.. autoclass:: HostDistance + :members: + +.. autoclass:: LoadBalancingPolicy + :members: + +.. autoclass:: RoundRobinPolicy + :members: + +.. autoclass:: DCAwareRoundRobinPolicy + :members: + +.. autoclass:: WhiteListRoundRobinPolicy + :members: + +.. autoclass:: TokenAwarePolicy + :members: + +.. autoclass:: HostFilterPolicy + + .. we document these methods manually so we can specify a param to predicate + + .. automethod:: predicate(host) + .. automethod:: distance + .. automethod:: make_query_plan + +.. autoclass:: DefaultLoadBalancingPolicy + :members: + +.. autoclass:: DSELoadBalancingPolicy + :members: + +Translating Server Node Addresses +--------------------------------- + +.. autoclass:: AddressTranslator + :members: + +.. autoclass:: IdentityTranslator + :members: + +.. autoclass:: EC2MultiRegionTranslator + :members: + +Marking Hosts Up or Down +------------------------ + +.. autoclass:: ConvictionPolicy + :members: + +.. autoclass:: SimpleConvictionPolicy + :members: + +Reconnecting to Dead Hosts +-------------------------- + +.. autoclass:: ReconnectionPolicy + :members: + +.. autoclass:: ConstantReconnectionPolicy + :members: + +.. autoclass:: ExponentialReconnectionPolicy + :members: + +Retrying Failed Operations +-------------------------- + +.. autoclass:: WriteType + :members: + +.. autoclass:: RetryPolicy + :members: + +.. autoclass:: FallthroughRetryPolicy + :members: + +.. autoclass:: DowngradingConsistencyRetryPolicy + :members: + +Retrying Idempotent Operations +------------------------------ + +.. autoclass:: SpeculativeExecutionPolicy + :members: + +.. autoclass:: ConstantSpeculativeExecutionPolicy + :members: diff --git a/3.25.4-scylla/_sources/api/cassandra/pool.rst.txt b/3.25.4-scylla/_sources/api/cassandra/pool.rst.txt new file mode 100644 index 0000000000..b14d30e19c --- /dev/null +++ b/3.25.4-scylla/_sources/api/cassandra/pool.rst.txt @@ -0,0 +1,11 @@ +``cassandra.pool`` - Hosts and Connection Pools +=============================================== + +.. automodule:: cassandra.pool + +.. autoclass:: Host () + :members: + :exclude-members: set_location_info, get_and_set_reconnection_handler + +.. autoexception:: NoConnectionsAvailable + :members: diff --git a/3.25.4-scylla/_sources/api/cassandra/protocol.rst.txt b/3.25.4-scylla/_sources/api/cassandra/protocol.rst.txt new file mode 100644 index 0000000000..f615ab1a70 --- /dev/null +++ b/3.25.4-scylla/_sources/api/cassandra/protocol.rst.txt @@ -0,0 +1,55 @@ +``cassandra.protocol`` - Protocol Features +===================================================================== + +.. module:: cassandra.protocol + +.. _custom_payload: + +Custom Payloads +--------------- +Native protocol version 4+ allows for a custom payload to be sent between clients +and custom query handlers. The payload is specified as a string:binary_type dict +holding custom key/value pairs. + +By default these are ignored by the server. They can be useful for servers implementing +a custom QueryHandler. + +See :meth:`.Session.execute`, ::meth:`.Session.execute_async`, :attr:`.ResponseFuture.custom_payload`. + +.. autoclass:: _ProtocolHandler + + .. autoattribute:: message_types_by_opcode + :annotation: = {default mapping} + + .. automethod:: encode_message + + .. automethod:: decode_message + +.. _faster_deser: + +Faster Deserialization +---------------------- +When python-driver is compiled with Cython, it uses a Cython-based deserialization path +to deserialize messages. By default, the driver will use a Cython-based parser that returns +lists of rows similar to the pure-Python version. In addition, there are two additional +ProtocolHandler classes that can be used to deserialize response messages: ``LazyProtocolHandler`` +and ``NumpyProtocolHandler``. They can be used as follows: + +.. code:: python + + from cassandra.protocol import NumpyProtocolHandler, LazyProtocolHandler + from cassandra.query import tuple_factory + s.client_protocol_handler = LazyProtocolHandler # for a result iterator + s.row_factory = tuple_factory #required for Numpy results + s.client_protocol_handler = NumpyProtocolHandler # for a dict of NumPy arrays as result + +These protocol handlers comprise different parsers, and return results as described below: + +- ProtocolHandler: this default implementation is a drop-in replacement for the pure-Python version. + The rows are all parsed upfront, before results are returned. + +- LazyProtocolHandler: near drop-in replacement for the above, except that it returns an iterator over rows, + lazily decoded into the default row format (this is more efficient since all decoded results are not materialized at once) + +- NumpyProtocolHander: deserializes results directly into NumPy arrays. This facilitates efficient integration with + analysis toolkits such as Pandas. diff --git a/3.25.4-scylla/_sources/api/cassandra/query.rst.txt b/3.25.4-scylla/_sources/api/cassandra/query.rst.txt new file mode 100644 index 0000000000..fcd79739b9 --- /dev/null +++ b/3.25.4-scylla/_sources/api/cassandra/query.rst.txt @@ -0,0 +1,59 @@ +``cassandra.query`` - Prepared Statements, Batch Statements, Tracing, and Row Factories +======================================================================================= + +.. module:: cassandra.query + +.. autofunction:: tuple_factory + +.. autofunction:: named_tuple_factory + +.. autofunction:: dict_factory + +.. autofunction:: ordered_dict_factory + +.. autoclass:: SimpleStatement + :members: + +.. autoclass:: PreparedStatement () + :members: + +.. autoclass:: BoundStatement + :members: + +.. autoclass:: Statement () + :members: + +.. autodata:: UNSET_VALUE + :annotation: + +.. autoclass:: BatchStatement (batch_type=BatchType.LOGGED, retry_policy=None, consistency_level=None) + :members: + +.. autoclass:: BatchType () + + .. autoattribute:: LOGGED + + .. autoattribute:: UNLOGGED + + .. autoattribute:: COUNTER + +.. autoclass:: cassandra.query.ValueSequence + + A wrapper class that is used to specify that a sequence of values should + be treated as a CQL list of values instead of a single column collection when used + as part of the `parameters` argument for :meth:`.Session.execute()`. + + This is typically needed when supplying a list of keys to select. + For example:: + + >>> my_user_ids = ('alice', 'bob', 'charles') + >>> query = "SELECT * FROM users WHERE user_id IN %s" + >>> session.execute(query, parameters=[ValueSequence(my_user_ids)]) + +.. autoclass:: QueryTrace () + :members: + +.. autoclass:: TraceEvent () + :members: + +.. autoexception:: TraceUnavailable diff --git a/3.25.4-scylla/_sources/api/cassandra/timestamps.rst.txt b/3.25.4-scylla/_sources/api/cassandra/timestamps.rst.txt new file mode 100644 index 0000000000..00d25b06d9 --- /dev/null +++ b/3.25.4-scylla/_sources/api/cassandra/timestamps.rst.txt @@ -0,0 +1,14 @@ +``cassandra.timestamps`` - Timestamp Generation +=============================================== + +.. module:: cassandra.timestamps + +.. autoclass:: MonotonicTimestampGenerator (warn_on_drift=True, warning_threshold=0, warning_interval=0) + + .. autoattribute:: warn_on_drift + + .. autoattribute:: warning_threshold + + .. autoattribute:: warning_interval + + .. automethod:: _next_timestamp diff --git a/3.25.4-scylla/_sources/api/cassandra/util.rst.txt b/3.25.4-scylla/_sources/api/cassandra/util.rst.txt new file mode 100644 index 0000000000..848d4d5fc2 --- /dev/null +++ b/3.25.4-scylla/_sources/api/cassandra/util.rst.txt @@ -0,0 +1,5 @@ +``cassandra.util`` - Utilities +=================================== + +.. automodule:: cassandra.util + :members: diff --git a/3.25.4-scylla/_sources/api/index.rst.txt b/3.25.4-scylla/_sources/api/index.rst.txt new file mode 100644 index 0000000000..9e778d508c --- /dev/null +++ b/3.25.4-scylla/_sources/api/index.rst.txt @@ -0,0 +1,54 @@ +API Documentation +================= + +Core Driver +----------- +.. toctree:: + :maxdepth: 2 + + cassandra + cassandra/cluster + cassandra/policies + cassandra/auth + cassandra/graph + cassandra/metadata + cassandra/metrics + cassandra/query + cassandra/pool + cassandra/protocol + cassandra/encoder + cassandra/decoder + cassandra/concurrent + cassandra/connection + cassandra/util + cassandra/timestamps + cassandra/io/asyncioreactor + cassandra/io/asyncorereactor + cassandra/io/eventletreactor + cassandra/io/libevreactor + cassandra/io/geventreactor + cassandra/io/twistedreactor + +.. _om_api: + +Object Mapper +------------- +.. toctree:: + :maxdepth: 1 + + cassandra/cqlengine/models + cassandra/cqlengine/columns + cassandra/cqlengine/query + cassandra/cqlengine/connection + cassandra/cqlengine/management + cassandra/cqlengine/usertype + +DataStax Graph +-------------- +.. toctree:: + :maxdepth: 1 + + cassandra/datastax/graph/index + cassandra/datastax/graph/fluent/index + cassandra/datastax/graph/fluent/query + cassandra/datastax/graph/fluent/predicates diff --git a/3.25.4-scylla/_sources/cqlengine/batches.rst.txt b/3.25.4-scylla/_sources/cqlengine/batches.rst.txt new file mode 100644 index 0000000000..306e7d01a6 --- /dev/null +++ b/3.25.4-scylla/_sources/cqlengine/batches.rst.txt @@ -0,0 +1,108 @@ +============= +Batch Queries +============= + +cqlengine supports batch queries using the BatchQuery class. Batch queries can be started and stopped manually, or within a context manager. To add queries to the batch object, you just need to precede the create/save/delete call with a call to batch, and pass in the batch object. + + +Batch Query General Use Pattern +=============================== + +You can only create, update, and delete rows with a batch query, attempting to read rows out of the database with a batch query will fail. + +.. code-block:: python + + from cassandra.cqlengine.query import BatchQuery + + #using a context manager + with BatchQuery() as b: + now = datetime.now() + em1 = ExampleModel.batch(b).create(example_type=0, description="1", created_at=now) + em2 = ExampleModel.batch(b).create(example_type=0, description="2", created_at=now) + em3 = ExampleModel.batch(b).create(example_type=0, description="3", created_at=now) + + # -- or -- + + #manually + b = BatchQuery() + now = datetime.now() + em1 = ExampleModel.batch(b).create(example_type=0, description="1", created_at=now) + em2 = ExampleModel.batch(b).create(example_type=0, description="2", created_at=now) + em3 = ExampleModel.batch(b).create(example_type=0, description="3", created_at=now) + b.execute() + + # updating in a batch + + b = BatchQuery() + em1.description = "new description" + em1.batch(b).save() + em2.description = "another new description" + em2.batch(b).save() + b.execute() + + # deleting in a batch + b = BatchQuery() + ExampleModel.objects(id=some_id).batch(b).delete() + ExampleModel.objects(id=some_id2).batch(b).delete() + b.execute() + + +Typically you will not want the block to execute if an exception occurs inside the `with` block. However, in the case that this is desirable, it's achievable by using the following syntax: + +.. code-block:: python + + with BatchQuery(execute_on_exception=True) as b: + LogEntry.batch(b).create(k=1, v=1) + mystery_function() # exception thrown in here + LogEntry.batch(b).create(k=1, v=2) # this code is never reached due to the exception, but anything leading up to here will execute in the batch. + +If an exception is thrown somewhere in the block, any statements that have been added to the batch will still be executed. This is useful for some logging situations. + +Batch Query Execution Callbacks +=============================== + +In order to allow secondary tasks to be chained to the end of batch, BatchQuery instances allow callbacks to be +registered with the batch, to be executed immediately after the batch executes. + +Multiple callbacks can be attached to same BatchQuery instance, they are executed in the same order that they +are added to the batch. + +The callbacks attached to a given batch instance are executed only if the batch executes. If the batch is used as a +context manager and an exception is raised, the queued up callbacks will not be run. + +.. code-block:: python + + def my_callback(*args, **kwargs): + pass + + batch = BatchQuery() + + batch.add_callback(my_callback) + batch.add_callback(my_callback, 'positional arg', named_arg='named arg value') + + # if you need reference to the batch within the callback, + # just trap it in the arguments to be passed to the callback: + batch.add_callback(my_callback, cqlengine_batch=batch) + + # once the batch executes... + batch.execute() + + # the effect of the above scheduled callbacks will be similar to + my_callback() + my_callback('positional arg', named_arg='named arg value') + my_callback(cqlengine_batch=batch) + +Failure in any of the callbacks does not affect the batch's execution, as the callbacks are started after the execution +of the batch is complete. + +Logged vs Unlogged Batches +--------------------------- +By default, queries in cqlengine are LOGGED, which carries additional overhead from UNLOGGED. To explicitly state which batch type to use, simply: + + +.. code-block:: python + + from cassandra.cqlengine.query import BatchType + with BatchQuery(batch_type=BatchType.Unlogged) as b: + LogEntry.batch(b).create(k=1, v=1) + LogEntry.batch(b).create(k=1, v=2) diff --git a/3.25.4-scylla/_sources/cqlengine/connections.rst.txt b/3.25.4-scylla/_sources/cqlengine/connections.rst.txt new file mode 100644 index 0000000000..03ade27521 --- /dev/null +++ b/3.25.4-scylla/_sources/cqlengine/connections.rst.txt @@ -0,0 +1,137 @@ +=========== +Connections +=========== + +Connections aim to ease the use of multiple sessions with cqlengine. Connections can be set on a model class, per query or using a context manager. + + +Register a new connection +========================= + +To use cqlengine, you need at least a default connection. If you initialize cqlengine's connections with with :func:`connection.setup <.connection.setup>`, a connection will be created automatically. If you want to use another cluster/session, you need to register a new cqlengine connection. You register a connection with :func:`~.connection.register_connection`: + +.. code-block:: python + + from cassandra.cqlengine import connection + + connection.setup(['127.0.0.1') + connection.register_connection('cluster2', ['127.0.0.2']) + +:func:`~.connection.register_connection` can take a list of hosts, as shown above, in which case it will create a connection with a new session. It can also take a `session` argument if you've already created a session: + +.. code-block:: python + + from cassandra.cqlengine import connection + from cassandra.cluster import Cluster + + session = Cluster(['127.0.0.1']).connect() + connection.register_connection('cluster3', session=session) + + +Change the default connection +============================= + +You can change the default cqlengine connection on registration: + +.. code-block:: python + + from cassandra.cqlengine import connection + + connection.register_connection('cluster2', ['127.0.0.2'] default=True) + +or on the fly using :func:`~.connection.set_default_connection` + +.. code-block:: python + + connection.set_default_connection('cluster2') + +Unregister a connection +======================= + +You can unregister a connection using :func:`~.connection.unregister_connection`: + +.. code-block:: python + + connection.unregister_connection('cluster2') + +Management +========== + +When using multiples connections, you also need to sync your models on all connections (and keyspaces) that you need operate on. Management commands have been improved to ease this part. Here is an example: + +.. code-block:: python + + from cassandra.cqlengine import management + + keyspaces = ['ks1', 'ks2'] + conns = ['cluster1', 'cluster2'] + + # registers your connections + # ... + + # create all keyspaces on all connections + for ks in keyspaces: + management.create_simple_keyspace(ks, connections=conns) + + # define your Automobile model + # ... + + # sync your models + management.sync_table(Automobile, keyspaces=keyspaces, connections=conns) + + +Connection Selection +==================== + +cqlengine will select the default connection, unless your specify a connection using one of the following methods. + +Default Model Connection +------------------------ + +You can specify a default connection per model: + +.. code-block:: python + + class Automobile(Model): + __keyspace__ = 'test' + __connection__ = 'cluster2' + manufacturer = columns.Text(primary_key=True) + year = columns.Integer(primary_key=True) + model = columns.Text(primary_key=True) + + print len(Automobile.objects.all()) # executed on the connection 'cluster2' + +QuerySet and model instance +--------------------------- + +You can use the :attr:`using() <.query.ModelQuerySet.using>` method to select a connection (or keyspace): + +.. code-block:: python + + Automobile.objects.using(connection='cluster1').create(manufacturer='honda', year=2010, model='civic') + q = Automobile.objects.filter(manufacturer='Tesla') + autos = q.using(keyspace='ks2', connection='cluster2').all() + + for auto in autos: + auto.using(connection='cluster1').save() + +Context Manager +--------------- + +You can use the ContextQuery as well to select a connection: + +.. code-block:: python + + with ContextQuery(Automobile, connection='cluster1') as A: + A.objects.filter(manufacturer='honda').all() # executed on 'cluster1' + + +BatchQuery +---------- + +With a BatchQuery, you can select the connection with the context manager. Note that all operations in the batch need to use the same connection. + +.. code-block:: python + + with BatchQuery(connection='cluster1') as b: + Automobile.objects.batch(b).create(manufacturer='honda', year=2010, model='civic') diff --git a/3.25.4-scylla/_sources/cqlengine/faq.rst.txt b/3.25.4-scylla/_sources/cqlengine/faq.rst.txt new file mode 100644 index 0000000000..6c056d02ea --- /dev/null +++ b/3.25.4-scylla/_sources/cqlengine/faq.rst.txt @@ -0,0 +1,67 @@ +========================== +Frequently Asked Questions +========================== + +Why don't updates work correctly on models instantiated as Model(field=value, field2=value2)? +------------------------------------------------------------------------------------------------ + +The recommended way to create new rows is with the models .create method. The values passed into a model's init method are interpreted by the model as the values as they were read from a row. This allows the model to "know" which rows have changed since the row was read out of cassandra, and create suitable update statements. + +How to preserve ordering in batch query? +------------------------------------------- + +Statement Ordering is not supported by CQL3 batches. Therefore, +once cassandra needs resolving conflict(Updating the same column in one batch), +The algorithm below would be used. + +* If timestamps are different, pick the column with the largest timestamp (the value being a regular column or a tombstone) +* If timestamps are the same, and one of the columns in a tombstone ('null') - pick the tombstone +* If timestamps are the same, and none of the columns are tombstones, pick the column with the largest value + +Below is an example to show this scenario. + +.. code-block:: python + + class MyMode(Model): + id = columns.Integer(primary_key=True) + count = columns.Integer() + text = columns.Text() + + with BatchQuery() as b: + MyModel.batch(b).create(id=1, count=2, text='123') + MyModel.batch(b).create(id=1, count=3, text='111') + + assert MyModel.objects(id=1).first().count == 3 + assert MyModel.objects(id=1).first().text == '123' + +The largest value of count is 3, and the largest value of text would be '123'. + +The workaround is applying timestamp to each statement, then Cassandra would +resolve to the statement with the lastest timestamp. + +.. code-block:: python + + with BatchQuery() as b: + MyModel.timestamp(datetime.now()).batch(b).create(id=1, count=2, text='123') + MyModel.timestamp(datetime.now()).batch(b).create(id=1, count=3, text='111') + + assert MyModel.objects(id=1).first().count == 3 + assert MyModel.objects(id=1).first().text == '111' + +How can I delete individual values from a row? +------------------------------------------------- + +When inserting with CQLEngine, ``None`` is equivalent to CQL ``NULL`` or to +issuing a ``DELETE`` on that column. For example: + +.. code-block:: python + + class MyModel(Model): + id = columns.Integer(primary_key=True) + text = columns.Text() + + m = MyModel.create(id=1, text='We can delete this with None') + assert MyModel.objects(id=1).first().text is not None + + m.update(text=None) + assert MyModel.objects(id=1).first().text is None diff --git a/3.25.4-scylla/_sources/cqlengine/models.rst.txt b/3.25.4-scylla/_sources/cqlengine/models.rst.txt new file mode 100644 index 0000000000..c0ba390119 --- /dev/null +++ b/3.25.4-scylla/_sources/cqlengine/models.rst.txt @@ -0,0 +1,218 @@ +====== +Models +====== + +.. module:: cqlengine.models + +A model is a python class representing a CQL table. Models derive from :class:`Model`, and +define basic table properties and columns for a table. + +Columns in your models map to columns in your CQL table. You define CQL columns by defining column attributes on your model classes. +For a model to be valid it needs at least one primary key column and one non-primary key column. Just as in CQL, the order you define +your columns in is important, and is the same order they are defined in on a model's corresponding table. + +Some basic examples defining models are shown below. Consult the :doc:`Model API docs ` and :doc:`Column API docs ` for complete details. + +Example Definitions +=================== + +This example defines a ``Person`` table, with the columns ``first_name`` and ``last_name`` + +.. code-block:: python + + from cassandra.cqlengine import columns + from cassandra.cqlengine.models import Model + + class Person(Model): + id = columns.UUID(primary_key=True) + first_name = columns.Text() + last_name = columns.Text() + + +The Person model would create this CQL table: + +.. code-block:: sql + + CREATE TABLE cqlengine.person ( + id uuid, + first_name text, + last_name text, + PRIMARY KEY (id) + ); + +Here's an example of a comment table created with clustering keys, in descending order: + +.. code-block:: python + + from cassandra.cqlengine import columns + from cassandra.cqlengine.models import Model + + class Comment(Model): + photo_id = columns.UUID(primary_key=True) + comment_id = columns.TimeUUID(primary_key=True, clustering_order="DESC") + comment = columns.Text() + +The Comment model's ``create table`` would look like the following: + +.. code-block:: sql + + CREATE TABLE comment ( + photo_id uuid, + comment_id timeuuid, + comment text, + PRIMARY KEY (photo_id, comment_id) + ) WITH CLUSTERING ORDER BY (comment_id DESC); + +To sync the models to the database, you may do the following*: + +.. code-block:: python + + from cassandra.cqlengine.management import sync_table + sync_table(Person) + sync_table(Comment) + +\*Note: synchronizing models causes schema changes, and should be done with caution. +Please see the discussion in :doc:`/api/cassandra/cqlengine/management` for considerations. + +For examples on manipulating data and creating queries, see :doc:`queryset` + +Manipulating model instances as dictionaries +============================================ + +Model instances can be accessed like dictionaries. + +.. code-block:: python + + class Person(Model): + first_name = columns.Text() + last_name = columns.Text() + + kevin = Person.create(first_name="Kevin", last_name="Deldycke") + dict(kevin) # returns {'first_name': 'Kevin', 'last_name': 'Deldycke'} + kevin['first_name'] # returns 'Kevin' + kevin.keys() # returns ['first_name', 'last_name'] + kevin.values() # returns ['Kevin', 'Deldycke'] + kevin.items() # returns [('first_name', 'Kevin'), ('last_name', 'Deldycke')] + + kevin['first_name'] = 'KEVIN5000' # changes the models first name + +Extending Model Validation +========================== + +Each time you save a model instance in cqlengine, the data in the model is validated against the schema you've defined +for your model. Most of the validation is fairly straightforward, it basically checks that you're not trying to do +something like save text into an integer column, and it enforces the ``required`` flag set on column definitions. +It also performs any transformations needed to save the data properly. + +However, there are often additional constraints or transformations you want to impose on your data, beyond simply +making sure that Cassandra won't complain when you try to insert it. To define additional validation on a model, +extend the model's validation method: + +.. code-block:: python + + class Member(Model): + person_id = UUID(primary_key=True) + name = Text(required=True) + + def validate(self): + super(Member, self).validate() + if self.name == 'jon': + raise ValidationError('no jon\'s allowed') + +*Note*: while not required, the convention is to raise a ``ValidationError`` (``from cassandra.cqlengine import ValidationError``) +if validation fails. + +.. _model_inheritance: + +Model Inheritance +================= +It is possible to save and load different model classes using a single CQL table. +This is useful in situations where you have different object types that you want to store in a single cassandra row. + +For instance, suppose you want a table that stores rows of pets owned by an owner: + +.. code-block:: python + + class Pet(Model): + __table_name__ = 'pet' + owner_id = UUID(primary_key=True) + pet_id = UUID(primary_key=True) + pet_type = Text(discriminator_column=True) + name = Text() + + def eat(self, food): + pass + + def sleep(self, time): + pass + + class Cat(Pet): + __discriminator_value__ = 'cat' + cuteness = Float() + + def tear_up_couch(self): + pass + + class Dog(Pet): + __discriminator_value__ = 'dog' + fierceness = Float() + + def bark_all_night(self): + pass + +After calling ``sync_table`` on each of these tables, the columns defined in each model will be added to the +``pet`` table. Additionally, saving ``Cat`` and ``Dog`` models will save the meta data needed to identify each row +as either a cat or dog. + +To setup a model structure with inheritance, follow these steps + +1. Create a base model with a column set as the distriminator (``distriminator_column=True`` in the column definition) +2. Create subclass models, and define a unique ``__discriminator_value__`` value on each +3. Run ``sync_table`` on each of the sub tables + +**About the discriminator value** + +The discriminator value is what cqlengine uses under the covers to map logical cql rows to the appropriate model type. The +base model maintains a map of discriminator values to subclasses. When a specialized model is saved, its discriminator value is +automatically saved into the discriminator column. The discriminator column may be any column type except counter and container types. +Additionally, if you set ``index=True`` on your discriminator column, you can execute queries against specialized subclasses, and a +``WHERE`` clause will be automatically added to your query, returning only rows of that type. Note that you must +define a unique ``__discriminator_value__`` to each subclass, and that you can only assign a single discriminator column per model. + +.. _user_types: + +User Defined Types +================== +cqlengine models User Defined Types (UDTs) much like tables, with fields defined by column type attributes. However, UDT instances +are only created, presisted, and queried via table Models. A short example to introduce the pattern:: + + from cassandra.cqlengine.columns import * + from cassandra.cqlengine.models import Model + from cassandra.cqlengine.usertype import UserType + + class address(UserType): + street = Text() + zipcode = Integer() + + class users(Model): + __keyspace__ = 'account' + name = Text(primary_key=True) + addr = UserDefinedType(address) + + users.create(name="Joe", addr=address(street="Easy St.", zipcode=99999)) + user = users.objects(name="Joe")[0] + print user.name, user.addr + # Joe address(street=u'Easy St.', zipcode=99999) + +UDTs are modeled by inheriting :class:`~.usertype.UserType`, and setting column type attributes. Types are then used in defining +models by declaring a column of type :class:`~.columns.UserDefinedType`, with the ``UserType`` class as a parameter. + +``sync_table`` will implicitly +synchronize any types contained in the table. Alternatively :func:`~.management.sync_type` can be used to create/alter types +explicitly. + +Upon declaration, types are automatically registered with the driver, so query results return instances of your ``UserType`` +class*. + +***Note**: UDTs were not added to the native protocol until v3. When setting up the cqlengine connection, be sure to specify +``protocol_version=3``. If using an earlier version, UDT queries will still work, but the returned type will be a namedtuple. diff --git a/3.25.4-scylla/_sources/cqlengine/queryset.rst.txt b/3.25.4-scylla/_sources/cqlengine/queryset.rst.txt new file mode 100644 index 0000000000..375ea22316 --- /dev/null +++ b/3.25.4-scylla/_sources/cqlengine/queryset.rst.txt @@ -0,0 +1,419 @@ +============== +Making Queries +============== + +.. module:: cqlengine.queryset + +Retrieving objects +================== +Once you've populated Cassandra with data, you'll probably want to retrieve some of it. This is accomplished with QuerySet objects. This section will describe how to use QuerySet objects to retrieve the data you're looking for. + +Retrieving all objects +---------------------- +The simplest query you can make is to return all objects from a table. + +This is accomplished with the ``.all()`` method, which returns a QuerySet of all objects in a table + +Using the Person example model, we would get all Person objects like this: + +.. code-block:: python + + all_objects = Person.objects.all() + +.. _retrieving-objects-with-filters: + +Retrieving objects with filters +------------------------------- +Typically, you'll want to query only a subset of the records in your database. + +That can be accomplished with the QuerySet's ``.filter(\*\*)`` method. + +For example, given the model definition: + +.. code-block:: python + + class Automobile(Model): + manufacturer = columns.Text(primary_key=True) + year = columns.Integer(primary_key=True) + model = columns.Text() + price = columns.Decimal() + options = columns.Set(columns.Text) + +...and assuming the Automobile table contains a record of every car model manufactured in the last 20 years or so, we can retrieve only the cars made by a single manufacturer like this: + + +.. code-block:: python + + q = Automobile.objects.filter(manufacturer='Tesla') + +You can also use the more convenient syntax: + +.. code-block:: python + + q = Automobile.objects(Automobile.manufacturer == 'Tesla') + +We can then further filter our query with another call to **.filter** + +.. code-block:: python + + q = q.filter(year=2012) + +*Note: all queries involving any filtering MUST define either an '=' or an 'in' relation to either a primary key column, or an indexed column.* + +Accessing objects in a QuerySet +=============================== + +There are several methods for getting objects out of a queryset + +* iterating over the queryset + .. code-block:: python + + for car in Automobile.objects.all(): + #...do something to the car instance + pass + +* list index + .. code-block:: python + + q = Automobile.objects.all() + q[0] #returns the first result + q[1] #returns the second result + + .. note:: + + * CQL does not support specifying a start position in it's queries. Therefore, accessing elements using array indexing will load every result up to the index value requested + * Using negative indices requires a "SELECT COUNT()" to be executed. This has a performance cost on large datasets. + +* list slicing + .. code-block:: python + + q = Automobile.objects.all() + q[1:] #returns all results except the first + q[1:9] #returns a slice of the results + + .. note:: + + * CQL does not support specifying a start position in it's queries. Therefore, accessing elements using array slicing will load every result up to the index value requested + * Using negative indices requires a "SELECT COUNT()" to be executed. This has a performance cost on large datasets. + +* calling :attr:`get() ` on the queryset + .. code-block:: python + + q = Automobile.objects.filter(manufacturer='Tesla') + q = q.filter(year=2012) + car = q.get() + + this returns the object matching the queryset + +* calling :attr:`first() ` on the queryset + .. code-block:: python + + q = Automobile.objects.filter(manufacturer='Tesla') + q = q.filter(year=2012) + car = q.first() + + this returns the first value in the queryset + +.. _query-filtering-operators: + +Filtering Operators +=================== + +:attr:`Equal To ` + +The default filtering operator. + +.. code-block:: python + + q = Automobile.objects.filter(manufacturer='Tesla') + q = q.filter(year=2012) #year == 2012 + +In addition to simple equal to queries, cqlengine also supports querying with other operators by appending a ``__`` to the field name on the filtering call + +:attr:`in (__in) ` + +.. code-block:: python + + q = Automobile.objects.filter(manufacturer='Tesla') + q = q.filter(year__in=[2011, 2012]) + + +:attr:`> (__gt) ` + +.. code-block:: python + + q = Automobile.objects.filter(manufacturer='Tesla') + q = q.filter(year__gt=2010) # year > 2010 + + # or the nicer syntax + + q.filter(Automobile.year > 2010) + +:attr:`>= (__gte) ` + +.. code-block:: python + + q = Automobile.objects.filter(manufacturer='Tesla') + q = q.filter(year__gte=2010) # year >= 2010 + + # or the nicer syntax + + q.filter(Automobile.year >= 2010) + +:attr:`< (__lt) ` + +.. code-block:: python + + q = Automobile.objects.filter(manufacturer='Tesla') + q = q.filter(year__lt=2012) # year < 2012 + + # or... + + q.filter(Automobile.year < 2012) + +:attr:`<= (__lte) ` + +.. code-block:: python + + q = Automobile.objects.filter(manufacturer='Tesla') + q = q.filter(year__lte=2012) # year <= 2012 + + q.filter(Automobile.year <= 2012) + +:attr:`CONTAINS (__contains) ` + +The CONTAINS operator is available for all collection types (List, Set, Map). + +.. code-block:: python + + q = Automobile.objects.filter(manufacturer='Tesla') + q.filter(options__contains='backup camera').allow_filtering() + +Note that we need to use allow_filtering() since the *options* column has no secondary index. + +:attr:`LIKE (__like) ` + +The LIKE operator is available for text columns that have a SASI secondary index. + +.. code-block:: python + + q = Automobile.objects.filter(model__like='%Civic%').allow_filtering() + +:attr:`IS NOT NULL (IsNotNull(column_name)) ` + +The IS NOT NULL operator is not yet supported for C*. + +.. code-block:: python + + q = Automobile.objects.filter(IsNotNull('model')) + +Limitations: + +- Currently, cqlengine does not support SASI index creation. To use this feature, you need to create the SASI index using the core driver. +- Queries using LIKE must use allow_filtering() since the *model* column has no standard secondary index. Note that the server will use the SASI index properly when executing the query. + +TimeUUID Functions +================== + +In addition to querying using regular values, there are two functions you can pass in when querying TimeUUID columns to help make filtering by them easier. Note that these functions don't actually return a value, but instruct the cql interpreter to use the functions in it's query. + +.. class:: MinTimeUUID(datetime) + + returns the minimum time uuid value possible for the given datetime + +.. class:: MaxTimeUUID(datetime) + + returns the maximum time uuid value possible for the given datetime + +*Example* + +.. code-block:: python + + class DataStream(Model): + id = columns.UUID(partition_key=True) + time = columns.TimeUUID(primary_key=True) + data = columns.Bytes() + + min_time = datetime(1982, 1, 1) + max_time = datetime(1982, 3, 9) + + DataStream.filter(time__gt=functions.MinTimeUUID(min_time), time__lt=functions.MaxTimeUUID(max_time)) + +Token Function +============== + +Token functon may be used only on special, virtual column pk__token, representing token of partition key (it also works for composite partition keys). +Cassandra orders returned items by value of partition key token, so using cqlengine.Token we can easy paginate through all table rows. + +See http://cassandra.apache.org/doc/cql3/CQL-3.0.html#tokenFun + +*Example* + +.. code-block:: python + + class Items(Model): + id = columns.Text(primary_key=True) + data = columns.Bytes() + + query = Items.objects.all().limit(10) + + first_page = list(query); + last = first_page[-1] + next_page = list(query.filter(pk__token__gt=cqlengine.Token(last.pk))) + +QuerySets are immutable +======================= + +When calling any method that changes a queryset, the method does not actually change the queryset object it's called on, but returns a new queryset object with the attributes of the original queryset, plus the attributes added in the method call. + +*Example* + +.. code-block:: python + + #this produces 3 different querysets + #q does not change after it's initial definition + q = Automobiles.objects.filter(year=2012) + tesla2012 = q.filter(manufacturer='Tesla') + honda2012 = q.filter(manufacturer='Honda') + +Ordering QuerySets +================== + +Since Cassandra is essentially a distributed hash table on steroids, the order you get records back in will not be particularly predictable. + +However, you can set a column to order on with the ``.order_by(column_name)`` method. + +*Example* + +.. code-block:: python + + #sort ascending + q = Automobiles.objects.all().order_by('year') + #sort descending + q = Automobiles.objects.all().order_by('-year') + +*Note: Cassandra only supports ordering on a clustering key. In other words, to support ordering results, your model must have more than one primary key, and you must order on a primary key, excluding the first one.* + +*For instance, given our Automobile model, year is the only column we can order on.* + +Values Lists +============ + +There is a special QuerySet's method ``.values_list()`` - when called, QuerySet returns lists of values instead of model instances. It may significantly speedup things with lower memory footprint for large responses. +Each tuple contains the value from the respective field passed into the ``values_list()`` call — so the first item is the first field, etc. For example: + +.. code-block:: python + + items = list(range(20)) + random.shuffle(items) + for i in items: + TestModel.create(id=1, clustering_key=i) + + values = list(TestModel.objects.values_list('clustering_key', flat=True)) + # [19L, 18L, 17L, 16L, 15L, 14L, 13L, 12L, 11L, 10L, 9L, 8L, 7L, 6L, 5L, 4L, 3L, 2L, 1L, 0L] + +Per Query Timeouts +=================== + +By default all queries are executed with the timeout defined in `~cqlengine.connection.setup()` +The examples below show how to specify a per-query timeout. +A timeout is specified in seconds and can be an int, float or None. +None means no timeout. + + +.. code-block:: python + + class Row(Model): + id = columns.Integer(primary_key=True) + name = columns.Text() + + +Fetch all objects with a timeout of 5 seconds + +.. code-block:: python + + Row.objects().timeout(5).all() + +Create a single row with a 50ms timeout + +.. code-block:: python + + Row(id=1, name='Jon').timeout(0.05).create() + +Delete a single row with no timeout + +.. code-block:: python + + Row(id=1).timeout(None).delete() + +Update a single row with no timeout + +.. code-block:: python + + Row(id=1).timeout(None).update(name='Blake') + +Batch query timeouts + +.. code-block:: python + + with BatchQuery(timeout=10) as b: + Row(id=1, name='Jon').create() + + +NOTE: You cannot set both timeout and batch at the same time, batch will use the timeout defined in it's constructor. +Setting the timeout on the model is meaningless and will raise an AssertionError. + + +.. _ttl-change: + +Default TTL and Per Query TTL +============================= + +Model default TTL now relies on the *default_time_to_live* feature, introduced in Cassandra 2.0. It is not handled anymore in the CQLEngine Model (scylla-driver >=3.6). You can set the default TTL of a table like this: + +Example: + +.. code-block:: python + + class User(Model): + __options__ = {'default_time_to_live': 20} + + user_id = columns.UUID(primary_key=True) + ... + +You can set TTL per-query if needed. Here are a some examples: + +Example: + +.. code-block:: python + + class User(Model): + __options__ = {'default_time_to_live': 20} + + user_id = columns.UUID(primary_key=True) + ... + + user = User.objects.create(user_id=1) # Default TTL 20 will be set automatically on the server + + user.ttl(30).update(age=21) # Update the TTL to 30 + User.objects.ttl(10).create(user_id=1) # TTL 10 + User(user_id=1, age=21).ttl(10).save() # TTL 10 + + +Named Tables +=================== + +Named tables are a way of querying a table without creating an class. They're useful for querying system tables or exploring an unfamiliar database. + + +.. code-block:: python + + from cassandra.cqlengine.connection import setup + setup("127.0.0.1", "cqlengine_test") + + from cassandra.cqlengine.named import NamedTable + user = NamedTable("cqlengine_test", "user") + user.objects() + user.objects()[0] + + # {u'pk': 1, u't': datetime.datetime(2014, 6, 26, 17, 10, 31, 774000)} diff --git a/3.25.4-scylla/_sources/cqlengine/third_party.rst.txt b/3.25.4-scylla/_sources/cqlengine/third_party.rst.txt new file mode 100644 index 0000000000..20c26df304 --- /dev/null +++ b/3.25.4-scylla/_sources/cqlengine/third_party.rst.txt @@ -0,0 +1,64 @@ +======================== +Third party integrations +======================== + + +Celery +------ + +Here's how, in substance, CQLengine can be plugged to `Celery +`_: + +.. code-block:: python + + from celery import Celery + from celery.signals import worker_process_init, beat_init + from cassandra.cqlengine import connection + from cassandra.cqlengine.connection import ( + cluster as cql_cluster, session as cql_session) + + def cassandra_init(**kwargs): + """ Initialize a clean Cassandra connection. """ + if cql_cluster is not None: + cql_cluster.shutdown() + if cql_session is not None: + cql_session.shutdown() + connection.setup() + + # Initialize worker context for both standard and periodic tasks. + worker_process_init.connect(cassandra_init) + beat_init.connect(cassandra_init) + + app = Celery() + + +uWSGI +----- + +This is the code required for proper connection handling of CQLengine for a +`uWSGI `_-run application: + +.. code-block:: python + + from cassandra.cqlengine import connection + from cassandra.cqlengine.connection import ( + cluster as cql_cluster, session as cql_session) + + try: + from uwsgidecorators import postfork + except ImportError: + # We're not in a uWSGI context, no need to hook Cassandra session + # initialization to the postfork event. + pass + else: + @postfork + def cassandra_init(**kwargs): + """ Initialize a new Cassandra session in the context. + + Ensures that a new session is returned for every new request. + """ + if cql_cluster is not None: + cql_cluster.shutdown() + if cql_session is not None: + cql_session.shutdown() + connection.setup() diff --git a/3.25.4-scylla/_sources/cqlengine/upgrade_guide.rst.txt b/3.25.4-scylla/_sources/cqlengine/upgrade_guide.rst.txt new file mode 100644 index 0000000000..5a10ebb757 --- /dev/null +++ b/3.25.4-scylla/_sources/cqlengine/upgrade_guide.rst.txt @@ -0,0 +1,155 @@ +======================== +Upgrade Guide +======================== + +This is an overview of things that changed as the cqlengine project was merged into +scylla-driver. While efforts were taken to preserve the API and most functionality exactly, +conversion to this package will still require certain minimal updates (namely, imports). + +**THERE IS ONE FUNCTIONAL CHANGE**, described in the first section below. + +Functional Changes +================== +List Prepend Reversing +---------------------- +Legacy cqlengine included a workaround for a Cassandra bug in which prepended list segments were +reversed (`CASSANDRA-8733 `_). As of +this integration, this workaround is removed. The first released integrated version emits +a warning when prepend is used. Subsequent versions will have this warning removed. + +Date Column Type +---------------- +The Date column type in legacy cqlengine used a ``timestamp`` CQL type and truncated the time. +Going forward, the :class:`~.columns.Date` type represents a ``date`` for Cassandra 2.2+ +(`PYTHON-245 `_). +Users of the legacy functionality should convert models to use :class:`~.columns.DateTime` (which +uses ``timestamp`` internally), and use the build-in ``datetime.date`` for input values. + +Remove cqlengine +================ +To avoid confusion or mistakes using the legacy package in your application, it +is prudent to remove the cqlengine package when upgrading to the integrated version. + +The driver setup script will warn if the legacy package is detected during install, +but it will not prevent side-by-side installation. + +Organization +============ +Imports +------- +cqlengine is now integrated as a sub-package of the driver base package 'cassandra'. +Upgrading will require adjusting imports to cqlengine. For example:: + + from cassandra.cqlengine import columns + +is now:: + + from cassandra.cqlengine import columns + +Package-Level Aliases +--------------------- +Legacy cqlengine defined a number of aliases at the package level, which became redundant +when the package was integrated for a driver. These have been removed in favor of absolute +imports, and referring to cannonical definitions. For example, ``cqlengine.ONE`` was an alias +of ``cassandra.ConsistencyLevel.ONE``. In the integrated package, only the +:class:`cassandra.ConsistencyLevel` remains. + +Additionally, submodule aliases are removed from cqlengine in favor of absolute imports. + +These aliases are removed, and not deprecated because they should be straightforward to iron out +at module load time. + +Exceptions +---------- +The legacy cqlengine.exceptions module had a number of Exception classes that were variously +common to the package, or only used in specific modules. Common exceptions were relocated to +cqlengine, and specialized exceptions were placed in the module that raises them. Below is a +listing of updated locations: + +============================ ========== +Exception class New module +============================ ========== +CQLEngineException cassandra.cqlengine +ModelException cassandra.cqlengine.models +ValidationError cassandra.cqlengine +UndefinedKeyspaceException cassandra.cqlengine.connection +LWTException cassandra.cqlengine.query +IfNotExistsWithCounterColumn cassandra.cqlengine.query +============================ ========== + +UnicodeMixin Consolidation +-------------------------- +``class UnicodeMixin`` was defined in several cqlengine modules. This has been consolidated +to a single definition in the cqlengine package init file. This is not technically part of +the API, but noted here for completeness. + +API Deprecations +================ +This upgrade served as a good juncture to deprecate certain API features and invite users to upgrade +to new ones. The first released version does not change functionality -- only introduces deprecation +warnings. Future releases will remove these features in favor of the alternatives. + +Float/Double Overload +--------------------- +Previously there was no ``Double`` column type. Doubles were modeled by specifying ``Float(double_precision=True)``. +This inititializer parameter is now deprecated. Applications should use :class:`~.columns.Double` for CQL ``double``, and :class:`~.columns.Float` +for CQL ``float``. + +Schema Management +----------------- +``cassandra.cqlengine.management.create_keyspace`` is deprecated. Instead, use the new replication-strategy-specific +functions that accept explicit options for known strategies: + +- :func:`~.create_keyspace_simple` +- :func:`~.create_keyspace_network_topology` + +``cassandra.cqlengine.management.delete_keyspace`` is deprecated in favor of a new function, :func:`~.drop_keyspace`. The +intent is simply to make the function match the CQL verb it invokes. + +Model Inheritance +----------------- +The names for class attributes controlling model inheritance are changing. Changes are as follows: + +- Replace 'polymorphic_key' in the base class Column definition with :attr:`~.discriminator_column` +- Replace the '__polymorphic_key__' class attribute the derived classes with :attr:`~.__discriminator_value__` + +The functionality is unchanged -- the intent here is to make the names and language around these attributes more precise. +For now, the old names are just deprecated, and the mapper will emit warnings if they are used. The old names +will be removed in a future version. + +The example below shows a simple translation: + +Before:: + + class Pet(Model): + __table_name__ = 'pet' + owner_id = UUID(primary_key=True) + pet_id = UUID(primary_key=True) + pet_type = Text(polymorphic_key=True) + name = Text() + + class Cat(Pet): + __polymorphic_key__ = 'cat' + + class Dog(Pet): + __polymorphic_key__ = 'dog' + +After:: + + class Pet(models.Model): + __table_name__ = 'pet' + owner_id = UUID(primary_key=True) + pet_id = UUID(primary_key=True) + pet_type = Text(discriminator_column=True) + name = Text() + + class Cat(Pet): + __discriminator_value__ = 'cat' + + class Dog(Pet): + __discriminator_value__ = 'dog' + + +TimeUUID.from_datetime +---------------------- +This function is deprecated in favor of the core utility function :func:`~.uuid_from_time`. diff --git a/3.25.4-scylla/_sources/dates_and_times.rst.txt b/3.25.4-scylla/_sources/dates_and_times.rst.txt new file mode 100644 index 0000000000..7a89f77437 --- /dev/null +++ b/3.25.4-scylla/_sources/dates_and_times.rst.txt @@ -0,0 +1,87 @@ +Working with Dates and Times +============================ + +This document is meant to provide on overview of the assumptions and limitations of the driver time handling, the +reasoning behind it, and describe approaches to working with these types. + +timestamps (Cassandra DateType) +------------------------------- + +Timestamps in Cassandra are timezone-naive timestamps encoded as millseconds since UNIX epoch. Clients working with +timestamps in this database usually find it easiest to reason about them if they are always assumed to be UTC. To quote the +pytz documentation, "The preferred way of dealing with times is to always work in UTC, converting to localtime only when +generating output to be read by humans." The driver adheres to this tenant, and assumes UTC is always in the database. The +driver attempts to make this correct on the way in, and assumes no timezone on the way out. + +Write Path +~~~~~~~~~~ +When inserting timestamps, the driver handles serialization for the write path as follows: + +If the input is a ``datetime.datetime``, the serialization is normalized by starting with the ``utctimetuple()`` of the +value. + +- If the ``datetime`` object is timezone-aware, the timestamp is shifted, and represents the UTC timestamp equivalent. +- If the ``datetime`` object is timezone-naive, this results in no shift -- any ``datetime`` with no timezone information is assumed to be UTC + +Note the second point above applies even to "local" times created using ``now()``:: + + >>> d = datetime.now() + + >>> print(d.tzinfo) + None + + +These do not contain timezone information intrinsically, so they will be assumed to be UTC and not shifted. When generating +timestamps in the application, it is clearer to use ``datetime.utcnow()`` to be explicit about it. + +If the input for a timestamp is numeric, it is assumed to be a epoch-relative millisecond timestamp, as specified in the +CQL spec -- no scaling or conversion is done. + +Read Path +~~~~~~~~~ +The driver always assumes persisted timestamps are UTC and makes no attempt to localize them. Returned values are +timezone-naive ``datetime.datetime``. We follow this approach because the datetime API has deficiencies around daylight +saving time, and the defacto package for handling this is a third-party package (we try to minimize external dependencies +and not make decisions for the integrator). + +The decision for how to handle timezones is left to the application. For the most part it is straightforward to apply +localization to the ``datetime``\s returned by queries. One prevalent method is to use pytz for localization:: + + import pytz + user_tz = pytz.timezone('US/Central') + timestamp_naive = row.ts + timestamp_utc = pytz.utc.localize(timestamp_naive) + timestamp_presented = timestamp_utc.astimezone(user_tz) + +This is the most robust approach (likely refactored into a function). If it is deemed too cumbersome to apply for all call +sites in the application, it is possible to patch the driver with custom deserialization for this type. However, doing +this depends depends some on internal APIs and what extensions are present, so we will only mention the possibility, and +not spell it out here. + +date, time (Cassandra DateType) +------------------------------- +Date and time in Cassandra are idealized markers, much like ``datetime.date`` and ``datetime.time`` in the Python standard +library. Unlike these Python implementations, the Cassandra encoding supports much wider ranges. To accommodate these +ranges without overflow, this driver returns these data in custom types: :class:`.util.Date` and :class:`.util.Time`. + +Write Path +~~~~~~~~~~ +For simple (not prepared) statements, the input values for each of these can be either a string literal or an encoded +integer. See `Working with dates `_ +or `Working with time `_ for details +on the encoding or string formats. + +For prepared statements, the driver accepts anything that can be used to construct the :class:`.util.Date` or +:class:`.util.Time` classes. See the linked API docs for details. + +Read Path +~~~~~~~~~ +The driver always returns custom types for ``date`` and ``time``. + +The driver returns :class:`.util.Date` for ``date`` in order to accommodate the wider range of values without overflow. +For applications working within the supported range of [``datetime.MINYEAR``, ``datetime.MAXYEAR``], these are easily +converted to standard ``datetime.date`` insances using :meth:`.Date.date`. + +The driver returns :class:`.util.Time` for ``time`` in order to retain nanosecond precision stored in the database. +For applications not concerned with this level of precision, these are easily converted to standard ``datetime.time`` +insances using :meth:`.Time.time`. diff --git a/3.25.4-scylla/_sources/execution_profiles.rst.txt b/3.25.4-scylla/_sources/execution_profiles.rst.txt new file mode 100644 index 0000000000..7be1a85e3f --- /dev/null +++ b/3.25.4-scylla/_sources/execution_profiles.rst.txt @@ -0,0 +1,156 @@ +Execution Profiles +================== + +Execution profiles aim at making it easier to execute requests in different ways within +a single connected ``Session``. Execution profiles are being introduced to deal with the exploding number of +configuration options, especially as the database platform evolves more complex workloads. + +The legacy configuration remains intact, but legacy and Execution Profile APIs +cannot be used simultaneously on the same client ``Cluster``. Legacy configuration +will be removed in the next major release (4.0). + +An execution profile and its parameters should be unique across ``Cluster`` instances. +For example, an execution profile and its ``LoadBalancingPolicy`` should +not be applied to more than one ``Cluster`` instance. + +This document explains how Execution Profiles relate to existing settings, and shows how to use the new profiles for +request execution. + +Mapping Legacy Parameters to Profiles +------------------------------------- + +Execution profiles can inherit from :class:`.cluster.ExecutionProfile`, and currently provide the following options, +previously input from the noted attributes: + +- load_balancing_policy - :attr:`.Cluster.load_balancing_policy` +- request_timeout - :attr:`.Session.default_timeout`, optional :meth:`.Session.execute` parameter +- retry_policy - :attr:`.Cluster.default_retry_policy`, optional :attr:`.Statement.retry_policy` attribute +- consistency_level - :attr:`.Session.default_consistency_level`, optional :attr:`.Statement.consistency_level` attribute +- serial_consistency_level - :attr:`.Session.default_serial_consistency_level`, optional :attr:`.Statement.serial_consistency_level` attribute +- row_factory - :attr:`.Session.row_factory` attribute + +When using the new API, these parameters can be defined by instances of :class:`.cluster.ExecutionProfile`. + +Using Execution Profiles +------------------------ +Default +~~~~~~~ + +.. code:: python + + from cassandra.cluster import Cluster + cluster = Cluster() + session = cluster.connect() + local_query = 'SELECT rpc_address FROM system.local' + for _ in cluster.metadata.all_hosts(): + print session.execute(local_query)[0] + + +.. parsed-literal:: + + Row(rpc_address='127.0.0.2') + Row(rpc_address='127.0.0.1') + + +The default execution profile is built from Cluster parameters and default Session attributes. This profile matches existing default +parameters. + +Initializing cluster with profiles +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. code:: python + + from cassandra.cluster import ExecutionProfile + from cassandra.policies import WhiteListRoundRobinPolicy + + node1_profile = ExecutionProfile(load_balancing_policy=WhiteListRoundRobinPolicy(['127.0.0.1'])) + node2_profile = ExecutionProfile(load_balancing_policy=WhiteListRoundRobinPolicy(['127.0.0.2'])) + + profiles = {'node1': node1_profile, 'node2': node2_profile} + session = Cluster(execution_profiles=profiles).connect() + for _ in cluster.metadata.all_hosts(): + print session.execute(local_query, execution_profile='node1')[0] + + +.. parsed-literal:: + + Row(rpc_address='127.0.0.1') + Row(rpc_address='127.0.0.1') + + +.. code:: python + + for _ in cluster.metadata.all_hosts(): + print session.execute(local_query, execution_profile='node2')[0] + + +.. parsed-literal:: + + Row(rpc_address='127.0.0.2') + Row(rpc_address='127.0.0.2') + + +.. code:: python + + for _ in cluster.metadata.all_hosts(): + print session.execute(local_query)[0] + + +.. parsed-literal:: + + Row(rpc_address='127.0.0.2') + Row(rpc_address='127.0.0.1') + +Note that, even when custom profiles are injected, the default ``TokenAwarePolicy(DCAwareRoundRobinPolicy())`` is still +present. To override the default, specify a policy with the :data:`~.cluster.EXEC_PROFILE_DEFAULT` key. + +.. code:: python + + from cassandra.cluster import EXEC_PROFILE_DEFAULT + profile = ExecutionProfile(request_timeout=30) + cluster = Cluster(execution_profiles={EXEC_PROFILE_DEFAULT: profile}) + + +Adding named profiles +~~~~~~~~~~~~~~~~~~~~~ + +New profiles can be added constructing from scratch, or deriving from default: + +.. code:: python + + locked_execution = ExecutionProfile(load_balancing_policy=WhiteListRoundRobinPolicy(['127.0.0.1'])) + node1_profile = 'node1_whitelist' + cluster.add_execution_profile(node1_profile, locked_execution) + + for _ in cluster.metadata.all_hosts(): + print session.execute(local_query, execution_profile=node1_profile)[0] + + +.. parsed-literal:: + + Row(rpc_address='127.0.0.1') + Row(rpc_address='127.0.0.1') + +See :meth:`.Cluster.add_execution_profile` for details and optional parameters. + +Passing a profile instance without mapping +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +We also have the ability to pass profile instances to be used for execution, but not added to the mapping: + +.. code:: python + + from cassandra.query import tuple_factory + + tmp = session.execution_profile_clone_update('node1', request_timeout=100, row_factory=tuple_factory) + + print session.execute(local_query, execution_profile=tmp)[0] + print session.execute(local_query, execution_profile='node1')[0] + +.. parsed-literal:: + + ('127.0.0.1',) + Row(rpc_address='127.0.0.1') + +The new profile is a shallow copy, so the ``tmp`` profile shares a load balancing policy with one managed by the cluster. +If reference objects are to be updated in the clone, one would typically set those attributes to a new instance. diff --git a/3.25.4-scylla/_sources/faq.rst.txt b/3.25.4-scylla/_sources/faq.rst.txt new file mode 100644 index 0000000000..56cb648a24 --- /dev/null +++ b/3.25.4-scylla/_sources/faq.rst.txt @@ -0,0 +1,83 @@ +Frequently Asked Questions +========================== + +See also :doc:`cqlengine FAQ ` + +Why do connections or IO operations timeout in my WSGI application? +------------------------------------------------------------------- +Depending on your application process model, it may be forking after driver Session is created. Most IO reactors do not handle this, and problems will manifest as timeouts. + +To avoid this, make sure to create sessions per process, after the fork. Using uWSGI and Flask for example: + +.. code-block:: python + + from flask import Flask + from uwsgidecorators import postfork + from cassandra.cluster import Cluster + + session = None + prepared = None + + @postfork + def connect(): + global session, prepared + session = Cluster().connect() + prepared = session.prepare("SELECT release_version FROM system.local WHERE key=?") + + app = Flask(__name__) + + @app.route('/') + def server_version(): + row = session.execute(prepared, ('local',))[0] + return row.release_version + +uWSGI provides a ``postfork`` hook you can use to create sessions and prepared statements after the child process forks. + +How do I trace a request? +------------------------- +Request tracing can be turned on for any request by setting ``trace=True`` in :meth:`.Session.execute_async`. View the results by waiting on the future, then :meth:`.ResponseFuture.get_query_trace`. +Since tracing is done asynchronously to the request, this method polls until the trace is complete before querying data. + +.. code-block:: python + + >>> future = session.execute_async("SELECT * FROM system.local", trace=True) + >>> result = future.result() + >>> trace = future.get_query_trace() + >>> for e in trace.events: + >>> print e.source_elapsed, e.description + + 0:00:00.000077 Parsing select * from system.local + 0:00:00.000153 Preparing statement + 0:00:00.000309 Computing ranges to query + 0:00:00.000368 Submitting range requests on 1 ranges with a concurrency of 1 (279.77142 rows per range expected) + 0:00:00.000422 Submitted 1 concurrent range requests covering 1 ranges + 0:00:00.000480 Executing seq scan across 1 sstables for (min(-9223372036854775808), min(-9223372036854775808)) + 0:00:00.000669 Read 1 live and 0 tombstone cells + 0:00:00.000755 Scanned 1 rows and matched 1 + +``trace`` is a :class:`QueryTrace` object. + +How do I determine the replicas for a query? +---------------------------------------------- +With prepared statements, the replicas are obtained by ``routing_key``, based on current cluster token metadata: + +.. code-block:: python + + >>> prepared = session.prepare("SELECT * FROM example.t WHERE key=?") + >>> bound = prepared.bind((1,)) + >>> replicas = cluster.metadata.get_replicas(bound.keyspace, bound.routing_key) + >>> for h in replicas: + >>> print h.address + 127.0.0.1 + 127.0.0.2 + +``replicas`` is a list of :class:`Host` objects. + +How does the driver manage request retries? +------------------------------------------- +By default, retries are managed by the :attr:`.Cluster.default_retry_policy` set on the session Cluster. It can also +be specialized per statement by setting :attr:`.Statement.retry_policy`. + +Retries are presently attempted on the same coordinator, but this may change in the future. + +Please see :class:`.policies.RetryPolicy` for further details. diff --git a/3.25.4-scylla/_sources/getting_started.rst.txt b/3.25.4-scylla/_sources/getting_started.rst.txt new file mode 100644 index 0000000000..59a2acbd04 --- /dev/null +++ b/3.25.4-scylla/_sources/getting_started.rst.txt @@ -0,0 +1,479 @@ +Getting Started +=============== + +First, make sure you have the driver properly :doc:`installed `. + +Connecting to a Cluster +----------------------- +Before we can start executing any queries against a Cassandra cluster we need to setup +an instance of :class:`~.Cluster`. As the name suggests, you will typically have one +instance of :class:`~.Cluster` for each Cassandra cluster you want to interact +with. + +First, make sure you have the Cassandra driver properly :doc:`installed `. + +Connecting to Cassandra ++++++++++++++++++++++++ +The simplest way to create a :class:`~.Cluster` is like this: + +.. code-block:: python + + from cassandra.cluster import Cluster + + cluster = Cluster() + +This will attempt to connection to a Cassandra instance on your +local machine (127.0.0.1). You can also specify a list of IP +addresses for nodes in your cluster: + +.. code-block:: python + + from cassandra.cluster import Cluster + + cluster = Cluster(['192.168.0.1', '192.168.0.2']) + +The set of IP addresses we pass to the :class:`~.Cluster` is simply +an initial set of contact points. After the driver connects to one +of these nodes it will *automatically discover* the rest of the +nodes in the cluster and connect to them, so you don't need to list +every node in your cluster. + +If you need to use a non-standard port, use SSL, or customize the driver's +behavior in some other way, this is the place to do it: + +.. code-block:: python + + from cassandra.cluster import Cluster + cluster = Cluster(['192.168.0.1', '192.168.0.2'], port=..., ssl_context=...) + +Instantiating a :class:`~.Cluster` does not actually connect us to any nodes. +To establish connections and begin executing queries we need a +:class:`~.Session`, which is created by calling :meth:`.Cluster.connect()`: + +.. code-block:: python + + cluster = Cluster() + session = cluster.connect() + +Session Keyspace +---------------- +The :meth:`~.Cluster.connect()` method takes an optional ``keyspace`` argument +which sets the default keyspace for all queries made through that :class:`~.Session`: + +.. code-block:: python + + cluster = Cluster() + session = cluster.connect('mykeyspace') + +You can always change a Session's keyspace using :meth:`~.Session.set_keyspace` or +by executing a ``USE `` query: + +.. code-block:: python + + session.set_keyspace('users') + # or you can do this instead + session.execute('USE users') + +Execution Profiles +------------------ +Profiles are passed in by ``execution_profiles`` dict. + +In this case we can construct the base ``ExecutionProfile`` passing all attributes: + +.. code-block:: python + + from cassandra.cluster import Cluster, ExecutionProfile, EXEC_PROFILE_DEFAULT + from cassandra.policies import WhiteListRoundRobinPolicy, DowngradingConsistencyRetryPolicy + from cassandra.query import tuple_factory + + profile = ExecutionProfile( + load_balancing_policy=WhiteListRoundRobinPolicy(['127.0.0.1']), + retry_policy=DowngradingConsistencyRetryPolicy(), + consistency_level=ConsistencyLevel.LOCAL_QUORUM, + serial_consistency_level=ConsistencyLevel.LOCAL_SERIAL, + request_timeout=15, + row_factory=tuple_factory + ) + cluster = Cluster(execution_profiles={EXEC_PROFILE_DEFAULT: profile}) + session = cluster.connect() + + print(session.execute("SELECT release_version FROM system.local").one()) + +Users are free to setup additional profiles to be used by name: + +.. code-block:: python + + profile_long = ExecutionProfile(request_timeout=30) + cluster = Cluster(execution_profiles={'long': profile_long}) + session = cluster.connect() + session.execute(statement, execution_profile='long') + +Also, parameters passed to ``Session.execute`` or attached to ``Statement``\s are still honored as before. + +Executing Queries +----------------- +Now that we have a :class:`.Session` we can begin to execute queries. The simplest +way to execute a query is to use :meth:`~.Session.execute()`: + +.. code-block:: python + + rows = session.execute('SELECT name, age, email FROM users') + for user_row in rows: + print user_row.name, user_row.age, user_row.email + +This will transparently pick a Cassandra node to execute the query against +and handle any retries that are necessary if the operation fails. + +By default, each row in the result set will be a +`namedtuple `_. +Each row will have a matching attribute for each column defined in the schema, +such as ``name``, ``age``, and so on. You can also treat them as normal tuples +by unpacking them or accessing fields by position. The following three +examples are equivalent: + +.. code-block:: python + + rows = session.execute('SELECT name, age, email FROM users') + for row in rows: + print row.name, row.age, row.email + +.. code-block:: python + + rows = session.execute('SELECT name, age, email FROM users') + for (name, age, email) in rows: + print name, age, email + +.. code-block:: python + + rows = session.execute('SELECT name, age, email FROM users') + for row in rows: + print row[0], row[1], row[2] + +If you prefer another result format, such as a ``dict`` per row, you +can change the :attr:`~.Session.row_factory` attribute. + +As mentioned in our `Drivers Best Practices Guide `_, +it is highly recommended to use `Prepared statements <#prepared-statement>`_ for your +frequently run queries. + +.. _prepared-statement: + +Prepared Statements +------------------- +Prepared statements are queries that are parsed by Cassandra and then saved +for later use. When the driver uses a prepared statement, it only needs to +send the values of parameters to bind. This lowers network traffic +and CPU utilization within Cassandra because Cassandra does not have to +re-parse the query each time. + +To prepare a query, use :meth:`.Session.prepare()`: + +.. code-block:: python + + user_lookup_stmt = session.prepare("SELECT * FROM users WHERE user_id=?") + + users = [] + for user_id in user_ids_to_query: + user = session.execute(user_lookup_stmt, [user_id]) + users.append(user) + +:meth:`~.Session.prepare()` returns a :class:`~.PreparedStatement` instance +which can be used in place of :class:`~.SimpleStatement` instances or literal +string queries. It is automatically prepared against all nodes, and the driver +handles re-preparing against new nodes and restarted nodes when necessary. + +Note that the placeholders for prepared statements are ``?`` characters. This +is different than for simple, non-prepared statements (although future versions +of the driver may use the same placeholders for both). + +Passing Parameters to CQL Queries +--------------------------------- +Althought it is not recommended, you can also pass parameters to non-prepared +statements. The driver supports two forms of parameter place-holders: positional +and named. + +Positional parameters are used with a ``%s`` placeholder. For example, +when you execute: + +.. code-block:: python + + session.execute( + """ + INSERT INTO users (name, credits, user_id) + VALUES (%s, %s, %s) + """, + ("John O'Reilly", 42, uuid.uuid1()) + ) + +It is translated to the following CQL query:: + + INSERT INTO users (name, credits, user_id) + VALUES ('John O''Reilly', 42, 2644bada-852c-11e3-89fb-e0b9a54a6d93) + +Note that you should use ``%s`` for all types of arguments, not just strings. +For example, this would be **wrong**: + +.. code-block:: python + + session.execute("INSERT INTO USERS (name, age) VALUES (%s, %d)", ("bob", 42)) # wrong + +Instead, use ``%s`` for the age placeholder. + +If you need to use a literal ``%`` character, use ``%%``. + +**Note**: you must always use a sequence for the second argument, even if you are +only passing in a single variable: + +.. code-block:: python + + session.execute("INSERT INTO foo (bar) VALUES (%s)", "blah") # wrong + session.execute("INSERT INTO foo (bar) VALUES (%s)", ("blah")) # wrong + session.execute("INSERT INTO foo (bar) VALUES (%s)", ("blah", )) # right + session.execute("INSERT INTO foo (bar) VALUES (%s)", ["blah"]) # right + + +Note that the second line is incorrect because in Python, single-element tuples +require a comma. + +Named place-holders use the ``%(name)s`` form: + +.. code-block:: python + + session.execute( + """ + INSERT INTO users (name, credits, user_id, username) + VALUES (%(name)s, %(credits)s, %(user_id)s, %(name)s) + """, + {'name': "John O'Reilly", 'credits': 42, 'user_id': uuid.uuid1()} + ) + +Note that you can repeat placeholders with the same name, such as ``%(name)s`` +in the above example. + +Only data values should be supplied this way. Other items, such as keyspaces, +table names, and column names should be set ahead of time (typically using +normal string formatting). + +.. _type-conversions: + +Type Conversions +---------------- +For non-prepared statements, Python types are cast to CQL literals in the +following way: + +.. table:: + + +--------------------+-------------------------+ + | Python Type | CQL Literal Type | + +====================+=========================+ + | ``None`` | ``NULL`` | + +--------------------+-------------------------+ + | ``bool`` | ``boolean`` | + +--------------------+-------------------------+ + | ``float`` | | ``float`` | + | | | ``double`` | + +--------------------+-------------------------+ + | | ``int`` | | ``int`` | + | | ``long`` | | ``bigint`` | + | | | ``varint`` | + | | | ``smallint`` | + | | | ``tinyint`` | + | | | ``counter`` | + +--------------------+-------------------------+ + | ``decimal.Decimal``| ``decimal`` | + +--------------------+-------------------------+ + | | ``str`` | | ``ascii`` | + | | ``unicode`` | | ``varchar`` | + | | | ``text`` | + +--------------------+-------------------------+ + | | ``buffer`` | ``blob`` | + | | ``bytearray`` | | + +--------------------+-------------------------+ + | ``date`` | ``date`` | + +--------------------+-------------------------+ + | ``datetime`` | ``timestamp`` | + +--------------------+-------------------------+ + | ``time`` | ``time`` | + +--------------------+-------------------------+ + | | ``list`` | ``list`` | + | | ``tuple`` | | + | | generator | | + +--------------------+-------------------------+ + | | ``set`` | ``set`` | + | | ``frozenset`` | | + +--------------------+-------------------------+ + | | ``dict`` | ``map`` | + | | ``OrderedDict`` | | + +--------------------+-------------------------+ + | ``uuid.UUID`` | | ``timeuuid`` | + | | | ``uuid`` | + +--------------------+-------------------------+ + + +Asynchronous Queries +-------------------- +The driver supports asynchronous query execution through +:meth:`~.Session.execute_async()`. Instead of waiting for the query to +complete and returning rows directly, this method almost immediately +returns a :class:`~.ResponseFuture` object. There are two ways of +getting the final result from this object. + +The first is by calling :meth:`~.ResponseFuture.result()` on it. If +the query has not yet completed, this will block until it has and +then return the result or raise an Exception if an error occurred. +For example: + +.. code-block:: python + + from cassandra import ReadTimeout + + query = "SELECT * FROM users WHERE user_id=%s" + future = session.execute_async(query, [user_id]) + + # ... do some other work + + try: + rows = future.result() + user = rows[0] + print user.name, user.age + except ReadTimeout: + log.exception("Query timed out:") + +This works well for executing many queries concurrently: + +.. code-block:: python + + # build a list of futures + futures = [] + query = "SELECT * FROM users WHERE user_id=%s" + for user_id in ids_to_fetch: + futures.append(session.execute_async(query, [user_id]) + + # wait for them to complete and use the results + for future in futures: + rows = future.result() + print rows[0].name + +Alternatively, instead of calling :meth:`~.ResponseFuture.result()`, +you can attach callback and errback functions through the +:meth:`~.ResponseFuture.add_callback()`, +:meth:`~.ResponseFuture.add_errback()`, and +:meth:`~.ResponseFuture.add_callbacks()`, methods. If you have used +Twisted Python before, this is designed to be a lightweight version of +that: + +.. code-block:: python + + def handle_success(rows): + user = rows[0] + try: + process_user(user.name, user.age, user.id) + except Exception: + log.error("Failed to process user %s", user.id) + # don't re-raise errors in the callback + + def handle_error(exception): + log.error("Failed to fetch user info: %s", exception) + + + future = session.execute_async(query) + future.add_callbacks(handle_success, handle_error) + +There are a few important things to remember when working with callbacks: + * **Exceptions that are raised inside the callback functions will be logged and then ignored.** + * Your callback will be run on the event loop thread, so any long-running + operations will prevent other requests from being handled + + +Setting a Consistency Level +--------------------------- +The consistency level used for a query determines how many of the +replicas of the data you are interacting with need to respond for +the query to be considered a success. + +By default, :attr:`.ConsistencyLevel.LOCAL_ONE` will be used for all queries. +You can specify a different default by setting the :attr:`.ExecutionProfile.consistency_level` +for the execution profile with key :data:`~.cluster.EXEC_PROFILE_DEFAULT`. +To specify a different consistency level per request, wrap queries +in a :class:`~.SimpleStatement`: + +.. code-block:: python + + from cassandra import ConsistencyLevel + from cassandra.query import SimpleStatement + + query = SimpleStatement( + "INSERT INTO users (name, age) VALUES (%s, %s)", + consistency_level=ConsistencyLevel.QUORUM) + session.execute(query, ('John', 42)) + +Setting a Consistency Level with Prepared Statements +---------------------------------------------------- +To specify a consistency level for prepared statements, you have two options. + +The first is to set a default consistency level for every execution of the +prepared statement: + +.. code-block:: python + + from cassandra import ConsistencyLevel + + cluster = Cluster() + session = cluster.connect("mykeyspace") + user_lookup_stmt = session.prepare("SELECT * FROM users WHERE user_id=?") + user_lookup_stmt.consistency_level = ConsistencyLevel.QUORUM + + # these will both use QUORUM + user1 = session.execute(user_lookup_stmt, [user_id1])[0] + user2 = session.execute(user_lookup_stmt, [user_id2])[0] + +The second option is to create a :class:`~.BoundStatement` from the +:class:`~.PreparedStatement` and binding parameters and set a consistency +level on that: + +.. code-block:: python + + # override the QUORUM default + user3_lookup = user_lookup_stmt.bind([user_id3]) + user3_lookup.consistency_level = ConsistencyLevel.ALL + user3 = session.execute(user3_lookup) + +Speculative Execution +--------------------- + +Speculative execution is a way to minimize latency by preemptively executing several +instances of the same query against different nodes. For more details about this +technique, see `Speculative Execution with DataStax Drivers `_. + +To enable speculative execution: + +* Configure a :class:`~.policies.SpeculativeExecutionPolicy` with the ExecutionProfile +* Mark your query as idempotent, which mean it can be applied multiple + times without changing the result of the initial application. + See `Query Idempotence `_ for more details. + + +Example: + +.. code-block:: python + + from cassandra.cluster import Cluster, ExecutionProfile, EXEC_PROFILE_DEFAULT + from cassandra.policies import ConstantSpeculativeExecutionPolicy + from cassandra.query import SimpleStatement + + # Configure the speculative execution policy + ep = ExecutionProfile( + speculative_execution_policy=ConstantSpeculativeExecutionPolicy(delay=.5, max_attempts=10) + ) + cluster = Cluster(..., execution_profiles={EXEC_PROFILE_DEFAULT: ep}) + session = cluster.connect() + + # Mark the query idempotent + query = SimpleStatement( + "UPDATE my_table SET list_col = [1] WHERE pk = 1", + is_idempotent=True + ) + + # Execute. A new query will be sent to the server every 0.5 second + # until we receive a response, for a max number attempts of 10. + session.execute(query) diff --git a/3.25.4-scylla/_sources/index.rst.txt b/3.25.4-scylla/_sources/index.rst.txt new file mode 100644 index 0000000000..fed26e9fc9 --- /dev/null +++ b/3.25.4-scylla/_sources/index.rst.txt @@ -0,0 +1,105 @@ +Python Driver for Scylla and Apache Cassandra® +============================================== +A Python client driver for `Scylla `_. +This driver works exclusively with the Cassandra Query Language v3 (CQL3) +and Cassandra's native protocol. + +The driver supports Python 2.7, 3.5, 3.6, 3.7 and 3.8. + +This driver is open source under the +`Apache v2 License `_. +The source code for this driver can be found on `GitHub `_. + +Scylla Driver is a fork from `DataStax Python Driver `_, including some non-breaking changes for Scylla optimization, with more updates planned. + +Contents +-------- +:doc:`installation` + How to install the driver. + +:doc:`getting_started` + A guide through the first steps of connecting to Scylla and executing queries + +:doc:`scylla_specific` + A list of feature available only on ``scylla-driver`` + +:doc:`execution_profiles` + An introduction to a more flexible way of configuring request execution + +:doc:`lwt` + Working with results of conditional requests + +:doc:`object_mapper` + Introduction to the integrated object mapper, cqlengine + +:doc:`performance` + Tips for getting good performance. + +:doc:`query_paging` + Notes on paging large query results + +:doc:`security` + An overview of the security features of the driver + +:doc:`upgrading` + A guide to upgrading versions of the driver + +:doc:`user_defined_types` + Working with Scylla's user-defined types (UDT) + +:doc:`dates_and_times` + Some discussion on the driver's approach to working with timestamp, date, time types + +:doc:`scylla_cloud` + Connect to Scylla Cloud + +:doc:`CHANGELOG` + Log of changes to the driver, organized by version. + +:doc:`faq` + A collection of Frequently Asked Questions + +:doc:`api/index` + The API documentation. + +.. toctree:: + :hidden: + + api/index + installation + getting_started + scylla_specific + upgrading + execution_profiles + performance + query_paging + lwt + security + user_defined_types + object_mapper + dates_and_times + scylla_cloud + faq + +Getting Help +------------ +Visit the :doc:`FAQ section ` in this documentation. + +Please send questions to the Scylla `user list `_. + + +Reporting Issues +---------------- + +Please report any bugs and make any feature requests on the `Github project issues `_ + + +Copyright +--------- + +© 2013-2017 DataStax + +© 2016, The Apache Software Foundation. +Apache®, Apache Cassandra®, Cassandra®, the Apache feather logo and the Apache Cassandra® Eye logo are either registered trademarks or trademarks of the Apache Software Foundation in the United States and/or other countries. No endorsement by The Apache Software Foundation is implied by the use of these marks. + + diff --git a/3.25.4-scylla/_sources/installation.rst.txt b/3.25.4-scylla/_sources/installation.rst.txt new file mode 100644 index 0000000000..4996a02c1b --- /dev/null +++ b/3.25.4-scylla/_sources/installation.rst.txt @@ -0,0 +1,234 @@ +Installation +============ + +Supported Platforms +------------------- +Python 2.7, 3.5, 3.6, 3.7 and 3.8 are supported. Both CPython (the standard Python +implementation) and `PyPy `_ are supported and tested. + +Linux, OSX, and Windows are supported. + +Installation through pip +------------------------ +`pip `_ is the suggested tool for installing +packages. It will handle installing all Python dependencies for the driver at +the same time as the driver itself. To install the driver*:: + + pip install scylla-driver + +You can use ``pip install --pre scylla-driver`` if you need to install a beta version. + +***Note**: if intending to use optional extensions, install the `dependencies <#optional-non-python-dependencies>`_ first. The driver may need to be reinstalled if dependencies are added after the initial installation. + +Verifying your Installation +--------------------------- +To check if the installation was successful, you can run:: + + python -c 'import cassandra; print cassandra.__version__' + +It should print something like "3.22.0". + +.. _installation-datastax-graph: + +(*Optional*) Graph +--------------------------- +The driver provides an optional fluent graph API that depends on Apache TinkerPop (gremlinpython). It is +not installed by default. To be able to build Gremlin traversals, you need to install +the `graph` requirements:: + + pip install scylla-driver[graph] + +(*Optional*) Compression Support +-------------------------------- +Compression can optionally be used for communication between the driver and +Cassandra. There are currently two supported compression algorithms: +snappy (in Cassandra 1.2+) and LZ4 (only in Cassandra 2.0+). If either is +available for the driver and Cassandra also supports it, it will +be used automatically. + +For lz4 support:: + + pip install lz4 + +For snappy support:: + + pip install python-snappy + +(If using a Debian Linux derivative such as Ubuntu, it may be easier to +just run ``apt-get install python-snappy``.) + +(*Optional*) Metrics Support +---------------------------- +The driver has built-in support for capturing :attr:`.Cluster.metrics` about +the queries you run. However, the ``scales`` library is required to +support this:: + + pip install scales + + +Speeding Up Installation +^^^^^^^^^^^^^^^^^^^^^^^^ + +By default, installing the driver through ``pip`` uses a pre-compiled, platform-specific wheel when available. +If using a source distribution rather than a wheel, Cython is used to compile certain parts of the driver. +This makes those hot paths faster at runtime, but the Cython compilation +process can take a long time -- as long as 10 minutes in some environments. + +In environments where performance is less important, it may be worth it to +:ref:`disable Cython as documented below `. +You can also use ``CASS_DRIVER_BUILD_CONCURRENCY`` to increase the number of +threads used to build the driver and any C extensions: + +.. code-block:: bash + + $ # installing from source + $ CASS_DRIVER_BUILD_CONCURRENCY=8 python setup.py install + $ # installing from pip + $ CASS_DRIVER_BUILD_CONCURRENCY=8 pip install scylla-driver + +OSX Installation Error +^^^^^^^^^^^^^^^^^^^^^^ +If you're installing on OSX and have XCode 5.1 installed, you may see an error like this:: + + clang: error: unknown argument: '-mno-fused-madd' [-Wunused-command-line-argument-hard-error-in-future] + +To fix this, re-run the installation with an extra compilation flag: + +.. code-block:: bash + + ARCHFLAGS=-Wno-error=unused-command-line-argument-hard-error-in-future pip install scylla-driver + +.. _windows_build: + +Windows Installation Notes +-------------------------- +Installing the driver with extensions in Windows sometimes presents some challenges. A few notes about common +hang-ups: + +Setup requires a compiler. When using Python 2, this is as simple as installing `this package `_ +(this link is also emitted during install if setuptools is unable to find the resources it needs). Depending on your +system settings, this package may install as a user-specific application. Make sure to install for everyone, or at least +as the user that will be building the Python environment. + +It is also possible to run the build with your compiler of choice. Just make sure to have your environment setup with +the proper paths. Make sure the compiler target architecture matches the bitness of your Python runtime. +Perhaps the easiest way to do this is to run the build/install from a Visual Studio Command Prompt (a +shortcut installed with Visual Studio that sources the appropriate environment and presents a shell). + +Manual Installation +------------------- +You can always install the driver directly from a source checkout or tarball. +When installing manually, ensure the python dependencies are already +installed. You can find the list of dependencies in +`requirements.txt `_. + +Once the dependencies are installed, simply run:: + + python setup.py install + + +(*Optional*) Non-python Dependencies +------------------------------------ +The driver has several **optional** features that have non-Python dependencies. + +C Extensions +^^^^^^^^^^^^ +By default, a number of extensions are compiled, providing faster hashing +for token-aware routing with the ``Murmur3Partitioner``, +`libev `_ event loop integration, +and Cython optimized extensions. + +When installing manually through setup.py, you can disable both with +the ``--no-extensions`` option, or selectively disable them with +with ``--no-murmur3``, ``--no-libev``, or ``--no-cython``. + +To compile the extensions, ensure that GCC and the Python headers are available. + +On Ubuntu and Debian, this can be accomplished by running:: + + $ sudo apt-get install gcc python-dev + +On RedHat and RedHat-based systems like CentOS and Fedora:: + + $ sudo yum install gcc python-devel + +On OS X, homebrew installations of Python should provide the necessary headers. + +See :ref:`windows_build` for notes on configuring the build environment on Windows. + +.. _cython-extensions: + +Cython-based Extensions +~~~~~~~~~~~~~~~~~~~~~~~ +By default, this package uses `Cython `_ to optimize core modules and build custom extensions. +This is not a hard requirement, but is engaged by default to build extensions offering better performance than the +pure Python implementation. + +This is a costly build phase, especially in clean environments where the Cython compiler must be built +This build phase can be avoided using the build switch, or an environment variable:: + + python setup.py install --no-cython + +Alternatively, an environment variable can be used to switch this option regardless of +context:: + + CASS_DRIVER_NO_CYTHON=1 + - or, to disable all extensions: + CASS_DRIVER_NO_EXTENSIONS=1 + +This method is required when using pip, which provides no other way of injecting user options in a single command:: + + CASS_DRIVER_NO_CYTHON=1 pip install scylla-driver + CASS_DRIVER_NO_CYTHON=1 sudo -E pip install ~/python-driver + +The environment variable is the preferred option because it spans all invocations of setup.py, and will +prevent Cython from being materialized as a setup requirement. + +If your sudo configuration does not allow SETENV, you must push the option flag down via pip. However, pip +applies these options to all dependencies (which break on the custom flag). Therefore, you must first install +dependencies, then use install-option:: + + sudo pip install six futures + sudo pip install --install-option="--no-cython" + + +libev support +^^^^^^^^^^^^^ +The driver currently uses Python's ``asyncore`` module for its default +event loop. For better performance, ``libev`` is also supported through +a C extension. + +If you're on Linux, you should be able to install libev +through a package manager. For example, on Debian/Ubuntu:: + + $ sudo apt-get install libev4 libev-dev + +On RHEL/CentOS/Fedora:: + + $ sudo yum install libev libev-devel + +If you're on Mac OS X, you should be able to install libev +through `Homebrew `_. For example, on Mac OS X:: + + $ brew install libev + +The libev extension is not built for Windows (the build process is complex, and the Windows implementation uses +select anyway). + +If successful, you should be able to build and install the extension +(just using ``setup.py build`` or ``setup.py install``) and then use +the libev event loop by doing the following: + +.. code-block:: python + + >>> from cassandra.io.libevreactor import LibevConnection + >>> from cassandra.cluster import Cluster + + >>> cluster = Cluster() + >>> cluster.connection_class = LibevConnection + >>> session = cluster.connect() + +(*Optional*) Configuring SSL +----------------------------- +Andrew Mussey has published a thorough guide on +`Using SSL with the DataStax Python driver `_. diff --git a/3.25.4-scylla/_sources/lwt.rst.txt b/3.25.4-scylla/_sources/lwt.rst.txt new file mode 100644 index 0000000000..2cc272f350 --- /dev/null +++ b/3.25.4-scylla/_sources/lwt.rst.txt @@ -0,0 +1,91 @@ +Lightweight Transactions (Compare-and-set) +========================================== + +Lightweight Transactions (LWTs) are mostly pass-through CQL for the driver. However, +the server returns some specialized results indicating the outcome and optional state +preceding the transaction. + +For pertinent execution parameters, see :attr:`.Statement.serial_consistency_level`. + +This section discusses working with specialized result sets returned by the server for LWTs, +and how to work with them using the driver. + + +Specialized Results +------------------- +The result returned from a LWT request is always a single row result. It will always have +prepended a special column named ``[applied]``. How this value appears in your results depends +on the row factory in use. See below for examples. + +The value of this ``[applied]`` column is boolean value indicating whether or not the transaction was applied. +If ``True``, it is the only column in the result. If ``False``, the additional columns depend on the LWT operation being +executed: + +- When using a ``UPDATE ... IF "col" = ...`` clause, the result will contain the ``[applied]`` column, plus the existing columns + and values for any columns in the ``IF`` clause (and thus the value that caused the transaction to fail). + +- When using ``INSERT ... IF NOT EXISTS``, the result will contain the ``[applied]`` column, plus all columns and values + of the existing row that rejected the transaction. + +- ``UPDATE .. IF EXISTS`` never has additional columns, regardless of ``[applied]`` status. + +How the ``[applied]`` column manifests depends on the row factory in use. Considering the following (initially empty) table:: + + CREATE TABLE test.t ( + k int PRIMARY KEY, + v int, + x int + ) + +... the following sections show the expected result for a number of example statements, using the three base row factories. + +named_tuple_factory (default) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +The name ``[applied]`` is not a valid Python identifier, so the square brackets are actually removed +from the attribute for the resulting ``namedtuple``. The row always has a boolean column ``applied`` in position 0:: + + >>> session.execute("INSERT INTO t (k,v) VALUES (0,0) IF NOT EXISTS") + Row(applied=True) + + >>> session.execute("INSERT INTO t (k,v) VALUES (0,0) IF NOT EXISTS") + Row(applied=False, k=0, v=0, x=None) + + >>> session.execute("UPDATE t SET v = 1, x = 2 WHERE k = 0 IF v =0") + Row(applied=True) + + >>> session.execute("UPDATE t SET v = 1, x = 2 WHERE k = 0 IF v =0 AND x = 1") + Row(applied=False, v=1, x=2) + +tuple_factory +~~~~~~~~~~~~~ +This return type does not refer to names, but the boolean value ``applied`` is always present in position 0:: + + >>> session.execute("INSERT INTO t (k,v) VALUES (0,0) IF NOT EXISTS") + (True,) + + >>> session.execute("INSERT INTO t (k,v) VALUES (0,0) IF NOT EXISTS") + (False, 0, 0, None) + + >>> session.execute("UPDATE t SET v = 1, x = 2 WHERE k = 0 IF v =0") + (True,) + + >>> session.execute("UPDATE t SET v = 1, x = 2 WHERE k = 0 IF v =0 AND x = 1") + (False, 1, 2) + +dict_factory +~~~~~~~~~~~~ +The retuned ``dict`` contains the ``[applied]`` key:: + + >>> session.execute("INSERT INTO t (k,v) VALUES (0,0) IF NOT EXISTS") + {u'[applied]': True} + + >>> session.execute("INSERT INTO t (k,v) VALUES (0,0) IF NOT EXISTS") + {u'x': 2, u'[applied]': False, u'v': 1} + + >>> session.execute("UPDATE t SET v = 1, x = 2 WHERE k = 0 IF v =0") + {u'x': None, u'[applied]': False, u'k': 0, u'v': 0} + + >>> session.execute("UPDATE t SET v = 1, x = 2 WHERE k = 0 IF v =0 AND x = 1") + {u'[applied]': True} + + diff --git a/3.25.4-scylla/_sources/object_mapper.rst.txt b/3.25.4-scylla/_sources/object_mapper.rst.txt new file mode 100644 index 0000000000..50d3cbf320 --- /dev/null +++ b/3.25.4-scylla/_sources/object_mapper.rst.txt @@ -0,0 +1,105 @@ +Object Mapper +============= + +cqlengine is the Cassandra CQL 3 Object Mapper packaged with this driver + +:ref:`Jump to Getting Started ` + +Contents +-------- +:doc:`cqlengine/upgrade_guide` + For migrating projects from legacy cqlengine, to the integrated product + +:doc:`cqlengine/models` + Examples defining models, and mapping them to tables + +:doc:`cqlengine/queryset` + Overview of query sets and filtering + +:doc:`cqlengine/batches` + Working with batch mutations + +:doc:`cqlengine/connections` + Working with multiple sessions + +:ref:`API Documentation ` + Index of API documentation + +:doc:`cqlengine/third_party` + High-level examples in Celery and uWSGI + +:doc:`cqlengine/faq` + +.. toctree:: + :hidden: + + cqlengine/upgrade_guide + cqlengine/models + cqlengine/queryset + cqlengine/batches + cqlengine/connections + cqlengine/third_party + cqlengine/faq + +.. _getting-started: + +Getting Started +--------------- + +.. code-block:: python + + import uuid + from cassandra.cqlengine import columns + from cassandra.cqlengine import connection + from datetime import datetime + from cassandra.cqlengine.management import sync_table + from cassandra.cqlengine.models import Model + + #first, define a model + class ExampleModel(Model): + example_id = columns.UUID(primary_key=True, default=uuid.uuid4) + example_type = columns.Integer(index=True) + created_at = columns.DateTime() + description = columns.Text(required=False) + + #next, setup the connection to your cassandra server(s)... + # see http://datastax.github.io/python-driver/api/cassandra/cluster.html for options + # the list of hosts will be passed to create a Cluster() instance + connection.setup(['127.0.0.1'], "cqlengine", protocol_version=3) + + #...and create your CQL table + >>> sync_table(ExampleModel) + + #now we can create some rows: + >>> em1 = ExampleModel.create(example_type=0, description="example1", created_at=datetime.now()) + >>> em2 = ExampleModel.create(example_type=0, description="example2", created_at=datetime.now()) + >>> em3 = ExampleModel.create(example_type=0, description="example3", created_at=datetime.now()) + >>> em4 = ExampleModel.create(example_type=0, description="example4", created_at=datetime.now()) + >>> em5 = ExampleModel.create(example_type=1, description="example5", created_at=datetime.now()) + >>> em6 = ExampleModel.create(example_type=1, description="example6", created_at=datetime.now()) + >>> em7 = ExampleModel.create(example_type=1, description="example7", created_at=datetime.now()) + >>> em8 = ExampleModel.create(example_type=1, description="example8", created_at=datetime.now()) + + #and now we can run some queries against our table + >>> ExampleModel.objects.count() + 8 + >>> q = ExampleModel.objects(example_type=1) + >>> q.count() + 4 + >>> for instance in q: + >>> print instance.description + example5 + example6 + example7 + example8 + + #here we are applying additional filtering to an existing query + #query objects are immutable, so calling filter returns a new + #query object + >>> q2 = q.filter(example_id=em5.example_id) + + >>> q2.count() + 1 + >>> for instance in q2: + >>> print instance.description + example5 diff --git a/3.25.4-scylla/_sources/performance.rst.txt b/3.25.4-scylla/_sources/performance.rst.txt new file mode 100644 index 0000000000..f7a3f49e0f --- /dev/null +++ b/3.25.4-scylla/_sources/performance.rst.txt @@ -0,0 +1,45 @@ +Performance Notes +================= +The Python driver for Cassandra offers several methods for executing queries. +You can synchronously block for queries to complete using +:meth:`.Session.execute()`, you can obtain asynchronous request futures through +:meth:`.Session.execute_async()`, and you can attach a callback to the future +with :meth:`.ResponseFuture.add_callback()`. + +Examples of multiple request patterns can be found in the benchmark scripts included in the driver project. + +The choice of execution pattern will depend on the application context. For applications dealing with multiple +requests in a given context, the recommended pattern is to use concurrent asynchronous +requests with callbacks. For many use cases, you don't need to implement this pattern yourself. +:meth:`cassandra.concurrent.execute_concurrent` and :meth:`cassandra.concurrent.execute_concurrent_with_args` +provide this pattern with a synchronous API and tunable concurrency. + +Due to the GIL and limited concurrency, the driver can become CPU-bound pretty quickly. The sections below +discuss further runtime and design considerations for mitigating this limitation. + +PyPy +---- +`PyPy `_ is an alternative Python runtime which uses a JIT compiler to +reduce CPU consumption. This leads to a huge improvement in the driver performance, +more than doubling throughput for many workloads. + +Cython Extensions +----------------- +`Cython `_ is an optimizing compiler and language that can be used to compile the core files and +optional extensions for the driver. Cython is not a strict dependency, but the extensions will be built by default. + +See :doc:`installation` for details on controlling this build. + +multiprocessing +--------------- +All of the patterns discussed above may be used over multiple processes using the +`multiprocessing `_ +module. Multiple processes will scale better than multiple threads, so if high throughput is your goal, +consider this option. + +Be sure to **never share any** :class:`~.Cluster`, :class:`~.Session`, +**or** :class:`~.ResponseFuture` **objects across multiple processes**. These +objects should all be created after forking the process, not before. + +For further discussion and simple examples using the driver with ``multiprocessing``, +see `this blog post `_. diff --git a/3.25.4-scylla/_sources/query_paging.rst.txt b/3.25.4-scylla/_sources/query_paging.rst.txt new file mode 100644 index 0000000000..23ee2c1129 --- /dev/null +++ b/3.25.4-scylla/_sources/query_paging.rst.txt @@ -0,0 +1,95 @@ +.. _query-paging: + +Paging Large Queries +==================== +Cassandra 2.0+ offers support for automatic query paging. Starting with +version 2.0 of the driver, if :attr:`~.Cluster.protocol_version` is greater than +:const:`2` (it is by default), queries returning large result sets will be +automatically paged. + +Controlling the Page Size +------------------------- +By default, :attr:`.Session.default_fetch_size` controls how many rows will +be fetched per page. This can be overridden per-query by setting +:attr:`~.fetch_size` on a :class:`~.Statement`. By default, each page +will contain at most 5000 rows. + +Handling Paged Results +---------------------- +Whenever the number of result rows for are query exceed the page size, an +instance of :class:`~.PagedResult` will be returned instead of a normal +list. This class implements the iterator interface, so you can treat +it like a normal iterator over rows:: + + from cassandra.query import SimpleStatement + query = "SELECT * FROM users" # users contains 100 rows + statement = SimpleStatement(query, fetch_size=10) + for user_row in session.execute(statement): + process_user(user_row) + +Whenever there are no more rows in the current page, the next page will +be fetched transparently. However, note that it *is* possible for +an :class:`Exception` to be raised while fetching the next page, just +like you might see on a normal call to ``session.execute()``. + +If you use :meth:`.Session.execute_async()` along with, +:meth:`.ResponseFuture.result()`, the first page will be fetched before +:meth:`~.ResponseFuture.result()` returns, but latter pages will be +transparently fetched synchronously while iterating the result. + +Handling Paged Results with Callbacks +------------------------------------- +If callbacks are attached to a query that returns a paged result, +the callback will be called once per page with a normal list of rows. + +Use :attr:`.ResponseFuture.has_more_pages` and +:meth:`.ResponseFuture.start_fetching_next_page()` to continue fetching +pages. For example:: + + class PagedResultHandler(object): + + def __init__(self, future): + self.error = None + self.finished_event = Event() + self.future = future + self.future.add_callbacks( + callback=self.handle_page, + errback=self.handle_err) + + def handle_page(self, rows): + for row in rows: + process_row(row) + + if self.future.has_more_pages: + self.future.start_fetching_next_page() + else: + self.finished_event.set() + + def handle_error(self, exc): + self.error = exc + self.finished_event.set() + + future = session.execute_async("SELECT * FROM users") + handler = PagedResultHandler(future) + handler.finished_event.wait() + if handler.error: + raise handler.error + +Resume Paged Results +-------------------- + +You can resume the pagination when executing a new query by using the :attr:`.ResultSet.paging_state`. This can be useful if you want to provide some stateless pagination capabilities to your application (ie. via http). For example:: + + from cassandra.query import SimpleStatement + query = "SELECT * FROM users" + statement = SimpleStatement(query, fetch_size=10) + results = session.execute(statement) + + # save the paging_state somewhere and return current results + web_session['paging_state'] = results.paging_state + + + # resume the pagination sometime later... + statement = SimpleStatement(query, fetch_size=10) + ps = web_session['paging_state'] + results = session.execute(statement, paging_state=ps) diff --git a/3.25.4-scylla/_sources/scylla_cloud.rst.txt b/3.25.4-scylla/_sources/scylla_cloud.rst.txt new file mode 100644 index 0000000000..62aaf76433 --- /dev/null +++ b/3.25.4-scylla/_sources/scylla_cloud.rst.txt @@ -0,0 +1,5 @@ +Scylla Cloud +------------ + +To connect to a `Scylla Cloud `_ cluster, go to the Cluster Connect page, Python example. +For best performance, make sure to use the Scylla Driver. diff --git a/3.25.4-scylla/_sources/scylla_specific.rst.txt b/3.25.4-scylla/_sources/scylla_specific.rst.txt new file mode 100644 index 0000000000..24e2182dc6 --- /dev/null +++ b/3.25.4-scylla/_sources/scylla_specific.rst.txt @@ -0,0 +1,106 @@ +Scylla Specific Features +======================== + +Shard Awareness +--------------- + +**scylla-driver** is shard aware and contains extensions that work with the TokenAwarePolicy supported by Scylla 2.3 and onwards. Using this policy, the driver can select a connection to a particular shard based on the shard's token. +As a result, latency is significantly reduced because there is no need to pass data between the shards. + +Details on the scylla cql protocol extensions +https://github.com/scylladb/scylla/blob/master/docs/design-notes/protocol-extensions.md#intranode-sharding + +For using it you only need to enable ``TokenAwarePolicy`` on the ``Cluster`` + +See the configuration of ``native_shard_aware_transport_port`` and ``native_shard_aware_transport_port_ssl`` on scylla.yaml: +https://github.com/scylladb/scylla/blob/master/docs/design-notes/protocols.md#cql-client-protocol + +.. code:: python + + from cassandra.cluster import Cluster + from cassandra.policies import TokenAwarePolicy, RoundRobinPolicy + + cluster = Cluster(load_balancing_policy=TokenAwarePolicy(RoundRobinPolicy())) + + +New Cluster Helpers +------------------- + +* ``shard_aware_options`` + + Setting it to ``dict(disable=True)`` would disable the shard aware functionally, for cases favoring once connection per host (example, lots of processes connecting from one client host, generating a big load of connections + + Other option is to configure scylla by setting ``enable_shard_aware_drivers: false`` on scylla.yaml. + +.. code:: python + + from cassandra.cluster import Cluster + + cluster = Cluster(shard_aware_options=dict(disable=True)) + session = cluster.connect() + + assert not cluster.is_shard_aware(), "Shard aware should be disabled" + + # or just disable the shard aware port logic + cluster = Cluster(shard_aware_options=dict(disable_shardaware_port=True)) + session = cluster.connect() + +* ``cluster.is_shard_aware()`` + + New method available on ``Cluster`` allowing to check whether the remote cluster supports shard awareness (bool) + +.. code:: python + + from cassandra.cluster import Cluster + + cluster = Cluster() + session = cluster.connect() + + if cluster.is_shard_aware(): + print("connected to a scylla cluster") + +* ``cluster.shard_aware_stats()`` + + New method available on ``Cluster`` allowing to check the status of shard aware connections to all available hosts (dict) + +.. code:: python + + from cassandra.cluster import Cluster + + cluster = Cluster() + session = cluster.connect() + + stats = cluster.shard_aware_stats() + if all([v["shards_count"] == v["connected"] for v in stats.values()]): + print("successfully connected to all shards of all scylla nodes") + + +New Table Attributes +-------------------- + +* ``in_memory`` flag + + New flag available on ``TableMetadata.options`` to indicate that it is an `In Memory `_ table + +.. note:: in memory tables is a feature existing only in Scylla Enterprise + +.. code:: python + + from cassandra.cluster import Cluster + + cluster = Cluster() + session = cluster.connect() + session.execute(""" + CREATE KEYSPACE IF NOT EXISTS keyspace1 + WITH replication = {'class': 'SimpleStrategy', 'replication_factor': '1'}; + """) + + session.execute(""" + CREATE TABLE IF NOT EXISTS keyspace1.standard1 ( + key blob PRIMARY KEY, + "C0" blob + ) WITH in_memory=true AND compaction={'class': 'InMemoryCompactionStrategy'} + """) + + cluster.refresh_table_metadata("keyspace1", "standard1") + assert cluster.metadata.keyspaces["keyspace1"].tables["standard1"].options["in_memory"] == True diff --git a/3.25.4-scylla/_sources/security.rst.txt b/3.25.4-scylla/_sources/security.rst.txt new file mode 100644 index 0000000000..c30189562f --- /dev/null +++ b/3.25.4-scylla/_sources/security.rst.txt @@ -0,0 +1,421 @@ +.. _security: + +Security +======== +The two main security components you will use with the +Python driver are Authentication and SSL. + +Authentication +-------------- +Versions 2.0 and higher of the driver support a SASL-based +authentication mechanism when :attr:`~.Cluster.protocol_version` +is set to 2 or higher. To use this authentication, set +:attr:`~.Cluster.auth_provider` to an instance of a subclass +of :class:`~cassandra.auth.AuthProvider`. When working +with Cassandra's ``PasswordAuthenticator``, you can use +the :class:`~cassandra.auth.PlainTextAuthProvider` class. + +For example, suppose Cassandra is setup with its default +'cassandra' user with a password of 'cassandra': + +.. code-block:: python + + from cassandra.cluster import Cluster + from cassandra.auth import PlainTextAuthProvider + + auth_provider = PlainTextAuthProvider(username='cassandra', password='cassandra') + cluster = Cluster(auth_provider=auth_provider, protocol_version=2) + + + +Custom Authenticators +^^^^^^^^^^^^^^^^^^^^^ +If you're using something other than Cassandra's ``PasswordAuthenticator``, +:class:`~.SaslAuthProvider` is provided for generic SASL authentication mechanisms, +utilizing the ``pure-sasl`` package. +If these do not suit your needs, you may need to create your own subclasses of +:class:`~.AuthProvider` and :class:`~.Authenticator`. You can use the Sasl classes +as example implementations. + +Protocol v1 Authentication +^^^^^^^^^^^^^^^^^^^^^^^^^^ +When working with Cassandra 1.2 (or a higher version with +:attr:`~.Cluster.protocol_version` set to ``1``), you will not pass in +an :class:`~.AuthProvider` instance. Instead, you should pass in a +function that takes one argument, the IP address of a host, and returns +a dict of credentials with a ``username`` and ``password`` key: + +.. code-block:: python + + from cassandra.cluster import Cluster + + def get_credentials(host_address): + return {'username': 'joe', 'password': '1234'} + + cluster = Cluster(auth_provider=get_credentials, protocol_version=1) + +SSL +--- +SSL should be used when client encryption is enabled in Cassandra. + +To give you as much control as possible over your SSL configuration, our SSL +API takes a user-created `SSLContext` instance from the Python standard library. +These docs will include some examples for how to achieve common configurations, +but the `ssl.SSLContext `_ documentation +gives a more complete description of what is possible. + +To enable SSL with version 3.17.0 and higher, you will need to set :attr:`.Cluster.ssl_context` to a +``ssl.SSLContext`` instance to enable SSL. Optionally, you can also set :attr:`.Cluster.ssl_options` +to a dict of options. These will be passed as kwargs to ``ssl.SSLContext.wrap_socket()`` +when new sockets are created. + +If you create your SSLContext using `ssl.create_default_context `_, +be aware that SSLContext.check_hostname is set to True by default, so the hostname validation will be done +by Python and not the driver. For this reason, we need to set the server_hostname at best effort, which is the +resolved ip address. If this validation needs to be done against the FQDN, consider enabling it using the ssl_options +as described in the following examples or implement your own :class:`~.connection.EndPoint` and +:class:`~.connection.EndPointFactory`. + + +The following examples assume you have generated your Cassandra certificate and +keystore files with these intructions: + +* `Setup SSL Cert `_ + +It might be also useful to learn about the different levels of identity verification to understand the examples: + +* `Using SSL in DSE drivers `_ + +SSL with Twisted or Eventlet +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Twisted and Eventlet both use an alternative SSL implementation called pyOpenSSL, so if your `Cluster`'s connection class is +:class:`~cassandra.io.twistedreactor.TwistedConnection` or :class:`~cassandra.io.eventletreactor.EventletConnection`, you must pass a +`pyOpenSSL context `_ instead. +An example is provided in these docs, and more details can be found in the +`documentation `_. +pyOpenSSL is not installed by the driver and must be installed separately. + +SSL Configuration Examples +^^^^^^^^^^^^^^^^^^^^^^^^^^ +Here, we'll describe the server and driver configuration necessary to set up SSL to meet various goals, such as the client verifying the server and the server verifying the client. We'll also include Python code demonstrating how to use servers and drivers configured in these ways. + +.. _ssl-no-identify-verification: + +No identity verification +++++++++++++++++++++++++ + +No identity verification at all. Note that this is not recommended for for production deployments. + +The Cassandra configuration:: + + client_encryption_options: + enabled: true + keystore: /path/to/127.0.0.1.keystore + keystore_password: myStorePass + require_client_auth: false + +The driver configuration: + +.. code-block:: python + + from cassandra.cluster import Cluster, Session + from ssl import SSLContext, PROTOCOL_TLS + + ssl_context = SSLContext(PROTOCOL_TLS) + + cluster = Cluster(['127.0.0.1'], ssl_context=ssl_context) + session = cluster.connect() + +.. _ssl-client-verifies-server: + +Client verifies server +++++++++++++++++++++++ + +Ensure the python driver verifies the identity of the server. + +The Cassandra configuration:: + + client_encryption_options: + enabled: true + keystore: /path/to/127.0.0.1.keystore + keystore_password: myStorePass + require_client_auth: false + +For the driver configuration, it's very important to set `ssl_context.verify_mode` +to `CERT_REQUIRED`. Otherwise, the loaded verify certificate will have no effect: + +.. code-block:: python + + from cassandra.cluster import Cluster, Session + from ssl import SSLContext, PROTOCOL_TLS, CERT_REQUIRED + + ssl_context = SSLContext(PROTOCOL_TLS) + ssl_context.load_verify_locations('/path/to/rootca.crt') + ssl_context.verify_mode = CERT_REQUIRED + + cluster = Cluster(['127.0.0.1'], ssl_context=ssl_context) + session = cluster.connect() + +Additionally, you can also force the driver to verify the `hostname` of the server by passing additional options to `ssl_context.wrap_socket` via the `ssl_options` kwarg: + +.. code-block:: python + + from cassandra.cluster import Cluster, Session + from ssl import SSLContext, PROTOCOL_TLS, CERT_REQUIRED + + ssl_context = SSLContext(PROTOCOL_TLS) + ssl_context.load_verify_locations('/path/to/rootca.crt') + ssl_context.verify_mode = CERT_REQUIRED + ssl_context.check_hostname = True + ssl_options = {'server_hostname': '127.0.0.1'} + + cluster = Cluster(['127.0.0.1'], ssl_context=ssl_context, ssl_options=ssl_options) + session = cluster.connect() + +.. _ssl-server-verifies-client: + +Server verifies client +++++++++++++++++++++++ + +If Cassandra is configured to verify clients (``require_client_auth``), you need to generate +SSL key and certificate files. + +The cassandra configuration:: + + client_encryption_options: + enabled: true + keystore: /path/to/127.0.0.1.keystore + keystore_password: myStorePass + require_client_auth: true + truststore: /path/to/dse-truststore.jks + truststore_password: myStorePass + +The Python ``ssl`` APIs require the certificate in PEM format. First, create a certificate +conf file: + +.. code-block:: bash + + cat > gen_client_cert.conf <`__ +for more details about ``SSLContext`` configuration. + +**Server verifies client and client verifies server using Twisted and pyOpenSSL** + +.. code-block:: python + + from OpenSSL import SSL, crypto + from cassandra.cluster import Cluster + from cassandra.io.twistedreactor import TwistedConnection + + ssl_context = SSL.Context(SSL.TLSv1_2_METHOD) + ssl_context.set_verify(SSL.VERIFY_PEER, callback=lambda _1, _2, _3, _4, ok: ok) + ssl_context.use_certificate_file('/path/to/client.crt_signed') + ssl_context.use_privatekey_file('/path/to/client.key') + ssl_context.load_verify_locations('/path/to/rootca.crt') + + cluster = Cluster( + contact_points=['127.0.0.1'], + connection_class=TwistedConnection, + ssl_context=ssl_context, + ssl_options={'check_hostname': True} + ) + session = cluster.connect() + + +Connecting using Eventlet would look similar except instead of importing and using ``TwistedConnection``, you would +import and use ``EventletConnection``, including the appropriate monkey-patching. + +Versions 3.16.0 and lower +^^^^^^^^^^^^^^^^^^^^^^^^^ + +To enable SSL you will need to set :attr:`.Cluster.ssl_options` to a +dict of options. These will be passed as kwargs to ``ssl.wrap_socket()`` +when new sockets are created. Note that this use of ssl_options will be +deprecated in the next major release. + +By default, a ``ca_certs`` value should be supplied (the value should be +a string pointing to the location of the CA certs file), and you probably +want to specify ``ssl_version`` as ``ssl.PROTOCOL_TLS`` to match +Cassandra's default protocol. + +For example: + +.. code-block:: python + + from cassandra.cluster import Cluster + from ssl import PROTOCOL_TLS, CERT_REQUIRED + + ssl_opts = { + 'ca_certs': '/path/to/my/ca.certs', + 'ssl_version': PROTOCOL_TLS, + 'cert_reqs': CERT_REQUIRED # Certificates are required and validated + } + cluster = Cluster(ssl_options=ssl_opts) + +This is only an example to show how to pass the ssl parameters. Consider reading +the `python ssl documentation `__ for +your configuration. For further reading, Andrew Mussey has published a thorough guide on +`Using SSL with the DataStax Python driver `_. + +SSL with Twisted +++++++++++++++++ + +In case the twisted event loop is used pyOpenSSL must be installed or an exception will be risen. Also +to set the ``ssl_version`` and ``cert_reqs`` in ``ssl_opts`` the appropriate constants from pyOpenSSL are expected. + +DSE Authentication +------------------ +When authenticating against DSE, the Cassandra driver provides two auth providers that work both with legacy kerberos and Cassandra authenticators, +as well as the new DSE Unified Authentication. This allows client to configure this auth provider independently, +and in advance of any server upgrade. These auth providers are configured in the same way as any previous implementation:: + + from cassandra.auth import DSEGSSAPIAuthProvider + auth_provider = DSEGSSAPIAuthProvider(service='dse', qops=["auth"]) + cluster = Cluster(auth_provider=auth_provider) + session = cluster.connect() + +Implementations are :attr:`.DSEPlainTextAuthProvider`, :class:`.DSEGSSAPIAuthProvider` and :class:`.SaslAuthProvider`. + +DSE Unified Authentication +^^^^^^^^^^^^^^^^^^^^^^^^^^ + +With DSE (>=5.1), unified Authentication allows you to: + +* Proxy Login: Authenticate using a fixed set of authentication credentials but allow authorization of resources based another user id. +* Proxy Execute: Authenticate using a fixed set of authentication credentials but execute requests based on another user id. + +Proxy Login ++++++++++++ + +Proxy login allows you to authenticate with a user but act as another one. You need to ensure the authenticated user has the permission to use the authorization of resources of the other user. ie. this example will allow the `server` user to authenticate as usual but use the authorization of `user1`: + +.. code-block:: text + + GRANT PROXY.LOGIN on role user1 to server + +then you can do the proxy authentication.... + +.. code-block:: python + + from cassandra.cluster import Cluster + from cassandra.auth import SaslAuthProvider + + sasl_kwargs = { + "service": 'dse', + "mechanism":"PLAIN", + "username": 'server', + 'password': 'server', + 'authorization_id': 'user1' + } + + auth_provider = SaslAuthProvider(**sasl_kwargs) + c = Cluster(auth_provider=auth_provider) + s = c.connect() + s.execute(...) # all requests will be executed as 'user1' + +If you are using kerberos, you can use directly :class:`.DSEGSSAPIAuthProvider` and pass the authorization_id, like this: + +.. code-block:: python + + from cassandra.cluster import Cluster + from cassandra.auth import DSEGSSAPIAuthProvider + + # Ensure the kerberos ticket of the server user is set with the kinit utility. + auth_provider = DSEGSSAPIAuthProvider(service='dse', qops=["auth"], principal="server@DATASTAX.COM", + authorization_id='user1@DATASTAX.COM') + c = Cluster(auth_provider=auth_provider) + s = c.connect() + s.execute(...) # all requests will be executed as 'user1' + + +Proxy Execute ++++++++++++++ + +Proxy execute allows you to execute requests as another user than the authenticated one. You need to ensure the authenticated user has the permission to use the authorization of resources of the specified user. ie. this example will allow the `server` user to execute requests as `user1`: + +.. code-block:: text + + GRANT PROXY.EXECUTE on role user1 to server + +then you can do a proxy execute... + +.. code-block:: python + + from cassandra.cluster import Cluster + from cassandra.auth import DSEPlainTextAuthProvider, + + auth_provider = DSEPlainTextAuthProvider('server', 'server') + + c = Cluster(auth_provider=auth_provider) + s = c.connect() + s.execute('select * from k.t;', execute_as='user1') # the request will be executed as 'user1' + +Please see the `official documentation `_ for more details on the feature and configuration process. diff --git a/3.25.4-scylla/_sources/upgrading.rst.txt b/3.25.4-scylla/_sources/upgrading.rst.txt new file mode 100644 index 0000000000..9559fa3579 --- /dev/null +++ b/3.25.4-scylla/_sources/upgrading.rst.txt @@ -0,0 +1,388 @@ +Upgrading +========= + +.. toctree:: + :maxdepth: 1 + +Upgrading from dse-driver +------------------------- + +Since 3.21.0, scylla-driver fully supports DataStax products. dse-driver and +dse-graph users should now migrate to scylla-driver to benefit from latest bug fixes +and new features. The upgrade to this new unified driver version is straightforward +with no major API changes. + +Installation +^^^^^^^^^^^^ + +Only the `scylla-driver` package should be installed. `dse-driver` and `dse-graph` +are not required anymore:: + + pip install scylla-driver + +If you need the Graph *Fluent* API (features provided by dse-graph):: + + pip install scylla-driver[graph] + +See :doc:`installation` for more details. + +Import from the cassandra module +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +There is no `dse` module, so you should import from the `cassandra` module. You +need to change only the first module of your import statements, not the submodules. + +.. code-block:: python + + from dse.cluster import Cluster, EXEC_PROFILE_GRAPH_DEFAULT + from dse.auth import PlainTextAuthProvider + from dse.policies import WhiteListRoundRobinPolicy + + # becomes + + from cassandra.cluster import Cluster, EXEC_PROFILE_GRAPH_DEFAULT + from cassandra.auth import PlainTextAuthProvider + from cassandra.policies import WhiteListRoundRobinPolicy + +Also note that the cassandra.hosts module doesn't exist in scylla-driver. This +module is named cassandra.pool. + +dse-graph +^^^^^^^^^ + +dse-graph features are now built into scylla-driver. The only change you need +to do is your import statements: + +.. code-block:: python + + from dse_graph import .. + from dse_graph.query import .. + + # becomes + + from cassandra.datastax.graph.fluent import .. + from cassandra.datastax.graph.fluent.query import .. + +See :mod:`~.datastax.graph.fluent`. + +Session.execute and Session.execute_async API +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Although it is not common to use this API with positional arguments, it is +important to be aware that the `host` and `execute_as` parameters have had +their positional order swapped. This is only because `execute_as` was added +in dse-driver before `host`. + +See :meth:`.Session.execute`. + +Deprecations +^^^^^^^^^^^^ + +These changes are optional, but recommended: + +* Importing from `cassandra.graph` is deprecated. Consider importing from `cassandra.datastax.graph`. +* Use :class:`~.policies.DefaultLoadBalancingPolicy` instead of DSELoadBalancingPolicy. + +Upgrading to 3.0 +---------------- +Version 3.0 of the DataStax Python driver for Apache Cassandra +adds support for Cassandra 3.0 while maintaining support for +previously supported versions. In addition to substantial internal rework, +there are several updates to the API that integrators will need +to consider: + +Default consistency is now ``LOCAL_ONE`` +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Previous value was ``ONE``. The new value is introduced to mesh with the default +DC-aware load balancing policy and to match other drivers. + +Execution API Updates +^^^^^^^^^^^^^^^^^^^^^ +Result return normalization +~~~~~~~~~~~~~~~~~~~~~~~~~~~ +`PYTHON-368 `_ + +Previously results would be returned as a ``list`` of rows for result rows +up to ``fetch_size``, and ``PagedResult`` afterward. This could break +application code that assumed one type and got another. + +Now, all results are returned as an iterable :class:`~.ResultSet`. + +The preferred way to consume results of unknown size is to iterate through +them, letting automatic paging occur as they are consumed. + +.. code-block:: python + + results = session.execute("SELECT * FROM system.local") + for row in results: + process(row) + +If the expected size of the results is known, it is still possible to +materialize a list using the iterator: + +.. code-block:: python + + results = session.execute("SELECT * FROM system.local") + row_list = list(results) + +For backward compatibility, :class:`~.ResultSet` supports indexing. When +accessed at an index, a `~.ResultSet` object will materialize all its pages: + +.. code-block:: python + + results = session.execute("SELECT * FROM system.local") + first_result = results[0] # materializes results, fetching all pages + +This can send requests and load (possibly large) results into memory, so +`~.ResultSet` will log a warning on implicit materialization. + +Trace information is not attached to executed Statements +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +`PYTHON-318 `_ + +Previously trace data was attached to Statements if tracing was enabled. This +could lead to confusion if the same statement was used for multiple executions. + +Now, trace data is associated with the ``ResponseFuture`` and ``ResultSet`` +returned for each query: + +:meth:`.ResponseFuture.get_query_trace()` + +:meth:`.ResponseFuture.get_all_query_traces()` + +:meth:`.ResultSet.get_query_trace()` + +:meth:`.ResultSet.get_all_query_traces()` + +Binding named parameters now ignores extra names +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +`PYTHON-178 `_ + +Previously, :meth:`.BoundStatement.bind()` would raise if a mapping +was passed with extra names not found in the prepared statement. + +Behavior in 3.0+ is to ignore extra names. + +blist removed as soft dependency +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +`PYTHON-385 `_ + +Previously the driver had a soft dependency on ``blist sortedset``, using +that where available and using an internal fallback where possible. + +Now, the driver never chooses the ``blist`` variant, instead returning the +internal :class:`.util.SortedSet` for all ``set`` results. The class implements +all standard set operations, so no integration code should need to change unless +it explicitly checks for ``sortedset`` type. + +Metadata API Updates +^^^^^^^^^^^^^^^^^^^^ +`PYTHON-276 `_, `PYTHON-408 `_, `PYTHON-400 `_, `PYTHON-422 `_ + +Cassandra 3.0 brought a substantial overhaul to the internal schema metadata representation. +This version of the driver supports that metadata in addition to the legacy version. Doing so +also brought some changes to the metadata model. + +The present API is documented: :any:`cassandra.metadata`. Changes highlighted below: + +* All types are now exposed as CQL types instead of types derived from the internal server implementation +* Some metadata attributes have changed names to match current nomenclature (for example, :attr:`.Index.kind` in place of ``Index.type``). +* Some metadata attributes removed + + * ``TableMetadata.keyspace`` reference replaced with :attr:`.TableMetadata.keyspace_name` + * ``ColumnMetadata.index`` is removed table- and keyspace-level mappings are still maintained + +Several deprecated features are removed +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +`PYTHON-292 `_ + +* ``ResponseFuture.result`` timeout parameter is removed, use ``Session.execute`` timeout instead (`031ebb0 `_) +* ``Cluster.refresh_schema`` removed, use ``Cluster.refresh_*_metadata`` instead (`419fcdf `_) +* ``Cluster.submit_schema_refresh`` removed (`574266d `_) +* ``cqltypes`` time/date functions removed, use ``util`` entry points instead (`bb984ee `_) +* ``decoder`` module removed (`e16a073 `_) +* ``TableMetadata.keyspace`` attribute replaced with ``keyspace_name`` (`cc94073 `_) +* ``cqlengine.columns.TimeUUID.from_datetime`` removed, use ``util`` variant instead (`96489cc `_) +* ``cqlengine.columns.Float(double_precision)`` parameter removed, use ``columns.Double`` instead (`a2d3a98 `_) +* ``cqlengine`` keyspace management functions are removed in favor of the strategy-specific entry points (`4bd5909 `_) +* ``cqlengine.Model.__polymorphic_*__`` attributes removed, use ``__discriminator*`` attributes instead (`9d98c8e `_) +* ``cqlengine.statements`` will no longer warn about list list prepend behavior (`79efe97 `_) + + +Upgrading to 2.1 from 2.0 +------------------------- +Version 2.1 of the DataStax Python driver for Apache Cassandra +adds support for Cassandra 2.1 and version 3 of the native protocol. + +Cassandra 1.2, 2.0, and 2.1 are all supported. However, 1.2 only +supports protocol version 1, and 2.0 only supports versions 1 and +2, so some features may not be available. + +Using the v3 Native Protocol +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +By default, the driver will attempt to use version 2 of the +native protocol. To use version 3, you must explicitly +set the :attr:`~.Cluster.protocol_version`: + +.. code-block:: python + + from cassandra.cluster import Cluster + + cluster = Cluster(protocol_version=3) + +Note that protocol version 3 is only supported by Cassandra 2.1+. + +In future releases, the driver may default to using protocol version +3. + +Working with User-Defined Types +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Cassandra 2.1 introduced the ability to define new types:: + + USE KEYSPACE mykeyspace; + + CREATE TYPE address (street text, city text, zip int); + +The driver generally expects you to use instances of a specific +class to represent column values of this type. You can let the +driver know what class to use with :meth:`.Cluster.register_user_type`: + +.. code-block:: python + + cluster = Cluster() + + class Address(object): + + def __init__(self, street, city, zipcode): + self.street = street + self.city = text + self.zipcode = zipcode + + cluster.register_user_type('mykeyspace', 'address', Address) + +When inserting data for ``address`` columns, you should pass in +instances of ``Address``. When querying data, ``address`` column +values will be instances of ``Address``. + +If no class is registered for a user-defined type, query results +will use a ``namedtuple`` class and data may only be inserted +though prepared statements. + +See :ref:`udts` for more details. + +Customizing Encoders for Non-prepared Statements +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Starting with version 2.1 of the driver, it is possible to customize +how Python types are converted to CQL literals when working with +non-prepared statements. This is done on a per-:class:`~.Session` +basis through :attr:`.Session.encoder`: + +.. code-block:: python + + cluster = Cluster() + session = cluster.connect() + session.encoder.mapping[tuple] = session.encoder.cql_encode_tuple + +See :ref:`type-conversions` for the table of default CQL literal conversions. + +Using Client-Side Protocol-Level Timestamps +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +With version 3 of the native protocol, timestamps may be supplied by the +client at the protocol level. (Normally, if they are not specified within +the CQL query itself, a timestamp is generated server-side.) + +When :attr:`~.Cluster.protocol_version` is set to 3 or higher, the driver +will automatically use client-side timestamps with microsecond precision +unless :attr:`.Session.use_client_timestamp` is changed to :const:`False`. +If a timestamp is specified within the CQL query, it will override the +timestamp generated by the driver. + +Upgrading to 2.0 from 1.x +------------------------- +Version 2.0 of the DataStax Python driver for Apache Cassandra +includes some notable improvements over version 1.x. This version +of the driver supports Cassandra 1.2, 2.0, and 2.1. However, not +all features may be used with Cassandra 1.2, and some new features +in 2.1 are not yet supported. + +Using the v2 Native Protocol +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +By default, the driver will attempt to use version 2 of Cassandra's +native protocol. You can explicitly set the protocol version to +2, though: + +.. code-block:: python + + from cassandra.cluster import Cluster + + cluster = Cluster(protocol_version=2) + +When working with Cassandra 1.2, you will need to +explicitly set the :attr:`~.Cluster.protocol_version` to 1: + +.. code-block:: python + + from cassandra.cluster import Cluster + + cluster = Cluster(protocol_version=1) + +Automatic Query Paging +^^^^^^^^^^^^^^^^^^^^^^ +Version 2 of the native protocol adds support for automatic query +paging, which can make dealing with large result sets much simpler. + +See :ref:`query-paging` for full details. + +Protocol-Level Batch Statements +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +With version 1 of the native protocol, batching of statements required +using a `BATCH cql query `_. +With version 2 of the native protocol, you can now batch statements at +the protocol level. This allows you to use many different prepared +statements within a single batch. + +See :class:`~.query.BatchStatement` for details and usage examples. + +SASL-based Authentication +^^^^^^^^^^^^^^^^^^^^^^^^^ +Also new in version 2 of the native protocol is SASL-based authentication. +See the section on :ref:`security` for details and examples. + +Lightweight Transactions +^^^^^^^^^^^^^^^^^^^^^^^^ +`Lightweight transactions `_ are another new feature. To use lightweight transactions, add ``IF`` clauses +to your CQL queries and set the :attr:`~.Statement.serial_consistency_level` +on your statements. + +Calling Cluster.shutdown() +^^^^^^^^^^^^^^^^^^^^^^^^^^ +In order to fix some issues around garbage collection and unclean interpreter +shutdowns, version 2.0 of the driver requires you to call :meth:`.Cluster.shutdown()` +on your :class:`~.Cluster` objects when you are through with them. +This helps to guarantee a clean shutdown. + +Deprecations +^^^^^^^^^^^^ +The following functions have moved from ``cassandra.decoder`` to ``cassandra.query``. +The original functions have been left in place with a :exc:`DeprecationWarning` for +now: + +* :attr:`cassandra.decoder.tuple_factory` has moved to + :attr:`cassandra.query.tuple_factory` +* :attr:`cassandra.decoder.named_tuple_factory` has moved to + :attr:`cassandra.query.named_tuple_factory` +* :attr:`cassandra.decoder.dict_factory` has moved to + :attr:`cassandra.query.dict_factory` +* :attr:`cassandra.decoder.ordered_dict_factory` has moved to + :attr:`cassandra.query.ordered_dict_factory` + +Dependency Changes +^^^^^^^^^^^^^^^^^^ +The following dependencies have officially been made optional: + +* ``scales`` +* ``blist`` + +And one new dependency has been added (to enable Python 3 support): + +* ``six`` diff --git a/3.25.4-scylla/_sources/user_defined_types.rst.txt b/3.25.4-scylla/_sources/user_defined_types.rst.txt new file mode 100644 index 0000000000..32c03e37e8 --- /dev/null +++ b/3.25.4-scylla/_sources/user_defined_types.rst.txt @@ -0,0 +1,118 @@ +.. _udts: + +User Defined Types +================== +Cassandra 2.1 introduced user-defined types (UDTs). You can create a +new type through ``CREATE TYPE`` statements in CQL:: + + CREATE TYPE address (street text, zip int); + +Version 2.1 of the Python driver adds support for user-defined types. + +Registering a UDT +----------------- +You can tell the Python driver to return columns of a specific UDT as +instances of a class or a dict by registering them with your :class:`~.Cluster` +instance through :meth:`.Cluster.register_user_type`: + + +Map a Class to a UDT +++++++++++++++++++++ + +.. code-block:: python + + cluster = Cluster(protocol_version=3) + session = cluster.connect() + session.set_keyspace('mykeyspace') + session.execute("CREATE TYPE address (street text, zipcode int)") + session.execute("CREATE TABLE users (id int PRIMARY KEY, location frozen
)") + + # create a class to map to the "address" UDT + class Address(object): + + def __init__(self, street, zipcode): + self.street = street + self.zipcode = zipcode + + cluster.register_user_type('mykeyspace', 'address', Address) + + # insert a row using an instance of Address + session.execute("INSERT INTO users (id, location) VALUES (%s, %s)", + (0, Address("123 Main St.", 78723))) + + # results will include Address instances + results = session.execute("SELECT * FROM users") + row = results[0] + print(row.id, row.location.street, row.location.zipcode) + +Map a dict to a UDT ++++++++++++++++++++ + +.. code-block:: python + + cluster = Cluster(protocol_version=3) + session = cluster.connect() + session.set_keyspace('mykeyspace') + session.execute("CREATE TYPE address (street text, zipcode int)") + session.execute("CREATE TABLE users (id int PRIMARY KEY, location frozen
)") + + cluster.register_user_type('mykeyspace', 'address', dict) + + # insert a row using a prepared statement and a tuple + insert_statement = session.prepare("INSERT INTO mykeyspace.users (id, location) VALUES (?, ?)") + session.execute(insert_statement, [0, ("123 Main St.", 78723)]) + + # results will include dict instances + results = session.execute("SELECT * FROM users") + row = results[0] + print(row.id, row.location['street'], row.location['zipcode']) + +Using UDTs Without Registering Them +----------------------------------- +Although it is recommended to register your types with +:meth:`.Cluster.register_user_type`, the driver gives you some options +for working with unregistered UDTS. + +When you use prepared statements, the driver knows what data types to +expect for each placeholder. This allows you to pass any object you +want for a UDT, as long as it has attributes that match the field names +for the UDT: + +.. code-block:: python + + cluster = Cluster(protocol_version=3) + session = cluster.connect() + session.set_keyspace('mykeyspace') + session.execute("CREATE TYPE address (street text, zipcode int)") + session.execute("CREATE TABLE users (id int PRIMARY KEY, location frozen
)") + + class Foo(object): + + def __init__(self, street, zipcode, otherstuff): + self.street = street + self.zipcode = zipcode + self.otherstuff = otherstuff + + insert_statement = session.prepare("INSERT INTO users (id, location) VALUES (?, ?)") + + # since we're using a prepared statement, we don't *have* to register + # a class to map to the UDT to insert data. The object just needs to have + # "street" and "zipcode" attributes (which Foo does): + session.execute(insert_statement, [0, Foo("123 Main St.", 78723, "some other stuff")]) + + # when we query data, UDT columns that don't have a class registered + # will be returned as namedtuples: + results = session.execute("SELECT * FROM users") + first_row = results[0] + address = first_row.location + print(address) # prints "Address(street='123 Main St.', zipcode=78723)" + street = address.street + zipcode = address.street + +As shown in the code example, inserting data for UDT columns without registering +a class works fine for prepared statements. However, **you must register a +class to insert UDT columns with unprepared statements**.\* You can still query +UDT columns without registered classes using unprepared statements, they will +simply return ``namedtuple`` instances (just like prepared statements do). + +\* this applies to *parameterized* unprepared statements, in which the driver will be formatting parameters -- not statements with interpolated UDT literals. diff --git a/3.25.4-scylla/_static/basic.css b/3.25.4-scylla/_static/basic.css new file mode 100644 index 0000000000..603f6a8798 --- /dev/null +++ b/3.25.4-scylla/_static/basic.css @@ -0,0 +1,905 @@ +/* + * basic.css + * ~~~~~~~~~ + * + * Sphinx stylesheet -- basic theme. + * + * :copyright: Copyright 2007-2021 by the Sphinx team, see AUTHORS. + * :license: BSD, see LICENSE for details. + * + */ + +/* -- main layout ----------------------------------------------------------- */ + +div.clearer { + clear: both; +} + +div.section::after { + display: block; + content: ''; + clear: left; +} + +/* -- relbar ---------------------------------------------------------------- */ + +div.related { + width: 100%; + font-size: 90%; +} + +div.related h3 { + display: none; +} + +div.related ul { + margin: 0; + padding: 0 0 0 10px; + list-style: none; +} + +div.related li { + display: inline; +} + +div.related li.right { + float: right; + margin-right: 5px; +} + +/* -- sidebar --------------------------------------------------------------- */ + +div.sphinxsidebarwrapper { + padding: 10px 5px 0 10px; +} + +div.sphinxsidebar { + float: left; + width: 230px; + margin-left: -100%; + font-size: 90%; + word-wrap: break-word; + overflow-wrap : break-word; +} + +div.sphinxsidebar ul { + list-style: none; +} + +div.sphinxsidebar ul ul, +div.sphinxsidebar ul.want-points { + margin-left: 20px; + list-style: square; +} + +div.sphinxsidebar ul ul { + margin-top: 0; + margin-bottom: 0; +} + +div.sphinxsidebar form { + margin-top: 10px; +} + +div.sphinxsidebar input { + border: 1px solid #98dbcc; + font-family: sans-serif; + font-size: 1em; +} + +div.sphinxsidebar #searchbox form.search { + overflow: hidden; +} + +div.sphinxsidebar #searchbox input[type="text"] { + float: left; + width: 80%; + padding: 0.25em; + box-sizing: border-box; +} + +div.sphinxsidebar #searchbox input[type="submit"] { + float: left; + width: 20%; + border-left: none; + padding: 0.25em; + box-sizing: border-box; +} + + +img { + border: 0; + max-width: 100%; +} + +/* -- search page ----------------------------------------------------------- */ + +ul.search { + margin: 10px 0 0 20px; + padding: 0; +} + +ul.search li { + padding: 5px 0 5px 20px; + background-image: url(file.png); + background-repeat: no-repeat; + background-position: 0 7px; +} + +ul.search li a { + font-weight: bold; +} + +ul.search li p.context { + color: #888; + margin: 2px 0 0 30px; + text-align: left; +} + +ul.keywordmatches li.goodmatch a { + font-weight: bold; +} + +/* -- index page ------------------------------------------------------------ */ + +table.contentstable { + width: 90%; + margin-left: auto; + margin-right: auto; +} + +table.contentstable p.biglink { + line-height: 150%; +} + +a.biglink { + font-size: 1.3em; +} + +span.linkdescr { + font-style: italic; + padding-top: 5px; + font-size: 90%; +} + +/* -- general index --------------------------------------------------------- */ + +table.indextable { + width: 100%; +} + +table.indextable td { + text-align: left; + vertical-align: top; +} + +table.indextable ul { + margin-top: 0; + margin-bottom: 0; + list-style-type: none; +} + +table.indextable > tbody > tr > td > ul { + padding-left: 0em; +} + +table.indextable tr.pcap { + height: 10px; +} + +table.indextable tr.cap { + margin-top: 10px; + background-color: #f2f2f2; +} + +img.toggler { + margin-right: 3px; + margin-top: 3px; + cursor: pointer; +} + +div.modindex-jumpbox { + border-top: 1px solid #ddd; + border-bottom: 1px solid #ddd; + margin: 1em 0 1em 0; + padding: 0.4em; +} + +div.genindex-jumpbox { + border-top: 1px solid #ddd; + border-bottom: 1px solid #ddd; + margin: 1em 0 1em 0; + padding: 0.4em; +} + +/* -- domain module index --------------------------------------------------- */ + +table.modindextable td { + padding: 2px; + border-collapse: collapse; +} + +/* -- general body styles --------------------------------------------------- */ + +div.body { + min-width: 450px; + max-width: 800px; +} + +div.body p, div.body dd, div.body li, div.body blockquote { + -moz-hyphens: auto; + -ms-hyphens: auto; + -webkit-hyphens: auto; + hyphens: auto; +} + +a.headerlink { + visibility: hidden; +} + +a.brackets:before, +span.brackets > a:before{ + content: "["; +} + +a.brackets:after, +span.brackets > a:after { + content: "]"; +} + +h1:hover > a.headerlink, +h2:hover > a.headerlink, +h3:hover > a.headerlink, +h4:hover > a.headerlink, +h5:hover > a.headerlink, +h6:hover > a.headerlink, +dt:hover > a.headerlink, +caption:hover > a.headerlink, +p.caption:hover > a.headerlink, +div.code-block-caption:hover > a.headerlink { + visibility: visible; +} + +div.body p.caption { + text-align: inherit; +} + +div.body td { + text-align: left; +} + +.first { + margin-top: 0 !important; +} + +p.rubric { + margin-top: 30px; + font-weight: bold; +} + +img.align-left, figure.align-left, .figure.align-left, object.align-left { + clear: left; + float: left; + margin-right: 1em; +} + +img.align-right, figure.align-right, .figure.align-right, object.align-right { + clear: right; + float: right; + margin-left: 1em; +} + +img.align-center, figure.align-center, .figure.align-center, object.align-center { + display: block; + margin-left: auto; + margin-right: auto; +} + +img.align-default, figure.align-default, .figure.align-default { + display: block; + margin-left: auto; + margin-right: auto; +} + +.align-left { + text-align: left; +} + +.align-center { + text-align: center; +} + +.align-default { + text-align: center; +} + +.align-right { + text-align: right; +} + +/* -- sidebars -------------------------------------------------------------- */ + +div.sidebar, +aside.sidebar { + margin: 0 0 0.5em 1em; + border: 1px solid #ddb; + padding: 7px; + background-color: #ffe; + width: 40%; + float: right; + clear: right; + overflow-x: auto; +} + +p.sidebar-title { + font-weight: bold; +} + +div.admonition, div.topic, blockquote { + clear: left; +} + +/* -- topics ---------------------------------------------------------------- */ + +div.topic { + border: 1px solid #ccc; + padding: 7px; + margin: 10px 0 10px 0; +} + +p.topic-title { + font-size: 1.1em; + font-weight: bold; + margin-top: 10px; +} + +/* -- admonitions ----------------------------------------------------------- */ + +div.admonition { + margin-top: 10px; + margin-bottom: 10px; + padding: 7px; +} + +div.admonition dt { + font-weight: bold; +} + +p.admonition-title { + margin: 0px 10px 5px 0px; + font-weight: bold; +} + +div.body p.centered { + text-align: center; + margin-top: 25px; +} + +/* -- content of sidebars/topics/admonitions -------------------------------- */ + +div.sidebar > :last-child, +aside.sidebar > :last-child, +div.topic > :last-child, +div.admonition > :last-child { + margin-bottom: 0; +} + +div.sidebar::after, +aside.sidebar::after, +div.topic::after, +div.admonition::after, +blockquote::after { + display: block; + content: ''; + clear: both; +} + +/* -- tables ---------------------------------------------------------------- */ + +table.docutils { + margin-top: 10px; + margin-bottom: 10px; + border: 0; + border-collapse: collapse; +} + +table.align-center { + margin-left: auto; + margin-right: auto; +} + +table.align-default { + margin-left: auto; + margin-right: auto; +} + +table caption span.caption-number { + font-style: italic; +} + +table caption span.caption-text { +} + +table.docutils td, table.docutils th { + padding: 1px 8px 1px 5px; + border-top: 0; + border-left: 0; + border-right: 0; + border-bottom: 1px solid #aaa; +} + +table.footnote td, table.footnote th { + border: 0 !important; +} + +th { + text-align: left; + padding-right: 5px; +} + +table.citation { + border-left: solid 1px gray; + margin-left: 1px; +} + +table.citation td { + border-bottom: none; +} + +th > :first-child, +td > :first-child { + margin-top: 0px; +} + +th > :last-child, +td > :last-child { + margin-bottom: 0px; +} + +/* -- figures --------------------------------------------------------------- */ + +div.figure, figure { + margin: 0.5em; + padding: 0.5em; +} + +div.figure p.caption, figcaption { + padding: 0.3em; +} + +div.figure p.caption span.caption-number, +figcaption span.caption-number { + font-style: italic; +} + +div.figure p.caption span.caption-text, +figcaption span.caption-text { +} + +/* -- field list styles ----------------------------------------------------- */ + +table.field-list td, table.field-list th { + border: 0 !important; +} + +.field-list ul { + margin: 0; + padding-left: 1em; +} + +.field-list p { + margin: 0; +} + +.field-name { + -moz-hyphens: manual; + -ms-hyphens: manual; + -webkit-hyphens: manual; + hyphens: manual; +} + +/* -- hlist styles ---------------------------------------------------------- */ + +table.hlist { + margin: 1em 0; +} + +table.hlist td { + vertical-align: top; +} + +/* -- object description styles --------------------------------------------- */ + +.sig { + font-family: 'Consolas', 'Menlo', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace; +} + +.sig-name, code.descname { + background-color: transparent; + font-weight: bold; +} + +.sig-name { + font-size: 1.1em; +} + +code.descname { + font-size: 1.2em; +} + +.sig-prename, code.descclassname { + background-color: transparent; +} + +.optional { + font-size: 1.3em; +} + +.sig-paren { + font-size: larger; +} + +.sig-param.n { + font-style: italic; +} + +/* C++ specific styling */ + +.sig-inline.c-texpr, +.sig-inline.cpp-texpr { + font-family: unset; +} + +.sig.c .k, .sig.c .kt, +.sig.cpp .k, .sig.cpp .kt { + color: #0033B3; +} + +.sig.c .m, +.sig.cpp .m { + color: #1750EB; +} + +.sig.c .s, .sig.c .sc, +.sig.cpp .s, .sig.cpp .sc { + color: #067D17; +} + + +/* -- other body styles ----------------------------------------------------- */ + +ol.arabic { + list-style: decimal; +} + +ol.loweralpha { + list-style: lower-alpha; +} + +ol.upperalpha { + list-style: upper-alpha; +} + +ol.lowerroman { + list-style: lower-roman; +} + +ol.upperroman { + list-style: upper-roman; +} + +:not(li) > ol > li:first-child > :first-child, +:not(li) > ul > li:first-child > :first-child { + margin-top: 0px; +} + +:not(li) > ol > li:last-child > :last-child, +:not(li) > ul > li:last-child > :last-child { + margin-bottom: 0px; +} + +ol.simple ol p, +ol.simple ul p, +ul.simple ol p, +ul.simple ul p { + margin-top: 0; +} + +ol.simple > li:not(:first-child) > p, +ul.simple > li:not(:first-child) > p { + margin-top: 0; +} + +ol.simple p, +ul.simple p { + margin-bottom: 0; +} + +dl.footnote > dt, +dl.citation > dt { + float: left; + margin-right: 0.5em; +} + +dl.footnote > dd, +dl.citation > dd { + margin-bottom: 0em; +} + +dl.footnote > dd:after, +dl.citation > dd:after { + content: ""; + clear: both; +} + +dl.field-list { + display: grid; + grid-template-columns: fit-content(30%) auto; +} + +dl.field-list > dt { + font-weight: bold; + word-break: break-word; + padding-left: 0.5em; + padding-right: 5px; +} + +dl.field-list > dt:after { + content: ":"; +} + +dl.field-list > dd { + padding-left: 0.5em; + margin-top: 0em; + margin-left: 0em; + margin-bottom: 0em; +} + +dl { + margin-bottom: 15px; +} + +dd > :first-child { + margin-top: 0px; +} + +dd ul, dd table { + margin-bottom: 10px; +} + +dd { + margin-top: 3px; + margin-bottom: 10px; + margin-left: 30px; +} + +dl > dd:last-child, +dl > dd:last-child > :last-child { + margin-bottom: 0; +} + +dt:target, span.highlighted { + background-color: #fbe54e; +} + +rect.highlighted { + fill: #fbe54e; +} + +dl.glossary dt { + font-weight: bold; + font-size: 1.1em; +} + +.versionmodified { + font-style: italic; +} + +.system-message { + background-color: #fda; + padding: 5px; + border: 3px solid red; +} + +.footnote:target { + background-color: #ffa; +} + +.line-block { + display: block; + margin-top: 1em; + margin-bottom: 1em; +} + +.line-block .line-block { + margin-top: 0; + margin-bottom: 0; + margin-left: 1.5em; +} + +.guilabel, .menuselection { + font-family: sans-serif; +} + +.accelerator { + text-decoration: underline; +} + +.classifier { + font-style: oblique; +} + +.classifier:before { + font-style: normal; + margin: 0 0.5em; + content: ":"; + display: inline-block; +} + +abbr, acronym { + border-bottom: dotted 1px; + cursor: help; +} + +/* -- code displays --------------------------------------------------------- */ + +pre { + overflow: auto; + overflow-y: hidden; /* fixes display issues on Chrome browsers */ +} + +pre, div[class*="highlight-"] { + clear: both; +} + +span.pre { + -moz-hyphens: none; + -ms-hyphens: none; + -webkit-hyphens: none; + hyphens: none; +} + +div[class*="highlight-"] { + margin: 1em 0; +} + +td.linenos pre { + border: 0; + background-color: transparent; + color: #aaa; +} + +table.highlighttable { + display: block; +} + +table.highlighttable tbody { + display: block; +} + +table.highlighttable tr { + display: flex; +} + +table.highlighttable td { + margin: 0; + padding: 0; +} + +table.highlighttable td.linenos { + padding-right: 0.5em; +} + +table.highlighttable td.code { + flex: 1; + overflow: hidden; +} + +.highlight .hll { + display: block; +} + +div.highlight pre, +table.highlighttable pre { + margin: 0; +} + +div.code-block-caption + div { + margin-top: 0; +} + +div.code-block-caption { + margin-top: 1em; + padding: 2px 5px; + font-size: small; +} + +div.code-block-caption code { + background-color: transparent; +} + +table.highlighttable td.linenos, +span.linenos, +div.highlight span.gp { /* gp: Generic.Prompt */ + user-select: none; + -webkit-user-select: text; /* Safari fallback only */ + -webkit-user-select: none; /* Chrome/Safari */ + -moz-user-select: none; /* Firefox */ + -ms-user-select: none; /* IE10+ */ +} + +div.code-block-caption span.caption-number { + padding: 0.1em 0.3em; + font-style: italic; +} + +div.code-block-caption span.caption-text { +} + +div.literal-block-wrapper { + margin: 1em 0; +} + +code.xref, a code { + background-color: transparent; + font-weight: bold; +} + +h1 code, h2 code, h3 code, h4 code, h5 code, h6 code { + background-color: transparent; +} + +.viewcode-link { + float: right; +} + +.viewcode-back { + float: right; + font-family: sans-serif; +} + +div.viewcode-block:target { + margin: -1px -10px; + padding: 0 10px; +} + +/* -- math display ---------------------------------------------------------- */ + +img.math { + vertical-align: middle; +} + +div.body div.math p { + text-align: center; +} + +span.eqno { + float: right; +} + +span.eqno a.headerlink { + position: absolute; + z-index: 1; +} + +div.math:hover a.headerlink { + visibility: visible; +} + +/* -- printout stylesheet --------------------------------------------------- */ + +@media print { + div.document, + div.documentwrapper, + div.bodywrapper { + margin: 0 !important; + width: 100%; + } + + div.sphinxsidebar, + div.related, + div.footer, + #top-link { + display: none; + } +} \ No newline at end of file diff --git a/3.25.4-scylla/_static/check-solid.svg b/3.25.4-scylla/_static/check-solid.svg new file mode 100644 index 0000000000..92fad4b5c0 --- /dev/null +++ b/3.25.4-scylla/_static/check-solid.svg @@ -0,0 +1,4 @@ + + + + diff --git a/3.25.4-scylla/_static/clipboard.min.js b/3.25.4-scylla/_static/clipboard.min.js new file mode 100644 index 0000000000..54b3c46381 --- /dev/null +++ b/3.25.4-scylla/_static/clipboard.min.js @@ -0,0 +1,7 @@ +/*! + * clipboard.js v2.0.8 + * https://clipboardjs.com/ + * + * Licensed MIT © Zeno Rocha + */ +!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?exports.ClipboardJS=e():t.ClipboardJS=e()}(this,function(){return n={686:function(t,e,n){"use strict";n.d(e,{default:function(){return o}});var e=n(279),i=n.n(e),e=n(370),u=n.n(e),e=n(817),c=n.n(e);function a(t){try{return document.execCommand(t)}catch(t){return}}var f=function(t){t=c()(t);return a("cut"),t};var l=function(t){var e,n,o,r=1 + + + + diff --git a/3.25.4-scylla/_static/copybutton.css b/3.25.4-scylla/_static/copybutton.css new file mode 100644 index 0000000000..f1916ec7d1 --- /dev/null +++ b/3.25.4-scylla/_static/copybutton.css @@ -0,0 +1,94 @@ +/* Copy buttons */ +button.copybtn { + position: absolute; + display: flex; + top: .3em; + right: .3em; + width: 1.7em; + height: 1.7em; + opacity: 0; + transition: opacity 0.3s, border .3s, background-color .3s; + user-select: none; + padding: 0; + border: none; + outline: none; + border-radius: 0.4em; + /* The colors that GitHub uses */ + border: #1b1f2426 1px solid; + background-color: #f6f8fa; + color: #57606a; +} + +button.copybtn.success { + border-color: #22863a; + color: #22863a; +} + +button.copybtn svg { + stroke: currentColor; + width: 1.5em; + height: 1.5em; + padding: 0.1em; +} + +div.highlight { + position: relative; +} + +/* Show the copybutton */ +.highlight:hover button.copybtn, button.copybtn.success { + opacity: 1; +} + +.highlight button.copybtn:hover { + background-color: rgb(235, 235, 235); +} + +.highlight button.copybtn:active { + background-color: rgb(187, 187, 187); +} + +/** + * A minimal CSS-only tooltip copied from: + * https://codepen.io/mildrenben/pen/rVBrpK + * + * To use, write HTML like the following: + * + *

Short

+ */ + .o-tooltip--left { + position: relative; + } + + .o-tooltip--left:after { + opacity: 0; + visibility: hidden; + position: absolute; + content: attr(data-tooltip); + padding: .2em; + font-size: .8em; + left: -.2em; + background: grey; + color: white; + white-space: nowrap; + z-index: 2; + border-radius: 2px; + transform: translateX(-102%) translateY(0); + transition: opacity 0.2s cubic-bezier(0.64, 0.09, 0.08, 1), transform 0.2s cubic-bezier(0.64, 0.09, 0.08, 1); +} + +.o-tooltip--left:hover:after { + display: block; + opacity: 1; + visibility: visible; + transform: translateX(-100%) translateY(0); + transition: opacity 0.2s cubic-bezier(0.64, 0.09, 0.08, 1), transform 0.2s cubic-bezier(0.64, 0.09, 0.08, 1); + transition-delay: .5s; +} + +/* By default the copy button shouldn't show up when printing a page */ +@media print { + button.copybtn { + display: none; + } +} diff --git a/3.25.4-scylla/_static/copybutton.js b/3.25.4-scylla/_static/copybutton.js new file mode 100644 index 0000000000..2ea7ff3e21 --- /dev/null +++ b/3.25.4-scylla/_static/copybutton.js @@ -0,0 +1,248 @@ +// Localization support +const messages = { + 'en': { + 'copy': 'Copy', + 'copy_to_clipboard': 'Copy to clipboard', + 'copy_success': 'Copied!', + 'copy_failure': 'Failed to copy', + }, + 'es' : { + 'copy': 'Copiar', + 'copy_to_clipboard': 'Copiar al portapapeles', + 'copy_success': '¡Copiado!', + 'copy_failure': 'Error al copiar', + }, + 'de' : { + 'copy': 'Kopieren', + 'copy_to_clipboard': 'In die Zwischenablage kopieren', + 'copy_success': 'Kopiert!', + 'copy_failure': 'Fehler beim Kopieren', + }, + 'fr' : { + 'copy': 'Copier', + 'copy_to_clipboard': 'Copier dans le presse-papier', + 'copy_success': 'Copié !', + 'copy_failure': 'Échec de la copie', + }, + 'ru': { + 'copy': 'Скопировать', + 'copy_to_clipboard': 'Скопировать в буфер', + 'copy_success': 'Скопировано!', + 'copy_failure': 'Не удалось скопировать', + }, + 'zh-CN': { + 'copy': '复制', + 'copy_to_clipboard': '复制到剪贴板', + 'copy_success': '复制成功!', + 'copy_failure': '复制失败', + }, + 'it' : { + 'copy': 'Copiare', + 'copy_to_clipboard': 'Copiato negli appunti', + 'copy_success': 'Copiato!', + 'copy_failure': 'Errore durante la copia', + } +} + +let locale = 'en' +if( document.documentElement.lang !== undefined + && messages[document.documentElement.lang] !== undefined ) { + locale = document.documentElement.lang +} + +let doc_url_root = DOCUMENTATION_OPTIONS.URL_ROOT; +if (doc_url_root == '#') { + doc_url_root = ''; +} + +/** + * SVG files for our copy buttons + */ +let iconCheck = ` + ${messages[locale]['copy_success']} + + +` + +// If the user specified their own SVG use that, otherwise use the default +let iconCopy = ``; +if (!iconCopy) { + iconCopy = ` + ${messages[locale]['copy_to_clipboard']} + + + +` +} + +/** + * Set up copy/paste for code blocks + */ + +const runWhenDOMLoaded = cb => { + if (document.readyState != 'loading') { + cb() + } else if (document.addEventListener) { + document.addEventListener('DOMContentLoaded', cb) + } else { + document.attachEvent('onreadystatechange', function() { + if (document.readyState == 'complete') cb() + }) + } +} + +const codeCellId = index => `codecell${index}` + +// Clears selected text since ClipboardJS will select the text when copying +const clearSelection = () => { + if (window.getSelection) { + window.getSelection().removeAllRanges() + } else if (document.selection) { + document.selection.empty() + } +} + +// Changes tooltip text for a moment, then changes it back +// We want the timeout of our `success` class to be a bit shorter than the +// tooltip and icon change, so that we can hide the icon before changing back. +var timeoutIcon = 2000; +var timeoutSuccessClass = 1500; + +const temporarilyChangeTooltip = (el, oldText, newText) => { + el.setAttribute('data-tooltip', newText) + el.classList.add('success') + // Remove success a little bit sooner than we change the tooltip + // So that we can use CSS to hide the copybutton first + setTimeout(() => el.classList.remove('success'), timeoutSuccessClass) + setTimeout(() => el.setAttribute('data-tooltip', oldText), timeoutIcon) +} + +// Changes the copy button icon for two seconds, then changes it back +const temporarilyChangeIcon = (el) => { + el.innerHTML = iconCheck; + setTimeout(() => {el.innerHTML = iconCopy}, timeoutIcon) +} + +const addCopyButtonToCodeCells = () => { + // If ClipboardJS hasn't loaded, wait a bit and try again. This + // happens because we load ClipboardJS asynchronously. + if (window.ClipboardJS === undefined) { + setTimeout(addCopyButtonToCodeCells, 250) + return + } + + // Add copybuttons to all of our code cells + const COPYBUTTON_SELECTOR = 'div.highlight pre'; + const codeCells = document.querySelectorAll(COPYBUTTON_SELECTOR) + codeCells.forEach((codeCell, index) => { + const id = codeCellId(index) + codeCell.setAttribute('id', id) + + const clipboardButton = id => + `` + codeCell.insertAdjacentHTML('afterend', clipboardButton(id)) + }) + +function escapeRegExp(string) { + return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string +} + +/** + * Removes excluded text from a Node. + * + * @param {Node} target Node to filter. + * @param {string} exclude CSS selector of nodes to exclude. + * @returns {DOMString} Text from `target` with text removed. + */ +function filterText(target, exclude) { + const clone = target.cloneNode(true); // clone as to not modify the live DOM + if (exclude) { + // remove excluded nodes + clone.querySelectorAll(exclude).forEach(node => node.remove()); + } + return clone.innerText; +} + +// Callback when a copy button is clicked. Will be passed the node that was clicked +// should then grab the text and replace pieces of text that shouldn't be used in output +function formatCopyText(textContent, copybuttonPromptText, isRegexp = false, onlyCopyPromptLines = true, removePrompts = true, copyEmptyLines = true, lineContinuationChar = "", hereDocDelim = "") { + var regexp; + var match; + + // Do we check for line continuation characters and "HERE-documents"? + var useLineCont = !!lineContinuationChar + var useHereDoc = !!hereDocDelim + + // create regexp to capture prompt and remaining line + if (isRegexp) { + regexp = new RegExp('^(' + copybuttonPromptText + ')(.*)') + } else { + regexp = new RegExp('^(' + escapeRegExp(copybuttonPromptText) + ')(.*)') + } + + const outputLines = []; + var promptFound = false; + var gotLineCont = false; + var gotHereDoc = false; + const lineGotPrompt = []; + for (const line of textContent.split('\n')) { + match = line.match(regexp) + if (match || gotLineCont || gotHereDoc) { + promptFound = regexp.test(line) + lineGotPrompt.push(promptFound) + if (removePrompts && promptFound) { + outputLines.push(match[2]) + } else { + outputLines.push(line) + } + gotLineCont = line.endsWith(lineContinuationChar) & useLineCont + if (line.includes(hereDocDelim) & useHereDoc) + gotHereDoc = !gotHereDoc + } else if (!onlyCopyPromptLines) { + outputLines.push(line) + } else if (copyEmptyLines && line.trim() === '') { + outputLines.push(line) + } + } + + // If no lines with the prompt were found then just use original lines + if (lineGotPrompt.some(v => v === true)) { + textContent = outputLines.join('\n'); + } + + // Remove a trailing newline to avoid auto-running when pasting + if (textContent.endsWith("\n")) { + textContent = textContent.slice(0, -1) + } + return textContent +} + + +var copyTargetText = (trigger) => { + var target = document.querySelector(trigger.attributes['data-clipboard-target'].value); + + // get filtered text + let exclude = '.linenos'; + + let text = filterText(target, exclude); + return formatCopyText(text, '', false, true, true, true, '', '') +} + + // Initialize with a callback so we can modify the text before copy + const clipboard = new ClipboardJS('.copybtn', {text: copyTargetText}) + + // Update UI with error/success messages + clipboard.on('success', event => { + clearSelection() + temporarilyChangeTooltip(event.trigger, messages[locale]['copy'], messages[locale]['copy_success']) + temporarilyChangeIcon(event.trigger) + }) + + clipboard.on('error', event => { + temporarilyChangeTooltip(event.trigger, messages[locale]['copy'], messages[locale]['copy_failure']) + }) +} + +runWhenDOMLoaded(addCopyButtonToCodeCells) \ No newline at end of file diff --git a/3.25.4-scylla/_static/copybutton_funcs.js b/3.25.4-scylla/_static/copybutton_funcs.js new file mode 100644 index 0000000000..dbe1aaad79 --- /dev/null +++ b/3.25.4-scylla/_static/copybutton_funcs.js @@ -0,0 +1,73 @@ +function escapeRegExp(string) { + return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string +} + +/** + * Removes excluded text from a Node. + * + * @param {Node} target Node to filter. + * @param {string} exclude CSS selector of nodes to exclude. + * @returns {DOMString} Text from `target` with text removed. + */ +export function filterText(target, exclude) { + const clone = target.cloneNode(true); // clone as to not modify the live DOM + if (exclude) { + // remove excluded nodes + clone.querySelectorAll(exclude).forEach(node => node.remove()); + } + return clone.innerText; +} + +// Callback when a copy button is clicked. Will be passed the node that was clicked +// should then grab the text and replace pieces of text that shouldn't be used in output +export function formatCopyText(textContent, copybuttonPromptText, isRegexp = false, onlyCopyPromptLines = true, removePrompts = true, copyEmptyLines = true, lineContinuationChar = "", hereDocDelim = "") { + var regexp; + var match; + + // Do we check for line continuation characters and "HERE-documents"? + var useLineCont = !!lineContinuationChar + var useHereDoc = !!hereDocDelim + + // create regexp to capture prompt and remaining line + if (isRegexp) { + regexp = new RegExp('^(' + copybuttonPromptText + ')(.*)') + } else { + regexp = new RegExp('^(' + escapeRegExp(copybuttonPromptText) + ')(.*)') + } + + const outputLines = []; + var promptFound = false; + var gotLineCont = false; + var gotHereDoc = false; + const lineGotPrompt = []; + for (const line of textContent.split('\n')) { + match = line.match(regexp) + if (match || gotLineCont || gotHereDoc) { + promptFound = regexp.test(line) + lineGotPrompt.push(promptFound) + if (removePrompts && promptFound) { + outputLines.push(match[2]) + } else { + outputLines.push(line) + } + gotLineCont = line.endsWith(lineContinuationChar) & useLineCont + if (line.includes(hereDocDelim) & useHereDoc) + gotHereDoc = !gotHereDoc + } else if (!onlyCopyPromptLines) { + outputLines.push(line) + } else if (copyEmptyLines && line.trim() === '') { + outputLines.push(line) + } + } + + // If no lines with the prompt were found then just use original lines + if (lineGotPrompt.some(v => v === true)) { + textContent = outputLines.join('\n'); + } + + // Remove a trailing newline to avoid auto-running when pasting + if (textContent.endsWith("\n")) { + textContent = textContent.slice(0, -1) + } + return textContent +} diff --git a/3.25.4-scylla/_static/css/main.css b/3.25.4-scylla/_static/css/main.css new file mode 100644 index 0000000000..4ac0174528 --- /dev/null +++ b/3.25.4-scylla/_static/css/main.css @@ -0,0 +1 @@ +@media print,screen and (min-width:40em){.reveal,.reveal.large,.reveal.small,.reveal.tiny{left:auto;margin:0 auto;right:auto}}/*! normalize.css v8.0.0 | MIT License | github.com/necolas/normalize.css */html{-webkit-text-size-adjust:100%;line-height:1.15}h1{font-size:2em;margin:.67em 0}hr{-webkit-box-sizing:content-box;box-sizing:content-box;overflow:visible}pre{font-family:monospace,monospace;font-size:1em}a{background-color:transparent}abbr[title]{border-bottom:0;-webkit-text-decoration:underline dotted;text-decoration:underline dotted}b,strong{font-weight:bolder}code,kbd,samp{font-family:monospace,monospace;font-size:1em}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}img{border-style:none}button,input,optgroup,select,textarea{font-size:100%;line-height:1.15;margin:0}button,input{overflow:visible}button,select{text-transform:none}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button}[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner,button::-moz-focus-inner{border-style:none;padding:0}[type=button]:-moz-focusring,[type=reset]:-moz-focusring,[type=submit]:-moz-focusring,button:-moz-focusring{outline:1px dotted ButtonText}fieldset{padding:.35em .75em .625em}legend{-webkit-box-sizing:border-box;box-sizing:border-box;color:inherit;display:table;padding:0;white-space:normal}progress{vertical-align:baseline}textarea{overflow:auto}[type=checkbox],[type=radio]{-webkit-box-sizing:border-box;box-sizing:border-box;padding:0}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}details{display:block}summary{display:list-item}template{display:none}[hidden]{display:none}[data-whatinput=mouse] *,[data-whatinput=mouse] :focus,[data-whatinput=touch] *,[data-whatinput=touch] :focus,[data-whatintent=mouse] *,[data-whatintent=mouse] :focus,[data-whatintent=touch] *,[data-whatintent=touch] :focus{outline:0}[draggable=false]{-webkit-touch-callout:none;-webkit-user-select:none}.foundation-mq{font-family:"small=0em&medium=40em&large=64em&xlarge=75em&xxlarge=90em"}html{-webkit-box-sizing:border-box;font-size:100%}*,:after,:before{-webkit-box-sizing:inherit}body{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;background:#fefefe;color:#0a0a0a;font-family:Helvetica Neue,Helvetica,Roboto,Arial,sans-serif;font-weight:400;line-height:1.5;margin:0;padding:0}img{-ms-interpolation-mode:bicubic;display:inline-block;height:auto;vertical-align:middle}textarea{border-radius:0;height:auto;min-height:50px}select{-webkit-box-sizing:border-box;box-sizing:border-box;width:100%}.map_canvas embed,.map_canvas img,.map_canvas object,.mqa-display embed,.mqa-display img,.mqa-display object{max-width:none!important}button{-webkit-appearance:none;-moz-appearance:none;appearance:none;background:0 0;border:0;border-radius:0;cursor:auto;line-height:1;padding:0}[data-whatinput=mouse] button{outline:0}pre{-webkit-overflow-scrolling:touch;overflow:auto}button,input,optgroup,select,textarea{font-family:inherit}.is-visible{display:block!important}.is-hidden{display:none!important}[type=color],[type=date],[type=datetime-local],[type=datetime],[type=email],[type=month],[type=number],[type=password],[type=search],[type=tel],[type=text],[type=time],[type=url],[type=week],textarea{-webkit-appearance:none;-moz-appearance:none;appearance:none;background-color:#fefefe;border:1px solid #cacaca;border-radius:0;-webkit-box-shadow:inset 0 1px 2px hsla(0,0%,4%,.1);box-shadow:inset 0 1px 2px hsla(0,0%,4%,.1);-webkit-box-sizing:border-box;box-sizing:border-box;color:#0a0a0a;display:block;font-family:inherit;font-size:1rem;font-weight:400;height:2.4375rem;line-height:1.5;margin:0 0 1rem;padding:.5rem;-webkit-transition:border-color .25s ease-in-out,-webkit-box-shadow .5s;transition:border-color .25s ease-in-out,-webkit-box-shadow .5s;transition:box-shadow .5s,border-color .25s ease-in-out;transition:box-shadow .5s,border-color .25s ease-in-out,-webkit-box-shadow .5s;width:100%}[type=color]:focus,[type=date]:focus,[type=datetime-local]:focus,[type=datetime]:focus,[type=email]:focus,[type=month]:focus,[type=number]:focus,[type=password]:focus,[type=search]:focus,[type=tel]:focus,[type=text]:focus,[type=time]:focus,[type=url]:focus,[type=week]:focus,textarea:focus{background-color:#fefefe;border:1px solid #8a8a8a;-webkit-box-shadow:0 0 5px #cacaca;box-shadow:0 0 5px #cacaca;outline:0;-webkit-transition:border-color .25s ease-in-out,-webkit-box-shadow .5s;transition:border-color .25s ease-in-out,-webkit-box-shadow .5s;transition:box-shadow .5s,border-color .25s ease-in-out;transition:box-shadow .5s,border-color .25s ease-in-out,-webkit-box-shadow .5s}textarea{max-width:100%}textarea[rows]{height:auto}input:disabled,input[readonly],textarea:disabled,textarea[readonly]{background-color:#e6e6e6;cursor:not-allowed}[type=button],[type=submit]{-webkit-appearance:none;-moz-appearance:none;appearance:none;border-radius:0}input[type=search]{-webkit-box-sizing:border-box;box-sizing:border-box}::-webkit-input-placeholder{color:#cacaca}::-moz-placeholder{color:#cacaca}:-ms-input-placeholder{color:#cacaca}::-ms-input-placeholder{color:#cacaca}::placeholder{color:#cacaca}[type=checkbox],[type=file],[type=radio]{margin:0 0 1rem}[type=checkbox]+label,[type=radio]+label{display:inline-block;margin-bottom:0;margin-left:.5rem;margin-right:1rem;vertical-align:baseline}[type=checkbox]+label[for],[type=radio]+label[for]{cursor:pointer}label>[type=checkbox],label>[type=radio]{margin-right:.5rem}[type=file]{width:100%}label{color:#0a0a0a;display:block;font-size:.875rem;font-weight:400;line-height:1.8;margin:0}label.middle{line-height:1.5;margin:0 0 1rem;padding:.5625rem 0}.help-text{color:#0a0a0a;font-size:.8125rem;font-style:italic;margin-top:-.5rem}.input-group{-webkit-box-align:stretch;-ms-flex-align:stretch;-webkit-align-items:stretch;align-items:stretch;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;margin-bottom:1rem;width:100%}.input-group>:first-child,.input-group>:first-child.input-group-button>*{border-radius:0}.input-group>:last-child,.input-group>:last-child.input-group-button>*{border-radius:0}.input-group-button,.input-group-button a,.input-group-button button,.input-group-button input,.input-group-button label,.input-group-field,.input-group-label{margin:0;white-space:nowrap}.input-group-label{-webkit-box-flex:0;-webkit-box-align:center;-ms-flex-align:center;-webkit-align-items:center;align-items:center;background:#e6e6e6;border:1px solid #cacaca;color:#0a0a0a;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto;padding:0 1rem;text-align:center;white-space:nowrap}.input-group-label:first-child{border-right:0}.input-group-label:last-child{border-left:0}.input-group-field{-webkit-box-flex:1;border-radius:0;-webkit-flex:1 1 0px;-ms-flex:1 1 0px;flex:1 1 0px;min-width:0}.input-group-button{-webkit-box-flex:0;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto;padding-bottom:0;padding-top:0;text-align:center}.input-group-button a,.input-group-button button,.input-group-button input,.input-group-button label{-ms-flex-item-align:stretch;-webkit-align-self:stretch;align-self:stretch;font-size:1rem;height:auto;padding-bottom:0;padding-top:0}fieldset{border:0;margin:0;padding:0}legend{margin-bottom:.5rem;max-width:100%}.fieldset{border:1px solid #cacaca;margin:1.125rem 0;padding:1.25rem}.fieldset legend{margin:0 0 0 -.1875rem;padding:0 .1875rem}select{-webkit-appearance:none;-moz-appearance:none;appearance:none;background-color:#fefefe;background-image:url('data:image/svg+xml;utf8,');background-origin:content-box;background-position:right -1rem center;background-repeat:no-repeat;background-size:9px 6px;border:1px solid #cacaca;border-radius:0;color:#0a0a0a;font-family:inherit;font-size:1rem;font-weight:400;height:2.4375rem;line-height:1.5;margin:0 0 1rem;padding:.5rem 1.5rem .5rem .5rem;-webkit-transition:border-color .25s ease-in-out,-webkit-box-shadow .5s;transition:border-color .25s ease-in-out,-webkit-box-shadow .5s;transition:box-shadow .5s,border-color .25s ease-in-out;transition:box-shadow .5s,border-color .25s ease-in-out,-webkit-box-shadow .5s}@media screen and (min-width:0\0){select{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAYCAYAAACbU/80AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAIpJREFUeNrEkckNgDAMBBfRkEt0ObRBBdsGXUDgmQfK4XhH2m8czQAAy27R3tsw4Qfe2x8uOO6oYLb6GlOor3GF+swURAOmUJ+RwtEJs9WvTGEYxBXqI1MQAZhCfUQKRzDMVj+TwrAIV6jvSUEkYAr1LSkcyTBb/V+KYfX7xAeusq3sLDtGH3kEGACPWIflNZfhRQAAAABJRU5ErkJggg==)}}select:focus{background-color:#fefefe;border:1px solid #8a8a8a;-webkit-box-shadow:0 0 5px #cacaca;box-shadow:0 0 5px #cacaca;outline:0;-webkit-transition:border-color .25s ease-in-out,-webkit-box-shadow .5s;transition:border-color .25s ease-in-out,-webkit-box-shadow .5s;transition:box-shadow .5s,border-color .25s ease-in-out;transition:box-shadow .5s,border-color .25s ease-in-out,-webkit-box-shadow .5s}select:disabled{background-color:#e6e6e6;cursor:not-allowed}select::-ms-expand{display:none}select[multiple]{background-image:none;height:auto}select:not([multiple]){padding-bottom:0;padding-top:0}.is-invalid-input:not(:focus){background-color:#f9ecea;border-color:#cc4b37}.is-invalid-input:not(:focus)::-webkit-input-placeholder{color:#cc4b37}.is-invalid-input:not(:focus)::-moz-placeholder{color:#cc4b37}.is-invalid-input:not(:focus):-ms-input-placeholder{color:#cc4b37}.is-invalid-input:not(:focus)::-ms-input-placeholder{color:#cc4b37}.is-invalid-input:not(:focus)::placeholder{color:#cc4b37}.form-error,.is-invalid-label{color:#cc4b37}.form-error{display:none;font-size:.75rem;font-weight:700;margin-bottom:1rem;margin-top:-.5rem}.form-error.is-visible{display:block}blockquote,dd,div,dl,dt,form,h1,h2,h3,h4,h5,h6,li,ol,p,pre,td,th,ul{margin:0;padding:0}p{text-rendering:optimizeLegibility;font-size:inherit;line-height:1.6;margin-bottom:1rem}em,i{font-style:italic}b,em,i,strong{line-height:inherit}b,strong{font-weight:700}small{font-size:80%;line-height:inherit}.h1,.h2,.h3,.h4,.h5,.h6,h1,h2,h3,h4,h5,h6{text-rendering:optimizeLegibility;color:inherit;font-family:Helvetica Neue,Helvetica,Roboto,Arial,sans-serif;font-style:normal;font-weight:400}.h1 small,.h2 small,.h3 small,.h4 small,.h5 small,.h6 small,h1 small,h2 small,h3 small,h4 small,h5 small,h6 small{color:#cacaca;line-height:0}.h1,h1{font-size:1.5rem}.h1,.h2,h1,h2{line-height:1.4;margin-bottom:.5rem;margin-top:0}.h2,h2{font-size:1.25rem}.h3,h3{font-size:1.1875rem}.h3,.h4,h3,h4{line-height:1.4;margin-bottom:.5rem;margin-top:0}.h4,h4{font-size:1.125rem}.h5,h5{font-size:1.0625rem}.h5,.h6,h5,h6{line-height:1.4;margin-bottom:.5rem;margin-top:0}.h6,h6{font-size:1rem}@media print,screen and (min-width:40em){.h1,h1{font-size:3rem}.h2,h2{font-size:2.5rem}.h3,h3{font-size:1.9375rem}.h4,h4{font-size:1.5625rem}.h5,h5{font-size:1.25rem}.h6,h6{font-size:1rem}}a{color:#1779ba;cursor:pointer;line-height:inherit;text-decoration:none}a:focus,a:hover{color:#1468a0}a img,hr{border:0}hr{border-bottom:1px solid #cacaca;clear:both;height:0;margin:1.25rem auto;max-width:75rem}dl,ol,ul{line-height:1.6;list-style-position:outside;margin-bottom:1rem}li{font-size:inherit}ul{list-style-type:disc}ol,ul{margin-left:1.25rem}ol ol,ol ul,ul ol,ul ul{margin-bottom:0;margin-left:1.25rem}dl{margin-bottom:1rem}dl dt{font-weight:700;margin-bottom:.3rem}blockquote{border-left:1px solid #cacaca;margin:0 0 1rem;padding:.5625rem 1.25rem 0 1.1875rem}blockquote,blockquote p{color:#8a8a8a;line-height:1.6}abbr,abbr[title]{border-bottom:1px dotted #0a0a0a;cursor:help;text-decoration:none}figure,kbd{margin:0}kbd{background-color:#e6e6e6;color:#0a0a0a;font-family:Consolas,Liberation Mono,Courier,monospace;padding:.125rem .25rem 0}.subheader{color:#8a8a8a;font-weight:400;line-height:1.4;margin-bottom:.5rem;margin-top:.2rem}.lead{font-size:125%;line-height:1.6}.stat{font-size:2.5rem;line-height:1}p+.stat{margin-top:-1rem}ol.no-bullet,ul.no-bullet{list-style:none;margin-left:0}.cite-block,cite{color:#8a8a8a;display:block;font-size:.8125rem}.cite-block:before,cite:before{content:"— "}.code-inline,code{word-wrap:break-word;display:inline;max-width:100%;padding:.125rem .3125rem .0625rem}.code-block,.code-inline,code{background-color:#e6e6e6;border:1px solid #cacaca;color:#0a0a0a;font-family:Consolas,Liberation Mono,Courier,monospace;font-weight:400}.code-block{display:block;margin-bottom:1.5rem;overflow:auto;padding:1rem;white-space:pre}.text-left{text-align:left}.text-right{text-align:right}.text-center{text-align:center}.text-justify{text-align:justify}@media print,screen and (min-width:40em){.medium-text-left{text-align:left}.medium-text-right{text-align:right}.medium-text-center{text-align:center}.medium-text-justify{text-align:justify}}@media print,screen and (min-width:64em){.large-text-left{text-align:left}.large-text-right{text-align:right}.large-text-center{text-align:center}.large-text-justify{text-align:justify}}.show-for-print{display:none!important}@media print{*{-webkit-print-color-adjust:economy;background:0 0!important;-webkit-box-shadow:none!important;box-shadow:none!important;color:#000!important;color-adjust:economy;text-shadow:none!important}.show-for-print{display:block!important}.hide-for-print{display:none!important}table.show-for-print{display:table!important}thead.show-for-print{display:table-header-group!important}tbody.show-for-print{display:table-row-group!important}tr.show-for-print{display:table-row!important}td.show-for-print,th.show-for-print{display:table-cell!important}a,a:visited{text-decoration:underline}a[href]:after{content:" (" attr(href) ")"}.ir a:after,a[href^="#"]:after,a[href^="javascript:"]:after{content:""}abbr[title]:after{content:" (" attr(title) ")"}blockquote,pre{border:1px solid #8a8a8a;page-break-inside:avoid}thead{display:table-header-group}img,tr{page-break-inside:avoid}img{max-width:100%!important}@page{margin:.5cm}h2,h3,p{orphans:3;widows:3}h2,h3{page-break-after:avoid}.print-break-inside{page-break-inside:auto}}.grid-container{margin-left:auto;margin-right:auto;max-width:75rem;padding-left:.625rem;padding-right:.625rem}@media print,screen and (min-width:40em){.grid-container{padding-left:.9375rem;padding-right:.9375rem}}.grid-container.fluid{margin-left:auto;margin-right:auto;max-width:100%;padding-left:.625rem;padding-right:.625rem}@media print,screen and (min-width:40em){.grid-container.fluid{padding-left:.9375rem;padding-right:.9375rem}}.grid-container.full{margin-left:auto;margin-right:auto;max-width:100%;padding-left:0;padding-right:0}.grid-x{-webkit-box-orient:horizontal;-webkit-box-direction:normal;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-flow:row wrap;-ms-flex-flow:row wrap;flex-flow:row wrap}.cell{-webkit-box-flex:0;-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto;min-height:0;min-width:0;width:100%}.cell.auto{-webkit-box-flex:1;-webkit-flex:1 1 0;-ms-flex:1 1 0px;flex:1 1 0}.cell.shrink{-webkit-box-flex:0;-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto}.grid-x>.auto{width:auto}.grid-x>.shrink{width:auto}.grid-x>.small-1,.grid-x>.small-2,.grid-x>.small-3,.grid-x>.small-4,.grid-x>.small-5,.grid-x>.small-6,.grid-x>.small-7,.grid-x>.small-8,.grid-x>.small-9,.grid-x>.small-10,.grid-x>.small-11,.grid-x>.small-12,.grid-x>.small-full,.grid-x>.small-shrink{-ms-flex-preferred-size:auto;-webkit-flex-basis:auto;flex-basis:auto}@media print,screen and (min-width:40em){.grid-x>.medium-1,.grid-x>.medium-2,.grid-x>.medium-3,.grid-x>.medium-4,.grid-x>.medium-5,.grid-x>.medium-6,.grid-x>.medium-7,.grid-x>.medium-8,.grid-x>.medium-9,.grid-x>.medium-10,.grid-x>.medium-11,.grid-x>.medium-12,.grid-x>.medium-full,.grid-x>.medium-shrink{-ms-flex-preferred-size:auto;-webkit-flex-basis:auto;flex-basis:auto}}@media print,screen and (min-width:64em){.grid-x>.large-1,.grid-x>.large-2,.grid-x>.large-3,.grid-x>.large-4,.grid-x>.large-5,.grid-x>.large-6,.grid-x>.large-7,.grid-x>.large-8,.grid-x>.large-9,.grid-x>.large-10,.grid-x>.large-11,.grid-x>.large-12,.grid-x>.large-full,.grid-x>.large-shrink{-ms-flex-preferred-size:auto;-webkit-flex-basis:auto;flex-basis:auto}}.grid-x>.small-1,.grid-x>.small-2,.grid-x>.small-3,.grid-x>.small-4,.grid-x>.small-5,.grid-x>.small-6,.grid-x>.small-7,.grid-x>.small-8,.grid-x>.small-9,.grid-x>.small-10,.grid-x>.small-11,.grid-x>.small-12{-webkit-box-flex:0;-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto}.grid-x>.small-1{width:8.33333%}.grid-x>.small-2{width:16.66667%}.grid-x>.small-3{width:25%}.grid-x>.small-4{width:33.33333%}.grid-x>.small-5{width:41.66667%}.grid-x>.small-6{width:50%}.grid-x>.small-7{width:58.33333%}.grid-x>.small-8{width:66.66667%}.grid-x>.small-9{width:75%}.grid-x>.small-10{width:83.33333%}.grid-x>.small-11{width:91.66667%}.grid-x>.small-12{width:100%}@media print,screen and (min-width:40em){.grid-x>.medium-auto{-webkit-box-flex:1;-webkit-flex:1 1 0;-ms-flex:1 1 0px;flex:1 1 0;width:auto}.grid-x>.medium-1,.grid-x>.medium-2,.grid-x>.medium-3,.grid-x>.medium-4,.grid-x>.medium-5,.grid-x>.medium-6,.grid-x>.medium-7,.grid-x>.medium-8,.grid-x>.medium-9,.grid-x>.medium-10,.grid-x>.medium-11,.grid-x>.medium-12,.grid-x>.medium-shrink{-webkit-box-flex:0;-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto}.grid-x>.medium-shrink{width:auto}.grid-x>.medium-1{width:8.33333%}.grid-x>.medium-2{width:16.66667%}.grid-x>.medium-3{width:25%}.grid-x>.medium-4{width:33.33333%}.grid-x>.medium-5{width:41.66667%}.grid-x>.medium-6{width:50%}.grid-x>.medium-7{width:58.33333%}.grid-x>.medium-8{width:66.66667%}.grid-x>.medium-9{width:75%}.grid-x>.medium-10{width:83.33333%}.grid-x>.medium-11{width:91.66667%}.grid-x>.medium-12{width:100%}}@media print,screen and (min-width:64em){.grid-x>.large-auto{-webkit-box-flex:1;-webkit-flex:1 1 0;-ms-flex:1 1 0px;flex:1 1 0;width:auto}.grid-x>.large-1,.grid-x>.large-2,.grid-x>.large-3,.grid-x>.large-4,.grid-x>.large-5,.grid-x>.large-6,.grid-x>.large-7,.grid-x>.large-8,.grid-x>.large-9,.grid-x>.large-10,.grid-x>.large-11,.grid-x>.large-12,.grid-x>.large-shrink{-webkit-box-flex:0;-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto}.grid-x>.large-shrink{width:auto}.grid-x>.large-1{width:8.33333%}.grid-x>.large-2{width:16.66667%}.grid-x>.large-3{width:25%}.grid-x>.large-4{width:33.33333%}.grid-x>.large-5{width:41.66667%}.grid-x>.large-6{width:50%}.grid-x>.large-7{width:58.33333%}.grid-x>.large-8{width:66.66667%}.grid-x>.large-9{width:75%}.grid-x>.large-10{width:83.33333%}.grid-x>.large-11{width:91.66667%}.grid-x>.large-12{width:100%}}.grid-margin-x:not(.grid-x)>.cell{width:auto}.grid-margin-y:not(.grid-y)>.cell{height:auto}.grid-margin-x{margin-left:-.625rem;margin-right:-.625rem}@media print,screen and (min-width:40em){.grid-margin-x{margin-left:-.9375rem;margin-right:-.9375rem}}.grid-margin-x>.cell{margin-left:.625rem;margin-right:.625rem;width:calc(100% - 1.25rem)}@media print,screen and (min-width:40em){.grid-margin-x>.cell{margin-left:.9375rem;margin-right:.9375rem;width:calc(100% - 1.875rem)}}.grid-margin-x>.auto{width:auto}.grid-margin-x>.shrink{width:auto}.grid-margin-x>.small-1{width:calc(8.33333% - 1.25rem)}.grid-margin-x>.small-2{width:calc(16.66667% - 1.25rem)}.grid-margin-x>.small-3{width:calc(25% - 1.25rem)}.grid-margin-x>.small-4{width:calc(33.33333% - 1.25rem)}.grid-margin-x>.small-5{width:calc(41.66667% - 1.25rem)}.grid-margin-x>.small-6{width:calc(50% - 1.25rem)}.grid-margin-x>.small-7{width:calc(58.33333% - 1.25rem)}.grid-margin-x>.small-8{width:calc(66.66667% - 1.25rem)}.grid-margin-x>.small-9{width:calc(75% - 1.25rem)}.grid-margin-x>.small-10{width:calc(83.33333% - 1.25rem)}.grid-margin-x>.small-11{width:calc(91.66667% - 1.25rem)}.grid-margin-x>.small-12{width:calc(100% - 1.25rem)}@media print,screen and (min-width:40em){.grid-margin-x>.auto{width:auto}.grid-margin-x>.shrink{width:auto}.grid-margin-x>.small-1{width:calc(8.33333% - 1.875rem)}.grid-margin-x>.small-2{width:calc(16.66667% - 1.875rem)}.grid-margin-x>.small-3{width:calc(25% - 1.875rem)}.grid-margin-x>.small-4{width:calc(33.33333% - 1.875rem)}.grid-margin-x>.small-5{width:calc(41.66667% - 1.875rem)}.grid-margin-x>.small-6{width:calc(50% - 1.875rem)}.grid-margin-x>.small-7{width:calc(58.33333% - 1.875rem)}.grid-margin-x>.small-8{width:calc(66.66667% - 1.875rem)}.grid-margin-x>.small-9{width:calc(75% - 1.875rem)}.grid-margin-x>.small-10{width:calc(83.33333% - 1.875rem)}.grid-margin-x>.small-11{width:calc(91.66667% - 1.875rem)}.grid-margin-x>.small-12{width:calc(100% - 1.875rem)}.grid-margin-x>.medium-auto{width:auto}.grid-margin-x>.medium-shrink{width:auto}.grid-margin-x>.medium-1{width:calc(8.33333% - 1.875rem)}.grid-margin-x>.medium-2{width:calc(16.66667% - 1.875rem)}.grid-margin-x>.medium-3{width:calc(25% - 1.875rem)}.grid-margin-x>.medium-4{width:calc(33.33333% - 1.875rem)}.grid-margin-x>.medium-5{width:calc(41.66667% - 1.875rem)}.grid-margin-x>.medium-6{width:calc(50% - 1.875rem)}.grid-margin-x>.medium-7{width:calc(58.33333% - 1.875rem)}.grid-margin-x>.medium-8{width:calc(66.66667% - 1.875rem)}.grid-margin-x>.medium-9{width:calc(75% - 1.875rem)}.grid-margin-x>.medium-10{width:calc(83.33333% - 1.875rem)}.grid-margin-x>.medium-11{width:calc(91.66667% - 1.875rem)}.grid-margin-x>.medium-12{width:calc(100% - 1.875rem)}}@media print,screen and (min-width:64em){.grid-margin-x>.large-auto{width:auto}.grid-margin-x>.large-shrink{width:auto}.grid-margin-x>.large-1{width:calc(8.33333% - 1.875rem)}.grid-margin-x>.large-2{width:calc(16.66667% - 1.875rem)}.grid-margin-x>.large-3{width:calc(25% - 1.875rem)}.grid-margin-x>.large-4{width:calc(33.33333% - 1.875rem)}.grid-margin-x>.large-5{width:calc(41.66667% - 1.875rem)}.grid-margin-x>.large-6{width:calc(50% - 1.875rem)}.grid-margin-x>.large-7{width:calc(58.33333% - 1.875rem)}.grid-margin-x>.large-8{width:calc(66.66667% - 1.875rem)}.grid-margin-x>.large-9{width:calc(75% - 1.875rem)}.grid-margin-x>.large-10{width:calc(83.33333% - 1.875rem)}.grid-margin-x>.large-11{width:calc(91.66667% - 1.875rem)}.grid-margin-x>.large-12{width:calc(100% - 1.875rem)}}.grid-padding-x .grid-padding-x{margin-left:-.625rem;margin-right:-.625rem}@media print,screen and (min-width:40em){.grid-padding-x .grid-padding-x{margin-left:-.9375rem;margin-right:-.9375rem}}.grid-container:not(.full)>.grid-padding-x{margin-left:-.625rem;margin-right:-.625rem}@media print,screen and (min-width:40em){.grid-container:not(.full)>.grid-padding-x{margin-left:-.9375rem;margin-right:-.9375rem}}.grid-padding-x>.cell{padding-left:.625rem;padding-right:.625rem}@media print,screen and (min-width:40em){.grid-padding-x>.cell{padding-left:.9375rem;padding-right:.9375rem}}.small-up-1>.cell{width:100%}.small-up-2>.cell{width:50%}.small-up-3>.cell{width:33.33333%}.small-up-4>.cell{width:25%}.small-up-5>.cell{width:20%}.small-up-6>.cell{width:16.66667%}.small-up-7>.cell{width:14.28571%}.small-up-8>.cell{width:12.5%}@media print,screen and (min-width:40em){.medium-up-1>.cell{width:100%}.medium-up-2>.cell{width:50%}.medium-up-3>.cell{width:33.33333%}.medium-up-4>.cell{width:25%}.medium-up-5>.cell{width:20%}.medium-up-6>.cell{width:16.66667%}.medium-up-7>.cell{width:14.28571%}.medium-up-8>.cell{width:12.5%}}@media print,screen and (min-width:64em){.large-up-1>.cell{width:100%}.large-up-2>.cell{width:50%}.large-up-3>.cell{width:33.33333%}.large-up-4>.cell{width:25%}.large-up-5>.cell{width:20%}.large-up-6>.cell{width:16.66667%}.large-up-7>.cell{width:14.28571%}.large-up-8>.cell{width:12.5%}}.grid-margin-x.small-up-1>.cell{width:calc(100% - 1.25rem)}.grid-margin-x.small-up-2>.cell{width:calc(50% - 1.25rem)}.grid-margin-x.small-up-3>.cell{width:calc(33.33333% - 1.25rem)}.grid-margin-x.small-up-4>.cell{width:calc(25% - 1.25rem)}.grid-margin-x.small-up-5>.cell{width:calc(20% - 1.25rem)}.grid-margin-x.small-up-6>.cell{width:calc(16.66667% - 1.25rem)}.grid-margin-x.small-up-7>.cell{width:calc(14.28571% - 1.25rem)}.grid-margin-x.small-up-8>.cell{width:calc(12.5% - 1.25rem)}@media print,screen and (min-width:40em){.grid-margin-x.small-up-1>.cell{width:calc(100% - 1.875rem)}.grid-margin-x.small-up-2>.cell{width:calc(50% - 1.875rem)}.grid-margin-x.small-up-3>.cell{width:calc(33.33333% - 1.875rem)}.grid-margin-x.small-up-4>.cell{width:calc(25% - 1.875rem)}.grid-margin-x.small-up-5>.cell{width:calc(20% - 1.875rem)}.grid-margin-x.small-up-6>.cell{width:calc(16.66667% - 1.875rem)}.grid-margin-x.small-up-7>.cell{width:calc(14.28571% - 1.875rem)}.grid-margin-x.small-up-8>.cell{width:calc(12.5% - 1.875rem)}.grid-margin-x.medium-up-1>.cell{width:calc(100% - 1.875rem)}.grid-margin-x.medium-up-2>.cell{width:calc(50% - 1.875rem)}.grid-margin-x.medium-up-3>.cell{width:calc(33.33333% - 1.875rem)}.grid-margin-x.medium-up-4>.cell{width:calc(25% - 1.875rem)}.grid-margin-x.medium-up-5>.cell{width:calc(20% - 1.875rem)}.grid-margin-x.medium-up-6>.cell{width:calc(16.66667% - 1.875rem)}.grid-margin-x.medium-up-7>.cell{width:calc(14.28571% - 1.875rem)}.grid-margin-x.medium-up-8>.cell{width:calc(12.5% - 1.875rem)}}@media print,screen and (min-width:64em){.grid-margin-x.large-up-1>.cell{width:calc(100% - 1.875rem)}.grid-margin-x.large-up-2>.cell{width:calc(50% - 1.875rem)}.grid-margin-x.large-up-3>.cell{width:calc(33.33333% - 1.875rem)}.grid-margin-x.large-up-4>.cell{width:calc(25% - 1.875rem)}.grid-margin-x.large-up-5>.cell{width:calc(20% - 1.875rem)}.grid-margin-x.large-up-6>.cell{width:calc(16.66667% - 1.875rem)}.grid-margin-x.large-up-7>.cell{width:calc(14.28571% - 1.875rem)}.grid-margin-x.large-up-8>.cell{width:calc(12.5% - 1.875rem)}}.small-margin-collapse{margin-left:0;margin-right:0}.small-margin-collapse>.cell{margin-left:0;margin-right:0}.small-margin-collapse>.small-1{width:8.33333%}.small-margin-collapse>.small-2{width:16.66667%}.small-margin-collapse>.small-3{width:25%}.small-margin-collapse>.small-4{width:33.33333%}.small-margin-collapse>.small-5{width:41.66667%}.small-margin-collapse>.small-6{width:50%}.small-margin-collapse>.small-7{width:58.33333%}.small-margin-collapse>.small-8{width:66.66667%}.small-margin-collapse>.small-9{width:75%}.small-margin-collapse>.small-10{width:83.33333%}.small-margin-collapse>.small-11{width:91.66667%}.small-margin-collapse>.small-12{width:100%}@media print,screen and (min-width:40em){.small-margin-collapse>.medium-1{width:8.33333%}.small-margin-collapse>.medium-2{width:16.66667%}.small-margin-collapse>.medium-3{width:25%}.small-margin-collapse>.medium-4{width:33.33333%}.small-margin-collapse>.medium-5{width:41.66667%}.small-margin-collapse>.medium-6{width:50%}.small-margin-collapse>.medium-7{width:58.33333%}.small-margin-collapse>.medium-8{width:66.66667%}.small-margin-collapse>.medium-9{width:75%}.small-margin-collapse>.medium-10{width:83.33333%}.small-margin-collapse>.medium-11{width:91.66667%}.small-margin-collapse>.medium-12{width:100%}}@media print,screen and (min-width:64em){.small-margin-collapse>.large-1{width:8.33333%}.small-margin-collapse>.large-2{width:16.66667%}.small-margin-collapse>.large-3{width:25%}.small-margin-collapse>.large-4{width:33.33333%}.small-margin-collapse>.large-5{width:41.66667%}.small-margin-collapse>.large-6{width:50%}.small-margin-collapse>.large-7{width:58.33333%}.small-margin-collapse>.large-8{width:66.66667%}.small-margin-collapse>.large-9{width:75%}.small-margin-collapse>.large-10{width:83.33333%}.small-margin-collapse>.large-11{width:91.66667%}.small-margin-collapse>.large-12{width:100%}}.small-padding-collapse{margin-left:0;margin-right:0}.small-padding-collapse>.cell{padding-left:0;padding-right:0}@media print,screen and (min-width:40em){.medium-margin-collapse{margin-left:0;margin-right:0}.medium-margin-collapse>.cell{margin-left:0;margin-right:0}}@media print,screen and (min-width:40em){.medium-margin-collapse>.small-1{width:8.33333%}.medium-margin-collapse>.small-2{width:16.66667%}.medium-margin-collapse>.small-3{width:25%}.medium-margin-collapse>.small-4{width:33.33333%}.medium-margin-collapse>.small-5{width:41.66667%}.medium-margin-collapse>.small-6{width:50%}.medium-margin-collapse>.small-7{width:58.33333%}.medium-margin-collapse>.small-8{width:66.66667%}.medium-margin-collapse>.small-9{width:75%}.medium-margin-collapse>.small-10{width:83.33333%}.medium-margin-collapse>.small-11{width:91.66667%}.medium-margin-collapse>.small-12{width:100%}}@media print,screen and (min-width:40em){.medium-margin-collapse>.medium-1{width:8.33333%}.medium-margin-collapse>.medium-2{width:16.66667%}.medium-margin-collapse>.medium-3{width:25%}.medium-margin-collapse>.medium-4{width:33.33333%}.medium-margin-collapse>.medium-5{width:41.66667%}.medium-margin-collapse>.medium-6{width:50%}.medium-margin-collapse>.medium-7{width:58.33333%}.medium-margin-collapse>.medium-8{width:66.66667%}.medium-margin-collapse>.medium-9{width:75%}.medium-margin-collapse>.medium-10{width:83.33333%}.medium-margin-collapse>.medium-11{width:91.66667%}.medium-margin-collapse>.medium-12{width:100%}}@media print,screen and (min-width:64em){.medium-margin-collapse>.large-1{width:8.33333%}.medium-margin-collapse>.large-2{width:16.66667%}.medium-margin-collapse>.large-3{width:25%}.medium-margin-collapse>.large-4{width:33.33333%}.medium-margin-collapse>.large-5{width:41.66667%}.medium-margin-collapse>.large-6{width:50%}.medium-margin-collapse>.large-7{width:58.33333%}.medium-margin-collapse>.large-8{width:66.66667%}.medium-margin-collapse>.large-9{width:75%}.medium-margin-collapse>.large-10{width:83.33333%}.medium-margin-collapse>.large-11{width:91.66667%}.medium-margin-collapse>.large-12{width:100%}}@media print,screen and (min-width:40em){.medium-padding-collapse{margin-left:0;margin-right:0}.medium-padding-collapse>.cell{padding-left:0;padding-right:0}}@media print,screen and (min-width:64em){.large-margin-collapse{margin-left:0;margin-right:0}.large-margin-collapse>.cell{margin-left:0;margin-right:0}}@media print,screen and (min-width:64em){.large-margin-collapse>.small-1{width:8.33333%}.large-margin-collapse>.small-2{width:16.66667%}.large-margin-collapse>.small-3{width:25%}.large-margin-collapse>.small-4{width:33.33333%}.large-margin-collapse>.small-5{width:41.66667%}.large-margin-collapse>.small-6{width:50%}.large-margin-collapse>.small-7{width:58.33333%}.large-margin-collapse>.small-8{width:66.66667%}.large-margin-collapse>.small-9{width:75%}.large-margin-collapse>.small-10{width:83.33333%}.large-margin-collapse>.small-11{width:91.66667%}.large-margin-collapse>.small-12{width:100%}}@media print,screen and (min-width:64em){.large-margin-collapse>.medium-1{width:8.33333%}.large-margin-collapse>.medium-2{width:16.66667%}.large-margin-collapse>.medium-3{width:25%}.large-margin-collapse>.medium-4{width:33.33333%}.large-margin-collapse>.medium-5{width:41.66667%}.large-margin-collapse>.medium-6{width:50%}.large-margin-collapse>.medium-7{width:58.33333%}.large-margin-collapse>.medium-8{width:66.66667%}.large-margin-collapse>.medium-9{width:75%}.large-margin-collapse>.medium-10{width:83.33333%}.large-margin-collapse>.medium-11{width:91.66667%}.large-margin-collapse>.medium-12{width:100%}}@media print,screen and (min-width:64em){.large-margin-collapse>.large-1{width:8.33333%}.large-margin-collapse>.large-2{width:16.66667%}.large-margin-collapse>.large-3{width:25%}.large-margin-collapse>.large-4{width:33.33333%}.large-margin-collapse>.large-5{width:41.66667%}.large-margin-collapse>.large-6{width:50%}.large-margin-collapse>.large-7{width:58.33333%}.large-margin-collapse>.large-8{width:66.66667%}.large-margin-collapse>.large-9{width:75%}.large-margin-collapse>.large-10{width:83.33333%}.large-margin-collapse>.large-11{width:91.66667%}.large-margin-collapse>.large-12{width:100%}}@media print,screen and (min-width:64em){.large-padding-collapse{margin-left:0;margin-right:0}.large-padding-collapse>.cell{padding-left:0;padding-right:0}}.small-offset-0{margin-left:0}.grid-margin-x>.small-offset-0{margin-left:.625rem}.small-offset-1{margin-left:8.33333%}.grid-margin-x>.small-offset-1{margin-left:calc(8.33333% + .625rem)}.small-offset-2{margin-left:16.66667%}.grid-margin-x>.small-offset-2{margin-left:calc(16.66667% + .625rem)}.small-offset-3{margin-left:25%}.grid-margin-x>.small-offset-3{margin-left:calc(25% + .625rem)}.small-offset-4{margin-left:33.33333%}.grid-margin-x>.small-offset-4{margin-left:calc(33.33333% + .625rem)}.small-offset-5{margin-left:41.66667%}.grid-margin-x>.small-offset-5{margin-left:calc(41.66667% + .625rem)}.small-offset-6{margin-left:50%}.grid-margin-x>.small-offset-6{margin-left:calc(50% + .625rem)}.small-offset-7{margin-left:58.33333%}.grid-margin-x>.small-offset-7{margin-left:calc(58.33333% + .625rem)}.small-offset-8{margin-left:66.66667%}.grid-margin-x>.small-offset-8{margin-left:calc(66.66667% + .625rem)}.small-offset-9{margin-left:75%}.grid-margin-x>.small-offset-9{margin-left:calc(75% + .625rem)}.small-offset-10{margin-left:83.33333%}.grid-margin-x>.small-offset-10{margin-left:calc(83.33333% + .625rem)}.small-offset-11{margin-left:91.66667%}.grid-margin-x>.small-offset-11{margin-left:calc(91.66667% + .625rem)}@media print,screen and (min-width:40em){.medium-offset-0{margin-left:0}.grid-margin-x>.medium-offset-0{margin-left:.9375rem}.medium-offset-1{margin-left:8.33333%}.grid-margin-x>.medium-offset-1{margin-left:calc(8.33333% + .9375rem)}.medium-offset-2{margin-left:16.66667%}.grid-margin-x>.medium-offset-2{margin-left:calc(16.66667% + .9375rem)}.medium-offset-3{margin-left:25%}.grid-margin-x>.medium-offset-3{margin-left:calc(25% + .9375rem)}.medium-offset-4{margin-left:33.33333%}.grid-margin-x>.medium-offset-4{margin-left:calc(33.33333% + .9375rem)}.medium-offset-5{margin-left:41.66667%}.grid-margin-x>.medium-offset-5{margin-left:calc(41.66667% + .9375rem)}.medium-offset-6{margin-left:50%}.grid-margin-x>.medium-offset-6{margin-left:calc(50% + .9375rem)}.medium-offset-7{margin-left:58.33333%}.grid-margin-x>.medium-offset-7{margin-left:calc(58.33333% + .9375rem)}.medium-offset-8{margin-left:66.66667%}.grid-margin-x>.medium-offset-8{margin-left:calc(66.66667% + .9375rem)}.medium-offset-9{margin-left:75%}.grid-margin-x>.medium-offset-9{margin-left:calc(75% + .9375rem)}.medium-offset-10{margin-left:83.33333%}.grid-margin-x>.medium-offset-10{margin-left:calc(83.33333% + .9375rem)}.medium-offset-11{margin-left:91.66667%}.grid-margin-x>.medium-offset-11{margin-left:calc(91.66667% + .9375rem)}}@media print,screen and (min-width:64em){.large-offset-0{margin-left:0}.grid-margin-x>.large-offset-0{margin-left:.9375rem}.large-offset-1{margin-left:8.33333%}.grid-margin-x>.large-offset-1{margin-left:calc(8.33333% + .9375rem)}.large-offset-2{margin-left:16.66667%}.grid-margin-x>.large-offset-2{margin-left:calc(16.66667% + .9375rem)}.large-offset-3{margin-left:25%}.grid-margin-x>.large-offset-3{margin-left:calc(25% + .9375rem)}.large-offset-4{margin-left:33.33333%}.grid-margin-x>.large-offset-4{margin-left:calc(33.33333% + .9375rem)}.large-offset-5{margin-left:41.66667%}.grid-margin-x>.large-offset-5{margin-left:calc(41.66667% + .9375rem)}.large-offset-6{margin-left:50%}.grid-margin-x>.large-offset-6{margin-left:calc(50% + .9375rem)}.large-offset-7{margin-left:58.33333%}.grid-margin-x>.large-offset-7{margin-left:calc(58.33333% + .9375rem)}.large-offset-8{margin-left:66.66667%}.grid-margin-x>.large-offset-8{margin-left:calc(66.66667% + .9375rem)}.large-offset-9{margin-left:75%}.grid-margin-x>.large-offset-9{margin-left:calc(75% + .9375rem)}.large-offset-10{margin-left:83.33333%}.grid-margin-x>.large-offset-10{margin-left:calc(83.33333% + .9375rem)}.large-offset-11{margin-left:91.66667%}.grid-margin-x>.large-offset-11{margin-left:calc(91.66667% + .9375rem)}}.grid-y{-webkit-box-orient:vertical;-webkit-box-direction:normal;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-flow:column nowrap;-ms-flex-flow:column nowrap;flex-flow:column nowrap}.grid-y>.cell{height:auto;max-height:none}.grid-y>.auto{height:auto}.grid-y>.shrink{height:auto}.grid-y>.small-1,.grid-y>.small-2,.grid-y>.small-3,.grid-y>.small-4,.grid-y>.small-5,.grid-y>.small-6,.grid-y>.small-7,.grid-y>.small-8,.grid-y>.small-9,.grid-y>.small-10,.grid-y>.small-11,.grid-y>.small-12,.grid-y>.small-full,.grid-y>.small-shrink{-ms-flex-preferred-size:auto;-webkit-flex-basis:auto;flex-basis:auto}@media print,screen and (min-width:40em){.grid-y>.medium-1,.grid-y>.medium-2,.grid-y>.medium-3,.grid-y>.medium-4,.grid-y>.medium-5,.grid-y>.medium-6,.grid-y>.medium-7,.grid-y>.medium-8,.grid-y>.medium-9,.grid-y>.medium-10,.grid-y>.medium-11,.grid-y>.medium-12,.grid-y>.medium-full,.grid-y>.medium-shrink{-ms-flex-preferred-size:auto;-webkit-flex-basis:auto;flex-basis:auto}}@media print,screen and (min-width:64em){.grid-y>.large-1,.grid-y>.large-2,.grid-y>.large-3,.grid-y>.large-4,.grid-y>.large-5,.grid-y>.large-6,.grid-y>.large-7,.grid-y>.large-8,.grid-y>.large-9,.grid-y>.large-10,.grid-y>.large-11,.grid-y>.large-12,.grid-y>.large-full,.grid-y>.large-shrink{-ms-flex-preferred-size:auto;-webkit-flex-basis:auto;flex-basis:auto}}.grid-y>.small-1,.grid-y>.small-2,.grid-y>.small-3,.grid-y>.small-4,.grid-y>.small-5,.grid-y>.small-6,.grid-y>.small-7,.grid-y>.small-8,.grid-y>.small-9,.grid-y>.small-10,.grid-y>.small-11,.grid-y>.small-12{-webkit-box-flex:0;-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto}.grid-y>.small-1{height:8.33333%}.grid-y>.small-2{height:16.66667%}.grid-y>.small-3{height:25%}.grid-y>.small-4{height:33.33333%}.grid-y>.small-5{height:41.66667%}.grid-y>.small-6{height:50%}.grid-y>.small-7{height:58.33333%}.grid-y>.small-8{height:66.66667%}.grid-y>.small-9{height:75%}.grid-y>.small-10{height:83.33333%}.grid-y>.small-11{height:91.66667%}.grid-y>.small-12{height:100%}@media print,screen and (min-width:40em){.grid-y>.medium-auto{-webkit-box-flex:1;-webkit-flex:1 1 0;-ms-flex:1 1 0px;flex:1 1 0;height:auto}.grid-y>.medium-1,.grid-y>.medium-2,.grid-y>.medium-3,.grid-y>.medium-4,.grid-y>.medium-5,.grid-y>.medium-6,.grid-y>.medium-7,.grid-y>.medium-8,.grid-y>.medium-9,.grid-y>.medium-10,.grid-y>.medium-11,.grid-y>.medium-12,.grid-y>.medium-shrink{-webkit-box-flex:0;-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto}.grid-y>.medium-shrink{height:auto}.grid-y>.medium-1{height:8.33333%}.grid-y>.medium-2{height:16.66667%}.grid-y>.medium-3{height:25%}.grid-y>.medium-4{height:33.33333%}.grid-y>.medium-5{height:41.66667%}.grid-y>.medium-6{height:50%}.grid-y>.medium-7{height:58.33333%}.grid-y>.medium-8{height:66.66667%}.grid-y>.medium-9{height:75%}.grid-y>.medium-10{height:83.33333%}.grid-y>.medium-11{height:91.66667%}.grid-y>.medium-12{height:100%}}@media print,screen and (min-width:64em){.grid-y>.large-auto{-webkit-box-flex:1;-webkit-flex:1 1 0;-ms-flex:1 1 0px;flex:1 1 0;height:auto}.grid-y>.large-1,.grid-y>.large-2,.grid-y>.large-3,.grid-y>.large-4,.grid-y>.large-5,.grid-y>.large-6,.grid-y>.large-7,.grid-y>.large-8,.grid-y>.large-9,.grid-y>.large-10,.grid-y>.large-11,.grid-y>.large-12,.grid-y>.large-shrink{-webkit-box-flex:0;-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto}.grid-y>.large-shrink{height:auto}.grid-y>.large-1{height:8.33333%}.grid-y>.large-2{height:16.66667%}.grid-y>.large-3{height:25%}.grid-y>.large-4{height:33.33333%}.grid-y>.large-5{height:41.66667%}.grid-y>.large-6{height:50%}.grid-y>.large-7{height:58.33333%}.grid-y>.large-8{height:66.66667%}.grid-y>.large-9{height:75%}.grid-y>.large-10{height:83.33333%}.grid-y>.large-11{height:91.66667%}.grid-y>.large-12{height:100%}}.grid-padding-y .grid-padding-y{margin-bottom:-.625rem;margin-top:-.625rem}@media print,screen and (min-width:40em){.grid-padding-y .grid-padding-y{margin-bottom:-.9375rem;margin-top:-.9375rem}}.grid-padding-y>.cell{padding-bottom:.625rem;padding-top:.625rem}@media print,screen and (min-width:40em){.grid-padding-y>.cell{padding-bottom:.9375rem;padding-top:.9375rem}}.grid-frame{-webkit-box-align:stretch;-ms-flex-align:stretch;-webkit-align-items:stretch;align-items:stretch;-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap;overflow:hidden;position:relative;width:100vw}.cell .grid-frame{width:100%}.cell-block{max-width:100%;overflow-x:auto}.cell-block,.cell-block-y{-webkit-overflow-scrolling:touch;-ms-overflow-style:-ms-autohiding-scrollbar}.cell-block-y{max-height:100%;min-height:100%;overflow-y:auto}.cell-block-container{-webkit-box-orient:vertical;-webkit-box-direction:normal;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;max-height:100%}.cell-block-container>.grid-x{-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap;max-height:100%}@media print,screen and (min-width:40em){.medium-grid-frame{-webkit-box-align:stretch;-ms-flex-align:stretch;-webkit-align-items:stretch;align-items:stretch;-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap;overflow:hidden;position:relative;width:100vw}.cell .medium-grid-frame{width:100%}.medium-cell-block{-webkit-overflow-scrolling:touch;-ms-overflow-style:-ms-autohiding-scrollbar;max-width:100%;overflow-x:auto}.medium-cell-block-container{-webkit-box-orient:vertical;-webkit-box-direction:normal;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;max-height:100%}.medium-cell-block-container>.grid-x{-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap;max-height:100%}.medium-cell-block-y{-webkit-overflow-scrolling:touch;-ms-overflow-style:-ms-autohiding-scrollbar;max-height:100%;min-height:100%;overflow-y:auto}}@media print,screen and (min-width:64em){.large-grid-frame{-webkit-box-align:stretch;-ms-flex-align:stretch;-webkit-align-items:stretch;align-items:stretch;-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap;overflow:hidden;position:relative;width:100vw}.cell .large-grid-frame{width:100%}.large-cell-block{-webkit-overflow-scrolling:touch;-ms-overflow-style:-ms-autohiding-scrollbar;max-width:100%;overflow-x:auto}.large-cell-block-container{-webkit-box-orient:vertical;-webkit-box-direction:normal;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;max-height:100%}.large-cell-block-container>.grid-x{-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap;max-height:100%}.large-cell-block-y{-webkit-overflow-scrolling:touch;-ms-overflow-style:-ms-autohiding-scrollbar;max-height:100%;min-height:100%;overflow-y:auto}}.grid-y.grid-frame{-webkit-box-align:stretch;-ms-flex-align:stretch;-webkit-align-items:stretch;align-items:stretch;-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap;height:100vh;overflow:hidden;position:relative;width:auto}@media print,screen and (min-width:40em){.grid-y.medium-grid-frame{-webkit-box-align:stretch;-ms-flex-align:stretch;-webkit-align-items:stretch;align-items:stretch;-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap;height:100vh;overflow:hidden;position:relative;width:auto}}@media print,screen and (min-width:64em){.grid-y.large-grid-frame{-webkit-box-align:stretch;-ms-flex-align:stretch;-webkit-align-items:stretch;align-items:stretch;-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap;height:100vh;overflow:hidden;position:relative;width:auto}}.cell .grid-y.grid-frame{height:100%}@media print,screen and (min-width:40em){.cell .grid-y.medium-grid-frame{height:100%}}@media print,screen and (min-width:64em){.cell .grid-y.large-grid-frame{height:100%}}.grid-margin-y{margin-bottom:-.625rem;margin-top:-.625rem}@media print,screen and (min-width:40em){.grid-margin-y{margin-bottom:-.9375rem;margin-top:-.9375rem}}.grid-margin-y>.cell{height:calc(100% - 1.25rem);margin-bottom:.625rem;margin-top:.625rem}@media print,screen and (min-width:40em){.grid-margin-y>.cell{height:calc(100% - 1.875rem);margin-bottom:.9375rem;margin-top:.9375rem}}.grid-margin-y>.auto{height:auto}.grid-margin-y>.shrink{height:auto}.grid-margin-y>.small-1{height:calc(8.33333% - 1.25rem)}.grid-margin-y>.small-2{height:calc(16.66667% - 1.25rem)}.grid-margin-y>.small-3{height:calc(25% - 1.25rem)}.grid-margin-y>.small-4{height:calc(33.33333% - 1.25rem)}.grid-margin-y>.small-5{height:calc(41.66667% - 1.25rem)}.grid-margin-y>.small-6{height:calc(50% - 1.25rem)}.grid-margin-y>.small-7{height:calc(58.33333% - 1.25rem)}.grid-margin-y>.small-8{height:calc(66.66667% - 1.25rem)}.grid-margin-y>.small-9{height:calc(75% - 1.25rem)}.grid-margin-y>.small-10{height:calc(83.33333% - 1.25rem)}.grid-margin-y>.small-11{height:calc(91.66667% - 1.25rem)}.grid-margin-y>.small-12{height:calc(100% - 1.25rem)}@media print,screen and (min-width:40em){.grid-margin-y>.auto{height:auto}.grid-margin-y>.shrink{height:auto}.grid-margin-y>.small-1{height:calc(8.33333% - 1.875rem)}.grid-margin-y>.small-2{height:calc(16.66667% - 1.875rem)}.grid-margin-y>.small-3{height:calc(25% - 1.875rem)}.grid-margin-y>.small-4{height:calc(33.33333% - 1.875rem)}.grid-margin-y>.small-5{height:calc(41.66667% - 1.875rem)}.grid-margin-y>.small-6{height:calc(50% - 1.875rem)}.grid-margin-y>.small-7{height:calc(58.33333% - 1.875rem)}.grid-margin-y>.small-8{height:calc(66.66667% - 1.875rem)}.grid-margin-y>.small-9{height:calc(75% - 1.875rem)}.grid-margin-y>.small-10{height:calc(83.33333% - 1.875rem)}.grid-margin-y>.small-11{height:calc(91.66667% - 1.875rem)}.grid-margin-y>.small-12{height:calc(100% - 1.875rem)}.grid-margin-y>.medium-auto{height:auto}.grid-margin-y>.medium-shrink{height:auto}.grid-margin-y>.medium-1{height:calc(8.33333% - 1.875rem)}.grid-margin-y>.medium-2{height:calc(16.66667% - 1.875rem)}.grid-margin-y>.medium-3{height:calc(25% - 1.875rem)}.grid-margin-y>.medium-4{height:calc(33.33333% - 1.875rem)}.grid-margin-y>.medium-5{height:calc(41.66667% - 1.875rem)}.grid-margin-y>.medium-6{height:calc(50% - 1.875rem)}.grid-margin-y>.medium-7{height:calc(58.33333% - 1.875rem)}.grid-margin-y>.medium-8{height:calc(66.66667% - 1.875rem)}.grid-margin-y>.medium-9{height:calc(75% - 1.875rem)}.grid-margin-y>.medium-10{height:calc(83.33333% - 1.875rem)}.grid-margin-y>.medium-11{height:calc(91.66667% - 1.875rem)}.grid-margin-y>.medium-12{height:calc(100% - 1.875rem)}}@media print,screen and (min-width:64em){.grid-margin-y>.large-auto{height:auto}.grid-margin-y>.large-shrink{height:auto}.grid-margin-y>.large-1{height:calc(8.33333% - 1.875rem)}.grid-margin-y>.large-2{height:calc(16.66667% - 1.875rem)}.grid-margin-y>.large-3{height:calc(25% - 1.875rem)}.grid-margin-y>.large-4{height:calc(33.33333% - 1.875rem)}.grid-margin-y>.large-5{height:calc(41.66667% - 1.875rem)}.grid-margin-y>.large-6{height:calc(50% - 1.875rem)}.grid-margin-y>.large-7{height:calc(58.33333% - 1.875rem)}.grid-margin-y>.large-8{height:calc(66.66667% - 1.875rem)}.grid-margin-y>.large-9{height:calc(75% - 1.875rem)}.grid-margin-y>.large-10{height:calc(83.33333% - 1.875rem)}.grid-margin-y>.large-11{height:calc(91.66667% - 1.875rem)}.grid-margin-y>.large-12{height:calc(100% - 1.875rem)}}.grid-frame.grid-margin-y{height:calc(100vh + 1.25rem)}@media print,screen and (min-width:40em){.grid-frame.grid-margin-y{height:calc(100vh + 1.875rem)}}@media print,screen and (min-width:64em){.grid-frame.grid-margin-y{height:calc(100vh + 1.875rem)}}@media print,screen and (min-width:40em){.grid-margin-y.medium-grid-frame{height:calc(100vh + 1.875rem)}}@media print,screen and (min-width:64em){.grid-margin-y.large-grid-frame{height:calc(100vh + 1.875rem)}}.button{-webkit-appearance:none;border:1px solid transparent;border-radius:0;cursor:pointer;display:inline-block;font-family:inherit;font-size:.9rem;line-height:1;margin:0 0 1rem;padding:.85em 1em;text-align:center;-webkit-transition:background-color .25s ease-out,color .25s ease-out;transition:background-color .25s ease-out,color .25s ease-out;vertical-align:middle}[data-whatinput=mouse] .button{outline:0}.button.tiny{font-size:.6rem}.button.small{font-size:.75rem}.button.large{font-size:1.25rem}.button.expanded{display:block;margin-left:0;margin-right:0;width:100%}.button,.button.disabled,.button.disabled:focus,.button.disabled:hover,.button[disabled],.button[disabled]:focus,.button[disabled]:hover{background-color:#1779ba;color:#fefefe}.button:focus,.button:hover{background-color:#14679e;color:#fefefe}.button.primary,.button.primary.disabled,.button.primary.disabled:focus,.button.primary.disabled:hover,.button.primary[disabled],.button.primary[disabled]:focus,.button.primary[disabled]:hover{background-color:#1779ba;color:#fefefe}.button.primary:focus,.button.primary:hover{background-color:#126195;color:#fefefe}.button.secondary,.button.secondary.disabled,.button.secondary.disabled:focus,.button.secondary.disabled:hover,.button.secondary[disabled],.button.secondary[disabled]:focus,.button.secondary[disabled]:hover{background-color:#767676;color:#fefefe}.button.secondary:focus,.button.secondary:hover{background-color:#5e5e5e;color:#fefefe}.button.success,.button.success.disabled,.button.success.disabled:focus,.button.success.disabled:hover,.button.success[disabled],.button.success[disabled]:focus,.button.success[disabled]:hover{background-color:#3adb76;color:#0a0a0a}.button.success:focus,.button.success:hover{background-color:#22bb5b;color:#0a0a0a}.button.warning,.button.warning.disabled,.button.warning.disabled:focus,.button.warning.disabled:hover,.button.warning[disabled],.button.warning[disabled]:focus,.button.warning[disabled]:hover{background-color:#ffae00;color:#0a0a0a}.button.warning:focus,.button.warning:hover{background-color:#cc8b00;color:#0a0a0a}.button.alert,.button.alert.disabled,.button.alert.disabled:focus,.button.alert.disabled:hover,.button.alert[disabled],.button.alert[disabled]:focus,.button.alert[disabled]:hover{background-color:#cc4b37;color:#fefefe}.button.alert:focus,.button.alert:hover{background-color:#a53b2a;color:#fefefe}.button.hollow,.button.hollow.disabled,.button.hollow.disabled:focus,.button.hollow.disabled:hover,.button.hollow:focus,.button.hollow:hover,.button.hollow[disabled],.button.hollow[disabled]:focus,.button.hollow[disabled]:hover{background-color:transparent}.button.hollow,.button.hollow.disabled,.button.hollow.disabled:focus,.button.hollow.disabled:hover,.button.hollow[disabled],.button.hollow[disabled]:focus,.button.hollow[disabled]:hover{border:1px solid #1779ba;color:#1779ba}.button.hollow:focus,.button.hollow:hover{border-color:#0c3d5d;color:#0c3d5d}.button.hollow.primary,.button.hollow.primary.disabled,.button.hollow.primary.disabled:focus,.button.hollow.primary.disabled:hover,.button.hollow.primary[disabled],.button.hollow.primary[disabled]:focus,.button.hollow.primary[disabled]:hover{border:1px solid #1779ba;color:#1779ba}.button.hollow.primary:focus,.button.hollow.primary:hover{border-color:#0c3d5d;color:#0c3d5d}.button.hollow.secondary,.button.hollow.secondary.disabled,.button.hollow.secondary.disabled:focus,.button.hollow.secondary.disabled:hover,.button.hollow.secondary[disabled],.button.hollow.secondary[disabled]:focus,.button.hollow.secondary[disabled]:hover{border:1px solid #767676;color:#767676}.button.hollow.secondary:focus,.button.hollow.secondary:hover{border-color:#3b3b3b;color:#3b3b3b}.button.hollow.success,.button.hollow.success.disabled,.button.hollow.success.disabled:focus,.button.hollow.success.disabled:hover,.button.hollow.success[disabled],.button.hollow.success[disabled]:focus,.button.hollow.success[disabled]:hover{border:1px solid #3adb76;color:#3adb76}.button.hollow.success:focus,.button.hollow.success:hover{border-color:#157539;color:#157539}.button.hollow.warning,.button.hollow.warning.disabled,.button.hollow.warning.disabled:focus,.button.hollow.warning.disabled:hover,.button.hollow.warning[disabled],.button.hollow.warning[disabled]:focus,.button.hollow.warning[disabled]:hover{border:1px solid #ffae00;color:#ffae00}.button.hollow.warning:focus,.button.hollow.warning:hover{border-color:#805700;color:#805700}.button.hollow.alert,.button.hollow.alert.disabled,.button.hollow.alert.disabled:focus,.button.hollow.alert.disabled:hover,.button.hollow.alert[disabled],.button.hollow.alert[disabled]:focus,.button.hollow.alert[disabled]:hover{border:1px solid #cc4b37;color:#cc4b37}.button.hollow.alert:focus,.button.hollow.alert:hover{border-color:#67251a;color:#67251a}.button.clear,.button.clear.disabled,.button.clear.disabled:focus,.button.clear.disabled:hover,.button.clear:focus,.button.clear:hover,.button.clear[disabled],.button.clear[disabled]:focus,.button.clear[disabled]:hover{background-color:transparent;border-color:transparent}.button.clear,.button.clear.disabled,.button.clear.disabled:focus,.button.clear.disabled:hover,.button.clear[disabled],.button.clear[disabled]:focus,.button.clear[disabled]:hover{color:#1779ba}.button.clear:focus,.button.clear:hover{color:#0c3d5d}.button.clear.primary,.button.clear.primary.disabled,.button.clear.primary.disabled:focus,.button.clear.primary.disabled:hover,.button.clear.primary[disabled],.button.clear.primary[disabled]:focus,.button.clear.primary[disabled]:hover{color:#1779ba}.button.clear.primary:focus,.button.clear.primary:hover{color:#0c3d5d}.button.clear.secondary,.button.clear.secondary.disabled,.button.clear.secondary.disabled:focus,.button.clear.secondary.disabled:hover,.button.clear.secondary[disabled],.button.clear.secondary[disabled]:focus,.button.clear.secondary[disabled]:hover{color:#767676}.button.clear.secondary:focus,.button.clear.secondary:hover{color:#3b3b3b}.button.clear.success,.button.clear.success.disabled,.button.clear.success.disabled:focus,.button.clear.success.disabled:hover,.button.clear.success[disabled],.button.clear.success[disabled]:focus,.button.clear.success[disabled]:hover{color:#3adb76}.button.clear.success:focus,.button.clear.success:hover{color:#157539}.button.clear.warning,.button.clear.warning.disabled,.button.clear.warning.disabled:focus,.button.clear.warning.disabled:hover,.button.clear.warning[disabled],.button.clear.warning[disabled]:focus,.button.clear.warning[disabled]:hover{color:#ffae00}.button.clear.warning:focus,.button.clear.warning:hover{color:#805700}.button.clear.alert,.button.clear.alert.disabled,.button.clear.alert.disabled:focus,.button.clear.alert.disabled:hover,.button.clear.alert[disabled],.button.clear.alert[disabled]:focus,.button.clear.alert[disabled]:hover{color:#cc4b37}.button.clear.alert:focus,.button.clear.alert:hover{color:#67251a}.button.disabled,.button[disabled]{cursor:not-allowed;opacity:.25}.button.dropdown:after{border-color:#fefefe transparent transparent;border-style:solid;border-width:.4em .4em 0;content:"";display:block;display:inline-block;float:right;height:0;margin-left:1em;position:relative;top:.4em;width:0}.button.dropdown.clear:after,.button.dropdown.hollow:after{border-top-color:#1779ba}.button.dropdown.clear.primary:after,.button.dropdown.hollow.primary:after{border-top-color:#1779ba}.button.dropdown.clear.secondary:after,.button.dropdown.hollow.secondary:after{border-top-color:#767676}.button.dropdown.clear.success:after,.button.dropdown.hollow.success:after{border-top-color:#3adb76}.button.dropdown.clear.warning:after,.button.dropdown.hollow.warning:after{border-top-color:#ffae00}.button.dropdown.clear.alert:after,.button.dropdown.hollow.alert:after{border-top-color:#cc4b37}.button.arrow-only:after{float:none;margin-left:0;top:-.1em}a.button:focus,a.button:hover{text-decoration:none}.button-group{-webkit-box-align:stretch;-ms-flex-align:stretch;-webkit-box-flex:1;-ms-flex-positive:1;-webkit-align-items:stretch;align-items:stretch;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-grow:1;flex-grow:1;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;margin-bottom:1rem}.button-group:after,.button-group:before{-ms-flex-preferred-size:0;-webkit-box-ordinal-group:2;-ms-flex-order:1;content:" ";display:table;-webkit-flex-basis:0;flex-basis:0;-webkit-order:1;order:1}.button-group:after{clear:both}.button-group:after,.button-group:before{display:none}.button-group .button{-webkit-box-flex:0;-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto;font-size:.9rem;margin:0 1px 1px 0}.button-group .button:last-child{margin-right:0}.button-group.tiny .button{font-size:.6rem}.button-group.small .button{font-size:.75rem}.button-group.large .button{font-size:1.25rem}.button-group.expanded .button{-webkit-box-flex:1;-webkit-flex:1 1 0px;-ms-flex:1 1 0px;flex:1 1 0px}.button-group.primary .button,.button-group.primary .button.disabled,.button-group.primary .button.disabled:focus,.button-group.primary .button.disabled:hover,.button-group.primary .button[disabled],.button-group.primary .button[disabled]:focus,.button-group.primary .button[disabled]:hover{background-color:#1779ba;color:#fefefe}.button-group.primary .button:focus,.button-group.primary .button:hover{background-color:#126195;color:#fefefe}.button-group.secondary .button,.button-group.secondary .button.disabled,.button-group.secondary .button.disabled:focus,.button-group.secondary .button.disabled:hover,.button-group.secondary .button[disabled],.button-group.secondary .button[disabled]:focus,.button-group.secondary .button[disabled]:hover{background-color:#767676;color:#fefefe}.button-group.secondary .button:focus,.button-group.secondary .button:hover{background-color:#5e5e5e;color:#fefefe}.button-group.success .button,.button-group.success .button.disabled,.button-group.success .button.disabled:focus,.button-group.success .button.disabled:hover,.button-group.success .button[disabled],.button-group.success .button[disabled]:focus,.button-group.success .button[disabled]:hover{background-color:#3adb76;color:#0a0a0a}.button-group.success .button:focus,.button-group.success .button:hover{background-color:#22bb5b;color:#0a0a0a}.button-group.warning .button,.button-group.warning .button.disabled,.button-group.warning .button.disabled:focus,.button-group.warning .button.disabled:hover,.button-group.warning .button[disabled],.button-group.warning .button[disabled]:focus,.button-group.warning .button[disabled]:hover{background-color:#ffae00;color:#0a0a0a}.button-group.warning .button:focus,.button-group.warning .button:hover{background-color:#cc8b00;color:#0a0a0a}.button-group.alert .button,.button-group.alert .button.disabled,.button-group.alert .button.disabled:focus,.button-group.alert .button.disabled:hover,.button-group.alert .button[disabled],.button-group.alert .button[disabled]:focus,.button-group.alert .button[disabled]:hover{background-color:#cc4b37;color:#fefefe}.button-group.alert .button:focus,.button-group.alert .button:hover{background-color:#a53b2a;color:#fefefe}.button-group.hollow .button,.button-group.hollow .button.disabled,.button-group.hollow .button.disabled:focus,.button-group.hollow .button.disabled:hover,.button-group.hollow .button:focus,.button-group.hollow .button:hover,.button-group.hollow .button[disabled],.button-group.hollow .button[disabled]:focus,.button-group.hollow .button[disabled]:hover{background-color:transparent}.button-group.hollow .button,.button-group.hollow .button.disabled,.button-group.hollow .button.disabled:focus,.button-group.hollow .button.disabled:hover,.button-group.hollow .button[disabled],.button-group.hollow .button[disabled]:focus,.button-group.hollow .button[disabled]:hover{border:1px solid #1779ba;color:#1779ba}.button-group.hollow .button:focus,.button-group.hollow .button:hover{border-color:#0c3d5d;color:#0c3d5d}.button-group.hollow .button.primary,.button-group.hollow .button.primary.disabled,.button-group.hollow .button.primary.disabled:focus,.button-group.hollow .button.primary.disabled:hover,.button-group.hollow .button.primary[disabled],.button-group.hollow .button.primary[disabled]:focus,.button-group.hollow .button.primary[disabled]:hover,.button-group.hollow.primary .button,.button-group.hollow.primary .button.disabled,.button-group.hollow.primary .button.disabled:focus,.button-group.hollow.primary .button.disabled:hover,.button-group.hollow.primary .button[disabled],.button-group.hollow.primary .button[disabled]:focus,.button-group.hollow.primary .button[disabled]:hover{border:1px solid #1779ba;color:#1779ba}.button-group.hollow .button.primary:focus,.button-group.hollow .button.primary:hover,.button-group.hollow.primary .button:focus,.button-group.hollow.primary .button:hover{border-color:#0c3d5d;color:#0c3d5d}.button-group.hollow .button.secondary,.button-group.hollow .button.secondary.disabled,.button-group.hollow .button.secondary.disabled:focus,.button-group.hollow .button.secondary.disabled:hover,.button-group.hollow .button.secondary[disabled],.button-group.hollow .button.secondary[disabled]:focus,.button-group.hollow .button.secondary[disabled]:hover,.button-group.hollow.secondary .button,.button-group.hollow.secondary .button.disabled,.button-group.hollow.secondary .button.disabled:focus,.button-group.hollow.secondary .button.disabled:hover,.button-group.hollow.secondary .button[disabled],.button-group.hollow.secondary .button[disabled]:focus,.button-group.hollow.secondary .button[disabled]:hover{border:1px solid #767676;color:#767676}.button-group.hollow .button.secondary:focus,.button-group.hollow .button.secondary:hover,.button-group.hollow.secondary .button:focus,.button-group.hollow.secondary .button:hover{border-color:#3b3b3b;color:#3b3b3b}.button-group.hollow .button.success,.button-group.hollow .button.success.disabled,.button-group.hollow .button.success.disabled:focus,.button-group.hollow .button.success.disabled:hover,.button-group.hollow .button.success[disabled],.button-group.hollow .button.success[disabled]:focus,.button-group.hollow .button.success[disabled]:hover,.button-group.hollow.success .button,.button-group.hollow.success .button.disabled,.button-group.hollow.success .button.disabled:focus,.button-group.hollow.success .button.disabled:hover,.button-group.hollow.success .button[disabled],.button-group.hollow.success .button[disabled]:focus,.button-group.hollow.success .button[disabled]:hover{border:1px solid #3adb76;color:#3adb76}.button-group.hollow .button.success:focus,.button-group.hollow .button.success:hover,.button-group.hollow.success .button:focus,.button-group.hollow.success .button:hover{border-color:#157539;color:#157539}.button-group.hollow .button.warning,.button-group.hollow .button.warning.disabled,.button-group.hollow .button.warning.disabled:focus,.button-group.hollow .button.warning.disabled:hover,.button-group.hollow .button.warning[disabled],.button-group.hollow .button.warning[disabled]:focus,.button-group.hollow .button.warning[disabled]:hover,.button-group.hollow.warning .button,.button-group.hollow.warning .button.disabled,.button-group.hollow.warning .button.disabled:focus,.button-group.hollow.warning .button.disabled:hover,.button-group.hollow.warning .button[disabled],.button-group.hollow.warning .button[disabled]:focus,.button-group.hollow.warning .button[disabled]:hover{border:1px solid #ffae00;color:#ffae00}.button-group.hollow .button.warning:focus,.button-group.hollow .button.warning:hover,.button-group.hollow.warning .button:focus,.button-group.hollow.warning .button:hover{border-color:#805700;color:#805700}.button-group.hollow.alert .button,.button-group.hollow.alert .button.disabled,.button-group.hollow.alert .button.disabled:focus,.button-group.hollow.alert .button.disabled:hover,.button-group.hollow.alert .button[disabled],.button-group.hollow.alert .button[disabled]:focus,.button-group.hollow.alert .button[disabled]:hover,.button-group.hollow .button.alert,.button-group.hollow .button.alert.disabled,.button-group.hollow .button.alert.disabled:focus,.button-group.hollow .button.alert.disabled:hover,.button-group.hollow .button.alert[disabled],.button-group.hollow .button.alert[disabled]:focus,.button-group.hollow .button.alert[disabled]:hover{border:1px solid #cc4b37;color:#cc4b37}.button-group.hollow.alert .button:focus,.button-group.hollow.alert .button:hover,.button-group.hollow .button.alert:focus,.button-group.hollow .button.alert:hover{border-color:#67251a;color:#67251a}.button-group.clear .button,.button-group.clear .button.disabled,.button-group.clear .button.disabled:focus,.button-group.clear .button.disabled:hover,.button-group.clear .button:focus,.button-group.clear .button:hover,.button-group.clear .button[disabled],.button-group.clear .button[disabled]:focus,.button-group.clear .button[disabled]:hover{background-color:transparent;border-color:transparent}.button-group.clear .button,.button-group.clear .button.disabled,.button-group.clear .button.disabled:focus,.button-group.clear .button.disabled:hover,.button-group.clear .button[disabled],.button-group.clear .button[disabled]:focus,.button-group.clear .button[disabled]:hover{color:#1779ba}.button-group.clear .button:focus,.button-group.clear .button:hover{color:#0c3d5d}.button-group.clear .button.primary,.button-group.clear .button.primary.disabled,.button-group.clear .button.primary.disabled:focus,.button-group.clear .button.primary.disabled:hover,.button-group.clear .button.primary[disabled],.button-group.clear .button.primary[disabled]:focus,.button-group.clear .button.primary[disabled]:hover,.button-group.clear.primary .button,.button-group.clear.primary .button.disabled,.button-group.clear.primary .button.disabled:focus,.button-group.clear.primary .button.disabled:hover,.button-group.clear.primary .button[disabled],.button-group.clear.primary .button[disabled]:focus,.button-group.clear.primary .button[disabled]:hover{color:#1779ba}.button-group.clear .button.primary:focus,.button-group.clear .button.primary:hover,.button-group.clear.primary .button:focus,.button-group.clear.primary .button:hover{color:#0c3d5d}.button-group.clear .button.secondary,.button-group.clear .button.secondary.disabled,.button-group.clear .button.secondary.disabled:focus,.button-group.clear .button.secondary.disabled:hover,.button-group.clear .button.secondary[disabled],.button-group.clear .button.secondary[disabled]:focus,.button-group.clear .button.secondary[disabled]:hover,.button-group.clear.secondary .button,.button-group.clear.secondary .button.disabled,.button-group.clear.secondary .button.disabled:focus,.button-group.clear.secondary .button.disabled:hover,.button-group.clear.secondary .button[disabled],.button-group.clear.secondary .button[disabled]:focus,.button-group.clear.secondary .button[disabled]:hover{color:#767676}.button-group.clear .button.secondary:focus,.button-group.clear .button.secondary:hover,.button-group.clear.secondary .button:focus,.button-group.clear.secondary .button:hover{color:#3b3b3b}.button-group.clear .button.success,.button-group.clear .button.success.disabled,.button-group.clear .button.success.disabled:focus,.button-group.clear .button.success.disabled:hover,.button-group.clear .button.success[disabled],.button-group.clear .button.success[disabled]:focus,.button-group.clear .button.success[disabled]:hover,.button-group.clear.success .button,.button-group.clear.success .button.disabled,.button-group.clear.success .button.disabled:focus,.button-group.clear.success .button.disabled:hover,.button-group.clear.success .button[disabled],.button-group.clear.success .button[disabled]:focus,.button-group.clear.success .button[disabled]:hover{color:#3adb76}.button-group.clear .button.success:focus,.button-group.clear .button.success:hover,.button-group.clear.success .button:focus,.button-group.clear.success .button:hover{color:#157539}.button-group.clear .button.warning,.button-group.clear .button.warning.disabled,.button-group.clear .button.warning.disabled:focus,.button-group.clear .button.warning.disabled:hover,.button-group.clear .button.warning[disabled],.button-group.clear .button.warning[disabled]:focus,.button-group.clear .button.warning[disabled]:hover,.button-group.clear.warning .button,.button-group.clear.warning .button.disabled,.button-group.clear.warning .button.disabled:focus,.button-group.clear.warning .button.disabled:hover,.button-group.clear.warning .button[disabled],.button-group.clear.warning .button[disabled]:focus,.button-group.clear.warning .button[disabled]:hover{color:#ffae00}.button-group.clear .button.warning:focus,.button-group.clear .button.warning:hover,.button-group.clear.warning .button:focus,.button-group.clear.warning .button:hover{color:#805700}.button-group.clear.alert .button,.button-group.clear.alert .button.disabled,.button-group.clear.alert .button.disabled:focus,.button-group.clear.alert .button.disabled:hover,.button-group.clear.alert .button[disabled],.button-group.clear.alert .button[disabled]:focus,.button-group.clear.alert .button[disabled]:hover,.button-group.clear .button.alert,.button-group.clear .button.alert.disabled,.button-group.clear .button.alert.disabled:focus,.button-group.clear .button.alert.disabled:hover,.button-group.clear .button.alert[disabled],.button-group.clear .button.alert[disabled]:focus,.button-group.clear .button.alert[disabled]:hover{color:#cc4b37}.button-group.clear.alert .button:focus,.button-group.clear.alert .button:hover,.button-group.clear .button.alert:focus,.button-group.clear .button.alert:hover{color:#67251a}.button-group.no-gaps .button{margin-right:-.0625rem}.button-group.no-gaps .button+.button{border-left-color:transparent}.button-group.stacked,.button-group.stacked-for-medium,.button-group.stacked-for-small{-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap}.button-group.stacked-for-medium .button,.button-group.stacked-for-small .button,.button-group.stacked .button{-webkit-box-flex:0;-webkit-flex:0 0 100%;-ms-flex:0 0 100%;flex:0 0 100%}.button-group.stacked-for-medium .button:last-child,.button-group.stacked-for-small .button:last-child,.button-group.stacked .button:last-child{margin-bottom:0}.button-group.stacked-for-medium.expanded .button,.button-group.stacked-for-small.expanded .button,.button-group.stacked.expanded .button{-webkit-box-flex:1;-webkit-flex:1 1 0px;-ms-flex:1 1 0px;flex:1 1 0px}@media print,screen and (min-width:40em){.button-group.stacked-for-small .button{-webkit-box-flex:0;-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto;margin-bottom:0}}@media print,screen and (min-width:64em){.button-group.stacked-for-medium .button{-webkit-box-flex:0;-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto;margin-bottom:0}}@media print,screen and (max-width:39.99875em){.button-group.stacked-for-small.expanded{display:block}.button-group.stacked-for-small.expanded .button{display:block;margin-right:0}}@media print,screen and (max-width:63.99875em){.button-group.stacked-for-medium.expanded{display:block}.button-group.stacked-for-medium.expanded .button{display:block;margin-right:0}}.close-button{color:#8a8a8a;cursor:pointer;position:absolute;z-index:10}[data-whatinput=mouse] .close-button{outline:0}.close-button:focus,.close-button:hover{color:#0a0a0a}.close-button.small{font-size:1.5em;line-height:1;right:.66rem;top:.33em}.close-button,.close-button.medium{font-size:2em;line-height:1;right:1rem;top:.5rem}.label{border-radius:0;cursor:default;display:inline-block;font-size:.8rem;line-height:1;padding:.33333rem .5rem;white-space:nowrap}.label,.label.primary{background:#1779ba;color:#fefefe}.label.secondary{background:#767676;color:#fefefe}.label.success{background:#3adb76;color:#0a0a0a}.label.warning{background:#ffae00;color:#0a0a0a}.label.alert{background:#cc4b37;color:#fefefe}.progress{background-color:#cacaca;border-radius:0;height:1rem;margin-bottom:1rem}.progress.primary .progress-meter{background-color:#1779ba}.progress.secondary .progress-meter{background-color:#767676}.progress.success .progress-meter{background-color:#3adb76}.progress.warning .progress-meter{background-color:#ffae00}.progress.alert .progress-meter{background-color:#cc4b37}.progress-meter{background-color:#1779ba;display:block;height:100%;position:relative;width:0}.progress-meter-text{color:#fefefe;font-size:.75rem;font-weight:700;left:50%;margin:0;position:absolute;top:50%;-webkit-transform:translate(-50%,-50%);-ms-transform:translate(-50%,-50%);transform:translate(-50%,-50%);white-space:nowrap}.slider{background-color:#e6e6e6;cursor:pointer;height:.5rem;margin-bottom:2.25rem;margin-top:1.25rem;position:relative;-ms-touch-action:none;touch-action:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.slider-fill{background-color:#cacaca;display:inline-block;height:.5rem;left:0;max-width:100%;position:absolute;top:0;-webkit-transition:all .2s ease-in-out;transition:all .2s ease-in-out}.slider-fill.is-dragging{-webkit-transition:all 0s linear;transition:all 0s linear}.slider-handle{background-color:#1779ba;border-radius:0;cursor:-webkit-grab;cursor:grab;display:inline-block;height:1.4rem;left:0;position:absolute;top:50%;-ms-touch-action:manipulation;touch-action:manipulation;-webkit-transform:translateY(-50%);-ms-transform:translateY(-50%);transform:translateY(-50%);-webkit-transition:all .2s ease-in-out;transition:all .2s ease-in-out;width:1.4rem;z-index:1}[data-whatinput=mouse] .slider-handle{outline:0}.slider-handle:hover{background-color:#14679e}.slider-handle.is-dragging{cursor:-webkit-grabbing;cursor:grabbing;-webkit-transition:all 0s linear;transition:all 0s linear}.slider.disabled,.slider[disabled]{cursor:not-allowed;opacity:.25}.slider.vertical{display:inline-block;height:12.5rem;margin:0 1.25rem;-webkit-transform:scaleY(-1);-ms-transform:scaleY(-1);transform:scaleY(-1);width:.5rem}.slider.vertical .slider-fill{max-height:100%;top:0;width:.5rem}.slider.vertical .slider-handle{height:1.4rem;left:50%;position:absolute;top:0;-webkit-transform:translateX(-50%);-ms-transform:translateX(-50%);transform:translateX(-50%);width:1.4rem}.switch{color:#fefefe;font-size:.875rem;font-weight:700;height:2rem;margin-bottom:1rem;outline:0;position:relative;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.switch-input{margin-bottom:0;opacity:0;position:absolute}.switch-paddle{background:#cacaca;border-radius:0;color:inherit;cursor:pointer;display:block;font-weight:inherit;height:2rem;position:relative;-webkit-transition:all .25s ease-out;transition:all .25s ease-out;width:4rem}input+.switch-paddle{margin:0}.switch-paddle:after{background:#fefefe;border-radius:0;content:"";display:block;height:1.5rem;left:.25rem;position:absolute;top:.25rem;-webkit-transform:translateZ(0);transform:translateZ(0);-webkit-transition:all .25s ease-out;transition:all .25s ease-out;width:1.5rem}input:checked~.switch-paddle{background:#1779ba}input:checked~.switch-paddle:after{left:2.25rem}input:disabled~.switch-paddle{cursor:not-allowed;opacity:.5}[data-whatinput=mouse] input:focus~.switch-paddle{outline:0}.switch-active,.switch-inactive{position:absolute;top:50%;-webkit-transform:translateY(-50%);-ms-transform:translateY(-50%);transform:translateY(-50%)}.switch-active{display:none;left:8%}input:checked+label>.switch-active{display:block}.switch-inactive{right:15%}input:checked+label>.switch-inactive{display:none}.switch.tiny{height:1.5rem}.switch.tiny .switch-paddle{font-size:.625rem;height:1.5rem;width:3rem}.switch.tiny .switch-paddle:after{height:1rem;left:.25rem;top:.25rem;width:1rem}.switch.tiny input:checked~.switch-paddle:after{left:1.75rem}.switch.small{height:1.75rem}.switch.small .switch-paddle{font-size:.75rem;height:1.75rem;width:3.5rem}.switch.small .switch-paddle:after{height:1.25rem;left:.25rem;top:.25rem;width:1.25rem}.switch.small input:checked~.switch-paddle:after{left:2rem}.switch.large{height:2.5rem}.switch.large .switch-paddle{font-size:1rem;height:2.5rem;width:5rem}.switch.large .switch-paddle:after{height:2rem;left:.25rem;top:.25rem;width:2rem}.switch.large input:checked~.switch-paddle:after{left:2.75rem}table{border-collapse:collapse;border-radius:0;margin-bottom:1rem;width:100%}tbody,tfoot,thead{background-color:#fefefe;border:1px solid #f1f1f1}caption{font-weight:700;padding:.5rem .625rem .625rem}thead{background:#f8f8f8}tfoot,thead{color:#0a0a0a}tfoot{background:#f1f1f1}tfoot tr,thead tr{background:0 0}tfoot td,tfoot th,thead td,thead th{font-weight:700;padding:.5rem .625rem .625rem;text-align:left}tbody td,tbody th{padding:.5rem .625rem .625rem}tbody tr:nth-child(2n){background-color:#f1f1f1;border-bottom:0}table.unstriped tbody{background-color:#fefefe}table.unstriped tbody tr{background-color:#fefefe;border-bottom:1px solid #f1f1f1}@media print,screen and (max-width:63.99875em){table.stack tfoot,table.stack thead{display:none}table.stack td,table.stack th,table.stack tr{display:block}table.stack td{border-top:0}}table.scroll{display:block;overflow-x:auto;width:100%}table.hover thead tr:hover{background-color:#f3f3f3}table.hover tfoot tr:hover{background-color:#ececec}table.hover tbody tr:hover{background-color:#f9f9f9}table.hover:not(.unstriped) tr:nth-of-type(2n):hover{background-color:#ececec}.table-scroll{overflow-x:auto}.badge{border-radius:50%;display:inline-block;font-size:.6rem;min-width:2.1em;padding:.3em;text-align:center}.badge,.badge.primary{background:#1779ba;color:#fefefe}.badge.secondary{background:#767676;color:#fefefe}.badge.success{background:#3adb76;color:#0a0a0a}.badge.warning{background:#ffae00;color:#0a0a0a}.badge.alert{background:#cc4b37;color:#fefefe}.breadcrumbs{list-style:none;margin:0 0 1rem}.breadcrumbs:after,.breadcrumbs:before{-ms-flex-preferred-size:0;-webkit-box-ordinal-group:2;-ms-flex-order:1;content:" ";display:table;-webkit-flex-basis:0;flex-basis:0;-webkit-order:1;order:1}.breadcrumbs:after{clear:both}.breadcrumbs li{color:#0a0a0a;cursor:default;float:left;font-size:.6875rem;text-transform:uppercase}.breadcrumbs li:not(:last-child):after{color:#cacaca;content:"/";margin:0 .75rem;opacity:1;position:relative}.breadcrumbs a{color:#1779ba}.breadcrumbs a:hover{text-decoration:underline}.breadcrumbs .disabled{color:#cacaca;cursor:not-allowed}.callout{background-color:#fff;border:1px solid hsla(0,0%,4%,.25);border-radius:0;color:#0a0a0a;margin:0 0 1rem;padding:1rem;position:relative}.callout>:first-child{margin-top:0}.callout>:last-child{margin-bottom:0}.callout.primary{background-color:#d7ecfa;color:#0a0a0a}.callout.secondary{background-color:#eaeaea;color:#0a0a0a}.callout.success{background-color:#e1faea;color:#0a0a0a}.callout.warning{background-color:#fff3d9;color:#0a0a0a}.callout.alert{background-color:#f7e4e1;color:#0a0a0a}.callout.small{padding:.5rem}.callout.large{padding:3rem}.card{-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-box-flex:1;-ms-flex-positive:1;background:#fefefe;border:1px solid #e6e6e6;border-radius:0;-webkit-box-shadow:none;box-shadow:none;color:#0a0a0a;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;-webkit-flex-grow:1;flex-grow:1;margin-bottom:1rem;overflow:hidden}.card>:last-child{margin-bottom:0}.card-divider{-webkit-box-flex:0;background:#e6e6e6;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex:0 1 auto;-ms-flex:0 1 auto;flex:0 1 auto;padding:1rem}.card-divider>:last-child{margin-bottom:0}.card-section{-webkit-box-flex:1;-webkit-flex:1 0 auto;-ms-flex:1 0 auto;flex:1 0 auto;padding:1rem}.card-section>:last-child{margin-bottom:0}.card-image{min-height:1px}.dropdown-pane{background-color:#fefefe;border:1px solid #cacaca;border-radius:0;display:none;font-size:1rem;padding:1rem;position:absolute;visibility:hidden;width:300px;z-index:10}.dropdown-pane.is-opening{display:block}.dropdown-pane.is-open{display:block;visibility:visible}.dropdown-pane.tiny{width:100px}.dropdown-pane.small{width:200px}.dropdown-pane.large{width:400px}.pagination{margin-bottom:1rem;margin-left:0}.pagination:after,.pagination:before{-ms-flex-preferred-size:0;-webkit-box-ordinal-group:2;-ms-flex-order:1;content:" ";display:table;-webkit-flex-basis:0;flex-basis:0;-webkit-order:1;order:1}.pagination:after{clear:both}.pagination li{border-radius:0;display:none;font-size:.875rem;margin-right:.0625rem}.pagination li:first-child,.pagination li:last-child{display:inline-block}@media print,screen and (min-width:40em){.pagination li{display:inline-block}}.pagination a,.pagination button{border-radius:0;color:#0a0a0a;display:block;padding:.1875rem .625rem}.pagination a:hover,.pagination button:hover{background:#e6e6e6}.pagination .current{background:#1779ba;color:#fefefe;cursor:default;padding:.1875rem .625rem}.pagination .disabled{color:#cacaca;cursor:not-allowed;padding:.1875rem .625rem}.pagination .disabled:hover{background:0 0}.pagination .ellipsis:after{color:#0a0a0a;content:"…";padding:.1875rem .625rem}.pagination-previous.disabled:before,.pagination-previous a:before{content:"«";display:inline-block;margin-right:.5rem}.pagination-next.disabled:after,.pagination-next a:after{content:"»";display:inline-block;margin-left:.5rem}.has-tip{border-bottom:1px dotted #8a8a8a;cursor:help;display:inline-block;font-weight:700;position:relative}.tooltip{background-color:#0a0a0a;border-radius:0;color:#fefefe;font-size:80%;max-width:10rem;padding:.75rem;position:absolute;top:calc(100% + .6495rem);z-index:1200}.tooltip:before{position:absolute}.tooltip.bottom:before{border-color:transparent transparent #0a0a0a;border-style:solid;border-width:0 .75rem .75rem;bottom:100%;content:"";display:block;height:0;width:0}.tooltip.bottom.align-center:before{left:50%;-webkit-transform:translateX(-50%);-ms-transform:translateX(-50%);transform:translateX(-50%)}.tooltip.top:before{border-color:#0a0a0a transparent transparent;border-style:solid;border-width:.75rem .75rem 0;bottom:auto;content:"";display:block;height:0;top:100%;width:0}.tooltip.top.align-center:before{left:50%;-webkit-transform:translateX(-50%);-ms-transform:translateX(-50%);transform:translateX(-50%)}.tooltip.left:before{border-color:transparent transparent transparent #0a0a0a;border-style:solid;border-width:.75rem 0 .75rem .75rem;content:"";display:block;height:0;left:100%;width:0}.tooltip.left.align-center:before{bottom:auto;top:50%;-webkit-transform:translateY(-50%);-ms-transform:translateY(-50%);transform:translateY(-50%)}.tooltip.right:before{border-color:transparent #0a0a0a transparent transparent;border-style:solid;border-width:.75rem .75rem .75rem 0;content:"";display:block;height:0;left:auto;right:100%;width:0}.tooltip.right.align-center:before{bottom:auto;top:50%;-webkit-transform:translateY(-50%);-ms-transform:translateY(-50%);transform:translateY(-50%)}.tooltip.align-top:before{bottom:auto;top:10%}.tooltip.align-bottom:before{bottom:10%;top:auto}.tooltip.align-left:before{left:10%;right:auto}.tooltip.align-right:before{left:auto;right:10%}.accordion{background:#fefefe;list-style-type:none;margin-left:0}.accordion[disabled] .accordion-title{cursor:not-allowed}.accordion-item:first-child>:first-child{border-radius:0}.accordion-item:last-child>:last-child{border-radius:0}.accordion-title{border:1px solid #e6e6e6;border-bottom:0;color:#1779ba;display:block;font-size:.75rem;line-height:1;padding:1.25rem 1rem;position:relative}:last-child:not(.is-active)>.accordion-title{border-bottom:1px solid #e6e6e6;border-radius:0}.accordion-title:focus,.accordion-title:hover{background-color:#e6e6e6}.accordion-title:before{content:"+";margin-top:-.5rem;position:absolute;right:1rem;top:50%}.is-active>.accordion-title:before{content:"–"}.accordion-content{background-color:#fefefe;border:1px solid #e6e6e6;border-bottom:0;color:#0a0a0a;display:none;padding:1rem}:last-child>.accordion-content:last-child{border-bottom:1px solid #e6e6e6}.media-object{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap;margin-bottom:1rem}.media-object img{max-width:none}@media print,screen and (max-width:39.99875em){.media-object.stack-for-small{-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap}}.media-object-section{-webkit-box-flex:0;-webkit-flex:0 1 auto;-ms-flex:0 1 auto;flex:0 1 auto}.media-object-section:first-child{padding-right:1rem}.media-object-section:last-child:not(:nth-child(2)){padding-left:1rem}.media-object-section>:last-child{margin-bottom:0}@media print,screen and (max-width:39.99875em){.stack-for-small .media-object-section{-ms-flex-preferred-size:100%;-webkit-flex-basis:100%;flex-basis:100%;max-width:100%;padding:0 0 1rem}.stack-for-small .media-object-section img{width:100%}}.media-object-section.main-section{-webkit-box-flex:1;-webkit-flex:1 1 0px;-ms-flex:1 1 0px;flex:1 1 0px}.orbit,.orbit-container{position:relative}.orbit-container{height:0;list-style:none;margin:0;overflow:hidden}.orbit-slide{position:absolute;width:100%}.orbit-slide.no-motionui.is-active{left:0;top:0}.orbit-figure{margin:0}.orbit-image{margin:0;max-width:100%;width:100%}.orbit-caption{background-color:hsla(0,0%,4%,.5);bottom:0;margin-bottom:0;width:100%}.orbit-caption,.orbit-next,.orbit-previous{color:#fefefe;padding:1rem;position:absolute}.orbit-next,.orbit-previous{top:50%;-webkit-transform:translateY(-50%);-ms-transform:translateY(-50%);transform:translateY(-50%);z-index:10}[data-whatinput=mouse] .orbit-next,[data-whatinput=mouse] .orbit-previous{outline:0}.orbit-next:active,.orbit-next:focus,.orbit-next:hover,.orbit-previous:active,.orbit-previous:focus,.orbit-previous:hover{background-color:hsla(0,0%,4%,.5)}.orbit-previous{left:0}.orbit-next{left:auto;right:0}.orbit-bullets{margin-bottom:.8rem;margin-top:.8rem;position:relative;text-align:center}[data-whatinput=mouse] .orbit-bullets{outline:0}.orbit-bullets button{background-color:#cacaca;border-radius:50%;height:1.2rem;margin:.1rem;width:1.2rem}.orbit-bullets button:hover{background-color:#8a8a8a}.orbit-bullets button.is-active{background-color:#8a8a8a}.flex-video,.responsive-embed{height:0;margin-bottom:1rem;overflow:hidden;padding-bottom:75%;position:relative}.flex-video embed,.flex-video iframe,.flex-video object,.flex-video video,.responsive-embed embed,.responsive-embed iframe,.responsive-embed object,.responsive-embed video{height:100%;left:0;position:absolute;top:0;width:100%}.flex-video.widescreen,.responsive-embed.widescreen{padding-bottom:56.25%}.tabs{background:#fefefe;border:1px solid #e6e6e6;list-style-type:none;margin:0}.tabs:after,.tabs:before{-ms-flex-preferred-size:0;-webkit-box-ordinal-group:2;-ms-flex-order:1;content:" ";display:table;-webkit-flex-basis:0;flex-basis:0;-webkit-order:1;order:1}.tabs:after{clear:both}.tabs.vertical>li{display:block;float:none;width:auto}.tabs.simple>li>a{padding:0}.tabs.simple>li>a:hover{background:0 0}.tabs.primary{background:#1779ba}.tabs.primary>li>a{color:#fefefe}.tabs.primary>li>a:focus,.tabs.primary>li>a:hover{background:#1673b1}.tabs-title{float:left}.tabs-title>a{color:#1779ba;display:block;font-size:.75rem;line-height:1;padding:1.25rem 1.5rem}[data-whatinput=mouse] .tabs-title>a{outline:0}.tabs-title>a:hover{background:#fefefe;color:#1468a0}.tabs-title>a:focus,.tabs-title>a[aria-selected=true]{background:#e6e6e6;color:#1779ba}.tabs-content{background:#fefefe;border:1px solid #e6e6e6;border-top:0;color:#0a0a0a;-webkit-transition:all .5s ease;transition:all .5s ease}.tabs-content.vertical{border:1px solid #e6e6e6;border-left:0}.tabs-panel{display:none;padding:1rem}.tabs-panel.is-active{display:block}.thumbnail{border:4px solid #fefefe;border-radius:0;-webkit-box-shadow:0 0 0 1px hsla(0,0%,4%,.2);box-shadow:0 0 0 1px hsla(0,0%,4%,.2);display:inline-block;line-height:0;margin-bottom:1rem;max-width:100%}a.thumbnail{-webkit-transition:-webkit-box-shadow .2s ease-out;transition:-webkit-box-shadow .2s ease-out;transition:box-shadow .2s ease-out;transition:box-shadow .2s ease-out,-webkit-box-shadow .2s ease-out}a.thumbnail:focus,a.thumbnail:hover{-webkit-box-shadow:0 0 6px 1px rgba(23,121,186,.5);box-shadow:0 0 6px 1px rgba(23,121,186,.5)}a.thumbnail image{-webkit-box-shadow:none;box-shadow:none}.menu{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;list-style:none;margin:0;padding:0;position:relative}[data-whatinput=mouse] .menu li{outline:0}.menu .button,.menu a{display:block;line-height:1;padding:.7rem 1rem;text-decoration:none}.menu a,.menu button,.menu input,.menu select{margin-bottom:0}.menu input{display:inline-block}.menu,.menu.horizontal{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap}.menu.vertical{-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap}.menu.vertical.icon-bottom li a i,.menu.vertical.icon-bottom li a img,.menu.vertical.icon-bottom li a svg,.menu.vertical.icon-top li a i,.menu.vertical.icon-top li a img,.menu.vertical.icon-top li a svg{text-align:left}.menu.expanded li{-webkit-box-flex:1;-webkit-flex:1 1 0px;-ms-flex:1 1 0px;flex:1 1 0px}.menu.expanded.icon-bottom li a i,.menu.expanded.icon-bottom li a img,.menu.expanded.icon-bottom li a svg,.menu.expanded.icon-top li a i,.menu.expanded.icon-top li a img,.menu.expanded.icon-top li a svg{text-align:left}.menu.simple{-webkit-box-align:center;-ms-flex-align:center;-webkit-align-items:center;align-items:center}.menu.simple li+li{margin-left:1rem}.menu.simple a{padding:0}@media print,screen and (min-width:40em){.menu.medium-horizontal{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap}.menu.medium-vertical{-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap}.menu.medium-expanded li,.menu.medium-simple li{-webkit-box-flex:1;-webkit-flex:1 1 0px;-ms-flex:1 1 0px;flex:1 1 0px}}@media print,screen and (min-width:64em){.menu.large-horizontal{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap}.menu.large-vertical{-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap}.menu.large-expanded li,.menu.large-simple li{-webkit-box-flex:1;-webkit-flex:1 1 0px;-ms-flex:1 1 0px;flex:1 1 0px}}.menu.nested{margin-left:1rem;margin-right:0}.menu.icon-bottom a,.menu.icon-left a,.menu.icon-right a,.menu.icon-top a,.menu.icons a{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex}.menu.icon-left li a,.menu.nested.icon-left li a{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-flow:row nowrap;-ms-flex-flow:row nowrap;flex-flow:row nowrap}.menu.icon-left li a i,.menu.icon-left li a img,.menu.icon-left li a svg,.menu.nested.icon-left li a i,.menu.nested.icon-left li a img,.menu.nested.icon-left li a svg{margin-right:.25rem}.menu.icon-right li a,.menu.nested.icon-right li a{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-flow:row nowrap;-ms-flex-flow:row nowrap;flex-flow:row nowrap}.menu.icon-right li a i,.menu.icon-right li a img,.menu.icon-right li a svg,.menu.nested.icon-right li a i,.menu.nested.icon-right li a img,.menu.nested.icon-right li a svg{margin-left:.25rem}.menu.icon-top li a,.menu.nested.icon-top li a{-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-flow:column nowrap;-ms-flex-flow:column nowrap;flex-flow:column nowrap}.menu.icon-top li a i,.menu.icon-top li a img,.menu.icon-top li a svg,.menu.nested.icon-top li a i,.menu.nested.icon-top li a img,.menu.nested.icon-top li a svg{-ms-flex-item-align:stretch;-webkit-align-self:stretch;align-self:stretch;margin-bottom:.25rem;text-align:center}.menu.icon-bottom li a,.menu.nested.icon-bottom li a{-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-flow:column nowrap;-ms-flex-flow:column nowrap;flex-flow:column nowrap}.menu.icon-bottom li a i,.menu.icon-bottom li a img,.menu.icon-bottom li a svg,.menu.nested.icon-bottom li a i,.menu.nested.icon-bottom li a img,.menu.nested.icon-bottom li a svg{-ms-flex-item-align:stretch;-webkit-align-self:stretch;align-self:stretch;margin-bottom:.25rem;text-align:center}.menu .is-active>a{background:#1779ba;color:#fefefe}.menu .active>a{background:#1779ba;color:#fefefe}.menu.align-left{-webkit-box-pack:start;-ms-flex-pack:start;-webkit-justify-content:flex-start;justify-content:flex-start}.menu.align-right li{-webkit-box-pack:end;-ms-flex-pack:end;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-justify-content:flex-end;justify-content:flex-end}.menu.align-right li .submenu li{-webkit-box-pack:start;-ms-flex-pack:start;-webkit-justify-content:flex-start;justify-content:flex-start}.menu.align-right.vertical li{display:block;text-align:right}.menu.align-right.icon-bottom li a i,.menu.align-right.icon-bottom li a img,.menu.align-right.icon-bottom li a svg,.menu.align-right.icon-top li a i,.menu.align-right.icon-top li a img,.menu.align-right.icon-top li a svg,.menu.align-right.vertical li .submenu li{text-align:right}.menu.align-right .nested{margin-left:0;margin-right:1rem}.menu.align-center li{-webkit-box-pack:center;-ms-flex-pack:center;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-justify-content:center;justify-content:center}.menu.align-center li .submenu li{-webkit-box-pack:start;-ms-flex-pack:start;-webkit-justify-content:flex-start;justify-content:flex-start}.menu .menu-text{color:inherit;font-weight:700;line-height:1;padding:.7rem 1rem}.menu-centered>.menu{-webkit-box-pack:center;-ms-flex-pack:center;-webkit-justify-content:center;justify-content:center}.menu-centered>.menu li{-webkit-box-pack:center;-ms-flex-pack:center;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-justify-content:center;justify-content:center}.menu-centered>.menu li .submenu li{-webkit-box-pack:start;-ms-flex-pack:start;-webkit-justify-content:flex-start;justify-content:flex-start}.no-js [data-responsive-menu] ul{display:none}.menu-icon{cursor:pointer;display:inline-block;height:16px;position:relative;vertical-align:middle;width:20px}.menu-icon:after{background:#fefefe;-webkit-box-shadow:0 7px 0 #fefefe,0 14px 0 #fefefe;box-shadow:0 7px 0 #fefefe,0 14px 0 #fefefe;content:"";display:block;height:2px;left:0;position:absolute;top:0;width:100%}.menu-icon:hover:after{background:#cacaca;-webkit-box-shadow:0 7px 0 #cacaca,0 14px 0 #cacaca;box-shadow:0 7px 0 #cacaca,0 14px 0 #cacaca}.menu-icon.dark{cursor:pointer;display:inline-block;height:16px;position:relative;vertical-align:middle;width:20px}.menu-icon.dark:after{background:#0a0a0a;-webkit-box-shadow:0 7px 0 #0a0a0a,0 14px 0 #0a0a0a;box-shadow:0 7px 0 #0a0a0a,0 14px 0 #0a0a0a;content:"";display:block;height:2px;left:0;position:absolute;top:0;width:100%}.menu-icon.dark:hover:after{background:#8a8a8a;-webkit-box-shadow:0 7px 0 #8a8a8a,0 14px 0 #8a8a8a;box-shadow:0 7px 0 #8a8a8a,0 14px 0 #8a8a8a}.accordion-menu li{width:100%}.accordion-menu .is-accordion-submenu a,.accordion-menu a{padding:.7rem 1rem}.accordion-menu .nested.is-accordion-submenu{margin-left:1rem;margin-right:0}.accordion-menu.align-right .nested.is-accordion-submenu{margin-left:0;margin-right:1rem}.accordion-menu .is-accordion-submenu-parent:not(.has-submenu-toggle)>a{position:relative}.accordion-menu .is-accordion-submenu-parent:not(.has-submenu-toggle)>a:after{border-color:#1779ba transparent transparent;border-style:solid;border-width:6px 6px 0;content:"";display:block;height:0;margin-top:-3px;position:absolute;right:1rem;top:50%;width:0}.accordion-menu.align-left .is-accordion-submenu-parent>a:after{left:auto;right:1rem}.accordion-menu.align-right .is-accordion-submenu-parent>a:after{left:1rem;right:auto}.accordion-menu .is-accordion-submenu-parent[aria-expanded=true]>a:after{-webkit-transform:rotate(180deg);-ms-transform:rotate(180deg);transform:rotate(180deg);-webkit-transform-origin:50% 50%;-ms-transform-origin:50% 50%;transform-origin:50% 50%}.is-accordion-submenu-parent{position:relative}.has-submenu-toggle>a{margin-right:40px}.submenu-toggle{cursor:pointer;height:40px;position:absolute;right:0;top:0;width:40px}.submenu-toggle:after{border-color:#1779ba transparent transparent;border-style:solid;border-width:6px 6px 0;bottom:0;content:"";display:block;height:0;margin:auto;top:0;width:0}.submenu-toggle[aria-expanded=true]:after{-webkit-transform:scaleY(-1);-ms-transform:scaleY(-1);transform:scaleY(-1);-webkit-transform-origin:50% 50%;-ms-transform-origin:50% 50%;transform-origin:50% 50%}.submenu-toggle-text{clip:rect(0,0,0,0)!important;border:0!important;height:1px!important;overflow:hidden!important;padding:0!important;position:absolute!important;white-space:nowrap!important;width:1px!important}.is-drilldown{overflow:hidden;position:relative}.is-drilldown li{display:block}.is-drilldown.animate-height{-webkit-transition:height .5s;transition:height .5s}.drilldown a{background:#fefefe;padding:.7rem 1rem}.drilldown .is-drilldown-submenu{background:#fefefe;left:100%;position:absolute;top:0;-webkit-transition:-webkit-transform .15s linear;transition:-webkit-transform .15s linear;transition:transform .15s linear;transition:transform .15s linear,-webkit-transform .15s linear;width:100%;z-index:-1}.drilldown .is-drilldown-submenu.is-active{display:block;-webkit-transform:translateX(-100%);-ms-transform:translateX(-100%);transform:translateX(-100%);z-index:1}.drilldown .is-drilldown-submenu.is-closing{-webkit-transform:translateX(100%);-ms-transform:translateX(100%);transform:translateX(100%)}.drilldown .is-drilldown-submenu a{padding:.7rem 1rem}.drilldown .nested.is-drilldown-submenu{margin-left:0;margin-right:0}.drilldown .drilldown-submenu-cover-previous{min-height:100%}.drilldown .is-drilldown-submenu-parent>a{position:relative}.drilldown .is-drilldown-submenu-parent>a:after{border-color:transparent transparent transparent #1779ba;border-style:solid;border-width:6px 0 6px 6px;content:"";display:block;height:0;margin-top:-6px;position:absolute;right:1rem;top:50%;width:0}.drilldown.align-left .is-drilldown-submenu-parent>a:after{border-color:transparent transparent transparent #1779ba;border-style:solid;border-width:6px 0 6px 6px;content:"";display:block;height:0;left:auto;right:1rem;width:0}.drilldown.align-right .is-drilldown-submenu-parent>a:after{border-color:transparent #1779ba transparent transparent;border-style:solid;border-width:6px 6px 6px 0;content:"";display:block;height:0;left:1rem;right:auto;width:0}.drilldown .js-drilldown-back>a:before{border-color:transparent #1779ba transparent transparent;border-style:solid;border-width:6px 6px 6px 0;content:"";display:block;display:inline-block;height:0;margin-right:.75rem;vertical-align:middle;width:0}.dropdown.menu>li.opens-left>.is-dropdown-submenu{left:auto;right:0;top:100%}.dropdown.menu>li.opens-right>.is-dropdown-submenu{left:0;right:auto;top:100%}.dropdown.menu>li.is-dropdown-submenu-parent>a{padding-right:1.5rem;position:relative}.dropdown.menu>li.is-dropdown-submenu-parent>a:after{border-color:#1779ba transparent transparent;border-style:solid;border-width:6px 6px 0;content:"";display:block;height:0;left:auto;margin-top:-3px;right:5px;width:0}[data-whatinput=mouse] .dropdown.menu a{outline:0}.dropdown.menu>li>a{padding:.7rem 1rem}.dropdown.menu>li.is-active>a{background:0 0;color:#1779ba}.no-js .dropdown.menu ul{display:none}.dropdown.menu .nested.is-dropdown-submenu{margin-left:0;margin-right:0}.dropdown.menu.vertical>li .is-dropdown-submenu{top:0}.dropdown.menu.vertical>li.opens-left>.is-dropdown-submenu{left:auto;right:100%;top:0}.dropdown.menu.vertical>li.opens-right>.is-dropdown-submenu{left:100%;right:auto}.dropdown.menu.vertical>li>a:after{right:14px}.dropdown.menu.vertical>li.opens-left>a:after{border-color:transparent #1779ba transparent transparent;border-style:solid;border-width:6px 6px 6px 0;content:"";display:block;height:0;left:5px;right:auto;width:0}.dropdown.menu.vertical>li.opens-right>a:after{border-color:transparent transparent transparent #1779ba;border-style:solid;border-width:6px 0 6px 6px;content:"";display:block;height:0;width:0}@media print,screen and (min-width:40em){.dropdown.menu.medium-horizontal>li.opens-left>.is-dropdown-submenu{left:auto;right:0;top:100%}.dropdown.menu.medium-horizontal>li.opens-right>.is-dropdown-submenu{left:0;right:auto;top:100%}.dropdown.menu.medium-horizontal>li.is-dropdown-submenu-parent>a{padding-right:1.5rem;position:relative}.dropdown.menu.medium-horizontal>li.is-dropdown-submenu-parent>a:after{border-color:#1779ba transparent transparent;border-style:solid;border-width:6px 6px 0;content:"";display:block;height:0;left:auto;margin-top:-3px;right:5px;width:0}.dropdown.menu.medium-vertical>li .is-dropdown-submenu{top:0}.dropdown.menu.medium-vertical>li.opens-left>.is-dropdown-submenu{left:auto;right:100%;top:0}.dropdown.menu.medium-vertical>li.opens-right>.is-dropdown-submenu{left:100%;right:auto}.dropdown.menu.medium-vertical>li>a:after{right:14px}.dropdown.menu.medium-vertical>li.opens-left>a:after{border-color:transparent #1779ba transparent transparent;border-style:solid;border-width:6px 6px 6px 0;content:"";display:block;height:0;left:5px;right:auto;width:0}.dropdown.menu.medium-vertical>li.opens-right>a:after{border-color:transparent transparent transparent #1779ba;border-style:solid;border-width:6px 0 6px 6px;content:"";display:block;height:0;width:0}}@media print,screen and (min-width:64em){.dropdown.menu.large-horizontal>li.opens-left>.is-dropdown-submenu{left:auto;right:0;top:100%}.dropdown.menu.large-horizontal>li.opens-right>.is-dropdown-submenu{left:0;right:auto;top:100%}.dropdown.menu.large-horizontal>li.is-dropdown-submenu-parent>a{padding-right:1.5rem;position:relative}.dropdown.menu.large-horizontal>li.is-dropdown-submenu-parent>a:after{border-color:#1779ba transparent transparent;border-style:solid;border-width:6px 6px 0;content:"";display:block;height:0;left:auto;margin-top:-3px;right:5px;width:0}.dropdown.menu.large-vertical>li .is-dropdown-submenu{top:0}.dropdown.menu.large-vertical>li.opens-left>.is-dropdown-submenu{left:auto;right:100%;top:0}.dropdown.menu.large-vertical>li.opens-right>.is-dropdown-submenu{left:100%;right:auto}.dropdown.menu.large-vertical>li>a:after{right:14px}.dropdown.menu.large-vertical>li.opens-left>a:after{border-color:transparent #1779ba transparent transparent;border-style:solid;border-width:6px 6px 6px 0;content:"";display:block;height:0;left:5px;right:auto;width:0}.dropdown.menu.large-vertical>li.opens-right>a:after{border-color:transparent transparent transparent #1779ba;border-style:solid;border-width:6px 0 6px 6px;content:"";display:block;height:0;width:0}}.dropdown.menu.align-right .is-dropdown-submenu.first-sub{left:auto;right:0;top:100%}.is-dropdown-menu.vertical{width:100px}.is-dropdown-menu.vertical.align-right{float:right}.is-dropdown-submenu-parent{position:relative}.is-dropdown-submenu-parent a:after{left:auto;margin-top:-6px;position:absolute;right:5px;top:50%}.is-dropdown-submenu-parent.opens-inner>.is-dropdown-submenu{left:auto;top:100%}.is-dropdown-submenu-parent.opens-left>.is-dropdown-submenu{left:auto;right:100%}.is-dropdown-submenu-parent.opens-right>.is-dropdown-submenu{left:100%;right:auto}.is-dropdown-submenu{background:#fefefe;border:1px solid #cacaca;display:none;left:100%;min-width:200px;position:absolute;top:0;z-index:1}.dropdown .is-dropdown-submenu a{padding:.7rem 1rem}.is-dropdown-submenu .is-dropdown-submenu-parent>a:after{right:14px}.is-dropdown-submenu .is-dropdown-submenu-parent.opens-left>a:after{border-color:transparent #1779ba transparent transparent;border-style:solid;border-width:6px 6px 6px 0;content:"";display:block;height:0;left:5px;right:auto;width:0}.is-dropdown-submenu .is-dropdown-submenu-parent.opens-right>a:after{border-color:transparent transparent transparent #1779ba;border-style:solid;border-width:6px 0 6px 6px;content:"";display:block;height:0;width:0}.is-dropdown-submenu .is-dropdown-submenu{margin-top:-1px}.is-dropdown-submenu>li{width:100%}.is-dropdown-submenu.js-dropdown-active{display:block}.is-off-canvas-open{overflow:hidden}.js-off-canvas-overlay{background:hsla(0,0%,100%,.25);height:100%;left:0;opacity:0;overflow:hidden;position:absolute;top:0;-webkit-transition:opacity .5s ease,visibility .5s ease;transition:opacity .5s ease,visibility .5s ease;visibility:hidden;width:100%;z-index:11}.js-off-canvas-overlay.is-visible{opacity:1;visibility:visible}.js-off-canvas-overlay.is-closable{cursor:pointer}.js-off-canvas-overlay.is-overlay-absolute{position:absolute}.js-off-canvas-overlay.is-overlay-fixed{position:fixed}.off-canvas-wrapper{overflow:hidden;position:relative}.off-canvas{-webkit-backface-visibility:hidden;backface-visibility:hidden;background:#e6e6e6;position:fixed;-webkit-transition:-webkit-transform .5s ease;transition:-webkit-transform .5s ease;transition:transform .5s ease;transition:transform .5s ease,-webkit-transform .5s ease;z-index:12}[data-whatinput=mouse] .off-canvas{outline:0}.off-canvas.is-transition-push{z-index:12}.off-canvas.is-closed{visibility:hidden}.off-canvas.is-transition-overlap{z-index:13}.off-canvas.is-transition-overlap.is-open{-webkit-box-shadow:0 0 10px hsla(0,0%,4%,.7);box-shadow:0 0 10px hsla(0,0%,4%,.7)}.off-canvas.is-open{-webkit-transform:translate(0);-ms-transform:translate(0);transform:translate(0)}.off-canvas-absolute{-webkit-backface-visibility:hidden;backface-visibility:hidden;background:#e6e6e6;position:absolute;-webkit-transition:-webkit-transform .5s ease;transition:-webkit-transform .5s ease;transition:transform .5s ease;transition:transform .5s ease,-webkit-transform .5s ease;z-index:12}[data-whatinput=mouse] .off-canvas-absolute{outline:0}.off-canvas-absolute.is-transition-push{z-index:12}.off-canvas-absolute.is-closed{visibility:hidden}.off-canvas-absolute.is-transition-overlap{z-index:13}.off-canvas-absolute.is-transition-overlap.is-open{-webkit-box-shadow:0 0 10px hsla(0,0%,4%,.7);box-shadow:0 0 10px hsla(0,0%,4%,.7)}.off-canvas-absolute.is-open{-webkit-transform:translate(0);-ms-transform:translate(0);transform:translate(0)}.position-left{-webkit-overflow-scrolling:touch;height:100%;left:0;overflow-y:auto;top:0;width:250px}.off-canvas-content .off-canvas.position-left,.position-left{-webkit-transform:translateX(-250px);-ms-transform:translateX(-250px);transform:translateX(-250px)}.off-canvas-content .off-canvas.position-left.is-transition-overlap.is-open{-webkit-transform:translate(0);-ms-transform:translate(0);transform:translate(0)}.off-canvas-content.is-open-left.has-transition-push{-webkit-transform:translateX(250px);-ms-transform:translateX(250px);transform:translateX(250px)}.position-left.is-transition-push{-webkit-box-shadow:inset -13px 0 20px -13px hsla(0,0%,4%,.25);box-shadow:inset -13px 0 20px -13px hsla(0,0%,4%,.25)}.position-right{-webkit-overflow-scrolling:touch;height:100%;overflow-y:auto;right:0;top:0;width:250px}.off-canvas-content .off-canvas.position-right,.position-right{-webkit-transform:translateX(250px);-ms-transform:translateX(250px);transform:translateX(250px)}.off-canvas-content .off-canvas.position-right.is-transition-overlap.is-open{-webkit-transform:translate(0);-ms-transform:translate(0);transform:translate(0)}.off-canvas-content.is-open-right.has-transition-push{-webkit-transform:translateX(-250px);-ms-transform:translateX(-250px);transform:translateX(-250px)}.position-right.is-transition-push{-webkit-box-shadow:inset 13px 0 20px -13px hsla(0,0%,4%,.25);box-shadow:inset 13px 0 20px -13px hsla(0,0%,4%,.25)}.position-top{-webkit-overflow-scrolling:touch;height:250px;left:0;overflow-x:auto;top:0;width:100%}.off-canvas-content .off-canvas.position-top,.position-top{-webkit-transform:translateY(-250px);-ms-transform:translateY(-250px);transform:translateY(-250px)}.off-canvas-content .off-canvas.position-top.is-transition-overlap.is-open{-webkit-transform:translate(0);-ms-transform:translate(0);transform:translate(0)}.off-canvas-content.is-open-top.has-transition-push{-webkit-transform:translateY(250px);-ms-transform:translateY(250px);transform:translateY(250px)}.position-top.is-transition-push{-webkit-box-shadow:inset 0 -13px 20px -13px hsla(0,0%,4%,.25);box-shadow:inset 0 -13px 20px -13px hsla(0,0%,4%,.25)}.position-bottom{-webkit-overflow-scrolling:touch;bottom:0;height:250px;left:0;overflow-x:auto;width:100%}.off-canvas-content .off-canvas.position-bottom,.position-bottom{-webkit-transform:translateY(250px);-ms-transform:translateY(250px);transform:translateY(250px)}.off-canvas-content .off-canvas.position-bottom.is-transition-overlap.is-open{-webkit-transform:translate(0);-ms-transform:translate(0);transform:translate(0)}.off-canvas-content.is-open-bottom.has-transition-push{-webkit-transform:translateY(-250px);-ms-transform:translateY(-250px);transform:translateY(-250px)}.position-bottom.is-transition-push{-webkit-box-shadow:inset 0 13px 20px -13px hsla(0,0%,4%,.25);box-shadow:inset 0 13px 20px -13px hsla(0,0%,4%,.25)}.off-canvas-content{-webkit-backface-visibility:hidden;backface-visibility:hidden;-webkit-transform:none;-ms-transform:none;transform:none}.off-canvas-content.has-transition-overlap,.off-canvas-content.has-transition-push{-webkit-transition:-webkit-transform .5s ease;transition:-webkit-transform .5s ease;transition:transform .5s ease;transition:transform .5s ease,-webkit-transform .5s ease}.off-canvas-content.has-transition-push,.off-canvas-content .off-canvas.is-open{-webkit-transform:translate(0);-ms-transform:translate(0);transform:translate(0)}@media print,screen and (min-width:40em){.position-left.reveal-for-medium{-webkit-transform:none;-ms-transform:none;transform:none;-webkit-transition:none;transition:none;visibility:visible;z-index:12}.position-left.reveal-for-medium .close-button{display:none}.off-canvas-content .position-left.reveal-for-medium{-webkit-transform:none;-ms-transform:none;transform:none}.off-canvas-content.has-reveal-left{margin-left:250px}.position-left.reveal-for-medium~.off-canvas-content{margin-left:250px}.position-right.reveal-for-medium{-webkit-transform:none;-ms-transform:none;transform:none;-webkit-transition:none;transition:none;visibility:visible;z-index:12}.position-right.reveal-for-medium .close-button{display:none}.off-canvas-content .position-right.reveal-for-medium{-webkit-transform:none;-ms-transform:none;transform:none}.off-canvas-content.has-reveal-right{margin-right:250px}.position-right.reveal-for-medium~.off-canvas-content{margin-right:250px}.position-top.reveal-for-medium{-webkit-transform:none;-ms-transform:none;transform:none;-webkit-transition:none;transition:none;visibility:visible;z-index:12}.position-top.reveal-for-medium .close-button{display:none}.off-canvas-content .position-top.reveal-for-medium{-webkit-transform:none;-ms-transform:none;transform:none}.off-canvas-content.has-reveal-top{margin-top:250px}.position-top.reveal-for-medium~.off-canvas-content{margin-top:250px}.position-bottom.reveal-for-medium{-webkit-transform:none;-ms-transform:none;transform:none;-webkit-transition:none;transition:none;visibility:visible;z-index:12}.position-bottom.reveal-for-medium .close-button{display:none}.off-canvas-content .position-bottom.reveal-for-medium{-webkit-transform:none;-ms-transform:none;transform:none}.off-canvas-content.has-reveal-bottom{margin-bottom:250px}.position-bottom.reveal-for-medium~.off-canvas-content{margin-bottom:250px}}@media print,screen and (min-width:64em){.position-left.reveal-for-large{-webkit-transform:none;-ms-transform:none;transform:none;-webkit-transition:none;transition:none;visibility:visible;z-index:12}.position-left.reveal-for-large .close-button{display:none}.off-canvas-content .position-left.reveal-for-large{-webkit-transform:none;-ms-transform:none;transform:none}.off-canvas-content.has-reveal-left{margin-left:250px}.position-left.reveal-for-large~.off-canvas-content{margin-left:250px}.position-right.reveal-for-large{-webkit-transform:none;-ms-transform:none;transform:none;-webkit-transition:none;transition:none;visibility:visible;z-index:12}.position-right.reveal-for-large .close-button{display:none}.off-canvas-content .position-right.reveal-for-large{-webkit-transform:none;-ms-transform:none;transform:none}.off-canvas-content.has-reveal-right{margin-right:250px}.position-right.reveal-for-large~.off-canvas-content{margin-right:250px}.position-top.reveal-for-large{-webkit-transform:none;-ms-transform:none;transform:none;-webkit-transition:none;transition:none;visibility:visible;z-index:12}.position-top.reveal-for-large .close-button{display:none}.off-canvas-content .position-top.reveal-for-large{-webkit-transform:none;-ms-transform:none;transform:none}.off-canvas-content.has-reveal-top{margin-top:250px}.position-top.reveal-for-large~.off-canvas-content{margin-top:250px}.position-bottom.reveal-for-large{-webkit-transform:none;-ms-transform:none;transform:none;-webkit-transition:none;transition:none;visibility:visible;z-index:12}.position-bottom.reveal-for-large .close-button{display:none}.off-canvas-content .position-bottom.reveal-for-large{-webkit-transform:none;-ms-transform:none;transform:none}.off-canvas-content.has-reveal-bottom{margin-bottom:250px}.position-bottom.reveal-for-large~.off-canvas-content{margin-bottom:250px}}@media print,screen and (min-width:40em){.off-canvas.in-canvas-for-medium{background:0 0;height:auto;overflow:visible;position:static;-webkit-transition:none;transition:none;visibility:visible;width:auto}.off-canvas.in-canvas-for-medium.position-bottom,.off-canvas.in-canvas-for-medium.position-left,.off-canvas.in-canvas-for-medium.position-right,.off-canvas.in-canvas-for-medium.position-top{-webkit-box-shadow:none;box-shadow:none;-webkit-transform:none;-ms-transform:none;transform:none}.off-canvas.in-canvas-for-medium .close-button{display:none}}@media print,screen and (min-width:64em){.off-canvas.in-canvas-for-large{background:0 0;height:auto;overflow:visible;position:static;-webkit-transition:none;transition:none;visibility:visible;width:auto}.off-canvas.in-canvas-for-large.position-bottom,.off-canvas.in-canvas-for-large.position-left,.off-canvas.in-canvas-for-large.position-right,.off-canvas.in-canvas-for-large.position-top{-webkit-box-shadow:none;box-shadow:none;-webkit-transform:none;-ms-transform:none;transform:none}.off-canvas.in-canvas-for-large .close-button{display:none}}html.is-reveal-open{overflow-y:hidden;position:fixed;width:100%}html.is-reveal-open.zf-has-scroll{-webkit-overflow-scrolling:touch;overflow-y:scroll}html.is-reveal-open body{overflow-y:hidden}.reveal-overlay{background-color:hsla(0,0%,4%,.45);bottom:0;left:0;position:fixed;right:0;top:0;z-index:1005}.reveal,.reveal-overlay{-webkit-overflow-scrolling:touch;display:none;overflow-y:auto}.reveal{-webkit-backface-visibility:hidden;backface-visibility:hidden;background-color:#fefefe;border:1px solid #cacaca;border-radius:0;margin-left:auto;margin-right:auto;padding:1rem;position:relative;top:100px;z-index:1006}[data-whatinput=mouse] .reveal{outline:0}@media print,screen and (min-width:40em){.reveal{min-height:0}}.reveal .column{min-width:0}.reveal>:last-child{margin-bottom:0}@media print,screen and (min-width:40em){.reveal{max-width:75rem;width:600px}}.reveal.collapse{padding:0}@media print,screen and (min-width:40em){.reveal.tiny{max-width:75rem;width:30%}.reveal.small{max-width:75rem;width:50%}.reveal.large{max-width:75rem;width:90%}}.reveal.full{border:0;border-radius:0;bottom:0;height:100%;left:0;margin-left:0;max-width:none;min-height:100%;right:0;top:0;width:100%}@media print,screen and (max-width:39.99875em){.reveal{border:0;border-radius:0;bottom:0;height:100%;left:0;margin-left:0;max-width:none;min-height:100%;right:0;top:0;width:100%}}.reveal.without-overlay{position:fixed}.sticky,.sticky-container{position:relative}.sticky{-webkit-transform:translateZ(0);transform:translateZ(0);z-index:0}.sticky.is-stuck{position:fixed;width:100%;z-index:5}.sticky.is-stuck.is-at-top{top:0}.sticky.is-stuck.is-at-bottom{bottom:0}.sticky.is-anchored{left:auto;position:relative;right:auto}.sticky.is-anchored.is-at-bottom{bottom:0}.title-bar{-webkit-box-pack:start;-ms-flex-pack:start;-webkit-box-align:center;-ms-flex-align:center;-webkit-align-items:center;align-items:center;background:#0a0a0a;color:#fefefe;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-justify-content:flex-start;justify-content:flex-start;padding:.5rem}.title-bar .menu-icon{margin-left:.25rem;margin-right:.25rem}.title-bar-left,.title-bar-right{-webkit-box-flex:1;-webkit-flex:1 1 0px;-ms-flex:1 1 0px;flex:1 1 0px}.title-bar-right{text-align:right}.title-bar-title{display:inline-block;font-weight:700;vertical-align:middle}.top-bar{-webkit-box-pack:justify;-ms-flex-pack:justify;-webkit-box-align:center;-ms-flex-align:center;-webkit-align-items:center;align-items:center;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;-webkit-justify-content:space-between;justify-content:space-between;padding:.5rem}.top-bar,.top-bar ul{background-color:#e6e6e6}.top-bar input{margin-right:1rem;max-width:200px}.top-bar .input-group-field{margin-right:0;width:100%}.top-bar input.button{width:auto}.top-bar .top-bar-left,.top-bar .top-bar-right{-webkit-box-flex:0;-webkit-flex:0 0 100%;-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}@media print,screen and (min-width:40em){.top-bar{-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap}.top-bar .top-bar-left{-webkit-box-flex:1;-webkit-flex:1 1 auto;-ms-flex:1 1 auto;flex:1 1 auto;margin-right:auto}.top-bar .top-bar-right{-webkit-box-flex:0;-webkit-flex:0 1 auto;-ms-flex:0 1 auto;flex:0 1 auto;margin-left:auto}}@media print,screen and (max-width:63.99875em){.top-bar.stacked-for-medium{-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap}.top-bar.stacked-for-medium .top-bar-left,.top-bar.stacked-for-medium .top-bar-right{-webkit-box-flex:0;-webkit-flex:0 0 100%;-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}}@media print,screen and (max-width:74.99875em){.top-bar.stacked-for-large{-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap}.top-bar.stacked-for-large .top-bar-left,.top-bar.stacked-for-large .top-bar-right{-webkit-box-flex:0;-webkit-flex:0 0 100%;-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}}.top-bar-title{margin:.5rem 1rem .5rem 0}.top-bar-left,.top-bar-right,.top-bar-title{-webkit-box-flex:0;-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto}.float-left{float:left!important}.float-right{float:right!important}.float-center{display:block;margin-left:auto;margin-right:auto}.clearfix:after,.clearfix:before{-ms-flex-preferred-size:0;-webkit-box-ordinal-group:2;-ms-flex-order:1;content:" ";display:table;-webkit-flex-basis:0;flex-basis:0;-webkit-order:1;order:1}.clearfix:after{clear:both}.align-left{-webkit-box-pack:start;-ms-flex-pack:start;-webkit-justify-content:flex-start;justify-content:flex-start}.align-right{-webkit-box-pack:end;-ms-flex-pack:end;-webkit-justify-content:flex-end;justify-content:flex-end}.align-center{-webkit-box-pack:center;-ms-flex-pack:center;-webkit-justify-content:center;justify-content:center}.align-justify{-webkit-box-pack:justify;-ms-flex-pack:justify;-webkit-justify-content:space-between;justify-content:space-between}.align-spaced{-ms-flex-pack:distribute;-webkit-justify-content:space-around;justify-content:space-around}.align-left.vertical.menu>li>a{-webkit-box-pack:start;-ms-flex-pack:start;-webkit-justify-content:flex-start;justify-content:flex-start}.align-right.vertical.menu>li>a{-webkit-box-pack:end;-ms-flex-pack:end;-webkit-justify-content:flex-end;justify-content:flex-end}.align-center.vertical.menu>li>a{-webkit-box-pack:center;-ms-flex-pack:center;-webkit-justify-content:center;justify-content:center}.align-top{-webkit-box-align:start;-ms-flex-align:start;-webkit-align-items:flex-start;align-items:flex-start}.align-self-top{-ms-flex-item-align:start;-webkit-align-self:flex-start;align-self:flex-start}.align-bottom{-webkit-box-align:end;-ms-flex-align:end;-webkit-align-items:flex-end;align-items:flex-end}.align-self-bottom{-ms-flex-item-align:end;-webkit-align-self:flex-end;align-self:flex-end}.align-middle{-webkit-box-align:center;-ms-flex-align:center;-webkit-align-items:center;align-items:center}.align-self-middle{-ms-flex-item-align:center;-webkit-align-self:center;align-self:center}.align-stretch{-webkit-box-align:stretch;-ms-flex-align:stretch;-webkit-align-items:stretch;align-items:stretch}.align-self-stretch{-ms-flex-item-align:stretch;-webkit-align-self:stretch;align-self:stretch}.align-center-middle{-webkit-box-pack:center;-ms-flex-pack:center;-webkit-box-align:center;-ms-flex-align:center;-ms-flex-line-pack:center;-webkit-align-content:center;align-content:center;-webkit-align-items:center;align-items:center;-webkit-justify-content:center;justify-content:center}.small-order-1{-webkit-box-ordinal-group:2;-ms-flex-order:1;-webkit-order:1;order:1}.small-order-2{-webkit-box-ordinal-group:3;-ms-flex-order:2;-webkit-order:2;order:2}.small-order-3{-webkit-box-ordinal-group:4;-ms-flex-order:3;-webkit-order:3;order:3}.small-order-4{-webkit-box-ordinal-group:5;-ms-flex-order:4;-webkit-order:4;order:4}.small-order-5{-webkit-box-ordinal-group:6;-ms-flex-order:5;-webkit-order:5;order:5}.small-order-6{-webkit-box-ordinal-group:7;-ms-flex-order:6;-webkit-order:6;order:6}@media print,screen and (min-width:40em){.medium-order-1{-webkit-box-ordinal-group:2;-ms-flex-order:1;-webkit-order:1;order:1}.medium-order-2{-webkit-box-ordinal-group:3;-ms-flex-order:2;-webkit-order:2;order:2}.medium-order-3{-webkit-box-ordinal-group:4;-ms-flex-order:3;-webkit-order:3;order:3}.medium-order-4{-webkit-box-ordinal-group:5;-ms-flex-order:4;-webkit-order:4;order:4}.medium-order-5{-webkit-box-ordinal-group:6;-ms-flex-order:5;-webkit-order:5;order:5}.medium-order-6{-webkit-box-ordinal-group:7;-ms-flex-order:6;-webkit-order:6;order:6}}@media print,screen and (min-width:64em){.large-order-1{-webkit-box-ordinal-group:2;-ms-flex-order:1;-webkit-order:1;order:1}.large-order-2{-webkit-box-ordinal-group:3;-ms-flex-order:2;-webkit-order:2;order:2}.large-order-3{-webkit-box-ordinal-group:4;-ms-flex-order:3;-webkit-order:3;order:3}.large-order-4{-webkit-box-ordinal-group:5;-ms-flex-order:4;-webkit-order:4;order:4}.large-order-5{-webkit-box-ordinal-group:6;-ms-flex-order:5;-webkit-order:5;order:5}.large-order-6{-webkit-box-ordinal-group:7;-ms-flex-order:6;-webkit-order:6;order:6}}.flex-container{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex}.flex-child-auto{-webkit-box-flex:1;-webkit-flex:1 1 auto;-ms-flex:1 1 auto;flex:1 1 auto}.flex-child-grow{-webkit-box-flex:1;-webkit-flex:1 0 auto;-ms-flex:1 0 auto;flex:1 0 auto}.flex-child-shrink{-webkit-box-flex:0;-webkit-flex:0 1 auto;-ms-flex:0 1 auto;flex:0 1 auto}.flex-dir-row{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row}.flex-dir-row-reverse{-webkit-box-orient:horizontal;-webkit-box-direction:reverse;-webkit-flex-direction:row-reverse;-ms-flex-direction:row-reverse;flex-direction:row-reverse}.flex-dir-column{-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column}.flex-dir-column-reverse{-webkit-box-orient:vertical;-webkit-box-direction:reverse;-webkit-flex-direction:column-reverse;-ms-flex-direction:column-reverse;flex-direction:column-reverse}@media print,screen and (min-width:40em){.medium-flex-container{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex}.medium-flex-child-auto{-webkit-box-flex:1;-webkit-flex:1 1 auto;-ms-flex:1 1 auto;flex:1 1 auto}.medium-flex-child-grow{-webkit-box-flex:1;-webkit-flex:1 0 auto;-ms-flex:1 0 auto;flex:1 0 auto}.medium-flex-child-shrink{-webkit-box-flex:0;-webkit-flex:0 1 auto;-ms-flex:0 1 auto;flex:0 1 auto}.medium-flex-dir-row{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row}.medium-flex-dir-row-reverse{-webkit-box-orient:horizontal;-webkit-box-direction:reverse;-webkit-flex-direction:row-reverse;-ms-flex-direction:row-reverse;flex-direction:row-reverse}.medium-flex-dir-column{-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column}.medium-flex-dir-column-reverse{-webkit-box-orient:vertical;-webkit-box-direction:reverse;-webkit-flex-direction:column-reverse;-ms-flex-direction:column-reverse;flex-direction:column-reverse}}@media print,screen and (min-width:64em){.large-flex-container{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex}.large-flex-child-auto{-webkit-box-flex:1;-webkit-flex:1 1 auto;-ms-flex:1 1 auto;flex:1 1 auto}.large-flex-child-grow{-webkit-box-flex:1;-webkit-flex:1 0 auto;-ms-flex:1 0 auto;flex:1 0 auto}.large-flex-child-shrink{-webkit-box-flex:0;-webkit-flex:0 1 auto;-ms-flex:0 1 auto;flex:0 1 auto}.large-flex-dir-row{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row}.large-flex-dir-row-reverse{-webkit-box-orient:horizontal;-webkit-box-direction:reverse;-webkit-flex-direction:row-reverse;-ms-flex-direction:row-reverse;flex-direction:row-reverse}.large-flex-dir-column{-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column}.large-flex-dir-column-reverse{-webkit-box-orient:vertical;-webkit-box-direction:reverse;-webkit-flex-direction:column-reverse;-ms-flex-direction:column-reverse;flex-direction:column-reverse}}.hide{display:none!important}.invisible{visibility:hidden}.visible{visibility:visible}@media print,screen and (max-width:39.99875em){.hide-for-small-only{display:none!important}}@media screen and (max-width:0em),screen and (min-width:40em){.show-for-small-only{display:none!important}}@media print,screen and (min-width:40em){.hide-for-medium{display:none!important}}@media screen and (max-width:39.99875em){.show-for-medium{display:none!important}}@media print,screen and (min-width:40em)and (max-width:63.99875em){.hide-for-medium-only{display:none!important}}@media screen and (max-width:39.99875em),screen and (min-width:64em){.show-for-medium-only{display:none!important}}@media print,screen and (min-width:64em){.hide-for-large{display:none!important}}@media screen and (max-width:63.99875em){.show-for-large{display:none!important}}@media print,screen and (min-width:64em)and (max-width:74.99875em){.hide-for-large-only{display:none!important}}@media screen and (max-width:63.99875em),screen and (min-width:75em){.show-for-large-only{display:none!important}}.show-for-sr,.show-on-focus{clip:rect(0,0,0,0)!important;border:0!important;height:1px!important;overflow:hidden!important;padding:0!important;position:absolute!important;white-space:nowrap!important;width:1px!important}.show-on-focus:active,.show-on-focus:focus{clip:auto!important;height:auto!important;overflow:visible!important;position:static!important;white-space:normal!important;width:auto!important}.hide-for-portrait,.show-for-landscape{display:block!important}@media screen and (orientation:landscape){.hide-for-portrait,.show-for-landscape{display:block!important}}@media screen and (orientation:portrait){.hide-for-portrait,.show-for-landscape{display:none!important}}.hide-for-landscape,.show-for-portrait{display:none!important}@media screen and (orientation:landscape){.hide-for-landscape,.show-for-portrait{display:none!important}}@media screen and (orientation:portrait){.hide-for-landscape,.show-for-portrait{display:block!important}}.show-for-dark-mode{display:none}.hide-for-dark-mode{display:block}@media screen and (prefers-color-scheme:dark){.show-for-dark-mode{display:block!important}.hide-for-dark-mode{display:none!important}}.show-for-ie{display:none}@media (-ms-high-contrast:active),(-ms-high-contrast:none){.show-for-ie{display:block!important}.hide-for-ie{display:none!important}}.show-for-sticky{display:none}.is-stuck .show-for-sticky{display:block}.is-stuck .hide-for-sticky{display:none}@font-face{font-display:"swap";font-family:FontAwesome}html{box-sizing:border-box}body{font-family:Roboto,sans-serif;font-size:16px;line-height:1}*,:after,:before{box-sizing:inherit}a{color:#3c4fe0}a.reference:after{font-family:FontAwesome;font-size:12px;padding:0 4px}a.reference.external:after{content:""}a.reference.download:after{content:""}a:hover{color:#3c4fe0;font-weight:500}.headerlink{margin-left:5px;visibility:hidden}.toc-backref:hover{color:#23263b}h1,h2,h3,h4,h5,h6{font-family:Roboto,sans-serif;font-size:16px;font-weight:500;letter-spacing:.2px;line-height:24px;margin-bottom:16px}h1:hover>a.headerlink,h2:hover>a.headerlink,h3:hover>a.headerlink,h4:hover>a.headerlink,h5:hover>a.headerlink,h6:hover>a.headerlink{visibility:visible}h1 a,h2 a,h3 a,h4 a,h5 a,h6 a{color:inherit}h1{font-size:32px;font-weight:700;line-height:40px;margin-bottom:28px}h2{font-size:24px;line-height:32px}h3{font-size:20px}h4{font-size:18px}h5{font-size:16px}h6{font-weight:400}img{max-width:100%}button:focus{outline:0}blockquote{border:0;margin:0;padding:0}blockquote,blockquote p,cite{color:inherit}cite{display:inline;font-size:inherit}cite:before{content:""}.show{display:block!important}.centered{display:block;margin:0 auto}.break{flex-basis:100%;height:0}@media screen and (min-width:1024px){h1{font-size:36px}}.admonition-title:before,.contents.local>ul>li a:before,.scylla-icon,.secondary-side-nav__content li a:before{background-repeat:no-repeat;background-size:contain;display:inline-block;filter:brightness(0);vertical-align:middle}.scylla-icon--about-team{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMSwuY2xzLTJ7ZmlsbDpub25lO3N0cm9rZTpncmF5O3N0cm9rZS1taXRlcmxpbWl0OjEwfS5jbHMtMntzdHJva2UtbGluZWNhcDpyb3VuZH08L3N0eWxlPjwvZGVmcz48ZyBpZD0iQ2FscXVlXzQiIGRhdGEtbmFtZT0iQ2FscXVlIDQiPjxwYXRoIGNsYXNzPSJjbHMtMSIgZD0iTTQuNjYgOS44MSAyLjYzIDExYTIuMDggMi4wOCAwIDAgMC0xLjEzIDEuODN2Ny44MWMuMTkgMS4xMS41IDEuNTMgMS41IDEuNDdNNy4wNiA5Ljk0bDEuNDQuOTQiLz48cGF0aCBjbGFzcz0iY2xzLTIiIGQ9Ik0zLjUgMTguNXY1LjM0TTkuNSAxOC41djUuMzRNOC41NCAxOC40MnY1LjMzTTE1LjUgMTguNXY1LjM0TTE2LjUgMTguNXY1LjM0TTMuMzMgMjAuNTNoNS4wOE0xMS40NSA4Ljg0bC4wNi4wNmExLjY1IDEuNjUgMCAwIDAgMi4zNCAwaDAiLz48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Ik0xMi40MiA3LjVhMS44MSAxLjgxIDAgMCAxLTEuOTItMS43N1Y1YTEuOTQgMS45NCAwIDAgMSAxLjkyLTIgMi4wNyAyLjA3IDAgMCAxIDIuMDggMnYuNzdhMiAyIDAgMCAxLTIuMDggMS43M1pNMTEuNDIgOC43NCA5LjYzIDkuOWEyLjA3IDIuMDcgMCAwIDAtMS4xMyAxLjg1djcuODJBMS40NyAxLjQ3IDAgMCAwIDEwIDIxTTEzLjc1IDkuMThsMiAuNjVjLjcuMzUuNzYgMS4wNi43NiAxLjg0djcuOWMwIC43Ny0uMjMgMS4yNC0xIDEuMjQiLz48cGF0aCBjbGFzcz0iY2xzLTIiIGQ9Ik05LjkzIDE5LjVoNS40Ii8+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNMTkuNDIgOS4xMmEyLjA3IDIuMDcgMCAwIDAgMi4wOC0xLjkzdi0uNzdhMi4wNyAyLjA3IDAgMCAwLTIuMDgtMS45MiAxLjkzIDEuOTMgMCAwIDAtMS45MiAxLjkydi43N2ExLjk0IDEuOTQgMCAwIDAgMS45MiAxLjkzWk01LjU5IDkuMTJhMS45MyAxLjkzIDAgMCAwIDEuOTItMS45M3YtLjc3QTEuOTMgMS45MyAwIDAgMCA1LjU5IDQuNSAyLjA4IDIuMDggMCAwIDAgMy41IDYuNDJ2Ljc3YTIuMDggMi4wOCAwIDAgMCAyLjA5IDEuOTNaTTIwLjQ0IDkuODFsMiAxLjE3YTIuMDYgMi4wNiAwIDAgMSAxLjEzIDEuODV2Ny44MWMtLjE4IDEuMTEtLjQ3IDEuNTMtMS40NyAxLjQ3TTE4LjA0IDkuOTRsLTEuNDQuOTMiLz48cGF0aCBjbGFzcz0iY2xzLTIiIGQ9Ik0yMS42IDE4LjV2NS4zNE0yMS43NyAyMC41M2gtNS4wOCIvPjwvZz48L3N2Zz4=)}.scylla-icon--about-us{background-image:url(data:image/svg+xml;base64,PHN2ZyBpZD0iTGF5ZXJfMyIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB2aWV3Qm94PSIwIDAgMjAgMjAiPjxkZWZzPjxzdHlsZT4uY2xzLTF7ZmlsbDpub25lO3N0cm9rZTojMDAwO3N0cm9rZS1saW5lY2FwOnJvdW5kO3N0cm9rZS1saW5lam9pbjpyb3VuZDtzdHJva2Utd2lkdGg6LjhweH08L3N0eWxlPjwvZGVmcz48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Ik02LjI4IDE5LjQ4Yy0uMTIuMDgtLjA4LjA3LS4yMy4xLS41OC4wOS0xLjEyLS4yOC0xLjI1LS44NCAwIDAtMi4zLTkuMTgtMi4zLTExLjExQzIuNSAzLjYgNS44OC40NCAxMC4zOC40NFMxNy41IDMuNDggMTcuNSA3LjVjMCAxLjkzLTEuMzIgMTEuMjMtMS4zMiAxMS4yMy0uMTMuNTYtLjY3Ljk0LTEuMjUuODQtLjEyLS4wMi0uMTMgMC0uMjMtLjA3Ii8+PHBhdGggZD0iTTE1Ljc1IDE1Ljc1Yy0uMTcgMS4xNS0uMjIgMi4zNC0uNTUgMy40Ni0uMzcuODUtMS42MyAxLjA2LTIuMjIuMzMtLjI1LS4yOC4xOS0uNjguNDQtLjQuNDMuNDYgMS4yNC4xOCAxLjMxLS40NGwuMDYtLjM0Yy4xOS0uODkuMzUtMS43OS41Ny0yLjY4LjA1LS4yNC40Mi0uMTcuMzkuMDdaIi8+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNMTEuNSA3YzAgMS45LTEuNTYgMy41LTMuNDYgMy41UzQuNSA4LjkgNC41IDdzMS42NC0zLjUgMy41NC0zLjVTMTEuNSA1LjEgMTEuNSA3WiIvPjxwYXRoIGQ9Ik04LjU1IDQuNzVjLS41OS4xMi0uNzEgMS40Mi0uMzYgMS43OC4yMy4yMy43MS4zMS43MS40N3MtLjQ4LjI0LS43MS40N2MtLjM2LjM2LS4yNCAxLjY2LjM2IDEuNzguNzEuMTQgMS43OC0uNzEgMS43OC0yLjI1UzkuMjYgNC42MSA4LjU1IDQuNzVaTTYuNTEgMTIuMmMyLjEyLjMxIDQuMzQtLjIgNS42OC0xLjk2LjMyLS40MS45Ni4xMS42Mi41MS0uNzYuOS0xLjc4IDEuNjMtMi45MyAxLjk1LTEuMTQuMzMtMi4zMy4zMS0zLjQ2LjE2YS4zNC4zNCAwIDAgMS0uMjktLjM4Yy4wMi0uMTguMTktLjMxLjM3LS4yOVpNNy45NyAxOS41OWMtLjk5Ljk2LTIuMzYuMDgtMi4zNi0xLjE1LS4xMi0uOS0uMjctMS43OS0uMzctMi42OS0uMDEtLjExLjA3LS4yMS4xOC0uMjIuMS0uMDEuMTkuMDYuMjEuMTUuMjIuODguMzggMS43Ny41NiAyLjY2LjAxLjc4LjY4IDEuMzggMS4zNS44My4yNy0uMjcuNjkuMTYuNDIuNDNaIi8+PHBhdGggZD0iTTkuNzUgMTkuMjdjLS40Mi45LTEuOC45Ni0yLjMyLjExLS41LTEuMTMtLjMxLTIuNS0uNDctMy43MiAwLS4xMS4wOC0uMi4xOS0uMjEuMSAwIC4xOS4wNy4yMS4xNy4xNy45NS4yOCAxLjkxLjQyIDIuODcuMDEuNDUuMjMuNzQuNTcuODUuMzMuMS43MS0uMDUuODgtLjM2LjE4LS4zNC43MS0uMDUuNTIuMjlaTTE0LjAzIDE1LjY2Yy0uMTYgMS4yMy4wMyAyLjU3LS40NiAzLjcyLS41Mi44Ni0xLjkxLjc5LTIuMzItLjExLS4xNy0uMzQuMzUtLjYxLjUzLS4yOC40Mi43MSAxLjQ4LjM4IDEuNDUtLjQ5LjE0LS45Ni4yNS0xLjkyLjQyLTIuODcuMDQtLjI0LjQxLS4yLjQuMDRaIi8+PHBhdGggZD0iTTExLjg1IDE1LjU0Yy4wMi43OS4wMSAxLjU4LjAxIDIuMzctLjAyLjQxLjA3LjktLjE0IDEuMjktLjQzIDEuMDItMi4wMSAxLjAyLTIuNDUgMC0uMjEtLjM5LS4xMy0uODktLjE0LTEuMjkgMC0uNzkgMC0xLjU4LjAxLTIuMzcgMC0uMTEuMS0uMi4yMS0uMTkuMSAwIC4xOC4wOC4xOS4xOC4wNy43OS4xIDEuNTguMTUgMi4zNy4wMy4yNyAwIC44Mi4xMyAxLjA0LjEzLjI2LjQuNDMuNjguNDIuNDYgMCAuNzktLjQuNzctLjg3bC4wMy0uNTljLjA0LS43OS4wOC0xLjU4LjE1LTIuMzcuMDItLjI0LjQtLjIzLjQuMDFaIi8+PC9zdmc+)}.scylla-icon--about-us-m{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNi4zOCAzMi40MyI+PHBhdGggZD0iTTYuNTUgMzEuNjRjLS4yLjEzLS40My4yMi0uNjkuMjZhMS44MSAxLjgxIDAgMCAxLTIuMDYtMS4zOVMuNDkgMTQuOTkuNDkgMTEuODJDLjUgNS4xOSA1Ljc3LjUgMTMuMTkuNXMxMi42OSA0LjY5IDEyLjY5IDExLjMyYzAgMy4xOC0zLjMxIDE4LjY5LTMuMzEgMTguNjlhMS44MSAxLjgxIDAgMCAxLTIuNjIgMS4yIiBzdHlsZT0iZmlsbDpub25lO3N0cm9rZTojMDAwO3N0cm9rZS1saW5lY2FwOnJvdW5kO3N0cm9rZS1saW5lam9pbjpyb3VuZCIvPjxwYXRoIGQ9Ik0yMS44NiAyNS4zNmMtLjI4IDEuOS0uMzcgMy44Ni0uOTEgNS43MS0uNjEgMS40MS0yLjY4IDEuNzUtMy42Ni41NS0uNDEtLjQ3LjMxLTEuMTEuNzMtLjY2LjcxLjc2IDIuMDQuMjkgMi4xNi0uNzMuMzItMS42Ni42NS0zLjMzIDEuMDQtNC45OC4wOS0uMzkuNy0uMjguNjUuMTFaIi8+PHBhdGggZD0iTTE0LjggMTAuNTdjMCAzLjEzLTIuNTMgNS42Ni01LjY2IDUuNjZzLTUuNDctMi41My01LjQ3LTUuNjYgMi4zNC01LjY2IDUuNDctNS42NiA1LjY2IDIuNTMgNS42NiA1LjY2WiIgc3R5bGU9InN0cm9rZS13aWR0aDouOXB4O2ZpbGw6bm9uZTtzdHJva2U6IzAwMDtzdHJva2UtbGluZWNhcDpyb3VuZDtzdHJva2UtbGluZWpvaW46cm91bmQiLz48cGF0aCBkPSJNMTAuMzEgNi44NmMtLjk4LjItMS4xNyAyLjM0LS41OSAyLjkzLjM4LjM4IDEuMTcuNTEgMS4xNy43OHMtLjc5LjQtMS4xNy43OGMtLjU5LjU5LS4zOSAyLjczLjU5IDIuOTMgMS4xNi4yMyAyLjkzLTEuMTcgMi45My0zLjcxcy0xLjc2LTMuOTQtMi45My0zLjcxWk02LjgyIDE4LjUxYzMuNDkuODkgNi45Ny0uNSA5LjUxLTIuOTMuNDctLjQ0IDEuMTYuMzEuNjguNzQtMS4zOCAxLjIzLTIuOTggMi4yOS00Ljc5IDIuODctMS44LjU5LTMuNzcuNTgtNS41OC4xNGEuNDIxLjQyMSAwIDAgMS0uMzEtLjVjLjA1LS4yMi4yOC0uMzYuNS0uMzFaIi8+PHBhdGggZD0iTTE2LjczIDE2LjY3Yy0uMTItLjQ2LS41MS0uODMtLjk5LS44My0uNzUtLjAyLS41OS0xLjE3LjE0LS45OS44MS4xNiAxLjQzLjg1IDEuNSAxLjY2LjA4LjQtLjU0LjU0LS42NS4xNVpNOS4wMyAzMS43Yy0xLjI2IDEuMzYtMy42Mi40NS0zLjgtMS4zNWwtLjA5LS41NWMtLjIxLTEuNDgtLjQ1LTIuOTUtLjYtNC40NC0uMDItLjE4LjExLS4zNC4yOS0uMzYuMTctLjAyLjMyLjA5LjM1LjI1LjM5IDEuNjMuNzEgMy4yOCAxLjAzIDQuOTMuMDkgMS4wMiAxLjM4IDEuNTQgMi4xMi44MS40NS0uNDQgMS4xNC4yNi42OS43WiIvPjxwYXRoIGQ9Ik0xMS45NiAzMS4xNmMtMSAxLjk4LTQuMDQgMS4zLTQuMjEtLjg4LS4xNS0xLjY5LS4zLTMuMzgtLjM5LTUuMDcgMC0uMTguMTMtLjM0LjMxLS4zNC4xNyAwIC4zMS4xMS4zNC4yNy4yOCAxLjY3LjUgMy4zNS43MiA1LjAzLjA5IDEuMiAxLjc3IDEuNTkgMi4zNi41MS4zMS0uNTYgMS4xNi0uMDkuODcuNDdaTTE5LjAzIDI1LjIxYy0uMDggMS42OS0uMjQgMy4zOC0uMzkgNS4wNy0uMDQuMzctLjE3Ljc1LS4zOCAxLjA2LS44NiAxLjQtMy4xMSAxLjMxLTMuODMtLjE3LS4zLS41Ni41NS0xLjAzLjg2LS40OC41OSAxLjA4IDIuMjcuNjkgMi4zNS0uNTIuMjItMS42OC40My0zLjM2LjcyLTUuMDMuMDYtLjQuNjgtLjMzLjY1LjA3WiIvPjxwYXRoIGQ9Ik0xNS40MyAyNS4wMmMuMDQgMS4zMS4wMiAyLjYxLjAyIDMuOTEtLjAzLjY3LjExIDEuNDgtLjIzIDIuMTMtLjc0IDEuNjktMy4yOSAxLjY5LTQuMDMgMC0uMzQtLjY1LS4yMS0xLjQ3LS4yNC0yLjEzIDAtMS4zLS4wMi0yLjYxLjAyLTMuOTEgMC0uMTguMTYtLjMyLjM0LS4zMi4xNyAwIC4zLjE0LjMyLjMuMTEgMS4zLjE3IDIuNi4yNCAzLjkxLjA1LjQ1IDAgMS4zNS4yMSAxLjcyLjIxLjQzLjY2LjcxIDEuMTIuNy40Ni4wMi45MS0uMjcgMS4xMi0uNjkuMjItLjM2LjE2LTEuMjguMjEtMS43Mi4wNy0xLjMuMTMtMi42MS4yNC0zLjkxLjAyLS40LjY2LS4zOC42Ni4wMloiLz48L3N2Zz4=)}.scylla-icon--alternator{background-image:url(data:image/svg+xml;base64,PHN2ZyBpZD0iTGF5ZXJfMyIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB2aWV3Qm94PSIwIDAgMjAgMjAiPjxkZWZzPjxzdHlsZT4uY2xzLTF7ZmlsbDpub25lO3N0cm9rZTojMDAwO3N0cm9rZS1saW5lY2FwOnJvdW5kO3N0cm9rZS1saW5lam9pbjpyb3VuZH08L3N0eWxlPjwvZGVmcz48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Ik0xNy41IDIuOTFjMCAxLjI4LTMuNjcgMi41OS04IDIuNTlzLTgtMS4zMS04LTIuNTlTNS4wOS41IDkuNDIuNXM4LjA4IDEuMTMgOC4wOCAyLjQxWk0xNy41IDcuNjZjMCAxLjI4LTMuNjMgMi44LTcuOTYgMi44UzEuNSA4LjkzIDEuNSA3LjY2TTE3LjUgMTIuNDdjMCAxLjI4LTMuNjcgMy4wMy04IDMuMDNzLTgtMS43NS04LTMuMDNNMTcuNSAxNy4yOWMwIDEuMjgtMy43NSAyLjMtOC4wOCAyLjNzLTcuOTItMS4wMy03LjkyLTIuM00xLjUgMTcuMTlWMi45MU0xNy41IDE3LjE5VjIuOTEiLz48L3N2Zz4=)}.scylla-icon--apps{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyMSAxOSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOm5vbmU7c3Ryb2tlOiM0ZDRkNGQ7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJDYWxxdWVfNCIgZGF0YS1uYW1lPSJDYWxxdWUgNCI+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNLjUgMS41aDIwdjE0SC41ek03LjUgMTUuNzR2Mi44OU0xMi44MyAxNS42M3YyLjMyTTUuNSAxOC41aDkuMTQiLz48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Im0zLjY0IDUuNTYgNC41OCAyLjkxLTQuNTggMi45Mk05LjEgMTIuMDhoNC4zMiIvPjwvZz48L3N2Zz4=)}.scylla-icon--architecture{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMSwuY2xzLTIsLmNscy01e2ZpbGw6bm9uZTtzdHJva2U6Z3JheX0uY2xzLTF7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfS5jbHMtMiwuY2xzLTV7c3Ryb2tlLW1pdGVybGltaXQ6MTB9LmNscy0ye3N0cm9rZS13aWR0aDouOThweH0uY2xzLTV7c3Ryb2tlLXdpZHRoOi45OXB4fTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJDYWxxdWVfMiIgZGF0YS1uYW1lPSJDYWxxdWUgMiI+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNMS45IDEwLjI3YTEwLjgzIDEwLjgzIDAgMCAxIDguNzMtOC4zOE0xMC41MSAyMy4wOEExMC43OSAxMC43OSAwIDAgMSAxLjc3IDE0TTIzLjIzIDE0YTEwLjgxIDEwLjgxIDAgMCAxLTkgOS4xMU0xNC4yNyAxLjg4YTEwLjgxIDEwLjgxIDAgMCAxIDguODMgOC4zNyIvPjxjaXJjbGUgY2xhc3M9ImNscy0yIiBjeD0iMTIuMjUiIGN5PSIxLjc1IiByPSIxLjc1Ii8+PGNpcmNsZSBjbGFzcz0iY2xzLTIiIGN4PSIxMi4yNSIgY3k9IjIyLjc1IiByPSIxLjc1Ii8+PGNpcmNsZSBjeD0iNC45MiIgY3k9IjQuNzUiIHI9IjEuNzUiIHN0eWxlPSJzdHJva2Utd2lkdGg6Ljk5cHg7ZmlsbDpncmF5O3N0cm9rZS1taXRlcmxpbWl0OjEwO3N0cm9rZTpncmF5Ii8+PGNpcmNsZSBjeD0iMjAuMDkiIGN5PSIxOS45MSIgcj0iMS43NSIgc3R5bGU9InN0cm9rZS13aWR0aDouOTlweDtmaWxsOmdyYXk7c3Ryb2tlLW1pdGVybGltaXQ6MTA7c3Ryb2tlOmdyYXkiLz48Y2lyY2xlIGNsYXNzPSJjbHMtNSIgY3g9IjEuNzUiIGN5PSIxMi4yNSIgcj0iMS43NSIvPjxjaXJjbGUgY2xhc3M9ImNscy01IiBjeD0iMjMuMjUiIGN5PSIxMi4yNSIgcj0iMS43NSIvPjxjaXJjbGUgY3g9IjQuNzUiIGN5PSIxOS42NCIgcj0iMS43NSIgc3R5bGU9InN0cm9rZS13aWR0aDouOTlweDtmaWxsOmdyYXk7c3Ryb2tlLW1pdGVybGltaXQ6MTA7c3Ryb2tlOmdyYXkiLz48Y2lyY2xlIGN4PSIxOS45MSIgY3k9IjQuNDgiIHI9IjEuNzUiIHN0eWxlPSJzdHJva2Utd2lkdGg6Ljk5cHg7ZmlsbDpncmF5O3N0cm9rZS1taXRlcmxpbWl0OjEwO3N0cm9rZTpncmF5Ii8+PC9nPjwvc3ZnPg==)}.scylla-icon--benchmarks{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVqb2luOnJvdW5kO3N0cm9rZS13aWR0aDozcHh9PC9zdHlsZT48L2RlZnM+PGcgaWQ9IkNhbHF1ZV8yIiBkYXRhLW5hbWU9IkNhbHF1ZSAyIj48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Ik01LjUxIDI0Ljkxdi01Ljg1TTEyLjU3IDI0Ljkxdi05Ljc0TTE5LjYyIDI0LjkxVjEwLjE1Ii8+PHBhdGggc3R5bGU9InN0cm9rZS1saW5lY2FwOnJvdW5kO2ZpbGw6bm9uZTtzdHJva2U6Z3JheTtzdHJva2UtbGluZWpvaW46cm91bmQiIGQ9Im0uOTEgMTQuOTggNS4xMy03Ljk0IDYuMjUgNS44OEwyNCAxIi8+PHBhdGggc3R5bGU9ImZpbGw6Z3JheSIgZD0ibTI1IDUtNS01aDV2NXoiLz48L2c+PC9zdmc+)}.scylla-icon--blog{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJDYWxxdWVfNCIgZGF0YS1uYW1lPSJDYWxxdWUgNCI+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJtOSAxNS0yLjUtMS41IDgtMTJMMTcgMyA5IDE1eiIvPjxwYXRoIHN0eWxlPSJmaWxsOmdyYXk7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kIiBkPSJtNi41IDEzLjUtLjUgM0w5IDE1bC0yLjUtMS41eiIvPjxwYXRoIGNsYXNzPSJjbHMtMSIgZD0iTTE5LjI1IDIuNWg0LjI1djE2aC0xM3Y0LjE3TDYuNDYgMTguNWwtNC45Ni0uMDRWMi41aDguMzFNMTQuNSAyLjVsMS42NyAxLjMzIi8+PC9nPjwvc3ZnPg==)}.scylla-icon--careers{background-image:url(data:image/svg+xml;base64,PHN2ZyBpZD0iQ2FscXVlXzEiIGRhdGEtbmFtZT0iQ2FscXVlIDEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmlld0JveD0iMCAwIDI1IDI1Ij48ZGVmcz48c3R5bGU+LmNscy0xe2ZpbGw6bm9uZTtzdHJva2U6Z3JheTtzdHJva2UtbGluZWNhcDpyb3VuZDtzdHJva2UtbGluZWpvaW46cm91bmR9PC9zdHlsZT48L2RlZnM+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNMS41IDExLjU1djhjMCAuNTYgMS4wNyAyIDIgMmgxOGMuODkgMCAyLTEuNDQgMi0ydi04Ii8+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNMjMuMzEgMy41SDEuODFjLS40OCAwLTEuMzEuNTUtMS4zMSAxdjZsMTAgMmE4LjQ1IDguNDUgMCAwIDAgNCAwbDEwLTJ2LTZjMC0uNDUtLjcyLTEtMS4xOS0xWk0xNS42MiAzLjV2LTFjMC0uNzYtLjYxLTEtMS4zOC0xaC0zLjQ1Yy0uNzYgMC0xLjM4LjI0LTEuMzggMXYxIi8+PHJlY3QgeD0iMTAiIHk9IjExIiB3aWR0aD0iNSIgaGVpZ2h0PSIzLjk5IiByeD0iLjU1IiByeT0iLjU1IiBzdHlsZT0iZmlsbDpncmF5Ii8+PC9zdmc+)}.scylla-icon--chevron-left{background-image:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTAiIGhlaWdodD0iMTYiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZD0iTTguMDkyIDE2IDEwIDE0LjExMyAzLjgxNyA4IDEwIDEuODg3IDguMDkyIDAgMCA4bDguMDkyIDhaIiBmaWxsPSIjMDAwIi8+PC9zdmc+)}.contents.local>ul>li a:before,.scylla-icon--chevron-right,.secondary-side-nav__content li a:before{background-image:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTAiIGhlaWdodD0iMTYiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZD0iTTEuOTA4IDAgMCAxLjg4NyA2LjE4MyA4IDAgMTQuMTEzIDEuOTA4IDE2IDEwIDggMS45MDggMFoiIGZpbGw9IiMwMDAiLz48L3N2Zz4=)}.scylla-icon--circe{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAzOCAzMCI+PGRlZnM+PHN0eWxlPi5jbHMtMiwuY2xzLTN7ZmlsbDpub25lO3N0cm9rZTojNGQ0ZDRkO3N0cm9rZS1saW5lY2FwOnJvdW5kO3N0cm9rZS1saW5lam9pbjpyb3VuZH0uY2xzLTN7c3Ryb2tlLXdpZHRoOjEuMTFweH08L3N0eWxlPjwvZGVmcz48ZyBpZD0iQ2FscXVlXzQiIGRhdGEtbmFtZT0iQ2FscXVlIDQiPjxwYXRoIGQ9Ik0yMi4xIDEyaC02LjE2YTEuMDYgMS4wNiAwIDAgMS0uOTQtMS4wNy45My45MyAwIDAgMSAuOTQtLjkzaDYuMTZhLjkzLjkzIDAgMCAxIC45NC45M0ExLjA2IDEuMDYgMCAwIDEgMjIuMSAxMloiIHN0eWxlPSJmaWxsOiM0ZDRkNGQiLz48cGF0aCBjbGFzcz0iY2xzLTIiIGQ9Ik0xMy40NCA0LjQ5SDkuNTF2MjRoMTl2LTI0SDI0LjUiLz48cGF0aCBjbGFzcz0iY2xzLTMiIGQ9Ik0xMyAzLjQ5SDguNWwtLjA4IDI2LjFIMjkuNVYzLjM5SDI1Ii8+PHBhdGggY2xhc3M9ImNscy0yIiBkPSJNMTIuNSAxOC4zOGgxM00xMi41IDE1LjQ5aDEzTTEyLjUgMjEuNDNoMTNNMTIuNSAyNC40N2gxM00xMy41IDIuNWgxMXYzLjk4aC0xMXoiLz48cGF0aCBjbGFzcz0iY2xzLTMiIGQ9Ik0yMS41LjVoLTUuMDR2MS45NWw1LjA0LjA1di0yeiIvPjwvZz48L3N2Zz4=)}.scylla-icon--clock{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyMSAxOSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOm5vbmU7c3Ryb2tlOiM0ZDRkNGQ7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJDYWxxdWVfNCIgZGF0YS1uYW1lPSJDYWxxdWUgNCI+PGNpcmNsZSBjbGFzcz0iY2xzLTEiIGN4PSIxMC41IiBjeT0iOS41IiByPSI5Ii8+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNMTAuNSAzLjV2NmwzLjA2IDMiLz48L2c+PC9zdmc+)}.scylla-icon--close{background-image:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMzQiIGhlaWdodD0iMzQiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGcgY2xpcC1wYXRoPSJ1cmwoI2EpIiBmaWxsPSIjZmZmIj48cGF0aCBkPSJNMTEuNjcgMjIuMTNhLjU2NC41NjQgMCAwIDEtLjM5OC0uOTYybDkuODk2LTkuODk2YS41NjMuNTYzIDAgMSAxIC43OTcuNzk3bC05Ljg5NiA5Ljg5NmEuNTU5LjU1OSAwIDAgMS0uMzk5LjE2NVoiLz48cGF0aCBkPSJNMjEuNTY2IDIyLjEzYS41NTkuNTU5IDAgMCAxLS4zOTgtLjE2NWwtOS44OTYtOS44OTZhLjU2My41NjMgMCAxIDEgLjc5Ny0uNzk3bDkuODk2IDkuODk1YS41NjQuNTY0IDAgMCAxLS4zOTkuOTYzWiIvPjxwYXRoIGQ9Ik0xNi42MTkgMzMuMjM3QzcuNDU1IDMzLjIzNyAwIDI1Ljc4MiAwIDE2LjYxOSAwIDcuNDU2IDcuNDU1IDAgMTYuNjE5IDBzMTYuNjE5IDcuNDU1IDE2LjYxOSAxNi42MTktNy40NTYgMTYuNjE4LTE2LjYyIDE2LjYxOFptMC0zMi4xMWMtOC41NDIgMC0xNS40OTIgNi45NS0xNS40OTIgMTUuNDkyIDAgOC41NDIgNi45NSAxNS40OTIgMTUuNDkyIDE1LjQ5MiA4LjU0MiAwIDE1LjQ5Mi02Ljk1IDE1LjQ5Mi0xNS40OTIgMC04LjU0Mi02Ljk1LTE1LjQ5Mi0xNS40OTItMTUuNDkyWiIvPjwvZz48ZGVmcz48Y2xpcFBhdGggaWQ9ImEiPjxwYXRoIGZpbGw9IiNmZmYiIGQ9Ik0wIDBoMzMuMjM3djMzLjIzN0gweiIvPjwvY2xpcFBhdGg+PC9kZWZzPjwvc3ZnPg==)}.scylla-icon--cloud{background-image:url(data:image/svg+xml;base64,PHN2ZyBpZD0iTGF5ZXJfMiIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB2aWV3Qm94PSIwIDAgNDMuMDQgMzIuMDMiPjxkZWZzPjxzdHlsZT4uY2xzLTF7ZmlsbDpub25lO3N0cm9rZTojMWQxZDFiO3N0cm9rZS1saW5lY2FwOnJvdW5kO3N0cm9rZS1saW5lam9pbjpyb3VuZH08L3N0eWxlPjwvZGVmcz48ZyBpZD0iTGF5ZXJfMyI+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNNDIuNTQgNC4wNmMwIDEuNjgtMy42MyAyLjQ0LTkgMi40NHMtMTAtLjczLTEwLTIuNFMyNy42Ny41IDMzLjA0LjVzOS41IDEuODkgOS41IDMuNTZaTTQyLjU0IDkuNjNjMCAxLjY4LTMuNzYgMi45MS05LjEyIDIuOTFzLTkuODQtMS4yMy05Ljg0LTIuOTFNNDIuNTQgMTUuMzRjMCAxLjY4LTMuNjggMy4yNS05LjA0IDMuMjUtNCAwLTcuNi0uOTYtOS4wOS0yLjA0TTQyLjU0IDIwLjY1YzAgMS42OC0zLjcyIDIuOTctOS4wOCAyLjk3TTIzLjU0IDE1LjQ2VjQuMU00Mi41NCAyMC43N1Y0LjEiLz48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Ik0yOC4xMSAyMS4wOGMtLjg3IDAtMS42Ny4yMy0yLjM5LjYxIDAtLjA3LjAxLS4xNC4wMS0uMjEgMC00Ljg1LTMuODMtOC45LTguNjgtOC45cy04Ljg4IDQuMDUtOC44OCA4LjljMCAuMTcuMDIuMzQuMDMuNTEtLjg0LS41Ny0xLjg1LS45MS0yLjk1LS45MS0yLjg4IDAtNC43NCAyLjU3LTQuNzQgNS40NnMxLjg2IDQuOTkgNC43NCA0Ljk5aDIyLjg2YzIuODggMCA1LjUyLTIuMjcgNS41Mi01LjE2cy0yLjYzLTUuMjktNS41Mi01LjI5WiIvPjwvZz48L3N2Zz4=)}.scylla-icon--cloud-docs{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyMSAxOSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOm5vbmU7c3Ryb2tlOiM0ZDRkNGQ7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJDYWxxdWVfNCIgZGF0YS1uYW1lPSJDYWxxdWUgNCI+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNNi41IDExLjVoOHYxaC04ek0xNS42NSA2LjU1YTMuNDIgMy40MiAwIDAgMC0zLjE1IDIiLz48cGF0aCBkPSJNMTAuMDYgMi44QTUuMTcgNS4xNyAwIDAgMSAxNSA2LjM1aC4yNGE0Ljg0IDQuODQgMCAwIDEgMCA5LjY3aC0xMWEzLjQ1IDMuNDUgMCAwIDEgMC02LjlBMy4xNyAzLjE3IDAgMCAxIDUgOS4yIDUuMzMgNS4zMyAwIDAgMSA0Ljg2IDhhNS4yIDUuMiAwIDAgMSA1LjItNS4ybTAtLjhhNiA2IDAgMCAwLTYgNnYuMzFhNC4yNSA0LjI1IDAgMCAwIC4xOCA4LjQ5aDExYTUuNjMgNS42MyAwIDAgMCAuMy0xMS4yNkE2IDYgMCAwIDAgMTAuMDYgMloiIHN0eWxlPSJmaWxsOiM0ZDRkNGQiLz48L2c+PC9zdmc+)}.scylla-icon--comparison{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMSwuY2xzLTIsLmNscy00e2ZpbGw6bm9uZTtzdHJva2U6Z3JheX0uY2xzLTEsLmNscy0ye3N0cm9rZS1taXRlcmxpbWl0OjEwfS5jbHMtMiwuY2xzLTR7c3Ryb2tlLWxpbmVjYXA6cm91bmR9LmNscy00e3N0cm9rZS1saW5lam9pbjpyb3VuZH08L3N0eWxlPjwvZGVmcz48ZyBpZD0iQ2FscXVlXzQiIGRhdGEtbmFtZT0iQ2FscXVlIDQiPjxwYXRoIGNsYXNzPSJjbHMtMSIgZD0iTTQuNSAxMy42M3YyLjg4aDYuMDZNMjAuNSAxMy41NHYyLjk2bC01LjUuMDEiLz48cGF0aCBjbGFzcz0iY2xzLTIiIGQ9Ik0xMi41IDE4LjV2Mi43Mk03LjUgMjEuNWgxMCIvPjxjaXJjbGUgY3g9IjEyLjUiIGN5PSIxNi41IiByPSIyIiBzdHlsZT0iZmlsbDpncmF5O3N0cm9rZS13aWR0aDouOTVweDtzdHJva2UtbWl0ZXJsaW1pdDoxMDtzdHJva2U6Z3JheSIvPjxwYXRoIGNsYXNzPSJjbHMtNCIgZD0iTTUuMDYgMTMuNThIMy44OEEzLjEgMy4xIDAgMCAxIC41IDEwLjVoOGEzLjE2IDMuMTYgMCAwIDEtMy40NCAzLjA4Wk0yMSAxMy41OGgtMS4xN2EzLjA5IDMuMDkgMCAwIDEtMy4zNy0zLjA3aDhBMy4xNiAzLjE2IDAgMCAxIDIxIDEzLjU4Wk03LjQ2IDUuMTJjMCAuNTctMS4xLjQ2LTIuNzkuNDZTMS41OCA1LjYgMS41OCA1IDMgNC40IDQuNjkgNC40czIuNzcuMTYgMi43Ny43MlpNMS41IDkuODVWNS4zMU03LjUgMTAuMzVWNS44MU0yMy41IDUuMTJjMCAuNTctMS4xLjQ2LTIuNzkuNDZzLTMuMDkgMC0zLjA5LS41NFMxOSA0LjQgMjAuNzMgNC40czIuNzcuMTYgMi43Ny43MlpNMTcuNTQgOS44NVY1LjMxTTIzLjU0IDEwLjM1VjUuODEiLz48L2c+PC9zdmc+)}.scylla-icon--contact-us{background-image:url(data:image/svg+xml;base64,PHN2ZyBpZD0iQ2FscXVlXzEiIGRhdGEtbmFtZT0iQ2FscXVlIDEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmlld0JveD0iMCAwIDI1IDI1Ij48ZGVmcz48c3R5bGU+LmNscy0xe2ZpbGw6bm9uZTtzdHJva2U6Z3JheTtzdHJva2UtbGluZWNhcDpyb3VuZDtzdHJva2UtbGluZWpvaW46cm91bmQ7c3Ryb2tlLXdpZHRoOjEuMDZweH08L3N0eWxlPjwvZGVmcz48cGF0aCBjbGFzcz0iY2xzLTEiIHRyYW5zZm9ybT0icm90YXRlKC0yNy40OSAxNS41NTIgMTEuMDgzKSIgZD0iTTcuNzYgNi4wMWgxNS41OXYxMC4xM0g3Ljc2eiIvPjxwYXRoIGNsYXNzPSJjbHMtMSIgZD0ibTYuMyAxMC4xOCA4LjYzIDEuNTZhMS40MiAxLjQyIDAgMCAwIDEuNTMtLjc0bDMuNjctOE0xMS4wMiAxOS4wM2wxLjc0LTVNMjQuNTkgMTEuOTdsLTUuMDktMS40NU03LjA5IDE3LjU4IDMuOSAxOS4zNE02LjA2IDE1LjQxLjU0IDE4LjM2Ii8+PC9zdmc+)}.scylla-icon--developers-blog{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOmdyYXl9PC9zdHlsZT48L2RlZnM+PGcgaWQ9IkNhbHF1ZV80IiBkYXRhLW5hbWU9IkNhbHF1ZSA0Ij48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Im02LjQ4IDEwLjU5LS41LjE3LjUuMTZMMTEgMTIuMTZWMTRsLTctMi40OVYxMGw3LTIuNXYxLjgzWk0xNCA5LjMyVjcuNWw3IDIuNXYxLjU0TDE0IDE0di0xLjgzbDQuMTQtMS4zLjQ0LS4xMy0uNDMtLjE0WiIvPjxwYXRoIHN0eWxlPSJmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kO3N0cm9rZS13aWR0aDouOThweCIgZD0iTTEuNSAyLjVoMjJ2MTZoLTEzdjQuMTdMNi40NiAxOC41bC00Ljk2LS4wNFYyLjV6Ii8+PC9nPjwvc3ZnPg==)}.scylla-icon--docs{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfS5jbHMtMntmaWxsOmdyYXl9PC9zdHlsZT48L2RlZnM+PGcgaWQ9IkNhbHF1ZV80IiBkYXRhLW5hbWU9IkNhbHF1ZSA0Ij48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Ik0zLjUgMi41MWgxNi45NHYyMC45MUgzLjV6Ii8+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJtMjIuNDUgMjEuNS4wNS0yMWgtMTdhMi4xNiAyLjE2IDAgMCAwLTIgMiIvPjxwYXRoIGNsYXNzPSJjbHMtMiIgZD0iTTYgNmg3djJINnpNNiA5aDExdjJINnoiLz48L2c+PC9zdmc+)}.scylla-icon--enterprise{background-image:url(data:image/svg+xml;base64,PHN2ZyBpZD0iTGF5ZXJfMyIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB2aWV3Qm94PSIwIDAgMjAgMjAiPjxkZWZzPjxzdHlsZT4uY2xzLTEsLmNscy0ye2ZpbGw6bm9uZTtzdHJva2U6IzAwMDtzdHJva2UtbGluZWNhcDpyb3VuZDtzdHJva2UtbGluZWpvaW46cm91bmR9LmNscy0ye3N0cm9rZS13aWR0aDoxLjA3cHh9PC9zdHlsZT48L2RlZnM+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJtMTMuNjIgNy41IDEuODgtMS4wOCAyIDIuMDh2N2gxTTE1LjUgMTUuNXYtNSIvPjxwYXRoIGNsYXNzPSJjbHMtMiIgZD0iTTUuNSAxNS41di0xMmw0LTIgNCAydjEyTTkuNSAxNS41VjEuNk03LjUgNS41djEwTTExLjUgNS41djEwIi8+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNNS41IDguNTQgMy40NiA3LjVsLTEuOTYuOTZ2Ny4wNGgtMU0zLjUgMTAuNXY1TS41IDE3LjVoMTgiLz48L3N2Zz4=)}.scylla-icon--enterprise-m{background-image:url(data:image/svg+xml;base64,PHN2ZyB2ZXJzaW9uPSIxLjEiIGlkPSJMYXllcl8yXzAwMDAwMDE2NzY4MDY2MDE5MjYzMjMyNzcwMDAwMDA1NDc1ODA5NTExODI4NjY2MDM2XyIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4PSIwIiB5PSIwIiB2aWV3Qm94PSIwIDAgNDMgMzEiIHN0eWxlPSJlbmFibGUtYmFja2dyb3VuZDpuZXcgMCAwIDQzIDMxIiB4bWw6c3BhY2U9InByZXNlcnZlIj48c3R5bGU+LnN0MHtmaWxsOm5vbmU7c3Ryb2tlOiMxZDFkMWI7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfTwvc3R5bGU+PGcgaWQ9IkxheWVyXzMiPjxwYXRoIGNsYXNzPSJzdDAiIGQ9Im0yOS42IDkuNSA0LTIgNi45IDQuMXYxNS45aDJNMzMuNiAyNy41VjcuNk0xNC42IDI3LjVWNC44TDIyLjUuNSAyOS42IDV2MjIuNU0yMi41IDI3LjVWMU0yNC41IDUuNmwzIDJNMjQuNSA5LjZsMyAyTTI0LjUgMTMuNmwzIDJNMjQuNSAxNy41bDMgMk0yNC41IDIxLjVsMyAyTTM1LjQgMTEuNmwzIDJNMzUuNCAxNS42bDMgMS45TTM1LjQgMTkuNWwzIDJNMzUuNCAyMy41bDMgMS45TTE4LjUgNS44djIxLjdNMTQuNiA5LjdsLTQuMS0yLjUtOCA0LjR2MTUuOWgtMk0xMC41IDI3LjVWNy4yTTEyLjUgMTEuNmwyIDFNMTIuNSAxNS42bDIgLjlNMTIuNSAxOS41bDIgMU0xMi41IDIzLjVsMi4xIDFNNi40IDEyLjR2MTUuMU0uNSAzMC41aDQyIi8+PC9nPjwvc3ZnPg==)}.scylla-icon--events{background-image:url(data:image/svg+xml;base64,PHN2ZyBpZD0iQ2FscXVlXzEiIGRhdGEtbmFtZT0iQ2FscXVlIDEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmlld0JveD0iMCAwIDI1IDI1Ij48ZGVmcz48c3R5bGU+LmNscy0xe2ZpbGw6bm9uZTtzdHJva2U6Z3JheTtzdHJva2UtbGluZWNhcDpyb3VuZDtzdHJva2UtbGluZWpvaW46cm91bmR9LmNscy0ye2ZpbGw6Z3JheX08L3N0eWxlPjwvZGVmcz48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Ik0yMi41IDIzLjVoLTIxdi0yMGgyMnYxNS4yMSIvPjxwYXRoIGNsYXNzPSJjbHMtMSIgZD0iTTQuNDIgMy41YzAtMS4zNiAxLjA5LTIgMi40NS0yYTIuNDYgMi40NiAwIDEgMSAwIDQuOTEgMi42MSAyLjYxIDAgMCAxLTEtLjIxTTEwLjY3IDMuNWMwLTEuMzYgMS4xLTIgMi40Ni0yYTIuNDYgMi40NiAwIDAgMSAwIDQuOTEgMi42MSAyLjYxIDAgMCAxLTEtLjIxTTE2LjkzIDMuNWMwLTEuMzYgMS4xLTIgMi40NS0yYTIuNDYgMi40NiAwIDEgMSAwIDQuOTEgMi41MiAyLjUyIDAgMCAxLTEtLjIxIi8+PHBhdGggY2xhc3M9ImNscy0yIiBkPSJNNyA5aDN2M0g3ek0xMiA5aDN2M2gtM3pNMTcgOWgzdjNoLTN6TTcgMTRoM3YzSDd6TTEyIDE0aDN2M2gtM3pNMTcgMTRoM3YzaC0zeiIvPjxwYXRoIGNsYXNzPSJjbHMtMSIgZD0iTTMuNSAzLjY3djE2LjY2TTMuNSAyMC40M2MwIDEuMjkuNDQgMi4zMyAxLjczIDIuMzNzMi4zMy0xLjkgMi4zMy0zLjE5bDE2Ljk0LS4wN2MwIDEuMjktLjU1IDMuMTItMS44MyAzLjEySDYuMyIvPjwvc3ZnPg==)}.admonition.note .admonition-title:before,.admonition.tip .admonition-title:before,.scylla-icon--exclamation{background-image:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PG1hc2sgaWQ9ImEiIG1hc2stdHlwZT0iYWxwaGEiIG1hc2tVbml0cz0idXNlclNwYWNlT25Vc2UiIHg9IjEiIHk9IjEiIHdpZHRoPSIyMiIgaGVpZ2h0PSIyMiI+PHBhdGggZD0iTTEyIDIzQzUuOSAyMyAxIDE4LjEgMSAxMlM1LjkgMSAxMiAxczExIDQuOSAxMSAxMS00LjkgMTEtMTEgMTFabTAtMjBjLTUgMC05IDQtOSA5czQgOSA5IDkgOS00IDktOS00LTktOS05WiIgZmlsbD0iI2ZmZiIvPjxwYXRoIGQ9Ik0xMiAxM2MtLjYgMC0xLS40LTEtMVY4YzAtLjYuNC0xIDEtMXMxIC40IDEgMXY0YzAgLjYtLjQgMS0xIDFaTTEyIDE3Yy0uMyAwLS41LS4xLS43LS4zLS4yLS4yLS4zLS40LS4zLS43IDAtLjEgMC0uMy4xLS40LjEtLjEuMS0uMi4yLS4zLjMtLjMuNy0uNCAxLjEtLjIuMSAwIC4xIDAgLjIuMSAwIDAgLjEuMS4yLjEuMS4xLjIuMi4yLjN2LjRjMCAuMSAwIC4zLS4xLjQtLjEuMS0uMS4yLS4yLjMtLjIuMi0uNC4zLS43LjNaIiBmaWxsPSIjZmZmIi8+PC9tYXNrPjxnIG1hc2s9InVybCgjYSkiPjxwYXRoIGZpbGw9IiNmZmYiIGQ9Ik0wIDBoMjR2MjRIMHoiLz48L2c+PC9zdmc+)}.collapsible-button i,.scylla-icon--expand{background-image:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYuMDAxIiBoZWlnaHQ9IjE2IiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjxwYXRoIGQ9Ik01IDEzYTEgMSAwIDAgMS0uNzEtLjI5bC00LTRhMSAxIDAgMCAxIDAtMS40MWw0LTRhMSAxIDAgMCAxIDEuNDIgMS40MUwyLjQxIDhsMy4yOSAzLjI5QTEgMSAwIDAgMSA1IDEzeiIvPjxwYXRoIGQ9Ik0xMSA5SDFhMSAxIDAgMCAxIDAtMmgxMGExIDEgMCAwIDEgMCAyek0xNSAxNmExIDEgMCAwIDEtMS0xVjFhMSAxIDAgMCAxIDIgMHYxNGExIDEgMCAwIDEtMSAxeiIvPjwvc3ZnPg==)}.scylla-icon--forum{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSJjdXJyZW50Q29sb3IiIHN0cm9rZS13aWR0aD0iMS41IiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiIGNsYXNzPSJmZWF0aGVyIGZlYXRoZXItdXNlcnMiPjxwYXRoIGQ9Ik0xNyAyMXYtMmE0IDQgMCAwIDAtNC00SDVhNCA0IDAgMCAwLTQgNHYyIi8+PGNpcmNsZSBjeD0iOSIgY3k9IjciIHI9IjQiLz48cGF0aCBkPSJNMjMgMjF2LTJhNCA0IDAgMCAwLTMtMy44N00xNiAzLjEzYTQgNCAwIDAgMSAwIDcuNzUiLz48L3N2Zz4=)}.scylla-icon--home{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyMSAxOSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOm5vbmU7c3Ryb2tlOiM0ZDRkNGQ7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJMYXllcl81IiBkYXRhLW5hbWU9IkxheWVyIDUiPjxwYXRoIGNsYXNzPSJjbHMtMSIgZD0iTTMuNSA2LjE0djExYTEuMzggMS4zOCAwIDAgMCAxLjM3IDEuMzZoMTEuMjZhMS4zOCAxLjM4IDAgMCAwIDEuMzctMS4zN3YtMTEiLz48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Im0xOS41IDcuNS04LTYuMjVhMS41OSAxLjU5IDAgMCAwLTEuOTQgMEwxLjUgNy41TTEyLjczIDE4LjAydi03LjIxSDguMjd2Ny4yMSIvPjwvZz48L3N2Zz4=)}.scylla-icon--getting-started{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyMSAxOSI+PGcgZGF0YS1uYW1lPSJDYWxxdWUgNCI+PHBhdGggc3R5bGU9ImZpbGw6IzRkNGQ0ZCIgZD0ibTcgNC41IDguNTEgNS4wNUw3IDE0LjV2LTEweiIvPjxyZWN0IHg9IjEuNSIgeT0iLjUiIHdpZHRoPSIxOCIgaGVpZ2h0PSIxOCIgcng9IjIuNDMiIHN0eWxlPSJmaWxsOm5vbmU7c3Ryb2tlOiM0ZDRkNGQ7c3Ryb2tlLW1pdGVybGltaXQ6MTAiLz48L2c+PC9zdmc+)}.scylla-icon--glossary{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyMSAxOSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOm5vbmU7c3Ryb2tlOiM0ZDRkNGQ7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJDYWxxdWVfNCIgZGF0YS1uYW1lPSJDYWxxdWUgNCI+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNMi41IDIuNWgxM3YxNmgtMTN6Ii8+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNMTUuNTggMTcuMjFoMS45MlYuNWgtMTNhMi4zNCAyLjM0IDAgMCAwLTIgMiIvPjxwYXRoIGQ9Ik00LjggMTMuOTNhMSAxIDAgMCAwIC43NS0uNDMgNiA2IDAgMCAwIC41Mi0xLjA4bDIuODctNy4wN2guMzZsMi44OCA2Ljc5YTguOTIgOC45MiAwIDAgMCAuNzIgMS40Ny43Ni43NiAwIDAgMCAuNjguMzJ2LjMySDkuNHYtLjMyYTMuMjQgMy4yNCAwIDAgMCAuODMtLjExYy4xMy0uMDYuMi0uMTkuMi0uNDJhMS41OSAxLjU5IDAgMCAwLS4xLS40NmMwLS4xMi0uMS0uMjctLjE3LS40NGwtLjMzLS43OGgtMi45Yy0uMTkuNTEtLjMxLjg1LS4zNiAxYTIuMzggMi4zOCAwIDAgMC0uMTcuNzNjMCAuMTguMTIuMzIuMzcuNGEyLjU2IDIuNTYgMCAwIDAgLjY2LjA4di4zMkg0LjhabTQuODQtMi43Mi0xLjI0LTNoLS4xMWwtMS4xNiAzWiIgc3R5bGU9ImZpbGw6IzRkNGQ0ZCIvPjwvZz48L3N2Zz4=)}.scylla-icon--infoworld{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLW1pdGVybGltaXQ6MTB9PC9zdHlsZT48L2RlZnM+PGcgaWQ9IkNhbHF1ZV80IiBkYXRhLW5hbWU9IkNhbHF1ZSA0Ij48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Ik0xMiAyLjVINi41VjZjMCAzIC41NSA3LjE3IDUgOS41djQiLz48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Ik02LjQgNC40NGgtNFMyLjU2IDExIDguNSAxM00xOC41IDQuNWw0LS4wNnMtLjA2IDYuNTYtNiA4LjU2Ii8+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNMTIgMi41aDYuNVY2YzAgMi45NC0uNCA3LjA4LTUgOS41djRNOS41IDE5LjVoNnYyaC02eiIvPjxwYXRoIHN0eWxlPSJmaWxsOmdyYXk7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLW1pdGVybGltaXQ6MTAiIGQ9Ik03LjUgMjEuNWgxMHYxaC0xMHoiLz48L2c+PC9zdmc+)}.scylla-icon--integrations{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOm5vbmU7c3Ryb2tlOiM0ZDRkNGQ7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJDYWxxdWVfNCIgZGF0YS1uYW1lPSJDYWxxdWUgNCI+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJtMTQuNTYgMTIuNy0xLjI1LTEuNTctMS4zMS43NmE2IDYgMCAwIDAtMS42NS0xbC4wOC0xLjQ5LTItLjQtLjUzIDEuNDRhNS43MyA1LjczIDAgMCAwLTEuODcuMzFsLS44OC0xLjE5LTEuNzcgMUwzLjkyIDEyYTYuMyA2LjMgMCAwIDAtMS4yMiAxLjQxbC0xLjUtLjM1LS43NCAxLjg3IDEuMzguOGE2LjIzIDYuMjMgMCAwIDAgMCAxLjgzbC0xLjQxLjcyLjY0IDEuOTEgMS41OS0uMjhhNy42MyA3LjYzIDAgMCAwIC40OC42OCA1Ljg2IDUuODYgMCAwIDAgLjY3LjczbC0uNjIgMS40NiAxLjcyIDEgMS0xLjI0YTYuNDYgNi40NiAwIDAgMCAxLjc5LjM1bC40NiAxLjUyIDItLjN2LTEuNmE2LjQzIDYuNDMgMCAwIDAgMS42Mi0uODlsMS4zLjg1TDE0LjQzIDIxbC0xLTEuMmE2LjI0IDYuMjQgMCAwIDAgLjY4LTEuNzVsMS41MS0uMTkuMDUtMi0xLjUxLS4yNmE2LjA3IDYuMDcgMCAwIDAtLjYyLTEuODFabS01LjM1IDUuNTFhMS45MyAxLjkzIDAgMSAxIC4zMS0yLjcxIDEuOTIgMS45MiAwIDAgMS0uMzEgMi43MVoiLz48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Im0yNC4zMSA4LjA1LS4xMy0xLjY1LTEuMjUtLjA5YTUuMjYgNS4yNiAwIDAgMC0uNjctMS40NGwuNzUtMS0xLjE2LTEuMTctMSAuNzRhNS4xOCA1LjE4IDAgMCAwLTEuNDMtLjY2bC0uMDYtMS4yNC0xLjY1LS4xNy0uMzIgMS4yNWE1Ljc3IDUuNzcgMCAwIDAtMS41Mi4zOEwxNSAyLjFsLTEuMzcuOS41OCAxLjE4YTQuODggNC44OCAwIDAgMC0uODYgMS4yNWwtMS4zLS4xNi0uNDUgMS42IDEuMjIuNTVhNS4xNyA1LjE3IDAgMCAwIDAgLjY4QTQuMjggNC4yOCAwIDAgMCAxMyA5bC0xLjExLjcyLjY5IDEuNTEgMS4yOC0uMzdhNC45NCA0Ljk0IDAgMCAwIDEuMDcgMS4wN2wtLjM5IDEuMjYgMS41LjcxLjc0LTEuMDlhNS4wNyA1LjA3IDAgMCAwIDEuNTIuMTRsLjUgMS4xOSAxLjYxLS40MS0uMTMtMS4yOWE1LjE0IDUuMTQgMCAwIDAgMS4yNy0uODhsMS4xMi41NyAxLTEuMzUtLjkxLS44OGE0LjkgNC45IDAgMCAwIC40Mi0xLjUyWm0tNi4yIDEuNDNhMS43NCAxLjc0IDAgMSAxIDEuNi0xLjg2IDEuNzQgMS43NCAwIDAgMS0xLjYgMS44NloiLz48L2c+PC9zdmc+)}.scylla-icon--knowledge-base{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyMSAxOSI+PGRlZnM+PHN0eWxlPi5jbHMtMSwuY2xzLTJ7ZmlsbDpub25lO3N0cm9rZTojNGQ0ZDRkfS5jbHMtMXtzdHJva2UtbGluZWNhcDpyb3VuZDtzdHJva2UtbGluZWpvaW46cm91bmR9LmNscy0ye3N0cm9rZS1taXRlcmxpbWl0OjEwfTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJMYXllcl81IiBkYXRhLW5hbWU9IkxheWVyIDUiPjxwYXRoIGNsYXNzPSJjbHMtMSIgZD0iTTE2LjIxIDYuMzhhNS4zNiA1LjM2IDAgMCAxLTEuNTEgMy43MyA1IDUgMCAwIDAtMS40NSAzLjMxSDguNDdhNS40MSA1LjQxIDAgMCAwLTEuMjgtMy4xMSA1LjM3IDUuMzcgMCAxIDEgOS0zLjkzWk0xMy4yMyAxNS42N0g4LjQ1Ii8+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNMTMuMjQgMTMuNGgtNC44djQuMTZhLjcuNyAwIDAgMCAuNzEuN2gzLjM4YS43LjcgMCAwIDAgLjcxLS43WiIvPjxwYXRoIGNsYXNzPSJjbHMtMiIgZD0iTTEwLjg0IDguMjFhMS42NSAxLjY1IDAgMSAxIDEuNjQtMS42NSAxLjY1IDEuNjUgMCAwIDEtMS42NCAxLjY1Wk0xMC44NCA4LjY3djQuNjQiLz48L2c+PC9zdmc+)}.scylla-icon--less{background-image:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTciIGhlaWdodD0iMTciIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHJlY3Qgd2lkdGg9IjE3IiBoZWlnaHQ9IjE3IiByeD0iMSIgZmlsbD0iI0IzQkFDNSIvPjxwYXRoIGQ9Ik0xMyA4LjVhMSAxIDAgMCAxLTEgMUg1YTEgMSAwIDAgMSAwLTJoN2ExIDEgMCAwIDEgMSAxWiIgZmlsbD0iI2ZmZiIvPjxwYXRoIGQ9Ik0xMyA4LjVhMSAxIDAgMCAxLTEgMUg1YTEgMSAwIDAgMSAwLTJoN2ExIDEgMCAwIDEgMSAxWiIgZmlsbD0iI2ZmZiIvPjxwYXRoIGQ9Ik0xMyA4LjVhMSAxIDAgMCAxLTEgMUg1YTEgMSAwIDAgMSAwLTJoN2ExIDEgMCAwIDEgMSAxWiIgZmlsbD0iI2ZmZiIvPjxwYXRoIGQ9Ik0xMyA4LjVhMSAxIDAgMCAxLTEgMUg1YTEgMSAwIDAgMSAwLTJoN2ExIDEgMCAwIDEgMSAxWiIgZmlsbD0iI2ZmZiIvPjxwYXRoIGQ9Ik0xMyA4LjVhMSAxIDAgMCAxLTEgMUg1YTEgMSAwIDAgMSAwLTJoN2ExIDEgMCAwIDEgMSAxWiIgZmlsbD0iI2ZmZiIvPjwvc3ZnPg==);filter:none}.scylla-icon--live-test{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtNntmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLW1pdGVybGltaXQ6MTA7c3Ryb2tlLWxpbmVjYXA6cm91bmR9PC9zdHlsZT48L2RlZnM+PGcgaWQ9IkNhbHF1ZV80IiBkYXRhLW5hbWU9IkNhbHF1ZSA0Ij48Y2lyY2xlIGN4PSIxMi41IiBjeT0iMTUiIHI9IjkuNSIgc3R5bGU9InN0cm9rZS13aWR0aDoxLjVweDtzdHJva2UtbWl0ZXJsaW1pdDoxMDtmaWxsOm5vbmU7c3Ryb2tlOmdyYXkiLz48cGF0aCBzdHlsZT0ic3Ryb2tlLXdpZHRoOjEuMXB4O3N0cm9rZS1saW5lam9pbjpyb3VuZDtzdHJva2UtbGluZWNhcDpyb3VuZDtmaWxsOm5vbmU7c3Ryb2tlOmdyYXkiIGQ9Ik0xMCAuNWg1djJoLTV6Ii8+PHBhdGggc3R5bGU9InN0cm9rZS13aWR0aDoxLjExcHg7c3Ryb2tlLWxpbmVqb2luOnJvdW5kO3N0cm9rZS1saW5lY2FwOnJvdW5kO2ZpbGw6bm9uZTtzdHJva2U6Z3JheSIgZD0iTTUuOCA4LjIgNC4xMyA2LjUzbDEuOC0xLjgxTDcuNiA2LjQiLz48cGF0aCBzdHlsZT0ic3Ryb2tlLXdpZHRoOjEuMTNweDtzdHJva2UtbWl0ZXJsaW1pdDoxMDtmaWxsOm5vbmU7c3Ryb2tlOmdyYXkiIGQ9Ik0xMiA2VjIuNSIvPjxwYXRoIHN0eWxlPSJzdHJva2Utd2lkdGg6MS4wOHB4O3N0cm9rZS1taXRlcmxpbWl0OjEwO2ZpbGw6bm9uZTtzdHJva2U6Z3JheSIgZD0iTTEzIDZWMi41Ii8+PHBhdGggY2xhc3M9ImNscy02IiBkPSJNMTIuNSA4LjA2VjEwTTEyLjUgMjAuMDR2MS44OE03LjEzIDEwLjA4bDEuNzkgMS44OE0xNi4wNCAxNy4wOGwyIDEuODhNNyAxOC45MmwxLjg4LTEuODhNMTYuMTMgMTEuOTZsMS43OS0xLjgzIi8+PGVsbGlwc2UgY3g9IjEyLjUiIGN5PSIxNC4zNiIgcng9IjEuNSIgcnk9IjEuMzYiIHN0eWxlPSJmaWxsOmdyYXkiLz48cGF0aCBjbGFzcz0iY2xzLTYiIGQ9Im0xMi42MyAxNC41NCAyLjUgNi4zOCIvPjwvZz48L3N2Zz4=)}.scylla-icon--mail-list{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSJjdXJyZW50Q29sb3IiIHN0cm9rZS13aWR0aD0iMS41IiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiIGNsYXNzPSJmZWF0aGVyIGZlYXRoZXItbWFpbCI+PHBhdGggZD0iTTQgNGgxNmMxLjEgMCAyIC45IDIgMnYxMmMwIDEuMS0uOSAyLTIgMkg0Yy0xLjEgMC0yLS45LTItMlY2YzAtMS4xLjktMiAyLTJ6Ii8+PHBhdGggZD0ibTIyIDYtMTAgN0wyIDYiLz48L3N2Zz4=)}.scylla-icon--manager{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtM3tmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kO3N0cm9rZS13aWR0aDouOTdweH0uY2xzLTR7ZmlsbDpncmF5fTwvc3R5bGU+PC9kZWZzPjxwYXRoIHN0eWxlPSJmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kIiBkPSJNMTggMmg1djIySDNWMmg0LjkyIiBpZD0iQ2FscXVlXzIiIGRhdGEtbmFtZT0iQ2FscXVlIDIiLz48ZyBpZD0iQ2FscXVlXzQiIGRhdGEtbmFtZT0iQ2FscXVlIDQiPjxwYXRoIHN0eWxlPSJzdHJva2Utd2lkdGg6MS4wN3B4O2ZpbGw6bm9uZTtzdHJva2U6Z3JheTtzdHJva2UtbGluZWNhcDpyb3VuZDtzdHJva2UtbGluZWpvaW46cm91bmQiIGQ9Ik04IDBoMTB2NEg4eiIvPjxwYXRoIGNsYXNzPSJjbHMtMyIgZD0iTTcgOWgzdjNIN3pNNyAxNmgzdjNIN3oiLz48cGF0aCBjbGFzcz0iY2xzLTQiIGQ9Ik0xMi41IDkuNWg3djJoLTd6TTEyLjUgMTYuNWg3djJoLTd6Ii8+PC9nPjwvc3ZnPg==)}.scylla-icon--memory-management{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMSwuY2xzLTJ7ZmlsbDpub25lO3N0cm9rZTpncmF5O3N0cm9rZS1saW5lY2FwOnJvdW5kO3N0cm9rZS1saW5lam9pbjpyb3VuZH0uY2xzLTJ7c3Ryb2tlLXdpZHRoOjEuMTNweH08L3N0eWxlPjwvZGVmcz48ZyBpZD0iQ2FscXVlXzQiIGRhdGEtbmFtZT0iQ2FscXVlIDQiPjxyZWN0IGNsYXNzPSJjbHMtMSIgeD0iNS41IiB5PSI1LjUiIHdpZHRoPSIxNSIgaGVpZ2h0PSIxNSIgcng9IjIuNzQiIHJ5PSIyLjc0Ii8+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNOS41IDkuNWg3djdoLTd6Ii8+PHBhdGggY2xhc3M9ImNscy0yIiBkPSJNOC41IDUuNXYtNE0xMS41IDUuNXYtNE0xNC41IDUuNXYtNE0xNy41IDUuNXYtNE04LjUgMjQuNXYtNE0xMS41IDI0LjV2LTRNMTQuNSAyNC41di00TTE3LjUgMjQuNXYtNE0yMC41IDguNWg0TTIwLjUgMTEuNWg0TTIwLjUgMTQuNWg0TTIwLjUgMTcuNWg0TTEuNSA4LjVoNE0xLjUgMTEuNWg0TTEuNSAxNC41aDRNMS41IDE3LjVoNCIvPjwvZz48L3N2Zz4=)}.scylla-icon--monitoring{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGcgZGF0YS1uYW1lPSJDYWxxdWUgNCI+PHBhdGggZD0iTTUuNTUgMTAuODlhMy44MyAzLjgzIDAgMCAxLS4xNS0zLjc2IiBzdHlsZT0ic3Ryb2tlLWxpbmVqb2luOnJvdW5kO3N0cm9rZS1saW5lY2FwOnJvdW5kO3N0cm9rZTpncmF5O2ZpbGw6bm9uZSIvPjxyZWN0IHg9IjE3LjYzIiB5PSIxNC4wMSIgd2lkdGg9IjMuMDUiIGhlaWdodD0iMTAuOCIgcng9Ii41NyIgcnk9Ii41NyIgdHJhbnNmb3JtPSJyb3RhdGUoLTQ1IDE5LjE1OCAxOS40MDUpIiBzdHlsZT0ic3Ryb2tlLW1pdGVybGltaXQ6MTA7ZmlsbDpncmF5O3N0cm9rZS13aWR0aDouOTVweDtzdHJva2U6Z3JheSIvPjxjaXJjbGUgY3g9IjguNSIgY3k9IjkiIHI9IjciIHN0eWxlPSJzdHJva2Utd2lkdGg6MnB4O3N0cm9rZS1taXRlcmxpbWl0OjEwO3N0cm9rZTpncmF5O2ZpbGw6bm9uZSIvPjxwYXRoIHN0eWxlPSJzdHJva2UtbWl0ZXJsaW1pdDoxMDtzdHJva2UtbGluZWNhcDpyb3VuZDtzdHJva2U6Z3JheTtmaWxsOm5vbmUiIGQ9Im0xNi4wNSAxNi4zOS0yLjI4LTIuMjgiLz48L2c+PC9zdmc+)}.scylla-icon--networking{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMntmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLW1pdGVybGltaXQ6MTB9PC9zdHlsZT48L2RlZnM+PGcgaWQ9IkNhbHF1ZV80IiBkYXRhLW5hbWU9IkNhbHF1ZSA0Ij48Y2lyY2xlIGN4PSIxMi41IiBjeT0iMTIuNSIgcj0iNCIgc3R5bGU9InN0cm9rZS13aWR0aDouOTRweDtmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLW1pdGVybGltaXQ6MTAiLz48Y2lyY2xlIGNsYXNzPSJjbHMtMiIgY3g9IjUiIGN5PSIzIiByPSIyLjUiLz48Y2lyY2xlIGNsYXNzPSJjbHMtMiIgY3g9IjE5IiBjeT0iMjAiIHI9IjIuNSIvPjxjaXJjbGUgY2xhc3M9ImNscy0yIiBjeD0iMjIiIGN5PSI2LjYiIHI9IjIuNSIvPjxjaXJjbGUgY2xhc3M9ImNscy0yIiBjeD0iNC41IiBjeT0iMjIiIHI9IjIuNSIvPjxwYXRoIGNsYXNzPSJjbHMtMiIgZD0ibTYuODMgNS41IDMuMjUgNC4zM00yMC4yMyA3Ljg1IDE1LjMzIDExTTkuODMgMTUuMDhsLTQuMDkgNS44NE0xNC41OCAxNS4zM2wzIDMuMDkiLz48Y2lyY2xlIGN4PSIxMi41IiBjeT0iMTIuNSIgcj0iMS41IiBzdHlsZT0iZmlsbDpncmF5Ii8+PC9nPjwvc3ZnPg==)}.scylla-icon--news{background-image:url(data:image/svg+xml;base64,PHN2ZyBpZD0iQ2FscXVlXzEiIGRhdGEtbmFtZT0iQ2FscXVlIDEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmlld0JveD0iMCAwIDI1IDI1Ij48ZGVmcz48c3R5bGU+LmNscy0xe2ZpbGw6bm9uZTtzdHJva2U6Z3JheTtzdHJva2UtbGluZWNhcDpyb3VuZDtzdHJva2UtbGluZWpvaW46cm91bmR9PC9zdHlsZT48L2RlZnM+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNMyAxNS4xNyAxNi4zMSAzLjgyYTEuNDggMS40OCAwIDAgMSAyLjIyLjQ2bDUuMTUgOS42NWExLjQ2IDEuNDYgMCAwIDEtLjkzIDIuMTJMNS42OSAxOS45Wk04LjcxIDE5LjMzbC43NiAyLjIyYTEuNTEgMS41MSAwIDAgMCAxLjg1IDFsMy41OC0xLjA2YTEuNSAxLjUgMCAwIDAgMS0xLjg2TDE1LjQ1IDE4TTUuNTQgMjBsLTEuODMgMWEuOTIuOTIgMCAwIDEtMS4yNS0uMzdMLjYxIDE3LjQ5QS45Mi45MiAwIDAgMSAxIDE2LjI0bDEuODMtMU04LjUgMTRsNy4zOC01LjUiLz48L3N2Zz4=)}.scylla-icon--newsletter{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMSwuY2xzLTJ7ZmlsbDpub25lO3N0cm9rZTpncmF5O3N0cm9rZS1taXRlcmxpbWl0OjEwfS5jbHMtMntzdHJva2UtbGluZWNhcDpyb3VuZH08L3N0eWxlPjwvZGVmcz48ZyBpZD0iQ2FscXVlXzQiIGRhdGEtbmFtZT0iQ2FscXVlIDQiPjxwYXRoIGNsYXNzPSJjbHMtMSIgZD0iTTE5LjUgOS41aDN2MTJoLTIwdi0xMmgzIi8+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJtMi42NSA5Ljg0IDkuODUgNi44OCA4LjYzLTYuODgiLz48cGF0aCBjbGFzcz0iY2xzLTIiIGQ9Im01LjUgNy41LTMgMk0xNC4zNSAzLjg2bC0xLjQ2LTEuMDktMS40NyAxLjA5TTIxLjUgOS41bC0yLTJNMTkuNSAxMS41di03aC0xNHY3LjQ3Ii8+PC9nPjwvc3ZnPg==)}.scylla-icon--nsql-guides{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGcgZGF0YS1uYW1lPSJDYWxxdWUgNCI+PHJlY3QgeD0iNC4zNyIgeT0iMTMuNzEiIHdpZHRoPSIxLjE1IiBoZWlnaHQ9IjkuNzIiIHJ4PSIuNTQiIHJ5PSIuNTQiIHRyYW5zZm9ybT0icm90YXRlKDQ1IDQuOTQ4IDE4LjU3KSIgc3R5bGU9InN0cm9rZTpncmF5O3N0cm9rZS1taXRlcmxpbWl0OjEwO2ZpbGw6Z3JheTtzdHJva2Utd2lkdGg6MS4wOXB4Ii8+PGNpcmNsZSBjeD0iMTIuMjUiIGN5PSIxMi4yNSIgcj0iNC43NSIgc3R5bGU9InN0cm9rZS13aWR0aDoxLjVweDtmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLW1pdGVybGltaXQ6MTAiLz48cGF0aCBzdHlsZT0ic3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLXdpZHRoOjEuMDZweDtmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLW1pdGVybGltaXQ6MTAiIGQ9Ik04LjUgMjAuNXYzaDE1di0yMWgtMTV2MiIvPjwvZz48L3N2Zz4=)}.scylla-icon--open-source{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfS5jbHMtMntmaWxsOmdyYXl9PC9zdHlsZT48L2RlZnM+PGcgaWQ9IkNhbHF1ZV80IiBkYXRhLW5hbWU9IkNhbHF1ZSA0Ij48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Ik0uMzEgMjEuNTEgNSAxOS42OWEyLjM3IDIuMzcgMCAwIDEgMS44OC4xOWw1LjI0IDEuNjhhMi4yMyAyLjIzIDAgMCAwIDItLjEybDkuNS00Ljc1Yy44LS40NCAxLjY0LTEuMzEgMS4xMy0xLjkxYTIuMzQgMi4zNCAwIDAgMC0yLjY0LS40MkwxOCAxNi4wOSIvPjxwYXRoIGNsYXNzPSJjbHMtMSIgZD0ibS4yNSAxNS42OSA0Ljg4LTEuMjFjMS4yNS0uMyAyLjE3LS42MyAzLjQ0LS4xM2ExNS4yMSAxNS4yMSAwIDAgMCA0IDEuMWg0LjUyYy44NSAwIC45NS41NC45NSAxLjEzYTEgMSAwIDAgMS0xLjA4IDEgNjUuODYgNjUuODYgMCAwIDEtNy0uMzEiLz48cGF0aCBjbGFzcz0iY2xzLTIiIGQ9Ik04LjU2IDkuNjh2LS44MWMwLS45MS0uMzgtMS4yMS0xLjI5LTEuMjFIN1Y2LjNoLjMxYy45MSAwIDEuMjktLjMgMS4yOS0xLjIxdi0uODFjMC0xLjIuNjYtMS45MiAyLjgyLTIuM3YxLjE2Yy0xLjI0LjM1LTEuNDMuNjgtMS40MyAxLjR2Ljg3QTEuNTIgMS41MiAwIDAgMSA4Ljc1IDcgMS41MiAxLjUyIDAgMCAxIDEwIDguNTZ2Ljg3YzAgLjcxLjE5IDEgMS40MyAxLjRWMTJjLTIuMjEtLjM1LTIuODctMS4xMi0yLjg3LTIuMzJaTTE3LjQzIDQuM3YuODFjMCAuOTEuMzcgMS4yMSAxLjI5IDEuMjFIMTl2MS4zNmgtLjMxYy0uOTIgMC0xLjI5LjMtMS4yOSAxLjIxdi44MWMwIDEuMi0uNjUgMi0yLjgxIDIuMzV2LTEuMmMxLjI1LS4zNiAxLjQ0LS42OSAxLjQ0LTEuNHYtLjg3QTEuNTMgMS41MyAwIDAgMSAxNy4yNSA3IDEuNTMgMS41MyAwIDAgMSAxNiA1LjQzdi0uODdjMC0uNzItLjE5LTEtMS40NC0xLjRWMmMyLjIyLjM4IDIuODcgMS4xIDIuODcgMi4zWiIvPjwvZz48L3N2Zz4=)}.scylla-icon--operator{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjQuODEgMS4wMSAyOC4zMiAyNy42NCI+PHBhdGggZD0iTTMyLjUyIDE4cy0uMDkgMC0uMDktLjA1LS4wOCAwLS4xNyAwYTIuMTkgMi4xOSAwIDAgMC0uNTEgMCAuNDcuNDcgMCAwIDEtLjI2LS4wNSA5LjI5IDkuMjkgMCAwIDEtMS40OS0uMzIuNTQuNTQgMCAwIDEtLjMtLjMxbC0uMzQtLjA4YTExLjI1IDExLjI1IDAgMCAwLS4xOC0zLjc5IDExLjU1IDExLjU1IDAgMCAwLTEuNS0zLjUybC4yNi0uMjZhLjU5LjU5IDAgMCAxIC4xMy0uMzkgNy43MyA3LjczIDAgMCAxIDEuMi0uODZsLjI2LS4xMy40Ny0uM3MuMDkgMCAuMTMtLjA4IDAtLjA1IDAtLjA5YS44NC44NCAwIDAgMCAuMTctMS4yLjc4Ljc4IDAgMCAwLS42LS4zIDEgMSAwIDAgMC0uNi4yMWMtLjA1LjA1LS4wOS4wOS0uMTMuMDlhMy4wOCAzLjA4IDAgMCAwLS4zNS4zOWMwIC4wOC0uMTMuMTMtLjE3LjE3YTUuNjQgNS42NCAwIDAgMS0xLjA3Ljk0LjU4LjU4IDAgMCAxLS4yNi4wOS4yNS4yNSAwIDAgMS0uMTcgMGgtLjA1bC0uMzQuMjEtMS4wOC0xYTExIDExIDAgMCAwLTUuNjUtMi4yN3YtLjM0YS42LjYgMCAwIDEtLjIyLS4zNEE4LjE4IDguMTggMCAwIDEgMTkuNjYgM3YtLjI1YzAtLjA4LjA1LS4zNS4wOS0uNTJ2LS4zMWEuODIuODIgMCAwIDAtMS40Ni0uNi44Ni44NiAwIDAgMC0uMjYuNnYuMjJhMS44MiAxLjgyIDAgMCAwIC4wOS41MS41OS41OSAwIDAgMSAwIC4yNlYzYTguODIgOC44MiAwIDAgMSAuMDggMS40Ny41OS41OSAwIDAgMS0uMjEuMzRWNS4yNGMtLjQ4IDAtMSAuMTMtMS40Ny4yMmExMC4xNiAxMC4xNiAwIDAgMC01LjI4IDNMMTEgOC4yNGgtLjE3YS43My43MyAwIDAgMS0uMjYtLjA5IDcuOCA3LjggMCAwIDEtMS4wNy0xYzAtLjA4LS4xMy0uMTMtLjE3LS4xN3MtLjI1LS4yLS4zMy0uMzMtLjA4IDAtLjEzLS4wOHYtLjA1YTEgMSAwIDAgMC0uNi0uMjEuNjQuNjQgMCAwIDAtLjYuMy45MS45MSAwIDAgMCAuMTcgMS4yczAgLjA1IDAgLjA1LjA5LjA4LjEzLjA4YTUgNSAwIDAgMCAuNDcuMjZsLjI2LjEzYTYuNjEgNi42MSAwIDAgMSAxLjIxLjg2LjQ3LjQ3IDAgMCAxIC4xMy4zOXYtLjA1bC4yNS4yNmEyLjUzIDIuNTMgMCAwIDEtLjEzLjIyIDEwLjIgMTAuMiAwIDAgMC0xLjUgN2wtLjM1LjA5YzAgLjEzLS4xNy4yMS0uMy4zYTguNTYgOC41NiAwIDAgMS0xLjQ2LjI2LjU5LjU5IDAgMCAwLS4yNiAwaC0uNTJjLS4xOCAwLS4wOC4wNS0uMTcuMDVoLS4wOGEuODQuODQgMCAwIDAtLjY5IDEgLjc5Ljc5IDAgMCAwIC44Ni42LjM5LjM5IDAgMCAwIC4yMSAwSDYuMTJhMy42MSAzLjYxIDAgMCAwIC40Ny0uMTcuNjUuNjUgMCAwIDEgLjI2LS4wOCA3LjY1IDcuNjUgMCAwIDEgMS40Mi0uMzkuNDkuNDkgMCAwIDEgLjM1LjEzaC4zOWExMC4zMiAxMC4zMiAwIDAgMCAzLjUzIDUgNi4zMSA2LjMxIDAgMCAwIDEuMTYuNzdsLS4yMi4zYS41MS41MSAwIDAgMSAwIC40MyA2LjU0IDYuNTQgMCAwIDEtLjY5IDEuMjR2LjA1YS43OC43OCAwIDAgMS0uMTcuMjFjLS4wOS4wOS0uMTcuMjYtLjMuNDNzMCAuMDktLjA5LjEzIDAgLjA1IDAgLjA1YS44OC44OCAwIDAgMCAuMzQgMS4xNi45LjkgMCAwIDAgLjMuMDggMSAxIDAgMCAwIC44Mi0uNTFzMC0uMDguMDktLjEzLjEzLS4zLjE3LS40N2wuMDktLjI2YTcuMDcgNy4wNyAwIDAgMSAuNTYtMS4zMy42Mi42MiAwIDAgMSAuMzQtLjI2bC4xNy0uMzVhMTAuMDUgMTAuMDUgMCAwIDAgMy43NS42OSA4LjQ1IDguNDUgMCAwIDAgMi4zMi0uMyAxMS40NiAxMS40NiAwIDAgMCAxLjM3LS4zOWwuMTguMzFhLjYyLjYyIDAgMCAxIC4zNC4yNiA3LjA3IDcuMDcgMCAwIDEgLjU2IDEuMzNsLjA5LjI2YTEuMzEgMS4zMSAwIDAgMCAuMTcuNDdjMCAuMDUgMCAuMDkuMDkuMTNhMSAxIDAgMCAwIC44Mi41MSAxLjA1IDEuMDUgMCAwIDAgLjM0LS4wOC43Ni43NiAwIDAgMCAuMzktLjQ4IDEuMDggMS4wOCAwIDAgMC0uMDUtLjY0LjIuMiAwIDAgMC0uMDgtLjEzIDEuNTMgMS41MyAwIDAgMC0uMzEtLjQzLjY1LjY1IDAgMCAwLS4xNy0uMjJ2LS4wOWE1LjIyIDUuMjIgMCAwIDEtLjY5LTEuMjQuNTEuNTEgMCAwIDEgLjA1LS40M2wtLjEzLS4zNEExMC42OCAxMC42OCAwIDAgMCAyOSAxOC44MmwuMzQuMDV2LS4wNWEuNTQuNTQgMCAwIDEgLjM1LS4xMyA3LjgyIDcuODIgMCAwIDEgMS4zOC4zOS42Mi42MiAwIDAgMCAuMjYuMDkgMi40MiAyLjQyIDAgMCAwIC40Ny4yMXMuMDkgMCAuMTcgMGguMDlhLjM5LjM5IDAgMCAwIC4yMSAwIC45NC45NCAwIDAgMCAuODYtLjYgMSAxIDAgMCAwLS43Ny0uOVptLTEyLjQzLTEuMzMtMS4xNi41Ni0xLjE2LS41Ni0uMy0xLjI1LjgxLTFoMS4yOWwuODIgMVptNy0yLjc5YTggOCAwIDAgMSAuMTcgMi43MWwtNC4xNS0uNzVjLS4zOC0uMDgtLjY4LS45LS43MS0xLjIyYTQgNCAwIDAgMSAuMjEtLjc0bDMuNDUtMi41NGE4LjU4IDguNTggMCAwIDEgMS4wNCAyLjU0Wm0tMi4zMS00LjEzLTMuMjIgMi42OWExLjI4IDEuMjggMCAwIDEtMS4yNS0uMzdjLS4wOS0uMDktLjM3LS4yNS0uMzctLjM4VjcuNDNhOC4wNyA4LjA3IDAgMCAxIDQuODYgMi4zMlpNMTcgNy41NmwxLS4xOC0uMDYgNC4zMWMwIC4zOC0uNjQuNjgtMSAuNjhhMS4xMSAxLjExIDAgMCAxLS4zNS0uMDhMMTMgOS43NWE4LjQxIDguNDEgMCAwIDEgNC0yLjE5Wm0tNS4yNCAzLjc4IDMuMzcgMi40Ny4zMi41M2ExLjE0IDEuMTQgMCAwIDEtLjI1IDEgLjc4Ljc4IDAgMCAxLS4zOC4zMWwtNC4zMS45YTkgOSAwIDAgMSAxLjI0LTUuMjFaTTExIDE4LjYxbDQuMS0xLjIzYy4zNSAwIC44NC43MS44OSAxLjA2YS41MS41MSAwIDAgMS0uMDUuNDNsLTEuNjMgMy45NUE4LjQxIDguNDEgMCAwIDEgMTEgMTguNjFabTkuNzYgNS4zM2E4LjY3IDguNjcgMCAwIDEtMS44NS4yMSA5LjU5IDkuNTkgMCAwIDEtMi43MS0uNDNsMS42Ni00Yy4yMS0uMjYgMS0uMiAxLjMxIDBhMi40OCAyLjQ4IDAgMCAxIC4zNC4zbDIuMDcgMy43NGE1LjcyIDUuNzIgMCAwIDAtLjguMThaTTI2IDIwLjJhOC4zNiA4LjM2IDAgMCAxLTIuNTggMi41OGwtMS45Mi0zLjcyYTEuMTUgMS4xNSAwIDAgMSAuNDEtMWMuMjEtLjI1LjU5LS41OS43MS0uNTlsNC4yMiAxLjA2QTYuMjcgNi4yNyAwIDAgMSAyNiAyMC4yWiIgc3R5bGU9ImZpbGw6IzRkNGQ0ZCIgZGF0YS1uYW1lPSJDYWxxdWUgMiIvPjwvc3ZnPg==)}.scylla-icon--overview{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJDYWxxdWVfNCIgZGF0YS1uYW1lPSJDYWxxdWUgNCI+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNMjIuNjEgMy40NUMyMi42MSA1LjA2IDE4IDYuNSAxMi41IDYuNXMtMTAtMS40NC0xMC0zIDQuNS0zIDEwLTMgMTAuMTEgMS4zMyAxMC4xMSAyLjk1Wk0yMi42MSA5LjQ0YzAgMS42MS00LjY0IDMuMDYtMTAuMTEgMy4wNnMtMTAtMS40NS0xMC0zLjA2TTIyLjYxIDE1LjUxYzAgMS42Mi00LjY0IDMtMTAuMTEgM3MtMTAtMS4zNy0xMC0zTTIyLjYxIDIxLjU5YzAgMS42Mi00LjY0IDIuOTEtMTAuMTEgMi45MXMtMTAtMS4yOS0xMC0yLjkxTTIuNSAyMS40N1YzLjQ1TTIyLjUgMjEuNDdWMy40NSIvPjwvZz48L3N2Zz4=)}.scylla-icon--partners{background-image:url(data:image/svg+xml;base64,PHN2ZyBpZD0iQ2FscXVlXzEiIGRhdGEtbmFtZT0iQ2FscXVlIDEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmlld0JveD0iMCAwIDI1IDI1Ij48ZGVmcz48c3R5bGU+LmNscy0xe2ZpbGw6bm9uZTtzdHJva2U6Z3JheTtzdHJva2UtbGluZWNhcDpyb3VuZDtzdHJva2UtbGluZWpvaW46cm91bmR9PC9zdHlsZT48L2RlZnM+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNMTguNSA4LjI2aC00LjcybC0xLjIzIDEuMjdNMi4zOSAxNS4wOS4xNSAxMy43NGw0Ljg3LTguNDIgMi4yNCAxLjM0LTQuODcgOC40M3pNMjIuNTkgMTUuMDlsMi4yNC0xLjM1LTQuODYtOC40Mi0yLjI0IDEuMzQgNC44NiA4LjQzek0xMC43MSAxNS4yNmwtMi45MyAyLjIxTTEyLjE4IDE2LjRsLTIuOTMgMi4yMU0xMy42OCAxNy41M2wtMi45MyAyLjIyIi8+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNNi4zOCA4LjNoMy43OGEyLjI3IDIuMjcgMCAwIDEgMS4zNy40N2MxLjI2IDEgNC4wOSAzLjE4IDQuNDggMy41NnMtMS4xNCAxLjY4LTIuMjcgMS4xYTE4LjM0IDE4LjM0IDAgMCAwLTIuMTEtLjkyLjU3LjU3IDAgMCAwLS41Ni4wOWwtNC43OSAzLjg5TDEyLjMzIDIxbDkuNDYtNy4wOU0zLjI0IDE0LjIybDMuNCAxLjg1Ii8+PC9zdmc+)}.scylla-icon--plus{background-image:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTciIGhlaWdodD0iMTciIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHJlY3Qgd2lkdGg9IjE3IiBoZWlnaHQ9IjE3IiByeD0iMSIgZmlsbD0iI0IzQkFDNSIvPjxwYXRoIGZpbGwtcnVsZT0iZXZlbm9kZCIgY2xpcC1ydWxlPSJldmVub2RkIiBkPSJNOS41IDVhMSAxIDAgMSAwLTIgMHYyLjVINWExIDEgMCAxIDAgMCAyaDIuNVYxMmExIDEgMCAxIDAgMiAwVjkuNUgxMmExIDEgMCAxIDAgMC0ySDkuNVY1WiIgZmlsbD0iI2ZmZiIvPjxwYXRoIGZpbGwtcnVsZT0iZXZlbm9kZCIgY2xpcC1ydWxlPSJldmVub2RkIiBkPSJNOS41IDVhMSAxIDAgMSAwLTIgMHYyLjVINWExIDEgMCAxIDAgMCAyaDIuNVYxMmExIDEgMCAxIDAgMiAwVjkuNUgxMmExIDEgMCAxIDAgMC0ySDkuNVY1WiIgZmlsbD0iI2ZmZiIvPjxwYXRoIGZpbGwtcnVsZT0iZXZlbm9kZCIgY2xpcC1ydWxlPSJldmVub2RkIiBkPSJNOS41IDVhMSAxIDAgMSAwLTIgMHYyLjVINWExIDEgMCAxIDAgMCAyaDIuNVYxMmExIDEgMCAxIDAgMiAwVjkuNUgxMmExIDEgMCAxIDAgMC0ySDkuNVY1WiIgZmlsbD0iI2ZmZiIvPjxwYXRoIGZpbGwtcnVsZT0iZXZlbm9kZCIgY2xpcC1ydWxlPSJldmVub2RkIiBkPSJNOS41IDVhMSAxIDAgMSAwLTIgMHYyLjVINWExIDEgMCAxIDAgMCAyaDIuNVYxMmExIDEgMCAxIDAgMiAwVjkuNUgxMmExIDEgMCAxIDAgMC0ySDkuNVY1WiIgZmlsbD0iI2ZmZiIvPjxwYXRoIGZpbGwtcnVsZT0iZXZlbm9kZCIgY2xpcC1ydWxlPSJldmVub2RkIiBkPSJNOS41IDVhMSAxIDAgMSAwLTIgMHYyLjVINWExIDEgMCAxIDAgMCAyaDIuNVYxMmExIDEgMCAxIDAgMiAwVjkuNUgxMmExIDEgMCAxIDAgMC0ySDkuNVY1WiIgZmlsbD0iI2ZmZiIvPjwvc3ZnPg==);filter:none}.scylla-icon--pricing{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJDYWxxdWVfMiIgZGF0YS1uYW1lPSJDYWxxdWUgMiI+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJtMjEuNzMgNy0yLjQxLTUuMTJhMi41MiAyLjUyIDAgMCAwLTIuODItMWwtNi4wOCAyLjA0QTEuNjkgMS42OSAwIDAgMCA5LjUxIDRMMy45MyAxOS4yOWExLjA2IDEuMDYgMCAwIDAgLjY0IDEuMTdsMTAuMzQgMy43NmExIDEgMCAwIDAgMS4yMi0uNDNsNS41OC0xNS4zM0ExLjg3IDEuODcgMCAwIDAgMjEuNzMgN1oiLz48Y2lyY2xlIGNsYXNzPSJjbHMtMSIgY3g9IjE1LjczIiBjeT0iNS44OSIgcj0iMiIvPjx0ZXh0IHRyYW5zZm9ybT0icm90YXRlKDIwIC00OC4yNDQgMzAuNjcpIiBzdHlsZT0iZm9udC1zaXplOjEycHg7ZmlsbDpncmF5O2ZvbnQtZmFtaWx5OlJvYm90by1NZWRpdW0sUm9ib3RvIj4kPC90ZXh0PjwvZz48L3N2Zz4=)}.scylla-icon--release-note{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMntmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kO3N0cm9rZS13aWR0aDouOTFweH08L3N0eWxlPjwvZGVmcz48ZyBpZD0iQ2FscXVlXzIiIGRhdGEtbmFtZT0iQ2FscXVlIDIiPjxwYXRoIHN0eWxlPSJzdHJva2Utd2lkdGg6LjlweDtmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kIiBkPSJNMjEuNSAyNC41aC0xN1Y1LjdMOC45NS41NCAyMS41LjV2MjR6Ii8+PHBhdGggY2xhc3M9ImNscy0yIiBkPSJNNC42NSA1LjVIOS41VjFNNy41IDguNWgxMU03LjUgMTEuNWgxMU03LjUgMTQuNWgxMU03LjUgMTcuNWgxMU03LjUgMjAuNWgxMSIvPjwvZz48L3N2Zz4=)}.scylla-icon--resource-center{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfS5jbHMtMntmaWxsOmdyYXl9PC9zdHlsZT48L2RlZnM+PGcgaWQ9IkNhbHF1ZV80IiBkYXRhLW5hbWU9IkNhbHF1ZSA0Ij48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Ik01LjUgMi41aDYuOTFsLjA5IDIwaC03di0yMHoiLz48cGF0aCBjbGFzcz0iY2xzLTIiIGQ9Ik04IDRoMnYxMC45N0w4IDE1VjR6Ii8+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNNS4zNiAyLjI5IDIuNSAzLjV2MThsMi43OSAxLjE0Ii8+PHBhdGggc3R5bGU9InN0cm9rZS13aWR0aDouNjhweDtmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kIiBkPSJtMTIuNTcgMjEuODYgMS41Ny43NSIvPjxwYXRoIHN0eWxlPSJzdHJva2Utd2lkdGg6Ljg1cHg7ZmlsbDpub25lO3N0cm9rZTpncmF5O3N0cm9rZS1saW5lY2FwOnJvdW5kO3N0cm9rZS1saW5lam9pbjpyb3VuZCIgZD0ibTE0LjExIDIuNS0xLjU0LjU3Ii8+PGNpcmNsZSBjbGFzcz0iY2xzLTIiIGN4PSI5IiBjeT0iMTkiIHI9IjEiLz48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Ik0xNC41IDIuNWg2Ljk0bC4wNiAyMGgtN3YtMjB6Ii8+PHBhdGggY2xhc3M9ImNscy0yIiBkPSJNMTcgNGgydjEwLjk3TDE3IDE1VjR6Ii8+PGNpcmNsZSBjbGFzcz0iY2xzLTIiIGN4PSIxOCIgY3k9IjE5IiByPSIxIi8+PHBhdGggY2xhc3M9ImNscy0yIiBkPSJNMTIuNiAyLjczaDEuNjdWMjIuNkgxMi42ek0yLjU4IDIxLjVsMi43NSAxLjFWMi43M2wtMi42Ni45NC0uMDkgMTcuODN6Ii8+PC9nPjwvc3ZnPg==)}.scylla-icon--roadmap{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMSwuY2xzLTJ7ZmlsbDpub25lO3N0cm9rZTpncmF5fS5jbHMtMXtzdHJva2UtbGluZWNhcDpyb3VuZDtzdHJva2UtbGluZWpvaW46cm91bmQ7c3Ryb2tlLXdpZHRoOi45OHB4fS5jbHMtMntzdHJva2UtbWl0ZXJsaW1pdDoxMH0uY2xzLTN7ZmlsbDpncmF5fTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJDYWxxdWVfNCIgZGF0YS1uYW1lPSJDYWxxdWUgNCI+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJtLjUgNC41IDgtMyA4IDQgOC0zdjE3bC04IDMtOC00LTggM3YtMTd6TTguNSAxLjVWMThNMTYuNSA1LjVWMjIiLz48cGF0aCBjbGFzcz0iY2xzLTIiIGQ9Ik0yLjUgMTMgNyAxNi41TTcgMTJsLTQuNSA1LjVNMTguNSA4bDQuNSAzLjVNMjMgN2wtNC41IDUuNSIvPjxwYXRoIGNsYXNzPSJjbHMtMyIgZD0iTTEwIDEzaDF2MWgtMXpNMTIgMTJoMXYxaC0xek0xNCAxMWgxdjFoLTF6Ii8+PC9nPjwvc3ZnPg==)}.scylla-icon--search{background-image:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZD0iTTEwLjUgMThhNy41IDcuNSAwIDEgMCAwLTE1IDcuNSA3LjUgMCAwIDAgMCAxNVpNMjEgMjFsLTUuMi01LjIiIHN0cm9rZT0iIzAwMCIgc3Ryb2tlLXdpZHRoPSIyIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiLz48L3N2Zz4=)}.scylla-icon--slack{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0NDggNTEyIj48IS0tISBGb250IEF3ZXNvbWUgUHJvIDYuMC4wIGJ5IEBmb250YXdlc29tZSAtIGh0dHBzOi8vZm9udGF3ZXNvbWUuY29tIExpY2Vuc2UgLSBodHRwczovL2ZvbnRhd2Vzb21lLmNvbS9saWNlbnNlIChDb21tZXJjaWFsIExpY2Vuc2UpIENvcHlyaWdodCAyMDIyIEZvbnRpY29ucywgSW5jLi0tPjxwYXRoIGQ9Ik05NC4xMiAzMTUuMWMwIDI1LjktMjEuMTYgNDcuMDYtNDcuMDYgNDcuMDZTMCAzNDEgMCAzMTUuMWMwLTI1LjkgMjEuMTYtNDcuMDYgNDcuMDYtNDcuMDZoNDcuMDZ2NDcuMDZ6bTIzLjcyIDBjMC0yNS45IDIxLjE2LTQ3LjA2IDQ3LjA2LTQ3LjA2czQ3LjA2IDIxLjE2IDQ3LjA2IDQ3LjA2djExNy44NGMwIDI1LjktMjEuMTYgNDcuMDYtNDcuMDYgNDcuMDZzLTQ3LjA2LTIxLjE2LTQ3LjA2LTQ3LjA2VjMxNS4xem00Ny4wNi0xODguOThjLTI1LjkgMC00Ny4wNi0yMS4xNi00Ny4wNi00Ny4wNlMxMzkgMzIgMTY0LjkgMzJzNDcuMDYgMjEuMTYgNDcuMDYgNDcuMDZ2NDcuMDZIMTY0Ljl6bTAgMjMuNzJjMjUuOSAwIDQ3LjA2IDIxLjE2IDQ3LjA2IDQ3LjA2cy0yMS4xNiA0Ny4wNi00Ny4wNiA0Ny4wNkg0Ny4wNkMyMS4xNiAyNDMuOTYgMCAyMjIuOCAwIDE5Ni45czIxLjE2LTQ3LjA2IDQ3LjA2LTQ3LjA2SDE2NC45em0xODguOTggNDcuMDZjMC0yNS45IDIxLjE2LTQ3LjA2IDQ3LjA2LTQ3LjA2IDI1LjkgMCA0Ny4wNiAyMS4xNiA0Ny4wNiA0Ny4wNnMtMjEuMTYgNDcuMDYtNDcuMDYgNDcuMDZoLTQ3LjA2VjE5Ni45em0tMjMuNzIgMGMwIDI1LjktMjEuMTYgNDcuMDYtNDcuMDYgNDcuMDYtMjUuOSAwLTQ3LjA2LTIxLjE2LTQ3LjA2LTQ3LjA2Vjc5LjA2YzAtMjUuOSAyMS4xNi00Ny4wNiA0Ny4wNi00Ny4wNiAyNS45IDAgNDcuMDYgMjEuMTYgNDcuMDYgNDcuMDZWMTk2Ljl6TTI4My4xIDM4NS44OGMyNS45IDAgNDcuMDYgMjEuMTYgNDcuMDYgNDcuMDYgMCAyNS45LTIxLjE2IDQ3LjA2LTQ3LjA2IDQ3LjA2LTI1LjkgMC00Ny4wNi0yMS4xNi00Ny4wNi00Ny4wNnYtNDcuMDZoNDcuMDZ6bTAtMjMuNzJjLTI1LjkgMC00Ny4wNi0yMS4xNi00Ny4wNi00Ny4wNiAwLTI1LjkgMjEuMTYtNDcuMDYgNDcuMDYtNDcuMDZoMTE3Ljg0YzI1LjkgMCA0Ny4wNiAyMS4xNiA0Ny4wNiA0Ny4wNiAwIDI1LjktMjEuMTYgNDcuMDYtNDcuMDYgNDcuMDZIMjgzLjF6Ii8+PC9zdmc+)}.scylla-icon--stack-overflow{background-image:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjQiIGhlaWdodD0iMzEiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Im0yMS45NDkuMTEzIDIuMDQzIDExLjY3LTIuNTE0LjQzMkwxOS40MzUuNTQ1IDIxLjk1LjExNFptLTE3Ljk3MyAyNiAxMS45NDUtLjAwNS0uMDAyLTIuNTMtMTEuOTQ0LjAwNi4wMDEgMi41M1ptMTIuMjMyLTUuNzc3TDQuMzE1IDE5LjI1bC0uMjM1IDIuNTIgMTEuODk0IDEuMDg1LjIzNC0yLjUxOVptLTEwLjc1LTYuMzc1IDExLjUzNSAzLjA3NC0uNjYyIDIuNDQzLTExLjUzNS0zLjA3NS42NjItMi40NDJabTEzLjA0LjE4TDguMjEyIDguMTI2bC0xLjI5NyAyLjE3OCAxMC4yODkgNi4wMTcgMS4yOTYtMi4xNzhabS00LjIwNi0xMS41NiA2LjczIDkuNzg3LTIuMTA4IDEuNDI0LTYuNzMtOS43ODUgMi4xMDgtMS40MjVaIiBmaWxsPSIjMDAwIi8+PHBhdGggZD0iTTE3Ljk1IDE3Ljc4OVYyOC4xM0gyLjI4MlYxNy43ODlILjI0M3YxMi4zMjZIMTkuOThWMTcuNzg5aC0yLjAzWiIgZmlsbD0iIzAwMCIvPjwvc3ZnPg==)}.scylla-icon--summit{background-image:url(data:image/svg+xml;base64,PHN2ZyBpZD0iQ2FscXVlXzEiIGRhdGEtbmFtZT0iQ2FscXVlIDEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmlld0JveD0iMCAwIDI1IDI1Ij48ZGVmcz48c3R5bGU+LmNscy0xe2ZpbGw6bm9uZTtzdHJva2U6IzRkNGQ0ZDtzdHJva2UtbGluZWNhcDpyb3VuZDtzdHJva2UtbGluZWpvaW46cm91bmR9PC9zdHlsZT48L2RlZnM+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJtMTYuNSAyMiAxLTYuNS0xMCAuMDMgMSA2LjQzIi8+PHBhdGggZD0iTTMuNDYgMTJBNS42OSA1LjY5IDAgMCAxIDUgNy41IiBzdHlsZT0ic3Ryb2tlLXdpZHRoOjEuMXB4O3N0cm9rZTojNGQ0ZDRkO3N0cm9rZS1saW5lY2FwOnJvdW5kO3N0cm9rZS1saW5lam9pbjpyb3VuZDtmaWxsOm5vbmUiLz48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Ik0xNC42MiA1YTIuMzMgMi4zMyAwIDAgMS0yLjI1IDIuNWMtMS4zMyAwLTItMS4xMi0xLjk1LTIuNDRzLjctMi41IDItMi40OEEyLjI3IDIuMjcgMCAwIDEgMTQuNjIgNVpNMTcuNTggMTJhMy4yMyAzLjIzIDAgMCAwLTMuNDYtMy41SDExQTMuMjYgMy4yNiAwIDAgMCA3LjUgMTIiLz48Y2lyY2xlIGN4PSI0Ljk0IiBjeT0iNi45NiIgcj0iMS4wMSIgc3R5bGU9ImZpbGw6IzRkNGQ0ZDtzdHJva2Utd2lkdGg6MS4xcHg7c3Ryb2tlOiM0ZDRkNGQ7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kIi8+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNNy41NCAxOC41SDQuNWwtMi02aDIwbC0yIDZoLTMiLz48L3N2Zz4=)}.scylla-icon--support{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJDYWxxdWVfNCIgZGF0YS1uYW1lPSJDYWxxdWUgNCI+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNMTguMTkgNy41YTEwIDEwIDAgMCAxIC4yMSAyLjA3YzAgNC4zNi0yLjYzIDYuOTMtNS45IDYuOTNzLTUuOTQtMi41Ny01Ljk0LTYuOTNhMTAuNTEgMTAuNTEgMCAwIDEgLjIyLTIuMTIiLz48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Ik03LjY3IDIuMjNBNi41OCA2LjU4IDAgMCAxIDEyLjUuNWE1LjY1IDUuNjUgMCAwIDEgNC4yOSAxLjdjMS45MyAxLjk0IDIuMzUgNS4wNyAyLjQzIDYuNzJhMS40OSAxLjQ5IDAgMCAwLS43OS4wNSA4LjY4IDguNjggMCAwIDAtLjA4LTEuMTZoMGE1LjUzIDUuNTMgMCAwIDEtMS43Ny0yLjM0TDE2LjQ5IDVsLS4zOC4yMkExOSAxOSAwIDAgMSA2LjggNy4zOGEuNTIuNTIgMCAwIDAtLjQyLjE2Yy0uMjMuMjQtLjE1LjY1LS4wNyAxLjA4IDAgLjExIDAgLjIyLjA1LjMyYTEuNCAxLjQgMCAwIDAtLjU4IDBjLS4xLTEuNDUtLjA2LTQuNjggMS44OS02LjcxWk02LjM4IDljLS42NS0uMDgtMSAuMS0xLjE0Ljc5YTIuMDYgMi4wNiAwIDAgMCAxLjM3IDIuMjlNMTguNTYgOWMuNjUtLjA4IDEuMDUuMSAxLjE0Ljc5YTIuMDYgMi4wNiAwIDAgMS0xLjM3IDIuMjlNOS41IDE4LjIzVjE1LjVNMTUuNSAxNS41djIuNzNNMi41IDI0LjE2Yy4yNC0yIC41OS0zLjYzIDIuNDMtNC40OWEyNC4yOSAyNC4yOSAwIDAgMSA0LjgyLTEuMzdNMjIuNSAyNC4zM2MtLjI0LTItLjQyLTMuOC0yLjI2LTQuNjZhMjQuMjkgMjQuMjkgMCAwIDAtNC44Mi0xLjM3Ii8+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNMTUuMzkgMTguMzlhNC4zNyA0LjM3IDAgMCAxLTIuOTEgMS4wNyA0LjQyIDQuNDIgMCAwIDEtMi44OS0xLjA1Ii8+PHBhdGggc3R5bGU9ImZpbGw6Z3JheSIgZD0iTTExIDEzaDN2MmgtM3oiLz48cGF0aCBkPSJNMTguMDcgMTJhOS4yMSA5LjIxIDAgMCAxLTUuNTMgMi4wNyIgc3R5bGU9InN0cm9rZS1taXRlcmxpbWl0OjEwO2ZpbGw6bm9uZTtzdHJva2U6Z3JheSIvPjwvZz48L3N2Zz4=)}.scylla-icon--tech-talks{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJDYWxxdWVfNCIgZGF0YS1uYW1lPSJDYWxxdWUgNCI+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNOC4zOSA0LjVIMjMuNXYxM2gtMTUiLz48Y2lyY2xlIGN4PSI0LjUiIGN5PSI2LjUiIHI9IjIiIHN0eWxlPSJzdHJva2UtbWl0ZXJsaW1pdDoxMDtmaWxsOm5vbmU7c3Ryb2tlOmdyYXkiLz48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Ik0xLjUgOS41aDJsLjguODYuNy0uODZoNS41OGExIDEgMCAxIDEgMCAySDYuNXYxMC44OGExIDEgMCAwIDEtMSAxLjEyIDEgMSAwIDAgMS0xLTEgMSAxIDAgMCAxLTEgMSAuOTMuOTMgMCAwIDEtMS0xdi02Yy0uNzggMC0yLS40Ny0yLTF2LTVhMSAxIDAgMCAxIDEtMVoiLz48L2c+PC9zdmc+)}.scylla-icon--testing{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJDYWxxdWVfNCIgZGF0YS1uYW1lPSJDYWxxdWUgNCI+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNNi41IDYuNWgxMnYxMmgtMTJ6Ii8+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNNC41IDQuNWgxNnYxNmgtMTZ6Ii8+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJtOC41IDEwLjUgNSA1IDExLTEyIi8+PC9nPjwvc3ZnPg==)}.scylla-icon--thumbs-up{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSJjdXJyZW50Q29sb3IiIHN0cm9rZS13aWR0aD0iMiIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIiBjbGFzcz0iZmVhdGhlciBmZWF0aGVyLXRodW1icy11cCI+PHBhdGggZD0iTTE0IDlWNWEzIDMgMCAwIDAtMy0zbC00IDl2MTFoMTEuMjhhMiAyIDAgMCAwIDItMS43bDEuMzgtOWEyIDIgMCAwIDAtMi0yLjN6TTcgMjJINGEyIDIgMCAwIDEtMi0ydi03YTIgMiAwIDAgMSAyLTJoMyIvPjwvc3ZnPg==)}.scylla-icon--thumbs-down{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSJjdXJyZW50Q29sb3IiIHN0cm9rZS13aWR0aD0iMiIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIiBjbGFzcz0iZmVhdGhlciBmZWF0aGVyLXRodW1icy1kb3duIj48cGF0aCBkPSJNMTAgMTV2NGEzIDMgMCAwIDAgMyAzbDQtOVYySDUuNzJhMiAyIDAgMCAwLTIgMS43bC0xLjM4IDlhMiAyIDAgMCAwIDIgMi4zem03LTEzaDIuNjdBMi4zMSAyLjMxIDAgMCAxIDIyIDR2N2EyLjMxIDIuMzEgMCAwIDEtMi4zMyAySDE3Ii8+PC9zdmc+)}.scylla-icon--tip{background-image:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZD0iTTEyIDI0QzUuNCAyNCAwIDE4LjYgMCAxMlM1LjQgMCAxMiAwczEyIDUuNCAxMiAxMi01LjQgMTItMTIgMTJabTAtMjJDNi41IDIgMiA2LjUgMiAxMnM0LjUgMTAgMTAgMTAgMTAtNC41IDEwLTEwUzE3LjUgMiAxMiAyWiIgZmlsbD0iI2ZmZiIvPjxwYXRoIGQ9Ik0xMSAxNmMtLjMgMC0uNS0uMS0uNy0uM2wtMy0zYy0uNC0uNC0uNC0xIDAtMS40LjQtLjQgMS0uNCAxLjQgMGwzIDNjLjQuNC40IDEgMCAxLjQtLjIuMi0uNC4zLS43LjNaIiBmaWxsPSIjZmZmIi8+PHBhdGggZD0iTTExIDE2Yy0uMyAwLS41LS4xLS43LS4zLS40LS40LS40LTEgMC0xLjRsNi02Yy40LS40IDEtLjQgMS40IDAgLjQuNC40IDEgMCAxLjRsLTYgNmMtLjIuMi0uNC4zLS43LjNaIiBmaWxsPSIjZmZmIi8+PC9zdmc+)}.scylla-icon--training{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJDYWxxdWVfMiIgZGF0YS1uYW1lPSJDYWxxdWUgMiI+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNMTcuNSAxNS41SC41di0xM2gxOE01LjUgMjVsNC00LjMgNCA0LjMiLz48Y2lyY2xlIGN4PSIyMSIgY3k9IjQiIHI9IjIuNSIgc3R5bGU9InN0cm9rZS1taXRlcmxpbWl0OjEwO2ZpbGw6bm9uZTtzdHJva2U6Z3JheSIvPjxwYXRoIGNsYXNzPSJjbHMtMSIgZD0iTTIzLjQxIDcuNWgtMS41MkwyMSA5bC0uOS0xLjVIMTNBMS44IDEuOCAwIDAgMCAxMS41IDlhMS44IDEuOCAwIDAgMCAxLjUgMS41aDQuNXYxMy4yNEExLjQxIDEuNDEgMCAwIDAgMTkgMjVhMS40MiAxLjQyIDAgMCAwIDEuNS0xLjIyIDEuNTMgMS41MyAwIDAgMCAzIDB2LTcuMTFhMS4xMSAxLjExIDAgMCAwIDEuMDktMS4xOFY4LjY3YTEuMTggMS4xOCAwIDAgMC0xLjE4LTEuMTdaTTkuNSAxNS40NHY1LjM4Ii8+PC9nPjwvc3ZnPg==)}.collapsible-button .side-nav__content .toctree-checkbox:checked~label i,.collapsible-button .side-nav__content i,.scylla-icon--triangle-down,.side-nav__content .collapsible-button i,.side-nav__content .scylla-icon--expand,.side-nav__content .toctree-checkbox:checked~label .collapsible-button i,.side-nav__content .toctree-checkbox:checked~label .scylla-icon--expand{background-image:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTAiIGhlaWdodD0iNSIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cGF0aCBmaWxsLXJ1bGU9ImV2ZW5vZGQiIGNsaXAtcnVsZT0iZXZlbm9kZCIgZD0ibTAgMCA1IDUgNS01SDBaIiBmaWxsPSIjM0EyRDU1Ii8+PC9zdmc+)}.scylla-icon--university{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJDYWxxdWVfNCIgZGF0YS1uYW1lPSJDYWxxdWUgNCI+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJtMS41IDguNSAxMS00IDExIDR2M2wtMTEgNC0xMS00di0zeiIvPjxwYXRoIGNsYXNzPSJjbHMtMSIgZD0iTTUuNSAxMi41djVhMTIuNDYgMTIuNDYgMCAwIDAgNyAyIDExLjIgMTEuMiAwIDAgMCA3LTJ2LTUiLz48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Im0xMy41IDkuNSA4IDEuMjN2OC43N00yMi41IDE2LjV2MyIvPjwvZz48L3N2Zz4=)}.scylla-icon--users-blog{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMntmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJDYWxxdWVfNCIgZGF0YS1uYW1lPSJDYWxxdWUgNCI+PHBhdGggc3R5bGU9InN0cm9rZS13aWR0aDouOThweDtmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kIiBkPSJNMjMuNSAyLjVoLTIydjE2aDEzdjQuMTdsNC4wNC00LjE3IDQuOTYtLjA0VjIuNXoiLz48cGF0aCBjbGFzcz0iY2xzLTIiIGQ9Ik0xMC44NSA4QTEwLjM4IDEwLjM4IDAgMCAxIDExIDkuNWMwIDIuNDctMS4yMSA0LTMgNHMtMy41LTItMy41LTQuNWE0LjE4IDQuMTggMCAwIDEgMC0xIi8+PHBhdGggY2xhc3M9ImNscy0yIiBkPSJNNS4yIDUuMDdhMy4yMiAzLjIyIDAgMCAxIDIuNS0xIDMuMTYgMy4xNiAwIDAgMSAyLjQgMSA2LjIyIDYuMjIgMCAwIDEgMS4zIDMuODEuNzQuNzQgMCAwIDAtLjQyIDBjMC0uMjQgMC0uNDQtLjA1LS42NmgwQTMgMyAwIDAgMSAxMCA2Ljl2LS4yNGwtLjIxLjEyQTkuNjIgOS42MiAwIDAgMSA0LjczIDhhLjI1LjI1IDAgMCAwLS4yMi4wOWMtLjEzLjE0LS4wOS4zNyAwIC42MXYuMThhLjg1Ljg1IDAgMCAwLS4zMiAwQTUuMzcgNS4zNyAwIDAgMSA1LjIgNS4wN1pNNC41MSA4LjkzYy0uMzUgMC0uNTcuMDUtLjYxLjQ0YTEuMTcgMS4xNyAwIDAgMCAuNzMgMS4zTTExIDguOTNjLjM2IDAgLjU3LjA1LjYyLjQ0YTEuMTcgMS4xNyAwIDAgMS0uNzQgMS4zTTYuMzEgMTQuMTN2LS44NE05LjI1IDEzLjE5di45NE0yLjQyIDE4Yy4xMy0xLjE1LjU4LTIuNTIgMS41OC0zYTE0LjcxIDE0LjcxIDAgMCAxIDIuMzEtLjgyTTEzLjUgMThjLS4xMy0xLjE1LS41MS0yLjUyLTEuNS0zcy0yLjUtMS0yLjUtMSIvPjxwYXRoIGNsYXNzPSJjbHMtMiIgZD0iTTkuMzQgMTQuMjJhMi4yMyAyLjIzIDAgMCAxLTEuNTYuNjEgMi4zMiAyLjMyIDAgMCAxLTEuNTUtLjU5TTIxLjUgNi41aC03TTIxLjUgOS41aC03TTE4LjUgMTIuNWgtNCIvPjwvZz48L3N2Zz4=)}.admonition.caution .admonition-title:before,.admonition.warning .admonition-title:before,.scylla-icon--warning{background-image:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PG1hc2sgaWQ9ImEiIG1hc2stdHlwZT0iYWxwaGEiIG1hc2tVbml0cz0idXNlclNwYWNlT25Vc2UiIHg9IjAiIHk9IjEiIHdpZHRoPSIyNCIgaGVpZ2h0PSIyMSI+PHBhdGggZD0iTTMuNSAyMmMtLjUgMC0xLS4xLTEuNS0uNEMuNiAyMC44LjEgMTguOS45IDE3LjVMOS40IDMuM2MuMy0uNC42LS44IDEtMSAuNy0uNCAxLjUtLjUgMi4zLS4zLjguMiAxLjQuNyAxLjkgMS40TDIzIDE3LjVjLjMuNS40IDEgLjQgMS41IDAgLjgtLjMgMS42LS45IDIuMS0uNS42LTEuMi45LTIgLjloLTE3Wm03LjYtMTcuNkwyLjcgMTguNWMtLjMuNS0uMSAxLjEuNCAxLjQuMS4xLjMuMS40LjFoMTYuOWMuMyAwIC41LS4xLjctLjMuMi0uMi4zLS40LjMtLjcgMC0uMiAwLS4zLS4xLS41TDEyLjkgNC40Yy0uMy0uNS0uOS0uNi0xLjQtLjQtLjIuMS0uMy4yLS40LjRaIiBmaWxsPSIjMDYxOTM4Ii8+PHBhdGggZD0iTTEyIDE0Yy0uNiAwLTEtLjQtMS0xVjljMC0uNi40LTEgMS0xczEgLjQgMSAxdjRjMCAuNi0uNCAxLTEgMVpNMTIgMThjLS4zIDAtLjUtLjEtLjctLjMtLjItLjItLjMtLjQtLjMtLjcgMC0uMSAwLS4zLjEtLjQuMS0uMS4xLS4yLjItLjMuMS0uMS4yLS4yLjMtLjIuMi0uMS40LS4xLjYtLjEuMSAwIC4xIDAgLjIuMS4xIDAgLjEgMCAuMi4xIDAgMCAuMS4xLjIuMS4xLjEuMi4yLjIuMyAwIC4xLjEuMy4xLjQgMCAuMy0uMS41LS4zLjctLjMuMi0uNS4zLS44LjNaIiBmaWxsPSIjMDYxOTM4Ii8+PC9tYXNrPjxnIG1hc2s9InVybCgjYSkiPjxwYXRoIGZpbGw9IiMwNjE5MzgiIGQ9Ik0wIDBoMjR2MjRIMHoiLz48L2c+PC9zdmc+)}.scylla-icon--webinars{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMntmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJDYWxxdWVfNCIgZGF0YS1uYW1lPSJDYWxxdWUgNCI+PHBhdGggc3R5bGU9InN0cm9rZS1taXRlcmxpbWl0OjEwO2ZpbGw6bm9uZTtzdHJva2U6Z3JheSIgZD0iTTEuNSA1LjVoMjJ2MTRoLTIyeiIvPjxwYXRoIGNsYXNzPSJjbHMtMiIgZD0iTTkuNDcgMjAuNXYxLjg4TTE1LjUgMjAuNXYyTTYuNSAyMi41aDEyIi8+PHBhdGggc3R5bGU9ImZpbGw6Z3JheSIgZD0ibTkgOSA3LjUgMy41M0w5IDE2Vjl6Ii8+PC9nPjwvc3ZnPg==)}.scylla-icon--whitepapers{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMntmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJDYWxxdWVfNCIgZGF0YS1uYW1lPSJDYWxxdWUgNCI+PHBhdGggc3R5bGU9ImZpbGw6Z3JheSIgZD0iTTggOWg4djJIOHoiLz48cGF0aCBjbGFzcz0iY2xzLTIiIGQ9Ik0xNC4wNiAxLjUgMy41IDEuNTJWMjMuNWgxN1Y3bC02LjQ0LTUuNXoiLz48cGF0aCBkPSJNMTQuMzIgMS40MnYzLjM3YTIuMDYgMi4wNiAwIDAgMCAyLjA4IDIuMWgzLjY3IiBzdHlsZT0ic3Ryb2tlLW1pdGVybGltaXQ6MTA7ZmlsbDpub25lO3N0cm9rZTpncmF5Ii8+PHBhdGggY2xhc3M9ImNscy0yIiBkPSJNNi41IDE5LjVoNE0xMy41IDE5LjVoNE02LjUgMTYuNWg0TTEzLjUgMTYuNWg0TTYuNSAxMy41aDRNMTMuNSAxMy41aDQiLz48L2c+PC9zdmc+)}.scylla-icon--workshop{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMSwuY2xzLTJ7ZmlsbDpub25lO3N0cm9rZTojNGQ0ZDRkfS5jbHMtMXtzdHJva2UtbWl0ZXJsaW1pdDoxMH0uY2xzLTJ7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJDYWxxdWVfNCIgZGF0YS1uYW1lPSJDYWxxdWUgNCI+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNMS41IDUuNWgyMnYxNGgtMjJ6Ii8+PHBhdGggY2xhc3M9ImNscy0yIiBkPSJtOS41IDE5LjUtLjAzIDIuODhNMTUuNSAxOS41djNNNi41IDIyLjVoMTIiLz48cGF0aCBzdHlsZT0iZmlsbDojNGQ0ZDRkIiBkPSJtNCA4IDIgOCAuOTctMy45NUwxMSAxMiA0IDh6Ii8+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJtNi40NyAxMS4zNCAzLjM3IDQuMjgiLz48L2c+PC9zdmc+)}.button{background:transparent;border:1px solid #3a2d55;border-radius:4px;color:#3a2d55;display:inline;font-size:14px;letter-spacing:1px;line-height:21px;margin:0;padding:12px 14px}.button:focus,.button:hover{background:transparent;color:#3a2d55;text-decoration:none}.button--reverse{background:#fff;border:0}.button--reverse:focus,.button--reverse:hover{background:#fff}.tooltip{background-color:rgba(0,0,0,.56);border-radius:4px;font-size:12px;padding:6px}.tooltip:before{display:none!important}.tooltip:empty{display:none!important}.has-tip{border:0;cursor:pointer}.scylla-dropdown{color:#23263b;font-size:14px;line-height:20px}.scylla-dropdown a,.scylla-dropdown a:focus,.scylla-dropdown a:hover{color:#23263b!important;padding:0!important}.scylla-dropdown__item{font-size:16px;padding:15px}.scylla-dropdown__title{align-items:center;display:flex!important;position:static!important}.scylla-dropdown__title:after{display:none!important}.scylla-dropdown__title .chevron{min-height:5px;width:10px}.scylla-dropdown__content{background:#fff;border:0;border-radius:8px;box-shadow:0 4px 25px rgba(0,0,0,.15);font-size:16px;list-style:none;margin-top:15px;overflow:hidden;padding:16px 0;width:max-content}.scylla-dropdown__content li{padding:7px 16px}.scylla-dropdown__content .contents.local>ul>li a:before,.scylla-dropdown__content .secondary-side-nav__content li a:before,.scylla-dropdown__content li .admonition-title:before,.scylla-dropdown__content li .scylla-icon,.secondary-side-nav__content .scylla-dropdown__content li a:before{margin-right:10px}.enlarge-image{cursor:zoom-in}.enlarge-image-reveal{background:transparent;border:none;cursor:zoom-out;padding:0;text-align:center;width:fit-content}.enlarge-image-reveal img{background-color:#fff;padding:15px}.header{background-color:#fff;box-shadow:0 2px 22px rgba(74,93,166,.15);justify-content:space-between;padding:12.75px 0;position:fixed;width:100%;z-index:99}.header,.header-logo{align-items:center;display:flex}.header-logo{margin-left:20px;width:auto}.header-logo__img{width:110px}.header-logo__bar{background-color:#3a2d55;border-left:1px solid #3a2d55;height:11.56px;margin:0 7.5px;width:0}.header-logo__text{color:#3a2d55;font-size:10.11px;letter-spacing:.722408px;line-height:12px;text-transform:uppercase}.header-navigation{display:none}.header-button{display:none;margin-left:15px;text-transform:uppercase}.header-search-box{display:none;margin-right:20px;width:200px}.scylla-dropdown--header .scylla-dropdown__item{font-size:14px}.scylla-dropdown--header .scylla-dropdown__title{text-transform:uppercase}.scylla-dropdown--header .scylla-dropdown__title .chevron{margin-left:10px}.contents.local>ul>li .scylla-dropdown--header .scylla-dropdown__content a:before,.scylla-dropdown--header .scylla-dropdown__content .admonition-title:before,.scylla-dropdown--header .scylla-dropdown__content .contents.local>ul>li a:before,.scylla-dropdown--header .scylla-dropdown__content .scylla-icon,.scylla-dropdown--header .scylla-dropdown__content .secondary-side-nav__content li a:before,.secondary-side-nav__content li .scylla-dropdown--header .scylla-dropdown__content a:before{min-height:20px;width:20px}@media screen and (min-width:1024px){.header{padding:18px 0}.header-logo__img{width:152px}.header-logo__bar{height:16px;margin:0 10px}.header-logo__text{font-size:14px;letter-spacing:.722408px;line-height:12px;text-transform:uppercase}.header-navigation{align-items:center;display:flex;justify-content:center}.header-search-box{display:block}}@media screen and (min-width:1200px){.header-logo{margin-left:30px;width:357px}.header-search-box{margin-right:30px;max-width:20%;width:318px}.header-button{display:block}}.side-nav{background:#fff;display:none;height:100vh;left:0;line-height:24px;max-height:calc(100vh - 50px);overflow-y:auto;padding:20px 20px 0;position:fixed;top:50px;width:100%;z-index:100}.side-nav__title{font-weight:700;margin-bottom:20px}.side-nav__content{max-width:90%;overflow-wrap:break-word}.side-nav__content label,.side-nav__content label i{margin:0;padding:0}.side-nav__content label{font-size:inherit;line-height:1;margin-left:5px;max-height:5px}.collapsible-button .side-nav__content i,.side-nav__content .collapsible-button i,.side-nav__content .scylla-icon--expand{height:5px;vertical-align:top;width:10px}.side-nav__content .toctree-checkbox{display:none;position:absolute;right:20px}.side-nav__content .toctree-checkbox~ul{display:none;margin-right:20px}.side-nav__content .toctree-checkbox:checked~ul{display:block}.side-nav__content ul{margin:0}.side-nav__content a{color:#23263b}.side-nav__content a:hover{color:#3c4fe0;font-weight:400}.side-nav__content li{list-style:none;padding:0 0 24px}.side-nav__content li.has-children{align-items:center;display:flex;flex-wrap:wrap}.side-nav__content li.has-children>a{max-width:calc(100% - 15px)}.side-nav__content li.has-children.current{padding-bottom:20px}.side-nav__content li.has-children:hover>a{color:#3c4fe0}.side-nav__content li.has-children:hover>.toctree-checkbox~label i{filter:invert(38%) sepia(71%) saturate(6789%) hue-rotate(231deg) brightness(90%) contrast(95%)}.side-nav__content li.current-page>a{color:#3c4fe0}.side-nav__content li.current-page>.toctree-checkbox:checked~label i{filter:invert(38%) sepia(71%) saturate(6789%) hue-rotate(231deg) brightness(90%) contrast(95%)}.side-nav__content li ul{margin-top:18px;width:100%}.side-nav__content li ul li{border-left:1px solid #3c4fe0;padding:4px 0 4px 13px}.side-nav__content li ul ul{margin-left:0}.side-nav__content li .label{display:none}.side-nav__versions{max-width:90%}.side-nav__search,.side-nav__versions .dropdown{margin-bottom:20px}.collapsible-button{background:#fff;background-color:#fff;border:0;border-radius:8px;border-radius:50%;bottom:10px;box-shadow:0 4px 25px rgba(0,0,0,.15);cursor:pointer;display:none;font-size:0;left:300px;overflow:hidden;padding:13.5px;position:fixed}.collapsible-button i{height:16px;margin:0;width:16px}.side-nav--collapsed .collapsible-button{border-radius:0 20px 20px 0;left:-10px}.side-nav--collapsed .collapsible-button i{transform:rotate(180deg)}.layout--has-banner .side-nav{max-height:calc(100vh - 92.5px)}@media screen and (min-width:1024px){.side-nav{background-color:#f6f8ff;display:block;height:100%;left:auto;max-height:100vh;max-height:calc(100vh - 80px);padding:30px 40px;top:80px;width:286px;z-index:25}.side-nav__content{max-width:100%;padding-bottom:180px}.side-nav__search{display:none}.side-nav__versions{max-width:100%}.toctree-checkbox{right:40px}.layout--has-banner .side-nav{max-height:calc(100vh - 150px)}}@media screen and (min-width:1200px){.side-nav{width:357px}.side-nav--collapsed{background-color:transparent;padding-left:0;padding-right:0;width:126px}.side-nav--collapsed .side-nav-content{display:none}.collapsible-button{display:block}}.side-nav-toggle{cursor:pointer;display:block;margin-right:20px;position:relative;z-index:300}@media screen and (min-width:1024px){.side-nav-toggle{display:none}}.secondary-side-nav{display:none;height:100%;line-height:24px;padding:20px;width:100%}.secondary-side-nav__content{overflow-wrap:break-word}.secondary-side-nav__content ul{list-style:none;margin:0}.secondary-side-nav__content li{border-bottom:1px solid rgba(90,94,154,.1);display:none;padding:10px 0;word-break:break-word}.secondary-side-nav__content li:last-child{border:0}.secondary-side-nav__content li .label{display:none}.secondary-side-nav__content li a{align-items:baseline;color:#b3bac5;display:flex;font-size:14px}.secondary-side-nav__content li a:before{content:"";filter:invert(40%) sepia(11%) saturate(2157%) hue-rotate(198deg) brightness(89%) contrast(87%)!important;flex-shrink:0;margin-right:10px;min-height:10px;opacity:.5;width:6px}.secondary-side-nav__content li a.current,.secondary-side-nav__content li a:hover{color:#23263b;font-weight:400}.secondary-side-nav__content li a.current:before,.secondary-side-nav__content li a:hover:before{filter:brightness(0);opacity:1}.secondary-side-nav__content li a.current{font-weight:700}.secondary-side-nav__content>ul>li>ul>li{display:block}.secondary-side-nav__content>ul>li{border:0;display:block}.secondary-side-nav__content>ul>li>a{display:none}@media screen and (min-width:1200px){.secondary-side-nav{display:block;max-height:100vh;max-height:calc(100vh - 80px);overflow-y:auto;padding:60px 60px 60px 20px;position:fixed;top:80px;width:286px}.secondary-side-nav__content{padding-bottom:180px}.layout--has-banner .secondary-side-nav{max-height:calc(100vh - 150px)}}.layout{display:flex}.pre-content{align-items:center;display:flex;justify-content:space-between;margin-bottom:20px}.content{margin-top:50px;max-width:1440px;overflow-wrap:break-word;padding:20px;scroll-margin-top:50px;width:100%}.content .line-block,.content p{line-height:28px;margin-bottom:20px}.content ul{list-style:none}.content ul li:before{color:#b3bac5;content:"•";float:left;font-family:FontAwesome;font-size:20px;font-weight:700;margin-left:-1em;margin-top:-2px;width:1em}.content ul ul{list-style:circle}.content ul ul li:before{content:""}.content ol ol{list-style:lower-latin}.content img{margin-bottom:30px}.content section{margin-top:-50px;padding-top:50px}.content .inline-icon.fa-check{color:#42c4e6}.layout--full-width .content{max-width:100%;padding:0;width:100%}.layout--full-width .content .hero-wrapper,.layout--full-width .content .topics-grid{max-width:1190px}.layout--full-width .content.content--collapsed{margin-left:0}.layout--full-width:not(.layout--sidebar) .content{margin-left:0}.layout--has-banner .content{scroll-margin-top:92.5px}.layout--has-banner .content section{margin-top:-92.5px;padding-top:92.5px}.landing__content{padding:0 16px}@media screen and (min-width:1024px){.content{margin-left:286px;margin-top:80px;min-height:calc(100vh - 260px);padding-bottom:100px;scroll-margin-top:80px;width:calc(100% - 286px)}.content section{margin-top:-80px;padding-top:80px}}@media screen and (min-width:1200px){.content{margin-left:357px;padding:60px 40px 40px;width:calc(100% - 643px)}.content--collapsed{margin-left:126px;width:calc(100% - 412px)}.pre-content{margin-bottom:10px}.layout--has-banner .content{scroll-margin-top:150px}.layout--has-banner .content section{margin-top:-150px;padding-top:150px}.landing__content{padding:0 60px}.landing--floating .landing__content{position:relative;top:-70px}}.contents.local>ul{margin-bottom:30px;margin-left:0}.contents.local>ul>li{border-bottom:1px solid rgba(90,94,154,.1);padding:10px 0;word-break:break-word}.contents.local>ul>li:before{content:""}.contents.local>ul>li:last-child{border:0}.contents.local>ul>li ul{display:none}.contents.local>ul>li p{margin:0}.contents.local>ul>li a{font-size:14px}.contents.local>ul>li a:before{content:"";filter:invert(40%) sepia(11%) saturate(2157%) hue-rotate(198deg) brightness(89%) contrast(87%)!important;margin-right:10px;min-height:10px;opacity:.5;width:10px}.contents.local>ul>li a.current:before,.contents.local>ul>li a:hover:before{filter:brightness(0);opacity:1}.topic-title{color:rgba(35,38,59,.75);font-size:10px;letter-spacing:1.5px;margin-bottom:0;text-transform:uppercase}.notice{margin-top:40px}.footer{background-color:#fff;box-shadow:0 -4px 10px hsla(0,0%,82%,.25);padding:30px 0;position:relative;width:100%;z-index:50}.footer-group{margin:0 auto;max-width:1030px;padding:0 20px}.footer-top{align-items:center;border-bottom:1px solid rgba(0,0,0,.1);display:flex;flex-wrap:wrap;justify-content:space-between;padding-bottom:8px;text-align:center}.footer-logo{margin-bottom:30px;width:100%}.footer-logo img{float:left;height:36px}.footer-links{text-align:left}.footer-links__link{color:#333;font-size:12px;font-weight:500;letter-spacing:2.4px;margin-right:16px;text-transform:uppercase}.footer-actions{align-items:center;display:flex;justify-content:space-between;width:90px}.footer-actions__link{color:#000}.footer-actions__link img{height:23px}.footer-bottom{color:#979797;display:flex;flex-wrap:wrap;font-size:12px;font-style:normal;font-weight:400;justify-content:center;letter-spacing:1.4px;line-height:23px;padding:20px 0 10px;text-align:center;text-transform:uppercase}@media screen and (max-width:510px){.footer-links{margin-bottom:20px}}@media screen and (min-width:1024px){.footer{padding:30px 0}.footer-group{padding:0}.footer-top{padding-bottom:30px}.footer-logo{margin:0;width:auto}.footer-links{padding:0 40px}.footer-links__link{font-size:14px;margin-right:28px}.footer-actions{width:110px}.footer-actions__link img{height:28px}.footer-bottom .footer-bottom__copyright,.footer-bottom .footer-bottom__last-updated,.footer-bottom .footer-bottom__version{padding:0 10px}.footer-bottom .footer-bottom__copyright{border-left:none}}.not-found{background-color:#f6f8ff;height:100%;overflow:hidden}.not-found__icon{display:block;margin:40px auto;max-width:300px}.not-found__text{text-align:center}.not-found__text h1{font-size:60px;line-height:1}.not-found__text p{margin:30px 0;width:100%}.not-found__button{text-transform:uppercase}.admonition{border-radius:4px;box-shadow:0 4px 4px rgba(0,0,0,.12);color:rgba(0,0,0,.56);font-size:14px;line-height:20px;margin-bottom:30px;overflow:auto;padding:20px;position:relative}.admonition:before{bottom:0;content:" ";left:0;position:absolute;right:0;top:0;z-index:-1}.admonition-title{color:#23263b;margin-bottom:0!important}.admonition-title:before{content:"";margin-right:8px;min-height:24px;width:24px}.admonition p:not(.admonition-title){margin-bottom:0!important;margin-left:32px}.admonition.tip{border:1px solid #43a047}.admonition.tip:before{border-left:8px solid rgba(67,160,71,.4)}.admonition.tip .admonition-title:before{filter:invert(47%) sepia(11%) saturate(2286%) hue-rotate(73deg) brightness(109%) contrast(88%)}.admonition.note{border:1px solid #1976d2}.admonition.note:before{border-left:8px solid rgba(25,118,210,.4)}.admonition.note .admonition-title:before{filter:invert(44%) sepia(55%) saturate(2310%) hue-rotate(191deg) brightness(81%) contrast(103%)}.admonition.caution{border:1px solid #ffab00}.admonition.caution:before{border-left:8px solid rgba(255,171,0,.4)}.admonition.caution .admonition-title:before{filter:invert(77%) sepia(56%) saturate(3332%) hue-rotate(357deg) brightness(98%) contrast(108%)}.admonition.warning{border:1px solid #e74c3c}.admonition.warning:before{border-left:8px solid rgba(231,76,60,.4)}.admonition.warning .admonition-title:before{filter:invert(41%) sepia(42%) saturate(6427%) hue-rotate(343deg) brightness(99%) contrast(83%)}.breadcrumbs{margin-bottom:0;text-transform:uppercase}.breadcrumbs .bread__item,.breadcrumbs .bread__item:not(.bread__item--last):after,.breadcrumbs a{color:#23263b;font-size:12px;font-weight:400;letter-spacing:1.5px;line-height:2;margin:0;padding:0}.breadcrumbs .bread__item:before{display:none}.breadcrumbs .bread__item:not(.bread__item--last):after{content:"/";margin:0 5px;opacity:1;position:relative}.breadcrumbs .bread__highlight{color:#3c4fe0}.breadcrumbs .bread__highlight:hover{font-weight:700;text-decoration:none}code{background-color:#f7f8f9;border:none;border-radius:4px;color:#23263b;font-size:14px}code.download{background:none;color:#23263b}.highlight{background:transparent!important}.highlight pre{background-color:#f7f8f9;border-radius:8px;color:#23263b;font-size:14px;line-height:26px;margin-bottom:30px;overflow:auto;padding:16px}.highlight a.copybtn{right:1em;top:1em}.highlighttable{background-color:#f7f8f9;border-radius:16px;box-shadow:none}.highlighttable tbody{background-color:transparent;border:0}.highlighttable tbody td{padding:15px!important}.highlighttable tbody tr{border-top:none}.highlighttable .linenos{background-color:#f7f8f9;color:#5a7184;width:50px}.highlighttable .linenos span{line-height:26px}.highlighttable .highlight pre{background-color:transparent;margin:0;padding:0}.highlighttable .highlight a.copybtn{right:.2em;top:.2em}.hide-copy-button .copybtn{display:none}.sphinx_collapse__label{display:flex!important;flex-direction:row-reverse;font-size:medium;font-weight:700;justify-content:flex-end;margin-left:0!important}.sphinx_collapse__icon{margin-left:5px;margin-right:0}.sphinx_collapse__input:checked~.sphinx_collapse__label,.sphinx_collapse__label:hover{color:#3c4fe0}.sphinx_collapse__input:checked~.sphinx_collapse__label .sphinx_collapse__icon,.sphinx_collapse__label:hover .sphinx_collapse__icon{border-top-color:#3c4fe0}.sphinx_collapse__content{margin-top:10px}.contribute{margin:0 0 20px}.contribute__item{font-size:14px;list-style:none;padding-bottom:10px}.contribute__item .icon{margin-right:5px}.content-navigation{display:flex;justify-content:space-between;margin-top:40px}.navigation{max-width:50%;word-break:break-word}.navigation,.navigation__link{display:flex}.navigation__title{word-wrap:break-word;color:#23263b;font-size:12px;font-weight:500;letter-spacing:1.5px;line-height:24px;text-transform:uppercase}.navigation__title .colored{color:#42c4e6}.navigation__button{background:#fff;background-color:#fff;border:0;border-radius:8px;box-shadow:0 4px 25px rgba(0,0,0,.15);cursor:pointer;display:none;font-size:0;height:fit-content;overflow:hidden;padding:13.5px 16.5px}.navigation__button i{height:16px;margin:0;width:10px}.navigation--prev .navigation__title{margin-left:15px}.navigation--next .navigation__title{margin-right:15px;text-align:right}@media screen and (min-width:1200px){.navigation__title{display:inline-block}.navigation__button{display:block}.navigation--next .navigation__title{text-align:left}}.scylla-dropdown--versions .scylla-dropdown__item{background:#fff;border-radius:8px;box-shadow:0 28px 32px rgba(0,0,0,.06);width:100%}.scylla-dropdown--versions .scylla-dropdown__title{align-items:center;display:flex;justify-content:space-between}.scylla-dropdown--versions .scylla-dropdown__title .chevron{min-height:12px;transform:rotate(90deg);width:8px}@media screen and (min-width:1024px){.scylla-dropdown--versions .scylla-dropdown__item{box-shadow:none}}.feedback-container{font-size:16px;margin-top:40px;text-align:left}.feedback-container__title{font-weight:700;margin-bottom:5px!important}.feedback-container__button{background:#fff;border:0;border-radius:8px;box-shadow:0 4px 25px rgba(0,0,0,.15);cursor:pointer;margin:4px;overflow:hidden;padding:8px}.feedback-container__button.active{border:1px solid #3c4fe0}.feedback-container__icon{height:20px;width:20px}.feedback-container__message{font-size:16px;margin-top:10px}.hero{background:#f6f8ff;margin-bottom:30px;overflow:hidden;padding:30px 16px;text-align:left}.hero__title{font-size:28px;font-weight:500;line-height:38px;margin-bottom:14px;max-width:229px}.hero__text{font-size:16px;line-height:26px;max-width:343px}.hero__text a{border-bottom:1px dotted #23263b;color:#23263b}.hero__text p{margin-bottom:0!important}.hero__img{position:absolute;right:-18px;top:20px}.hero__img img{margin-bottom:0!important;width:124px}.hero__button{margin-top:20px;text-transform:uppercase}.hero__button .icon{margin-right:5px}.hero__search-box{box-shadow:0 4px 25px rgba(0,0,0,.02);margin-top:20px}.hero-wrapper{align-items:center;display:flex;justify-content:space-between;margin:0 auto;position:relative}@media screen and (min-width:640px){.hero{padding:60px 16px}.hero__title{font-size:32px;line-height:42px;max-width:482px}.hero__text{font-size:18px;line-height:26px;max-width:482px}.hero__img{display:block;position:static}.hero__img img{height:100%;width:295px}.hero .hero-wrapper{flex-direction:row-reverse}.hero .landing--floating .hero{padding:30px 16px 100px}}@media screen and (min-width:1024px){.hero{padding:60px}}.label{background-color:#23263b;border:0;border-radius:4px;color:#fff;font-size:inherit}.label--note{background-color:#1976d2}.label--tip{background-color:#43a047}.label--caution{background-color:#ffab00}.label--warning{background-color:#e74c3c}.last-updated{color:#4458a3;font-size:12px;letter-spacing:1.5px;margin:10px 0;text-transform:uppercase}.last-updated__icon{font-size:14px}@media screen and (min-width:1024px){.last-updated{float:right;margin:0}}.panel{border:0;border-radius:4px;margin-bottom:30px}.promo-banner{background-color:#4458a3;background-image:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTQ0MCIgaGVpZ2h0PSI3MCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48bWFzayBpZD0iYSIgbWFzay10eXBlPSJhbHBoYSIgbWFza1VuaXRzPSJ1c2VyU3BhY2VPblVzZSIgeD0iMCIgeT0iMCIgd2lkdGg9IjE0NDAiIGhlaWdodD0iNzAiPjxwYXRoIGZpbGw9IiM0NDU4QTMiIGQ9Ik0wIDBoMTQ0MHY3MEgweiIvPjwvbWFzaz48ZyBtYXNrPSJ1cmwoI2EpIiBmaWxsPSIjNTA2NEFFIj48cGF0aCBkPSJNLTE5MyAyMDEuODg0IDEuNS0xMzUgMzU3LjQzNiA3MC41bC0xOTQuNSAzMzYuODg0ek0xMDkyLjkyLTM4LjAwOSA5NzIuODAzLTI0Ni4wNTcgNDAyLjk5NiA4Mi45MiA1MjMuMTEzIDI5MC45N3oiLz48cGF0aCBkPSJtMTAzOC0zOC4wMDkgMTIwLjExNy0yMDguMDQ5IDU2OS44MDcgMzI4Ljk3OS0xMjAuMTE3IDIwOC4wNDl6Ii8+PC9nPjwvc3ZnPg==);background-position:50%;background-repeat:no-repeat;background-size:cover;display:none;overflow:hidden;position:fixed;top:0;width:100%;z-index:900}.promo-banner__icon{margin-right:15px}.promo-banner__icon img{height:40px}.promo-banner__title{color:#fff;font-size:12px;line-height:16px;margin-right:15px}.promo-banner__button{background:#fff;border-radius:4px;font-size:12px;min-width:max-content;padding:5px}.promo-banner__close{display:none;position:absolute;right:16px;top:16px}.contents.local>ul>li .promo-banner__close a:before,.promo-banner__close .admonition-title:before,.promo-banner__close .contents.local>ul>li a:before,.promo-banner__close .scylla-icon,.promo-banner__close .secondary-side-nav__content li a:before,.secondary-side-nav__content li .promo-banner__close a:before{filter:brightness(100%);height:34px;width:34px}.promo-banner__close:hover{cursor:pointer;filter:opacity(.8)}.promo-banner-wrapper{align-items:center;display:flex;justify-content:center;padding:5.85px 20px}@media(min-width:1024px){.promo-banner__title{font-size:18px;line-height:23px}.promo-banner__button{font-size:14px;padding:8.5px}.promo-banner__close{display:block}.promo-banner-wrapper{flex-direction:unset;padding:16px}}.custom-scroll-bar::-webkit-scrollbar{background-color:transparent;width:5px}.custom-scroll-bar::-webkit-scrollbar-thumb{background-color:#b3bac5;-webkit-border-radius:8px;border-radius:8px}.search-box{background:#f7f8f9;border-radius:4px;display:flex;padding:10px 15px}.search-box--hero{background-color:#fff;padding:12px 14px}.search-box:before{background-image:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZD0iTTEwLjUgMThhNy41IDcuNSAwIDEgMCAwLTE1IDcuNSA3LjUgMCAwIDAgMCAxNVpNMjEgMjFsLTUuMi01LjIiIHN0cm9rZT0iIzAwMCIgc3Ryb2tlLXdpZHRoPSIyIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiLz48L3N2Zz4=);background-repeat:no-repeat;background-size:contain;content:"";display:inline-block;filter:brightness(0);margin-top:2px;min-height:18px;min-width:18px;vertical-align:middle;width:20px}.search-box .er-dummy-search,.search-box .er-dummy-search-box,.search-box .er-search-form,.search-box ci-search,.search-box input{margin:0!important;width:100%!important}.search-box input{background:transparent!important;color:rgba(80,80,80,.5)!important;font-size:14px!important;padding:0!important}.search-box input::placeholder{color:rgba(80,80,80,.5)!important;opacity:1!important}.search-box button{display:none!important}.er_search_suggestions{background:#fff;border:0;border:0!important;border-radius:8px;box-shadow:0 4px 25px rgba(0,0,0,.15);overflow:hidden}.er_search_suggestions .er-search-result-box{border-width:1px!important;padding-bottom:10px!important;padding-top:10px!important}.er_search_suggestions .er-search-result-box:hover{background:#f7f8f9!important}.er_search_suggestions .er_more_result_btn{cursor:pointer}.er_search_suggestions h3{font-size:16px!important}.er-search-content{padding:20px!important}#er_search_results .er-search-result-box{display:block!important;margin:10px auto 0!important;width:100%!important}#er_search_results .text,#er_search_results .title a,#er_search_results .url a{max-width:100%!important}#search-result-input-form{max-width:800px!important}#er_search_button{text-align:center}#er_clear_input{right:0!important;top:0!important}.er-facet-header{background-color:transparent!important;border:0!important;padding:0 0 8px!important}.er-facet-val{padding:5px 2px!important}.er-facet-val input{display:block!important;margin:0}#er_search_pagination{margin-top:20px!important}#er_search_pagination li.er-paginator-list.er-active{border-bottom:0!important;font-weight:700}.er-suggestion-sm .er_search_input_dummy{margin:0!important}.er-suggestion-sm .er_search_button_dummy{border:0!important}#er_gcs_mobile_model_container .er-facet-values .er-facet-val{align-items:baseline}@media screen and (min-width:640px){.er-facets{display:none;max-width:300px!important;min-width:auto!important;width:auto!important}}@media screen and (min-width:1024px){.er-suggestions{left:15px!important}}@media screen and (min-width:1200px){.er-facets{display:block;position:fixed!important}.er-facet-count{display:none}}.sphinx-tabs{margin-bottom:30px}.sphinx-tabs-tab{border-bottom:1px solid rgba(0,0,0,.56);color:rgba(0,0,0,.56);cursor:pointer;font-size:14px;font-weight:500;line-height:13px;padding:20px 25px}.sphinx-tabs-tab[aria-selected=true]{border-bottom:2px solid #2196f3;color:#2196f3;padding-bottom:19px}.sphinx-tabs-panel{margin:30px 0}.table-wrapper{border:1px solid #e0e0e0;border-radius:4px;box-shadow:0 1px 2px rgba(0,0,0,.25);display:block;margin-bottom:30px;max-width:100%;overflow-x:auto}table{color:#000;font-size:14px;line-height:24px;margin:0;overflow:hidden}table p{margin:0!important}table caption{background:#f6f8ff;border-bottom:1px solid #e0e0e0;color:#23263b;padding:10px 25px}table thead{background:#f6f8ff;border:0;border-bottom:1px solid #4458a3}table thead th{color:#23263b;font-size:14px;font-weight:700}table td,table thead th{padding:20px 25px}table tbody tr{background-color:transparent!important;border-top:1px solid #e0e0e0;line-height:18px}table:not(.highlighttable) tbody tr:first-child{border-top:1px solid #4458a3}table.thead-border thead .row-odd th{color:#23263b}table.thead-border thead .row-even th{font-weight:400}table.thead-border thead th{border:1px solid #e0e0e0}table.thead-border thead tr:first-child th{border-top:none}table.thead-border thead tr:last-child th{border-bottom:none}table.thead-border thead tr th:first-child{border-left:none}table.thead-border thead tr th:last-child{border-right:none}.topics-grid{display:block;margin:0 auto 30px}.topics-grid__title{color:#23263b;font-size:24px;font-weight:700;line-height:32px;margin-bottom:6px}.topics-grid__text{color:#4458a3;font-size:18px;line-height:24px}.topics-grid--scrollable .hs{-ms-overflow-style:none;display:grid;grid-auto-flow:column;overflow-x:scroll;padding:20px 10px;scrollbar-width:none}.topics-grid--scrollable .hs::-webkit-scrollbar{display:none}.topics-grid--scrollable .hs .topic-box:last-child:after{content:"";width:20px}.topic-box{align-items:stretch;display:flex}.topic-box .card{background:#fff;border:1px solid transparent;border-radius:8px;box-shadow:0 4px 25px rgba(0,0,0,.15);display:flex;flex-direction:column;font-size:18px;margin:0 auto 30px;overflow:hidden;padding:20px;position:relative}.topic-box .card:hover{border:1px solid #4458a3;color:#23263b;font-weight:400}.topic-box__title{color:#23263b;font-size:16px;font-weight:700;line-height:24px;margin-bottom:0}.topic-box__title img{bottom:0;opacity:.3;position:absolute;right:0;top:0}.topic-box__body{color:#000;display:flex;flex-direction:column;flex-grow:1;max-width:80%}.topic-box__body .container{flex-grow:1;margin:0;padding:0}.topic-box__body .line-block,.topic-box__body p{font-size:16px;line-height:19px;margin-top:10px}.topic-box__anchor{color:#42c4e6;font-size:14px;font-weight:700;line-height:24px}.topic-box__icon{display:block;font-size:50px;margin-bottom:20px}.topic-box__icon i{filter:brightness(0);min-height:50px;width:100%}.topic-box__icon img{bottom:-12px;display:none;height:140px;margin:0;opacity:.3;position:absolute;right:-5px}.topic-box--product .card{box-shadow:none;padding:20px;text-align:center}.topic-box--product .card .topic-box__title{color:#23263b;font-size:14px}.topic-box--product .card .topic-box__body{display:flex;flex-direction:column;max-width:100%}.topic-box--product .card .topic-box__body .line-block,.topic-box--product .card .topic-box__body p{font-size:12px}.topic-box--product .card .topic-box__icon img{display:inline-block;max-height:84px;opacity:1;position:static}.topic-box--product .card:hover{background:#fff;border:0;border-radius:8px;box-shadow:0 4px 25px rgba(0,0,0,.15);overflow:hidden}@media screen and (max-width:1024px){.topics-grid--scrollable .topic-box{width:280px!important}.topic-box--product:nth-last-child(-n+2) .card{margin-bottom:0}}@media screen and (min-width:1024px){.topics-grid{margin-bottom:10px}.topics-grid__text{font-size:16px}.topics-grid--scrollable .hs{display:flex;overflow-x:initial;padding:0}.topics-grid--scrollable .hs .topic-box:last-child:after{display:none}.topic-box .card{margin-bottom:60px;padding:45px 30px}.topic-box__title{font-size:20px;line-height:32px}.topic-box__body .line-block,.topic-box__body p{font-size:18px;line-height:26px}.topic-box__anchor{font-size:20px;line-height:26px}.topic-box .topic-box__icon img{display:inline-block}.topic-box--product .card{padding:20px}.topic-box--product .card .topic-box__title{font-size:18px;line-height:24px}.topic-box--product .card .topic-box__body .line-block,.topic-box--product .card .topic-box__body p{font-size:14px}.topic-box--product .card .topic-box__icon img{max-height:111px}.landing .topics-grid--products{margin-bottom:40px}} \ No newline at end of file diff --git a/3.25.4-scylla/_static/doctools.js b/3.25.4-scylla/_static/doctools.js new file mode 100644 index 0000000000..8cbf1b161a --- /dev/null +++ b/3.25.4-scylla/_static/doctools.js @@ -0,0 +1,323 @@ +/* + * doctools.js + * ~~~~~~~~~~~ + * + * Sphinx JavaScript utilities for all documentation. + * + * :copyright: Copyright 2007-2021 by the Sphinx team, see AUTHORS. + * :license: BSD, see LICENSE for details. + * + */ + +/** + * select a different prefix for underscore + */ +$u = _.noConflict(); + +/** + * make the code below compatible with browsers without + * an installed firebug like debugger +if (!window.console || !console.firebug) { + var names = ["log", "debug", "info", "warn", "error", "assert", "dir", + "dirxml", "group", "groupEnd", "time", "timeEnd", "count", "trace", + "profile", "profileEnd"]; + window.console = {}; + for (var i = 0; i < names.length; ++i) + window.console[names[i]] = function() {}; +} + */ + +/** + * small helper function to urldecode strings + * + * See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/decodeURIComponent#Decoding_query_parameters_from_a_URL + */ +jQuery.urldecode = function(x) { + if (!x) { + return x + } + return decodeURIComponent(x.replace(/\+/g, ' ')); +}; + +/** + * small helper function to urlencode strings + */ +jQuery.urlencode = encodeURIComponent; + +/** + * This function returns the parsed url parameters of the + * current request. Multiple values per key are supported, + * it will always return arrays of strings for the value parts. + */ +jQuery.getQueryParameters = function(s) { + if (typeof s === 'undefined') + s = document.location.search; + var parts = s.substr(s.indexOf('?') + 1).split('&'); + var result = {}; + for (var i = 0; i < parts.length; i++) { + var tmp = parts[i].split('=', 2); + var key = jQuery.urldecode(tmp[0]); + var value = jQuery.urldecode(tmp[1]); + if (key in result) + result[key].push(value); + else + result[key] = [value]; + } + return result; +}; + +/** + * highlight a given string on a jquery object by wrapping it in + * span elements with the given class name. + */ +jQuery.fn.highlightText = function(text, className) { + function highlight(node, addItems) { + if (node.nodeType === 3) { + var val = node.nodeValue; + var pos = val.toLowerCase().indexOf(text); + if (pos >= 0 && + !jQuery(node.parentNode).hasClass(className) && + !jQuery(node.parentNode).hasClass("nohighlight")) { + var span; + var isInSVG = jQuery(node).closest("body, svg, foreignObject").is("svg"); + if (isInSVG) { + span = document.createElementNS("http://www.w3.org/2000/svg", "tspan"); + } else { + span = document.createElement("span"); + span.className = className; + } + span.appendChild(document.createTextNode(val.substr(pos, text.length))); + node.parentNode.insertBefore(span, node.parentNode.insertBefore( + document.createTextNode(val.substr(pos + text.length)), + node.nextSibling)); + node.nodeValue = val.substr(0, pos); + if (isInSVG) { + var rect = document.createElementNS("http://www.w3.org/2000/svg", "rect"); + var bbox = node.parentElement.getBBox(); + rect.x.baseVal.value = bbox.x; + rect.y.baseVal.value = bbox.y; + rect.width.baseVal.value = bbox.width; + rect.height.baseVal.value = bbox.height; + rect.setAttribute('class', className); + addItems.push({ + "parent": node.parentNode, + "target": rect}); + } + } + } + else if (!jQuery(node).is("button, select, textarea")) { + jQuery.each(node.childNodes, function() { + highlight(this, addItems); + }); + } + } + var addItems = []; + var result = this.each(function() { + highlight(this, addItems); + }); + for (var i = 0; i < addItems.length; ++i) { + jQuery(addItems[i].parent).before(addItems[i].target); + } + return result; +}; + +/* + * backward compatibility for jQuery.browser + * This will be supported until firefox bug is fixed. + */ +if (!jQuery.browser) { + jQuery.uaMatch = function(ua) { + ua = ua.toLowerCase(); + + var match = /(chrome)[ \/]([\w.]+)/.exec(ua) || + /(webkit)[ \/]([\w.]+)/.exec(ua) || + /(opera)(?:.*version|)[ \/]([\w.]+)/.exec(ua) || + /(msie) ([\w.]+)/.exec(ua) || + ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec(ua) || + []; + + return { + browser: match[ 1 ] || "", + version: match[ 2 ] || "0" + }; + }; + jQuery.browser = {}; + jQuery.browser[jQuery.uaMatch(navigator.userAgent).browser] = true; +} + +/** + * Small JavaScript module for the documentation. + */ +var Documentation = { + + init : function() { + this.fixFirefoxAnchorBug(); + this.highlightSearchWords(); + this.initIndexTable(); + if (DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS) { + this.initOnKeyListeners(); + } + }, + + /** + * i18n support + */ + TRANSLATIONS : {}, + PLURAL_EXPR : function(n) { return n === 1 ? 0 : 1; }, + LOCALE : 'unknown', + + // gettext and ngettext don't access this so that the functions + // can safely bound to a different name (_ = Documentation.gettext) + gettext : function(string) { + var translated = Documentation.TRANSLATIONS[string]; + if (typeof translated === 'undefined') + return string; + return (typeof translated === 'string') ? translated : translated[0]; + }, + + ngettext : function(singular, plural, n) { + var translated = Documentation.TRANSLATIONS[singular]; + if (typeof translated === 'undefined') + return (n == 1) ? singular : plural; + return translated[Documentation.PLURALEXPR(n)]; + }, + + addTranslations : function(catalog) { + for (var key in catalog.messages) + this.TRANSLATIONS[key] = catalog.messages[key]; + this.PLURAL_EXPR = new Function('n', 'return +(' + catalog.plural_expr + ')'); + this.LOCALE = catalog.locale; + }, + + /** + * add context elements like header anchor links + */ + addContextElements : function() { + $('div[id] > :header:first').each(function() { + $('\u00B6'). + attr('href', '#' + this.id). + attr('title', _('Permalink to this headline')). + appendTo(this); + }); + $('dt[id]').each(function() { + $('\u00B6'). + attr('href', '#' + this.id). + attr('title', _('Permalink to this definition')). + appendTo(this); + }); + }, + + /** + * workaround a firefox stupidity + * see: https://bugzilla.mozilla.org/show_bug.cgi?id=645075 + */ + fixFirefoxAnchorBug : function() { + if (document.location.hash && $.browser.mozilla) + window.setTimeout(function() { + document.location.href += ''; + }, 10); + }, + + /** + * highlight the search words provided in the url in the text + */ + highlightSearchWords : function() { + var params = $.getQueryParameters(); + var terms = (params.highlight) ? params.highlight[0].split(/\s+/) : []; + if (terms.length) { + var body = $('div.body'); + if (!body.length) { + body = $('body'); + } + window.setTimeout(function() { + $.each(terms, function() { + body.highlightText(this.toLowerCase(), 'highlighted'); + }); + }, 10); + $('') + .appendTo($('#searchbox')); + } + }, + + /** + * init the domain index toggle buttons + */ + initIndexTable : function() { + var togglers = $('img.toggler').click(function() { + var src = $(this).attr('src'); + var idnum = $(this).attr('id').substr(7); + $('tr.cg-' + idnum).toggle(); + if (src.substr(-9) === 'minus.png') + $(this).attr('src', src.substr(0, src.length-9) + 'plus.png'); + else + $(this).attr('src', src.substr(0, src.length-8) + 'minus.png'); + }).css('display', ''); + if (DOCUMENTATION_OPTIONS.COLLAPSE_INDEX) { + togglers.click(); + } + }, + + /** + * helper function to hide the search marks again + */ + hideSearchWords : function() { + $('#searchbox .highlight-link').fadeOut(300); + $('span.highlighted').removeClass('highlighted'); + }, + + /** + * make the url absolute + */ + makeURL : function(relativeURL) { + return DOCUMENTATION_OPTIONS.URL_ROOT + '/' + relativeURL; + }, + + /** + * get the current relative url + */ + getCurrentURL : function() { + var path = document.location.pathname; + var parts = path.split(/\//); + $.each(DOCUMENTATION_OPTIONS.URL_ROOT.split(/\//), function() { + if (this === '..') + parts.pop(); + }); + var url = parts.join('/'); + return path.substring(url.lastIndexOf('/') + 1, path.length - 1); + }, + + initOnKeyListeners: function() { + $(document).keydown(function(event) { + var activeElementType = document.activeElement.tagName; + // don't navigate when in search box, textarea, dropdown or button + if (activeElementType !== 'TEXTAREA' && activeElementType !== 'INPUT' && activeElementType !== 'SELECT' + && activeElementType !== 'BUTTON' && !event.altKey && !event.ctrlKey && !event.metaKey + && !event.shiftKey) { + switch (event.keyCode) { + case 37: // left + var prevHref = $('link[rel="prev"]').prop('href'); + if (prevHref) { + window.location.href = prevHref; + return false; + } + break; + case 39: // right + var nextHref = $('link[rel="next"]').prop('href'); + if (nextHref) { + window.location.href = nextHref; + return false; + } + break; + } + } + }); + } +}; + +// quick alias for translations +_ = Documentation.gettext; + +$(document).ready(function() { + Documentation.init(); +}); diff --git a/3.25.4-scylla/_static/documentation_options.js b/3.25.4-scylla/_static/documentation_options.js new file mode 100644 index 0000000000..ec2787ff28 --- /dev/null +++ b/3.25.4-scylla/_static/documentation_options.js @@ -0,0 +1,12 @@ +var DOCUMENTATION_OPTIONS = { + URL_ROOT: document.getElementById("documentation_options").getAttribute('data-url_root'), + VERSION: '3.25.4', + LANGUAGE: 'None', + COLLAPSE_INDEX: false, + BUILDER: 'html', + FILE_SUFFIX: '.html', + LINK_SUFFIX: '.html', + HAS_SOURCE: true, + SOURCELINK_SUFFIX: '.txt', + NAVIGATION_WITH_KEYS: false +}; \ No newline at end of file diff --git a/3.25.4-scylla/_static/file.png b/3.25.4-scylla/_static/file.png new file mode 100644 index 0000000000..a858a410e4 Binary files /dev/null and b/3.25.4-scylla/_static/file.png differ diff --git a/3.25.4-scylla/_static/img/banner-background.svg b/3.25.4-scylla/_static/img/banner-background.svg new file mode 100644 index 0000000000..f8520d5b3e --- /dev/null +++ b/3.25.4-scylla/_static/img/banner-background.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/3.25.4-scylla/_static/img/favicon-228x228.png b/3.25.4-scylla/_static/img/favicon-228x228.png new file mode 100644 index 0000000000..f30770c7ed Binary files /dev/null and b/3.25.4-scylla/_static/img/favicon-228x228.png differ diff --git a/3.25.4-scylla/_static/img/favicon-32x32.png b/3.25.4-scylla/_static/img/favicon-32x32.png new file mode 100644 index 0000000000..aae1708f26 Binary files /dev/null and b/3.25.4-scylla/_static/img/favicon-32x32.png differ diff --git a/3.25.4-scylla/_static/img/favicon.ico b/3.25.4-scylla/_static/img/favicon.ico new file mode 100644 index 0000000000..6c7484f082 Binary files /dev/null and b/3.25.4-scylla/_static/img/favicon.ico differ diff --git a/3.25.4-scylla/_static/img/icons/icon-about-team.svg b/3.25.4-scylla/_static/img/icons/icon-about-team.svg new file mode 100644 index 0000000000..5448c7f007 --- /dev/null +++ b/3.25.4-scylla/_static/img/icons/icon-about-team.svg @@ -0,0 +1 @@ +icon-about-team diff --git a/3.25.4-scylla/_static/img/icons/icon-about-us-m.svg b/3.25.4-scylla/_static/img/icons/icon-about-us-m.svg new file mode 100644 index 0000000000..09107d9520 --- /dev/null +++ b/3.25.4-scylla/_static/img/icons/icon-about-us-m.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/3.25.4-scylla/_static/img/icons/icon-about-us.svg b/3.25.4-scylla/_static/img/icons/icon-about-us.svg new file mode 100644 index 0000000000..1b1fcc83e3 --- /dev/null +++ b/3.25.4-scylla/_static/img/icons/icon-about-us.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/3.25.4-scylla/_static/img/icons/icon-alternator.svg b/3.25.4-scylla/_static/img/icons/icon-alternator.svg new file mode 100644 index 0000000000..7c2b4ebae0 --- /dev/null +++ b/3.25.4-scylla/_static/img/icons/icon-alternator.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/3.25.4-scylla/_static/img/icons/icon-apps.svg b/3.25.4-scylla/_static/img/icons/icon-apps.svg new file mode 100644 index 0000000000..7e93612026 --- /dev/null +++ b/3.25.4-scylla/_static/img/icons/icon-apps.svg @@ -0,0 +1 @@ + diff --git a/3.25.4-scylla/_static/img/icons/icon-architecture.svg b/3.25.4-scylla/_static/img/icons/icon-architecture.svg new file mode 100644 index 0000000000..67ebbc2f38 --- /dev/null +++ b/3.25.4-scylla/_static/img/icons/icon-architecture.svg @@ -0,0 +1 @@ +icon-architecture diff --git a/3.25.4-scylla/_static/img/icons/icon-benchmarks.svg b/3.25.4-scylla/_static/img/icons/icon-benchmarks.svg new file mode 100644 index 0000000000..e1ce2c1d78 --- /dev/null +++ b/3.25.4-scylla/_static/img/icons/icon-benchmarks.svg @@ -0,0 +1 @@ +icon-benchmarks diff --git a/3.25.4-scylla/_static/img/icons/icon-blog.svg b/3.25.4-scylla/_static/img/icons/icon-blog.svg new file mode 100644 index 0000000000..f4096cbf11 --- /dev/null +++ b/3.25.4-scylla/_static/img/icons/icon-blog.svg @@ -0,0 +1 @@ +icon-blog2 diff --git a/3.25.4-scylla/_static/img/icons/icon-careers.svg b/3.25.4-scylla/_static/img/icons/icon-careers.svg new file mode 100644 index 0000000000..2a7c6ea0b7 --- /dev/null +++ b/3.25.4-scylla/_static/img/icons/icon-careers.svg @@ -0,0 +1 @@ +icon-careers diff --git a/3.25.4-scylla/_static/img/icons/icon-chevron-left.svg b/3.25.4-scylla/_static/img/icons/icon-chevron-left.svg new file mode 100644 index 0000000000..3afa25c481 --- /dev/null +++ b/3.25.4-scylla/_static/img/icons/icon-chevron-left.svg @@ -0,0 +1,3 @@ + + + diff --git a/3.25.4-scylla/_static/img/icons/icon-chevron-right.svg b/3.25.4-scylla/_static/img/icons/icon-chevron-right.svg new file mode 100644 index 0000000000..44eb829cdc --- /dev/null +++ b/3.25.4-scylla/_static/img/icons/icon-chevron-right.svg @@ -0,0 +1,3 @@ + + + diff --git a/3.25.4-scylla/_static/img/icons/icon-circe.svg b/3.25.4-scylla/_static/img/icons/icon-circe.svg new file mode 100644 index 0000000000..875e421670 --- /dev/null +++ b/3.25.4-scylla/_static/img/icons/icon-circe.svg @@ -0,0 +1 @@ + diff --git a/3.25.4-scylla/_static/img/icons/icon-clock.svg b/3.25.4-scylla/_static/img/icons/icon-clock.svg new file mode 100644 index 0000000000..8c92469808 --- /dev/null +++ b/3.25.4-scylla/_static/img/icons/icon-clock.svg @@ -0,0 +1 @@ + diff --git a/3.25.4-scylla/_static/img/icons/icon-close.svg b/3.25.4-scylla/_static/img/icons/icon-close.svg new file mode 100644 index 0000000000..d1162b73e7 --- /dev/null +++ b/3.25.4-scylla/_static/img/icons/icon-close.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/3.25.4-scylla/_static/img/icons/icon-cloud-docs.svg b/3.25.4-scylla/_static/img/icons/icon-cloud-docs.svg new file mode 100644 index 0000000000..a9069bb6e5 --- /dev/null +++ b/3.25.4-scylla/_static/img/icons/icon-cloud-docs.svg @@ -0,0 +1 @@ + diff --git a/3.25.4-scylla/_static/img/icons/icon-cloud.svg b/3.25.4-scylla/_static/img/icons/icon-cloud.svg new file mode 100644 index 0000000000..cfb2318dae --- /dev/null +++ b/3.25.4-scylla/_static/img/icons/icon-cloud.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/3.25.4-scylla/_static/img/icons/icon-comparison.svg b/3.25.4-scylla/_static/img/icons/icon-comparison.svg new file mode 100644 index 0000000000..49d809a5df --- /dev/null +++ b/3.25.4-scylla/_static/img/icons/icon-comparison.svg @@ -0,0 +1 @@ +icon-comparison diff --git a/3.25.4-scylla/_static/img/icons/icon-contact-us.svg b/3.25.4-scylla/_static/img/icons/icon-contact-us.svg new file mode 100644 index 0000000000..9df3145dd2 --- /dev/null +++ b/3.25.4-scylla/_static/img/icons/icon-contact-us.svg @@ -0,0 +1 @@ +icon-contact-us diff --git a/3.25.4-scylla/_static/img/icons/icon-developers-blog.svg b/3.25.4-scylla/_static/img/icons/icon-developers-blog.svg new file mode 100644 index 0000000000..ee804197a0 --- /dev/null +++ b/3.25.4-scylla/_static/img/icons/icon-developers-blog.svg @@ -0,0 +1 @@ +icon-developers-blog diff --git a/3.25.4-scylla/_static/img/icons/icon-docs.svg b/3.25.4-scylla/_static/img/icons/icon-docs.svg new file mode 100644 index 0000000000..5501492f3e --- /dev/null +++ b/3.25.4-scylla/_static/img/icons/icon-docs.svg @@ -0,0 +1 @@ +icon-docs diff --git a/3.25.4-scylla/_static/img/icons/icon-enterprise-m.svg b/3.25.4-scylla/_static/img/icons/icon-enterprise-m.svg new file mode 100644 index 0000000000..97be900b50 --- /dev/null +++ b/3.25.4-scylla/_static/img/icons/icon-enterprise-m.svg @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/3.25.4-scylla/_static/img/icons/icon-enterprise.svg b/3.25.4-scylla/_static/img/icons/icon-enterprise.svg new file mode 100644 index 0000000000..ee1ac26283 --- /dev/null +++ b/3.25.4-scylla/_static/img/icons/icon-enterprise.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/3.25.4-scylla/_static/img/icons/icon-events.svg b/3.25.4-scylla/_static/img/icons/icon-events.svg new file mode 100644 index 0000000000..ba5f211864 --- /dev/null +++ b/3.25.4-scylla/_static/img/icons/icon-events.svg @@ -0,0 +1 @@ +icon-events diff --git a/3.25.4-scylla/_static/img/icons/icon-exclamation.svg b/3.25.4-scylla/_static/img/icons/icon-exclamation.svg new file mode 100644 index 0000000000..a7eb4b77a4 --- /dev/null +++ b/3.25.4-scylla/_static/img/icons/icon-exclamation.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/3.25.4-scylla/_static/img/icons/icon-expand.svg b/3.25.4-scylla/_static/img/icons/icon-expand.svg new file mode 100644 index 0000000000..3806565367 --- /dev/null +++ b/3.25.4-scylla/_static/img/icons/icon-expand.svg @@ -0,0 +1,50 @@ + + + + + + + + + diff --git a/3.25.4-scylla/_static/img/icons/icon-forum.svg b/3.25.4-scylla/_static/img/icons/icon-forum.svg new file mode 100644 index 0000000000..37a709f7a8 --- /dev/null +++ b/3.25.4-scylla/_static/img/icons/icon-forum.svg @@ -0,0 +1 @@ + diff --git a/3.25.4-scylla/_static/img/icons/icon-getting-started.svg b/3.25.4-scylla/_static/img/icons/icon-getting-started.svg new file mode 100644 index 0000000000..702500be40 --- /dev/null +++ b/3.25.4-scylla/_static/img/icons/icon-getting-started.svg @@ -0,0 +1 @@ + diff --git a/3.25.4-scylla/_static/img/icons/icon-glossary.svg b/3.25.4-scylla/_static/img/icons/icon-glossary.svg new file mode 100644 index 0000000000..e8329c2afe --- /dev/null +++ b/3.25.4-scylla/_static/img/icons/icon-glossary.svg @@ -0,0 +1 @@ + diff --git a/3.25.4-scylla/_static/img/icons/icon-home.svg b/3.25.4-scylla/_static/img/icons/icon-home.svg new file mode 100644 index 0000000000..f0b9c25419 --- /dev/null +++ b/3.25.4-scylla/_static/img/icons/icon-home.svg @@ -0,0 +1 @@ + diff --git a/3.25.4-scylla/_static/img/icons/icon-infoworld.svg b/3.25.4-scylla/_static/img/icons/icon-infoworld.svg new file mode 100644 index 0000000000..906e87279c --- /dev/null +++ b/3.25.4-scylla/_static/img/icons/icon-infoworld.svg @@ -0,0 +1 @@ +icon-infoworld diff --git a/3.25.4-scylla/_static/img/icons/icon-integrations.svg b/3.25.4-scylla/_static/img/icons/icon-integrations.svg new file mode 100644 index 0000000000..1ef0920d49 --- /dev/null +++ b/3.25.4-scylla/_static/img/icons/icon-integrations.svg @@ -0,0 +1 @@ + diff --git a/3.25.4-scylla/_static/img/icons/icon-knowledge-base.svg b/3.25.4-scylla/_static/img/icons/icon-knowledge-base.svg new file mode 100644 index 0000000000..884451270d --- /dev/null +++ b/3.25.4-scylla/_static/img/icons/icon-knowledge-base.svg @@ -0,0 +1 @@ + diff --git a/3.25.4-scylla/_static/img/icons/icon-less.svg b/3.25.4-scylla/_static/img/icons/icon-less.svg new file mode 100644 index 0000000000..3094127dec --- /dev/null +++ b/3.25.4-scylla/_static/img/icons/icon-less.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/3.25.4-scylla/_static/img/icons/icon-live-test.svg b/3.25.4-scylla/_static/img/icons/icon-live-test.svg new file mode 100644 index 0000000000..dcb5916c26 --- /dev/null +++ b/3.25.4-scylla/_static/img/icons/icon-live-test.svg @@ -0,0 +1 @@ +icon-live-test diff --git a/3.25.4-scylla/_static/img/icons/icon-mail-list.svg b/3.25.4-scylla/_static/img/icons/icon-mail-list.svg new file mode 100644 index 0000000000..0e6192a352 --- /dev/null +++ b/3.25.4-scylla/_static/img/icons/icon-mail-list.svg @@ -0,0 +1 @@ + diff --git a/3.25.4-scylla/_static/img/icons/icon-manager.svg b/3.25.4-scylla/_static/img/icons/icon-manager.svg new file mode 100644 index 0000000000..02b4e425be --- /dev/null +++ b/3.25.4-scylla/_static/img/icons/icon-manager.svg @@ -0,0 +1 @@ +icon-manager diff --git a/3.25.4-scylla/_static/img/icons/icon-memory-management.svg b/3.25.4-scylla/_static/img/icons/icon-memory-management.svg new file mode 100644 index 0000000000..e34eb4504f --- /dev/null +++ b/3.25.4-scylla/_static/img/icons/icon-memory-management.svg @@ -0,0 +1 @@ +icon-memory-management diff --git a/3.25.4-scylla/_static/img/icons/icon-modeling.svg b/3.25.4-scylla/_static/img/icons/icon-modeling.svg new file mode 100644 index 0000000000..97fa3a0e21 --- /dev/null +++ b/3.25.4-scylla/_static/img/icons/icon-modeling.svg @@ -0,0 +1 @@ + diff --git a/3.25.4-scylla/_static/img/icons/icon-monitoring.svg b/3.25.4-scylla/_static/img/icons/icon-monitoring.svg new file mode 100644 index 0000000000..80b3787f66 --- /dev/null +++ b/3.25.4-scylla/_static/img/icons/icon-monitoring.svg @@ -0,0 +1 @@ +icon-monitoring diff --git a/3.25.4-scylla/_static/img/icons/icon-networking.svg b/3.25.4-scylla/_static/img/icons/icon-networking.svg new file mode 100644 index 0000000000..40a3fd5f6f --- /dev/null +++ b/3.25.4-scylla/_static/img/icons/icon-networking.svg @@ -0,0 +1 @@ +icon-networking diff --git a/3.25.4-scylla/_static/img/icons/icon-news.svg b/3.25.4-scylla/_static/img/icons/icon-news.svg new file mode 100644 index 0000000000..a952b59937 --- /dev/null +++ b/3.25.4-scylla/_static/img/icons/icon-news.svg @@ -0,0 +1 @@ +icon-news diff --git a/3.25.4-scylla/_static/img/icons/icon-newsletter.svg b/3.25.4-scylla/_static/img/icons/icon-newsletter.svg new file mode 100644 index 0000000000..5b8d47eb15 --- /dev/null +++ b/3.25.4-scylla/_static/img/icons/icon-newsletter.svg @@ -0,0 +1 @@ +icon-newsletter diff --git a/3.25.4-scylla/_static/img/icons/icon-nsql-guides.svg b/3.25.4-scylla/_static/img/icons/icon-nsql-guides.svg new file mode 100644 index 0000000000..60ebab3795 --- /dev/null +++ b/3.25.4-scylla/_static/img/icons/icon-nsql-guides.svg @@ -0,0 +1 @@ +icon-nsql-guides diff --git a/3.25.4-scylla/_static/img/icons/icon-open-source.svg b/3.25.4-scylla/_static/img/icons/icon-open-source.svg new file mode 100644 index 0000000000..98c2ea7d5b --- /dev/null +++ b/3.25.4-scylla/_static/img/icons/icon-open-source.svg @@ -0,0 +1 @@ +icon-open-source diff --git a/3.25.4-scylla/_static/img/icons/icon-operator.svg b/3.25.4-scylla/_static/img/icons/icon-operator.svg new file mode 100644 index 0000000000..bb7d8d3ea8 --- /dev/null +++ b/3.25.4-scylla/_static/img/icons/icon-operator.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/3.25.4-scylla/_static/img/icons/icon-overview.svg b/3.25.4-scylla/_static/img/icons/icon-overview.svg new file mode 100644 index 0000000000..515c1528a2 --- /dev/null +++ b/3.25.4-scylla/_static/img/icons/icon-overview.svg @@ -0,0 +1 @@ +icon-overview diff --git a/3.25.4-scylla/_static/img/icons/icon-partners.svg b/3.25.4-scylla/_static/img/icons/icon-partners.svg new file mode 100644 index 0000000000..d0146fc497 --- /dev/null +++ b/3.25.4-scylla/_static/img/icons/icon-partners.svg @@ -0,0 +1 @@ +icon-partners diff --git a/3.25.4-scylla/_static/img/icons/icon-plus.svg b/3.25.4-scylla/_static/img/icons/icon-plus.svg new file mode 100644 index 0000000000..5757435085 --- /dev/null +++ b/3.25.4-scylla/_static/img/icons/icon-plus.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/3.25.4-scylla/_static/img/icons/icon-pricing.svg b/3.25.4-scylla/_static/img/icons/icon-pricing.svg new file mode 100644 index 0000000000..74b01db168 --- /dev/null +++ b/3.25.4-scylla/_static/img/icons/icon-pricing.svg @@ -0,0 +1 @@ +icon-pricing$ diff --git a/3.25.4-scylla/_static/img/icons/icon-release-notes.svg b/3.25.4-scylla/_static/img/icons/icon-release-notes.svg new file mode 100644 index 0000000000..80c490c7b0 --- /dev/null +++ b/3.25.4-scylla/_static/img/icons/icon-release-notes.svg @@ -0,0 +1 @@ +icon-release-notes diff --git a/3.25.4-scylla/_static/img/icons/icon-resource-center.svg b/3.25.4-scylla/_static/img/icons/icon-resource-center.svg new file mode 100644 index 0000000000..6e3ab08e79 --- /dev/null +++ b/3.25.4-scylla/_static/img/icons/icon-resource-center.svg @@ -0,0 +1 @@ +icon-ressource-center diff --git a/3.25.4-scylla/_static/img/icons/icon-roadmap.svg b/3.25.4-scylla/_static/img/icons/icon-roadmap.svg new file mode 100644 index 0000000000..c8cbf67c8c --- /dev/null +++ b/3.25.4-scylla/_static/img/icons/icon-roadmap.svg @@ -0,0 +1 @@ +icon-roadmap-4 diff --git a/3.25.4-scylla/_static/img/icons/icon-search.svg b/3.25.4-scylla/_static/img/icons/icon-search.svg new file mode 100644 index 0000000000..81aae93eef --- /dev/null +++ b/3.25.4-scylla/_static/img/icons/icon-search.svg @@ -0,0 +1,4 @@ + + + + diff --git a/3.25.4-scylla/_static/img/icons/icon-slack.svg b/3.25.4-scylla/_static/img/icons/icon-slack.svg new file mode 100644 index 0000000000..fc164ea1e7 --- /dev/null +++ b/3.25.4-scylla/_static/img/icons/icon-slack.svg @@ -0,0 +1 @@ + diff --git a/3.25.4-scylla/_static/img/icons/icon-stack-overflow.svg b/3.25.4-scylla/_static/img/icons/icon-stack-overflow.svg new file mode 100644 index 0000000000..bebe9b8274 --- /dev/null +++ b/3.25.4-scylla/_static/img/icons/icon-stack-overflow.svg @@ -0,0 +1,4 @@ + + + + diff --git a/3.25.4-scylla/_static/img/icons/icon-summit.svg b/3.25.4-scylla/_static/img/icons/icon-summit.svg new file mode 100644 index 0000000000..4b900bd0c0 --- /dev/null +++ b/3.25.4-scylla/_static/img/icons/icon-summit.svg @@ -0,0 +1 @@ + diff --git a/3.25.4-scylla/_static/img/icons/icon-support.svg b/3.25.4-scylla/_static/img/icons/icon-support.svg new file mode 100644 index 0000000000..a4228b34e8 --- /dev/null +++ b/3.25.4-scylla/_static/img/icons/icon-support.svg @@ -0,0 +1 @@ +icon-support diff --git a/3.25.4-scylla/_static/img/icons/icon-tech-talks.svg b/3.25.4-scylla/_static/img/icons/icon-tech-talks.svg new file mode 100644 index 0000000000..df42b5522b --- /dev/null +++ b/3.25.4-scylla/_static/img/icons/icon-tech-talks.svg @@ -0,0 +1 @@ +icon-tech-talks diff --git a/3.25.4-scylla/_static/img/icons/icon-testing.svg b/3.25.4-scylla/_static/img/icons/icon-testing.svg new file mode 100644 index 0000000000..2fe54efdbc --- /dev/null +++ b/3.25.4-scylla/_static/img/icons/icon-testing.svg @@ -0,0 +1 @@ +icon-testing diff --git a/3.25.4-scylla/_static/img/icons/icon-thumbs-down.svg b/3.25.4-scylla/_static/img/icons/icon-thumbs-down.svg new file mode 100644 index 0000000000..3e7bcd6d90 --- /dev/null +++ b/3.25.4-scylla/_static/img/icons/icon-thumbs-down.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/3.25.4-scylla/_static/img/icons/icon-thumbs-up.svg b/3.25.4-scylla/_static/img/icons/icon-thumbs-up.svg new file mode 100644 index 0000000000..226c44d853 --- /dev/null +++ b/3.25.4-scylla/_static/img/icons/icon-thumbs-up.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/3.25.4-scylla/_static/img/icons/icon-tip.svg b/3.25.4-scylla/_static/img/icons/icon-tip.svg new file mode 100644 index 0000000000..bf7aa6af84 --- /dev/null +++ b/3.25.4-scylla/_static/img/icons/icon-tip.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/3.25.4-scylla/_static/img/icons/icon-training.svg b/3.25.4-scylla/_static/img/icons/icon-training.svg new file mode 100644 index 0000000000..08b95a88ed --- /dev/null +++ b/3.25.4-scylla/_static/img/icons/icon-training.svg @@ -0,0 +1 @@ +icon-training diff --git a/3.25.4-scylla/_static/img/icons/icon-triangle-down.svg b/3.25.4-scylla/_static/img/icons/icon-triangle-down.svg new file mode 100644 index 0000000000..e8ae088106 --- /dev/null +++ b/3.25.4-scylla/_static/img/icons/icon-triangle-down.svg @@ -0,0 +1,3 @@ + + + diff --git a/3.25.4-scylla/_static/img/icons/icon-university.svg b/3.25.4-scylla/_static/img/icons/icon-university.svg new file mode 100644 index 0000000000..f7547ab959 --- /dev/null +++ b/3.25.4-scylla/_static/img/icons/icon-university.svg @@ -0,0 +1 @@ +icon-university diff --git a/3.25.4-scylla/_static/img/icons/icon-users-blog.svg b/3.25.4-scylla/_static/img/icons/icon-users-blog.svg new file mode 100644 index 0000000000..47e56cddcf --- /dev/null +++ b/3.25.4-scylla/_static/img/icons/icon-users-blog.svg @@ -0,0 +1 @@ +icon-users-blog diff --git a/3.25.4-scylla/_static/img/icons/icon-warning.svg b/3.25.4-scylla/_static/img/icons/icon-warning.svg new file mode 100644 index 0000000000..e4b1d40331 --- /dev/null +++ b/3.25.4-scylla/_static/img/icons/icon-warning.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/3.25.4-scylla/_static/img/icons/icon-webinars.svg b/3.25.4-scylla/_static/img/icons/icon-webinars.svg new file mode 100644 index 0000000000..5e9f5cd427 --- /dev/null +++ b/3.25.4-scylla/_static/img/icons/icon-webinars.svg @@ -0,0 +1 @@ +icon-webinars diff --git a/3.25.4-scylla/_static/img/icons/icon-whitepapers.svg b/3.25.4-scylla/_static/img/icons/icon-whitepapers.svg new file mode 100644 index 0000000000..3351e51d23 --- /dev/null +++ b/3.25.4-scylla/_static/img/icons/icon-whitepapers.svg @@ -0,0 +1 @@ +icon-whitepapers diff --git a/3.25.4-scylla/_static/img/icons/icon-workshop.svg b/3.25.4-scylla/_static/img/icons/icon-workshop.svg new file mode 100644 index 0000000000..5206e58e98 --- /dev/null +++ b/3.25.4-scylla/_static/img/icons/icon-workshop.svg @@ -0,0 +1 @@ + diff --git a/3.25.4-scylla/_static/img/logo-docs.svg b/3.25.4-scylla/_static/img/logo-docs.svg new file mode 100644 index 0000000000..4fff669cb6 --- /dev/null +++ b/3.25.4-scylla/_static/img/logo-docs.svg @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/3.25.4-scylla/_static/img/logo-scylla-horizontal-RGB.svg b/3.25.4-scylla/_static/img/logo-scylla-horizontal-RGB.svg new file mode 100644 index 0000000000..b5022d7c4d --- /dev/null +++ b/3.25.4-scylla/_static/img/logo-scylla-horizontal-RGB.svg @@ -0,0 +1,74 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/3.25.4-scylla/_static/img/mascots/404.jpg b/3.25.4-scylla/_static/img/mascots/404.jpg new file mode 100644 index 0000000000..769fa0889f Binary files /dev/null and b/3.25.4-scylla/_static/img/mascots/404.jpg differ diff --git a/3.25.4-scylla/_static/img/mascots/scylla-3monsters.png b/3.25.4-scylla/_static/img/mascots/scylla-3monsters.png new file mode 100644 index 0000000000..7c06d01674 Binary files /dev/null and b/3.25.4-scylla/_static/img/mascots/scylla-3monsters.png differ diff --git a/3.25.4-scylla/_static/img/mascots/scylla-advisor-crystal.png b/3.25.4-scylla/_static/img/mascots/scylla-advisor-crystal.png new file mode 100644 index 0000000000..d33fddd62f Binary files /dev/null and b/3.25.4-scylla/_static/img/mascots/scylla-advisor-crystal.png differ diff --git a/3.25.4-scylla/_static/img/mascots/scylla-alternator.svg b/3.25.4-scylla/_static/img/mascots/scylla-alternator.svg new file mode 100644 index 0000000000..0462f893d5 --- /dev/null +++ b/3.25.4-scylla/_static/img/mascots/scylla-alternator.svg @@ -0,0 +1 @@ +scylla-alternator diff --git a/3.25.4-scylla/_static/img/mascots/scylla-cloud.svg b/3.25.4-scylla/_static/img/mascots/scylla-cloud.svg new file mode 100644 index 0000000000..a6c6a26fc9 --- /dev/null +++ b/3.25.4-scylla/_static/img/mascots/scylla-cloud.svg @@ -0,0 +1 @@ +scylla-cloud diff --git a/3.25.4-scylla/_static/img/mascots/scylla-computer-3-monsters.png b/3.25.4-scylla/_static/img/mascots/scylla-computer-3-monsters.png new file mode 100644 index 0000000000..d0368a7027 Binary files /dev/null and b/3.25.4-scylla/_static/img/mascots/scylla-computer-3-monsters.png differ diff --git a/3.25.4-scylla/_static/img/mascots/scylla-computer-headset.png b/3.25.4-scylla/_static/img/mascots/scylla-computer-headset.png new file mode 100644 index 0000000000..0cdadaa216 Binary files /dev/null and b/3.25.4-scylla/_static/img/mascots/scylla-computer-headset.png differ diff --git a/3.25.4-scylla/_static/img/mascots/scylla-cup-number-one.png b/3.25.4-scylla/_static/img/mascots/scylla-cup-number-one.png new file mode 100644 index 0000000000..e889f4e368 Binary files /dev/null and b/3.25.4-scylla/_static/img/mascots/scylla-cup-number-one.png differ diff --git a/3.25.4-scylla/_static/img/mascots/scylla-docs.svg b/3.25.4-scylla/_static/img/mascots/scylla-docs.svg new file mode 100644 index 0000000000..a5bce950c2 --- /dev/null +++ b/3.25.4-scylla/_static/img/mascots/scylla-docs.svg @@ -0,0 +1 @@ +scylla-docs diff --git a/3.25.4-scylla/_static/img/mascots/scylla-drivers.svg b/3.25.4-scylla/_static/img/mascots/scylla-drivers.svg new file mode 100644 index 0000000000..6012e71679 --- /dev/null +++ b/3.25.4-scylla/_static/img/mascots/scylla-drivers.svg @@ -0,0 +1 @@ +scylla-manager diff --git a/3.25.4-scylla/_static/img/mascots/scylla-enterprise.svg b/3.25.4-scylla/_static/img/mascots/scylla-enterprise.svg new file mode 100644 index 0000000000..a1aa0b46ac --- /dev/null +++ b/3.25.4-scylla/_static/img/mascots/scylla-enterprise.svg @@ -0,0 +1 @@ +scylla-enterprise diff --git a/3.25.4-scylla/_static/img/mascots/scylla-forklift-boxes.png b/3.25.4-scylla/_static/img/mascots/scylla-forklift-boxes.png new file mode 100644 index 0000000000..f64c29e6c7 Binary files /dev/null and b/3.25.4-scylla/_static/img/mascots/scylla-forklift-boxes.png differ diff --git a/3.25.4-scylla/_static/img/mascots/scylla-forklift-migration.png b/3.25.4-scylla/_static/img/mascots/scylla-forklift-migration.png new file mode 100644 index 0000000000..d2f645c645 Binary files /dev/null and b/3.25.4-scylla/_static/img/mascots/scylla-forklift-migration.png differ diff --git a/3.25.4-scylla/_static/img/mascots/scylla-gear.png b/3.25.4-scylla/_static/img/mascots/scylla-gear.png new file mode 100644 index 0000000000..0f53b26afa Binary files /dev/null and b/3.25.4-scylla/_static/img/mascots/scylla-gear.png differ diff --git a/3.25.4-scylla/_static/img/mascots/scylla-hardhat.png b/3.25.4-scylla/_static/img/mascots/scylla-hardhat.png new file mode 100644 index 0000000000..630f2d9094 Binary files /dev/null and b/3.25.4-scylla/_static/img/mascots/scylla-hardhat.png differ diff --git a/3.25.4-scylla/_static/img/mascots/scylla-headband.png b/3.25.4-scylla/_static/img/mascots/scylla-headband.png new file mode 100644 index 0000000000..c87abe684d Binary files /dev/null and b/3.25.4-scylla/_static/img/mascots/scylla-headband.png differ diff --git a/3.25.4-scylla/_static/img/mascots/scylla-headset.png b/3.25.4-scylla/_static/img/mascots/scylla-headset.png new file mode 100644 index 0000000000..ba52cd223d Binary files /dev/null and b/3.25.4-scylla/_static/img/mascots/scylla-headset.png differ diff --git a/3.25.4-scylla/_static/img/mascots/scylla-hearts.png b/3.25.4-scylla/_static/img/mascots/scylla-hearts.png new file mode 100644 index 0000000000..cef08c8654 Binary files /dev/null and b/3.25.4-scylla/_static/img/mascots/scylla-hearts.png differ diff --git a/3.25.4-scylla/_static/img/mascots/scylla-looking-down.png b/3.25.4-scylla/_static/img/mascots/scylla-looking-down.png new file mode 100644 index 0000000000..75cccbfdf1 Binary files /dev/null and b/3.25.4-scylla/_static/img/mascots/scylla-looking-down.png differ diff --git a/3.25.4-scylla/_static/img/mascots/scylla-looking-up.png b/3.25.4-scylla/_static/img/mascots/scylla-looking-up.png new file mode 100644 index 0000000000..6f10405f21 Binary files /dev/null and b/3.25.4-scylla/_static/img/mascots/scylla-looking-up.png differ diff --git a/3.25.4-scylla/_static/img/mascots/scylla-magnifying-glass-fronting.png b/3.25.4-scylla/_static/img/mascots/scylla-magnifying-glass-fronting.png new file mode 100644 index 0000000000..e368cae169 Binary files /dev/null and b/3.25.4-scylla/_static/img/mascots/scylla-magnifying-glass-fronting.png differ diff --git a/3.25.4-scylla/_static/img/mascots/scylla-magnifying-glass.png b/3.25.4-scylla/_static/img/mascots/scylla-magnifying-glass.png new file mode 100644 index 0000000000..74ad669500 Binary files /dev/null and b/3.25.4-scylla/_static/img/mascots/scylla-magnifying-glass.png differ diff --git a/3.25.4-scylla/_static/img/mascots/scylla-manager.svg b/3.25.4-scylla/_static/img/mascots/scylla-manager.svg new file mode 100644 index 0000000000..6ba9ed937c --- /dev/null +++ b/3.25.4-scylla/_static/img/mascots/scylla-manager.svg @@ -0,0 +1 @@ +scylla-manager-2 diff --git a/3.25.4-scylla/_static/img/mascots/scylla-monitor.svg b/3.25.4-scylla/_static/img/mascots/scylla-monitor.svg new file mode 100644 index 0000000000..48bec7dde3 --- /dev/null +++ b/3.25.4-scylla/_static/img/mascots/scylla-monitor.svg @@ -0,0 +1 @@ +scylla-monitor diff --git a/3.25.4-scylla/_static/img/mascots/scylla-movement-fast.png b/3.25.4-scylla/_static/img/mascots/scylla-movement-fast.png new file mode 100644 index 0000000000..956d1dd0e2 Binary files /dev/null and b/3.25.4-scylla/_static/img/mascots/scylla-movement-fast.png differ diff --git a/3.25.4-scylla/_static/img/mascots/scylla-movement.png b/3.25.4-scylla/_static/img/mascots/scylla-movement.png new file mode 100644 index 0000000000..7ee2b04338 Binary files /dev/null and b/3.25.4-scylla/_static/img/mascots/scylla-movement.png differ diff --git a/3.25.4-scylla/_static/img/mascots/scylla-onpremise.png b/3.25.4-scylla/_static/img/mascots/scylla-onpremise.png new file mode 100644 index 0000000000..3b2dc8f1a2 Binary files /dev/null and b/3.25.4-scylla/_static/img/mascots/scylla-onpremise.png differ diff --git a/3.25.4-scylla/_static/img/mascots/scylla-opensource.svg b/3.25.4-scylla/_static/img/mascots/scylla-opensource.svg new file mode 100644 index 0000000000..299e9cb995 --- /dev/null +++ b/3.25.4-scylla/_static/img/mascots/scylla-opensource.svg @@ -0,0 +1 @@ +Plan de travail 1 diff --git a/3.25.4-scylla/_static/img/mascots/scylla-operator.svg b/3.25.4-scylla/_static/img/mascots/scylla-operator.svg new file mode 100644 index 0000000000..655a450b2a --- /dev/null +++ b/3.25.4-scylla/_static/img/mascots/scylla-operator.svg @@ -0,0 +1 @@ +scylla-operator diff --git a/3.25.4-scylla/_static/img/mascots/scylla-plugin.png b/3.25.4-scylla/_static/img/mascots/scylla-plugin.png new file mode 100644 index 0000000000..b28dc857cc Binary files /dev/null and b/3.25.4-scylla/_static/img/mascots/scylla-plugin.png differ diff --git a/3.25.4-scylla/_static/img/mascots/scylla-release-mascot.png b/3.25.4-scylla/_static/img/mascots/scylla-release-mascot.png new file mode 100644 index 0000000000..09342ac687 Binary files /dev/null and b/3.25.4-scylla/_static/img/mascots/scylla-release-mascot.png differ diff --git a/3.25.4-scylla/_static/img/mascots/scylla-repair.png b/3.25.4-scylla/_static/img/mascots/scylla-repair.png new file mode 100644 index 0000000000..9b4c613e70 Binary files /dev/null and b/3.25.4-scylla/_static/img/mascots/scylla-repair.png differ diff --git a/3.25.4-scylla/_static/img/mascots/scylla-server.png b/3.25.4-scylla/_static/img/mascots/scylla-server.png new file mode 100644 index 0000000000..96dc785298 Binary files /dev/null and b/3.25.4-scylla/_static/img/mascots/scylla-server.png differ diff --git a/3.25.4-scylla/_static/img/mascots/scylla-sleeping.png b/3.25.4-scylla/_static/img/mascots/scylla-sleeping.png new file mode 100644 index 0000000000..f88598e05a Binary files /dev/null and b/3.25.4-scylla/_static/img/mascots/scylla-sleeping.png differ diff --git a/3.25.4-scylla/_static/img/mascots/scylla-tall-measure.png b/3.25.4-scylla/_static/img/mascots/scylla-tall-measure.png new file mode 100644 index 0000000000..6f0ca146c0 Binary files /dev/null and b/3.25.4-scylla/_static/img/mascots/scylla-tall-measure.png differ diff --git a/3.25.4-scylla/_static/img/mascots/scylla-university.png b/3.25.4-scylla/_static/img/mascots/scylla-university.png new file mode 100644 index 0000000000..b3d0621193 Binary files /dev/null and b/3.25.4-scylla/_static/img/mascots/scylla-university.png differ diff --git a/3.25.4-scylla/_static/img/mascots/scylla-weights.png b/3.25.4-scylla/_static/img/mascots/scylla-weights.png new file mode 100644 index 0000000000..b070bb022c Binary files /dev/null and b/3.25.4-scylla/_static/img/mascots/scylla-weights.png differ diff --git a/3.25.4-scylla/_static/img/mascots/scylla-window-cleaning.png b/3.25.4-scylla/_static/img/mascots/scylla-window-cleaning.png new file mode 100644 index 0000000000..6a8b16a6b4 Binary files /dev/null and b/3.25.4-scylla/_static/img/mascots/scylla-window-cleaning.png differ diff --git a/3.25.4-scylla/_static/img/mascots/scylla-with-computer-2.png b/3.25.4-scylla/_static/img/mascots/scylla-with-computer-2.png new file mode 100644 index 0000000000..f3b8b2984f Binary files /dev/null and b/3.25.4-scylla/_static/img/mascots/scylla-with-computer-2.png differ diff --git a/3.25.4-scylla/_static/img/mascots/scylla-with-computer.png b/3.25.4-scylla/_static/img/mascots/scylla-with-computer.png new file mode 100644 index 0000000000..b38a6fbbe0 Binary files /dev/null and b/3.25.4-scylla/_static/img/mascots/scylla-with-computer.png differ diff --git a/3.25.4-scylla/_static/img/mascots/scylla-with-linux.png b/3.25.4-scylla/_static/img/mascots/scylla-with-linux.png new file mode 100644 index 0000000000..954bf13bc2 Binary files /dev/null and b/3.25.4-scylla/_static/img/mascots/scylla-with-linux.png differ diff --git a/3.25.4-scylla/_static/img/mascots/scylla-writting.png b/3.25.4-scylla/_static/img/mascots/scylla-writting.png new file mode 100644 index 0000000000..d35a13d380 Binary files /dev/null and b/3.25.4-scylla/_static/img/mascots/scylla-writting.png differ diff --git a/3.25.4-scylla/_static/img/menu.svg b/3.25.4-scylla/_static/img/menu.svg new file mode 100644 index 0000000000..30ea1d901e --- /dev/null +++ b/3.25.4-scylla/_static/img/menu.svg @@ -0,0 +1,3 @@ + + + diff --git a/3.25.4-scylla/_static/jquery-3.5.1.js b/3.25.4-scylla/_static/jquery-3.5.1.js new file mode 100644 index 0000000000..50937333b9 --- /dev/null +++ b/3.25.4-scylla/_static/jquery-3.5.1.js @@ -0,0 +1,10872 @@ +/*! + * jQuery JavaScript Library v3.5.1 + * https://jquery.com/ + * + * Includes Sizzle.js + * https://sizzlejs.com/ + * + * Copyright JS Foundation and other contributors + * Released under the MIT license + * https://jquery.org/license + * + * Date: 2020-05-04T22:49Z + */ +( function( global, factory ) { + + "use strict"; + + if ( typeof module === "object" && typeof module.exports === "object" ) { + + // For CommonJS and CommonJS-like environments where a proper `window` + // is present, execute the factory and get jQuery. + // For environments that do not have a `window` with a `document` + // (such as Node.js), expose a factory as module.exports. + // This accentuates the need for the creation of a real `window`. + // e.g. var jQuery = require("jquery")(window); + // See ticket #14549 for more info. + module.exports = global.document ? + factory( global, true ) : + function( w ) { + if ( !w.document ) { + throw new Error( "jQuery requires a window with a document" ); + } + return factory( w ); + }; + } else { + factory( global ); + } + +// Pass this if window is not defined yet +} )( typeof window !== "undefined" ? window : this, function( window, noGlobal ) { + +// Edge <= 12 - 13+, Firefox <=18 - 45+, IE 10 - 11, Safari 5.1 - 9+, iOS 6 - 9.1 +// throw exceptions when non-strict code (e.g., ASP.NET 4.5) accesses strict mode +// arguments.callee.caller (trac-13335). But as of jQuery 3.0 (2016), strict mode should be common +// enough that all such attempts are guarded in a try block. +"use strict"; + +var arr = []; + +var getProto = Object.getPrototypeOf; + +var slice = arr.slice; + +var flat = arr.flat ? function( array ) { + return arr.flat.call( array ); +} : function( array ) { + return arr.concat.apply( [], array ); +}; + + +var push = arr.push; + +var indexOf = arr.indexOf; + +var class2type = {}; + +var toString = class2type.toString; + +var hasOwn = class2type.hasOwnProperty; + +var fnToString = hasOwn.toString; + +var ObjectFunctionString = fnToString.call( Object ); + +var support = {}; + +var isFunction = function isFunction( obj ) { + + // Support: Chrome <=57, Firefox <=52 + // In some browsers, typeof returns "function" for HTML elements + // (i.e., `typeof document.createElement( "object" ) === "function"`). + // We don't want to classify *any* DOM node as a function. + return typeof obj === "function" && typeof obj.nodeType !== "number"; + }; + + +var isWindow = function isWindow( obj ) { + return obj != null && obj === obj.window; + }; + + +var document = window.document; + + + + var preservedScriptAttributes = { + type: true, + src: true, + nonce: true, + noModule: true + }; + + function DOMEval( code, node, doc ) { + doc = doc || document; + + var i, val, + script = doc.createElement( "script" ); + + script.text = code; + if ( node ) { + for ( i in preservedScriptAttributes ) { + + // Support: Firefox 64+, Edge 18+ + // Some browsers don't support the "nonce" property on scripts. + // On the other hand, just using `getAttribute` is not enough as + // the `nonce` attribute is reset to an empty string whenever it + // becomes browsing-context connected. + // See https://github.com/whatwg/html/issues/2369 + // See https://html.spec.whatwg.org/#nonce-attributes + // The `node.getAttribute` check was added for the sake of + // `jQuery.globalEval` so that it can fake a nonce-containing node + // via an object. + val = node[ i ] || node.getAttribute && node.getAttribute( i ); + if ( val ) { + script.setAttribute( i, val ); + } + } + } + doc.head.appendChild( script ).parentNode.removeChild( script ); + } + + +function toType( obj ) { + if ( obj == null ) { + return obj + ""; + } + + // Support: Android <=2.3 only (functionish RegExp) + return typeof obj === "object" || typeof obj === "function" ? + class2type[ toString.call( obj ) ] || "object" : + typeof obj; +} +/* global Symbol */ +// Defining this global in .eslintrc.json would create a danger of using the global +// unguarded in another place, it seems safer to define global only for this module + + + +var + version = "3.5.1", + + // Define a local copy of jQuery + jQuery = function( selector, context ) { + + // The jQuery object is actually just the init constructor 'enhanced' + // Need init if jQuery is called (just allow error to be thrown if not included) + return new jQuery.fn.init( selector, context ); + }; + +jQuery.fn = jQuery.prototype = { + + // The current version of jQuery being used + jquery: version, + + constructor: jQuery, + + // The default length of a jQuery object is 0 + length: 0, + + toArray: function() { + return slice.call( this ); + }, + + // Get the Nth element in the matched element set OR + // Get the whole matched element set as a clean array + get: function( num ) { + + // Return all the elements in a clean array + if ( num == null ) { + return slice.call( this ); + } + + // Return just the one element from the set + return num < 0 ? this[ num + this.length ] : this[ num ]; + }, + + // Take an array of elements and push it onto the stack + // (returning the new matched element set) + pushStack: function( elems ) { + + // Build a new jQuery matched element set + var ret = jQuery.merge( this.constructor(), elems ); + + // Add the old object onto the stack (as a reference) + ret.prevObject = this; + + // Return the newly-formed element set + return ret; + }, + + // Execute a callback for every element in the matched set. + each: function( callback ) { + return jQuery.each( this, callback ); + }, + + map: function( callback ) { + return this.pushStack( jQuery.map( this, function( elem, i ) { + return callback.call( elem, i, elem ); + } ) ); + }, + + slice: function() { + return this.pushStack( slice.apply( this, arguments ) ); + }, + + first: function() { + return this.eq( 0 ); + }, + + last: function() { + return this.eq( -1 ); + }, + + even: function() { + return this.pushStack( jQuery.grep( this, function( _elem, i ) { + return ( i + 1 ) % 2; + } ) ); + }, + + odd: function() { + return this.pushStack( jQuery.grep( this, function( _elem, i ) { + return i % 2; + } ) ); + }, + + eq: function( i ) { + var len = this.length, + j = +i + ( i < 0 ? len : 0 ); + return this.pushStack( j >= 0 && j < len ? [ this[ j ] ] : [] ); + }, + + end: function() { + return this.prevObject || this.constructor(); + }, + + // For internal use only. + // Behaves like an Array's method, not like a jQuery method. + push: push, + sort: arr.sort, + splice: arr.splice +}; + +jQuery.extend = jQuery.fn.extend = function() { + var options, name, src, copy, copyIsArray, clone, + target = arguments[ 0 ] || {}, + i = 1, + length = arguments.length, + deep = false; + + // Handle a deep copy situation + if ( typeof target === "boolean" ) { + deep = target; + + // Skip the boolean and the target + target = arguments[ i ] || {}; + i++; + } + + // Handle case when target is a string or something (possible in deep copy) + if ( typeof target !== "object" && !isFunction( target ) ) { + target = {}; + } + + // Extend jQuery itself if only one argument is passed + if ( i === length ) { + target = this; + i--; + } + + for ( ; i < length; i++ ) { + + // Only deal with non-null/undefined values + if ( ( options = arguments[ i ] ) != null ) { + + // Extend the base object + for ( name in options ) { + copy = options[ name ]; + + // Prevent Object.prototype pollution + // Prevent never-ending loop + if ( name === "__proto__" || target === copy ) { + continue; + } + + // Recurse if we're merging plain objects or arrays + if ( deep && copy && ( jQuery.isPlainObject( copy ) || + ( copyIsArray = Array.isArray( copy ) ) ) ) { + src = target[ name ]; + + // Ensure proper type for the source value + if ( copyIsArray && !Array.isArray( src ) ) { + clone = []; + } else if ( !copyIsArray && !jQuery.isPlainObject( src ) ) { + clone = {}; + } else { + clone = src; + } + copyIsArray = false; + + // Never move original objects, clone them + target[ name ] = jQuery.extend( deep, clone, copy ); + + // Don't bring in undefined values + } else if ( copy !== undefined ) { + target[ name ] = copy; + } + } + } + } + + // Return the modified object + return target; +}; + +jQuery.extend( { + + // Unique for each copy of jQuery on the page + expando: "jQuery" + ( version + Math.random() ).replace( /\D/g, "" ), + + // Assume jQuery is ready without the ready module + isReady: true, + + error: function( msg ) { + throw new Error( msg ); + }, + + noop: function() {}, + + isPlainObject: function( obj ) { + var proto, Ctor; + + // Detect obvious negatives + // Use toString instead of jQuery.type to catch host objects + if ( !obj || toString.call( obj ) !== "[object Object]" ) { + return false; + } + + proto = getProto( obj ); + + // Objects with no prototype (e.g., `Object.create( null )`) are plain + if ( !proto ) { + return true; + } + + // Objects with prototype are plain iff they were constructed by a global Object function + Ctor = hasOwn.call( proto, "constructor" ) && proto.constructor; + return typeof Ctor === "function" && fnToString.call( Ctor ) === ObjectFunctionString; + }, + + isEmptyObject: function( obj ) { + var name; + + for ( name in obj ) { + return false; + } + return true; + }, + + // Evaluates a script in a provided context; falls back to the global one + // if not specified. + globalEval: function( code, options, doc ) { + DOMEval( code, { nonce: options && options.nonce }, doc ); + }, + + each: function( obj, callback ) { + var length, i = 0; + + if ( isArrayLike( obj ) ) { + length = obj.length; + for ( ; i < length; i++ ) { + if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) { + break; + } + } + } else { + for ( i in obj ) { + if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) { + break; + } + } + } + + return obj; + }, + + // results is for internal usage only + makeArray: function( arr, results ) { + var ret = results || []; + + if ( arr != null ) { + if ( isArrayLike( Object( arr ) ) ) { + jQuery.merge( ret, + typeof arr === "string" ? + [ arr ] : arr + ); + } else { + push.call( ret, arr ); + } + } + + return ret; + }, + + inArray: function( elem, arr, i ) { + return arr == null ? -1 : indexOf.call( arr, elem, i ); + }, + + // Support: Android <=4.0 only, PhantomJS 1 only + // push.apply(_, arraylike) throws on ancient WebKit + merge: function( first, second ) { + var len = +second.length, + j = 0, + i = first.length; + + for ( ; j < len; j++ ) { + first[ i++ ] = second[ j ]; + } + + first.length = i; + + return first; + }, + + grep: function( elems, callback, invert ) { + var callbackInverse, + matches = [], + i = 0, + length = elems.length, + callbackExpect = !invert; + + // Go through the array, only saving the items + // that pass the validator function + for ( ; i < length; i++ ) { + callbackInverse = !callback( elems[ i ], i ); + if ( callbackInverse !== callbackExpect ) { + matches.push( elems[ i ] ); + } + } + + return matches; + }, + + // arg is for internal usage only + map: function( elems, callback, arg ) { + var length, value, + i = 0, + ret = []; + + // Go through the array, translating each of the items to their new values + if ( isArrayLike( elems ) ) { + length = elems.length; + for ( ; i < length; i++ ) { + value = callback( elems[ i ], i, arg ); + + if ( value != null ) { + ret.push( value ); + } + } + + // Go through every key on the object, + } else { + for ( i in elems ) { + value = callback( elems[ i ], i, arg ); + + if ( value != null ) { + ret.push( value ); + } + } + } + + // Flatten any nested arrays + return flat( ret ); + }, + + // A global GUID counter for objects + guid: 1, + + // jQuery.support is not used in Core but other projects attach their + // properties to it so it needs to exist. + support: support +} ); + +if ( typeof Symbol === "function" ) { + jQuery.fn[ Symbol.iterator ] = arr[ Symbol.iterator ]; +} + +// Populate the class2type map +jQuery.each( "Boolean Number String Function Array Date RegExp Object Error Symbol".split( " " ), +function( _i, name ) { + class2type[ "[object " + name + "]" ] = name.toLowerCase(); +} ); + +function isArrayLike( obj ) { + + // Support: real iOS 8.2 only (not reproducible in simulator) + // `in` check used to prevent JIT error (gh-2145) + // hasOwn isn't used here due to false negatives + // regarding Nodelist length in IE + var length = !!obj && "length" in obj && obj.length, + type = toType( obj ); + + if ( isFunction( obj ) || isWindow( obj ) ) { + return false; + } + + return type === "array" || length === 0 || + typeof length === "number" && length > 0 && ( length - 1 ) in obj; +} +var Sizzle = +/*! + * Sizzle CSS Selector Engine v2.3.5 + * https://sizzlejs.com/ + * + * Copyright JS Foundation and other contributors + * Released under the MIT license + * https://js.foundation/ + * + * Date: 2020-03-14 + */ +( function( window ) { +var i, + support, + Expr, + getText, + isXML, + tokenize, + compile, + select, + outermostContext, + sortInput, + hasDuplicate, + + // Local document vars + setDocument, + document, + docElem, + documentIsHTML, + rbuggyQSA, + rbuggyMatches, + matches, + contains, + + // Instance-specific data + expando = "sizzle" + 1 * new Date(), + preferredDoc = window.document, + dirruns = 0, + done = 0, + classCache = createCache(), + tokenCache = createCache(), + compilerCache = createCache(), + nonnativeSelectorCache = createCache(), + sortOrder = function( a, b ) { + if ( a === b ) { + hasDuplicate = true; + } + return 0; + }, + + // Instance methods + hasOwn = ( {} ).hasOwnProperty, + arr = [], + pop = arr.pop, + pushNative = arr.push, + push = arr.push, + slice = arr.slice, + + // Use a stripped-down indexOf as it's faster than native + // https://jsperf.com/thor-indexof-vs-for/5 + indexOf = function( list, elem ) { + var i = 0, + len = list.length; + for ( ; i < len; i++ ) { + if ( list[ i ] === elem ) { + return i; + } + } + return -1; + }, + + booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|" + + "ismap|loop|multiple|open|readonly|required|scoped", + + // Regular expressions + + // http://www.w3.org/TR/css3-selectors/#whitespace + whitespace = "[\\x20\\t\\r\\n\\f]", + + // https://www.w3.org/TR/css-syntax-3/#ident-token-diagram + identifier = "(?:\\\\[\\da-fA-F]{1,6}" + whitespace + + "?|\\\\[^\\r\\n\\f]|[\\w-]|[^\0-\\x7f])+", + + // Attribute selectors: http://www.w3.org/TR/selectors/#attribute-selectors + attributes = "\\[" + whitespace + "*(" + identifier + ")(?:" + whitespace + + + // Operator (capture 2) + "*([*^$|!~]?=)" + whitespace + + + // "Attribute values must be CSS identifiers [capture 5] + // or strings [capture 3 or capture 4]" + "*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|(" + identifier + "))|)" + + whitespace + "*\\]", + + pseudos = ":(" + identifier + ")(?:\\((" + + + // To reduce the number of selectors needing tokenize in the preFilter, prefer arguments: + // 1. quoted (capture 3; capture 4 or capture 5) + "('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|" + + + // 2. simple (capture 6) + "((?:\\\\.|[^\\\\()[\\]]|" + attributes + ")*)|" + + + // 3. anything else (capture 2) + ".*" + + ")\\)|)", + + // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter + rwhitespace = new RegExp( whitespace + "+", "g" ), + rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + + whitespace + "+$", "g" ), + + rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ), + rcombinators = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + + "*" ), + rdescend = new RegExp( whitespace + "|>" ), + + rpseudo = new RegExp( pseudos ), + ridentifier = new RegExp( "^" + identifier + "$" ), + + matchExpr = { + "ID": new RegExp( "^#(" + identifier + ")" ), + "CLASS": new RegExp( "^\\.(" + identifier + ")" ), + "TAG": new RegExp( "^(" + identifier + "|[*])" ), + "ATTR": new RegExp( "^" + attributes ), + "PSEUDO": new RegExp( "^" + pseudos ), + "CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + + whitespace + "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + + whitespace + "*(\\d+)|))" + whitespace + "*\\)|)", "i" ), + "bool": new RegExp( "^(?:" + booleans + ")$", "i" ), + + // For use in libraries implementing .is() + // We use this for POS matching in `select` + "needsContext": new RegExp( "^" + whitespace + + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" + whitespace + + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" ) + }, + + rhtml = /HTML$/i, + rinputs = /^(?:input|select|textarea|button)$/i, + rheader = /^h\d$/i, + + rnative = /^[^{]+\{\s*\[native \w/, + + // Easily-parseable/retrievable ID or TAG or CLASS selectors + rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/, + + rsibling = /[+~]/, + + // CSS escapes + // http://www.w3.org/TR/CSS21/syndata.html#escaped-characters + runescape = new RegExp( "\\\\[\\da-fA-F]{1,6}" + whitespace + "?|\\\\([^\\r\\n\\f])", "g" ), + funescape = function( escape, nonHex ) { + var high = "0x" + escape.slice( 1 ) - 0x10000; + + return nonHex ? + + // Strip the backslash prefix from a non-hex escape sequence + nonHex : + + // Replace a hexadecimal escape sequence with the encoded Unicode code point + // Support: IE <=11+ + // For values outside the Basic Multilingual Plane (BMP), manually construct a + // surrogate pair + high < 0 ? + String.fromCharCode( high + 0x10000 ) : + String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 ); + }, + + // CSS string/identifier serialization + // https://drafts.csswg.org/cssom/#common-serializing-idioms + rcssescape = /([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g, + fcssescape = function( ch, asCodePoint ) { + if ( asCodePoint ) { + + // U+0000 NULL becomes U+FFFD REPLACEMENT CHARACTER + if ( ch === "\0" ) { + return "\uFFFD"; + } + + // Control characters and (dependent upon position) numbers get escaped as code points + return ch.slice( 0, -1 ) + "\\" + + ch.charCodeAt( ch.length - 1 ).toString( 16 ) + " "; + } + + // Other potentially-special ASCII characters get backslash-escaped + return "\\" + ch; + }, + + // Used for iframes + // See setDocument() + // Removing the function wrapper causes a "Permission Denied" + // error in IE + unloadHandler = function() { + setDocument(); + }, + + inDisabledFieldset = addCombinator( + function( elem ) { + return elem.disabled === true && elem.nodeName.toLowerCase() === "fieldset"; + }, + { dir: "parentNode", next: "legend" } + ); + +// Optimize for push.apply( _, NodeList ) +try { + push.apply( + ( arr = slice.call( preferredDoc.childNodes ) ), + preferredDoc.childNodes + ); + + // Support: Android<4.0 + // Detect silently failing push.apply + // eslint-disable-next-line no-unused-expressions + arr[ preferredDoc.childNodes.length ].nodeType; +} catch ( e ) { + push = { apply: arr.length ? + + // Leverage slice if possible + function( target, els ) { + pushNative.apply( target, slice.call( els ) ); + } : + + // Support: IE<9 + // Otherwise append directly + function( target, els ) { + var j = target.length, + i = 0; + + // Can't trust NodeList.length + while ( ( target[ j++ ] = els[ i++ ] ) ) {} + target.length = j - 1; + } + }; +} + +function Sizzle( selector, context, results, seed ) { + var m, i, elem, nid, match, groups, newSelector, + newContext = context && context.ownerDocument, + + // nodeType defaults to 9, since context defaults to document + nodeType = context ? context.nodeType : 9; + + results = results || []; + + // Return early from calls with invalid selector or context + if ( typeof selector !== "string" || !selector || + nodeType !== 1 && nodeType !== 9 && nodeType !== 11 ) { + + return results; + } + + // Try to shortcut find operations (as opposed to filters) in HTML documents + if ( !seed ) { + setDocument( context ); + context = context || document; + + if ( documentIsHTML ) { + + // If the selector is sufficiently simple, try using a "get*By*" DOM method + // (excepting DocumentFragment context, where the methods don't exist) + if ( nodeType !== 11 && ( match = rquickExpr.exec( selector ) ) ) { + + // ID selector + if ( ( m = match[ 1 ] ) ) { + + // Document context + if ( nodeType === 9 ) { + if ( ( elem = context.getElementById( m ) ) ) { + + // Support: IE, Opera, Webkit + // TODO: identify versions + // getElementById can match elements by name instead of ID + if ( elem.id === m ) { + results.push( elem ); + return results; + } + } else { + return results; + } + + // Element context + } else { + + // Support: IE, Opera, Webkit + // TODO: identify versions + // getElementById can match elements by name instead of ID + if ( newContext && ( elem = newContext.getElementById( m ) ) && + contains( context, elem ) && + elem.id === m ) { + + results.push( elem ); + return results; + } + } + + // Type selector + } else if ( match[ 2 ] ) { + push.apply( results, context.getElementsByTagName( selector ) ); + return results; + + // Class selector + } else if ( ( m = match[ 3 ] ) && support.getElementsByClassName && + context.getElementsByClassName ) { + + push.apply( results, context.getElementsByClassName( m ) ); + return results; + } + } + + // Take advantage of querySelectorAll + if ( support.qsa && + !nonnativeSelectorCache[ selector + " " ] && + ( !rbuggyQSA || !rbuggyQSA.test( selector ) ) && + + // Support: IE 8 only + // Exclude object elements + ( nodeType !== 1 || context.nodeName.toLowerCase() !== "object" ) ) { + + newSelector = selector; + newContext = context; + + // qSA considers elements outside a scoping root when evaluating child or + // descendant combinators, which is not what we want. + // In such cases, we work around the behavior by prefixing every selector in the + // list with an ID selector referencing the scope context. + // The technique has to be used as well when a leading combinator is used + // as such selectors are not recognized by querySelectorAll. + // Thanks to Andrew Dupont for this technique. + if ( nodeType === 1 && + ( rdescend.test( selector ) || rcombinators.test( selector ) ) ) { + + // Expand context for sibling selectors + newContext = rsibling.test( selector ) && testContext( context.parentNode ) || + context; + + // We can use :scope instead of the ID hack if the browser + // supports it & if we're not changing the context. + if ( newContext !== context || !support.scope ) { + + // Capture the context ID, setting it first if necessary + if ( ( nid = context.getAttribute( "id" ) ) ) { + nid = nid.replace( rcssescape, fcssescape ); + } else { + context.setAttribute( "id", ( nid = expando ) ); + } + } + + // Prefix every selector in the list + groups = tokenize( selector ); + i = groups.length; + while ( i-- ) { + groups[ i ] = ( nid ? "#" + nid : ":scope" ) + " " + + toSelector( groups[ i ] ); + } + newSelector = groups.join( "," ); + } + + try { + push.apply( results, + newContext.querySelectorAll( newSelector ) + ); + return results; + } catch ( qsaError ) { + nonnativeSelectorCache( selector, true ); + } finally { + if ( nid === expando ) { + context.removeAttribute( "id" ); + } + } + } + } + } + + // All others + return select( selector.replace( rtrim, "$1" ), context, results, seed ); +} + +/** + * Create key-value caches of limited size + * @returns {function(string, object)} Returns the Object data after storing it on itself with + * property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength) + * deleting the oldest entry + */ +function createCache() { + var keys = []; + + function cache( key, value ) { + + // Use (key + " ") to avoid collision with native prototype properties (see Issue #157) + if ( keys.push( key + " " ) > Expr.cacheLength ) { + + // Only keep the most recent entries + delete cache[ keys.shift() ]; + } + return ( cache[ key + " " ] = value ); + } + return cache; +} + +/** + * Mark a function for special use by Sizzle + * @param {Function} fn The function to mark + */ +function markFunction( fn ) { + fn[ expando ] = true; + return fn; +} + +/** + * Support testing using an element + * @param {Function} fn Passed the created element and returns a boolean result + */ +function assert( fn ) { + var el = document.createElement( "fieldset" ); + + try { + return !!fn( el ); + } catch ( e ) { + return false; + } finally { + + // Remove from its parent by default + if ( el.parentNode ) { + el.parentNode.removeChild( el ); + } + + // release memory in IE + el = null; + } +} + +/** + * Adds the same handler for all of the specified attrs + * @param {String} attrs Pipe-separated list of attributes + * @param {Function} handler The method that will be applied + */ +function addHandle( attrs, handler ) { + var arr = attrs.split( "|" ), + i = arr.length; + + while ( i-- ) { + Expr.attrHandle[ arr[ i ] ] = handler; + } +} + +/** + * Checks document order of two siblings + * @param {Element} a + * @param {Element} b + * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b + */ +function siblingCheck( a, b ) { + var cur = b && a, + diff = cur && a.nodeType === 1 && b.nodeType === 1 && + a.sourceIndex - b.sourceIndex; + + // Use IE sourceIndex if available on both nodes + if ( diff ) { + return diff; + } + + // Check if b follows a + if ( cur ) { + while ( ( cur = cur.nextSibling ) ) { + if ( cur === b ) { + return -1; + } + } + } + + return a ? 1 : -1; +} + +/** + * Returns a function to use in pseudos for input types + * @param {String} type + */ +function createInputPseudo( type ) { + return function( elem ) { + var name = elem.nodeName.toLowerCase(); + return name === "input" && elem.type === type; + }; +} + +/** + * Returns a function to use in pseudos for buttons + * @param {String} type + */ +function createButtonPseudo( type ) { + return function( elem ) { + var name = elem.nodeName.toLowerCase(); + return ( name === "input" || name === "button" ) && elem.type === type; + }; +} + +/** + * Returns a function to use in pseudos for :enabled/:disabled + * @param {Boolean} disabled true for :disabled; false for :enabled + */ +function createDisabledPseudo( disabled ) { + + // Known :disabled false positives: fieldset[disabled] > legend:nth-of-type(n+2) :can-disable + return function( elem ) { + + // Only certain elements can match :enabled or :disabled + // https://html.spec.whatwg.org/multipage/scripting.html#selector-enabled + // https://html.spec.whatwg.org/multipage/scripting.html#selector-disabled + if ( "form" in elem ) { + + // Check for inherited disabledness on relevant non-disabled elements: + // * listed form-associated elements in a disabled fieldset + // https://html.spec.whatwg.org/multipage/forms.html#category-listed + // https://html.spec.whatwg.org/multipage/forms.html#concept-fe-disabled + // * option elements in a disabled optgroup + // https://html.spec.whatwg.org/multipage/forms.html#concept-option-disabled + // All such elements have a "form" property. + if ( elem.parentNode && elem.disabled === false ) { + + // Option elements defer to a parent optgroup if present + if ( "label" in elem ) { + if ( "label" in elem.parentNode ) { + return elem.parentNode.disabled === disabled; + } else { + return elem.disabled === disabled; + } + } + + // Support: IE 6 - 11 + // Use the isDisabled shortcut property to check for disabled fieldset ancestors + return elem.isDisabled === disabled || + + // Where there is no isDisabled, check manually + /* jshint -W018 */ + elem.isDisabled !== !disabled && + inDisabledFieldset( elem ) === disabled; + } + + return elem.disabled === disabled; + + // Try to winnow out elements that can't be disabled before trusting the disabled property. + // Some victims get caught in our net (label, legend, menu, track), but it shouldn't + // even exist on them, let alone have a boolean value. + } else if ( "label" in elem ) { + return elem.disabled === disabled; + } + + // Remaining elements are neither :enabled nor :disabled + return false; + }; +} + +/** + * Returns a function to use in pseudos for positionals + * @param {Function} fn + */ +function createPositionalPseudo( fn ) { + return markFunction( function( argument ) { + argument = +argument; + return markFunction( function( seed, matches ) { + var j, + matchIndexes = fn( [], seed.length, argument ), + i = matchIndexes.length; + + // Match elements found at the specified indexes + while ( i-- ) { + if ( seed[ ( j = matchIndexes[ i ] ) ] ) { + seed[ j ] = !( matches[ j ] = seed[ j ] ); + } + } + } ); + } ); +} + +/** + * Checks a node for validity as a Sizzle context + * @param {Element|Object=} context + * @returns {Element|Object|Boolean} The input node if acceptable, otherwise a falsy value + */ +function testContext( context ) { + return context && typeof context.getElementsByTagName !== "undefined" && context; +} + +// Expose support vars for convenience +support = Sizzle.support = {}; + +/** + * Detects XML nodes + * @param {Element|Object} elem An element or a document + * @returns {Boolean} True iff elem is a non-HTML XML node + */ +isXML = Sizzle.isXML = function( elem ) { + var namespace = elem.namespaceURI, + docElem = ( elem.ownerDocument || elem ).documentElement; + + // Support: IE <=8 + // Assume HTML when documentElement doesn't yet exist, such as inside loading iframes + // https://bugs.jquery.com/ticket/4833 + return !rhtml.test( namespace || docElem && docElem.nodeName || "HTML" ); +}; + +/** + * Sets document-related variables once based on the current document + * @param {Element|Object} [doc] An element or document object to use to set the document + * @returns {Object} Returns the current document + */ +setDocument = Sizzle.setDocument = function( node ) { + var hasCompare, subWindow, + doc = node ? node.ownerDocument || node : preferredDoc; + + // Return early if doc is invalid or already selected + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( doc == document || doc.nodeType !== 9 || !doc.documentElement ) { + return document; + } + + // Update global variables + document = doc; + docElem = document.documentElement; + documentIsHTML = !isXML( document ); + + // Support: IE 9 - 11+, Edge 12 - 18+ + // Accessing iframe documents after unload throws "permission denied" errors (jQuery #13936) + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( preferredDoc != document && + ( subWindow = document.defaultView ) && subWindow.top !== subWindow ) { + + // Support: IE 11, Edge + if ( subWindow.addEventListener ) { + subWindow.addEventListener( "unload", unloadHandler, false ); + + // Support: IE 9 - 10 only + } else if ( subWindow.attachEvent ) { + subWindow.attachEvent( "onunload", unloadHandler ); + } + } + + // Support: IE 8 - 11+, Edge 12 - 18+, Chrome <=16 - 25 only, Firefox <=3.6 - 31 only, + // Safari 4 - 5 only, Opera <=11.6 - 12.x only + // IE/Edge & older browsers don't support the :scope pseudo-class. + // Support: Safari 6.0 only + // Safari 6.0 supports :scope but it's an alias of :root there. + support.scope = assert( function( el ) { + docElem.appendChild( el ).appendChild( document.createElement( "div" ) ); + return typeof el.querySelectorAll !== "undefined" && + !el.querySelectorAll( ":scope fieldset div" ).length; + } ); + + /* Attributes + ---------------------------------------------------------------------- */ + + // Support: IE<8 + // Verify that getAttribute really returns attributes and not properties + // (excepting IE8 booleans) + support.attributes = assert( function( el ) { + el.className = "i"; + return !el.getAttribute( "className" ); + } ); + + /* getElement(s)By* + ---------------------------------------------------------------------- */ + + // Check if getElementsByTagName("*") returns only elements + support.getElementsByTagName = assert( function( el ) { + el.appendChild( document.createComment( "" ) ); + return !el.getElementsByTagName( "*" ).length; + } ); + + // Support: IE<9 + support.getElementsByClassName = rnative.test( document.getElementsByClassName ); + + // Support: IE<10 + // Check if getElementById returns elements by name + // The broken getElementById methods don't pick up programmatically-set names, + // so use a roundabout getElementsByName test + support.getById = assert( function( el ) { + docElem.appendChild( el ).id = expando; + return !document.getElementsByName || !document.getElementsByName( expando ).length; + } ); + + // ID filter and find + if ( support.getById ) { + Expr.filter[ "ID" ] = function( id ) { + var attrId = id.replace( runescape, funescape ); + return function( elem ) { + return elem.getAttribute( "id" ) === attrId; + }; + }; + Expr.find[ "ID" ] = function( id, context ) { + if ( typeof context.getElementById !== "undefined" && documentIsHTML ) { + var elem = context.getElementById( id ); + return elem ? [ elem ] : []; + } + }; + } else { + Expr.filter[ "ID" ] = function( id ) { + var attrId = id.replace( runescape, funescape ); + return function( elem ) { + var node = typeof elem.getAttributeNode !== "undefined" && + elem.getAttributeNode( "id" ); + return node && node.value === attrId; + }; + }; + + // Support: IE 6 - 7 only + // getElementById is not reliable as a find shortcut + Expr.find[ "ID" ] = function( id, context ) { + if ( typeof context.getElementById !== "undefined" && documentIsHTML ) { + var node, i, elems, + elem = context.getElementById( id ); + + if ( elem ) { + + // Verify the id attribute + node = elem.getAttributeNode( "id" ); + if ( node && node.value === id ) { + return [ elem ]; + } + + // Fall back on getElementsByName + elems = context.getElementsByName( id ); + i = 0; + while ( ( elem = elems[ i++ ] ) ) { + node = elem.getAttributeNode( "id" ); + if ( node && node.value === id ) { + return [ elem ]; + } + } + } + + return []; + } + }; + } + + // Tag + Expr.find[ "TAG" ] = support.getElementsByTagName ? + function( tag, context ) { + if ( typeof context.getElementsByTagName !== "undefined" ) { + return context.getElementsByTagName( tag ); + + // DocumentFragment nodes don't have gEBTN + } else if ( support.qsa ) { + return context.querySelectorAll( tag ); + } + } : + + function( tag, context ) { + var elem, + tmp = [], + i = 0, + + // By happy coincidence, a (broken) gEBTN appears on DocumentFragment nodes too + results = context.getElementsByTagName( tag ); + + // Filter out possible comments + if ( tag === "*" ) { + while ( ( elem = results[ i++ ] ) ) { + if ( elem.nodeType === 1 ) { + tmp.push( elem ); + } + } + + return tmp; + } + return results; + }; + + // Class + Expr.find[ "CLASS" ] = support.getElementsByClassName && function( className, context ) { + if ( typeof context.getElementsByClassName !== "undefined" && documentIsHTML ) { + return context.getElementsByClassName( className ); + } + }; + + /* QSA/matchesSelector + ---------------------------------------------------------------------- */ + + // QSA and matchesSelector support + + // matchesSelector(:active) reports false when true (IE9/Opera 11.5) + rbuggyMatches = []; + + // qSa(:focus) reports false when true (Chrome 21) + // We allow this because of a bug in IE8/9 that throws an error + // whenever `document.activeElement` is accessed on an iframe + // So, we allow :focus to pass through QSA all the time to avoid the IE error + // See https://bugs.jquery.com/ticket/13378 + rbuggyQSA = []; + + if ( ( support.qsa = rnative.test( document.querySelectorAll ) ) ) { + + // Build QSA regex + // Regex strategy adopted from Diego Perini + assert( function( el ) { + + var input; + + // Select is set to empty string on purpose + // This is to test IE's treatment of not explicitly + // setting a boolean content attribute, + // since its presence should be enough + // https://bugs.jquery.com/ticket/12359 + docElem.appendChild( el ).innerHTML = "" + + ""; + + // Support: IE8, Opera 11-12.16 + // Nothing should be selected when empty strings follow ^= or $= or *= + // The test attribute must be unknown in Opera but "safe" for WinRT + // https://msdn.microsoft.com/en-us/library/ie/hh465388.aspx#attribute_section + if ( el.querySelectorAll( "[msallowcapture^='']" ).length ) { + rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:''|\"\")" ); + } + + // Support: IE8 + // Boolean attributes and "value" are not treated correctly + if ( !el.querySelectorAll( "[selected]" ).length ) { + rbuggyQSA.push( "\\[" + whitespace + "*(?:value|" + booleans + ")" ); + } + + // Support: Chrome<29, Android<4.4, Safari<7.0+, iOS<7.0+, PhantomJS<1.9.8+ + if ( !el.querySelectorAll( "[id~=" + expando + "-]" ).length ) { + rbuggyQSA.push( "~=" ); + } + + // Support: IE 11+, Edge 15 - 18+ + // IE 11/Edge don't find elements on a `[name='']` query in some cases. + // Adding a temporary attribute to the document before the selection works + // around the issue. + // Interestingly, IE 10 & older don't seem to have the issue. + input = document.createElement( "input" ); + input.setAttribute( "name", "" ); + el.appendChild( input ); + if ( !el.querySelectorAll( "[name='']" ).length ) { + rbuggyQSA.push( "\\[" + whitespace + "*name" + whitespace + "*=" + + whitespace + "*(?:''|\"\")" ); + } + + // Webkit/Opera - :checked should return selected option elements + // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked + // IE8 throws error here and will not see later tests + if ( !el.querySelectorAll( ":checked" ).length ) { + rbuggyQSA.push( ":checked" ); + } + + // Support: Safari 8+, iOS 8+ + // https://bugs.webkit.org/show_bug.cgi?id=136851 + // In-page `selector#id sibling-combinator selector` fails + if ( !el.querySelectorAll( "a#" + expando + "+*" ).length ) { + rbuggyQSA.push( ".#.+[+~]" ); + } + + // Support: Firefox <=3.6 - 5 only + // Old Firefox doesn't throw on a badly-escaped identifier. + el.querySelectorAll( "\\\f" ); + rbuggyQSA.push( "[\\r\\n\\f]" ); + } ); + + assert( function( el ) { + el.innerHTML = "" + + ""; + + // Support: Windows 8 Native Apps + // The type and name attributes are restricted during .innerHTML assignment + var input = document.createElement( "input" ); + input.setAttribute( "type", "hidden" ); + el.appendChild( input ).setAttribute( "name", "D" ); + + // Support: IE8 + // Enforce case-sensitivity of name attribute + if ( el.querySelectorAll( "[name=d]" ).length ) { + rbuggyQSA.push( "name" + whitespace + "*[*^$|!~]?=" ); + } + + // FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled) + // IE8 throws error here and will not see later tests + if ( el.querySelectorAll( ":enabled" ).length !== 2 ) { + rbuggyQSA.push( ":enabled", ":disabled" ); + } + + // Support: IE9-11+ + // IE's :disabled selector does not pick up the children of disabled fieldsets + docElem.appendChild( el ).disabled = true; + if ( el.querySelectorAll( ":disabled" ).length !== 2 ) { + rbuggyQSA.push( ":enabled", ":disabled" ); + } + + // Support: Opera 10 - 11 only + // Opera 10-11 does not throw on post-comma invalid pseudos + el.querySelectorAll( "*,:x" ); + rbuggyQSA.push( ",.*:" ); + } ); + } + + if ( ( support.matchesSelector = rnative.test( ( matches = docElem.matches || + docElem.webkitMatchesSelector || + docElem.mozMatchesSelector || + docElem.oMatchesSelector || + docElem.msMatchesSelector ) ) ) ) { + + assert( function( el ) { + + // Check to see if it's possible to do matchesSelector + // on a disconnected node (IE 9) + support.disconnectedMatch = matches.call( el, "*" ); + + // This should fail with an exception + // Gecko does not error, returns false instead + matches.call( el, "[s!='']:x" ); + rbuggyMatches.push( "!=", pseudos ); + } ); + } + + rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join( "|" ) ); + rbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join( "|" ) ); + + /* Contains + ---------------------------------------------------------------------- */ + hasCompare = rnative.test( docElem.compareDocumentPosition ); + + // Element contains another + // Purposefully self-exclusive + // As in, an element does not contain itself + contains = hasCompare || rnative.test( docElem.contains ) ? + function( a, b ) { + var adown = a.nodeType === 9 ? a.documentElement : a, + bup = b && b.parentNode; + return a === bup || !!( bup && bup.nodeType === 1 && ( + adown.contains ? + adown.contains( bup ) : + a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16 + ) ); + } : + function( a, b ) { + if ( b ) { + while ( ( b = b.parentNode ) ) { + if ( b === a ) { + return true; + } + } + } + return false; + }; + + /* Sorting + ---------------------------------------------------------------------- */ + + // Document order sorting + sortOrder = hasCompare ? + function( a, b ) { + + // Flag for duplicate removal + if ( a === b ) { + hasDuplicate = true; + return 0; + } + + // Sort on method existence if only one input has compareDocumentPosition + var compare = !a.compareDocumentPosition - !b.compareDocumentPosition; + if ( compare ) { + return compare; + } + + // Calculate position if both inputs belong to the same document + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + compare = ( a.ownerDocument || a ) == ( b.ownerDocument || b ) ? + a.compareDocumentPosition( b ) : + + // Otherwise we know they are disconnected + 1; + + // Disconnected nodes + if ( compare & 1 || + ( !support.sortDetached && b.compareDocumentPosition( a ) === compare ) ) { + + // Choose the first element that is related to our preferred document + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( a == document || a.ownerDocument == preferredDoc && + contains( preferredDoc, a ) ) { + return -1; + } + + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( b == document || b.ownerDocument == preferredDoc && + contains( preferredDoc, b ) ) { + return 1; + } + + // Maintain original order + return sortInput ? + ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) : + 0; + } + + return compare & 4 ? -1 : 1; + } : + function( a, b ) { + + // Exit early if the nodes are identical + if ( a === b ) { + hasDuplicate = true; + return 0; + } + + var cur, + i = 0, + aup = a.parentNode, + bup = b.parentNode, + ap = [ a ], + bp = [ b ]; + + // Parentless nodes are either documents or disconnected + if ( !aup || !bup ) { + + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + /* eslint-disable eqeqeq */ + return a == document ? -1 : + b == document ? 1 : + /* eslint-enable eqeqeq */ + aup ? -1 : + bup ? 1 : + sortInput ? + ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) : + 0; + + // If the nodes are siblings, we can do a quick check + } else if ( aup === bup ) { + return siblingCheck( a, b ); + } + + // Otherwise we need full lists of their ancestors for comparison + cur = a; + while ( ( cur = cur.parentNode ) ) { + ap.unshift( cur ); + } + cur = b; + while ( ( cur = cur.parentNode ) ) { + bp.unshift( cur ); + } + + // Walk down the tree looking for a discrepancy + while ( ap[ i ] === bp[ i ] ) { + i++; + } + + return i ? + + // Do a sibling check if the nodes have a common ancestor + siblingCheck( ap[ i ], bp[ i ] ) : + + // Otherwise nodes in our document sort first + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + /* eslint-disable eqeqeq */ + ap[ i ] == preferredDoc ? -1 : + bp[ i ] == preferredDoc ? 1 : + /* eslint-enable eqeqeq */ + 0; + }; + + return document; +}; + +Sizzle.matches = function( expr, elements ) { + return Sizzle( expr, null, null, elements ); +}; + +Sizzle.matchesSelector = function( elem, expr ) { + setDocument( elem ); + + if ( support.matchesSelector && documentIsHTML && + !nonnativeSelectorCache[ expr + " " ] && + ( !rbuggyMatches || !rbuggyMatches.test( expr ) ) && + ( !rbuggyQSA || !rbuggyQSA.test( expr ) ) ) { + + try { + var ret = matches.call( elem, expr ); + + // IE 9's matchesSelector returns false on disconnected nodes + if ( ret || support.disconnectedMatch || + + // As well, disconnected nodes are said to be in a document + // fragment in IE 9 + elem.document && elem.document.nodeType !== 11 ) { + return ret; + } + } catch ( e ) { + nonnativeSelectorCache( expr, true ); + } + } + + return Sizzle( expr, document, null, [ elem ] ).length > 0; +}; + +Sizzle.contains = function( context, elem ) { + + // Set document vars if needed + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( ( context.ownerDocument || context ) != document ) { + setDocument( context ); + } + return contains( context, elem ); +}; + +Sizzle.attr = function( elem, name ) { + + // Set document vars if needed + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( ( elem.ownerDocument || elem ) != document ) { + setDocument( elem ); + } + + var fn = Expr.attrHandle[ name.toLowerCase() ], + + // Don't get fooled by Object.prototype properties (jQuery #13807) + val = fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ? + fn( elem, name, !documentIsHTML ) : + undefined; + + return val !== undefined ? + val : + support.attributes || !documentIsHTML ? + elem.getAttribute( name ) : + ( val = elem.getAttributeNode( name ) ) && val.specified ? + val.value : + null; +}; + +Sizzle.escape = function( sel ) { + return ( sel + "" ).replace( rcssescape, fcssescape ); +}; + +Sizzle.error = function( msg ) { + throw new Error( "Syntax error, unrecognized expression: " + msg ); +}; + +/** + * Document sorting and removing duplicates + * @param {ArrayLike} results + */ +Sizzle.uniqueSort = function( results ) { + var elem, + duplicates = [], + j = 0, + i = 0; + + // Unless we *know* we can detect duplicates, assume their presence + hasDuplicate = !support.detectDuplicates; + sortInput = !support.sortStable && results.slice( 0 ); + results.sort( sortOrder ); + + if ( hasDuplicate ) { + while ( ( elem = results[ i++ ] ) ) { + if ( elem === results[ i ] ) { + j = duplicates.push( i ); + } + } + while ( j-- ) { + results.splice( duplicates[ j ], 1 ); + } + } + + // Clear input after sorting to release objects + // See https://github.com/jquery/sizzle/pull/225 + sortInput = null; + + return results; +}; + +/** + * Utility function for retrieving the text value of an array of DOM nodes + * @param {Array|Element} elem + */ +getText = Sizzle.getText = function( elem ) { + var node, + ret = "", + i = 0, + nodeType = elem.nodeType; + + if ( !nodeType ) { + + // If no nodeType, this is expected to be an array + while ( ( node = elem[ i++ ] ) ) { + + // Do not traverse comment nodes + ret += getText( node ); + } + } else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) { + + // Use textContent for elements + // innerText usage removed for consistency of new lines (jQuery #11153) + if ( typeof elem.textContent === "string" ) { + return elem.textContent; + } else { + + // Traverse its children + for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { + ret += getText( elem ); + } + } + } else if ( nodeType === 3 || nodeType === 4 ) { + return elem.nodeValue; + } + + // Do not include comment or processing instruction nodes + + return ret; +}; + +Expr = Sizzle.selectors = { + + // Can be adjusted by the user + cacheLength: 50, + + createPseudo: markFunction, + + match: matchExpr, + + attrHandle: {}, + + find: {}, + + relative: { + ">": { dir: "parentNode", first: true }, + " ": { dir: "parentNode" }, + "+": { dir: "previousSibling", first: true }, + "~": { dir: "previousSibling" } + }, + + preFilter: { + "ATTR": function( match ) { + match[ 1 ] = match[ 1 ].replace( runescape, funescape ); + + // Move the given value to match[3] whether quoted or unquoted + match[ 3 ] = ( match[ 3 ] || match[ 4 ] || + match[ 5 ] || "" ).replace( runescape, funescape ); + + if ( match[ 2 ] === "~=" ) { + match[ 3 ] = " " + match[ 3 ] + " "; + } + + return match.slice( 0, 4 ); + }, + + "CHILD": function( match ) { + + /* matches from matchExpr["CHILD"] + 1 type (only|nth|...) + 2 what (child|of-type) + 3 argument (even|odd|\d*|\d*n([+-]\d+)?|...) + 4 xn-component of xn+y argument ([+-]?\d*n|) + 5 sign of xn-component + 6 x of xn-component + 7 sign of y-component + 8 y of y-component + */ + match[ 1 ] = match[ 1 ].toLowerCase(); + + if ( match[ 1 ].slice( 0, 3 ) === "nth" ) { + + // nth-* requires argument + if ( !match[ 3 ] ) { + Sizzle.error( match[ 0 ] ); + } + + // numeric x and y parameters for Expr.filter.CHILD + // remember that false/true cast respectively to 0/1 + match[ 4 ] = +( match[ 4 ] ? + match[ 5 ] + ( match[ 6 ] || 1 ) : + 2 * ( match[ 3 ] === "even" || match[ 3 ] === "odd" ) ); + match[ 5 ] = +( ( match[ 7 ] + match[ 8 ] ) || match[ 3 ] === "odd" ); + + // other types prohibit arguments + } else if ( match[ 3 ] ) { + Sizzle.error( match[ 0 ] ); + } + + return match; + }, + + "PSEUDO": function( match ) { + var excess, + unquoted = !match[ 6 ] && match[ 2 ]; + + if ( matchExpr[ "CHILD" ].test( match[ 0 ] ) ) { + return null; + } + + // Accept quoted arguments as-is + if ( match[ 3 ] ) { + match[ 2 ] = match[ 4 ] || match[ 5 ] || ""; + + // Strip excess characters from unquoted arguments + } else if ( unquoted && rpseudo.test( unquoted ) && + + // Get excess from tokenize (recursively) + ( excess = tokenize( unquoted, true ) ) && + + // advance to the next closing parenthesis + ( excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length ) ) { + + // excess is a negative index + match[ 0 ] = match[ 0 ].slice( 0, excess ); + match[ 2 ] = unquoted.slice( 0, excess ); + } + + // Return only captures needed by the pseudo filter method (type and argument) + return match.slice( 0, 3 ); + } + }, + + filter: { + + "TAG": function( nodeNameSelector ) { + var nodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase(); + return nodeNameSelector === "*" ? + function() { + return true; + } : + function( elem ) { + return elem.nodeName && elem.nodeName.toLowerCase() === nodeName; + }; + }, + + "CLASS": function( className ) { + var pattern = classCache[ className + " " ]; + + return pattern || + ( pattern = new RegExp( "(^|" + whitespace + + ")" + className + "(" + whitespace + "|$)" ) ) && classCache( + className, function( elem ) { + return pattern.test( + typeof elem.className === "string" && elem.className || + typeof elem.getAttribute !== "undefined" && + elem.getAttribute( "class" ) || + "" + ); + } ); + }, + + "ATTR": function( name, operator, check ) { + return function( elem ) { + var result = Sizzle.attr( elem, name ); + + if ( result == null ) { + return operator === "!="; + } + if ( !operator ) { + return true; + } + + result += ""; + + /* eslint-disable max-len */ + + return operator === "=" ? result === check : + operator === "!=" ? result !== check : + operator === "^=" ? check && result.indexOf( check ) === 0 : + operator === "*=" ? check && result.indexOf( check ) > -1 : + operator === "$=" ? check && result.slice( -check.length ) === check : + operator === "~=" ? ( " " + result.replace( rwhitespace, " " ) + " " ).indexOf( check ) > -1 : + operator === "|=" ? result === check || result.slice( 0, check.length + 1 ) === check + "-" : + false; + /* eslint-enable max-len */ + + }; + }, + + "CHILD": function( type, what, _argument, first, last ) { + var simple = type.slice( 0, 3 ) !== "nth", + forward = type.slice( -4 ) !== "last", + ofType = what === "of-type"; + + return first === 1 && last === 0 ? + + // Shortcut for :nth-*(n) + function( elem ) { + return !!elem.parentNode; + } : + + function( elem, _context, xml ) { + var cache, uniqueCache, outerCache, node, nodeIndex, start, + dir = simple !== forward ? "nextSibling" : "previousSibling", + parent = elem.parentNode, + name = ofType && elem.nodeName.toLowerCase(), + useCache = !xml && !ofType, + diff = false; + + if ( parent ) { + + // :(first|last|only)-(child|of-type) + if ( simple ) { + while ( dir ) { + node = elem; + while ( ( node = node[ dir ] ) ) { + if ( ofType ? + node.nodeName.toLowerCase() === name : + node.nodeType === 1 ) { + + return false; + } + } + + // Reverse direction for :only-* (if we haven't yet done so) + start = dir = type === "only" && !start && "nextSibling"; + } + return true; + } + + start = [ forward ? parent.firstChild : parent.lastChild ]; + + // non-xml :nth-child(...) stores cache data on `parent` + if ( forward && useCache ) { + + // Seek `elem` from a previously-cached index + + // ...in a gzip-friendly way + node = parent; + outerCache = node[ expando ] || ( node[ expando ] = {} ); + + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ node.uniqueID ] || + ( outerCache[ node.uniqueID ] = {} ); + + cache = uniqueCache[ type ] || []; + nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ]; + diff = nodeIndex && cache[ 2 ]; + node = nodeIndex && parent.childNodes[ nodeIndex ]; + + while ( ( node = ++nodeIndex && node && node[ dir ] || + + // Fallback to seeking `elem` from the start + ( diff = nodeIndex = 0 ) || start.pop() ) ) { + + // When found, cache indexes on `parent` and break + if ( node.nodeType === 1 && ++diff && node === elem ) { + uniqueCache[ type ] = [ dirruns, nodeIndex, diff ]; + break; + } + } + + } else { + + // Use previously-cached element index if available + if ( useCache ) { + + // ...in a gzip-friendly way + node = elem; + outerCache = node[ expando ] || ( node[ expando ] = {} ); + + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ node.uniqueID ] || + ( outerCache[ node.uniqueID ] = {} ); + + cache = uniqueCache[ type ] || []; + nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ]; + diff = nodeIndex; + } + + // xml :nth-child(...) + // or :nth-last-child(...) or :nth(-last)?-of-type(...) + if ( diff === false ) { + + // Use the same loop as above to seek `elem` from the start + while ( ( node = ++nodeIndex && node && node[ dir ] || + ( diff = nodeIndex = 0 ) || start.pop() ) ) { + + if ( ( ofType ? + node.nodeName.toLowerCase() === name : + node.nodeType === 1 ) && + ++diff ) { + + // Cache the index of each encountered element + if ( useCache ) { + outerCache = node[ expando ] || + ( node[ expando ] = {} ); + + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ node.uniqueID ] || + ( outerCache[ node.uniqueID ] = {} ); + + uniqueCache[ type ] = [ dirruns, diff ]; + } + + if ( node === elem ) { + break; + } + } + } + } + } + + // Incorporate the offset, then check against cycle size + diff -= last; + return diff === first || ( diff % first === 0 && diff / first >= 0 ); + } + }; + }, + + "PSEUDO": function( pseudo, argument ) { + + // pseudo-class names are case-insensitive + // http://www.w3.org/TR/selectors/#pseudo-classes + // Prioritize by case sensitivity in case custom pseudos are added with uppercase letters + // Remember that setFilters inherits from pseudos + var args, + fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] || + Sizzle.error( "unsupported pseudo: " + pseudo ); + + // The user may use createPseudo to indicate that + // arguments are needed to create the filter function + // just as Sizzle does + if ( fn[ expando ] ) { + return fn( argument ); + } + + // But maintain support for old signatures + if ( fn.length > 1 ) { + args = [ pseudo, pseudo, "", argument ]; + return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ? + markFunction( function( seed, matches ) { + var idx, + matched = fn( seed, argument ), + i = matched.length; + while ( i-- ) { + idx = indexOf( seed, matched[ i ] ); + seed[ idx ] = !( matches[ idx ] = matched[ i ] ); + } + } ) : + function( elem ) { + return fn( elem, 0, args ); + }; + } + + return fn; + } + }, + + pseudos: { + + // Potentially complex pseudos + "not": markFunction( function( selector ) { + + // Trim the selector passed to compile + // to avoid treating leading and trailing + // spaces as combinators + var input = [], + results = [], + matcher = compile( selector.replace( rtrim, "$1" ) ); + + return matcher[ expando ] ? + markFunction( function( seed, matches, _context, xml ) { + var elem, + unmatched = matcher( seed, null, xml, [] ), + i = seed.length; + + // Match elements unmatched by `matcher` + while ( i-- ) { + if ( ( elem = unmatched[ i ] ) ) { + seed[ i ] = !( matches[ i ] = elem ); + } + } + } ) : + function( elem, _context, xml ) { + input[ 0 ] = elem; + matcher( input, null, xml, results ); + + // Don't keep the element (issue #299) + input[ 0 ] = null; + return !results.pop(); + }; + } ), + + "has": markFunction( function( selector ) { + return function( elem ) { + return Sizzle( selector, elem ).length > 0; + }; + } ), + + "contains": markFunction( function( text ) { + text = text.replace( runescape, funescape ); + return function( elem ) { + return ( elem.textContent || getText( elem ) ).indexOf( text ) > -1; + }; + } ), + + // "Whether an element is represented by a :lang() selector + // is based solely on the element's language value + // being equal to the identifier C, + // or beginning with the identifier C immediately followed by "-". + // The matching of C against the element's language value is performed case-insensitively. + // The identifier C does not have to be a valid language name." + // http://www.w3.org/TR/selectors/#lang-pseudo + "lang": markFunction( function( lang ) { + + // lang value must be a valid identifier + if ( !ridentifier.test( lang || "" ) ) { + Sizzle.error( "unsupported lang: " + lang ); + } + lang = lang.replace( runescape, funescape ).toLowerCase(); + return function( elem ) { + var elemLang; + do { + if ( ( elemLang = documentIsHTML ? + elem.lang : + elem.getAttribute( "xml:lang" ) || elem.getAttribute( "lang" ) ) ) { + + elemLang = elemLang.toLowerCase(); + return elemLang === lang || elemLang.indexOf( lang + "-" ) === 0; + } + } while ( ( elem = elem.parentNode ) && elem.nodeType === 1 ); + return false; + }; + } ), + + // Miscellaneous + "target": function( elem ) { + var hash = window.location && window.location.hash; + return hash && hash.slice( 1 ) === elem.id; + }, + + "root": function( elem ) { + return elem === docElem; + }, + + "focus": function( elem ) { + return elem === document.activeElement && + ( !document.hasFocus || document.hasFocus() ) && + !!( elem.type || elem.href || ~elem.tabIndex ); + }, + + // Boolean properties + "enabled": createDisabledPseudo( false ), + "disabled": createDisabledPseudo( true ), + + "checked": function( elem ) { + + // In CSS3, :checked should return both checked and selected elements + // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked + var nodeName = elem.nodeName.toLowerCase(); + return ( nodeName === "input" && !!elem.checked ) || + ( nodeName === "option" && !!elem.selected ); + }, + + "selected": function( elem ) { + + // Accessing this property makes selected-by-default + // options in Safari work properly + if ( elem.parentNode ) { + // eslint-disable-next-line no-unused-expressions + elem.parentNode.selectedIndex; + } + + return elem.selected === true; + }, + + // Contents + "empty": function( elem ) { + + // http://www.w3.org/TR/selectors/#empty-pseudo + // :empty is negated by element (1) or content nodes (text: 3; cdata: 4; entity ref: 5), + // but not by others (comment: 8; processing instruction: 7; etc.) + // nodeType < 6 works because attributes (2) do not appear as children + for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { + if ( elem.nodeType < 6 ) { + return false; + } + } + return true; + }, + + "parent": function( elem ) { + return !Expr.pseudos[ "empty" ]( elem ); + }, + + // Element/input types + "header": function( elem ) { + return rheader.test( elem.nodeName ); + }, + + "input": function( elem ) { + return rinputs.test( elem.nodeName ); + }, + + "button": function( elem ) { + var name = elem.nodeName.toLowerCase(); + return name === "input" && elem.type === "button" || name === "button"; + }, + + "text": function( elem ) { + var attr; + return elem.nodeName.toLowerCase() === "input" && + elem.type === "text" && + + // Support: IE<8 + // New HTML5 attribute values (e.g., "search") appear with elem.type === "text" + ( ( attr = elem.getAttribute( "type" ) ) == null || + attr.toLowerCase() === "text" ); + }, + + // Position-in-collection + "first": createPositionalPseudo( function() { + return [ 0 ]; + } ), + + "last": createPositionalPseudo( function( _matchIndexes, length ) { + return [ length - 1 ]; + } ), + + "eq": createPositionalPseudo( function( _matchIndexes, length, argument ) { + return [ argument < 0 ? argument + length : argument ]; + } ), + + "even": createPositionalPseudo( function( matchIndexes, length ) { + var i = 0; + for ( ; i < length; i += 2 ) { + matchIndexes.push( i ); + } + return matchIndexes; + } ), + + "odd": createPositionalPseudo( function( matchIndexes, length ) { + var i = 1; + for ( ; i < length; i += 2 ) { + matchIndexes.push( i ); + } + return matchIndexes; + } ), + + "lt": createPositionalPseudo( function( matchIndexes, length, argument ) { + var i = argument < 0 ? + argument + length : + argument > length ? + length : + argument; + for ( ; --i >= 0; ) { + matchIndexes.push( i ); + } + return matchIndexes; + } ), + + "gt": createPositionalPseudo( function( matchIndexes, length, argument ) { + var i = argument < 0 ? argument + length : argument; + for ( ; ++i < length; ) { + matchIndexes.push( i ); + } + return matchIndexes; + } ) + } +}; + +Expr.pseudos[ "nth" ] = Expr.pseudos[ "eq" ]; + +// Add button/input type pseudos +for ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) { + Expr.pseudos[ i ] = createInputPseudo( i ); +} +for ( i in { submit: true, reset: true } ) { + Expr.pseudos[ i ] = createButtonPseudo( i ); +} + +// Easy API for creating new setFilters +function setFilters() {} +setFilters.prototype = Expr.filters = Expr.pseudos; +Expr.setFilters = new setFilters(); + +tokenize = Sizzle.tokenize = function( selector, parseOnly ) { + var matched, match, tokens, type, + soFar, groups, preFilters, + cached = tokenCache[ selector + " " ]; + + if ( cached ) { + return parseOnly ? 0 : cached.slice( 0 ); + } + + soFar = selector; + groups = []; + preFilters = Expr.preFilter; + + while ( soFar ) { + + // Comma and first run + if ( !matched || ( match = rcomma.exec( soFar ) ) ) { + if ( match ) { + + // Don't consume trailing commas as valid + soFar = soFar.slice( match[ 0 ].length ) || soFar; + } + groups.push( ( tokens = [] ) ); + } + + matched = false; + + // Combinators + if ( ( match = rcombinators.exec( soFar ) ) ) { + matched = match.shift(); + tokens.push( { + value: matched, + + // Cast descendant combinators to space + type: match[ 0 ].replace( rtrim, " " ) + } ); + soFar = soFar.slice( matched.length ); + } + + // Filters + for ( type in Expr.filter ) { + if ( ( match = matchExpr[ type ].exec( soFar ) ) && ( !preFilters[ type ] || + ( match = preFilters[ type ]( match ) ) ) ) { + matched = match.shift(); + tokens.push( { + value: matched, + type: type, + matches: match + } ); + soFar = soFar.slice( matched.length ); + } + } + + if ( !matched ) { + break; + } + } + + // Return the length of the invalid excess + // if we're just parsing + // Otherwise, throw an error or return tokens + return parseOnly ? + soFar.length : + soFar ? + Sizzle.error( selector ) : + + // Cache the tokens + tokenCache( selector, groups ).slice( 0 ); +}; + +function toSelector( tokens ) { + var i = 0, + len = tokens.length, + selector = ""; + for ( ; i < len; i++ ) { + selector += tokens[ i ].value; + } + return selector; +} + +function addCombinator( matcher, combinator, base ) { + var dir = combinator.dir, + skip = combinator.next, + key = skip || dir, + checkNonElements = base && key === "parentNode", + doneName = done++; + + return combinator.first ? + + // Check against closest ancestor/preceding element + function( elem, context, xml ) { + while ( ( elem = elem[ dir ] ) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + return matcher( elem, context, xml ); + } + } + return false; + } : + + // Check against all ancestor/preceding elements + function( elem, context, xml ) { + var oldCache, uniqueCache, outerCache, + newCache = [ dirruns, doneName ]; + + // We can't set arbitrary data on XML nodes, so they don't benefit from combinator caching + if ( xml ) { + while ( ( elem = elem[ dir ] ) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + if ( matcher( elem, context, xml ) ) { + return true; + } + } + } + } else { + while ( ( elem = elem[ dir ] ) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + outerCache = elem[ expando ] || ( elem[ expando ] = {} ); + + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ elem.uniqueID ] || + ( outerCache[ elem.uniqueID ] = {} ); + + if ( skip && skip === elem.nodeName.toLowerCase() ) { + elem = elem[ dir ] || elem; + } else if ( ( oldCache = uniqueCache[ key ] ) && + oldCache[ 0 ] === dirruns && oldCache[ 1 ] === doneName ) { + + // Assign to newCache so results back-propagate to previous elements + return ( newCache[ 2 ] = oldCache[ 2 ] ); + } else { + + // Reuse newcache so results back-propagate to previous elements + uniqueCache[ key ] = newCache; + + // A match means we're done; a fail means we have to keep checking + if ( ( newCache[ 2 ] = matcher( elem, context, xml ) ) ) { + return true; + } + } + } + } + } + return false; + }; +} + +function elementMatcher( matchers ) { + return matchers.length > 1 ? + function( elem, context, xml ) { + var i = matchers.length; + while ( i-- ) { + if ( !matchers[ i ]( elem, context, xml ) ) { + return false; + } + } + return true; + } : + matchers[ 0 ]; +} + +function multipleContexts( selector, contexts, results ) { + var i = 0, + len = contexts.length; + for ( ; i < len; i++ ) { + Sizzle( selector, contexts[ i ], results ); + } + return results; +} + +function condense( unmatched, map, filter, context, xml ) { + var elem, + newUnmatched = [], + i = 0, + len = unmatched.length, + mapped = map != null; + + for ( ; i < len; i++ ) { + if ( ( elem = unmatched[ i ] ) ) { + if ( !filter || filter( elem, context, xml ) ) { + newUnmatched.push( elem ); + if ( mapped ) { + map.push( i ); + } + } + } + } + + return newUnmatched; +} + +function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) { + if ( postFilter && !postFilter[ expando ] ) { + postFilter = setMatcher( postFilter ); + } + if ( postFinder && !postFinder[ expando ] ) { + postFinder = setMatcher( postFinder, postSelector ); + } + return markFunction( function( seed, results, context, xml ) { + var temp, i, elem, + preMap = [], + postMap = [], + preexisting = results.length, + + // Get initial elements from seed or context + elems = seed || multipleContexts( + selector || "*", + context.nodeType ? [ context ] : context, + [] + ), + + // Prefilter to get matcher input, preserving a map for seed-results synchronization + matcherIn = preFilter && ( seed || !selector ) ? + condense( elems, preMap, preFilter, context, xml ) : + elems, + + matcherOut = matcher ? + + // If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results, + postFinder || ( seed ? preFilter : preexisting || postFilter ) ? + + // ...intermediate processing is necessary + [] : + + // ...otherwise use results directly + results : + matcherIn; + + // Find primary matches + if ( matcher ) { + matcher( matcherIn, matcherOut, context, xml ); + } + + // Apply postFilter + if ( postFilter ) { + temp = condense( matcherOut, postMap ); + postFilter( temp, [], context, xml ); + + // Un-match failing elements by moving them back to matcherIn + i = temp.length; + while ( i-- ) { + if ( ( elem = temp[ i ] ) ) { + matcherOut[ postMap[ i ] ] = !( matcherIn[ postMap[ i ] ] = elem ); + } + } + } + + if ( seed ) { + if ( postFinder || preFilter ) { + if ( postFinder ) { + + // Get the final matcherOut by condensing this intermediate into postFinder contexts + temp = []; + i = matcherOut.length; + while ( i-- ) { + if ( ( elem = matcherOut[ i ] ) ) { + + // Restore matcherIn since elem is not yet a final match + temp.push( ( matcherIn[ i ] = elem ) ); + } + } + postFinder( null, ( matcherOut = [] ), temp, xml ); + } + + // Move matched elements from seed to results to keep them synchronized + i = matcherOut.length; + while ( i-- ) { + if ( ( elem = matcherOut[ i ] ) && + ( temp = postFinder ? indexOf( seed, elem ) : preMap[ i ] ) > -1 ) { + + seed[ temp ] = !( results[ temp ] = elem ); + } + } + } + + // Add elements to results, through postFinder if defined + } else { + matcherOut = condense( + matcherOut === results ? + matcherOut.splice( preexisting, matcherOut.length ) : + matcherOut + ); + if ( postFinder ) { + postFinder( null, results, matcherOut, xml ); + } else { + push.apply( results, matcherOut ); + } + } + } ); +} + +function matcherFromTokens( tokens ) { + var checkContext, matcher, j, + len = tokens.length, + leadingRelative = Expr.relative[ tokens[ 0 ].type ], + implicitRelative = leadingRelative || Expr.relative[ " " ], + i = leadingRelative ? 1 : 0, + + // The foundational matcher ensures that elements are reachable from top-level context(s) + matchContext = addCombinator( function( elem ) { + return elem === checkContext; + }, implicitRelative, true ), + matchAnyContext = addCombinator( function( elem ) { + return indexOf( checkContext, elem ) > -1; + }, implicitRelative, true ), + matchers = [ function( elem, context, xml ) { + var ret = ( !leadingRelative && ( xml || context !== outermostContext ) ) || ( + ( checkContext = context ).nodeType ? + matchContext( elem, context, xml ) : + matchAnyContext( elem, context, xml ) ); + + // Avoid hanging onto element (issue #299) + checkContext = null; + return ret; + } ]; + + for ( ; i < len; i++ ) { + if ( ( matcher = Expr.relative[ tokens[ i ].type ] ) ) { + matchers = [ addCombinator( elementMatcher( matchers ), matcher ) ]; + } else { + matcher = Expr.filter[ tokens[ i ].type ].apply( null, tokens[ i ].matches ); + + // Return special upon seeing a positional matcher + if ( matcher[ expando ] ) { + + // Find the next relative operator (if any) for proper handling + j = ++i; + for ( ; j < len; j++ ) { + if ( Expr.relative[ tokens[ j ].type ] ) { + break; + } + } + return setMatcher( + i > 1 && elementMatcher( matchers ), + i > 1 && toSelector( + + // If the preceding token was a descendant combinator, insert an implicit any-element `*` + tokens + .slice( 0, i - 1 ) + .concat( { value: tokens[ i - 2 ].type === " " ? "*" : "" } ) + ).replace( rtrim, "$1" ), + matcher, + i < j && matcherFromTokens( tokens.slice( i, j ) ), + j < len && matcherFromTokens( ( tokens = tokens.slice( j ) ) ), + j < len && toSelector( tokens ) + ); + } + matchers.push( matcher ); + } + } + + return elementMatcher( matchers ); +} + +function matcherFromGroupMatchers( elementMatchers, setMatchers ) { + var bySet = setMatchers.length > 0, + byElement = elementMatchers.length > 0, + superMatcher = function( seed, context, xml, results, outermost ) { + var elem, j, matcher, + matchedCount = 0, + i = "0", + unmatched = seed && [], + setMatched = [], + contextBackup = outermostContext, + + // We must always have either seed elements or outermost context + elems = seed || byElement && Expr.find[ "TAG" ]( "*", outermost ), + + // Use integer dirruns iff this is the outermost matcher + dirrunsUnique = ( dirruns += contextBackup == null ? 1 : Math.random() || 0.1 ), + len = elems.length; + + if ( outermost ) { + + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + outermostContext = context == document || context || outermost; + } + + // Add elements passing elementMatchers directly to results + // Support: IE<9, Safari + // Tolerate NodeList properties (IE: "length"; Safari: ) matching elements by id + for ( ; i !== len && ( elem = elems[ i ] ) != null; i++ ) { + if ( byElement && elem ) { + j = 0; + + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( !context && elem.ownerDocument != document ) { + setDocument( elem ); + xml = !documentIsHTML; + } + while ( ( matcher = elementMatchers[ j++ ] ) ) { + if ( matcher( elem, context || document, xml ) ) { + results.push( elem ); + break; + } + } + if ( outermost ) { + dirruns = dirrunsUnique; + } + } + + // Track unmatched elements for set filters + if ( bySet ) { + + // They will have gone through all possible matchers + if ( ( elem = !matcher && elem ) ) { + matchedCount--; + } + + // Lengthen the array for every element, matched or not + if ( seed ) { + unmatched.push( elem ); + } + } + } + + // `i` is now the count of elements visited above, and adding it to `matchedCount` + // makes the latter nonnegative. + matchedCount += i; + + // Apply set filters to unmatched elements + // NOTE: This can be skipped if there are no unmatched elements (i.e., `matchedCount` + // equals `i`), unless we didn't visit _any_ elements in the above loop because we have + // no element matchers and no seed. + // Incrementing an initially-string "0" `i` allows `i` to remain a string only in that + // case, which will result in a "00" `matchedCount` that differs from `i` but is also + // numerically zero. + if ( bySet && i !== matchedCount ) { + j = 0; + while ( ( matcher = setMatchers[ j++ ] ) ) { + matcher( unmatched, setMatched, context, xml ); + } + + if ( seed ) { + + // Reintegrate element matches to eliminate the need for sorting + if ( matchedCount > 0 ) { + while ( i-- ) { + if ( !( unmatched[ i ] || setMatched[ i ] ) ) { + setMatched[ i ] = pop.call( results ); + } + } + } + + // Discard index placeholder values to get only actual matches + setMatched = condense( setMatched ); + } + + // Add matches to results + push.apply( results, setMatched ); + + // Seedless set matches succeeding multiple successful matchers stipulate sorting + if ( outermost && !seed && setMatched.length > 0 && + ( matchedCount + setMatchers.length ) > 1 ) { + + Sizzle.uniqueSort( results ); + } + } + + // Override manipulation of globals by nested matchers + if ( outermost ) { + dirruns = dirrunsUnique; + outermostContext = contextBackup; + } + + return unmatched; + }; + + return bySet ? + markFunction( superMatcher ) : + superMatcher; +} + +compile = Sizzle.compile = function( selector, match /* Internal Use Only */ ) { + var i, + setMatchers = [], + elementMatchers = [], + cached = compilerCache[ selector + " " ]; + + if ( !cached ) { + + // Generate a function of recursive functions that can be used to check each element + if ( !match ) { + match = tokenize( selector ); + } + i = match.length; + while ( i-- ) { + cached = matcherFromTokens( match[ i ] ); + if ( cached[ expando ] ) { + setMatchers.push( cached ); + } else { + elementMatchers.push( cached ); + } + } + + // Cache the compiled function + cached = compilerCache( + selector, + matcherFromGroupMatchers( elementMatchers, setMatchers ) + ); + + // Save selector and tokenization + cached.selector = selector; + } + return cached; +}; + +/** + * A low-level selection function that works with Sizzle's compiled + * selector functions + * @param {String|Function} selector A selector or a pre-compiled + * selector function built with Sizzle.compile + * @param {Element} context + * @param {Array} [results] + * @param {Array} [seed] A set of elements to match against + */ +select = Sizzle.select = function( selector, context, results, seed ) { + var i, tokens, token, type, find, + compiled = typeof selector === "function" && selector, + match = !seed && tokenize( ( selector = compiled.selector || selector ) ); + + results = results || []; + + // Try to minimize operations if there is only one selector in the list and no seed + // (the latter of which guarantees us context) + if ( match.length === 1 ) { + + // Reduce context if the leading compound selector is an ID + tokens = match[ 0 ] = match[ 0 ].slice( 0 ); + if ( tokens.length > 2 && ( token = tokens[ 0 ] ).type === "ID" && + context.nodeType === 9 && documentIsHTML && Expr.relative[ tokens[ 1 ].type ] ) { + + context = ( Expr.find[ "ID" ]( token.matches[ 0 ] + .replace( runescape, funescape ), context ) || [] )[ 0 ]; + if ( !context ) { + return results; + + // Precompiled matchers will still verify ancestry, so step up a level + } else if ( compiled ) { + context = context.parentNode; + } + + selector = selector.slice( tokens.shift().value.length ); + } + + // Fetch a seed set for right-to-left matching + i = matchExpr[ "needsContext" ].test( selector ) ? 0 : tokens.length; + while ( i-- ) { + token = tokens[ i ]; + + // Abort if we hit a combinator + if ( Expr.relative[ ( type = token.type ) ] ) { + break; + } + if ( ( find = Expr.find[ type ] ) ) { + + // Search, expanding context for leading sibling combinators + if ( ( seed = find( + token.matches[ 0 ].replace( runescape, funescape ), + rsibling.test( tokens[ 0 ].type ) && testContext( context.parentNode ) || + context + ) ) ) { + + // If seed is empty or no tokens remain, we can return early + tokens.splice( i, 1 ); + selector = seed.length && toSelector( tokens ); + if ( !selector ) { + push.apply( results, seed ); + return results; + } + + break; + } + } + } + } + + // Compile and execute a filtering function if one is not provided + // Provide `match` to avoid retokenization if we modified the selector above + ( compiled || compile( selector, match ) )( + seed, + context, + !documentIsHTML, + results, + !context || rsibling.test( selector ) && testContext( context.parentNode ) || context + ); + return results; +}; + +// One-time assignments + +// Sort stability +support.sortStable = expando.split( "" ).sort( sortOrder ).join( "" ) === expando; + +// Support: Chrome 14-35+ +// Always assume duplicates if they aren't passed to the comparison function +support.detectDuplicates = !!hasDuplicate; + +// Initialize against the default document +setDocument(); + +// Support: Webkit<537.32 - Safari 6.0.3/Chrome 25 (fixed in Chrome 27) +// Detached nodes confoundingly follow *each other* +support.sortDetached = assert( function( el ) { + + // Should return 1, but returns 4 (following) + return el.compareDocumentPosition( document.createElement( "fieldset" ) ) & 1; +} ); + +// Support: IE<8 +// Prevent attribute/property "interpolation" +// https://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx +if ( !assert( function( el ) { + el.innerHTML = ""; + return el.firstChild.getAttribute( "href" ) === "#"; +} ) ) { + addHandle( "type|href|height|width", function( elem, name, isXML ) { + if ( !isXML ) { + return elem.getAttribute( name, name.toLowerCase() === "type" ? 1 : 2 ); + } + } ); +} + +// Support: IE<9 +// Use defaultValue in place of getAttribute("value") +if ( !support.attributes || !assert( function( el ) { + el.innerHTML = ""; + el.firstChild.setAttribute( "value", "" ); + return el.firstChild.getAttribute( "value" ) === ""; +} ) ) { + addHandle( "value", function( elem, _name, isXML ) { + if ( !isXML && elem.nodeName.toLowerCase() === "input" ) { + return elem.defaultValue; + } + } ); +} + +// Support: IE<9 +// Use getAttributeNode to fetch booleans when getAttribute lies +if ( !assert( function( el ) { + return el.getAttribute( "disabled" ) == null; +} ) ) { + addHandle( booleans, function( elem, name, isXML ) { + var val; + if ( !isXML ) { + return elem[ name ] === true ? name.toLowerCase() : + ( val = elem.getAttributeNode( name ) ) && val.specified ? + val.value : + null; + } + } ); +} + +return Sizzle; + +} )( window ); + + + +jQuery.find = Sizzle; +jQuery.expr = Sizzle.selectors; + +// Deprecated +jQuery.expr[ ":" ] = jQuery.expr.pseudos; +jQuery.uniqueSort = jQuery.unique = Sizzle.uniqueSort; +jQuery.text = Sizzle.getText; +jQuery.isXMLDoc = Sizzle.isXML; +jQuery.contains = Sizzle.contains; +jQuery.escapeSelector = Sizzle.escape; + + + + +var dir = function( elem, dir, until ) { + var matched = [], + truncate = until !== undefined; + + while ( ( elem = elem[ dir ] ) && elem.nodeType !== 9 ) { + if ( elem.nodeType === 1 ) { + if ( truncate && jQuery( elem ).is( until ) ) { + break; + } + matched.push( elem ); + } + } + return matched; +}; + + +var siblings = function( n, elem ) { + var matched = []; + + for ( ; n; n = n.nextSibling ) { + if ( n.nodeType === 1 && n !== elem ) { + matched.push( n ); + } + } + + return matched; +}; + + +var rneedsContext = jQuery.expr.match.needsContext; + + + +function nodeName( elem, name ) { + + return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase(); + +}; +var rsingleTag = ( /^<([a-z][^\/\0>:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i ); + + + +// Implement the identical functionality for filter and not +function winnow( elements, qualifier, not ) { + if ( isFunction( qualifier ) ) { + return jQuery.grep( elements, function( elem, i ) { + return !!qualifier.call( elem, i, elem ) !== not; + } ); + } + + // Single element + if ( qualifier.nodeType ) { + return jQuery.grep( elements, function( elem ) { + return ( elem === qualifier ) !== not; + } ); + } + + // Arraylike of elements (jQuery, arguments, Array) + if ( typeof qualifier !== "string" ) { + return jQuery.grep( elements, function( elem ) { + return ( indexOf.call( qualifier, elem ) > -1 ) !== not; + } ); + } + + // Filtered directly for both simple and complex selectors + return jQuery.filter( qualifier, elements, not ); +} + +jQuery.filter = function( expr, elems, not ) { + var elem = elems[ 0 ]; + + if ( not ) { + expr = ":not(" + expr + ")"; + } + + if ( elems.length === 1 && elem.nodeType === 1 ) { + return jQuery.find.matchesSelector( elem, expr ) ? [ elem ] : []; + } + + return jQuery.find.matches( expr, jQuery.grep( elems, function( elem ) { + return elem.nodeType === 1; + } ) ); +}; + +jQuery.fn.extend( { + find: function( selector ) { + var i, ret, + len = this.length, + self = this; + + if ( typeof selector !== "string" ) { + return this.pushStack( jQuery( selector ).filter( function() { + for ( i = 0; i < len; i++ ) { + if ( jQuery.contains( self[ i ], this ) ) { + return true; + } + } + } ) ); + } + + ret = this.pushStack( [] ); + + for ( i = 0; i < len; i++ ) { + jQuery.find( selector, self[ i ], ret ); + } + + return len > 1 ? jQuery.uniqueSort( ret ) : ret; + }, + filter: function( selector ) { + return this.pushStack( winnow( this, selector || [], false ) ); + }, + not: function( selector ) { + return this.pushStack( winnow( this, selector || [], true ) ); + }, + is: function( selector ) { + return !!winnow( + this, + + // If this is a positional/relative selector, check membership in the returned set + // so $("p:first").is("p:last") won't return true for a doc with two "p". + typeof selector === "string" && rneedsContext.test( selector ) ? + jQuery( selector ) : + selector || [], + false + ).length; + } +} ); + + +// Initialize a jQuery object + + +// A central reference to the root jQuery(document) +var rootjQuery, + + // A simple way to check for HTML strings + // Prioritize #id over to avoid XSS via location.hash (#9521) + // Strict HTML recognition (#11290: must start with <) + // Shortcut simple #id case for speed + rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]+))$/, + + init = jQuery.fn.init = function( selector, context, root ) { + var match, elem; + + // HANDLE: $(""), $(null), $(undefined), $(false) + if ( !selector ) { + return this; + } + + // Method init() accepts an alternate rootjQuery + // so migrate can support jQuery.sub (gh-2101) + root = root || rootjQuery; + + // Handle HTML strings + if ( typeof selector === "string" ) { + if ( selector[ 0 ] === "<" && + selector[ selector.length - 1 ] === ">" && + selector.length >= 3 ) { + + // Assume that strings that start and end with <> are HTML and skip the regex check + match = [ null, selector, null ]; + + } else { + match = rquickExpr.exec( selector ); + } + + // Match html or make sure no context is specified for #id + if ( match && ( match[ 1 ] || !context ) ) { + + // HANDLE: $(html) -> $(array) + if ( match[ 1 ] ) { + context = context instanceof jQuery ? context[ 0 ] : context; + + // Option to run scripts is true for back-compat + // Intentionally let the error be thrown if parseHTML is not present + jQuery.merge( this, jQuery.parseHTML( + match[ 1 ], + context && context.nodeType ? context.ownerDocument || context : document, + true + ) ); + + // HANDLE: $(html, props) + if ( rsingleTag.test( match[ 1 ] ) && jQuery.isPlainObject( context ) ) { + for ( match in context ) { + + // Properties of context are called as methods if possible + if ( isFunction( this[ match ] ) ) { + this[ match ]( context[ match ] ); + + // ...and otherwise set as attributes + } else { + this.attr( match, context[ match ] ); + } + } + } + + return this; + + // HANDLE: $(#id) + } else { + elem = document.getElementById( match[ 2 ] ); + + if ( elem ) { + + // Inject the element directly into the jQuery object + this[ 0 ] = elem; + this.length = 1; + } + return this; + } + + // HANDLE: $(expr, $(...)) + } else if ( !context || context.jquery ) { + return ( context || root ).find( selector ); + + // HANDLE: $(expr, context) + // (which is just equivalent to: $(context).find(expr) + } else { + return this.constructor( context ).find( selector ); + } + + // HANDLE: $(DOMElement) + } else if ( selector.nodeType ) { + this[ 0 ] = selector; + this.length = 1; + return this; + + // HANDLE: $(function) + // Shortcut for document ready + } else if ( isFunction( selector ) ) { + return root.ready !== undefined ? + root.ready( selector ) : + + // Execute immediately if ready is not present + selector( jQuery ); + } + + return jQuery.makeArray( selector, this ); + }; + +// Give the init function the jQuery prototype for later instantiation +init.prototype = jQuery.fn; + +// Initialize central reference +rootjQuery = jQuery( document ); + + +var rparentsprev = /^(?:parents|prev(?:Until|All))/, + + // Methods guaranteed to produce a unique set when starting from a unique set + guaranteedUnique = { + children: true, + contents: true, + next: true, + prev: true + }; + +jQuery.fn.extend( { + has: function( target ) { + var targets = jQuery( target, this ), + l = targets.length; + + return this.filter( function() { + var i = 0; + for ( ; i < l; i++ ) { + if ( jQuery.contains( this, targets[ i ] ) ) { + return true; + } + } + } ); + }, + + closest: function( selectors, context ) { + var cur, + i = 0, + l = this.length, + matched = [], + targets = typeof selectors !== "string" && jQuery( selectors ); + + // Positional selectors never match, since there's no _selection_ context + if ( !rneedsContext.test( selectors ) ) { + for ( ; i < l; i++ ) { + for ( cur = this[ i ]; cur && cur !== context; cur = cur.parentNode ) { + + // Always skip document fragments + if ( cur.nodeType < 11 && ( targets ? + targets.index( cur ) > -1 : + + // Don't pass non-elements to Sizzle + cur.nodeType === 1 && + jQuery.find.matchesSelector( cur, selectors ) ) ) { + + matched.push( cur ); + break; + } + } + } + } + + return this.pushStack( matched.length > 1 ? jQuery.uniqueSort( matched ) : matched ); + }, + + // Determine the position of an element within the set + index: function( elem ) { + + // No argument, return index in parent + if ( !elem ) { + return ( this[ 0 ] && this[ 0 ].parentNode ) ? this.first().prevAll().length : -1; + } + + // Index in selector + if ( typeof elem === "string" ) { + return indexOf.call( jQuery( elem ), this[ 0 ] ); + } + + // Locate the position of the desired element + return indexOf.call( this, + + // If it receives a jQuery object, the first element is used + elem.jquery ? elem[ 0 ] : elem + ); + }, + + add: function( selector, context ) { + return this.pushStack( + jQuery.uniqueSort( + jQuery.merge( this.get(), jQuery( selector, context ) ) + ) + ); + }, + + addBack: function( selector ) { + return this.add( selector == null ? + this.prevObject : this.prevObject.filter( selector ) + ); + } +} ); + +function sibling( cur, dir ) { + while ( ( cur = cur[ dir ] ) && cur.nodeType !== 1 ) {} + return cur; +} + +jQuery.each( { + parent: function( elem ) { + var parent = elem.parentNode; + return parent && parent.nodeType !== 11 ? parent : null; + }, + parents: function( elem ) { + return dir( elem, "parentNode" ); + }, + parentsUntil: function( elem, _i, until ) { + return dir( elem, "parentNode", until ); + }, + next: function( elem ) { + return sibling( elem, "nextSibling" ); + }, + prev: function( elem ) { + return sibling( elem, "previousSibling" ); + }, + nextAll: function( elem ) { + return dir( elem, "nextSibling" ); + }, + prevAll: function( elem ) { + return dir( elem, "previousSibling" ); + }, + nextUntil: function( elem, _i, until ) { + return dir( elem, "nextSibling", until ); + }, + prevUntil: function( elem, _i, until ) { + return dir( elem, "previousSibling", until ); + }, + siblings: function( elem ) { + return siblings( ( elem.parentNode || {} ).firstChild, elem ); + }, + children: function( elem ) { + return siblings( elem.firstChild ); + }, + contents: function( elem ) { + if ( elem.contentDocument != null && + + // Support: IE 11+ + // elements with no `data` attribute has an object + // `contentDocument` with a `null` prototype. + getProto( elem.contentDocument ) ) { + + return elem.contentDocument; + } + + // Support: IE 9 - 11 only, iOS 7 only, Android Browser <=4.3 only + // Treat the template element as a regular one in browsers that + // don't support it. + if ( nodeName( elem, "template" ) ) { + elem = elem.content || elem; + } + + return jQuery.merge( [], elem.childNodes ); + } +}, function( name, fn ) { + jQuery.fn[ name ] = function( until, selector ) { + var matched = jQuery.map( this, fn, until ); + + if ( name.slice( -5 ) !== "Until" ) { + selector = until; + } + + if ( selector && typeof selector === "string" ) { + matched = jQuery.filter( selector, matched ); + } + + if ( this.length > 1 ) { + + // Remove duplicates + if ( !guaranteedUnique[ name ] ) { + jQuery.uniqueSort( matched ); + } + + // Reverse order for parents* and prev-derivatives + if ( rparentsprev.test( name ) ) { + matched.reverse(); + } + } + + return this.pushStack( matched ); + }; +} ); +var rnothtmlwhite = ( /[^\x20\t\r\n\f]+/g ); + + + +// Convert String-formatted options into Object-formatted ones +function createOptions( options ) { + var object = {}; + jQuery.each( options.match( rnothtmlwhite ) || [], function( _, flag ) { + object[ flag ] = true; + } ); + return object; +} + +/* + * Create a callback list using the following parameters: + * + * options: an optional list of space-separated options that will change how + * the callback list behaves or a more traditional option object + * + * By default a callback list will act like an event callback list and can be + * "fired" multiple times. + * + * Possible options: + * + * once: will ensure the callback list can only be fired once (like a Deferred) + * + * memory: will keep track of previous values and will call any callback added + * after the list has been fired right away with the latest "memorized" + * values (like a Deferred) + * + * unique: will ensure a callback can only be added once (no duplicate in the list) + * + * stopOnFalse: interrupt callings when a callback returns false + * + */ +jQuery.Callbacks = function( options ) { + + // Convert options from String-formatted to Object-formatted if needed + // (we check in cache first) + options = typeof options === "string" ? + createOptions( options ) : + jQuery.extend( {}, options ); + + var // Flag to know if list is currently firing + firing, + + // Last fire value for non-forgettable lists + memory, + + // Flag to know if list was already fired + fired, + + // Flag to prevent firing + locked, + + // Actual callback list + list = [], + + // Queue of execution data for repeatable lists + queue = [], + + // Index of currently firing callback (modified by add/remove as needed) + firingIndex = -1, + + // Fire callbacks + fire = function() { + + // Enforce single-firing + locked = locked || options.once; + + // Execute callbacks for all pending executions, + // respecting firingIndex overrides and runtime changes + fired = firing = true; + for ( ; queue.length; firingIndex = -1 ) { + memory = queue.shift(); + while ( ++firingIndex < list.length ) { + + // Run callback and check for early termination + if ( list[ firingIndex ].apply( memory[ 0 ], memory[ 1 ] ) === false && + options.stopOnFalse ) { + + // Jump to end and forget the data so .add doesn't re-fire + firingIndex = list.length; + memory = false; + } + } + } + + // Forget the data if we're done with it + if ( !options.memory ) { + memory = false; + } + + firing = false; + + // Clean up if we're done firing for good + if ( locked ) { + + // Keep an empty list if we have data for future add calls + if ( memory ) { + list = []; + + // Otherwise, this object is spent + } else { + list = ""; + } + } + }, + + // Actual Callbacks object + self = { + + // Add a callback or a collection of callbacks to the list + add: function() { + if ( list ) { + + // If we have memory from a past run, we should fire after adding + if ( memory && !firing ) { + firingIndex = list.length - 1; + queue.push( memory ); + } + + ( function add( args ) { + jQuery.each( args, function( _, arg ) { + if ( isFunction( arg ) ) { + if ( !options.unique || !self.has( arg ) ) { + list.push( arg ); + } + } else if ( arg && arg.length && toType( arg ) !== "string" ) { + + // Inspect recursively + add( arg ); + } + } ); + } )( arguments ); + + if ( memory && !firing ) { + fire(); + } + } + return this; + }, + + // Remove a callback from the list + remove: function() { + jQuery.each( arguments, function( _, arg ) { + var index; + while ( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) { + list.splice( index, 1 ); + + // Handle firing indexes + if ( index <= firingIndex ) { + firingIndex--; + } + } + } ); + return this; + }, + + // Check if a given callback is in the list. + // If no argument is given, return whether or not list has callbacks attached. + has: function( fn ) { + return fn ? + jQuery.inArray( fn, list ) > -1 : + list.length > 0; + }, + + // Remove all callbacks from the list + empty: function() { + if ( list ) { + list = []; + } + return this; + }, + + // Disable .fire and .add + // Abort any current/pending executions + // Clear all callbacks and values + disable: function() { + locked = queue = []; + list = memory = ""; + return this; + }, + disabled: function() { + return !list; + }, + + // Disable .fire + // Also disable .add unless we have memory (since it would have no effect) + // Abort any pending executions + lock: function() { + locked = queue = []; + if ( !memory && !firing ) { + list = memory = ""; + } + return this; + }, + locked: function() { + return !!locked; + }, + + // Call all callbacks with the given context and arguments + fireWith: function( context, args ) { + if ( !locked ) { + args = args || []; + args = [ context, args.slice ? args.slice() : args ]; + queue.push( args ); + if ( !firing ) { + fire(); + } + } + return this; + }, + + // Call all the callbacks with the given arguments + fire: function() { + self.fireWith( this, arguments ); + return this; + }, + + // To know if the callbacks have already been called at least once + fired: function() { + return !!fired; + } + }; + + return self; +}; + + +function Identity( v ) { + return v; +} +function Thrower( ex ) { + throw ex; +} + +function adoptValue( value, resolve, reject, noValue ) { + var method; + + try { + + // Check for promise aspect first to privilege synchronous behavior + if ( value && isFunction( ( method = value.promise ) ) ) { + method.call( value ).done( resolve ).fail( reject ); + + // Other thenables + } else if ( value && isFunction( ( method = value.then ) ) ) { + method.call( value, resolve, reject ); + + // Other non-thenables + } else { + + // Control `resolve` arguments by letting Array#slice cast boolean `noValue` to integer: + // * false: [ value ].slice( 0 ) => resolve( value ) + // * true: [ value ].slice( 1 ) => resolve() + resolve.apply( undefined, [ value ].slice( noValue ) ); + } + + // For Promises/A+, convert exceptions into rejections + // Since jQuery.when doesn't unwrap thenables, we can skip the extra checks appearing in + // Deferred#then to conditionally suppress rejection. + } catch ( value ) { + + // Support: Android 4.0 only + // Strict mode functions invoked without .call/.apply get global-object context + reject.apply( undefined, [ value ] ); + } +} + +jQuery.extend( { + + Deferred: function( func ) { + var tuples = [ + + // action, add listener, callbacks, + // ... .then handlers, argument index, [final state] + [ "notify", "progress", jQuery.Callbacks( "memory" ), + jQuery.Callbacks( "memory" ), 2 ], + [ "resolve", "done", jQuery.Callbacks( "once memory" ), + jQuery.Callbacks( "once memory" ), 0, "resolved" ], + [ "reject", "fail", jQuery.Callbacks( "once memory" ), + jQuery.Callbacks( "once memory" ), 1, "rejected" ] + ], + state = "pending", + promise = { + state: function() { + return state; + }, + always: function() { + deferred.done( arguments ).fail( arguments ); + return this; + }, + "catch": function( fn ) { + return promise.then( null, fn ); + }, + + // Keep pipe for back-compat + pipe: function( /* fnDone, fnFail, fnProgress */ ) { + var fns = arguments; + + return jQuery.Deferred( function( newDefer ) { + jQuery.each( tuples, function( _i, tuple ) { + + // Map tuples (progress, done, fail) to arguments (done, fail, progress) + var fn = isFunction( fns[ tuple[ 4 ] ] ) && fns[ tuple[ 4 ] ]; + + // deferred.progress(function() { bind to newDefer or newDefer.notify }) + // deferred.done(function() { bind to newDefer or newDefer.resolve }) + // deferred.fail(function() { bind to newDefer or newDefer.reject }) + deferred[ tuple[ 1 ] ]( function() { + var returned = fn && fn.apply( this, arguments ); + if ( returned && isFunction( returned.promise ) ) { + returned.promise() + .progress( newDefer.notify ) + .done( newDefer.resolve ) + .fail( newDefer.reject ); + } else { + newDefer[ tuple[ 0 ] + "With" ]( + this, + fn ? [ returned ] : arguments + ); + } + } ); + } ); + fns = null; + } ).promise(); + }, + then: function( onFulfilled, onRejected, onProgress ) { + var maxDepth = 0; + function resolve( depth, deferred, handler, special ) { + return function() { + var that = this, + args = arguments, + mightThrow = function() { + var returned, then; + + // Support: Promises/A+ section 2.3.3.3.3 + // https://promisesaplus.com/#point-59 + // Ignore double-resolution attempts + if ( depth < maxDepth ) { + return; + } + + returned = handler.apply( that, args ); + + // Support: Promises/A+ section 2.3.1 + // https://promisesaplus.com/#point-48 + if ( returned === deferred.promise() ) { + throw new TypeError( "Thenable self-resolution" ); + } + + // Support: Promises/A+ sections 2.3.3.1, 3.5 + // https://promisesaplus.com/#point-54 + // https://promisesaplus.com/#point-75 + // Retrieve `then` only once + then = returned && + + // Support: Promises/A+ section 2.3.4 + // https://promisesaplus.com/#point-64 + // Only check objects and functions for thenability + ( typeof returned === "object" || + typeof returned === "function" ) && + returned.then; + + // Handle a returned thenable + if ( isFunction( then ) ) { + + // Special processors (notify) just wait for resolution + if ( special ) { + then.call( + returned, + resolve( maxDepth, deferred, Identity, special ), + resolve( maxDepth, deferred, Thrower, special ) + ); + + // Normal processors (resolve) also hook into progress + } else { + + // ...and disregard older resolution values + maxDepth++; + + then.call( + returned, + resolve( maxDepth, deferred, Identity, special ), + resolve( maxDepth, deferred, Thrower, special ), + resolve( maxDepth, deferred, Identity, + deferred.notifyWith ) + ); + } + + // Handle all other returned values + } else { + + // Only substitute handlers pass on context + // and multiple values (non-spec behavior) + if ( handler !== Identity ) { + that = undefined; + args = [ returned ]; + } + + // Process the value(s) + // Default process is resolve + ( special || deferred.resolveWith )( that, args ); + } + }, + + // Only normal processors (resolve) catch and reject exceptions + process = special ? + mightThrow : + function() { + try { + mightThrow(); + } catch ( e ) { + + if ( jQuery.Deferred.exceptionHook ) { + jQuery.Deferred.exceptionHook( e, + process.stackTrace ); + } + + // Support: Promises/A+ section 2.3.3.3.4.1 + // https://promisesaplus.com/#point-61 + // Ignore post-resolution exceptions + if ( depth + 1 >= maxDepth ) { + + // Only substitute handlers pass on context + // and multiple values (non-spec behavior) + if ( handler !== Thrower ) { + that = undefined; + args = [ e ]; + } + + deferred.rejectWith( that, args ); + } + } + }; + + // Support: Promises/A+ section 2.3.3.3.1 + // https://promisesaplus.com/#point-57 + // Re-resolve promises immediately to dodge false rejection from + // subsequent errors + if ( depth ) { + process(); + } else { + + // Call an optional hook to record the stack, in case of exception + // since it's otherwise lost when execution goes async + if ( jQuery.Deferred.getStackHook ) { + process.stackTrace = jQuery.Deferred.getStackHook(); + } + window.setTimeout( process ); + } + }; + } + + return jQuery.Deferred( function( newDefer ) { + + // progress_handlers.add( ... ) + tuples[ 0 ][ 3 ].add( + resolve( + 0, + newDefer, + isFunction( onProgress ) ? + onProgress : + Identity, + newDefer.notifyWith + ) + ); + + // fulfilled_handlers.add( ... ) + tuples[ 1 ][ 3 ].add( + resolve( + 0, + newDefer, + isFunction( onFulfilled ) ? + onFulfilled : + Identity + ) + ); + + // rejected_handlers.add( ... ) + tuples[ 2 ][ 3 ].add( + resolve( + 0, + newDefer, + isFunction( onRejected ) ? + onRejected : + Thrower + ) + ); + } ).promise(); + }, + + // Get a promise for this deferred + // If obj is provided, the promise aspect is added to the object + promise: function( obj ) { + return obj != null ? jQuery.extend( obj, promise ) : promise; + } + }, + deferred = {}; + + // Add list-specific methods + jQuery.each( tuples, function( i, tuple ) { + var list = tuple[ 2 ], + stateString = tuple[ 5 ]; + + // promise.progress = list.add + // promise.done = list.add + // promise.fail = list.add + promise[ tuple[ 1 ] ] = list.add; + + // Handle state + if ( stateString ) { + list.add( + function() { + + // state = "resolved" (i.e., fulfilled) + // state = "rejected" + state = stateString; + }, + + // rejected_callbacks.disable + // fulfilled_callbacks.disable + tuples[ 3 - i ][ 2 ].disable, + + // rejected_handlers.disable + // fulfilled_handlers.disable + tuples[ 3 - i ][ 3 ].disable, + + // progress_callbacks.lock + tuples[ 0 ][ 2 ].lock, + + // progress_handlers.lock + tuples[ 0 ][ 3 ].lock + ); + } + + // progress_handlers.fire + // fulfilled_handlers.fire + // rejected_handlers.fire + list.add( tuple[ 3 ].fire ); + + // deferred.notify = function() { deferred.notifyWith(...) } + // deferred.resolve = function() { deferred.resolveWith(...) } + // deferred.reject = function() { deferred.rejectWith(...) } + deferred[ tuple[ 0 ] ] = function() { + deferred[ tuple[ 0 ] + "With" ]( this === deferred ? undefined : this, arguments ); + return this; + }; + + // deferred.notifyWith = list.fireWith + // deferred.resolveWith = list.fireWith + // deferred.rejectWith = list.fireWith + deferred[ tuple[ 0 ] + "With" ] = list.fireWith; + } ); + + // Make the deferred a promise + promise.promise( deferred ); + + // Call given func if any + if ( func ) { + func.call( deferred, deferred ); + } + + // All done! + return deferred; + }, + + // Deferred helper + when: function( singleValue ) { + var + + // count of uncompleted subordinates + remaining = arguments.length, + + // count of unprocessed arguments + i = remaining, + + // subordinate fulfillment data + resolveContexts = Array( i ), + resolveValues = slice.call( arguments ), + + // the master Deferred + master = jQuery.Deferred(), + + // subordinate callback factory + updateFunc = function( i ) { + return function( value ) { + resolveContexts[ i ] = this; + resolveValues[ i ] = arguments.length > 1 ? slice.call( arguments ) : value; + if ( !( --remaining ) ) { + master.resolveWith( resolveContexts, resolveValues ); + } + }; + }; + + // Single- and empty arguments are adopted like Promise.resolve + if ( remaining <= 1 ) { + adoptValue( singleValue, master.done( updateFunc( i ) ).resolve, master.reject, + !remaining ); + + // Use .then() to unwrap secondary thenables (cf. gh-3000) + if ( master.state() === "pending" || + isFunction( resolveValues[ i ] && resolveValues[ i ].then ) ) { + + return master.then(); + } + } + + // Multiple arguments are aggregated like Promise.all array elements + while ( i-- ) { + adoptValue( resolveValues[ i ], updateFunc( i ), master.reject ); + } + + return master.promise(); + } +} ); + + +// These usually indicate a programmer mistake during development, +// warn about them ASAP rather than swallowing them by default. +var rerrorNames = /^(Eval|Internal|Range|Reference|Syntax|Type|URI)Error$/; + +jQuery.Deferred.exceptionHook = function( error, stack ) { + + // Support: IE 8 - 9 only + // Console exists when dev tools are open, which can happen at any time + if ( window.console && window.console.warn && error && rerrorNames.test( error.name ) ) { + window.console.warn( "jQuery.Deferred exception: " + error.message, error.stack, stack ); + } +}; + + + + +jQuery.readyException = function( error ) { + window.setTimeout( function() { + throw error; + } ); +}; + + + + +// The deferred used on DOM ready +var readyList = jQuery.Deferred(); + +jQuery.fn.ready = function( fn ) { + + readyList + .then( fn ) + + // Wrap jQuery.readyException in a function so that the lookup + // happens at the time of error handling instead of callback + // registration. + .catch( function( error ) { + jQuery.readyException( error ); + } ); + + return this; +}; + +jQuery.extend( { + + // Is the DOM ready to be used? Set to true once it occurs. + isReady: false, + + // A counter to track how many items to wait for before + // the ready event fires. See #6781 + readyWait: 1, + + // Handle when the DOM is ready + ready: function( wait ) { + + // Abort if there are pending holds or we're already ready + if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) { + return; + } + + // Remember that the DOM is ready + jQuery.isReady = true; + + // If a normal DOM Ready event fired, decrement, and wait if need be + if ( wait !== true && --jQuery.readyWait > 0 ) { + return; + } + + // If there are functions bound, to execute + readyList.resolveWith( document, [ jQuery ] ); + } +} ); + +jQuery.ready.then = readyList.then; + +// The ready event handler and self cleanup method +function completed() { + document.removeEventListener( "DOMContentLoaded", completed ); + window.removeEventListener( "load", completed ); + jQuery.ready(); +} + +// Catch cases where $(document).ready() is called +// after the browser event has already occurred. +// Support: IE <=9 - 10 only +// Older IE sometimes signals "interactive" too soon +if ( document.readyState === "complete" || + ( document.readyState !== "loading" && !document.documentElement.doScroll ) ) { + + // Handle it asynchronously to allow scripts the opportunity to delay ready + window.setTimeout( jQuery.ready ); + +} else { + + // Use the handy event callback + document.addEventListener( "DOMContentLoaded", completed ); + + // A fallback to window.onload, that will always work + window.addEventListener( "load", completed ); +} + + + + +// Multifunctional method to get and set values of a collection +// The value/s can optionally be executed if it's a function +var access = function( elems, fn, key, value, chainable, emptyGet, raw ) { + var i = 0, + len = elems.length, + bulk = key == null; + + // Sets many values + if ( toType( key ) === "object" ) { + chainable = true; + for ( i in key ) { + access( elems, fn, i, key[ i ], true, emptyGet, raw ); + } + + // Sets one value + } else if ( value !== undefined ) { + chainable = true; + + if ( !isFunction( value ) ) { + raw = true; + } + + if ( bulk ) { + + // Bulk operations run against the entire set + if ( raw ) { + fn.call( elems, value ); + fn = null; + + // ...except when executing function values + } else { + bulk = fn; + fn = function( elem, _key, value ) { + return bulk.call( jQuery( elem ), value ); + }; + } + } + + if ( fn ) { + for ( ; i < len; i++ ) { + fn( + elems[ i ], key, raw ? + value : + value.call( elems[ i ], i, fn( elems[ i ], key ) ) + ); + } + } + } + + if ( chainable ) { + return elems; + } + + // Gets + if ( bulk ) { + return fn.call( elems ); + } + + return len ? fn( elems[ 0 ], key ) : emptyGet; +}; + + +// Matches dashed string for camelizing +var rmsPrefix = /^-ms-/, + rdashAlpha = /-([a-z])/g; + +// Used by camelCase as callback to replace() +function fcamelCase( _all, letter ) { + return letter.toUpperCase(); +} + +// Convert dashed to camelCase; used by the css and data modules +// Support: IE <=9 - 11, Edge 12 - 15 +// Microsoft forgot to hump their vendor prefix (#9572) +function camelCase( string ) { + return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase ); +} +var acceptData = function( owner ) { + + // Accepts only: + // - Node + // - Node.ELEMENT_NODE + // - Node.DOCUMENT_NODE + // - Object + // - Any + return owner.nodeType === 1 || owner.nodeType === 9 || !( +owner.nodeType ); +}; + + + + +function Data() { + this.expando = jQuery.expando + Data.uid++; +} + +Data.uid = 1; + +Data.prototype = { + + cache: function( owner ) { + + // Check if the owner object already has a cache + var value = owner[ this.expando ]; + + // If not, create one + if ( !value ) { + value = {}; + + // We can accept data for non-element nodes in modern browsers, + // but we should not, see #8335. + // Always return an empty object. + if ( acceptData( owner ) ) { + + // If it is a node unlikely to be stringify-ed or looped over + // use plain assignment + if ( owner.nodeType ) { + owner[ this.expando ] = value; + + // Otherwise secure it in a non-enumerable property + // configurable must be true to allow the property to be + // deleted when data is removed + } else { + Object.defineProperty( owner, this.expando, { + value: value, + configurable: true + } ); + } + } + } + + return value; + }, + set: function( owner, data, value ) { + var prop, + cache = this.cache( owner ); + + // Handle: [ owner, key, value ] args + // Always use camelCase key (gh-2257) + if ( typeof data === "string" ) { + cache[ camelCase( data ) ] = value; + + // Handle: [ owner, { properties } ] args + } else { + + // Copy the properties one-by-one to the cache object + for ( prop in data ) { + cache[ camelCase( prop ) ] = data[ prop ]; + } + } + return cache; + }, + get: function( owner, key ) { + return key === undefined ? + this.cache( owner ) : + + // Always use camelCase key (gh-2257) + owner[ this.expando ] && owner[ this.expando ][ camelCase( key ) ]; + }, + access: function( owner, key, value ) { + + // In cases where either: + // + // 1. No key was specified + // 2. A string key was specified, but no value provided + // + // Take the "read" path and allow the get method to determine + // which value to return, respectively either: + // + // 1. The entire cache object + // 2. The data stored at the key + // + if ( key === undefined || + ( ( key && typeof key === "string" ) && value === undefined ) ) { + + return this.get( owner, key ); + } + + // When the key is not a string, or both a key and value + // are specified, set or extend (existing objects) with either: + // + // 1. An object of properties + // 2. A key and value + // + this.set( owner, key, value ); + + // Since the "set" path can have two possible entry points + // return the expected data based on which path was taken[*] + return value !== undefined ? value : key; + }, + remove: function( owner, key ) { + var i, + cache = owner[ this.expando ]; + + if ( cache === undefined ) { + return; + } + + if ( key !== undefined ) { + + // Support array or space separated string of keys + if ( Array.isArray( key ) ) { + + // If key is an array of keys... + // We always set camelCase keys, so remove that. + key = key.map( camelCase ); + } else { + key = camelCase( key ); + + // If a key with the spaces exists, use it. + // Otherwise, create an array by matching non-whitespace + key = key in cache ? + [ key ] : + ( key.match( rnothtmlwhite ) || [] ); + } + + i = key.length; + + while ( i-- ) { + delete cache[ key[ i ] ]; + } + } + + // Remove the expando if there's no more data + if ( key === undefined || jQuery.isEmptyObject( cache ) ) { + + // Support: Chrome <=35 - 45 + // Webkit & Blink performance suffers when deleting properties + // from DOM nodes, so set to undefined instead + // https://bugs.chromium.org/p/chromium/issues/detail?id=378607 (bug restricted) + if ( owner.nodeType ) { + owner[ this.expando ] = undefined; + } else { + delete owner[ this.expando ]; + } + } + }, + hasData: function( owner ) { + var cache = owner[ this.expando ]; + return cache !== undefined && !jQuery.isEmptyObject( cache ); + } +}; +var dataPriv = new Data(); + +var dataUser = new Data(); + + + +// Implementation Summary +// +// 1. Enforce API surface and semantic compatibility with 1.9.x branch +// 2. Improve the module's maintainability by reducing the storage +// paths to a single mechanism. +// 3. Use the same single mechanism to support "private" and "user" data. +// 4. _Never_ expose "private" data to user code (TODO: Drop _data, _removeData) +// 5. Avoid exposing implementation details on user objects (eg. expando properties) +// 6. Provide a clear path for implementation upgrade to WeakMap in 2014 + +var rbrace = /^(?:\{[\w\W]*\}|\[[\w\W]*\])$/, + rmultiDash = /[A-Z]/g; + +function getData( data ) { + if ( data === "true" ) { + return true; + } + + if ( data === "false" ) { + return false; + } + + if ( data === "null" ) { + return null; + } + + // Only convert to a number if it doesn't change the string + if ( data === +data + "" ) { + return +data; + } + + if ( rbrace.test( data ) ) { + return JSON.parse( data ); + } + + return data; +} + +function dataAttr( elem, key, data ) { + var name; + + // If nothing was found internally, try to fetch any + // data from the HTML5 data-* attribute + if ( data === undefined && elem.nodeType === 1 ) { + name = "data-" + key.replace( rmultiDash, "-$&" ).toLowerCase(); + data = elem.getAttribute( name ); + + if ( typeof data === "string" ) { + try { + data = getData( data ); + } catch ( e ) {} + + // Make sure we set the data so it isn't changed later + dataUser.set( elem, key, data ); + } else { + data = undefined; + } + } + return data; +} + +jQuery.extend( { + hasData: function( elem ) { + return dataUser.hasData( elem ) || dataPriv.hasData( elem ); + }, + + data: function( elem, name, data ) { + return dataUser.access( elem, name, data ); + }, + + removeData: function( elem, name ) { + dataUser.remove( elem, name ); + }, + + // TODO: Now that all calls to _data and _removeData have been replaced + // with direct calls to dataPriv methods, these can be deprecated. + _data: function( elem, name, data ) { + return dataPriv.access( elem, name, data ); + }, + + _removeData: function( elem, name ) { + dataPriv.remove( elem, name ); + } +} ); + +jQuery.fn.extend( { + data: function( key, value ) { + var i, name, data, + elem = this[ 0 ], + attrs = elem && elem.attributes; + + // Gets all values + if ( key === undefined ) { + if ( this.length ) { + data = dataUser.get( elem ); + + if ( elem.nodeType === 1 && !dataPriv.get( elem, "hasDataAttrs" ) ) { + i = attrs.length; + while ( i-- ) { + + // Support: IE 11 only + // The attrs elements can be null (#14894) + if ( attrs[ i ] ) { + name = attrs[ i ].name; + if ( name.indexOf( "data-" ) === 0 ) { + name = camelCase( name.slice( 5 ) ); + dataAttr( elem, name, data[ name ] ); + } + } + } + dataPriv.set( elem, "hasDataAttrs", true ); + } + } + + return data; + } + + // Sets multiple values + if ( typeof key === "object" ) { + return this.each( function() { + dataUser.set( this, key ); + } ); + } + + return access( this, function( value ) { + var data; + + // The calling jQuery object (element matches) is not empty + // (and therefore has an element appears at this[ 0 ]) and the + // `value` parameter was not undefined. An empty jQuery object + // will result in `undefined` for elem = this[ 0 ] which will + // throw an exception if an attempt to read a data cache is made. + if ( elem && value === undefined ) { + + // Attempt to get data from the cache + // The key will always be camelCased in Data + data = dataUser.get( elem, key ); + if ( data !== undefined ) { + return data; + } + + // Attempt to "discover" the data in + // HTML5 custom data-* attrs + data = dataAttr( elem, key ); + if ( data !== undefined ) { + return data; + } + + // We tried really hard, but the data doesn't exist. + return; + } + + // Set the data... + this.each( function() { + + // We always store the camelCased key + dataUser.set( this, key, value ); + } ); + }, null, value, arguments.length > 1, null, true ); + }, + + removeData: function( key ) { + return this.each( function() { + dataUser.remove( this, key ); + } ); + } +} ); + + +jQuery.extend( { + queue: function( elem, type, data ) { + var queue; + + if ( elem ) { + type = ( type || "fx" ) + "queue"; + queue = dataPriv.get( elem, type ); + + // Speed up dequeue by getting out quickly if this is just a lookup + if ( data ) { + if ( !queue || Array.isArray( data ) ) { + queue = dataPriv.access( elem, type, jQuery.makeArray( data ) ); + } else { + queue.push( data ); + } + } + return queue || []; + } + }, + + dequeue: function( elem, type ) { + type = type || "fx"; + + var queue = jQuery.queue( elem, type ), + startLength = queue.length, + fn = queue.shift(), + hooks = jQuery._queueHooks( elem, type ), + next = function() { + jQuery.dequeue( elem, type ); + }; + + // If the fx queue is dequeued, always remove the progress sentinel + if ( fn === "inprogress" ) { + fn = queue.shift(); + startLength--; + } + + if ( fn ) { + + // Add a progress sentinel to prevent the fx queue from being + // automatically dequeued + if ( type === "fx" ) { + queue.unshift( "inprogress" ); + } + + // Clear up the last queue stop function + delete hooks.stop; + fn.call( elem, next, hooks ); + } + + if ( !startLength && hooks ) { + hooks.empty.fire(); + } + }, + + // Not public - generate a queueHooks object, or return the current one + _queueHooks: function( elem, type ) { + var key = type + "queueHooks"; + return dataPriv.get( elem, key ) || dataPriv.access( elem, key, { + empty: jQuery.Callbacks( "once memory" ).add( function() { + dataPriv.remove( elem, [ type + "queue", key ] ); + } ) + } ); + } +} ); + +jQuery.fn.extend( { + queue: function( type, data ) { + var setter = 2; + + if ( typeof type !== "string" ) { + data = type; + type = "fx"; + setter--; + } + + if ( arguments.length < setter ) { + return jQuery.queue( this[ 0 ], type ); + } + + return data === undefined ? + this : + this.each( function() { + var queue = jQuery.queue( this, type, data ); + + // Ensure a hooks for this queue + jQuery._queueHooks( this, type ); + + if ( type === "fx" && queue[ 0 ] !== "inprogress" ) { + jQuery.dequeue( this, type ); + } + } ); + }, + dequeue: function( type ) { + return this.each( function() { + jQuery.dequeue( this, type ); + } ); + }, + clearQueue: function( type ) { + return this.queue( type || "fx", [] ); + }, + + // Get a promise resolved when queues of a certain type + // are emptied (fx is the type by default) + promise: function( type, obj ) { + var tmp, + count = 1, + defer = jQuery.Deferred(), + elements = this, + i = this.length, + resolve = function() { + if ( !( --count ) ) { + defer.resolveWith( elements, [ elements ] ); + } + }; + + if ( typeof type !== "string" ) { + obj = type; + type = undefined; + } + type = type || "fx"; + + while ( i-- ) { + tmp = dataPriv.get( elements[ i ], type + "queueHooks" ); + if ( tmp && tmp.empty ) { + count++; + tmp.empty.add( resolve ); + } + } + resolve(); + return defer.promise( obj ); + } +} ); +var pnum = ( /[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/ ).source; + +var rcssNum = new RegExp( "^(?:([+-])=|)(" + pnum + ")([a-z%]*)$", "i" ); + + +var cssExpand = [ "Top", "Right", "Bottom", "Left" ]; + +var documentElement = document.documentElement; + + + + var isAttached = function( elem ) { + return jQuery.contains( elem.ownerDocument, elem ); + }, + composed = { composed: true }; + + // Support: IE 9 - 11+, Edge 12 - 18+, iOS 10.0 - 10.2 only + // Check attachment across shadow DOM boundaries when possible (gh-3504) + // Support: iOS 10.0-10.2 only + // Early iOS 10 versions support `attachShadow` but not `getRootNode`, + // leading to errors. We need to check for `getRootNode`. + if ( documentElement.getRootNode ) { + isAttached = function( elem ) { + return jQuery.contains( elem.ownerDocument, elem ) || + elem.getRootNode( composed ) === elem.ownerDocument; + }; + } +var isHiddenWithinTree = function( elem, el ) { + + // isHiddenWithinTree might be called from jQuery#filter function; + // in that case, element will be second argument + elem = el || elem; + + // Inline style trumps all + return elem.style.display === "none" || + elem.style.display === "" && + + // Otherwise, check computed style + // Support: Firefox <=43 - 45 + // Disconnected elements can have computed display: none, so first confirm that elem is + // in the document. + isAttached( elem ) && + + jQuery.css( elem, "display" ) === "none"; + }; + + + +function adjustCSS( elem, prop, valueParts, tween ) { + var adjusted, scale, + maxIterations = 20, + currentValue = tween ? + function() { + return tween.cur(); + } : + function() { + return jQuery.css( elem, prop, "" ); + }, + initial = currentValue(), + unit = valueParts && valueParts[ 3 ] || ( jQuery.cssNumber[ prop ] ? "" : "px" ), + + // Starting value computation is required for potential unit mismatches + initialInUnit = elem.nodeType && + ( jQuery.cssNumber[ prop ] || unit !== "px" && +initial ) && + rcssNum.exec( jQuery.css( elem, prop ) ); + + if ( initialInUnit && initialInUnit[ 3 ] !== unit ) { + + // Support: Firefox <=54 + // Halve the iteration target value to prevent interference from CSS upper bounds (gh-2144) + initial = initial / 2; + + // Trust units reported by jQuery.css + unit = unit || initialInUnit[ 3 ]; + + // Iteratively approximate from a nonzero starting point + initialInUnit = +initial || 1; + + while ( maxIterations-- ) { + + // Evaluate and update our best guess (doubling guesses that zero out). + // Finish if the scale equals or crosses 1 (making the old*new product non-positive). + jQuery.style( elem, prop, initialInUnit + unit ); + if ( ( 1 - scale ) * ( 1 - ( scale = currentValue() / initial || 0.5 ) ) <= 0 ) { + maxIterations = 0; + } + initialInUnit = initialInUnit / scale; + + } + + initialInUnit = initialInUnit * 2; + jQuery.style( elem, prop, initialInUnit + unit ); + + // Make sure we update the tween properties later on + valueParts = valueParts || []; + } + + if ( valueParts ) { + initialInUnit = +initialInUnit || +initial || 0; + + // Apply relative offset (+=/-=) if specified + adjusted = valueParts[ 1 ] ? + initialInUnit + ( valueParts[ 1 ] + 1 ) * valueParts[ 2 ] : + +valueParts[ 2 ]; + if ( tween ) { + tween.unit = unit; + tween.start = initialInUnit; + tween.end = adjusted; + } + } + return adjusted; +} + + +var defaultDisplayMap = {}; + +function getDefaultDisplay( elem ) { + var temp, + doc = elem.ownerDocument, + nodeName = elem.nodeName, + display = defaultDisplayMap[ nodeName ]; + + if ( display ) { + return display; + } + + temp = doc.body.appendChild( doc.createElement( nodeName ) ); + display = jQuery.css( temp, "display" ); + + temp.parentNode.removeChild( temp ); + + if ( display === "none" ) { + display = "block"; + } + defaultDisplayMap[ nodeName ] = display; + + return display; +} + +function showHide( elements, show ) { + var display, elem, + values = [], + index = 0, + length = elements.length; + + // Determine new display value for elements that need to change + for ( ; index < length; index++ ) { + elem = elements[ index ]; + if ( !elem.style ) { + continue; + } + + display = elem.style.display; + if ( show ) { + + // Since we force visibility upon cascade-hidden elements, an immediate (and slow) + // check is required in this first loop unless we have a nonempty display value (either + // inline or about-to-be-restored) + if ( display === "none" ) { + values[ index ] = dataPriv.get( elem, "display" ) || null; + if ( !values[ index ] ) { + elem.style.display = ""; + } + } + if ( elem.style.display === "" && isHiddenWithinTree( elem ) ) { + values[ index ] = getDefaultDisplay( elem ); + } + } else { + if ( display !== "none" ) { + values[ index ] = "none"; + + // Remember what we're overwriting + dataPriv.set( elem, "display", display ); + } + } + } + + // Set the display of the elements in a second loop to avoid constant reflow + for ( index = 0; index < length; index++ ) { + if ( values[ index ] != null ) { + elements[ index ].style.display = values[ index ]; + } + } + + return elements; +} + +jQuery.fn.extend( { + show: function() { + return showHide( this, true ); + }, + hide: function() { + return showHide( this ); + }, + toggle: function( state ) { + if ( typeof state === "boolean" ) { + return state ? this.show() : this.hide(); + } + + return this.each( function() { + if ( isHiddenWithinTree( this ) ) { + jQuery( this ).show(); + } else { + jQuery( this ).hide(); + } + } ); + } +} ); +var rcheckableType = ( /^(?:checkbox|radio)$/i ); + +var rtagName = ( /<([a-z][^\/\0>\x20\t\r\n\f]*)/i ); + +var rscriptType = ( /^$|^module$|\/(?:java|ecma)script/i ); + + + +( function() { + var fragment = document.createDocumentFragment(), + div = fragment.appendChild( document.createElement( "div" ) ), + input = document.createElement( "input" ); + + // Support: Android 4.0 - 4.3 only + // Check state lost if the name is set (#11217) + // Support: Windows Web Apps (WWA) + // `name` and `type` must use .setAttribute for WWA (#14901) + input.setAttribute( "type", "radio" ); + input.setAttribute( "checked", "checked" ); + input.setAttribute( "name", "t" ); + + div.appendChild( input ); + + // Support: Android <=4.1 only + // Older WebKit doesn't clone checked state correctly in fragments + support.checkClone = div.cloneNode( true ).cloneNode( true ).lastChild.checked; + + // Support: IE <=11 only + // Make sure textarea (and checkbox) defaultValue is properly cloned + div.innerHTML = ""; + support.noCloneChecked = !!div.cloneNode( true ).lastChild.defaultValue; + + // Support: IE <=9 only + // IE <=9 replaces "; + support.option = !!div.lastChild; +} )(); + + +// We have to close these tags to support XHTML (#13200) +var wrapMap = { + + // XHTML parsers do not magically insert elements in the + // same way that tag soup parsers do. So we cannot shorten + // this by omitting or other required elements. + thead: [ 1, "", "
" ], + col: [ 2, "", "
" ], + tr: [ 2, "", "
" ], + td: [ 3, "", "
" ], + + _default: [ 0, "", "" ] +}; + +wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; +wrapMap.th = wrapMap.td; + +// Support: IE <=9 only +if ( !support.option ) { + wrapMap.optgroup = wrapMap.option = [ 1, "" ]; +} + + +function getAll( context, tag ) { + + // Support: IE <=9 - 11 only + // Use typeof to avoid zero-argument method invocation on host objects (#15151) + var ret; + + if ( typeof context.getElementsByTagName !== "undefined" ) { + ret = context.getElementsByTagName( tag || "*" ); + + } else if ( typeof context.querySelectorAll !== "undefined" ) { + ret = context.querySelectorAll( tag || "*" ); + + } else { + ret = []; + } + + if ( tag === undefined || tag && nodeName( context, tag ) ) { + return jQuery.merge( [ context ], ret ); + } + + return ret; +} + + +// Mark scripts as having already been evaluated +function setGlobalEval( elems, refElements ) { + var i = 0, + l = elems.length; + + for ( ; i < l; i++ ) { + dataPriv.set( + elems[ i ], + "globalEval", + !refElements || dataPriv.get( refElements[ i ], "globalEval" ) + ); + } +} + + +var rhtml = /<|&#?\w+;/; + +function buildFragment( elems, context, scripts, selection, ignored ) { + var elem, tmp, tag, wrap, attached, j, + fragment = context.createDocumentFragment(), + nodes = [], + i = 0, + l = elems.length; + + for ( ; i < l; i++ ) { + elem = elems[ i ]; + + if ( elem || elem === 0 ) { + + // Add nodes directly + if ( toType( elem ) === "object" ) { + + // Support: Android <=4.0 only, PhantomJS 1 only + // push.apply(_, arraylike) throws on ancient WebKit + jQuery.merge( nodes, elem.nodeType ? [ elem ] : elem ); + + // Convert non-html into a text node + } else if ( !rhtml.test( elem ) ) { + nodes.push( context.createTextNode( elem ) ); + + // Convert html into DOM nodes + } else { + tmp = tmp || fragment.appendChild( context.createElement( "div" ) ); + + // Deserialize a standard representation + tag = ( rtagName.exec( elem ) || [ "", "" ] )[ 1 ].toLowerCase(); + wrap = wrapMap[ tag ] || wrapMap._default; + tmp.innerHTML = wrap[ 1 ] + jQuery.htmlPrefilter( elem ) + wrap[ 2 ]; + + // Descend through wrappers to the right content + j = wrap[ 0 ]; + while ( j-- ) { + tmp = tmp.lastChild; + } + + // Support: Android <=4.0 only, PhantomJS 1 only + // push.apply(_, arraylike) throws on ancient WebKit + jQuery.merge( nodes, tmp.childNodes ); + + // Remember the top-level container + tmp = fragment.firstChild; + + // Ensure the created nodes are orphaned (#12392) + tmp.textContent = ""; + } + } + } + + // Remove wrapper from fragment + fragment.textContent = ""; + + i = 0; + while ( ( elem = nodes[ i++ ] ) ) { + + // Skip elements already in the context collection (trac-4087) + if ( selection && jQuery.inArray( elem, selection ) > -1 ) { + if ( ignored ) { + ignored.push( elem ); + } + continue; + } + + attached = isAttached( elem ); + + // Append to fragment + tmp = getAll( fragment.appendChild( elem ), "script" ); + + // Preserve script evaluation history + if ( attached ) { + setGlobalEval( tmp ); + } + + // Capture executables + if ( scripts ) { + j = 0; + while ( ( elem = tmp[ j++ ] ) ) { + if ( rscriptType.test( elem.type || "" ) ) { + scripts.push( elem ); + } + } + } + } + + return fragment; +} + + +var + rkeyEvent = /^key/, + rmouseEvent = /^(?:mouse|pointer|contextmenu|drag|drop)|click/, + rtypenamespace = /^([^.]*)(?:\.(.+)|)/; + +function returnTrue() { + return true; +} + +function returnFalse() { + return false; +} + +// Support: IE <=9 - 11+ +// focus() and blur() are asynchronous, except when they are no-op. +// So expect focus to be synchronous when the element is already active, +// and blur to be synchronous when the element is not already active. +// (focus and blur are always synchronous in other supported browsers, +// this just defines when we can count on it). +function expectSync( elem, type ) { + return ( elem === safeActiveElement() ) === ( type === "focus" ); +} + +// Support: IE <=9 only +// Accessing document.activeElement can throw unexpectedly +// https://bugs.jquery.com/ticket/13393 +function safeActiveElement() { + try { + return document.activeElement; + } catch ( err ) { } +} + +function on( elem, types, selector, data, fn, one ) { + var origFn, type; + + // Types can be a map of types/handlers + if ( typeof types === "object" ) { + + // ( types-Object, selector, data ) + if ( typeof selector !== "string" ) { + + // ( types-Object, data ) + data = data || selector; + selector = undefined; + } + for ( type in types ) { + on( elem, type, selector, data, types[ type ], one ); + } + return elem; + } + + if ( data == null && fn == null ) { + + // ( types, fn ) + fn = selector; + data = selector = undefined; + } else if ( fn == null ) { + if ( typeof selector === "string" ) { + + // ( types, selector, fn ) + fn = data; + data = undefined; + } else { + + // ( types, data, fn ) + fn = data; + data = selector; + selector = undefined; + } + } + if ( fn === false ) { + fn = returnFalse; + } else if ( !fn ) { + return elem; + } + + if ( one === 1 ) { + origFn = fn; + fn = function( event ) { + + // Can use an empty set, since event contains the info + jQuery().off( event ); + return origFn.apply( this, arguments ); + }; + + // Use same guid so caller can remove using origFn + fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ ); + } + return elem.each( function() { + jQuery.event.add( this, types, fn, data, selector ); + } ); +} + +/* + * Helper functions for managing events -- not part of the public interface. + * Props to Dean Edwards' addEvent library for many of the ideas. + */ +jQuery.event = { + + global: {}, + + add: function( elem, types, handler, data, selector ) { + + var handleObjIn, eventHandle, tmp, + events, t, handleObj, + special, handlers, type, namespaces, origType, + elemData = dataPriv.get( elem ); + + // Only attach events to objects that accept data + if ( !acceptData( elem ) ) { + return; + } + + // Caller can pass in an object of custom data in lieu of the handler + if ( handler.handler ) { + handleObjIn = handler; + handler = handleObjIn.handler; + selector = handleObjIn.selector; + } + + // Ensure that invalid selectors throw exceptions at attach time + // Evaluate against documentElement in case elem is a non-element node (e.g., document) + if ( selector ) { + jQuery.find.matchesSelector( documentElement, selector ); + } + + // Make sure that the handler has a unique ID, used to find/remove it later + if ( !handler.guid ) { + handler.guid = jQuery.guid++; + } + + // Init the element's event structure and main handler, if this is the first + if ( !( events = elemData.events ) ) { + events = elemData.events = Object.create( null ); + } + if ( !( eventHandle = elemData.handle ) ) { + eventHandle = elemData.handle = function( e ) { + + // Discard the second event of a jQuery.event.trigger() and + // when an event is called after a page has unloaded + return typeof jQuery !== "undefined" && jQuery.event.triggered !== e.type ? + jQuery.event.dispatch.apply( elem, arguments ) : undefined; + }; + } + + // Handle multiple events separated by a space + types = ( types || "" ).match( rnothtmlwhite ) || [ "" ]; + t = types.length; + while ( t-- ) { + tmp = rtypenamespace.exec( types[ t ] ) || []; + type = origType = tmp[ 1 ]; + namespaces = ( tmp[ 2 ] || "" ).split( "." ).sort(); + + // There *must* be a type, no attaching namespace-only handlers + if ( !type ) { + continue; + } + + // If event changes its type, use the special event handlers for the changed type + special = jQuery.event.special[ type ] || {}; + + // If selector defined, determine special event api type, otherwise given type + type = ( selector ? special.delegateType : special.bindType ) || type; + + // Update special based on newly reset type + special = jQuery.event.special[ type ] || {}; + + // handleObj is passed to all event handlers + handleObj = jQuery.extend( { + type: type, + origType: origType, + data: data, + handler: handler, + guid: handler.guid, + selector: selector, + needsContext: selector && jQuery.expr.match.needsContext.test( selector ), + namespace: namespaces.join( "." ) + }, handleObjIn ); + + // Init the event handler queue if we're the first + if ( !( handlers = events[ type ] ) ) { + handlers = events[ type ] = []; + handlers.delegateCount = 0; + + // Only use addEventListener if the special events handler returns false + if ( !special.setup || + special.setup.call( elem, data, namespaces, eventHandle ) === false ) { + + if ( elem.addEventListener ) { + elem.addEventListener( type, eventHandle ); + } + } + } + + if ( special.add ) { + special.add.call( elem, handleObj ); + + if ( !handleObj.handler.guid ) { + handleObj.handler.guid = handler.guid; + } + } + + // Add to the element's handler list, delegates in front + if ( selector ) { + handlers.splice( handlers.delegateCount++, 0, handleObj ); + } else { + handlers.push( handleObj ); + } + + // Keep track of which events have ever been used, for event optimization + jQuery.event.global[ type ] = true; + } + + }, + + // Detach an event or set of events from an element + remove: function( elem, types, handler, selector, mappedTypes ) { + + var j, origCount, tmp, + events, t, handleObj, + special, handlers, type, namespaces, origType, + elemData = dataPriv.hasData( elem ) && dataPriv.get( elem ); + + if ( !elemData || !( events = elemData.events ) ) { + return; + } + + // Once for each type.namespace in types; type may be omitted + types = ( types || "" ).match( rnothtmlwhite ) || [ "" ]; + t = types.length; + while ( t-- ) { + tmp = rtypenamespace.exec( types[ t ] ) || []; + type = origType = tmp[ 1 ]; + namespaces = ( tmp[ 2 ] || "" ).split( "." ).sort(); + + // Unbind all events (on this namespace, if provided) for the element + if ( !type ) { + for ( type in events ) { + jQuery.event.remove( elem, type + types[ t ], handler, selector, true ); + } + continue; + } + + special = jQuery.event.special[ type ] || {}; + type = ( selector ? special.delegateType : special.bindType ) || type; + handlers = events[ type ] || []; + tmp = tmp[ 2 ] && + new RegExp( "(^|\\.)" + namespaces.join( "\\.(?:.*\\.|)" ) + "(\\.|$)" ); + + // Remove matching events + origCount = j = handlers.length; + while ( j-- ) { + handleObj = handlers[ j ]; + + if ( ( mappedTypes || origType === handleObj.origType ) && + ( !handler || handler.guid === handleObj.guid ) && + ( !tmp || tmp.test( handleObj.namespace ) ) && + ( !selector || selector === handleObj.selector || + selector === "**" && handleObj.selector ) ) { + handlers.splice( j, 1 ); + + if ( handleObj.selector ) { + handlers.delegateCount--; + } + if ( special.remove ) { + special.remove.call( elem, handleObj ); + } + } + } + + // Remove generic event handler if we removed something and no more handlers exist + // (avoids potential for endless recursion during removal of special event handlers) + if ( origCount && !handlers.length ) { + if ( !special.teardown || + special.teardown.call( elem, namespaces, elemData.handle ) === false ) { + + jQuery.removeEvent( elem, type, elemData.handle ); + } + + delete events[ type ]; + } + } + + // Remove data and the expando if it's no longer used + if ( jQuery.isEmptyObject( events ) ) { + dataPriv.remove( elem, "handle events" ); + } + }, + + dispatch: function( nativeEvent ) { + + var i, j, ret, matched, handleObj, handlerQueue, + args = new Array( arguments.length ), + + // Make a writable jQuery.Event from the native event object + event = jQuery.event.fix( nativeEvent ), + + handlers = ( + dataPriv.get( this, "events" ) || Object.create( null ) + )[ event.type ] || [], + special = jQuery.event.special[ event.type ] || {}; + + // Use the fix-ed jQuery.Event rather than the (read-only) native event + args[ 0 ] = event; + + for ( i = 1; i < arguments.length; i++ ) { + args[ i ] = arguments[ i ]; + } + + event.delegateTarget = this; + + // Call the preDispatch hook for the mapped type, and let it bail if desired + if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) { + return; + } + + // Determine handlers + handlerQueue = jQuery.event.handlers.call( this, event, handlers ); + + // Run delegates first; they may want to stop propagation beneath us + i = 0; + while ( ( matched = handlerQueue[ i++ ] ) && !event.isPropagationStopped() ) { + event.currentTarget = matched.elem; + + j = 0; + while ( ( handleObj = matched.handlers[ j++ ] ) && + !event.isImmediatePropagationStopped() ) { + + // If the event is namespaced, then each handler is only invoked if it is + // specially universal or its namespaces are a superset of the event's. + if ( !event.rnamespace || handleObj.namespace === false || + event.rnamespace.test( handleObj.namespace ) ) { + + event.handleObj = handleObj; + event.data = handleObj.data; + + ret = ( ( jQuery.event.special[ handleObj.origType ] || {} ).handle || + handleObj.handler ).apply( matched.elem, args ); + + if ( ret !== undefined ) { + if ( ( event.result = ret ) === false ) { + event.preventDefault(); + event.stopPropagation(); + } + } + } + } + } + + // Call the postDispatch hook for the mapped type + if ( special.postDispatch ) { + special.postDispatch.call( this, event ); + } + + return event.result; + }, + + handlers: function( event, handlers ) { + var i, handleObj, sel, matchedHandlers, matchedSelectors, + handlerQueue = [], + delegateCount = handlers.delegateCount, + cur = event.target; + + // Find delegate handlers + if ( delegateCount && + + // Support: IE <=9 + // Black-hole SVG instance trees (trac-13180) + cur.nodeType && + + // Support: Firefox <=42 + // Suppress spec-violating clicks indicating a non-primary pointer button (trac-3861) + // https://www.w3.org/TR/DOM-Level-3-Events/#event-type-click + // Support: IE 11 only + // ...but not arrow key "clicks" of radio inputs, which can have `button` -1 (gh-2343) + !( event.type === "click" && event.button >= 1 ) ) { + + for ( ; cur !== this; cur = cur.parentNode || this ) { + + // Don't check non-elements (#13208) + // Don't process clicks on disabled elements (#6911, #8165, #11382, #11764) + if ( cur.nodeType === 1 && !( event.type === "click" && cur.disabled === true ) ) { + matchedHandlers = []; + matchedSelectors = {}; + for ( i = 0; i < delegateCount; i++ ) { + handleObj = handlers[ i ]; + + // Don't conflict with Object.prototype properties (#13203) + sel = handleObj.selector + " "; + + if ( matchedSelectors[ sel ] === undefined ) { + matchedSelectors[ sel ] = handleObj.needsContext ? + jQuery( sel, this ).index( cur ) > -1 : + jQuery.find( sel, this, null, [ cur ] ).length; + } + if ( matchedSelectors[ sel ] ) { + matchedHandlers.push( handleObj ); + } + } + if ( matchedHandlers.length ) { + handlerQueue.push( { elem: cur, handlers: matchedHandlers } ); + } + } + } + } + + // Add the remaining (directly-bound) handlers + cur = this; + if ( delegateCount < handlers.length ) { + handlerQueue.push( { elem: cur, handlers: handlers.slice( delegateCount ) } ); + } + + return handlerQueue; + }, + + addProp: function( name, hook ) { + Object.defineProperty( jQuery.Event.prototype, name, { + enumerable: true, + configurable: true, + + get: isFunction( hook ) ? + function() { + if ( this.originalEvent ) { + return hook( this.originalEvent ); + } + } : + function() { + if ( this.originalEvent ) { + return this.originalEvent[ name ]; + } + }, + + set: function( value ) { + Object.defineProperty( this, name, { + enumerable: true, + configurable: true, + writable: true, + value: value + } ); + } + } ); + }, + + fix: function( originalEvent ) { + return originalEvent[ jQuery.expando ] ? + originalEvent : + new jQuery.Event( originalEvent ); + }, + + special: { + load: { + + // Prevent triggered image.load events from bubbling to window.load + noBubble: true + }, + click: { + + // Utilize native event to ensure correct state for checkable inputs + setup: function( data ) { + + // For mutual compressibility with _default, replace `this` access with a local var. + // `|| data` is dead code meant only to preserve the variable through minification. + var el = this || data; + + // Claim the first handler + if ( rcheckableType.test( el.type ) && + el.click && nodeName( el, "input" ) ) { + + // dataPriv.set( el, "click", ... ) + leverageNative( el, "click", returnTrue ); + } + + // Return false to allow normal processing in the caller + return false; + }, + trigger: function( data ) { + + // For mutual compressibility with _default, replace `this` access with a local var. + // `|| data` is dead code meant only to preserve the variable through minification. + var el = this || data; + + // Force setup before triggering a click + if ( rcheckableType.test( el.type ) && + el.click && nodeName( el, "input" ) ) { + + leverageNative( el, "click" ); + } + + // Return non-false to allow normal event-path propagation + return true; + }, + + // For cross-browser consistency, suppress native .click() on links + // Also prevent it if we're currently inside a leveraged native-event stack + _default: function( event ) { + var target = event.target; + return rcheckableType.test( target.type ) && + target.click && nodeName( target, "input" ) && + dataPriv.get( target, "click" ) || + nodeName( target, "a" ); + } + }, + + beforeunload: { + postDispatch: function( event ) { + + // Support: Firefox 20+ + // Firefox doesn't alert if the returnValue field is not set. + if ( event.result !== undefined && event.originalEvent ) { + event.originalEvent.returnValue = event.result; + } + } + } + } +}; + +// Ensure the presence of an event listener that handles manually-triggered +// synthetic events by interrupting progress until reinvoked in response to +// *native* events that it fires directly, ensuring that state changes have +// already occurred before other listeners are invoked. +function leverageNative( el, type, expectSync ) { + + // Missing expectSync indicates a trigger call, which must force setup through jQuery.event.add + if ( !expectSync ) { + if ( dataPriv.get( el, type ) === undefined ) { + jQuery.event.add( el, type, returnTrue ); + } + return; + } + + // Register the controller as a special universal handler for all event namespaces + dataPriv.set( el, type, false ); + jQuery.event.add( el, type, { + namespace: false, + handler: function( event ) { + var notAsync, result, + saved = dataPriv.get( this, type ); + + if ( ( event.isTrigger & 1 ) && this[ type ] ) { + + // Interrupt processing of the outer synthetic .trigger()ed event + // Saved data should be false in such cases, but might be a leftover capture object + // from an async native handler (gh-4350) + if ( !saved.length ) { + + // Store arguments for use when handling the inner native event + // There will always be at least one argument (an event object), so this array + // will not be confused with a leftover capture object. + saved = slice.call( arguments ); + dataPriv.set( this, type, saved ); + + // Trigger the native event and capture its result + // Support: IE <=9 - 11+ + // focus() and blur() are asynchronous + notAsync = expectSync( this, type ); + this[ type ](); + result = dataPriv.get( this, type ); + if ( saved !== result || notAsync ) { + dataPriv.set( this, type, false ); + } else { + result = {}; + } + if ( saved !== result ) { + + // Cancel the outer synthetic event + event.stopImmediatePropagation(); + event.preventDefault(); + return result.value; + } + + // If this is an inner synthetic event for an event with a bubbling surrogate + // (focus or blur), assume that the surrogate already propagated from triggering the + // native event and prevent that from happening again here. + // This technically gets the ordering wrong w.r.t. to `.trigger()` (in which the + // bubbling surrogate propagates *after* the non-bubbling base), but that seems + // less bad than duplication. + } else if ( ( jQuery.event.special[ type ] || {} ).delegateType ) { + event.stopPropagation(); + } + + // If this is a native event triggered above, everything is now in order + // Fire an inner synthetic event with the original arguments + } else if ( saved.length ) { + + // ...and capture the result + dataPriv.set( this, type, { + value: jQuery.event.trigger( + + // Support: IE <=9 - 11+ + // Extend with the prototype to reset the above stopImmediatePropagation() + jQuery.extend( saved[ 0 ], jQuery.Event.prototype ), + saved.slice( 1 ), + this + ) + } ); + + // Abort handling of the native event + event.stopImmediatePropagation(); + } + } + } ); +} + +jQuery.removeEvent = function( elem, type, handle ) { + + // This "if" is needed for plain objects + if ( elem.removeEventListener ) { + elem.removeEventListener( type, handle ); + } +}; + +jQuery.Event = function( src, props ) { + + // Allow instantiation without the 'new' keyword + if ( !( this instanceof jQuery.Event ) ) { + return new jQuery.Event( src, props ); + } + + // Event object + if ( src && src.type ) { + this.originalEvent = src; + this.type = src.type; + + // Events bubbling up the document may have been marked as prevented + // by a handler lower down the tree; reflect the correct value. + this.isDefaultPrevented = src.defaultPrevented || + src.defaultPrevented === undefined && + + // Support: Android <=2.3 only + src.returnValue === false ? + returnTrue : + returnFalse; + + // Create target properties + // Support: Safari <=6 - 7 only + // Target should not be a text node (#504, #13143) + this.target = ( src.target && src.target.nodeType === 3 ) ? + src.target.parentNode : + src.target; + + this.currentTarget = src.currentTarget; + this.relatedTarget = src.relatedTarget; + + // Event type + } else { + this.type = src; + } + + // Put explicitly provided properties onto the event object + if ( props ) { + jQuery.extend( this, props ); + } + + // Create a timestamp if incoming event doesn't have one + this.timeStamp = src && src.timeStamp || Date.now(); + + // Mark it as fixed + this[ jQuery.expando ] = true; +}; + +// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding +// https://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html +jQuery.Event.prototype = { + constructor: jQuery.Event, + isDefaultPrevented: returnFalse, + isPropagationStopped: returnFalse, + isImmediatePropagationStopped: returnFalse, + isSimulated: false, + + preventDefault: function() { + var e = this.originalEvent; + + this.isDefaultPrevented = returnTrue; + + if ( e && !this.isSimulated ) { + e.preventDefault(); + } + }, + stopPropagation: function() { + var e = this.originalEvent; + + this.isPropagationStopped = returnTrue; + + if ( e && !this.isSimulated ) { + e.stopPropagation(); + } + }, + stopImmediatePropagation: function() { + var e = this.originalEvent; + + this.isImmediatePropagationStopped = returnTrue; + + if ( e && !this.isSimulated ) { + e.stopImmediatePropagation(); + } + + this.stopPropagation(); + } +}; + +// Includes all common event props including KeyEvent and MouseEvent specific props +jQuery.each( { + altKey: true, + bubbles: true, + cancelable: true, + changedTouches: true, + ctrlKey: true, + detail: true, + eventPhase: true, + metaKey: true, + pageX: true, + pageY: true, + shiftKey: true, + view: true, + "char": true, + code: true, + charCode: true, + key: true, + keyCode: true, + button: true, + buttons: true, + clientX: true, + clientY: true, + offsetX: true, + offsetY: true, + pointerId: true, + pointerType: true, + screenX: true, + screenY: true, + targetTouches: true, + toElement: true, + touches: true, + + which: function( event ) { + var button = event.button; + + // Add which for key events + if ( event.which == null && rkeyEvent.test( event.type ) ) { + return event.charCode != null ? event.charCode : event.keyCode; + } + + // Add which for click: 1 === left; 2 === middle; 3 === right + if ( !event.which && button !== undefined && rmouseEvent.test( event.type ) ) { + if ( button & 1 ) { + return 1; + } + + if ( button & 2 ) { + return 3; + } + + if ( button & 4 ) { + return 2; + } + + return 0; + } + + return event.which; + } +}, jQuery.event.addProp ); + +jQuery.each( { focus: "focusin", blur: "focusout" }, function( type, delegateType ) { + jQuery.event.special[ type ] = { + + // Utilize native event if possible so blur/focus sequence is correct + setup: function() { + + // Claim the first handler + // dataPriv.set( this, "focus", ... ) + // dataPriv.set( this, "blur", ... ) + leverageNative( this, type, expectSync ); + + // Return false to allow normal processing in the caller + return false; + }, + trigger: function() { + + // Force setup before trigger + leverageNative( this, type ); + + // Return non-false to allow normal event-path propagation + return true; + }, + + delegateType: delegateType + }; +} ); + +// Create mouseenter/leave events using mouseover/out and event-time checks +// so that event delegation works in jQuery. +// Do the same for pointerenter/pointerleave and pointerover/pointerout +// +// Support: Safari 7 only +// Safari sends mouseenter too often; see: +// https://bugs.chromium.org/p/chromium/issues/detail?id=470258 +// for the description of the bug (it existed in older Chrome versions as well). +jQuery.each( { + mouseenter: "mouseover", + mouseleave: "mouseout", + pointerenter: "pointerover", + pointerleave: "pointerout" +}, function( orig, fix ) { + jQuery.event.special[ orig ] = { + delegateType: fix, + bindType: fix, + + handle: function( event ) { + var ret, + target = this, + related = event.relatedTarget, + handleObj = event.handleObj; + + // For mouseenter/leave call the handler if related is outside the target. + // NB: No relatedTarget if the mouse left/entered the browser window + if ( !related || ( related !== target && !jQuery.contains( target, related ) ) ) { + event.type = handleObj.origType; + ret = handleObj.handler.apply( this, arguments ); + event.type = fix; + } + return ret; + } + }; +} ); + +jQuery.fn.extend( { + + on: function( types, selector, data, fn ) { + return on( this, types, selector, data, fn ); + }, + one: function( types, selector, data, fn ) { + return on( this, types, selector, data, fn, 1 ); + }, + off: function( types, selector, fn ) { + var handleObj, type; + if ( types && types.preventDefault && types.handleObj ) { + + // ( event ) dispatched jQuery.Event + handleObj = types.handleObj; + jQuery( types.delegateTarget ).off( + handleObj.namespace ? + handleObj.origType + "." + handleObj.namespace : + handleObj.origType, + handleObj.selector, + handleObj.handler + ); + return this; + } + if ( typeof types === "object" ) { + + // ( types-object [, selector] ) + for ( type in types ) { + this.off( type, selector, types[ type ] ); + } + return this; + } + if ( selector === false || typeof selector === "function" ) { + + // ( types [, fn] ) + fn = selector; + selector = undefined; + } + if ( fn === false ) { + fn = returnFalse; + } + return this.each( function() { + jQuery.event.remove( this, types, fn, selector ); + } ); + } +} ); + + +var + + // Support: IE <=10 - 11, Edge 12 - 13 only + // In IE/Edge using regex groups here causes severe slowdowns. + // See https://connect.microsoft.com/IE/feedback/details/1736512/ + rnoInnerhtml = /\s*$/g; + +// Prefer a tbody over its parent table for containing new rows +function manipulationTarget( elem, content ) { + if ( nodeName( elem, "table" ) && + nodeName( content.nodeType !== 11 ? content : content.firstChild, "tr" ) ) { + + return jQuery( elem ).children( "tbody" )[ 0 ] || elem; + } + + return elem; +} + +// Replace/restore the type attribute of script elements for safe DOM manipulation +function disableScript( elem ) { + elem.type = ( elem.getAttribute( "type" ) !== null ) + "/" + elem.type; + return elem; +} +function restoreScript( elem ) { + if ( ( elem.type || "" ).slice( 0, 5 ) === "true/" ) { + elem.type = elem.type.slice( 5 ); + } else { + elem.removeAttribute( "type" ); + } + + return elem; +} + +function cloneCopyEvent( src, dest ) { + var i, l, type, pdataOld, udataOld, udataCur, events; + + if ( dest.nodeType !== 1 ) { + return; + } + + // 1. Copy private data: events, handlers, etc. + if ( dataPriv.hasData( src ) ) { + pdataOld = dataPriv.get( src ); + events = pdataOld.events; + + if ( events ) { + dataPriv.remove( dest, "handle events" ); + + for ( type in events ) { + for ( i = 0, l = events[ type ].length; i < l; i++ ) { + jQuery.event.add( dest, type, events[ type ][ i ] ); + } + } + } + } + + // 2. Copy user data + if ( dataUser.hasData( src ) ) { + udataOld = dataUser.access( src ); + udataCur = jQuery.extend( {}, udataOld ); + + dataUser.set( dest, udataCur ); + } +} + +// Fix IE bugs, see support tests +function fixInput( src, dest ) { + var nodeName = dest.nodeName.toLowerCase(); + + // Fails to persist the checked state of a cloned checkbox or radio button. + if ( nodeName === "input" && rcheckableType.test( src.type ) ) { + dest.checked = src.checked; + + // Fails to return the selected option to the default selected state when cloning options + } else if ( nodeName === "input" || nodeName === "textarea" ) { + dest.defaultValue = src.defaultValue; + } +} + +function domManip( collection, args, callback, ignored ) { + + // Flatten any nested arrays + args = flat( args ); + + var fragment, first, scripts, hasScripts, node, doc, + i = 0, + l = collection.length, + iNoClone = l - 1, + value = args[ 0 ], + valueIsFunction = isFunction( value ); + + // We can't cloneNode fragments that contain checked, in WebKit + if ( valueIsFunction || + ( l > 1 && typeof value === "string" && + !support.checkClone && rchecked.test( value ) ) ) { + return collection.each( function( index ) { + var self = collection.eq( index ); + if ( valueIsFunction ) { + args[ 0 ] = value.call( this, index, self.html() ); + } + domManip( self, args, callback, ignored ); + } ); + } + + if ( l ) { + fragment = buildFragment( args, collection[ 0 ].ownerDocument, false, collection, ignored ); + first = fragment.firstChild; + + if ( fragment.childNodes.length === 1 ) { + fragment = first; + } + + // Require either new content or an interest in ignored elements to invoke the callback + if ( first || ignored ) { + scripts = jQuery.map( getAll( fragment, "script" ), disableScript ); + hasScripts = scripts.length; + + // Use the original fragment for the last item + // instead of the first because it can end up + // being emptied incorrectly in certain situations (#8070). + for ( ; i < l; i++ ) { + node = fragment; + + if ( i !== iNoClone ) { + node = jQuery.clone( node, true, true ); + + // Keep references to cloned scripts for later restoration + if ( hasScripts ) { + + // Support: Android <=4.0 only, PhantomJS 1 only + // push.apply(_, arraylike) throws on ancient WebKit + jQuery.merge( scripts, getAll( node, "script" ) ); + } + } + + callback.call( collection[ i ], node, i ); + } + + if ( hasScripts ) { + doc = scripts[ scripts.length - 1 ].ownerDocument; + + // Reenable scripts + jQuery.map( scripts, restoreScript ); + + // Evaluate executable scripts on first document insertion + for ( i = 0; i < hasScripts; i++ ) { + node = scripts[ i ]; + if ( rscriptType.test( node.type || "" ) && + !dataPriv.access( node, "globalEval" ) && + jQuery.contains( doc, node ) ) { + + if ( node.src && ( node.type || "" ).toLowerCase() !== "module" ) { + + // Optional AJAX dependency, but won't run scripts if not present + if ( jQuery._evalUrl && !node.noModule ) { + jQuery._evalUrl( node.src, { + nonce: node.nonce || node.getAttribute( "nonce" ) + }, doc ); + } + } else { + DOMEval( node.textContent.replace( rcleanScript, "" ), node, doc ); + } + } + } + } + } + } + + return collection; +} + +function remove( elem, selector, keepData ) { + var node, + nodes = selector ? jQuery.filter( selector, elem ) : elem, + i = 0; + + for ( ; ( node = nodes[ i ] ) != null; i++ ) { + if ( !keepData && node.nodeType === 1 ) { + jQuery.cleanData( getAll( node ) ); + } + + if ( node.parentNode ) { + if ( keepData && isAttached( node ) ) { + setGlobalEval( getAll( node, "script" ) ); + } + node.parentNode.removeChild( node ); + } + } + + return elem; +} + +jQuery.extend( { + htmlPrefilter: function( html ) { + return html; + }, + + clone: function( elem, dataAndEvents, deepDataAndEvents ) { + var i, l, srcElements, destElements, + clone = elem.cloneNode( true ), + inPage = isAttached( elem ); + + // Fix IE cloning issues + if ( !support.noCloneChecked && ( elem.nodeType === 1 || elem.nodeType === 11 ) && + !jQuery.isXMLDoc( elem ) ) { + + // We eschew Sizzle here for performance reasons: https://jsperf.com/getall-vs-sizzle/2 + destElements = getAll( clone ); + srcElements = getAll( elem ); + + for ( i = 0, l = srcElements.length; i < l; i++ ) { + fixInput( srcElements[ i ], destElements[ i ] ); + } + } + + // Copy the events from the original to the clone + if ( dataAndEvents ) { + if ( deepDataAndEvents ) { + srcElements = srcElements || getAll( elem ); + destElements = destElements || getAll( clone ); + + for ( i = 0, l = srcElements.length; i < l; i++ ) { + cloneCopyEvent( srcElements[ i ], destElements[ i ] ); + } + } else { + cloneCopyEvent( elem, clone ); + } + } + + // Preserve script evaluation history + destElements = getAll( clone, "script" ); + if ( destElements.length > 0 ) { + setGlobalEval( destElements, !inPage && getAll( elem, "script" ) ); + } + + // Return the cloned set + return clone; + }, + + cleanData: function( elems ) { + var data, elem, type, + special = jQuery.event.special, + i = 0; + + for ( ; ( elem = elems[ i ] ) !== undefined; i++ ) { + if ( acceptData( elem ) ) { + if ( ( data = elem[ dataPriv.expando ] ) ) { + if ( data.events ) { + for ( type in data.events ) { + if ( special[ type ] ) { + jQuery.event.remove( elem, type ); + + // This is a shortcut to avoid jQuery.event.remove's overhead + } else { + jQuery.removeEvent( elem, type, data.handle ); + } + } + } + + // Support: Chrome <=35 - 45+ + // Assign undefined instead of using delete, see Data#remove + elem[ dataPriv.expando ] = undefined; + } + if ( elem[ dataUser.expando ] ) { + + // Support: Chrome <=35 - 45+ + // Assign undefined instead of using delete, see Data#remove + elem[ dataUser.expando ] = undefined; + } + } + } + } +} ); + +jQuery.fn.extend( { + detach: function( selector ) { + return remove( this, selector, true ); + }, + + remove: function( selector ) { + return remove( this, selector ); + }, + + text: function( value ) { + return access( this, function( value ) { + return value === undefined ? + jQuery.text( this ) : + this.empty().each( function() { + if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { + this.textContent = value; + } + } ); + }, null, value, arguments.length ); + }, + + append: function() { + return domManip( this, arguments, function( elem ) { + if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { + var target = manipulationTarget( this, elem ); + target.appendChild( elem ); + } + } ); + }, + + prepend: function() { + return domManip( this, arguments, function( elem ) { + if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { + var target = manipulationTarget( this, elem ); + target.insertBefore( elem, target.firstChild ); + } + } ); + }, + + before: function() { + return domManip( this, arguments, function( elem ) { + if ( this.parentNode ) { + this.parentNode.insertBefore( elem, this ); + } + } ); + }, + + after: function() { + return domManip( this, arguments, function( elem ) { + if ( this.parentNode ) { + this.parentNode.insertBefore( elem, this.nextSibling ); + } + } ); + }, + + empty: function() { + var elem, + i = 0; + + for ( ; ( elem = this[ i ] ) != null; i++ ) { + if ( elem.nodeType === 1 ) { + + // Prevent memory leaks + jQuery.cleanData( getAll( elem, false ) ); + + // Remove any remaining nodes + elem.textContent = ""; + } + } + + return this; + }, + + clone: function( dataAndEvents, deepDataAndEvents ) { + dataAndEvents = dataAndEvents == null ? false : dataAndEvents; + deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents; + + return this.map( function() { + return jQuery.clone( this, dataAndEvents, deepDataAndEvents ); + } ); + }, + + html: function( value ) { + return access( this, function( value ) { + var elem = this[ 0 ] || {}, + i = 0, + l = this.length; + + if ( value === undefined && elem.nodeType === 1 ) { + return elem.innerHTML; + } + + // See if we can take a shortcut and just use innerHTML + if ( typeof value === "string" && !rnoInnerhtml.test( value ) && + !wrapMap[ ( rtagName.exec( value ) || [ "", "" ] )[ 1 ].toLowerCase() ] ) { + + value = jQuery.htmlPrefilter( value ); + + try { + for ( ; i < l; i++ ) { + elem = this[ i ] || {}; + + // Remove element nodes and prevent memory leaks + if ( elem.nodeType === 1 ) { + jQuery.cleanData( getAll( elem, false ) ); + elem.innerHTML = value; + } + } + + elem = 0; + + // If using innerHTML throws an exception, use the fallback method + } catch ( e ) {} + } + + if ( elem ) { + this.empty().append( value ); + } + }, null, value, arguments.length ); + }, + + replaceWith: function() { + var ignored = []; + + // Make the changes, replacing each non-ignored context element with the new content + return domManip( this, arguments, function( elem ) { + var parent = this.parentNode; + + if ( jQuery.inArray( this, ignored ) < 0 ) { + jQuery.cleanData( getAll( this ) ); + if ( parent ) { + parent.replaceChild( elem, this ); + } + } + + // Force callback invocation + }, ignored ); + } +} ); + +jQuery.each( { + appendTo: "append", + prependTo: "prepend", + insertBefore: "before", + insertAfter: "after", + replaceAll: "replaceWith" +}, function( name, original ) { + jQuery.fn[ name ] = function( selector ) { + var elems, + ret = [], + insert = jQuery( selector ), + last = insert.length - 1, + i = 0; + + for ( ; i <= last; i++ ) { + elems = i === last ? this : this.clone( true ); + jQuery( insert[ i ] )[ original ]( elems ); + + // Support: Android <=4.0 only, PhantomJS 1 only + // .get() because push.apply(_, arraylike) throws on ancient WebKit + push.apply( ret, elems.get() ); + } + + return this.pushStack( ret ); + }; +} ); +var rnumnonpx = new RegExp( "^(" + pnum + ")(?!px)[a-z%]+$", "i" ); + +var getStyles = function( elem ) { + + // Support: IE <=11 only, Firefox <=30 (#15098, #14150) + // IE throws on elements created in popups + // FF meanwhile throws on frame elements through "defaultView.getComputedStyle" + var view = elem.ownerDocument.defaultView; + + if ( !view || !view.opener ) { + view = window; + } + + return view.getComputedStyle( elem ); + }; + +var swap = function( elem, options, callback ) { + var ret, name, + old = {}; + + // Remember the old values, and insert the new ones + for ( name in options ) { + old[ name ] = elem.style[ name ]; + elem.style[ name ] = options[ name ]; + } + + ret = callback.call( elem ); + + // Revert the old values + for ( name in options ) { + elem.style[ name ] = old[ name ]; + } + + return ret; +}; + + +var rboxStyle = new RegExp( cssExpand.join( "|" ), "i" ); + + + +( function() { + + // Executing both pixelPosition & boxSizingReliable tests require only one layout + // so they're executed at the same time to save the second computation. + function computeStyleTests() { + + // This is a singleton, we need to execute it only once + if ( !div ) { + return; + } + + container.style.cssText = "position:absolute;left:-11111px;width:60px;" + + "margin-top:1px;padding:0;border:0"; + div.style.cssText = + "position:relative;display:block;box-sizing:border-box;overflow:scroll;" + + "margin:auto;border:1px;padding:1px;" + + "width:60%;top:1%"; + documentElement.appendChild( container ).appendChild( div ); + + var divStyle = window.getComputedStyle( div ); + pixelPositionVal = divStyle.top !== "1%"; + + // Support: Android 4.0 - 4.3 only, Firefox <=3 - 44 + reliableMarginLeftVal = roundPixelMeasures( divStyle.marginLeft ) === 12; + + // Support: Android 4.0 - 4.3 only, Safari <=9.1 - 10.1, iOS <=7.0 - 9.3 + // Some styles come back with percentage values, even though they shouldn't + div.style.right = "60%"; + pixelBoxStylesVal = roundPixelMeasures( divStyle.right ) === 36; + + // Support: IE 9 - 11 only + // Detect misreporting of content dimensions for box-sizing:border-box elements + boxSizingReliableVal = roundPixelMeasures( divStyle.width ) === 36; + + // Support: IE 9 only + // Detect overflow:scroll screwiness (gh-3699) + // Support: Chrome <=64 + // Don't get tricked when zoom affects offsetWidth (gh-4029) + div.style.position = "absolute"; + scrollboxSizeVal = roundPixelMeasures( div.offsetWidth / 3 ) === 12; + + documentElement.removeChild( container ); + + // Nullify the div so it wouldn't be stored in the memory and + // it will also be a sign that checks already performed + div = null; + } + + function roundPixelMeasures( measure ) { + return Math.round( parseFloat( measure ) ); + } + + var pixelPositionVal, boxSizingReliableVal, scrollboxSizeVal, pixelBoxStylesVal, + reliableTrDimensionsVal, reliableMarginLeftVal, + container = document.createElement( "div" ), + div = document.createElement( "div" ); + + // Finish early in limited (non-browser) environments + if ( !div.style ) { + return; + } + + // Support: IE <=9 - 11 only + // Style of cloned element affects source element cloned (#8908) + div.style.backgroundClip = "content-box"; + div.cloneNode( true ).style.backgroundClip = ""; + support.clearCloneStyle = div.style.backgroundClip === "content-box"; + + jQuery.extend( support, { + boxSizingReliable: function() { + computeStyleTests(); + return boxSizingReliableVal; + }, + pixelBoxStyles: function() { + computeStyleTests(); + return pixelBoxStylesVal; + }, + pixelPosition: function() { + computeStyleTests(); + return pixelPositionVal; + }, + reliableMarginLeft: function() { + computeStyleTests(); + return reliableMarginLeftVal; + }, + scrollboxSize: function() { + computeStyleTests(); + return scrollboxSizeVal; + }, + + // Support: IE 9 - 11+, Edge 15 - 18+ + // IE/Edge misreport `getComputedStyle` of table rows with width/height + // set in CSS while `offset*` properties report correct values. + // Behavior in IE 9 is more subtle than in newer versions & it passes + // some versions of this test; make sure not to make it pass there! + reliableTrDimensions: function() { + var table, tr, trChild, trStyle; + if ( reliableTrDimensionsVal == null ) { + table = document.createElement( "table" ); + tr = document.createElement( "tr" ); + trChild = document.createElement( "div" ); + + table.style.cssText = "position:absolute;left:-11111px"; + tr.style.height = "1px"; + trChild.style.height = "9px"; + + documentElement + .appendChild( table ) + .appendChild( tr ) + .appendChild( trChild ); + + trStyle = window.getComputedStyle( tr ); + reliableTrDimensionsVal = parseInt( trStyle.height ) > 3; + + documentElement.removeChild( table ); + } + return reliableTrDimensionsVal; + } + } ); +} )(); + + +function curCSS( elem, name, computed ) { + var width, minWidth, maxWidth, ret, + + // Support: Firefox 51+ + // Retrieving style before computed somehow + // fixes an issue with getting wrong values + // on detached elements + style = elem.style; + + computed = computed || getStyles( elem ); + + // getPropertyValue is needed for: + // .css('filter') (IE 9 only, #12537) + // .css('--customProperty) (#3144) + if ( computed ) { + ret = computed.getPropertyValue( name ) || computed[ name ]; + + if ( ret === "" && !isAttached( elem ) ) { + ret = jQuery.style( elem, name ); + } + + // A tribute to the "awesome hack by Dean Edwards" + // Android Browser returns percentage for some values, + // but width seems to be reliably pixels. + // This is against the CSSOM draft spec: + // https://drafts.csswg.org/cssom/#resolved-values + if ( !support.pixelBoxStyles() && rnumnonpx.test( ret ) && rboxStyle.test( name ) ) { + + // Remember the original values + width = style.width; + minWidth = style.minWidth; + maxWidth = style.maxWidth; + + // Put in the new values to get a computed value out + style.minWidth = style.maxWidth = style.width = ret; + ret = computed.width; + + // Revert the changed values + style.width = width; + style.minWidth = minWidth; + style.maxWidth = maxWidth; + } + } + + return ret !== undefined ? + + // Support: IE <=9 - 11 only + // IE returns zIndex value as an integer. + ret + "" : + ret; +} + + +function addGetHookIf( conditionFn, hookFn ) { + + // Define the hook, we'll check on the first run if it's really needed. + return { + get: function() { + if ( conditionFn() ) { + + // Hook not needed (or it's not possible to use it due + // to missing dependency), remove it. + delete this.get; + return; + } + + // Hook needed; redefine it so that the support test is not executed again. + return ( this.get = hookFn ).apply( this, arguments ); + } + }; +} + + +var cssPrefixes = [ "Webkit", "Moz", "ms" ], + emptyStyle = document.createElement( "div" ).style, + vendorProps = {}; + +// Return a vendor-prefixed property or undefined +function vendorPropName( name ) { + + // Check for vendor prefixed names + var capName = name[ 0 ].toUpperCase() + name.slice( 1 ), + i = cssPrefixes.length; + + while ( i-- ) { + name = cssPrefixes[ i ] + capName; + if ( name in emptyStyle ) { + return name; + } + } +} + +// Return a potentially-mapped jQuery.cssProps or vendor prefixed property +function finalPropName( name ) { + var final = jQuery.cssProps[ name ] || vendorProps[ name ]; + + if ( final ) { + return final; + } + if ( name in emptyStyle ) { + return name; + } + return vendorProps[ name ] = vendorPropName( name ) || name; +} + + +var + + // Swappable if display is none or starts with table + // except "table", "table-cell", or "table-caption" + // See here for display values: https://developer.mozilla.org/en-US/docs/CSS/display + rdisplayswap = /^(none|table(?!-c[ea]).+)/, + rcustomProp = /^--/, + cssShow = { position: "absolute", visibility: "hidden", display: "block" }, + cssNormalTransform = { + letterSpacing: "0", + fontWeight: "400" + }; + +function setPositiveNumber( _elem, value, subtract ) { + + // Any relative (+/-) values have already been + // normalized at this point + var matches = rcssNum.exec( value ); + return matches ? + + // Guard against undefined "subtract", e.g., when used as in cssHooks + Math.max( 0, matches[ 2 ] - ( subtract || 0 ) ) + ( matches[ 3 ] || "px" ) : + value; +} + +function boxModelAdjustment( elem, dimension, box, isBorderBox, styles, computedVal ) { + var i = dimension === "width" ? 1 : 0, + extra = 0, + delta = 0; + + // Adjustment may not be necessary + if ( box === ( isBorderBox ? "border" : "content" ) ) { + return 0; + } + + for ( ; i < 4; i += 2 ) { + + // Both box models exclude margin + if ( box === "margin" ) { + delta += jQuery.css( elem, box + cssExpand[ i ], true, styles ); + } + + // If we get here with a content-box, we're seeking "padding" or "border" or "margin" + if ( !isBorderBox ) { + + // Add padding + delta += jQuery.css( elem, "padding" + cssExpand[ i ], true, styles ); + + // For "border" or "margin", add border + if ( box !== "padding" ) { + delta += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); + + // But still keep track of it otherwise + } else { + extra += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); + } + + // If we get here with a border-box (content + padding + border), we're seeking "content" or + // "padding" or "margin" + } else { + + // For "content", subtract padding + if ( box === "content" ) { + delta -= jQuery.css( elem, "padding" + cssExpand[ i ], true, styles ); + } + + // For "content" or "padding", subtract border + if ( box !== "margin" ) { + delta -= jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); + } + } + } + + // Account for positive content-box scroll gutter when requested by providing computedVal + if ( !isBorderBox && computedVal >= 0 ) { + + // offsetWidth/offsetHeight is a rounded sum of content, padding, scroll gutter, and border + // Assuming integer scroll gutter, subtract the rest and round down + delta += Math.max( 0, Math.ceil( + elem[ "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ) ] - + computedVal - + delta - + extra - + 0.5 + + // If offsetWidth/offsetHeight is unknown, then we can't determine content-box scroll gutter + // Use an explicit zero to avoid NaN (gh-3964) + ) ) || 0; + } + + return delta; +} + +function getWidthOrHeight( elem, dimension, extra ) { + + // Start with computed style + var styles = getStyles( elem ), + + // To avoid forcing a reflow, only fetch boxSizing if we need it (gh-4322). + // Fake content-box until we know it's needed to know the true value. + boxSizingNeeded = !support.boxSizingReliable() || extra, + isBorderBox = boxSizingNeeded && + jQuery.css( elem, "boxSizing", false, styles ) === "border-box", + valueIsBorderBox = isBorderBox, + + val = curCSS( elem, dimension, styles ), + offsetProp = "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ); + + // Support: Firefox <=54 + // Return a confounding non-pixel value or feign ignorance, as appropriate. + if ( rnumnonpx.test( val ) ) { + if ( !extra ) { + return val; + } + val = "auto"; + } + + + // Support: IE 9 - 11 only + // Use offsetWidth/offsetHeight for when box sizing is unreliable. + // In those cases, the computed value can be trusted to be border-box. + if ( ( !support.boxSizingReliable() && isBorderBox || + + // Support: IE 10 - 11+, Edge 15 - 18+ + // IE/Edge misreport `getComputedStyle` of table rows with width/height + // set in CSS while `offset*` properties report correct values. + // Interestingly, in some cases IE 9 doesn't suffer from this issue. + !support.reliableTrDimensions() && nodeName( elem, "tr" ) || + + // Fall back to offsetWidth/offsetHeight when value is "auto" + // This happens for inline elements with no explicit setting (gh-3571) + val === "auto" || + + // Support: Android <=4.1 - 4.3 only + // Also use offsetWidth/offsetHeight for misreported inline dimensions (gh-3602) + !parseFloat( val ) && jQuery.css( elem, "display", false, styles ) === "inline" ) && + + // Make sure the element is visible & connected + elem.getClientRects().length ) { + + isBorderBox = jQuery.css( elem, "boxSizing", false, styles ) === "border-box"; + + // Where available, offsetWidth/offsetHeight approximate border box dimensions. + // Where not available (e.g., SVG), assume unreliable box-sizing and interpret the + // retrieved value as a content box dimension. + valueIsBorderBox = offsetProp in elem; + if ( valueIsBorderBox ) { + val = elem[ offsetProp ]; + } + } + + // Normalize "" and auto + val = parseFloat( val ) || 0; + + // Adjust for the element's box model + return ( val + + boxModelAdjustment( + elem, + dimension, + extra || ( isBorderBox ? "border" : "content" ), + valueIsBorderBox, + styles, + + // Provide the current computed size to request scroll gutter calculation (gh-3589) + val + ) + ) + "px"; +} + +jQuery.extend( { + + // Add in style property hooks for overriding the default + // behavior of getting and setting a style property + cssHooks: { + opacity: { + get: function( elem, computed ) { + if ( computed ) { + + // We should always get a number back from opacity + var ret = curCSS( elem, "opacity" ); + return ret === "" ? "1" : ret; + } + } + } + }, + + // Don't automatically add "px" to these possibly-unitless properties + cssNumber: { + "animationIterationCount": true, + "columnCount": true, + "fillOpacity": true, + "flexGrow": true, + "flexShrink": true, + "fontWeight": true, + "gridArea": true, + "gridColumn": true, + "gridColumnEnd": true, + "gridColumnStart": true, + "gridRow": true, + "gridRowEnd": true, + "gridRowStart": true, + "lineHeight": true, + "opacity": true, + "order": true, + "orphans": true, + "widows": true, + "zIndex": true, + "zoom": true + }, + + // Add in properties whose names you wish to fix before + // setting or getting the value + cssProps: {}, + + // Get and set the style property on a DOM Node + style: function( elem, name, value, extra ) { + + // Don't set styles on text and comment nodes + if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) { + return; + } + + // Make sure that we're working with the right name + var ret, type, hooks, + origName = camelCase( name ), + isCustomProp = rcustomProp.test( name ), + style = elem.style; + + // Make sure that we're working with the right name. We don't + // want to query the value if it is a CSS custom property + // since they are user-defined. + if ( !isCustomProp ) { + name = finalPropName( origName ); + } + + // Gets hook for the prefixed version, then unprefixed version + hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ]; + + // Check if we're setting a value + if ( value !== undefined ) { + type = typeof value; + + // Convert "+=" or "-=" to relative numbers (#7345) + if ( type === "string" && ( ret = rcssNum.exec( value ) ) && ret[ 1 ] ) { + value = adjustCSS( elem, name, ret ); + + // Fixes bug #9237 + type = "number"; + } + + // Make sure that null and NaN values aren't set (#7116) + if ( value == null || value !== value ) { + return; + } + + // If a number was passed in, add the unit (except for certain CSS properties) + // The isCustomProp check can be removed in jQuery 4.0 when we only auto-append + // "px" to a few hardcoded values. + if ( type === "number" && !isCustomProp ) { + value += ret && ret[ 3 ] || ( jQuery.cssNumber[ origName ] ? "" : "px" ); + } + + // background-* props affect original clone's values + if ( !support.clearCloneStyle && value === "" && name.indexOf( "background" ) === 0 ) { + style[ name ] = "inherit"; + } + + // If a hook was provided, use that value, otherwise just set the specified value + if ( !hooks || !( "set" in hooks ) || + ( value = hooks.set( elem, value, extra ) ) !== undefined ) { + + if ( isCustomProp ) { + style.setProperty( name, value ); + } else { + style[ name ] = value; + } + } + + } else { + + // If a hook was provided get the non-computed value from there + if ( hooks && "get" in hooks && + ( ret = hooks.get( elem, false, extra ) ) !== undefined ) { + + return ret; + } + + // Otherwise just get the value from the style object + return style[ name ]; + } + }, + + css: function( elem, name, extra, styles ) { + var val, num, hooks, + origName = camelCase( name ), + isCustomProp = rcustomProp.test( name ); + + // Make sure that we're working with the right name. We don't + // want to modify the value if it is a CSS custom property + // since they are user-defined. + if ( !isCustomProp ) { + name = finalPropName( origName ); + } + + // Try prefixed name followed by the unprefixed name + hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ]; + + // If a hook was provided get the computed value from there + if ( hooks && "get" in hooks ) { + val = hooks.get( elem, true, extra ); + } + + // Otherwise, if a way to get the computed value exists, use that + if ( val === undefined ) { + val = curCSS( elem, name, styles ); + } + + // Convert "normal" to computed value + if ( val === "normal" && name in cssNormalTransform ) { + val = cssNormalTransform[ name ]; + } + + // Make numeric if forced or a qualifier was provided and val looks numeric + if ( extra === "" || extra ) { + num = parseFloat( val ); + return extra === true || isFinite( num ) ? num || 0 : val; + } + + return val; + } +} ); + +jQuery.each( [ "height", "width" ], function( _i, dimension ) { + jQuery.cssHooks[ dimension ] = { + get: function( elem, computed, extra ) { + if ( computed ) { + + // Certain elements can have dimension info if we invisibly show them + // but it must have a current display style that would benefit + return rdisplayswap.test( jQuery.css( elem, "display" ) ) && + + // Support: Safari 8+ + // Table columns in Safari have non-zero offsetWidth & zero + // getBoundingClientRect().width unless display is changed. + // Support: IE <=11 only + // Running getBoundingClientRect on a disconnected node + // in IE throws an error. + ( !elem.getClientRects().length || !elem.getBoundingClientRect().width ) ? + swap( elem, cssShow, function() { + return getWidthOrHeight( elem, dimension, extra ); + } ) : + getWidthOrHeight( elem, dimension, extra ); + } + }, + + set: function( elem, value, extra ) { + var matches, + styles = getStyles( elem ), + + // Only read styles.position if the test has a chance to fail + // to avoid forcing a reflow. + scrollboxSizeBuggy = !support.scrollboxSize() && + styles.position === "absolute", + + // To avoid forcing a reflow, only fetch boxSizing if we need it (gh-3991) + boxSizingNeeded = scrollboxSizeBuggy || extra, + isBorderBox = boxSizingNeeded && + jQuery.css( elem, "boxSizing", false, styles ) === "border-box", + subtract = extra ? + boxModelAdjustment( + elem, + dimension, + extra, + isBorderBox, + styles + ) : + 0; + + // Account for unreliable border-box dimensions by comparing offset* to computed and + // faking a content-box to get border and padding (gh-3699) + if ( isBorderBox && scrollboxSizeBuggy ) { + subtract -= Math.ceil( + elem[ "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ) ] - + parseFloat( styles[ dimension ] ) - + boxModelAdjustment( elem, dimension, "border", false, styles ) - + 0.5 + ); + } + + // Convert to pixels if value adjustment is needed + if ( subtract && ( matches = rcssNum.exec( value ) ) && + ( matches[ 3 ] || "px" ) !== "px" ) { + + elem.style[ dimension ] = value; + value = jQuery.css( elem, dimension ); + } + + return setPositiveNumber( elem, value, subtract ); + } + }; +} ); + +jQuery.cssHooks.marginLeft = addGetHookIf( support.reliableMarginLeft, + function( elem, computed ) { + if ( computed ) { + return ( parseFloat( curCSS( elem, "marginLeft" ) ) || + elem.getBoundingClientRect().left - + swap( elem, { marginLeft: 0 }, function() { + return elem.getBoundingClientRect().left; + } ) + ) + "px"; + } + } +); + +// These hooks are used by animate to expand properties +jQuery.each( { + margin: "", + padding: "", + border: "Width" +}, function( prefix, suffix ) { + jQuery.cssHooks[ prefix + suffix ] = { + expand: function( value ) { + var i = 0, + expanded = {}, + + // Assumes a single number if not a string + parts = typeof value === "string" ? value.split( " " ) : [ value ]; + + for ( ; i < 4; i++ ) { + expanded[ prefix + cssExpand[ i ] + suffix ] = + parts[ i ] || parts[ i - 2 ] || parts[ 0 ]; + } + + return expanded; + } + }; + + if ( prefix !== "margin" ) { + jQuery.cssHooks[ prefix + suffix ].set = setPositiveNumber; + } +} ); + +jQuery.fn.extend( { + css: function( name, value ) { + return access( this, function( elem, name, value ) { + var styles, len, + map = {}, + i = 0; + + if ( Array.isArray( name ) ) { + styles = getStyles( elem ); + len = name.length; + + for ( ; i < len; i++ ) { + map[ name[ i ] ] = jQuery.css( elem, name[ i ], false, styles ); + } + + return map; + } + + return value !== undefined ? + jQuery.style( elem, name, value ) : + jQuery.css( elem, name ); + }, name, value, arguments.length > 1 ); + } +} ); + + +function Tween( elem, options, prop, end, easing ) { + return new Tween.prototype.init( elem, options, prop, end, easing ); +} +jQuery.Tween = Tween; + +Tween.prototype = { + constructor: Tween, + init: function( elem, options, prop, end, easing, unit ) { + this.elem = elem; + this.prop = prop; + this.easing = easing || jQuery.easing._default; + this.options = options; + this.start = this.now = this.cur(); + this.end = end; + this.unit = unit || ( jQuery.cssNumber[ prop ] ? "" : "px" ); + }, + cur: function() { + var hooks = Tween.propHooks[ this.prop ]; + + return hooks && hooks.get ? + hooks.get( this ) : + Tween.propHooks._default.get( this ); + }, + run: function( percent ) { + var eased, + hooks = Tween.propHooks[ this.prop ]; + + if ( this.options.duration ) { + this.pos = eased = jQuery.easing[ this.easing ]( + percent, this.options.duration * percent, 0, 1, this.options.duration + ); + } else { + this.pos = eased = percent; + } + this.now = ( this.end - this.start ) * eased + this.start; + + if ( this.options.step ) { + this.options.step.call( this.elem, this.now, this ); + } + + if ( hooks && hooks.set ) { + hooks.set( this ); + } else { + Tween.propHooks._default.set( this ); + } + return this; + } +}; + +Tween.prototype.init.prototype = Tween.prototype; + +Tween.propHooks = { + _default: { + get: function( tween ) { + var result; + + // Use a property on the element directly when it is not a DOM element, + // or when there is no matching style property that exists. + if ( tween.elem.nodeType !== 1 || + tween.elem[ tween.prop ] != null && tween.elem.style[ tween.prop ] == null ) { + return tween.elem[ tween.prop ]; + } + + // Passing an empty string as a 3rd parameter to .css will automatically + // attempt a parseFloat and fallback to a string if the parse fails. + // Simple values such as "10px" are parsed to Float; + // complex values such as "rotate(1rad)" are returned as-is. + result = jQuery.css( tween.elem, tween.prop, "" ); + + // Empty strings, null, undefined and "auto" are converted to 0. + return !result || result === "auto" ? 0 : result; + }, + set: function( tween ) { + + // Use step hook for back compat. + // Use cssHook if its there. + // Use .style if available and use plain properties where available. + if ( jQuery.fx.step[ tween.prop ] ) { + jQuery.fx.step[ tween.prop ]( tween ); + } else if ( tween.elem.nodeType === 1 && ( + jQuery.cssHooks[ tween.prop ] || + tween.elem.style[ finalPropName( tween.prop ) ] != null ) ) { + jQuery.style( tween.elem, tween.prop, tween.now + tween.unit ); + } else { + tween.elem[ tween.prop ] = tween.now; + } + } + } +}; + +// Support: IE <=9 only +// Panic based approach to setting things on disconnected nodes +Tween.propHooks.scrollTop = Tween.propHooks.scrollLeft = { + set: function( tween ) { + if ( tween.elem.nodeType && tween.elem.parentNode ) { + tween.elem[ tween.prop ] = tween.now; + } + } +}; + +jQuery.easing = { + linear: function( p ) { + return p; + }, + swing: function( p ) { + return 0.5 - Math.cos( p * Math.PI ) / 2; + }, + _default: "swing" +}; + +jQuery.fx = Tween.prototype.init; + +// Back compat <1.8 extension point +jQuery.fx.step = {}; + + + + +var + fxNow, inProgress, + rfxtypes = /^(?:toggle|show|hide)$/, + rrun = /queueHooks$/; + +function schedule() { + if ( inProgress ) { + if ( document.hidden === false && window.requestAnimationFrame ) { + window.requestAnimationFrame( schedule ); + } else { + window.setTimeout( schedule, jQuery.fx.interval ); + } + + jQuery.fx.tick(); + } +} + +// Animations created synchronously will run synchronously +function createFxNow() { + window.setTimeout( function() { + fxNow = undefined; + } ); + return ( fxNow = Date.now() ); +} + +// Generate parameters to create a standard animation +function genFx( type, includeWidth ) { + var which, + i = 0, + attrs = { height: type }; + + // If we include width, step value is 1 to do all cssExpand values, + // otherwise step value is 2 to skip over Left and Right + includeWidth = includeWidth ? 1 : 0; + for ( ; i < 4; i += 2 - includeWidth ) { + which = cssExpand[ i ]; + attrs[ "margin" + which ] = attrs[ "padding" + which ] = type; + } + + if ( includeWidth ) { + attrs.opacity = attrs.width = type; + } + + return attrs; +} + +function createTween( value, prop, animation ) { + var tween, + collection = ( Animation.tweeners[ prop ] || [] ).concat( Animation.tweeners[ "*" ] ), + index = 0, + length = collection.length; + for ( ; index < length; index++ ) { + if ( ( tween = collection[ index ].call( animation, prop, value ) ) ) { + + // We're done with this property + return tween; + } + } +} + +function defaultPrefilter( elem, props, opts ) { + var prop, value, toggle, hooks, oldfire, propTween, restoreDisplay, display, + isBox = "width" in props || "height" in props, + anim = this, + orig = {}, + style = elem.style, + hidden = elem.nodeType && isHiddenWithinTree( elem ), + dataShow = dataPriv.get( elem, "fxshow" ); + + // Queue-skipping animations hijack the fx hooks + if ( !opts.queue ) { + hooks = jQuery._queueHooks( elem, "fx" ); + if ( hooks.unqueued == null ) { + hooks.unqueued = 0; + oldfire = hooks.empty.fire; + hooks.empty.fire = function() { + if ( !hooks.unqueued ) { + oldfire(); + } + }; + } + hooks.unqueued++; + + anim.always( function() { + + // Ensure the complete handler is called before this completes + anim.always( function() { + hooks.unqueued--; + if ( !jQuery.queue( elem, "fx" ).length ) { + hooks.empty.fire(); + } + } ); + } ); + } + + // Detect show/hide animations + for ( prop in props ) { + value = props[ prop ]; + if ( rfxtypes.test( value ) ) { + delete props[ prop ]; + toggle = toggle || value === "toggle"; + if ( value === ( hidden ? "hide" : "show" ) ) { + + // Pretend to be hidden if this is a "show" and + // there is still data from a stopped show/hide + if ( value === "show" && dataShow && dataShow[ prop ] !== undefined ) { + hidden = true; + + // Ignore all other no-op show/hide data + } else { + continue; + } + } + orig[ prop ] = dataShow && dataShow[ prop ] || jQuery.style( elem, prop ); + } + } + + // Bail out if this is a no-op like .hide().hide() + propTween = !jQuery.isEmptyObject( props ); + if ( !propTween && jQuery.isEmptyObject( orig ) ) { + return; + } + + // Restrict "overflow" and "display" styles during box animations + if ( isBox && elem.nodeType === 1 ) { + + // Support: IE <=9 - 11, Edge 12 - 15 + // Record all 3 overflow attributes because IE does not infer the shorthand + // from identically-valued overflowX and overflowY and Edge just mirrors + // the overflowX value there. + opts.overflow = [ style.overflow, style.overflowX, style.overflowY ]; + + // Identify a display type, preferring old show/hide data over the CSS cascade + restoreDisplay = dataShow && dataShow.display; + if ( restoreDisplay == null ) { + restoreDisplay = dataPriv.get( elem, "display" ); + } + display = jQuery.css( elem, "display" ); + if ( display === "none" ) { + if ( restoreDisplay ) { + display = restoreDisplay; + } else { + + // Get nonempty value(s) by temporarily forcing visibility + showHide( [ elem ], true ); + restoreDisplay = elem.style.display || restoreDisplay; + display = jQuery.css( elem, "display" ); + showHide( [ elem ] ); + } + } + + // Animate inline elements as inline-block + if ( display === "inline" || display === "inline-block" && restoreDisplay != null ) { + if ( jQuery.css( elem, "float" ) === "none" ) { + + // Restore the original display value at the end of pure show/hide animations + if ( !propTween ) { + anim.done( function() { + style.display = restoreDisplay; + } ); + if ( restoreDisplay == null ) { + display = style.display; + restoreDisplay = display === "none" ? "" : display; + } + } + style.display = "inline-block"; + } + } + } + + if ( opts.overflow ) { + style.overflow = "hidden"; + anim.always( function() { + style.overflow = opts.overflow[ 0 ]; + style.overflowX = opts.overflow[ 1 ]; + style.overflowY = opts.overflow[ 2 ]; + } ); + } + + // Implement show/hide animations + propTween = false; + for ( prop in orig ) { + + // General show/hide setup for this element animation + if ( !propTween ) { + if ( dataShow ) { + if ( "hidden" in dataShow ) { + hidden = dataShow.hidden; + } + } else { + dataShow = dataPriv.access( elem, "fxshow", { display: restoreDisplay } ); + } + + // Store hidden/visible for toggle so `.stop().toggle()` "reverses" + if ( toggle ) { + dataShow.hidden = !hidden; + } + + // Show elements before animating them + if ( hidden ) { + showHide( [ elem ], true ); + } + + /* eslint-disable no-loop-func */ + + anim.done( function() { + + /* eslint-enable no-loop-func */ + + // The final step of a "hide" animation is actually hiding the element + if ( !hidden ) { + showHide( [ elem ] ); + } + dataPriv.remove( elem, "fxshow" ); + for ( prop in orig ) { + jQuery.style( elem, prop, orig[ prop ] ); + } + } ); + } + + // Per-property setup + propTween = createTween( hidden ? dataShow[ prop ] : 0, prop, anim ); + if ( !( prop in dataShow ) ) { + dataShow[ prop ] = propTween.start; + if ( hidden ) { + propTween.end = propTween.start; + propTween.start = 0; + } + } + } +} + +function propFilter( props, specialEasing ) { + var index, name, easing, value, hooks; + + // camelCase, specialEasing and expand cssHook pass + for ( index in props ) { + name = camelCase( index ); + easing = specialEasing[ name ]; + value = props[ index ]; + if ( Array.isArray( value ) ) { + easing = value[ 1 ]; + value = props[ index ] = value[ 0 ]; + } + + if ( index !== name ) { + props[ name ] = value; + delete props[ index ]; + } + + hooks = jQuery.cssHooks[ name ]; + if ( hooks && "expand" in hooks ) { + value = hooks.expand( value ); + delete props[ name ]; + + // Not quite $.extend, this won't overwrite existing keys. + // Reusing 'index' because we have the correct "name" + for ( index in value ) { + if ( !( index in props ) ) { + props[ index ] = value[ index ]; + specialEasing[ index ] = easing; + } + } + } else { + specialEasing[ name ] = easing; + } + } +} + +function Animation( elem, properties, options ) { + var result, + stopped, + index = 0, + length = Animation.prefilters.length, + deferred = jQuery.Deferred().always( function() { + + // Don't match elem in the :animated selector + delete tick.elem; + } ), + tick = function() { + if ( stopped ) { + return false; + } + var currentTime = fxNow || createFxNow(), + remaining = Math.max( 0, animation.startTime + animation.duration - currentTime ), + + // Support: Android 2.3 only + // Archaic crash bug won't allow us to use `1 - ( 0.5 || 0 )` (#12497) + temp = remaining / animation.duration || 0, + percent = 1 - temp, + index = 0, + length = animation.tweens.length; + + for ( ; index < length; index++ ) { + animation.tweens[ index ].run( percent ); + } + + deferred.notifyWith( elem, [ animation, percent, remaining ] ); + + // If there's more to do, yield + if ( percent < 1 && length ) { + return remaining; + } + + // If this was an empty animation, synthesize a final progress notification + if ( !length ) { + deferred.notifyWith( elem, [ animation, 1, 0 ] ); + } + + // Resolve the animation and report its conclusion + deferred.resolveWith( elem, [ animation ] ); + return false; + }, + animation = deferred.promise( { + elem: elem, + props: jQuery.extend( {}, properties ), + opts: jQuery.extend( true, { + specialEasing: {}, + easing: jQuery.easing._default + }, options ), + originalProperties: properties, + originalOptions: options, + startTime: fxNow || createFxNow(), + duration: options.duration, + tweens: [], + createTween: function( prop, end ) { + var tween = jQuery.Tween( elem, animation.opts, prop, end, + animation.opts.specialEasing[ prop ] || animation.opts.easing ); + animation.tweens.push( tween ); + return tween; + }, + stop: function( gotoEnd ) { + var index = 0, + + // If we are going to the end, we want to run all the tweens + // otherwise we skip this part + length = gotoEnd ? animation.tweens.length : 0; + if ( stopped ) { + return this; + } + stopped = true; + for ( ; index < length; index++ ) { + animation.tweens[ index ].run( 1 ); + } + + // Resolve when we played the last frame; otherwise, reject + if ( gotoEnd ) { + deferred.notifyWith( elem, [ animation, 1, 0 ] ); + deferred.resolveWith( elem, [ animation, gotoEnd ] ); + } else { + deferred.rejectWith( elem, [ animation, gotoEnd ] ); + } + return this; + } + } ), + props = animation.props; + + propFilter( props, animation.opts.specialEasing ); + + for ( ; index < length; index++ ) { + result = Animation.prefilters[ index ].call( animation, elem, props, animation.opts ); + if ( result ) { + if ( isFunction( result.stop ) ) { + jQuery._queueHooks( animation.elem, animation.opts.queue ).stop = + result.stop.bind( result ); + } + return result; + } + } + + jQuery.map( props, createTween, animation ); + + if ( isFunction( animation.opts.start ) ) { + animation.opts.start.call( elem, animation ); + } + + // Attach callbacks from options + animation + .progress( animation.opts.progress ) + .done( animation.opts.done, animation.opts.complete ) + .fail( animation.opts.fail ) + .always( animation.opts.always ); + + jQuery.fx.timer( + jQuery.extend( tick, { + elem: elem, + anim: animation, + queue: animation.opts.queue + } ) + ); + + return animation; +} + +jQuery.Animation = jQuery.extend( Animation, { + + tweeners: { + "*": [ function( prop, value ) { + var tween = this.createTween( prop, value ); + adjustCSS( tween.elem, prop, rcssNum.exec( value ), tween ); + return tween; + } ] + }, + + tweener: function( props, callback ) { + if ( isFunction( props ) ) { + callback = props; + props = [ "*" ]; + } else { + props = props.match( rnothtmlwhite ); + } + + var prop, + index = 0, + length = props.length; + + for ( ; index < length; index++ ) { + prop = props[ index ]; + Animation.tweeners[ prop ] = Animation.tweeners[ prop ] || []; + Animation.tweeners[ prop ].unshift( callback ); + } + }, + + prefilters: [ defaultPrefilter ], + + prefilter: function( callback, prepend ) { + if ( prepend ) { + Animation.prefilters.unshift( callback ); + } else { + Animation.prefilters.push( callback ); + } + } +} ); + +jQuery.speed = function( speed, easing, fn ) { + var opt = speed && typeof speed === "object" ? jQuery.extend( {}, speed ) : { + complete: fn || !fn && easing || + isFunction( speed ) && speed, + duration: speed, + easing: fn && easing || easing && !isFunction( easing ) && easing + }; + + // Go to the end state if fx are off + if ( jQuery.fx.off ) { + opt.duration = 0; + + } else { + if ( typeof opt.duration !== "number" ) { + if ( opt.duration in jQuery.fx.speeds ) { + opt.duration = jQuery.fx.speeds[ opt.duration ]; + + } else { + opt.duration = jQuery.fx.speeds._default; + } + } + } + + // Normalize opt.queue - true/undefined/null -> "fx" + if ( opt.queue == null || opt.queue === true ) { + opt.queue = "fx"; + } + + // Queueing + opt.old = opt.complete; + + opt.complete = function() { + if ( isFunction( opt.old ) ) { + opt.old.call( this ); + } + + if ( opt.queue ) { + jQuery.dequeue( this, opt.queue ); + } + }; + + return opt; +}; + +jQuery.fn.extend( { + fadeTo: function( speed, to, easing, callback ) { + + // Show any hidden elements after setting opacity to 0 + return this.filter( isHiddenWithinTree ).css( "opacity", 0 ).show() + + // Animate to the value specified + .end().animate( { opacity: to }, speed, easing, callback ); + }, + animate: function( prop, speed, easing, callback ) { + var empty = jQuery.isEmptyObject( prop ), + optall = jQuery.speed( speed, easing, callback ), + doAnimation = function() { + + // Operate on a copy of prop so per-property easing won't be lost + var anim = Animation( this, jQuery.extend( {}, prop ), optall ); + + // Empty animations, or finishing resolves immediately + if ( empty || dataPriv.get( this, "finish" ) ) { + anim.stop( true ); + } + }; + doAnimation.finish = doAnimation; + + return empty || optall.queue === false ? + this.each( doAnimation ) : + this.queue( optall.queue, doAnimation ); + }, + stop: function( type, clearQueue, gotoEnd ) { + var stopQueue = function( hooks ) { + var stop = hooks.stop; + delete hooks.stop; + stop( gotoEnd ); + }; + + if ( typeof type !== "string" ) { + gotoEnd = clearQueue; + clearQueue = type; + type = undefined; + } + if ( clearQueue ) { + this.queue( type || "fx", [] ); + } + + return this.each( function() { + var dequeue = true, + index = type != null && type + "queueHooks", + timers = jQuery.timers, + data = dataPriv.get( this ); + + if ( index ) { + if ( data[ index ] && data[ index ].stop ) { + stopQueue( data[ index ] ); + } + } else { + for ( index in data ) { + if ( data[ index ] && data[ index ].stop && rrun.test( index ) ) { + stopQueue( data[ index ] ); + } + } + } + + for ( index = timers.length; index--; ) { + if ( timers[ index ].elem === this && + ( type == null || timers[ index ].queue === type ) ) { + + timers[ index ].anim.stop( gotoEnd ); + dequeue = false; + timers.splice( index, 1 ); + } + } + + // Start the next in the queue if the last step wasn't forced. + // Timers currently will call their complete callbacks, which + // will dequeue but only if they were gotoEnd. + if ( dequeue || !gotoEnd ) { + jQuery.dequeue( this, type ); + } + } ); + }, + finish: function( type ) { + if ( type !== false ) { + type = type || "fx"; + } + return this.each( function() { + var index, + data = dataPriv.get( this ), + queue = data[ type + "queue" ], + hooks = data[ type + "queueHooks" ], + timers = jQuery.timers, + length = queue ? queue.length : 0; + + // Enable finishing flag on private data + data.finish = true; + + // Empty the queue first + jQuery.queue( this, type, [] ); + + if ( hooks && hooks.stop ) { + hooks.stop.call( this, true ); + } + + // Look for any active animations, and finish them + for ( index = timers.length; index--; ) { + if ( timers[ index ].elem === this && timers[ index ].queue === type ) { + timers[ index ].anim.stop( true ); + timers.splice( index, 1 ); + } + } + + // Look for any animations in the old queue and finish them + for ( index = 0; index < length; index++ ) { + if ( queue[ index ] && queue[ index ].finish ) { + queue[ index ].finish.call( this ); + } + } + + // Turn off finishing flag + delete data.finish; + } ); + } +} ); + +jQuery.each( [ "toggle", "show", "hide" ], function( _i, name ) { + var cssFn = jQuery.fn[ name ]; + jQuery.fn[ name ] = function( speed, easing, callback ) { + return speed == null || typeof speed === "boolean" ? + cssFn.apply( this, arguments ) : + this.animate( genFx( name, true ), speed, easing, callback ); + }; +} ); + +// Generate shortcuts for custom animations +jQuery.each( { + slideDown: genFx( "show" ), + slideUp: genFx( "hide" ), + slideToggle: genFx( "toggle" ), + fadeIn: { opacity: "show" }, + fadeOut: { opacity: "hide" }, + fadeToggle: { opacity: "toggle" } +}, function( name, props ) { + jQuery.fn[ name ] = function( speed, easing, callback ) { + return this.animate( props, speed, easing, callback ); + }; +} ); + +jQuery.timers = []; +jQuery.fx.tick = function() { + var timer, + i = 0, + timers = jQuery.timers; + + fxNow = Date.now(); + + for ( ; i < timers.length; i++ ) { + timer = timers[ i ]; + + // Run the timer and safely remove it when done (allowing for external removal) + if ( !timer() && timers[ i ] === timer ) { + timers.splice( i--, 1 ); + } + } + + if ( !timers.length ) { + jQuery.fx.stop(); + } + fxNow = undefined; +}; + +jQuery.fx.timer = function( timer ) { + jQuery.timers.push( timer ); + jQuery.fx.start(); +}; + +jQuery.fx.interval = 13; +jQuery.fx.start = function() { + if ( inProgress ) { + return; + } + + inProgress = true; + schedule(); +}; + +jQuery.fx.stop = function() { + inProgress = null; +}; + +jQuery.fx.speeds = { + slow: 600, + fast: 200, + + // Default speed + _default: 400 +}; + + +// Based off of the plugin by Clint Helfers, with permission. +// https://web.archive.org/web/20100324014747/http://blindsignals.com/index.php/2009/07/jquery-delay/ +jQuery.fn.delay = function( time, type ) { + time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time; + type = type || "fx"; + + return this.queue( type, function( next, hooks ) { + var timeout = window.setTimeout( next, time ); + hooks.stop = function() { + window.clearTimeout( timeout ); + }; + } ); +}; + + +( function() { + var input = document.createElement( "input" ), + select = document.createElement( "select" ), + opt = select.appendChild( document.createElement( "option" ) ); + + input.type = "checkbox"; + + // Support: Android <=4.3 only + // Default value for a checkbox should be "on" + support.checkOn = input.value !== ""; + + // Support: IE <=11 only + // Must access selectedIndex to make default options select + support.optSelected = opt.selected; + + // Support: IE <=11 only + // An input loses its value after becoming a radio + input = document.createElement( "input" ); + input.value = "t"; + input.type = "radio"; + support.radioValue = input.value === "t"; +} )(); + + +var boolHook, + attrHandle = jQuery.expr.attrHandle; + +jQuery.fn.extend( { + attr: function( name, value ) { + return access( this, jQuery.attr, name, value, arguments.length > 1 ); + }, + + removeAttr: function( name ) { + return this.each( function() { + jQuery.removeAttr( this, name ); + } ); + } +} ); + +jQuery.extend( { + attr: function( elem, name, value ) { + var ret, hooks, + nType = elem.nodeType; + + // Don't get/set attributes on text, comment and attribute nodes + if ( nType === 3 || nType === 8 || nType === 2 ) { + return; + } + + // Fallback to prop when attributes are not supported + if ( typeof elem.getAttribute === "undefined" ) { + return jQuery.prop( elem, name, value ); + } + + // Attribute hooks are determined by the lowercase version + // Grab necessary hook if one is defined + if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) { + hooks = jQuery.attrHooks[ name.toLowerCase() ] || + ( jQuery.expr.match.bool.test( name ) ? boolHook : undefined ); + } + + if ( value !== undefined ) { + if ( value === null ) { + jQuery.removeAttr( elem, name ); + return; + } + + if ( hooks && "set" in hooks && + ( ret = hooks.set( elem, value, name ) ) !== undefined ) { + return ret; + } + + elem.setAttribute( name, value + "" ); + return value; + } + + if ( hooks && "get" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) { + return ret; + } + + ret = jQuery.find.attr( elem, name ); + + // Non-existent attributes return null, we normalize to undefined + return ret == null ? undefined : ret; + }, + + attrHooks: { + type: { + set: function( elem, value ) { + if ( !support.radioValue && value === "radio" && + nodeName( elem, "input" ) ) { + var val = elem.value; + elem.setAttribute( "type", value ); + if ( val ) { + elem.value = val; + } + return value; + } + } + } + }, + + removeAttr: function( elem, value ) { + var name, + i = 0, + + // Attribute names can contain non-HTML whitespace characters + // https://html.spec.whatwg.org/multipage/syntax.html#attributes-2 + attrNames = value && value.match( rnothtmlwhite ); + + if ( attrNames && elem.nodeType === 1 ) { + while ( ( name = attrNames[ i++ ] ) ) { + elem.removeAttribute( name ); + } + } + } +} ); + +// Hooks for boolean attributes +boolHook = { + set: function( elem, value, name ) { + if ( value === false ) { + + // Remove boolean attributes when set to false + jQuery.removeAttr( elem, name ); + } else { + elem.setAttribute( name, name ); + } + return name; + } +}; + +jQuery.each( jQuery.expr.match.bool.source.match( /\w+/g ), function( _i, name ) { + var getter = attrHandle[ name ] || jQuery.find.attr; + + attrHandle[ name ] = function( elem, name, isXML ) { + var ret, handle, + lowercaseName = name.toLowerCase(); + + if ( !isXML ) { + + // Avoid an infinite loop by temporarily removing this function from the getter + handle = attrHandle[ lowercaseName ]; + attrHandle[ lowercaseName ] = ret; + ret = getter( elem, name, isXML ) != null ? + lowercaseName : + null; + attrHandle[ lowercaseName ] = handle; + } + return ret; + }; +} ); + + + + +var rfocusable = /^(?:input|select|textarea|button)$/i, + rclickable = /^(?:a|area)$/i; + +jQuery.fn.extend( { + prop: function( name, value ) { + return access( this, jQuery.prop, name, value, arguments.length > 1 ); + }, + + removeProp: function( name ) { + return this.each( function() { + delete this[ jQuery.propFix[ name ] || name ]; + } ); + } +} ); + +jQuery.extend( { + prop: function( elem, name, value ) { + var ret, hooks, + nType = elem.nodeType; + + // Don't get/set properties on text, comment and attribute nodes + if ( nType === 3 || nType === 8 || nType === 2 ) { + return; + } + + if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) { + + // Fix name and attach hooks + name = jQuery.propFix[ name ] || name; + hooks = jQuery.propHooks[ name ]; + } + + if ( value !== undefined ) { + if ( hooks && "set" in hooks && + ( ret = hooks.set( elem, value, name ) ) !== undefined ) { + return ret; + } + + return ( elem[ name ] = value ); + } + + if ( hooks && "get" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) { + return ret; + } + + return elem[ name ]; + }, + + propHooks: { + tabIndex: { + get: function( elem ) { + + // Support: IE <=9 - 11 only + // elem.tabIndex doesn't always return the + // correct value when it hasn't been explicitly set + // https://web.archive.org/web/20141116233347/http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/ + // Use proper attribute retrieval(#12072) + var tabindex = jQuery.find.attr( elem, "tabindex" ); + + if ( tabindex ) { + return parseInt( tabindex, 10 ); + } + + if ( + rfocusable.test( elem.nodeName ) || + rclickable.test( elem.nodeName ) && + elem.href + ) { + return 0; + } + + return -1; + } + } + }, + + propFix: { + "for": "htmlFor", + "class": "className" + } +} ); + +// Support: IE <=11 only +// Accessing the selectedIndex property +// forces the browser to respect setting selected +// on the option +// The getter ensures a default option is selected +// when in an optgroup +// eslint rule "no-unused-expressions" is disabled for this code +// since it considers such accessions noop +if ( !support.optSelected ) { + jQuery.propHooks.selected = { + get: function( elem ) { + + /* eslint no-unused-expressions: "off" */ + + var parent = elem.parentNode; + if ( parent && parent.parentNode ) { + parent.parentNode.selectedIndex; + } + return null; + }, + set: function( elem ) { + + /* eslint no-unused-expressions: "off" */ + + var parent = elem.parentNode; + if ( parent ) { + parent.selectedIndex; + + if ( parent.parentNode ) { + parent.parentNode.selectedIndex; + } + } + } + }; +} + +jQuery.each( [ + "tabIndex", + "readOnly", + "maxLength", + "cellSpacing", + "cellPadding", + "rowSpan", + "colSpan", + "useMap", + "frameBorder", + "contentEditable" +], function() { + jQuery.propFix[ this.toLowerCase() ] = this; +} ); + + + + + // Strip and collapse whitespace according to HTML spec + // https://infra.spec.whatwg.org/#strip-and-collapse-ascii-whitespace + function stripAndCollapse( value ) { + var tokens = value.match( rnothtmlwhite ) || []; + return tokens.join( " " ); + } + + +function getClass( elem ) { + return elem.getAttribute && elem.getAttribute( "class" ) || ""; +} + +function classesToArray( value ) { + if ( Array.isArray( value ) ) { + return value; + } + if ( typeof value === "string" ) { + return value.match( rnothtmlwhite ) || []; + } + return []; +} + +jQuery.fn.extend( { + addClass: function( value ) { + var classes, elem, cur, curValue, clazz, j, finalValue, + i = 0; + + if ( isFunction( value ) ) { + return this.each( function( j ) { + jQuery( this ).addClass( value.call( this, j, getClass( this ) ) ); + } ); + } + + classes = classesToArray( value ); + + if ( classes.length ) { + while ( ( elem = this[ i++ ] ) ) { + curValue = getClass( elem ); + cur = elem.nodeType === 1 && ( " " + stripAndCollapse( curValue ) + " " ); + + if ( cur ) { + j = 0; + while ( ( clazz = classes[ j++ ] ) ) { + if ( cur.indexOf( " " + clazz + " " ) < 0 ) { + cur += clazz + " "; + } + } + + // Only assign if different to avoid unneeded rendering. + finalValue = stripAndCollapse( cur ); + if ( curValue !== finalValue ) { + elem.setAttribute( "class", finalValue ); + } + } + } + } + + return this; + }, + + removeClass: function( value ) { + var classes, elem, cur, curValue, clazz, j, finalValue, + i = 0; + + if ( isFunction( value ) ) { + return this.each( function( j ) { + jQuery( this ).removeClass( value.call( this, j, getClass( this ) ) ); + } ); + } + + if ( !arguments.length ) { + return this.attr( "class", "" ); + } + + classes = classesToArray( value ); + + if ( classes.length ) { + while ( ( elem = this[ i++ ] ) ) { + curValue = getClass( elem ); + + // This expression is here for better compressibility (see addClass) + cur = elem.nodeType === 1 && ( " " + stripAndCollapse( curValue ) + " " ); + + if ( cur ) { + j = 0; + while ( ( clazz = classes[ j++ ] ) ) { + + // Remove *all* instances + while ( cur.indexOf( " " + clazz + " " ) > -1 ) { + cur = cur.replace( " " + clazz + " ", " " ); + } + } + + // Only assign if different to avoid unneeded rendering. + finalValue = stripAndCollapse( cur ); + if ( curValue !== finalValue ) { + elem.setAttribute( "class", finalValue ); + } + } + } + } + + return this; + }, + + toggleClass: function( value, stateVal ) { + var type = typeof value, + isValidValue = type === "string" || Array.isArray( value ); + + if ( typeof stateVal === "boolean" && isValidValue ) { + return stateVal ? this.addClass( value ) : this.removeClass( value ); + } + + if ( isFunction( value ) ) { + return this.each( function( i ) { + jQuery( this ).toggleClass( + value.call( this, i, getClass( this ), stateVal ), + stateVal + ); + } ); + } + + return this.each( function() { + var className, i, self, classNames; + + if ( isValidValue ) { + + // Toggle individual class names + i = 0; + self = jQuery( this ); + classNames = classesToArray( value ); + + while ( ( className = classNames[ i++ ] ) ) { + + // Check each className given, space separated list + if ( self.hasClass( className ) ) { + self.removeClass( className ); + } else { + self.addClass( className ); + } + } + + // Toggle whole class name + } else if ( value === undefined || type === "boolean" ) { + className = getClass( this ); + if ( className ) { + + // Store className if set + dataPriv.set( this, "__className__", className ); + } + + // If the element has a class name or if we're passed `false`, + // then remove the whole classname (if there was one, the above saved it). + // Otherwise bring back whatever was previously saved (if anything), + // falling back to the empty string if nothing was stored. + if ( this.setAttribute ) { + this.setAttribute( "class", + className || value === false ? + "" : + dataPriv.get( this, "__className__" ) || "" + ); + } + } + } ); + }, + + hasClass: function( selector ) { + var className, elem, + i = 0; + + className = " " + selector + " "; + while ( ( elem = this[ i++ ] ) ) { + if ( elem.nodeType === 1 && + ( " " + stripAndCollapse( getClass( elem ) ) + " " ).indexOf( className ) > -1 ) { + return true; + } + } + + return false; + } +} ); + + + + +var rreturn = /\r/g; + +jQuery.fn.extend( { + val: function( value ) { + var hooks, ret, valueIsFunction, + elem = this[ 0 ]; + + if ( !arguments.length ) { + if ( elem ) { + hooks = jQuery.valHooks[ elem.type ] || + jQuery.valHooks[ elem.nodeName.toLowerCase() ]; + + if ( hooks && + "get" in hooks && + ( ret = hooks.get( elem, "value" ) ) !== undefined + ) { + return ret; + } + + ret = elem.value; + + // Handle most common string cases + if ( typeof ret === "string" ) { + return ret.replace( rreturn, "" ); + } + + // Handle cases where value is null/undef or number + return ret == null ? "" : ret; + } + + return; + } + + valueIsFunction = isFunction( value ); + + return this.each( function( i ) { + var val; + + if ( this.nodeType !== 1 ) { + return; + } + + if ( valueIsFunction ) { + val = value.call( this, i, jQuery( this ).val() ); + } else { + val = value; + } + + // Treat null/undefined as ""; convert numbers to string + if ( val == null ) { + val = ""; + + } else if ( typeof val === "number" ) { + val += ""; + + } else if ( Array.isArray( val ) ) { + val = jQuery.map( val, function( value ) { + return value == null ? "" : value + ""; + } ); + } + + hooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ]; + + // If set returns undefined, fall back to normal setting + if ( !hooks || !( "set" in hooks ) || hooks.set( this, val, "value" ) === undefined ) { + this.value = val; + } + } ); + } +} ); + +jQuery.extend( { + valHooks: { + option: { + get: function( elem ) { + + var val = jQuery.find.attr( elem, "value" ); + return val != null ? + val : + + // Support: IE <=10 - 11 only + // option.text throws exceptions (#14686, #14858) + // Strip and collapse whitespace + // https://html.spec.whatwg.org/#strip-and-collapse-whitespace + stripAndCollapse( jQuery.text( elem ) ); + } + }, + select: { + get: function( elem ) { + var value, option, i, + options = elem.options, + index = elem.selectedIndex, + one = elem.type === "select-one", + values = one ? null : [], + max = one ? index + 1 : options.length; + + if ( index < 0 ) { + i = max; + + } else { + i = one ? index : 0; + } + + // Loop through all the selected options + for ( ; i < max; i++ ) { + option = options[ i ]; + + // Support: IE <=9 only + // IE8-9 doesn't update selected after form reset (#2551) + if ( ( option.selected || i === index ) && + + // Don't return options that are disabled or in a disabled optgroup + !option.disabled && + ( !option.parentNode.disabled || + !nodeName( option.parentNode, "optgroup" ) ) ) { + + // Get the specific value for the option + value = jQuery( option ).val(); + + // We don't need an array for one selects + if ( one ) { + return value; + } + + // Multi-Selects return an array + values.push( value ); + } + } + + return values; + }, + + set: function( elem, value ) { + var optionSet, option, + options = elem.options, + values = jQuery.makeArray( value ), + i = options.length; + + while ( i-- ) { + option = options[ i ]; + + /* eslint-disable no-cond-assign */ + + if ( option.selected = + jQuery.inArray( jQuery.valHooks.option.get( option ), values ) > -1 + ) { + optionSet = true; + } + + /* eslint-enable no-cond-assign */ + } + + // Force browsers to behave consistently when non-matching value is set + if ( !optionSet ) { + elem.selectedIndex = -1; + } + return values; + } + } + } +} ); + +// Radios and checkboxes getter/setter +jQuery.each( [ "radio", "checkbox" ], function() { + jQuery.valHooks[ this ] = { + set: function( elem, value ) { + if ( Array.isArray( value ) ) { + return ( elem.checked = jQuery.inArray( jQuery( elem ).val(), value ) > -1 ); + } + } + }; + if ( !support.checkOn ) { + jQuery.valHooks[ this ].get = function( elem ) { + return elem.getAttribute( "value" ) === null ? "on" : elem.value; + }; + } +} ); + + + + +// Return jQuery for attributes-only inclusion + + +support.focusin = "onfocusin" in window; + + +var rfocusMorph = /^(?:focusinfocus|focusoutblur)$/, + stopPropagationCallback = function( e ) { + e.stopPropagation(); + }; + +jQuery.extend( jQuery.event, { + + trigger: function( event, data, elem, onlyHandlers ) { + + var i, cur, tmp, bubbleType, ontype, handle, special, lastElement, + eventPath = [ elem || document ], + type = hasOwn.call( event, "type" ) ? event.type : event, + namespaces = hasOwn.call( event, "namespace" ) ? event.namespace.split( "." ) : []; + + cur = lastElement = tmp = elem = elem || document; + + // Don't do events on text and comment nodes + if ( elem.nodeType === 3 || elem.nodeType === 8 ) { + return; + } + + // focus/blur morphs to focusin/out; ensure we're not firing them right now + if ( rfocusMorph.test( type + jQuery.event.triggered ) ) { + return; + } + + if ( type.indexOf( "." ) > -1 ) { + + // Namespaced trigger; create a regexp to match event type in handle() + namespaces = type.split( "." ); + type = namespaces.shift(); + namespaces.sort(); + } + ontype = type.indexOf( ":" ) < 0 && "on" + type; + + // Caller can pass in a jQuery.Event object, Object, or just an event type string + event = event[ jQuery.expando ] ? + event : + new jQuery.Event( type, typeof event === "object" && event ); + + // Trigger bitmask: & 1 for native handlers; & 2 for jQuery (always true) + event.isTrigger = onlyHandlers ? 2 : 3; + event.namespace = namespaces.join( "." ); + event.rnamespace = event.namespace ? + new RegExp( "(^|\\.)" + namespaces.join( "\\.(?:.*\\.|)" ) + "(\\.|$)" ) : + null; + + // Clean up the event in case it is being reused + event.result = undefined; + if ( !event.target ) { + event.target = elem; + } + + // Clone any incoming data and prepend the event, creating the handler arg list + data = data == null ? + [ event ] : + jQuery.makeArray( data, [ event ] ); + + // Allow special events to draw outside the lines + special = jQuery.event.special[ type ] || {}; + if ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) { + return; + } + + // Determine event propagation path in advance, per W3C events spec (#9951) + // Bubble up to document, then to window; watch for a global ownerDocument var (#9724) + if ( !onlyHandlers && !special.noBubble && !isWindow( elem ) ) { + + bubbleType = special.delegateType || type; + if ( !rfocusMorph.test( bubbleType + type ) ) { + cur = cur.parentNode; + } + for ( ; cur; cur = cur.parentNode ) { + eventPath.push( cur ); + tmp = cur; + } + + // Only add window if we got to document (e.g., not plain obj or detached DOM) + if ( tmp === ( elem.ownerDocument || document ) ) { + eventPath.push( tmp.defaultView || tmp.parentWindow || window ); + } + } + + // Fire handlers on the event path + i = 0; + while ( ( cur = eventPath[ i++ ] ) && !event.isPropagationStopped() ) { + lastElement = cur; + event.type = i > 1 ? + bubbleType : + special.bindType || type; + + // jQuery handler + handle = ( + dataPriv.get( cur, "events" ) || Object.create( null ) + )[ event.type ] && + dataPriv.get( cur, "handle" ); + if ( handle ) { + handle.apply( cur, data ); + } + + // Native handler + handle = ontype && cur[ ontype ]; + if ( handle && handle.apply && acceptData( cur ) ) { + event.result = handle.apply( cur, data ); + if ( event.result === false ) { + event.preventDefault(); + } + } + } + event.type = type; + + // If nobody prevented the default action, do it now + if ( !onlyHandlers && !event.isDefaultPrevented() ) { + + if ( ( !special._default || + special._default.apply( eventPath.pop(), data ) === false ) && + acceptData( elem ) ) { + + // Call a native DOM method on the target with the same name as the event. + // Don't do default actions on window, that's where global variables be (#6170) + if ( ontype && isFunction( elem[ type ] ) && !isWindow( elem ) ) { + + // Don't re-trigger an onFOO event when we call its FOO() method + tmp = elem[ ontype ]; + + if ( tmp ) { + elem[ ontype ] = null; + } + + // Prevent re-triggering of the same event, since we already bubbled it above + jQuery.event.triggered = type; + + if ( event.isPropagationStopped() ) { + lastElement.addEventListener( type, stopPropagationCallback ); + } + + elem[ type ](); + + if ( event.isPropagationStopped() ) { + lastElement.removeEventListener( type, stopPropagationCallback ); + } + + jQuery.event.triggered = undefined; + + if ( tmp ) { + elem[ ontype ] = tmp; + } + } + } + } + + return event.result; + }, + + // Piggyback on a donor event to simulate a different one + // Used only for `focus(in | out)` events + simulate: function( type, elem, event ) { + var e = jQuery.extend( + new jQuery.Event(), + event, + { + type: type, + isSimulated: true + } + ); + + jQuery.event.trigger( e, null, elem ); + } + +} ); + +jQuery.fn.extend( { + + trigger: function( type, data ) { + return this.each( function() { + jQuery.event.trigger( type, data, this ); + } ); + }, + triggerHandler: function( type, data ) { + var elem = this[ 0 ]; + if ( elem ) { + return jQuery.event.trigger( type, data, elem, true ); + } + } +} ); + + +// Support: Firefox <=44 +// Firefox doesn't have focus(in | out) events +// Related ticket - https://bugzilla.mozilla.org/show_bug.cgi?id=687787 +// +// Support: Chrome <=48 - 49, Safari <=9.0 - 9.1 +// focus(in | out) events fire after focus & blur events, +// which is spec violation - http://www.w3.org/TR/DOM-Level-3-Events/#events-focusevent-event-order +// Related ticket - https://bugs.chromium.org/p/chromium/issues/detail?id=449857 +if ( !support.focusin ) { + jQuery.each( { focus: "focusin", blur: "focusout" }, function( orig, fix ) { + + // Attach a single capturing handler on the document while someone wants focusin/focusout + var handler = function( event ) { + jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ) ); + }; + + jQuery.event.special[ fix ] = { + setup: function() { + + // Handle: regular nodes (via `this.ownerDocument`), window + // (via `this.document`) & document (via `this`). + var doc = this.ownerDocument || this.document || this, + attaches = dataPriv.access( doc, fix ); + + if ( !attaches ) { + doc.addEventListener( orig, handler, true ); + } + dataPriv.access( doc, fix, ( attaches || 0 ) + 1 ); + }, + teardown: function() { + var doc = this.ownerDocument || this.document || this, + attaches = dataPriv.access( doc, fix ) - 1; + + if ( !attaches ) { + doc.removeEventListener( orig, handler, true ); + dataPriv.remove( doc, fix ); + + } else { + dataPriv.access( doc, fix, attaches ); + } + } + }; + } ); +} +var location = window.location; + +var nonce = { guid: Date.now() }; + +var rquery = ( /\?/ ); + + + +// Cross-browser xml parsing +jQuery.parseXML = function( data ) { + var xml; + if ( !data || typeof data !== "string" ) { + return null; + } + + // Support: IE 9 - 11 only + // IE throws on parseFromString with invalid input. + try { + xml = ( new window.DOMParser() ).parseFromString( data, "text/xml" ); + } catch ( e ) { + xml = undefined; + } + + if ( !xml || xml.getElementsByTagName( "parsererror" ).length ) { + jQuery.error( "Invalid XML: " + data ); + } + return xml; +}; + + +var + rbracket = /\[\]$/, + rCRLF = /\r?\n/g, + rsubmitterTypes = /^(?:submit|button|image|reset|file)$/i, + rsubmittable = /^(?:input|select|textarea|keygen)/i; + +function buildParams( prefix, obj, traditional, add ) { + var name; + + if ( Array.isArray( obj ) ) { + + // Serialize array item. + jQuery.each( obj, function( i, v ) { + if ( traditional || rbracket.test( prefix ) ) { + + // Treat each array item as a scalar. + add( prefix, v ); + + } else { + + // Item is non-scalar (array or object), encode its numeric index. + buildParams( + prefix + "[" + ( typeof v === "object" && v != null ? i : "" ) + "]", + v, + traditional, + add + ); + } + } ); + + } else if ( !traditional && toType( obj ) === "object" ) { + + // Serialize object item. + for ( name in obj ) { + buildParams( prefix + "[" + name + "]", obj[ name ], traditional, add ); + } + + } else { + + // Serialize scalar item. + add( prefix, obj ); + } +} + +// Serialize an array of form elements or a set of +// key/values into a query string +jQuery.param = function( a, traditional ) { + var prefix, + s = [], + add = function( key, valueOrFunction ) { + + // If value is a function, invoke it and use its return value + var value = isFunction( valueOrFunction ) ? + valueOrFunction() : + valueOrFunction; + + s[ s.length ] = encodeURIComponent( key ) + "=" + + encodeURIComponent( value == null ? "" : value ); + }; + + if ( a == null ) { + return ""; + } + + // If an array was passed in, assume that it is an array of form elements. + if ( Array.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) { + + // Serialize the form elements + jQuery.each( a, function() { + add( this.name, this.value ); + } ); + + } else { + + // If traditional, encode the "old" way (the way 1.3.2 or older + // did it), otherwise encode params recursively. + for ( prefix in a ) { + buildParams( prefix, a[ prefix ], traditional, add ); + } + } + + // Return the resulting serialization + return s.join( "&" ); +}; + +jQuery.fn.extend( { + serialize: function() { + return jQuery.param( this.serializeArray() ); + }, + serializeArray: function() { + return this.map( function() { + + // Can add propHook for "elements" to filter or add form elements + var elements = jQuery.prop( this, "elements" ); + return elements ? jQuery.makeArray( elements ) : this; + } ) + .filter( function() { + var type = this.type; + + // Use .is( ":disabled" ) so that fieldset[disabled] works + return this.name && !jQuery( this ).is( ":disabled" ) && + rsubmittable.test( this.nodeName ) && !rsubmitterTypes.test( type ) && + ( this.checked || !rcheckableType.test( type ) ); + } ) + .map( function( _i, elem ) { + var val = jQuery( this ).val(); + + if ( val == null ) { + return null; + } + + if ( Array.isArray( val ) ) { + return jQuery.map( val, function( val ) { + return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) }; + } ); + } + + return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) }; + } ).get(); + } +} ); + + +var + r20 = /%20/g, + rhash = /#.*$/, + rantiCache = /([?&])_=[^&]*/, + rheaders = /^(.*?):[ \t]*([^\r\n]*)$/mg, + + // #7653, #8125, #8152: local protocol detection + rlocalProtocol = /^(?:about|app|app-storage|.+-extension|file|res|widget):$/, + rnoContent = /^(?:GET|HEAD)$/, + rprotocol = /^\/\//, + + /* Prefilters + * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example) + * 2) These are called: + * - BEFORE asking for a transport + * - AFTER param serialization (s.data is a string if s.processData is true) + * 3) key is the dataType + * 4) the catchall symbol "*" can be used + * 5) execution will start with transport dataType and THEN continue down to "*" if needed + */ + prefilters = {}, + + /* Transports bindings + * 1) key is the dataType + * 2) the catchall symbol "*" can be used + * 3) selection will start with transport dataType and THEN go to "*" if needed + */ + transports = {}, + + // Avoid comment-prolog char sequence (#10098); must appease lint and evade compression + allTypes = "*/".concat( "*" ), + + // Anchor tag for parsing the document origin + originAnchor = document.createElement( "a" ); + originAnchor.href = location.href; + +// Base "constructor" for jQuery.ajaxPrefilter and jQuery.ajaxTransport +function addToPrefiltersOrTransports( structure ) { + + // dataTypeExpression is optional and defaults to "*" + return function( dataTypeExpression, func ) { + + if ( typeof dataTypeExpression !== "string" ) { + func = dataTypeExpression; + dataTypeExpression = "*"; + } + + var dataType, + i = 0, + dataTypes = dataTypeExpression.toLowerCase().match( rnothtmlwhite ) || []; + + if ( isFunction( func ) ) { + + // For each dataType in the dataTypeExpression + while ( ( dataType = dataTypes[ i++ ] ) ) { + + // Prepend if requested + if ( dataType[ 0 ] === "+" ) { + dataType = dataType.slice( 1 ) || "*"; + ( structure[ dataType ] = structure[ dataType ] || [] ).unshift( func ); + + // Otherwise append + } else { + ( structure[ dataType ] = structure[ dataType ] || [] ).push( func ); + } + } + } + }; +} + +// Base inspection function for prefilters and transports +function inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR ) { + + var inspected = {}, + seekingTransport = ( structure === transports ); + + function inspect( dataType ) { + var selected; + inspected[ dataType ] = true; + jQuery.each( structure[ dataType ] || [], function( _, prefilterOrFactory ) { + var dataTypeOrTransport = prefilterOrFactory( options, originalOptions, jqXHR ); + if ( typeof dataTypeOrTransport === "string" && + !seekingTransport && !inspected[ dataTypeOrTransport ] ) { + + options.dataTypes.unshift( dataTypeOrTransport ); + inspect( dataTypeOrTransport ); + return false; + } else if ( seekingTransport ) { + return !( selected = dataTypeOrTransport ); + } + } ); + return selected; + } + + return inspect( options.dataTypes[ 0 ] ) || !inspected[ "*" ] && inspect( "*" ); +} + +// A special extend for ajax options +// that takes "flat" options (not to be deep extended) +// Fixes #9887 +function ajaxExtend( target, src ) { + var key, deep, + flatOptions = jQuery.ajaxSettings.flatOptions || {}; + + for ( key in src ) { + if ( src[ key ] !== undefined ) { + ( flatOptions[ key ] ? target : ( deep || ( deep = {} ) ) )[ key ] = src[ key ]; + } + } + if ( deep ) { + jQuery.extend( true, target, deep ); + } + + return target; +} + +/* Handles responses to an ajax request: + * - finds the right dataType (mediates between content-type and expected dataType) + * - returns the corresponding response + */ +function ajaxHandleResponses( s, jqXHR, responses ) { + + var ct, type, finalDataType, firstDataType, + contents = s.contents, + dataTypes = s.dataTypes; + + // Remove auto dataType and get content-type in the process + while ( dataTypes[ 0 ] === "*" ) { + dataTypes.shift(); + if ( ct === undefined ) { + ct = s.mimeType || jqXHR.getResponseHeader( "Content-Type" ); + } + } + + // Check if we're dealing with a known content-type + if ( ct ) { + for ( type in contents ) { + if ( contents[ type ] && contents[ type ].test( ct ) ) { + dataTypes.unshift( type ); + break; + } + } + } + + // Check to see if we have a response for the expected dataType + if ( dataTypes[ 0 ] in responses ) { + finalDataType = dataTypes[ 0 ]; + } else { + + // Try convertible dataTypes + for ( type in responses ) { + if ( !dataTypes[ 0 ] || s.converters[ type + " " + dataTypes[ 0 ] ] ) { + finalDataType = type; + break; + } + if ( !firstDataType ) { + firstDataType = type; + } + } + + // Or just use first one + finalDataType = finalDataType || firstDataType; + } + + // If we found a dataType + // We add the dataType to the list if needed + // and return the corresponding response + if ( finalDataType ) { + if ( finalDataType !== dataTypes[ 0 ] ) { + dataTypes.unshift( finalDataType ); + } + return responses[ finalDataType ]; + } +} + +/* Chain conversions given the request and the original response + * Also sets the responseXXX fields on the jqXHR instance + */ +function ajaxConvert( s, response, jqXHR, isSuccess ) { + var conv2, current, conv, tmp, prev, + converters = {}, + + // Work with a copy of dataTypes in case we need to modify it for conversion + dataTypes = s.dataTypes.slice(); + + // Create converters map with lowercased keys + if ( dataTypes[ 1 ] ) { + for ( conv in s.converters ) { + converters[ conv.toLowerCase() ] = s.converters[ conv ]; + } + } + + current = dataTypes.shift(); + + // Convert to each sequential dataType + while ( current ) { + + if ( s.responseFields[ current ] ) { + jqXHR[ s.responseFields[ current ] ] = response; + } + + // Apply the dataFilter if provided + if ( !prev && isSuccess && s.dataFilter ) { + response = s.dataFilter( response, s.dataType ); + } + + prev = current; + current = dataTypes.shift(); + + if ( current ) { + + // There's only work to do if current dataType is non-auto + if ( current === "*" ) { + + current = prev; + + // Convert response if prev dataType is non-auto and differs from current + } else if ( prev !== "*" && prev !== current ) { + + // Seek a direct converter + conv = converters[ prev + " " + current ] || converters[ "* " + current ]; + + // If none found, seek a pair + if ( !conv ) { + for ( conv2 in converters ) { + + // If conv2 outputs current + tmp = conv2.split( " " ); + if ( tmp[ 1 ] === current ) { + + // If prev can be converted to accepted input + conv = converters[ prev + " " + tmp[ 0 ] ] || + converters[ "* " + tmp[ 0 ] ]; + if ( conv ) { + + // Condense equivalence converters + if ( conv === true ) { + conv = converters[ conv2 ]; + + // Otherwise, insert the intermediate dataType + } else if ( converters[ conv2 ] !== true ) { + current = tmp[ 0 ]; + dataTypes.unshift( tmp[ 1 ] ); + } + break; + } + } + } + } + + // Apply converter (if not an equivalence) + if ( conv !== true ) { + + // Unless errors are allowed to bubble, catch and return them + if ( conv && s.throws ) { + response = conv( response ); + } else { + try { + response = conv( response ); + } catch ( e ) { + return { + state: "parsererror", + error: conv ? e : "No conversion from " + prev + " to " + current + }; + } + } + } + } + } + } + + return { state: "success", data: response }; +} + +jQuery.extend( { + + // Counter for holding the number of active queries + active: 0, + + // Last-Modified header cache for next request + lastModified: {}, + etag: {}, + + ajaxSettings: { + url: location.href, + type: "GET", + isLocal: rlocalProtocol.test( location.protocol ), + global: true, + processData: true, + async: true, + contentType: "application/x-www-form-urlencoded; charset=UTF-8", + + /* + timeout: 0, + data: null, + dataType: null, + username: null, + password: null, + cache: null, + throws: false, + traditional: false, + headers: {}, + */ + + accepts: { + "*": allTypes, + text: "text/plain", + html: "text/html", + xml: "application/xml, text/xml", + json: "application/json, text/javascript" + }, + + contents: { + xml: /\bxml\b/, + html: /\bhtml/, + json: /\bjson\b/ + }, + + responseFields: { + xml: "responseXML", + text: "responseText", + json: "responseJSON" + }, + + // Data converters + // Keys separate source (or catchall "*") and destination types with a single space + converters: { + + // Convert anything to text + "* text": String, + + // Text to html (true = no transformation) + "text html": true, + + // Evaluate text as a json expression + "text json": JSON.parse, + + // Parse text as xml + "text xml": jQuery.parseXML + }, + + // For options that shouldn't be deep extended: + // you can add your own custom options here if + // and when you create one that shouldn't be + // deep extended (see ajaxExtend) + flatOptions: { + url: true, + context: true + } + }, + + // Creates a full fledged settings object into target + // with both ajaxSettings and settings fields. + // If target is omitted, writes into ajaxSettings. + ajaxSetup: function( target, settings ) { + return settings ? + + // Building a settings object + ajaxExtend( ajaxExtend( target, jQuery.ajaxSettings ), settings ) : + + // Extending ajaxSettings + ajaxExtend( jQuery.ajaxSettings, target ); + }, + + ajaxPrefilter: addToPrefiltersOrTransports( prefilters ), + ajaxTransport: addToPrefiltersOrTransports( transports ), + + // Main method + ajax: function( url, options ) { + + // If url is an object, simulate pre-1.5 signature + if ( typeof url === "object" ) { + options = url; + url = undefined; + } + + // Force options to be an object + options = options || {}; + + var transport, + + // URL without anti-cache param + cacheURL, + + // Response headers + responseHeadersString, + responseHeaders, + + // timeout handle + timeoutTimer, + + // Url cleanup var + urlAnchor, + + // Request state (becomes false upon send and true upon completion) + completed, + + // To know if global events are to be dispatched + fireGlobals, + + // Loop variable + i, + + // uncached part of the url + uncached, + + // Create the final options object + s = jQuery.ajaxSetup( {}, options ), + + // Callbacks context + callbackContext = s.context || s, + + // Context for global events is callbackContext if it is a DOM node or jQuery collection + globalEventContext = s.context && + ( callbackContext.nodeType || callbackContext.jquery ) ? + jQuery( callbackContext ) : + jQuery.event, + + // Deferreds + deferred = jQuery.Deferred(), + completeDeferred = jQuery.Callbacks( "once memory" ), + + // Status-dependent callbacks + statusCode = s.statusCode || {}, + + // Headers (they are sent all at once) + requestHeaders = {}, + requestHeadersNames = {}, + + // Default abort message + strAbort = "canceled", + + // Fake xhr + jqXHR = { + readyState: 0, + + // Builds headers hashtable if needed + getResponseHeader: function( key ) { + var match; + if ( completed ) { + if ( !responseHeaders ) { + responseHeaders = {}; + while ( ( match = rheaders.exec( responseHeadersString ) ) ) { + responseHeaders[ match[ 1 ].toLowerCase() + " " ] = + ( responseHeaders[ match[ 1 ].toLowerCase() + " " ] || [] ) + .concat( match[ 2 ] ); + } + } + match = responseHeaders[ key.toLowerCase() + " " ]; + } + return match == null ? null : match.join( ", " ); + }, + + // Raw string + getAllResponseHeaders: function() { + return completed ? responseHeadersString : null; + }, + + // Caches the header + setRequestHeader: function( name, value ) { + if ( completed == null ) { + name = requestHeadersNames[ name.toLowerCase() ] = + requestHeadersNames[ name.toLowerCase() ] || name; + requestHeaders[ name ] = value; + } + return this; + }, + + // Overrides response content-type header + overrideMimeType: function( type ) { + if ( completed == null ) { + s.mimeType = type; + } + return this; + }, + + // Status-dependent callbacks + statusCode: function( map ) { + var code; + if ( map ) { + if ( completed ) { + + // Execute the appropriate callbacks + jqXHR.always( map[ jqXHR.status ] ); + } else { + + // Lazy-add the new callbacks in a way that preserves old ones + for ( code in map ) { + statusCode[ code ] = [ statusCode[ code ], map[ code ] ]; + } + } + } + return this; + }, + + // Cancel the request + abort: function( statusText ) { + var finalText = statusText || strAbort; + if ( transport ) { + transport.abort( finalText ); + } + done( 0, finalText ); + return this; + } + }; + + // Attach deferreds + deferred.promise( jqXHR ); + + // Add protocol if not provided (prefilters might expect it) + // Handle falsy url in the settings object (#10093: consistency with old signature) + // We also use the url parameter if available + s.url = ( ( url || s.url || location.href ) + "" ) + .replace( rprotocol, location.protocol + "//" ); + + // Alias method option to type as per ticket #12004 + s.type = options.method || options.type || s.method || s.type; + + // Extract dataTypes list + s.dataTypes = ( s.dataType || "*" ).toLowerCase().match( rnothtmlwhite ) || [ "" ]; + + // A cross-domain request is in order when the origin doesn't match the current origin. + if ( s.crossDomain == null ) { + urlAnchor = document.createElement( "a" ); + + // Support: IE <=8 - 11, Edge 12 - 15 + // IE throws exception on accessing the href property if url is malformed, + // e.g. http://example.com:80x/ + try { + urlAnchor.href = s.url; + + // Support: IE <=8 - 11 only + // Anchor's host property isn't correctly set when s.url is relative + urlAnchor.href = urlAnchor.href; + s.crossDomain = originAnchor.protocol + "//" + originAnchor.host !== + urlAnchor.protocol + "//" + urlAnchor.host; + } catch ( e ) { + + // If there is an error parsing the URL, assume it is crossDomain, + // it can be rejected by the transport if it is invalid + s.crossDomain = true; + } + } + + // Convert data if not already a string + if ( s.data && s.processData && typeof s.data !== "string" ) { + s.data = jQuery.param( s.data, s.traditional ); + } + + // Apply prefilters + inspectPrefiltersOrTransports( prefilters, s, options, jqXHR ); + + // If request was aborted inside a prefilter, stop there + if ( completed ) { + return jqXHR; + } + + // We can fire global events as of now if asked to + // Don't fire events if jQuery.event is undefined in an AMD-usage scenario (#15118) + fireGlobals = jQuery.event && s.global; + + // Watch for a new set of requests + if ( fireGlobals && jQuery.active++ === 0 ) { + jQuery.event.trigger( "ajaxStart" ); + } + + // Uppercase the type + s.type = s.type.toUpperCase(); + + // Determine if request has content + s.hasContent = !rnoContent.test( s.type ); + + // Save the URL in case we're toying with the If-Modified-Since + // and/or If-None-Match header later on + // Remove hash to simplify url manipulation + cacheURL = s.url.replace( rhash, "" ); + + // More options handling for requests with no content + if ( !s.hasContent ) { + + // Remember the hash so we can put it back + uncached = s.url.slice( cacheURL.length ); + + // If data is available and should be processed, append data to url + if ( s.data && ( s.processData || typeof s.data === "string" ) ) { + cacheURL += ( rquery.test( cacheURL ) ? "&" : "?" ) + s.data; + + // #9682: remove data so that it's not used in an eventual retry + delete s.data; + } + + // Add or update anti-cache param if needed + if ( s.cache === false ) { + cacheURL = cacheURL.replace( rantiCache, "$1" ); + uncached = ( rquery.test( cacheURL ) ? "&" : "?" ) + "_=" + ( nonce.guid++ ) + + uncached; + } + + // Put hash and anti-cache on the URL that will be requested (gh-1732) + s.url = cacheURL + uncached; + + // Change '%20' to '+' if this is encoded form body content (gh-2658) + } else if ( s.data && s.processData && + ( s.contentType || "" ).indexOf( "application/x-www-form-urlencoded" ) === 0 ) { + s.data = s.data.replace( r20, "+" ); + } + + // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode. + if ( s.ifModified ) { + if ( jQuery.lastModified[ cacheURL ] ) { + jqXHR.setRequestHeader( "If-Modified-Since", jQuery.lastModified[ cacheURL ] ); + } + if ( jQuery.etag[ cacheURL ] ) { + jqXHR.setRequestHeader( "If-None-Match", jQuery.etag[ cacheURL ] ); + } + } + + // Set the correct header, if data is being sent + if ( s.data && s.hasContent && s.contentType !== false || options.contentType ) { + jqXHR.setRequestHeader( "Content-Type", s.contentType ); + } + + // Set the Accepts header for the server, depending on the dataType + jqXHR.setRequestHeader( + "Accept", + s.dataTypes[ 0 ] && s.accepts[ s.dataTypes[ 0 ] ] ? + s.accepts[ s.dataTypes[ 0 ] ] + + ( s.dataTypes[ 0 ] !== "*" ? ", " + allTypes + "; q=0.01" : "" ) : + s.accepts[ "*" ] + ); + + // Check for headers option + for ( i in s.headers ) { + jqXHR.setRequestHeader( i, s.headers[ i ] ); + } + + // Allow custom headers/mimetypes and early abort + if ( s.beforeSend && + ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || completed ) ) { + + // Abort if not done already and return + return jqXHR.abort(); + } + + // Aborting is no longer a cancellation + strAbort = "abort"; + + // Install callbacks on deferreds + completeDeferred.add( s.complete ); + jqXHR.done( s.success ); + jqXHR.fail( s.error ); + + // Get transport + transport = inspectPrefiltersOrTransports( transports, s, options, jqXHR ); + + // If no transport, we auto-abort + if ( !transport ) { + done( -1, "No Transport" ); + } else { + jqXHR.readyState = 1; + + // Send global event + if ( fireGlobals ) { + globalEventContext.trigger( "ajaxSend", [ jqXHR, s ] ); + } + + // If request was aborted inside ajaxSend, stop there + if ( completed ) { + return jqXHR; + } + + // Timeout + if ( s.async && s.timeout > 0 ) { + timeoutTimer = window.setTimeout( function() { + jqXHR.abort( "timeout" ); + }, s.timeout ); + } + + try { + completed = false; + transport.send( requestHeaders, done ); + } catch ( e ) { + + // Rethrow post-completion exceptions + if ( completed ) { + throw e; + } + + // Propagate others as results + done( -1, e ); + } + } + + // Callback for when everything is done + function done( status, nativeStatusText, responses, headers ) { + var isSuccess, success, error, response, modified, + statusText = nativeStatusText; + + // Ignore repeat invocations + if ( completed ) { + return; + } + + completed = true; + + // Clear timeout if it exists + if ( timeoutTimer ) { + window.clearTimeout( timeoutTimer ); + } + + // Dereference transport for early garbage collection + // (no matter how long the jqXHR object will be used) + transport = undefined; + + // Cache response headers + responseHeadersString = headers || ""; + + // Set readyState + jqXHR.readyState = status > 0 ? 4 : 0; + + // Determine if successful + isSuccess = status >= 200 && status < 300 || status === 304; + + // Get response data + if ( responses ) { + response = ajaxHandleResponses( s, jqXHR, responses ); + } + + // Use a noop converter for missing script + if ( !isSuccess && jQuery.inArray( "script", s.dataTypes ) > -1 ) { + s.converters[ "text script" ] = function() {}; + } + + // Convert no matter what (that way responseXXX fields are always set) + response = ajaxConvert( s, response, jqXHR, isSuccess ); + + // If successful, handle type chaining + if ( isSuccess ) { + + // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode. + if ( s.ifModified ) { + modified = jqXHR.getResponseHeader( "Last-Modified" ); + if ( modified ) { + jQuery.lastModified[ cacheURL ] = modified; + } + modified = jqXHR.getResponseHeader( "etag" ); + if ( modified ) { + jQuery.etag[ cacheURL ] = modified; + } + } + + // if no content + if ( status === 204 || s.type === "HEAD" ) { + statusText = "nocontent"; + + // if not modified + } else if ( status === 304 ) { + statusText = "notmodified"; + + // If we have data, let's convert it + } else { + statusText = response.state; + success = response.data; + error = response.error; + isSuccess = !error; + } + } else { + + // Extract error from statusText and normalize for non-aborts + error = statusText; + if ( status || !statusText ) { + statusText = "error"; + if ( status < 0 ) { + status = 0; + } + } + } + + // Set data for the fake xhr object + jqXHR.status = status; + jqXHR.statusText = ( nativeStatusText || statusText ) + ""; + + // Success/Error + if ( isSuccess ) { + deferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] ); + } else { + deferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] ); + } + + // Status-dependent callbacks + jqXHR.statusCode( statusCode ); + statusCode = undefined; + + if ( fireGlobals ) { + globalEventContext.trigger( isSuccess ? "ajaxSuccess" : "ajaxError", + [ jqXHR, s, isSuccess ? success : error ] ); + } + + // Complete + completeDeferred.fireWith( callbackContext, [ jqXHR, statusText ] ); + + if ( fireGlobals ) { + globalEventContext.trigger( "ajaxComplete", [ jqXHR, s ] ); + + // Handle the global AJAX counter + if ( !( --jQuery.active ) ) { + jQuery.event.trigger( "ajaxStop" ); + } + } + } + + return jqXHR; + }, + + getJSON: function( url, data, callback ) { + return jQuery.get( url, data, callback, "json" ); + }, + + getScript: function( url, callback ) { + return jQuery.get( url, undefined, callback, "script" ); + } +} ); + +jQuery.each( [ "get", "post" ], function( _i, method ) { + jQuery[ method ] = function( url, data, callback, type ) { + + // Shift arguments if data argument was omitted + if ( isFunction( data ) ) { + type = type || callback; + callback = data; + data = undefined; + } + + // The url can be an options object (which then must have .url) + return jQuery.ajax( jQuery.extend( { + url: url, + type: method, + dataType: type, + data: data, + success: callback + }, jQuery.isPlainObject( url ) && url ) ); + }; +} ); + +jQuery.ajaxPrefilter( function( s ) { + var i; + for ( i in s.headers ) { + if ( i.toLowerCase() === "content-type" ) { + s.contentType = s.headers[ i ] || ""; + } + } +} ); + + +jQuery._evalUrl = function( url, options, doc ) { + return jQuery.ajax( { + url: url, + + // Make this explicit, since user can override this through ajaxSetup (#11264) + type: "GET", + dataType: "script", + cache: true, + async: false, + global: false, + + // Only evaluate the response if it is successful (gh-4126) + // dataFilter is not invoked for failure responses, so using it instead + // of the default converter is kludgy but it works. + converters: { + "text script": function() {} + }, + dataFilter: function( response ) { + jQuery.globalEval( response, options, doc ); + } + } ); +}; + + +jQuery.fn.extend( { + wrapAll: function( html ) { + var wrap; + + if ( this[ 0 ] ) { + if ( isFunction( html ) ) { + html = html.call( this[ 0 ] ); + } + + // The elements to wrap the target around + wrap = jQuery( html, this[ 0 ].ownerDocument ).eq( 0 ).clone( true ); + + if ( this[ 0 ].parentNode ) { + wrap.insertBefore( this[ 0 ] ); + } + + wrap.map( function() { + var elem = this; + + while ( elem.firstElementChild ) { + elem = elem.firstElementChild; + } + + return elem; + } ).append( this ); + } + + return this; + }, + + wrapInner: function( html ) { + if ( isFunction( html ) ) { + return this.each( function( i ) { + jQuery( this ).wrapInner( html.call( this, i ) ); + } ); + } + + return this.each( function() { + var self = jQuery( this ), + contents = self.contents(); + + if ( contents.length ) { + contents.wrapAll( html ); + + } else { + self.append( html ); + } + } ); + }, + + wrap: function( html ) { + var htmlIsFunction = isFunction( html ); + + return this.each( function( i ) { + jQuery( this ).wrapAll( htmlIsFunction ? html.call( this, i ) : html ); + } ); + }, + + unwrap: function( selector ) { + this.parent( selector ).not( "body" ).each( function() { + jQuery( this ).replaceWith( this.childNodes ); + } ); + return this; + } +} ); + + +jQuery.expr.pseudos.hidden = function( elem ) { + return !jQuery.expr.pseudos.visible( elem ); +}; +jQuery.expr.pseudos.visible = function( elem ) { + return !!( elem.offsetWidth || elem.offsetHeight || elem.getClientRects().length ); +}; + + + + +jQuery.ajaxSettings.xhr = function() { + try { + return new window.XMLHttpRequest(); + } catch ( e ) {} +}; + +var xhrSuccessStatus = { + + // File protocol always yields status code 0, assume 200 + 0: 200, + + // Support: IE <=9 only + // #1450: sometimes IE returns 1223 when it should be 204 + 1223: 204 + }, + xhrSupported = jQuery.ajaxSettings.xhr(); + +support.cors = !!xhrSupported && ( "withCredentials" in xhrSupported ); +support.ajax = xhrSupported = !!xhrSupported; + +jQuery.ajaxTransport( function( options ) { + var callback, errorCallback; + + // Cross domain only allowed if supported through XMLHttpRequest + if ( support.cors || xhrSupported && !options.crossDomain ) { + return { + send: function( headers, complete ) { + var i, + xhr = options.xhr(); + + xhr.open( + options.type, + options.url, + options.async, + options.username, + options.password + ); + + // Apply custom fields if provided + if ( options.xhrFields ) { + for ( i in options.xhrFields ) { + xhr[ i ] = options.xhrFields[ i ]; + } + } + + // Override mime type if needed + if ( options.mimeType && xhr.overrideMimeType ) { + xhr.overrideMimeType( options.mimeType ); + } + + // X-Requested-With header + // For cross-domain requests, seeing as conditions for a preflight are + // akin to a jigsaw puzzle, we simply never set it to be sure. + // (it can always be set on a per-request basis or even using ajaxSetup) + // For same-domain requests, won't change header if already provided. + if ( !options.crossDomain && !headers[ "X-Requested-With" ] ) { + headers[ "X-Requested-With" ] = "XMLHttpRequest"; + } + + // Set headers + for ( i in headers ) { + xhr.setRequestHeader( i, headers[ i ] ); + } + + // Callback + callback = function( type ) { + return function() { + if ( callback ) { + callback = errorCallback = xhr.onload = + xhr.onerror = xhr.onabort = xhr.ontimeout = + xhr.onreadystatechange = null; + + if ( type === "abort" ) { + xhr.abort(); + } else if ( type === "error" ) { + + // Support: IE <=9 only + // On a manual native abort, IE9 throws + // errors on any property access that is not readyState + if ( typeof xhr.status !== "number" ) { + complete( 0, "error" ); + } else { + complete( + + // File: protocol always yields status 0; see #8605, #14207 + xhr.status, + xhr.statusText + ); + } + } else { + complete( + xhrSuccessStatus[ xhr.status ] || xhr.status, + xhr.statusText, + + // Support: IE <=9 only + // IE9 has no XHR2 but throws on binary (trac-11426) + // For XHR2 non-text, let the caller handle it (gh-2498) + ( xhr.responseType || "text" ) !== "text" || + typeof xhr.responseText !== "string" ? + { binary: xhr.response } : + { text: xhr.responseText }, + xhr.getAllResponseHeaders() + ); + } + } + }; + }; + + // Listen to events + xhr.onload = callback(); + errorCallback = xhr.onerror = xhr.ontimeout = callback( "error" ); + + // Support: IE 9 only + // Use onreadystatechange to replace onabort + // to handle uncaught aborts + if ( xhr.onabort !== undefined ) { + xhr.onabort = errorCallback; + } else { + xhr.onreadystatechange = function() { + + // Check readyState before timeout as it changes + if ( xhr.readyState === 4 ) { + + // Allow onerror to be called first, + // but that will not handle a native abort + // Also, save errorCallback to a variable + // as xhr.onerror cannot be accessed + window.setTimeout( function() { + if ( callback ) { + errorCallback(); + } + } ); + } + }; + } + + // Create the abort callback + callback = callback( "abort" ); + + try { + + // Do send the request (this may raise an exception) + xhr.send( options.hasContent && options.data || null ); + } catch ( e ) { + + // #14683: Only rethrow if this hasn't been notified as an error yet + if ( callback ) { + throw e; + } + } + }, + + abort: function() { + if ( callback ) { + callback(); + } + } + }; + } +} ); + + + + +// Prevent auto-execution of scripts when no explicit dataType was provided (See gh-2432) +jQuery.ajaxPrefilter( function( s ) { + if ( s.crossDomain ) { + s.contents.script = false; + } +} ); + +// Install script dataType +jQuery.ajaxSetup( { + accepts: { + script: "text/javascript, application/javascript, " + + "application/ecmascript, application/x-ecmascript" + }, + contents: { + script: /\b(?:java|ecma)script\b/ + }, + converters: { + "text script": function( text ) { + jQuery.globalEval( text ); + return text; + } + } +} ); + +// Handle cache's special case and crossDomain +jQuery.ajaxPrefilter( "script", function( s ) { + if ( s.cache === undefined ) { + s.cache = false; + } + if ( s.crossDomain ) { + s.type = "GET"; + } +} ); + +// Bind script tag hack transport +jQuery.ajaxTransport( "script", function( s ) { + + // This transport only deals with cross domain or forced-by-attrs requests + if ( s.crossDomain || s.scriptAttrs ) { + var script, callback; + return { + send: function( _, complete ) { + script = jQuery( " + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra - Exceptions and Enums

+
+
+cassandra.__version_info__
+

The version of the driver in a tuple format

+
+ +
+
+cassandra.__version__
+

The version of the driver in a string format

+
+ +
+
+class cassandra.ConsistencyLevel
+

Spcifies how many replicas must respond for an operation to be considered +a success. By default, ONE is used for all operations.

+
+
+ANY = 0
+

Only requires that one replica receives the write or the coordinator +stores a hint to replay later. Valid only for writes.

+
+ +
+
+ONE = 1
+

Only one replica needs to respond to consider the operation a success

+
+ +
+
+TWO = 2
+

Two replicas must respond to consider the operation a success

+
+ +
+
+THREE = 3
+

Three replicas must respond to consider the operation a success

+
+ +
+
+QUORUM = 4
+

ceil(RF/2) + 1 replicas must respond to consider the operation a success

+
+ +
+
+ALL = 5
+

All replicas must respond to consider the operation a success

+
+ +
+
+LOCAL_QUORUM = 6
+

Requires a quorum of replicas in the local datacenter

+
+ +
+
+EACH_QUORUM = 7
+

Requires a quorum of replicas in each datacenter

+
+ +
+
+SERIAL = 8
+

For conditional inserts/updates that utilize Cassandra’s lightweight +transactions, this requires consensus among all replicas for the +modified data.

+
+ +
+
+LOCAL_SERIAL = 9
+

Like SERIAL, but only requires consensus +among replicas in the local datacenter.

+
+ +
+
+LOCAL_ONE = 10
+

Sends a request only to replicas in the local datacenter and waits for +one response.

+
+ +
+ +
+
+class cassandra.ProtocolVersion
+

Defines native protocol versions supported by this driver.

+
+
+V1 = 1
+

v1, supported in Cassandra 1.2–>2.2

+
+ +
+
+V2 = 2
+

v2, supported in Cassandra 2.0–>2.2; +added support for lightweight transactions, batch operations, and automatic query paging.

+
+ +
+
+V3 = 3
+

v3, supported in Cassandra 2.1–>3.x+; +added support for protocol-level client-side timestamps (see Session.use_client_timestamp), +serial consistency levels for BatchStatement, and an improved connection pool.

+
+ +
+
+V4 = 4
+

v4, supported in Cassandra 2.2–>3.x+; +added a number of new types, server warnings, new failure messages, and custom payloads. Details in the +project docs

+
+ +
+
+V5 = 5
+

v5, in beta from 3.x+. Finalised in 4.0-beta5

+
+ +
+
+V6 = 6
+

v6, in beta from 4.0-beta5

+
+ +
+
+DSE_V1 = 65
+

DSE private protocol v1, supported in DSE 5.1+

+
+ +
+
+DSE_V2 = 66
+

DSE private protocol v2, supported in DSE 6.0+

+
+ +
+
+SUPPORTED_VERSIONS = (66, 65, 6, 5, 4, 3, 2, 1)
+

A tuple of all supported protocol versions

+
+ +
+
+BETA_VERSIONS = (6,)
+

A tuple of all beta protocol versions

+
+ +
+
+MIN_SUPPORTED = 1
+

Minimum protocol version supported by this driver.

+
+ +
+
+MAX_SUPPORTED = 66
+

Maximum protocol version supported by this driver.

+
+ +
+
+classmethod get_lower_supported(previous_version)
+

Return the lower supported protocol version. Beta versions are omitted.

+
+ +
+ +
+
+class cassandra.UserFunctionDescriptor(name, argument_types)
+

Describes a User function by name and argument signature

+
+
+name = None
+

name of the function

+
+ +
+
+argument_types = None
+

Ordered list of CQL argument type names comprising the type signature

+
+ +
+
+property signature
+

function signature string in the form ‘name([type0[,type1[…]]])’

+

can be used to uniquely identify overloaded function names within a keyspace

+
+ +
+ +
+
+class cassandra.UserAggregateDescriptor(name, argument_types)
+

Describes a User aggregate function by name and argument signature

+
+
+name = None
+

name of the aggregate

+
+ +
+
+argument_types = None
+

Ordered list of CQL argument type names comprising the type signature

+
+ +
+
+property signature
+

function signature string in the form ‘name([type0[,type1[…]]])’

+

can be used to uniquely identify overloaded function names within a keyspace

+
+ +
+ +
+
+exception cassandra.DriverException
+

Base for all exceptions explicitly raised by the driver.

+
+ +
+
+exception cassandra.RequestExecutionException
+

Base for request execution exceptions returned from the server.

+
+ +
+
+exception cassandra.Unavailable
+

There were not enough live replicas to satisfy the requested consistency +level, so the coordinator node immediately failed the request without +forwarding it to any replicas.

+
+
+consistency = None
+

The requested ConsistencyLevel

+
+ +
+
+required_replicas = None
+

The number of replicas that needed to be live to complete the operation

+
+ +
+
+alive_replicas = None
+

The number of replicas that were actually alive

+
+ +
+ +
+
+exception cassandra.Timeout
+

Replicas failed to respond to the coordinator node before timing out.

+
+
+consistency = None
+

The requested ConsistencyLevel

+
+ +
+
+required_responses = None
+

The number of required replica responses

+
+ +
+
+received_responses = None
+

The number of replicas that responded before the coordinator timed out +the operation

+
+ +
+ +
+
+exception cassandra.ReadTimeout
+

A subclass of Timeout for read operations.

+

This indicates that the replicas failed to respond to the coordinator +node before the configured timeout. This timeout is configured in +cassandra.yaml with the read_request_timeout_in_ms +and range_request_timeout_in_ms options.

+
+
+data_retrieved = None
+

A boolean indicating whether the requested data was retrieved +by the coordinator from any replicas before it timed out the +operation

+
+ +
+ +
+
+exception cassandra.WriteTimeout
+

A subclass of Timeout for write operations.

+

This indicates that the replicas failed to respond to the coordinator +node before the configured timeout. This timeout is configured in +cassandra.yaml with the write_request_timeout_in_ms +option.

+
+
+write_type = None
+

The type of write operation, enum on WriteType

+
+ +
+ +
+
+exception cassandra.CoordinationFailure
+

Replicas sent a failure to the coordinator.

+
+
+consistency = None
+

The requested ConsistencyLevel

+
+ +
+
+required_responses = None
+

The number of required replica responses

+
+ +
+
+received_responses = None
+

The number of replicas that responded before the coordinator timed out +the operation

+
+ +
+
+failures = None
+

The number of replicas that sent a failure message

+
+ +
+
+error_code_map = None
+

A map of inet addresses to error codes representing replicas that sent +a failure message. Only set when protocol_version is 5 or higher.

+
+ +
+ +
+
+exception cassandra.ReadFailure
+

A subclass of CoordinationFailure for read operations.

+

This indicates that the replicas sent a failure message to the coordinator.

+
+
+data_retrieved = None
+

A boolean indicating whether the requested data was retrieved +by the coordinator from any replicas before it timed out the +operation

+
+ +
+ +
+
+exception cassandra.WriteFailure
+

A subclass of CoordinationFailure for write operations.

+

This indicates that the replicas sent a failure message to the coordinator.

+
+
+write_type = None
+

The type of write operation, enum on WriteType

+
+ +
+ +
+
+exception cassandra.FunctionFailure
+

User Defined Function failed during execution

+
+
+keyspace = None
+

Keyspace of the function

+
+ +
+
+function = None
+

Name of the function

+
+ +
+
+arg_types = None
+

List of argument type names of the function

+
+ +
+ +
+
+exception cassandra.RequestValidationException
+

Server request validation failed

+
+ +
+
+exception cassandra.ConfigurationException
+

Server indicated request errro due to current configuration

+
+ +
+
+exception cassandra.AlreadyExists
+

An attempt was made to create a keyspace or table that already exists.

+
+
+keyspace = None
+

The name of the keyspace that already exists, or, if an attempt was +made to create a new table, the keyspace that the table is in.

+
+ +
+
+table = None
+

The name of the table that already exists, or, if an attempt was +make to create a keyspace, None.

+
+ +
+ +
+
+exception cassandra.InvalidRequest
+

A query was made that was invalid for some reason, such as trying to set +the keyspace for a connection to a nonexistent keyspace.

+
+ +
+
+exception cassandra.Unauthorized
+

The current user is not authorized to perform the requested operation.

+
+ +
+
+exception cassandra.AuthenticationFailed
+

Failed to authenticate.

+
+ +
+
+exception cassandra.OperationTimedOut
+

The operation took longer than the specified (client-side) timeout +to complete. This is not an error generated by Cassandra, only +the driver.

+
+
+errors = None
+

A dict of errors keyed by the Host against which they occurred.

+
+ +
+
+last_host = None
+

The last Host this operation was attempted against.

+
+ +
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.25.4-scylla/api/cassandra/auth.html b/3.25.4-scylla/api/cassandra/auth.html new file mode 100644 index 0000000000..27d3b053f8 --- /dev/null +++ b/3.25.4-scylla/api/cassandra/auth.html @@ -0,0 +1,806 @@ + + + + + + + + + + + + + cassandra.auth - Authentication | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.auth - Authentication

+
+
+class cassandra.auth.AuthProvider
+

An abstract class that defines the interface that will be used for +creating Authenticator instances when opening new +connections to Cassandra.

+
+

New in version 2.0.0.

+
+
+
+new_authenticator(host)
+

Implementations of this class should return a new instance +of Authenticator or one of its subclasses.

+
+ +
+ +
+
+class cassandra.auth.Authenticator
+

An abstract class that handles SASL authentication with Cassandra servers.

+

Each time a new connection is created and the server requires authentication, +a new instance of this class will be created by the corresponding +AuthProvider to handler that authentication. The lifecycle of the +new Authenticator will the be:

+

1) The initial_response() method will be called. The return +value will be sent to the server to initiate the handshake.

+

2) The server will respond to each client response by either issuing a +challenge or indicating that the authentication is complete (successful or not). +If a new challenge is issued, evaluate_challenge() +will be called to produce a response that will be sent to the +server. This challenge/response negotiation will continue until the server +responds that authentication is successful (or an AuthenticationFailed +is raised).

+

3) When the server indicates that authentication is successful, +on_authentication_success() will be called a token string that +that the server may optionally have sent.

+

The exact nature of the negotiation between the client and server is specific +to the authentication mechanism configured server-side.

+
+

New in version 2.0.0.

+
+
+
+server_authenticator_class = None
+

Set during the connection AUTHENTICATE phase

+
+ +
+
+initial_response()
+

Returns an message to send to the server to initiate the SASL handshake. +None may be returned to send an empty message.

+
+ +
+
+evaluate_challenge(challenge)
+

Called when the server sends a challenge message. Generally, this method +should return None when authentication is complete from a +client perspective. Otherwise, a string should be returned.

+
+ +
+
+on_authentication_success(token)
+

Called when the server indicates that authentication was successful. +Depending on the authentication mechanism, token may be None +or a string.

+
+ +
+ +
+
+class cassandra.auth.PlainTextAuthProvider(username, password)
+

An AuthProvider that works with Cassandra’s PasswordAuthenticator.

+

Example usage:

+
from cassandra.cluster import Cluster
+from cassandra.auth import PlainTextAuthProvider
+
+auth_provider = PlainTextAuthProvider(
+        username='cassandra', password='cassandra')
+cluster = Cluster(auth_provider=auth_provider)
+
+
+
+

New in version 2.0.0.

+
+
+
+new_authenticator(host)
+

Implementations of this class should return a new instance +of Authenticator or one of its subclasses.

+
+ +
+ +
+
+class cassandra.auth.PlainTextAuthenticator(username, password)
+
+
+evaluate_challenge(challenge)
+

Called when the server sends a challenge message. Generally, this method +should return None when authentication is complete from a +client perspective. Otherwise, a string should be returned.

+
+ +
+ +
+
+class cassandra.auth.SaslAuthProvider(**sasl_kwargs)
+

An AuthProvider supporting general SASL auth mechanisms

+

Suitable for GSSAPI or other SASL mechanisms

+

Example usage:

+
from cassandra.cluster import Cluster
+from cassandra.auth import SaslAuthProvider
+
+sasl_kwargs = {'service': 'something',
+               'mechanism': 'GSSAPI',
+               'qops': 'auth'.split(',')}
+auth_provider = SaslAuthProvider(**sasl_kwargs)
+cluster = Cluster(auth_provider=auth_provider)
+
+
+
+

New in version 2.1.4.

+
+
+
+new_authenticator(host)
+

Implementations of this class should return a new instance +of Authenticator or one of its subclasses.

+
+ +
+ +
+
+class cassandra.auth.SaslAuthenticator(host, service, mechanism='GSSAPI', **sasl_kwargs)
+

A pass-through Authenticator using the third party package +‘pure-sasl’ for authentication

+
+

New in version 2.1.4.

+
+
+
+initial_response()
+

Returns an message to send to the server to initiate the SASL handshake. +None may be returned to send an empty message.

+
+ +
+
+evaluate_challenge(challenge)
+

Called when the server sends a challenge message. Generally, this method +should return None when authentication is complete from a +client perspective. Otherwise, a string should be returned.

+
+ +
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.25.4-scylla/api/cassandra/cluster.html b/3.25.4-scylla/api/cassandra/cluster.html new file mode 100644 index 0000000000..0d46cfbf80 --- /dev/null +++ b/3.25.4-scylla/api/cassandra/cluster.html @@ -0,0 +1,1778 @@ + + + + + + + + + + + + + cassandra.cluster - Clusters and Sessions | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.cluster - Clusters and Sessions

+
+
+class cassandra.cluster.Cluster([contact_points=('127.0.0.1',)][, port=9042][, executor_threads=2], **attr_kwargs)
+

The main class to use when interacting with a Cassandra cluster. +Typically, one instance of this class will be created for each +separate Cassandra cluster that your application interacts with.

+

Example usage:

+
>>> from cassandra.cluster import Cluster
+>>> cluster = Cluster(['192.168.1.1', '192.168.1.2'])
+>>> session = cluster.connect()
+>>> session.execute("CREATE KEYSPACE ...")
+>>> ...
+>>> cluster.shutdown()
+
+
+

Cluster and Session also provide context management functions +which implicitly handle shutdown when leaving scope.

+

executor_threads defines the number of threads in a pool for handling asynchronous tasks such as +extablishing connection pools or refreshing metadata.

+

Any of the mutable Cluster attributes may be set as keyword arguments to the constructor.

+
+
+contact_points = ['127.0.0.1']
+
+ +
+
+port = 9042
+
+ +
+
+cql_version = None
+
+ +
+
+protocol_version = 66
+
+ +
+
+compression = True
+
+ +
+
+auth_provider
+

When protocol_version is 2 or higher, this should +be an instance of a subclass of AuthProvider, +such as PlainTextAuthProvider.

+

When protocol_version is 1, this should be +a function that accepts one argument, the IP address of a node, +and returns a dict of credentials for that node.

+

When not using authentication, this should be left as None.

+
+ +
+
+load_balancing_policy
+

An instance of policies.LoadBalancingPolicy or +one of its subclasses.

+
+

Changed in version 2.6.0.

+
+

Defaults to TokenAwarePolicy (DCAwareRoundRobinPolicy). +when using CPython (where the murmur3 extension is available). DCAwareRoundRobinPolicy +otherwise. Default local DC will be chosen from contact points.

+

Please see DCAwareRoundRobinPolicy for a discussion on default behavior with respect to +DC locality and remote nodes.

+
+ +
+
+reconnection_policy = <cassandra.policies.ExponentialReconnectionPolicy object>
+
+ +
+
+default_retry_policy = <cassandra.policies.RetryPolicy object>
+

A default policies.RetryPolicy instance to use for all +Statement objects which do not have a retry_policy +explicitly set.

+
+ +
+
+conviction_policy_factory = <class 'cassandra.policies.SimpleConvictionPolicy'>
+
+ +
+
+address_translator = <cassandra.policies.IdentityTranslator object>
+
+ +
+
+metrics_enabled = False
+
+ +
+
+metrics = None
+
+ +
+
+ssl_context = None
+
+ +
+
+ssl_options = None
+
+ +
+
+sockopts = None
+
+ +
+
+max_schema_agreement_wait = 10
+
+ +
+
+metadata = None
+
+ +
+
+connection_class = <class 'cassandra.io.libevreactor.LibevConnection'>
+
+ +
+
+control_connection_timeout = 2.0
+
+ +
+
+idle_heartbeat_interval = 30
+
+ +
+
+idle_heartbeat_timeout = 30
+
+ +
+
+schema_event_refresh_window = 2
+
+ +
+
+topology_event_refresh_window = 10
+
+ +
+
+status_event_refresh_window = 2
+
+ +
+
+prepare_on_all_hosts = True
+
+ +
+
+reprepare_on_up = True
+
+ +
+
+connect_timeout = 5
+
+ +
+
+schema_metadata_enabled = True
+

Flag indicating whether internal schema metadata is updated.

+

When disabled, the driver does not populate Cluster.metadata.keyspaces on connect, or on schema change events. This +can be used to speed initial connection, and reduce load on client and server during operation. Turning this off +gives away token aware request routing, and programmatic inspection of the metadata model.

+
+ +
+
+token_metadata_enabled = True
+

Flag indicating whether internal token metadata is updated.

+

When disabled, the driver does not query node token information on connect, or on topology change events. This +can be used to speed initial connection, and reduce load on client and server during operation. It is most useful +in large clusters using vnodes, where the token map can be expensive to compute. Turning this off +gives away token aware request routing, and programmatic inspection of the token ring.

+
+ +
+
+timestamp_generator = None
+
+ +
+
+endpoint_factory = None
+
+ +
+
+cloud = None
+
+ +
+
+connect(keyspace=None, wait_for_all_pools=False)
+

Creates and returns a new Session object.

+

If keyspace is specified, that keyspace will be the default keyspace for +operations on the Session.

+

wait_for_all_pools specifies whether this call should wait for all connection pools to be +established or attempted. Default is False, which means it will return when the first +successful connection is established. Remaining pools are added asynchronously.

+
+ +
+
+shutdown()
+

Closes all sessions and connection associated with this Cluster. +To ensure all connections are properly closed, you should always +call shutdown() on a Cluster instance when you are done with it.

+

Once shutdown, a Cluster should not be used for any purpose.

+
+ +
+
+register_user_type(keyspace, user_type, klass)
+

Registers a class to use to represent a particular user-defined type. +Query parameters for this user-defined type will be assumed to be +instances of klass. Result sets for this user-defined type will +be instances of klass. If no class is registered for a user-defined +type, a namedtuple will be used for result sets, and non-prepared +statements may not encode parameters for this type correctly.

+

keyspace is the name of the keyspace that the UDT is defined in.

+

user_type is the string name of the UDT to register the mapping +for.

+

klass should be a class with attributes whose names match the +fields of the user-defined type. The constructor must accepts kwargs +for each of the fields in the UDT.

+

This method should only be called after the type has been created +within Cassandra.

+

Example:

+
cluster = Cluster(protocol_version=3)
+session = cluster.connect()
+session.set_keyspace('mykeyspace')
+session.execute("CREATE TYPE address (street text, zipcode int)")
+session.execute("CREATE TABLE users (id int PRIMARY KEY, location address)")
+
+# create a class to map to the "address" UDT
+class Address(object):
+
+    def __init__(self, street, zipcode):
+        self.street = street
+        self.zipcode = zipcode
+
+cluster.register_user_type('mykeyspace', 'address', Address)
+
+# insert a row using an instance of Address
+session.execute("INSERT INTO users (id, location) VALUES (%s, %s)",
+                (0, Address("123 Main St.", 78723)))
+
+# results will include Address instances
+results = session.execute("SELECT * FROM users")
+row = results[0]
+print row.id, row.location.street, row.location.zipcode
+
+
+
+ +
+
+register_listener(listener)
+

Adds a cassandra.policies.HostStateListener subclass instance to +the list of listeners to be notified when a host is added, removed, +marked up, or marked down.

+
+ +
+
+unregister_listener(listener)
+

Removes a registered listener.

+
+ +
+
+add_execution_profile(name, profile, pool_wait_timeout=5)
+

Adds an ExecutionProfile to the cluster. This makes it available for use by name in Session.execute() +and Session.execute_async(). This method will raise if the profile already exists.

+

Normally profiles will be injected at cluster initialization via Cluster(execution_profiles). This method +provides a way of adding them dynamically.

+

Adding a new profile updates the connection pools according to the specified load_balancing_policy. By default, +this method will wait up to five seconds for the pool creation to complete, so the profile can be used immediately +upon return. This behavior can be controlled using pool_wait_timeout (see +concurrent.futures.wait +for timeout semantics).

+
+ +
+
+set_max_requests_per_connection(host_distance, max_requests)
+

Sets a threshold for concurrent requests per connection, above which new +connections will be created to a host (up to max connections; +see set_max_connections_per_host()).

+

Pertains to connection pool management in protocol versions {1,2}.

+
+ +
+
+get_max_requests_per_connection(host_distance)
+
+ +
+
+set_min_requests_per_connection(host_distance, min_requests)
+

Sets a threshold for concurrent requests per connection, below which +connections will be considered for disposal (down to core connections; +see set_core_connections_per_host()).

+

Pertains to connection pool management in protocol versions {1,2}.

+
+ +
+
+get_min_requests_per_connection(host_distance)
+
+ +
+
+get_core_connections_per_host(host_distance)
+

Gets the minimum number of connections per Session that will be opened +for each host with HostDistance equal to host_distance. +The default is 2 for LOCAL and 1 for +REMOTE.

+

This property is ignored if protocol_version is +3 or higher.

+
+ +
+
+set_core_connections_per_host(host_distance, core_connections)
+

Sets the minimum number of connections per Session that will be opened +for each host with HostDistance equal to host_distance. +The default is 2 for LOCAL and 1 for +REMOTE.

+

Protocol version 1 and 2 are limited in the number of concurrent +requests they can send per connection. The driver implements connection +pooling to support higher levels of concurrency.

+

If protocol_version is set to 3 or higher, this +is not supported (there is always one connection per host, unless +the host is remote and connect_to_remote_hosts is False) +and using this will result in an UnsupportedOperation.

+
+ +
+
+get_max_connections_per_host(host_distance)
+

Gets the maximum number of connections per Session that will be opened +for each host with HostDistance equal to host_distance. +The default is 8 for LOCAL and 2 for +REMOTE.

+

This property is ignored if protocol_version is +3 or higher.

+
+ +
+
+set_max_connections_per_host(host_distance, max_connections)
+

Sets the maximum number of connections per Session that will be opened +for each host with HostDistance equal to host_distance. +The default is 2 for LOCAL and 1 for +REMOTE.

+

If protocol_version is set to 3 or higher, this +is not supported (there is always one connection per host, unless +the host is remote and connect_to_remote_hosts is False) +and using this will result in an UnsupportedOperation.

+
+ +
+
+get_control_connection_host()
+

Returns the control connection host metadata.

+
+ +
+
+refresh_schema_metadata(max_schema_agreement_wait=None)
+

Synchronously refresh all schema metadata.

+

By default, the timeout for this operation is governed by max_schema_agreement_wait +and control_connection_timeout.

+

Passing max_schema_agreement_wait here overrides max_schema_agreement_wait.

+

Setting max_schema_agreement_wait <= 0 will bypass schema agreement and refresh schema immediately.

+

An Exception is raised if schema refresh fails for any reason.

+
+ +
+
+refresh_keyspace_metadata(keyspace, max_schema_agreement_wait=None)
+

Synchronously refresh keyspace metadata. This applies to keyspace-level information such as replication +and durability settings. It does not refresh tables, types, etc. contained in the keyspace.

+

See refresh_schema_metadata() for description of max_schema_agreement_wait behavior

+
+ +
+
+refresh_table_metadata(keyspace, table, max_schema_agreement_wait=None)
+

Synchronously refresh table metadata. This applies to a table, and any triggers or indexes attached +to the table.

+

See refresh_schema_metadata() for description of max_schema_agreement_wait behavior

+
+ +
+
+refresh_user_type_metadata(keyspace, user_type, max_schema_agreement_wait=None)
+

Synchronously refresh user defined type metadata.

+

See refresh_schema_metadata() for description of max_schema_agreement_wait behavior

+
+ +
+
+refresh_user_function_metadata(keyspace, function, max_schema_agreement_wait=None)
+

Synchronously refresh user defined function metadata.

+

function is a cassandra.UserFunctionDescriptor.

+

See refresh_schema_metadata() for description of max_schema_agreement_wait behavior

+
+ +
+
+refresh_user_aggregate_metadata(keyspace, aggregate, max_schema_agreement_wait=None)
+

Synchronously refresh user defined aggregate metadata.

+

aggregate is a cassandra.UserAggregateDescriptor.

+

See refresh_schema_metadata() for description of max_schema_agreement_wait behavior

+
+ +
+
+refresh_nodes(force_token_rebuild=False)
+

Synchronously refresh the node list and token metadata

+

force_token_rebuild can be used to rebuild the token map metadata, even if no new nodes are discovered.

+

An Exception is raised if node refresh fails for any reason.

+
+ +
+
+set_meta_refresh_enabled(enabled)
+

Deprecated: set schema_metadata_enabled token_metadata_enabled instead

+

Sets a flag to enable (True) or disable (False) all metadata refresh queries. +This applies to both schema and node topology.

+

Disabling this is useful to minimize refreshes during multiple changes.

+

Meta refresh must be enabled for the driver to become aware of any cluster +topology changes or schema updates.

+
+ +
+ +
+
+class cassandra.cluster.ExecutionProfile(load_balancing_policy=<object object>, retry_policy=None, consistency_level=ConsistencyLevel.LOCAL_ONE, serial_consistency_level=None, request_timeout=10.0, row_factory=<function named_tuple_factory>, speculative_execution_policy=None)
+
+
+consistency_level = LOCAL_ONE
+
+ +
+
+static row_factory(colnames, rows)
+

Returns each row as a namedtuple. +This is the default row factory.

+

Example:

+
>>> from cassandra.query import named_tuple_factory
+>>> session = cluster.connect('mykeyspace')
+>>> session.row_factory = named_tuple_factory
+>>> rows = session.execute("SELECT name, age FROM users LIMIT 1")
+>>> user = rows[0]
+
+>>> # you can access field by their name:
+>>> print "name: %s, age: %d" % (user.name, user.age)
+name: Bob, age: 42
+
+>>> # or you can access fields by their position (like a tuple)
+>>> name, age = user
+>>> print "name: %s, age: %d" % (name, age)
+name: Bob, age: 42
+>>> name = user[0]
+>>> age = user[1]
+>>> print "name: %s, age: %d" % (name, age)
+name: Bob, age: 42
+
+
+
+

Changed in version 2.0.0: moved from cassandra.decoder to cassandra.query

+
+
+ +
+ +
+
+class cassandra.cluster.GraphExecutionProfile(load_balancing_policy=_NOT_SET, retry_policy=None, consistency_level=ConsistencyLevel.LOCAL_ONE, serial_consistency_level=None, request_timeout=30.0, row_factory=None, graph_options=None, continuous_paging_options=_NOT_SET)
+

Default execution profile for graph execution.

+

See ExecutionProfile for base attributes. Note that if not explicitly set, +the row_factory and graph_options.graph_protocol are resolved during the query execution. +These options will resolve to graph_graphson3_row_factory and GraphProtocol.GRAPHSON_3_0 +for the core graph engine (DSE 6.8+), otherwise graph_object_row_factory and GraphProtocol.GRAPHSON_1_0

+

In addition to default parameters shown in the signature, this profile also defaults retry_policy to +cassandra.policies.NeverRetryPolicy.

+
+ +
+
+class cassandra.cluster.GraphAnalyticsExecutionProfile(load_balancing_policy=None, retry_policy=None, consistency_level=ConsistencyLevel.LOCAL_ONE, serial_consistency_level=None, request_timeout=3600.0 * 24.0 * 7.0, row_factory=None, graph_options=None)
+

Execution profile with timeout and load balancing appropriate for graph analytics queries.

+

See also GraphExecutionPolicy.

+

In addition to default parameters shown in the signature, this profile also defaults retry_policy to +cassandra.policies.NeverRetryPolicy, and load_balancing_policy to one that targets the current Spark +master.

+

Note: The graph_options.graph_source is set automatically to b’a’ (analytics) +when using GraphAnalyticsExecutionProfile. This is mandatory to target analytics nodes.

+
+ +
+
+cassandra.cluster.EXEC_PROFILE_DEFAULT
+

The most base type

+
+ +
+
+cassandra.cluster.EXEC_PROFILE_GRAPH_DEFAULT
+

The most base type

+
+ +
+
+cassandra.cluster.EXEC_PROFILE_GRAPH_SYSTEM_DEFAULT
+

The most base type

+
+ +
+
+cassandra.cluster.EXEC_PROFILE_GRAPH_ANALYTICS_DEFAULT
+

The most base type

+
+ +
+
+class cassandra.cluster.Session
+

A collection of connection pools for each host in the cluster. +Instances of this class should not be created directly, only +using Cluster.connect().

+

Queries and statements can be executed through Session instances +using the execute() and execute_async() +methods.

+

Example usage:

+
>>> session = cluster.connect()
+>>> session.set_keyspace("mykeyspace")
+>>> session.execute("SELECT * FROM mycf")
+
+
+
+
+default_timeout = 10.0
+

A default timeout, measured in seconds, for queries executed through +execute() or execute_async(). This default may be +overridden with the timeout parameter for either of those methods.

+

Setting this to None will cause no timeouts to be set by default.

+

Please see ResponseFuture.result() for details on the scope and +effect of this timeout.

+
+

New in version 2.0.0.

+
+
+ +
+
+default_consistency_level = LOCAL_ONE
+

Deprecated: use execution profiles instead +The default ConsistencyLevel for operations executed through +this session. This default may be overridden by setting the +consistency_level on individual statements.

+
+

New in version 1.2.0.

+
+
+

Changed in version 3.0.0: default changed from ONE to LOCAL_ONE

+
+
+ +
+
+default_serial_consistency_level = None
+

The default ConsistencyLevel for serial phase of conditional updates executed through +this session. This default may be overridden by setting the +serial_consistency_level on individual statements.

+

Only valid for protocol_version >= 2.

+
+ +
+
+row_factory = <function named_tuple_factory>
+

The format to return row results in. By default, each +returned row will be a named tuple. You can alternatively +use any of the following:

+ +
+ +
+
+default_fetch_size = 5000
+
+ +
+
+use_client_timestamp = True
+
+ +
+
+timestamp_generator = None
+
+ +
+
+encoder = None
+
+ +
+
+client_protocol_handler = <class 'cassandra.protocol.cython_protocol_handler.<locals>.CythonProtocolHandler'>
+
+ +
+
+execute(statement[, parameters][, timeout][, trace][, custom_payload][, paging_state][, host][, execute_as])
+

Execute the given query and synchronously wait for the response.

+

If an error is encountered while executing the query, an Exception +will be raised.

+

query may be a query string or an instance of cassandra.query.Statement.

+

parameters may be a sequence or dict of parameters to bind. If a +sequence is used, %s should be used the placeholder for each +argument. If a dict is used, %(name)s style placeholders must +be used.

+

timeout should specify a floating-point timeout (in seconds) after +which an OperationTimedOut exception will be raised if the query +has not completed. If not set, the timeout defaults to the request_timeout of the selected execution_profile. +If set to None, there is no timeout. Please see ResponseFuture.result() for details on +the scope and effect of this timeout.

+

If trace is set to True, the query will be sent with tracing enabled. +The trace details can be obtained using the returned ResultSet object.

+

custom_payload is a Custom Payloads dict to be passed to the server. +If query is a Statement with its own custom_payload. The message payload +will be a union of the two, with the values specified here taking precedence.

+

execution_profile is the execution profile to use for this request. It can be a key to a profile configured +via Cluster.add_execution_profile() or an instance (from Session.execution_profile_clone_update(), +for example

+

paging_state is an optional paging state, reused from a previous ResultSet.

+

host is the cassandra.pool.Host that should handle the query. If the host specified is down or +not yet connected, the query will fail with NoHostAvailable. Using this is +discouraged except in a few cases, e.g., querying node-local tables and applying schema changes.

+

execute_as the user that will be used on the server to execute the request. This is only available +on a DSE cluster.

+
+ +
+
+execute_async(statement[, parameters][, trace][, custom_payload][, paging_state][, host][, execute_as])
+

Execute the given query and return a ResponseFuture object +which callbacks may be attached to for asynchronous response +delivery. You may also call result() +on the ResponseFuture to synchronously block for results at +any time.

+

See Session.execute() for parameter definitions.

+

Example usage:

+
>>> session = cluster.connect()
+>>> future = session.execute_async("SELECT * FROM mycf")
+
+>>> def log_results(results):
+...     for row in results:
+...         log.info("Results: %s", row)
+
+>>> def log_error(exc):
+>>>     log.error("Operation failed: %s", exc)
+
+>>> future.add_callbacks(log_results, log_error)
+
+
+

Async execution with blocking wait for results:

+
>>> future = session.execute_async("SELECT * FROM mycf")
+>>> # do other stuff...
+
+>>> try:
+...     results = future.result()
+... except Exception:
+...     log.exception("Operation failed:")
+
+
+
+ +
+
+execute_graph(statement[, parameters][, trace][, execution_profile=EXEC_PROFILE_GRAPH_DEFAULT][, execute_as])
+

Executes a Gremlin query string or GraphStatement synchronously, +and returns a ResultSet from this execution.

+

parameters is dict of named parameters to bind. The values must be +JSON-serializable.

+

execution_profile: Selects an execution profile for the request.

+

execute_as the user that will be used on the server to execute the request.

+
+ +
+
+execute_graph_async(statement[, parameters][, trace][, execution_profile=EXEC_PROFILE_GRAPH_DEFAULT][, execute_as])
+

Execute the graph query and return a ResponseFuture +object which callbacks may be attached to for asynchronous response delivery. You may also call ResponseFuture.result() to synchronously block for +results at any time.

+
+ +
+
+prepare(statement)
+

Prepares a query string, returning a PreparedStatement +instance which can be used as follows:

+
>>> session = cluster.connect("mykeyspace")
+>>> query = "INSERT INTO users (id, name, age) VALUES (?, ?, ?)"
+>>> prepared = session.prepare(query)
+>>> session.execute(prepared, (user.id, user.name, user.age))
+
+
+

Or you may bind values to the prepared statement ahead of time:

+
>>> prepared = session.prepare(query)
+>>> bound_stmt = prepared.bind((user.id, user.name, user.age))
+>>> session.execute(bound_stmt)
+
+
+

Of course, prepared statements may (and should) be reused:

+
>>> prepared = session.prepare(query)
+>>> for user in users:
+...     bound = prepared.bind((user.id, user.name, user.age))
+...     session.execute(bound)
+
+
+

Alternatively, if protocol_version is 5 or higher +(requires Cassandra 4.0+), the keyspace can be specified as a +parameter. This will allow you to avoid specifying the keyspace in the +query without specifying a keyspace in connect(). It +even will let you prepare and use statements against a keyspace other +than the one originally specified on connection:

+
>>> analyticskeyspace_prepared = session.prepare(
+...     "INSERT INTO user_activity id, last_activity VALUES (?, ?)",
+...     keyspace="analyticskeyspace")  # note the different keyspace
+
+
+

Important: PreparedStatements should be prepared only once. +Preparing the same query more than once will likely affect performance.

+

custom_payload is a key value map to be passed along with the prepare +message. See Custom Payloads.

+
+ +
+
+shutdown()
+

Close all connections. Session instances should not be used +for any purpose after being shutdown.

+
+ +
+
+set_keyspace(keyspace)
+

Set the default keyspace for all queries made through this Session. +This operation blocks until complete.

+
+ +
+
+get_execution_profile(name)
+

Returns the execution profile associated with the provided name.

+
+
Parameters
+

name – The name (or key) of the execution profile.

+
+
+
+ +
+
+execution_profile_clone_update(ep, **kwargs)
+

Returns a clone of the ep profile. kwargs can be specified to update attributes +of the returned profile.

+

This is a shallow clone, so any objects referenced by the profile are shared. This means Load Balancing Policy +is maintained by inclusion in the active profiles. It also means updating any other rich objects will be seen +by the active profile. In cases where this is not desirable, be sure to replace the instance instead of manipulating +the shared object.

+
+ +
+
+add_request_init_listener(fn, *args, **kwargs)
+

Adds a callback with arguments to be called when any request is created.

+

It will be invoked as fn(response_future, *args, **kwargs) after each client request is created, +and before the request is sent. This can be used to create extensions by adding result callbacks to the +response future.

+

response_future is the ResponseFuture for the request.

+

Note that the init callback is done on the client thread creating the request, so you may need to consider +synchronization if you have multiple threads. Any callbacks added to the response future will be executed +on the event loop thread, so the normal advice about minimizing cycles and avoiding blocking apply (see Note in +ResponseFuture.add_callbacks().

+

See this example in the +source tree for an example.

+
+ +
+
+remove_request_init_listener(fn, *args, **kwargs)
+

Removes a callback and arguments from the list.

+

See Session.add_request_init_listener().

+
+ +
+ +
+
+class cassandra.cluster.ResponseFuture
+

An asynchronous response delivery mechanism that is returned from calls +to Session.execute_async().

+
+
There are two ways for results to be delivered:
+
+
+
+
+query = None
+
+ +
+
+result()
+

Return the final result or raise an Exception if errors were +encountered. If the final result or error has not been set +yet, this method will block until it is set, or the timeout +set for the request expires.

+

Timeout is specified in the Session request execution functions. +If the timeout is exceeded, an cassandra.OperationTimedOut will be raised. +This is a client-side timeout. For more information +about server-side coordinator timeouts, see policies.RetryPolicy.

+

Example usage:

+
>>> future = session.execute_async("SELECT * FROM mycf")
+>>> # do other stuff...
+
+>>> try:
+...     rows = future.result()
+...     for row in rows:
+...         ... # process results
+... except Exception:
+...     log.exception("Operation failed:")
+
+
+
+ +
+
+get_query_trace()
+

Fetches and returns the query trace of the last response, or None if tracing was +not enabled.

+

Note that this may raise an exception if there are problems retrieving the trace +details from Cassandra. If the trace is not available after max_wait, +cassandra.query.TraceUnavailable will be raised.

+

If the ResponseFuture is not done (async execution) and you try to retrieve the trace, +cassandra.query.TraceUnavailable will be raised.

+

query_cl is the consistency level used to poll the trace tables.

+
+ +
+
+get_all_query_traces()
+

Fetches and returns the query traces for all query pages, if tracing was enabled.

+

See note in get_query_trace() regarding possible exceptions.

+
+ +
+
+custom_payload
+

The custom payload returned from the server, if any. This will only be +set by Cassandra servers implementing a custom QueryHandler, and only +for protocol_version 4+.

+

Ensure the future is complete before trying to access this property +(call result(), or after callback is invoked). +Otherwise it may throw if the response has not been received.

+
+
Returns
+

Custom Payloads.

+
+
+
+ +
+
+is_schema_agreed = True
+
+ +
+
+has_more_pages
+

Returns True if there are more pages left in the +query results, False otherwise. This should only +be checked after the first page has been returned.

+
+

New in version 2.0.0.

+
+
+ +
+
+warnings
+

Warnings returned from the server, if any. This will only be +set for protocol_version 4+.

+

Warnings may be returned for such things as oversized batches, +or too many tombstones in slice queries.

+

Ensure the future is complete before trying to access this property +(call result(), or after callback is invoked). +Otherwise it may throw if the response has not been received.

+
+ +
+
+start_fetching_next_page()
+

If there are more pages left in the query result, this asynchronously +starts fetching the next page. If there are no pages left, QueryExhausted +is raised. Also see has_more_pages.

+

This should only be called after the first page has been returned.

+
+

New in version 2.0.0.

+
+
+ +
+
+add_callback(fn, *args, **kwargs)
+

Attaches a callback function to be called when the final results arrive.

+

By default, fn will be called with the results as the first and only +argument. If *args or **kwargs are supplied, they will be passed +through as additional positional or keyword arguments to fn.

+

If an error is hit while executing the operation, a callback attached +here will not be called. Use add_errback() or add_callbacks() +if you wish to handle that case.

+

If the final result has already been seen when this method is called, +the callback will be called immediately (before this method returns).

+

Note: in the case that the result is not available when the callback is added, +the callback is executed by IO event thread. This means that the callback +should not block or attempt further synchronous requests, because no further +IO will be processed until the callback returns.

+

Important: if the callback you attach results in an exception being +raised, the exception will be ignored, so please ensure your +callback handles all error cases that you care about.

+

Usage example:

+
>>> session = cluster.connect("mykeyspace")
+
+>>> def handle_results(rows, start_time, should_log=False):
+...     if should_log:
+...         log.info("Total time: %f", time.time() - start_time)
+...     ...
+
+>>> future = session.execute_async("SELECT * FROM users")
+>>> future.add_callback(handle_results, time.time(), should_log=True)
+
+
+
+ +
+
+add_errback(fn, *args, **kwargs)
+

Like add_callback(), but handles error cases. +An Exception instance will be passed as the first positional argument +to fn.

+
+ +
+
+ResponseFuture.add_callbacks(callback, errback, callback_args=(), callback_kwargs=None, errback_args=(), errback_args=None)
+

A convenient combination of add_callback() and +add_errback().

+

Example usage:

+
>>> session = cluster.connect()
+>>> query = "SELECT * FROM mycf"
+>>> future = session.execute_async(query)
+
+>>> def log_results(results, level='debug'):
+...     for row in results:
+...         log.log(level, "Result: %s", row)
+
+>>> def log_error(exc, query):
+...     log.error("Query '%s' failed: %s", query, exc)
+
+>>> future.add_callbacks(
+...     callback=log_results, callback_kwargs={'level': 'info'},
+...     errback=log_error, errback_args=(query,))
+
+
+
+ +
+ +
+
+class cassandra.cluster.ResultSet
+

An iterator over the rows from a query result. Also supplies basic equality +and indexing methods for backward-compatability. These methods materialize +the entire result set (loading all pages), and should only be used if the +total result size is understood. Warnings are emitted when paged results +are materialized in this fashion.

+

You can treat this as a normal iterator over rows:

+
>>> from cassandra.query import SimpleStatement
+>>> statement = SimpleStatement("SELECT * FROM users", fetch_size=10)
+>>> for user_row in session.execute(statement):
+...     process_user(user_row)
+
+
+

Whenever there are no more rows in the current page, the next page will +be fetched transparently. However, note that it is possible for +an Exception to be raised while fetching the next page, just +like you might see on a normal call to session.execute().

+
+
+all()
+

Returns all the remaining rows as a list. This is basically +a convenient shortcut to list(result_set).

+

This function is not recommended for queries that return a large number of elements.

+
+ +
+
+property current_rows
+

The list of current page rows. May be empty if the result was empty, +or this is the last page.

+
+ +
+
+fetch_next_page()
+

Manually, synchronously fetch the next page. Supplied for manually retrieving pages +and inspecting current_page(). It is not necessary to call this when iterating +through results; paging happens implicitly in iteration.

+
+ +
+
+get_all_query_traces(max_wait_sec_per=None)
+

Gets all query traces from the associated future. +See ResponseFuture.get_all_query_traces() for details.

+
+ +
+
+get_query_trace(max_wait_sec=None)
+

Gets the last query trace from the associated future. +See ResponseFuture.get_query_trace() for details.

+
+ +
+
+property has_more_pages
+

True if the last response indicated more pages; False otherwise

+
+ +
+
+one()
+

Return a single row of the results or None if empty. This is basically +a shortcut to result_set.current_rows[0] and should only be used when +you know a query returns a single row. Consider using an iterator if the +ResultSet contains more than one row.

+
+ +
+
+property paging_state
+

Server paging state of the query. Can be None if the query was not paged.

+

The driver treats paging state as opaque, but it may contain primary key data, so applications may want to +avoid sending this to untrusted parties.

+
+ +
+
+property was_applied
+

For LWT results, returns whether the transaction was applied.

+

Result is indeterminate if called on a result that was not an LWT request or on +a query.BatchStatement containing LWT. In the latter case either all the batch +succeeds or fails.

+

Only valid when one of the of the internal row factories is in use.

+
+ +
+ +
+
+exception cassandra.cluster.QueryExhausted
+

Raised when ResponseFuture.start_fetching_next_page() is called and +there are no more pages. You can check ResponseFuture.has_more_pages +before calling to avoid this.

+
+

New in version 2.0.0.

+
+
+ +
+
+exception cassandra.cluster.NoHostAvailable
+

Raised when an operation is attempted but all connections are +busy, defunct, closed, or resulted in errors when used.

+
+ +
+
+exception cassandra.cluster.UserTypeDoesNotExist
+

An attempt was made to use a user-defined type that does not exist.

+
+

New in version 2.1.0.

+
+
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.25.4-scylla/api/cassandra/concurrent.html b/3.25.4-scylla/api/cassandra/concurrent.html new file mode 100644 index 0000000000..747d6d465c --- /dev/null +++ b/3.25.4-scylla/api/cassandra/concurrent.html @@ -0,0 +1,710 @@ + + + + + + + + + + + + + cassandra.concurrent - Utilities for Concurrent Statement Execution | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.concurrent - Utilities for Concurrent Statement Execution

+
+
+cassandra.concurrent.execute_concurrent(session, statements_and_parameters, concurrency=100, raise_on_first_error=True, results_generator=False, execution_profile=<object object>)
+

Executes a sequence of (statement, parameters) tuples concurrently. Each +parameters item must be a sequence or None.

+

The concurrency parameter controls how many statements will be executed +concurrently. When Cluster.protocol_version is set to 1 or 2, +it is recommended that this be kept below 100 times the number of +core connections per host times the number of connected hosts (see +Cluster.set_core_connections_per_host()). If that amount is exceeded, +the event loop thread may attempt to block on new connection creation, +substantially impacting throughput. If protocol_version +is 3 or higher, you can safely experiment with higher levels of concurrency.

+

If raise_on_first_error is left as True, execution will stop +after the first failed statement and the corresponding exception will be +raised.

+

results_generator controls how the results are returned.

+
    +
  • If False, the results are returned only after all requests have completed.

  • +
  • If True, a generator expression is returned. Using a generator results in a constrained +memory footprint when the results set will be large – results are yielded +as they return instead of materializing the entire list at once. The trade for lower memory +footprint is marginal CPU overhead (more thread coordination and sorting out-of-order results +on-the-fly).

  • +
+

execution_profile argument is the execution profile to use for this +request, it is passed directly to Session.execute_async().

+

A sequence of ExecutionResult(success, result_or_exc) namedtuples is returned +in the same order that the statements were passed in. If success is False, +there was an error executing the statement, and result_or_exc will be +an Exception. If success is True, result_or_exc +will be the query result.

+

Example usage:

+
select_statement = session.prepare("SELECT * FROM users WHERE id=?")
+
+statements_and_params = []
+for user_id in user_ids:
+    params = (user_id, )
+    statements_and_params.append((select_statement, params))
+
+results = execute_concurrent(
+    session, statements_and_params, raise_on_first_error=False)
+
+for (success, result) in results:
+    if not success:
+        handle_error(result)  # result will be an Exception
+    else:
+        process_user(result[0])  # result will be a list of rows
+
+
+

Note: in the case that generators are used, it is important to ensure the consumers do not +block or attempt further synchronous requests, because no further IO will be processed until +the consumer returns. This may also produce a deadlock in the IO event thread.

+
+ +
+
+cassandra.concurrent.execute_concurrent_with_args(session, statement, parameters, *args, **kwargs)
+

Like execute_concurrent(), but takes a single +statement and a sequence of parameters. Each item in parameters +should be a sequence or None.

+

Example usage:

+
statement = session.prepare("INSERT INTO mytable (a, b) VALUES (1, ?)")
+parameters = [(x,) for x in range(1000)]
+execute_concurrent_with_args(session, statement, parameters, concurrency=50)
+
+
+
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.25.4-scylla/api/cassandra/connection.html b/3.25.4-scylla/api/cassandra/connection.html new file mode 100644 index 0000000000..b7f1122256 --- /dev/null +++ b/3.25.4-scylla/api/cassandra/connection.html @@ -0,0 +1,738 @@ + + + + + + + + + + + + + cassandra.connection - Low Level Connection Info | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.connection - Low Level Connection Info

+
+
+exception cassandra.connection.ConnectionException
+

An unrecoverable error was hit when attempting to use a connection, +or the connection was already closed or defunct.

+
+ +
+
+exception cassandra.connection.ConnectionShutdown
+

Raised when a connection has been marked as defunct or has been closed.

+
+ +
+
+exception cassandra.connection.ConnectionBusy
+

An attempt was made to send a message through a Connection that +was already at the max number of in-flight operations.

+
+ +
+
+exception cassandra.connection.ProtocolError
+

Communication did not match the protocol that this driver expects.

+
+ +
+
+class cassandra.connection.EndPoint
+

Represents the information to connect to a cassandra node.

+
+
+property address
+

The IP address of the node. This is the RPC address the driver uses when connecting to the node

+
+ +
+
+property port
+

The port of the node.

+
+ +
+
+resolve()
+

Resolve the endpoint to an address/port. This is called +only on socket connection.

+
+ +
+
+property socket_family
+

The socket family of the endpoint.

+
+ +
+
+property ssl_options
+

SSL options specific to this endpoint.

+
+ +
+ +
+
+class cassandra.connection.EndPointFactory
+
+
+configure(cluster)
+

This is called by the cluster during its initialization.

+
+ +
+
+create(row)
+

Create an EndPoint from a system.peers row.

+
+ +
+ +
+
+class cassandra.connection.SniEndPoint(proxy_address, server_name, port=9042)
+

SNI Proxy EndPoint implementation.

+
+ +
+
+class cassandra.connection.SniEndPointFactory(proxy_address, port, node_domain=None)
+
+ +
+
+class cassandra.connection.UnixSocketEndPoint(unix_socket_path)
+

Unix Socket EndPoint implementation.

+
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.25.4-scylla/api/cassandra/cqlengine/columns.html b/3.25.4-scylla/api/cassandra/cqlengine/columns.html new file mode 100644 index 0000000000..9bffc541f0 --- /dev/null +++ b/3.25.4-scylla/api/cassandra/cqlengine/columns.html @@ -0,0 +1,956 @@ + + + + + + + + + + + + + cassandra.cqlengine.columns - Column types for object mapping models | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.cqlengine.columns - Column types for object mapping models

+
+

Columns

+

Columns in your models map to columns in your CQL table. You define CQL columns by defining column attributes on your model classes. +For a model to be valid it needs at least one primary key column and one non-primary key column.

+

Just as in CQL, the order you define your columns in is important, and is the same order they are defined in on a model’s corresponding table.

+

Each column on your model definitions needs to be an instance of a Column class.

+
+
+class cassandra.cqlengine.columns.Column(**kwargs)
+
+
+primary_key = False
+

bool flag, indicates this column is a primary key. The first primary key defined +on a model is the partition key (unless partition keys are set), all others are cluster keys

+
+ +
+
+partition_key = False
+

indicates that this column should be the partition key, defining +more than one partition key column creates a compound partition key

+
+ +
+
+index = False
+

bool flag, indicates an index should be created for this column

+
+ +
+
+custom_index = False
+

bool flag, indicates an index is managed outside of cqlengine. This is +useful if you want to do filter queries on fields that have custom +indexes.

+
+ +
+
+db_field = None
+

the fieldname this field will map to in the database

+
+ +
+
+default = None
+

the default value, can be a value or a callable (no args)

+
+ +
+
+required = False
+

boolean, is the field required? Model validation will raise and +exception if required is set to True and there is a None value assigned

+
+ +
+
+clustering_order = None
+

only applicable on clustering keys (primary keys that are not partition keys) +determines the order that the clustering keys are sorted on disk

+
+ +
+
+discriminator_column = False
+

boolean, if set to True, this column will be used for discriminating records +of inherited models.

+

Should only be set on a column of an abstract model being used for inheritance.

+

There may only be one discriminator column per model. See __discriminator_value__ +for how to specify the value of this column on specialized models.

+
+ +
+
+static = False
+

boolean, if set to True, this is a static column, with a single value per partition

+
+ +
+ +
+
+

Column Types

+

Columns of all types are initialized by passing Column attributes to the constructor by keyword.

+
+
+class cassandra.cqlengine.columns.Ascii(**kwargs)
+

Stores a US-ASCII character string

+
+
Parameters
+
    +
  • min_length (int) – Sets the minimum length of this string, for validation purposes. +Defaults to 1 if this is a required column. Otherwise, None.

  • +
  • max_length (int) – Sets the maximum length of this string, for validation purposes.

  • +
+
+
+
+ +
+
+class cassandra.cqlengine.columns.BigInt(**kwargs)
+

Stores a 64-bit signed integer value

+
+ +
+
+class cassandra.cqlengine.columns.Blob(**kwargs)
+

Stores a raw binary value

+
+ +
+
+cassandra.cqlengine.columns.Bytes
+

alias of cassandra.cqlengine.columns.Blob

+
+ +
+
+class cassandra.cqlengine.columns.Boolean(**kwargs)
+

Stores a boolean True or False value

+
+ +
+
+class cassandra.cqlengine.columns.Counter(index=False, db_field=None, required=False)
+

Stores a counter that can be incremented and decremented

+
+ +
+
+class cassandra.cqlengine.columns.Date(**kwargs)
+

Stores a simple date, with no time-of-day

+
+

Changed in version 2.6.0: removed overload of Date and DateTime. DateTime is a drop-in replacement for legacy models

+
+

requires C* 2.2+ and protocol v4+

+
+ +
+
+class cassandra.cqlengine.columns.DateTime(**kwargs)
+

Stores a datetime value

+
+
+truncate_microseconds = False
+

Set this True to have model instances truncate the date, quantizing it in the same way it will be in the database. +This allows equality comparison between assigned values and values read back from the database:

+
DateTime.truncate_microseconds = True
+assert Model.create(id=0, d=datetime.utcnow()) == Model.objects(id=0).first()
+
+
+

Defaults to False to preserve legacy behavior. May change in the future.

+
+ +
+ +
+
+class cassandra.cqlengine.columns.Decimal(**kwargs)
+

Stores a variable precision decimal value

+
+ +
+
+class cassandra.cqlengine.columns.Double(**kwargs)
+

Stores a double-precision floating-point value

+
+ +
+
+class cassandra.cqlengine.columns.Float(primary_key=False, partition_key=False, index=False, db_field=None, default=None, required=False, clustering_order=None, discriminator_column=False, static=False, custom_index=False)
+

Stores a single-precision floating-point value

+
+ +
+
+class cassandra.cqlengine.columns.Integer(**kwargs)
+

Stores a 32-bit signed integer value

+
+ +
+
+class cassandra.cqlengine.columns.List(value_type, default=<class 'list'>, **kwargs)
+

Stores a list of ordered values

+

http://www.datastax.com/documentation/cql/3.1/cql/cql_using/use_list_t.html

+
+
Parameters
+

value_type – a column class indicating the types of the value

+
+
+
+ +
+
+class cassandra.cqlengine.columns.Map(key_type, value_type, default=<class 'dict'>, **kwargs)
+

Stores a key -> value map (dictionary)

+

https://docs.datastax.com/en/dse/6.7/cql/cql/cql_using/useMap.html

+
+
Parameters
+
    +
  • key_type – a column class indicating the types of the key

  • +
  • value_type – a column class indicating the types of the value

  • +
+
+
+
+ +
+
+class cassandra.cqlengine.columns.Set(value_type, strict=True, default=<class 'set'>, **kwargs)
+

Stores a set of unordered, unique values

+

http://www.datastax.com/documentation/cql/3.1/cql/cql_using/use_set_t.html

+
+
Parameters
+
    +
  • value_type – a column class indicating the types of the value

  • +
  • strict – sets whether non set values will be coerced to set +type on validation, or raise a validation error, defaults to True

  • +
+
+
+
+ +
+
+class cassandra.cqlengine.columns.SmallInt(**kwargs)
+

Stores a 16-bit signed integer value

+
+

New in version 2.6.0.

+
+

requires C* 2.2+ and protocol v4+

+
+ +
+
+class cassandra.cqlengine.columns.Text(min_length=None, max_length=None, **kwargs)
+

Stores a UTF-8 encoded string

+
+
Parameters
+
    +
  • min_length (int) – Sets the minimum length of this string, for validation purposes. +Defaults to 1 if this is a required column. Otherwise, None.

  • +
  • max_length (int) – Sets the maximum length of this string, for validation purposes.

  • +
+
+
+
+ +
+
+class cassandra.cqlengine.columns.Time(**kwargs)
+

Stores a timezone-naive time-of-day, with nanosecond precision

+
+

New in version 2.6.0.

+
+

requires C* 2.2+ and protocol v4+

+
+ +
+
+class cassandra.cqlengine.columns.TimeUUID(**kwargs)
+

UUID containing timestamp

+
+ +
+
+class cassandra.cqlengine.columns.TinyInt(**kwargs)
+

Stores an 8-bit signed integer value

+
+

New in version 2.6.0.

+
+

requires C* 2.2+ and protocol v4+

+
+ +
+
+class cassandra.cqlengine.columns.UserDefinedType(user_type, **kwargs)
+

User Defined Type column

+

http://www.datastax.com/documentation/cql/3.1/cql/cql_using/cqlUseUDT.html

+

These columns are represented by a specialization of cassandra.cqlengine.usertype.UserType.

+

Please see User Defined Types for examples and discussion.

+
+
Parameters
+

user_type (type) – specifies the UserType model of the column

+
+
+
+ +
+
+class cassandra.cqlengine.columns.UUID(**kwargs)
+

Stores a type 1 or 4 UUID

+
+ +
+
+class cassandra.cqlengine.columns.VarInt(**kwargs)
+

Stores an arbitrary-precision integer

+
+ +
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.25.4-scylla/api/cassandra/cqlengine/connection.html b/3.25.4-scylla/api/cassandra/cqlengine/connection.html new file mode 100644 index 0000000000..75f3c762d9 --- /dev/null +++ b/3.25.4-scylla/api/cassandra/cqlengine/connection.html @@ -0,0 +1,717 @@ + + + + + + + + + + + + + cassandra.cqlengine.connection - Connection management for cqlengine | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.cqlengine.connection - Connection management for cqlengine

+
+
+cassandra.cqlengine.connection.default()
+

Configures the default connection to localhost, using the driver defaults +(except for row_factory)

+
+ +
+
+cassandra.cqlengine.connection.set_session(s)
+

Configures the default connection with a preexisting cassandra.cluster.Session

+

Note: the mapper presently requires a Session cassandra.cluster.Session.row_factory set to dict_factory. +This may be relaxed in the future

+
+ +
+
+cassandra.cqlengine.connection.setup(hosts, default_keyspace, consistency=None, lazy_connect=False, retry_connect=False, **kwargs)
+

Setup a the driver connection used by the mapper

+
+
Parameters
+
    +
  • hosts (list) – list of hosts, (contact_points for cassandra.cluster.Cluster)

  • +
  • default_keyspace (str) – The default keyspace to use

  • +
  • consistency (int) – The global default ConsistencyLevel - default is the same as Session.default_consistency_level

  • +
  • lazy_connect (bool) – True if should not connect until first use

  • +
  • retry_connect (bool) – True if we should retry to connect even if there was a connection failure initially

  • +
  • **kwargs – Pass-through keyword arguments for cassandra.cluster.Cluster

  • +
+
+
+
+ +
+
+cassandra.cqlengine.connection.register_connection(name, hosts=None, consistency=None, lazy_connect=False, retry_connect=False, cluster_options=None, default=False, session=None)
+

Add a connection to the connection registry. hosts and session are +mutually exclusive, and consistency, lazy_connect, +retry_connect, and cluster_options only work with hosts. Using +hosts will create a new cassandra.cluster.Cluster and +cassandra.cluster.Session.

+
+
Parameters
+
    +
  • hosts (list) – list of hosts, (contact_points for cassandra.cluster.Cluster).

  • +
  • consistency (int) – The default ConsistencyLevel for the +registered connection’s new session. Default is the same as +Session.default_consistency_level. For use with hosts only; +will fail when used with session.

  • +
  • lazy_connect (bool) – True if should not connect until first use. For +use with hosts only; will fail when used with session.

  • +
  • retry_connect (bool) – True if we should retry to connect even if there +was a connection failure initially. For use with hosts only; will +fail when used with session.

  • +
  • cluster_options (dict) – A dict of options to be used as keyword +arguments to cassandra.cluster.Cluster. For use with hosts +only; will fail when used with session.

  • +
  • default (bool) – If True, set the new connection as the cqlengine +default

  • +
  • session (Session) – A cassandra.cluster.Session to be used in +the created connection.

  • +
+
+
+
+ +
+
+cassandra.cqlengine.connection.unregister_connection(name)
+
+ +
+
+cassandra.cqlengine.connection.set_default_connection(name)
+
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.25.4-scylla/api/cassandra/cqlengine/management.html b/3.25.4-scylla/api/cassandra/cqlengine/management.html new file mode 100644 index 0000000000..47af9d8c80 --- /dev/null +++ b/3.25.4-scylla/api/cassandra/cqlengine/management.html @@ -0,0 +1,739 @@ + + + + + + + + + + + + + cassandra.cqlengine.management - Schema management for cqlengine | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.cqlengine.management - Schema management for cqlengine

+

A collection of functions for managing keyspace and table schema.

+
+
+cassandra.cqlengine.management.create_keyspace_simple(name, replication_factor, durable_writes=True, connections=None)
+

Creates a keyspace with SimpleStrategy for replica placement

+

If the keyspace already exists, it will not be modified.

+

This function should be used with caution, especially in production environments. +Take care to execute schema modifications in a single context (i.e. not concurrently with other clients).

+

There are plans to guard schema-modifying functions with an environment-driven conditional.

+
+
Parameters
+
    +
  • name (str) – name of keyspace to create

  • +
  • replication_factor (int) – keyspace replication factor, used with SimpleStrategy

  • +
  • durable_writes (bool) – Write log is bypassed if set to False

  • +
  • connections (list) – List of connection names

  • +
+
+
+
+ +
+
+cassandra.cqlengine.management.create_keyspace_network_topology(name, dc_replication_map, durable_writes=True, connections=None)
+

Creates a keyspace with NetworkTopologyStrategy for replica placement

+

If the keyspace already exists, it will not be modified.

+

This function should be used with caution, especially in production environments. +Take care to execute schema modifications in a single context (i.e. not concurrently with other clients).

+

There are plans to guard schema-modifying functions with an environment-driven conditional.

+
+
Parameters
+
    +
  • name (str) – name of keyspace to create

  • +
  • dc_replication_map (dict) – map of dc_names: replication_factor

  • +
  • durable_writes (bool) – Write log is bypassed if set to False

  • +
  • connections (list) – List of connection names

  • +
+
+
+
+ +
+
+cassandra.cqlengine.management.drop_keyspace(name, connections=None)
+

Drops a keyspace, if it exists.

+

There are plans to guard schema-modifying functions with an environment-driven conditional.

+

This function should be used with caution, especially in production environments. +Take care to execute schema modifications in a single context (i.e. not concurrently with other clients).

+
+
Parameters
+
    +
  • name (str) – name of keyspace to drop

  • +
  • connections (list) – List of connection names

  • +
+
+
+
+ +
+
+cassandra.cqlengine.management.sync_table(model, keyspaces=None, connections=None)
+

Inspects the model and creates / updates the corresponding table and columns.

+

If keyspaces is specified, the table will be synched for all specified keyspaces. +Note that the Model.__keyspace__ is ignored in that case.

+

If connections is specified, the table will be synched for all specified connections. Note that the Model.__connection__ is ignored in that case. +If not specified, it will try to get the connection from the Model.

+

Any User Defined Types used in the table are implicitly synchronized.

+

This function can only add fields that are not part of the primary key.

+

Note that the attributes removed from the model are not deleted on the database. +They become effectively ignored by (will not show up on) the model.

+

This function should be used with caution, especially in production environments. +Take care to execute schema modifications in a single context (i.e. not concurrently with other clients).

+

There are plans to guard schema-modifying functions with an environment-driven conditional.

+
+ +
+
+cassandra.cqlengine.management.sync_type(ks_name, type_model, connection=None)
+

Inspects the type_model and creates / updates the corresponding type.

+

Note that the attributes removed from the type_model are not deleted on the database (this operation is not supported). +They become effectively ignored by (will not show up on) the type_model.

+

This function should be used with caution, especially in production environments. +Take care to execute schema modifications in a single context (i.e. not concurrently with other clients).

+

There are plans to guard schema-modifying functions with an environment-driven conditional.

+
+ +
+
+cassandra.cqlengine.management.drop_table(model, keyspaces=None, connections=None)
+

Drops the table indicated by the model, if it exists.

+

If keyspaces is specified, the table will be dropped for all specified keyspaces. Note that the Model.__keyspace__ is ignored in that case.

+

If connections is specified, the table will be synched for all specified connections. Note that the Model.__connection__ is ignored in that case. +If not specified, it will try to get the connection from the Model.

+

This function should be used with caution, especially in production environments. +Take care to execute schema modifications in a single context (i.e. not concurrently with other clients).

+

There are plans to guard schema-modifying functions with an environment-driven conditional.

+
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.25.4-scylla/api/cassandra/cqlengine/models.html b/3.25.4-scylla/api/cassandra/cqlengine/models.html new file mode 100644 index 0000000000..414acdd011 --- /dev/null +++ b/3.25.4-scylla/api/cassandra/cqlengine/models.html @@ -0,0 +1,944 @@ + + + + + + + + + + + + + cassandra.cqlengine.models - Table models for object mapping | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.cqlengine.models - Table models for object mapping

+
+

Model

+
+
+class cassandra.cqlengine.models.Model(\*\*kwargs)
+

The initializer creates an instance of the model. Pass in keyword arguments for columns you’ve defined on the model.

+
class Person(Model):
+    id = columns.UUID(primary_key=True)
+    first_name  = columns.Text()
+    last_name = columns.Text()
+
+person = Person(first_name='Blake', last_name='Eggleston')
+person.first_name  #returns 'Blake'
+person.last_name  #returns 'Eggleston'
+
+
+

Model attributes define how the model maps to tables in the database. These are class variables that should be set +when defining Model deriviatives.

+
+
+__abstract__ = False
+

Optional. Indicates that this model is only intended to be used as a base class for other models. +You can’t create tables for abstract models, but checks around schema validity are skipped during class construction.

+
+ +
+
+__table_name__ = None
+

Optional. Sets the name of the CQL table for this model. If left blank, the table name will be the name of the model, with it’s module name as it’s prefix. Manually defined table names are not inherited.

+
+ +
+
+__table_name_case_sensitive__ = False
+

Optional. By default, __table_name__ is case insensitive. Set this to True if you want to preserve the case sensitivity.

+
+ +
+
+__keyspace__ = None
+

Sets the name of the keyspace used by this model.

+
+ +
+
+__connection__ = None
+

Sets the name of the default connection used by this model.

+
+ +
+
+__default_ttl__ = None
+

Will be deprecated in release 4.0. You can set the default ttl by configuring the table __options__. See Default TTL and Per Query TTL for more details.

+
+ +
+
+__discriminator_value__ = None
+

Optional Specifies a value for the discriminator column when using model inheritance.

+

See Model Inheritance for usage examples.

+
+ +

Each table can have its own set of configuration options, including compaction. Unspecified, these default to sensible values in +the server. To override defaults, set options using the model __options__ attribute, which allows options specified a dict.

+

When a table is synced, it will be altered to match the options set on your table. +This means that if you are changing settings manually they will be changed back on resync.

+

Do not use the options settings of cqlengine if you want to manage your compaction settings manually.

+

See the list of supported table properties for more information.

+
+
+__options__
+

For example:

+
class User(Model):
+    __options__ = {'compaction': {'class': 'LeveledCompactionStrategy',
+                                  'sstable_size_in_mb': '64',
+                                  'tombstone_threshold': '.2'},
+                   'comment': 'User data stored here'}
+
+    user_id = columns.UUID(primary_key=True)
+    name = columns.Text()
+
+
+

or :

+
class TimeData(Model):
+    __options__ = {'compaction': {'class': 'SizeTieredCompactionStrategy',
+                                  'bucket_low': '.3',
+                                  'bucket_high': '2',
+                                  'min_threshold': '2',
+                                  'max_threshold': '64',
+                                  'tombstone_compaction_interval': '86400'},
+                   'gc_grace_seconds': '0'}
+
+
+
+ +
+
+__compute_routing_key__ = True
+

Optional Setting False disables computing the routing key for TokenAwareRouting

+
+ +

The base methods allow creating, storing, and querying modeled objects.

+
+
+classmethod create(**kwargs)
+

Create an instance of this model in the database.

+

Takes the model column values as keyword arguments. Setting a value to +None is equivalent to running a CQL DELETE on that column.

+

Returns the instance.

+
+ +
+
+if_not_exists()
+

Check the existence of an object before insertion. The existence of an +object is determined by its primary key(s). And please note using this flag +would incur performance cost.

+

If the insertion isn’t applied, a LWTException is raised.

+
try:
+    TestIfNotExistsModel.if_not_exists().create(id=id, count=9, text='111111111111')
+except LWTException as e:
+    # handle failure case
+    print e.existing  # dict containing LWT result fields
+
+
+

This method is supported on Cassandra 2.0 or later.

+
+ +
+
+if_exists()
+

Check the existence of an object before an update or delete. The existence of an +object is determined by its primary key(s). And please note using this flag +would incur performance cost.

+

If the update or delete isn’t applied, a LWTException is raised.

+
try:
+    TestIfExistsModel.objects(id=id).if_exists().update(count=9, text='111111111111')
+except LWTException as e:
+    # handle failure case
+    pass
+
+
+

This method is supported on Cassandra 2.0 or later.

+
+ +
+
+save()
+

Saves an object to the database.

+
#create a person instance
+person = Person(first_name='Kimberly', last_name='Eggleston')
+#saves it to Cassandra
+person.save()
+
+
+
+ +
+
+update(**values)
+

Performs an update on the model instance. You can pass in values to set on the model +for updating, or you can call without values to execute an update against any modified +fields. If no fields on the model have been modified since loading, no query will be +performed. Model validation is performed normally. Setting a value to None is +equivalent to running a CQL DELETE on that column.

+

It is possible to do a blind update, that is, to update a field without having first selected the object out of the database. +See Blind Updates

+
+ +
+
+iff(**values)
+

Checks to ensure that the values specified are correct on the Cassandra cluster. +Simply specify the column(s) and the expected value(s). As with if_not_exists, +this incurs a performance cost.

+

If the insertion isn’t applied, a LWTException is raised.

+
t = TestTransactionModel(text='some text', count=5)
+try:
+     t.iff(count=5).update('other text')
+except LWTException as e:
+    # handle failure case
+    print e.existing # existing object
+
+
+
+ +
+
+classmethod get(*args, **kwargs)
+

Returns a single object based on the passed filter constraints.

+

This is a pass-through to the model objects().:method:~cqlengine.queries.get.

+
+ +
+
+classmethod filter(*args, **kwargs)
+

Returns a queryset based on filter parameters.

+

This is a pass-through to the model objects().:method:~cqlengine.queries.filter.

+
+ +
+
+classmethod all()
+

Returns a queryset representing all stored objects

+

This is a pass-through to the model objects().all()

+
+ +
+
+delete()
+

Deletes the object from the database

+
+ +
+
+batch(batch_object)
+

Sets the batch object to run instance updates and inserts queries with.

+

See Batch Queries for usage examples

+
+ +
+
+timeout(timeout)
+

Sets a timeout for use in save(), update(), and delete() +operations

+
+ +
+
+timestamp(timedelta_or_datetime)
+

Sets the timestamp for the query

+
+ +
+
+ttl(ttl_in_sec)
+

Sets the ttl values to run instance updates and inserts queries with.

+
+ +
+
+using(connection=None)
+

Change the context on the fly of the model instance (keyspace, connection)

+
+ +
+
+classmethod column_family_name(include_keyspace=True)
+

Returns the column family name if it’s been defined +otherwise, it creates it from the module and class name

+
+ +

Models also support dict-like access:

+
+
+len(m)
+

Returns the number of columns defined in the model

+
+ +
+
+m[col_name]
+

Returns the value of column col_name

+
+ +
+
+m[col_name] = value
+

Set m[col_name] to value

+
+ +
+
+keys()
+

Returns a list of column IDs.

+
+ +
+
+values()
+

Returns list of column values.

+
+ +
+
+items()
+

Returns a list of column ID/value tuples.

+
+ +
+ +
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.25.4-scylla/api/cassandra/cqlengine/query.html b/3.25.4-scylla/api/cassandra/cqlengine/query.html new file mode 100644 index 0000000000..cf0a1d8d54 --- /dev/null +++ b/3.25.4-scylla/api/cassandra/cqlengine/query.html @@ -0,0 +1,1040 @@ + + + + + + + + + + + + + cassandra.cqlengine.query - Query and filter model objects | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.cqlengine.query - Query and filter model objects

+
+

QuerySet

+

QuerySet objects are typically obtained by calling objects() on a model class. +The methods here are used to filter, order, and constrain results.

+
+
+class cassandra.cqlengine.query.ModelQuerySet(model)
+
+
+all()
+

Returns a queryset matching all rows

+
for user in User.objects().all():
+    print(user)
+
+
+
+ +
+
+batch(batch_obj)
+

Set a batch object to run the query on.

+

Note: running a select query with a batch object will raise an exception

+
+ +
+
+consistency(consistency)
+

Sets the consistency level for the operation. See ConsistencyLevel.

+
for user in User.objects(id=3).consistency(CL.ONE):
+    print(user)
+
+
+
+ +
+
+count()
+

Returns the number of rows matched by this query.

+

Note: This function executes a SELECT COUNT() and has a performance cost on large datasets

+
+ +
+
+len(queryset)
+

Returns the number of rows matched by this query. This function uses count() internally.

+

Note: This function executes a SELECT COUNT() and has a performance cost on large datasets

+
+ +
+
+distinct(distinct_fields=None)
+

Returns the DISTINCT rows matched by this query.

+

distinct_fields default to the partition key fields if not specified.

+

Note: distinct_fields must be a partition key or a static column

+
class Automobile(Model):
+    manufacturer = columns.Text(partition_key=True)
+    year = columns.Integer(primary_key=True)
+    model = columns.Text(primary_key=True)
+    price = columns.Decimal()
+
+sync_table(Automobile)
+
+# create rows
+
+Automobile.objects.distinct()
+
+# or
+
+Automobile.objects.distinct(['manufacturer'])
+
+
+
+ +
+
+filter(*args, **kwargs)
+

Adds WHERE arguments to the queryset, returning a new queryset

+

See Retrieving objects with filters

+

Returns a QuerySet filtered on the keyword arguments

+
+ +
+
+get(*args, **kwargs)
+

Returns a single instance matching this query, optionally with additional filter kwargs.

+

See Retrieving objects with filters

+

Returns a single object matching the QuerySet.

+
user = User.get(id=1)
+
+
+

If no objects are matched, a DoesNotExist exception is raised.

+

If more than one object is found, a MultipleObjectsReturned exception is raised.

+
+ +
+
+limit(v)
+

Limits the number of results returned by Cassandra. Use 0 or None to disable.

+

Note that CQL’s default limit is 10,000, so all queries without a limit set explicitly will have an implicit limit of 10,000

+
# Fetch 100 users
+for user in User.objects().limit(100):
+    print(user)
+
+# Fetch all users
+for user in User.objects().limit(None):
+    print(user)
+
+
+
+ +
+
+fetch_size(v)
+

Sets the number of rows that are fetched at a time.

+

Note that driver’s default fetch size is 5000.

+
for user in User.objects().fetch_size(500):
+    print(user)
+
+
+
+ +
+
+if_not_exists()
+

Check the existence of an object before insertion.

+

If the insertion isn’t applied, a LWTException is raised.

+
+ +
+
+if_exists()
+

Check the existence of an object before an update or delete.

+

If the update or delete isn’t applied, a LWTException is raised.

+
+ +
+
+order_by(*colnames)
+

Sets the column(s) to be used for ordering

+

Default order is ascending, prepend a ‘-’ to any column name for descending

+

Note: column names must be a clustering key

+
from uuid import uuid1,uuid4
+
+class Comment(Model):
+    photo_id = UUID(primary_key=True)
+    comment_id = TimeUUID(primary_key=True, default=uuid1) # second primary key component is a clustering key
+    comment = Text()
+
+sync_table(Comment)
+
+u = uuid4()
+for x in range(5):
+    Comment.create(photo_id=u, comment="test %d" % x)
+
+print("Normal")
+for comment in Comment.objects(photo_id=u):
+    print comment.comment_id
+
+print("Reversed")
+for comment in Comment.objects(photo_id=u).order_by("-comment_id"):
+    print comment.comment_id
+
+
+
+ +
+
+allow_filtering()
+

Enables the (usually) unwise practive of querying on a clustering key without also defining a partition key

+
+ +
+
+only(fields)
+

Load only these fields for the returned query

+
+ +
+
+defer(fields)
+

Don’t load these fields for the returned query

+
+ +
+
+timestamp(timestamp)
+

Allows for custom timestamps to be saved with the record.

+
+ +
+
+ttl(ttl)
+

Sets the ttl (in seconds) for modified data.

+

Note that running a select query with a ttl value will raise an exception

+
+ +
+
+using(keyspace=None, connection=None)
+

Change the context on-the-fly of the Model class (keyspace, connection)

+
+ +
+
+update(**values)
+

Performs an update on the row selected by the queryset. Include values to update in the +update like so:

+
Model.objects(key=n).update(value='x')
+
+
+

Passing in updates for columns which are not part of the model will raise a ValidationError.

+

Per column validation will be performed, but instance level validation will not +(i.e., Model.validate is not called). This is sometimes referred to as a blind update.

+

For example:

+
class User(Model):
+    id = Integer(primary_key=True)
+    name = Text()
+
+setup(["localhost"], "test")
+sync_table(User)
+
+u = User.create(id=1, name="jon")
+
+User.objects(id=1).update(name="Steve")
+
+# sets name to null
+User.objects(id=1).update(name=None)
+
+
+

Also supported is blindly adding and removing elements from container columns, +without loading a model instance from Cassandra.

+

Using the syntax .update(column_name={x, y, z}) will overwrite the contents of the container, like updating a +non container column. However, adding __<operation> to the end of the keyword arg, makes the update call add +or remove items from the collection, without overwriting then entire column.

+

Given the model below, here are the operations that can be performed on the different container columns:

+
class Row(Model):
+    row_id      = columns.Integer(primary_key=True)
+    set_column  = columns.Set(Integer)
+    list_column = columns.List(Integer)
+    map_column  = columns.Map(Integer, Integer)
+
+
+

Set

+
    +
  • add: adds the elements of the given set to the column

  • +
  • remove: removes the elements of the given set to the column

  • +
+
# add elements to a set
+Row.objects(row_id=5).update(set_column__add={6})
+
+# remove elements to a set
+Row.objects(row_id=5).update(set_column__remove={4})
+
+
+

List

+
    +
  • append: appends the elements of the given list to the end of the column

  • +
  • prepend: prepends the elements of the given list to the beginning of the column

  • +
+
# append items to a list
+Row.objects(row_id=5).update(list_column__append=[6, 7])
+
+# prepend items to a list
+Row.objects(row_id=5).update(list_column__prepend=[1, 2])
+
+
+

Map

+
    +
  • update: adds the given keys/values to the columns, creating new entries if they didn’t exist, and overwriting old ones if they did

  • +
+
# add items to a map
+Row.objects(row_id=5).update(map_column__update={1: 2, 3: 4})
+
+# remove items from a map
+Row.objects(row_id=5).update(map_column__remove={1, 2})
+
+
+
+ +
+ +
+
+class cassandra.cqlengine.query.BatchQuery(batch_type=None, timestamp=None, consistency=None, execute_on_exception=False, timeout=<object object>, connection=None)
+

Handles the batching of queries

+

http://docs.datastax.com/en/cql/3.0/cql/cql_reference/batch_r.html

+

See Batch Queries for more details.

+
+
Parameters
+
    +
  • batch_type (BatchType, str or None) – (optional) One of batch type values available through BatchType enum

  • +
  • timestamp (datetime or timedelta or None) – (optional) A datetime or timedelta object with desired timestamp to be applied +to the batch conditional.

  • +
  • consistency (The ConsistencyLevel to be used for the batch query, or None.) – (optional) One of consistency values (“ANY”, “ONE”, “QUORUM” etc)

  • +
  • execute_on_exception (bool) – (Defaults to False) Indicates that when the BatchQuery instance is used +as a context manager the queries accumulated within the context must be executed despite +encountering an error within the context. By default, any exception raised from within +the context scope will cause the batched queries not to be executed.

  • +
  • timeout (float or None) – (optional) Timeout for the entire batch (in seconds), if not specified fallback +to default session timeout

  • +
  • connection (str) – Connection name to use for the batch execution

  • +
+
+
+
+
+add_query(query)
+
+ +
+
+execute()
+
+ +
+
+add_callback(fn, *args, **kwargs)
+

Add a function and arguments to be passed to it to be executed after the batch executes.

+

A batch can support multiple callbacks.

+

Note, that if the batch does not execute, the callbacks are not executed. +A callback, thus, is an “on batch success” handler.

+
+
Parameters
+
    +
  • fn (callable) – Callable object

  • +
  • *args – Positional arguments to be passed to the callback at the time of execution

  • +
  • **kwargs – Named arguments to be passed to the callback at the time of execution

  • +
+
+
+
+ +
+ +
+
+class cassandra.cqlengine.query.ContextQuery(*args, **kwargs)
+

A Context manager to allow a Model to switch context easily. Presently, the context only +specifies a keyspace for model IO.

+
+
Parameters
+
    +
  • *args – One or more models. A model should be a class type, not an instance.

  • +
  • **kwargs – (optional) Context parameters: can be keyspace or connection

  • +
+
+
+

For example:

+
with ContextQuery(Automobile, keyspace='test2') as A:
+    A.objects.create(manufacturer='honda', year=2008, model='civic')
+    print len(A.objects.all())  # 1 result
+
+with ContextQuery(Automobile, keyspace='test4') as A:
+    print len(A.objects.all())  # 0 result
+
+# Multiple models
+with ContextQuery(Automobile, Automobile2, connection='cluster2') as (A, A2):
+    print len(A.objects.all())
+    print len(A2.objects.all())
+
+
+
+ +
+
+class cassandra.cqlengine.query.DoesNotExist
+
+ +
+
+class cassandra.cqlengine.query.MultipleObjectsReturned
+
+ +
+
+class cassandra.cqlengine.query.LWTException(existing)
+

Lightweight conditional exception.

+

This exception will be raised when a write using an IF clause could not be +applied due to existing data violating the condition. The existing data is +available through the existing attribute.

+
+
Parameters
+

existing – The current state of the data which prevented the write.

+
+
+
+ +
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.25.4-scylla/api/cassandra/cqlengine/usertype.html b/3.25.4-scylla/api/cassandra/cqlengine/usertype.html new file mode 100644 index 0000000000..eb82400ea6 --- /dev/null +++ b/3.25.4-scylla/api/cassandra/cqlengine/usertype.html @@ -0,0 +1,683 @@ + + + + + + + + + + + + + cassandra.cqlengine.usertype - Model classes for User Defined Types | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.cqlengine.usertype - Model classes for User Defined Types

+
+

UserType

+
+
+class cassandra.cqlengine.usertype.UserType(**values)
+

This class is used to model User Defined Types. To define a type, declare a class inheriting from this, +and assign field types as class attributes:

+
# connect with default keyspace ...
+
+from cassandra.cqlengine.columns import Text, Integer
+from cassandra.cqlengine.usertype import UserType
+
+class address(UserType):
+    street = Text()
+    zipcode = Integer()
+
+from cassandra.cqlengine import management
+management.sync_type(address)
+
+
+

Please see User Defined Types for a complete example and discussion.

+
+
+__type_name__ = None
+

Optional. Sets the name of the CQL type for this type.

+

If not specified, the type name will be the name of the class, with it’s module name as it’s prefix.

+
+ +
+ +
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.25.4-scylla/api/cassandra/datastax/graph/fluent/index.html b/3.25.4-scylla/api/cassandra/datastax/graph/fluent/index.html new file mode 100644 index 0000000000..f41ac78bbd --- /dev/null +++ b/3.25.4-scylla/api/cassandra/datastax/graph/fluent/index.html @@ -0,0 +1,757 @@ + + + + + + + + + + + + + cassandra.datastax.graph.fluent | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.datastax.graph.fluent

+
+
+class cassandra.datastax.graph.fluent.DseGraph
+

Dse Graph utility class for GraphTraversal construction and execution.

+
+
+DSE_GRAPH_QUERY_LANGUAGE = 'bytecode-json'
+

Graph query language, Default is ‘bytecode-json’ (GraphSON).

+
+ +
+
+static create_execution_profile(graph_name, graph_protocol=b'graphson-2.0', **kwargs)
+

Creates an ExecutionProfile for GraphTraversal execution. You need to register that execution profile to the +cluster by using cluster.add_execution_profile.

+
+
Parameters
+
    +
  • graph_name – The graph name

  • +
  • graph_protocol – (Optional) The graph protocol, default is DSE_GRAPH_QUERY_PROTOCOL.

  • +
+
+
+
+ +
+
+static query_from_traversal(traversal, graph_protocol=b'graphson-2.0', context=None)
+

From a GraphTraversal, return a query string based on the language specified in DseGraph.DSE_GRAPH_QUERY_LANGUAGE.

+
+
Parameters
+
    +
  • traversal – The GraphTraversal object

  • +
  • graph_protocol – The graph protocol. Default is DseGraph.DSE_GRAPH_QUERY_PROTOCOL.

  • +
  • context – The dict of the serialization context, needed for GraphSON3 (tuple, udt). +e.g: {‘cluster’: cluster, ‘graph_name’: name}

  • +
+
+
+
+ +
+
+static traversal_source(session=None, graph_name=None, execution_profile=EXEC_PROFILE_GRAPH_DEFAULT, traversal_class=None)
+

Returns a TinkerPop GraphTraversalSource binded to the session and graph_name if provided.

+
+
Parameters
+
    +
  • session – (Optional) A DSE session

  • +
  • graph_name – (Optional) DSE Graph name

  • +
  • execution_profile – (Optional) Execution profile for traversal queries. Default is set to EXEC_PROFILE_GRAPH_DEFAULT.

  • +
  • traversal_class – (Optional) The GraphTraversalSource class to use (DSL).

  • +
+
+
+
from cassandra.cluster import Cluster
+from cassandra.datastax.graph.fluent import DseGraph
+
+c = Cluster()
+session = c.connect()
+
+g = DseGraph.traversal_source(session, 'my_graph')
+print g.V().valueMap().toList()
+
+
+
+ +
+
+static batch(session=None, execution_profile=None)
+

Returns the cassandra.datastax.graph.fluent.query.TraversalBatch object allowing to +execute multiple traversals in the same transaction.

+
+ +
+ +
+
+class cassandra.datastax.graph.fluent.DSESessionRemoteGraphConnection(session[, graph_name, execution_profile])
+

A Tinkerpop RemoteConnection to execute traversal queries on DSE.

+
+
Parameters
+
    +
  • session – A DSE session

  • +
  • graph_name – (Optional) DSE Graph name.

  • +
  • execution_profile – (Optional) Execution profile for traversal queries. Default is set to EXEC_PROFILE_GRAPH_DEFAULT.

  • +
+
+
+
+ +
+
+class cassandra.datastax.graph.fluent.BaseGraphRowFactory(cluster)
+

Base row factory for graph traversal. This class basically wraps a +graphson reader function to handle additional features of Gremlin/DSE +and is callable as a normal row factory.

+
+
Currently supported:
    +
  • bulk results

  • +
+
+
+
+ +
+
+cassandra.datastax.graph.fluent.graph_traversal_row_factory
+

alias of cassandra.datastax.graph.fluent._GremlinGraphSON2RowFactory

+
+ +
+
+cassandra.datastax.graph.fluent.graph_traversal_dse_object_row_factory
+

alias of cassandra.datastax.graph.fluent._DseGraphSON2RowFactory

+
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.25.4-scylla/api/cassandra/datastax/graph/fluent/predicates.html b/3.25.4-scylla/api/cassandra/datastax/graph/fluent/predicates.html new file mode 100644 index 0000000000..c855cf69d6 --- /dev/null +++ b/3.25.4-scylla/api/cassandra/datastax/graph/fluent/predicates.html @@ -0,0 +1,753 @@ + + + + + + + + + + + + + cassandra.datastax.graph.fluent.predicates | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.datastax.graph.fluent.predicates

+
+
+class cassandra.datastax.graph.fluent.predicates.Search
+
+
+static token(value)
+

Search any instance of a certain token within the text property targeted. +:param value: the value to look for.

+
+ +
+
+static token_prefix(value)
+

Search any instance of a certain token prefix withing the text property targeted. +:param value: the value to look for.

+
+ +
+
+static token_regex(value)
+

Search any instance of the provided regular expression for the targeted property. +:param value: the value to look for.

+
+ +
+
+static prefix(value)
+

Search for a specific prefix at the beginning of the text property targeted. +:param value: the value to look for.

+
+ +
+
+static regex(value)
+

Search for this regular expression inside the text property targeted. +:param value: the value to look for.

+
+ +
+
+static fuzzy(value, distance)
+

Search for a fuzzy string inside the text property targeted. +:param value: the value to look for. +:param distance: The distance for the fuzzy search. ie. 1, to allow a one-letter misspellings.

+
+ +
+
+static token_fuzzy(value, distance)
+

Search for a token fuzzy inside the text property targeted. +:param value: the value to look for. +:param distance: The distance for the token fuzzy search. ie. 1, to allow a one-letter misspellings.

+
+ +
+
+static phrase(value, proximity)
+

Search for a phrase inside the text property targeted. +:param value: the value to look for. +:param proximity: The proximity for the phrase search. ie. phrase(‘David Felcey’, 2).. to find ‘David Felcey’ with up to two middle names.

+
+ +
+ +
+
+class cassandra.datastax.graph.fluent.predicates.CqlCollection
+
+
+static contains(value)
+

Search for a value inside a cql list/set column. +:param value: the value to look for.

+
+ +
+
+static contains_value(value)
+

Search for a map value. +:param value: the value to look for.

+
+ +
+
+static contains_key(value)
+

Search for a map key. +:param value: the value to look for.

+
+ +
+
+static entry_eq(value)
+

Search for a map entry. +:param value: the value to look for.

+
+ +
+ +
+
+class cassandra.datastax.graph.fluent.predicates.Geo
+
+
+static inside(value, units=1)
+

Search any instance of geometry inside the Distance targeted. +:param value: A Distance to look for. +:param units: The units for value. See GeoUnit enum. (Can also +provide an integer to use as a multiplier to convert value to +degrees.)

+
+ +
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.25.4-scylla/api/cassandra/datastax/graph/fluent/query.html b/3.25.4-scylla/api/cassandra/datastax/graph/fluent/query.html new file mode 100644 index 0000000000..5d62f89ebf --- /dev/null +++ b/3.25.4-scylla/api/cassandra/datastax/graph/fluent/query.html @@ -0,0 +1,704 @@ + + + + + + + + + + + + + cassandra.datastax.graph.fluent.query | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.datastax.graph.fluent.query

+
+
+class cassandra.datastax.graph.fluent.query.TraversalBatch(session=None, execution_profile=None)
+

A TraversalBatch is used to execute multiple graph traversals in a +single transaction. If any traversal in the batch fails, the entire +batch will fail to apply.

+

If a TraversalBatch is bounded to a DSE session, it can be executed using +traversal_batch.execute().

+
+
Parameters
+
    +
  • session – (Optional) A DSE session

  • +
  • execution_profile – (Optional) The execution profile to use for the batch execution

  • +
+
+
+
+
+add(traversal)
+

Add a traversal to the batch.

+
+
Parameters
+

traversal – A gremlin GraphTraversal

+
+
+
+ +
+
+add_all(traversals)
+

Adds a sequence of traversals to the batch.

+
+
Parameters
+

traversals – A sequence of gremlin GraphTraversal

+
+
+
+ +
+
+execute()
+

Execute the traversal batch if bounded to a DSE Session.

+
+ +
+
+as_graph_statement(graph_protocol=b'graphson-2.0')
+

Return the traversal batch as GraphStatement.

+
+
Parameters
+

graph_protocol – The graph protocol for the GraphSONWriter. Default is GraphProtocol.GRAPHSON_2_0.

+
+
+
+ +
+
+clear()
+

Clear a traversal batch for reuse.

+
+ +
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.25.4-scylla/api/cassandra/datastax/graph/index.html b/3.25.4-scylla/api/cassandra/datastax/graph/index.html new file mode 100644 index 0000000000..71812e4a3c --- /dev/null +++ b/3.25.4-scylla/api/cassandra/datastax/graph/index.html @@ -0,0 +1,1035 @@ + + + + + + + + + + + + + cassandra.datastax.graph - Graph Statements, Options, and Row Factories | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.datastax.graph - Graph Statements, Options, and Row Factories

+
+
+cassandra.datastax.graph.single_object_row_factory(column_names, rows)
+

returns the JSON string value of graph results

+
+ +
+
+cassandra.datastax.graph.graph_result_row_factory(column_names, rows)
+

Returns a Result object that can load graph results and produce specific types. +The Result JSON is deserialized and unpacked from the top-level ‘result’ dict.

+
+ +
+
+cassandra.datastax.graph.graph_object_row_factory(column_names, rows)
+

Like graph_result_row_factory(), except known element types (Vertex, Edge) are +converted to their simplified objects. Some low-level metadata is shed in this conversion. Unknown result types are +still returned as Result.

+
+ +
+
+cassandra.datastax.graph.graph_graphson2_row_factory(cluster)
+

Row factory to deserialize GraphSON2 results.

+
+ +
+
+cassandra.datastax.graph.graph_graphson3_row_factory(cluster)
+

Row factory to deserialize GraphSON3 results.

+
+ +
+
+cassandra.datastax.graph.to_int(value)
+

Wraps a value to be explicitly serialized as a graphson Int.

+
+ +
+
+cassandra.datastax.graph.to_bigint(value)
+

Wraps a value to be explicitly serialized as a graphson Bigint.

+
+ +
+
+cassandra.datastax.graph.to_smallint(value)
+

Wraps a value to be explicitly serialized as a graphson Smallint.

+
+ +
+
+cassandra.datastax.graph.to_float(value)
+

Wraps a value to be explicitly serialized as a graphson Float.

+
+ +
+
+cassandra.datastax.graph.to_double(value)
+

Wraps a value to be explicitly serialized as a graphson Double.

+
+ +
+
+class cassandra.datastax.graph.GraphProtocol
+
+
+GRAPHSON_1_0 = b'graphson-1.0'
+

GraphSON1

+
+ +
+
+GRAPHSON_2_0 = b'graphson-2.0'
+

GraphSON2

+
+ +
+
+GRAPHSON_3_0 = b'graphson-3.0'
+

GraphSON3

+
+ +
+ +
+
+class cassandra.datastax.graph.GraphOptions(**kwargs)
+

Options for DSE Graph Query handler.

+
+
+graph_name
+

name of the targeted graph.

+
+ +
+
+graph_source
+

choose the graph traversal source, configured on the server side.

+
+ +
+
+graph_language
+

the language used in the queries (default “gremlin-groovy”)

+
+ +
+
+graph_read_consistency_level
+

read cassandra.ConsistencyLevel for graph queries (if distinct from session default). +Setting this overrides the native Statement.consistency_level for read operations from Cassandra persistence

+
+ +
+
+graph_write_consistency_level
+

write cassandra.ConsistencyLevel for graph queries (if distinct from session default). +Setting this overrides the native Statement.consistency_level for write operations to Cassandra persistence.

+
+ +
+
+is_default_source
+
+ +
+
+is_analytics_source
+

True if graph_source is set to the server-defined analytics traversal source (‘a’)

+
+ +
+
+is_graph_source
+

True if graph_source is set to the server-defined graph traversal source (‘g’)

+
+ +
+
+set_source_default()
+

Sets graph_source to the server-defined default traversal source (‘default’)

+
+ +
+
+set_source_analytics()
+

Sets graph_source to the server-defined analytic traversal source (‘a’)

+
+ +
+
+set_source_graph()
+

Sets graph_source to the server-defined graph traversal source (‘g’)

+
+ +
+ +
+
+class cassandra.datastax.graph.SimpleGraphStatement(query_string, retry_policy=None, consistency_level=None, routing_key=None, serial_consistency_level=None, fetch_size=<object object>, keyspace=None, custom_payload=None, is_idempotent=False)
+

Simple graph statement for Session.execute_graph(). +Takes the same parameters as SimpleStatement.

+

query_string should be a literal CQL statement with the exception +of parameter placeholders that will be filled through the +parameters argument of Session.execute().

+

See Statement attributes for a description of the other parameters.

+
+ +
+
+class cassandra.datastax.graph.Result(value)
+

Represents deserialized graph results. +Property and item getters are provided for convenience.

+
+
+value = None
+

Deserialized value from the result

+
+ +
+
+as_vertex()
+

Return a Vertex parsed from this result

+

Raises TypeError if parsing fails (i.e. the result structure is not valid).

+
+ +
+
+as_edge()
+

Return a Edge parsed from this result

+

Raises TypeError if parsing fails (i.e. the result structure is not valid).

+
+ +
+
+as_path()
+

Return a Path parsed from this result

+

Raises TypeError if parsing fails (i.e. the result structure is not valid).

+
+ +
+ +
+
+class cassandra.datastax.graph.Vertex(id, label, type, properties)
+

Represents a Vertex element from a graph query.

+

Vertex properties are extracted into a dict of property names to list of VertexProperty (list +because they are always encoded that way, and sometimes have multiple cardinality; VertexProperty because sometimes +the properties themselves have property maps).

+
+ +
+
+class cassandra.datastax.graph.VertexProperty(label, value, properties=None)
+

Vertex properties have a top-level value and an optional dict of properties.

+
+
+label = None
+

label of the property

+
+ +
+
+value = None
+

Value of the property

+
+ +
+
+properties = None
+

dict of properties attached to the property

+
+ +
+ +
+
+class cassandra.datastax.graph.Edge(id, label, type, properties, inV, inVLabel, outV, outVLabel)
+

Represents an Edge element from a graph query.

+

Attributes match initializer parameters.

+
+ +
+
+class cassandra.datastax.graph.Path(labels, objects)
+

Represents a graph path.

+

Labels list is taken verbatim from the results.

+

Objects are either Result or Vertex/Edge for recognized types

+
+
+labels = None
+

List of labels in the path

+
+ +
+
+objects = None
+

List of objects in the path

+
+ +
+ +
+
+class cassandra.datastax.graph.T(name, val)
+

Represents a collection of tokens for more concise Traversal definitions.

+
+
+id = T.id
+
+ +
+
+key = T.key
+
+ +
+
+label = T.label
+
+ +
+
+value = T.value
+
+ +
+ +
+
+class cassandra.datastax.graph.GraphSON1Serializer
+

Serialize python objects to graphson types.

+
+ +
+
+class cassandra.datastax.graph.GraphSON1Deserializer
+

Deserialize graphson1 types to python objects.

+
+
+classmethod deserialize_date(value)
+
+ +
+
+classmethod deserialize_timestamp(value)
+
+ +
+
+classmethod deserialize_time(value)
+
+ +
+
+classmethod deserialize_duration(value)
+
+ +
+
+classmethod deserialize_int(value)
+
+ +
+
+classmethod deserialize_bigint(value)
+
+ +
+
+classmethod deserialize_double(value)
+
+ +
+
+classmethod deserialize_float(value)
+
+ +
+
+classmethod deserialize_uuid(value)
+
+ +
+
+classmethod deserialize_blob(value)
+
+ +
+
+classmethod deserialize_decimal(value)
+
+ +
+
+classmethod deserialize_point(value)
+
+ +
+
+classmethod deserialize_linestring(value)
+
+ +
+
+classmethod deserialize_polygon(value)
+
+ +
+ +
+
+class cassandra.datastax.graph.GraphSON2Reader(context, extra_deserializer_map=None)
+

GraphSON2 Reader that parse json and deserialize to python objects.

+
+
Parameters
+

extra_deserializer_map – map from GraphSON type tag to deserializer instance implementing deserialize

+
+
+
+
+read(json_data)
+

Read and deserialize json_data.

+
+ +
+
+deserialize(obj)
+

Deserialize GraphSON type-tagged dict values into objects mapped in self.deserializers

+
+ +
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.25.4-scylla/api/cassandra/decoder.html b/3.25.4-scylla/api/cassandra/decoder.html new file mode 100644 index 0000000000..fc48cd2a62 --- /dev/null +++ b/3.25.4-scylla/api/cassandra/decoder.html @@ -0,0 +1,665 @@ + + + + + + + + + + + + + cassandra.decoder - Data Return Formats | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.decoder - Data Return Formats

+
+
+cassandra.decoder.tuple_factory()
+

Deprecated in 2.0.0. Use cassandra.query.tuple_factory()

+
+ +
+
+cassandra.decoder.named_tuple_factory()
+

Deprecated in 2.0.0. Use cassandra.query.named_tuple_factory()

+
+ +
+
+cassandra.decoder.dict_factory()
+

Deprecated in 2.0.0. Use cassandra.query.dict_factory()

+
+ +
+
+cassandra.decoder.ordered_dict_factory()
+

Deprecated in 2.0.0. Use cassandra.query.ordered_dict_factory()

+
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.25.4-scylla/api/cassandra/encoder.html b/3.25.4-scylla/api/cassandra/encoder.html new file mode 100644 index 0000000000..7aaf179e44 --- /dev/null +++ b/3.25.4-scylla/api/cassandra/encoder.html @@ -0,0 +1,742 @@ + + + + + + + + + + + + + cassandra.encoder - Encoders for non-prepared Statements | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.encoder - Encoders for non-prepared Statements

+
+
+class cassandra.encoder.Encoder
+

A container for mapping python types to CQL string literals when working +with non-prepared statements. The type mapping can be +directly customized by users.

+
+
+mapping = None
+

A map of python types to encoder functions.

+
+ +
+
+cql_encode_none()
+

Converts None to the string ‘NULL’.

+
+ +
+
+cql_encode_object()
+

Default encoder for all objects that do not have a specific encoder function +registered. This function simply calls str() on the object.

+
+ +
+
+cql_encode_all_types()
+

Converts any type into a CQL string, defaulting to cql_encode_object +if mapping does not contain an entry for the type.

+
+ +
+
+cql_encode_sequence()
+

Converts a sequence to a string of the form (item1, item2, ...). This +is suitable for IN value lists.

+
+ +
+
+cql_encode_str()
+

Escapes quotes in str objects.

+
+ +
+
+cql_encode_unicode()
+

Converts unicode objects to UTF-8 encoded strings with quote escaping.

+
+ +
+
+cql_encode_bytes()
+

Converts strings, buffers, and bytearrays into CQL blob literals.

+
+ +
+
+cql_encode_datetime()
+

Converts a datetime.datetime object to a (string) integer timestamp +with millisecond precision.

+
+ +
+
+cql_encode_date()
+

Converts a datetime.date object to a string with format +YYYY-MM-DD.

+
+ +
+
+cql_encode_map_collection()
+

Converts a dict into a string of the form {key1: val1, key2: val2, ...}. +This is suitable for map type columns.

+
+ +
+
+cql_encode_list_collection()
+

Converts a sequence to a string of the form [item1, item2, ...]. This +is suitable for list type columns.

+
+ +
+
+cql_encode_set_collection()
+

Converts a sequence to a string of the form {item1, item2, ...}. This +is suitable for set type columns.

+
+ +
+
+cql_encode_tuple()
+

Converts a sequence to a string of the form (item1, item2, ...). This +is suitable for tuple type columns.

+
+ +
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.25.4-scylla/api/cassandra/graph.html b/3.25.4-scylla/api/cassandra/graph.html new file mode 100644 index 0000000000..9ae0dbb0f0 --- /dev/null +++ b/3.25.4-scylla/api/cassandra/graph.html @@ -0,0 +1,1028 @@ + + + + + + + + + + + + + cassandra.graph - Graph Statements, Options, and Row Factories | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.graph - Graph Statements, Options, and Row Factories

+
+

Note

+

This module is only for backward compatibility for dse-driver users. Consider using cassandra.datastax.graph.

+
+
+
+cassandra.graph.single_object_row_factory(column_names, rows)
+

returns the JSON string value of graph results

+
+ +
+
+cassandra.graph.graph_result_row_factory(column_names, rows)
+

Returns a Result object that can load graph results and produce specific types. +The Result JSON is deserialized and unpacked from the top-level ‘result’ dict.

+
+ +
+
+cassandra.graph.graph_object_row_factory(column_names, rows)
+

Like graph_result_row_factory(), except known element types (Vertex, Edge) are +converted to their simplified objects. Some low-level metadata is shed in this conversion. Unknown result types are +still returned as Result.

+
+ +
+
+cassandra.graph.graph_graphson2_row_factory(cluster)
+

Row factory to deserialize GraphSON2 results.

+
+ +
+
+cassandra.graph.graph_graphson3_row_factory(cluster)
+

Row factory to deserialize GraphSON3 results.

+
+ +
+
+cassandra.graph.to_int(value)
+

Wraps a value to be explicitly serialized as a graphson Int.

+
+ +
+
+cassandra.graph.to_bigint(value)
+

Wraps a value to be explicitly serialized as a graphson Bigint.

+
+ +
+
+cassandra.graph.to_smallint(value)
+

Wraps a value to be explicitly serialized as a graphson Smallint.

+
+ +
+
+cassandra.graph.to_float(value)
+

Wraps a value to be explicitly serialized as a graphson Float.

+
+ +
+
+cassandra.graph.to_double(value)
+

Wraps a value to be explicitly serialized as a graphson Double.

+
+ +
+
+class cassandra.graph.GraphProtocol
+
+
+GRAPHSON_1_0 = b'graphson-1.0'
+

GraphSON1

+
+ +
+
+GRAPHSON_2_0 = b'graphson-2.0'
+

GraphSON2

+
+ +
+
+GRAPHSON_3_0 = b'graphson-3.0'
+

GraphSON3

+
+ +
+ +
+
+class cassandra.graph.GraphOptions(**kwargs)
+

Options for DSE Graph Query handler.

+
+
+graph_name
+

name of the targeted graph.

+
+ +
+
+graph_source
+

choose the graph traversal source, configured on the server side.

+
+ +
+
+graph_language
+

the language used in the queries (default “gremlin-groovy”)

+
+ +
+
+graph_read_consistency_level
+

read cassandra.ConsistencyLevel for graph queries (if distinct from session default). +Setting this overrides the native Statement.consistency_level for read operations from Cassandra persistence

+
+ +
+
+graph_write_consistency_level
+

write cassandra.ConsistencyLevel for graph queries (if distinct from session default). +Setting this overrides the native Statement.consistency_level for write operations to Cassandra persistence.

+
+ +
+
+is_default_source
+
+ +
+
+is_analytics_source
+

True if graph_source is set to the server-defined analytics traversal source (‘a’)

+
+ +
+
+is_graph_source
+

True if graph_source is set to the server-defined graph traversal source (‘g’)

+
+ +
+
+set_source_default()
+

Sets graph_source to the server-defined default traversal source (‘default’)

+
+ +
+
+set_source_analytics()
+

Sets graph_source to the server-defined analytic traversal source (‘a’)

+
+ +
+
+set_source_graph()
+

Sets graph_source to the server-defined graph traversal source (‘g’)

+
+ +
+ +
+
+class cassandra.graph.SimpleGraphStatement(query_string, retry_policy=None, consistency_level=None, routing_key=None, serial_consistency_level=None, fetch_size=<object object>, keyspace=None, custom_payload=None, is_idempotent=False)
+

Simple graph statement for Session.execute_graph(). +Takes the same parameters as SimpleStatement.

+

query_string should be a literal CQL statement with the exception +of parameter placeholders that will be filled through the +parameters argument of Session.execute().

+

See Statement attributes for a description of the other parameters.

+
+ +
+
+class cassandra.graph.Result(value)
+

Represents deserialized graph results. +Property and item getters are provided for convenience.

+
+
+value = None
+

Deserialized value from the result

+
+ +
+
+as_vertex()
+

Return a Vertex parsed from this result

+

Raises TypeError if parsing fails (i.e. the result structure is not valid).

+
+ +
+
+as_edge()
+

Return a Edge parsed from this result

+

Raises TypeError if parsing fails (i.e. the result structure is not valid).

+
+ +
+
+as_path()
+

Return a Path parsed from this result

+

Raises TypeError if parsing fails (i.e. the result structure is not valid).

+
+ +
+ +
+
+class cassandra.graph.Vertex(id, label, type, properties)
+

Represents a Vertex element from a graph query.

+

Vertex properties are extracted into a dict of property names to list of VertexProperty (list +because they are always encoded that way, and sometimes have multiple cardinality; VertexProperty because sometimes +the properties themselves have property maps).

+
+ +
+
+class cassandra.graph.VertexProperty(label, value, properties=None)
+

Vertex properties have a top-level value and an optional dict of properties.

+
+
+label = None
+

label of the property

+
+ +
+
+value = None
+

Value of the property

+
+ +
+
+properties = None
+

dict of properties attached to the property

+
+ +
+ +
+
+class cassandra.graph.Edge(id, label, type, properties, inV, inVLabel, outV, outVLabel)
+

Represents an Edge element from a graph query.

+

Attributes match initializer parameters.

+
+ +
+
+class cassandra.graph.Path(labels, objects)
+

Represents a graph path.

+

Labels list is taken verbatim from the results.

+

Objects are either Result or Vertex/Edge for recognized types

+
+
+labels = None
+

List of labels in the path

+
+ +
+
+objects = None
+

List of objects in the path

+
+ +
+ +
+
+class cassandra.graph.GraphSON1Serializer
+

Serialize python objects to graphson types.

+
+ +
+
+class cassandra.graph.GraphSON1Deserializer
+

Deserialize graphson1 types to python objects.

+
+
+classmethod deserialize_date(value)
+
+ +
+
+classmethod deserialize_timestamp(value)
+
+ +
+
+classmethod deserialize_time(value)
+
+ +
+
+classmethod deserialize_duration(value)
+
+ +
+
+classmethod deserialize_int(value)
+
+ +
+
+classmethod deserialize_bigint(value)
+
+ +
+
+classmethod deserialize_double(value)
+
+ +
+
+classmethod deserialize_float(value)
+
+ +
+
+classmethod deserialize_uuid(value)
+
+ +
+
+classmethod deserialize_blob(value)
+
+ +
+
+classmethod deserialize_decimal(value)
+
+ +
+
+classmethod deserialize_point(value)
+
+ +
+
+classmethod deserialize_linestring(value)
+
+ +
+
+classmethod deserialize_polygon(value)
+
+ +
+ +
+
+class cassandra.graph.GraphSON2Reader(context, extra_deserializer_map=None)
+

GraphSON2 Reader that parse json and deserialize to python objects.

+
+
Parameters
+

extra_deserializer_map – map from GraphSON type tag to deserializer instance implementing deserialize

+
+
+
+
+read(json_data)
+

Read and deserialize json_data.

+
+ +
+
+deserialize(obj)
+

Deserialize GraphSON type-tagged dict values into objects mapped in self.deserializers

+
+ +
+ +
+
+class cassandra.graph.GraphSON3Reader(context, extra_deserializer_map=None)
+

GraphSON3 Reader that parse json and deserialize to python objects.

+
+
Parameters
+
    +
  • context – A dict of the context, mostly used as context for udt deserialization.

  • +
  • extra_deserializer_map – map from GraphSON type tag to deserializer instance implementing deserialize

  • +
+
+
+
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.25.4-scylla/api/cassandra/io/asyncioreactor.html b/3.25.4-scylla/api/cassandra/io/asyncioreactor.html new file mode 100644 index 0000000000..1d7841bfdc --- /dev/null +++ b/3.25.4-scylla/api/cassandra/io/asyncioreactor.html @@ -0,0 +1,657 @@ + + + + + + + + + + + + + cassandra.io.asyncioreactor - asyncio Event Loop | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.io.asyncioreactor - asyncio Event Loop

+
+
+class cassandra.io.asyncioreactor.AsyncioConnection(*args, **kwargs)
+

An experimental implementation of Connection that uses the +asyncio module in the Python standard library for its event loop.

+

Note that it requires asyncio features that were only introduced in the +3.4 line in 3.4.6, and in the 3.5 line in 3.5.1.

+
+
+classmethod initialize_reactor()
+

Called once by Cluster.connect(). This should be used by implementations +to set up any resources that will be shared across connections.

+
+ +
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.25.4-scylla/api/cassandra/io/asyncorereactor.html b/3.25.4-scylla/api/cassandra/io/asyncorereactor.html new file mode 100644 index 0000000000..12903f8719 --- /dev/null +++ b/3.25.4-scylla/api/cassandra/io/asyncorereactor.html @@ -0,0 +1,662 @@ + + + + + + + + + + + + + cassandra.io.asyncorereactor - asyncore Event Loop | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.io.asyncorereactor - asyncore Event Loop

+
+
+class cassandra.io.asyncorereactor.AsyncoreConnection(*args, **kwargs)
+

An implementation of Connection that uses the asyncore +module in the Python standard library for its event loop.

+
+
+classmethod initialize_reactor()
+

Called once by Cluster.connect(). This should be used by implementations +to set up any resources that will be shared across connections.

+
+ +
+
+classmethod handle_fork()
+

Called after a forking. This should cleanup any remaining reactor state +from the parent process.

+
+ +
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.25.4-scylla/api/cassandra/io/eventletreactor.html b/3.25.4-scylla/api/cassandra/io/eventletreactor.html new file mode 100644 index 0000000000..88b76b3daf --- /dev/null +++ b/3.25.4-scylla/api/cassandra/io/eventletreactor.html @@ -0,0 +1,664 @@ + + + + + + + + + + + + + cassandra.io.eventletreactor - eventlet-compatible Connection | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.io.eventletreactor - eventlet-compatible Connection

+
+
+class cassandra.io.eventletreactor.EventletConnection(*args, **kwargs)
+

An implementation of Connection that utilizes eventlet.

+

This implementation assumes all eventlet monkey patching is active. It is not tested with partial patching.

+
+
+classmethod initialize_reactor()
+

Called once by Cluster.connect(). This should be used by implementations +to set up any resources that will be shared across connections.

+
+ +
+
+classmethod service_timeouts()
+

cls._timeout_watcher runs in this loop forever. +It is usually waiting for the next timeout on the cls._new_timer Event. +When new timers are added, that event is set so that the watcher can +wake up and possibly set an earlier timeout.

+
+ +
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.25.4-scylla/api/cassandra/io/geventreactor.html b/3.25.4-scylla/api/cassandra/io/geventreactor.html new file mode 100644 index 0000000000..1f88bf3830 --- /dev/null +++ b/3.25.4-scylla/api/cassandra/io/geventreactor.html @@ -0,0 +1,655 @@ + + + + + + + + + + + + + cassandra.io.geventreactor - gevent-compatible Event Loop | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.io.geventreactor - gevent-compatible Event Loop

+
+
+class cassandra.io.geventreactor.GeventConnection(*args, **kwargs)
+

An implementation of Connection that utilizes gevent.

+

This implementation assumes all gevent monkey patching is active. It is not tested with partial patching.

+
+
+classmethod initialize_reactor()
+

Called once by Cluster.connect(). This should be used by implementations +to set up any resources that will be shared across connections.

+
+ +
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.25.4-scylla/api/cassandra/io/libevreactor.html b/3.25.4-scylla/api/cassandra/io/libevreactor.html new file mode 100644 index 0000000000..7f3cf75430 --- /dev/null +++ b/3.25.4-scylla/api/cassandra/io/libevreactor.html @@ -0,0 +1,647 @@ + + + + + + + + + + + + + cassandra.io.libevreactor - libev Event Loop | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.io.libevreactor - libev Event Loop

+
+
+class cassandra.io.libevreactor.LibevConnection(*args, **kwargs)
+

An implementation of Connection that uses libev for its event loop.

+
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.25.4-scylla/api/cassandra/io/twistedreactor.html b/3.25.4-scylla/api/cassandra/io/twistedreactor.html new file mode 100644 index 0000000000..114a675838 --- /dev/null +++ b/3.25.4-scylla/api/cassandra/io/twistedreactor.html @@ -0,0 +1,648 @@ + + + + + + + + + + + + + cassandra.io.twistedreactor - Twisted Event Loop | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.io.twistedreactor - Twisted Event Loop

+
+
+class cassandra.io.twistedreactor.TwistedConnection
+

An implementation of Connection that uses +Twisted’s reactor as its event loop.

+
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.25.4-scylla/api/cassandra/metadata.html b/3.25.4-scylla/api/cassandra/metadata.html new file mode 100644 index 0000000000..39d1eafa0a --- /dev/null +++ b/3.25.4-scylla/api/cassandra/metadata.html @@ -0,0 +1,1032 @@ + + + + + + + + + + + + + cassandra.metadata - Schema and Ring Topology | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.metadata - Schema and Ring Topology

+
+
+cassandra.metadata.cql_keywords
+

set() -> new empty set object +set(iterable) -> new set object

+

Build an unordered collection of unique elements.

+
+ +
+
+cassandra.metadata.cql_keywords_unreserved
+

set() -> new empty set object +set(iterable) -> new set object

+

Build an unordered collection of unique elements.

+
+ +
+
+cassandra.metadata.cql_keywords_reserved
+

set() -> new empty set object +set(iterable) -> new set object

+

Build an unordered collection of unique elements.

+
+ +
+
+class cassandra.metadata.Metadata
+

Holds a representation of the cluster schema and topology.

+
+
+add_or_return_host(host)
+

Returns a tuple (host, new), where host is a Host +instance, and new is a bool indicating whether +the host was newly added.

+
+ +
+
+all_hosts()
+

Returns a list of all known Host instances in the cluster.

+
+ +
+
+export_schema_as_string()
+

Returns a string that can be executed as a query in order to recreate +the entire schema. The string is formatted to be human readable.

+
+ +
+
+get_host(endpoint_or_address, port=None)
+

Find a host in the metadata for a specific endpoint. If a string inet address and port are passed, +iterate all hosts to match the broadcast_rpc_address and +broadcast_rpc_port attributes.

+
+ +
+
+get_host_by_host_id(host_id)
+

Same as get_host() but use host_id for lookup.

+
+ +
+
+get_replicas(keyspace, key)
+

Returns a list of Host instances that are replicas for a given +partition key.

+
+ +
+ +
+

Schemas

+
+
+class cassandra.metadata.KeyspaceMetadata
+

A representation of the schema for a single keyspace.

+
+
+as_cql_query()
+

Returns a CQL query string that can be used to recreate just this keyspace, +not including user-defined types and tables.

+
+ +
+
+export_as_string()
+

Returns a CQL query string that can be used to recreate the entire keyspace, +including user-defined types and tables.

+
+ +
+ +
+
+class cassandra.metadata.UserType
+

A user defined type, as created by CREATE TYPE statements.

+

User-defined types were introduced in Cassandra 2.1.

+
+

New in version 2.1.0.

+
+
+
+as_cql_query(formatted=False)
+

Returns a CQL query that can be used to recreate this type. +If formatted is set to True, extra whitespace will +be added to make the query more readable.

+
+ +
+ +
+
+class cassandra.metadata.Function
+

A user defined function, as created by CREATE FUNCTION statements.

+

User-defined functions were introduced in Cassandra 2.2

+
+

New in version 2.6.0.

+
+
+
+as_cql_query(formatted=False)
+

Returns a CQL query that can be used to recreate this function. +If formatted is set to True, extra whitespace will +be added to make the query more readable.

+
+ +
+ +
+
+class cassandra.metadata.Aggregate
+

A user defined aggregate function, as created by CREATE AGGREGATE statements.

+

Aggregate functions were introduced in Cassandra 2.2

+
+

New in version 2.6.0.

+
+
+
+as_cql_query(formatted=False)
+

Returns a CQL query that can be used to recreate this aggregate. +If formatted is set to True, extra whitespace will +be added to make the query more readable.

+
+ +
+ +
+
+class cassandra.metadata.TableMetadata
+

A representation of the schema for a single table.

+
+
+as_cql_query(formatted=False)
+

Returns a CQL query that can be used to recreate this table (index +creations are not included). If formatted is set to True, +extra whitespace will be added to make the query human readable.

+
+ +
+
+export_as_string()
+

Returns a string of CQL queries that can be used to recreate this table +along with all indexes on it. The returned string is formatted to +be human readable.

+
+ +
+
+property is_cql_compatible
+

A boolean indicating if this table can be represented as CQL in export

+
+ +
+
+property primary_key
+

A list of ColumnMetadata representing the components of +the primary key for this table.

+
+ +
+ +
+
+class cassandra.metadata.TableMetadataV3
+

For C* 3.0+. option_maps take a superset of map names, so if nothing +changes structurally, new option maps can just be appended to the list.

+
+
+property is_cql_compatible
+

A boolean indicating if this table can be represented as CQL in export

+
+ +
+ +
+
+class cassandra.metadata.TableMetadataDSE68
+
+
+as_cql_query(formatted=False)
+

Returns a CQL query that can be used to recreate this table (index +creations are not included). If formatted is set to True, +extra whitespace will be added to make the query human readable.

+
+ +
+ +
+
+class cassandra.metadata.ColumnMetadata
+

A representation of a single column in a table.

+
+ +
+
+class cassandra.metadata.IndexMetadata
+

A representation of a secondary index on a column.

+
+
+as_cql_query()
+

Returns a CQL query that can be used to recreate this index.

+
+ +
+
+export_as_string()
+

Returns a CQL query string that can be used to recreate this index.

+
+ +
+ +
+
+class cassandra.metadata.MaterializedViewMetadata
+

A representation of a materialized view on a table

+
+
+as_cql_query(formatted=False)
+

Returns a CQL query that can be used to recreate this function. +If formatted is set to True, extra whitespace will +be added to make the query more readable.

+
+ +
+ +
+
+class cassandra.metadata.VertexMetadata
+

A representation of a vertex on a table

+
+ +
+
+class cassandra.metadata.EdgeMetadata
+

A representation of an edge on a table

+
+ +
+
+

Tokens and Ring Topology

+
+
+class cassandra.metadata.TokenMap
+

Information about the layout of the ring.

+
+
+get_replicas(keyspace, token)
+

Get a set of Host instances representing all of the +replica nodes for a given Token.

+
+ +
+ +
+
+class cassandra.metadata.Token
+

Abstract class representing a token.

+
+ +
+
+class cassandra.metadata.Murmur3Token(token)
+

A token for Murmur3Partitioner.

+

token is an int or string representing the token.

+
+ +
+
+class cassandra.metadata.MD5Token(token)
+

A token for RandomPartitioner.

+
+ +
+
+class cassandra.metadata.BytesToken(token)
+

A token for ByteOrderedPartitioner.

+
+
+classmethod from_string(token_string)
+

token_string should be the string representation from the server.

+
+ +
+ +
+
+cassandra.metadata.ReplicationStrategy
+

alias of cassandra.metadata._ReplicationStrategy

+
+ +
+
+class cassandra.metadata.ReplicationFactor(all_replicas, transient_replicas=None)
+

Represent the replication factor of a keyspace.

+
+ +
+
+class cassandra.metadata.SimpleStrategy(options_map)
+
+
+export_for_schema()
+

Returns a string version of these replication options which are +suitable for use in a CREATE KEYSPACE statement.

+
+ +
+
+property replication_factor
+

The replication factor for this keyspace.

+

For backward compatibility, this returns the +cassandra.metadata.ReplicationFactor.full_replicas value of +cassandra.metadata.SimpleStrategy.replication_factor_info.

+
+ +
+ +
+
+class cassandra.metadata.NetworkTopologyStrategy(dc_replication_factors)
+
+
+export_for_schema()
+

Returns a string version of these replication options which are +suitable for use in a CREATE KEYSPACE statement.

+
+ +
+ +
+
+class cassandra.metadata.LocalStrategy(options_map)
+
+
+export_for_schema()
+

Returns a string version of these replication options which are +suitable for use in a CREATE KEYSPACE statement.

+
+ +
+ +
+
+cassandra.metadata.group_keys_by_replica(session, keyspace, table, keys)
+

Returns a dict with the keys grouped per host. This can be +used to more accurately group by IN clause or to batch the keys per host.

+

If a valid replica is not found for a particular key it will be grouped under +NO_VALID_REPLICA

+

Example usage:

+
>>> result = group_keys_by_replica(
+...     session, "system", "peers",
+...     (("127.0.0.1", ), ("127.0.0.2", )))
+
+
+
+ +
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.25.4-scylla/api/cassandra/metrics.html b/3.25.4-scylla/api/cassandra/metrics.html new file mode 100644 index 0000000000..84cb15ddb9 --- /dev/null +++ b/3.25.4-scylla/api/cassandra/metrics.html @@ -0,0 +1,755 @@ + + + + + + + + + + + + + cassandra.metrics - Performance Metrics | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.metrics - Performance Metrics

+
+
+class cassandra.metrics.Metrics
+

A collection of timers and counters for various performance metrics.

+

Timer metrics are represented as floating point seconds.

+
+
+request_timer = None
+

A greplin.scales.PmfStat timer for requests. This is a dict-like +object with the following keys:

+
    +
  • count - number of requests that have been timed

  • +
  • min - min latency

  • +
  • max - max latency

  • +
  • mean - mean latency

  • +
  • stddev - standard deviation for latencies

  • +
  • median - median latency

  • +
  • 75percentile - 75th percentile latencies

  • +
  • 95percentile - 95th percentile latencies

  • +
  • 98percentile - 98th percentile latencies

  • +
  • 99percentile - 99th percentile latencies

  • +
  • 999percentile - 99.9th percentile latencies

  • +
+
+ +
+
+connection_errors = None
+

A greplin.scales.IntStat count of the number of times that a +request to a Cassandra node has failed due to a connection problem.

+
+ +
+
+write_timeouts = None
+

A greplin.scales.IntStat count of write requests that resulted +in a timeout.

+
+ +
+
+read_timeouts = None
+

A greplin.scales.IntStat count of read requests that resulted +in a timeout.

+
+ +
+
+unavailables = None
+

A greplin.scales.IntStat count of write or read requests that +failed due to an insufficient number of replicas being alive to meet +the requested ConsistencyLevel.

+
+ +
+
+other_errors = None
+

A greplin.scales.IntStat count of all other request failures, +including failures caused by invalid requests, bootstrapping nodes, +overloaded nodes, etc.

+
+ +
+
+retries = None
+

A greplin.scales.IntStat count of the number of times a +request was retried based on the RetryPolicy decision.

+
+ +
+
+ignores = None
+

A greplin.scales.IntStat count of the number of times a +failed request was ignored based on the RetryPolicy decision.

+
+ +
+
+known_hosts = None
+

A greplin.scales.IntStat count of the number of nodes in +the cluster that the driver is aware of, regardless of whether any +connections are opened to those nodes.

+
+ +
+
+connected_to = None
+

A greplin.scales.IntStat count of the number of nodes that +the driver currently has at least one connection open to.

+
+ +
+
+open_connections = None
+

A greplin.scales.IntStat count of the number connections +the driver currently has open.

+
+ +
+
+get_stats()
+

Returns the metrics for the registered cluster instance.

+
+ +
+
+set_stats_name(stats_name)
+

Set the metrics stats name. +The stats_name is a string used to access the metris through scales: scales.getStats()[<stats_name>] +Default is ‘cassandra-<num>’.

+
+ +
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.25.4-scylla/api/cassandra/policies.html b/3.25.4-scylla/api/cassandra/policies.html new file mode 100644 index 0000000000..a962f2fece --- /dev/null +++ b/3.25.4-scylla/api/cassandra/policies.html @@ -0,0 +1,1742 @@ + + + + + + + + + + + + + cassandra.policies - Load balancing and Failure Handling Policies | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.policies - Load balancing and Failure Handling Policies

+
+

Load Balancing

+
+
+class cassandra.policies.HostDistance
+

A measure of how “distant” a node is from the client, which +may influence how the load balancer distributes requests +and how many connections are opened to the node.

+
+
+IGNORED = -1
+

A node with this distance should never be queried or have +connections opened to it.

+
+ +
+
+LOCAL = 0
+

Nodes with LOCAL distance will be preferred for operations +under some load balancing policies (such as DCAwareRoundRobinPolicy) +and will have a greater number of connections opened against +them by default.

+

This distance is typically used for nodes within the same +datacenter as the client.

+
+ +
+
+REMOTE = 1
+

Nodes with REMOTE distance will be treated as a last resort +by some load balancing policies (such as DCAwareRoundRobinPolicy) +and will have a smaller number of connections opened against +them by default.

+

This distance is typically used for nodes outside of the +datacenter that the client is running in.

+
+ +
+ +
+
+class cassandra.policies.LoadBalancingPolicy
+

Load balancing policies are used to decide how to distribute +requests among all possible coordinator nodes in the cluster.

+

In particular, they may focus on querying “near” nodes (those +in a local datacenter) or on querying nodes who happen to +be replicas for the requested data.

+

You may also use subclasses of LoadBalancingPolicy for +custom behavior.

+
+
+distance(host)
+

Returns a measure of how remote a Host is in +terms of the HostDistance enums.

+
+ +
+
+populate(cluster, hosts)
+

This method is called to initialize the load balancing +policy with a set of Host instances before its +first use. The cluster parameter is an instance of +Cluster.

+
+ +
+
+make_query_plan(working_keyspace=None, query=None)
+

Given a Statement instance, return a iterable +of Host instances which should be queried in that +order. A generator may work well for custom implementations +of this method.

+

Note that the query argument may be None when preparing +statements.

+

working_keyspace should be the string name of the current keyspace, +as set through Session.set_keyspace() or with a USE +statement.

+
+ +
+
+check_supported()
+

This will be called after the cluster Metadata has been initialized. +If the load balancing policy implementation cannot be supported for +some reason (such as a missing C extension), this is the point at +which it should raise an exception.

+
+ +
+ +
+
+class cassandra.policies.RoundRobinPolicy
+

A subclass of LoadBalancingPolicy which evenly +distributes queries across all nodes in the cluster, +regardless of what datacenter the nodes may be in.

+
+
+populate(cluster, hosts)
+

This method is called to initialize the load balancing +policy with a set of Host instances before its +first use. The cluster parameter is an instance of +Cluster.

+
+ +
+
+distance(host)
+

Returns a measure of how remote a Host is in +terms of the HostDistance enums.

+
+ +
+
+make_query_plan(working_keyspace=None, query=None)
+

Given a Statement instance, return a iterable +of Host instances which should be queried in that +order. A generator may work well for custom implementations +of this method.

+

Note that the query argument may be None when preparing +statements.

+

working_keyspace should be the string name of the current keyspace, +as set through Session.set_keyspace() or with a USE +statement.

+
+ +
+
+on_up(host)
+

Called when a node is marked up.

+
+ +
+
+on_down(host)
+

Called when a node is marked down.

+
+ +
+
+on_add(host)
+

Called when a node is added to the cluster. The newly added node +should be considered up.

+
+ +
+
+on_remove(host)
+

Called when a node is removed from the cluster.

+
+ +
+ +
+
+class cassandra.policies.DCAwareRoundRobinPolicy(local_dc='', used_hosts_per_remote_dc=0)
+

Similar to RoundRobinPolicy, but prefers hosts +in the local datacenter and only uses nodes in remote +datacenters as a last resort.

+

The local_dc parameter should be the name of the datacenter +(such as is reported by nodetool ring) that should +be considered local. If not specified, the driver will choose +a local_dc based on the first host among Cluster.contact_points +having a valid DC. If relying on this mechanism, all specified +contact points should be nodes in a single, local DC.

+

used_hosts_per_remote_dc controls how many nodes in +each remote datacenter will have connections opened +against them. In other words, used_hosts_per_remote_dc hosts +will be considered REMOTE and the +rest will be considered IGNORED. +By default, all remote hosts are ignored.

+
+
+populate(cluster, hosts)
+

This method is called to initialize the load balancing +policy with a set of Host instances before its +first use. The cluster parameter is an instance of +Cluster.

+
+ +
+
+distance(host)
+

Returns a measure of how remote a Host is in +terms of the HostDistance enums.

+
+ +
+
+make_query_plan(working_keyspace=None, query=None)
+

Given a Statement instance, return a iterable +of Host instances which should be queried in that +order. A generator may work well for custom implementations +of this method.

+

Note that the query argument may be None when preparing +statements.

+

working_keyspace should be the string name of the current keyspace, +as set through Session.set_keyspace() or with a USE +statement.

+
+ +
+
+on_up(host)
+

Called when a node is marked up.

+
+ +
+
+on_down(host)
+

Called when a node is marked down.

+
+ +
+
+on_add(host)
+

Called when a node is added to the cluster. The newly added node +should be considered up.

+
+ +
+
+on_remove(host)
+

Called when a node is removed from the cluster.

+
+ +
+ +
+
+class cassandra.policies.WhiteListRoundRobinPolicy(hosts)
+

A subclass of RoundRobinPolicy which evenly +distributes queries across all nodes in the cluster, +regardless of what datacenter the nodes may be in, but +only if that node exists in the list of allowed nodes

+

This policy is addresses the issue described in +https://datastax-oss.atlassian.net/browse/JAVA-145 +Where connection errors occur when connection +attempts are made to private IP addresses remotely

+

The hosts parameter should be a sequence of hosts to permit +connections to.

+
+
+populate(cluster, hosts)
+

This method is called to initialize the load balancing +policy with a set of Host instances before its +first use. The cluster parameter is an instance of +Cluster.

+
+ +
+
+distance(host)
+

Returns a measure of how remote a Host is in +terms of the HostDistance enums.

+
+ +
+
+on_up(host)
+

Called when a node is marked up.

+
+ +
+
+on_add(host)
+

Called when a node is added to the cluster. The newly added node +should be considered up.

+
+ +
+ +
+
+class cassandra.policies.TokenAwarePolicy(child_policy, shuffle_replicas=False)
+

A LoadBalancingPolicy wrapper that adds token awareness to +a child policy.

+

This alters the child policy’s behavior so that it first attempts to +send queries to LOCAL replicas (as determined +by the child policy) based on the Statement’s +routing_key. If shuffle_replicas is +truthy, these replicas will be yielded in a random order. Once those +hosts are exhausted, the remaining hosts in the child policy’s query +plan will be used in the order provided by the child policy.

+

If no routing_key is set on the query, the child +policy’s query plan will be used as is.

+
+
+shuffle_replicas = False
+

Yield local replicas in a random order.

+
+ +
+
+populate(cluster, hosts)
+

This method is called to initialize the load balancing +policy with a set of Host instances before its +first use. The cluster parameter is an instance of +Cluster.

+
+ +
+
+check_supported()
+

This will be called after the cluster Metadata has been initialized. +If the load balancing policy implementation cannot be supported for +some reason (such as a missing C extension), this is the point at +which it should raise an exception.

+
+ +
+
+distance(*args, **kwargs)
+

Returns a measure of how remote a Host is in +terms of the HostDistance enums.

+
+ +
+
+make_query_plan(working_keyspace=None, query=None)
+

Given a Statement instance, return a iterable +of Host instances which should be queried in that +order. A generator may work well for custom implementations +of this method.

+

Note that the query argument may be None when preparing +statements.

+

working_keyspace should be the string name of the current keyspace, +as set through Session.set_keyspace() or with a USE +statement.

+
+ +
+
+on_up(*args, **kwargs)
+

Called when a node is marked up.

+
+ +
+
+on_down(*args, **kwargs)
+

Called when a node is marked down.

+
+ +
+
+on_add(*args, **kwargs)
+

Called when a node is added to the cluster. The newly added node +should be considered up.

+
+ +
+
+on_remove(*args, **kwargs)
+

Called when a node is removed from the cluster.

+
+ +
+ +
+
+class cassandra.policies.HostFilterPolicy(child_policy, predicate)
+

A LoadBalancingPolicy subclass configured with a child policy, +and a single-argument predicate. This policy defers to the child policy for +hosts where predicate(host) is truthy. Hosts for which +predicate(host) is falsey will be considered IGNORED, and will +not be used in a query plan.

+

This can be used in the cases where you need a whitelist or blacklist +policy, e.g. to prepare for decommissioning nodes or for testing:

+
def address_is_ignored(host):
+    return host.address in [ignored_address0, ignored_address1]
+
+blacklist_filter_policy = HostFilterPolicy(
+    child_policy=RoundRobinPolicy(),
+    predicate=address_is_ignored
+)
+
+cluster = Cluster(
+    primary_host,
+    load_balancing_policy=blacklist_filter_policy,
+)
+
+
+

See the note in the make_query_plan() documentation for a caveat on +how wrapping ordering polices (e.g. RoundRobinPolicy) may break +desirable properties of the wrapped policy.

+

Please note that whitelist and blacklist policies are not recommended for +general, day-to-day use. You probably want something like +DCAwareRoundRobinPolicy, which prefers a local DC but has +fallbacks, over a brute-force method like whitelisting or blacklisting.

+
+
Parameters
+
    +
  • child_policy – an instantiated LoadBalancingPolicy +that this one will defer to.

  • +
  • predicate – a one-parameter function that takes a Host. +If it returns a falsey value, the Host will +be IGNORED and not returned in query plans.

  • +
+
+
+
+
+predicate(host)
+

A predicate, set on object initialization, that takes a Host +and returns a value. If the value is falsy, the Host is +IGNORED. If the value is truthy, +HostFilterPolicy defers to the child policy to determine the +host’s distance.

+

This is a read-only value set in __init__, implemented as a +property.

+
+ +
+
+distance(host)
+

Checks if predicate(host), then returns +IGNORED if falsey, and defers to the child policy +otherwise.

+
+ +
+
+make_query_plan(working_keyspace=None, query=None)
+

Defers to the child policy’s +LoadBalancingPolicy.make_query_plan() and filters the results.

+

Note that this filtering may break desirable properties of the wrapped +policy in some cases. For instance, imagine if you configure this +policy to filter out host2, and to wrap a round-robin policy that +rotates through three hosts in the order host1, host2, host3, +host2, host3, host1, host3, host1, host2, repeating. This +policy will yield host1, host3, host3, host1, host3, host1, +disproportionately favoring host3.

+
+ +
+ +
+
+class cassandra.policies.DefaultLoadBalancingPolicy(child_policy)
+

A LoadBalancingPolicy wrapper that adds the ability to target a specific host first.

+

If no host is set on the query, the child policy’s query plan will be used as is.

+
+
+populate(cluster, hosts)
+

This method is called to initialize the load balancing +policy with a set of Host instances before its +first use. The cluster parameter is an instance of +Cluster.

+
+ +
+
+make_query_plan(working_keyspace=None, query=None)
+

Given a Statement instance, return a iterable +of Host instances which should be queried in that +order. A generator may work well for custom implementations +of this method.

+

Note that the query argument may be None when preparing +statements.

+

working_keyspace should be the string name of the current keyspace, +as set through Session.set_keyspace() or with a USE +statement.

+
+ +
+ +
+
+class cassandra.policies.DSELoadBalancingPolicy(*args, **kwargs)
+

Deprecated: This will be removed in the next major release, +consider using DefaultLoadBalancingPolicy.

+
+ +
+
+

Translating Server Node Addresses

+
+
+class cassandra.policies.AddressTranslator
+

Interface for translating cluster-defined endpoints.

+

The driver discovers nodes using server metadata and topology change events. Normally, +the endpoint defined by the server is the right way to connect to a node. In some environments, +these addresses may not be reachable, or not preferred (public vs. private IPs in cloud environments, +suboptimal routing, etc). This interface allows for translating from server defined endpoints to +preferred addresses for driver connections.

+

Note: contact_points provided while creating the Cluster instance are not +translated using this mechanism – only addresses received from Cassandra nodes are.

+
+
+translate(addr)
+

Accepts the node ip address, and returns a translated address to be used connecting to this node.

+
+ +
+ +
+
+class cassandra.policies.IdentityTranslator
+

Returns the endpoint with no translation

+
+
+translate(addr)
+

Accepts the node ip address, and returns a translated address to be used connecting to this node.

+
+ +
+ +
+
+class cassandra.policies.EC2MultiRegionTranslator
+

Resolves private ips of the hosts in the same datacenter as the client, and public ips of hosts in other datacenters.

+
+
+translate(addr)
+

Reverse DNS the public broadcast_address, then lookup that hostname to get the AWS-resolved IP, which +will point to the private IP address within the same datacenter.

+
+ +
+ +
+
+

Marking Hosts Up or Down

+
+
+class cassandra.policies.ConvictionPolicy(host)
+

A policy which decides when hosts should be considered down +based on the types of failures and the number of failures.

+

If custom behavior is needed, this class may be subclassed.

+

host is an instance of Host.

+
+
+add_failure(connection_exc)
+

Implementations should return True if the host should be +convicted, False otherwise.

+
+ +
+
+reset()
+

Implementations should clear out any convictions or state regarding +the host.

+
+ +
+ +
+
+class cassandra.policies.SimpleConvictionPolicy(host)
+

The default implementation of ConvictionPolicy, +which simply marks a host as down after the first failure +of any kind.

+

host is an instance of Host.

+
+
+add_failure(connection_exc)
+

Implementations should return True if the host should be +convicted, False otherwise.

+
+ +
+
+reset()
+

Implementations should clear out any convictions or state regarding +the host.

+
+ +
+ +
+
+

Reconnecting to Dead Hosts

+
+
+class cassandra.policies.ReconnectionPolicy
+

This class and its subclasses govern how frequently an attempt is made +to reconnect to nodes that are marked as dead.

+

If custom behavior is needed, this class may be subclassed.

+
+
+new_schedule()
+

This should return a finite or infinite iterable of delays (each as a +floating point number of seconds) inbetween each failed reconnection +attempt. Note that if the iterable is finite, reconnection attempts +will cease once the iterable is exhausted.

+
+ +
+ +
+
+class cassandra.policies.ConstantReconnectionPolicy(delay, max_attempts=64)
+

A ReconnectionPolicy subclass which sleeps for a fixed delay +inbetween each reconnection attempt.

+

delay should be a floating point number of seconds to wait inbetween +each attempt.

+

max_attempts should be a total number of attempts to be made before +giving up, or None to continue reconnection attempts forever. +The default is 64.

+
+
+new_schedule()
+

This should return a finite or infinite iterable of delays (each as a +floating point number of seconds) inbetween each failed reconnection +attempt. Note that if the iterable is finite, reconnection attempts +will cease once the iterable is exhausted.

+
+ +
+ +
+
+class cassandra.policies.ExponentialReconnectionPolicy(base_delay, max_delay, max_attempts=64)
+

A ReconnectionPolicy subclass which exponentially increases +the length of the delay inbetween each reconnection attempt up to +a set maximum delay.

+

A random amount of jitter (+/- 15%) will be added to the pure exponential +delay value to avoid the situations where many reconnection handlers are +trying to reconnect at exactly the same time.

+

base_delay and max_delay should be in floating point units of +seconds.

+

max_attempts should be a total number of attempts to be made before +giving up, or None to continue reconnection attempts forever. +The default is 64.

+
+
+new_schedule()
+

This should return a finite or infinite iterable of delays (each as a +floating point number of seconds) inbetween each failed reconnection +attempt. Note that if the iterable is finite, reconnection attempts +will cease once the iterable is exhausted.

+
+ +
+ +
+
+

Retrying Failed Operations

+
+
+class cassandra.policies.WriteType
+

For usage with RetryPolicy, this describe a type +of write operation.

+
+
+SIMPLE = 0
+

A write to a single partition key. Such writes are guaranteed to be atomic +and isolated.

+
+ +
+
+BATCH = 1
+

A write to multiple partition keys that used the distributed batch log to +ensure atomicity.

+
+ +
+
+UNLOGGED_BATCH = 2
+

A write to multiple partition keys that did not use the distributed batch +log. Atomicity for such writes is not guaranteed.

+
+ +
+
+COUNTER = 3
+

A counter write (for one or multiple partition keys). Such writes should +not be replayed in order to avoid overcount.

+
+ +
+
+BATCH_LOG = 4
+

The initial write to the distributed batch log that Cassandra performs +internally before a BATCH write.

+
+ +
+
+CAS = 5
+

A lighweight-transaction write, such as “DELETE … IF EXISTS”.

+
+ +
+
+VIEW = 6
+

This WriteType is only seen in results for requests that were unable to +complete MV operations.

+
+ +
+
+CDC = 7
+

This WriteType is only seen in results for requests that were unable to +complete CDC operations.

+
+ +
+ +
+
+class cassandra.policies.RetryPolicy
+

A policy that describes whether to retry, rethrow, or ignore coordinator +timeout and unavailable failures. These are failures reported from the +server side. Timeouts are configured by +settings in cassandra.yaml. +Unavailable failures occur when the coordinator cannot acheive the consistency +level for a request. For further information see the method descriptions +below.

+

To specify a default retry policy, set the +Cluster.default_retry_policy attribute to an instance of this +class or one of its subclasses.

+

To specify a retry policy per query, set the Statement.retry_policy +attribute to an instance of this class or one of its subclasses.

+

If custom behavior is needed for retrying certain operations, +this class may be subclassed.

+
+
+RETRY = 0
+

This should be returned from the below methods if the operation +should be retried on the same connection.

+
+ +
+
+RETHROW = 1
+

This should be returned from the below methods if the failure +should be propagated and no more retries attempted.

+
+ +
+
+IGNORE = 2
+

This should be returned from the below methods if the failure +should be ignored but no more retries should be attempted.

+
+ +
+
+RETRY_NEXT_HOST = 3
+

This should be returned from the below methods if the operation +should be retried on another connection.

+
+ +
+
+on_read_timeout(query, consistency, required_responses, received_responses, data_retrieved, retry_num)
+

This is called when a read operation times out from the coordinator’s +perspective (i.e. a replica did not respond to the coordinator in time). +It should return a tuple with two items: one of the class enums (such +as RETRY) and a ConsistencyLevel to retry the +operation at or None to keep the same consistency level.

+

query is the Statement that timed out.

+

consistency is the ConsistencyLevel that the operation was +attempted at.

+

The required_responses and received_responses parameters describe +how many replicas needed to respond to meet the requested consistency +level and how many actually did respond before the coordinator timed +out the request. data_retrieved is a boolean indicating whether +any of those responses contained data (as opposed to just a digest).

+

retry_num counts how many times the operation has been retried, so +the first time this method is called, retry_num will be 0.

+

By default, operations will be retried at most once, and only if +a sufficient number of replicas responded (with data digests).

+
+ +
+
+on_write_timeout(query, consistency, write_type, required_responses, received_responses, retry_num)
+

This is called when a write operation times out from the coordinator’s +perspective (i.e. a replica did not respond to the coordinator in time).

+

query is the Statement that timed out.

+

consistency is the ConsistencyLevel that the operation was +attempted at.

+

write_type is one of the WriteType enums describing the +type of write operation.

+

The required_responses and received_responses parameters describe +how many replicas needed to acknowledge the write to meet the requested +consistency level and how many replicas actually did acknowledge the +write before the coordinator timed out the request.

+

retry_num counts how many times the operation has been retried, so +the first time this method is called, retry_num will be 0.

+

By default, failed write operations will retried at most once, and +they will only be retried if the write_type was +BATCH_LOG.

+
+ +
+
+on_unavailable(query, consistency, required_replicas, alive_replicas, retry_num)
+

This is called when the coordinator node determines that a read or +write operation cannot be successful because the number of live +replicas are too low to meet the requested ConsistencyLevel. +This means that the read or write operation was never forwarded to +any replicas.

+

query is the Statement that failed.

+

consistency is the ConsistencyLevel that the operation was +attempted at.

+

required_replicas is the number of replicas that would have needed to +acknowledge the operation to meet the requested consistency level. +alive_replicas is the number of replicas that the coordinator +considered alive at the time of the request.

+

retry_num counts how many times the operation has been retried, so +the first time this method is called, retry_num will be 0.

+

By default, if this is the first retry, it triggers a retry on the next +host in the query plan with the same consistency level. If this is not the +first retry, no retries will be attempted and the error will be re-raised.

+
+ +
+
+on_request_error(query, consistency, error, retry_num)
+

This is called when an unexpected error happens. This can be in the +following situations:

+
    +
  • On a connection error

  • +
  • On server errors: overloaded, isBootstrapping, serverError, etc.

  • +
+

query is the Statement that timed out.

+

consistency is the ConsistencyLevel that the operation was +attempted at.

+

error the instance of the exception.

+

retry_num counts how many times the operation has been retried, so +the first time this method is called, retry_num will be 0.

+

The default, it triggers a retry on the next host in the query plan +with the same consistency level.

+
+ +
+ +
+
+class cassandra.policies.FallthroughRetryPolicy
+

A retry policy that never retries and always propagates failures to +the application.

+
+
+on_read_timeout(*args, **kwargs)
+

This is called when a read operation times out from the coordinator’s +perspective (i.e. a replica did not respond to the coordinator in time). +It should return a tuple with two items: one of the class enums (such +as RETRY) and a ConsistencyLevel to retry the +operation at or None to keep the same consistency level.

+

query is the Statement that timed out.

+

consistency is the ConsistencyLevel that the operation was +attempted at.

+

The required_responses and received_responses parameters describe +how many replicas needed to respond to meet the requested consistency +level and how many actually did respond before the coordinator timed +out the request. data_retrieved is a boolean indicating whether +any of those responses contained data (as opposed to just a digest).

+

retry_num counts how many times the operation has been retried, so +the first time this method is called, retry_num will be 0.

+

By default, operations will be retried at most once, and only if +a sufficient number of replicas responded (with data digests).

+
+ +
+
+on_write_timeout(*args, **kwargs)
+

This is called when a write operation times out from the coordinator’s +perspective (i.e. a replica did not respond to the coordinator in time).

+

query is the Statement that timed out.

+

consistency is the ConsistencyLevel that the operation was +attempted at.

+

write_type is one of the WriteType enums describing the +type of write operation.

+

The required_responses and received_responses parameters describe +how many replicas needed to acknowledge the write to meet the requested +consistency level and how many replicas actually did acknowledge the +write before the coordinator timed out the request.

+

retry_num counts how many times the operation has been retried, so +the first time this method is called, retry_num will be 0.

+

By default, failed write operations will retried at most once, and +they will only be retried if the write_type was +BATCH_LOG.

+
+ +
+
+on_unavailable(*args, **kwargs)
+

This is called when the coordinator node determines that a read or +write operation cannot be successful because the number of live +replicas are too low to meet the requested ConsistencyLevel. +This means that the read or write operation was never forwarded to +any replicas.

+

query is the Statement that failed.

+

consistency is the ConsistencyLevel that the operation was +attempted at.

+

required_replicas is the number of replicas that would have needed to +acknowledge the operation to meet the requested consistency level. +alive_replicas is the number of replicas that the coordinator +considered alive at the time of the request.

+

retry_num counts how many times the operation has been retried, so +the first time this method is called, retry_num will be 0.

+

By default, if this is the first retry, it triggers a retry on the next +host in the query plan with the same consistency level. If this is not the +first retry, no retries will be attempted and the error will be re-raised.

+
+ +
+
+on_request_error(*args, **kwargs)
+

This is called when an unexpected error happens. This can be in the +following situations:

+
    +
  • On a connection error

  • +
  • On server errors: overloaded, isBootstrapping, serverError, etc.

  • +
+

query is the Statement that timed out.

+

consistency is the ConsistencyLevel that the operation was +attempted at.

+

error the instance of the exception.

+

retry_num counts how many times the operation has been retried, so +the first time this method is called, retry_num will be 0.

+

The default, it triggers a retry on the next host in the query plan +with the same consistency level.

+
+ +
+ +
+
+class cassandra.policies.DowngradingConsistencyRetryPolicy(*args, **kwargs)
+

Deprecated: This retry policy will be removed in the next major release.

+

A retry policy that sometimes retries with a lower consistency level than +the one initially requested.

+

BEWARE: This policy may retry queries using a lower consistency +level than the one initially requested. By doing so, it may break +consistency guarantees. In other words, if you use this retry policy, +there are cases (documented below) where a read at QUORUM +may not see a preceding write at QUORUM. Do not use this +policy unless you have understood the cases where this can happen and +are ok with that. It is also recommended to subclass this class so +that queries that required a consistency level downgrade can be +recorded (so that repairs can be made later, etc).

+

This policy implements the same retries as RetryPolicy, +but on top of that, it also retries in the following cases:

+
    +
  • On a read timeout: if the number of replicas that responded is +greater than one but lower than is required by the requested +consistency level, the operation is retried at a lower consistency +level.

  • +
  • On a write timeout: if the operation is an UNLOGGED_BATCH +and at least one replica acknowledged the write, the operation is +retried at a lower consistency level. Furthermore, for other +write types, if at least one replica acknowledged the write, the +timeout is ignored.

  • +
  • On an unavailable exception: if at least one replica is alive, the +operation is retried at a lower consistency level.

  • +
+

The reasoning behind this retry policy is as follows: if, based +on the information the Cassandra coordinator node returns, retrying the +operation with the initially requested consistency has a chance to +succeed, do it. Otherwise, if based on that information we know the +initially requested consistency level cannot be achieved currently, then:

+
    +
  • For writes, ignore the exception (thus silently failing the +consistency requirement) if we know the write has been persisted on at +least one replica.

  • +
  • For reads, try reading at a lower consistency level (thus silently +failing the consistency requirement).

  • +
+

In other words, this policy implements the idea that if the requested +consistency level cannot be achieved, the next best thing for writes is +to make sure the data is persisted, and that reading something is better +than reading nothing, even if there is a risk of reading stale data.

+
+
+on_read_timeout(query, consistency, required_responses, received_responses, data_retrieved, retry_num)
+

This is called when a read operation times out from the coordinator’s +perspective (i.e. a replica did not respond to the coordinator in time). +It should return a tuple with two items: one of the class enums (such +as RETRY) and a ConsistencyLevel to retry the +operation at or None to keep the same consistency level.

+

query is the Statement that timed out.

+

consistency is the ConsistencyLevel that the operation was +attempted at.

+

The required_responses and received_responses parameters describe +how many replicas needed to respond to meet the requested consistency +level and how many actually did respond before the coordinator timed +out the request. data_retrieved is a boolean indicating whether +any of those responses contained data (as opposed to just a digest).

+

retry_num counts how many times the operation has been retried, so +the first time this method is called, retry_num will be 0.

+

By default, operations will be retried at most once, and only if +a sufficient number of replicas responded (with data digests).

+
+ +
+
+on_write_timeout(query, consistency, write_type, required_responses, received_responses, retry_num)
+

This is called when a write operation times out from the coordinator’s +perspective (i.e. a replica did not respond to the coordinator in time).

+

query is the Statement that timed out.

+

consistency is the ConsistencyLevel that the operation was +attempted at.

+

write_type is one of the WriteType enums describing the +type of write operation.

+

The required_responses and received_responses parameters describe +how many replicas needed to acknowledge the write to meet the requested +consistency level and how many replicas actually did acknowledge the +write before the coordinator timed out the request.

+

retry_num counts how many times the operation has been retried, so +the first time this method is called, retry_num will be 0.

+

By default, failed write operations will retried at most once, and +they will only be retried if the write_type was +BATCH_LOG.

+
+ +
+
+on_unavailable(query, consistency, required_replicas, alive_replicas, retry_num)
+

This is called when the coordinator node determines that a read or +write operation cannot be successful because the number of live +replicas are too low to meet the requested ConsistencyLevel. +This means that the read or write operation was never forwarded to +any replicas.

+

query is the Statement that failed.

+

consistency is the ConsistencyLevel that the operation was +attempted at.

+

required_replicas is the number of replicas that would have needed to +acknowledge the operation to meet the requested consistency level. +alive_replicas is the number of replicas that the coordinator +considered alive at the time of the request.

+

retry_num counts how many times the operation has been retried, so +the first time this method is called, retry_num will be 0.

+

By default, if this is the first retry, it triggers a retry on the next +host in the query plan with the same consistency level. If this is not the +first retry, no retries will be attempted and the error will be re-raised.

+
+ +
+ +
+
+

Retrying Idempotent Operations

+
+
+class cassandra.policies.SpeculativeExecutionPolicy
+

Interface for specifying speculative execution plans

+
+
+new_plan(keyspace, statement)
+

Returns

+
+
Parameters
+
    +
  • keyspace

  • +
  • statement

  • +
+
+
Returns
+

+
+
+
+ +
+ +
+
+class cassandra.policies.ConstantSpeculativeExecutionPolicy(delay, max_attempts)
+

A speculative execution policy that sends a new query every X seconds (delay) for a maximum of Y attempts (max_attempts).

+
+
+new_plan(keyspace, statement)
+

Returns

+
+
Parameters
+
    +
  • keyspace

  • +
  • statement

  • +
+
+
Returns
+

+
+
+
+ +
+ +
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.25.4-scylla/api/cassandra/pool.html b/3.25.4-scylla/api/cassandra/pool.html new file mode 100644 index 0000000000..cf78530532 --- /dev/null +++ b/3.25.4-scylla/api/cassandra/pool.html @@ -0,0 +1,673 @@ + + + + + + + + + + + + + cassandra.pool - Hosts and Connection Pools | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.pool - Hosts and Connection Pools

+

Connection pooling and host management.

+
+
+class cassandra.pool.Host
+

Represents a single Cassandra node.

+
+
+property address
+

The IP address of the endpoint. This is the RPC address the driver uses when connecting to the node.

+
+ +
+
+property datacenter
+

The datacenter the node is in.

+
+ +
+
+property rack
+

The rack the node is in.

+
+ +
+ +
+
+exception cassandra.pool.NoConnectionsAvailable
+

All existing connections to a given host are busy, or there are +no open connections.

+
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.25.4-scylla/api/cassandra/protocol.html b/3.25.4-scylla/api/cassandra/protocol.html new file mode 100644 index 0000000000..d81470a9da --- /dev/null +++ b/3.25.4-scylla/api/cassandra/protocol.html @@ -0,0 +1,739 @@ + + + + + + + + + + + + + cassandra.protocol - Protocol Features | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.protocol - Protocol Features

+
+

Custom Payloads

+

Native protocol version 4+ allows for a custom payload to be sent between clients +and custom query handlers. The payload is specified as a string:binary_type dict +holding custom key/value pairs.

+

By default these are ignored by the server. They can be useful for servers implementing +a custom QueryHandler.

+

See Session.execute(), :Session.execute_async(), ResponseFuture.custom_payload.

+
+
+class cassandra.protocol._ProtocolHandler
+

_ProtocolHander handles encoding and decoding messages.

+

This class can be specialized to compose Handlers which implement alternative +result decoding or type deserialization. Class definitions are passed to cassandra.cluster.Cluster +on initialization.

+

Contracted class methods are _ProtocolHandler.encode_message() and _ProtocolHandler.decode_message().

+
+
+message_types_by_opcode = {default mapping}
+
+ +
+
+classmethod encode_message(msg, stream_id, protocol_version, compressor, allow_beta_protocol_version)
+

Encodes a message using the specified frame parameters, and compressor

+
+
Parameters
+
    +
  • msg – the message, typically of cassandra.protocol._MessageType, generated by the driver

  • +
  • stream_id – protocol stream id for the frame header

  • +
  • protocol_version – version for the frame header, and used encoding contents

  • +
  • compressor – optional compression function to be used on the body

  • +
+
+
+
+ +
+
+classmethod decode_message(protocol_version, user_type_map, stream_id, flags, opcode, body, decompressor, result_metadata)
+

Decodes a native protocol message body

+
+
Parameters
+
    +
  • protocol_version – version to use decoding contents

  • +
  • user_type_map – map[keyspace name] = map[type name] = custom type to instantiate when deserializing this type

  • +
  • stream_id – native protocol stream id from the frame header

  • +
  • flags – native protocol flags bitmap from the header

  • +
  • opcode – native protocol opcode from the header

  • +
  • body – frame body

  • +
  • decompressor – optional decompression function to inflate the body

  • +
+
+
Returns
+

a message decoded from the body and frame attributes

+
+
+
+ +
+ +
+
+

Faster Deserialization

+

When python-driver is compiled with Cython, it uses a Cython-based deserialization path +to deserialize messages. By default, the driver will use a Cython-based parser that returns +lists of rows similar to the pure-Python version. In addition, there are two additional +ProtocolHandler classes that can be used to deserialize response messages: LazyProtocolHandler +and NumpyProtocolHandler. They can be used as follows:

+
from cassandra.protocol import NumpyProtocolHandler, LazyProtocolHandler
+from cassandra.query import tuple_factory
+s.client_protocol_handler = LazyProtocolHandler   # for a result iterator
+s.row_factory = tuple_factory  #required for Numpy results
+s.client_protocol_handler = NumpyProtocolHandler  # for a dict of NumPy arrays as result
+
+
+

These protocol handlers comprise different parsers, and return results as described below:

+
    +
  • ProtocolHandler: this default implementation is a drop-in replacement for the pure-Python version. +The rows are all parsed upfront, before results are returned.

  • +
  • LazyProtocolHandler: near drop-in replacement for the above, except that it returns an iterator over rows, +lazily decoded into the default row format (this is more efficient since all decoded results are not materialized at once)

  • +
  • NumpyProtocolHander: deserializes results directly into NumPy arrays. This facilitates efficient integration with +analysis toolkits such as Pandas.

  • +
+
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.25.4-scylla/api/cassandra/query.html b/3.25.4-scylla/api/cassandra/query.html new file mode 100644 index 0000000000..ba7cef100e --- /dev/null +++ b/3.25.4-scylla/api/cassandra/query.html @@ -0,0 +1,1002 @@ + + + + + + + + + + + + + cassandra.query - Prepared Statements, Batch Statements, Tracing, and Row Factories | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.query - Prepared Statements, Batch Statements, Tracing, and Row Factories

+
+
+cassandra.query.tuple_factory(colnames, rows)
+

Returns each row as a tuple

+

Example:

+
>>> from cassandra.query import tuple_factory
+>>> session = cluster.connect('mykeyspace')
+>>> session.row_factory = tuple_factory
+>>> rows = session.execute("SELECT name, age FROM users LIMIT 1")
+>>> print rows[0]
+('Bob', 42)
+
+
+
+

Changed in version 2.0.0: moved from cassandra.decoder to cassandra.query

+
+
+ +
+
+cassandra.query.named_tuple_factory(colnames, rows)
+

Returns each row as a namedtuple. +This is the default row factory.

+

Example:

+
>>> from cassandra.query import named_tuple_factory
+>>> session = cluster.connect('mykeyspace')
+>>> session.row_factory = named_tuple_factory
+>>> rows = session.execute("SELECT name, age FROM users LIMIT 1")
+>>> user = rows[0]
+
+>>> # you can access field by their name:
+>>> print "name: %s, age: %d" % (user.name, user.age)
+name: Bob, age: 42
+
+>>> # or you can access fields by their position (like a tuple)
+>>> name, age = user
+>>> print "name: %s, age: %d" % (name, age)
+name: Bob, age: 42
+>>> name = user[0]
+>>> age = user[1]
+>>> print "name: %s, age: %d" % (name, age)
+name: Bob, age: 42
+
+
+
+

Changed in version 2.0.0: moved from cassandra.decoder to cassandra.query

+
+
+ +
+
+cassandra.query.dict_factory(colnames, rows)
+

Returns each row as a dict.

+

Example:

+
>>> from cassandra.query import dict_factory
+>>> session = cluster.connect('mykeyspace')
+>>> session.row_factory = dict_factory
+>>> rows = session.execute("SELECT name, age FROM users LIMIT 1")
+>>> print rows[0]
+{u'age': 42, u'name': u'Bob'}
+
+
+
+

Changed in version 2.0.0: moved from cassandra.decoder to cassandra.query

+
+
+ +
+
+cassandra.query.ordered_dict_factory(colnames, rows)
+

Like dict_factory(), but returns each row as an OrderedDict, +so the order of the columns is preserved.

+
+

Changed in version 2.0.0: moved from cassandra.decoder to cassandra.query

+
+
+ +
+
+class cassandra.query.SimpleStatement(query_string, retry_policy=None, consistency_level=None, routing_key=None, serial_consistency_level=None, fetch_size=<object object>, keyspace=None, custom_payload=None, is_idempotent=False)
+

A simple, un-prepared query.

+

query_string should be a literal CQL statement with the exception +of parameter placeholders that will be filled through the +parameters argument of Session.execute().

+

See Statement attributes for a description of the other parameters.

+
+ +
+
+class cassandra.query.PreparedStatement
+

A statement that has been prepared against at least one Cassandra node. +Instances of this class should not be created directly, but through +Session.prepare().

+

A PreparedStatement should be prepared only once. Re-preparing a statement +may affect performance (as the operation requires a network roundtrip).

+

A note about * in prepared statements: Do not use * in prepared statements if you might +change the schema of the table being queried. The driver and server each +maintain a map between metadata for a schema and statements that were +prepared against that schema. When a user changes a schema, e.g. by adding +or removing a column, the server invalidates its mappings involving that +schema. However, there is currently no way to propagate that invalidation +to drivers. Thus, after a schema change, the driver will incorrectly +interpret the results of SELECT * queries prepared before the schema +change. This is currently being addressed in CASSANDRA-10786.

+
+
+bind(values)
+

Creates and returns a BoundStatement instance using values.

+

See BoundStatement.bind() for rules on input values.

+
+ +
+ +
+
+class cassandra.query.BoundStatement(prepared_statement, retry_policy=None, consistency_level=None, routing_key=None, serial_consistency_level=None, fetch_size=<object object>, keyspace=None, custom_payload=None)
+

A prepared statement that has been bound to a particular set of values. +These may be created directly or through PreparedStatement.bind().

+

prepared_statement should be an instance of PreparedStatement.

+

See Statement attributes for a description of the other parameters.

+
+
+bind(values)
+

Binds a sequence of values for the prepared statement parameters +and returns this instance. Note that values must be:

+
    +
  • a sequence, even if you are only binding one value, or

  • +
  • a dict that relates 1-to-1 between dict keys and columns

  • +
+
+

Changed in version 2.6.0: UNSET_VALUE was introduced. These can be bound as positional parameters +in a sequence, or by name in a dict. Additionally, when using protocol v4+:

+
    +
  • short sequences will be extended to match bind parameters with UNSET_VALUE

  • +
  • names may be omitted from a dict with UNSET_VALUE implied.

  • +
+
+
+

Changed in version 3.0.0: method will not throw if extra keys are present in bound dict (PYTHON-178)

+
+
+ +
+
+property routing_key
+

The partition_key portion of the primary key, +which can be used to determine which nodes are replicas for the query.

+

If the partition key is a composite, a list or tuple must be passed in. +Each key component should be in its packed (binary) format, so all +components should be strings.

+
+ +
+ +
+
+class cassandra.query.Statement
+

An abstract class representing a single query. There are three subclasses: +SimpleStatement, BoundStatement, and BatchStatement. +These can be passed to Session.execute().

+
+
+property routing_key
+

The partition_key portion of the primary key, +which can be used to determine which nodes are replicas for the query.

+

If the partition key is a composite, a list or tuple must be passed in. +Each key component should be in its packed (binary) format, so all +components should be strings.

+
+ +
+
+property serial_consistency_level
+

The serial consistency level is only used by conditional updates +(INSERT, UPDATE and DELETE with an IF condition). For +those, the serial_consistency_level defines the consistency level of +the serial phase (or “paxos” phase) while the normal +consistency_level defines the consistency for the “learn” phase, +i.e. what type of reads will be guaranteed to see the update right away. +For example, if a conditional write has a consistency_level of +QUORUM (and is successful), then a +QUORUM read is guaranteed to see that write. +But if the regular consistency_level of that write is +ANY, then only a read with a +consistency_level of SERIAL is +guaranteed to see it (even a read with consistency +ALL is not guaranteed to be enough).

+

The serial consistency can only be one of SERIAL +or LOCAL_SERIAL. While SERIAL guarantees full +linearizability (with other SERIAL updates), LOCAL_SERIAL only +guarantees it in the local data center.

+

The serial consistency level is ignored for any query that is not a +conditional update. Serial reads should use the regular +consistency_level.

+

Serial consistency levels may only be used against Cassandra 2.0+ +and the protocol_version must be set to 2 or higher.

+

See Lightweight Transactions (Compare-and-set) for a discussion on how to work with results returned from +conditional statements.

+
+

New in version 2.0.0.

+
+
+ +
+ +
+
+cassandra.query.UNSET_VALUE
+

The most base type

+
+ +
+
+class cassandra.query.BatchStatement(batch_type=BatchType.LOGGED, retry_policy=None, consistency_level=None)
+

A protocol-level batch of operations which are applied atomically +by default.

+
+

New in version 2.0.0.

+
+

batch_type specifies The BatchType for the batch operation. +Defaults to BatchType.LOGGED.

+

retry_policy should be a RetryPolicy instance for +controlling retries on the operation.

+

consistency_level should be a ConsistencyLevel value +to be used for all operations in the batch.

+

custom_payload is a Custom Payloads passed to the server. +Note: as Statement objects are added to the batch, this map is +updated with any values found in their custom payloads. These are +only allowed when using protocol version 4 or higher.

+

Example usage:

+
insert_user = session.prepare("INSERT INTO users (name, age) VALUES (?, ?)")
+batch = BatchStatement(consistency_level=ConsistencyLevel.QUORUM)
+
+for (name, age) in users_to_insert:
+    batch.add(insert_user, (name, age))
+
+session.execute(batch)
+
+
+

You can also mix different types of operations within a batch:

+
batch = BatchStatement()
+batch.add(SimpleStatement("INSERT INTO users (name, age) VALUES (%s, %s)"), (name, age))
+batch.add(SimpleStatement("DELETE FROM pending_users WHERE name=%s"), (name,))
+session.execute(batch)
+
+
+
+

New in version 2.0.0.

+
+
+

Changed in version 2.1.0: Added serial_consistency_level as a parameter

+
+
+

Changed in version 2.6.0: Added custom_payload as a parameter

+
+
+
+add(statement, parameters=None)
+

Adds a Statement and optional sequence of parameters +to be used with the statement to the batch.

+

Like with other statements, parameters must be a sequence, even +if there is only one item.

+
+ +
+
+add_all(statements, parameters)
+

Adds a sequence of Statement objects and a matching sequence +of parameters to the batch. Statement and parameter sequences must be of equal length or +one will be truncated. None can be used in the parameters position where are needed.

+
+ +
+
+clear()
+

This is a convenience method to clear a batch statement for reuse.

+

Note: it should not be used concurrently with uncompleted execution futures executing the same +BatchStatement.

+
+ +
+
+serial_consistency_level = None
+
+ +
+ +
+
+class cassandra.query.BatchType
+

A BatchType is used with BatchStatement instances to control +the atomicity of the batch operation.

+
+

New in version 2.0.0.

+
+
+
+LOGGED = BatchType.LOGGED
+
+ +
+
+UNLOGGED = BatchType.UNLOGGED
+
+ +
+
+COUNTER = BatchType.COUNTER
+
+ +
+ +
+
+class cassandra.query.ValueSequence(iterable=(), /)
+

A wrapper class that is used to specify that a sequence of values should +be treated as a CQL list of values instead of a single column collection when used +as part of the parameters argument for Session.execute().

+

This is typically needed when supplying a list of keys to select. +For example:

+
>>> my_user_ids = ('alice', 'bob', 'charles')
+>>> query = "SELECT * FROM users WHERE user_id IN %s"
+>>> session.execute(query, parameters=[ValueSequence(my_user_ids)])
+
+
+
+ +
+
+class cassandra.query.QueryTrace
+

A trace of the duration and events that occurred when executing +an operation.

+
+
+populate(max_wait=2.0, wait_for_complete=True, query_cl=None)
+

Retrieves the actual tracing details from Cassandra and populates the +attributes of this instance. Because tracing details are stored +asynchronously by Cassandra, this may need to retry the session +detail fetch. If the trace is still not available after max_wait +seconds, TraceUnavailable will be raised; if max_wait is +None, this will retry forever.

+

wait_for_complete=False bypasses the wait for duration to be populated. +This can be used to query events from partial sessions.

+

query_cl specifies a consistency level to use for polling the trace tables, +if it should be different than the session default.

+
+ +
+ +
+
+class cassandra.query.TraceEvent
+

Representation of a single event within a query trace.

+
+ +
+
+exception cassandra.query.TraceUnavailable
+

Raised when complete trace details cannot be fetched from Cassandra.

+
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.25.4-scylla/api/cassandra/timestamps.html b/3.25.4-scylla/api/cassandra/timestamps.html new file mode 100644 index 0000000000..898799d0d1 --- /dev/null +++ b/3.25.4-scylla/api/cassandra/timestamps.html @@ -0,0 +1,695 @@ + + + + + + + + + + + + + cassandra.timestamps - Timestamp Generation | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.timestamps - Timestamp Generation

+
+
+class cassandra.timestamps.MonotonicTimestampGenerator(warn_on_drift=True, warning_threshold=0, warning_interval=0)
+

An object that, when called, returns int(time.time() * 1e6) when +possible, but, if the value returned by time.time doesn’t increase, +drifts into the future and logs warnings. +Exposed configuration attributes can be configured with arguments to +__init__ or by changing attributes on an initialized object.

+
+

New in version 3.8.0.

+
+
+
+warn_on_drift = True
+

If true, log warnings when timestamps drift into the future as allowed by +warning_threshold and warning_interval.

+
+ +
+
+warning_threshold = 1
+

This object will only issue warnings when the returned timestamp drifts +more than warning_threshold seconds into the future. +Defaults to 1 second.

+
+ +
+
+warning_interval = 1
+

This object will only issue warnings every warning_interval seconds. +Defaults to 1 second.

+
+ +
+
+_next_timestamp(now, last)
+

Returns the timestamp that should be used if now is the current +time and last is the last timestamp returned by this object. +Intended for internal and testing use only; to generate timestamps, +call an instantiated MonotonicTimestampGenerator object.

+
+
Parameters
+
    +
  • now (int) – an integer to be used as the current time, typically +representing the current time in microseconds since the UNIX epoch

  • +
  • last (int) – an integer representing the last timestamp returned by +this object

  • +
+
+
+
+ +
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.25.4-scylla/api/cassandra/util.html b/3.25.4-scylla/api/cassandra/util.html new file mode 100644 index 0000000000..265de7a988 --- /dev/null +++ b/3.25.4-scylla/api/cassandra/util.html @@ -0,0 +1,1030 @@ + + + + + + + + + + + + + cassandra.util - Utilities | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.util - Utilities

+
+
+class cassandra.util.Date(value)
+

Idealized date: year, month, day

+

Offers wider year range than datetime.date. For Dates that cannot be represented +as a datetime.date (because datetime.MINYEAR, datetime.MAXYEAR), this type falls back +to printing days_from_epoch offset.

+

Initializer value can be:

+
    +
  • integer_type: absolute days from epoch (1970, 1, 1). Can be negative.

  • +
  • datetime.date: built-in date

  • +
  • string_type: a string time of the form “yyyy-mm-dd”

  • +
+
+
+date()
+

Return a built-in datetime.date for Dates falling in the years [datetime.MINYEAR, datetime.MAXYEAR]

+

ValueError is raised for Dates outside this range.

+
+ +
+
+property seconds
+

Absolute seconds from epoch (can be negative)

+
+ +
+ +
+
+class cassandra.util.DateRange(lower_bound=None, upper_bound=None, value=None)
+

DSE DateRange Type

+
+
+lower_bound
+

DateRangeBound representing the lower bound of a bounded range.

+
+ +
+
+upper_bound
+

DateRangeBound representing the upper bound of a bounded range.

+
+ +
+
+value
+

DateRangeBound representing the value of a single-value range.

+
+ +

As noted in its documentation, DateRangeBound uses a millisecond +offset from the UNIX epoch to allow DateRange to represent values +datetime.datetime cannot. For such values, string representions will show +this offset rather than the CQL representation.

+
+
Parameters
+
+
+
+
+ +
+
+class cassandra.util.DateRangeBound(value, precision)
+

Represents a single date value and its precision for DateRange.

+
+
+milliseconds
+

Integer representing milliseconds since the UNIX epoch. May be negative.

+
+ +
+
+precision
+

String representing the precision of a bound. Must be a valid +DateRangePrecision member.

+
+ +

DateRangeBound uses a millisecond offset from the UNIX epoch to +allow DateRange to represent values datetime.datetime cannot. +For such values, string representions will show this offset rather than the +CQL representation.

+
+
Parameters
+
    +
  • value – a value representing ms since the epoch. Accepts an +integer or a datetime.

  • +
  • precision – a string representing precision

  • +
+
+
+
+
+datetime()
+

Return milliseconds as a datetime.datetime if possible. +Raises an OverflowError if the value is out of range.

+
+ +
+
+classmethod from_value(value)
+

Construct a new DateRangeBound from a given value. If +possible, use the value[‘milliseconds’] and value[‘precision’] keys +of the argument. Otherwise, use the argument as a (milliseconds, +precision) iterable.

+
+
Parameters
+

value – a dictlike or iterable object

+
+
+
+ +
+ +
+
+class cassandra.util.DateRangePrecision
+

An “enum” representing the valid values for DateRange.precision.

+
+ +
+
+class cassandra.util.Distance(x=nan, y=nan, radius=nan)
+

Represents a Distance geometry for DSE

+
+
+static from_wkt(s)
+

Parse a Distance geometry from a wkt string and return a new Distance object.

+
+ +
+ +
+
+class cassandra.util.Duration(months=0, days=0, nanoseconds=0)
+

Cassandra Duration Type

+
+ +
+
+class cassandra.util.LineString(coords=())
+

Represents a linestring geometry for DSE

+

‘coords`: a sequence of (x, y) coordinates of points in the linestring

+
+
+static from_wkt(s)
+

Parse a LineString geometry from a wkt string and return a new LineString object.

+
+ +
+ +
+
+class cassandra.util.OrderedMap(*args, **kwargs)
+

An ordered map that accepts non-hashable types for keys. It also maintains the +insertion order of items, behaving as OrderedDict in that regard. These maps +are constructed and read just as normal mapping types, except that they may +contain arbitrary collections and other non-hashable items as keys:

+
>>> od = OrderedMap([({'one': 1, 'two': 2}, 'value'),
+...                  ({'three': 3, 'four': 4}, 'value2')])
+>>> list(od.keys())
+[{'two': 2, 'one': 1}, {'three': 3, 'four': 4}]
+>>> list(od.values())
+['value', 'value2']
+
+
+

These constructs are needed to support nested collections in Cassandra 2.1.3+, +where frozen collections can be specified as parameters to others:

+
CREATE TABLE example (
+    ...
+    value map<frozen<map<int, int>>, double>
+    ...
+)
+
+
+

This class derives from the (immutable) Mapping API. Objects in these maps +are not intended be modified.

+
+ +
+
+class cassandra.util.OrderedMapSerializedKey(cass_type, protocol_version)
+
+ +
+
+class cassandra.util.Point(x=nan, y=nan)
+

Represents a point geometry for DSE

+
+
+static from_wkt(s)
+

Parse a Point geometry from a wkt string and return a new Point object.

+
+ +
+ +
+
+class cassandra.util.Polygon(exterior=(), interiors=None)
+

Represents a polygon geometry for DSE

+

‘exterior`: a sequence of (x, y) coordinates of points in the linestring +interiors: None, or a sequence of sequences or (x, y) coordinates of points describing interior linear rings

+
+
+static from_wkt(s)
+

Parse a Polygon geometry from a wkt string and return a new Polygon object.

+
+ +
+ +
+
+class cassandra.util.SortedSet(iterable=())
+

A sorted set based on sorted list

+

A sorted set implementation is used in this case because it does not +require its elements to be immutable/hashable.

+

#Not implemented: update functions, inplace operators

+
+ +
+
+class cassandra.util.Time(value)
+

Idealized time, independent of day.

+

Up to nanosecond resolution

+

Initializer value can be:

+
    +
  • integer_type: absolute nanoseconds in the day

  • +
  • datetime.time: built-in time

  • +
  • string_type: a string time of the form “HH:MM:SS[.mmmuuunnn]”

  • +
+
+
+property hour
+

The hour component of this time (0-23)

+
+ +
+
+property minute
+

The minute component of this time (0-59)

+
+ +
+
+property nanosecond
+

The fractional seconds component of the time, in nanoseconds

+
+ +
+
+property second
+

The second component of this time (0-59)

+
+ +
+
+time()
+

Return a built-in datetime.time (nanosecond precision truncated to micros).

+
+ +
+ +
+
+class cassandra.util.Version(version)
+

Internal minimalist class to compare versions. +A valid version is: <int>.<int>.<int>.<int or str>.

+

TODO: when python2 support is removed, use packaging.version.

+
+ +
+
+cassandra.util.datetime_from_timestamp(timestamp)
+

Creates a timezone-agnostic datetime from timestamp (in seconds) in a consistent manner. +Works around a Windows issue with large negative timestamps (PYTHON-119), +and rounding differences in Python 3.4 (PYTHON-340).

+
+
Parameters
+

timestamp – a unix timestamp, in seconds

+
+
+
+ +
+
+cassandra.util.datetime_from_uuid1(uuid_arg)
+

Creates a timezone-agnostic datetime from the timestamp in the +specified type-1 UUID.

+
+
Parameters
+

uuid_arg – a version 1 UUID

+
+
+
+ +
+
+cassandra.util.max_uuid_from_time(timestamp)
+

Generates the maximum TimeUUID (type 1) for a given timestamp, as compared by Cassandra.

+

See uuid_from_time() for argument and return types.

+
+ +
+
+cassandra.util.min_uuid_from_time(timestamp)
+

Generates the minimum TimeUUID (type 1) for a given timestamp, as compared by Cassandra.

+

See uuid_from_time() for argument and return types.

+
+ +
+
+cassandra.util.ms_timestamp_from_datetime(dt)
+

Converts a datetime to a timestamp expressed in milliseconds.

+
+
Parameters
+

dt – a datetime.datetime

+
+
+
+ +
+
+cassandra.util.sortedset
+

alias of cassandra.util.SortedSet

+
+ +
+
+cassandra.util.unix_time_from_uuid1(uuid_arg)
+

Converts a version 1 uuid.UUID to a timestamp with the same precision +as time.time() returns. This is useful for examining the +results of queries returning a v1 UUID.

+
+
Parameters
+

uuid_arg – a version 1 UUID

+
+
+
+ +
+
+cassandra.util.utc_datetime_from_ms_timestamp(timestamp)
+

Creates a UTC datetime from a timestamp in milliseconds. See +datetime_from_timestamp().

+

Raises an OverflowError if the timestamp is out of range for +datetime.

+
+
Parameters
+

timestamp – timestamp, in milliseconds

+
+
+
+ +
+
+cassandra.util.uuid_from_time(time_arg, node=None, clock_seq=None)
+

Converts a datetime or timestamp to a type 1 uuid.UUID.

+
+
Parameters
+
    +
  • time_arg – The time to use for the timestamp portion of the UUID. +This can either be a datetime object or a timestamp +in seconds (as returned from time.time()).

  • +
  • node (long) – None integer for the UUID (up to 48 bits). If not specified, this +field is randomized.

  • +
  • clock_seq (int) – Clock sequence field for the UUID (up to 14 bits). If not specified, +a random sequence is generated.

  • +
+
+
Return type
+

uuid.UUID

+
+
+
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.25.4-scylla/api/index.html b/3.25.4-scylla/api/index.html new file mode 100644 index 0000000000..3be4f0c6cb --- /dev/null +++ b/3.25.4-scylla/api/index.html @@ -0,0 +1,716 @@ + + + + + + + + + + + + + API Documentation | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

API Documentation

+
+

Core Driver

+ +
+
+

Object Mapper

+ +
+
+

DataStax Graph

+ +
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.25.4-scylla/cqlengine/batches.html b/3.25.4-scylla/cqlengine/batches.html new file mode 100644 index 0000000000..2bce814c31 --- /dev/null +++ b/3.25.4-scylla/cqlengine/batches.html @@ -0,0 +1,746 @@ + + + + + + + + + + + + + Batch Queries | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + + + +
+

Batch Queries

+

cqlengine supports batch queries using the BatchQuery class. Batch queries can be started and stopped manually, or within a context manager. To add queries to the batch object, you just need to precede the create/save/delete call with a call to batch, and pass in the batch object.

+
+

Batch Query General Use Pattern

+

You can only create, update, and delete rows with a batch query, attempting to read rows out of the database with a batch query will fail.

+
from cassandra.cqlengine.query import BatchQuery
+
+#using a context manager
+with BatchQuery() as b:
+    now = datetime.now()
+    em1 = ExampleModel.batch(b).create(example_type=0, description="1", created_at=now)
+    em2 = ExampleModel.batch(b).create(example_type=0, description="2", created_at=now)
+    em3 = ExampleModel.batch(b).create(example_type=0, description="3", created_at=now)
+
+# -- or --
+
+#manually
+b = BatchQuery()
+now = datetime.now()
+em1 = ExampleModel.batch(b).create(example_type=0, description="1", created_at=now)
+em2 = ExampleModel.batch(b).create(example_type=0, description="2", created_at=now)
+em3 = ExampleModel.batch(b).create(example_type=0, description="3", created_at=now)
+b.execute()
+
+# updating in a batch
+
+b = BatchQuery()
+em1.description = "new description"
+em1.batch(b).save()
+em2.description = "another new description"
+em2.batch(b).save()
+b.execute()
+
+# deleting in a batch
+b = BatchQuery()
+ExampleModel.objects(id=some_id).batch(b).delete()
+ExampleModel.objects(id=some_id2).batch(b).delete()
+b.execute()
+
+
+

Typically you will not want the block to execute if an exception occurs inside the with block. However, in the case that this is desirable, it’s achievable by using the following syntax:

+
with BatchQuery(execute_on_exception=True) as b:
+    LogEntry.batch(b).create(k=1, v=1)
+    mystery_function() # exception thrown in here
+    LogEntry.batch(b).create(k=1, v=2) # this code is never reached due to the exception, but anything leading up to here will execute in the batch.
+
+
+

If an exception is thrown somewhere in the block, any statements that have been added to the batch will still be executed. This is useful for some logging situations.

+
+
+

Batch Query Execution Callbacks

+

In order to allow secondary tasks to be chained to the end of batch, BatchQuery instances allow callbacks to be +registered with the batch, to be executed immediately after the batch executes.

+

Multiple callbacks can be attached to same BatchQuery instance, they are executed in the same order that they +are added to the batch.

+

The callbacks attached to a given batch instance are executed only if the batch executes. If the batch is used as a +context manager and an exception is raised, the queued up callbacks will not be run.

+
def my_callback(*args, **kwargs):
+    pass
+
+batch = BatchQuery()
+
+batch.add_callback(my_callback)
+batch.add_callback(my_callback, 'positional arg', named_arg='named arg value')
+
+# if you need reference to the batch within the callback,
+# just trap it in the arguments to be passed to the callback:
+batch.add_callback(my_callback, cqlengine_batch=batch)
+
+# once the batch executes...
+batch.execute()
+
+# the effect of the above scheduled callbacks will be similar to
+my_callback()
+my_callback('positional arg', named_arg='named arg value')
+my_callback(cqlengine_batch=batch)
+
+
+

Failure in any of the callbacks does not affect the batch’s execution, as the callbacks are started after the execution +of the batch is complete.

+
+

Logged vs Unlogged Batches

+

By default, queries in cqlengine are LOGGED, which carries additional overhead from UNLOGGED. To explicitly state which batch type to use, simply:

+
from cassandra.cqlengine.query import BatchType
+with BatchQuery(batch_type=BatchType.Unlogged) as b:
+    LogEntry.batch(b).create(k=1, v=1)
+    LogEntry.batch(b).create(k=1, v=2)
+
+
+
+
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.25.4-scylla/cqlengine/connections.html b/3.25.4-scylla/cqlengine/connections.html new file mode 100644 index 0000000000..4b56c64c26 --- /dev/null +++ b/3.25.4-scylla/cqlengine/connections.html @@ -0,0 +1,770 @@ + + + + + + + + + + + + + Connections | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + + + +
+

Connections

+

Connections aim to ease the use of multiple sessions with cqlengine. Connections can be set on a model class, per query or using a context manager.

+
+

Register a new connection

+

To use cqlengine, you need at least a default connection. If you initialize cqlengine’s connections with with connection.setup, a connection will be created automatically. If you want to use another cluster/session, you need to register a new cqlengine connection. You register a connection with register_connection():

+
from cassandra.cqlengine import connection
+
+connection.setup(['127.0.0.1')
+connection.register_connection('cluster2', ['127.0.0.2'])
+
+
+

register_connection() can take a list of hosts, as shown above, in which case it will create a connection with a new session. It can also take a session argument if you’ve already created a session:

+
from cassandra.cqlengine import connection
+from cassandra.cluster import Cluster
+
+session = Cluster(['127.0.0.1']).connect()
+connection.register_connection('cluster3', session=session)
+
+
+
+
+

Change the default connection

+

You can change the default cqlengine connection on registration:

+
from cassandra.cqlengine import connection
+
+connection.register_connection('cluster2', ['127.0.0.2'] default=True)
+
+
+

or on the fly using set_default_connection()

+
connection.set_default_connection('cluster2')
+
+
+
+
+

Unregister a connection

+

You can unregister a connection using unregister_connection():

+
connection.unregister_connection('cluster2')
+
+
+
+
+

Management

+

When using multiples connections, you also need to sync your models on all connections (and keyspaces) that you need operate on. Management commands have been improved to ease this part. Here is an example:

+
from cassandra.cqlengine import management
+
+keyspaces = ['ks1', 'ks2']
+conns = ['cluster1', 'cluster2']
+
+# registers your connections
+# ...
+
+# create all keyspaces on all connections
+for ks in keyspaces:
+    management.create_simple_keyspace(ks, connections=conns)
+
+# define your Automobile model
+# ...
+
+# sync your models
+management.sync_table(Automobile, keyspaces=keyspaces, connections=conns)
+
+
+
+
+

Connection Selection

+

cqlengine will select the default connection, unless your specify a connection using one of the following methods.

+
+

Default Model Connection

+

You can specify a default connection per model:

+
class Automobile(Model):
+    __keyspace__ = 'test'
+    __connection__ = 'cluster2'
+    manufacturer = columns.Text(primary_key=True)
+    year = columns.Integer(primary_key=True)
+    model = columns.Text(primary_key=True)
+
+print len(Automobile.objects.all())  # executed on the connection 'cluster2'
+
+
+
+
+

QuerySet and model instance

+

You can use the using() method to select a connection (or keyspace):

+
Automobile.objects.using(connection='cluster1').create(manufacturer='honda', year=2010, model='civic')
+q = Automobile.objects.filter(manufacturer='Tesla')
+autos = q.using(keyspace='ks2', connection='cluster2').all()
+
+for auto in autos:
+    auto.using(connection='cluster1').save()
+
+
+
+
+

Context Manager

+

You can use the ContextQuery as well to select a connection:

+
with ContextQuery(Automobile, connection='cluster1') as A:
+    A.objects.filter(manufacturer='honda').all()  # executed on 'cluster1'
+
+
+
+
+

BatchQuery

+

With a BatchQuery, you can select the connection with the context manager. Note that all operations in the batch need to use the same connection.

+
with BatchQuery(connection='cluster1') as b:
+    Automobile.objects.batch(b).create(manufacturer='honda', year=2010, model='civic')
+
+
+
+
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.25.4-scylla/cqlengine/faq.html b/3.25.4-scylla/cqlengine/faq.html new file mode 100644 index 0000000000..0392a56ae1 --- /dev/null +++ b/3.25.4-scylla/cqlengine/faq.html @@ -0,0 +1,710 @@ + + + + + + + + + + + + + Frequently Asked Questions | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

Frequently Asked Questions

+
+

Why don’t updates work correctly on models instantiated as Model(field=value, field2=value2)?

+

The recommended way to create new rows is with the models .create method. The values passed into a model’s init method are interpreted by the model as the values as they were read from a row. This allows the model to “know” which rows have changed since the row was read out of cassandra, and create suitable update statements.

+
+
+

How to preserve ordering in batch query?

+

Statement Ordering is not supported by CQL3 batches. Therefore, +once cassandra needs resolving conflict(Updating the same column in one batch), +The algorithm below would be used.

+
    +
  • If timestamps are different, pick the column with the largest timestamp (the value being a regular column or a tombstone)

  • +
  • If timestamps are the same, and one of the columns in a tombstone (‘null’) - pick the tombstone

  • +
  • If timestamps are the same, and none of the columns are tombstones, pick the column with the largest value

  • +
+

Below is an example to show this scenario.

+
class MyMode(Model):
+    id    = columns.Integer(primary_key=True)
+    count = columns.Integer()
+    text  = columns.Text()
+
+with BatchQuery() as b:
+   MyModel.batch(b).create(id=1, count=2, text='123')
+   MyModel.batch(b).create(id=1, count=3, text='111')
+
+assert MyModel.objects(id=1).first().count == 3
+assert MyModel.objects(id=1).first().text  == '123'
+
+
+

The largest value of count is 3, and the largest value of text would be ‘123’.

+

The workaround is applying timestamp to each statement, then Cassandra would +resolve to the statement with the lastest timestamp.

+
with BatchQuery() as b:
+    MyModel.timestamp(datetime.now()).batch(b).create(id=1, count=2, text='123')
+    MyModel.timestamp(datetime.now()).batch(b).create(id=1, count=3, text='111')
+
+assert MyModel.objects(id=1).first().count == 3
+assert MyModel.objects(id=1).first().text  == '111'
+
+
+
+
+

How can I delete individual values from a row?

+

When inserting with CQLEngine, None is equivalent to CQL NULL or to +issuing a DELETE on that column. For example:

+
class MyModel(Model):
+    id    = columns.Integer(primary_key=True)
+    text  = columns.Text()
+
+m = MyModel.create(id=1, text='We can delete this with None')
+assert MyModel.objects(id=1).first().text is not None
+
+m.update(text=None)
+assert MyModel.objects(id=1).first().text is None
+
+
+
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.25.4-scylla/cqlengine/models.html b/3.25.4-scylla/cqlengine/models.html new file mode 100644 index 0000000000..dfd3a8642c --- /dev/null +++ b/3.25.4-scylla/cqlengine/models.html @@ -0,0 +1,835 @@ + + + + + + + + + + + + + Models | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + + + +
+

Models

+

A model is a python class representing a CQL table. Models derive from Model, and +define basic table properties and columns for a table.

+

Columns in your models map to columns in your CQL table. You define CQL columns by defining column attributes on your model classes. +For a model to be valid it needs at least one primary key column and one non-primary key column. Just as in CQL, the order you define +your columns in is important, and is the same order they are defined in on a model’s corresponding table.

+

Some basic examples defining models are shown below. Consult the Model API docs and Column API docs for complete details.

+
+

Example Definitions

+

This example defines a Person table, with the columns first_name and last_name

+
from cassandra.cqlengine import columns
+from cassandra.cqlengine.models import Model
+
+ class Person(Model):
+     id = columns.UUID(primary_key=True)
+     first_name  = columns.Text()
+     last_name = columns.Text()
+
+
+

The Person model would create this CQL table:

+
CREATE TABLE cqlengine.person (
+    id uuid,
+    first_name text,
+    last_name text,
+    PRIMARY KEY (id)
+);
+
+
+

Here’s an example of a comment table created with clustering keys, in descending order:

+
from cassandra.cqlengine import columns
+from cassandra.cqlengine.models import Model
+
+class Comment(Model):
+    photo_id = columns.UUID(primary_key=True)
+    comment_id = columns.TimeUUID(primary_key=True, clustering_order="DESC")
+    comment = columns.Text()
+
+
+

The Comment model’s create table would look like the following:

+
CREATE TABLE comment (
+  photo_id uuid,
+  comment_id timeuuid,
+  comment text,
+  PRIMARY KEY (photo_id, comment_id)
+) WITH CLUSTERING ORDER BY (comment_id DESC);
+
+
+

To sync the models to the database, you may do the following*:

+
from cassandra.cqlengine.management import sync_table
+sync_table(Person)
+sync_table(Comment)
+
+
+

*Note: synchronizing models causes schema changes, and should be done with caution. +Please see the discussion in cassandra.cqlengine.management - Schema management for cqlengine for considerations.

+

For examples on manipulating data and creating queries, see Making Queries

+
+
+

Manipulating model instances as dictionaries

+

Model instances can be accessed like dictionaries.

+
class Person(Model):
+    first_name  = columns.Text()
+    last_name = columns.Text()
+
+kevin = Person.create(first_name="Kevin", last_name="Deldycke")
+dict(kevin)  # returns {'first_name': 'Kevin', 'last_name': 'Deldycke'}
+kevin['first_name']  # returns 'Kevin'
+kevin.keys()  # returns ['first_name', 'last_name']
+kevin.values()  # returns ['Kevin', 'Deldycke']
+kevin.items()  # returns [('first_name', 'Kevin'), ('last_name', 'Deldycke')]
+
+kevin['first_name'] = 'KEVIN5000'  # changes the models first name
+
+
+
+
+

Extending Model Validation

+

Each time you save a model instance in cqlengine, the data in the model is validated against the schema you’ve defined +for your model. Most of the validation is fairly straightforward, it basically checks that you’re not trying to do +something like save text into an integer column, and it enforces the required flag set on column definitions. +It also performs any transformations needed to save the data properly.

+

However, there are often additional constraints or transformations you want to impose on your data, beyond simply +making sure that Cassandra won’t complain when you try to insert it. To define additional validation on a model, +extend the model’s validation method:

+
class Member(Model):
+    person_id = UUID(primary_key=True)
+    name = Text(required=True)
+
+    def validate(self):
+        super(Member, self).validate()
+        if self.name == 'jon':
+            raise ValidationError('no jon\'s allowed')
+
+
+

Note: while not required, the convention is to raise a ValidationError (from cassandra.cqlengine import ValidationError) +if validation fails.

+
+
+

Model Inheritance

+

It is possible to save and load different model classes using a single CQL table. +This is useful in situations where you have different object types that you want to store in a single cassandra row.

+

For instance, suppose you want a table that stores rows of pets owned by an owner:

+
class Pet(Model):
+    __table_name__ = 'pet'
+    owner_id = UUID(primary_key=True)
+    pet_id = UUID(primary_key=True)
+    pet_type = Text(discriminator_column=True)
+    name = Text()
+
+    def eat(self, food):
+        pass
+
+    def sleep(self, time):
+        pass
+
+class Cat(Pet):
+    __discriminator_value__ = 'cat'
+    cuteness = Float()
+
+    def tear_up_couch(self):
+        pass
+
+class Dog(Pet):
+    __discriminator_value__ = 'dog'
+    fierceness = Float()
+
+    def bark_all_night(self):
+        pass
+
+
+

After calling sync_table on each of these tables, the columns defined in each model will be added to the +pet table. Additionally, saving Cat and Dog models will save the meta data needed to identify each row +as either a cat or dog.

+

To setup a model structure with inheritance, follow these steps

+
    +
  1. Create a base model with a column set as the distriminator (distriminator_column=True in the column definition)

  2. +
  3. Create subclass models, and define a unique __discriminator_value__ value on each

  4. +
  5. Run sync_table on each of the sub tables

  6. +
+

About the discriminator value

+

The discriminator value is what cqlengine uses under the covers to map logical cql rows to the appropriate model type. The +base model maintains a map of discriminator values to subclasses. When a specialized model is saved, its discriminator value is +automatically saved into the discriminator column. The discriminator column may be any column type except counter and container types. +Additionally, if you set index=True on your discriminator column, you can execute queries against specialized subclasses, and a +WHERE clause will be automatically added to your query, returning only rows of that type. Note that you must +define a unique __discriminator_value__ to each subclass, and that you can only assign a single discriminator column per model.

+
+
+

User Defined Types

+

cqlengine models User Defined Types (UDTs) much like tables, with fields defined by column type attributes. However, UDT instances +are only created, presisted, and queried via table Models. A short example to introduce the pattern:

+
from cassandra.cqlengine.columns import *
+from cassandra.cqlengine.models import Model
+from cassandra.cqlengine.usertype import UserType
+
+class address(UserType):
+    street = Text()
+    zipcode = Integer()
+
+class users(Model):
+    __keyspace__ = 'account'
+    name = Text(primary_key=True)
+    addr = UserDefinedType(address)
+
+users.create(name="Joe", addr=address(street="Easy St.", zipcode=99999))
+user = users.objects(name="Joe")[0]
+print user.name, user.addr
+# Joe address(street=u'Easy St.', zipcode=99999)
+
+
+

UDTs are modeled by inheriting UserType, and setting column type attributes. Types are then used in defining +models by declaring a column of type UserDefinedType, with the UserType class as a parameter.

+

sync_table will implicitly +synchronize any types contained in the table. Alternatively sync_type() can be used to create/alter types +explicitly.

+

Upon declaration, types are automatically registered with the driver, so query results return instances of your UserType +class*.

+

*Note: UDTs were not added to the native protocol until v3. When setting up the cqlengine connection, be sure to specify +protocol_version=3. If using an earlier version, UDT queries will still work, but the returned type will be a namedtuple.

+
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.25.4-scylla/cqlengine/queryset.html b/3.25.4-scylla/cqlengine/queryset.html new file mode 100644 index 0000000000..e3e8511643 --- /dev/null +++ b/3.25.4-scylla/cqlengine/queryset.html @@ -0,0 +1,1007 @@ + + + + + + + + + + + + + Making Queries | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

Making Queries

+
+

Retrieving objects

+

Once you’ve populated Cassandra with data, you’ll probably want to retrieve some of it. This is accomplished with QuerySet objects. This section will describe how to use QuerySet objects to retrieve the data you’re looking for.

+
+

Retrieving all objects

+

The simplest query you can make is to return all objects from a table.

+

This is accomplished with the .all() method, which returns a QuerySet of all objects in a table

+

Using the Person example model, we would get all Person objects like this:

+
all_objects = Person.objects.all()
+
+
+
+
+

Retrieving objects with filters

+

Typically, you’ll want to query only a subset of the records in your database.

+

That can be accomplished with the QuerySet’s .filter(\*\*) method.

+

For example, given the model definition:

+
class Automobile(Model):
+    manufacturer = columns.Text(primary_key=True)
+    year = columns.Integer(primary_key=True)
+    model = columns.Text()
+    price = columns.Decimal()
+    options = columns.Set(columns.Text)
+
+
+

…and assuming the Automobile table contains a record of every car model manufactured in the last 20 years or so, we can retrieve only the cars made by a single manufacturer like this:

+
q = Automobile.objects.filter(manufacturer='Tesla')
+
+
+

You can also use the more convenient syntax:

+
q = Automobile.objects(Automobile.manufacturer == 'Tesla')
+
+
+

We can then further filter our query with another call to .filter

+
q = q.filter(year=2012)
+
+
+

Note: all queries involving any filtering MUST define either an ‘=’ or an ‘in’ relation to either a primary key column, or an indexed column.

+
+
+
+

Accessing objects in a QuerySet

+

There are several methods for getting objects out of a queryset

+
    +
  • +
    iterating over the queryset
    for car in Automobile.objects.all():
    +    #...do something to the car instance
    +    pass
    +
    +
    +
    +
    +
  • +
  • +
    list index
    q = Automobile.objects.all()
    +q[0] #returns the first result
    +q[1] #returns the second result
    +
    +
    +
    +

    Note

    +
      +
    • CQL does not support specifying a start position in it’s queries. Therefore, accessing elements using array indexing will load every result up to the index value requested

    • +
    • Using negative indices requires a “SELECT COUNT()” to be executed. This has a performance cost on large datasets.

    • +
    +
    +
    +
    +
  • +
  • +
    list slicing
    q = Automobile.objects.all()
    +q[1:] #returns all results except the first
    +q[1:9] #returns a slice of the results
    +
    +
    +
    +

    Note

    +
      +
    • CQL does not support specifying a start position in it’s queries. Therefore, accessing elements using array slicing will load every result up to the index value requested

    • +
    • Using negative indices requires a “SELECT COUNT()” to be executed. This has a performance cost on large datasets.

    • +
    +
    +
    +
    +
  • +
  • +
    calling get() on the queryset
    q = Automobile.objects.filter(manufacturer='Tesla')
    +q = q.filter(year=2012)
    +car = q.get()
    +
    +
    +

    this returns the object matching the queryset

    +
    +
    +
  • +
  • +
    calling first() on the queryset
    q = Automobile.objects.filter(manufacturer='Tesla')
    +q = q.filter(year=2012)
    +car = q.first()
    +
    +
    +

    this returns the first value in the queryset

    +
    +
    +
  • +
+
+
+

Filtering Operators

+

Equal To

+

The default filtering operator.

+
q = Automobile.objects.filter(manufacturer='Tesla')
+q = q.filter(year=2012)  #year == 2012
+
+
+

In addition to simple equal to queries, cqlengine also supports querying with other operators by appending a __<op> to the field name on the filtering call

+

in (__in)

+
q = Automobile.objects.filter(manufacturer='Tesla')
+q = q.filter(year__in=[2011, 2012])
+
+
+

> (__gt)

+
q = Automobile.objects.filter(manufacturer='Tesla')
+q = q.filter(year__gt=2010)  # year > 2010
+
+# or the nicer syntax
+
+q.filter(Automobile.year > 2010)
+
+
+

>= (__gte)

+
q = Automobile.objects.filter(manufacturer='Tesla')
+q = q.filter(year__gte=2010)  # year >= 2010
+
+# or the nicer syntax
+
+q.filter(Automobile.year >= 2010)
+
+
+

< (__lt)

+
q = Automobile.objects.filter(manufacturer='Tesla')
+q = q.filter(year__lt=2012)  # year < 2012
+
+# or...
+
+q.filter(Automobile.year < 2012)
+
+
+

<= (__lte)

+
q = Automobile.objects.filter(manufacturer='Tesla')
+q = q.filter(year__lte=2012)  # year <= 2012
+
+q.filter(Automobile.year <= 2012)
+
+
+

CONTAINS (__contains)

+

The CONTAINS operator is available for all collection types (List, Set, Map).

+
q = Automobile.objects.filter(manufacturer='Tesla')
+q.filter(options__contains='backup camera').allow_filtering()
+
+
+

Note that we need to use allow_filtering() since the options column has no secondary index.

+

LIKE (__like)

+

The LIKE operator is available for text columns that have a SASI secondary index.

+
q = Automobile.objects.filter(model__like='%Civic%').allow_filtering()
+
+
+

IS NOT NULL (IsNotNull(column_name))

+

The IS NOT NULL operator is not yet supported for C*.

+
q = Automobile.objects.filter(IsNotNull('model'))
+
+
+

Limitations:

+
    +
  • Currently, cqlengine does not support SASI index creation. To use this feature, you need to create the SASI index using the core driver.

  • +
  • Queries using LIKE must use allow_filtering() since the model column has no standard secondary index. Note that the server will use the SASI index properly when executing the query.

  • +
+
+
+

TimeUUID Functions

+

In addition to querying using regular values, there are two functions you can pass in when querying TimeUUID columns to help make filtering by them easier. Note that these functions don’t actually return a value, but instruct the cql interpreter to use the functions in it’s query.

+
+
+class cqlengine.queryset.MinTimeUUID(datetime)
+

returns the minimum time uuid value possible for the given datetime

+
+ +
+
+class cqlengine.queryset.MaxTimeUUID(datetime)
+

returns the maximum time uuid value possible for the given datetime

+
+ +

Example

+
class DataStream(Model):
+    id      = columns.UUID(partition_key=True)
+    time    = columns.TimeUUID(primary_key=True)
+    data    = columns.Bytes()
+
+min_time = datetime(1982, 1, 1)
+max_time = datetime(1982, 3, 9)
+
+DataStream.filter(time__gt=functions.MinTimeUUID(min_time), time__lt=functions.MaxTimeUUID(max_time))
+
+
+
+
+

Token Function

+

Token functon may be used only on special, virtual column pk__token, representing token of partition key (it also works for composite partition keys). +Cassandra orders returned items by value of partition key token, so using cqlengine.Token we can easy paginate through all table rows.

+

See http://cassandra.apache.org/doc/cql3/CQL-3.0.html#tokenFun

+

Example

+
class Items(Model):
+    id      = columns.Text(primary_key=True)
+    data    = columns.Bytes()
+
+query = Items.objects.all().limit(10)
+
+first_page = list(query);
+last = first_page[-1]
+next_page = list(query.filter(pk__token__gt=cqlengine.Token(last.pk)))
+
+
+
+
+

QuerySets are immutable

+

When calling any method that changes a queryset, the method does not actually change the queryset object it’s called on, but returns a new queryset object with the attributes of the original queryset, plus the attributes added in the method call.

+

Example

+
#this produces 3 different querysets
+#q does not change after it's initial definition
+q = Automobiles.objects.filter(year=2012)
+tesla2012 = q.filter(manufacturer='Tesla')
+honda2012 = q.filter(manufacturer='Honda')
+
+
+
+
+

Ordering QuerySets

+

Since Cassandra is essentially a distributed hash table on steroids, the order you get records back in will not be particularly predictable.

+

However, you can set a column to order on with the .order_by(column_name) method.

+

Example

+
#sort ascending
+q = Automobiles.objects.all().order_by('year')
+#sort descending
+q = Automobiles.objects.all().order_by('-year')
+
+
+

Note: Cassandra only supports ordering on a clustering key. In other words, to support ordering results, your model must have more than one primary key, and you must order on a primary key, excluding the first one.

+

For instance, given our Automobile model, year is the only column we can order on.

+
+
+

Values Lists

+

There is a special QuerySet’s method .values_list() - when called, QuerySet returns lists of values instead of model instances. It may significantly speedup things with lower memory footprint for large responses. +Each tuple contains the value from the respective field passed into the values_list() call — so the first item is the first field, etc. For example:

+
items = list(range(20))
+random.shuffle(items)
+for i in items:
+    TestModel.create(id=1, clustering_key=i)
+
+values = list(TestModel.objects.values_list('clustering_key', flat=True))
+# [19L, 18L, 17L, 16L, 15L, 14L, 13L, 12L, 11L, 10L, 9L, 8L, 7L, 6L, 5L, 4L, 3L, 2L, 1L, 0L]
+
+
+
+
+

Per Query Timeouts

+

By default all queries are executed with the timeout defined in ~cqlengine.connection.setup() +The examples below show how to specify a per-query timeout. +A timeout is specified in seconds and can be an int, float or None. +None means no timeout.

+
class Row(Model):
+    id = columns.Integer(primary_key=True)
+    name = columns.Text()
+
+
+

Fetch all objects with a timeout of 5 seconds

+
Row.objects().timeout(5).all()
+
+
+

Create a single row with a 50ms timeout

+
Row(id=1, name='Jon').timeout(0.05).create()
+
+
+

Delete a single row with no timeout

+
Row(id=1).timeout(None).delete()
+
+
+

Update a single row with no timeout

+
Row(id=1).timeout(None).update(name='Blake')
+
+
+

Batch query timeouts

+
with BatchQuery(timeout=10) as b:
+    Row(id=1, name='Jon').create()
+
+
+

NOTE: You cannot set both timeout and batch at the same time, batch will use the timeout defined in it’s constructor. +Setting the timeout on the model is meaningless and will raise an AssertionError.

+
+
+

Default TTL and Per Query TTL

+

Model default TTL now relies on the default_time_to_live feature, introduced in Cassandra 2.0. It is not handled anymore in the CQLEngine Model (scylla-driver >=3.6). You can set the default TTL of a table like this:

+

Example:

+
class User(Model):
+    __options__ = {'default_time_to_live': 20}
+
+    user_id = columns.UUID(primary_key=True)
+    ...
+
+
+

You can set TTL per-query if needed. Here are a some examples:

+

Example:

+
class User(Model):
+    __options__ = {'default_time_to_live': 20}
+
+    user_id = columns.UUID(primary_key=True)
+    ...
+
+user = User.objects.create(user_id=1)  # Default TTL 20 will be set automatically on the server
+
+user.ttl(30).update(age=21)            # Update the TTL to 30
+User.objects.ttl(10).create(user_id=1)  # TTL 10
+User(user_id=1, age=21).ttl(10).save()  # TTL 10
+
+
+
+
+

Named Tables

+

Named tables are a way of querying a table without creating an class. They’re useful for querying system tables or exploring an unfamiliar database.

+
from cassandra.cqlengine.connection import setup
+setup("127.0.0.1", "cqlengine_test")
+
+from cassandra.cqlengine.named import NamedTable
+user = NamedTable("cqlengine_test", "user")
+user.objects()
+user.objects()[0]
+
+# {u'pk': 1, u't': datetime.datetime(2014, 6, 26, 17, 10, 31, 774000)}
+
+
+
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.25.4-scylla/cqlengine/third_party.html b/3.25.4-scylla/cqlengine/third_party.html new file mode 100644 index 0000000000..3086827e0b --- /dev/null +++ b/3.25.4-scylla/cqlengine/third_party.html @@ -0,0 +1,707 @@ + + + + + + + + + + + + + Third party integrations | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

Third party integrations

+
+

Celery

+

Here’s how, in substance, CQLengine can be plugged to Celery:

+
from celery import Celery
+from celery.signals import worker_process_init, beat_init
+from cassandra.cqlengine import connection
+from cassandra.cqlengine.connection import (
+    cluster as cql_cluster, session as cql_session)
+
+def cassandra_init(**kwargs):
+    """ Initialize a clean Cassandra connection. """
+    if cql_cluster is not None:
+        cql_cluster.shutdown()
+    if cql_session is not None:
+        cql_session.shutdown()
+    connection.setup()
+
+# Initialize worker context for both standard and periodic tasks.
+worker_process_init.connect(cassandra_init)
+beat_init.connect(cassandra_init)
+
+app = Celery()
+
+
+
+
+

uWSGI

+

This is the code required for proper connection handling of CQLengine for a +uWSGI-run application:

+
from cassandra.cqlengine import connection
+from cassandra.cqlengine.connection import (
+    cluster as cql_cluster, session as cql_session)
+
+try:
+    from uwsgidecorators import postfork
+except ImportError:
+    # We're not in a uWSGI context, no need to hook Cassandra session
+    # initialization to the postfork event.
+    pass
+else:
+    @postfork
+    def cassandra_init(**kwargs):
+        """ Initialize a new Cassandra session in the context.
+
+        Ensures that a new session is returned for every new request.
+        """
+        if cql_cluster is not None:
+            cql_cluster.shutdown()
+        if cql_session is not None:
+            cql_session.shutdown()
+        connection.setup()
+
+
+
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.25.4-scylla/cqlengine/upgrade_guide.html b/3.25.4-scylla/cqlengine/upgrade_guide.html new file mode 100644 index 0000000000..668aeda39a --- /dev/null +++ b/3.25.4-scylla/cqlengine/upgrade_guide.html @@ -0,0 +1,839 @@ + + + + + + + + + + + + + Upgrade Guide | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + + + +
+

Upgrade Guide

+

This is an overview of things that changed as the cqlengine project was merged into +scylla-driver. While efforts were taken to preserve the API and most functionality exactly, +conversion to this package will still require certain minimal updates (namely, imports).

+

THERE IS ONE FUNCTIONAL CHANGE, described in the first section below.

+
+

Functional Changes

+
+

List Prepend Reversing

+

Legacy cqlengine included a workaround for a Cassandra bug in which prepended list segments were +reversed (CASSANDRA-8733). As of +this integration, this workaround is removed. The first released integrated version emits +a warning when prepend is used. Subsequent versions will have this warning removed.

+
+
+

Date Column Type

+

The Date column type in legacy cqlengine used a timestamp CQL type and truncated the time. +Going forward, the Date type represents a date for Cassandra 2.2+ +(PYTHON-245). +Users of the legacy functionality should convert models to use DateTime (which +uses timestamp internally), and use the build-in datetime.date for input values.

+
+
+
+

Remove cqlengine

+

To avoid confusion or mistakes using the legacy package in your application, it +is prudent to remove the cqlengine package when upgrading to the integrated version.

+

The driver setup script will warn if the legacy package is detected during install, +but it will not prevent side-by-side installation.

+
+
+

Organization

+
+

Imports

+

cqlengine is now integrated as a sub-package of the driver base package ‘cassandra’. +Upgrading will require adjusting imports to cqlengine. For example:

+
from cassandra.cqlengine import columns
+
+
+

is now:

+
from cassandra.cqlengine import columns
+
+
+
+
+

Package-Level Aliases

+

Legacy cqlengine defined a number of aliases at the package level, which became redundant +when the package was integrated for a driver. These have been removed in favor of absolute +imports, and referring to cannonical definitions. For example, cqlengine.ONE was an alias +of cassandra.ConsistencyLevel.ONE. In the integrated package, only the +cassandra.ConsistencyLevel remains.

+

Additionally, submodule aliases are removed from cqlengine in favor of absolute imports.

+

These aliases are removed, and not deprecated because they should be straightforward to iron out +at module load time.

+
+
+

Exceptions

+

The legacy cqlengine.exceptions module had a number of Exception classes that were variously +common to the package, or only used in specific modules. Common exceptions were relocated to +cqlengine, and specialized exceptions were placed in the module that raises them. Below is a +listing of updated locations:

+ ++++ + + + + + + + + + + + + + + + + + + + + + + + + + +

Exception class

New module

CQLEngineException

cassandra.cqlengine

ModelException

cassandra.cqlengine.models

ValidationError

cassandra.cqlengine

UndefinedKeyspaceException

cassandra.cqlengine.connection

LWTException

cassandra.cqlengine.query

IfNotExistsWithCounterColumn

cassandra.cqlengine.query

+
+
+

UnicodeMixin Consolidation

+

class UnicodeMixin was defined in several cqlengine modules. This has been consolidated +to a single definition in the cqlengine package init file. This is not technically part of +the API, but noted here for completeness.

+
+
+
+

API Deprecations

+

This upgrade served as a good juncture to deprecate certain API features and invite users to upgrade +to new ones. The first released version does not change functionality – only introduces deprecation +warnings. Future releases will remove these features in favor of the alternatives.

+
+

Float/Double Overload

+

Previously there was no Double column type. Doubles were modeled by specifying Float(double_precision=True). +This inititializer parameter is now deprecated. Applications should use Double for CQL double, and Float +for CQL float.

+
+
+

Schema Management

+

cassandra.cqlengine.management.create_keyspace is deprecated. Instead, use the new replication-strategy-specific +functions that accept explicit options for known strategies:

+ +

cassandra.cqlengine.management.delete_keyspace is deprecated in favor of a new function, drop_keyspace(). The +intent is simply to make the function match the CQL verb it invokes.

+
+
+

Model Inheritance

+

The names for class attributes controlling model inheritance are changing. Changes are as follows:

+ +

The functionality is unchanged – the intent here is to make the names and language around these attributes more precise. +For now, the old names are just deprecated, and the mapper will emit warnings if they are used. The old names +will be removed in a future version.

+

The example below shows a simple translation:

+

Before:

+
class Pet(Model):
+    __table_name__ = 'pet'
+    owner_id = UUID(primary_key=True)
+    pet_id = UUID(primary_key=True)
+    pet_type = Text(polymorphic_key=True)
+    name = Text()
+
+class Cat(Pet):
+    __polymorphic_key__ = 'cat'
+
+class Dog(Pet):
+    __polymorphic_key__ = 'dog'
+
+
+

After:

+
class Pet(models.Model):
+    __table_name__ = 'pet'
+    owner_id = UUID(primary_key=True)
+    pet_id = UUID(primary_key=True)
+    pet_type = Text(discriminator_column=True)
+    name = Text()
+
+class Cat(Pet):
+    __discriminator_value__ = 'cat'
+
+class Dog(Pet):
+    __discriminator_value__ = 'dog'
+
+
+
+
+

TimeUUID.from_datetime

+

This function is deprecated in favor of the core utility function uuid_from_time().

+
+
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.25.4-scylla/dates_and_times.html b/3.25.4-scylla/dates_and_times.html new file mode 100644 index 0000000000..2220a0a0a1 --- /dev/null +++ b/3.25.4-scylla/dates_and_times.html @@ -0,0 +1,731 @@ + + + + + + + + + + + + + Working with Dates and Times | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

Working with Dates and Times

+

This document is meant to provide on overview of the assumptions and limitations of the driver time handling, the +reasoning behind it, and describe approaches to working with these types.

+
+

timestamps (Cassandra DateType)

+

Timestamps in Cassandra are timezone-naive timestamps encoded as millseconds since UNIX epoch. Clients working with +timestamps in this database usually find it easiest to reason about them if they are always assumed to be UTC. To quote the +pytz documentation, “The preferred way of dealing with times is to always work in UTC, converting to localtime only when +generating output to be read by humans.” The driver adheres to this tenant, and assumes UTC is always in the database. The +driver attempts to make this correct on the way in, and assumes no timezone on the way out.

+
+

Write Path

+

When inserting timestamps, the driver handles serialization for the write path as follows:

+

If the input is a datetime.datetime, the serialization is normalized by starting with the utctimetuple() of the +value.

+
    +
  • If the datetime object is timezone-aware, the timestamp is shifted, and represents the UTC timestamp equivalent.

  • +
  • If the datetime object is timezone-naive, this results in no shift – any datetime with no timezone information is assumed to be UTC

  • +
+

Note the second point above applies even to “local” times created using now():

+
>>> d = datetime.now()
+
+>>> print(d.tzinfo)
+None
+
+
+

These do not contain timezone information intrinsically, so they will be assumed to be UTC and not shifted. When generating +timestamps in the application, it is clearer to use datetime.utcnow() to be explicit about it.

+

If the input for a timestamp is numeric, it is assumed to be a epoch-relative millisecond timestamp, as specified in the +CQL spec – no scaling or conversion is done.

+
+
+

Read Path

+

The driver always assumes persisted timestamps are UTC and makes no attempt to localize them. Returned values are +timezone-naive datetime.datetime. We follow this approach because the datetime API has deficiencies around daylight +saving time, and the defacto package for handling this is a third-party package (we try to minimize external dependencies +and not make decisions for the integrator).

+

The decision for how to handle timezones is left to the application. For the most part it is straightforward to apply +localization to the datetimes returned by queries. One prevalent method is to use pytz for localization:

+
import pytz
+user_tz = pytz.timezone('US/Central')
+timestamp_naive = row.ts
+timestamp_utc = pytz.utc.localize(timestamp_naive)
+timestamp_presented = timestamp_utc.astimezone(user_tz)
+
+
+

This is the most robust approach (likely refactored into a function). If it is deemed too cumbersome to apply for all call +sites in the application, it is possible to patch the driver with custom deserialization for this type. However, doing +this depends depends some on internal APIs and what extensions are present, so we will only mention the possibility, and +not spell it out here.

+
+
+
+

date, time (Cassandra DateType)

+

Date and time in Cassandra are idealized markers, much like datetime.date and datetime.time in the Python standard +library. Unlike these Python implementations, the Cassandra encoding supports much wider ranges. To accommodate these +ranges without overflow, this driver returns these data in custom types: util.Date and util.Time.

+
+

Write Path

+

For simple (not prepared) statements, the input values for each of these can be either a string literal or an encoded +integer. See Working with dates +or Working with time for details +on the encoding or string formats.

+

For prepared statements, the driver accepts anything that can be used to construct the util.Date or +util.Time classes. See the linked API docs for details.

+
+
+

Read Path

+

The driver always returns custom types for date and time.

+

The driver returns util.Date for date in order to accommodate the wider range of values without overflow. +For applications working within the supported range of [datetime.MINYEAR, datetime.MAXYEAR], these are easily +converted to standard datetime.date insances using Date.date().

+

The driver returns util.Time for time in order to retain nanosecond precision stored in the database. +For applications not concerned with this level of precision, these are easily converted to standard datetime.time +insances using Time.time().

+
+
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.25.4-scylla/execution_profiles.html b/3.25.4-scylla/execution_profiles.html new file mode 100644 index 0000000000..243ccb9204 --- /dev/null +++ b/3.25.4-scylla/execution_profiles.html @@ -0,0 +1,775 @@ + + + + + + + + + + + + + Execution Profiles | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

Execution Profiles

+

Execution profiles aim at making it easier to execute requests in different ways within +a single connected Session. Execution profiles are being introduced to deal with the exploding number of +configuration options, especially as the database platform evolves more complex workloads.

+

The legacy configuration remains intact, but legacy and Execution Profile APIs +cannot be used simultaneously on the same client Cluster. Legacy configuration +will be removed in the next major release (4.0).

+

An execution profile and its parameters should be unique across Cluster instances. +For example, an execution profile and its LoadBalancingPolicy should +not be applied to more than one Cluster instance.

+

This document explains how Execution Profiles relate to existing settings, and shows how to use the new profiles for +request execution.

+
+

Mapping Legacy Parameters to Profiles

+

Execution profiles can inherit from cluster.ExecutionProfile, and currently provide the following options, +previously input from the noted attributes:

+ +

When using the new API, these parameters can be defined by instances of cluster.ExecutionProfile.

+
+
+

Using Execution Profiles

+
+

Default

+
from cassandra.cluster import Cluster
+cluster = Cluster()
+session = cluster.connect()
+local_query = 'SELECT rpc_address FROM system.local'
+for _ in cluster.metadata.all_hosts():
+    print session.execute(local_query)[0]
+
+
+
Row(rpc_address='127.0.0.2')
+Row(rpc_address='127.0.0.1')
+
+
+

The default execution profile is built from Cluster parameters and default Session attributes. This profile matches existing default +parameters.

+
+
+

Initializing cluster with profiles

+
from cassandra.cluster import ExecutionProfile
+from cassandra.policies import WhiteListRoundRobinPolicy
+
+node1_profile = ExecutionProfile(load_balancing_policy=WhiteListRoundRobinPolicy(['127.0.0.1']))
+node2_profile = ExecutionProfile(load_balancing_policy=WhiteListRoundRobinPolicy(['127.0.0.2']))
+
+profiles = {'node1': node1_profile, 'node2': node2_profile}
+session = Cluster(execution_profiles=profiles).connect()
+for _ in cluster.metadata.all_hosts():
+    print session.execute(local_query, execution_profile='node1')[0]
+
+
+
Row(rpc_address='127.0.0.1')
+Row(rpc_address='127.0.0.1')
+
+
+
for _ in cluster.metadata.all_hosts():
+    print session.execute(local_query, execution_profile='node2')[0]
+
+
+
Row(rpc_address='127.0.0.2')
+Row(rpc_address='127.0.0.2')
+
+
+
for _ in cluster.metadata.all_hosts():
+    print session.execute(local_query)[0]
+
+
+
Row(rpc_address='127.0.0.2')
+Row(rpc_address='127.0.0.1')
+
+
+

Note that, even when custom profiles are injected, the default TokenAwarePolicy(DCAwareRoundRobinPolicy()) is still +present. To override the default, specify a policy with the EXEC_PROFILE_DEFAULT key.

+
from cassandra.cluster import EXEC_PROFILE_DEFAULT
+profile = ExecutionProfile(request_timeout=30)
+cluster = Cluster(execution_profiles={EXEC_PROFILE_DEFAULT: profile})
+
+
+
+
+

Adding named profiles

+

New profiles can be added constructing from scratch, or deriving from default:

+
locked_execution = ExecutionProfile(load_balancing_policy=WhiteListRoundRobinPolicy(['127.0.0.1']))
+node1_profile = 'node1_whitelist'
+cluster.add_execution_profile(node1_profile, locked_execution)
+
+for _ in cluster.metadata.all_hosts():
+    print session.execute(local_query, execution_profile=node1_profile)[0]
+
+
+
Row(rpc_address='127.0.0.1')
+Row(rpc_address='127.0.0.1')
+
+
+

See Cluster.add_execution_profile() for details and optional parameters.

+
+
+

Passing a profile instance without mapping

+

We also have the ability to pass profile instances to be used for execution, but not added to the mapping:

+
from cassandra.query import tuple_factory
+
+tmp = session.execution_profile_clone_update('node1', request_timeout=100, row_factory=tuple_factory)
+
+print session.execute(local_query, execution_profile=tmp)[0]
+print session.execute(local_query, execution_profile='node1')[0]
+
+
+
('127.0.0.1',)
+Row(rpc_address='127.0.0.1')
+
+
+

The new profile is a shallow copy, so the tmp profile shares a load balancing policy with one managed by the cluster. +If reference objects are to be updated in the clone, one would typically set those attributes to a new instance.

+
+
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.25.4-scylla/faq.html b/3.25.4-scylla/faq.html new file mode 100644 index 0000000000..91ebbbace6 --- /dev/null +++ b/3.25.4-scylla/faq.html @@ -0,0 +1,711 @@ + + + + + + + + + + + + + Frequently Asked Questions | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

Frequently Asked Questions

+

See also cqlengine FAQ

+
+

Why do connections or IO operations timeout in my WSGI application?

+

Depending on your application process model, it may be forking after driver Session is created. Most IO reactors do not handle this, and problems will manifest as timeouts.

+

To avoid this, make sure to create sessions per process, after the fork. Using uWSGI and Flask for example:

+
from flask import Flask
+from uwsgidecorators import postfork
+from cassandra.cluster import Cluster
+
+session = None
+prepared = None
+
+@postfork
+def connect():
+    global session, prepared
+    session = Cluster().connect()
+    prepared = session.prepare("SELECT release_version FROM system.local WHERE key=?")
+
+app = Flask(__name__)
+
+@app.route('/')
+def server_version():
+    row = session.execute(prepared, ('local',))[0]
+    return row.release_version
+
+
+

uWSGI provides a postfork hook you can use to create sessions and prepared statements after the child process forks.

+
+
+

How do I trace a request?

+

Request tracing can be turned on for any request by setting trace=True in Session.execute_async(). View the results by waiting on the future, then ResponseFuture.get_query_trace(). +Since tracing is done asynchronously to the request, this method polls until the trace is complete before querying data.

+
>>> future = session.execute_async("SELECT * FROM system.local", trace=True)
+>>> result = future.result()
+>>> trace = future.get_query_trace()
+>>> for e in trace.events:
+>>>     print e.source_elapsed, e.description
+
+0:00:00.000077 Parsing select * from system.local
+0:00:00.000153 Preparing statement
+0:00:00.000309 Computing ranges to query
+0:00:00.000368 Submitting range requests on 1 ranges with a concurrency of 1 (279.77142 rows per range expected)
+0:00:00.000422 Submitted 1 concurrent range requests covering 1 ranges
+0:00:00.000480 Executing seq scan across 1 sstables for (min(-9223372036854775808), min(-9223372036854775808))
+0:00:00.000669 Read 1 live and 0 tombstone cells
+0:00:00.000755 Scanned 1 rows and matched 1
+
+
+

trace is a QueryTrace object.

+
+
+

How do I determine the replicas for a query?

+

With prepared statements, the replicas are obtained by routing_key, based on current cluster token metadata:

+
>>> prepared = session.prepare("SELECT * FROM example.t WHERE key=?")
+>>> bound = prepared.bind((1,))
+>>> replicas = cluster.metadata.get_replicas(bound.keyspace, bound.routing_key)
+>>> for h in replicas:
+>>>   print h.address
+127.0.0.1
+127.0.0.2
+
+
+

replicas is a list of Host objects.

+
+
+

How does the driver manage request retries?

+

By default, retries are managed by the Cluster.default_retry_policy set on the session Cluster. It can also +be specialized per statement by setting Statement.retry_policy.

+

Retries are presently attempted on the same coordinator, but this may change in the future.

+

Please see policies.RetryPolicy for further details.

+
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.25.4-scylla/getting_started.html b/3.25.4-scylla/getting_started.html new file mode 100644 index 0000000000..28b14381a0 --- /dev/null +++ b/3.25.4-scylla/getting_started.html @@ -0,0 +1,1126 @@ + + + + + + + + + + + + + Getting Started | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

Getting Started

+

First, make sure you have the driver properly installed.

+
+

Connecting to a Cluster

+

Before we can start executing any queries against a Cassandra cluster we need to setup +an instance of Cluster. As the name suggests, you will typically have one +instance of Cluster for each Cassandra cluster you want to interact +with.

+

First, make sure you have the Cassandra driver properly installed.

+
+

Connecting to Cassandra

+

The simplest way to create a Cluster is like this:

+
from cassandra.cluster import Cluster
+
+cluster = Cluster()
+
+
+

This will attempt to connection to a Cassandra instance on your +local machine (127.0.0.1). You can also specify a list of IP +addresses for nodes in your cluster:

+
from cassandra.cluster import Cluster
+
+cluster = Cluster(['192.168.0.1', '192.168.0.2'])
+
+
+

The set of IP addresses we pass to the Cluster is simply +an initial set of contact points. After the driver connects to one +of these nodes it will automatically discover the rest of the +nodes in the cluster and connect to them, so you don’t need to list +every node in your cluster.

+

If you need to use a non-standard port, use SSL, or customize the driver’s +behavior in some other way, this is the place to do it:

+
from cassandra.cluster import Cluster
+cluster = Cluster(['192.168.0.1', '192.168.0.2'], port=..., ssl_context=...)
+
+
+

Instantiating a Cluster does not actually connect us to any nodes. +To establish connections and begin executing queries we need a +Session, which is created by calling Cluster.connect():

+
cluster = Cluster()
+session = cluster.connect()
+
+
+
+
+
+

Session Keyspace

+

The connect() method takes an optional keyspace argument +which sets the default keyspace for all queries made through that Session:

+
cluster = Cluster()
+session = cluster.connect('mykeyspace')
+
+
+

You can always change a Session’s keyspace using set_keyspace() or +by executing a USE <keyspace> query:

+
session.set_keyspace('users')
+# or you can do this instead
+session.execute('USE users')
+
+
+
+
+

Execution Profiles

+

Profiles are passed in by execution_profiles dict.

+

In this case we can construct the base ExecutionProfile passing all attributes:

+
from cassandra.cluster import Cluster, ExecutionProfile, EXEC_PROFILE_DEFAULT
+from cassandra.policies import WhiteListRoundRobinPolicy, DowngradingConsistencyRetryPolicy
+from cassandra.query import tuple_factory
+
+profile = ExecutionProfile(
+    load_balancing_policy=WhiteListRoundRobinPolicy(['127.0.0.1']),
+    retry_policy=DowngradingConsistencyRetryPolicy(),
+    consistency_level=ConsistencyLevel.LOCAL_QUORUM,
+    serial_consistency_level=ConsistencyLevel.LOCAL_SERIAL,
+    request_timeout=15,
+    row_factory=tuple_factory
+)
+cluster = Cluster(execution_profiles={EXEC_PROFILE_DEFAULT: profile})
+session = cluster.connect()
+
+print(session.execute("SELECT release_version FROM system.local").one())
+
+
+

Users are free to setup additional profiles to be used by name:

+
profile_long = ExecutionProfile(request_timeout=30)
+cluster = Cluster(execution_profiles={'long': profile_long})
+session = cluster.connect()
+session.execute(statement, execution_profile='long')
+
+
+

Also, parameters passed to Session.execute or attached to Statements are still honored as before.

+
+
+

Executing Queries

+

Now that we have a Session we can begin to execute queries. The simplest +way to execute a query is to use execute():

+
rows = session.execute('SELECT name, age, email FROM users')
+for user_row in rows:
+    print user_row.name, user_row.age, user_row.email
+
+
+

This will transparently pick a Cassandra node to execute the query against +and handle any retries that are necessary if the operation fails.

+

By default, each row in the result set will be a +namedtuple. +Each row will have a matching attribute for each column defined in the schema, +such as name, age, and so on. You can also treat them as normal tuples +by unpacking them or accessing fields by position. The following three +examples are equivalent:

+
rows = session.execute('SELECT name, age, email FROM users')
+for row in rows:
+    print row.name, row.age, row.email
+
+
+
rows = session.execute('SELECT name, age, email FROM users')
+for (name, age, email) in rows:
+    print name, age, email
+
+
+
rows = session.execute('SELECT name, age, email FROM users')
+for row in rows:
+    print row[0], row[1], row[2]
+
+
+

If you prefer another result format, such as a dict per row, you +can change the row_factory attribute.

+

As mentioned in our Drivers Best Practices Guide, +it is highly recommended to use Prepared statements for your +frequently run queries.

+
+
+

Prepared Statements

+

Prepared statements are queries that are parsed by Cassandra and then saved +for later use. When the driver uses a prepared statement, it only needs to +send the values of parameters to bind. This lowers network traffic +and CPU utilization within Cassandra because Cassandra does not have to +re-parse the query each time.

+

To prepare a query, use Session.prepare():

+
user_lookup_stmt = session.prepare("SELECT * FROM users WHERE user_id=?")
+
+users = []
+for user_id in user_ids_to_query:
+    user = session.execute(user_lookup_stmt, [user_id])
+    users.append(user)
+
+
+

prepare() returns a PreparedStatement instance +which can be used in place of SimpleStatement instances or literal +string queries. It is automatically prepared against all nodes, and the driver +handles re-preparing against new nodes and restarted nodes when necessary.

+

Note that the placeholders for prepared statements are ? characters. This +is different than for simple, non-prepared statements (although future versions +of the driver may use the same placeholders for both).

+
+
+

Passing Parameters to CQL Queries

+

Althought it is not recommended, you can also pass parameters to non-prepared +statements. The driver supports two forms of parameter place-holders: positional +and named.

+

Positional parameters are used with a %s placeholder. For example, +when you execute:

+
session.execute(
+    """
+    INSERT INTO users (name, credits, user_id)
+    VALUES (%s, %s, %s)
+    """,
+    ("John O'Reilly", 42, uuid.uuid1())
+)
+
+
+

It is translated to the following CQL query:

+
INSERT INTO users (name, credits, user_id)
+VALUES ('John O''Reilly', 42, 2644bada-852c-11e3-89fb-e0b9a54a6d93)
+
+
+

Note that you should use %s for all types of arguments, not just strings. +For example, this would be wrong:

+
session.execute("INSERT INTO USERS (name, age) VALUES (%s, %d)", ("bob", 42))  # wrong
+
+
+

Instead, use %s for the age placeholder.

+

If you need to use a literal % character, use %%.

+

Note: you must always use a sequence for the second argument, even if you are +only passing in a single variable:

+
session.execute("INSERT INTO foo (bar) VALUES (%s)", "blah")  # wrong
+session.execute("INSERT INTO foo (bar) VALUES (%s)", ("blah"))  # wrong
+session.execute("INSERT INTO foo (bar) VALUES (%s)", ("blah", ))  # right
+session.execute("INSERT INTO foo (bar) VALUES (%s)", ["blah"])  # right
+
+
+

Note that the second line is incorrect because in Python, single-element tuples +require a comma.

+

Named place-holders use the %(name)s form:

+
session.execute(
+    """
+    INSERT INTO users (name, credits, user_id, username)
+    VALUES (%(name)s, %(credits)s, %(user_id)s, %(name)s)
+    """,
+    {'name': "John O'Reilly", 'credits': 42, 'user_id': uuid.uuid1()}
+)
+
+
+

Note that you can repeat placeholders with the same name, such as %(name)s +in the above example.

+

Only data values should be supplied this way. Other items, such as keyspaces, +table names, and column names should be set ahead of time (typically using +normal string formatting).

+
+
+

Type Conversions

+

For non-prepared statements, Python types are cast to CQL literals in the +following way:

+ ++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Python Type

CQL Literal Type

None

NULL

bool

boolean

float

+
float
+
double
+
+
+
int
+
long
+
+
+
int
+
bigint
+
varint
+
smallint
+
tinyint
+
counter
+
+

decimal.Decimal

decimal

+
str
+
unicode
+
+
+
ascii
+
varchar
+
text
+
+
+
buffer
+
bytearray
+
+

blob

date

date

datetime

timestamp

time

time

+
list
+
tuple
+
generator
+
+

list

+
set
+
frozenset
+
+

set

+
dict
+
OrderedDict
+
+

map

uuid.UUID

+
timeuuid
+
uuid
+
+
+
+
+

Asynchronous Queries

+

The driver supports asynchronous query execution through +execute_async(). Instead of waiting for the query to +complete and returning rows directly, this method almost immediately +returns a ResponseFuture object. There are two ways of +getting the final result from this object.

+

The first is by calling result() on it. If +the query has not yet completed, this will block until it has and +then return the result or raise an Exception if an error occurred. +For example:

+
from cassandra import ReadTimeout
+
+query = "SELECT * FROM users WHERE user_id=%s"
+future = session.execute_async(query, [user_id])
+
+# ... do some other work
+
+try:
+    rows = future.result()
+    user = rows[0]
+    print user.name, user.age
+except ReadTimeout:
+    log.exception("Query timed out:")
+
+
+

This works well for executing many queries concurrently:

+
# build a list of futures
+futures = []
+query = "SELECT * FROM users WHERE user_id=%s"
+for user_id in ids_to_fetch:
+    futures.append(session.execute_async(query, [user_id])
+
+# wait for them to complete and use the results
+for future in futures:
+    rows = future.result()
+    print rows[0].name
+
+
+

Alternatively, instead of calling result(), +you can attach callback and errback functions through the +add_callback(), +add_errback(), and +add_callbacks(), methods. If you have used +Twisted Python before, this is designed to be a lightweight version of +that:

+
def handle_success(rows):
+    user = rows[0]
+    try:
+        process_user(user.name, user.age, user.id)
+    except Exception:
+        log.error("Failed to process user %s", user.id)
+        # don't re-raise errors in the callback
+
+def handle_error(exception):
+    log.error("Failed to fetch user info: %s", exception)
+
+
+future = session.execute_async(query)
+future.add_callbacks(handle_success, handle_error)
+
+
+
+
There are a few important things to remember when working with callbacks:
    +
  • Exceptions that are raised inside the callback functions will be logged and then ignored.

  • +
  • Your callback will be run on the event loop thread, so any long-running +operations will prevent other requests from being handled

  • +
+
+
+
+
+

Setting a Consistency Level

+

The consistency level used for a query determines how many of the +replicas of the data you are interacting with need to respond for +the query to be considered a success.

+

By default, ConsistencyLevel.LOCAL_ONE will be used for all queries. +You can specify a different default by setting the ExecutionProfile.consistency_level +for the execution profile with key EXEC_PROFILE_DEFAULT. +To specify a different consistency level per request, wrap queries +in a SimpleStatement:

+
from cassandra import ConsistencyLevel
+from cassandra.query import SimpleStatement
+
+query = SimpleStatement(
+    "INSERT INTO users (name, age) VALUES (%s, %s)",
+    consistency_level=ConsistencyLevel.QUORUM)
+session.execute(query, ('John', 42))
+
+
+
+
+

Setting a Consistency Level with Prepared Statements

+

To specify a consistency level for prepared statements, you have two options.

+

The first is to set a default consistency level for every execution of the +prepared statement:

+
from cassandra import ConsistencyLevel
+
+cluster = Cluster()
+session = cluster.connect("mykeyspace")
+user_lookup_stmt = session.prepare("SELECT * FROM users WHERE user_id=?")
+user_lookup_stmt.consistency_level = ConsistencyLevel.QUORUM
+
+# these will both use QUORUM
+user1 = session.execute(user_lookup_stmt, [user_id1])[0]
+user2 = session.execute(user_lookup_stmt, [user_id2])[0]
+
+
+

The second option is to create a BoundStatement from the +PreparedStatement and binding parameters and set a consistency +level on that:

+
# override the QUORUM default
+user3_lookup = user_lookup_stmt.bind([user_id3])
+user3_lookup.consistency_level = ConsistencyLevel.ALL
+user3 = session.execute(user3_lookup)
+
+
+
+
+

Speculative Execution

+

Speculative execution is a way to minimize latency by preemptively executing several +instances of the same query against different nodes. For more details about this +technique, see Speculative Execution with DataStax Drivers.

+

To enable speculative execution:

+
    +
  • Configure a SpeculativeExecutionPolicy with the ExecutionProfile

  • +
  • Mark your query as idempotent, which mean it can be applied multiple +times without changing the result of the initial application. +See Query Idempotence for more details.

  • +
+

Example:

+
from cassandra.cluster import Cluster, ExecutionProfile, EXEC_PROFILE_DEFAULT
+from cassandra.policies import ConstantSpeculativeExecutionPolicy
+from cassandra.query import SimpleStatement
+
+# Configure the speculative execution policy
+ep = ExecutionProfile(
+    speculative_execution_policy=ConstantSpeculativeExecutionPolicy(delay=.5, max_attempts=10)
+)
+cluster = Cluster(..., execution_profiles={EXEC_PROFILE_DEFAULT: ep})
+session = cluster.connect()
+
+# Mark the query idempotent
+query = SimpleStatement(
+    "UPDATE my_table SET list_col = [1] WHERE pk = 1",
+    is_idempotent=True
+)
+
+# Execute. A new query will be sent to the server every 0.5 second
+# until we receive a response, for a max number attempts of 10.
+session.execute(query)
+
+
+
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.25.4-scylla/index.html b/3.25.4-scylla/index.html new file mode 100644 index 0000000000..72a2aec934 --- /dev/null +++ b/3.25.4-scylla/index.html @@ -0,0 +1,701 @@ + + + + + + + + + + + + + Python Driver for Scylla and Apache Cassandra® | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

Python Driver for Scylla and Apache Cassandra®

+

A Python client driver for Scylla. +This driver works exclusively with the Cassandra Query Language v3 (CQL3) +and Cassandra’s native protocol.

+

The driver supports Python 2.7, 3.5, 3.6, 3.7 and 3.8.

+

This driver is open source under the +Apache v2 License. +The source code for this driver can be found on GitHub.

+

Scylla Driver is a fork from DataStax Python Driver, including some non-breaking changes for Scylla optimization, with more updates planned.

+
+

Contents

+
+
Installation

How to install the driver.

+
+
Getting Started

A guide through the first steps of connecting to Scylla and executing queries

+
+
Scylla Specific Features

A list of feature available only on scylla-driver

+
+
Execution Profiles

An introduction to a more flexible way of configuring request execution

+
+
Lightweight Transactions (Compare-and-set)

Working with results of conditional requests

+
+
Object Mapper

Introduction to the integrated object mapper, cqlengine

+
+
Performance Notes

Tips for getting good performance.

+
+
Paging Large Queries

Notes on paging large query results

+
+
Security

An overview of the security features of the driver

+
+
Upgrading

A guide to upgrading versions of the driver

+
+
User Defined Types

Working with Scylla’s user-defined types (UDT)

+
+
Working with Dates and Times

Some discussion on the driver’s approach to working with timestamp, date, time types

+
+
Scylla Cloud

Connect to Scylla Cloud

+
+
CHANGELOG

Log of changes to the driver, organized by version.

+
+
Frequently Asked Questions

A collection of Frequently Asked Questions

+
+
API Documentation

The API documentation.

+
+
+
+
+
+
+

Getting Help

+

Visit the FAQ section in this documentation.

+

Please send questions to the Scylla user list.

+
+
+

Reporting Issues

+

Please report any bugs and make any feature requests on the Github project issues

+
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.25.4-scylla/installation.html b/3.25.4-scylla/installation.html new file mode 100644 index 0000000000..1aaf7006ec --- /dev/null +++ b/3.25.4-scylla/installation.html @@ -0,0 +1,874 @@ + + + + + + + + + + + + + Installation | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

Installation

+
+

Supported Platforms

+

Python 2.7, 3.5, 3.6, 3.7 and 3.8 are supported. Both CPython (the standard Python +implementation) and PyPy are supported and tested.

+

Linux, OSX, and Windows are supported.

+
+
+

Installation through pip

+

pip is the suggested tool for installing +packages. It will handle installing all Python dependencies for the driver at +the same time as the driver itself. To install the driver*:

+
pip install scylla-driver
+
+
+

You can use pip install --pre scylla-driver if you need to install a beta version.

+

*Note: if intending to use optional extensions, install the dependencies first. The driver may need to be reinstalled if dependencies are added after the initial installation.

+
+
+

Verifying your Installation

+

To check if the installation was successful, you can run:

+
python -c 'import cassandra; print cassandra.__version__'
+
+
+

It should print something like “3.22.0”.

+
+
+

(Optional) Graph

+

The driver provides an optional fluent graph API that depends on Apache TinkerPop (gremlinpython). It is +not installed by default. To be able to build Gremlin traversals, you need to install +the graph requirements:

+
pip install scylla-driver[graph]
+
+
+
+
+

(Optional) Compression Support

+

Compression can optionally be used for communication between the driver and +Cassandra. There are currently two supported compression algorithms: +snappy (in Cassandra 1.2+) and LZ4 (only in Cassandra 2.0+). If either is +available for the driver and Cassandra also supports it, it will +be used automatically.

+

For lz4 support:

+
pip install lz4
+
+
+

For snappy support:

+
pip install python-snappy
+
+
+

(If using a Debian Linux derivative such as Ubuntu, it may be easier to +just run apt-get install python-snappy.)

+
+
+

(Optional) Metrics Support

+

The driver has built-in support for capturing Cluster.metrics about +the queries you run. However, the scales library is required to +support this:

+
pip install scales
+
+
+
+

Speeding Up Installation

+

By default, installing the driver through pip uses a pre-compiled, platform-specific wheel when available. +If using a source distribution rather than a wheel, Cython is used to compile certain parts of the driver. +This makes those hot paths faster at runtime, but the Cython compilation +process can take a long time – as long as 10 minutes in some environments.

+

In environments where performance is less important, it may be worth it to +disable Cython as documented below. +You can also use CASS_DRIVER_BUILD_CONCURRENCY to increase the number of +threads used to build the driver and any C extensions:

+
$ # installing from source
+$ CASS_DRIVER_BUILD_CONCURRENCY=8 python setup.py install
+$ # installing from pip
+$ CASS_DRIVER_BUILD_CONCURRENCY=8 pip install scylla-driver
+
+
+
+
+

OSX Installation Error

+

If you’re installing on OSX and have XCode 5.1 installed, you may see an error like this:

+
clang: error: unknown argument: '-mno-fused-madd' [-Wunused-command-line-argument-hard-error-in-future]
+
+
+

To fix this, re-run the installation with an extra compilation flag:

+
ARCHFLAGS=-Wno-error=unused-command-line-argument-hard-error-in-future pip install scylla-driver
+
+
+
+
+
+

Windows Installation Notes

+

Installing the driver with extensions in Windows sometimes presents some challenges. A few notes about common +hang-ups:

+

Setup requires a compiler. When using Python 2, this is as simple as installing this package +(this link is also emitted during install if setuptools is unable to find the resources it needs). Depending on your +system settings, this package may install as a user-specific application. Make sure to install for everyone, or at least +as the user that will be building the Python environment.

+

It is also possible to run the build with your compiler of choice. Just make sure to have your environment setup with +the proper paths. Make sure the compiler target architecture matches the bitness of your Python runtime. +Perhaps the easiest way to do this is to run the build/install from a Visual Studio Command Prompt (a +shortcut installed with Visual Studio that sources the appropriate environment and presents a shell).

+
+
+

Manual Installation

+

You can always install the driver directly from a source checkout or tarball. +When installing manually, ensure the python dependencies are already +installed. You can find the list of dependencies in +requirements.txt.

+

Once the dependencies are installed, simply run:

+
python setup.py install
+
+
+
+
+

(Optional) Non-python Dependencies

+

The driver has several optional features that have non-Python dependencies.

+
+

C Extensions

+

By default, a number of extensions are compiled, providing faster hashing +for token-aware routing with the Murmur3Partitioner, +libev event loop integration, +and Cython optimized extensions.

+

When installing manually through setup.py, you can disable both with +the --no-extensions option, or selectively disable them with +with --no-murmur3, --no-libev, or --no-cython.

+

To compile the extensions, ensure that GCC and the Python headers are available.

+

On Ubuntu and Debian, this can be accomplished by running:

+
$ sudo apt-get install gcc python-dev
+
+
+

On RedHat and RedHat-based systems like CentOS and Fedora:

+
$ sudo yum install gcc python-devel
+
+
+

On OS X, homebrew installations of Python should provide the necessary headers.

+

See Windows Installation Notes for notes on configuring the build environment on Windows.

+
+

Cython-based Extensions

+

By default, this package uses Cython to optimize core modules and build custom extensions. +This is not a hard requirement, but is engaged by default to build extensions offering better performance than the +pure Python implementation.

+

This is a costly build phase, especially in clean environments where the Cython compiler must be built +This build phase can be avoided using the build switch, or an environment variable:

+
python setup.py install --no-cython
+
+
+

Alternatively, an environment variable can be used to switch this option regardless of +context:

+
CASS_DRIVER_NO_CYTHON=1 <your script here>
+- or, to disable all extensions:
+CASS_DRIVER_NO_EXTENSIONS=1 <your script here>
+
+
+

This method is required when using pip, which provides no other way of injecting user options in a single command:

+
CASS_DRIVER_NO_CYTHON=1 pip install scylla-driver
+CASS_DRIVER_NO_CYTHON=1 sudo -E pip install ~/python-driver
+
+
+

The environment variable is the preferred option because it spans all invocations of setup.py, and will +prevent Cython from being materialized as a setup requirement.

+

If your sudo configuration does not allow SETENV, you must push the option flag down via pip. However, pip +applies these options to all dependencies (which break on the custom flag). Therefore, you must first install +dependencies, then use install-option:

+
sudo pip install six futures
+sudo pip install --install-option="--no-cython"
+
+
+
+
+
+

libev support

+

The driver currently uses Python’s asyncore module for its default +event loop. For better performance, libev is also supported through +a C extension.

+

If you’re on Linux, you should be able to install libev +through a package manager. For example, on Debian/Ubuntu:

+
$ sudo apt-get install libev4 libev-dev
+
+
+

On RHEL/CentOS/Fedora:

+
$ sudo yum install libev libev-devel
+
+
+

If you’re on Mac OS X, you should be able to install libev +through Homebrew. For example, on Mac OS X:

+
$ brew install libev
+
+
+

The libev extension is not built for Windows (the build process is complex, and the Windows implementation uses +select anyway).

+

If successful, you should be able to build and install the extension +(just using setup.py build or setup.py install) and then use +the libev event loop by doing the following:

+
>>> from cassandra.io.libevreactor import LibevConnection
+>>> from cassandra.cluster import Cluster
+
+>>> cluster = Cluster()
+>>> cluster.connection_class = LibevConnection
+>>> session = cluster.connect()
+
+
+
+
+
+

(Optional) Configuring SSL

+

Andrew Mussey has published a thorough guide on +Using SSL with the DataStax Python driver.

+
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.25.4-scylla/lwt.html b/3.25.4-scylla/lwt.html new file mode 100644 index 0000000000..8391c5835a --- /dev/null +++ b/3.25.4-scylla/lwt.html @@ -0,0 +1,734 @@ + + + + + + + + + + + + + Lightweight Transactions (Compare-and-set) | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

Lightweight Transactions (Compare-and-set)

+

Lightweight Transactions (LWTs) are mostly pass-through CQL for the driver. However, +the server returns some specialized results indicating the outcome and optional state +preceding the transaction.

+

For pertinent execution parameters, see Statement.serial_consistency_level.

+

This section discusses working with specialized result sets returned by the server for LWTs, +and how to work with them using the driver.

+
+

Specialized Results

+

The result returned from a LWT request is always a single row result. It will always have +prepended a special column named [applied]. How this value appears in your results depends +on the row factory in use. See below for examples.

+

The value of this [applied] column is boolean value indicating whether or not the transaction was applied. +If True, it is the only column in the result. If False, the additional columns depend on the LWT operation being +executed:

+
    +
  • When using a UPDATE ... IF "col" = ... clause, the result will contain the [applied] column, plus the existing columns +and values for any columns in the IF clause (and thus the value that caused the transaction to fail).

  • +
  • When using INSERT ... IF NOT EXISTS, the result will contain the [applied] column, plus all columns and values +of the existing row that rejected the transaction.

  • +
  • UPDATE .. IF EXISTS never has additional columns, regardless of [applied] status.

  • +
+

How the [applied] column manifests depends on the row factory in use. Considering the following (initially empty) table:

+
CREATE TABLE test.t (
+    k int PRIMARY KEY,
+    v int,
+    x int
+)
+
+
+

… the following sections show the expected result for a number of example statements, using the three base row factories.

+
+

named_tuple_factory (default)

+

The name [applied] is not a valid Python identifier, so the square brackets are actually removed +from the attribute for the resulting namedtuple. The row always has a boolean column applied in position 0:

+
>>> session.execute("INSERT INTO t (k,v) VALUES (0,0) IF NOT EXISTS")
+Row(applied=True)
+
+>>> session.execute("INSERT INTO t (k,v) VALUES (0,0) IF NOT EXISTS")
+Row(applied=False, k=0, v=0, x=None)
+
+>>> session.execute("UPDATE t SET v = 1, x = 2 WHERE k = 0 IF v =0")
+Row(applied=True)
+
+>>> session.execute("UPDATE t SET v = 1, x = 2 WHERE k = 0 IF v =0 AND x = 1")
+Row(applied=False, v=1, x=2)
+
+
+
+
+

tuple_factory

+

This return type does not refer to names, but the boolean value applied is always present in position 0:

+
>>> session.execute("INSERT INTO t (k,v) VALUES (0,0) IF NOT EXISTS")
+(True,)
+
+>>> session.execute("INSERT INTO t (k,v) VALUES (0,0) IF NOT EXISTS")
+(False, 0, 0, None)
+
+>>> session.execute("UPDATE t SET v = 1, x = 2 WHERE k = 0 IF v =0")
+(True,)
+
+>>> session.execute("UPDATE t SET v = 1, x = 2 WHERE k = 0 IF v =0 AND x = 1")
+(False, 1, 2)
+
+
+
+
+

dict_factory

+

The retuned dict contains the [applied] key:

+
>>> session.execute("INSERT INTO t (k,v) VALUES (0,0) IF NOT EXISTS")
+{u'[applied]': True}
+
+>>> session.execute("INSERT INTO t (k,v) VALUES (0,0) IF NOT EXISTS")
+{u'x': 2, u'[applied]': False, u'v': 1}
+
+>>> session.execute("UPDATE t SET v = 1, x = 2 WHERE k = 0 IF v =0")
+{u'x': None, u'[applied]': False, u'k': 0, u'v': 0}
+
+>>> session.execute("UPDATE t SET v = 1, x = 2 WHERE k = 0 IF v =0 AND x = 1")
+{u'[applied]': True}
+
+
+
+
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.25.4-scylla/object_mapper.html b/3.25.4-scylla/object_mapper.html new file mode 100644 index 0000000000..015781c4ab --- /dev/null +++ b/3.25.4-scylla/object_mapper.html @@ -0,0 +1,731 @@ + + + + + + + + + + + + + Object Mapper | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

Object Mapper

+

cqlengine is the Cassandra CQL 3 Object Mapper packaged with this driver

+

Jump to Getting Started

+
+

Contents

+
+
Upgrade Guide

For migrating projects from legacy cqlengine, to the integrated product

+
+
Models

Examples defining models, and mapping them to tables

+
+
Making Queries

Overview of query sets and filtering

+
+
Batch Queries

Working with batch mutations

+
+
Connections

Working with multiple sessions

+
+
API Documentation

Index of API documentation

+
+
Third party integrations

High-level examples in Celery and uWSGI

+
+
+

Frequently Asked Questions

+
+
+
+
+

Getting Started

+
import uuid
+from cassandra.cqlengine import columns
+from cassandra.cqlengine import connection
+from datetime import datetime
+from cassandra.cqlengine.management import sync_table
+from cassandra.cqlengine.models import Model
+
+#first, define a model
+class ExampleModel(Model):
+    example_id      = columns.UUID(primary_key=True, default=uuid.uuid4)
+    example_type    = columns.Integer(index=True)
+    created_at      = columns.DateTime()
+    description     = columns.Text(required=False)
+
+#next, setup the connection to your cassandra server(s)...
+# see http://datastax.github.io/python-driver/api/cassandra/cluster.html for options
+# the list of hosts will be passed to create a Cluster() instance
+connection.setup(['127.0.0.1'], "cqlengine", protocol_version=3)
+
+#...and create your CQL table
+>>> sync_table(ExampleModel)
+
+#now we can create some rows:
+>>> em1 = ExampleModel.create(example_type=0, description="example1", created_at=datetime.now())
+>>> em2 = ExampleModel.create(example_type=0, description="example2", created_at=datetime.now())
+>>> em3 = ExampleModel.create(example_type=0, description="example3", created_at=datetime.now())
+>>> em4 = ExampleModel.create(example_type=0, description="example4", created_at=datetime.now())
+>>> em5 = ExampleModel.create(example_type=1, description="example5", created_at=datetime.now())
+>>> em6 = ExampleModel.create(example_type=1, description="example6", created_at=datetime.now())
+>>> em7 = ExampleModel.create(example_type=1, description="example7", created_at=datetime.now())
+>>> em8 = ExampleModel.create(example_type=1, description="example8", created_at=datetime.now())
+
+#and now we can run some queries against our table
+>>> ExampleModel.objects.count()
+8
+>>> q = ExampleModel.objects(example_type=1)
+>>> q.count()
+4
+>>> for instance in q:
+>>>     print instance.description
+example5
+example6
+example7
+example8
+
+#here we are applying additional filtering to an existing query
+#query objects are immutable, so calling filter returns a new
+#query object
+>>> q2 = q.filter(example_id=em5.example_id)
+
+>>> q2.count()
+1
+>>> for instance in q2:
+>>>     print instance.description
+example5
+
+
+
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.25.4-scylla/objects.inv b/3.25.4-scylla/objects.inv new file mode 100644 index 0000000000..5afe5fd25d Binary files /dev/null and b/3.25.4-scylla/objects.inv differ diff --git a/3.25.4-scylla/performance.html b/3.25.4-scylla/performance.html new file mode 100644 index 0000000000..02adda47bd --- /dev/null +++ b/3.25.4-scylla/performance.html @@ -0,0 +1,685 @@ + + + + + + + + + + + + + Performance Notes | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

Performance Notes

+

The Python driver for Cassandra offers several methods for executing queries. +You can synchronously block for queries to complete using +Session.execute(), you can obtain asynchronous request futures through +Session.execute_async(), and you can attach a callback to the future +with ResponseFuture.add_callback().

+

Examples of multiple request patterns can be found in the benchmark scripts included in the driver project.

+

The choice of execution pattern will depend on the application context. For applications dealing with multiple +requests in a given context, the recommended pattern is to use concurrent asynchronous +requests with callbacks. For many use cases, you don’t need to implement this pattern yourself. +cassandra.concurrent.execute_concurrent() and cassandra.concurrent.execute_concurrent_with_args() +provide this pattern with a synchronous API and tunable concurrency.

+

Due to the GIL and limited concurrency, the driver can become CPU-bound pretty quickly. The sections below +discuss further runtime and design considerations for mitigating this limitation.

+
+

PyPy

+

PyPy is an alternative Python runtime which uses a JIT compiler to +reduce CPU consumption. This leads to a huge improvement in the driver performance, +more than doubling throughput for many workloads.

+
+
+

Cython Extensions

+

Cython is an optimizing compiler and language that can be used to compile the core files and +optional extensions for the driver. Cython is not a strict dependency, but the extensions will be built by default.

+

See Installation for details on controlling this build.

+
+
+

multiprocessing

+

All of the patterns discussed above may be used over multiple processes using the +multiprocessing +module. Multiple processes will scale better than multiple threads, so if high throughput is your goal, +consider this option.

+

Be sure to never share any Cluster, Session, +or ResponseFuture objects across multiple processes. These +objects should all be created after forking the process, not before.

+

For further discussion and simple examples using the driver with multiprocessing, +see this blog post.

+
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.25.4-scylla/py-modindex.html b/3.25.4-scylla/py-modindex.html new file mode 100644 index 0000000000..71c0a5431d --- /dev/null +++ b/3.25.4-scylla/py-modindex.html @@ -0,0 +1,618 @@ + + + + + + + + + + + + + Python Module Index | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ + + +
+ + + + + +
+ + +
+
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.25.4-scylla/query_paging.html b/3.25.4-scylla/query_paging.html new file mode 100644 index 0000000000..46f4b1a0ea --- /dev/null +++ b/3.25.4-scylla/query_paging.html @@ -0,0 +1,739 @@ + + + + + + + + + + + + + Paging Large Queries | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

Paging Large Queries

+

Cassandra 2.0+ offers support for automatic query paging. Starting with +version 2.0 of the driver, if protocol_version is greater than +2 (it is by default), queries returning large result sets will be +automatically paged.

+
+

Controlling the Page Size

+

By default, Session.default_fetch_size controls how many rows will +be fetched per page. This can be overridden per-query by setting +fetch_size on a Statement. By default, each page +will contain at most 5000 rows.

+
+
+

Handling Paged Results

+

Whenever the number of result rows for are query exceed the page size, an +instance of PagedResult will be returned instead of a normal +list. This class implements the iterator interface, so you can treat +it like a normal iterator over rows:

+
from cassandra.query import SimpleStatement
+query = "SELECT * FROM users"  # users contains 100 rows
+statement = SimpleStatement(query, fetch_size=10)
+for user_row in session.execute(statement):
+    process_user(user_row)
+
+
+

Whenever there are no more rows in the current page, the next page will +be fetched transparently. However, note that it is possible for +an Exception to be raised while fetching the next page, just +like you might see on a normal call to session.execute().

+

If you use Session.execute_async() along with, +ResponseFuture.result(), the first page will be fetched before +result() returns, but latter pages will be +transparently fetched synchronously while iterating the result.

+
+
+

Handling Paged Results with Callbacks

+

If callbacks are attached to a query that returns a paged result, +the callback will be called once per page with a normal list of rows.

+

Use ResponseFuture.has_more_pages and +ResponseFuture.start_fetching_next_page() to continue fetching +pages. For example:

+
class PagedResultHandler(object):
+
+    def __init__(self, future):
+        self.error = None
+        self.finished_event = Event()
+        self.future = future
+        self.future.add_callbacks(
+            callback=self.handle_page,
+            errback=self.handle_err)
+
+    def handle_page(self, rows):
+        for row in rows:
+            process_row(row)
+
+        if self.future.has_more_pages:
+            self.future.start_fetching_next_page()
+        else:
+            self.finished_event.set()
+
+    def handle_error(self, exc):
+        self.error = exc
+        self.finished_event.set()
+
+future = session.execute_async("SELECT * FROM users")
+handler = PagedResultHandler(future)
+handler.finished_event.wait()
+if handler.error:
+    raise handler.error
+
+
+
+
+

Resume Paged Results

+

You can resume the pagination when executing a new query by using the ResultSet.paging_state. This can be useful if you want to provide some stateless pagination capabilities to your application (ie. via http). For example:

+
from cassandra.query import SimpleStatement
+query = "SELECT * FROM users"
+statement = SimpleStatement(query, fetch_size=10)
+results = session.execute(statement)
+
+# save the paging_state somewhere and return current results
+web_session['paging_state'] = results.paging_state
+
+
+# resume the pagination sometime later...
+statement = SimpleStatement(query, fetch_size=10)
+ps = web_session['paging_state']
+results = session.execute(statement, paging_state=ps)
+
+
+
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.25.4-scylla/scylla_cloud.html b/3.25.4-scylla/scylla_cloud.html new file mode 100644 index 0000000000..2054de55d3 --- /dev/null +++ b/3.25.4-scylla/scylla_cloud.html @@ -0,0 +1,637 @@ + + + + + + + + + + + + + Scylla Cloud | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

Scylla Cloud

+

To connect to a Scylla Cloud cluster, go to the Cluster Connect page, Python example. +For best performance, make sure to use the Scylla Driver.

+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.25.4-scylla/scylla_specific.html b/3.25.4-scylla/scylla_specific.html new file mode 100644 index 0000000000..10bc0c18bc --- /dev/null +++ b/3.25.4-scylla/scylla_specific.html @@ -0,0 +1,746 @@ + + + + + + + + + + + + + Scylla Specific Features | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

Scylla Specific Features

+
+

Shard Awareness

+

scylla-driver is shard aware and contains extensions that work with the TokenAwarePolicy supported by Scylla 2.3 and onwards. Using this policy, the driver can select a connection to a particular shard based on the shard’s token. +As a result, latency is significantly reduced because there is no need to pass data between the shards.

+

Details on the scylla cql protocol extensions +https://github.com/scylladb/scylla/blob/master/docs/design-notes/protocol-extensions.md#intranode-sharding

+

For using it you only need to enable TokenAwarePolicy on the Cluster

+

See the configuration of native_shard_aware_transport_port and native_shard_aware_transport_port_ssl on scylla.yaml: +https://github.com/scylladb/scylla/blob/master/docs/design-notes/protocols.md#cql-client-protocol

+
from cassandra.cluster import Cluster
+from cassandra.policies import TokenAwarePolicy, RoundRobinPolicy
+
+cluster = Cluster(load_balancing_policy=TokenAwarePolicy(RoundRobinPolicy()))
+
+
+
+
+

New Cluster Helpers

+
    +
  • shard_aware_options

    +

    Setting it to dict(disable=True) would disable the shard aware functionally, for cases favoring once connection per host (example, lots of processes connecting from one client host, generating a big load of connections

    +

    Other option is to configure scylla by setting enable_shard_aware_drivers: false on scylla.yaml.

    +
  • +
+
from cassandra.cluster import Cluster
+
+cluster = Cluster(shard_aware_options=dict(disable=True))
+session = cluster.connect()
+
+assert not cluster.is_shard_aware(), "Shard aware should be disabled"
+
+# or just disable the shard aware port logic
+cluster = Cluster(shard_aware_options=dict(disable_shardaware_port=True))
+session = cluster.connect()
+
+
+
    +
  • cluster.is_shard_aware()

    +

    New method available on Cluster allowing to check whether the remote cluster supports shard awareness (bool)

    +
  • +
+
from cassandra.cluster import Cluster
+
+cluster = Cluster()
+session = cluster.connect()
+
+if cluster.is_shard_aware():
+    print("connected to a scylla cluster")
+
+
+
    +
  • cluster.shard_aware_stats()

    +

    New method available on Cluster allowing to check the status of shard aware connections to all available hosts (dict)

    +
  • +
+
from cassandra.cluster import Cluster
+
+cluster = Cluster()
+session = cluster.connect()
+
+stats = cluster.shard_aware_stats()
+if all([v["shards_count"] == v["connected"] for v in stats.values()]):
+    print("successfully connected to all shards of all scylla nodes")
+
+
+
+
+

New Table Attributes

+
    +
  • in_memory flag

    +

    New flag available on TableMetadata.options to indicate that it is an In Memory table

    +
  • +
+
+

Note

+

in memory tables is a feature existing only in Scylla Enterprise

+
+
from cassandra.cluster import Cluster
+
+cluster = Cluster()
+session = cluster.connect()
+session.execute("""
+    CREATE KEYSPACE IF NOT EXISTS keyspace1
+    WITH replication = {'class': 'SimpleStrategy', 'replication_factor': '1'};
+""")
+
+session.execute("""
+    CREATE TABLE IF NOT EXISTS keyspace1.standard1 (
+        key blob PRIMARY KEY,
+        "C0" blob
+    ) WITH in_memory=true AND compaction={'class': 'InMemoryCompactionStrategy'}
+""")
+
+cluster.refresh_table_metadata("keyspace1", "standard1")
+assert cluster.metadata.keyspaces["keyspace1"].tables["standard1"].options["in_memory"] == True
+
+
+
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.25.4-scylla/search.html b/3.25.4-scylla/search.html new file mode 100644 index 0000000000..314f285374 --- /dev/null +++ b/3.25.4-scylla/search.html @@ -0,0 +1,621 @@ + + + + + + + + + + + + + Search | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + + + + + +
+ + + + + +
+ + +
+
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.25.4-scylla/searchindex.js b/3.25.4-scylla/searchindex.js new file mode 100644 index 0000000000..9e83cad291 --- /dev/null +++ b/3.25.4-scylla/searchindex.js @@ -0,0 +1 @@ +Search.setIndex({docnames:["CHANGELOG","api/cassandra","api/cassandra/auth","api/cassandra/cluster","api/cassandra/concurrent","api/cassandra/connection","api/cassandra/cqlengine/columns","api/cassandra/cqlengine/connection","api/cassandra/cqlengine/management","api/cassandra/cqlengine/models","api/cassandra/cqlengine/query","api/cassandra/cqlengine/usertype","api/cassandra/datastax/graph/fluent/index","api/cassandra/datastax/graph/fluent/predicates","api/cassandra/datastax/graph/fluent/query","api/cassandra/datastax/graph/index","api/cassandra/decoder","api/cassandra/encoder","api/cassandra/graph","api/cassandra/io/asyncioreactor","api/cassandra/io/asyncorereactor","api/cassandra/io/eventletreactor","api/cassandra/io/geventreactor","api/cassandra/io/libevreactor","api/cassandra/io/twistedreactor","api/cassandra/metadata","api/cassandra/metrics","api/cassandra/policies","api/cassandra/pool","api/cassandra/protocol","api/cassandra/query","api/cassandra/timestamps","api/cassandra/util","api/index","cqlengine/batches","cqlengine/connections","cqlengine/faq","cqlengine/models","cqlengine/queryset","cqlengine/third_party","cqlengine/upgrade_guide","dates_and_times","execution_profiles","faq","getting_started","index","installation","lwt","object_mapper","performance","query_paging","scylla_cloud","scylla_specific","security","upgrading","user_defined_types"],envversion:{"sphinx.domains.c":2,"sphinx.domains.changeset":1,"sphinx.domains.citation":1,"sphinx.domains.cpp":4,"sphinx.domains.index":1,"sphinx.domains.javascript":2,"sphinx.domains.math":2,"sphinx.domains.python":3,"sphinx.domains.rst":2,"sphinx.domains.std":2,"sphinx.ext.todo":2,sphinx:56},filenames:["CHANGELOG.rst","api/cassandra.rst","api/cassandra/auth.rst","api/cassandra/cluster.rst","api/cassandra/concurrent.rst","api/cassandra/connection.rst","api/cassandra/cqlengine/columns.rst","api/cassandra/cqlengine/connection.rst","api/cassandra/cqlengine/management.rst","api/cassandra/cqlengine/models.rst","api/cassandra/cqlengine/query.rst","api/cassandra/cqlengine/usertype.rst","api/cassandra/datastax/graph/fluent/index.rst","api/cassandra/datastax/graph/fluent/predicates.rst","api/cassandra/datastax/graph/fluent/query.rst","api/cassandra/datastax/graph/index.rst","api/cassandra/decoder.rst","api/cassandra/encoder.rst","api/cassandra/graph.rst","api/cassandra/io/asyncioreactor.rst","api/cassandra/io/asyncorereactor.rst","api/cassandra/io/eventletreactor.rst","api/cassandra/io/geventreactor.rst","api/cassandra/io/libevreactor.rst","api/cassandra/io/twistedreactor.rst","api/cassandra/metadata.rst","api/cassandra/metrics.rst","api/cassandra/policies.rst","api/cassandra/pool.rst","api/cassandra/protocol.rst","api/cassandra/query.rst","api/cassandra/timestamps.rst","api/cassandra/util.rst","api/index.rst","cqlengine/batches.rst","cqlengine/connections.rst","cqlengine/faq.rst","cqlengine/models.rst","cqlengine/queryset.rst","cqlengine/third_party.rst","cqlengine/upgrade_guide.rst","dates_and_times.rst","execution_profiles.rst","faq.rst","getting_started.rst","index.rst","installation.rst","lwt.rst","object_mapper.rst","performance.rst","query_paging.rst","scylla_cloud.rst","scylla_specific.rst","security.rst","upgrading.rst","user_defined_types.rst"],objects:{"":[[1,0,0,"-","cassandra"]],"cassandra.AlreadyExists":[[1,2,1,"","keyspace"],[1,2,1,"","table"]],"cassandra.ConsistencyLevel":[[1,2,1,"","ALL"],[1,2,1,"","ANY"],[1,2,1,"","EACH_QUORUM"],[1,2,1,"","LOCAL_ONE"],[1,2,1,"","LOCAL_QUORUM"],[1,2,1,"","LOCAL_SERIAL"],[1,2,1,"","ONE"],[1,2,1,"","QUORUM"],[1,2,1,"","SERIAL"],[1,2,1,"","THREE"],[1,2,1,"","TWO"]],"cassandra.CoordinationFailure":[[1,2,1,"","consistency"],[1,2,1,"","error_code_map"],[1,2,1,"","failures"],[1,2,1,"","received_responses"],[1,2,1,"","required_responses"]],"cassandra.FunctionFailure":[[1,2,1,"","arg_types"],[1,2,1,"","function"],[1,2,1,"","keyspace"]],"cassandra.OperationTimedOut":[[1,2,1,"","errors"],[1,2,1,"","last_host"]],"cassandra.ProtocolVersion":[[1,2,1,"","BETA_VERSIONS"],[1,2,1,"","DSE_V1"],[1,2,1,"","DSE_V2"],[1,2,1,"","MAX_SUPPORTED"],[1,2,1,"","MIN_SUPPORTED"],[1,2,1,"","SUPPORTED_VERSIONS"],[1,2,1,"","V1"],[1,2,1,"","V2"],[1,2,1,"","V3"],[1,2,1,"","V4"],[1,2,1,"","V5"],[1,2,1,"","V6"],[1,4,1,"","get_lower_supported"]],"cassandra.ReadFailure":[[1,2,1,"","data_retrieved"]],"cassandra.ReadTimeout":[[1,2,1,"","data_retrieved"]],"cassandra.Timeout":[[1,2,1,"","consistency"],[1,2,1,"","received_responses"],[1,2,1,"","required_responses"]],"cassandra.Unavailable":[[1,2,1,"","alive_replicas"],[1,2,1,"","consistency"],[1,2,1,"","required_replicas"]],"cassandra.UserAggregateDescriptor":[[1,2,1,"","argument_types"],[1,2,1,"","name"],[1,5,1,"","signature"]],"cassandra.UserFunctionDescriptor":[[1,2,1,"","argument_types"],[1,2,1,"","name"],[1,5,1,"","signature"]],"cassandra.WriteFailure":[[1,2,1,"","write_type"]],"cassandra.WriteTimeout":[[1,2,1,"","write_type"]],"cassandra.auth":[[2,3,1,"","AuthProvider"],[2,3,1,"","Authenticator"],[2,3,1,"","PlainTextAuthProvider"],[2,3,1,"","PlainTextAuthenticator"],[2,3,1,"","SaslAuthProvider"],[2,3,1,"","SaslAuthenticator"]],"cassandra.auth.AuthProvider":[[2,4,1,"","new_authenticator"]],"cassandra.auth.Authenticator":[[2,4,1,"","evaluate_challenge"],[2,4,1,"","initial_response"],[2,4,1,"","on_authentication_success"],[2,2,1,"","server_authenticator_class"]],"cassandra.auth.PlainTextAuthProvider":[[2,4,1,"","new_authenticator"]],"cassandra.auth.PlainTextAuthenticator":[[2,4,1,"","evaluate_challenge"]],"cassandra.auth.SaslAuthProvider":[[2,4,1,"","new_authenticator"]],"cassandra.auth.SaslAuthenticator":[[2,4,1,"","evaluate_challenge"],[2,4,1,"","initial_response"]],"cassandra.cluster":[[3,3,1,"","Cluster"],[3,6,1,"","EXEC_PROFILE_DEFAULT"],[3,6,1,"","EXEC_PROFILE_GRAPH_ANALYTICS_DEFAULT"],[3,6,1,"","EXEC_PROFILE_GRAPH_DEFAULT"],[3,6,1,"","EXEC_PROFILE_GRAPH_SYSTEM_DEFAULT"],[3,3,1,"","ExecutionProfile"],[3,3,1,"","GraphAnalyticsExecutionProfile"],[3,3,1,"","GraphExecutionProfile"],[3,1,1,"","NoHostAvailable"],[3,1,1,"","QueryExhausted"],[3,3,1,"","ResponseFuture"],[3,3,1,"","ResultSet"],[3,3,1,"","Session"],[3,1,1,"","UserTypeDoesNotExist"]],"cassandra.cluster.Cluster":[[3,4,1,"","add_execution_profile"],[3,2,1,"","address_translator"],[3,2,1,"","auth_provider"],[3,2,1,"","cloud"],[3,2,1,"","compression"],[3,4,1,"","connect"],[3,2,1,"","connect_timeout"],[3,2,1,"","connection_class"],[3,2,1,"","contact_points"],[3,2,1,"","control_connection_timeout"],[3,2,1,"","conviction_policy_factory"],[3,2,1,"","cql_version"],[3,2,1,"","default_retry_policy"],[3,2,1,"","endpoint_factory"],[3,4,1,"","get_control_connection_host"],[3,4,1,"","get_core_connections_per_host"],[3,4,1,"","get_max_connections_per_host"],[3,4,1,"","get_max_requests_per_connection"],[3,4,1,"","get_min_requests_per_connection"],[3,2,1,"","idle_heartbeat_interval"],[3,2,1,"","idle_heartbeat_timeout"],[3,2,1,"","load_balancing_policy"],[3,2,1,"","max_schema_agreement_wait"],[3,2,1,"","metadata"],[3,2,1,"","metrics"],[3,2,1,"","metrics_enabled"],[3,2,1,"","port"],[3,2,1,"","prepare_on_all_hosts"],[3,2,1,"","protocol_version"],[3,2,1,"","reconnection_policy"],[3,4,1,"","refresh_keyspace_metadata"],[3,4,1,"","refresh_nodes"],[3,4,1,"","refresh_schema_metadata"],[3,4,1,"","refresh_table_metadata"],[3,4,1,"","refresh_user_aggregate_metadata"],[3,4,1,"","refresh_user_function_metadata"],[3,4,1,"","refresh_user_type_metadata"],[3,4,1,"","register_listener"],[3,4,1,"","register_user_type"],[3,2,1,"","reprepare_on_up"],[3,2,1,"","schema_event_refresh_window"],[3,2,1,"","schema_metadata_enabled"],[3,4,1,"","set_core_connections_per_host"],[3,4,1,"","set_max_connections_per_host"],[3,4,1,"","set_max_requests_per_connection"],[3,4,1,"","set_meta_refresh_enabled"],[3,4,1,"","set_min_requests_per_connection"],[3,4,1,"","shutdown"],[3,2,1,"","sockopts"],[3,2,1,"","ssl_context"],[3,2,1,"","ssl_options"],[3,2,1,"","status_event_refresh_window"],[3,2,1,"","timestamp_generator"],[3,2,1,"","token_metadata_enabled"],[3,2,1,"","topology_event_refresh_window"],[3,4,1,"","unregister_listener"]],"cassandra.cluster.ExecutionProfile":[[3,2,1,"","consistency_level"],[3,4,1,"","row_factory"]],"cassandra.cluster.ResponseFuture":[[3,4,1,"","add_callback"],[3,4,1,"","add_errback"],[3,2,1,"","custom_payload"],[3,4,1,"","get_all_query_traces"],[3,4,1,"","get_query_trace"],[3,2,1,"","has_more_pages"],[3,2,1,"","is_schema_agreed"],[3,2,1,"","query"],[3,4,1,"","result"],[3,4,1,"","start_fetching_next_page"],[3,2,1,"","warnings"]],"cassandra.cluster.ResultSet":[[3,4,1,"","all"],[3,5,1,"","current_rows"],[3,4,1,"","fetch_next_page"],[3,4,1,"","get_all_query_traces"],[3,4,1,"","get_query_trace"],[3,5,1,"","has_more_pages"],[3,4,1,"","one"],[3,5,1,"","paging_state"],[3,5,1,"","was_applied"]],"cassandra.cluster.Session":[[3,4,1,"","add_request_init_listener"],[3,2,1,"","client_protocol_handler"],[3,2,1,"","default_consistency_level"],[3,2,1,"","default_fetch_size"],[3,2,1,"","default_serial_consistency_level"],[3,2,1,"","default_timeout"],[3,2,1,"","encoder"],[3,4,1,"","execute"],[3,4,1,"","execute_async"],[3,4,1,"","execute_graph"],[3,4,1,"","execute_graph_async"],[3,4,1,"","execution_profile_clone_update"],[3,4,1,"","get_execution_profile"],[3,4,1,"","prepare"],[3,4,1,"","remove_request_init_listener"],[3,2,1,"","row_factory"],[3,4,1,"","set_keyspace"],[3,4,1,"","shutdown"],[3,2,1,"","timestamp_generator"],[3,2,1,"","use_client_timestamp"]],"cassandra.concurrent":[[4,7,1,"","execute_concurrent"],[4,7,1,"","execute_concurrent_with_args"]],"cassandra.connection":[[5,1,1,"","ConnectionBusy"],[5,1,1,"","ConnectionException"],[5,1,1,"","ConnectionShutdown"],[5,3,1,"","EndPoint"],[5,3,1,"","EndPointFactory"],[5,1,1,"","ProtocolError"],[5,3,1,"","SniEndPoint"],[5,3,1,"","SniEndPointFactory"],[5,3,1,"","UnixSocketEndPoint"]],"cassandra.connection.EndPoint":[[5,5,1,"","address"],[5,5,1,"","port"],[5,4,1,"","resolve"],[5,5,1,"","socket_family"],[5,5,1,"","ssl_options"]],"cassandra.connection.EndPointFactory":[[5,4,1,"","configure"],[5,4,1,"","create"]],"cassandra.cqlengine":[[6,0,0,"-","columns"],[7,0,0,"-","connection"],[8,0,0,"-","management"],[9,0,0,"-","models"],[10,0,0,"-","query"],[11,0,0,"-","usertype"]],"cassandra.cqlengine.columns":[[6,3,1,"","Ascii"],[6,3,1,"","BigInt"],[6,3,1,"","Blob"],[6,3,1,"","Boolean"],[6,2,1,"","Bytes"],[6,3,1,"","Column"],[6,3,1,"","Counter"],[6,3,1,"","Date"],[6,3,1,"","DateTime"],[6,3,1,"","Decimal"],[6,3,1,"","Double"],[6,3,1,"","Float"],[6,3,1,"","Integer"],[6,3,1,"","List"],[6,3,1,"","Map"],[6,3,1,"","Set"],[6,3,1,"","SmallInt"],[6,3,1,"","Text"],[6,3,1,"","Time"],[6,3,1,"","TimeUUID"],[6,3,1,"","TinyInt"],[6,3,1,"","UUID"],[6,3,1,"","UserDefinedType"],[6,3,1,"","VarInt"]],"cassandra.cqlengine.columns.Column":[[6,2,1,"","clustering_order"],[6,2,1,"","custom_index"],[6,2,1,"","db_field"],[6,2,1,"","default"],[6,2,1,"","discriminator_column"],[6,2,1,"","index"],[6,2,1,"","partition_key"],[6,2,1,"","primary_key"],[6,2,1,"","required"],[6,2,1,"","static"]],"cassandra.cqlengine.columns.DateTime":[[6,2,1,"","truncate_microseconds"]],"cassandra.cqlengine.connection":[[7,7,1,"","default"],[7,7,1,"","register_connection"],[7,7,1,"","set_default_connection"],[7,7,1,"","set_session"],[7,7,1,"","setup"],[7,7,1,"","unregister_connection"]],"cassandra.cqlengine.management":[[8,7,1,"","create_keyspace_network_topology"],[8,7,1,"","create_keyspace_simple"],[8,7,1,"","drop_keyspace"],[8,7,1,"","drop_table"],[8,7,1,"","sync_table"],[8,7,1,"","sync_type"]],"cassandra.cqlengine.models":[[9,3,1,"","Model"]],"cassandra.cqlengine.models.Model":[[9,2,1,"","__abstract__"],[9,2,1,"","__compute_routing_key__"],[9,2,1,"","__connection__"],[9,2,1,"","__default_ttl__"],[9,2,1,"","__discriminator_value__"],[9,2,1,"","__keyspace__"],[9,2,1,"","__options__"],[9,2,1,"","__table_name__"],[9,2,1,"","__table_name_case_sensitive__"],[9,4,1,"","all"],[9,4,1,"","batch"],[9,4,1,"","column_family_name"],[9,4,1,"","create"],[9,4,1,"","delete"],[9,4,1,"","filter"],[9,4,1,"","get"],[9,4,1,"","if_exists"],[9,4,1,"","if_not_exists"],[9,4,1,"","iff"],[9,4,1,"","items"],[9,4,1,"","keys"],[9,4,1,"","len"],[9,4,1,"","save"],[9,4,1,"","timeout"],[9,4,1,"","timestamp"],[9,4,1,"","ttl"],[9,4,1,"","update"],[9,4,1,"","using"],[9,4,1,"","values"]],"cassandra.cqlengine.query":[[10,3,1,"","BatchQuery"],[10,3,1,"","ContextQuery"],[10,3,1,"","DoesNotExist"],[10,3,1,"","LWTException"],[10,3,1,"","ModelQuerySet"],[10,3,1,"","MultipleObjectsReturned"]],"cassandra.cqlengine.query.BatchQuery":[[10,4,1,"","add_callback"],[10,4,1,"","add_query"],[10,4,1,"","execute"]],"cassandra.cqlengine.query.ModelQuerySet":[[10,4,1,"","all"],[10,4,1,"","allow_filtering"],[10,4,1,"","batch"],[10,4,1,"","consistency"],[10,4,1,"","count"],[10,4,1,"","defer"],[10,4,1,"","distinct"],[10,4,1,"","fetch_size"],[10,4,1,"","filter"],[10,4,1,"","get"],[10,4,1,"","if_exists"],[10,4,1,"","if_not_exists"],[10,4,1,"","len"],[10,4,1,"","limit"],[10,4,1,"","only"],[10,4,1,"","order_by"],[10,4,1,"","timestamp"],[10,4,1,"","ttl"],[10,4,1,"","update"],[10,4,1,"","using"]],"cassandra.cqlengine.usertype":[[11,3,1,"","UserType"]],"cassandra.cqlengine.usertype.UserType":[[11,2,1,"","__type_name__"]],"cassandra.datastax":[[15,0,0,"-","graph"]],"cassandra.datastax.graph":[[12,0,0,"-","fluent"],[15,7,1,"","graph_graphson2_row_factory"],[15,7,1,"","graph_graphson3_row_factory"],[15,7,1,"","graph_object_row_factory"],[15,7,1,"","graph_result_row_factory"],[15,7,1,"","single_object_row_factory"],[15,7,1,"","to_bigint"],[15,7,1,"","to_double"],[15,7,1,"","to_float"],[15,7,1,"","to_int"],[15,7,1,"","to_smallint"]],"cassandra.datastax.graph.GraphOptions":[[15,2,1,"","graph_language"],[15,2,1,"","graph_name"],[15,2,1,"","graph_read_consistency_level"],[15,2,1,"","graph_source"],[15,2,1,"","graph_write_consistency_level"],[15,2,1,"","is_analytics_source"],[15,2,1,"","is_default_source"],[15,2,1,"","is_graph_source"],[15,4,1,"","set_source_analytics"],[15,4,1,"","set_source_default"],[15,4,1,"","set_source_graph"]],"cassandra.datastax.graph.GraphSON1Deserializer":[[15,4,1,"","deserialize_bigint"],[15,4,1,"","deserialize_blob"],[15,4,1,"","deserialize_date"],[15,4,1,"","deserialize_decimal"],[15,4,1,"","deserialize_double"],[15,4,1,"","deserialize_duration"],[15,4,1,"","deserialize_float"],[15,4,1,"","deserialize_int"],[15,4,1,"","deserialize_linestring"],[15,4,1,"","deserialize_point"],[15,4,1,"","deserialize_polygon"],[15,4,1,"","deserialize_time"],[15,4,1,"","deserialize_timestamp"],[15,4,1,"","deserialize_uuid"]],"cassandra.datastax.graph.fluent":[[12,3,1,"","BaseGraphRowFactory"],[12,3,1,"","DSESessionRemoteGraphConnection"],[12,3,1,"","DseGraph"],[12,2,1,"","graph_traversal_dse_object_row_factory"],[12,2,1,"","graph_traversal_row_factory"],[13,0,0,"-","predicates"],[14,0,0,"-","query"]],"cassandra.datastax.graph.fluent.DseGraph":[[12,2,1,"","DSE_GRAPH_QUERY_LANGUAGE"],[12,4,1,"","batch"],[12,4,1,"","create_execution_profile"],[12,4,1,"","query_from_traversal"],[12,4,1,"","traversal_source"]],"cassandra.datastax.graph.fluent.predicates":[[13,3,1,"","CqlCollection"],[13,3,1,"","Geo"],[13,3,1,"","Search"]],"cassandra.datastax.graph.fluent.predicates.CqlCollection":[[13,4,1,"","contains"],[13,4,1,"","contains_key"],[13,4,1,"","contains_value"],[13,4,1,"","entry_eq"]],"cassandra.datastax.graph.fluent.predicates.Geo":[[13,4,1,"","inside"]],"cassandra.datastax.graph.fluent.predicates.Search":[[13,4,1,"","fuzzy"],[13,4,1,"","phrase"],[13,4,1,"","prefix"],[13,4,1,"","regex"],[13,4,1,"","token"],[13,4,1,"","token_fuzzy"],[13,4,1,"","token_prefix"],[13,4,1,"","token_regex"]],"cassandra.datastax.graph.fluent.query":[[14,3,1,"","TraversalBatch"]],"cassandra.datastax.graph.fluent.query.TraversalBatch":[[14,4,1,"","add"],[14,4,1,"","add_all"],[14,4,1,"","as_graph_statement"],[14,4,1,"","clear"],[14,4,1,"","execute"]],"cassandra.decoder":[[16,7,1,"","dict_factory"],[16,7,1,"","named_tuple_factory"],[16,7,1,"","ordered_dict_factory"],[16,7,1,"","tuple_factory"]],"cassandra.encoder":[[17,3,1,"","Encoder"]],"cassandra.encoder.Encoder":[[17,4,1,"","cql_encode_all_types"],[17,4,1,"","cql_encode_bytes"],[17,4,1,"","cql_encode_date"],[17,4,1,"","cql_encode_datetime"],[17,4,1,"","cql_encode_list_collection"],[17,4,1,"","cql_encode_map_collection"],[17,4,1,"","cql_encode_none"],[17,4,1,"","cql_encode_object"],[17,4,1,"","cql_encode_sequence"],[17,4,1,"","cql_encode_set_collection"],[17,4,1,"","cql_encode_str"],[17,4,1,"","cql_encode_tuple"],[17,4,1,"","cql_encode_unicode"],[17,2,1,"","mapping"]],"cassandra.graph":[[18,3,1,"","Edge"],[18,3,1,"","GraphOptions"],[18,3,1,"","GraphProtocol"],[18,3,1,"","GraphSON1Deserializer"],[18,3,1,"","GraphSON1Serializer"],[18,3,1,"","GraphSON2Reader"],[18,3,1,"","GraphSON3Reader"],[18,3,1,"","Path"],[18,3,1,"","Result"],[18,3,1,"","SimpleGraphStatement"],[18,3,1,"","Vertex"],[18,3,1,"","VertexProperty"],[18,7,1,"","graph_graphson2_row_factory"],[18,7,1,"","graph_graphson3_row_factory"],[18,7,1,"","graph_object_row_factory"],[18,7,1,"","graph_result_row_factory"],[18,7,1,"","single_object_row_factory"],[18,7,1,"","to_bigint"],[18,7,1,"","to_double"],[18,7,1,"","to_float"],[18,7,1,"","to_int"],[18,7,1,"","to_smallint"]],"cassandra.graph.GraphOptions":[[18,2,1,"","graph_language"],[18,2,1,"","graph_name"],[18,2,1,"","graph_read_consistency_level"],[18,2,1,"","graph_source"],[18,2,1,"","graph_write_consistency_level"],[18,2,1,"","is_analytics_source"],[18,2,1,"","is_default_source"],[18,2,1,"","is_graph_source"],[18,4,1,"","set_source_analytics"],[18,4,1,"","set_source_default"],[18,4,1,"","set_source_graph"]],"cassandra.graph.GraphProtocol":[[18,2,1,"","GRAPHSON_1_0"],[18,2,1,"","GRAPHSON_2_0"],[18,2,1,"","GRAPHSON_3_0"]],"cassandra.graph.GraphSON1Deserializer":[[18,4,1,"","deserialize_bigint"],[18,4,1,"","deserialize_blob"],[18,4,1,"","deserialize_date"],[18,4,1,"","deserialize_decimal"],[18,4,1,"","deserialize_double"],[18,4,1,"","deserialize_duration"],[18,4,1,"","deserialize_float"],[18,4,1,"","deserialize_int"],[18,4,1,"","deserialize_linestring"],[18,4,1,"","deserialize_point"],[18,4,1,"","deserialize_polygon"],[18,4,1,"","deserialize_time"],[18,4,1,"","deserialize_timestamp"],[18,4,1,"","deserialize_uuid"]],"cassandra.graph.GraphSON2Reader":[[18,4,1,"","deserialize"],[18,4,1,"","read"]],"cassandra.graph.Path":[[18,2,1,"","labels"],[18,2,1,"","objects"]],"cassandra.graph.Result":[[18,4,1,"","as_edge"],[18,4,1,"","as_path"],[18,4,1,"","as_vertex"],[18,2,1,"","value"]],"cassandra.graph.VertexProperty":[[18,2,1,"","label"],[18,2,1,"","properties"],[18,2,1,"","value"]],"cassandra.io":[[19,0,0,"-","asyncioreactor"],[20,0,0,"-","asyncorereactor"],[21,0,0,"-","eventletreactor"],[22,0,0,"-","geventreactor"],[23,0,0,"-","libevreactor"],[24,0,0,"-","twistedreactor"]],"cassandra.io.asyncioreactor":[[19,3,1,"","AsyncioConnection"]],"cassandra.io.asyncioreactor.AsyncioConnection":[[19,4,1,"","initialize_reactor"]],"cassandra.io.asyncorereactor":[[20,3,1,"","AsyncoreConnection"]],"cassandra.io.asyncorereactor.AsyncoreConnection":[[20,4,1,"","handle_fork"],[20,4,1,"","initialize_reactor"]],"cassandra.io.eventletreactor":[[21,3,1,"","EventletConnection"]],"cassandra.io.eventletreactor.EventletConnection":[[21,4,1,"","initialize_reactor"],[21,4,1,"","service_timeouts"]],"cassandra.io.geventreactor":[[22,3,1,"","GeventConnection"]],"cassandra.io.geventreactor.GeventConnection":[[22,4,1,"","initialize_reactor"]],"cassandra.io.libevreactor":[[23,3,1,"","LibevConnection"]],"cassandra.io.twistedreactor":[[24,3,1,"","TwistedConnection"]],"cassandra.metadata":[[25,3,1,"","Aggregate"],[25,3,1,"","BytesToken"],[25,3,1,"","ColumnMetadata"],[25,3,1,"","EdgeMetadata"],[25,3,1,"","Function"],[25,3,1,"","IndexMetadata"],[25,3,1,"","KeyspaceMetadata"],[25,3,1,"","LocalStrategy"],[25,3,1,"","MD5Token"],[25,3,1,"","MaterializedViewMetadata"],[25,3,1,"","Metadata"],[25,3,1,"","Murmur3Token"],[25,3,1,"","NetworkTopologyStrategy"],[25,3,1,"","ReplicationFactor"],[25,2,1,"","ReplicationStrategy"],[25,3,1,"","SimpleStrategy"],[25,3,1,"","TableMetadata"],[25,3,1,"","TableMetadataDSE68"],[25,3,1,"","TableMetadataV3"],[25,3,1,"","Token"],[25,3,1,"","TokenMap"],[25,3,1,"","UserType"],[25,3,1,"","VertexMetadata"],[25,6,1,"","cql_keywords"],[25,6,1,"","cql_keywords_reserved"],[25,6,1,"","cql_keywords_unreserved"],[25,7,1,"","group_keys_by_replica"]],"cassandra.metadata.Aggregate":[[25,4,1,"","as_cql_query"]],"cassandra.metadata.BytesToken":[[25,4,1,"","from_string"]],"cassandra.metadata.Function":[[25,4,1,"","as_cql_query"]],"cassandra.metadata.IndexMetadata":[[25,4,1,"","as_cql_query"],[25,4,1,"","export_as_string"]],"cassandra.metadata.KeyspaceMetadata":[[25,4,1,"","as_cql_query"],[25,4,1,"","export_as_string"]],"cassandra.metadata.LocalStrategy":[[25,4,1,"","export_for_schema"]],"cassandra.metadata.MaterializedViewMetadata":[[25,4,1,"","as_cql_query"]],"cassandra.metadata.Metadata":[[25,4,1,"","add_or_return_host"],[25,4,1,"","all_hosts"],[25,4,1,"","export_schema_as_string"],[25,4,1,"","get_host"],[25,4,1,"","get_host_by_host_id"],[25,4,1,"","get_replicas"]],"cassandra.metadata.NetworkTopologyStrategy":[[25,4,1,"","export_for_schema"]],"cassandra.metadata.SimpleStrategy":[[25,4,1,"","export_for_schema"],[25,5,1,"","replication_factor"]],"cassandra.metadata.TableMetadata":[[25,4,1,"","as_cql_query"],[25,4,1,"","export_as_string"],[25,5,1,"","is_cql_compatible"],[25,5,1,"","primary_key"]],"cassandra.metadata.TableMetadataDSE68":[[25,4,1,"","as_cql_query"]],"cassandra.metadata.TableMetadataV3":[[25,5,1,"","is_cql_compatible"]],"cassandra.metadata.TokenMap":[[25,4,1,"","get_replicas"]],"cassandra.metadata.UserType":[[25,4,1,"","as_cql_query"]],"cassandra.metrics":[[26,3,1,"","Metrics"]],"cassandra.metrics.Metrics":[[26,2,1,"","connected_to"],[26,2,1,"","connection_errors"],[26,4,1,"","get_stats"],[26,2,1,"","ignores"],[26,2,1,"","known_hosts"],[26,2,1,"","open_connections"],[26,2,1,"","other_errors"],[26,2,1,"","read_timeouts"],[26,2,1,"","request_timer"],[26,2,1,"","retries"],[26,4,1,"","set_stats_name"],[26,2,1,"","unavailables"],[26,2,1,"","write_timeouts"]],"cassandra.policies":[[27,3,1,"","AddressTranslator"],[27,3,1,"","ConstantReconnectionPolicy"],[27,3,1,"","ConstantSpeculativeExecutionPolicy"],[27,3,1,"","ConvictionPolicy"],[27,3,1,"","DCAwareRoundRobinPolicy"],[27,3,1,"","DSELoadBalancingPolicy"],[27,3,1,"","DefaultLoadBalancingPolicy"],[27,3,1,"","DowngradingConsistencyRetryPolicy"],[27,3,1,"","EC2MultiRegionTranslator"],[27,3,1,"","ExponentialReconnectionPolicy"],[27,3,1,"","FallthroughRetryPolicy"],[27,3,1,"","HostDistance"],[27,3,1,"","HostFilterPolicy"],[27,3,1,"","IdentityTranslator"],[27,3,1,"","LoadBalancingPolicy"],[27,3,1,"","ReconnectionPolicy"],[27,3,1,"","RetryPolicy"],[27,3,1,"","RoundRobinPolicy"],[27,3,1,"","SimpleConvictionPolicy"],[27,3,1,"","SpeculativeExecutionPolicy"],[27,3,1,"","TokenAwarePolicy"],[27,3,1,"","WhiteListRoundRobinPolicy"],[27,3,1,"","WriteType"]],"cassandra.policies.AddressTranslator":[[27,4,1,"","translate"]],"cassandra.policies.ConstantReconnectionPolicy":[[27,4,1,"","new_schedule"]],"cassandra.policies.ConstantSpeculativeExecutionPolicy":[[27,4,1,"","new_plan"]],"cassandra.policies.ConvictionPolicy":[[27,4,1,"","add_failure"],[27,4,1,"","reset"]],"cassandra.policies.DCAwareRoundRobinPolicy":[[27,4,1,"","distance"],[27,4,1,"","make_query_plan"],[27,4,1,"","on_add"],[27,4,1,"","on_down"],[27,4,1,"","on_remove"],[27,4,1,"","on_up"],[27,4,1,"","populate"]],"cassandra.policies.DefaultLoadBalancingPolicy":[[27,4,1,"","make_query_plan"],[27,4,1,"","populate"]],"cassandra.policies.DowngradingConsistencyRetryPolicy":[[27,4,1,"","on_read_timeout"],[27,4,1,"","on_unavailable"],[27,4,1,"","on_write_timeout"]],"cassandra.policies.EC2MultiRegionTranslator":[[27,4,1,"","translate"]],"cassandra.policies.ExponentialReconnectionPolicy":[[27,4,1,"","new_schedule"]],"cassandra.policies.FallthroughRetryPolicy":[[27,4,1,"","on_read_timeout"],[27,4,1,"","on_request_error"],[27,4,1,"","on_unavailable"],[27,4,1,"","on_write_timeout"]],"cassandra.policies.HostDistance":[[27,2,1,"","IGNORED"],[27,2,1,"","LOCAL"],[27,2,1,"","REMOTE"]],"cassandra.policies.HostFilterPolicy":[[27,4,1,"","distance"],[27,4,1,"","make_query_plan"],[27,4,1,"","predicate"]],"cassandra.policies.IdentityTranslator":[[27,4,1,"","translate"]],"cassandra.policies.LoadBalancingPolicy":[[27,4,1,"","check_supported"],[27,4,1,"","distance"],[27,4,1,"","make_query_plan"],[27,4,1,"","populate"]],"cassandra.policies.ReconnectionPolicy":[[27,4,1,"","new_schedule"]],"cassandra.policies.RetryPolicy":[[27,2,1,"","IGNORE"],[27,2,1,"","RETHROW"],[27,2,1,"","RETRY"],[27,2,1,"","RETRY_NEXT_HOST"],[27,4,1,"","on_read_timeout"],[27,4,1,"","on_request_error"],[27,4,1,"","on_unavailable"],[27,4,1,"","on_write_timeout"]],"cassandra.policies.RoundRobinPolicy":[[27,4,1,"","distance"],[27,4,1,"","make_query_plan"],[27,4,1,"","on_add"],[27,4,1,"","on_down"],[27,4,1,"","on_remove"],[27,4,1,"","on_up"],[27,4,1,"","populate"]],"cassandra.policies.SimpleConvictionPolicy":[[27,4,1,"","add_failure"],[27,4,1,"","reset"]],"cassandra.policies.SpeculativeExecutionPolicy":[[27,4,1,"","new_plan"]],"cassandra.policies.TokenAwarePolicy":[[27,4,1,"","check_supported"],[27,4,1,"","distance"],[27,4,1,"","make_query_plan"],[27,4,1,"","on_add"],[27,4,1,"","on_down"],[27,4,1,"","on_remove"],[27,4,1,"","on_up"],[27,4,1,"","populate"],[27,2,1,"","shuffle_replicas"]],"cassandra.policies.WhiteListRoundRobinPolicy":[[27,4,1,"","distance"],[27,4,1,"","on_add"],[27,4,1,"","on_up"],[27,4,1,"","populate"]],"cassandra.policies.WriteType":[[27,2,1,"","BATCH"],[27,2,1,"","BATCH_LOG"],[27,2,1,"","CAS"],[27,2,1,"","CDC"],[27,2,1,"","COUNTER"],[27,2,1,"","SIMPLE"],[27,2,1,"","UNLOGGED_BATCH"],[27,2,1,"","VIEW"]],"cassandra.pool":[[28,3,1,"","Host"],[28,1,1,"","NoConnectionsAvailable"]],"cassandra.pool.Host":[[28,5,1,"","address"],[28,5,1,"","datacenter"],[28,5,1,"","rack"]],"cassandra.protocol":[[29,3,1,"","_ProtocolHandler"]],"cassandra.protocol._ProtocolHandler":[[29,4,1,"","decode_message"],[29,4,1,"","encode_message"],[29,2,1,"","message_types_by_opcode"]],"cassandra.query":[[30,3,1,"","BatchStatement"],[30,3,1,"","BatchType"],[30,3,1,"","BoundStatement"],[30,3,1,"","PreparedStatement"],[30,3,1,"","QueryTrace"],[30,3,1,"","SimpleStatement"],[30,3,1,"","Statement"],[30,3,1,"","TraceEvent"],[30,1,1,"","TraceUnavailable"],[30,6,1,"","UNSET_VALUE"],[30,3,1,"","ValueSequence"],[30,7,1,"","dict_factory"],[30,7,1,"","named_tuple_factory"],[30,7,1,"","ordered_dict_factory"],[30,7,1,"","tuple_factory"]],"cassandra.query.BatchStatement":[[30,4,1,"","add"],[30,4,1,"","add_all"],[30,4,1,"","clear"],[30,2,1,"","serial_consistency_level"]],"cassandra.query.BatchType":[[30,2,1,"","COUNTER"],[30,2,1,"","LOGGED"],[30,2,1,"","UNLOGGED"]],"cassandra.query.BoundStatement":[[30,4,1,"","bind"],[30,5,1,"","routing_key"]],"cassandra.query.PreparedStatement":[[30,4,1,"","bind"]],"cassandra.query.QueryTrace":[[30,4,1,"","populate"]],"cassandra.query.Statement":[[30,5,1,"","routing_key"],[30,5,1,"","serial_consistency_level"]],"cassandra.timestamps":[[31,3,1,"","MonotonicTimestampGenerator"]],"cassandra.timestamps.MonotonicTimestampGenerator":[[31,4,1,"","_next_timestamp"],[31,2,1,"","warn_on_drift"],[31,2,1,"","warning_interval"],[31,2,1,"","warning_threshold"]],"cassandra.util":[[32,3,1,"","Date"],[32,3,1,"","DateRange"],[32,3,1,"","DateRangeBound"],[32,3,1,"","DateRangePrecision"],[32,3,1,"","Distance"],[32,3,1,"","Duration"],[32,3,1,"","LineString"],[32,3,1,"","OrderedMap"],[32,3,1,"","OrderedMapSerializedKey"],[32,3,1,"","Point"],[32,3,1,"","Polygon"],[32,3,1,"","SortedSet"],[32,3,1,"","Time"],[32,3,1,"","Version"],[32,7,1,"","datetime_from_timestamp"],[32,7,1,"","datetime_from_uuid1"],[32,7,1,"","max_uuid_from_time"],[32,7,1,"","min_uuid_from_time"],[32,7,1,"","ms_timestamp_from_datetime"],[32,2,1,"","sortedset"],[32,7,1,"","unix_time_from_uuid1"],[32,7,1,"","utc_datetime_from_ms_timestamp"],[32,7,1,"","uuid_from_time"]],"cassandra.util.Date":[[32,4,1,"","date"],[32,5,1,"","seconds"]],"cassandra.util.DateRange":[[32,2,1,"","lower_bound"],[32,2,1,"","upper_bound"],[32,2,1,"","value"]],"cassandra.util.DateRangeBound":[[32,4,1,"","datetime"],[32,4,1,"","from_value"],[32,2,1,"","milliseconds"],[32,2,1,"","precision"]],"cassandra.util.Distance":[[32,4,1,"","from_wkt"]],"cassandra.util.LineString":[[32,4,1,"","from_wkt"]],"cassandra.util.Point":[[32,4,1,"","from_wkt"]],"cassandra.util.Polygon":[[32,4,1,"","from_wkt"]],"cassandra.util.Time":[[32,5,1,"","hour"],[32,5,1,"","minute"],[32,5,1,"","nanosecond"],[32,5,1,"","second"],[32,4,1,"","time"]],"cqlengine.queryset":[[38,3,1,"","MaxTimeUUID"],[38,3,1,"","MinTimeUUID"]],cassandra:[[1,1,1,"","AlreadyExists"],[1,1,1,"","AuthenticationFailed"],[1,1,1,"","ConfigurationException"],[1,3,1,"","ConsistencyLevel"],[1,1,1,"","CoordinationFailure"],[1,1,1,"","DriverException"],[1,1,1,"","FunctionFailure"],[1,1,1,"","InvalidRequest"],[1,1,1,"","OperationTimedOut"],[1,3,1,"","ProtocolVersion"],[1,1,1,"","ReadFailure"],[1,1,1,"","ReadTimeout"],[1,1,1,"","RequestExecutionException"],[1,1,1,"","RequestValidationException"],[1,1,1,"","Timeout"],[1,1,1,"","Unauthorized"],[1,1,1,"","Unavailable"],[1,3,1,"","UserAggregateDescriptor"],[1,3,1,"","UserFunctionDescriptor"],[1,1,1,"","WriteFailure"],[1,1,1,"","WriteTimeout"],[1,6,1,"","__version__"],[1,6,1,"","__version_info__"],[2,0,0,"-","auth"],[3,0,0,"-","cluster"],[4,0,0,"-","concurrent"],[5,0,0,"-","connection"],[16,0,0,"-","decoder"],[17,0,0,"-","encoder"],[18,0,0,"-","graph"],[25,0,0,"-","metadata"],[26,0,0,"-","metrics"],[27,0,0,"-","policies"],[28,0,0,"-","pool"],[29,0,0,"-","protocol"],[30,0,0,"-","query"],[31,0,0,"-","timestamps"],[32,0,0,"-","util"]],cqlengine:[[37,0,0,"-","models"],[38,0,0,"-","queryset"]]},objnames:{"0":["py","module","Python module"],"1":["py","exception","Python exception"],"2":["py","attribute","Python attribute"],"3":["py","class","Python class"],"4":["py","method","Python method"],"5":["py","property","Python property"],"6":["py","data","Python data"],"7":["py","function","Python function"]},objtypes:{"0":"py:module","1":"py:exception","2":"py:attribute","3":"py:class","4":"py:method","5":"py:property","6":"py:data","7":"py:function"},terms:{"0":[1,2,3,4,6,9,10,12,14,15,16,18,25,27,30,31,32,34,35,37,38,42,43,44,46,47,48,50,55],"00":43,"000":10,"000077":43,"000153":43,"000309":43,"000368":43,"000422":43,"000480":43,"000669":43,"000755":43,"031ebb0":54,"04":0,"05":38,"0l":38,"0m":0,"1":[1,2,3,4,6,10,13,15,18,19,25,27,30,31,32,34,35,36,38,42,43,44,46,47,48,52,53,55],"10":[1,3,10,38,44,46,50],"100":[0,4,10,42,50],"1000":[0,4],"1004":0,"1005":0,"1006":0,"1007":0,"1008":0,"1009":0,"101":0,"1012":0,"1013":0,"1015":0,"1016":0,"1017":0,"1018":0,"1019":0,"1020":0,"1021":0,"1023":0,"1024":0,"1026":0,"1027":0,"103":0,"1031":0,"1033":0,"1036":0,"1039":0,"104":0,"1042":0,"1044":0,"1045":0,"1047":0,"1048":0,"105":0,"1051":0,"1054":0,"1056":0,"1057":0,"106":0,"1060":0,"1064":0,"1065":0,"1067":0,"1068":0,"1074":0,"10786":30,"1079":0,"108":0,"1081":0,"1082":0,"1087":0,"1089":0,"109":0,"1090":0,"1091":0,"1093":0,"10l":38,"110":0,"1100":0,"1104":0,"1105":0,"111":[0,36],"111111111111":9,"1117":0,"1118":0,"1119":0,"112":0,"1121":0,"1122":0,"1123":0,"1124":0,"1127":0,"1129":0,"1130":0,"1140":0,"1158":0,"116":0,"1161":0,"1162":0,"1163":0,"1166":0,"1172":0,"1174":0,"1177":0,"1181":0,"1183":0,"1185":0,"1186":0,"1187":0,"1189":0,"119":[0,32],"1192":0,"11e3":44,"11l":38,"120":0,"1203":0,"1204":0,"1205":0,"1207":0,"1212":0,"122":0,"1220":0,"1228":0,"123":[0,3,36,55],"1233":0,"1234":53,"1237":0,"1238":0,"1239":0,"124":0,"1240":0,"1241":0,"1243":0,"1244":0,"1245":0,"1248":0,"125":0,"1258":0,"126":0,"1260":0,"1264":0,"1265":0,"1266":0,"1269":0,"127":[3,25,35,38,42,43,44,48,53],"12l":38,"135":0,"138":0,"13l":38,"14":32,"141":0,"143":0,"144":0,"145":27,"147":0,"148":0,"14l":38,"15":[27,44],"150":0,"151":0,"155":0,"157":0,"159":0,"15l":38,"16":6,"160":0,"163":0,"164":0,"165":0,"166":0,"167":0,"168":[3,44],"16l":38,"17":[38,53],"173":0,"174":0,"175":0,"178":[0,30,54],"179":0,"17l":38,"180":0,"181":0,"182":0,"184":0,"185":0,"186":0,"187":0,"189":0,"18l":38,"190":0,"191":0,"192":[0,3,44],"194":0,"195":0,"196":0,"197":0,"1970":32,"198":0,"1982":38,"19l":38,"1e6":31,"1l":38,"1s":0,"2":[1,2,3,4,6,9,10,12,13,14,15,16,18,25,27,30,32,34,35,36,38,40,42,43,44,45,46,47,50,52,53,55],"20":38,"200":0,"2008":10,"2010":[35,38],"2011":38,"2012":38,"2013":[0,45],"2014":[0,38],"2015":0,"2016":[0,45],"2017":[0,45],"2018":0,"2019":0,"202":0,"2020":0,"2021":0,"204":0,"2048":53,"205":0,"206":0,"207":0,"208":0,"21":[38,54],"210":0,"211":0,"212":0,"213":0,"215":0,"218":0,"219":0,"22":46,"220":0,"222":0,"226":0,"229":0,"23":32,"230":0,"231":0,"234":0,"235":0,"238":0,"239":0,"24":3,"240":0,"241":0,"243":0,"244":0,"245":[0,40],"246":0,"249":0,"255":0,"258":0,"26":[0,38],"260":0,"2644bada":44,"266":0,"27":0,"272":0,"273":0,"276":[0,54],"277":0,"278":0,"279":43,"28":0,"280":0,"282":0,"283":0,"284":0,"285":0,"286":0,"288":0,"289":0,"29":0,"291":0,"292":[0,54],"294":0,"295":0,"296":0,"297":0,"298":0,"299":0,"2l":38,"3":[1,2,3,4,6,9,10,15,18,19,25,27,30,31,32,34,36,37,38,45,46,48,52,55],"30":[0,3,38,42,44],"300":0,"301":0,"302":0,"303":0,"305":0,"306":0,"309":0,"31":[0,38],"310":0,"311":0,"313":0,"315":0,"317":0,"318":[0,54],"319":0,"32":6,"322":0,"323":0,"324":0,"325":0,"327":0,"329":0,"331":0,"332":0,"333":0,"334":0,"335":0,"336":0,"337":0,"338":0,"340":32,"341":0,"342":0,"343":0,"344":0,"345":0,"346":0,"347":0,"348":0,"349":0,"351":0,"352":0,"353":0,"354":0,"357":0,"358":0,"360":0,"3600":3,"361":0,"362":0,"363":0,"365":0,"368":[0,54],"370":0,"371":0,"375":0,"377":0,"378":0,"379":0,"381":0,"385":[0,54],"386":0,"392":0,"393":0,"394":0,"395":0,"396":0,"397":0,"398":0,"3l":38,"4":[1,2,3,6,9,10,19,27,29,30,32,42,48],"400":[0,54],"405":0,"407":0,"408":[0,54],"409":0,"412":0,"413":0,"415":0,"416":0,"419fcdf":54,"42":[3,30,44],"422":[0,54],"429":0,"430":0,"432":0,"433":0,"434":0,"435":0,"438":0,"439":0,"442":0,"443":0,"444":0,"445":0,"447":0,"450":0,"451":0,"452":0,"454":0,"458":0,"459":0,"46":0,"464":0,"466":0,"467":0,"468":0,"469":0,"470":0,"471":0,"473":0,"475":0,"476":0,"477":0,"478":0,"479":0,"48":32,"480":0,"481":0,"482":0,"486":0,"487":0,"489":0,"495":0,"498":0,"4bd5909":54,"4l":38,"4th":0,"5":[1,3,9,10,19,27,38,44,45,46,53],"50":4,"500":10,"5000":[3,10,50],"501":0,"502":0,"503":0,"505":0,"507":0,"508":0,"509":0,"50m":38,"510":0,"512":0,"514":0,"520":0,"521":0,"522":0,"527":0,"528":0,"530":0,"531":0,"532":0,"533":0,"535":0,"537":0,"538":0,"542":0,"547":0,"548":0,"549":0,"550":0,"551":0,"553":0,"555":0,"556":0,"557":0,"559":0,"56":0,"560":0,"561":0,"562":0,"565":0,"566":0,"568":0,"569":0,"570":0,"572":0,"5723":0,"573":0,"574":0,"574266d":54,"576":0,"577":0,"578":0,"579":0,"580":0,"583":0,"584":0,"585":0,"589":0,"59":[0,32],"591":0,"593":0,"595":0,"596":0,"598":0,"599":0,"5l":38,"6":[1,3,6,10,19,25,27,30,38,45,46],"60":0,"600":0,"606":0,"607":0,"608":0,"609":0,"613":0,"614":0,"616":0,"617":0,"618":0,"619":0,"621":0,"622":0,"623":0,"626":0,"628":0,"630":0,"631":0,"636":0,"64":[6,9,27],"640":0,"642":0,"643":0,"644":0,"645":0,"646":0,"647":0,"648":0,"649":0,"65":1,"650":0,"653":0,"655":0,"656":0,"657":0,"66":[1,3],"665":0,"668":0,"669":0,"673":0,"676":0,"678":0,"682":0,"684":0,"686":0,"688":0,"69":0,"690":0,"692":0,"694":0,"697":0,"6l":38,"7":[1,3,6,10,27,45,46],"70":0,"700":0,"705":0,"706":0,"707":0,"708":0,"709":0,"71":0,"710":0,"714":0,"717":0,"719":0,"720":0,"721":0,"723":0,"724":0,"727":0,"728":0,"729":0,"73":0,"730":0,"732":0,"733":0,"734":0,"735":0,"736":0,"737":0,"739":0,"740":0,"741":0,"742":0,"743":0,"746":0,"747":0,"749":0,"75":0,"750":0,"751":0,"752":0,"754":0,"755":0,"759":0,"75percentil":26,"75th":26,"76":0,"761":0,"762":0,"763":0,"767":0,"768":0,"769":0,"77142":43,"772":0,"773":0,"774":0,"774000":38,"775":0,"778":0,"781":0,"782":0,"785":0,"7857":0,"78723":[3,55],"788":0,"789":0,"79":0,"793":0,"794":0,"798":0,"799":0,"79efe97":54,"7l":38,"8":[1,3,6,17,31,45,46,48],"80":0,"804dea3":0,"805":0,"808":0,"81":0,"810":0,"812":0,"813":0,"814":0,"819":0,"82":0,"827":0,"829":0,"831":0,"833":0,"836":0,"837":0,"838":0,"839":0,"84":0,"840":0,"843":0,"846":0,"848":0,"852c":44,"853":0,"86":0,"860":0,"861":0,"862":0,"863":0,"86400":9,"865":0,"868":0,"872":0,"8733":40,"877":0,"88":0,"885":0,"888":0,"89":0,"891":0,"892":0,"893":0,"894":0,"895":0,"897":0,"89fb":44,"8l":38,"9":[1,9,38],"90":0,"900":0,"901":0,"903":0,"9042":[3,5],"91":0,"910":0,"915":0,"916":0,"92":0,"9223372036854775808":43,"93":0,"932":0,"934":0,"937":0,"940":0,"941":0,"944":0,"945":0,"946":0,"947":0,"95":0,"953":0,"955":0,"95percentil":26,"95th":26,"96":0,"963":0,"96489cc":54,"966":0,"968":0,"97":0,"973":0,"978":0,"98":0,"98percentil":26,"98th":26,"99":[0,26],"992":0,"993":0,"995":0,"996":0,"998":0,"99999":37,"999percentil":26,"99percentil":26,"99th":26,"9d98c8e":54,"9l":38,"9th":26,"abstract":[0,2,6,9,25,30],"boolean":[0,1,6,25,27,44,47],"break":[0,27,45,46,54],"byte":[0,6,38],"case":[0,3,4,8,9,27,32,34,35,44,49,52,53],"catch":0,"char":0,"class":[0,1,2,3,5,6,9,10,12,13,14,15,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,40,41,48,50,52,53,54],"default":[0,1,3,6,7,9,10,11,12,14,15,17,18,26,27,29,30,31,34,43,44,46,48,49,50,53],"do":[0,3,4,6,9,17,27,30,37,38,41,44,46,53,54,55],"enum":[10,13,27,32,33],"export":[0,25],"final":[3,44,53],"float":[0,3,6,10,15,18,26,27,37,38,44,54],"function":[0,1,3,8,10,12,17,25,27,29,32,41,44,52,53,54],"import":[0,2,3,4,6,10,11,12,29,30,34,35,37,38,39,41,42,43,44,46,48,50,52,53],"int":[0,3,6,7,8,15,18,25,31,32,38,44,47,54,55],"long":[0,32,44,46,55],"new":[0,1,2,3,4,6,7,10,21,25,27,30,31,32,34,36,38,39,40,42,44,48,50,53,54,55],"null":[0,10,17,36,38,44],"public":27,"return":[0,1,2,3,4,9,10,12,14,15,18,25,26,27,29,30,31,32,33,37,38,39,41,43,44,47,48,50,53,55],"short":[0,30,37],"static":[0,3,6,10,12,13,32],"super":37,"switch":[0,10,46],"throw":[0,3,30],"transient":0,"true":[0,3,4,6,7,8,9,10,15,18,25,27,30,31,34,35,36,37,38,40,43,44,47,48,52,53],"try":[0,1,3,8,9,27,37,39,41,44],"while":[0,3,27,30,37,40,50,54],A:[0,1,2,3,4,7,8,10,12,13,14,17,18,25,26,27,30,32,35,37,38,44,45,46],AND:[47,52],And:[9,53,54],As:[9,32,40,44,52,55],BY:37,Be:49,But:30,By:[1,3,9,10,27,29,34,38,43,44,46,50,53,54],For:[0,1,3,6,7,9,10,25,27,30,32,36,37,38,40,41,42,44,46,47,48,49,50,51,52,53,54],IF:[0,10,27,30,47,52,54],IN:[17,25,30],INTO:[3,4,30,44,47,55],IS:[0,38,40],If:[0,2,3,4,7,8,9,10,11,14,25,27,30,31,32,34,35,36,37,41,42,44,46,47,50,53,54],In:[0,3,27,29,34,38,40,44,46,52,53,54],It:[0,3,9,21,22,27,32,35,37,38,43,44,46,47,53],NOT:[0,38,47,52],No:45,Not:[0,32],ONE:[1,3,10,40,54],Of:3,On:[0,27,46],One:[10,41],Or:3,Such:27,THERE:40,That:38,The:[0,1,2,3,4,5,6,7,9,10,12,13,14,15,17,18,25,26,27,28,29,30,32,34,36,37,38,40,41,42,44,45,46,47,49,53,54,55],Then:53,There:[1,3,6,8,30,38,44,46,54],These:[0,3,6,9,27,29,30,32,40,41,49,53,54],To:[3,9,11,27,34,35,37,38,40,41,42,43,44,46,51,53,54],WITH:[37,52],Will:9,With:[0,35,43,53,54],_1:53,_2:53,_3:53,_4:53,_:42,__:[10,38,54],__abstract__:9,__compute_routing_key__:9,__connection__:[8,9,35],__contain:38,__default_ttl__:9,__del__:0,__discrimin:54,__discriminator_value__:[6,9,37,40],__ge__:0,__gt:38,__gte:38,__in:[0,38],__init__:[0,3,27,31,50,54,55],__keyspace__:[8,9,35,37],__le__:0,__len__:0,__like:38,__lt:38,__lte:38,__name__:43,__ne__:0,__options__:[9,38],__polymorphic_:54,__polymorphic_key__:40,__repr__:0,__table_name__:[9,37,40],__table_name_case_sensitive__:9,__type_name__:11,__version__:[1,46],__version_info__:1,_connect:0,_dsegraphson2rowfactori:12,_gremlingraphson2rowfactori:12,_messagetyp:29,_metadata:54,_new_tim:21,_next_timestamp:31,_not_set:3,_protocolhand:29,_protocolhandl:29,_replicationstrategi:25,_set_final_except:0,_set_result:0,_timeout_watch:21,a2:10,a2d3a98:54,abil:[0,27,42,54],abl:46,about:[0,3,25,30,37,41,44,46,53,54],abov:[3,29,34,35,41,44,49],absolut:[32,40],accept:[0,3,27,32,40,41],access:[0,3,9,26,30,37,44,54],accommod:[0,41],accomplish:[38,46],accord:[0,3],accordingli:0,account:[0,37],accumul:10,accur:25,acheiv:27,achiev:[27,34,53],acknowledg:27,across:[0,19,20,21,22,27,42,43,49],act:53,activ:[0,3,21,22],actual:[0,1,27,30,38,44,47],ad:[0,1,3,10,21,25,27,30,34,37,38,46,54],add:[0,3,7,8,10,14,27,30,34,54,55],add_al:[14,30],add_callback:[3,10,34,44,49,50],add_collback:0,add_errback:[3,44],add_execution_profil:[3,12,42],add_failur:27,add_or_return_host:25,add_queri:10,add_request_init_listen:3,add_tim:0,addit:[0,3,10,12,29,34,37,38,44,47,48,53,54],addition:[30,37,40,53],additional_write_polici:0,addr:[27,37],address:[0,1,3,5,11,25,28,30,33,37,43,44,53,54,55],address_is_ignor:27,address_transl:3,addresstransl:[0,27],adher:41,adjust:[0,40],advanc:53,advic:3,affect:[3,30,34],after:[0,3,4,10,20,27,30,34,37,38,40,43,44,46,49],afterward:54,ag:[3,30,38,44],against:[0,1,3,9,27,30,37,44,48,53],aggreg:[0,1,3,25],agnost:32,agre:0,agreement:[0,3],ahead:[3,44],aim:[35,42],algorithm:[36,46],alia:[6,12,25,32,40],alias:0,alic:30,align:0,aliv:[1,26,27],alive_replica:[1,27],all:[0,1,3,4,6,8,9,10,17,21,22,25,26,27,28,29,30,35,41,44,46,47,49,52,53,54],all_host:[25,42],all_object:38,all_replica:25,allow:[0,3,6,9,10,12,13,27,29,30,31,32,34,36,37,46,52,53,54,55],allow_beta_protocol_vers:29,allow_filt:[10,38],almost:44,along:[3,25,50],alpha:0,alphanumer:0,alreadi:[0,1,3,5,8,35,46],alreadyexist:1,also:[0,3,4,9,10,13,27,30,32,35,37,38,42,43,44,46,53,54],alter:[9,27,37],altern:[3,29,37,40,44,46,49,53],although:[44,54,55],althought:44,alwai:[0,3,15,18,27,41,44,46,47],ambigu:0,among:[1,27],amount:[0,4,27],an:[0,1,2,3,4,5,6,8,9,10,12,13,15,17,18,19,20,21,22,23,24,25,26,27,29,30,31,32,34,35,36,37,38,40,41,42,44,45,46,48,49,50,52,53,54,55],analysi:29,analyt:[0,3,15,18],analyticskeyspac:3,analyticskeyspace_prepar:3,andrew:[46,53],ani:[0,1,3,8,9,10,13,14,17,19,20,21,22,26,27,30,34,37,38,41,43,44,45,46,47,49,53,55],anomali:0,anoth:[27,34,35,38,44,53,54],anymor:[38,54],anyth:[34,41],anywai:46,apach:[38,46,54],api:[0,32,37,41,42,45,46,48,49,53],app:[39,43],appear:47,append:[4,10,25,38,44],appli:[0,3,9,10,14,30,36,41,42,44,46,47,48,55],applic:[0,3,6,27,39,40,41,44,46,49,50,54],approach:[41,45],appropri:[3,37,46,53],april:0,apt:46,ar:[0,1,3,4,6,7,8,9,10,15,18,21,25,26,27,28,29,30,32,34,36,37,40,41,42,43,44,45,46,47,48,50,53],arbitrari:[6,32],archflag:46,architectur:46,arg:[3,4,6,9,10,19,20,21,22,23,27,32,34],arg_typ:1,argument:[0,1,3,4,7,9,10,15,18,27,30,31,32,34,35,44,46,53,54],argument_typ:1,arm:0,around:[0,9,32,40,41,54],arrai:[29,38],arriv:3,as_cql_queri:[0,25],as_edg:[15,18],as_graph_stat:14,as_path:[15,18],as_vertex:[15,18],ascend:[10,38],ascii:[0,6,44],ask:[45,48],assert:[6,36,52],assertionerror:38,assign:[0,6,11,37],associ:[0,3,54],assum:[3,21,22,38,41,53,54],assumpt:41,astimezon:41,astra:0,async:3,asynchron:[0,3,30,43,49],asyncio:[0,33],asyncioconnect:19,asyncioreactor:33,asyncor:[0,33,46],asyncoreconnect:[0,20],asyncorereactor:[0,33],atexit:0,atlassian:27,atom:[27,30],attach:[0,3,15,18,34,44,49,50],attempt:[0,1,3,4,5,27,34,41,43,44,54],attr_kwarg:3,attribut:[0,3,6,8,9,10,11,15,18,25,27,29,30,31,37,38,40,42,44,47,54,55],attributeerror:0,aug:0,august:0,auth:[0,33,53,54],auth_provid:[2,3,53],authent:[0,1,3,33],authenticationfail:[1,2],author:[1,53],authorization_id:53,authprovid:[0,2,3,53],auto:35,automat:[0,1,3,35,37,38,44,46,50],automobil:[10,35,38],automobile2:10,avail:[0,3,10,30,38,45,46,52,54],avoid:[0,3,27,40,43,46],aw:27,awai:[3,30],awar:[0,3,26,27,41,46,53,54],ayncoreconnect:0,b:[3,4,12,14,15,18,34,35,36,38],back:[0,6,9,32,38],backoff:0,backpressur:0,backup:38,backward:[3,18,25,54],bad:0,badli:0,balanc:[0,3,33,42,54],bar:44,bark_all_night:37,base:[0,1,3,9,12,26,27,29,30,32,37,40,43,44,47,52,53],base_delai:27,basegraphrowfactori:12,basi:[0,54],basic:[0,3,12,37],batch:[0,1,3,9,10,12,14,25,27,33,35,38,48],batch_log:27,batch_obj:10,batch_object:9,batch_r:10,batch_typ:[10,30,34],batchqueri:[0,10,34,36,38],batchstat:[0,1,3,30,54],batchtyp:[0,10,30,34],bb984ee:54,beat_init:39,becam:[0,40],becaus:[0,3,4,15,18,27,30,32,40,41,44,46,52,54],becom:[0,3,8,49,54],been:[0,3,5,9,26,27,30,34,35,40,54],befor:[0,1,3,9,10,27,29,30,40,43,44,49,50,54],begin:[0,10,13,44],behav:32,behavior:[0,3,6,27,44,54],behind:[27,41],being:[0,3,6,26,30,36,42,44,46,47],below:[3,4,10,27,29,36,37,38,40,46,47,49,54],benchmark:[0,49],benefit:54,best:[27,44,51,53],beta5:1,beta:[1,46],beta_vers:1,better:[0,27,46,49],between:[0,2,6,29,30,46,52],bewar:27,beyond:37,big:[0,52],bigint:[6,15,18,44],binari:[0,6,30],binary_typ:29,bind:[0,3,12,30,43,44],bit:[6,32,46],bitmap:29,blacklist:27,blacklist_filter_polici:27,blah:44,blake:[9,38],blank:9,blind:[9,10],blindli:10,blist:0,blob:[0,6,17,44,52],block:[0,3,4,34,44,49],blog:49,bob:[3,30,44],bodi:[0,29],bool:[6,7,8,10,25,44,52],bootstrap:[0,26],bop:0,borrow_connect:0,both:[0,3,38,39,44,46,53],bound:[3,14,30,32,43,49],bound_stmt:3,boundstat:[0,30,44,54],bracket:47,brew:46,broadcast_address:27,broadcast_rpc_address:25,broadcast_rpc_port:25,broken:0,brought:54,brows:27,brute:27,bu:0,bucket_high:9,bucket_low:9,buffer:[0,17,44],bug:[40,45,54],build:[0,25,40,44,46,49],built:[0,32,42,46,49,54],bulk:12,bulkset:0,bump:0,busi:[3,28],bypass:[0,3,8,30],bytearrai:[0,17,44],bytebuff:0,bytecod:12,byteorderedpartition:[0,25],bytesio:0,bytestoken:25,c0:52,c:[0,6,12,25,27,38,53],ca:[0,27,53],ca_cert:53,cach:0,cacreateseri:53,cakei:53,calcul:0,call:[0,2,3,5,9,10,17,19,20,21,22,27,31,34,37,38,41,44,48,50,53],callabl:[6,10,12],callback:[0,3,10,44,49,53],callback_arg:3,callback_kwarg:3,camera:38,can:[0,1,3,4,6,8,9,10,13,14,15,17,18,21,25,27,29,30,31,32,34,35,37,38,39,41,42,43,44,45,46,48,49,50,52,53,54,55],cancel:0,cannon:40,cannot:[0,27,30,32,38,42],capabl:50,captur:[0,46],car:38,cardin:[15,18],care:[3,8],carri:34,cass_driver_build_concurr:46,cass_driver_no_cython:46,cass_driver_no_extens:46,cass_server_vers:0,cass_typ:32,cassandra:[0,33,34,35,36,37,38,39,40,42,43,46,48,49,50,52,53,55],cassandra_init:39,cassandra_vers:0,cast:44,cat:[37,40,53],caus:[0,3,10,26,37,47],caution:[8,37],caveat:27,cc94073:54,cdc:[0,27],cdef:0,ceas:27,ceil:1,celeri:48,cell:43,center:30,cento:[0,46],central:41,cert:53,cert_countri:53,cert_org_nam:53,cert_ou:53,cert_req:53,cert_requir:53,cert_valid:53,certain:[13,27,40,46],certfil:53,certif:[0,53],chain:34,challeng:[2,46],chanc:27,chang:[0,3,6,9,10,25,27,30,31,36,37,38,43,44,45],changelog:45,charact:[0,6,44],charl:30,check:[0,3,9,10,27,37,46,52,54],check_hostnam:[0,53],check_support:27,checkout:46,checksum:0,child:[0,27,43],child_polici:27,choic:[46,49],choos:[15,18,27,54],chosen:3,chunk:0,circuit:0,circumst:0,citi:54,civic:[10,35,38],cl:[0,10,21],clang:46,classic:0,classmethod:[1,9,15,18,19,20,21,22,25,29,32],claus:[0,10,25,37,47,54],clean:[0,39,46,54],cleanup:[0,20],clear:[0,14,27,30],clearer:41,client:[0,1,2,3,8,27,29,41,42,45,52],client_encryption_opt:53,client_protocol_handl:[3,29],clock:32,clock_seq:32,clone:[3,42],close:[0,3,5],closur:0,cloud:[0,3,27,45],cluster1:35,cluster2:[10,35],cluster3:35,cluster:[0,2,4,5,6,7,9,10,12,15,18,19,20,21,22,25,26,27,29,30,33,35,37,38,39,43,46,48,49,51,53,55],cluster_opt:7,clustering_kei:38,clustering_ord:[6,37],clustertest:0,cn:53,code:[0,1,34,39,45,53,54,55],codebas:0,coerc:6,coincid:0,col:[0,47],col_nam:9,collect:[0,3,8,10,15,25,26,30,32,38,45,54],collis:0,colnam:[3,10,30],column:[0,8,9,10,11,13,17,25,30,33,35,36,37,38,44,47,48,54,55],column_family_nam:9,column_nam:[10,15,18,38],columnmetadata:[25,54],com:[6,10,52,53],combin:[0,3],come:0,comma:44,command:[0,35,46],comment:[9,10,37],comment_id:[10,37],common:[0,40,46,53,54],commun:[0,5,46],compact:[0,9,52],compar:[0,30,32,45],comparison:[0,6],compat:[0,3,18,25,33,54],compil:[0,29,46,49],complain:37,complet:[0,1,2,3,4,11,27,30,34,37,40,43,44,49,53],complex:[0,42,46],compliant:0,compon:[0,10,25,30,32,53],compos:29,composit:[0,30,38],compositetyp:0,compound:6,compress:[0,3,29],compressor:29,compris:[1,29],comput:[0,3,9,43],concern:41,concis:15,concurr:[0,3,8,30,33,43,44,49],condit:[0,1,3,8,10,30,45],conf:53,config:[0,53],configur:[0,1,2,3,5,7,9,15,18,27,31,42,44,45,52],configurationexcept:1,confirm:0,conflict:36,confus:[40,54],conn:35,connect:[0,1,2,3,4,8,9,10,11,12,19,20,22,23,24,26,27,30,33,37,38,39,40,42,45,46,48,51,52,53,54,55],connect_timeout:[0,3],connect_to_remote_host:3,connected_to:26,connection_class:[3,46,53],connection_error:26,connection_exc:27,connectionbusi:5,connectionexcept:[0,5],connectionshutdown:5,consensu:1,consid:[0,1,3,18,27,44,47,49,53,54],consider:[37,49],consist:[0,1,3,7,10,27,30,32],consistency_level:[3,15,18,30,42,44],consistencylevel:[0,1,3,7,10,15,18,26,27,30,40,44],consit:0,constant:[0,53],constantreconnectionpolici:[0,27],constantspeculativeexecutionpolici:[0,27,44],constrain:[4,10],constraint:[9,37],construct:[0,9,12,32,41,42,44],constructor:[0,3,6,38],consult:37,consum:[0,4,54],consumpt:[0,49],contact:[0,3,27,44],contact_point:[0,3,7,27,53],contain:[0,3,6,9,10,13,17,27,32,37,38,41,47,50,52],contains_kei:13,contains_valu:13,contend:0,content:[0,10,29],context:[0,3,8,9,10,12,15,18,34,39,46,49,53],contextqueri:[0,10,35],contin:0,continu:[0,2,27,50],continuous_paging_opt:3,contract:[0,29],control:[0,3,4,27,30,40,49,53],control_connection_timeout:3,conveni:[3,15,18,30,38],convent:37,convers:[15,18,40,41,54],convert:[0,13,15,17,18,32,40,41,54],convict:27,conviction_policy_factori:3,convictionpolici:27,coord:32,coordin:[1,3,4,27,32,43],coordinationfailur:1,copi:42,copyright:0,core:[0,3,4,38,40,46,49],core_connect:3,correct:[0,9,41],correctli:[0,3],correspond:[2,4,6,8,37],cost:[0,9,10,38],costli:46,could:[0,10,54],count:[0,9,10,26,27,36,38,48],counter:[0,6,26,27,30,37,44],countri:45,cours:3,cover:[37,43],coverag:0,cpu:[0,4,44,49],cpython:[0,3,46],cql3:[36,38,45],cql:[0,1,6,9,10,11,13,15,17,18,25,30,32,36,37,38,40,41,47,48,52,54,55],cql_cluster:39,cql_encode_all_typ:17,cql_encode_byt:17,cql_encode_d:17,cql_encode_datetim:17,cql_encode_list_collect:17,cql_encode_map_collect:17,cql_encode_non:17,cql_encode_object:17,cql_encode_sequ:17,cql_encode_set_collect:17,cql_encode_str:17,cql_encode_tupl:[17,54],cql_encode_unicod:17,cql_keyword:25,cql_keywords_reserv:25,cql_keywords_unreserv:25,cql_refer:10,cql_session:39,cql_use:6,cql_version:[0,3],cqlcollect:13,cqle:0,cqlengin:[0,33,34,35,36,37,38,39,43,45,48,54],cqlengine_batch:34,cqlengine_test:38,cqlengineexcept:[0,40],cqltype:54,cqluseudt:6,crash:0,creat:[0,1,2,3,5,6,7,8,9,10,12,25,27,30,32,34,35,36,37,38,41,43,44,47,48,49,52,53,54,55],create_default_context:53,create_execution_profil:12,create_keyspac:40,create_keyspace_network_topolog:[8,40],create_keyspace_simpl:[8,40],create_simple_keyspac:35,created_at:[34,48],creation:[0,3,4,25,38],credenti:[0,3,53],credit:44,crt:53,crt_sign:53,crypto:53,csr:53,cstringio:0,cumbersom:41,current:[0,1,3,10,12,26,27,30,31,38,42,43,46,50,54],current_pag:3,current_row:3,custom:[0,1,3,6,10,17,27,30,33,41,42,44,46],custom_index:6,custom_payload:[3,15,18,29,30],cut:0,cute:37,cycl:3,cython:[0,29],cython_protocol_handl:3,cythonprotocolhandl:3,d:[3,6,10,30,41,44],daemon:0,dai:[6,27,32,53],dash:0,data:[0,1,3,9,10,27,30,33,37,38,41,43,44,52,54,55],data_retriev:[1,27],databas:[6,8,9,34,37,38,41,42],datacent:[0,1,27,28],dataset:[0,10,38],datastax:[0,6,10,18,27,44,45,46,48,53,54],datastream:38,datatyp:0,date:[0,6,17,32,44,45,54],daterang:[0,32],daterangebound:32,daterangeprecis:32,datetim:[0,6,10,17,32,34,36,38,40,41,44,48],datetime_from_timestamp:32,datetime_from_uuid1:32,datetyp:0,david:13,daylight:41,days_from_epoch:32,db:0,db_field:[0,6],dc:[0,3,27,54],dc_name:8,dc_replication_factor:25,dc_replication_map:8,dcawar:0,dcawareloadbalancingpolici:0,dcawareroundrobinpolici:[0,3,27,42],dclocal_read_repair_ch:0,dct:0,dd:[17,32],ddl:0,dead:33,deadlock:[0,4],deal:[0,41,42,49,54],debian:[0,46],debug:[0,3],decemb:0,decid:27,decim:[0,6,10,38,44],decimaltyp:0,decis:[0,26,41],declar:[11,37],decod:[0,3,29,30,33,54],decode_messag:29,decomiss:0,decommiss:[0,27],decompress:29,decompressor:29,decor:0,decrement:6,deem:41,def:[3,27,34,37,39,43,44,50,53,54,55],defacto:41,default_bit:53,default_consistency_level:[0,3,7,42],default_fetch_s:[3,50],default_keyspac:[0,7],default_retry_polici:[3,27,42,43],default_serial_consistency_level:[0,3,42],default_time_to_l:[0,38],default_timeout:[3,42],defaultloadbalancingpolici:[0,27,54],defer:[0,10,27],defici:41,defin:[0,1,2,3,6,8,9,10,15,18,25,27,30,33,35,38,40,42,44,45,48],definit:[0,3,6,15,29,38,40],defunct:[0,3,5],degre:13,delai:[0,27,44],deldyck:37,delet:[0,8,9,10,27,30,34,38],delete_keyspac:40,deliv:3,deliveri:3,demand:0,demonstr:53,dep:0,depend:[0,2,41,43,47,49],deploy:53,deprec:[3,9,16,27,53],deprecationwarn:[0,54],depth:0,dequ:0,deriv:[32,37,40,42,46,54],derivi:9,desc:37,descend:[10,37,38],describ:[1,27,29,32,38,40,41,53],descript:[0,3,15,18,27,30,34,43,48,53],descriptor:0,deseri:[0,15,18,33,41],deserialize_bigint:[15,18],deserialize_blob:[15,18],deserialize_d:[15,18],deserialize_decim:[15,18],deserialize_doubl:[15,18],deserialize_dur:[15,18],deserialize_float:[15,18],deserialize_int:[15,18],deserialize_linestr:[15,18],deserialize_point:[15,18],deserialize_polygon:[15,18],deserialize_tim:[15,18],deserialize_timestamp:[15,18],deserialize_uuid:[15,18],design:[44,49,52],desir:[3,10,27,34],despit:10,destroi:0,detail:[0,1,3,9,10,30,37,41,42,43,44,49,52,53,54],detect:[0,40],determin:[6,9,27,30,44],determinist:0,dev:46,devel:46,deviat:26,devic:0,dict:[0,1,3,6,7,8,9,12,15,17,18,25,26,29,30,37,44,47,52,53],dict_factori:[0,3,7,16,30,54],dictionari:[0,6],dictlik:32,did:[5,10,27],didn:10,differ:[0,3,10,29,30,32,36,37,38,42,44,53,54],digest:27,dir:0,directli:[3,4,17,29,30,44,46,53],disabl:[0,3,9,10,46,52],disable_shardaware_port:52,discontinu:0,discourag:3,discov:[0,3,27,44],discoveri:0,discrimin:[6,9,37],discriminator_column:[6,37,40],discuss:[3,6,11,30,37,45,47,49],disentangl:0,disk:6,dispos:3,disproportion:27,distanc:[13,27,32],distant:27,distinct:[0,10,15,18],distinct_field:10,distinguish:0,distinguished_nam:53,distribut:[0,27,38,46],distrimin:37,distriminator_column:37,dll:0,dn:27,doc:[0,1,6,10,37,38,41,52,53],document:[0,6,27,32,41,42,45,46,48,53,54],doe:[0,3,10,17,32,34,38,40,44,46,47,55],doesn:[0,31,54],doesnotexist:[0,10],dog:[37,40],dollar:0,don:[0,10,38,44,49,55],done:[0,3,37,41,43,53,54],dont:0,doubl:[0,6,15,18,32,44,49,54],double_precis:[40,54],down:[0,3,33,46],downgrad:[0,27],downgradingconsistencyretrypolici:[0,27,44],drain:0,drift:31,driven:8,driver:[0,1,3,5,7,10,18,26,27,28,29,30,37,38,40,41,44,46,47,48,49,50,51,52,53,55],driverexcept:1,drop:[0,6,8,29],drop_keyspac:[8,40],drop_tabl:8,drope:0,dsa:0,dse:[0,1,3,6,12,14,15,18,32],dse_graph:54,dse_graph_query_languag:12,dse_graph_query_protocol:12,dse_v1:[0,1],dse_v2:1,dsegraph:12,dsegssapiauthprovid:[0,53],dseloadbalancingpolici:[0,27,54],dseplaintextauthprovid:53,dsesessionremotegraphconnect:12,dsl:12,dt:32,due:[0,1,10,26,34,49],duplic:0,durabl:3,durable_writ:8,durat:[0,30,32],durationtyp:0,dure:[0,1,2,3,5,9,40,46],dynam:[0,3],dynamiccompositetyp:0,e0b9a54a6d93:44,e16a073:54,e:[3,8,9,10,12,15,18,27,30,43,46],each:[1,2,3,4,6,9,27,30,36,37,38,41,44,50,54,55],each_quorum:1,eagain:0,eai:0,earlier:[0,21,37],eas:35,easi:[0,37,38],easier:[38,42,46],easiest:[41,46],easili:[0,10,41],eat:37,ec2:0,ec2multiregiontransl:27,ed:0,edg:[0,15,18,25],edgemetadata:25,effect:[0,3,8,34,53],effici:[0,29],effort:[0,40,53],eggleston:9,either:[2,3,15,18,32,37,38,41,45,46],element:[0,3,10,15,18,25,32,38,44],elementmap:0,els:[4,39,50],em1:[34,48],em2:[34,48],em3:[34,48],em4:48,em5:48,em6:48,em7:48,em8:48,email:44,emit:[3,40,46],empti:[0,2,3,25,47],en:[6,10],enabl:[0,3,10,44,52,53,54],enable_shard_aware_driv:52,encod:[0,3,6,15,18,29,33,41],encode_messag:29,encount:[0,3,10],encrypt:[0,53],end:[0,10,34],endian:0,endless:0,endors:45,endpoint:[5,25,27,28,53],endpoint_factori:3,endpoint_or_address:25,endpointfactori:[5,53],enforc:[0,37],engag:46,engin:[0,3],enough:[1,30],ensur:[0,3,4,9,27,39,46,53],enterpris:52,entir:[0,3,4,10,14,25],entiti:0,entri:[10,13,17,54],entry_eq:13,environ:[8,27,46],eof:53,ep:[3,44],epoch:[0,31,32,41],eq:0,equal:[0,3,6,30,38],equival:[9,36,41,44],errback:[0,3,44,50],errback_arg:3,errno:0,error:[0,1,3,4,5,6,10,27,44,50],error_code_map:1,errro:1,escap:[0,17],especi:[0,8,42,46],essenti:38,establish:[3,44],etc:[3,10,26,27,38],evaluate_challeng:2,even:[0,3,7,27,30,41,42,44],evenli:27,event:[0,3,4,21,27,30,33,39,43,44,46,50,53],eventlet:[0,33],eventletconnect:[21,53],eventletreactor:33,everi:[0,27,31,38,39,44],everyon:46,evict:0,evolv:42,ewouldblock:0,exact:2,exactli:[0,27,40],examin:32,exampl:[0,2,3,4,6,9,10,11,25,30,32,35,36,38,40,42,43,44,46,47,48,49,50,51,52,54,55],example1:48,example2:48,example3:48,example4:48,example5:48,example6:48,example7:48,example8:48,example_id:48,example_mapp:0,example_typ:[34,48],examplemodel:[34,48],exc:[3,50],exce:[0,50],exceed:[3,4],except:[0,3,4,5,6,7,9,10,15,18,27,28,29,30,32,33,34,37,38,39,44,50,53],excess:0,exclud:38,exclus:[7,32,45],exec_profile_default:[3,42,44],exec_profile_graph_analytics_default:3,exec_profile_graph_default:[3,12,54],exec_profile_graph_system_default:3,exect:0,execut:[0,1,3,8,9,10,12,14,15,18,25,27,29,30,33,35,37,38,43,45,47,49,50,52,55],execute_a:[3,53,54],execute_async:[0,3,4,29,43,44,49,50],execute_concurr:[0,4,49],execute_concurrent_with_arg:[4,49],execute_graph:[3,15,18],execute_graph_async:3,execute_on_except:[10,34],execution_profil:[3,4,12,14,42,44],execution_profile_clone_upd:[3,42],executionprofil:[0,3,12,42,44],executionresult:4,executor:0,executor_thread:3,exhaust:[0,27],exist:[0,1,3,8,9,10,27,28,42,47,48,52,54],exit:0,expand:0,expect:[0,5,9,43,47,53,54,55],expens:3,experi:4,experiment:[0,19],expir:3,explain:[0,42],explicit:[0,40,41],explicitli:[0,1,3,10,15,18,34,37,54],explod:42,explor:38,exponenti:[0,27],exponentialreconnectionpolici:[0,3,27],export_as_str:[0,25],export_for_schema:[0,25],export_schema_as_str:25,expos:[0,31,54],express:[4,13,32],extablish:3,extend:30,extens:[0,3,27,41,52],exterior:32,extern:41,extra:[0,25,30,46],extra_deserializer_map:[15,18],extract:[15,18],ey:45,f:3,facilit:29,factor:[0,8,25],factori:[3,12,33,47],fail:[0,1,3,4,7,14,15,18,26,33,34,37,44,47],failur:[0,1,7,9,26,33,34],fairli:37,fall:[0,32],fallback:[10,27,54],fallthroughretrypolici:27,fals:[3,4,6,7,8,9,10,15,18,25,27,30,47,48,52,53,54],falsei:27,falsi:27,famili:[0,5,9],faq:[43,45],fashion:3,faster:[0,33,46],favor:[27,40,52,54],feather:45,featur:[12,19,33,38,40,45,46,53],feb:0,februari:0,fedora:46,feedback:0,felcei:13,fetch:[0,3,10,30,38,44,50,54],fetch_next_pag:3,fetch_siz:[0,3,10,15,18,30,50,54],few:[3,44,46],field:[0,3,6,8,9,10,11,30,32,37,38,44,55],fieldnam:6,fierc:37,file:[0,40,49,53],fill:[15,18,30],filter:[0,6,9,27,33,35,48],finalis:1,find:[13,25,41,46],fine:55,finished_ev:50,finit:27,first:[0,3,4,6,7,9,27,36,37,38,40,44,45,46,48,50,53,54],first_nam:[9,37],first_pag:38,first_result:54,first_row:55,five:3,fix:[27,46,53,54],flag:[0,3,6,9,29,37,46,52],flake:0,flask:43,flat:38,flexibl:[0,45],flight:[0,5],flow:0,fluent:[0,33,46,54],fly:[0,4,9,10,35],fn:[3,10],focu:27,follow:[0,3,26,27,29,34,35,37,40,41,42,44,46,47,53,54],foo:[44,55],food:37,footprint:[4,38],forc:[0,27,53],force_token_rebuild:3,forev:[21,27,30],fork:[0,20,43,45,49],form:[1,17,32,44],format:[0,1,3,17,25,29,30,33,41,44,53,55],formerli:0,forward:[1,27,40],found:[0,10,25,30,45,49,53,54],foundat:45,four:32,fqdn:[0,53],fraction:32,frame:29,free:44,frequent:[27,44,45,48],from:[1,2,3,4,5,6,8,9,10,11,12,15,18,20,25,27,29,30,32,34,35,37,38,39,40,42,43,44,45,46,47,48,50,52,53,55],from_datetim:54,from_kei:0,from_str:25,from_valu:32,from_wkt:32,frozen:[0,32,55],frozenset:44,full:[0,30,54],full_replica:25,fulli:54,functionfailur:1,functon:38,further:[3,4,27,38,43,49,53],furthermor:27,fuse:46,futur:[0,3,6,7,30,31,40,43,44,46,49,50,54],fuzzi:13,g:[0,3,12,15,18,27,30],garbag:[0,54],gc:0,gc_grace_second:9,gcc:46,gen_client_cert:53,gener:[0,1,2,4,27,29,32,33,41,44,52,53,54],geo:[0,13],geom:0,geomet:0,geometri:[13,32],geospati:0,geounit:13,get:[0,3,8,9,10,25,27,38,46],get_all_query_trac:[3,54],get_control_connection_host:3,get_core_connections_per_host:3,get_credenti:53,get_execution_profil:[0,3],get_host:[0,25],get_host_by_host_id:25,get_lower_support:1,get_max_connections_per_host:3,get_max_requests_per_connect:3,get_min_requests_per_connect:3,get_query_trac:[0,3,43,54],get_replica:[0,25,43],get_stat:26,getstat:26,getter:[15,18],gevent:[0,33],geventconnect:[0,22],geventreactor:[0,33],gil:[0,49],github:[0,45,48,52],give:[3,27,53,55],given:[0,3,10,25,27,28,32,34,38,49],global:[0,7,43],go:[0,40,51],goal:[49,53],goe:0,good:[40,45],got:54,govern:[3,27],gracefulli:0,grant:53,graph:[0,3],graph_graphson2_row_factori:[15,18],graph_graphson3_row_factori:[3,15,18],graph_languag:[15,18],graph_nam:[12,15,18],graph_object_row_factori:[3,15,18],graph_opt:[0,3],graph_protocol:[3,12,14],graph_read_consistency_level:[15,18],graph_result_row_factori:[15,18],graph_sourc:[0,3,15,18],graph_traversal_dse_object_row_factori:12,graph_traversal_row_factori:12,graph_write_consistency_level:[15,18],graphanalyticsexecutionprofil:3,graphexecutionpolici:3,graphexecutionprofil:3,graphopt:[0,15,18],graphprotocol:[3,14,15,18],graphson1:[15,18],graphson1deseri:[15,18],graphson1seri:[15,18],graphson2:[0,15,18],graphson2read:[15,18],graphson3:[0,12,15,18],graphson3read:18,graphson:[0,12,14,15,18],graphson_1_0:[3,15,18],graphson_2_0:[14,15,18],graphson_3_0:[3,15,18],graphsonwrit:14,graphstat:[0,3,14],graphtravers:[12,14],graphtraversalsourc:12,greater:[27,50],greatli:0,greenlet:0,gremlin:[0,3,12,14,15,18,46],gremlinpython:[0,46],greplin:[0,26],groovi:[15,18],group:25,group_keys_by_replica:25,grow:0,gssapi:2,guarante:[0,27,30,54],guard:8,guid:[0,44,45,46,48,53],gx:0,h:[0,43],ha:[0,3,5,10,26,27,30,38,40,41,44,46,47,53,54,55],had:[0,40,54],handl:[0,2,3,9,10,12,29,33,38,39,41,43,44,46],handle_err:50,handle_error:[4,44,50],handle_fork:20,handle_pag:50,handle_result:3,handle_success:44,handle_writ:0,handler:[0,2,10,15,18,27,29,50],handshak:2,hang:[0,46],happen:[0,3,27],hard:46,has_more_pag:[0,3,50],hash:[0,38,46],hashabl:[0,32],hasn:0,have:[0,2,3,4,6,9,10,15,17,18,26,27,34,35,36,37,38,40,42,44,46,47,53,54,55],header:[0,29,46],healthmonitor:0,heap:0,heartbeat:0,help:[0,38,54],here:[3,9,10,34,35,37,38,39,40,41,46,48,53],hex:0,hh:32,high:[0,48,49],higher:[1,3,4,30,53,54],highli:44,highlight:54,hint:1,hit:[3,5],hold:[0,25,29],holder:44,homebrew:[0,46],honda2012:38,honda:[10,35,38],honor:[0,44],hook:[39,43],host1:27,host2:27,host3:27,host:[0,1,2,3,4,7,25,33,35,43,48,52,53,54],host_address:53,host_dist:3,host_id:25,hostconnect:0,hostdist:[0,3,27],hostfilterpolici:[0,27],hostnam:[0,27,53],hoststatelisten:3,hot:46,hour:32,how:[0,1,4,6,9,27,30,38,39,41,42,44,45,47,50,53,54],howev:[0,3,10,30,34,37,38,41,46,47,50,54,55],html:[6,10,38,48],http:[6,10,27,38,48,50,52],huge:49,human:[25,41],i:[8,10,15,18,27,30,38],id:[0,3,4,6,9,10,15,18,29,34,36,37,38,44,53,55],idea:27,ideal:[32,41],idempot:[33,44],identifi:[0,1,37,47],identitytransl:[3,27],idl:0,idle_heartbeat_interv:3,idle_heartbeat_timeout:[0,3],ids_to_fetch:44,ie:[13,50,53],if_exist:[9,10],if_not_exist:[9,10],iff:9,ifnotexistswithcountercolumn:40,ignor:[0,3,8,26,27,29,30,44],ignored_address0:27,ignored_address1:27,imagin:27,immedi:[1,3,34,44],immut:[0,32,48],impact:4,implement:[0,2,3,5,15,18,19,20,21,22,23,24,27,29,32,41,46,49,50,53,54],impli:[30,45],implicit:[0,10,54],implicitli:[3,8,37],importerror:39,impos:37,improv:[0,1,35,49,54],in_memori:52,inbetween:27,includ:[0,3,9,10,25,26,40,45,49,53,54,55],include_keyspac:9,inclus:3,incomplet:0,inconsist:0,incorrect:[0,44],incorrectli:[0,30],increas:[0,27,31,46],increment:6,incur:9,indefinit:0,independ:[32,53],indetermin:3,index:[0,3,6,25,37,38,48,54],indexmetadata:25,indic:[0,1,2,3,6,8,9,10,25,27,38,47,52],individu:3,inet:[0,1,25],inet_address:0,inet_ntop:0,inet_pton:0,infin:0,infinit:[0,27],inflat:29,influenc:27,info:[0,3,33,44],inform:[0,3,5,9,25,27,41],inherit:[0,6,9,11,42],init:[0,3,36,40],initi:[0,2,3,5,6,7,9,15,18,27,29,31,32,35,38,39,44,46,47,53],initial_respons:2,initialize_reactor:[19,20,21,22],inititi:40,inject:[3,42,46],inmemorycompactionstrategi:52,inplac:32,input:[0,30,40,41,42],insanc:41,insensit:9,insert:[0,1,3,4,9,10,30,32,36,37,41,44,47,54,55],insert_stat:55,insert_us:30,insid:[13,34,44],insight:0,inspect:[3,8],instal:[0,40,44,45,49,53],instanc:[0,2,3,6,9,10,13,15,18,25,26,27,30,34,38,44,48,50,53,54,55],instanti:[0,27,29,31,44],instead:[0,3,4,30,38,40,44,50,53,54],instruct:38,insuffici:[0,26],intact:42,integ:[0,6,10,11,13,17,31,32,35,36,37,38,41,48],integer_typ:32,integr:[0,29,40,41,45,46,48,54],intend:[9,31,32,46],intent:40,interact:[3,44],interfac:[0,2,27,50],interior:32,intern:[0,3,10,27,31,32,40,41,54],interpol:55,interpret:[0,30,36,38,54],intranod:52,intrins:41,introduc:[0,19,25,30,37,38,40,42,54,55],introduct:45,intruct:53,intstat:26,inupt:0,inv:[15,18],invalid:[0,1,26,30],invalidparametertypeerror:0,invalidrequest:1,invalidtypeparametererror:0,invit:40,invlabel:[15,18],invoc:46,invok:[0,3,40],involv:[30,38],io:[0,3,4,10,33,46,48,53],ip:[0,3,5,27,28,44,53],ipv4address:0,ipv6:0,ipv6address:0,irc:0,iron:40,is_analytics_sourc:[15,18],is_cql_compat:25,is_default_sourc:[15,18],is_graph_sourc:[15,18],is_idempot:[0,15,18,30,44],is_schema_agre:3,is_seri:0,is_shard_awar:52,is_shutdown:0,is_up:0,isbootstrap:27,isn:[0,9,10],isnotnul:38,isoformat:0,isol:27,issu:[0,2,27,31,32,36,54],item1:17,item2:17,item:[0,4,9,10,15,18,27,30,32,37,38,44],iter:[0,3,25,27,29,30,32,38,50,54],its:[0,2,3,5,9,19,20,23,24,27,30,32,37,42,46,53,54],itself:[46,54],jan:0,januari:0,java:27,jit:49,jitter:[0,27],jk:53,joe:[37,53],john:44,join:0,jon:[10,37,38],json:[3,12,15,18],json_data:[15,18],juli:0,jump:48,junctur:40,june:0,just:[0,3,6,25,27,32,34,37,40,44,46,50,52,55],k:[34,47,53],keep:[0,27],keepal:0,kei:[0,1,3,6,8,9,10,13,15,25,26,27,29,30,32,37,38,42,43,44,47,52,53,55],kept:4,kerbero:[0,53],kevin5000:37,kevin:37,key1:17,key2:17,key_typ:6,keyerror:0,keyfil:53,keyout:53,keyspac:[0,1,3,7,8,9,10,11,15,18,25,27,29,30,35,43,52,54],keyspace1:52,keyspace_nam:54,keyspacemetadata:[0,25],keystor:53,keystore_password:53,keyword:[0,3,6,7,9,10],kill:0,kimberli:9,kind:[0,27,54],kinit:53,klass:3,know:[3,27,36,54,55],known:[0,15,18,25,40,54],known_host:26,ks1:35,ks2:35,ks:35,ks_name:8,kwarg:[0,3,4,6,7,9,10,12,15,18,19,20,21,22,23,27,32,34,39,53],label:[15,18],lambda:53,languag:[12,15,18,40,45,49],larg:[0,3,4,10,32,38,45,54],largest:36,last:[0,1,3,27,31,38],last_act:3,last_host:1,last_nam:[9,37],lastest:36,latenc:[26,44,52],later:[0,1,9,27,44,50],latest:[0,54],latter:[3,50],layout:25,lazi:0,lazili:29,lazy_connect:[0,7],lazyprotocolhandl:29,lbp:0,lead:[0,34,49,54],leak:0,learn:[30,53],least:[6,26,27,30,35,37,46],leav:[0,3],left:[0,3,4,9,41,54],legaci:[0,6,40,48,53,54],len:[0,9,10,35],length:[6,27,30],less:[0,46],let:[0,3,54],letter:13,level:[0,1,3,4,10,15,18,27,30,33,41,48,53],leveledcompactionstrategi:9,lib:0,libev4:46,libev:[0,33],libevconnect:[3,23,46],libevreactor:[0,3,33,46],libevwrapp:0,librari:[0,19,20,41,46,53],licens:45,lifecycl:2,lightweight:[0,1,10,30,44,45],lighweight:27,like:[0,1,3,4,9,10,15,18,26,27,30,37,38,41,44,46,50,53,55],limit:[0,3,10,30,38,41,49],line:[0,19,44,46],linear:32,lineariz:30,linestr:32,link:[0,41,46],linux:46,list:[0,1,3,4,6,7,8,9,10,13,15,17,18,25,27,29,30,32,35,43,44,45,46,48,50,54],list_col:44,list_column:10,list_column__append:10,list_column__prepend:10,listen:[0,3],listen_address:0,liter:[0,15,17,18,30,41,44,54,55],live:[1,27,43],ll:[38,53],load:[0,3,9,10,15,18,33,37,38,40,42,52,53,54],load_balancing_polici:[3,27,42,44,52],load_cert_chain:53,load_verify_loc:53,loadbalancingpolici:[0,3,27,42],local:[0,1,3,27,30,41,42,43,44,54],local_dc:[0,27],local_on:[0,1,3,44],local_queri:42,local_quorum:[0,1,44],local_seri:[1,30,44],localhost:[7,10],localstrategi:25,localtim:41,locat:[3,40,53,55],lock:0,locked_execut:42,log:[0,3,8,27,30,31,44,45,54],log_error:3,log_result:3,logentri:34,logger:0,logic:[0,37,52],logo:45,longer:[0,1,54],look:[13,37,38,53],lookup:[0,25,27],loop:[0,3,4,21,33,44,46,53],lose:0,loss:0,lot:[0,52],low:[15,18,27,33],lower:[1,4,27,32,38,44],lower_bound:32,lowercas:0,lwt:[0,3,9,47],lwtexcept:[0,9,10,40],lz4:[0,46],m:[9,36],mac:[0,46],machin:44,madd:46,made:[1,3,5,27,38,44,54],mai:[0,2,3,4,6,7,27,30,32,37,38,43,44,46,49,53,54],main:[0,3,53,55],maintain:[0,3,30,32,37,54],major:[0,27,42,53,54],make:[0,1,3,10,25,27,37,40,41,42,43,44,45,46,48,51,53,54],make_query_plan:27,make_token_replica_map:0,manag:[0,3,6,9,10,11,28,33,34,37,42,46,48,54],mandatori:[0,3],mani:[0,1,3,4,27,44,49,50,53,54],manifest:[0,43,47],manipul:[0,3],manner:32,manual:[3,9,34],manufactur:[10,35,38],map:[0,1,3,8,10,13,15,17,18,25,29,30,32,33,37,38,44,48,54],map_column:10,map_column__remov:10,map_column__upd:10,mapper:[0,7,40,45],march:0,margin:4,mark:[0,3,5,33,44,45],marker:41,master:[0,3,52],match:[0,3,5,9,10,15,18,25,30,38,40,42,43,44,46,53,54,55],materi:[0,3,4,25,29,46,54],materializedviewmetadata:25,math:0,max:[0,3,5,26,44],max_attempt:[27,44],max_connect:3,max_delai:27,max_length:6,max_request:3,max_schema_agreement_wait:3,max_support:1,max_threshold:9,max_tim:38,max_uuid_from_tim:32,max_wait:[3,30],max_wait_sec:3,max_wait_sec_p:3,maximum:[1,3,6,27,32,38],maxtimeuuid:38,maxyear:[32,41],md5token:25,md:52,mean:[3,9,26,27,38,44],meaningless:38,meant:41,measur:[3,27],mechan:[0,2,3,27,53],median:26,meet:[26,27,53],member:[32,37],memori:[0,4,38,52,54],mention:[0,41,44],merg:40,mesh:54,messag:[0,1,2,3,5,29],message_types_by_opcod:29,meta:[0,3,37],metadata:[0,3,15,18,27,30,33,42,43,52],method:[0,2,3,9,10,27,29,30,35,36,37,38,41,43,44,46,49,52],metri:26,metric:[0,3,33],metrics_en:3,micro:32,microsecond:[0,31,54],middl:13,might:[0,3,30,50,53],migrat:[48,54],millisecond:[0,17,32,41],millsecond:41,min:[0,26,43],min_length:[0,6],min_request:3,min_support:1,min_threshold:9,min_tim:38,min_uuid_from_tim:32,minim:[3,40,41,44],minimalist:32,minimum:[1,3,6,32,38],mintimeuuid:38,minut:[0,32,46],minyear:[32,41],mismatch:0,misplac:0,miss:[0,27],misspel:13,mistak:40,mitig:49,mix:[0,30],mke:0,mm:[17,32],mmmuuunnn:32,mno:46,mock:0,mode:0,model:[0,3,8,33,38,43,48,54],model__lik:38,modelexcept:40,modelqueryset:10,modern:0,modif:8,modifi:[0,1,8,9,10,32],modul:[0,9,11,18,19,20,40,46,49],monkei:[0,21,22,53],monkey_patch_loop:0,monoton:0,monotonictimestampgener:31,month:32,montonictimestampgener:0,more:[0,3,4,6,9,10,15,25,27,29,31,38,40,42,44,45,49,50,53,54],most:[3,27,30,37,40,41,43,50],mostli:[18,47],move:[0,3,30,54],ms:32,ms_timestamp_from_datetim:32,msg:29,much:[37,41,53,54],multipl:[0,3,10,12,14,15,18,27,34,35,44,48,49,54],multipleobjectsreturn:[0,10],multipli:13,multiprocess:0,multithread:0,murmur3:[0,3,46],murmur3partition:[0,25,46],murmur3token:[0,25],mussei:[46,53],must:[0,1,3,4,10,30,32,37,38,44,46,53,54,55],mutabl:3,mutat:48,mutual:[7,32],mv:27,my:53,my_callback:34,my_graph:12,my_tabl:44,my_user_id:30,mycf:3,mykeyspac:[3,30,44,54,55],mymod:36,mymodel:36,mystery_funct:34,mystorepass:53,mytabl:4,n:10,naiv:[6,41],name:[0,1,3,7,8,9,10,11,12,13,15,18,25,26,27,29,30,34,37,40,44,47,55],named_arg:34,named_tuple_factori:[0,3,16,30,54],namedt:38,namedtupl:[0,3,4,30,37,44,47,54,55],namedtuple_factori:0,nan:[0,32],nanosecond:[6,32,41],nativ:[0,1,15,18,29,37,45],native_shard_aware_transport_port:52,native_shard_aware_transport_port_ssl:52,native_transport_address:0,natur:2,necessari:[3,44,46,53],need:[0,1,3,6,12,27,30,32,34,35,36,37,38,39,44,46,49,52,53,54,55],neg:[0,32,38],negoti:2,nest:[0,32],net:27,network:[0,30,44],networktopologystrategi:[0,8,25],never:[0,27,34,47,49,54],neverretrypolici:3,new_authent:2,new_nod:0,new_plan:27,new_schedul:27,newkei:53,newli:[0,25,27],next:[0,3,21,27,42,48,50,53],next_pag:38,ngdg:0,nice:0,nicer:38,no_compact:0,no_valid_replica:25,noconnectionsavail:28,node1:42,node1_profil:42,node1_whitelist:42,node2:42,node2_profil:42,node:[0,1,3,5,25,26,28,30,32,33,44,52,53],node_domain:5,nodesync:0,nodetool:27,nohostavail:[0,3],nomenclatur:54,non:[0,3,6,10,32,33,37,44,45],nonblock:0,none:[0,1,2,3,4,5,6,7,8,9,10,11,12,14,15,17,18,25,26,27,30,32,36,38,39,41,43,44,47,50],nonetyp:0,nonexist:[0,1],normal:[0,3,9,10,12,27,30,32,41,44,50],nose:0,notabl:54,note:[0,3,4,7,8,9,10,19,27,30,32,35,37,38,40,41,42,44,45,50,52,53,54],noth:[0,25,27],notic:0,notif:0,notifi:3,nov:0,novemb:0,now:[0,31,34,36,38,40,41,44,48],nt:0,nullhandl:0,num:26,number:[0,1,3,4,5,9,10,26,27,40,42,44,46,47,50],numer:[0,41],numpi:29,numpyprotocolhand:29,numpyprotocolhandl:[0,29],o:[44,53],obj:[15,18],object:[0,3,4,12,15,17,18,25,26,27,30,31,32,34,35,36,37,41,42,43,44,45,49,50,54,55],obtain:[3,10,43,49],occur:[1,27,30,34,44,54],oct:0,octob:0,od:32,off:3,offer:[32,46,49,50],offici:[53,54],offset:32,often:37,ok:[27,53],old:[0,10,40],omit:[1,30],on_add:27,on_authentication_success:2,on_down:27,on_read_timeout:27,on_remov:27,on_request_error:[0,27],on_unavail:27,on_up:[0,27],on_write_timeout:[0,27],onc:[3,4,19,20,21,22,27,29,30,34,36,38,46,50,52],one:[0,1,2,3,6,10,13,26,27,30,32,35,36,37,38,42,44,52,53,54],ones:[10,40],onli:[0,1,3,4,5,6,7,8,9,10,18,19,27,30,31,34,37,38,40,41,44,45,46,47,52,53,54],onward:52,op:38,opaqu:3,opcod:29,open:[0,2,3,26,27,28,32,45],open_connect:26,openssl:53,oper:[0,1,3,5,8,9,10,15,18,30,32,33,35,44,47,54],operationtimedout:[0,1,3],opertaion:0,oppos:27,optim:[0,45,46,49],option:[0,1,2,3,5,7,9,10,11,12,14,25,29,30,33,38,40,42,44,47,48,49,52,53,54,55],option_map:25,options__contain:38,options_map:25,order:[0,1,4,6,10,25,27,30,32,34,37,41,54],order_bi:[10,38],ordered_dict_factori:[0,3,16,30,54],ordereddict:[0,3,30,32,44],orderedmap:[0,32],orderedmapserializedkei:32,orderedset:0,org:38,organ:45,origin:[0,3,38,54],os:46,oss:[0,27],other:[2,3,6,8,9,15,18,26,27,30,32,38,44,45,46,52,53,54,55],other_error:26,otherstuff:55,otherwis:[2,3,6,9,27,32,53],ou:53,our:[38,44,48,53],out:[0,1,4,9,27,32,34,36,38,40,41,44,53],outcom:47,output:[0,41],output_password:53,outsid:[0,6,27,32],outv:[15,18],outvlabel:[15,18],over:[3,27,29,38,49,50,53,54],overcount:27,overflow:[0,41],overflowerror:[0,32],overhaul:54,overhead:[0,4,34],overload:[0,1,6,26,27],overrid:[0,3,9,15,18,42,44,54],overridden:[0,3,50],overriden:0,overs:3,overview:[40,41,45,48],overwrit:10,own:[3,9,37,53],owner:37,owner_id:[37,40],pack:[0,30],packag:[0,2,32,41,46,48,53,54],page:[0,1,3,45,51],pagedresult:[0,50,54],pagedresulthandl:50,pagin:[0,38,50],paging_st:[3,50],pair:[0,29],panda:29,parallel:0,param:[0,4,13],paramet:[0,3,4,6,7,8,9,10,12,14,15,18,27,29,30,31,32,37,40,47,53,55],parameter:55,parent:[0,20],pars:[0,15,18,29,32,43,44],parser:[0,29],part:[0,8,10,30,35,40,41,46],parti:[2,3,41,48],partial:[0,21,22,30],particular:[0,3,25,27,30,52],particularli:38,partit:[0,6,10,25,27,30,38],partition:0,partition_kei:[6,10,30,38],pass:[0,2,3,4,6,7,9,10,25,29,30,34,36,37,38,39,47,48,52,53,54,55],passin:53,password:[2,53],passwordauthent:[2,53],patch:[0,21,22,41,53],path:[0,15,18,29,46,53],pattern:[37,49],paxo:30,payload:[0,1,3,30,33],peer:[0,5,25],peers_v2:0,pem:53,pend:0,pending_us:30,pep:0,per:[0,3,4,6,9,10,25,27,35,37,43,44,50,52,54],percentil:26,perform:[0,1,3,9,10,27,30,33,37,38,45,46,51],perhap:46,period:39,permiss:53,permit:27,persist:[0,15,18,27,41],person:[9,37,38],person_id:37,perspect:[2,27],pertain:3,pertin:47,pet:[37,40],pet_id:[37,40],pet_typ:[37,40],phase:[2,3,30,46],photo_id:[10,37],phrase:13,pick:[36,44],pip:[0,54],pk:[38,44],pk__token:[0,38],pk__token__gt:[0,38],place:[0,40,44,54],placehold:[3,15,18,30,44,55],placement:[0,8],plai:0,plain:53,plaintextauthent:2,plaintextauthprovid:[0,2,3,53,54],plan:[0,8,27,45],platform:[0,42],pleas:[0,3,6,9,11,27,37,43,45,53],plu:[38,47],plug:39,pluggabl:0,pmfstat:26,point:[0,3,6,26,27,32,41,44,53,54],polic:27,polici:[0,3,33,42,43,44,52,54],poll:[3,30,43],polygon:32,polymorphic_kei:40,pool:[0,1,3,33,54],pool_wait_timeout:3,popul:[0,3,27,30,38],port:[0,3,5,25,44,52],portion:[30,32],posit:[3,10,30,34,38,44,47,54],possibl:[0,3,9,21,27,31,32,37,38,41,46,50,53,54],post:[0,49],postfork:[39,43],potenti:0,pr:0,practic:44,practiv:10,pre:[0,46],preced:[3,27,34,47],precis:[0,6,17,32,40,41,54],predic:[0,27,33],predict:38,preemptiv:44,preexist:7,prefer:[0,27,41,44,46,54],prefix:[9,11,13],prematur:0,prepar:[0,3,4,27,33,41,43,53,55],prepare_on_all_host:3,prepared_stat:30,preparedstat:[0,3,30,44],preparemessag:0,prepend:[10,47,54],present:[0,7,10,30,41,42,43,46,47,54],preserv:[0,6,9,30,40],presist:37,pretti:49,preval:41,prevent:[0,10,40,44,46],previou:[0,3,53,54],previous:[0,40,42,54],previous_vers:1,price:[10,38],primari:[0,3,6,8,9,10,25,30,37,38,47,52,55],primary_host:27,primary_kei:[6,9,10,25,35,36,37,38,40,48],princip:[0,53],print:[3,9,10,12,30,32,35,37,41,42,43,44,46,48,52,55],prior:0,privat:[0,1,27],probabl:[27,38,53],problem:[0,3,26,43],process:[0,3,4,20,43,44,46,49,52,53,54],process_row:50,process_us:[3,4,44,50],produc:[2,4,15,18,38],product:[8,48,53,54],profil:[0,3,4,12,14,45],profile_long:44,programmat:3,project:[1,40,45,48,49],prompt:[46,53],proof:0,propag:[0,27,30],proper:[0,39,46],properli:[0,3,37,38,44],properti:[0,1,3,5,9,13,15,18,25,27,28,30,32,37],protect:0,protocol:[0,1,3,5,6,12,14,30,33,37,45,52],protocol_tl:[0,53],protocol_vers:[0,1,3,4,29,30,32,37,48,50,53,54,55],protocolerror:5,protocolhandl:[0,29],protocolvers:1,provid:[0,3,12,13,15,18,27,41,42,43,46,49,50,53,54],proxi:5,proxim:13,proxy_address:5,prudent:40,ps:50,publish:[0,46,53],pure:[0,2,27,29,46,53],purpos:[3,6],push:[0,46],py:[0,46],pyopenssl:[0,53],pypi:[0,46],python2:32,python3:0,python:[0,15,17,18,19,20,29,30,32,37,40,41,44,47,48,49,51,53,54,55],pyton:0,pytz:41,q2:48,q:[35,38,48],qop:[2,53],quadrat:0,quantiz:6,queri:[0,1,3,4,6,9,12,15,16,18,25,27,29,32,33,35,37,40,41,42,45,46,48,49,55],query_cl:[3,30],query_from_travers:12,query_str:[15,18,30],queryexhaust:3,queryhandl:[3,29],queryoper:0,queryset:[0,9],querytrac:[0,30,43],question:[45,48],queu:34,quickli:[0,49],quorum:[1,10,27,30,44],quot:[0,17,41],race:0,rack:[0,28],radiu:32,rais:[0,1,2,3,4,5,6,9,10,15,18,27,30,32,34,37,38,40,44,50,54],raise_on_first_error:4,random:[0,27,32,38],randompartition:25,rang:[0,4,10,32,38,41,43],range_request_timeout_in_m:1,rare:0,rather:[0,32,46],raw:6,re:[0,27,30,37,38,39,44,46,53,55],reach:34,reachabl:27,reactor:[0,20,24,43],read:[0,1,6,15,18,26,27,30,32,34,36,43,53],read_inet:0,read_repair:0,read_repair_ch:0,read_request_timeout_in_m:1,read_timeout:26,readabl:25,reader:[12,15,18],readfailur:1,readm:0,readtimeout:[1,44],reason:[1,3,27,41,53],rebuild:[0,3],rebuilt:0,receiv:[0,1,3,27,44],received_respons:[1,27],recent:0,recogn:[15,18],recommend:[0,3,4,27,36,44,49,53,54,55],reconnect:[0,33],reconnection_polici:3,reconnectionpolici:[0,27],reconnector:0,record:[0,6,10,27,38],recreat:[0,25],recurs:0,redhat:46,reduc:[0,3,49,52],redund:40,reevalu:0,ref:0,refactor:[0,41],refer:[0,10,34,40,42,47,54],referenc:3,refresh:[0,3],refresh_:54,refresh_keyspace_metadata:3,refresh_nod:[0,3],refresh_schema:[0,54],refresh_schema_metadata:3,refresh_table_metadata:[3,52],refresh_user_aggregate_metadata:3,refresh_user_function_metadata:3,refresh_user_type_metadata:3,regard:[3,27,32],regardless:[26,27,46,47],regex:13,regist:[0,3,7,12,17,26,34,37,45,54],register_connect:[0,7,35],register_listen:[0,3],register_user_typ:[3,54,55],registr:35,registri:7,regress:0,regular:[13,30,36,38],reilli:44,reinstal:46,reject:47,rel:41,relat:[0,30,38,42],relax:7,releas:[0,9,27,40,42,53,54],release_vers:[43,44],reli:[27,38],reloc:40,remain:[3,20,27,40,42],rememb:44,remot:[0,3,27,52],remoteconnect:12,remov:[0,3,6,8,10,27,30,32,42,47],remove_request_init_listen:3,repair:27,repeat:[27,44],replac:[0,3,6,29,40,53,54],replai:[1,27],replic:[0,3,8,25,40,52],replica:[0,1,8,25,26,27,30,44],replication_factor:[8,25,52],replication_factor_info:25,replicationfactor:25,replicationstrategi:25,report:[0,27],reprepar:0,reprepare_on_up:3,repres:[1,3,5,6,9,15,18,25,26,28,30,31,32,37,38,40,41,54],represent:[0,25,30,32,54],reproduc:0,req:53,req_distinguished_nam:53,request:[0,1,3,4,26,27,38,39,42,44,45,47,49,53,54],request_id:0,request_tim:[0,26],request_timeout:[3,42,44],requestexecutionexcept:1,requestvalidationexcept:1,requir:[0,1,2,3,6,7,19,27,29,30,32,37,38,39,40,44,46,48,53,54],require_client_auth:53,required_replica:[1,27],required_respons:[1,27],reserv:0,reset:27,resolut:[0,32],resolv:[0,3,5,27,36,53],resort:27,resourc:[19,20,21,22,46,53],respect:[0,3,38],respond:[1,2,27,44],respons:[0,1,2,3,27,29,38,44],response_futur:3,responsefutur:[0,3,29,43,44,49,50,54],rest:[27,44],restart:[0,44],resulset:0,result:[0,3,4,9,10,12,15,18,25,26,27,29,30,32,37,38,41,43,44,45,52,55],result_cach:0,result_metadata:29,result_or_exc:4,result_set:3,results_gener:4,results_metadata:0,resultset:[0,3,50,54],resync:9,retain:[0,41],rethrow:27,rethrown:0,retri:[0,7,26,30,33,44],retriev:[1,3,10,30],retry_connect:7,retry_next_host:27,retry_num:27,retry_polici:[0,3,15,18,27,30,42,43,44],retrypolici:[0,3,26,27,30,43],retun:47,reus:[3,14,30],revers:[10,27],review:0,rework:54,rf:[0,1],rhel:46,rich:3,right:[27,30,44],ring:[0,3,27,32,33],risen:53,risk:27,rlac:0,robin:27,robust:[0,41],role:53,root:53,root_ca_base_nam:53,root_cert_pass:53,rootca:53,rotat:27,round:[0,27,32],roundrobinpolici:[27,52],roundtrip:30,rout:[0,3,9,27,43,46],routing_kei:[15,18,27,30,43],row:[0,3,4,5,10,12,29,33,34,37,38,41,42,43,44,47,48,50,54,55],row_factori:[0,3,7,29,30,42,44],row_id:10,row_list:54,rpc:[5,28],rpc_addr:0,rpc_address:[0,42],rsa:53,rule:30,run:[0,9,10,21,27,34,37,39,44,46,48],run_in_executor:0,runtim:[0,46,49],runtimeerror:0,s:[0,1,2,3,6,7,9,10,11,24,27,29,30,32,34,35,36,37,38,39,41,44,45,46,48,52,53,54,55],safe:[0,4],safeti:0,same:[0,3,4,6,7,12,15,18,25,27,30,32,34,35,36,37,38,42,43,44,46,53,54],sasi:38,sasl:[0,2,53],sasl_kwarg:[2,53],saslauthent:[0,2],saslauthprovid:[0,2,53],saslclient:0,satisfi:1,save:[0,9,10,34,35,37,38,41,44,50],scale:[0,26,41,46,49,54],scan:43,scenario:[0,36],schedul:[0,34],schema:[0,3,9,30,33,37,44,54],schema_event_refresh_window:3,schema_metadata_en:3,schema_trigg:0,schemapars:0,scope:[0,3,10],scratch:42,script:[0,40,46,49],scylla:[38,40,46,54],scylladb:52,search:13,second:[0,3,10,26,27,30,31,32,38,41,44],secondari:[0,25,34,38],section:[0,38,40,45,47,49,53,54],secur:[0,45,54],see:[0,1,3,4,6,9,10,11,13,15,18,27,29,30,32,37,38,41,42,43,44,46,47,48,49,50,52,53,54],seen:[0,3,27],segment:40,select:[0,3,4,9,10,30,38,42,43,44,46,50,52,53,54,55],select_stat:4,self:[3,15,18,37,50,54,55],semant:[0,3],send:[0,1,2,3,5,27,44,45,54],sensibl:9,sensit:[0,9],sent:[0,1,2,3,29,44],sep:0,separ:[3,53],septemb:0,seq:43,sequenc:[0,3,4,14,17,27,30,32,44],sequenti:0,serd:0,serial:[0,1,3,12,15,18,30,41],serial_consistency_level:[3,15,18,30,42,44,47,54],serializ:3,serv:40,server:[0,1,2,3,9,15,18,25,29,30,33,38,44,47,48,54],server_authenticator_class:2,server_hostnam:53,server_nam:5,server_vers:43,servererror:27,servic:[2,53],service_timeout:21,session:[0,1,4,7,10,12,14,15,18,25,27,29,30,33,35,39,42,43,46,47,48,49,50,52,53,55],sesssion:0,set:[0,1,2,3,4,6,7,8,9,10,11,12,13,15,17,18,19,20,21,22,25,26,27,30,32,35,37,38,42,43,45,46,48,50,52,53,54],set_column:10,set_column__add:10,set_column__remov:10,set_core_connections_per_host:[3,4],set_default_connect:[7,35],set_keyspac:[0,3,27,44,55],set_max_connections_per_host:3,set_max_requests_per_connect:3,set_meta_refresh_en:3,set_min_requests_per_connect:3,set_sess:[0,7],set_source_analyt:[15,18],set_source_default:[15,18],set_source_graph:[15,18],set_stats_nam:26,set_verifi:53,setenv:46,setup:[0,7,10,35,37,38,39,40,44,46,48,53],setuptool:[0,46],sever:[0,38,40,44,46,49],shallow:[3,42],shard_aware_opt:52,shard_aware_stat:52,shards_count:52,share:[0,3,19,20,21,22,42,49],shed:[15,18],shell:46,shift:41,shortcut:[3,46],should:[0,2,3,4,6,7,8,9,10,15,18,19,20,21,22,25,27,30,31,37,40,42,44,46,49,52,53,54],should_log:3,shouldn:0,show:[0,8,32,36,38,40,42,47,53],shown:[3,35,37,55],shuffl:38,shuffle_replica:27,shutdown:[0,3,39],side:[0,1,2,3,15,18,27,40],sign:[6,53],signal:39,signatur:[1,3],significantli:[38,52],silent:27,similar:[27,29,34,53],simpl:[0,6,15,18,27,30,38,40,41,44,46,49],simpleconvictionpolici:[3,27],simplegraphstat:[15,18],simpler:54,simplest:[38,44],simplestat:[0,3,15,18,30,44,50],simplestrategi:[8,25,52],simpli:[0,9,17,27,34,37,40,44,46,55],simplifi:[15,18],simultan:42,sinc:[0,9,29,31,32,36,38,41,43,54,55],singl:[0,3,4,6,8,9,10,14,25,27,28,30,32,37,38,40,42,44,46,47,54],single_object_row_factori:[15,18],site:[0,41],situat:[27,34,37],six:[0,46,54],size:[0,3,10,54],sizeti:0,sizetieredcompactionstrategi:9,skip:[0,9],slack:0,sleep:[27,37],slice:[0,3,38],slightli:0,slow:0,smaller:27,smallint:[0,6,15,18,44],smoke:0,snappi:46,snapshot:0,sni:5,sniendpoint:5,sniendpointfactori:5,so:[0,1,3,10,21,25,27,30,37,38,41,42,44,47,48,49,50,53,54],socket:[0,5,53],socket_famili:5,sockopt:3,soft:0,softwar:45,some:[0,1,9,15,18,27,34,37,38,41,44,45,46,47,48,50,53,54,55],some_id2:34,some_id:34,someth:[2,27,37,38,46,53],sometim:[0,10,15,18,27,46,50],somewher:[34,50],sort:[0,4,6,32,38],sortedset:[0,32,54],sourc:[0,3,15,18,45,46],source_elaps:[0,43],span:46,spark:[0,3],spcifi:1,spec:41,special:[0,6,29,37,38,40,43],specif:[0,2,5,13,15,17,18,25,27,40,45,46,54,55],specifi:[0,1,3,6,8,9,10,11,12,27,29,30,32,35,37,38,40,41,42,44,53,54],specul:[0,27],speculative_execution_polici:[3,44],speculativeexecutionpolici:[27,44],speed:3,speedup:38,spell:41,spin:0,split:2,squar:47,ss:32,ssl:[0,5,44],ssl_context:[0,3,44,53],ssl_error_want_read:0,ssl_error_want_writ:0,ssl_opt:53,ssl_option:[0,3,5,53],ssl_version:53,sslcontext:[0,53],sstabl:43,sstable_size_in_mb:9,st:[3,37,55],stabil:0,stabl:0,stale:27,stall:0,standard1:52,standard:[0,19,20,26,38,39,41,44,46,53,54],start:[0,3,34,38,41,45,50,54],start_fetching_next_pag:[3,50],start_tim:3,startup:0,stat:[0,26,52],state:[0,3,10,20,27,34,45,47],stateless:50,statement:[0,3,25,27,33,34,36,41,42,43,47,50,55],statements_and_param:4,statements_and_paramet:4,stats_nam:26,statu:[47,52],status_event_refresh_window:3,stddev:26,stdlib:0,step:[37,45],steroid:38,steve:10,still:[0,15,18,30,34,37,40,42,44,54,55],stmt:0,stop:[4,34],store:[0,1,6,9,30,37,41],str:[7,8,10,17,32,44],straightforward:[37,40,41,54],strategi:[0,40,54],stream:[0,29],stream_id:29,street:[3,11,37,54,55],stress:0,strict:[6,49],strictli:0,string:[0,1,2,3,6,12,13,15,17,18,25,26,27,29,30,32,41,44,53],string_typ:32,strip:0,strong:0,structur:[15,18,25,37],studio:46,stuff:[3,55],style:3,sub:[37,40],subclass:[0,1,2,3,27,30,37,53],submit:[0,43],submit_schema_refresh:54,submodul:[40,54],suboptim:27,subsequ:40,subset:38,substanc:39,substanti:[4,54],succe:[3,27],succeed:0,success:[0,1,2,3,4,10,27,30,44,46],successfulli:[0,52],sudo:46,suffici:27,suggest:[44,46],suit:[0,53],suitabl:[2,17,25,36],superset:25,suppli:[0,3,30,44,53,54],support:[0,1,2,3,8,9,10,12,27,32,34,36,38,41,44,45,50,52,53,54,55],supported_vers:1,suppos:[0,37,53],sure:[0,3,27,37,43,44,46,49,51,53],surfac:0,surround:0,swap:54,sy:0,sync:[9,35,37],sync_schema:0,sync_tabl:[0,8,10,35,37,48],sync_typ:[8,11,37],synch:8,synchron:[0,3,4,8,37,49,50],syntax:[0,10,34,38],syntaxexcept:0,system:[0,5,25,38,42,43,44,46,54],t:[0,9,10,15,31,37,38,43,44,47,49,53,54,55],tabl:[0,1,3,6,8,25,30,32,33,37,44,47,48,54,55],tablemetadata:[0,25,52,54],tablemetadatadse68:25,tablemetadatav3:25,tag:[0,15,18],take:[0,3,4,8,9,15,18,25,27,35,44,46,53],taken:[15,18,40],tarbal:46,target:[0,3,13,15,18,27,46],task:[0,3,34,39],tcp:0,tear_up_couch:37,technic:40,techniqu:44,tell:55,tenant:41,term:27,tesla2012:38,tesla:[35,38],test2:10,test4:10,test:[0,10,21,22,27,31,35,46,47],test_clone_shared_lbp:0,test_clust:0,test_set_keyspace_twic:0,testifexistsmodel:9,testifnotexistsmodel:9,testmodel:38,testtransactionmodel:9,text:[0,3,6,9,10,11,13,35,36,37,38,40,44,48,54,55],than:[0,1,3,6,10,27,30,31,32,38,42,44,46,49,50,53],thei:[0,1,3,4,6,8,9,10,15,18,27,29,32,34,36,37,38,40,41,54,55],them:[0,3,27,38,40,41,44,46,47,48,54],themselv:[15,18],therefor:[36,38,46],thi:[0,1,2,3,4,5,6,7,8,9,10,11,12,13,15,17,18,19,20,21,22,25,26,27,28,29,30,31,32,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,52,53,54,55],thing:[3,27,38,40,44],third:[2,41,48],thorough:[46,53],those:[0,3,26,27,30,42,46],though:54,thread:[0,3,4,44,46,49],threadpoolexecutor:0,three:[1,27,30,32,44,47],threshold:[0,3],thrift:0,throttl:0,through:[0,2,3,5,7,9,10,15,18,26,27,30,38,44,45,47,49,54,55],throughput:[0,4,49],thrown:34,thu:[10,27,30,47],ticket:53,time:[0,1,2,3,4,6,10,26,27,31,32,37,38,40,44,45,46,54],time__gt:38,time__lt:38,time_arg:32,timedata:9,timedelta:10,timedelta_or_datetim:9,timeout:[0,1,3,9,10,21,26,27,54],timer:[0,21,26],timestamp:[0,1,6,9,10,17,32,33,36,40,44,45],timestamp_gener:3,timestamp_na:41,timestamp_pres:41,timestamp_utc:41,timestamptyp:0,timeuuid:[0,6,10,32,37,44,54],timezon:[0,6,32,41],tinkerpop:[12,46],tinyint:[0,6,44],tip:45,tlsv1_2_method:53,tmp:42,to_bigint:[15,18],to_doubl:[15,18],to_float:[15,18],to_int:[15,18],to_python:0,to_smallint:[15,18],todo:32,token:[0,2,3,13,15,27,33,43,46,52],token_fuzzi:13,token_map:0,token_metadata_en:3,token_prefix:13,token_regex:13,token_str:25,tokenawar:0,tokenawarepolici:[0,3,27,42,52],tokenawarerout:9,tokenfun:38,tokenmap:[0,25],toler:0,tolist:12,tombston:[3,36,43],tombstone_compaction_interv:9,tombstone_threshold:9,too:[0,3,27,41],took:1,tool:46,toolkit:29,top:[15,18,27],topo:0,topolog:[0,3,27,33],topology_event_refresh_window:3,total:[3,27],trace:[0,3,33],traceev:30,traceunavail:[3,30],tracing_en:0,track:0,trade:4,trademark:45,traffic:[0,44],trail:0,transact:[0,1,3,12,14,27,30,45],transform:37,transient_replica:25,transit:0,translat:[33,40,44],transpar:[3,44,50],trap:34,trash:0,travers:[0,12,14,15,18,46],traversal_batch:14,traversal_class:12,traversal_sourc:12,traversalbatch:[12,14],traversalmetr:0,travisci:0,treat:[3,27,30,44,50],tree:3,tri:0,trigger:[0,3,27],truncat:[6,30,32,40],truncate_microsecond:6,truststor:53,truststore_password:53,truthi:27,ts:41,ttl:[0,9,10],ttl_in_sec:9,tunabl:49,tune:0,tupl:[0,1,3,4,9,12,17,25,27,30,38,44,54,55],tuple_factori:[0,3,16,29,30,42,44,54],turn:[3,43],twice:0,twist:[0,33,44],twistedconnect:[24,53],twistedreactor:[33,53],two:[0,1,3,13,27,29,32,38,44,46,53],txt:[0,46],type0:1,type1:1,type:[0,1,3,8,10,15,17,18,25,27,29,30,32,33,34,38,41,45,47],type_model:8,typeerror:[0,15,18],typestr:0,typic:[3,10,27,29,30,31,34,38,42,44],typo:0,tzinfo:41,u:[10,30,37,38,47],ubuntu:[0,46],uda:0,udf:0,udt:[0,3,12,18,37,45],un:[0,30],unabl:[0,27,46],unauthor:[0,1],unavail:[0,1,26,27],uncal:0,unchang:40,unclean:54,uncompar:0,uncomplet:30,uncondit:0,undefinedkeyspaceexcept:40,under:[0,25,27,37,45],underscor:0,understand:53,understood:[3,27],underutil:0,unexpect:27,unexpectedli:0,unfamiliar:38,unhexlifi:0,unicod:[0,17,44],unicodedecodeerror:0,unif:0,unifi:[0,54],unintend:0,union:3,uniqu:[1,6,25,37,42],unit:[0,13,27,45],unix:[0,5,31,32,41],unix_socket_path:5,unix_time_from_uuid1:32,unixsocketendpoint:5,unknown:[0,15,18,46,54],unless:[3,6,27,35,54],unlik:41,unlog:30,unlogged_batch:27,unord:[6,25],unorder:0,unpack:[0,15,18,44],unprepar:55,unrecogn:0,unrecover:5,unreferenc:0,unregist:[0,55],unregister_connect:[7,35],unregister_listen:3,unset:0,unset_valu:30,unspecifi:[0,9],unsupport:0,unsupportedoper:3,until:[0,2,3,4,7,37,43,44],untrust:3,unus:[0,46],unwis:10,up:[0,3,8,13,19,20,21,22,32,33,34,37,38,53,54],updat:[0,1,3,8,9,10,30,32,34,38,40,42,44,45,47],update_view_metadata:0,updatestat:0,upfront:29,upgrad:[45,48,53],upon:[3,37],upper:32,upper_bound:32,uppercas:0,us:[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,35,36,37,38,40,41,43,44,45,46,47,49,50,51,52,53],usag:[0,2,3,4,9,25,27,30,54],use_certificate_fil:53,use_client_timestamp:[0,1,3,54],use_default_tempdir:0,use_list_t:6,use_privatekey_fil:53,use_set_t:6,used_hosts_per_remote_dc:27,usemap:6,user1:[44,53],user2:44,user3:44,user3_lookup:44,user:[0,1,3,4,6,8,9,10,17,18,25,30,33,38,40,44,45,46,50,53],user_act:3,user_id1:44,user_id2:44,user_id3:44,user_id:[4,9,30,38,44],user_ids_to_queri:44,user_lookup_stmt:44,user_row:[3,44,50],user_typ:[3,6],user_type_map:29,user_tz:41,useraggregatedescriptor:[1,3],userdefinedtyp:[0,6,37],userfunctiondescriptor:[1,3],usernam:[2,44,53],users_to_insert:30,usertyp:[0,6,25,33,37],usertypedoesnotexist:3,usual:[10,21,41,53],utc:[32,41],utc_datetime_from_ms_timestamp:32,utcfromtim:0,utcnow:[6,41],utctimetupl:41,utf8:0,utf8typ:0,utf:[0,6,17],util:[0,1,12,21,22,33,40,41,44,53,54],uuid1:[10,44],uuid4:[10,48],uuid:[0,6,9,10,32,37,38,40,44,48],uuid_arg:32,uuid_from_tim:[32,40],uwsgi:[43,48],uwsgidecor:[39,43],v1:[0,1,32],v2:[0,1,45],v3:[0,1,37,45],v4:[0,1,6,30],v5:[0,1],v6:1,v:[10,12,34,47,52],val1:17,val2:17,val:15,valid:[0,1,3,6,9,10,15,18,25,27,32,47,53],validationerror:[10,37,40],valu:[0,2,3,4,6,9,10,11,13,15,17,18,25,27,29,30,31,32,34,37,40,41,44,47,52,53,54,55],value2:32,value_typ:6,valueerror:[0,32],valuemap:12,values_list:[0,38],valuesequ:30,varchar:44,variabl:[0,6,9,44,46,53],variant:54,varint:[0,6,44],variou:[26,53],various:40,ve:[9,35,37,38],verb:40,verbatim:[15,18],veri:53,verif:0,verifi:0,verify_mod:53,verify_p:53,version:[0,1,2,3,6,25,29,30,31,32,37,40,44,45,46,50,54,55],vertex:[15,18,25],vertexmetadata:25,vertexproperti:[15,18],via:[0,3,37,46,50,53],view:[0,25,27,43],violat:10,virtual:[0,38],visit:45,visual:46,vnode:3,vs:[0,27],wa:[0,1,2,3,4,5,7,25,26,27,30,36,40,46,47,54],wai:[0,3,6,15,18,27,30,36,38,41,42,44,45,46,53,54],wait:[0,1,3,21,27,30,43,44,50],wait_for_all_pool:3,wait_for_complet:30,wake:21,want:[0,3,6,9,27,34,35,37,38,44,50,53,55],warn:[0,1,3,31,40,54],warn_on_drift:31,warning_interv:31,warning_threshold:31,was_appli:[0,3],watcher:21,we:[0,7,27,36,38,39,41,42,44,48,53,55],weakref:0,web_sess:50,well:[0,27,35,44,53],were:[0,1,3,4,19,25,27,30,36,37,40],what:[27,30,37,41,53,54,55],wheel:[0,46],when:[0,1,2,3,4,5,7,9,10,17,21,27,28,29,30,31,32,35,36,37,38,40,41,42,44,46,47,50,53,54,55],whenev:[3,50],where:[0,3,4,10,25,27,30,32,37,43,44,46,47,54],whether:[1,3,6,25,26,27,47,52],which:[0,1,3,9,10,25,27,29,30,34,35,36,38,40,44,46,49,53,54,55],whilst:0,whitelist:27,whitelistroundrobinpolici:[0,27,42,44,54],whitespac:25,who:27,whose:3,wider:[32,41],window:[0,32],wish:3,within:[0,1,3,10,13,27,30,34,41,42,44,54],withing:13,without:[0,1,3,9,10,38,41,44],wkt:[0,32],wno:46,won:37,word:[27,38],work:[0,2,7,17,27,30,32,37,38,44,45,47,48,52,53,55],workaround:[0,36,40],worker:[0,39],worker_process_init:39,working_keyspac:27,workload:[0,42,49],worth:46,would:[0,9,27,36,37,38,42,44,52,53,54],wrap:[12,15,18,27,44],wrap_socket:53,wrapper:[0,27,30],write:[0,1,8,10,15,18,26,27,30],write_request_timeout_in_m:1,write_timeout:26,write_typ:[1,27],writefailur:1,writetimeout:[0,1],writetyp:[0,1,27],written:0,wrong:[0,44],wunus:46,www:6,x509:53,x:[1,4,10,27,32,46,47],xcode:46,xrang:0,y:[0,10,27,32],yaml:[1,27,52],year:[10,32,35,38],year__gt:38,year__in:38,year__lt:38,yet:[3,38,44,54],yield:[4,27],you:[0,3,4,6,9,12,27,30,34,35,37,38,43,44,46,49,50,52,53,54,55],your:[0,3,6,9,35,37,38,40,43,44,47,48,49,50,53,54,55],yourself:49,yum:46,yyyi:[17,32],z:10,zero:0,zip:[54,55],zipcod:[3,11,37,54,55]},titles:["CHANGELOG","cassandra - Exceptions and Enums","cassandra.auth - Authentication","cassandra.cluster - Clusters and Sessions","cassandra.concurrent - Utilities for Concurrent Statement Execution","cassandra.connection - Low Level Connection Info","cassandra.cqlengine.columns - Column types for object mapping models","cassandra.cqlengine.connection - Connection management for cqlengine","cassandra.cqlengine.management - Schema management for cqlengine","cassandra.cqlengine.models - Table models for object mapping","cassandra.cqlengine.query - Query and filter model objects","cassandra.cqlengine.usertype - Model classes for User Defined Types","cassandra.datastax.graph.fluent","cassandra.datastax.graph.fluent.predicates","cassandra.datastax.graph.fluent.query","cassandra.datastax.graph - Graph Statements, Options, and Row Factories","cassandra.decoder - Data Return Formats","cassandra.encoder - Encoders for non-prepared Statements","cassandra.graph - Graph Statements, Options, and Row Factories","cassandra.io.asyncioreactor - asyncio Event Loop","cassandra.io.asyncorereactor - asyncore Event Loop","cassandra.io.eventletreactor - eventlet-compatible Connection","cassandra.io.geventreactor - gevent-compatible Event Loop","cassandra.io.libevreactor - libev Event Loop","cassandra.io.twistedreactor - Twisted Event Loop","cassandra.metadata - Schema and Ring Topology","cassandra.metrics - Performance Metrics","cassandra.policies - Load balancing and Failure Handling Policies","cassandra.pool - Hosts and Connection Pools","cassandra.protocol - Protocol Features","cassandra.query - Prepared Statements, Batch Statements, Tracing, and Row Factories","cassandra.timestamps - Timestamp Generation","cassandra.util - Utilities","API Documentation","Batch Queries","Connections","Frequently Asked Questions","Models","Making Queries","Third party integrations","Upgrade Guide","Working with Dates and Times","Execution Profiles","Frequently Asked Questions","Getting Started","Python Driver for Scylla and Apache Cassandra\u00ae","Installation","Lightweight Transactions (Compare-and-set)","Object Mapper","Performance Notes","Paging Large Queries","Scylla Cloud","Scylla Specific Features","Security","Upgrading","User Defined Types"],titleterms:{"0":[0,53,54],"0b1":0,"0b5":0,"0b6":0,"0b7":0,"0c1":0,"0c2":0,"0rc1":0,"1":[0,54],"10":0,"11":0,"12":0,"13":0,"14":0,"15":0,"16":[0,53],"17":0,"18":0,"19":0,"2":[0,54],"20":0,"21":0,"22":0,"23":0,"24":0,"25":0,"3":[0,53,54],"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"class":[11,55],"default":[35,38,42,47,54],"do":43,"enum":1,"final":0,"float":40,"function":[38,40],"import":[40,54],"new":[35,52],"return":[16,54],No:53,access:38,ad:42,address:27,alias:40,all:38,apach:45,api:[33,40,54],applic:43,ar:[38,54],ask:[36,43],asynchron:44,asyncio:19,asyncioreactor:19,asyncor:20,asyncorereactor:20,attach:54,attribut:52,auth:2,authent:[2,53,54],automat:54,awar:52,balanc:27,base:[46,54],batch:[30,34,36,54],batchqueri:35,beta2:0,beta3:0,beta4:0,beta:0,bind:54,blist:54,bug:0,c:46,call:54,callback:[34,50],can:36,cassandra:[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,41,44,45,54],celeri:39,chang:[35,40,54],changelog:0,client:[53,54],cloud:51,cluster:[3,42,44,52,54],column:[6,40],compar:47,compat:[21,22],compress:46,concurr:4,configur:[46,53],connect:[5,7,21,28,35,43,44],consist:[44,54],consolid:40,content:[45,48],context:35,control:50,convers:44,copyright:45,core:33,correctli:36,cql:44,cqlengin:[6,7,8,9,10,11,40],custom:[29,53,54],cython:[46,49],data:16,datastax:[12,13,14,15,33],date:[40,41],datetyp:41,dead:27,decod:16,defin:[11,37,54,55],definit:37,delet:36,depend:[46,54],deprec:[0,40,54],deseri:29,determin:43,dict:55,dict_factori:47,dictionari:37,document:33,doe:43,don:36,doubl:40,down:27,driver:[33,43,45,54],dse:[53,54],encod:[17,54],error:46,event:[19,20,22,23,24],eventlet:[21,53],eventletreactor:21,exampl:[37,53],except:[1,40],execut:[4,34,42,44,53,54],execute_async:54,extend:37,extens:[46,49],extra:54,factori:[15,18,30],fail:27,failur:27,faster:29,featur:[0,29,52,54],field2:36,field:36,filter:[10,38],fix:0,fluent:[12,13,14],format:16,frequent:[36,43],from:[0,36,54],from_datetim:40,gener:[31,34],get:[44,45,48],gevent:22,geventreactor:22,graph:[12,13,14,15,18,33,46,54],guid:40,handl:[27,50],help:45,helper:52,host:[27,28],how:[36,43],i:[36,43],idempot:27,ident:53,ignor:54,immut:38,individu:36,info:5,inform:54,inherit:[37,40],initi:42,instal:[46,54],instanc:[35,37,42],instanti:36,integr:39,io:[19,20,21,22,23,24,43],issu:45,keyspac:44,larg:50,legaci:42,level:[5,40,44,54],libev:[23,46],libevreactor:23,lightweight:[47,54],list:[38,40],load:27,local_on:54,log:34,login:53,loop:[19,20,22,23,24],low:5,lower:53,make:38,manag:[7,8,35,40,43],manipul:37,manual:46,map:[6,9,42,55],mapper:[33,48],mark:27,merg:0,metadata:[25,54],metric:[26,46],model:[6,9,10,11,35,36,37,40],modul:54,multiprocess:49,my:43,name:[38,42,54],named_tuple_factori:47,nativ:54,node:27,non:[17,46,54],normal:54,note:[46,49],now:54,object:[6,9,10,33,38,48],oper:[27,38,43],option:[15,18,46],order:[36,38],organ:40,osx:46,other:0,overload:40,packag:40,page:[50,54],paramet:[42,44,54],parti:39,pass:[42,44],path:41,pattern:34,payload:29,per:38,perform:[26,49],pip:46,platform:46,polici:27,pool:28,predic:13,prepar:[17,30,44,54],prepend:40,preserv:36,profil:[42,44],protocol:[29,53,54],proxi:53,pypi:49,python:[45,46],queri:[10,14,30,34,36,38,43,44,50,54],queryset:[10,35,38],question:[36,43],read:41,reconnect:27,regist:[35,55],remov:[40,54],replica:43,report:45,request:43,result:[47,50,54],resum:50,retri:[27,43],retriev:38,revers:40,ring:25,row:[15,18,30,36],sasl:54,schema:[8,25,40],scylla:[45,51,52],secur:53,select:35,server:[27,53],session:[3,44,54],set:[44,47],sever:54,shard:52,shutdown:54,side:54,size:50,soft:54,special:47,specif:52,specul:44,speed:46,ssl:[46,53],start:[44,48],statement:[4,15,17,18,30,44,54],support:46,t:36,tabl:[9,38,52],them:55,third:39,through:46,time:41,timeout:[38,43],timestamp:[31,41,54],timeuuid:[38,40],token:[25,38],topolog:25,trace:[30,43,54],transact:[47,54],translat:27,ttl:38,tuple_factori:47,twist:[24,53],twistedreactor:24,type:[6,11,37,40,44,54,55],udt:55,unicodemixin:40,unifi:53,unlog:34,unregist:35,up:[27,46],updat:[36,54],upgrad:[0,40,54],us:[34,42,54,55],user:[11,37,54,55],usertyp:11,util:[4,32],uwsgi:39,v1:53,v2:54,v3:54,valid:37,valu:[36,38],value2:36,verif:53,verifi:[46,53],version:53,vs:34,why:[36,43],window:46,without:[42,55],work:[36,41,54],write:41,wsgi:43,x:[0,54],your:46}}) \ No newline at end of file diff --git a/3.25.4-scylla/security.html b/3.25.4-scylla/security.html new file mode 100644 index 0000000000..c9c02a432a --- /dev/null +++ b/3.25.4-scylla/security.html @@ -0,0 +1,1029 @@ + + + + + + + + + + + + + Security | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

Security

+

The two main security components you will use with the +Python driver are Authentication and SSL.

+
+

Authentication

+

Versions 2.0 and higher of the driver support a SASL-based +authentication mechanism when protocol_version +is set to 2 or higher. To use this authentication, set +auth_provider to an instance of a subclass +of AuthProvider. When working +with Cassandra’s PasswordAuthenticator, you can use +the PlainTextAuthProvider class.

+

For example, suppose Cassandra is setup with its default +‘cassandra’ user with a password of ‘cassandra’:

+
from cassandra.cluster import Cluster
+from cassandra.auth import PlainTextAuthProvider
+
+auth_provider = PlainTextAuthProvider(username='cassandra', password='cassandra')
+cluster = Cluster(auth_provider=auth_provider, protocol_version=2)
+
+
+
+

Custom Authenticators

+

If you’re using something other than Cassandra’s PasswordAuthenticator, +SaslAuthProvider is provided for generic SASL authentication mechanisms, +utilizing the pure-sasl package. +If these do not suit your needs, you may need to create your own subclasses of +AuthProvider and Authenticator. You can use the Sasl classes +as example implementations.

+
+
+

Protocol v1 Authentication

+

When working with Cassandra 1.2 (or a higher version with +protocol_version set to 1), you will not pass in +an AuthProvider instance. Instead, you should pass in a +function that takes one argument, the IP address of a host, and returns +a dict of credentials with a username and password key:

+
from cassandra.cluster import Cluster
+
+def get_credentials(host_address):
+    return {'username': 'joe', 'password': '1234'}
+
+cluster = Cluster(auth_provider=get_credentials, protocol_version=1)
+
+
+
+
+
+

SSL

+

SSL should be used when client encryption is enabled in Cassandra.

+

To give you as much control as possible over your SSL configuration, our SSL +API takes a user-created SSLContext instance from the Python standard library. +These docs will include some examples for how to achieve common configurations, +but the ssl.SSLContext documentation +gives a more complete description of what is possible.

+

To enable SSL with version 3.17.0 and higher, you will need to set Cluster.ssl_context to a +ssl.SSLContext instance to enable SSL. Optionally, you can also set Cluster.ssl_options +to a dict of options. These will be passed as kwargs to ssl.SSLContext.wrap_socket() +when new sockets are created.

+

If you create your SSLContext using ssl.create_default_context, +be aware that SSLContext.check_hostname is set to True by default, so the hostname validation will be done +by Python and not the driver. For this reason, we need to set the server_hostname at best effort, which is the +resolved ip address. If this validation needs to be done against the FQDN, consider enabling it using the ssl_options +as described in the following examples or implement your own EndPoint and +EndPointFactory.

+

The following examples assume you have generated your Cassandra certificate and +keystore files with these intructions:

+ +

It might be also useful to learn about the different levels of identity verification to understand the examples:

+ +
+

SSL with Twisted or Eventlet

+

Twisted and Eventlet both use an alternative SSL implementation called pyOpenSSL, so if your Cluster’s connection class is +TwistedConnection or EventletConnection, you must pass a +pyOpenSSL context instead. +An example is provided in these docs, and more details can be found in the +documentation. +pyOpenSSL is not installed by the driver and must be installed separately.

+
+
+

SSL Configuration Examples

+

Here, we’ll describe the server and driver configuration necessary to set up SSL to meet various goals, such as the client verifying the server and the server verifying the client. We’ll also include Python code demonstrating how to use servers and drivers configured in these ways.

+
+

No identity verification

+

No identity verification at all. Note that this is not recommended for for production deployments.

+

The Cassandra configuration:

+
client_encryption_options:
+  enabled: true
+  keystore: /path/to/127.0.0.1.keystore
+  keystore_password: myStorePass
+  require_client_auth: false
+
+
+

The driver configuration:

+
from cassandra.cluster import Cluster, Session
+from ssl import SSLContext, PROTOCOL_TLS
+
+ssl_context = SSLContext(PROTOCOL_TLS)
+
+cluster = Cluster(['127.0.0.1'], ssl_context=ssl_context)
+session = cluster.connect()
+
+
+
+
+

Client verifies server

+

Ensure the python driver verifies the identity of the server.

+

The Cassandra configuration:

+
client_encryption_options:
+  enabled: true
+  keystore: /path/to/127.0.0.1.keystore
+  keystore_password: myStorePass
+  require_client_auth: false
+
+
+

For the driver configuration, it’s very important to set ssl_context.verify_mode +to CERT_REQUIRED. Otherwise, the loaded verify certificate will have no effect:

+
from cassandra.cluster import Cluster, Session
+from ssl import SSLContext, PROTOCOL_TLS, CERT_REQUIRED
+
+ssl_context = SSLContext(PROTOCOL_TLS)
+ssl_context.load_verify_locations('/path/to/rootca.crt')
+ssl_context.verify_mode = CERT_REQUIRED
+
+cluster = Cluster(['127.0.0.1'], ssl_context=ssl_context)
+session = cluster.connect()
+
+
+

Additionally, you can also force the driver to verify the hostname of the server by passing additional options to ssl_context.wrap_socket via the ssl_options kwarg:

+
from cassandra.cluster import Cluster, Session
+from ssl import SSLContext, PROTOCOL_TLS, CERT_REQUIRED
+
+ssl_context = SSLContext(PROTOCOL_TLS)
+ssl_context.load_verify_locations('/path/to/rootca.crt')
+ssl_context.verify_mode = CERT_REQUIRED
+ssl_context.check_hostname = True
+ssl_options = {'server_hostname': '127.0.0.1'}
+
+cluster = Cluster(['127.0.0.1'], ssl_context=ssl_context, ssl_options=ssl_options)
+session = cluster.connect()
+
+
+
+
+

Server verifies client

+

If Cassandra is configured to verify clients (require_client_auth), you need to generate +SSL key and certificate files.

+

The cassandra configuration:

+
client_encryption_options:
+  enabled: true
+  keystore: /path/to/127.0.0.1.keystore
+  keystore_password: myStorePass
+  require_client_auth: true
+  truststore: /path/to/dse-truststore.jks
+  truststore_password: myStorePass
+
+
+

The Python ssl APIs require the certificate in PEM format. First, create a certificate +conf file:

+
cat > gen_client_cert.conf <<EOF
+[ req ]
+distinguished_name = req_distinguished_name
+prompt = no
+output_password = ${ROOT_CERT_PASS}
+default_bits = 2048
+
+[ req_distinguished_name ]
+C = ${CERT_COUNTRY}
+O = ${CERT_ORG_NAME}
+OU = ${CERT_OU}
+CN = client
+EOF
+
+
+

Make sure you replaced the variables with the same values you used for the initial +root CA certificate. Then, generate the key:

+
openssl req -newkey rsa:2048 -nodes -keyout client.key -out client.csr -config gen_client_cert.conf
+
+
+

And generate the client signed certificate:

+
openssl x509 -req -CA ${ROOT_CA_BASE_NAME}.crt -CAkey ${ROOT_CA_BASE_NAME}.key -passin pass:${ROOT_CERT_PASS} \
+    -in client.csr -out client.crt_signed -days ${CERT_VALIDITY} -CAcreateserial
+
+
+

Finally, you can use that configuration with the following driver code:

+
from cassandra.cluster import Cluster, Session
+from ssl import SSLContext, PROTOCOL_TLS
+
+ssl_context = SSLContext(PROTOCOL_TLS)
+ssl_context.load_cert_chain(
+    certfile='/path/to/client.crt_signed',
+    keyfile='/path/to/client.key')
+
+cluster = Cluster(['127.0.0.1'], ssl_context=ssl_context)
+session = cluster.connect()
+
+
+
+
+

Server verifies client and client verifies server

+

See the previous section for examples of Cassandra configuration and preparing +the client certificates.

+

The following driver code specifies that the connection should use two-way verification:

+
from cassandra.cluster import Cluster, Session
+from ssl import SSLContext, PROTOCOL_TLS, CERT_REQUIRED
+
+ssl_context = SSLContext(PROTOCOL_TLS)
+ssl_context.load_verify_locations('/path/to/rootca.crt')
+ssl_context.verify_mode = CERT_REQUIRED
+ssl_context.load_cert_chain(
+    certfile='/path/to/client.crt_signed',
+    keyfile='/path/to/client.key')
+
+cluster = Cluster(['127.0.0.1'], ssl_context=ssl_context)
+session = cluster.connect()
+
+
+

The driver uses SSLContext directly to give you many other options in configuring SSL. Consider reading the Python SSL documentation +for more details about SSLContext configuration.

+

Server verifies client and client verifies server using Twisted and pyOpenSSL

+
from OpenSSL import SSL, crypto
+from cassandra.cluster import Cluster
+from cassandra.io.twistedreactor import TwistedConnection
+
+ssl_context = SSL.Context(SSL.TLSv1_2_METHOD)
+ssl_context.set_verify(SSL.VERIFY_PEER, callback=lambda _1, _2, _3, _4, ok: ok)
+ssl_context.use_certificate_file('/path/to/client.crt_signed')
+ssl_context.use_privatekey_file('/path/to/client.key')
+ssl_context.load_verify_locations('/path/to/rootca.crt')
+
+cluster = Cluster(
+    contact_points=['127.0.0.1'],
+    connection_class=TwistedConnection,
+    ssl_context=ssl_context,
+    ssl_options={'check_hostname': True}
+)
+session = cluster.connect()
+
+
+

Connecting using Eventlet would look similar except instead of importing and using TwistedConnection, you would +import and use EventletConnection, including the appropriate monkey-patching.

+
+
+
+

Versions 3.16.0 and lower

+

To enable SSL you will need to set Cluster.ssl_options to a +dict of options. These will be passed as kwargs to ssl.wrap_socket() +when new sockets are created. Note that this use of ssl_options will be +deprecated in the next major release.

+

By default, a ca_certs value should be supplied (the value should be +a string pointing to the location of the CA certs file), and you probably +want to specify ssl_version as ssl.PROTOCOL_TLS to match +Cassandra’s default protocol.

+

For example:

+
from cassandra.cluster import Cluster
+from ssl import PROTOCOL_TLS, CERT_REQUIRED
+
+ssl_opts = {
+    'ca_certs': '/path/to/my/ca.certs',
+    'ssl_version': PROTOCOL_TLS,
+    'cert_reqs': CERT_REQUIRED  # Certificates are required and validated
+}
+cluster = Cluster(ssl_options=ssl_opts)
+
+
+

This is only an example to show how to pass the ssl parameters. Consider reading +the python ssl documentation for +your configuration. For further reading, Andrew Mussey has published a thorough guide on +Using SSL with the DataStax Python driver.

+
+

SSL with Twisted

+

In case the twisted event loop is used pyOpenSSL must be installed or an exception will be risen. Also +to set the ssl_version and cert_reqs in ssl_opts the appropriate constants from pyOpenSSL are expected.

+
+
+
+
+

DSE Authentication

+

When authenticating against DSE, the Cassandra driver provides two auth providers that work both with legacy kerberos and Cassandra authenticators, +as well as the new DSE Unified Authentication. This allows client to configure this auth provider independently, +and in advance of any server upgrade. These auth providers are configured in the same way as any previous implementation:

+
from cassandra.auth import DSEGSSAPIAuthProvider
+auth_provider = DSEGSSAPIAuthProvider(service='dse', qops=["auth"])
+cluster = Cluster(auth_provider=auth_provider)
+session = cluster.connect()
+
+
+

Implementations are DSEPlainTextAuthProvider, DSEGSSAPIAuthProvider and SaslAuthProvider.

+
+

DSE Unified Authentication

+

With DSE (>=5.1), unified Authentication allows you to:

+
    +
  • Proxy Login: Authenticate using a fixed set of authentication credentials but allow authorization of resources based another user id.

  • +
  • Proxy Execute: Authenticate using a fixed set of authentication credentials but execute requests based on another user id.

  • +
+
+

Proxy Login

+

Proxy login allows you to authenticate with a user but act as another one. You need to ensure the authenticated user has the permission to use the authorization of resources of the other user. ie. this example will allow the server user to authenticate as usual but use the authorization of user1:

+
GRANT PROXY.LOGIN on role user1 to server
+
+
+

then you can do the proxy authentication….

+
from cassandra.cluster import Cluster
+from cassandra.auth import SaslAuthProvider
+
+sasl_kwargs = {
+  "service": 'dse',
+  "mechanism":"PLAIN",
+  "username": 'server',
+  'password': 'server',
+  'authorization_id': 'user1'
+}
+
+auth_provider = SaslAuthProvider(**sasl_kwargs)
+c = Cluster(auth_provider=auth_provider)
+s = c.connect()
+s.execute(...)  # all requests will be executed as 'user1'
+
+
+

If you are using kerberos, you can use directly DSEGSSAPIAuthProvider and pass the authorization_id, like this:

+
from cassandra.cluster import Cluster
+from cassandra.auth import DSEGSSAPIAuthProvider
+
+# Ensure the kerberos ticket of the server user is set with the kinit utility.
+auth_provider = DSEGSSAPIAuthProvider(service='dse', qops=["auth"], principal="server@DATASTAX.COM",
+                                      authorization_id='user1@DATASTAX.COM')
+c = Cluster(auth_provider=auth_provider)
+s = c.connect()
+s.execute(...)  # all requests will be executed as 'user1'
+
+
+
+
+

Proxy Execute

+

Proxy execute allows you to execute requests as another user than the authenticated one. You need to ensure the authenticated user has the permission to use the authorization of resources of the specified user. ie. this example will allow the server user to execute requests as user1:

+
GRANT PROXY.EXECUTE on role user1 to server
+
+
+

then you can do a proxy execute…

+
from cassandra.cluster import Cluster
+from cassandra.auth import DSEPlainTextAuthProvider,
+
+auth_provider = DSEPlainTextAuthProvider('server', 'server')
+
+c = Cluster(auth_provider=auth_provider)
+s = c.connect()
+s.execute('select * from k.t;', execute_as='user1')  # the request will be executed as 'user1'
+
+
+

Please see the official documentation for more details on the feature and configuration process.

+
+
+
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.25.4-scylla/sitemap.xml b/3.25.4-scylla/sitemap.xml new file mode 100644 index 0000000000..f03cce40f2 --- /dev/null +++ b/3.25.4-scylla/sitemap.xml @@ -0,0 +1,2 @@ + +https://python-driver.docs.scylladb.com/stable/CHANGELOG.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/auth.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/cluster.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/concurrent.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/connection.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/cqlengine/columns.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/cqlengine/connection.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/cqlengine/management.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/cqlengine/models.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/cqlengine/query.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/cqlengine/usertype.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/datastax/graph/fluent/index.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/datastax/graph/fluent/predicates.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/datastax/graph/fluent/query.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/datastax/graph/index.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/decoder.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/encoder.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/graph.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/io/asyncioreactor.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/io/asyncorereactor.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/io/eventletreactor.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/io/geventreactor.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/io/libevreactor.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/io/twistedreactor.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/metadata.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/metrics.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/policies.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/pool.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/protocol.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/query.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/timestamps.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/util.htmlhttps://python-driver.docs.scylladb.com/stable/api/index.htmlhttps://python-driver.docs.scylladb.com/stable/cqlengine/batches.htmlhttps://python-driver.docs.scylladb.com/stable/cqlengine/connections.htmlhttps://python-driver.docs.scylladb.com/stable/cqlengine/faq.htmlhttps://python-driver.docs.scylladb.com/stable/cqlengine/models.htmlhttps://python-driver.docs.scylladb.com/stable/cqlengine/queryset.htmlhttps://python-driver.docs.scylladb.com/stable/cqlengine/third_party.htmlhttps://python-driver.docs.scylladb.com/stable/cqlengine/upgrade_guide.htmlhttps://python-driver.docs.scylladb.com/stable/dates_and_times.htmlhttps://python-driver.docs.scylladb.com/stable/execution_profiles.htmlhttps://python-driver.docs.scylladb.com/stable/faq.htmlhttps://python-driver.docs.scylladb.com/stable/getting_started.htmlhttps://python-driver.docs.scylladb.com/stable/index.htmlhttps://python-driver.docs.scylladb.com/stable/installation.htmlhttps://python-driver.docs.scylladb.com/stable/lwt.htmlhttps://python-driver.docs.scylladb.com/stable/object_mapper.htmlhttps://python-driver.docs.scylladb.com/stable/performance.htmlhttps://python-driver.docs.scylladb.com/stable/query_paging.htmlhttps://python-driver.docs.scylladb.com/stable/scylla_cloud.htmlhttps://python-driver.docs.scylladb.com/stable/scylla_specific.htmlhttps://python-driver.docs.scylladb.com/stable/security.htmlhttps://python-driver.docs.scylladb.com/stable/upgrading.htmlhttps://python-driver.docs.scylladb.com/stable/user_defined_types.htmlhttps://python-driver.docs.scylladb.com/stable/py-modindex.htmlhttps://python-driver.docs.scylladb.com/stable/404.htmlhttps://python-driver.docs.scylladb.com/stable/search.html \ No newline at end of file diff --git a/3.25.4-scylla/upgrading.html b/3.25.4-scylla/upgrading.html new file mode 100644 index 0000000000..7d6d579e8b --- /dev/null +++ b/3.25.4-scylla/upgrading.html @@ -0,0 +1,1028 @@ + + + + + + + + + + + + + Upgrading | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

Upgrading

+
+
+
+

Upgrading from dse-driver

+

Since 3.21.0, scylla-driver fully supports DataStax products. dse-driver and +dse-graph users should now migrate to scylla-driver to benefit from latest bug fixes +and new features. The upgrade to this new unified driver version is straightforward +with no major API changes.

+
+

Installation

+

Only the scylla-driver package should be installed. dse-driver and dse-graph +are not required anymore:

+
pip install scylla-driver
+
+
+

If you need the Graph Fluent API (features provided by dse-graph):

+
pip install scylla-driver[graph]
+
+
+

See Installation for more details.

+
+
+

Import from the cassandra module

+

There is no dse module, so you should import from the cassandra module. You +need to change only the first module of your import statements, not the submodules.

+
from dse.cluster import Cluster, EXEC_PROFILE_GRAPH_DEFAULT
+from dse.auth import PlainTextAuthProvider
+from dse.policies import WhiteListRoundRobinPolicy
+
+# becomes
+
+from cassandra.cluster import Cluster, EXEC_PROFILE_GRAPH_DEFAULT
+from cassandra.auth import PlainTextAuthProvider
+from cassandra.policies import WhiteListRoundRobinPolicy
+
+
+

Also note that the cassandra.hosts module doesn’t exist in scylla-driver. This +module is named cassandra.pool.

+
+
+

dse-graph

+

dse-graph features are now built into scylla-driver. The only change you need +to do is your import statements:

+
from dse_graph import ..
+from dse_graph.query import ..
+
+# becomes
+
+from cassandra.datastax.graph.fluent import ..
+from cassandra.datastax.graph.fluent.query import ..
+
+
+

See fluent.

+
+
+

Session.execute and Session.execute_async API

+

Although it is not common to use this API with positional arguments, it is +important to be aware that the host and execute_as parameters have had +their positional order swapped. This is only because execute_as was added +in dse-driver before host.

+

See Session.execute().

+
+
+

Deprecations

+

These changes are optional, but recommended:

+
    +
  • Importing from cassandra.graph is deprecated. Consider importing from cassandra.datastax.graph.

  • +
  • Use DefaultLoadBalancingPolicy instead of DSELoadBalancingPolicy.

  • +
+
+
+
+

Upgrading to 3.0

+

Version 3.0 of the DataStax Python driver for Apache Cassandra +adds support for Cassandra 3.0 while maintaining support for +previously supported versions. In addition to substantial internal rework, +there are several updates to the API that integrators will need +to consider:

+
+

Default consistency is now LOCAL_ONE

+

Previous value was ONE. The new value is introduced to mesh with the default +DC-aware load balancing policy and to match other drivers.

+
+
+

Execution API Updates

+
+

Result return normalization

+

PYTHON-368

+

Previously results would be returned as a list of rows for result rows +up to fetch_size, and PagedResult afterward. This could break +application code that assumed one type and got another.

+

Now, all results are returned as an iterable ResultSet.

+

The preferred way to consume results of unknown size is to iterate through +them, letting automatic paging occur as they are consumed.

+
results = session.execute("SELECT * FROM system.local")
+for row in results:
+    process(row)
+
+
+

If the expected size of the results is known, it is still possible to +materialize a list using the iterator:

+
results = session.execute("SELECT * FROM system.local")
+row_list = list(results)
+
+
+

For backward compatibility, ResultSet supports indexing. When +accessed at an index, a ~.ResultSet object will materialize all its pages:

+
results = session.execute("SELECT * FROM system.local")
+first_result = results[0]  # materializes results, fetching all pages
+
+
+

This can send requests and load (possibly large) results into memory, so +~.ResultSet will log a warning on implicit materialization.

+
+
+

Trace information is not attached to executed Statements

+

PYTHON-318

+

Previously trace data was attached to Statements if tracing was enabled. This +could lead to confusion if the same statement was used for multiple executions.

+

Now, trace data is associated with the ResponseFuture and ResultSet +returned for each query:

+

ResponseFuture.get_query_trace()

+

ResponseFuture.get_all_query_traces()

+

ResultSet.get_query_trace()

+

ResultSet.get_all_query_traces()

+
+
+

Binding named parameters now ignores extra names

+

PYTHON-178

+

Previously, BoundStatement.bind() would raise if a mapping +was passed with extra names not found in the prepared statement.

+

Behavior in 3.0+ is to ignore extra names.

+
+
+
+

blist removed as soft dependency

+

PYTHON-385

+

Previously the driver had a soft dependency on blist sortedset, using +that where available and using an internal fallback where possible.

+

Now, the driver never chooses the blist variant, instead returning the +internal util.SortedSet for all set results. The class implements +all standard set operations, so no integration code should need to change unless +it explicitly checks for sortedset type.

+
+
+

Metadata API Updates

+

PYTHON-276, PYTHON-408, PYTHON-400, PYTHON-422

+

Cassandra 3.0 brought a substantial overhaul to the internal schema metadata representation. +This version of the driver supports that metadata in addition to the legacy version. Doing so +also brought some changes to the metadata model.

+

The present API is documented: cassandra.metadata. Changes highlighted below:

+
    +
  • All types are now exposed as CQL types instead of types derived from the internal server implementation

  • +
  • Some metadata attributes have changed names to match current nomenclature (for example, Index.kind in place of Index.type).

  • +
  • Some metadata attributes removed

    +
      +
    • TableMetadata.keyspace reference replaced with TableMetadata.keyspace_name

    • +
    • ColumnMetadata.index is removed table- and keyspace-level mappings are still maintained

    • +
    +
  • +
+
+
+

Several deprecated features are removed

+

PYTHON-292

+
    +
  • ResponseFuture.result timeout parameter is removed, use Session.execute timeout instead (031ebb0)

  • +
  • Cluster.refresh_schema removed, use Cluster.refresh_*_metadata instead (419fcdf)

  • +
  • Cluster.submit_schema_refresh removed (574266d)

  • +
  • cqltypes time/date functions removed, use util entry points instead (bb984ee)

  • +
  • decoder module removed (e16a073)

  • +
  • TableMetadata.keyspace attribute replaced with keyspace_name (cc94073)

  • +
  • cqlengine.columns.TimeUUID.from_datetime removed, use util variant instead (96489cc)

  • +
  • cqlengine.columns.Float(double_precision) parameter removed, use columns.Double instead (a2d3a98)

  • +
  • cqlengine keyspace management functions are removed in favor of the strategy-specific entry points (4bd5909)

  • +
  • cqlengine.Model.__polymorphic_*__ attributes removed, use __discriminator* attributes instead (9d98c8e)

  • +
  • cqlengine.statements will no longer warn about list list prepend behavior (79efe97)

  • +
+
+
+
+

Upgrading to 2.1 from 2.0

+

Version 2.1 of the DataStax Python driver for Apache Cassandra +adds support for Cassandra 2.1 and version 3 of the native protocol.

+

Cassandra 1.2, 2.0, and 2.1 are all supported. However, 1.2 only +supports protocol version 1, and 2.0 only supports versions 1 and +2, so some features may not be available.

+
+

Using the v3 Native Protocol

+

By default, the driver will attempt to use version 2 of the +native protocol. To use version 3, you must explicitly +set the protocol_version:

+
from cassandra.cluster import Cluster
+
+cluster = Cluster(protocol_version=3)
+
+
+

Note that protocol version 3 is only supported by Cassandra 2.1+.

+

In future releases, the driver may default to using protocol version +3.

+
+
+

Working with User-Defined Types

+

Cassandra 2.1 introduced the ability to define new types:

+
USE KEYSPACE mykeyspace;
+
+CREATE TYPE address (street text, city text, zip int);
+
+
+

The driver generally expects you to use instances of a specific +class to represent column values of this type. You can let the +driver know what class to use with Cluster.register_user_type():

+
cluster = Cluster()
+
+class Address(object):
+
+    def __init__(self, street, city, zipcode):
+        self.street = street
+        self.city = text
+        self.zipcode = zipcode
+
+cluster.register_user_type('mykeyspace', 'address', Address)
+
+
+

When inserting data for address columns, you should pass in +instances of Address. When querying data, address column +values will be instances of Address.

+

If no class is registered for a user-defined type, query results +will use a namedtuple class and data may only be inserted +though prepared statements.

+

See User Defined Types for more details.

+
+
+

Customizing Encoders for Non-prepared Statements

+

Starting with version 2.1 of the driver, it is possible to customize +how Python types are converted to CQL literals when working with +non-prepared statements. This is done on a per-Session +basis through Session.encoder:

+
cluster = Cluster()
+session = cluster.connect()
+session.encoder.mapping[tuple] = session.encoder.cql_encode_tuple
+
+
+

See Type Conversions for the table of default CQL literal conversions.

+
+
+

Using Client-Side Protocol-Level Timestamps

+

With version 3 of the native protocol, timestamps may be supplied by the +client at the protocol level. (Normally, if they are not specified within +the CQL query itself, a timestamp is generated server-side.)

+

When protocol_version is set to 3 or higher, the driver +will automatically use client-side timestamps with microsecond precision +unless Session.use_client_timestamp is changed to False. +If a timestamp is specified within the CQL query, it will override the +timestamp generated by the driver.

+
+
+
+

Upgrading to 2.0 from 1.x

+

Version 2.0 of the DataStax Python driver for Apache Cassandra +includes some notable improvements over version 1.x. This version +of the driver supports Cassandra 1.2, 2.0, and 2.1. However, not +all features may be used with Cassandra 1.2, and some new features +in 2.1 are not yet supported.

+
+

Using the v2 Native Protocol

+

By default, the driver will attempt to use version 2 of Cassandra’s +native protocol. You can explicitly set the protocol version to +2, though:

+
from cassandra.cluster import Cluster
+
+cluster = Cluster(protocol_version=2)
+
+
+

When working with Cassandra 1.2, you will need to +explicitly set the protocol_version to 1:

+
from cassandra.cluster import Cluster
+
+cluster = Cluster(protocol_version=1)
+
+
+
+
+

Automatic Query Paging

+

Version 2 of the native protocol adds support for automatic query +paging, which can make dealing with large result sets much simpler.

+

See Paging Large Queries for full details.

+
+
+

Protocol-Level Batch Statements

+

With version 1 of the native protocol, batching of statements required +using a BATCH cql query. +With version 2 of the native protocol, you can now batch statements at +the protocol level. This allows you to use many different prepared +statements within a single batch.

+

See BatchStatement for details and usage examples.

+
+
+

SASL-based Authentication

+

Also new in version 2 of the native protocol is SASL-based authentication. +See the section on Security for details and examples.

+
+
+

Lightweight Transactions

+

Lightweight transactions are another new feature. To use lightweight transactions, add IF clauses +to your CQL queries and set the serial_consistency_level +on your statements.

+
+
+

Calling Cluster.shutdown()

+

In order to fix some issues around garbage collection and unclean interpreter +shutdowns, version 2.0 of the driver requires you to call Cluster.shutdown() +on your Cluster objects when you are through with them. +This helps to guarantee a clean shutdown.

+
+
+

Deprecations

+

The following functions have moved from cassandra.decoder to cassandra.query. +The original functions have been left in place with a DeprecationWarning for +now:

+ +
+
+

Dependency Changes

+

The following dependencies have officially been made optional:

+
    +
  • scales

  • +
  • blist

  • +
+

And one new dependency has been added (to enable Python 3 support):

+
    +
  • six

  • +
+
+
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.25.4-scylla/user_defined_types.html b/3.25.4-scylla/user_defined_types.html new file mode 100644 index 0000000000..de519b3d0d --- /dev/null +++ b/3.25.4-scylla/user_defined_types.html @@ -0,0 +1,758 @@ + + + + + + + + + + + + + User Defined Types | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for a previous version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

User Defined Types

+

Cassandra 2.1 introduced user-defined types (UDTs). You can create a +new type through CREATE TYPE statements in CQL:

+
CREATE TYPE address (street text, zip int);
+
+
+

Version 2.1 of the Python driver adds support for user-defined types.

+
+

Registering a UDT

+

You can tell the Python driver to return columns of a specific UDT as +instances of a class or a dict by registering them with your Cluster +instance through Cluster.register_user_type():

+
+

Map a Class to a UDT

+
cluster = Cluster(protocol_version=3)
+session = cluster.connect()
+session.set_keyspace('mykeyspace')
+session.execute("CREATE TYPE address (street text, zipcode int)")
+session.execute("CREATE TABLE users (id int PRIMARY KEY, location frozen<address>)")
+
+# create a class to map to the "address" UDT
+class Address(object):
+
+    def __init__(self, street, zipcode):
+        self.street = street
+        self.zipcode = zipcode
+
+cluster.register_user_type('mykeyspace', 'address', Address)
+
+# insert a row using an instance of Address
+session.execute("INSERT INTO users (id, location) VALUES (%s, %s)",
+                (0, Address("123 Main St.", 78723)))
+
+# results will include Address instances
+results = session.execute("SELECT * FROM users")
+row = results[0]
+print(row.id, row.location.street, row.location.zipcode)
+
+
+
+
+

Map a dict to a UDT

+
cluster = Cluster(protocol_version=3)
+session = cluster.connect()
+session.set_keyspace('mykeyspace')
+session.execute("CREATE TYPE address (street text, zipcode int)")
+session.execute("CREATE TABLE users (id int PRIMARY KEY, location frozen<address>)")
+
+cluster.register_user_type('mykeyspace', 'address', dict)
+
+# insert a row using a prepared statement and a tuple
+insert_statement = session.prepare("INSERT INTO mykeyspace.users (id, location) VALUES (?, ?)")
+session.execute(insert_statement, [0, ("123 Main St.", 78723)])
+
+# results will include dict instances
+results = session.execute("SELECT * FROM users")
+row = results[0]
+print(row.id, row.location['street'], row.location['zipcode'])
+
+
+
+
+
+

Using UDTs Without Registering Them

+

Although it is recommended to register your types with +Cluster.register_user_type(), the driver gives you some options +for working with unregistered UDTS.

+

When you use prepared statements, the driver knows what data types to +expect for each placeholder. This allows you to pass any object you +want for a UDT, as long as it has attributes that match the field names +for the UDT:

+
cluster = Cluster(protocol_version=3)
+session = cluster.connect()
+session.set_keyspace('mykeyspace')
+session.execute("CREATE TYPE address (street text, zipcode int)")
+session.execute("CREATE TABLE users (id int PRIMARY KEY, location frozen<address>)")
+
+class Foo(object):
+
+    def __init__(self, street, zipcode, otherstuff):
+        self.street = street
+        self.zipcode = zipcode
+        self.otherstuff = otherstuff
+
+insert_statement = session.prepare("INSERT INTO users (id, location) VALUES (?, ?)")
+
+# since we're using a prepared statement, we don't *have* to register
+# a class to map to the UDT to insert data.  The object just needs to have
+# "street" and "zipcode" attributes (which Foo does):
+session.execute(insert_statement, [0, Foo("123 Main St.", 78723, "some other stuff")])
+
+# when we query data, UDT columns that don't have a class registered
+# will be returned as namedtuples:
+results = session.execute("SELECT * FROM users")
+first_row = results[0]
+address = first_row.location
+print(address)  # prints "Address(street='123 Main St.', zipcode=78723)"
+street = address.street
+zipcode = address.street
+
+
+

As shown in the code example, inserting data for UDT columns without registering +a class works fine for prepared statements. However, you must register a +class to insert UDT columns with unprepared statements.* You can still query +UDT columns without registered classes using unprepared statements, they will +simply return namedtuple instances (just like prepared statements do).

+

* this applies to parameterized unprepared statements, in which the driver will be formatting parameters – not statements with interpolated UDT literals.

+
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.26.2-scylla/.buildinfo b/3.26.2-scylla/.buildinfo new file mode 100644 index 0000000000..7f4cb20925 --- /dev/null +++ b/3.26.2-scylla/.buildinfo @@ -0,0 +1,4 @@ +# Sphinx build info version 1 +# This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done. +config: cfc961d6ca3409e87cb3e7d1c552b73f +tags: 645f666f9bcd5a90fca523b33c5a78b7 diff --git a/3.26.2-scylla/.doctrees/CHANGELOG.doctree b/3.26.2-scylla/.doctrees/CHANGELOG.doctree new file mode 100644 index 0000000000..d33e3c5c2d Binary files /dev/null and b/3.26.2-scylla/.doctrees/CHANGELOG.doctree differ diff --git a/3.26.2-scylla/.doctrees/api/cassandra.doctree b/3.26.2-scylla/.doctrees/api/cassandra.doctree new file mode 100644 index 0000000000..5e12608782 Binary files /dev/null and b/3.26.2-scylla/.doctrees/api/cassandra.doctree differ diff --git a/3.26.2-scylla/.doctrees/api/cassandra/auth.doctree b/3.26.2-scylla/.doctrees/api/cassandra/auth.doctree new file mode 100644 index 0000000000..c57613c769 Binary files /dev/null and b/3.26.2-scylla/.doctrees/api/cassandra/auth.doctree differ diff --git a/3.26.2-scylla/.doctrees/api/cassandra/cluster.doctree b/3.26.2-scylla/.doctrees/api/cassandra/cluster.doctree new file mode 100644 index 0000000000..550b263ae5 Binary files /dev/null and b/3.26.2-scylla/.doctrees/api/cassandra/cluster.doctree differ diff --git a/3.26.2-scylla/.doctrees/api/cassandra/concurrent.doctree b/3.26.2-scylla/.doctrees/api/cassandra/concurrent.doctree new file mode 100644 index 0000000000..c3809aa7dc Binary files /dev/null and b/3.26.2-scylla/.doctrees/api/cassandra/concurrent.doctree differ diff --git a/3.26.2-scylla/.doctrees/api/cassandra/connection.doctree b/3.26.2-scylla/.doctrees/api/cassandra/connection.doctree new file mode 100644 index 0000000000..3b1e0f26ea Binary files /dev/null and b/3.26.2-scylla/.doctrees/api/cassandra/connection.doctree differ diff --git a/3.26.2-scylla/.doctrees/api/cassandra/cqlengine/columns.doctree b/3.26.2-scylla/.doctrees/api/cassandra/cqlengine/columns.doctree new file mode 100644 index 0000000000..654fde2ed5 Binary files /dev/null and b/3.26.2-scylla/.doctrees/api/cassandra/cqlengine/columns.doctree differ diff --git a/3.26.2-scylla/.doctrees/api/cassandra/cqlengine/connection.doctree b/3.26.2-scylla/.doctrees/api/cassandra/cqlengine/connection.doctree new file mode 100644 index 0000000000..1d3db8b023 Binary files /dev/null and b/3.26.2-scylla/.doctrees/api/cassandra/cqlengine/connection.doctree differ diff --git a/3.26.2-scylla/.doctrees/api/cassandra/cqlengine/management.doctree b/3.26.2-scylla/.doctrees/api/cassandra/cqlengine/management.doctree new file mode 100644 index 0000000000..0bfe36d49e Binary files /dev/null and b/3.26.2-scylla/.doctrees/api/cassandra/cqlengine/management.doctree differ diff --git a/3.26.2-scylla/.doctrees/api/cassandra/cqlengine/models.doctree b/3.26.2-scylla/.doctrees/api/cassandra/cqlengine/models.doctree new file mode 100644 index 0000000000..a2297472c0 Binary files /dev/null and b/3.26.2-scylla/.doctrees/api/cassandra/cqlengine/models.doctree differ diff --git a/3.26.2-scylla/.doctrees/api/cassandra/cqlengine/query.doctree b/3.26.2-scylla/.doctrees/api/cassandra/cqlengine/query.doctree new file mode 100644 index 0000000000..cfddd049e9 Binary files /dev/null and b/3.26.2-scylla/.doctrees/api/cassandra/cqlengine/query.doctree differ diff --git a/3.26.2-scylla/.doctrees/api/cassandra/cqlengine/usertype.doctree b/3.26.2-scylla/.doctrees/api/cassandra/cqlengine/usertype.doctree new file mode 100644 index 0000000000..d87bd3fbce Binary files /dev/null and b/3.26.2-scylla/.doctrees/api/cassandra/cqlengine/usertype.doctree differ diff --git a/3.26.2-scylla/.doctrees/api/cassandra/datastax/graph/fluent/index.doctree b/3.26.2-scylla/.doctrees/api/cassandra/datastax/graph/fluent/index.doctree new file mode 100644 index 0000000000..5132230c72 Binary files /dev/null and b/3.26.2-scylla/.doctrees/api/cassandra/datastax/graph/fluent/index.doctree differ diff --git a/3.26.2-scylla/.doctrees/api/cassandra/datastax/graph/fluent/predicates.doctree b/3.26.2-scylla/.doctrees/api/cassandra/datastax/graph/fluent/predicates.doctree new file mode 100644 index 0000000000..ff3ad8e6db Binary files /dev/null and b/3.26.2-scylla/.doctrees/api/cassandra/datastax/graph/fluent/predicates.doctree differ diff --git a/3.26.2-scylla/.doctrees/api/cassandra/datastax/graph/fluent/query.doctree b/3.26.2-scylla/.doctrees/api/cassandra/datastax/graph/fluent/query.doctree new file mode 100644 index 0000000000..0e89648ef4 Binary files /dev/null and b/3.26.2-scylla/.doctrees/api/cassandra/datastax/graph/fluent/query.doctree differ diff --git a/3.26.2-scylla/.doctrees/api/cassandra/datastax/graph/index.doctree b/3.26.2-scylla/.doctrees/api/cassandra/datastax/graph/index.doctree new file mode 100644 index 0000000000..ee7ad60e72 Binary files /dev/null and b/3.26.2-scylla/.doctrees/api/cassandra/datastax/graph/index.doctree differ diff --git a/3.26.2-scylla/.doctrees/api/cassandra/decoder.doctree b/3.26.2-scylla/.doctrees/api/cassandra/decoder.doctree new file mode 100644 index 0000000000..bc05d8b530 Binary files /dev/null and b/3.26.2-scylla/.doctrees/api/cassandra/decoder.doctree differ diff --git a/3.26.2-scylla/.doctrees/api/cassandra/encoder.doctree b/3.26.2-scylla/.doctrees/api/cassandra/encoder.doctree new file mode 100644 index 0000000000..b7157d3b84 Binary files /dev/null and b/3.26.2-scylla/.doctrees/api/cassandra/encoder.doctree differ diff --git a/3.26.2-scylla/.doctrees/api/cassandra/graph.doctree b/3.26.2-scylla/.doctrees/api/cassandra/graph.doctree new file mode 100644 index 0000000000..02b62fe7ae Binary files /dev/null and b/3.26.2-scylla/.doctrees/api/cassandra/graph.doctree differ diff --git a/3.26.2-scylla/.doctrees/api/cassandra/io/asyncioreactor.doctree b/3.26.2-scylla/.doctrees/api/cassandra/io/asyncioreactor.doctree new file mode 100644 index 0000000000..6c1d5ded7a Binary files /dev/null and b/3.26.2-scylla/.doctrees/api/cassandra/io/asyncioreactor.doctree differ diff --git a/3.26.2-scylla/.doctrees/api/cassandra/io/asyncorereactor.doctree b/3.26.2-scylla/.doctrees/api/cassandra/io/asyncorereactor.doctree new file mode 100644 index 0000000000..a00c8cfa7d Binary files /dev/null and b/3.26.2-scylla/.doctrees/api/cassandra/io/asyncorereactor.doctree differ diff --git a/3.26.2-scylla/.doctrees/api/cassandra/io/eventletreactor.doctree b/3.26.2-scylla/.doctrees/api/cassandra/io/eventletreactor.doctree new file mode 100644 index 0000000000..ff3b7b9ecf Binary files /dev/null and b/3.26.2-scylla/.doctrees/api/cassandra/io/eventletreactor.doctree differ diff --git a/3.26.2-scylla/.doctrees/api/cassandra/io/geventreactor.doctree b/3.26.2-scylla/.doctrees/api/cassandra/io/geventreactor.doctree new file mode 100644 index 0000000000..568203ae54 Binary files /dev/null and b/3.26.2-scylla/.doctrees/api/cassandra/io/geventreactor.doctree differ diff --git a/3.26.2-scylla/.doctrees/api/cassandra/io/libevreactor.doctree b/3.26.2-scylla/.doctrees/api/cassandra/io/libevreactor.doctree new file mode 100644 index 0000000000..bc45531d44 Binary files /dev/null and b/3.26.2-scylla/.doctrees/api/cassandra/io/libevreactor.doctree differ diff --git a/3.26.2-scylla/.doctrees/api/cassandra/io/twistedreactor.doctree b/3.26.2-scylla/.doctrees/api/cassandra/io/twistedreactor.doctree new file mode 100644 index 0000000000..b18af8287d Binary files /dev/null and b/3.26.2-scylla/.doctrees/api/cassandra/io/twistedreactor.doctree differ diff --git a/3.26.2-scylla/.doctrees/api/cassandra/metadata.doctree b/3.26.2-scylla/.doctrees/api/cassandra/metadata.doctree new file mode 100644 index 0000000000..143e87d588 Binary files /dev/null and b/3.26.2-scylla/.doctrees/api/cassandra/metadata.doctree differ diff --git a/3.26.2-scylla/.doctrees/api/cassandra/metrics.doctree b/3.26.2-scylla/.doctrees/api/cassandra/metrics.doctree new file mode 100644 index 0000000000..4e3d0169b1 Binary files /dev/null and b/3.26.2-scylla/.doctrees/api/cassandra/metrics.doctree differ diff --git a/3.26.2-scylla/.doctrees/api/cassandra/policies.doctree b/3.26.2-scylla/.doctrees/api/cassandra/policies.doctree new file mode 100644 index 0000000000..06c33aa472 Binary files /dev/null and b/3.26.2-scylla/.doctrees/api/cassandra/policies.doctree differ diff --git a/3.26.2-scylla/.doctrees/api/cassandra/pool.doctree b/3.26.2-scylla/.doctrees/api/cassandra/pool.doctree new file mode 100644 index 0000000000..1ca8048ddc Binary files /dev/null and b/3.26.2-scylla/.doctrees/api/cassandra/pool.doctree differ diff --git a/3.26.2-scylla/.doctrees/api/cassandra/protocol.doctree b/3.26.2-scylla/.doctrees/api/cassandra/protocol.doctree new file mode 100644 index 0000000000..c3be592ba7 Binary files /dev/null and b/3.26.2-scylla/.doctrees/api/cassandra/protocol.doctree differ diff --git a/3.26.2-scylla/.doctrees/api/cassandra/query.doctree b/3.26.2-scylla/.doctrees/api/cassandra/query.doctree new file mode 100644 index 0000000000..cbc6843a56 Binary files /dev/null and b/3.26.2-scylla/.doctrees/api/cassandra/query.doctree differ diff --git a/3.26.2-scylla/.doctrees/api/cassandra/timestamps.doctree b/3.26.2-scylla/.doctrees/api/cassandra/timestamps.doctree new file mode 100644 index 0000000000..671d88e005 Binary files /dev/null and b/3.26.2-scylla/.doctrees/api/cassandra/timestamps.doctree differ diff --git a/3.26.2-scylla/.doctrees/api/cassandra/util.doctree b/3.26.2-scylla/.doctrees/api/cassandra/util.doctree new file mode 100644 index 0000000000..410c1adf8c Binary files /dev/null and b/3.26.2-scylla/.doctrees/api/cassandra/util.doctree differ diff --git a/3.26.2-scylla/.doctrees/api/index.doctree b/3.26.2-scylla/.doctrees/api/index.doctree new file mode 100644 index 0000000000..cecb227392 Binary files /dev/null and b/3.26.2-scylla/.doctrees/api/index.doctree differ diff --git a/3.26.2-scylla/.doctrees/cqlengine/batches.doctree b/3.26.2-scylla/.doctrees/cqlengine/batches.doctree new file mode 100644 index 0000000000..0f5fff949b Binary files /dev/null and b/3.26.2-scylla/.doctrees/cqlengine/batches.doctree differ diff --git a/3.26.2-scylla/.doctrees/cqlengine/connections.doctree b/3.26.2-scylla/.doctrees/cqlengine/connections.doctree new file mode 100644 index 0000000000..fb04993514 Binary files /dev/null and b/3.26.2-scylla/.doctrees/cqlengine/connections.doctree differ diff --git a/3.26.2-scylla/.doctrees/cqlengine/faq.doctree b/3.26.2-scylla/.doctrees/cqlengine/faq.doctree new file mode 100644 index 0000000000..4dc14023e2 Binary files /dev/null and b/3.26.2-scylla/.doctrees/cqlengine/faq.doctree differ diff --git a/3.26.2-scylla/.doctrees/cqlengine/models.doctree b/3.26.2-scylla/.doctrees/cqlengine/models.doctree new file mode 100644 index 0000000000..fd4f453d9b Binary files /dev/null and b/3.26.2-scylla/.doctrees/cqlengine/models.doctree differ diff --git a/3.26.2-scylla/.doctrees/cqlengine/queryset.doctree b/3.26.2-scylla/.doctrees/cqlengine/queryset.doctree new file mode 100644 index 0000000000..c97bea64ff Binary files /dev/null and b/3.26.2-scylla/.doctrees/cqlengine/queryset.doctree differ diff --git a/3.26.2-scylla/.doctrees/cqlengine/third-party.doctree b/3.26.2-scylla/.doctrees/cqlengine/third-party.doctree new file mode 100644 index 0000000000..7d7e01a930 Binary files /dev/null and b/3.26.2-scylla/.doctrees/cqlengine/third-party.doctree differ diff --git a/3.26.2-scylla/.doctrees/cqlengine/upgrade-guide.doctree b/3.26.2-scylla/.doctrees/cqlengine/upgrade-guide.doctree new file mode 100644 index 0000000000..b2669ecf01 Binary files /dev/null and b/3.26.2-scylla/.doctrees/cqlengine/upgrade-guide.doctree differ diff --git a/3.26.2-scylla/.doctrees/dates-and-times.doctree b/3.26.2-scylla/.doctrees/dates-and-times.doctree new file mode 100644 index 0000000000..586b4615f7 Binary files /dev/null and b/3.26.2-scylla/.doctrees/dates-and-times.doctree differ diff --git a/3.26.2-scylla/.doctrees/environment.pickle b/3.26.2-scylla/.doctrees/environment.pickle new file mode 100644 index 0000000000..85e3dbc0f8 Binary files /dev/null and b/3.26.2-scylla/.doctrees/environment.pickle differ diff --git a/3.26.2-scylla/.doctrees/execution-profiles.doctree b/3.26.2-scylla/.doctrees/execution-profiles.doctree new file mode 100644 index 0000000000..f55d6e09f5 Binary files /dev/null and b/3.26.2-scylla/.doctrees/execution-profiles.doctree differ diff --git a/3.26.2-scylla/.doctrees/faq.doctree b/3.26.2-scylla/.doctrees/faq.doctree new file mode 100644 index 0000000000..7795d9d1f6 Binary files /dev/null and b/3.26.2-scylla/.doctrees/faq.doctree differ diff --git a/3.26.2-scylla/.doctrees/getting-started.doctree b/3.26.2-scylla/.doctrees/getting-started.doctree new file mode 100644 index 0000000000..1f903a41ef Binary files /dev/null and b/3.26.2-scylla/.doctrees/getting-started.doctree differ diff --git a/3.26.2-scylla/.doctrees/index.doctree b/3.26.2-scylla/.doctrees/index.doctree new file mode 100644 index 0000000000..f15f9de0db Binary files /dev/null and b/3.26.2-scylla/.doctrees/index.doctree differ diff --git a/3.26.2-scylla/.doctrees/installation.doctree b/3.26.2-scylla/.doctrees/installation.doctree new file mode 100644 index 0000000000..c11d6b4f22 Binary files /dev/null and b/3.26.2-scylla/.doctrees/installation.doctree differ diff --git a/3.26.2-scylla/.doctrees/lwt.doctree b/3.26.2-scylla/.doctrees/lwt.doctree new file mode 100644 index 0000000000..0825cae638 Binary files /dev/null and b/3.26.2-scylla/.doctrees/lwt.doctree differ diff --git a/3.26.2-scylla/.doctrees/object-mapper.doctree b/3.26.2-scylla/.doctrees/object-mapper.doctree new file mode 100644 index 0000000000..8231ef523d Binary files /dev/null and b/3.26.2-scylla/.doctrees/object-mapper.doctree differ diff --git a/3.26.2-scylla/.doctrees/performance.doctree b/3.26.2-scylla/.doctrees/performance.doctree new file mode 100644 index 0000000000..7ff82a323b Binary files /dev/null and b/3.26.2-scylla/.doctrees/performance.doctree differ diff --git a/3.26.2-scylla/.doctrees/query-paging.doctree b/3.26.2-scylla/.doctrees/query-paging.doctree new file mode 100644 index 0000000000..1b96796b0d Binary files /dev/null and b/3.26.2-scylla/.doctrees/query-paging.doctree differ diff --git a/3.26.2-scylla/.doctrees/scylla-cloud-serverless.doctree b/3.26.2-scylla/.doctrees/scylla-cloud-serverless.doctree new file mode 100644 index 0000000000..323103c0a5 Binary files /dev/null and b/3.26.2-scylla/.doctrees/scylla-cloud-serverless.doctree differ diff --git a/3.26.2-scylla/.doctrees/scylla-cloud.doctree b/3.26.2-scylla/.doctrees/scylla-cloud.doctree new file mode 100644 index 0000000000..c563f04221 Binary files /dev/null and b/3.26.2-scylla/.doctrees/scylla-cloud.doctree differ diff --git a/3.26.2-scylla/.doctrees/scylla-specific.doctree b/3.26.2-scylla/.doctrees/scylla-specific.doctree new file mode 100644 index 0000000000..358639eda0 Binary files /dev/null and b/3.26.2-scylla/.doctrees/scylla-specific.doctree differ diff --git a/3.26.2-scylla/.doctrees/security.doctree b/3.26.2-scylla/.doctrees/security.doctree new file mode 100644 index 0000000000..3024b87af6 Binary files /dev/null and b/3.26.2-scylla/.doctrees/security.doctree differ diff --git a/3.26.2-scylla/.doctrees/upgrading.doctree b/3.26.2-scylla/.doctrees/upgrading.doctree new file mode 100644 index 0000000000..9e84beb1f2 Binary files /dev/null and b/3.26.2-scylla/.doctrees/upgrading.doctree differ diff --git a/3.26.2-scylla/.doctrees/user-defined-types.doctree b/3.26.2-scylla/.doctrees/user-defined-types.doctree new file mode 100644 index 0000000000..903f45bdba Binary files /dev/null and b/3.26.2-scylla/.doctrees/user-defined-types.doctree differ diff --git a/3.26.2-scylla/.nojekyll b/3.26.2-scylla/.nojekyll new file mode 100644 index 0000000000..e69de29bb2 diff --git a/3.26.2-scylla/404.html b/3.26.2-scylla/404.html new file mode 100644 index 0000000000..d60936cbfe --- /dev/null +++ b/3.26.2-scylla/404.html @@ -0,0 +1,31 @@ + + + + + + + + + ScyllaDB + + + + + + + + + + + +
+

404

+

The ScyllaDB monster ate your page!

+

+ Home +

+
+ + + \ No newline at end of file diff --git a/3.26.2-scylla/CHANGELOG.html b/3.26.2-scylla/CHANGELOG.html new file mode 100644 index 0000000000..c84e597664 --- /dev/null +++ b/3.26.2-scylla/CHANGELOG.html @@ -0,0 +1,2957 @@ + + + + + + + + + + + + + CHANGELOG | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + + + +
+ +
+ +
+

CHANGELOG

+
+

3.26.0

+

March 13, 2023

+
+

Features

+
    +
  • Add support for execution profiles in execute_concurrent (PR 1122)

  • +
+
+
+

Bug Fixes

+
    +
  • Handle empty non-final result pages (PR 1110)

  • +
  • Do not re-use stream IDs for in-flight requests (PR 1114)

  • +
  • Asyncore race condition cause logging exception on shutdown (PYTHON-1266)

  • +
+
+
+

Others

+
    +
  • Fix deprecation warning in query tracing (PR 1103)

  • +
  • Remove mutable default values from some tests (PR 1116)

  • +
  • Remove dependency on unittest2 (PYTHON-1289)

  • +
  • Fix deprecation warnings for asyncio.coroutine annotation in asyncioreactor (PYTTHON-1290)

  • +
  • Fix typos in source files (PR 1126)

  • +
  • HostFilterPolicyInitTest fix for Python 3.11 (PR 1131)

  • +
  • Fix for DontPrepareOnIgnoredHostsTest (PYTHON-1287)

  • +
  • tests.integration.simulacron.test_connection failures (PYTHON-1304)

  • +
  • tests.integration.standard.test_single_interface.py appears to be failing for C* 4.0 (PYTHON-1329)

  • +
  • Authentication tests appear to be failing fraudulently (PYTHON-1328)

  • +
  • PreparedStatementTests.test_fail_if_different_query_id_on_reprepare() failing unexpectedly (PTYHON-1327)

  • +
  • Refactor deprecated unittest aliases for Python 3.11 compatibility (PR 1112)

  • +
+
+
+

Deprecations

+
    +
  • This release removes support for Python 2.7.x as well as Python 3.5.x and 3.6.x

  • +
+
+
+
+

3.25.0

+

March 18, 2021

+
+

Features

+
    +
  • Ensure the driver can connect when invalid peer hosts are in system.peers (PYTHON-1260)

  • +
  • Implement protocol v5 checksumming (PYTHON-1258)

  • +
  • Fix the default cqlengine connection mechanism to work with Astra (PYTHON-1265)

  • +
+
+
+

Bug Fixes

+
    +
  • Asyncore race condition cause logging exception on shutdown (PYTHON-1266)

  • +
  • Update list of reserved keywords (PYTHON-1269)

  • +
+
+
+

Others

+
    +
  • Drop Python 3.4 support (PYTHON-1220)

  • +
  • Update security documentation and examples to use PROTOCOL_TLS (PYTHON-1264)

  • +
+
+
+
+

3.24.0

+

June 18, 2020

+
+

Features

+
    +
  • Make geomet an optional dependency at runtime (PYTHON-1237)

  • +
  • Add use_default_tempdir cloud config options (PYTHON-1245)

  • +
  • Tcp flow control for libevreactor (PYTHON-1248)

  • +
+
+
+

Bug Fixes

+
    +
  • Unable to connect to a cloud cluster using Ubuntu 20.04 (PYTHON-1238)

  • +
  • PlainTextAuthProvider fails with unicode chars and Python3 (PYTHON-1241)

  • +
  • [GRAPH] Graph execution profiles consistency level are not set to LOCAL_QUORUM with a cloud cluster (PYTHON-1240)

  • +
  • [GRAPH] Can’t write data in a Boolean field using the Fluent API (PYTHON-1239)

  • +
  • [GRAPH] Fix elementMap() result deserialization (PYTHON-1233)

  • +
+
+
+

Others

+
    +
  • Bump geomet dependency version to 0.2 (PYTHON-1243)

  • +
  • Bump gremlinpython dependency version to 3.4.6 (PYTHON-1212)

  • +
  • Improve fluent graph documentation for core graphs (PYTHON-1244)

  • +
+
+
+
+

3.23.0

+

April 6, 2020

+
+

Features

+
    +
  • Transient Replication Support (PYTHON-1207)

  • +
  • Support system.peers_v2 and port discovery for C* 4.0 (PYTHON-700)

  • +
+
+
+

Bug Fixes

+
    +
  • Asyncore logging exception on shutdown (PYTHON-1228)

  • +
+
+
+
+

3.22.0

+

February 26, 2020

+
+

Features

+
    +
  • Add all() function to the ResultSet API (PYTHON-1203)

  • +
  • Parse new schema metadata in NGDG and generate table edges CQL syntax (PYTHON-996)

  • +
  • Add GraphSON3 support (PYTHON-788)

  • +
  • Use GraphSON3 as default for Native graphs (PYTHON-1004)

  • +
  • Add Tuple and UDT types for native graph (PYTHON-1005)

  • +
  • Add Duration type for native graph (PYTHON-1000)

  • +
  • Add gx:ByteBuffer graphson type support for Blob field (PYTHON-1027)

  • +
  • Enable Paging Through DSE Driver for Gremlin Traversals (PYTHON-1045)

  • +
  • Provide numerical wrappers to ensure proper graphson schema definition (PYTHON-1051)

  • +
  • Resolve the row_factory automatically for native graphs (PYTHON-1056)

  • +
  • Add g:TraversalMetrics/g:Metrics graph deserializers (PYTHON-1057)

  • +
  • Add g:BulkSet graph deserializers (PYTHON-1060)

  • +
  • Update Graph Engine names and the way to create a Classic/Native Graph (PYTHON-1090)

  • +
  • Update Native to Core Graph Engine

  • +
  • Add graphson3 and native graph support (PYTHON-1039)

  • +
  • Enable Paging Through DSE Driver for Gremlin Traversals (PYTHON-1045)

  • +
  • Expose filter predicates for cql collections (PYTHON-1019)

  • +
  • Add g:TraversalMetrics/Metrics deserializers (PYTHON-1057)

  • +
  • Make graph metadata handling more robust (PYTHON-1204)

  • +
+
+
+

Bug Fixes

+
    +
  • Make sure to only query the native_transport_address column with DSE (PYTHON-1205)

  • +
+
+
+
+

3.21.0

+

January 15, 2020

+
+

Features

+
    +
  • Unified driver: merge core and DSE drivers into a single package (PYTHON-1130)

  • +
  • Add Python 3.8 support (PYTHON-1189)

  • +
  • Allow passing ssl context for Twisted (PYTHON-1161)

  • +
  • Ssl context and cloud support for Eventlet (PYTHON-1162)

  • +
  • Cloud Twisted support (PYTHON-1163)

  • +
  • Add additional_write_policy and read_repair to system schema parsing (PYTHON-1048)

  • +
  • Flexible version parsing (PYTHON-1174)

  • +
  • Support NULL in collection deserializer (PYTHON-1123)

  • +
  • [GRAPH] Ability to execute Fluent Graph queries asynchronously (PYTHON-1129)

  • +
+
+
+

Bug Fixes

+
    +
  • Handle prepared id mismatch when repreparing on the fly (PYTHON-1124)

  • +
  • re-raising the CQLEngineException will fail on Python 3 (PYTHON-1166)

  • +
  • asyncio message chunks can be processed discontinuously (PYTHON-1185)

  • +
  • Reconnect attempts persist after downed node removed from peers (PYTHON-1181)

  • +
  • Connection fails to validate ssl certificate hostname when SSLContext.check_hostname is set (PYTHON-1186)

  • +
  • ResponseFuture._set_result crashes on connection error when used with PrepareMessage (PYTHON-1187)

  • +
  • Insights fail to serialize the startup message when the SSL Context is from PyOpenSSL (PYTHON-1192)

  • +
+
+
+

Others

+
    +
  • The driver has a new dependency: geomet. It comes from the dse-driver unification and +is used to support DSE geo types.

  • +
  • Remove *read_repair_chance table options (PYTHON-1140)

  • +
  • Avoid warnings about unspecified load balancing policy when connecting to a cloud cluster (PYTHON-1177)

  • +
  • Add new DSE CQL keywords (PYTHON-1122)

  • +
  • Publish binary wheel distributions (PYTHON-1013)

  • +
+
+
+

Deprecations

+
    +
  • DSELoadBalancingPolicy will be removed in the next major, consider using +the DefaultLoadBalancingPolicy.

  • +
+

Merged from dse-driver:

+
+
+

Features

+
    +
  • Insights integration (PYTHON-1047)

  • +
  • Graph execution profiles should preserve their graph_source when graph_options is overridden (PYTHON-1021)

  • +
  • Add NodeSync metadata (PYTHON-799)

  • +
  • Add new NodeSync failure values (PYTHON-934)

  • +
  • DETERMINISTIC and MONOTONIC Clauses for Functions and Aggregates (PYTHON-955)

  • +
  • GraphOptions should show a warning for unknown parameters (PYTHON-819)

  • +
  • DSE protocol version 2 and continous paging backpressure (PYTHON-798)

  • +
  • GraphSON2 Serialization/Deserialization Support (PYTHON-775)

  • +
  • Add graph-results payload option for GraphSON format (PYTHON-773)

  • +
  • Create an AuthProvider for the DSE transitional mode (PYTHON-831)

  • +
  • Implement serializers for the Graph String API (PYTHON-778)

  • +
  • Provide deserializers for GraphSON types (PYTHON-782)

  • +
  • Add Graph DurationType support (PYTHON-607)

  • +
  • Support DSE DateRange type (PYTHON-668)

  • +
  • RLAC CQL output for materialized views (PYTHON-682)

  • +
  • Add Geom Types wkt deserializer

  • +
  • DSE Graph Client timeouts in custom payload (PYTHON-589)

  • +
  • Make DSEGSSAPIAuthProvider accept principal name (PYTHON-574)

  • +
  • Add config profiles to DSE graph execution (PYTHON-570)

  • +
  • DSE Driver version checking (PYTHON-568)

  • +
  • Distinct default timeout for graph queries (PYTHON-477)

  • +
  • Graph result parsing for known types (PYTHON-479,487)

  • +
  • Distinct read/write CL for graph execution (PYTHON-509)

  • +
  • Target graph analytics query to spark master when available (PYTHON-510)

  • +
+
+
+

Bug Fixes

+
    +
  • Continuous paging sessions raise RuntimeError when results are not entirely consumed (PYTHON-1054)

  • +
  • GraphSON Property deserializer should return a dict instead of a set (PYTHON-1033)

  • +
  • ResponseFuture.has_more_pages may hold the wrong value (PYTHON-946)

  • +
  • DETERMINISTIC clause in AGGREGATE misplaced in CQL generation (PYTHON-963)

  • +
  • graph module import cause a DLL issue on Windows due to its cythonizing failure (PYTHON-900)

  • +
  • Update date serialization to isoformat in graph (PYTHON-805)

  • +
  • DateRange Parse Error (PYTHON-729)

  • +
  • MontonicTimestampGenerator.__init__ ignores class defaults (PYTHON-728)

  • +
  • metadata.get_host returning None unexpectedly (PYTHON-709)

  • +
  • Sockets associated with sessions not getting cleaned up on session.shutdown() (PYTHON-673)

  • +
  • Resolve FQDN from ip address and use that as host passed to SASLClient (PYTHON-566)

  • +
  • Geospatial type implementations don’t handle ‘EMPTY’ values. (PYTHON-481)

  • +
  • Correctly handle other types in geo type equality (PYTHON-508)

  • +
+
+
+

Other

+
    +
  • Add tests around cqlengine and continuous paging (PYTHON-872)

  • +
  • Add an abstract GraphStatement to handle different graph statements (PYTHON-789)

  • +
  • Write documentation examples for DSE 2.0 features (PYTHON-732)

  • +
  • DSE_V1 protocol should not include all of protocol v5 (PYTHON-694)

  • +
+
+
+
+

3.20.2

+

November 19, 2019

+
+

Bug Fixes

+
    +
  • Fix import error for old python installation without SSLContext (PYTHON-1183)

  • +
+
+
+
+

3.20.1

+

November 6, 2019

+
+

Bug Fixes

+
    +
  • ValueError: too many values to unpack (expected 2)” when there are two dashes in server version number (PYTHON-1172)

  • +
+
+
+
+

3.20.0

+

October 28, 2019

+
+

Features

+
    +
  • DataStax Astra Support (PYTHON-1074)

  • +
  • Use 4.0 schema parser in 4 alpha and snapshot builds (PYTHON-1158)

  • +
+
+
+

Bug Fixes

+
    +
  • Connection setup methods prevent using ExecutionProfile in cqlengine (PYTHON-1009)

  • +
  • Driver deadlock if all connections dropped by heartbeat whilst request in flight and request times out (PYTHON-1044)

  • +
  • Exception when use pk__token__gt filter In python 3.7 (PYTHON-1121)

  • +
+
+
+
+

3.19.0

+

August 26, 2019

+
+

Features

+
    +
  • Add Python 3.7 support (PYTHON-1016)

  • +
  • Future-proof Mapping imports (PYTHON-1023)

  • +
  • Include param values in cqlengine logging (PYTHON-1105)

  • +
  • NTS Token Replica Map Generation is slow (PYTHON-622)

  • +
+
+
+

Bug Fixes

+
    +
  • as_cql_query UDF/UDA parameters incorrectly includes “frozen” if arguments are collections (PYTHON-1031)

  • +
  • cqlengine does not currently support combining TTL and TIMESTAMP on INSERT (PYTHON-1093)

  • +
  • Fix incorrect metadata for compact counter tables (PYTHON-1100)

  • +
  • Call ConnectionException with correct kwargs (PYTHON-1117)

  • +
  • Can’t connect to clusters built from source because version parsing doesn’t handle ‘x.y-SNAPSHOT’ (PYTHON-1118)

  • +
  • Discovered node doesn´t honor the configured Cluster port on connection (PYTHON-1127)

  • +
  • Exception when use pk__token__gt filter In python 3.7 (PYTHON-1121)

  • +
+
+
+

Other

+
    +
  • Remove invalid warning in set_session when we initialize a default connection (PYTHON-1104)

  • +
  • Set the proper default ExecutionProfile.row_factory value (PYTHON-1119)

  • +
+
+
+
+

3.18.0

+

May 27, 2019

+
+

Features

+
    +
  • Abstract Host Connection information (PYTHON-1079)

  • +
  • Improve version parsing to support a non-integer 4th component (PYTHON-1091)

  • +
  • Expose on_request_error method in the RetryPolicy (PYTHON-1064)

  • +
  • Add jitter to ExponentialReconnectionPolicy (PYTHON-1065)

  • +
+
+
+

Bug Fixes

+
    +
  • Fix error when preparing queries with beta protocol v5 (PYTHON-1081)

  • +
  • Accept legacy empty strings as column names (PYTHON-1082)

  • +
  • Let util.SortedSet handle uncomparable elements (PYTHON-1087)

  • +
+
+
+
+

3.17.1

+

May 2, 2019

+
+

Bug Fixes

+
    +
  • Socket errors EAGAIN/EWOULDBLOCK are not handled properly and cause timeouts (PYTHON-1089)

  • +
+
+
+
+

3.17.0

+

February 19, 2019

+
+

Features

+
    +
  • Send driver name and version in startup message (PYTHON-1068)

  • +
  • Add Cluster ssl_context option to enable SSL (PYTHON-995)

  • +
  • Allow encrypted private keys for 2-way SSL cluster connections (PYTHON-995)

  • +
  • Introduce new method ConsistencyLevel.is_serial (PYTHON-1067)

  • +
  • Add Session.get_execution_profile (PYTHON-932)

  • +
  • Add host kwarg to Session.execute/execute_async APIs to send a query to a specific node (PYTHON-993)

  • +
+
+
+

Bug Fixes

+
    +
  • NoHostAvailable when all hosts are up and connectable (PYTHON-891)

  • +
  • Serial consistency level is not used (PYTHON-1007)

  • +
+
+
+

Other

+
    +
  • Fail faster on incorrect lz4 import (PYTHON-1042)

  • +
  • Bump Cython dependency version to 0.29 (PYTHON-1036)

  • +
  • Expand Driver SSL Documentation (PYTHON-740)

  • +
+
+
+

Deprecations

+
    +
  • Using Cluster.ssl_options to enable SSL is deprecated and will be removed in +the next major release, use ssl_context.

  • +
  • DowngradingConsistencyRetryPolicy is deprecated and will be +removed in the next major release. (PYTHON-937)

  • +
+
+
+
+

3.16.0

+

November 12, 2018

+
+

Bug Fixes

+
    +
  • Improve and fix socket error-catching code in nonblocking-socket reactors (PYTHON-1024)

  • +
  • Non-ASCII characters in schema break CQL string generation (PYTHON-1008)

  • +
  • Fix OSS driver’s virtual table support against DSE 6.0.X and future server releases (PYTHON-1020)

  • +
  • ResultSet.one() fails if the row_factory is using a generator (PYTHON-1026)

  • +
  • Log profile name on attempt to create existing profile (PYTHON-944)

  • +
  • Cluster instantiation fails if any contact points’ hostname resolution fails (PYTHON-895)

  • +
+
+
+

Other

+
    +
  • Fix tests when RF is not maintained if we decomission a node (PYTHON-1017)

  • +
  • Fix wrong use of ResultSet indexing (PYTHON-1015)

  • +
+
+
+
+

3.15.1

+

September 6, 2018

+
+

Bug Fixes

+
    +
  • C* 4.0 schema-parsing logic breaks running against DSE 6.0.X (PYTHON-1018)

  • +
+
+
+
+

3.15.0

+

August 30, 2018

+
+

Features

+
    +
  • Parse Virtual Keyspace Metadata (PYTHON-992)

  • +
+
+
+

Bug Fixes

+
    +
  • Tokenmap.get_replicas returns the wrong value if token coincides with the end of the range (PYTHON-978)

  • +
  • Python Driver fails with “more than 255 arguments” python exception when > 255 columns specified in query response (PYTHON-893)

  • +
  • Hang in integration.standard.test_cluster.ClusterTests.test_set_keyspace_twice (PYTHON-998)

  • +
  • Asyncore reactors should use a global variable instead of a class variable for the event loop (PYTHON-697)

  • +
+
+
+

Other

+
    +
  • Use global variable for libev loops so it can be subclassed (PYTHON-973)

  • +
  • Update SchemaParser for V4 (PYTHON-1006)

  • +
  • Bump Cython dependency version to 0.28 (PYTHON-1012)

  • +
+
+
+
+

3.14.0

+

April 17, 2018

+
+

Features

+
    +
  • Add one() function to the ResultSet API (PYTHON-947)

  • +
  • Create an utility function to fetch concurrently many keys from the same replica (PYTHON-647)

  • +
  • Allow filter queries with fields that have an index managed outside of cqlengine (PYTHON-966)

  • +
  • Twisted SSL Support (PYTHON-343)

  • +
  • Support IS NOT NULL operator in cqlengine (PYTHON-968)

  • +
+
+
+

Other

+
    +
  • Fix Broken Links in Docs (PYTHON-916)

  • +
  • Reevaluate MONKEY_PATCH_LOOP in test codebase (PYTHON-903)

  • +
  • Remove CASS_SERVER_VERSION and replace it for CASSANDRA_VERSION in tests (PYTHON-910)

  • +
  • Refactor CASSANDRA_VERSION to a some kind of version object (PYTHON-915)

  • +
  • Log warning when driver configures an authenticator, but server does not request authentication (PYTHON-940)

  • +
  • Warn users when using the deprecated Session.default_consistency_level (PYTHON-953)

  • +
  • Add DSE smoke test to OSS driver tests (PYTHON-894)

  • +
  • Document long compilation times and workarounds (PYTHON-868)

  • +
  • Improve error for batch WriteTimeouts (PYTHON-941)

  • +
  • Deprecate ResultSet indexing (PYTHON-945)

  • +
+
+
+
+

3.13.0

+

January 30, 2018

+
+

Features

+
    +
  • cqlengine: LIKE filter operator (PYTHON-512)

  • +
  • Support cassandra.query.BatchType with cqlengine BatchQuery (PYTHON-888)

  • +
+
+
+

Bug Fixes

+
    +
  • AttributeError: ‘NoneType’ object has no attribute ‘add_timer’ (PYTHON-862)

  • +
  • Support retry_policy in PreparedStatement (PYTHON-861)

  • +
  • __del__ method in Session is throwing an exception (PYTHON-813)

  • +
  • LZ4 import issue with recent versions (PYTHON-897)

  • +
  • ResponseFuture._connection can be None when returning request_id (PYTHON-853)

  • +
  • ResultSet.was_applied doesn’t support batch with LWT statements (PYTHON-848)

  • +
+
+
+

Other

+
    +
  • cqlengine: avoid warning when unregistering connection on shutdown (PYTHON-865)

  • +
  • Fix DeprecationWarning of log.warn (PYTHON-846)

  • +
  • Fix example_mapper.py for python3 (PYTHON-860)

  • +
  • Possible deadlock on cassandra.concurrent.execute_concurrent (PYTHON-768)

  • +
  • Add some known deprecated warnings for 4.x (PYTHON-877)

  • +
  • Remove copyright dates from copyright notices (PYTHON-863)

  • +
  • Remove “Experimental” tag from execution profiles documentation (PYTHON-840)

  • +
  • request_timer metrics descriptions are slightly incorrect (PYTHON-885)

  • +
  • Remove “Experimental” tag from cqlengine connections documentation (PYTHON-892)

  • +
  • Set in documentation default consistency for operations is LOCAL_ONE (PYTHON-901)

  • +
+
+
+
+

3.12.0

+

November 6, 2017

+
+

Features

+
    +
  • Send keyspace in QUERY, PREPARE, and BATCH messages (PYTHON-678)

  • +
  • Add IPv4Address/IPv6Address support for inet types (PYTHON-751)

  • +
  • WriteType.CDC and VIEW missing (PYTHON-794)

  • +
  • Warn on Cluster init if contact points are specified but LBP isn’t (legacy mode) (PYTHON-812)

  • +
  • Warn on Cluster init if contact points are specified but LBP isn’t (exection profile mode) (PYTHON-838)

  • +
  • Include hash of result set metadata in prepared stmt id (PYTHON-808)

  • +
  • Add NO_COMPACT startup option (PYTHON-839)

  • +
  • Add new exception type for CDC (PYTHON-837)

  • +
  • Allow 0ms in ConstantSpeculativeExecutionPolicy (PYTHON-836)

  • +
  • Add asyncio reactor (PYTHON-507)

  • +
+
+
+

Bug Fixes

+
    +
  • Both _set_final_exception/result called for the same ResponseFuture (PYTHON-630)

  • +
  • Use of DCAwareRoundRobinPolicy raises NoHostAvailable exception (PYTHON-781)

  • +
  • Not create two sessions by default in CQLEngine (PYTHON-814)

  • +
  • Bug when subclassing AyncoreConnection (PYTHON-827)

  • +
  • Error at cleanup when closing the asyncore connections (PYTHON-829)

  • +
  • Fix sites where sessions can change during iteration (PYTHON-793)

  • +
  • cqlengine: allow min_length=0 for Ascii and Text column types (PYTHON-735)

  • +
  • Rare exception when “sys.exit(0)” after query timeouts (PYTHON-752)

  • +
  • Dont set the session keyspace when preparing statements (PYTHON-843)

  • +
  • Use of DCAwareRoundRobinPolicy raises NoHostAvailable exception (PYTHON-781)

  • +
+
+
+

Other

+
    +
  • Remove DeprecationWarning when using WhiteListRoundRobinPolicy (PYTHON-810)

  • +
  • Bump Cython dependency version to 0.27 (PYTHON-833)

  • +
+
+
+
+

3.11.0

+

July 24, 2017

+
+

Features

+
    +
  • Add idle_heartbeat_timeout cluster option to tune how long to wait for heartbeat responses. (PYTHON-762)

  • +
  • Add HostFilterPolicy (PYTHON-761)

  • +
+
+
+

Bug Fixes

+
    +
  • is_idempotent flag is not propagated from PreparedStatement to BoundStatement (PYTHON-736)

  • +
  • Fix asyncore hang on exit (PYTHON-767)

  • +
  • Driver takes several minutes to remove a bad host from session (PYTHON-762)

  • +
  • Installation doesn’t always fall back to no cython in Windows (PYTHON-763)

  • +
  • Avoid to replace a connection that is supposed to shutdown (PYTHON-772)

  • +
  • request_ids may not be returned to the pool (PYTHON-739)

  • +
  • Fix murmur3 on big-endian systems (PYTHON-653)

  • +
  • Ensure unused connections are closed if a Session is deleted by the GC (PYTHON-774)

  • +
  • Fix .values_list by using db names internally (cqlengine) (PYTHON-785)

  • +
+
+
+

Other

+
    +
  • Bump Cython dependency version to 0.25.2 (PYTHON-754)

  • +
  • Fix DeprecationWarning when using lz4 (PYTHON-769)

  • +
  • Deprecate WhiteListRoundRobinPolicy (PYTHON-759)

  • +
  • Improve upgrade guide for materializing pages (PYTHON-464)

  • +
  • Documentation for time/date specifies timestamp inupt as microseconds (PYTHON-717)

  • +
  • Point to DSA Slack, not IRC, in docs index

  • +
+
+
+
+

3.10.0

+

May 24, 2017

+
+

Features

+
    +
  • Add Duration type to cqlengine (PYTHON-750)

  • +
  • Community PR review: Raise error on primary key update only if its value changed (PYTHON-705)

  • +
  • get_query_trace() contract is ambiguous (PYTHON-196)

  • +
+
+
+

Bug Fixes

+
    +
  • Queries using speculative execution policy timeout prematurely (PYTHON-755)

  • +
  • Fix map where results are not consumed (PYTHON-749)

  • +
  • Driver fails to encode Duration’s with large values (PYTHON-747)

  • +
  • UDT values are not updated correctly in CQLEngine (PYTHON-743)

  • +
  • UDT types are not validated in CQLEngine (PYTHON-742)

  • +
  • to_python is not implemented for types columns.Type and columns.Date in CQLEngine (PYTHON-741)

  • +
  • Clients spin infinitely trying to connect to a host that is drained (PYTHON-734)

  • +
  • Resulset.get_query_trace returns empty trace sometimes (PYTHON-730)

  • +
  • Memory grows and doesn’t get removed (PYTHON-720)

  • +
  • Fix RuntimeError caused by change dict size during iteration (PYTHON-708)

  • +
  • fix ExponentialReconnectionPolicy may throw OverflowError problem (PYTHON-707)

  • +
  • Avoid using nonexistent prepared statement in ResponseFuture (PYTHON-706)

  • +
+
+
+

Other

+
    +
  • Update README (PYTHON-746)

  • +
  • Test python versions 3.5 and 3.6 (PYTHON-737)

  • +
  • Docs Warning About Prepare select * (PYTHON-626)

  • +
  • Increase Coverage in CqlEngine Test Suite (PYTHON-505)

  • +
  • Example SSL connection code does not verify server certificates (PYTHON-469)

  • +
+
+
+
+

3.9.0

+
+

Features

+
    +
  • cqlengine: remove elements by key from a map (PYTHON-688)

  • +
+
+
+

Bug Fixes

+
    +
  • improve error handling when connecting to non-existent keyspace (PYTHON-665)

  • +
  • Sockets associated with sessions not getting cleaned up on session.shutdown() (PYTHON-673)

  • +
  • rare flake on integration.standard.test_cluster.ClusterTests.test_clone_shared_lbp (PYTHON-727)

  • +
  • MontonicTimestampGenerator.__init__ ignores class defaults (PYTHON-728)

  • +
  • race where callback or errback for request may not be called (PYTHON-733)

  • +
  • cqlengine: model.update() should not update columns with a default value that hasn’t changed (PYTHON-657)

  • +
  • cqlengine: field value manager’s explicit flag is True when queried back from cassandra (PYTHON-719)

  • +
+
+
+

Other

+
    +
  • Connection not closed in example_mapper (PYTHON-723)

  • +
  • Remove mention of pre-2.0 C* versions from OSS 3.0+ docs (PYTHON-710)

  • +
+
+
+
+

3.8.1

+

March 16, 2017

+
+

Bug Fixes

+
    +
  • implement __le__/__ge__/__ne__ on some custom types (PYTHON-714)

  • +
  • Fix bug in eventlet and gevent reactors that could cause hangs (PYTHON-721)

  • +
  • Fix DecimalType regression (PYTHON-724)

  • +
+
+
+
+

3.8.0

+
+

Features

+
    +
  • Quote index names in metadata CQL generation (PYTHON-616)

  • +
  • On column deserialization failure, keep error message consistent between python and cython (PYTHON-631)

  • +
  • TokenAwarePolicy always sends requests to the same replica for a given key (PYTHON-643)

  • +
  • Added cql types to result set (PYTHON-648)

  • +
  • Add __len__ to BatchStatement (PYTHON-650)

  • +
  • Duration Type for Cassandra (PYTHON-655)

  • +
  • Send flags with PREPARE message in v5 (PYTHON-684)

  • +
+
+
+

Bug Fixes

+
    +
  • Potential Timing issue if application exits prior to session pool initialization (PYTHON-636)

  • +
  • “Host X.X.X.X has been marked down” without any exceptions (PYTHON-640)

  • +
  • NoHostAvailable or OperationTimedOut when using execute_concurrent with a generator that inserts into more than one table (PYTHON-642)

  • +
  • ResponseFuture creates Timers and don’t cancel them even when result is received which leads to memory leaks (PYTHON-644)

  • +
  • Driver cannot connect to Cassandra version > 3 (PYTHON-646)

  • +
  • Unable to import model using UserType without setuping connection since 3.7 (PYTHON-649)

  • +
  • Don’t prepare queries on ignored hosts on_up (PYTHON-669)

  • +
  • Sockets associated with sessions not getting cleaned up on session.shutdown() (PYTHON-673)

  • +
  • Make client timestamps strictly monotonic (PYTHON-676)

  • +
  • cassandra.cqlengine.connection.register_connection broken when hosts=None (PYTHON-692)

  • +
+
+
+

Other

+
    +
  • Create a cqlengine doc section explaining None semantics (PYTHON-623)

  • +
  • Resolve warnings in documentation generation (PYTHON-645)

  • +
  • Cython dependency (PYTHON-686)

  • +
  • Drop Support for Python 2.6 (PYTHON-690)

  • +
+
+
+
+

3.7.1

+

October 26, 2016

+
+

Bug Fixes

+
    +
  • Cython upgrade has broken stable version of cassandra-driver (PYTHON-656)

  • +
+
+
+
+

3.7.0

+

September 13, 2016

+
+

Features

+
    +
  • Add v5 protocol failure map (PYTHON-619)

  • +
  • Don’t return from initial connect on first error (PYTHON-617)

  • +
  • Indicate failed column when deserialization fails (PYTHON-361)

  • +
  • Let Cluster.refresh_nodes force a token map rebuild (PYTHON-349)

  • +
  • Refresh UDTs after “keyspace updated” event with v1/v2 protocol (PYTHON-106)

  • +
  • EC2 Address Resolver (PYTHON-198)

  • +
  • Speculative query retries (PYTHON-218)

  • +
  • Expose paging state in API (PYTHON-200)

  • +
  • Don’t mark host down while one connection is active (PYTHON-498)

  • +
  • Query request size information (PYTHON-284)

  • +
  • Avoid quadratic ring processing with invalid replication factors (PYTHON-379)

  • +
  • Improve Connection/Pool creation concurrency on startup (PYTHON-82)

  • +
  • Add beta version native protocol flag (PYTHON-614)

  • +
  • cqlengine: Connections: support of multiple keyspaces and sessions (PYTHON-613)

  • +
+
+
+

Bug Fixes

+
    +
  • Race when adding a pool while setting keyspace (PYTHON-628)

  • +
  • Update results_metadata when prepared statement is reprepared (PYTHON-621)

  • +
  • CQL Export for Thrift Tables (PYTHON-213)

  • +
  • cqlengine: default value not applied to UserDefinedType (PYTHON-606)

  • +
  • cqlengine: columns are no longer hashable (PYTHON-618)

  • +
  • cqlengine: remove clustering keys from where clause when deleting only static columns (PYTHON-608)

  • +
+
+
+
+

3.6.0

+

August 1, 2016

+
+

Features

+
    +
  • Handle null values in NumpyProtocolHandler (PYTHON-553)

  • +
  • Collect greplin scales stats per cluster (PYTHON-561)

  • +
  • Update mock unit test dependency requirement (PYTHON-591)

  • +
  • Handle Missing CompositeType metadata following C* upgrade (PYTHON-562)

  • +
  • Improve Host.is_up state for HostDistance.IGNORED hosts (PYTHON-551)

  • +
  • Utilize v2 protocol’s ability to skip result set metadata for prepared statement execution (PYTHON-71)

  • +
  • Return from Cluster.connect() when first contact point connection(pool) is opened (PYTHON-105)

  • +
  • cqlengine: Add ContextQuery to allow cqlengine models to switch the keyspace context easily (PYTHON-598)

  • +
  • Standardize Validation between Ascii and Text types in Cqlengine (PYTHON-609)

  • +
+
+
+

Bug Fixes

+
    +
  • Fix geventreactor with SSL support (PYTHON-600)

  • +
  • Don’t downgrade protocol version if explicitly set (PYTHON-537)

  • +
  • Nonexistent contact point tries to connect indefinitely (PYTHON-549)

  • +
  • Execute_concurrent can exceed max recursion depth in failure mode (PYTHON-585)

  • +
  • Libev loop shutdown race (PYTHON-578)

  • +
  • Include aliases in DCT type string (PYTHON-579)

  • +
  • cqlengine: Comparison operators for Columns (PYTHON-595)

  • +
  • cqlengine: disentangle default_time_to_live table option from model query default TTL (PYTHON-538)

  • +
  • cqlengine: pk__token column name issue with the equality operator (PYTHON-584)

  • +
  • cqlengine: Fix “__in” filtering operator converts True to string “True” automatically (PYTHON-596)

  • +
  • cqlengine: Avoid LWTExceptions when updating columns that are part of the condition (PYTHON-580)

  • +
  • cqlengine: Cannot execute a query when the filter contains all columns (PYTHON-599)

  • +
  • cqlengine: routing key computation issue when a primary key column is overriden by model inheritance (PYTHON-576)

  • +
+
+
+
+

3.5.0

+

June 27, 2016

+
+

Features

+
    +
  • Optional Execution Profiles for the core driver (PYTHON-569)

  • +
  • API to get the host metadata associated with the control connection node (PYTHON-583)

  • +
  • Expose CDC option in table metadata CQL (PYTHON-593)

  • +
+
+
+

Bug Fixes

+
    +
  • Clean up Asyncore socket map when fork is detected (PYTHON-577)

  • +
  • cqlengine: QuerySet only() is not respected when there are deferred fields (PYTHON-560)

  • +
+
+
+
+

3.4.1

+

May 26, 2016

+
+

Bug Fixes

+
    +
  • Gevent connection closes on IO timeout (PYTHON-573)

  • +
  • “dictionary changed size during iteration” with Python 3 (PYTHON-572)

  • +
+
+
+
+

3.4.0

+

May 24, 2016

+
+

Features

+
    +
  • Include DSE version and workload in Host data (PYTHON-555)

  • +
  • Add a context manager to Cluster and Session (PYTHON-521)

  • +
  • Better Error Message for Unsupported Protocol Version (PYTHON-157)

  • +
  • Make the error message explicitly state when an error comes from the server (PYTHON-412)

  • +
  • Short Circuit meta refresh on topo change if NEW_NODE already exists (PYTHON-557)

  • +
  • Show warning when the wrong config is passed to SimpleStatement (PYTHON-219)

  • +
  • Return namedtuple result pairs from execute_concurrent (PYTHON-362)

  • +
  • BatchStatement should enforce batch size limit in a better way (PYTHON-151)

  • +
  • Validate min/max request thresholds for connection pool scaling (PYTHON-220)

  • +
  • Handle or warn about multiple hosts with the same rpc_address (PYTHON-365)

  • +
  • Write docs around working with datetime and timezones (PYTHON-394)

  • +
+
+
+

Bug Fixes

+
    +
  • High CPU utilization when using asyncore event loop (PYTHON-239)

  • +
  • Fix CQL Export for non-ASCII Identifiers (PYTHON-447)

  • +
  • Make stress scripts Python 2.6 compatible (PYTHON-434)

  • +
  • UnicodeDecodeError when unicode characters in key in BOP (PYTHON-559)

  • +
  • WhiteListRoundRobinPolicy should resolve hosts (PYTHON-565)

  • +
  • Cluster and Session do not GC after leaving scope (PYTHON-135)

  • +
  • Don’t wait for schema agreement on ignored nodes (PYTHON-531)

  • +
  • Reprepare on_up with many clients causes node overload (PYTHON-556)

  • +
  • None inserted into host map when control connection node is decommissioned (PYTHON-548)

  • +
  • weakref.ref does not accept keyword arguments (github #585)

  • +
+
+
+
+

3.3.0

+

May 2, 2016

+
+

Features

+
    +
  • Add an AddressTranslator interface (PYTHON-69)

  • +
  • New Retry Policy Decision - try next host (PYTHON-285)

  • +
  • Don’t mark host down on timeout (PYTHON-286)

  • +
  • SSL hostname verification (PYTHON-296)

  • +
  • Add C* version to metadata or cluster objects (PYTHON-301)

  • +
  • Options to Disable Schema, Token Metadata Processing (PYTHON-327)

  • +
  • Expose listen_address of node we get ring information from (PYTHON-332)

  • +
  • Use A-record with multiple IPs for contact points (PYTHON-415)

  • +
  • Custom consistency level for populating query traces (PYTHON-435)

  • +
  • Normalize Server Exception Types (PYTHON-443)

  • +
  • Propagate exception message when DDL schema agreement fails (PYTHON-444)

  • +
  • Specialized exceptions for metadata refresh methods failure (PYTHON-527)

  • +
+
+
+

Bug Fixes

+
    +
  • Resolve contact point hostnames to avoid duplicate hosts (PYTHON-103)

  • +
  • GeventConnection stalls requests when read is a multiple of the input buffer size (PYTHON-429)

  • +
  • named_tuple_factory breaks with duplicate “cleaned” col names (PYTHON-467)

  • +
  • Connection leak if Cluster.shutdown() happens during reconnection (PYTHON-482)

  • +
  • HostConnection.borrow_connection does not block when all request ids are used (PYTHON-514)

  • +
  • Empty field not being handled by the NumpyProtocolHandler (PYTHON-550)

  • +
+
+
+
+

3.2.2

+

April 19, 2016

+
    +
  • Fix counter save-after-no-update (PYTHON-547)

  • +
+
+
+

3.2.1

+

April 13, 2016

+
    +
  • Introduced an update to allow deserializer compilation with recently released Cython 0.24 (PYTHON-542)

  • +
+
+
+

3.2.0

+

April 12, 2016

+
+

Features

+
    +
  • cqlengine: Warn on sync_schema type mismatch (PYTHON-260)

  • +
  • cqlengine: Automatically defer fields with the ‘=’ operator (and immutable values) in select queries (PYTHON-520)

  • +
  • cqlengine: support non-equal conditions for LWT (PYTHON-528)

  • +
  • cqlengine: sync_table should validate the primary key composition (PYTHON-532)

  • +
  • cqlengine: token-aware routing for mapper statements (PYTHON-535)

  • +
+
+
+

Bug Fixes

+
    +
  • Deleting a column in a lightweight transaction raises a SyntaxException #325 (PYTHON-249)

  • +
  • cqlengine: make Token function works with named tables/columns #86 (PYTHON-272)

  • +
  • comparing models with datetime fields fail #79 (PYTHON-273)

  • +
  • cython date deserializer integer math should be aligned with CPython (PYTHON-480)

  • +
  • db_field is not always respected with UpdateStatement (PYTHON-530)

  • +
  • Sync_table fails on column.Set with secondary index (PYTHON-533)

  • +
+
+
+
+

3.1.1

+

March 14, 2016

+
+

Bug Fixes

+
    +
  • cqlengine: Fix performance issue related to additional “COUNT” queries (PYTHON-522)

  • +
+
+
+
+

3.1.0

+

March 10, 2016

+
+

Features

+
    +
  • Pass name of server auth class to AuthProvider (PYTHON-454)

  • +
  • Surface schema agreed flag for DDL statements (PYTHON-458)

  • +
  • Automatically convert float and int to Decimal on serialization (PYTHON-468)

  • +
  • Eventlet Reactor IO improvement (PYTHON-495)

  • +
  • Make pure Python ProtocolHandler available even when Cython is present (PYTHON-501)

  • +
  • Optional Cython deserializer for bytes as bytearray (PYTHON-503)

  • +
  • Add Session.default_serial_consistency_level (github #510)

  • +
  • cqlengine: Expose prior state information via cqlengine LWTException (github #343, PYTHON-336)

  • +
  • cqlengine: Collection datatype “contains” operators support (Cassandra 2.1) #278 (PYTHON-258)

  • +
  • cqlengine: Add DISTINCT query operator (PYTHON-266)

  • +
  • cqlengine: Tuple cqlengine api (PYTHON-306)

  • +
  • cqlengine: Add support for UPDATE/DELETE … IF EXISTS statements (PYTHON-432)

  • +
  • cqlengine: Allow nested container types (PYTHON-478)

  • +
  • cqlengine: Add ability to set query’s fetch_size and limit (PYTHON-323)

  • +
  • cqlengine: Internalize default keyspace from successive set_session (PYTHON-486)

  • +
  • cqlengine: Warn when Model.create() on Counters (to be deprecated) (PYTHON-333)

  • +
+
+
+

Bug Fixes

+
    +
  • Bus error (alignment issues) when running cython on some ARM platforms (PYTHON-450)

  • +
  • Overflow when decoding large collections (cython) (PYTHON-459)

  • +
  • Timer heap comparison issue with Python 3 (github #466)

  • +
  • Cython deserializer date overflow at 2^31 - 1 (PYTHON-452)

  • +
  • Decode error encountered when cython deserializing large map results (PYTHON-459)

  • +
  • Don’t require Cython for build if compiler or Python header not present (PYTHON-471)

  • +
  • Unorderable types in task scheduling with Python 3 (h(PYTHON-473)

  • +
  • cqlengine: Fix crash when updating a UDT column with a None value (github #467)

  • +
  • cqlengine: Race condition in ..connection.execute with lazy_connect (PYTHON-310)

  • +
  • cqlengine: doesn’t support case sensitive column family names (PYTHON-337)

  • +
  • cqlengine: UserDefinedType mandatory in create or update (PYTHON-344)

  • +
  • cqlengine: db_field breaks UserType (PYTHON-346)

  • +
  • cqlengine: UDT badly quoted (PYTHON-347)

  • +
  • cqlengine: Use of db_field on primary key prevents querying except while tracing. (PYTHON-351)

  • +
  • cqlengine: DateType.deserialize being called with one argument vs two (PYTHON-354)

  • +
  • cqlengine: Querying without setting up connection now throws AttributeError and not CQLEngineException (PYTHON-395)

  • +
  • cqlengine: BatchQuery multiple time executing execute statements. (PYTHON-445)

  • +
  • cqlengine: Better error for management functions when no connection set (PYTHON-451)

  • +
  • cqlengine: Handle None values for UDT attributes in cqlengine (PYTHON-470)

  • +
  • cqlengine: Fix inserting None for model save (PYTHON-475)

  • +
  • cqlengine: EQ doesn’t map to a QueryOperator (setup race condition) (PYTHON-476)

  • +
  • cqlengine: class.MultipleObjectsReturned has DoesNotExist as base class (PYTHON-489)

  • +
  • cqlengine: Typo in cqlengine UserType __len__ breaks attribute assignment (PYTHON-502)

  • +
+
+
+

Other

+
    +
  • cqlengine: a major improvement on queryset has been introduced. It +is a lot more efficient to iterate large datasets: the rows are +now fetched on demand using the driver pagination.

  • +
  • cqlengine: the queryset len() and count() behaviors have changed. It +now executes a “SELECT COUNT(*)” of the query rather than returning +the size of the internal result_cache (loaded rows). On large +queryset, you might want to avoid using them due to the performance +cost. Note that trying to access objects using list index/slicing +with negative indices also requires a count to be +executed.

  • +
+
+
+
+

3.0.0

+

November 24, 2015

+
+

Features

+
    +
  • Support datetime.date objects as a DateType (PYTHON-212)

  • +
  • Add Cluster.update_view_metadata (PYTHON-407)

  • +
  • QueryTrace option to populate partial trace sessions (PYTHON-438)

  • +
  • Attach column names to ResultSet (PYTHON-439)

  • +
  • Change default consistency level to LOCAL_ONE

  • +
+
+
+

Bug Fixes

+
    +
  • Properly SerDes nested collections when protocol_version < 3 (PYTHON-215)

  • +
  • Evict UDTs from UserType cache on change (PYTHON-226)

  • +
  • Make sure query strings are always encoded UTF-8 (PYTHON-334)

  • +
  • Track previous value of columns at instantiation in CQLengine (PYTHON-348)

  • +
  • UDT CQL encoding does not work for unicode values (PYTHON-353)

  • +
  • NetworkTopologyStrategy#make_token_replica_map does not account for multiple racks in a DC (PYTHON-378)

  • +
  • Cython integer overflow on decimal type deserialization (PYTHON-433)

  • +
  • Query trace: if session hasn’t been logged, query trace can throw exception (PYTHON-442)

  • +
+
+
+
+

3.0.0rc1

+

November 9, 2015

+
+

Features

+
    +
  • Process Modernized Schema Tables for Cassandra 3.0 (PYTHON-276, PYTHON-408, PYTHON-400, PYTHON-422)

  • +
  • Remove deprecated features (PYTHON-292)

  • +
  • Don’t assign trace data to Statements (PYTHON-318)

  • +
  • Normalize results return (PYTHON-368)

  • +
  • Process Materialized View Metadata/Events (PYTHON-371)

  • +
  • Remove blist as soft dependency (PYTHON-385)

  • +
  • Change default consistency level to LOCAL_QUORUM (PYTHON-416)

  • +
  • Normalize CQL query/export in metadata model (PYTHON-405)

  • +
+
+
+

Bug Fixes

+
    +
  • Implementation of named arguments bind is non-pythonic (PYTHON-178)

  • +
  • CQL encoding is incorrect for NaN and Infinity floats (PYTHON-282)

  • +
  • Protocol downgrade issue with C* 2.0.x, 2.1.x, and python3, with non-default logging (PYTHON-409)

  • +
  • ValueError when accessing usertype with non-alphanumeric field names (PYTHON-413)

  • +
  • NumpyProtocolHandler does not play well with PagedResult (PYTHON-430)

  • +
+
+
+
+

2.7.2

+

September 14, 2015

+
+

Bug Fixes

+
    +
  • Resolve CQL export error for UDF with zero parameters (PYTHON-392)

  • +
  • Remove futures dep. for Python 3 (PYTHON-393)

  • +
  • Avoid Python closure in cdef (supports earlier Cython compiler) (PYTHON-396)

  • +
  • Unit test runtime issues (PYTHON-397,398)

  • +
+
+
+
+

2.7.1

+

August 25, 2015

+
+

Bug Fixes

+
    +
  • Explicitly include extension source files in Manifest

  • +
+
+
+
+

2.7.0

+

August 25, 2015

+

Cython is introduced, providing compiled extensions for core modules, and +extensions for optimized results deserialization.

+
+

Features

+
    +
  • General Performance Improvements for Throughput (PYTHON-283)

  • +
  • Improve synchronous request performance with Timers (PYTHON-108)

  • +
  • Enable C Extensions for PyPy Runtime (PYTHON-357)

  • +
  • Refactor SerDes functionality for pluggable interface (PYTHON-313)

  • +
  • Cython SerDes Extension (PYTHON-377)

  • +
  • Accept iterators/generators for execute_concurrent() (PYTHON-123)

  • +
  • cythonize existing modules (PYTHON-342)

  • +
  • Pure Python murmur3 implementation (PYTHON-363)

  • +
  • Make driver tolerant of inconsistent metadata (PYTHON-370)

  • +
+
+
+

Bug Fixes

+
    +
  • Drop Events out-of-order Cause KeyError on Processing (PYTHON-358)

  • +
  • DowngradingConsistencyRetryPolicy doesn’t check response count on write timeouts (PYTHON-338)

  • +
  • Blocking connect does not use connect_timeout (PYTHON-381)

  • +
  • Properly protect partition key in CQL export (PYTHON-375)

  • +
  • Trigger error callbacks on timeout (PYTHON-294)

  • +
+
+
+
+

2.6.0

+

July 20, 2015

+
+

Bug Fixes

+
    +
  • Output proper CQL for compact tables with no clustering columns (PYTHON-360)

  • +
+
+
+
+

2.6.0c2

+

June 24, 2015

+
+

Features

+
    +
  • Automatic Protocol Version Downgrade (PYTHON-240)

  • +
  • cqlengine Python 2.6 compatibility (PYTHON-288)

  • +
  • Double-dollar string quote UDF body (PYTHON-345)

  • +
  • Set models.DEFAULT_KEYSPACE when calling set_session (github #352)

  • +
+
+
+

Bug Fixes

+
    +
  • Avoid stall while connecting to mixed version cluster (PYTHON-303)

  • +
  • Make SSL work with AsyncoreConnection in python 2.6.9 (PYTHON-322)

  • +
  • Fix Murmur3Token.from_key() on Windows (PYTHON-331)

  • +
  • Fix cqlengine TimeUUID rounding error for Windows (PYTHON-341)

  • +
  • Avoid invalid compaction options in CQL export for non-SizeTiered (PYTHON-352)

  • +
+
+
+
+

2.6.0c1

+

June 4, 2015

+

This release adds support for Cassandra 2.2 features, including version +4 of the native protocol.

+
+

Features

+
    +
  • Default load balancing policy to TokenAware(DCAware) (PYTHON-160)

  • +
  • Configuration option for connection timeout (PYTHON-206)

  • +
  • Support User Defined Function and Aggregate metadata in C* 2.2 (PYTHON-211)

  • +
  • Surface request client in QueryTrace for C* 2.2+ (PYTHON-235)

  • +
  • Implement new request failure messages in protocol v4+ (PYTHON-238)

  • +
  • Metadata model now maps index meta by index name (PYTHON-241)

  • +
  • Support new types in C* 2.2: date, time, smallint, tinyint (PYTHON-245, 295)

  • +
  • cqle: add Double column type and remove Float overload (PYTHON-246)

  • +
  • Use partition key column information in prepared response for protocol v4+ (PYTHON-277)

  • +
  • Support message custom payloads in protocol v4+ (PYTHON-280, PYTHON-329)

  • +
  • Deprecate refresh_schema and replace with functions for specific entities (PYTHON-291)

  • +
  • Save trace id even when trace complete times out (PYTHON-302)

  • +
  • Warn when registering client UDT class for protocol < v3 (PYTHON-305)

  • +
  • Support client warnings returned with messages in protocol v4+ (PYTHON-315)

  • +
  • Ability to distinguish between NULL and UNSET values in protocol v4+ (PYTHON-317)

  • +
  • Expose CQL keywords in API (PYTHON-324)

  • +
+
+
+

Bug Fixes

+
    +
  • IPv6 address support on Windows (PYTHON-20)

  • +
  • Convert exceptions during automatic re-preparation to nice exceptions (PYTHON-207)

  • +
  • cqle: Quote keywords properly in table management functions (PYTHON-244)

  • +
  • Don’t default to GeventConnection when gevent is loaded, but not monkey-patched (PYTHON-289)

  • +
  • Pass dynamic host from SaslAuthProvider to SaslAuthenticator (PYTHON-300)

  • +
  • Make protocol read_inet work for Windows (PYTHON-309)

  • +
  • cqle: Correct encoding for nested types (PYTHON-311)

  • +
  • Update list of CQL keywords used quoting identifiers (PYTHON-319)

  • +
  • Make ConstantReconnectionPolicy work with infinite retries (github #327, PYTHON-325)

  • +
  • Accept UUIDs with uppercase hex as valid in cqlengine (github #335)

  • +
+
+
+
+

2.5.1

+

April 23, 2015

+
+

Bug Fixes

+
    +
  • Fix thread safety in DC-aware load balancing policy (PYTHON-297)

  • +
  • Fix race condition in node/token rebuild (PYTHON-298)

  • +
  • Set and send serial consistency parameter (PYTHON-299)

  • +
+
+
+
+

2.5.0

+

March 30, 2015

+
+

Features

+
    +
  • Integrated cqlengine object mapping package

  • +
  • Utility functions for converting timeuuids and datetime (PYTHON-99)

  • +
  • Schema metadata fetch window randomized, config options added (PYTHON-202)

  • +
  • Support for new Date and Time Cassandra types (PYTHON-190)

  • +
+
+
+

Bug Fixes

+
    +
  • Fix index target for collection indexes (full(), keys()) (PYTHON-222)

  • +
  • Thread exception during GIL cleanup (PYTHON-229)

  • +
  • Workaround for rounding anomaly in datetime.utcfromtime (Python 3.4) (PYTHON-230)

  • +
  • Normalize text serialization for lookup in OrderedMap (PYTHON-231)

  • +
  • Support reading CompositeType data (PYTHON-234)

  • +
  • Preserve float precision in CQL encoding (PYTHON-243)

  • +
+
+
+
+

2.1.4

+

January 26, 2015

+
+

Features

+
    +
  • SaslAuthenticator for Kerberos support (PYTHON-109)

  • +
  • Heartbeat for network device keepalive and detecting failures on idle connections (PYTHON-197)

  • +
  • Support nested, frozen collections for Cassandra 2.1.3+ (PYTHON-186)

  • +
  • Schema agreement wait bypass config, new call for synchronous schema refresh (PYTHON-205)

  • +
  • Add eventlet connection support (PYTHON-194)

  • +
+
+
+

Bug Fixes

+
    +
  • Schema meta fix for complex thrift tables (PYTHON-191)

  • +
  • Support for ‘unknown’ replica placement strategies in schema meta (PYTHON-192)

  • +
  • Resolve stream ID leak on set_keyspace (PYTHON-195)

  • +
  • Remove implicit timestamp scaling on serialization of numeric timestamps (PYTHON-204)

  • +
  • Resolve stream id collision when using SASL auth (PYTHON-210)

  • +
  • Correct unhexlify usage for user defined type meta in Python3 (PYTHON-208)

  • +
+
+
+
+

2.1.3

+

December 16, 2014

+
+

Features

+
    +
  • INFO-level log confirmation that a connection was opened to a node that was marked up (PYTHON-116)

  • +
  • Avoid connecting to peer with incomplete metadata (PYTHON-163)

  • +
  • Add SSL support to gevent reactor (PYTHON-174)

  • +
  • Use control connection timeout in wait for schema agreement (PYTHON-175)

  • +
  • Better consistency level representation in unavailable+timeout exceptions (PYTHON-180)

  • +
  • Update schema metadata processing to accommodate coming schema modernization (PYTHON-185)

  • +
+
+
+

Bug Fixes

+
    +
  • Support large negative timestamps on Windows (PYTHON-119)

  • +
  • Fix schema agreement for clusters with peer rpc_addres 0.0.0.0 (PYTHON-166)

  • +
  • Retain table metadata following keyspace meta refresh (PYTHON-173)

  • +
  • Use a timeout when preparing a statement for all nodes (PYTHON-179)

  • +
  • Make TokenAware routing tolerant of statements with no keyspace (PYTHON-181)

  • +
  • Update add_collback to store/invoke multiple callbacks (PYTHON-182)

  • +
  • Correct routing key encoding for composite keys (PYTHON-184)

  • +
  • Include compression option in schema export string when disabled (PYTHON-187)

  • +
+
+
+
+

2.1.2

+

October 16, 2014

+
+

Features

+
    +
  • Allow DCAwareRoundRobinPolicy to be constructed without a local_dc, defaulting +instead to the DC of a contact_point (PYTHON-126)

  • +
  • Set routing key in BatchStatement.add() if none specified in batch (PYTHON-148)

  • +
  • Improved feedback on ValueError using named_tuple_factory with invalid column names (PYTHON-122)

  • +
+
+
+

Bug Fixes

+
    +
  • Make execute_concurrent compatible with Python 2.6 (PYTHON-159)

  • +
  • Handle Unauthorized message on schema_triggers query (PYTHON-155)

  • +
  • Pure Python sorted set in support of UDTs nested in collections (PYTON-167)

  • +
  • Support CUSTOM index metadata and string export (PYTHON-165)

  • +
+
+
+
+

2.1.1

+

September 11, 2014

+
+

Features

+
    +
  • Detect triggers and include them in CQL queries generated to recreate +the schema (github-189)

  • +
  • Support IPv6 addresses (PYTHON-144) (note: basic functionality added; Windows +platform not addressed (PYTHON-20))

  • +
+
+
+

Bug Fixes

+
    +
  • Fix NetworkTopologyStrategy.export_for_schema (PYTHON-120)

  • +
  • Keep timeout for paged results (PYTHON-150)

  • +
+
+
+

Other

+
    +
  • Add frozen<> type modifier to UDTs and tuples to handle CASSANDRA-7857

  • +
+
+
+
+

2.1.0

+

August 7, 2014

+
+

Bug Fixes

+
    +
  • Correctly serialize and deserialize null values in tuples and +user-defined types (PYTHON-110)

  • +
  • Include additional header and lib dirs, allowing libevwrapper to build +against Homebrew and Mac Ports installs of libev (PYTHON-112 and 804dea3)

  • +
+
+
+
+

2.1.0c1

+

July 25, 2014

+
+

Bug Fixes

+
    +
  • Properly specify UDTs for columns in CREATE TABLE statements

  • +
  • Avoid moving retries to a new host when using request ID zero (PYTHON-88)

  • +
  • Don’t ignore fetch_size arguments to Statement constructors (github-151)

  • +
  • Allow disabling automatic paging on a per-statement basis when it’s +enabled by default for the session (PYTHON-93)

  • +
  • Raise ValueError when tuple query parameters for prepared statements +have extra items (PYTHON-98)

  • +
  • Correctly encode nested tuples and UDTs for non-prepared statements (PYTHON-100)

  • +
  • Raise TypeError when a string is used for contact_points (github #164)

  • +
  • Include User Defined Types in KeyspaceMetadata.export_as_string() (PYTHON-96)

  • +
+
+
+

Other

+
    +
  • Return list collection columns as python lists instead of tuples +now that tuples are a specific Cassandra type

  • +
+
+
+
+

2.1.0b1

+

July 11, 2014

+

This release adds support for Cassandra 2.1 features, including version +3 of the native protocol.

+
+

Features

+
    +
  • When using the v3 protocol, only one connection is opened per-host, and +throughput is improved due to reduced pooling overhead and lock contention.

  • +
  • Support for user-defined types (Cassandra 2.1+)

  • +
  • Support for tuple type in (limited usage Cassandra 2.0.9, full usage +in Cassandra 2.1)

  • +
  • Protocol-level client-side timestamps (see Session.use_client_timestamp)

  • +
  • Overridable type encoding for non-prepared statements (see Session.encoders)

  • +
  • Configurable serial consistency levels for batch statements

  • +
  • Use io.BytesIO for reduced CPU consumption (github #143)

  • +
  • Support Twisted as a reactor. Note that a Twisted-compatible +API is not exposed (so no Deferreds), this is just a reactor +implementation. (github #135, PYTHON-8)

  • +
+
+
+

Bug Fixes

+
    +
  • Fix references to xrange that do not go through “six” in libevreactor and +geventreactor (github #138)

  • +
  • Make BoundStatements inherit fetch_size from their parent +PreparedStatement (PYTHON-80)

  • +
  • Clear reactor state in child process after forking to prevent errors with +multiprocessing when the parent process has connected a Cluster before +forking (github #141)

  • +
  • Don’t share prepared statement lock across Cluster instances

  • +
  • Format CompositeType and DynamicCompositeType columns correctly in +CREATE TABLE statements.

  • +
  • Fix cassandra.concurrent behavior when dealing with automatic paging +(PYTHON-81)

  • +
  • Properly defunct connections after protocol errors

  • +
  • Avoid UnicodeDecodeError when query string is unicode (PYTHON-76)

  • +
  • Correctly capture dclocal_read_repair_chance for tables and +use it when generating CREATE TABLE statements (PYTHON-84)

  • +
  • Avoid race condition with AsyncoreConnection that may cause messages +to fail to be written until a new message is pushed

  • +
  • Make sure cluster.metadata.partitioner and cluster.metadata.token_map +are populated when all nodes in the cluster are included in the +contact points (PYTHON-90)

  • +
  • Make Murmur3 hash match Cassandra’s hash for all values (PYTHON-89, +github #147)

  • +
  • Don’t attempt to reconnect to hosts that should be ignored (according +to the load balancing policy) when a notification is received that the +host is down.

  • +
  • Add CAS WriteType, avoiding KeyError on CAS write timeout (PYTHON-91)

  • +
+
+
+
+

2.0.2

+

June 10, 2014

+
+

Bug Fixes

+
    +
  • Add six to requirements.txt

  • +
  • Avoid KeyError during schema refresh when a keyspace is dropped +and TokenAwarePolicy is not in use

  • +
  • Avoid registering multiple atexit cleanup functions when the +asyncore event loop is restarted multiple times

  • +
  • Delay initialization of reactors in order to avoid problems +with shared state when using multiprocessing (PYTHON-60)

  • +
  • Add python-six to debian dependencies, move python-blist to recommends

  • +
  • Fix memory leak when libev connections are created and +destroyed (github #93)

  • +
  • Ensure token map is rebuilt when hosts are removed from the cluster

  • +
+
+
+
+

2.0.1

+

May 28, 2014

+
+

Bug Fixes

+
    +
  • Fix check for Cluster.is_shutdown in in @run_in_executor +decorator

  • +
+
+
+
+

2.0.0

+

May 28, 2014

+
+

Features

+
    +
  • Make libev C extension Python3-compatible (PYTHON-70)

  • +
  • Support v2 protocol authentication (PYTHON-73, github #125)

  • +
+
+
+

Bug Fixes

+
    +
  • Fix murmur3 C extension compilation under Python3.4 (github #124)

  • +
+
+
+

Merged From 1.x

+
+

Features

+
    +
  • Add Session.default_consistency_level (PYTHON-14)

  • +
+
+
+

Bug Fixes

+
    +
  • Don’t strip trailing underscores from column names when using the +named_tuple_factory (PYTHON-56)

  • +
  • Ensure replication factors are ints for NetworkTopologyStrategy +to avoid TypeErrors (github #120)

  • +
  • Pass WriteType instance to RetryPolicy.on_write_timeout() instead +of the string name of the write type. This caused write timeout +errors to always be rethrown instead of retrying. (github #123)

  • +
  • Avoid submitting tasks to the ThreadPoolExecutor after shutdown. With +retries enabled, this could cause Cluster.shutdown() to hang under +some circumstances.

  • +
  • Fix unintended rebuild of token replica map when keyspaces are +discovered (on startup), added, or updated and TokenAwarePolicy is not +in use.

  • +
  • Avoid rebuilding token metadata when cluster topology has not +actually changed

  • +
  • Avoid preparing queries for hosts that should be ignored (such as +remote hosts when using the DCAwareRoundRobinPolicy) (PYTHON-75)

  • +
+
+
+

Other

+
    +
  • Add 1 second timeout to join() call on event loop thread during +interpreter shutdown. This can help to prevent the process from +hanging during shutdown.

  • +
+
+
+
+
+

2.0.0b1

+

May 6, 2014

+
+

Upgrading from 1.x

+

Cluster.shutdown() should always be called when you are done with a +Cluster instance. If it is not called, there are no guarantees that the +driver will not hang. However, if you do have a reproduceable case +where Cluster.shutdown() is not called and the driver hangs, please +report it so that we can attempt to fix it.

+

If you’re using the 2.0 driver against Cassandra 1.2, you will need +to set your protocol version to 1. For example:

+
+

cluster = Cluster(…, protocol_version=1)

+
+
+
+

Features

+
    +
  • Support v2 of Cassandra’s native protocol, which includes the following +new features: automatic query paging support, protocol-level batch statements, +and lightweight transactions

  • +
  • Support for Python 3.3 and 3.4

  • +
  • Allow a default query timeout to be set per-Session

  • +
+
+
+

Bug Fixes

+
    +
  • Avoid errors during interpreter shutdown (the driver attempts to cleanup +daemonized worker threads before interpreter shutdown)

  • +
+
+
+

Deprecations

+

The following functions have moved from cassandra.decoder to cassandra.query. +The original functions have been left in place with a DeprecationWarning for +now:

+
    +
  • cassandra.decoder.tuple_factory has moved to cassandra.query.tuple_factory

  • +
  • cassandra.decoder.named_tuple_factory has moved to cassandra.query.named_tuple_factory

  • +
  • cassandra.decoder.dict_factory has moved to cassandra.query.dict_factory

  • +
  • cassandra.decoder.ordered_dict_factory has moved to cassandra.query.ordered_dict_factory

  • +
+

Exceptions that were in cassandra.decoder have been moved to cassandra.protocol. If +you handle any of these exceptions, you must adjust the code accordingly.

+
+
+
+

1.1.2

+

May 8, 2014

+
+

Features

+
    +
  • Allow a specific compression type to be requested for communications with +Cassandra and prefer lz4 if available

  • +
+
+
+

Bug Fixes

+
    +
  • Update token metadata (for TokenAware calculations) when a node is removed +from the ring

  • +
  • Fix file handle leak with gevent reactor due to blocking Greenlet kills when +closing excess connections

  • +
  • Avoid handling a node coming up multiple times due to a reconnection attempt +succeeding close to the same time that an UP notification is pushed

  • +
  • Fix duplicate node-up handling, which could result in multiple reconnectors +being started as well as the executor threads becoming deadlocked, preventing +future node up or node down handling from being executed.

  • +
  • Handle exhausted ReconnectionPolicy schedule correctly

  • +
+
+
+

Other

+
    +
  • Don’t log at ERROR when a connection is closed during the startup +communications

  • +
  • Mke scales, blist optional dependencies

  • +
+
+
+
+

1.1.1

+

April 16, 2014

+
+

Bug Fixes

+
    +
  • Fix unconditional import of nose in setup.py (github #111)

  • +
+
+
+
+

1.1.0

+

April 16, 2014

+
+

Features

+
    +
  • Gevent is now supported through monkey-patching the stdlib (PYTHON-7, +github issue #46)

  • +
  • Support static columns in schemas, which are available starting in +Cassandra 2.1. (github issue #91)

  • +
  • Add debian packaging (github issue #101)

  • +
  • Add utility methods for easy concurrent execution of statements. See +the new cassandra.concurrent module. (github issue #7)

  • +
+
+
+

Bug Fixes

+
    +
  • Correctly supply compaction and compression parameters in CREATE statements +for tables when working with Cassandra 2.0+

  • +
  • Lowercase boolean literals when generating schemas

  • +
  • Ignore SSL_ERROR_WANT_READ and SSL_ERROR_WANT_WRITE socket errors. Previously, +these resulted in the connection being defuncted, but they can safely be +ignored by the driver.

  • +
  • Don’t reconnect the control connection every time Cluster.connect() is +called

  • +
  • Avoid race condition that could leave ResponseFuture callbacks uncalled +if the callback was added outside of the event loop thread (github issue #95)

  • +
  • Properly escape keyspace name in Session.set_keyspace(). Previously, the +keyspace name was quoted, but any quotes in the string were not escaped.

  • +
  • Avoid adding hosts to the load balancing policy before their datacenter +and rack information has been set, if possible.

  • +
  • Avoid KeyError when updating metadata after droping a table (github issues +#97, #98)

  • +
  • Use tuples instead of sets for DCAwareLoadBalancingPolicy to ensure equal +distribution of requests

  • +
+
+
+

Other

+
    +
  • Don’t ignore column names when parsing typestrings. This is needed for +user-defined type support. (github issue #90)

  • +
  • Better error message when libevwrapper is not found

  • +
  • Only try to import scales when metrics are enabled (github issue #92)

  • +
  • Cut down on the number of queries executing when a new Cluster +connects and when the control connection has to reconnect (github issue #104, +PYTHON-59)

  • +
  • Issue warning log when schema versions do not match

  • +
+
+
+
+

1.0.2

+

March 4, 2014

+
+

Bug Fixes

+
    +
  • With asyncorereactor, correctly handle EAGAIN/EWOULDBLOCK when the message from +Cassandra is a multiple of the read buffer size. Previously, if no more data +became available to read on the socket, the message would never be processed, +resulting in an OperationTimedOut error.

  • +
  • Double quote keyspace, table and column names that require them (those using +uppercase characters or keywords) when generating CREATE statements through +KeyspaceMetadata and TableMetadata.

  • +
  • Decode TimestampType as DateType. (Cassandra replaced DateType with +TimestampType to fix sorting of pre-unix epoch dates in CASSANDRA-5723.)

  • +
  • Handle latest table options when parsing the schema and generating +CREATE statements.

  • +
  • Avoid ‘Set changed size during iteration’ during query plan generation +when hosts go up or down

  • +
+
+
+

Other

+
    +
  • Remove ignored tracing_enabled parameter for SimpleStatement. The +correct way to trace a query is by setting the trace argument to True +in Session.execute() and Session.execute_async().

  • +
  • Raise TypeError instead of cassandra.query.InvalidParameterTypeError when +a parameter for a prepared statement has the wrong type; remove +cassandra.query.InvalidParameterTypeError.

  • +
  • More consistent type checking for query parameters

  • +
  • Add option to a return special object for empty string values for non-string +columns

  • +
+
+
+
+

1.0.1

+

Feb 19, 2014

+
+

Bug Fixes

+
    +
  • Include table indexes in KeyspaceMetadata.export_as_string()

  • +
  • Fix broken token awareness on ByteOrderedPartitioner

  • +
  • Always close socket when defuncting error’ed connections to avoid a potential +file descriptor leak

  • +
  • Handle “custom” types (such as the replaced DateType) correctly

  • +
  • With libevreactor, correctly handle EAGAIN/EWOULDBLOCK when the message from +Cassandra is a multiple of the read buffer size. Previously, if no more data +became available to read on the socket, the message would never be processed, +resulting in an OperationTimedOut error.

  • +
  • Don’t break tracing when a Session’s row_factory is not the default +namedtuple_factory.

  • +
  • Handle data that is already utf8-encoded for UTF8Type values

  • +
  • Fix token-aware routing for tokens that fall before the first node token in +the ring and tokens that exactly match a node’s token

  • +
  • Tolerate null source_elapsed values for Trace events. These may not be +set when events complete after the main operation has already completed.

  • +
+
+
+

Other

+
    +
  • Skip sending OPTIONS message on connection creation if compression is +disabled or not available and a CQL version has not been explicitly +set

  • +
  • Add details about errors and the last queried host to OperationTimedOut

  • +
+
+
+
+

1.0.0 Final

+

Jan 29, 2014

+
+

Bug Fixes

+
    +
  • Prevent leak of Scheduler thread (even with proper shutdown)

  • +
  • Correctly handle ignored hosts, which are common with the +DCAwareRoundRobinPolicy

  • +
  • Hold strong reference to prepared statement while executing it to avoid +garbage collection

  • +
  • Add NullHandler logging handler to the cassandra package to avoid +warnings about there being no configured logger

  • +
  • Fix bad handling of nodes that have been removed from the cluster

  • +
  • Properly escape string types within cql collections

  • +
  • Handle setting the same keyspace twice in a row

  • +
  • Avoid race condition during schema agreement checks that could result +in schema update queries returning before all nodes had seen the change

  • +
  • Preserve millisecond-level precision in datetimes when performing inserts +with simple (non-prepared) statements

  • +
  • Properly defunct connections when libev reports an error by setting +errno instead of simply logging the error

  • +
  • Fix endless hanging of some requests when using the libev reactor

  • +
  • Always start a reconnection process when we fail to connect to +a newly bootstrapped node

  • +
  • Generators map to CQL lists, not key sequences

  • +
  • Always defunct connections when an internal operation fails

  • +
  • Correctly break from handle_write() if nothing was sent (asyncore +reactor only)

  • +
  • Avoid potential double-erroring of callbacks when a connection +becomes defunct

  • +
+
+
+

Features

+
    +
  • Add default query timeout to Session

  • +
  • Add timeout parameter to Session.execute()

  • +
  • Add WhiteListRoundRobinPolicy as a load balancing policy option

  • +
  • Support for consistency level LOCAL_ONE

  • +
  • Make the backoff for fetching traces exponentially increasing and +configurable

  • +
+
+
+

Other

+
    +
  • Raise Exception if TokenAwarePolicy is used against a cluster using the +Murmur3Partitioner if the murmur3 C extension has not been compiled

  • +
  • Add encoder mapping for OrderedDict

  • +
  • Use timeouts on all control connection queries

  • +
  • Benchmark improvements, including command line options and eay +multithreading support

  • +
  • Reduced lock contention when using the asyncore reactor

  • +
  • Warn when non-datetimes are used for ‘timestamp’ column values in +prepared statements

  • +
  • Add requirements.txt and test-requirements.txt

  • +
  • TravisCI integration for running unit tests against Python 2.6, +Python 2.7, and PyPy

  • +
+
+
+
+

1.0.0b7

+

Nov 12, 2013

+

This release makes many stability improvements, especially around +prepared statements and node failure handling. In particular, +several cases where a request would never be completed (and as a +result, leave the application hanging) have been resolved.

+
+

Features

+
    +
  • Add timeout kwarg to ResponseFuture.result()

  • +
  • Create connection pools to all hosts in parallel when initializing +new Sesssions.

  • +
+
+
+

Bug Fixes

+
    +
  • Properly set exception on ResponseFuture when a query fails +against all hosts

  • +
  • Improved cleanup and reconnection efforts when reconnection fails +on a node that has recently come up

  • +
  • Use correct consistency level when retrying failed operations +against a different host. (An invalid consistency level was being +used, causing the retry to fail.)

  • +
  • Better error messages for failed Session.prepare() opertaions

  • +
  • Prepare new statements against all hosts in parallel (formerly +sequential)

  • +
  • Fix failure to save the new current keyspace on connections. (This +could cause problems for prepared statements and lead to extra +operations to continuously re-set the keyspace.)

  • +
  • Avoid sharing LoadBalancingPolicies across Cluster instances. (When +a second Cluster was connected, it effectively mark nodes down for the +first Cluster.)

  • +
  • Better handling of failures during the re-preparation sequence for +unrecognized prepared statements

  • +
  • Throttle trashing of underutilized connections to avoid trashing newly +created connections

  • +
  • Fix race condition which could result in trashed connections being closed +before the last operations had completed

  • +
  • Avoid preparing statements on the event loop thread (which could lead to +deadlock)

  • +
  • Correctly mark up non-contact point nodes discovered by the control +connection. (This lead to prepared statements not being prepared +against those hosts, generating extra traffic later when the +statements were executed and unrecognized.)

  • +
  • Correctly handle large messages through libev

  • +
  • Add timeout to schema agreement check queries

  • +
  • More complete (and less contended) locking around manipulation of the +pending message deque for libev connections

  • +
+
+
+

Other

+
    +
  • Prepare statements in batches of 10. (When many prepared statements +are in use, this allows the driver to start utilizing nodes that +were restarted more quickly.)

  • +
  • Better debug logging around connection management

  • +
  • Don’t retain unreferenced prepared statements in the local cache. +(If many different prepared statements were created, this would +increase memory usage and greatly increase the amount of time +required to begin utilizing a node that was added or marked +up.)

  • +
+
+
+
+

1.0.0b6

+

Oct 22, 2013

+
+

Bug Fixes

+
    +
  • Use lazy string formatting when logging

  • +
  • Avoid several deadlock scenarios, especially when nodes go down

  • +
  • Avoid trashing newly created connections due to insufficient traffic

  • +
  • Gracefully handle un-handled Exceptions when erroring callbacks

  • +
+
+
+

Other

+
    +
  • Node state listeners (which are called when a node is added, removed, +goes down, or comes up) should now be registered through +Cluster.register_listener() instead of through a host’s HealthMonitor +(which has been removed)

  • +
+
+
+
+

1.0.0b5

+

Oct 10, 2013

+
+

Features

+
    +
  • SSL support

  • +
+
+
+

Bug Fixes

+
    +
  • Avoid KeyError when building replica map for NetworkTopologyStrategy

  • +
  • Work around python bug which causes deadlock when a thread imports +the utf8 module

  • +
  • Handle no blist library, which is not compatible with pypy

  • +
  • Avoid deadlock triggered by a keyspace being set on a connection (which +may happen automatically for new connections)

  • +
+
+
+

Other

+
    +
  • Switch packaging from Distribute to setuptools, improved C extension +support

  • +
  • Use PEP 386 compliant beta and post-release versions

  • +
+
+
+
+

1.0.0-beta4

+

Sep 24, 2013

+
+

Features

+
    +
  • Handle new blob syntax in Cassandra 2.0 by accepting bytearray +objects for blob values

  • +
  • Add cql_version kwarg to Cluster.__init__

  • +
+
+
+

Bug Fixes

+
    +
  • Fix KeyError when building token map with NetworkTopologyStrategy +keyspaces (this prevented a Cluster from successfully connecting +at all).

  • +
  • Don’t lose default consitency level from parent PreparedStatement +when creating BoundStatements

  • +
+
+
+
+

1.0.0-beta3

+

Sep 20, 2013

+
+

Features

+
    +
  • Support for LZ4 compression (Cassandra 2.0+)

  • +
  • Token-aware routing will now utilize all replicas for a query instead +of just the first replica

  • +
+
+
+

Bug Fixes

+
    +
  • Fix libev include path for CentOS

  • +
  • Fix varint packing of the value 0

  • +
  • Correctly pack unicode values

  • +
  • Don’t attempt to return failed connections to the pool when a final result +is set

  • +
  • Fix bad iteration of connection credentials

  • +
  • Use blist’s orderedset for set collections and OrderedDict for map +collections so that Cassandra’s ordering is preserved

  • +
  • Fix connection failure on Windows due to unavailability of inet_pton +and inet_ntop. (Note that IPv6 inet_address values are still not +supported on Windows.)

  • +
  • Boolean constants shouldn’t be surrounded by single quotes

  • +
  • Avoid a potential loss of precision on float constants due to string +formatting

  • +
  • Actually utilize non-standard ports set on Cluster objects

  • +
  • Fix export of schema as a set of CQL queries

  • +
+
+
+

Other

+
    +
  • Use cStringIO for connection buffer for better performance

  • +
  • Add __repr__ method for Statement classes

  • +
  • Raise InvalidTypeParameterError when parameters of the wrong +type are used with statements

  • +
  • Make all tests compatible with Python 2.6

  • +
  • Add 1s timeout for opening new connections

  • +
+
+
+
+

1.0.0-beta2

+

Aug 19, 2013

+
+

Bug Fixes

+
    +
  • Fix pip packaging

  • +
+
+
+
+

1.0.0-beta

+

Aug 16, 2013

+

Initial release

+
+
+ + +
+ + + + + +
+ + +
+
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.26.2-scylla/CNAME b/3.26.2-scylla/CNAME new file mode 100644 index 0000000000..9f3e01a070 --- /dev/null +++ b/3.26.2-scylla/CNAME @@ -0,0 +1 @@ +python-driver.docs.scylladb.com \ No newline at end of file diff --git a/3.26.2-scylla/_sources/CHANGELOG.rst.txt b/3.26.2-scylla/_sources/CHANGELOG.rst.txt new file mode 100644 index 0000000000..f6d642b27f --- /dev/null +++ b/3.26.2-scylla/_sources/CHANGELOG.rst.txt @@ -0,0 +1,7 @@ +:orphan: + +********* +CHANGELOG +********* + +.. include:: ../CHANGELOG.rst diff --git a/3.26.2-scylla/_sources/api/cassandra.rst.txt b/3.26.2-scylla/_sources/api/cassandra.rst.txt new file mode 100644 index 0000000000..d46aae56cb --- /dev/null +++ b/3.26.2-scylla/_sources/api/cassandra.rst.txt @@ -0,0 +1,77 @@ +:mod:`cassandra` - Exceptions and Enums +======================================= + +.. module:: cassandra + +.. data:: __version_info__ + + The version of the driver in a tuple format + +.. data:: __version__ + + The version of the driver in a string format + +.. autoclass:: ConsistencyLevel + :members: + +.. autoclass:: ProtocolVersion + :members: + +.. autoclass:: UserFunctionDescriptor + :members: + :inherited-members: + +.. autoclass:: UserAggregateDescriptor + :members: + :inherited-members: + +.. autoexception:: DriverException() + :members: + +.. autoexception:: RequestExecutionException() + :members: + +.. autoexception:: Unavailable() + :members: + +.. autoexception:: Timeout() + :members: + +.. autoexception:: ReadTimeout() + :members: + +.. autoexception:: WriteTimeout() + :members: + +.. autoexception:: CoordinationFailure() + :members: + +.. autoexception:: ReadFailure() + :members: + +.. autoexception:: WriteFailure() + :members: + +.. autoexception:: FunctionFailure() + :members: + +.. autoexception:: RequestValidationException() + :members: + +.. autoexception:: ConfigurationException() + :members: + +.. autoexception:: AlreadyExists() + :members: + +.. autoexception:: InvalidRequest() + :members: + +.. autoexception:: Unauthorized() + :members: + +.. autoexception:: AuthenticationFailed() + :members: + +.. autoexception:: OperationTimedOut() + :members: diff --git a/3.26.2-scylla/_sources/api/cassandra/auth.rst.txt b/3.26.2-scylla/_sources/api/cassandra/auth.rst.txt new file mode 100644 index 0000000000..58c964cf89 --- /dev/null +++ b/3.26.2-scylla/_sources/api/cassandra/auth.rst.txt @@ -0,0 +1,22 @@ +``cassandra.auth`` - Authentication +=================================== + +.. module:: cassandra.auth + +.. autoclass:: AuthProvider + :members: + +.. autoclass:: Authenticator + :members: + +.. autoclass:: PlainTextAuthProvider + :members: + +.. autoclass:: PlainTextAuthenticator + :members: + +.. autoclass:: SaslAuthProvider + :members: + +.. autoclass:: SaslAuthenticator + :members: diff --git a/3.26.2-scylla/_sources/api/cassandra/cluster.rst.txt b/3.26.2-scylla/_sources/api/cassandra/cluster.rst.txt new file mode 100644 index 0000000000..2b3d7828a8 --- /dev/null +++ b/3.26.2-scylla/_sources/api/cassandra/cluster.rst.txt @@ -0,0 +1,228 @@ +``cassandra.cluster`` - Clusters and Sessions +============================================= + +.. module:: cassandra.cluster + +.. autoclass:: Cluster ([contact_points=('127.0.0.1',)][, port=9042][, executor_threads=2], **attr_kwargs) + + .. autoattribute:: contact_points + + .. autoattribute:: port + + .. autoattribute:: cql_version + + .. autoattribute:: protocol_version + + .. autoattribute:: compression + + .. autoattribute:: auth_provider + + .. autoattribute:: load_balancing_policy + + .. autoattribute:: reconnection_policy + + .. autoattribute:: default_retry_policy + :annotation: = + + .. autoattribute:: conviction_policy_factory + + .. autoattribute:: address_translator + + .. autoattribute:: metrics_enabled + + .. autoattribute:: metrics + + .. autoattribute:: ssl_context + + .. autoattribute:: ssl_options + + .. autoattribute:: sockopts + + .. autoattribute:: max_schema_agreement_wait + + .. autoattribute:: metadata + + .. autoattribute:: connection_class + + .. autoattribute:: control_connection_timeout + + .. autoattribute:: idle_heartbeat_interval + + .. autoattribute:: idle_heartbeat_timeout + + .. autoattribute:: schema_event_refresh_window + + .. autoattribute:: topology_event_refresh_window + + .. autoattribute:: status_event_refresh_window + + .. autoattribute:: prepare_on_all_hosts + + .. autoattribute:: reprepare_on_up + + .. autoattribute:: connect_timeout + + .. autoattribute:: schema_metadata_enabled + :annotation: = True + + .. autoattribute:: token_metadata_enabled + :annotation: = True + + .. autoattribute:: timestamp_generator + + .. autoattribute:: endpoint_factory + + .. autoattribute:: cloud + + .. automethod:: connect + + .. automethod:: shutdown + + .. automethod:: register_user_type + + .. automethod:: register_listener + + .. automethod:: unregister_listener + + .. automethod:: add_execution_profile + + .. automethod:: set_max_requests_per_connection + + .. automethod:: get_max_requests_per_connection + + .. automethod:: set_min_requests_per_connection + + .. automethod:: get_min_requests_per_connection + + .. automethod:: get_core_connections_per_host + + .. automethod:: set_core_connections_per_host + + .. automethod:: get_max_connections_per_host + + .. automethod:: set_max_connections_per_host + + .. automethod:: get_control_connection_host + + .. automethod:: refresh_schema_metadata + + .. automethod:: refresh_keyspace_metadata + + .. automethod:: refresh_table_metadata + + .. automethod:: refresh_user_type_metadata + + .. automethod:: refresh_user_function_metadata + + .. automethod:: refresh_user_aggregate_metadata + + .. automethod:: refresh_nodes + + .. automethod:: set_meta_refresh_enabled + +.. autoclass:: ExecutionProfile (load_balancing_policy=, retry_policy=None, consistency_level=ConsistencyLevel.LOCAL_ONE, serial_consistency_level=None, request_timeout=10.0, row_factory=, speculative_execution_policy=None) + :members: + :exclude-members: consistency_level + + .. autoattribute:: consistency_level + :annotation: = LOCAL_ONE + +.. autoclass:: GraphExecutionProfile (load_balancing_policy=_NOT_SET, retry_policy=None, consistency_level=ConsistencyLevel.LOCAL_ONE, serial_consistency_level=None, request_timeout=30.0, row_factory=None, graph_options=None, continuous_paging_options=_NOT_SET) + :members: + +.. autoclass:: GraphAnalyticsExecutionProfile (load_balancing_policy=None, retry_policy=None, consistency_level=ConsistencyLevel.LOCAL_ONE, serial_consistency_level=None, request_timeout=3600. * 24. * 7., row_factory=None, graph_options=None) + :members: + +.. autodata:: EXEC_PROFILE_DEFAULT + :annotation: + +.. autodata:: EXEC_PROFILE_GRAPH_DEFAULT + :annotation: + +.. autodata:: EXEC_PROFILE_GRAPH_SYSTEM_DEFAULT + :annotation: + +.. autodata:: EXEC_PROFILE_GRAPH_ANALYTICS_DEFAULT + :annotation: + +.. autoclass:: Session () + + .. autoattribute:: default_timeout + :annotation: = 10.0 + + .. autoattribute:: default_consistency_level + :annotation: = LOCAL_ONE + + .. autoattribute:: default_serial_consistency_level + :annotation: = None + + .. autoattribute:: row_factory + :annotation: = + + .. autoattribute:: default_fetch_size + + .. autoattribute:: use_client_timestamp + + .. autoattribute:: timestamp_generator + + .. autoattribute:: encoder + + .. autoattribute:: client_protocol_handler + + .. automethod:: execute(statement[, parameters][, timeout][, trace][, custom_payload][, paging_state][, host][, execute_as]) + + .. automethod:: execute_async(statement[, parameters][, trace][, custom_payload][, paging_state][, host][, execute_as]) + + .. automethod:: execute_graph(statement[, parameters][, trace][, execution_profile=EXEC_PROFILE_GRAPH_DEFAULT][, execute_as]) + + .. automethod:: execute_graph_async(statement[, parameters][, trace][, execution_profile=EXEC_PROFILE_GRAPH_DEFAULT][, execute_as]) + + .. automethod:: prepare(statement) + + .. automethod:: shutdown() + + .. automethod:: set_keyspace(keyspace) + + .. automethod:: get_execution_profile + + .. automethod:: execution_profile_clone_update + + .. automethod:: add_request_init_listener + + .. automethod:: remove_request_init_listener + +.. autoclass:: ResponseFuture () + + .. autoattribute:: query + + .. automethod:: result() + + .. automethod:: get_query_trace() + + .. automethod:: get_all_query_traces() + + .. autoattribute:: custom_payload() + + .. autoattribute:: is_schema_agreed + + .. autoattribute:: has_more_pages + + .. autoattribute:: warnings + + .. automethod:: start_fetching_next_page() + + .. automethod:: add_callback(fn, *args, **kwargs) + + .. automethod:: add_errback(fn, *args, **kwargs) + + .. automethod:: add_callbacks(callback, errback, callback_args=(), callback_kwargs=None, errback_args=(), errback_args=None) + +.. autoclass:: ResultSet () + :members: + +.. autoexception:: QueryExhausted () + +.. autoexception:: NoHostAvailable () + :members: + +.. autoexception:: UserTypeDoesNotExist () diff --git a/3.26.2-scylla/_sources/api/cassandra/concurrent.rst.txt b/3.26.2-scylla/_sources/api/cassandra/concurrent.rst.txt new file mode 100644 index 0000000000..f4bab6f048 --- /dev/null +++ b/3.26.2-scylla/_sources/api/cassandra/concurrent.rst.txt @@ -0,0 +1,8 @@ +``cassandra.concurrent`` - Utilities for Concurrent Statement Execution +======================================================================= + +.. module:: cassandra.concurrent + +.. autofunction:: execute_concurrent + +.. autofunction:: execute_concurrent_with_args diff --git a/3.26.2-scylla/_sources/api/cassandra/connection.rst.txt b/3.26.2-scylla/_sources/api/cassandra/connection.rst.txt new file mode 100644 index 0000000000..32cca590c0 --- /dev/null +++ b/3.26.2-scylla/_sources/api/cassandra/connection.rst.txt @@ -0,0 +1,21 @@ +``cassandra.connection`` - Low Level Connection Info +==================================================== + +.. module:: cassandra.connection + +.. autoexception:: ConnectionException () +.. autoexception:: ConnectionShutdown () +.. autoexception:: ConnectionBusy () +.. autoexception:: ProtocolError () + +.. autoclass:: EndPoint + :members: + +.. autoclass:: EndPointFactory + :members: + +.. autoclass:: SniEndPoint + +.. autoclass:: SniEndPointFactory + +.. autoclass:: UnixSocketEndPoint diff --git a/3.26.2-scylla/_sources/api/cassandra/cqlengine/columns.rst.txt b/3.26.2-scylla/_sources/api/cassandra/cqlengine/columns.rst.txt new file mode 100644 index 0000000000..d44be8adb8 --- /dev/null +++ b/3.26.2-scylla/_sources/api/cassandra/cqlengine/columns.rst.txt @@ -0,0 +1,89 @@ +``cassandra.cqlengine.columns`` - Column types for object mapping models +======================================================================== + +.. module:: cassandra.cqlengine.columns + +Columns +------- + +Columns in your models map to columns in your CQL table. You define CQL columns by defining column attributes on your model classes. +For a model to be valid it needs at least one primary key column and one non-primary key column. + +Just as in CQL, the order you define your columns in is important, and is the same order they are defined in on a model's corresponding table. + +Each column on your model definitions needs to be an instance of a Column class. + +.. autoclass:: Column(**kwargs) + + .. autoattribute:: primary_key + + .. autoattribute:: partition_key + + .. autoattribute:: index + + .. autoattribute:: custom_index + + .. autoattribute:: db_field + + .. autoattribute:: default + + .. autoattribute:: required + + .. autoattribute:: clustering_order + + .. autoattribute:: discriminator_column + + .. autoattribute:: static + +Column Types +------------ + +Columns of all types are initialized by passing :class:`.Column` attributes to the constructor by keyword. + +.. autoclass:: Ascii(**kwargs) + +.. autoclass:: BigInt(**kwargs) + +.. autoclass:: Blob(**kwargs) + +.. autoclass:: Bytes(**kwargs) + +.. autoclass:: Boolean(**kwargs) + +.. autoclass:: Counter + +.. autoclass:: Date(**kwargs) + +.. autoclass:: DateTime(**kwargs) + + .. autoattribute:: truncate_microseconds + +.. autoclass:: Decimal(**kwargs) + +.. autoclass:: Double(**kwargs) + +.. autoclass:: Float + +.. autoclass:: Integer(**kwargs) + +.. autoclass:: List + +.. autoclass:: Map + +.. autoclass:: Set + +.. autoclass:: SmallInt(**kwargs) + +.. autoclass:: Text + +.. autoclass:: Time(**kwargs) + +.. autoclass:: TimeUUID(**kwargs) + +.. autoclass:: TinyInt(**kwargs) + +.. autoclass:: UserDefinedType + +.. autoclass:: UUID(**kwargs) + +.. autoclass:: VarInt(**kwargs) diff --git a/3.26.2-scylla/_sources/api/cassandra/cqlengine/connection.rst.txt b/3.26.2-scylla/_sources/api/cassandra/cqlengine/connection.rst.txt new file mode 100644 index 0000000000..0f584fcca2 --- /dev/null +++ b/3.26.2-scylla/_sources/api/cassandra/cqlengine/connection.rst.txt @@ -0,0 +1,16 @@ +``cassandra.cqlengine.connection`` - Connection management for cqlengine +======================================================================== + +.. module:: cassandra.cqlengine.connection + +.. autofunction:: default + +.. autofunction:: set_session + +.. autofunction:: setup + +.. autofunction:: register_connection + +.. autofunction:: unregister_connection + +.. autofunction:: set_default_connection diff --git a/3.26.2-scylla/_sources/api/cassandra/cqlengine/management.rst.txt b/3.26.2-scylla/_sources/api/cassandra/cqlengine/management.rst.txt new file mode 100644 index 0000000000..fb483abc81 --- /dev/null +++ b/3.26.2-scylla/_sources/api/cassandra/cqlengine/management.rst.txt @@ -0,0 +1,19 @@ +``cassandra.cqlengine.management`` - Schema management for cqlengine +======================================================================== + +.. module:: cassandra.cqlengine.management + +A collection of functions for managing keyspace and table schema. + +.. autofunction:: create_keyspace_simple + +.. autofunction:: create_keyspace_network_topology + +.. autofunction:: drop_keyspace + +.. autofunction:: sync_table + +.. autofunction:: sync_type + +.. autofunction:: drop_table + diff --git a/3.26.2-scylla/_sources/api/cassandra/cqlengine/models.rst.txt b/3.26.2-scylla/_sources/api/cassandra/cqlengine/models.rst.txt new file mode 100644 index 0000000000..60b1471184 --- /dev/null +++ b/3.26.2-scylla/_sources/api/cassandra/cqlengine/models.rst.txt @@ -0,0 +1,197 @@ +``cassandra.cqlengine.models`` - Table models for object mapping +================================================================ + +.. module:: cassandra.cqlengine.models + +Model +----- +.. autoclass:: Model(\*\*kwargs) + + The initializer creates an instance of the model. Pass in keyword arguments for columns you've defined on the model. + + .. code-block:: python + + class Person(Model): + id = columns.UUID(primary_key=True) + first_name = columns.Text() + last_name = columns.Text() + + person = Person(first_name='Blake', last_name='Eggleston') + person.first_name #returns 'Blake' + person.last_name #returns 'Eggleston' + + Model attributes define how the model maps to tables in the database. These are class variables that should be set + when defining Model deriviatives. + + .. autoattribute:: __abstract__ + :annotation: = False + + .. autoattribute:: __table_name__ + + .. autoattribute:: __table_name_case_sensitive__ + + .. autoattribute:: __keyspace__ + + .. autoattribute:: __connection__ + + .. attribute:: __default_ttl__ + :annotation: = None + + Will be deprecated in release 4.0. You can set the default ttl by configuring the table ``__options__``. See :ref:`ttl-change` for more details. + + .. autoattribute:: __discriminator_value__ + + See :ref:`model_inheritance` for usage examples. + + Each table can have its own set of configuration options, including compaction. Unspecified, these default to sensible values in + the server. To override defaults, set options using the model ``__options__`` attribute, which allows options specified a dict. + + When a table is synced, it will be altered to match the options set on your table. + This means that if you are changing settings manually they will be changed back on resync. + + Do not use the options settings of cqlengine if you want to manage your compaction settings manually. + + See the `list of supported table properties for more information + `_. + + .. attribute:: __options__ + + For example: + + .. code-block:: python + + class User(Model): + __options__ = {'compaction': {'class': 'LeveledCompactionStrategy', + 'sstable_size_in_mb': '64', + 'tombstone_threshold': '.2'}, + 'comment': 'User data stored here'} + + user_id = columns.UUID(primary_key=True) + name = columns.Text() + + or : + + .. code-block:: python + + class TimeData(Model): + __options__ = {'compaction': {'class': 'SizeTieredCompactionStrategy', + 'bucket_low': '.3', + 'bucket_high': '2', + 'min_threshold': '2', + 'max_threshold': '64', + 'tombstone_compaction_interval': '86400'}, + 'gc_grace_seconds': '0'} + + .. autoattribute:: __compute_routing_key__ + + + The base methods allow creating, storing, and querying modeled objects. + + .. automethod:: create + + .. method:: if_not_exists() + + Check the existence of an object before insertion. The existence of an + object is determined by its primary key(s). And please note using this flag + would incur performance cost. + + If the insertion isn't applied, a :class:`~cassandra.cqlengine.query.LWTException` is raised. + + .. code-block:: python + + try: + TestIfNotExistsModel.if_not_exists().create(id=id, count=9, text='111111111111') + except LWTException as e: + # handle failure case + print e.existing # dict containing LWT result fields + + This method is supported on Cassandra 2.0 or later. + + .. method:: if_exists() + + Check the existence of an object before an update or delete. The existence of an + object is determined by its primary key(s). And please note using this flag + would incur performance cost. + + If the update or delete isn't applied, a :class:`~cassandra.cqlengine.query.LWTException` is raised. + + .. code-block:: python + + try: + TestIfExistsModel.objects(id=id).if_exists().update(count=9, text='111111111111') + except LWTException as e: + # handle failure case + pass + + This method is supported on Cassandra 2.0 or later. + + .. automethod:: save + + .. automethod:: update + + .. method:: iff(**values) + + Checks to ensure that the values specified are correct on the Cassandra cluster. + Simply specify the column(s) and the expected value(s). As with if_not_exists, + this incurs a performance cost. + + If the insertion isn't applied, a :class:`~cassandra.cqlengine.query.LWTException` is raised. + + .. code-block:: python + + t = TestTransactionModel(text='some text', count=5) + try: + t.iff(count=5).update('other text') + except LWTException as e: + # handle failure case + print e.existing # existing object + + .. automethod:: get + + .. automethod:: filter + + .. automethod:: all + + .. automethod:: delete + + .. method:: batch(batch_object) + + Sets the batch object to run instance updates and inserts queries with. + + See :doc:`/cqlengine/batches` for usage examples + + .. automethod:: timeout + + .. method:: timestamp(timedelta_or_datetime) + + Sets the timestamp for the query + + .. method:: ttl(ttl_in_sec) + + Sets the ttl values to run instance updates and inserts queries with. + + .. method:: using(connection=None) + + Change the context on the fly of the model instance (keyspace, connection) + + .. automethod:: column_family_name + + Models also support dict-like access: + + .. method:: len(m) + + Returns the number of columns defined in the model + + .. method:: m[col_name] + + Returns the value of column ``col_name`` + + .. method:: m[col_name] = value + + Set ``m[col_name]`` to value + + .. automethod:: keys + + .. automethod:: values + + .. automethod:: items diff --git a/3.26.2-scylla/_sources/api/cassandra/cqlengine/query.rst.txt b/3.26.2-scylla/_sources/api/cassandra/cqlengine/query.rst.txt new file mode 100644 index 0000000000..ce8f764b6b --- /dev/null +++ b/3.26.2-scylla/_sources/api/cassandra/cqlengine/query.rst.txt @@ -0,0 +1,71 @@ +``cassandra.cqlengine.query`` - Query and filter model objects +================================================================= + +.. module:: cassandra.cqlengine.query + +QuerySet +-------- +QuerySet objects are typically obtained by calling :meth:`~.cassandra.cqlengine.models.Model.objects` on a model class. +The methods here are used to filter, order, and constrain results. + +.. autoclass:: ModelQuerySet + + .. automethod:: all + + .. automethod:: batch + + .. automethod:: consistency + + .. automethod:: count + + .. method:: len(queryset) + + Returns the number of rows matched by this query. This function uses :meth:`~.cassandra.cqlengine.query.ModelQuerySet.count` internally. + + *Note: This function executes a SELECT COUNT() and has a performance cost on large datasets* + + .. automethod:: distinct + + .. automethod:: filter + + .. automethod:: get + + .. automethod:: limit + + .. automethod:: fetch_size + + .. automethod:: if_not_exists + + .. automethod:: if_exists + + .. automethod:: order_by + + .. automethod:: allow_filtering + + .. automethod:: only + + .. automethod:: defer + + .. automethod:: timestamp + + .. automethod:: ttl + + .. automethod:: using + + .. _blind_updates: + + .. automethod:: update + +.. autoclass:: BatchQuery + :members: + + .. automethod:: add_query + .. automethod:: execute + +.. autoclass:: ContextQuery + +.. autoclass:: DoesNotExist + +.. autoclass:: MultipleObjectsReturned + +.. autoclass:: LWTException diff --git a/3.26.2-scylla/_sources/api/cassandra/cqlengine/usertype.rst.txt b/3.26.2-scylla/_sources/api/cassandra/cqlengine/usertype.rst.txt new file mode 100644 index 0000000000..ebed187da9 --- /dev/null +++ b/3.26.2-scylla/_sources/api/cassandra/cqlengine/usertype.rst.txt @@ -0,0 +1,10 @@ +``cassandra.cqlengine.usertype`` - Model classes for User Defined Types +======================================================================= + +.. module:: cassandra.cqlengine.usertype + +UserType +-------- +.. autoclass:: UserType + + .. autoattribute:: __type_name__ diff --git a/3.26.2-scylla/_sources/api/cassandra/datastax/graph/fluent/index.rst.txt b/3.26.2-scylla/_sources/api/cassandra/datastax/graph/fluent/index.rst.txt new file mode 100644 index 0000000000..5547e0fdd7 --- /dev/null +++ b/3.26.2-scylla/_sources/api/cassandra/datastax/graph/fluent/index.rst.txt @@ -0,0 +1,24 @@ +:mod:`cassandra.datastax.graph.fluent` +====================================== + +.. module:: cassandra.datastax.graph.fluent + +.. autoclass:: DseGraph + + .. autoattribute:: DSE_GRAPH_QUERY_LANGUAGE + + .. automethod:: create_execution_profile + + .. automethod:: query_from_traversal + + .. automethod:: traversal_source(session=None, graph_name=None, execution_profile=EXEC_PROFILE_GRAPH_DEFAULT, traversal_class=None) + + .. automethod:: batch(session=None, execution_profile=None) + +.. autoclass:: DSESessionRemoteGraphConnection(session[, graph_name, execution_profile]) + +.. autoclass:: BaseGraphRowFactory + +.. autoclass:: graph_traversal_row_factory + +.. autoclass:: graph_traversal_dse_object_row_factory diff --git a/3.26.2-scylla/_sources/api/cassandra/datastax/graph/fluent/predicates.rst.txt b/3.26.2-scylla/_sources/api/cassandra/datastax/graph/fluent/predicates.rst.txt new file mode 100644 index 0000000000..f6e86f6451 --- /dev/null +++ b/3.26.2-scylla/_sources/api/cassandra/datastax/graph/fluent/predicates.rst.txt @@ -0,0 +1,14 @@ +:mod:`cassandra.datastax.graph.fluent.predicates` +================================================= + +.. module:: cassandra.datastax.graph.fluent.predicates + + +.. autoclass:: Search + :members: + +.. autoclass:: CqlCollection + :members: + +.. autoclass:: Geo + :members: diff --git a/3.26.2-scylla/_sources/api/cassandra/datastax/graph/fluent/query.rst.txt b/3.26.2-scylla/_sources/api/cassandra/datastax/graph/fluent/query.rst.txt new file mode 100644 index 0000000000..3dd859f96e --- /dev/null +++ b/3.26.2-scylla/_sources/api/cassandra/datastax/graph/fluent/query.rst.txt @@ -0,0 +1,8 @@ +:mod:`cassandra.datastax.graph.fluent.query` +============================================ + +.. module:: cassandra.datastax.graph.fluent.query + + +.. autoclass:: TraversalBatch + :members: diff --git a/3.26.2-scylla/_sources/api/cassandra/datastax/graph/index.rst.txt b/3.26.2-scylla/_sources/api/cassandra/datastax/graph/index.rst.txt new file mode 100644 index 0000000000..a9b41cbdc2 --- /dev/null +++ b/3.26.2-scylla/_sources/api/cassandra/datastax/graph/index.rst.txt @@ -0,0 +1,133 @@ +``cassandra.datastax.graph`` - Graph Statements, Options, and Row Factories +=========================================================================== + +.. _api-datastax-graph: + +.. module:: cassandra.datastax.graph + +.. autofunction:: single_object_row_factory + +.. autofunction:: graph_result_row_factory + +.. autofunction:: graph_object_row_factory + +.. autofunction:: graph_graphson2_row_factory + +.. autofunction:: graph_graphson3_row_factory + +.. function:: to_int(value) + + Wraps a value to be explicitly serialized as a graphson Int. + +.. function:: to_bigint(value) + + Wraps a value to be explicitly serialized as a graphson Bigint. + +.. function:: to_smallint(value) + + Wraps a value to be explicitly serialized as a graphson Smallint. + +.. function:: to_float(value) + + Wraps a value to be explicitly serialized as a graphson Float. + +.. function:: to_double(value) + + Wraps a value to be explicitly serialized as a graphson Double. + +.. autoclass:: GraphProtocol + :members: + :noindex: + +.. autoclass:: GraphOptions + :noindex: + + .. autoattribute:: graph_name + + .. autoattribute:: graph_source + + .. autoattribute:: graph_language + + .. autoattribute:: graph_read_consistency_level + + .. autoattribute:: graph_write_consistency_level + + .. autoattribute:: is_default_source + + .. autoattribute:: is_analytics_source + + .. autoattribute:: is_graph_source + + .. automethod:: set_source_default + + .. automethod:: set_source_analytics + + .. automethod:: set_source_graph + + +.. autoclass:: SimpleGraphStatement + :members: + :noindex: + +.. autoclass:: Result + :members: + :noindex: + +.. autoclass:: Vertex + :members: + :noindex: + +.. autoclass:: VertexProperty + :members: + :noindex: + +.. autoclass:: Edge + :members: + :noindex: + +.. autoclass:: Path + :members: + :noindex: + +.. autoclass:: T + :members: + :noindex: + +.. autoclass:: GraphSON1Serializer + :members: + :noindex: + +.. autoclass:: GraphSON1Deserializer + :noindex: + + .. automethod:: deserialize_date + + .. automethod:: deserialize_timestamp + + .. automethod:: deserialize_time + + .. automethod:: deserialize_duration + + .. automethod:: deserialize_int + + .. automethod:: deserialize_bigint + + .. automethod:: deserialize_double + + .. automethod:: deserialize_float + + .. automethod:: deserialize_uuid + + .. automethod:: deserialize_blob + + .. automethod:: deserialize_decimal + + .. automethod:: deserialize_point + + .. automethod:: deserialize_linestring + + .. automethod:: deserialize_polygon + +.. autoclass:: GraphSON2Reader + :members: + :noindex: diff --git a/3.26.2-scylla/_sources/api/cassandra/decoder.rst.txt b/3.26.2-scylla/_sources/api/cassandra/decoder.rst.txt new file mode 100644 index 0000000000..e213cc6d74 --- /dev/null +++ b/3.26.2-scylla/_sources/api/cassandra/decoder.rst.txt @@ -0,0 +1,20 @@ +``cassandra.decoder`` - Data Return Formats +=========================================== + +.. module:: cassandra.decoder + +.. function:: tuple_factory + + **Deprecated in 2.0.0.** Use :meth:`cassandra.query.tuple_factory` + +.. function:: named_tuple_factory + + **Deprecated in 2.0.0.** Use :meth:`cassandra.query.named_tuple_factory` + +.. function:: dict_factory + + **Deprecated in 2.0.0.** Use :meth:`cassandra.query.dict_factory` + +.. function:: ordered_dict_factory + + **Deprecated in 2.0.0.** Use :meth:`cassandra.query.ordered_dict_factory` diff --git a/3.26.2-scylla/_sources/api/cassandra/encoder.rst.txt b/3.26.2-scylla/_sources/api/cassandra/encoder.rst.txt new file mode 100644 index 0000000000..de3b180510 --- /dev/null +++ b/3.26.2-scylla/_sources/api/cassandra/encoder.rst.txt @@ -0,0 +1,36 @@ +``cassandra.encoder`` - Encoders for non-prepared Statements +============================================================ + +.. module:: cassandra.encoder + +.. autoclass:: Encoder () + + .. autoattribute:: cassandra.encoder.Encoder.mapping + + .. automethod:: cassandra.encoder.Encoder.cql_encode_none () + + .. automethod:: cassandra.encoder.Encoder.cql_encode_object () + + .. automethod:: cassandra.encoder.Encoder.cql_encode_all_types () + + .. automethod:: cassandra.encoder.Encoder.cql_encode_sequence () + + .. automethod:: cassandra.encoder.Encoder.cql_encode_str () + + .. automethod:: cassandra.encoder.Encoder.cql_encode_unicode () + + .. automethod:: cassandra.encoder.Encoder.cql_encode_bytes () + + Converts strings, buffers, and bytearrays into CQL blob literals. + + .. automethod:: cassandra.encoder.Encoder.cql_encode_datetime () + + .. automethod:: cassandra.encoder.Encoder.cql_encode_date () + + .. automethod:: cassandra.encoder.Encoder.cql_encode_map_collection () + + .. automethod:: cassandra.encoder.Encoder.cql_encode_list_collection () + + .. automethod:: cassandra.encoder.Encoder.cql_encode_set_collection () + + .. automethod:: cql_encode_tuple () diff --git a/3.26.2-scylla/_sources/api/cassandra/graph.rst.txt b/3.26.2-scylla/_sources/api/cassandra/graph.rst.txt new file mode 100644 index 0000000000..43ddd3086c --- /dev/null +++ b/3.26.2-scylla/_sources/api/cassandra/graph.rst.txt @@ -0,0 +1,121 @@ +``cassandra.graph`` - Graph Statements, Options, and Row Factories +================================================================== + +.. note:: This module is only for backward compatibility for dse-driver users. Consider using :ref:`cassandra.datastax.graph `. + +.. module:: cassandra.graph + +.. autofunction:: single_object_row_factory + +.. autofunction:: graph_result_row_factory + +.. autofunction:: graph_object_row_factory + +.. autofunction:: graph_graphson2_row_factory + +.. autofunction:: graph_graphson3_row_factory + +.. function:: to_int(value) + + Wraps a value to be explicitly serialized as a graphson Int. + +.. function:: to_bigint(value) + + Wraps a value to be explicitly serialized as a graphson Bigint. + +.. function:: to_smallint(value) + + Wraps a value to be explicitly serialized as a graphson Smallint. + +.. function:: to_float(value) + + Wraps a value to be explicitly serialized as a graphson Float. + +.. function:: to_double(value) + + Wraps a value to be explicitly serialized as a graphson Double. + +.. autoclass:: GraphProtocol + :members: + +.. autoclass:: GraphOptions + + .. autoattribute:: graph_name + + .. autoattribute:: graph_source + + .. autoattribute:: graph_language + + .. autoattribute:: graph_read_consistency_level + + .. autoattribute:: graph_write_consistency_level + + .. autoattribute:: is_default_source + + .. autoattribute:: is_analytics_source + + .. autoattribute:: is_graph_source + + .. automethod:: set_source_default + + .. automethod:: set_source_analytics + + .. automethod:: set_source_graph + + +.. autoclass:: SimpleGraphStatement + :members: + +.. autoclass:: Result + :members: + +.. autoclass:: Vertex + :members: + +.. autoclass:: VertexProperty + :members: + +.. autoclass:: Edge + :members: + +.. autoclass:: Path + :members: + +.. autoclass:: GraphSON1Serializer + :members: + +.. autoclass:: GraphSON1Deserializer + + .. automethod:: deserialize_date + + .. automethod:: deserialize_timestamp + + .. automethod:: deserialize_time + + .. automethod:: deserialize_duration + + .. automethod:: deserialize_int + + .. automethod:: deserialize_bigint + + .. automethod:: deserialize_double + + .. automethod:: deserialize_float + + .. automethod:: deserialize_uuid + + .. automethod:: deserialize_blob + + .. automethod:: deserialize_decimal + + .. automethod:: deserialize_point + + .. automethod:: deserialize_linestring + + .. automethod:: deserialize_polygon + +.. autoclass:: GraphSON2Reader + :members: + +.. autoclass:: GraphSON3Reader + :members: diff --git a/3.26.2-scylla/_sources/api/cassandra/io/asyncioreactor.rst.txt b/3.26.2-scylla/_sources/api/cassandra/io/asyncioreactor.rst.txt new file mode 100644 index 0000000000..38ae63ca7f --- /dev/null +++ b/3.26.2-scylla/_sources/api/cassandra/io/asyncioreactor.rst.txt @@ -0,0 +1,7 @@ +``cassandra.io.asyncioreactor`` - ``asyncio`` Event Loop +===================================================================== + +.. module:: cassandra.io.asyncioreactor + +.. autoclass:: AsyncioConnection + :members: diff --git a/3.26.2-scylla/_sources/api/cassandra/io/asyncorereactor.rst.txt b/3.26.2-scylla/_sources/api/cassandra/io/asyncorereactor.rst.txt new file mode 100644 index 0000000000..ade7887e70 --- /dev/null +++ b/3.26.2-scylla/_sources/api/cassandra/io/asyncorereactor.rst.txt @@ -0,0 +1,7 @@ +``cassandra.io.asyncorereactor`` - ``asyncore`` Event Loop +========================================================== + +.. module:: cassandra.io.asyncorereactor + +.. autoclass:: AsyncoreConnection + :members: diff --git a/3.26.2-scylla/_sources/api/cassandra/io/eventletreactor.rst.txt b/3.26.2-scylla/_sources/api/cassandra/io/eventletreactor.rst.txt new file mode 100644 index 0000000000..1ba742c7e9 --- /dev/null +++ b/3.26.2-scylla/_sources/api/cassandra/io/eventletreactor.rst.txt @@ -0,0 +1,7 @@ +``cassandra.io.eventletreactor`` - ``eventlet``-compatible Connection +===================================================================== + +.. module:: cassandra.io.eventletreactor + +.. autoclass:: EventletConnection + :members: diff --git a/3.26.2-scylla/_sources/api/cassandra/io/geventreactor.rst.txt b/3.26.2-scylla/_sources/api/cassandra/io/geventreactor.rst.txt new file mode 100644 index 0000000000..603affe140 --- /dev/null +++ b/3.26.2-scylla/_sources/api/cassandra/io/geventreactor.rst.txt @@ -0,0 +1,7 @@ +``cassandra.io.geventreactor`` - ``gevent``-compatible Event Loop +================================================================= + +.. module:: cassandra.io.geventreactor + +.. autoclass:: GeventConnection + :members: diff --git a/3.26.2-scylla/_sources/api/cassandra/io/libevreactor.rst.txt b/3.26.2-scylla/_sources/api/cassandra/io/libevreactor.rst.txt new file mode 100644 index 0000000000..5b7288edf2 --- /dev/null +++ b/3.26.2-scylla/_sources/api/cassandra/io/libevreactor.rst.txt @@ -0,0 +1,6 @@ +``cassandra.io.libevreactor`` - ``libev`` Event Loop +==================================================== + +.. module:: cassandra.io.libevreactor + +.. autoclass:: LibevConnection diff --git a/3.26.2-scylla/_sources/api/cassandra/io/twistedreactor.rst.txt b/3.26.2-scylla/_sources/api/cassandra/io/twistedreactor.rst.txt new file mode 100644 index 0000000000..24e93bd432 --- /dev/null +++ b/3.26.2-scylla/_sources/api/cassandra/io/twistedreactor.rst.txt @@ -0,0 +1,9 @@ +``cassandra.io.twistedreactor`` - Twisted Event Loop +==================================================== + +.. module:: cassandra.io.twistedreactor + +.. class:: TwistedConnection + + An implementation of :class:`~cassandra.io.connection.Connection` that uses + Twisted's reactor as its event loop. diff --git a/3.26.2-scylla/_sources/api/cassandra/metadata.rst.txt b/3.26.2-scylla/_sources/api/cassandra/metadata.rst.txt new file mode 100644 index 0000000000..7c1280bcf7 --- /dev/null +++ b/3.26.2-scylla/_sources/api/cassandra/metadata.rst.txt @@ -0,0 +1,93 @@ +``cassandra.metadata`` - Schema and Ring Topology +================================================= + +.. module:: cassandra.metadata + +.. autodata:: cql_keywords + :annotation: + +.. autodata:: cql_keywords_unreserved + :annotation: + +.. autodata:: cql_keywords_reserved + :annotation: + +.. autoclass:: Metadata () + :members: + :exclude-members: rebuild_schema, rebuild_token_map, add_host, remove_host + +Schemas +------- + +.. autoclass:: KeyspaceMetadata () + :members: + +.. autoclass:: UserType () + :members: + +.. autoclass:: Function () + :members: + +.. autoclass:: Aggregate () + :members: + +.. autoclass:: TableMetadata () + :members: + +.. autoclass:: TableMetadataV3 () + :members: + +.. autoclass:: TableMetadataDSE68 () + :members: + +.. autoclass:: ColumnMetadata () + :members: + +.. autoclass:: IndexMetadata () + :members: + +.. autoclass:: MaterializedViewMetadata () + :members: + +.. autoclass:: VertexMetadata () + :members: + +.. autoclass:: EdgeMetadata () + :members: + +Tokens and Ring Topology +------------------------ + +.. autoclass:: TokenMap () + :members: + +.. autoclass:: Token () + :members: + +.. autoclass:: Murmur3Token + :members: + +.. autoclass:: MD5Token + :members: + +.. autoclass:: BytesToken + :members: + +.. autoclass:: ReplicationStrategy + :members: + +.. autoclass:: ReplicationFactor + :members: + :exclude-members: create + +.. autoclass:: SimpleStrategy + :members: + +.. autoclass:: NetworkTopologyStrategy + :members: + +.. autoclass:: LocalStrategy + :members: + +.. autofunction:: group_keys_by_replica + diff --git a/3.26.2-scylla/_sources/api/cassandra/metrics.rst.txt b/3.26.2-scylla/_sources/api/cassandra/metrics.rst.txt new file mode 100644 index 0000000000..0df7f8b5b9 --- /dev/null +++ b/3.26.2-scylla/_sources/api/cassandra/metrics.rst.txt @@ -0,0 +1,7 @@ +``cassandra.metrics`` - Performance Metrics +=========================================== + +.. module:: cassandra.metrics + +.. autoclass:: cassandra.metrics.Metrics () + :members: diff --git a/3.26.2-scylla/_sources/api/cassandra/policies.rst.txt b/3.26.2-scylla/_sources/api/cassandra/policies.rst.txt new file mode 100644 index 0000000000..387b19ed95 --- /dev/null +++ b/3.26.2-scylla/_sources/api/cassandra/policies.rst.txt @@ -0,0 +1,96 @@ +``cassandra.policies`` - Load balancing and Failure Handling Policies +===================================================================== + +.. module:: cassandra.policies + +Load Balancing +-------------- + +.. autoclass:: HostDistance + :members: + +.. autoclass:: LoadBalancingPolicy + :members: + +.. autoclass:: RoundRobinPolicy + :members: + +.. autoclass:: DCAwareRoundRobinPolicy + :members: + +.. autoclass:: WhiteListRoundRobinPolicy + :members: + +.. autoclass:: TokenAwarePolicy + :members: + +.. autoclass:: HostFilterPolicy + + .. we document these methods manually so we can specify a param to predicate + + .. automethod:: predicate(host) + .. automethod:: distance + .. automethod:: make_query_plan + +.. autoclass:: DefaultLoadBalancingPolicy + :members: + +.. autoclass:: DSELoadBalancingPolicy + :members: + +Translating Server Node Addresses +--------------------------------- + +.. autoclass:: AddressTranslator + :members: + +.. autoclass:: IdentityTranslator + :members: + +.. autoclass:: EC2MultiRegionTranslator + :members: + +Marking Hosts Up or Down +------------------------ + +.. autoclass:: ConvictionPolicy + :members: + +.. autoclass:: SimpleConvictionPolicy + :members: + +Reconnecting to Dead Hosts +-------------------------- + +.. autoclass:: ReconnectionPolicy + :members: + +.. autoclass:: ConstantReconnectionPolicy + :members: + +.. autoclass:: ExponentialReconnectionPolicy + :members: + +Retrying Failed Operations +-------------------------- + +.. autoclass:: WriteType + :members: + +.. autoclass:: RetryPolicy + :members: + +.. autoclass:: FallthroughRetryPolicy + :members: + +.. autoclass:: DowngradingConsistencyRetryPolicy + :members: + +Retrying Idempotent Operations +------------------------------ + +.. autoclass:: SpeculativeExecutionPolicy + :members: + +.. autoclass:: ConstantSpeculativeExecutionPolicy + :members: diff --git a/3.26.2-scylla/_sources/api/cassandra/pool.rst.txt b/3.26.2-scylla/_sources/api/cassandra/pool.rst.txt new file mode 100644 index 0000000000..b14d30e19c --- /dev/null +++ b/3.26.2-scylla/_sources/api/cassandra/pool.rst.txt @@ -0,0 +1,11 @@ +``cassandra.pool`` - Hosts and Connection Pools +=============================================== + +.. automodule:: cassandra.pool + +.. autoclass:: Host () + :members: + :exclude-members: set_location_info, get_and_set_reconnection_handler + +.. autoexception:: NoConnectionsAvailable + :members: diff --git a/3.26.2-scylla/_sources/api/cassandra/protocol.rst.txt b/3.26.2-scylla/_sources/api/cassandra/protocol.rst.txt new file mode 100644 index 0000000000..f615ab1a70 --- /dev/null +++ b/3.26.2-scylla/_sources/api/cassandra/protocol.rst.txt @@ -0,0 +1,55 @@ +``cassandra.protocol`` - Protocol Features +===================================================================== + +.. module:: cassandra.protocol + +.. _custom_payload: + +Custom Payloads +--------------- +Native protocol version 4+ allows for a custom payload to be sent between clients +and custom query handlers. The payload is specified as a string:binary_type dict +holding custom key/value pairs. + +By default these are ignored by the server. They can be useful for servers implementing +a custom QueryHandler. + +See :meth:`.Session.execute`, ::meth:`.Session.execute_async`, :attr:`.ResponseFuture.custom_payload`. + +.. autoclass:: _ProtocolHandler + + .. autoattribute:: message_types_by_opcode + :annotation: = {default mapping} + + .. automethod:: encode_message + + .. automethod:: decode_message + +.. _faster_deser: + +Faster Deserialization +---------------------- +When python-driver is compiled with Cython, it uses a Cython-based deserialization path +to deserialize messages. By default, the driver will use a Cython-based parser that returns +lists of rows similar to the pure-Python version. In addition, there are two additional +ProtocolHandler classes that can be used to deserialize response messages: ``LazyProtocolHandler`` +and ``NumpyProtocolHandler``. They can be used as follows: + +.. code:: python + + from cassandra.protocol import NumpyProtocolHandler, LazyProtocolHandler + from cassandra.query import tuple_factory + s.client_protocol_handler = LazyProtocolHandler # for a result iterator + s.row_factory = tuple_factory #required for Numpy results + s.client_protocol_handler = NumpyProtocolHandler # for a dict of NumPy arrays as result + +These protocol handlers comprise different parsers, and return results as described below: + +- ProtocolHandler: this default implementation is a drop-in replacement for the pure-Python version. + The rows are all parsed upfront, before results are returned. + +- LazyProtocolHandler: near drop-in replacement for the above, except that it returns an iterator over rows, + lazily decoded into the default row format (this is more efficient since all decoded results are not materialized at once) + +- NumpyProtocolHander: deserializes results directly into NumPy arrays. This facilitates efficient integration with + analysis toolkits such as Pandas. diff --git a/3.26.2-scylla/_sources/api/cassandra/query.rst.txt b/3.26.2-scylla/_sources/api/cassandra/query.rst.txt new file mode 100644 index 0000000000..fcd79739b9 --- /dev/null +++ b/3.26.2-scylla/_sources/api/cassandra/query.rst.txt @@ -0,0 +1,59 @@ +``cassandra.query`` - Prepared Statements, Batch Statements, Tracing, and Row Factories +======================================================================================= + +.. module:: cassandra.query + +.. autofunction:: tuple_factory + +.. autofunction:: named_tuple_factory + +.. autofunction:: dict_factory + +.. autofunction:: ordered_dict_factory + +.. autoclass:: SimpleStatement + :members: + +.. autoclass:: PreparedStatement () + :members: + +.. autoclass:: BoundStatement + :members: + +.. autoclass:: Statement () + :members: + +.. autodata:: UNSET_VALUE + :annotation: + +.. autoclass:: BatchStatement (batch_type=BatchType.LOGGED, retry_policy=None, consistency_level=None) + :members: + +.. autoclass:: BatchType () + + .. autoattribute:: LOGGED + + .. autoattribute:: UNLOGGED + + .. autoattribute:: COUNTER + +.. autoclass:: cassandra.query.ValueSequence + + A wrapper class that is used to specify that a sequence of values should + be treated as a CQL list of values instead of a single column collection when used + as part of the `parameters` argument for :meth:`.Session.execute()`. + + This is typically needed when supplying a list of keys to select. + For example:: + + >>> my_user_ids = ('alice', 'bob', 'charles') + >>> query = "SELECT * FROM users WHERE user_id IN %s" + >>> session.execute(query, parameters=[ValueSequence(my_user_ids)]) + +.. autoclass:: QueryTrace () + :members: + +.. autoclass:: TraceEvent () + :members: + +.. autoexception:: TraceUnavailable diff --git a/3.26.2-scylla/_sources/api/cassandra/timestamps.rst.txt b/3.26.2-scylla/_sources/api/cassandra/timestamps.rst.txt new file mode 100644 index 0000000000..00d25b06d9 --- /dev/null +++ b/3.26.2-scylla/_sources/api/cassandra/timestamps.rst.txt @@ -0,0 +1,14 @@ +``cassandra.timestamps`` - Timestamp Generation +=============================================== + +.. module:: cassandra.timestamps + +.. autoclass:: MonotonicTimestampGenerator (warn_on_drift=True, warning_threshold=0, warning_interval=0) + + .. autoattribute:: warn_on_drift + + .. autoattribute:: warning_threshold + + .. autoattribute:: warning_interval + + .. automethod:: _next_timestamp diff --git a/3.26.2-scylla/_sources/api/cassandra/util.rst.txt b/3.26.2-scylla/_sources/api/cassandra/util.rst.txt new file mode 100644 index 0000000000..848d4d5fc2 --- /dev/null +++ b/3.26.2-scylla/_sources/api/cassandra/util.rst.txt @@ -0,0 +1,5 @@ +``cassandra.util`` - Utilities +=================================== + +.. automodule:: cassandra.util + :members: diff --git a/3.26.2-scylla/_sources/api/index.rst.txt b/3.26.2-scylla/_sources/api/index.rst.txt new file mode 100644 index 0000000000..9e778d508c --- /dev/null +++ b/3.26.2-scylla/_sources/api/index.rst.txt @@ -0,0 +1,54 @@ +API Documentation +================= + +Core Driver +----------- +.. toctree:: + :maxdepth: 2 + + cassandra + cassandra/cluster + cassandra/policies + cassandra/auth + cassandra/graph + cassandra/metadata + cassandra/metrics + cassandra/query + cassandra/pool + cassandra/protocol + cassandra/encoder + cassandra/decoder + cassandra/concurrent + cassandra/connection + cassandra/util + cassandra/timestamps + cassandra/io/asyncioreactor + cassandra/io/asyncorereactor + cassandra/io/eventletreactor + cassandra/io/libevreactor + cassandra/io/geventreactor + cassandra/io/twistedreactor + +.. _om_api: + +Object Mapper +------------- +.. toctree:: + :maxdepth: 1 + + cassandra/cqlengine/models + cassandra/cqlengine/columns + cassandra/cqlengine/query + cassandra/cqlengine/connection + cassandra/cqlengine/management + cassandra/cqlengine/usertype + +DataStax Graph +-------------- +.. toctree:: + :maxdepth: 1 + + cassandra/datastax/graph/index + cassandra/datastax/graph/fluent/index + cassandra/datastax/graph/fluent/query + cassandra/datastax/graph/fluent/predicates diff --git a/3.26.2-scylla/_sources/cqlengine/batches.rst.txt b/3.26.2-scylla/_sources/cqlengine/batches.rst.txt new file mode 100644 index 0000000000..306e7d01a6 --- /dev/null +++ b/3.26.2-scylla/_sources/cqlengine/batches.rst.txt @@ -0,0 +1,108 @@ +============= +Batch Queries +============= + +cqlengine supports batch queries using the BatchQuery class. Batch queries can be started and stopped manually, or within a context manager. To add queries to the batch object, you just need to precede the create/save/delete call with a call to batch, and pass in the batch object. + + +Batch Query General Use Pattern +=============================== + +You can only create, update, and delete rows with a batch query, attempting to read rows out of the database with a batch query will fail. + +.. code-block:: python + + from cassandra.cqlengine.query import BatchQuery + + #using a context manager + with BatchQuery() as b: + now = datetime.now() + em1 = ExampleModel.batch(b).create(example_type=0, description="1", created_at=now) + em2 = ExampleModel.batch(b).create(example_type=0, description="2", created_at=now) + em3 = ExampleModel.batch(b).create(example_type=0, description="3", created_at=now) + + # -- or -- + + #manually + b = BatchQuery() + now = datetime.now() + em1 = ExampleModel.batch(b).create(example_type=0, description="1", created_at=now) + em2 = ExampleModel.batch(b).create(example_type=0, description="2", created_at=now) + em3 = ExampleModel.batch(b).create(example_type=0, description="3", created_at=now) + b.execute() + + # updating in a batch + + b = BatchQuery() + em1.description = "new description" + em1.batch(b).save() + em2.description = "another new description" + em2.batch(b).save() + b.execute() + + # deleting in a batch + b = BatchQuery() + ExampleModel.objects(id=some_id).batch(b).delete() + ExampleModel.objects(id=some_id2).batch(b).delete() + b.execute() + + +Typically you will not want the block to execute if an exception occurs inside the `with` block. However, in the case that this is desirable, it's achievable by using the following syntax: + +.. code-block:: python + + with BatchQuery(execute_on_exception=True) as b: + LogEntry.batch(b).create(k=1, v=1) + mystery_function() # exception thrown in here + LogEntry.batch(b).create(k=1, v=2) # this code is never reached due to the exception, but anything leading up to here will execute in the batch. + +If an exception is thrown somewhere in the block, any statements that have been added to the batch will still be executed. This is useful for some logging situations. + +Batch Query Execution Callbacks +=============================== + +In order to allow secondary tasks to be chained to the end of batch, BatchQuery instances allow callbacks to be +registered with the batch, to be executed immediately after the batch executes. + +Multiple callbacks can be attached to same BatchQuery instance, they are executed in the same order that they +are added to the batch. + +The callbacks attached to a given batch instance are executed only if the batch executes. If the batch is used as a +context manager and an exception is raised, the queued up callbacks will not be run. + +.. code-block:: python + + def my_callback(*args, **kwargs): + pass + + batch = BatchQuery() + + batch.add_callback(my_callback) + batch.add_callback(my_callback, 'positional arg', named_arg='named arg value') + + # if you need reference to the batch within the callback, + # just trap it in the arguments to be passed to the callback: + batch.add_callback(my_callback, cqlengine_batch=batch) + + # once the batch executes... + batch.execute() + + # the effect of the above scheduled callbacks will be similar to + my_callback() + my_callback('positional arg', named_arg='named arg value') + my_callback(cqlengine_batch=batch) + +Failure in any of the callbacks does not affect the batch's execution, as the callbacks are started after the execution +of the batch is complete. + +Logged vs Unlogged Batches +--------------------------- +By default, queries in cqlengine are LOGGED, which carries additional overhead from UNLOGGED. To explicitly state which batch type to use, simply: + + +.. code-block:: python + + from cassandra.cqlengine.query import BatchType + with BatchQuery(batch_type=BatchType.Unlogged) as b: + LogEntry.batch(b).create(k=1, v=1) + LogEntry.batch(b).create(k=1, v=2) diff --git a/3.26.2-scylla/_sources/cqlengine/connections.rst.txt b/3.26.2-scylla/_sources/cqlengine/connections.rst.txt new file mode 100644 index 0000000000..03ade27521 --- /dev/null +++ b/3.26.2-scylla/_sources/cqlengine/connections.rst.txt @@ -0,0 +1,137 @@ +=========== +Connections +=========== + +Connections aim to ease the use of multiple sessions with cqlengine. Connections can be set on a model class, per query or using a context manager. + + +Register a new connection +========================= + +To use cqlengine, you need at least a default connection. If you initialize cqlengine's connections with with :func:`connection.setup <.connection.setup>`, a connection will be created automatically. If you want to use another cluster/session, you need to register a new cqlengine connection. You register a connection with :func:`~.connection.register_connection`: + +.. code-block:: python + + from cassandra.cqlengine import connection + + connection.setup(['127.0.0.1') + connection.register_connection('cluster2', ['127.0.0.2']) + +:func:`~.connection.register_connection` can take a list of hosts, as shown above, in which case it will create a connection with a new session. It can also take a `session` argument if you've already created a session: + +.. code-block:: python + + from cassandra.cqlengine import connection + from cassandra.cluster import Cluster + + session = Cluster(['127.0.0.1']).connect() + connection.register_connection('cluster3', session=session) + + +Change the default connection +============================= + +You can change the default cqlengine connection on registration: + +.. code-block:: python + + from cassandra.cqlengine import connection + + connection.register_connection('cluster2', ['127.0.0.2'] default=True) + +or on the fly using :func:`~.connection.set_default_connection` + +.. code-block:: python + + connection.set_default_connection('cluster2') + +Unregister a connection +======================= + +You can unregister a connection using :func:`~.connection.unregister_connection`: + +.. code-block:: python + + connection.unregister_connection('cluster2') + +Management +========== + +When using multiples connections, you also need to sync your models on all connections (and keyspaces) that you need operate on. Management commands have been improved to ease this part. Here is an example: + +.. code-block:: python + + from cassandra.cqlengine import management + + keyspaces = ['ks1', 'ks2'] + conns = ['cluster1', 'cluster2'] + + # registers your connections + # ... + + # create all keyspaces on all connections + for ks in keyspaces: + management.create_simple_keyspace(ks, connections=conns) + + # define your Automobile model + # ... + + # sync your models + management.sync_table(Automobile, keyspaces=keyspaces, connections=conns) + + +Connection Selection +==================== + +cqlengine will select the default connection, unless your specify a connection using one of the following methods. + +Default Model Connection +------------------------ + +You can specify a default connection per model: + +.. code-block:: python + + class Automobile(Model): + __keyspace__ = 'test' + __connection__ = 'cluster2' + manufacturer = columns.Text(primary_key=True) + year = columns.Integer(primary_key=True) + model = columns.Text(primary_key=True) + + print len(Automobile.objects.all()) # executed on the connection 'cluster2' + +QuerySet and model instance +--------------------------- + +You can use the :attr:`using() <.query.ModelQuerySet.using>` method to select a connection (or keyspace): + +.. code-block:: python + + Automobile.objects.using(connection='cluster1').create(manufacturer='honda', year=2010, model='civic') + q = Automobile.objects.filter(manufacturer='Tesla') + autos = q.using(keyspace='ks2', connection='cluster2').all() + + for auto in autos: + auto.using(connection='cluster1').save() + +Context Manager +--------------- + +You can use the ContextQuery as well to select a connection: + +.. code-block:: python + + with ContextQuery(Automobile, connection='cluster1') as A: + A.objects.filter(manufacturer='honda').all() # executed on 'cluster1' + + +BatchQuery +---------- + +With a BatchQuery, you can select the connection with the context manager. Note that all operations in the batch need to use the same connection. + +.. code-block:: python + + with BatchQuery(connection='cluster1') as b: + Automobile.objects.batch(b).create(manufacturer='honda', year=2010, model='civic') diff --git a/3.26.2-scylla/_sources/cqlengine/faq.rst.txt b/3.26.2-scylla/_sources/cqlengine/faq.rst.txt new file mode 100644 index 0000000000..6c056d02ea --- /dev/null +++ b/3.26.2-scylla/_sources/cqlengine/faq.rst.txt @@ -0,0 +1,67 @@ +========================== +Frequently Asked Questions +========================== + +Why don't updates work correctly on models instantiated as Model(field=value, field2=value2)? +------------------------------------------------------------------------------------------------ + +The recommended way to create new rows is with the models .create method. The values passed into a model's init method are interpreted by the model as the values as they were read from a row. This allows the model to "know" which rows have changed since the row was read out of cassandra, and create suitable update statements. + +How to preserve ordering in batch query? +------------------------------------------- + +Statement Ordering is not supported by CQL3 batches. Therefore, +once cassandra needs resolving conflict(Updating the same column in one batch), +The algorithm below would be used. + +* If timestamps are different, pick the column with the largest timestamp (the value being a regular column or a tombstone) +* If timestamps are the same, and one of the columns in a tombstone ('null') - pick the tombstone +* If timestamps are the same, and none of the columns are tombstones, pick the column with the largest value + +Below is an example to show this scenario. + +.. code-block:: python + + class MyMode(Model): + id = columns.Integer(primary_key=True) + count = columns.Integer() + text = columns.Text() + + with BatchQuery() as b: + MyModel.batch(b).create(id=1, count=2, text='123') + MyModel.batch(b).create(id=1, count=3, text='111') + + assert MyModel.objects(id=1).first().count == 3 + assert MyModel.objects(id=1).first().text == '123' + +The largest value of count is 3, and the largest value of text would be '123'. + +The workaround is applying timestamp to each statement, then Cassandra would +resolve to the statement with the lastest timestamp. + +.. code-block:: python + + with BatchQuery() as b: + MyModel.timestamp(datetime.now()).batch(b).create(id=1, count=2, text='123') + MyModel.timestamp(datetime.now()).batch(b).create(id=1, count=3, text='111') + + assert MyModel.objects(id=1).first().count == 3 + assert MyModel.objects(id=1).first().text == '111' + +How can I delete individual values from a row? +------------------------------------------------- + +When inserting with CQLEngine, ``None`` is equivalent to CQL ``NULL`` or to +issuing a ``DELETE`` on that column. For example: + +.. code-block:: python + + class MyModel(Model): + id = columns.Integer(primary_key=True) + text = columns.Text() + + m = MyModel.create(id=1, text='We can delete this with None') + assert MyModel.objects(id=1).first().text is not None + + m.update(text=None) + assert MyModel.objects(id=1).first().text is None diff --git a/3.26.2-scylla/_sources/cqlengine/models.rst.txt b/3.26.2-scylla/_sources/cqlengine/models.rst.txt new file mode 100644 index 0000000000..c0ba390119 --- /dev/null +++ b/3.26.2-scylla/_sources/cqlengine/models.rst.txt @@ -0,0 +1,218 @@ +====== +Models +====== + +.. module:: cqlengine.models + +A model is a python class representing a CQL table. Models derive from :class:`Model`, and +define basic table properties and columns for a table. + +Columns in your models map to columns in your CQL table. You define CQL columns by defining column attributes on your model classes. +For a model to be valid it needs at least one primary key column and one non-primary key column. Just as in CQL, the order you define +your columns in is important, and is the same order they are defined in on a model's corresponding table. + +Some basic examples defining models are shown below. Consult the :doc:`Model API docs ` and :doc:`Column API docs ` for complete details. + +Example Definitions +=================== + +This example defines a ``Person`` table, with the columns ``first_name`` and ``last_name`` + +.. code-block:: python + + from cassandra.cqlengine import columns + from cassandra.cqlengine.models import Model + + class Person(Model): + id = columns.UUID(primary_key=True) + first_name = columns.Text() + last_name = columns.Text() + + +The Person model would create this CQL table: + +.. code-block:: sql + + CREATE TABLE cqlengine.person ( + id uuid, + first_name text, + last_name text, + PRIMARY KEY (id) + ); + +Here's an example of a comment table created with clustering keys, in descending order: + +.. code-block:: python + + from cassandra.cqlengine import columns + from cassandra.cqlengine.models import Model + + class Comment(Model): + photo_id = columns.UUID(primary_key=True) + comment_id = columns.TimeUUID(primary_key=True, clustering_order="DESC") + comment = columns.Text() + +The Comment model's ``create table`` would look like the following: + +.. code-block:: sql + + CREATE TABLE comment ( + photo_id uuid, + comment_id timeuuid, + comment text, + PRIMARY KEY (photo_id, comment_id) + ) WITH CLUSTERING ORDER BY (comment_id DESC); + +To sync the models to the database, you may do the following*: + +.. code-block:: python + + from cassandra.cqlengine.management import sync_table + sync_table(Person) + sync_table(Comment) + +\*Note: synchronizing models causes schema changes, and should be done with caution. +Please see the discussion in :doc:`/api/cassandra/cqlengine/management` for considerations. + +For examples on manipulating data and creating queries, see :doc:`queryset` + +Manipulating model instances as dictionaries +============================================ + +Model instances can be accessed like dictionaries. + +.. code-block:: python + + class Person(Model): + first_name = columns.Text() + last_name = columns.Text() + + kevin = Person.create(first_name="Kevin", last_name="Deldycke") + dict(kevin) # returns {'first_name': 'Kevin', 'last_name': 'Deldycke'} + kevin['first_name'] # returns 'Kevin' + kevin.keys() # returns ['first_name', 'last_name'] + kevin.values() # returns ['Kevin', 'Deldycke'] + kevin.items() # returns [('first_name', 'Kevin'), ('last_name', 'Deldycke')] + + kevin['first_name'] = 'KEVIN5000' # changes the models first name + +Extending Model Validation +========================== + +Each time you save a model instance in cqlengine, the data in the model is validated against the schema you've defined +for your model. Most of the validation is fairly straightforward, it basically checks that you're not trying to do +something like save text into an integer column, and it enforces the ``required`` flag set on column definitions. +It also performs any transformations needed to save the data properly. + +However, there are often additional constraints or transformations you want to impose on your data, beyond simply +making sure that Cassandra won't complain when you try to insert it. To define additional validation on a model, +extend the model's validation method: + +.. code-block:: python + + class Member(Model): + person_id = UUID(primary_key=True) + name = Text(required=True) + + def validate(self): + super(Member, self).validate() + if self.name == 'jon': + raise ValidationError('no jon\'s allowed') + +*Note*: while not required, the convention is to raise a ``ValidationError`` (``from cassandra.cqlengine import ValidationError``) +if validation fails. + +.. _model_inheritance: + +Model Inheritance +================= +It is possible to save and load different model classes using a single CQL table. +This is useful in situations where you have different object types that you want to store in a single cassandra row. + +For instance, suppose you want a table that stores rows of pets owned by an owner: + +.. code-block:: python + + class Pet(Model): + __table_name__ = 'pet' + owner_id = UUID(primary_key=True) + pet_id = UUID(primary_key=True) + pet_type = Text(discriminator_column=True) + name = Text() + + def eat(self, food): + pass + + def sleep(self, time): + pass + + class Cat(Pet): + __discriminator_value__ = 'cat' + cuteness = Float() + + def tear_up_couch(self): + pass + + class Dog(Pet): + __discriminator_value__ = 'dog' + fierceness = Float() + + def bark_all_night(self): + pass + +After calling ``sync_table`` on each of these tables, the columns defined in each model will be added to the +``pet`` table. Additionally, saving ``Cat`` and ``Dog`` models will save the meta data needed to identify each row +as either a cat or dog. + +To setup a model structure with inheritance, follow these steps + +1. Create a base model with a column set as the distriminator (``distriminator_column=True`` in the column definition) +2. Create subclass models, and define a unique ``__discriminator_value__`` value on each +3. Run ``sync_table`` on each of the sub tables + +**About the discriminator value** + +The discriminator value is what cqlengine uses under the covers to map logical cql rows to the appropriate model type. The +base model maintains a map of discriminator values to subclasses. When a specialized model is saved, its discriminator value is +automatically saved into the discriminator column. The discriminator column may be any column type except counter and container types. +Additionally, if you set ``index=True`` on your discriminator column, you can execute queries against specialized subclasses, and a +``WHERE`` clause will be automatically added to your query, returning only rows of that type. Note that you must +define a unique ``__discriminator_value__`` to each subclass, and that you can only assign a single discriminator column per model. + +.. _user_types: + +User Defined Types +================== +cqlengine models User Defined Types (UDTs) much like tables, with fields defined by column type attributes. However, UDT instances +are only created, presisted, and queried via table Models. A short example to introduce the pattern:: + + from cassandra.cqlengine.columns import * + from cassandra.cqlengine.models import Model + from cassandra.cqlengine.usertype import UserType + + class address(UserType): + street = Text() + zipcode = Integer() + + class users(Model): + __keyspace__ = 'account' + name = Text(primary_key=True) + addr = UserDefinedType(address) + + users.create(name="Joe", addr=address(street="Easy St.", zipcode=99999)) + user = users.objects(name="Joe")[0] + print user.name, user.addr + # Joe address(street=u'Easy St.', zipcode=99999) + +UDTs are modeled by inheriting :class:`~.usertype.UserType`, and setting column type attributes. Types are then used in defining +models by declaring a column of type :class:`~.columns.UserDefinedType`, with the ``UserType`` class as a parameter. + +``sync_table`` will implicitly +synchronize any types contained in the table. Alternatively :func:`~.management.sync_type` can be used to create/alter types +explicitly. + +Upon declaration, types are automatically registered with the driver, so query results return instances of your ``UserType`` +class*. + +***Note**: UDTs were not added to the native protocol until v3. When setting up the cqlengine connection, be sure to specify +``protocol_version=3``. If using an earlier version, UDT queries will still work, but the returned type will be a namedtuple. diff --git a/3.26.2-scylla/_sources/cqlengine/queryset.rst.txt b/3.26.2-scylla/_sources/cqlengine/queryset.rst.txt new file mode 100644 index 0000000000..375ea22316 --- /dev/null +++ b/3.26.2-scylla/_sources/cqlengine/queryset.rst.txt @@ -0,0 +1,419 @@ +============== +Making Queries +============== + +.. module:: cqlengine.queryset + +Retrieving objects +================== +Once you've populated Cassandra with data, you'll probably want to retrieve some of it. This is accomplished with QuerySet objects. This section will describe how to use QuerySet objects to retrieve the data you're looking for. + +Retrieving all objects +---------------------- +The simplest query you can make is to return all objects from a table. + +This is accomplished with the ``.all()`` method, which returns a QuerySet of all objects in a table + +Using the Person example model, we would get all Person objects like this: + +.. code-block:: python + + all_objects = Person.objects.all() + +.. _retrieving-objects-with-filters: + +Retrieving objects with filters +------------------------------- +Typically, you'll want to query only a subset of the records in your database. + +That can be accomplished with the QuerySet's ``.filter(\*\*)`` method. + +For example, given the model definition: + +.. code-block:: python + + class Automobile(Model): + manufacturer = columns.Text(primary_key=True) + year = columns.Integer(primary_key=True) + model = columns.Text() + price = columns.Decimal() + options = columns.Set(columns.Text) + +...and assuming the Automobile table contains a record of every car model manufactured in the last 20 years or so, we can retrieve only the cars made by a single manufacturer like this: + + +.. code-block:: python + + q = Automobile.objects.filter(manufacturer='Tesla') + +You can also use the more convenient syntax: + +.. code-block:: python + + q = Automobile.objects(Automobile.manufacturer == 'Tesla') + +We can then further filter our query with another call to **.filter** + +.. code-block:: python + + q = q.filter(year=2012) + +*Note: all queries involving any filtering MUST define either an '=' or an 'in' relation to either a primary key column, or an indexed column.* + +Accessing objects in a QuerySet +=============================== + +There are several methods for getting objects out of a queryset + +* iterating over the queryset + .. code-block:: python + + for car in Automobile.objects.all(): + #...do something to the car instance + pass + +* list index + .. code-block:: python + + q = Automobile.objects.all() + q[0] #returns the first result + q[1] #returns the second result + + .. note:: + + * CQL does not support specifying a start position in it's queries. Therefore, accessing elements using array indexing will load every result up to the index value requested + * Using negative indices requires a "SELECT COUNT()" to be executed. This has a performance cost on large datasets. + +* list slicing + .. code-block:: python + + q = Automobile.objects.all() + q[1:] #returns all results except the first + q[1:9] #returns a slice of the results + + .. note:: + + * CQL does not support specifying a start position in it's queries. Therefore, accessing elements using array slicing will load every result up to the index value requested + * Using negative indices requires a "SELECT COUNT()" to be executed. This has a performance cost on large datasets. + +* calling :attr:`get() ` on the queryset + .. code-block:: python + + q = Automobile.objects.filter(manufacturer='Tesla') + q = q.filter(year=2012) + car = q.get() + + this returns the object matching the queryset + +* calling :attr:`first() ` on the queryset + .. code-block:: python + + q = Automobile.objects.filter(manufacturer='Tesla') + q = q.filter(year=2012) + car = q.first() + + this returns the first value in the queryset + +.. _query-filtering-operators: + +Filtering Operators +=================== + +:attr:`Equal To ` + +The default filtering operator. + +.. code-block:: python + + q = Automobile.objects.filter(manufacturer='Tesla') + q = q.filter(year=2012) #year == 2012 + +In addition to simple equal to queries, cqlengine also supports querying with other operators by appending a ``__`` to the field name on the filtering call + +:attr:`in (__in) ` + +.. code-block:: python + + q = Automobile.objects.filter(manufacturer='Tesla') + q = q.filter(year__in=[2011, 2012]) + + +:attr:`> (__gt) ` + +.. code-block:: python + + q = Automobile.objects.filter(manufacturer='Tesla') + q = q.filter(year__gt=2010) # year > 2010 + + # or the nicer syntax + + q.filter(Automobile.year > 2010) + +:attr:`>= (__gte) ` + +.. code-block:: python + + q = Automobile.objects.filter(manufacturer='Tesla') + q = q.filter(year__gte=2010) # year >= 2010 + + # or the nicer syntax + + q.filter(Automobile.year >= 2010) + +:attr:`< (__lt) ` + +.. code-block:: python + + q = Automobile.objects.filter(manufacturer='Tesla') + q = q.filter(year__lt=2012) # year < 2012 + + # or... + + q.filter(Automobile.year < 2012) + +:attr:`<= (__lte) ` + +.. code-block:: python + + q = Automobile.objects.filter(manufacturer='Tesla') + q = q.filter(year__lte=2012) # year <= 2012 + + q.filter(Automobile.year <= 2012) + +:attr:`CONTAINS (__contains) ` + +The CONTAINS operator is available for all collection types (List, Set, Map). + +.. code-block:: python + + q = Automobile.objects.filter(manufacturer='Tesla') + q.filter(options__contains='backup camera').allow_filtering() + +Note that we need to use allow_filtering() since the *options* column has no secondary index. + +:attr:`LIKE (__like) ` + +The LIKE operator is available for text columns that have a SASI secondary index. + +.. code-block:: python + + q = Automobile.objects.filter(model__like='%Civic%').allow_filtering() + +:attr:`IS NOT NULL (IsNotNull(column_name)) ` + +The IS NOT NULL operator is not yet supported for C*. + +.. code-block:: python + + q = Automobile.objects.filter(IsNotNull('model')) + +Limitations: + +- Currently, cqlengine does not support SASI index creation. To use this feature, you need to create the SASI index using the core driver. +- Queries using LIKE must use allow_filtering() since the *model* column has no standard secondary index. Note that the server will use the SASI index properly when executing the query. + +TimeUUID Functions +================== + +In addition to querying using regular values, there are two functions you can pass in when querying TimeUUID columns to help make filtering by them easier. Note that these functions don't actually return a value, but instruct the cql interpreter to use the functions in it's query. + +.. class:: MinTimeUUID(datetime) + + returns the minimum time uuid value possible for the given datetime + +.. class:: MaxTimeUUID(datetime) + + returns the maximum time uuid value possible for the given datetime + +*Example* + +.. code-block:: python + + class DataStream(Model): + id = columns.UUID(partition_key=True) + time = columns.TimeUUID(primary_key=True) + data = columns.Bytes() + + min_time = datetime(1982, 1, 1) + max_time = datetime(1982, 3, 9) + + DataStream.filter(time__gt=functions.MinTimeUUID(min_time), time__lt=functions.MaxTimeUUID(max_time)) + +Token Function +============== + +Token functon may be used only on special, virtual column pk__token, representing token of partition key (it also works for composite partition keys). +Cassandra orders returned items by value of partition key token, so using cqlengine.Token we can easy paginate through all table rows. + +See http://cassandra.apache.org/doc/cql3/CQL-3.0.html#tokenFun + +*Example* + +.. code-block:: python + + class Items(Model): + id = columns.Text(primary_key=True) + data = columns.Bytes() + + query = Items.objects.all().limit(10) + + first_page = list(query); + last = first_page[-1] + next_page = list(query.filter(pk__token__gt=cqlengine.Token(last.pk))) + +QuerySets are immutable +======================= + +When calling any method that changes a queryset, the method does not actually change the queryset object it's called on, but returns a new queryset object with the attributes of the original queryset, plus the attributes added in the method call. + +*Example* + +.. code-block:: python + + #this produces 3 different querysets + #q does not change after it's initial definition + q = Automobiles.objects.filter(year=2012) + tesla2012 = q.filter(manufacturer='Tesla') + honda2012 = q.filter(manufacturer='Honda') + +Ordering QuerySets +================== + +Since Cassandra is essentially a distributed hash table on steroids, the order you get records back in will not be particularly predictable. + +However, you can set a column to order on with the ``.order_by(column_name)`` method. + +*Example* + +.. code-block:: python + + #sort ascending + q = Automobiles.objects.all().order_by('year') + #sort descending + q = Automobiles.objects.all().order_by('-year') + +*Note: Cassandra only supports ordering on a clustering key. In other words, to support ordering results, your model must have more than one primary key, and you must order on a primary key, excluding the first one.* + +*For instance, given our Automobile model, year is the only column we can order on.* + +Values Lists +============ + +There is a special QuerySet's method ``.values_list()`` - when called, QuerySet returns lists of values instead of model instances. It may significantly speedup things with lower memory footprint for large responses. +Each tuple contains the value from the respective field passed into the ``values_list()`` call — so the first item is the first field, etc. For example: + +.. code-block:: python + + items = list(range(20)) + random.shuffle(items) + for i in items: + TestModel.create(id=1, clustering_key=i) + + values = list(TestModel.objects.values_list('clustering_key', flat=True)) + # [19L, 18L, 17L, 16L, 15L, 14L, 13L, 12L, 11L, 10L, 9L, 8L, 7L, 6L, 5L, 4L, 3L, 2L, 1L, 0L] + +Per Query Timeouts +=================== + +By default all queries are executed with the timeout defined in `~cqlengine.connection.setup()` +The examples below show how to specify a per-query timeout. +A timeout is specified in seconds and can be an int, float or None. +None means no timeout. + + +.. code-block:: python + + class Row(Model): + id = columns.Integer(primary_key=True) + name = columns.Text() + + +Fetch all objects with a timeout of 5 seconds + +.. code-block:: python + + Row.objects().timeout(5).all() + +Create a single row with a 50ms timeout + +.. code-block:: python + + Row(id=1, name='Jon').timeout(0.05).create() + +Delete a single row with no timeout + +.. code-block:: python + + Row(id=1).timeout(None).delete() + +Update a single row with no timeout + +.. code-block:: python + + Row(id=1).timeout(None).update(name='Blake') + +Batch query timeouts + +.. code-block:: python + + with BatchQuery(timeout=10) as b: + Row(id=1, name='Jon').create() + + +NOTE: You cannot set both timeout and batch at the same time, batch will use the timeout defined in it's constructor. +Setting the timeout on the model is meaningless and will raise an AssertionError. + + +.. _ttl-change: + +Default TTL and Per Query TTL +============================= + +Model default TTL now relies on the *default_time_to_live* feature, introduced in Cassandra 2.0. It is not handled anymore in the CQLEngine Model (scylla-driver >=3.6). You can set the default TTL of a table like this: + +Example: + +.. code-block:: python + + class User(Model): + __options__ = {'default_time_to_live': 20} + + user_id = columns.UUID(primary_key=True) + ... + +You can set TTL per-query if needed. Here are a some examples: + +Example: + +.. code-block:: python + + class User(Model): + __options__ = {'default_time_to_live': 20} + + user_id = columns.UUID(primary_key=True) + ... + + user = User.objects.create(user_id=1) # Default TTL 20 will be set automatically on the server + + user.ttl(30).update(age=21) # Update the TTL to 30 + User.objects.ttl(10).create(user_id=1) # TTL 10 + User(user_id=1, age=21).ttl(10).save() # TTL 10 + + +Named Tables +=================== + +Named tables are a way of querying a table without creating an class. They're useful for querying system tables or exploring an unfamiliar database. + + +.. code-block:: python + + from cassandra.cqlengine.connection import setup + setup("127.0.0.1", "cqlengine_test") + + from cassandra.cqlengine.named import NamedTable + user = NamedTable("cqlengine_test", "user") + user.objects() + user.objects()[0] + + # {u'pk': 1, u't': datetime.datetime(2014, 6, 26, 17, 10, 31, 774000)} diff --git a/3.26.2-scylla/_sources/cqlengine/third-party.rst.txt b/3.26.2-scylla/_sources/cqlengine/third-party.rst.txt new file mode 100644 index 0000000000..20c26df304 --- /dev/null +++ b/3.26.2-scylla/_sources/cqlengine/third-party.rst.txt @@ -0,0 +1,64 @@ +======================== +Third party integrations +======================== + + +Celery +------ + +Here's how, in substance, CQLengine can be plugged to `Celery +`_: + +.. code-block:: python + + from celery import Celery + from celery.signals import worker_process_init, beat_init + from cassandra.cqlengine import connection + from cassandra.cqlengine.connection import ( + cluster as cql_cluster, session as cql_session) + + def cassandra_init(**kwargs): + """ Initialize a clean Cassandra connection. """ + if cql_cluster is not None: + cql_cluster.shutdown() + if cql_session is not None: + cql_session.shutdown() + connection.setup() + + # Initialize worker context for both standard and periodic tasks. + worker_process_init.connect(cassandra_init) + beat_init.connect(cassandra_init) + + app = Celery() + + +uWSGI +----- + +This is the code required for proper connection handling of CQLengine for a +`uWSGI `_-run application: + +.. code-block:: python + + from cassandra.cqlengine import connection + from cassandra.cqlengine.connection import ( + cluster as cql_cluster, session as cql_session) + + try: + from uwsgidecorators import postfork + except ImportError: + # We're not in a uWSGI context, no need to hook Cassandra session + # initialization to the postfork event. + pass + else: + @postfork + def cassandra_init(**kwargs): + """ Initialize a new Cassandra session in the context. + + Ensures that a new session is returned for every new request. + """ + if cql_cluster is not None: + cql_cluster.shutdown() + if cql_session is not None: + cql_session.shutdown() + connection.setup() diff --git a/3.26.2-scylla/_sources/cqlengine/upgrade-guide.rst.txt b/3.26.2-scylla/_sources/cqlengine/upgrade-guide.rst.txt new file mode 100644 index 0000000000..5a10ebb757 --- /dev/null +++ b/3.26.2-scylla/_sources/cqlengine/upgrade-guide.rst.txt @@ -0,0 +1,155 @@ +======================== +Upgrade Guide +======================== + +This is an overview of things that changed as the cqlengine project was merged into +scylla-driver. While efforts were taken to preserve the API and most functionality exactly, +conversion to this package will still require certain minimal updates (namely, imports). + +**THERE IS ONE FUNCTIONAL CHANGE**, described in the first section below. + +Functional Changes +================== +List Prepend Reversing +---------------------- +Legacy cqlengine included a workaround for a Cassandra bug in which prepended list segments were +reversed (`CASSANDRA-8733 `_). As of +this integration, this workaround is removed. The first released integrated version emits +a warning when prepend is used. Subsequent versions will have this warning removed. + +Date Column Type +---------------- +The Date column type in legacy cqlengine used a ``timestamp`` CQL type and truncated the time. +Going forward, the :class:`~.columns.Date` type represents a ``date`` for Cassandra 2.2+ +(`PYTHON-245 `_). +Users of the legacy functionality should convert models to use :class:`~.columns.DateTime` (which +uses ``timestamp`` internally), and use the build-in ``datetime.date`` for input values. + +Remove cqlengine +================ +To avoid confusion or mistakes using the legacy package in your application, it +is prudent to remove the cqlengine package when upgrading to the integrated version. + +The driver setup script will warn if the legacy package is detected during install, +but it will not prevent side-by-side installation. + +Organization +============ +Imports +------- +cqlengine is now integrated as a sub-package of the driver base package 'cassandra'. +Upgrading will require adjusting imports to cqlengine. For example:: + + from cassandra.cqlengine import columns + +is now:: + + from cassandra.cqlengine import columns + +Package-Level Aliases +--------------------- +Legacy cqlengine defined a number of aliases at the package level, which became redundant +when the package was integrated for a driver. These have been removed in favor of absolute +imports, and referring to cannonical definitions. For example, ``cqlengine.ONE`` was an alias +of ``cassandra.ConsistencyLevel.ONE``. In the integrated package, only the +:class:`cassandra.ConsistencyLevel` remains. + +Additionally, submodule aliases are removed from cqlengine in favor of absolute imports. + +These aliases are removed, and not deprecated because they should be straightforward to iron out +at module load time. + +Exceptions +---------- +The legacy cqlengine.exceptions module had a number of Exception classes that were variously +common to the package, or only used in specific modules. Common exceptions were relocated to +cqlengine, and specialized exceptions were placed in the module that raises them. Below is a +listing of updated locations: + +============================ ========== +Exception class New module +============================ ========== +CQLEngineException cassandra.cqlengine +ModelException cassandra.cqlengine.models +ValidationError cassandra.cqlengine +UndefinedKeyspaceException cassandra.cqlengine.connection +LWTException cassandra.cqlengine.query +IfNotExistsWithCounterColumn cassandra.cqlengine.query +============================ ========== + +UnicodeMixin Consolidation +-------------------------- +``class UnicodeMixin`` was defined in several cqlengine modules. This has been consolidated +to a single definition in the cqlengine package init file. This is not technically part of +the API, but noted here for completeness. + +API Deprecations +================ +This upgrade served as a good juncture to deprecate certain API features and invite users to upgrade +to new ones. The first released version does not change functionality -- only introduces deprecation +warnings. Future releases will remove these features in favor of the alternatives. + +Float/Double Overload +--------------------- +Previously there was no ``Double`` column type. Doubles were modeled by specifying ``Float(double_precision=True)``. +This inititializer parameter is now deprecated. Applications should use :class:`~.columns.Double` for CQL ``double``, and :class:`~.columns.Float` +for CQL ``float``. + +Schema Management +----------------- +``cassandra.cqlengine.management.create_keyspace`` is deprecated. Instead, use the new replication-strategy-specific +functions that accept explicit options for known strategies: + +- :func:`~.create_keyspace_simple` +- :func:`~.create_keyspace_network_topology` + +``cassandra.cqlengine.management.delete_keyspace`` is deprecated in favor of a new function, :func:`~.drop_keyspace`. The +intent is simply to make the function match the CQL verb it invokes. + +Model Inheritance +----------------- +The names for class attributes controlling model inheritance are changing. Changes are as follows: + +- Replace 'polymorphic_key' in the base class Column definition with :attr:`~.discriminator_column` +- Replace the '__polymorphic_key__' class attribute the derived classes with :attr:`~.__discriminator_value__` + +The functionality is unchanged -- the intent here is to make the names and language around these attributes more precise. +For now, the old names are just deprecated, and the mapper will emit warnings if they are used. The old names +will be removed in a future version. + +The example below shows a simple translation: + +Before:: + + class Pet(Model): + __table_name__ = 'pet' + owner_id = UUID(primary_key=True) + pet_id = UUID(primary_key=True) + pet_type = Text(polymorphic_key=True) + name = Text() + + class Cat(Pet): + __polymorphic_key__ = 'cat' + + class Dog(Pet): + __polymorphic_key__ = 'dog' + +After:: + + class Pet(models.Model): + __table_name__ = 'pet' + owner_id = UUID(primary_key=True) + pet_id = UUID(primary_key=True) + pet_type = Text(discriminator_column=True) + name = Text() + + class Cat(Pet): + __discriminator_value__ = 'cat' + + class Dog(Pet): + __discriminator_value__ = 'dog' + + +TimeUUID.from_datetime +---------------------- +This function is deprecated in favor of the core utility function :func:`~.uuid_from_time`. diff --git a/3.26.2-scylla/_sources/dates-and-times.rst.txt b/3.26.2-scylla/_sources/dates-and-times.rst.txt new file mode 100644 index 0000000000..7a89f77437 --- /dev/null +++ b/3.26.2-scylla/_sources/dates-and-times.rst.txt @@ -0,0 +1,87 @@ +Working with Dates and Times +============================ + +This document is meant to provide on overview of the assumptions and limitations of the driver time handling, the +reasoning behind it, and describe approaches to working with these types. + +timestamps (Cassandra DateType) +------------------------------- + +Timestamps in Cassandra are timezone-naive timestamps encoded as millseconds since UNIX epoch. Clients working with +timestamps in this database usually find it easiest to reason about them if they are always assumed to be UTC. To quote the +pytz documentation, "The preferred way of dealing with times is to always work in UTC, converting to localtime only when +generating output to be read by humans." The driver adheres to this tenant, and assumes UTC is always in the database. The +driver attempts to make this correct on the way in, and assumes no timezone on the way out. + +Write Path +~~~~~~~~~~ +When inserting timestamps, the driver handles serialization for the write path as follows: + +If the input is a ``datetime.datetime``, the serialization is normalized by starting with the ``utctimetuple()`` of the +value. + +- If the ``datetime`` object is timezone-aware, the timestamp is shifted, and represents the UTC timestamp equivalent. +- If the ``datetime`` object is timezone-naive, this results in no shift -- any ``datetime`` with no timezone information is assumed to be UTC + +Note the second point above applies even to "local" times created using ``now()``:: + + >>> d = datetime.now() + + >>> print(d.tzinfo) + None + + +These do not contain timezone information intrinsically, so they will be assumed to be UTC and not shifted. When generating +timestamps in the application, it is clearer to use ``datetime.utcnow()`` to be explicit about it. + +If the input for a timestamp is numeric, it is assumed to be a epoch-relative millisecond timestamp, as specified in the +CQL spec -- no scaling or conversion is done. + +Read Path +~~~~~~~~~ +The driver always assumes persisted timestamps are UTC and makes no attempt to localize them. Returned values are +timezone-naive ``datetime.datetime``. We follow this approach because the datetime API has deficiencies around daylight +saving time, and the defacto package for handling this is a third-party package (we try to minimize external dependencies +and not make decisions for the integrator). + +The decision for how to handle timezones is left to the application. For the most part it is straightforward to apply +localization to the ``datetime``\s returned by queries. One prevalent method is to use pytz for localization:: + + import pytz + user_tz = pytz.timezone('US/Central') + timestamp_naive = row.ts + timestamp_utc = pytz.utc.localize(timestamp_naive) + timestamp_presented = timestamp_utc.astimezone(user_tz) + +This is the most robust approach (likely refactored into a function). If it is deemed too cumbersome to apply for all call +sites in the application, it is possible to patch the driver with custom deserialization for this type. However, doing +this depends depends some on internal APIs and what extensions are present, so we will only mention the possibility, and +not spell it out here. + +date, time (Cassandra DateType) +------------------------------- +Date and time in Cassandra are idealized markers, much like ``datetime.date`` and ``datetime.time`` in the Python standard +library. Unlike these Python implementations, the Cassandra encoding supports much wider ranges. To accommodate these +ranges without overflow, this driver returns these data in custom types: :class:`.util.Date` and :class:`.util.Time`. + +Write Path +~~~~~~~~~~ +For simple (not prepared) statements, the input values for each of these can be either a string literal or an encoded +integer. See `Working with dates `_ +or `Working with time `_ for details +on the encoding or string formats. + +For prepared statements, the driver accepts anything that can be used to construct the :class:`.util.Date` or +:class:`.util.Time` classes. See the linked API docs for details. + +Read Path +~~~~~~~~~ +The driver always returns custom types for ``date`` and ``time``. + +The driver returns :class:`.util.Date` for ``date`` in order to accommodate the wider range of values without overflow. +For applications working within the supported range of [``datetime.MINYEAR``, ``datetime.MAXYEAR``], these are easily +converted to standard ``datetime.date`` insances using :meth:`.Date.date`. + +The driver returns :class:`.util.Time` for ``time`` in order to retain nanosecond precision stored in the database. +For applications not concerned with this level of precision, these are easily converted to standard ``datetime.time`` +insances using :meth:`.Time.time`. diff --git a/3.26.2-scylla/_sources/execution-profiles.rst.txt b/3.26.2-scylla/_sources/execution-profiles.rst.txt new file mode 100644 index 0000000000..7be1a85e3f --- /dev/null +++ b/3.26.2-scylla/_sources/execution-profiles.rst.txt @@ -0,0 +1,156 @@ +Execution Profiles +================== + +Execution profiles aim at making it easier to execute requests in different ways within +a single connected ``Session``. Execution profiles are being introduced to deal with the exploding number of +configuration options, especially as the database platform evolves more complex workloads. + +The legacy configuration remains intact, but legacy and Execution Profile APIs +cannot be used simultaneously on the same client ``Cluster``. Legacy configuration +will be removed in the next major release (4.0). + +An execution profile and its parameters should be unique across ``Cluster`` instances. +For example, an execution profile and its ``LoadBalancingPolicy`` should +not be applied to more than one ``Cluster`` instance. + +This document explains how Execution Profiles relate to existing settings, and shows how to use the new profiles for +request execution. + +Mapping Legacy Parameters to Profiles +------------------------------------- + +Execution profiles can inherit from :class:`.cluster.ExecutionProfile`, and currently provide the following options, +previously input from the noted attributes: + +- load_balancing_policy - :attr:`.Cluster.load_balancing_policy` +- request_timeout - :attr:`.Session.default_timeout`, optional :meth:`.Session.execute` parameter +- retry_policy - :attr:`.Cluster.default_retry_policy`, optional :attr:`.Statement.retry_policy` attribute +- consistency_level - :attr:`.Session.default_consistency_level`, optional :attr:`.Statement.consistency_level` attribute +- serial_consistency_level - :attr:`.Session.default_serial_consistency_level`, optional :attr:`.Statement.serial_consistency_level` attribute +- row_factory - :attr:`.Session.row_factory` attribute + +When using the new API, these parameters can be defined by instances of :class:`.cluster.ExecutionProfile`. + +Using Execution Profiles +------------------------ +Default +~~~~~~~ + +.. code:: python + + from cassandra.cluster import Cluster + cluster = Cluster() + session = cluster.connect() + local_query = 'SELECT rpc_address FROM system.local' + for _ in cluster.metadata.all_hosts(): + print session.execute(local_query)[0] + + +.. parsed-literal:: + + Row(rpc_address='127.0.0.2') + Row(rpc_address='127.0.0.1') + + +The default execution profile is built from Cluster parameters and default Session attributes. This profile matches existing default +parameters. + +Initializing cluster with profiles +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. code:: python + + from cassandra.cluster import ExecutionProfile + from cassandra.policies import WhiteListRoundRobinPolicy + + node1_profile = ExecutionProfile(load_balancing_policy=WhiteListRoundRobinPolicy(['127.0.0.1'])) + node2_profile = ExecutionProfile(load_balancing_policy=WhiteListRoundRobinPolicy(['127.0.0.2'])) + + profiles = {'node1': node1_profile, 'node2': node2_profile} + session = Cluster(execution_profiles=profiles).connect() + for _ in cluster.metadata.all_hosts(): + print session.execute(local_query, execution_profile='node1')[0] + + +.. parsed-literal:: + + Row(rpc_address='127.0.0.1') + Row(rpc_address='127.0.0.1') + + +.. code:: python + + for _ in cluster.metadata.all_hosts(): + print session.execute(local_query, execution_profile='node2')[0] + + +.. parsed-literal:: + + Row(rpc_address='127.0.0.2') + Row(rpc_address='127.0.0.2') + + +.. code:: python + + for _ in cluster.metadata.all_hosts(): + print session.execute(local_query)[0] + + +.. parsed-literal:: + + Row(rpc_address='127.0.0.2') + Row(rpc_address='127.0.0.1') + +Note that, even when custom profiles are injected, the default ``TokenAwarePolicy(DCAwareRoundRobinPolicy())`` is still +present. To override the default, specify a policy with the :data:`~.cluster.EXEC_PROFILE_DEFAULT` key. + +.. code:: python + + from cassandra.cluster import EXEC_PROFILE_DEFAULT + profile = ExecutionProfile(request_timeout=30) + cluster = Cluster(execution_profiles={EXEC_PROFILE_DEFAULT: profile}) + + +Adding named profiles +~~~~~~~~~~~~~~~~~~~~~ + +New profiles can be added constructing from scratch, or deriving from default: + +.. code:: python + + locked_execution = ExecutionProfile(load_balancing_policy=WhiteListRoundRobinPolicy(['127.0.0.1'])) + node1_profile = 'node1_whitelist' + cluster.add_execution_profile(node1_profile, locked_execution) + + for _ in cluster.metadata.all_hosts(): + print session.execute(local_query, execution_profile=node1_profile)[0] + + +.. parsed-literal:: + + Row(rpc_address='127.0.0.1') + Row(rpc_address='127.0.0.1') + +See :meth:`.Cluster.add_execution_profile` for details and optional parameters. + +Passing a profile instance without mapping +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +We also have the ability to pass profile instances to be used for execution, but not added to the mapping: + +.. code:: python + + from cassandra.query import tuple_factory + + tmp = session.execution_profile_clone_update('node1', request_timeout=100, row_factory=tuple_factory) + + print session.execute(local_query, execution_profile=tmp)[0] + print session.execute(local_query, execution_profile='node1')[0] + +.. parsed-literal:: + + ('127.0.0.1',) + Row(rpc_address='127.0.0.1') + +The new profile is a shallow copy, so the ``tmp`` profile shares a load balancing policy with one managed by the cluster. +If reference objects are to be updated in the clone, one would typically set those attributes to a new instance. diff --git a/3.26.2-scylla/_sources/faq.rst.txt b/3.26.2-scylla/_sources/faq.rst.txt new file mode 100644 index 0000000000..56cb648a24 --- /dev/null +++ b/3.26.2-scylla/_sources/faq.rst.txt @@ -0,0 +1,83 @@ +Frequently Asked Questions +========================== + +See also :doc:`cqlengine FAQ ` + +Why do connections or IO operations timeout in my WSGI application? +------------------------------------------------------------------- +Depending on your application process model, it may be forking after driver Session is created. Most IO reactors do not handle this, and problems will manifest as timeouts. + +To avoid this, make sure to create sessions per process, after the fork. Using uWSGI and Flask for example: + +.. code-block:: python + + from flask import Flask + from uwsgidecorators import postfork + from cassandra.cluster import Cluster + + session = None + prepared = None + + @postfork + def connect(): + global session, prepared + session = Cluster().connect() + prepared = session.prepare("SELECT release_version FROM system.local WHERE key=?") + + app = Flask(__name__) + + @app.route('/') + def server_version(): + row = session.execute(prepared, ('local',))[0] + return row.release_version + +uWSGI provides a ``postfork`` hook you can use to create sessions and prepared statements after the child process forks. + +How do I trace a request? +------------------------- +Request tracing can be turned on for any request by setting ``trace=True`` in :meth:`.Session.execute_async`. View the results by waiting on the future, then :meth:`.ResponseFuture.get_query_trace`. +Since tracing is done asynchronously to the request, this method polls until the trace is complete before querying data. + +.. code-block:: python + + >>> future = session.execute_async("SELECT * FROM system.local", trace=True) + >>> result = future.result() + >>> trace = future.get_query_trace() + >>> for e in trace.events: + >>> print e.source_elapsed, e.description + + 0:00:00.000077 Parsing select * from system.local + 0:00:00.000153 Preparing statement + 0:00:00.000309 Computing ranges to query + 0:00:00.000368 Submitting range requests on 1 ranges with a concurrency of 1 (279.77142 rows per range expected) + 0:00:00.000422 Submitted 1 concurrent range requests covering 1 ranges + 0:00:00.000480 Executing seq scan across 1 sstables for (min(-9223372036854775808), min(-9223372036854775808)) + 0:00:00.000669 Read 1 live and 0 tombstone cells + 0:00:00.000755 Scanned 1 rows and matched 1 + +``trace`` is a :class:`QueryTrace` object. + +How do I determine the replicas for a query? +---------------------------------------------- +With prepared statements, the replicas are obtained by ``routing_key``, based on current cluster token metadata: + +.. code-block:: python + + >>> prepared = session.prepare("SELECT * FROM example.t WHERE key=?") + >>> bound = prepared.bind((1,)) + >>> replicas = cluster.metadata.get_replicas(bound.keyspace, bound.routing_key) + >>> for h in replicas: + >>> print h.address + 127.0.0.1 + 127.0.0.2 + +``replicas`` is a list of :class:`Host` objects. + +How does the driver manage request retries? +------------------------------------------- +By default, retries are managed by the :attr:`.Cluster.default_retry_policy` set on the session Cluster. It can also +be specialized per statement by setting :attr:`.Statement.retry_policy`. + +Retries are presently attempted on the same coordinator, but this may change in the future. + +Please see :class:`.policies.RetryPolicy` for further details. diff --git a/3.26.2-scylla/_sources/getting-started.rst.txt b/3.26.2-scylla/_sources/getting-started.rst.txt new file mode 100644 index 0000000000..59a2acbd04 --- /dev/null +++ b/3.26.2-scylla/_sources/getting-started.rst.txt @@ -0,0 +1,479 @@ +Getting Started +=============== + +First, make sure you have the driver properly :doc:`installed `. + +Connecting to a Cluster +----------------------- +Before we can start executing any queries against a Cassandra cluster we need to setup +an instance of :class:`~.Cluster`. As the name suggests, you will typically have one +instance of :class:`~.Cluster` for each Cassandra cluster you want to interact +with. + +First, make sure you have the Cassandra driver properly :doc:`installed `. + +Connecting to Cassandra ++++++++++++++++++++++++ +The simplest way to create a :class:`~.Cluster` is like this: + +.. code-block:: python + + from cassandra.cluster import Cluster + + cluster = Cluster() + +This will attempt to connection to a Cassandra instance on your +local machine (127.0.0.1). You can also specify a list of IP +addresses for nodes in your cluster: + +.. code-block:: python + + from cassandra.cluster import Cluster + + cluster = Cluster(['192.168.0.1', '192.168.0.2']) + +The set of IP addresses we pass to the :class:`~.Cluster` is simply +an initial set of contact points. After the driver connects to one +of these nodes it will *automatically discover* the rest of the +nodes in the cluster and connect to them, so you don't need to list +every node in your cluster. + +If you need to use a non-standard port, use SSL, or customize the driver's +behavior in some other way, this is the place to do it: + +.. code-block:: python + + from cassandra.cluster import Cluster + cluster = Cluster(['192.168.0.1', '192.168.0.2'], port=..., ssl_context=...) + +Instantiating a :class:`~.Cluster` does not actually connect us to any nodes. +To establish connections and begin executing queries we need a +:class:`~.Session`, which is created by calling :meth:`.Cluster.connect()`: + +.. code-block:: python + + cluster = Cluster() + session = cluster.connect() + +Session Keyspace +---------------- +The :meth:`~.Cluster.connect()` method takes an optional ``keyspace`` argument +which sets the default keyspace for all queries made through that :class:`~.Session`: + +.. code-block:: python + + cluster = Cluster() + session = cluster.connect('mykeyspace') + +You can always change a Session's keyspace using :meth:`~.Session.set_keyspace` or +by executing a ``USE `` query: + +.. code-block:: python + + session.set_keyspace('users') + # or you can do this instead + session.execute('USE users') + +Execution Profiles +------------------ +Profiles are passed in by ``execution_profiles`` dict. + +In this case we can construct the base ``ExecutionProfile`` passing all attributes: + +.. code-block:: python + + from cassandra.cluster import Cluster, ExecutionProfile, EXEC_PROFILE_DEFAULT + from cassandra.policies import WhiteListRoundRobinPolicy, DowngradingConsistencyRetryPolicy + from cassandra.query import tuple_factory + + profile = ExecutionProfile( + load_balancing_policy=WhiteListRoundRobinPolicy(['127.0.0.1']), + retry_policy=DowngradingConsistencyRetryPolicy(), + consistency_level=ConsistencyLevel.LOCAL_QUORUM, + serial_consistency_level=ConsistencyLevel.LOCAL_SERIAL, + request_timeout=15, + row_factory=tuple_factory + ) + cluster = Cluster(execution_profiles={EXEC_PROFILE_DEFAULT: profile}) + session = cluster.connect() + + print(session.execute("SELECT release_version FROM system.local").one()) + +Users are free to setup additional profiles to be used by name: + +.. code-block:: python + + profile_long = ExecutionProfile(request_timeout=30) + cluster = Cluster(execution_profiles={'long': profile_long}) + session = cluster.connect() + session.execute(statement, execution_profile='long') + +Also, parameters passed to ``Session.execute`` or attached to ``Statement``\s are still honored as before. + +Executing Queries +----------------- +Now that we have a :class:`.Session` we can begin to execute queries. The simplest +way to execute a query is to use :meth:`~.Session.execute()`: + +.. code-block:: python + + rows = session.execute('SELECT name, age, email FROM users') + for user_row in rows: + print user_row.name, user_row.age, user_row.email + +This will transparently pick a Cassandra node to execute the query against +and handle any retries that are necessary if the operation fails. + +By default, each row in the result set will be a +`namedtuple `_. +Each row will have a matching attribute for each column defined in the schema, +such as ``name``, ``age``, and so on. You can also treat them as normal tuples +by unpacking them or accessing fields by position. The following three +examples are equivalent: + +.. code-block:: python + + rows = session.execute('SELECT name, age, email FROM users') + for row in rows: + print row.name, row.age, row.email + +.. code-block:: python + + rows = session.execute('SELECT name, age, email FROM users') + for (name, age, email) in rows: + print name, age, email + +.. code-block:: python + + rows = session.execute('SELECT name, age, email FROM users') + for row in rows: + print row[0], row[1], row[2] + +If you prefer another result format, such as a ``dict`` per row, you +can change the :attr:`~.Session.row_factory` attribute. + +As mentioned in our `Drivers Best Practices Guide `_, +it is highly recommended to use `Prepared statements <#prepared-statement>`_ for your +frequently run queries. + +.. _prepared-statement: + +Prepared Statements +------------------- +Prepared statements are queries that are parsed by Cassandra and then saved +for later use. When the driver uses a prepared statement, it only needs to +send the values of parameters to bind. This lowers network traffic +and CPU utilization within Cassandra because Cassandra does not have to +re-parse the query each time. + +To prepare a query, use :meth:`.Session.prepare()`: + +.. code-block:: python + + user_lookup_stmt = session.prepare("SELECT * FROM users WHERE user_id=?") + + users = [] + for user_id in user_ids_to_query: + user = session.execute(user_lookup_stmt, [user_id]) + users.append(user) + +:meth:`~.Session.prepare()` returns a :class:`~.PreparedStatement` instance +which can be used in place of :class:`~.SimpleStatement` instances or literal +string queries. It is automatically prepared against all nodes, and the driver +handles re-preparing against new nodes and restarted nodes when necessary. + +Note that the placeholders for prepared statements are ``?`` characters. This +is different than for simple, non-prepared statements (although future versions +of the driver may use the same placeholders for both). + +Passing Parameters to CQL Queries +--------------------------------- +Althought it is not recommended, you can also pass parameters to non-prepared +statements. The driver supports two forms of parameter place-holders: positional +and named. + +Positional parameters are used with a ``%s`` placeholder. For example, +when you execute: + +.. code-block:: python + + session.execute( + """ + INSERT INTO users (name, credits, user_id) + VALUES (%s, %s, %s) + """, + ("John O'Reilly", 42, uuid.uuid1()) + ) + +It is translated to the following CQL query:: + + INSERT INTO users (name, credits, user_id) + VALUES ('John O''Reilly', 42, 2644bada-852c-11e3-89fb-e0b9a54a6d93) + +Note that you should use ``%s`` for all types of arguments, not just strings. +For example, this would be **wrong**: + +.. code-block:: python + + session.execute("INSERT INTO USERS (name, age) VALUES (%s, %d)", ("bob", 42)) # wrong + +Instead, use ``%s`` for the age placeholder. + +If you need to use a literal ``%`` character, use ``%%``. + +**Note**: you must always use a sequence for the second argument, even if you are +only passing in a single variable: + +.. code-block:: python + + session.execute("INSERT INTO foo (bar) VALUES (%s)", "blah") # wrong + session.execute("INSERT INTO foo (bar) VALUES (%s)", ("blah")) # wrong + session.execute("INSERT INTO foo (bar) VALUES (%s)", ("blah", )) # right + session.execute("INSERT INTO foo (bar) VALUES (%s)", ["blah"]) # right + + +Note that the second line is incorrect because in Python, single-element tuples +require a comma. + +Named place-holders use the ``%(name)s`` form: + +.. code-block:: python + + session.execute( + """ + INSERT INTO users (name, credits, user_id, username) + VALUES (%(name)s, %(credits)s, %(user_id)s, %(name)s) + """, + {'name': "John O'Reilly", 'credits': 42, 'user_id': uuid.uuid1()} + ) + +Note that you can repeat placeholders with the same name, such as ``%(name)s`` +in the above example. + +Only data values should be supplied this way. Other items, such as keyspaces, +table names, and column names should be set ahead of time (typically using +normal string formatting). + +.. _type-conversions: + +Type Conversions +---------------- +For non-prepared statements, Python types are cast to CQL literals in the +following way: + +.. table:: + + +--------------------+-------------------------+ + | Python Type | CQL Literal Type | + +====================+=========================+ + | ``None`` | ``NULL`` | + +--------------------+-------------------------+ + | ``bool`` | ``boolean`` | + +--------------------+-------------------------+ + | ``float`` | | ``float`` | + | | | ``double`` | + +--------------------+-------------------------+ + | | ``int`` | | ``int`` | + | | ``long`` | | ``bigint`` | + | | | ``varint`` | + | | | ``smallint`` | + | | | ``tinyint`` | + | | | ``counter`` | + +--------------------+-------------------------+ + | ``decimal.Decimal``| ``decimal`` | + +--------------------+-------------------------+ + | | ``str`` | | ``ascii`` | + | | ``unicode`` | | ``varchar`` | + | | | ``text`` | + +--------------------+-------------------------+ + | | ``buffer`` | ``blob`` | + | | ``bytearray`` | | + +--------------------+-------------------------+ + | ``date`` | ``date`` | + +--------------------+-------------------------+ + | ``datetime`` | ``timestamp`` | + +--------------------+-------------------------+ + | ``time`` | ``time`` | + +--------------------+-------------------------+ + | | ``list`` | ``list`` | + | | ``tuple`` | | + | | generator | | + +--------------------+-------------------------+ + | | ``set`` | ``set`` | + | | ``frozenset`` | | + +--------------------+-------------------------+ + | | ``dict`` | ``map`` | + | | ``OrderedDict`` | | + +--------------------+-------------------------+ + | ``uuid.UUID`` | | ``timeuuid`` | + | | | ``uuid`` | + +--------------------+-------------------------+ + + +Asynchronous Queries +-------------------- +The driver supports asynchronous query execution through +:meth:`~.Session.execute_async()`. Instead of waiting for the query to +complete and returning rows directly, this method almost immediately +returns a :class:`~.ResponseFuture` object. There are two ways of +getting the final result from this object. + +The first is by calling :meth:`~.ResponseFuture.result()` on it. If +the query has not yet completed, this will block until it has and +then return the result or raise an Exception if an error occurred. +For example: + +.. code-block:: python + + from cassandra import ReadTimeout + + query = "SELECT * FROM users WHERE user_id=%s" + future = session.execute_async(query, [user_id]) + + # ... do some other work + + try: + rows = future.result() + user = rows[0] + print user.name, user.age + except ReadTimeout: + log.exception("Query timed out:") + +This works well for executing many queries concurrently: + +.. code-block:: python + + # build a list of futures + futures = [] + query = "SELECT * FROM users WHERE user_id=%s" + for user_id in ids_to_fetch: + futures.append(session.execute_async(query, [user_id]) + + # wait for them to complete and use the results + for future in futures: + rows = future.result() + print rows[0].name + +Alternatively, instead of calling :meth:`~.ResponseFuture.result()`, +you can attach callback and errback functions through the +:meth:`~.ResponseFuture.add_callback()`, +:meth:`~.ResponseFuture.add_errback()`, and +:meth:`~.ResponseFuture.add_callbacks()`, methods. If you have used +Twisted Python before, this is designed to be a lightweight version of +that: + +.. code-block:: python + + def handle_success(rows): + user = rows[0] + try: + process_user(user.name, user.age, user.id) + except Exception: + log.error("Failed to process user %s", user.id) + # don't re-raise errors in the callback + + def handle_error(exception): + log.error("Failed to fetch user info: %s", exception) + + + future = session.execute_async(query) + future.add_callbacks(handle_success, handle_error) + +There are a few important things to remember when working with callbacks: + * **Exceptions that are raised inside the callback functions will be logged and then ignored.** + * Your callback will be run on the event loop thread, so any long-running + operations will prevent other requests from being handled + + +Setting a Consistency Level +--------------------------- +The consistency level used for a query determines how many of the +replicas of the data you are interacting with need to respond for +the query to be considered a success. + +By default, :attr:`.ConsistencyLevel.LOCAL_ONE` will be used for all queries. +You can specify a different default by setting the :attr:`.ExecutionProfile.consistency_level` +for the execution profile with key :data:`~.cluster.EXEC_PROFILE_DEFAULT`. +To specify a different consistency level per request, wrap queries +in a :class:`~.SimpleStatement`: + +.. code-block:: python + + from cassandra import ConsistencyLevel + from cassandra.query import SimpleStatement + + query = SimpleStatement( + "INSERT INTO users (name, age) VALUES (%s, %s)", + consistency_level=ConsistencyLevel.QUORUM) + session.execute(query, ('John', 42)) + +Setting a Consistency Level with Prepared Statements +---------------------------------------------------- +To specify a consistency level for prepared statements, you have two options. + +The first is to set a default consistency level for every execution of the +prepared statement: + +.. code-block:: python + + from cassandra import ConsistencyLevel + + cluster = Cluster() + session = cluster.connect("mykeyspace") + user_lookup_stmt = session.prepare("SELECT * FROM users WHERE user_id=?") + user_lookup_stmt.consistency_level = ConsistencyLevel.QUORUM + + # these will both use QUORUM + user1 = session.execute(user_lookup_stmt, [user_id1])[0] + user2 = session.execute(user_lookup_stmt, [user_id2])[0] + +The second option is to create a :class:`~.BoundStatement` from the +:class:`~.PreparedStatement` and binding parameters and set a consistency +level on that: + +.. code-block:: python + + # override the QUORUM default + user3_lookup = user_lookup_stmt.bind([user_id3]) + user3_lookup.consistency_level = ConsistencyLevel.ALL + user3 = session.execute(user3_lookup) + +Speculative Execution +--------------------- + +Speculative execution is a way to minimize latency by preemptively executing several +instances of the same query against different nodes. For more details about this +technique, see `Speculative Execution with DataStax Drivers `_. + +To enable speculative execution: + +* Configure a :class:`~.policies.SpeculativeExecutionPolicy` with the ExecutionProfile +* Mark your query as idempotent, which mean it can be applied multiple + times without changing the result of the initial application. + See `Query Idempotence `_ for more details. + + +Example: + +.. code-block:: python + + from cassandra.cluster import Cluster, ExecutionProfile, EXEC_PROFILE_DEFAULT + from cassandra.policies import ConstantSpeculativeExecutionPolicy + from cassandra.query import SimpleStatement + + # Configure the speculative execution policy + ep = ExecutionProfile( + speculative_execution_policy=ConstantSpeculativeExecutionPolicy(delay=.5, max_attempts=10) + ) + cluster = Cluster(..., execution_profiles={EXEC_PROFILE_DEFAULT: ep}) + session = cluster.connect() + + # Mark the query idempotent + query = SimpleStatement( + "UPDATE my_table SET list_col = [1] WHERE pk = 1", + is_idempotent=True + ) + + # Execute. A new query will be sent to the server every 0.5 second + # until we receive a response, for a max number attempts of 10. + session.execute(query) diff --git a/3.26.2-scylla/_sources/index.rst.txt b/3.26.2-scylla/_sources/index.rst.txt new file mode 100644 index 0000000000..c21d293b6f --- /dev/null +++ b/3.26.2-scylla/_sources/index.rst.txt @@ -0,0 +1,107 @@ +Python Driver for Scylla and Apache Cassandra® +============================================== +A Python client driver for `Scylla `_. +This driver works exclusively with the Cassandra Query Language v3 (CQL3) +and Cassandra's native protocol. + +The driver supports Python 2.7, 3.5, 3.6, 3.7 and 3.8. + +This driver is open source under the +`Apache v2 License `_. +The source code for this driver can be found on `GitHub `_. + +Scylla Driver is a fork from `DataStax Python Driver `_, including some non-breaking changes for Scylla optimization, with more updates planned. + +Contents +-------- +:doc:`installation` + How to install the driver. + +:doc:`getting-started` + A guide through the first steps of connecting to Scylla and executing queries + +:doc:`scylla-specific` + A list of feature available only on ``scylla-driver`` + +:doc:`execution-profiles` + An introduction to a more flexible way of configuring request execution + +:doc:`lwt` + Working with results of conditional requests + +:doc:`object-mapper` + Introduction to the integrated object mapper, cqlengine + +:doc:`performance` + Tips for getting good performance. + +:doc:`query-paging` + Notes on paging large query results + +:doc:`security` + An overview of the security features of the driver + +:doc:`upgrading` + A guide to upgrading versions of the driver + +:doc:`user-defined-types` + Working with Scylla's user-defined types (UDT) + +:doc:`dates-and-times` + Some discussion on the driver's approach to working with timestamp, date, time types + +:doc:`scylla-cloud` + Connect to ScyllaDB Cloud + +:doc:`scylla-cloud-serverless` + Connect to ScyllaDB Cloud Serverless + +:doc:`CHANGELOG` + Log of changes to the driver, organized by version. + +:doc:`faq` + A collection of Frequently Asked Questions + +:doc:`api/index` + The API documentation. + +.. toctree:: + :hidden: + + api/index + installation + getting-started + scylla-specific + upgrading + execution-profiles + performance + query-paging + lwt + security + user-defined-types + object-mapper + dates-and-times + scylla-cloud + scylla-cloud-serverless + faq + +Getting Help +------------ +Visit the :doc:`FAQ section ` in this documentation. + +Please send questions to the Scylla `user list `_. + + +Reporting Issues +---------------- + +Please report any bugs and make any feature requests on the `Github project issues `_ + + +Copyright +--------- + +© 2013-2017 DataStax + +© 2016, The Apache Software Foundation. +Apache®, Apache Cassandra®, Cassandra®, the Apache feather logo and the Apache Cassandra® Eye logo are either registered trademarks or trademarks of the Apache Software Foundation in the United States and/or other countries. No endorsement by The Apache Software Foundation is implied by the use of these marks. diff --git a/3.26.2-scylla/_sources/installation.rst.txt b/3.26.2-scylla/_sources/installation.rst.txt new file mode 100644 index 0000000000..4996a02c1b --- /dev/null +++ b/3.26.2-scylla/_sources/installation.rst.txt @@ -0,0 +1,234 @@ +Installation +============ + +Supported Platforms +------------------- +Python 2.7, 3.5, 3.6, 3.7 and 3.8 are supported. Both CPython (the standard Python +implementation) and `PyPy `_ are supported and tested. + +Linux, OSX, and Windows are supported. + +Installation through pip +------------------------ +`pip `_ is the suggested tool for installing +packages. It will handle installing all Python dependencies for the driver at +the same time as the driver itself. To install the driver*:: + + pip install scylla-driver + +You can use ``pip install --pre scylla-driver`` if you need to install a beta version. + +***Note**: if intending to use optional extensions, install the `dependencies <#optional-non-python-dependencies>`_ first. The driver may need to be reinstalled if dependencies are added after the initial installation. + +Verifying your Installation +--------------------------- +To check if the installation was successful, you can run:: + + python -c 'import cassandra; print cassandra.__version__' + +It should print something like "3.22.0". + +.. _installation-datastax-graph: + +(*Optional*) Graph +--------------------------- +The driver provides an optional fluent graph API that depends on Apache TinkerPop (gremlinpython). It is +not installed by default. To be able to build Gremlin traversals, you need to install +the `graph` requirements:: + + pip install scylla-driver[graph] + +(*Optional*) Compression Support +-------------------------------- +Compression can optionally be used for communication between the driver and +Cassandra. There are currently two supported compression algorithms: +snappy (in Cassandra 1.2+) and LZ4 (only in Cassandra 2.0+). If either is +available for the driver and Cassandra also supports it, it will +be used automatically. + +For lz4 support:: + + pip install lz4 + +For snappy support:: + + pip install python-snappy + +(If using a Debian Linux derivative such as Ubuntu, it may be easier to +just run ``apt-get install python-snappy``.) + +(*Optional*) Metrics Support +---------------------------- +The driver has built-in support for capturing :attr:`.Cluster.metrics` about +the queries you run. However, the ``scales`` library is required to +support this:: + + pip install scales + + +Speeding Up Installation +^^^^^^^^^^^^^^^^^^^^^^^^ + +By default, installing the driver through ``pip`` uses a pre-compiled, platform-specific wheel when available. +If using a source distribution rather than a wheel, Cython is used to compile certain parts of the driver. +This makes those hot paths faster at runtime, but the Cython compilation +process can take a long time -- as long as 10 minutes in some environments. + +In environments where performance is less important, it may be worth it to +:ref:`disable Cython as documented below `. +You can also use ``CASS_DRIVER_BUILD_CONCURRENCY`` to increase the number of +threads used to build the driver and any C extensions: + +.. code-block:: bash + + $ # installing from source + $ CASS_DRIVER_BUILD_CONCURRENCY=8 python setup.py install + $ # installing from pip + $ CASS_DRIVER_BUILD_CONCURRENCY=8 pip install scylla-driver + +OSX Installation Error +^^^^^^^^^^^^^^^^^^^^^^ +If you're installing on OSX and have XCode 5.1 installed, you may see an error like this:: + + clang: error: unknown argument: '-mno-fused-madd' [-Wunused-command-line-argument-hard-error-in-future] + +To fix this, re-run the installation with an extra compilation flag: + +.. code-block:: bash + + ARCHFLAGS=-Wno-error=unused-command-line-argument-hard-error-in-future pip install scylla-driver + +.. _windows_build: + +Windows Installation Notes +-------------------------- +Installing the driver with extensions in Windows sometimes presents some challenges. A few notes about common +hang-ups: + +Setup requires a compiler. When using Python 2, this is as simple as installing `this package `_ +(this link is also emitted during install if setuptools is unable to find the resources it needs). Depending on your +system settings, this package may install as a user-specific application. Make sure to install for everyone, or at least +as the user that will be building the Python environment. + +It is also possible to run the build with your compiler of choice. Just make sure to have your environment setup with +the proper paths. Make sure the compiler target architecture matches the bitness of your Python runtime. +Perhaps the easiest way to do this is to run the build/install from a Visual Studio Command Prompt (a +shortcut installed with Visual Studio that sources the appropriate environment and presents a shell). + +Manual Installation +------------------- +You can always install the driver directly from a source checkout or tarball. +When installing manually, ensure the python dependencies are already +installed. You can find the list of dependencies in +`requirements.txt `_. + +Once the dependencies are installed, simply run:: + + python setup.py install + + +(*Optional*) Non-python Dependencies +------------------------------------ +The driver has several **optional** features that have non-Python dependencies. + +C Extensions +^^^^^^^^^^^^ +By default, a number of extensions are compiled, providing faster hashing +for token-aware routing with the ``Murmur3Partitioner``, +`libev `_ event loop integration, +and Cython optimized extensions. + +When installing manually through setup.py, you can disable both with +the ``--no-extensions`` option, or selectively disable them with +with ``--no-murmur3``, ``--no-libev``, or ``--no-cython``. + +To compile the extensions, ensure that GCC and the Python headers are available. + +On Ubuntu and Debian, this can be accomplished by running:: + + $ sudo apt-get install gcc python-dev + +On RedHat and RedHat-based systems like CentOS and Fedora:: + + $ sudo yum install gcc python-devel + +On OS X, homebrew installations of Python should provide the necessary headers. + +See :ref:`windows_build` for notes on configuring the build environment on Windows. + +.. _cython-extensions: + +Cython-based Extensions +~~~~~~~~~~~~~~~~~~~~~~~ +By default, this package uses `Cython `_ to optimize core modules and build custom extensions. +This is not a hard requirement, but is engaged by default to build extensions offering better performance than the +pure Python implementation. + +This is a costly build phase, especially in clean environments where the Cython compiler must be built +This build phase can be avoided using the build switch, or an environment variable:: + + python setup.py install --no-cython + +Alternatively, an environment variable can be used to switch this option regardless of +context:: + + CASS_DRIVER_NO_CYTHON=1 + - or, to disable all extensions: + CASS_DRIVER_NO_EXTENSIONS=1 + +This method is required when using pip, which provides no other way of injecting user options in a single command:: + + CASS_DRIVER_NO_CYTHON=1 pip install scylla-driver + CASS_DRIVER_NO_CYTHON=1 sudo -E pip install ~/python-driver + +The environment variable is the preferred option because it spans all invocations of setup.py, and will +prevent Cython from being materialized as a setup requirement. + +If your sudo configuration does not allow SETENV, you must push the option flag down via pip. However, pip +applies these options to all dependencies (which break on the custom flag). Therefore, you must first install +dependencies, then use install-option:: + + sudo pip install six futures + sudo pip install --install-option="--no-cython" + + +libev support +^^^^^^^^^^^^^ +The driver currently uses Python's ``asyncore`` module for its default +event loop. For better performance, ``libev`` is also supported through +a C extension. + +If you're on Linux, you should be able to install libev +through a package manager. For example, on Debian/Ubuntu:: + + $ sudo apt-get install libev4 libev-dev + +On RHEL/CentOS/Fedora:: + + $ sudo yum install libev libev-devel + +If you're on Mac OS X, you should be able to install libev +through `Homebrew `_. For example, on Mac OS X:: + + $ brew install libev + +The libev extension is not built for Windows (the build process is complex, and the Windows implementation uses +select anyway). + +If successful, you should be able to build and install the extension +(just using ``setup.py build`` or ``setup.py install``) and then use +the libev event loop by doing the following: + +.. code-block:: python + + >>> from cassandra.io.libevreactor import LibevConnection + >>> from cassandra.cluster import Cluster + + >>> cluster = Cluster() + >>> cluster.connection_class = LibevConnection + >>> session = cluster.connect() + +(*Optional*) Configuring SSL +----------------------------- +Andrew Mussey has published a thorough guide on +`Using SSL with the DataStax Python driver `_. diff --git a/3.26.2-scylla/_sources/lwt.rst.txt b/3.26.2-scylla/_sources/lwt.rst.txt new file mode 100644 index 0000000000..2cc272f350 --- /dev/null +++ b/3.26.2-scylla/_sources/lwt.rst.txt @@ -0,0 +1,91 @@ +Lightweight Transactions (Compare-and-set) +========================================== + +Lightweight Transactions (LWTs) are mostly pass-through CQL for the driver. However, +the server returns some specialized results indicating the outcome and optional state +preceding the transaction. + +For pertinent execution parameters, see :attr:`.Statement.serial_consistency_level`. + +This section discusses working with specialized result sets returned by the server for LWTs, +and how to work with them using the driver. + + +Specialized Results +------------------- +The result returned from a LWT request is always a single row result. It will always have +prepended a special column named ``[applied]``. How this value appears in your results depends +on the row factory in use. See below for examples. + +The value of this ``[applied]`` column is boolean value indicating whether or not the transaction was applied. +If ``True``, it is the only column in the result. If ``False``, the additional columns depend on the LWT operation being +executed: + +- When using a ``UPDATE ... IF "col" = ...`` clause, the result will contain the ``[applied]`` column, plus the existing columns + and values for any columns in the ``IF`` clause (and thus the value that caused the transaction to fail). + +- When using ``INSERT ... IF NOT EXISTS``, the result will contain the ``[applied]`` column, plus all columns and values + of the existing row that rejected the transaction. + +- ``UPDATE .. IF EXISTS`` never has additional columns, regardless of ``[applied]`` status. + +How the ``[applied]`` column manifests depends on the row factory in use. Considering the following (initially empty) table:: + + CREATE TABLE test.t ( + k int PRIMARY KEY, + v int, + x int + ) + +... the following sections show the expected result for a number of example statements, using the three base row factories. + +named_tuple_factory (default) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +The name ``[applied]`` is not a valid Python identifier, so the square brackets are actually removed +from the attribute for the resulting ``namedtuple``. The row always has a boolean column ``applied`` in position 0:: + + >>> session.execute("INSERT INTO t (k,v) VALUES (0,0) IF NOT EXISTS") + Row(applied=True) + + >>> session.execute("INSERT INTO t (k,v) VALUES (0,0) IF NOT EXISTS") + Row(applied=False, k=0, v=0, x=None) + + >>> session.execute("UPDATE t SET v = 1, x = 2 WHERE k = 0 IF v =0") + Row(applied=True) + + >>> session.execute("UPDATE t SET v = 1, x = 2 WHERE k = 0 IF v =0 AND x = 1") + Row(applied=False, v=1, x=2) + +tuple_factory +~~~~~~~~~~~~~ +This return type does not refer to names, but the boolean value ``applied`` is always present in position 0:: + + >>> session.execute("INSERT INTO t (k,v) VALUES (0,0) IF NOT EXISTS") + (True,) + + >>> session.execute("INSERT INTO t (k,v) VALUES (0,0) IF NOT EXISTS") + (False, 0, 0, None) + + >>> session.execute("UPDATE t SET v = 1, x = 2 WHERE k = 0 IF v =0") + (True,) + + >>> session.execute("UPDATE t SET v = 1, x = 2 WHERE k = 0 IF v =0 AND x = 1") + (False, 1, 2) + +dict_factory +~~~~~~~~~~~~ +The retuned ``dict`` contains the ``[applied]`` key:: + + >>> session.execute("INSERT INTO t (k,v) VALUES (0,0) IF NOT EXISTS") + {u'[applied]': True} + + >>> session.execute("INSERT INTO t (k,v) VALUES (0,0) IF NOT EXISTS") + {u'x': 2, u'[applied]': False, u'v': 1} + + >>> session.execute("UPDATE t SET v = 1, x = 2 WHERE k = 0 IF v =0") + {u'x': None, u'[applied]': False, u'k': 0, u'v': 0} + + >>> session.execute("UPDATE t SET v = 1, x = 2 WHERE k = 0 IF v =0 AND x = 1") + {u'[applied]': True} + + diff --git a/3.26.2-scylla/_sources/object-mapper.rst.txt b/3.26.2-scylla/_sources/object-mapper.rst.txt new file mode 100644 index 0000000000..421be246ac --- /dev/null +++ b/3.26.2-scylla/_sources/object-mapper.rst.txt @@ -0,0 +1,105 @@ +Object Mapper +============= + +cqlengine is the Cassandra CQL 3 Object Mapper packaged with this driver + +:ref:`Jump to Getting Started ` + +Contents +-------- +:doc:`cqlengine/upgrade-guide` + For migrating projects from legacy cqlengine, to the integrated product + +:doc:`cqlengine/models` + Examples defining models, and mapping them to tables + +:doc:`cqlengine/queryset` + Overview of query sets and filtering + +:doc:`cqlengine/batches` + Working with batch mutations + +:doc:`cqlengine/connections` + Working with multiple sessions + +:ref:`API Documentation ` + Index of API documentation + +:doc:`cqlengine/third-party` + High-level examples in Celery and uWSGI + +:doc:`cqlengine/faq` + +.. toctree:: + :hidden: + + cqlengine/upgrade-guide + cqlengine/models + cqlengine/queryset + cqlengine/batches + cqlengine/connections + cqlengine/third-party + cqlengine/faq + +.. _getting-started: + +Getting Started +--------------- + +.. code-block:: python + + import uuid + from cassandra.cqlengine import columns + from cassandra.cqlengine import connection + from datetime import datetime + from cassandra.cqlengine.management import sync_table + from cassandra.cqlengine.models import Model + + #first, define a model + class ExampleModel(Model): + example_id = columns.UUID(primary_key=True, default=uuid.uuid4) + example_type = columns.Integer(index=True) + created_at = columns.DateTime() + description = columns.Text(required=False) + + #next, setup the connection to your cassandra server(s)... + # see http://datastax.github.io/python-driver/api/cassandra/cluster.html for options + # the list of hosts will be passed to create a Cluster() instance + connection.setup(['127.0.0.1'], "cqlengine", protocol_version=3) + + #...and create your CQL table + >>> sync_table(ExampleModel) + + #now we can create some rows: + >>> em1 = ExampleModel.create(example_type=0, description="example1", created_at=datetime.now()) + >>> em2 = ExampleModel.create(example_type=0, description="example2", created_at=datetime.now()) + >>> em3 = ExampleModel.create(example_type=0, description="example3", created_at=datetime.now()) + >>> em4 = ExampleModel.create(example_type=0, description="example4", created_at=datetime.now()) + >>> em5 = ExampleModel.create(example_type=1, description="example5", created_at=datetime.now()) + >>> em6 = ExampleModel.create(example_type=1, description="example6", created_at=datetime.now()) + >>> em7 = ExampleModel.create(example_type=1, description="example7", created_at=datetime.now()) + >>> em8 = ExampleModel.create(example_type=1, description="example8", created_at=datetime.now()) + + #and now we can run some queries against our table + >>> ExampleModel.objects.count() + 8 + >>> q = ExampleModel.objects(example_type=1) + >>> q.count() + 4 + >>> for instance in q: + >>> print instance.description + example5 + example6 + example7 + example8 + + #here we are applying additional filtering to an existing query + #query objects are immutable, so calling filter returns a new + #query object + >>> q2 = q.filter(example_id=em5.example_id) + + >>> q2.count() + 1 + >>> for instance in q2: + >>> print instance.description + example5 diff --git a/3.26.2-scylla/_sources/performance.rst.txt b/3.26.2-scylla/_sources/performance.rst.txt new file mode 100644 index 0000000000..f7a3f49e0f --- /dev/null +++ b/3.26.2-scylla/_sources/performance.rst.txt @@ -0,0 +1,45 @@ +Performance Notes +================= +The Python driver for Cassandra offers several methods for executing queries. +You can synchronously block for queries to complete using +:meth:`.Session.execute()`, you can obtain asynchronous request futures through +:meth:`.Session.execute_async()`, and you can attach a callback to the future +with :meth:`.ResponseFuture.add_callback()`. + +Examples of multiple request patterns can be found in the benchmark scripts included in the driver project. + +The choice of execution pattern will depend on the application context. For applications dealing with multiple +requests in a given context, the recommended pattern is to use concurrent asynchronous +requests with callbacks. For many use cases, you don't need to implement this pattern yourself. +:meth:`cassandra.concurrent.execute_concurrent` and :meth:`cassandra.concurrent.execute_concurrent_with_args` +provide this pattern with a synchronous API and tunable concurrency. + +Due to the GIL and limited concurrency, the driver can become CPU-bound pretty quickly. The sections below +discuss further runtime and design considerations for mitigating this limitation. + +PyPy +---- +`PyPy `_ is an alternative Python runtime which uses a JIT compiler to +reduce CPU consumption. This leads to a huge improvement in the driver performance, +more than doubling throughput for many workloads. + +Cython Extensions +----------------- +`Cython `_ is an optimizing compiler and language that can be used to compile the core files and +optional extensions for the driver. Cython is not a strict dependency, but the extensions will be built by default. + +See :doc:`installation` for details on controlling this build. + +multiprocessing +--------------- +All of the patterns discussed above may be used over multiple processes using the +`multiprocessing `_ +module. Multiple processes will scale better than multiple threads, so if high throughput is your goal, +consider this option. + +Be sure to **never share any** :class:`~.Cluster`, :class:`~.Session`, +**or** :class:`~.ResponseFuture` **objects across multiple processes**. These +objects should all be created after forking the process, not before. + +For further discussion and simple examples using the driver with ``multiprocessing``, +see `this blog post `_. diff --git a/3.26.2-scylla/_sources/query-paging.rst.txt b/3.26.2-scylla/_sources/query-paging.rst.txt new file mode 100644 index 0000000000..23ee2c1129 --- /dev/null +++ b/3.26.2-scylla/_sources/query-paging.rst.txt @@ -0,0 +1,95 @@ +.. _query-paging: + +Paging Large Queries +==================== +Cassandra 2.0+ offers support for automatic query paging. Starting with +version 2.0 of the driver, if :attr:`~.Cluster.protocol_version` is greater than +:const:`2` (it is by default), queries returning large result sets will be +automatically paged. + +Controlling the Page Size +------------------------- +By default, :attr:`.Session.default_fetch_size` controls how many rows will +be fetched per page. This can be overridden per-query by setting +:attr:`~.fetch_size` on a :class:`~.Statement`. By default, each page +will contain at most 5000 rows. + +Handling Paged Results +---------------------- +Whenever the number of result rows for are query exceed the page size, an +instance of :class:`~.PagedResult` will be returned instead of a normal +list. This class implements the iterator interface, so you can treat +it like a normal iterator over rows:: + + from cassandra.query import SimpleStatement + query = "SELECT * FROM users" # users contains 100 rows + statement = SimpleStatement(query, fetch_size=10) + for user_row in session.execute(statement): + process_user(user_row) + +Whenever there are no more rows in the current page, the next page will +be fetched transparently. However, note that it *is* possible for +an :class:`Exception` to be raised while fetching the next page, just +like you might see on a normal call to ``session.execute()``. + +If you use :meth:`.Session.execute_async()` along with, +:meth:`.ResponseFuture.result()`, the first page will be fetched before +:meth:`~.ResponseFuture.result()` returns, but latter pages will be +transparently fetched synchronously while iterating the result. + +Handling Paged Results with Callbacks +------------------------------------- +If callbacks are attached to a query that returns a paged result, +the callback will be called once per page with a normal list of rows. + +Use :attr:`.ResponseFuture.has_more_pages` and +:meth:`.ResponseFuture.start_fetching_next_page()` to continue fetching +pages. For example:: + + class PagedResultHandler(object): + + def __init__(self, future): + self.error = None + self.finished_event = Event() + self.future = future + self.future.add_callbacks( + callback=self.handle_page, + errback=self.handle_err) + + def handle_page(self, rows): + for row in rows: + process_row(row) + + if self.future.has_more_pages: + self.future.start_fetching_next_page() + else: + self.finished_event.set() + + def handle_error(self, exc): + self.error = exc + self.finished_event.set() + + future = session.execute_async("SELECT * FROM users") + handler = PagedResultHandler(future) + handler.finished_event.wait() + if handler.error: + raise handler.error + +Resume Paged Results +-------------------- + +You can resume the pagination when executing a new query by using the :attr:`.ResultSet.paging_state`. This can be useful if you want to provide some stateless pagination capabilities to your application (ie. via http). For example:: + + from cassandra.query import SimpleStatement + query = "SELECT * FROM users" + statement = SimpleStatement(query, fetch_size=10) + results = session.execute(statement) + + # save the paging_state somewhere and return current results + web_session['paging_state'] = results.paging_state + + + # resume the pagination sometime later... + statement = SimpleStatement(query, fetch_size=10) + ps = web_session['paging_state'] + results = session.execute(statement, paging_state=ps) diff --git a/3.26.2-scylla/_sources/scylla-cloud-serverless.rst.txt b/3.26.2-scylla/_sources/scylla-cloud-serverless.rst.txt new file mode 100644 index 0000000000..4e0bafd1b8 --- /dev/null +++ b/3.26.2-scylla/_sources/scylla-cloud-serverless.rst.txt @@ -0,0 +1,49 @@ +ScyllaDB Cloud Serverless +------------------------- + +With ScyllaDB Cloud, you can deploy `serverless databases `_. +The Python driver allows you to connect to a serverless database by utilizing the connection bundle you can download via the **Connect>Python** tab in the Cloud application. +The connection bundle is a YAML file with connection and credential information for your cluster. + +Connecting to a ScyllaDB Cloud serverless database is very similar to a standard connection to a ScyllaDB database. + +Here’s a short program that connects to a ScyllaDB Cloud serverless database and prints metadata about the cluster: + +.. code-block:: python + + from cassandra.cluster import Cluster, ExecutionProfile, EXEC_PROFILE_DEFAULT + from cassandra.policies import DCAwareRoundRobinPolicy, TokenAwarePolicy + + PATH_TO_BUNDLE_YAML = '/file/downloaded/from/cloud/connect-bundle.yaml' + + + def get_cluster(): + profile = ExecutionProfile( + load_balancing_policy=TokenAwarePolicy( + DCAwareRoundRobinPolicy(local_dc='us-east-1') + ) + ) + + return Cluster( + execution_profiles={EXEC_PROFILE_DEFAULT: profile}, + scylla_cloud=PATH_TO_BUNDLE_YAML, + ) + + + print('Connecting to cluster') + cluster = get_cluster() + session = cluster.connect() + + print('Connected to cluster', cluster.metadata.cluster_name) + + print('Getting metadata') + for host in cluster.metadata.all_hosts(): + print('Datacenter: {}; Host: {}; Rack: {}'.format( + host.datacenter, host.address, host.rack) + ) + + cluster.shutdown() + +By providing the ``scylla_cloud`` parameter to the :class:`~.Cluster` constructor, +the driver can set up the connection based on the endpoint and credential information +stored in your downloaded ScyllaDB Cloud Serverless connection bundle. \ No newline at end of file diff --git a/3.26.2-scylla/_sources/scylla-cloud.rst.txt b/3.26.2-scylla/_sources/scylla-cloud.rst.txt new file mode 100644 index 0000000000..b5eb6df798 --- /dev/null +++ b/3.26.2-scylla/_sources/scylla-cloud.rst.txt @@ -0,0 +1,5 @@ +ScyllaDB Cloud +-------------- + +To connect to a `ScyllaDB Cloud `_ cluster, go to the Cluster Connect page, Python example. +For best performance, make sure to use the Scylla Driver. diff --git a/3.26.2-scylla/_sources/scylla-specific.rst.txt b/3.26.2-scylla/_sources/scylla-specific.rst.txt new file mode 100644 index 0000000000..101ddb534b --- /dev/null +++ b/3.26.2-scylla/_sources/scylla-specific.rst.txt @@ -0,0 +1,106 @@ +Scylla Specific Features +======================== + +Shard Awareness +--------------- + +**scylla-driver** is shard aware and contains extensions that work with the TokenAwarePolicy supported by Scylla 2.3 and onwards. Using this policy, the driver can select a connection to a particular shard based on the shard's token. +As a result, latency is significantly reduced because there is no need to pass data between the shards. + +Details on the scylla cql protocol extensions +https://github.com/scylladb/scylla/blob/master/docs/dev/protocol-extensions.md#intranode-sharding + +For using it you only need to enable ``TokenAwarePolicy`` on the ``Cluster`` + +See the configuration of ``native_shard_aware_transport_port`` and ``native_shard_aware_transport_port_ssl`` on scylla.yaml: +https://github.com/scylladb/scylla/blob/master/docs/dev/protocols.md#cql-client-protocol + +.. code:: python + + from cassandra.cluster import Cluster + from cassandra.policies import TokenAwarePolicy, RoundRobinPolicy + + cluster = Cluster(load_balancing_policy=TokenAwarePolicy(RoundRobinPolicy())) + + +New Cluster Helpers +------------------- + +* ``shard_aware_options`` + + Setting it to ``dict(disable=True)`` would disable the shard aware functionally, for cases favoring once connection per host (example, lots of processes connecting from one client host, generating a big load of connections + + Other option is to configure scylla by setting ``enable_shard_aware_drivers: false`` on scylla.yaml. + +.. code:: python + + from cassandra.cluster import Cluster + + cluster = Cluster(shard_aware_options=dict(disable=True)) + session = cluster.connect() + + assert not cluster.is_shard_aware(), "Shard aware should be disabled" + + # or just disable the shard aware port logic + cluster = Cluster(shard_aware_options=dict(disable_shardaware_port=True)) + session = cluster.connect() + +* ``cluster.is_shard_aware()`` + + New method available on ``Cluster`` allowing to check whether the remote cluster supports shard awareness (bool) + +.. code:: python + + from cassandra.cluster import Cluster + + cluster = Cluster() + session = cluster.connect() + + if cluster.is_shard_aware(): + print("connected to a scylla cluster") + +* ``cluster.shard_aware_stats()`` + + New method available on ``Cluster`` allowing to check the status of shard aware connections to all available hosts (dict) + +.. code:: python + + from cassandra.cluster import Cluster + + cluster = Cluster() + session = cluster.connect() + + stats = cluster.shard_aware_stats() + if all([v["shards_count"] == v["connected"] for v in stats.values()]): + print("successfully connected to all shards of all scylla nodes") + + +New Table Attributes +-------------------- + +* ``in_memory`` flag + + New flag available on ``TableMetadata.options`` to indicate that it is an `In Memory `_ table + +.. note:: in memory tables is a feature existing only in Scylla Enterprise + +.. code:: python + + from cassandra.cluster import Cluster + + cluster = Cluster() + session = cluster.connect() + session.execute(""" + CREATE KEYSPACE IF NOT EXISTS keyspace1 + WITH replication = {'class': 'SimpleStrategy', 'replication_factor': '1'}; + """) + + session.execute(""" + CREATE TABLE IF NOT EXISTS keyspace1.standard1 ( + key blob PRIMARY KEY, + "C0" blob + ) WITH in_memory=true AND compaction={'class': 'InMemoryCompactionStrategy'} + """) + + cluster.refresh_table_metadata("keyspace1", "standard1") + assert cluster.metadata.keyspaces["keyspace1"].tables["standard1"].options["in_memory"] == True diff --git a/3.26.2-scylla/_sources/security.rst.txt b/3.26.2-scylla/_sources/security.rst.txt new file mode 100644 index 0000000000..c30189562f --- /dev/null +++ b/3.26.2-scylla/_sources/security.rst.txt @@ -0,0 +1,421 @@ +.. _security: + +Security +======== +The two main security components you will use with the +Python driver are Authentication and SSL. + +Authentication +-------------- +Versions 2.0 and higher of the driver support a SASL-based +authentication mechanism when :attr:`~.Cluster.protocol_version` +is set to 2 or higher. To use this authentication, set +:attr:`~.Cluster.auth_provider` to an instance of a subclass +of :class:`~cassandra.auth.AuthProvider`. When working +with Cassandra's ``PasswordAuthenticator``, you can use +the :class:`~cassandra.auth.PlainTextAuthProvider` class. + +For example, suppose Cassandra is setup with its default +'cassandra' user with a password of 'cassandra': + +.. code-block:: python + + from cassandra.cluster import Cluster + from cassandra.auth import PlainTextAuthProvider + + auth_provider = PlainTextAuthProvider(username='cassandra', password='cassandra') + cluster = Cluster(auth_provider=auth_provider, protocol_version=2) + + + +Custom Authenticators +^^^^^^^^^^^^^^^^^^^^^ +If you're using something other than Cassandra's ``PasswordAuthenticator``, +:class:`~.SaslAuthProvider` is provided for generic SASL authentication mechanisms, +utilizing the ``pure-sasl`` package. +If these do not suit your needs, you may need to create your own subclasses of +:class:`~.AuthProvider` and :class:`~.Authenticator`. You can use the Sasl classes +as example implementations. + +Protocol v1 Authentication +^^^^^^^^^^^^^^^^^^^^^^^^^^ +When working with Cassandra 1.2 (or a higher version with +:attr:`~.Cluster.protocol_version` set to ``1``), you will not pass in +an :class:`~.AuthProvider` instance. Instead, you should pass in a +function that takes one argument, the IP address of a host, and returns +a dict of credentials with a ``username`` and ``password`` key: + +.. code-block:: python + + from cassandra.cluster import Cluster + + def get_credentials(host_address): + return {'username': 'joe', 'password': '1234'} + + cluster = Cluster(auth_provider=get_credentials, protocol_version=1) + +SSL +--- +SSL should be used when client encryption is enabled in Cassandra. + +To give you as much control as possible over your SSL configuration, our SSL +API takes a user-created `SSLContext` instance from the Python standard library. +These docs will include some examples for how to achieve common configurations, +but the `ssl.SSLContext `_ documentation +gives a more complete description of what is possible. + +To enable SSL with version 3.17.0 and higher, you will need to set :attr:`.Cluster.ssl_context` to a +``ssl.SSLContext`` instance to enable SSL. Optionally, you can also set :attr:`.Cluster.ssl_options` +to a dict of options. These will be passed as kwargs to ``ssl.SSLContext.wrap_socket()`` +when new sockets are created. + +If you create your SSLContext using `ssl.create_default_context `_, +be aware that SSLContext.check_hostname is set to True by default, so the hostname validation will be done +by Python and not the driver. For this reason, we need to set the server_hostname at best effort, which is the +resolved ip address. If this validation needs to be done against the FQDN, consider enabling it using the ssl_options +as described in the following examples or implement your own :class:`~.connection.EndPoint` and +:class:`~.connection.EndPointFactory`. + + +The following examples assume you have generated your Cassandra certificate and +keystore files with these intructions: + +* `Setup SSL Cert `_ + +It might be also useful to learn about the different levels of identity verification to understand the examples: + +* `Using SSL in DSE drivers `_ + +SSL with Twisted or Eventlet +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Twisted and Eventlet both use an alternative SSL implementation called pyOpenSSL, so if your `Cluster`'s connection class is +:class:`~cassandra.io.twistedreactor.TwistedConnection` or :class:`~cassandra.io.eventletreactor.EventletConnection`, you must pass a +`pyOpenSSL context `_ instead. +An example is provided in these docs, and more details can be found in the +`documentation `_. +pyOpenSSL is not installed by the driver and must be installed separately. + +SSL Configuration Examples +^^^^^^^^^^^^^^^^^^^^^^^^^^ +Here, we'll describe the server and driver configuration necessary to set up SSL to meet various goals, such as the client verifying the server and the server verifying the client. We'll also include Python code demonstrating how to use servers and drivers configured in these ways. + +.. _ssl-no-identify-verification: + +No identity verification +++++++++++++++++++++++++ + +No identity verification at all. Note that this is not recommended for for production deployments. + +The Cassandra configuration:: + + client_encryption_options: + enabled: true + keystore: /path/to/127.0.0.1.keystore + keystore_password: myStorePass + require_client_auth: false + +The driver configuration: + +.. code-block:: python + + from cassandra.cluster import Cluster, Session + from ssl import SSLContext, PROTOCOL_TLS + + ssl_context = SSLContext(PROTOCOL_TLS) + + cluster = Cluster(['127.0.0.1'], ssl_context=ssl_context) + session = cluster.connect() + +.. _ssl-client-verifies-server: + +Client verifies server +++++++++++++++++++++++ + +Ensure the python driver verifies the identity of the server. + +The Cassandra configuration:: + + client_encryption_options: + enabled: true + keystore: /path/to/127.0.0.1.keystore + keystore_password: myStorePass + require_client_auth: false + +For the driver configuration, it's very important to set `ssl_context.verify_mode` +to `CERT_REQUIRED`. Otherwise, the loaded verify certificate will have no effect: + +.. code-block:: python + + from cassandra.cluster import Cluster, Session + from ssl import SSLContext, PROTOCOL_TLS, CERT_REQUIRED + + ssl_context = SSLContext(PROTOCOL_TLS) + ssl_context.load_verify_locations('/path/to/rootca.crt') + ssl_context.verify_mode = CERT_REQUIRED + + cluster = Cluster(['127.0.0.1'], ssl_context=ssl_context) + session = cluster.connect() + +Additionally, you can also force the driver to verify the `hostname` of the server by passing additional options to `ssl_context.wrap_socket` via the `ssl_options` kwarg: + +.. code-block:: python + + from cassandra.cluster import Cluster, Session + from ssl import SSLContext, PROTOCOL_TLS, CERT_REQUIRED + + ssl_context = SSLContext(PROTOCOL_TLS) + ssl_context.load_verify_locations('/path/to/rootca.crt') + ssl_context.verify_mode = CERT_REQUIRED + ssl_context.check_hostname = True + ssl_options = {'server_hostname': '127.0.0.1'} + + cluster = Cluster(['127.0.0.1'], ssl_context=ssl_context, ssl_options=ssl_options) + session = cluster.connect() + +.. _ssl-server-verifies-client: + +Server verifies client +++++++++++++++++++++++ + +If Cassandra is configured to verify clients (``require_client_auth``), you need to generate +SSL key and certificate files. + +The cassandra configuration:: + + client_encryption_options: + enabled: true + keystore: /path/to/127.0.0.1.keystore + keystore_password: myStorePass + require_client_auth: true + truststore: /path/to/dse-truststore.jks + truststore_password: myStorePass + +The Python ``ssl`` APIs require the certificate in PEM format. First, create a certificate +conf file: + +.. code-block:: bash + + cat > gen_client_cert.conf <`__ +for more details about ``SSLContext`` configuration. + +**Server verifies client and client verifies server using Twisted and pyOpenSSL** + +.. code-block:: python + + from OpenSSL import SSL, crypto + from cassandra.cluster import Cluster + from cassandra.io.twistedreactor import TwistedConnection + + ssl_context = SSL.Context(SSL.TLSv1_2_METHOD) + ssl_context.set_verify(SSL.VERIFY_PEER, callback=lambda _1, _2, _3, _4, ok: ok) + ssl_context.use_certificate_file('/path/to/client.crt_signed') + ssl_context.use_privatekey_file('/path/to/client.key') + ssl_context.load_verify_locations('/path/to/rootca.crt') + + cluster = Cluster( + contact_points=['127.0.0.1'], + connection_class=TwistedConnection, + ssl_context=ssl_context, + ssl_options={'check_hostname': True} + ) + session = cluster.connect() + + +Connecting using Eventlet would look similar except instead of importing and using ``TwistedConnection``, you would +import and use ``EventletConnection``, including the appropriate monkey-patching. + +Versions 3.16.0 and lower +^^^^^^^^^^^^^^^^^^^^^^^^^ + +To enable SSL you will need to set :attr:`.Cluster.ssl_options` to a +dict of options. These will be passed as kwargs to ``ssl.wrap_socket()`` +when new sockets are created. Note that this use of ssl_options will be +deprecated in the next major release. + +By default, a ``ca_certs`` value should be supplied (the value should be +a string pointing to the location of the CA certs file), and you probably +want to specify ``ssl_version`` as ``ssl.PROTOCOL_TLS`` to match +Cassandra's default protocol. + +For example: + +.. code-block:: python + + from cassandra.cluster import Cluster + from ssl import PROTOCOL_TLS, CERT_REQUIRED + + ssl_opts = { + 'ca_certs': '/path/to/my/ca.certs', + 'ssl_version': PROTOCOL_TLS, + 'cert_reqs': CERT_REQUIRED # Certificates are required and validated + } + cluster = Cluster(ssl_options=ssl_opts) + +This is only an example to show how to pass the ssl parameters. Consider reading +the `python ssl documentation `__ for +your configuration. For further reading, Andrew Mussey has published a thorough guide on +`Using SSL with the DataStax Python driver `_. + +SSL with Twisted +++++++++++++++++ + +In case the twisted event loop is used pyOpenSSL must be installed or an exception will be risen. Also +to set the ``ssl_version`` and ``cert_reqs`` in ``ssl_opts`` the appropriate constants from pyOpenSSL are expected. + +DSE Authentication +------------------ +When authenticating against DSE, the Cassandra driver provides two auth providers that work both with legacy kerberos and Cassandra authenticators, +as well as the new DSE Unified Authentication. This allows client to configure this auth provider independently, +and in advance of any server upgrade. These auth providers are configured in the same way as any previous implementation:: + + from cassandra.auth import DSEGSSAPIAuthProvider + auth_provider = DSEGSSAPIAuthProvider(service='dse', qops=["auth"]) + cluster = Cluster(auth_provider=auth_provider) + session = cluster.connect() + +Implementations are :attr:`.DSEPlainTextAuthProvider`, :class:`.DSEGSSAPIAuthProvider` and :class:`.SaslAuthProvider`. + +DSE Unified Authentication +^^^^^^^^^^^^^^^^^^^^^^^^^^ + +With DSE (>=5.1), unified Authentication allows you to: + +* Proxy Login: Authenticate using a fixed set of authentication credentials but allow authorization of resources based another user id. +* Proxy Execute: Authenticate using a fixed set of authentication credentials but execute requests based on another user id. + +Proxy Login ++++++++++++ + +Proxy login allows you to authenticate with a user but act as another one. You need to ensure the authenticated user has the permission to use the authorization of resources of the other user. ie. this example will allow the `server` user to authenticate as usual but use the authorization of `user1`: + +.. code-block:: text + + GRANT PROXY.LOGIN on role user1 to server + +then you can do the proxy authentication.... + +.. code-block:: python + + from cassandra.cluster import Cluster + from cassandra.auth import SaslAuthProvider + + sasl_kwargs = { + "service": 'dse', + "mechanism":"PLAIN", + "username": 'server', + 'password': 'server', + 'authorization_id': 'user1' + } + + auth_provider = SaslAuthProvider(**sasl_kwargs) + c = Cluster(auth_provider=auth_provider) + s = c.connect() + s.execute(...) # all requests will be executed as 'user1' + +If you are using kerberos, you can use directly :class:`.DSEGSSAPIAuthProvider` and pass the authorization_id, like this: + +.. code-block:: python + + from cassandra.cluster import Cluster + from cassandra.auth import DSEGSSAPIAuthProvider + + # Ensure the kerberos ticket of the server user is set with the kinit utility. + auth_provider = DSEGSSAPIAuthProvider(service='dse', qops=["auth"], principal="server@DATASTAX.COM", + authorization_id='user1@DATASTAX.COM') + c = Cluster(auth_provider=auth_provider) + s = c.connect() + s.execute(...) # all requests will be executed as 'user1' + + +Proxy Execute ++++++++++++++ + +Proxy execute allows you to execute requests as another user than the authenticated one. You need to ensure the authenticated user has the permission to use the authorization of resources of the specified user. ie. this example will allow the `server` user to execute requests as `user1`: + +.. code-block:: text + + GRANT PROXY.EXECUTE on role user1 to server + +then you can do a proxy execute... + +.. code-block:: python + + from cassandra.cluster import Cluster + from cassandra.auth import DSEPlainTextAuthProvider, + + auth_provider = DSEPlainTextAuthProvider('server', 'server') + + c = Cluster(auth_provider=auth_provider) + s = c.connect() + s.execute('select * from k.t;', execute_as='user1') # the request will be executed as 'user1' + +Please see the `official documentation `_ for more details on the feature and configuration process. diff --git a/3.26.2-scylla/_sources/upgrading.rst.txt b/3.26.2-scylla/_sources/upgrading.rst.txt new file mode 100644 index 0000000000..9559fa3579 --- /dev/null +++ b/3.26.2-scylla/_sources/upgrading.rst.txt @@ -0,0 +1,388 @@ +Upgrading +========= + +.. toctree:: + :maxdepth: 1 + +Upgrading from dse-driver +------------------------- + +Since 3.21.0, scylla-driver fully supports DataStax products. dse-driver and +dse-graph users should now migrate to scylla-driver to benefit from latest bug fixes +and new features. The upgrade to this new unified driver version is straightforward +with no major API changes. + +Installation +^^^^^^^^^^^^ + +Only the `scylla-driver` package should be installed. `dse-driver` and `dse-graph` +are not required anymore:: + + pip install scylla-driver + +If you need the Graph *Fluent* API (features provided by dse-graph):: + + pip install scylla-driver[graph] + +See :doc:`installation` for more details. + +Import from the cassandra module +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +There is no `dse` module, so you should import from the `cassandra` module. You +need to change only the first module of your import statements, not the submodules. + +.. code-block:: python + + from dse.cluster import Cluster, EXEC_PROFILE_GRAPH_DEFAULT + from dse.auth import PlainTextAuthProvider + from dse.policies import WhiteListRoundRobinPolicy + + # becomes + + from cassandra.cluster import Cluster, EXEC_PROFILE_GRAPH_DEFAULT + from cassandra.auth import PlainTextAuthProvider + from cassandra.policies import WhiteListRoundRobinPolicy + +Also note that the cassandra.hosts module doesn't exist in scylla-driver. This +module is named cassandra.pool. + +dse-graph +^^^^^^^^^ + +dse-graph features are now built into scylla-driver. The only change you need +to do is your import statements: + +.. code-block:: python + + from dse_graph import .. + from dse_graph.query import .. + + # becomes + + from cassandra.datastax.graph.fluent import .. + from cassandra.datastax.graph.fluent.query import .. + +See :mod:`~.datastax.graph.fluent`. + +Session.execute and Session.execute_async API +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Although it is not common to use this API with positional arguments, it is +important to be aware that the `host` and `execute_as` parameters have had +their positional order swapped. This is only because `execute_as` was added +in dse-driver before `host`. + +See :meth:`.Session.execute`. + +Deprecations +^^^^^^^^^^^^ + +These changes are optional, but recommended: + +* Importing from `cassandra.graph` is deprecated. Consider importing from `cassandra.datastax.graph`. +* Use :class:`~.policies.DefaultLoadBalancingPolicy` instead of DSELoadBalancingPolicy. + +Upgrading to 3.0 +---------------- +Version 3.0 of the DataStax Python driver for Apache Cassandra +adds support for Cassandra 3.0 while maintaining support for +previously supported versions. In addition to substantial internal rework, +there are several updates to the API that integrators will need +to consider: + +Default consistency is now ``LOCAL_ONE`` +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Previous value was ``ONE``. The new value is introduced to mesh with the default +DC-aware load balancing policy and to match other drivers. + +Execution API Updates +^^^^^^^^^^^^^^^^^^^^^ +Result return normalization +~~~~~~~~~~~~~~~~~~~~~~~~~~~ +`PYTHON-368 `_ + +Previously results would be returned as a ``list`` of rows for result rows +up to ``fetch_size``, and ``PagedResult`` afterward. This could break +application code that assumed one type and got another. + +Now, all results are returned as an iterable :class:`~.ResultSet`. + +The preferred way to consume results of unknown size is to iterate through +them, letting automatic paging occur as they are consumed. + +.. code-block:: python + + results = session.execute("SELECT * FROM system.local") + for row in results: + process(row) + +If the expected size of the results is known, it is still possible to +materialize a list using the iterator: + +.. code-block:: python + + results = session.execute("SELECT * FROM system.local") + row_list = list(results) + +For backward compatibility, :class:`~.ResultSet` supports indexing. When +accessed at an index, a `~.ResultSet` object will materialize all its pages: + +.. code-block:: python + + results = session.execute("SELECT * FROM system.local") + first_result = results[0] # materializes results, fetching all pages + +This can send requests and load (possibly large) results into memory, so +`~.ResultSet` will log a warning on implicit materialization. + +Trace information is not attached to executed Statements +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +`PYTHON-318 `_ + +Previously trace data was attached to Statements if tracing was enabled. This +could lead to confusion if the same statement was used for multiple executions. + +Now, trace data is associated with the ``ResponseFuture`` and ``ResultSet`` +returned for each query: + +:meth:`.ResponseFuture.get_query_trace()` + +:meth:`.ResponseFuture.get_all_query_traces()` + +:meth:`.ResultSet.get_query_trace()` + +:meth:`.ResultSet.get_all_query_traces()` + +Binding named parameters now ignores extra names +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +`PYTHON-178 `_ + +Previously, :meth:`.BoundStatement.bind()` would raise if a mapping +was passed with extra names not found in the prepared statement. + +Behavior in 3.0+ is to ignore extra names. + +blist removed as soft dependency +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +`PYTHON-385 `_ + +Previously the driver had a soft dependency on ``blist sortedset``, using +that where available and using an internal fallback where possible. + +Now, the driver never chooses the ``blist`` variant, instead returning the +internal :class:`.util.SortedSet` for all ``set`` results. The class implements +all standard set operations, so no integration code should need to change unless +it explicitly checks for ``sortedset`` type. + +Metadata API Updates +^^^^^^^^^^^^^^^^^^^^ +`PYTHON-276 `_, `PYTHON-408 `_, `PYTHON-400 `_, `PYTHON-422 `_ + +Cassandra 3.0 brought a substantial overhaul to the internal schema metadata representation. +This version of the driver supports that metadata in addition to the legacy version. Doing so +also brought some changes to the metadata model. + +The present API is documented: :any:`cassandra.metadata`. Changes highlighted below: + +* All types are now exposed as CQL types instead of types derived from the internal server implementation +* Some metadata attributes have changed names to match current nomenclature (for example, :attr:`.Index.kind` in place of ``Index.type``). +* Some metadata attributes removed + + * ``TableMetadata.keyspace`` reference replaced with :attr:`.TableMetadata.keyspace_name` + * ``ColumnMetadata.index`` is removed table- and keyspace-level mappings are still maintained + +Several deprecated features are removed +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +`PYTHON-292 `_ + +* ``ResponseFuture.result`` timeout parameter is removed, use ``Session.execute`` timeout instead (`031ebb0 `_) +* ``Cluster.refresh_schema`` removed, use ``Cluster.refresh_*_metadata`` instead (`419fcdf `_) +* ``Cluster.submit_schema_refresh`` removed (`574266d `_) +* ``cqltypes`` time/date functions removed, use ``util`` entry points instead (`bb984ee `_) +* ``decoder`` module removed (`e16a073 `_) +* ``TableMetadata.keyspace`` attribute replaced with ``keyspace_name`` (`cc94073 `_) +* ``cqlengine.columns.TimeUUID.from_datetime`` removed, use ``util`` variant instead (`96489cc `_) +* ``cqlengine.columns.Float(double_precision)`` parameter removed, use ``columns.Double`` instead (`a2d3a98 `_) +* ``cqlengine`` keyspace management functions are removed in favor of the strategy-specific entry points (`4bd5909 `_) +* ``cqlengine.Model.__polymorphic_*__`` attributes removed, use ``__discriminator*`` attributes instead (`9d98c8e `_) +* ``cqlengine.statements`` will no longer warn about list list prepend behavior (`79efe97 `_) + + +Upgrading to 2.1 from 2.0 +------------------------- +Version 2.1 of the DataStax Python driver for Apache Cassandra +adds support for Cassandra 2.1 and version 3 of the native protocol. + +Cassandra 1.2, 2.0, and 2.1 are all supported. However, 1.2 only +supports protocol version 1, and 2.0 only supports versions 1 and +2, so some features may not be available. + +Using the v3 Native Protocol +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +By default, the driver will attempt to use version 2 of the +native protocol. To use version 3, you must explicitly +set the :attr:`~.Cluster.protocol_version`: + +.. code-block:: python + + from cassandra.cluster import Cluster + + cluster = Cluster(protocol_version=3) + +Note that protocol version 3 is only supported by Cassandra 2.1+. + +In future releases, the driver may default to using protocol version +3. + +Working with User-Defined Types +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Cassandra 2.1 introduced the ability to define new types:: + + USE KEYSPACE mykeyspace; + + CREATE TYPE address (street text, city text, zip int); + +The driver generally expects you to use instances of a specific +class to represent column values of this type. You can let the +driver know what class to use with :meth:`.Cluster.register_user_type`: + +.. code-block:: python + + cluster = Cluster() + + class Address(object): + + def __init__(self, street, city, zipcode): + self.street = street + self.city = text + self.zipcode = zipcode + + cluster.register_user_type('mykeyspace', 'address', Address) + +When inserting data for ``address`` columns, you should pass in +instances of ``Address``. When querying data, ``address`` column +values will be instances of ``Address``. + +If no class is registered for a user-defined type, query results +will use a ``namedtuple`` class and data may only be inserted +though prepared statements. + +See :ref:`udts` for more details. + +Customizing Encoders for Non-prepared Statements +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Starting with version 2.1 of the driver, it is possible to customize +how Python types are converted to CQL literals when working with +non-prepared statements. This is done on a per-:class:`~.Session` +basis through :attr:`.Session.encoder`: + +.. code-block:: python + + cluster = Cluster() + session = cluster.connect() + session.encoder.mapping[tuple] = session.encoder.cql_encode_tuple + +See :ref:`type-conversions` for the table of default CQL literal conversions. + +Using Client-Side Protocol-Level Timestamps +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +With version 3 of the native protocol, timestamps may be supplied by the +client at the protocol level. (Normally, if they are not specified within +the CQL query itself, a timestamp is generated server-side.) + +When :attr:`~.Cluster.protocol_version` is set to 3 or higher, the driver +will automatically use client-side timestamps with microsecond precision +unless :attr:`.Session.use_client_timestamp` is changed to :const:`False`. +If a timestamp is specified within the CQL query, it will override the +timestamp generated by the driver. + +Upgrading to 2.0 from 1.x +------------------------- +Version 2.0 of the DataStax Python driver for Apache Cassandra +includes some notable improvements over version 1.x. This version +of the driver supports Cassandra 1.2, 2.0, and 2.1. However, not +all features may be used with Cassandra 1.2, and some new features +in 2.1 are not yet supported. + +Using the v2 Native Protocol +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +By default, the driver will attempt to use version 2 of Cassandra's +native protocol. You can explicitly set the protocol version to +2, though: + +.. code-block:: python + + from cassandra.cluster import Cluster + + cluster = Cluster(protocol_version=2) + +When working with Cassandra 1.2, you will need to +explicitly set the :attr:`~.Cluster.protocol_version` to 1: + +.. code-block:: python + + from cassandra.cluster import Cluster + + cluster = Cluster(protocol_version=1) + +Automatic Query Paging +^^^^^^^^^^^^^^^^^^^^^^ +Version 2 of the native protocol adds support for automatic query +paging, which can make dealing with large result sets much simpler. + +See :ref:`query-paging` for full details. + +Protocol-Level Batch Statements +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +With version 1 of the native protocol, batching of statements required +using a `BATCH cql query `_. +With version 2 of the native protocol, you can now batch statements at +the protocol level. This allows you to use many different prepared +statements within a single batch. + +See :class:`~.query.BatchStatement` for details and usage examples. + +SASL-based Authentication +^^^^^^^^^^^^^^^^^^^^^^^^^ +Also new in version 2 of the native protocol is SASL-based authentication. +See the section on :ref:`security` for details and examples. + +Lightweight Transactions +^^^^^^^^^^^^^^^^^^^^^^^^ +`Lightweight transactions `_ are another new feature. To use lightweight transactions, add ``IF`` clauses +to your CQL queries and set the :attr:`~.Statement.serial_consistency_level` +on your statements. + +Calling Cluster.shutdown() +^^^^^^^^^^^^^^^^^^^^^^^^^^ +In order to fix some issues around garbage collection and unclean interpreter +shutdowns, version 2.0 of the driver requires you to call :meth:`.Cluster.shutdown()` +on your :class:`~.Cluster` objects when you are through with them. +This helps to guarantee a clean shutdown. + +Deprecations +^^^^^^^^^^^^ +The following functions have moved from ``cassandra.decoder`` to ``cassandra.query``. +The original functions have been left in place with a :exc:`DeprecationWarning` for +now: + +* :attr:`cassandra.decoder.tuple_factory` has moved to + :attr:`cassandra.query.tuple_factory` +* :attr:`cassandra.decoder.named_tuple_factory` has moved to + :attr:`cassandra.query.named_tuple_factory` +* :attr:`cassandra.decoder.dict_factory` has moved to + :attr:`cassandra.query.dict_factory` +* :attr:`cassandra.decoder.ordered_dict_factory` has moved to + :attr:`cassandra.query.ordered_dict_factory` + +Dependency Changes +^^^^^^^^^^^^^^^^^^ +The following dependencies have officially been made optional: + +* ``scales`` +* ``blist`` + +And one new dependency has been added (to enable Python 3 support): + +* ``six`` diff --git a/3.26.2-scylla/_sources/user-defined-types.rst.txt b/3.26.2-scylla/_sources/user-defined-types.rst.txt new file mode 100644 index 0000000000..32c03e37e8 --- /dev/null +++ b/3.26.2-scylla/_sources/user-defined-types.rst.txt @@ -0,0 +1,118 @@ +.. _udts: + +User Defined Types +================== +Cassandra 2.1 introduced user-defined types (UDTs). You can create a +new type through ``CREATE TYPE`` statements in CQL:: + + CREATE TYPE address (street text, zip int); + +Version 2.1 of the Python driver adds support for user-defined types. + +Registering a UDT +----------------- +You can tell the Python driver to return columns of a specific UDT as +instances of a class or a dict by registering them with your :class:`~.Cluster` +instance through :meth:`.Cluster.register_user_type`: + + +Map a Class to a UDT +++++++++++++++++++++ + +.. code-block:: python + + cluster = Cluster(protocol_version=3) + session = cluster.connect() + session.set_keyspace('mykeyspace') + session.execute("CREATE TYPE address (street text, zipcode int)") + session.execute("CREATE TABLE users (id int PRIMARY KEY, location frozen
)") + + # create a class to map to the "address" UDT + class Address(object): + + def __init__(self, street, zipcode): + self.street = street + self.zipcode = zipcode + + cluster.register_user_type('mykeyspace', 'address', Address) + + # insert a row using an instance of Address + session.execute("INSERT INTO users (id, location) VALUES (%s, %s)", + (0, Address("123 Main St.", 78723))) + + # results will include Address instances + results = session.execute("SELECT * FROM users") + row = results[0] + print(row.id, row.location.street, row.location.zipcode) + +Map a dict to a UDT ++++++++++++++++++++ + +.. code-block:: python + + cluster = Cluster(protocol_version=3) + session = cluster.connect() + session.set_keyspace('mykeyspace') + session.execute("CREATE TYPE address (street text, zipcode int)") + session.execute("CREATE TABLE users (id int PRIMARY KEY, location frozen
)") + + cluster.register_user_type('mykeyspace', 'address', dict) + + # insert a row using a prepared statement and a tuple + insert_statement = session.prepare("INSERT INTO mykeyspace.users (id, location) VALUES (?, ?)") + session.execute(insert_statement, [0, ("123 Main St.", 78723)]) + + # results will include dict instances + results = session.execute("SELECT * FROM users") + row = results[0] + print(row.id, row.location['street'], row.location['zipcode']) + +Using UDTs Without Registering Them +----------------------------------- +Although it is recommended to register your types with +:meth:`.Cluster.register_user_type`, the driver gives you some options +for working with unregistered UDTS. + +When you use prepared statements, the driver knows what data types to +expect for each placeholder. This allows you to pass any object you +want for a UDT, as long as it has attributes that match the field names +for the UDT: + +.. code-block:: python + + cluster = Cluster(protocol_version=3) + session = cluster.connect() + session.set_keyspace('mykeyspace') + session.execute("CREATE TYPE address (street text, zipcode int)") + session.execute("CREATE TABLE users (id int PRIMARY KEY, location frozen
)") + + class Foo(object): + + def __init__(self, street, zipcode, otherstuff): + self.street = street + self.zipcode = zipcode + self.otherstuff = otherstuff + + insert_statement = session.prepare("INSERT INTO users (id, location) VALUES (?, ?)") + + # since we're using a prepared statement, we don't *have* to register + # a class to map to the UDT to insert data. The object just needs to have + # "street" and "zipcode" attributes (which Foo does): + session.execute(insert_statement, [0, Foo("123 Main St.", 78723, "some other stuff")]) + + # when we query data, UDT columns that don't have a class registered + # will be returned as namedtuples: + results = session.execute("SELECT * FROM users") + first_row = results[0] + address = first_row.location + print(address) # prints "Address(street='123 Main St.', zipcode=78723)" + street = address.street + zipcode = address.street + +As shown in the code example, inserting data for UDT columns without registering +a class works fine for prepared statements. However, **you must register a +class to insert UDT columns with unprepared statements**.\* You can still query +UDT columns without registered classes using unprepared statements, they will +simply return ``namedtuple`` instances (just like prepared statements do). + +\* this applies to *parameterized* unprepared statements, in which the driver will be formatting parameters -- not statements with interpolated UDT literals. diff --git a/3.26.2-scylla/_static/basic.css b/3.26.2-scylla/_static/basic.css new file mode 100644 index 0000000000..603f6a8798 --- /dev/null +++ b/3.26.2-scylla/_static/basic.css @@ -0,0 +1,905 @@ +/* + * basic.css + * ~~~~~~~~~ + * + * Sphinx stylesheet -- basic theme. + * + * :copyright: Copyright 2007-2021 by the Sphinx team, see AUTHORS. + * :license: BSD, see LICENSE for details. + * + */ + +/* -- main layout ----------------------------------------------------------- */ + +div.clearer { + clear: both; +} + +div.section::after { + display: block; + content: ''; + clear: left; +} + +/* -- relbar ---------------------------------------------------------------- */ + +div.related { + width: 100%; + font-size: 90%; +} + +div.related h3 { + display: none; +} + +div.related ul { + margin: 0; + padding: 0 0 0 10px; + list-style: none; +} + +div.related li { + display: inline; +} + +div.related li.right { + float: right; + margin-right: 5px; +} + +/* -- sidebar --------------------------------------------------------------- */ + +div.sphinxsidebarwrapper { + padding: 10px 5px 0 10px; +} + +div.sphinxsidebar { + float: left; + width: 230px; + margin-left: -100%; + font-size: 90%; + word-wrap: break-word; + overflow-wrap : break-word; +} + +div.sphinxsidebar ul { + list-style: none; +} + +div.sphinxsidebar ul ul, +div.sphinxsidebar ul.want-points { + margin-left: 20px; + list-style: square; +} + +div.sphinxsidebar ul ul { + margin-top: 0; + margin-bottom: 0; +} + +div.sphinxsidebar form { + margin-top: 10px; +} + +div.sphinxsidebar input { + border: 1px solid #98dbcc; + font-family: sans-serif; + font-size: 1em; +} + +div.sphinxsidebar #searchbox form.search { + overflow: hidden; +} + +div.sphinxsidebar #searchbox input[type="text"] { + float: left; + width: 80%; + padding: 0.25em; + box-sizing: border-box; +} + +div.sphinxsidebar #searchbox input[type="submit"] { + float: left; + width: 20%; + border-left: none; + padding: 0.25em; + box-sizing: border-box; +} + + +img { + border: 0; + max-width: 100%; +} + +/* -- search page ----------------------------------------------------------- */ + +ul.search { + margin: 10px 0 0 20px; + padding: 0; +} + +ul.search li { + padding: 5px 0 5px 20px; + background-image: url(file.png); + background-repeat: no-repeat; + background-position: 0 7px; +} + +ul.search li a { + font-weight: bold; +} + +ul.search li p.context { + color: #888; + margin: 2px 0 0 30px; + text-align: left; +} + +ul.keywordmatches li.goodmatch a { + font-weight: bold; +} + +/* -- index page ------------------------------------------------------------ */ + +table.contentstable { + width: 90%; + margin-left: auto; + margin-right: auto; +} + +table.contentstable p.biglink { + line-height: 150%; +} + +a.biglink { + font-size: 1.3em; +} + +span.linkdescr { + font-style: italic; + padding-top: 5px; + font-size: 90%; +} + +/* -- general index --------------------------------------------------------- */ + +table.indextable { + width: 100%; +} + +table.indextable td { + text-align: left; + vertical-align: top; +} + +table.indextable ul { + margin-top: 0; + margin-bottom: 0; + list-style-type: none; +} + +table.indextable > tbody > tr > td > ul { + padding-left: 0em; +} + +table.indextable tr.pcap { + height: 10px; +} + +table.indextable tr.cap { + margin-top: 10px; + background-color: #f2f2f2; +} + +img.toggler { + margin-right: 3px; + margin-top: 3px; + cursor: pointer; +} + +div.modindex-jumpbox { + border-top: 1px solid #ddd; + border-bottom: 1px solid #ddd; + margin: 1em 0 1em 0; + padding: 0.4em; +} + +div.genindex-jumpbox { + border-top: 1px solid #ddd; + border-bottom: 1px solid #ddd; + margin: 1em 0 1em 0; + padding: 0.4em; +} + +/* -- domain module index --------------------------------------------------- */ + +table.modindextable td { + padding: 2px; + border-collapse: collapse; +} + +/* -- general body styles --------------------------------------------------- */ + +div.body { + min-width: 450px; + max-width: 800px; +} + +div.body p, div.body dd, div.body li, div.body blockquote { + -moz-hyphens: auto; + -ms-hyphens: auto; + -webkit-hyphens: auto; + hyphens: auto; +} + +a.headerlink { + visibility: hidden; +} + +a.brackets:before, +span.brackets > a:before{ + content: "["; +} + +a.brackets:after, +span.brackets > a:after { + content: "]"; +} + +h1:hover > a.headerlink, +h2:hover > a.headerlink, +h3:hover > a.headerlink, +h4:hover > a.headerlink, +h5:hover > a.headerlink, +h6:hover > a.headerlink, +dt:hover > a.headerlink, +caption:hover > a.headerlink, +p.caption:hover > a.headerlink, +div.code-block-caption:hover > a.headerlink { + visibility: visible; +} + +div.body p.caption { + text-align: inherit; +} + +div.body td { + text-align: left; +} + +.first { + margin-top: 0 !important; +} + +p.rubric { + margin-top: 30px; + font-weight: bold; +} + +img.align-left, figure.align-left, .figure.align-left, object.align-left { + clear: left; + float: left; + margin-right: 1em; +} + +img.align-right, figure.align-right, .figure.align-right, object.align-right { + clear: right; + float: right; + margin-left: 1em; +} + +img.align-center, figure.align-center, .figure.align-center, object.align-center { + display: block; + margin-left: auto; + margin-right: auto; +} + +img.align-default, figure.align-default, .figure.align-default { + display: block; + margin-left: auto; + margin-right: auto; +} + +.align-left { + text-align: left; +} + +.align-center { + text-align: center; +} + +.align-default { + text-align: center; +} + +.align-right { + text-align: right; +} + +/* -- sidebars -------------------------------------------------------------- */ + +div.sidebar, +aside.sidebar { + margin: 0 0 0.5em 1em; + border: 1px solid #ddb; + padding: 7px; + background-color: #ffe; + width: 40%; + float: right; + clear: right; + overflow-x: auto; +} + +p.sidebar-title { + font-weight: bold; +} + +div.admonition, div.topic, blockquote { + clear: left; +} + +/* -- topics ---------------------------------------------------------------- */ + +div.topic { + border: 1px solid #ccc; + padding: 7px; + margin: 10px 0 10px 0; +} + +p.topic-title { + font-size: 1.1em; + font-weight: bold; + margin-top: 10px; +} + +/* -- admonitions ----------------------------------------------------------- */ + +div.admonition { + margin-top: 10px; + margin-bottom: 10px; + padding: 7px; +} + +div.admonition dt { + font-weight: bold; +} + +p.admonition-title { + margin: 0px 10px 5px 0px; + font-weight: bold; +} + +div.body p.centered { + text-align: center; + margin-top: 25px; +} + +/* -- content of sidebars/topics/admonitions -------------------------------- */ + +div.sidebar > :last-child, +aside.sidebar > :last-child, +div.topic > :last-child, +div.admonition > :last-child { + margin-bottom: 0; +} + +div.sidebar::after, +aside.sidebar::after, +div.topic::after, +div.admonition::after, +blockquote::after { + display: block; + content: ''; + clear: both; +} + +/* -- tables ---------------------------------------------------------------- */ + +table.docutils { + margin-top: 10px; + margin-bottom: 10px; + border: 0; + border-collapse: collapse; +} + +table.align-center { + margin-left: auto; + margin-right: auto; +} + +table.align-default { + margin-left: auto; + margin-right: auto; +} + +table caption span.caption-number { + font-style: italic; +} + +table caption span.caption-text { +} + +table.docutils td, table.docutils th { + padding: 1px 8px 1px 5px; + border-top: 0; + border-left: 0; + border-right: 0; + border-bottom: 1px solid #aaa; +} + +table.footnote td, table.footnote th { + border: 0 !important; +} + +th { + text-align: left; + padding-right: 5px; +} + +table.citation { + border-left: solid 1px gray; + margin-left: 1px; +} + +table.citation td { + border-bottom: none; +} + +th > :first-child, +td > :first-child { + margin-top: 0px; +} + +th > :last-child, +td > :last-child { + margin-bottom: 0px; +} + +/* -- figures --------------------------------------------------------------- */ + +div.figure, figure { + margin: 0.5em; + padding: 0.5em; +} + +div.figure p.caption, figcaption { + padding: 0.3em; +} + +div.figure p.caption span.caption-number, +figcaption span.caption-number { + font-style: italic; +} + +div.figure p.caption span.caption-text, +figcaption span.caption-text { +} + +/* -- field list styles ----------------------------------------------------- */ + +table.field-list td, table.field-list th { + border: 0 !important; +} + +.field-list ul { + margin: 0; + padding-left: 1em; +} + +.field-list p { + margin: 0; +} + +.field-name { + -moz-hyphens: manual; + -ms-hyphens: manual; + -webkit-hyphens: manual; + hyphens: manual; +} + +/* -- hlist styles ---------------------------------------------------------- */ + +table.hlist { + margin: 1em 0; +} + +table.hlist td { + vertical-align: top; +} + +/* -- object description styles --------------------------------------------- */ + +.sig { + font-family: 'Consolas', 'Menlo', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace; +} + +.sig-name, code.descname { + background-color: transparent; + font-weight: bold; +} + +.sig-name { + font-size: 1.1em; +} + +code.descname { + font-size: 1.2em; +} + +.sig-prename, code.descclassname { + background-color: transparent; +} + +.optional { + font-size: 1.3em; +} + +.sig-paren { + font-size: larger; +} + +.sig-param.n { + font-style: italic; +} + +/* C++ specific styling */ + +.sig-inline.c-texpr, +.sig-inline.cpp-texpr { + font-family: unset; +} + +.sig.c .k, .sig.c .kt, +.sig.cpp .k, .sig.cpp .kt { + color: #0033B3; +} + +.sig.c .m, +.sig.cpp .m { + color: #1750EB; +} + +.sig.c .s, .sig.c .sc, +.sig.cpp .s, .sig.cpp .sc { + color: #067D17; +} + + +/* -- other body styles ----------------------------------------------------- */ + +ol.arabic { + list-style: decimal; +} + +ol.loweralpha { + list-style: lower-alpha; +} + +ol.upperalpha { + list-style: upper-alpha; +} + +ol.lowerroman { + list-style: lower-roman; +} + +ol.upperroman { + list-style: upper-roman; +} + +:not(li) > ol > li:first-child > :first-child, +:not(li) > ul > li:first-child > :first-child { + margin-top: 0px; +} + +:not(li) > ol > li:last-child > :last-child, +:not(li) > ul > li:last-child > :last-child { + margin-bottom: 0px; +} + +ol.simple ol p, +ol.simple ul p, +ul.simple ol p, +ul.simple ul p { + margin-top: 0; +} + +ol.simple > li:not(:first-child) > p, +ul.simple > li:not(:first-child) > p { + margin-top: 0; +} + +ol.simple p, +ul.simple p { + margin-bottom: 0; +} + +dl.footnote > dt, +dl.citation > dt { + float: left; + margin-right: 0.5em; +} + +dl.footnote > dd, +dl.citation > dd { + margin-bottom: 0em; +} + +dl.footnote > dd:after, +dl.citation > dd:after { + content: ""; + clear: both; +} + +dl.field-list { + display: grid; + grid-template-columns: fit-content(30%) auto; +} + +dl.field-list > dt { + font-weight: bold; + word-break: break-word; + padding-left: 0.5em; + padding-right: 5px; +} + +dl.field-list > dt:after { + content: ":"; +} + +dl.field-list > dd { + padding-left: 0.5em; + margin-top: 0em; + margin-left: 0em; + margin-bottom: 0em; +} + +dl { + margin-bottom: 15px; +} + +dd > :first-child { + margin-top: 0px; +} + +dd ul, dd table { + margin-bottom: 10px; +} + +dd { + margin-top: 3px; + margin-bottom: 10px; + margin-left: 30px; +} + +dl > dd:last-child, +dl > dd:last-child > :last-child { + margin-bottom: 0; +} + +dt:target, span.highlighted { + background-color: #fbe54e; +} + +rect.highlighted { + fill: #fbe54e; +} + +dl.glossary dt { + font-weight: bold; + font-size: 1.1em; +} + +.versionmodified { + font-style: italic; +} + +.system-message { + background-color: #fda; + padding: 5px; + border: 3px solid red; +} + +.footnote:target { + background-color: #ffa; +} + +.line-block { + display: block; + margin-top: 1em; + margin-bottom: 1em; +} + +.line-block .line-block { + margin-top: 0; + margin-bottom: 0; + margin-left: 1.5em; +} + +.guilabel, .menuselection { + font-family: sans-serif; +} + +.accelerator { + text-decoration: underline; +} + +.classifier { + font-style: oblique; +} + +.classifier:before { + font-style: normal; + margin: 0 0.5em; + content: ":"; + display: inline-block; +} + +abbr, acronym { + border-bottom: dotted 1px; + cursor: help; +} + +/* -- code displays --------------------------------------------------------- */ + +pre { + overflow: auto; + overflow-y: hidden; /* fixes display issues on Chrome browsers */ +} + +pre, div[class*="highlight-"] { + clear: both; +} + +span.pre { + -moz-hyphens: none; + -ms-hyphens: none; + -webkit-hyphens: none; + hyphens: none; +} + +div[class*="highlight-"] { + margin: 1em 0; +} + +td.linenos pre { + border: 0; + background-color: transparent; + color: #aaa; +} + +table.highlighttable { + display: block; +} + +table.highlighttable tbody { + display: block; +} + +table.highlighttable tr { + display: flex; +} + +table.highlighttable td { + margin: 0; + padding: 0; +} + +table.highlighttable td.linenos { + padding-right: 0.5em; +} + +table.highlighttable td.code { + flex: 1; + overflow: hidden; +} + +.highlight .hll { + display: block; +} + +div.highlight pre, +table.highlighttable pre { + margin: 0; +} + +div.code-block-caption + div { + margin-top: 0; +} + +div.code-block-caption { + margin-top: 1em; + padding: 2px 5px; + font-size: small; +} + +div.code-block-caption code { + background-color: transparent; +} + +table.highlighttable td.linenos, +span.linenos, +div.highlight span.gp { /* gp: Generic.Prompt */ + user-select: none; + -webkit-user-select: text; /* Safari fallback only */ + -webkit-user-select: none; /* Chrome/Safari */ + -moz-user-select: none; /* Firefox */ + -ms-user-select: none; /* IE10+ */ +} + +div.code-block-caption span.caption-number { + padding: 0.1em 0.3em; + font-style: italic; +} + +div.code-block-caption span.caption-text { +} + +div.literal-block-wrapper { + margin: 1em 0; +} + +code.xref, a code { + background-color: transparent; + font-weight: bold; +} + +h1 code, h2 code, h3 code, h4 code, h5 code, h6 code { + background-color: transparent; +} + +.viewcode-link { + float: right; +} + +.viewcode-back { + float: right; + font-family: sans-serif; +} + +div.viewcode-block:target { + margin: -1px -10px; + padding: 0 10px; +} + +/* -- math display ---------------------------------------------------------- */ + +img.math { + vertical-align: middle; +} + +div.body div.math p { + text-align: center; +} + +span.eqno { + float: right; +} + +span.eqno a.headerlink { + position: absolute; + z-index: 1; +} + +div.math:hover a.headerlink { + visibility: visible; +} + +/* -- printout stylesheet --------------------------------------------------- */ + +@media print { + div.document, + div.documentwrapper, + div.bodywrapper { + margin: 0 !important; + width: 100%; + } + + div.sphinxsidebar, + div.related, + div.footer, + #top-link { + display: none; + } +} \ No newline at end of file diff --git a/3.26.2-scylla/_static/check-solid.svg b/3.26.2-scylla/_static/check-solid.svg new file mode 100644 index 0000000000..92fad4b5c0 --- /dev/null +++ b/3.26.2-scylla/_static/check-solid.svg @@ -0,0 +1,4 @@ + + + + diff --git a/3.26.2-scylla/_static/clipboard.min.js b/3.26.2-scylla/_static/clipboard.min.js new file mode 100644 index 0000000000..54b3c46381 --- /dev/null +++ b/3.26.2-scylla/_static/clipboard.min.js @@ -0,0 +1,7 @@ +/*! + * clipboard.js v2.0.8 + * https://clipboardjs.com/ + * + * Licensed MIT © Zeno Rocha + */ +!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?exports.ClipboardJS=e():t.ClipboardJS=e()}(this,function(){return n={686:function(t,e,n){"use strict";n.d(e,{default:function(){return o}});var e=n(279),i=n.n(e),e=n(370),u=n.n(e),e=n(817),c=n.n(e);function a(t){try{return document.execCommand(t)}catch(t){return}}var f=function(t){t=c()(t);return a("cut"),t};var l=function(t){var e,n,o,r=1 + + + + diff --git a/3.26.2-scylla/_static/copybutton.css b/3.26.2-scylla/_static/copybutton.css new file mode 100644 index 0000000000..f1916ec7d1 --- /dev/null +++ b/3.26.2-scylla/_static/copybutton.css @@ -0,0 +1,94 @@ +/* Copy buttons */ +button.copybtn { + position: absolute; + display: flex; + top: .3em; + right: .3em; + width: 1.7em; + height: 1.7em; + opacity: 0; + transition: opacity 0.3s, border .3s, background-color .3s; + user-select: none; + padding: 0; + border: none; + outline: none; + border-radius: 0.4em; + /* The colors that GitHub uses */ + border: #1b1f2426 1px solid; + background-color: #f6f8fa; + color: #57606a; +} + +button.copybtn.success { + border-color: #22863a; + color: #22863a; +} + +button.copybtn svg { + stroke: currentColor; + width: 1.5em; + height: 1.5em; + padding: 0.1em; +} + +div.highlight { + position: relative; +} + +/* Show the copybutton */ +.highlight:hover button.copybtn, button.copybtn.success { + opacity: 1; +} + +.highlight button.copybtn:hover { + background-color: rgb(235, 235, 235); +} + +.highlight button.copybtn:active { + background-color: rgb(187, 187, 187); +} + +/** + * A minimal CSS-only tooltip copied from: + * https://codepen.io/mildrenben/pen/rVBrpK + * + * To use, write HTML like the following: + * + *

Short

+ */ + .o-tooltip--left { + position: relative; + } + + .o-tooltip--left:after { + opacity: 0; + visibility: hidden; + position: absolute; + content: attr(data-tooltip); + padding: .2em; + font-size: .8em; + left: -.2em; + background: grey; + color: white; + white-space: nowrap; + z-index: 2; + border-radius: 2px; + transform: translateX(-102%) translateY(0); + transition: opacity 0.2s cubic-bezier(0.64, 0.09, 0.08, 1), transform 0.2s cubic-bezier(0.64, 0.09, 0.08, 1); +} + +.o-tooltip--left:hover:after { + display: block; + opacity: 1; + visibility: visible; + transform: translateX(-100%) translateY(0); + transition: opacity 0.2s cubic-bezier(0.64, 0.09, 0.08, 1), transform 0.2s cubic-bezier(0.64, 0.09, 0.08, 1); + transition-delay: .5s; +} + +/* By default the copy button shouldn't show up when printing a page */ +@media print { + button.copybtn { + display: none; + } +} diff --git a/3.26.2-scylla/_static/copybutton.js b/3.26.2-scylla/_static/copybutton.js new file mode 100644 index 0000000000..2ea7ff3e21 --- /dev/null +++ b/3.26.2-scylla/_static/copybutton.js @@ -0,0 +1,248 @@ +// Localization support +const messages = { + 'en': { + 'copy': 'Copy', + 'copy_to_clipboard': 'Copy to clipboard', + 'copy_success': 'Copied!', + 'copy_failure': 'Failed to copy', + }, + 'es' : { + 'copy': 'Copiar', + 'copy_to_clipboard': 'Copiar al portapapeles', + 'copy_success': '¡Copiado!', + 'copy_failure': 'Error al copiar', + }, + 'de' : { + 'copy': 'Kopieren', + 'copy_to_clipboard': 'In die Zwischenablage kopieren', + 'copy_success': 'Kopiert!', + 'copy_failure': 'Fehler beim Kopieren', + }, + 'fr' : { + 'copy': 'Copier', + 'copy_to_clipboard': 'Copier dans le presse-papier', + 'copy_success': 'Copié !', + 'copy_failure': 'Échec de la copie', + }, + 'ru': { + 'copy': 'Скопировать', + 'copy_to_clipboard': 'Скопировать в буфер', + 'copy_success': 'Скопировано!', + 'copy_failure': 'Не удалось скопировать', + }, + 'zh-CN': { + 'copy': '复制', + 'copy_to_clipboard': '复制到剪贴板', + 'copy_success': '复制成功!', + 'copy_failure': '复制失败', + }, + 'it' : { + 'copy': 'Copiare', + 'copy_to_clipboard': 'Copiato negli appunti', + 'copy_success': 'Copiato!', + 'copy_failure': 'Errore durante la copia', + } +} + +let locale = 'en' +if( document.documentElement.lang !== undefined + && messages[document.documentElement.lang] !== undefined ) { + locale = document.documentElement.lang +} + +let doc_url_root = DOCUMENTATION_OPTIONS.URL_ROOT; +if (doc_url_root == '#') { + doc_url_root = ''; +} + +/** + * SVG files for our copy buttons + */ +let iconCheck = ` + ${messages[locale]['copy_success']} + + +` + +// If the user specified their own SVG use that, otherwise use the default +let iconCopy = ``; +if (!iconCopy) { + iconCopy = ` + ${messages[locale]['copy_to_clipboard']} + + + +` +} + +/** + * Set up copy/paste for code blocks + */ + +const runWhenDOMLoaded = cb => { + if (document.readyState != 'loading') { + cb() + } else if (document.addEventListener) { + document.addEventListener('DOMContentLoaded', cb) + } else { + document.attachEvent('onreadystatechange', function() { + if (document.readyState == 'complete') cb() + }) + } +} + +const codeCellId = index => `codecell${index}` + +// Clears selected text since ClipboardJS will select the text when copying +const clearSelection = () => { + if (window.getSelection) { + window.getSelection().removeAllRanges() + } else if (document.selection) { + document.selection.empty() + } +} + +// Changes tooltip text for a moment, then changes it back +// We want the timeout of our `success` class to be a bit shorter than the +// tooltip and icon change, so that we can hide the icon before changing back. +var timeoutIcon = 2000; +var timeoutSuccessClass = 1500; + +const temporarilyChangeTooltip = (el, oldText, newText) => { + el.setAttribute('data-tooltip', newText) + el.classList.add('success') + // Remove success a little bit sooner than we change the tooltip + // So that we can use CSS to hide the copybutton first + setTimeout(() => el.classList.remove('success'), timeoutSuccessClass) + setTimeout(() => el.setAttribute('data-tooltip', oldText), timeoutIcon) +} + +// Changes the copy button icon for two seconds, then changes it back +const temporarilyChangeIcon = (el) => { + el.innerHTML = iconCheck; + setTimeout(() => {el.innerHTML = iconCopy}, timeoutIcon) +} + +const addCopyButtonToCodeCells = () => { + // If ClipboardJS hasn't loaded, wait a bit and try again. This + // happens because we load ClipboardJS asynchronously. + if (window.ClipboardJS === undefined) { + setTimeout(addCopyButtonToCodeCells, 250) + return + } + + // Add copybuttons to all of our code cells + const COPYBUTTON_SELECTOR = 'div.highlight pre'; + const codeCells = document.querySelectorAll(COPYBUTTON_SELECTOR) + codeCells.forEach((codeCell, index) => { + const id = codeCellId(index) + codeCell.setAttribute('id', id) + + const clipboardButton = id => + `` + codeCell.insertAdjacentHTML('afterend', clipboardButton(id)) + }) + +function escapeRegExp(string) { + return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string +} + +/** + * Removes excluded text from a Node. + * + * @param {Node} target Node to filter. + * @param {string} exclude CSS selector of nodes to exclude. + * @returns {DOMString} Text from `target` with text removed. + */ +function filterText(target, exclude) { + const clone = target.cloneNode(true); // clone as to not modify the live DOM + if (exclude) { + // remove excluded nodes + clone.querySelectorAll(exclude).forEach(node => node.remove()); + } + return clone.innerText; +} + +// Callback when a copy button is clicked. Will be passed the node that was clicked +// should then grab the text and replace pieces of text that shouldn't be used in output +function formatCopyText(textContent, copybuttonPromptText, isRegexp = false, onlyCopyPromptLines = true, removePrompts = true, copyEmptyLines = true, lineContinuationChar = "", hereDocDelim = "") { + var regexp; + var match; + + // Do we check for line continuation characters and "HERE-documents"? + var useLineCont = !!lineContinuationChar + var useHereDoc = !!hereDocDelim + + // create regexp to capture prompt and remaining line + if (isRegexp) { + regexp = new RegExp('^(' + copybuttonPromptText + ')(.*)') + } else { + regexp = new RegExp('^(' + escapeRegExp(copybuttonPromptText) + ')(.*)') + } + + const outputLines = []; + var promptFound = false; + var gotLineCont = false; + var gotHereDoc = false; + const lineGotPrompt = []; + for (const line of textContent.split('\n')) { + match = line.match(regexp) + if (match || gotLineCont || gotHereDoc) { + promptFound = regexp.test(line) + lineGotPrompt.push(promptFound) + if (removePrompts && promptFound) { + outputLines.push(match[2]) + } else { + outputLines.push(line) + } + gotLineCont = line.endsWith(lineContinuationChar) & useLineCont + if (line.includes(hereDocDelim) & useHereDoc) + gotHereDoc = !gotHereDoc + } else if (!onlyCopyPromptLines) { + outputLines.push(line) + } else if (copyEmptyLines && line.trim() === '') { + outputLines.push(line) + } + } + + // If no lines with the prompt were found then just use original lines + if (lineGotPrompt.some(v => v === true)) { + textContent = outputLines.join('\n'); + } + + // Remove a trailing newline to avoid auto-running when pasting + if (textContent.endsWith("\n")) { + textContent = textContent.slice(0, -1) + } + return textContent +} + + +var copyTargetText = (trigger) => { + var target = document.querySelector(trigger.attributes['data-clipboard-target'].value); + + // get filtered text + let exclude = '.linenos'; + + let text = filterText(target, exclude); + return formatCopyText(text, '', false, true, true, true, '', '') +} + + // Initialize with a callback so we can modify the text before copy + const clipboard = new ClipboardJS('.copybtn', {text: copyTargetText}) + + // Update UI with error/success messages + clipboard.on('success', event => { + clearSelection() + temporarilyChangeTooltip(event.trigger, messages[locale]['copy'], messages[locale]['copy_success']) + temporarilyChangeIcon(event.trigger) + }) + + clipboard.on('error', event => { + temporarilyChangeTooltip(event.trigger, messages[locale]['copy'], messages[locale]['copy_failure']) + }) +} + +runWhenDOMLoaded(addCopyButtonToCodeCells) \ No newline at end of file diff --git a/3.26.2-scylla/_static/copybutton_funcs.js b/3.26.2-scylla/_static/copybutton_funcs.js new file mode 100644 index 0000000000..dbe1aaad79 --- /dev/null +++ b/3.26.2-scylla/_static/copybutton_funcs.js @@ -0,0 +1,73 @@ +function escapeRegExp(string) { + return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string +} + +/** + * Removes excluded text from a Node. + * + * @param {Node} target Node to filter. + * @param {string} exclude CSS selector of nodes to exclude. + * @returns {DOMString} Text from `target` with text removed. + */ +export function filterText(target, exclude) { + const clone = target.cloneNode(true); // clone as to not modify the live DOM + if (exclude) { + // remove excluded nodes + clone.querySelectorAll(exclude).forEach(node => node.remove()); + } + return clone.innerText; +} + +// Callback when a copy button is clicked. Will be passed the node that was clicked +// should then grab the text and replace pieces of text that shouldn't be used in output +export function formatCopyText(textContent, copybuttonPromptText, isRegexp = false, onlyCopyPromptLines = true, removePrompts = true, copyEmptyLines = true, lineContinuationChar = "", hereDocDelim = "") { + var regexp; + var match; + + // Do we check for line continuation characters and "HERE-documents"? + var useLineCont = !!lineContinuationChar + var useHereDoc = !!hereDocDelim + + // create regexp to capture prompt and remaining line + if (isRegexp) { + regexp = new RegExp('^(' + copybuttonPromptText + ')(.*)') + } else { + regexp = new RegExp('^(' + escapeRegExp(copybuttonPromptText) + ')(.*)') + } + + const outputLines = []; + var promptFound = false; + var gotLineCont = false; + var gotHereDoc = false; + const lineGotPrompt = []; + for (const line of textContent.split('\n')) { + match = line.match(regexp) + if (match || gotLineCont || gotHereDoc) { + promptFound = regexp.test(line) + lineGotPrompt.push(promptFound) + if (removePrompts && promptFound) { + outputLines.push(match[2]) + } else { + outputLines.push(line) + } + gotLineCont = line.endsWith(lineContinuationChar) & useLineCont + if (line.includes(hereDocDelim) & useHereDoc) + gotHereDoc = !gotHereDoc + } else if (!onlyCopyPromptLines) { + outputLines.push(line) + } else if (copyEmptyLines && line.trim() === '') { + outputLines.push(line) + } + } + + // If no lines with the prompt were found then just use original lines + if (lineGotPrompt.some(v => v === true)) { + textContent = outputLines.join('\n'); + } + + // Remove a trailing newline to avoid auto-running when pasting + if (textContent.endsWith("\n")) { + textContent = textContent.slice(0, -1) + } + return textContent +} diff --git a/3.26.2-scylla/_static/css/main.css b/3.26.2-scylla/_static/css/main.css new file mode 100644 index 0000000000..4ac0174528 --- /dev/null +++ b/3.26.2-scylla/_static/css/main.css @@ -0,0 +1 @@ +@media print,screen and (min-width:40em){.reveal,.reveal.large,.reveal.small,.reveal.tiny{left:auto;margin:0 auto;right:auto}}/*! normalize.css v8.0.0 | MIT License | github.com/necolas/normalize.css */html{-webkit-text-size-adjust:100%;line-height:1.15}h1{font-size:2em;margin:.67em 0}hr{-webkit-box-sizing:content-box;box-sizing:content-box;overflow:visible}pre{font-family:monospace,monospace;font-size:1em}a{background-color:transparent}abbr[title]{border-bottom:0;-webkit-text-decoration:underline dotted;text-decoration:underline dotted}b,strong{font-weight:bolder}code,kbd,samp{font-family:monospace,monospace;font-size:1em}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}img{border-style:none}button,input,optgroup,select,textarea{font-size:100%;line-height:1.15;margin:0}button,input{overflow:visible}button,select{text-transform:none}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button}[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner,button::-moz-focus-inner{border-style:none;padding:0}[type=button]:-moz-focusring,[type=reset]:-moz-focusring,[type=submit]:-moz-focusring,button:-moz-focusring{outline:1px dotted ButtonText}fieldset{padding:.35em .75em .625em}legend{-webkit-box-sizing:border-box;box-sizing:border-box;color:inherit;display:table;padding:0;white-space:normal}progress{vertical-align:baseline}textarea{overflow:auto}[type=checkbox],[type=radio]{-webkit-box-sizing:border-box;box-sizing:border-box;padding:0}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}details{display:block}summary{display:list-item}template{display:none}[hidden]{display:none}[data-whatinput=mouse] *,[data-whatinput=mouse] :focus,[data-whatinput=touch] *,[data-whatinput=touch] :focus,[data-whatintent=mouse] *,[data-whatintent=mouse] :focus,[data-whatintent=touch] *,[data-whatintent=touch] :focus{outline:0}[draggable=false]{-webkit-touch-callout:none;-webkit-user-select:none}.foundation-mq{font-family:"small=0em&medium=40em&large=64em&xlarge=75em&xxlarge=90em"}html{-webkit-box-sizing:border-box;font-size:100%}*,:after,:before{-webkit-box-sizing:inherit}body{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;background:#fefefe;color:#0a0a0a;font-family:Helvetica Neue,Helvetica,Roboto,Arial,sans-serif;font-weight:400;line-height:1.5;margin:0;padding:0}img{-ms-interpolation-mode:bicubic;display:inline-block;height:auto;vertical-align:middle}textarea{border-radius:0;height:auto;min-height:50px}select{-webkit-box-sizing:border-box;box-sizing:border-box;width:100%}.map_canvas embed,.map_canvas img,.map_canvas object,.mqa-display embed,.mqa-display img,.mqa-display object{max-width:none!important}button{-webkit-appearance:none;-moz-appearance:none;appearance:none;background:0 0;border:0;border-radius:0;cursor:auto;line-height:1;padding:0}[data-whatinput=mouse] button{outline:0}pre{-webkit-overflow-scrolling:touch;overflow:auto}button,input,optgroup,select,textarea{font-family:inherit}.is-visible{display:block!important}.is-hidden{display:none!important}[type=color],[type=date],[type=datetime-local],[type=datetime],[type=email],[type=month],[type=number],[type=password],[type=search],[type=tel],[type=text],[type=time],[type=url],[type=week],textarea{-webkit-appearance:none;-moz-appearance:none;appearance:none;background-color:#fefefe;border:1px solid #cacaca;border-radius:0;-webkit-box-shadow:inset 0 1px 2px hsla(0,0%,4%,.1);box-shadow:inset 0 1px 2px hsla(0,0%,4%,.1);-webkit-box-sizing:border-box;box-sizing:border-box;color:#0a0a0a;display:block;font-family:inherit;font-size:1rem;font-weight:400;height:2.4375rem;line-height:1.5;margin:0 0 1rem;padding:.5rem;-webkit-transition:border-color .25s ease-in-out,-webkit-box-shadow .5s;transition:border-color .25s ease-in-out,-webkit-box-shadow .5s;transition:box-shadow .5s,border-color .25s ease-in-out;transition:box-shadow .5s,border-color .25s ease-in-out,-webkit-box-shadow .5s;width:100%}[type=color]:focus,[type=date]:focus,[type=datetime-local]:focus,[type=datetime]:focus,[type=email]:focus,[type=month]:focus,[type=number]:focus,[type=password]:focus,[type=search]:focus,[type=tel]:focus,[type=text]:focus,[type=time]:focus,[type=url]:focus,[type=week]:focus,textarea:focus{background-color:#fefefe;border:1px solid #8a8a8a;-webkit-box-shadow:0 0 5px #cacaca;box-shadow:0 0 5px #cacaca;outline:0;-webkit-transition:border-color .25s ease-in-out,-webkit-box-shadow .5s;transition:border-color .25s ease-in-out,-webkit-box-shadow .5s;transition:box-shadow .5s,border-color .25s ease-in-out;transition:box-shadow .5s,border-color .25s ease-in-out,-webkit-box-shadow .5s}textarea{max-width:100%}textarea[rows]{height:auto}input:disabled,input[readonly],textarea:disabled,textarea[readonly]{background-color:#e6e6e6;cursor:not-allowed}[type=button],[type=submit]{-webkit-appearance:none;-moz-appearance:none;appearance:none;border-radius:0}input[type=search]{-webkit-box-sizing:border-box;box-sizing:border-box}::-webkit-input-placeholder{color:#cacaca}::-moz-placeholder{color:#cacaca}:-ms-input-placeholder{color:#cacaca}::-ms-input-placeholder{color:#cacaca}::placeholder{color:#cacaca}[type=checkbox],[type=file],[type=radio]{margin:0 0 1rem}[type=checkbox]+label,[type=radio]+label{display:inline-block;margin-bottom:0;margin-left:.5rem;margin-right:1rem;vertical-align:baseline}[type=checkbox]+label[for],[type=radio]+label[for]{cursor:pointer}label>[type=checkbox],label>[type=radio]{margin-right:.5rem}[type=file]{width:100%}label{color:#0a0a0a;display:block;font-size:.875rem;font-weight:400;line-height:1.8;margin:0}label.middle{line-height:1.5;margin:0 0 1rem;padding:.5625rem 0}.help-text{color:#0a0a0a;font-size:.8125rem;font-style:italic;margin-top:-.5rem}.input-group{-webkit-box-align:stretch;-ms-flex-align:stretch;-webkit-align-items:stretch;align-items:stretch;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;margin-bottom:1rem;width:100%}.input-group>:first-child,.input-group>:first-child.input-group-button>*{border-radius:0}.input-group>:last-child,.input-group>:last-child.input-group-button>*{border-radius:0}.input-group-button,.input-group-button a,.input-group-button button,.input-group-button input,.input-group-button label,.input-group-field,.input-group-label{margin:0;white-space:nowrap}.input-group-label{-webkit-box-flex:0;-webkit-box-align:center;-ms-flex-align:center;-webkit-align-items:center;align-items:center;background:#e6e6e6;border:1px solid #cacaca;color:#0a0a0a;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto;padding:0 1rem;text-align:center;white-space:nowrap}.input-group-label:first-child{border-right:0}.input-group-label:last-child{border-left:0}.input-group-field{-webkit-box-flex:1;border-radius:0;-webkit-flex:1 1 0px;-ms-flex:1 1 0px;flex:1 1 0px;min-width:0}.input-group-button{-webkit-box-flex:0;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto;padding-bottom:0;padding-top:0;text-align:center}.input-group-button a,.input-group-button button,.input-group-button input,.input-group-button label{-ms-flex-item-align:stretch;-webkit-align-self:stretch;align-self:stretch;font-size:1rem;height:auto;padding-bottom:0;padding-top:0}fieldset{border:0;margin:0;padding:0}legend{margin-bottom:.5rem;max-width:100%}.fieldset{border:1px solid #cacaca;margin:1.125rem 0;padding:1.25rem}.fieldset legend{margin:0 0 0 -.1875rem;padding:0 .1875rem}select{-webkit-appearance:none;-moz-appearance:none;appearance:none;background-color:#fefefe;background-image:url('data:image/svg+xml;utf8,');background-origin:content-box;background-position:right -1rem center;background-repeat:no-repeat;background-size:9px 6px;border:1px solid #cacaca;border-radius:0;color:#0a0a0a;font-family:inherit;font-size:1rem;font-weight:400;height:2.4375rem;line-height:1.5;margin:0 0 1rem;padding:.5rem 1.5rem .5rem .5rem;-webkit-transition:border-color .25s ease-in-out,-webkit-box-shadow .5s;transition:border-color .25s ease-in-out,-webkit-box-shadow .5s;transition:box-shadow .5s,border-color .25s ease-in-out;transition:box-shadow .5s,border-color .25s ease-in-out,-webkit-box-shadow .5s}@media screen and (min-width:0\0){select{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAYCAYAAACbU/80AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAIpJREFUeNrEkckNgDAMBBfRkEt0ObRBBdsGXUDgmQfK4XhH2m8czQAAy27R3tsw4Qfe2x8uOO6oYLb6GlOor3GF+swURAOmUJ+RwtEJs9WvTGEYxBXqI1MQAZhCfUQKRzDMVj+TwrAIV6jvSUEkYAr1LSkcyTBb/V+KYfX7xAeusq3sLDtGH3kEGACPWIflNZfhRQAAAABJRU5ErkJggg==)}}select:focus{background-color:#fefefe;border:1px solid #8a8a8a;-webkit-box-shadow:0 0 5px #cacaca;box-shadow:0 0 5px #cacaca;outline:0;-webkit-transition:border-color .25s ease-in-out,-webkit-box-shadow .5s;transition:border-color .25s ease-in-out,-webkit-box-shadow .5s;transition:box-shadow .5s,border-color .25s ease-in-out;transition:box-shadow .5s,border-color .25s ease-in-out,-webkit-box-shadow .5s}select:disabled{background-color:#e6e6e6;cursor:not-allowed}select::-ms-expand{display:none}select[multiple]{background-image:none;height:auto}select:not([multiple]){padding-bottom:0;padding-top:0}.is-invalid-input:not(:focus){background-color:#f9ecea;border-color:#cc4b37}.is-invalid-input:not(:focus)::-webkit-input-placeholder{color:#cc4b37}.is-invalid-input:not(:focus)::-moz-placeholder{color:#cc4b37}.is-invalid-input:not(:focus):-ms-input-placeholder{color:#cc4b37}.is-invalid-input:not(:focus)::-ms-input-placeholder{color:#cc4b37}.is-invalid-input:not(:focus)::placeholder{color:#cc4b37}.form-error,.is-invalid-label{color:#cc4b37}.form-error{display:none;font-size:.75rem;font-weight:700;margin-bottom:1rem;margin-top:-.5rem}.form-error.is-visible{display:block}blockquote,dd,div,dl,dt,form,h1,h2,h3,h4,h5,h6,li,ol,p,pre,td,th,ul{margin:0;padding:0}p{text-rendering:optimizeLegibility;font-size:inherit;line-height:1.6;margin-bottom:1rem}em,i{font-style:italic}b,em,i,strong{line-height:inherit}b,strong{font-weight:700}small{font-size:80%;line-height:inherit}.h1,.h2,.h3,.h4,.h5,.h6,h1,h2,h3,h4,h5,h6{text-rendering:optimizeLegibility;color:inherit;font-family:Helvetica Neue,Helvetica,Roboto,Arial,sans-serif;font-style:normal;font-weight:400}.h1 small,.h2 small,.h3 small,.h4 small,.h5 small,.h6 small,h1 small,h2 small,h3 small,h4 small,h5 small,h6 small{color:#cacaca;line-height:0}.h1,h1{font-size:1.5rem}.h1,.h2,h1,h2{line-height:1.4;margin-bottom:.5rem;margin-top:0}.h2,h2{font-size:1.25rem}.h3,h3{font-size:1.1875rem}.h3,.h4,h3,h4{line-height:1.4;margin-bottom:.5rem;margin-top:0}.h4,h4{font-size:1.125rem}.h5,h5{font-size:1.0625rem}.h5,.h6,h5,h6{line-height:1.4;margin-bottom:.5rem;margin-top:0}.h6,h6{font-size:1rem}@media print,screen and (min-width:40em){.h1,h1{font-size:3rem}.h2,h2{font-size:2.5rem}.h3,h3{font-size:1.9375rem}.h4,h4{font-size:1.5625rem}.h5,h5{font-size:1.25rem}.h6,h6{font-size:1rem}}a{color:#1779ba;cursor:pointer;line-height:inherit;text-decoration:none}a:focus,a:hover{color:#1468a0}a img,hr{border:0}hr{border-bottom:1px solid #cacaca;clear:both;height:0;margin:1.25rem auto;max-width:75rem}dl,ol,ul{line-height:1.6;list-style-position:outside;margin-bottom:1rem}li{font-size:inherit}ul{list-style-type:disc}ol,ul{margin-left:1.25rem}ol ol,ol ul,ul ol,ul ul{margin-bottom:0;margin-left:1.25rem}dl{margin-bottom:1rem}dl dt{font-weight:700;margin-bottom:.3rem}blockquote{border-left:1px solid #cacaca;margin:0 0 1rem;padding:.5625rem 1.25rem 0 1.1875rem}blockquote,blockquote p{color:#8a8a8a;line-height:1.6}abbr,abbr[title]{border-bottom:1px dotted #0a0a0a;cursor:help;text-decoration:none}figure,kbd{margin:0}kbd{background-color:#e6e6e6;color:#0a0a0a;font-family:Consolas,Liberation Mono,Courier,monospace;padding:.125rem .25rem 0}.subheader{color:#8a8a8a;font-weight:400;line-height:1.4;margin-bottom:.5rem;margin-top:.2rem}.lead{font-size:125%;line-height:1.6}.stat{font-size:2.5rem;line-height:1}p+.stat{margin-top:-1rem}ol.no-bullet,ul.no-bullet{list-style:none;margin-left:0}.cite-block,cite{color:#8a8a8a;display:block;font-size:.8125rem}.cite-block:before,cite:before{content:"— "}.code-inline,code{word-wrap:break-word;display:inline;max-width:100%;padding:.125rem .3125rem .0625rem}.code-block,.code-inline,code{background-color:#e6e6e6;border:1px solid #cacaca;color:#0a0a0a;font-family:Consolas,Liberation Mono,Courier,monospace;font-weight:400}.code-block{display:block;margin-bottom:1.5rem;overflow:auto;padding:1rem;white-space:pre}.text-left{text-align:left}.text-right{text-align:right}.text-center{text-align:center}.text-justify{text-align:justify}@media print,screen and (min-width:40em){.medium-text-left{text-align:left}.medium-text-right{text-align:right}.medium-text-center{text-align:center}.medium-text-justify{text-align:justify}}@media print,screen and (min-width:64em){.large-text-left{text-align:left}.large-text-right{text-align:right}.large-text-center{text-align:center}.large-text-justify{text-align:justify}}.show-for-print{display:none!important}@media print{*{-webkit-print-color-adjust:economy;background:0 0!important;-webkit-box-shadow:none!important;box-shadow:none!important;color:#000!important;color-adjust:economy;text-shadow:none!important}.show-for-print{display:block!important}.hide-for-print{display:none!important}table.show-for-print{display:table!important}thead.show-for-print{display:table-header-group!important}tbody.show-for-print{display:table-row-group!important}tr.show-for-print{display:table-row!important}td.show-for-print,th.show-for-print{display:table-cell!important}a,a:visited{text-decoration:underline}a[href]:after{content:" (" attr(href) ")"}.ir a:after,a[href^="#"]:after,a[href^="javascript:"]:after{content:""}abbr[title]:after{content:" (" attr(title) ")"}blockquote,pre{border:1px solid #8a8a8a;page-break-inside:avoid}thead{display:table-header-group}img,tr{page-break-inside:avoid}img{max-width:100%!important}@page{margin:.5cm}h2,h3,p{orphans:3;widows:3}h2,h3{page-break-after:avoid}.print-break-inside{page-break-inside:auto}}.grid-container{margin-left:auto;margin-right:auto;max-width:75rem;padding-left:.625rem;padding-right:.625rem}@media print,screen and (min-width:40em){.grid-container{padding-left:.9375rem;padding-right:.9375rem}}.grid-container.fluid{margin-left:auto;margin-right:auto;max-width:100%;padding-left:.625rem;padding-right:.625rem}@media print,screen and (min-width:40em){.grid-container.fluid{padding-left:.9375rem;padding-right:.9375rem}}.grid-container.full{margin-left:auto;margin-right:auto;max-width:100%;padding-left:0;padding-right:0}.grid-x{-webkit-box-orient:horizontal;-webkit-box-direction:normal;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-flow:row wrap;-ms-flex-flow:row wrap;flex-flow:row wrap}.cell{-webkit-box-flex:0;-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto;min-height:0;min-width:0;width:100%}.cell.auto{-webkit-box-flex:1;-webkit-flex:1 1 0;-ms-flex:1 1 0px;flex:1 1 0}.cell.shrink{-webkit-box-flex:0;-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto}.grid-x>.auto{width:auto}.grid-x>.shrink{width:auto}.grid-x>.small-1,.grid-x>.small-2,.grid-x>.small-3,.grid-x>.small-4,.grid-x>.small-5,.grid-x>.small-6,.grid-x>.small-7,.grid-x>.small-8,.grid-x>.small-9,.grid-x>.small-10,.grid-x>.small-11,.grid-x>.small-12,.grid-x>.small-full,.grid-x>.small-shrink{-ms-flex-preferred-size:auto;-webkit-flex-basis:auto;flex-basis:auto}@media print,screen and (min-width:40em){.grid-x>.medium-1,.grid-x>.medium-2,.grid-x>.medium-3,.grid-x>.medium-4,.grid-x>.medium-5,.grid-x>.medium-6,.grid-x>.medium-7,.grid-x>.medium-8,.grid-x>.medium-9,.grid-x>.medium-10,.grid-x>.medium-11,.grid-x>.medium-12,.grid-x>.medium-full,.grid-x>.medium-shrink{-ms-flex-preferred-size:auto;-webkit-flex-basis:auto;flex-basis:auto}}@media print,screen and (min-width:64em){.grid-x>.large-1,.grid-x>.large-2,.grid-x>.large-3,.grid-x>.large-4,.grid-x>.large-5,.grid-x>.large-6,.grid-x>.large-7,.grid-x>.large-8,.grid-x>.large-9,.grid-x>.large-10,.grid-x>.large-11,.grid-x>.large-12,.grid-x>.large-full,.grid-x>.large-shrink{-ms-flex-preferred-size:auto;-webkit-flex-basis:auto;flex-basis:auto}}.grid-x>.small-1,.grid-x>.small-2,.grid-x>.small-3,.grid-x>.small-4,.grid-x>.small-5,.grid-x>.small-6,.grid-x>.small-7,.grid-x>.small-8,.grid-x>.small-9,.grid-x>.small-10,.grid-x>.small-11,.grid-x>.small-12{-webkit-box-flex:0;-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto}.grid-x>.small-1{width:8.33333%}.grid-x>.small-2{width:16.66667%}.grid-x>.small-3{width:25%}.grid-x>.small-4{width:33.33333%}.grid-x>.small-5{width:41.66667%}.grid-x>.small-6{width:50%}.grid-x>.small-7{width:58.33333%}.grid-x>.small-8{width:66.66667%}.grid-x>.small-9{width:75%}.grid-x>.small-10{width:83.33333%}.grid-x>.small-11{width:91.66667%}.grid-x>.small-12{width:100%}@media print,screen and (min-width:40em){.grid-x>.medium-auto{-webkit-box-flex:1;-webkit-flex:1 1 0;-ms-flex:1 1 0px;flex:1 1 0;width:auto}.grid-x>.medium-1,.grid-x>.medium-2,.grid-x>.medium-3,.grid-x>.medium-4,.grid-x>.medium-5,.grid-x>.medium-6,.grid-x>.medium-7,.grid-x>.medium-8,.grid-x>.medium-9,.grid-x>.medium-10,.grid-x>.medium-11,.grid-x>.medium-12,.grid-x>.medium-shrink{-webkit-box-flex:0;-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto}.grid-x>.medium-shrink{width:auto}.grid-x>.medium-1{width:8.33333%}.grid-x>.medium-2{width:16.66667%}.grid-x>.medium-3{width:25%}.grid-x>.medium-4{width:33.33333%}.grid-x>.medium-5{width:41.66667%}.grid-x>.medium-6{width:50%}.grid-x>.medium-7{width:58.33333%}.grid-x>.medium-8{width:66.66667%}.grid-x>.medium-9{width:75%}.grid-x>.medium-10{width:83.33333%}.grid-x>.medium-11{width:91.66667%}.grid-x>.medium-12{width:100%}}@media print,screen and (min-width:64em){.grid-x>.large-auto{-webkit-box-flex:1;-webkit-flex:1 1 0;-ms-flex:1 1 0px;flex:1 1 0;width:auto}.grid-x>.large-1,.grid-x>.large-2,.grid-x>.large-3,.grid-x>.large-4,.grid-x>.large-5,.grid-x>.large-6,.grid-x>.large-7,.grid-x>.large-8,.grid-x>.large-9,.grid-x>.large-10,.grid-x>.large-11,.grid-x>.large-12,.grid-x>.large-shrink{-webkit-box-flex:0;-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto}.grid-x>.large-shrink{width:auto}.grid-x>.large-1{width:8.33333%}.grid-x>.large-2{width:16.66667%}.grid-x>.large-3{width:25%}.grid-x>.large-4{width:33.33333%}.grid-x>.large-5{width:41.66667%}.grid-x>.large-6{width:50%}.grid-x>.large-7{width:58.33333%}.grid-x>.large-8{width:66.66667%}.grid-x>.large-9{width:75%}.grid-x>.large-10{width:83.33333%}.grid-x>.large-11{width:91.66667%}.grid-x>.large-12{width:100%}}.grid-margin-x:not(.grid-x)>.cell{width:auto}.grid-margin-y:not(.grid-y)>.cell{height:auto}.grid-margin-x{margin-left:-.625rem;margin-right:-.625rem}@media print,screen and (min-width:40em){.grid-margin-x{margin-left:-.9375rem;margin-right:-.9375rem}}.grid-margin-x>.cell{margin-left:.625rem;margin-right:.625rem;width:calc(100% - 1.25rem)}@media print,screen and (min-width:40em){.grid-margin-x>.cell{margin-left:.9375rem;margin-right:.9375rem;width:calc(100% - 1.875rem)}}.grid-margin-x>.auto{width:auto}.grid-margin-x>.shrink{width:auto}.grid-margin-x>.small-1{width:calc(8.33333% - 1.25rem)}.grid-margin-x>.small-2{width:calc(16.66667% - 1.25rem)}.grid-margin-x>.small-3{width:calc(25% - 1.25rem)}.grid-margin-x>.small-4{width:calc(33.33333% - 1.25rem)}.grid-margin-x>.small-5{width:calc(41.66667% - 1.25rem)}.grid-margin-x>.small-6{width:calc(50% - 1.25rem)}.grid-margin-x>.small-7{width:calc(58.33333% - 1.25rem)}.grid-margin-x>.small-8{width:calc(66.66667% - 1.25rem)}.grid-margin-x>.small-9{width:calc(75% - 1.25rem)}.grid-margin-x>.small-10{width:calc(83.33333% - 1.25rem)}.grid-margin-x>.small-11{width:calc(91.66667% - 1.25rem)}.grid-margin-x>.small-12{width:calc(100% - 1.25rem)}@media print,screen and (min-width:40em){.grid-margin-x>.auto{width:auto}.grid-margin-x>.shrink{width:auto}.grid-margin-x>.small-1{width:calc(8.33333% - 1.875rem)}.grid-margin-x>.small-2{width:calc(16.66667% - 1.875rem)}.grid-margin-x>.small-3{width:calc(25% - 1.875rem)}.grid-margin-x>.small-4{width:calc(33.33333% - 1.875rem)}.grid-margin-x>.small-5{width:calc(41.66667% - 1.875rem)}.grid-margin-x>.small-6{width:calc(50% - 1.875rem)}.grid-margin-x>.small-7{width:calc(58.33333% - 1.875rem)}.grid-margin-x>.small-8{width:calc(66.66667% - 1.875rem)}.grid-margin-x>.small-9{width:calc(75% - 1.875rem)}.grid-margin-x>.small-10{width:calc(83.33333% - 1.875rem)}.grid-margin-x>.small-11{width:calc(91.66667% - 1.875rem)}.grid-margin-x>.small-12{width:calc(100% - 1.875rem)}.grid-margin-x>.medium-auto{width:auto}.grid-margin-x>.medium-shrink{width:auto}.grid-margin-x>.medium-1{width:calc(8.33333% - 1.875rem)}.grid-margin-x>.medium-2{width:calc(16.66667% - 1.875rem)}.grid-margin-x>.medium-3{width:calc(25% - 1.875rem)}.grid-margin-x>.medium-4{width:calc(33.33333% - 1.875rem)}.grid-margin-x>.medium-5{width:calc(41.66667% - 1.875rem)}.grid-margin-x>.medium-6{width:calc(50% - 1.875rem)}.grid-margin-x>.medium-7{width:calc(58.33333% - 1.875rem)}.grid-margin-x>.medium-8{width:calc(66.66667% - 1.875rem)}.grid-margin-x>.medium-9{width:calc(75% - 1.875rem)}.grid-margin-x>.medium-10{width:calc(83.33333% - 1.875rem)}.grid-margin-x>.medium-11{width:calc(91.66667% - 1.875rem)}.grid-margin-x>.medium-12{width:calc(100% - 1.875rem)}}@media print,screen and (min-width:64em){.grid-margin-x>.large-auto{width:auto}.grid-margin-x>.large-shrink{width:auto}.grid-margin-x>.large-1{width:calc(8.33333% - 1.875rem)}.grid-margin-x>.large-2{width:calc(16.66667% - 1.875rem)}.grid-margin-x>.large-3{width:calc(25% - 1.875rem)}.grid-margin-x>.large-4{width:calc(33.33333% - 1.875rem)}.grid-margin-x>.large-5{width:calc(41.66667% - 1.875rem)}.grid-margin-x>.large-6{width:calc(50% - 1.875rem)}.grid-margin-x>.large-7{width:calc(58.33333% - 1.875rem)}.grid-margin-x>.large-8{width:calc(66.66667% - 1.875rem)}.grid-margin-x>.large-9{width:calc(75% - 1.875rem)}.grid-margin-x>.large-10{width:calc(83.33333% - 1.875rem)}.grid-margin-x>.large-11{width:calc(91.66667% - 1.875rem)}.grid-margin-x>.large-12{width:calc(100% - 1.875rem)}}.grid-padding-x .grid-padding-x{margin-left:-.625rem;margin-right:-.625rem}@media print,screen and (min-width:40em){.grid-padding-x .grid-padding-x{margin-left:-.9375rem;margin-right:-.9375rem}}.grid-container:not(.full)>.grid-padding-x{margin-left:-.625rem;margin-right:-.625rem}@media print,screen and (min-width:40em){.grid-container:not(.full)>.grid-padding-x{margin-left:-.9375rem;margin-right:-.9375rem}}.grid-padding-x>.cell{padding-left:.625rem;padding-right:.625rem}@media print,screen and (min-width:40em){.grid-padding-x>.cell{padding-left:.9375rem;padding-right:.9375rem}}.small-up-1>.cell{width:100%}.small-up-2>.cell{width:50%}.small-up-3>.cell{width:33.33333%}.small-up-4>.cell{width:25%}.small-up-5>.cell{width:20%}.small-up-6>.cell{width:16.66667%}.small-up-7>.cell{width:14.28571%}.small-up-8>.cell{width:12.5%}@media print,screen and (min-width:40em){.medium-up-1>.cell{width:100%}.medium-up-2>.cell{width:50%}.medium-up-3>.cell{width:33.33333%}.medium-up-4>.cell{width:25%}.medium-up-5>.cell{width:20%}.medium-up-6>.cell{width:16.66667%}.medium-up-7>.cell{width:14.28571%}.medium-up-8>.cell{width:12.5%}}@media print,screen and (min-width:64em){.large-up-1>.cell{width:100%}.large-up-2>.cell{width:50%}.large-up-3>.cell{width:33.33333%}.large-up-4>.cell{width:25%}.large-up-5>.cell{width:20%}.large-up-6>.cell{width:16.66667%}.large-up-7>.cell{width:14.28571%}.large-up-8>.cell{width:12.5%}}.grid-margin-x.small-up-1>.cell{width:calc(100% - 1.25rem)}.grid-margin-x.small-up-2>.cell{width:calc(50% - 1.25rem)}.grid-margin-x.small-up-3>.cell{width:calc(33.33333% - 1.25rem)}.grid-margin-x.small-up-4>.cell{width:calc(25% - 1.25rem)}.grid-margin-x.small-up-5>.cell{width:calc(20% - 1.25rem)}.grid-margin-x.small-up-6>.cell{width:calc(16.66667% - 1.25rem)}.grid-margin-x.small-up-7>.cell{width:calc(14.28571% - 1.25rem)}.grid-margin-x.small-up-8>.cell{width:calc(12.5% - 1.25rem)}@media print,screen and (min-width:40em){.grid-margin-x.small-up-1>.cell{width:calc(100% - 1.875rem)}.grid-margin-x.small-up-2>.cell{width:calc(50% - 1.875rem)}.grid-margin-x.small-up-3>.cell{width:calc(33.33333% - 1.875rem)}.grid-margin-x.small-up-4>.cell{width:calc(25% - 1.875rem)}.grid-margin-x.small-up-5>.cell{width:calc(20% - 1.875rem)}.grid-margin-x.small-up-6>.cell{width:calc(16.66667% - 1.875rem)}.grid-margin-x.small-up-7>.cell{width:calc(14.28571% - 1.875rem)}.grid-margin-x.small-up-8>.cell{width:calc(12.5% - 1.875rem)}.grid-margin-x.medium-up-1>.cell{width:calc(100% - 1.875rem)}.grid-margin-x.medium-up-2>.cell{width:calc(50% - 1.875rem)}.grid-margin-x.medium-up-3>.cell{width:calc(33.33333% - 1.875rem)}.grid-margin-x.medium-up-4>.cell{width:calc(25% - 1.875rem)}.grid-margin-x.medium-up-5>.cell{width:calc(20% - 1.875rem)}.grid-margin-x.medium-up-6>.cell{width:calc(16.66667% - 1.875rem)}.grid-margin-x.medium-up-7>.cell{width:calc(14.28571% - 1.875rem)}.grid-margin-x.medium-up-8>.cell{width:calc(12.5% - 1.875rem)}}@media print,screen and (min-width:64em){.grid-margin-x.large-up-1>.cell{width:calc(100% - 1.875rem)}.grid-margin-x.large-up-2>.cell{width:calc(50% - 1.875rem)}.grid-margin-x.large-up-3>.cell{width:calc(33.33333% - 1.875rem)}.grid-margin-x.large-up-4>.cell{width:calc(25% - 1.875rem)}.grid-margin-x.large-up-5>.cell{width:calc(20% - 1.875rem)}.grid-margin-x.large-up-6>.cell{width:calc(16.66667% - 1.875rem)}.grid-margin-x.large-up-7>.cell{width:calc(14.28571% - 1.875rem)}.grid-margin-x.large-up-8>.cell{width:calc(12.5% - 1.875rem)}}.small-margin-collapse{margin-left:0;margin-right:0}.small-margin-collapse>.cell{margin-left:0;margin-right:0}.small-margin-collapse>.small-1{width:8.33333%}.small-margin-collapse>.small-2{width:16.66667%}.small-margin-collapse>.small-3{width:25%}.small-margin-collapse>.small-4{width:33.33333%}.small-margin-collapse>.small-5{width:41.66667%}.small-margin-collapse>.small-6{width:50%}.small-margin-collapse>.small-7{width:58.33333%}.small-margin-collapse>.small-8{width:66.66667%}.small-margin-collapse>.small-9{width:75%}.small-margin-collapse>.small-10{width:83.33333%}.small-margin-collapse>.small-11{width:91.66667%}.small-margin-collapse>.small-12{width:100%}@media print,screen and (min-width:40em){.small-margin-collapse>.medium-1{width:8.33333%}.small-margin-collapse>.medium-2{width:16.66667%}.small-margin-collapse>.medium-3{width:25%}.small-margin-collapse>.medium-4{width:33.33333%}.small-margin-collapse>.medium-5{width:41.66667%}.small-margin-collapse>.medium-6{width:50%}.small-margin-collapse>.medium-7{width:58.33333%}.small-margin-collapse>.medium-8{width:66.66667%}.small-margin-collapse>.medium-9{width:75%}.small-margin-collapse>.medium-10{width:83.33333%}.small-margin-collapse>.medium-11{width:91.66667%}.small-margin-collapse>.medium-12{width:100%}}@media print,screen and (min-width:64em){.small-margin-collapse>.large-1{width:8.33333%}.small-margin-collapse>.large-2{width:16.66667%}.small-margin-collapse>.large-3{width:25%}.small-margin-collapse>.large-4{width:33.33333%}.small-margin-collapse>.large-5{width:41.66667%}.small-margin-collapse>.large-6{width:50%}.small-margin-collapse>.large-7{width:58.33333%}.small-margin-collapse>.large-8{width:66.66667%}.small-margin-collapse>.large-9{width:75%}.small-margin-collapse>.large-10{width:83.33333%}.small-margin-collapse>.large-11{width:91.66667%}.small-margin-collapse>.large-12{width:100%}}.small-padding-collapse{margin-left:0;margin-right:0}.small-padding-collapse>.cell{padding-left:0;padding-right:0}@media print,screen and (min-width:40em){.medium-margin-collapse{margin-left:0;margin-right:0}.medium-margin-collapse>.cell{margin-left:0;margin-right:0}}@media print,screen and (min-width:40em){.medium-margin-collapse>.small-1{width:8.33333%}.medium-margin-collapse>.small-2{width:16.66667%}.medium-margin-collapse>.small-3{width:25%}.medium-margin-collapse>.small-4{width:33.33333%}.medium-margin-collapse>.small-5{width:41.66667%}.medium-margin-collapse>.small-6{width:50%}.medium-margin-collapse>.small-7{width:58.33333%}.medium-margin-collapse>.small-8{width:66.66667%}.medium-margin-collapse>.small-9{width:75%}.medium-margin-collapse>.small-10{width:83.33333%}.medium-margin-collapse>.small-11{width:91.66667%}.medium-margin-collapse>.small-12{width:100%}}@media print,screen and (min-width:40em){.medium-margin-collapse>.medium-1{width:8.33333%}.medium-margin-collapse>.medium-2{width:16.66667%}.medium-margin-collapse>.medium-3{width:25%}.medium-margin-collapse>.medium-4{width:33.33333%}.medium-margin-collapse>.medium-5{width:41.66667%}.medium-margin-collapse>.medium-6{width:50%}.medium-margin-collapse>.medium-7{width:58.33333%}.medium-margin-collapse>.medium-8{width:66.66667%}.medium-margin-collapse>.medium-9{width:75%}.medium-margin-collapse>.medium-10{width:83.33333%}.medium-margin-collapse>.medium-11{width:91.66667%}.medium-margin-collapse>.medium-12{width:100%}}@media print,screen and (min-width:64em){.medium-margin-collapse>.large-1{width:8.33333%}.medium-margin-collapse>.large-2{width:16.66667%}.medium-margin-collapse>.large-3{width:25%}.medium-margin-collapse>.large-4{width:33.33333%}.medium-margin-collapse>.large-5{width:41.66667%}.medium-margin-collapse>.large-6{width:50%}.medium-margin-collapse>.large-7{width:58.33333%}.medium-margin-collapse>.large-8{width:66.66667%}.medium-margin-collapse>.large-9{width:75%}.medium-margin-collapse>.large-10{width:83.33333%}.medium-margin-collapse>.large-11{width:91.66667%}.medium-margin-collapse>.large-12{width:100%}}@media print,screen and (min-width:40em){.medium-padding-collapse{margin-left:0;margin-right:0}.medium-padding-collapse>.cell{padding-left:0;padding-right:0}}@media print,screen and (min-width:64em){.large-margin-collapse{margin-left:0;margin-right:0}.large-margin-collapse>.cell{margin-left:0;margin-right:0}}@media print,screen and (min-width:64em){.large-margin-collapse>.small-1{width:8.33333%}.large-margin-collapse>.small-2{width:16.66667%}.large-margin-collapse>.small-3{width:25%}.large-margin-collapse>.small-4{width:33.33333%}.large-margin-collapse>.small-5{width:41.66667%}.large-margin-collapse>.small-6{width:50%}.large-margin-collapse>.small-7{width:58.33333%}.large-margin-collapse>.small-8{width:66.66667%}.large-margin-collapse>.small-9{width:75%}.large-margin-collapse>.small-10{width:83.33333%}.large-margin-collapse>.small-11{width:91.66667%}.large-margin-collapse>.small-12{width:100%}}@media print,screen and (min-width:64em){.large-margin-collapse>.medium-1{width:8.33333%}.large-margin-collapse>.medium-2{width:16.66667%}.large-margin-collapse>.medium-3{width:25%}.large-margin-collapse>.medium-4{width:33.33333%}.large-margin-collapse>.medium-5{width:41.66667%}.large-margin-collapse>.medium-6{width:50%}.large-margin-collapse>.medium-7{width:58.33333%}.large-margin-collapse>.medium-8{width:66.66667%}.large-margin-collapse>.medium-9{width:75%}.large-margin-collapse>.medium-10{width:83.33333%}.large-margin-collapse>.medium-11{width:91.66667%}.large-margin-collapse>.medium-12{width:100%}}@media print,screen and (min-width:64em){.large-margin-collapse>.large-1{width:8.33333%}.large-margin-collapse>.large-2{width:16.66667%}.large-margin-collapse>.large-3{width:25%}.large-margin-collapse>.large-4{width:33.33333%}.large-margin-collapse>.large-5{width:41.66667%}.large-margin-collapse>.large-6{width:50%}.large-margin-collapse>.large-7{width:58.33333%}.large-margin-collapse>.large-8{width:66.66667%}.large-margin-collapse>.large-9{width:75%}.large-margin-collapse>.large-10{width:83.33333%}.large-margin-collapse>.large-11{width:91.66667%}.large-margin-collapse>.large-12{width:100%}}@media print,screen and (min-width:64em){.large-padding-collapse{margin-left:0;margin-right:0}.large-padding-collapse>.cell{padding-left:0;padding-right:0}}.small-offset-0{margin-left:0}.grid-margin-x>.small-offset-0{margin-left:.625rem}.small-offset-1{margin-left:8.33333%}.grid-margin-x>.small-offset-1{margin-left:calc(8.33333% + .625rem)}.small-offset-2{margin-left:16.66667%}.grid-margin-x>.small-offset-2{margin-left:calc(16.66667% + .625rem)}.small-offset-3{margin-left:25%}.grid-margin-x>.small-offset-3{margin-left:calc(25% + .625rem)}.small-offset-4{margin-left:33.33333%}.grid-margin-x>.small-offset-4{margin-left:calc(33.33333% + .625rem)}.small-offset-5{margin-left:41.66667%}.grid-margin-x>.small-offset-5{margin-left:calc(41.66667% + .625rem)}.small-offset-6{margin-left:50%}.grid-margin-x>.small-offset-6{margin-left:calc(50% + .625rem)}.small-offset-7{margin-left:58.33333%}.grid-margin-x>.small-offset-7{margin-left:calc(58.33333% + .625rem)}.small-offset-8{margin-left:66.66667%}.grid-margin-x>.small-offset-8{margin-left:calc(66.66667% + .625rem)}.small-offset-9{margin-left:75%}.grid-margin-x>.small-offset-9{margin-left:calc(75% + .625rem)}.small-offset-10{margin-left:83.33333%}.grid-margin-x>.small-offset-10{margin-left:calc(83.33333% + .625rem)}.small-offset-11{margin-left:91.66667%}.grid-margin-x>.small-offset-11{margin-left:calc(91.66667% + .625rem)}@media print,screen and (min-width:40em){.medium-offset-0{margin-left:0}.grid-margin-x>.medium-offset-0{margin-left:.9375rem}.medium-offset-1{margin-left:8.33333%}.grid-margin-x>.medium-offset-1{margin-left:calc(8.33333% + .9375rem)}.medium-offset-2{margin-left:16.66667%}.grid-margin-x>.medium-offset-2{margin-left:calc(16.66667% + .9375rem)}.medium-offset-3{margin-left:25%}.grid-margin-x>.medium-offset-3{margin-left:calc(25% + .9375rem)}.medium-offset-4{margin-left:33.33333%}.grid-margin-x>.medium-offset-4{margin-left:calc(33.33333% + .9375rem)}.medium-offset-5{margin-left:41.66667%}.grid-margin-x>.medium-offset-5{margin-left:calc(41.66667% + .9375rem)}.medium-offset-6{margin-left:50%}.grid-margin-x>.medium-offset-6{margin-left:calc(50% + .9375rem)}.medium-offset-7{margin-left:58.33333%}.grid-margin-x>.medium-offset-7{margin-left:calc(58.33333% + .9375rem)}.medium-offset-8{margin-left:66.66667%}.grid-margin-x>.medium-offset-8{margin-left:calc(66.66667% + .9375rem)}.medium-offset-9{margin-left:75%}.grid-margin-x>.medium-offset-9{margin-left:calc(75% + .9375rem)}.medium-offset-10{margin-left:83.33333%}.grid-margin-x>.medium-offset-10{margin-left:calc(83.33333% + .9375rem)}.medium-offset-11{margin-left:91.66667%}.grid-margin-x>.medium-offset-11{margin-left:calc(91.66667% + .9375rem)}}@media print,screen and (min-width:64em){.large-offset-0{margin-left:0}.grid-margin-x>.large-offset-0{margin-left:.9375rem}.large-offset-1{margin-left:8.33333%}.grid-margin-x>.large-offset-1{margin-left:calc(8.33333% + .9375rem)}.large-offset-2{margin-left:16.66667%}.grid-margin-x>.large-offset-2{margin-left:calc(16.66667% + .9375rem)}.large-offset-3{margin-left:25%}.grid-margin-x>.large-offset-3{margin-left:calc(25% + .9375rem)}.large-offset-4{margin-left:33.33333%}.grid-margin-x>.large-offset-4{margin-left:calc(33.33333% + .9375rem)}.large-offset-5{margin-left:41.66667%}.grid-margin-x>.large-offset-5{margin-left:calc(41.66667% + .9375rem)}.large-offset-6{margin-left:50%}.grid-margin-x>.large-offset-6{margin-left:calc(50% + .9375rem)}.large-offset-7{margin-left:58.33333%}.grid-margin-x>.large-offset-7{margin-left:calc(58.33333% + .9375rem)}.large-offset-8{margin-left:66.66667%}.grid-margin-x>.large-offset-8{margin-left:calc(66.66667% + .9375rem)}.large-offset-9{margin-left:75%}.grid-margin-x>.large-offset-9{margin-left:calc(75% + .9375rem)}.large-offset-10{margin-left:83.33333%}.grid-margin-x>.large-offset-10{margin-left:calc(83.33333% + .9375rem)}.large-offset-11{margin-left:91.66667%}.grid-margin-x>.large-offset-11{margin-left:calc(91.66667% + .9375rem)}}.grid-y{-webkit-box-orient:vertical;-webkit-box-direction:normal;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-flow:column nowrap;-ms-flex-flow:column nowrap;flex-flow:column nowrap}.grid-y>.cell{height:auto;max-height:none}.grid-y>.auto{height:auto}.grid-y>.shrink{height:auto}.grid-y>.small-1,.grid-y>.small-2,.grid-y>.small-3,.grid-y>.small-4,.grid-y>.small-5,.grid-y>.small-6,.grid-y>.small-7,.grid-y>.small-8,.grid-y>.small-9,.grid-y>.small-10,.grid-y>.small-11,.grid-y>.small-12,.grid-y>.small-full,.grid-y>.small-shrink{-ms-flex-preferred-size:auto;-webkit-flex-basis:auto;flex-basis:auto}@media print,screen and (min-width:40em){.grid-y>.medium-1,.grid-y>.medium-2,.grid-y>.medium-3,.grid-y>.medium-4,.grid-y>.medium-5,.grid-y>.medium-6,.grid-y>.medium-7,.grid-y>.medium-8,.grid-y>.medium-9,.grid-y>.medium-10,.grid-y>.medium-11,.grid-y>.medium-12,.grid-y>.medium-full,.grid-y>.medium-shrink{-ms-flex-preferred-size:auto;-webkit-flex-basis:auto;flex-basis:auto}}@media print,screen and (min-width:64em){.grid-y>.large-1,.grid-y>.large-2,.grid-y>.large-3,.grid-y>.large-4,.grid-y>.large-5,.grid-y>.large-6,.grid-y>.large-7,.grid-y>.large-8,.grid-y>.large-9,.grid-y>.large-10,.grid-y>.large-11,.grid-y>.large-12,.grid-y>.large-full,.grid-y>.large-shrink{-ms-flex-preferred-size:auto;-webkit-flex-basis:auto;flex-basis:auto}}.grid-y>.small-1,.grid-y>.small-2,.grid-y>.small-3,.grid-y>.small-4,.grid-y>.small-5,.grid-y>.small-6,.grid-y>.small-7,.grid-y>.small-8,.grid-y>.small-9,.grid-y>.small-10,.grid-y>.small-11,.grid-y>.small-12{-webkit-box-flex:0;-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto}.grid-y>.small-1{height:8.33333%}.grid-y>.small-2{height:16.66667%}.grid-y>.small-3{height:25%}.grid-y>.small-4{height:33.33333%}.grid-y>.small-5{height:41.66667%}.grid-y>.small-6{height:50%}.grid-y>.small-7{height:58.33333%}.grid-y>.small-8{height:66.66667%}.grid-y>.small-9{height:75%}.grid-y>.small-10{height:83.33333%}.grid-y>.small-11{height:91.66667%}.grid-y>.small-12{height:100%}@media print,screen and (min-width:40em){.grid-y>.medium-auto{-webkit-box-flex:1;-webkit-flex:1 1 0;-ms-flex:1 1 0px;flex:1 1 0;height:auto}.grid-y>.medium-1,.grid-y>.medium-2,.grid-y>.medium-3,.grid-y>.medium-4,.grid-y>.medium-5,.grid-y>.medium-6,.grid-y>.medium-7,.grid-y>.medium-8,.grid-y>.medium-9,.grid-y>.medium-10,.grid-y>.medium-11,.grid-y>.medium-12,.grid-y>.medium-shrink{-webkit-box-flex:0;-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto}.grid-y>.medium-shrink{height:auto}.grid-y>.medium-1{height:8.33333%}.grid-y>.medium-2{height:16.66667%}.grid-y>.medium-3{height:25%}.grid-y>.medium-4{height:33.33333%}.grid-y>.medium-5{height:41.66667%}.grid-y>.medium-6{height:50%}.grid-y>.medium-7{height:58.33333%}.grid-y>.medium-8{height:66.66667%}.grid-y>.medium-9{height:75%}.grid-y>.medium-10{height:83.33333%}.grid-y>.medium-11{height:91.66667%}.grid-y>.medium-12{height:100%}}@media print,screen and (min-width:64em){.grid-y>.large-auto{-webkit-box-flex:1;-webkit-flex:1 1 0;-ms-flex:1 1 0px;flex:1 1 0;height:auto}.grid-y>.large-1,.grid-y>.large-2,.grid-y>.large-3,.grid-y>.large-4,.grid-y>.large-5,.grid-y>.large-6,.grid-y>.large-7,.grid-y>.large-8,.grid-y>.large-9,.grid-y>.large-10,.grid-y>.large-11,.grid-y>.large-12,.grid-y>.large-shrink{-webkit-box-flex:0;-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto}.grid-y>.large-shrink{height:auto}.grid-y>.large-1{height:8.33333%}.grid-y>.large-2{height:16.66667%}.grid-y>.large-3{height:25%}.grid-y>.large-4{height:33.33333%}.grid-y>.large-5{height:41.66667%}.grid-y>.large-6{height:50%}.grid-y>.large-7{height:58.33333%}.grid-y>.large-8{height:66.66667%}.grid-y>.large-9{height:75%}.grid-y>.large-10{height:83.33333%}.grid-y>.large-11{height:91.66667%}.grid-y>.large-12{height:100%}}.grid-padding-y .grid-padding-y{margin-bottom:-.625rem;margin-top:-.625rem}@media print,screen and (min-width:40em){.grid-padding-y .grid-padding-y{margin-bottom:-.9375rem;margin-top:-.9375rem}}.grid-padding-y>.cell{padding-bottom:.625rem;padding-top:.625rem}@media print,screen and (min-width:40em){.grid-padding-y>.cell{padding-bottom:.9375rem;padding-top:.9375rem}}.grid-frame{-webkit-box-align:stretch;-ms-flex-align:stretch;-webkit-align-items:stretch;align-items:stretch;-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap;overflow:hidden;position:relative;width:100vw}.cell .grid-frame{width:100%}.cell-block{max-width:100%;overflow-x:auto}.cell-block,.cell-block-y{-webkit-overflow-scrolling:touch;-ms-overflow-style:-ms-autohiding-scrollbar}.cell-block-y{max-height:100%;min-height:100%;overflow-y:auto}.cell-block-container{-webkit-box-orient:vertical;-webkit-box-direction:normal;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;max-height:100%}.cell-block-container>.grid-x{-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap;max-height:100%}@media print,screen and (min-width:40em){.medium-grid-frame{-webkit-box-align:stretch;-ms-flex-align:stretch;-webkit-align-items:stretch;align-items:stretch;-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap;overflow:hidden;position:relative;width:100vw}.cell .medium-grid-frame{width:100%}.medium-cell-block{-webkit-overflow-scrolling:touch;-ms-overflow-style:-ms-autohiding-scrollbar;max-width:100%;overflow-x:auto}.medium-cell-block-container{-webkit-box-orient:vertical;-webkit-box-direction:normal;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;max-height:100%}.medium-cell-block-container>.grid-x{-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap;max-height:100%}.medium-cell-block-y{-webkit-overflow-scrolling:touch;-ms-overflow-style:-ms-autohiding-scrollbar;max-height:100%;min-height:100%;overflow-y:auto}}@media print,screen and (min-width:64em){.large-grid-frame{-webkit-box-align:stretch;-ms-flex-align:stretch;-webkit-align-items:stretch;align-items:stretch;-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap;overflow:hidden;position:relative;width:100vw}.cell .large-grid-frame{width:100%}.large-cell-block{-webkit-overflow-scrolling:touch;-ms-overflow-style:-ms-autohiding-scrollbar;max-width:100%;overflow-x:auto}.large-cell-block-container{-webkit-box-orient:vertical;-webkit-box-direction:normal;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;max-height:100%}.large-cell-block-container>.grid-x{-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap;max-height:100%}.large-cell-block-y{-webkit-overflow-scrolling:touch;-ms-overflow-style:-ms-autohiding-scrollbar;max-height:100%;min-height:100%;overflow-y:auto}}.grid-y.grid-frame{-webkit-box-align:stretch;-ms-flex-align:stretch;-webkit-align-items:stretch;align-items:stretch;-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap;height:100vh;overflow:hidden;position:relative;width:auto}@media print,screen and (min-width:40em){.grid-y.medium-grid-frame{-webkit-box-align:stretch;-ms-flex-align:stretch;-webkit-align-items:stretch;align-items:stretch;-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap;height:100vh;overflow:hidden;position:relative;width:auto}}@media print,screen and (min-width:64em){.grid-y.large-grid-frame{-webkit-box-align:stretch;-ms-flex-align:stretch;-webkit-align-items:stretch;align-items:stretch;-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap;height:100vh;overflow:hidden;position:relative;width:auto}}.cell .grid-y.grid-frame{height:100%}@media print,screen and (min-width:40em){.cell .grid-y.medium-grid-frame{height:100%}}@media print,screen and (min-width:64em){.cell .grid-y.large-grid-frame{height:100%}}.grid-margin-y{margin-bottom:-.625rem;margin-top:-.625rem}@media print,screen and (min-width:40em){.grid-margin-y{margin-bottom:-.9375rem;margin-top:-.9375rem}}.grid-margin-y>.cell{height:calc(100% - 1.25rem);margin-bottom:.625rem;margin-top:.625rem}@media print,screen and (min-width:40em){.grid-margin-y>.cell{height:calc(100% - 1.875rem);margin-bottom:.9375rem;margin-top:.9375rem}}.grid-margin-y>.auto{height:auto}.grid-margin-y>.shrink{height:auto}.grid-margin-y>.small-1{height:calc(8.33333% - 1.25rem)}.grid-margin-y>.small-2{height:calc(16.66667% - 1.25rem)}.grid-margin-y>.small-3{height:calc(25% - 1.25rem)}.grid-margin-y>.small-4{height:calc(33.33333% - 1.25rem)}.grid-margin-y>.small-5{height:calc(41.66667% - 1.25rem)}.grid-margin-y>.small-6{height:calc(50% - 1.25rem)}.grid-margin-y>.small-7{height:calc(58.33333% - 1.25rem)}.grid-margin-y>.small-8{height:calc(66.66667% - 1.25rem)}.grid-margin-y>.small-9{height:calc(75% - 1.25rem)}.grid-margin-y>.small-10{height:calc(83.33333% - 1.25rem)}.grid-margin-y>.small-11{height:calc(91.66667% - 1.25rem)}.grid-margin-y>.small-12{height:calc(100% - 1.25rem)}@media print,screen and (min-width:40em){.grid-margin-y>.auto{height:auto}.grid-margin-y>.shrink{height:auto}.grid-margin-y>.small-1{height:calc(8.33333% - 1.875rem)}.grid-margin-y>.small-2{height:calc(16.66667% - 1.875rem)}.grid-margin-y>.small-3{height:calc(25% - 1.875rem)}.grid-margin-y>.small-4{height:calc(33.33333% - 1.875rem)}.grid-margin-y>.small-5{height:calc(41.66667% - 1.875rem)}.grid-margin-y>.small-6{height:calc(50% - 1.875rem)}.grid-margin-y>.small-7{height:calc(58.33333% - 1.875rem)}.grid-margin-y>.small-8{height:calc(66.66667% - 1.875rem)}.grid-margin-y>.small-9{height:calc(75% - 1.875rem)}.grid-margin-y>.small-10{height:calc(83.33333% - 1.875rem)}.grid-margin-y>.small-11{height:calc(91.66667% - 1.875rem)}.grid-margin-y>.small-12{height:calc(100% - 1.875rem)}.grid-margin-y>.medium-auto{height:auto}.grid-margin-y>.medium-shrink{height:auto}.grid-margin-y>.medium-1{height:calc(8.33333% - 1.875rem)}.grid-margin-y>.medium-2{height:calc(16.66667% - 1.875rem)}.grid-margin-y>.medium-3{height:calc(25% - 1.875rem)}.grid-margin-y>.medium-4{height:calc(33.33333% - 1.875rem)}.grid-margin-y>.medium-5{height:calc(41.66667% - 1.875rem)}.grid-margin-y>.medium-6{height:calc(50% - 1.875rem)}.grid-margin-y>.medium-7{height:calc(58.33333% - 1.875rem)}.grid-margin-y>.medium-8{height:calc(66.66667% - 1.875rem)}.grid-margin-y>.medium-9{height:calc(75% - 1.875rem)}.grid-margin-y>.medium-10{height:calc(83.33333% - 1.875rem)}.grid-margin-y>.medium-11{height:calc(91.66667% - 1.875rem)}.grid-margin-y>.medium-12{height:calc(100% - 1.875rem)}}@media print,screen and (min-width:64em){.grid-margin-y>.large-auto{height:auto}.grid-margin-y>.large-shrink{height:auto}.grid-margin-y>.large-1{height:calc(8.33333% - 1.875rem)}.grid-margin-y>.large-2{height:calc(16.66667% - 1.875rem)}.grid-margin-y>.large-3{height:calc(25% - 1.875rem)}.grid-margin-y>.large-4{height:calc(33.33333% - 1.875rem)}.grid-margin-y>.large-5{height:calc(41.66667% - 1.875rem)}.grid-margin-y>.large-6{height:calc(50% - 1.875rem)}.grid-margin-y>.large-7{height:calc(58.33333% - 1.875rem)}.grid-margin-y>.large-8{height:calc(66.66667% - 1.875rem)}.grid-margin-y>.large-9{height:calc(75% - 1.875rem)}.grid-margin-y>.large-10{height:calc(83.33333% - 1.875rem)}.grid-margin-y>.large-11{height:calc(91.66667% - 1.875rem)}.grid-margin-y>.large-12{height:calc(100% - 1.875rem)}}.grid-frame.grid-margin-y{height:calc(100vh + 1.25rem)}@media print,screen and (min-width:40em){.grid-frame.grid-margin-y{height:calc(100vh + 1.875rem)}}@media print,screen and (min-width:64em){.grid-frame.grid-margin-y{height:calc(100vh + 1.875rem)}}@media print,screen and (min-width:40em){.grid-margin-y.medium-grid-frame{height:calc(100vh + 1.875rem)}}@media print,screen and (min-width:64em){.grid-margin-y.large-grid-frame{height:calc(100vh + 1.875rem)}}.button{-webkit-appearance:none;border:1px solid transparent;border-radius:0;cursor:pointer;display:inline-block;font-family:inherit;font-size:.9rem;line-height:1;margin:0 0 1rem;padding:.85em 1em;text-align:center;-webkit-transition:background-color .25s ease-out,color .25s ease-out;transition:background-color .25s ease-out,color .25s ease-out;vertical-align:middle}[data-whatinput=mouse] .button{outline:0}.button.tiny{font-size:.6rem}.button.small{font-size:.75rem}.button.large{font-size:1.25rem}.button.expanded{display:block;margin-left:0;margin-right:0;width:100%}.button,.button.disabled,.button.disabled:focus,.button.disabled:hover,.button[disabled],.button[disabled]:focus,.button[disabled]:hover{background-color:#1779ba;color:#fefefe}.button:focus,.button:hover{background-color:#14679e;color:#fefefe}.button.primary,.button.primary.disabled,.button.primary.disabled:focus,.button.primary.disabled:hover,.button.primary[disabled],.button.primary[disabled]:focus,.button.primary[disabled]:hover{background-color:#1779ba;color:#fefefe}.button.primary:focus,.button.primary:hover{background-color:#126195;color:#fefefe}.button.secondary,.button.secondary.disabled,.button.secondary.disabled:focus,.button.secondary.disabled:hover,.button.secondary[disabled],.button.secondary[disabled]:focus,.button.secondary[disabled]:hover{background-color:#767676;color:#fefefe}.button.secondary:focus,.button.secondary:hover{background-color:#5e5e5e;color:#fefefe}.button.success,.button.success.disabled,.button.success.disabled:focus,.button.success.disabled:hover,.button.success[disabled],.button.success[disabled]:focus,.button.success[disabled]:hover{background-color:#3adb76;color:#0a0a0a}.button.success:focus,.button.success:hover{background-color:#22bb5b;color:#0a0a0a}.button.warning,.button.warning.disabled,.button.warning.disabled:focus,.button.warning.disabled:hover,.button.warning[disabled],.button.warning[disabled]:focus,.button.warning[disabled]:hover{background-color:#ffae00;color:#0a0a0a}.button.warning:focus,.button.warning:hover{background-color:#cc8b00;color:#0a0a0a}.button.alert,.button.alert.disabled,.button.alert.disabled:focus,.button.alert.disabled:hover,.button.alert[disabled],.button.alert[disabled]:focus,.button.alert[disabled]:hover{background-color:#cc4b37;color:#fefefe}.button.alert:focus,.button.alert:hover{background-color:#a53b2a;color:#fefefe}.button.hollow,.button.hollow.disabled,.button.hollow.disabled:focus,.button.hollow.disabled:hover,.button.hollow:focus,.button.hollow:hover,.button.hollow[disabled],.button.hollow[disabled]:focus,.button.hollow[disabled]:hover{background-color:transparent}.button.hollow,.button.hollow.disabled,.button.hollow.disabled:focus,.button.hollow.disabled:hover,.button.hollow[disabled],.button.hollow[disabled]:focus,.button.hollow[disabled]:hover{border:1px solid #1779ba;color:#1779ba}.button.hollow:focus,.button.hollow:hover{border-color:#0c3d5d;color:#0c3d5d}.button.hollow.primary,.button.hollow.primary.disabled,.button.hollow.primary.disabled:focus,.button.hollow.primary.disabled:hover,.button.hollow.primary[disabled],.button.hollow.primary[disabled]:focus,.button.hollow.primary[disabled]:hover{border:1px solid #1779ba;color:#1779ba}.button.hollow.primary:focus,.button.hollow.primary:hover{border-color:#0c3d5d;color:#0c3d5d}.button.hollow.secondary,.button.hollow.secondary.disabled,.button.hollow.secondary.disabled:focus,.button.hollow.secondary.disabled:hover,.button.hollow.secondary[disabled],.button.hollow.secondary[disabled]:focus,.button.hollow.secondary[disabled]:hover{border:1px solid #767676;color:#767676}.button.hollow.secondary:focus,.button.hollow.secondary:hover{border-color:#3b3b3b;color:#3b3b3b}.button.hollow.success,.button.hollow.success.disabled,.button.hollow.success.disabled:focus,.button.hollow.success.disabled:hover,.button.hollow.success[disabled],.button.hollow.success[disabled]:focus,.button.hollow.success[disabled]:hover{border:1px solid #3adb76;color:#3adb76}.button.hollow.success:focus,.button.hollow.success:hover{border-color:#157539;color:#157539}.button.hollow.warning,.button.hollow.warning.disabled,.button.hollow.warning.disabled:focus,.button.hollow.warning.disabled:hover,.button.hollow.warning[disabled],.button.hollow.warning[disabled]:focus,.button.hollow.warning[disabled]:hover{border:1px solid #ffae00;color:#ffae00}.button.hollow.warning:focus,.button.hollow.warning:hover{border-color:#805700;color:#805700}.button.hollow.alert,.button.hollow.alert.disabled,.button.hollow.alert.disabled:focus,.button.hollow.alert.disabled:hover,.button.hollow.alert[disabled],.button.hollow.alert[disabled]:focus,.button.hollow.alert[disabled]:hover{border:1px solid #cc4b37;color:#cc4b37}.button.hollow.alert:focus,.button.hollow.alert:hover{border-color:#67251a;color:#67251a}.button.clear,.button.clear.disabled,.button.clear.disabled:focus,.button.clear.disabled:hover,.button.clear:focus,.button.clear:hover,.button.clear[disabled],.button.clear[disabled]:focus,.button.clear[disabled]:hover{background-color:transparent;border-color:transparent}.button.clear,.button.clear.disabled,.button.clear.disabled:focus,.button.clear.disabled:hover,.button.clear[disabled],.button.clear[disabled]:focus,.button.clear[disabled]:hover{color:#1779ba}.button.clear:focus,.button.clear:hover{color:#0c3d5d}.button.clear.primary,.button.clear.primary.disabled,.button.clear.primary.disabled:focus,.button.clear.primary.disabled:hover,.button.clear.primary[disabled],.button.clear.primary[disabled]:focus,.button.clear.primary[disabled]:hover{color:#1779ba}.button.clear.primary:focus,.button.clear.primary:hover{color:#0c3d5d}.button.clear.secondary,.button.clear.secondary.disabled,.button.clear.secondary.disabled:focus,.button.clear.secondary.disabled:hover,.button.clear.secondary[disabled],.button.clear.secondary[disabled]:focus,.button.clear.secondary[disabled]:hover{color:#767676}.button.clear.secondary:focus,.button.clear.secondary:hover{color:#3b3b3b}.button.clear.success,.button.clear.success.disabled,.button.clear.success.disabled:focus,.button.clear.success.disabled:hover,.button.clear.success[disabled],.button.clear.success[disabled]:focus,.button.clear.success[disabled]:hover{color:#3adb76}.button.clear.success:focus,.button.clear.success:hover{color:#157539}.button.clear.warning,.button.clear.warning.disabled,.button.clear.warning.disabled:focus,.button.clear.warning.disabled:hover,.button.clear.warning[disabled],.button.clear.warning[disabled]:focus,.button.clear.warning[disabled]:hover{color:#ffae00}.button.clear.warning:focus,.button.clear.warning:hover{color:#805700}.button.clear.alert,.button.clear.alert.disabled,.button.clear.alert.disabled:focus,.button.clear.alert.disabled:hover,.button.clear.alert[disabled],.button.clear.alert[disabled]:focus,.button.clear.alert[disabled]:hover{color:#cc4b37}.button.clear.alert:focus,.button.clear.alert:hover{color:#67251a}.button.disabled,.button[disabled]{cursor:not-allowed;opacity:.25}.button.dropdown:after{border-color:#fefefe transparent transparent;border-style:solid;border-width:.4em .4em 0;content:"";display:block;display:inline-block;float:right;height:0;margin-left:1em;position:relative;top:.4em;width:0}.button.dropdown.clear:after,.button.dropdown.hollow:after{border-top-color:#1779ba}.button.dropdown.clear.primary:after,.button.dropdown.hollow.primary:after{border-top-color:#1779ba}.button.dropdown.clear.secondary:after,.button.dropdown.hollow.secondary:after{border-top-color:#767676}.button.dropdown.clear.success:after,.button.dropdown.hollow.success:after{border-top-color:#3adb76}.button.dropdown.clear.warning:after,.button.dropdown.hollow.warning:after{border-top-color:#ffae00}.button.dropdown.clear.alert:after,.button.dropdown.hollow.alert:after{border-top-color:#cc4b37}.button.arrow-only:after{float:none;margin-left:0;top:-.1em}a.button:focus,a.button:hover{text-decoration:none}.button-group{-webkit-box-align:stretch;-ms-flex-align:stretch;-webkit-box-flex:1;-ms-flex-positive:1;-webkit-align-items:stretch;align-items:stretch;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-grow:1;flex-grow:1;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;margin-bottom:1rem}.button-group:after,.button-group:before{-ms-flex-preferred-size:0;-webkit-box-ordinal-group:2;-ms-flex-order:1;content:" ";display:table;-webkit-flex-basis:0;flex-basis:0;-webkit-order:1;order:1}.button-group:after{clear:both}.button-group:after,.button-group:before{display:none}.button-group .button{-webkit-box-flex:0;-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto;font-size:.9rem;margin:0 1px 1px 0}.button-group .button:last-child{margin-right:0}.button-group.tiny .button{font-size:.6rem}.button-group.small .button{font-size:.75rem}.button-group.large .button{font-size:1.25rem}.button-group.expanded .button{-webkit-box-flex:1;-webkit-flex:1 1 0px;-ms-flex:1 1 0px;flex:1 1 0px}.button-group.primary .button,.button-group.primary .button.disabled,.button-group.primary .button.disabled:focus,.button-group.primary .button.disabled:hover,.button-group.primary .button[disabled],.button-group.primary .button[disabled]:focus,.button-group.primary .button[disabled]:hover{background-color:#1779ba;color:#fefefe}.button-group.primary .button:focus,.button-group.primary .button:hover{background-color:#126195;color:#fefefe}.button-group.secondary .button,.button-group.secondary .button.disabled,.button-group.secondary .button.disabled:focus,.button-group.secondary .button.disabled:hover,.button-group.secondary .button[disabled],.button-group.secondary .button[disabled]:focus,.button-group.secondary .button[disabled]:hover{background-color:#767676;color:#fefefe}.button-group.secondary .button:focus,.button-group.secondary .button:hover{background-color:#5e5e5e;color:#fefefe}.button-group.success .button,.button-group.success .button.disabled,.button-group.success .button.disabled:focus,.button-group.success .button.disabled:hover,.button-group.success .button[disabled],.button-group.success .button[disabled]:focus,.button-group.success .button[disabled]:hover{background-color:#3adb76;color:#0a0a0a}.button-group.success .button:focus,.button-group.success .button:hover{background-color:#22bb5b;color:#0a0a0a}.button-group.warning .button,.button-group.warning .button.disabled,.button-group.warning .button.disabled:focus,.button-group.warning .button.disabled:hover,.button-group.warning .button[disabled],.button-group.warning .button[disabled]:focus,.button-group.warning .button[disabled]:hover{background-color:#ffae00;color:#0a0a0a}.button-group.warning .button:focus,.button-group.warning .button:hover{background-color:#cc8b00;color:#0a0a0a}.button-group.alert .button,.button-group.alert .button.disabled,.button-group.alert .button.disabled:focus,.button-group.alert .button.disabled:hover,.button-group.alert .button[disabled],.button-group.alert .button[disabled]:focus,.button-group.alert .button[disabled]:hover{background-color:#cc4b37;color:#fefefe}.button-group.alert .button:focus,.button-group.alert .button:hover{background-color:#a53b2a;color:#fefefe}.button-group.hollow .button,.button-group.hollow .button.disabled,.button-group.hollow .button.disabled:focus,.button-group.hollow .button.disabled:hover,.button-group.hollow .button:focus,.button-group.hollow .button:hover,.button-group.hollow .button[disabled],.button-group.hollow .button[disabled]:focus,.button-group.hollow .button[disabled]:hover{background-color:transparent}.button-group.hollow .button,.button-group.hollow .button.disabled,.button-group.hollow .button.disabled:focus,.button-group.hollow .button.disabled:hover,.button-group.hollow .button[disabled],.button-group.hollow .button[disabled]:focus,.button-group.hollow .button[disabled]:hover{border:1px solid #1779ba;color:#1779ba}.button-group.hollow .button:focus,.button-group.hollow .button:hover{border-color:#0c3d5d;color:#0c3d5d}.button-group.hollow .button.primary,.button-group.hollow .button.primary.disabled,.button-group.hollow .button.primary.disabled:focus,.button-group.hollow .button.primary.disabled:hover,.button-group.hollow .button.primary[disabled],.button-group.hollow .button.primary[disabled]:focus,.button-group.hollow .button.primary[disabled]:hover,.button-group.hollow.primary .button,.button-group.hollow.primary .button.disabled,.button-group.hollow.primary .button.disabled:focus,.button-group.hollow.primary .button.disabled:hover,.button-group.hollow.primary .button[disabled],.button-group.hollow.primary .button[disabled]:focus,.button-group.hollow.primary .button[disabled]:hover{border:1px solid #1779ba;color:#1779ba}.button-group.hollow .button.primary:focus,.button-group.hollow .button.primary:hover,.button-group.hollow.primary .button:focus,.button-group.hollow.primary .button:hover{border-color:#0c3d5d;color:#0c3d5d}.button-group.hollow .button.secondary,.button-group.hollow .button.secondary.disabled,.button-group.hollow .button.secondary.disabled:focus,.button-group.hollow .button.secondary.disabled:hover,.button-group.hollow .button.secondary[disabled],.button-group.hollow .button.secondary[disabled]:focus,.button-group.hollow .button.secondary[disabled]:hover,.button-group.hollow.secondary .button,.button-group.hollow.secondary .button.disabled,.button-group.hollow.secondary .button.disabled:focus,.button-group.hollow.secondary .button.disabled:hover,.button-group.hollow.secondary .button[disabled],.button-group.hollow.secondary .button[disabled]:focus,.button-group.hollow.secondary .button[disabled]:hover{border:1px solid #767676;color:#767676}.button-group.hollow .button.secondary:focus,.button-group.hollow .button.secondary:hover,.button-group.hollow.secondary .button:focus,.button-group.hollow.secondary .button:hover{border-color:#3b3b3b;color:#3b3b3b}.button-group.hollow .button.success,.button-group.hollow .button.success.disabled,.button-group.hollow .button.success.disabled:focus,.button-group.hollow .button.success.disabled:hover,.button-group.hollow .button.success[disabled],.button-group.hollow .button.success[disabled]:focus,.button-group.hollow .button.success[disabled]:hover,.button-group.hollow.success .button,.button-group.hollow.success .button.disabled,.button-group.hollow.success .button.disabled:focus,.button-group.hollow.success .button.disabled:hover,.button-group.hollow.success .button[disabled],.button-group.hollow.success .button[disabled]:focus,.button-group.hollow.success .button[disabled]:hover{border:1px solid #3adb76;color:#3adb76}.button-group.hollow .button.success:focus,.button-group.hollow .button.success:hover,.button-group.hollow.success .button:focus,.button-group.hollow.success .button:hover{border-color:#157539;color:#157539}.button-group.hollow .button.warning,.button-group.hollow .button.warning.disabled,.button-group.hollow .button.warning.disabled:focus,.button-group.hollow .button.warning.disabled:hover,.button-group.hollow .button.warning[disabled],.button-group.hollow .button.warning[disabled]:focus,.button-group.hollow .button.warning[disabled]:hover,.button-group.hollow.warning .button,.button-group.hollow.warning .button.disabled,.button-group.hollow.warning .button.disabled:focus,.button-group.hollow.warning .button.disabled:hover,.button-group.hollow.warning .button[disabled],.button-group.hollow.warning .button[disabled]:focus,.button-group.hollow.warning .button[disabled]:hover{border:1px solid #ffae00;color:#ffae00}.button-group.hollow .button.warning:focus,.button-group.hollow .button.warning:hover,.button-group.hollow.warning .button:focus,.button-group.hollow.warning .button:hover{border-color:#805700;color:#805700}.button-group.hollow.alert .button,.button-group.hollow.alert .button.disabled,.button-group.hollow.alert .button.disabled:focus,.button-group.hollow.alert .button.disabled:hover,.button-group.hollow.alert .button[disabled],.button-group.hollow.alert .button[disabled]:focus,.button-group.hollow.alert .button[disabled]:hover,.button-group.hollow .button.alert,.button-group.hollow .button.alert.disabled,.button-group.hollow .button.alert.disabled:focus,.button-group.hollow .button.alert.disabled:hover,.button-group.hollow .button.alert[disabled],.button-group.hollow .button.alert[disabled]:focus,.button-group.hollow .button.alert[disabled]:hover{border:1px solid #cc4b37;color:#cc4b37}.button-group.hollow.alert .button:focus,.button-group.hollow.alert .button:hover,.button-group.hollow .button.alert:focus,.button-group.hollow .button.alert:hover{border-color:#67251a;color:#67251a}.button-group.clear .button,.button-group.clear .button.disabled,.button-group.clear .button.disabled:focus,.button-group.clear .button.disabled:hover,.button-group.clear .button:focus,.button-group.clear .button:hover,.button-group.clear .button[disabled],.button-group.clear .button[disabled]:focus,.button-group.clear .button[disabled]:hover{background-color:transparent;border-color:transparent}.button-group.clear .button,.button-group.clear .button.disabled,.button-group.clear .button.disabled:focus,.button-group.clear .button.disabled:hover,.button-group.clear .button[disabled],.button-group.clear .button[disabled]:focus,.button-group.clear .button[disabled]:hover{color:#1779ba}.button-group.clear .button:focus,.button-group.clear .button:hover{color:#0c3d5d}.button-group.clear .button.primary,.button-group.clear .button.primary.disabled,.button-group.clear .button.primary.disabled:focus,.button-group.clear .button.primary.disabled:hover,.button-group.clear .button.primary[disabled],.button-group.clear .button.primary[disabled]:focus,.button-group.clear .button.primary[disabled]:hover,.button-group.clear.primary .button,.button-group.clear.primary .button.disabled,.button-group.clear.primary .button.disabled:focus,.button-group.clear.primary .button.disabled:hover,.button-group.clear.primary .button[disabled],.button-group.clear.primary .button[disabled]:focus,.button-group.clear.primary .button[disabled]:hover{color:#1779ba}.button-group.clear .button.primary:focus,.button-group.clear .button.primary:hover,.button-group.clear.primary .button:focus,.button-group.clear.primary .button:hover{color:#0c3d5d}.button-group.clear .button.secondary,.button-group.clear .button.secondary.disabled,.button-group.clear .button.secondary.disabled:focus,.button-group.clear .button.secondary.disabled:hover,.button-group.clear .button.secondary[disabled],.button-group.clear .button.secondary[disabled]:focus,.button-group.clear .button.secondary[disabled]:hover,.button-group.clear.secondary .button,.button-group.clear.secondary .button.disabled,.button-group.clear.secondary .button.disabled:focus,.button-group.clear.secondary .button.disabled:hover,.button-group.clear.secondary .button[disabled],.button-group.clear.secondary .button[disabled]:focus,.button-group.clear.secondary .button[disabled]:hover{color:#767676}.button-group.clear .button.secondary:focus,.button-group.clear .button.secondary:hover,.button-group.clear.secondary .button:focus,.button-group.clear.secondary .button:hover{color:#3b3b3b}.button-group.clear .button.success,.button-group.clear .button.success.disabled,.button-group.clear .button.success.disabled:focus,.button-group.clear .button.success.disabled:hover,.button-group.clear .button.success[disabled],.button-group.clear .button.success[disabled]:focus,.button-group.clear .button.success[disabled]:hover,.button-group.clear.success .button,.button-group.clear.success .button.disabled,.button-group.clear.success .button.disabled:focus,.button-group.clear.success .button.disabled:hover,.button-group.clear.success .button[disabled],.button-group.clear.success .button[disabled]:focus,.button-group.clear.success .button[disabled]:hover{color:#3adb76}.button-group.clear .button.success:focus,.button-group.clear .button.success:hover,.button-group.clear.success .button:focus,.button-group.clear.success .button:hover{color:#157539}.button-group.clear .button.warning,.button-group.clear .button.warning.disabled,.button-group.clear .button.warning.disabled:focus,.button-group.clear .button.warning.disabled:hover,.button-group.clear .button.warning[disabled],.button-group.clear .button.warning[disabled]:focus,.button-group.clear .button.warning[disabled]:hover,.button-group.clear.warning .button,.button-group.clear.warning .button.disabled,.button-group.clear.warning .button.disabled:focus,.button-group.clear.warning .button.disabled:hover,.button-group.clear.warning .button[disabled],.button-group.clear.warning .button[disabled]:focus,.button-group.clear.warning .button[disabled]:hover{color:#ffae00}.button-group.clear .button.warning:focus,.button-group.clear .button.warning:hover,.button-group.clear.warning .button:focus,.button-group.clear.warning .button:hover{color:#805700}.button-group.clear.alert .button,.button-group.clear.alert .button.disabled,.button-group.clear.alert .button.disabled:focus,.button-group.clear.alert .button.disabled:hover,.button-group.clear.alert .button[disabled],.button-group.clear.alert .button[disabled]:focus,.button-group.clear.alert .button[disabled]:hover,.button-group.clear .button.alert,.button-group.clear .button.alert.disabled,.button-group.clear .button.alert.disabled:focus,.button-group.clear .button.alert.disabled:hover,.button-group.clear .button.alert[disabled],.button-group.clear .button.alert[disabled]:focus,.button-group.clear .button.alert[disabled]:hover{color:#cc4b37}.button-group.clear.alert .button:focus,.button-group.clear.alert .button:hover,.button-group.clear .button.alert:focus,.button-group.clear .button.alert:hover{color:#67251a}.button-group.no-gaps .button{margin-right:-.0625rem}.button-group.no-gaps .button+.button{border-left-color:transparent}.button-group.stacked,.button-group.stacked-for-medium,.button-group.stacked-for-small{-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap}.button-group.stacked-for-medium .button,.button-group.stacked-for-small .button,.button-group.stacked .button{-webkit-box-flex:0;-webkit-flex:0 0 100%;-ms-flex:0 0 100%;flex:0 0 100%}.button-group.stacked-for-medium .button:last-child,.button-group.stacked-for-small .button:last-child,.button-group.stacked .button:last-child{margin-bottom:0}.button-group.stacked-for-medium.expanded .button,.button-group.stacked-for-small.expanded .button,.button-group.stacked.expanded .button{-webkit-box-flex:1;-webkit-flex:1 1 0px;-ms-flex:1 1 0px;flex:1 1 0px}@media print,screen and (min-width:40em){.button-group.stacked-for-small .button{-webkit-box-flex:0;-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto;margin-bottom:0}}@media print,screen and (min-width:64em){.button-group.stacked-for-medium .button{-webkit-box-flex:0;-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto;margin-bottom:0}}@media print,screen and (max-width:39.99875em){.button-group.stacked-for-small.expanded{display:block}.button-group.stacked-for-small.expanded .button{display:block;margin-right:0}}@media print,screen and (max-width:63.99875em){.button-group.stacked-for-medium.expanded{display:block}.button-group.stacked-for-medium.expanded .button{display:block;margin-right:0}}.close-button{color:#8a8a8a;cursor:pointer;position:absolute;z-index:10}[data-whatinput=mouse] .close-button{outline:0}.close-button:focus,.close-button:hover{color:#0a0a0a}.close-button.small{font-size:1.5em;line-height:1;right:.66rem;top:.33em}.close-button,.close-button.medium{font-size:2em;line-height:1;right:1rem;top:.5rem}.label{border-radius:0;cursor:default;display:inline-block;font-size:.8rem;line-height:1;padding:.33333rem .5rem;white-space:nowrap}.label,.label.primary{background:#1779ba;color:#fefefe}.label.secondary{background:#767676;color:#fefefe}.label.success{background:#3adb76;color:#0a0a0a}.label.warning{background:#ffae00;color:#0a0a0a}.label.alert{background:#cc4b37;color:#fefefe}.progress{background-color:#cacaca;border-radius:0;height:1rem;margin-bottom:1rem}.progress.primary .progress-meter{background-color:#1779ba}.progress.secondary .progress-meter{background-color:#767676}.progress.success .progress-meter{background-color:#3adb76}.progress.warning .progress-meter{background-color:#ffae00}.progress.alert .progress-meter{background-color:#cc4b37}.progress-meter{background-color:#1779ba;display:block;height:100%;position:relative;width:0}.progress-meter-text{color:#fefefe;font-size:.75rem;font-weight:700;left:50%;margin:0;position:absolute;top:50%;-webkit-transform:translate(-50%,-50%);-ms-transform:translate(-50%,-50%);transform:translate(-50%,-50%);white-space:nowrap}.slider{background-color:#e6e6e6;cursor:pointer;height:.5rem;margin-bottom:2.25rem;margin-top:1.25rem;position:relative;-ms-touch-action:none;touch-action:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.slider-fill{background-color:#cacaca;display:inline-block;height:.5rem;left:0;max-width:100%;position:absolute;top:0;-webkit-transition:all .2s ease-in-out;transition:all .2s ease-in-out}.slider-fill.is-dragging{-webkit-transition:all 0s linear;transition:all 0s linear}.slider-handle{background-color:#1779ba;border-radius:0;cursor:-webkit-grab;cursor:grab;display:inline-block;height:1.4rem;left:0;position:absolute;top:50%;-ms-touch-action:manipulation;touch-action:manipulation;-webkit-transform:translateY(-50%);-ms-transform:translateY(-50%);transform:translateY(-50%);-webkit-transition:all .2s ease-in-out;transition:all .2s ease-in-out;width:1.4rem;z-index:1}[data-whatinput=mouse] .slider-handle{outline:0}.slider-handle:hover{background-color:#14679e}.slider-handle.is-dragging{cursor:-webkit-grabbing;cursor:grabbing;-webkit-transition:all 0s linear;transition:all 0s linear}.slider.disabled,.slider[disabled]{cursor:not-allowed;opacity:.25}.slider.vertical{display:inline-block;height:12.5rem;margin:0 1.25rem;-webkit-transform:scaleY(-1);-ms-transform:scaleY(-1);transform:scaleY(-1);width:.5rem}.slider.vertical .slider-fill{max-height:100%;top:0;width:.5rem}.slider.vertical .slider-handle{height:1.4rem;left:50%;position:absolute;top:0;-webkit-transform:translateX(-50%);-ms-transform:translateX(-50%);transform:translateX(-50%);width:1.4rem}.switch{color:#fefefe;font-size:.875rem;font-weight:700;height:2rem;margin-bottom:1rem;outline:0;position:relative;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.switch-input{margin-bottom:0;opacity:0;position:absolute}.switch-paddle{background:#cacaca;border-radius:0;color:inherit;cursor:pointer;display:block;font-weight:inherit;height:2rem;position:relative;-webkit-transition:all .25s ease-out;transition:all .25s ease-out;width:4rem}input+.switch-paddle{margin:0}.switch-paddle:after{background:#fefefe;border-radius:0;content:"";display:block;height:1.5rem;left:.25rem;position:absolute;top:.25rem;-webkit-transform:translateZ(0);transform:translateZ(0);-webkit-transition:all .25s ease-out;transition:all .25s ease-out;width:1.5rem}input:checked~.switch-paddle{background:#1779ba}input:checked~.switch-paddle:after{left:2.25rem}input:disabled~.switch-paddle{cursor:not-allowed;opacity:.5}[data-whatinput=mouse] input:focus~.switch-paddle{outline:0}.switch-active,.switch-inactive{position:absolute;top:50%;-webkit-transform:translateY(-50%);-ms-transform:translateY(-50%);transform:translateY(-50%)}.switch-active{display:none;left:8%}input:checked+label>.switch-active{display:block}.switch-inactive{right:15%}input:checked+label>.switch-inactive{display:none}.switch.tiny{height:1.5rem}.switch.tiny .switch-paddle{font-size:.625rem;height:1.5rem;width:3rem}.switch.tiny .switch-paddle:after{height:1rem;left:.25rem;top:.25rem;width:1rem}.switch.tiny input:checked~.switch-paddle:after{left:1.75rem}.switch.small{height:1.75rem}.switch.small .switch-paddle{font-size:.75rem;height:1.75rem;width:3.5rem}.switch.small .switch-paddle:after{height:1.25rem;left:.25rem;top:.25rem;width:1.25rem}.switch.small input:checked~.switch-paddle:after{left:2rem}.switch.large{height:2.5rem}.switch.large .switch-paddle{font-size:1rem;height:2.5rem;width:5rem}.switch.large .switch-paddle:after{height:2rem;left:.25rem;top:.25rem;width:2rem}.switch.large input:checked~.switch-paddle:after{left:2.75rem}table{border-collapse:collapse;border-radius:0;margin-bottom:1rem;width:100%}tbody,tfoot,thead{background-color:#fefefe;border:1px solid #f1f1f1}caption{font-weight:700;padding:.5rem .625rem .625rem}thead{background:#f8f8f8}tfoot,thead{color:#0a0a0a}tfoot{background:#f1f1f1}tfoot tr,thead tr{background:0 0}tfoot td,tfoot th,thead td,thead th{font-weight:700;padding:.5rem .625rem .625rem;text-align:left}tbody td,tbody th{padding:.5rem .625rem .625rem}tbody tr:nth-child(2n){background-color:#f1f1f1;border-bottom:0}table.unstriped tbody{background-color:#fefefe}table.unstriped tbody tr{background-color:#fefefe;border-bottom:1px solid #f1f1f1}@media print,screen and (max-width:63.99875em){table.stack tfoot,table.stack thead{display:none}table.stack td,table.stack th,table.stack tr{display:block}table.stack td{border-top:0}}table.scroll{display:block;overflow-x:auto;width:100%}table.hover thead tr:hover{background-color:#f3f3f3}table.hover tfoot tr:hover{background-color:#ececec}table.hover tbody tr:hover{background-color:#f9f9f9}table.hover:not(.unstriped) tr:nth-of-type(2n):hover{background-color:#ececec}.table-scroll{overflow-x:auto}.badge{border-radius:50%;display:inline-block;font-size:.6rem;min-width:2.1em;padding:.3em;text-align:center}.badge,.badge.primary{background:#1779ba;color:#fefefe}.badge.secondary{background:#767676;color:#fefefe}.badge.success{background:#3adb76;color:#0a0a0a}.badge.warning{background:#ffae00;color:#0a0a0a}.badge.alert{background:#cc4b37;color:#fefefe}.breadcrumbs{list-style:none;margin:0 0 1rem}.breadcrumbs:after,.breadcrumbs:before{-ms-flex-preferred-size:0;-webkit-box-ordinal-group:2;-ms-flex-order:1;content:" ";display:table;-webkit-flex-basis:0;flex-basis:0;-webkit-order:1;order:1}.breadcrumbs:after{clear:both}.breadcrumbs li{color:#0a0a0a;cursor:default;float:left;font-size:.6875rem;text-transform:uppercase}.breadcrumbs li:not(:last-child):after{color:#cacaca;content:"/";margin:0 .75rem;opacity:1;position:relative}.breadcrumbs a{color:#1779ba}.breadcrumbs a:hover{text-decoration:underline}.breadcrumbs .disabled{color:#cacaca;cursor:not-allowed}.callout{background-color:#fff;border:1px solid hsla(0,0%,4%,.25);border-radius:0;color:#0a0a0a;margin:0 0 1rem;padding:1rem;position:relative}.callout>:first-child{margin-top:0}.callout>:last-child{margin-bottom:0}.callout.primary{background-color:#d7ecfa;color:#0a0a0a}.callout.secondary{background-color:#eaeaea;color:#0a0a0a}.callout.success{background-color:#e1faea;color:#0a0a0a}.callout.warning{background-color:#fff3d9;color:#0a0a0a}.callout.alert{background-color:#f7e4e1;color:#0a0a0a}.callout.small{padding:.5rem}.callout.large{padding:3rem}.card{-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-box-flex:1;-ms-flex-positive:1;background:#fefefe;border:1px solid #e6e6e6;border-radius:0;-webkit-box-shadow:none;box-shadow:none;color:#0a0a0a;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;-webkit-flex-grow:1;flex-grow:1;margin-bottom:1rem;overflow:hidden}.card>:last-child{margin-bottom:0}.card-divider{-webkit-box-flex:0;background:#e6e6e6;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex:0 1 auto;-ms-flex:0 1 auto;flex:0 1 auto;padding:1rem}.card-divider>:last-child{margin-bottom:0}.card-section{-webkit-box-flex:1;-webkit-flex:1 0 auto;-ms-flex:1 0 auto;flex:1 0 auto;padding:1rem}.card-section>:last-child{margin-bottom:0}.card-image{min-height:1px}.dropdown-pane{background-color:#fefefe;border:1px solid #cacaca;border-radius:0;display:none;font-size:1rem;padding:1rem;position:absolute;visibility:hidden;width:300px;z-index:10}.dropdown-pane.is-opening{display:block}.dropdown-pane.is-open{display:block;visibility:visible}.dropdown-pane.tiny{width:100px}.dropdown-pane.small{width:200px}.dropdown-pane.large{width:400px}.pagination{margin-bottom:1rem;margin-left:0}.pagination:after,.pagination:before{-ms-flex-preferred-size:0;-webkit-box-ordinal-group:2;-ms-flex-order:1;content:" ";display:table;-webkit-flex-basis:0;flex-basis:0;-webkit-order:1;order:1}.pagination:after{clear:both}.pagination li{border-radius:0;display:none;font-size:.875rem;margin-right:.0625rem}.pagination li:first-child,.pagination li:last-child{display:inline-block}@media print,screen and (min-width:40em){.pagination li{display:inline-block}}.pagination a,.pagination button{border-radius:0;color:#0a0a0a;display:block;padding:.1875rem .625rem}.pagination a:hover,.pagination button:hover{background:#e6e6e6}.pagination .current{background:#1779ba;color:#fefefe;cursor:default;padding:.1875rem .625rem}.pagination .disabled{color:#cacaca;cursor:not-allowed;padding:.1875rem .625rem}.pagination .disabled:hover{background:0 0}.pagination .ellipsis:after{color:#0a0a0a;content:"…";padding:.1875rem .625rem}.pagination-previous.disabled:before,.pagination-previous a:before{content:"«";display:inline-block;margin-right:.5rem}.pagination-next.disabled:after,.pagination-next a:after{content:"»";display:inline-block;margin-left:.5rem}.has-tip{border-bottom:1px dotted #8a8a8a;cursor:help;display:inline-block;font-weight:700;position:relative}.tooltip{background-color:#0a0a0a;border-radius:0;color:#fefefe;font-size:80%;max-width:10rem;padding:.75rem;position:absolute;top:calc(100% + .6495rem);z-index:1200}.tooltip:before{position:absolute}.tooltip.bottom:before{border-color:transparent transparent #0a0a0a;border-style:solid;border-width:0 .75rem .75rem;bottom:100%;content:"";display:block;height:0;width:0}.tooltip.bottom.align-center:before{left:50%;-webkit-transform:translateX(-50%);-ms-transform:translateX(-50%);transform:translateX(-50%)}.tooltip.top:before{border-color:#0a0a0a transparent transparent;border-style:solid;border-width:.75rem .75rem 0;bottom:auto;content:"";display:block;height:0;top:100%;width:0}.tooltip.top.align-center:before{left:50%;-webkit-transform:translateX(-50%);-ms-transform:translateX(-50%);transform:translateX(-50%)}.tooltip.left:before{border-color:transparent transparent transparent #0a0a0a;border-style:solid;border-width:.75rem 0 .75rem .75rem;content:"";display:block;height:0;left:100%;width:0}.tooltip.left.align-center:before{bottom:auto;top:50%;-webkit-transform:translateY(-50%);-ms-transform:translateY(-50%);transform:translateY(-50%)}.tooltip.right:before{border-color:transparent #0a0a0a transparent transparent;border-style:solid;border-width:.75rem .75rem .75rem 0;content:"";display:block;height:0;left:auto;right:100%;width:0}.tooltip.right.align-center:before{bottom:auto;top:50%;-webkit-transform:translateY(-50%);-ms-transform:translateY(-50%);transform:translateY(-50%)}.tooltip.align-top:before{bottom:auto;top:10%}.tooltip.align-bottom:before{bottom:10%;top:auto}.tooltip.align-left:before{left:10%;right:auto}.tooltip.align-right:before{left:auto;right:10%}.accordion{background:#fefefe;list-style-type:none;margin-left:0}.accordion[disabled] .accordion-title{cursor:not-allowed}.accordion-item:first-child>:first-child{border-radius:0}.accordion-item:last-child>:last-child{border-radius:0}.accordion-title{border:1px solid #e6e6e6;border-bottom:0;color:#1779ba;display:block;font-size:.75rem;line-height:1;padding:1.25rem 1rem;position:relative}:last-child:not(.is-active)>.accordion-title{border-bottom:1px solid #e6e6e6;border-radius:0}.accordion-title:focus,.accordion-title:hover{background-color:#e6e6e6}.accordion-title:before{content:"+";margin-top:-.5rem;position:absolute;right:1rem;top:50%}.is-active>.accordion-title:before{content:"–"}.accordion-content{background-color:#fefefe;border:1px solid #e6e6e6;border-bottom:0;color:#0a0a0a;display:none;padding:1rem}:last-child>.accordion-content:last-child{border-bottom:1px solid #e6e6e6}.media-object{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap;margin-bottom:1rem}.media-object img{max-width:none}@media print,screen and (max-width:39.99875em){.media-object.stack-for-small{-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap}}.media-object-section{-webkit-box-flex:0;-webkit-flex:0 1 auto;-ms-flex:0 1 auto;flex:0 1 auto}.media-object-section:first-child{padding-right:1rem}.media-object-section:last-child:not(:nth-child(2)){padding-left:1rem}.media-object-section>:last-child{margin-bottom:0}@media print,screen and (max-width:39.99875em){.stack-for-small .media-object-section{-ms-flex-preferred-size:100%;-webkit-flex-basis:100%;flex-basis:100%;max-width:100%;padding:0 0 1rem}.stack-for-small .media-object-section img{width:100%}}.media-object-section.main-section{-webkit-box-flex:1;-webkit-flex:1 1 0px;-ms-flex:1 1 0px;flex:1 1 0px}.orbit,.orbit-container{position:relative}.orbit-container{height:0;list-style:none;margin:0;overflow:hidden}.orbit-slide{position:absolute;width:100%}.orbit-slide.no-motionui.is-active{left:0;top:0}.orbit-figure{margin:0}.orbit-image{margin:0;max-width:100%;width:100%}.orbit-caption{background-color:hsla(0,0%,4%,.5);bottom:0;margin-bottom:0;width:100%}.orbit-caption,.orbit-next,.orbit-previous{color:#fefefe;padding:1rem;position:absolute}.orbit-next,.orbit-previous{top:50%;-webkit-transform:translateY(-50%);-ms-transform:translateY(-50%);transform:translateY(-50%);z-index:10}[data-whatinput=mouse] .orbit-next,[data-whatinput=mouse] .orbit-previous{outline:0}.orbit-next:active,.orbit-next:focus,.orbit-next:hover,.orbit-previous:active,.orbit-previous:focus,.orbit-previous:hover{background-color:hsla(0,0%,4%,.5)}.orbit-previous{left:0}.orbit-next{left:auto;right:0}.orbit-bullets{margin-bottom:.8rem;margin-top:.8rem;position:relative;text-align:center}[data-whatinput=mouse] .orbit-bullets{outline:0}.orbit-bullets button{background-color:#cacaca;border-radius:50%;height:1.2rem;margin:.1rem;width:1.2rem}.orbit-bullets button:hover{background-color:#8a8a8a}.orbit-bullets button.is-active{background-color:#8a8a8a}.flex-video,.responsive-embed{height:0;margin-bottom:1rem;overflow:hidden;padding-bottom:75%;position:relative}.flex-video embed,.flex-video iframe,.flex-video object,.flex-video video,.responsive-embed embed,.responsive-embed iframe,.responsive-embed object,.responsive-embed video{height:100%;left:0;position:absolute;top:0;width:100%}.flex-video.widescreen,.responsive-embed.widescreen{padding-bottom:56.25%}.tabs{background:#fefefe;border:1px solid #e6e6e6;list-style-type:none;margin:0}.tabs:after,.tabs:before{-ms-flex-preferred-size:0;-webkit-box-ordinal-group:2;-ms-flex-order:1;content:" ";display:table;-webkit-flex-basis:0;flex-basis:0;-webkit-order:1;order:1}.tabs:after{clear:both}.tabs.vertical>li{display:block;float:none;width:auto}.tabs.simple>li>a{padding:0}.tabs.simple>li>a:hover{background:0 0}.tabs.primary{background:#1779ba}.tabs.primary>li>a{color:#fefefe}.tabs.primary>li>a:focus,.tabs.primary>li>a:hover{background:#1673b1}.tabs-title{float:left}.tabs-title>a{color:#1779ba;display:block;font-size:.75rem;line-height:1;padding:1.25rem 1.5rem}[data-whatinput=mouse] .tabs-title>a{outline:0}.tabs-title>a:hover{background:#fefefe;color:#1468a0}.tabs-title>a:focus,.tabs-title>a[aria-selected=true]{background:#e6e6e6;color:#1779ba}.tabs-content{background:#fefefe;border:1px solid #e6e6e6;border-top:0;color:#0a0a0a;-webkit-transition:all .5s ease;transition:all .5s ease}.tabs-content.vertical{border:1px solid #e6e6e6;border-left:0}.tabs-panel{display:none;padding:1rem}.tabs-panel.is-active{display:block}.thumbnail{border:4px solid #fefefe;border-radius:0;-webkit-box-shadow:0 0 0 1px hsla(0,0%,4%,.2);box-shadow:0 0 0 1px hsla(0,0%,4%,.2);display:inline-block;line-height:0;margin-bottom:1rem;max-width:100%}a.thumbnail{-webkit-transition:-webkit-box-shadow .2s ease-out;transition:-webkit-box-shadow .2s ease-out;transition:box-shadow .2s ease-out;transition:box-shadow .2s ease-out,-webkit-box-shadow .2s ease-out}a.thumbnail:focus,a.thumbnail:hover{-webkit-box-shadow:0 0 6px 1px rgba(23,121,186,.5);box-shadow:0 0 6px 1px rgba(23,121,186,.5)}a.thumbnail image{-webkit-box-shadow:none;box-shadow:none}.menu{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;list-style:none;margin:0;padding:0;position:relative}[data-whatinput=mouse] .menu li{outline:0}.menu .button,.menu a{display:block;line-height:1;padding:.7rem 1rem;text-decoration:none}.menu a,.menu button,.menu input,.menu select{margin-bottom:0}.menu input{display:inline-block}.menu,.menu.horizontal{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap}.menu.vertical{-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap}.menu.vertical.icon-bottom li a i,.menu.vertical.icon-bottom li a img,.menu.vertical.icon-bottom li a svg,.menu.vertical.icon-top li a i,.menu.vertical.icon-top li a img,.menu.vertical.icon-top li a svg{text-align:left}.menu.expanded li{-webkit-box-flex:1;-webkit-flex:1 1 0px;-ms-flex:1 1 0px;flex:1 1 0px}.menu.expanded.icon-bottom li a i,.menu.expanded.icon-bottom li a img,.menu.expanded.icon-bottom li a svg,.menu.expanded.icon-top li a i,.menu.expanded.icon-top li a img,.menu.expanded.icon-top li a svg{text-align:left}.menu.simple{-webkit-box-align:center;-ms-flex-align:center;-webkit-align-items:center;align-items:center}.menu.simple li+li{margin-left:1rem}.menu.simple a{padding:0}@media print,screen and (min-width:40em){.menu.medium-horizontal{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap}.menu.medium-vertical{-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap}.menu.medium-expanded li,.menu.medium-simple li{-webkit-box-flex:1;-webkit-flex:1 1 0px;-ms-flex:1 1 0px;flex:1 1 0px}}@media print,screen and (min-width:64em){.menu.large-horizontal{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap}.menu.large-vertical{-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap}.menu.large-expanded li,.menu.large-simple li{-webkit-box-flex:1;-webkit-flex:1 1 0px;-ms-flex:1 1 0px;flex:1 1 0px}}.menu.nested{margin-left:1rem;margin-right:0}.menu.icon-bottom a,.menu.icon-left a,.menu.icon-right a,.menu.icon-top a,.menu.icons a{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex}.menu.icon-left li a,.menu.nested.icon-left li a{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-flow:row nowrap;-ms-flex-flow:row nowrap;flex-flow:row nowrap}.menu.icon-left li a i,.menu.icon-left li a img,.menu.icon-left li a svg,.menu.nested.icon-left li a i,.menu.nested.icon-left li a img,.menu.nested.icon-left li a svg{margin-right:.25rem}.menu.icon-right li a,.menu.nested.icon-right li a{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-flow:row nowrap;-ms-flex-flow:row nowrap;flex-flow:row nowrap}.menu.icon-right li a i,.menu.icon-right li a img,.menu.icon-right li a svg,.menu.nested.icon-right li a i,.menu.nested.icon-right li a img,.menu.nested.icon-right li a svg{margin-left:.25rem}.menu.icon-top li a,.menu.nested.icon-top li a{-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-flow:column nowrap;-ms-flex-flow:column nowrap;flex-flow:column nowrap}.menu.icon-top li a i,.menu.icon-top li a img,.menu.icon-top li a svg,.menu.nested.icon-top li a i,.menu.nested.icon-top li a img,.menu.nested.icon-top li a svg{-ms-flex-item-align:stretch;-webkit-align-self:stretch;align-self:stretch;margin-bottom:.25rem;text-align:center}.menu.icon-bottom li a,.menu.nested.icon-bottom li a{-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-flow:column nowrap;-ms-flex-flow:column nowrap;flex-flow:column nowrap}.menu.icon-bottom li a i,.menu.icon-bottom li a img,.menu.icon-bottom li a svg,.menu.nested.icon-bottom li a i,.menu.nested.icon-bottom li a img,.menu.nested.icon-bottom li a svg{-ms-flex-item-align:stretch;-webkit-align-self:stretch;align-self:stretch;margin-bottom:.25rem;text-align:center}.menu .is-active>a{background:#1779ba;color:#fefefe}.menu .active>a{background:#1779ba;color:#fefefe}.menu.align-left{-webkit-box-pack:start;-ms-flex-pack:start;-webkit-justify-content:flex-start;justify-content:flex-start}.menu.align-right li{-webkit-box-pack:end;-ms-flex-pack:end;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-justify-content:flex-end;justify-content:flex-end}.menu.align-right li .submenu li{-webkit-box-pack:start;-ms-flex-pack:start;-webkit-justify-content:flex-start;justify-content:flex-start}.menu.align-right.vertical li{display:block;text-align:right}.menu.align-right.icon-bottom li a i,.menu.align-right.icon-bottom li a img,.menu.align-right.icon-bottom li a svg,.menu.align-right.icon-top li a i,.menu.align-right.icon-top li a img,.menu.align-right.icon-top li a svg,.menu.align-right.vertical li .submenu li{text-align:right}.menu.align-right .nested{margin-left:0;margin-right:1rem}.menu.align-center li{-webkit-box-pack:center;-ms-flex-pack:center;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-justify-content:center;justify-content:center}.menu.align-center li .submenu li{-webkit-box-pack:start;-ms-flex-pack:start;-webkit-justify-content:flex-start;justify-content:flex-start}.menu .menu-text{color:inherit;font-weight:700;line-height:1;padding:.7rem 1rem}.menu-centered>.menu{-webkit-box-pack:center;-ms-flex-pack:center;-webkit-justify-content:center;justify-content:center}.menu-centered>.menu li{-webkit-box-pack:center;-ms-flex-pack:center;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-justify-content:center;justify-content:center}.menu-centered>.menu li .submenu li{-webkit-box-pack:start;-ms-flex-pack:start;-webkit-justify-content:flex-start;justify-content:flex-start}.no-js [data-responsive-menu] ul{display:none}.menu-icon{cursor:pointer;display:inline-block;height:16px;position:relative;vertical-align:middle;width:20px}.menu-icon:after{background:#fefefe;-webkit-box-shadow:0 7px 0 #fefefe,0 14px 0 #fefefe;box-shadow:0 7px 0 #fefefe,0 14px 0 #fefefe;content:"";display:block;height:2px;left:0;position:absolute;top:0;width:100%}.menu-icon:hover:after{background:#cacaca;-webkit-box-shadow:0 7px 0 #cacaca,0 14px 0 #cacaca;box-shadow:0 7px 0 #cacaca,0 14px 0 #cacaca}.menu-icon.dark{cursor:pointer;display:inline-block;height:16px;position:relative;vertical-align:middle;width:20px}.menu-icon.dark:after{background:#0a0a0a;-webkit-box-shadow:0 7px 0 #0a0a0a,0 14px 0 #0a0a0a;box-shadow:0 7px 0 #0a0a0a,0 14px 0 #0a0a0a;content:"";display:block;height:2px;left:0;position:absolute;top:0;width:100%}.menu-icon.dark:hover:after{background:#8a8a8a;-webkit-box-shadow:0 7px 0 #8a8a8a,0 14px 0 #8a8a8a;box-shadow:0 7px 0 #8a8a8a,0 14px 0 #8a8a8a}.accordion-menu li{width:100%}.accordion-menu .is-accordion-submenu a,.accordion-menu a{padding:.7rem 1rem}.accordion-menu .nested.is-accordion-submenu{margin-left:1rem;margin-right:0}.accordion-menu.align-right .nested.is-accordion-submenu{margin-left:0;margin-right:1rem}.accordion-menu .is-accordion-submenu-parent:not(.has-submenu-toggle)>a{position:relative}.accordion-menu .is-accordion-submenu-parent:not(.has-submenu-toggle)>a:after{border-color:#1779ba transparent transparent;border-style:solid;border-width:6px 6px 0;content:"";display:block;height:0;margin-top:-3px;position:absolute;right:1rem;top:50%;width:0}.accordion-menu.align-left .is-accordion-submenu-parent>a:after{left:auto;right:1rem}.accordion-menu.align-right .is-accordion-submenu-parent>a:after{left:1rem;right:auto}.accordion-menu .is-accordion-submenu-parent[aria-expanded=true]>a:after{-webkit-transform:rotate(180deg);-ms-transform:rotate(180deg);transform:rotate(180deg);-webkit-transform-origin:50% 50%;-ms-transform-origin:50% 50%;transform-origin:50% 50%}.is-accordion-submenu-parent{position:relative}.has-submenu-toggle>a{margin-right:40px}.submenu-toggle{cursor:pointer;height:40px;position:absolute;right:0;top:0;width:40px}.submenu-toggle:after{border-color:#1779ba transparent transparent;border-style:solid;border-width:6px 6px 0;bottom:0;content:"";display:block;height:0;margin:auto;top:0;width:0}.submenu-toggle[aria-expanded=true]:after{-webkit-transform:scaleY(-1);-ms-transform:scaleY(-1);transform:scaleY(-1);-webkit-transform-origin:50% 50%;-ms-transform-origin:50% 50%;transform-origin:50% 50%}.submenu-toggle-text{clip:rect(0,0,0,0)!important;border:0!important;height:1px!important;overflow:hidden!important;padding:0!important;position:absolute!important;white-space:nowrap!important;width:1px!important}.is-drilldown{overflow:hidden;position:relative}.is-drilldown li{display:block}.is-drilldown.animate-height{-webkit-transition:height .5s;transition:height .5s}.drilldown a{background:#fefefe;padding:.7rem 1rem}.drilldown .is-drilldown-submenu{background:#fefefe;left:100%;position:absolute;top:0;-webkit-transition:-webkit-transform .15s linear;transition:-webkit-transform .15s linear;transition:transform .15s linear;transition:transform .15s linear,-webkit-transform .15s linear;width:100%;z-index:-1}.drilldown .is-drilldown-submenu.is-active{display:block;-webkit-transform:translateX(-100%);-ms-transform:translateX(-100%);transform:translateX(-100%);z-index:1}.drilldown .is-drilldown-submenu.is-closing{-webkit-transform:translateX(100%);-ms-transform:translateX(100%);transform:translateX(100%)}.drilldown .is-drilldown-submenu a{padding:.7rem 1rem}.drilldown .nested.is-drilldown-submenu{margin-left:0;margin-right:0}.drilldown .drilldown-submenu-cover-previous{min-height:100%}.drilldown .is-drilldown-submenu-parent>a{position:relative}.drilldown .is-drilldown-submenu-parent>a:after{border-color:transparent transparent transparent #1779ba;border-style:solid;border-width:6px 0 6px 6px;content:"";display:block;height:0;margin-top:-6px;position:absolute;right:1rem;top:50%;width:0}.drilldown.align-left .is-drilldown-submenu-parent>a:after{border-color:transparent transparent transparent #1779ba;border-style:solid;border-width:6px 0 6px 6px;content:"";display:block;height:0;left:auto;right:1rem;width:0}.drilldown.align-right .is-drilldown-submenu-parent>a:after{border-color:transparent #1779ba transparent transparent;border-style:solid;border-width:6px 6px 6px 0;content:"";display:block;height:0;left:1rem;right:auto;width:0}.drilldown .js-drilldown-back>a:before{border-color:transparent #1779ba transparent transparent;border-style:solid;border-width:6px 6px 6px 0;content:"";display:block;display:inline-block;height:0;margin-right:.75rem;vertical-align:middle;width:0}.dropdown.menu>li.opens-left>.is-dropdown-submenu{left:auto;right:0;top:100%}.dropdown.menu>li.opens-right>.is-dropdown-submenu{left:0;right:auto;top:100%}.dropdown.menu>li.is-dropdown-submenu-parent>a{padding-right:1.5rem;position:relative}.dropdown.menu>li.is-dropdown-submenu-parent>a:after{border-color:#1779ba transparent transparent;border-style:solid;border-width:6px 6px 0;content:"";display:block;height:0;left:auto;margin-top:-3px;right:5px;width:0}[data-whatinput=mouse] .dropdown.menu a{outline:0}.dropdown.menu>li>a{padding:.7rem 1rem}.dropdown.menu>li.is-active>a{background:0 0;color:#1779ba}.no-js .dropdown.menu ul{display:none}.dropdown.menu .nested.is-dropdown-submenu{margin-left:0;margin-right:0}.dropdown.menu.vertical>li .is-dropdown-submenu{top:0}.dropdown.menu.vertical>li.opens-left>.is-dropdown-submenu{left:auto;right:100%;top:0}.dropdown.menu.vertical>li.opens-right>.is-dropdown-submenu{left:100%;right:auto}.dropdown.menu.vertical>li>a:after{right:14px}.dropdown.menu.vertical>li.opens-left>a:after{border-color:transparent #1779ba transparent transparent;border-style:solid;border-width:6px 6px 6px 0;content:"";display:block;height:0;left:5px;right:auto;width:0}.dropdown.menu.vertical>li.opens-right>a:after{border-color:transparent transparent transparent #1779ba;border-style:solid;border-width:6px 0 6px 6px;content:"";display:block;height:0;width:0}@media print,screen and (min-width:40em){.dropdown.menu.medium-horizontal>li.opens-left>.is-dropdown-submenu{left:auto;right:0;top:100%}.dropdown.menu.medium-horizontal>li.opens-right>.is-dropdown-submenu{left:0;right:auto;top:100%}.dropdown.menu.medium-horizontal>li.is-dropdown-submenu-parent>a{padding-right:1.5rem;position:relative}.dropdown.menu.medium-horizontal>li.is-dropdown-submenu-parent>a:after{border-color:#1779ba transparent transparent;border-style:solid;border-width:6px 6px 0;content:"";display:block;height:0;left:auto;margin-top:-3px;right:5px;width:0}.dropdown.menu.medium-vertical>li .is-dropdown-submenu{top:0}.dropdown.menu.medium-vertical>li.opens-left>.is-dropdown-submenu{left:auto;right:100%;top:0}.dropdown.menu.medium-vertical>li.opens-right>.is-dropdown-submenu{left:100%;right:auto}.dropdown.menu.medium-vertical>li>a:after{right:14px}.dropdown.menu.medium-vertical>li.opens-left>a:after{border-color:transparent #1779ba transparent transparent;border-style:solid;border-width:6px 6px 6px 0;content:"";display:block;height:0;left:5px;right:auto;width:0}.dropdown.menu.medium-vertical>li.opens-right>a:after{border-color:transparent transparent transparent #1779ba;border-style:solid;border-width:6px 0 6px 6px;content:"";display:block;height:0;width:0}}@media print,screen and (min-width:64em){.dropdown.menu.large-horizontal>li.opens-left>.is-dropdown-submenu{left:auto;right:0;top:100%}.dropdown.menu.large-horizontal>li.opens-right>.is-dropdown-submenu{left:0;right:auto;top:100%}.dropdown.menu.large-horizontal>li.is-dropdown-submenu-parent>a{padding-right:1.5rem;position:relative}.dropdown.menu.large-horizontal>li.is-dropdown-submenu-parent>a:after{border-color:#1779ba transparent transparent;border-style:solid;border-width:6px 6px 0;content:"";display:block;height:0;left:auto;margin-top:-3px;right:5px;width:0}.dropdown.menu.large-vertical>li .is-dropdown-submenu{top:0}.dropdown.menu.large-vertical>li.opens-left>.is-dropdown-submenu{left:auto;right:100%;top:0}.dropdown.menu.large-vertical>li.opens-right>.is-dropdown-submenu{left:100%;right:auto}.dropdown.menu.large-vertical>li>a:after{right:14px}.dropdown.menu.large-vertical>li.opens-left>a:after{border-color:transparent #1779ba transparent transparent;border-style:solid;border-width:6px 6px 6px 0;content:"";display:block;height:0;left:5px;right:auto;width:0}.dropdown.menu.large-vertical>li.opens-right>a:after{border-color:transparent transparent transparent #1779ba;border-style:solid;border-width:6px 0 6px 6px;content:"";display:block;height:0;width:0}}.dropdown.menu.align-right .is-dropdown-submenu.first-sub{left:auto;right:0;top:100%}.is-dropdown-menu.vertical{width:100px}.is-dropdown-menu.vertical.align-right{float:right}.is-dropdown-submenu-parent{position:relative}.is-dropdown-submenu-parent a:after{left:auto;margin-top:-6px;position:absolute;right:5px;top:50%}.is-dropdown-submenu-parent.opens-inner>.is-dropdown-submenu{left:auto;top:100%}.is-dropdown-submenu-parent.opens-left>.is-dropdown-submenu{left:auto;right:100%}.is-dropdown-submenu-parent.opens-right>.is-dropdown-submenu{left:100%;right:auto}.is-dropdown-submenu{background:#fefefe;border:1px solid #cacaca;display:none;left:100%;min-width:200px;position:absolute;top:0;z-index:1}.dropdown .is-dropdown-submenu a{padding:.7rem 1rem}.is-dropdown-submenu .is-dropdown-submenu-parent>a:after{right:14px}.is-dropdown-submenu .is-dropdown-submenu-parent.opens-left>a:after{border-color:transparent #1779ba transparent transparent;border-style:solid;border-width:6px 6px 6px 0;content:"";display:block;height:0;left:5px;right:auto;width:0}.is-dropdown-submenu .is-dropdown-submenu-parent.opens-right>a:after{border-color:transparent transparent transparent #1779ba;border-style:solid;border-width:6px 0 6px 6px;content:"";display:block;height:0;width:0}.is-dropdown-submenu .is-dropdown-submenu{margin-top:-1px}.is-dropdown-submenu>li{width:100%}.is-dropdown-submenu.js-dropdown-active{display:block}.is-off-canvas-open{overflow:hidden}.js-off-canvas-overlay{background:hsla(0,0%,100%,.25);height:100%;left:0;opacity:0;overflow:hidden;position:absolute;top:0;-webkit-transition:opacity .5s ease,visibility .5s ease;transition:opacity .5s ease,visibility .5s ease;visibility:hidden;width:100%;z-index:11}.js-off-canvas-overlay.is-visible{opacity:1;visibility:visible}.js-off-canvas-overlay.is-closable{cursor:pointer}.js-off-canvas-overlay.is-overlay-absolute{position:absolute}.js-off-canvas-overlay.is-overlay-fixed{position:fixed}.off-canvas-wrapper{overflow:hidden;position:relative}.off-canvas{-webkit-backface-visibility:hidden;backface-visibility:hidden;background:#e6e6e6;position:fixed;-webkit-transition:-webkit-transform .5s ease;transition:-webkit-transform .5s ease;transition:transform .5s ease;transition:transform .5s ease,-webkit-transform .5s ease;z-index:12}[data-whatinput=mouse] .off-canvas{outline:0}.off-canvas.is-transition-push{z-index:12}.off-canvas.is-closed{visibility:hidden}.off-canvas.is-transition-overlap{z-index:13}.off-canvas.is-transition-overlap.is-open{-webkit-box-shadow:0 0 10px hsla(0,0%,4%,.7);box-shadow:0 0 10px hsla(0,0%,4%,.7)}.off-canvas.is-open{-webkit-transform:translate(0);-ms-transform:translate(0);transform:translate(0)}.off-canvas-absolute{-webkit-backface-visibility:hidden;backface-visibility:hidden;background:#e6e6e6;position:absolute;-webkit-transition:-webkit-transform .5s ease;transition:-webkit-transform .5s ease;transition:transform .5s ease;transition:transform .5s ease,-webkit-transform .5s ease;z-index:12}[data-whatinput=mouse] .off-canvas-absolute{outline:0}.off-canvas-absolute.is-transition-push{z-index:12}.off-canvas-absolute.is-closed{visibility:hidden}.off-canvas-absolute.is-transition-overlap{z-index:13}.off-canvas-absolute.is-transition-overlap.is-open{-webkit-box-shadow:0 0 10px hsla(0,0%,4%,.7);box-shadow:0 0 10px hsla(0,0%,4%,.7)}.off-canvas-absolute.is-open{-webkit-transform:translate(0);-ms-transform:translate(0);transform:translate(0)}.position-left{-webkit-overflow-scrolling:touch;height:100%;left:0;overflow-y:auto;top:0;width:250px}.off-canvas-content .off-canvas.position-left,.position-left{-webkit-transform:translateX(-250px);-ms-transform:translateX(-250px);transform:translateX(-250px)}.off-canvas-content .off-canvas.position-left.is-transition-overlap.is-open{-webkit-transform:translate(0);-ms-transform:translate(0);transform:translate(0)}.off-canvas-content.is-open-left.has-transition-push{-webkit-transform:translateX(250px);-ms-transform:translateX(250px);transform:translateX(250px)}.position-left.is-transition-push{-webkit-box-shadow:inset -13px 0 20px -13px hsla(0,0%,4%,.25);box-shadow:inset -13px 0 20px -13px hsla(0,0%,4%,.25)}.position-right{-webkit-overflow-scrolling:touch;height:100%;overflow-y:auto;right:0;top:0;width:250px}.off-canvas-content .off-canvas.position-right,.position-right{-webkit-transform:translateX(250px);-ms-transform:translateX(250px);transform:translateX(250px)}.off-canvas-content .off-canvas.position-right.is-transition-overlap.is-open{-webkit-transform:translate(0);-ms-transform:translate(0);transform:translate(0)}.off-canvas-content.is-open-right.has-transition-push{-webkit-transform:translateX(-250px);-ms-transform:translateX(-250px);transform:translateX(-250px)}.position-right.is-transition-push{-webkit-box-shadow:inset 13px 0 20px -13px hsla(0,0%,4%,.25);box-shadow:inset 13px 0 20px -13px hsla(0,0%,4%,.25)}.position-top{-webkit-overflow-scrolling:touch;height:250px;left:0;overflow-x:auto;top:0;width:100%}.off-canvas-content .off-canvas.position-top,.position-top{-webkit-transform:translateY(-250px);-ms-transform:translateY(-250px);transform:translateY(-250px)}.off-canvas-content .off-canvas.position-top.is-transition-overlap.is-open{-webkit-transform:translate(0);-ms-transform:translate(0);transform:translate(0)}.off-canvas-content.is-open-top.has-transition-push{-webkit-transform:translateY(250px);-ms-transform:translateY(250px);transform:translateY(250px)}.position-top.is-transition-push{-webkit-box-shadow:inset 0 -13px 20px -13px hsla(0,0%,4%,.25);box-shadow:inset 0 -13px 20px -13px hsla(0,0%,4%,.25)}.position-bottom{-webkit-overflow-scrolling:touch;bottom:0;height:250px;left:0;overflow-x:auto;width:100%}.off-canvas-content .off-canvas.position-bottom,.position-bottom{-webkit-transform:translateY(250px);-ms-transform:translateY(250px);transform:translateY(250px)}.off-canvas-content .off-canvas.position-bottom.is-transition-overlap.is-open{-webkit-transform:translate(0);-ms-transform:translate(0);transform:translate(0)}.off-canvas-content.is-open-bottom.has-transition-push{-webkit-transform:translateY(-250px);-ms-transform:translateY(-250px);transform:translateY(-250px)}.position-bottom.is-transition-push{-webkit-box-shadow:inset 0 13px 20px -13px hsla(0,0%,4%,.25);box-shadow:inset 0 13px 20px -13px hsla(0,0%,4%,.25)}.off-canvas-content{-webkit-backface-visibility:hidden;backface-visibility:hidden;-webkit-transform:none;-ms-transform:none;transform:none}.off-canvas-content.has-transition-overlap,.off-canvas-content.has-transition-push{-webkit-transition:-webkit-transform .5s ease;transition:-webkit-transform .5s ease;transition:transform .5s ease;transition:transform .5s ease,-webkit-transform .5s ease}.off-canvas-content.has-transition-push,.off-canvas-content .off-canvas.is-open{-webkit-transform:translate(0);-ms-transform:translate(0);transform:translate(0)}@media print,screen and (min-width:40em){.position-left.reveal-for-medium{-webkit-transform:none;-ms-transform:none;transform:none;-webkit-transition:none;transition:none;visibility:visible;z-index:12}.position-left.reveal-for-medium .close-button{display:none}.off-canvas-content .position-left.reveal-for-medium{-webkit-transform:none;-ms-transform:none;transform:none}.off-canvas-content.has-reveal-left{margin-left:250px}.position-left.reveal-for-medium~.off-canvas-content{margin-left:250px}.position-right.reveal-for-medium{-webkit-transform:none;-ms-transform:none;transform:none;-webkit-transition:none;transition:none;visibility:visible;z-index:12}.position-right.reveal-for-medium .close-button{display:none}.off-canvas-content .position-right.reveal-for-medium{-webkit-transform:none;-ms-transform:none;transform:none}.off-canvas-content.has-reveal-right{margin-right:250px}.position-right.reveal-for-medium~.off-canvas-content{margin-right:250px}.position-top.reveal-for-medium{-webkit-transform:none;-ms-transform:none;transform:none;-webkit-transition:none;transition:none;visibility:visible;z-index:12}.position-top.reveal-for-medium .close-button{display:none}.off-canvas-content .position-top.reveal-for-medium{-webkit-transform:none;-ms-transform:none;transform:none}.off-canvas-content.has-reveal-top{margin-top:250px}.position-top.reveal-for-medium~.off-canvas-content{margin-top:250px}.position-bottom.reveal-for-medium{-webkit-transform:none;-ms-transform:none;transform:none;-webkit-transition:none;transition:none;visibility:visible;z-index:12}.position-bottom.reveal-for-medium .close-button{display:none}.off-canvas-content .position-bottom.reveal-for-medium{-webkit-transform:none;-ms-transform:none;transform:none}.off-canvas-content.has-reveal-bottom{margin-bottom:250px}.position-bottom.reveal-for-medium~.off-canvas-content{margin-bottom:250px}}@media print,screen and (min-width:64em){.position-left.reveal-for-large{-webkit-transform:none;-ms-transform:none;transform:none;-webkit-transition:none;transition:none;visibility:visible;z-index:12}.position-left.reveal-for-large .close-button{display:none}.off-canvas-content .position-left.reveal-for-large{-webkit-transform:none;-ms-transform:none;transform:none}.off-canvas-content.has-reveal-left{margin-left:250px}.position-left.reveal-for-large~.off-canvas-content{margin-left:250px}.position-right.reveal-for-large{-webkit-transform:none;-ms-transform:none;transform:none;-webkit-transition:none;transition:none;visibility:visible;z-index:12}.position-right.reveal-for-large .close-button{display:none}.off-canvas-content .position-right.reveal-for-large{-webkit-transform:none;-ms-transform:none;transform:none}.off-canvas-content.has-reveal-right{margin-right:250px}.position-right.reveal-for-large~.off-canvas-content{margin-right:250px}.position-top.reveal-for-large{-webkit-transform:none;-ms-transform:none;transform:none;-webkit-transition:none;transition:none;visibility:visible;z-index:12}.position-top.reveal-for-large .close-button{display:none}.off-canvas-content .position-top.reveal-for-large{-webkit-transform:none;-ms-transform:none;transform:none}.off-canvas-content.has-reveal-top{margin-top:250px}.position-top.reveal-for-large~.off-canvas-content{margin-top:250px}.position-bottom.reveal-for-large{-webkit-transform:none;-ms-transform:none;transform:none;-webkit-transition:none;transition:none;visibility:visible;z-index:12}.position-bottom.reveal-for-large .close-button{display:none}.off-canvas-content .position-bottom.reveal-for-large{-webkit-transform:none;-ms-transform:none;transform:none}.off-canvas-content.has-reveal-bottom{margin-bottom:250px}.position-bottom.reveal-for-large~.off-canvas-content{margin-bottom:250px}}@media print,screen and (min-width:40em){.off-canvas.in-canvas-for-medium{background:0 0;height:auto;overflow:visible;position:static;-webkit-transition:none;transition:none;visibility:visible;width:auto}.off-canvas.in-canvas-for-medium.position-bottom,.off-canvas.in-canvas-for-medium.position-left,.off-canvas.in-canvas-for-medium.position-right,.off-canvas.in-canvas-for-medium.position-top{-webkit-box-shadow:none;box-shadow:none;-webkit-transform:none;-ms-transform:none;transform:none}.off-canvas.in-canvas-for-medium .close-button{display:none}}@media print,screen and (min-width:64em){.off-canvas.in-canvas-for-large{background:0 0;height:auto;overflow:visible;position:static;-webkit-transition:none;transition:none;visibility:visible;width:auto}.off-canvas.in-canvas-for-large.position-bottom,.off-canvas.in-canvas-for-large.position-left,.off-canvas.in-canvas-for-large.position-right,.off-canvas.in-canvas-for-large.position-top{-webkit-box-shadow:none;box-shadow:none;-webkit-transform:none;-ms-transform:none;transform:none}.off-canvas.in-canvas-for-large .close-button{display:none}}html.is-reveal-open{overflow-y:hidden;position:fixed;width:100%}html.is-reveal-open.zf-has-scroll{-webkit-overflow-scrolling:touch;overflow-y:scroll}html.is-reveal-open body{overflow-y:hidden}.reveal-overlay{background-color:hsla(0,0%,4%,.45);bottom:0;left:0;position:fixed;right:0;top:0;z-index:1005}.reveal,.reveal-overlay{-webkit-overflow-scrolling:touch;display:none;overflow-y:auto}.reveal{-webkit-backface-visibility:hidden;backface-visibility:hidden;background-color:#fefefe;border:1px solid #cacaca;border-radius:0;margin-left:auto;margin-right:auto;padding:1rem;position:relative;top:100px;z-index:1006}[data-whatinput=mouse] .reveal{outline:0}@media print,screen and (min-width:40em){.reveal{min-height:0}}.reveal .column{min-width:0}.reveal>:last-child{margin-bottom:0}@media print,screen and (min-width:40em){.reveal{max-width:75rem;width:600px}}.reveal.collapse{padding:0}@media print,screen and (min-width:40em){.reveal.tiny{max-width:75rem;width:30%}.reveal.small{max-width:75rem;width:50%}.reveal.large{max-width:75rem;width:90%}}.reveal.full{border:0;border-radius:0;bottom:0;height:100%;left:0;margin-left:0;max-width:none;min-height:100%;right:0;top:0;width:100%}@media print,screen and (max-width:39.99875em){.reveal{border:0;border-radius:0;bottom:0;height:100%;left:0;margin-left:0;max-width:none;min-height:100%;right:0;top:0;width:100%}}.reveal.without-overlay{position:fixed}.sticky,.sticky-container{position:relative}.sticky{-webkit-transform:translateZ(0);transform:translateZ(0);z-index:0}.sticky.is-stuck{position:fixed;width:100%;z-index:5}.sticky.is-stuck.is-at-top{top:0}.sticky.is-stuck.is-at-bottom{bottom:0}.sticky.is-anchored{left:auto;position:relative;right:auto}.sticky.is-anchored.is-at-bottom{bottom:0}.title-bar{-webkit-box-pack:start;-ms-flex-pack:start;-webkit-box-align:center;-ms-flex-align:center;-webkit-align-items:center;align-items:center;background:#0a0a0a;color:#fefefe;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-justify-content:flex-start;justify-content:flex-start;padding:.5rem}.title-bar .menu-icon{margin-left:.25rem;margin-right:.25rem}.title-bar-left,.title-bar-right{-webkit-box-flex:1;-webkit-flex:1 1 0px;-ms-flex:1 1 0px;flex:1 1 0px}.title-bar-right{text-align:right}.title-bar-title{display:inline-block;font-weight:700;vertical-align:middle}.top-bar{-webkit-box-pack:justify;-ms-flex-pack:justify;-webkit-box-align:center;-ms-flex-align:center;-webkit-align-items:center;align-items:center;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;-webkit-justify-content:space-between;justify-content:space-between;padding:.5rem}.top-bar,.top-bar ul{background-color:#e6e6e6}.top-bar input{margin-right:1rem;max-width:200px}.top-bar .input-group-field{margin-right:0;width:100%}.top-bar input.button{width:auto}.top-bar .top-bar-left,.top-bar .top-bar-right{-webkit-box-flex:0;-webkit-flex:0 0 100%;-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}@media print,screen and (min-width:40em){.top-bar{-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap}.top-bar .top-bar-left{-webkit-box-flex:1;-webkit-flex:1 1 auto;-ms-flex:1 1 auto;flex:1 1 auto;margin-right:auto}.top-bar .top-bar-right{-webkit-box-flex:0;-webkit-flex:0 1 auto;-ms-flex:0 1 auto;flex:0 1 auto;margin-left:auto}}@media print,screen and (max-width:63.99875em){.top-bar.stacked-for-medium{-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap}.top-bar.stacked-for-medium .top-bar-left,.top-bar.stacked-for-medium .top-bar-right{-webkit-box-flex:0;-webkit-flex:0 0 100%;-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}}@media print,screen and (max-width:74.99875em){.top-bar.stacked-for-large{-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap}.top-bar.stacked-for-large .top-bar-left,.top-bar.stacked-for-large .top-bar-right{-webkit-box-flex:0;-webkit-flex:0 0 100%;-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}}.top-bar-title{margin:.5rem 1rem .5rem 0}.top-bar-left,.top-bar-right,.top-bar-title{-webkit-box-flex:0;-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto}.float-left{float:left!important}.float-right{float:right!important}.float-center{display:block;margin-left:auto;margin-right:auto}.clearfix:after,.clearfix:before{-ms-flex-preferred-size:0;-webkit-box-ordinal-group:2;-ms-flex-order:1;content:" ";display:table;-webkit-flex-basis:0;flex-basis:0;-webkit-order:1;order:1}.clearfix:after{clear:both}.align-left{-webkit-box-pack:start;-ms-flex-pack:start;-webkit-justify-content:flex-start;justify-content:flex-start}.align-right{-webkit-box-pack:end;-ms-flex-pack:end;-webkit-justify-content:flex-end;justify-content:flex-end}.align-center{-webkit-box-pack:center;-ms-flex-pack:center;-webkit-justify-content:center;justify-content:center}.align-justify{-webkit-box-pack:justify;-ms-flex-pack:justify;-webkit-justify-content:space-between;justify-content:space-between}.align-spaced{-ms-flex-pack:distribute;-webkit-justify-content:space-around;justify-content:space-around}.align-left.vertical.menu>li>a{-webkit-box-pack:start;-ms-flex-pack:start;-webkit-justify-content:flex-start;justify-content:flex-start}.align-right.vertical.menu>li>a{-webkit-box-pack:end;-ms-flex-pack:end;-webkit-justify-content:flex-end;justify-content:flex-end}.align-center.vertical.menu>li>a{-webkit-box-pack:center;-ms-flex-pack:center;-webkit-justify-content:center;justify-content:center}.align-top{-webkit-box-align:start;-ms-flex-align:start;-webkit-align-items:flex-start;align-items:flex-start}.align-self-top{-ms-flex-item-align:start;-webkit-align-self:flex-start;align-self:flex-start}.align-bottom{-webkit-box-align:end;-ms-flex-align:end;-webkit-align-items:flex-end;align-items:flex-end}.align-self-bottom{-ms-flex-item-align:end;-webkit-align-self:flex-end;align-self:flex-end}.align-middle{-webkit-box-align:center;-ms-flex-align:center;-webkit-align-items:center;align-items:center}.align-self-middle{-ms-flex-item-align:center;-webkit-align-self:center;align-self:center}.align-stretch{-webkit-box-align:stretch;-ms-flex-align:stretch;-webkit-align-items:stretch;align-items:stretch}.align-self-stretch{-ms-flex-item-align:stretch;-webkit-align-self:stretch;align-self:stretch}.align-center-middle{-webkit-box-pack:center;-ms-flex-pack:center;-webkit-box-align:center;-ms-flex-align:center;-ms-flex-line-pack:center;-webkit-align-content:center;align-content:center;-webkit-align-items:center;align-items:center;-webkit-justify-content:center;justify-content:center}.small-order-1{-webkit-box-ordinal-group:2;-ms-flex-order:1;-webkit-order:1;order:1}.small-order-2{-webkit-box-ordinal-group:3;-ms-flex-order:2;-webkit-order:2;order:2}.small-order-3{-webkit-box-ordinal-group:4;-ms-flex-order:3;-webkit-order:3;order:3}.small-order-4{-webkit-box-ordinal-group:5;-ms-flex-order:4;-webkit-order:4;order:4}.small-order-5{-webkit-box-ordinal-group:6;-ms-flex-order:5;-webkit-order:5;order:5}.small-order-6{-webkit-box-ordinal-group:7;-ms-flex-order:6;-webkit-order:6;order:6}@media print,screen and (min-width:40em){.medium-order-1{-webkit-box-ordinal-group:2;-ms-flex-order:1;-webkit-order:1;order:1}.medium-order-2{-webkit-box-ordinal-group:3;-ms-flex-order:2;-webkit-order:2;order:2}.medium-order-3{-webkit-box-ordinal-group:4;-ms-flex-order:3;-webkit-order:3;order:3}.medium-order-4{-webkit-box-ordinal-group:5;-ms-flex-order:4;-webkit-order:4;order:4}.medium-order-5{-webkit-box-ordinal-group:6;-ms-flex-order:5;-webkit-order:5;order:5}.medium-order-6{-webkit-box-ordinal-group:7;-ms-flex-order:6;-webkit-order:6;order:6}}@media print,screen and (min-width:64em){.large-order-1{-webkit-box-ordinal-group:2;-ms-flex-order:1;-webkit-order:1;order:1}.large-order-2{-webkit-box-ordinal-group:3;-ms-flex-order:2;-webkit-order:2;order:2}.large-order-3{-webkit-box-ordinal-group:4;-ms-flex-order:3;-webkit-order:3;order:3}.large-order-4{-webkit-box-ordinal-group:5;-ms-flex-order:4;-webkit-order:4;order:4}.large-order-5{-webkit-box-ordinal-group:6;-ms-flex-order:5;-webkit-order:5;order:5}.large-order-6{-webkit-box-ordinal-group:7;-ms-flex-order:6;-webkit-order:6;order:6}}.flex-container{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex}.flex-child-auto{-webkit-box-flex:1;-webkit-flex:1 1 auto;-ms-flex:1 1 auto;flex:1 1 auto}.flex-child-grow{-webkit-box-flex:1;-webkit-flex:1 0 auto;-ms-flex:1 0 auto;flex:1 0 auto}.flex-child-shrink{-webkit-box-flex:0;-webkit-flex:0 1 auto;-ms-flex:0 1 auto;flex:0 1 auto}.flex-dir-row{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row}.flex-dir-row-reverse{-webkit-box-orient:horizontal;-webkit-box-direction:reverse;-webkit-flex-direction:row-reverse;-ms-flex-direction:row-reverse;flex-direction:row-reverse}.flex-dir-column{-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column}.flex-dir-column-reverse{-webkit-box-orient:vertical;-webkit-box-direction:reverse;-webkit-flex-direction:column-reverse;-ms-flex-direction:column-reverse;flex-direction:column-reverse}@media print,screen and (min-width:40em){.medium-flex-container{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex}.medium-flex-child-auto{-webkit-box-flex:1;-webkit-flex:1 1 auto;-ms-flex:1 1 auto;flex:1 1 auto}.medium-flex-child-grow{-webkit-box-flex:1;-webkit-flex:1 0 auto;-ms-flex:1 0 auto;flex:1 0 auto}.medium-flex-child-shrink{-webkit-box-flex:0;-webkit-flex:0 1 auto;-ms-flex:0 1 auto;flex:0 1 auto}.medium-flex-dir-row{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row}.medium-flex-dir-row-reverse{-webkit-box-orient:horizontal;-webkit-box-direction:reverse;-webkit-flex-direction:row-reverse;-ms-flex-direction:row-reverse;flex-direction:row-reverse}.medium-flex-dir-column{-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column}.medium-flex-dir-column-reverse{-webkit-box-orient:vertical;-webkit-box-direction:reverse;-webkit-flex-direction:column-reverse;-ms-flex-direction:column-reverse;flex-direction:column-reverse}}@media print,screen and (min-width:64em){.large-flex-container{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex}.large-flex-child-auto{-webkit-box-flex:1;-webkit-flex:1 1 auto;-ms-flex:1 1 auto;flex:1 1 auto}.large-flex-child-grow{-webkit-box-flex:1;-webkit-flex:1 0 auto;-ms-flex:1 0 auto;flex:1 0 auto}.large-flex-child-shrink{-webkit-box-flex:0;-webkit-flex:0 1 auto;-ms-flex:0 1 auto;flex:0 1 auto}.large-flex-dir-row{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row}.large-flex-dir-row-reverse{-webkit-box-orient:horizontal;-webkit-box-direction:reverse;-webkit-flex-direction:row-reverse;-ms-flex-direction:row-reverse;flex-direction:row-reverse}.large-flex-dir-column{-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column}.large-flex-dir-column-reverse{-webkit-box-orient:vertical;-webkit-box-direction:reverse;-webkit-flex-direction:column-reverse;-ms-flex-direction:column-reverse;flex-direction:column-reverse}}.hide{display:none!important}.invisible{visibility:hidden}.visible{visibility:visible}@media print,screen and (max-width:39.99875em){.hide-for-small-only{display:none!important}}@media screen and (max-width:0em),screen and (min-width:40em){.show-for-small-only{display:none!important}}@media print,screen and (min-width:40em){.hide-for-medium{display:none!important}}@media screen and (max-width:39.99875em){.show-for-medium{display:none!important}}@media print,screen and (min-width:40em)and (max-width:63.99875em){.hide-for-medium-only{display:none!important}}@media screen and (max-width:39.99875em),screen and (min-width:64em){.show-for-medium-only{display:none!important}}@media print,screen and (min-width:64em){.hide-for-large{display:none!important}}@media screen and (max-width:63.99875em){.show-for-large{display:none!important}}@media print,screen and (min-width:64em)and (max-width:74.99875em){.hide-for-large-only{display:none!important}}@media screen and (max-width:63.99875em),screen and (min-width:75em){.show-for-large-only{display:none!important}}.show-for-sr,.show-on-focus{clip:rect(0,0,0,0)!important;border:0!important;height:1px!important;overflow:hidden!important;padding:0!important;position:absolute!important;white-space:nowrap!important;width:1px!important}.show-on-focus:active,.show-on-focus:focus{clip:auto!important;height:auto!important;overflow:visible!important;position:static!important;white-space:normal!important;width:auto!important}.hide-for-portrait,.show-for-landscape{display:block!important}@media screen and (orientation:landscape){.hide-for-portrait,.show-for-landscape{display:block!important}}@media screen and (orientation:portrait){.hide-for-portrait,.show-for-landscape{display:none!important}}.hide-for-landscape,.show-for-portrait{display:none!important}@media screen and (orientation:landscape){.hide-for-landscape,.show-for-portrait{display:none!important}}@media screen and (orientation:portrait){.hide-for-landscape,.show-for-portrait{display:block!important}}.show-for-dark-mode{display:none}.hide-for-dark-mode{display:block}@media screen and (prefers-color-scheme:dark){.show-for-dark-mode{display:block!important}.hide-for-dark-mode{display:none!important}}.show-for-ie{display:none}@media (-ms-high-contrast:active),(-ms-high-contrast:none){.show-for-ie{display:block!important}.hide-for-ie{display:none!important}}.show-for-sticky{display:none}.is-stuck .show-for-sticky{display:block}.is-stuck .hide-for-sticky{display:none}@font-face{font-display:"swap";font-family:FontAwesome}html{box-sizing:border-box}body{font-family:Roboto,sans-serif;font-size:16px;line-height:1}*,:after,:before{box-sizing:inherit}a{color:#3c4fe0}a.reference:after{font-family:FontAwesome;font-size:12px;padding:0 4px}a.reference.external:after{content:""}a.reference.download:after{content:""}a:hover{color:#3c4fe0;font-weight:500}.headerlink{margin-left:5px;visibility:hidden}.toc-backref:hover{color:#23263b}h1,h2,h3,h4,h5,h6{font-family:Roboto,sans-serif;font-size:16px;font-weight:500;letter-spacing:.2px;line-height:24px;margin-bottom:16px}h1:hover>a.headerlink,h2:hover>a.headerlink,h3:hover>a.headerlink,h4:hover>a.headerlink,h5:hover>a.headerlink,h6:hover>a.headerlink{visibility:visible}h1 a,h2 a,h3 a,h4 a,h5 a,h6 a{color:inherit}h1{font-size:32px;font-weight:700;line-height:40px;margin-bottom:28px}h2{font-size:24px;line-height:32px}h3{font-size:20px}h4{font-size:18px}h5{font-size:16px}h6{font-weight:400}img{max-width:100%}button:focus{outline:0}blockquote{border:0;margin:0;padding:0}blockquote,blockquote p,cite{color:inherit}cite{display:inline;font-size:inherit}cite:before{content:""}.show{display:block!important}.centered{display:block;margin:0 auto}.break{flex-basis:100%;height:0}@media screen and (min-width:1024px){h1{font-size:36px}}.admonition-title:before,.contents.local>ul>li a:before,.scylla-icon,.secondary-side-nav__content li a:before{background-repeat:no-repeat;background-size:contain;display:inline-block;filter:brightness(0);vertical-align:middle}.scylla-icon--about-team{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMSwuY2xzLTJ7ZmlsbDpub25lO3N0cm9rZTpncmF5O3N0cm9rZS1taXRlcmxpbWl0OjEwfS5jbHMtMntzdHJva2UtbGluZWNhcDpyb3VuZH08L3N0eWxlPjwvZGVmcz48ZyBpZD0iQ2FscXVlXzQiIGRhdGEtbmFtZT0iQ2FscXVlIDQiPjxwYXRoIGNsYXNzPSJjbHMtMSIgZD0iTTQuNjYgOS44MSAyLjYzIDExYTIuMDggMi4wOCAwIDAgMC0xLjEzIDEuODN2Ny44MWMuMTkgMS4xMS41IDEuNTMgMS41IDEuNDdNNy4wNiA5Ljk0bDEuNDQuOTQiLz48cGF0aCBjbGFzcz0iY2xzLTIiIGQ9Ik0zLjUgMTguNXY1LjM0TTkuNSAxOC41djUuMzRNOC41NCAxOC40MnY1LjMzTTE1LjUgMTguNXY1LjM0TTE2LjUgMTguNXY1LjM0TTMuMzMgMjAuNTNoNS4wOE0xMS40NSA4Ljg0bC4wNi4wNmExLjY1IDEuNjUgMCAwIDAgMi4zNCAwaDAiLz48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Ik0xMi40MiA3LjVhMS44MSAxLjgxIDAgMCAxLTEuOTItMS43N1Y1YTEuOTQgMS45NCAwIDAgMSAxLjkyLTIgMi4wNyAyLjA3IDAgMCAxIDIuMDggMnYuNzdhMiAyIDAgMCAxLTIuMDggMS43M1pNMTEuNDIgOC43NCA5LjYzIDkuOWEyLjA3IDIuMDcgMCAwIDAtMS4xMyAxLjg1djcuODJBMS40NyAxLjQ3IDAgMCAwIDEwIDIxTTEzLjc1IDkuMThsMiAuNjVjLjcuMzUuNzYgMS4wNi43NiAxLjg0djcuOWMwIC43Ny0uMjMgMS4yNC0xIDEuMjQiLz48cGF0aCBjbGFzcz0iY2xzLTIiIGQ9Ik05LjkzIDE5LjVoNS40Ii8+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNMTkuNDIgOS4xMmEyLjA3IDIuMDcgMCAwIDAgMi4wOC0xLjkzdi0uNzdhMi4wNyAyLjA3IDAgMCAwLTIuMDgtMS45MiAxLjkzIDEuOTMgMCAwIDAtMS45MiAxLjkydi43N2ExLjk0IDEuOTQgMCAwIDAgMS45MiAxLjkzWk01LjU5IDkuMTJhMS45MyAxLjkzIDAgMCAwIDEuOTItMS45M3YtLjc3QTEuOTMgMS45MyAwIDAgMCA1LjU5IDQuNSAyLjA4IDIuMDggMCAwIDAgMy41IDYuNDJ2Ljc3YTIuMDggMi4wOCAwIDAgMCAyLjA5IDEuOTNaTTIwLjQ0IDkuODFsMiAxLjE3YTIuMDYgMi4wNiAwIDAgMSAxLjEzIDEuODV2Ny44MWMtLjE4IDEuMTEtLjQ3IDEuNTMtMS40NyAxLjQ3TTE4LjA0IDkuOTRsLTEuNDQuOTMiLz48cGF0aCBjbGFzcz0iY2xzLTIiIGQ9Ik0yMS42IDE4LjV2NS4zNE0yMS43NyAyMC41M2gtNS4wOCIvPjwvZz48L3N2Zz4=)}.scylla-icon--about-us{background-image:url(data:image/svg+xml;base64,PHN2ZyBpZD0iTGF5ZXJfMyIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB2aWV3Qm94PSIwIDAgMjAgMjAiPjxkZWZzPjxzdHlsZT4uY2xzLTF7ZmlsbDpub25lO3N0cm9rZTojMDAwO3N0cm9rZS1saW5lY2FwOnJvdW5kO3N0cm9rZS1saW5lam9pbjpyb3VuZDtzdHJva2Utd2lkdGg6LjhweH08L3N0eWxlPjwvZGVmcz48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Ik02LjI4IDE5LjQ4Yy0uMTIuMDgtLjA4LjA3LS4yMy4xLS41OC4wOS0xLjEyLS4yOC0xLjI1LS44NCAwIDAtMi4zLTkuMTgtMi4zLTExLjExQzIuNSAzLjYgNS44OC40NCAxMC4zOC40NFMxNy41IDMuNDggMTcuNSA3LjVjMCAxLjkzLTEuMzIgMTEuMjMtMS4zMiAxMS4yMy0uMTMuNTYtLjY3Ljk0LTEuMjUuODQtLjEyLS4wMi0uMTMgMC0uMjMtLjA3Ii8+PHBhdGggZD0iTTE1Ljc1IDE1Ljc1Yy0uMTcgMS4xNS0uMjIgMi4zNC0uNTUgMy40Ni0uMzcuODUtMS42MyAxLjA2LTIuMjIuMzMtLjI1LS4yOC4xOS0uNjguNDQtLjQuNDMuNDYgMS4yNC4xOCAxLjMxLS40NGwuMDYtLjM0Yy4xOS0uODkuMzUtMS43OS41Ny0yLjY4LjA1LS4yNC40Mi0uMTcuMzkuMDdaIi8+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNMTEuNSA3YzAgMS45LTEuNTYgMy41LTMuNDYgMy41UzQuNSA4LjkgNC41IDdzMS42NC0zLjUgMy41NC0zLjVTMTEuNSA1LjEgMTEuNSA3WiIvPjxwYXRoIGQ9Ik04LjU1IDQuNzVjLS41OS4xMi0uNzEgMS40Mi0uMzYgMS43OC4yMy4yMy43MS4zMS43MS40N3MtLjQ4LjI0LS43MS40N2MtLjM2LjM2LS4yNCAxLjY2LjM2IDEuNzguNzEuMTQgMS43OC0uNzEgMS43OC0yLjI1UzkuMjYgNC42MSA4LjU1IDQuNzVaTTYuNTEgMTIuMmMyLjEyLjMxIDQuMzQtLjIgNS42OC0xLjk2LjMyLS40MS45Ni4xMS42Mi41MS0uNzYuOS0xLjc4IDEuNjMtMi45MyAxLjk1LTEuMTQuMzMtMi4zMy4zMS0zLjQ2LjE2YS4zNC4zNCAwIDAgMS0uMjktLjM4Yy4wMi0uMTguMTktLjMxLjM3LS4yOVpNNy45NyAxOS41OWMtLjk5Ljk2LTIuMzYuMDgtMi4zNi0xLjE1LS4xMi0uOS0uMjctMS43OS0uMzctMi42OS0uMDEtLjExLjA3LS4yMS4xOC0uMjIuMS0uMDEuMTkuMDYuMjEuMTUuMjIuODguMzggMS43Ny41NiAyLjY2LjAxLjc4LjY4IDEuMzggMS4zNS44My4yNy0uMjcuNjkuMTYuNDIuNDNaIi8+PHBhdGggZD0iTTkuNzUgMTkuMjdjLS40Mi45LTEuOC45Ni0yLjMyLjExLS41LTEuMTMtLjMxLTIuNS0uNDctMy43MiAwLS4xMS4wOC0uMi4xOS0uMjEuMSAwIC4xOS4wNy4yMS4xNy4xNy45NS4yOCAxLjkxLjQyIDIuODcuMDEuNDUuMjMuNzQuNTcuODUuMzMuMS43MS0uMDUuODgtLjM2LjE4LS4zNC43MS0uMDUuNTIuMjlaTTE0LjAzIDE1LjY2Yy0uMTYgMS4yMy4wMyAyLjU3LS40NiAzLjcyLS41Mi44Ni0xLjkxLjc5LTIuMzItLjExLS4xNy0uMzQuMzUtLjYxLjUzLS4yOC40Mi43MSAxLjQ4LjM4IDEuNDUtLjQ5LjE0LS45Ni4yNS0xLjkyLjQyLTIuODcuMDQtLjI0LjQxLS4yLjQuMDRaIi8+PHBhdGggZD0iTTExLjg1IDE1LjU0Yy4wMi43OS4wMSAxLjU4LjAxIDIuMzctLjAyLjQxLjA3LjktLjE0IDEuMjktLjQzIDEuMDItMi4wMSAxLjAyLTIuNDUgMC0uMjEtLjM5LS4xMy0uODktLjE0LTEuMjkgMC0uNzkgMC0xLjU4LjAxLTIuMzcgMC0uMTEuMS0uMi4yMS0uMTkuMSAwIC4xOC4wOC4xOS4xOC4wNy43OS4xIDEuNTguMTUgMi4zNy4wMy4yNyAwIC44Mi4xMyAxLjA0LjEzLjI2LjQuNDMuNjguNDIuNDYgMCAuNzktLjQuNzctLjg3bC4wMy0uNTljLjA0LS43OS4wOC0xLjU4LjE1LTIuMzcuMDItLjI0LjQtLjIzLjQuMDFaIi8+PC9zdmc+)}.scylla-icon--about-us-m{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNi4zOCAzMi40MyI+PHBhdGggZD0iTTYuNTUgMzEuNjRjLS4yLjEzLS40My4yMi0uNjkuMjZhMS44MSAxLjgxIDAgMCAxLTIuMDYtMS4zOVMuNDkgMTQuOTkuNDkgMTEuODJDLjUgNS4xOSA1Ljc3LjUgMTMuMTkuNXMxMi42OSA0LjY5IDEyLjY5IDExLjMyYzAgMy4xOC0zLjMxIDE4LjY5LTMuMzEgMTguNjlhMS44MSAxLjgxIDAgMCAxLTIuNjIgMS4yIiBzdHlsZT0iZmlsbDpub25lO3N0cm9rZTojMDAwO3N0cm9rZS1saW5lY2FwOnJvdW5kO3N0cm9rZS1saW5lam9pbjpyb3VuZCIvPjxwYXRoIGQ9Ik0yMS44NiAyNS4zNmMtLjI4IDEuOS0uMzcgMy44Ni0uOTEgNS43MS0uNjEgMS40MS0yLjY4IDEuNzUtMy42Ni41NS0uNDEtLjQ3LjMxLTEuMTEuNzMtLjY2LjcxLjc2IDIuMDQuMjkgMi4xNi0uNzMuMzItMS42Ni42NS0zLjMzIDEuMDQtNC45OC4wOS0uMzkuNy0uMjguNjUuMTFaIi8+PHBhdGggZD0iTTE0LjggMTAuNTdjMCAzLjEzLTIuNTMgNS42Ni01LjY2IDUuNjZzLTUuNDctMi41My01LjQ3LTUuNjYgMi4zNC01LjY2IDUuNDctNS42NiA1LjY2IDIuNTMgNS42NiA1LjY2WiIgc3R5bGU9InN0cm9rZS13aWR0aDouOXB4O2ZpbGw6bm9uZTtzdHJva2U6IzAwMDtzdHJva2UtbGluZWNhcDpyb3VuZDtzdHJva2UtbGluZWpvaW46cm91bmQiLz48cGF0aCBkPSJNMTAuMzEgNi44NmMtLjk4LjItMS4xNyAyLjM0LS41OSAyLjkzLjM4LjM4IDEuMTcuNTEgMS4xNy43OHMtLjc5LjQtMS4xNy43OGMtLjU5LjU5LS4zOSAyLjczLjU5IDIuOTMgMS4xNi4yMyAyLjkzLTEuMTcgMi45My0zLjcxcy0xLjc2LTMuOTQtMi45My0zLjcxWk02LjgyIDE4LjUxYzMuNDkuODkgNi45Ny0uNSA5LjUxLTIuOTMuNDctLjQ0IDEuMTYuMzEuNjguNzQtMS4zOCAxLjIzLTIuOTggMi4yOS00Ljc5IDIuODctMS44LjU5LTMuNzcuNTgtNS41OC4xNGEuNDIxLjQyMSAwIDAgMS0uMzEtLjVjLjA1LS4yMi4yOC0uMzYuNS0uMzFaIi8+PHBhdGggZD0iTTE2LjczIDE2LjY3Yy0uMTItLjQ2LS41MS0uODMtLjk5LS44My0uNzUtLjAyLS41OS0xLjE3LjE0LS45OS44MS4xNiAxLjQzLjg1IDEuNSAxLjY2LjA4LjQtLjU0LjU0LS42NS4xNVpNOS4wMyAzMS43Yy0xLjI2IDEuMzYtMy42Mi40NS0zLjgtMS4zNWwtLjA5LS41NWMtLjIxLTEuNDgtLjQ1LTIuOTUtLjYtNC40NC0uMDItLjE4LjExLS4zNC4yOS0uMzYuMTctLjAyLjMyLjA5LjM1LjI1LjM5IDEuNjMuNzEgMy4yOCAxLjAzIDQuOTMuMDkgMS4wMiAxLjM4IDEuNTQgMi4xMi44MS40NS0uNDQgMS4xNC4yNi42OS43WiIvPjxwYXRoIGQ9Ik0xMS45NiAzMS4xNmMtMSAxLjk4LTQuMDQgMS4zLTQuMjEtLjg4LS4xNS0xLjY5LS4zLTMuMzgtLjM5LTUuMDcgMC0uMTguMTMtLjM0LjMxLS4zNC4xNyAwIC4zMS4xMS4zNC4yNy4yOCAxLjY3LjUgMy4zNS43MiA1LjAzLjA5IDEuMiAxLjc3IDEuNTkgMi4zNi41MS4zMS0uNTYgMS4xNi0uMDkuODcuNDdaTTE5LjAzIDI1LjIxYy0uMDggMS42OS0uMjQgMy4zOC0uMzkgNS4wNy0uMDQuMzctLjE3Ljc1LS4zOCAxLjA2LS44NiAxLjQtMy4xMSAxLjMxLTMuODMtLjE3LS4zLS41Ni41NS0xLjAzLjg2LS40OC41OSAxLjA4IDIuMjcuNjkgMi4zNS0uNTIuMjItMS42OC40My0zLjM2LjcyLTUuMDMuMDYtLjQuNjgtLjMzLjY1LjA3WiIvPjxwYXRoIGQ9Ik0xNS40MyAyNS4wMmMuMDQgMS4zMS4wMiAyLjYxLjAyIDMuOTEtLjAzLjY3LjExIDEuNDgtLjIzIDIuMTMtLjc0IDEuNjktMy4yOSAxLjY5LTQuMDMgMC0uMzQtLjY1LS4yMS0xLjQ3LS4yNC0yLjEzIDAtMS4zLS4wMi0yLjYxLjAyLTMuOTEgMC0uMTguMTYtLjMyLjM0LS4zMi4xNyAwIC4zLjE0LjMyLjMuMTEgMS4zLjE3IDIuNi4yNCAzLjkxLjA1LjQ1IDAgMS4zNS4yMSAxLjcyLjIxLjQzLjY2LjcxIDEuMTIuNy40Ni4wMi45MS0uMjcgMS4xMi0uNjkuMjItLjM2LjE2LTEuMjguMjEtMS43Mi4wNy0xLjMuMTMtMi42MS4yNC0zLjkxLjAyLS40LjY2LS4zOC42Ni4wMloiLz48L3N2Zz4=)}.scylla-icon--alternator{background-image:url(data:image/svg+xml;base64,PHN2ZyBpZD0iTGF5ZXJfMyIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB2aWV3Qm94PSIwIDAgMjAgMjAiPjxkZWZzPjxzdHlsZT4uY2xzLTF7ZmlsbDpub25lO3N0cm9rZTojMDAwO3N0cm9rZS1saW5lY2FwOnJvdW5kO3N0cm9rZS1saW5lam9pbjpyb3VuZH08L3N0eWxlPjwvZGVmcz48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Ik0xNy41IDIuOTFjMCAxLjI4LTMuNjcgMi41OS04IDIuNTlzLTgtMS4zMS04LTIuNTlTNS4wOS41IDkuNDIuNXM4LjA4IDEuMTMgOC4wOCAyLjQxWk0xNy41IDcuNjZjMCAxLjI4LTMuNjMgMi44LTcuOTYgMi44UzEuNSA4LjkzIDEuNSA3LjY2TTE3LjUgMTIuNDdjMCAxLjI4LTMuNjcgMy4wMy04IDMuMDNzLTgtMS43NS04LTMuMDNNMTcuNSAxNy4yOWMwIDEuMjgtMy43NSAyLjMtOC4wOCAyLjNzLTcuOTItMS4wMy03LjkyLTIuM00xLjUgMTcuMTlWMi45MU0xNy41IDE3LjE5VjIuOTEiLz48L3N2Zz4=)}.scylla-icon--apps{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyMSAxOSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOm5vbmU7c3Ryb2tlOiM0ZDRkNGQ7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJDYWxxdWVfNCIgZGF0YS1uYW1lPSJDYWxxdWUgNCI+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNLjUgMS41aDIwdjE0SC41ek03LjUgMTUuNzR2Mi44OU0xMi44MyAxNS42M3YyLjMyTTUuNSAxOC41aDkuMTQiLz48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Im0zLjY0IDUuNTYgNC41OCAyLjkxLTQuNTggMi45Mk05LjEgMTIuMDhoNC4zMiIvPjwvZz48L3N2Zz4=)}.scylla-icon--architecture{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMSwuY2xzLTIsLmNscy01e2ZpbGw6bm9uZTtzdHJva2U6Z3JheX0uY2xzLTF7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfS5jbHMtMiwuY2xzLTV7c3Ryb2tlLW1pdGVybGltaXQ6MTB9LmNscy0ye3N0cm9rZS13aWR0aDouOThweH0uY2xzLTV7c3Ryb2tlLXdpZHRoOi45OXB4fTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJDYWxxdWVfMiIgZGF0YS1uYW1lPSJDYWxxdWUgMiI+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNMS45IDEwLjI3YTEwLjgzIDEwLjgzIDAgMCAxIDguNzMtOC4zOE0xMC41MSAyMy4wOEExMC43OSAxMC43OSAwIDAgMSAxLjc3IDE0TTIzLjIzIDE0YTEwLjgxIDEwLjgxIDAgMCAxLTkgOS4xMU0xNC4yNyAxLjg4YTEwLjgxIDEwLjgxIDAgMCAxIDguODMgOC4zNyIvPjxjaXJjbGUgY2xhc3M9ImNscy0yIiBjeD0iMTIuMjUiIGN5PSIxLjc1IiByPSIxLjc1Ii8+PGNpcmNsZSBjbGFzcz0iY2xzLTIiIGN4PSIxMi4yNSIgY3k9IjIyLjc1IiByPSIxLjc1Ii8+PGNpcmNsZSBjeD0iNC45MiIgY3k9IjQuNzUiIHI9IjEuNzUiIHN0eWxlPSJzdHJva2Utd2lkdGg6Ljk5cHg7ZmlsbDpncmF5O3N0cm9rZS1taXRlcmxpbWl0OjEwO3N0cm9rZTpncmF5Ii8+PGNpcmNsZSBjeD0iMjAuMDkiIGN5PSIxOS45MSIgcj0iMS43NSIgc3R5bGU9InN0cm9rZS13aWR0aDouOTlweDtmaWxsOmdyYXk7c3Ryb2tlLW1pdGVybGltaXQ6MTA7c3Ryb2tlOmdyYXkiLz48Y2lyY2xlIGNsYXNzPSJjbHMtNSIgY3g9IjEuNzUiIGN5PSIxMi4yNSIgcj0iMS43NSIvPjxjaXJjbGUgY2xhc3M9ImNscy01IiBjeD0iMjMuMjUiIGN5PSIxMi4yNSIgcj0iMS43NSIvPjxjaXJjbGUgY3g9IjQuNzUiIGN5PSIxOS42NCIgcj0iMS43NSIgc3R5bGU9InN0cm9rZS13aWR0aDouOTlweDtmaWxsOmdyYXk7c3Ryb2tlLW1pdGVybGltaXQ6MTA7c3Ryb2tlOmdyYXkiLz48Y2lyY2xlIGN4PSIxOS45MSIgY3k9IjQuNDgiIHI9IjEuNzUiIHN0eWxlPSJzdHJva2Utd2lkdGg6Ljk5cHg7ZmlsbDpncmF5O3N0cm9rZS1taXRlcmxpbWl0OjEwO3N0cm9rZTpncmF5Ii8+PC9nPjwvc3ZnPg==)}.scylla-icon--benchmarks{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVqb2luOnJvdW5kO3N0cm9rZS13aWR0aDozcHh9PC9zdHlsZT48L2RlZnM+PGcgaWQ9IkNhbHF1ZV8yIiBkYXRhLW5hbWU9IkNhbHF1ZSAyIj48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Ik01LjUxIDI0Ljkxdi01Ljg1TTEyLjU3IDI0Ljkxdi05Ljc0TTE5LjYyIDI0LjkxVjEwLjE1Ii8+PHBhdGggc3R5bGU9InN0cm9rZS1saW5lY2FwOnJvdW5kO2ZpbGw6bm9uZTtzdHJva2U6Z3JheTtzdHJva2UtbGluZWpvaW46cm91bmQiIGQ9Im0uOTEgMTQuOTggNS4xMy03Ljk0IDYuMjUgNS44OEwyNCAxIi8+PHBhdGggc3R5bGU9ImZpbGw6Z3JheSIgZD0ibTI1IDUtNS01aDV2NXoiLz48L2c+PC9zdmc+)}.scylla-icon--blog{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJDYWxxdWVfNCIgZGF0YS1uYW1lPSJDYWxxdWUgNCI+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJtOSAxNS0yLjUtMS41IDgtMTJMMTcgMyA5IDE1eiIvPjxwYXRoIHN0eWxlPSJmaWxsOmdyYXk7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kIiBkPSJtNi41IDEzLjUtLjUgM0w5IDE1bC0yLjUtMS41eiIvPjxwYXRoIGNsYXNzPSJjbHMtMSIgZD0iTTE5LjI1IDIuNWg0LjI1djE2aC0xM3Y0LjE3TDYuNDYgMTguNWwtNC45Ni0uMDRWMi41aDguMzFNMTQuNSAyLjVsMS42NyAxLjMzIi8+PC9nPjwvc3ZnPg==)}.scylla-icon--careers{background-image:url(data:image/svg+xml;base64,PHN2ZyBpZD0iQ2FscXVlXzEiIGRhdGEtbmFtZT0iQ2FscXVlIDEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmlld0JveD0iMCAwIDI1IDI1Ij48ZGVmcz48c3R5bGU+LmNscy0xe2ZpbGw6bm9uZTtzdHJva2U6Z3JheTtzdHJva2UtbGluZWNhcDpyb3VuZDtzdHJva2UtbGluZWpvaW46cm91bmR9PC9zdHlsZT48L2RlZnM+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNMS41IDExLjU1djhjMCAuNTYgMS4wNyAyIDIgMmgxOGMuODkgMCAyLTEuNDQgMi0ydi04Ii8+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNMjMuMzEgMy41SDEuODFjLS40OCAwLTEuMzEuNTUtMS4zMSAxdjZsMTAgMmE4LjQ1IDguNDUgMCAwIDAgNCAwbDEwLTJ2LTZjMC0uNDUtLjcyLTEtMS4xOS0xWk0xNS42MiAzLjV2LTFjMC0uNzYtLjYxLTEtMS4zOC0xaC0zLjQ1Yy0uNzYgMC0xLjM4LjI0LTEuMzggMXYxIi8+PHJlY3QgeD0iMTAiIHk9IjExIiB3aWR0aD0iNSIgaGVpZ2h0PSIzLjk5IiByeD0iLjU1IiByeT0iLjU1IiBzdHlsZT0iZmlsbDpncmF5Ii8+PC9zdmc+)}.scylla-icon--chevron-left{background-image:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTAiIGhlaWdodD0iMTYiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZD0iTTguMDkyIDE2IDEwIDE0LjExMyAzLjgxNyA4IDEwIDEuODg3IDguMDkyIDAgMCA4bDguMDkyIDhaIiBmaWxsPSIjMDAwIi8+PC9zdmc+)}.contents.local>ul>li a:before,.scylla-icon--chevron-right,.secondary-side-nav__content li a:before{background-image:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTAiIGhlaWdodD0iMTYiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZD0iTTEuOTA4IDAgMCAxLjg4NyA2LjE4MyA4IDAgMTQuMTEzIDEuOTA4IDE2IDEwIDggMS45MDggMFoiIGZpbGw9IiMwMDAiLz48L3N2Zz4=)}.scylla-icon--circe{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAzOCAzMCI+PGRlZnM+PHN0eWxlPi5jbHMtMiwuY2xzLTN7ZmlsbDpub25lO3N0cm9rZTojNGQ0ZDRkO3N0cm9rZS1saW5lY2FwOnJvdW5kO3N0cm9rZS1saW5lam9pbjpyb3VuZH0uY2xzLTN7c3Ryb2tlLXdpZHRoOjEuMTFweH08L3N0eWxlPjwvZGVmcz48ZyBpZD0iQ2FscXVlXzQiIGRhdGEtbmFtZT0iQ2FscXVlIDQiPjxwYXRoIGQ9Ik0yMi4xIDEyaC02LjE2YTEuMDYgMS4wNiAwIDAgMS0uOTQtMS4wNy45My45MyAwIDAgMSAuOTQtLjkzaDYuMTZhLjkzLjkzIDAgMCAxIC45NC45M0ExLjA2IDEuMDYgMCAwIDEgMjIuMSAxMloiIHN0eWxlPSJmaWxsOiM0ZDRkNGQiLz48cGF0aCBjbGFzcz0iY2xzLTIiIGQ9Ik0xMy40NCA0LjQ5SDkuNTF2MjRoMTl2LTI0SDI0LjUiLz48cGF0aCBjbGFzcz0iY2xzLTMiIGQ9Ik0xMyAzLjQ5SDguNWwtLjA4IDI2LjFIMjkuNVYzLjM5SDI1Ii8+PHBhdGggY2xhc3M9ImNscy0yIiBkPSJNMTIuNSAxOC4zOGgxM00xMi41IDE1LjQ5aDEzTTEyLjUgMjEuNDNoMTNNMTIuNSAyNC40N2gxM00xMy41IDIuNWgxMXYzLjk4aC0xMXoiLz48cGF0aCBjbGFzcz0iY2xzLTMiIGQ9Ik0yMS41LjVoLTUuMDR2MS45NWw1LjA0LjA1di0yeiIvPjwvZz48L3N2Zz4=)}.scylla-icon--clock{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyMSAxOSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOm5vbmU7c3Ryb2tlOiM0ZDRkNGQ7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJDYWxxdWVfNCIgZGF0YS1uYW1lPSJDYWxxdWUgNCI+PGNpcmNsZSBjbGFzcz0iY2xzLTEiIGN4PSIxMC41IiBjeT0iOS41IiByPSI5Ii8+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNMTAuNSAzLjV2NmwzLjA2IDMiLz48L2c+PC9zdmc+)}.scylla-icon--close{background-image:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMzQiIGhlaWdodD0iMzQiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGcgY2xpcC1wYXRoPSJ1cmwoI2EpIiBmaWxsPSIjZmZmIj48cGF0aCBkPSJNMTEuNjcgMjIuMTNhLjU2NC41NjQgMCAwIDEtLjM5OC0uOTYybDkuODk2LTkuODk2YS41NjMuNTYzIDAgMSAxIC43OTcuNzk3bC05Ljg5NiA5Ljg5NmEuNTU5LjU1OSAwIDAgMS0uMzk5LjE2NVoiLz48cGF0aCBkPSJNMjEuNTY2IDIyLjEzYS41NTkuNTU5IDAgMCAxLS4zOTgtLjE2NWwtOS44OTYtOS44OTZhLjU2My41NjMgMCAxIDEgLjc5Ny0uNzk3bDkuODk2IDkuODk1YS41NjQuNTY0IDAgMCAxLS4zOTkuOTYzWiIvPjxwYXRoIGQ9Ik0xNi42MTkgMzMuMjM3QzcuNDU1IDMzLjIzNyAwIDI1Ljc4MiAwIDE2LjYxOSAwIDcuNDU2IDcuNDU1IDAgMTYuNjE5IDBzMTYuNjE5IDcuNDU1IDE2LjYxOSAxNi42MTktNy40NTYgMTYuNjE4LTE2LjYyIDE2LjYxOFptMC0zMi4xMWMtOC41NDIgMC0xNS40OTIgNi45NS0xNS40OTIgMTUuNDkyIDAgOC41NDIgNi45NSAxNS40OTIgMTUuNDkyIDE1LjQ5MiA4LjU0MiAwIDE1LjQ5Mi02Ljk1IDE1LjQ5Mi0xNS40OTIgMC04LjU0Mi02Ljk1LTE1LjQ5Mi0xNS40OTItMTUuNDkyWiIvPjwvZz48ZGVmcz48Y2xpcFBhdGggaWQ9ImEiPjxwYXRoIGZpbGw9IiNmZmYiIGQ9Ik0wIDBoMzMuMjM3djMzLjIzN0gweiIvPjwvY2xpcFBhdGg+PC9kZWZzPjwvc3ZnPg==)}.scylla-icon--cloud{background-image:url(data:image/svg+xml;base64,PHN2ZyBpZD0iTGF5ZXJfMiIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB2aWV3Qm94PSIwIDAgNDMuMDQgMzIuMDMiPjxkZWZzPjxzdHlsZT4uY2xzLTF7ZmlsbDpub25lO3N0cm9rZTojMWQxZDFiO3N0cm9rZS1saW5lY2FwOnJvdW5kO3N0cm9rZS1saW5lam9pbjpyb3VuZH08L3N0eWxlPjwvZGVmcz48ZyBpZD0iTGF5ZXJfMyI+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNNDIuNTQgNC4wNmMwIDEuNjgtMy42MyAyLjQ0LTkgMi40NHMtMTAtLjczLTEwLTIuNFMyNy42Ny41IDMzLjA0LjVzOS41IDEuODkgOS41IDMuNTZaTTQyLjU0IDkuNjNjMCAxLjY4LTMuNzYgMi45MS05LjEyIDIuOTFzLTkuODQtMS4yMy05Ljg0LTIuOTFNNDIuNTQgMTUuMzRjMCAxLjY4LTMuNjggMy4yNS05LjA0IDMuMjUtNCAwLTcuNi0uOTYtOS4wOS0yLjA0TTQyLjU0IDIwLjY1YzAgMS42OC0zLjcyIDIuOTctOS4wOCAyLjk3TTIzLjU0IDE1LjQ2VjQuMU00Mi41NCAyMC43N1Y0LjEiLz48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Ik0yOC4xMSAyMS4wOGMtLjg3IDAtMS42Ny4yMy0yLjM5LjYxIDAtLjA3LjAxLS4xNC4wMS0uMjEgMC00Ljg1LTMuODMtOC45LTguNjgtOC45cy04Ljg4IDQuMDUtOC44OCA4LjljMCAuMTcuMDIuMzQuMDMuNTEtLjg0LS41Ny0xLjg1LS45MS0yLjk1LS45MS0yLjg4IDAtNC43NCAyLjU3LTQuNzQgNS40NnMxLjg2IDQuOTkgNC43NCA0Ljk5aDIyLjg2YzIuODggMCA1LjUyLTIuMjcgNS41Mi01LjE2cy0yLjYzLTUuMjktNS41Mi01LjI5WiIvPjwvZz48L3N2Zz4=)}.scylla-icon--cloud-docs{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyMSAxOSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOm5vbmU7c3Ryb2tlOiM0ZDRkNGQ7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJDYWxxdWVfNCIgZGF0YS1uYW1lPSJDYWxxdWUgNCI+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNNi41IDExLjVoOHYxaC04ek0xNS42NSA2LjU1YTMuNDIgMy40MiAwIDAgMC0zLjE1IDIiLz48cGF0aCBkPSJNMTAuMDYgMi44QTUuMTcgNS4xNyAwIDAgMSAxNSA2LjM1aC4yNGE0Ljg0IDQuODQgMCAwIDEgMCA5LjY3aC0xMWEzLjQ1IDMuNDUgMCAwIDEgMC02LjlBMy4xNyAzLjE3IDAgMCAxIDUgOS4yIDUuMzMgNS4zMyAwIDAgMSA0Ljg2IDhhNS4yIDUuMiAwIDAgMSA1LjItNS4ybTAtLjhhNiA2IDAgMCAwLTYgNnYuMzFhNC4yNSA0LjI1IDAgMCAwIC4xOCA4LjQ5aDExYTUuNjMgNS42MyAwIDAgMCAuMy0xMS4yNkE2IDYgMCAwIDAgMTAuMDYgMloiIHN0eWxlPSJmaWxsOiM0ZDRkNGQiLz48L2c+PC9zdmc+)}.scylla-icon--comparison{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMSwuY2xzLTIsLmNscy00e2ZpbGw6bm9uZTtzdHJva2U6Z3JheX0uY2xzLTEsLmNscy0ye3N0cm9rZS1taXRlcmxpbWl0OjEwfS5jbHMtMiwuY2xzLTR7c3Ryb2tlLWxpbmVjYXA6cm91bmR9LmNscy00e3N0cm9rZS1saW5lam9pbjpyb3VuZH08L3N0eWxlPjwvZGVmcz48ZyBpZD0iQ2FscXVlXzQiIGRhdGEtbmFtZT0iQ2FscXVlIDQiPjxwYXRoIGNsYXNzPSJjbHMtMSIgZD0iTTQuNSAxMy42M3YyLjg4aDYuMDZNMjAuNSAxMy41NHYyLjk2bC01LjUuMDEiLz48cGF0aCBjbGFzcz0iY2xzLTIiIGQ9Ik0xMi41IDE4LjV2Mi43Mk03LjUgMjEuNWgxMCIvPjxjaXJjbGUgY3g9IjEyLjUiIGN5PSIxNi41IiByPSIyIiBzdHlsZT0iZmlsbDpncmF5O3N0cm9rZS13aWR0aDouOTVweDtzdHJva2UtbWl0ZXJsaW1pdDoxMDtzdHJva2U6Z3JheSIvPjxwYXRoIGNsYXNzPSJjbHMtNCIgZD0iTTUuMDYgMTMuNThIMy44OEEzLjEgMy4xIDAgMCAxIC41IDEwLjVoOGEzLjE2IDMuMTYgMCAwIDEtMy40NCAzLjA4Wk0yMSAxMy41OGgtMS4xN2EzLjA5IDMuMDkgMCAwIDEtMy4zNy0zLjA3aDhBMy4xNiAzLjE2IDAgMCAxIDIxIDEzLjU4Wk03LjQ2IDUuMTJjMCAuNTctMS4xLjQ2LTIuNzkuNDZTMS41OCA1LjYgMS41OCA1IDMgNC40IDQuNjkgNC40czIuNzcuMTYgMi43Ny43MlpNMS41IDkuODVWNS4zMU03LjUgMTAuMzVWNS44MU0yMy41IDUuMTJjMCAuNTctMS4xLjQ2LTIuNzkuNDZzLTMuMDkgMC0zLjA5LS41NFMxOSA0LjQgMjAuNzMgNC40czIuNzcuMTYgMi43Ny43MlpNMTcuNTQgOS44NVY1LjMxTTIzLjU0IDEwLjM1VjUuODEiLz48L2c+PC9zdmc+)}.scylla-icon--contact-us{background-image:url(data:image/svg+xml;base64,PHN2ZyBpZD0iQ2FscXVlXzEiIGRhdGEtbmFtZT0iQ2FscXVlIDEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmlld0JveD0iMCAwIDI1IDI1Ij48ZGVmcz48c3R5bGU+LmNscy0xe2ZpbGw6bm9uZTtzdHJva2U6Z3JheTtzdHJva2UtbGluZWNhcDpyb3VuZDtzdHJva2UtbGluZWpvaW46cm91bmQ7c3Ryb2tlLXdpZHRoOjEuMDZweH08L3N0eWxlPjwvZGVmcz48cGF0aCBjbGFzcz0iY2xzLTEiIHRyYW5zZm9ybT0icm90YXRlKC0yNy40OSAxNS41NTIgMTEuMDgzKSIgZD0iTTcuNzYgNi4wMWgxNS41OXYxMC4xM0g3Ljc2eiIvPjxwYXRoIGNsYXNzPSJjbHMtMSIgZD0ibTYuMyAxMC4xOCA4LjYzIDEuNTZhMS40MiAxLjQyIDAgMCAwIDEuNTMtLjc0bDMuNjctOE0xMS4wMiAxOS4wM2wxLjc0LTVNMjQuNTkgMTEuOTdsLTUuMDktMS40NU03LjA5IDE3LjU4IDMuOSAxOS4zNE02LjA2IDE1LjQxLjU0IDE4LjM2Ii8+PC9zdmc+)}.scylla-icon--developers-blog{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOmdyYXl9PC9zdHlsZT48L2RlZnM+PGcgaWQ9IkNhbHF1ZV80IiBkYXRhLW5hbWU9IkNhbHF1ZSA0Ij48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Im02LjQ4IDEwLjU5LS41LjE3LjUuMTZMMTEgMTIuMTZWMTRsLTctMi40OVYxMGw3LTIuNXYxLjgzWk0xNCA5LjMyVjcuNWw3IDIuNXYxLjU0TDE0IDE0di0xLjgzbDQuMTQtMS4zLjQ0LS4xMy0uNDMtLjE0WiIvPjxwYXRoIHN0eWxlPSJmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kO3N0cm9rZS13aWR0aDouOThweCIgZD0iTTEuNSAyLjVoMjJ2MTZoLTEzdjQuMTdMNi40NiAxOC41bC00Ljk2LS4wNFYyLjV6Ii8+PC9nPjwvc3ZnPg==)}.scylla-icon--docs{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfS5jbHMtMntmaWxsOmdyYXl9PC9zdHlsZT48L2RlZnM+PGcgaWQ9IkNhbHF1ZV80IiBkYXRhLW5hbWU9IkNhbHF1ZSA0Ij48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Ik0zLjUgMi41MWgxNi45NHYyMC45MUgzLjV6Ii8+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJtMjIuNDUgMjEuNS4wNS0yMWgtMTdhMi4xNiAyLjE2IDAgMCAwLTIgMiIvPjxwYXRoIGNsYXNzPSJjbHMtMiIgZD0iTTYgNmg3djJINnpNNiA5aDExdjJINnoiLz48L2c+PC9zdmc+)}.scylla-icon--enterprise{background-image:url(data:image/svg+xml;base64,PHN2ZyBpZD0iTGF5ZXJfMyIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB2aWV3Qm94PSIwIDAgMjAgMjAiPjxkZWZzPjxzdHlsZT4uY2xzLTEsLmNscy0ye2ZpbGw6bm9uZTtzdHJva2U6IzAwMDtzdHJva2UtbGluZWNhcDpyb3VuZDtzdHJva2UtbGluZWpvaW46cm91bmR9LmNscy0ye3N0cm9rZS13aWR0aDoxLjA3cHh9PC9zdHlsZT48L2RlZnM+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJtMTMuNjIgNy41IDEuODgtMS4wOCAyIDIuMDh2N2gxTTE1LjUgMTUuNXYtNSIvPjxwYXRoIGNsYXNzPSJjbHMtMiIgZD0iTTUuNSAxNS41di0xMmw0LTIgNCAydjEyTTkuNSAxNS41VjEuNk03LjUgNS41djEwTTExLjUgNS41djEwIi8+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNNS41IDguNTQgMy40NiA3LjVsLTEuOTYuOTZ2Ny4wNGgtMU0zLjUgMTAuNXY1TS41IDE3LjVoMTgiLz48L3N2Zz4=)}.scylla-icon--enterprise-m{background-image:url(data:image/svg+xml;base64,PHN2ZyB2ZXJzaW9uPSIxLjEiIGlkPSJMYXllcl8yXzAwMDAwMDE2NzY4MDY2MDE5MjYzMjMyNzcwMDAwMDA1NDc1ODA5NTExODI4NjY2MDM2XyIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4PSIwIiB5PSIwIiB2aWV3Qm94PSIwIDAgNDMgMzEiIHN0eWxlPSJlbmFibGUtYmFja2dyb3VuZDpuZXcgMCAwIDQzIDMxIiB4bWw6c3BhY2U9InByZXNlcnZlIj48c3R5bGU+LnN0MHtmaWxsOm5vbmU7c3Ryb2tlOiMxZDFkMWI7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfTwvc3R5bGU+PGcgaWQ9IkxheWVyXzMiPjxwYXRoIGNsYXNzPSJzdDAiIGQ9Im0yOS42IDkuNSA0LTIgNi45IDQuMXYxNS45aDJNMzMuNiAyNy41VjcuNk0xNC42IDI3LjVWNC44TDIyLjUuNSAyOS42IDV2MjIuNU0yMi41IDI3LjVWMU0yNC41IDUuNmwzIDJNMjQuNSA5LjZsMyAyTTI0LjUgMTMuNmwzIDJNMjQuNSAxNy41bDMgMk0yNC41IDIxLjVsMyAyTTM1LjQgMTEuNmwzIDJNMzUuNCAxNS42bDMgMS45TTM1LjQgMTkuNWwzIDJNMzUuNCAyMy41bDMgMS45TTE4LjUgNS44djIxLjdNMTQuNiA5LjdsLTQuMS0yLjUtOCA0LjR2MTUuOWgtMk0xMC41IDI3LjVWNy4yTTEyLjUgMTEuNmwyIDFNMTIuNSAxNS42bDIgLjlNMTIuNSAxOS41bDIgMU0xMi41IDIzLjVsMi4xIDFNNi40IDEyLjR2MTUuMU0uNSAzMC41aDQyIi8+PC9nPjwvc3ZnPg==)}.scylla-icon--events{background-image:url(data:image/svg+xml;base64,PHN2ZyBpZD0iQ2FscXVlXzEiIGRhdGEtbmFtZT0iQ2FscXVlIDEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmlld0JveD0iMCAwIDI1IDI1Ij48ZGVmcz48c3R5bGU+LmNscy0xe2ZpbGw6bm9uZTtzdHJva2U6Z3JheTtzdHJva2UtbGluZWNhcDpyb3VuZDtzdHJva2UtbGluZWpvaW46cm91bmR9LmNscy0ye2ZpbGw6Z3JheX08L3N0eWxlPjwvZGVmcz48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Ik0yMi41IDIzLjVoLTIxdi0yMGgyMnYxNS4yMSIvPjxwYXRoIGNsYXNzPSJjbHMtMSIgZD0iTTQuNDIgMy41YzAtMS4zNiAxLjA5LTIgMi40NS0yYTIuNDYgMi40NiAwIDEgMSAwIDQuOTEgMi42MSAyLjYxIDAgMCAxLTEtLjIxTTEwLjY3IDMuNWMwLTEuMzYgMS4xLTIgMi40Ni0yYTIuNDYgMi40NiAwIDAgMSAwIDQuOTEgMi42MSAyLjYxIDAgMCAxLTEtLjIxTTE2LjkzIDMuNWMwLTEuMzYgMS4xLTIgMi40NS0yYTIuNDYgMi40NiAwIDEgMSAwIDQuOTEgMi41MiAyLjUyIDAgMCAxLTEtLjIxIi8+PHBhdGggY2xhc3M9ImNscy0yIiBkPSJNNyA5aDN2M0g3ek0xMiA5aDN2M2gtM3pNMTcgOWgzdjNoLTN6TTcgMTRoM3YzSDd6TTEyIDE0aDN2M2gtM3pNMTcgMTRoM3YzaC0zeiIvPjxwYXRoIGNsYXNzPSJjbHMtMSIgZD0iTTMuNSAzLjY3djE2LjY2TTMuNSAyMC40M2MwIDEuMjkuNDQgMi4zMyAxLjczIDIuMzNzMi4zMy0xLjkgMi4zMy0zLjE5bDE2Ljk0LS4wN2MwIDEuMjktLjU1IDMuMTItMS44MyAzLjEySDYuMyIvPjwvc3ZnPg==)}.admonition.note .admonition-title:before,.admonition.tip .admonition-title:before,.scylla-icon--exclamation{background-image:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PG1hc2sgaWQ9ImEiIG1hc2stdHlwZT0iYWxwaGEiIG1hc2tVbml0cz0idXNlclNwYWNlT25Vc2UiIHg9IjEiIHk9IjEiIHdpZHRoPSIyMiIgaGVpZ2h0PSIyMiI+PHBhdGggZD0iTTEyIDIzQzUuOSAyMyAxIDE4LjEgMSAxMlM1LjkgMSAxMiAxczExIDQuOSAxMSAxMS00LjkgMTEtMTEgMTFabTAtMjBjLTUgMC05IDQtOSA5czQgOSA5IDkgOS00IDktOS00LTktOS05WiIgZmlsbD0iI2ZmZiIvPjxwYXRoIGQ9Ik0xMiAxM2MtLjYgMC0xLS40LTEtMVY4YzAtLjYuNC0xIDEtMXMxIC40IDEgMXY0YzAgLjYtLjQgMS0xIDFaTTEyIDE3Yy0uMyAwLS41LS4xLS43LS4zLS4yLS4yLS4zLS40LS4zLS43IDAtLjEgMC0uMy4xLS40LjEtLjEuMS0uMi4yLS4zLjMtLjMuNy0uNCAxLjEtLjIuMSAwIC4xIDAgLjIuMSAwIDAgLjEuMS4yLjEuMS4xLjIuMi4yLjN2LjRjMCAuMSAwIC4zLS4xLjQtLjEuMS0uMS4yLS4yLjMtLjIuMi0uNC4zLS43LjNaIiBmaWxsPSIjZmZmIi8+PC9tYXNrPjxnIG1hc2s9InVybCgjYSkiPjxwYXRoIGZpbGw9IiNmZmYiIGQ9Ik0wIDBoMjR2MjRIMHoiLz48L2c+PC9zdmc+)}.collapsible-button i,.scylla-icon--expand{background-image:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYuMDAxIiBoZWlnaHQ9IjE2IiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjxwYXRoIGQ9Ik01IDEzYTEgMSAwIDAgMS0uNzEtLjI5bC00LTRhMSAxIDAgMCAxIDAtMS40MWw0LTRhMSAxIDAgMCAxIDEuNDIgMS40MUwyLjQxIDhsMy4yOSAzLjI5QTEgMSAwIDAgMSA1IDEzeiIvPjxwYXRoIGQ9Ik0xMSA5SDFhMSAxIDAgMCAxIDAtMmgxMGExIDEgMCAwIDEgMCAyek0xNSAxNmExIDEgMCAwIDEtMS0xVjFhMSAxIDAgMCAxIDIgMHYxNGExIDEgMCAwIDEtMSAxeiIvPjwvc3ZnPg==)}.scylla-icon--forum{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSJjdXJyZW50Q29sb3IiIHN0cm9rZS13aWR0aD0iMS41IiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiIGNsYXNzPSJmZWF0aGVyIGZlYXRoZXItdXNlcnMiPjxwYXRoIGQ9Ik0xNyAyMXYtMmE0IDQgMCAwIDAtNC00SDVhNCA0IDAgMCAwLTQgNHYyIi8+PGNpcmNsZSBjeD0iOSIgY3k9IjciIHI9IjQiLz48cGF0aCBkPSJNMjMgMjF2LTJhNCA0IDAgMCAwLTMtMy44N00xNiAzLjEzYTQgNCAwIDAgMSAwIDcuNzUiLz48L3N2Zz4=)}.scylla-icon--home{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyMSAxOSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOm5vbmU7c3Ryb2tlOiM0ZDRkNGQ7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJMYXllcl81IiBkYXRhLW5hbWU9IkxheWVyIDUiPjxwYXRoIGNsYXNzPSJjbHMtMSIgZD0iTTMuNSA2LjE0djExYTEuMzggMS4zOCAwIDAgMCAxLjM3IDEuMzZoMTEuMjZhMS4zOCAxLjM4IDAgMCAwIDEuMzctMS4zN3YtMTEiLz48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Im0xOS41IDcuNS04LTYuMjVhMS41OSAxLjU5IDAgMCAwLTEuOTQgMEwxLjUgNy41TTEyLjczIDE4LjAydi03LjIxSDguMjd2Ny4yMSIvPjwvZz48L3N2Zz4=)}.scylla-icon--getting-started{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyMSAxOSI+PGcgZGF0YS1uYW1lPSJDYWxxdWUgNCI+PHBhdGggc3R5bGU9ImZpbGw6IzRkNGQ0ZCIgZD0ibTcgNC41IDguNTEgNS4wNUw3IDE0LjV2LTEweiIvPjxyZWN0IHg9IjEuNSIgeT0iLjUiIHdpZHRoPSIxOCIgaGVpZ2h0PSIxOCIgcng9IjIuNDMiIHN0eWxlPSJmaWxsOm5vbmU7c3Ryb2tlOiM0ZDRkNGQ7c3Ryb2tlLW1pdGVybGltaXQ6MTAiLz48L2c+PC9zdmc+)}.scylla-icon--glossary{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyMSAxOSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOm5vbmU7c3Ryb2tlOiM0ZDRkNGQ7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJDYWxxdWVfNCIgZGF0YS1uYW1lPSJDYWxxdWUgNCI+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNMi41IDIuNWgxM3YxNmgtMTN6Ii8+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNMTUuNTggMTcuMjFoMS45MlYuNWgtMTNhMi4zNCAyLjM0IDAgMCAwLTIgMiIvPjxwYXRoIGQ9Ik00LjggMTMuOTNhMSAxIDAgMCAwIC43NS0uNDMgNiA2IDAgMCAwIC41Mi0xLjA4bDIuODctNy4wN2guMzZsMi44OCA2Ljc5YTguOTIgOC45MiAwIDAgMCAuNzIgMS40Ny43Ni43NiAwIDAgMCAuNjguMzJ2LjMySDkuNHYtLjMyYTMuMjQgMy4yNCAwIDAgMCAuODMtLjExYy4xMy0uMDYuMi0uMTkuMi0uNDJhMS41OSAxLjU5IDAgMCAwLS4xLS40NmMwLS4xMi0uMS0uMjctLjE3LS40NGwtLjMzLS43OGgtMi45Yy0uMTkuNTEtLjMxLjg1LS4zNiAxYTIuMzggMi4zOCAwIDAgMC0uMTcuNzNjMCAuMTguMTIuMzIuMzcuNGEyLjU2IDIuNTYgMCAwIDAgLjY2LjA4di4zMkg0LjhabTQuODQtMi43Mi0xLjI0LTNoLS4xMWwtMS4xNiAzWiIgc3R5bGU9ImZpbGw6IzRkNGQ0ZCIvPjwvZz48L3N2Zz4=)}.scylla-icon--infoworld{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLW1pdGVybGltaXQ6MTB9PC9zdHlsZT48L2RlZnM+PGcgaWQ9IkNhbHF1ZV80IiBkYXRhLW5hbWU9IkNhbHF1ZSA0Ij48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Ik0xMiAyLjVINi41VjZjMCAzIC41NSA3LjE3IDUgOS41djQiLz48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Ik02LjQgNC40NGgtNFMyLjU2IDExIDguNSAxM00xOC41IDQuNWw0LS4wNnMtLjA2IDYuNTYtNiA4LjU2Ii8+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNMTIgMi41aDYuNVY2YzAgMi45NC0uNCA3LjA4LTUgOS41djRNOS41IDE5LjVoNnYyaC02eiIvPjxwYXRoIHN0eWxlPSJmaWxsOmdyYXk7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLW1pdGVybGltaXQ6MTAiIGQ9Ik03LjUgMjEuNWgxMHYxaC0xMHoiLz48L2c+PC9zdmc+)}.scylla-icon--integrations{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOm5vbmU7c3Ryb2tlOiM0ZDRkNGQ7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJDYWxxdWVfNCIgZGF0YS1uYW1lPSJDYWxxdWUgNCI+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJtMTQuNTYgMTIuNy0xLjI1LTEuNTctMS4zMS43NmE2IDYgMCAwIDAtMS42NS0xbC4wOC0xLjQ5LTItLjQtLjUzIDEuNDRhNS43MyA1LjczIDAgMCAwLTEuODcuMzFsLS44OC0xLjE5LTEuNzcgMUwzLjkyIDEyYTYuMyA2LjMgMCAwIDAtMS4yMiAxLjQxbC0xLjUtLjM1LS43NCAxLjg3IDEuMzguOGE2LjIzIDYuMjMgMCAwIDAgMCAxLjgzbC0xLjQxLjcyLjY0IDEuOTEgMS41OS0uMjhhNy42MyA3LjYzIDAgMCAwIC40OC42OCA1Ljg2IDUuODYgMCAwIDAgLjY3LjczbC0uNjIgMS40NiAxLjcyIDEgMS0xLjI0YTYuNDYgNi40NiAwIDAgMCAxLjc5LjM1bC40NiAxLjUyIDItLjN2LTEuNmE2LjQzIDYuNDMgMCAwIDAgMS42Mi0uODlsMS4zLjg1TDE0LjQzIDIxbC0xLTEuMmE2LjI0IDYuMjQgMCAwIDAgLjY4LTEuNzVsMS41MS0uMTkuMDUtMi0xLjUxLS4yNmE2LjA3IDYuMDcgMCAwIDAtLjYyLTEuODFabS01LjM1IDUuNTFhMS45MyAxLjkzIDAgMSAxIC4zMS0yLjcxIDEuOTIgMS45MiAwIDAgMS0uMzEgMi43MVoiLz48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Im0yNC4zMSA4LjA1LS4xMy0xLjY1LTEuMjUtLjA5YTUuMjYgNS4yNiAwIDAgMC0uNjctMS40NGwuNzUtMS0xLjE2LTEuMTctMSAuNzRhNS4xOCA1LjE4IDAgMCAwLTEuNDMtLjY2bC0uMDYtMS4yNC0xLjY1LS4xNy0uMzIgMS4yNWE1Ljc3IDUuNzcgMCAwIDAtMS41Mi4zOEwxNSAyLjFsLTEuMzcuOS41OCAxLjE4YTQuODggNC44OCAwIDAgMC0uODYgMS4yNWwtMS4zLS4xNi0uNDUgMS42IDEuMjIuNTVhNS4xNyA1LjE3IDAgMCAwIDAgLjY4QTQuMjggNC4yOCAwIDAgMCAxMyA5bC0xLjExLjcyLjY5IDEuNTEgMS4yOC0uMzdhNC45NCA0Ljk0IDAgMCAwIDEuMDcgMS4wN2wtLjM5IDEuMjYgMS41LjcxLjc0LTEuMDlhNS4wNyA1LjA3IDAgMCAwIDEuNTIuMTRsLjUgMS4xOSAxLjYxLS40MS0uMTMtMS4yOWE1LjE0IDUuMTQgMCAwIDAgMS4yNy0uODhsMS4xMi41NyAxLTEuMzUtLjkxLS44OGE0LjkgNC45IDAgMCAwIC40Mi0xLjUyWm0tNi4yIDEuNDNhMS43NCAxLjc0IDAgMSAxIDEuNi0xLjg2IDEuNzQgMS43NCAwIDAgMS0xLjYgMS44NloiLz48L2c+PC9zdmc+)}.scylla-icon--knowledge-base{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyMSAxOSI+PGRlZnM+PHN0eWxlPi5jbHMtMSwuY2xzLTJ7ZmlsbDpub25lO3N0cm9rZTojNGQ0ZDRkfS5jbHMtMXtzdHJva2UtbGluZWNhcDpyb3VuZDtzdHJva2UtbGluZWpvaW46cm91bmR9LmNscy0ye3N0cm9rZS1taXRlcmxpbWl0OjEwfTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJMYXllcl81IiBkYXRhLW5hbWU9IkxheWVyIDUiPjxwYXRoIGNsYXNzPSJjbHMtMSIgZD0iTTE2LjIxIDYuMzhhNS4zNiA1LjM2IDAgMCAxLTEuNTEgMy43MyA1IDUgMCAwIDAtMS40NSAzLjMxSDguNDdhNS40MSA1LjQxIDAgMCAwLTEuMjgtMy4xMSA1LjM3IDUuMzcgMCAxIDEgOS0zLjkzWk0xMy4yMyAxNS42N0g4LjQ1Ii8+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNMTMuMjQgMTMuNGgtNC44djQuMTZhLjcuNyAwIDAgMCAuNzEuN2gzLjM4YS43LjcgMCAwIDAgLjcxLS43WiIvPjxwYXRoIGNsYXNzPSJjbHMtMiIgZD0iTTEwLjg0IDguMjFhMS42NSAxLjY1IDAgMSAxIDEuNjQtMS42NSAxLjY1IDEuNjUgMCAwIDEtMS42NCAxLjY1Wk0xMC44NCA4LjY3djQuNjQiLz48L2c+PC9zdmc+)}.scylla-icon--less{background-image:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTciIGhlaWdodD0iMTciIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHJlY3Qgd2lkdGg9IjE3IiBoZWlnaHQ9IjE3IiByeD0iMSIgZmlsbD0iI0IzQkFDNSIvPjxwYXRoIGQ9Ik0xMyA4LjVhMSAxIDAgMCAxLTEgMUg1YTEgMSAwIDAgMSAwLTJoN2ExIDEgMCAwIDEgMSAxWiIgZmlsbD0iI2ZmZiIvPjxwYXRoIGQ9Ik0xMyA4LjVhMSAxIDAgMCAxLTEgMUg1YTEgMSAwIDAgMSAwLTJoN2ExIDEgMCAwIDEgMSAxWiIgZmlsbD0iI2ZmZiIvPjxwYXRoIGQ9Ik0xMyA4LjVhMSAxIDAgMCAxLTEgMUg1YTEgMSAwIDAgMSAwLTJoN2ExIDEgMCAwIDEgMSAxWiIgZmlsbD0iI2ZmZiIvPjxwYXRoIGQ9Ik0xMyA4LjVhMSAxIDAgMCAxLTEgMUg1YTEgMSAwIDAgMSAwLTJoN2ExIDEgMCAwIDEgMSAxWiIgZmlsbD0iI2ZmZiIvPjxwYXRoIGQ9Ik0xMyA4LjVhMSAxIDAgMCAxLTEgMUg1YTEgMSAwIDAgMSAwLTJoN2ExIDEgMCAwIDEgMSAxWiIgZmlsbD0iI2ZmZiIvPjwvc3ZnPg==);filter:none}.scylla-icon--live-test{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtNntmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLW1pdGVybGltaXQ6MTA7c3Ryb2tlLWxpbmVjYXA6cm91bmR9PC9zdHlsZT48L2RlZnM+PGcgaWQ9IkNhbHF1ZV80IiBkYXRhLW5hbWU9IkNhbHF1ZSA0Ij48Y2lyY2xlIGN4PSIxMi41IiBjeT0iMTUiIHI9IjkuNSIgc3R5bGU9InN0cm9rZS13aWR0aDoxLjVweDtzdHJva2UtbWl0ZXJsaW1pdDoxMDtmaWxsOm5vbmU7c3Ryb2tlOmdyYXkiLz48cGF0aCBzdHlsZT0ic3Ryb2tlLXdpZHRoOjEuMXB4O3N0cm9rZS1saW5lam9pbjpyb3VuZDtzdHJva2UtbGluZWNhcDpyb3VuZDtmaWxsOm5vbmU7c3Ryb2tlOmdyYXkiIGQ9Ik0xMCAuNWg1djJoLTV6Ii8+PHBhdGggc3R5bGU9InN0cm9rZS13aWR0aDoxLjExcHg7c3Ryb2tlLWxpbmVqb2luOnJvdW5kO3N0cm9rZS1saW5lY2FwOnJvdW5kO2ZpbGw6bm9uZTtzdHJva2U6Z3JheSIgZD0iTTUuOCA4LjIgNC4xMyA2LjUzbDEuOC0xLjgxTDcuNiA2LjQiLz48cGF0aCBzdHlsZT0ic3Ryb2tlLXdpZHRoOjEuMTNweDtzdHJva2UtbWl0ZXJsaW1pdDoxMDtmaWxsOm5vbmU7c3Ryb2tlOmdyYXkiIGQ9Ik0xMiA2VjIuNSIvPjxwYXRoIHN0eWxlPSJzdHJva2Utd2lkdGg6MS4wOHB4O3N0cm9rZS1taXRlcmxpbWl0OjEwO2ZpbGw6bm9uZTtzdHJva2U6Z3JheSIgZD0iTTEzIDZWMi41Ii8+PHBhdGggY2xhc3M9ImNscy02IiBkPSJNMTIuNSA4LjA2VjEwTTEyLjUgMjAuMDR2MS44OE03LjEzIDEwLjA4bDEuNzkgMS44OE0xNi4wNCAxNy4wOGwyIDEuODhNNyAxOC45MmwxLjg4LTEuODhNMTYuMTMgMTEuOTZsMS43OS0xLjgzIi8+PGVsbGlwc2UgY3g9IjEyLjUiIGN5PSIxNC4zNiIgcng9IjEuNSIgcnk9IjEuMzYiIHN0eWxlPSJmaWxsOmdyYXkiLz48cGF0aCBjbGFzcz0iY2xzLTYiIGQ9Im0xMi42MyAxNC41NCAyLjUgNi4zOCIvPjwvZz48L3N2Zz4=)}.scylla-icon--mail-list{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSJjdXJyZW50Q29sb3IiIHN0cm9rZS13aWR0aD0iMS41IiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiIGNsYXNzPSJmZWF0aGVyIGZlYXRoZXItbWFpbCI+PHBhdGggZD0iTTQgNGgxNmMxLjEgMCAyIC45IDIgMnYxMmMwIDEuMS0uOSAyLTIgMkg0Yy0xLjEgMC0yLS45LTItMlY2YzAtMS4xLjktMiAyLTJ6Ii8+PHBhdGggZD0ibTIyIDYtMTAgN0wyIDYiLz48L3N2Zz4=)}.scylla-icon--manager{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtM3tmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kO3N0cm9rZS13aWR0aDouOTdweH0uY2xzLTR7ZmlsbDpncmF5fTwvc3R5bGU+PC9kZWZzPjxwYXRoIHN0eWxlPSJmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kIiBkPSJNMTggMmg1djIySDNWMmg0LjkyIiBpZD0iQ2FscXVlXzIiIGRhdGEtbmFtZT0iQ2FscXVlIDIiLz48ZyBpZD0iQ2FscXVlXzQiIGRhdGEtbmFtZT0iQ2FscXVlIDQiPjxwYXRoIHN0eWxlPSJzdHJva2Utd2lkdGg6MS4wN3B4O2ZpbGw6bm9uZTtzdHJva2U6Z3JheTtzdHJva2UtbGluZWNhcDpyb3VuZDtzdHJva2UtbGluZWpvaW46cm91bmQiIGQ9Ik04IDBoMTB2NEg4eiIvPjxwYXRoIGNsYXNzPSJjbHMtMyIgZD0iTTcgOWgzdjNIN3pNNyAxNmgzdjNIN3oiLz48cGF0aCBjbGFzcz0iY2xzLTQiIGQ9Ik0xMi41IDkuNWg3djJoLTd6TTEyLjUgMTYuNWg3djJoLTd6Ii8+PC9nPjwvc3ZnPg==)}.scylla-icon--memory-management{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMSwuY2xzLTJ7ZmlsbDpub25lO3N0cm9rZTpncmF5O3N0cm9rZS1saW5lY2FwOnJvdW5kO3N0cm9rZS1saW5lam9pbjpyb3VuZH0uY2xzLTJ7c3Ryb2tlLXdpZHRoOjEuMTNweH08L3N0eWxlPjwvZGVmcz48ZyBpZD0iQ2FscXVlXzQiIGRhdGEtbmFtZT0iQ2FscXVlIDQiPjxyZWN0IGNsYXNzPSJjbHMtMSIgeD0iNS41IiB5PSI1LjUiIHdpZHRoPSIxNSIgaGVpZ2h0PSIxNSIgcng9IjIuNzQiIHJ5PSIyLjc0Ii8+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNOS41IDkuNWg3djdoLTd6Ii8+PHBhdGggY2xhc3M9ImNscy0yIiBkPSJNOC41IDUuNXYtNE0xMS41IDUuNXYtNE0xNC41IDUuNXYtNE0xNy41IDUuNXYtNE04LjUgMjQuNXYtNE0xMS41IDI0LjV2LTRNMTQuNSAyNC41di00TTE3LjUgMjQuNXYtNE0yMC41IDguNWg0TTIwLjUgMTEuNWg0TTIwLjUgMTQuNWg0TTIwLjUgMTcuNWg0TTEuNSA4LjVoNE0xLjUgMTEuNWg0TTEuNSAxNC41aDRNMS41IDE3LjVoNCIvPjwvZz48L3N2Zz4=)}.scylla-icon--monitoring{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGcgZGF0YS1uYW1lPSJDYWxxdWUgNCI+PHBhdGggZD0iTTUuNTUgMTAuODlhMy44MyAzLjgzIDAgMCAxLS4xNS0zLjc2IiBzdHlsZT0ic3Ryb2tlLWxpbmVqb2luOnJvdW5kO3N0cm9rZS1saW5lY2FwOnJvdW5kO3N0cm9rZTpncmF5O2ZpbGw6bm9uZSIvPjxyZWN0IHg9IjE3LjYzIiB5PSIxNC4wMSIgd2lkdGg9IjMuMDUiIGhlaWdodD0iMTAuOCIgcng9Ii41NyIgcnk9Ii41NyIgdHJhbnNmb3JtPSJyb3RhdGUoLTQ1IDE5LjE1OCAxOS40MDUpIiBzdHlsZT0ic3Ryb2tlLW1pdGVybGltaXQ6MTA7ZmlsbDpncmF5O3N0cm9rZS13aWR0aDouOTVweDtzdHJva2U6Z3JheSIvPjxjaXJjbGUgY3g9IjguNSIgY3k9IjkiIHI9IjciIHN0eWxlPSJzdHJva2Utd2lkdGg6MnB4O3N0cm9rZS1taXRlcmxpbWl0OjEwO3N0cm9rZTpncmF5O2ZpbGw6bm9uZSIvPjxwYXRoIHN0eWxlPSJzdHJva2UtbWl0ZXJsaW1pdDoxMDtzdHJva2UtbGluZWNhcDpyb3VuZDtzdHJva2U6Z3JheTtmaWxsOm5vbmUiIGQ9Im0xNi4wNSAxNi4zOS0yLjI4LTIuMjgiLz48L2c+PC9zdmc+)}.scylla-icon--networking{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMntmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLW1pdGVybGltaXQ6MTB9PC9zdHlsZT48L2RlZnM+PGcgaWQ9IkNhbHF1ZV80IiBkYXRhLW5hbWU9IkNhbHF1ZSA0Ij48Y2lyY2xlIGN4PSIxMi41IiBjeT0iMTIuNSIgcj0iNCIgc3R5bGU9InN0cm9rZS13aWR0aDouOTRweDtmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLW1pdGVybGltaXQ6MTAiLz48Y2lyY2xlIGNsYXNzPSJjbHMtMiIgY3g9IjUiIGN5PSIzIiByPSIyLjUiLz48Y2lyY2xlIGNsYXNzPSJjbHMtMiIgY3g9IjE5IiBjeT0iMjAiIHI9IjIuNSIvPjxjaXJjbGUgY2xhc3M9ImNscy0yIiBjeD0iMjIiIGN5PSI2LjYiIHI9IjIuNSIvPjxjaXJjbGUgY2xhc3M9ImNscy0yIiBjeD0iNC41IiBjeT0iMjIiIHI9IjIuNSIvPjxwYXRoIGNsYXNzPSJjbHMtMiIgZD0ibTYuODMgNS41IDMuMjUgNC4zM00yMC4yMyA3Ljg1IDE1LjMzIDExTTkuODMgMTUuMDhsLTQuMDkgNS44NE0xNC41OCAxNS4zM2wzIDMuMDkiLz48Y2lyY2xlIGN4PSIxMi41IiBjeT0iMTIuNSIgcj0iMS41IiBzdHlsZT0iZmlsbDpncmF5Ii8+PC9nPjwvc3ZnPg==)}.scylla-icon--news{background-image:url(data:image/svg+xml;base64,PHN2ZyBpZD0iQ2FscXVlXzEiIGRhdGEtbmFtZT0iQ2FscXVlIDEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmlld0JveD0iMCAwIDI1IDI1Ij48ZGVmcz48c3R5bGU+LmNscy0xe2ZpbGw6bm9uZTtzdHJva2U6Z3JheTtzdHJva2UtbGluZWNhcDpyb3VuZDtzdHJva2UtbGluZWpvaW46cm91bmR9PC9zdHlsZT48L2RlZnM+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNMyAxNS4xNyAxNi4zMSAzLjgyYTEuNDggMS40OCAwIDAgMSAyLjIyLjQ2bDUuMTUgOS42NWExLjQ2IDEuNDYgMCAwIDEtLjkzIDIuMTJMNS42OSAxOS45Wk04LjcxIDE5LjMzbC43NiAyLjIyYTEuNTEgMS41MSAwIDAgMCAxLjg1IDFsMy41OC0xLjA2YTEuNSAxLjUgMCAwIDAgMS0xLjg2TDE1LjQ1IDE4TTUuNTQgMjBsLTEuODMgMWEuOTIuOTIgMCAwIDEtMS4yNS0uMzdMLjYxIDE3LjQ5QS45Mi45MiAwIDAgMSAxIDE2LjI0bDEuODMtMU04LjUgMTRsNy4zOC01LjUiLz48L3N2Zz4=)}.scylla-icon--newsletter{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMSwuY2xzLTJ7ZmlsbDpub25lO3N0cm9rZTpncmF5O3N0cm9rZS1taXRlcmxpbWl0OjEwfS5jbHMtMntzdHJva2UtbGluZWNhcDpyb3VuZH08L3N0eWxlPjwvZGVmcz48ZyBpZD0iQ2FscXVlXzQiIGRhdGEtbmFtZT0iQ2FscXVlIDQiPjxwYXRoIGNsYXNzPSJjbHMtMSIgZD0iTTE5LjUgOS41aDN2MTJoLTIwdi0xMmgzIi8+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJtMi42NSA5Ljg0IDkuODUgNi44OCA4LjYzLTYuODgiLz48cGF0aCBjbGFzcz0iY2xzLTIiIGQ9Im01LjUgNy41LTMgMk0xNC4zNSAzLjg2bC0xLjQ2LTEuMDktMS40NyAxLjA5TTIxLjUgOS41bC0yLTJNMTkuNSAxMS41di03aC0xNHY3LjQ3Ii8+PC9nPjwvc3ZnPg==)}.scylla-icon--nsql-guides{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGcgZGF0YS1uYW1lPSJDYWxxdWUgNCI+PHJlY3QgeD0iNC4zNyIgeT0iMTMuNzEiIHdpZHRoPSIxLjE1IiBoZWlnaHQ9IjkuNzIiIHJ4PSIuNTQiIHJ5PSIuNTQiIHRyYW5zZm9ybT0icm90YXRlKDQ1IDQuOTQ4IDE4LjU3KSIgc3R5bGU9InN0cm9rZTpncmF5O3N0cm9rZS1taXRlcmxpbWl0OjEwO2ZpbGw6Z3JheTtzdHJva2Utd2lkdGg6MS4wOXB4Ii8+PGNpcmNsZSBjeD0iMTIuMjUiIGN5PSIxMi4yNSIgcj0iNC43NSIgc3R5bGU9InN0cm9rZS13aWR0aDoxLjVweDtmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLW1pdGVybGltaXQ6MTAiLz48cGF0aCBzdHlsZT0ic3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLXdpZHRoOjEuMDZweDtmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLW1pdGVybGltaXQ6MTAiIGQ9Ik04LjUgMjAuNXYzaDE1di0yMWgtMTV2MiIvPjwvZz48L3N2Zz4=)}.scylla-icon--open-source{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfS5jbHMtMntmaWxsOmdyYXl9PC9zdHlsZT48L2RlZnM+PGcgaWQ9IkNhbHF1ZV80IiBkYXRhLW5hbWU9IkNhbHF1ZSA0Ij48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Ik0uMzEgMjEuNTEgNSAxOS42OWEyLjM3IDIuMzcgMCAwIDEgMS44OC4xOWw1LjI0IDEuNjhhMi4yMyAyLjIzIDAgMCAwIDItLjEybDkuNS00Ljc1Yy44LS40NCAxLjY0LTEuMzEgMS4xMy0xLjkxYTIuMzQgMi4zNCAwIDAgMC0yLjY0LS40MkwxOCAxNi4wOSIvPjxwYXRoIGNsYXNzPSJjbHMtMSIgZD0ibS4yNSAxNS42OSA0Ljg4LTEuMjFjMS4yNS0uMyAyLjE3LS42MyAzLjQ0LS4xM2ExNS4yMSAxNS4yMSAwIDAgMCA0IDEuMWg0LjUyYy44NSAwIC45NS41NC45NSAxLjEzYTEgMSAwIDAgMS0xLjA4IDEgNjUuODYgNjUuODYgMCAwIDEtNy0uMzEiLz48cGF0aCBjbGFzcz0iY2xzLTIiIGQ9Ik04LjU2IDkuNjh2LS44MWMwLS45MS0uMzgtMS4yMS0xLjI5LTEuMjFIN1Y2LjNoLjMxYy45MSAwIDEuMjktLjMgMS4yOS0xLjIxdi0uODFjMC0xLjIuNjYtMS45MiAyLjgyLTIuM3YxLjE2Yy0xLjI0LjM1LTEuNDMuNjgtMS40MyAxLjR2Ljg3QTEuNTIgMS41MiAwIDAgMSA4Ljc1IDcgMS41MiAxLjUyIDAgMCAxIDEwIDguNTZ2Ljg3YzAgLjcxLjE5IDEgMS40MyAxLjRWMTJjLTIuMjEtLjM1LTIuODctMS4xMi0yLjg3LTIuMzJaTTE3LjQzIDQuM3YuODFjMCAuOTEuMzcgMS4yMSAxLjI5IDEuMjFIMTl2MS4zNmgtLjMxYy0uOTIgMC0xLjI5LjMtMS4yOSAxLjIxdi44MWMwIDEuMi0uNjUgMi0yLjgxIDIuMzV2LTEuMmMxLjI1LS4zNiAxLjQ0LS42OSAxLjQ0LTEuNHYtLjg3QTEuNTMgMS41MyAwIDAgMSAxNy4yNSA3IDEuNTMgMS41MyAwIDAgMSAxNiA1LjQzdi0uODdjMC0uNzItLjE5LTEtMS40NC0xLjRWMmMyLjIyLjM4IDIuODcgMS4xIDIuODcgMi4zWiIvPjwvZz48L3N2Zz4=)}.scylla-icon--operator{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjQuODEgMS4wMSAyOC4zMiAyNy42NCI+PHBhdGggZD0iTTMyLjUyIDE4cy0uMDkgMC0uMDktLjA1LS4wOCAwLS4xNyAwYTIuMTkgMi4xOSAwIDAgMC0uNTEgMCAuNDcuNDcgMCAwIDEtLjI2LS4wNSA5LjI5IDkuMjkgMCAwIDEtMS40OS0uMzIuNTQuNTQgMCAwIDEtLjMtLjMxbC0uMzQtLjA4YTExLjI1IDExLjI1IDAgMCAwLS4xOC0zLjc5IDExLjU1IDExLjU1IDAgMCAwLTEuNS0zLjUybC4yNi0uMjZhLjU5LjU5IDAgMCAxIC4xMy0uMzkgNy43MyA3LjczIDAgMCAxIDEuMi0uODZsLjI2LS4xMy40Ny0uM3MuMDkgMCAuMTMtLjA4IDAtLjA1IDAtLjA5YS44NC44NCAwIDAgMCAuMTctMS4yLjc4Ljc4IDAgMCAwLS42LS4zIDEgMSAwIDAgMC0uNi4yMWMtLjA1LjA1LS4wOS4wOS0uMTMuMDlhMy4wOCAzLjA4IDAgMCAwLS4zNS4zOWMwIC4wOC0uMTMuMTMtLjE3LjE3YTUuNjQgNS42NCAwIDAgMS0xLjA3Ljk0LjU4LjU4IDAgMCAxLS4yNi4wOS4yNS4yNSAwIDAgMS0uMTcgMGgtLjA1bC0uMzQuMjEtMS4wOC0xYTExIDExIDAgMCAwLTUuNjUtMi4yN3YtLjM0YS42LjYgMCAwIDEtLjIyLS4zNEE4LjE4IDguMTggMCAwIDEgMTkuNjYgM3YtLjI1YzAtLjA4LjA1LS4zNS4wOS0uNTJ2LS4zMWEuODIuODIgMCAwIDAtMS40Ni0uNi44Ni44NiAwIDAgMC0uMjYuNnYuMjJhMS44MiAxLjgyIDAgMCAwIC4wOS41MS41OS41OSAwIDAgMSAwIC4yNlYzYTguODIgOC44MiAwIDAgMSAuMDggMS40Ny41OS41OSAwIDAgMS0uMjEuMzRWNS4yNGMtLjQ4IDAtMSAuMTMtMS40Ny4yMmExMC4xNiAxMC4xNiAwIDAgMC01LjI4IDNMMTEgOC4yNGgtLjE3YS43My43MyAwIDAgMS0uMjYtLjA5IDcuOCA3LjggMCAwIDEtMS4wNy0xYzAtLjA4LS4xMy0uMTMtLjE3LS4xN3MtLjI1LS4yLS4zMy0uMzMtLjA4IDAtLjEzLS4wOHYtLjA1YTEgMSAwIDAgMC0uNi0uMjEuNjQuNjQgMCAwIDAtLjYuMy45MS45MSAwIDAgMCAuMTcgMS4yczAgLjA1IDAgLjA1LjA5LjA4LjEzLjA4YTUgNSAwIDAgMCAuNDcuMjZsLjI2LjEzYTYuNjEgNi42MSAwIDAgMSAxLjIxLjg2LjQ3LjQ3IDAgMCAxIC4xMy4zOXYtLjA1bC4yNS4yNmEyLjUzIDIuNTMgMCAwIDEtLjEzLjIyIDEwLjIgMTAuMiAwIDAgMC0xLjUgN2wtLjM1LjA5YzAgLjEzLS4xNy4yMS0uMy4zYTguNTYgOC41NiAwIDAgMS0xLjQ2LjI2LjU5LjU5IDAgMCAwLS4yNiAwaC0uNTJjLS4xOCAwLS4wOC4wNS0uMTcuMDVoLS4wOGEuODQuODQgMCAwIDAtLjY5IDEgLjc5Ljc5IDAgMCAwIC44Ni42LjM5LjM5IDAgMCAwIC4yMSAwSDYuMTJhMy42MSAzLjYxIDAgMCAwIC40Ny0uMTcuNjUuNjUgMCAwIDEgLjI2LS4wOCA3LjY1IDcuNjUgMCAwIDEgMS40Mi0uMzkuNDkuNDkgMCAwIDEgLjM1LjEzaC4zOWExMC4zMiAxMC4zMiAwIDAgMCAzLjUzIDUgNi4zMSA2LjMxIDAgMCAwIDEuMTYuNzdsLS4yMi4zYS41MS41MSAwIDAgMSAwIC40MyA2LjU0IDYuNTQgMCAwIDEtLjY5IDEuMjR2LjA1YS43OC43OCAwIDAgMS0uMTcuMjFjLS4wOS4wOS0uMTcuMjYtLjMuNDNzMCAuMDktLjA5LjEzIDAgLjA1IDAgLjA1YS44OC44OCAwIDAgMCAuMzQgMS4xNi45LjkgMCAwIDAgLjMuMDggMSAxIDAgMCAwIC44Mi0uNTFzMC0uMDguMDktLjEzLjEzLS4zLjE3LS40N2wuMDktLjI2YTcuMDcgNy4wNyAwIDAgMSAuNTYtMS4zMy42Mi42MiAwIDAgMSAuMzQtLjI2bC4xNy0uMzVhMTAuMDUgMTAuMDUgMCAwIDAgMy43NS42OSA4LjQ1IDguNDUgMCAwIDAgMi4zMi0uMyAxMS40NiAxMS40NiAwIDAgMCAxLjM3LS4zOWwuMTguMzFhLjYyLjYyIDAgMCAxIC4zNC4yNiA3LjA3IDcuMDcgMCAwIDEgLjU2IDEuMzNsLjA5LjI2YTEuMzEgMS4zMSAwIDAgMCAuMTcuNDdjMCAuMDUgMCAuMDkuMDkuMTNhMSAxIDAgMCAwIC44Mi41MSAxLjA1IDEuMDUgMCAwIDAgLjM0LS4wOC43Ni43NiAwIDAgMCAuMzktLjQ4IDEuMDggMS4wOCAwIDAgMC0uMDUtLjY0LjIuMiAwIDAgMC0uMDgtLjEzIDEuNTMgMS41MyAwIDAgMC0uMzEtLjQzLjY1LjY1IDAgMCAwLS4xNy0uMjJ2LS4wOWE1LjIyIDUuMjIgMCAwIDEtLjY5LTEuMjQuNTEuNTEgMCAwIDEgLjA1LS40M2wtLjEzLS4zNEExMC42OCAxMC42OCAwIDAgMCAyOSAxOC44MmwuMzQuMDV2LS4wNWEuNTQuNTQgMCAwIDEgLjM1LS4xMyA3LjgyIDcuODIgMCAwIDEgMS4zOC4zOS42Mi42MiAwIDAgMCAuMjYuMDkgMi40MiAyLjQyIDAgMCAwIC40Ny4yMXMuMDkgMCAuMTcgMGguMDlhLjM5LjM5IDAgMCAwIC4yMSAwIC45NC45NCAwIDAgMCAuODYtLjYgMSAxIDAgMCAwLS43Ny0uOVptLTEyLjQzLTEuMzMtMS4xNi41Ni0xLjE2LS41Ni0uMy0xLjI1LjgxLTFoMS4yOWwuODIgMVptNy0yLjc5YTggOCAwIDAgMSAuMTcgMi43MWwtNC4xNS0uNzVjLS4zOC0uMDgtLjY4LS45LS43MS0xLjIyYTQgNCAwIDAgMSAuMjEtLjc0bDMuNDUtMi41NGE4LjU4IDguNTggMCAwIDEgMS4wNCAyLjU0Wm0tMi4zMS00LjEzLTMuMjIgMi42OWExLjI4IDEuMjggMCAwIDEtMS4yNS0uMzdjLS4wOS0uMDktLjM3LS4yNS0uMzctLjM4VjcuNDNhOC4wNyA4LjA3IDAgMCAxIDQuODYgMi4zMlpNMTcgNy41NmwxLS4xOC0uMDYgNC4zMWMwIC4zOC0uNjQuNjgtMSAuNjhhMS4xMSAxLjExIDAgMCAxLS4zNS0uMDhMMTMgOS43NWE4LjQxIDguNDEgMCAwIDEgNC0yLjE5Wm0tNS4yNCAzLjc4IDMuMzcgMi40Ny4zMi41M2ExLjE0IDEuMTQgMCAwIDEtLjI1IDEgLjc4Ljc4IDAgMCAxLS4zOC4zMWwtNC4zMS45YTkgOSAwIDAgMSAxLjI0LTUuMjFaTTExIDE4LjYxbDQuMS0xLjIzYy4zNSAwIC44NC43MS44OSAxLjA2YS41MS41MSAwIDAgMS0uMDUuNDNsLTEuNjMgMy45NUE4LjQxIDguNDEgMCAwIDEgMTEgMTguNjFabTkuNzYgNS4zM2E4LjY3IDguNjcgMCAwIDEtMS44NS4yMSA5LjU5IDkuNTkgMCAwIDEtMi43MS0uNDNsMS42Ni00Yy4yMS0uMjYgMS0uMiAxLjMxIDBhMi40OCAyLjQ4IDAgMCAxIC4zNC4zbDIuMDcgMy43NGE1LjcyIDUuNzIgMCAwIDAtLjguMThaTTI2IDIwLjJhOC4zNiA4LjM2IDAgMCAxLTIuNTggMi41OGwtMS45Mi0zLjcyYTEuMTUgMS4xNSAwIDAgMSAuNDEtMWMuMjEtLjI1LjU5LS41OS43MS0uNTlsNC4yMiAxLjA2QTYuMjcgNi4yNyAwIDAgMSAyNiAyMC4yWiIgc3R5bGU9ImZpbGw6IzRkNGQ0ZCIgZGF0YS1uYW1lPSJDYWxxdWUgMiIvPjwvc3ZnPg==)}.scylla-icon--overview{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJDYWxxdWVfNCIgZGF0YS1uYW1lPSJDYWxxdWUgNCI+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNMjIuNjEgMy40NUMyMi42MSA1LjA2IDE4IDYuNSAxMi41IDYuNXMtMTAtMS40NC0xMC0zIDQuNS0zIDEwLTMgMTAuMTEgMS4zMyAxMC4xMSAyLjk1Wk0yMi42MSA5LjQ0YzAgMS42MS00LjY0IDMuMDYtMTAuMTEgMy4wNnMtMTAtMS40NS0xMC0zLjA2TTIyLjYxIDE1LjUxYzAgMS42Mi00LjY0IDMtMTAuMTEgM3MtMTAtMS4zNy0xMC0zTTIyLjYxIDIxLjU5YzAgMS42Mi00LjY0IDIuOTEtMTAuMTEgMi45MXMtMTAtMS4yOS0xMC0yLjkxTTIuNSAyMS40N1YzLjQ1TTIyLjUgMjEuNDdWMy40NSIvPjwvZz48L3N2Zz4=)}.scylla-icon--partners{background-image:url(data:image/svg+xml;base64,PHN2ZyBpZD0iQ2FscXVlXzEiIGRhdGEtbmFtZT0iQ2FscXVlIDEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmlld0JveD0iMCAwIDI1IDI1Ij48ZGVmcz48c3R5bGU+LmNscy0xe2ZpbGw6bm9uZTtzdHJva2U6Z3JheTtzdHJva2UtbGluZWNhcDpyb3VuZDtzdHJva2UtbGluZWpvaW46cm91bmR9PC9zdHlsZT48L2RlZnM+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNMTguNSA4LjI2aC00LjcybC0xLjIzIDEuMjdNMi4zOSAxNS4wOS4xNSAxMy43NGw0Ljg3LTguNDIgMi4yNCAxLjM0LTQuODcgOC40M3pNMjIuNTkgMTUuMDlsMi4yNC0xLjM1LTQuODYtOC40Mi0yLjI0IDEuMzQgNC44NiA4LjQzek0xMC43MSAxNS4yNmwtMi45MyAyLjIxTTEyLjE4IDE2LjRsLTIuOTMgMi4yMU0xMy42OCAxNy41M2wtMi45MyAyLjIyIi8+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNNi4zOCA4LjNoMy43OGEyLjI3IDIuMjcgMCAwIDEgMS4zNy40N2MxLjI2IDEgNC4wOSAzLjE4IDQuNDggMy41NnMtMS4xNCAxLjY4LTIuMjcgMS4xYTE4LjM0IDE4LjM0IDAgMCAwLTIuMTEtLjkyLjU3LjU3IDAgMCAwLS41Ni4wOWwtNC43OSAzLjg5TDEyLjMzIDIxbDkuNDYtNy4wOU0zLjI0IDE0LjIybDMuNCAxLjg1Ii8+PC9zdmc+)}.scylla-icon--plus{background-image:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTciIGhlaWdodD0iMTciIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHJlY3Qgd2lkdGg9IjE3IiBoZWlnaHQ9IjE3IiByeD0iMSIgZmlsbD0iI0IzQkFDNSIvPjxwYXRoIGZpbGwtcnVsZT0iZXZlbm9kZCIgY2xpcC1ydWxlPSJldmVub2RkIiBkPSJNOS41IDVhMSAxIDAgMSAwLTIgMHYyLjVINWExIDEgMCAxIDAgMCAyaDIuNVYxMmExIDEgMCAxIDAgMiAwVjkuNUgxMmExIDEgMCAxIDAgMC0ySDkuNVY1WiIgZmlsbD0iI2ZmZiIvPjxwYXRoIGZpbGwtcnVsZT0iZXZlbm9kZCIgY2xpcC1ydWxlPSJldmVub2RkIiBkPSJNOS41IDVhMSAxIDAgMSAwLTIgMHYyLjVINWExIDEgMCAxIDAgMCAyaDIuNVYxMmExIDEgMCAxIDAgMiAwVjkuNUgxMmExIDEgMCAxIDAgMC0ySDkuNVY1WiIgZmlsbD0iI2ZmZiIvPjxwYXRoIGZpbGwtcnVsZT0iZXZlbm9kZCIgY2xpcC1ydWxlPSJldmVub2RkIiBkPSJNOS41IDVhMSAxIDAgMSAwLTIgMHYyLjVINWExIDEgMCAxIDAgMCAyaDIuNVYxMmExIDEgMCAxIDAgMiAwVjkuNUgxMmExIDEgMCAxIDAgMC0ySDkuNVY1WiIgZmlsbD0iI2ZmZiIvPjxwYXRoIGZpbGwtcnVsZT0iZXZlbm9kZCIgY2xpcC1ydWxlPSJldmVub2RkIiBkPSJNOS41IDVhMSAxIDAgMSAwLTIgMHYyLjVINWExIDEgMCAxIDAgMCAyaDIuNVYxMmExIDEgMCAxIDAgMiAwVjkuNUgxMmExIDEgMCAxIDAgMC0ySDkuNVY1WiIgZmlsbD0iI2ZmZiIvPjxwYXRoIGZpbGwtcnVsZT0iZXZlbm9kZCIgY2xpcC1ydWxlPSJldmVub2RkIiBkPSJNOS41IDVhMSAxIDAgMSAwLTIgMHYyLjVINWExIDEgMCAxIDAgMCAyaDIuNVYxMmExIDEgMCAxIDAgMiAwVjkuNUgxMmExIDEgMCAxIDAgMC0ySDkuNVY1WiIgZmlsbD0iI2ZmZiIvPjwvc3ZnPg==);filter:none}.scylla-icon--pricing{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJDYWxxdWVfMiIgZGF0YS1uYW1lPSJDYWxxdWUgMiI+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJtMjEuNzMgNy0yLjQxLTUuMTJhMi41MiAyLjUyIDAgMCAwLTIuODItMWwtNi4wOCAyLjA0QTEuNjkgMS42OSAwIDAgMCA5LjUxIDRMMy45MyAxOS4yOWExLjA2IDEuMDYgMCAwIDAgLjY0IDEuMTdsMTAuMzQgMy43NmExIDEgMCAwIDAgMS4yMi0uNDNsNS41OC0xNS4zM0ExLjg3IDEuODcgMCAwIDAgMjEuNzMgN1oiLz48Y2lyY2xlIGNsYXNzPSJjbHMtMSIgY3g9IjE1LjczIiBjeT0iNS44OSIgcj0iMiIvPjx0ZXh0IHRyYW5zZm9ybT0icm90YXRlKDIwIC00OC4yNDQgMzAuNjcpIiBzdHlsZT0iZm9udC1zaXplOjEycHg7ZmlsbDpncmF5O2ZvbnQtZmFtaWx5OlJvYm90by1NZWRpdW0sUm9ib3RvIj4kPC90ZXh0PjwvZz48L3N2Zz4=)}.scylla-icon--release-note{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMntmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kO3N0cm9rZS13aWR0aDouOTFweH08L3N0eWxlPjwvZGVmcz48ZyBpZD0iQ2FscXVlXzIiIGRhdGEtbmFtZT0iQ2FscXVlIDIiPjxwYXRoIHN0eWxlPSJzdHJva2Utd2lkdGg6LjlweDtmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kIiBkPSJNMjEuNSAyNC41aC0xN1Y1LjdMOC45NS41NCAyMS41LjV2MjR6Ii8+PHBhdGggY2xhc3M9ImNscy0yIiBkPSJNNC42NSA1LjVIOS41VjFNNy41IDguNWgxMU03LjUgMTEuNWgxMU03LjUgMTQuNWgxMU03LjUgMTcuNWgxMU03LjUgMjAuNWgxMSIvPjwvZz48L3N2Zz4=)}.scylla-icon--resource-center{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfS5jbHMtMntmaWxsOmdyYXl9PC9zdHlsZT48L2RlZnM+PGcgaWQ9IkNhbHF1ZV80IiBkYXRhLW5hbWU9IkNhbHF1ZSA0Ij48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Ik01LjUgMi41aDYuOTFsLjA5IDIwaC03di0yMHoiLz48cGF0aCBjbGFzcz0iY2xzLTIiIGQ9Ik04IDRoMnYxMC45N0w4IDE1VjR6Ii8+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNNS4zNiAyLjI5IDIuNSAzLjV2MThsMi43OSAxLjE0Ii8+PHBhdGggc3R5bGU9InN0cm9rZS13aWR0aDouNjhweDtmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kIiBkPSJtMTIuNTcgMjEuODYgMS41Ny43NSIvPjxwYXRoIHN0eWxlPSJzdHJva2Utd2lkdGg6Ljg1cHg7ZmlsbDpub25lO3N0cm9rZTpncmF5O3N0cm9rZS1saW5lY2FwOnJvdW5kO3N0cm9rZS1saW5lam9pbjpyb3VuZCIgZD0ibTE0LjExIDIuNS0xLjU0LjU3Ii8+PGNpcmNsZSBjbGFzcz0iY2xzLTIiIGN4PSI5IiBjeT0iMTkiIHI9IjEiLz48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Ik0xNC41IDIuNWg2Ljk0bC4wNiAyMGgtN3YtMjB6Ii8+PHBhdGggY2xhc3M9ImNscy0yIiBkPSJNMTcgNGgydjEwLjk3TDE3IDE1VjR6Ii8+PGNpcmNsZSBjbGFzcz0iY2xzLTIiIGN4PSIxOCIgY3k9IjE5IiByPSIxIi8+PHBhdGggY2xhc3M9ImNscy0yIiBkPSJNMTIuNiAyLjczaDEuNjdWMjIuNkgxMi42ek0yLjU4IDIxLjVsMi43NSAxLjFWMi43M2wtMi42Ni45NC0uMDkgMTcuODN6Ii8+PC9nPjwvc3ZnPg==)}.scylla-icon--roadmap{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMSwuY2xzLTJ7ZmlsbDpub25lO3N0cm9rZTpncmF5fS5jbHMtMXtzdHJva2UtbGluZWNhcDpyb3VuZDtzdHJva2UtbGluZWpvaW46cm91bmQ7c3Ryb2tlLXdpZHRoOi45OHB4fS5jbHMtMntzdHJva2UtbWl0ZXJsaW1pdDoxMH0uY2xzLTN7ZmlsbDpncmF5fTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJDYWxxdWVfNCIgZGF0YS1uYW1lPSJDYWxxdWUgNCI+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJtLjUgNC41IDgtMyA4IDQgOC0zdjE3bC04IDMtOC00LTggM3YtMTd6TTguNSAxLjVWMThNMTYuNSA1LjVWMjIiLz48cGF0aCBjbGFzcz0iY2xzLTIiIGQ9Ik0yLjUgMTMgNyAxNi41TTcgMTJsLTQuNSA1LjVNMTguNSA4bDQuNSAzLjVNMjMgN2wtNC41IDUuNSIvPjxwYXRoIGNsYXNzPSJjbHMtMyIgZD0iTTEwIDEzaDF2MWgtMXpNMTIgMTJoMXYxaC0xek0xNCAxMWgxdjFoLTF6Ii8+PC9nPjwvc3ZnPg==)}.scylla-icon--search{background-image:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZD0iTTEwLjUgMThhNy41IDcuNSAwIDEgMCAwLTE1IDcuNSA3LjUgMCAwIDAgMCAxNVpNMjEgMjFsLTUuMi01LjIiIHN0cm9rZT0iIzAwMCIgc3Ryb2tlLXdpZHRoPSIyIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiLz48L3N2Zz4=)}.scylla-icon--slack{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0NDggNTEyIj48IS0tISBGb250IEF3ZXNvbWUgUHJvIDYuMC4wIGJ5IEBmb250YXdlc29tZSAtIGh0dHBzOi8vZm9udGF3ZXNvbWUuY29tIExpY2Vuc2UgLSBodHRwczovL2ZvbnRhd2Vzb21lLmNvbS9saWNlbnNlIChDb21tZXJjaWFsIExpY2Vuc2UpIENvcHlyaWdodCAyMDIyIEZvbnRpY29ucywgSW5jLi0tPjxwYXRoIGQ9Ik05NC4xMiAzMTUuMWMwIDI1LjktMjEuMTYgNDcuMDYtNDcuMDYgNDcuMDZTMCAzNDEgMCAzMTUuMWMwLTI1LjkgMjEuMTYtNDcuMDYgNDcuMDYtNDcuMDZoNDcuMDZ2NDcuMDZ6bTIzLjcyIDBjMC0yNS45IDIxLjE2LTQ3LjA2IDQ3LjA2LTQ3LjA2czQ3LjA2IDIxLjE2IDQ3LjA2IDQ3LjA2djExNy44NGMwIDI1LjktMjEuMTYgNDcuMDYtNDcuMDYgNDcuMDZzLTQ3LjA2LTIxLjE2LTQ3LjA2LTQ3LjA2VjMxNS4xem00Ny4wNi0xODguOThjLTI1LjkgMC00Ny4wNi0yMS4xNi00Ny4wNi00Ny4wNlMxMzkgMzIgMTY0LjkgMzJzNDcuMDYgMjEuMTYgNDcuMDYgNDcuMDZ2NDcuMDZIMTY0Ljl6bTAgMjMuNzJjMjUuOSAwIDQ3LjA2IDIxLjE2IDQ3LjA2IDQ3LjA2cy0yMS4xNiA0Ny4wNi00Ny4wNiA0Ny4wNkg0Ny4wNkMyMS4xNiAyNDMuOTYgMCAyMjIuOCAwIDE5Ni45czIxLjE2LTQ3LjA2IDQ3LjA2LTQ3LjA2SDE2NC45em0xODguOTggNDcuMDZjMC0yNS45IDIxLjE2LTQ3LjA2IDQ3LjA2LTQ3LjA2IDI1LjkgMCA0Ny4wNiAyMS4xNiA0Ny4wNiA0Ny4wNnMtMjEuMTYgNDcuMDYtNDcuMDYgNDcuMDZoLTQ3LjA2VjE5Ni45em0tMjMuNzIgMGMwIDI1LjktMjEuMTYgNDcuMDYtNDcuMDYgNDcuMDYtMjUuOSAwLTQ3LjA2LTIxLjE2LTQ3LjA2LTQ3LjA2Vjc5LjA2YzAtMjUuOSAyMS4xNi00Ny4wNiA0Ny4wNi00Ny4wNiAyNS45IDAgNDcuMDYgMjEuMTYgNDcuMDYgNDcuMDZWMTk2Ljl6TTI4My4xIDM4NS44OGMyNS45IDAgNDcuMDYgMjEuMTYgNDcuMDYgNDcuMDYgMCAyNS45LTIxLjE2IDQ3LjA2LTQ3LjA2IDQ3LjA2LTI1LjkgMC00Ny4wNi0yMS4xNi00Ny4wNi00Ny4wNnYtNDcuMDZoNDcuMDZ6bTAtMjMuNzJjLTI1LjkgMC00Ny4wNi0yMS4xNi00Ny4wNi00Ny4wNiAwLTI1LjkgMjEuMTYtNDcuMDYgNDcuMDYtNDcuMDZoMTE3Ljg0YzI1LjkgMCA0Ny4wNiAyMS4xNiA0Ny4wNiA0Ny4wNiAwIDI1LjktMjEuMTYgNDcuMDYtNDcuMDYgNDcuMDZIMjgzLjF6Ii8+PC9zdmc+)}.scylla-icon--stack-overflow{background-image:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjQiIGhlaWdodD0iMzEiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Im0yMS45NDkuMTEzIDIuMDQzIDExLjY3LTIuNTE0LjQzMkwxOS40MzUuNTQ1IDIxLjk1LjExNFptLTE3Ljk3MyAyNiAxMS45NDUtLjAwNS0uMDAyLTIuNTMtMTEuOTQ0LjAwNi4wMDEgMi41M1ptMTIuMjMyLTUuNzc3TDQuMzE1IDE5LjI1bC0uMjM1IDIuNTIgMTEuODk0IDEuMDg1LjIzNC0yLjUxOVptLTEwLjc1LTYuMzc1IDExLjUzNSAzLjA3NC0uNjYyIDIuNDQzLTExLjUzNS0zLjA3NS42NjItMi40NDJabTEzLjA0LjE4TDguMjEyIDguMTI2bC0xLjI5NyAyLjE3OCAxMC4yODkgNi4wMTcgMS4yOTYtMi4xNzhabS00LjIwNi0xMS41NiA2LjczIDkuNzg3LTIuMTA4IDEuNDI0LTYuNzMtOS43ODUgMi4xMDgtMS40MjVaIiBmaWxsPSIjMDAwIi8+PHBhdGggZD0iTTE3Ljk1IDE3Ljc4OVYyOC4xM0gyLjI4MlYxNy43ODlILjI0M3YxMi4zMjZIMTkuOThWMTcuNzg5aC0yLjAzWiIgZmlsbD0iIzAwMCIvPjwvc3ZnPg==)}.scylla-icon--summit{background-image:url(data:image/svg+xml;base64,PHN2ZyBpZD0iQ2FscXVlXzEiIGRhdGEtbmFtZT0iQ2FscXVlIDEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmlld0JveD0iMCAwIDI1IDI1Ij48ZGVmcz48c3R5bGU+LmNscy0xe2ZpbGw6bm9uZTtzdHJva2U6IzRkNGQ0ZDtzdHJva2UtbGluZWNhcDpyb3VuZDtzdHJva2UtbGluZWpvaW46cm91bmR9PC9zdHlsZT48L2RlZnM+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJtMTYuNSAyMiAxLTYuNS0xMCAuMDMgMSA2LjQzIi8+PHBhdGggZD0iTTMuNDYgMTJBNS42OSA1LjY5IDAgMCAxIDUgNy41IiBzdHlsZT0ic3Ryb2tlLXdpZHRoOjEuMXB4O3N0cm9rZTojNGQ0ZDRkO3N0cm9rZS1saW5lY2FwOnJvdW5kO3N0cm9rZS1saW5lam9pbjpyb3VuZDtmaWxsOm5vbmUiLz48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Ik0xNC42MiA1YTIuMzMgMi4zMyAwIDAgMS0yLjI1IDIuNWMtMS4zMyAwLTItMS4xMi0xLjk1LTIuNDRzLjctMi41IDItMi40OEEyLjI3IDIuMjcgMCAwIDEgMTQuNjIgNVpNMTcuNTggMTJhMy4yMyAzLjIzIDAgMCAwLTMuNDYtMy41SDExQTMuMjYgMy4yNiAwIDAgMCA3LjUgMTIiLz48Y2lyY2xlIGN4PSI0Ljk0IiBjeT0iNi45NiIgcj0iMS4wMSIgc3R5bGU9ImZpbGw6IzRkNGQ0ZDtzdHJva2Utd2lkdGg6MS4xcHg7c3Ryb2tlOiM0ZDRkNGQ7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kIi8+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNNy41NCAxOC41SDQuNWwtMi02aDIwbC0yIDZoLTMiLz48L3N2Zz4=)}.scylla-icon--support{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJDYWxxdWVfNCIgZGF0YS1uYW1lPSJDYWxxdWUgNCI+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNMTguMTkgNy41YTEwIDEwIDAgMCAxIC4yMSAyLjA3YzAgNC4zNi0yLjYzIDYuOTMtNS45IDYuOTNzLTUuOTQtMi41Ny01Ljk0LTYuOTNhMTAuNTEgMTAuNTEgMCAwIDEgLjIyLTIuMTIiLz48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Ik03LjY3IDIuMjNBNi41OCA2LjU4IDAgMCAxIDEyLjUuNWE1LjY1IDUuNjUgMCAwIDEgNC4yOSAxLjdjMS45MyAxLjk0IDIuMzUgNS4wNyAyLjQzIDYuNzJhMS40OSAxLjQ5IDAgMCAwLS43OS4wNSA4LjY4IDguNjggMCAwIDAtLjA4LTEuMTZoMGE1LjUzIDUuNTMgMCAwIDEtMS43Ny0yLjM0TDE2LjQ5IDVsLS4zOC4yMkExOSAxOSAwIDAgMSA2LjggNy4zOGEuNTIuNTIgMCAwIDAtLjQyLjE2Yy0uMjMuMjQtLjE1LjY1LS4wNyAxLjA4IDAgLjExIDAgLjIyLjA1LjMyYTEuNCAxLjQgMCAwIDAtLjU4IDBjLS4xLTEuNDUtLjA2LTQuNjggMS44OS02LjcxWk02LjM4IDljLS42NS0uMDgtMSAuMS0xLjE0Ljc5YTIuMDYgMi4wNiAwIDAgMCAxLjM3IDIuMjlNMTguNTYgOWMuNjUtLjA4IDEuMDUuMSAxLjE0Ljc5YTIuMDYgMi4wNiAwIDAgMS0xLjM3IDIuMjlNOS41IDE4LjIzVjE1LjVNMTUuNSAxNS41djIuNzNNMi41IDI0LjE2Yy4yNC0yIC41OS0zLjYzIDIuNDMtNC40OWEyNC4yOSAyNC4yOSAwIDAgMSA0LjgyLTEuMzdNMjIuNSAyNC4zM2MtLjI0LTItLjQyLTMuOC0yLjI2LTQuNjZhMjQuMjkgMjQuMjkgMCAwIDAtNC44Mi0xLjM3Ii8+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNMTUuMzkgMTguMzlhNC4zNyA0LjM3IDAgMCAxLTIuOTEgMS4wNyA0LjQyIDQuNDIgMCAwIDEtMi44OS0xLjA1Ii8+PHBhdGggc3R5bGU9ImZpbGw6Z3JheSIgZD0iTTExIDEzaDN2MmgtM3oiLz48cGF0aCBkPSJNMTguMDcgMTJhOS4yMSA5LjIxIDAgMCAxLTUuNTMgMi4wNyIgc3R5bGU9InN0cm9rZS1taXRlcmxpbWl0OjEwO2ZpbGw6bm9uZTtzdHJva2U6Z3JheSIvPjwvZz48L3N2Zz4=)}.scylla-icon--tech-talks{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJDYWxxdWVfNCIgZGF0YS1uYW1lPSJDYWxxdWUgNCI+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNOC4zOSA0LjVIMjMuNXYxM2gtMTUiLz48Y2lyY2xlIGN4PSI0LjUiIGN5PSI2LjUiIHI9IjIiIHN0eWxlPSJzdHJva2UtbWl0ZXJsaW1pdDoxMDtmaWxsOm5vbmU7c3Ryb2tlOmdyYXkiLz48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Ik0xLjUgOS41aDJsLjguODYuNy0uODZoNS41OGExIDEgMCAxIDEgMCAySDYuNXYxMC44OGExIDEgMCAwIDEtMSAxLjEyIDEgMSAwIDAgMS0xLTEgMSAxIDAgMCAxLTEgMSAuOTMuOTMgMCAwIDEtMS0xdi02Yy0uNzggMC0yLS40Ny0yLTF2LTVhMSAxIDAgMCAxIDEtMVoiLz48L2c+PC9zdmc+)}.scylla-icon--testing{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJDYWxxdWVfNCIgZGF0YS1uYW1lPSJDYWxxdWUgNCI+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNNi41IDYuNWgxMnYxMmgtMTJ6Ii8+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNNC41IDQuNWgxNnYxNmgtMTZ6Ii8+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJtOC41IDEwLjUgNSA1IDExLTEyIi8+PC9nPjwvc3ZnPg==)}.scylla-icon--thumbs-up{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSJjdXJyZW50Q29sb3IiIHN0cm9rZS13aWR0aD0iMiIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIiBjbGFzcz0iZmVhdGhlciBmZWF0aGVyLXRodW1icy11cCI+PHBhdGggZD0iTTE0IDlWNWEzIDMgMCAwIDAtMy0zbC00IDl2MTFoMTEuMjhhMiAyIDAgMCAwIDItMS43bDEuMzgtOWEyIDIgMCAwIDAtMi0yLjN6TTcgMjJINGEyIDIgMCAwIDEtMi0ydi03YTIgMiAwIDAgMSAyLTJoMyIvPjwvc3ZnPg==)}.scylla-icon--thumbs-down{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSJjdXJyZW50Q29sb3IiIHN0cm9rZS13aWR0aD0iMiIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIiBjbGFzcz0iZmVhdGhlciBmZWF0aGVyLXRodW1icy1kb3duIj48cGF0aCBkPSJNMTAgMTV2NGEzIDMgMCAwIDAgMyAzbDQtOVYySDUuNzJhMiAyIDAgMCAwLTIgMS43bC0xLjM4IDlhMiAyIDAgMCAwIDIgMi4zem03LTEzaDIuNjdBMi4zMSAyLjMxIDAgMCAxIDIyIDR2N2EyLjMxIDIuMzEgMCAwIDEtMi4zMyAySDE3Ii8+PC9zdmc+)}.scylla-icon--tip{background-image:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZD0iTTEyIDI0QzUuNCAyNCAwIDE4LjYgMCAxMlM1LjQgMCAxMiAwczEyIDUuNCAxMiAxMi01LjQgMTItMTIgMTJabTAtMjJDNi41IDIgMiA2LjUgMiAxMnM0LjUgMTAgMTAgMTAgMTAtNC41IDEwLTEwUzE3LjUgMiAxMiAyWiIgZmlsbD0iI2ZmZiIvPjxwYXRoIGQ9Ik0xMSAxNmMtLjMgMC0uNS0uMS0uNy0uM2wtMy0zYy0uNC0uNC0uNC0xIDAtMS40LjQtLjQgMS0uNCAxLjQgMGwzIDNjLjQuNC40IDEgMCAxLjQtLjIuMi0uNC4zLS43LjNaIiBmaWxsPSIjZmZmIi8+PHBhdGggZD0iTTExIDE2Yy0uMyAwLS41LS4xLS43LS4zLS40LS40LS40LTEgMC0xLjRsNi02Yy40LS40IDEtLjQgMS40IDAgLjQuNC40IDEgMCAxLjRsLTYgNmMtLjIuMi0uNC4zLS43LjNaIiBmaWxsPSIjZmZmIi8+PC9zdmc+)}.scylla-icon--training{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJDYWxxdWVfMiIgZGF0YS1uYW1lPSJDYWxxdWUgMiI+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNMTcuNSAxNS41SC41di0xM2gxOE01LjUgMjVsNC00LjMgNCA0LjMiLz48Y2lyY2xlIGN4PSIyMSIgY3k9IjQiIHI9IjIuNSIgc3R5bGU9InN0cm9rZS1taXRlcmxpbWl0OjEwO2ZpbGw6bm9uZTtzdHJva2U6Z3JheSIvPjxwYXRoIGNsYXNzPSJjbHMtMSIgZD0iTTIzLjQxIDcuNWgtMS41MkwyMSA5bC0uOS0xLjVIMTNBMS44IDEuOCAwIDAgMCAxMS41IDlhMS44IDEuOCAwIDAgMCAxLjUgMS41aDQuNXYxMy4yNEExLjQxIDEuNDEgMCAwIDAgMTkgMjVhMS40MiAxLjQyIDAgMCAwIDEuNS0xLjIyIDEuNTMgMS41MyAwIDAgMCAzIDB2LTcuMTFhMS4xMSAxLjExIDAgMCAwIDEuMDktMS4xOFY4LjY3YTEuMTggMS4xOCAwIDAgMC0xLjE4LTEuMTdaTTkuNSAxNS40NHY1LjM4Ii8+PC9nPjwvc3ZnPg==)}.collapsible-button .side-nav__content .toctree-checkbox:checked~label i,.collapsible-button .side-nav__content i,.scylla-icon--triangle-down,.side-nav__content .collapsible-button i,.side-nav__content .scylla-icon--expand,.side-nav__content .toctree-checkbox:checked~label .collapsible-button i,.side-nav__content .toctree-checkbox:checked~label .scylla-icon--expand{background-image:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTAiIGhlaWdodD0iNSIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cGF0aCBmaWxsLXJ1bGU9ImV2ZW5vZGQiIGNsaXAtcnVsZT0iZXZlbm9kZCIgZD0ibTAgMCA1IDUgNS01SDBaIiBmaWxsPSIjM0EyRDU1Ii8+PC9zdmc+)}.scylla-icon--university{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJDYWxxdWVfNCIgZGF0YS1uYW1lPSJDYWxxdWUgNCI+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJtMS41IDguNSAxMS00IDExIDR2M2wtMTEgNC0xMS00di0zeiIvPjxwYXRoIGNsYXNzPSJjbHMtMSIgZD0iTTUuNSAxMi41djVhMTIuNDYgMTIuNDYgMCAwIDAgNyAyIDExLjIgMTEuMiAwIDAgMCA3LTJ2LTUiLz48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Im0xMy41IDkuNSA4IDEuMjN2OC43N00yMi41IDE2LjV2MyIvPjwvZz48L3N2Zz4=)}.scylla-icon--users-blog{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMntmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJDYWxxdWVfNCIgZGF0YS1uYW1lPSJDYWxxdWUgNCI+PHBhdGggc3R5bGU9InN0cm9rZS13aWR0aDouOThweDtmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kIiBkPSJNMjMuNSAyLjVoLTIydjE2aDEzdjQuMTdsNC4wNC00LjE3IDQuOTYtLjA0VjIuNXoiLz48cGF0aCBjbGFzcz0iY2xzLTIiIGQ9Ik0xMC44NSA4QTEwLjM4IDEwLjM4IDAgMCAxIDExIDkuNWMwIDIuNDctMS4yMSA0LTMgNHMtMy41LTItMy41LTQuNWE0LjE4IDQuMTggMCAwIDEgMC0xIi8+PHBhdGggY2xhc3M9ImNscy0yIiBkPSJNNS4yIDUuMDdhMy4yMiAzLjIyIDAgMCAxIDIuNS0xIDMuMTYgMy4xNiAwIDAgMSAyLjQgMSA2LjIyIDYuMjIgMCAwIDEgMS4zIDMuODEuNzQuNzQgMCAwIDAtLjQyIDBjMC0uMjQgMC0uNDQtLjA1LS42NmgwQTMgMyAwIDAgMSAxMCA2Ljl2LS4yNGwtLjIxLjEyQTkuNjIgOS42MiAwIDAgMSA0LjczIDhhLjI1LjI1IDAgMCAwLS4yMi4wOWMtLjEzLjE0LS4wOS4zNyAwIC42MXYuMThhLjg1Ljg1IDAgMCAwLS4zMiAwQTUuMzcgNS4zNyAwIDAgMSA1LjIgNS4wN1pNNC41MSA4LjkzYy0uMzUgMC0uNTcuMDUtLjYxLjQ0YTEuMTcgMS4xNyAwIDAgMCAuNzMgMS4zTTExIDguOTNjLjM2IDAgLjU3LjA1LjYyLjQ0YTEuMTcgMS4xNyAwIDAgMS0uNzQgMS4zTTYuMzEgMTQuMTN2LS44NE05LjI1IDEzLjE5di45NE0yLjQyIDE4Yy4xMy0xLjE1LjU4LTIuNTIgMS41OC0zYTE0LjcxIDE0LjcxIDAgMCAxIDIuMzEtLjgyTTEzLjUgMThjLS4xMy0xLjE1LS41MS0yLjUyLTEuNS0zcy0yLjUtMS0yLjUtMSIvPjxwYXRoIGNsYXNzPSJjbHMtMiIgZD0iTTkuMzQgMTQuMjJhMi4yMyAyLjIzIDAgMCAxLTEuNTYuNjEgMi4zMiAyLjMyIDAgMCAxLTEuNTUtLjU5TTIxLjUgNi41aC03TTIxLjUgOS41aC03TTE4LjUgMTIuNWgtNCIvPjwvZz48L3N2Zz4=)}.admonition.caution .admonition-title:before,.admonition.warning .admonition-title:before,.scylla-icon--warning{background-image:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PG1hc2sgaWQ9ImEiIG1hc2stdHlwZT0iYWxwaGEiIG1hc2tVbml0cz0idXNlclNwYWNlT25Vc2UiIHg9IjAiIHk9IjEiIHdpZHRoPSIyNCIgaGVpZ2h0PSIyMSI+PHBhdGggZD0iTTMuNSAyMmMtLjUgMC0xLS4xLTEuNS0uNEMuNiAyMC44LjEgMTguOS45IDE3LjVMOS40IDMuM2MuMy0uNC42LS44IDEtMSAuNy0uNCAxLjUtLjUgMi4zLS4zLjguMiAxLjQuNyAxLjkgMS40TDIzIDE3LjVjLjMuNS40IDEgLjQgMS41IDAgLjgtLjMgMS42LS45IDIuMS0uNS42LTEuMi45LTIgLjloLTE3Wm03LjYtMTcuNkwyLjcgMTguNWMtLjMuNS0uMSAxLjEuNCAxLjQuMS4xLjMuMS40LjFoMTYuOWMuMyAwIC41LS4xLjctLjMuMi0uMi4zLS40LjMtLjcgMC0uMiAwLS4zLS4xLS41TDEyLjkgNC40Yy0uMy0uNS0uOS0uNi0xLjQtLjQtLjIuMS0uMy4yLS40LjRaIiBmaWxsPSIjMDYxOTM4Ii8+PHBhdGggZD0iTTEyIDE0Yy0uNiAwLTEtLjQtMS0xVjljMC0uNi40LTEgMS0xczEgLjQgMSAxdjRjMCAuNi0uNCAxLTEgMVpNMTIgMThjLS4zIDAtLjUtLjEtLjctLjMtLjItLjItLjMtLjQtLjMtLjcgMC0uMSAwLS4zLjEtLjQuMS0uMS4xLS4yLjItLjMuMS0uMS4yLS4yLjMtLjIuMi0uMS40LS4xLjYtLjEuMSAwIC4xIDAgLjIuMS4xIDAgLjEgMCAuMi4xIDAgMCAuMS4xLjIuMS4xLjEuMi4yLjIuMyAwIC4xLjEuMy4xLjQgMCAuMy0uMS41LS4zLjctLjMuMi0uNS4zLS44LjNaIiBmaWxsPSIjMDYxOTM4Ii8+PC9tYXNrPjxnIG1hc2s9InVybCgjYSkiPjxwYXRoIGZpbGw9IiMwNjE5MzgiIGQ9Ik0wIDBoMjR2MjRIMHoiLz48L2c+PC9zdmc+)}.scylla-icon--webinars{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMntmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJDYWxxdWVfNCIgZGF0YS1uYW1lPSJDYWxxdWUgNCI+PHBhdGggc3R5bGU9InN0cm9rZS1taXRlcmxpbWl0OjEwO2ZpbGw6bm9uZTtzdHJva2U6Z3JheSIgZD0iTTEuNSA1LjVoMjJ2MTRoLTIyeiIvPjxwYXRoIGNsYXNzPSJjbHMtMiIgZD0iTTkuNDcgMjAuNXYxLjg4TTE1LjUgMjAuNXYyTTYuNSAyMi41aDEyIi8+PHBhdGggc3R5bGU9ImZpbGw6Z3JheSIgZD0ibTkgOSA3LjUgMy41M0w5IDE2Vjl6Ii8+PC9nPjwvc3ZnPg==)}.scylla-icon--whitepapers{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMntmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJDYWxxdWVfNCIgZGF0YS1uYW1lPSJDYWxxdWUgNCI+PHBhdGggc3R5bGU9ImZpbGw6Z3JheSIgZD0iTTggOWg4djJIOHoiLz48cGF0aCBjbGFzcz0iY2xzLTIiIGQ9Ik0xNC4wNiAxLjUgMy41IDEuNTJWMjMuNWgxN1Y3bC02LjQ0LTUuNXoiLz48cGF0aCBkPSJNMTQuMzIgMS40MnYzLjM3YTIuMDYgMi4wNiAwIDAgMCAyLjA4IDIuMWgzLjY3IiBzdHlsZT0ic3Ryb2tlLW1pdGVybGltaXQ6MTA7ZmlsbDpub25lO3N0cm9rZTpncmF5Ii8+PHBhdGggY2xhc3M9ImNscy0yIiBkPSJNNi41IDE5LjVoNE0xMy41IDE5LjVoNE02LjUgMTYuNWg0TTEzLjUgMTYuNWg0TTYuNSAxMy41aDRNMTMuNSAxMy41aDQiLz48L2c+PC9zdmc+)}.scylla-icon--workshop{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMSwuY2xzLTJ7ZmlsbDpub25lO3N0cm9rZTojNGQ0ZDRkfS5jbHMtMXtzdHJva2UtbWl0ZXJsaW1pdDoxMH0uY2xzLTJ7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJDYWxxdWVfNCIgZGF0YS1uYW1lPSJDYWxxdWUgNCI+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNMS41IDUuNWgyMnYxNGgtMjJ6Ii8+PHBhdGggY2xhc3M9ImNscy0yIiBkPSJtOS41IDE5LjUtLjAzIDIuODhNMTUuNSAxOS41djNNNi41IDIyLjVoMTIiLz48cGF0aCBzdHlsZT0iZmlsbDojNGQ0ZDRkIiBkPSJtNCA4IDIgOCAuOTctMy45NUwxMSAxMiA0IDh6Ii8+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJtNi40NyAxMS4zNCAzLjM3IDQuMjgiLz48L2c+PC9zdmc+)}.button{background:transparent;border:1px solid #3a2d55;border-radius:4px;color:#3a2d55;display:inline;font-size:14px;letter-spacing:1px;line-height:21px;margin:0;padding:12px 14px}.button:focus,.button:hover{background:transparent;color:#3a2d55;text-decoration:none}.button--reverse{background:#fff;border:0}.button--reverse:focus,.button--reverse:hover{background:#fff}.tooltip{background-color:rgba(0,0,0,.56);border-radius:4px;font-size:12px;padding:6px}.tooltip:before{display:none!important}.tooltip:empty{display:none!important}.has-tip{border:0;cursor:pointer}.scylla-dropdown{color:#23263b;font-size:14px;line-height:20px}.scylla-dropdown a,.scylla-dropdown a:focus,.scylla-dropdown a:hover{color:#23263b!important;padding:0!important}.scylla-dropdown__item{font-size:16px;padding:15px}.scylla-dropdown__title{align-items:center;display:flex!important;position:static!important}.scylla-dropdown__title:after{display:none!important}.scylla-dropdown__title .chevron{min-height:5px;width:10px}.scylla-dropdown__content{background:#fff;border:0;border-radius:8px;box-shadow:0 4px 25px rgba(0,0,0,.15);font-size:16px;list-style:none;margin-top:15px;overflow:hidden;padding:16px 0;width:max-content}.scylla-dropdown__content li{padding:7px 16px}.scylla-dropdown__content .contents.local>ul>li a:before,.scylla-dropdown__content .secondary-side-nav__content li a:before,.scylla-dropdown__content li .admonition-title:before,.scylla-dropdown__content li .scylla-icon,.secondary-side-nav__content .scylla-dropdown__content li a:before{margin-right:10px}.enlarge-image{cursor:zoom-in}.enlarge-image-reveal{background:transparent;border:none;cursor:zoom-out;padding:0;text-align:center;width:fit-content}.enlarge-image-reveal img{background-color:#fff;padding:15px}.header{background-color:#fff;box-shadow:0 2px 22px rgba(74,93,166,.15);justify-content:space-between;padding:12.75px 0;position:fixed;width:100%;z-index:99}.header,.header-logo{align-items:center;display:flex}.header-logo{margin-left:20px;width:auto}.header-logo__img{width:110px}.header-logo__bar{background-color:#3a2d55;border-left:1px solid #3a2d55;height:11.56px;margin:0 7.5px;width:0}.header-logo__text{color:#3a2d55;font-size:10.11px;letter-spacing:.722408px;line-height:12px;text-transform:uppercase}.header-navigation{display:none}.header-button{display:none;margin-left:15px;text-transform:uppercase}.header-search-box{display:none;margin-right:20px;width:200px}.scylla-dropdown--header .scylla-dropdown__item{font-size:14px}.scylla-dropdown--header .scylla-dropdown__title{text-transform:uppercase}.scylla-dropdown--header .scylla-dropdown__title .chevron{margin-left:10px}.contents.local>ul>li .scylla-dropdown--header .scylla-dropdown__content a:before,.scylla-dropdown--header .scylla-dropdown__content .admonition-title:before,.scylla-dropdown--header .scylla-dropdown__content .contents.local>ul>li a:before,.scylla-dropdown--header .scylla-dropdown__content .scylla-icon,.scylla-dropdown--header .scylla-dropdown__content .secondary-side-nav__content li a:before,.secondary-side-nav__content li .scylla-dropdown--header .scylla-dropdown__content a:before{min-height:20px;width:20px}@media screen and (min-width:1024px){.header{padding:18px 0}.header-logo__img{width:152px}.header-logo__bar{height:16px;margin:0 10px}.header-logo__text{font-size:14px;letter-spacing:.722408px;line-height:12px;text-transform:uppercase}.header-navigation{align-items:center;display:flex;justify-content:center}.header-search-box{display:block}}@media screen and (min-width:1200px){.header-logo{margin-left:30px;width:357px}.header-search-box{margin-right:30px;max-width:20%;width:318px}.header-button{display:block}}.side-nav{background:#fff;display:none;height:100vh;left:0;line-height:24px;max-height:calc(100vh - 50px);overflow-y:auto;padding:20px 20px 0;position:fixed;top:50px;width:100%;z-index:100}.side-nav__title{font-weight:700;margin-bottom:20px}.side-nav__content{max-width:90%;overflow-wrap:break-word}.side-nav__content label,.side-nav__content label i{margin:0;padding:0}.side-nav__content label{font-size:inherit;line-height:1;margin-left:5px;max-height:5px}.collapsible-button .side-nav__content i,.side-nav__content .collapsible-button i,.side-nav__content .scylla-icon--expand{height:5px;vertical-align:top;width:10px}.side-nav__content .toctree-checkbox{display:none;position:absolute;right:20px}.side-nav__content .toctree-checkbox~ul{display:none;margin-right:20px}.side-nav__content .toctree-checkbox:checked~ul{display:block}.side-nav__content ul{margin:0}.side-nav__content a{color:#23263b}.side-nav__content a:hover{color:#3c4fe0;font-weight:400}.side-nav__content li{list-style:none;padding:0 0 24px}.side-nav__content li.has-children{align-items:center;display:flex;flex-wrap:wrap}.side-nav__content li.has-children>a{max-width:calc(100% - 15px)}.side-nav__content li.has-children.current{padding-bottom:20px}.side-nav__content li.has-children:hover>a{color:#3c4fe0}.side-nav__content li.has-children:hover>.toctree-checkbox~label i{filter:invert(38%) sepia(71%) saturate(6789%) hue-rotate(231deg) brightness(90%) contrast(95%)}.side-nav__content li.current-page>a{color:#3c4fe0}.side-nav__content li.current-page>.toctree-checkbox:checked~label i{filter:invert(38%) sepia(71%) saturate(6789%) hue-rotate(231deg) brightness(90%) contrast(95%)}.side-nav__content li ul{margin-top:18px;width:100%}.side-nav__content li ul li{border-left:1px solid #3c4fe0;padding:4px 0 4px 13px}.side-nav__content li ul ul{margin-left:0}.side-nav__content li .label{display:none}.side-nav__versions{max-width:90%}.side-nav__search,.side-nav__versions .dropdown{margin-bottom:20px}.collapsible-button{background:#fff;background-color:#fff;border:0;border-radius:8px;border-radius:50%;bottom:10px;box-shadow:0 4px 25px rgba(0,0,0,.15);cursor:pointer;display:none;font-size:0;left:300px;overflow:hidden;padding:13.5px;position:fixed}.collapsible-button i{height:16px;margin:0;width:16px}.side-nav--collapsed .collapsible-button{border-radius:0 20px 20px 0;left:-10px}.side-nav--collapsed .collapsible-button i{transform:rotate(180deg)}.layout--has-banner .side-nav{max-height:calc(100vh - 92.5px)}@media screen and (min-width:1024px){.side-nav{background-color:#f6f8ff;display:block;height:100%;left:auto;max-height:100vh;max-height:calc(100vh - 80px);padding:30px 40px;top:80px;width:286px;z-index:25}.side-nav__content{max-width:100%;padding-bottom:180px}.side-nav__search{display:none}.side-nav__versions{max-width:100%}.toctree-checkbox{right:40px}.layout--has-banner .side-nav{max-height:calc(100vh - 150px)}}@media screen and (min-width:1200px){.side-nav{width:357px}.side-nav--collapsed{background-color:transparent;padding-left:0;padding-right:0;width:126px}.side-nav--collapsed .side-nav-content{display:none}.collapsible-button{display:block}}.side-nav-toggle{cursor:pointer;display:block;margin-right:20px;position:relative;z-index:300}@media screen and (min-width:1024px){.side-nav-toggle{display:none}}.secondary-side-nav{display:none;height:100%;line-height:24px;padding:20px;width:100%}.secondary-side-nav__content{overflow-wrap:break-word}.secondary-side-nav__content ul{list-style:none;margin:0}.secondary-side-nav__content li{border-bottom:1px solid rgba(90,94,154,.1);display:none;padding:10px 0;word-break:break-word}.secondary-side-nav__content li:last-child{border:0}.secondary-side-nav__content li .label{display:none}.secondary-side-nav__content li a{align-items:baseline;color:#b3bac5;display:flex;font-size:14px}.secondary-side-nav__content li a:before{content:"";filter:invert(40%) sepia(11%) saturate(2157%) hue-rotate(198deg) brightness(89%) contrast(87%)!important;flex-shrink:0;margin-right:10px;min-height:10px;opacity:.5;width:6px}.secondary-side-nav__content li a.current,.secondary-side-nav__content li a:hover{color:#23263b;font-weight:400}.secondary-side-nav__content li a.current:before,.secondary-side-nav__content li a:hover:before{filter:brightness(0);opacity:1}.secondary-side-nav__content li a.current{font-weight:700}.secondary-side-nav__content>ul>li>ul>li{display:block}.secondary-side-nav__content>ul>li{border:0;display:block}.secondary-side-nav__content>ul>li>a{display:none}@media screen and (min-width:1200px){.secondary-side-nav{display:block;max-height:100vh;max-height:calc(100vh - 80px);overflow-y:auto;padding:60px 60px 60px 20px;position:fixed;top:80px;width:286px}.secondary-side-nav__content{padding-bottom:180px}.layout--has-banner .secondary-side-nav{max-height:calc(100vh - 150px)}}.layout{display:flex}.pre-content{align-items:center;display:flex;justify-content:space-between;margin-bottom:20px}.content{margin-top:50px;max-width:1440px;overflow-wrap:break-word;padding:20px;scroll-margin-top:50px;width:100%}.content .line-block,.content p{line-height:28px;margin-bottom:20px}.content ul{list-style:none}.content ul li:before{color:#b3bac5;content:"•";float:left;font-family:FontAwesome;font-size:20px;font-weight:700;margin-left:-1em;margin-top:-2px;width:1em}.content ul ul{list-style:circle}.content ul ul li:before{content:""}.content ol ol{list-style:lower-latin}.content img{margin-bottom:30px}.content section{margin-top:-50px;padding-top:50px}.content .inline-icon.fa-check{color:#42c4e6}.layout--full-width .content{max-width:100%;padding:0;width:100%}.layout--full-width .content .hero-wrapper,.layout--full-width .content .topics-grid{max-width:1190px}.layout--full-width .content.content--collapsed{margin-left:0}.layout--full-width:not(.layout--sidebar) .content{margin-left:0}.layout--has-banner .content{scroll-margin-top:92.5px}.layout--has-banner .content section{margin-top:-92.5px;padding-top:92.5px}.landing__content{padding:0 16px}@media screen and (min-width:1024px){.content{margin-left:286px;margin-top:80px;min-height:calc(100vh - 260px);padding-bottom:100px;scroll-margin-top:80px;width:calc(100% - 286px)}.content section{margin-top:-80px;padding-top:80px}}@media screen and (min-width:1200px){.content{margin-left:357px;padding:60px 40px 40px;width:calc(100% - 643px)}.content--collapsed{margin-left:126px;width:calc(100% - 412px)}.pre-content{margin-bottom:10px}.layout--has-banner .content{scroll-margin-top:150px}.layout--has-banner .content section{margin-top:-150px;padding-top:150px}.landing__content{padding:0 60px}.landing--floating .landing__content{position:relative;top:-70px}}.contents.local>ul{margin-bottom:30px;margin-left:0}.contents.local>ul>li{border-bottom:1px solid rgba(90,94,154,.1);padding:10px 0;word-break:break-word}.contents.local>ul>li:before{content:""}.contents.local>ul>li:last-child{border:0}.contents.local>ul>li ul{display:none}.contents.local>ul>li p{margin:0}.contents.local>ul>li a{font-size:14px}.contents.local>ul>li a:before{content:"";filter:invert(40%) sepia(11%) saturate(2157%) hue-rotate(198deg) brightness(89%) contrast(87%)!important;margin-right:10px;min-height:10px;opacity:.5;width:10px}.contents.local>ul>li a.current:before,.contents.local>ul>li a:hover:before{filter:brightness(0);opacity:1}.topic-title{color:rgba(35,38,59,.75);font-size:10px;letter-spacing:1.5px;margin-bottom:0;text-transform:uppercase}.notice{margin-top:40px}.footer{background-color:#fff;box-shadow:0 -4px 10px hsla(0,0%,82%,.25);padding:30px 0;position:relative;width:100%;z-index:50}.footer-group{margin:0 auto;max-width:1030px;padding:0 20px}.footer-top{align-items:center;border-bottom:1px solid rgba(0,0,0,.1);display:flex;flex-wrap:wrap;justify-content:space-between;padding-bottom:8px;text-align:center}.footer-logo{margin-bottom:30px;width:100%}.footer-logo img{float:left;height:36px}.footer-links{text-align:left}.footer-links__link{color:#333;font-size:12px;font-weight:500;letter-spacing:2.4px;margin-right:16px;text-transform:uppercase}.footer-actions{align-items:center;display:flex;justify-content:space-between;width:90px}.footer-actions__link{color:#000}.footer-actions__link img{height:23px}.footer-bottom{color:#979797;display:flex;flex-wrap:wrap;font-size:12px;font-style:normal;font-weight:400;justify-content:center;letter-spacing:1.4px;line-height:23px;padding:20px 0 10px;text-align:center;text-transform:uppercase}@media screen and (max-width:510px){.footer-links{margin-bottom:20px}}@media screen and (min-width:1024px){.footer{padding:30px 0}.footer-group{padding:0}.footer-top{padding-bottom:30px}.footer-logo{margin:0;width:auto}.footer-links{padding:0 40px}.footer-links__link{font-size:14px;margin-right:28px}.footer-actions{width:110px}.footer-actions__link img{height:28px}.footer-bottom .footer-bottom__copyright,.footer-bottom .footer-bottom__last-updated,.footer-bottom .footer-bottom__version{padding:0 10px}.footer-bottom .footer-bottom__copyright{border-left:none}}.not-found{background-color:#f6f8ff;height:100%;overflow:hidden}.not-found__icon{display:block;margin:40px auto;max-width:300px}.not-found__text{text-align:center}.not-found__text h1{font-size:60px;line-height:1}.not-found__text p{margin:30px 0;width:100%}.not-found__button{text-transform:uppercase}.admonition{border-radius:4px;box-shadow:0 4px 4px rgba(0,0,0,.12);color:rgba(0,0,0,.56);font-size:14px;line-height:20px;margin-bottom:30px;overflow:auto;padding:20px;position:relative}.admonition:before{bottom:0;content:" ";left:0;position:absolute;right:0;top:0;z-index:-1}.admonition-title{color:#23263b;margin-bottom:0!important}.admonition-title:before{content:"";margin-right:8px;min-height:24px;width:24px}.admonition p:not(.admonition-title){margin-bottom:0!important;margin-left:32px}.admonition.tip{border:1px solid #43a047}.admonition.tip:before{border-left:8px solid rgba(67,160,71,.4)}.admonition.tip .admonition-title:before{filter:invert(47%) sepia(11%) saturate(2286%) hue-rotate(73deg) brightness(109%) contrast(88%)}.admonition.note{border:1px solid #1976d2}.admonition.note:before{border-left:8px solid rgba(25,118,210,.4)}.admonition.note .admonition-title:before{filter:invert(44%) sepia(55%) saturate(2310%) hue-rotate(191deg) brightness(81%) contrast(103%)}.admonition.caution{border:1px solid #ffab00}.admonition.caution:before{border-left:8px solid rgba(255,171,0,.4)}.admonition.caution .admonition-title:before{filter:invert(77%) sepia(56%) saturate(3332%) hue-rotate(357deg) brightness(98%) contrast(108%)}.admonition.warning{border:1px solid #e74c3c}.admonition.warning:before{border-left:8px solid rgba(231,76,60,.4)}.admonition.warning .admonition-title:before{filter:invert(41%) sepia(42%) saturate(6427%) hue-rotate(343deg) brightness(99%) contrast(83%)}.breadcrumbs{margin-bottom:0;text-transform:uppercase}.breadcrumbs .bread__item,.breadcrumbs .bread__item:not(.bread__item--last):after,.breadcrumbs a{color:#23263b;font-size:12px;font-weight:400;letter-spacing:1.5px;line-height:2;margin:0;padding:0}.breadcrumbs .bread__item:before{display:none}.breadcrumbs .bread__item:not(.bread__item--last):after{content:"/";margin:0 5px;opacity:1;position:relative}.breadcrumbs .bread__highlight{color:#3c4fe0}.breadcrumbs .bread__highlight:hover{font-weight:700;text-decoration:none}code{background-color:#f7f8f9;border:none;border-radius:4px;color:#23263b;font-size:14px}code.download{background:none;color:#23263b}.highlight{background:transparent!important}.highlight pre{background-color:#f7f8f9;border-radius:8px;color:#23263b;font-size:14px;line-height:26px;margin-bottom:30px;overflow:auto;padding:16px}.highlight a.copybtn{right:1em;top:1em}.highlighttable{background-color:#f7f8f9;border-radius:16px;box-shadow:none}.highlighttable tbody{background-color:transparent;border:0}.highlighttable tbody td{padding:15px!important}.highlighttable tbody tr{border-top:none}.highlighttable .linenos{background-color:#f7f8f9;color:#5a7184;width:50px}.highlighttable .linenos span{line-height:26px}.highlighttable .highlight pre{background-color:transparent;margin:0;padding:0}.highlighttable .highlight a.copybtn{right:.2em;top:.2em}.hide-copy-button .copybtn{display:none}.sphinx_collapse__label{display:flex!important;flex-direction:row-reverse;font-size:medium;font-weight:700;justify-content:flex-end;margin-left:0!important}.sphinx_collapse__icon{margin-left:5px;margin-right:0}.sphinx_collapse__input:checked~.sphinx_collapse__label,.sphinx_collapse__label:hover{color:#3c4fe0}.sphinx_collapse__input:checked~.sphinx_collapse__label .sphinx_collapse__icon,.sphinx_collapse__label:hover .sphinx_collapse__icon{border-top-color:#3c4fe0}.sphinx_collapse__content{margin-top:10px}.contribute{margin:0 0 20px}.contribute__item{font-size:14px;list-style:none;padding-bottom:10px}.contribute__item .icon{margin-right:5px}.content-navigation{display:flex;justify-content:space-between;margin-top:40px}.navigation{max-width:50%;word-break:break-word}.navigation,.navigation__link{display:flex}.navigation__title{word-wrap:break-word;color:#23263b;font-size:12px;font-weight:500;letter-spacing:1.5px;line-height:24px;text-transform:uppercase}.navigation__title .colored{color:#42c4e6}.navigation__button{background:#fff;background-color:#fff;border:0;border-radius:8px;box-shadow:0 4px 25px rgba(0,0,0,.15);cursor:pointer;display:none;font-size:0;height:fit-content;overflow:hidden;padding:13.5px 16.5px}.navigation__button i{height:16px;margin:0;width:10px}.navigation--prev .navigation__title{margin-left:15px}.navigation--next .navigation__title{margin-right:15px;text-align:right}@media screen and (min-width:1200px){.navigation__title{display:inline-block}.navigation__button{display:block}.navigation--next .navigation__title{text-align:left}}.scylla-dropdown--versions .scylla-dropdown__item{background:#fff;border-radius:8px;box-shadow:0 28px 32px rgba(0,0,0,.06);width:100%}.scylla-dropdown--versions .scylla-dropdown__title{align-items:center;display:flex;justify-content:space-between}.scylla-dropdown--versions .scylla-dropdown__title .chevron{min-height:12px;transform:rotate(90deg);width:8px}@media screen and (min-width:1024px){.scylla-dropdown--versions .scylla-dropdown__item{box-shadow:none}}.feedback-container{font-size:16px;margin-top:40px;text-align:left}.feedback-container__title{font-weight:700;margin-bottom:5px!important}.feedback-container__button{background:#fff;border:0;border-radius:8px;box-shadow:0 4px 25px rgba(0,0,0,.15);cursor:pointer;margin:4px;overflow:hidden;padding:8px}.feedback-container__button.active{border:1px solid #3c4fe0}.feedback-container__icon{height:20px;width:20px}.feedback-container__message{font-size:16px;margin-top:10px}.hero{background:#f6f8ff;margin-bottom:30px;overflow:hidden;padding:30px 16px;text-align:left}.hero__title{font-size:28px;font-weight:500;line-height:38px;margin-bottom:14px;max-width:229px}.hero__text{font-size:16px;line-height:26px;max-width:343px}.hero__text a{border-bottom:1px dotted #23263b;color:#23263b}.hero__text p{margin-bottom:0!important}.hero__img{position:absolute;right:-18px;top:20px}.hero__img img{margin-bottom:0!important;width:124px}.hero__button{margin-top:20px;text-transform:uppercase}.hero__button .icon{margin-right:5px}.hero__search-box{box-shadow:0 4px 25px rgba(0,0,0,.02);margin-top:20px}.hero-wrapper{align-items:center;display:flex;justify-content:space-between;margin:0 auto;position:relative}@media screen and (min-width:640px){.hero{padding:60px 16px}.hero__title{font-size:32px;line-height:42px;max-width:482px}.hero__text{font-size:18px;line-height:26px;max-width:482px}.hero__img{display:block;position:static}.hero__img img{height:100%;width:295px}.hero .hero-wrapper{flex-direction:row-reverse}.hero .landing--floating .hero{padding:30px 16px 100px}}@media screen and (min-width:1024px){.hero{padding:60px}}.label{background-color:#23263b;border:0;border-radius:4px;color:#fff;font-size:inherit}.label--note{background-color:#1976d2}.label--tip{background-color:#43a047}.label--caution{background-color:#ffab00}.label--warning{background-color:#e74c3c}.last-updated{color:#4458a3;font-size:12px;letter-spacing:1.5px;margin:10px 0;text-transform:uppercase}.last-updated__icon{font-size:14px}@media screen and (min-width:1024px){.last-updated{float:right;margin:0}}.panel{border:0;border-radius:4px;margin-bottom:30px}.promo-banner{background-color:#4458a3;background-image:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTQ0MCIgaGVpZ2h0PSI3MCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48bWFzayBpZD0iYSIgbWFzay10eXBlPSJhbHBoYSIgbWFza1VuaXRzPSJ1c2VyU3BhY2VPblVzZSIgeD0iMCIgeT0iMCIgd2lkdGg9IjE0NDAiIGhlaWdodD0iNzAiPjxwYXRoIGZpbGw9IiM0NDU4QTMiIGQ9Ik0wIDBoMTQ0MHY3MEgweiIvPjwvbWFzaz48ZyBtYXNrPSJ1cmwoI2EpIiBmaWxsPSIjNTA2NEFFIj48cGF0aCBkPSJNLTE5MyAyMDEuODg0IDEuNS0xMzUgMzU3LjQzNiA3MC41bC0xOTQuNSAzMzYuODg0ek0xMDkyLjkyLTM4LjAwOSA5NzIuODAzLTI0Ni4wNTcgNDAyLjk5NiA4Mi45MiA1MjMuMTEzIDI5MC45N3oiLz48cGF0aCBkPSJtMTAzOC0zOC4wMDkgMTIwLjExNy0yMDguMDQ5IDU2OS44MDcgMzI4Ljk3OS0xMjAuMTE3IDIwOC4wNDl6Ii8+PC9nPjwvc3ZnPg==);background-position:50%;background-repeat:no-repeat;background-size:cover;display:none;overflow:hidden;position:fixed;top:0;width:100%;z-index:900}.promo-banner__icon{margin-right:15px}.promo-banner__icon img{height:40px}.promo-banner__title{color:#fff;font-size:12px;line-height:16px;margin-right:15px}.promo-banner__button{background:#fff;border-radius:4px;font-size:12px;min-width:max-content;padding:5px}.promo-banner__close{display:none;position:absolute;right:16px;top:16px}.contents.local>ul>li .promo-banner__close a:before,.promo-banner__close .admonition-title:before,.promo-banner__close .contents.local>ul>li a:before,.promo-banner__close .scylla-icon,.promo-banner__close .secondary-side-nav__content li a:before,.secondary-side-nav__content li .promo-banner__close a:before{filter:brightness(100%);height:34px;width:34px}.promo-banner__close:hover{cursor:pointer;filter:opacity(.8)}.promo-banner-wrapper{align-items:center;display:flex;justify-content:center;padding:5.85px 20px}@media(min-width:1024px){.promo-banner__title{font-size:18px;line-height:23px}.promo-banner__button{font-size:14px;padding:8.5px}.promo-banner__close{display:block}.promo-banner-wrapper{flex-direction:unset;padding:16px}}.custom-scroll-bar::-webkit-scrollbar{background-color:transparent;width:5px}.custom-scroll-bar::-webkit-scrollbar-thumb{background-color:#b3bac5;-webkit-border-radius:8px;border-radius:8px}.search-box{background:#f7f8f9;border-radius:4px;display:flex;padding:10px 15px}.search-box--hero{background-color:#fff;padding:12px 14px}.search-box:before{background-image:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZD0iTTEwLjUgMThhNy41IDcuNSAwIDEgMCAwLTE1IDcuNSA3LjUgMCAwIDAgMCAxNVpNMjEgMjFsLTUuMi01LjIiIHN0cm9rZT0iIzAwMCIgc3Ryb2tlLXdpZHRoPSIyIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiLz48L3N2Zz4=);background-repeat:no-repeat;background-size:contain;content:"";display:inline-block;filter:brightness(0);margin-top:2px;min-height:18px;min-width:18px;vertical-align:middle;width:20px}.search-box .er-dummy-search,.search-box .er-dummy-search-box,.search-box .er-search-form,.search-box ci-search,.search-box input{margin:0!important;width:100%!important}.search-box input{background:transparent!important;color:rgba(80,80,80,.5)!important;font-size:14px!important;padding:0!important}.search-box input::placeholder{color:rgba(80,80,80,.5)!important;opacity:1!important}.search-box button{display:none!important}.er_search_suggestions{background:#fff;border:0;border:0!important;border-radius:8px;box-shadow:0 4px 25px rgba(0,0,0,.15);overflow:hidden}.er_search_suggestions .er-search-result-box{border-width:1px!important;padding-bottom:10px!important;padding-top:10px!important}.er_search_suggestions .er-search-result-box:hover{background:#f7f8f9!important}.er_search_suggestions .er_more_result_btn{cursor:pointer}.er_search_suggestions h3{font-size:16px!important}.er-search-content{padding:20px!important}#er_search_results .er-search-result-box{display:block!important;margin:10px auto 0!important;width:100%!important}#er_search_results .text,#er_search_results .title a,#er_search_results .url a{max-width:100%!important}#search-result-input-form{max-width:800px!important}#er_search_button{text-align:center}#er_clear_input{right:0!important;top:0!important}.er-facet-header{background-color:transparent!important;border:0!important;padding:0 0 8px!important}.er-facet-val{padding:5px 2px!important}.er-facet-val input{display:block!important;margin:0}#er_search_pagination{margin-top:20px!important}#er_search_pagination li.er-paginator-list.er-active{border-bottom:0!important;font-weight:700}.er-suggestion-sm .er_search_input_dummy{margin:0!important}.er-suggestion-sm .er_search_button_dummy{border:0!important}#er_gcs_mobile_model_container .er-facet-values .er-facet-val{align-items:baseline}@media screen and (min-width:640px){.er-facets{display:none;max-width:300px!important;min-width:auto!important;width:auto!important}}@media screen and (min-width:1024px){.er-suggestions{left:15px!important}}@media screen and (min-width:1200px){.er-facets{display:block;position:fixed!important}.er-facet-count{display:none}}.sphinx-tabs{margin-bottom:30px}.sphinx-tabs-tab{border-bottom:1px solid rgba(0,0,0,.56);color:rgba(0,0,0,.56);cursor:pointer;font-size:14px;font-weight:500;line-height:13px;padding:20px 25px}.sphinx-tabs-tab[aria-selected=true]{border-bottom:2px solid #2196f3;color:#2196f3;padding-bottom:19px}.sphinx-tabs-panel{margin:30px 0}.table-wrapper{border:1px solid #e0e0e0;border-radius:4px;box-shadow:0 1px 2px rgba(0,0,0,.25);display:block;margin-bottom:30px;max-width:100%;overflow-x:auto}table{color:#000;font-size:14px;line-height:24px;margin:0;overflow:hidden}table p{margin:0!important}table caption{background:#f6f8ff;border-bottom:1px solid #e0e0e0;color:#23263b;padding:10px 25px}table thead{background:#f6f8ff;border:0;border-bottom:1px solid #4458a3}table thead th{color:#23263b;font-size:14px;font-weight:700}table td,table thead th{padding:20px 25px}table tbody tr{background-color:transparent!important;border-top:1px solid #e0e0e0;line-height:18px}table:not(.highlighttable) tbody tr:first-child{border-top:1px solid #4458a3}table.thead-border thead .row-odd th{color:#23263b}table.thead-border thead .row-even th{font-weight:400}table.thead-border thead th{border:1px solid #e0e0e0}table.thead-border thead tr:first-child th{border-top:none}table.thead-border thead tr:last-child th{border-bottom:none}table.thead-border thead tr th:first-child{border-left:none}table.thead-border thead tr th:last-child{border-right:none}.topics-grid{display:block;margin:0 auto 30px}.topics-grid__title{color:#23263b;font-size:24px;font-weight:700;line-height:32px;margin-bottom:6px}.topics-grid__text{color:#4458a3;font-size:18px;line-height:24px}.topics-grid--scrollable .hs{-ms-overflow-style:none;display:grid;grid-auto-flow:column;overflow-x:scroll;padding:20px 10px;scrollbar-width:none}.topics-grid--scrollable .hs::-webkit-scrollbar{display:none}.topics-grid--scrollable .hs .topic-box:last-child:after{content:"";width:20px}.topic-box{align-items:stretch;display:flex}.topic-box .card{background:#fff;border:1px solid transparent;border-radius:8px;box-shadow:0 4px 25px rgba(0,0,0,.15);display:flex;flex-direction:column;font-size:18px;margin:0 auto 30px;overflow:hidden;padding:20px;position:relative}.topic-box .card:hover{border:1px solid #4458a3;color:#23263b;font-weight:400}.topic-box__title{color:#23263b;font-size:16px;font-weight:700;line-height:24px;margin-bottom:0}.topic-box__title img{bottom:0;opacity:.3;position:absolute;right:0;top:0}.topic-box__body{color:#000;display:flex;flex-direction:column;flex-grow:1;max-width:80%}.topic-box__body .container{flex-grow:1;margin:0;padding:0}.topic-box__body .line-block,.topic-box__body p{font-size:16px;line-height:19px;margin-top:10px}.topic-box__anchor{color:#42c4e6;font-size:14px;font-weight:700;line-height:24px}.topic-box__icon{display:block;font-size:50px;margin-bottom:20px}.topic-box__icon i{filter:brightness(0);min-height:50px;width:100%}.topic-box__icon img{bottom:-12px;display:none;height:140px;margin:0;opacity:.3;position:absolute;right:-5px}.topic-box--product .card{box-shadow:none;padding:20px;text-align:center}.topic-box--product .card .topic-box__title{color:#23263b;font-size:14px}.topic-box--product .card .topic-box__body{display:flex;flex-direction:column;max-width:100%}.topic-box--product .card .topic-box__body .line-block,.topic-box--product .card .topic-box__body p{font-size:12px}.topic-box--product .card .topic-box__icon img{display:inline-block;max-height:84px;opacity:1;position:static}.topic-box--product .card:hover{background:#fff;border:0;border-radius:8px;box-shadow:0 4px 25px rgba(0,0,0,.15);overflow:hidden}@media screen and (max-width:1024px){.topics-grid--scrollable .topic-box{width:280px!important}.topic-box--product:nth-last-child(-n+2) .card{margin-bottom:0}}@media screen and (min-width:1024px){.topics-grid{margin-bottom:10px}.topics-grid__text{font-size:16px}.topics-grid--scrollable .hs{display:flex;overflow-x:initial;padding:0}.topics-grid--scrollable .hs .topic-box:last-child:after{display:none}.topic-box .card{margin-bottom:60px;padding:45px 30px}.topic-box__title{font-size:20px;line-height:32px}.topic-box__body .line-block,.topic-box__body p{font-size:18px;line-height:26px}.topic-box__anchor{font-size:20px;line-height:26px}.topic-box .topic-box__icon img{display:inline-block}.topic-box--product .card{padding:20px}.topic-box--product .card .topic-box__title{font-size:18px;line-height:24px}.topic-box--product .card .topic-box__body .line-block,.topic-box--product .card .topic-box__body p{font-size:14px}.topic-box--product .card .topic-box__icon img{max-height:111px}.landing .topics-grid--products{margin-bottom:40px}} \ No newline at end of file diff --git a/3.26.2-scylla/_static/doctools.js b/3.26.2-scylla/_static/doctools.js new file mode 100644 index 0000000000..8cbf1b161a --- /dev/null +++ b/3.26.2-scylla/_static/doctools.js @@ -0,0 +1,323 @@ +/* + * doctools.js + * ~~~~~~~~~~~ + * + * Sphinx JavaScript utilities for all documentation. + * + * :copyright: Copyright 2007-2021 by the Sphinx team, see AUTHORS. + * :license: BSD, see LICENSE for details. + * + */ + +/** + * select a different prefix for underscore + */ +$u = _.noConflict(); + +/** + * make the code below compatible with browsers without + * an installed firebug like debugger +if (!window.console || !console.firebug) { + var names = ["log", "debug", "info", "warn", "error", "assert", "dir", + "dirxml", "group", "groupEnd", "time", "timeEnd", "count", "trace", + "profile", "profileEnd"]; + window.console = {}; + for (var i = 0; i < names.length; ++i) + window.console[names[i]] = function() {}; +} + */ + +/** + * small helper function to urldecode strings + * + * See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/decodeURIComponent#Decoding_query_parameters_from_a_URL + */ +jQuery.urldecode = function(x) { + if (!x) { + return x + } + return decodeURIComponent(x.replace(/\+/g, ' ')); +}; + +/** + * small helper function to urlencode strings + */ +jQuery.urlencode = encodeURIComponent; + +/** + * This function returns the parsed url parameters of the + * current request. Multiple values per key are supported, + * it will always return arrays of strings for the value parts. + */ +jQuery.getQueryParameters = function(s) { + if (typeof s === 'undefined') + s = document.location.search; + var parts = s.substr(s.indexOf('?') + 1).split('&'); + var result = {}; + for (var i = 0; i < parts.length; i++) { + var tmp = parts[i].split('=', 2); + var key = jQuery.urldecode(tmp[0]); + var value = jQuery.urldecode(tmp[1]); + if (key in result) + result[key].push(value); + else + result[key] = [value]; + } + return result; +}; + +/** + * highlight a given string on a jquery object by wrapping it in + * span elements with the given class name. + */ +jQuery.fn.highlightText = function(text, className) { + function highlight(node, addItems) { + if (node.nodeType === 3) { + var val = node.nodeValue; + var pos = val.toLowerCase().indexOf(text); + if (pos >= 0 && + !jQuery(node.parentNode).hasClass(className) && + !jQuery(node.parentNode).hasClass("nohighlight")) { + var span; + var isInSVG = jQuery(node).closest("body, svg, foreignObject").is("svg"); + if (isInSVG) { + span = document.createElementNS("http://www.w3.org/2000/svg", "tspan"); + } else { + span = document.createElement("span"); + span.className = className; + } + span.appendChild(document.createTextNode(val.substr(pos, text.length))); + node.parentNode.insertBefore(span, node.parentNode.insertBefore( + document.createTextNode(val.substr(pos + text.length)), + node.nextSibling)); + node.nodeValue = val.substr(0, pos); + if (isInSVG) { + var rect = document.createElementNS("http://www.w3.org/2000/svg", "rect"); + var bbox = node.parentElement.getBBox(); + rect.x.baseVal.value = bbox.x; + rect.y.baseVal.value = bbox.y; + rect.width.baseVal.value = bbox.width; + rect.height.baseVal.value = bbox.height; + rect.setAttribute('class', className); + addItems.push({ + "parent": node.parentNode, + "target": rect}); + } + } + } + else if (!jQuery(node).is("button, select, textarea")) { + jQuery.each(node.childNodes, function() { + highlight(this, addItems); + }); + } + } + var addItems = []; + var result = this.each(function() { + highlight(this, addItems); + }); + for (var i = 0; i < addItems.length; ++i) { + jQuery(addItems[i].parent).before(addItems[i].target); + } + return result; +}; + +/* + * backward compatibility for jQuery.browser + * This will be supported until firefox bug is fixed. + */ +if (!jQuery.browser) { + jQuery.uaMatch = function(ua) { + ua = ua.toLowerCase(); + + var match = /(chrome)[ \/]([\w.]+)/.exec(ua) || + /(webkit)[ \/]([\w.]+)/.exec(ua) || + /(opera)(?:.*version|)[ \/]([\w.]+)/.exec(ua) || + /(msie) ([\w.]+)/.exec(ua) || + ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec(ua) || + []; + + return { + browser: match[ 1 ] || "", + version: match[ 2 ] || "0" + }; + }; + jQuery.browser = {}; + jQuery.browser[jQuery.uaMatch(navigator.userAgent).browser] = true; +} + +/** + * Small JavaScript module for the documentation. + */ +var Documentation = { + + init : function() { + this.fixFirefoxAnchorBug(); + this.highlightSearchWords(); + this.initIndexTable(); + if (DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS) { + this.initOnKeyListeners(); + } + }, + + /** + * i18n support + */ + TRANSLATIONS : {}, + PLURAL_EXPR : function(n) { return n === 1 ? 0 : 1; }, + LOCALE : 'unknown', + + // gettext and ngettext don't access this so that the functions + // can safely bound to a different name (_ = Documentation.gettext) + gettext : function(string) { + var translated = Documentation.TRANSLATIONS[string]; + if (typeof translated === 'undefined') + return string; + return (typeof translated === 'string') ? translated : translated[0]; + }, + + ngettext : function(singular, plural, n) { + var translated = Documentation.TRANSLATIONS[singular]; + if (typeof translated === 'undefined') + return (n == 1) ? singular : plural; + return translated[Documentation.PLURALEXPR(n)]; + }, + + addTranslations : function(catalog) { + for (var key in catalog.messages) + this.TRANSLATIONS[key] = catalog.messages[key]; + this.PLURAL_EXPR = new Function('n', 'return +(' + catalog.plural_expr + ')'); + this.LOCALE = catalog.locale; + }, + + /** + * add context elements like header anchor links + */ + addContextElements : function() { + $('div[id] > :header:first').each(function() { + $('\u00B6'). + attr('href', '#' + this.id). + attr('title', _('Permalink to this headline')). + appendTo(this); + }); + $('dt[id]').each(function() { + $('\u00B6'). + attr('href', '#' + this.id). + attr('title', _('Permalink to this definition')). + appendTo(this); + }); + }, + + /** + * workaround a firefox stupidity + * see: https://bugzilla.mozilla.org/show_bug.cgi?id=645075 + */ + fixFirefoxAnchorBug : function() { + if (document.location.hash && $.browser.mozilla) + window.setTimeout(function() { + document.location.href += ''; + }, 10); + }, + + /** + * highlight the search words provided in the url in the text + */ + highlightSearchWords : function() { + var params = $.getQueryParameters(); + var terms = (params.highlight) ? params.highlight[0].split(/\s+/) : []; + if (terms.length) { + var body = $('div.body'); + if (!body.length) { + body = $('body'); + } + window.setTimeout(function() { + $.each(terms, function() { + body.highlightText(this.toLowerCase(), 'highlighted'); + }); + }, 10); + $('') + .appendTo($('#searchbox')); + } + }, + + /** + * init the domain index toggle buttons + */ + initIndexTable : function() { + var togglers = $('img.toggler').click(function() { + var src = $(this).attr('src'); + var idnum = $(this).attr('id').substr(7); + $('tr.cg-' + idnum).toggle(); + if (src.substr(-9) === 'minus.png') + $(this).attr('src', src.substr(0, src.length-9) + 'plus.png'); + else + $(this).attr('src', src.substr(0, src.length-8) + 'minus.png'); + }).css('display', ''); + if (DOCUMENTATION_OPTIONS.COLLAPSE_INDEX) { + togglers.click(); + } + }, + + /** + * helper function to hide the search marks again + */ + hideSearchWords : function() { + $('#searchbox .highlight-link').fadeOut(300); + $('span.highlighted').removeClass('highlighted'); + }, + + /** + * make the url absolute + */ + makeURL : function(relativeURL) { + return DOCUMENTATION_OPTIONS.URL_ROOT + '/' + relativeURL; + }, + + /** + * get the current relative url + */ + getCurrentURL : function() { + var path = document.location.pathname; + var parts = path.split(/\//); + $.each(DOCUMENTATION_OPTIONS.URL_ROOT.split(/\//), function() { + if (this === '..') + parts.pop(); + }); + var url = parts.join('/'); + return path.substring(url.lastIndexOf('/') + 1, path.length - 1); + }, + + initOnKeyListeners: function() { + $(document).keydown(function(event) { + var activeElementType = document.activeElement.tagName; + // don't navigate when in search box, textarea, dropdown or button + if (activeElementType !== 'TEXTAREA' && activeElementType !== 'INPUT' && activeElementType !== 'SELECT' + && activeElementType !== 'BUTTON' && !event.altKey && !event.ctrlKey && !event.metaKey + && !event.shiftKey) { + switch (event.keyCode) { + case 37: // left + var prevHref = $('link[rel="prev"]').prop('href'); + if (prevHref) { + window.location.href = prevHref; + return false; + } + break; + case 39: // right + var nextHref = $('link[rel="next"]').prop('href'); + if (nextHref) { + window.location.href = nextHref; + return false; + } + break; + } + } + }); + } +}; + +// quick alias for translations +_ = Documentation.gettext; + +$(document).ready(function() { + Documentation.init(); +}); diff --git a/3.26.2-scylla/_static/documentation_options.js b/3.26.2-scylla/_static/documentation_options.js new file mode 100644 index 0000000000..c23c68c3e7 --- /dev/null +++ b/3.26.2-scylla/_static/documentation_options.js @@ -0,0 +1,12 @@ +var DOCUMENTATION_OPTIONS = { + URL_ROOT: document.getElementById("documentation_options").getAttribute('data-url_root'), + VERSION: '3.26.2', + LANGUAGE: 'None', + COLLAPSE_INDEX: false, + BUILDER: 'html', + FILE_SUFFIX: '.html', + LINK_SUFFIX: '.html', + HAS_SOURCE: true, + SOURCELINK_SUFFIX: '.txt', + NAVIGATION_WITH_KEYS: false +}; \ No newline at end of file diff --git a/3.26.2-scylla/_static/file.png b/3.26.2-scylla/_static/file.png new file mode 100644 index 0000000000..a858a410e4 Binary files /dev/null and b/3.26.2-scylla/_static/file.png differ diff --git a/3.26.2-scylla/_static/img/banner-background.svg b/3.26.2-scylla/_static/img/banner-background.svg new file mode 100644 index 0000000000..f8520d5b3e --- /dev/null +++ b/3.26.2-scylla/_static/img/banner-background.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/3.26.2-scylla/_static/img/favicon-228x228.png b/3.26.2-scylla/_static/img/favicon-228x228.png new file mode 100644 index 0000000000..f30770c7ed Binary files /dev/null and b/3.26.2-scylla/_static/img/favicon-228x228.png differ diff --git a/3.26.2-scylla/_static/img/favicon-32x32.png b/3.26.2-scylla/_static/img/favicon-32x32.png new file mode 100644 index 0000000000..aae1708f26 Binary files /dev/null and b/3.26.2-scylla/_static/img/favicon-32x32.png differ diff --git a/3.26.2-scylla/_static/img/favicon.ico b/3.26.2-scylla/_static/img/favicon.ico new file mode 100644 index 0000000000..6c7484f082 Binary files /dev/null and b/3.26.2-scylla/_static/img/favicon.ico differ diff --git a/3.26.2-scylla/_static/img/icons/icon-about-team.svg b/3.26.2-scylla/_static/img/icons/icon-about-team.svg new file mode 100644 index 0000000000..5448c7f007 --- /dev/null +++ b/3.26.2-scylla/_static/img/icons/icon-about-team.svg @@ -0,0 +1 @@ +icon-about-team diff --git a/3.26.2-scylla/_static/img/icons/icon-about-us-m.svg b/3.26.2-scylla/_static/img/icons/icon-about-us-m.svg new file mode 100644 index 0000000000..09107d9520 --- /dev/null +++ b/3.26.2-scylla/_static/img/icons/icon-about-us-m.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/3.26.2-scylla/_static/img/icons/icon-about-us.svg b/3.26.2-scylla/_static/img/icons/icon-about-us.svg new file mode 100644 index 0000000000..1b1fcc83e3 --- /dev/null +++ b/3.26.2-scylla/_static/img/icons/icon-about-us.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/3.26.2-scylla/_static/img/icons/icon-alternator.svg b/3.26.2-scylla/_static/img/icons/icon-alternator.svg new file mode 100644 index 0000000000..7c2b4ebae0 --- /dev/null +++ b/3.26.2-scylla/_static/img/icons/icon-alternator.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/3.26.2-scylla/_static/img/icons/icon-apps.svg b/3.26.2-scylla/_static/img/icons/icon-apps.svg new file mode 100644 index 0000000000..7e93612026 --- /dev/null +++ b/3.26.2-scylla/_static/img/icons/icon-apps.svg @@ -0,0 +1 @@ + diff --git a/3.26.2-scylla/_static/img/icons/icon-architecture.svg b/3.26.2-scylla/_static/img/icons/icon-architecture.svg new file mode 100644 index 0000000000..67ebbc2f38 --- /dev/null +++ b/3.26.2-scylla/_static/img/icons/icon-architecture.svg @@ -0,0 +1 @@ +icon-architecture diff --git a/3.26.2-scylla/_static/img/icons/icon-benchmarks.svg b/3.26.2-scylla/_static/img/icons/icon-benchmarks.svg new file mode 100644 index 0000000000..e1ce2c1d78 --- /dev/null +++ b/3.26.2-scylla/_static/img/icons/icon-benchmarks.svg @@ -0,0 +1 @@ +icon-benchmarks diff --git a/3.26.2-scylla/_static/img/icons/icon-blog.svg b/3.26.2-scylla/_static/img/icons/icon-blog.svg new file mode 100644 index 0000000000..f4096cbf11 --- /dev/null +++ b/3.26.2-scylla/_static/img/icons/icon-blog.svg @@ -0,0 +1 @@ +icon-blog2 diff --git a/3.26.2-scylla/_static/img/icons/icon-careers.svg b/3.26.2-scylla/_static/img/icons/icon-careers.svg new file mode 100644 index 0000000000..2a7c6ea0b7 --- /dev/null +++ b/3.26.2-scylla/_static/img/icons/icon-careers.svg @@ -0,0 +1 @@ +icon-careers diff --git a/3.26.2-scylla/_static/img/icons/icon-chevron-left.svg b/3.26.2-scylla/_static/img/icons/icon-chevron-left.svg new file mode 100644 index 0000000000..3afa25c481 --- /dev/null +++ b/3.26.2-scylla/_static/img/icons/icon-chevron-left.svg @@ -0,0 +1,3 @@ + + + diff --git a/3.26.2-scylla/_static/img/icons/icon-chevron-right.svg b/3.26.2-scylla/_static/img/icons/icon-chevron-right.svg new file mode 100644 index 0000000000..44eb829cdc --- /dev/null +++ b/3.26.2-scylla/_static/img/icons/icon-chevron-right.svg @@ -0,0 +1,3 @@ + + + diff --git a/3.26.2-scylla/_static/img/icons/icon-circe.svg b/3.26.2-scylla/_static/img/icons/icon-circe.svg new file mode 100644 index 0000000000..875e421670 --- /dev/null +++ b/3.26.2-scylla/_static/img/icons/icon-circe.svg @@ -0,0 +1 @@ + diff --git a/3.26.2-scylla/_static/img/icons/icon-clock.svg b/3.26.2-scylla/_static/img/icons/icon-clock.svg new file mode 100644 index 0000000000..8c92469808 --- /dev/null +++ b/3.26.2-scylla/_static/img/icons/icon-clock.svg @@ -0,0 +1 @@ + diff --git a/3.26.2-scylla/_static/img/icons/icon-close.svg b/3.26.2-scylla/_static/img/icons/icon-close.svg new file mode 100644 index 0000000000..d1162b73e7 --- /dev/null +++ b/3.26.2-scylla/_static/img/icons/icon-close.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/3.26.2-scylla/_static/img/icons/icon-cloud-docs.svg b/3.26.2-scylla/_static/img/icons/icon-cloud-docs.svg new file mode 100644 index 0000000000..a9069bb6e5 --- /dev/null +++ b/3.26.2-scylla/_static/img/icons/icon-cloud-docs.svg @@ -0,0 +1 @@ + diff --git a/3.26.2-scylla/_static/img/icons/icon-cloud.svg b/3.26.2-scylla/_static/img/icons/icon-cloud.svg new file mode 100644 index 0000000000..cfb2318dae --- /dev/null +++ b/3.26.2-scylla/_static/img/icons/icon-cloud.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/3.26.2-scylla/_static/img/icons/icon-comparison.svg b/3.26.2-scylla/_static/img/icons/icon-comparison.svg new file mode 100644 index 0000000000..49d809a5df --- /dev/null +++ b/3.26.2-scylla/_static/img/icons/icon-comparison.svg @@ -0,0 +1 @@ +icon-comparison diff --git a/3.26.2-scylla/_static/img/icons/icon-contact-us.svg b/3.26.2-scylla/_static/img/icons/icon-contact-us.svg new file mode 100644 index 0000000000..9df3145dd2 --- /dev/null +++ b/3.26.2-scylla/_static/img/icons/icon-contact-us.svg @@ -0,0 +1 @@ +icon-contact-us diff --git a/3.26.2-scylla/_static/img/icons/icon-developers-blog.svg b/3.26.2-scylla/_static/img/icons/icon-developers-blog.svg new file mode 100644 index 0000000000..ee804197a0 --- /dev/null +++ b/3.26.2-scylla/_static/img/icons/icon-developers-blog.svg @@ -0,0 +1 @@ +icon-developers-blog diff --git a/3.26.2-scylla/_static/img/icons/icon-docs.svg b/3.26.2-scylla/_static/img/icons/icon-docs.svg new file mode 100644 index 0000000000..5501492f3e --- /dev/null +++ b/3.26.2-scylla/_static/img/icons/icon-docs.svg @@ -0,0 +1 @@ +icon-docs diff --git a/3.26.2-scylla/_static/img/icons/icon-enterprise-m.svg b/3.26.2-scylla/_static/img/icons/icon-enterprise-m.svg new file mode 100644 index 0000000000..97be900b50 --- /dev/null +++ b/3.26.2-scylla/_static/img/icons/icon-enterprise-m.svg @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/3.26.2-scylla/_static/img/icons/icon-enterprise.svg b/3.26.2-scylla/_static/img/icons/icon-enterprise.svg new file mode 100644 index 0000000000..ee1ac26283 --- /dev/null +++ b/3.26.2-scylla/_static/img/icons/icon-enterprise.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/3.26.2-scylla/_static/img/icons/icon-events.svg b/3.26.2-scylla/_static/img/icons/icon-events.svg new file mode 100644 index 0000000000..ba5f211864 --- /dev/null +++ b/3.26.2-scylla/_static/img/icons/icon-events.svg @@ -0,0 +1 @@ +icon-events diff --git a/3.26.2-scylla/_static/img/icons/icon-exclamation.svg b/3.26.2-scylla/_static/img/icons/icon-exclamation.svg new file mode 100644 index 0000000000..a7eb4b77a4 --- /dev/null +++ b/3.26.2-scylla/_static/img/icons/icon-exclamation.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/3.26.2-scylla/_static/img/icons/icon-expand.svg b/3.26.2-scylla/_static/img/icons/icon-expand.svg new file mode 100644 index 0000000000..3806565367 --- /dev/null +++ b/3.26.2-scylla/_static/img/icons/icon-expand.svg @@ -0,0 +1,50 @@ + + + + + + + + + diff --git a/3.26.2-scylla/_static/img/icons/icon-forum.svg b/3.26.2-scylla/_static/img/icons/icon-forum.svg new file mode 100644 index 0000000000..37a709f7a8 --- /dev/null +++ b/3.26.2-scylla/_static/img/icons/icon-forum.svg @@ -0,0 +1 @@ + diff --git a/3.26.2-scylla/_static/img/icons/icon-getting-started.svg b/3.26.2-scylla/_static/img/icons/icon-getting-started.svg new file mode 100644 index 0000000000..702500be40 --- /dev/null +++ b/3.26.2-scylla/_static/img/icons/icon-getting-started.svg @@ -0,0 +1 @@ + diff --git a/3.26.2-scylla/_static/img/icons/icon-glossary.svg b/3.26.2-scylla/_static/img/icons/icon-glossary.svg new file mode 100644 index 0000000000..e8329c2afe --- /dev/null +++ b/3.26.2-scylla/_static/img/icons/icon-glossary.svg @@ -0,0 +1 @@ + diff --git a/3.26.2-scylla/_static/img/icons/icon-home.svg b/3.26.2-scylla/_static/img/icons/icon-home.svg new file mode 100644 index 0000000000..f0b9c25419 --- /dev/null +++ b/3.26.2-scylla/_static/img/icons/icon-home.svg @@ -0,0 +1 @@ + diff --git a/3.26.2-scylla/_static/img/icons/icon-infoworld.svg b/3.26.2-scylla/_static/img/icons/icon-infoworld.svg new file mode 100644 index 0000000000..906e87279c --- /dev/null +++ b/3.26.2-scylla/_static/img/icons/icon-infoworld.svg @@ -0,0 +1 @@ +icon-infoworld diff --git a/3.26.2-scylla/_static/img/icons/icon-integrations.svg b/3.26.2-scylla/_static/img/icons/icon-integrations.svg new file mode 100644 index 0000000000..1ef0920d49 --- /dev/null +++ b/3.26.2-scylla/_static/img/icons/icon-integrations.svg @@ -0,0 +1 @@ + diff --git a/3.26.2-scylla/_static/img/icons/icon-knowledge-base.svg b/3.26.2-scylla/_static/img/icons/icon-knowledge-base.svg new file mode 100644 index 0000000000..884451270d --- /dev/null +++ b/3.26.2-scylla/_static/img/icons/icon-knowledge-base.svg @@ -0,0 +1 @@ + diff --git a/3.26.2-scylla/_static/img/icons/icon-less.svg b/3.26.2-scylla/_static/img/icons/icon-less.svg new file mode 100644 index 0000000000..3094127dec --- /dev/null +++ b/3.26.2-scylla/_static/img/icons/icon-less.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/3.26.2-scylla/_static/img/icons/icon-live-test.svg b/3.26.2-scylla/_static/img/icons/icon-live-test.svg new file mode 100644 index 0000000000..dcb5916c26 --- /dev/null +++ b/3.26.2-scylla/_static/img/icons/icon-live-test.svg @@ -0,0 +1 @@ +icon-live-test diff --git a/3.26.2-scylla/_static/img/icons/icon-mail-list.svg b/3.26.2-scylla/_static/img/icons/icon-mail-list.svg new file mode 100644 index 0000000000..0e6192a352 --- /dev/null +++ b/3.26.2-scylla/_static/img/icons/icon-mail-list.svg @@ -0,0 +1 @@ + diff --git a/3.26.2-scylla/_static/img/icons/icon-manager.svg b/3.26.2-scylla/_static/img/icons/icon-manager.svg new file mode 100644 index 0000000000..02b4e425be --- /dev/null +++ b/3.26.2-scylla/_static/img/icons/icon-manager.svg @@ -0,0 +1 @@ +icon-manager diff --git a/3.26.2-scylla/_static/img/icons/icon-memory-management.svg b/3.26.2-scylla/_static/img/icons/icon-memory-management.svg new file mode 100644 index 0000000000..e34eb4504f --- /dev/null +++ b/3.26.2-scylla/_static/img/icons/icon-memory-management.svg @@ -0,0 +1 @@ +icon-memory-management diff --git a/3.26.2-scylla/_static/img/icons/icon-modeling.svg b/3.26.2-scylla/_static/img/icons/icon-modeling.svg new file mode 100644 index 0000000000..97fa3a0e21 --- /dev/null +++ b/3.26.2-scylla/_static/img/icons/icon-modeling.svg @@ -0,0 +1 @@ + diff --git a/3.26.2-scylla/_static/img/icons/icon-monitoring.svg b/3.26.2-scylla/_static/img/icons/icon-monitoring.svg new file mode 100644 index 0000000000..80b3787f66 --- /dev/null +++ b/3.26.2-scylla/_static/img/icons/icon-monitoring.svg @@ -0,0 +1 @@ +icon-monitoring diff --git a/3.26.2-scylla/_static/img/icons/icon-networking.svg b/3.26.2-scylla/_static/img/icons/icon-networking.svg new file mode 100644 index 0000000000..40a3fd5f6f --- /dev/null +++ b/3.26.2-scylla/_static/img/icons/icon-networking.svg @@ -0,0 +1 @@ +icon-networking diff --git a/3.26.2-scylla/_static/img/icons/icon-news.svg b/3.26.2-scylla/_static/img/icons/icon-news.svg new file mode 100644 index 0000000000..a952b59937 --- /dev/null +++ b/3.26.2-scylla/_static/img/icons/icon-news.svg @@ -0,0 +1 @@ +icon-news diff --git a/3.26.2-scylla/_static/img/icons/icon-newsletter.svg b/3.26.2-scylla/_static/img/icons/icon-newsletter.svg new file mode 100644 index 0000000000..5b8d47eb15 --- /dev/null +++ b/3.26.2-scylla/_static/img/icons/icon-newsletter.svg @@ -0,0 +1 @@ +icon-newsletter diff --git a/3.26.2-scylla/_static/img/icons/icon-nsql-guides.svg b/3.26.2-scylla/_static/img/icons/icon-nsql-guides.svg new file mode 100644 index 0000000000..60ebab3795 --- /dev/null +++ b/3.26.2-scylla/_static/img/icons/icon-nsql-guides.svg @@ -0,0 +1 @@ +icon-nsql-guides diff --git a/3.26.2-scylla/_static/img/icons/icon-open-source.svg b/3.26.2-scylla/_static/img/icons/icon-open-source.svg new file mode 100644 index 0000000000..98c2ea7d5b --- /dev/null +++ b/3.26.2-scylla/_static/img/icons/icon-open-source.svg @@ -0,0 +1 @@ +icon-open-source diff --git a/3.26.2-scylla/_static/img/icons/icon-operator.svg b/3.26.2-scylla/_static/img/icons/icon-operator.svg new file mode 100644 index 0000000000..bb7d8d3ea8 --- /dev/null +++ b/3.26.2-scylla/_static/img/icons/icon-operator.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/3.26.2-scylla/_static/img/icons/icon-overview.svg b/3.26.2-scylla/_static/img/icons/icon-overview.svg new file mode 100644 index 0000000000..515c1528a2 --- /dev/null +++ b/3.26.2-scylla/_static/img/icons/icon-overview.svg @@ -0,0 +1 @@ +icon-overview diff --git a/3.26.2-scylla/_static/img/icons/icon-partners.svg b/3.26.2-scylla/_static/img/icons/icon-partners.svg new file mode 100644 index 0000000000..d0146fc497 --- /dev/null +++ b/3.26.2-scylla/_static/img/icons/icon-partners.svg @@ -0,0 +1 @@ +icon-partners diff --git a/3.26.2-scylla/_static/img/icons/icon-plus.svg b/3.26.2-scylla/_static/img/icons/icon-plus.svg new file mode 100644 index 0000000000..5757435085 --- /dev/null +++ b/3.26.2-scylla/_static/img/icons/icon-plus.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/3.26.2-scylla/_static/img/icons/icon-pricing.svg b/3.26.2-scylla/_static/img/icons/icon-pricing.svg new file mode 100644 index 0000000000..74b01db168 --- /dev/null +++ b/3.26.2-scylla/_static/img/icons/icon-pricing.svg @@ -0,0 +1 @@ +icon-pricing$ diff --git a/3.26.2-scylla/_static/img/icons/icon-release-notes.svg b/3.26.2-scylla/_static/img/icons/icon-release-notes.svg new file mode 100644 index 0000000000..80c490c7b0 --- /dev/null +++ b/3.26.2-scylla/_static/img/icons/icon-release-notes.svg @@ -0,0 +1 @@ +icon-release-notes diff --git a/3.26.2-scylla/_static/img/icons/icon-resource-center.svg b/3.26.2-scylla/_static/img/icons/icon-resource-center.svg new file mode 100644 index 0000000000..6e3ab08e79 --- /dev/null +++ b/3.26.2-scylla/_static/img/icons/icon-resource-center.svg @@ -0,0 +1 @@ +icon-ressource-center diff --git a/3.26.2-scylla/_static/img/icons/icon-roadmap.svg b/3.26.2-scylla/_static/img/icons/icon-roadmap.svg new file mode 100644 index 0000000000..c8cbf67c8c --- /dev/null +++ b/3.26.2-scylla/_static/img/icons/icon-roadmap.svg @@ -0,0 +1 @@ +icon-roadmap-4 diff --git a/3.26.2-scylla/_static/img/icons/icon-search.svg b/3.26.2-scylla/_static/img/icons/icon-search.svg new file mode 100644 index 0000000000..81aae93eef --- /dev/null +++ b/3.26.2-scylla/_static/img/icons/icon-search.svg @@ -0,0 +1,4 @@ + + + + diff --git a/3.26.2-scylla/_static/img/icons/icon-slack.svg b/3.26.2-scylla/_static/img/icons/icon-slack.svg new file mode 100644 index 0000000000..fc164ea1e7 --- /dev/null +++ b/3.26.2-scylla/_static/img/icons/icon-slack.svg @@ -0,0 +1 @@ + diff --git a/3.26.2-scylla/_static/img/icons/icon-stack-overflow.svg b/3.26.2-scylla/_static/img/icons/icon-stack-overflow.svg new file mode 100644 index 0000000000..bebe9b8274 --- /dev/null +++ b/3.26.2-scylla/_static/img/icons/icon-stack-overflow.svg @@ -0,0 +1,4 @@ + + + + diff --git a/3.26.2-scylla/_static/img/icons/icon-summit.svg b/3.26.2-scylla/_static/img/icons/icon-summit.svg new file mode 100644 index 0000000000..4b900bd0c0 --- /dev/null +++ b/3.26.2-scylla/_static/img/icons/icon-summit.svg @@ -0,0 +1 @@ + diff --git a/3.26.2-scylla/_static/img/icons/icon-support.svg b/3.26.2-scylla/_static/img/icons/icon-support.svg new file mode 100644 index 0000000000..a4228b34e8 --- /dev/null +++ b/3.26.2-scylla/_static/img/icons/icon-support.svg @@ -0,0 +1 @@ +icon-support diff --git a/3.26.2-scylla/_static/img/icons/icon-tech-talks.svg b/3.26.2-scylla/_static/img/icons/icon-tech-talks.svg new file mode 100644 index 0000000000..df42b5522b --- /dev/null +++ b/3.26.2-scylla/_static/img/icons/icon-tech-talks.svg @@ -0,0 +1 @@ +icon-tech-talks diff --git a/3.26.2-scylla/_static/img/icons/icon-testing.svg b/3.26.2-scylla/_static/img/icons/icon-testing.svg new file mode 100644 index 0000000000..2fe54efdbc --- /dev/null +++ b/3.26.2-scylla/_static/img/icons/icon-testing.svg @@ -0,0 +1 @@ +icon-testing diff --git a/3.26.2-scylla/_static/img/icons/icon-thumbs-down.svg b/3.26.2-scylla/_static/img/icons/icon-thumbs-down.svg new file mode 100644 index 0000000000..3e7bcd6d90 --- /dev/null +++ b/3.26.2-scylla/_static/img/icons/icon-thumbs-down.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/3.26.2-scylla/_static/img/icons/icon-thumbs-up.svg b/3.26.2-scylla/_static/img/icons/icon-thumbs-up.svg new file mode 100644 index 0000000000..226c44d853 --- /dev/null +++ b/3.26.2-scylla/_static/img/icons/icon-thumbs-up.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/3.26.2-scylla/_static/img/icons/icon-tip.svg b/3.26.2-scylla/_static/img/icons/icon-tip.svg new file mode 100644 index 0000000000..bf7aa6af84 --- /dev/null +++ b/3.26.2-scylla/_static/img/icons/icon-tip.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/3.26.2-scylla/_static/img/icons/icon-training.svg b/3.26.2-scylla/_static/img/icons/icon-training.svg new file mode 100644 index 0000000000..08b95a88ed --- /dev/null +++ b/3.26.2-scylla/_static/img/icons/icon-training.svg @@ -0,0 +1 @@ +icon-training diff --git a/3.26.2-scylla/_static/img/icons/icon-triangle-down.svg b/3.26.2-scylla/_static/img/icons/icon-triangle-down.svg new file mode 100644 index 0000000000..e8ae088106 --- /dev/null +++ b/3.26.2-scylla/_static/img/icons/icon-triangle-down.svg @@ -0,0 +1,3 @@ + + + diff --git a/3.26.2-scylla/_static/img/icons/icon-university.svg b/3.26.2-scylla/_static/img/icons/icon-university.svg new file mode 100644 index 0000000000..f7547ab959 --- /dev/null +++ b/3.26.2-scylla/_static/img/icons/icon-university.svg @@ -0,0 +1 @@ +icon-university diff --git a/3.26.2-scylla/_static/img/icons/icon-users-blog.svg b/3.26.2-scylla/_static/img/icons/icon-users-blog.svg new file mode 100644 index 0000000000..47e56cddcf --- /dev/null +++ b/3.26.2-scylla/_static/img/icons/icon-users-blog.svg @@ -0,0 +1 @@ +icon-users-blog diff --git a/3.26.2-scylla/_static/img/icons/icon-warning.svg b/3.26.2-scylla/_static/img/icons/icon-warning.svg new file mode 100644 index 0000000000..e4b1d40331 --- /dev/null +++ b/3.26.2-scylla/_static/img/icons/icon-warning.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/3.26.2-scylla/_static/img/icons/icon-webinars.svg b/3.26.2-scylla/_static/img/icons/icon-webinars.svg new file mode 100644 index 0000000000..5e9f5cd427 --- /dev/null +++ b/3.26.2-scylla/_static/img/icons/icon-webinars.svg @@ -0,0 +1 @@ +icon-webinars diff --git a/3.26.2-scylla/_static/img/icons/icon-whitepapers.svg b/3.26.2-scylla/_static/img/icons/icon-whitepapers.svg new file mode 100644 index 0000000000..3351e51d23 --- /dev/null +++ b/3.26.2-scylla/_static/img/icons/icon-whitepapers.svg @@ -0,0 +1 @@ +icon-whitepapers diff --git a/3.26.2-scylla/_static/img/icons/icon-workshop.svg b/3.26.2-scylla/_static/img/icons/icon-workshop.svg new file mode 100644 index 0000000000..5206e58e98 --- /dev/null +++ b/3.26.2-scylla/_static/img/icons/icon-workshop.svg @@ -0,0 +1 @@ + diff --git a/3.26.2-scylla/_static/img/logo-docs.svg b/3.26.2-scylla/_static/img/logo-docs.svg new file mode 100644 index 0000000000..4fff669cb6 --- /dev/null +++ b/3.26.2-scylla/_static/img/logo-docs.svg @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/3.26.2-scylla/_static/img/logo-scylla-horizontal-RGB.svg b/3.26.2-scylla/_static/img/logo-scylla-horizontal-RGB.svg new file mode 100644 index 0000000000..b5022d7c4d --- /dev/null +++ b/3.26.2-scylla/_static/img/logo-scylla-horizontal-RGB.svg @@ -0,0 +1,74 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/3.26.2-scylla/_static/img/mascots/404.jpg b/3.26.2-scylla/_static/img/mascots/404.jpg new file mode 100644 index 0000000000..769fa0889f Binary files /dev/null and b/3.26.2-scylla/_static/img/mascots/404.jpg differ diff --git a/3.26.2-scylla/_static/img/mascots/scylla-3monsters.png b/3.26.2-scylla/_static/img/mascots/scylla-3monsters.png new file mode 100644 index 0000000000..7c06d01674 Binary files /dev/null and b/3.26.2-scylla/_static/img/mascots/scylla-3monsters.png differ diff --git a/3.26.2-scylla/_static/img/mascots/scylla-advisor-crystal.png b/3.26.2-scylla/_static/img/mascots/scylla-advisor-crystal.png new file mode 100644 index 0000000000..d33fddd62f Binary files /dev/null and b/3.26.2-scylla/_static/img/mascots/scylla-advisor-crystal.png differ diff --git a/3.26.2-scylla/_static/img/mascots/scylla-alternator.svg b/3.26.2-scylla/_static/img/mascots/scylla-alternator.svg new file mode 100644 index 0000000000..0462f893d5 --- /dev/null +++ b/3.26.2-scylla/_static/img/mascots/scylla-alternator.svg @@ -0,0 +1 @@ +scylla-alternator diff --git a/3.26.2-scylla/_static/img/mascots/scylla-cloud.svg b/3.26.2-scylla/_static/img/mascots/scylla-cloud.svg new file mode 100644 index 0000000000..a6c6a26fc9 --- /dev/null +++ b/3.26.2-scylla/_static/img/mascots/scylla-cloud.svg @@ -0,0 +1 @@ +scylla-cloud diff --git a/3.26.2-scylla/_static/img/mascots/scylla-computer-3-monsters.png b/3.26.2-scylla/_static/img/mascots/scylla-computer-3-monsters.png new file mode 100644 index 0000000000..d0368a7027 Binary files /dev/null and b/3.26.2-scylla/_static/img/mascots/scylla-computer-3-monsters.png differ diff --git a/3.26.2-scylla/_static/img/mascots/scylla-computer-headset.png b/3.26.2-scylla/_static/img/mascots/scylla-computer-headset.png new file mode 100644 index 0000000000..0cdadaa216 Binary files /dev/null and b/3.26.2-scylla/_static/img/mascots/scylla-computer-headset.png differ diff --git a/3.26.2-scylla/_static/img/mascots/scylla-cup-number-one.png b/3.26.2-scylla/_static/img/mascots/scylla-cup-number-one.png new file mode 100644 index 0000000000..e889f4e368 Binary files /dev/null and b/3.26.2-scylla/_static/img/mascots/scylla-cup-number-one.png differ diff --git a/3.26.2-scylla/_static/img/mascots/scylla-docs.svg b/3.26.2-scylla/_static/img/mascots/scylla-docs.svg new file mode 100644 index 0000000000..a5bce950c2 --- /dev/null +++ b/3.26.2-scylla/_static/img/mascots/scylla-docs.svg @@ -0,0 +1 @@ +scylla-docs diff --git a/3.26.2-scylla/_static/img/mascots/scylla-drivers.svg b/3.26.2-scylla/_static/img/mascots/scylla-drivers.svg new file mode 100644 index 0000000000..6012e71679 --- /dev/null +++ b/3.26.2-scylla/_static/img/mascots/scylla-drivers.svg @@ -0,0 +1 @@ +scylla-manager diff --git a/3.26.2-scylla/_static/img/mascots/scylla-enterprise.svg b/3.26.2-scylla/_static/img/mascots/scylla-enterprise.svg new file mode 100644 index 0000000000..a1aa0b46ac --- /dev/null +++ b/3.26.2-scylla/_static/img/mascots/scylla-enterprise.svg @@ -0,0 +1 @@ +scylla-enterprise diff --git a/3.26.2-scylla/_static/img/mascots/scylla-forklift-boxes.png b/3.26.2-scylla/_static/img/mascots/scylla-forklift-boxes.png new file mode 100644 index 0000000000..f64c29e6c7 Binary files /dev/null and b/3.26.2-scylla/_static/img/mascots/scylla-forklift-boxes.png differ diff --git a/3.26.2-scylla/_static/img/mascots/scylla-forklift-migration.png b/3.26.2-scylla/_static/img/mascots/scylla-forklift-migration.png new file mode 100644 index 0000000000..d2f645c645 Binary files /dev/null and b/3.26.2-scylla/_static/img/mascots/scylla-forklift-migration.png differ diff --git a/3.26.2-scylla/_static/img/mascots/scylla-gear.png b/3.26.2-scylla/_static/img/mascots/scylla-gear.png new file mode 100644 index 0000000000..0f53b26afa Binary files /dev/null and b/3.26.2-scylla/_static/img/mascots/scylla-gear.png differ diff --git a/3.26.2-scylla/_static/img/mascots/scylla-hardhat.png b/3.26.2-scylla/_static/img/mascots/scylla-hardhat.png new file mode 100644 index 0000000000..630f2d9094 Binary files /dev/null and b/3.26.2-scylla/_static/img/mascots/scylla-hardhat.png differ diff --git a/3.26.2-scylla/_static/img/mascots/scylla-headband.png b/3.26.2-scylla/_static/img/mascots/scylla-headband.png new file mode 100644 index 0000000000..c87abe684d Binary files /dev/null and b/3.26.2-scylla/_static/img/mascots/scylla-headband.png differ diff --git a/3.26.2-scylla/_static/img/mascots/scylla-headset.png b/3.26.2-scylla/_static/img/mascots/scylla-headset.png new file mode 100644 index 0000000000..ba52cd223d Binary files /dev/null and b/3.26.2-scylla/_static/img/mascots/scylla-headset.png differ diff --git a/3.26.2-scylla/_static/img/mascots/scylla-hearts.png b/3.26.2-scylla/_static/img/mascots/scylla-hearts.png new file mode 100644 index 0000000000..cef08c8654 Binary files /dev/null and b/3.26.2-scylla/_static/img/mascots/scylla-hearts.png differ diff --git a/3.26.2-scylla/_static/img/mascots/scylla-looking-down.png b/3.26.2-scylla/_static/img/mascots/scylla-looking-down.png new file mode 100644 index 0000000000..75cccbfdf1 Binary files /dev/null and b/3.26.2-scylla/_static/img/mascots/scylla-looking-down.png differ diff --git a/3.26.2-scylla/_static/img/mascots/scylla-looking-up.png b/3.26.2-scylla/_static/img/mascots/scylla-looking-up.png new file mode 100644 index 0000000000..6f10405f21 Binary files /dev/null and b/3.26.2-scylla/_static/img/mascots/scylla-looking-up.png differ diff --git a/3.26.2-scylla/_static/img/mascots/scylla-magnifying-glass-fronting.png b/3.26.2-scylla/_static/img/mascots/scylla-magnifying-glass-fronting.png new file mode 100644 index 0000000000..e368cae169 Binary files /dev/null and b/3.26.2-scylla/_static/img/mascots/scylla-magnifying-glass-fronting.png differ diff --git a/3.26.2-scylla/_static/img/mascots/scylla-magnifying-glass.png b/3.26.2-scylla/_static/img/mascots/scylla-magnifying-glass.png new file mode 100644 index 0000000000..74ad669500 Binary files /dev/null and b/3.26.2-scylla/_static/img/mascots/scylla-magnifying-glass.png differ diff --git a/3.26.2-scylla/_static/img/mascots/scylla-manager.svg b/3.26.2-scylla/_static/img/mascots/scylla-manager.svg new file mode 100644 index 0000000000..6ba9ed937c --- /dev/null +++ b/3.26.2-scylla/_static/img/mascots/scylla-manager.svg @@ -0,0 +1 @@ +scylla-manager-2 diff --git a/3.26.2-scylla/_static/img/mascots/scylla-monitor.svg b/3.26.2-scylla/_static/img/mascots/scylla-monitor.svg new file mode 100644 index 0000000000..48bec7dde3 --- /dev/null +++ b/3.26.2-scylla/_static/img/mascots/scylla-monitor.svg @@ -0,0 +1 @@ +scylla-monitor diff --git a/3.26.2-scylla/_static/img/mascots/scylla-movement-fast.png b/3.26.2-scylla/_static/img/mascots/scylla-movement-fast.png new file mode 100644 index 0000000000..956d1dd0e2 Binary files /dev/null and b/3.26.2-scylla/_static/img/mascots/scylla-movement-fast.png differ diff --git a/3.26.2-scylla/_static/img/mascots/scylla-movement.png b/3.26.2-scylla/_static/img/mascots/scylla-movement.png new file mode 100644 index 0000000000..7ee2b04338 Binary files /dev/null and b/3.26.2-scylla/_static/img/mascots/scylla-movement.png differ diff --git a/3.26.2-scylla/_static/img/mascots/scylla-onpremise.png b/3.26.2-scylla/_static/img/mascots/scylla-onpremise.png new file mode 100644 index 0000000000..3b2dc8f1a2 Binary files /dev/null and b/3.26.2-scylla/_static/img/mascots/scylla-onpremise.png differ diff --git a/3.26.2-scylla/_static/img/mascots/scylla-opensource.svg b/3.26.2-scylla/_static/img/mascots/scylla-opensource.svg new file mode 100644 index 0000000000..299e9cb995 --- /dev/null +++ b/3.26.2-scylla/_static/img/mascots/scylla-opensource.svg @@ -0,0 +1 @@ +Plan de travail 1 diff --git a/3.26.2-scylla/_static/img/mascots/scylla-operator.svg b/3.26.2-scylla/_static/img/mascots/scylla-operator.svg new file mode 100644 index 0000000000..655a450b2a --- /dev/null +++ b/3.26.2-scylla/_static/img/mascots/scylla-operator.svg @@ -0,0 +1 @@ +scylla-operator diff --git a/3.26.2-scylla/_static/img/mascots/scylla-plugin.png b/3.26.2-scylla/_static/img/mascots/scylla-plugin.png new file mode 100644 index 0000000000..b28dc857cc Binary files /dev/null and b/3.26.2-scylla/_static/img/mascots/scylla-plugin.png differ diff --git a/3.26.2-scylla/_static/img/mascots/scylla-release-mascot.png b/3.26.2-scylla/_static/img/mascots/scylla-release-mascot.png new file mode 100644 index 0000000000..09342ac687 Binary files /dev/null and b/3.26.2-scylla/_static/img/mascots/scylla-release-mascot.png differ diff --git a/3.26.2-scylla/_static/img/mascots/scylla-repair.png b/3.26.2-scylla/_static/img/mascots/scylla-repair.png new file mode 100644 index 0000000000..9b4c613e70 Binary files /dev/null and b/3.26.2-scylla/_static/img/mascots/scylla-repair.png differ diff --git a/3.26.2-scylla/_static/img/mascots/scylla-server.png b/3.26.2-scylla/_static/img/mascots/scylla-server.png new file mode 100644 index 0000000000..96dc785298 Binary files /dev/null and b/3.26.2-scylla/_static/img/mascots/scylla-server.png differ diff --git a/3.26.2-scylla/_static/img/mascots/scylla-sleeping.png b/3.26.2-scylla/_static/img/mascots/scylla-sleeping.png new file mode 100644 index 0000000000..f88598e05a Binary files /dev/null and b/3.26.2-scylla/_static/img/mascots/scylla-sleeping.png differ diff --git a/3.26.2-scylla/_static/img/mascots/scylla-tall-measure.png b/3.26.2-scylla/_static/img/mascots/scylla-tall-measure.png new file mode 100644 index 0000000000..6f0ca146c0 Binary files /dev/null and b/3.26.2-scylla/_static/img/mascots/scylla-tall-measure.png differ diff --git a/3.26.2-scylla/_static/img/mascots/scylla-university.png b/3.26.2-scylla/_static/img/mascots/scylla-university.png new file mode 100644 index 0000000000..b3d0621193 Binary files /dev/null and b/3.26.2-scylla/_static/img/mascots/scylla-university.png differ diff --git a/3.26.2-scylla/_static/img/mascots/scylla-weights.png b/3.26.2-scylla/_static/img/mascots/scylla-weights.png new file mode 100644 index 0000000000..b070bb022c Binary files /dev/null and b/3.26.2-scylla/_static/img/mascots/scylla-weights.png differ diff --git a/3.26.2-scylla/_static/img/mascots/scylla-window-cleaning.png b/3.26.2-scylla/_static/img/mascots/scylla-window-cleaning.png new file mode 100644 index 0000000000..6a8b16a6b4 Binary files /dev/null and b/3.26.2-scylla/_static/img/mascots/scylla-window-cleaning.png differ diff --git a/3.26.2-scylla/_static/img/mascots/scylla-with-computer-2.png b/3.26.2-scylla/_static/img/mascots/scylla-with-computer-2.png new file mode 100644 index 0000000000..f3b8b2984f Binary files /dev/null and b/3.26.2-scylla/_static/img/mascots/scylla-with-computer-2.png differ diff --git a/3.26.2-scylla/_static/img/mascots/scylla-with-computer.png b/3.26.2-scylla/_static/img/mascots/scylla-with-computer.png new file mode 100644 index 0000000000..b38a6fbbe0 Binary files /dev/null and b/3.26.2-scylla/_static/img/mascots/scylla-with-computer.png differ diff --git a/3.26.2-scylla/_static/img/mascots/scylla-with-linux.png b/3.26.2-scylla/_static/img/mascots/scylla-with-linux.png new file mode 100644 index 0000000000..954bf13bc2 Binary files /dev/null and b/3.26.2-scylla/_static/img/mascots/scylla-with-linux.png differ diff --git a/3.26.2-scylla/_static/img/mascots/scylla-writting.png b/3.26.2-scylla/_static/img/mascots/scylla-writting.png new file mode 100644 index 0000000000..d35a13d380 Binary files /dev/null and b/3.26.2-scylla/_static/img/mascots/scylla-writting.png differ diff --git a/3.26.2-scylla/_static/img/menu.svg b/3.26.2-scylla/_static/img/menu.svg new file mode 100644 index 0000000000..30ea1d901e --- /dev/null +++ b/3.26.2-scylla/_static/img/menu.svg @@ -0,0 +1,3 @@ + + + diff --git a/3.26.2-scylla/_static/jquery-3.5.1.js b/3.26.2-scylla/_static/jquery-3.5.1.js new file mode 100644 index 0000000000..50937333b9 --- /dev/null +++ b/3.26.2-scylla/_static/jquery-3.5.1.js @@ -0,0 +1,10872 @@ +/*! + * jQuery JavaScript Library v3.5.1 + * https://jquery.com/ + * + * Includes Sizzle.js + * https://sizzlejs.com/ + * + * Copyright JS Foundation and other contributors + * Released under the MIT license + * https://jquery.org/license + * + * Date: 2020-05-04T22:49Z + */ +( function( global, factory ) { + + "use strict"; + + if ( typeof module === "object" && typeof module.exports === "object" ) { + + // For CommonJS and CommonJS-like environments where a proper `window` + // is present, execute the factory and get jQuery. + // For environments that do not have a `window` with a `document` + // (such as Node.js), expose a factory as module.exports. + // This accentuates the need for the creation of a real `window`. + // e.g. var jQuery = require("jquery")(window); + // See ticket #14549 for more info. + module.exports = global.document ? + factory( global, true ) : + function( w ) { + if ( !w.document ) { + throw new Error( "jQuery requires a window with a document" ); + } + return factory( w ); + }; + } else { + factory( global ); + } + +// Pass this if window is not defined yet +} )( typeof window !== "undefined" ? window : this, function( window, noGlobal ) { + +// Edge <= 12 - 13+, Firefox <=18 - 45+, IE 10 - 11, Safari 5.1 - 9+, iOS 6 - 9.1 +// throw exceptions when non-strict code (e.g., ASP.NET 4.5) accesses strict mode +// arguments.callee.caller (trac-13335). But as of jQuery 3.0 (2016), strict mode should be common +// enough that all such attempts are guarded in a try block. +"use strict"; + +var arr = []; + +var getProto = Object.getPrototypeOf; + +var slice = arr.slice; + +var flat = arr.flat ? function( array ) { + return arr.flat.call( array ); +} : function( array ) { + return arr.concat.apply( [], array ); +}; + + +var push = arr.push; + +var indexOf = arr.indexOf; + +var class2type = {}; + +var toString = class2type.toString; + +var hasOwn = class2type.hasOwnProperty; + +var fnToString = hasOwn.toString; + +var ObjectFunctionString = fnToString.call( Object ); + +var support = {}; + +var isFunction = function isFunction( obj ) { + + // Support: Chrome <=57, Firefox <=52 + // In some browsers, typeof returns "function" for HTML elements + // (i.e., `typeof document.createElement( "object" ) === "function"`). + // We don't want to classify *any* DOM node as a function. + return typeof obj === "function" && typeof obj.nodeType !== "number"; + }; + + +var isWindow = function isWindow( obj ) { + return obj != null && obj === obj.window; + }; + + +var document = window.document; + + + + var preservedScriptAttributes = { + type: true, + src: true, + nonce: true, + noModule: true + }; + + function DOMEval( code, node, doc ) { + doc = doc || document; + + var i, val, + script = doc.createElement( "script" ); + + script.text = code; + if ( node ) { + for ( i in preservedScriptAttributes ) { + + // Support: Firefox 64+, Edge 18+ + // Some browsers don't support the "nonce" property on scripts. + // On the other hand, just using `getAttribute` is not enough as + // the `nonce` attribute is reset to an empty string whenever it + // becomes browsing-context connected. + // See https://github.com/whatwg/html/issues/2369 + // See https://html.spec.whatwg.org/#nonce-attributes + // The `node.getAttribute` check was added for the sake of + // `jQuery.globalEval` so that it can fake a nonce-containing node + // via an object. + val = node[ i ] || node.getAttribute && node.getAttribute( i ); + if ( val ) { + script.setAttribute( i, val ); + } + } + } + doc.head.appendChild( script ).parentNode.removeChild( script ); + } + + +function toType( obj ) { + if ( obj == null ) { + return obj + ""; + } + + // Support: Android <=2.3 only (functionish RegExp) + return typeof obj === "object" || typeof obj === "function" ? + class2type[ toString.call( obj ) ] || "object" : + typeof obj; +} +/* global Symbol */ +// Defining this global in .eslintrc.json would create a danger of using the global +// unguarded in another place, it seems safer to define global only for this module + + + +var + version = "3.5.1", + + // Define a local copy of jQuery + jQuery = function( selector, context ) { + + // The jQuery object is actually just the init constructor 'enhanced' + // Need init if jQuery is called (just allow error to be thrown if not included) + return new jQuery.fn.init( selector, context ); + }; + +jQuery.fn = jQuery.prototype = { + + // The current version of jQuery being used + jquery: version, + + constructor: jQuery, + + // The default length of a jQuery object is 0 + length: 0, + + toArray: function() { + return slice.call( this ); + }, + + // Get the Nth element in the matched element set OR + // Get the whole matched element set as a clean array + get: function( num ) { + + // Return all the elements in a clean array + if ( num == null ) { + return slice.call( this ); + } + + // Return just the one element from the set + return num < 0 ? this[ num + this.length ] : this[ num ]; + }, + + // Take an array of elements and push it onto the stack + // (returning the new matched element set) + pushStack: function( elems ) { + + // Build a new jQuery matched element set + var ret = jQuery.merge( this.constructor(), elems ); + + // Add the old object onto the stack (as a reference) + ret.prevObject = this; + + // Return the newly-formed element set + return ret; + }, + + // Execute a callback for every element in the matched set. + each: function( callback ) { + return jQuery.each( this, callback ); + }, + + map: function( callback ) { + return this.pushStack( jQuery.map( this, function( elem, i ) { + return callback.call( elem, i, elem ); + } ) ); + }, + + slice: function() { + return this.pushStack( slice.apply( this, arguments ) ); + }, + + first: function() { + return this.eq( 0 ); + }, + + last: function() { + return this.eq( -1 ); + }, + + even: function() { + return this.pushStack( jQuery.grep( this, function( _elem, i ) { + return ( i + 1 ) % 2; + } ) ); + }, + + odd: function() { + return this.pushStack( jQuery.grep( this, function( _elem, i ) { + return i % 2; + } ) ); + }, + + eq: function( i ) { + var len = this.length, + j = +i + ( i < 0 ? len : 0 ); + return this.pushStack( j >= 0 && j < len ? [ this[ j ] ] : [] ); + }, + + end: function() { + return this.prevObject || this.constructor(); + }, + + // For internal use only. + // Behaves like an Array's method, not like a jQuery method. + push: push, + sort: arr.sort, + splice: arr.splice +}; + +jQuery.extend = jQuery.fn.extend = function() { + var options, name, src, copy, copyIsArray, clone, + target = arguments[ 0 ] || {}, + i = 1, + length = arguments.length, + deep = false; + + // Handle a deep copy situation + if ( typeof target === "boolean" ) { + deep = target; + + // Skip the boolean and the target + target = arguments[ i ] || {}; + i++; + } + + // Handle case when target is a string or something (possible in deep copy) + if ( typeof target !== "object" && !isFunction( target ) ) { + target = {}; + } + + // Extend jQuery itself if only one argument is passed + if ( i === length ) { + target = this; + i--; + } + + for ( ; i < length; i++ ) { + + // Only deal with non-null/undefined values + if ( ( options = arguments[ i ] ) != null ) { + + // Extend the base object + for ( name in options ) { + copy = options[ name ]; + + // Prevent Object.prototype pollution + // Prevent never-ending loop + if ( name === "__proto__" || target === copy ) { + continue; + } + + // Recurse if we're merging plain objects or arrays + if ( deep && copy && ( jQuery.isPlainObject( copy ) || + ( copyIsArray = Array.isArray( copy ) ) ) ) { + src = target[ name ]; + + // Ensure proper type for the source value + if ( copyIsArray && !Array.isArray( src ) ) { + clone = []; + } else if ( !copyIsArray && !jQuery.isPlainObject( src ) ) { + clone = {}; + } else { + clone = src; + } + copyIsArray = false; + + // Never move original objects, clone them + target[ name ] = jQuery.extend( deep, clone, copy ); + + // Don't bring in undefined values + } else if ( copy !== undefined ) { + target[ name ] = copy; + } + } + } + } + + // Return the modified object + return target; +}; + +jQuery.extend( { + + // Unique for each copy of jQuery on the page + expando: "jQuery" + ( version + Math.random() ).replace( /\D/g, "" ), + + // Assume jQuery is ready without the ready module + isReady: true, + + error: function( msg ) { + throw new Error( msg ); + }, + + noop: function() {}, + + isPlainObject: function( obj ) { + var proto, Ctor; + + // Detect obvious negatives + // Use toString instead of jQuery.type to catch host objects + if ( !obj || toString.call( obj ) !== "[object Object]" ) { + return false; + } + + proto = getProto( obj ); + + // Objects with no prototype (e.g., `Object.create( null )`) are plain + if ( !proto ) { + return true; + } + + // Objects with prototype are plain iff they were constructed by a global Object function + Ctor = hasOwn.call( proto, "constructor" ) && proto.constructor; + return typeof Ctor === "function" && fnToString.call( Ctor ) === ObjectFunctionString; + }, + + isEmptyObject: function( obj ) { + var name; + + for ( name in obj ) { + return false; + } + return true; + }, + + // Evaluates a script in a provided context; falls back to the global one + // if not specified. + globalEval: function( code, options, doc ) { + DOMEval( code, { nonce: options && options.nonce }, doc ); + }, + + each: function( obj, callback ) { + var length, i = 0; + + if ( isArrayLike( obj ) ) { + length = obj.length; + for ( ; i < length; i++ ) { + if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) { + break; + } + } + } else { + for ( i in obj ) { + if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) { + break; + } + } + } + + return obj; + }, + + // results is for internal usage only + makeArray: function( arr, results ) { + var ret = results || []; + + if ( arr != null ) { + if ( isArrayLike( Object( arr ) ) ) { + jQuery.merge( ret, + typeof arr === "string" ? + [ arr ] : arr + ); + } else { + push.call( ret, arr ); + } + } + + return ret; + }, + + inArray: function( elem, arr, i ) { + return arr == null ? -1 : indexOf.call( arr, elem, i ); + }, + + // Support: Android <=4.0 only, PhantomJS 1 only + // push.apply(_, arraylike) throws on ancient WebKit + merge: function( first, second ) { + var len = +second.length, + j = 0, + i = first.length; + + for ( ; j < len; j++ ) { + first[ i++ ] = second[ j ]; + } + + first.length = i; + + return first; + }, + + grep: function( elems, callback, invert ) { + var callbackInverse, + matches = [], + i = 0, + length = elems.length, + callbackExpect = !invert; + + // Go through the array, only saving the items + // that pass the validator function + for ( ; i < length; i++ ) { + callbackInverse = !callback( elems[ i ], i ); + if ( callbackInverse !== callbackExpect ) { + matches.push( elems[ i ] ); + } + } + + return matches; + }, + + // arg is for internal usage only + map: function( elems, callback, arg ) { + var length, value, + i = 0, + ret = []; + + // Go through the array, translating each of the items to their new values + if ( isArrayLike( elems ) ) { + length = elems.length; + for ( ; i < length; i++ ) { + value = callback( elems[ i ], i, arg ); + + if ( value != null ) { + ret.push( value ); + } + } + + // Go through every key on the object, + } else { + for ( i in elems ) { + value = callback( elems[ i ], i, arg ); + + if ( value != null ) { + ret.push( value ); + } + } + } + + // Flatten any nested arrays + return flat( ret ); + }, + + // A global GUID counter for objects + guid: 1, + + // jQuery.support is not used in Core but other projects attach their + // properties to it so it needs to exist. + support: support +} ); + +if ( typeof Symbol === "function" ) { + jQuery.fn[ Symbol.iterator ] = arr[ Symbol.iterator ]; +} + +// Populate the class2type map +jQuery.each( "Boolean Number String Function Array Date RegExp Object Error Symbol".split( " " ), +function( _i, name ) { + class2type[ "[object " + name + "]" ] = name.toLowerCase(); +} ); + +function isArrayLike( obj ) { + + // Support: real iOS 8.2 only (not reproducible in simulator) + // `in` check used to prevent JIT error (gh-2145) + // hasOwn isn't used here due to false negatives + // regarding Nodelist length in IE + var length = !!obj && "length" in obj && obj.length, + type = toType( obj ); + + if ( isFunction( obj ) || isWindow( obj ) ) { + return false; + } + + return type === "array" || length === 0 || + typeof length === "number" && length > 0 && ( length - 1 ) in obj; +} +var Sizzle = +/*! + * Sizzle CSS Selector Engine v2.3.5 + * https://sizzlejs.com/ + * + * Copyright JS Foundation and other contributors + * Released under the MIT license + * https://js.foundation/ + * + * Date: 2020-03-14 + */ +( function( window ) { +var i, + support, + Expr, + getText, + isXML, + tokenize, + compile, + select, + outermostContext, + sortInput, + hasDuplicate, + + // Local document vars + setDocument, + document, + docElem, + documentIsHTML, + rbuggyQSA, + rbuggyMatches, + matches, + contains, + + // Instance-specific data + expando = "sizzle" + 1 * new Date(), + preferredDoc = window.document, + dirruns = 0, + done = 0, + classCache = createCache(), + tokenCache = createCache(), + compilerCache = createCache(), + nonnativeSelectorCache = createCache(), + sortOrder = function( a, b ) { + if ( a === b ) { + hasDuplicate = true; + } + return 0; + }, + + // Instance methods + hasOwn = ( {} ).hasOwnProperty, + arr = [], + pop = arr.pop, + pushNative = arr.push, + push = arr.push, + slice = arr.slice, + + // Use a stripped-down indexOf as it's faster than native + // https://jsperf.com/thor-indexof-vs-for/5 + indexOf = function( list, elem ) { + var i = 0, + len = list.length; + for ( ; i < len; i++ ) { + if ( list[ i ] === elem ) { + return i; + } + } + return -1; + }, + + booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|" + + "ismap|loop|multiple|open|readonly|required|scoped", + + // Regular expressions + + // http://www.w3.org/TR/css3-selectors/#whitespace + whitespace = "[\\x20\\t\\r\\n\\f]", + + // https://www.w3.org/TR/css-syntax-3/#ident-token-diagram + identifier = "(?:\\\\[\\da-fA-F]{1,6}" + whitespace + + "?|\\\\[^\\r\\n\\f]|[\\w-]|[^\0-\\x7f])+", + + // Attribute selectors: http://www.w3.org/TR/selectors/#attribute-selectors + attributes = "\\[" + whitespace + "*(" + identifier + ")(?:" + whitespace + + + // Operator (capture 2) + "*([*^$|!~]?=)" + whitespace + + + // "Attribute values must be CSS identifiers [capture 5] + // or strings [capture 3 or capture 4]" + "*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|(" + identifier + "))|)" + + whitespace + "*\\]", + + pseudos = ":(" + identifier + ")(?:\\((" + + + // To reduce the number of selectors needing tokenize in the preFilter, prefer arguments: + // 1. quoted (capture 3; capture 4 or capture 5) + "('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|" + + + // 2. simple (capture 6) + "((?:\\\\.|[^\\\\()[\\]]|" + attributes + ")*)|" + + + // 3. anything else (capture 2) + ".*" + + ")\\)|)", + + // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter + rwhitespace = new RegExp( whitespace + "+", "g" ), + rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + + whitespace + "+$", "g" ), + + rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ), + rcombinators = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + + "*" ), + rdescend = new RegExp( whitespace + "|>" ), + + rpseudo = new RegExp( pseudos ), + ridentifier = new RegExp( "^" + identifier + "$" ), + + matchExpr = { + "ID": new RegExp( "^#(" + identifier + ")" ), + "CLASS": new RegExp( "^\\.(" + identifier + ")" ), + "TAG": new RegExp( "^(" + identifier + "|[*])" ), + "ATTR": new RegExp( "^" + attributes ), + "PSEUDO": new RegExp( "^" + pseudos ), + "CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + + whitespace + "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + + whitespace + "*(\\d+)|))" + whitespace + "*\\)|)", "i" ), + "bool": new RegExp( "^(?:" + booleans + ")$", "i" ), + + // For use in libraries implementing .is() + // We use this for POS matching in `select` + "needsContext": new RegExp( "^" + whitespace + + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" + whitespace + + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" ) + }, + + rhtml = /HTML$/i, + rinputs = /^(?:input|select|textarea|button)$/i, + rheader = /^h\d$/i, + + rnative = /^[^{]+\{\s*\[native \w/, + + // Easily-parseable/retrievable ID or TAG or CLASS selectors + rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/, + + rsibling = /[+~]/, + + // CSS escapes + // http://www.w3.org/TR/CSS21/syndata.html#escaped-characters + runescape = new RegExp( "\\\\[\\da-fA-F]{1,6}" + whitespace + "?|\\\\([^\\r\\n\\f])", "g" ), + funescape = function( escape, nonHex ) { + var high = "0x" + escape.slice( 1 ) - 0x10000; + + return nonHex ? + + // Strip the backslash prefix from a non-hex escape sequence + nonHex : + + // Replace a hexadecimal escape sequence with the encoded Unicode code point + // Support: IE <=11+ + // For values outside the Basic Multilingual Plane (BMP), manually construct a + // surrogate pair + high < 0 ? + String.fromCharCode( high + 0x10000 ) : + String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 ); + }, + + // CSS string/identifier serialization + // https://drafts.csswg.org/cssom/#common-serializing-idioms + rcssescape = /([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g, + fcssescape = function( ch, asCodePoint ) { + if ( asCodePoint ) { + + // U+0000 NULL becomes U+FFFD REPLACEMENT CHARACTER + if ( ch === "\0" ) { + return "\uFFFD"; + } + + // Control characters and (dependent upon position) numbers get escaped as code points + return ch.slice( 0, -1 ) + "\\" + + ch.charCodeAt( ch.length - 1 ).toString( 16 ) + " "; + } + + // Other potentially-special ASCII characters get backslash-escaped + return "\\" + ch; + }, + + // Used for iframes + // See setDocument() + // Removing the function wrapper causes a "Permission Denied" + // error in IE + unloadHandler = function() { + setDocument(); + }, + + inDisabledFieldset = addCombinator( + function( elem ) { + return elem.disabled === true && elem.nodeName.toLowerCase() === "fieldset"; + }, + { dir: "parentNode", next: "legend" } + ); + +// Optimize for push.apply( _, NodeList ) +try { + push.apply( + ( arr = slice.call( preferredDoc.childNodes ) ), + preferredDoc.childNodes + ); + + // Support: Android<4.0 + // Detect silently failing push.apply + // eslint-disable-next-line no-unused-expressions + arr[ preferredDoc.childNodes.length ].nodeType; +} catch ( e ) { + push = { apply: arr.length ? + + // Leverage slice if possible + function( target, els ) { + pushNative.apply( target, slice.call( els ) ); + } : + + // Support: IE<9 + // Otherwise append directly + function( target, els ) { + var j = target.length, + i = 0; + + // Can't trust NodeList.length + while ( ( target[ j++ ] = els[ i++ ] ) ) {} + target.length = j - 1; + } + }; +} + +function Sizzle( selector, context, results, seed ) { + var m, i, elem, nid, match, groups, newSelector, + newContext = context && context.ownerDocument, + + // nodeType defaults to 9, since context defaults to document + nodeType = context ? context.nodeType : 9; + + results = results || []; + + // Return early from calls with invalid selector or context + if ( typeof selector !== "string" || !selector || + nodeType !== 1 && nodeType !== 9 && nodeType !== 11 ) { + + return results; + } + + // Try to shortcut find operations (as opposed to filters) in HTML documents + if ( !seed ) { + setDocument( context ); + context = context || document; + + if ( documentIsHTML ) { + + // If the selector is sufficiently simple, try using a "get*By*" DOM method + // (excepting DocumentFragment context, where the methods don't exist) + if ( nodeType !== 11 && ( match = rquickExpr.exec( selector ) ) ) { + + // ID selector + if ( ( m = match[ 1 ] ) ) { + + // Document context + if ( nodeType === 9 ) { + if ( ( elem = context.getElementById( m ) ) ) { + + // Support: IE, Opera, Webkit + // TODO: identify versions + // getElementById can match elements by name instead of ID + if ( elem.id === m ) { + results.push( elem ); + return results; + } + } else { + return results; + } + + // Element context + } else { + + // Support: IE, Opera, Webkit + // TODO: identify versions + // getElementById can match elements by name instead of ID + if ( newContext && ( elem = newContext.getElementById( m ) ) && + contains( context, elem ) && + elem.id === m ) { + + results.push( elem ); + return results; + } + } + + // Type selector + } else if ( match[ 2 ] ) { + push.apply( results, context.getElementsByTagName( selector ) ); + return results; + + // Class selector + } else if ( ( m = match[ 3 ] ) && support.getElementsByClassName && + context.getElementsByClassName ) { + + push.apply( results, context.getElementsByClassName( m ) ); + return results; + } + } + + // Take advantage of querySelectorAll + if ( support.qsa && + !nonnativeSelectorCache[ selector + " " ] && + ( !rbuggyQSA || !rbuggyQSA.test( selector ) ) && + + // Support: IE 8 only + // Exclude object elements + ( nodeType !== 1 || context.nodeName.toLowerCase() !== "object" ) ) { + + newSelector = selector; + newContext = context; + + // qSA considers elements outside a scoping root when evaluating child or + // descendant combinators, which is not what we want. + // In such cases, we work around the behavior by prefixing every selector in the + // list with an ID selector referencing the scope context. + // The technique has to be used as well when a leading combinator is used + // as such selectors are not recognized by querySelectorAll. + // Thanks to Andrew Dupont for this technique. + if ( nodeType === 1 && + ( rdescend.test( selector ) || rcombinators.test( selector ) ) ) { + + // Expand context for sibling selectors + newContext = rsibling.test( selector ) && testContext( context.parentNode ) || + context; + + // We can use :scope instead of the ID hack if the browser + // supports it & if we're not changing the context. + if ( newContext !== context || !support.scope ) { + + // Capture the context ID, setting it first if necessary + if ( ( nid = context.getAttribute( "id" ) ) ) { + nid = nid.replace( rcssescape, fcssescape ); + } else { + context.setAttribute( "id", ( nid = expando ) ); + } + } + + // Prefix every selector in the list + groups = tokenize( selector ); + i = groups.length; + while ( i-- ) { + groups[ i ] = ( nid ? "#" + nid : ":scope" ) + " " + + toSelector( groups[ i ] ); + } + newSelector = groups.join( "," ); + } + + try { + push.apply( results, + newContext.querySelectorAll( newSelector ) + ); + return results; + } catch ( qsaError ) { + nonnativeSelectorCache( selector, true ); + } finally { + if ( nid === expando ) { + context.removeAttribute( "id" ); + } + } + } + } + } + + // All others + return select( selector.replace( rtrim, "$1" ), context, results, seed ); +} + +/** + * Create key-value caches of limited size + * @returns {function(string, object)} Returns the Object data after storing it on itself with + * property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength) + * deleting the oldest entry + */ +function createCache() { + var keys = []; + + function cache( key, value ) { + + // Use (key + " ") to avoid collision with native prototype properties (see Issue #157) + if ( keys.push( key + " " ) > Expr.cacheLength ) { + + // Only keep the most recent entries + delete cache[ keys.shift() ]; + } + return ( cache[ key + " " ] = value ); + } + return cache; +} + +/** + * Mark a function for special use by Sizzle + * @param {Function} fn The function to mark + */ +function markFunction( fn ) { + fn[ expando ] = true; + return fn; +} + +/** + * Support testing using an element + * @param {Function} fn Passed the created element and returns a boolean result + */ +function assert( fn ) { + var el = document.createElement( "fieldset" ); + + try { + return !!fn( el ); + } catch ( e ) { + return false; + } finally { + + // Remove from its parent by default + if ( el.parentNode ) { + el.parentNode.removeChild( el ); + } + + // release memory in IE + el = null; + } +} + +/** + * Adds the same handler for all of the specified attrs + * @param {String} attrs Pipe-separated list of attributes + * @param {Function} handler The method that will be applied + */ +function addHandle( attrs, handler ) { + var arr = attrs.split( "|" ), + i = arr.length; + + while ( i-- ) { + Expr.attrHandle[ arr[ i ] ] = handler; + } +} + +/** + * Checks document order of two siblings + * @param {Element} a + * @param {Element} b + * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b + */ +function siblingCheck( a, b ) { + var cur = b && a, + diff = cur && a.nodeType === 1 && b.nodeType === 1 && + a.sourceIndex - b.sourceIndex; + + // Use IE sourceIndex if available on both nodes + if ( diff ) { + return diff; + } + + // Check if b follows a + if ( cur ) { + while ( ( cur = cur.nextSibling ) ) { + if ( cur === b ) { + return -1; + } + } + } + + return a ? 1 : -1; +} + +/** + * Returns a function to use in pseudos for input types + * @param {String} type + */ +function createInputPseudo( type ) { + return function( elem ) { + var name = elem.nodeName.toLowerCase(); + return name === "input" && elem.type === type; + }; +} + +/** + * Returns a function to use in pseudos for buttons + * @param {String} type + */ +function createButtonPseudo( type ) { + return function( elem ) { + var name = elem.nodeName.toLowerCase(); + return ( name === "input" || name === "button" ) && elem.type === type; + }; +} + +/** + * Returns a function to use in pseudos for :enabled/:disabled + * @param {Boolean} disabled true for :disabled; false for :enabled + */ +function createDisabledPseudo( disabled ) { + + // Known :disabled false positives: fieldset[disabled] > legend:nth-of-type(n+2) :can-disable + return function( elem ) { + + // Only certain elements can match :enabled or :disabled + // https://html.spec.whatwg.org/multipage/scripting.html#selector-enabled + // https://html.spec.whatwg.org/multipage/scripting.html#selector-disabled + if ( "form" in elem ) { + + // Check for inherited disabledness on relevant non-disabled elements: + // * listed form-associated elements in a disabled fieldset + // https://html.spec.whatwg.org/multipage/forms.html#category-listed + // https://html.spec.whatwg.org/multipage/forms.html#concept-fe-disabled + // * option elements in a disabled optgroup + // https://html.spec.whatwg.org/multipage/forms.html#concept-option-disabled + // All such elements have a "form" property. + if ( elem.parentNode && elem.disabled === false ) { + + // Option elements defer to a parent optgroup if present + if ( "label" in elem ) { + if ( "label" in elem.parentNode ) { + return elem.parentNode.disabled === disabled; + } else { + return elem.disabled === disabled; + } + } + + // Support: IE 6 - 11 + // Use the isDisabled shortcut property to check for disabled fieldset ancestors + return elem.isDisabled === disabled || + + // Where there is no isDisabled, check manually + /* jshint -W018 */ + elem.isDisabled !== !disabled && + inDisabledFieldset( elem ) === disabled; + } + + return elem.disabled === disabled; + + // Try to winnow out elements that can't be disabled before trusting the disabled property. + // Some victims get caught in our net (label, legend, menu, track), but it shouldn't + // even exist on them, let alone have a boolean value. + } else if ( "label" in elem ) { + return elem.disabled === disabled; + } + + // Remaining elements are neither :enabled nor :disabled + return false; + }; +} + +/** + * Returns a function to use in pseudos for positionals + * @param {Function} fn + */ +function createPositionalPseudo( fn ) { + return markFunction( function( argument ) { + argument = +argument; + return markFunction( function( seed, matches ) { + var j, + matchIndexes = fn( [], seed.length, argument ), + i = matchIndexes.length; + + // Match elements found at the specified indexes + while ( i-- ) { + if ( seed[ ( j = matchIndexes[ i ] ) ] ) { + seed[ j ] = !( matches[ j ] = seed[ j ] ); + } + } + } ); + } ); +} + +/** + * Checks a node for validity as a Sizzle context + * @param {Element|Object=} context + * @returns {Element|Object|Boolean} The input node if acceptable, otherwise a falsy value + */ +function testContext( context ) { + return context && typeof context.getElementsByTagName !== "undefined" && context; +} + +// Expose support vars for convenience +support = Sizzle.support = {}; + +/** + * Detects XML nodes + * @param {Element|Object} elem An element or a document + * @returns {Boolean} True iff elem is a non-HTML XML node + */ +isXML = Sizzle.isXML = function( elem ) { + var namespace = elem.namespaceURI, + docElem = ( elem.ownerDocument || elem ).documentElement; + + // Support: IE <=8 + // Assume HTML when documentElement doesn't yet exist, such as inside loading iframes + // https://bugs.jquery.com/ticket/4833 + return !rhtml.test( namespace || docElem && docElem.nodeName || "HTML" ); +}; + +/** + * Sets document-related variables once based on the current document + * @param {Element|Object} [doc] An element or document object to use to set the document + * @returns {Object} Returns the current document + */ +setDocument = Sizzle.setDocument = function( node ) { + var hasCompare, subWindow, + doc = node ? node.ownerDocument || node : preferredDoc; + + // Return early if doc is invalid or already selected + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( doc == document || doc.nodeType !== 9 || !doc.documentElement ) { + return document; + } + + // Update global variables + document = doc; + docElem = document.documentElement; + documentIsHTML = !isXML( document ); + + // Support: IE 9 - 11+, Edge 12 - 18+ + // Accessing iframe documents after unload throws "permission denied" errors (jQuery #13936) + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( preferredDoc != document && + ( subWindow = document.defaultView ) && subWindow.top !== subWindow ) { + + // Support: IE 11, Edge + if ( subWindow.addEventListener ) { + subWindow.addEventListener( "unload", unloadHandler, false ); + + // Support: IE 9 - 10 only + } else if ( subWindow.attachEvent ) { + subWindow.attachEvent( "onunload", unloadHandler ); + } + } + + // Support: IE 8 - 11+, Edge 12 - 18+, Chrome <=16 - 25 only, Firefox <=3.6 - 31 only, + // Safari 4 - 5 only, Opera <=11.6 - 12.x only + // IE/Edge & older browsers don't support the :scope pseudo-class. + // Support: Safari 6.0 only + // Safari 6.0 supports :scope but it's an alias of :root there. + support.scope = assert( function( el ) { + docElem.appendChild( el ).appendChild( document.createElement( "div" ) ); + return typeof el.querySelectorAll !== "undefined" && + !el.querySelectorAll( ":scope fieldset div" ).length; + } ); + + /* Attributes + ---------------------------------------------------------------------- */ + + // Support: IE<8 + // Verify that getAttribute really returns attributes and not properties + // (excepting IE8 booleans) + support.attributes = assert( function( el ) { + el.className = "i"; + return !el.getAttribute( "className" ); + } ); + + /* getElement(s)By* + ---------------------------------------------------------------------- */ + + // Check if getElementsByTagName("*") returns only elements + support.getElementsByTagName = assert( function( el ) { + el.appendChild( document.createComment( "" ) ); + return !el.getElementsByTagName( "*" ).length; + } ); + + // Support: IE<9 + support.getElementsByClassName = rnative.test( document.getElementsByClassName ); + + // Support: IE<10 + // Check if getElementById returns elements by name + // The broken getElementById methods don't pick up programmatically-set names, + // so use a roundabout getElementsByName test + support.getById = assert( function( el ) { + docElem.appendChild( el ).id = expando; + return !document.getElementsByName || !document.getElementsByName( expando ).length; + } ); + + // ID filter and find + if ( support.getById ) { + Expr.filter[ "ID" ] = function( id ) { + var attrId = id.replace( runescape, funescape ); + return function( elem ) { + return elem.getAttribute( "id" ) === attrId; + }; + }; + Expr.find[ "ID" ] = function( id, context ) { + if ( typeof context.getElementById !== "undefined" && documentIsHTML ) { + var elem = context.getElementById( id ); + return elem ? [ elem ] : []; + } + }; + } else { + Expr.filter[ "ID" ] = function( id ) { + var attrId = id.replace( runescape, funescape ); + return function( elem ) { + var node = typeof elem.getAttributeNode !== "undefined" && + elem.getAttributeNode( "id" ); + return node && node.value === attrId; + }; + }; + + // Support: IE 6 - 7 only + // getElementById is not reliable as a find shortcut + Expr.find[ "ID" ] = function( id, context ) { + if ( typeof context.getElementById !== "undefined" && documentIsHTML ) { + var node, i, elems, + elem = context.getElementById( id ); + + if ( elem ) { + + // Verify the id attribute + node = elem.getAttributeNode( "id" ); + if ( node && node.value === id ) { + return [ elem ]; + } + + // Fall back on getElementsByName + elems = context.getElementsByName( id ); + i = 0; + while ( ( elem = elems[ i++ ] ) ) { + node = elem.getAttributeNode( "id" ); + if ( node && node.value === id ) { + return [ elem ]; + } + } + } + + return []; + } + }; + } + + // Tag + Expr.find[ "TAG" ] = support.getElementsByTagName ? + function( tag, context ) { + if ( typeof context.getElementsByTagName !== "undefined" ) { + return context.getElementsByTagName( tag ); + + // DocumentFragment nodes don't have gEBTN + } else if ( support.qsa ) { + return context.querySelectorAll( tag ); + } + } : + + function( tag, context ) { + var elem, + tmp = [], + i = 0, + + // By happy coincidence, a (broken) gEBTN appears on DocumentFragment nodes too + results = context.getElementsByTagName( tag ); + + // Filter out possible comments + if ( tag === "*" ) { + while ( ( elem = results[ i++ ] ) ) { + if ( elem.nodeType === 1 ) { + tmp.push( elem ); + } + } + + return tmp; + } + return results; + }; + + // Class + Expr.find[ "CLASS" ] = support.getElementsByClassName && function( className, context ) { + if ( typeof context.getElementsByClassName !== "undefined" && documentIsHTML ) { + return context.getElementsByClassName( className ); + } + }; + + /* QSA/matchesSelector + ---------------------------------------------------------------------- */ + + // QSA and matchesSelector support + + // matchesSelector(:active) reports false when true (IE9/Opera 11.5) + rbuggyMatches = []; + + // qSa(:focus) reports false when true (Chrome 21) + // We allow this because of a bug in IE8/9 that throws an error + // whenever `document.activeElement` is accessed on an iframe + // So, we allow :focus to pass through QSA all the time to avoid the IE error + // See https://bugs.jquery.com/ticket/13378 + rbuggyQSA = []; + + if ( ( support.qsa = rnative.test( document.querySelectorAll ) ) ) { + + // Build QSA regex + // Regex strategy adopted from Diego Perini + assert( function( el ) { + + var input; + + // Select is set to empty string on purpose + // This is to test IE's treatment of not explicitly + // setting a boolean content attribute, + // since its presence should be enough + // https://bugs.jquery.com/ticket/12359 + docElem.appendChild( el ).innerHTML = "" + + ""; + + // Support: IE8, Opera 11-12.16 + // Nothing should be selected when empty strings follow ^= or $= or *= + // The test attribute must be unknown in Opera but "safe" for WinRT + // https://msdn.microsoft.com/en-us/library/ie/hh465388.aspx#attribute_section + if ( el.querySelectorAll( "[msallowcapture^='']" ).length ) { + rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:''|\"\")" ); + } + + // Support: IE8 + // Boolean attributes and "value" are not treated correctly + if ( !el.querySelectorAll( "[selected]" ).length ) { + rbuggyQSA.push( "\\[" + whitespace + "*(?:value|" + booleans + ")" ); + } + + // Support: Chrome<29, Android<4.4, Safari<7.0+, iOS<7.0+, PhantomJS<1.9.8+ + if ( !el.querySelectorAll( "[id~=" + expando + "-]" ).length ) { + rbuggyQSA.push( "~=" ); + } + + // Support: IE 11+, Edge 15 - 18+ + // IE 11/Edge don't find elements on a `[name='']` query in some cases. + // Adding a temporary attribute to the document before the selection works + // around the issue. + // Interestingly, IE 10 & older don't seem to have the issue. + input = document.createElement( "input" ); + input.setAttribute( "name", "" ); + el.appendChild( input ); + if ( !el.querySelectorAll( "[name='']" ).length ) { + rbuggyQSA.push( "\\[" + whitespace + "*name" + whitespace + "*=" + + whitespace + "*(?:''|\"\")" ); + } + + // Webkit/Opera - :checked should return selected option elements + // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked + // IE8 throws error here and will not see later tests + if ( !el.querySelectorAll( ":checked" ).length ) { + rbuggyQSA.push( ":checked" ); + } + + // Support: Safari 8+, iOS 8+ + // https://bugs.webkit.org/show_bug.cgi?id=136851 + // In-page `selector#id sibling-combinator selector` fails + if ( !el.querySelectorAll( "a#" + expando + "+*" ).length ) { + rbuggyQSA.push( ".#.+[+~]" ); + } + + // Support: Firefox <=3.6 - 5 only + // Old Firefox doesn't throw on a badly-escaped identifier. + el.querySelectorAll( "\\\f" ); + rbuggyQSA.push( "[\\r\\n\\f]" ); + } ); + + assert( function( el ) { + el.innerHTML = "" + + ""; + + // Support: Windows 8 Native Apps + // The type and name attributes are restricted during .innerHTML assignment + var input = document.createElement( "input" ); + input.setAttribute( "type", "hidden" ); + el.appendChild( input ).setAttribute( "name", "D" ); + + // Support: IE8 + // Enforce case-sensitivity of name attribute + if ( el.querySelectorAll( "[name=d]" ).length ) { + rbuggyQSA.push( "name" + whitespace + "*[*^$|!~]?=" ); + } + + // FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled) + // IE8 throws error here and will not see later tests + if ( el.querySelectorAll( ":enabled" ).length !== 2 ) { + rbuggyQSA.push( ":enabled", ":disabled" ); + } + + // Support: IE9-11+ + // IE's :disabled selector does not pick up the children of disabled fieldsets + docElem.appendChild( el ).disabled = true; + if ( el.querySelectorAll( ":disabled" ).length !== 2 ) { + rbuggyQSA.push( ":enabled", ":disabled" ); + } + + // Support: Opera 10 - 11 only + // Opera 10-11 does not throw on post-comma invalid pseudos + el.querySelectorAll( "*,:x" ); + rbuggyQSA.push( ",.*:" ); + } ); + } + + if ( ( support.matchesSelector = rnative.test( ( matches = docElem.matches || + docElem.webkitMatchesSelector || + docElem.mozMatchesSelector || + docElem.oMatchesSelector || + docElem.msMatchesSelector ) ) ) ) { + + assert( function( el ) { + + // Check to see if it's possible to do matchesSelector + // on a disconnected node (IE 9) + support.disconnectedMatch = matches.call( el, "*" ); + + // This should fail with an exception + // Gecko does not error, returns false instead + matches.call( el, "[s!='']:x" ); + rbuggyMatches.push( "!=", pseudos ); + } ); + } + + rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join( "|" ) ); + rbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join( "|" ) ); + + /* Contains + ---------------------------------------------------------------------- */ + hasCompare = rnative.test( docElem.compareDocumentPosition ); + + // Element contains another + // Purposefully self-exclusive + // As in, an element does not contain itself + contains = hasCompare || rnative.test( docElem.contains ) ? + function( a, b ) { + var adown = a.nodeType === 9 ? a.documentElement : a, + bup = b && b.parentNode; + return a === bup || !!( bup && bup.nodeType === 1 && ( + adown.contains ? + adown.contains( bup ) : + a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16 + ) ); + } : + function( a, b ) { + if ( b ) { + while ( ( b = b.parentNode ) ) { + if ( b === a ) { + return true; + } + } + } + return false; + }; + + /* Sorting + ---------------------------------------------------------------------- */ + + // Document order sorting + sortOrder = hasCompare ? + function( a, b ) { + + // Flag for duplicate removal + if ( a === b ) { + hasDuplicate = true; + return 0; + } + + // Sort on method existence if only one input has compareDocumentPosition + var compare = !a.compareDocumentPosition - !b.compareDocumentPosition; + if ( compare ) { + return compare; + } + + // Calculate position if both inputs belong to the same document + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + compare = ( a.ownerDocument || a ) == ( b.ownerDocument || b ) ? + a.compareDocumentPosition( b ) : + + // Otherwise we know they are disconnected + 1; + + // Disconnected nodes + if ( compare & 1 || + ( !support.sortDetached && b.compareDocumentPosition( a ) === compare ) ) { + + // Choose the first element that is related to our preferred document + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( a == document || a.ownerDocument == preferredDoc && + contains( preferredDoc, a ) ) { + return -1; + } + + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( b == document || b.ownerDocument == preferredDoc && + contains( preferredDoc, b ) ) { + return 1; + } + + // Maintain original order + return sortInput ? + ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) : + 0; + } + + return compare & 4 ? -1 : 1; + } : + function( a, b ) { + + // Exit early if the nodes are identical + if ( a === b ) { + hasDuplicate = true; + return 0; + } + + var cur, + i = 0, + aup = a.parentNode, + bup = b.parentNode, + ap = [ a ], + bp = [ b ]; + + // Parentless nodes are either documents or disconnected + if ( !aup || !bup ) { + + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + /* eslint-disable eqeqeq */ + return a == document ? -1 : + b == document ? 1 : + /* eslint-enable eqeqeq */ + aup ? -1 : + bup ? 1 : + sortInput ? + ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) : + 0; + + // If the nodes are siblings, we can do a quick check + } else if ( aup === bup ) { + return siblingCheck( a, b ); + } + + // Otherwise we need full lists of their ancestors for comparison + cur = a; + while ( ( cur = cur.parentNode ) ) { + ap.unshift( cur ); + } + cur = b; + while ( ( cur = cur.parentNode ) ) { + bp.unshift( cur ); + } + + // Walk down the tree looking for a discrepancy + while ( ap[ i ] === bp[ i ] ) { + i++; + } + + return i ? + + // Do a sibling check if the nodes have a common ancestor + siblingCheck( ap[ i ], bp[ i ] ) : + + // Otherwise nodes in our document sort first + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + /* eslint-disable eqeqeq */ + ap[ i ] == preferredDoc ? -1 : + bp[ i ] == preferredDoc ? 1 : + /* eslint-enable eqeqeq */ + 0; + }; + + return document; +}; + +Sizzle.matches = function( expr, elements ) { + return Sizzle( expr, null, null, elements ); +}; + +Sizzle.matchesSelector = function( elem, expr ) { + setDocument( elem ); + + if ( support.matchesSelector && documentIsHTML && + !nonnativeSelectorCache[ expr + " " ] && + ( !rbuggyMatches || !rbuggyMatches.test( expr ) ) && + ( !rbuggyQSA || !rbuggyQSA.test( expr ) ) ) { + + try { + var ret = matches.call( elem, expr ); + + // IE 9's matchesSelector returns false on disconnected nodes + if ( ret || support.disconnectedMatch || + + // As well, disconnected nodes are said to be in a document + // fragment in IE 9 + elem.document && elem.document.nodeType !== 11 ) { + return ret; + } + } catch ( e ) { + nonnativeSelectorCache( expr, true ); + } + } + + return Sizzle( expr, document, null, [ elem ] ).length > 0; +}; + +Sizzle.contains = function( context, elem ) { + + // Set document vars if needed + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( ( context.ownerDocument || context ) != document ) { + setDocument( context ); + } + return contains( context, elem ); +}; + +Sizzle.attr = function( elem, name ) { + + // Set document vars if needed + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( ( elem.ownerDocument || elem ) != document ) { + setDocument( elem ); + } + + var fn = Expr.attrHandle[ name.toLowerCase() ], + + // Don't get fooled by Object.prototype properties (jQuery #13807) + val = fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ? + fn( elem, name, !documentIsHTML ) : + undefined; + + return val !== undefined ? + val : + support.attributes || !documentIsHTML ? + elem.getAttribute( name ) : + ( val = elem.getAttributeNode( name ) ) && val.specified ? + val.value : + null; +}; + +Sizzle.escape = function( sel ) { + return ( sel + "" ).replace( rcssescape, fcssescape ); +}; + +Sizzle.error = function( msg ) { + throw new Error( "Syntax error, unrecognized expression: " + msg ); +}; + +/** + * Document sorting and removing duplicates + * @param {ArrayLike} results + */ +Sizzle.uniqueSort = function( results ) { + var elem, + duplicates = [], + j = 0, + i = 0; + + // Unless we *know* we can detect duplicates, assume their presence + hasDuplicate = !support.detectDuplicates; + sortInput = !support.sortStable && results.slice( 0 ); + results.sort( sortOrder ); + + if ( hasDuplicate ) { + while ( ( elem = results[ i++ ] ) ) { + if ( elem === results[ i ] ) { + j = duplicates.push( i ); + } + } + while ( j-- ) { + results.splice( duplicates[ j ], 1 ); + } + } + + // Clear input after sorting to release objects + // See https://github.com/jquery/sizzle/pull/225 + sortInput = null; + + return results; +}; + +/** + * Utility function for retrieving the text value of an array of DOM nodes + * @param {Array|Element} elem + */ +getText = Sizzle.getText = function( elem ) { + var node, + ret = "", + i = 0, + nodeType = elem.nodeType; + + if ( !nodeType ) { + + // If no nodeType, this is expected to be an array + while ( ( node = elem[ i++ ] ) ) { + + // Do not traverse comment nodes + ret += getText( node ); + } + } else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) { + + // Use textContent for elements + // innerText usage removed for consistency of new lines (jQuery #11153) + if ( typeof elem.textContent === "string" ) { + return elem.textContent; + } else { + + // Traverse its children + for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { + ret += getText( elem ); + } + } + } else if ( nodeType === 3 || nodeType === 4 ) { + return elem.nodeValue; + } + + // Do not include comment or processing instruction nodes + + return ret; +}; + +Expr = Sizzle.selectors = { + + // Can be adjusted by the user + cacheLength: 50, + + createPseudo: markFunction, + + match: matchExpr, + + attrHandle: {}, + + find: {}, + + relative: { + ">": { dir: "parentNode", first: true }, + " ": { dir: "parentNode" }, + "+": { dir: "previousSibling", first: true }, + "~": { dir: "previousSibling" } + }, + + preFilter: { + "ATTR": function( match ) { + match[ 1 ] = match[ 1 ].replace( runescape, funescape ); + + // Move the given value to match[3] whether quoted or unquoted + match[ 3 ] = ( match[ 3 ] || match[ 4 ] || + match[ 5 ] || "" ).replace( runescape, funescape ); + + if ( match[ 2 ] === "~=" ) { + match[ 3 ] = " " + match[ 3 ] + " "; + } + + return match.slice( 0, 4 ); + }, + + "CHILD": function( match ) { + + /* matches from matchExpr["CHILD"] + 1 type (only|nth|...) + 2 what (child|of-type) + 3 argument (even|odd|\d*|\d*n([+-]\d+)?|...) + 4 xn-component of xn+y argument ([+-]?\d*n|) + 5 sign of xn-component + 6 x of xn-component + 7 sign of y-component + 8 y of y-component + */ + match[ 1 ] = match[ 1 ].toLowerCase(); + + if ( match[ 1 ].slice( 0, 3 ) === "nth" ) { + + // nth-* requires argument + if ( !match[ 3 ] ) { + Sizzle.error( match[ 0 ] ); + } + + // numeric x and y parameters for Expr.filter.CHILD + // remember that false/true cast respectively to 0/1 + match[ 4 ] = +( match[ 4 ] ? + match[ 5 ] + ( match[ 6 ] || 1 ) : + 2 * ( match[ 3 ] === "even" || match[ 3 ] === "odd" ) ); + match[ 5 ] = +( ( match[ 7 ] + match[ 8 ] ) || match[ 3 ] === "odd" ); + + // other types prohibit arguments + } else if ( match[ 3 ] ) { + Sizzle.error( match[ 0 ] ); + } + + return match; + }, + + "PSEUDO": function( match ) { + var excess, + unquoted = !match[ 6 ] && match[ 2 ]; + + if ( matchExpr[ "CHILD" ].test( match[ 0 ] ) ) { + return null; + } + + // Accept quoted arguments as-is + if ( match[ 3 ] ) { + match[ 2 ] = match[ 4 ] || match[ 5 ] || ""; + + // Strip excess characters from unquoted arguments + } else if ( unquoted && rpseudo.test( unquoted ) && + + // Get excess from tokenize (recursively) + ( excess = tokenize( unquoted, true ) ) && + + // advance to the next closing parenthesis + ( excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length ) ) { + + // excess is a negative index + match[ 0 ] = match[ 0 ].slice( 0, excess ); + match[ 2 ] = unquoted.slice( 0, excess ); + } + + // Return only captures needed by the pseudo filter method (type and argument) + return match.slice( 0, 3 ); + } + }, + + filter: { + + "TAG": function( nodeNameSelector ) { + var nodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase(); + return nodeNameSelector === "*" ? + function() { + return true; + } : + function( elem ) { + return elem.nodeName && elem.nodeName.toLowerCase() === nodeName; + }; + }, + + "CLASS": function( className ) { + var pattern = classCache[ className + " " ]; + + return pattern || + ( pattern = new RegExp( "(^|" + whitespace + + ")" + className + "(" + whitespace + "|$)" ) ) && classCache( + className, function( elem ) { + return pattern.test( + typeof elem.className === "string" && elem.className || + typeof elem.getAttribute !== "undefined" && + elem.getAttribute( "class" ) || + "" + ); + } ); + }, + + "ATTR": function( name, operator, check ) { + return function( elem ) { + var result = Sizzle.attr( elem, name ); + + if ( result == null ) { + return operator === "!="; + } + if ( !operator ) { + return true; + } + + result += ""; + + /* eslint-disable max-len */ + + return operator === "=" ? result === check : + operator === "!=" ? result !== check : + operator === "^=" ? check && result.indexOf( check ) === 0 : + operator === "*=" ? check && result.indexOf( check ) > -1 : + operator === "$=" ? check && result.slice( -check.length ) === check : + operator === "~=" ? ( " " + result.replace( rwhitespace, " " ) + " " ).indexOf( check ) > -1 : + operator === "|=" ? result === check || result.slice( 0, check.length + 1 ) === check + "-" : + false; + /* eslint-enable max-len */ + + }; + }, + + "CHILD": function( type, what, _argument, first, last ) { + var simple = type.slice( 0, 3 ) !== "nth", + forward = type.slice( -4 ) !== "last", + ofType = what === "of-type"; + + return first === 1 && last === 0 ? + + // Shortcut for :nth-*(n) + function( elem ) { + return !!elem.parentNode; + } : + + function( elem, _context, xml ) { + var cache, uniqueCache, outerCache, node, nodeIndex, start, + dir = simple !== forward ? "nextSibling" : "previousSibling", + parent = elem.parentNode, + name = ofType && elem.nodeName.toLowerCase(), + useCache = !xml && !ofType, + diff = false; + + if ( parent ) { + + // :(first|last|only)-(child|of-type) + if ( simple ) { + while ( dir ) { + node = elem; + while ( ( node = node[ dir ] ) ) { + if ( ofType ? + node.nodeName.toLowerCase() === name : + node.nodeType === 1 ) { + + return false; + } + } + + // Reverse direction for :only-* (if we haven't yet done so) + start = dir = type === "only" && !start && "nextSibling"; + } + return true; + } + + start = [ forward ? parent.firstChild : parent.lastChild ]; + + // non-xml :nth-child(...) stores cache data on `parent` + if ( forward && useCache ) { + + // Seek `elem` from a previously-cached index + + // ...in a gzip-friendly way + node = parent; + outerCache = node[ expando ] || ( node[ expando ] = {} ); + + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ node.uniqueID ] || + ( outerCache[ node.uniqueID ] = {} ); + + cache = uniqueCache[ type ] || []; + nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ]; + diff = nodeIndex && cache[ 2 ]; + node = nodeIndex && parent.childNodes[ nodeIndex ]; + + while ( ( node = ++nodeIndex && node && node[ dir ] || + + // Fallback to seeking `elem` from the start + ( diff = nodeIndex = 0 ) || start.pop() ) ) { + + // When found, cache indexes on `parent` and break + if ( node.nodeType === 1 && ++diff && node === elem ) { + uniqueCache[ type ] = [ dirruns, nodeIndex, diff ]; + break; + } + } + + } else { + + // Use previously-cached element index if available + if ( useCache ) { + + // ...in a gzip-friendly way + node = elem; + outerCache = node[ expando ] || ( node[ expando ] = {} ); + + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ node.uniqueID ] || + ( outerCache[ node.uniqueID ] = {} ); + + cache = uniqueCache[ type ] || []; + nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ]; + diff = nodeIndex; + } + + // xml :nth-child(...) + // or :nth-last-child(...) or :nth(-last)?-of-type(...) + if ( diff === false ) { + + // Use the same loop as above to seek `elem` from the start + while ( ( node = ++nodeIndex && node && node[ dir ] || + ( diff = nodeIndex = 0 ) || start.pop() ) ) { + + if ( ( ofType ? + node.nodeName.toLowerCase() === name : + node.nodeType === 1 ) && + ++diff ) { + + // Cache the index of each encountered element + if ( useCache ) { + outerCache = node[ expando ] || + ( node[ expando ] = {} ); + + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ node.uniqueID ] || + ( outerCache[ node.uniqueID ] = {} ); + + uniqueCache[ type ] = [ dirruns, diff ]; + } + + if ( node === elem ) { + break; + } + } + } + } + } + + // Incorporate the offset, then check against cycle size + diff -= last; + return diff === first || ( diff % first === 0 && diff / first >= 0 ); + } + }; + }, + + "PSEUDO": function( pseudo, argument ) { + + // pseudo-class names are case-insensitive + // http://www.w3.org/TR/selectors/#pseudo-classes + // Prioritize by case sensitivity in case custom pseudos are added with uppercase letters + // Remember that setFilters inherits from pseudos + var args, + fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] || + Sizzle.error( "unsupported pseudo: " + pseudo ); + + // The user may use createPseudo to indicate that + // arguments are needed to create the filter function + // just as Sizzle does + if ( fn[ expando ] ) { + return fn( argument ); + } + + // But maintain support for old signatures + if ( fn.length > 1 ) { + args = [ pseudo, pseudo, "", argument ]; + return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ? + markFunction( function( seed, matches ) { + var idx, + matched = fn( seed, argument ), + i = matched.length; + while ( i-- ) { + idx = indexOf( seed, matched[ i ] ); + seed[ idx ] = !( matches[ idx ] = matched[ i ] ); + } + } ) : + function( elem ) { + return fn( elem, 0, args ); + }; + } + + return fn; + } + }, + + pseudos: { + + // Potentially complex pseudos + "not": markFunction( function( selector ) { + + // Trim the selector passed to compile + // to avoid treating leading and trailing + // spaces as combinators + var input = [], + results = [], + matcher = compile( selector.replace( rtrim, "$1" ) ); + + return matcher[ expando ] ? + markFunction( function( seed, matches, _context, xml ) { + var elem, + unmatched = matcher( seed, null, xml, [] ), + i = seed.length; + + // Match elements unmatched by `matcher` + while ( i-- ) { + if ( ( elem = unmatched[ i ] ) ) { + seed[ i ] = !( matches[ i ] = elem ); + } + } + } ) : + function( elem, _context, xml ) { + input[ 0 ] = elem; + matcher( input, null, xml, results ); + + // Don't keep the element (issue #299) + input[ 0 ] = null; + return !results.pop(); + }; + } ), + + "has": markFunction( function( selector ) { + return function( elem ) { + return Sizzle( selector, elem ).length > 0; + }; + } ), + + "contains": markFunction( function( text ) { + text = text.replace( runescape, funescape ); + return function( elem ) { + return ( elem.textContent || getText( elem ) ).indexOf( text ) > -1; + }; + } ), + + // "Whether an element is represented by a :lang() selector + // is based solely on the element's language value + // being equal to the identifier C, + // or beginning with the identifier C immediately followed by "-". + // The matching of C against the element's language value is performed case-insensitively. + // The identifier C does not have to be a valid language name." + // http://www.w3.org/TR/selectors/#lang-pseudo + "lang": markFunction( function( lang ) { + + // lang value must be a valid identifier + if ( !ridentifier.test( lang || "" ) ) { + Sizzle.error( "unsupported lang: " + lang ); + } + lang = lang.replace( runescape, funescape ).toLowerCase(); + return function( elem ) { + var elemLang; + do { + if ( ( elemLang = documentIsHTML ? + elem.lang : + elem.getAttribute( "xml:lang" ) || elem.getAttribute( "lang" ) ) ) { + + elemLang = elemLang.toLowerCase(); + return elemLang === lang || elemLang.indexOf( lang + "-" ) === 0; + } + } while ( ( elem = elem.parentNode ) && elem.nodeType === 1 ); + return false; + }; + } ), + + // Miscellaneous + "target": function( elem ) { + var hash = window.location && window.location.hash; + return hash && hash.slice( 1 ) === elem.id; + }, + + "root": function( elem ) { + return elem === docElem; + }, + + "focus": function( elem ) { + return elem === document.activeElement && + ( !document.hasFocus || document.hasFocus() ) && + !!( elem.type || elem.href || ~elem.tabIndex ); + }, + + // Boolean properties + "enabled": createDisabledPseudo( false ), + "disabled": createDisabledPseudo( true ), + + "checked": function( elem ) { + + // In CSS3, :checked should return both checked and selected elements + // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked + var nodeName = elem.nodeName.toLowerCase(); + return ( nodeName === "input" && !!elem.checked ) || + ( nodeName === "option" && !!elem.selected ); + }, + + "selected": function( elem ) { + + // Accessing this property makes selected-by-default + // options in Safari work properly + if ( elem.parentNode ) { + // eslint-disable-next-line no-unused-expressions + elem.parentNode.selectedIndex; + } + + return elem.selected === true; + }, + + // Contents + "empty": function( elem ) { + + // http://www.w3.org/TR/selectors/#empty-pseudo + // :empty is negated by element (1) or content nodes (text: 3; cdata: 4; entity ref: 5), + // but not by others (comment: 8; processing instruction: 7; etc.) + // nodeType < 6 works because attributes (2) do not appear as children + for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { + if ( elem.nodeType < 6 ) { + return false; + } + } + return true; + }, + + "parent": function( elem ) { + return !Expr.pseudos[ "empty" ]( elem ); + }, + + // Element/input types + "header": function( elem ) { + return rheader.test( elem.nodeName ); + }, + + "input": function( elem ) { + return rinputs.test( elem.nodeName ); + }, + + "button": function( elem ) { + var name = elem.nodeName.toLowerCase(); + return name === "input" && elem.type === "button" || name === "button"; + }, + + "text": function( elem ) { + var attr; + return elem.nodeName.toLowerCase() === "input" && + elem.type === "text" && + + // Support: IE<8 + // New HTML5 attribute values (e.g., "search") appear with elem.type === "text" + ( ( attr = elem.getAttribute( "type" ) ) == null || + attr.toLowerCase() === "text" ); + }, + + // Position-in-collection + "first": createPositionalPseudo( function() { + return [ 0 ]; + } ), + + "last": createPositionalPseudo( function( _matchIndexes, length ) { + return [ length - 1 ]; + } ), + + "eq": createPositionalPseudo( function( _matchIndexes, length, argument ) { + return [ argument < 0 ? argument + length : argument ]; + } ), + + "even": createPositionalPseudo( function( matchIndexes, length ) { + var i = 0; + for ( ; i < length; i += 2 ) { + matchIndexes.push( i ); + } + return matchIndexes; + } ), + + "odd": createPositionalPseudo( function( matchIndexes, length ) { + var i = 1; + for ( ; i < length; i += 2 ) { + matchIndexes.push( i ); + } + return matchIndexes; + } ), + + "lt": createPositionalPseudo( function( matchIndexes, length, argument ) { + var i = argument < 0 ? + argument + length : + argument > length ? + length : + argument; + for ( ; --i >= 0; ) { + matchIndexes.push( i ); + } + return matchIndexes; + } ), + + "gt": createPositionalPseudo( function( matchIndexes, length, argument ) { + var i = argument < 0 ? argument + length : argument; + for ( ; ++i < length; ) { + matchIndexes.push( i ); + } + return matchIndexes; + } ) + } +}; + +Expr.pseudos[ "nth" ] = Expr.pseudos[ "eq" ]; + +// Add button/input type pseudos +for ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) { + Expr.pseudos[ i ] = createInputPseudo( i ); +} +for ( i in { submit: true, reset: true } ) { + Expr.pseudos[ i ] = createButtonPseudo( i ); +} + +// Easy API for creating new setFilters +function setFilters() {} +setFilters.prototype = Expr.filters = Expr.pseudos; +Expr.setFilters = new setFilters(); + +tokenize = Sizzle.tokenize = function( selector, parseOnly ) { + var matched, match, tokens, type, + soFar, groups, preFilters, + cached = tokenCache[ selector + " " ]; + + if ( cached ) { + return parseOnly ? 0 : cached.slice( 0 ); + } + + soFar = selector; + groups = []; + preFilters = Expr.preFilter; + + while ( soFar ) { + + // Comma and first run + if ( !matched || ( match = rcomma.exec( soFar ) ) ) { + if ( match ) { + + // Don't consume trailing commas as valid + soFar = soFar.slice( match[ 0 ].length ) || soFar; + } + groups.push( ( tokens = [] ) ); + } + + matched = false; + + // Combinators + if ( ( match = rcombinators.exec( soFar ) ) ) { + matched = match.shift(); + tokens.push( { + value: matched, + + // Cast descendant combinators to space + type: match[ 0 ].replace( rtrim, " " ) + } ); + soFar = soFar.slice( matched.length ); + } + + // Filters + for ( type in Expr.filter ) { + if ( ( match = matchExpr[ type ].exec( soFar ) ) && ( !preFilters[ type ] || + ( match = preFilters[ type ]( match ) ) ) ) { + matched = match.shift(); + tokens.push( { + value: matched, + type: type, + matches: match + } ); + soFar = soFar.slice( matched.length ); + } + } + + if ( !matched ) { + break; + } + } + + // Return the length of the invalid excess + // if we're just parsing + // Otherwise, throw an error or return tokens + return parseOnly ? + soFar.length : + soFar ? + Sizzle.error( selector ) : + + // Cache the tokens + tokenCache( selector, groups ).slice( 0 ); +}; + +function toSelector( tokens ) { + var i = 0, + len = tokens.length, + selector = ""; + for ( ; i < len; i++ ) { + selector += tokens[ i ].value; + } + return selector; +} + +function addCombinator( matcher, combinator, base ) { + var dir = combinator.dir, + skip = combinator.next, + key = skip || dir, + checkNonElements = base && key === "parentNode", + doneName = done++; + + return combinator.first ? + + // Check against closest ancestor/preceding element + function( elem, context, xml ) { + while ( ( elem = elem[ dir ] ) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + return matcher( elem, context, xml ); + } + } + return false; + } : + + // Check against all ancestor/preceding elements + function( elem, context, xml ) { + var oldCache, uniqueCache, outerCache, + newCache = [ dirruns, doneName ]; + + // We can't set arbitrary data on XML nodes, so they don't benefit from combinator caching + if ( xml ) { + while ( ( elem = elem[ dir ] ) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + if ( matcher( elem, context, xml ) ) { + return true; + } + } + } + } else { + while ( ( elem = elem[ dir ] ) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + outerCache = elem[ expando ] || ( elem[ expando ] = {} ); + + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ elem.uniqueID ] || + ( outerCache[ elem.uniqueID ] = {} ); + + if ( skip && skip === elem.nodeName.toLowerCase() ) { + elem = elem[ dir ] || elem; + } else if ( ( oldCache = uniqueCache[ key ] ) && + oldCache[ 0 ] === dirruns && oldCache[ 1 ] === doneName ) { + + // Assign to newCache so results back-propagate to previous elements + return ( newCache[ 2 ] = oldCache[ 2 ] ); + } else { + + // Reuse newcache so results back-propagate to previous elements + uniqueCache[ key ] = newCache; + + // A match means we're done; a fail means we have to keep checking + if ( ( newCache[ 2 ] = matcher( elem, context, xml ) ) ) { + return true; + } + } + } + } + } + return false; + }; +} + +function elementMatcher( matchers ) { + return matchers.length > 1 ? + function( elem, context, xml ) { + var i = matchers.length; + while ( i-- ) { + if ( !matchers[ i ]( elem, context, xml ) ) { + return false; + } + } + return true; + } : + matchers[ 0 ]; +} + +function multipleContexts( selector, contexts, results ) { + var i = 0, + len = contexts.length; + for ( ; i < len; i++ ) { + Sizzle( selector, contexts[ i ], results ); + } + return results; +} + +function condense( unmatched, map, filter, context, xml ) { + var elem, + newUnmatched = [], + i = 0, + len = unmatched.length, + mapped = map != null; + + for ( ; i < len; i++ ) { + if ( ( elem = unmatched[ i ] ) ) { + if ( !filter || filter( elem, context, xml ) ) { + newUnmatched.push( elem ); + if ( mapped ) { + map.push( i ); + } + } + } + } + + return newUnmatched; +} + +function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) { + if ( postFilter && !postFilter[ expando ] ) { + postFilter = setMatcher( postFilter ); + } + if ( postFinder && !postFinder[ expando ] ) { + postFinder = setMatcher( postFinder, postSelector ); + } + return markFunction( function( seed, results, context, xml ) { + var temp, i, elem, + preMap = [], + postMap = [], + preexisting = results.length, + + // Get initial elements from seed or context + elems = seed || multipleContexts( + selector || "*", + context.nodeType ? [ context ] : context, + [] + ), + + // Prefilter to get matcher input, preserving a map for seed-results synchronization + matcherIn = preFilter && ( seed || !selector ) ? + condense( elems, preMap, preFilter, context, xml ) : + elems, + + matcherOut = matcher ? + + // If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results, + postFinder || ( seed ? preFilter : preexisting || postFilter ) ? + + // ...intermediate processing is necessary + [] : + + // ...otherwise use results directly + results : + matcherIn; + + // Find primary matches + if ( matcher ) { + matcher( matcherIn, matcherOut, context, xml ); + } + + // Apply postFilter + if ( postFilter ) { + temp = condense( matcherOut, postMap ); + postFilter( temp, [], context, xml ); + + // Un-match failing elements by moving them back to matcherIn + i = temp.length; + while ( i-- ) { + if ( ( elem = temp[ i ] ) ) { + matcherOut[ postMap[ i ] ] = !( matcherIn[ postMap[ i ] ] = elem ); + } + } + } + + if ( seed ) { + if ( postFinder || preFilter ) { + if ( postFinder ) { + + // Get the final matcherOut by condensing this intermediate into postFinder contexts + temp = []; + i = matcherOut.length; + while ( i-- ) { + if ( ( elem = matcherOut[ i ] ) ) { + + // Restore matcherIn since elem is not yet a final match + temp.push( ( matcherIn[ i ] = elem ) ); + } + } + postFinder( null, ( matcherOut = [] ), temp, xml ); + } + + // Move matched elements from seed to results to keep them synchronized + i = matcherOut.length; + while ( i-- ) { + if ( ( elem = matcherOut[ i ] ) && + ( temp = postFinder ? indexOf( seed, elem ) : preMap[ i ] ) > -1 ) { + + seed[ temp ] = !( results[ temp ] = elem ); + } + } + } + + // Add elements to results, through postFinder if defined + } else { + matcherOut = condense( + matcherOut === results ? + matcherOut.splice( preexisting, matcherOut.length ) : + matcherOut + ); + if ( postFinder ) { + postFinder( null, results, matcherOut, xml ); + } else { + push.apply( results, matcherOut ); + } + } + } ); +} + +function matcherFromTokens( tokens ) { + var checkContext, matcher, j, + len = tokens.length, + leadingRelative = Expr.relative[ tokens[ 0 ].type ], + implicitRelative = leadingRelative || Expr.relative[ " " ], + i = leadingRelative ? 1 : 0, + + // The foundational matcher ensures that elements are reachable from top-level context(s) + matchContext = addCombinator( function( elem ) { + return elem === checkContext; + }, implicitRelative, true ), + matchAnyContext = addCombinator( function( elem ) { + return indexOf( checkContext, elem ) > -1; + }, implicitRelative, true ), + matchers = [ function( elem, context, xml ) { + var ret = ( !leadingRelative && ( xml || context !== outermostContext ) ) || ( + ( checkContext = context ).nodeType ? + matchContext( elem, context, xml ) : + matchAnyContext( elem, context, xml ) ); + + // Avoid hanging onto element (issue #299) + checkContext = null; + return ret; + } ]; + + for ( ; i < len; i++ ) { + if ( ( matcher = Expr.relative[ tokens[ i ].type ] ) ) { + matchers = [ addCombinator( elementMatcher( matchers ), matcher ) ]; + } else { + matcher = Expr.filter[ tokens[ i ].type ].apply( null, tokens[ i ].matches ); + + // Return special upon seeing a positional matcher + if ( matcher[ expando ] ) { + + // Find the next relative operator (if any) for proper handling + j = ++i; + for ( ; j < len; j++ ) { + if ( Expr.relative[ tokens[ j ].type ] ) { + break; + } + } + return setMatcher( + i > 1 && elementMatcher( matchers ), + i > 1 && toSelector( + + // If the preceding token was a descendant combinator, insert an implicit any-element `*` + tokens + .slice( 0, i - 1 ) + .concat( { value: tokens[ i - 2 ].type === " " ? "*" : "" } ) + ).replace( rtrim, "$1" ), + matcher, + i < j && matcherFromTokens( tokens.slice( i, j ) ), + j < len && matcherFromTokens( ( tokens = tokens.slice( j ) ) ), + j < len && toSelector( tokens ) + ); + } + matchers.push( matcher ); + } + } + + return elementMatcher( matchers ); +} + +function matcherFromGroupMatchers( elementMatchers, setMatchers ) { + var bySet = setMatchers.length > 0, + byElement = elementMatchers.length > 0, + superMatcher = function( seed, context, xml, results, outermost ) { + var elem, j, matcher, + matchedCount = 0, + i = "0", + unmatched = seed && [], + setMatched = [], + contextBackup = outermostContext, + + // We must always have either seed elements or outermost context + elems = seed || byElement && Expr.find[ "TAG" ]( "*", outermost ), + + // Use integer dirruns iff this is the outermost matcher + dirrunsUnique = ( dirruns += contextBackup == null ? 1 : Math.random() || 0.1 ), + len = elems.length; + + if ( outermost ) { + + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + outermostContext = context == document || context || outermost; + } + + // Add elements passing elementMatchers directly to results + // Support: IE<9, Safari + // Tolerate NodeList properties (IE: "length"; Safari: ) matching elements by id + for ( ; i !== len && ( elem = elems[ i ] ) != null; i++ ) { + if ( byElement && elem ) { + j = 0; + + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( !context && elem.ownerDocument != document ) { + setDocument( elem ); + xml = !documentIsHTML; + } + while ( ( matcher = elementMatchers[ j++ ] ) ) { + if ( matcher( elem, context || document, xml ) ) { + results.push( elem ); + break; + } + } + if ( outermost ) { + dirruns = dirrunsUnique; + } + } + + // Track unmatched elements for set filters + if ( bySet ) { + + // They will have gone through all possible matchers + if ( ( elem = !matcher && elem ) ) { + matchedCount--; + } + + // Lengthen the array for every element, matched or not + if ( seed ) { + unmatched.push( elem ); + } + } + } + + // `i` is now the count of elements visited above, and adding it to `matchedCount` + // makes the latter nonnegative. + matchedCount += i; + + // Apply set filters to unmatched elements + // NOTE: This can be skipped if there are no unmatched elements (i.e., `matchedCount` + // equals `i`), unless we didn't visit _any_ elements in the above loop because we have + // no element matchers and no seed. + // Incrementing an initially-string "0" `i` allows `i` to remain a string only in that + // case, which will result in a "00" `matchedCount` that differs from `i` but is also + // numerically zero. + if ( bySet && i !== matchedCount ) { + j = 0; + while ( ( matcher = setMatchers[ j++ ] ) ) { + matcher( unmatched, setMatched, context, xml ); + } + + if ( seed ) { + + // Reintegrate element matches to eliminate the need for sorting + if ( matchedCount > 0 ) { + while ( i-- ) { + if ( !( unmatched[ i ] || setMatched[ i ] ) ) { + setMatched[ i ] = pop.call( results ); + } + } + } + + // Discard index placeholder values to get only actual matches + setMatched = condense( setMatched ); + } + + // Add matches to results + push.apply( results, setMatched ); + + // Seedless set matches succeeding multiple successful matchers stipulate sorting + if ( outermost && !seed && setMatched.length > 0 && + ( matchedCount + setMatchers.length ) > 1 ) { + + Sizzle.uniqueSort( results ); + } + } + + // Override manipulation of globals by nested matchers + if ( outermost ) { + dirruns = dirrunsUnique; + outermostContext = contextBackup; + } + + return unmatched; + }; + + return bySet ? + markFunction( superMatcher ) : + superMatcher; +} + +compile = Sizzle.compile = function( selector, match /* Internal Use Only */ ) { + var i, + setMatchers = [], + elementMatchers = [], + cached = compilerCache[ selector + " " ]; + + if ( !cached ) { + + // Generate a function of recursive functions that can be used to check each element + if ( !match ) { + match = tokenize( selector ); + } + i = match.length; + while ( i-- ) { + cached = matcherFromTokens( match[ i ] ); + if ( cached[ expando ] ) { + setMatchers.push( cached ); + } else { + elementMatchers.push( cached ); + } + } + + // Cache the compiled function + cached = compilerCache( + selector, + matcherFromGroupMatchers( elementMatchers, setMatchers ) + ); + + // Save selector and tokenization + cached.selector = selector; + } + return cached; +}; + +/** + * A low-level selection function that works with Sizzle's compiled + * selector functions + * @param {String|Function} selector A selector or a pre-compiled + * selector function built with Sizzle.compile + * @param {Element} context + * @param {Array} [results] + * @param {Array} [seed] A set of elements to match against + */ +select = Sizzle.select = function( selector, context, results, seed ) { + var i, tokens, token, type, find, + compiled = typeof selector === "function" && selector, + match = !seed && tokenize( ( selector = compiled.selector || selector ) ); + + results = results || []; + + // Try to minimize operations if there is only one selector in the list and no seed + // (the latter of which guarantees us context) + if ( match.length === 1 ) { + + // Reduce context if the leading compound selector is an ID + tokens = match[ 0 ] = match[ 0 ].slice( 0 ); + if ( tokens.length > 2 && ( token = tokens[ 0 ] ).type === "ID" && + context.nodeType === 9 && documentIsHTML && Expr.relative[ tokens[ 1 ].type ] ) { + + context = ( Expr.find[ "ID" ]( token.matches[ 0 ] + .replace( runescape, funescape ), context ) || [] )[ 0 ]; + if ( !context ) { + return results; + + // Precompiled matchers will still verify ancestry, so step up a level + } else if ( compiled ) { + context = context.parentNode; + } + + selector = selector.slice( tokens.shift().value.length ); + } + + // Fetch a seed set for right-to-left matching + i = matchExpr[ "needsContext" ].test( selector ) ? 0 : tokens.length; + while ( i-- ) { + token = tokens[ i ]; + + // Abort if we hit a combinator + if ( Expr.relative[ ( type = token.type ) ] ) { + break; + } + if ( ( find = Expr.find[ type ] ) ) { + + // Search, expanding context for leading sibling combinators + if ( ( seed = find( + token.matches[ 0 ].replace( runescape, funescape ), + rsibling.test( tokens[ 0 ].type ) && testContext( context.parentNode ) || + context + ) ) ) { + + // If seed is empty or no tokens remain, we can return early + tokens.splice( i, 1 ); + selector = seed.length && toSelector( tokens ); + if ( !selector ) { + push.apply( results, seed ); + return results; + } + + break; + } + } + } + } + + // Compile and execute a filtering function if one is not provided + // Provide `match` to avoid retokenization if we modified the selector above + ( compiled || compile( selector, match ) )( + seed, + context, + !documentIsHTML, + results, + !context || rsibling.test( selector ) && testContext( context.parentNode ) || context + ); + return results; +}; + +// One-time assignments + +// Sort stability +support.sortStable = expando.split( "" ).sort( sortOrder ).join( "" ) === expando; + +// Support: Chrome 14-35+ +// Always assume duplicates if they aren't passed to the comparison function +support.detectDuplicates = !!hasDuplicate; + +// Initialize against the default document +setDocument(); + +// Support: Webkit<537.32 - Safari 6.0.3/Chrome 25 (fixed in Chrome 27) +// Detached nodes confoundingly follow *each other* +support.sortDetached = assert( function( el ) { + + // Should return 1, but returns 4 (following) + return el.compareDocumentPosition( document.createElement( "fieldset" ) ) & 1; +} ); + +// Support: IE<8 +// Prevent attribute/property "interpolation" +// https://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx +if ( !assert( function( el ) { + el.innerHTML = ""; + return el.firstChild.getAttribute( "href" ) === "#"; +} ) ) { + addHandle( "type|href|height|width", function( elem, name, isXML ) { + if ( !isXML ) { + return elem.getAttribute( name, name.toLowerCase() === "type" ? 1 : 2 ); + } + } ); +} + +// Support: IE<9 +// Use defaultValue in place of getAttribute("value") +if ( !support.attributes || !assert( function( el ) { + el.innerHTML = ""; + el.firstChild.setAttribute( "value", "" ); + return el.firstChild.getAttribute( "value" ) === ""; +} ) ) { + addHandle( "value", function( elem, _name, isXML ) { + if ( !isXML && elem.nodeName.toLowerCase() === "input" ) { + return elem.defaultValue; + } + } ); +} + +// Support: IE<9 +// Use getAttributeNode to fetch booleans when getAttribute lies +if ( !assert( function( el ) { + return el.getAttribute( "disabled" ) == null; +} ) ) { + addHandle( booleans, function( elem, name, isXML ) { + var val; + if ( !isXML ) { + return elem[ name ] === true ? name.toLowerCase() : + ( val = elem.getAttributeNode( name ) ) && val.specified ? + val.value : + null; + } + } ); +} + +return Sizzle; + +} )( window ); + + + +jQuery.find = Sizzle; +jQuery.expr = Sizzle.selectors; + +// Deprecated +jQuery.expr[ ":" ] = jQuery.expr.pseudos; +jQuery.uniqueSort = jQuery.unique = Sizzle.uniqueSort; +jQuery.text = Sizzle.getText; +jQuery.isXMLDoc = Sizzle.isXML; +jQuery.contains = Sizzle.contains; +jQuery.escapeSelector = Sizzle.escape; + + + + +var dir = function( elem, dir, until ) { + var matched = [], + truncate = until !== undefined; + + while ( ( elem = elem[ dir ] ) && elem.nodeType !== 9 ) { + if ( elem.nodeType === 1 ) { + if ( truncate && jQuery( elem ).is( until ) ) { + break; + } + matched.push( elem ); + } + } + return matched; +}; + + +var siblings = function( n, elem ) { + var matched = []; + + for ( ; n; n = n.nextSibling ) { + if ( n.nodeType === 1 && n !== elem ) { + matched.push( n ); + } + } + + return matched; +}; + + +var rneedsContext = jQuery.expr.match.needsContext; + + + +function nodeName( elem, name ) { + + return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase(); + +}; +var rsingleTag = ( /^<([a-z][^\/\0>:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i ); + + + +// Implement the identical functionality for filter and not +function winnow( elements, qualifier, not ) { + if ( isFunction( qualifier ) ) { + return jQuery.grep( elements, function( elem, i ) { + return !!qualifier.call( elem, i, elem ) !== not; + } ); + } + + // Single element + if ( qualifier.nodeType ) { + return jQuery.grep( elements, function( elem ) { + return ( elem === qualifier ) !== not; + } ); + } + + // Arraylike of elements (jQuery, arguments, Array) + if ( typeof qualifier !== "string" ) { + return jQuery.grep( elements, function( elem ) { + return ( indexOf.call( qualifier, elem ) > -1 ) !== not; + } ); + } + + // Filtered directly for both simple and complex selectors + return jQuery.filter( qualifier, elements, not ); +} + +jQuery.filter = function( expr, elems, not ) { + var elem = elems[ 0 ]; + + if ( not ) { + expr = ":not(" + expr + ")"; + } + + if ( elems.length === 1 && elem.nodeType === 1 ) { + return jQuery.find.matchesSelector( elem, expr ) ? [ elem ] : []; + } + + return jQuery.find.matches( expr, jQuery.grep( elems, function( elem ) { + return elem.nodeType === 1; + } ) ); +}; + +jQuery.fn.extend( { + find: function( selector ) { + var i, ret, + len = this.length, + self = this; + + if ( typeof selector !== "string" ) { + return this.pushStack( jQuery( selector ).filter( function() { + for ( i = 0; i < len; i++ ) { + if ( jQuery.contains( self[ i ], this ) ) { + return true; + } + } + } ) ); + } + + ret = this.pushStack( [] ); + + for ( i = 0; i < len; i++ ) { + jQuery.find( selector, self[ i ], ret ); + } + + return len > 1 ? jQuery.uniqueSort( ret ) : ret; + }, + filter: function( selector ) { + return this.pushStack( winnow( this, selector || [], false ) ); + }, + not: function( selector ) { + return this.pushStack( winnow( this, selector || [], true ) ); + }, + is: function( selector ) { + return !!winnow( + this, + + // If this is a positional/relative selector, check membership in the returned set + // so $("p:first").is("p:last") won't return true for a doc with two "p". + typeof selector === "string" && rneedsContext.test( selector ) ? + jQuery( selector ) : + selector || [], + false + ).length; + } +} ); + + +// Initialize a jQuery object + + +// A central reference to the root jQuery(document) +var rootjQuery, + + // A simple way to check for HTML strings + // Prioritize #id over to avoid XSS via location.hash (#9521) + // Strict HTML recognition (#11290: must start with <) + // Shortcut simple #id case for speed + rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]+))$/, + + init = jQuery.fn.init = function( selector, context, root ) { + var match, elem; + + // HANDLE: $(""), $(null), $(undefined), $(false) + if ( !selector ) { + return this; + } + + // Method init() accepts an alternate rootjQuery + // so migrate can support jQuery.sub (gh-2101) + root = root || rootjQuery; + + // Handle HTML strings + if ( typeof selector === "string" ) { + if ( selector[ 0 ] === "<" && + selector[ selector.length - 1 ] === ">" && + selector.length >= 3 ) { + + // Assume that strings that start and end with <> are HTML and skip the regex check + match = [ null, selector, null ]; + + } else { + match = rquickExpr.exec( selector ); + } + + // Match html or make sure no context is specified for #id + if ( match && ( match[ 1 ] || !context ) ) { + + // HANDLE: $(html) -> $(array) + if ( match[ 1 ] ) { + context = context instanceof jQuery ? context[ 0 ] : context; + + // Option to run scripts is true for back-compat + // Intentionally let the error be thrown if parseHTML is not present + jQuery.merge( this, jQuery.parseHTML( + match[ 1 ], + context && context.nodeType ? context.ownerDocument || context : document, + true + ) ); + + // HANDLE: $(html, props) + if ( rsingleTag.test( match[ 1 ] ) && jQuery.isPlainObject( context ) ) { + for ( match in context ) { + + // Properties of context are called as methods if possible + if ( isFunction( this[ match ] ) ) { + this[ match ]( context[ match ] ); + + // ...and otherwise set as attributes + } else { + this.attr( match, context[ match ] ); + } + } + } + + return this; + + // HANDLE: $(#id) + } else { + elem = document.getElementById( match[ 2 ] ); + + if ( elem ) { + + // Inject the element directly into the jQuery object + this[ 0 ] = elem; + this.length = 1; + } + return this; + } + + // HANDLE: $(expr, $(...)) + } else if ( !context || context.jquery ) { + return ( context || root ).find( selector ); + + // HANDLE: $(expr, context) + // (which is just equivalent to: $(context).find(expr) + } else { + return this.constructor( context ).find( selector ); + } + + // HANDLE: $(DOMElement) + } else if ( selector.nodeType ) { + this[ 0 ] = selector; + this.length = 1; + return this; + + // HANDLE: $(function) + // Shortcut for document ready + } else if ( isFunction( selector ) ) { + return root.ready !== undefined ? + root.ready( selector ) : + + // Execute immediately if ready is not present + selector( jQuery ); + } + + return jQuery.makeArray( selector, this ); + }; + +// Give the init function the jQuery prototype for later instantiation +init.prototype = jQuery.fn; + +// Initialize central reference +rootjQuery = jQuery( document ); + + +var rparentsprev = /^(?:parents|prev(?:Until|All))/, + + // Methods guaranteed to produce a unique set when starting from a unique set + guaranteedUnique = { + children: true, + contents: true, + next: true, + prev: true + }; + +jQuery.fn.extend( { + has: function( target ) { + var targets = jQuery( target, this ), + l = targets.length; + + return this.filter( function() { + var i = 0; + for ( ; i < l; i++ ) { + if ( jQuery.contains( this, targets[ i ] ) ) { + return true; + } + } + } ); + }, + + closest: function( selectors, context ) { + var cur, + i = 0, + l = this.length, + matched = [], + targets = typeof selectors !== "string" && jQuery( selectors ); + + // Positional selectors never match, since there's no _selection_ context + if ( !rneedsContext.test( selectors ) ) { + for ( ; i < l; i++ ) { + for ( cur = this[ i ]; cur && cur !== context; cur = cur.parentNode ) { + + // Always skip document fragments + if ( cur.nodeType < 11 && ( targets ? + targets.index( cur ) > -1 : + + // Don't pass non-elements to Sizzle + cur.nodeType === 1 && + jQuery.find.matchesSelector( cur, selectors ) ) ) { + + matched.push( cur ); + break; + } + } + } + } + + return this.pushStack( matched.length > 1 ? jQuery.uniqueSort( matched ) : matched ); + }, + + // Determine the position of an element within the set + index: function( elem ) { + + // No argument, return index in parent + if ( !elem ) { + return ( this[ 0 ] && this[ 0 ].parentNode ) ? this.first().prevAll().length : -1; + } + + // Index in selector + if ( typeof elem === "string" ) { + return indexOf.call( jQuery( elem ), this[ 0 ] ); + } + + // Locate the position of the desired element + return indexOf.call( this, + + // If it receives a jQuery object, the first element is used + elem.jquery ? elem[ 0 ] : elem + ); + }, + + add: function( selector, context ) { + return this.pushStack( + jQuery.uniqueSort( + jQuery.merge( this.get(), jQuery( selector, context ) ) + ) + ); + }, + + addBack: function( selector ) { + return this.add( selector == null ? + this.prevObject : this.prevObject.filter( selector ) + ); + } +} ); + +function sibling( cur, dir ) { + while ( ( cur = cur[ dir ] ) && cur.nodeType !== 1 ) {} + return cur; +} + +jQuery.each( { + parent: function( elem ) { + var parent = elem.parentNode; + return parent && parent.nodeType !== 11 ? parent : null; + }, + parents: function( elem ) { + return dir( elem, "parentNode" ); + }, + parentsUntil: function( elem, _i, until ) { + return dir( elem, "parentNode", until ); + }, + next: function( elem ) { + return sibling( elem, "nextSibling" ); + }, + prev: function( elem ) { + return sibling( elem, "previousSibling" ); + }, + nextAll: function( elem ) { + return dir( elem, "nextSibling" ); + }, + prevAll: function( elem ) { + return dir( elem, "previousSibling" ); + }, + nextUntil: function( elem, _i, until ) { + return dir( elem, "nextSibling", until ); + }, + prevUntil: function( elem, _i, until ) { + return dir( elem, "previousSibling", until ); + }, + siblings: function( elem ) { + return siblings( ( elem.parentNode || {} ).firstChild, elem ); + }, + children: function( elem ) { + return siblings( elem.firstChild ); + }, + contents: function( elem ) { + if ( elem.contentDocument != null && + + // Support: IE 11+ + // elements with no `data` attribute has an object + // `contentDocument` with a `null` prototype. + getProto( elem.contentDocument ) ) { + + return elem.contentDocument; + } + + // Support: IE 9 - 11 only, iOS 7 only, Android Browser <=4.3 only + // Treat the template element as a regular one in browsers that + // don't support it. + if ( nodeName( elem, "template" ) ) { + elem = elem.content || elem; + } + + return jQuery.merge( [], elem.childNodes ); + } +}, function( name, fn ) { + jQuery.fn[ name ] = function( until, selector ) { + var matched = jQuery.map( this, fn, until ); + + if ( name.slice( -5 ) !== "Until" ) { + selector = until; + } + + if ( selector && typeof selector === "string" ) { + matched = jQuery.filter( selector, matched ); + } + + if ( this.length > 1 ) { + + // Remove duplicates + if ( !guaranteedUnique[ name ] ) { + jQuery.uniqueSort( matched ); + } + + // Reverse order for parents* and prev-derivatives + if ( rparentsprev.test( name ) ) { + matched.reverse(); + } + } + + return this.pushStack( matched ); + }; +} ); +var rnothtmlwhite = ( /[^\x20\t\r\n\f]+/g ); + + + +// Convert String-formatted options into Object-formatted ones +function createOptions( options ) { + var object = {}; + jQuery.each( options.match( rnothtmlwhite ) || [], function( _, flag ) { + object[ flag ] = true; + } ); + return object; +} + +/* + * Create a callback list using the following parameters: + * + * options: an optional list of space-separated options that will change how + * the callback list behaves or a more traditional option object + * + * By default a callback list will act like an event callback list and can be + * "fired" multiple times. + * + * Possible options: + * + * once: will ensure the callback list can only be fired once (like a Deferred) + * + * memory: will keep track of previous values and will call any callback added + * after the list has been fired right away with the latest "memorized" + * values (like a Deferred) + * + * unique: will ensure a callback can only be added once (no duplicate in the list) + * + * stopOnFalse: interrupt callings when a callback returns false + * + */ +jQuery.Callbacks = function( options ) { + + // Convert options from String-formatted to Object-formatted if needed + // (we check in cache first) + options = typeof options === "string" ? + createOptions( options ) : + jQuery.extend( {}, options ); + + var // Flag to know if list is currently firing + firing, + + // Last fire value for non-forgettable lists + memory, + + // Flag to know if list was already fired + fired, + + // Flag to prevent firing + locked, + + // Actual callback list + list = [], + + // Queue of execution data for repeatable lists + queue = [], + + // Index of currently firing callback (modified by add/remove as needed) + firingIndex = -1, + + // Fire callbacks + fire = function() { + + // Enforce single-firing + locked = locked || options.once; + + // Execute callbacks for all pending executions, + // respecting firingIndex overrides and runtime changes + fired = firing = true; + for ( ; queue.length; firingIndex = -1 ) { + memory = queue.shift(); + while ( ++firingIndex < list.length ) { + + // Run callback and check for early termination + if ( list[ firingIndex ].apply( memory[ 0 ], memory[ 1 ] ) === false && + options.stopOnFalse ) { + + // Jump to end and forget the data so .add doesn't re-fire + firingIndex = list.length; + memory = false; + } + } + } + + // Forget the data if we're done with it + if ( !options.memory ) { + memory = false; + } + + firing = false; + + // Clean up if we're done firing for good + if ( locked ) { + + // Keep an empty list if we have data for future add calls + if ( memory ) { + list = []; + + // Otherwise, this object is spent + } else { + list = ""; + } + } + }, + + // Actual Callbacks object + self = { + + // Add a callback or a collection of callbacks to the list + add: function() { + if ( list ) { + + // If we have memory from a past run, we should fire after adding + if ( memory && !firing ) { + firingIndex = list.length - 1; + queue.push( memory ); + } + + ( function add( args ) { + jQuery.each( args, function( _, arg ) { + if ( isFunction( arg ) ) { + if ( !options.unique || !self.has( arg ) ) { + list.push( arg ); + } + } else if ( arg && arg.length && toType( arg ) !== "string" ) { + + // Inspect recursively + add( arg ); + } + } ); + } )( arguments ); + + if ( memory && !firing ) { + fire(); + } + } + return this; + }, + + // Remove a callback from the list + remove: function() { + jQuery.each( arguments, function( _, arg ) { + var index; + while ( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) { + list.splice( index, 1 ); + + // Handle firing indexes + if ( index <= firingIndex ) { + firingIndex--; + } + } + } ); + return this; + }, + + // Check if a given callback is in the list. + // If no argument is given, return whether or not list has callbacks attached. + has: function( fn ) { + return fn ? + jQuery.inArray( fn, list ) > -1 : + list.length > 0; + }, + + // Remove all callbacks from the list + empty: function() { + if ( list ) { + list = []; + } + return this; + }, + + // Disable .fire and .add + // Abort any current/pending executions + // Clear all callbacks and values + disable: function() { + locked = queue = []; + list = memory = ""; + return this; + }, + disabled: function() { + return !list; + }, + + // Disable .fire + // Also disable .add unless we have memory (since it would have no effect) + // Abort any pending executions + lock: function() { + locked = queue = []; + if ( !memory && !firing ) { + list = memory = ""; + } + return this; + }, + locked: function() { + return !!locked; + }, + + // Call all callbacks with the given context and arguments + fireWith: function( context, args ) { + if ( !locked ) { + args = args || []; + args = [ context, args.slice ? args.slice() : args ]; + queue.push( args ); + if ( !firing ) { + fire(); + } + } + return this; + }, + + // Call all the callbacks with the given arguments + fire: function() { + self.fireWith( this, arguments ); + return this; + }, + + // To know if the callbacks have already been called at least once + fired: function() { + return !!fired; + } + }; + + return self; +}; + + +function Identity( v ) { + return v; +} +function Thrower( ex ) { + throw ex; +} + +function adoptValue( value, resolve, reject, noValue ) { + var method; + + try { + + // Check for promise aspect first to privilege synchronous behavior + if ( value && isFunction( ( method = value.promise ) ) ) { + method.call( value ).done( resolve ).fail( reject ); + + // Other thenables + } else if ( value && isFunction( ( method = value.then ) ) ) { + method.call( value, resolve, reject ); + + // Other non-thenables + } else { + + // Control `resolve` arguments by letting Array#slice cast boolean `noValue` to integer: + // * false: [ value ].slice( 0 ) => resolve( value ) + // * true: [ value ].slice( 1 ) => resolve() + resolve.apply( undefined, [ value ].slice( noValue ) ); + } + + // For Promises/A+, convert exceptions into rejections + // Since jQuery.when doesn't unwrap thenables, we can skip the extra checks appearing in + // Deferred#then to conditionally suppress rejection. + } catch ( value ) { + + // Support: Android 4.0 only + // Strict mode functions invoked without .call/.apply get global-object context + reject.apply( undefined, [ value ] ); + } +} + +jQuery.extend( { + + Deferred: function( func ) { + var tuples = [ + + // action, add listener, callbacks, + // ... .then handlers, argument index, [final state] + [ "notify", "progress", jQuery.Callbacks( "memory" ), + jQuery.Callbacks( "memory" ), 2 ], + [ "resolve", "done", jQuery.Callbacks( "once memory" ), + jQuery.Callbacks( "once memory" ), 0, "resolved" ], + [ "reject", "fail", jQuery.Callbacks( "once memory" ), + jQuery.Callbacks( "once memory" ), 1, "rejected" ] + ], + state = "pending", + promise = { + state: function() { + return state; + }, + always: function() { + deferred.done( arguments ).fail( arguments ); + return this; + }, + "catch": function( fn ) { + return promise.then( null, fn ); + }, + + // Keep pipe for back-compat + pipe: function( /* fnDone, fnFail, fnProgress */ ) { + var fns = arguments; + + return jQuery.Deferred( function( newDefer ) { + jQuery.each( tuples, function( _i, tuple ) { + + // Map tuples (progress, done, fail) to arguments (done, fail, progress) + var fn = isFunction( fns[ tuple[ 4 ] ] ) && fns[ tuple[ 4 ] ]; + + // deferred.progress(function() { bind to newDefer or newDefer.notify }) + // deferred.done(function() { bind to newDefer or newDefer.resolve }) + // deferred.fail(function() { bind to newDefer or newDefer.reject }) + deferred[ tuple[ 1 ] ]( function() { + var returned = fn && fn.apply( this, arguments ); + if ( returned && isFunction( returned.promise ) ) { + returned.promise() + .progress( newDefer.notify ) + .done( newDefer.resolve ) + .fail( newDefer.reject ); + } else { + newDefer[ tuple[ 0 ] + "With" ]( + this, + fn ? [ returned ] : arguments + ); + } + } ); + } ); + fns = null; + } ).promise(); + }, + then: function( onFulfilled, onRejected, onProgress ) { + var maxDepth = 0; + function resolve( depth, deferred, handler, special ) { + return function() { + var that = this, + args = arguments, + mightThrow = function() { + var returned, then; + + // Support: Promises/A+ section 2.3.3.3.3 + // https://promisesaplus.com/#point-59 + // Ignore double-resolution attempts + if ( depth < maxDepth ) { + return; + } + + returned = handler.apply( that, args ); + + // Support: Promises/A+ section 2.3.1 + // https://promisesaplus.com/#point-48 + if ( returned === deferred.promise() ) { + throw new TypeError( "Thenable self-resolution" ); + } + + // Support: Promises/A+ sections 2.3.3.1, 3.5 + // https://promisesaplus.com/#point-54 + // https://promisesaplus.com/#point-75 + // Retrieve `then` only once + then = returned && + + // Support: Promises/A+ section 2.3.4 + // https://promisesaplus.com/#point-64 + // Only check objects and functions for thenability + ( typeof returned === "object" || + typeof returned === "function" ) && + returned.then; + + // Handle a returned thenable + if ( isFunction( then ) ) { + + // Special processors (notify) just wait for resolution + if ( special ) { + then.call( + returned, + resolve( maxDepth, deferred, Identity, special ), + resolve( maxDepth, deferred, Thrower, special ) + ); + + // Normal processors (resolve) also hook into progress + } else { + + // ...and disregard older resolution values + maxDepth++; + + then.call( + returned, + resolve( maxDepth, deferred, Identity, special ), + resolve( maxDepth, deferred, Thrower, special ), + resolve( maxDepth, deferred, Identity, + deferred.notifyWith ) + ); + } + + // Handle all other returned values + } else { + + // Only substitute handlers pass on context + // and multiple values (non-spec behavior) + if ( handler !== Identity ) { + that = undefined; + args = [ returned ]; + } + + // Process the value(s) + // Default process is resolve + ( special || deferred.resolveWith )( that, args ); + } + }, + + // Only normal processors (resolve) catch and reject exceptions + process = special ? + mightThrow : + function() { + try { + mightThrow(); + } catch ( e ) { + + if ( jQuery.Deferred.exceptionHook ) { + jQuery.Deferred.exceptionHook( e, + process.stackTrace ); + } + + // Support: Promises/A+ section 2.3.3.3.4.1 + // https://promisesaplus.com/#point-61 + // Ignore post-resolution exceptions + if ( depth + 1 >= maxDepth ) { + + // Only substitute handlers pass on context + // and multiple values (non-spec behavior) + if ( handler !== Thrower ) { + that = undefined; + args = [ e ]; + } + + deferred.rejectWith( that, args ); + } + } + }; + + // Support: Promises/A+ section 2.3.3.3.1 + // https://promisesaplus.com/#point-57 + // Re-resolve promises immediately to dodge false rejection from + // subsequent errors + if ( depth ) { + process(); + } else { + + // Call an optional hook to record the stack, in case of exception + // since it's otherwise lost when execution goes async + if ( jQuery.Deferred.getStackHook ) { + process.stackTrace = jQuery.Deferred.getStackHook(); + } + window.setTimeout( process ); + } + }; + } + + return jQuery.Deferred( function( newDefer ) { + + // progress_handlers.add( ... ) + tuples[ 0 ][ 3 ].add( + resolve( + 0, + newDefer, + isFunction( onProgress ) ? + onProgress : + Identity, + newDefer.notifyWith + ) + ); + + // fulfilled_handlers.add( ... ) + tuples[ 1 ][ 3 ].add( + resolve( + 0, + newDefer, + isFunction( onFulfilled ) ? + onFulfilled : + Identity + ) + ); + + // rejected_handlers.add( ... ) + tuples[ 2 ][ 3 ].add( + resolve( + 0, + newDefer, + isFunction( onRejected ) ? + onRejected : + Thrower + ) + ); + } ).promise(); + }, + + // Get a promise for this deferred + // If obj is provided, the promise aspect is added to the object + promise: function( obj ) { + return obj != null ? jQuery.extend( obj, promise ) : promise; + } + }, + deferred = {}; + + // Add list-specific methods + jQuery.each( tuples, function( i, tuple ) { + var list = tuple[ 2 ], + stateString = tuple[ 5 ]; + + // promise.progress = list.add + // promise.done = list.add + // promise.fail = list.add + promise[ tuple[ 1 ] ] = list.add; + + // Handle state + if ( stateString ) { + list.add( + function() { + + // state = "resolved" (i.e., fulfilled) + // state = "rejected" + state = stateString; + }, + + // rejected_callbacks.disable + // fulfilled_callbacks.disable + tuples[ 3 - i ][ 2 ].disable, + + // rejected_handlers.disable + // fulfilled_handlers.disable + tuples[ 3 - i ][ 3 ].disable, + + // progress_callbacks.lock + tuples[ 0 ][ 2 ].lock, + + // progress_handlers.lock + tuples[ 0 ][ 3 ].lock + ); + } + + // progress_handlers.fire + // fulfilled_handlers.fire + // rejected_handlers.fire + list.add( tuple[ 3 ].fire ); + + // deferred.notify = function() { deferred.notifyWith(...) } + // deferred.resolve = function() { deferred.resolveWith(...) } + // deferred.reject = function() { deferred.rejectWith(...) } + deferred[ tuple[ 0 ] ] = function() { + deferred[ tuple[ 0 ] + "With" ]( this === deferred ? undefined : this, arguments ); + return this; + }; + + // deferred.notifyWith = list.fireWith + // deferred.resolveWith = list.fireWith + // deferred.rejectWith = list.fireWith + deferred[ tuple[ 0 ] + "With" ] = list.fireWith; + } ); + + // Make the deferred a promise + promise.promise( deferred ); + + // Call given func if any + if ( func ) { + func.call( deferred, deferred ); + } + + // All done! + return deferred; + }, + + // Deferred helper + when: function( singleValue ) { + var + + // count of uncompleted subordinates + remaining = arguments.length, + + // count of unprocessed arguments + i = remaining, + + // subordinate fulfillment data + resolveContexts = Array( i ), + resolveValues = slice.call( arguments ), + + // the master Deferred + master = jQuery.Deferred(), + + // subordinate callback factory + updateFunc = function( i ) { + return function( value ) { + resolveContexts[ i ] = this; + resolveValues[ i ] = arguments.length > 1 ? slice.call( arguments ) : value; + if ( !( --remaining ) ) { + master.resolveWith( resolveContexts, resolveValues ); + } + }; + }; + + // Single- and empty arguments are adopted like Promise.resolve + if ( remaining <= 1 ) { + adoptValue( singleValue, master.done( updateFunc( i ) ).resolve, master.reject, + !remaining ); + + // Use .then() to unwrap secondary thenables (cf. gh-3000) + if ( master.state() === "pending" || + isFunction( resolveValues[ i ] && resolveValues[ i ].then ) ) { + + return master.then(); + } + } + + // Multiple arguments are aggregated like Promise.all array elements + while ( i-- ) { + adoptValue( resolveValues[ i ], updateFunc( i ), master.reject ); + } + + return master.promise(); + } +} ); + + +// These usually indicate a programmer mistake during development, +// warn about them ASAP rather than swallowing them by default. +var rerrorNames = /^(Eval|Internal|Range|Reference|Syntax|Type|URI)Error$/; + +jQuery.Deferred.exceptionHook = function( error, stack ) { + + // Support: IE 8 - 9 only + // Console exists when dev tools are open, which can happen at any time + if ( window.console && window.console.warn && error && rerrorNames.test( error.name ) ) { + window.console.warn( "jQuery.Deferred exception: " + error.message, error.stack, stack ); + } +}; + + + + +jQuery.readyException = function( error ) { + window.setTimeout( function() { + throw error; + } ); +}; + + + + +// The deferred used on DOM ready +var readyList = jQuery.Deferred(); + +jQuery.fn.ready = function( fn ) { + + readyList + .then( fn ) + + // Wrap jQuery.readyException in a function so that the lookup + // happens at the time of error handling instead of callback + // registration. + .catch( function( error ) { + jQuery.readyException( error ); + } ); + + return this; +}; + +jQuery.extend( { + + // Is the DOM ready to be used? Set to true once it occurs. + isReady: false, + + // A counter to track how many items to wait for before + // the ready event fires. See #6781 + readyWait: 1, + + // Handle when the DOM is ready + ready: function( wait ) { + + // Abort if there are pending holds or we're already ready + if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) { + return; + } + + // Remember that the DOM is ready + jQuery.isReady = true; + + // If a normal DOM Ready event fired, decrement, and wait if need be + if ( wait !== true && --jQuery.readyWait > 0 ) { + return; + } + + // If there are functions bound, to execute + readyList.resolveWith( document, [ jQuery ] ); + } +} ); + +jQuery.ready.then = readyList.then; + +// The ready event handler and self cleanup method +function completed() { + document.removeEventListener( "DOMContentLoaded", completed ); + window.removeEventListener( "load", completed ); + jQuery.ready(); +} + +// Catch cases where $(document).ready() is called +// after the browser event has already occurred. +// Support: IE <=9 - 10 only +// Older IE sometimes signals "interactive" too soon +if ( document.readyState === "complete" || + ( document.readyState !== "loading" && !document.documentElement.doScroll ) ) { + + // Handle it asynchronously to allow scripts the opportunity to delay ready + window.setTimeout( jQuery.ready ); + +} else { + + // Use the handy event callback + document.addEventListener( "DOMContentLoaded", completed ); + + // A fallback to window.onload, that will always work + window.addEventListener( "load", completed ); +} + + + + +// Multifunctional method to get and set values of a collection +// The value/s can optionally be executed if it's a function +var access = function( elems, fn, key, value, chainable, emptyGet, raw ) { + var i = 0, + len = elems.length, + bulk = key == null; + + // Sets many values + if ( toType( key ) === "object" ) { + chainable = true; + for ( i in key ) { + access( elems, fn, i, key[ i ], true, emptyGet, raw ); + } + + // Sets one value + } else if ( value !== undefined ) { + chainable = true; + + if ( !isFunction( value ) ) { + raw = true; + } + + if ( bulk ) { + + // Bulk operations run against the entire set + if ( raw ) { + fn.call( elems, value ); + fn = null; + + // ...except when executing function values + } else { + bulk = fn; + fn = function( elem, _key, value ) { + return bulk.call( jQuery( elem ), value ); + }; + } + } + + if ( fn ) { + for ( ; i < len; i++ ) { + fn( + elems[ i ], key, raw ? + value : + value.call( elems[ i ], i, fn( elems[ i ], key ) ) + ); + } + } + } + + if ( chainable ) { + return elems; + } + + // Gets + if ( bulk ) { + return fn.call( elems ); + } + + return len ? fn( elems[ 0 ], key ) : emptyGet; +}; + + +// Matches dashed string for camelizing +var rmsPrefix = /^-ms-/, + rdashAlpha = /-([a-z])/g; + +// Used by camelCase as callback to replace() +function fcamelCase( _all, letter ) { + return letter.toUpperCase(); +} + +// Convert dashed to camelCase; used by the css and data modules +// Support: IE <=9 - 11, Edge 12 - 15 +// Microsoft forgot to hump their vendor prefix (#9572) +function camelCase( string ) { + return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase ); +} +var acceptData = function( owner ) { + + // Accepts only: + // - Node + // - Node.ELEMENT_NODE + // - Node.DOCUMENT_NODE + // - Object + // - Any + return owner.nodeType === 1 || owner.nodeType === 9 || !( +owner.nodeType ); +}; + + + + +function Data() { + this.expando = jQuery.expando + Data.uid++; +} + +Data.uid = 1; + +Data.prototype = { + + cache: function( owner ) { + + // Check if the owner object already has a cache + var value = owner[ this.expando ]; + + // If not, create one + if ( !value ) { + value = {}; + + // We can accept data for non-element nodes in modern browsers, + // but we should not, see #8335. + // Always return an empty object. + if ( acceptData( owner ) ) { + + // If it is a node unlikely to be stringify-ed or looped over + // use plain assignment + if ( owner.nodeType ) { + owner[ this.expando ] = value; + + // Otherwise secure it in a non-enumerable property + // configurable must be true to allow the property to be + // deleted when data is removed + } else { + Object.defineProperty( owner, this.expando, { + value: value, + configurable: true + } ); + } + } + } + + return value; + }, + set: function( owner, data, value ) { + var prop, + cache = this.cache( owner ); + + // Handle: [ owner, key, value ] args + // Always use camelCase key (gh-2257) + if ( typeof data === "string" ) { + cache[ camelCase( data ) ] = value; + + // Handle: [ owner, { properties } ] args + } else { + + // Copy the properties one-by-one to the cache object + for ( prop in data ) { + cache[ camelCase( prop ) ] = data[ prop ]; + } + } + return cache; + }, + get: function( owner, key ) { + return key === undefined ? + this.cache( owner ) : + + // Always use camelCase key (gh-2257) + owner[ this.expando ] && owner[ this.expando ][ camelCase( key ) ]; + }, + access: function( owner, key, value ) { + + // In cases where either: + // + // 1. No key was specified + // 2. A string key was specified, but no value provided + // + // Take the "read" path and allow the get method to determine + // which value to return, respectively either: + // + // 1. The entire cache object + // 2. The data stored at the key + // + if ( key === undefined || + ( ( key && typeof key === "string" ) && value === undefined ) ) { + + return this.get( owner, key ); + } + + // When the key is not a string, or both a key and value + // are specified, set or extend (existing objects) with either: + // + // 1. An object of properties + // 2. A key and value + // + this.set( owner, key, value ); + + // Since the "set" path can have two possible entry points + // return the expected data based on which path was taken[*] + return value !== undefined ? value : key; + }, + remove: function( owner, key ) { + var i, + cache = owner[ this.expando ]; + + if ( cache === undefined ) { + return; + } + + if ( key !== undefined ) { + + // Support array or space separated string of keys + if ( Array.isArray( key ) ) { + + // If key is an array of keys... + // We always set camelCase keys, so remove that. + key = key.map( camelCase ); + } else { + key = camelCase( key ); + + // If a key with the spaces exists, use it. + // Otherwise, create an array by matching non-whitespace + key = key in cache ? + [ key ] : + ( key.match( rnothtmlwhite ) || [] ); + } + + i = key.length; + + while ( i-- ) { + delete cache[ key[ i ] ]; + } + } + + // Remove the expando if there's no more data + if ( key === undefined || jQuery.isEmptyObject( cache ) ) { + + // Support: Chrome <=35 - 45 + // Webkit & Blink performance suffers when deleting properties + // from DOM nodes, so set to undefined instead + // https://bugs.chromium.org/p/chromium/issues/detail?id=378607 (bug restricted) + if ( owner.nodeType ) { + owner[ this.expando ] = undefined; + } else { + delete owner[ this.expando ]; + } + } + }, + hasData: function( owner ) { + var cache = owner[ this.expando ]; + return cache !== undefined && !jQuery.isEmptyObject( cache ); + } +}; +var dataPriv = new Data(); + +var dataUser = new Data(); + + + +// Implementation Summary +// +// 1. Enforce API surface and semantic compatibility with 1.9.x branch +// 2. Improve the module's maintainability by reducing the storage +// paths to a single mechanism. +// 3. Use the same single mechanism to support "private" and "user" data. +// 4. _Never_ expose "private" data to user code (TODO: Drop _data, _removeData) +// 5. Avoid exposing implementation details on user objects (eg. expando properties) +// 6. Provide a clear path for implementation upgrade to WeakMap in 2014 + +var rbrace = /^(?:\{[\w\W]*\}|\[[\w\W]*\])$/, + rmultiDash = /[A-Z]/g; + +function getData( data ) { + if ( data === "true" ) { + return true; + } + + if ( data === "false" ) { + return false; + } + + if ( data === "null" ) { + return null; + } + + // Only convert to a number if it doesn't change the string + if ( data === +data + "" ) { + return +data; + } + + if ( rbrace.test( data ) ) { + return JSON.parse( data ); + } + + return data; +} + +function dataAttr( elem, key, data ) { + var name; + + // If nothing was found internally, try to fetch any + // data from the HTML5 data-* attribute + if ( data === undefined && elem.nodeType === 1 ) { + name = "data-" + key.replace( rmultiDash, "-$&" ).toLowerCase(); + data = elem.getAttribute( name ); + + if ( typeof data === "string" ) { + try { + data = getData( data ); + } catch ( e ) {} + + // Make sure we set the data so it isn't changed later + dataUser.set( elem, key, data ); + } else { + data = undefined; + } + } + return data; +} + +jQuery.extend( { + hasData: function( elem ) { + return dataUser.hasData( elem ) || dataPriv.hasData( elem ); + }, + + data: function( elem, name, data ) { + return dataUser.access( elem, name, data ); + }, + + removeData: function( elem, name ) { + dataUser.remove( elem, name ); + }, + + // TODO: Now that all calls to _data and _removeData have been replaced + // with direct calls to dataPriv methods, these can be deprecated. + _data: function( elem, name, data ) { + return dataPriv.access( elem, name, data ); + }, + + _removeData: function( elem, name ) { + dataPriv.remove( elem, name ); + } +} ); + +jQuery.fn.extend( { + data: function( key, value ) { + var i, name, data, + elem = this[ 0 ], + attrs = elem && elem.attributes; + + // Gets all values + if ( key === undefined ) { + if ( this.length ) { + data = dataUser.get( elem ); + + if ( elem.nodeType === 1 && !dataPriv.get( elem, "hasDataAttrs" ) ) { + i = attrs.length; + while ( i-- ) { + + // Support: IE 11 only + // The attrs elements can be null (#14894) + if ( attrs[ i ] ) { + name = attrs[ i ].name; + if ( name.indexOf( "data-" ) === 0 ) { + name = camelCase( name.slice( 5 ) ); + dataAttr( elem, name, data[ name ] ); + } + } + } + dataPriv.set( elem, "hasDataAttrs", true ); + } + } + + return data; + } + + // Sets multiple values + if ( typeof key === "object" ) { + return this.each( function() { + dataUser.set( this, key ); + } ); + } + + return access( this, function( value ) { + var data; + + // The calling jQuery object (element matches) is not empty + // (and therefore has an element appears at this[ 0 ]) and the + // `value` parameter was not undefined. An empty jQuery object + // will result in `undefined` for elem = this[ 0 ] which will + // throw an exception if an attempt to read a data cache is made. + if ( elem && value === undefined ) { + + // Attempt to get data from the cache + // The key will always be camelCased in Data + data = dataUser.get( elem, key ); + if ( data !== undefined ) { + return data; + } + + // Attempt to "discover" the data in + // HTML5 custom data-* attrs + data = dataAttr( elem, key ); + if ( data !== undefined ) { + return data; + } + + // We tried really hard, but the data doesn't exist. + return; + } + + // Set the data... + this.each( function() { + + // We always store the camelCased key + dataUser.set( this, key, value ); + } ); + }, null, value, arguments.length > 1, null, true ); + }, + + removeData: function( key ) { + return this.each( function() { + dataUser.remove( this, key ); + } ); + } +} ); + + +jQuery.extend( { + queue: function( elem, type, data ) { + var queue; + + if ( elem ) { + type = ( type || "fx" ) + "queue"; + queue = dataPriv.get( elem, type ); + + // Speed up dequeue by getting out quickly if this is just a lookup + if ( data ) { + if ( !queue || Array.isArray( data ) ) { + queue = dataPriv.access( elem, type, jQuery.makeArray( data ) ); + } else { + queue.push( data ); + } + } + return queue || []; + } + }, + + dequeue: function( elem, type ) { + type = type || "fx"; + + var queue = jQuery.queue( elem, type ), + startLength = queue.length, + fn = queue.shift(), + hooks = jQuery._queueHooks( elem, type ), + next = function() { + jQuery.dequeue( elem, type ); + }; + + // If the fx queue is dequeued, always remove the progress sentinel + if ( fn === "inprogress" ) { + fn = queue.shift(); + startLength--; + } + + if ( fn ) { + + // Add a progress sentinel to prevent the fx queue from being + // automatically dequeued + if ( type === "fx" ) { + queue.unshift( "inprogress" ); + } + + // Clear up the last queue stop function + delete hooks.stop; + fn.call( elem, next, hooks ); + } + + if ( !startLength && hooks ) { + hooks.empty.fire(); + } + }, + + // Not public - generate a queueHooks object, or return the current one + _queueHooks: function( elem, type ) { + var key = type + "queueHooks"; + return dataPriv.get( elem, key ) || dataPriv.access( elem, key, { + empty: jQuery.Callbacks( "once memory" ).add( function() { + dataPriv.remove( elem, [ type + "queue", key ] ); + } ) + } ); + } +} ); + +jQuery.fn.extend( { + queue: function( type, data ) { + var setter = 2; + + if ( typeof type !== "string" ) { + data = type; + type = "fx"; + setter--; + } + + if ( arguments.length < setter ) { + return jQuery.queue( this[ 0 ], type ); + } + + return data === undefined ? + this : + this.each( function() { + var queue = jQuery.queue( this, type, data ); + + // Ensure a hooks for this queue + jQuery._queueHooks( this, type ); + + if ( type === "fx" && queue[ 0 ] !== "inprogress" ) { + jQuery.dequeue( this, type ); + } + } ); + }, + dequeue: function( type ) { + return this.each( function() { + jQuery.dequeue( this, type ); + } ); + }, + clearQueue: function( type ) { + return this.queue( type || "fx", [] ); + }, + + // Get a promise resolved when queues of a certain type + // are emptied (fx is the type by default) + promise: function( type, obj ) { + var tmp, + count = 1, + defer = jQuery.Deferred(), + elements = this, + i = this.length, + resolve = function() { + if ( !( --count ) ) { + defer.resolveWith( elements, [ elements ] ); + } + }; + + if ( typeof type !== "string" ) { + obj = type; + type = undefined; + } + type = type || "fx"; + + while ( i-- ) { + tmp = dataPriv.get( elements[ i ], type + "queueHooks" ); + if ( tmp && tmp.empty ) { + count++; + tmp.empty.add( resolve ); + } + } + resolve(); + return defer.promise( obj ); + } +} ); +var pnum = ( /[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/ ).source; + +var rcssNum = new RegExp( "^(?:([+-])=|)(" + pnum + ")([a-z%]*)$", "i" ); + + +var cssExpand = [ "Top", "Right", "Bottom", "Left" ]; + +var documentElement = document.documentElement; + + + + var isAttached = function( elem ) { + return jQuery.contains( elem.ownerDocument, elem ); + }, + composed = { composed: true }; + + // Support: IE 9 - 11+, Edge 12 - 18+, iOS 10.0 - 10.2 only + // Check attachment across shadow DOM boundaries when possible (gh-3504) + // Support: iOS 10.0-10.2 only + // Early iOS 10 versions support `attachShadow` but not `getRootNode`, + // leading to errors. We need to check for `getRootNode`. + if ( documentElement.getRootNode ) { + isAttached = function( elem ) { + return jQuery.contains( elem.ownerDocument, elem ) || + elem.getRootNode( composed ) === elem.ownerDocument; + }; + } +var isHiddenWithinTree = function( elem, el ) { + + // isHiddenWithinTree might be called from jQuery#filter function; + // in that case, element will be second argument + elem = el || elem; + + // Inline style trumps all + return elem.style.display === "none" || + elem.style.display === "" && + + // Otherwise, check computed style + // Support: Firefox <=43 - 45 + // Disconnected elements can have computed display: none, so first confirm that elem is + // in the document. + isAttached( elem ) && + + jQuery.css( elem, "display" ) === "none"; + }; + + + +function adjustCSS( elem, prop, valueParts, tween ) { + var adjusted, scale, + maxIterations = 20, + currentValue = tween ? + function() { + return tween.cur(); + } : + function() { + return jQuery.css( elem, prop, "" ); + }, + initial = currentValue(), + unit = valueParts && valueParts[ 3 ] || ( jQuery.cssNumber[ prop ] ? "" : "px" ), + + // Starting value computation is required for potential unit mismatches + initialInUnit = elem.nodeType && + ( jQuery.cssNumber[ prop ] || unit !== "px" && +initial ) && + rcssNum.exec( jQuery.css( elem, prop ) ); + + if ( initialInUnit && initialInUnit[ 3 ] !== unit ) { + + // Support: Firefox <=54 + // Halve the iteration target value to prevent interference from CSS upper bounds (gh-2144) + initial = initial / 2; + + // Trust units reported by jQuery.css + unit = unit || initialInUnit[ 3 ]; + + // Iteratively approximate from a nonzero starting point + initialInUnit = +initial || 1; + + while ( maxIterations-- ) { + + // Evaluate and update our best guess (doubling guesses that zero out). + // Finish if the scale equals or crosses 1 (making the old*new product non-positive). + jQuery.style( elem, prop, initialInUnit + unit ); + if ( ( 1 - scale ) * ( 1 - ( scale = currentValue() / initial || 0.5 ) ) <= 0 ) { + maxIterations = 0; + } + initialInUnit = initialInUnit / scale; + + } + + initialInUnit = initialInUnit * 2; + jQuery.style( elem, prop, initialInUnit + unit ); + + // Make sure we update the tween properties later on + valueParts = valueParts || []; + } + + if ( valueParts ) { + initialInUnit = +initialInUnit || +initial || 0; + + // Apply relative offset (+=/-=) if specified + adjusted = valueParts[ 1 ] ? + initialInUnit + ( valueParts[ 1 ] + 1 ) * valueParts[ 2 ] : + +valueParts[ 2 ]; + if ( tween ) { + tween.unit = unit; + tween.start = initialInUnit; + tween.end = adjusted; + } + } + return adjusted; +} + + +var defaultDisplayMap = {}; + +function getDefaultDisplay( elem ) { + var temp, + doc = elem.ownerDocument, + nodeName = elem.nodeName, + display = defaultDisplayMap[ nodeName ]; + + if ( display ) { + return display; + } + + temp = doc.body.appendChild( doc.createElement( nodeName ) ); + display = jQuery.css( temp, "display" ); + + temp.parentNode.removeChild( temp ); + + if ( display === "none" ) { + display = "block"; + } + defaultDisplayMap[ nodeName ] = display; + + return display; +} + +function showHide( elements, show ) { + var display, elem, + values = [], + index = 0, + length = elements.length; + + // Determine new display value for elements that need to change + for ( ; index < length; index++ ) { + elem = elements[ index ]; + if ( !elem.style ) { + continue; + } + + display = elem.style.display; + if ( show ) { + + // Since we force visibility upon cascade-hidden elements, an immediate (and slow) + // check is required in this first loop unless we have a nonempty display value (either + // inline or about-to-be-restored) + if ( display === "none" ) { + values[ index ] = dataPriv.get( elem, "display" ) || null; + if ( !values[ index ] ) { + elem.style.display = ""; + } + } + if ( elem.style.display === "" && isHiddenWithinTree( elem ) ) { + values[ index ] = getDefaultDisplay( elem ); + } + } else { + if ( display !== "none" ) { + values[ index ] = "none"; + + // Remember what we're overwriting + dataPriv.set( elem, "display", display ); + } + } + } + + // Set the display of the elements in a second loop to avoid constant reflow + for ( index = 0; index < length; index++ ) { + if ( values[ index ] != null ) { + elements[ index ].style.display = values[ index ]; + } + } + + return elements; +} + +jQuery.fn.extend( { + show: function() { + return showHide( this, true ); + }, + hide: function() { + return showHide( this ); + }, + toggle: function( state ) { + if ( typeof state === "boolean" ) { + return state ? this.show() : this.hide(); + } + + return this.each( function() { + if ( isHiddenWithinTree( this ) ) { + jQuery( this ).show(); + } else { + jQuery( this ).hide(); + } + } ); + } +} ); +var rcheckableType = ( /^(?:checkbox|radio)$/i ); + +var rtagName = ( /<([a-z][^\/\0>\x20\t\r\n\f]*)/i ); + +var rscriptType = ( /^$|^module$|\/(?:java|ecma)script/i ); + + + +( function() { + var fragment = document.createDocumentFragment(), + div = fragment.appendChild( document.createElement( "div" ) ), + input = document.createElement( "input" ); + + // Support: Android 4.0 - 4.3 only + // Check state lost if the name is set (#11217) + // Support: Windows Web Apps (WWA) + // `name` and `type` must use .setAttribute for WWA (#14901) + input.setAttribute( "type", "radio" ); + input.setAttribute( "checked", "checked" ); + input.setAttribute( "name", "t" ); + + div.appendChild( input ); + + // Support: Android <=4.1 only + // Older WebKit doesn't clone checked state correctly in fragments + support.checkClone = div.cloneNode( true ).cloneNode( true ).lastChild.checked; + + // Support: IE <=11 only + // Make sure textarea (and checkbox) defaultValue is properly cloned + div.innerHTML = ""; + support.noCloneChecked = !!div.cloneNode( true ).lastChild.defaultValue; + + // Support: IE <=9 only + // IE <=9 replaces "; + support.option = !!div.lastChild; +} )(); + + +// We have to close these tags to support XHTML (#13200) +var wrapMap = { + + // XHTML parsers do not magically insert elements in the + // same way that tag soup parsers do. So we cannot shorten + // this by omitting or other required elements. + thead: [ 1, "", "
" ], + col: [ 2, "", "
" ], + tr: [ 2, "", "
" ], + td: [ 3, "", "
" ], + + _default: [ 0, "", "" ] +}; + +wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; +wrapMap.th = wrapMap.td; + +// Support: IE <=9 only +if ( !support.option ) { + wrapMap.optgroup = wrapMap.option = [ 1, "" ]; +} + + +function getAll( context, tag ) { + + // Support: IE <=9 - 11 only + // Use typeof to avoid zero-argument method invocation on host objects (#15151) + var ret; + + if ( typeof context.getElementsByTagName !== "undefined" ) { + ret = context.getElementsByTagName( tag || "*" ); + + } else if ( typeof context.querySelectorAll !== "undefined" ) { + ret = context.querySelectorAll( tag || "*" ); + + } else { + ret = []; + } + + if ( tag === undefined || tag && nodeName( context, tag ) ) { + return jQuery.merge( [ context ], ret ); + } + + return ret; +} + + +// Mark scripts as having already been evaluated +function setGlobalEval( elems, refElements ) { + var i = 0, + l = elems.length; + + for ( ; i < l; i++ ) { + dataPriv.set( + elems[ i ], + "globalEval", + !refElements || dataPriv.get( refElements[ i ], "globalEval" ) + ); + } +} + + +var rhtml = /<|&#?\w+;/; + +function buildFragment( elems, context, scripts, selection, ignored ) { + var elem, tmp, tag, wrap, attached, j, + fragment = context.createDocumentFragment(), + nodes = [], + i = 0, + l = elems.length; + + for ( ; i < l; i++ ) { + elem = elems[ i ]; + + if ( elem || elem === 0 ) { + + // Add nodes directly + if ( toType( elem ) === "object" ) { + + // Support: Android <=4.0 only, PhantomJS 1 only + // push.apply(_, arraylike) throws on ancient WebKit + jQuery.merge( nodes, elem.nodeType ? [ elem ] : elem ); + + // Convert non-html into a text node + } else if ( !rhtml.test( elem ) ) { + nodes.push( context.createTextNode( elem ) ); + + // Convert html into DOM nodes + } else { + tmp = tmp || fragment.appendChild( context.createElement( "div" ) ); + + // Deserialize a standard representation + tag = ( rtagName.exec( elem ) || [ "", "" ] )[ 1 ].toLowerCase(); + wrap = wrapMap[ tag ] || wrapMap._default; + tmp.innerHTML = wrap[ 1 ] + jQuery.htmlPrefilter( elem ) + wrap[ 2 ]; + + // Descend through wrappers to the right content + j = wrap[ 0 ]; + while ( j-- ) { + tmp = tmp.lastChild; + } + + // Support: Android <=4.0 only, PhantomJS 1 only + // push.apply(_, arraylike) throws on ancient WebKit + jQuery.merge( nodes, tmp.childNodes ); + + // Remember the top-level container + tmp = fragment.firstChild; + + // Ensure the created nodes are orphaned (#12392) + tmp.textContent = ""; + } + } + } + + // Remove wrapper from fragment + fragment.textContent = ""; + + i = 0; + while ( ( elem = nodes[ i++ ] ) ) { + + // Skip elements already in the context collection (trac-4087) + if ( selection && jQuery.inArray( elem, selection ) > -1 ) { + if ( ignored ) { + ignored.push( elem ); + } + continue; + } + + attached = isAttached( elem ); + + // Append to fragment + tmp = getAll( fragment.appendChild( elem ), "script" ); + + // Preserve script evaluation history + if ( attached ) { + setGlobalEval( tmp ); + } + + // Capture executables + if ( scripts ) { + j = 0; + while ( ( elem = tmp[ j++ ] ) ) { + if ( rscriptType.test( elem.type || "" ) ) { + scripts.push( elem ); + } + } + } + } + + return fragment; +} + + +var + rkeyEvent = /^key/, + rmouseEvent = /^(?:mouse|pointer|contextmenu|drag|drop)|click/, + rtypenamespace = /^([^.]*)(?:\.(.+)|)/; + +function returnTrue() { + return true; +} + +function returnFalse() { + return false; +} + +// Support: IE <=9 - 11+ +// focus() and blur() are asynchronous, except when they are no-op. +// So expect focus to be synchronous when the element is already active, +// and blur to be synchronous when the element is not already active. +// (focus and blur are always synchronous in other supported browsers, +// this just defines when we can count on it). +function expectSync( elem, type ) { + return ( elem === safeActiveElement() ) === ( type === "focus" ); +} + +// Support: IE <=9 only +// Accessing document.activeElement can throw unexpectedly +// https://bugs.jquery.com/ticket/13393 +function safeActiveElement() { + try { + return document.activeElement; + } catch ( err ) { } +} + +function on( elem, types, selector, data, fn, one ) { + var origFn, type; + + // Types can be a map of types/handlers + if ( typeof types === "object" ) { + + // ( types-Object, selector, data ) + if ( typeof selector !== "string" ) { + + // ( types-Object, data ) + data = data || selector; + selector = undefined; + } + for ( type in types ) { + on( elem, type, selector, data, types[ type ], one ); + } + return elem; + } + + if ( data == null && fn == null ) { + + // ( types, fn ) + fn = selector; + data = selector = undefined; + } else if ( fn == null ) { + if ( typeof selector === "string" ) { + + // ( types, selector, fn ) + fn = data; + data = undefined; + } else { + + // ( types, data, fn ) + fn = data; + data = selector; + selector = undefined; + } + } + if ( fn === false ) { + fn = returnFalse; + } else if ( !fn ) { + return elem; + } + + if ( one === 1 ) { + origFn = fn; + fn = function( event ) { + + // Can use an empty set, since event contains the info + jQuery().off( event ); + return origFn.apply( this, arguments ); + }; + + // Use same guid so caller can remove using origFn + fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ ); + } + return elem.each( function() { + jQuery.event.add( this, types, fn, data, selector ); + } ); +} + +/* + * Helper functions for managing events -- not part of the public interface. + * Props to Dean Edwards' addEvent library for many of the ideas. + */ +jQuery.event = { + + global: {}, + + add: function( elem, types, handler, data, selector ) { + + var handleObjIn, eventHandle, tmp, + events, t, handleObj, + special, handlers, type, namespaces, origType, + elemData = dataPriv.get( elem ); + + // Only attach events to objects that accept data + if ( !acceptData( elem ) ) { + return; + } + + // Caller can pass in an object of custom data in lieu of the handler + if ( handler.handler ) { + handleObjIn = handler; + handler = handleObjIn.handler; + selector = handleObjIn.selector; + } + + // Ensure that invalid selectors throw exceptions at attach time + // Evaluate against documentElement in case elem is a non-element node (e.g., document) + if ( selector ) { + jQuery.find.matchesSelector( documentElement, selector ); + } + + // Make sure that the handler has a unique ID, used to find/remove it later + if ( !handler.guid ) { + handler.guid = jQuery.guid++; + } + + // Init the element's event structure and main handler, if this is the first + if ( !( events = elemData.events ) ) { + events = elemData.events = Object.create( null ); + } + if ( !( eventHandle = elemData.handle ) ) { + eventHandle = elemData.handle = function( e ) { + + // Discard the second event of a jQuery.event.trigger() and + // when an event is called after a page has unloaded + return typeof jQuery !== "undefined" && jQuery.event.triggered !== e.type ? + jQuery.event.dispatch.apply( elem, arguments ) : undefined; + }; + } + + // Handle multiple events separated by a space + types = ( types || "" ).match( rnothtmlwhite ) || [ "" ]; + t = types.length; + while ( t-- ) { + tmp = rtypenamespace.exec( types[ t ] ) || []; + type = origType = tmp[ 1 ]; + namespaces = ( tmp[ 2 ] || "" ).split( "." ).sort(); + + // There *must* be a type, no attaching namespace-only handlers + if ( !type ) { + continue; + } + + // If event changes its type, use the special event handlers for the changed type + special = jQuery.event.special[ type ] || {}; + + // If selector defined, determine special event api type, otherwise given type + type = ( selector ? special.delegateType : special.bindType ) || type; + + // Update special based on newly reset type + special = jQuery.event.special[ type ] || {}; + + // handleObj is passed to all event handlers + handleObj = jQuery.extend( { + type: type, + origType: origType, + data: data, + handler: handler, + guid: handler.guid, + selector: selector, + needsContext: selector && jQuery.expr.match.needsContext.test( selector ), + namespace: namespaces.join( "." ) + }, handleObjIn ); + + // Init the event handler queue if we're the first + if ( !( handlers = events[ type ] ) ) { + handlers = events[ type ] = []; + handlers.delegateCount = 0; + + // Only use addEventListener if the special events handler returns false + if ( !special.setup || + special.setup.call( elem, data, namespaces, eventHandle ) === false ) { + + if ( elem.addEventListener ) { + elem.addEventListener( type, eventHandle ); + } + } + } + + if ( special.add ) { + special.add.call( elem, handleObj ); + + if ( !handleObj.handler.guid ) { + handleObj.handler.guid = handler.guid; + } + } + + // Add to the element's handler list, delegates in front + if ( selector ) { + handlers.splice( handlers.delegateCount++, 0, handleObj ); + } else { + handlers.push( handleObj ); + } + + // Keep track of which events have ever been used, for event optimization + jQuery.event.global[ type ] = true; + } + + }, + + // Detach an event or set of events from an element + remove: function( elem, types, handler, selector, mappedTypes ) { + + var j, origCount, tmp, + events, t, handleObj, + special, handlers, type, namespaces, origType, + elemData = dataPriv.hasData( elem ) && dataPriv.get( elem ); + + if ( !elemData || !( events = elemData.events ) ) { + return; + } + + // Once for each type.namespace in types; type may be omitted + types = ( types || "" ).match( rnothtmlwhite ) || [ "" ]; + t = types.length; + while ( t-- ) { + tmp = rtypenamespace.exec( types[ t ] ) || []; + type = origType = tmp[ 1 ]; + namespaces = ( tmp[ 2 ] || "" ).split( "." ).sort(); + + // Unbind all events (on this namespace, if provided) for the element + if ( !type ) { + for ( type in events ) { + jQuery.event.remove( elem, type + types[ t ], handler, selector, true ); + } + continue; + } + + special = jQuery.event.special[ type ] || {}; + type = ( selector ? special.delegateType : special.bindType ) || type; + handlers = events[ type ] || []; + tmp = tmp[ 2 ] && + new RegExp( "(^|\\.)" + namespaces.join( "\\.(?:.*\\.|)" ) + "(\\.|$)" ); + + // Remove matching events + origCount = j = handlers.length; + while ( j-- ) { + handleObj = handlers[ j ]; + + if ( ( mappedTypes || origType === handleObj.origType ) && + ( !handler || handler.guid === handleObj.guid ) && + ( !tmp || tmp.test( handleObj.namespace ) ) && + ( !selector || selector === handleObj.selector || + selector === "**" && handleObj.selector ) ) { + handlers.splice( j, 1 ); + + if ( handleObj.selector ) { + handlers.delegateCount--; + } + if ( special.remove ) { + special.remove.call( elem, handleObj ); + } + } + } + + // Remove generic event handler if we removed something and no more handlers exist + // (avoids potential for endless recursion during removal of special event handlers) + if ( origCount && !handlers.length ) { + if ( !special.teardown || + special.teardown.call( elem, namespaces, elemData.handle ) === false ) { + + jQuery.removeEvent( elem, type, elemData.handle ); + } + + delete events[ type ]; + } + } + + // Remove data and the expando if it's no longer used + if ( jQuery.isEmptyObject( events ) ) { + dataPriv.remove( elem, "handle events" ); + } + }, + + dispatch: function( nativeEvent ) { + + var i, j, ret, matched, handleObj, handlerQueue, + args = new Array( arguments.length ), + + // Make a writable jQuery.Event from the native event object + event = jQuery.event.fix( nativeEvent ), + + handlers = ( + dataPriv.get( this, "events" ) || Object.create( null ) + )[ event.type ] || [], + special = jQuery.event.special[ event.type ] || {}; + + // Use the fix-ed jQuery.Event rather than the (read-only) native event + args[ 0 ] = event; + + for ( i = 1; i < arguments.length; i++ ) { + args[ i ] = arguments[ i ]; + } + + event.delegateTarget = this; + + // Call the preDispatch hook for the mapped type, and let it bail if desired + if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) { + return; + } + + // Determine handlers + handlerQueue = jQuery.event.handlers.call( this, event, handlers ); + + // Run delegates first; they may want to stop propagation beneath us + i = 0; + while ( ( matched = handlerQueue[ i++ ] ) && !event.isPropagationStopped() ) { + event.currentTarget = matched.elem; + + j = 0; + while ( ( handleObj = matched.handlers[ j++ ] ) && + !event.isImmediatePropagationStopped() ) { + + // If the event is namespaced, then each handler is only invoked if it is + // specially universal or its namespaces are a superset of the event's. + if ( !event.rnamespace || handleObj.namespace === false || + event.rnamespace.test( handleObj.namespace ) ) { + + event.handleObj = handleObj; + event.data = handleObj.data; + + ret = ( ( jQuery.event.special[ handleObj.origType ] || {} ).handle || + handleObj.handler ).apply( matched.elem, args ); + + if ( ret !== undefined ) { + if ( ( event.result = ret ) === false ) { + event.preventDefault(); + event.stopPropagation(); + } + } + } + } + } + + // Call the postDispatch hook for the mapped type + if ( special.postDispatch ) { + special.postDispatch.call( this, event ); + } + + return event.result; + }, + + handlers: function( event, handlers ) { + var i, handleObj, sel, matchedHandlers, matchedSelectors, + handlerQueue = [], + delegateCount = handlers.delegateCount, + cur = event.target; + + // Find delegate handlers + if ( delegateCount && + + // Support: IE <=9 + // Black-hole SVG instance trees (trac-13180) + cur.nodeType && + + // Support: Firefox <=42 + // Suppress spec-violating clicks indicating a non-primary pointer button (trac-3861) + // https://www.w3.org/TR/DOM-Level-3-Events/#event-type-click + // Support: IE 11 only + // ...but not arrow key "clicks" of radio inputs, which can have `button` -1 (gh-2343) + !( event.type === "click" && event.button >= 1 ) ) { + + for ( ; cur !== this; cur = cur.parentNode || this ) { + + // Don't check non-elements (#13208) + // Don't process clicks on disabled elements (#6911, #8165, #11382, #11764) + if ( cur.nodeType === 1 && !( event.type === "click" && cur.disabled === true ) ) { + matchedHandlers = []; + matchedSelectors = {}; + for ( i = 0; i < delegateCount; i++ ) { + handleObj = handlers[ i ]; + + // Don't conflict with Object.prototype properties (#13203) + sel = handleObj.selector + " "; + + if ( matchedSelectors[ sel ] === undefined ) { + matchedSelectors[ sel ] = handleObj.needsContext ? + jQuery( sel, this ).index( cur ) > -1 : + jQuery.find( sel, this, null, [ cur ] ).length; + } + if ( matchedSelectors[ sel ] ) { + matchedHandlers.push( handleObj ); + } + } + if ( matchedHandlers.length ) { + handlerQueue.push( { elem: cur, handlers: matchedHandlers } ); + } + } + } + } + + // Add the remaining (directly-bound) handlers + cur = this; + if ( delegateCount < handlers.length ) { + handlerQueue.push( { elem: cur, handlers: handlers.slice( delegateCount ) } ); + } + + return handlerQueue; + }, + + addProp: function( name, hook ) { + Object.defineProperty( jQuery.Event.prototype, name, { + enumerable: true, + configurable: true, + + get: isFunction( hook ) ? + function() { + if ( this.originalEvent ) { + return hook( this.originalEvent ); + } + } : + function() { + if ( this.originalEvent ) { + return this.originalEvent[ name ]; + } + }, + + set: function( value ) { + Object.defineProperty( this, name, { + enumerable: true, + configurable: true, + writable: true, + value: value + } ); + } + } ); + }, + + fix: function( originalEvent ) { + return originalEvent[ jQuery.expando ] ? + originalEvent : + new jQuery.Event( originalEvent ); + }, + + special: { + load: { + + // Prevent triggered image.load events from bubbling to window.load + noBubble: true + }, + click: { + + // Utilize native event to ensure correct state for checkable inputs + setup: function( data ) { + + // For mutual compressibility with _default, replace `this` access with a local var. + // `|| data` is dead code meant only to preserve the variable through minification. + var el = this || data; + + // Claim the first handler + if ( rcheckableType.test( el.type ) && + el.click && nodeName( el, "input" ) ) { + + // dataPriv.set( el, "click", ... ) + leverageNative( el, "click", returnTrue ); + } + + // Return false to allow normal processing in the caller + return false; + }, + trigger: function( data ) { + + // For mutual compressibility with _default, replace `this` access with a local var. + // `|| data` is dead code meant only to preserve the variable through minification. + var el = this || data; + + // Force setup before triggering a click + if ( rcheckableType.test( el.type ) && + el.click && nodeName( el, "input" ) ) { + + leverageNative( el, "click" ); + } + + // Return non-false to allow normal event-path propagation + return true; + }, + + // For cross-browser consistency, suppress native .click() on links + // Also prevent it if we're currently inside a leveraged native-event stack + _default: function( event ) { + var target = event.target; + return rcheckableType.test( target.type ) && + target.click && nodeName( target, "input" ) && + dataPriv.get( target, "click" ) || + nodeName( target, "a" ); + } + }, + + beforeunload: { + postDispatch: function( event ) { + + // Support: Firefox 20+ + // Firefox doesn't alert if the returnValue field is not set. + if ( event.result !== undefined && event.originalEvent ) { + event.originalEvent.returnValue = event.result; + } + } + } + } +}; + +// Ensure the presence of an event listener that handles manually-triggered +// synthetic events by interrupting progress until reinvoked in response to +// *native* events that it fires directly, ensuring that state changes have +// already occurred before other listeners are invoked. +function leverageNative( el, type, expectSync ) { + + // Missing expectSync indicates a trigger call, which must force setup through jQuery.event.add + if ( !expectSync ) { + if ( dataPriv.get( el, type ) === undefined ) { + jQuery.event.add( el, type, returnTrue ); + } + return; + } + + // Register the controller as a special universal handler for all event namespaces + dataPriv.set( el, type, false ); + jQuery.event.add( el, type, { + namespace: false, + handler: function( event ) { + var notAsync, result, + saved = dataPriv.get( this, type ); + + if ( ( event.isTrigger & 1 ) && this[ type ] ) { + + // Interrupt processing of the outer synthetic .trigger()ed event + // Saved data should be false in such cases, but might be a leftover capture object + // from an async native handler (gh-4350) + if ( !saved.length ) { + + // Store arguments for use when handling the inner native event + // There will always be at least one argument (an event object), so this array + // will not be confused with a leftover capture object. + saved = slice.call( arguments ); + dataPriv.set( this, type, saved ); + + // Trigger the native event and capture its result + // Support: IE <=9 - 11+ + // focus() and blur() are asynchronous + notAsync = expectSync( this, type ); + this[ type ](); + result = dataPriv.get( this, type ); + if ( saved !== result || notAsync ) { + dataPriv.set( this, type, false ); + } else { + result = {}; + } + if ( saved !== result ) { + + // Cancel the outer synthetic event + event.stopImmediatePropagation(); + event.preventDefault(); + return result.value; + } + + // If this is an inner synthetic event for an event with a bubbling surrogate + // (focus or blur), assume that the surrogate already propagated from triggering the + // native event and prevent that from happening again here. + // This technically gets the ordering wrong w.r.t. to `.trigger()` (in which the + // bubbling surrogate propagates *after* the non-bubbling base), but that seems + // less bad than duplication. + } else if ( ( jQuery.event.special[ type ] || {} ).delegateType ) { + event.stopPropagation(); + } + + // If this is a native event triggered above, everything is now in order + // Fire an inner synthetic event with the original arguments + } else if ( saved.length ) { + + // ...and capture the result + dataPriv.set( this, type, { + value: jQuery.event.trigger( + + // Support: IE <=9 - 11+ + // Extend with the prototype to reset the above stopImmediatePropagation() + jQuery.extend( saved[ 0 ], jQuery.Event.prototype ), + saved.slice( 1 ), + this + ) + } ); + + // Abort handling of the native event + event.stopImmediatePropagation(); + } + } + } ); +} + +jQuery.removeEvent = function( elem, type, handle ) { + + // This "if" is needed for plain objects + if ( elem.removeEventListener ) { + elem.removeEventListener( type, handle ); + } +}; + +jQuery.Event = function( src, props ) { + + // Allow instantiation without the 'new' keyword + if ( !( this instanceof jQuery.Event ) ) { + return new jQuery.Event( src, props ); + } + + // Event object + if ( src && src.type ) { + this.originalEvent = src; + this.type = src.type; + + // Events bubbling up the document may have been marked as prevented + // by a handler lower down the tree; reflect the correct value. + this.isDefaultPrevented = src.defaultPrevented || + src.defaultPrevented === undefined && + + // Support: Android <=2.3 only + src.returnValue === false ? + returnTrue : + returnFalse; + + // Create target properties + // Support: Safari <=6 - 7 only + // Target should not be a text node (#504, #13143) + this.target = ( src.target && src.target.nodeType === 3 ) ? + src.target.parentNode : + src.target; + + this.currentTarget = src.currentTarget; + this.relatedTarget = src.relatedTarget; + + // Event type + } else { + this.type = src; + } + + // Put explicitly provided properties onto the event object + if ( props ) { + jQuery.extend( this, props ); + } + + // Create a timestamp if incoming event doesn't have one + this.timeStamp = src && src.timeStamp || Date.now(); + + // Mark it as fixed + this[ jQuery.expando ] = true; +}; + +// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding +// https://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html +jQuery.Event.prototype = { + constructor: jQuery.Event, + isDefaultPrevented: returnFalse, + isPropagationStopped: returnFalse, + isImmediatePropagationStopped: returnFalse, + isSimulated: false, + + preventDefault: function() { + var e = this.originalEvent; + + this.isDefaultPrevented = returnTrue; + + if ( e && !this.isSimulated ) { + e.preventDefault(); + } + }, + stopPropagation: function() { + var e = this.originalEvent; + + this.isPropagationStopped = returnTrue; + + if ( e && !this.isSimulated ) { + e.stopPropagation(); + } + }, + stopImmediatePropagation: function() { + var e = this.originalEvent; + + this.isImmediatePropagationStopped = returnTrue; + + if ( e && !this.isSimulated ) { + e.stopImmediatePropagation(); + } + + this.stopPropagation(); + } +}; + +// Includes all common event props including KeyEvent and MouseEvent specific props +jQuery.each( { + altKey: true, + bubbles: true, + cancelable: true, + changedTouches: true, + ctrlKey: true, + detail: true, + eventPhase: true, + metaKey: true, + pageX: true, + pageY: true, + shiftKey: true, + view: true, + "char": true, + code: true, + charCode: true, + key: true, + keyCode: true, + button: true, + buttons: true, + clientX: true, + clientY: true, + offsetX: true, + offsetY: true, + pointerId: true, + pointerType: true, + screenX: true, + screenY: true, + targetTouches: true, + toElement: true, + touches: true, + + which: function( event ) { + var button = event.button; + + // Add which for key events + if ( event.which == null && rkeyEvent.test( event.type ) ) { + return event.charCode != null ? event.charCode : event.keyCode; + } + + // Add which for click: 1 === left; 2 === middle; 3 === right + if ( !event.which && button !== undefined && rmouseEvent.test( event.type ) ) { + if ( button & 1 ) { + return 1; + } + + if ( button & 2 ) { + return 3; + } + + if ( button & 4 ) { + return 2; + } + + return 0; + } + + return event.which; + } +}, jQuery.event.addProp ); + +jQuery.each( { focus: "focusin", blur: "focusout" }, function( type, delegateType ) { + jQuery.event.special[ type ] = { + + // Utilize native event if possible so blur/focus sequence is correct + setup: function() { + + // Claim the first handler + // dataPriv.set( this, "focus", ... ) + // dataPriv.set( this, "blur", ... ) + leverageNative( this, type, expectSync ); + + // Return false to allow normal processing in the caller + return false; + }, + trigger: function() { + + // Force setup before trigger + leverageNative( this, type ); + + // Return non-false to allow normal event-path propagation + return true; + }, + + delegateType: delegateType + }; +} ); + +// Create mouseenter/leave events using mouseover/out and event-time checks +// so that event delegation works in jQuery. +// Do the same for pointerenter/pointerleave and pointerover/pointerout +// +// Support: Safari 7 only +// Safari sends mouseenter too often; see: +// https://bugs.chromium.org/p/chromium/issues/detail?id=470258 +// for the description of the bug (it existed in older Chrome versions as well). +jQuery.each( { + mouseenter: "mouseover", + mouseleave: "mouseout", + pointerenter: "pointerover", + pointerleave: "pointerout" +}, function( orig, fix ) { + jQuery.event.special[ orig ] = { + delegateType: fix, + bindType: fix, + + handle: function( event ) { + var ret, + target = this, + related = event.relatedTarget, + handleObj = event.handleObj; + + // For mouseenter/leave call the handler if related is outside the target. + // NB: No relatedTarget if the mouse left/entered the browser window + if ( !related || ( related !== target && !jQuery.contains( target, related ) ) ) { + event.type = handleObj.origType; + ret = handleObj.handler.apply( this, arguments ); + event.type = fix; + } + return ret; + } + }; +} ); + +jQuery.fn.extend( { + + on: function( types, selector, data, fn ) { + return on( this, types, selector, data, fn ); + }, + one: function( types, selector, data, fn ) { + return on( this, types, selector, data, fn, 1 ); + }, + off: function( types, selector, fn ) { + var handleObj, type; + if ( types && types.preventDefault && types.handleObj ) { + + // ( event ) dispatched jQuery.Event + handleObj = types.handleObj; + jQuery( types.delegateTarget ).off( + handleObj.namespace ? + handleObj.origType + "." + handleObj.namespace : + handleObj.origType, + handleObj.selector, + handleObj.handler + ); + return this; + } + if ( typeof types === "object" ) { + + // ( types-object [, selector] ) + for ( type in types ) { + this.off( type, selector, types[ type ] ); + } + return this; + } + if ( selector === false || typeof selector === "function" ) { + + // ( types [, fn] ) + fn = selector; + selector = undefined; + } + if ( fn === false ) { + fn = returnFalse; + } + return this.each( function() { + jQuery.event.remove( this, types, fn, selector ); + } ); + } +} ); + + +var + + // Support: IE <=10 - 11, Edge 12 - 13 only + // In IE/Edge using regex groups here causes severe slowdowns. + // See https://connect.microsoft.com/IE/feedback/details/1736512/ + rnoInnerhtml = /\s*$/g; + +// Prefer a tbody over its parent table for containing new rows +function manipulationTarget( elem, content ) { + if ( nodeName( elem, "table" ) && + nodeName( content.nodeType !== 11 ? content : content.firstChild, "tr" ) ) { + + return jQuery( elem ).children( "tbody" )[ 0 ] || elem; + } + + return elem; +} + +// Replace/restore the type attribute of script elements for safe DOM manipulation +function disableScript( elem ) { + elem.type = ( elem.getAttribute( "type" ) !== null ) + "/" + elem.type; + return elem; +} +function restoreScript( elem ) { + if ( ( elem.type || "" ).slice( 0, 5 ) === "true/" ) { + elem.type = elem.type.slice( 5 ); + } else { + elem.removeAttribute( "type" ); + } + + return elem; +} + +function cloneCopyEvent( src, dest ) { + var i, l, type, pdataOld, udataOld, udataCur, events; + + if ( dest.nodeType !== 1 ) { + return; + } + + // 1. Copy private data: events, handlers, etc. + if ( dataPriv.hasData( src ) ) { + pdataOld = dataPriv.get( src ); + events = pdataOld.events; + + if ( events ) { + dataPriv.remove( dest, "handle events" ); + + for ( type in events ) { + for ( i = 0, l = events[ type ].length; i < l; i++ ) { + jQuery.event.add( dest, type, events[ type ][ i ] ); + } + } + } + } + + // 2. Copy user data + if ( dataUser.hasData( src ) ) { + udataOld = dataUser.access( src ); + udataCur = jQuery.extend( {}, udataOld ); + + dataUser.set( dest, udataCur ); + } +} + +// Fix IE bugs, see support tests +function fixInput( src, dest ) { + var nodeName = dest.nodeName.toLowerCase(); + + // Fails to persist the checked state of a cloned checkbox or radio button. + if ( nodeName === "input" && rcheckableType.test( src.type ) ) { + dest.checked = src.checked; + + // Fails to return the selected option to the default selected state when cloning options + } else if ( nodeName === "input" || nodeName === "textarea" ) { + dest.defaultValue = src.defaultValue; + } +} + +function domManip( collection, args, callback, ignored ) { + + // Flatten any nested arrays + args = flat( args ); + + var fragment, first, scripts, hasScripts, node, doc, + i = 0, + l = collection.length, + iNoClone = l - 1, + value = args[ 0 ], + valueIsFunction = isFunction( value ); + + // We can't cloneNode fragments that contain checked, in WebKit + if ( valueIsFunction || + ( l > 1 && typeof value === "string" && + !support.checkClone && rchecked.test( value ) ) ) { + return collection.each( function( index ) { + var self = collection.eq( index ); + if ( valueIsFunction ) { + args[ 0 ] = value.call( this, index, self.html() ); + } + domManip( self, args, callback, ignored ); + } ); + } + + if ( l ) { + fragment = buildFragment( args, collection[ 0 ].ownerDocument, false, collection, ignored ); + first = fragment.firstChild; + + if ( fragment.childNodes.length === 1 ) { + fragment = first; + } + + // Require either new content or an interest in ignored elements to invoke the callback + if ( first || ignored ) { + scripts = jQuery.map( getAll( fragment, "script" ), disableScript ); + hasScripts = scripts.length; + + // Use the original fragment for the last item + // instead of the first because it can end up + // being emptied incorrectly in certain situations (#8070). + for ( ; i < l; i++ ) { + node = fragment; + + if ( i !== iNoClone ) { + node = jQuery.clone( node, true, true ); + + // Keep references to cloned scripts for later restoration + if ( hasScripts ) { + + // Support: Android <=4.0 only, PhantomJS 1 only + // push.apply(_, arraylike) throws on ancient WebKit + jQuery.merge( scripts, getAll( node, "script" ) ); + } + } + + callback.call( collection[ i ], node, i ); + } + + if ( hasScripts ) { + doc = scripts[ scripts.length - 1 ].ownerDocument; + + // Reenable scripts + jQuery.map( scripts, restoreScript ); + + // Evaluate executable scripts on first document insertion + for ( i = 0; i < hasScripts; i++ ) { + node = scripts[ i ]; + if ( rscriptType.test( node.type || "" ) && + !dataPriv.access( node, "globalEval" ) && + jQuery.contains( doc, node ) ) { + + if ( node.src && ( node.type || "" ).toLowerCase() !== "module" ) { + + // Optional AJAX dependency, but won't run scripts if not present + if ( jQuery._evalUrl && !node.noModule ) { + jQuery._evalUrl( node.src, { + nonce: node.nonce || node.getAttribute( "nonce" ) + }, doc ); + } + } else { + DOMEval( node.textContent.replace( rcleanScript, "" ), node, doc ); + } + } + } + } + } + } + + return collection; +} + +function remove( elem, selector, keepData ) { + var node, + nodes = selector ? jQuery.filter( selector, elem ) : elem, + i = 0; + + for ( ; ( node = nodes[ i ] ) != null; i++ ) { + if ( !keepData && node.nodeType === 1 ) { + jQuery.cleanData( getAll( node ) ); + } + + if ( node.parentNode ) { + if ( keepData && isAttached( node ) ) { + setGlobalEval( getAll( node, "script" ) ); + } + node.parentNode.removeChild( node ); + } + } + + return elem; +} + +jQuery.extend( { + htmlPrefilter: function( html ) { + return html; + }, + + clone: function( elem, dataAndEvents, deepDataAndEvents ) { + var i, l, srcElements, destElements, + clone = elem.cloneNode( true ), + inPage = isAttached( elem ); + + // Fix IE cloning issues + if ( !support.noCloneChecked && ( elem.nodeType === 1 || elem.nodeType === 11 ) && + !jQuery.isXMLDoc( elem ) ) { + + // We eschew Sizzle here for performance reasons: https://jsperf.com/getall-vs-sizzle/2 + destElements = getAll( clone ); + srcElements = getAll( elem ); + + for ( i = 0, l = srcElements.length; i < l; i++ ) { + fixInput( srcElements[ i ], destElements[ i ] ); + } + } + + // Copy the events from the original to the clone + if ( dataAndEvents ) { + if ( deepDataAndEvents ) { + srcElements = srcElements || getAll( elem ); + destElements = destElements || getAll( clone ); + + for ( i = 0, l = srcElements.length; i < l; i++ ) { + cloneCopyEvent( srcElements[ i ], destElements[ i ] ); + } + } else { + cloneCopyEvent( elem, clone ); + } + } + + // Preserve script evaluation history + destElements = getAll( clone, "script" ); + if ( destElements.length > 0 ) { + setGlobalEval( destElements, !inPage && getAll( elem, "script" ) ); + } + + // Return the cloned set + return clone; + }, + + cleanData: function( elems ) { + var data, elem, type, + special = jQuery.event.special, + i = 0; + + for ( ; ( elem = elems[ i ] ) !== undefined; i++ ) { + if ( acceptData( elem ) ) { + if ( ( data = elem[ dataPriv.expando ] ) ) { + if ( data.events ) { + for ( type in data.events ) { + if ( special[ type ] ) { + jQuery.event.remove( elem, type ); + + // This is a shortcut to avoid jQuery.event.remove's overhead + } else { + jQuery.removeEvent( elem, type, data.handle ); + } + } + } + + // Support: Chrome <=35 - 45+ + // Assign undefined instead of using delete, see Data#remove + elem[ dataPriv.expando ] = undefined; + } + if ( elem[ dataUser.expando ] ) { + + // Support: Chrome <=35 - 45+ + // Assign undefined instead of using delete, see Data#remove + elem[ dataUser.expando ] = undefined; + } + } + } + } +} ); + +jQuery.fn.extend( { + detach: function( selector ) { + return remove( this, selector, true ); + }, + + remove: function( selector ) { + return remove( this, selector ); + }, + + text: function( value ) { + return access( this, function( value ) { + return value === undefined ? + jQuery.text( this ) : + this.empty().each( function() { + if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { + this.textContent = value; + } + } ); + }, null, value, arguments.length ); + }, + + append: function() { + return domManip( this, arguments, function( elem ) { + if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { + var target = manipulationTarget( this, elem ); + target.appendChild( elem ); + } + } ); + }, + + prepend: function() { + return domManip( this, arguments, function( elem ) { + if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { + var target = manipulationTarget( this, elem ); + target.insertBefore( elem, target.firstChild ); + } + } ); + }, + + before: function() { + return domManip( this, arguments, function( elem ) { + if ( this.parentNode ) { + this.parentNode.insertBefore( elem, this ); + } + } ); + }, + + after: function() { + return domManip( this, arguments, function( elem ) { + if ( this.parentNode ) { + this.parentNode.insertBefore( elem, this.nextSibling ); + } + } ); + }, + + empty: function() { + var elem, + i = 0; + + for ( ; ( elem = this[ i ] ) != null; i++ ) { + if ( elem.nodeType === 1 ) { + + // Prevent memory leaks + jQuery.cleanData( getAll( elem, false ) ); + + // Remove any remaining nodes + elem.textContent = ""; + } + } + + return this; + }, + + clone: function( dataAndEvents, deepDataAndEvents ) { + dataAndEvents = dataAndEvents == null ? false : dataAndEvents; + deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents; + + return this.map( function() { + return jQuery.clone( this, dataAndEvents, deepDataAndEvents ); + } ); + }, + + html: function( value ) { + return access( this, function( value ) { + var elem = this[ 0 ] || {}, + i = 0, + l = this.length; + + if ( value === undefined && elem.nodeType === 1 ) { + return elem.innerHTML; + } + + // See if we can take a shortcut and just use innerHTML + if ( typeof value === "string" && !rnoInnerhtml.test( value ) && + !wrapMap[ ( rtagName.exec( value ) || [ "", "" ] )[ 1 ].toLowerCase() ] ) { + + value = jQuery.htmlPrefilter( value ); + + try { + for ( ; i < l; i++ ) { + elem = this[ i ] || {}; + + // Remove element nodes and prevent memory leaks + if ( elem.nodeType === 1 ) { + jQuery.cleanData( getAll( elem, false ) ); + elem.innerHTML = value; + } + } + + elem = 0; + + // If using innerHTML throws an exception, use the fallback method + } catch ( e ) {} + } + + if ( elem ) { + this.empty().append( value ); + } + }, null, value, arguments.length ); + }, + + replaceWith: function() { + var ignored = []; + + // Make the changes, replacing each non-ignored context element with the new content + return domManip( this, arguments, function( elem ) { + var parent = this.parentNode; + + if ( jQuery.inArray( this, ignored ) < 0 ) { + jQuery.cleanData( getAll( this ) ); + if ( parent ) { + parent.replaceChild( elem, this ); + } + } + + // Force callback invocation + }, ignored ); + } +} ); + +jQuery.each( { + appendTo: "append", + prependTo: "prepend", + insertBefore: "before", + insertAfter: "after", + replaceAll: "replaceWith" +}, function( name, original ) { + jQuery.fn[ name ] = function( selector ) { + var elems, + ret = [], + insert = jQuery( selector ), + last = insert.length - 1, + i = 0; + + for ( ; i <= last; i++ ) { + elems = i === last ? this : this.clone( true ); + jQuery( insert[ i ] )[ original ]( elems ); + + // Support: Android <=4.0 only, PhantomJS 1 only + // .get() because push.apply(_, arraylike) throws on ancient WebKit + push.apply( ret, elems.get() ); + } + + return this.pushStack( ret ); + }; +} ); +var rnumnonpx = new RegExp( "^(" + pnum + ")(?!px)[a-z%]+$", "i" ); + +var getStyles = function( elem ) { + + // Support: IE <=11 only, Firefox <=30 (#15098, #14150) + // IE throws on elements created in popups + // FF meanwhile throws on frame elements through "defaultView.getComputedStyle" + var view = elem.ownerDocument.defaultView; + + if ( !view || !view.opener ) { + view = window; + } + + return view.getComputedStyle( elem ); + }; + +var swap = function( elem, options, callback ) { + var ret, name, + old = {}; + + // Remember the old values, and insert the new ones + for ( name in options ) { + old[ name ] = elem.style[ name ]; + elem.style[ name ] = options[ name ]; + } + + ret = callback.call( elem ); + + // Revert the old values + for ( name in options ) { + elem.style[ name ] = old[ name ]; + } + + return ret; +}; + + +var rboxStyle = new RegExp( cssExpand.join( "|" ), "i" ); + + + +( function() { + + // Executing both pixelPosition & boxSizingReliable tests require only one layout + // so they're executed at the same time to save the second computation. + function computeStyleTests() { + + // This is a singleton, we need to execute it only once + if ( !div ) { + return; + } + + container.style.cssText = "position:absolute;left:-11111px;width:60px;" + + "margin-top:1px;padding:0;border:0"; + div.style.cssText = + "position:relative;display:block;box-sizing:border-box;overflow:scroll;" + + "margin:auto;border:1px;padding:1px;" + + "width:60%;top:1%"; + documentElement.appendChild( container ).appendChild( div ); + + var divStyle = window.getComputedStyle( div ); + pixelPositionVal = divStyle.top !== "1%"; + + // Support: Android 4.0 - 4.3 only, Firefox <=3 - 44 + reliableMarginLeftVal = roundPixelMeasures( divStyle.marginLeft ) === 12; + + // Support: Android 4.0 - 4.3 only, Safari <=9.1 - 10.1, iOS <=7.0 - 9.3 + // Some styles come back with percentage values, even though they shouldn't + div.style.right = "60%"; + pixelBoxStylesVal = roundPixelMeasures( divStyle.right ) === 36; + + // Support: IE 9 - 11 only + // Detect misreporting of content dimensions for box-sizing:border-box elements + boxSizingReliableVal = roundPixelMeasures( divStyle.width ) === 36; + + // Support: IE 9 only + // Detect overflow:scroll screwiness (gh-3699) + // Support: Chrome <=64 + // Don't get tricked when zoom affects offsetWidth (gh-4029) + div.style.position = "absolute"; + scrollboxSizeVal = roundPixelMeasures( div.offsetWidth / 3 ) === 12; + + documentElement.removeChild( container ); + + // Nullify the div so it wouldn't be stored in the memory and + // it will also be a sign that checks already performed + div = null; + } + + function roundPixelMeasures( measure ) { + return Math.round( parseFloat( measure ) ); + } + + var pixelPositionVal, boxSizingReliableVal, scrollboxSizeVal, pixelBoxStylesVal, + reliableTrDimensionsVal, reliableMarginLeftVal, + container = document.createElement( "div" ), + div = document.createElement( "div" ); + + // Finish early in limited (non-browser) environments + if ( !div.style ) { + return; + } + + // Support: IE <=9 - 11 only + // Style of cloned element affects source element cloned (#8908) + div.style.backgroundClip = "content-box"; + div.cloneNode( true ).style.backgroundClip = ""; + support.clearCloneStyle = div.style.backgroundClip === "content-box"; + + jQuery.extend( support, { + boxSizingReliable: function() { + computeStyleTests(); + return boxSizingReliableVal; + }, + pixelBoxStyles: function() { + computeStyleTests(); + return pixelBoxStylesVal; + }, + pixelPosition: function() { + computeStyleTests(); + return pixelPositionVal; + }, + reliableMarginLeft: function() { + computeStyleTests(); + return reliableMarginLeftVal; + }, + scrollboxSize: function() { + computeStyleTests(); + return scrollboxSizeVal; + }, + + // Support: IE 9 - 11+, Edge 15 - 18+ + // IE/Edge misreport `getComputedStyle` of table rows with width/height + // set in CSS while `offset*` properties report correct values. + // Behavior in IE 9 is more subtle than in newer versions & it passes + // some versions of this test; make sure not to make it pass there! + reliableTrDimensions: function() { + var table, tr, trChild, trStyle; + if ( reliableTrDimensionsVal == null ) { + table = document.createElement( "table" ); + tr = document.createElement( "tr" ); + trChild = document.createElement( "div" ); + + table.style.cssText = "position:absolute;left:-11111px"; + tr.style.height = "1px"; + trChild.style.height = "9px"; + + documentElement + .appendChild( table ) + .appendChild( tr ) + .appendChild( trChild ); + + trStyle = window.getComputedStyle( tr ); + reliableTrDimensionsVal = parseInt( trStyle.height ) > 3; + + documentElement.removeChild( table ); + } + return reliableTrDimensionsVal; + } + } ); +} )(); + + +function curCSS( elem, name, computed ) { + var width, minWidth, maxWidth, ret, + + // Support: Firefox 51+ + // Retrieving style before computed somehow + // fixes an issue with getting wrong values + // on detached elements + style = elem.style; + + computed = computed || getStyles( elem ); + + // getPropertyValue is needed for: + // .css('filter') (IE 9 only, #12537) + // .css('--customProperty) (#3144) + if ( computed ) { + ret = computed.getPropertyValue( name ) || computed[ name ]; + + if ( ret === "" && !isAttached( elem ) ) { + ret = jQuery.style( elem, name ); + } + + // A tribute to the "awesome hack by Dean Edwards" + // Android Browser returns percentage for some values, + // but width seems to be reliably pixels. + // This is against the CSSOM draft spec: + // https://drafts.csswg.org/cssom/#resolved-values + if ( !support.pixelBoxStyles() && rnumnonpx.test( ret ) && rboxStyle.test( name ) ) { + + // Remember the original values + width = style.width; + minWidth = style.minWidth; + maxWidth = style.maxWidth; + + // Put in the new values to get a computed value out + style.minWidth = style.maxWidth = style.width = ret; + ret = computed.width; + + // Revert the changed values + style.width = width; + style.minWidth = minWidth; + style.maxWidth = maxWidth; + } + } + + return ret !== undefined ? + + // Support: IE <=9 - 11 only + // IE returns zIndex value as an integer. + ret + "" : + ret; +} + + +function addGetHookIf( conditionFn, hookFn ) { + + // Define the hook, we'll check on the first run if it's really needed. + return { + get: function() { + if ( conditionFn() ) { + + // Hook not needed (or it's not possible to use it due + // to missing dependency), remove it. + delete this.get; + return; + } + + // Hook needed; redefine it so that the support test is not executed again. + return ( this.get = hookFn ).apply( this, arguments ); + } + }; +} + + +var cssPrefixes = [ "Webkit", "Moz", "ms" ], + emptyStyle = document.createElement( "div" ).style, + vendorProps = {}; + +// Return a vendor-prefixed property or undefined +function vendorPropName( name ) { + + // Check for vendor prefixed names + var capName = name[ 0 ].toUpperCase() + name.slice( 1 ), + i = cssPrefixes.length; + + while ( i-- ) { + name = cssPrefixes[ i ] + capName; + if ( name in emptyStyle ) { + return name; + } + } +} + +// Return a potentially-mapped jQuery.cssProps or vendor prefixed property +function finalPropName( name ) { + var final = jQuery.cssProps[ name ] || vendorProps[ name ]; + + if ( final ) { + return final; + } + if ( name in emptyStyle ) { + return name; + } + return vendorProps[ name ] = vendorPropName( name ) || name; +} + + +var + + // Swappable if display is none or starts with table + // except "table", "table-cell", or "table-caption" + // See here for display values: https://developer.mozilla.org/en-US/docs/CSS/display + rdisplayswap = /^(none|table(?!-c[ea]).+)/, + rcustomProp = /^--/, + cssShow = { position: "absolute", visibility: "hidden", display: "block" }, + cssNormalTransform = { + letterSpacing: "0", + fontWeight: "400" + }; + +function setPositiveNumber( _elem, value, subtract ) { + + // Any relative (+/-) values have already been + // normalized at this point + var matches = rcssNum.exec( value ); + return matches ? + + // Guard against undefined "subtract", e.g., when used as in cssHooks + Math.max( 0, matches[ 2 ] - ( subtract || 0 ) ) + ( matches[ 3 ] || "px" ) : + value; +} + +function boxModelAdjustment( elem, dimension, box, isBorderBox, styles, computedVal ) { + var i = dimension === "width" ? 1 : 0, + extra = 0, + delta = 0; + + // Adjustment may not be necessary + if ( box === ( isBorderBox ? "border" : "content" ) ) { + return 0; + } + + for ( ; i < 4; i += 2 ) { + + // Both box models exclude margin + if ( box === "margin" ) { + delta += jQuery.css( elem, box + cssExpand[ i ], true, styles ); + } + + // If we get here with a content-box, we're seeking "padding" or "border" or "margin" + if ( !isBorderBox ) { + + // Add padding + delta += jQuery.css( elem, "padding" + cssExpand[ i ], true, styles ); + + // For "border" or "margin", add border + if ( box !== "padding" ) { + delta += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); + + // But still keep track of it otherwise + } else { + extra += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); + } + + // If we get here with a border-box (content + padding + border), we're seeking "content" or + // "padding" or "margin" + } else { + + // For "content", subtract padding + if ( box === "content" ) { + delta -= jQuery.css( elem, "padding" + cssExpand[ i ], true, styles ); + } + + // For "content" or "padding", subtract border + if ( box !== "margin" ) { + delta -= jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); + } + } + } + + // Account for positive content-box scroll gutter when requested by providing computedVal + if ( !isBorderBox && computedVal >= 0 ) { + + // offsetWidth/offsetHeight is a rounded sum of content, padding, scroll gutter, and border + // Assuming integer scroll gutter, subtract the rest and round down + delta += Math.max( 0, Math.ceil( + elem[ "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ) ] - + computedVal - + delta - + extra - + 0.5 + + // If offsetWidth/offsetHeight is unknown, then we can't determine content-box scroll gutter + // Use an explicit zero to avoid NaN (gh-3964) + ) ) || 0; + } + + return delta; +} + +function getWidthOrHeight( elem, dimension, extra ) { + + // Start with computed style + var styles = getStyles( elem ), + + // To avoid forcing a reflow, only fetch boxSizing if we need it (gh-4322). + // Fake content-box until we know it's needed to know the true value. + boxSizingNeeded = !support.boxSizingReliable() || extra, + isBorderBox = boxSizingNeeded && + jQuery.css( elem, "boxSizing", false, styles ) === "border-box", + valueIsBorderBox = isBorderBox, + + val = curCSS( elem, dimension, styles ), + offsetProp = "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ); + + // Support: Firefox <=54 + // Return a confounding non-pixel value or feign ignorance, as appropriate. + if ( rnumnonpx.test( val ) ) { + if ( !extra ) { + return val; + } + val = "auto"; + } + + + // Support: IE 9 - 11 only + // Use offsetWidth/offsetHeight for when box sizing is unreliable. + // In those cases, the computed value can be trusted to be border-box. + if ( ( !support.boxSizingReliable() && isBorderBox || + + // Support: IE 10 - 11+, Edge 15 - 18+ + // IE/Edge misreport `getComputedStyle` of table rows with width/height + // set in CSS while `offset*` properties report correct values. + // Interestingly, in some cases IE 9 doesn't suffer from this issue. + !support.reliableTrDimensions() && nodeName( elem, "tr" ) || + + // Fall back to offsetWidth/offsetHeight when value is "auto" + // This happens for inline elements with no explicit setting (gh-3571) + val === "auto" || + + // Support: Android <=4.1 - 4.3 only + // Also use offsetWidth/offsetHeight for misreported inline dimensions (gh-3602) + !parseFloat( val ) && jQuery.css( elem, "display", false, styles ) === "inline" ) && + + // Make sure the element is visible & connected + elem.getClientRects().length ) { + + isBorderBox = jQuery.css( elem, "boxSizing", false, styles ) === "border-box"; + + // Where available, offsetWidth/offsetHeight approximate border box dimensions. + // Where not available (e.g., SVG), assume unreliable box-sizing and interpret the + // retrieved value as a content box dimension. + valueIsBorderBox = offsetProp in elem; + if ( valueIsBorderBox ) { + val = elem[ offsetProp ]; + } + } + + // Normalize "" and auto + val = parseFloat( val ) || 0; + + // Adjust for the element's box model + return ( val + + boxModelAdjustment( + elem, + dimension, + extra || ( isBorderBox ? "border" : "content" ), + valueIsBorderBox, + styles, + + // Provide the current computed size to request scroll gutter calculation (gh-3589) + val + ) + ) + "px"; +} + +jQuery.extend( { + + // Add in style property hooks for overriding the default + // behavior of getting and setting a style property + cssHooks: { + opacity: { + get: function( elem, computed ) { + if ( computed ) { + + // We should always get a number back from opacity + var ret = curCSS( elem, "opacity" ); + return ret === "" ? "1" : ret; + } + } + } + }, + + // Don't automatically add "px" to these possibly-unitless properties + cssNumber: { + "animationIterationCount": true, + "columnCount": true, + "fillOpacity": true, + "flexGrow": true, + "flexShrink": true, + "fontWeight": true, + "gridArea": true, + "gridColumn": true, + "gridColumnEnd": true, + "gridColumnStart": true, + "gridRow": true, + "gridRowEnd": true, + "gridRowStart": true, + "lineHeight": true, + "opacity": true, + "order": true, + "orphans": true, + "widows": true, + "zIndex": true, + "zoom": true + }, + + // Add in properties whose names you wish to fix before + // setting or getting the value + cssProps: {}, + + // Get and set the style property on a DOM Node + style: function( elem, name, value, extra ) { + + // Don't set styles on text and comment nodes + if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) { + return; + } + + // Make sure that we're working with the right name + var ret, type, hooks, + origName = camelCase( name ), + isCustomProp = rcustomProp.test( name ), + style = elem.style; + + // Make sure that we're working with the right name. We don't + // want to query the value if it is a CSS custom property + // since they are user-defined. + if ( !isCustomProp ) { + name = finalPropName( origName ); + } + + // Gets hook for the prefixed version, then unprefixed version + hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ]; + + // Check if we're setting a value + if ( value !== undefined ) { + type = typeof value; + + // Convert "+=" or "-=" to relative numbers (#7345) + if ( type === "string" && ( ret = rcssNum.exec( value ) ) && ret[ 1 ] ) { + value = adjustCSS( elem, name, ret ); + + // Fixes bug #9237 + type = "number"; + } + + // Make sure that null and NaN values aren't set (#7116) + if ( value == null || value !== value ) { + return; + } + + // If a number was passed in, add the unit (except for certain CSS properties) + // The isCustomProp check can be removed in jQuery 4.0 when we only auto-append + // "px" to a few hardcoded values. + if ( type === "number" && !isCustomProp ) { + value += ret && ret[ 3 ] || ( jQuery.cssNumber[ origName ] ? "" : "px" ); + } + + // background-* props affect original clone's values + if ( !support.clearCloneStyle && value === "" && name.indexOf( "background" ) === 0 ) { + style[ name ] = "inherit"; + } + + // If a hook was provided, use that value, otherwise just set the specified value + if ( !hooks || !( "set" in hooks ) || + ( value = hooks.set( elem, value, extra ) ) !== undefined ) { + + if ( isCustomProp ) { + style.setProperty( name, value ); + } else { + style[ name ] = value; + } + } + + } else { + + // If a hook was provided get the non-computed value from there + if ( hooks && "get" in hooks && + ( ret = hooks.get( elem, false, extra ) ) !== undefined ) { + + return ret; + } + + // Otherwise just get the value from the style object + return style[ name ]; + } + }, + + css: function( elem, name, extra, styles ) { + var val, num, hooks, + origName = camelCase( name ), + isCustomProp = rcustomProp.test( name ); + + // Make sure that we're working with the right name. We don't + // want to modify the value if it is a CSS custom property + // since they are user-defined. + if ( !isCustomProp ) { + name = finalPropName( origName ); + } + + // Try prefixed name followed by the unprefixed name + hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ]; + + // If a hook was provided get the computed value from there + if ( hooks && "get" in hooks ) { + val = hooks.get( elem, true, extra ); + } + + // Otherwise, if a way to get the computed value exists, use that + if ( val === undefined ) { + val = curCSS( elem, name, styles ); + } + + // Convert "normal" to computed value + if ( val === "normal" && name in cssNormalTransform ) { + val = cssNormalTransform[ name ]; + } + + // Make numeric if forced or a qualifier was provided and val looks numeric + if ( extra === "" || extra ) { + num = parseFloat( val ); + return extra === true || isFinite( num ) ? num || 0 : val; + } + + return val; + } +} ); + +jQuery.each( [ "height", "width" ], function( _i, dimension ) { + jQuery.cssHooks[ dimension ] = { + get: function( elem, computed, extra ) { + if ( computed ) { + + // Certain elements can have dimension info if we invisibly show them + // but it must have a current display style that would benefit + return rdisplayswap.test( jQuery.css( elem, "display" ) ) && + + // Support: Safari 8+ + // Table columns in Safari have non-zero offsetWidth & zero + // getBoundingClientRect().width unless display is changed. + // Support: IE <=11 only + // Running getBoundingClientRect on a disconnected node + // in IE throws an error. + ( !elem.getClientRects().length || !elem.getBoundingClientRect().width ) ? + swap( elem, cssShow, function() { + return getWidthOrHeight( elem, dimension, extra ); + } ) : + getWidthOrHeight( elem, dimension, extra ); + } + }, + + set: function( elem, value, extra ) { + var matches, + styles = getStyles( elem ), + + // Only read styles.position if the test has a chance to fail + // to avoid forcing a reflow. + scrollboxSizeBuggy = !support.scrollboxSize() && + styles.position === "absolute", + + // To avoid forcing a reflow, only fetch boxSizing if we need it (gh-3991) + boxSizingNeeded = scrollboxSizeBuggy || extra, + isBorderBox = boxSizingNeeded && + jQuery.css( elem, "boxSizing", false, styles ) === "border-box", + subtract = extra ? + boxModelAdjustment( + elem, + dimension, + extra, + isBorderBox, + styles + ) : + 0; + + // Account for unreliable border-box dimensions by comparing offset* to computed and + // faking a content-box to get border and padding (gh-3699) + if ( isBorderBox && scrollboxSizeBuggy ) { + subtract -= Math.ceil( + elem[ "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ) ] - + parseFloat( styles[ dimension ] ) - + boxModelAdjustment( elem, dimension, "border", false, styles ) - + 0.5 + ); + } + + // Convert to pixels if value adjustment is needed + if ( subtract && ( matches = rcssNum.exec( value ) ) && + ( matches[ 3 ] || "px" ) !== "px" ) { + + elem.style[ dimension ] = value; + value = jQuery.css( elem, dimension ); + } + + return setPositiveNumber( elem, value, subtract ); + } + }; +} ); + +jQuery.cssHooks.marginLeft = addGetHookIf( support.reliableMarginLeft, + function( elem, computed ) { + if ( computed ) { + return ( parseFloat( curCSS( elem, "marginLeft" ) ) || + elem.getBoundingClientRect().left - + swap( elem, { marginLeft: 0 }, function() { + return elem.getBoundingClientRect().left; + } ) + ) + "px"; + } + } +); + +// These hooks are used by animate to expand properties +jQuery.each( { + margin: "", + padding: "", + border: "Width" +}, function( prefix, suffix ) { + jQuery.cssHooks[ prefix + suffix ] = { + expand: function( value ) { + var i = 0, + expanded = {}, + + // Assumes a single number if not a string + parts = typeof value === "string" ? value.split( " " ) : [ value ]; + + for ( ; i < 4; i++ ) { + expanded[ prefix + cssExpand[ i ] + suffix ] = + parts[ i ] || parts[ i - 2 ] || parts[ 0 ]; + } + + return expanded; + } + }; + + if ( prefix !== "margin" ) { + jQuery.cssHooks[ prefix + suffix ].set = setPositiveNumber; + } +} ); + +jQuery.fn.extend( { + css: function( name, value ) { + return access( this, function( elem, name, value ) { + var styles, len, + map = {}, + i = 0; + + if ( Array.isArray( name ) ) { + styles = getStyles( elem ); + len = name.length; + + for ( ; i < len; i++ ) { + map[ name[ i ] ] = jQuery.css( elem, name[ i ], false, styles ); + } + + return map; + } + + return value !== undefined ? + jQuery.style( elem, name, value ) : + jQuery.css( elem, name ); + }, name, value, arguments.length > 1 ); + } +} ); + + +function Tween( elem, options, prop, end, easing ) { + return new Tween.prototype.init( elem, options, prop, end, easing ); +} +jQuery.Tween = Tween; + +Tween.prototype = { + constructor: Tween, + init: function( elem, options, prop, end, easing, unit ) { + this.elem = elem; + this.prop = prop; + this.easing = easing || jQuery.easing._default; + this.options = options; + this.start = this.now = this.cur(); + this.end = end; + this.unit = unit || ( jQuery.cssNumber[ prop ] ? "" : "px" ); + }, + cur: function() { + var hooks = Tween.propHooks[ this.prop ]; + + return hooks && hooks.get ? + hooks.get( this ) : + Tween.propHooks._default.get( this ); + }, + run: function( percent ) { + var eased, + hooks = Tween.propHooks[ this.prop ]; + + if ( this.options.duration ) { + this.pos = eased = jQuery.easing[ this.easing ]( + percent, this.options.duration * percent, 0, 1, this.options.duration + ); + } else { + this.pos = eased = percent; + } + this.now = ( this.end - this.start ) * eased + this.start; + + if ( this.options.step ) { + this.options.step.call( this.elem, this.now, this ); + } + + if ( hooks && hooks.set ) { + hooks.set( this ); + } else { + Tween.propHooks._default.set( this ); + } + return this; + } +}; + +Tween.prototype.init.prototype = Tween.prototype; + +Tween.propHooks = { + _default: { + get: function( tween ) { + var result; + + // Use a property on the element directly when it is not a DOM element, + // or when there is no matching style property that exists. + if ( tween.elem.nodeType !== 1 || + tween.elem[ tween.prop ] != null && tween.elem.style[ tween.prop ] == null ) { + return tween.elem[ tween.prop ]; + } + + // Passing an empty string as a 3rd parameter to .css will automatically + // attempt a parseFloat and fallback to a string if the parse fails. + // Simple values such as "10px" are parsed to Float; + // complex values such as "rotate(1rad)" are returned as-is. + result = jQuery.css( tween.elem, tween.prop, "" ); + + // Empty strings, null, undefined and "auto" are converted to 0. + return !result || result === "auto" ? 0 : result; + }, + set: function( tween ) { + + // Use step hook for back compat. + // Use cssHook if its there. + // Use .style if available and use plain properties where available. + if ( jQuery.fx.step[ tween.prop ] ) { + jQuery.fx.step[ tween.prop ]( tween ); + } else if ( tween.elem.nodeType === 1 && ( + jQuery.cssHooks[ tween.prop ] || + tween.elem.style[ finalPropName( tween.prop ) ] != null ) ) { + jQuery.style( tween.elem, tween.prop, tween.now + tween.unit ); + } else { + tween.elem[ tween.prop ] = tween.now; + } + } + } +}; + +// Support: IE <=9 only +// Panic based approach to setting things on disconnected nodes +Tween.propHooks.scrollTop = Tween.propHooks.scrollLeft = { + set: function( tween ) { + if ( tween.elem.nodeType && tween.elem.parentNode ) { + tween.elem[ tween.prop ] = tween.now; + } + } +}; + +jQuery.easing = { + linear: function( p ) { + return p; + }, + swing: function( p ) { + return 0.5 - Math.cos( p * Math.PI ) / 2; + }, + _default: "swing" +}; + +jQuery.fx = Tween.prototype.init; + +// Back compat <1.8 extension point +jQuery.fx.step = {}; + + + + +var + fxNow, inProgress, + rfxtypes = /^(?:toggle|show|hide)$/, + rrun = /queueHooks$/; + +function schedule() { + if ( inProgress ) { + if ( document.hidden === false && window.requestAnimationFrame ) { + window.requestAnimationFrame( schedule ); + } else { + window.setTimeout( schedule, jQuery.fx.interval ); + } + + jQuery.fx.tick(); + } +} + +// Animations created synchronously will run synchronously +function createFxNow() { + window.setTimeout( function() { + fxNow = undefined; + } ); + return ( fxNow = Date.now() ); +} + +// Generate parameters to create a standard animation +function genFx( type, includeWidth ) { + var which, + i = 0, + attrs = { height: type }; + + // If we include width, step value is 1 to do all cssExpand values, + // otherwise step value is 2 to skip over Left and Right + includeWidth = includeWidth ? 1 : 0; + for ( ; i < 4; i += 2 - includeWidth ) { + which = cssExpand[ i ]; + attrs[ "margin" + which ] = attrs[ "padding" + which ] = type; + } + + if ( includeWidth ) { + attrs.opacity = attrs.width = type; + } + + return attrs; +} + +function createTween( value, prop, animation ) { + var tween, + collection = ( Animation.tweeners[ prop ] || [] ).concat( Animation.tweeners[ "*" ] ), + index = 0, + length = collection.length; + for ( ; index < length; index++ ) { + if ( ( tween = collection[ index ].call( animation, prop, value ) ) ) { + + // We're done with this property + return tween; + } + } +} + +function defaultPrefilter( elem, props, opts ) { + var prop, value, toggle, hooks, oldfire, propTween, restoreDisplay, display, + isBox = "width" in props || "height" in props, + anim = this, + orig = {}, + style = elem.style, + hidden = elem.nodeType && isHiddenWithinTree( elem ), + dataShow = dataPriv.get( elem, "fxshow" ); + + // Queue-skipping animations hijack the fx hooks + if ( !opts.queue ) { + hooks = jQuery._queueHooks( elem, "fx" ); + if ( hooks.unqueued == null ) { + hooks.unqueued = 0; + oldfire = hooks.empty.fire; + hooks.empty.fire = function() { + if ( !hooks.unqueued ) { + oldfire(); + } + }; + } + hooks.unqueued++; + + anim.always( function() { + + // Ensure the complete handler is called before this completes + anim.always( function() { + hooks.unqueued--; + if ( !jQuery.queue( elem, "fx" ).length ) { + hooks.empty.fire(); + } + } ); + } ); + } + + // Detect show/hide animations + for ( prop in props ) { + value = props[ prop ]; + if ( rfxtypes.test( value ) ) { + delete props[ prop ]; + toggle = toggle || value === "toggle"; + if ( value === ( hidden ? "hide" : "show" ) ) { + + // Pretend to be hidden if this is a "show" and + // there is still data from a stopped show/hide + if ( value === "show" && dataShow && dataShow[ prop ] !== undefined ) { + hidden = true; + + // Ignore all other no-op show/hide data + } else { + continue; + } + } + orig[ prop ] = dataShow && dataShow[ prop ] || jQuery.style( elem, prop ); + } + } + + // Bail out if this is a no-op like .hide().hide() + propTween = !jQuery.isEmptyObject( props ); + if ( !propTween && jQuery.isEmptyObject( orig ) ) { + return; + } + + // Restrict "overflow" and "display" styles during box animations + if ( isBox && elem.nodeType === 1 ) { + + // Support: IE <=9 - 11, Edge 12 - 15 + // Record all 3 overflow attributes because IE does not infer the shorthand + // from identically-valued overflowX and overflowY and Edge just mirrors + // the overflowX value there. + opts.overflow = [ style.overflow, style.overflowX, style.overflowY ]; + + // Identify a display type, preferring old show/hide data over the CSS cascade + restoreDisplay = dataShow && dataShow.display; + if ( restoreDisplay == null ) { + restoreDisplay = dataPriv.get( elem, "display" ); + } + display = jQuery.css( elem, "display" ); + if ( display === "none" ) { + if ( restoreDisplay ) { + display = restoreDisplay; + } else { + + // Get nonempty value(s) by temporarily forcing visibility + showHide( [ elem ], true ); + restoreDisplay = elem.style.display || restoreDisplay; + display = jQuery.css( elem, "display" ); + showHide( [ elem ] ); + } + } + + // Animate inline elements as inline-block + if ( display === "inline" || display === "inline-block" && restoreDisplay != null ) { + if ( jQuery.css( elem, "float" ) === "none" ) { + + // Restore the original display value at the end of pure show/hide animations + if ( !propTween ) { + anim.done( function() { + style.display = restoreDisplay; + } ); + if ( restoreDisplay == null ) { + display = style.display; + restoreDisplay = display === "none" ? "" : display; + } + } + style.display = "inline-block"; + } + } + } + + if ( opts.overflow ) { + style.overflow = "hidden"; + anim.always( function() { + style.overflow = opts.overflow[ 0 ]; + style.overflowX = opts.overflow[ 1 ]; + style.overflowY = opts.overflow[ 2 ]; + } ); + } + + // Implement show/hide animations + propTween = false; + for ( prop in orig ) { + + // General show/hide setup for this element animation + if ( !propTween ) { + if ( dataShow ) { + if ( "hidden" in dataShow ) { + hidden = dataShow.hidden; + } + } else { + dataShow = dataPriv.access( elem, "fxshow", { display: restoreDisplay } ); + } + + // Store hidden/visible for toggle so `.stop().toggle()` "reverses" + if ( toggle ) { + dataShow.hidden = !hidden; + } + + // Show elements before animating them + if ( hidden ) { + showHide( [ elem ], true ); + } + + /* eslint-disable no-loop-func */ + + anim.done( function() { + + /* eslint-enable no-loop-func */ + + // The final step of a "hide" animation is actually hiding the element + if ( !hidden ) { + showHide( [ elem ] ); + } + dataPriv.remove( elem, "fxshow" ); + for ( prop in orig ) { + jQuery.style( elem, prop, orig[ prop ] ); + } + } ); + } + + // Per-property setup + propTween = createTween( hidden ? dataShow[ prop ] : 0, prop, anim ); + if ( !( prop in dataShow ) ) { + dataShow[ prop ] = propTween.start; + if ( hidden ) { + propTween.end = propTween.start; + propTween.start = 0; + } + } + } +} + +function propFilter( props, specialEasing ) { + var index, name, easing, value, hooks; + + // camelCase, specialEasing and expand cssHook pass + for ( index in props ) { + name = camelCase( index ); + easing = specialEasing[ name ]; + value = props[ index ]; + if ( Array.isArray( value ) ) { + easing = value[ 1 ]; + value = props[ index ] = value[ 0 ]; + } + + if ( index !== name ) { + props[ name ] = value; + delete props[ index ]; + } + + hooks = jQuery.cssHooks[ name ]; + if ( hooks && "expand" in hooks ) { + value = hooks.expand( value ); + delete props[ name ]; + + // Not quite $.extend, this won't overwrite existing keys. + // Reusing 'index' because we have the correct "name" + for ( index in value ) { + if ( !( index in props ) ) { + props[ index ] = value[ index ]; + specialEasing[ index ] = easing; + } + } + } else { + specialEasing[ name ] = easing; + } + } +} + +function Animation( elem, properties, options ) { + var result, + stopped, + index = 0, + length = Animation.prefilters.length, + deferred = jQuery.Deferred().always( function() { + + // Don't match elem in the :animated selector + delete tick.elem; + } ), + tick = function() { + if ( stopped ) { + return false; + } + var currentTime = fxNow || createFxNow(), + remaining = Math.max( 0, animation.startTime + animation.duration - currentTime ), + + // Support: Android 2.3 only + // Archaic crash bug won't allow us to use `1 - ( 0.5 || 0 )` (#12497) + temp = remaining / animation.duration || 0, + percent = 1 - temp, + index = 0, + length = animation.tweens.length; + + for ( ; index < length; index++ ) { + animation.tweens[ index ].run( percent ); + } + + deferred.notifyWith( elem, [ animation, percent, remaining ] ); + + // If there's more to do, yield + if ( percent < 1 && length ) { + return remaining; + } + + // If this was an empty animation, synthesize a final progress notification + if ( !length ) { + deferred.notifyWith( elem, [ animation, 1, 0 ] ); + } + + // Resolve the animation and report its conclusion + deferred.resolveWith( elem, [ animation ] ); + return false; + }, + animation = deferred.promise( { + elem: elem, + props: jQuery.extend( {}, properties ), + opts: jQuery.extend( true, { + specialEasing: {}, + easing: jQuery.easing._default + }, options ), + originalProperties: properties, + originalOptions: options, + startTime: fxNow || createFxNow(), + duration: options.duration, + tweens: [], + createTween: function( prop, end ) { + var tween = jQuery.Tween( elem, animation.opts, prop, end, + animation.opts.specialEasing[ prop ] || animation.opts.easing ); + animation.tweens.push( tween ); + return tween; + }, + stop: function( gotoEnd ) { + var index = 0, + + // If we are going to the end, we want to run all the tweens + // otherwise we skip this part + length = gotoEnd ? animation.tweens.length : 0; + if ( stopped ) { + return this; + } + stopped = true; + for ( ; index < length; index++ ) { + animation.tweens[ index ].run( 1 ); + } + + // Resolve when we played the last frame; otherwise, reject + if ( gotoEnd ) { + deferred.notifyWith( elem, [ animation, 1, 0 ] ); + deferred.resolveWith( elem, [ animation, gotoEnd ] ); + } else { + deferred.rejectWith( elem, [ animation, gotoEnd ] ); + } + return this; + } + } ), + props = animation.props; + + propFilter( props, animation.opts.specialEasing ); + + for ( ; index < length; index++ ) { + result = Animation.prefilters[ index ].call( animation, elem, props, animation.opts ); + if ( result ) { + if ( isFunction( result.stop ) ) { + jQuery._queueHooks( animation.elem, animation.opts.queue ).stop = + result.stop.bind( result ); + } + return result; + } + } + + jQuery.map( props, createTween, animation ); + + if ( isFunction( animation.opts.start ) ) { + animation.opts.start.call( elem, animation ); + } + + // Attach callbacks from options + animation + .progress( animation.opts.progress ) + .done( animation.opts.done, animation.opts.complete ) + .fail( animation.opts.fail ) + .always( animation.opts.always ); + + jQuery.fx.timer( + jQuery.extend( tick, { + elem: elem, + anim: animation, + queue: animation.opts.queue + } ) + ); + + return animation; +} + +jQuery.Animation = jQuery.extend( Animation, { + + tweeners: { + "*": [ function( prop, value ) { + var tween = this.createTween( prop, value ); + adjustCSS( tween.elem, prop, rcssNum.exec( value ), tween ); + return tween; + } ] + }, + + tweener: function( props, callback ) { + if ( isFunction( props ) ) { + callback = props; + props = [ "*" ]; + } else { + props = props.match( rnothtmlwhite ); + } + + var prop, + index = 0, + length = props.length; + + for ( ; index < length; index++ ) { + prop = props[ index ]; + Animation.tweeners[ prop ] = Animation.tweeners[ prop ] || []; + Animation.tweeners[ prop ].unshift( callback ); + } + }, + + prefilters: [ defaultPrefilter ], + + prefilter: function( callback, prepend ) { + if ( prepend ) { + Animation.prefilters.unshift( callback ); + } else { + Animation.prefilters.push( callback ); + } + } +} ); + +jQuery.speed = function( speed, easing, fn ) { + var opt = speed && typeof speed === "object" ? jQuery.extend( {}, speed ) : { + complete: fn || !fn && easing || + isFunction( speed ) && speed, + duration: speed, + easing: fn && easing || easing && !isFunction( easing ) && easing + }; + + // Go to the end state if fx are off + if ( jQuery.fx.off ) { + opt.duration = 0; + + } else { + if ( typeof opt.duration !== "number" ) { + if ( opt.duration in jQuery.fx.speeds ) { + opt.duration = jQuery.fx.speeds[ opt.duration ]; + + } else { + opt.duration = jQuery.fx.speeds._default; + } + } + } + + // Normalize opt.queue - true/undefined/null -> "fx" + if ( opt.queue == null || opt.queue === true ) { + opt.queue = "fx"; + } + + // Queueing + opt.old = opt.complete; + + opt.complete = function() { + if ( isFunction( opt.old ) ) { + opt.old.call( this ); + } + + if ( opt.queue ) { + jQuery.dequeue( this, opt.queue ); + } + }; + + return opt; +}; + +jQuery.fn.extend( { + fadeTo: function( speed, to, easing, callback ) { + + // Show any hidden elements after setting opacity to 0 + return this.filter( isHiddenWithinTree ).css( "opacity", 0 ).show() + + // Animate to the value specified + .end().animate( { opacity: to }, speed, easing, callback ); + }, + animate: function( prop, speed, easing, callback ) { + var empty = jQuery.isEmptyObject( prop ), + optall = jQuery.speed( speed, easing, callback ), + doAnimation = function() { + + // Operate on a copy of prop so per-property easing won't be lost + var anim = Animation( this, jQuery.extend( {}, prop ), optall ); + + // Empty animations, or finishing resolves immediately + if ( empty || dataPriv.get( this, "finish" ) ) { + anim.stop( true ); + } + }; + doAnimation.finish = doAnimation; + + return empty || optall.queue === false ? + this.each( doAnimation ) : + this.queue( optall.queue, doAnimation ); + }, + stop: function( type, clearQueue, gotoEnd ) { + var stopQueue = function( hooks ) { + var stop = hooks.stop; + delete hooks.stop; + stop( gotoEnd ); + }; + + if ( typeof type !== "string" ) { + gotoEnd = clearQueue; + clearQueue = type; + type = undefined; + } + if ( clearQueue ) { + this.queue( type || "fx", [] ); + } + + return this.each( function() { + var dequeue = true, + index = type != null && type + "queueHooks", + timers = jQuery.timers, + data = dataPriv.get( this ); + + if ( index ) { + if ( data[ index ] && data[ index ].stop ) { + stopQueue( data[ index ] ); + } + } else { + for ( index in data ) { + if ( data[ index ] && data[ index ].stop && rrun.test( index ) ) { + stopQueue( data[ index ] ); + } + } + } + + for ( index = timers.length; index--; ) { + if ( timers[ index ].elem === this && + ( type == null || timers[ index ].queue === type ) ) { + + timers[ index ].anim.stop( gotoEnd ); + dequeue = false; + timers.splice( index, 1 ); + } + } + + // Start the next in the queue if the last step wasn't forced. + // Timers currently will call their complete callbacks, which + // will dequeue but only if they were gotoEnd. + if ( dequeue || !gotoEnd ) { + jQuery.dequeue( this, type ); + } + } ); + }, + finish: function( type ) { + if ( type !== false ) { + type = type || "fx"; + } + return this.each( function() { + var index, + data = dataPriv.get( this ), + queue = data[ type + "queue" ], + hooks = data[ type + "queueHooks" ], + timers = jQuery.timers, + length = queue ? queue.length : 0; + + // Enable finishing flag on private data + data.finish = true; + + // Empty the queue first + jQuery.queue( this, type, [] ); + + if ( hooks && hooks.stop ) { + hooks.stop.call( this, true ); + } + + // Look for any active animations, and finish them + for ( index = timers.length; index--; ) { + if ( timers[ index ].elem === this && timers[ index ].queue === type ) { + timers[ index ].anim.stop( true ); + timers.splice( index, 1 ); + } + } + + // Look for any animations in the old queue and finish them + for ( index = 0; index < length; index++ ) { + if ( queue[ index ] && queue[ index ].finish ) { + queue[ index ].finish.call( this ); + } + } + + // Turn off finishing flag + delete data.finish; + } ); + } +} ); + +jQuery.each( [ "toggle", "show", "hide" ], function( _i, name ) { + var cssFn = jQuery.fn[ name ]; + jQuery.fn[ name ] = function( speed, easing, callback ) { + return speed == null || typeof speed === "boolean" ? + cssFn.apply( this, arguments ) : + this.animate( genFx( name, true ), speed, easing, callback ); + }; +} ); + +// Generate shortcuts for custom animations +jQuery.each( { + slideDown: genFx( "show" ), + slideUp: genFx( "hide" ), + slideToggle: genFx( "toggle" ), + fadeIn: { opacity: "show" }, + fadeOut: { opacity: "hide" }, + fadeToggle: { opacity: "toggle" } +}, function( name, props ) { + jQuery.fn[ name ] = function( speed, easing, callback ) { + return this.animate( props, speed, easing, callback ); + }; +} ); + +jQuery.timers = []; +jQuery.fx.tick = function() { + var timer, + i = 0, + timers = jQuery.timers; + + fxNow = Date.now(); + + for ( ; i < timers.length; i++ ) { + timer = timers[ i ]; + + // Run the timer and safely remove it when done (allowing for external removal) + if ( !timer() && timers[ i ] === timer ) { + timers.splice( i--, 1 ); + } + } + + if ( !timers.length ) { + jQuery.fx.stop(); + } + fxNow = undefined; +}; + +jQuery.fx.timer = function( timer ) { + jQuery.timers.push( timer ); + jQuery.fx.start(); +}; + +jQuery.fx.interval = 13; +jQuery.fx.start = function() { + if ( inProgress ) { + return; + } + + inProgress = true; + schedule(); +}; + +jQuery.fx.stop = function() { + inProgress = null; +}; + +jQuery.fx.speeds = { + slow: 600, + fast: 200, + + // Default speed + _default: 400 +}; + + +// Based off of the plugin by Clint Helfers, with permission. +// https://web.archive.org/web/20100324014747/http://blindsignals.com/index.php/2009/07/jquery-delay/ +jQuery.fn.delay = function( time, type ) { + time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time; + type = type || "fx"; + + return this.queue( type, function( next, hooks ) { + var timeout = window.setTimeout( next, time ); + hooks.stop = function() { + window.clearTimeout( timeout ); + }; + } ); +}; + + +( function() { + var input = document.createElement( "input" ), + select = document.createElement( "select" ), + opt = select.appendChild( document.createElement( "option" ) ); + + input.type = "checkbox"; + + // Support: Android <=4.3 only + // Default value for a checkbox should be "on" + support.checkOn = input.value !== ""; + + // Support: IE <=11 only + // Must access selectedIndex to make default options select + support.optSelected = opt.selected; + + // Support: IE <=11 only + // An input loses its value after becoming a radio + input = document.createElement( "input" ); + input.value = "t"; + input.type = "radio"; + support.radioValue = input.value === "t"; +} )(); + + +var boolHook, + attrHandle = jQuery.expr.attrHandle; + +jQuery.fn.extend( { + attr: function( name, value ) { + return access( this, jQuery.attr, name, value, arguments.length > 1 ); + }, + + removeAttr: function( name ) { + return this.each( function() { + jQuery.removeAttr( this, name ); + } ); + } +} ); + +jQuery.extend( { + attr: function( elem, name, value ) { + var ret, hooks, + nType = elem.nodeType; + + // Don't get/set attributes on text, comment and attribute nodes + if ( nType === 3 || nType === 8 || nType === 2 ) { + return; + } + + // Fallback to prop when attributes are not supported + if ( typeof elem.getAttribute === "undefined" ) { + return jQuery.prop( elem, name, value ); + } + + // Attribute hooks are determined by the lowercase version + // Grab necessary hook if one is defined + if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) { + hooks = jQuery.attrHooks[ name.toLowerCase() ] || + ( jQuery.expr.match.bool.test( name ) ? boolHook : undefined ); + } + + if ( value !== undefined ) { + if ( value === null ) { + jQuery.removeAttr( elem, name ); + return; + } + + if ( hooks && "set" in hooks && + ( ret = hooks.set( elem, value, name ) ) !== undefined ) { + return ret; + } + + elem.setAttribute( name, value + "" ); + return value; + } + + if ( hooks && "get" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) { + return ret; + } + + ret = jQuery.find.attr( elem, name ); + + // Non-existent attributes return null, we normalize to undefined + return ret == null ? undefined : ret; + }, + + attrHooks: { + type: { + set: function( elem, value ) { + if ( !support.radioValue && value === "radio" && + nodeName( elem, "input" ) ) { + var val = elem.value; + elem.setAttribute( "type", value ); + if ( val ) { + elem.value = val; + } + return value; + } + } + } + }, + + removeAttr: function( elem, value ) { + var name, + i = 0, + + // Attribute names can contain non-HTML whitespace characters + // https://html.spec.whatwg.org/multipage/syntax.html#attributes-2 + attrNames = value && value.match( rnothtmlwhite ); + + if ( attrNames && elem.nodeType === 1 ) { + while ( ( name = attrNames[ i++ ] ) ) { + elem.removeAttribute( name ); + } + } + } +} ); + +// Hooks for boolean attributes +boolHook = { + set: function( elem, value, name ) { + if ( value === false ) { + + // Remove boolean attributes when set to false + jQuery.removeAttr( elem, name ); + } else { + elem.setAttribute( name, name ); + } + return name; + } +}; + +jQuery.each( jQuery.expr.match.bool.source.match( /\w+/g ), function( _i, name ) { + var getter = attrHandle[ name ] || jQuery.find.attr; + + attrHandle[ name ] = function( elem, name, isXML ) { + var ret, handle, + lowercaseName = name.toLowerCase(); + + if ( !isXML ) { + + // Avoid an infinite loop by temporarily removing this function from the getter + handle = attrHandle[ lowercaseName ]; + attrHandle[ lowercaseName ] = ret; + ret = getter( elem, name, isXML ) != null ? + lowercaseName : + null; + attrHandle[ lowercaseName ] = handle; + } + return ret; + }; +} ); + + + + +var rfocusable = /^(?:input|select|textarea|button)$/i, + rclickable = /^(?:a|area)$/i; + +jQuery.fn.extend( { + prop: function( name, value ) { + return access( this, jQuery.prop, name, value, arguments.length > 1 ); + }, + + removeProp: function( name ) { + return this.each( function() { + delete this[ jQuery.propFix[ name ] || name ]; + } ); + } +} ); + +jQuery.extend( { + prop: function( elem, name, value ) { + var ret, hooks, + nType = elem.nodeType; + + // Don't get/set properties on text, comment and attribute nodes + if ( nType === 3 || nType === 8 || nType === 2 ) { + return; + } + + if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) { + + // Fix name and attach hooks + name = jQuery.propFix[ name ] || name; + hooks = jQuery.propHooks[ name ]; + } + + if ( value !== undefined ) { + if ( hooks && "set" in hooks && + ( ret = hooks.set( elem, value, name ) ) !== undefined ) { + return ret; + } + + return ( elem[ name ] = value ); + } + + if ( hooks && "get" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) { + return ret; + } + + return elem[ name ]; + }, + + propHooks: { + tabIndex: { + get: function( elem ) { + + // Support: IE <=9 - 11 only + // elem.tabIndex doesn't always return the + // correct value when it hasn't been explicitly set + // https://web.archive.org/web/20141116233347/http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/ + // Use proper attribute retrieval(#12072) + var tabindex = jQuery.find.attr( elem, "tabindex" ); + + if ( tabindex ) { + return parseInt( tabindex, 10 ); + } + + if ( + rfocusable.test( elem.nodeName ) || + rclickable.test( elem.nodeName ) && + elem.href + ) { + return 0; + } + + return -1; + } + } + }, + + propFix: { + "for": "htmlFor", + "class": "className" + } +} ); + +// Support: IE <=11 only +// Accessing the selectedIndex property +// forces the browser to respect setting selected +// on the option +// The getter ensures a default option is selected +// when in an optgroup +// eslint rule "no-unused-expressions" is disabled for this code +// since it considers such accessions noop +if ( !support.optSelected ) { + jQuery.propHooks.selected = { + get: function( elem ) { + + /* eslint no-unused-expressions: "off" */ + + var parent = elem.parentNode; + if ( parent && parent.parentNode ) { + parent.parentNode.selectedIndex; + } + return null; + }, + set: function( elem ) { + + /* eslint no-unused-expressions: "off" */ + + var parent = elem.parentNode; + if ( parent ) { + parent.selectedIndex; + + if ( parent.parentNode ) { + parent.parentNode.selectedIndex; + } + } + } + }; +} + +jQuery.each( [ + "tabIndex", + "readOnly", + "maxLength", + "cellSpacing", + "cellPadding", + "rowSpan", + "colSpan", + "useMap", + "frameBorder", + "contentEditable" +], function() { + jQuery.propFix[ this.toLowerCase() ] = this; +} ); + + + + + // Strip and collapse whitespace according to HTML spec + // https://infra.spec.whatwg.org/#strip-and-collapse-ascii-whitespace + function stripAndCollapse( value ) { + var tokens = value.match( rnothtmlwhite ) || []; + return tokens.join( " " ); + } + + +function getClass( elem ) { + return elem.getAttribute && elem.getAttribute( "class" ) || ""; +} + +function classesToArray( value ) { + if ( Array.isArray( value ) ) { + return value; + } + if ( typeof value === "string" ) { + return value.match( rnothtmlwhite ) || []; + } + return []; +} + +jQuery.fn.extend( { + addClass: function( value ) { + var classes, elem, cur, curValue, clazz, j, finalValue, + i = 0; + + if ( isFunction( value ) ) { + return this.each( function( j ) { + jQuery( this ).addClass( value.call( this, j, getClass( this ) ) ); + } ); + } + + classes = classesToArray( value ); + + if ( classes.length ) { + while ( ( elem = this[ i++ ] ) ) { + curValue = getClass( elem ); + cur = elem.nodeType === 1 && ( " " + stripAndCollapse( curValue ) + " " ); + + if ( cur ) { + j = 0; + while ( ( clazz = classes[ j++ ] ) ) { + if ( cur.indexOf( " " + clazz + " " ) < 0 ) { + cur += clazz + " "; + } + } + + // Only assign if different to avoid unneeded rendering. + finalValue = stripAndCollapse( cur ); + if ( curValue !== finalValue ) { + elem.setAttribute( "class", finalValue ); + } + } + } + } + + return this; + }, + + removeClass: function( value ) { + var classes, elem, cur, curValue, clazz, j, finalValue, + i = 0; + + if ( isFunction( value ) ) { + return this.each( function( j ) { + jQuery( this ).removeClass( value.call( this, j, getClass( this ) ) ); + } ); + } + + if ( !arguments.length ) { + return this.attr( "class", "" ); + } + + classes = classesToArray( value ); + + if ( classes.length ) { + while ( ( elem = this[ i++ ] ) ) { + curValue = getClass( elem ); + + // This expression is here for better compressibility (see addClass) + cur = elem.nodeType === 1 && ( " " + stripAndCollapse( curValue ) + " " ); + + if ( cur ) { + j = 0; + while ( ( clazz = classes[ j++ ] ) ) { + + // Remove *all* instances + while ( cur.indexOf( " " + clazz + " " ) > -1 ) { + cur = cur.replace( " " + clazz + " ", " " ); + } + } + + // Only assign if different to avoid unneeded rendering. + finalValue = stripAndCollapse( cur ); + if ( curValue !== finalValue ) { + elem.setAttribute( "class", finalValue ); + } + } + } + } + + return this; + }, + + toggleClass: function( value, stateVal ) { + var type = typeof value, + isValidValue = type === "string" || Array.isArray( value ); + + if ( typeof stateVal === "boolean" && isValidValue ) { + return stateVal ? this.addClass( value ) : this.removeClass( value ); + } + + if ( isFunction( value ) ) { + return this.each( function( i ) { + jQuery( this ).toggleClass( + value.call( this, i, getClass( this ), stateVal ), + stateVal + ); + } ); + } + + return this.each( function() { + var className, i, self, classNames; + + if ( isValidValue ) { + + // Toggle individual class names + i = 0; + self = jQuery( this ); + classNames = classesToArray( value ); + + while ( ( className = classNames[ i++ ] ) ) { + + // Check each className given, space separated list + if ( self.hasClass( className ) ) { + self.removeClass( className ); + } else { + self.addClass( className ); + } + } + + // Toggle whole class name + } else if ( value === undefined || type === "boolean" ) { + className = getClass( this ); + if ( className ) { + + // Store className if set + dataPriv.set( this, "__className__", className ); + } + + // If the element has a class name or if we're passed `false`, + // then remove the whole classname (if there was one, the above saved it). + // Otherwise bring back whatever was previously saved (if anything), + // falling back to the empty string if nothing was stored. + if ( this.setAttribute ) { + this.setAttribute( "class", + className || value === false ? + "" : + dataPriv.get( this, "__className__" ) || "" + ); + } + } + } ); + }, + + hasClass: function( selector ) { + var className, elem, + i = 0; + + className = " " + selector + " "; + while ( ( elem = this[ i++ ] ) ) { + if ( elem.nodeType === 1 && + ( " " + stripAndCollapse( getClass( elem ) ) + " " ).indexOf( className ) > -1 ) { + return true; + } + } + + return false; + } +} ); + + + + +var rreturn = /\r/g; + +jQuery.fn.extend( { + val: function( value ) { + var hooks, ret, valueIsFunction, + elem = this[ 0 ]; + + if ( !arguments.length ) { + if ( elem ) { + hooks = jQuery.valHooks[ elem.type ] || + jQuery.valHooks[ elem.nodeName.toLowerCase() ]; + + if ( hooks && + "get" in hooks && + ( ret = hooks.get( elem, "value" ) ) !== undefined + ) { + return ret; + } + + ret = elem.value; + + // Handle most common string cases + if ( typeof ret === "string" ) { + return ret.replace( rreturn, "" ); + } + + // Handle cases where value is null/undef or number + return ret == null ? "" : ret; + } + + return; + } + + valueIsFunction = isFunction( value ); + + return this.each( function( i ) { + var val; + + if ( this.nodeType !== 1 ) { + return; + } + + if ( valueIsFunction ) { + val = value.call( this, i, jQuery( this ).val() ); + } else { + val = value; + } + + // Treat null/undefined as ""; convert numbers to string + if ( val == null ) { + val = ""; + + } else if ( typeof val === "number" ) { + val += ""; + + } else if ( Array.isArray( val ) ) { + val = jQuery.map( val, function( value ) { + return value == null ? "" : value + ""; + } ); + } + + hooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ]; + + // If set returns undefined, fall back to normal setting + if ( !hooks || !( "set" in hooks ) || hooks.set( this, val, "value" ) === undefined ) { + this.value = val; + } + } ); + } +} ); + +jQuery.extend( { + valHooks: { + option: { + get: function( elem ) { + + var val = jQuery.find.attr( elem, "value" ); + return val != null ? + val : + + // Support: IE <=10 - 11 only + // option.text throws exceptions (#14686, #14858) + // Strip and collapse whitespace + // https://html.spec.whatwg.org/#strip-and-collapse-whitespace + stripAndCollapse( jQuery.text( elem ) ); + } + }, + select: { + get: function( elem ) { + var value, option, i, + options = elem.options, + index = elem.selectedIndex, + one = elem.type === "select-one", + values = one ? null : [], + max = one ? index + 1 : options.length; + + if ( index < 0 ) { + i = max; + + } else { + i = one ? index : 0; + } + + // Loop through all the selected options + for ( ; i < max; i++ ) { + option = options[ i ]; + + // Support: IE <=9 only + // IE8-9 doesn't update selected after form reset (#2551) + if ( ( option.selected || i === index ) && + + // Don't return options that are disabled or in a disabled optgroup + !option.disabled && + ( !option.parentNode.disabled || + !nodeName( option.parentNode, "optgroup" ) ) ) { + + // Get the specific value for the option + value = jQuery( option ).val(); + + // We don't need an array for one selects + if ( one ) { + return value; + } + + // Multi-Selects return an array + values.push( value ); + } + } + + return values; + }, + + set: function( elem, value ) { + var optionSet, option, + options = elem.options, + values = jQuery.makeArray( value ), + i = options.length; + + while ( i-- ) { + option = options[ i ]; + + /* eslint-disable no-cond-assign */ + + if ( option.selected = + jQuery.inArray( jQuery.valHooks.option.get( option ), values ) > -1 + ) { + optionSet = true; + } + + /* eslint-enable no-cond-assign */ + } + + // Force browsers to behave consistently when non-matching value is set + if ( !optionSet ) { + elem.selectedIndex = -1; + } + return values; + } + } + } +} ); + +// Radios and checkboxes getter/setter +jQuery.each( [ "radio", "checkbox" ], function() { + jQuery.valHooks[ this ] = { + set: function( elem, value ) { + if ( Array.isArray( value ) ) { + return ( elem.checked = jQuery.inArray( jQuery( elem ).val(), value ) > -1 ); + } + } + }; + if ( !support.checkOn ) { + jQuery.valHooks[ this ].get = function( elem ) { + return elem.getAttribute( "value" ) === null ? "on" : elem.value; + }; + } +} ); + + + + +// Return jQuery for attributes-only inclusion + + +support.focusin = "onfocusin" in window; + + +var rfocusMorph = /^(?:focusinfocus|focusoutblur)$/, + stopPropagationCallback = function( e ) { + e.stopPropagation(); + }; + +jQuery.extend( jQuery.event, { + + trigger: function( event, data, elem, onlyHandlers ) { + + var i, cur, tmp, bubbleType, ontype, handle, special, lastElement, + eventPath = [ elem || document ], + type = hasOwn.call( event, "type" ) ? event.type : event, + namespaces = hasOwn.call( event, "namespace" ) ? event.namespace.split( "." ) : []; + + cur = lastElement = tmp = elem = elem || document; + + // Don't do events on text and comment nodes + if ( elem.nodeType === 3 || elem.nodeType === 8 ) { + return; + } + + // focus/blur morphs to focusin/out; ensure we're not firing them right now + if ( rfocusMorph.test( type + jQuery.event.triggered ) ) { + return; + } + + if ( type.indexOf( "." ) > -1 ) { + + // Namespaced trigger; create a regexp to match event type in handle() + namespaces = type.split( "." ); + type = namespaces.shift(); + namespaces.sort(); + } + ontype = type.indexOf( ":" ) < 0 && "on" + type; + + // Caller can pass in a jQuery.Event object, Object, or just an event type string + event = event[ jQuery.expando ] ? + event : + new jQuery.Event( type, typeof event === "object" && event ); + + // Trigger bitmask: & 1 for native handlers; & 2 for jQuery (always true) + event.isTrigger = onlyHandlers ? 2 : 3; + event.namespace = namespaces.join( "." ); + event.rnamespace = event.namespace ? + new RegExp( "(^|\\.)" + namespaces.join( "\\.(?:.*\\.|)" ) + "(\\.|$)" ) : + null; + + // Clean up the event in case it is being reused + event.result = undefined; + if ( !event.target ) { + event.target = elem; + } + + // Clone any incoming data and prepend the event, creating the handler arg list + data = data == null ? + [ event ] : + jQuery.makeArray( data, [ event ] ); + + // Allow special events to draw outside the lines + special = jQuery.event.special[ type ] || {}; + if ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) { + return; + } + + // Determine event propagation path in advance, per W3C events spec (#9951) + // Bubble up to document, then to window; watch for a global ownerDocument var (#9724) + if ( !onlyHandlers && !special.noBubble && !isWindow( elem ) ) { + + bubbleType = special.delegateType || type; + if ( !rfocusMorph.test( bubbleType + type ) ) { + cur = cur.parentNode; + } + for ( ; cur; cur = cur.parentNode ) { + eventPath.push( cur ); + tmp = cur; + } + + // Only add window if we got to document (e.g., not plain obj or detached DOM) + if ( tmp === ( elem.ownerDocument || document ) ) { + eventPath.push( tmp.defaultView || tmp.parentWindow || window ); + } + } + + // Fire handlers on the event path + i = 0; + while ( ( cur = eventPath[ i++ ] ) && !event.isPropagationStopped() ) { + lastElement = cur; + event.type = i > 1 ? + bubbleType : + special.bindType || type; + + // jQuery handler + handle = ( + dataPriv.get( cur, "events" ) || Object.create( null ) + )[ event.type ] && + dataPriv.get( cur, "handle" ); + if ( handle ) { + handle.apply( cur, data ); + } + + // Native handler + handle = ontype && cur[ ontype ]; + if ( handle && handle.apply && acceptData( cur ) ) { + event.result = handle.apply( cur, data ); + if ( event.result === false ) { + event.preventDefault(); + } + } + } + event.type = type; + + // If nobody prevented the default action, do it now + if ( !onlyHandlers && !event.isDefaultPrevented() ) { + + if ( ( !special._default || + special._default.apply( eventPath.pop(), data ) === false ) && + acceptData( elem ) ) { + + // Call a native DOM method on the target with the same name as the event. + // Don't do default actions on window, that's where global variables be (#6170) + if ( ontype && isFunction( elem[ type ] ) && !isWindow( elem ) ) { + + // Don't re-trigger an onFOO event when we call its FOO() method + tmp = elem[ ontype ]; + + if ( tmp ) { + elem[ ontype ] = null; + } + + // Prevent re-triggering of the same event, since we already bubbled it above + jQuery.event.triggered = type; + + if ( event.isPropagationStopped() ) { + lastElement.addEventListener( type, stopPropagationCallback ); + } + + elem[ type ](); + + if ( event.isPropagationStopped() ) { + lastElement.removeEventListener( type, stopPropagationCallback ); + } + + jQuery.event.triggered = undefined; + + if ( tmp ) { + elem[ ontype ] = tmp; + } + } + } + } + + return event.result; + }, + + // Piggyback on a donor event to simulate a different one + // Used only for `focus(in | out)` events + simulate: function( type, elem, event ) { + var e = jQuery.extend( + new jQuery.Event(), + event, + { + type: type, + isSimulated: true + } + ); + + jQuery.event.trigger( e, null, elem ); + } + +} ); + +jQuery.fn.extend( { + + trigger: function( type, data ) { + return this.each( function() { + jQuery.event.trigger( type, data, this ); + } ); + }, + triggerHandler: function( type, data ) { + var elem = this[ 0 ]; + if ( elem ) { + return jQuery.event.trigger( type, data, elem, true ); + } + } +} ); + + +// Support: Firefox <=44 +// Firefox doesn't have focus(in | out) events +// Related ticket - https://bugzilla.mozilla.org/show_bug.cgi?id=687787 +// +// Support: Chrome <=48 - 49, Safari <=9.0 - 9.1 +// focus(in | out) events fire after focus & blur events, +// which is spec violation - http://www.w3.org/TR/DOM-Level-3-Events/#events-focusevent-event-order +// Related ticket - https://bugs.chromium.org/p/chromium/issues/detail?id=449857 +if ( !support.focusin ) { + jQuery.each( { focus: "focusin", blur: "focusout" }, function( orig, fix ) { + + // Attach a single capturing handler on the document while someone wants focusin/focusout + var handler = function( event ) { + jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ) ); + }; + + jQuery.event.special[ fix ] = { + setup: function() { + + // Handle: regular nodes (via `this.ownerDocument`), window + // (via `this.document`) & document (via `this`). + var doc = this.ownerDocument || this.document || this, + attaches = dataPriv.access( doc, fix ); + + if ( !attaches ) { + doc.addEventListener( orig, handler, true ); + } + dataPriv.access( doc, fix, ( attaches || 0 ) + 1 ); + }, + teardown: function() { + var doc = this.ownerDocument || this.document || this, + attaches = dataPriv.access( doc, fix ) - 1; + + if ( !attaches ) { + doc.removeEventListener( orig, handler, true ); + dataPriv.remove( doc, fix ); + + } else { + dataPriv.access( doc, fix, attaches ); + } + } + }; + } ); +} +var location = window.location; + +var nonce = { guid: Date.now() }; + +var rquery = ( /\?/ ); + + + +// Cross-browser xml parsing +jQuery.parseXML = function( data ) { + var xml; + if ( !data || typeof data !== "string" ) { + return null; + } + + // Support: IE 9 - 11 only + // IE throws on parseFromString with invalid input. + try { + xml = ( new window.DOMParser() ).parseFromString( data, "text/xml" ); + } catch ( e ) { + xml = undefined; + } + + if ( !xml || xml.getElementsByTagName( "parsererror" ).length ) { + jQuery.error( "Invalid XML: " + data ); + } + return xml; +}; + + +var + rbracket = /\[\]$/, + rCRLF = /\r?\n/g, + rsubmitterTypes = /^(?:submit|button|image|reset|file)$/i, + rsubmittable = /^(?:input|select|textarea|keygen)/i; + +function buildParams( prefix, obj, traditional, add ) { + var name; + + if ( Array.isArray( obj ) ) { + + // Serialize array item. + jQuery.each( obj, function( i, v ) { + if ( traditional || rbracket.test( prefix ) ) { + + // Treat each array item as a scalar. + add( prefix, v ); + + } else { + + // Item is non-scalar (array or object), encode its numeric index. + buildParams( + prefix + "[" + ( typeof v === "object" && v != null ? i : "" ) + "]", + v, + traditional, + add + ); + } + } ); + + } else if ( !traditional && toType( obj ) === "object" ) { + + // Serialize object item. + for ( name in obj ) { + buildParams( prefix + "[" + name + "]", obj[ name ], traditional, add ); + } + + } else { + + // Serialize scalar item. + add( prefix, obj ); + } +} + +// Serialize an array of form elements or a set of +// key/values into a query string +jQuery.param = function( a, traditional ) { + var prefix, + s = [], + add = function( key, valueOrFunction ) { + + // If value is a function, invoke it and use its return value + var value = isFunction( valueOrFunction ) ? + valueOrFunction() : + valueOrFunction; + + s[ s.length ] = encodeURIComponent( key ) + "=" + + encodeURIComponent( value == null ? "" : value ); + }; + + if ( a == null ) { + return ""; + } + + // If an array was passed in, assume that it is an array of form elements. + if ( Array.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) { + + // Serialize the form elements + jQuery.each( a, function() { + add( this.name, this.value ); + } ); + + } else { + + // If traditional, encode the "old" way (the way 1.3.2 or older + // did it), otherwise encode params recursively. + for ( prefix in a ) { + buildParams( prefix, a[ prefix ], traditional, add ); + } + } + + // Return the resulting serialization + return s.join( "&" ); +}; + +jQuery.fn.extend( { + serialize: function() { + return jQuery.param( this.serializeArray() ); + }, + serializeArray: function() { + return this.map( function() { + + // Can add propHook for "elements" to filter or add form elements + var elements = jQuery.prop( this, "elements" ); + return elements ? jQuery.makeArray( elements ) : this; + } ) + .filter( function() { + var type = this.type; + + // Use .is( ":disabled" ) so that fieldset[disabled] works + return this.name && !jQuery( this ).is( ":disabled" ) && + rsubmittable.test( this.nodeName ) && !rsubmitterTypes.test( type ) && + ( this.checked || !rcheckableType.test( type ) ); + } ) + .map( function( _i, elem ) { + var val = jQuery( this ).val(); + + if ( val == null ) { + return null; + } + + if ( Array.isArray( val ) ) { + return jQuery.map( val, function( val ) { + return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) }; + } ); + } + + return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) }; + } ).get(); + } +} ); + + +var + r20 = /%20/g, + rhash = /#.*$/, + rantiCache = /([?&])_=[^&]*/, + rheaders = /^(.*?):[ \t]*([^\r\n]*)$/mg, + + // #7653, #8125, #8152: local protocol detection + rlocalProtocol = /^(?:about|app|app-storage|.+-extension|file|res|widget):$/, + rnoContent = /^(?:GET|HEAD)$/, + rprotocol = /^\/\//, + + /* Prefilters + * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example) + * 2) These are called: + * - BEFORE asking for a transport + * - AFTER param serialization (s.data is a string if s.processData is true) + * 3) key is the dataType + * 4) the catchall symbol "*" can be used + * 5) execution will start with transport dataType and THEN continue down to "*" if needed + */ + prefilters = {}, + + /* Transports bindings + * 1) key is the dataType + * 2) the catchall symbol "*" can be used + * 3) selection will start with transport dataType and THEN go to "*" if needed + */ + transports = {}, + + // Avoid comment-prolog char sequence (#10098); must appease lint and evade compression + allTypes = "*/".concat( "*" ), + + // Anchor tag for parsing the document origin + originAnchor = document.createElement( "a" ); + originAnchor.href = location.href; + +// Base "constructor" for jQuery.ajaxPrefilter and jQuery.ajaxTransport +function addToPrefiltersOrTransports( structure ) { + + // dataTypeExpression is optional and defaults to "*" + return function( dataTypeExpression, func ) { + + if ( typeof dataTypeExpression !== "string" ) { + func = dataTypeExpression; + dataTypeExpression = "*"; + } + + var dataType, + i = 0, + dataTypes = dataTypeExpression.toLowerCase().match( rnothtmlwhite ) || []; + + if ( isFunction( func ) ) { + + // For each dataType in the dataTypeExpression + while ( ( dataType = dataTypes[ i++ ] ) ) { + + // Prepend if requested + if ( dataType[ 0 ] === "+" ) { + dataType = dataType.slice( 1 ) || "*"; + ( structure[ dataType ] = structure[ dataType ] || [] ).unshift( func ); + + // Otherwise append + } else { + ( structure[ dataType ] = structure[ dataType ] || [] ).push( func ); + } + } + } + }; +} + +// Base inspection function for prefilters and transports +function inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR ) { + + var inspected = {}, + seekingTransport = ( structure === transports ); + + function inspect( dataType ) { + var selected; + inspected[ dataType ] = true; + jQuery.each( structure[ dataType ] || [], function( _, prefilterOrFactory ) { + var dataTypeOrTransport = prefilterOrFactory( options, originalOptions, jqXHR ); + if ( typeof dataTypeOrTransport === "string" && + !seekingTransport && !inspected[ dataTypeOrTransport ] ) { + + options.dataTypes.unshift( dataTypeOrTransport ); + inspect( dataTypeOrTransport ); + return false; + } else if ( seekingTransport ) { + return !( selected = dataTypeOrTransport ); + } + } ); + return selected; + } + + return inspect( options.dataTypes[ 0 ] ) || !inspected[ "*" ] && inspect( "*" ); +} + +// A special extend for ajax options +// that takes "flat" options (not to be deep extended) +// Fixes #9887 +function ajaxExtend( target, src ) { + var key, deep, + flatOptions = jQuery.ajaxSettings.flatOptions || {}; + + for ( key in src ) { + if ( src[ key ] !== undefined ) { + ( flatOptions[ key ] ? target : ( deep || ( deep = {} ) ) )[ key ] = src[ key ]; + } + } + if ( deep ) { + jQuery.extend( true, target, deep ); + } + + return target; +} + +/* Handles responses to an ajax request: + * - finds the right dataType (mediates between content-type and expected dataType) + * - returns the corresponding response + */ +function ajaxHandleResponses( s, jqXHR, responses ) { + + var ct, type, finalDataType, firstDataType, + contents = s.contents, + dataTypes = s.dataTypes; + + // Remove auto dataType and get content-type in the process + while ( dataTypes[ 0 ] === "*" ) { + dataTypes.shift(); + if ( ct === undefined ) { + ct = s.mimeType || jqXHR.getResponseHeader( "Content-Type" ); + } + } + + // Check if we're dealing with a known content-type + if ( ct ) { + for ( type in contents ) { + if ( contents[ type ] && contents[ type ].test( ct ) ) { + dataTypes.unshift( type ); + break; + } + } + } + + // Check to see if we have a response for the expected dataType + if ( dataTypes[ 0 ] in responses ) { + finalDataType = dataTypes[ 0 ]; + } else { + + // Try convertible dataTypes + for ( type in responses ) { + if ( !dataTypes[ 0 ] || s.converters[ type + " " + dataTypes[ 0 ] ] ) { + finalDataType = type; + break; + } + if ( !firstDataType ) { + firstDataType = type; + } + } + + // Or just use first one + finalDataType = finalDataType || firstDataType; + } + + // If we found a dataType + // We add the dataType to the list if needed + // and return the corresponding response + if ( finalDataType ) { + if ( finalDataType !== dataTypes[ 0 ] ) { + dataTypes.unshift( finalDataType ); + } + return responses[ finalDataType ]; + } +} + +/* Chain conversions given the request and the original response + * Also sets the responseXXX fields on the jqXHR instance + */ +function ajaxConvert( s, response, jqXHR, isSuccess ) { + var conv2, current, conv, tmp, prev, + converters = {}, + + // Work with a copy of dataTypes in case we need to modify it for conversion + dataTypes = s.dataTypes.slice(); + + // Create converters map with lowercased keys + if ( dataTypes[ 1 ] ) { + for ( conv in s.converters ) { + converters[ conv.toLowerCase() ] = s.converters[ conv ]; + } + } + + current = dataTypes.shift(); + + // Convert to each sequential dataType + while ( current ) { + + if ( s.responseFields[ current ] ) { + jqXHR[ s.responseFields[ current ] ] = response; + } + + // Apply the dataFilter if provided + if ( !prev && isSuccess && s.dataFilter ) { + response = s.dataFilter( response, s.dataType ); + } + + prev = current; + current = dataTypes.shift(); + + if ( current ) { + + // There's only work to do if current dataType is non-auto + if ( current === "*" ) { + + current = prev; + + // Convert response if prev dataType is non-auto and differs from current + } else if ( prev !== "*" && prev !== current ) { + + // Seek a direct converter + conv = converters[ prev + " " + current ] || converters[ "* " + current ]; + + // If none found, seek a pair + if ( !conv ) { + for ( conv2 in converters ) { + + // If conv2 outputs current + tmp = conv2.split( " " ); + if ( tmp[ 1 ] === current ) { + + // If prev can be converted to accepted input + conv = converters[ prev + " " + tmp[ 0 ] ] || + converters[ "* " + tmp[ 0 ] ]; + if ( conv ) { + + // Condense equivalence converters + if ( conv === true ) { + conv = converters[ conv2 ]; + + // Otherwise, insert the intermediate dataType + } else if ( converters[ conv2 ] !== true ) { + current = tmp[ 0 ]; + dataTypes.unshift( tmp[ 1 ] ); + } + break; + } + } + } + } + + // Apply converter (if not an equivalence) + if ( conv !== true ) { + + // Unless errors are allowed to bubble, catch and return them + if ( conv && s.throws ) { + response = conv( response ); + } else { + try { + response = conv( response ); + } catch ( e ) { + return { + state: "parsererror", + error: conv ? e : "No conversion from " + prev + " to " + current + }; + } + } + } + } + } + } + + return { state: "success", data: response }; +} + +jQuery.extend( { + + // Counter for holding the number of active queries + active: 0, + + // Last-Modified header cache for next request + lastModified: {}, + etag: {}, + + ajaxSettings: { + url: location.href, + type: "GET", + isLocal: rlocalProtocol.test( location.protocol ), + global: true, + processData: true, + async: true, + contentType: "application/x-www-form-urlencoded; charset=UTF-8", + + /* + timeout: 0, + data: null, + dataType: null, + username: null, + password: null, + cache: null, + throws: false, + traditional: false, + headers: {}, + */ + + accepts: { + "*": allTypes, + text: "text/plain", + html: "text/html", + xml: "application/xml, text/xml", + json: "application/json, text/javascript" + }, + + contents: { + xml: /\bxml\b/, + html: /\bhtml/, + json: /\bjson\b/ + }, + + responseFields: { + xml: "responseXML", + text: "responseText", + json: "responseJSON" + }, + + // Data converters + // Keys separate source (or catchall "*") and destination types with a single space + converters: { + + // Convert anything to text + "* text": String, + + // Text to html (true = no transformation) + "text html": true, + + // Evaluate text as a json expression + "text json": JSON.parse, + + // Parse text as xml + "text xml": jQuery.parseXML + }, + + // For options that shouldn't be deep extended: + // you can add your own custom options here if + // and when you create one that shouldn't be + // deep extended (see ajaxExtend) + flatOptions: { + url: true, + context: true + } + }, + + // Creates a full fledged settings object into target + // with both ajaxSettings and settings fields. + // If target is omitted, writes into ajaxSettings. + ajaxSetup: function( target, settings ) { + return settings ? + + // Building a settings object + ajaxExtend( ajaxExtend( target, jQuery.ajaxSettings ), settings ) : + + // Extending ajaxSettings + ajaxExtend( jQuery.ajaxSettings, target ); + }, + + ajaxPrefilter: addToPrefiltersOrTransports( prefilters ), + ajaxTransport: addToPrefiltersOrTransports( transports ), + + // Main method + ajax: function( url, options ) { + + // If url is an object, simulate pre-1.5 signature + if ( typeof url === "object" ) { + options = url; + url = undefined; + } + + // Force options to be an object + options = options || {}; + + var transport, + + // URL without anti-cache param + cacheURL, + + // Response headers + responseHeadersString, + responseHeaders, + + // timeout handle + timeoutTimer, + + // Url cleanup var + urlAnchor, + + // Request state (becomes false upon send and true upon completion) + completed, + + // To know if global events are to be dispatched + fireGlobals, + + // Loop variable + i, + + // uncached part of the url + uncached, + + // Create the final options object + s = jQuery.ajaxSetup( {}, options ), + + // Callbacks context + callbackContext = s.context || s, + + // Context for global events is callbackContext if it is a DOM node or jQuery collection + globalEventContext = s.context && + ( callbackContext.nodeType || callbackContext.jquery ) ? + jQuery( callbackContext ) : + jQuery.event, + + // Deferreds + deferred = jQuery.Deferred(), + completeDeferred = jQuery.Callbacks( "once memory" ), + + // Status-dependent callbacks + statusCode = s.statusCode || {}, + + // Headers (they are sent all at once) + requestHeaders = {}, + requestHeadersNames = {}, + + // Default abort message + strAbort = "canceled", + + // Fake xhr + jqXHR = { + readyState: 0, + + // Builds headers hashtable if needed + getResponseHeader: function( key ) { + var match; + if ( completed ) { + if ( !responseHeaders ) { + responseHeaders = {}; + while ( ( match = rheaders.exec( responseHeadersString ) ) ) { + responseHeaders[ match[ 1 ].toLowerCase() + " " ] = + ( responseHeaders[ match[ 1 ].toLowerCase() + " " ] || [] ) + .concat( match[ 2 ] ); + } + } + match = responseHeaders[ key.toLowerCase() + " " ]; + } + return match == null ? null : match.join( ", " ); + }, + + // Raw string + getAllResponseHeaders: function() { + return completed ? responseHeadersString : null; + }, + + // Caches the header + setRequestHeader: function( name, value ) { + if ( completed == null ) { + name = requestHeadersNames[ name.toLowerCase() ] = + requestHeadersNames[ name.toLowerCase() ] || name; + requestHeaders[ name ] = value; + } + return this; + }, + + // Overrides response content-type header + overrideMimeType: function( type ) { + if ( completed == null ) { + s.mimeType = type; + } + return this; + }, + + // Status-dependent callbacks + statusCode: function( map ) { + var code; + if ( map ) { + if ( completed ) { + + // Execute the appropriate callbacks + jqXHR.always( map[ jqXHR.status ] ); + } else { + + // Lazy-add the new callbacks in a way that preserves old ones + for ( code in map ) { + statusCode[ code ] = [ statusCode[ code ], map[ code ] ]; + } + } + } + return this; + }, + + // Cancel the request + abort: function( statusText ) { + var finalText = statusText || strAbort; + if ( transport ) { + transport.abort( finalText ); + } + done( 0, finalText ); + return this; + } + }; + + // Attach deferreds + deferred.promise( jqXHR ); + + // Add protocol if not provided (prefilters might expect it) + // Handle falsy url in the settings object (#10093: consistency with old signature) + // We also use the url parameter if available + s.url = ( ( url || s.url || location.href ) + "" ) + .replace( rprotocol, location.protocol + "//" ); + + // Alias method option to type as per ticket #12004 + s.type = options.method || options.type || s.method || s.type; + + // Extract dataTypes list + s.dataTypes = ( s.dataType || "*" ).toLowerCase().match( rnothtmlwhite ) || [ "" ]; + + // A cross-domain request is in order when the origin doesn't match the current origin. + if ( s.crossDomain == null ) { + urlAnchor = document.createElement( "a" ); + + // Support: IE <=8 - 11, Edge 12 - 15 + // IE throws exception on accessing the href property if url is malformed, + // e.g. http://example.com:80x/ + try { + urlAnchor.href = s.url; + + // Support: IE <=8 - 11 only + // Anchor's host property isn't correctly set when s.url is relative + urlAnchor.href = urlAnchor.href; + s.crossDomain = originAnchor.protocol + "//" + originAnchor.host !== + urlAnchor.protocol + "//" + urlAnchor.host; + } catch ( e ) { + + // If there is an error parsing the URL, assume it is crossDomain, + // it can be rejected by the transport if it is invalid + s.crossDomain = true; + } + } + + // Convert data if not already a string + if ( s.data && s.processData && typeof s.data !== "string" ) { + s.data = jQuery.param( s.data, s.traditional ); + } + + // Apply prefilters + inspectPrefiltersOrTransports( prefilters, s, options, jqXHR ); + + // If request was aborted inside a prefilter, stop there + if ( completed ) { + return jqXHR; + } + + // We can fire global events as of now if asked to + // Don't fire events if jQuery.event is undefined in an AMD-usage scenario (#15118) + fireGlobals = jQuery.event && s.global; + + // Watch for a new set of requests + if ( fireGlobals && jQuery.active++ === 0 ) { + jQuery.event.trigger( "ajaxStart" ); + } + + // Uppercase the type + s.type = s.type.toUpperCase(); + + // Determine if request has content + s.hasContent = !rnoContent.test( s.type ); + + // Save the URL in case we're toying with the If-Modified-Since + // and/or If-None-Match header later on + // Remove hash to simplify url manipulation + cacheURL = s.url.replace( rhash, "" ); + + // More options handling for requests with no content + if ( !s.hasContent ) { + + // Remember the hash so we can put it back + uncached = s.url.slice( cacheURL.length ); + + // If data is available and should be processed, append data to url + if ( s.data && ( s.processData || typeof s.data === "string" ) ) { + cacheURL += ( rquery.test( cacheURL ) ? "&" : "?" ) + s.data; + + // #9682: remove data so that it's not used in an eventual retry + delete s.data; + } + + // Add or update anti-cache param if needed + if ( s.cache === false ) { + cacheURL = cacheURL.replace( rantiCache, "$1" ); + uncached = ( rquery.test( cacheURL ) ? "&" : "?" ) + "_=" + ( nonce.guid++ ) + + uncached; + } + + // Put hash and anti-cache on the URL that will be requested (gh-1732) + s.url = cacheURL + uncached; + + // Change '%20' to '+' if this is encoded form body content (gh-2658) + } else if ( s.data && s.processData && + ( s.contentType || "" ).indexOf( "application/x-www-form-urlencoded" ) === 0 ) { + s.data = s.data.replace( r20, "+" ); + } + + // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode. + if ( s.ifModified ) { + if ( jQuery.lastModified[ cacheURL ] ) { + jqXHR.setRequestHeader( "If-Modified-Since", jQuery.lastModified[ cacheURL ] ); + } + if ( jQuery.etag[ cacheURL ] ) { + jqXHR.setRequestHeader( "If-None-Match", jQuery.etag[ cacheURL ] ); + } + } + + // Set the correct header, if data is being sent + if ( s.data && s.hasContent && s.contentType !== false || options.contentType ) { + jqXHR.setRequestHeader( "Content-Type", s.contentType ); + } + + // Set the Accepts header for the server, depending on the dataType + jqXHR.setRequestHeader( + "Accept", + s.dataTypes[ 0 ] && s.accepts[ s.dataTypes[ 0 ] ] ? + s.accepts[ s.dataTypes[ 0 ] ] + + ( s.dataTypes[ 0 ] !== "*" ? ", " + allTypes + "; q=0.01" : "" ) : + s.accepts[ "*" ] + ); + + // Check for headers option + for ( i in s.headers ) { + jqXHR.setRequestHeader( i, s.headers[ i ] ); + } + + // Allow custom headers/mimetypes and early abort + if ( s.beforeSend && + ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || completed ) ) { + + // Abort if not done already and return + return jqXHR.abort(); + } + + // Aborting is no longer a cancellation + strAbort = "abort"; + + // Install callbacks on deferreds + completeDeferred.add( s.complete ); + jqXHR.done( s.success ); + jqXHR.fail( s.error ); + + // Get transport + transport = inspectPrefiltersOrTransports( transports, s, options, jqXHR ); + + // If no transport, we auto-abort + if ( !transport ) { + done( -1, "No Transport" ); + } else { + jqXHR.readyState = 1; + + // Send global event + if ( fireGlobals ) { + globalEventContext.trigger( "ajaxSend", [ jqXHR, s ] ); + } + + // If request was aborted inside ajaxSend, stop there + if ( completed ) { + return jqXHR; + } + + // Timeout + if ( s.async && s.timeout > 0 ) { + timeoutTimer = window.setTimeout( function() { + jqXHR.abort( "timeout" ); + }, s.timeout ); + } + + try { + completed = false; + transport.send( requestHeaders, done ); + } catch ( e ) { + + // Rethrow post-completion exceptions + if ( completed ) { + throw e; + } + + // Propagate others as results + done( -1, e ); + } + } + + // Callback for when everything is done + function done( status, nativeStatusText, responses, headers ) { + var isSuccess, success, error, response, modified, + statusText = nativeStatusText; + + // Ignore repeat invocations + if ( completed ) { + return; + } + + completed = true; + + // Clear timeout if it exists + if ( timeoutTimer ) { + window.clearTimeout( timeoutTimer ); + } + + // Dereference transport for early garbage collection + // (no matter how long the jqXHR object will be used) + transport = undefined; + + // Cache response headers + responseHeadersString = headers || ""; + + // Set readyState + jqXHR.readyState = status > 0 ? 4 : 0; + + // Determine if successful + isSuccess = status >= 200 && status < 300 || status === 304; + + // Get response data + if ( responses ) { + response = ajaxHandleResponses( s, jqXHR, responses ); + } + + // Use a noop converter for missing script + if ( !isSuccess && jQuery.inArray( "script", s.dataTypes ) > -1 ) { + s.converters[ "text script" ] = function() {}; + } + + // Convert no matter what (that way responseXXX fields are always set) + response = ajaxConvert( s, response, jqXHR, isSuccess ); + + // If successful, handle type chaining + if ( isSuccess ) { + + // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode. + if ( s.ifModified ) { + modified = jqXHR.getResponseHeader( "Last-Modified" ); + if ( modified ) { + jQuery.lastModified[ cacheURL ] = modified; + } + modified = jqXHR.getResponseHeader( "etag" ); + if ( modified ) { + jQuery.etag[ cacheURL ] = modified; + } + } + + // if no content + if ( status === 204 || s.type === "HEAD" ) { + statusText = "nocontent"; + + // if not modified + } else if ( status === 304 ) { + statusText = "notmodified"; + + // If we have data, let's convert it + } else { + statusText = response.state; + success = response.data; + error = response.error; + isSuccess = !error; + } + } else { + + // Extract error from statusText and normalize for non-aborts + error = statusText; + if ( status || !statusText ) { + statusText = "error"; + if ( status < 0 ) { + status = 0; + } + } + } + + // Set data for the fake xhr object + jqXHR.status = status; + jqXHR.statusText = ( nativeStatusText || statusText ) + ""; + + // Success/Error + if ( isSuccess ) { + deferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] ); + } else { + deferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] ); + } + + // Status-dependent callbacks + jqXHR.statusCode( statusCode ); + statusCode = undefined; + + if ( fireGlobals ) { + globalEventContext.trigger( isSuccess ? "ajaxSuccess" : "ajaxError", + [ jqXHR, s, isSuccess ? success : error ] ); + } + + // Complete + completeDeferred.fireWith( callbackContext, [ jqXHR, statusText ] ); + + if ( fireGlobals ) { + globalEventContext.trigger( "ajaxComplete", [ jqXHR, s ] ); + + // Handle the global AJAX counter + if ( !( --jQuery.active ) ) { + jQuery.event.trigger( "ajaxStop" ); + } + } + } + + return jqXHR; + }, + + getJSON: function( url, data, callback ) { + return jQuery.get( url, data, callback, "json" ); + }, + + getScript: function( url, callback ) { + return jQuery.get( url, undefined, callback, "script" ); + } +} ); + +jQuery.each( [ "get", "post" ], function( _i, method ) { + jQuery[ method ] = function( url, data, callback, type ) { + + // Shift arguments if data argument was omitted + if ( isFunction( data ) ) { + type = type || callback; + callback = data; + data = undefined; + } + + // The url can be an options object (which then must have .url) + return jQuery.ajax( jQuery.extend( { + url: url, + type: method, + dataType: type, + data: data, + success: callback + }, jQuery.isPlainObject( url ) && url ) ); + }; +} ); + +jQuery.ajaxPrefilter( function( s ) { + var i; + for ( i in s.headers ) { + if ( i.toLowerCase() === "content-type" ) { + s.contentType = s.headers[ i ] || ""; + } + } +} ); + + +jQuery._evalUrl = function( url, options, doc ) { + return jQuery.ajax( { + url: url, + + // Make this explicit, since user can override this through ajaxSetup (#11264) + type: "GET", + dataType: "script", + cache: true, + async: false, + global: false, + + // Only evaluate the response if it is successful (gh-4126) + // dataFilter is not invoked for failure responses, so using it instead + // of the default converter is kludgy but it works. + converters: { + "text script": function() {} + }, + dataFilter: function( response ) { + jQuery.globalEval( response, options, doc ); + } + } ); +}; + + +jQuery.fn.extend( { + wrapAll: function( html ) { + var wrap; + + if ( this[ 0 ] ) { + if ( isFunction( html ) ) { + html = html.call( this[ 0 ] ); + } + + // The elements to wrap the target around + wrap = jQuery( html, this[ 0 ].ownerDocument ).eq( 0 ).clone( true ); + + if ( this[ 0 ].parentNode ) { + wrap.insertBefore( this[ 0 ] ); + } + + wrap.map( function() { + var elem = this; + + while ( elem.firstElementChild ) { + elem = elem.firstElementChild; + } + + return elem; + } ).append( this ); + } + + return this; + }, + + wrapInner: function( html ) { + if ( isFunction( html ) ) { + return this.each( function( i ) { + jQuery( this ).wrapInner( html.call( this, i ) ); + } ); + } + + return this.each( function() { + var self = jQuery( this ), + contents = self.contents(); + + if ( contents.length ) { + contents.wrapAll( html ); + + } else { + self.append( html ); + } + } ); + }, + + wrap: function( html ) { + var htmlIsFunction = isFunction( html ); + + return this.each( function( i ) { + jQuery( this ).wrapAll( htmlIsFunction ? html.call( this, i ) : html ); + } ); + }, + + unwrap: function( selector ) { + this.parent( selector ).not( "body" ).each( function() { + jQuery( this ).replaceWith( this.childNodes ); + } ); + return this; + } +} ); + + +jQuery.expr.pseudos.hidden = function( elem ) { + return !jQuery.expr.pseudos.visible( elem ); +}; +jQuery.expr.pseudos.visible = function( elem ) { + return !!( elem.offsetWidth || elem.offsetHeight || elem.getClientRects().length ); +}; + + + + +jQuery.ajaxSettings.xhr = function() { + try { + return new window.XMLHttpRequest(); + } catch ( e ) {} +}; + +var xhrSuccessStatus = { + + // File protocol always yields status code 0, assume 200 + 0: 200, + + // Support: IE <=9 only + // #1450: sometimes IE returns 1223 when it should be 204 + 1223: 204 + }, + xhrSupported = jQuery.ajaxSettings.xhr(); + +support.cors = !!xhrSupported && ( "withCredentials" in xhrSupported ); +support.ajax = xhrSupported = !!xhrSupported; + +jQuery.ajaxTransport( function( options ) { + var callback, errorCallback; + + // Cross domain only allowed if supported through XMLHttpRequest + if ( support.cors || xhrSupported && !options.crossDomain ) { + return { + send: function( headers, complete ) { + var i, + xhr = options.xhr(); + + xhr.open( + options.type, + options.url, + options.async, + options.username, + options.password + ); + + // Apply custom fields if provided + if ( options.xhrFields ) { + for ( i in options.xhrFields ) { + xhr[ i ] = options.xhrFields[ i ]; + } + } + + // Override mime type if needed + if ( options.mimeType && xhr.overrideMimeType ) { + xhr.overrideMimeType( options.mimeType ); + } + + // X-Requested-With header + // For cross-domain requests, seeing as conditions for a preflight are + // akin to a jigsaw puzzle, we simply never set it to be sure. + // (it can always be set on a per-request basis or even using ajaxSetup) + // For same-domain requests, won't change header if already provided. + if ( !options.crossDomain && !headers[ "X-Requested-With" ] ) { + headers[ "X-Requested-With" ] = "XMLHttpRequest"; + } + + // Set headers + for ( i in headers ) { + xhr.setRequestHeader( i, headers[ i ] ); + } + + // Callback + callback = function( type ) { + return function() { + if ( callback ) { + callback = errorCallback = xhr.onload = + xhr.onerror = xhr.onabort = xhr.ontimeout = + xhr.onreadystatechange = null; + + if ( type === "abort" ) { + xhr.abort(); + } else if ( type === "error" ) { + + // Support: IE <=9 only + // On a manual native abort, IE9 throws + // errors on any property access that is not readyState + if ( typeof xhr.status !== "number" ) { + complete( 0, "error" ); + } else { + complete( + + // File: protocol always yields status 0; see #8605, #14207 + xhr.status, + xhr.statusText + ); + } + } else { + complete( + xhrSuccessStatus[ xhr.status ] || xhr.status, + xhr.statusText, + + // Support: IE <=9 only + // IE9 has no XHR2 but throws on binary (trac-11426) + // For XHR2 non-text, let the caller handle it (gh-2498) + ( xhr.responseType || "text" ) !== "text" || + typeof xhr.responseText !== "string" ? + { binary: xhr.response } : + { text: xhr.responseText }, + xhr.getAllResponseHeaders() + ); + } + } + }; + }; + + // Listen to events + xhr.onload = callback(); + errorCallback = xhr.onerror = xhr.ontimeout = callback( "error" ); + + // Support: IE 9 only + // Use onreadystatechange to replace onabort + // to handle uncaught aborts + if ( xhr.onabort !== undefined ) { + xhr.onabort = errorCallback; + } else { + xhr.onreadystatechange = function() { + + // Check readyState before timeout as it changes + if ( xhr.readyState === 4 ) { + + // Allow onerror to be called first, + // but that will not handle a native abort + // Also, save errorCallback to a variable + // as xhr.onerror cannot be accessed + window.setTimeout( function() { + if ( callback ) { + errorCallback(); + } + } ); + } + }; + } + + // Create the abort callback + callback = callback( "abort" ); + + try { + + // Do send the request (this may raise an exception) + xhr.send( options.hasContent && options.data || null ); + } catch ( e ) { + + // #14683: Only rethrow if this hasn't been notified as an error yet + if ( callback ) { + throw e; + } + } + }, + + abort: function() { + if ( callback ) { + callback(); + } + } + }; + } +} ); + + + + +// Prevent auto-execution of scripts when no explicit dataType was provided (See gh-2432) +jQuery.ajaxPrefilter( function( s ) { + if ( s.crossDomain ) { + s.contents.script = false; + } +} ); + +// Install script dataType +jQuery.ajaxSetup( { + accepts: { + script: "text/javascript, application/javascript, " + + "application/ecmascript, application/x-ecmascript" + }, + contents: { + script: /\b(?:java|ecma)script\b/ + }, + converters: { + "text script": function( text ) { + jQuery.globalEval( text ); + return text; + } + } +} ); + +// Handle cache's special case and crossDomain +jQuery.ajaxPrefilter( "script", function( s ) { + if ( s.cache === undefined ) { + s.cache = false; + } + if ( s.crossDomain ) { + s.type = "GET"; + } +} ); + +// Bind script tag hack transport +jQuery.ajaxTransport( "script", function( s ) { + + // This transport only deals with cross domain or forced-by-attrs requests + if ( s.crossDomain || s.scriptAttrs ) { + var script, callback; + return { + send: function( _, complete ) { + script = jQuery( " + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + + + +
+ +
+ +
+

cassandra - Exceptions and Enums

+
+
+cassandra.__version_info__
+

The version of the driver in a tuple format

+
+ +
+
+cassandra.__version__
+

The version of the driver in a string format

+
+ +
+
+class cassandra.ConsistencyLevel
+

Spcifies how many replicas must respond for an operation to be considered +a success. By default, ONE is used for all operations.

+
+
+ANY = 0
+

Only requires that one replica receives the write or the coordinator +stores a hint to replay later. Valid only for writes.

+
+ +
+
+ONE = 1
+

Only one replica needs to respond to consider the operation a success

+
+ +
+
+TWO = 2
+

Two replicas must respond to consider the operation a success

+
+ +
+
+THREE = 3
+

Three replicas must respond to consider the operation a success

+
+ +
+
+QUORUM = 4
+

ceil(RF/2) + 1 replicas must respond to consider the operation a success

+
+ +
+
+ALL = 5
+

All replicas must respond to consider the operation a success

+
+ +
+
+LOCAL_QUORUM = 6
+

Requires a quorum of replicas in the local datacenter

+
+ +
+
+EACH_QUORUM = 7
+

Requires a quorum of replicas in each datacenter

+
+ +
+
+SERIAL = 8
+

For conditional inserts/updates that utilize Cassandra’s lightweight +transactions, this requires consensus among all replicas for the +modified data.

+
+ +
+
+LOCAL_SERIAL = 9
+

Like SERIAL, but only requires consensus +among replicas in the local datacenter.

+
+ +
+
+LOCAL_ONE = 10
+

Sends a request only to replicas in the local datacenter and waits for +one response.

+
+ +
+ +
+
+class cassandra.ProtocolVersion
+

Defines native protocol versions supported by this driver.

+
+
+V1 = 1
+

v1, supported in Cassandra 1.2–>2.2

+
+ +
+
+V2 = 2
+

v2, supported in Cassandra 2.0–>2.2; +added support for lightweight transactions, batch operations, and automatic query paging.

+
+ +
+
+V3 = 3
+

v3, supported in Cassandra 2.1–>3.x+; +added support for protocol-level client-side timestamps (see Session.use_client_timestamp), +serial consistency levels for BatchStatement, and an improved connection pool.

+
+ +
+
+V4 = 4
+

v4, supported in Cassandra 2.2–>3.x+; +added a number of new types, server warnings, new failure messages, and custom payloads. Details in the +project docs

+
+ +
+
+V5 = 5
+

v5, in beta from 3.x+. Finalised in 4.0-beta5

+
+ +
+
+V6 = 6
+

v6, in beta from 4.0-beta5

+
+ +
+
+DSE_V1 = 65
+

DSE private protocol v1, supported in DSE 5.1+

+
+ +
+
+DSE_V2 = 66
+

DSE private protocol v2, supported in DSE 6.0+

+
+ +
+
+SUPPORTED_VERSIONS = (66, 65, 6, 5, 4, 3, 2, 1)
+

A tuple of all supported protocol versions

+
+ +
+
+BETA_VERSIONS = (6,)
+

A tuple of all beta protocol versions

+
+ +
+
+MIN_SUPPORTED = 1
+

Minimum protocol version supported by this driver.

+
+ +
+
+MAX_SUPPORTED = 66
+

Maximum protocol version supported by this driver.

+
+ +
+
+classmethod get_lower_supported(previous_version)
+

Return the lower supported protocol version. Beta versions are omitted.

+
+ +
+ +
+
+class cassandra.UserFunctionDescriptor(name, argument_types)
+

Describes a User function by name and argument signature

+
+
+name = None
+

name of the function

+
+ +
+
+argument_types = None
+

Ordered list of CQL argument type names comprising the type signature

+
+ +
+
+property signature
+

function signature string in the form ‘name([type0[,type1[…]]])’

+

can be used to uniquely identify overloaded function names within a keyspace

+
+ +
+ +
+
+class cassandra.UserAggregateDescriptor(name, argument_types)
+

Describes a User aggregate function by name and argument signature

+
+
+name = None
+

name of the aggregate

+
+ +
+
+argument_types = None
+

Ordered list of CQL argument type names comprising the type signature

+
+ +
+
+property signature
+

function signature string in the form ‘name([type0[,type1[…]]])’

+

can be used to uniquely identify overloaded function names within a keyspace

+
+ +
+ +
+
+exception cassandra.DriverException
+

Base for all exceptions explicitly raised by the driver.

+
+ +
+
+exception cassandra.RequestExecutionException
+

Base for request execution exceptions returned from the server.

+
+ +
+
+exception cassandra.Unavailable
+

There were not enough live replicas to satisfy the requested consistency +level, so the coordinator node immediately failed the request without +forwarding it to any replicas.

+
+
+consistency = None
+

The requested ConsistencyLevel

+
+ +
+
+required_replicas = None
+

The number of replicas that needed to be live to complete the operation

+
+ +
+
+alive_replicas = None
+

The number of replicas that were actually alive

+
+ +
+ +
+
+exception cassandra.Timeout
+

Replicas failed to respond to the coordinator node before timing out.

+
+
+consistency = None
+

The requested ConsistencyLevel

+
+ +
+
+required_responses = None
+

The number of required replica responses

+
+ +
+
+received_responses = None
+

The number of replicas that responded before the coordinator timed out +the operation

+
+ +
+ +
+
+exception cassandra.ReadTimeout
+

A subclass of Timeout for read operations.

+

This indicates that the replicas failed to respond to the coordinator +node before the configured timeout. This timeout is configured in +cassandra.yaml with the read_request_timeout_in_ms +and range_request_timeout_in_ms options.

+
+
+data_retrieved = None
+

A boolean indicating whether the requested data was retrieved +by the coordinator from any replicas before it timed out the +operation

+
+ +
+ +
+
+exception cassandra.WriteTimeout
+

A subclass of Timeout for write operations.

+

This indicates that the replicas failed to respond to the coordinator +node before the configured timeout. This timeout is configured in +cassandra.yaml with the write_request_timeout_in_ms +option.

+
+
+write_type = None
+

The type of write operation, enum on WriteType

+
+ +
+ +
+
+exception cassandra.CoordinationFailure
+

Replicas sent a failure to the coordinator.

+
+
+consistency = None
+

The requested ConsistencyLevel

+
+ +
+
+required_responses = None
+

The number of required replica responses

+
+ +
+
+received_responses = None
+

The number of replicas that responded before the coordinator timed out +the operation

+
+ +
+
+failures = None
+

The number of replicas that sent a failure message

+
+ +
+
+error_code_map = None
+

A map of inet addresses to error codes representing replicas that sent +a failure message. Only set when protocol_version is 5 or higher.

+
+ +
+ +
+
+exception cassandra.ReadFailure
+

A subclass of CoordinationFailure for read operations.

+

This indicates that the replicas sent a failure message to the coordinator.

+
+
+data_retrieved = None
+

A boolean indicating whether the requested data was retrieved +by the coordinator from any replicas before it timed out the +operation

+
+ +
+ +
+
+exception cassandra.WriteFailure
+

A subclass of CoordinationFailure for write operations.

+

This indicates that the replicas sent a failure message to the coordinator.

+
+
+write_type = None
+

The type of write operation, enum on WriteType

+
+ +
+ +
+
+exception cassandra.FunctionFailure
+

User Defined Function failed during execution

+
+
+keyspace = None
+

Keyspace of the function

+
+ +
+
+function = None
+

Name of the function

+
+ +
+
+arg_types = None
+

List of argument type names of the function

+
+ +
+ +
+
+exception cassandra.RequestValidationException
+

Server request validation failed

+
+ +
+
+exception cassandra.ConfigurationException
+

Server indicated request errro due to current configuration

+
+ +
+
+exception cassandra.AlreadyExists
+

An attempt was made to create a keyspace or table that already exists.

+
+
+keyspace = None
+

The name of the keyspace that already exists, or, if an attempt was +made to create a new table, the keyspace that the table is in.

+
+ +
+
+table = None
+

The name of the table that already exists, or, if an attempt was +make to create a keyspace, None.

+
+ +
+ +
+
+exception cassandra.InvalidRequest
+

A query was made that was invalid for some reason, such as trying to set +the keyspace for a connection to a nonexistent keyspace.

+
+ +
+
+exception cassandra.Unauthorized
+

The current user is not authorized to perform the requested operation.

+
+ +
+
+exception cassandra.AuthenticationFailed
+

Failed to authenticate.

+
+ +
+
+exception cassandra.OperationTimedOut
+

The operation took longer than the specified (client-side) timeout +to complete. This is not an error generated by Cassandra, only +the driver.

+
+
+errors = None
+

A dict of errors keyed by the Host against which they occurred.

+
+ +
+
+last_host = None
+

The last Host this operation was attempted against.

+
+ +
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.26.2-scylla/api/cassandra/auth.html b/3.26.2-scylla/api/cassandra/auth.html new file mode 100644 index 0000000000..e39e858ff0 --- /dev/null +++ b/3.26.2-scylla/api/cassandra/auth.html @@ -0,0 +1,797 @@ + + + + + + + + + + + + + cassandra.auth - Authentication | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + + + +
+ +
+ +
+

cassandra.auth - Authentication

+
+
+class cassandra.auth.AuthProvider
+

An abstract class that defines the interface that will be used for +creating Authenticator instances when opening new +connections to Cassandra.

+
+

New in version 2.0.0.

+
+
+
+new_authenticator(host)
+

Implementations of this class should return a new instance +of Authenticator or one of its subclasses.

+
+ +
+ +
+
+class cassandra.auth.Authenticator
+

An abstract class that handles SASL authentication with Cassandra servers.

+

Each time a new connection is created and the server requires authentication, +a new instance of this class will be created by the corresponding +AuthProvider to handler that authentication. The lifecycle of the +new Authenticator will the be:

+

1) The initial_response() method will be called. The return +value will be sent to the server to initiate the handshake.

+

2) The server will respond to each client response by either issuing a +challenge or indicating that the authentication is complete (successful or not). +If a new challenge is issued, evaluate_challenge() +will be called to produce a response that will be sent to the +server. This challenge/response negotiation will continue until the server +responds that authentication is successful (or an AuthenticationFailed +is raised).

+

3) When the server indicates that authentication is successful, +on_authentication_success() will be called a token string that +that the server may optionally have sent.

+

The exact nature of the negotiation between the client and server is specific +to the authentication mechanism configured server-side.

+
+

New in version 2.0.0.

+
+
+
+server_authenticator_class = None
+

Set during the connection AUTHENTICATE phase

+
+ +
+
+initial_response()
+

Returns an message to send to the server to initiate the SASL handshake. +None may be returned to send an empty message.

+
+ +
+
+evaluate_challenge(challenge)
+

Called when the server sends a challenge message. Generally, this method +should return None when authentication is complete from a +client perspective. Otherwise, a string should be returned.

+
+ +
+
+on_authentication_success(token)
+

Called when the server indicates that authentication was successful. +Depending on the authentication mechanism, token may be None +or a string.

+
+ +
+ +
+
+class cassandra.auth.PlainTextAuthProvider(username, password)
+

An AuthProvider that works with Cassandra’s PasswordAuthenticator.

+

Example usage:

+
from cassandra.cluster import Cluster
+from cassandra.auth import PlainTextAuthProvider
+
+auth_provider = PlainTextAuthProvider(
+        username='cassandra', password='cassandra')
+cluster = Cluster(auth_provider=auth_provider)
+
+
+
+

New in version 2.0.0.

+
+
+
+new_authenticator(host)
+

Implementations of this class should return a new instance +of Authenticator or one of its subclasses.

+
+ +
+ +
+
+class cassandra.auth.PlainTextAuthenticator(username, password)
+
+
+evaluate_challenge(challenge)
+

Called when the server sends a challenge message. Generally, this method +should return None when authentication is complete from a +client perspective. Otherwise, a string should be returned.

+
+ +
+ +
+
+class cassandra.auth.SaslAuthProvider(**sasl_kwargs)
+

An AuthProvider supporting general SASL auth mechanisms

+

Suitable for GSSAPI or other SASL mechanisms

+

Example usage:

+
from cassandra.cluster import Cluster
+from cassandra.auth import SaslAuthProvider
+
+sasl_kwargs = {'service': 'something',
+               'mechanism': 'GSSAPI',
+               'qops': 'auth'.split(',')}
+auth_provider = SaslAuthProvider(**sasl_kwargs)
+cluster = Cluster(auth_provider=auth_provider)
+
+
+
+

New in version 2.1.4.

+
+
+
+new_authenticator(host)
+

Implementations of this class should return a new instance +of Authenticator or one of its subclasses.

+
+ +
+ +
+
+class cassandra.auth.SaslAuthenticator(host, service, mechanism='GSSAPI', **sasl_kwargs)
+

A pass-through Authenticator using the third party package +‘pure-sasl’ for authentication

+
+

New in version 2.1.4.

+
+
+
+initial_response()
+

Returns an message to send to the server to initiate the SASL handshake. +None may be returned to send an empty message.

+
+ +
+
+evaluate_challenge(challenge)
+

Called when the server sends a challenge message. Generally, this method +should return None when authentication is complete from a +client perspective. Otherwise, a string should be returned.

+
+ +
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.26.2-scylla/api/cassandra/cluster.html b/3.26.2-scylla/api/cassandra/cluster.html new file mode 100644 index 0000000000..143bdd4cbd --- /dev/null +++ b/3.26.2-scylla/api/cassandra/cluster.html @@ -0,0 +1,1769 @@ + + + + + + + + + + + + + cassandra.cluster - Clusters and Sessions | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + + + +
+ +
+ +
+

cassandra.cluster - Clusters and Sessions

+
+
+class cassandra.cluster.Cluster([contact_points=('127.0.0.1',)][, port=9042][, executor_threads=2], **attr_kwargs)
+

The main class to use when interacting with a Cassandra cluster. +Typically, one instance of this class will be created for each +separate Cassandra cluster that your application interacts with.

+

Example usage:

+
>>> from cassandra.cluster import Cluster
+>>> cluster = Cluster(['192.168.1.1', '192.168.1.2'])
+>>> session = cluster.connect()
+>>> session.execute("CREATE KEYSPACE ...")
+>>> ...
+>>> cluster.shutdown()
+
+
+

Cluster and Session also provide context management functions +which implicitly handle shutdown when leaving scope.

+

executor_threads defines the number of threads in a pool for handling asynchronous tasks such as +extablishing connection pools or refreshing metadata.

+

Any of the mutable Cluster attributes may be set as keyword arguments to the constructor.

+
+
+contact_points = ['127.0.0.1']
+
+ +
+
+port = 9042
+
+ +
+
+cql_version = None
+
+ +
+
+protocol_version = 66
+
+ +
+
+compression = True
+
+ +
+
+auth_provider
+

When protocol_version is 2 or higher, this should +be an instance of a subclass of AuthProvider, +such as PlainTextAuthProvider.

+

When protocol_version is 1, this should be +a function that accepts one argument, the IP address of a node, +and returns a dict of credentials for that node.

+

When not using authentication, this should be left as None.

+
+ +
+
+load_balancing_policy
+

An instance of policies.LoadBalancingPolicy or +one of its subclasses.

+
+

Changed in version 2.6.0.

+
+

Defaults to TokenAwarePolicy (DCAwareRoundRobinPolicy). +when using CPython (where the murmur3 extension is available). DCAwareRoundRobinPolicy +otherwise. Default local DC will be chosen from contact points.

+

Please see DCAwareRoundRobinPolicy for a discussion on default behavior with respect to +DC locality and remote nodes.

+
+ +
+
+reconnection_policy = <cassandra.policies.ExponentialReconnectionPolicy object>
+
+ +
+
+default_retry_policy = <cassandra.policies.RetryPolicy object>
+

A default policies.RetryPolicy instance to use for all +Statement objects which do not have a retry_policy +explicitly set.

+
+ +
+
+conviction_policy_factory = <class 'cassandra.policies.SimpleConvictionPolicy'>
+
+ +
+
+address_translator = <cassandra.policies.IdentityTranslator object>
+
+ +
+
+metrics_enabled = False
+
+ +
+
+metrics = None
+
+ +
+
+ssl_context = None
+
+ +
+
+ssl_options = None
+
+ +
+
+sockopts = None
+
+ +
+
+max_schema_agreement_wait = 10
+
+ +
+
+metadata = None
+
+ +
+
+connection_class = <class 'cassandra.io.libevreactor.LibevConnection'>
+
+ +
+
+control_connection_timeout = 2.0
+
+ +
+
+idle_heartbeat_interval = 30
+
+ +
+
+idle_heartbeat_timeout = 30
+
+ +
+
+schema_event_refresh_window = 2
+
+ +
+
+topology_event_refresh_window = 10
+
+ +
+
+status_event_refresh_window = 2
+
+ +
+
+prepare_on_all_hosts = True
+
+ +
+
+reprepare_on_up = True
+
+ +
+
+connect_timeout = 5
+
+ +
+
+schema_metadata_enabled = True
+

Flag indicating whether internal schema metadata is updated.

+

When disabled, the driver does not populate Cluster.metadata.keyspaces on connect, or on schema change events. This +can be used to speed initial connection, and reduce load on client and server during operation. Turning this off +gives away token aware request routing, and programmatic inspection of the metadata model.

+
+ +
+
+token_metadata_enabled = True
+

Flag indicating whether internal token metadata is updated.

+

When disabled, the driver does not query node token information on connect, or on topology change events. This +can be used to speed initial connection, and reduce load on client and server during operation. It is most useful +in large clusters using vnodes, where the token map can be expensive to compute. Turning this off +gives away token aware request routing, and programmatic inspection of the token ring.

+
+ +
+
+timestamp_generator = None
+
+ +
+
+endpoint_factory = None
+
+ +
+
+cloud = None
+
+ +
+
+connect(keyspace=None, wait_for_all_pools=False)
+

Creates and returns a new Session object.

+

If keyspace is specified, that keyspace will be the default keyspace for +operations on the Session.

+

wait_for_all_pools specifies whether this call should wait for all connection pools to be +established or attempted. Default is False, which means it will return when the first +successful connection is established. Remaining pools are added asynchronously.

+
+ +
+
+shutdown()
+

Closes all sessions and connection associated with this Cluster. +To ensure all connections are properly closed, you should always +call shutdown() on a Cluster instance when you are done with it.

+

Once shutdown, a Cluster should not be used for any purpose.

+
+ +
+
+register_user_type(keyspace, user_type, klass)
+

Registers a class to use to represent a particular user-defined type. +Query parameters for this user-defined type will be assumed to be +instances of klass. Result sets for this user-defined type will +be instances of klass. If no class is registered for a user-defined +type, a namedtuple will be used for result sets, and non-prepared +statements may not encode parameters for this type correctly.

+

keyspace is the name of the keyspace that the UDT is defined in.

+

user_type is the string name of the UDT to register the mapping +for.

+

klass should be a class with attributes whose names match the +fields of the user-defined type. The constructor must accepts kwargs +for each of the fields in the UDT.

+

This method should only be called after the type has been created +within Cassandra.

+

Example:

+
cluster = Cluster(protocol_version=3)
+session = cluster.connect()
+session.set_keyspace('mykeyspace')
+session.execute("CREATE TYPE address (street text, zipcode int)")
+session.execute("CREATE TABLE users (id int PRIMARY KEY, location address)")
+
+# create a class to map to the "address" UDT
+class Address(object):
+
+    def __init__(self, street, zipcode):
+        self.street = street
+        self.zipcode = zipcode
+
+cluster.register_user_type('mykeyspace', 'address', Address)
+
+# insert a row using an instance of Address
+session.execute("INSERT INTO users (id, location) VALUES (%s, %s)",
+                (0, Address("123 Main St.", 78723)))
+
+# results will include Address instances
+results = session.execute("SELECT * FROM users")
+row = results[0]
+print row.id, row.location.street, row.location.zipcode
+
+
+
+ +
+
+register_listener(listener)
+

Adds a cassandra.policies.HostStateListener subclass instance to +the list of listeners to be notified when a host is added, removed, +marked up, or marked down.

+
+ +
+
+unregister_listener(listener)
+

Removes a registered listener.

+
+ +
+
+add_execution_profile(name, profile, pool_wait_timeout=5)
+

Adds an ExecutionProfile to the cluster. This makes it available for use by name in Session.execute() +and Session.execute_async(). This method will raise if the profile already exists.

+

Normally profiles will be injected at cluster initialization via Cluster(execution_profiles). This method +provides a way of adding them dynamically.

+

Adding a new profile updates the connection pools according to the specified load_balancing_policy. By default, +this method will wait up to five seconds for the pool creation to complete, so the profile can be used immediately +upon return. This behavior can be controlled using pool_wait_timeout (see +concurrent.futures.wait +for timeout semantics).

+
+ +
+
+set_max_requests_per_connection(host_distance, max_requests)
+

Sets a threshold for concurrent requests per connection, above which new +connections will be created to a host (up to max connections; +see set_max_connections_per_host()).

+

Pertains to connection pool management in protocol versions {1,2}.

+
+ +
+
+get_max_requests_per_connection(host_distance)
+
+ +
+
+set_min_requests_per_connection(host_distance, min_requests)
+

Sets a threshold for concurrent requests per connection, below which +connections will be considered for disposal (down to core connections; +see set_core_connections_per_host()).

+

Pertains to connection pool management in protocol versions {1,2}.

+
+ +
+
+get_min_requests_per_connection(host_distance)
+
+ +
+
+get_core_connections_per_host(host_distance)
+

Gets the minimum number of connections per Session that will be opened +for each host with HostDistance equal to host_distance. +The default is 2 for LOCAL and 1 for +REMOTE.

+

This property is ignored if protocol_version is +3 or higher.

+
+ +
+
+set_core_connections_per_host(host_distance, core_connections)
+

Sets the minimum number of connections per Session that will be opened +for each host with HostDistance equal to host_distance. +The default is 2 for LOCAL and 1 for +REMOTE.

+

Protocol version 1 and 2 are limited in the number of concurrent +requests they can send per connection. The driver implements connection +pooling to support higher levels of concurrency.

+

If protocol_version is set to 3 or higher, this +is not supported (there is always one connection per host, unless +the host is remote and connect_to_remote_hosts is False) +and using this will result in an UnsupportedOperation.

+
+ +
+
+get_max_connections_per_host(host_distance)
+

Gets the maximum number of connections per Session that will be opened +for each host with HostDistance equal to host_distance. +The default is 8 for LOCAL and 2 for +REMOTE.

+

This property is ignored if protocol_version is +3 or higher.

+
+ +
+
+set_max_connections_per_host(host_distance, max_connections)
+

Sets the maximum number of connections per Session that will be opened +for each host with HostDistance equal to host_distance. +The default is 2 for LOCAL and 1 for +REMOTE.

+

If protocol_version is set to 3 or higher, this +is not supported (there is always one connection per host, unless +the host is remote and connect_to_remote_hosts is False) +and using this will result in an UnsupportedOperation.

+
+ +
+
+get_control_connection_host()
+

Returns the control connection host metadata.

+
+ +
+
+refresh_schema_metadata(max_schema_agreement_wait=None)
+

Synchronously refresh all schema metadata.

+

By default, the timeout for this operation is governed by max_schema_agreement_wait +and control_connection_timeout.

+

Passing max_schema_agreement_wait here overrides max_schema_agreement_wait.

+

Setting max_schema_agreement_wait <= 0 will bypass schema agreement and refresh schema immediately.

+

An Exception is raised if schema refresh fails for any reason.

+
+ +
+
+refresh_keyspace_metadata(keyspace, max_schema_agreement_wait=None)
+

Synchronously refresh keyspace metadata. This applies to keyspace-level information such as replication +and durability settings. It does not refresh tables, types, etc. contained in the keyspace.

+

See refresh_schema_metadata() for description of max_schema_agreement_wait behavior

+
+ +
+
+refresh_table_metadata(keyspace, table, max_schema_agreement_wait=None)
+

Synchronously refresh table metadata. This applies to a table, and any triggers or indexes attached +to the table.

+

See refresh_schema_metadata() for description of max_schema_agreement_wait behavior

+
+ +
+
+refresh_user_type_metadata(keyspace, user_type, max_schema_agreement_wait=None)
+

Synchronously refresh user defined type metadata.

+

See refresh_schema_metadata() for description of max_schema_agreement_wait behavior

+
+ +
+
+refresh_user_function_metadata(keyspace, function, max_schema_agreement_wait=None)
+

Synchronously refresh user defined function metadata.

+

function is a cassandra.UserFunctionDescriptor.

+

See refresh_schema_metadata() for description of max_schema_agreement_wait behavior

+
+ +
+
+refresh_user_aggregate_metadata(keyspace, aggregate, max_schema_agreement_wait=None)
+

Synchronously refresh user defined aggregate metadata.

+

aggregate is a cassandra.UserAggregateDescriptor.

+

See refresh_schema_metadata() for description of max_schema_agreement_wait behavior

+
+ +
+
+refresh_nodes(force_token_rebuild=False)
+

Synchronously refresh the node list and token metadata

+

force_token_rebuild can be used to rebuild the token map metadata, even if no new nodes are discovered.

+

An Exception is raised if node refresh fails for any reason.

+
+ +
+
+set_meta_refresh_enabled(enabled)
+

Deprecated: set schema_metadata_enabled token_metadata_enabled instead

+

Sets a flag to enable (True) or disable (False) all metadata refresh queries. +This applies to both schema and node topology.

+

Disabling this is useful to minimize refreshes during multiple changes.

+

Meta refresh must be enabled for the driver to become aware of any cluster +topology changes or schema updates.

+
+ +
+ +
+
+class cassandra.cluster.ExecutionProfile(load_balancing_policy=<object object>, retry_policy=None, consistency_level=ConsistencyLevel.LOCAL_ONE, serial_consistency_level=None, request_timeout=10.0, row_factory=<function named_tuple_factory>, speculative_execution_policy=None)
+
+
+consistency_level = LOCAL_ONE
+
+ +
+
+static row_factory(colnames, rows)
+

Returns each row as a namedtuple. +This is the default row factory.

+

Example:

+
>>> from cassandra.query import named_tuple_factory
+>>> session = cluster.connect('mykeyspace')
+>>> session.row_factory = named_tuple_factory
+>>> rows = session.execute("SELECT name, age FROM users LIMIT 1")
+>>> user = rows[0]
+
+>>> # you can access field by their name:
+>>> print "name: %s, age: %d" % (user.name, user.age)
+name: Bob, age: 42
+
+>>> # or you can access fields by their position (like a tuple)
+>>> name, age = user
+>>> print "name: %s, age: %d" % (name, age)
+name: Bob, age: 42
+>>> name = user[0]
+>>> age = user[1]
+>>> print "name: %s, age: %d" % (name, age)
+name: Bob, age: 42
+
+
+
+

Changed in version 2.0.0: moved from cassandra.decoder to cassandra.query

+
+
+ +
+ +
+
+class cassandra.cluster.GraphExecutionProfile(load_balancing_policy=_NOT_SET, retry_policy=None, consistency_level=ConsistencyLevel.LOCAL_ONE, serial_consistency_level=None, request_timeout=30.0, row_factory=None, graph_options=None, continuous_paging_options=_NOT_SET)
+

Default execution profile for graph execution.

+

See ExecutionProfile for base attributes. Note that if not explicitly set, +the row_factory and graph_options.graph_protocol are resolved during the query execution. +These options will resolve to graph_graphson3_row_factory and GraphProtocol.GRAPHSON_3_0 +for the core graph engine (DSE 6.8+), otherwise graph_object_row_factory and GraphProtocol.GRAPHSON_1_0

+

In addition to default parameters shown in the signature, this profile also defaults retry_policy to +cassandra.policies.NeverRetryPolicy.

+
+ +
+
+class cassandra.cluster.GraphAnalyticsExecutionProfile(load_balancing_policy=None, retry_policy=None, consistency_level=ConsistencyLevel.LOCAL_ONE, serial_consistency_level=None, request_timeout=3600.0 * 24.0 * 7.0, row_factory=None, graph_options=None)
+

Execution profile with timeout and load balancing appropriate for graph analytics queries.

+

See also GraphExecutionPolicy.

+

In addition to default parameters shown in the signature, this profile also defaults retry_policy to +cassandra.policies.NeverRetryPolicy, and load_balancing_policy to one that targets the current Spark +master.

+

Note: The graph_options.graph_source is set automatically to b’a’ (analytics) +when using GraphAnalyticsExecutionProfile. This is mandatory to target analytics nodes.

+
+ +
+
+cassandra.cluster.EXEC_PROFILE_DEFAULT
+

The most base type

+
+ +
+
+cassandra.cluster.EXEC_PROFILE_GRAPH_DEFAULT
+

The most base type

+
+ +
+
+cassandra.cluster.EXEC_PROFILE_GRAPH_SYSTEM_DEFAULT
+

The most base type

+
+ +
+
+cassandra.cluster.EXEC_PROFILE_GRAPH_ANALYTICS_DEFAULT
+

The most base type

+
+ +
+
+class cassandra.cluster.Session
+

A collection of connection pools for each host in the cluster. +Instances of this class should not be created directly, only +using Cluster.connect().

+

Queries and statements can be executed through Session instances +using the execute() and execute_async() +methods.

+

Example usage:

+
>>> session = cluster.connect()
+>>> session.set_keyspace("mykeyspace")
+>>> session.execute("SELECT * FROM mycf")
+
+
+
+
+default_timeout = 10.0
+

A default timeout, measured in seconds, for queries executed through +execute() or execute_async(). This default may be +overridden with the timeout parameter for either of those methods.

+

Setting this to None will cause no timeouts to be set by default.

+

Please see ResponseFuture.result() for details on the scope and +effect of this timeout.

+
+

New in version 2.0.0.

+
+
+ +
+
+default_consistency_level = LOCAL_ONE
+

Deprecated: use execution profiles instead +The default ConsistencyLevel for operations executed through +this session. This default may be overridden by setting the +consistency_level on individual statements.

+
+

New in version 1.2.0.

+
+
+

Changed in version 3.0.0: default changed from ONE to LOCAL_ONE

+
+
+ +
+
+default_serial_consistency_level = None
+

The default ConsistencyLevel for serial phase of conditional updates executed through +this session. This default may be overridden by setting the +serial_consistency_level on individual statements.

+

Only valid for protocol_version >= 2.

+
+ +
+
+row_factory = <function named_tuple_factory>
+

The format to return row results in. By default, each +returned row will be a named tuple. You can alternatively +use any of the following:

+ +
+ +
+
+default_fetch_size = 5000
+
+ +
+
+use_client_timestamp = True
+
+ +
+
+timestamp_generator = None
+
+ +
+
+encoder = None
+
+ +
+
+client_protocol_handler = <class 'cassandra.protocol.cython_protocol_handler.<locals>.CythonProtocolHandler'>
+
+ +
+
+execute(statement[, parameters][, timeout][, trace][, custom_payload][, paging_state][, host][, execute_as])
+

Execute the given query and synchronously wait for the response.

+

If an error is encountered while executing the query, an Exception +will be raised.

+

query may be a query string or an instance of cassandra.query.Statement.

+

parameters may be a sequence or dict of parameters to bind. If a +sequence is used, %s should be used the placeholder for each +argument. If a dict is used, %(name)s style placeholders must +be used.

+

timeout should specify a floating-point timeout (in seconds) after +which an OperationTimedOut exception will be raised if the query +has not completed. If not set, the timeout defaults to the request_timeout of the selected execution_profile. +If set to None, there is no timeout. Please see ResponseFuture.result() for details on +the scope and effect of this timeout.

+

If trace is set to True, the query will be sent with tracing enabled. +The trace details can be obtained using the returned ResultSet object.

+

custom_payload is a Custom Payloads dict to be passed to the server. +If query is a Statement with its own custom_payload. The message payload +will be a union of the two, with the values specified here taking precedence.

+

execution_profile is the execution profile to use for this request. It can be a key to a profile configured +via Cluster.add_execution_profile() or an instance (from Session.execution_profile_clone_update(), +for example

+

paging_state is an optional paging state, reused from a previous ResultSet.

+

host is the cassandra.pool.Host that should handle the query. If the host specified is down or +not yet connected, the query will fail with NoHostAvailable. Using this is +discouraged except in a few cases, e.g., querying node-local tables and applying schema changes.

+

execute_as the user that will be used on the server to execute the request. This is only available +on a DSE cluster.

+
+ +
+
+execute_async(statement[, parameters][, trace][, custom_payload][, paging_state][, host][, execute_as])
+

Execute the given query and return a ResponseFuture object +which callbacks may be attached to for asynchronous response +delivery. You may also call result() +on the ResponseFuture to synchronously block for results at +any time.

+

See Session.execute() for parameter definitions.

+

Example usage:

+
>>> session = cluster.connect()
+>>> future = session.execute_async("SELECT * FROM mycf")
+
+>>> def log_results(results):
+...     for row in results:
+...         log.info("Results: %s", row)
+
+>>> def log_error(exc):
+>>>     log.error("Operation failed: %s", exc)
+
+>>> future.add_callbacks(log_results, log_error)
+
+
+

Async execution with blocking wait for results:

+
>>> future = session.execute_async("SELECT * FROM mycf")
+>>> # do other stuff...
+
+>>> try:
+...     results = future.result()
+... except Exception:
+...     log.exception("Operation failed:")
+
+
+
+ +
+
+execute_graph(statement[, parameters][, trace][, execution_profile=EXEC_PROFILE_GRAPH_DEFAULT][, execute_as])
+

Executes a Gremlin query string or GraphStatement synchronously, +and returns a ResultSet from this execution.

+

parameters is dict of named parameters to bind. The values must be +JSON-serializable.

+

execution_profile: Selects an execution profile for the request.

+

execute_as the user that will be used on the server to execute the request.

+
+ +
+
+execute_graph_async(statement[, parameters][, trace][, execution_profile=EXEC_PROFILE_GRAPH_DEFAULT][, execute_as])
+

Execute the graph query and return a ResponseFuture +object which callbacks may be attached to for asynchronous response delivery. You may also call ResponseFuture.result() to synchronously block for +results at any time.

+
+ +
+
+prepare(statement)
+

Prepares a query string, returning a PreparedStatement +instance which can be used as follows:

+
>>> session = cluster.connect("mykeyspace")
+>>> query = "INSERT INTO users (id, name, age) VALUES (?, ?, ?)"
+>>> prepared = session.prepare(query)
+>>> session.execute(prepared, (user.id, user.name, user.age))
+
+
+

Or you may bind values to the prepared statement ahead of time:

+
>>> prepared = session.prepare(query)
+>>> bound_stmt = prepared.bind((user.id, user.name, user.age))
+>>> session.execute(bound_stmt)
+
+
+

Of course, prepared statements may (and should) be reused:

+
>>> prepared = session.prepare(query)
+>>> for user in users:
+...     bound = prepared.bind((user.id, user.name, user.age))
+...     session.execute(bound)
+
+
+

Alternatively, if protocol_version is 5 or higher +(requires Cassandra 4.0+), the keyspace can be specified as a +parameter. This will allow you to avoid specifying the keyspace in the +query without specifying a keyspace in connect(). It +even will let you prepare and use statements against a keyspace other +than the one originally specified on connection:

+
>>> analyticskeyspace_prepared = session.prepare(
+...     "INSERT INTO user_activity id, last_activity VALUES (?, ?)",
+...     keyspace="analyticskeyspace")  # note the different keyspace
+
+
+

Important: PreparedStatements should be prepared only once. +Preparing the same query more than once will likely affect performance.

+

custom_payload is a key value map to be passed along with the prepare +message. See Custom Payloads.

+
+ +
+
+shutdown()
+

Close all connections. Session instances should not be used +for any purpose after being shutdown.

+
+ +
+
+set_keyspace(keyspace)
+

Set the default keyspace for all queries made through this Session. +This operation blocks until complete.

+
+ +
+
+get_execution_profile(name)
+

Returns the execution profile associated with the provided name.

+
+
Parameters
+

name – The name (or key) of the execution profile.

+
+
+
+ +
+
+execution_profile_clone_update(ep, **kwargs)
+

Returns a clone of the ep profile. kwargs can be specified to update attributes +of the returned profile.

+

This is a shallow clone, so any objects referenced by the profile are shared. This means Load Balancing Policy +is maintained by inclusion in the active profiles. It also means updating any other rich objects will be seen +by the active profile. In cases where this is not desirable, be sure to replace the instance instead of manipulating +the shared object.

+
+ +
+
+add_request_init_listener(fn, *args, **kwargs)
+

Adds a callback with arguments to be called when any request is created.

+

It will be invoked as fn(response_future, *args, **kwargs) after each client request is created, +and before the request is sent. This can be used to create extensions by adding result callbacks to the +response future.

+

response_future is the ResponseFuture for the request.

+

Note that the init callback is done on the client thread creating the request, so you may need to consider +synchronization if you have multiple threads. Any callbacks added to the response future will be executed +on the event loop thread, so the normal advice about minimizing cycles and avoiding blocking apply (see Note in +ResponseFuture.add_callbacks().

+

See this example in the +source tree for an example.

+
+ +
+
+remove_request_init_listener(fn, *args, **kwargs)
+

Removes a callback and arguments from the list.

+

See Session.add_request_init_listener().

+
+ +
+ +
+
+class cassandra.cluster.ResponseFuture
+

An asynchronous response delivery mechanism that is returned from calls +to Session.execute_async().

+
+
There are two ways for results to be delivered:
+
+
+
+
+query = None
+
+ +
+
+result()
+

Return the final result or raise an Exception if errors were +encountered. If the final result or error has not been set +yet, this method will block until it is set, or the timeout +set for the request expires.

+

Timeout is specified in the Session request execution functions. +If the timeout is exceeded, an cassandra.OperationTimedOut will be raised. +This is a client-side timeout. For more information +about server-side coordinator timeouts, see policies.RetryPolicy.

+

Example usage:

+
>>> future = session.execute_async("SELECT * FROM mycf")
+>>> # do other stuff...
+
+>>> try:
+...     rows = future.result()
+...     for row in rows:
+...         ... # process results
+... except Exception:
+...     log.exception("Operation failed:")
+
+
+
+ +
+
+get_query_trace()
+

Fetches and returns the query trace of the last response, or None if tracing was +not enabled.

+

Note that this may raise an exception if there are problems retrieving the trace +details from Cassandra. If the trace is not available after max_wait, +cassandra.query.TraceUnavailable will be raised.

+

If the ResponseFuture is not done (async execution) and you try to retrieve the trace, +cassandra.query.TraceUnavailable will be raised.

+

query_cl is the consistency level used to poll the trace tables.

+
+ +
+
+get_all_query_traces()
+

Fetches and returns the query traces for all query pages, if tracing was enabled.

+

See note in get_query_trace() regarding possible exceptions.

+
+ +
+
+custom_payload
+

The custom payload returned from the server, if any. This will only be +set by Cassandra servers implementing a custom QueryHandler, and only +for protocol_version 4+.

+

Ensure the future is complete before trying to access this property +(call result(), or after callback is invoked). +Otherwise it may throw if the response has not been received.

+
+
Returns
+

Custom Payloads.

+
+
+
+ +
+
+is_schema_agreed = True
+
+ +
+
+has_more_pages
+

Returns True if there are more pages left in the +query results, False otherwise. This should only +be checked after the first page has been returned.

+
+

New in version 2.0.0.

+
+
+ +
+
+warnings
+

Warnings returned from the server, if any. This will only be +set for protocol_version 4+.

+

Warnings may be returned for such things as oversized batches, +or too many tombstones in slice queries.

+

Ensure the future is complete before trying to access this property +(call result(), or after callback is invoked). +Otherwise it may throw if the response has not been received.

+
+ +
+
+start_fetching_next_page()
+

If there are more pages left in the query result, this asynchronously +starts fetching the next page. If there are no pages left, QueryExhausted +is raised. Also see has_more_pages.

+

This should only be called after the first page has been returned.

+
+

New in version 2.0.0.

+
+
+ +
+
+add_callback(fn, *args, **kwargs)
+

Attaches a callback function to be called when the final results arrive.

+

By default, fn will be called with the results as the first and only +argument. If *args or **kwargs are supplied, they will be passed +through as additional positional or keyword arguments to fn.

+

If an error is hit while executing the operation, a callback attached +here will not be called. Use add_errback() or add_callbacks() +if you wish to handle that case.

+

If the final result has already been seen when this method is called, +the callback will be called immediately (before this method returns).

+

Note: in the case that the result is not available when the callback is added, +the callback is executed by IO event thread. This means that the callback +should not block or attempt further synchronous requests, because no further +IO will be processed until the callback returns.

+

Important: if the callback you attach results in an exception being +raised, the exception will be ignored, so please ensure your +callback handles all error cases that you care about.

+

Usage example:

+
>>> session = cluster.connect("mykeyspace")
+
+>>> def handle_results(rows, start_time, should_log=False):
+...     if should_log:
+...         log.info("Total time: %f", time.time() - start_time)
+...     ...
+
+>>> future = session.execute_async("SELECT * FROM users")
+>>> future.add_callback(handle_results, time.time(), should_log=True)
+
+
+
+ +
+
+add_errback(fn, *args, **kwargs)
+

Like add_callback(), but handles error cases. +An Exception instance will be passed as the first positional argument +to fn.

+
+ +
+
+ResponseFuture.add_callbacks(callback, errback, callback_args=(), callback_kwargs=None, errback_args=(), errback_args=None)
+

A convenient combination of add_callback() and +add_errback().

+

Example usage:

+
>>> session = cluster.connect()
+>>> query = "SELECT * FROM mycf"
+>>> future = session.execute_async(query)
+
+>>> def log_results(results, level='debug'):
+...     for row in results:
+...         log.log(level, "Result: %s", row)
+
+>>> def log_error(exc, query):
+...     log.error("Query '%s' failed: %s", query, exc)
+
+>>> future.add_callbacks(
+...     callback=log_results, callback_kwargs={'level': 'info'},
+...     errback=log_error, errback_args=(query,))
+
+
+
+ +
+ +
+
+class cassandra.cluster.ResultSet
+

An iterator over the rows from a query result. Also supplies basic equality +and indexing methods for backward-compatability. These methods materialize +the entire result set (loading all pages), and should only be used if the +total result size is understood. Warnings are emitted when paged results +are materialized in this fashion.

+

You can treat this as a normal iterator over rows:

+
>>> from cassandra.query import SimpleStatement
+>>> statement = SimpleStatement("SELECT * FROM users", fetch_size=10)
+>>> for user_row in session.execute(statement):
+...     process_user(user_row)
+
+
+

Whenever there are no more rows in the current page, the next page will +be fetched transparently. However, note that it is possible for +an Exception to be raised while fetching the next page, just +like you might see on a normal call to session.execute().

+
+
+all()
+

Returns all the remaining rows as a list. This is basically +a convenient shortcut to list(result_set).

+

This function is not recommended for queries that return a large number of elements.

+
+ +
+
+property current_rows
+

The list of current page rows. May be empty if the result was empty, +or this is the last page.

+
+ +
+
+fetch_next_page()
+

Manually, synchronously fetch the next page. Supplied for manually retrieving pages +and inspecting current_page(). It is not necessary to call this when iterating +through results; paging happens implicitly in iteration.

+
+ +
+
+get_all_query_traces(max_wait_sec_per=None)
+

Gets all query traces from the associated future. +See ResponseFuture.get_all_query_traces() for details.

+
+ +
+
+get_query_trace(max_wait_sec=None)
+

Gets the last query trace from the associated future. +See ResponseFuture.get_query_trace() for details.

+
+ +
+
+property has_more_pages
+

True if the last response indicated more pages; False otherwise

+
+ +
+
+one()
+

Return a single row of the results or None if empty. This is basically +a shortcut to result_set.current_rows[0] and should only be used when +you know a query returns a single row. Consider using an iterator if the +ResultSet contains more than one row.

+
+ +
+
+property paging_state
+

Server paging state of the query. Can be None if the query was not paged.

+

The driver treats paging state as opaque, but it may contain primary key data, so applications may want to +avoid sending this to untrusted parties.

+
+ +
+
+property was_applied
+

For LWT results, returns whether the transaction was applied.

+

Result is indeterminate if called on a result that was not an LWT request or on +a query.BatchStatement containing LWT. In the latter case either all the batch +succeeds or fails.

+

Only valid when one of the of the internal row factories is in use.

+
+ +
+ +
+
+exception cassandra.cluster.QueryExhausted
+

Raised when ResponseFuture.start_fetching_next_page() is called and +there are no more pages. You can check ResponseFuture.has_more_pages +before calling to avoid this.

+
+

New in version 2.0.0.

+
+
+ +
+
+exception cassandra.cluster.NoHostAvailable
+

Raised when an operation is attempted but all connections are +busy, defunct, closed, or resulted in errors when used.

+
+ +
+
+exception cassandra.cluster.UserTypeDoesNotExist
+

An attempt was made to use a user-defined type that does not exist.

+
+

New in version 2.1.0.

+
+
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.26.2-scylla/api/cassandra/concurrent.html b/3.26.2-scylla/api/cassandra/concurrent.html new file mode 100644 index 0000000000..e0703d9591 --- /dev/null +++ b/3.26.2-scylla/api/cassandra/concurrent.html @@ -0,0 +1,701 @@ + + + + + + + + + + + + + cassandra.concurrent - Utilities for Concurrent Statement Execution | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + + + +
+ +
+ +
+

cassandra.concurrent - Utilities for Concurrent Statement Execution

+
+
+cassandra.concurrent.execute_concurrent(session, statements_and_parameters, concurrency=100, raise_on_first_error=True, results_generator=False, execution_profile=<object object>)
+

Executes a sequence of (statement, parameters) tuples concurrently. Each +parameters item must be a sequence or None.

+

The concurrency parameter controls how many statements will be executed +concurrently. When Cluster.protocol_version is set to 1 or 2, +it is recommended that this be kept below 100 times the number of +core connections per host times the number of connected hosts (see +Cluster.set_core_connections_per_host()). If that amount is exceeded, +the event loop thread may attempt to block on new connection creation, +substantially impacting throughput. If protocol_version +is 3 or higher, you can safely experiment with higher levels of concurrency.

+

If raise_on_first_error is left as True, execution will stop +after the first failed statement and the corresponding exception will be +raised.

+

results_generator controls how the results are returned.

+
    +
  • If False, the results are returned only after all requests have completed.

  • +
  • If True, a generator expression is returned. Using a generator results in a constrained +memory footprint when the results set will be large – results are yielded +as they return instead of materializing the entire list at once. The trade for lower memory +footprint is marginal CPU overhead (more thread coordination and sorting out-of-order results +on-the-fly).

  • +
+

execution_profile argument is the execution profile to use for this +request, it is passed directly to Session.execute_async().

+

A sequence of ExecutionResult(success, result_or_exc) namedtuples is returned +in the same order that the statements were passed in. If success is False, +there was an error executing the statement, and result_or_exc will be +an Exception. If success is True, result_or_exc +will be the query result.

+

Example usage:

+
select_statement = session.prepare("SELECT * FROM users WHERE id=?")
+
+statements_and_params = []
+for user_id in user_ids:
+    params = (user_id, )
+    statements_and_params.append((select_statement, params))
+
+results = execute_concurrent(
+    session, statements_and_params, raise_on_first_error=False)
+
+for (success, result) in results:
+    if not success:
+        handle_error(result)  # result will be an Exception
+    else:
+        process_user(result[0])  # result will be a list of rows
+
+
+

Note: in the case that generators are used, it is important to ensure the consumers do not +block or attempt further synchronous requests, because no further IO will be processed until +the consumer returns. This may also produce a deadlock in the IO event thread.

+
+ +
+
+cassandra.concurrent.execute_concurrent_with_args(session, statement, parameters, *args, **kwargs)
+

Like execute_concurrent(), but takes a single +statement and a sequence of parameters. Each item in parameters +should be a sequence or None.

+

Example usage:

+
statement = session.prepare("INSERT INTO mytable (a, b) VALUES (1, ?)")
+parameters = [(x,) for x in range(1000)]
+execute_concurrent_with_args(session, statement, parameters, concurrency=50)
+
+
+
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.26.2-scylla/api/cassandra/connection.html b/3.26.2-scylla/api/cassandra/connection.html new file mode 100644 index 0000000000..c36e16834f --- /dev/null +++ b/3.26.2-scylla/api/cassandra/connection.html @@ -0,0 +1,729 @@ + + + + + + + + + + + + + cassandra.connection - Low Level Connection Info | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + + + +
+ +
+ +
+

cassandra.connection - Low Level Connection Info

+
+
+exception cassandra.connection.ConnectionException
+

An unrecoverable error was hit when attempting to use a connection, +or the connection was already closed or defunct.

+
+ +
+
+exception cassandra.connection.ConnectionShutdown
+

Raised when a connection has been marked as defunct or has been closed.

+
+ +
+
+exception cassandra.connection.ConnectionBusy
+

An attempt was made to send a message through a Connection that +was already at the max number of in-flight operations.

+
+ +
+
+exception cassandra.connection.ProtocolError
+

Communication did not match the protocol that this driver expects.

+
+ +
+
+class cassandra.connection.EndPoint
+

Represents the information to connect to a cassandra node.

+
+
+property address
+

The IP address of the node. This is the RPC address the driver uses when connecting to the node

+
+ +
+
+property port
+

The port of the node.

+
+ +
+
+resolve()
+

Resolve the endpoint to an address/port. This is called +only on socket connection.

+
+ +
+
+property socket_family
+

The socket family of the endpoint.

+
+ +
+
+property ssl_options
+

SSL options specific to this endpoint.

+
+ +
+ +
+
+class cassandra.connection.EndPointFactory
+
+
+configure(cluster)
+

This is called by the cluster during its initialization.

+
+ +
+
+create(row)
+

Create an EndPoint from a system.peers row.

+
+ +
+ +
+
+class cassandra.connection.SniEndPoint(proxy_address, server_name, port=9042)
+

SNI Proxy EndPoint implementation.

+
+ +
+
+class cassandra.connection.SniEndPointFactory(proxy_address, port, node_domain=None)
+
+ +
+
+class cassandra.connection.UnixSocketEndPoint(unix_socket_path)
+

Unix Socket EndPoint implementation.

+
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.26.2-scylla/api/cassandra/cqlengine/columns.html b/3.26.2-scylla/api/cassandra/cqlengine/columns.html new file mode 100644 index 0000000000..b7e7583043 --- /dev/null +++ b/3.26.2-scylla/api/cassandra/cqlengine/columns.html @@ -0,0 +1,947 @@ + + + + + + + + + + + + + cassandra.cqlengine.columns - Column types for object mapping models | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + + + +
+ +
+ +
+

cassandra.cqlengine.columns - Column types for object mapping models

+
+

Columns

+

Columns in your models map to columns in your CQL table. You define CQL columns by defining column attributes on your model classes. +For a model to be valid it needs at least one primary key column and one non-primary key column.

+

Just as in CQL, the order you define your columns in is important, and is the same order they are defined in on a model’s corresponding table.

+

Each column on your model definitions needs to be an instance of a Column class.

+
+
+class cassandra.cqlengine.columns.Column(**kwargs)
+
+
+primary_key = False
+

bool flag, indicates this column is a primary key. The first primary key defined +on a model is the partition key (unless partition keys are set), all others are cluster keys

+
+ +
+
+partition_key = False
+

indicates that this column should be the partition key, defining +more than one partition key column creates a compound partition key

+
+ +
+
+index = False
+

bool flag, indicates an index should be created for this column

+
+ +
+
+custom_index = False
+

bool flag, indicates an index is managed outside of cqlengine. This is +useful if you want to do filter queries on fields that have custom +indexes.

+
+ +
+
+db_field = None
+

the fieldname this field will map to in the database

+
+ +
+
+default = None
+

the default value, can be a value or a callable (no args)

+
+ +
+
+required = False
+

boolean, is the field required? Model validation will raise and +exception if required is set to True and there is a None value assigned

+
+ +
+
+clustering_order = None
+

only applicable on clustering keys (primary keys that are not partition keys) +determines the order that the clustering keys are sorted on disk

+
+ +
+
+discriminator_column = False
+

boolean, if set to True, this column will be used for discriminating records +of inherited models.

+

Should only be set on a column of an abstract model being used for inheritance.

+

There may only be one discriminator column per model. See __discriminator_value__ +for how to specify the value of this column on specialized models.

+
+ +
+
+static = False
+

boolean, if set to True, this is a static column, with a single value per partition

+
+ +
+ +
+
+

Column Types

+

Columns of all types are initialized by passing Column attributes to the constructor by keyword.

+
+
+class cassandra.cqlengine.columns.Ascii(**kwargs)
+

Stores a US-ASCII character string

+
+
Parameters
+
    +
  • min_length (int) – Sets the minimum length of this string, for validation purposes. +Defaults to 1 if this is a required column. Otherwise, None.

  • +
  • max_length (int) – Sets the maximum length of this string, for validation purposes.

  • +
+
+
+
+ +
+
+class cassandra.cqlengine.columns.BigInt(**kwargs)
+

Stores a 64-bit signed integer value

+
+ +
+
+class cassandra.cqlengine.columns.Blob(**kwargs)
+

Stores a raw binary value

+
+ +
+
+cassandra.cqlengine.columns.Bytes
+

alias of cassandra.cqlengine.columns.Blob

+
+ +
+
+class cassandra.cqlengine.columns.Boolean(**kwargs)
+

Stores a boolean True or False value

+
+ +
+
+class cassandra.cqlengine.columns.Counter(index=False, db_field=None, required=False)
+

Stores a counter that can be incremented and decremented

+
+ +
+
+class cassandra.cqlengine.columns.Date(**kwargs)
+

Stores a simple date, with no time-of-day

+
+

Changed in version 2.6.0: removed overload of Date and DateTime. DateTime is a drop-in replacement for legacy models

+
+

requires C* 2.2+ and protocol v4+

+
+ +
+
+class cassandra.cqlengine.columns.DateTime(**kwargs)
+

Stores a datetime value

+
+
+truncate_microseconds = False
+

Set this True to have model instances truncate the date, quantizing it in the same way it will be in the database. +This allows equality comparison between assigned values and values read back from the database:

+
DateTime.truncate_microseconds = True
+assert Model.create(id=0, d=datetime.utcnow()) == Model.objects(id=0).first()
+
+
+

Defaults to False to preserve legacy behavior. May change in the future.

+
+ +
+ +
+
+class cassandra.cqlengine.columns.Decimal(**kwargs)
+

Stores a variable precision decimal value

+
+ +
+
+class cassandra.cqlengine.columns.Double(**kwargs)
+

Stores a double-precision floating-point value

+
+ +
+
+class cassandra.cqlengine.columns.Float(primary_key=False, partition_key=False, index=False, db_field=None, default=None, required=False, clustering_order=None, discriminator_column=False, static=False, custom_index=False)
+

Stores a single-precision floating-point value

+
+ +
+
+class cassandra.cqlengine.columns.Integer(**kwargs)
+

Stores a 32-bit signed integer value

+
+ +
+
+class cassandra.cqlengine.columns.List(value_type, default=<class 'list'>, **kwargs)
+

Stores a list of ordered values

+

http://www.datastax.com/documentation/cql/3.1/cql/cql_using/use_list_t.html

+
+
Parameters
+

value_type – a column class indicating the types of the value

+
+
+
+ +
+
+class cassandra.cqlengine.columns.Map(key_type, value_type, default=<class 'dict'>, **kwargs)
+

Stores a key -> value map (dictionary)

+

https://docs.datastax.com/en/dse/6.7/cql/cql/cql_using/useMap.html

+
+
Parameters
+
    +
  • key_type – a column class indicating the types of the key

  • +
  • value_type – a column class indicating the types of the value

  • +
+
+
+
+ +
+
+class cassandra.cqlengine.columns.Set(value_type, strict=True, default=<class 'set'>, **kwargs)
+

Stores a set of unordered, unique values

+

http://www.datastax.com/documentation/cql/3.1/cql/cql_using/use_set_t.html

+
+
Parameters
+
    +
  • value_type – a column class indicating the types of the value

  • +
  • strict – sets whether non set values will be coerced to set +type on validation, or raise a validation error, defaults to True

  • +
+
+
+
+ +
+
+class cassandra.cqlengine.columns.SmallInt(**kwargs)
+

Stores a 16-bit signed integer value

+
+

New in version 2.6.0.

+
+

requires C* 2.2+ and protocol v4+

+
+ +
+
+class cassandra.cqlengine.columns.Text(min_length=None, max_length=None, **kwargs)
+

Stores a UTF-8 encoded string

+
+
Parameters
+
    +
  • min_length (int) – Sets the minimum length of this string, for validation purposes. +Defaults to 1 if this is a required column. Otherwise, None.

  • +
  • max_length (int) – Sets the maximum length of this string, for validation purposes.

  • +
+
+
+
+ +
+
+class cassandra.cqlengine.columns.Time(**kwargs)
+

Stores a timezone-naive time-of-day, with nanosecond precision

+
+

New in version 2.6.0.

+
+

requires C* 2.2+ and protocol v4+

+
+ +
+
+class cassandra.cqlengine.columns.TimeUUID(**kwargs)
+

UUID containing timestamp

+
+ +
+
+class cassandra.cqlengine.columns.TinyInt(**kwargs)
+

Stores an 8-bit signed integer value

+
+

New in version 2.6.0.

+
+

requires C* 2.2+ and protocol v4+

+
+ +
+
+class cassandra.cqlengine.columns.UserDefinedType(user_type, **kwargs)
+

User Defined Type column

+

http://www.datastax.com/documentation/cql/3.1/cql/cql_using/cqlUseUDT.html

+

These columns are represented by a specialization of cassandra.cqlengine.usertype.UserType.

+

Please see User Defined Types for examples and discussion.

+
+
Parameters
+

user_type (type) – specifies the UserType model of the column

+
+
+
+ +
+
+class cassandra.cqlengine.columns.UUID(**kwargs)
+

Stores a type 1 or 4 UUID

+
+ +
+
+class cassandra.cqlengine.columns.VarInt(**kwargs)
+

Stores an arbitrary-precision integer

+
+ +
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.26.2-scylla/api/cassandra/cqlengine/connection.html b/3.26.2-scylla/api/cassandra/cqlengine/connection.html new file mode 100644 index 0000000000..1afa408540 --- /dev/null +++ b/3.26.2-scylla/api/cassandra/cqlengine/connection.html @@ -0,0 +1,708 @@ + + + + + + + + + + + + + cassandra.cqlengine.connection - Connection management for cqlengine | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + + + +
+ +
+ +
+

cassandra.cqlengine.connection - Connection management for cqlengine

+
+
+cassandra.cqlengine.connection.default()
+

Configures the default connection to localhost, using the driver defaults +(except for row_factory)

+
+ +
+
+cassandra.cqlengine.connection.set_session(s)
+

Configures the default connection with a preexisting cassandra.cluster.Session

+

Note: the mapper presently requires a Session cassandra.cluster.Session.row_factory set to dict_factory. +This may be relaxed in the future

+
+ +
+
+cassandra.cqlengine.connection.setup(hosts, default_keyspace, consistency=None, lazy_connect=False, retry_connect=False, **kwargs)
+

Setup a the driver connection used by the mapper

+
+
Parameters
+
    +
  • hosts (list) – list of hosts, (contact_points for cassandra.cluster.Cluster)

  • +
  • default_keyspace (str) – The default keyspace to use

  • +
  • consistency (int) – The global default ConsistencyLevel - default is the same as Session.default_consistency_level

  • +
  • lazy_connect (bool) – True if should not connect until first use

  • +
  • retry_connect (bool) – True if we should retry to connect even if there was a connection failure initially

  • +
  • **kwargs – Pass-through keyword arguments for cassandra.cluster.Cluster

  • +
+
+
+
+ +
+
+cassandra.cqlengine.connection.register_connection(name, hosts=None, consistency=None, lazy_connect=False, retry_connect=False, cluster_options=None, default=False, session=None)
+

Add a connection to the connection registry. hosts and session are +mutually exclusive, and consistency, lazy_connect, +retry_connect, and cluster_options only work with hosts. Using +hosts will create a new cassandra.cluster.Cluster and +cassandra.cluster.Session.

+
+
Parameters
+
    +
  • hosts (list) – list of hosts, (contact_points for cassandra.cluster.Cluster).

  • +
  • consistency (int) – The default ConsistencyLevel for the +registered connection’s new session. Default is the same as +Session.default_consistency_level. For use with hosts only; +will fail when used with session.

  • +
  • lazy_connect (bool) – True if should not connect until first use. For +use with hosts only; will fail when used with session.

  • +
  • retry_connect (bool) – True if we should retry to connect even if there +was a connection failure initially. For use with hosts only; will +fail when used with session.

  • +
  • cluster_options (dict) – A dict of options to be used as keyword +arguments to cassandra.cluster.Cluster. For use with hosts +only; will fail when used with session.

  • +
  • default (bool) – If True, set the new connection as the cqlengine +default

  • +
  • session (Session) – A cassandra.cluster.Session to be used in +the created connection.

  • +
+
+
+
+ +
+
+cassandra.cqlengine.connection.unregister_connection(name)
+
+ +
+
+cassandra.cqlengine.connection.set_default_connection(name)
+
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.26.2-scylla/api/cassandra/cqlengine/management.html b/3.26.2-scylla/api/cassandra/cqlengine/management.html new file mode 100644 index 0000000000..0a04504ccc --- /dev/null +++ b/3.26.2-scylla/api/cassandra/cqlengine/management.html @@ -0,0 +1,730 @@ + + + + + + + + + + + + + cassandra.cqlengine.management - Schema management for cqlengine | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + + + +
+ +
+ +
+

cassandra.cqlengine.management - Schema management for cqlengine

+

A collection of functions for managing keyspace and table schema.

+
+
+cassandra.cqlengine.management.create_keyspace_simple(name, replication_factor, durable_writes=True, connections=None)
+

Creates a keyspace with SimpleStrategy for replica placement

+

If the keyspace already exists, it will not be modified.

+

This function should be used with caution, especially in production environments. +Take care to execute schema modifications in a single context (i.e. not concurrently with other clients).

+

There are plans to guard schema-modifying functions with an environment-driven conditional.

+
+
Parameters
+
    +
  • name (str) – name of keyspace to create

  • +
  • replication_factor (int) – keyspace replication factor, used with SimpleStrategy

  • +
  • durable_writes (bool) – Write log is bypassed if set to False

  • +
  • connections (list) – List of connection names

  • +
+
+
+
+ +
+
+cassandra.cqlengine.management.create_keyspace_network_topology(name, dc_replication_map, durable_writes=True, connections=None)
+

Creates a keyspace with NetworkTopologyStrategy for replica placement

+

If the keyspace already exists, it will not be modified.

+

This function should be used with caution, especially in production environments. +Take care to execute schema modifications in a single context (i.e. not concurrently with other clients).

+

There are plans to guard schema-modifying functions with an environment-driven conditional.

+
+
Parameters
+
    +
  • name (str) – name of keyspace to create

  • +
  • dc_replication_map (dict) – map of dc_names: replication_factor

  • +
  • durable_writes (bool) – Write log is bypassed if set to False

  • +
  • connections (list) – List of connection names

  • +
+
+
+
+ +
+
+cassandra.cqlengine.management.drop_keyspace(name, connections=None)
+

Drops a keyspace, if it exists.

+

There are plans to guard schema-modifying functions with an environment-driven conditional.

+

This function should be used with caution, especially in production environments. +Take care to execute schema modifications in a single context (i.e. not concurrently with other clients).

+
+
Parameters
+
    +
  • name (str) – name of keyspace to drop

  • +
  • connections (list) – List of connection names

  • +
+
+
+
+ +
+
+cassandra.cqlengine.management.sync_table(model, keyspaces=None, connections=None)
+

Inspects the model and creates / updates the corresponding table and columns.

+

If keyspaces is specified, the table will be synched for all specified keyspaces. +Note that the Model.__keyspace__ is ignored in that case.

+

If connections is specified, the table will be synched for all specified connections. Note that the Model.__connection__ is ignored in that case. +If not specified, it will try to get the connection from the Model.

+

Any User Defined Types used in the table are implicitly synchronized.

+

This function can only add fields that are not part of the primary key.

+

Note that the attributes removed from the model are not deleted on the database. +They become effectively ignored by (will not show up on) the model.

+

This function should be used with caution, especially in production environments. +Take care to execute schema modifications in a single context (i.e. not concurrently with other clients).

+

There are plans to guard schema-modifying functions with an environment-driven conditional.

+
+ +
+
+cassandra.cqlengine.management.sync_type(ks_name, type_model, connection=None)
+

Inspects the type_model and creates / updates the corresponding type.

+

Note that the attributes removed from the type_model are not deleted on the database (this operation is not supported). +They become effectively ignored by (will not show up on) the type_model.

+

This function should be used with caution, especially in production environments. +Take care to execute schema modifications in a single context (i.e. not concurrently with other clients).

+

There are plans to guard schema-modifying functions with an environment-driven conditional.

+
+ +
+
+cassandra.cqlengine.management.drop_table(model, keyspaces=None, connections=None)
+

Drops the table indicated by the model, if it exists.

+

If keyspaces is specified, the table will be dropped for all specified keyspaces. Note that the Model.__keyspace__ is ignored in that case.

+

If connections is specified, the table will be synched for all specified connections. Note that the Model.__connection__ is ignored in that case. +If not specified, it will try to get the connection from the Model.

+

This function should be used with caution, especially in production environments. +Take care to execute schema modifications in a single context (i.e. not concurrently with other clients).

+

There are plans to guard schema-modifying functions with an environment-driven conditional.

+
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.26.2-scylla/api/cassandra/cqlengine/models.html b/3.26.2-scylla/api/cassandra/cqlengine/models.html new file mode 100644 index 0000000000..1d0bd2e00e --- /dev/null +++ b/3.26.2-scylla/api/cassandra/cqlengine/models.html @@ -0,0 +1,935 @@ + + + + + + + + + + + + + cassandra.cqlengine.models - Table models for object mapping | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + + + +
+ +
+ +
+

cassandra.cqlengine.models - Table models for object mapping

+
+

Model

+
+
+class cassandra.cqlengine.models.Model(\*\*kwargs)
+

The initializer creates an instance of the model. Pass in keyword arguments for columns you’ve defined on the model.

+
class Person(Model):
+    id = columns.UUID(primary_key=True)
+    first_name  = columns.Text()
+    last_name = columns.Text()
+
+person = Person(first_name='Blake', last_name='Eggleston')
+person.first_name  #returns 'Blake'
+person.last_name  #returns 'Eggleston'
+
+
+

Model attributes define how the model maps to tables in the database. These are class variables that should be set +when defining Model deriviatives.

+
+
+__abstract__ = False
+

Optional. Indicates that this model is only intended to be used as a base class for other models. +You can’t create tables for abstract models, but checks around schema validity are skipped during class construction.

+
+ +
+
+__table_name__ = None
+

Optional. Sets the name of the CQL table for this model. If left blank, the table name will be the name of the model, with it’s module name as it’s prefix. Manually defined table names are not inherited.

+
+ +
+
+__table_name_case_sensitive__ = False
+

Optional. By default, __table_name__ is case insensitive. Set this to True if you want to preserve the case sensitivity.

+
+ +
+
+__keyspace__ = None
+

Sets the name of the keyspace used by this model.

+
+ +
+
+__connection__ = None
+

Sets the name of the default connection used by this model.

+
+ +
+
+__default_ttl__ = None
+

Will be deprecated in release 4.0. You can set the default ttl by configuring the table __options__. See Default TTL and Per Query TTL for more details.

+
+ +
+
+__discriminator_value__ = None
+

Optional Specifies a value for the discriminator column when using model inheritance.

+

See Model Inheritance for usage examples.

+
+ +

Each table can have its own set of configuration options, including compaction. Unspecified, these default to sensible values in +the server. To override defaults, set options using the model __options__ attribute, which allows options specified a dict.

+

When a table is synced, it will be altered to match the options set on your table. +This means that if you are changing settings manually they will be changed back on resync.

+

Do not use the options settings of cqlengine if you want to manage your compaction settings manually.

+

See the list of supported table properties for more information.

+
+
+__options__
+

For example:

+
class User(Model):
+    __options__ = {'compaction': {'class': 'LeveledCompactionStrategy',
+                                  'sstable_size_in_mb': '64',
+                                  'tombstone_threshold': '.2'},
+                   'comment': 'User data stored here'}
+
+    user_id = columns.UUID(primary_key=True)
+    name = columns.Text()
+
+
+

or :

+
class TimeData(Model):
+    __options__ = {'compaction': {'class': 'SizeTieredCompactionStrategy',
+                                  'bucket_low': '.3',
+                                  'bucket_high': '2',
+                                  'min_threshold': '2',
+                                  'max_threshold': '64',
+                                  'tombstone_compaction_interval': '86400'},
+                   'gc_grace_seconds': '0'}
+
+
+
+ +
+
+__compute_routing_key__ = True
+

Optional Setting False disables computing the routing key for TokenAwareRouting

+
+ +

The base methods allow creating, storing, and querying modeled objects.

+
+
+classmethod create(**kwargs)
+

Create an instance of this model in the database.

+

Takes the model column values as keyword arguments. Setting a value to +None is equivalent to running a CQL DELETE on that column.

+

Returns the instance.

+
+ +
+
+if_not_exists()
+

Check the existence of an object before insertion. The existence of an +object is determined by its primary key(s). And please note using this flag +would incur performance cost.

+

If the insertion isn’t applied, a LWTException is raised.

+
try:
+    TestIfNotExistsModel.if_not_exists().create(id=id, count=9, text='111111111111')
+except LWTException as e:
+    # handle failure case
+    print e.existing  # dict containing LWT result fields
+
+
+

This method is supported on Cassandra 2.0 or later.

+
+ +
+
+if_exists()
+

Check the existence of an object before an update or delete. The existence of an +object is determined by its primary key(s). And please note using this flag +would incur performance cost.

+

If the update or delete isn’t applied, a LWTException is raised.

+
try:
+    TestIfExistsModel.objects(id=id).if_exists().update(count=9, text='111111111111')
+except LWTException as e:
+    # handle failure case
+    pass
+
+
+

This method is supported on Cassandra 2.0 or later.

+
+ +
+
+save()
+

Saves an object to the database.

+
#create a person instance
+person = Person(first_name='Kimberly', last_name='Eggleston')
+#saves it to Cassandra
+person.save()
+
+
+
+ +
+
+update(**values)
+

Performs an update on the model instance. You can pass in values to set on the model +for updating, or you can call without values to execute an update against any modified +fields. If no fields on the model have been modified since loading, no query will be +performed. Model validation is performed normally. Setting a value to None is +equivalent to running a CQL DELETE on that column.

+

It is possible to do a blind update, that is, to update a field without having first selected the object out of the database. +See Blind Updates

+
+ +
+
+iff(**values)
+

Checks to ensure that the values specified are correct on the Cassandra cluster. +Simply specify the column(s) and the expected value(s). As with if_not_exists, +this incurs a performance cost.

+

If the insertion isn’t applied, a LWTException is raised.

+
t = TestTransactionModel(text='some text', count=5)
+try:
+     t.iff(count=5).update('other text')
+except LWTException as e:
+    # handle failure case
+    print e.existing # existing object
+
+
+
+ +
+
+classmethod get(*args, **kwargs)
+

Returns a single object based on the passed filter constraints.

+

This is a pass-through to the model objects().:method:~cqlengine.queries.get.

+
+ +
+
+classmethod filter(*args, **kwargs)
+

Returns a queryset based on filter parameters.

+

This is a pass-through to the model objects().:method:~cqlengine.queries.filter.

+
+ +
+
+classmethod all()
+

Returns a queryset representing all stored objects

+

This is a pass-through to the model objects().all()

+
+ +
+
+delete()
+

Deletes the object from the database

+
+ +
+
+batch(batch_object)
+

Sets the batch object to run instance updates and inserts queries with.

+

See Batch Queries for usage examples

+
+ +
+
+timeout(timeout)
+

Sets a timeout for use in save(), update(), and delete() +operations

+
+ +
+
+timestamp(timedelta_or_datetime)
+

Sets the timestamp for the query

+
+ +
+
+ttl(ttl_in_sec)
+

Sets the ttl values to run instance updates and inserts queries with.

+
+ +
+
+using(connection=None)
+

Change the context on the fly of the model instance (keyspace, connection)

+
+ +
+
+classmethod column_family_name(include_keyspace=True)
+

Returns the column family name if it’s been defined +otherwise, it creates it from the module and class name

+
+ +

Models also support dict-like access:

+
+
+len(m)
+

Returns the number of columns defined in the model

+
+ +
+
+m[col_name]
+

Returns the value of column col_name

+
+ +
+
+m[col_name] = value
+

Set m[col_name] to value

+
+ +
+
+keys()
+

Returns a list of column IDs.

+
+ +
+
+values()
+

Returns list of column values.

+
+ +
+
+items()
+

Returns a list of column ID/value tuples.

+
+ +
+ +
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.26.2-scylla/api/cassandra/cqlengine/query.html b/3.26.2-scylla/api/cassandra/cqlengine/query.html new file mode 100644 index 0000000000..6eef3ab682 --- /dev/null +++ b/3.26.2-scylla/api/cassandra/cqlengine/query.html @@ -0,0 +1,1031 @@ + + + + + + + + + + + + + cassandra.cqlengine.query - Query and filter model objects | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + + + +
+ +
+ +
+

cassandra.cqlengine.query - Query and filter model objects

+
+

QuerySet

+

QuerySet objects are typically obtained by calling objects() on a model class. +The methods here are used to filter, order, and constrain results.

+
+
+class cassandra.cqlengine.query.ModelQuerySet(model)
+
+
+all()
+

Returns a queryset matching all rows

+
for user in User.objects().all():
+    print(user)
+
+
+
+ +
+
+batch(batch_obj)
+

Set a batch object to run the query on.

+

Note: running a select query with a batch object will raise an exception

+
+ +
+
+consistency(consistency)
+

Sets the consistency level for the operation. See ConsistencyLevel.

+
for user in User.objects(id=3).consistency(CL.ONE):
+    print(user)
+
+
+
+ +
+
+count()
+

Returns the number of rows matched by this query.

+

Note: This function executes a SELECT COUNT() and has a performance cost on large datasets

+
+ +
+
+len(queryset)
+

Returns the number of rows matched by this query. This function uses count() internally.

+

Note: This function executes a SELECT COUNT() and has a performance cost on large datasets

+
+ +
+
+distinct(distinct_fields=None)
+

Returns the DISTINCT rows matched by this query.

+

distinct_fields default to the partition key fields if not specified.

+

Note: distinct_fields must be a partition key or a static column

+
class Automobile(Model):
+    manufacturer = columns.Text(partition_key=True)
+    year = columns.Integer(primary_key=True)
+    model = columns.Text(primary_key=True)
+    price = columns.Decimal()
+
+sync_table(Automobile)
+
+# create rows
+
+Automobile.objects.distinct()
+
+# or
+
+Automobile.objects.distinct(['manufacturer'])
+
+
+
+ +
+
+filter(*args, **kwargs)
+

Adds WHERE arguments to the queryset, returning a new queryset

+

See Retrieving objects with filters

+

Returns a QuerySet filtered on the keyword arguments

+
+ +
+
+get(*args, **kwargs)
+

Returns a single instance matching this query, optionally with additional filter kwargs.

+

See Retrieving objects with filters

+

Returns a single object matching the QuerySet.

+
user = User.get(id=1)
+
+
+

If no objects are matched, a DoesNotExist exception is raised.

+

If more than one object is found, a MultipleObjectsReturned exception is raised.

+
+ +
+
+limit(v)
+

Limits the number of results returned by Cassandra. Use 0 or None to disable.

+

Note that CQL’s default limit is 10,000, so all queries without a limit set explicitly will have an implicit limit of 10,000

+
# Fetch 100 users
+for user in User.objects().limit(100):
+    print(user)
+
+# Fetch all users
+for user in User.objects().limit(None):
+    print(user)
+
+
+
+ +
+
+fetch_size(v)
+

Sets the number of rows that are fetched at a time.

+

Note that driver’s default fetch size is 5000.

+
for user in User.objects().fetch_size(500):
+    print(user)
+
+
+
+ +
+
+if_not_exists()
+

Check the existence of an object before insertion.

+

If the insertion isn’t applied, a LWTException is raised.

+
+ +
+
+if_exists()
+

Check the existence of an object before an update or delete.

+

If the update or delete isn’t applied, a LWTException is raised.

+
+ +
+
+order_by(*colnames)
+

Sets the column(s) to be used for ordering

+

Default order is ascending, prepend a ‘-’ to any column name for descending

+

Note: column names must be a clustering key

+
from uuid import uuid1,uuid4
+
+class Comment(Model):
+    photo_id = UUID(primary_key=True)
+    comment_id = TimeUUID(primary_key=True, default=uuid1) # second primary key component is a clustering key
+    comment = Text()
+
+sync_table(Comment)
+
+u = uuid4()
+for x in range(5):
+    Comment.create(photo_id=u, comment="test %d" % x)
+
+print("Normal")
+for comment in Comment.objects(photo_id=u):
+    print comment.comment_id
+
+print("Reversed")
+for comment in Comment.objects(photo_id=u).order_by("-comment_id"):
+    print comment.comment_id
+
+
+
+ +
+
+allow_filtering()
+

Enables the (usually) unwise practive of querying on a clustering key without also defining a partition key

+
+ +
+
+only(fields)
+

Load only these fields for the returned query

+
+ +
+
+defer(fields)
+

Don’t load these fields for the returned query

+
+ +
+
+timestamp(timestamp)
+

Allows for custom timestamps to be saved with the record.

+
+ +
+
+ttl(ttl)
+

Sets the ttl (in seconds) for modified data.

+

Note that running a select query with a ttl value will raise an exception

+
+ +
+
+using(keyspace=None, connection=None)
+

Change the context on-the-fly of the Model class (keyspace, connection)

+
+ +
+
+update(**values)
+

Performs an update on the row selected by the queryset. Include values to update in the +update like so:

+
Model.objects(key=n).update(value='x')
+
+
+

Passing in updates for columns which are not part of the model will raise a ValidationError.

+

Per column validation will be performed, but instance level validation will not +(i.e., Model.validate is not called). This is sometimes referred to as a blind update.

+

For example:

+
class User(Model):
+    id = Integer(primary_key=True)
+    name = Text()
+
+setup(["localhost"], "test")
+sync_table(User)
+
+u = User.create(id=1, name="jon")
+
+User.objects(id=1).update(name="Steve")
+
+# sets name to null
+User.objects(id=1).update(name=None)
+
+
+

Also supported is blindly adding and removing elements from container columns, +without loading a model instance from Cassandra.

+

Using the syntax .update(column_name={x, y, z}) will overwrite the contents of the container, like updating a +non container column. However, adding __<operation> to the end of the keyword arg, makes the update call add +or remove items from the collection, without overwriting then entire column.

+

Given the model below, here are the operations that can be performed on the different container columns:

+
class Row(Model):
+    row_id      = columns.Integer(primary_key=True)
+    set_column  = columns.Set(Integer)
+    list_column = columns.List(Integer)
+    map_column  = columns.Map(Integer, Integer)
+
+
+

Set

+
    +
  • add: adds the elements of the given set to the column

  • +
  • remove: removes the elements of the given set to the column

  • +
+
# add elements to a set
+Row.objects(row_id=5).update(set_column__add={6})
+
+# remove elements to a set
+Row.objects(row_id=5).update(set_column__remove={4})
+
+
+

List

+
    +
  • append: appends the elements of the given list to the end of the column

  • +
  • prepend: prepends the elements of the given list to the beginning of the column

  • +
+
# append items to a list
+Row.objects(row_id=5).update(list_column__append=[6, 7])
+
+# prepend items to a list
+Row.objects(row_id=5).update(list_column__prepend=[1, 2])
+
+
+

Map

+
    +
  • update: adds the given keys/values to the columns, creating new entries if they didn’t exist, and overwriting old ones if they did

  • +
+
# add items to a map
+Row.objects(row_id=5).update(map_column__update={1: 2, 3: 4})
+
+# remove items from a map
+Row.objects(row_id=5).update(map_column__remove={1, 2})
+
+
+
+ +
+ +
+
+class cassandra.cqlengine.query.BatchQuery(batch_type=None, timestamp=None, consistency=None, execute_on_exception=False, timeout=<object object>, connection=None)
+

Handles the batching of queries

+

http://docs.datastax.com/en/cql/3.0/cql/cql_reference/batch_r.html

+

See Batch Queries for more details.

+
+
Parameters
+
    +
  • batch_type (BatchType, str or None) – (optional) One of batch type values available through BatchType enum

  • +
  • timestamp (datetime or timedelta or None) – (optional) A datetime or timedelta object with desired timestamp to be applied +to the batch conditional.

  • +
  • consistency (The ConsistencyLevel to be used for the batch query, or None.) – (optional) One of consistency values (“ANY”, “ONE”, “QUORUM” etc)

  • +
  • execute_on_exception (bool) – (Defaults to False) Indicates that when the BatchQuery instance is used +as a context manager the queries accumulated within the context must be executed despite +encountering an error within the context. By default, any exception raised from within +the context scope will cause the batched queries not to be executed.

  • +
  • timeout (float or None) – (optional) Timeout for the entire batch (in seconds), if not specified fallback +to default session timeout

  • +
  • connection (str) – Connection name to use for the batch execution

  • +
+
+
+
+
+add_query(query)
+
+ +
+
+execute()
+
+ +
+
+add_callback(fn, *args, **kwargs)
+

Add a function and arguments to be passed to it to be executed after the batch executes.

+

A batch can support multiple callbacks.

+

Note, that if the batch does not execute, the callbacks are not executed. +A callback, thus, is an “on batch success” handler.

+
+
Parameters
+
    +
  • fn (callable) – Callable object

  • +
  • *args – Positional arguments to be passed to the callback at the time of execution

  • +
  • **kwargs – Named arguments to be passed to the callback at the time of execution

  • +
+
+
+
+ +
+ +
+
+class cassandra.cqlengine.query.ContextQuery(*args, **kwargs)
+

A Context manager to allow a Model to switch context easily. Presently, the context only +specifies a keyspace for model IO.

+
+
Parameters
+
    +
  • *args – One or more models. A model should be a class type, not an instance.

  • +
  • **kwargs – (optional) Context parameters: can be keyspace or connection

  • +
+
+
+

For example:

+
with ContextQuery(Automobile, keyspace='test2') as A:
+    A.objects.create(manufacturer='honda', year=2008, model='civic')
+    print len(A.objects.all())  # 1 result
+
+with ContextQuery(Automobile, keyspace='test4') as A:
+    print len(A.objects.all())  # 0 result
+
+# Multiple models
+with ContextQuery(Automobile, Automobile2, connection='cluster2') as (A, A2):
+    print len(A.objects.all())
+    print len(A2.objects.all())
+
+
+
+ +
+
+class cassandra.cqlengine.query.DoesNotExist
+
+ +
+
+class cassandra.cqlengine.query.MultipleObjectsReturned
+
+ +
+
+class cassandra.cqlengine.query.LWTException(existing)
+

Lightweight conditional exception.

+

This exception will be raised when a write using an IF clause could not be +applied due to existing data violating the condition. The existing data is +available through the existing attribute.

+
+
Parameters
+

existing – The current state of the data which prevented the write.

+
+
+
+ +
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.26.2-scylla/api/cassandra/cqlengine/usertype.html b/3.26.2-scylla/api/cassandra/cqlengine/usertype.html new file mode 100644 index 0000000000..9f63dbba70 --- /dev/null +++ b/3.26.2-scylla/api/cassandra/cqlengine/usertype.html @@ -0,0 +1,674 @@ + + + + + + + + + + + + + cassandra.cqlengine.usertype - Model classes for User Defined Types | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + + + +
+ +
+ +
+

cassandra.cqlengine.usertype - Model classes for User Defined Types

+
+

UserType

+
+
+class cassandra.cqlengine.usertype.UserType(**values)
+

This class is used to model User Defined Types. To define a type, declare a class inheriting from this, +and assign field types as class attributes:

+
# connect with default keyspace ...
+
+from cassandra.cqlengine.columns import Text, Integer
+from cassandra.cqlengine.usertype import UserType
+
+class address(UserType):
+    street = Text()
+    zipcode = Integer()
+
+from cassandra.cqlengine import management
+management.sync_type(address)
+
+
+

Please see User Defined Types for a complete example and discussion.

+
+
+__type_name__ = None
+

Optional. Sets the name of the CQL type for this type.

+

If not specified, the type name will be the name of the class, with it’s module name as it’s prefix.

+
+ +
+ +
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.26.2-scylla/api/cassandra/datastax/graph/fluent/index.html b/3.26.2-scylla/api/cassandra/datastax/graph/fluent/index.html new file mode 100644 index 0000000000..f84447d2ca --- /dev/null +++ b/3.26.2-scylla/api/cassandra/datastax/graph/fluent/index.html @@ -0,0 +1,748 @@ + + + + + + + + + + + + + cassandra.datastax.graph.fluent | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + + + +
+ +
+ +
+

cassandra.datastax.graph.fluent

+
+
+class cassandra.datastax.graph.fluent.DseGraph
+

Dse Graph utility class for GraphTraversal construction and execution.

+
+
+DSE_GRAPH_QUERY_LANGUAGE = 'bytecode-json'
+

Graph query language, Default is ‘bytecode-json’ (GraphSON).

+
+ +
+
+static create_execution_profile(graph_name, graph_protocol=b'graphson-2.0', **kwargs)
+

Creates an ExecutionProfile for GraphTraversal execution. You need to register that execution profile to the +cluster by using cluster.add_execution_profile.

+
+
Parameters
+
    +
  • graph_name – The graph name

  • +
  • graph_protocol – (Optional) The graph protocol, default is DSE_GRAPH_QUERY_PROTOCOL.

  • +
+
+
+
+ +
+
+static query_from_traversal(traversal, graph_protocol=b'graphson-2.0', context=None)
+

From a GraphTraversal, return a query string based on the language specified in DseGraph.DSE_GRAPH_QUERY_LANGUAGE.

+
+
Parameters
+
    +
  • traversal – The GraphTraversal object

  • +
  • graph_protocol – The graph protocol. Default is DseGraph.DSE_GRAPH_QUERY_PROTOCOL.

  • +
  • context – The dict of the serialization context, needed for GraphSON3 (tuple, udt). +e.g: {‘cluster’: cluster, ‘graph_name’: name}

  • +
+
+
+
+ +
+
+static traversal_source(session=None, graph_name=None, execution_profile=EXEC_PROFILE_GRAPH_DEFAULT, traversal_class=None)
+

Returns a TinkerPop GraphTraversalSource binded to the session and graph_name if provided.

+
+
Parameters
+
    +
  • session – (Optional) A DSE session

  • +
  • graph_name – (Optional) DSE Graph name

  • +
  • execution_profile – (Optional) Execution profile for traversal queries. Default is set to EXEC_PROFILE_GRAPH_DEFAULT.

  • +
  • traversal_class – (Optional) The GraphTraversalSource class to use (DSL).

  • +
+
+
+
from cassandra.cluster import Cluster
+from cassandra.datastax.graph.fluent import DseGraph
+
+c = Cluster()
+session = c.connect()
+
+g = DseGraph.traversal_source(session, 'my_graph')
+print g.V().valueMap().toList()
+
+
+
+ +
+
+static batch(session=None, execution_profile=None)
+

Returns the cassandra.datastax.graph.fluent.query.TraversalBatch object allowing to +execute multiple traversals in the same transaction.

+
+ +
+ +
+
+class cassandra.datastax.graph.fluent.DSESessionRemoteGraphConnection(session[, graph_name, execution_profile])
+

A Tinkerpop RemoteConnection to execute traversal queries on DSE.

+
+
Parameters
+
    +
  • session – A DSE session

  • +
  • graph_name – (Optional) DSE Graph name.

  • +
  • execution_profile – (Optional) Execution profile for traversal queries. Default is set to EXEC_PROFILE_GRAPH_DEFAULT.

  • +
+
+
+
+ +
+
+class cassandra.datastax.graph.fluent.BaseGraphRowFactory(cluster)
+

Base row factory for graph traversal. This class basically wraps a +graphson reader function to handle additional features of Gremlin/DSE +and is callable as a normal row factory.

+
+
Currently supported:
    +
  • bulk results

  • +
+
+
+
+ +
+
+cassandra.datastax.graph.fluent.graph_traversal_row_factory
+

alias of cassandra.datastax.graph.fluent._GremlinGraphSON2RowFactory

+
+ +
+
+cassandra.datastax.graph.fluent.graph_traversal_dse_object_row_factory
+

alias of cassandra.datastax.graph.fluent._DseGraphSON2RowFactory

+
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.26.2-scylla/api/cassandra/datastax/graph/fluent/predicates.html b/3.26.2-scylla/api/cassandra/datastax/graph/fluent/predicates.html new file mode 100644 index 0000000000..ad7cad230c --- /dev/null +++ b/3.26.2-scylla/api/cassandra/datastax/graph/fluent/predicates.html @@ -0,0 +1,744 @@ + + + + + + + + + + + + + cassandra.datastax.graph.fluent.predicates | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + + + +
+ +
+ +
+

cassandra.datastax.graph.fluent.predicates

+
+
+class cassandra.datastax.graph.fluent.predicates.Search
+
+
+static token(value)
+

Search any instance of a certain token within the text property targeted. +:param value: the value to look for.

+
+ +
+
+static token_prefix(value)
+

Search any instance of a certain token prefix withing the text property targeted. +:param value: the value to look for.

+
+ +
+
+static token_regex(value)
+

Search any instance of the provided regular expression for the targeted property. +:param value: the value to look for.

+
+ +
+
+static prefix(value)
+

Search for a specific prefix at the beginning of the text property targeted. +:param value: the value to look for.

+
+ +
+
+static regex(value)
+

Search for this regular expression inside the text property targeted. +:param value: the value to look for.

+
+ +
+
+static fuzzy(value, distance)
+

Search for a fuzzy string inside the text property targeted. +:param value: the value to look for. +:param distance: The distance for the fuzzy search. ie. 1, to allow a one-letter misspellings.

+
+ +
+
+static token_fuzzy(value, distance)
+

Search for a token fuzzy inside the text property targeted. +:param value: the value to look for. +:param distance: The distance for the token fuzzy search. ie. 1, to allow a one-letter misspellings.

+
+ +
+
+static phrase(value, proximity)
+

Search for a phrase inside the text property targeted. +:param value: the value to look for. +:param proximity: The proximity for the phrase search. ie. phrase(‘David Felcey’, 2).. to find ‘David Felcey’ with up to two middle names.

+
+ +
+ +
+
+class cassandra.datastax.graph.fluent.predicates.CqlCollection
+
+
+static contains(value)
+

Search for a value inside a cql list/set column. +:param value: the value to look for.

+
+ +
+
+static contains_value(value)
+

Search for a map value. +:param value: the value to look for.

+
+ +
+
+static contains_key(value)
+

Search for a map key. +:param value: the value to look for.

+
+ +
+
+static entry_eq(value)
+

Search for a map entry. +:param value: the value to look for.

+
+ +
+ +
+
+class cassandra.datastax.graph.fluent.predicates.Geo
+
+
+static inside(value, units=1)
+

Search any instance of geometry inside the Distance targeted. +:param value: A Distance to look for. +:param units: The units for value. See GeoUnit enum. (Can also +provide an integer to use as a multiplier to convert value to +degrees.)

+
+ +
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.26.2-scylla/api/cassandra/datastax/graph/fluent/query.html b/3.26.2-scylla/api/cassandra/datastax/graph/fluent/query.html new file mode 100644 index 0000000000..d7ed43bfb3 --- /dev/null +++ b/3.26.2-scylla/api/cassandra/datastax/graph/fluent/query.html @@ -0,0 +1,695 @@ + + + + + + + + + + + + + cassandra.datastax.graph.fluent.query | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + + + +
+ +
+ +
+

cassandra.datastax.graph.fluent.query

+
+
+class cassandra.datastax.graph.fluent.query.TraversalBatch(session=None, execution_profile=None)
+

A TraversalBatch is used to execute multiple graph traversals in a +single transaction. If any traversal in the batch fails, the entire +batch will fail to apply.

+

If a TraversalBatch is bounded to a DSE session, it can be executed using +traversal_batch.execute().

+
+
Parameters
+
    +
  • session – (Optional) A DSE session

  • +
  • execution_profile – (Optional) The execution profile to use for the batch execution

  • +
+
+
+
+
+add(traversal)
+

Add a traversal to the batch.

+
+
Parameters
+

traversal – A gremlin GraphTraversal

+
+
+
+ +
+
+add_all(traversals)
+

Adds a sequence of traversals to the batch.

+
+
Parameters
+

traversals – A sequence of gremlin GraphTraversal

+
+
+
+ +
+
+execute()
+

Execute the traversal batch if bounded to a DSE Session.

+
+ +
+
+as_graph_statement(graph_protocol=b'graphson-2.0')
+

Return the traversal batch as GraphStatement.

+
+
Parameters
+

graph_protocol – The graph protocol for the GraphSONWriter. Default is GraphProtocol.GRAPHSON_2_0.

+
+
+
+ +
+
+clear()
+

Clear a traversal batch for reuse.

+
+ +
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.26.2-scylla/api/cassandra/datastax/graph/index.html b/3.26.2-scylla/api/cassandra/datastax/graph/index.html new file mode 100644 index 0000000000..9a0ea62ae3 --- /dev/null +++ b/3.26.2-scylla/api/cassandra/datastax/graph/index.html @@ -0,0 +1,1026 @@ + + + + + + + + + + + + + cassandra.datastax.graph - Graph Statements, Options, and Row Factories | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + + + +
+ +
+ +
+

cassandra.datastax.graph - Graph Statements, Options, and Row Factories

+
+
+cassandra.datastax.graph.single_object_row_factory(column_names, rows)
+

returns the JSON string value of graph results

+
+ +
+
+cassandra.datastax.graph.graph_result_row_factory(column_names, rows)
+

Returns a Result object that can load graph results and produce specific types. +The Result JSON is deserialized and unpacked from the top-level ‘result’ dict.

+
+ +
+
+cassandra.datastax.graph.graph_object_row_factory(column_names, rows)
+

Like graph_result_row_factory(), except known element types (Vertex, Edge) are +converted to their simplified objects. Some low-level metadata is shed in this conversion. Unknown result types are +still returned as Result.

+
+ +
+
+cassandra.datastax.graph.graph_graphson2_row_factory(cluster)
+

Row factory to deserialize GraphSON2 results.

+
+ +
+
+cassandra.datastax.graph.graph_graphson3_row_factory(cluster)
+

Row factory to deserialize GraphSON3 results.

+
+ +
+
+cassandra.datastax.graph.to_int(value)
+

Wraps a value to be explicitly serialized as a graphson Int.

+
+ +
+
+cassandra.datastax.graph.to_bigint(value)
+

Wraps a value to be explicitly serialized as a graphson Bigint.

+
+ +
+
+cassandra.datastax.graph.to_smallint(value)
+

Wraps a value to be explicitly serialized as a graphson Smallint.

+
+ +
+
+cassandra.datastax.graph.to_float(value)
+

Wraps a value to be explicitly serialized as a graphson Float.

+
+ +
+
+cassandra.datastax.graph.to_double(value)
+

Wraps a value to be explicitly serialized as a graphson Double.

+
+ +
+
+class cassandra.datastax.graph.GraphProtocol
+
+
+GRAPHSON_1_0 = b'graphson-1.0'
+

GraphSON1

+
+ +
+
+GRAPHSON_2_0 = b'graphson-2.0'
+

GraphSON2

+
+ +
+
+GRAPHSON_3_0 = b'graphson-3.0'
+

GraphSON3

+
+ +
+ +
+
+class cassandra.datastax.graph.GraphOptions(**kwargs)
+

Options for DSE Graph Query handler.

+
+
+graph_name
+

name of the targeted graph.

+
+ +
+
+graph_source
+

choose the graph traversal source, configured on the server side.

+
+ +
+
+graph_language
+

the language used in the queries (default “gremlin-groovy”)

+
+ +
+
+graph_read_consistency_level
+

read cassandra.ConsistencyLevel for graph queries (if distinct from session default). +Setting this overrides the native Statement.consistency_level for read operations from Cassandra persistence

+
+ +
+
+graph_write_consistency_level
+

write cassandra.ConsistencyLevel for graph queries (if distinct from session default). +Setting this overrides the native Statement.consistency_level for write operations to Cassandra persistence.

+
+ +
+
+is_default_source
+
+ +
+
+is_analytics_source
+

True if graph_source is set to the server-defined analytics traversal source (‘a’)

+
+ +
+
+is_graph_source
+

True if graph_source is set to the server-defined graph traversal source (‘g’)

+
+ +
+
+set_source_default()
+

Sets graph_source to the server-defined default traversal source (‘default’)

+
+ +
+
+set_source_analytics()
+

Sets graph_source to the server-defined analytic traversal source (‘a’)

+
+ +
+
+set_source_graph()
+

Sets graph_source to the server-defined graph traversal source (‘g’)

+
+ +
+ +
+
+class cassandra.datastax.graph.SimpleGraphStatement(query_string, retry_policy=None, consistency_level=None, routing_key=None, serial_consistency_level=None, fetch_size=<object object>, keyspace=None, custom_payload=None, is_idempotent=False)
+

Simple graph statement for Session.execute_graph(). +Takes the same parameters as SimpleStatement.

+

query_string should be a literal CQL statement with the exception +of parameter placeholders that will be filled through the +parameters argument of Session.execute().

+

See Statement attributes for a description of the other parameters.

+
+ +
+
+class cassandra.datastax.graph.Result(value)
+

Represents deserialized graph results. +Property and item getters are provided for convenience.

+
+
+value = None
+

Deserialized value from the result

+
+ +
+
+as_vertex()
+

Return a Vertex parsed from this result

+

Raises TypeError if parsing fails (i.e. the result structure is not valid).

+
+ +
+
+as_edge()
+

Return a Edge parsed from this result

+

Raises TypeError if parsing fails (i.e. the result structure is not valid).

+
+ +
+
+as_path()
+

Return a Path parsed from this result

+

Raises TypeError if parsing fails (i.e. the result structure is not valid).

+
+ +
+ +
+
+class cassandra.datastax.graph.Vertex(id, label, type, properties)
+

Represents a Vertex element from a graph query.

+

Vertex properties are extracted into a dict of property names to list of VertexProperty (list +because they are always encoded that way, and sometimes have multiple cardinality; VertexProperty because sometimes +the properties themselves have property maps).

+
+ +
+
+class cassandra.datastax.graph.VertexProperty(label, value, properties=None)
+

Vertex properties have a top-level value and an optional dict of properties.

+
+
+label = None
+

label of the property

+
+ +
+
+value = None
+

Value of the property

+
+ +
+
+properties = None
+

dict of properties attached to the property

+
+ +
+ +
+
+class cassandra.datastax.graph.Edge(id, label, type, properties, inV, inVLabel, outV, outVLabel)
+

Represents an Edge element from a graph query.

+

Attributes match initializer parameters.

+
+ +
+
+class cassandra.datastax.graph.Path(labels, objects)
+

Represents a graph path.

+

Labels list is taken verbatim from the results.

+

Objects are either Result or Vertex/Edge for recognized types

+
+
+labels = None
+

List of labels in the path

+
+ +
+
+objects = None
+

List of objects in the path

+
+ +
+ +
+
+class cassandra.datastax.graph.T(name, val)
+

Represents a collection of tokens for more concise Traversal definitions.

+
+
+id = T.id
+
+ +
+
+key = T.key
+
+ +
+
+label = T.label
+
+ +
+
+value = T.value
+
+ +
+ +
+
+class cassandra.datastax.graph.GraphSON1Serializer
+

Serialize python objects to graphson types.

+
+ +
+
+class cassandra.datastax.graph.GraphSON1Deserializer
+

Deserialize graphson1 types to python objects.

+
+
+classmethod deserialize_date(value)
+
+ +
+
+classmethod deserialize_timestamp(value)
+
+ +
+
+classmethod deserialize_time(value)
+
+ +
+
+classmethod deserialize_duration(value)
+
+ +
+
+classmethod deserialize_int(value)
+
+ +
+
+classmethod deserialize_bigint(value)
+
+ +
+
+classmethod deserialize_double(value)
+
+ +
+
+classmethod deserialize_float(value)
+
+ +
+
+classmethod deserialize_uuid(value)
+
+ +
+
+classmethod deserialize_blob(value)
+
+ +
+
+classmethod deserialize_decimal(value)
+
+ +
+
+classmethod deserialize_point(value)
+
+ +
+
+classmethod deserialize_linestring(value)
+
+ +
+
+classmethod deserialize_polygon(value)
+
+ +
+ +
+
+class cassandra.datastax.graph.GraphSON2Reader(context, extra_deserializer_map=None)
+

GraphSON2 Reader that parse json and deserialize to python objects.

+
+
Parameters
+

extra_deserializer_map – map from GraphSON type tag to deserializer instance implementing deserialize

+
+
+
+
+read(json_data)
+

Read and deserialize json_data.

+
+ +
+
+deserialize(obj)
+

Deserialize GraphSON type-tagged dict values into objects mapped in self.deserializers

+
+ +
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.26.2-scylla/api/cassandra/decoder.html b/3.26.2-scylla/api/cassandra/decoder.html new file mode 100644 index 0000000000..98ba97340d --- /dev/null +++ b/3.26.2-scylla/api/cassandra/decoder.html @@ -0,0 +1,656 @@ + + + + + + + + + + + + + cassandra.decoder - Data Return Formats | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + + + +
+ +
+ +
+

cassandra.decoder - Data Return Formats

+
+
+cassandra.decoder.tuple_factory()
+

Deprecated in 2.0.0. Use cassandra.query.tuple_factory()

+
+ +
+
+cassandra.decoder.named_tuple_factory()
+

Deprecated in 2.0.0. Use cassandra.query.named_tuple_factory()

+
+ +
+
+cassandra.decoder.dict_factory()
+

Deprecated in 2.0.0. Use cassandra.query.dict_factory()

+
+ +
+
+cassandra.decoder.ordered_dict_factory()
+

Deprecated in 2.0.0. Use cassandra.query.ordered_dict_factory()

+
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.26.2-scylla/api/cassandra/encoder.html b/3.26.2-scylla/api/cassandra/encoder.html new file mode 100644 index 0000000000..98627bcb3d --- /dev/null +++ b/3.26.2-scylla/api/cassandra/encoder.html @@ -0,0 +1,733 @@ + + + + + + + + + + + + + cassandra.encoder - Encoders for non-prepared Statements | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + + + +
+ +
+ +
+

cassandra.encoder - Encoders for non-prepared Statements

+
+
+class cassandra.encoder.Encoder
+

A container for mapping python types to CQL string literals when working +with non-prepared statements. The type mapping can be +directly customized by users.

+
+
+mapping = None
+

A map of python types to encoder functions.

+
+ +
+
+cql_encode_none()
+

Converts None to the string ‘NULL’.

+
+ +
+
+cql_encode_object()
+

Default encoder for all objects that do not have a specific encoder function +registered. This function simply calls str() on the object.

+
+ +
+
+cql_encode_all_types()
+

Converts any type into a CQL string, defaulting to cql_encode_object +if mapping does not contain an entry for the type.

+
+ +
+
+cql_encode_sequence()
+

Converts a sequence to a string of the form (item1, item2, ...). This +is suitable for IN value lists.

+
+ +
+
+cql_encode_str()
+

Escapes quotes in str objects.

+
+ +
+
+cql_encode_unicode()
+

Converts unicode objects to UTF-8 encoded strings with quote escaping.

+
+ +
+
+cql_encode_bytes()
+

Converts strings, buffers, and bytearrays into CQL blob literals.

+
+ +
+
+cql_encode_datetime()
+

Converts a datetime.datetime object to a (string) integer timestamp +with millisecond precision.

+
+ +
+
+cql_encode_date()
+

Converts a datetime.date object to a string with format +YYYY-MM-DD.

+
+ +
+
+cql_encode_map_collection()
+

Converts a dict into a string of the form {key1: val1, key2: val2, ...}. +This is suitable for map type columns.

+
+ +
+
+cql_encode_list_collection()
+

Converts a sequence to a string of the form [item1, item2, ...]. This +is suitable for list type columns.

+
+ +
+
+cql_encode_set_collection()
+

Converts a sequence to a string of the form {item1, item2, ...}. This +is suitable for set type columns.

+
+ +
+
+cql_encode_tuple()
+

Converts a sequence to a string of the form (item1, item2, ...). This +is suitable for tuple type columns.

+
+ +
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.26.2-scylla/api/cassandra/graph.html b/3.26.2-scylla/api/cassandra/graph.html new file mode 100644 index 0000000000..22caee0996 --- /dev/null +++ b/3.26.2-scylla/api/cassandra/graph.html @@ -0,0 +1,1019 @@ + + + + + + + + + + + + + cassandra.graph - Graph Statements, Options, and Row Factories | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + + + +
+ +
+ +
+

cassandra.graph - Graph Statements, Options, and Row Factories

+
+

Note

+

This module is only for backward compatibility for dse-driver users. Consider using cassandra.datastax.graph.

+
+
+
+cassandra.graph.single_object_row_factory(column_names, rows)
+

returns the JSON string value of graph results

+
+ +
+
+cassandra.graph.graph_result_row_factory(column_names, rows)
+

Returns a Result object that can load graph results and produce specific types. +The Result JSON is deserialized and unpacked from the top-level ‘result’ dict.

+
+ +
+
+cassandra.graph.graph_object_row_factory(column_names, rows)
+

Like graph_result_row_factory(), except known element types (Vertex, Edge) are +converted to their simplified objects. Some low-level metadata is shed in this conversion. Unknown result types are +still returned as Result.

+
+ +
+
+cassandra.graph.graph_graphson2_row_factory(cluster)
+

Row factory to deserialize GraphSON2 results.

+
+ +
+
+cassandra.graph.graph_graphson3_row_factory(cluster)
+

Row factory to deserialize GraphSON3 results.

+
+ +
+
+cassandra.graph.to_int(value)
+

Wraps a value to be explicitly serialized as a graphson Int.

+
+ +
+
+cassandra.graph.to_bigint(value)
+

Wraps a value to be explicitly serialized as a graphson Bigint.

+
+ +
+
+cassandra.graph.to_smallint(value)
+

Wraps a value to be explicitly serialized as a graphson Smallint.

+
+ +
+
+cassandra.graph.to_float(value)
+

Wraps a value to be explicitly serialized as a graphson Float.

+
+ +
+
+cassandra.graph.to_double(value)
+

Wraps a value to be explicitly serialized as a graphson Double.

+
+ +
+
+class cassandra.graph.GraphProtocol
+
+
+GRAPHSON_1_0 = b'graphson-1.0'
+

GraphSON1

+
+ +
+
+GRAPHSON_2_0 = b'graphson-2.0'
+

GraphSON2

+
+ +
+
+GRAPHSON_3_0 = b'graphson-3.0'
+

GraphSON3

+
+ +
+ +
+
+class cassandra.graph.GraphOptions(**kwargs)
+

Options for DSE Graph Query handler.

+
+
+graph_name
+

name of the targeted graph.

+
+ +
+
+graph_source
+

choose the graph traversal source, configured on the server side.

+
+ +
+
+graph_language
+

the language used in the queries (default “gremlin-groovy”)

+
+ +
+
+graph_read_consistency_level
+

read cassandra.ConsistencyLevel for graph queries (if distinct from session default). +Setting this overrides the native Statement.consistency_level for read operations from Cassandra persistence

+
+ +
+
+graph_write_consistency_level
+

write cassandra.ConsistencyLevel for graph queries (if distinct from session default). +Setting this overrides the native Statement.consistency_level for write operations to Cassandra persistence.

+
+ +
+
+is_default_source
+
+ +
+
+is_analytics_source
+

True if graph_source is set to the server-defined analytics traversal source (‘a’)

+
+ +
+
+is_graph_source
+

True if graph_source is set to the server-defined graph traversal source (‘g’)

+
+ +
+
+set_source_default()
+

Sets graph_source to the server-defined default traversal source (‘default’)

+
+ +
+
+set_source_analytics()
+

Sets graph_source to the server-defined analytic traversal source (‘a’)

+
+ +
+
+set_source_graph()
+

Sets graph_source to the server-defined graph traversal source (‘g’)

+
+ +
+ +
+
+class cassandra.graph.SimpleGraphStatement(query_string, retry_policy=None, consistency_level=None, routing_key=None, serial_consistency_level=None, fetch_size=<object object>, keyspace=None, custom_payload=None, is_idempotent=False)
+

Simple graph statement for Session.execute_graph(). +Takes the same parameters as SimpleStatement.

+

query_string should be a literal CQL statement with the exception +of parameter placeholders that will be filled through the +parameters argument of Session.execute().

+

See Statement attributes for a description of the other parameters.

+
+ +
+
+class cassandra.graph.Result(value)
+

Represents deserialized graph results. +Property and item getters are provided for convenience.

+
+
+value = None
+

Deserialized value from the result

+
+ +
+
+as_vertex()
+

Return a Vertex parsed from this result

+

Raises TypeError if parsing fails (i.e. the result structure is not valid).

+
+ +
+
+as_edge()
+

Return a Edge parsed from this result

+

Raises TypeError if parsing fails (i.e. the result structure is not valid).

+
+ +
+
+as_path()
+

Return a Path parsed from this result

+

Raises TypeError if parsing fails (i.e. the result structure is not valid).

+
+ +
+ +
+
+class cassandra.graph.Vertex(id, label, type, properties)
+

Represents a Vertex element from a graph query.

+

Vertex properties are extracted into a dict of property names to list of VertexProperty (list +because they are always encoded that way, and sometimes have multiple cardinality; VertexProperty because sometimes +the properties themselves have property maps).

+
+ +
+
+class cassandra.graph.VertexProperty(label, value, properties=None)
+

Vertex properties have a top-level value and an optional dict of properties.

+
+
+label = None
+

label of the property

+
+ +
+
+value = None
+

Value of the property

+
+ +
+
+properties = None
+

dict of properties attached to the property

+
+ +
+ +
+
+class cassandra.graph.Edge(id, label, type, properties, inV, inVLabel, outV, outVLabel)
+

Represents an Edge element from a graph query.

+

Attributes match initializer parameters.

+
+ +
+
+class cassandra.graph.Path(labels, objects)
+

Represents a graph path.

+

Labels list is taken verbatim from the results.

+

Objects are either Result or Vertex/Edge for recognized types

+
+
+labels = None
+

List of labels in the path

+
+ +
+
+objects = None
+

List of objects in the path

+
+ +
+ +
+
+class cassandra.graph.GraphSON1Serializer
+

Serialize python objects to graphson types.

+
+ +
+
+class cassandra.graph.GraphSON1Deserializer
+

Deserialize graphson1 types to python objects.

+
+
+classmethod deserialize_date(value)
+
+ +
+
+classmethod deserialize_timestamp(value)
+
+ +
+
+classmethod deserialize_time(value)
+
+ +
+
+classmethod deserialize_duration(value)
+
+ +
+
+classmethod deserialize_int(value)
+
+ +
+
+classmethod deserialize_bigint(value)
+
+ +
+
+classmethod deserialize_double(value)
+
+ +
+
+classmethod deserialize_float(value)
+
+ +
+
+classmethod deserialize_uuid(value)
+
+ +
+
+classmethod deserialize_blob(value)
+
+ +
+
+classmethod deserialize_decimal(value)
+
+ +
+
+classmethod deserialize_point(value)
+
+ +
+
+classmethod deserialize_linestring(value)
+
+ +
+
+classmethod deserialize_polygon(value)
+
+ +
+ +
+
+class cassandra.graph.GraphSON2Reader(context, extra_deserializer_map=None)
+

GraphSON2 Reader that parse json and deserialize to python objects.

+
+
Parameters
+

extra_deserializer_map – map from GraphSON type tag to deserializer instance implementing deserialize

+
+
+
+
+read(json_data)
+

Read and deserialize json_data.

+
+ +
+
+deserialize(obj)
+

Deserialize GraphSON type-tagged dict values into objects mapped in self.deserializers

+
+ +
+ +
+
+class cassandra.graph.GraphSON3Reader(context, extra_deserializer_map=None)
+

GraphSON3 Reader that parse json and deserialize to python objects.

+
+
Parameters
+
    +
  • context – A dict of the context, mostly used as context for udt deserialization.

  • +
  • extra_deserializer_map – map from GraphSON type tag to deserializer instance implementing deserialize

  • +
+
+
+
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.26.2-scylla/api/cassandra/io/asyncioreactor.html b/3.26.2-scylla/api/cassandra/io/asyncioreactor.html new file mode 100644 index 0000000000..7a84df30e5 --- /dev/null +++ b/3.26.2-scylla/api/cassandra/io/asyncioreactor.html @@ -0,0 +1,648 @@ + + + + + + + + + + + + + cassandra.io.asyncioreactor - asyncio Event Loop | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + + + +
+ +
+ +
+

cassandra.io.asyncioreactor - asyncio Event Loop

+
+
+class cassandra.io.asyncioreactor.AsyncioConnection(*args, **kwargs)
+

An experimental implementation of Connection that uses the +asyncio module in the Python standard library for its event loop.

+

Note that it requires asyncio features that were only introduced in the +3.4 line in 3.4.6, and in the 3.5 line in 3.5.1.

+
+
+classmethod initialize_reactor()
+

Called once by Cluster.connect(). This should be used by implementations +to set up any resources that will be shared across connections.

+
+ +
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.26.2-scylla/api/cassandra/io/asyncorereactor.html b/3.26.2-scylla/api/cassandra/io/asyncorereactor.html new file mode 100644 index 0000000000..194895bc8f --- /dev/null +++ b/3.26.2-scylla/api/cassandra/io/asyncorereactor.html @@ -0,0 +1,653 @@ + + + + + + + + + + + + + cassandra.io.asyncorereactor - asyncore Event Loop | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + + + +
+ +
+ +
+

cassandra.io.asyncorereactor - asyncore Event Loop

+
+
+class cassandra.io.asyncorereactor.AsyncoreConnection(*args, **kwargs)
+

An implementation of Connection that uses the asyncore +module in the Python standard library for its event loop.

+
+
+classmethod initialize_reactor()
+

Called once by Cluster.connect(). This should be used by implementations +to set up any resources that will be shared across connections.

+
+ +
+
+classmethod handle_fork()
+

Called after a forking. This should cleanup any remaining reactor state +from the parent process.

+
+ +
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.26.2-scylla/api/cassandra/io/eventletreactor.html b/3.26.2-scylla/api/cassandra/io/eventletreactor.html new file mode 100644 index 0000000000..3086314943 --- /dev/null +++ b/3.26.2-scylla/api/cassandra/io/eventletreactor.html @@ -0,0 +1,655 @@ + + + + + + + + + + + + + cassandra.io.eventletreactor - eventlet-compatible Connection | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + + + +
+ +
+ +
+

cassandra.io.eventletreactor - eventlet-compatible Connection

+
+
+class cassandra.io.eventletreactor.EventletConnection(*args, **kwargs)
+

An implementation of Connection that utilizes eventlet.

+

This implementation assumes all eventlet monkey patching is active. It is not tested with partial patching.

+
+
+classmethod initialize_reactor()
+

Called once by Cluster.connect(). This should be used by implementations +to set up any resources that will be shared across connections.

+
+ +
+
+classmethod service_timeouts()
+

cls._timeout_watcher runs in this loop forever. +It is usually waiting for the next timeout on the cls._new_timer Event. +When new timers are added, that event is set so that the watcher can +wake up and possibly set an earlier timeout.

+
+ +
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.26.2-scylla/api/cassandra/io/geventreactor.html b/3.26.2-scylla/api/cassandra/io/geventreactor.html new file mode 100644 index 0000000000..0e7c87c005 --- /dev/null +++ b/3.26.2-scylla/api/cassandra/io/geventreactor.html @@ -0,0 +1,646 @@ + + + + + + + + + + + + + cassandra.io.geventreactor - gevent-compatible Event Loop | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + + + +
+ +
+ +
+

cassandra.io.geventreactor - gevent-compatible Event Loop

+
+
+class cassandra.io.geventreactor.GeventConnection(*args, **kwargs)
+

An implementation of Connection that utilizes gevent.

+

This implementation assumes all gevent monkey patching is active. It is not tested with partial patching.

+
+
+classmethod initialize_reactor()
+

Called once by Cluster.connect(). This should be used by implementations +to set up any resources that will be shared across connections.

+
+ +
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.26.2-scylla/api/cassandra/io/libevreactor.html b/3.26.2-scylla/api/cassandra/io/libevreactor.html new file mode 100644 index 0000000000..b353911eff --- /dev/null +++ b/3.26.2-scylla/api/cassandra/io/libevreactor.html @@ -0,0 +1,638 @@ + + + + + + + + + + + + + cassandra.io.libevreactor - libev Event Loop | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + + + +
+ +
+ +
+

cassandra.io.libevreactor - libev Event Loop

+
+
+class cassandra.io.libevreactor.LibevConnection(*args, **kwargs)
+

An implementation of Connection that uses libev for its event loop.

+
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.26.2-scylla/api/cassandra/io/twistedreactor.html b/3.26.2-scylla/api/cassandra/io/twistedreactor.html new file mode 100644 index 0000000000..a41178f50a --- /dev/null +++ b/3.26.2-scylla/api/cassandra/io/twistedreactor.html @@ -0,0 +1,639 @@ + + + + + + + + + + + + + cassandra.io.twistedreactor - Twisted Event Loop | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + + + +
+ +
+ +
+

cassandra.io.twistedreactor - Twisted Event Loop

+
+
+class cassandra.io.twistedreactor.TwistedConnection
+

An implementation of Connection that uses +Twisted’s reactor as its event loop.

+
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.26.2-scylla/api/cassandra/metadata.html b/3.26.2-scylla/api/cassandra/metadata.html new file mode 100644 index 0000000000..71748d7cb5 --- /dev/null +++ b/3.26.2-scylla/api/cassandra/metadata.html @@ -0,0 +1,1023 @@ + + + + + + + + + + + + + cassandra.metadata - Schema and Ring Topology | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + + + +
+ +
+ +
+

cassandra.metadata - Schema and Ring Topology

+
+
+cassandra.metadata.cql_keywords
+

set() -> new empty set object +set(iterable) -> new set object

+

Build an unordered collection of unique elements.

+
+ +
+
+cassandra.metadata.cql_keywords_unreserved
+

set() -> new empty set object +set(iterable) -> new set object

+

Build an unordered collection of unique elements.

+
+ +
+
+cassandra.metadata.cql_keywords_reserved
+

set() -> new empty set object +set(iterable) -> new set object

+

Build an unordered collection of unique elements.

+
+ +
+
+class cassandra.metadata.Metadata
+

Holds a representation of the cluster schema and topology.

+
+
+add_or_return_host(host)
+

Returns a tuple (host, new), where host is a Host +instance, and new is a bool indicating whether +the host was newly added.

+
+ +
+
+all_hosts()
+

Returns a list of all known Host instances in the cluster.

+
+ +
+
+export_schema_as_string()
+

Returns a string that can be executed as a query in order to recreate +the entire schema. The string is formatted to be human readable.

+
+ +
+
+get_host(endpoint_or_address, port=None)
+

Find a host in the metadata for a specific endpoint. If a string inet address and port are passed, +iterate all hosts to match the broadcast_rpc_address and +broadcast_rpc_port attributes.

+
+ +
+
+get_host_by_host_id(host_id)
+

Same as get_host() but use host_id for lookup.

+
+ +
+
+get_replicas(keyspace, key)
+

Returns a list of Host instances that are replicas for a given +partition key.

+
+ +
+ +
+

Schemas

+
+
+class cassandra.metadata.KeyspaceMetadata
+

A representation of the schema for a single keyspace.

+
+
+as_cql_query()
+

Returns a CQL query string that can be used to recreate just this keyspace, +not including user-defined types and tables.

+
+ +
+
+export_as_string()
+

Returns a CQL query string that can be used to recreate the entire keyspace, +including user-defined types and tables.

+
+ +
+ +
+
+class cassandra.metadata.UserType
+

A user defined type, as created by CREATE TYPE statements.

+

User-defined types were introduced in Cassandra 2.1.

+
+

New in version 2.1.0.

+
+
+
+as_cql_query(formatted=False)
+

Returns a CQL query that can be used to recreate this type. +If formatted is set to True, extra whitespace will +be added to make the query more readable.

+
+ +
+ +
+
+class cassandra.metadata.Function
+

A user defined function, as created by CREATE FUNCTION statements.

+

User-defined functions were introduced in Cassandra 2.2

+
+

New in version 2.6.0.

+
+
+
+as_cql_query(formatted=False)
+

Returns a CQL query that can be used to recreate this function. +If formatted is set to True, extra whitespace will +be added to make the query more readable.

+
+ +
+ +
+
+class cassandra.metadata.Aggregate
+

A user defined aggregate function, as created by CREATE AGGREGATE statements.

+

Aggregate functions were introduced in Cassandra 2.2

+
+

New in version 2.6.0.

+
+
+
+as_cql_query(formatted=False)
+

Returns a CQL query that can be used to recreate this aggregate. +If formatted is set to True, extra whitespace will +be added to make the query more readable.

+
+ +
+ +
+
+class cassandra.metadata.TableMetadata
+

A representation of the schema for a single table.

+
+
+as_cql_query(formatted=False)
+

Returns a CQL query that can be used to recreate this table (index +creations are not included). If formatted is set to True, +extra whitespace will be added to make the query human readable.

+
+ +
+
+export_as_string()
+

Returns a string of CQL queries that can be used to recreate this table +along with all indexes on it. The returned string is formatted to +be human readable.

+
+ +
+
+property is_cql_compatible
+

A boolean indicating if this table can be represented as CQL in export

+
+ +
+
+property primary_key
+

A list of ColumnMetadata representing the components of +the primary key for this table.

+
+ +
+ +
+
+class cassandra.metadata.TableMetadataV3
+

For C* 3.0+. option_maps take a superset of map names, so if nothing +changes structurally, new option maps can just be appended to the list.

+
+
+property is_cql_compatible
+

A boolean indicating if this table can be represented as CQL in export

+
+ +
+ +
+
+class cassandra.metadata.TableMetadataDSE68
+
+
+as_cql_query(formatted=False)
+

Returns a CQL query that can be used to recreate this table (index +creations are not included). If formatted is set to True, +extra whitespace will be added to make the query human readable.

+
+ +
+ +
+
+class cassandra.metadata.ColumnMetadata
+

A representation of a single column in a table.

+
+ +
+
+class cassandra.metadata.IndexMetadata
+

A representation of a secondary index on a column.

+
+
+as_cql_query()
+

Returns a CQL query that can be used to recreate this index.

+
+ +
+
+export_as_string()
+

Returns a CQL query string that can be used to recreate this index.

+
+ +
+ +
+
+class cassandra.metadata.MaterializedViewMetadata
+

A representation of a materialized view on a table

+
+
+as_cql_query(formatted=False)
+

Returns a CQL query that can be used to recreate this function. +If formatted is set to True, extra whitespace will +be added to make the query more readable.

+
+ +
+ +
+
+class cassandra.metadata.VertexMetadata
+

A representation of a vertex on a table

+
+ +
+
+class cassandra.metadata.EdgeMetadata
+

A representation of an edge on a table

+
+ +
+
+

Tokens and Ring Topology

+
+
+class cassandra.metadata.TokenMap
+

Information about the layout of the ring.

+
+
+get_replicas(keyspace, token)
+

Get a set of Host instances representing all of the +replica nodes for a given Token.

+
+ +
+ +
+
+class cassandra.metadata.Token
+

Abstract class representing a token.

+
+ +
+
+class cassandra.metadata.Murmur3Token(token)
+

A token for Murmur3Partitioner.

+

token is an int or string representing the token.

+
+ +
+
+class cassandra.metadata.MD5Token(token)
+

A token for RandomPartitioner.

+
+ +
+
+class cassandra.metadata.BytesToken(token)
+

A token for ByteOrderedPartitioner.

+
+
+classmethod from_string(token_string)
+

token_string should be the string representation from the server.

+
+ +
+ +
+
+cassandra.metadata.ReplicationStrategy
+

alias of cassandra.metadata._ReplicationStrategy

+
+ +
+
+class cassandra.metadata.ReplicationFactor(all_replicas, transient_replicas=None)
+

Represent the replication factor of a keyspace.

+
+ +
+
+class cassandra.metadata.SimpleStrategy(options_map)
+
+
+export_for_schema()
+

Returns a string version of these replication options which are +suitable for use in a CREATE KEYSPACE statement.

+
+ +
+
+property replication_factor
+

The replication factor for this keyspace.

+

For backward compatibility, this returns the +cassandra.metadata.ReplicationFactor.full_replicas value of +cassandra.metadata.SimpleStrategy.replication_factor_info.

+
+ +
+ +
+
+class cassandra.metadata.NetworkTopologyStrategy(dc_replication_factors)
+
+
+export_for_schema()
+

Returns a string version of these replication options which are +suitable for use in a CREATE KEYSPACE statement.

+
+ +
+ +
+
+class cassandra.metadata.LocalStrategy(options_map)
+
+
+export_for_schema()
+

Returns a string version of these replication options which are +suitable for use in a CREATE KEYSPACE statement.

+
+ +
+ +
+
+cassandra.metadata.group_keys_by_replica(session, keyspace, table, keys)
+

Returns a dict with the keys grouped per host. This can be +used to more accurately group by IN clause or to batch the keys per host.

+

If a valid replica is not found for a particular key it will be grouped under +NO_VALID_REPLICA

+

Example usage:

+
>>> result = group_keys_by_replica(
+...     session, "system", "peers",
+...     (("127.0.0.1", ), ("127.0.0.2", )))
+
+
+
+ +
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.26.2-scylla/api/cassandra/metrics.html b/3.26.2-scylla/api/cassandra/metrics.html new file mode 100644 index 0000000000..7cdf34db82 --- /dev/null +++ b/3.26.2-scylla/api/cassandra/metrics.html @@ -0,0 +1,746 @@ + + + + + + + + + + + + + cassandra.metrics - Performance Metrics | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + + + +
+ +
+ +
+

cassandra.metrics - Performance Metrics

+
+
+class cassandra.metrics.Metrics
+

A collection of timers and counters for various performance metrics.

+

Timer metrics are represented as floating point seconds.

+
+
+request_timer = None
+

A greplin.scales.PmfStat timer for requests. This is a dict-like +object with the following keys:

+
    +
  • count - number of requests that have been timed

  • +
  • min - min latency

  • +
  • max - max latency

  • +
  • mean - mean latency

  • +
  • stddev - standard deviation for latencies

  • +
  • median - median latency

  • +
  • 75percentile - 75th percentile latencies

  • +
  • 95percentile - 95th percentile latencies

  • +
  • 98percentile - 98th percentile latencies

  • +
  • 99percentile - 99th percentile latencies

  • +
  • 999percentile - 99.9th percentile latencies

  • +
+
+ +
+
+connection_errors = None
+

A greplin.scales.IntStat count of the number of times that a +request to a Cassandra node has failed due to a connection problem.

+
+ +
+
+write_timeouts = None
+

A greplin.scales.IntStat count of write requests that resulted +in a timeout.

+
+ +
+
+read_timeouts = None
+

A greplin.scales.IntStat count of read requests that resulted +in a timeout.

+
+ +
+
+unavailables = None
+

A greplin.scales.IntStat count of write or read requests that +failed due to an insufficient number of replicas being alive to meet +the requested ConsistencyLevel.

+
+ +
+
+other_errors = None
+

A greplin.scales.IntStat count of all other request failures, +including failures caused by invalid requests, bootstrapping nodes, +overloaded nodes, etc.

+
+ +
+
+retries = None
+

A greplin.scales.IntStat count of the number of times a +request was retried based on the RetryPolicy decision.

+
+ +
+
+ignores = None
+

A greplin.scales.IntStat count of the number of times a +failed request was ignored based on the RetryPolicy decision.

+
+ +
+
+known_hosts = None
+

A greplin.scales.IntStat count of the number of nodes in +the cluster that the driver is aware of, regardless of whether any +connections are opened to those nodes.

+
+ +
+
+connected_to = None
+

A greplin.scales.IntStat count of the number of nodes that +the driver currently has at least one connection open to.

+
+ +
+
+open_connections = None
+

A greplin.scales.IntStat count of the number connections +the driver currently has open.

+
+ +
+
+get_stats()
+

Returns the metrics for the registered cluster instance.

+
+ +
+
+set_stats_name(stats_name)
+

Set the metrics stats name. +The stats_name is a string used to access the metris through scales: scales.getStats()[<stats_name>] +Default is ‘cassandra-<num>’.

+
+ +
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.26.2-scylla/api/cassandra/policies.html b/3.26.2-scylla/api/cassandra/policies.html new file mode 100644 index 0000000000..150e1b016c --- /dev/null +++ b/3.26.2-scylla/api/cassandra/policies.html @@ -0,0 +1,1733 @@ + + + + + + + + + + + + + cassandra.policies - Load balancing and Failure Handling Policies | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + + + +
+ +
+ +
+

cassandra.policies - Load balancing and Failure Handling Policies

+
+

Load Balancing

+
+
+class cassandra.policies.HostDistance
+

A measure of how “distant” a node is from the client, which +may influence how the load balancer distributes requests +and how many connections are opened to the node.

+
+
+IGNORED = -1
+

A node with this distance should never be queried or have +connections opened to it.

+
+ +
+
+LOCAL = 0
+

Nodes with LOCAL distance will be preferred for operations +under some load balancing policies (such as DCAwareRoundRobinPolicy) +and will have a greater number of connections opened against +them by default.

+

This distance is typically used for nodes within the same +datacenter as the client.

+
+ +
+
+REMOTE = 1
+

Nodes with REMOTE distance will be treated as a last resort +by some load balancing policies (such as DCAwareRoundRobinPolicy) +and will have a smaller number of connections opened against +them by default.

+

This distance is typically used for nodes outside of the +datacenter that the client is running in.

+
+ +
+ +
+
+class cassandra.policies.LoadBalancingPolicy
+

Load balancing policies are used to decide how to distribute +requests among all possible coordinator nodes in the cluster.

+

In particular, they may focus on querying “near” nodes (those +in a local datacenter) or on querying nodes who happen to +be replicas for the requested data.

+

You may also use subclasses of LoadBalancingPolicy for +custom behavior.

+
+
+distance(host)
+

Returns a measure of how remote a Host is in +terms of the HostDistance enums.

+
+ +
+
+populate(cluster, hosts)
+

This method is called to initialize the load balancing +policy with a set of Host instances before its +first use. The cluster parameter is an instance of +Cluster.

+
+ +
+
+make_query_plan(working_keyspace=None, query=None)
+

Given a Statement instance, return a iterable +of Host instances which should be queried in that +order. A generator may work well for custom implementations +of this method.

+

Note that the query argument may be None when preparing +statements.

+

working_keyspace should be the string name of the current keyspace, +as set through Session.set_keyspace() or with a USE +statement.

+
+ +
+
+check_supported()
+

This will be called after the cluster Metadata has been initialized. +If the load balancing policy implementation cannot be supported for +some reason (such as a missing C extension), this is the point at +which it should raise an exception.

+
+ +
+ +
+
+class cassandra.policies.RoundRobinPolicy
+

A subclass of LoadBalancingPolicy which evenly +distributes queries across all nodes in the cluster, +regardless of what datacenter the nodes may be in.

+
+
+populate(cluster, hosts)
+

This method is called to initialize the load balancing +policy with a set of Host instances before its +first use. The cluster parameter is an instance of +Cluster.

+
+ +
+
+distance(host)
+

Returns a measure of how remote a Host is in +terms of the HostDistance enums.

+
+ +
+
+make_query_plan(working_keyspace=None, query=None)
+

Given a Statement instance, return a iterable +of Host instances which should be queried in that +order. A generator may work well for custom implementations +of this method.

+

Note that the query argument may be None when preparing +statements.

+

working_keyspace should be the string name of the current keyspace, +as set through Session.set_keyspace() or with a USE +statement.

+
+ +
+
+on_up(host)
+

Called when a node is marked up.

+
+ +
+
+on_down(host)
+

Called when a node is marked down.

+
+ +
+
+on_add(host)
+

Called when a node is added to the cluster. The newly added node +should be considered up.

+
+ +
+
+on_remove(host)
+

Called when a node is removed from the cluster.

+
+ +
+ +
+
+class cassandra.policies.DCAwareRoundRobinPolicy(local_dc='', used_hosts_per_remote_dc=0)
+

Similar to RoundRobinPolicy, but prefers hosts +in the local datacenter and only uses nodes in remote +datacenters as a last resort.

+

The local_dc parameter should be the name of the datacenter +(such as is reported by nodetool ring) that should +be considered local. If not specified, the driver will choose +a local_dc based on the first host among Cluster.contact_points +having a valid DC. If relying on this mechanism, all specified +contact points should be nodes in a single, local DC.

+

used_hosts_per_remote_dc controls how many nodes in +each remote datacenter will have connections opened +against them. In other words, used_hosts_per_remote_dc hosts +will be considered REMOTE and the +rest will be considered IGNORED. +By default, all remote hosts are ignored.

+
+
+populate(cluster, hosts)
+

This method is called to initialize the load balancing +policy with a set of Host instances before its +first use. The cluster parameter is an instance of +Cluster.

+
+ +
+
+distance(host)
+

Returns a measure of how remote a Host is in +terms of the HostDistance enums.

+
+ +
+
+make_query_plan(working_keyspace=None, query=None)
+

Given a Statement instance, return a iterable +of Host instances which should be queried in that +order. A generator may work well for custom implementations +of this method.

+

Note that the query argument may be None when preparing +statements.

+

working_keyspace should be the string name of the current keyspace, +as set through Session.set_keyspace() or with a USE +statement.

+
+ +
+
+on_up(host)
+

Called when a node is marked up.

+
+ +
+
+on_down(host)
+

Called when a node is marked down.

+
+ +
+
+on_add(host)
+

Called when a node is added to the cluster. The newly added node +should be considered up.

+
+ +
+
+on_remove(host)
+

Called when a node is removed from the cluster.

+
+ +
+ +
+
+class cassandra.policies.WhiteListRoundRobinPolicy(hosts)
+

A subclass of RoundRobinPolicy which evenly +distributes queries across all nodes in the cluster, +regardless of what datacenter the nodes may be in, but +only if that node exists in the list of allowed nodes

+

This policy is addresses the issue described in +https://datastax-oss.atlassian.net/browse/JAVA-145 +Where connection errors occur when connection +attempts are made to private IP addresses remotely

+

The hosts parameter should be a sequence of hosts to permit +connections to.

+
+
+populate(cluster, hosts)
+

This method is called to initialize the load balancing +policy with a set of Host instances before its +first use. The cluster parameter is an instance of +Cluster.

+
+ +
+
+distance(host)
+

Returns a measure of how remote a Host is in +terms of the HostDistance enums.

+
+ +
+
+on_up(host)
+

Called when a node is marked up.

+
+ +
+
+on_add(host)
+

Called when a node is added to the cluster. The newly added node +should be considered up.

+
+ +
+ +
+
+class cassandra.policies.TokenAwarePolicy(child_policy, shuffle_replicas=False)
+

A LoadBalancingPolicy wrapper that adds token awareness to +a child policy.

+

This alters the child policy’s behavior so that it first attempts to +send queries to LOCAL replicas (as determined +by the child policy) based on the Statement’s +routing_key. If shuffle_replicas is +truthy, these replicas will be yielded in a random order. Once those +hosts are exhausted, the remaining hosts in the child policy’s query +plan will be used in the order provided by the child policy.

+

If no routing_key is set on the query, the child +policy’s query plan will be used as is.

+
+
+shuffle_replicas = False
+

Yield local replicas in a random order.

+
+ +
+
+populate(cluster, hosts)
+

This method is called to initialize the load balancing +policy with a set of Host instances before its +first use. The cluster parameter is an instance of +Cluster.

+
+ +
+
+check_supported()
+

This will be called after the cluster Metadata has been initialized. +If the load balancing policy implementation cannot be supported for +some reason (such as a missing C extension), this is the point at +which it should raise an exception.

+
+ +
+
+distance(*args, **kwargs)
+

Returns a measure of how remote a Host is in +terms of the HostDistance enums.

+
+ +
+
+make_query_plan(working_keyspace=None, query=None)
+

Given a Statement instance, return a iterable +of Host instances which should be queried in that +order. A generator may work well for custom implementations +of this method.

+

Note that the query argument may be None when preparing +statements.

+

working_keyspace should be the string name of the current keyspace, +as set through Session.set_keyspace() or with a USE +statement.

+
+ +
+
+on_up(*args, **kwargs)
+

Called when a node is marked up.

+
+ +
+
+on_down(*args, **kwargs)
+

Called when a node is marked down.

+
+ +
+
+on_add(*args, **kwargs)
+

Called when a node is added to the cluster. The newly added node +should be considered up.

+
+ +
+
+on_remove(*args, **kwargs)
+

Called when a node is removed from the cluster.

+
+ +
+ +
+
+class cassandra.policies.HostFilterPolicy(child_policy, predicate)
+

A LoadBalancingPolicy subclass configured with a child policy, +and a single-argument predicate. This policy defers to the child policy for +hosts where predicate(host) is truthy. Hosts for which +predicate(host) is falsey will be considered IGNORED, and will +not be used in a query plan.

+

This can be used in the cases where you need a whitelist or blacklist +policy, e.g. to prepare for decommissioning nodes or for testing:

+
def address_is_ignored(host):
+    return host.address in [ignored_address0, ignored_address1]
+
+blacklist_filter_policy = HostFilterPolicy(
+    child_policy=RoundRobinPolicy(),
+    predicate=address_is_ignored
+)
+
+cluster = Cluster(
+    primary_host,
+    load_balancing_policy=blacklist_filter_policy,
+)
+
+
+

See the note in the make_query_plan() documentation for a caveat on +how wrapping ordering polices (e.g. RoundRobinPolicy) may break +desirable properties of the wrapped policy.

+

Please note that whitelist and blacklist policies are not recommended for +general, day-to-day use. You probably want something like +DCAwareRoundRobinPolicy, which prefers a local DC but has +fallbacks, over a brute-force method like whitelisting or blacklisting.

+
+
Parameters
+
    +
  • child_policy – an instantiated LoadBalancingPolicy +that this one will defer to.

  • +
  • predicate – a one-parameter function that takes a Host. +If it returns a falsey value, the Host will +be IGNORED and not returned in query plans.

  • +
+
+
+
+
+predicate(host)
+

A predicate, set on object initialization, that takes a Host +and returns a value. If the value is falsy, the Host is +IGNORED. If the value is truthy, +HostFilterPolicy defers to the child policy to determine the +host’s distance.

+

This is a read-only value set in __init__, implemented as a +property.

+
+ +
+
+distance(host)
+

Checks if predicate(host), then returns +IGNORED if falsey, and defers to the child policy +otherwise.

+
+ +
+
+make_query_plan(working_keyspace=None, query=None)
+

Defers to the child policy’s +LoadBalancingPolicy.make_query_plan() and filters the results.

+

Note that this filtering may break desirable properties of the wrapped +policy in some cases. For instance, imagine if you configure this +policy to filter out host2, and to wrap a round-robin policy that +rotates through three hosts in the order host1, host2, host3, +host2, host3, host1, host3, host1, host2, repeating. This +policy will yield host1, host3, host3, host1, host3, host1, +disproportionately favoring host3.

+
+ +
+ +
+
+class cassandra.policies.DefaultLoadBalancingPolicy(child_policy)
+

A LoadBalancingPolicy wrapper that adds the ability to target a specific host first.

+

If no host is set on the query, the child policy’s query plan will be used as is.

+
+
+populate(cluster, hosts)
+

This method is called to initialize the load balancing +policy with a set of Host instances before its +first use. The cluster parameter is an instance of +Cluster.

+
+ +
+
+make_query_plan(working_keyspace=None, query=None)
+

Given a Statement instance, return a iterable +of Host instances which should be queried in that +order. A generator may work well for custom implementations +of this method.

+

Note that the query argument may be None when preparing +statements.

+

working_keyspace should be the string name of the current keyspace, +as set through Session.set_keyspace() or with a USE +statement.

+
+ +
+ +
+
+class cassandra.policies.DSELoadBalancingPolicy(*args, **kwargs)
+

Deprecated: This will be removed in the next major release, +consider using DefaultLoadBalancingPolicy.

+
+ +
+
+

Translating Server Node Addresses

+
+
+class cassandra.policies.AddressTranslator
+

Interface for translating cluster-defined endpoints.

+

The driver discovers nodes using server metadata and topology change events. Normally, +the endpoint defined by the server is the right way to connect to a node. In some environments, +these addresses may not be reachable, or not preferred (public vs. private IPs in cloud environments, +suboptimal routing, etc). This interface allows for translating from server defined endpoints to +preferred addresses for driver connections.

+

Note: contact_points provided while creating the Cluster instance are not +translated using this mechanism – only addresses received from Cassandra nodes are.

+
+
+translate(addr)
+

Accepts the node ip address, and returns a translated address to be used connecting to this node.

+
+ +
+ +
+
+class cassandra.policies.IdentityTranslator
+

Returns the endpoint with no translation

+
+
+translate(addr)
+

Accepts the node ip address, and returns a translated address to be used connecting to this node.

+
+ +
+ +
+
+class cassandra.policies.EC2MultiRegionTranslator
+

Resolves private ips of the hosts in the same datacenter as the client, and public ips of hosts in other datacenters.

+
+
+translate(addr)
+

Reverse DNS the public broadcast_address, then lookup that hostname to get the AWS-resolved IP, which +will point to the private IP address within the same datacenter.

+
+ +
+ +
+
+

Marking Hosts Up or Down

+
+
+class cassandra.policies.ConvictionPolicy(host)
+

A policy which decides when hosts should be considered down +based on the types of failures and the number of failures.

+

If custom behavior is needed, this class may be subclassed.

+

host is an instance of Host.

+
+
+add_failure(connection_exc)
+

Implementations should return True if the host should be +convicted, False otherwise.

+
+ +
+
+reset()
+

Implementations should clear out any convictions or state regarding +the host.

+
+ +
+ +
+
+class cassandra.policies.SimpleConvictionPolicy(host)
+

The default implementation of ConvictionPolicy, +which simply marks a host as down after the first failure +of any kind.

+

host is an instance of Host.

+
+
+add_failure(connection_exc)
+

Implementations should return True if the host should be +convicted, False otherwise.

+
+ +
+
+reset()
+

Implementations should clear out any convictions or state regarding +the host.

+
+ +
+ +
+
+

Reconnecting to Dead Hosts

+
+
+class cassandra.policies.ReconnectionPolicy
+

This class and its subclasses govern how frequently an attempt is made +to reconnect to nodes that are marked as dead.

+

If custom behavior is needed, this class may be subclassed.

+
+
+new_schedule()
+

This should return a finite or infinite iterable of delays (each as a +floating point number of seconds) inbetween each failed reconnection +attempt. Note that if the iterable is finite, reconnection attempts +will cease once the iterable is exhausted.

+
+ +
+ +
+
+class cassandra.policies.ConstantReconnectionPolicy(delay, max_attempts=64)
+

A ReconnectionPolicy subclass which sleeps for a fixed delay +inbetween each reconnection attempt.

+

delay should be a floating point number of seconds to wait inbetween +each attempt.

+

max_attempts should be a total number of attempts to be made before +giving up, or None to continue reconnection attempts forever. +The default is 64.

+
+
+new_schedule()
+

This should return a finite or infinite iterable of delays (each as a +floating point number of seconds) inbetween each failed reconnection +attempt. Note that if the iterable is finite, reconnection attempts +will cease once the iterable is exhausted.

+
+ +
+ +
+
+class cassandra.policies.ExponentialReconnectionPolicy(base_delay, max_delay, max_attempts=64)
+

A ReconnectionPolicy subclass which exponentially increases +the length of the delay inbetween each reconnection attempt up to +a set maximum delay.

+

A random amount of jitter (+/- 15%) will be added to the pure exponential +delay value to avoid the situations where many reconnection handlers are +trying to reconnect at exactly the same time.

+

base_delay and max_delay should be in floating point units of +seconds.

+

max_attempts should be a total number of attempts to be made before +giving up, or None to continue reconnection attempts forever. +The default is 64.

+
+
+new_schedule()
+

This should return a finite or infinite iterable of delays (each as a +floating point number of seconds) inbetween each failed reconnection +attempt. Note that if the iterable is finite, reconnection attempts +will cease once the iterable is exhausted.

+
+ +
+ +
+
+

Retrying Failed Operations

+
+
+class cassandra.policies.WriteType
+

For usage with RetryPolicy, this describe a type +of write operation.

+
+
+SIMPLE = 0
+

A write to a single partition key. Such writes are guaranteed to be atomic +and isolated.

+
+ +
+
+BATCH = 1
+

A write to multiple partition keys that used the distributed batch log to +ensure atomicity.

+
+ +
+
+UNLOGGED_BATCH = 2
+

A write to multiple partition keys that did not use the distributed batch +log. Atomicity for such writes is not guaranteed.

+
+ +
+
+COUNTER = 3
+

A counter write (for one or multiple partition keys). Such writes should +not be replayed in order to avoid overcount.

+
+ +
+
+BATCH_LOG = 4
+

The initial write to the distributed batch log that Cassandra performs +internally before a BATCH write.

+
+ +
+
+CAS = 5
+

A lighweight-transaction write, such as “DELETE … IF EXISTS”.

+
+ +
+
+VIEW = 6
+

This WriteType is only seen in results for requests that were unable to +complete MV operations.

+
+ +
+
+CDC = 7
+

This WriteType is only seen in results for requests that were unable to +complete CDC operations.

+
+ +
+ +
+
+class cassandra.policies.RetryPolicy
+

A policy that describes whether to retry, rethrow, or ignore coordinator +timeout and unavailable failures. These are failures reported from the +server side. Timeouts are configured by +settings in cassandra.yaml. +Unavailable failures occur when the coordinator cannot acheive the consistency +level for a request. For further information see the method descriptions +below.

+

To specify a default retry policy, set the +Cluster.default_retry_policy attribute to an instance of this +class or one of its subclasses.

+

To specify a retry policy per query, set the Statement.retry_policy +attribute to an instance of this class or one of its subclasses.

+

If custom behavior is needed for retrying certain operations, +this class may be subclassed.

+
+
+RETRY = 0
+

This should be returned from the below methods if the operation +should be retried on the same connection.

+
+ +
+
+RETHROW = 1
+

This should be returned from the below methods if the failure +should be propagated and no more retries attempted.

+
+ +
+
+IGNORE = 2
+

This should be returned from the below methods if the failure +should be ignored but no more retries should be attempted.

+
+ +
+
+RETRY_NEXT_HOST = 3
+

This should be returned from the below methods if the operation +should be retried on another connection.

+
+ +
+
+on_read_timeout(query, consistency, required_responses, received_responses, data_retrieved, retry_num)
+

This is called when a read operation times out from the coordinator’s +perspective (i.e. a replica did not respond to the coordinator in time). +It should return a tuple with two items: one of the class enums (such +as RETRY) and a ConsistencyLevel to retry the +operation at or None to keep the same consistency level.

+

query is the Statement that timed out.

+

consistency is the ConsistencyLevel that the operation was +attempted at.

+

The required_responses and received_responses parameters describe +how many replicas needed to respond to meet the requested consistency +level and how many actually did respond before the coordinator timed +out the request. data_retrieved is a boolean indicating whether +any of those responses contained data (as opposed to just a digest).

+

retry_num counts how many times the operation has been retried, so +the first time this method is called, retry_num will be 0.

+

By default, operations will be retried at most once, and only if +a sufficient number of replicas responded (with data digests).

+
+ +
+
+on_write_timeout(query, consistency, write_type, required_responses, received_responses, retry_num)
+

This is called when a write operation times out from the coordinator’s +perspective (i.e. a replica did not respond to the coordinator in time).

+

query is the Statement that timed out.

+

consistency is the ConsistencyLevel that the operation was +attempted at.

+

write_type is one of the WriteType enums describing the +type of write operation.

+

The required_responses and received_responses parameters describe +how many replicas needed to acknowledge the write to meet the requested +consistency level and how many replicas actually did acknowledge the +write before the coordinator timed out the request.

+

retry_num counts how many times the operation has been retried, so +the first time this method is called, retry_num will be 0.

+

By default, failed write operations will retried at most once, and +they will only be retried if the write_type was +BATCH_LOG.

+
+ +
+
+on_unavailable(query, consistency, required_replicas, alive_replicas, retry_num)
+

This is called when the coordinator node determines that a read or +write operation cannot be successful because the number of live +replicas are too low to meet the requested ConsistencyLevel. +This means that the read or write operation was never forwarded to +any replicas.

+

query is the Statement that failed.

+

consistency is the ConsistencyLevel that the operation was +attempted at.

+

required_replicas is the number of replicas that would have needed to +acknowledge the operation to meet the requested consistency level. +alive_replicas is the number of replicas that the coordinator +considered alive at the time of the request.

+

retry_num counts how many times the operation has been retried, so +the first time this method is called, retry_num will be 0.

+

By default, if this is the first retry, it triggers a retry on the next +host in the query plan with the same consistency level. If this is not the +first retry, no retries will be attempted and the error will be re-raised.

+
+ +
+
+on_request_error(query, consistency, error, retry_num)
+

This is called when an unexpected error happens. This can be in the +following situations:

+
    +
  • On a connection error

  • +
  • On server errors: overloaded, isBootstrapping, serverError, etc.

  • +
+

query is the Statement that timed out.

+

consistency is the ConsistencyLevel that the operation was +attempted at.

+

error the instance of the exception.

+

retry_num counts how many times the operation has been retried, so +the first time this method is called, retry_num will be 0.

+

The default, it triggers a retry on the next host in the query plan +with the same consistency level.

+
+ +
+ +
+
+class cassandra.policies.FallthroughRetryPolicy
+

A retry policy that never retries and always propagates failures to +the application.

+
+
+on_read_timeout(*args, **kwargs)
+

This is called when a read operation times out from the coordinator’s +perspective (i.e. a replica did not respond to the coordinator in time). +It should return a tuple with two items: one of the class enums (such +as RETRY) and a ConsistencyLevel to retry the +operation at or None to keep the same consistency level.

+

query is the Statement that timed out.

+

consistency is the ConsistencyLevel that the operation was +attempted at.

+

The required_responses and received_responses parameters describe +how many replicas needed to respond to meet the requested consistency +level and how many actually did respond before the coordinator timed +out the request. data_retrieved is a boolean indicating whether +any of those responses contained data (as opposed to just a digest).

+

retry_num counts how many times the operation has been retried, so +the first time this method is called, retry_num will be 0.

+

By default, operations will be retried at most once, and only if +a sufficient number of replicas responded (with data digests).

+
+ +
+
+on_write_timeout(*args, **kwargs)
+

This is called when a write operation times out from the coordinator’s +perspective (i.e. a replica did not respond to the coordinator in time).

+

query is the Statement that timed out.

+

consistency is the ConsistencyLevel that the operation was +attempted at.

+

write_type is one of the WriteType enums describing the +type of write operation.

+

The required_responses and received_responses parameters describe +how many replicas needed to acknowledge the write to meet the requested +consistency level and how many replicas actually did acknowledge the +write before the coordinator timed out the request.

+

retry_num counts how many times the operation has been retried, so +the first time this method is called, retry_num will be 0.

+

By default, failed write operations will retried at most once, and +they will only be retried if the write_type was +BATCH_LOG.

+
+ +
+
+on_unavailable(*args, **kwargs)
+

This is called when the coordinator node determines that a read or +write operation cannot be successful because the number of live +replicas are too low to meet the requested ConsistencyLevel. +This means that the read or write operation was never forwarded to +any replicas.

+

query is the Statement that failed.

+

consistency is the ConsistencyLevel that the operation was +attempted at.

+

required_replicas is the number of replicas that would have needed to +acknowledge the operation to meet the requested consistency level. +alive_replicas is the number of replicas that the coordinator +considered alive at the time of the request.

+

retry_num counts how many times the operation has been retried, so +the first time this method is called, retry_num will be 0.

+

By default, if this is the first retry, it triggers a retry on the next +host in the query plan with the same consistency level. If this is not the +first retry, no retries will be attempted and the error will be re-raised.

+
+ +
+
+on_request_error(*args, **kwargs)
+

This is called when an unexpected error happens. This can be in the +following situations:

+
    +
  • On a connection error

  • +
  • On server errors: overloaded, isBootstrapping, serverError, etc.

  • +
+

query is the Statement that timed out.

+

consistency is the ConsistencyLevel that the operation was +attempted at.

+

error the instance of the exception.

+

retry_num counts how many times the operation has been retried, so +the first time this method is called, retry_num will be 0.

+

The default, it triggers a retry on the next host in the query plan +with the same consistency level.

+
+ +
+ +
+
+class cassandra.policies.DowngradingConsistencyRetryPolicy(*args, **kwargs)
+

Deprecated: This retry policy will be removed in the next major release.

+

A retry policy that sometimes retries with a lower consistency level than +the one initially requested.

+

BEWARE: This policy may retry queries using a lower consistency +level than the one initially requested. By doing so, it may break +consistency guarantees. In other words, if you use this retry policy, +there are cases (documented below) where a read at QUORUM +may not see a preceding write at QUORUM. Do not use this +policy unless you have understood the cases where this can happen and +are ok with that. It is also recommended to subclass this class so +that queries that required a consistency level downgrade can be +recorded (so that repairs can be made later, etc).

+

This policy implements the same retries as RetryPolicy, +but on top of that, it also retries in the following cases:

+
    +
  • On a read timeout: if the number of replicas that responded is +greater than one but lower than is required by the requested +consistency level, the operation is retried at a lower consistency +level.

  • +
  • On a write timeout: if the operation is an UNLOGGED_BATCH +and at least one replica acknowledged the write, the operation is +retried at a lower consistency level. Furthermore, for other +write types, if at least one replica acknowledged the write, the +timeout is ignored.

  • +
  • On an unavailable exception: if at least one replica is alive, the +operation is retried at a lower consistency level.

  • +
+

The reasoning behind this retry policy is as follows: if, based +on the information the Cassandra coordinator node returns, retrying the +operation with the initially requested consistency has a chance to +succeed, do it. Otherwise, if based on that information we know the +initially requested consistency level cannot be achieved currently, then:

+
    +
  • For writes, ignore the exception (thus silently failing the +consistency requirement) if we know the write has been persisted on at +least one replica.

  • +
  • For reads, try reading at a lower consistency level (thus silently +failing the consistency requirement).

  • +
+

In other words, this policy implements the idea that if the requested +consistency level cannot be achieved, the next best thing for writes is +to make sure the data is persisted, and that reading something is better +than reading nothing, even if there is a risk of reading stale data.

+
+
+on_read_timeout(query, consistency, required_responses, received_responses, data_retrieved, retry_num)
+

This is called when a read operation times out from the coordinator’s +perspective (i.e. a replica did not respond to the coordinator in time). +It should return a tuple with two items: one of the class enums (such +as RETRY) and a ConsistencyLevel to retry the +operation at or None to keep the same consistency level.

+

query is the Statement that timed out.

+

consistency is the ConsistencyLevel that the operation was +attempted at.

+

The required_responses and received_responses parameters describe +how many replicas needed to respond to meet the requested consistency +level and how many actually did respond before the coordinator timed +out the request. data_retrieved is a boolean indicating whether +any of those responses contained data (as opposed to just a digest).

+

retry_num counts how many times the operation has been retried, so +the first time this method is called, retry_num will be 0.

+

By default, operations will be retried at most once, and only if +a sufficient number of replicas responded (with data digests).

+
+ +
+
+on_write_timeout(query, consistency, write_type, required_responses, received_responses, retry_num)
+

This is called when a write operation times out from the coordinator’s +perspective (i.e. a replica did not respond to the coordinator in time).

+

query is the Statement that timed out.

+

consistency is the ConsistencyLevel that the operation was +attempted at.

+

write_type is one of the WriteType enums describing the +type of write operation.

+

The required_responses and received_responses parameters describe +how many replicas needed to acknowledge the write to meet the requested +consistency level and how many replicas actually did acknowledge the +write before the coordinator timed out the request.

+

retry_num counts how many times the operation has been retried, so +the first time this method is called, retry_num will be 0.

+

By default, failed write operations will retried at most once, and +they will only be retried if the write_type was +BATCH_LOG.

+
+ +
+
+on_unavailable(query, consistency, required_replicas, alive_replicas, retry_num)
+

This is called when the coordinator node determines that a read or +write operation cannot be successful because the number of live +replicas are too low to meet the requested ConsistencyLevel. +This means that the read or write operation was never forwarded to +any replicas.

+

query is the Statement that failed.

+

consistency is the ConsistencyLevel that the operation was +attempted at.

+

required_replicas is the number of replicas that would have needed to +acknowledge the operation to meet the requested consistency level. +alive_replicas is the number of replicas that the coordinator +considered alive at the time of the request.

+

retry_num counts how many times the operation has been retried, so +the first time this method is called, retry_num will be 0.

+

By default, if this is the first retry, it triggers a retry on the next +host in the query plan with the same consistency level. If this is not the +first retry, no retries will be attempted and the error will be re-raised.

+
+ +
+ +
+
+

Retrying Idempotent Operations

+
+
+class cassandra.policies.SpeculativeExecutionPolicy
+

Interface for specifying speculative execution plans

+
+
+new_plan(keyspace, statement)
+

Returns

+
+
Parameters
+
    +
  • keyspace

  • +
  • statement

  • +
+
+
Returns
+

+
+
+
+ +
+ +
+
+class cassandra.policies.ConstantSpeculativeExecutionPolicy(delay, max_attempts)
+

A speculative execution policy that sends a new query every X seconds (delay) for a maximum of Y attempts (max_attempts).

+
+
+new_plan(keyspace, statement)
+

Returns

+
+
Parameters
+
    +
  • keyspace

  • +
  • statement

  • +
+
+
Returns
+

+
+
+
+ +
+ +
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.26.2-scylla/api/cassandra/pool.html b/3.26.2-scylla/api/cassandra/pool.html new file mode 100644 index 0000000000..d856e490c1 --- /dev/null +++ b/3.26.2-scylla/api/cassandra/pool.html @@ -0,0 +1,664 @@ + + + + + + + + + + + + + cassandra.pool - Hosts and Connection Pools | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + + + +
+ +
+ +
+

cassandra.pool - Hosts and Connection Pools

+

Connection pooling and host management.

+
+
+class cassandra.pool.Host
+

Represents a single Cassandra node.

+
+
+property address
+

The IP address of the endpoint. This is the RPC address the driver uses when connecting to the node.

+
+ +
+
+property datacenter
+

The datacenter the node is in.

+
+ +
+
+property rack
+

The rack the node is in.

+
+ +
+ +
+
+exception cassandra.pool.NoConnectionsAvailable
+

All existing connections to a given host are busy, or there are +no open connections.

+
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.26.2-scylla/api/cassandra/protocol.html b/3.26.2-scylla/api/cassandra/protocol.html new file mode 100644 index 0000000000..d97b6275df --- /dev/null +++ b/3.26.2-scylla/api/cassandra/protocol.html @@ -0,0 +1,730 @@ + + + + + + + + + + + + + cassandra.protocol - Protocol Features | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + + + +
+ +
+ +
+

cassandra.protocol - Protocol Features

+
+

Custom Payloads

+

Native protocol version 4+ allows for a custom payload to be sent between clients +and custom query handlers. The payload is specified as a string:binary_type dict +holding custom key/value pairs.

+

By default these are ignored by the server. They can be useful for servers implementing +a custom QueryHandler.

+

See Session.execute(), :Session.execute_async(), ResponseFuture.custom_payload.

+
+
+class cassandra.protocol._ProtocolHandler
+

_ProtocolHander handles encoding and decoding messages.

+

This class can be specialized to compose Handlers which implement alternative +result decoding or type deserialization. Class definitions are passed to cassandra.cluster.Cluster +on initialization.

+

Contracted class methods are _ProtocolHandler.encode_message() and _ProtocolHandler.decode_message().

+
+
+message_types_by_opcode = {default mapping}
+
+ +
+
+classmethod encode_message(msg, stream_id, protocol_version, compressor, allow_beta_protocol_version)
+

Encodes a message using the specified frame parameters, and compressor

+
+
Parameters
+
    +
  • msg – the message, typically of cassandra.protocol._MessageType, generated by the driver

  • +
  • stream_id – protocol stream id for the frame header

  • +
  • protocol_version – version for the frame header, and used encoding contents

  • +
  • compressor – optional compression function to be used on the body

  • +
+
+
+
+ +
+
+classmethod decode_message(protocol_version, user_type_map, stream_id, flags, opcode, body, decompressor, result_metadata)
+

Decodes a native protocol message body

+
+
Parameters
+
    +
  • protocol_version – version to use decoding contents

  • +
  • user_type_map – map[keyspace name] = map[type name] = custom type to instantiate when deserializing this type

  • +
  • stream_id – native protocol stream id from the frame header

  • +
  • flags – native protocol flags bitmap from the header

  • +
  • opcode – native protocol opcode from the header

  • +
  • body – frame body

  • +
  • decompressor – optional decompression function to inflate the body

  • +
+
+
Returns
+

a message decoded from the body and frame attributes

+
+
+
+ +
+ +
+
+

Faster Deserialization

+

When python-driver is compiled with Cython, it uses a Cython-based deserialization path +to deserialize messages. By default, the driver will use a Cython-based parser that returns +lists of rows similar to the pure-Python version. In addition, there are two additional +ProtocolHandler classes that can be used to deserialize response messages: LazyProtocolHandler +and NumpyProtocolHandler. They can be used as follows:

+
from cassandra.protocol import NumpyProtocolHandler, LazyProtocolHandler
+from cassandra.query import tuple_factory
+s.client_protocol_handler = LazyProtocolHandler   # for a result iterator
+s.row_factory = tuple_factory  #required for Numpy results
+s.client_protocol_handler = NumpyProtocolHandler  # for a dict of NumPy arrays as result
+
+
+

These protocol handlers comprise different parsers, and return results as described below:

+
    +
  • ProtocolHandler: this default implementation is a drop-in replacement for the pure-Python version. +The rows are all parsed upfront, before results are returned.

  • +
  • LazyProtocolHandler: near drop-in replacement for the above, except that it returns an iterator over rows, +lazily decoded into the default row format (this is more efficient since all decoded results are not materialized at once)

  • +
  • NumpyProtocolHander: deserializes results directly into NumPy arrays. This facilitates efficient integration with +analysis toolkits such as Pandas.

  • +
+
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.26.2-scylla/api/cassandra/query.html b/3.26.2-scylla/api/cassandra/query.html new file mode 100644 index 0000000000..729a6d57c6 --- /dev/null +++ b/3.26.2-scylla/api/cassandra/query.html @@ -0,0 +1,993 @@ + + + + + + + + + + + + + cassandra.query - Prepared Statements, Batch Statements, Tracing, and Row Factories | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + + + +
+ +
+ +
+

cassandra.query - Prepared Statements, Batch Statements, Tracing, and Row Factories

+
+
+cassandra.query.tuple_factory(colnames, rows)
+

Returns each row as a tuple

+

Example:

+
>>> from cassandra.query import tuple_factory
+>>> session = cluster.connect('mykeyspace')
+>>> session.row_factory = tuple_factory
+>>> rows = session.execute("SELECT name, age FROM users LIMIT 1")
+>>> print rows[0]
+('Bob', 42)
+
+
+
+

Changed in version 2.0.0: moved from cassandra.decoder to cassandra.query

+
+
+ +
+
+cassandra.query.named_tuple_factory(colnames, rows)
+

Returns each row as a namedtuple. +This is the default row factory.

+

Example:

+
>>> from cassandra.query import named_tuple_factory
+>>> session = cluster.connect('mykeyspace')
+>>> session.row_factory = named_tuple_factory
+>>> rows = session.execute("SELECT name, age FROM users LIMIT 1")
+>>> user = rows[0]
+
+>>> # you can access field by their name:
+>>> print "name: %s, age: %d" % (user.name, user.age)
+name: Bob, age: 42
+
+>>> # or you can access fields by their position (like a tuple)
+>>> name, age = user
+>>> print "name: %s, age: %d" % (name, age)
+name: Bob, age: 42
+>>> name = user[0]
+>>> age = user[1]
+>>> print "name: %s, age: %d" % (name, age)
+name: Bob, age: 42
+
+
+
+

Changed in version 2.0.0: moved from cassandra.decoder to cassandra.query

+
+
+ +
+
+cassandra.query.dict_factory(colnames, rows)
+

Returns each row as a dict.

+

Example:

+
>>> from cassandra.query import dict_factory
+>>> session = cluster.connect('mykeyspace')
+>>> session.row_factory = dict_factory
+>>> rows = session.execute("SELECT name, age FROM users LIMIT 1")
+>>> print rows[0]
+{u'age': 42, u'name': u'Bob'}
+
+
+
+

Changed in version 2.0.0: moved from cassandra.decoder to cassandra.query

+
+
+ +
+
+cassandra.query.ordered_dict_factory(colnames, rows)
+

Like dict_factory(), but returns each row as an OrderedDict, +so the order of the columns is preserved.

+
+

Changed in version 2.0.0: moved from cassandra.decoder to cassandra.query

+
+
+ +
+
+class cassandra.query.SimpleStatement(query_string, retry_policy=None, consistency_level=None, routing_key=None, serial_consistency_level=None, fetch_size=<object object>, keyspace=None, custom_payload=None, is_idempotent=False)
+

A simple, un-prepared query.

+

query_string should be a literal CQL statement with the exception +of parameter placeholders that will be filled through the +parameters argument of Session.execute().

+

See Statement attributes for a description of the other parameters.

+
+ +
+
+class cassandra.query.PreparedStatement
+

A statement that has been prepared against at least one Cassandra node. +Instances of this class should not be created directly, but through +Session.prepare().

+

A PreparedStatement should be prepared only once. Re-preparing a statement +may affect performance (as the operation requires a network roundtrip).

+

A note about * in prepared statements: Do not use * in prepared statements if you might +change the schema of the table being queried. The driver and server each +maintain a map between metadata for a schema and statements that were +prepared against that schema. When a user changes a schema, e.g. by adding +or removing a column, the server invalidates its mappings involving that +schema. However, there is currently no way to propagate that invalidation +to drivers. Thus, after a schema change, the driver will incorrectly +interpret the results of SELECT * queries prepared before the schema +change. This is currently being addressed in CASSANDRA-10786.

+
+
+bind(values)
+

Creates and returns a BoundStatement instance using values.

+

See BoundStatement.bind() for rules on input values.

+
+ +
+ +
+
+class cassandra.query.BoundStatement(prepared_statement, retry_policy=None, consistency_level=None, routing_key=None, serial_consistency_level=None, fetch_size=<object object>, keyspace=None, custom_payload=None)
+

A prepared statement that has been bound to a particular set of values. +These may be created directly or through PreparedStatement.bind().

+

prepared_statement should be an instance of PreparedStatement.

+

See Statement attributes for a description of the other parameters.

+
+
+bind(values)
+

Binds a sequence of values for the prepared statement parameters +and returns this instance. Note that values must be:

+
    +
  • a sequence, even if you are only binding one value, or

  • +
  • a dict that relates 1-to-1 between dict keys and columns

  • +
+
+

Changed in version 2.6.0: UNSET_VALUE was introduced. These can be bound as positional parameters +in a sequence, or by name in a dict. Additionally, when using protocol v4+:

+
    +
  • short sequences will be extended to match bind parameters with UNSET_VALUE

  • +
  • names may be omitted from a dict with UNSET_VALUE implied.

  • +
+
+
+

Changed in version 3.0.0: method will not throw if extra keys are present in bound dict (PYTHON-178)

+
+
+ +
+
+property routing_key
+

The partition_key portion of the primary key, +which can be used to determine which nodes are replicas for the query.

+

If the partition key is a composite, a list or tuple must be passed in. +Each key component should be in its packed (binary) format, so all +components should be strings.

+
+ +
+ +
+
+class cassandra.query.Statement
+

An abstract class representing a single query. There are three subclasses: +SimpleStatement, BoundStatement, and BatchStatement. +These can be passed to Session.execute().

+
+
+property routing_key
+

The partition_key portion of the primary key, +which can be used to determine which nodes are replicas for the query.

+

If the partition key is a composite, a list or tuple must be passed in. +Each key component should be in its packed (binary) format, so all +components should be strings.

+
+ +
+
+property serial_consistency_level
+

The serial consistency level is only used by conditional updates +(INSERT, UPDATE and DELETE with an IF condition). For +those, the serial_consistency_level defines the consistency level of +the serial phase (or “paxos” phase) while the normal +consistency_level defines the consistency for the “learn” phase, +i.e. what type of reads will be guaranteed to see the update right away. +For example, if a conditional write has a consistency_level of +QUORUM (and is successful), then a +QUORUM read is guaranteed to see that write. +But if the regular consistency_level of that write is +ANY, then only a read with a +consistency_level of SERIAL is +guaranteed to see it (even a read with consistency +ALL is not guaranteed to be enough).

+

The serial consistency can only be one of SERIAL +or LOCAL_SERIAL. While SERIAL guarantees full +linearizability (with other SERIAL updates), LOCAL_SERIAL only +guarantees it in the local data center.

+

The serial consistency level is ignored for any query that is not a +conditional update. Serial reads should use the regular +consistency_level.

+

Serial consistency levels may only be used against Cassandra 2.0+ +and the protocol_version must be set to 2 or higher.

+

See Lightweight Transactions (Compare-and-set) for a discussion on how to work with results returned from +conditional statements.

+
+

New in version 2.0.0.

+
+
+ +
+ +
+
+cassandra.query.UNSET_VALUE
+

The most base type

+
+ +
+
+class cassandra.query.BatchStatement(batch_type=BatchType.LOGGED, retry_policy=None, consistency_level=None)
+

A protocol-level batch of operations which are applied atomically +by default.

+
+

New in version 2.0.0.

+
+

batch_type specifies The BatchType for the batch operation. +Defaults to BatchType.LOGGED.

+

retry_policy should be a RetryPolicy instance for +controlling retries on the operation.

+

consistency_level should be a ConsistencyLevel value +to be used for all operations in the batch.

+

custom_payload is a Custom Payloads passed to the server. +Note: as Statement objects are added to the batch, this map is +updated with any values found in their custom payloads. These are +only allowed when using protocol version 4 or higher.

+

Example usage:

+
insert_user = session.prepare("INSERT INTO users (name, age) VALUES (?, ?)")
+batch = BatchStatement(consistency_level=ConsistencyLevel.QUORUM)
+
+for (name, age) in users_to_insert:
+    batch.add(insert_user, (name, age))
+
+session.execute(batch)
+
+
+

You can also mix different types of operations within a batch:

+
batch = BatchStatement()
+batch.add(SimpleStatement("INSERT INTO users (name, age) VALUES (%s, %s)"), (name, age))
+batch.add(SimpleStatement("DELETE FROM pending_users WHERE name=%s"), (name,))
+session.execute(batch)
+
+
+
+

New in version 2.0.0.

+
+
+

Changed in version 2.1.0: Added serial_consistency_level as a parameter

+
+
+

Changed in version 2.6.0: Added custom_payload as a parameter

+
+
+
+add(statement, parameters=None)
+

Adds a Statement and optional sequence of parameters +to be used with the statement to the batch.

+

Like with other statements, parameters must be a sequence, even +if there is only one item.

+
+ +
+
+add_all(statements, parameters)
+

Adds a sequence of Statement objects and a matching sequence +of parameters to the batch. Statement and parameter sequences must be of equal length or +one will be truncated. None can be used in the parameters position where are needed.

+
+ +
+
+clear()
+

This is a convenience method to clear a batch statement for reuse.

+

Note: it should not be used concurrently with uncompleted execution futures executing the same +BatchStatement.

+
+ +
+
+serial_consistency_level = None
+
+ +
+ +
+
+class cassandra.query.BatchType
+

A BatchType is used with BatchStatement instances to control +the atomicity of the batch operation.

+
+

New in version 2.0.0.

+
+
+
+LOGGED = BatchType.LOGGED
+
+ +
+
+UNLOGGED = BatchType.UNLOGGED
+
+ +
+
+COUNTER = BatchType.COUNTER
+
+ +
+ +
+
+class cassandra.query.ValueSequence(iterable=(), /)
+

A wrapper class that is used to specify that a sequence of values should +be treated as a CQL list of values instead of a single column collection when used +as part of the parameters argument for Session.execute().

+

This is typically needed when supplying a list of keys to select. +For example:

+
>>> my_user_ids = ('alice', 'bob', 'charles')
+>>> query = "SELECT * FROM users WHERE user_id IN %s"
+>>> session.execute(query, parameters=[ValueSequence(my_user_ids)])
+
+
+
+ +
+
+class cassandra.query.QueryTrace
+

A trace of the duration and events that occurred when executing +an operation.

+
+
+populate(max_wait=2.0, wait_for_complete=True, query_cl=None)
+

Retrieves the actual tracing details from Cassandra and populates the +attributes of this instance. Because tracing details are stored +asynchronously by Cassandra, this may need to retry the session +detail fetch. If the trace is still not available after max_wait +seconds, TraceUnavailable will be raised; if max_wait is +None, this will retry forever.

+

wait_for_complete=False bypasses the wait for duration to be populated. +This can be used to query events from partial sessions.

+

query_cl specifies a consistency level to use for polling the trace tables, +if it should be different than the session default.

+
+ +
+ +
+
+class cassandra.query.TraceEvent
+

Representation of a single event within a query trace.

+
+ +
+
+exception cassandra.query.TraceUnavailable
+

Raised when complete trace details cannot be fetched from Cassandra.

+
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.26.2-scylla/api/cassandra/timestamps.html b/3.26.2-scylla/api/cassandra/timestamps.html new file mode 100644 index 0000000000..7aa904e54e --- /dev/null +++ b/3.26.2-scylla/api/cassandra/timestamps.html @@ -0,0 +1,686 @@ + + + + + + + + + + + + + cassandra.timestamps - Timestamp Generation | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + + + +
+ +
+ +
+

cassandra.timestamps - Timestamp Generation

+
+
+class cassandra.timestamps.MonotonicTimestampGenerator(warn_on_drift=True, warning_threshold=0, warning_interval=0)
+

An object that, when called, returns int(time.time() * 1e6) when +possible, but, if the value returned by time.time doesn’t increase, +drifts into the future and logs warnings. +Exposed configuration attributes can be configured with arguments to +__init__ or by changing attributes on an initialized object.

+
+

New in version 3.8.0.

+
+
+
+warn_on_drift = True
+

If true, log warnings when timestamps drift into the future as allowed by +warning_threshold and warning_interval.

+
+ +
+
+warning_threshold = 1
+

This object will only issue warnings when the returned timestamp drifts +more than warning_threshold seconds into the future. +Defaults to 1 second.

+
+ +
+
+warning_interval = 1
+

This object will only issue warnings every warning_interval seconds. +Defaults to 1 second.

+
+ +
+
+_next_timestamp(now, last)
+

Returns the timestamp that should be used if now is the current +time and last is the last timestamp returned by this object. +Intended for internal and testing use only; to generate timestamps, +call an instantiated MonotonicTimestampGenerator object.

+
+
Parameters
+
    +
  • now (int) – an integer to be used as the current time, typically +representing the current time in microseconds since the UNIX epoch

  • +
  • last (int) – an integer representing the last timestamp returned by +this object

  • +
+
+
+
+ +
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.26.2-scylla/api/cassandra/util.html b/3.26.2-scylla/api/cassandra/util.html new file mode 100644 index 0000000000..b1d76aacf9 --- /dev/null +++ b/3.26.2-scylla/api/cassandra/util.html @@ -0,0 +1,1021 @@ + + + + + + + + + + + + + cassandra.util - Utilities | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + + + +
+ +
+ +
+

cassandra.util - Utilities

+
+
+class cassandra.util.Date(value)
+

Idealized date: year, month, day

+

Offers wider year range than datetime.date. For Dates that cannot be represented +as a datetime.date (because datetime.MINYEAR, datetime.MAXYEAR), this type falls back +to printing days_from_epoch offset.

+

Initializer value can be:

+
    +
  • integer_type: absolute days from epoch (1970, 1, 1). Can be negative.

  • +
  • datetime.date: built-in date

  • +
  • string_type: a string time of the form “yyyy-mm-dd”

  • +
+
+
+date()
+

Return a built-in datetime.date for Dates falling in the years [datetime.MINYEAR, datetime.MAXYEAR]

+

ValueError is raised for Dates outside this range.

+
+ +
+
+property seconds
+

Absolute seconds from epoch (can be negative)

+
+ +
+ +
+
+class cassandra.util.DateRange(lower_bound=None, upper_bound=None, value=None)
+

DSE DateRange Type

+
+
+lower_bound
+

DateRangeBound representing the lower bound of a bounded range.

+
+ +
+
+upper_bound
+

DateRangeBound representing the upper bound of a bounded range.

+
+ +
+
+value
+

DateRangeBound representing the value of a single-value range.

+
+ +

As noted in its documentation, DateRangeBound uses a millisecond +offset from the UNIX epoch to allow DateRange to represent values +datetime.datetime cannot. For such values, string representions will show +this offset rather than the CQL representation.

+
+
Parameters
+
+
+
+
+ +
+
+class cassandra.util.DateRangeBound(value, precision)
+

Represents a single date value and its precision for DateRange.

+
+
+milliseconds
+

Integer representing milliseconds since the UNIX epoch. May be negative.

+
+ +
+
+precision
+

String representing the precision of a bound. Must be a valid +DateRangePrecision member.

+
+ +

DateRangeBound uses a millisecond offset from the UNIX epoch to +allow DateRange to represent values datetime.datetime cannot. +For such values, string representions will show this offset rather than the +CQL representation.

+
+
Parameters
+
    +
  • value – a value representing ms since the epoch. Accepts an +integer or a datetime.

  • +
  • precision – a string representing precision

  • +
+
+
+
+
+datetime()
+

Return milliseconds as a datetime.datetime if possible. +Raises an OverflowError if the value is out of range.

+
+ +
+
+classmethod from_value(value)
+

Construct a new DateRangeBound from a given value. If +possible, use the value[‘milliseconds’] and value[‘precision’] keys +of the argument. Otherwise, use the argument as a (milliseconds, +precision) iterable.

+
+
Parameters
+

value – a dictlike or iterable object

+
+
+
+ +
+ +
+
+class cassandra.util.DateRangePrecision
+

An “enum” representing the valid values for DateRange.precision.

+
+ +
+
+class cassandra.util.Distance(x=nan, y=nan, radius=nan)
+

Represents a Distance geometry for DSE

+
+
+static from_wkt(s)
+

Parse a Distance geometry from a wkt string and return a new Distance object.

+
+ +
+ +
+
+class cassandra.util.Duration(months=0, days=0, nanoseconds=0)
+

Cassandra Duration Type

+
+ +
+
+class cassandra.util.LineString(coords=())
+

Represents a linestring geometry for DSE

+

‘coords`: a sequence of (x, y) coordinates of points in the linestring

+
+
+static from_wkt(s)
+

Parse a LineString geometry from a wkt string and return a new LineString object.

+
+ +
+ +
+
+class cassandra.util.OrderedMap(*args, **kwargs)
+

An ordered map that accepts non-hashable types for keys. It also maintains the +insertion order of items, behaving as OrderedDict in that regard. These maps +are constructed and read just as normal mapping types, except that they may +contain arbitrary collections and other non-hashable items as keys:

+
>>> od = OrderedMap([({'one': 1, 'two': 2}, 'value'),
+...                  ({'three': 3, 'four': 4}, 'value2')])
+>>> list(od.keys())
+[{'two': 2, 'one': 1}, {'three': 3, 'four': 4}]
+>>> list(od.values())
+['value', 'value2']
+
+
+

These constructs are needed to support nested collections in Cassandra 2.1.3+, +where frozen collections can be specified as parameters to others:

+
CREATE TABLE example (
+    ...
+    value map<frozen<map<int, int>>, double>
+    ...
+)
+
+
+

This class derives from the (immutable) Mapping API. Objects in these maps +are not intended be modified.

+
+ +
+
+class cassandra.util.OrderedMapSerializedKey(cass_type, protocol_version)
+
+ +
+
+class cassandra.util.Point(x=nan, y=nan)
+

Represents a point geometry for DSE

+
+
+static from_wkt(s)
+

Parse a Point geometry from a wkt string and return a new Point object.

+
+ +
+ +
+
+class cassandra.util.Polygon(exterior=(), interiors=None)
+

Represents a polygon geometry for DSE

+

‘exterior`: a sequence of (x, y) coordinates of points in the linestring +interiors: None, or a sequence of sequences or (x, y) coordinates of points describing interior linear rings

+
+
+static from_wkt(s)
+

Parse a Polygon geometry from a wkt string and return a new Polygon object.

+
+ +
+ +
+
+class cassandra.util.SortedSet(iterable=())
+

A sorted set based on sorted list

+

A sorted set implementation is used in this case because it does not +require its elements to be immutable/hashable.

+

#Not implemented: update functions, inplace operators

+
+ +
+
+class cassandra.util.Time(value)
+

Idealized time, independent of day.

+

Up to nanosecond resolution

+

Initializer value can be:

+
    +
  • integer_type: absolute nanoseconds in the day

  • +
  • datetime.time: built-in time

  • +
  • string_type: a string time of the form “HH:MM:SS[.mmmuuunnn]”

  • +
+
+
+property hour
+

The hour component of this time (0-23)

+
+ +
+
+property minute
+

The minute component of this time (0-59)

+
+ +
+
+property nanosecond
+

The fractional seconds component of the time, in nanoseconds

+
+ +
+
+property second
+

The second component of this time (0-59)

+
+ +
+
+time()
+

Return a built-in datetime.time (nanosecond precision truncated to micros).

+
+ +
+ +
+
+class cassandra.util.Version(version)
+

Internal minimalist class to compare versions. +A valid version is: <int>.<int>.<int>.<int or str>.

+

TODO: when python2 support is removed, use packaging.version.

+
+ +
+
+cassandra.util.datetime_from_timestamp(timestamp)
+

Creates a timezone-agnostic datetime from timestamp (in seconds) in a consistent manner. +Works around a Windows issue with large negative timestamps (PYTHON-119), +and rounding differences in Python 3.4 (PYTHON-340).

+
+
Parameters
+

timestamp – a unix timestamp, in seconds

+
+
+
+ +
+
+cassandra.util.datetime_from_uuid1(uuid_arg)
+

Creates a timezone-agnostic datetime from the timestamp in the +specified type-1 UUID.

+
+
Parameters
+

uuid_arg – a version 1 UUID

+
+
+
+ +
+
+cassandra.util.max_uuid_from_time(timestamp)
+

Generates the maximum TimeUUID (type 1) for a given timestamp, as compared by Cassandra.

+

See uuid_from_time() for argument and return types.

+
+ +
+
+cassandra.util.min_uuid_from_time(timestamp)
+

Generates the minimum TimeUUID (type 1) for a given timestamp, as compared by Cassandra.

+

See uuid_from_time() for argument and return types.

+
+ +
+
+cassandra.util.ms_timestamp_from_datetime(dt)
+

Converts a datetime to a timestamp expressed in milliseconds.

+
+
Parameters
+

dt – a datetime.datetime

+
+
+
+ +
+
+cassandra.util.sortedset
+

alias of cassandra.util.SortedSet

+
+ +
+
+cassandra.util.unix_time_from_uuid1(uuid_arg)
+

Converts a version 1 uuid.UUID to a timestamp with the same precision +as time.time() returns. This is useful for examining the +results of queries returning a v1 UUID.

+
+
Parameters
+

uuid_arg – a version 1 UUID

+
+
+
+ +
+
+cassandra.util.utc_datetime_from_ms_timestamp(timestamp)
+

Creates a UTC datetime from a timestamp in milliseconds. See +datetime_from_timestamp().

+

Raises an OverflowError if the timestamp is out of range for +datetime.

+
+
Parameters
+

timestamp – timestamp, in milliseconds

+
+
+
+ +
+
+cassandra.util.uuid_from_time(time_arg, node=None, clock_seq=None)
+

Converts a datetime or timestamp to a type 1 uuid.UUID.

+
+
Parameters
+
    +
  • time_arg – The time to use for the timestamp portion of the UUID. +This can either be a datetime object or a timestamp +in seconds (as returned from time.time()).

  • +
  • node (long) – None integer for the UUID (up to 48 bits). If not specified, this +field is randomized.

  • +
  • clock_seq (int) – Clock sequence field for the UUID (up to 14 bits). If not specified, +a random sequence is generated.

  • +
+
+
Return type
+

uuid.UUID

+
+
+
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.26.2-scylla/api/index.html b/3.26.2-scylla/api/index.html new file mode 100644 index 0000000000..f85685a257 --- /dev/null +++ b/3.26.2-scylla/api/index.html @@ -0,0 +1,707 @@ + + + + + + + + + + + + + API Documentation | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + + + +
+ +
+ +
+

API Documentation

+
+

Core Driver

+ +
+
+

Object Mapper

+ +
+
+

DataStax Graph

+ +
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.26.2-scylla/cqlengine/batches.html b/3.26.2-scylla/cqlengine/batches.html new file mode 100644 index 0000000000..4112cbda98 --- /dev/null +++ b/3.26.2-scylla/cqlengine/batches.html @@ -0,0 +1,737 @@ + + + + + + + + + + + + + Batch Queries | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + + + + + +
+

Batch Queries

+

cqlengine supports batch queries using the BatchQuery class. Batch queries can be started and stopped manually, or within a context manager. To add queries to the batch object, you just need to precede the create/save/delete call with a call to batch, and pass in the batch object.

+
+

Batch Query General Use Pattern

+

You can only create, update, and delete rows with a batch query, attempting to read rows out of the database with a batch query will fail.

+
from cassandra.cqlengine.query import BatchQuery
+
+#using a context manager
+with BatchQuery() as b:
+    now = datetime.now()
+    em1 = ExampleModel.batch(b).create(example_type=0, description="1", created_at=now)
+    em2 = ExampleModel.batch(b).create(example_type=0, description="2", created_at=now)
+    em3 = ExampleModel.batch(b).create(example_type=0, description="3", created_at=now)
+
+# -- or --
+
+#manually
+b = BatchQuery()
+now = datetime.now()
+em1 = ExampleModel.batch(b).create(example_type=0, description="1", created_at=now)
+em2 = ExampleModel.batch(b).create(example_type=0, description="2", created_at=now)
+em3 = ExampleModel.batch(b).create(example_type=0, description="3", created_at=now)
+b.execute()
+
+# updating in a batch
+
+b = BatchQuery()
+em1.description = "new description"
+em1.batch(b).save()
+em2.description = "another new description"
+em2.batch(b).save()
+b.execute()
+
+# deleting in a batch
+b = BatchQuery()
+ExampleModel.objects(id=some_id).batch(b).delete()
+ExampleModel.objects(id=some_id2).batch(b).delete()
+b.execute()
+
+
+

Typically you will not want the block to execute if an exception occurs inside the with block. However, in the case that this is desirable, it’s achievable by using the following syntax:

+
with BatchQuery(execute_on_exception=True) as b:
+    LogEntry.batch(b).create(k=1, v=1)
+    mystery_function() # exception thrown in here
+    LogEntry.batch(b).create(k=1, v=2) # this code is never reached due to the exception, but anything leading up to here will execute in the batch.
+
+
+

If an exception is thrown somewhere in the block, any statements that have been added to the batch will still be executed. This is useful for some logging situations.

+
+
+

Batch Query Execution Callbacks

+

In order to allow secondary tasks to be chained to the end of batch, BatchQuery instances allow callbacks to be +registered with the batch, to be executed immediately after the batch executes.

+

Multiple callbacks can be attached to same BatchQuery instance, they are executed in the same order that they +are added to the batch.

+

The callbacks attached to a given batch instance are executed only if the batch executes. If the batch is used as a +context manager and an exception is raised, the queued up callbacks will not be run.

+
def my_callback(*args, **kwargs):
+    pass
+
+batch = BatchQuery()
+
+batch.add_callback(my_callback)
+batch.add_callback(my_callback, 'positional arg', named_arg='named arg value')
+
+# if you need reference to the batch within the callback,
+# just trap it in the arguments to be passed to the callback:
+batch.add_callback(my_callback, cqlengine_batch=batch)
+
+# once the batch executes...
+batch.execute()
+
+# the effect of the above scheduled callbacks will be similar to
+my_callback()
+my_callback('positional arg', named_arg='named arg value')
+my_callback(cqlengine_batch=batch)
+
+
+

Failure in any of the callbacks does not affect the batch’s execution, as the callbacks are started after the execution +of the batch is complete.

+
+

Logged vs Unlogged Batches

+

By default, queries in cqlengine are LOGGED, which carries additional overhead from UNLOGGED. To explicitly state which batch type to use, simply:

+
from cassandra.cqlengine.query import BatchType
+with BatchQuery(batch_type=BatchType.Unlogged) as b:
+    LogEntry.batch(b).create(k=1, v=1)
+    LogEntry.batch(b).create(k=1, v=2)
+
+
+
+
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.26.2-scylla/cqlengine/connections.html b/3.26.2-scylla/cqlengine/connections.html new file mode 100644 index 0000000000..b3c4712d1b --- /dev/null +++ b/3.26.2-scylla/cqlengine/connections.html @@ -0,0 +1,761 @@ + + + + + + + + + + + + + Connections | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + + + + + +
+

Connections

+

Connections aim to ease the use of multiple sessions with cqlengine. Connections can be set on a model class, per query or using a context manager.

+
+

Register a new connection

+

To use cqlengine, you need at least a default connection. If you initialize cqlengine’s connections with with connection.setup, a connection will be created automatically. If you want to use another cluster/session, you need to register a new cqlengine connection. You register a connection with register_connection():

+
from cassandra.cqlengine import connection
+
+connection.setup(['127.0.0.1')
+connection.register_connection('cluster2', ['127.0.0.2'])
+
+
+

register_connection() can take a list of hosts, as shown above, in which case it will create a connection with a new session. It can also take a session argument if you’ve already created a session:

+
from cassandra.cqlengine import connection
+from cassandra.cluster import Cluster
+
+session = Cluster(['127.0.0.1']).connect()
+connection.register_connection('cluster3', session=session)
+
+
+
+
+

Change the default connection

+

You can change the default cqlengine connection on registration:

+
from cassandra.cqlengine import connection
+
+connection.register_connection('cluster2', ['127.0.0.2'] default=True)
+
+
+

or on the fly using set_default_connection()

+
connection.set_default_connection('cluster2')
+
+
+
+
+

Unregister a connection

+

You can unregister a connection using unregister_connection():

+
connection.unregister_connection('cluster2')
+
+
+
+
+

Management

+

When using multiples connections, you also need to sync your models on all connections (and keyspaces) that you need operate on. Management commands have been improved to ease this part. Here is an example:

+
from cassandra.cqlengine import management
+
+keyspaces = ['ks1', 'ks2']
+conns = ['cluster1', 'cluster2']
+
+# registers your connections
+# ...
+
+# create all keyspaces on all connections
+for ks in keyspaces:
+    management.create_simple_keyspace(ks, connections=conns)
+
+# define your Automobile model
+# ...
+
+# sync your models
+management.sync_table(Automobile, keyspaces=keyspaces, connections=conns)
+
+
+
+
+

Connection Selection

+

cqlengine will select the default connection, unless your specify a connection using one of the following methods.

+
+

Default Model Connection

+

You can specify a default connection per model:

+
class Automobile(Model):
+    __keyspace__ = 'test'
+    __connection__ = 'cluster2'
+    manufacturer = columns.Text(primary_key=True)
+    year = columns.Integer(primary_key=True)
+    model = columns.Text(primary_key=True)
+
+print len(Automobile.objects.all())  # executed on the connection 'cluster2'
+
+
+
+
+

QuerySet and model instance

+

You can use the using() method to select a connection (or keyspace):

+
Automobile.objects.using(connection='cluster1').create(manufacturer='honda', year=2010, model='civic')
+q = Automobile.objects.filter(manufacturer='Tesla')
+autos = q.using(keyspace='ks2', connection='cluster2').all()
+
+for auto in autos:
+    auto.using(connection='cluster1').save()
+
+
+
+
+

Context Manager

+

You can use the ContextQuery as well to select a connection:

+
with ContextQuery(Automobile, connection='cluster1') as A:
+    A.objects.filter(manufacturer='honda').all()  # executed on 'cluster1'
+
+
+
+
+

BatchQuery

+

With a BatchQuery, you can select the connection with the context manager. Note that all operations in the batch need to use the same connection.

+
with BatchQuery(connection='cluster1') as b:
+    Automobile.objects.batch(b).create(manufacturer='honda', year=2010, model='civic')
+
+
+
+
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.26.2-scylla/cqlengine/faq.html b/3.26.2-scylla/cqlengine/faq.html new file mode 100644 index 0000000000..0bf71e8186 --- /dev/null +++ b/3.26.2-scylla/cqlengine/faq.html @@ -0,0 +1,701 @@ + + + + + + + + + + + + + Frequently Asked Questions | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + + + +
+ +
+ +
+

Frequently Asked Questions

+
+

Why don’t updates work correctly on models instantiated as Model(field=value, field2=value2)?

+

The recommended way to create new rows is with the models .create method. The values passed into a model’s init method are interpreted by the model as the values as they were read from a row. This allows the model to “know” which rows have changed since the row was read out of cassandra, and create suitable update statements.

+
+
+

How to preserve ordering in batch query?

+

Statement Ordering is not supported by CQL3 batches. Therefore, +once cassandra needs resolving conflict(Updating the same column in one batch), +The algorithm below would be used.

+
    +
  • If timestamps are different, pick the column with the largest timestamp (the value being a regular column or a tombstone)

  • +
  • If timestamps are the same, and one of the columns in a tombstone (‘null’) - pick the tombstone

  • +
  • If timestamps are the same, and none of the columns are tombstones, pick the column with the largest value

  • +
+

Below is an example to show this scenario.

+
class MyMode(Model):
+    id    = columns.Integer(primary_key=True)
+    count = columns.Integer()
+    text  = columns.Text()
+
+with BatchQuery() as b:
+   MyModel.batch(b).create(id=1, count=2, text='123')
+   MyModel.batch(b).create(id=1, count=3, text='111')
+
+assert MyModel.objects(id=1).first().count == 3
+assert MyModel.objects(id=1).first().text  == '123'
+
+
+

The largest value of count is 3, and the largest value of text would be ‘123’.

+

The workaround is applying timestamp to each statement, then Cassandra would +resolve to the statement with the lastest timestamp.

+
with BatchQuery() as b:
+    MyModel.timestamp(datetime.now()).batch(b).create(id=1, count=2, text='123')
+    MyModel.timestamp(datetime.now()).batch(b).create(id=1, count=3, text='111')
+
+assert MyModel.objects(id=1).first().count == 3
+assert MyModel.objects(id=1).first().text  == '111'
+
+
+
+
+

How can I delete individual values from a row?

+

When inserting with CQLEngine, None is equivalent to CQL NULL or to +issuing a DELETE on that column. For example:

+
class MyModel(Model):
+    id    = columns.Integer(primary_key=True)
+    text  = columns.Text()
+
+m = MyModel.create(id=1, text='We can delete this with None')
+assert MyModel.objects(id=1).first().text is not None
+
+m.update(text=None)
+assert MyModel.objects(id=1).first().text is None
+
+
+
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.26.2-scylla/cqlengine/models.html b/3.26.2-scylla/cqlengine/models.html new file mode 100644 index 0000000000..0764fe29a6 --- /dev/null +++ b/3.26.2-scylla/cqlengine/models.html @@ -0,0 +1,826 @@ + + + + + + + + + + + + + Models | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + + + + + +
+

Models

+

A model is a python class representing a CQL table. Models derive from Model, and +define basic table properties and columns for a table.

+

Columns in your models map to columns in your CQL table. You define CQL columns by defining column attributes on your model classes. +For a model to be valid it needs at least one primary key column and one non-primary key column. Just as in CQL, the order you define +your columns in is important, and is the same order they are defined in on a model’s corresponding table.

+

Some basic examples defining models are shown below. Consult the Model API docs and Column API docs for complete details.

+
+

Example Definitions

+

This example defines a Person table, with the columns first_name and last_name

+
from cassandra.cqlengine import columns
+from cassandra.cqlengine.models import Model
+
+ class Person(Model):
+     id = columns.UUID(primary_key=True)
+     first_name  = columns.Text()
+     last_name = columns.Text()
+
+
+

The Person model would create this CQL table:

+
CREATE TABLE cqlengine.person (
+    id uuid,
+    first_name text,
+    last_name text,
+    PRIMARY KEY (id)
+);
+
+
+

Here’s an example of a comment table created with clustering keys, in descending order:

+
from cassandra.cqlengine import columns
+from cassandra.cqlengine.models import Model
+
+class Comment(Model):
+    photo_id = columns.UUID(primary_key=True)
+    comment_id = columns.TimeUUID(primary_key=True, clustering_order="DESC")
+    comment = columns.Text()
+
+
+

The Comment model’s create table would look like the following:

+
CREATE TABLE comment (
+  photo_id uuid,
+  comment_id timeuuid,
+  comment text,
+  PRIMARY KEY (photo_id, comment_id)
+) WITH CLUSTERING ORDER BY (comment_id DESC);
+
+
+

To sync the models to the database, you may do the following*:

+
from cassandra.cqlengine.management import sync_table
+sync_table(Person)
+sync_table(Comment)
+
+
+

*Note: synchronizing models causes schema changes, and should be done with caution. +Please see the discussion in cassandra.cqlengine.management - Schema management for cqlengine for considerations.

+

For examples on manipulating data and creating queries, see Making Queries

+
+
+

Manipulating model instances as dictionaries

+

Model instances can be accessed like dictionaries.

+
class Person(Model):
+    first_name  = columns.Text()
+    last_name = columns.Text()
+
+kevin = Person.create(first_name="Kevin", last_name="Deldycke")
+dict(kevin)  # returns {'first_name': 'Kevin', 'last_name': 'Deldycke'}
+kevin['first_name']  # returns 'Kevin'
+kevin.keys()  # returns ['first_name', 'last_name']
+kevin.values()  # returns ['Kevin', 'Deldycke']
+kevin.items()  # returns [('first_name', 'Kevin'), ('last_name', 'Deldycke')]
+
+kevin['first_name'] = 'KEVIN5000'  # changes the models first name
+
+
+
+
+

Extending Model Validation

+

Each time you save a model instance in cqlengine, the data in the model is validated against the schema you’ve defined +for your model. Most of the validation is fairly straightforward, it basically checks that you’re not trying to do +something like save text into an integer column, and it enforces the required flag set on column definitions. +It also performs any transformations needed to save the data properly.

+

However, there are often additional constraints or transformations you want to impose on your data, beyond simply +making sure that Cassandra won’t complain when you try to insert it. To define additional validation on a model, +extend the model’s validation method:

+
class Member(Model):
+    person_id = UUID(primary_key=True)
+    name = Text(required=True)
+
+    def validate(self):
+        super(Member, self).validate()
+        if self.name == 'jon':
+            raise ValidationError('no jon\'s allowed')
+
+
+

Note: while not required, the convention is to raise a ValidationError (from cassandra.cqlengine import ValidationError) +if validation fails.

+
+
+

Model Inheritance

+

It is possible to save and load different model classes using a single CQL table. +This is useful in situations where you have different object types that you want to store in a single cassandra row.

+

For instance, suppose you want a table that stores rows of pets owned by an owner:

+
class Pet(Model):
+    __table_name__ = 'pet'
+    owner_id = UUID(primary_key=True)
+    pet_id = UUID(primary_key=True)
+    pet_type = Text(discriminator_column=True)
+    name = Text()
+
+    def eat(self, food):
+        pass
+
+    def sleep(self, time):
+        pass
+
+class Cat(Pet):
+    __discriminator_value__ = 'cat'
+    cuteness = Float()
+
+    def tear_up_couch(self):
+        pass
+
+class Dog(Pet):
+    __discriminator_value__ = 'dog'
+    fierceness = Float()
+
+    def bark_all_night(self):
+        pass
+
+
+

After calling sync_table on each of these tables, the columns defined in each model will be added to the +pet table. Additionally, saving Cat and Dog models will save the meta data needed to identify each row +as either a cat or dog.

+

To setup a model structure with inheritance, follow these steps

+
    +
  1. Create a base model with a column set as the distriminator (distriminator_column=True in the column definition)

  2. +
  3. Create subclass models, and define a unique __discriminator_value__ value on each

  4. +
  5. Run sync_table on each of the sub tables

  6. +
+

About the discriminator value

+

The discriminator value is what cqlengine uses under the covers to map logical cql rows to the appropriate model type. The +base model maintains a map of discriminator values to subclasses. When a specialized model is saved, its discriminator value is +automatically saved into the discriminator column. The discriminator column may be any column type except counter and container types. +Additionally, if you set index=True on your discriminator column, you can execute queries against specialized subclasses, and a +WHERE clause will be automatically added to your query, returning only rows of that type. Note that you must +define a unique __discriminator_value__ to each subclass, and that you can only assign a single discriminator column per model.

+
+
+

User Defined Types

+

cqlengine models User Defined Types (UDTs) much like tables, with fields defined by column type attributes. However, UDT instances +are only created, presisted, and queried via table Models. A short example to introduce the pattern:

+
from cassandra.cqlengine.columns import *
+from cassandra.cqlengine.models import Model
+from cassandra.cqlengine.usertype import UserType
+
+class address(UserType):
+    street = Text()
+    zipcode = Integer()
+
+class users(Model):
+    __keyspace__ = 'account'
+    name = Text(primary_key=True)
+    addr = UserDefinedType(address)
+
+users.create(name="Joe", addr=address(street="Easy St.", zipcode=99999))
+user = users.objects(name="Joe")[0]
+print user.name, user.addr
+# Joe address(street=u'Easy St.', zipcode=99999)
+
+
+

UDTs are modeled by inheriting UserType, and setting column type attributes. Types are then used in defining +models by declaring a column of type UserDefinedType, with the UserType class as a parameter.

+

sync_table will implicitly +synchronize any types contained in the table. Alternatively sync_type() can be used to create/alter types +explicitly.

+

Upon declaration, types are automatically registered with the driver, so query results return instances of your UserType +class*.

+

*Note: UDTs were not added to the native protocol until v3. When setting up the cqlengine connection, be sure to specify +protocol_version=3. If using an earlier version, UDT queries will still work, but the returned type will be a namedtuple.

+
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.26.2-scylla/cqlengine/queryset.html b/3.26.2-scylla/cqlengine/queryset.html new file mode 100644 index 0000000000..196599ae35 --- /dev/null +++ b/3.26.2-scylla/cqlengine/queryset.html @@ -0,0 +1,998 @@ + + + + + + + + + + + + + Making Queries | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + + + +
+ +
+ +
+

Making Queries

+
+

Retrieving objects

+

Once you’ve populated Cassandra with data, you’ll probably want to retrieve some of it. This is accomplished with QuerySet objects. This section will describe how to use QuerySet objects to retrieve the data you’re looking for.

+
+

Retrieving all objects

+

The simplest query you can make is to return all objects from a table.

+

This is accomplished with the .all() method, which returns a QuerySet of all objects in a table

+

Using the Person example model, we would get all Person objects like this:

+
all_objects = Person.objects.all()
+
+
+
+
+

Retrieving objects with filters

+

Typically, you’ll want to query only a subset of the records in your database.

+

That can be accomplished with the QuerySet’s .filter(\*\*) method.

+

For example, given the model definition:

+
class Automobile(Model):
+    manufacturer = columns.Text(primary_key=True)
+    year = columns.Integer(primary_key=True)
+    model = columns.Text()
+    price = columns.Decimal()
+    options = columns.Set(columns.Text)
+
+
+

…and assuming the Automobile table contains a record of every car model manufactured in the last 20 years or so, we can retrieve only the cars made by a single manufacturer like this:

+
q = Automobile.objects.filter(manufacturer='Tesla')
+
+
+

You can also use the more convenient syntax:

+
q = Automobile.objects(Automobile.manufacturer == 'Tesla')
+
+
+

We can then further filter our query with another call to .filter

+
q = q.filter(year=2012)
+
+
+

Note: all queries involving any filtering MUST define either an ‘=’ or an ‘in’ relation to either a primary key column, or an indexed column.

+
+
+
+

Accessing objects in a QuerySet

+

There are several methods for getting objects out of a queryset

+
    +
  • +
    iterating over the queryset
    for car in Automobile.objects.all():
    +    #...do something to the car instance
    +    pass
    +
    +
    +
    +
    +
  • +
  • +
    list index
    q = Automobile.objects.all()
    +q[0] #returns the first result
    +q[1] #returns the second result
    +
    +
    +
    +

    Note

    +
      +
    • CQL does not support specifying a start position in it’s queries. Therefore, accessing elements using array indexing will load every result up to the index value requested

    • +
    • Using negative indices requires a “SELECT COUNT()” to be executed. This has a performance cost on large datasets.

    • +
    +
    +
    +
    +
  • +
  • +
    list slicing
    q = Automobile.objects.all()
    +q[1:] #returns all results except the first
    +q[1:9] #returns a slice of the results
    +
    +
    +
    +

    Note

    +
      +
    • CQL does not support specifying a start position in it’s queries. Therefore, accessing elements using array slicing will load every result up to the index value requested

    • +
    • Using negative indices requires a “SELECT COUNT()” to be executed. This has a performance cost on large datasets.

    • +
    +
    +
    +
    +
  • +
  • +
    calling get() on the queryset
    q = Automobile.objects.filter(manufacturer='Tesla')
    +q = q.filter(year=2012)
    +car = q.get()
    +
    +
    +

    this returns the object matching the queryset

    +
    +
    +
  • +
  • +
    calling first() on the queryset
    q = Automobile.objects.filter(manufacturer='Tesla')
    +q = q.filter(year=2012)
    +car = q.first()
    +
    +
    +

    this returns the first value in the queryset

    +
    +
    +
  • +
+
+
+

Filtering Operators

+

Equal To

+

The default filtering operator.

+
q = Automobile.objects.filter(manufacturer='Tesla')
+q = q.filter(year=2012)  #year == 2012
+
+
+

In addition to simple equal to queries, cqlengine also supports querying with other operators by appending a __<op> to the field name on the filtering call

+

in (__in)

+
q = Automobile.objects.filter(manufacturer='Tesla')
+q = q.filter(year__in=[2011, 2012])
+
+
+

> (__gt)

+
q = Automobile.objects.filter(manufacturer='Tesla')
+q = q.filter(year__gt=2010)  # year > 2010
+
+# or the nicer syntax
+
+q.filter(Automobile.year > 2010)
+
+
+

>= (__gte)

+
q = Automobile.objects.filter(manufacturer='Tesla')
+q = q.filter(year__gte=2010)  # year >= 2010
+
+# or the nicer syntax
+
+q.filter(Automobile.year >= 2010)
+
+
+

< (__lt)

+
q = Automobile.objects.filter(manufacturer='Tesla')
+q = q.filter(year__lt=2012)  # year < 2012
+
+# or...
+
+q.filter(Automobile.year < 2012)
+
+
+

<= (__lte)

+
q = Automobile.objects.filter(manufacturer='Tesla')
+q = q.filter(year__lte=2012)  # year <= 2012
+
+q.filter(Automobile.year <= 2012)
+
+
+

CONTAINS (__contains)

+

The CONTAINS operator is available for all collection types (List, Set, Map).

+
q = Automobile.objects.filter(manufacturer='Tesla')
+q.filter(options__contains='backup camera').allow_filtering()
+
+
+

Note that we need to use allow_filtering() since the options column has no secondary index.

+

LIKE (__like)

+

The LIKE operator is available for text columns that have a SASI secondary index.

+
q = Automobile.objects.filter(model__like='%Civic%').allow_filtering()
+
+
+

IS NOT NULL (IsNotNull(column_name))

+

The IS NOT NULL operator is not yet supported for C*.

+
q = Automobile.objects.filter(IsNotNull('model'))
+
+
+

Limitations:

+
    +
  • Currently, cqlengine does not support SASI index creation. To use this feature, you need to create the SASI index using the core driver.

  • +
  • Queries using LIKE must use allow_filtering() since the model column has no standard secondary index. Note that the server will use the SASI index properly when executing the query.

  • +
+
+
+

TimeUUID Functions

+

In addition to querying using regular values, there are two functions you can pass in when querying TimeUUID columns to help make filtering by them easier. Note that these functions don’t actually return a value, but instruct the cql interpreter to use the functions in it’s query.

+
+
+class cqlengine.queryset.MinTimeUUID(datetime)
+

returns the minimum time uuid value possible for the given datetime

+
+ +
+
+class cqlengine.queryset.MaxTimeUUID(datetime)
+

returns the maximum time uuid value possible for the given datetime

+
+ +

Example

+
class DataStream(Model):
+    id      = columns.UUID(partition_key=True)
+    time    = columns.TimeUUID(primary_key=True)
+    data    = columns.Bytes()
+
+min_time = datetime(1982, 1, 1)
+max_time = datetime(1982, 3, 9)
+
+DataStream.filter(time__gt=functions.MinTimeUUID(min_time), time__lt=functions.MaxTimeUUID(max_time))
+
+
+
+
+

Token Function

+

Token functon may be used only on special, virtual column pk__token, representing token of partition key (it also works for composite partition keys). +Cassandra orders returned items by value of partition key token, so using cqlengine.Token we can easy paginate through all table rows.

+

See http://cassandra.apache.org/doc/cql3/CQL-3.0.html#tokenFun

+

Example

+
class Items(Model):
+    id      = columns.Text(primary_key=True)
+    data    = columns.Bytes()
+
+query = Items.objects.all().limit(10)
+
+first_page = list(query);
+last = first_page[-1]
+next_page = list(query.filter(pk__token__gt=cqlengine.Token(last.pk)))
+
+
+
+
+

QuerySets are immutable

+

When calling any method that changes a queryset, the method does not actually change the queryset object it’s called on, but returns a new queryset object with the attributes of the original queryset, plus the attributes added in the method call.

+

Example

+
#this produces 3 different querysets
+#q does not change after it's initial definition
+q = Automobiles.objects.filter(year=2012)
+tesla2012 = q.filter(manufacturer='Tesla')
+honda2012 = q.filter(manufacturer='Honda')
+
+
+
+
+

Ordering QuerySets

+

Since Cassandra is essentially a distributed hash table on steroids, the order you get records back in will not be particularly predictable.

+

However, you can set a column to order on with the .order_by(column_name) method.

+

Example

+
#sort ascending
+q = Automobiles.objects.all().order_by('year')
+#sort descending
+q = Automobiles.objects.all().order_by('-year')
+
+
+

Note: Cassandra only supports ordering on a clustering key. In other words, to support ordering results, your model must have more than one primary key, and you must order on a primary key, excluding the first one.

+

For instance, given our Automobile model, year is the only column we can order on.

+
+
+

Values Lists

+

There is a special QuerySet’s method .values_list() - when called, QuerySet returns lists of values instead of model instances. It may significantly speedup things with lower memory footprint for large responses. +Each tuple contains the value from the respective field passed into the values_list() call — so the first item is the first field, etc. For example:

+
items = list(range(20))
+random.shuffle(items)
+for i in items:
+    TestModel.create(id=1, clustering_key=i)
+
+values = list(TestModel.objects.values_list('clustering_key', flat=True))
+# [19L, 18L, 17L, 16L, 15L, 14L, 13L, 12L, 11L, 10L, 9L, 8L, 7L, 6L, 5L, 4L, 3L, 2L, 1L, 0L]
+
+
+
+
+

Per Query Timeouts

+

By default all queries are executed with the timeout defined in ~cqlengine.connection.setup() +The examples below show how to specify a per-query timeout. +A timeout is specified in seconds and can be an int, float or None. +None means no timeout.

+
class Row(Model):
+    id = columns.Integer(primary_key=True)
+    name = columns.Text()
+
+
+

Fetch all objects with a timeout of 5 seconds

+
Row.objects().timeout(5).all()
+
+
+

Create a single row with a 50ms timeout

+
Row(id=1, name='Jon').timeout(0.05).create()
+
+
+

Delete a single row with no timeout

+
Row(id=1).timeout(None).delete()
+
+
+

Update a single row with no timeout

+
Row(id=1).timeout(None).update(name='Blake')
+
+
+

Batch query timeouts

+
with BatchQuery(timeout=10) as b:
+    Row(id=1, name='Jon').create()
+
+
+

NOTE: You cannot set both timeout and batch at the same time, batch will use the timeout defined in it’s constructor. +Setting the timeout on the model is meaningless and will raise an AssertionError.

+
+
+

Default TTL and Per Query TTL

+

Model default TTL now relies on the default_time_to_live feature, introduced in Cassandra 2.0. It is not handled anymore in the CQLEngine Model (scylla-driver >=3.6). You can set the default TTL of a table like this:

+

Example:

+
class User(Model):
+    __options__ = {'default_time_to_live': 20}
+
+    user_id = columns.UUID(primary_key=True)
+    ...
+
+
+

You can set TTL per-query if needed. Here are a some examples:

+

Example:

+
class User(Model):
+    __options__ = {'default_time_to_live': 20}
+
+    user_id = columns.UUID(primary_key=True)
+    ...
+
+user = User.objects.create(user_id=1)  # Default TTL 20 will be set automatically on the server
+
+user.ttl(30).update(age=21)            # Update the TTL to 30
+User.objects.ttl(10).create(user_id=1)  # TTL 10
+User(user_id=1, age=21).ttl(10).save()  # TTL 10
+
+
+
+
+

Named Tables

+

Named tables are a way of querying a table without creating an class. They’re useful for querying system tables or exploring an unfamiliar database.

+
from cassandra.cqlengine.connection import setup
+setup("127.0.0.1", "cqlengine_test")
+
+from cassandra.cqlengine.named import NamedTable
+user = NamedTable("cqlengine_test", "user")
+user.objects()
+user.objects()[0]
+
+# {u'pk': 1, u't': datetime.datetime(2014, 6, 26, 17, 10, 31, 774000)}
+
+
+
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.26.2-scylla/cqlengine/third-party.html b/3.26.2-scylla/cqlengine/third-party.html new file mode 100644 index 0000000000..ca367f6370 --- /dev/null +++ b/3.26.2-scylla/cqlengine/third-party.html @@ -0,0 +1,698 @@ + + + + + + + + + + + + + Third party integrations | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + + + +
+ +
+ +
+

Third party integrations

+
+

Celery

+

Here’s how, in substance, CQLengine can be plugged to Celery:

+
from celery import Celery
+from celery.signals import worker_process_init, beat_init
+from cassandra.cqlengine import connection
+from cassandra.cqlengine.connection import (
+    cluster as cql_cluster, session as cql_session)
+
+def cassandra_init(**kwargs):
+    """ Initialize a clean Cassandra connection. """
+    if cql_cluster is not None:
+        cql_cluster.shutdown()
+    if cql_session is not None:
+        cql_session.shutdown()
+    connection.setup()
+
+# Initialize worker context for both standard and periodic tasks.
+worker_process_init.connect(cassandra_init)
+beat_init.connect(cassandra_init)
+
+app = Celery()
+
+
+
+
+

uWSGI

+

This is the code required for proper connection handling of CQLengine for a +uWSGI-run application:

+
from cassandra.cqlengine import connection
+from cassandra.cqlengine.connection import (
+    cluster as cql_cluster, session as cql_session)
+
+try:
+    from uwsgidecorators import postfork
+except ImportError:
+    # We're not in a uWSGI context, no need to hook Cassandra session
+    # initialization to the postfork event.
+    pass
+else:
+    @postfork
+    def cassandra_init(**kwargs):
+        """ Initialize a new Cassandra session in the context.
+
+        Ensures that a new session is returned for every new request.
+        """
+        if cql_cluster is not None:
+            cql_cluster.shutdown()
+        if cql_session is not None:
+            cql_session.shutdown()
+        connection.setup()
+
+
+
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.26.2-scylla/cqlengine/upgrade-guide.html b/3.26.2-scylla/cqlengine/upgrade-guide.html new file mode 100644 index 0000000000..78e837ac6c --- /dev/null +++ b/3.26.2-scylla/cqlengine/upgrade-guide.html @@ -0,0 +1,830 @@ + + + + + + + + + + + + + Upgrade Guide | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + + + + + +
+

Upgrade Guide

+

This is an overview of things that changed as the cqlengine project was merged into +scylla-driver. While efforts were taken to preserve the API and most functionality exactly, +conversion to this package will still require certain minimal updates (namely, imports).

+

THERE IS ONE FUNCTIONAL CHANGE, described in the first section below.

+
+

Functional Changes

+
+

List Prepend Reversing

+

Legacy cqlengine included a workaround for a Cassandra bug in which prepended list segments were +reversed (CASSANDRA-8733). As of +this integration, this workaround is removed. The first released integrated version emits +a warning when prepend is used. Subsequent versions will have this warning removed.

+
+
+

Date Column Type

+

The Date column type in legacy cqlengine used a timestamp CQL type and truncated the time. +Going forward, the Date type represents a date for Cassandra 2.2+ +(PYTHON-245). +Users of the legacy functionality should convert models to use DateTime (which +uses timestamp internally), and use the build-in datetime.date for input values.

+
+
+
+

Remove cqlengine

+

To avoid confusion or mistakes using the legacy package in your application, it +is prudent to remove the cqlengine package when upgrading to the integrated version.

+

The driver setup script will warn if the legacy package is detected during install, +but it will not prevent side-by-side installation.

+
+
+

Organization

+
+

Imports

+

cqlengine is now integrated as a sub-package of the driver base package ‘cassandra’. +Upgrading will require adjusting imports to cqlengine. For example:

+
from cassandra.cqlengine import columns
+
+
+

is now:

+
from cassandra.cqlengine import columns
+
+
+
+
+

Package-Level Aliases

+

Legacy cqlengine defined a number of aliases at the package level, which became redundant +when the package was integrated for a driver. These have been removed in favor of absolute +imports, and referring to cannonical definitions. For example, cqlengine.ONE was an alias +of cassandra.ConsistencyLevel.ONE. In the integrated package, only the +cassandra.ConsistencyLevel remains.

+

Additionally, submodule aliases are removed from cqlengine in favor of absolute imports.

+

These aliases are removed, and not deprecated because they should be straightforward to iron out +at module load time.

+
+
+

Exceptions

+

The legacy cqlengine.exceptions module had a number of Exception classes that were variously +common to the package, or only used in specific modules. Common exceptions were relocated to +cqlengine, and specialized exceptions were placed in the module that raises them. Below is a +listing of updated locations:

+ ++++ + + + + + + + + + + + + + + + + + + + + + + + + + +

Exception class

New module

CQLEngineException

cassandra.cqlengine

ModelException

cassandra.cqlengine.models

ValidationError

cassandra.cqlengine

UndefinedKeyspaceException

cassandra.cqlengine.connection

LWTException

cassandra.cqlengine.query

IfNotExistsWithCounterColumn

cassandra.cqlengine.query

+
+
+

UnicodeMixin Consolidation

+

class UnicodeMixin was defined in several cqlengine modules. This has been consolidated +to a single definition in the cqlengine package init file. This is not technically part of +the API, but noted here for completeness.

+
+
+
+

API Deprecations

+

This upgrade served as a good juncture to deprecate certain API features and invite users to upgrade +to new ones. The first released version does not change functionality – only introduces deprecation +warnings. Future releases will remove these features in favor of the alternatives.

+
+

Float/Double Overload

+

Previously there was no Double column type. Doubles were modeled by specifying Float(double_precision=True). +This inititializer parameter is now deprecated. Applications should use Double for CQL double, and Float +for CQL float.

+
+
+

Schema Management

+

cassandra.cqlengine.management.create_keyspace is deprecated. Instead, use the new replication-strategy-specific +functions that accept explicit options for known strategies:

+ +

cassandra.cqlengine.management.delete_keyspace is deprecated in favor of a new function, drop_keyspace(). The +intent is simply to make the function match the CQL verb it invokes.

+
+
+

Model Inheritance

+

The names for class attributes controlling model inheritance are changing. Changes are as follows:

+ +

The functionality is unchanged – the intent here is to make the names and language around these attributes more precise. +For now, the old names are just deprecated, and the mapper will emit warnings if they are used. The old names +will be removed in a future version.

+

The example below shows a simple translation:

+

Before:

+
class Pet(Model):
+    __table_name__ = 'pet'
+    owner_id = UUID(primary_key=True)
+    pet_id = UUID(primary_key=True)
+    pet_type = Text(polymorphic_key=True)
+    name = Text()
+
+class Cat(Pet):
+    __polymorphic_key__ = 'cat'
+
+class Dog(Pet):
+    __polymorphic_key__ = 'dog'
+
+
+

After:

+
class Pet(models.Model):
+    __table_name__ = 'pet'
+    owner_id = UUID(primary_key=True)
+    pet_id = UUID(primary_key=True)
+    pet_type = Text(discriminator_column=True)
+    name = Text()
+
+class Cat(Pet):
+    __discriminator_value__ = 'cat'
+
+class Dog(Pet):
+    __discriminator_value__ = 'dog'
+
+
+
+
+

TimeUUID.from_datetime

+

This function is deprecated in favor of the core utility function uuid_from_time().

+
+
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.26.2-scylla/dates-and-times.html b/3.26.2-scylla/dates-and-times.html new file mode 100644 index 0000000000..36236ab3be --- /dev/null +++ b/3.26.2-scylla/dates-and-times.html @@ -0,0 +1,722 @@ + + + + + + + + + + + + + Working with Dates and Times | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + + + +
+ +
+ +
+

Working with Dates and Times

+

This document is meant to provide on overview of the assumptions and limitations of the driver time handling, the +reasoning behind it, and describe approaches to working with these types.

+
+

timestamps (Cassandra DateType)

+

Timestamps in Cassandra are timezone-naive timestamps encoded as millseconds since UNIX epoch. Clients working with +timestamps in this database usually find it easiest to reason about them if they are always assumed to be UTC. To quote the +pytz documentation, “The preferred way of dealing with times is to always work in UTC, converting to localtime only when +generating output to be read by humans.” The driver adheres to this tenant, and assumes UTC is always in the database. The +driver attempts to make this correct on the way in, and assumes no timezone on the way out.

+
+

Write Path

+

When inserting timestamps, the driver handles serialization for the write path as follows:

+

If the input is a datetime.datetime, the serialization is normalized by starting with the utctimetuple() of the +value.

+
    +
  • If the datetime object is timezone-aware, the timestamp is shifted, and represents the UTC timestamp equivalent.

  • +
  • If the datetime object is timezone-naive, this results in no shift – any datetime with no timezone information is assumed to be UTC

  • +
+

Note the second point above applies even to “local” times created using now():

+
>>> d = datetime.now()
+
+>>> print(d.tzinfo)
+None
+
+
+

These do not contain timezone information intrinsically, so they will be assumed to be UTC and not shifted. When generating +timestamps in the application, it is clearer to use datetime.utcnow() to be explicit about it.

+

If the input for a timestamp is numeric, it is assumed to be a epoch-relative millisecond timestamp, as specified in the +CQL spec – no scaling or conversion is done.

+
+
+

Read Path

+

The driver always assumes persisted timestamps are UTC and makes no attempt to localize them. Returned values are +timezone-naive datetime.datetime. We follow this approach because the datetime API has deficiencies around daylight +saving time, and the defacto package for handling this is a third-party package (we try to minimize external dependencies +and not make decisions for the integrator).

+

The decision for how to handle timezones is left to the application. For the most part it is straightforward to apply +localization to the datetimes returned by queries. One prevalent method is to use pytz for localization:

+
import pytz
+user_tz = pytz.timezone('US/Central')
+timestamp_naive = row.ts
+timestamp_utc = pytz.utc.localize(timestamp_naive)
+timestamp_presented = timestamp_utc.astimezone(user_tz)
+
+
+

This is the most robust approach (likely refactored into a function). If it is deemed too cumbersome to apply for all call +sites in the application, it is possible to patch the driver with custom deserialization for this type. However, doing +this depends depends some on internal APIs and what extensions are present, so we will only mention the possibility, and +not spell it out here.

+
+
+
+

date, time (Cassandra DateType)

+

Date and time in Cassandra are idealized markers, much like datetime.date and datetime.time in the Python standard +library. Unlike these Python implementations, the Cassandra encoding supports much wider ranges. To accommodate these +ranges without overflow, this driver returns these data in custom types: util.Date and util.Time.

+
+

Write Path

+

For simple (not prepared) statements, the input values for each of these can be either a string literal or an encoded +integer. See Working with dates +or Working with time for details +on the encoding or string formats.

+

For prepared statements, the driver accepts anything that can be used to construct the util.Date or +util.Time classes. See the linked API docs for details.

+
+
+

Read Path

+

The driver always returns custom types for date and time.

+

The driver returns util.Date for date in order to accommodate the wider range of values without overflow. +For applications working within the supported range of [datetime.MINYEAR, datetime.MAXYEAR], these are easily +converted to standard datetime.date insances using Date.date().

+

The driver returns util.Time for time in order to retain nanosecond precision stored in the database. +For applications not concerned with this level of precision, these are easily converted to standard datetime.time +insances using Time.time().

+
+
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.26.2-scylla/execution-profiles.html b/3.26.2-scylla/execution-profiles.html new file mode 100644 index 0000000000..a181436d2a --- /dev/null +++ b/3.26.2-scylla/execution-profiles.html @@ -0,0 +1,766 @@ + + + + + + + + + + + + + Execution Profiles | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + + + +
+ +
+ +
+

Execution Profiles

+

Execution profiles aim at making it easier to execute requests in different ways within +a single connected Session. Execution profiles are being introduced to deal with the exploding number of +configuration options, especially as the database platform evolves more complex workloads.

+

The legacy configuration remains intact, but legacy and Execution Profile APIs +cannot be used simultaneously on the same client Cluster. Legacy configuration +will be removed in the next major release (4.0).

+

An execution profile and its parameters should be unique across Cluster instances. +For example, an execution profile and its LoadBalancingPolicy should +not be applied to more than one Cluster instance.

+

This document explains how Execution Profiles relate to existing settings, and shows how to use the new profiles for +request execution.

+
+

Mapping Legacy Parameters to Profiles

+

Execution profiles can inherit from cluster.ExecutionProfile, and currently provide the following options, +previously input from the noted attributes:

+ +

When using the new API, these parameters can be defined by instances of cluster.ExecutionProfile.

+
+
+

Using Execution Profiles

+
+

Default

+
from cassandra.cluster import Cluster
+cluster = Cluster()
+session = cluster.connect()
+local_query = 'SELECT rpc_address FROM system.local'
+for _ in cluster.metadata.all_hosts():
+    print session.execute(local_query)[0]
+
+
+
Row(rpc_address='127.0.0.2')
+Row(rpc_address='127.0.0.1')
+
+
+

The default execution profile is built from Cluster parameters and default Session attributes. This profile matches existing default +parameters.

+
+
+

Initializing cluster with profiles

+
from cassandra.cluster import ExecutionProfile
+from cassandra.policies import WhiteListRoundRobinPolicy
+
+node1_profile = ExecutionProfile(load_balancing_policy=WhiteListRoundRobinPolicy(['127.0.0.1']))
+node2_profile = ExecutionProfile(load_balancing_policy=WhiteListRoundRobinPolicy(['127.0.0.2']))
+
+profiles = {'node1': node1_profile, 'node2': node2_profile}
+session = Cluster(execution_profiles=profiles).connect()
+for _ in cluster.metadata.all_hosts():
+    print session.execute(local_query, execution_profile='node1')[0]
+
+
+
Row(rpc_address='127.0.0.1')
+Row(rpc_address='127.0.0.1')
+
+
+
for _ in cluster.metadata.all_hosts():
+    print session.execute(local_query, execution_profile='node2')[0]
+
+
+
Row(rpc_address='127.0.0.2')
+Row(rpc_address='127.0.0.2')
+
+
+
for _ in cluster.metadata.all_hosts():
+    print session.execute(local_query)[0]
+
+
+
Row(rpc_address='127.0.0.2')
+Row(rpc_address='127.0.0.1')
+
+
+

Note that, even when custom profiles are injected, the default TokenAwarePolicy(DCAwareRoundRobinPolicy()) is still +present. To override the default, specify a policy with the EXEC_PROFILE_DEFAULT key.

+
from cassandra.cluster import EXEC_PROFILE_DEFAULT
+profile = ExecutionProfile(request_timeout=30)
+cluster = Cluster(execution_profiles={EXEC_PROFILE_DEFAULT: profile})
+
+
+
+
+

Adding named profiles

+

New profiles can be added constructing from scratch, or deriving from default:

+
locked_execution = ExecutionProfile(load_balancing_policy=WhiteListRoundRobinPolicy(['127.0.0.1']))
+node1_profile = 'node1_whitelist'
+cluster.add_execution_profile(node1_profile, locked_execution)
+
+for _ in cluster.metadata.all_hosts():
+    print session.execute(local_query, execution_profile=node1_profile)[0]
+
+
+
Row(rpc_address='127.0.0.1')
+Row(rpc_address='127.0.0.1')
+
+
+

See Cluster.add_execution_profile() for details and optional parameters.

+
+
+

Passing a profile instance without mapping

+

We also have the ability to pass profile instances to be used for execution, but not added to the mapping:

+
from cassandra.query import tuple_factory
+
+tmp = session.execution_profile_clone_update('node1', request_timeout=100, row_factory=tuple_factory)
+
+print session.execute(local_query, execution_profile=tmp)[0]
+print session.execute(local_query, execution_profile='node1')[0]
+
+
+
('127.0.0.1',)
+Row(rpc_address='127.0.0.1')
+
+
+

The new profile is a shallow copy, so the tmp profile shares a load balancing policy with one managed by the cluster. +If reference objects are to be updated in the clone, one would typically set those attributes to a new instance.

+
+
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.26.2-scylla/faq.html b/3.26.2-scylla/faq.html new file mode 100644 index 0000000000..3e0d44a260 --- /dev/null +++ b/3.26.2-scylla/faq.html @@ -0,0 +1,702 @@ + + + + + + + + + + + + + Frequently Asked Questions | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + + + +
+ +
+ +
+

Frequently Asked Questions

+

See also cqlengine FAQ

+
+

Why do connections or IO operations timeout in my WSGI application?

+

Depending on your application process model, it may be forking after driver Session is created. Most IO reactors do not handle this, and problems will manifest as timeouts.

+

To avoid this, make sure to create sessions per process, after the fork. Using uWSGI and Flask for example:

+
from flask import Flask
+from uwsgidecorators import postfork
+from cassandra.cluster import Cluster
+
+session = None
+prepared = None
+
+@postfork
+def connect():
+    global session, prepared
+    session = Cluster().connect()
+    prepared = session.prepare("SELECT release_version FROM system.local WHERE key=?")
+
+app = Flask(__name__)
+
+@app.route('/')
+def server_version():
+    row = session.execute(prepared, ('local',))[0]
+    return row.release_version
+
+
+

uWSGI provides a postfork hook you can use to create sessions and prepared statements after the child process forks.

+
+
+

How do I trace a request?

+

Request tracing can be turned on for any request by setting trace=True in Session.execute_async(). View the results by waiting on the future, then ResponseFuture.get_query_trace(). +Since tracing is done asynchronously to the request, this method polls until the trace is complete before querying data.

+
>>> future = session.execute_async("SELECT * FROM system.local", trace=True)
+>>> result = future.result()
+>>> trace = future.get_query_trace()
+>>> for e in trace.events:
+>>>     print e.source_elapsed, e.description
+
+0:00:00.000077 Parsing select * from system.local
+0:00:00.000153 Preparing statement
+0:00:00.000309 Computing ranges to query
+0:00:00.000368 Submitting range requests on 1 ranges with a concurrency of 1 (279.77142 rows per range expected)
+0:00:00.000422 Submitted 1 concurrent range requests covering 1 ranges
+0:00:00.000480 Executing seq scan across 1 sstables for (min(-9223372036854775808), min(-9223372036854775808))
+0:00:00.000669 Read 1 live and 0 tombstone cells
+0:00:00.000755 Scanned 1 rows and matched 1
+
+
+

trace is a QueryTrace object.

+
+
+

How do I determine the replicas for a query?

+

With prepared statements, the replicas are obtained by routing_key, based on current cluster token metadata:

+
>>> prepared = session.prepare("SELECT * FROM example.t WHERE key=?")
+>>> bound = prepared.bind((1,))
+>>> replicas = cluster.metadata.get_replicas(bound.keyspace, bound.routing_key)
+>>> for h in replicas:
+>>>   print h.address
+127.0.0.1
+127.0.0.2
+
+
+

replicas is a list of Host objects.

+
+
+

How does the driver manage request retries?

+

By default, retries are managed by the Cluster.default_retry_policy set on the session Cluster. It can also +be specialized per statement by setting Statement.retry_policy.

+

Retries are presently attempted on the same coordinator, but this may change in the future.

+

Please see policies.RetryPolicy for further details.

+
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.26.2-scylla/getting-started.html b/3.26.2-scylla/getting-started.html new file mode 100644 index 0000000000..54d690f145 --- /dev/null +++ b/3.26.2-scylla/getting-started.html @@ -0,0 +1,1117 @@ + + + + + + + + + + + + + Getting Started | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + + + +
+ +
+ +
+

Getting Started

+

First, make sure you have the driver properly installed.

+
+

Connecting to a Cluster

+

Before we can start executing any queries against a Cassandra cluster we need to setup +an instance of Cluster. As the name suggests, you will typically have one +instance of Cluster for each Cassandra cluster you want to interact +with.

+

First, make sure you have the Cassandra driver properly installed.

+
+

Connecting to Cassandra

+

The simplest way to create a Cluster is like this:

+
from cassandra.cluster import Cluster
+
+cluster = Cluster()
+
+
+

This will attempt to connection to a Cassandra instance on your +local machine (127.0.0.1). You can also specify a list of IP +addresses for nodes in your cluster:

+
from cassandra.cluster import Cluster
+
+cluster = Cluster(['192.168.0.1', '192.168.0.2'])
+
+
+

The set of IP addresses we pass to the Cluster is simply +an initial set of contact points. After the driver connects to one +of these nodes it will automatically discover the rest of the +nodes in the cluster and connect to them, so you don’t need to list +every node in your cluster.

+

If you need to use a non-standard port, use SSL, or customize the driver’s +behavior in some other way, this is the place to do it:

+
from cassandra.cluster import Cluster
+cluster = Cluster(['192.168.0.1', '192.168.0.2'], port=..., ssl_context=...)
+
+
+

Instantiating a Cluster does not actually connect us to any nodes. +To establish connections and begin executing queries we need a +Session, which is created by calling Cluster.connect():

+
cluster = Cluster()
+session = cluster.connect()
+
+
+
+
+
+

Session Keyspace

+

The connect() method takes an optional keyspace argument +which sets the default keyspace for all queries made through that Session:

+
cluster = Cluster()
+session = cluster.connect('mykeyspace')
+
+
+

You can always change a Session’s keyspace using set_keyspace() or +by executing a USE <keyspace> query:

+
session.set_keyspace('users')
+# or you can do this instead
+session.execute('USE users')
+
+
+
+
+

Execution Profiles

+

Profiles are passed in by execution_profiles dict.

+

In this case we can construct the base ExecutionProfile passing all attributes:

+
from cassandra.cluster import Cluster, ExecutionProfile, EXEC_PROFILE_DEFAULT
+from cassandra.policies import WhiteListRoundRobinPolicy, DowngradingConsistencyRetryPolicy
+from cassandra.query import tuple_factory
+
+profile = ExecutionProfile(
+    load_balancing_policy=WhiteListRoundRobinPolicy(['127.0.0.1']),
+    retry_policy=DowngradingConsistencyRetryPolicy(),
+    consistency_level=ConsistencyLevel.LOCAL_QUORUM,
+    serial_consistency_level=ConsistencyLevel.LOCAL_SERIAL,
+    request_timeout=15,
+    row_factory=tuple_factory
+)
+cluster = Cluster(execution_profiles={EXEC_PROFILE_DEFAULT: profile})
+session = cluster.connect()
+
+print(session.execute("SELECT release_version FROM system.local").one())
+
+
+

Users are free to setup additional profiles to be used by name:

+
profile_long = ExecutionProfile(request_timeout=30)
+cluster = Cluster(execution_profiles={'long': profile_long})
+session = cluster.connect()
+session.execute(statement, execution_profile='long')
+
+
+

Also, parameters passed to Session.execute or attached to Statements are still honored as before.

+
+
+

Executing Queries

+

Now that we have a Session we can begin to execute queries. The simplest +way to execute a query is to use execute():

+
rows = session.execute('SELECT name, age, email FROM users')
+for user_row in rows:
+    print user_row.name, user_row.age, user_row.email
+
+
+

This will transparently pick a Cassandra node to execute the query against +and handle any retries that are necessary if the operation fails.

+

By default, each row in the result set will be a +namedtuple. +Each row will have a matching attribute for each column defined in the schema, +such as name, age, and so on. You can also treat them as normal tuples +by unpacking them or accessing fields by position. The following three +examples are equivalent:

+
rows = session.execute('SELECT name, age, email FROM users')
+for row in rows:
+    print row.name, row.age, row.email
+
+
+
rows = session.execute('SELECT name, age, email FROM users')
+for (name, age, email) in rows:
+    print name, age, email
+
+
+
rows = session.execute('SELECT name, age, email FROM users')
+for row in rows:
+    print row[0], row[1], row[2]
+
+
+

If you prefer another result format, such as a dict per row, you +can change the row_factory attribute.

+

As mentioned in our Drivers Best Practices Guide, +it is highly recommended to use Prepared statements for your +frequently run queries.

+
+
+

Prepared Statements

+

Prepared statements are queries that are parsed by Cassandra and then saved +for later use. When the driver uses a prepared statement, it only needs to +send the values of parameters to bind. This lowers network traffic +and CPU utilization within Cassandra because Cassandra does not have to +re-parse the query each time.

+

To prepare a query, use Session.prepare():

+
user_lookup_stmt = session.prepare("SELECT * FROM users WHERE user_id=?")
+
+users = []
+for user_id in user_ids_to_query:
+    user = session.execute(user_lookup_stmt, [user_id])
+    users.append(user)
+
+
+

prepare() returns a PreparedStatement instance +which can be used in place of SimpleStatement instances or literal +string queries. It is automatically prepared against all nodes, and the driver +handles re-preparing against new nodes and restarted nodes when necessary.

+

Note that the placeholders for prepared statements are ? characters. This +is different than for simple, non-prepared statements (although future versions +of the driver may use the same placeholders for both).

+
+
+

Passing Parameters to CQL Queries

+

Althought it is not recommended, you can also pass parameters to non-prepared +statements. The driver supports two forms of parameter place-holders: positional +and named.

+

Positional parameters are used with a %s placeholder. For example, +when you execute:

+
session.execute(
+    """
+    INSERT INTO users (name, credits, user_id)
+    VALUES (%s, %s, %s)
+    """,
+    ("John O'Reilly", 42, uuid.uuid1())
+)
+
+
+

It is translated to the following CQL query:

+
INSERT INTO users (name, credits, user_id)
+VALUES ('John O''Reilly', 42, 2644bada-852c-11e3-89fb-e0b9a54a6d93)
+
+
+

Note that you should use %s for all types of arguments, not just strings. +For example, this would be wrong:

+
session.execute("INSERT INTO USERS (name, age) VALUES (%s, %d)", ("bob", 42))  # wrong
+
+
+

Instead, use %s for the age placeholder.

+

If you need to use a literal % character, use %%.

+

Note: you must always use a sequence for the second argument, even if you are +only passing in a single variable:

+
session.execute("INSERT INTO foo (bar) VALUES (%s)", "blah")  # wrong
+session.execute("INSERT INTO foo (bar) VALUES (%s)", ("blah"))  # wrong
+session.execute("INSERT INTO foo (bar) VALUES (%s)", ("blah", ))  # right
+session.execute("INSERT INTO foo (bar) VALUES (%s)", ["blah"])  # right
+
+
+

Note that the second line is incorrect because in Python, single-element tuples +require a comma.

+

Named place-holders use the %(name)s form:

+
session.execute(
+    """
+    INSERT INTO users (name, credits, user_id, username)
+    VALUES (%(name)s, %(credits)s, %(user_id)s, %(name)s)
+    """,
+    {'name': "John O'Reilly", 'credits': 42, 'user_id': uuid.uuid1()}
+)
+
+
+

Note that you can repeat placeholders with the same name, such as %(name)s +in the above example.

+

Only data values should be supplied this way. Other items, such as keyspaces, +table names, and column names should be set ahead of time (typically using +normal string formatting).

+
+
+

Type Conversions

+

For non-prepared statements, Python types are cast to CQL literals in the +following way:

+ ++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Python Type

CQL Literal Type

None

NULL

bool

boolean

float

+
float
+
double
+
+
+
int
+
long
+
+
+
int
+
bigint
+
varint
+
smallint
+
tinyint
+
counter
+
+

decimal.Decimal

decimal

+
str
+
unicode
+
+
+
ascii
+
varchar
+
text
+
+
+
buffer
+
bytearray
+
+

blob

date

date

datetime

timestamp

time

time

+
list
+
tuple
+
generator
+
+

list

+
set
+
frozenset
+
+

set

+
dict
+
OrderedDict
+
+

map

uuid.UUID

+
timeuuid
+
uuid
+
+
+
+
+

Asynchronous Queries

+

The driver supports asynchronous query execution through +execute_async(). Instead of waiting for the query to +complete and returning rows directly, this method almost immediately +returns a ResponseFuture object. There are two ways of +getting the final result from this object.

+

The first is by calling result() on it. If +the query has not yet completed, this will block until it has and +then return the result or raise an Exception if an error occurred. +For example:

+
from cassandra import ReadTimeout
+
+query = "SELECT * FROM users WHERE user_id=%s"
+future = session.execute_async(query, [user_id])
+
+# ... do some other work
+
+try:
+    rows = future.result()
+    user = rows[0]
+    print user.name, user.age
+except ReadTimeout:
+    log.exception("Query timed out:")
+
+
+

This works well for executing many queries concurrently:

+
# build a list of futures
+futures = []
+query = "SELECT * FROM users WHERE user_id=%s"
+for user_id in ids_to_fetch:
+    futures.append(session.execute_async(query, [user_id])
+
+# wait for them to complete and use the results
+for future in futures:
+    rows = future.result()
+    print rows[0].name
+
+
+

Alternatively, instead of calling result(), +you can attach callback and errback functions through the +add_callback(), +add_errback(), and +add_callbacks(), methods. If you have used +Twisted Python before, this is designed to be a lightweight version of +that:

+
def handle_success(rows):
+    user = rows[0]
+    try:
+        process_user(user.name, user.age, user.id)
+    except Exception:
+        log.error("Failed to process user %s", user.id)
+        # don't re-raise errors in the callback
+
+def handle_error(exception):
+    log.error("Failed to fetch user info: %s", exception)
+
+
+future = session.execute_async(query)
+future.add_callbacks(handle_success, handle_error)
+
+
+
+
There are a few important things to remember when working with callbacks:
    +
  • Exceptions that are raised inside the callback functions will be logged and then ignored.

  • +
  • Your callback will be run on the event loop thread, so any long-running +operations will prevent other requests from being handled

  • +
+
+
+
+
+

Setting a Consistency Level

+

The consistency level used for a query determines how many of the +replicas of the data you are interacting with need to respond for +the query to be considered a success.

+

By default, ConsistencyLevel.LOCAL_ONE will be used for all queries. +You can specify a different default by setting the ExecutionProfile.consistency_level +for the execution profile with key EXEC_PROFILE_DEFAULT. +To specify a different consistency level per request, wrap queries +in a SimpleStatement:

+
from cassandra import ConsistencyLevel
+from cassandra.query import SimpleStatement
+
+query = SimpleStatement(
+    "INSERT INTO users (name, age) VALUES (%s, %s)",
+    consistency_level=ConsistencyLevel.QUORUM)
+session.execute(query, ('John', 42))
+
+
+
+
+

Setting a Consistency Level with Prepared Statements

+

To specify a consistency level for prepared statements, you have two options.

+

The first is to set a default consistency level for every execution of the +prepared statement:

+
from cassandra import ConsistencyLevel
+
+cluster = Cluster()
+session = cluster.connect("mykeyspace")
+user_lookup_stmt = session.prepare("SELECT * FROM users WHERE user_id=?")
+user_lookup_stmt.consistency_level = ConsistencyLevel.QUORUM
+
+# these will both use QUORUM
+user1 = session.execute(user_lookup_stmt, [user_id1])[0]
+user2 = session.execute(user_lookup_stmt, [user_id2])[0]
+
+
+

The second option is to create a BoundStatement from the +PreparedStatement and binding parameters and set a consistency +level on that:

+
# override the QUORUM default
+user3_lookup = user_lookup_stmt.bind([user_id3])
+user3_lookup.consistency_level = ConsistencyLevel.ALL
+user3 = session.execute(user3_lookup)
+
+
+
+
+

Speculative Execution

+

Speculative execution is a way to minimize latency by preemptively executing several +instances of the same query against different nodes. For more details about this +technique, see Speculative Execution with DataStax Drivers.

+

To enable speculative execution:

+
    +
  • Configure a SpeculativeExecutionPolicy with the ExecutionProfile

  • +
  • Mark your query as idempotent, which mean it can be applied multiple +times without changing the result of the initial application. +See Query Idempotence for more details.

  • +
+

Example:

+
from cassandra.cluster import Cluster, ExecutionProfile, EXEC_PROFILE_DEFAULT
+from cassandra.policies import ConstantSpeculativeExecutionPolicy
+from cassandra.query import SimpleStatement
+
+# Configure the speculative execution policy
+ep = ExecutionProfile(
+    speculative_execution_policy=ConstantSpeculativeExecutionPolicy(delay=.5, max_attempts=10)
+)
+cluster = Cluster(..., execution_profiles={EXEC_PROFILE_DEFAULT: ep})
+session = cluster.connect()
+
+# Mark the query idempotent
+query = SimpleStatement(
+    "UPDATE my_table SET list_col = [1] WHERE pk = 1",
+    is_idempotent=True
+)
+
+# Execute. A new query will be sent to the server every 0.5 second
+# until we receive a response, for a max number attempts of 10.
+session.execute(query)
+
+
+
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.26.2-scylla/index.html b/3.26.2-scylla/index.html new file mode 100644 index 0000000000..951dc39070 --- /dev/null +++ b/3.26.2-scylla/index.html @@ -0,0 +1,694 @@ + + + + + + + + + + + + + Python Driver for Scylla and Apache Cassandra® | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + + + +
+ +
+ +
+

Python Driver for Scylla and Apache Cassandra®

+

A Python client driver for Scylla. +This driver works exclusively with the Cassandra Query Language v3 (CQL3) +and Cassandra’s native protocol.

+

The driver supports Python 2.7, 3.5, 3.6, 3.7 and 3.8.

+

This driver is open source under the +Apache v2 License. +The source code for this driver can be found on GitHub.

+

Scylla Driver is a fork from DataStax Python Driver, including some non-breaking changes for Scylla optimization, with more updates planned.

+
+

Contents

+
+
Installation

How to install the driver.

+
+
Getting Started

A guide through the first steps of connecting to Scylla and executing queries

+
+
Scylla Specific Features

A list of feature available only on scylla-driver

+
+
Execution Profiles

An introduction to a more flexible way of configuring request execution

+
+
Lightweight Transactions (Compare-and-set)

Working with results of conditional requests

+
+
Object Mapper

Introduction to the integrated object mapper, cqlengine

+
+
Performance Notes

Tips for getting good performance.

+
+
Paging Large Queries

Notes on paging large query results

+
+
Security

An overview of the security features of the driver

+
+
Upgrading

A guide to upgrading versions of the driver

+
+
User Defined Types

Working with Scylla’s user-defined types (UDT)

+
+
Working with Dates and Times

Some discussion on the driver’s approach to working with timestamp, date, time types

+
+
ScyllaDB Cloud

Connect to ScyllaDB Cloud

+
+
ScyllaDB Cloud Serverless

Connect to ScyllaDB Cloud Serverless

+
+
CHANGELOG

Log of changes to the driver, organized by version.

+
+
Frequently Asked Questions

A collection of Frequently Asked Questions

+
+
API Documentation

The API documentation.

+
+
+
+
+
+
+

Getting Help

+

Visit the FAQ section in this documentation.

+

Please send questions to the Scylla user list.

+
+
+

Reporting Issues

+

Please report any bugs and make any feature requests on the Github project issues

+
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.26.2-scylla/installation.html b/3.26.2-scylla/installation.html new file mode 100644 index 0000000000..573a715eeb --- /dev/null +++ b/3.26.2-scylla/installation.html @@ -0,0 +1,865 @@ + + + + + + + + + + + + + Installation | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + + + +
+ +
+ +
+

Installation

+
+

Supported Platforms

+

Python 2.7, 3.5, 3.6, 3.7 and 3.8 are supported. Both CPython (the standard Python +implementation) and PyPy are supported and tested.

+

Linux, OSX, and Windows are supported.

+
+
+

Installation through pip

+

pip is the suggested tool for installing +packages. It will handle installing all Python dependencies for the driver at +the same time as the driver itself. To install the driver*:

+
pip install scylla-driver
+
+
+

You can use pip install --pre scylla-driver if you need to install a beta version.

+

*Note: if intending to use optional extensions, install the dependencies first. The driver may need to be reinstalled if dependencies are added after the initial installation.

+
+
+

Verifying your Installation

+

To check if the installation was successful, you can run:

+
python -c 'import cassandra; print cassandra.__version__'
+
+
+

It should print something like “3.22.0”.

+
+
+

(Optional) Graph

+

The driver provides an optional fluent graph API that depends on Apache TinkerPop (gremlinpython). It is +not installed by default. To be able to build Gremlin traversals, you need to install +the graph requirements:

+
pip install scylla-driver[graph]
+
+
+
+
+

(Optional) Compression Support

+

Compression can optionally be used for communication between the driver and +Cassandra. There are currently two supported compression algorithms: +snappy (in Cassandra 1.2+) and LZ4 (only in Cassandra 2.0+). If either is +available for the driver and Cassandra also supports it, it will +be used automatically.

+

For lz4 support:

+
pip install lz4
+
+
+

For snappy support:

+
pip install python-snappy
+
+
+

(If using a Debian Linux derivative such as Ubuntu, it may be easier to +just run apt-get install python-snappy.)

+
+
+

(Optional) Metrics Support

+

The driver has built-in support for capturing Cluster.metrics about +the queries you run. However, the scales library is required to +support this:

+
pip install scales
+
+
+
+

Speeding Up Installation

+

By default, installing the driver through pip uses a pre-compiled, platform-specific wheel when available. +If using a source distribution rather than a wheel, Cython is used to compile certain parts of the driver. +This makes those hot paths faster at runtime, but the Cython compilation +process can take a long time – as long as 10 minutes in some environments.

+

In environments where performance is less important, it may be worth it to +disable Cython as documented below. +You can also use CASS_DRIVER_BUILD_CONCURRENCY to increase the number of +threads used to build the driver and any C extensions:

+
$ # installing from source
+$ CASS_DRIVER_BUILD_CONCURRENCY=8 python setup.py install
+$ # installing from pip
+$ CASS_DRIVER_BUILD_CONCURRENCY=8 pip install scylla-driver
+
+
+
+
+

OSX Installation Error

+

If you’re installing on OSX and have XCode 5.1 installed, you may see an error like this:

+
clang: error: unknown argument: '-mno-fused-madd' [-Wunused-command-line-argument-hard-error-in-future]
+
+
+

To fix this, re-run the installation with an extra compilation flag:

+
ARCHFLAGS=-Wno-error=unused-command-line-argument-hard-error-in-future pip install scylla-driver
+
+
+
+
+
+

Windows Installation Notes

+

Installing the driver with extensions in Windows sometimes presents some challenges. A few notes about common +hang-ups:

+

Setup requires a compiler. When using Python 2, this is as simple as installing this package +(this link is also emitted during install if setuptools is unable to find the resources it needs). Depending on your +system settings, this package may install as a user-specific application. Make sure to install for everyone, or at least +as the user that will be building the Python environment.

+

It is also possible to run the build with your compiler of choice. Just make sure to have your environment setup with +the proper paths. Make sure the compiler target architecture matches the bitness of your Python runtime. +Perhaps the easiest way to do this is to run the build/install from a Visual Studio Command Prompt (a +shortcut installed with Visual Studio that sources the appropriate environment and presents a shell).

+
+
+

Manual Installation

+

You can always install the driver directly from a source checkout or tarball. +When installing manually, ensure the python dependencies are already +installed. You can find the list of dependencies in +requirements.txt.

+

Once the dependencies are installed, simply run:

+
python setup.py install
+
+
+
+
+

(Optional) Non-python Dependencies

+

The driver has several optional features that have non-Python dependencies.

+
+

C Extensions

+

By default, a number of extensions are compiled, providing faster hashing +for token-aware routing with the Murmur3Partitioner, +libev event loop integration, +and Cython optimized extensions.

+

When installing manually through setup.py, you can disable both with +the --no-extensions option, or selectively disable them with +with --no-murmur3, --no-libev, or --no-cython.

+

To compile the extensions, ensure that GCC and the Python headers are available.

+

On Ubuntu and Debian, this can be accomplished by running:

+
$ sudo apt-get install gcc python-dev
+
+
+

On RedHat and RedHat-based systems like CentOS and Fedora:

+
$ sudo yum install gcc python-devel
+
+
+

On OS X, homebrew installations of Python should provide the necessary headers.

+

See Windows Installation Notes for notes on configuring the build environment on Windows.

+
+

Cython-based Extensions

+

By default, this package uses Cython to optimize core modules and build custom extensions. +This is not a hard requirement, but is engaged by default to build extensions offering better performance than the +pure Python implementation.

+

This is a costly build phase, especially in clean environments where the Cython compiler must be built +This build phase can be avoided using the build switch, or an environment variable:

+
python setup.py install --no-cython
+
+
+

Alternatively, an environment variable can be used to switch this option regardless of +context:

+
CASS_DRIVER_NO_CYTHON=1 <your script here>
+- or, to disable all extensions:
+CASS_DRIVER_NO_EXTENSIONS=1 <your script here>
+
+
+

This method is required when using pip, which provides no other way of injecting user options in a single command:

+
CASS_DRIVER_NO_CYTHON=1 pip install scylla-driver
+CASS_DRIVER_NO_CYTHON=1 sudo -E pip install ~/python-driver
+
+
+

The environment variable is the preferred option because it spans all invocations of setup.py, and will +prevent Cython from being materialized as a setup requirement.

+

If your sudo configuration does not allow SETENV, you must push the option flag down via pip. However, pip +applies these options to all dependencies (which break on the custom flag). Therefore, you must first install +dependencies, then use install-option:

+
sudo pip install six futures
+sudo pip install --install-option="--no-cython"
+
+
+
+
+
+

libev support

+

The driver currently uses Python’s asyncore module for its default +event loop. For better performance, libev is also supported through +a C extension.

+

If you’re on Linux, you should be able to install libev +through a package manager. For example, on Debian/Ubuntu:

+
$ sudo apt-get install libev4 libev-dev
+
+
+

On RHEL/CentOS/Fedora:

+
$ sudo yum install libev libev-devel
+
+
+

If you’re on Mac OS X, you should be able to install libev +through Homebrew. For example, on Mac OS X:

+
$ brew install libev
+
+
+

The libev extension is not built for Windows (the build process is complex, and the Windows implementation uses +select anyway).

+

If successful, you should be able to build and install the extension +(just using setup.py build or setup.py install) and then use +the libev event loop by doing the following:

+
>>> from cassandra.io.libevreactor import LibevConnection
+>>> from cassandra.cluster import Cluster
+
+>>> cluster = Cluster()
+>>> cluster.connection_class = LibevConnection
+>>> session = cluster.connect()
+
+
+
+
+
+

(Optional) Configuring SSL

+

Andrew Mussey has published a thorough guide on +Using SSL with the DataStax Python driver.

+
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.26.2-scylla/lwt.html b/3.26.2-scylla/lwt.html new file mode 100644 index 0000000000..cb00b62276 --- /dev/null +++ b/3.26.2-scylla/lwt.html @@ -0,0 +1,725 @@ + + + + + + + + + + + + + Lightweight Transactions (Compare-and-set) | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + + + +
+ +
+ +
+

Lightweight Transactions (Compare-and-set)

+

Lightweight Transactions (LWTs) are mostly pass-through CQL for the driver. However, +the server returns some specialized results indicating the outcome and optional state +preceding the transaction.

+

For pertinent execution parameters, see Statement.serial_consistency_level.

+

This section discusses working with specialized result sets returned by the server for LWTs, +and how to work with them using the driver.

+
+

Specialized Results

+

The result returned from a LWT request is always a single row result. It will always have +prepended a special column named [applied]. How this value appears in your results depends +on the row factory in use. See below for examples.

+

The value of this [applied] column is boolean value indicating whether or not the transaction was applied. +If True, it is the only column in the result. If False, the additional columns depend on the LWT operation being +executed:

+
    +
  • When using a UPDATE ... IF "col" = ... clause, the result will contain the [applied] column, plus the existing columns +and values for any columns in the IF clause (and thus the value that caused the transaction to fail).

  • +
  • When using INSERT ... IF NOT EXISTS, the result will contain the [applied] column, plus all columns and values +of the existing row that rejected the transaction.

  • +
  • UPDATE .. IF EXISTS never has additional columns, regardless of [applied] status.

  • +
+

How the [applied] column manifests depends on the row factory in use. Considering the following (initially empty) table:

+
CREATE TABLE test.t (
+    k int PRIMARY KEY,
+    v int,
+    x int
+)
+
+
+

… the following sections show the expected result for a number of example statements, using the three base row factories.

+
+

named_tuple_factory (default)

+

The name [applied] is not a valid Python identifier, so the square brackets are actually removed +from the attribute for the resulting namedtuple. The row always has a boolean column applied in position 0:

+
>>> session.execute("INSERT INTO t (k,v) VALUES (0,0) IF NOT EXISTS")
+Row(applied=True)
+
+>>> session.execute("INSERT INTO t (k,v) VALUES (0,0) IF NOT EXISTS")
+Row(applied=False, k=0, v=0, x=None)
+
+>>> session.execute("UPDATE t SET v = 1, x = 2 WHERE k = 0 IF v =0")
+Row(applied=True)
+
+>>> session.execute("UPDATE t SET v = 1, x = 2 WHERE k = 0 IF v =0 AND x = 1")
+Row(applied=False, v=1, x=2)
+
+
+
+
+

tuple_factory

+

This return type does not refer to names, but the boolean value applied is always present in position 0:

+
>>> session.execute("INSERT INTO t (k,v) VALUES (0,0) IF NOT EXISTS")
+(True,)
+
+>>> session.execute("INSERT INTO t (k,v) VALUES (0,0) IF NOT EXISTS")
+(False, 0, 0, None)
+
+>>> session.execute("UPDATE t SET v = 1, x = 2 WHERE k = 0 IF v =0")
+(True,)
+
+>>> session.execute("UPDATE t SET v = 1, x = 2 WHERE k = 0 IF v =0 AND x = 1")
+(False, 1, 2)
+
+
+
+
+

dict_factory

+

The retuned dict contains the [applied] key:

+
>>> session.execute("INSERT INTO t (k,v) VALUES (0,0) IF NOT EXISTS")
+{u'[applied]': True}
+
+>>> session.execute("INSERT INTO t (k,v) VALUES (0,0) IF NOT EXISTS")
+{u'x': 2, u'[applied]': False, u'v': 1}
+
+>>> session.execute("UPDATE t SET v = 1, x = 2 WHERE k = 0 IF v =0")
+{u'x': None, u'[applied]': False, u'k': 0, u'v': 0}
+
+>>> session.execute("UPDATE t SET v = 1, x = 2 WHERE k = 0 IF v =0 AND x = 1")
+{u'[applied]': True}
+
+
+
+
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.26.2-scylla/object-mapper.html b/3.26.2-scylla/object-mapper.html new file mode 100644 index 0000000000..22849c9f17 --- /dev/null +++ b/3.26.2-scylla/object-mapper.html @@ -0,0 +1,722 @@ + + + + + + + + + + + + + Object Mapper | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + + + +
+ +
+ +
+

Object Mapper

+

cqlengine is the Cassandra CQL 3 Object Mapper packaged with this driver

+

Jump to Getting Started

+
+

Contents

+
+
Upgrade Guide

For migrating projects from legacy cqlengine, to the integrated product

+
+
Models

Examples defining models, and mapping them to tables

+
+
Making Queries

Overview of query sets and filtering

+
+
Batch Queries

Working with batch mutations

+
+
Connections

Working with multiple sessions

+
+
API Documentation

Index of API documentation

+
+
Third party integrations

High-level examples in Celery and uWSGI

+
+
+

Frequently Asked Questions

+
+
+
+
+

Getting Started

+
import uuid
+from cassandra.cqlengine import columns
+from cassandra.cqlengine import connection
+from datetime import datetime
+from cassandra.cqlengine.management import sync_table
+from cassandra.cqlengine.models import Model
+
+#first, define a model
+class ExampleModel(Model):
+    example_id      = columns.UUID(primary_key=True, default=uuid.uuid4)
+    example_type    = columns.Integer(index=True)
+    created_at      = columns.DateTime()
+    description     = columns.Text(required=False)
+
+#next, setup the connection to your cassandra server(s)...
+# see http://datastax.github.io/python-driver/api/cassandra/cluster.html for options
+# the list of hosts will be passed to create a Cluster() instance
+connection.setup(['127.0.0.1'], "cqlengine", protocol_version=3)
+
+#...and create your CQL table
+>>> sync_table(ExampleModel)
+
+#now we can create some rows:
+>>> em1 = ExampleModel.create(example_type=0, description="example1", created_at=datetime.now())
+>>> em2 = ExampleModel.create(example_type=0, description="example2", created_at=datetime.now())
+>>> em3 = ExampleModel.create(example_type=0, description="example3", created_at=datetime.now())
+>>> em4 = ExampleModel.create(example_type=0, description="example4", created_at=datetime.now())
+>>> em5 = ExampleModel.create(example_type=1, description="example5", created_at=datetime.now())
+>>> em6 = ExampleModel.create(example_type=1, description="example6", created_at=datetime.now())
+>>> em7 = ExampleModel.create(example_type=1, description="example7", created_at=datetime.now())
+>>> em8 = ExampleModel.create(example_type=1, description="example8", created_at=datetime.now())
+
+#and now we can run some queries against our table
+>>> ExampleModel.objects.count()
+8
+>>> q = ExampleModel.objects(example_type=1)
+>>> q.count()
+4
+>>> for instance in q:
+>>>     print instance.description
+example5
+example6
+example7
+example8
+
+#here we are applying additional filtering to an existing query
+#query objects are immutable, so calling filter returns a new
+#query object
+>>> q2 = q.filter(example_id=em5.example_id)
+
+>>> q2.count()
+1
+>>> for instance in q2:
+>>>     print instance.description
+example5
+
+
+
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.26.2-scylla/objects.inv b/3.26.2-scylla/objects.inv new file mode 100644 index 0000000000..0ea4f4d635 Binary files /dev/null and b/3.26.2-scylla/objects.inv differ diff --git a/3.26.2-scylla/performance.html b/3.26.2-scylla/performance.html new file mode 100644 index 0000000000..244b27c48a --- /dev/null +++ b/3.26.2-scylla/performance.html @@ -0,0 +1,676 @@ + + + + + + + + + + + + + Performance Notes | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + + + +
+ +
+ +
+

Performance Notes

+

The Python driver for Cassandra offers several methods for executing queries. +You can synchronously block for queries to complete using +Session.execute(), you can obtain asynchronous request futures through +Session.execute_async(), and you can attach a callback to the future +with ResponseFuture.add_callback().

+

Examples of multiple request patterns can be found in the benchmark scripts included in the driver project.

+

The choice of execution pattern will depend on the application context. For applications dealing with multiple +requests in a given context, the recommended pattern is to use concurrent asynchronous +requests with callbacks. For many use cases, you don’t need to implement this pattern yourself. +cassandra.concurrent.execute_concurrent() and cassandra.concurrent.execute_concurrent_with_args() +provide this pattern with a synchronous API and tunable concurrency.

+

Due to the GIL and limited concurrency, the driver can become CPU-bound pretty quickly. The sections below +discuss further runtime and design considerations for mitigating this limitation.

+
+

PyPy

+

PyPy is an alternative Python runtime which uses a JIT compiler to +reduce CPU consumption. This leads to a huge improvement in the driver performance, +more than doubling throughput for many workloads.

+
+
+

Cython Extensions

+

Cython is an optimizing compiler and language that can be used to compile the core files and +optional extensions for the driver. Cython is not a strict dependency, but the extensions will be built by default.

+

See Installation for details on controlling this build.

+
+
+

multiprocessing

+

All of the patterns discussed above may be used over multiple processes using the +multiprocessing +module. Multiple processes will scale better than multiple threads, so if high throughput is your goal, +consider this option.

+

Be sure to never share any Cluster, Session, +or ResponseFuture objects across multiple processes. These +objects should all be created after forking the process, not before.

+

For further discussion and simple examples using the driver with multiprocessing, +see this blog post.

+
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.26.2-scylla/py-modindex.html b/3.26.2-scylla/py-modindex.html new file mode 100644 index 0000000000..5ada38f9e2 --- /dev/null +++ b/3.26.2-scylla/py-modindex.html @@ -0,0 +1,609 @@ + + + + + + + + + + + + + Python Module Index | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + + + +
+ +
+ + + +
+ + + + + +
+ + +
+
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.26.2-scylla/query-paging.html b/3.26.2-scylla/query-paging.html new file mode 100644 index 0000000000..83ed96388c --- /dev/null +++ b/3.26.2-scylla/query-paging.html @@ -0,0 +1,730 @@ + + + + + + + + + + + + + Paging Large Queries | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + + + +
+ +
+ +
+

Paging Large Queries

+

Cassandra 2.0+ offers support for automatic query paging. Starting with +version 2.0 of the driver, if protocol_version is greater than +2 (it is by default), queries returning large result sets will be +automatically paged.

+
+

Controlling the Page Size

+

By default, Session.default_fetch_size controls how many rows will +be fetched per page. This can be overridden per-query by setting +fetch_size on a Statement. By default, each page +will contain at most 5000 rows.

+
+
+

Handling Paged Results

+

Whenever the number of result rows for are query exceed the page size, an +instance of PagedResult will be returned instead of a normal +list. This class implements the iterator interface, so you can treat +it like a normal iterator over rows:

+
from cassandra.query import SimpleStatement
+query = "SELECT * FROM users"  # users contains 100 rows
+statement = SimpleStatement(query, fetch_size=10)
+for user_row in session.execute(statement):
+    process_user(user_row)
+
+
+

Whenever there are no more rows in the current page, the next page will +be fetched transparently. However, note that it is possible for +an Exception to be raised while fetching the next page, just +like you might see on a normal call to session.execute().

+

If you use Session.execute_async() along with, +ResponseFuture.result(), the first page will be fetched before +result() returns, but latter pages will be +transparently fetched synchronously while iterating the result.

+
+
+

Handling Paged Results with Callbacks

+

If callbacks are attached to a query that returns a paged result, +the callback will be called once per page with a normal list of rows.

+

Use ResponseFuture.has_more_pages and +ResponseFuture.start_fetching_next_page() to continue fetching +pages. For example:

+
class PagedResultHandler(object):
+
+    def __init__(self, future):
+        self.error = None
+        self.finished_event = Event()
+        self.future = future
+        self.future.add_callbacks(
+            callback=self.handle_page,
+            errback=self.handle_err)
+
+    def handle_page(self, rows):
+        for row in rows:
+            process_row(row)
+
+        if self.future.has_more_pages:
+            self.future.start_fetching_next_page()
+        else:
+            self.finished_event.set()
+
+    def handle_error(self, exc):
+        self.error = exc
+        self.finished_event.set()
+
+future = session.execute_async("SELECT * FROM users")
+handler = PagedResultHandler(future)
+handler.finished_event.wait()
+if handler.error:
+    raise handler.error
+
+
+
+
+

Resume Paged Results

+

You can resume the pagination when executing a new query by using the ResultSet.paging_state. This can be useful if you want to provide some stateless pagination capabilities to your application (ie. via http). For example:

+
from cassandra.query import SimpleStatement
+query = "SELECT * FROM users"
+statement = SimpleStatement(query, fetch_size=10)
+results = session.execute(statement)
+
+# save the paging_state somewhere and return current results
+web_session['paging_state'] = results.paging_state
+
+
+# resume the pagination sometime later...
+statement = SimpleStatement(query, fetch_size=10)
+ps = web_session['paging_state']
+results = session.execute(statement, paging_state=ps)
+
+
+
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.26.2-scylla/scylla-cloud-serverless.html b/3.26.2-scylla/scylla-cloud-serverless.html new file mode 100644 index 0000000000..cfe907bd96 --- /dev/null +++ b/3.26.2-scylla/scylla-cloud-serverless.html @@ -0,0 +1,668 @@ + + + + + + + + + + + + + ScyllaDB Cloud Serverless | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + + + +
+ +
+ +
+

ScyllaDB Cloud Serverless

+

With ScyllaDB Cloud, you can deploy serverless databases. +The Python driver allows you to connect to a serverless database by utilizing the connection bundle you can download via the Connect>Python tab in the Cloud application. +The connection bundle is a YAML file with connection and credential information for your cluster.

+

Connecting to a ScyllaDB Cloud serverless database is very similar to a standard connection to a ScyllaDB database.

+

Here’s a short program that connects to a ScyllaDB Cloud serverless database and prints metadata about the cluster:

+
from cassandra.cluster import Cluster, ExecutionProfile, EXEC_PROFILE_DEFAULT
+from cassandra.policies import DCAwareRoundRobinPolicy, TokenAwarePolicy
+
+PATH_TO_BUNDLE_YAML = '/file/downloaded/from/cloud/connect-bundle.yaml'
+
+
+def get_cluster():
+    profile = ExecutionProfile(
+        load_balancing_policy=TokenAwarePolicy(
+            DCAwareRoundRobinPolicy(local_dc='us-east-1')
+        )
+    )
+
+    return Cluster(
+        execution_profiles={EXEC_PROFILE_DEFAULT: profile},
+        scylla_cloud=PATH_TO_BUNDLE_YAML,
+    )
+
+
+print('Connecting to cluster')
+cluster = get_cluster()
+session = cluster.connect()
+
+print('Connected to cluster', cluster.metadata.cluster_name)
+
+print('Getting metadata')
+for host in cluster.metadata.all_hosts():
+    print('Datacenter: {}; Host: {}; Rack: {}'.format(
+        host.datacenter, host.address, host.rack)
+    )
+
+cluster.shutdown()
+
+
+

By providing the scylla_cloud parameter to the Cluster constructor, +the driver can set up the connection based on the endpoint and credential information +stored in your downloaded ScyllaDB Cloud Serverless connection bundle.

+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.26.2-scylla/scylla-cloud.html b/3.26.2-scylla/scylla-cloud.html new file mode 100644 index 0000000000..2aa9e75589 --- /dev/null +++ b/3.26.2-scylla/scylla-cloud.html @@ -0,0 +1,628 @@ + + + + + + + + + + + + + ScyllaDB Cloud | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + + + +
+ +
+ +
+

ScyllaDB Cloud

+

To connect to a ScyllaDB Cloud cluster, go to the Cluster Connect page, Python example. +For best performance, make sure to use the Scylla Driver.

+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.26.2-scylla/scylla-specific.html b/3.26.2-scylla/scylla-specific.html new file mode 100644 index 0000000000..f0322313db --- /dev/null +++ b/3.26.2-scylla/scylla-specific.html @@ -0,0 +1,737 @@ + + + + + + + + + + + + + Scylla Specific Features | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + + + +
+ +
+ +
+

Scylla Specific Features

+
+

Shard Awareness

+

scylla-driver is shard aware and contains extensions that work with the TokenAwarePolicy supported by Scylla 2.3 and onwards. Using this policy, the driver can select a connection to a particular shard based on the shard’s token. +As a result, latency is significantly reduced because there is no need to pass data between the shards.

+

Details on the scylla cql protocol extensions +https://github.com/scylladb/scylla/blob/master/docs/dev/protocol-extensions.md#intranode-sharding

+

For using it you only need to enable TokenAwarePolicy on the Cluster

+

See the configuration of native_shard_aware_transport_port and native_shard_aware_transport_port_ssl on scylla.yaml: +https://github.com/scylladb/scylla/blob/master/docs/dev/protocols.md#cql-client-protocol

+
from cassandra.cluster import Cluster
+from cassandra.policies import TokenAwarePolicy, RoundRobinPolicy
+
+cluster = Cluster(load_balancing_policy=TokenAwarePolicy(RoundRobinPolicy()))
+
+
+
+
+

New Cluster Helpers

+
    +
  • shard_aware_options

    +

    Setting it to dict(disable=True) would disable the shard aware functionally, for cases favoring once connection per host (example, lots of processes connecting from one client host, generating a big load of connections

    +

    Other option is to configure scylla by setting enable_shard_aware_drivers: false on scylla.yaml.

    +
  • +
+
from cassandra.cluster import Cluster
+
+cluster = Cluster(shard_aware_options=dict(disable=True))
+session = cluster.connect()
+
+assert not cluster.is_shard_aware(), "Shard aware should be disabled"
+
+# or just disable the shard aware port logic
+cluster = Cluster(shard_aware_options=dict(disable_shardaware_port=True))
+session = cluster.connect()
+
+
+
    +
  • cluster.is_shard_aware()

    +

    New method available on Cluster allowing to check whether the remote cluster supports shard awareness (bool)

    +
  • +
+
from cassandra.cluster import Cluster
+
+cluster = Cluster()
+session = cluster.connect()
+
+if cluster.is_shard_aware():
+    print("connected to a scylla cluster")
+
+
+
    +
  • cluster.shard_aware_stats()

    +

    New method available on Cluster allowing to check the status of shard aware connections to all available hosts (dict)

    +
  • +
+
from cassandra.cluster import Cluster
+
+cluster = Cluster()
+session = cluster.connect()
+
+stats = cluster.shard_aware_stats()
+if all([v["shards_count"] == v["connected"] for v in stats.values()]):
+    print("successfully connected to all shards of all scylla nodes")
+
+
+
+
+

New Table Attributes

+
    +
  • in_memory flag

    +

    New flag available on TableMetadata.options to indicate that it is an In Memory table

    +
  • +
+
+

Note

+

in memory tables is a feature existing only in Scylla Enterprise

+
+
from cassandra.cluster import Cluster
+
+cluster = Cluster()
+session = cluster.connect()
+session.execute("""
+    CREATE KEYSPACE IF NOT EXISTS keyspace1
+    WITH replication = {'class': 'SimpleStrategy', 'replication_factor': '1'};
+""")
+
+session.execute("""
+    CREATE TABLE IF NOT EXISTS keyspace1.standard1 (
+        key blob PRIMARY KEY,
+        "C0" blob
+    ) WITH in_memory=true AND compaction={'class': 'InMemoryCompactionStrategy'}
+""")
+
+cluster.refresh_table_metadata("keyspace1", "standard1")
+assert cluster.metadata.keyspaces["keyspace1"].tables["standard1"].options["in_memory"] == True
+
+
+
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.26.2-scylla/search.html b/3.26.2-scylla/search.html new file mode 100644 index 0000000000..0fc56e5a4a --- /dev/null +++ b/3.26.2-scylla/search.html @@ -0,0 +1,612 @@ + + + + + + + + + + + + + Search | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + + + + + + + +
+ + + + + +
+ + +
+
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.26.2-scylla/searchindex.js b/3.26.2-scylla/searchindex.js new file mode 100644 index 0000000000..d4a52413be --- /dev/null +++ b/3.26.2-scylla/searchindex.js @@ -0,0 +1 @@ +Search.setIndex({docnames:["CHANGELOG","api/cassandra","api/cassandra/auth","api/cassandra/cluster","api/cassandra/concurrent","api/cassandra/connection","api/cassandra/cqlengine/columns","api/cassandra/cqlengine/connection","api/cassandra/cqlengine/management","api/cassandra/cqlengine/models","api/cassandra/cqlengine/query","api/cassandra/cqlengine/usertype","api/cassandra/datastax/graph/fluent/index","api/cassandra/datastax/graph/fluent/predicates","api/cassandra/datastax/graph/fluent/query","api/cassandra/datastax/graph/index","api/cassandra/decoder","api/cassandra/encoder","api/cassandra/graph","api/cassandra/io/asyncioreactor","api/cassandra/io/asyncorereactor","api/cassandra/io/eventletreactor","api/cassandra/io/geventreactor","api/cassandra/io/libevreactor","api/cassandra/io/twistedreactor","api/cassandra/metadata","api/cassandra/metrics","api/cassandra/policies","api/cassandra/pool","api/cassandra/protocol","api/cassandra/query","api/cassandra/timestamps","api/cassandra/util","api/index","cqlengine/batches","cqlengine/connections","cqlengine/faq","cqlengine/models","cqlengine/queryset","cqlengine/third-party","cqlengine/upgrade-guide","dates-and-times","execution-profiles","faq","getting-started","index","installation","lwt","object-mapper","performance","query-paging","scylla-cloud","scylla-cloud-serverless","scylla-specific","security","upgrading","user-defined-types"],envversion:{"sphinx.domains.c":2,"sphinx.domains.changeset":1,"sphinx.domains.citation":1,"sphinx.domains.cpp":4,"sphinx.domains.index":1,"sphinx.domains.javascript":2,"sphinx.domains.math":2,"sphinx.domains.python":3,"sphinx.domains.rst":2,"sphinx.domains.std":2,"sphinx.ext.todo":2,sphinx:56},filenames:["CHANGELOG.rst","api/cassandra.rst","api/cassandra/auth.rst","api/cassandra/cluster.rst","api/cassandra/concurrent.rst","api/cassandra/connection.rst","api/cassandra/cqlengine/columns.rst","api/cassandra/cqlengine/connection.rst","api/cassandra/cqlengine/management.rst","api/cassandra/cqlengine/models.rst","api/cassandra/cqlengine/query.rst","api/cassandra/cqlengine/usertype.rst","api/cassandra/datastax/graph/fluent/index.rst","api/cassandra/datastax/graph/fluent/predicates.rst","api/cassandra/datastax/graph/fluent/query.rst","api/cassandra/datastax/graph/index.rst","api/cassandra/decoder.rst","api/cassandra/encoder.rst","api/cassandra/graph.rst","api/cassandra/io/asyncioreactor.rst","api/cassandra/io/asyncorereactor.rst","api/cassandra/io/eventletreactor.rst","api/cassandra/io/geventreactor.rst","api/cassandra/io/libevreactor.rst","api/cassandra/io/twistedreactor.rst","api/cassandra/metadata.rst","api/cassandra/metrics.rst","api/cassandra/policies.rst","api/cassandra/pool.rst","api/cassandra/protocol.rst","api/cassandra/query.rst","api/cassandra/timestamps.rst","api/cassandra/util.rst","api/index.rst","cqlengine/batches.rst","cqlengine/connections.rst","cqlengine/faq.rst","cqlengine/models.rst","cqlengine/queryset.rst","cqlengine/third-party.rst","cqlengine/upgrade-guide.rst","dates-and-times.rst","execution-profiles.rst","faq.rst","getting-started.rst","index.rst","installation.rst","lwt.rst","object-mapper.rst","performance.rst","query-paging.rst","scylla-cloud.rst","scylla-cloud-serverless.rst","scylla-specific.rst","security.rst","upgrading.rst","user-defined-types.rst"],objects:{"":[[1,0,0,"-","cassandra"]],"cassandra.AlreadyExists":[[1,2,1,"","keyspace"],[1,2,1,"","table"]],"cassandra.ConsistencyLevel":[[1,2,1,"","ALL"],[1,2,1,"","ANY"],[1,2,1,"","EACH_QUORUM"],[1,2,1,"","LOCAL_ONE"],[1,2,1,"","LOCAL_QUORUM"],[1,2,1,"","LOCAL_SERIAL"],[1,2,1,"","ONE"],[1,2,1,"","QUORUM"],[1,2,1,"","SERIAL"],[1,2,1,"","THREE"],[1,2,1,"","TWO"]],"cassandra.CoordinationFailure":[[1,2,1,"","consistency"],[1,2,1,"","error_code_map"],[1,2,1,"","failures"],[1,2,1,"","received_responses"],[1,2,1,"","required_responses"]],"cassandra.FunctionFailure":[[1,2,1,"","arg_types"],[1,2,1,"","function"],[1,2,1,"","keyspace"]],"cassandra.OperationTimedOut":[[1,2,1,"","errors"],[1,2,1,"","last_host"]],"cassandra.ProtocolVersion":[[1,2,1,"","BETA_VERSIONS"],[1,2,1,"","DSE_V1"],[1,2,1,"","DSE_V2"],[1,2,1,"","MAX_SUPPORTED"],[1,2,1,"","MIN_SUPPORTED"],[1,2,1,"","SUPPORTED_VERSIONS"],[1,2,1,"","V1"],[1,2,1,"","V2"],[1,2,1,"","V3"],[1,2,1,"","V4"],[1,2,1,"","V5"],[1,2,1,"","V6"],[1,4,1,"","get_lower_supported"]],"cassandra.ReadFailure":[[1,2,1,"","data_retrieved"]],"cassandra.ReadTimeout":[[1,2,1,"","data_retrieved"]],"cassandra.Timeout":[[1,2,1,"","consistency"],[1,2,1,"","received_responses"],[1,2,1,"","required_responses"]],"cassandra.Unavailable":[[1,2,1,"","alive_replicas"],[1,2,1,"","consistency"],[1,2,1,"","required_replicas"]],"cassandra.UserAggregateDescriptor":[[1,2,1,"","argument_types"],[1,2,1,"","name"],[1,5,1,"","signature"]],"cassandra.UserFunctionDescriptor":[[1,2,1,"","argument_types"],[1,2,1,"","name"],[1,5,1,"","signature"]],"cassandra.WriteFailure":[[1,2,1,"","write_type"]],"cassandra.WriteTimeout":[[1,2,1,"","write_type"]],"cassandra.auth":[[2,3,1,"","AuthProvider"],[2,3,1,"","Authenticator"],[2,3,1,"","PlainTextAuthProvider"],[2,3,1,"","PlainTextAuthenticator"],[2,3,1,"","SaslAuthProvider"],[2,3,1,"","SaslAuthenticator"]],"cassandra.auth.AuthProvider":[[2,4,1,"","new_authenticator"]],"cassandra.auth.Authenticator":[[2,4,1,"","evaluate_challenge"],[2,4,1,"","initial_response"],[2,4,1,"","on_authentication_success"],[2,2,1,"","server_authenticator_class"]],"cassandra.auth.PlainTextAuthProvider":[[2,4,1,"","new_authenticator"]],"cassandra.auth.PlainTextAuthenticator":[[2,4,1,"","evaluate_challenge"]],"cassandra.auth.SaslAuthProvider":[[2,4,1,"","new_authenticator"]],"cassandra.auth.SaslAuthenticator":[[2,4,1,"","evaluate_challenge"],[2,4,1,"","initial_response"]],"cassandra.cluster":[[3,3,1,"","Cluster"],[3,6,1,"","EXEC_PROFILE_DEFAULT"],[3,6,1,"","EXEC_PROFILE_GRAPH_ANALYTICS_DEFAULT"],[3,6,1,"","EXEC_PROFILE_GRAPH_DEFAULT"],[3,6,1,"","EXEC_PROFILE_GRAPH_SYSTEM_DEFAULT"],[3,3,1,"","ExecutionProfile"],[3,3,1,"","GraphAnalyticsExecutionProfile"],[3,3,1,"","GraphExecutionProfile"],[3,1,1,"","NoHostAvailable"],[3,1,1,"","QueryExhausted"],[3,3,1,"","ResponseFuture"],[3,3,1,"","ResultSet"],[3,3,1,"","Session"],[3,1,1,"","UserTypeDoesNotExist"]],"cassandra.cluster.Cluster":[[3,4,1,"","add_execution_profile"],[3,2,1,"","address_translator"],[3,2,1,"","auth_provider"],[3,2,1,"","cloud"],[3,2,1,"","compression"],[3,4,1,"","connect"],[3,2,1,"","connect_timeout"],[3,2,1,"","connection_class"],[3,2,1,"","contact_points"],[3,2,1,"","control_connection_timeout"],[3,2,1,"","conviction_policy_factory"],[3,2,1,"","cql_version"],[3,2,1,"","default_retry_policy"],[3,2,1,"","endpoint_factory"],[3,4,1,"","get_control_connection_host"],[3,4,1,"","get_core_connections_per_host"],[3,4,1,"","get_max_connections_per_host"],[3,4,1,"","get_max_requests_per_connection"],[3,4,1,"","get_min_requests_per_connection"],[3,2,1,"","idle_heartbeat_interval"],[3,2,1,"","idle_heartbeat_timeout"],[3,2,1,"","load_balancing_policy"],[3,2,1,"","max_schema_agreement_wait"],[3,2,1,"","metadata"],[3,2,1,"","metrics"],[3,2,1,"","metrics_enabled"],[3,2,1,"","port"],[3,2,1,"","prepare_on_all_hosts"],[3,2,1,"","protocol_version"],[3,2,1,"","reconnection_policy"],[3,4,1,"","refresh_keyspace_metadata"],[3,4,1,"","refresh_nodes"],[3,4,1,"","refresh_schema_metadata"],[3,4,1,"","refresh_table_metadata"],[3,4,1,"","refresh_user_aggregate_metadata"],[3,4,1,"","refresh_user_function_metadata"],[3,4,1,"","refresh_user_type_metadata"],[3,4,1,"","register_listener"],[3,4,1,"","register_user_type"],[3,2,1,"","reprepare_on_up"],[3,2,1,"","schema_event_refresh_window"],[3,2,1,"","schema_metadata_enabled"],[3,4,1,"","set_core_connections_per_host"],[3,4,1,"","set_max_connections_per_host"],[3,4,1,"","set_max_requests_per_connection"],[3,4,1,"","set_meta_refresh_enabled"],[3,4,1,"","set_min_requests_per_connection"],[3,4,1,"","shutdown"],[3,2,1,"","sockopts"],[3,2,1,"","ssl_context"],[3,2,1,"","ssl_options"],[3,2,1,"","status_event_refresh_window"],[3,2,1,"","timestamp_generator"],[3,2,1,"","token_metadata_enabled"],[3,2,1,"","topology_event_refresh_window"],[3,4,1,"","unregister_listener"]],"cassandra.cluster.ExecutionProfile":[[3,2,1,"","consistency_level"],[3,4,1,"","row_factory"]],"cassandra.cluster.ResponseFuture":[[3,4,1,"","add_callback"],[3,4,1,"","add_errback"],[3,2,1,"","custom_payload"],[3,4,1,"","get_all_query_traces"],[3,4,1,"","get_query_trace"],[3,2,1,"","has_more_pages"],[3,2,1,"","is_schema_agreed"],[3,2,1,"","query"],[3,4,1,"","result"],[3,4,1,"","start_fetching_next_page"],[3,2,1,"","warnings"]],"cassandra.cluster.ResultSet":[[3,4,1,"","all"],[3,5,1,"","current_rows"],[3,4,1,"","fetch_next_page"],[3,4,1,"","get_all_query_traces"],[3,4,1,"","get_query_trace"],[3,5,1,"","has_more_pages"],[3,4,1,"","one"],[3,5,1,"","paging_state"],[3,5,1,"","was_applied"]],"cassandra.cluster.Session":[[3,4,1,"","add_request_init_listener"],[3,2,1,"","client_protocol_handler"],[3,2,1,"","default_consistency_level"],[3,2,1,"","default_fetch_size"],[3,2,1,"","default_serial_consistency_level"],[3,2,1,"","default_timeout"],[3,2,1,"","encoder"],[3,4,1,"","execute"],[3,4,1,"","execute_async"],[3,4,1,"","execute_graph"],[3,4,1,"","execute_graph_async"],[3,4,1,"","execution_profile_clone_update"],[3,4,1,"","get_execution_profile"],[3,4,1,"","prepare"],[3,4,1,"","remove_request_init_listener"],[3,2,1,"","row_factory"],[3,4,1,"","set_keyspace"],[3,4,1,"","shutdown"],[3,2,1,"","timestamp_generator"],[3,2,1,"","use_client_timestamp"]],"cassandra.concurrent":[[4,7,1,"","execute_concurrent"],[4,7,1,"","execute_concurrent_with_args"]],"cassandra.connection":[[5,1,1,"","ConnectionBusy"],[5,1,1,"","ConnectionException"],[5,1,1,"","ConnectionShutdown"],[5,3,1,"","EndPoint"],[5,3,1,"","EndPointFactory"],[5,1,1,"","ProtocolError"],[5,3,1,"","SniEndPoint"],[5,3,1,"","SniEndPointFactory"],[5,3,1,"","UnixSocketEndPoint"]],"cassandra.connection.EndPoint":[[5,5,1,"","address"],[5,5,1,"","port"],[5,4,1,"","resolve"],[5,5,1,"","socket_family"],[5,5,1,"","ssl_options"]],"cassandra.connection.EndPointFactory":[[5,4,1,"","configure"],[5,4,1,"","create"]],"cassandra.cqlengine":[[6,0,0,"-","columns"],[7,0,0,"-","connection"],[8,0,0,"-","management"],[9,0,0,"-","models"],[10,0,0,"-","query"],[11,0,0,"-","usertype"]],"cassandra.cqlengine.columns":[[6,3,1,"","Ascii"],[6,3,1,"","BigInt"],[6,3,1,"","Blob"],[6,3,1,"","Boolean"],[6,2,1,"","Bytes"],[6,3,1,"","Column"],[6,3,1,"","Counter"],[6,3,1,"","Date"],[6,3,1,"","DateTime"],[6,3,1,"","Decimal"],[6,3,1,"","Double"],[6,3,1,"","Float"],[6,3,1,"","Integer"],[6,3,1,"","List"],[6,3,1,"","Map"],[6,3,1,"","Set"],[6,3,1,"","SmallInt"],[6,3,1,"","Text"],[6,3,1,"","Time"],[6,3,1,"","TimeUUID"],[6,3,1,"","TinyInt"],[6,3,1,"","UUID"],[6,3,1,"","UserDefinedType"],[6,3,1,"","VarInt"]],"cassandra.cqlengine.columns.Column":[[6,2,1,"","clustering_order"],[6,2,1,"","custom_index"],[6,2,1,"","db_field"],[6,2,1,"","default"],[6,2,1,"","discriminator_column"],[6,2,1,"","index"],[6,2,1,"","partition_key"],[6,2,1,"","primary_key"],[6,2,1,"","required"],[6,2,1,"","static"]],"cassandra.cqlengine.columns.DateTime":[[6,2,1,"","truncate_microseconds"]],"cassandra.cqlengine.connection":[[7,7,1,"","default"],[7,7,1,"","register_connection"],[7,7,1,"","set_default_connection"],[7,7,1,"","set_session"],[7,7,1,"","setup"],[7,7,1,"","unregister_connection"]],"cassandra.cqlengine.management":[[8,7,1,"","create_keyspace_network_topology"],[8,7,1,"","create_keyspace_simple"],[8,7,1,"","drop_keyspace"],[8,7,1,"","drop_table"],[8,7,1,"","sync_table"],[8,7,1,"","sync_type"]],"cassandra.cqlengine.models":[[9,3,1,"","Model"]],"cassandra.cqlengine.models.Model":[[9,2,1,"","__abstract__"],[9,2,1,"","__compute_routing_key__"],[9,2,1,"","__connection__"],[9,2,1,"","__default_ttl__"],[9,2,1,"","__discriminator_value__"],[9,2,1,"","__keyspace__"],[9,2,1,"","__options__"],[9,2,1,"","__table_name__"],[9,2,1,"","__table_name_case_sensitive__"],[9,4,1,"","all"],[9,4,1,"","batch"],[9,4,1,"","column_family_name"],[9,4,1,"","create"],[9,4,1,"","delete"],[9,4,1,"","filter"],[9,4,1,"","get"],[9,4,1,"","if_exists"],[9,4,1,"","if_not_exists"],[9,4,1,"","iff"],[9,4,1,"","items"],[9,4,1,"","keys"],[9,4,1,"","len"],[9,4,1,"","save"],[9,4,1,"","timeout"],[9,4,1,"","timestamp"],[9,4,1,"","ttl"],[9,4,1,"","update"],[9,4,1,"","using"],[9,4,1,"","values"]],"cassandra.cqlengine.query":[[10,3,1,"","BatchQuery"],[10,3,1,"","ContextQuery"],[10,3,1,"","DoesNotExist"],[10,3,1,"","LWTException"],[10,3,1,"","ModelQuerySet"],[10,3,1,"","MultipleObjectsReturned"]],"cassandra.cqlengine.query.BatchQuery":[[10,4,1,"","add_callback"],[10,4,1,"","add_query"],[10,4,1,"","execute"]],"cassandra.cqlengine.query.ModelQuerySet":[[10,4,1,"","all"],[10,4,1,"","allow_filtering"],[10,4,1,"","batch"],[10,4,1,"","consistency"],[10,4,1,"","count"],[10,4,1,"","defer"],[10,4,1,"","distinct"],[10,4,1,"","fetch_size"],[10,4,1,"","filter"],[10,4,1,"","get"],[10,4,1,"","if_exists"],[10,4,1,"","if_not_exists"],[10,4,1,"","len"],[10,4,1,"","limit"],[10,4,1,"","only"],[10,4,1,"","order_by"],[10,4,1,"","timestamp"],[10,4,1,"","ttl"],[10,4,1,"","update"],[10,4,1,"","using"]],"cassandra.cqlengine.usertype":[[11,3,1,"","UserType"]],"cassandra.cqlengine.usertype.UserType":[[11,2,1,"","__type_name__"]],"cassandra.datastax":[[15,0,0,"-","graph"]],"cassandra.datastax.graph":[[12,0,0,"-","fluent"],[15,7,1,"","graph_graphson2_row_factory"],[15,7,1,"","graph_graphson3_row_factory"],[15,7,1,"","graph_object_row_factory"],[15,7,1,"","graph_result_row_factory"],[15,7,1,"","single_object_row_factory"],[15,7,1,"","to_bigint"],[15,7,1,"","to_double"],[15,7,1,"","to_float"],[15,7,1,"","to_int"],[15,7,1,"","to_smallint"]],"cassandra.datastax.graph.GraphOptions":[[15,2,1,"","graph_language"],[15,2,1,"","graph_name"],[15,2,1,"","graph_read_consistency_level"],[15,2,1,"","graph_source"],[15,2,1,"","graph_write_consistency_level"],[15,2,1,"","is_analytics_source"],[15,2,1,"","is_default_source"],[15,2,1,"","is_graph_source"],[15,4,1,"","set_source_analytics"],[15,4,1,"","set_source_default"],[15,4,1,"","set_source_graph"]],"cassandra.datastax.graph.GraphSON1Deserializer":[[15,4,1,"","deserialize_bigint"],[15,4,1,"","deserialize_blob"],[15,4,1,"","deserialize_date"],[15,4,1,"","deserialize_decimal"],[15,4,1,"","deserialize_double"],[15,4,1,"","deserialize_duration"],[15,4,1,"","deserialize_float"],[15,4,1,"","deserialize_int"],[15,4,1,"","deserialize_linestring"],[15,4,1,"","deserialize_point"],[15,4,1,"","deserialize_polygon"],[15,4,1,"","deserialize_time"],[15,4,1,"","deserialize_timestamp"],[15,4,1,"","deserialize_uuid"]],"cassandra.datastax.graph.fluent":[[12,3,1,"","BaseGraphRowFactory"],[12,3,1,"","DSESessionRemoteGraphConnection"],[12,3,1,"","DseGraph"],[12,2,1,"","graph_traversal_dse_object_row_factory"],[12,2,1,"","graph_traversal_row_factory"],[13,0,0,"-","predicates"],[14,0,0,"-","query"]],"cassandra.datastax.graph.fluent.DseGraph":[[12,2,1,"","DSE_GRAPH_QUERY_LANGUAGE"],[12,4,1,"","batch"],[12,4,1,"","create_execution_profile"],[12,4,1,"","query_from_traversal"],[12,4,1,"","traversal_source"]],"cassandra.datastax.graph.fluent.predicates":[[13,3,1,"","CqlCollection"],[13,3,1,"","Geo"],[13,3,1,"","Search"]],"cassandra.datastax.graph.fluent.predicates.CqlCollection":[[13,4,1,"","contains"],[13,4,1,"","contains_key"],[13,4,1,"","contains_value"],[13,4,1,"","entry_eq"]],"cassandra.datastax.graph.fluent.predicates.Geo":[[13,4,1,"","inside"]],"cassandra.datastax.graph.fluent.predicates.Search":[[13,4,1,"","fuzzy"],[13,4,1,"","phrase"],[13,4,1,"","prefix"],[13,4,1,"","regex"],[13,4,1,"","token"],[13,4,1,"","token_fuzzy"],[13,4,1,"","token_prefix"],[13,4,1,"","token_regex"]],"cassandra.datastax.graph.fluent.query":[[14,3,1,"","TraversalBatch"]],"cassandra.datastax.graph.fluent.query.TraversalBatch":[[14,4,1,"","add"],[14,4,1,"","add_all"],[14,4,1,"","as_graph_statement"],[14,4,1,"","clear"],[14,4,1,"","execute"]],"cassandra.decoder":[[16,7,1,"","dict_factory"],[16,7,1,"","named_tuple_factory"],[16,7,1,"","ordered_dict_factory"],[16,7,1,"","tuple_factory"]],"cassandra.encoder":[[17,3,1,"","Encoder"]],"cassandra.encoder.Encoder":[[17,4,1,"","cql_encode_all_types"],[17,4,1,"","cql_encode_bytes"],[17,4,1,"","cql_encode_date"],[17,4,1,"","cql_encode_datetime"],[17,4,1,"","cql_encode_list_collection"],[17,4,1,"","cql_encode_map_collection"],[17,4,1,"","cql_encode_none"],[17,4,1,"","cql_encode_object"],[17,4,1,"","cql_encode_sequence"],[17,4,1,"","cql_encode_set_collection"],[17,4,1,"","cql_encode_str"],[17,4,1,"","cql_encode_tuple"],[17,4,1,"","cql_encode_unicode"],[17,2,1,"","mapping"]],"cassandra.graph":[[18,3,1,"","Edge"],[18,3,1,"","GraphOptions"],[18,3,1,"","GraphProtocol"],[18,3,1,"","GraphSON1Deserializer"],[18,3,1,"","GraphSON1Serializer"],[18,3,1,"","GraphSON2Reader"],[18,3,1,"","GraphSON3Reader"],[18,3,1,"","Path"],[18,3,1,"","Result"],[18,3,1,"","SimpleGraphStatement"],[18,3,1,"","Vertex"],[18,3,1,"","VertexProperty"],[18,7,1,"","graph_graphson2_row_factory"],[18,7,1,"","graph_graphson3_row_factory"],[18,7,1,"","graph_object_row_factory"],[18,7,1,"","graph_result_row_factory"],[18,7,1,"","single_object_row_factory"],[18,7,1,"","to_bigint"],[18,7,1,"","to_double"],[18,7,1,"","to_float"],[18,7,1,"","to_int"],[18,7,1,"","to_smallint"]],"cassandra.graph.GraphOptions":[[18,2,1,"","graph_language"],[18,2,1,"","graph_name"],[18,2,1,"","graph_read_consistency_level"],[18,2,1,"","graph_source"],[18,2,1,"","graph_write_consistency_level"],[18,2,1,"","is_analytics_source"],[18,2,1,"","is_default_source"],[18,2,1,"","is_graph_source"],[18,4,1,"","set_source_analytics"],[18,4,1,"","set_source_default"],[18,4,1,"","set_source_graph"]],"cassandra.graph.GraphProtocol":[[18,2,1,"","GRAPHSON_1_0"],[18,2,1,"","GRAPHSON_2_0"],[18,2,1,"","GRAPHSON_3_0"]],"cassandra.graph.GraphSON1Deserializer":[[18,4,1,"","deserialize_bigint"],[18,4,1,"","deserialize_blob"],[18,4,1,"","deserialize_date"],[18,4,1,"","deserialize_decimal"],[18,4,1,"","deserialize_double"],[18,4,1,"","deserialize_duration"],[18,4,1,"","deserialize_float"],[18,4,1,"","deserialize_int"],[18,4,1,"","deserialize_linestring"],[18,4,1,"","deserialize_point"],[18,4,1,"","deserialize_polygon"],[18,4,1,"","deserialize_time"],[18,4,1,"","deserialize_timestamp"],[18,4,1,"","deserialize_uuid"]],"cassandra.graph.GraphSON2Reader":[[18,4,1,"","deserialize"],[18,4,1,"","read"]],"cassandra.graph.Path":[[18,2,1,"","labels"],[18,2,1,"","objects"]],"cassandra.graph.Result":[[18,4,1,"","as_edge"],[18,4,1,"","as_path"],[18,4,1,"","as_vertex"],[18,2,1,"","value"]],"cassandra.graph.VertexProperty":[[18,2,1,"","label"],[18,2,1,"","properties"],[18,2,1,"","value"]],"cassandra.io":[[19,0,0,"-","asyncioreactor"],[20,0,0,"-","asyncorereactor"],[21,0,0,"-","eventletreactor"],[22,0,0,"-","geventreactor"],[23,0,0,"-","libevreactor"],[24,0,0,"-","twistedreactor"]],"cassandra.io.asyncioreactor":[[19,3,1,"","AsyncioConnection"]],"cassandra.io.asyncioreactor.AsyncioConnection":[[19,4,1,"","initialize_reactor"]],"cassandra.io.asyncorereactor":[[20,3,1,"","AsyncoreConnection"]],"cassandra.io.asyncorereactor.AsyncoreConnection":[[20,4,1,"","handle_fork"],[20,4,1,"","initialize_reactor"]],"cassandra.io.eventletreactor":[[21,3,1,"","EventletConnection"]],"cassandra.io.eventletreactor.EventletConnection":[[21,4,1,"","initialize_reactor"],[21,4,1,"","service_timeouts"]],"cassandra.io.geventreactor":[[22,3,1,"","GeventConnection"]],"cassandra.io.geventreactor.GeventConnection":[[22,4,1,"","initialize_reactor"]],"cassandra.io.libevreactor":[[23,3,1,"","LibevConnection"]],"cassandra.io.twistedreactor":[[24,3,1,"","TwistedConnection"]],"cassandra.metadata":[[25,3,1,"","Aggregate"],[25,3,1,"","BytesToken"],[25,3,1,"","ColumnMetadata"],[25,3,1,"","EdgeMetadata"],[25,3,1,"","Function"],[25,3,1,"","IndexMetadata"],[25,3,1,"","KeyspaceMetadata"],[25,3,1,"","LocalStrategy"],[25,3,1,"","MD5Token"],[25,3,1,"","MaterializedViewMetadata"],[25,3,1,"","Metadata"],[25,3,1,"","Murmur3Token"],[25,3,1,"","NetworkTopologyStrategy"],[25,3,1,"","ReplicationFactor"],[25,2,1,"","ReplicationStrategy"],[25,3,1,"","SimpleStrategy"],[25,3,1,"","TableMetadata"],[25,3,1,"","TableMetadataDSE68"],[25,3,1,"","TableMetadataV3"],[25,3,1,"","Token"],[25,3,1,"","TokenMap"],[25,3,1,"","UserType"],[25,3,1,"","VertexMetadata"],[25,6,1,"","cql_keywords"],[25,6,1,"","cql_keywords_reserved"],[25,6,1,"","cql_keywords_unreserved"],[25,7,1,"","group_keys_by_replica"]],"cassandra.metadata.Aggregate":[[25,4,1,"","as_cql_query"]],"cassandra.metadata.BytesToken":[[25,4,1,"","from_string"]],"cassandra.metadata.Function":[[25,4,1,"","as_cql_query"]],"cassandra.metadata.IndexMetadata":[[25,4,1,"","as_cql_query"],[25,4,1,"","export_as_string"]],"cassandra.metadata.KeyspaceMetadata":[[25,4,1,"","as_cql_query"],[25,4,1,"","export_as_string"]],"cassandra.metadata.LocalStrategy":[[25,4,1,"","export_for_schema"]],"cassandra.metadata.MaterializedViewMetadata":[[25,4,1,"","as_cql_query"]],"cassandra.metadata.Metadata":[[25,4,1,"","add_or_return_host"],[25,4,1,"","all_hosts"],[25,4,1,"","export_schema_as_string"],[25,4,1,"","get_host"],[25,4,1,"","get_host_by_host_id"],[25,4,1,"","get_replicas"]],"cassandra.metadata.NetworkTopologyStrategy":[[25,4,1,"","export_for_schema"]],"cassandra.metadata.SimpleStrategy":[[25,4,1,"","export_for_schema"],[25,5,1,"","replication_factor"]],"cassandra.metadata.TableMetadata":[[25,4,1,"","as_cql_query"],[25,4,1,"","export_as_string"],[25,5,1,"","is_cql_compatible"],[25,5,1,"","primary_key"]],"cassandra.metadata.TableMetadataDSE68":[[25,4,1,"","as_cql_query"]],"cassandra.metadata.TableMetadataV3":[[25,5,1,"","is_cql_compatible"]],"cassandra.metadata.TokenMap":[[25,4,1,"","get_replicas"]],"cassandra.metadata.UserType":[[25,4,1,"","as_cql_query"]],"cassandra.metrics":[[26,3,1,"","Metrics"]],"cassandra.metrics.Metrics":[[26,2,1,"","connected_to"],[26,2,1,"","connection_errors"],[26,4,1,"","get_stats"],[26,2,1,"","ignores"],[26,2,1,"","known_hosts"],[26,2,1,"","open_connections"],[26,2,1,"","other_errors"],[26,2,1,"","read_timeouts"],[26,2,1,"","request_timer"],[26,2,1,"","retries"],[26,4,1,"","set_stats_name"],[26,2,1,"","unavailables"],[26,2,1,"","write_timeouts"]],"cassandra.policies":[[27,3,1,"","AddressTranslator"],[27,3,1,"","ConstantReconnectionPolicy"],[27,3,1,"","ConstantSpeculativeExecutionPolicy"],[27,3,1,"","ConvictionPolicy"],[27,3,1,"","DCAwareRoundRobinPolicy"],[27,3,1,"","DSELoadBalancingPolicy"],[27,3,1,"","DefaultLoadBalancingPolicy"],[27,3,1,"","DowngradingConsistencyRetryPolicy"],[27,3,1,"","EC2MultiRegionTranslator"],[27,3,1,"","ExponentialReconnectionPolicy"],[27,3,1,"","FallthroughRetryPolicy"],[27,3,1,"","HostDistance"],[27,3,1,"","HostFilterPolicy"],[27,3,1,"","IdentityTranslator"],[27,3,1,"","LoadBalancingPolicy"],[27,3,1,"","ReconnectionPolicy"],[27,3,1,"","RetryPolicy"],[27,3,1,"","RoundRobinPolicy"],[27,3,1,"","SimpleConvictionPolicy"],[27,3,1,"","SpeculativeExecutionPolicy"],[27,3,1,"","TokenAwarePolicy"],[27,3,1,"","WhiteListRoundRobinPolicy"],[27,3,1,"","WriteType"]],"cassandra.policies.AddressTranslator":[[27,4,1,"","translate"]],"cassandra.policies.ConstantReconnectionPolicy":[[27,4,1,"","new_schedule"]],"cassandra.policies.ConstantSpeculativeExecutionPolicy":[[27,4,1,"","new_plan"]],"cassandra.policies.ConvictionPolicy":[[27,4,1,"","add_failure"],[27,4,1,"","reset"]],"cassandra.policies.DCAwareRoundRobinPolicy":[[27,4,1,"","distance"],[27,4,1,"","make_query_plan"],[27,4,1,"","on_add"],[27,4,1,"","on_down"],[27,4,1,"","on_remove"],[27,4,1,"","on_up"],[27,4,1,"","populate"]],"cassandra.policies.DefaultLoadBalancingPolicy":[[27,4,1,"","make_query_plan"],[27,4,1,"","populate"]],"cassandra.policies.DowngradingConsistencyRetryPolicy":[[27,4,1,"","on_read_timeout"],[27,4,1,"","on_unavailable"],[27,4,1,"","on_write_timeout"]],"cassandra.policies.EC2MultiRegionTranslator":[[27,4,1,"","translate"]],"cassandra.policies.ExponentialReconnectionPolicy":[[27,4,1,"","new_schedule"]],"cassandra.policies.FallthroughRetryPolicy":[[27,4,1,"","on_read_timeout"],[27,4,1,"","on_request_error"],[27,4,1,"","on_unavailable"],[27,4,1,"","on_write_timeout"]],"cassandra.policies.HostDistance":[[27,2,1,"","IGNORED"],[27,2,1,"","LOCAL"],[27,2,1,"","REMOTE"]],"cassandra.policies.HostFilterPolicy":[[27,4,1,"","distance"],[27,4,1,"","make_query_plan"],[27,4,1,"","predicate"]],"cassandra.policies.IdentityTranslator":[[27,4,1,"","translate"]],"cassandra.policies.LoadBalancingPolicy":[[27,4,1,"","check_supported"],[27,4,1,"","distance"],[27,4,1,"","make_query_plan"],[27,4,1,"","populate"]],"cassandra.policies.ReconnectionPolicy":[[27,4,1,"","new_schedule"]],"cassandra.policies.RetryPolicy":[[27,2,1,"","IGNORE"],[27,2,1,"","RETHROW"],[27,2,1,"","RETRY"],[27,2,1,"","RETRY_NEXT_HOST"],[27,4,1,"","on_read_timeout"],[27,4,1,"","on_request_error"],[27,4,1,"","on_unavailable"],[27,4,1,"","on_write_timeout"]],"cassandra.policies.RoundRobinPolicy":[[27,4,1,"","distance"],[27,4,1,"","make_query_plan"],[27,4,1,"","on_add"],[27,4,1,"","on_down"],[27,4,1,"","on_remove"],[27,4,1,"","on_up"],[27,4,1,"","populate"]],"cassandra.policies.SimpleConvictionPolicy":[[27,4,1,"","add_failure"],[27,4,1,"","reset"]],"cassandra.policies.SpeculativeExecutionPolicy":[[27,4,1,"","new_plan"]],"cassandra.policies.TokenAwarePolicy":[[27,4,1,"","check_supported"],[27,4,1,"","distance"],[27,4,1,"","make_query_plan"],[27,4,1,"","on_add"],[27,4,1,"","on_down"],[27,4,1,"","on_remove"],[27,4,1,"","on_up"],[27,4,1,"","populate"],[27,2,1,"","shuffle_replicas"]],"cassandra.policies.WhiteListRoundRobinPolicy":[[27,4,1,"","distance"],[27,4,1,"","on_add"],[27,4,1,"","on_up"],[27,4,1,"","populate"]],"cassandra.policies.WriteType":[[27,2,1,"","BATCH"],[27,2,1,"","BATCH_LOG"],[27,2,1,"","CAS"],[27,2,1,"","CDC"],[27,2,1,"","COUNTER"],[27,2,1,"","SIMPLE"],[27,2,1,"","UNLOGGED_BATCH"],[27,2,1,"","VIEW"]],"cassandra.pool":[[28,3,1,"","Host"],[28,1,1,"","NoConnectionsAvailable"]],"cassandra.pool.Host":[[28,5,1,"","address"],[28,5,1,"","datacenter"],[28,5,1,"","rack"]],"cassandra.protocol":[[29,3,1,"","_ProtocolHandler"]],"cassandra.protocol._ProtocolHandler":[[29,4,1,"","decode_message"],[29,4,1,"","encode_message"],[29,2,1,"","message_types_by_opcode"]],"cassandra.query":[[30,3,1,"","BatchStatement"],[30,3,1,"","BatchType"],[30,3,1,"","BoundStatement"],[30,3,1,"","PreparedStatement"],[30,3,1,"","QueryTrace"],[30,3,1,"","SimpleStatement"],[30,3,1,"","Statement"],[30,3,1,"","TraceEvent"],[30,1,1,"","TraceUnavailable"],[30,6,1,"","UNSET_VALUE"],[30,3,1,"","ValueSequence"],[30,7,1,"","dict_factory"],[30,7,1,"","named_tuple_factory"],[30,7,1,"","ordered_dict_factory"],[30,7,1,"","tuple_factory"]],"cassandra.query.BatchStatement":[[30,4,1,"","add"],[30,4,1,"","add_all"],[30,4,1,"","clear"],[30,2,1,"","serial_consistency_level"]],"cassandra.query.BatchType":[[30,2,1,"","COUNTER"],[30,2,1,"","LOGGED"],[30,2,1,"","UNLOGGED"]],"cassandra.query.BoundStatement":[[30,4,1,"","bind"],[30,5,1,"","routing_key"]],"cassandra.query.PreparedStatement":[[30,4,1,"","bind"]],"cassandra.query.QueryTrace":[[30,4,1,"","populate"]],"cassandra.query.Statement":[[30,5,1,"","routing_key"],[30,5,1,"","serial_consistency_level"]],"cassandra.timestamps":[[31,3,1,"","MonotonicTimestampGenerator"]],"cassandra.timestamps.MonotonicTimestampGenerator":[[31,4,1,"","_next_timestamp"],[31,2,1,"","warn_on_drift"],[31,2,1,"","warning_interval"],[31,2,1,"","warning_threshold"]],"cassandra.util":[[32,3,1,"","Date"],[32,3,1,"","DateRange"],[32,3,1,"","DateRangeBound"],[32,3,1,"","DateRangePrecision"],[32,3,1,"","Distance"],[32,3,1,"","Duration"],[32,3,1,"","LineString"],[32,3,1,"","OrderedMap"],[32,3,1,"","OrderedMapSerializedKey"],[32,3,1,"","Point"],[32,3,1,"","Polygon"],[32,3,1,"","SortedSet"],[32,3,1,"","Time"],[32,3,1,"","Version"],[32,7,1,"","datetime_from_timestamp"],[32,7,1,"","datetime_from_uuid1"],[32,7,1,"","max_uuid_from_time"],[32,7,1,"","min_uuid_from_time"],[32,7,1,"","ms_timestamp_from_datetime"],[32,2,1,"","sortedset"],[32,7,1,"","unix_time_from_uuid1"],[32,7,1,"","utc_datetime_from_ms_timestamp"],[32,7,1,"","uuid_from_time"]],"cassandra.util.Date":[[32,4,1,"","date"],[32,5,1,"","seconds"]],"cassandra.util.DateRange":[[32,2,1,"","lower_bound"],[32,2,1,"","upper_bound"],[32,2,1,"","value"]],"cassandra.util.DateRangeBound":[[32,4,1,"","datetime"],[32,4,1,"","from_value"],[32,2,1,"","milliseconds"],[32,2,1,"","precision"]],"cassandra.util.Distance":[[32,4,1,"","from_wkt"]],"cassandra.util.LineString":[[32,4,1,"","from_wkt"]],"cassandra.util.Point":[[32,4,1,"","from_wkt"]],"cassandra.util.Polygon":[[32,4,1,"","from_wkt"]],"cassandra.util.Time":[[32,5,1,"","hour"],[32,5,1,"","minute"],[32,5,1,"","nanosecond"],[32,5,1,"","second"],[32,4,1,"","time"]],"cqlengine.queryset":[[38,3,1,"","MaxTimeUUID"],[38,3,1,"","MinTimeUUID"]],cassandra:[[1,1,1,"","AlreadyExists"],[1,1,1,"","AuthenticationFailed"],[1,1,1,"","ConfigurationException"],[1,3,1,"","ConsistencyLevel"],[1,1,1,"","CoordinationFailure"],[1,1,1,"","DriverException"],[1,1,1,"","FunctionFailure"],[1,1,1,"","InvalidRequest"],[1,1,1,"","OperationTimedOut"],[1,3,1,"","ProtocolVersion"],[1,1,1,"","ReadFailure"],[1,1,1,"","ReadTimeout"],[1,1,1,"","RequestExecutionException"],[1,1,1,"","RequestValidationException"],[1,1,1,"","Timeout"],[1,1,1,"","Unauthorized"],[1,1,1,"","Unavailable"],[1,3,1,"","UserAggregateDescriptor"],[1,3,1,"","UserFunctionDescriptor"],[1,1,1,"","WriteFailure"],[1,1,1,"","WriteTimeout"],[1,6,1,"","__version__"],[1,6,1,"","__version_info__"],[2,0,0,"-","auth"],[3,0,0,"-","cluster"],[4,0,0,"-","concurrent"],[5,0,0,"-","connection"],[16,0,0,"-","decoder"],[17,0,0,"-","encoder"],[18,0,0,"-","graph"],[25,0,0,"-","metadata"],[26,0,0,"-","metrics"],[27,0,0,"-","policies"],[28,0,0,"-","pool"],[29,0,0,"-","protocol"],[30,0,0,"-","query"],[31,0,0,"-","timestamps"],[32,0,0,"-","util"]],cqlengine:[[37,0,0,"-","models"],[38,0,0,"-","queryset"]]},objnames:{"0":["py","module","Python module"],"1":["py","exception","Python exception"],"2":["py","attribute","Python attribute"],"3":["py","class","Python class"],"4":["py","method","Python method"],"5":["py","property","Python property"],"6":["py","data","Python data"],"7":["py","function","Python function"]},objtypes:{"0":"py:module","1":"py:exception","2":"py:attribute","3":"py:class","4":"py:method","5":"py:property","6":"py:data","7":"py:function"},terms:{"0":[1,2,3,4,6,9,10,12,14,15,16,18,25,27,30,31,32,34,35,37,38,42,43,44,46,47,48,50,56],"00":43,"000":10,"000077":43,"000153":43,"000309":43,"000368":43,"000422":43,"000480":43,"000669":43,"000755":43,"031ebb0":55,"04":0,"05":38,"0l":38,"0m":0,"1":[1,2,3,4,6,10,13,15,18,19,25,27,30,31,32,34,35,36,38,42,43,44,46,47,48,52,53,54,56],"10":[1,3,10,38,44,46,50],"100":[0,4,10,42,50],"1000":[0,4],"1004":0,"1005":0,"1006":0,"1007":0,"1008":0,"1009":0,"101":0,"1012":0,"1013":0,"1015":0,"1016":0,"1017":0,"1018":0,"1019":0,"1020":0,"1021":0,"1023":0,"1024":0,"1026":0,"1027":0,"103":0,"1031":0,"1033":0,"1036":0,"1039":0,"104":0,"1042":0,"1044":0,"1045":0,"1047":0,"1048":0,"105":0,"1051":0,"1054":0,"1056":0,"1057":0,"106":0,"1060":0,"1064":0,"1065":0,"1067":0,"1068":0,"1074":0,"10786":30,"1079":0,"108":0,"1081":0,"1082":0,"1087":0,"1089":0,"109":0,"1090":0,"1091":0,"1093":0,"10l":38,"110":0,"1100":0,"1103":0,"1104":0,"1105":0,"111":[0,36],"1110":0,"111111111111":9,"1112":0,"1114":0,"1116":0,"1117":0,"1118":0,"1119":0,"112":0,"1121":0,"1122":0,"1123":0,"1124":0,"1126":0,"1127":0,"1129":0,"1130":0,"1131":0,"1140":0,"1158":0,"116":0,"1161":0,"1162":0,"1163":0,"1166":0,"1172":0,"1174":0,"1177":0,"1181":0,"1183":0,"1185":0,"1186":0,"1187":0,"1189":0,"119":[0,32],"1192":0,"11e3":44,"11l":38,"120":0,"1203":0,"1204":0,"1205":0,"1207":0,"1212":0,"122":0,"1220":0,"1228":0,"123":[0,3,36,56],"1233":0,"1234":54,"1237":0,"1238":0,"1239":0,"124":0,"1240":0,"1241":0,"1243":0,"1244":0,"1245":0,"1248":0,"125":0,"1258":0,"126":0,"1260":0,"1264":0,"1265":0,"1266":0,"1269":0,"127":[3,25,35,38,42,43,44,48,54],"1287":0,"1289":0,"1290":0,"12l":38,"1304":0,"1327":0,"1328":0,"1329":0,"135":0,"138":0,"13l":38,"14":32,"141":0,"143":0,"144":0,"145":27,"147":0,"148":0,"14l":38,"15":[27,44],"150":0,"151":0,"155":0,"157":0,"159":0,"15l":38,"16":6,"160":0,"163":0,"164":0,"165":0,"166":0,"167":0,"168":[3,44],"16l":38,"17":[38,54],"173":0,"174":0,"175":0,"178":[0,30,55],"179":0,"17l":38,"180":0,"181":0,"182":0,"184":0,"185":0,"186":0,"187":0,"189":0,"18l":38,"190":0,"191":0,"192":[0,3,44],"194":0,"195":0,"196":0,"197":0,"1970":32,"198":0,"1982":38,"19l":38,"1e6":31,"1l":38,"1s":0,"2":[1,2,3,4,6,9,10,12,13,14,15,16,18,25,27,30,32,34,35,36,38,40,42,43,44,45,46,47,50,53,54,56],"20":38,"200":0,"2008":10,"2010":[35,38],"2011":38,"2012":38,"2013":[0,45],"2014":[0,38],"2015":0,"2016":[0,45],"2017":[0,45],"2018":0,"2019":0,"202":0,"2020":0,"2021":0,"2023":0,"204":0,"2048":54,"205":0,"206":0,"207":0,"208":0,"21":[38,55],"210":0,"211":0,"212":0,"213":0,"215":0,"218":0,"219":0,"22":46,"220":0,"222":0,"226":0,"229":0,"23":32,"230":0,"231":0,"234":0,"235":0,"238":0,"239":0,"24":3,"240":0,"241":0,"243":0,"244":0,"245":[0,40],"246":0,"249":0,"255":0,"258":0,"26":38,"260":0,"2644bada":44,"266":0,"27":0,"272":0,"273":0,"276":[0,55],"277":0,"278":0,"279":43,"28":0,"280":0,"282":0,"283":0,"284":0,"285":0,"286":0,"288":0,"289":0,"29":0,"291":0,"292":[0,55],"294":0,"295":0,"296":0,"297":0,"298":0,"299":0,"2l":38,"3":[1,2,3,4,6,9,10,15,18,19,25,27,30,31,32,34,36,37,38,45,46,48,53,56],"30":[0,3,38,42,44],"300":0,"301":0,"302":0,"303":0,"305":0,"306":0,"309":0,"31":[0,38],"310":0,"311":0,"313":0,"315":0,"317":0,"318":[0,55],"319":0,"32":6,"322":0,"323":0,"324":0,"325":0,"327":0,"329":0,"331":0,"332":0,"333":0,"334":0,"335":0,"336":0,"337":0,"338":0,"340":32,"341":0,"342":0,"343":0,"344":0,"345":0,"346":0,"347":0,"348":0,"349":0,"351":0,"352":0,"353":0,"354":0,"357":0,"358":0,"360":0,"3600":3,"361":0,"362":0,"363":0,"365":0,"368":[0,55],"370":0,"371":0,"375":0,"377":0,"378":0,"379":0,"381":0,"385":[0,55],"386":0,"392":0,"393":0,"394":0,"395":0,"396":0,"397":0,"398":0,"3l":38,"4":[1,2,3,6,9,10,19,27,29,30,32,42,48],"400":[0,55],"405":0,"407":0,"408":[0,55],"409":0,"412":0,"413":0,"415":0,"416":0,"419fcdf":55,"42":[3,30,44],"422":[0,55],"429":0,"430":0,"432":0,"433":0,"434":0,"435":0,"438":0,"439":0,"442":0,"443":0,"444":0,"445":0,"447":0,"450":0,"451":0,"452":0,"454":0,"458":0,"459":0,"46":0,"464":0,"466":0,"467":0,"468":0,"469":0,"470":0,"471":0,"473":0,"475":0,"476":0,"477":0,"478":0,"479":0,"48":32,"480":0,"481":0,"482":0,"486":0,"487":0,"489":0,"495":0,"498":0,"4bd5909":55,"4l":38,"4th":0,"5":[1,3,9,10,19,27,38,44,45,46,54],"50":4,"500":10,"5000":[3,10,50],"501":0,"502":0,"503":0,"505":0,"507":0,"508":0,"509":0,"50m":38,"510":0,"512":0,"514":0,"520":0,"521":0,"522":0,"527":0,"528":0,"530":0,"531":0,"532":0,"533":0,"535":0,"537":0,"538":0,"542":0,"547":0,"548":0,"549":0,"550":0,"551":0,"553":0,"555":0,"556":0,"557":0,"559":0,"56":0,"560":0,"561":0,"562":0,"565":0,"566":0,"568":0,"569":0,"570":0,"572":0,"5723":0,"573":0,"574":0,"574266d":55,"576":0,"577":0,"578":0,"579":0,"580":0,"583":0,"584":0,"585":0,"589":0,"59":[0,32],"591":0,"593":0,"595":0,"596":0,"598":0,"599":0,"5l":38,"6":[1,3,6,10,19,25,27,30,38,45,46],"60":0,"600":0,"606":0,"607":0,"608":0,"609":0,"613":0,"614":0,"616":0,"617":0,"618":0,"619":0,"621":0,"622":0,"623":0,"626":0,"628":0,"630":0,"631":0,"636":0,"64":[6,9,27],"640":0,"642":0,"643":0,"644":0,"645":0,"646":0,"647":0,"648":0,"649":0,"65":1,"650":0,"653":0,"655":0,"656":0,"657":0,"66":[1,3],"665":0,"668":0,"669":0,"673":0,"676":0,"678":0,"682":0,"684":0,"686":0,"688":0,"69":0,"690":0,"692":0,"694":0,"697":0,"6l":38,"7":[1,3,6,10,27,45,46],"70":0,"700":0,"705":0,"706":0,"707":0,"708":0,"709":0,"71":0,"710":0,"714":0,"717":0,"719":0,"720":0,"721":0,"723":0,"724":0,"727":0,"728":0,"729":0,"73":0,"730":0,"732":0,"733":0,"734":0,"735":0,"736":0,"737":0,"739":0,"740":0,"741":0,"742":0,"743":0,"746":0,"747":0,"749":0,"75":0,"750":0,"751":0,"752":0,"754":0,"755":0,"759":0,"75percentil":26,"75th":26,"76":0,"761":0,"762":0,"763":0,"767":0,"768":0,"769":0,"77142":43,"772":0,"773":0,"774":0,"774000":38,"775":0,"778":0,"781":0,"782":0,"785":0,"7857":0,"78723":[3,56],"788":0,"789":0,"79":0,"793":0,"794":0,"798":0,"799":0,"79efe97":55,"7l":38,"8":[1,3,6,17,31,45,46,48],"80":0,"804dea3":0,"805":0,"808":0,"81":0,"810":0,"812":0,"813":0,"814":0,"819":0,"82":0,"827":0,"829":0,"831":0,"833":0,"836":0,"837":0,"838":0,"839":0,"84":0,"840":0,"843":0,"846":0,"848":0,"852c":44,"853":0,"86":0,"860":0,"861":0,"862":0,"863":0,"86400":9,"865":0,"868":0,"872":0,"8733":40,"877":0,"88":0,"885":0,"888":0,"89":0,"891":0,"892":0,"893":0,"894":0,"895":0,"897":0,"89fb":44,"8l":38,"9":[1,9,38],"90":0,"900":0,"901":0,"903":0,"9042":[3,5],"91":0,"910":0,"915":0,"916":0,"92":0,"9223372036854775808":43,"93":0,"932":0,"934":0,"937":0,"940":0,"941":0,"944":0,"945":0,"946":0,"947":0,"95":0,"953":0,"955":0,"95percentil":26,"95th":26,"96":0,"963":0,"96489cc":55,"966":0,"968":0,"97":0,"973":0,"978":0,"98":0,"98percentil":26,"98th":26,"99":[0,26],"992":0,"993":0,"995":0,"996":0,"998":0,"99999":37,"999percentil":26,"99percentil":26,"99th":26,"9d98c8e":55,"9l":38,"9th":26,"abstract":[0,2,6,9,25,30],"boolean":[0,1,6,25,27,44,47],"break":[0,27,45,46,55],"byte":[0,6,38],"case":[0,3,4,8,9,27,32,34,35,44,49,53,54],"catch":0,"char":0,"class":[0,1,2,3,5,6,9,10,12,13,14,15,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,40,41,48,50,53,54,55],"default":[0,1,3,6,7,9,10,11,12,14,15,17,18,26,27,29,30,31,34,43,44,46,48,49,50,54],"do":[0,3,4,6,9,17,27,30,37,38,41,44,46,54,55,56],"enum":[10,13,27,32,33],"export":[0,25],"final":[3,44,54],"float":[0,3,6,10,15,18,26,27,37,38,44,55],"function":[0,1,3,8,10,12,17,25,27,29,32,41,44,53,54,55],"import":[0,2,3,4,6,10,11,12,29,30,34,35,37,38,39,41,42,43,44,46,48,50,52,53,54],"int":[0,3,6,7,8,15,18,25,31,32,38,44,47,55,56],"long":[0,32,44,46,56],"new":[0,1,2,3,4,6,7,10,21,25,27,30,31,32,34,36,38,39,40,42,44,48,50,54,55,56],"null":[0,10,17,36,38,44],"public":27,"return":[0,1,2,3,4,9,10,12,14,15,18,25,26,27,29,30,31,32,33,37,38,39,41,43,44,47,48,50,52,54,56],"short":[0,30,37,52],"static":[0,3,6,10,12,13,32],"super":37,"switch":[0,10,46],"throw":[0,3,30],"transient":0,"true":[0,3,4,6,7,8,9,10,15,18,25,27,30,31,34,35,36,37,38,40,43,44,47,48,53,54],"try":[0,1,3,8,9,27,37,39,41,44],"while":[0,3,27,30,37,40,50,55],A:[0,1,2,3,4,7,8,10,12,13,14,17,18,25,26,27,30,32,35,37,38,44,45,46],AND:[47,53],And:[9,54,55],As:[9,32,40,44,53,56],BY:37,Be:49,But:30,By:[1,3,9,10,27,29,34,38,43,44,46,50,52,54,55],For:[0,1,3,6,7,9,10,25,27,30,32,36,37,38,40,41,42,44,46,47,48,49,50,51,53,54,55],IF:[0,10,27,30,47,53,55],IN:[17,25,30],INTO:[3,4,30,44,47,56],IS:[0,38,40],If:[0,2,3,4,7,8,9,10,11,14,25,27,30,31,32,34,35,36,37,41,42,44,46,47,50,54,55],In:[0,3,27,29,34,38,40,44,46,53,54,55],It:[0,3,9,21,22,27,32,35,37,38,43,44,46,47,54],NOT:[0,38,47,53],No:45,Not:[0,32],ONE:[1,3,10,40,55],Of:3,On:[0,27,46],One:[10,41],Or:3,Such:27,THERE:40,That:38,The:[0,1,2,3,4,5,6,7,9,10,12,13,14,15,17,18,25,26,27,28,29,30,32,34,36,37,38,40,41,42,44,45,46,47,49,52,54,55,56],Then:54,There:[1,3,6,8,30,38,44,46,55],These:[0,3,6,9,27,29,30,32,40,41,49,54,55],To:[3,9,11,27,34,35,37,38,40,41,42,43,44,46,51,54,55],WITH:[37,53],Will:9,With:[0,35,43,52,54,55],_1:54,_2:54,_3:54,_4:54,_:42,__:[10,38,55],__abstract__:9,__compute_routing_key__:9,__connection__:[8,9,35],__contain:38,__default_ttl__:9,__del__:0,__discrimin:55,__discriminator_value__:[6,9,37,40],__ge__:0,__gt:38,__gte:38,__in:[0,38],__init__:[0,3,27,31,50,55,56],__keyspace__:[8,9,35,37],__le__:0,__len__:0,__like:38,__lt:38,__lte:38,__name__:43,__ne__:0,__options__:[9,38],__polymorphic_:55,__polymorphic_key__:40,__repr__:0,__table_name__:[9,37,40],__table_name_case_sensitive__:9,__type_name__:11,__version__:[1,46],__version_info__:1,_connect:0,_dsegraphson2rowfactori:12,_gremlingraphson2rowfactori:12,_messagetyp:29,_metadata:55,_new_tim:21,_next_timestamp:31,_not_set:3,_protocolhand:29,_protocolhandl:29,_replicationstrategi:25,_set_final_except:0,_set_result:0,_timeout_watch:21,a2:10,a2d3a98:55,abil:[0,27,42,55],abl:46,about:[0,3,25,30,37,41,44,46,52,54,55],abov:[3,29,34,35,41,44,49],absolut:[32,40],accept:[0,3,27,32,40,41],access:[0,3,9,26,30,37,44,55],accommod:[0,41],accomplish:[38,46],accord:[0,3],accordingli:0,account:[0,37],accumul:10,accur:25,acheiv:27,achiev:[27,34,54],acknowledg:27,across:[0,19,20,21,22,27,42,43,49],act:54,activ:[0,3,21,22],actual:[0,1,27,30,38,44,47],ad:[0,1,3,10,21,25,27,30,34,37,38,46,55],add:[0,3,7,8,10,14,27,30,34,55,56],add_al:[14,30],add_callback:[3,10,34,44,49,50],add_collback:0,add_errback:[3,44],add_execution_profil:[3,12,42],add_failur:27,add_or_return_host:25,add_queri:10,add_request_init_listen:3,add_tim:0,addit:[0,3,10,12,29,34,37,38,44,47,48,54,55],addition:[30,37,40,54],additional_write_polici:0,addr:[27,37],address:[0,1,3,5,11,25,28,30,33,37,43,44,52,54,55,56],address_is_ignor:27,address_transl:3,addresstransl:[0,27],adher:41,adjust:[0,40],advanc:54,advic:3,affect:[3,30,34],after:[0,3,4,10,20,27,30,34,37,38,40,43,44,46,49],afterward:55,ag:[3,30,38,44],against:[0,1,3,9,27,30,37,44,48,54],aggreg:[0,1,3,25],agnost:32,agre:0,agreement:[0,3],ahead:[3,44],aim:[35,42],algorithm:[36,46],alia:[6,12,25,32,40],alias:0,alic:30,align:0,aliv:[1,26,27],alive_replica:[1,27],all:[0,1,3,4,6,8,9,10,17,21,22,25,26,27,28,29,30,35,41,44,46,47,49,53,54,55],all_host:[25,42,52],all_object:38,all_replica:25,allow:[0,3,6,9,10,12,13,27,29,30,31,32,34,36,37,46,52,53,54,55,56],allow_beta_protocol_vers:29,allow_filt:[10,38],almost:44,along:[3,25,50],alpha:0,alphanumer:0,alreadi:[0,1,3,5,8,35,46],alreadyexist:1,also:[0,3,4,9,10,13,27,30,32,35,37,38,42,43,44,46,54,55],alter:[9,27,37],altern:[3,29,37,40,44,46,49,54],although:[44,55,56],althought:44,alwai:[0,3,15,18,27,41,44,46,47],ambigu:0,among:[1,27],amount:[0,4,27],an:[0,1,2,3,4,5,6,8,9,10,12,13,15,17,18,19,20,21,22,23,24,25,26,27,29,30,31,32,34,35,36,37,38,40,41,42,44,45,46,48,49,50,53,54,55,56],analysi:29,analyt:[0,3,15,18],analyticskeyspac:3,analyticskeyspace_prepar:3,andrew:[46,54],ani:[0,1,3,8,9,10,13,14,17,19,20,21,22,26,27,30,34,37,38,41,43,44,45,46,47,49,54,56],annot:0,anomali:0,anoth:[27,34,35,38,44,54,55],anymor:[38,55],anyth:[34,41],anywai:46,apach:[38,46,55],api:[0,32,37,41,42,45,46,48,49,54],app:[39,43],appear:[0,47],append:[4,10,25,38,44],appli:[0,3,9,10,14,30,36,41,42,44,46,47,48,56],applic:[0,3,6,27,39,40,41,44,46,49,50,52,55],approach:[41,45],appropri:[3,37,46,54],april:0,apt:46,ar:[0,1,3,4,6,7,8,9,10,15,18,21,25,26,27,28,29,30,32,34,36,37,40,41,42,43,44,45,46,47,48,50,54],arbitrari:[6,32],archflag:46,architectur:46,arg:[3,4,6,9,10,19,20,21,22,23,27,32,34],arg_typ:1,argument:[0,1,3,4,7,9,10,15,18,27,30,31,32,34,35,44,46,54,55],argument_typ:1,arm:0,around:[0,9,32,40,41,55],arrai:[29,38],arriv:3,as_cql_queri:[0,25],as_edg:[15,18],as_graph_stat:14,as_path:[15,18],as_vertex:[15,18],ascend:[10,38],ascii:[0,6,44],ask:[45,48],assert:[6,36,53],assertionerror:38,assign:[0,6,11,37],associ:[0,3,55],assum:[3,21,22,38,41,54,55],assumpt:41,astimezon:41,astra:0,async:3,asynchron:[0,3,30,43,49],asyncio:[0,33],asyncioconnect:19,asyncioreactor:[0,33],asyncor:[0,33,46],asyncoreconnect:[0,20],asyncorereactor:[0,33],atexit:0,atlassian:27,atom:[27,30],attach:[0,3,15,18,34,44,49,50],attempt:[0,1,3,4,5,27,34,41,43,44,55],attr_kwarg:3,attribut:[0,3,6,8,9,10,11,15,18,25,27,29,30,31,37,38,40,42,44,47,55,56],attributeerror:0,aug:0,august:0,auth:[0,33,54,55],auth_provid:[2,3,54],authent:[0,1,3,33],authenticationfail:[1,2],author:[1,54],authorization_id:54,authprovid:[0,2,3,54],auto:35,automat:[0,1,3,35,37,38,44,46,50],automobil:[10,35,38],automobile2:10,avail:[0,3,10,30,38,45,46,53,55],avoid:[0,3,27,40,43,46],aw:27,awai:[3,30],awar:[0,3,26,27,41,46,54,55],ayncoreconnect:0,b:[3,4,12,14,15,18,34,35,36,38],back:[0,6,9,32,38],backoff:0,backpressur:0,backup:38,backward:[3,18,25,55],bad:0,badli:0,balanc:[0,3,33,42,55],bar:44,bark_all_night:37,base:[0,1,3,9,12,26,27,29,30,32,37,40,43,44,47,52,53,54],base_delai:27,basegraphrowfactori:12,basi:[0,55],basic:[0,3,12,37],batch:[0,1,3,9,10,12,14,25,27,33,35,38,48],batch_log:27,batch_obj:10,batch_object:9,batch_r:10,batch_typ:[10,30,34],batchqueri:[0,10,34,36,38],batchstat:[0,1,3,30,55],batchtyp:[0,10,30,34],bb984ee:55,beat_init:39,becam:[0,40],becaus:[0,3,4,15,18,27,30,32,40,41,44,46,53,55],becom:[0,3,8,49,55],been:[0,3,5,9,26,27,30,34,35,40,55],befor:[0,1,3,9,10,27,29,30,40,43,44,49,50,55],begin:[0,10,13,44],behav:32,behavior:[0,3,6,27,44,55],behind:[27,41],being:[0,3,6,26,30,36,42,44,46,47],below:[3,4,10,27,29,36,37,38,40,46,47,49,55],benchmark:[0,49],benefit:55,best:[27,44,51,54],beta5:1,beta:[1,46],beta_vers:1,better:[0,27,46,49],between:[0,2,6,29,30,46,53],bewar:27,beyond:37,big:[0,53],bigint:[6,15,18,44],binari:[0,6,30],binary_typ:29,bind:[0,3,12,30,43,44],bit:[6,32,46],bitmap:29,blacklist:27,blacklist_filter_polici:27,blah:44,blake:[9,38],blank:9,blind:[9,10],blindli:10,blist:0,blob:[0,6,17,44,53],block:[0,3,4,34,44,49],blog:49,bob:[3,30,44],bodi:[0,29],bool:[6,7,8,10,25,44,53],bootstrap:[0,26],bop:0,borrow_connect:0,both:[0,3,38,39,44,46,54],bound:[3,14,30,32,43,49],bound_stmt:3,boundstat:[0,30,44,55],bracket:47,brew:46,broadcast_address:27,broadcast_rpc_address:25,broadcast_rpc_port:25,broken:0,brought:55,brows:27,brute:27,bu:0,bucket_high:9,bucket_low:9,buffer:[0,17,44],bug:[40,45,55],build:[0,25,40,44,46,49],built:[0,32,42,46,49,55],bulk:12,bulkset:0,bump:0,bundl:52,busi:[3,28],bypass:[0,3,8,30],bytearrai:[0,17,44],bytebuff:0,bytecod:12,byteorderedpartition:[0,25],bytesio:0,bytestoken:25,c0:53,c:[0,6,12,25,27,38,54],ca:[0,27,54],ca_cert:54,cach:0,cacreateseri:54,cakei:54,calcul:0,call:[0,2,3,5,9,10,17,19,20,21,22,27,31,34,37,38,41,44,48,50,54],callabl:[6,10,12],callback:[0,3,10,44,49,54],callback_arg:3,callback_kwarg:3,camera:38,can:[0,1,3,4,6,8,9,10,13,14,15,17,18,21,25,27,29,30,31,32,34,35,37,38,39,41,42,43,44,45,46,48,49,50,52,53,54,55,56],cancel:0,cannon:40,cannot:[0,27,30,32,38,42],capabl:50,captur:[0,46],car:38,cardin:[15,18],care:[3,8],carri:34,cass_driver_build_concurr:46,cass_driver_no_cython:46,cass_driver_no_extens:46,cass_server_vers:0,cass_typ:32,cassandra:[0,33,34,35,36,37,38,39,40,42,43,46,48,49,50,52,53,54,56],cassandra_init:39,cassandra_vers:0,cast:44,cat:[37,40,54],caus:[0,3,10,26,37,47],caution:[8,37],caveat:27,cc94073:55,cdc:[0,27],cdef:0,ceas:27,ceil:1,celeri:48,cell:43,center:30,cento:[0,46],central:41,cert:54,cert_countri:54,cert_org_nam:54,cert_ou:54,cert_req:54,cert_requir:54,cert_valid:54,certain:[13,27,40,46],certfil:54,certif:[0,54],chain:34,challeng:[2,46],chanc:27,chang:[0,3,6,9,10,25,27,30,31,36,37,38,43,44,45],changelog:45,charact:[0,6,44],charl:30,check:[0,3,9,10,27,37,46,53,55],check_hostnam:[0,54],check_support:27,checkout:46,checksum:0,child:[0,27,43],child_polici:27,choic:[46,49],choos:[15,18,27,55],chosen:3,chunk:0,circuit:0,circumst:0,citi:55,civic:[10,35,38],cl:[0,10,21],clang:46,classic:0,classmethod:[1,9,15,18,19,20,21,22,25,29,32],claus:[0,10,25,37,47,55],clean:[0,39,46,55],cleanup:[0,20],clear:[0,14,27,30],clearer:41,client:[0,1,2,3,8,27,29,41,42,45,53],client_encryption_opt:54,client_protocol_handl:[3,29],clock:32,clock_seq:32,clone:[3,42],close:[0,3,5],closur:0,cloud:[0,3,27,45],cluster1:35,cluster2:[10,35],cluster3:35,cluster:[0,2,4,5,6,7,9,10,12,15,18,19,20,21,22,25,26,27,29,30,33,35,37,38,39,43,46,48,49,51,52,54,56],cluster_nam:52,cluster_opt:7,clustering_kei:38,clustering_ord:[6,37],clustertest:0,cn:54,code:[0,1,34,39,45,54,55,56],codebas:0,coerc:6,coincid:0,col:[0,47],col_nam:9,collect:[0,3,8,10,15,25,26,30,32,38,45,55],collis:0,colnam:[3,10,30],column:[0,8,9,10,11,13,17,25,30,33,35,36,37,38,44,47,48,55,56],column_family_nam:9,column_nam:[10,15,18,38],columnmetadata:[25,55],com:[6,10,53,54],combin:[0,3],come:0,comma:44,command:[0,35,46],comment:[9,10,37],comment_id:[10,37],common:[0,40,46,54,55],commun:[0,5,46],compact:[0,9,53],compar:[0,30,32,45],comparison:[0,6],compat:[0,3,18,25,33,55],compil:[0,29,46,49],complain:37,complet:[0,1,2,3,4,11,27,30,34,37,40,43,44,49,54],complex:[0,42,46],compliant:0,compon:[0,10,25,30,32,54],compos:29,composit:[0,30,38],compositetyp:0,compound:6,compress:[0,3,29],compressor:29,compris:[1,29],comput:[0,3,9,43],concern:41,concis:15,concurr:[0,3,8,30,33,43,44,49],condit:[0,1,3,8,10,30,45],conf:54,config:[0,54],configur:[0,1,2,3,5,7,9,15,18,27,31,42,44,45,53],configurationexcept:1,confirm:0,conflict:36,confus:[40,55],conn:35,connect:[0,1,2,3,4,8,9,10,11,12,19,20,22,23,24,26,27,30,33,37,38,39,40,42,45,46,48,51,52,53,54,55,56],connect_timeout:[0,3],connect_to_remote_host:3,connected_to:26,connection_class:[3,46,54],connection_error:26,connection_exc:27,connectionbusi:5,connectionexcept:[0,5],connectionshutdown:5,consensu:1,consid:[0,1,3,18,27,44,47,49,54,55],consider:[37,49],consist:[0,1,3,7,10,27,30,32],consistency_level:[3,15,18,30,42,44],consistencylevel:[0,1,3,7,10,15,18,26,27,30,40,44],consit:0,constant:[0,54],constantreconnectionpolici:[0,27],constantspeculativeexecutionpolici:[0,27,44],constrain:[4,10],constraint:[9,37],construct:[0,9,12,32,41,42,44],constructor:[0,3,6,38,52],consult:37,consum:[0,4,55],consumpt:[0,49],contact:[0,3,27,44],contact_point:[0,3,7,27,54],contain:[0,3,6,9,10,13,17,27,32,37,38,41,47,50,53],contains_kei:13,contains_valu:13,contend:0,content:[0,10,29],context:[0,3,8,9,10,12,15,18,34,39,46,49,54],contextqueri:[0,10,35],contin:0,continu:[0,2,27,50],continuous_paging_opt:3,contract:[0,29],control:[0,3,4,27,30,40,49,54],control_connection_timeout:3,conveni:[3,15,18,30,38],convent:37,convers:[15,18,40,41,55],convert:[0,13,15,17,18,32,40,41,55],convict:27,conviction_policy_factori:3,convictionpolici:27,coord:32,coordin:[1,3,4,27,32,43],coordinationfailur:1,copi:42,copyright:0,core:[0,3,4,38,40,46,49],core_connect:3,coroutin:0,correct:[0,9,41],correctli:[0,3],correspond:[2,4,6,8,37],cost:[0,9,10,38],costli:46,could:[0,10,55],count:[0,9,10,26,27,36,38,48],counter:[0,6,26,27,30,37,44],countri:45,cours:3,cover:[37,43],coverag:0,cpu:[0,4,44,49],cpython:[0,3,46],cql3:[36,38,45],cql:[0,1,6,9,10,11,13,15,17,18,25,30,32,36,37,38,40,41,47,48,53,55,56],cql_cluster:39,cql_encode_all_typ:17,cql_encode_byt:17,cql_encode_d:17,cql_encode_datetim:17,cql_encode_list_collect:17,cql_encode_map_collect:17,cql_encode_non:17,cql_encode_object:17,cql_encode_sequ:17,cql_encode_set_collect:17,cql_encode_str:17,cql_encode_tupl:[17,55],cql_encode_unicod:17,cql_keyword:25,cql_keywords_reserv:25,cql_keywords_unreserv:25,cql_refer:10,cql_session:39,cql_use:6,cql_version:[0,3],cqlcollect:13,cqle:0,cqlengin:[0,33,34,35,36,37,38,39,43,45,48,55],cqlengine_batch:34,cqlengine_test:38,cqlengineexcept:[0,40],cqltype:55,cqluseudt:6,crash:0,creat:[0,1,2,3,5,6,7,8,9,10,12,25,27,30,32,34,35,36,37,38,41,43,44,47,48,49,53,54,55,56],create_default_context:54,create_execution_profil:12,create_keyspac:40,create_keyspace_network_topolog:[8,40],create_keyspace_simpl:[8,40],create_simple_keyspac:35,created_at:[34,48],creation:[0,3,4,25,38],credenti:[0,3,52,54],credit:44,crt:54,crt_sign:54,crypto:54,csr:54,cstringio:0,cumbersom:41,current:[0,1,3,10,12,26,27,30,31,38,42,43,46,50,55],current_pag:3,current_row:3,custom:[0,1,3,6,10,17,27,30,33,41,42,44,46],custom_index:6,custom_payload:[3,15,18,29,30],cut:0,cute:37,cycl:3,cython:[0,29],cython_protocol_handl:3,cythonprotocolhandl:3,d:[3,6,10,30,41,44],daemon:0,dai:[6,27,32,54],dash:0,data:[0,1,3,9,10,27,30,33,37,38,41,43,44,53,55,56],data_retriev:[1,27],databas:[6,8,9,34,37,38,41,42,52],datacent:[0,1,27,28,52],dataset:[0,10,38],datastax:[0,6,10,18,27,44,45,46,48,54,55],datastream:38,datatyp:0,date:[0,6,17,32,44,45,55],daterang:[0,32],daterangebound:32,daterangeprecis:32,datetim:[0,6,10,17,32,34,36,38,40,41,44,48],datetime_from_timestamp:32,datetime_from_uuid1:32,datetyp:0,david:13,daylight:41,days_from_epoch:32,db:0,db_field:[0,6],dc:[0,3,27,55],dc_name:8,dc_replication_factor:25,dc_replication_map:8,dcawar:0,dcawareloadbalancingpolici:0,dcawareroundrobinpolici:[0,3,27,42,52],dclocal_read_repair_ch:0,dct:0,dd:[17,32],ddl:0,dead:33,deadlock:[0,4],deal:[0,41,42,49,55],debian:[0,46],debug:[0,3],decemb:0,decid:27,decim:[0,6,10,38,44],decimaltyp:0,decis:[0,26,41],declar:[11,37],decod:[0,3,29,30,33,55],decode_messag:29,decomiss:0,decommiss:[0,27],decompress:29,decompressor:29,decor:0,decrement:6,deem:41,def:[3,27,34,37,39,43,44,50,52,54,55,56],defacto:41,default_bit:54,default_consistency_level:[0,3,7,42],default_fetch_s:[3,50],default_keyspac:[0,7],default_retry_polici:[3,27,42,43],default_serial_consistency_level:[0,3,42],default_time_to_l:[0,38],default_timeout:[3,42],defaultloadbalancingpolici:[0,27,55],defer:[0,10,27],defici:41,defin:[0,1,2,3,6,8,9,10,15,18,25,27,30,33,35,38,40,42,44,45,48],definit:[0,3,6,15,29,38,40],defunct:[0,3,5],degre:13,delai:[0,27,44],deldyck:37,delet:[0,8,9,10,27,30,34,38],delete_keyspac:40,deliv:3,deliveri:3,demand:0,demonstr:54,dep:0,depend:[0,2,41,43,47,49],deploi:52,deploy:54,deprec:[3,9,16,27,54],deprecationwarn:[0,55],depth:0,dequ:0,deriv:[32,37,40,42,46,55],derivi:9,desc:37,descend:[10,37,38],describ:[1,27,29,32,38,40,41,54],descript:[0,3,15,18,27,30,34,43,48,54],descriptor:0,deseri:[0,15,18,33,41],deserialize_bigint:[15,18],deserialize_blob:[15,18],deserialize_d:[15,18],deserialize_decim:[15,18],deserialize_doubl:[15,18],deserialize_dur:[15,18],deserialize_float:[15,18],deserialize_int:[15,18],deserialize_linestr:[15,18],deserialize_point:[15,18],deserialize_polygon:[15,18],deserialize_tim:[15,18],deserialize_timestamp:[15,18],deserialize_uuid:[15,18],design:[44,49],desir:[3,10,27,34],despit:10,destroi:0,detail:[0,1,3,9,10,30,37,41,42,43,44,49,53,54,55],detect:[0,40],determin:[6,9,27,30,44],determinist:0,dev:[46,53],devel:46,deviat:26,devic:0,dict:[0,1,3,6,7,8,9,12,15,17,18,25,26,29,30,37,44,47,53,54],dict_factori:[0,3,7,16,30,55],dictionari:[0,6],dictlik:32,did:[5,10,27],didn:10,differ:[0,3,10,29,30,32,36,37,38,42,44,54,55],digest:27,dir:0,directli:[3,4,17,29,30,44,46,54],disabl:[0,3,9,10,46,53],disable_shardaware_port:53,discontinu:0,discourag:3,discov:[0,3,27,44],discoveri:0,discrimin:[6,9,37],discriminator_column:[6,37,40],discuss:[3,6,11,30,37,45,47,49],disentangl:0,disk:6,dispos:3,disproportion:27,distanc:[13,27,32],distant:27,distinct:[0,10,15,18],distinct_field:10,distinguish:0,distinguished_nam:54,distribut:[0,27,38,46],distrimin:37,distriminator_column:37,dll:0,dn:27,doc:[0,1,6,10,37,38,41,53,54],document:[0,6,27,32,41,42,45,46,48,54,55],doe:[0,3,10,17,32,34,38,40,44,46,47,56],doesn:[0,31,55],doesnotexist:[0,10],dog:[37,40],dollar:0,don:[0,10,38,44,49,56],done:[0,3,37,41,43,54,55],dont:0,dontprepareonignoredhoststest:0,doubl:[0,6,15,18,32,44,49,55],double_precis:[40,55],down:[0,3,33,46],downgrad:[0,27],downgradingconsistencyretrypolici:[0,27,44],download:52,drain:0,drift:31,driven:8,driver:[0,1,3,5,7,10,18,26,27,28,29,30,37,38,40,41,44,46,47,48,49,50,51,52,53,54,56],driverexcept:1,drop:[0,6,8,29],drop_keyspac:[8,40],drop_tabl:8,drope:0,dsa:0,dse:[0,1,3,6,12,14,15,18,32],dse_graph:55,dse_graph_query_languag:12,dse_graph_query_protocol:12,dse_v1:[0,1],dse_v2:1,dsegraph:12,dsegssapiauthprovid:[0,54],dseloadbalancingpolici:[0,27,55],dseplaintextauthprovid:54,dsesessionremotegraphconnect:12,dsl:12,dt:32,due:[0,1,10,26,34,49],duplic:0,durabl:3,durable_writ:8,durat:[0,30,32],durationtyp:0,dure:[0,1,2,3,5,9,40,46],dynam:[0,3],dynamiccompositetyp:0,e0b9a54a6d93:44,e16a073:55,e:[3,8,9,10,12,15,18,27,30,43,46],each:[1,2,3,4,6,9,27,30,36,37,38,41,44,50,55,56],each_quorum:1,eagain:0,eai:0,earlier:[0,21,37],eas:35,easi:[0,37,38],easier:[38,42,46],easiest:[41,46],easili:[0,10,41],east:52,eat:37,ec2:0,ec2multiregiontransl:27,ed:0,edg:[0,15,18,25],edgemetadata:25,effect:[0,3,8,34,54],effici:[0,29],effort:[0,40,54],eggleston:9,either:[2,3,15,18,32,37,38,41,45,46],element:[0,3,10,15,18,25,32,38,44],elementmap:0,els:[4,39,50],em1:[34,48],em2:[34,48],em3:[34,48],em4:48,em5:48,em6:48,em7:48,em8:48,email:44,emit:[3,40,46],empti:[0,2,3,25,47],en:[6,10],enabl:[0,3,10,44,53,54,55],enable_shard_aware_driv:53,encod:[0,3,6,15,18,29,33,41],encode_messag:29,encount:[0,3,10],encrypt:[0,54],end:[0,10,34],endian:0,endless:0,endors:45,endpoint:[5,25,27,28,52,54],endpoint_factori:3,endpoint_or_address:25,endpointfactori:[5,54],enforc:[0,37],engag:46,engin:[0,3],enough:[1,30],ensur:[0,3,4,9,27,39,46,54],enterpris:53,entir:[0,3,4,10,14,25],entiti:0,entri:[10,13,17,55],entry_eq:13,environ:[8,27,46],eof:54,ep:[3,44],epoch:[0,31,32,41],eq:0,equal:[0,3,6,30,38],equival:[9,36,41,44],errback:[0,3,44,50],errback_arg:3,errno:0,error:[0,1,3,4,5,6,10,27,44,50],error_code_map:1,errro:1,escap:[0,17],especi:[0,8,42,46],essenti:38,establish:[3,44],etc:[3,10,26,27,38],evaluate_challeng:2,even:[0,3,7,27,30,41,42,44],evenli:27,event:[0,3,4,21,27,30,33,39,43,44,46,50,54],eventlet:[0,33],eventletconnect:[21,54],eventletreactor:33,everi:[0,27,31,38,39,44],everyon:46,evict:0,evolv:42,ewouldblock:0,exact:2,exactli:[0,27,40],examin:32,exampl:[0,2,3,4,6,9,10,11,25,30,32,35,36,38,40,42,43,44,46,47,48,49,50,51,53,55,56],example1:48,example2:48,example3:48,example4:48,example5:48,example6:48,example7:48,example8:48,example_id:48,example_mapp:0,example_typ:[34,48],examplemodel:[34,48],exc:[3,50],exce:[0,50],exceed:[3,4],except:[0,3,4,5,6,7,9,10,15,18,27,28,29,30,32,33,34,37,38,39,44,50,54],excess:0,exclud:38,exclus:[7,32,45],exec_profile_default:[3,42,44,52],exec_profile_graph_analytics_default:3,exec_profile_graph_default:[3,12,55],exec_profile_graph_system_default:3,exect:0,execut:[0,1,3,8,9,10,12,14,15,18,25,27,29,30,33,35,37,38,43,45,47,49,50,53,56],execute_a:[3,54,55],execute_async:[0,3,4,29,43,44,49,50],execute_concurr:[0,4,49],execute_concurrent_with_arg:[4,49],execute_graph:[3,15,18],execute_graph_async:3,execute_on_except:[10,34],execution_profil:[3,4,12,14,42,44,52],execution_profile_clone_upd:[3,42],executionprofil:[0,3,12,42,44,52],executionresult:4,executor:0,executor_thread:3,exhaust:[0,27],exist:[0,1,3,8,9,10,27,28,42,47,48,53,55],exit:0,expand:0,expect:[0,5,9,43,47,54,55,56],expens:3,experi:4,experiment:[0,19],expir:3,explain:[0,42],explicit:[0,40,41],explicitli:[0,1,3,10,15,18,34,37,55],explod:42,explor:38,exponenti:[0,27],exponentialreconnectionpolici:[0,3,27],export_as_str:[0,25],export_for_schema:[0,25],export_schema_as_str:25,expos:[0,31,55],express:[4,13,32],extablish:3,extend:30,extens:[0,3,27,41,53],exterior:32,extern:41,extra:[0,25,30,46],extra_deserializer_map:[15,18],extract:[15,18],ey:45,f:3,facilit:29,factor:[0,8,25],factori:[3,12,33,47],fail:[0,1,3,4,7,14,15,18,26,33,34,37,44,47],failur:[0,1,7,9,26,33,34],fairli:37,fall:[0,32],fallback:[10,27,55],fallthroughretrypolici:27,fals:[3,4,6,7,8,9,10,15,18,25,27,30,47,48,53,54,55],falsei:27,falsi:27,famili:[0,5,9],faq:[43,45],fashion:3,faster:[0,33,46],favor:[27,40,53,55],feather:45,featur:[12,19,33,38,40,45,46,54],feb:0,februari:0,fedora:46,feedback:0,felcei:13,fetch:[0,3,10,30,38,44,50,55],fetch_next_pag:3,fetch_siz:[0,3,10,15,18,30,50,55],few:[3,44,46],field:[0,3,6,8,9,10,11,30,32,37,38,44,56],fieldnam:6,fierc:37,file:[0,40,49,52,54],fill:[15,18,30],filter:[0,6,9,27,33,35,48],finalis:1,find:[13,25,41,46],fine:56,finished_ev:50,finit:27,first:[0,3,4,6,7,9,27,36,37,38,40,44,45,46,48,50,54,55],first_nam:[9,37],first_pag:38,first_result:55,first_row:56,five:3,fix:[27,46,54,55],flag:[0,3,6,9,29,37,46,53],flake:0,flask:43,flat:38,flexibl:[0,45],flight:[0,5],flow:0,fluent:[0,33,46,55],fly:[0,4,9,10,35],fn:[3,10],focu:27,follow:[0,3,26,27,29,34,35,37,40,41,42,44,46,47,54,55],foo:[44,56],food:37,footprint:[4,38],forc:[0,27,54],force_token_rebuild:3,forev:[21,27,30],fork:[0,20,43,45,49],form:[1,17,32,44],format:[0,1,3,17,25,29,30,33,41,44,52,54,56],formerli:0,forward:[1,27,40],found:[0,10,25,30,45,49,54,55],foundat:45,four:32,fqdn:[0,54],fraction:32,frame:29,fraudul:0,free:44,frequent:[27,44,45,48],from:[1,2,3,4,5,6,8,9,10,11,12,15,18,20,25,27,29,30,32,34,35,37,38,39,40,42,43,44,45,46,47,48,50,52,53,54,56],from_datetim:55,from_kei:0,from_str:25,from_valu:32,from_wkt:32,frozen:[0,32,56],frozenset:44,full:[0,30,55],full_replica:25,fulli:55,functionfailur:1,functon:38,further:[3,4,27,38,43,49,54],furthermor:27,fuse:46,futur:[0,3,6,7,30,31,40,43,44,46,49,50,55],fuzzi:13,g:[0,3,12,15,18,27,30],garbag:[0,55],gc:0,gc_grace_second:9,gcc:46,gen_client_cert:54,gener:[0,1,2,4,27,29,32,33,41,44,53,54,55],geo:[0,13],geom:0,geomet:0,geometri:[13,32],geospati:0,geounit:13,get:[0,3,8,9,10,25,27,38,46,52],get_all_query_trac:[3,55],get_clust:52,get_control_connection_host:3,get_core_connections_per_host:3,get_credenti:54,get_execution_profil:[0,3],get_host:[0,25],get_host_by_host_id:25,get_lower_support:1,get_max_connections_per_host:3,get_max_requests_per_connect:3,get_min_requests_per_connect:3,get_query_trac:[0,3,43,55],get_replica:[0,25,43],get_stat:26,getstat:26,getter:[15,18],gevent:[0,33],geventconnect:[0,22],geventreactor:[0,33],gil:[0,49],github:[0,45,48,53],give:[3,27,54,56],given:[0,3,10,25,27,28,32,34,38,49],global:[0,7,43],go:[0,40,51],goal:[49,54],goe:0,good:[40,45],got:55,govern:[3,27],gracefulli:0,grant:54,graph:[0,3],graph_graphson2_row_factori:[15,18],graph_graphson3_row_factori:[3,15,18],graph_languag:[15,18],graph_nam:[12,15,18],graph_object_row_factori:[3,15,18],graph_opt:[0,3],graph_protocol:[3,12,14],graph_read_consistency_level:[15,18],graph_result_row_factori:[15,18],graph_sourc:[0,3,15,18],graph_traversal_dse_object_row_factori:12,graph_traversal_row_factori:12,graph_write_consistency_level:[15,18],graphanalyticsexecutionprofil:3,graphexecutionpolici:3,graphexecutionprofil:3,graphopt:[0,15,18],graphprotocol:[3,14,15,18],graphson1:[15,18],graphson1deseri:[15,18],graphson1seri:[15,18],graphson2:[0,15,18],graphson2read:[15,18],graphson3:[0,12,15,18],graphson3read:18,graphson:[0,12,14,15,18],graphson_1_0:[3,15,18],graphson_2_0:[14,15,18],graphson_3_0:[3,15,18],graphsonwrit:14,graphstat:[0,3,14],graphtravers:[12,14],graphtraversalsourc:12,greater:[27,50],greatli:0,greenlet:0,gremlin:[0,3,12,14,15,18,46],gremlinpython:[0,46],greplin:[0,26],groovi:[15,18],group:25,group_keys_by_replica:25,grow:0,gssapi:2,guarante:[0,27,30,55],guard:8,guid:[0,44,45,46,48,54],gx:0,h:[0,43],ha:[0,3,5,10,26,27,30,38,40,41,44,46,47,54,55,56],had:[0,40,55],handl:[0,2,3,9,10,12,29,33,38,39,41,43,44,46],handle_err:50,handle_error:[4,44,50],handle_fork:20,handle_pag:50,handle_result:3,handle_success:44,handle_writ:0,handler:[0,2,10,15,18,27,29,50],handshak:2,hang:[0,46],happen:[0,3,27],hard:46,has_more_pag:[0,3,50],hash:[0,38,46],hashabl:[0,32],hasn:0,have:[0,2,3,4,6,9,10,15,17,18,26,27,34,35,36,37,38,40,42,44,46,47,54,55,56],header:[0,29,46],healthmonitor:0,heap:0,heartbeat:0,help:[0,38,55],here:[3,9,10,34,35,37,38,39,40,41,46,48,52,54],hex:0,hh:32,high:[0,48,49],higher:[1,3,4,30,54,55],highli:44,highlight:55,hint:1,hit:[3,5],hold:[0,25,29],holder:44,homebrew:[0,46],honda2012:38,honda:[10,35,38],honor:[0,44],hook:[39,43],host1:27,host2:27,host3:27,host:[0,1,2,3,4,7,25,33,35,43,48,52,53,54,55],host_address:54,host_dist:3,host_id:25,hostconnect:0,hostdist:[0,3,27],hostfilterpolici:[0,27],hostfilterpolicyinittest:0,hostnam:[0,27,54],hoststatelisten:3,hot:46,hour:32,how:[0,1,4,6,9,27,30,38,39,41,42,44,45,47,50,54,55],howev:[0,3,10,30,34,37,38,41,46,47,50,55,56],html:[6,10,38,48],http:[6,10,27,38,48,50,53],huge:49,human:[25,41],i:[8,10,15,18,27,30,38],id:[0,3,4,6,9,10,15,18,29,34,36,37,38,44,54,56],idea:27,ideal:[32,41],idempot:[33,44],identifi:[0,1,37,47],identitytransl:[3,27],idl:0,idle_heartbeat_interv:3,idle_heartbeat_timeout:[0,3],ids_to_fetch:44,ie:[13,50,54],if_exist:[9,10],if_not_exist:[9,10],iff:9,ifnotexistswithcountercolumn:40,ignor:[0,3,8,26,27,29,30,44],ignored_address0:27,ignored_address1:27,imagin:27,immedi:[1,3,34,44],immut:[0,32,48],impact:4,implement:[0,2,3,5,15,18,19,20,21,22,23,24,27,29,32,41,46,49,50,54,55],impli:[30,45],implicit:[0,10,55],implicitli:[3,8,37],importerror:39,impos:37,improv:[0,1,35,49,55],in_memori:53,inbetween:27,includ:[0,3,9,10,25,26,40,45,49,54,55,56],include_keyspac:9,inclus:3,incomplet:0,inconsist:0,incorrect:[0,44],incorrectli:[0,30],increas:[0,27,31,46],increment:6,incur:9,indefinit:0,independ:[32,54],indetermin:3,index:[0,3,6,25,37,38,48,55],indexmetadata:25,indic:[0,1,2,3,6,8,9,10,25,27,38,47,53],individu:3,inet:[0,1,25],inet_address:0,inet_ntop:0,inet_pton:0,infin:0,infinit:[0,27],inflat:29,influenc:27,info:[0,3,33,44],inform:[0,3,5,9,25,27,41,52],inherit:[0,6,9,11,42],init:[0,3,36,40],initi:[0,2,3,5,6,7,9,15,18,27,29,31,32,35,38,39,44,46,47,54],initial_respons:2,initialize_reactor:[19,20,21,22],inititi:40,inject:[3,42,46],inmemorycompactionstrategi:53,inplac:32,input:[0,30,40,41,42],insanc:41,insensit:9,insert:[0,1,3,4,9,10,30,32,36,37,41,44,47,55,56],insert_stat:56,insert_us:30,insid:[13,34,44],insight:0,inspect:[3,8],instal:[0,40,44,45,49,54],instanc:[0,2,3,6,9,10,13,15,18,25,26,27,30,34,38,44,48,50,54,55,56],instanti:[0,27,29,31,44],instead:[0,3,4,30,38,40,44,50,54,55],instruct:38,insuffici:[0,26],intact:42,integ:[0,6,10,11,13,17,31,32,35,36,37,38,41,48],integer_typ:32,integr:[0,29,40,41,45,46,48,55],intend:[9,31,32,46],intent:40,interact:[3,44],interfac:[0,2,27,50],interior:32,intern:[0,3,10,27,31,32,40,41,55],interpol:56,interpret:[0,30,36,38,55],intranod:53,intrins:41,introduc:[0,19,25,30,37,38,40,42,55,56],introduct:45,intruct:54,intstat:26,inupt:0,inv:[15,18],invalid:[0,1,26,30],invalidparametertypeerror:0,invalidrequest:1,invalidtypeparametererror:0,invit:40,invlabel:[15,18],invoc:46,invok:[0,3,40],involv:[30,38],io:[0,3,4,10,33,46,48,54],ip:[0,3,5,27,28,44,54],ipv4address:0,ipv6:0,ipv6address:0,irc:0,iron:40,is_analytics_sourc:[15,18],is_cql_compat:25,is_default_sourc:[15,18],is_graph_sourc:[15,18],is_idempot:[0,15,18,30,44],is_schema_agre:3,is_seri:0,is_shard_awar:53,is_shutdown:0,is_up:0,isbootstrap:27,isn:[0,9,10],isnotnul:38,isoformat:0,isol:27,issu:[0,2,27,31,32,36,55],item1:17,item2:17,item:[0,4,9,10,15,18,27,30,32,37,38,44],iter:[0,3,25,27,29,30,32,38,50,55],its:[0,2,3,5,9,19,20,23,24,27,30,32,37,42,46,54,55],itself:[46,55],jan:0,januari:0,java:27,jit:49,jitter:[0,27],jk:54,joe:[37,54],john:44,join:0,jon:[10,37,38],json:[3,12,15,18],json_data:[15,18],juli:0,jump:48,junctur:40,june:0,just:[0,3,6,25,27,32,34,37,40,44,46,50,53,56],k:[34,47,54],keep:[0,27],keepal:0,kei:[0,1,3,6,8,9,10,13,15,25,26,27,29,30,32,37,38,42,43,44,47,53,54,56],kept:4,kerbero:[0,54],kevin5000:37,kevin:37,key1:17,key2:17,key_typ:6,keyerror:0,keyfil:54,keyout:54,keyspac:[0,1,3,7,8,9,10,11,15,18,25,27,29,30,35,43,53,55],keyspace1:53,keyspace_nam:55,keyspacemetadata:[0,25],keystor:54,keystore_password:54,keyword:[0,3,6,7,9,10],kill:0,kimberli:9,kind:[0,27,55],kinit:54,klass:3,know:[3,27,36,55,56],known:[0,15,18,25,40,55],known_host:26,ks1:35,ks2:35,ks:35,ks_name:8,kwarg:[0,3,4,6,7,9,10,12,15,18,19,20,21,22,23,27,32,34,39,54],label:[15,18],lambda:54,languag:[12,15,18,40,45,49],larg:[0,3,4,10,32,38,45,55],largest:36,last:[0,1,3,27,31,38],last_act:3,last_host:1,last_nam:[9,37],lastest:36,latenc:[26,44,53],later:[0,1,9,27,44,50],latest:[0,55],latter:[3,50],layout:25,lazi:0,lazili:29,lazy_connect:[0,7],lazyprotocolhandl:29,lbp:0,lead:[0,34,49,55],leak:0,learn:[30,54],least:[6,26,27,30,35,37,46],leav:[0,3],left:[0,3,4,9,41,55],legaci:[0,6,40,48,54,55],len:[0,9,10,35],length:[6,27,30],less:[0,46],let:[0,3,55],letter:13,level:[0,1,3,4,10,15,18,27,30,33,41,48,54],leveledcompactionstrategi:9,lib:0,libev4:46,libev:[0,33],libevconnect:[3,23,46],libevreactor:[0,3,33,46],libevwrapp:0,librari:[0,19,20,41,46,54],licens:45,lifecycl:2,lightweight:[0,1,10,30,44,45],lighweight:27,like:[0,1,3,4,9,10,15,18,26,27,30,37,38,41,44,46,50,54,56],limit:[0,3,10,30,38,41,49],line:[0,19,44,46],linear:32,lineariz:30,linestr:32,link:[0,41,46],linux:46,list:[0,1,3,4,6,7,8,9,10,13,15,17,18,25,27,29,30,32,35,43,44,45,46,48,50,55],list_col:44,list_column:10,list_column__append:10,list_column__prepend:10,listen:[0,3],listen_address:0,liter:[0,15,17,18,30,41,44,55,56],live:[1,27,43],ll:[38,54],load:[0,3,9,10,15,18,33,37,38,40,42,53,54,55],load_balancing_polici:[3,27,42,44,52,53],load_cert_chain:54,load_verify_loc:54,loadbalancingpolici:[0,3,27,42],local:[0,1,3,27,30,41,42,43,44,55],local_dc:[0,27,52],local_on:[0,1,3,44],local_queri:42,local_quorum:[0,1,44],local_seri:[1,30,44],localhost:[7,10],localstrategi:25,localtim:41,locat:[3,40,54,56],lock:0,locked_execut:42,log:[0,3,8,27,30,31,44,45,55],log_error:3,log_result:3,logentri:34,logger:0,logic:[0,37,53],logo:45,longer:[0,1,55],look:[13,37,38,54],lookup:[0,25,27],loop:[0,3,4,21,33,44,46,54],lose:0,loss:0,lot:[0,53],low:[15,18,27,33],lower:[1,4,27,32,38,44],lower_bound:32,lowercas:0,lwt:[0,3,9,47],lwtexcept:[0,9,10,40],lz4:[0,46],m:[9,36],mac:[0,46],machin:44,madd:46,made:[1,3,5,27,38,44,55],mai:[0,2,3,4,6,7,27,30,32,37,38,43,44,46,49,54,55],main:[0,3,54,56],maintain:[0,3,30,32,37,55],major:[0,27,42,54,55],make:[0,1,3,10,25,27,37,40,41,42,43,44,45,46,48,51,54,55],make_query_plan:27,make_token_replica_map:0,manag:[0,3,6,9,10,11,28,33,34,37,42,46,48,55],mandatori:[0,3],mani:[0,1,3,4,27,44,49,50,54,55],manifest:[0,43,47],manipul:[0,3],manner:32,manual:[3,9,34],manufactur:[10,35,38],map:[0,1,3,8,10,13,15,17,18,25,29,30,32,33,37,38,44,48,55],map_column:10,map_column__remov:10,map_column__upd:10,mapper:[0,7,40,45],march:0,margin:4,mark:[0,3,5,33,44,45],marker:41,master:[0,3,53],match:[0,3,5,9,10,15,18,25,30,38,40,42,43,44,46,54,55,56],materi:[0,3,4,25,29,46,55],materializedviewmetadata:25,math:0,max:[0,3,5,26,44],max_attempt:[27,44],max_connect:3,max_delai:27,max_length:6,max_request:3,max_schema_agreement_wait:3,max_support:1,max_threshold:9,max_tim:38,max_uuid_from_tim:32,max_wait:[3,30],max_wait_sec:3,max_wait_sec_p:3,maximum:[1,3,6,27,32,38],maxtimeuuid:38,maxyear:[32,41],md5token:25,md:53,mean:[3,9,26,27,38,44],meaningless:38,meant:41,measur:[3,27],mechan:[0,2,3,27,54],median:26,meet:[26,27,54],member:[32,37],memori:[0,4,38,53,55],mention:[0,41,44],merg:40,mesh:55,messag:[0,1,2,3,5,29],message_types_by_opcod:29,meta:[0,3,37],metadata:[0,3,15,18,27,30,33,42,43,52,53],method:[0,2,3,9,10,27,29,30,35,36,37,38,41,43,44,46,49,53],metri:26,metric:[0,3,33],metrics_en:3,micro:32,microsecond:[0,31,55],middl:13,might:[0,3,30,50,54],migrat:[48,55],millisecond:[0,17,32,41],millsecond:41,min:[0,26,43],min_length:[0,6],min_request:3,min_support:1,min_threshold:9,min_tim:38,min_uuid_from_tim:32,minim:[3,40,41,44],minimalist:32,minimum:[1,3,6,32,38],mintimeuuid:38,minut:[0,32,46],minyear:[32,41],mismatch:0,misplac:0,miss:[0,27],misspel:13,mistak:40,mitig:49,mix:[0,30],mke:0,mm:[17,32],mmmuuunnn:32,mno:46,mock:0,mode:0,model:[0,3,8,33,38,43,48,55],model__lik:38,modelexcept:40,modelqueryset:10,modern:0,modif:8,modifi:[0,1,8,9,10,32],modul:[0,9,11,18,19,20,40,46,49],monkei:[0,21,22,54],monkey_patch_loop:0,monoton:0,monotonictimestampgener:31,month:32,montonictimestampgener:0,more:[0,3,4,6,9,10,15,25,27,29,31,38,40,42,44,45,49,50,54,55],most:[3,27,30,37,40,41,43,50],mostli:[18,47],move:[0,3,30,55],ms:32,ms_timestamp_from_datetim:32,msg:29,much:[37,41,54,55],multipl:[0,3,10,12,14,15,18,27,34,35,44,48,49,55],multipleobjectsreturn:[0,10],multipli:13,multiprocess:0,multithread:0,murmur3:[0,3,46],murmur3partition:[0,25,46],murmur3token:[0,25],mussei:[46,54],must:[0,1,3,4,10,30,32,37,38,44,46,54,55,56],mutabl:[0,3],mutat:48,mutual:[7,32],mv:27,my:54,my_callback:34,my_graph:12,my_tabl:44,my_user_id:30,mycf:3,mykeyspac:[3,30,44,55,56],mymod:36,mymodel:36,mystery_funct:34,mystorepass:54,mytabl:4,n:10,naiv:[6,41],name:[0,1,3,7,8,9,10,11,12,13,15,18,25,26,27,29,30,34,37,40,44,47,56],named_arg:34,named_tuple_factori:[0,3,16,30,55],namedt:38,namedtupl:[0,3,4,30,37,44,47,55,56],namedtuple_factori:0,nan:[0,32],nanosecond:[6,32,41],nativ:[0,1,15,18,29,37,45],native_shard_aware_transport_port:53,native_shard_aware_transport_port_ssl:53,native_transport_address:0,natur:2,necessari:[3,44,46,54],need:[0,1,3,6,12,27,30,32,34,35,36,37,38,39,44,46,49,53,54,55,56],neg:[0,32,38],negoti:2,nest:[0,32],net:27,network:[0,30,44],networktopologystrategi:[0,8,25],never:[0,27,34,47,49,55],neverretrypolici:3,new_authent:2,new_nod:0,new_plan:27,new_schedul:27,newkei:54,newli:[0,25,27],next:[0,3,21,27,42,48,50,54],next_pag:38,ngdg:0,nice:0,nicer:38,no_compact:0,no_valid_replica:25,noconnectionsavail:28,node1:42,node1_profil:42,node1_whitelist:42,node2:42,node2_profil:42,node:[0,1,3,5,25,26,28,30,32,33,44,53,54],node_domain:5,nodesync:0,nodetool:27,nohostavail:[0,3],nomenclatur:55,non:[0,3,6,10,32,33,37,44,45],nonblock:0,none:[0,1,2,3,4,5,6,7,8,9,10,11,12,14,15,17,18,25,26,27,30,32,36,38,39,41,43,44,47,50],nonetyp:0,nonexist:[0,1],normal:[0,3,9,10,12,27,30,32,41,44,50],nose:0,notabl:55,note:[0,3,4,7,8,9,10,19,27,30,32,35,37,38,40,41,42,44,45,50,54,55],noth:[0,25,27],notic:0,notif:0,notifi:3,nov:0,novemb:0,now:[0,31,34,36,38,40,41,44,48],nt:0,nullhandl:0,num:26,number:[0,1,3,4,5,9,10,26,27,40,42,44,46,47,50],numer:[0,41],numpi:29,numpyprotocolhand:29,numpyprotocolhandl:[0,29],o:[44,54],obj:[15,18],object:[0,3,4,12,15,17,18,25,26,27,30,31,32,34,35,36,37,41,42,43,44,45,49,50,55,56],obtain:[3,10,43,49],occur:[1,27,30,34,44,55],oct:0,octob:0,od:32,off:3,offer:[32,46,49,50],offici:[54,55],offset:32,often:37,ok:[27,54],old:[0,10,40],omit:[1,30],on_add:27,on_authentication_success:2,on_down:27,on_read_timeout:27,on_remov:27,on_request_error:[0,27],on_unavail:27,on_up:[0,27],on_write_timeout:[0,27],onc:[3,4,19,20,21,22,27,29,30,34,36,38,46,50,53],one:[0,1,2,3,6,10,13,26,27,30,32,35,36,37,38,42,44,53,54,55],ones:[10,40],onli:[0,1,3,4,5,6,7,8,9,10,18,19,27,30,31,34,37,38,40,41,44,45,46,47,53,54,55],onward:53,op:38,opaqu:3,opcod:29,open:[0,2,3,26,27,28,32,45],open_connect:26,openssl:54,oper:[0,1,3,5,8,9,10,15,18,30,32,33,35,44,47,55],operationtimedout:[0,1,3],opertaion:0,oppos:27,optim:[0,45,46,49],option:[0,1,2,3,5,7,9,10,11,12,14,25,29,30,33,38,40,42,44,47,48,49,53,54,55,56],option_map:25,options__contain:38,options_map:25,order:[0,1,4,6,10,25,27,30,32,34,37,41,55],order_bi:[10,38],ordered_dict_factori:[0,3,16,30,55],ordereddict:[0,3,30,32,44],orderedmap:[0,32],orderedmapserializedkei:32,orderedset:0,org:38,organ:45,origin:[0,3,38,55],os:46,oss:[0,27],other:[2,3,6,8,9,15,18,26,27,30,32,38,44,45,46,53,54,55,56],other_error:26,otherstuff:56,otherwis:[2,3,6,9,27,32,54],ou:54,our:[38,44,48,54],out:[0,1,4,9,27,32,34,36,38,40,41,44,54],outcom:47,output:[0,41],output_password:54,outsid:[0,6,27,32],outv:[15,18],outvlabel:[15,18],over:[3,27,29,38,49,50,54,55],overcount:27,overflow:[0,41],overflowerror:[0,32],overhaul:55,overhead:[0,4,34],overload:[0,1,6,26,27],overrid:[0,3,9,15,18,42,44,55],overridden:[0,3,50],overriden:0,overs:3,overview:[40,41,45,48],overwrit:10,own:[3,9,37,54],owner:37,owner_id:[37,40],pack:[0,30],packag:[0,2,32,41,46,48,54,55],page:[0,1,3,45,51],pagedresult:[0,50,55],pagedresulthandl:50,pagin:[0,38,50],paging_st:[3,50],pair:[0,29],panda:29,parallel:0,param:[0,4,13],paramet:[0,3,4,6,7,8,9,10,12,14,15,18,27,29,30,31,32,37,40,47,52,54,56],parameter:56,parent:[0,20],pars:[0,15,18,29,32,43,44],parser:[0,29],part:[0,8,10,30,35,40,41,46],parti:[2,3,41,48],partial:[0,21,22,30],particular:[0,3,25,27,30,53],particularli:38,partit:[0,6,10,25,27,30,38],partition:0,partition_kei:[6,10,30,38],pass:[0,2,3,4,6,7,9,10,25,29,30,34,36,37,38,39,47,48,53,54,55,56],passin:54,password:[2,54],passwordauthent:[2,54],patch:[0,21,22,41,54],path:[0,15,18,29,46,54],path_to_bundle_yaml:52,pattern:[37,49],paxo:30,payload:[0,1,3,30,33],peer:[0,5,25],peers_v2:0,pem:54,pend:0,pending_us:30,pep:0,per:[0,3,4,6,9,10,25,27,35,37,43,44,50,53,55],percentil:26,perform:[0,1,3,9,10,27,30,33,37,38,45,46,51],perhap:46,period:39,permiss:54,permit:27,persist:[0,15,18,27,41],person:[9,37,38],person_id:37,perspect:[2,27],pertain:3,pertin:47,pet:[37,40],pet_id:[37,40],pet_typ:[37,40],phase:[2,3,30,46],photo_id:[10,37],phrase:13,pick:[36,44],pip:[0,55],pk:[38,44],pk__token:[0,38],pk__token__gt:[0,38],place:[0,40,44,55],placehold:[3,15,18,30,44,56],placement:[0,8],plai:0,plain:54,plaintextauthent:2,plaintextauthprovid:[0,2,3,54,55],plan:[0,8,27,45],platform:[0,42],pleas:[0,3,6,9,11,27,37,43,45,54],plu:[38,47],plug:39,pluggabl:0,pmfstat:26,point:[0,3,6,26,27,32,41,44,54,55],polic:27,polici:[0,3,33,42,43,44,52,53,55],poll:[3,30,43],polygon:32,polymorphic_kei:40,pool:[0,1,3,33,55],pool_wait_timeout:3,popul:[0,3,27,30,38],port:[0,3,5,25,44,53],portion:[30,32],posit:[3,10,30,34,38,44,47,55],possibl:[0,3,9,21,27,31,32,37,38,41,46,50,54,55],post:[0,49],postfork:[39,43],potenti:0,pr:0,practic:44,practiv:10,pre:[0,46],preced:[3,27,34,47],precis:[0,6,17,32,40,41,55],predic:[0,27,33],predict:38,preemptiv:44,preexist:7,prefer:[0,27,41,44,46,55],prefix:[9,11,13],prematur:0,prepar:[0,3,4,27,33,41,43,54,56],prepare_on_all_host:3,prepared_stat:30,preparedstat:[0,3,30,44],preparedstatementtest:0,preparemessag:0,prepend:[10,47,55],present:[0,7,10,30,41,42,43,46,47,55],preserv:[0,6,9,30,40],presist:37,pretti:49,preval:41,prevent:[0,10,40,44,46],previou:[0,3,54,55],previous:[0,40,42,55],previous_vers:1,price:[10,38],primari:[0,3,6,8,9,10,25,30,37,38,47,53,56],primary_host:27,primary_kei:[6,9,10,25,35,36,37,38,40,48],princip:[0,54],print:[3,9,10,12,30,32,35,37,41,42,43,44,46,48,52,53,56],prior:0,privat:[0,1,27],probabl:[27,38,54],problem:[0,3,26,43],process:[0,3,4,20,43,44,46,49,53,54,55],process_row:50,process_us:[3,4,44,50],produc:[2,4,15,18,38],product:[8,48,54,55],profil:[0,3,4,12,14,45,52],profile_long:44,program:52,programmat:3,project:[1,40,45,48,49],prompt:[46,54],proof:0,propag:[0,27,30],proper:[0,39,46],properli:[0,3,37,38,44],properti:[0,1,3,5,9,13,15,18,25,27,28,30,32,37],protect:0,protocol:[0,1,3,5,6,12,14,30,33,37,45,53],protocol_tl:[0,54],protocol_vers:[0,1,3,4,29,30,32,37,48,50,54,55,56],protocolerror:5,protocolhandl:[0,29],protocolvers:1,provid:[0,3,12,13,15,18,27,41,42,43,46,49,50,52,54,55],proxi:5,proxim:13,proxy_address:5,prudent:40,ps:50,ptyhon:0,publish:[0,46,54],pure:[0,2,27,29,46,54],purpos:[3,6],push:[0,46],py:[0,46],pyopenssl:[0,54],pypi:[0,46],python2:32,python3:0,python:[0,15,17,18,19,20,29,30,32,37,40,41,44,47,48,49,51,52,54,55,56],pyton:0,pytthon:0,pytz:41,q2:48,q:[35,38,48],qop:[2,54],quadrat:0,quantiz:6,queri:[0,1,3,4,6,9,12,15,16,18,25,27,29,32,33,35,37,40,41,42,45,46,48,49,56],query_cl:[3,30],query_from_travers:12,query_str:[15,18,30],queryexhaust:3,queryhandl:[3,29],queryoper:0,queryset:[0,9],querytrac:[0,30,43],question:[45,48],queu:34,quickli:[0,49],quorum:[1,10,27,30,44],quot:[0,17,41],race:0,rack:[0,28,52],radiu:32,rais:[0,1,2,3,4,5,6,9,10,15,18,27,30,32,34,37,38,40,44,50,55],raise_on_first_error:4,random:[0,27,32,38],randompartition:25,rang:[0,4,10,32,38,41,43],range_request_timeout_in_m:1,rare:0,rather:[0,32,46],raw:6,re:[0,27,30,37,38,39,44,46,54,56],reach:34,reachabl:27,reactor:[0,20,24,43],read:[0,1,6,15,18,26,27,30,32,34,36,43,54],read_inet:0,read_repair:0,read_repair_ch:0,read_request_timeout_in_m:1,read_timeout:26,readabl:25,reader:[12,15,18],readfailur:1,readm:0,readtimeout:[1,44],reason:[1,3,27,41,54],rebuild:[0,3],rebuilt:0,receiv:[0,1,3,27,44],received_respons:[1,27],recent:0,recogn:[15,18],recommend:[0,3,4,27,36,44,49,54,55,56],reconnect:[0,33],reconnection_polici:3,reconnectionpolici:[0,27],reconnector:0,record:[0,6,10,27,38],recreat:[0,25],recurs:0,redhat:46,reduc:[0,3,49,53],redund:40,reevalu:0,ref:0,refactor:[0,41],refer:[0,10,34,40,42,47,55],referenc:3,refresh:[0,3],refresh_:55,refresh_keyspace_metadata:3,refresh_nod:[0,3],refresh_schema:[0,55],refresh_schema_metadata:3,refresh_table_metadata:[3,53],refresh_user_aggregate_metadata:3,refresh_user_function_metadata:3,refresh_user_type_metadata:3,regard:[3,27,32],regardless:[26,27,46,47],regex:13,regist:[0,3,7,12,17,26,34,37,45,55],register_connect:[0,7,35],register_listen:[0,3],register_user_typ:[3,55,56],registr:35,registri:7,regress:0,regular:[13,30,36,38],reilli:44,reinstal:46,reject:47,rel:41,relat:[0,30,38,42],relax:7,releas:[0,9,27,40,42,54,55],release_vers:[43,44],reli:[27,38],reloc:40,remain:[3,20,27,40,42],rememb:44,remot:[0,3,27,53],remoteconnect:12,remov:[0,3,6,8,10,27,30,32,42,47],remove_request_init_listen:3,repair:27,repeat:[27,44],replac:[0,3,6,29,40,54,55],replai:[1,27],replic:[0,3,8,25,40,53],replica:[0,1,8,25,26,27,30,44],replication_factor:[8,25,53],replication_factor_info:25,replicationfactor:25,replicationstrategi:25,report:[0,27],reprepar:0,reprepare_on_up:3,repres:[1,3,5,6,9,15,18,25,26,28,30,31,32,37,38,40,41,55],represent:[0,25,30,32,55],reproduc:0,req:54,req_distinguished_nam:54,request:[0,1,3,4,26,27,38,39,42,44,45,47,49,54,55],request_id:0,request_tim:[0,26],request_timeout:[3,42,44],requestexecutionexcept:1,requestvalidationexcept:1,requir:[0,1,2,3,6,7,19,27,29,30,32,37,38,39,40,44,46,48,54,55],require_client_auth:54,required_replica:[1,27],required_respons:[1,27],reserv:0,reset:27,resolut:[0,32],resolv:[0,3,5,27,36,54],resort:27,resourc:[19,20,21,22,46,54],respect:[0,3,38],respond:[1,2,27,44],respons:[0,1,2,3,27,29,38,44],response_futur:3,responsefutur:[0,3,29,43,44,49,50,55],rest:[27,44],restart:[0,44],resulset:0,result:[0,3,4,9,10,12,15,18,25,26,27,29,30,32,37,38,41,43,44,45,53,56],result_cach:0,result_metadata:29,result_or_exc:4,result_set:3,results_gener:4,results_metadata:0,resultset:[0,3,50,55],resync:9,retain:[0,41],rethrow:27,rethrown:0,retri:[0,7,26,30,33,44],retriev:[1,3,10,30],retry_connect:7,retry_next_host:27,retry_num:27,retry_polici:[0,3,15,18,27,30,42,43,44],retrypolici:[0,3,26,27,30,43],retun:47,reus:[3,14,30],revers:[10,27],review:0,rework:55,rf:[0,1],rhel:46,rich:3,right:[27,30,44],ring:[0,3,27,32,33],risen:54,risk:27,rlac:0,robin:27,robust:[0,41],role:54,root:54,root_ca_base_nam:54,root_cert_pass:54,rootca:54,rotat:27,round:[0,27,32],roundrobinpolici:[27,53],roundtrip:30,rout:[0,3,9,27,43,46],routing_kei:[15,18,27,30,43],row:[0,3,4,5,10,12,29,33,34,37,38,41,42,43,44,47,48,50,55,56],row_factori:[0,3,7,29,30,42,44],row_id:10,row_list:55,rpc:[5,28],rpc_addr:0,rpc_address:[0,42],rsa:54,rule:30,run:[0,9,10,21,27,34,37,39,44,46,48],run_in_executor:0,runtim:[0,46,49],runtimeerror:0,s:[0,1,2,3,6,7,9,10,11,24,27,29,30,32,34,35,36,37,38,39,41,44,45,46,48,52,53,54,55,56],safe:[0,4],safeti:0,same:[0,3,4,6,7,12,15,18,25,27,30,32,34,35,36,37,38,42,43,44,46,54,55],sasi:38,sasl:[0,2,54],sasl_kwarg:[2,54],saslauthent:[0,2],saslauthprovid:[0,2,54],saslclient:0,satisfi:1,save:[0,9,10,34,35,37,38,41,44,50],scale:[0,26,41,46,49,55],scan:43,scenario:[0,36],schedul:[0,34],schema:[0,3,9,30,33,37,44,55],schema_event_refresh_window:3,schema_metadata_en:3,schema_trigg:0,schemapars:0,scope:[0,3,10],scratch:42,script:[0,40,46,49],scylla:[38,40,46,51,55],scylla_cloud:52,scylladb:[45,53],search:13,second:[0,3,10,26,27,30,31,32,38,41,44],secondari:[0,25,34,38],section:[0,38,40,45,47,49,54,55],secur:[0,45,55],see:[0,1,3,4,6,9,10,11,13,15,18,27,29,30,32,37,38,41,42,43,44,46,47,48,49,50,53,54,55],seen:[0,3,27],segment:40,select:[0,3,4,9,10,30,38,42,43,44,46,50,53,54,55,56],select_stat:4,self:[3,15,18,37,50,55,56],semant:[0,3],send:[0,1,2,3,5,27,44,45,55],sensibl:9,sensit:[0,9],sent:[0,1,2,3,29,44],sep:0,separ:[3,54],septemb:0,seq:43,sequenc:[0,3,4,14,17,27,30,32,44],sequenti:0,serd:0,serial:[0,1,3,12,15,18,30,41],serial_consistency_level:[3,15,18,30,42,44,47,55],serializ:3,serv:40,server:[0,1,2,3,9,15,18,25,29,30,33,38,44,47,48,55],server_authenticator_class:2,server_hostnam:54,server_nam:5,server_vers:43,servererror:27,serverless:45,servic:[2,54],service_timeout:21,session:[0,1,4,7,10,12,14,15,18,25,27,29,30,33,35,39,42,43,46,47,48,49,50,52,53,54,56],sesssion:0,set:[0,1,2,3,4,6,7,8,9,10,11,12,13,15,17,18,19,20,21,22,25,26,27,30,32,35,37,38,42,43,45,46,48,50,52,53,54,55],set_column:10,set_column__add:10,set_column__remov:10,set_core_connections_per_host:[3,4],set_default_connect:[7,35],set_keyspac:[0,3,27,44,56],set_max_connections_per_host:3,set_max_requests_per_connect:3,set_meta_refresh_en:3,set_min_requests_per_connect:3,set_sess:[0,7],set_source_analyt:[15,18],set_source_default:[15,18],set_source_graph:[15,18],set_stats_nam:26,set_verifi:54,setenv:46,setup:[0,7,10,35,37,38,39,40,44,46,48,54],setuptool:[0,46],sever:[0,38,40,44,46,49],shallow:[3,42],shard_aware_opt:53,shard_aware_stat:53,shards_count:53,share:[0,3,19,20,21,22,42,49],shed:[15,18],shell:46,shift:41,shortcut:[3,46],should:[0,2,3,4,6,7,8,9,10,15,18,19,20,21,22,25,27,30,31,37,40,42,44,46,49,53,54,55],should_log:3,shouldn:0,show:[0,8,32,36,38,40,42,47,54],shown:[3,35,37,56],shuffl:38,shuffle_replica:27,shutdown:[0,3,39,52],side:[0,1,2,3,15,18,27,40],sign:[6,54],signal:39,signatur:[1,3],significantli:[38,53],silent:27,similar:[27,29,34,52,54],simpl:[0,6,15,18,27,30,38,40,41,44,46,49],simpleconvictionpolici:[3,27],simplegraphstat:[15,18],simpler:55,simplest:[38,44],simplestat:[0,3,15,18,30,44,50],simplestrategi:[8,25,53],simpli:[0,9,17,27,34,37,40,44,46,56],simplifi:[15,18],simulacron:0,simultan:42,sinc:[0,9,29,31,32,36,38,41,43,55,56],singl:[0,3,4,6,8,9,10,14,25,27,28,30,32,37,38,40,42,44,46,47,55],single_object_row_factori:[15,18],site:[0,41],situat:[27,34,37],six:[0,46,55],size:[0,3,10,55],sizeti:0,sizetieredcompactionstrategi:9,skip:[0,9],slack:0,sleep:[27,37],slice:[0,3,38],slightli:0,slow:0,smaller:27,smallint:[0,6,15,18,44],smoke:0,snappi:46,snapshot:0,sni:5,sniendpoint:5,sniendpointfactori:5,so:[0,1,3,10,21,25,27,30,37,38,41,42,44,47,48,49,50,54,55],socket:[0,5,54],socket_famili:5,sockopt:3,soft:0,softwar:45,some:[0,1,9,15,18,27,34,37,38,41,44,45,46,47,48,50,54,55,56],some_id2:34,some_id:34,someth:[2,27,37,38,46,54],sometim:[0,10,15,18,27,46,50],somewher:[34,50],sort:[0,4,6,32,38],sortedset:[0,32,55],sourc:[0,3,15,18,45,46],source_elaps:[0,43],span:46,spark:[0,3],spcifi:1,spec:41,special:[0,6,29,37,38,40,43],specif:[0,2,5,13,15,17,18,25,27,40,45,46,55,56],specifi:[0,1,3,6,8,9,10,11,12,27,29,30,32,35,37,38,40,41,42,44,54,55],specul:[0,27],speculative_execution_polici:[3,44],speculativeexecutionpolici:[27,44],speed:3,speedup:38,spell:41,spin:0,split:2,squar:47,ss:32,ssl:[0,5,44],ssl_context:[0,3,44,54],ssl_error_want_read:0,ssl_error_want_writ:0,ssl_opt:54,ssl_option:[0,3,5,54],ssl_version:54,sslcontext:[0,54],sstabl:43,sstable_size_in_mb:9,st:[3,37,56],stabil:0,stabl:0,stale:27,stall:0,standard1:53,standard:[0,19,20,26,38,39,41,44,46,52,54,55],start:[0,3,34,38,41,45,50,55],start_fetching_next_pag:[3,50],start_tim:3,startup:0,stat:[0,26,53],state:[0,3,10,20,27,34,45,47],stateless:50,statement:[0,3,25,27,33,34,36,41,42,43,47,50,56],statements_and_param:4,statements_and_paramet:4,stats_nam:26,statu:[47,53],status_event_refresh_window:3,stddev:26,stdlib:0,step:[37,45],steroid:38,steve:10,still:[0,15,18,30,34,37,40,42,44,55,56],stmt:0,stop:[4,34],store:[0,1,6,9,30,37,41,52],str:[7,8,10,17,32,44],straightforward:[37,40,41,55],strategi:[0,40,55],stream:[0,29],stream_id:29,street:[3,11,37,55,56],stress:0,strict:[6,49],strictli:0,string:[0,1,2,3,6,12,13,15,17,18,25,26,27,29,30,32,41,44,54],string_typ:32,strip:0,strong:0,structur:[15,18,25,37],studio:46,stuff:[3,56],style:3,sub:[37,40],subclass:[0,1,2,3,27,30,37,54],submit:[0,43],submit_schema_refresh:55,submodul:[40,55],suboptim:27,subsequ:40,subset:38,substanc:39,substanti:[4,55],succe:[3,27],succeed:0,success:[0,1,2,3,4,10,27,30,44,46],successfulli:[0,53],sudo:46,suffici:27,suggest:[44,46],suit:[0,54],suitabl:[2,17,25,36],superset:25,suppli:[0,3,30,44,54,55],support:[0,1,2,3,8,9,10,12,27,32,34,36,38,41,44,45,50,53,54,55,56],supported_vers:1,suppos:[0,37,54],sure:[0,3,27,37,43,44,46,49,51,54],surfac:0,surround:0,swap:55,sy:0,sync:[9,35,37],sync_schema:0,sync_tabl:[0,8,10,35,37,48],sync_typ:[8,11,37],synch:8,synchron:[0,3,4,8,37,49,50],syntax:[0,10,34,38],syntaxexcept:0,system:[0,5,25,38,42,43,44,46,55],t:[0,9,10,15,31,37,38,43,44,47,49,54,55,56],tab:52,tabl:[0,1,3,6,8,25,30,32,33,37,44,47,48,55,56],tablemetadata:[0,25,53,55],tablemetadatadse68:25,tablemetadatav3:25,tag:[0,15,18],take:[0,3,4,8,9,15,18,25,27,35,44,46,54],taken:[15,18,40],tarbal:46,target:[0,3,13,15,18,27,46],task:[0,3,34,39],tcp:0,tear_up_couch:37,technic:40,techniqu:44,tell:56,tenant:41,term:27,tesla2012:38,tesla:[35,38],test2:10,test4:10,test:[0,10,21,22,27,31,35,46,47],test_clone_shared_lbp:0,test_clust:0,test_connect:0,test_fail_if_different_query_id_on_reprepar:0,test_set_keyspace_twic:0,test_single_interfac:0,testifexistsmodel:9,testifnotexistsmodel:9,testmodel:38,testtransactionmodel:9,text:[0,3,6,9,10,11,13,35,36,37,38,40,44,48,55,56],than:[0,1,3,6,10,27,30,31,32,38,42,44,46,49,50,54],thei:[0,1,3,4,6,8,9,10,15,18,27,29,32,34,36,37,38,40,41,55,56],them:[0,3,27,38,40,41,44,46,47,48,55],themselv:[15,18],therefor:[36,38,46],thi:[0,1,2,3,4,5,6,7,8,9,10,11,12,13,15,17,18,19,20,21,22,25,26,27,28,29,30,31,32,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,53,54,55,56],thing:[3,27,38,40,44],third:[2,41,48],thorough:[46,54],those:[0,3,26,27,30,42,46],though:55,thread:[0,3,4,44,46,49],threadpoolexecutor:0,three:[1,27,30,32,44,47],threshold:[0,3],thrift:0,throttl:0,through:[0,2,3,5,7,9,10,15,18,26,27,30,38,44,45,47,49,55,56],throughput:[0,4,49],thrown:34,thu:[10,27,30,47],ticket:54,time:[0,1,2,3,4,6,10,26,27,31,32,37,38,40,44,45,46,55],time__gt:38,time__lt:38,time_arg:32,timedata:9,timedelta:10,timedelta_or_datetim:9,timeout:[0,1,3,9,10,21,26,27,55],timer:[0,21,26],timestamp:[0,1,6,9,10,17,32,33,36,40,44,45],timestamp_gener:3,timestamp_na:41,timestamp_pres:41,timestamp_utc:41,timestamptyp:0,timeuuid:[0,6,10,32,37,44,55],timezon:[0,6,32,41],tinkerpop:[12,46],tinyint:[0,6,44],tip:45,tlsv1_2_method:54,tmp:42,to_bigint:[15,18],to_doubl:[15,18],to_float:[15,18],to_int:[15,18],to_python:0,to_smallint:[15,18],todo:32,token:[0,2,3,13,15,27,33,43,46,53],token_fuzzi:13,token_map:0,token_metadata_en:3,token_prefix:13,token_regex:13,token_str:25,tokenawar:0,tokenawarepolici:[0,3,27,42,52,53],tokenawarerout:9,tokenfun:38,tokenmap:[0,25],toler:0,tolist:12,tombston:[3,36,43],tombstone_compaction_interv:9,tombstone_threshold:9,too:[0,3,27,41],took:1,tool:46,toolkit:29,top:[15,18,27],topo:0,topolog:[0,3,27,33],topology_event_refresh_window:3,total:[3,27],trace:[0,3,33],traceev:30,traceunavail:[3,30],tracing_en:0,track:0,trade:4,trademark:45,traffic:[0,44],trail:0,transact:[0,1,3,12,14,27,30,45],transform:37,transient_replica:25,transit:0,translat:[33,40,44],transpar:[3,44,50],trap:34,trash:0,travers:[0,12,14,15,18,46],traversal_batch:14,traversal_class:12,traversal_sourc:12,traversalbatch:[12,14],traversalmetr:0,travisci:0,treat:[3,27,30,44,50],tree:3,tri:0,trigger:[0,3,27],truncat:[6,30,32,40],truncate_microsecond:6,truststor:54,truststore_password:54,truthi:27,ts:41,ttl:[0,9,10],ttl_in_sec:9,tunabl:49,tune:0,tupl:[0,1,3,4,9,12,17,25,27,30,38,44,55,56],tuple_factori:[0,3,16,29,30,42,44,55],turn:[3,43],twice:0,twist:[0,33,44],twistedconnect:[24,54],twistedreactor:[33,54],two:[0,1,3,13,27,29,32,38,44,46,54],txt:[0,46],type0:1,type1:1,type:[0,1,3,8,10,15,17,18,25,27,29,30,32,33,34,38,41,45,47],type_model:8,typeerror:[0,15,18],typestr:0,typic:[3,10,27,29,30,31,34,38,42,44],typo:0,tzinfo:41,u:[10,30,37,38,47],ubuntu:[0,46],uda:0,udf:0,udt:[0,3,12,18,37,45],un:[0,30],unabl:[0,27,46],unauthor:[0,1],unavail:[0,1,26,27],uncal:0,unchang:40,unclean:55,uncompar:0,uncomplet:30,uncondit:0,undefinedkeyspaceexcept:40,under:[0,25,27,37,45],underscor:0,understand:54,understood:[3,27],underutil:0,unexpect:27,unexpectedli:0,unfamiliar:38,unhexlifi:0,unicod:[0,17,44],unicodedecodeerror:0,unif:0,unifi:[0,55],unintend:0,union:3,uniqu:[1,6,25,37,42],unit:[0,13,27,45],unittest2:0,unittest:0,unix:[0,5,31,32,41],unix_socket_path:5,unix_time_from_uuid1:32,unixsocketendpoint:5,unknown:[0,15,18,46,55],unless:[3,6,27,35,55],unlik:41,unlog:30,unlogged_batch:27,unord:[6,25],unorder:0,unpack:[0,15,18,44],unprepar:56,unrecogn:0,unrecover:5,unreferenc:0,unregist:[0,56],unregister_connect:[7,35],unregister_listen:3,unset:0,unset_valu:30,unspecifi:[0,9],unsupport:0,unsupportedoper:3,until:[0,2,3,4,7,37,43,44],untrust:3,unus:[0,46],unwis:10,up:[0,3,8,13,19,20,21,22,32,33,34,37,38,52,54,55],updat:[0,1,3,8,9,10,30,32,34,38,40,42,44,45,47],update_view_metadata:0,updatestat:0,upfront:29,upgrad:[45,48,54],upon:[3,37],upper:32,upper_bound:32,uppercas:0,us:[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,35,36,37,38,40,41,43,44,45,46,47,49,50,51,52,53,54],usag:[0,2,3,4,9,25,27,30,55],use_certificate_fil:54,use_client_timestamp:[0,1,3,55],use_default_tempdir:0,use_list_t:6,use_privatekey_fil:54,use_set_t:6,used_hosts_per_remote_dc:27,usemap:6,user1:[44,54],user2:44,user3:44,user3_lookup:44,user:[0,1,3,4,6,8,9,10,17,18,25,30,33,38,40,44,45,46,50,54],user_act:3,user_id1:44,user_id2:44,user_id3:44,user_id:[4,9,30,38,44],user_ids_to_queri:44,user_lookup_stmt:44,user_row:[3,44,50],user_typ:[3,6],user_type_map:29,user_tz:41,useraggregatedescriptor:[1,3],userdefinedtyp:[0,6,37],userfunctiondescriptor:[1,3],usernam:[2,44,54],users_to_insert:30,usertyp:[0,6,25,33,37],usertypedoesnotexist:3,usual:[10,21,41,54],utc:[32,41],utc_datetime_from_ms_timestamp:32,utcfromtim:0,utcnow:[6,41],utctimetupl:41,utf8:0,utf8typ:0,utf:[0,6,17],util:[0,1,12,21,22,33,40,41,44,52,54,55],uuid1:[10,44],uuid4:[10,48],uuid:[0,6,9,10,32,37,38,40,44,48],uuid_arg:32,uuid_from_tim:[32,40],uwsgi:[43,48],uwsgidecor:[39,43],v1:[0,1,32],v2:[0,1,45],v3:[0,1,37,45],v4:[0,1,6,30],v5:[0,1],v6:1,v:[10,12,34,47,53],val1:17,val2:17,val:15,valid:[0,1,3,6,9,10,15,18,25,27,32,47,54],validationerror:[10,37,40],valu:[0,2,3,4,6,9,10,11,13,15,17,18,25,27,29,30,31,32,34,37,40,41,44,47,53,54,55,56],value2:32,value_typ:6,valueerror:[0,32],valuemap:12,values_list:[0,38],valuesequ:30,varchar:44,variabl:[0,6,9,44,46,54],variant:55,varint:[0,6,44],variou:[26,54],various:40,ve:[9,35,37,38],verb:40,verbatim:[15,18],veri:[52,54],verif:0,verifi:0,verify_mod:54,verify_p:54,version:[0,1,2,3,6,25,29,30,31,32,37,40,44,45,46,50,55,56],vertex:[15,18,25],vertexmetadata:25,vertexproperti:[15,18],via:[0,3,37,46,50,52,54],view:[0,25,27,43],violat:10,virtual:[0,38],visit:45,visual:46,vnode:3,vs:[0,27],wa:[0,1,2,3,4,5,7,25,26,27,30,36,40,46,47,55],wai:[0,3,6,15,18,27,30,36,38,41,42,44,45,46,54,55],wait:[0,1,3,21,27,30,43,44,50],wait_for_all_pool:3,wait_for_complet:30,wake:21,want:[0,3,6,9,27,34,35,37,38,44,50,54,56],warn:[0,1,3,31,40,55],warn_on_drift:31,warning_interv:31,warning_threshold:31,was_appli:[0,3],watcher:21,we:[0,7,27,36,38,39,41,42,44,48,54,56],weakref:0,web_sess:50,well:[0,27,35,44,54],were:[0,1,3,4,19,25,27,30,36,37,40],what:[27,30,37,41,54,55,56],wheel:[0,46],when:[0,1,2,3,4,5,7,9,10,17,21,27,28,29,30,31,32,35,36,37,38,40,41,42,44,46,47,50,54,55,56],whenev:[3,50],where:[0,3,4,10,25,27,30,32,37,43,44,46,47,55],whether:[1,3,6,25,26,27,47,53],which:[0,1,3,9,10,25,27,29,30,34,35,36,38,40,44,46,49,54,55,56],whilst:0,whitelist:27,whitelistroundrobinpolici:[0,27,42,44,55],whitespac:25,who:27,whose:3,wider:[32,41],window:[0,32],wish:3,within:[0,1,3,10,13,27,30,34,41,42,44,55],withing:13,without:[0,1,3,9,10,38,41,44],wkt:[0,32],wno:46,won:37,word:[27,38],work:[0,2,7,17,27,30,32,37,38,44,45,47,48,53,54,56],workaround:[0,36,40],worker:[0,39],worker_process_init:39,working_keyspac:27,workload:[0,42,49],worth:46,would:[0,9,27,36,37,38,42,44,53,54,55],wrap:[12,15,18,27,44],wrap_socket:54,wrapper:[0,27,30],write:[0,1,8,10,15,18,26,27,30],write_request_timeout_in_m:1,write_timeout:26,write_typ:[1,27],writefailur:1,writetimeout:[0,1],writetyp:[0,1,27],written:0,wrong:[0,44],wunus:46,www:6,x509:54,x:[1,4,10,27,32,46,47],xcode:46,xrang:0,y:[0,10,27,32],yaml:[1,27,52,53],year:[10,32,35,38],year__gt:38,year__in:38,year__lt:38,yet:[3,38,44,55],yield:[4,27],you:[0,3,4,6,9,12,27,30,34,35,37,38,43,44,46,49,50,52,53,54,55,56],your:[0,3,6,9,35,37,38,40,43,44,47,48,49,50,52,54,55,56],yourself:49,yum:46,yyyi:[17,32],z:10,zero:0,zip:[55,56],zipcod:[3,11,37,55,56]},titles:["CHANGELOG","cassandra - Exceptions and Enums","cassandra.auth - Authentication","cassandra.cluster - Clusters and Sessions","cassandra.concurrent - Utilities for Concurrent Statement Execution","cassandra.connection - Low Level Connection Info","cassandra.cqlengine.columns - Column types for object mapping models","cassandra.cqlengine.connection - Connection management for cqlengine","cassandra.cqlengine.management - Schema management for cqlengine","cassandra.cqlengine.models - Table models for object mapping","cassandra.cqlengine.query - Query and filter model objects","cassandra.cqlengine.usertype - Model classes for User Defined Types","cassandra.datastax.graph.fluent","cassandra.datastax.graph.fluent.predicates","cassandra.datastax.graph.fluent.query","cassandra.datastax.graph - Graph Statements, Options, and Row Factories","cassandra.decoder - Data Return Formats","cassandra.encoder - Encoders for non-prepared Statements","cassandra.graph - Graph Statements, Options, and Row Factories","cassandra.io.asyncioreactor - asyncio Event Loop","cassandra.io.asyncorereactor - asyncore Event Loop","cassandra.io.eventletreactor - eventlet-compatible Connection","cassandra.io.geventreactor - gevent-compatible Event Loop","cassandra.io.libevreactor - libev Event Loop","cassandra.io.twistedreactor - Twisted Event Loop","cassandra.metadata - Schema and Ring Topology","cassandra.metrics - Performance Metrics","cassandra.policies - Load balancing and Failure Handling Policies","cassandra.pool - Hosts and Connection Pools","cassandra.protocol - Protocol Features","cassandra.query - Prepared Statements, Batch Statements, Tracing, and Row Factories","cassandra.timestamps - Timestamp Generation","cassandra.util - Utilities","API Documentation","Batch Queries","Connections","Frequently Asked Questions","Models","Making Queries","Third party integrations","Upgrade Guide","Working with Dates and Times","Execution Profiles","Frequently Asked Questions","Getting Started","Python Driver for Scylla and Apache Cassandra\u00ae","Installation","Lightweight Transactions (Compare-and-set)","Object Mapper","Performance Notes","Paging Large Queries","ScyllaDB Cloud","ScyllaDB Cloud Serverless","Scylla Specific Features","Security","Upgrading","User Defined Types"],titleterms:{"0":[0,54,55],"0b1":0,"0b5":0,"0b6":0,"0b7":0,"0c1":0,"0c2":0,"0rc1":0,"1":[0,55],"10":0,"11":0,"12":0,"13":0,"14":0,"15":0,"16":[0,54],"17":0,"18":0,"19":0,"2":[0,55],"20":0,"21":0,"22":0,"23":0,"24":0,"25":0,"26":0,"3":[0,54,55],"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"class":[11,56],"default":[35,38,42,47,55],"do":43,"enum":1,"final":0,"float":40,"function":[38,40],"import":[40,55],"new":[35,53],"return":[16,55],No:54,access:38,ad:42,address:27,alias:40,all:38,apach:45,api:[33,40,55],applic:43,ar:[38,55],ask:[36,43],asynchron:44,asyncio:19,asyncioreactor:19,asyncor:20,asyncorereactor:20,attach:55,attribut:53,auth:2,authent:[2,54,55],automat:55,awar:53,balanc:27,base:[46,55],batch:[30,34,36,55],batchqueri:35,beta2:0,beta3:0,beta4:0,beta:0,bind:55,blist:55,bug:0,c:46,call:55,callback:[34,50],can:36,cassandra:[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,41,44,45,55],celeri:39,chang:[35,40,55],changelog:0,client:[54,55],cloud:[51,52],cluster:[3,42,44,53,55],column:[6,40],compar:47,compat:[21,22],compress:46,concurr:4,configur:[46,54],connect:[5,7,21,28,35,43,44],consist:[44,55],consolid:40,content:[45,48],context:35,control:50,convers:44,copyright:45,core:33,correctli:36,cql:44,cqlengin:[6,7,8,9,10,11,40],custom:[29,54,55],cython:[46,49],data:16,datastax:[12,13,14,15,33],date:[40,41],datetyp:41,dead:27,decod:16,defin:[11,37,55,56],definit:37,delet:36,depend:[46,55],deprec:[0,40,55],deseri:29,determin:43,dict:56,dict_factori:47,dictionari:37,document:33,doe:43,don:36,doubl:40,down:27,driver:[33,43,45,55],dse:[54,55],encod:[17,55],error:46,event:[19,20,22,23,24],eventlet:[21,54],eventletreactor:21,exampl:[37,54],except:[1,40],execut:[4,34,42,44,54,55],execute_async:55,extend:37,extens:[46,49],extra:55,factori:[15,18,30],fail:27,failur:27,faster:29,featur:[0,29,53,55],field2:36,field:36,filter:[10,38],fix:0,fluent:[12,13,14],format:16,frequent:[36,43],from:[0,36,55],from_datetim:40,gener:[31,34],get:[44,45,48],gevent:22,geventreactor:22,graph:[12,13,14,15,18,33,46,55],guid:40,handl:[27,50],help:45,helper:53,host:[27,28],how:[36,43],i:[36,43],idempot:27,ident:54,ignor:55,immut:38,individu:36,info:5,inform:55,inherit:[37,40],initi:42,instal:[46,55],instanc:[35,37,42],instanti:36,integr:39,io:[19,20,21,22,23,24,43],issu:45,keyspac:44,larg:50,legaci:42,level:[5,40,44,55],libev:[23,46],libevreactor:23,lightweight:[47,55],list:[38,40],load:27,local_on:55,log:34,login:54,loop:[19,20,22,23,24],low:5,lower:54,make:38,manag:[7,8,35,40,43],manipul:37,manual:46,map:[6,9,42,56],mapper:[33,48],mark:27,merg:0,metadata:[25,55],metric:[26,46],model:[6,9,10,11,35,36,37,40],modul:55,multiprocess:49,my:43,name:[38,42,55],named_tuple_factori:47,nativ:55,node:27,non:[17,46,55],normal:55,note:[46,49],now:55,object:[6,9,10,33,38,48],oper:[27,38,43],option:[15,18,46],order:[36,38],organ:40,osx:46,other:0,overload:40,packag:40,page:[50,55],paramet:[42,44,55],parti:39,pass:[42,44],path:41,pattern:34,payload:29,per:38,perform:[26,49],pip:46,platform:46,polici:27,pool:28,predic:13,prepar:[17,30,44,55],prepend:40,preserv:36,profil:[42,44],protocol:[29,54,55],proxi:54,pypi:49,python:[45,46],queri:[10,14,30,34,36,38,43,44,50,55],queryset:[10,35,38],question:[36,43],read:41,reconnect:27,regist:[35,56],remov:[40,55],replica:43,report:45,request:43,result:[47,50,55],resum:50,retri:[27,43],retriev:38,revers:40,ring:25,row:[15,18,30,36],sasl:55,schema:[8,25,40],scylla:[45,53],scylladb:[51,52],secur:54,select:35,server:[27,54],serverless:52,session:[3,44,55],set:[44,47],sever:55,shard:53,shutdown:55,side:55,size:50,soft:55,special:47,specif:53,specul:44,speed:46,ssl:[46,54],start:[44,48],statement:[4,15,17,18,30,44,55],support:46,t:36,tabl:[9,38,53],them:56,third:39,through:46,time:41,timeout:[38,43],timestamp:[31,41,55],timeuuid:[38,40],token:[25,38],topolog:25,trace:[30,43,55],transact:[47,55],translat:27,ttl:38,tuple_factori:47,twist:[24,54],twistedreactor:24,type:[6,11,37,40,44,55,56],udt:56,unicodemixin:40,unifi:54,unlog:34,unregist:35,up:[27,46],updat:[36,55],upgrad:[0,40,55],us:[34,42,55,56],user:[11,37,55,56],usertyp:11,util:[4,32],uwsgi:39,v1:54,v2:55,v3:55,valid:37,valu:[36,38],value2:36,verif:54,verifi:[46,54],version:54,vs:34,why:[36,43],window:46,without:[42,56],work:[36,41,55],write:41,wsgi:43,x:[0,55],your:46}}) \ No newline at end of file diff --git a/3.26.2-scylla/security.html b/3.26.2-scylla/security.html new file mode 100644 index 0000000000..c830d70a47 --- /dev/null +++ b/3.26.2-scylla/security.html @@ -0,0 +1,1020 @@ + + + + + + + + + + + + + Security | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + + + +
+ +
+ +
+

Security

+

The two main security components you will use with the +Python driver are Authentication and SSL.

+
+

Authentication

+

Versions 2.0 and higher of the driver support a SASL-based +authentication mechanism when protocol_version +is set to 2 or higher. To use this authentication, set +auth_provider to an instance of a subclass +of AuthProvider. When working +with Cassandra’s PasswordAuthenticator, you can use +the PlainTextAuthProvider class.

+

For example, suppose Cassandra is setup with its default +‘cassandra’ user with a password of ‘cassandra’:

+
from cassandra.cluster import Cluster
+from cassandra.auth import PlainTextAuthProvider
+
+auth_provider = PlainTextAuthProvider(username='cassandra', password='cassandra')
+cluster = Cluster(auth_provider=auth_provider, protocol_version=2)
+
+
+
+

Custom Authenticators

+

If you’re using something other than Cassandra’s PasswordAuthenticator, +SaslAuthProvider is provided for generic SASL authentication mechanisms, +utilizing the pure-sasl package. +If these do not suit your needs, you may need to create your own subclasses of +AuthProvider and Authenticator. You can use the Sasl classes +as example implementations.

+
+
+

Protocol v1 Authentication

+

When working with Cassandra 1.2 (or a higher version with +protocol_version set to 1), you will not pass in +an AuthProvider instance. Instead, you should pass in a +function that takes one argument, the IP address of a host, and returns +a dict of credentials with a username and password key:

+
from cassandra.cluster import Cluster
+
+def get_credentials(host_address):
+    return {'username': 'joe', 'password': '1234'}
+
+cluster = Cluster(auth_provider=get_credentials, protocol_version=1)
+
+
+
+
+
+

SSL

+

SSL should be used when client encryption is enabled in Cassandra.

+

To give you as much control as possible over your SSL configuration, our SSL +API takes a user-created SSLContext instance from the Python standard library. +These docs will include some examples for how to achieve common configurations, +but the ssl.SSLContext documentation +gives a more complete description of what is possible.

+

To enable SSL with version 3.17.0 and higher, you will need to set Cluster.ssl_context to a +ssl.SSLContext instance to enable SSL. Optionally, you can also set Cluster.ssl_options +to a dict of options. These will be passed as kwargs to ssl.SSLContext.wrap_socket() +when new sockets are created.

+

If you create your SSLContext using ssl.create_default_context, +be aware that SSLContext.check_hostname is set to True by default, so the hostname validation will be done +by Python and not the driver. For this reason, we need to set the server_hostname at best effort, which is the +resolved ip address. If this validation needs to be done against the FQDN, consider enabling it using the ssl_options +as described in the following examples or implement your own EndPoint and +EndPointFactory.

+

The following examples assume you have generated your Cassandra certificate and +keystore files with these intructions:

+ +

It might be also useful to learn about the different levels of identity verification to understand the examples:

+ +
+

SSL with Twisted or Eventlet

+

Twisted and Eventlet both use an alternative SSL implementation called pyOpenSSL, so if your Cluster’s connection class is +TwistedConnection or EventletConnection, you must pass a +pyOpenSSL context instead. +An example is provided in these docs, and more details can be found in the +documentation. +pyOpenSSL is not installed by the driver and must be installed separately.

+
+
+

SSL Configuration Examples

+

Here, we’ll describe the server and driver configuration necessary to set up SSL to meet various goals, such as the client verifying the server and the server verifying the client. We’ll also include Python code demonstrating how to use servers and drivers configured in these ways.

+
+

No identity verification

+

No identity verification at all. Note that this is not recommended for for production deployments.

+

The Cassandra configuration:

+
client_encryption_options:
+  enabled: true
+  keystore: /path/to/127.0.0.1.keystore
+  keystore_password: myStorePass
+  require_client_auth: false
+
+
+

The driver configuration:

+
from cassandra.cluster import Cluster, Session
+from ssl import SSLContext, PROTOCOL_TLS
+
+ssl_context = SSLContext(PROTOCOL_TLS)
+
+cluster = Cluster(['127.0.0.1'], ssl_context=ssl_context)
+session = cluster.connect()
+
+
+
+
+

Client verifies server

+

Ensure the python driver verifies the identity of the server.

+

The Cassandra configuration:

+
client_encryption_options:
+  enabled: true
+  keystore: /path/to/127.0.0.1.keystore
+  keystore_password: myStorePass
+  require_client_auth: false
+
+
+

For the driver configuration, it’s very important to set ssl_context.verify_mode +to CERT_REQUIRED. Otherwise, the loaded verify certificate will have no effect:

+
from cassandra.cluster import Cluster, Session
+from ssl import SSLContext, PROTOCOL_TLS, CERT_REQUIRED
+
+ssl_context = SSLContext(PROTOCOL_TLS)
+ssl_context.load_verify_locations('/path/to/rootca.crt')
+ssl_context.verify_mode = CERT_REQUIRED
+
+cluster = Cluster(['127.0.0.1'], ssl_context=ssl_context)
+session = cluster.connect()
+
+
+

Additionally, you can also force the driver to verify the hostname of the server by passing additional options to ssl_context.wrap_socket via the ssl_options kwarg:

+
from cassandra.cluster import Cluster, Session
+from ssl import SSLContext, PROTOCOL_TLS, CERT_REQUIRED
+
+ssl_context = SSLContext(PROTOCOL_TLS)
+ssl_context.load_verify_locations('/path/to/rootca.crt')
+ssl_context.verify_mode = CERT_REQUIRED
+ssl_context.check_hostname = True
+ssl_options = {'server_hostname': '127.0.0.1'}
+
+cluster = Cluster(['127.0.0.1'], ssl_context=ssl_context, ssl_options=ssl_options)
+session = cluster.connect()
+
+
+
+
+

Server verifies client

+

If Cassandra is configured to verify clients (require_client_auth), you need to generate +SSL key and certificate files.

+

The cassandra configuration:

+
client_encryption_options:
+  enabled: true
+  keystore: /path/to/127.0.0.1.keystore
+  keystore_password: myStorePass
+  require_client_auth: true
+  truststore: /path/to/dse-truststore.jks
+  truststore_password: myStorePass
+
+
+

The Python ssl APIs require the certificate in PEM format. First, create a certificate +conf file:

+
cat > gen_client_cert.conf <<EOF
+[ req ]
+distinguished_name = req_distinguished_name
+prompt = no
+output_password = ${ROOT_CERT_PASS}
+default_bits = 2048
+
+[ req_distinguished_name ]
+C = ${CERT_COUNTRY}
+O = ${CERT_ORG_NAME}
+OU = ${CERT_OU}
+CN = client
+EOF
+
+
+

Make sure you replaced the variables with the same values you used for the initial +root CA certificate. Then, generate the key:

+
openssl req -newkey rsa:2048 -nodes -keyout client.key -out client.csr -config gen_client_cert.conf
+
+
+

And generate the client signed certificate:

+
openssl x509 -req -CA ${ROOT_CA_BASE_NAME}.crt -CAkey ${ROOT_CA_BASE_NAME}.key -passin pass:${ROOT_CERT_PASS} \
+    -in client.csr -out client.crt_signed -days ${CERT_VALIDITY} -CAcreateserial
+
+
+

Finally, you can use that configuration with the following driver code:

+
from cassandra.cluster import Cluster, Session
+from ssl import SSLContext, PROTOCOL_TLS
+
+ssl_context = SSLContext(PROTOCOL_TLS)
+ssl_context.load_cert_chain(
+    certfile='/path/to/client.crt_signed',
+    keyfile='/path/to/client.key')
+
+cluster = Cluster(['127.0.0.1'], ssl_context=ssl_context)
+session = cluster.connect()
+
+
+
+
+

Server verifies client and client verifies server

+

See the previous section for examples of Cassandra configuration and preparing +the client certificates.

+

The following driver code specifies that the connection should use two-way verification:

+
from cassandra.cluster import Cluster, Session
+from ssl import SSLContext, PROTOCOL_TLS, CERT_REQUIRED
+
+ssl_context = SSLContext(PROTOCOL_TLS)
+ssl_context.load_verify_locations('/path/to/rootca.crt')
+ssl_context.verify_mode = CERT_REQUIRED
+ssl_context.load_cert_chain(
+    certfile='/path/to/client.crt_signed',
+    keyfile='/path/to/client.key')
+
+cluster = Cluster(['127.0.0.1'], ssl_context=ssl_context)
+session = cluster.connect()
+
+
+

The driver uses SSLContext directly to give you many other options in configuring SSL. Consider reading the Python SSL documentation +for more details about SSLContext configuration.

+

Server verifies client and client verifies server using Twisted and pyOpenSSL

+
from OpenSSL import SSL, crypto
+from cassandra.cluster import Cluster
+from cassandra.io.twistedreactor import TwistedConnection
+
+ssl_context = SSL.Context(SSL.TLSv1_2_METHOD)
+ssl_context.set_verify(SSL.VERIFY_PEER, callback=lambda _1, _2, _3, _4, ok: ok)
+ssl_context.use_certificate_file('/path/to/client.crt_signed')
+ssl_context.use_privatekey_file('/path/to/client.key')
+ssl_context.load_verify_locations('/path/to/rootca.crt')
+
+cluster = Cluster(
+    contact_points=['127.0.0.1'],
+    connection_class=TwistedConnection,
+    ssl_context=ssl_context,
+    ssl_options={'check_hostname': True}
+)
+session = cluster.connect()
+
+
+

Connecting using Eventlet would look similar except instead of importing and using TwistedConnection, you would +import and use EventletConnection, including the appropriate monkey-patching.

+
+
+
+

Versions 3.16.0 and lower

+

To enable SSL you will need to set Cluster.ssl_options to a +dict of options. These will be passed as kwargs to ssl.wrap_socket() +when new sockets are created. Note that this use of ssl_options will be +deprecated in the next major release.

+

By default, a ca_certs value should be supplied (the value should be +a string pointing to the location of the CA certs file), and you probably +want to specify ssl_version as ssl.PROTOCOL_TLS to match +Cassandra’s default protocol.

+

For example:

+
from cassandra.cluster import Cluster
+from ssl import PROTOCOL_TLS, CERT_REQUIRED
+
+ssl_opts = {
+    'ca_certs': '/path/to/my/ca.certs',
+    'ssl_version': PROTOCOL_TLS,
+    'cert_reqs': CERT_REQUIRED  # Certificates are required and validated
+}
+cluster = Cluster(ssl_options=ssl_opts)
+
+
+

This is only an example to show how to pass the ssl parameters. Consider reading +the python ssl documentation for +your configuration. For further reading, Andrew Mussey has published a thorough guide on +Using SSL with the DataStax Python driver.

+
+

SSL with Twisted

+

In case the twisted event loop is used pyOpenSSL must be installed or an exception will be risen. Also +to set the ssl_version and cert_reqs in ssl_opts the appropriate constants from pyOpenSSL are expected.

+
+
+
+
+

DSE Authentication

+

When authenticating against DSE, the Cassandra driver provides two auth providers that work both with legacy kerberos and Cassandra authenticators, +as well as the new DSE Unified Authentication. This allows client to configure this auth provider independently, +and in advance of any server upgrade. These auth providers are configured in the same way as any previous implementation:

+
from cassandra.auth import DSEGSSAPIAuthProvider
+auth_provider = DSEGSSAPIAuthProvider(service='dse', qops=["auth"])
+cluster = Cluster(auth_provider=auth_provider)
+session = cluster.connect()
+
+
+

Implementations are DSEPlainTextAuthProvider, DSEGSSAPIAuthProvider and SaslAuthProvider.

+
+

DSE Unified Authentication

+

With DSE (>=5.1), unified Authentication allows you to:

+
    +
  • Proxy Login: Authenticate using a fixed set of authentication credentials but allow authorization of resources based another user id.

  • +
  • Proxy Execute: Authenticate using a fixed set of authentication credentials but execute requests based on another user id.

  • +
+
+

Proxy Login

+

Proxy login allows you to authenticate with a user but act as another one. You need to ensure the authenticated user has the permission to use the authorization of resources of the other user. ie. this example will allow the server user to authenticate as usual but use the authorization of user1:

+
GRANT PROXY.LOGIN on role user1 to server
+
+
+

then you can do the proxy authentication….

+
from cassandra.cluster import Cluster
+from cassandra.auth import SaslAuthProvider
+
+sasl_kwargs = {
+  "service": 'dse',
+  "mechanism":"PLAIN",
+  "username": 'server',
+  'password': 'server',
+  'authorization_id': 'user1'
+}
+
+auth_provider = SaslAuthProvider(**sasl_kwargs)
+c = Cluster(auth_provider=auth_provider)
+s = c.connect()
+s.execute(...)  # all requests will be executed as 'user1'
+
+
+

If you are using kerberos, you can use directly DSEGSSAPIAuthProvider and pass the authorization_id, like this:

+
from cassandra.cluster import Cluster
+from cassandra.auth import DSEGSSAPIAuthProvider
+
+# Ensure the kerberos ticket of the server user is set with the kinit utility.
+auth_provider = DSEGSSAPIAuthProvider(service='dse', qops=["auth"], principal="server@DATASTAX.COM",
+                                      authorization_id='user1@DATASTAX.COM')
+c = Cluster(auth_provider=auth_provider)
+s = c.connect()
+s.execute(...)  # all requests will be executed as 'user1'
+
+
+
+
+

Proxy Execute

+

Proxy execute allows you to execute requests as another user than the authenticated one. You need to ensure the authenticated user has the permission to use the authorization of resources of the specified user. ie. this example will allow the server user to execute requests as user1:

+
GRANT PROXY.EXECUTE on role user1 to server
+
+
+

then you can do a proxy execute…

+
from cassandra.cluster import Cluster
+from cassandra.auth import DSEPlainTextAuthProvider,
+
+auth_provider = DSEPlainTextAuthProvider('server', 'server')
+
+c = Cluster(auth_provider=auth_provider)
+s = c.connect()
+s.execute('select * from k.t;', execute_as='user1')  # the request will be executed as 'user1'
+
+
+

Please see the official documentation for more details on the feature and configuration process.

+
+
+
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.26.2-scylla/sitemap.xml b/3.26.2-scylla/sitemap.xml new file mode 100644 index 0000000000..bcdebfda06 --- /dev/null +++ b/3.26.2-scylla/sitemap.xml @@ -0,0 +1,2 @@ + +https://python-driver.docs.scylladb.com/stable/CHANGELOG.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/auth.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/cluster.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/concurrent.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/connection.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/cqlengine/columns.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/cqlengine/connection.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/cqlengine/management.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/cqlengine/models.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/cqlengine/query.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/cqlengine/usertype.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/datastax/graph/fluent/index.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/datastax/graph/fluent/predicates.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/datastax/graph/fluent/query.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/datastax/graph/index.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/decoder.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/encoder.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/graph.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/io/asyncioreactor.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/io/asyncorereactor.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/io/eventletreactor.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/io/geventreactor.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/io/libevreactor.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/io/twistedreactor.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/metadata.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/metrics.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/policies.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/pool.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/protocol.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/query.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/timestamps.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/util.htmlhttps://python-driver.docs.scylladb.com/stable/api/index.htmlhttps://python-driver.docs.scylladb.com/stable/cqlengine/batches.htmlhttps://python-driver.docs.scylladb.com/stable/cqlengine/connections.htmlhttps://python-driver.docs.scylladb.com/stable/cqlengine/faq.htmlhttps://python-driver.docs.scylladb.com/stable/cqlengine/models.htmlhttps://python-driver.docs.scylladb.com/stable/cqlengine/queryset.htmlhttps://python-driver.docs.scylladb.com/stable/cqlengine/third-party.htmlhttps://python-driver.docs.scylladb.com/stable/cqlengine/upgrade-guide.htmlhttps://python-driver.docs.scylladb.com/stable/dates-and-times.htmlhttps://python-driver.docs.scylladb.com/stable/execution-profiles.htmlhttps://python-driver.docs.scylladb.com/stable/faq.htmlhttps://python-driver.docs.scylladb.com/stable/getting-started.htmlhttps://python-driver.docs.scylladb.com/stable/index.htmlhttps://python-driver.docs.scylladb.com/stable/installation.htmlhttps://python-driver.docs.scylladb.com/stable/lwt.htmlhttps://python-driver.docs.scylladb.com/stable/object-mapper.htmlhttps://python-driver.docs.scylladb.com/stable/performance.htmlhttps://python-driver.docs.scylladb.com/stable/query-paging.htmlhttps://python-driver.docs.scylladb.com/stable/scylla-cloud.htmlhttps://python-driver.docs.scylladb.com/stable/scylla-cloud-serverless.htmlhttps://python-driver.docs.scylladb.com/stable/scylla-specific.htmlhttps://python-driver.docs.scylladb.com/stable/security.htmlhttps://python-driver.docs.scylladb.com/stable/upgrading.htmlhttps://python-driver.docs.scylladb.com/stable/user-defined-types.htmlhttps://python-driver.docs.scylladb.com/stable/py-modindex.htmlhttps://python-driver.docs.scylladb.com/stable/404.htmlhttps://python-driver.docs.scylladb.com/stable/search.html \ No newline at end of file diff --git a/3.26.2-scylla/upgrading.html b/3.26.2-scylla/upgrading.html new file mode 100644 index 0000000000..48b1cd0e9e --- /dev/null +++ b/3.26.2-scylla/upgrading.html @@ -0,0 +1,1019 @@ + + + + + + + + + + + + + Upgrading | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + + + +
+ +
+ +
+

Upgrading

+
+
+
+

Upgrading from dse-driver

+

Since 3.21.0, scylla-driver fully supports DataStax products. dse-driver and +dse-graph users should now migrate to scylla-driver to benefit from latest bug fixes +and new features. The upgrade to this new unified driver version is straightforward +with no major API changes.

+
+

Installation

+

Only the scylla-driver package should be installed. dse-driver and dse-graph +are not required anymore:

+
pip install scylla-driver
+
+
+

If you need the Graph Fluent API (features provided by dse-graph):

+
pip install scylla-driver[graph]
+
+
+

See Installation for more details.

+
+
+

Import from the cassandra module

+

There is no dse module, so you should import from the cassandra module. You +need to change only the first module of your import statements, not the submodules.

+
from dse.cluster import Cluster, EXEC_PROFILE_GRAPH_DEFAULT
+from dse.auth import PlainTextAuthProvider
+from dse.policies import WhiteListRoundRobinPolicy
+
+# becomes
+
+from cassandra.cluster import Cluster, EXEC_PROFILE_GRAPH_DEFAULT
+from cassandra.auth import PlainTextAuthProvider
+from cassandra.policies import WhiteListRoundRobinPolicy
+
+
+

Also note that the cassandra.hosts module doesn’t exist in scylla-driver. This +module is named cassandra.pool.

+
+
+

dse-graph

+

dse-graph features are now built into scylla-driver. The only change you need +to do is your import statements:

+
from dse_graph import ..
+from dse_graph.query import ..
+
+# becomes
+
+from cassandra.datastax.graph.fluent import ..
+from cassandra.datastax.graph.fluent.query import ..
+
+
+

See fluent.

+
+
+

Session.execute and Session.execute_async API

+

Although it is not common to use this API with positional arguments, it is +important to be aware that the host and execute_as parameters have had +their positional order swapped. This is only because execute_as was added +in dse-driver before host.

+

See Session.execute().

+
+
+

Deprecations

+

These changes are optional, but recommended:

+
    +
  • Importing from cassandra.graph is deprecated. Consider importing from cassandra.datastax.graph.

  • +
  • Use DefaultLoadBalancingPolicy instead of DSELoadBalancingPolicy.

  • +
+
+
+
+

Upgrading to 3.0

+

Version 3.0 of the DataStax Python driver for Apache Cassandra +adds support for Cassandra 3.0 while maintaining support for +previously supported versions. In addition to substantial internal rework, +there are several updates to the API that integrators will need +to consider:

+
+

Default consistency is now LOCAL_ONE

+

Previous value was ONE. The new value is introduced to mesh with the default +DC-aware load balancing policy and to match other drivers.

+
+
+

Execution API Updates

+
+

Result return normalization

+

PYTHON-368

+

Previously results would be returned as a list of rows for result rows +up to fetch_size, and PagedResult afterward. This could break +application code that assumed one type and got another.

+

Now, all results are returned as an iterable ResultSet.

+

The preferred way to consume results of unknown size is to iterate through +them, letting automatic paging occur as they are consumed.

+
results = session.execute("SELECT * FROM system.local")
+for row in results:
+    process(row)
+
+
+

If the expected size of the results is known, it is still possible to +materialize a list using the iterator:

+
results = session.execute("SELECT * FROM system.local")
+row_list = list(results)
+
+
+

For backward compatibility, ResultSet supports indexing. When +accessed at an index, a ~.ResultSet object will materialize all its pages:

+
results = session.execute("SELECT * FROM system.local")
+first_result = results[0]  # materializes results, fetching all pages
+
+
+

This can send requests and load (possibly large) results into memory, so +~.ResultSet will log a warning on implicit materialization.

+
+
+

Trace information is not attached to executed Statements

+

PYTHON-318

+

Previously trace data was attached to Statements if tracing was enabled. This +could lead to confusion if the same statement was used for multiple executions.

+

Now, trace data is associated with the ResponseFuture and ResultSet +returned for each query:

+

ResponseFuture.get_query_trace()

+

ResponseFuture.get_all_query_traces()

+

ResultSet.get_query_trace()

+

ResultSet.get_all_query_traces()

+
+
+

Binding named parameters now ignores extra names

+

PYTHON-178

+

Previously, BoundStatement.bind() would raise if a mapping +was passed with extra names not found in the prepared statement.

+

Behavior in 3.0+ is to ignore extra names.

+
+
+
+

blist removed as soft dependency

+

PYTHON-385

+

Previously the driver had a soft dependency on blist sortedset, using +that where available and using an internal fallback where possible.

+

Now, the driver never chooses the blist variant, instead returning the +internal util.SortedSet for all set results. The class implements +all standard set operations, so no integration code should need to change unless +it explicitly checks for sortedset type.

+
+
+

Metadata API Updates

+

PYTHON-276, PYTHON-408, PYTHON-400, PYTHON-422

+

Cassandra 3.0 brought a substantial overhaul to the internal schema metadata representation. +This version of the driver supports that metadata in addition to the legacy version. Doing so +also brought some changes to the metadata model.

+

The present API is documented: cassandra.metadata. Changes highlighted below:

+
    +
  • All types are now exposed as CQL types instead of types derived from the internal server implementation

  • +
  • Some metadata attributes have changed names to match current nomenclature (for example, Index.kind in place of Index.type).

  • +
  • Some metadata attributes removed

    +
      +
    • TableMetadata.keyspace reference replaced with TableMetadata.keyspace_name

    • +
    • ColumnMetadata.index is removed table- and keyspace-level mappings are still maintained

    • +
    +
  • +
+
+
+

Several deprecated features are removed

+

PYTHON-292

+
    +
  • ResponseFuture.result timeout parameter is removed, use Session.execute timeout instead (031ebb0)

  • +
  • Cluster.refresh_schema removed, use Cluster.refresh_*_metadata instead (419fcdf)

  • +
  • Cluster.submit_schema_refresh removed (574266d)

  • +
  • cqltypes time/date functions removed, use util entry points instead (bb984ee)

  • +
  • decoder module removed (e16a073)

  • +
  • TableMetadata.keyspace attribute replaced with keyspace_name (cc94073)

  • +
  • cqlengine.columns.TimeUUID.from_datetime removed, use util variant instead (96489cc)

  • +
  • cqlengine.columns.Float(double_precision) parameter removed, use columns.Double instead (a2d3a98)

  • +
  • cqlengine keyspace management functions are removed in favor of the strategy-specific entry points (4bd5909)

  • +
  • cqlengine.Model.__polymorphic_*__ attributes removed, use __discriminator* attributes instead (9d98c8e)

  • +
  • cqlengine.statements will no longer warn about list list prepend behavior (79efe97)

  • +
+
+
+
+

Upgrading to 2.1 from 2.0

+

Version 2.1 of the DataStax Python driver for Apache Cassandra +adds support for Cassandra 2.1 and version 3 of the native protocol.

+

Cassandra 1.2, 2.0, and 2.1 are all supported. However, 1.2 only +supports protocol version 1, and 2.0 only supports versions 1 and +2, so some features may not be available.

+
+

Using the v3 Native Protocol

+

By default, the driver will attempt to use version 2 of the +native protocol. To use version 3, you must explicitly +set the protocol_version:

+
from cassandra.cluster import Cluster
+
+cluster = Cluster(protocol_version=3)
+
+
+

Note that protocol version 3 is only supported by Cassandra 2.1+.

+

In future releases, the driver may default to using protocol version +3.

+
+
+

Working with User-Defined Types

+

Cassandra 2.1 introduced the ability to define new types:

+
USE KEYSPACE mykeyspace;
+
+CREATE TYPE address (street text, city text, zip int);
+
+
+

The driver generally expects you to use instances of a specific +class to represent column values of this type. You can let the +driver know what class to use with Cluster.register_user_type():

+
cluster = Cluster()
+
+class Address(object):
+
+    def __init__(self, street, city, zipcode):
+        self.street = street
+        self.city = text
+        self.zipcode = zipcode
+
+cluster.register_user_type('mykeyspace', 'address', Address)
+
+
+

When inserting data for address columns, you should pass in +instances of Address. When querying data, address column +values will be instances of Address.

+

If no class is registered for a user-defined type, query results +will use a namedtuple class and data may only be inserted +though prepared statements.

+

See User Defined Types for more details.

+
+
+

Customizing Encoders for Non-prepared Statements

+

Starting with version 2.1 of the driver, it is possible to customize +how Python types are converted to CQL literals when working with +non-prepared statements. This is done on a per-Session +basis through Session.encoder:

+
cluster = Cluster()
+session = cluster.connect()
+session.encoder.mapping[tuple] = session.encoder.cql_encode_tuple
+
+
+

See Type Conversions for the table of default CQL literal conversions.

+
+
+

Using Client-Side Protocol-Level Timestamps

+

With version 3 of the native protocol, timestamps may be supplied by the +client at the protocol level. (Normally, if they are not specified within +the CQL query itself, a timestamp is generated server-side.)

+

When protocol_version is set to 3 or higher, the driver +will automatically use client-side timestamps with microsecond precision +unless Session.use_client_timestamp is changed to False. +If a timestamp is specified within the CQL query, it will override the +timestamp generated by the driver.

+
+
+
+

Upgrading to 2.0 from 1.x

+

Version 2.0 of the DataStax Python driver for Apache Cassandra +includes some notable improvements over version 1.x. This version +of the driver supports Cassandra 1.2, 2.0, and 2.1. However, not +all features may be used with Cassandra 1.2, and some new features +in 2.1 are not yet supported.

+
+

Using the v2 Native Protocol

+

By default, the driver will attempt to use version 2 of Cassandra’s +native protocol. You can explicitly set the protocol version to +2, though:

+
from cassandra.cluster import Cluster
+
+cluster = Cluster(protocol_version=2)
+
+
+

When working with Cassandra 1.2, you will need to +explicitly set the protocol_version to 1:

+
from cassandra.cluster import Cluster
+
+cluster = Cluster(protocol_version=1)
+
+
+
+
+

Automatic Query Paging

+

Version 2 of the native protocol adds support for automatic query +paging, which can make dealing with large result sets much simpler.

+

See Paging Large Queries for full details.

+
+
+

Protocol-Level Batch Statements

+

With version 1 of the native protocol, batching of statements required +using a BATCH cql query. +With version 2 of the native protocol, you can now batch statements at +the protocol level. This allows you to use many different prepared +statements within a single batch.

+

See BatchStatement for details and usage examples.

+
+
+

SASL-based Authentication

+

Also new in version 2 of the native protocol is SASL-based authentication. +See the section on Security for details and examples.

+
+
+

Lightweight Transactions

+

Lightweight transactions are another new feature. To use lightweight transactions, add IF clauses +to your CQL queries and set the serial_consistency_level +on your statements.

+
+
+

Calling Cluster.shutdown()

+

In order to fix some issues around garbage collection and unclean interpreter +shutdowns, version 2.0 of the driver requires you to call Cluster.shutdown() +on your Cluster objects when you are through with them. +This helps to guarantee a clean shutdown.

+
+
+

Deprecations

+

The following functions have moved from cassandra.decoder to cassandra.query. +The original functions have been left in place with a DeprecationWarning for +now:

+ +
+
+

Dependency Changes

+

The following dependencies have officially been made optional:

+
    +
  • scales

  • +
  • blist

  • +
+

And one new dependency has been added (to enable Python 3 support):

+
    +
  • six

  • +
+
+
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/3.26.2-scylla/user-defined-types.html b/3.26.2-scylla/user-defined-types.html new file mode 100644 index 0000000000..518bdfb631 --- /dev/null +++ b/3.26.2-scylla/user-defined-types.html @@ -0,0 +1,749 @@ + + + + + + + + + + + + + User Defined Types | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + + + +
+ +
+ +
+

User Defined Types

+

Cassandra 2.1 introduced user-defined types (UDTs). You can create a +new type through CREATE TYPE statements in CQL:

+
CREATE TYPE address (street text, zip int);
+
+
+

Version 2.1 of the Python driver adds support for user-defined types.

+
+

Registering a UDT

+

You can tell the Python driver to return columns of a specific UDT as +instances of a class or a dict by registering them with your Cluster +instance through Cluster.register_user_type():

+
+

Map a Class to a UDT

+
cluster = Cluster(protocol_version=3)
+session = cluster.connect()
+session.set_keyspace('mykeyspace')
+session.execute("CREATE TYPE address (street text, zipcode int)")
+session.execute("CREATE TABLE users (id int PRIMARY KEY, location frozen<address>)")
+
+# create a class to map to the "address" UDT
+class Address(object):
+
+    def __init__(self, street, zipcode):
+        self.street = street
+        self.zipcode = zipcode
+
+cluster.register_user_type('mykeyspace', 'address', Address)
+
+# insert a row using an instance of Address
+session.execute("INSERT INTO users (id, location) VALUES (%s, %s)",
+                (0, Address("123 Main St.", 78723)))
+
+# results will include Address instances
+results = session.execute("SELECT * FROM users")
+row = results[0]
+print(row.id, row.location.street, row.location.zipcode)
+
+
+
+
+

Map a dict to a UDT

+
cluster = Cluster(protocol_version=3)
+session = cluster.connect()
+session.set_keyspace('mykeyspace')
+session.execute("CREATE TYPE address (street text, zipcode int)")
+session.execute("CREATE TABLE users (id int PRIMARY KEY, location frozen<address>)")
+
+cluster.register_user_type('mykeyspace', 'address', dict)
+
+# insert a row using a prepared statement and a tuple
+insert_statement = session.prepare("INSERT INTO mykeyspace.users (id, location) VALUES (?, ?)")
+session.execute(insert_statement, [0, ("123 Main St.", 78723)])
+
+# results will include dict instances
+results = session.execute("SELECT * FROM users")
+row = results[0]
+print(row.id, row.location['street'], row.location['zipcode'])
+
+
+
+
+
+

Using UDTs Without Registering Them

+

Although it is recommended to register your types with +Cluster.register_user_type(), the driver gives you some options +for working with unregistered UDTS.

+

When you use prepared statements, the driver knows what data types to +expect for each placeholder. This allows you to pass any object you +want for a UDT, as long as it has attributes that match the field names +for the UDT:

+
cluster = Cluster(protocol_version=3)
+session = cluster.connect()
+session.set_keyspace('mykeyspace')
+session.execute("CREATE TYPE address (street text, zipcode int)")
+session.execute("CREATE TABLE users (id int PRIMARY KEY, location frozen<address>)")
+
+class Foo(object):
+
+    def __init__(self, street, zipcode, otherstuff):
+        self.street = street
+        self.zipcode = zipcode
+        self.otherstuff = otherstuff
+
+insert_statement = session.prepare("INSERT INTO users (id, location) VALUES (?, ?)")
+
+# since we're using a prepared statement, we don't *have* to register
+# a class to map to the UDT to insert data.  The object just needs to have
+# "street" and "zipcode" attributes (which Foo does):
+session.execute(insert_statement, [0, Foo("123 Main St.", 78723, "some other stuff")])
+
+# when we query data, UDT columns that don't have a class registered
+# will be returned as namedtuples:
+results = session.execute("SELECT * FROM users")
+first_row = results[0]
+address = first_row.location
+print(address)  # prints "Address(street='123 Main St.', zipcode=78723)"
+street = address.street
+zipcode = address.street
+
+
+

As shown in the code example, inserting data for UDT columns without registering +a class works fine for prepared statements. However, you must register a +class to insert UDT columns with unprepared statements.* You can still query +UDT columns without registered classes using unprepared statements, they will +simply return namedtuple instances (just like prepared statements do).

+

* this applies to parameterized unprepared statements, in which the driver will be formatting parameters – not statements with interpolated UDT literals.

+
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/404.html b/404.html new file mode 100644 index 0000000000..d60936cbfe --- /dev/null +++ b/404.html @@ -0,0 +1,31 @@ + + + + + + + + + ScyllaDB + + + + + + + + + + + +
+

404

+

The ScyllaDB monster ate your page!

+

+ Home +

+
+ + + \ No newline at end of file diff --git a/CNAME b/CNAME new file mode 100644 index 0000000000..9f3e01a070 --- /dev/null +++ b/CNAME @@ -0,0 +1 @@ +python-driver.docs.scylladb.com \ No newline at end of file diff --git a/_static/basic.css b/_static/basic.css new file mode 100644 index 0000000000..603f6a8798 --- /dev/null +++ b/_static/basic.css @@ -0,0 +1,905 @@ +/* + * basic.css + * ~~~~~~~~~ + * + * Sphinx stylesheet -- basic theme. + * + * :copyright: Copyright 2007-2021 by the Sphinx team, see AUTHORS. + * :license: BSD, see LICENSE for details. + * + */ + +/* -- main layout ----------------------------------------------------------- */ + +div.clearer { + clear: both; +} + +div.section::after { + display: block; + content: ''; + clear: left; +} + +/* -- relbar ---------------------------------------------------------------- */ + +div.related { + width: 100%; + font-size: 90%; +} + +div.related h3 { + display: none; +} + +div.related ul { + margin: 0; + padding: 0 0 0 10px; + list-style: none; +} + +div.related li { + display: inline; +} + +div.related li.right { + float: right; + margin-right: 5px; +} + +/* -- sidebar --------------------------------------------------------------- */ + +div.sphinxsidebarwrapper { + padding: 10px 5px 0 10px; +} + +div.sphinxsidebar { + float: left; + width: 230px; + margin-left: -100%; + font-size: 90%; + word-wrap: break-word; + overflow-wrap : break-word; +} + +div.sphinxsidebar ul { + list-style: none; +} + +div.sphinxsidebar ul ul, +div.sphinxsidebar ul.want-points { + margin-left: 20px; + list-style: square; +} + +div.sphinxsidebar ul ul { + margin-top: 0; + margin-bottom: 0; +} + +div.sphinxsidebar form { + margin-top: 10px; +} + +div.sphinxsidebar input { + border: 1px solid #98dbcc; + font-family: sans-serif; + font-size: 1em; +} + +div.sphinxsidebar #searchbox form.search { + overflow: hidden; +} + +div.sphinxsidebar #searchbox input[type="text"] { + float: left; + width: 80%; + padding: 0.25em; + box-sizing: border-box; +} + +div.sphinxsidebar #searchbox input[type="submit"] { + float: left; + width: 20%; + border-left: none; + padding: 0.25em; + box-sizing: border-box; +} + + +img { + border: 0; + max-width: 100%; +} + +/* -- search page ----------------------------------------------------------- */ + +ul.search { + margin: 10px 0 0 20px; + padding: 0; +} + +ul.search li { + padding: 5px 0 5px 20px; + background-image: url(file.png); + background-repeat: no-repeat; + background-position: 0 7px; +} + +ul.search li a { + font-weight: bold; +} + +ul.search li p.context { + color: #888; + margin: 2px 0 0 30px; + text-align: left; +} + +ul.keywordmatches li.goodmatch a { + font-weight: bold; +} + +/* -- index page ------------------------------------------------------------ */ + +table.contentstable { + width: 90%; + margin-left: auto; + margin-right: auto; +} + +table.contentstable p.biglink { + line-height: 150%; +} + +a.biglink { + font-size: 1.3em; +} + +span.linkdescr { + font-style: italic; + padding-top: 5px; + font-size: 90%; +} + +/* -- general index --------------------------------------------------------- */ + +table.indextable { + width: 100%; +} + +table.indextable td { + text-align: left; + vertical-align: top; +} + +table.indextable ul { + margin-top: 0; + margin-bottom: 0; + list-style-type: none; +} + +table.indextable > tbody > tr > td > ul { + padding-left: 0em; +} + +table.indextable tr.pcap { + height: 10px; +} + +table.indextable tr.cap { + margin-top: 10px; + background-color: #f2f2f2; +} + +img.toggler { + margin-right: 3px; + margin-top: 3px; + cursor: pointer; +} + +div.modindex-jumpbox { + border-top: 1px solid #ddd; + border-bottom: 1px solid #ddd; + margin: 1em 0 1em 0; + padding: 0.4em; +} + +div.genindex-jumpbox { + border-top: 1px solid #ddd; + border-bottom: 1px solid #ddd; + margin: 1em 0 1em 0; + padding: 0.4em; +} + +/* -- domain module index --------------------------------------------------- */ + +table.modindextable td { + padding: 2px; + border-collapse: collapse; +} + +/* -- general body styles --------------------------------------------------- */ + +div.body { + min-width: 450px; + max-width: 800px; +} + +div.body p, div.body dd, div.body li, div.body blockquote { + -moz-hyphens: auto; + -ms-hyphens: auto; + -webkit-hyphens: auto; + hyphens: auto; +} + +a.headerlink { + visibility: hidden; +} + +a.brackets:before, +span.brackets > a:before{ + content: "["; +} + +a.brackets:after, +span.brackets > a:after { + content: "]"; +} + +h1:hover > a.headerlink, +h2:hover > a.headerlink, +h3:hover > a.headerlink, +h4:hover > a.headerlink, +h5:hover > a.headerlink, +h6:hover > a.headerlink, +dt:hover > a.headerlink, +caption:hover > a.headerlink, +p.caption:hover > a.headerlink, +div.code-block-caption:hover > a.headerlink { + visibility: visible; +} + +div.body p.caption { + text-align: inherit; +} + +div.body td { + text-align: left; +} + +.first { + margin-top: 0 !important; +} + +p.rubric { + margin-top: 30px; + font-weight: bold; +} + +img.align-left, figure.align-left, .figure.align-left, object.align-left { + clear: left; + float: left; + margin-right: 1em; +} + +img.align-right, figure.align-right, .figure.align-right, object.align-right { + clear: right; + float: right; + margin-left: 1em; +} + +img.align-center, figure.align-center, .figure.align-center, object.align-center { + display: block; + margin-left: auto; + margin-right: auto; +} + +img.align-default, figure.align-default, .figure.align-default { + display: block; + margin-left: auto; + margin-right: auto; +} + +.align-left { + text-align: left; +} + +.align-center { + text-align: center; +} + +.align-default { + text-align: center; +} + +.align-right { + text-align: right; +} + +/* -- sidebars -------------------------------------------------------------- */ + +div.sidebar, +aside.sidebar { + margin: 0 0 0.5em 1em; + border: 1px solid #ddb; + padding: 7px; + background-color: #ffe; + width: 40%; + float: right; + clear: right; + overflow-x: auto; +} + +p.sidebar-title { + font-weight: bold; +} + +div.admonition, div.topic, blockquote { + clear: left; +} + +/* -- topics ---------------------------------------------------------------- */ + +div.topic { + border: 1px solid #ccc; + padding: 7px; + margin: 10px 0 10px 0; +} + +p.topic-title { + font-size: 1.1em; + font-weight: bold; + margin-top: 10px; +} + +/* -- admonitions ----------------------------------------------------------- */ + +div.admonition { + margin-top: 10px; + margin-bottom: 10px; + padding: 7px; +} + +div.admonition dt { + font-weight: bold; +} + +p.admonition-title { + margin: 0px 10px 5px 0px; + font-weight: bold; +} + +div.body p.centered { + text-align: center; + margin-top: 25px; +} + +/* -- content of sidebars/topics/admonitions -------------------------------- */ + +div.sidebar > :last-child, +aside.sidebar > :last-child, +div.topic > :last-child, +div.admonition > :last-child { + margin-bottom: 0; +} + +div.sidebar::after, +aside.sidebar::after, +div.topic::after, +div.admonition::after, +blockquote::after { + display: block; + content: ''; + clear: both; +} + +/* -- tables ---------------------------------------------------------------- */ + +table.docutils { + margin-top: 10px; + margin-bottom: 10px; + border: 0; + border-collapse: collapse; +} + +table.align-center { + margin-left: auto; + margin-right: auto; +} + +table.align-default { + margin-left: auto; + margin-right: auto; +} + +table caption span.caption-number { + font-style: italic; +} + +table caption span.caption-text { +} + +table.docutils td, table.docutils th { + padding: 1px 8px 1px 5px; + border-top: 0; + border-left: 0; + border-right: 0; + border-bottom: 1px solid #aaa; +} + +table.footnote td, table.footnote th { + border: 0 !important; +} + +th { + text-align: left; + padding-right: 5px; +} + +table.citation { + border-left: solid 1px gray; + margin-left: 1px; +} + +table.citation td { + border-bottom: none; +} + +th > :first-child, +td > :first-child { + margin-top: 0px; +} + +th > :last-child, +td > :last-child { + margin-bottom: 0px; +} + +/* -- figures --------------------------------------------------------------- */ + +div.figure, figure { + margin: 0.5em; + padding: 0.5em; +} + +div.figure p.caption, figcaption { + padding: 0.3em; +} + +div.figure p.caption span.caption-number, +figcaption span.caption-number { + font-style: italic; +} + +div.figure p.caption span.caption-text, +figcaption span.caption-text { +} + +/* -- field list styles ----------------------------------------------------- */ + +table.field-list td, table.field-list th { + border: 0 !important; +} + +.field-list ul { + margin: 0; + padding-left: 1em; +} + +.field-list p { + margin: 0; +} + +.field-name { + -moz-hyphens: manual; + -ms-hyphens: manual; + -webkit-hyphens: manual; + hyphens: manual; +} + +/* -- hlist styles ---------------------------------------------------------- */ + +table.hlist { + margin: 1em 0; +} + +table.hlist td { + vertical-align: top; +} + +/* -- object description styles --------------------------------------------- */ + +.sig { + font-family: 'Consolas', 'Menlo', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace; +} + +.sig-name, code.descname { + background-color: transparent; + font-weight: bold; +} + +.sig-name { + font-size: 1.1em; +} + +code.descname { + font-size: 1.2em; +} + +.sig-prename, code.descclassname { + background-color: transparent; +} + +.optional { + font-size: 1.3em; +} + +.sig-paren { + font-size: larger; +} + +.sig-param.n { + font-style: italic; +} + +/* C++ specific styling */ + +.sig-inline.c-texpr, +.sig-inline.cpp-texpr { + font-family: unset; +} + +.sig.c .k, .sig.c .kt, +.sig.cpp .k, .sig.cpp .kt { + color: #0033B3; +} + +.sig.c .m, +.sig.cpp .m { + color: #1750EB; +} + +.sig.c .s, .sig.c .sc, +.sig.cpp .s, .sig.cpp .sc { + color: #067D17; +} + + +/* -- other body styles ----------------------------------------------------- */ + +ol.arabic { + list-style: decimal; +} + +ol.loweralpha { + list-style: lower-alpha; +} + +ol.upperalpha { + list-style: upper-alpha; +} + +ol.lowerroman { + list-style: lower-roman; +} + +ol.upperroman { + list-style: upper-roman; +} + +:not(li) > ol > li:first-child > :first-child, +:not(li) > ul > li:first-child > :first-child { + margin-top: 0px; +} + +:not(li) > ol > li:last-child > :last-child, +:not(li) > ul > li:last-child > :last-child { + margin-bottom: 0px; +} + +ol.simple ol p, +ol.simple ul p, +ul.simple ol p, +ul.simple ul p { + margin-top: 0; +} + +ol.simple > li:not(:first-child) > p, +ul.simple > li:not(:first-child) > p { + margin-top: 0; +} + +ol.simple p, +ul.simple p { + margin-bottom: 0; +} + +dl.footnote > dt, +dl.citation > dt { + float: left; + margin-right: 0.5em; +} + +dl.footnote > dd, +dl.citation > dd { + margin-bottom: 0em; +} + +dl.footnote > dd:after, +dl.citation > dd:after { + content: ""; + clear: both; +} + +dl.field-list { + display: grid; + grid-template-columns: fit-content(30%) auto; +} + +dl.field-list > dt { + font-weight: bold; + word-break: break-word; + padding-left: 0.5em; + padding-right: 5px; +} + +dl.field-list > dt:after { + content: ":"; +} + +dl.field-list > dd { + padding-left: 0.5em; + margin-top: 0em; + margin-left: 0em; + margin-bottom: 0em; +} + +dl { + margin-bottom: 15px; +} + +dd > :first-child { + margin-top: 0px; +} + +dd ul, dd table { + margin-bottom: 10px; +} + +dd { + margin-top: 3px; + margin-bottom: 10px; + margin-left: 30px; +} + +dl > dd:last-child, +dl > dd:last-child > :last-child { + margin-bottom: 0; +} + +dt:target, span.highlighted { + background-color: #fbe54e; +} + +rect.highlighted { + fill: #fbe54e; +} + +dl.glossary dt { + font-weight: bold; + font-size: 1.1em; +} + +.versionmodified { + font-style: italic; +} + +.system-message { + background-color: #fda; + padding: 5px; + border: 3px solid red; +} + +.footnote:target { + background-color: #ffa; +} + +.line-block { + display: block; + margin-top: 1em; + margin-bottom: 1em; +} + +.line-block .line-block { + margin-top: 0; + margin-bottom: 0; + margin-left: 1.5em; +} + +.guilabel, .menuselection { + font-family: sans-serif; +} + +.accelerator { + text-decoration: underline; +} + +.classifier { + font-style: oblique; +} + +.classifier:before { + font-style: normal; + margin: 0 0.5em; + content: ":"; + display: inline-block; +} + +abbr, acronym { + border-bottom: dotted 1px; + cursor: help; +} + +/* -- code displays --------------------------------------------------------- */ + +pre { + overflow: auto; + overflow-y: hidden; /* fixes display issues on Chrome browsers */ +} + +pre, div[class*="highlight-"] { + clear: both; +} + +span.pre { + -moz-hyphens: none; + -ms-hyphens: none; + -webkit-hyphens: none; + hyphens: none; +} + +div[class*="highlight-"] { + margin: 1em 0; +} + +td.linenos pre { + border: 0; + background-color: transparent; + color: #aaa; +} + +table.highlighttable { + display: block; +} + +table.highlighttable tbody { + display: block; +} + +table.highlighttable tr { + display: flex; +} + +table.highlighttable td { + margin: 0; + padding: 0; +} + +table.highlighttable td.linenos { + padding-right: 0.5em; +} + +table.highlighttable td.code { + flex: 1; + overflow: hidden; +} + +.highlight .hll { + display: block; +} + +div.highlight pre, +table.highlighttable pre { + margin: 0; +} + +div.code-block-caption + div { + margin-top: 0; +} + +div.code-block-caption { + margin-top: 1em; + padding: 2px 5px; + font-size: small; +} + +div.code-block-caption code { + background-color: transparent; +} + +table.highlighttable td.linenos, +span.linenos, +div.highlight span.gp { /* gp: Generic.Prompt */ + user-select: none; + -webkit-user-select: text; /* Safari fallback only */ + -webkit-user-select: none; /* Chrome/Safari */ + -moz-user-select: none; /* Firefox */ + -ms-user-select: none; /* IE10+ */ +} + +div.code-block-caption span.caption-number { + padding: 0.1em 0.3em; + font-style: italic; +} + +div.code-block-caption span.caption-text { +} + +div.literal-block-wrapper { + margin: 1em 0; +} + +code.xref, a code { + background-color: transparent; + font-weight: bold; +} + +h1 code, h2 code, h3 code, h4 code, h5 code, h6 code { + background-color: transparent; +} + +.viewcode-link { + float: right; +} + +.viewcode-back { + float: right; + font-family: sans-serif; +} + +div.viewcode-block:target { + margin: -1px -10px; + padding: 0 10px; +} + +/* -- math display ---------------------------------------------------------- */ + +img.math { + vertical-align: middle; +} + +div.body div.math p { + text-align: center; +} + +span.eqno { + float: right; +} + +span.eqno a.headerlink { + position: absolute; + z-index: 1; +} + +div.math:hover a.headerlink { + visibility: visible; +} + +/* -- printout stylesheet --------------------------------------------------- */ + +@media print { + div.document, + div.documentwrapper, + div.bodywrapper { + margin: 0 !important; + width: 100%; + } + + div.sphinxsidebar, + div.related, + div.footer, + #top-link { + display: none; + } +} \ No newline at end of file diff --git a/_static/check-solid.svg b/_static/check-solid.svg new file mode 100644 index 0000000000..92fad4b5c0 --- /dev/null +++ b/_static/check-solid.svg @@ -0,0 +1,4 @@ + + + + diff --git a/_static/clipboard.min.js b/_static/clipboard.min.js new file mode 100644 index 0000000000..54b3c46381 --- /dev/null +++ b/_static/clipboard.min.js @@ -0,0 +1,7 @@ +/*! + * clipboard.js v2.0.8 + * https://clipboardjs.com/ + * + * Licensed MIT © Zeno Rocha + */ +!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?exports.ClipboardJS=e():t.ClipboardJS=e()}(this,function(){return n={686:function(t,e,n){"use strict";n.d(e,{default:function(){return o}});var e=n(279),i=n.n(e),e=n(370),u=n.n(e),e=n(817),c=n.n(e);function a(t){try{return document.execCommand(t)}catch(t){return}}var f=function(t){t=c()(t);return a("cut"),t};var l=function(t){var e,n,o,r=1 + + + + diff --git a/_static/copybutton.css b/_static/copybutton.css new file mode 100644 index 0000000000..f1916ec7d1 --- /dev/null +++ b/_static/copybutton.css @@ -0,0 +1,94 @@ +/* Copy buttons */ +button.copybtn { + position: absolute; + display: flex; + top: .3em; + right: .3em; + width: 1.7em; + height: 1.7em; + opacity: 0; + transition: opacity 0.3s, border .3s, background-color .3s; + user-select: none; + padding: 0; + border: none; + outline: none; + border-radius: 0.4em; + /* The colors that GitHub uses */ + border: #1b1f2426 1px solid; + background-color: #f6f8fa; + color: #57606a; +} + +button.copybtn.success { + border-color: #22863a; + color: #22863a; +} + +button.copybtn svg { + stroke: currentColor; + width: 1.5em; + height: 1.5em; + padding: 0.1em; +} + +div.highlight { + position: relative; +} + +/* Show the copybutton */ +.highlight:hover button.copybtn, button.copybtn.success { + opacity: 1; +} + +.highlight button.copybtn:hover { + background-color: rgb(235, 235, 235); +} + +.highlight button.copybtn:active { + background-color: rgb(187, 187, 187); +} + +/** + * A minimal CSS-only tooltip copied from: + * https://codepen.io/mildrenben/pen/rVBrpK + * + * To use, write HTML like the following: + * + *

Short

+ */ + .o-tooltip--left { + position: relative; + } + + .o-tooltip--left:after { + opacity: 0; + visibility: hidden; + position: absolute; + content: attr(data-tooltip); + padding: .2em; + font-size: .8em; + left: -.2em; + background: grey; + color: white; + white-space: nowrap; + z-index: 2; + border-radius: 2px; + transform: translateX(-102%) translateY(0); + transition: opacity 0.2s cubic-bezier(0.64, 0.09, 0.08, 1), transform 0.2s cubic-bezier(0.64, 0.09, 0.08, 1); +} + +.o-tooltip--left:hover:after { + display: block; + opacity: 1; + visibility: visible; + transform: translateX(-100%) translateY(0); + transition: opacity 0.2s cubic-bezier(0.64, 0.09, 0.08, 1), transform 0.2s cubic-bezier(0.64, 0.09, 0.08, 1); + transition-delay: .5s; +} + +/* By default the copy button shouldn't show up when printing a page */ +@media print { + button.copybtn { + display: none; + } +} diff --git a/_static/copybutton.js b/_static/copybutton.js new file mode 100644 index 0000000000..2ea7ff3e21 --- /dev/null +++ b/_static/copybutton.js @@ -0,0 +1,248 @@ +// Localization support +const messages = { + 'en': { + 'copy': 'Copy', + 'copy_to_clipboard': 'Copy to clipboard', + 'copy_success': 'Copied!', + 'copy_failure': 'Failed to copy', + }, + 'es' : { + 'copy': 'Copiar', + 'copy_to_clipboard': 'Copiar al portapapeles', + 'copy_success': '¡Copiado!', + 'copy_failure': 'Error al copiar', + }, + 'de' : { + 'copy': 'Kopieren', + 'copy_to_clipboard': 'In die Zwischenablage kopieren', + 'copy_success': 'Kopiert!', + 'copy_failure': 'Fehler beim Kopieren', + }, + 'fr' : { + 'copy': 'Copier', + 'copy_to_clipboard': 'Copier dans le presse-papier', + 'copy_success': 'Copié !', + 'copy_failure': 'Échec de la copie', + }, + 'ru': { + 'copy': 'Скопировать', + 'copy_to_clipboard': 'Скопировать в буфер', + 'copy_success': 'Скопировано!', + 'copy_failure': 'Не удалось скопировать', + }, + 'zh-CN': { + 'copy': '复制', + 'copy_to_clipboard': '复制到剪贴板', + 'copy_success': '复制成功!', + 'copy_failure': '复制失败', + }, + 'it' : { + 'copy': 'Copiare', + 'copy_to_clipboard': 'Copiato negli appunti', + 'copy_success': 'Copiato!', + 'copy_failure': 'Errore durante la copia', + } +} + +let locale = 'en' +if( document.documentElement.lang !== undefined + && messages[document.documentElement.lang] !== undefined ) { + locale = document.documentElement.lang +} + +let doc_url_root = DOCUMENTATION_OPTIONS.URL_ROOT; +if (doc_url_root == '#') { + doc_url_root = ''; +} + +/** + * SVG files for our copy buttons + */ +let iconCheck = ` + ${messages[locale]['copy_success']} + + +` + +// If the user specified their own SVG use that, otherwise use the default +let iconCopy = ``; +if (!iconCopy) { + iconCopy = ` + ${messages[locale]['copy_to_clipboard']} + + + +` +} + +/** + * Set up copy/paste for code blocks + */ + +const runWhenDOMLoaded = cb => { + if (document.readyState != 'loading') { + cb() + } else if (document.addEventListener) { + document.addEventListener('DOMContentLoaded', cb) + } else { + document.attachEvent('onreadystatechange', function() { + if (document.readyState == 'complete') cb() + }) + } +} + +const codeCellId = index => `codecell${index}` + +// Clears selected text since ClipboardJS will select the text when copying +const clearSelection = () => { + if (window.getSelection) { + window.getSelection().removeAllRanges() + } else if (document.selection) { + document.selection.empty() + } +} + +// Changes tooltip text for a moment, then changes it back +// We want the timeout of our `success` class to be a bit shorter than the +// tooltip and icon change, so that we can hide the icon before changing back. +var timeoutIcon = 2000; +var timeoutSuccessClass = 1500; + +const temporarilyChangeTooltip = (el, oldText, newText) => { + el.setAttribute('data-tooltip', newText) + el.classList.add('success') + // Remove success a little bit sooner than we change the tooltip + // So that we can use CSS to hide the copybutton first + setTimeout(() => el.classList.remove('success'), timeoutSuccessClass) + setTimeout(() => el.setAttribute('data-tooltip', oldText), timeoutIcon) +} + +// Changes the copy button icon for two seconds, then changes it back +const temporarilyChangeIcon = (el) => { + el.innerHTML = iconCheck; + setTimeout(() => {el.innerHTML = iconCopy}, timeoutIcon) +} + +const addCopyButtonToCodeCells = () => { + // If ClipboardJS hasn't loaded, wait a bit and try again. This + // happens because we load ClipboardJS asynchronously. + if (window.ClipboardJS === undefined) { + setTimeout(addCopyButtonToCodeCells, 250) + return + } + + // Add copybuttons to all of our code cells + const COPYBUTTON_SELECTOR = 'div.highlight pre'; + const codeCells = document.querySelectorAll(COPYBUTTON_SELECTOR) + codeCells.forEach((codeCell, index) => { + const id = codeCellId(index) + codeCell.setAttribute('id', id) + + const clipboardButton = id => + `` + codeCell.insertAdjacentHTML('afterend', clipboardButton(id)) + }) + +function escapeRegExp(string) { + return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string +} + +/** + * Removes excluded text from a Node. + * + * @param {Node} target Node to filter. + * @param {string} exclude CSS selector of nodes to exclude. + * @returns {DOMString} Text from `target` with text removed. + */ +function filterText(target, exclude) { + const clone = target.cloneNode(true); // clone as to not modify the live DOM + if (exclude) { + // remove excluded nodes + clone.querySelectorAll(exclude).forEach(node => node.remove()); + } + return clone.innerText; +} + +// Callback when a copy button is clicked. Will be passed the node that was clicked +// should then grab the text and replace pieces of text that shouldn't be used in output +function formatCopyText(textContent, copybuttonPromptText, isRegexp = false, onlyCopyPromptLines = true, removePrompts = true, copyEmptyLines = true, lineContinuationChar = "", hereDocDelim = "") { + var regexp; + var match; + + // Do we check for line continuation characters and "HERE-documents"? + var useLineCont = !!lineContinuationChar + var useHereDoc = !!hereDocDelim + + // create regexp to capture prompt and remaining line + if (isRegexp) { + regexp = new RegExp('^(' + copybuttonPromptText + ')(.*)') + } else { + regexp = new RegExp('^(' + escapeRegExp(copybuttonPromptText) + ')(.*)') + } + + const outputLines = []; + var promptFound = false; + var gotLineCont = false; + var gotHereDoc = false; + const lineGotPrompt = []; + for (const line of textContent.split('\n')) { + match = line.match(regexp) + if (match || gotLineCont || gotHereDoc) { + promptFound = regexp.test(line) + lineGotPrompt.push(promptFound) + if (removePrompts && promptFound) { + outputLines.push(match[2]) + } else { + outputLines.push(line) + } + gotLineCont = line.endsWith(lineContinuationChar) & useLineCont + if (line.includes(hereDocDelim) & useHereDoc) + gotHereDoc = !gotHereDoc + } else if (!onlyCopyPromptLines) { + outputLines.push(line) + } else if (copyEmptyLines && line.trim() === '') { + outputLines.push(line) + } + } + + // If no lines with the prompt were found then just use original lines + if (lineGotPrompt.some(v => v === true)) { + textContent = outputLines.join('\n'); + } + + // Remove a trailing newline to avoid auto-running when pasting + if (textContent.endsWith("\n")) { + textContent = textContent.slice(0, -1) + } + return textContent +} + + +var copyTargetText = (trigger) => { + var target = document.querySelector(trigger.attributes['data-clipboard-target'].value); + + // get filtered text + let exclude = '.linenos'; + + let text = filterText(target, exclude); + return formatCopyText(text, '', false, true, true, true, '', '') +} + + // Initialize with a callback so we can modify the text before copy + const clipboard = new ClipboardJS('.copybtn', {text: copyTargetText}) + + // Update UI with error/success messages + clipboard.on('success', event => { + clearSelection() + temporarilyChangeTooltip(event.trigger, messages[locale]['copy'], messages[locale]['copy_success']) + temporarilyChangeIcon(event.trigger) + }) + + clipboard.on('error', event => { + temporarilyChangeTooltip(event.trigger, messages[locale]['copy'], messages[locale]['copy_failure']) + }) +} + +runWhenDOMLoaded(addCopyButtonToCodeCells) \ No newline at end of file diff --git a/_static/copybutton_funcs.js b/_static/copybutton_funcs.js new file mode 100644 index 0000000000..dbe1aaad79 --- /dev/null +++ b/_static/copybutton_funcs.js @@ -0,0 +1,73 @@ +function escapeRegExp(string) { + return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string +} + +/** + * Removes excluded text from a Node. + * + * @param {Node} target Node to filter. + * @param {string} exclude CSS selector of nodes to exclude. + * @returns {DOMString} Text from `target` with text removed. + */ +export function filterText(target, exclude) { + const clone = target.cloneNode(true); // clone as to not modify the live DOM + if (exclude) { + // remove excluded nodes + clone.querySelectorAll(exclude).forEach(node => node.remove()); + } + return clone.innerText; +} + +// Callback when a copy button is clicked. Will be passed the node that was clicked +// should then grab the text and replace pieces of text that shouldn't be used in output +export function formatCopyText(textContent, copybuttonPromptText, isRegexp = false, onlyCopyPromptLines = true, removePrompts = true, copyEmptyLines = true, lineContinuationChar = "", hereDocDelim = "") { + var regexp; + var match; + + // Do we check for line continuation characters and "HERE-documents"? + var useLineCont = !!lineContinuationChar + var useHereDoc = !!hereDocDelim + + // create regexp to capture prompt and remaining line + if (isRegexp) { + regexp = new RegExp('^(' + copybuttonPromptText + ')(.*)') + } else { + regexp = new RegExp('^(' + escapeRegExp(copybuttonPromptText) + ')(.*)') + } + + const outputLines = []; + var promptFound = false; + var gotLineCont = false; + var gotHereDoc = false; + const lineGotPrompt = []; + for (const line of textContent.split('\n')) { + match = line.match(regexp) + if (match || gotLineCont || gotHereDoc) { + promptFound = regexp.test(line) + lineGotPrompt.push(promptFound) + if (removePrompts && promptFound) { + outputLines.push(match[2]) + } else { + outputLines.push(line) + } + gotLineCont = line.endsWith(lineContinuationChar) & useLineCont + if (line.includes(hereDocDelim) & useHereDoc) + gotHereDoc = !gotHereDoc + } else if (!onlyCopyPromptLines) { + outputLines.push(line) + } else if (copyEmptyLines && line.trim() === '') { + outputLines.push(line) + } + } + + // If no lines with the prompt were found then just use original lines + if (lineGotPrompt.some(v => v === true)) { + textContent = outputLines.join('\n'); + } + + // Remove a trailing newline to avoid auto-running when pasting + if (textContent.endsWith("\n")) { + textContent = textContent.slice(0, -1) + } + return textContent +} diff --git a/_static/css/main.css b/_static/css/main.css new file mode 100644 index 0000000000..4ac0174528 --- /dev/null +++ b/_static/css/main.css @@ -0,0 +1 @@ +@media print,screen and (min-width:40em){.reveal,.reveal.large,.reveal.small,.reveal.tiny{left:auto;margin:0 auto;right:auto}}/*! normalize.css v8.0.0 | MIT License | github.com/necolas/normalize.css */html{-webkit-text-size-adjust:100%;line-height:1.15}h1{font-size:2em;margin:.67em 0}hr{-webkit-box-sizing:content-box;box-sizing:content-box;overflow:visible}pre{font-family:monospace,monospace;font-size:1em}a{background-color:transparent}abbr[title]{border-bottom:0;-webkit-text-decoration:underline dotted;text-decoration:underline dotted}b,strong{font-weight:bolder}code,kbd,samp{font-family:monospace,monospace;font-size:1em}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}img{border-style:none}button,input,optgroup,select,textarea{font-size:100%;line-height:1.15;margin:0}button,input{overflow:visible}button,select{text-transform:none}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button}[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner,button::-moz-focus-inner{border-style:none;padding:0}[type=button]:-moz-focusring,[type=reset]:-moz-focusring,[type=submit]:-moz-focusring,button:-moz-focusring{outline:1px dotted ButtonText}fieldset{padding:.35em .75em .625em}legend{-webkit-box-sizing:border-box;box-sizing:border-box;color:inherit;display:table;padding:0;white-space:normal}progress{vertical-align:baseline}textarea{overflow:auto}[type=checkbox],[type=radio]{-webkit-box-sizing:border-box;box-sizing:border-box;padding:0}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}details{display:block}summary{display:list-item}template{display:none}[hidden]{display:none}[data-whatinput=mouse] *,[data-whatinput=mouse] :focus,[data-whatinput=touch] *,[data-whatinput=touch] :focus,[data-whatintent=mouse] *,[data-whatintent=mouse] :focus,[data-whatintent=touch] *,[data-whatintent=touch] :focus{outline:0}[draggable=false]{-webkit-touch-callout:none;-webkit-user-select:none}.foundation-mq{font-family:"small=0em&medium=40em&large=64em&xlarge=75em&xxlarge=90em"}html{-webkit-box-sizing:border-box;font-size:100%}*,:after,:before{-webkit-box-sizing:inherit}body{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;background:#fefefe;color:#0a0a0a;font-family:Helvetica Neue,Helvetica,Roboto,Arial,sans-serif;font-weight:400;line-height:1.5;margin:0;padding:0}img{-ms-interpolation-mode:bicubic;display:inline-block;height:auto;vertical-align:middle}textarea{border-radius:0;height:auto;min-height:50px}select{-webkit-box-sizing:border-box;box-sizing:border-box;width:100%}.map_canvas embed,.map_canvas img,.map_canvas object,.mqa-display embed,.mqa-display img,.mqa-display object{max-width:none!important}button{-webkit-appearance:none;-moz-appearance:none;appearance:none;background:0 0;border:0;border-radius:0;cursor:auto;line-height:1;padding:0}[data-whatinput=mouse] button{outline:0}pre{-webkit-overflow-scrolling:touch;overflow:auto}button,input,optgroup,select,textarea{font-family:inherit}.is-visible{display:block!important}.is-hidden{display:none!important}[type=color],[type=date],[type=datetime-local],[type=datetime],[type=email],[type=month],[type=number],[type=password],[type=search],[type=tel],[type=text],[type=time],[type=url],[type=week],textarea{-webkit-appearance:none;-moz-appearance:none;appearance:none;background-color:#fefefe;border:1px solid #cacaca;border-radius:0;-webkit-box-shadow:inset 0 1px 2px hsla(0,0%,4%,.1);box-shadow:inset 0 1px 2px hsla(0,0%,4%,.1);-webkit-box-sizing:border-box;box-sizing:border-box;color:#0a0a0a;display:block;font-family:inherit;font-size:1rem;font-weight:400;height:2.4375rem;line-height:1.5;margin:0 0 1rem;padding:.5rem;-webkit-transition:border-color .25s ease-in-out,-webkit-box-shadow .5s;transition:border-color .25s ease-in-out,-webkit-box-shadow .5s;transition:box-shadow .5s,border-color .25s ease-in-out;transition:box-shadow .5s,border-color .25s ease-in-out,-webkit-box-shadow .5s;width:100%}[type=color]:focus,[type=date]:focus,[type=datetime-local]:focus,[type=datetime]:focus,[type=email]:focus,[type=month]:focus,[type=number]:focus,[type=password]:focus,[type=search]:focus,[type=tel]:focus,[type=text]:focus,[type=time]:focus,[type=url]:focus,[type=week]:focus,textarea:focus{background-color:#fefefe;border:1px solid #8a8a8a;-webkit-box-shadow:0 0 5px #cacaca;box-shadow:0 0 5px #cacaca;outline:0;-webkit-transition:border-color .25s ease-in-out,-webkit-box-shadow .5s;transition:border-color .25s ease-in-out,-webkit-box-shadow .5s;transition:box-shadow .5s,border-color .25s ease-in-out;transition:box-shadow .5s,border-color .25s ease-in-out,-webkit-box-shadow .5s}textarea{max-width:100%}textarea[rows]{height:auto}input:disabled,input[readonly],textarea:disabled,textarea[readonly]{background-color:#e6e6e6;cursor:not-allowed}[type=button],[type=submit]{-webkit-appearance:none;-moz-appearance:none;appearance:none;border-radius:0}input[type=search]{-webkit-box-sizing:border-box;box-sizing:border-box}::-webkit-input-placeholder{color:#cacaca}::-moz-placeholder{color:#cacaca}:-ms-input-placeholder{color:#cacaca}::-ms-input-placeholder{color:#cacaca}::placeholder{color:#cacaca}[type=checkbox],[type=file],[type=radio]{margin:0 0 1rem}[type=checkbox]+label,[type=radio]+label{display:inline-block;margin-bottom:0;margin-left:.5rem;margin-right:1rem;vertical-align:baseline}[type=checkbox]+label[for],[type=radio]+label[for]{cursor:pointer}label>[type=checkbox],label>[type=radio]{margin-right:.5rem}[type=file]{width:100%}label{color:#0a0a0a;display:block;font-size:.875rem;font-weight:400;line-height:1.8;margin:0}label.middle{line-height:1.5;margin:0 0 1rem;padding:.5625rem 0}.help-text{color:#0a0a0a;font-size:.8125rem;font-style:italic;margin-top:-.5rem}.input-group{-webkit-box-align:stretch;-ms-flex-align:stretch;-webkit-align-items:stretch;align-items:stretch;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;margin-bottom:1rem;width:100%}.input-group>:first-child,.input-group>:first-child.input-group-button>*{border-radius:0}.input-group>:last-child,.input-group>:last-child.input-group-button>*{border-radius:0}.input-group-button,.input-group-button a,.input-group-button button,.input-group-button input,.input-group-button label,.input-group-field,.input-group-label{margin:0;white-space:nowrap}.input-group-label{-webkit-box-flex:0;-webkit-box-align:center;-ms-flex-align:center;-webkit-align-items:center;align-items:center;background:#e6e6e6;border:1px solid #cacaca;color:#0a0a0a;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto;padding:0 1rem;text-align:center;white-space:nowrap}.input-group-label:first-child{border-right:0}.input-group-label:last-child{border-left:0}.input-group-field{-webkit-box-flex:1;border-radius:0;-webkit-flex:1 1 0px;-ms-flex:1 1 0px;flex:1 1 0px;min-width:0}.input-group-button{-webkit-box-flex:0;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto;padding-bottom:0;padding-top:0;text-align:center}.input-group-button a,.input-group-button button,.input-group-button input,.input-group-button label{-ms-flex-item-align:stretch;-webkit-align-self:stretch;align-self:stretch;font-size:1rem;height:auto;padding-bottom:0;padding-top:0}fieldset{border:0;margin:0;padding:0}legend{margin-bottom:.5rem;max-width:100%}.fieldset{border:1px solid #cacaca;margin:1.125rem 0;padding:1.25rem}.fieldset legend{margin:0 0 0 -.1875rem;padding:0 .1875rem}select{-webkit-appearance:none;-moz-appearance:none;appearance:none;background-color:#fefefe;background-image:url('data:image/svg+xml;utf8,');background-origin:content-box;background-position:right -1rem center;background-repeat:no-repeat;background-size:9px 6px;border:1px solid #cacaca;border-radius:0;color:#0a0a0a;font-family:inherit;font-size:1rem;font-weight:400;height:2.4375rem;line-height:1.5;margin:0 0 1rem;padding:.5rem 1.5rem .5rem .5rem;-webkit-transition:border-color .25s ease-in-out,-webkit-box-shadow .5s;transition:border-color .25s ease-in-out,-webkit-box-shadow .5s;transition:box-shadow .5s,border-color .25s ease-in-out;transition:box-shadow .5s,border-color .25s ease-in-out,-webkit-box-shadow .5s}@media screen and (min-width:0\0){select{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAYCAYAAACbU/80AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAIpJREFUeNrEkckNgDAMBBfRkEt0ObRBBdsGXUDgmQfK4XhH2m8czQAAy27R3tsw4Qfe2x8uOO6oYLb6GlOor3GF+swURAOmUJ+RwtEJs9WvTGEYxBXqI1MQAZhCfUQKRzDMVj+TwrAIV6jvSUEkYAr1LSkcyTBb/V+KYfX7xAeusq3sLDtGH3kEGACPWIflNZfhRQAAAABJRU5ErkJggg==)}}select:focus{background-color:#fefefe;border:1px solid #8a8a8a;-webkit-box-shadow:0 0 5px #cacaca;box-shadow:0 0 5px #cacaca;outline:0;-webkit-transition:border-color .25s ease-in-out,-webkit-box-shadow .5s;transition:border-color .25s ease-in-out,-webkit-box-shadow .5s;transition:box-shadow .5s,border-color .25s ease-in-out;transition:box-shadow .5s,border-color .25s ease-in-out,-webkit-box-shadow .5s}select:disabled{background-color:#e6e6e6;cursor:not-allowed}select::-ms-expand{display:none}select[multiple]{background-image:none;height:auto}select:not([multiple]){padding-bottom:0;padding-top:0}.is-invalid-input:not(:focus){background-color:#f9ecea;border-color:#cc4b37}.is-invalid-input:not(:focus)::-webkit-input-placeholder{color:#cc4b37}.is-invalid-input:not(:focus)::-moz-placeholder{color:#cc4b37}.is-invalid-input:not(:focus):-ms-input-placeholder{color:#cc4b37}.is-invalid-input:not(:focus)::-ms-input-placeholder{color:#cc4b37}.is-invalid-input:not(:focus)::placeholder{color:#cc4b37}.form-error,.is-invalid-label{color:#cc4b37}.form-error{display:none;font-size:.75rem;font-weight:700;margin-bottom:1rem;margin-top:-.5rem}.form-error.is-visible{display:block}blockquote,dd,div,dl,dt,form,h1,h2,h3,h4,h5,h6,li,ol,p,pre,td,th,ul{margin:0;padding:0}p{text-rendering:optimizeLegibility;font-size:inherit;line-height:1.6;margin-bottom:1rem}em,i{font-style:italic}b,em,i,strong{line-height:inherit}b,strong{font-weight:700}small{font-size:80%;line-height:inherit}.h1,.h2,.h3,.h4,.h5,.h6,h1,h2,h3,h4,h5,h6{text-rendering:optimizeLegibility;color:inherit;font-family:Helvetica Neue,Helvetica,Roboto,Arial,sans-serif;font-style:normal;font-weight:400}.h1 small,.h2 small,.h3 small,.h4 small,.h5 small,.h6 small,h1 small,h2 small,h3 small,h4 small,h5 small,h6 small{color:#cacaca;line-height:0}.h1,h1{font-size:1.5rem}.h1,.h2,h1,h2{line-height:1.4;margin-bottom:.5rem;margin-top:0}.h2,h2{font-size:1.25rem}.h3,h3{font-size:1.1875rem}.h3,.h4,h3,h4{line-height:1.4;margin-bottom:.5rem;margin-top:0}.h4,h4{font-size:1.125rem}.h5,h5{font-size:1.0625rem}.h5,.h6,h5,h6{line-height:1.4;margin-bottom:.5rem;margin-top:0}.h6,h6{font-size:1rem}@media print,screen and (min-width:40em){.h1,h1{font-size:3rem}.h2,h2{font-size:2.5rem}.h3,h3{font-size:1.9375rem}.h4,h4{font-size:1.5625rem}.h5,h5{font-size:1.25rem}.h6,h6{font-size:1rem}}a{color:#1779ba;cursor:pointer;line-height:inherit;text-decoration:none}a:focus,a:hover{color:#1468a0}a img,hr{border:0}hr{border-bottom:1px solid #cacaca;clear:both;height:0;margin:1.25rem auto;max-width:75rem}dl,ol,ul{line-height:1.6;list-style-position:outside;margin-bottom:1rem}li{font-size:inherit}ul{list-style-type:disc}ol,ul{margin-left:1.25rem}ol ol,ol ul,ul ol,ul ul{margin-bottom:0;margin-left:1.25rem}dl{margin-bottom:1rem}dl dt{font-weight:700;margin-bottom:.3rem}blockquote{border-left:1px solid #cacaca;margin:0 0 1rem;padding:.5625rem 1.25rem 0 1.1875rem}blockquote,blockquote p{color:#8a8a8a;line-height:1.6}abbr,abbr[title]{border-bottom:1px dotted #0a0a0a;cursor:help;text-decoration:none}figure,kbd{margin:0}kbd{background-color:#e6e6e6;color:#0a0a0a;font-family:Consolas,Liberation Mono,Courier,monospace;padding:.125rem .25rem 0}.subheader{color:#8a8a8a;font-weight:400;line-height:1.4;margin-bottom:.5rem;margin-top:.2rem}.lead{font-size:125%;line-height:1.6}.stat{font-size:2.5rem;line-height:1}p+.stat{margin-top:-1rem}ol.no-bullet,ul.no-bullet{list-style:none;margin-left:0}.cite-block,cite{color:#8a8a8a;display:block;font-size:.8125rem}.cite-block:before,cite:before{content:"— "}.code-inline,code{word-wrap:break-word;display:inline;max-width:100%;padding:.125rem .3125rem .0625rem}.code-block,.code-inline,code{background-color:#e6e6e6;border:1px solid #cacaca;color:#0a0a0a;font-family:Consolas,Liberation Mono,Courier,monospace;font-weight:400}.code-block{display:block;margin-bottom:1.5rem;overflow:auto;padding:1rem;white-space:pre}.text-left{text-align:left}.text-right{text-align:right}.text-center{text-align:center}.text-justify{text-align:justify}@media print,screen and (min-width:40em){.medium-text-left{text-align:left}.medium-text-right{text-align:right}.medium-text-center{text-align:center}.medium-text-justify{text-align:justify}}@media print,screen and (min-width:64em){.large-text-left{text-align:left}.large-text-right{text-align:right}.large-text-center{text-align:center}.large-text-justify{text-align:justify}}.show-for-print{display:none!important}@media print{*{-webkit-print-color-adjust:economy;background:0 0!important;-webkit-box-shadow:none!important;box-shadow:none!important;color:#000!important;color-adjust:economy;text-shadow:none!important}.show-for-print{display:block!important}.hide-for-print{display:none!important}table.show-for-print{display:table!important}thead.show-for-print{display:table-header-group!important}tbody.show-for-print{display:table-row-group!important}tr.show-for-print{display:table-row!important}td.show-for-print,th.show-for-print{display:table-cell!important}a,a:visited{text-decoration:underline}a[href]:after{content:" (" attr(href) ")"}.ir a:after,a[href^="#"]:after,a[href^="javascript:"]:after{content:""}abbr[title]:after{content:" (" attr(title) ")"}blockquote,pre{border:1px solid #8a8a8a;page-break-inside:avoid}thead{display:table-header-group}img,tr{page-break-inside:avoid}img{max-width:100%!important}@page{margin:.5cm}h2,h3,p{orphans:3;widows:3}h2,h3{page-break-after:avoid}.print-break-inside{page-break-inside:auto}}.grid-container{margin-left:auto;margin-right:auto;max-width:75rem;padding-left:.625rem;padding-right:.625rem}@media print,screen and (min-width:40em){.grid-container{padding-left:.9375rem;padding-right:.9375rem}}.grid-container.fluid{margin-left:auto;margin-right:auto;max-width:100%;padding-left:.625rem;padding-right:.625rem}@media print,screen and (min-width:40em){.grid-container.fluid{padding-left:.9375rem;padding-right:.9375rem}}.grid-container.full{margin-left:auto;margin-right:auto;max-width:100%;padding-left:0;padding-right:0}.grid-x{-webkit-box-orient:horizontal;-webkit-box-direction:normal;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-flow:row wrap;-ms-flex-flow:row wrap;flex-flow:row wrap}.cell{-webkit-box-flex:0;-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto;min-height:0;min-width:0;width:100%}.cell.auto{-webkit-box-flex:1;-webkit-flex:1 1 0;-ms-flex:1 1 0px;flex:1 1 0}.cell.shrink{-webkit-box-flex:0;-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto}.grid-x>.auto{width:auto}.grid-x>.shrink{width:auto}.grid-x>.small-1,.grid-x>.small-2,.grid-x>.small-3,.grid-x>.small-4,.grid-x>.small-5,.grid-x>.small-6,.grid-x>.small-7,.grid-x>.small-8,.grid-x>.small-9,.grid-x>.small-10,.grid-x>.small-11,.grid-x>.small-12,.grid-x>.small-full,.grid-x>.small-shrink{-ms-flex-preferred-size:auto;-webkit-flex-basis:auto;flex-basis:auto}@media print,screen and (min-width:40em){.grid-x>.medium-1,.grid-x>.medium-2,.grid-x>.medium-3,.grid-x>.medium-4,.grid-x>.medium-5,.grid-x>.medium-6,.grid-x>.medium-7,.grid-x>.medium-8,.grid-x>.medium-9,.grid-x>.medium-10,.grid-x>.medium-11,.grid-x>.medium-12,.grid-x>.medium-full,.grid-x>.medium-shrink{-ms-flex-preferred-size:auto;-webkit-flex-basis:auto;flex-basis:auto}}@media print,screen and (min-width:64em){.grid-x>.large-1,.grid-x>.large-2,.grid-x>.large-3,.grid-x>.large-4,.grid-x>.large-5,.grid-x>.large-6,.grid-x>.large-7,.grid-x>.large-8,.grid-x>.large-9,.grid-x>.large-10,.grid-x>.large-11,.grid-x>.large-12,.grid-x>.large-full,.grid-x>.large-shrink{-ms-flex-preferred-size:auto;-webkit-flex-basis:auto;flex-basis:auto}}.grid-x>.small-1,.grid-x>.small-2,.grid-x>.small-3,.grid-x>.small-4,.grid-x>.small-5,.grid-x>.small-6,.grid-x>.small-7,.grid-x>.small-8,.grid-x>.small-9,.grid-x>.small-10,.grid-x>.small-11,.grid-x>.small-12{-webkit-box-flex:0;-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto}.grid-x>.small-1{width:8.33333%}.grid-x>.small-2{width:16.66667%}.grid-x>.small-3{width:25%}.grid-x>.small-4{width:33.33333%}.grid-x>.small-5{width:41.66667%}.grid-x>.small-6{width:50%}.grid-x>.small-7{width:58.33333%}.grid-x>.small-8{width:66.66667%}.grid-x>.small-9{width:75%}.grid-x>.small-10{width:83.33333%}.grid-x>.small-11{width:91.66667%}.grid-x>.small-12{width:100%}@media print,screen and (min-width:40em){.grid-x>.medium-auto{-webkit-box-flex:1;-webkit-flex:1 1 0;-ms-flex:1 1 0px;flex:1 1 0;width:auto}.grid-x>.medium-1,.grid-x>.medium-2,.grid-x>.medium-3,.grid-x>.medium-4,.grid-x>.medium-5,.grid-x>.medium-6,.grid-x>.medium-7,.grid-x>.medium-8,.grid-x>.medium-9,.grid-x>.medium-10,.grid-x>.medium-11,.grid-x>.medium-12,.grid-x>.medium-shrink{-webkit-box-flex:0;-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto}.grid-x>.medium-shrink{width:auto}.grid-x>.medium-1{width:8.33333%}.grid-x>.medium-2{width:16.66667%}.grid-x>.medium-3{width:25%}.grid-x>.medium-4{width:33.33333%}.grid-x>.medium-5{width:41.66667%}.grid-x>.medium-6{width:50%}.grid-x>.medium-7{width:58.33333%}.grid-x>.medium-8{width:66.66667%}.grid-x>.medium-9{width:75%}.grid-x>.medium-10{width:83.33333%}.grid-x>.medium-11{width:91.66667%}.grid-x>.medium-12{width:100%}}@media print,screen and (min-width:64em){.grid-x>.large-auto{-webkit-box-flex:1;-webkit-flex:1 1 0;-ms-flex:1 1 0px;flex:1 1 0;width:auto}.grid-x>.large-1,.grid-x>.large-2,.grid-x>.large-3,.grid-x>.large-4,.grid-x>.large-5,.grid-x>.large-6,.grid-x>.large-7,.grid-x>.large-8,.grid-x>.large-9,.grid-x>.large-10,.grid-x>.large-11,.grid-x>.large-12,.grid-x>.large-shrink{-webkit-box-flex:0;-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto}.grid-x>.large-shrink{width:auto}.grid-x>.large-1{width:8.33333%}.grid-x>.large-2{width:16.66667%}.grid-x>.large-3{width:25%}.grid-x>.large-4{width:33.33333%}.grid-x>.large-5{width:41.66667%}.grid-x>.large-6{width:50%}.grid-x>.large-7{width:58.33333%}.grid-x>.large-8{width:66.66667%}.grid-x>.large-9{width:75%}.grid-x>.large-10{width:83.33333%}.grid-x>.large-11{width:91.66667%}.grid-x>.large-12{width:100%}}.grid-margin-x:not(.grid-x)>.cell{width:auto}.grid-margin-y:not(.grid-y)>.cell{height:auto}.grid-margin-x{margin-left:-.625rem;margin-right:-.625rem}@media print,screen and (min-width:40em){.grid-margin-x{margin-left:-.9375rem;margin-right:-.9375rem}}.grid-margin-x>.cell{margin-left:.625rem;margin-right:.625rem;width:calc(100% - 1.25rem)}@media print,screen and (min-width:40em){.grid-margin-x>.cell{margin-left:.9375rem;margin-right:.9375rem;width:calc(100% - 1.875rem)}}.grid-margin-x>.auto{width:auto}.grid-margin-x>.shrink{width:auto}.grid-margin-x>.small-1{width:calc(8.33333% - 1.25rem)}.grid-margin-x>.small-2{width:calc(16.66667% - 1.25rem)}.grid-margin-x>.small-3{width:calc(25% - 1.25rem)}.grid-margin-x>.small-4{width:calc(33.33333% - 1.25rem)}.grid-margin-x>.small-5{width:calc(41.66667% - 1.25rem)}.grid-margin-x>.small-6{width:calc(50% - 1.25rem)}.grid-margin-x>.small-7{width:calc(58.33333% - 1.25rem)}.grid-margin-x>.small-8{width:calc(66.66667% - 1.25rem)}.grid-margin-x>.small-9{width:calc(75% - 1.25rem)}.grid-margin-x>.small-10{width:calc(83.33333% - 1.25rem)}.grid-margin-x>.small-11{width:calc(91.66667% - 1.25rem)}.grid-margin-x>.small-12{width:calc(100% - 1.25rem)}@media print,screen and (min-width:40em){.grid-margin-x>.auto{width:auto}.grid-margin-x>.shrink{width:auto}.grid-margin-x>.small-1{width:calc(8.33333% - 1.875rem)}.grid-margin-x>.small-2{width:calc(16.66667% - 1.875rem)}.grid-margin-x>.small-3{width:calc(25% - 1.875rem)}.grid-margin-x>.small-4{width:calc(33.33333% - 1.875rem)}.grid-margin-x>.small-5{width:calc(41.66667% - 1.875rem)}.grid-margin-x>.small-6{width:calc(50% - 1.875rem)}.grid-margin-x>.small-7{width:calc(58.33333% - 1.875rem)}.grid-margin-x>.small-8{width:calc(66.66667% - 1.875rem)}.grid-margin-x>.small-9{width:calc(75% - 1.875rem)}.grid-margin-x>.small-10{width:calc(83.33333% - 1.875rem)}.grid-margin-x>.small-11{width:calc(91.66667% - 1.875rem)}.grid-margin-x>.small-12{width:calc(100% - 1.875rem)}.grid-margin-x>.medium-auto{width:auto}.grid-margin-x>.medium-shrink{width:auto}.grid-margin-x>.medium-1{width:calc(8.33333% - 1.875rem)}.grid-margin-x>.medium-2{width:calc(16.66667% - 1.875rem)}.grid-margin-x>.medium-3{width:calc(25% - 1.875rem)}.grid-margin-x>.medium-4{width:calc(33.33333% - 1.875rem)}.grid-margin-x>.medium-5{width:calc(41.66667% - 1.875rem)}.grid-margin-x>.medium-6{width:calc(50% - 1.875rem)}.grid-margin-x>.medium-7{width:calc(58.33333% - 1.875rem)}.grid-margin-x>.medium-8{width:calc(66.66667% - 1.875rem)}.grid-margin-x>.medium-9{width:calc(75% - 1.875rem)}.grid-margin-x>.medium-10{width:calc(83.33333% - 1.875rem)}.grid-margin-x>.medium-11{width:calc(91.66667% - 1.875rem)}.grid-margin-x>.medium-12{width:calc(100% - 1.875rem)}}@media print,screen and (min-width:64em){.grid-margin-x>.large-auto{width:auto}.grid-margin-x>.large-shrink{width:auto}.grid-margin-x>.large-1{width:calc(8.33333% - 1.875rem)}.grid-margin-x>.large-2{width:calc(16.66667% - 1.875rem)}.grid-margin-x>.large-3{width:calc(25% - 1.875rem)}.grid-margin-x>.large-4{width:calc(33.33333% - 1.875rem)}.grid-margin-x>.large-5{width:calc(41.66667% - 1.875rem)}.grid-margin-x>.large-6{width:calc(50% - 1.875rem)}.grid-margin-x>.large-7{width:calc(58.33333% - 1.875rem)}.grid-margin-x>.large-8{width:calc(66.66667% - 1.875rem)}.grid-margin-x>.large-9{width:calc(75% - 1.875rem)}.grid-margin-x>.large-10{width:calc(83.33333% - 1.875rem)}.grid-margin-x>.large-11{width:calc(91.66667% - 1.875rem)}.grid-margin-x>.large-12{width:calc(100% - 1.875rem)}}.grid-padding-x .grid-padding-x{margin-left:-.625rem;margin-right:-.625rem}@media print,screen and (min-width:40em){.grid-padding-x .grid-padding-x{margin-left:-.9375rem;margin-right:-.9375rem}}.grid-container:not(.full)>.grid-padding-x{margin-left:-.625rem;margin-right:-.625rem}@media print,screen and (min-width:40em){.grid-container:not(.full)>.grid-padding-x{margin-left:-.9375rem;margin-right:-.9375rem}}.grid-padding-x>.cell{padding-left:.625rem;padding-right:.625rem}@media print,screen and (min-width:40em){.grid-padding-x>.cell{padding-left:.9375rem;padding-right:.9375rem}}.small-up-1>.cell{width:100%}.small-up-2>.cell{width:50%}.small-up-3>.cell{width:33.33333%}.small-up-4>.cell{width:25%}.small-up-5>.cell{width:20%}.small-up-6>.cell{width:16.66667%}.small-up-7>.cell{width:14.28571%}.small-up-8>.cell{width:12.5%}@media print,screen and (min-width:40em){.medium-up-1>.cell{width:100%}.medium-up-2>.cell{width:50%}.medium-up-3>.cell{width:33.33333%}.medium-up-4>.cell{width:25%}.medium-up-5>.cell{width:20%}.medium-up-6>.cell{width:16.66667%}.medium-up-7>.cell{width:14.28571%}.medium-up-8>.cell{width:12.5%}}@media print,screen and (min-width:64em){.large-up-1>.cell{width:100%}.large-up-2>.cell{width:50%}.large-up-3>.cell{width:33.33333%}.large-up-4>.cell{width:25%}.large-up-5>.cell{width:20%}.large-up-6>.cell{width:16.66667%}.large-up-7>.cell{width:14.28571%}.large-up-8>.cell{width:12.5%}}.grid-margin-x.small-up-1>.cell{width:calc(100% - 1.25rem)}.grid-margin-x.small-up-2>.cell{width:calc(50% - 1.25rem)}.grid-margin-x.small-up-3>.cell{width:calc(33.33333% - 1.25rem)}.grid-margin-x.small-up-4>.cell{width:calc(25% - 1.25rem)}.grid-margin-x.small-up-5>.cell{width:calc(20% - 1.25rem)}.grid-margin-x.small-up-6>.cell{width:calc(16.66667% - 1.25rem)}.grid-margin-x.small-up-7>.cell{width:calc(14.28571% - 1.25rem)}.grid-margin-x.small-up-8>.cell{width:calc(12.5% - 1.25rem)}@media print,screen and (min-width:40em){.grid-margin-x.small-up-1>.cell{width:calc(100% - 1.875rem)}.grid-margin-x.small-up-2>.cell{width:calc(50% - 1.875rem)}.grid-margin-x.small-up-3>.cell{width:calc(33.33333% - 1.875rem)}.grid-margin-x.small-up-4>.cell{width:calc(25% - 1.875rem)}.grid-margin-x.small-up-5>.cell{width:calc(20% - 1.875rem)}.grid-margin-x.small-up-6>.cell{width:calc(16.66667% - 1.875rem)}.grid-margin-x.small-up-7>.cell{width:calc(14.28571% - 1.875rem)}.grid-margin-x.small-up-8>.cell{width:calc(12.5% - 1.875rem)}.grid-margin-x.medium-up-1>.cell{width:calc(100% - 1.875rem)}.grid-margin-x.medium-up-2>.cell{width:calc(50% - 1.875rem)}.grid-margin-x.medium-up-3>.cell{width:calc(33.33333% - 1.875rem)}.grid-margin-x.medium-up-4>.cell{width:calc(25% - 1.875rem)}.grid-margin-x.medium-up-5>.cell{width:calc(20% - 1.875rem)}.grid-margin-x.medium-up-6>.cell{width:calc(16.66667% - 1.875rem)}.grid-margin-x.medium-up-7>.cell{width:calc(14.28571% - 1.875rem)}.grid-margin-x.medium-up-8>.cell{width:calc(12.5% - 1.875rem)}}@media print,screen and (min-width:64em){.grid-margin-x.large-up-1>.cell{width:calc(100% - 1.875rem)}.grid-margin-x.large-up-2>.cell{width:calc(50% - 1.875rem)}.grid-margin-x.large-up-3>.cell{width:calc(33.33333% - 1.875rem)}.grid-margin-x.large-up-4>.cell{width:calc(25% - 1.875rem)}.grid-margin-x.large-up-5>.cell{width:calc(20% - 1.875rem)}.grid-margin-x.large-up-6>.cell{width:calc(16.66667% - 1.875rem)}.grid-margin-x.large-up-7>.cell{width:calc(14.28571% - 1.875rem)}.grid-margin-x.large-up-8>.cell{width:calc(12.5% - 1.875rem)}}.small-margin-collapse{margin-left:0;margin-right:0}.small-margin-collapse>.cell{margin-left:0;margin-right:0}.small-margin-collapse>.small-1{width:8.33333%}.small-margin-collapse>.small-2{width:16.66667%}.small-margin-collapse>.small-3{width:25%}.small-margin-collapse>.small-4{width:33.33333%}.small-margin-collapse>.small-5{width:41.66667%}.small-margin-collapse>.small-6{width:50%}.small-margin-collapse>.small-7{width:58.33333%}.small-margin-collapse>.small-8{width:66.66667%}.small-margin-collapse>.small-9{width:75%}.small-margin-collapse>.small-10{width:83.33333%}.small-margin-collapse>.small-11{width:91.66667%}.small-margin-collapse>.small-12{width:100%}@media print,screen and (min-width:40em){.small-margin-collapse>.medium-1{width:8.33333%}.small-margin-collapse>.medium-2{width:16.66667%}.small-margin-collapse>.medium-3{width:25%}.small-margin-collapse>.medium-4{width:33.33333%}.small-margin-collapse>.medium-5{width:41.66667%}.small-margin-collapse>.medium-6{width:50%}.small-margin-collapse>.medium-7{width:58.33333%}.small-margin-collapse>.medium-8{width:66.66667%}.small-margin-collapse>.medium-9{width:75%}.small-margin-collapse>.medium-10{width:83.33333%}.small-margin-collapse>.medium-11{width:91.66667%}.small-margin-collapse>.medium-12{width:100%}}@media print,screen and (min-width:64em){.small-margin-collapse>.large-1{width:8.33333%}.small-margin-collapse>.large-2{width:16.66667%}.small-margin-collapse>.large-3{width:25%}.small-margin-collapse>.large-4{width:33.33333%}.small-margin-collapse>.large-5{width:41.66667%}.small-margin-collapse>.large-6{width:50%}.small-margin-collapse>.large-7{width:58.33333%}.small-margin-collapse>.large-8{width:66.66667%}.small-margin-collapse>.large-9{width:75%}.small-margin-collapse>.large-10{width:83.33333%}.small-margin-collapse>.large-11{width:91.66667%}.small-margin-collapse>.large-12{width:100%}}.small-padding-collapse{margin-left:0;margin-right:0}.small-padding-collapse>.cell{padding-left:0;padding-right:0}@media print,screen and (min-width:40em){.medium-margin-collapse{margin-left:0;margin-right:0}.medium-margin-collapse>.cell{margin-left:0;margin-right:0}}@media print,screen and (min-width:40em){.medium-margin-collapse>.small-1{width:8.33333%}.medium-margin-collapse>.small-2{width:16.66667%}.medium-margin-collapse>.small-3{width:25%}.medium-margin-collapse>.small-4{width:33.33333%}.medium-margin-collapse>.small-5{width:41.66667%}.medium-margin-collapse>.small-6{width:50%}.medium-margin-collapse>.small-7{width:58.33333%}.medium-margin-collapse>.small-8{width:66.66667%}.medium-margin-collapse>.small-9{width:75%}.medium-margin-collapse>.small-10{width:83.33333%}.medium-margin-collapse>.small-11{width:91.66667%}.medium-margin-collapse>.small-12{width:100%}}@media print,screen and (min-width:40em){.medium-margin-collapse>.medium-1{width:8.33333%}.medium-margin-collapse>.medium-2{width:16.66667%}.medium-margin-collapse>.medium-3{width:25%}.medium-margin-collapse>.medium-4{width:33.33333%}.medium-margin-collapse>.medium-5{width:41.66667%}.medium-margin-collapse>.medium-6{width:50%}.medium-margin-collapse>.medium-7{width:58.33333%}.medium-margin-collapse>.medium-8{width:66.66667%}.medium-margin-collapse>.medium-9{width:75%}.medium-margin-collapse>.medium-10{width:83.33333%}.medium-margin-collapse>.medium-11{width:91.66667%}.medium-margin-collapse>.medium-12{width:100%}}@media print,screen and (min-width:64em){.medium-margin-collapse>.large-1{width:8.33333%}.medium-margin-collapse>.large-2{width:16.66667%}.medium-margin-collapse>.large-3{width:25%}.medium-margin-collapse>.large-4{width:33.33333%}.medium-margin-collapse>.large-5{width:41.66667%}.medium-margin-collapse>.large-6{width:50%}.medium-margin-collapse>.large-7{width:58.33333%}.medium-margin-collapse>.large-8{width:66.66667%}.medium-margin-collapse>.large-9{width:75%}.medium-margin-collapse>.large-10{width:83.33333%}.medium-margin-collapse>.large-11{width:91.66667%}.medium-margin-collapse>.large-12{width:100%}}@media print,screen and (min-width:40em){.medium-padding-collapse{margin-left:0;margin-right:0}.medium-padding-collapse>.cell{padding-left:0;padding-right:0}}@media print,screen and (min-width:64em){.large-margin-collapse{margin-left:0;margin-right:0}.large-margin-collapse>.cell{margin-left:0;margin-right:0}}@media print,screen and (min-width:64em){.large-margin-collapse>.small-1{width:8.33333%}.large-margin-collapse>.small-2{width:16.66667%}.large-margin-collapse>.small-3{width:25%}.large-margin-collapse>.small-4{width:33.33333%}.large-margin-collapse>.small-5{width:41.66667%}.large-margin-collapse>.small-6{width:50%}.large-margin-collapse>.small-7{width:58.33333%}.large-margin-collapse>.small-8{width:66.66667%}.large-margin-collapse>.small-9{width:75%}.large-margin-collapse>.small-10{width:83.33333%}.large-margin-collapse>.small-11{width:91.66667%}.large-margin-collapse>.small-12{width:100%}}@media print,screen and (min-width:64em){.large-margin-collapse>.medium-1{width:8.33333%}.large-margin-collapse>.medium-2{width:16.66667%}.large-margin-collapse>.medium-3{width:25%}.large-margin-collapse>.medium-4{width:33.33333%}.large-margin-collapse>.medium-5{width:41.66667%}.large-margin-collapse>.medium-6{width:50%}.large-margin-collapse>.medium-7{width:58.33333%}.large-margin-collapse>.medium-8{width:66.66667%}.large-margin-collapse>.medium-9{width:75%}.large-margin-collapse>.medium-10{width:83.33333%}.large-margin-collapse>.medium-11{width:91.66667%}.large-margin-collapse>.medium-12{width:100%}}@media print,screen and (min-width:64em){.large-margin-collapse>.large-1{width:8.33333%}.large-margin-collapse>.large-2{width:16.66667%}.large-margin-collapse>.large-3{width:25%}.large-margin-collapse>.large-4{width:33.33333%}.large-margin-collapse>.large-5{width:41.66667%}.large-margin-collapse>.large-6{width:50%}.large-margin-collapse>.large-7{width:58.33333%}.large-margin-collapse>.large-8{width:66.66667%}.large-margin-collapse>.large-9{width:75%}.large-margin-collapse>.large-10{width:83.33333%}.large-margin-collapse>.large-11{width:91.66667%}.large-margin-collapse>.large-12{width:100%}}@media print,screen and (min-width:64em){.large-padding-collapse{margin-left:0;margin-right:0}.large-padding-collapse>.cell{padding-left:0;padding-right:0}}.small-offset-0{margin-left:0}.grid-margin-x>.small-offset-0{margin-left:.625rem}.small-offset-1{margin-left:8.33333%}.grid-margin-x>.small-offset-1{margin-left:calc(8.33333% + .625rem)}.small-offset-2{margin-left:16.66667%}.grid-margin-x>.small-offset-2{margin-left:calc(16.66667% + .625rem)}.small-offset-3{margin-left:25%}.grid-margin-x>.small-offset-3{margin-left:calc(25% + .625rem)}.small-offset-4{margin-left:33.33333%}.grid-margin-x>.small-offset-4{margin-left:calc(33.33333% + .625rem)}.small-offset-5{margin-left:41.66667%}.grid-margin-x>.small-offset-5{margin-left:calc(41.66667% + .625rem)}.small-offset-6{margin-left:50%}.grid-margin-x>.small-offset-6{margin-left:calc(50% + .625rem)}.small-offset-7{margin-left:58.33333%}.grid-margin-x>.small-offset-7{margin-left:calc(58.33333% + .625rem)}.small-offset-8{margin-left:66.66667%}.grid-margin-x>.small-offset-8{margin-left:calc(66.66667% + .625rem)}.small-offset-9{margin-left:75%}.grid-margin-x>.small-offset-9{margin-left:calc(75% + .625rem)}.small-offset-10{margin-left:83.33333%}.grid-margin-x>.small-offset-10{margin-left:calc(83.33333% + .625rem)}.small-offset-11{margin-left:91.66667%}.grid-margin-x>.small-offset-11{margin-left:calc(91.66667% + .625rem)}@media print,screen and (min-width:40em){.medium-offset-0{margin-left:0}.grid-margin-x>.medium-offset-0{margin-left:.9375rem}.medium-offset-1{margin-left:8.33333%}.grid-margin-x>.medium-offset-1{margin-left:calc(8.33333% + .9375rem)}.medium-offset-2{margin-left:16.66667%}.grid-margin-x>.medium-offset-2{margin-left:calc(16.66667% + .9375rem)}.medium-offset-3{margin-left:25%}.grid-margin-x>.medium-offset-3{margin-left:calc(25% + .9375rem)}.medium-offset-4{margin-left:33.33333%}.grid-margin-x>.medium-offset-4{margin-left:calc(33.33333% + .9375rem)}.medium-offset-5{margin-left:41.66667%}.grid-margin-x>.medium-offset-5{margin-left:calc(41.66667% + .9375rem)}.medium-offset-6{margin-left:50%}.grid-margin-x>.medium-offset-6{margin-left:calc(50% + .9375rem)}.medium-offset-7{margin-left:58.33333%}.grid-margin-x>.medium-offset-7{margin-left:calc(58.33333% + .9375rem)}.medium-offset-8{margin-left:66.66667%}.grid-margin-x>.medium-offset-8{margin-left:calc(66.66667% + .9375rem)}.medium-offset-9{margin-left:75%}.grid-margin-x>.medium-offset-9{margin-left:calc(75% + .9375rem)}.medium-offset-10{margin-left:83.33333%}.grid-margin-x>.medium-offset-10{margin-left:calc(83.33333% + .9375rem)}.medium-offset-11{margin-left:91.66667%}.grid-margin-x>.medium-offset-11{margin-left:calc(91.66667% + .9375rem)}}@media print,screen and (min-width:64em){.large-offset-0{margin-left:0}.grid-margin-x>.large-offset-0{margin-left:.9375rem}.large-offset-1{margin-left:8.33333%}.grid-margin-x>.large-offset-1{margin-left:calc(8.33333% + .9375rem)}.large-offset-2{margin-left:16.66667%}.grid-margin-x>.large-offset-2{margin-left:calc(16.66667% + .9375rem)}.large-offset-3{margin-left:25%}.grid-margin-x>.large-offset-3{margin-left:calc(25% + .9375rem)}.large-offset-4{margin-left:33.33333%}.grid-margin-x>.large-offset-4{margin-left:calc(33.33333% + .9375rem)}.large-offset-5{margin-left:41.66667%}.grid-margin-x>.large-offset-5{margin-left:calc(41.66667% + .9375rem)}.large-offset-6{margin-left:50%}.grid-margin-x>.large-offset-6{margin-left:calc(50% + .9375rem)}.large-offset-7{margin-left:58.33333%}.grid-margin-x>.large-offset-7{margin-left:calc(58.33333% + .9375rem)}.large-offset-8{margin-left:66.66667%}.grid-margin-x>.large-offset-8{margin-left:calc(66.66667% + .9375rem)}.large-offset-9{margin-left:75%}.grid-margin-x>.large-offset-9{margin-left:calc(75% + .9375rem)}.large-offset-10{margin-left:83.33333%}.grid-margin-x>.large-offset-10{margin-left:calc(83.33333% + .9375rem)}.large-offset-11{margin-left:91.66667%}.grid-margin-x>.large-offset-11{margin-left:calc(91.66667% + .9375rem)}}.grid-y{-webkit-box-orient:vertical;-webkit-box-direction:normal;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-flow:column nowrap;-ms-flex-flow:column nowrap;flex-flow:column nowrap}.grid-y>.cell{height:auto;max-height:none}.grid-y>.auto{height:auto}.grid-y>.shrink{height:auto}.grid-y>.small-1,.grid-y>.small-2,.grid-y>.small-3,.grid-y>.small-4,.grid-y>.small-5,.grid-y>.small-6,.grid-y>.small-7,.grid-y>.small-8,.grid-y>.small-9,.grid-y>.small-10,.grid-y>.small-11,.grid-y>.small-12,.grid-y>.small-full,.grid-y>.small-shrink{-ms-flex-preferred-size:auto;-webkit-flex-basis:auto;flex-basis:auto}@media print,screen and (min-width:40em){.grid-y>.medium-1,.grid-y>.medium-2,.grid-y>.medium-3,.grid-y>.medium-4,.grid-y>.medium-5,.grid-y>.medium-6,.grid-y>.medium-7,.grid-y>.medium-8,.grid-y>.medium-9,.grid-y>.medium-10,.grid-y>.medium-11,.grid-y>.medium-12,.grid-y>.medium-full,.grid-y>.medium-shrink{-ms-flex-preferred-size:auto;-webkit-flex-basis:auto;flex-basis:auto}}@media print,screen and (min-width:64em){.grid-y>.large-1,.grid-y>.large-2,.grid-y>.large-3,.grid-y>.large-4,.grid-y>.large-5,.grid-y>.large-6,.grid-y>.large-7,.grid-y>.large-8,.grid-y>.large-9,.grid-y>.large-10,.grid-y>.large-11,.grid-y>.large-12,.grid-y>.large-full,.grid-y>.large-shrink{-ms-flex-preferred-size:auto;-webkit-flex-basis:auto;flex-basis:auto}}.grid-y>.small-1,.grid-y>.small-2,.grid-y>.small-3,.grid-y>.small-4,.grid-y>.small-5,.grid-y>.small-6,.grid-y>.small-7,.grid-y>.small-8,.grid-y>.small-9,.grid-y>.small-10,.grid-y>.small-11,.grid-y>.small-12{-webkit-box-flex:0;-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto}.grid-y>.small-1{height:8.33333%}.grid-y>.small-2{height:16.66667%}.grid-y>.small-3{height:25%}.grid-y>.small-4{height:33.33333%}.grid-y>.small-5{height:41.66667%}.grid-y>.small-6{height:50%}.grid-y>.small-7{height:58.33333%}.grid-y>.small-8{height:66.66667%}.grid-y>.small-9{height:75%}.grid-y>.small-10{height:83.33333%}.grid-y>.small-11{height:91.66667%}.grid-y>.small-12{height:100%}@media print,screen and (min-width:40em){.grid-y>.medium-auto{-webkit-box-flex:1;-webkit-flex:1 1 0;-ms-flex:1 1 0px;flex:1 1 0;height:auto}.grid-y>.medium-1,.grid-y>.medium-2,.grid-y>.medium-3,.grid-y>.medium-4,.grid-y>.medium-5,.grid-y>.medium-6,.grid-y>.medium-7,.grid-y>.medium-8,.grid-y>.medium-9,.grid-y>.medium-10,.grid-y>.medium-11,.grid-y>.medium-12,.grid-y>.medium-shrink{-webkit-box-flex:0;-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto}.grid-y>.medium-shrink{height:auto}.grid-y>.medium-1{height:8.33333%}.grid-y>.medium-2{height:16.66667%}.grid-y>.medium-3{height:25%}.grid-y>.medium-4{height:33.33333%}.grid-y>.medium-5{height:41.66667%}.grid-y>.medium-6{height:50%}.grid-y>.medium-7{height:58.33333%}.grid-y>.medium-8{height:66.66667%}.grid-y>.medium-9{height:75%}.grid-y>.medium-10{height:83.33333%}.grid-y>.medium-11{height:91.66667%}.grid-y>.medium-12{height:100%}}@media print,screen and (min-width:64em){.grid-y>.large-auto{-webkit-box-flex:1;-webkit-flex:1 1 0;-ms-flex:1 1 0px;flex:1 1 0;height:auto}.grid-y>.large-1,.grid-y>.large-2,.grid-y>.large-3,.grid-y>.large-4,.grid-y>.large-5,.grid-y>.large-6,.grid-y>.large-7,.grid-y>.large-8,.grid-y>.large-9,.grid-y>.large-10,.grid-y>.large-11,.grid-y>.large-12,.grid-y>.large-shrink{-webkit-box-flex:0;-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto}.grid-y>.large-shrink{height:auto}.grid-y>.large-1{height:8.33333%}.grid-y>.large-2{height:16.66667%}.grid-y>.large-3{height:25%}.grid-y>.large-4{height:33.33333%}.grid-y>.large-5{height:41.66667%}.grid-y>.large-6{height:50%}.grid-y>.large-7{height:58.33333%}.grid-y>.large-8{height:66.66667%}.grid-y>.large-9{height:75%}.grid-y>.large-10{height:83.33333%}.grid-y>.large-11{height:91.66667%}.grid-y>.large-12{height:100%}}.grid-padding-y .grid-padding-y{margin-bottom:-.625rem;margin-top:-.625rem}@media print,screen and (min-width:40em){.grid-padding-y .grid-padding-y{margin-bottom:-.9375rem;margin-top:-.9375rem}}.grid-padding-y>.cell{padding-bottom:.625rem;padding-top:.625rem}@media print,screen and (min-width:40em){.grid-padding-y>.cell{padding-bottom:.9375rem;padding-top:.9375rem}}.grid-frame{-webkit-box-align:stretch;-ms-flex-align:stretch;-webkit-align-items:stretch;align-items:stretch;-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap;overflow:hidden;position:relative;width:100vw}.cell .grid-frame{width:100%}.cell-block{max-width:100%;overflow-x:auto}.cell-block,.cell-block-y{-webkit-overflow-scrolling:touch;-ms-overflow-style:-ms-autohiding-scrollbar}.cell-block-y{max-height:100%;min-height:100%;overflow-y:auto}.cell-block-container{-webkit-box-orient:vertical;-webkit-box-direction:normal;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;max-height:100%}.cell-block-container>.grid-x{-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap;max-height:100%}@media print,screen and (min-width:40em){.medium-grid-frame{-webkit-box-align:stretch;-ms-flex-align:stretch;-webkit-align-items:stretch;align-items:stretch;-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap;overflow:hidden;position:relative;width:100vw}.cell .medium-grid-frame{width:100%}.medium-cell-block{-webkit-overflow-scrolling:touch;-ms-overflow-style:-ms-autohiding-scrollbar;max-width:100%;overflow-x:auto}.medium-cell-block-container{-webkit-box-orient:vertical;-webkit-box-direction:normal;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;max-height:100%}.medium-cell-block-container>.grid-x{-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap;max-height:100%}.medium-cell-block-y{-webkit-overflow-scrolling:touch;-ms-overflow-style:-ms-autohiding-scrollbar;max-height:100%;min-height:100%;overflow-y:auto}}@media print,screen and (min-width:64em){.large-grid-frame{-webkit-box-align:stretch;-ms-flex-align:stretch;-webkit-align-items:stretch;align-items:stretch;-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap;overflow:hidden;position:relative;width:100vw}.cell .large-grid-frame{width:100%}.large-cell-block{-webkit-overflow-scrolling:touch;-ms-overflow-style:-ms-autohiding-scrollbar;max-width:100%;overflow-x:auto}.large-cell-block-container{-webkit-box-orient:vertical;-webkit-box-direction:normal;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;max-height:100%}.large-cell-block-container>.grid-x{-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap;max-height:100%}.large-cell-block-y{-webkit-overflow-scrolling:touch;-ms-overflow-style:-ms-autohiding-scrollbar;max-height:100%;min-height:100%;overflow-y:auto}}.grid-y.grid-frame{-webkit-box-align:stretch;-ms-flex-align:stretch;-webkit-align-items:stretch;align-items:stretch;-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap;height:100vh;overflow:hidden;position:relative;width:auto}@media print,screen and (min-width:40em){.grid-y.medium-grid-frame{-webkit-box-align:stretch;-ms-flex-align:stretch;-webkit-align-items:stretch;align-items:stretch;-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap;height:100vh;overflow:hidden;position:relative;width:auto}}@media print,screen and (min-width:64em){.grid-y.large-grid-frame{-webkit-box-align:stretch;-ms-flex-align:stretch;-webkit-align-items:stretch;align-items:stretch;-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap;height:100vh;overflow:hidden;position:relative;width:auto}}.cell .grid-y.grid-frame{height:100%}@media print,screen and (min-width:40em){.cell .grid-y.medium-grid-frame{height:100%}}@media print,screen and (min-width:64em){.cell .grid-y.large-grid-frame{height:100%}}.grid-margin-y{margin-bottom:-.625rem;margin-top:-.625rem}@media print,screen and (min-width:40em){.grid-margin-y{margin-bottom:-.9375rem;margin-top:-.9375rem}}.grid-margin-y>.cell{height:calc(100% - 1.25rem);margin-bottom:.625rem;margin-top:.625rem}@media print,screen and (min-width:40em){.grid-margin-y>.cell{height:calc(100% - 1.875rem);margin-bottom:.9375rem;margin-top:.9375rem}}.grid-margin-y>.auto{height:auto}.grid-margin-y>.shrink{height:auto}.grid-margin-y>.small-1{height:calc(8.33333% - 1.25rem)}.grid-margin-y>.small-2{height:calc(16.66667% - 1.25rem)}.grid-margin-y>.small-3{height:calc(25% - 1.25rem)}.grid-margin-y>.small-4{height:calc(33.33333% - 1.25rem)}.grid-margin-y>.small-5{height:calc(41.66667% - 1.25rem)}.grid-margin-y>.small-6{height:calc(50% - 1.25rem)}.grid-margin-y>.small-7{height:calc(58.33333% - 1.25rem)}.grid-margin-y>.small-8{height:calc(66.66667% - 1.25rem)}.grid-margin-y>.small-9{height:calc(75% - 1.25rem)}.grid-margin-y>.small-10{height:calc(83.33333% - 1.25rem)}.grid-margin-y>.small-11{height:calc(91.66667% - 1.25rem)}.grid-margin-y>.small-12{height:calc(100% - 1.25rem)}@media print,screen and (min-width:40em){.grid-margin-y>.auto{height:auto}.grid-margin-y>.shrink{height:auto}.grid-margin-y>.small-1{height:calc(8.33333% - 1.875rem)}.grid-margin-y>.small-2{height:calc(16.66667% - 1.875rem)}.grid-margin-y>.small-3{height:calc(25% - 1.875rem)}.grid-margin-y>.small-4{height:calc(33.33333% - 1.875rem)}.grid-margin-y>.small-5{height:calc(41.66667% - 1.875rem)}.grid-margin-y>.small-6{height:calc(50% - 1.875rem)}.grid-margin-y>.small-7{height:calc(58.33333% - 1.875rem)}.grid-margin-y>.small-8{height:calc(66.66667% - 1.875rem)}.grid-margin-y>.small-9{height:calc(75% - 1.875rem)}.grid-margin-y>.small-10{height:calc(83.33333% - 1.875rem)}.grid-margin-y>.small-11{height:calc(91.66667% - 1.875rem)}.grid-margin-y>.small-12{height:calc(100% - 1.875rem)}.grid-margin-y>.medium-auto{height:auto}.grid-margin-y>.medium-shrink{height:auto}.grid-margin-y>.medium-1{height:calc(8.33333% - 1.875rem)}.grid-margin-y>.medium-2{height:calc(16.66667% - 1.875rem)}.grid-margin-y>.medium-3{height:calc(25% - 1.875rem)}.grid-margin-y>.medium-4{height:calc(33.33333% - 1.875rem)}.grid-margin-y>.medium-5{height:calc(41.66667% - 1.875rem)}.grid-margin-y>.medium-6{height:calc(50% - 1.875rem)}.grid-margin-y>.medium-7{height:calc(58.33333% - 1.875rem)}.grid-margin-y>.medium-8{height:calc(66.66667% - 1.875rem)}.grid-margin-y>.medium-9{height:calc(75% - 1.875rem)}.grid-margin-y>.medium-10{height:calc(83.33333% - 1.875rem)}.grid-margin-y>.medium-11{height:calc(91.66667% - 1.875rem)}.grid-margin-y>.medium-12{height:calc(100% - 1.875rem)}}@media print,screen and (min-width:64em){.grid-margin-y>.large-auto{height:auto}.grid-margin-y>.large-shrink{height:auto}.grid-margin-y>.large-1{height:calc(8.33333% - 1.875rem)}.grid-margin-y>.large-2{height:calc(16.66667% - 1.875rem)}.grid-margin-y>.large-3{height:calc(25% - 1.875rem)}.grid-margin-y>.large-4{height:calc(33.33333% - 1.875rem)}.grid-margin-y>.large-5{height:calc(41.66667% - 1.875rem)}.grid-margin-y>.large-6{height:calc(50% - 1.875rem)}.grid-margin-y>.large-7{height:calc(58.33333% - 1.875rem)}.grid-margin-y>.large-8{height:calc(66.66667% - 1.875rem)}.grid-margin-y>.large-9{height:calc(75% - 1.875rem)}.grid-margin-y>.large-10{height:calc(83.33333% - 1.875rem)}.grid-margin-y>.large-11{height:calc(91.66667% - 1.875rem)}.grid-margin-y>.large-12{height:calc(100% - 1.875rem)}}.grid-frame.grid-margin-y{height:calc(100vh + 1.25rem)}@media print,screen and (min-width:40em){.grid-frame.grid-margin-y{height:calc(100vh + 1.875rem)}}@media print,screen and (min-width:64em){.grid-frame.grid-margin-y{height:calc(100vh + 1.875rem)}}@media print,screen and (min-width:40em){.grid-margin-y.medium-grid-frame{height:calc(100vh + 1.875rem)}}@media print,screen and (min-width:64em){.grid-margin-y.large-grid-frame{height:calc(100vh + 1.875rem)}}.button{-webkit-appearance:none;border:1px solid transparent;border-radius:0;cursor:pointer;display:inline-block;font-family:inherit;font-size:.9rem;line-height:1;margin:0 0 1rem;padding:.85em 1em;text-align:center;-webkit-transition:background-color .25s ease-out,color .25s ease-out;transition:background-color .25s ease-out,color .25s ease-out;vertical-align:middle}[data-whatinput=mouse] .button{outline:0}.button.tiny{font-size:.6rem}.button.small{font-size:.75rem}.button.large{font-size:1.25rem}.button.expanded{display:block;margin-left:0;margin-right:0;width:100%}.button,.button.disabled,.button.disabled:focus,.button.disabled:hover,.button[disabled],.button[disabled]:focus,.button[disabled]:hover{background-color:#1779ba;color:#fefefe}.button:focus,.button:hover{background-color:#14679e;color:#fefefe}.button.primary,.button.primary.disabled,.button.primary.disabled:focus,.button.primary.disabled:hover,.button.primary[disabled],.button.primary[disabled]:focus,.button.primary[disabled]:hover{background-color:#1779ba;color:#fefefe}.button.primary:focus,.button.primary:hover{background-color:#126195;color:#fefefe}.button.secondary,.button.secondary.disabled,.button.secondary.disabled:focus,.button.secondary.disabled:hover,.button.secondary[disabled],.button.secondary[disabled]:focus,.button.secondary[disabled]:hover{background-color:#767676;color:#fefefe}.button.secondary:focus,.button.secondary:hover{background-color:#5e5e5e;color:#fefefe}.button.success,.button.success.disabled,.button.success.disabled:focus,.button.success.disabled:hover,.button.success[disabled],.button.success[disabled]:focus,.button.success[disabled]:hover{background-color:#3adb76;color:#0a0a0a}.button.success:focus,.button.success:hover{background-color:#22bb5b;color:#0a0a0a}.button.warning,.button.warning.disabled,.button.warning.disabled:focus,.button.warning.disabled:hover,.button.warning[disabled],.button.warning[disabled]:focus,.button.warning[disabled]:hover{background-color:#ffae00;color:#0a0a0a}.button.warning:focus,.button.warning:hover{background-color:#cc8b00;color:#0a0a0a}.button.alert,.button.alert.disabled,.button.alert.disabled:focus,.button.alert.disabled:hover,.button.alert[disabled],.button.alert[disabled]:focus,.button.alert[disabled]:hover{background-color:#cc4b37;color:#fefefe}.button.alert:focus,.button.alert:hover{background-color:#a53b2a;color:#fefefe}.button.hollow,.button.hollow.disabled,.button.hollow.disabled:focus,.button.hollow.disabled:hover,.button.hollow:focus,.button.hollow:hover,.button.hollow[disabled],.button.hollow[disabled]:focus,.button.hollow[disabled]:hover{background-color:transparent}.button.hollow,.button.hollow.disabled,.button.hollow.disabled:focus,.button.hollow.disabled:hover,.button.hollow[disabled],.button.hollow[disabled]:focus,.button.hollow[disabled]:hover{border:1px solid #1779ba;color:#1779ba}.button.hollow:focus,.button.hollow:hover{border-color:#0c3d5d;color:#0c3d5d}.button.hollow.primary,.button.hollow.primary.disabled,.button.hollow.primary.disabled:focus,.button.hollow.primary.disabled:hover,.button.hollow.primary[disabled],.button.hollow.primary[disabled]:focus,.button.hollow.primary[disabled]:hover{border:1px solid #1779ba;color:#1779ba}.button.hollow.primary:focus,.button.hollow.primary:hover{border-color:#0c3d5d;color:#0c3d5d}.button.hollow.secondary,.button.hollow.secondary.disabled,.button.hollow.secondary.disabled:focus,.button.hollow.secondary.disabled:hover,.button.hollow.secondary[disabled],.button.hollow.secondary[disabled]:focus,.button.hollow.secondary[disabled]:hover{border:1px solid #767676;color:#767676}.button.hollow.secondary:focus,.button.hollow.secondary:hover{border-color:#3b3b3b;color:#3b3b3b}.button.hollow.success,.button.hollow.success.disabled,.button.hollow.success.disabled:focus,.button.hollow.success.disabled:hover,.button.hollow.success[disabled],.button.hollow.success[disabled]:focus,.button.hollow.success[disabled]:hover{border:1px solid #3adb76;color:#3adb76}.button.hollow.success:focus,.button.hollow.success:hover{border-color:#157539;color:#157539}.button.hollow.warning,.button.hollow.warning.disabled,.button.hollow.warning.disabled:focus,.button.hollow.warning.disabled:hover,.button.hollow.warning[disabled],.button.hollow.warning[disabled]:focus,.button.hollow.warning[disabled]:hover{border:1px solid #ffae00;color:#ffae00}.button.hollow.warning:focus,.button.hollow.warning:hover{border-color:#805700;color:#805700}.button.hollow.alert,.button.hollow.alert.disabled,.button.hollow.alert.disabled:focus,.button.hollow.alert.disabled:hover,.button.hollow.alert[disabled],.button.hollow.alert[disabled]:focus,.button.hollow.alert[disabled]:hover{border:1px solid #cc4b37;color:#cc4b37}.button.hollow.alert:focus,.button.hollow.alert:hover{border-color:#67251a;color:#67251a}.button.clear,.button.clear.disabled,.button.clear.disabled:focus,.button.clear.disabled:hover,.button.clear:focus,.button.clear:hover,.button.clear[disabled],.button.clear[disabled]:focus,.button.clear[disabled]:hover{background-color:transparent;border-color:transparent}.button.clear,.button.clear.disabled,.button.clear.disabled:focus,.button.clear.disabled:hover,.button.clear[disabled],.button.clear[disabled]:focus,.button.clear[disabled]:hover{color:#1779ba}.button.clear:focus,.button.clear:hover{color:#0c3d5d}.button.clear.primary,.button.clear.primary.disabled,.button.clear.primary.disabled:focus,.button.clear.primary.disabled:hover,.button.clear.primary[disabled],.button.clear.primary[disabled]:focus,.button.clear.primary[disabled]:hover{color:#1779ba}.button.clear.primary:focus,.button.clear.primary:hover{color:#0c3d5d}.button.clear.secondary,.button.clear.secondary.disabled,.button.clear.secondary.disabled:focus,.button.clear.secondary.disabled:hover,.button.clear.secondary[disabled],.button.clear.secondary[disabled]:focus,.button.clear.secondary[disabled]:hover{color:#767676}.button.clear.secondary:focus,.button.clear.secondary:hover{color:#3b3b3b}.button.clear.success,.button.clear.success.disabled,.button.clear.success.disabled:focus,.button.clear.success.disabled:hover,.button.clear.success[disabled],.button.clear.success[disabled]:focus,.button.clear.success[disabled]:hover{color:#3adb76}.button.clear.success:focus,.button.clear.success:hover{color:#157539}.button.clear.warning,.button.clear.warning.disabled,.button.clear.warning.disabled:focus,.button.clear.warning.disabled:hover,.button.clear.warning[disabled],.button.clear.warning[disabled]:focus,.button.clear.warning[disabled]:hover{color:#ffae00}.button.clear.warning:focus,.button.clear.warning:hover{color:#805700}.button.clear.alert,.button.clear.alert.disabled,.button.clear.alert.disabled:focus,.button.clear.alert.disabled:hover,.button.clear.alert[disabled],.button.clear.alert[disabled]:focus,.button.clear.alert[disabled]:hover{color:#cc4b37}.button.clear.alert:focus,.button.clear.alert:hover{color:#67251a}.button.disabled,.button[disabled]{cursor:not-allowed;opacity:.25}.button.dropdown:after{border-color:#fefefe transparent transparent;border-style:solid;border-width:.4em .4em 0;content:"";display:block;display:inline-block;float:right;height:0;margin-left:1em;position:relative;top:.4em;width:0}.button.dropdown.clear:after,.button.dropdown.hollow:after{border-top-color:#1779ba}.button.dropdown.clear.primary:after,.button.dropdown.hollow.primary:after{border-top-color:#1779ba}.button.dropdown.clear.secondary:after,.button.dropdown.hollow.secondary:after{border-top-color:#767676}.button.dropdown.clear.success:after,.button.dropdown.hollow.success:after{border-top-color:#3adb76}.button.dropdown.clear.warning:after,.button.dropdown.hollow.warning:after{border-top-color:#ffae00}.button.dropdown.clear.alert:after,.button.dropdown.hollow.alert:after{border-top-color:#cc4b37}.button.arrow-only:after{float:none;margin-left:0;top:-.1em}a.button:focus,a.button:hover{text-decoration:none}.button-group{-webkit-box-align:stretch;-ms-flex-align:stretch;-webkit-box-flex:1;-ms-flex-positive:1;-webkit-align-items:stretch;align-items:stretch;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-grow:1;flex-grow:1;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;margin-bottom:1rem}.button-group:after,.button-group:before{-ms-flex-preferred-size:0;-webkit-box-ordinal-group:2;-ms-flex-order:1;content:" ";display:table;-webkit-flex-basis:0;flex-basis:0;-webkit-order:1;order:1}.button-group:after{clear:both}.button-group:after,.button-group:before{display:none}.button-group .button{-webkit-box-flex:0;-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto;font-size:.9rem;margin:0 1px 1px 0}.button-group .button:last-child{margin-right:0}.button-group.tiny .button{font-size:.6rem}.button-group.small .button{font-size:.75rem}.button-group.large .button{font-size:1.25rem}.button-group.expanded .button{-webkit-box-flex:1;-webkit-flex:1 1 0px;-ms-flex:1 1 0px;flex:1 1 0px}.button-group.primary .button,.button-group.primary .button.disabled,.button-group.primary .button.disabled:focus,.button-group.primary .button.disabled:hover,.button-group.primary .button[disabled],.button-group.primary .button[disabled]:focus,.button-group.primary .button[disabled]:hover{background-color:#1779ba;color:#fefefe}.button-group.primary .button:focus,.button-group.primary .button:hover{background-color:#126195;color:#fefefe}.button-group.secondary .button,.button-group.secondary .button.disabled,.button-group.secondary .button.disabled:focus,.button-group.secondary .button.disabled:hover,.button-group.secondary .button[disabled],.button-group.secondary .button[disabled]:focus,.button-group.secondary .button[disabled]:hover{background-color:#767676;color:#fefefe}.button-group.secondary .button:focus,.button-group.secondary .button:hover{background-color:#5e5e5e;color:#fefefe}.button-group.success .button,.button-group.success .button.disabled,.button-group.success .button.disabled:focus,.button-group.success .button.disabled:hover,.button-group.success .button[disabled],.button-group.success .button[disabled]:focus,.button-group.success .button[disabled]:hover{background-color:#3adb76;color:#0a0a0a}.button-group.success .button:focus,.button-group.success .button:hover{background-color:#22bb5b;color:#0a0a0a}.button-group.warning .button,.button-group.warning .button.disabled,.button-group.warning .button.disabled:focus,.button-group.warning .button.disabled:hover,.button-group.warning .button[disabled],.button-group.warning .button[disabled]:focus,.button-group.warning .button[disabled]:hover{background-color:#ffae00;color:#0a0a0a}.button-group.warning .button:focus,.button-group.warning .button:hover{background-color:#cc8b00;color:#0a0a0a}.button-group.alert .button,.button-group.alert .button.disabled,.button-group.alert .button.disabled:focus,.button-group.alert .button.disabled:hover,.button-group.alert .button[disabled],.button-group.alert .button[disabled]:focus,.button-group.alert .button[disabled]:hover{background-color:#cc4b37;color:#fefefe}.button-group.alert .button:focus,.button-group.alert .button:hover{background-color:#a53b2a;color:#fefefe}.button-group.hollow .button,.button-group.hollow .button.disabled,.button-group.hollow .button.disabled:focus,.button-group.hollow .button.disabled:hover,.button-group.hollow .button:focus,.button-group.hollow .button:hover,.button-group.hollow .button[disabled],.button-group.hollow .button[disabled]:focus,.button-group.hollow .button[disabled]:hover{background-color:transparent}.button-group.hollow .button,.button-group.hollow .button.disabled,.button-group.hollow .button.disabled:focus,.button-group.hollow .button.disabled:hover,.button-group.hollow .button[disabled],.button-group.hollow .button[disabled]:focus,.button-group.hollow .button[disabled]:hover{border:1px solid #1779ba;color:#1779ba}.button-group.hollow .button:focus,.button-group.hollow .button:hover{border-color:#0c3d5d;color:#0c3d5d}.button-group.hollow .button.primary,.button-group.hollow .button.primary.disabled,.button-group.hollow .button.primary.disabled:focus,.button-group.hollow .button.primary.disabled:hover,.button-group.hollow .button.primary[disabled],.button-group.hollow .button.primary[disabled]:focus,.button-group.hollow .button.primary[disabled]:hover,.button-group.hollow.primary .button,.button-group.hollow.primary .button.disabled,.button-group.hollow.primary .button.disabled:focus,.button-group.hollow.primary .button.disabled:hover,.button-group.hollow.primary .button[disabled],.button-group.hollow.primary .button[disabled]:focus,.button-group.hollow.primary .button[disabled]:hover{border:1px solid #1779ba;color:#1779ba}.button-group.hollow .button.primary:focus,.button-group.hollow .button.primary:hover,.button-group.hollow.primary .button:focus,.button-group.hollow.primary .button:hover{border-color:#0c3d5d;color:#0c3d5d}.button-group.hollow .button.secondary,.button-group.hollow .button.secondary.disabled,.button-group.hollow .button.secondary.disabled:focus,.button-group.hollow .button.secondary.disabled:hover,.button-group.hollow .button.secondary[disabled],.button-group.hollow .button.secondary[disabled]:focus,.button-group.hollow .button.secondary[disabled]:hover,.button-group.hollow.secondary .button,.button-group.hollow.secondary .button.disabled,.button-group.hollow.secondary .button.disabled:focus,.button-group.hollow.secondary .button.disabled:hover,.button-group.hollow.secondary .button[disabled],.button-group.hollow.secondary .button[disabled]:focus,.button-group.hollow.secondary .button[disabled]:hover{border:1px solid #767676;color:#767676}.button-group.hollow .button.secondary:focus,.button-group.hollow .button.secondary:hover,.button-group.hollow.secondary .button:focus,.button-group.hollow.secondary .button:hover{border-color:#3b3b3b;color:#3b3b3b}.button-group.hollow .button.success,.button-group.hollow .button.success.disabled,.button-group.hollow .button.success.disabled:focus,.button-group.hollow .button.success.disabled:hover,.button-group.hollow .button.success[disabled],.button-group.hollow .button.success[disabled]:focus,.button-group.hollow .button.success[disabled]:hover,.button-group.hollow.success .button,.button-group.hollow.success .button.disabled,.button-group.hollow.success .button.disabled:focus,.button-group.hollow.success .button.disabled:hover,.button-group.hollow.success .button[disabled],.button-group.hollow.success .button[disabled]:focus,.button-group.hollow.success .button[disabled]:hover{border:1px solid #3adb76;color:#3adb76}.button-group.hollow .button.success:focus,.button-group.hollow .button.success:hover,.button-group.hollow.success .button:focus,.button-group.hollow.success .button:hover{border-color:#157539;color:#157539}.button-group.hollow .button.warning,.button-group.hollow .button.warning.disabled,.button-group.hollow .button.warning.disabled:focus,.button-group.hollow .button.warning.disabled:hover,.button-group.hollow .button.warning[disabled],.button-group.hollow .button.warning[disabled]:focus,.button-group.hollow .button.warning[disabled]:hover,.button-group.hollow.warning .button,.button-group.hollow.warning .button.disabled,.button-group.hollow.warning .button.disabled:focus,.button-group.hollow.warning .button.disabled:hover,.button-group.hollow.warning .button[disabled],.button-group.hollow.warning .button[disabled]:focus,.button-group.hollow.warning .button[disabled]:hover{border:1px solid #ffae00;color:#ffae00}.button-group.hollow .button.warning:focus,.button-group.hollow .button.warning:hover,.button-group.hollow.warning .button:focus,.button-group.hollow.warning .button:hover{border-color:#805700;color:#805700}.button-group.hollow.alert .button,.button-group.hollow.alert .button.disabled,.button-group.hollow.alert .button.disabled:focus,.button-group.hollow.alert .button.disabled:hover,.button-group.hollow.alert .button[disabled],.button-group.hollow.alert .button[disabled]:focus,.button-group.hollow.alert .button[disabled]:hover,.button-group.hollow .button.alert,.button-group.hollow .button.alert.disabled,.button-group.hollow .button.alert.disabled:focus,.button-group.hollow .button.alert.disabled:hover,.button-group.hollow .button.alert[disabled],.button-group.hollow .button.alert[disabled]:focus,.button-group.hollow .button.alert[disabled]:hover{border:1px solid #cc4b37;color:#cc4b37}.button-group.hollow.alert .button:focus,.button-group.hollow.alert .button:hover,.button-group.hollow .button.alert:focus,.button-group.hollow .button.alert:hover{border-color:#67251a;color:#67251a}.button-group.clear .button,.button-group.clear .button.disabled,.button-group.clear .button.disabled:focus,.button-group.clear .button.disabled:hover,.button-group.clear .button:focus,.button-group.clear .button:hover,.button-group.clear .button[disabled],.button-group.clear .button[disabled]:focus,.button-group.clear .button[disabled]:hover{background-color:transparent;border-color:transparent}.button-group.clear .button,.button-group.clear .button.disabled,.button-group.clear .button.disabled:focus,.button-group.clear .button.disabled:hover,.button-group.clear .button[disabled],.button-group.clear .button[disabled]:focus,.button-group.clear .button[disabled]:hover{color:#1779ba}.button-group.clear .button:focus,.button-group.clear .button:hover{color:#0c3d5d}.button-group.clear .button.primary,.button-group.clear .button.primary.disabled,.button-group.clear .button.primary.disabled:focus,.button-group.clear .button.primary.disabled:hover,.button-group.clear .button.primary[disabled],.button-group.clear .button.primary[disabled]:focus,.button-group.clear .button.primary[disabled]:hover,.button-group.clear.primary .button,.button-group.clear.primary .button.disabled,.button-group.clear.primary .button.disabled:focus,.button-group.clear.primary .button.disabled:hover,.button-group.clear.primary .button[disabled],.button-group.clear.primary .button[disabled]:focus,.button-group.clear.primary .button[disabled]:hover{color:#1779ba}.button-group.clear .button.primary:focus,.button-group.clear .button.primary:hover,.button-group.clear.primary .button:focus,.button-group.clear.primary .button:hover{color:#0c3d5d}.button-group.clear .button.secondary,.button-group.clear .button.secondary.disabled,.button-group.clear .button.secondary.disabled:focus,.button-group.clear .button.secondary.disabled:hover,.button-group.clear .button.secondary[disabled],.button-group.clear .button.secondary[disabled]:focus,.button-group.clear .button.secondary[disabled]:hover,.button-group.clear.secondary .button,.button-group.clear.secondary .button.disabled,.button-group.clear.secondary .button.disabled:focus,.button-group.clear.secondary .button.disabled:hover,.button-group.clear.secondary .button[disabled],.button-group.clear.secondary .button[disabled]:focus,.button-group.clear.secondary .button[disabled]:hover{color:#767676}.button-group.clear .button.secondary:focus,.button-group.clear .button.secondary:hover,.button-group.clear.secondary .button:focus,.button-group.clear.secondary .button:hover{color:#3b3b3b}.button-group.clear .button.success,.button-group.clear .button.success.disabled,.button-group.clear .button.success.disabled:focus,.button-group.clear .button.success.disabled:hover,.button-group.clear .button.success[disabled],.button-group.clear .button.success[disabled]:focus,.button-group.clear .button.success[disabled]:hover,.button-group.clear.success .button,.button-group.clear.success .button.disabled,.button-group.clear.success .button.disabled:focus,.button-group.clear.success .button.disabled:hover,.button-group.clear.success .button[disabled],.button-group.clear.success .button[disabled]:focus,.button-group.clear.success .button[disabled]:hover{color:#3adb76}.button-group.clear .button.success:focus,.button-group.clear .button.success:hover,.button-group.clear.success .button:focus,.button-group.clear.success .button:hover{color:#157539}.button-group.clear .button.warning,.button-group.clear .button.warning.disabled,.button-group.clear .button.warning.disabled:focus,.button-group.clear .button.warning.disabled:hover,.button-group.clear .button.warning[disabled],.button-group.clear .button.warning[disabled]:focus,.button-group.clear .button.warning[disabled]:hover,.button-group.clear.warning .button,.button-group.clear.warning .button.disabled,.button-group.clear.warning .button.disabled:focus,.button-group.clear.warning .button.disabled:hover,.button-group.clear.warning .button[disabled],.button-group.clear.warning .button[disabled]:focus,.button-group.clear.warning .button[disabled]:hover{color:#ffae00}.button-group.clear .button.warning:focus,.button-group.clear .button.warning:hover,.button-group.clear.warning .button:focus,.button-group.clear.warning .button:hover{color:#805700}.button-group.clear.alert .button,.button-group.clear.alert .button.disabled,.button-group.clear.alert .button.disabled:focus,.button-group.clear.alert .button.disabled:hover,.button-group.clear.alert .button[disabled],.button-group.clear.alert .button[disabled]:focus,.button-group.clear.alert .button[disabled]:hover,.button-group.clear .button.alert,.button-group.clear .button.alert.disabled,.button-group.clear .button.alert.disabled:focus,.button-group.clear .button.alert.disabled:hover,.button-group.clear .button.alert[disabled],.button-group.clear .button.alert[disabled]:focus,.button-group.clear .button.alert[disabled]:hover{color:#cc4b37}.button-group.clear.alert .button:focus,.button-group.clear.alert .button:hover,.button-group.clear .button.alert:focus,.button-group.clear .button.alert:hover{color:#67251a}.button-group.no-gaps .button{margin-right:-.0625rem}.button-group.no-gaps .button+.button{border-left-color:transparent}.button-group.stacked,.button-group.stacked-for-medium,.button-group.stacked-for-small{-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap}.button-group.stacked-for-medium .button,.button-group.stacked-for-small .button,.button-group.stacked .button{-webkit-box-flex:0;-webkit-flex:0 0 100%;-ms-flex:0 0 100%;flex:0 0 100%}.button-group.stacked-for-medium .button:last-child,.button-group.stacked-for-small .button:last-child,.button-group.stacked .button:last-child{margin-bottom:0}.button-group.stacked-for-medium.expanded .button,.button-group.stacked-for-small.expanded .button,.button-group.stacked.expanded .button{-webkit-box-flex:1;-webkit-flex:1 1 0px;-ms-flex:1 1 0px;flex:1 1 0px}@media print,screen and (min-width:40em){.button-group.stacked-for-small .button{-webkit-box-flex:0;-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto;margin-bottom:0}}@media print,screen and (min-width:64em){.button-group.stacked-for-medium .button{-webkit-box-flex:0;-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto;margin-bottom:0}}@media print,screen and (max-width:39.99875em){.button-group.stacked-for-small.expanded{display:block}.button-group.stacked-for-small.expanded .button{display:block;margin-right:0}}@media print,screen and (max-width:63.99875em){.button-group.stacked-for-medium.expanded{display:block}.button-group.stacked-for-medium.expanded .button{display:block;margin-right:0}}.close-button{color:#8a8a8a;cursor:pointer;position:absolute;z-index:10}[data-whatinput=mouse] .close-button{outline:0}.close-button:focus,.close-button:hover{color:#0a0a0a}.close-button.small{font-size:1.5em;line-height:1;right:.66rem;top:.33em}.close-button,.close-button.medium{font-size:2em;line-height:1;right:1rem;top:.5rem}.label{border-radius:0;cursor:default;display:inline-block;font-size:.8rem;line-height:1;padding:.33333rem .5rem;white-space:nowrap}.label,.label.primary{background:#1779ba;color:#fefefe}.label.secondary{background:#767676;color:#fefefe}.label.success{background:#3adb76;color:#0a0a0a}.label.warning{background:#ffae00;color:#0a0a0a}.label.alert{background:#cc4b37;color:#fefefe}.progress{background-color:#cacaca;border-radius:0;height:1rem;margin-bottom:1rem}.progress.primary .progress-meter{background-color:#1779ba}.progress.secondary .progress-meter{background-color:#767676}.progress.success .progress-meter{background-color:#3adb76}.progress.warning .progress-meter{background-color:#ffae00}.progress.alert .progress-meter{background-color:#cc4b37}.progress-meter{background-color:#1779ba;display:block;height:100%;position:relative;width:0}.progress-meter-text{color:#fefefe;font-size:.75rem;font-weight:700;left:50%;margin:0;position:absolute;top:50%;-webkit-transform:translate(-50%,-50%);-ms-transform:translate(-50%,-50%);transform:translate(-50%,-50%);white-space:nowrap}.slider{background-color:#e6e6e6;cursor:pointer;height:.5rem;margin-bottom:2.25rem;margin-top:1.25rem;position:relative;-ms-touch-action:none;touch-action:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.slider-fill{background-color:#cacaca;display:inline-block;height:.5rem;left:0;max-width:100%;position:absolute;top:0;-webkit-transition:all .2s ease-in-out;transition:all .2s ease-in-out}.slider-fill.is-dragging{-webkit-transition:all 0s linear;transition:all 0s linear}.slider-handle{background-color:#1779ba;border-radius:0;cursor:-webkit-grab;cursor:grab;display:inline-block;height:1.4rem;left:0;position:absolute;top:50%;-ms-touch-action:manipulation;touch-action:manipulation;-webkit-transform:translateY(-50%);-ms-transform:translateY(-50%);transform:translateY(-50%);-webkit-transition:all .2s ease-in-out;transition:all .2s ease-in-out;width:1.4rem;z-index:1}[data-whatinput=mouse] .slider-handle{outline:0}.slider-handle:hover{background-color:#14679e}.slider-handle.is-dragging{cursor:-webkit-grabbing;cursor:grabbing;-webkit-transition:all 0s linear;transition:all 0s linear}.slider.disabled,.slider[disabled]{cursor:not-allowed;opacity:.25}.slider.vertical{display:inline-block;height:12.5rem;margin:0 1.25rem;-webkit-transform:scaleY(-1);-ms-transform:scaleY(-1);transform:scaleY(-1);width:.5rem}.slider.vertical .slider-fill{max-height:100%;top:0;width:.5rem}.slider.vertical .slider-handle{height:1.4rem;left:50%;position:absolute;top:0;-webkit-transform:translateX(-50%);-ms-transform:translateX(-50%);transform:translateX(-50%);width:1.4rem}.switch{color:#fefefe;font-size:.875rem;font-weight:700;height:2rem;margin-bottom:1rem;outline:0;position:relative;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.switch-input{margin-bottom:0;opacity:0;position:absolute}.switch-paddle{background:#cacaca;border-radius:0;color:inherit;cursor:pointer;display:block;font-weight:inherit;height:2rem;position:relative;-webkit-transition:all .25s ease-out;transition:all .25s ease-out;width:4rem}input+.switch-paddle{margin:0}.switch-paddle:after{background:#fefefe;border-radius:0;content:"";display:block;height:1.5rem;left:.25rem;position:absolute;top:.25rem;-webkit-transform:translateZ(0);transform:translateZ(0);-webkit-transition:all .25s ease-out;transition:all .25s ease-out;width:1.5rem}input:checked~.switch-paddle{background:#1779ba}input:checked~.switch-paddle:after{left:2.25rem}input:disabled~.switch-paddle{cursor:not-allowed;opacity:.5}[data-whatinput=mouse] input:focus~.switch-paddle{outline:0}.switch-active,.switch-inactive{position:absolute;top:50%;-webkit-transform:translateY(-50%);-ms-transform:translateY(-50%);transform:translateY(-50%)}.switch-active{display:none;left:8%}input:checked+label>.switch-active{display:block}.switch-inactive{right:15%}input:checked+label>.switch-inactive{display:none}.switch.tiny{height:1.5rem}.switch.tiny .switch-paddle{font-size:.625rem;height:1.5rem;width:3rem}.switch.tiny .switch-paddle:after{height:1rem;left:.25rem;top:.25rem;width:1rem}.switch.tiny input:checked~.switch-paddle:after{left:1.75rem}.switch.small{height:1.75rem}.switch.small .switch-paddle{font-size:.75rem;height:1.75rem;width:3.5rem}.switch.small .switch-paddle:after{height:1.25rem;left:.25rem;top:.25rem;width:1.25rem}.switch.small input:checked~.switch-paddle:after{left:2rem}.switch.large{height:2.5rem}.switch.large .switch-paddle{font-size:1rem;height:2.5rem;width:5rem}.switch.large .switch-paddle:after{height:2rem;left:.25rem;top:.25rem;width:2rem}.switch.large input:checked~.switch-paddle:after{left:2.75rem}table{border-collapse:collapse;border-radius:0;margin-bottom:1rem;width:100%}tbody,tfoot,thead{background-color:#fefefe;border:1px solid #f1f1f1}caption{font-weight:700;padding:.5rem .625rem .625rem}thead{background:#f8f8f8}tfoot,thead{color:#0a0a0a}tfoot{background:#f1f1f1}tfoot tr,thead tr{background:0 0}tfoot td,tfoot th,thead td,thead th{font-weight:700;padding:.5rem .625rem .625rem;text-align:left}tbody td,tbody th{padding:.5rem .625rem .625rem}tbody tr:nth-child(2n){background-color:#f1f1f1;border-bottom:0}table.unstriped tbody{background-color:#fefefe}table.unstriped tbody tr{background-color:#fefefe;border-bottom:1px solid #f1f1f1}@media print,screen and (max-width:63.99875em){table.stack tfoot,table.stack thead{display:none}table.stack td,table.stack th,table.stack tr{display:block}table.stack td{border-top:0}}table.scroll{display:block;overflow-x:auto;width:100%}table.hover thead tr:hover{background-color:#f3f3f3}table.hover tfoot tr:hover{background-color:#ececec}table.hover tbody tr:hover{background-color:#f9f9f9}table.hover:not(.unstriped) tr:nth-of-type(2n):hover{background-color:#ececec}.table-scroll{overflow-x:auto}.badge{border-radius:50%;display:inline-block;font-size:.6rem;min-width:2.1em;padding:.3em;text-align:center}.badge,.badge.primary{background:#1779ba;color:#fefefe}.badge.secondary{background:#767676;color:#fefefe}.badge.success{background:#3adb76;color:#0a0a0a}.badge.warning{background:#ffae00;color:#0a0a0a}.badge.alert{background:#cc4b37;color:#fefefe}.breadcrumbs{list-style:none;margin:0 0 1rem}.breadcrumbs:after,.breadcrumbs:before{-ms-flex-preferred-size:0;-webkit-box-ordinal-group:2;-ms-flex-order:1;content:" ";display:table;-webkit-flex-basis:0;flex-basis:0;-webkit-order:1;order:1}.breadcrumbs:after{clear:both}.breadcrumbs li{color:#0a0a0a;cursor:default;float:left;font-size:.6875rem;text-transform:uppercase}.breadcrumbs li:not(:last-child):after{color:#cacaca;content:"/";margin:0 .75rem;opacity:1;position:relative}.breadcrumbs a{color:#1779ba}.breadcrumbs a:hover{text-decoration:underline}.breadcrumbs .disabled{color:#cacaca;cursor:not-allowed}.callout{background-color:#fff;border:1px solid hsla(0,0%,4%,.25);border-radius:0;color:#0a0a0a;margin:0 0 1rem;padding:1rem;position:relative}.callout>:first-child{margin-top:0}.callout>:last-child{margin-bottom:0}.callout.primary{background-color:#d7ecfa;color:#0a0a0a}.callout.secondary{background-color:#eaeaea;color:#0a0a0a}.callout.success{background-color:#e1faea;color:#0a0a0a}.callout.warning{background-color:#fff3d9;color:#0a0a0a}.callout.alert{background-color:#f7e4e1;color:#0a0a0a}.callout.small{padding:.5rem}.callout.large{padding:3rem}.card{-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-box-flex:1;-ms-flex-positive:1;background:#fefefe;border:1px solid #e6e6e6;border-radius:0;-webkit-box-shadow:none;box-shadow:none;color:#0a0a0a;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;-webkit-flex-grow:1;flex-grow:1;margin-bottom:1rem;overflow:hidden}.card>:last-child{margin-bottom:0}.card-divider{-webkit-box-flex:0;background:#e6e6e6;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex:0 1 auto;-ms-flex:0 1 auto;flex:0 1 auto;padding:1rem}.card-divider>:last-child{margin-bottom:0}.card-section{-webkit-box-flex:1;-webkit-flex:1 0 auto;-ms-flex:1 0 auto;flex:1 0 auto;padding:1rem}.card-section>:last-child{margin-bottom:0}.card-image{min-height:1px}.dropdown-pane{background-color:#fefefe;border:1px solid #cacaca;border-radius:0;display:none;font-size:1rem;padding:1rem;position:absolute;visibility:hidden;width:300px;z-index:10}.dropdown-pane.is-opening{display:block}.dropdown-pane.is-open{display:block;visibility:visible}.dropdown-pane.tiny{width:100px}.dropdown-pane.small{width:200px}.dropdown-pane.large{width:400px}.pagination{margin-bottom:1rem;margin-left:0}.pagination:after,.pagination:before{-ms-flex-preferred-size:0;-webkit-box-ordinal-group:2;-ms-flex-order:1;content:" ";display:table;-webkit-flex-basis:0;flex-basis:0;-webkit-order:1;order:1}.pagination:after{clear:both}.pagination li{border-radius:0;display:none;font-size:.875rem;margin-right:.0625rem}.pagination li:first-child,.pagination li:last-child{display:inline-block}@media print,screen and (min-width:40em){.pagination li{display:inline-block}}.pagination a,.pagination button{border-radius:0;color:#0a0a0a;display:block;padding:.1875rem .625rem}.pagination a:hover,.pagination button:hover{background:#e6e6e6}.pagination .current{background:#1779ba;color:#fefefe;cursor:default;padding:.1875rem .625rem}.pagination .disabled{color:#cacaca;cursor:not-allowed;padding:.1875rem .625rem}.pagination .disabled:hover{background:0 0}.pagination .ellipsis:after{color:#0a0a0a;content:"…";padding:.1875rem .625rem}.pagination-previous.disabled:before,.pagination-previous a:before{content:"«";display:inline-block;margin-right:.5rem}.pagination-next.disabled:after,.pagination-next a:after{content:"»";display:inline-block;margin-left:.5rem}.has-tip{border-bottom:1px dotted #8a8a8a;cursor:help;display:inline-block;font-weight:700;position:relative}.tooltip{background-color:#0a0a0a;border-radius:0;color:#fefefe;font-size:80%;max-width:10rem;padding:.75rem;position:absolute;top:calc(100% + .6495rem);z-index:1200}.tooltip:before{position:absolute}.tooltip.bottom:before{border-color:transparent transparent #0a0a0a;border-style:solid;border-width:0 .75rem .75rem;bottom:100%;content:"";display:block;height:0;width:0}.tooltip.bottom.align-center:before{left:50%;-webkit-transform:translateX(-50%);-ms-transform:translateX(-50%);transform:translateX(-50%)}.tooltip.top:before{border-color:#0a0a0a transparent transparent;border-style:solid;border-width:.75rem .75rem 0;bottom:auto;content:"";display:block;height:0;top:100%;width:0}.tooltip.top.align-center:before{left:50%;-webkit-transform:translateX(-50%);-ms-transform:translateX(-50%);transform:translateX(-50%)}.tooltip.left:before{border-color:transparent transparent transparent #0a0a0a;border-style:solid;border-width:.75rem 0 .75rem .75rem;content:"";display:block;height:0;left:100%;width:0}.tooltip.left.align-center:before{bottom:auto;top:50%;-webkit-transform:translateY(-50%);-ms-transform:translateY(-50%);transform:translateY(-50%)}.tooltip.right:before{border-color:transparent #0a0a0a transparent transparent;border-style:solid;border-width:.75rem .75rem .75rem 0;content:"";display:block;height:0;left:auto;right:100%;width:0}.tooltip.right.align-center:before{bottom:auto;top:50%;-webkit-transform:translateY(-50%);-ms-transform:translateY(-50%);transform:translateY(-50%)}.tooltip.align-top:before{bottom:auto;top:10%}.tooltip.align-bottom:before{bottom:10%;top:auto}.tooltip.align-left:before{left:10%;right:auto}.tooltip.align-right:before{left:auto;right:10%}.accordion{background:#fefefe;list-style-type:none;margin-left:0}.accordion[disabled] .accordion-title{cursor:not-allowed}.accordion-item:first-child>:first-child{border-radius:0}.accordion-item:last-child>:last-child{border-radius:0}.accordion-title{border:1px solid #e6e6e6;border-bottom:0;color:#1779ba;display:block;font-size:.75rem;line-height:1;padding:1.25rem 1rem;position:relative}:last-child:not(.is-active)>.accordion-title{border-bottom:1px solid #e6e6e6;border-radius:0}.accordion-title:focus,.accordion-title:hover{background-color:#e6e6e6}.accordion-title:before{content:"+";margin-top:-.5rem;position:absolute;right:1rem;top:50%}.is-active>.accordion-title:before{content:"–"}.accordion-content{background-color:#fefefe;border:1px solid #e6e6e6;border-bottom:0;color:#0a0a0a;display:none;padding:1rem}:last-child>.accordion-content:last-child{border-bottom:1px solid #e6e6e6}.media-object{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap;margin-bottom:1rem}.media-object img{max-width:none}@media print,screen and (max-width:39.99875em){.media-object.stack-for-small{-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap}}.media-object-section{-webkit-box-flex:0;-webkit-flex:0 1 auto;-ms-flex:0 1 auto;flex:0 1 auto}.media-object-section:first-child{padding-right:1rem}.media-object-section:last-child:not(:nth-child(2)){padding-left:1rem}.media-object-section>:last-child{margin-bottom:0}@media print,screen and (max-width:39.99875em){.stack-for-small .media-object-section{-ms-flex-preferred-size:100%;-webkit-flex-basis:100%;flex-basis:100%;max-width:100%;padding:0 0 1rem}.stack-for-small .media-object-section img{width:100%}}.media-object-section.main-section{-webkit-box-flex:1;-webkit-flex:1 1 0px;-ms-flex:1 1 0px;flex:1 1 0px}.orbit,.orbit-container{position:relative}.orbit-container{height:0;list-style:none;margin:0;overflow:hidden}.orbit-slide{position:absolute;width:100%}.orbit-slide.no-motionui.is-active{left:0;top:0}.orbit-figure{margin:0}.orbit-image{margin:0;max-width:100%;width:100%}.orbit-caption{background-color:hsla(0,0%,4%,.5);bottom:0;margin-bottom:0;width:100%}.orbit-caption,.orbit-next,.orbit-previous{color:#fefefe;padding:1rem;position:absolute}.orbit-next,.orbit-previous{top:50%;-webkit-transform:translateY(-50%);-ms-transform:translateY(-50%);transform:translateY(-50%);z-index:10}[data-whatinput=mouse] .orbit-next,[data-whatinput=mouse] .orbit-previous{outline:0}.orbit-next:active,.orbit-next:focus,.orbit-next:hover,.orbit-previous:active,.orbit-previous:focus,.orbit-previous:hover{background-color:hsla(0,0%,4%,.5)}.orbit-previous{left:0}.orbit-next{left:auto;right:0}.orbit-bullets{margin-bottom:.8rem;margin-top:.8rem;position:relative;text-align:center}[data-whatinput=mouse] .orbit-bullets{outline:0}.orbit-bullets button{background-color:#cacaca;border-radius:50%;height:1.2rem;margin:.1rem;width:1.2rem}.orbit-bullets button:hover{background-color:#8a8a8a}.orbit-bullets button.is-active{background-color:#8a8a8a}.flex-video,.responsive-embed{height:0;margin-bottom:1rem;overflow:hidden;padding-bottom:75%;position:relative}.flex-video embed,.flex-video iframe,.flex-video object,.flex-video video,.responsive-embed embed,.responsive-embed iframe,.responsive-embed object,.responsive-embed video{height:100%;left:0;position:absolute;top:0;width:100%}.flex-video.widescreen,.responsive-embed.widescreen{padding-bottom:56.25%}.tabs{background:#fefefe;border:1px solid #e6e6e6;list-style-type:none;margin:0}.tabs:after,.tabs:before{-ms-flex-preferred-size:0;-webkit-box-ordinal-group:2;-ms-flex-order:1;content:" ";display:table;-webkit-flex-basis:0;flex-basis:0;-webkit-order:1;order:1}.tabs:after{clear:both}.tabs.vertical>li{display:block;float:none;width:auto}.tabs.simple>li>a{padding:0}.tabs.simple>li>a:hover{background:0 0}.tabs.primary{background:#1779ba}.tabs.primary>li>a{color:#fefefe}.tabs.primary>li>a:focus,.tabs.primary>li>a:hover{background:#1673b1}.tabs-title{float:left}.tabs-title>a{color:#1779ba;display:block;font-size:.75rem;line-height:1;padding:1.25rem 1.5rem}[data-whatinput=mouse] .tabs-title>a{outline:0}.tabs-title>a:hover{background:#fefefe;color:#1468a0}.tabs-title>a:focus,.tabs-title>a[aria-selected=true]{background:#e6e6e6;color:#1779ba}.tabs-content{background:#fefefe;border:1px solid #e6e6e6;border-top:0;color:#0a0a0a;-webkit-transition:all .5s ease;transition:all .5s ease}.tabs-content.vertical{border:1px solid #e6e6e6;border-left:0}.tabs-panel{display:none;padding:1rem}.tabs-panel.is-active{display:block}.thumbnail{border:4px solid #fefefe;border-radius:0;-webkit-box-shadow:0 0 0 1px hsla(0,0%,4%,.2);box-shadow:0 0 0 1px hsla(0,0%,4%,.2);display:inline-block;line-height:0;margin-bottom:1rem;max-width:100%}a.thumbnail{-webkit-transition:-webkit-box-shadow .2s ease-out;transition:-webkit-box-shadow .2s ease-out;transition:box-shadow .2s ease-out;transition:box-shadow .2s ease-out,-webkit-box-shadow .2s ease-out}a.thumbnail:focus,a.thumbnail:hover{-webkit-box-shadow:0 0 6px 1px rgba(23,121,186,.5);box-shadow:0 0 6px 1px rgba(23,121,186,.5)}a.thumbnail image{-webkit-box-shadow:none;box-shadow:none}.menu{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;list-style:none;margin:0;padding:0;position:relative}[data-whatinput=mouse] .menu li{outline:0}.menu .button,.menu a{display:block;line-height:1;padding:.7rem 1rem;text-decoration:none}.menu a,.menu button,.menu input,.menu select{margin-bottom:0}.menu input{display:inline-block}.menu,.menu.horizontal{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap}.menu.vertical{-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap}.menu.vertical.icon-bottom li a i,.menu.vertical.icon-bottom li a img,.menu.vertical.icon-bottom li a svg,.menu.vertical.icon-top li a i,.menu.vertical.icon-top li a img,.menu.vertical.icon-top li a svg{text-align:left}.menu.expanded li{-webkit-box-flex:1;-webkit-flex:1 1 0px;-ms-flex:1 1 0px;flex:1 1 0px}.menu.expanded.icon-bottom li a i,.menu.expanded.icon-bottom li a img,.menu.expanded.icon-bottom li a svg,.menu.expanded.icon-top li a i,.menu.expanded.icon-top li a img,.menu.expanded.icon-top li a svg{text-align:left}.menu.simple{-webkit-box-align:center;-ms-flex-align:center;-webkit-align-items:center;align-items:center}.menu.simple li+li{margin-left:1rem}.menu.simple a{padding:0}@media print,screen and (min-width:40em){.menu.medium-horizontal{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap}.menu.medium-vertical{-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap}.menu.medium-expanded li,.menu.medium-simple li{-webkit-box-flex:1;-webkit-flex:1 1 0px;-ms-flex:1 1 0px;flex:1 1 0px}}@media print,screen and (min-width:64em){.menu.large-horizontal{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap}.menu.large-vertical{-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap}.menu.large-expanded li,.menu.large-simple li{-webkit-box-flex:1;-webkit-flex:1 1 0px;-ms-flex:1 1 0px;flex:1 1 0px}}.menu.nested{margin-left:1rem;margin-right:0}.menu.icon-bottom a,.menu.icon-left a,.menu.icon-right a,.menu.icon-top a,.menu.icons a{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex}.menu.icon-left li a,.menu.nested.icon-left li a{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-flow:row nowrap;-ms-flex-flow:row nowrap;flex-flow:row nowrap}.menu.icon-left li a i,.menu.icon-left li a img,.menu.icon-left li a svg,.menu.nested.icon-left li a i,.menu.nested.icon-left li a img,.menu.nested.icon-left li a svg{margin-right:.25rem}.menu.icon-right li a,.menu.nested.icon-right li a{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-flow:row nowrap;-ms-flex-flow:row nowrap;flex-flow:row nowrap}.menu.icon-right li a i,.menu.icon-right li a img,.menu.icon-right li a svg,.menu.nested.icon-right li a i,.menu.nested.icon-right li a img,.menu.nested.icon-right li a svg{margin-left:.25rem}.menu.icon-top li a,.menu.nested.icon-top li a{-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-flow:column nowrap;-ms-flex-flow:column nowrap;flex-flow:column nowrap}.menu.icon-top li a i,.menu.icon-top li a img,.menu.icon-top li a svg,.menu.nested.icon-top li a i,.menu.nested.icon-top li a img,.menu.nested.icon-top li a svg{-ms-flex-item-align:stretch;-webkit-align-self:stretch;align-self:stretch;margin-bottom:.25rem;text-align:center}.menu.icon-bottom li a,.menu.nested.icon-bottom li a{-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-flow:column nowrap;-ms-flex-flow:column nowrap;flex-flow:column nowrap}.menu.icon-bottom li a i,.menu.icon-bottom li a img,.menu.icon-bottom li a svg,.menu.nested.icon-bottom li a i,.menu.nested.icon-bottom li a img,.menu.nested.icon-bottom li a svg{-ms-flex-item-align:stretch;-webkit-align-self:stretch;align-self:stretch;margin-bottom:.25rem;text-align:center}.menu .is-active>a{background:#1779ba;color:#fefefe}.menu .active>a{background:#1779ba;color:#fefefe}.menu.align-left{-webkit-box-pack:start;-ms-flex-pack:start;-webkit-justify-content:flex-start;justify-content:flex-start}.menu.align-right li{-webkit-box-pack:end;-ms-flex-pack:end;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-justify-content:flex-end;justify-content:flex-end}.menu.align-right li .submenu li{-webkit-box-pack:start;-ms-flex-pack:start;-webkit-justify-content:flex-start;justify-content:flex-start}.menu.align-right.vertical li{display:block;text-align:right}.menu.align-right.icon-bottom li a i,.menu.align-right.icon-bottom li a img,.menu.align-right.icon-bottom li a svg,.menu.align-right.icon-top li a i,.menu.align-right.icon-top li a img,.menu.align-right.icon-top li a svg,.menu.align-right.vertical li .submenu li{text-align:right}.menu.align-right .nested{margin-left:0;margin-right:1rem}.menu.align-center li{-webkit-box-pack:center;-ms-flex-pack:center;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-justify-content:center;justify-content:center}.menu.align-center li .submenu li{-webkit-box-pack:start;-ms-flex-pack:start;-webkit-justify-content:flex-start;justify-content:flex-start}.menu .menu-text{color:inherit;font-weight:700;line-height:1;padding:.7rem 1rem}.menu-centered>.menu{-webkit-box-pack:center;-ms-flex-pack:center;-webkit-justify-content:center;justify-content:center}.menu-centered>.menu li{-webkit-box-pack:center;-ms-flex-pack:center;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-justify-content:center;justify-content:center}.menu-centered>.menu li .submenu li{-webkit-box-pack:start;-ms-flex-pack:start;-webkit-justify-content:flex-start;justify-content:flex-start}.no-js [data-responsive-menu] ul{display:none}.menu-icon{cursor:pointer;display:inline-block;height:16px;position:relative;vertical-align:middle;width:20px}.menu-icon:after{background:#fefefe;-webkit-box-shadow:0 7px 0 #fefefe,0 14px 0 #fefefe;box-shadow:0 7px 0 #fefefe,0 14px 0 #fefefe;content:"";display:block;height:2px;left:0;position:absolute;top:0;width:100%}.menu-icon:hover:after{background:#cacaca;-webkit-box-shadow:0 7px 0 #cacaca,0 14px 0 #cacaca;box-shadow:0 7px 0 #cacaca,0 14px 0 #cacaca}.menu-icon.dark{cursor:pointer;display:inline-block;height:16px;position:relative;vertical-align:middle;width:20px}.menu-icon.dark:after{background:#0a0a0a;-webkit-box-shadow:0 7px 0 #0a0a0a,0 14px 0 #0a0a0a;box-shadow:0 7px 0 #0a0a0a,0 14px 0 #0a0a0a;content:"";display:block;height:2px;left:0;position:absolute;top:0;width:100%}.menu-icon.dark:hover:after{background:#8a8a8a;-webkit-box-shadow:0 7px 0 #8a8a8a,0 14px 0 #8a8a8a;box-shadow:0 7px 0 #8a8a8a,0 14px 0 #8a8a8a}.accordion-menu li{width:100%}.accordion-menu .is-accordion-submenu a,.accordion-menu a{padding:.7rem 1rem}.accordion-menu .nested.is-accordion-submenu{margin-left:1rem;margin-right:0}.accordion-menu.align-right .nested.is-accordion-submenu{margin-left:0;margin-right:1rem}.accordion-menu .is-accordion-submenu-parent:not(.has-submenu-toggle)>a{position:relative}.accordion-menu .is-accordion-submenu-parent:not(.has-submenu-toggle)>a:after{border-color:#1779ba transparent transparent;border-style:solid;border-width:6px 6px 0;content:"";display:block;height:0;margin-top:-3px;position:absolute;right:1rem;top:50%;width:0}.accordion-menu.align-left .is-accordion-submenu-parent>a:after{left:auto;right:1rem}.accordion-menu.align-right .is-accordion-submenu-parent>a:after{left:1rem;right:auto}.accordion-menu .is-accordion-submenu-parent[aria-expanded=true]>a:after{-webkit-transform:rotate(180deg);-ms-transform:rotate(180deg);transform:rotate(180deg);-webkit-transform-origin:50% 50%;-ms-transform-origin:50% 50%;transform-origin:50% 50%}.is-accordion-submenu-parent{position:relative}.has-submenu-toggle>a{margin-right:40px}.submenu-toggle{cursor:pointer;height:40px;position:absolute;right:0;top:0;width:40px}.submenu-toggle:after{border-color:#1779ba transparent transparent;border-style:solid;border-width:6px 6px 0;bottom:0;content:"";display:block;height:0;margin:auto;top:0;width:0}.submenu-toggle[aria-expanded=true]:after{-webkit-transform:scaleY(-1);-ms-transform:scaleY(-1);transform:scaleY(-1);-webkit-transform-origin:50% 50%;-ms-transform-origin:50% 50%;transform-origin:50% 50%}.submenu-toggle-text{clip:rect(0,0,0,0)!important;border:0!important;height:1px!important;overflow:hidden!important;padding:0!important;position:absolute!important;white-space:nowrap!important;width:1px!important}.is-drilldown{overflow:hidden;position:relative}.is-drilldown li{display:block}.is-drilldown.animate-height{-webkit-transition:height .5s;transition:height .5s}.drilldown a{background:#fefefe;padding:.7rem 1rem}.drilldown .is-drilldown-submenu{background:#fefefe;left:100%;position:absolute;top:0;-webkit-transition:-webkit-transform .15s linear;transition:-webkit-transform .15s linear;transition:transform .15s linear;transition:transform .15s linear,-webkit-transform .15s linear;width:100%;z-index:-1}.drilldown .is-drilldown-submenu.is-active{display:block;-webkit-transform:translateX(-100%);-ms-transform:translateX(-100%);transform:translateX(-100%);z-index:1}.drilldown .is-drilldown-submenu.is-closing{-webkit-transform:translateX(100%);-ms-transform:translateX(100%);transform:translateX(100%)}.drilldown .is-drilldown-submenu a{padding:.7rem 1rem}.drilldown .nested.is-drilldown-submenu{margin-left:0;margin-right:0}.drilldown .drilldown-submenu-cover-previous{min-height:100%}.drilldown .is-drilldown-submenu-parent>a{position:relative}.drilldown .is-drilldown-submenu-parent>a:after{border-color:transparent transparent transparent #1779ba;border-style:solid;border-width:6px 0 6px 6px;content:"";display:block;height:0;margin-top:-6px;position:absolute;right:1rem;top:50%;width:0}.drilldown.align-left .is-drilldown-submenu-parent>a:after{border-color:transparent transparent transparent #1779ba;border-style:solid;border-width:6px 0 6px 6px;content:"";display:block;height:0;left:auto;right:1rem;width:0}.drilldown.align-right .is-drilldown-submenu-parent>a:after{border-color:transparent #1779ba transparent transparent;border-style:solid;border-width:6px 6px 6px 0;content:"";display:block;height:0;left:1rem;right:auto;width:0}.drilldown .js-drilldown-back>a:before{border-color:transparent #1779ba transparent transparent;border-style:solid;border-width:6px 6px 6px 0;content:"";display:block;display:inline-block;height:0;margin-right:.75rem;vertical-align:middle;width:0}.dropdown.menu>li.opens-left>.is-dropdown-submenu{left:auto;right:0;top:100%}.dropdown.menu>li.opens-right>.is-dropdown-submenu{left:0;right:auto;top:100%}.dropdown.menu>li.is-dropdown-submenu-parent>a{padding-right:1.5rem;position:relative}.dropdown.menu>li.is-dropdown-submenu-parent>a:after{border-color:#1779ba transparent transparent;border-style:solid;border-width:6px 6px 0;content:"";display:block;height:0;left:auto;margin-top:-3px;right:5px;width:0}[data-whatinput=mouse] .dropdown.menu a{outline:0}.dropdown.menu>li>a{padding:.7rem 1rem}.dropdown.menu>li.is-active>a{background:0 0;color:#1779ba}.no-js .dropdown.menu ul{display:none}.dropdown.menu .nested.is-dropdown-submenu{margin-left:0;margin-right:0}.dropdown.menu.vertical>li .is-dropdown-submenu{top:0}.dropdown.menu.vertical>li.opens-left>.is-dropdown-submenu{left:auto;right:100%;top:0}.dropdown.menu.vertical>li.opens-right>.is-dropdown-submenu{left:100%;right:auto}.dropdown.menu.vertical>li>a:after{right:14px}.dropdown.menu.vertical>li.opens-left>a:after{border-color:transparent #1779ba transparent transparent;border-style:solid;border-width:6px 6px 6px 0;content:"";display:block;height:0;left:5px;right:auto;width:0}.dropdown.menu.vertical>li.opens-right>a:after{border-color:transparent transparent transparent #1779ba;border-style:solid;border-width:6px 0 6px 6px;content:"";display:block;height:0;width:0}@media print,screen and (min-width:40em){.dropdown.menu.medium-horizontal>li.opens-left>.is-dropdown-submenu{left:auto;right:0;top:100%}.dropdown.menu.medium-horizontal>li.opens-right>.is-dropdown-submenu{left:0;right:auto;top:100%}.dropdown.menu.medium-horizontal>li.is-dropdown-submenu-parent>a{padding-right:1.5rem;position:relative}.dropdown.menu.medium-horizontal>li.is-dropdown-submenu-parent>a:after{border-color:#1779ba transparent transparent;border-style:solid;border-width:6px 6px 0;content:"";display:block;height:0;left:auto;margin-top:-3px;right:5px;width:0}.dropdown.menu.medium-vertical>li .is-dropdown-submenu{top:0}.dropdown.menu.medium-vertical>li.opens-left>.is-dropdown-submenu{left:auto;right:100%;top:0}.dropdown.menu.medium-vertical>li.opens-right>.is-dropdown-submenu{left:100%;right:auto}.dropdown.menu.medium-vertical>li>a:after{right:14px}.dropdown.menu.medium-vertical>li.opens-left>a:after{border-color:transparent #1779ba transparent transparent;border-style:solid;border-width:6px 6px 6px 0;content:"";display:block;height:0;left:5px;right:auto;width:0}.dropdown.menu.medium-vertical>li.opens-right>a:after{border-color:transparent transparent transparent #1779ba;border-style:solid;border-width:6px 0 6px 6px;content:"";display:block;height:0;width:0}}@media print,screen and (min-width:64em){.dropdown.menu.large-horizontal>li.opens-left>.is-dropdown-submenu{left:auto;right:0;top:100%}.dropdown.menu.large-horizontal>li.opens-right>.is-dropdown-submenu{left:0;right:auto;top:100%}.dropdown.menu.large-horizontal>li.is-dropdown-submenu-parent>a{padding-right:1.5rem;position:relative}.dropdown.menu.large-horizontal>li.is-dropdown-submenu-parent>a:after{border-color:#1779ba transparent transparent;border-style:solid;border-width:6px 6px 0;content:"";display:block;height:0;left:auto;margin-top:-3px;right:5px;width:0}.dropdown.menu.large-vertical>li .is-dropdown-submenu{top:0}.dropdown.menu.large-vertical>li.opens-left>.is-dropdown-submenu{left:auto;right:100%;top:0}.dropdown.menu.large-vertical>li.opens-right>.is-dropdown-submenu{left:100%;right:auto}.dropdown.menu.large-vertical>li>a:after{right:14px}.dropdown.menu.large-vertical>li.opens-left>a:after{border-color:transparent #1779ba transparent transparent;border-style:solid;border-width:6px 6px 6px 0;content:"";display:block;height:0;left:5px;right:auto;width:0}.dropdown.menu.large-vertical>li.opens-right>a:after{border-color:transparent transparent transparent #1779ba;border-style:solid;border-width:6px 0 6px 6px;content:"";display:block;height:0;width:0}}.dropdown.menu.align-right .is-dropdown-submenu.first-sub{left:auto;right:0;top:100%}.is-dropdown-menu.vertical{width:100px}.is-dropdown-menu.vertical.align-right{float:right}.is-dropdown-submenu-parent{position:relative}.is-dropdown-submenu-parent a:after{left:auto;margin-top:-6px;position:absolute;right:5px;top:50%}.is-dropdown-submenu-parent.opens-inner>.is-dropdown-submenu{left:auto;top:100%}.is-dropdown-submenu-parent.opens-left>.is-dropdown-submenu{left:auto;right:100%}.is-dropdown-submenu-parent.opens-right>.is-dropdown-submenu{left:100%;right:auto}.is-dropdown-submenu{background:#fefefe;border:1px solid #cacaca;display:none;left:100%;min-width:200px;position:absolute;top:0;z-index:1}.dropdown .is-dropdown-submenu a{padding:.7rem 1rem}.is-dropdown-submenu .is-dropdown-submenu-parent>a:after{right:14px}.is-dropdown-submenu .is-dropdown-submenu-parent.opens-left>a:after{border-color:transparent #1779ba transparent transparent;border-style:solid;border-width:6px 6px 6px 0;content:"";display:block;height:0;left:5px;right:auto;width:0}.is-dropdown-submenu .is-dropdown-submenu-parent.opens-right>a:after{border-color:transparent transparent transparent #1779ba;border-style:solid;border-width:6px 0 6px 6px;content:"";display:block;height:0;width:0}.is-dropdown-submenu .is-dropdown-submenu{margin-top:-1px}.is-dropdown-submenu>li{width:100%}.is-dropdown-submenu.js-dropdown-active{display:block}.is-off-canvas-open{overflow:hidden}.js-off-canvas-overlay{background:hsla(0,0%,100%,.25);height:100%;left:0;opacity:0;overflow:hidden;position:absolute;top:0;-webkit-transition:opacity .5s ease,visibility .5s ease;transition:opacity .5s ease,visibility .5s ease;visibility:hidden;width:100%;z-index:11}.js-off-canvas-overlay.is-visible{opacity:1;visibility:visible}.js-off-canvas-overlay.is-closable{cursor:pointer}.js-off-canvas-overlay.is-overlay-absolute{position:absolute}.js-off-canvas-overlay.is-overlay-fixed{position:fixed}.off-canvas-wrapper{overflow:hidden;position:relative}.off-canvas{-webkit-backface-visibility:hidden;backface-visibility:hidden;background:#e6e6e6;position:fixed;-webkit-transition:-webkit-transform .5s ease;transition:-webkit-transform .5s ease;transition:transform .5s ease;transition:transform .5s ease,-webkit-transform .5s ease;z-index:12}[data-whatinput=mouse] .off-canvas{outline:0}.off-canvas.is-transition-push{z-index:12}.off-canvas.is-closed{visibility:hidden}.off-canvas.is-transition-overlap{z-index:13}.off-canvas.is-transition-overlap.is-open{-webkit-box-shadow:0 0 10px hsla(0,0%,4%,.7);box-shadow:0 0 10px hsla(0,0%,4%,.7)}.off-canvas.is-open{-webkit-transform:translate(0);-ms-transform:translate(0);transform:translate(0)}.off-canvas-absolute{-webkit-backface-visibility:hidden;backface-visibility:hidden;background:#e6e6e6;position:absolute;-webkit-transition:-webkit-transform .5s ease;transition:-webkit-transform .5s ease;transition:transform .5s ease;transition:transform .5s ease,-webkit-transform .5s ease;z-index:12}[data-whatinput=mouse] .off-canvas-absolute{outline:0}.off-canvas-absolute.is-transition-push{z-index:12}.off-canvas-absolute.is-closed{visibility:hidden}.off-canvas-absolute.is-transition-overlap{z-index:13}.off-canvas-absolute.is-transition-overlap.is-open{-webkit-box-shadow:0 0 10px hsla(0,0%,4%,.7);box-shadow:0 0 10px hsla(0,0%,4%,.7)}.off-canvas-absolute.is-open{-webkit-transform:translate(0);-ms-transform:translate(0);transform:translate(0)}.position-left{-webkit-overflow-scrolling:touch;height:100%;left:0;overflow-y:auto;top:0;width:250px}.off-canvas-content .off-canvas.position-left,.position-left{-webkit-transform:translateX(-250px);-ms-transform:translateX(-250px);transform:translateX(-250px)}.off-canvas-content .off-canvas.position-left.is-transition-overlap.is-open{-webkit-transform:translate(0);-ms-transform:translate(0);transform:translate(0)}.off-canvas-content.is-open-left.has-transition-push{-webkit-transform:translateX(250px);-ms-transform:translateX(250px);transform:translateX(250px)}.position-left.is-transition-push{-webkit-box-shadow:inset -13px 0 20px -13px hsla(0,0%,4%,.25);box-shadow:inset -13px 0 20px -13px hsla(0,0%,4%,.25)}.position-right{-webkit-overflow-scrolling:touch;height:100%;overflow-y:auto;right:0;top:0;width:250px}.off-canvas-content .off-canvas.position-right,.position-right{-webkit-transform:translateX(250px);-ms-transform:translateX(250px);transform:translateX(250px)}.off-canvas-content .off-canvas.position-right.is-transition-overlap.is-open{-webkit-transform:translate(0);-ms-transform:translate(0);transform:translate(0)}.off-canvas-content.is-open-right.has-transition-push{-webkit-transform:translateX(-250px);-ms-transform:translateX(-250px);transform:translateX(-250px)}.position-right.is-transition-push{-webkit-box-shadow:inset 13px 0 20px -13px hsla(0,0%,4%,.25);box-shadow:inset 13px 0 20px -13px hsla(0,0%,4%,.25)}.position-top{-webkit-overflow-scrolling:touch;height:250px;left:0;overflow-x:auto;top:0;width:100%}.off-canvas-content .off-canvas.position-top,.position-top{-webkit-transform:translateY(-250px);-ms-transform:translateY(-250px);transform:translateY(-250px)}.off-canvas-content .off-canvas.position-top.is-transition-overlap.is-open{-webkit-transform:translate(0);-ms-transform:translate(0);transform:translate(0)}.off-canvas-content.is-open-top.has-transition-push{-webkit-transform:translateY(250px);-ms-transform:translateY(250px);transform:translateY(250px)}.position-top.is-transition-push{-webkit-box-shadow:inset 0 -13px 20px -13px hsla(0,0%,4%,.25);box-shadow:inset 0 -13px 20px -13px hsla(0,0%,4%,.25)}.position-bottom{-webkit-overflow-scrolling:touch;bottom:0;height:250px;left:0;overflow-x:auto;width:100%}.off-canvas-content .off-canvas.position-bottom,.position-bottom{-webkit-transform:translateY(250px);-ms-transform:translateY(250px);transform:translateY(250px)}.off-canvas-content .off-canvas.position-bottom.is-transition-overlap.is-open{-webkit-transform:translate(0);-ms-transform:translate(0);transform:translate(0)}.off-canvas-content.is-open-bottom.has-transition-push{-webkit-transform:translateY(-250px);-ms-transform:translateY(-250px);transform:translateY(-250px)}.position-bottom.is-transition-push{-webkit-box-shadow:inset 0 13px 20px -13px hsla(0,0%,4%,.25);box-shadow:inset 0 13px 20px -13px hsla(0,0%,4%,.25)}.off-canvas-content{-webkit-backface-visibility:hidden;backface-visibility:hidden;-webkit-transform:none;-ms-transform:none;transform:none}.off-canvas-content.has-transition-overlap,.off-canvas-content.has-transition-push{-webkit-transition:-webkit-transform .5s ease;transition:-webkit-transform .5s ease;transition:transform .5s ease;transition:transform .5s ease,-webkit-transform .5s ease}.off-canvas-content.has-transition-push,.off-canvas-content .off-canvas.is-open{-webkit-transform:translate(0);-ms-transform:translate(0);transform:translate(0)}@media print,screen and (min-width:40em){.position-left.reveal-for-medium{-webkit-transform:none;-ms-transform:none;transform:none;-webkit-transition:none;transition:none;visibility:visible;z-index:12}.position-left.reveal-for-medium .close-button{display:none}.off-canvas-content .position-left.reveal-for-medium{-webkit-transform:none;-ms-transform:none;transform:none}.off-canvas-content.has-reveal-left{margin-left:250px}.position-left.reveal-for-medium~.off-canvas-content{margin-left:250px}.position-right.reveal-for-medium{-webkit-transform:none;-ms-transform:none;transform:none;-webkit-transition:none;transition:none;visibility:visible;z-index:12}.position-right.reveal-for-medium .close-button{display:none}.off-canvas-content .position-right.reveal-for-medium{-webkit-transform:none;-ms-transform:none;transform:none}.off-canvas-content.has-reveal-right{margin-right:250px}.position-right.reveal-for-medium~.off-canvas-content{margin-right:250px}.position-top.reveal-for-medium{-webkit-transform:none;-ms-transform:none;transform:none;-webkit-transition:none;transition:none;visibility:visible;z-index:12}.position-top.reveal-for-medium .close-button{display:none}.off-canvas-content .position-top.reveal-for-medium{-webkit-transform:none;-ms-transform:none;transform:none}.off-canvas-content.has-reveal-top{margin-top:250px}.position-top.reveal-for-medium~.off-canvas-content{margin-top:250px}.position-bottom.reveal-for-medium{-webkit-transform:none;-ms-transform:none;transform:none;-webkit-transition:none;transition:none;visibility:visible;z-index:12}.position-bottom.reveal-for-medium .close-button{display:none}.off-canvas-content .position-bottom.reveal-for-medium{-webkit-transform:none;-ms-transform:none;transform:none}.off-canvas-content.has-reveal-bottom{margin-bottom:250px}.position-bottom.reveal-for-medium~.off-canvas-content{margin-bottom:250px}}@media print,screen and (min-width:64em){.position-left.reveal-for-large{-webkit-transform:none;-ms-transform:none;transform:none;-webkit-transition:none;transition:none;visibility:visible;z-index:12}.position-left.reveal-for-large .close-button{display:none}.off-canvas-content .position-left.reveal-for-large{-webkit-transform:none;-ms-transform:none;transform:none}.off-canvas-content.has-reveal-left{margin-left:250px}.position-left.reveal-for-large~.off-canvas-content{margin-left:250px}.position-right.reveal-for-large{-webkit-transform:none;-ms-transform:none;transform:none;-webkit-transition:none;transition:none;visibility:visible;z-index:12}.position-right.reveal-for-large .close-button{display:none}.off-canvas-content .position-right.reveal-for-large{-webkit-transform:none;-ms-transform:none;transform:none}.off-canvas-content.has-reveal-right{margin-right:250px}.position-right.reveal-for-large~.off-canvas-content{margin-right:250px}.position-top.reveal-for-large{-webkit-transform:none;-ms-transform:none;transform:none;-webkit-transition:none;transition:none;visibility:visible;z-index:12}.position-top.reveal-for-large .close-button{display:none}.off-canvas-content .position-top.reveal-for-large{-webkit-transform:none;-ms-transform:none;transform:none}.off-canvas-content.has-reveal-top{margin-top:250px}.position-top.reveal-for-large~.off-canvas-content{margin-top:250px}.position-bottom.reveal-for-large{-webkit-transform:none;-ms-transform:none;transform:none;-webkit-transition:none;transition:none;visibility:visible;z-index:12}.position-bottom.reveal-for-large .close-button{display:none}.off-canvas-content .position-bottom.reveal-for-large{-webkit-transform:none;-ms-transform:none;transform:none}.off-canvas-content.has-reveal-bottom{margin-bottom:250px}.position-bottom.reveal-for-large~.off-canvas-content{margin-bottom:250px}}@media print,screen and (min-width:40em){.off-canvas.in-canvas-for-medium{background:0 0;height:auto;overflow:visible;position:static;-webkit-transition:none;transition:none;visibility:visible;width:auto}.off-canvas.in-canvas-for-medium.position-bottom,.off-canvas.in-canvas-for-medium.position-left,.off-canvas.in-canvas-for-medium.position-right,.off-canvas.in-canvas-for-medium.position-top{-webkit-box-shadow:none;box-shadow:none;-webkit-transform:none;-ms-transform:none;transform:none}.off-canvas.in-canvas-for-medium .close-button{display:none}}@media print,screen and (min-width:64em){.off-canvas.in-canvas-for-large{background:0 0;height:auto;overflow:visible;position:static;-webkit-transition:none;transition:none;visibility:visible;width:auto}.off-canvas.in-canvas-for-large.position-bottom,.off-canvas.in-canvas-for-large.position-left,.off-canvas.in-canvas-for-large.position-right,.off-canvas.in-canvas-for-large.position-top{-webkit-box-shadow:none;box-shadow:none;-webkit-transform:none;-ms-transform:none;transform:none}.off-canvas.in-canvas-for-large .close-button{display:none}}html.is-reveal-open{overflow-y:hidden;position:fixed;width:100%}html.is-reveal-open.zf-has-scroll{-webkit-overflow-scrolling:touch;overflow-y:scroll}html.is-reveal-open body{overflow-y:hidden}.reveal-overlay{background-color:hsla(0,0%,4%,.45);bottom:0;left:0;position:fixed;right:0;top:0;z-index:1005}.reveal,.reveal-overlay{-webkit-overflow-scrolling:touch;display:none;overflow-y:auto}.reveal{-webkit-backface-visibility:hidden;backface-visibility:hidden;background-color:#fefefe;border:1px solid #cacaca;border-radius:0;margin-left:auto;margin-right:auto;padding:1rem;position:relative;top:100px;z-index:1006}[data-whatinput=mouse] .reveal{outline:0}@media print,screen and (min-width:40em){.reveal{min-height:0}}.reveal .column{min-width:0}.reveal>:last-child{margin-bottom:0}@media print,screen and (min-width:40em){.reveal{max-width:75rem;width:600px}}.reveal.collapse{padding:0}@media print,screen and (min-width:40em){.reveal.tiny{max-width:75rem;width:30%}.reveal.small{max-width:75rem;width:50%}.reveal.large{max-width:75rem;width:90%}}.reveal.full{border:0;border-radius:0;bottom:0;height:100%;left:0;margin-left:0;max-width:none;min-height:100%;right:0;top:0;width:100%}@media print,screen and (max-width:39.99875em){.reveal{border:0;border-radius:0;bottom:0;height:100%;left:0;margin-left:0;max-width:none;min-height:100%;right:0;top:0;width:100%}}.reveal.without-overlay{position:fixed}.sticky,.sticky-container{position:relative}.sticky{-webkit-transform:translateZ(0);transform:translateZ(0);z-index:0}.sticky.is-stuck{position:fixed;width:100%;z-index:5}.sticky.is-stuck.is-at-top{top:0}.sticky.is-stuck.is-at-bottom{bottom:0}.sticky.is-anchored{left:auto;position:relative;right:auto}.sticky.is-anchored.is-at-bottom{bottom:0}.title-bar{-webkit-box-pack:start;-ms-flex-pack:start;-webkit-box-align:center;-ms-flex-align:center;-webkit-align-items:center;align-items:center;background:#0a0a0a;color:#fefefe;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-justify-content:flex-start;justify-content:flex-start;padding:.5rem}.title-bar .menu-icon{margin-left:.25rem;margin-right:.25rem}.title-bar-left,.title-bar-right{-webkit-box-flex:1;-webkit-flex:1 1 0px;-ms-flex:1 1 0px;flex:1 1 0px}.title-bar-right{text-align:right}.title-bar-title{display:inline-block;font-weight:700;vertical-align:middle}.top-bar{-webkit-box-pack:justify;-ms-flex-pack:justify;-webkit-box-align:center;-ms-flex-align:center;-webkit-align-items:center;align-items:center;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;-webkit-justify-content:space-between;justify-content:space-between;padding:.5rem}.top-bar,.top-bar ul{background-color:#e6e6e6}.top-bar input{margin-right:1rem;max-width:200px}.top-bar .input-group-field{margin-right:0;width:100%}.top-bar input.button{width:auto}.top-bar .top-bar-left,.top-bar .top-bar-right{-webkit-box-flex:0;-webkit-flex:0 0 100%;-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}@media print,screen and (min-width:40em){.top-bar{-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap}.top-bar .top-bar-left{-webkit-box-flex:1;-webkit-flex:1 1 auto;-ms-flex:1 1 auto;flex:1 1 auto;margin-right:auto}.top-bar .top-bar-right{-webkit-box-flex:0;-webkit-flex:0 1 auto;-ms-flex:0 1 auto;flex:0 1 auto;margin-left:auto}}@media print,screen and (max-width:63.99875em){.top-bar.stacked-for-medium{-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap}.top-bar.stacked-for-medium .top-bar-left,.top-bar.stacked-for-medium .top-bar-right{-webkit-box-flex:0;-webkit-flex:0 0 100%;-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}}@media print,screen and (max-width:74.99875em){.top-bar.stacked-for-large{-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap}.top-bar.stacked-for-large .top-bar-left,.top-bar.stacked-for-large .top-bar-right{-webkit-box-flex:0;-webkit-flex:0 0 100%;-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}}.top-bar-title{margin:.5rem 1rem .5rem 0}.top-bar-left,.top-bar-right,.top-bar-title{-webkit-box-flex:0;-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto}.float-left{float:left!important}.float-right{float:right!important}.float-center{display:block;margin-left:auto;margin-right:auto}.clearfix:after,.clearfix:before{-ms-flex-preferred-size:0;-webkit-box-ordinal-group:2;-ms-flex-order:1;content:" ";display:table;-webkit-flex-basis:0;flex-basis:0;-webkit-order:1;order:1}.clearfix:after{clear:both}.align-left{-webkit-box-pack:start;-ms-flex-pack:start;-webkit-justify-content:flex-start;justify-content:flex-start}.align-right{-webkit-box-pack:end;-ms-flex-pack:end;-webkit-justify-content:flex-end;justify-content:flex-end}.align-center{-webkit-box-pack:center;-ms-flex-pack:center;-webkit-justify-content:center;justify-content:center}.align-justify{-webkit-box-pack:justify;-ms-flex-pack:justify;-webkit-justify-content:space-between;justify-content:space-between}.align-spaced{-ms-flex-pack:distribute;-webkit-justify-content:space-around;justify-content:space-around}.align-left.vertical.menu>li>a{-webkit-box-pack:start;-ms-flex-pack:start;-webkit-justify-content:flex-start;justify-content:flex-start}.align-right.vertical.menu>li>a{-webkit-box-pack:end;-ms-flex-pack:end;-webkit-justify-content:flex-end;justify-content:flex-end}.align-center.vertical.menu>li>a{-webkit-box-pack:center;-ms-flex-pack:center;-webkit-justify-content:center;justify-content:center}.align-top{-webkit-box-align:start;-ms-flex-align:start;-webkit-align-items:flex-start;align-items:flex-start}.align-self-top{-ms-flex-item-align:start;-webkit-align-self:flex-start;align-self:flex-start}.align-bottom{-webkit-box-align:end;-ms-flex-align:end;-webkit-align-items:flex-end;align-items:flex-end}.align-self-bottom{-ms-flex-item-align:end;-webkit-align-self:flex-end;align-self:flex-end}.align-middle{-webkit-box-align:center;-ms-flex-align:center;-webkit-align-items:center;align-items:center}.align-self-middle{-ms-flex-item-align:center;-webkit-align-self:center;align-self:center}.align-stretch{-webkit-box-align:stretch;-ms-flex-align:stretch;-webkit-align-items:stretch;align-items:stretch}.align-self-stretch{-ms-flex-item-align:stretch;-webkit-align-self:stretch;align-self:stretch}.align-center-middle{-webkit-box-pack:center;-ms-flex-pack:center;-webkit-box-align:center;-ms-flex-align:center;-ms-flex-line-pack:center;-webkit-align-content:center;align-content:center;-webkit-align-items:center;align-items:center;-webkit-justify-content:center;justify-content:center}.small-order-1{-webkit-box-ordinal-group:2;-ms-flex-order:1;-webkit-order:1;order:1}.small-order-2{-webkit-box-ordinal-group:3;-ms-flex-order:2;-webkit-order:2;order:2}.small-order-3{-webkit-box-ordinal-group:4;-ms-flex-order:3;-webkit-order:3;order:3}.small-order-4{-webkit-box-ordinal-group:5;-ms-flex-order:4;-webkit-order:4;order:4}.small-order-5{-webkit-box-ordinal-group:6;-ms-flex-order:5;-webkit-order:5;order:5}.small-order-6{-webkit-box-ordinal-group:7;-ms-flex-order:6;-webkit-order:6;order:6}@media print,screen and (min-width:40em){.medium-order-1{-webkit-box-ordinal-group:2;-ms-flex-order:1;-webkit-order:1;order:1}.medium-order-2{-webkit-box-ordinal-group:3;-ms-flex-order:2;-webkit-order:2;order:2}.medium-order-3{-webkit-box-ordinal-group:4;-ms-flex-order:3;-webkit-order:3;order:3}.medium-order-4{-webkit-box-ordinal-group:5;-ms-flex-order:4;-webkit-order:4;order:4}.medium-order-5{-webkit-box-ordinal-group:6;-ms-flex-order:5;-webkit-order:5;order:5}.medium-order-6{-webkit-box-ordinal-group:7;-ms-flex-order:6;-webkit-order:6;order:6}}@media print,screen and (min-width:64em){.large-order-1{-webkit-box-ordinal-group:2;-ms-flex-order:1;-webkit-order:1;order:1}.large-order-2{-webkit-box-ordinal-group:3;-ms-flex-order:2;-webkit-order:2;order:2}.large-order-3{-webkit-box-ordinal-group:4;-ms-flex-order:3;-webkit-order:3;order:3}.large-order-4{-webkit-box-ordinal-group:5;-ms-flex-order:4;-webkit-order:4;order:4}.large-order-5{-webkit-box-ordinal-group:6;-ms-flex-order:5;-webkit-order:5;order:5}.large-order-6{-webkit-box-ordinal-group:7;-ms-flex-order:6;-webkit-order:6;order:6}}.flex-container{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex}.flex-child-auto{-webkit-box-flex:1;-webkit-flex:1 1 auto;-ms-flex:1 1 auto;flex:1 1 auto}.flex-child-grow{-webkit-box-flex:1;-webkit-flex:1 0 auto;-ms-flex:1 0 auto;flex:1 0 auto}.flex-child-shrink{-webkit-box-flex:0;-webkit-flex:0 1 auto;-ms-flex:0 1 auto;flex:0 1 auto}.flex-dir-row{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row}.flex-dir-row-reverse{-webkit-box-orient:horizontal;-webkit-box-direction:reverse;-webkit-flex-direction:row-reverse;-ms-flex-direction:row-reverse;flex-direction:row-reverse}.flex-dir-column{-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column}.flex-dir-column-reverse{-webkit-box-orient:vertical;-webkit-box-direction:reverse;-webkit-flex-direction:column-reverse;-ms-flex-direction:column-reverse;flex-direction:column-reverse}@media print,screen and (min-width:40em){.medium-flex-container{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex}.medium-flex-child-auto{-webkit-box-flex:1;-webkit-flex:1 1 auto;-ms-flex:1 1 auto;flex:1 1 auto}.medium-flex-child-grow{-webkit-box-flex:1;-webkit-flex:1 0 auto;-ms-flex:1 0 auto;flex:1 0 auto}.medium-flex-child-shrink{-webkit-box-flex:0;-webkit-flex:0 1 auto;-ms-flex:0 1 auto;flex:0 1 auto}.medium-flex-dir-row{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row}.medium-flex-dir-row-reverse{-webkit-box-orient:horizontal;-webkit-box-direction:reverse;-webkit-flex-direction:row-reverse;-ms-flex-direction:row-reverse;flex-direction:row-reverse}.medium-flex-dir-column{-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column}.medium-flex-dir-column-reverse{-webkit-box-orient:vertical;-webkit-box-direction:reverse;-webkit-flex-direction:column-reverse;-ms-flex-direction:column-reverse;flex-direction:column-reverse}}@media print,screen and (min-width:64em){.large-flex-container{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex}.large-flex-child-auto{-webkit-box-flex:1;-webkit-flex:1 1 auto;-ms-flex:1 1 auto;flex:1 1 auto}.large-flex-child-grow{-webkit-box-flex:1;-webkit-flex:1 0 auto;-ms-flex:1 0 auto;flex:1 0 auto}.large-flex-child-shrink{-webkit-box-flex:0;-webkit-flex:0 1 auto;-ms-flex:0 1 auto;flex:0 1 auto}.large-flex-dir-row{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row}.large-flex-dir-row-reverse{-webkit-box-orient:horizontal;-webkit-box-direction:reverse;-webkit-flex-direction:row-reverse;-ms-flex-direction:row-reverse;flex-direction:row-reverse}.large-flex-dir-column{-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column}.large-flex-dir-column-reverse{-webkit-box-orient:vertical;-webkit-box-direction:reverse;-webkit-flex-direction:column-reverse;-ms-flex-direction:column-reverse;flex-direction:column-reverse}}.hide{display:none!important}.invisible{visibility:hidden}.visible{visibility:visible}@media print,screen and (max-width:39.99875em){.hide-for-small-only{display:none!important}}@media screen and (max-width:0em),screen and (min-width:40em){.show-for-small-only{display:none!important}}@media print,screen and (min-width:40em){.hide-for-medium{display:none!important}}@media screen and (max-width:39.99875em){.show-for-medium{display:none!important}}@media print,screen and (min-width:40em)and (max-width:63.99875em){.hide-for-medium-only{display:none!important}}@media screen and (max-width:39.99875em),screen and (min-width:64em){.show-for-medium-only{display:none!important}}@media print,screen and (min-width:64em){.hide-for-large{display:none!important}}@media screen and (max-width:63.99875em){.show-for-large{display:none!important}}@media print,screen and (min-width:64em)and (max-width:74.99875em){.hide-for-large-only{display:none!important}}@media screen and (max-width:63.99875em),screen and (min-width:75em){.show-for-large-only{display:none!important}}.show-for-sr,.show-on-focus{clip:rect(0,0,0,0)!important;border:0!important;height:1px!important;overflow:hidden!important;padding:0!important;position:absolute!important;white-space:nowrap!important;width:1px!important}.show-on-focus:active,.show-on-focus:focus{clip:auto!important;height:auto!important;overflow:visible!important;position:static!important;white-space:normal!important;width:auto!important}.hide-for-portrait,.show-for-landscape{display:block!important}@media screen and (orientation:landscape){.hide-for-portrait,.show-for-landscape{display:block!important}}@media screen and (orientation:portrait){.hide-for-portrait,.show-for-landscape{display:none!important}}.hide-for-landscape,.show-for-portrait{display:none!important}@media screen and (orientation:landscape){.hide-for-landscape,.show-for-portrait{display:none!important}}@media screen and (orientation:portrait){.hide-for-landscape,.show-for-portrait{display:block!important}}.show-for-dark-mode{display:none}.hide-for-dark-mode{display:block}@media screen and (prefers-color-scheme:dark){.show-for-dark-mode{display:block!important}.hide-for-dark-mode{display:none!important}}.show-for-ie{display:none}@media (-ms-high-contrast:active),(-ms-high-contrast:none){.show-for-ie{display:block!important}.hide-for-ie{display:none!important}}.show-for-sticky{display:none}.is-stuck .show-for-sticky{display:block}.is-stuck .hide-for-sticky{display:none}@font-face{font-display:"swap";font-family:FontAwesome}html{box-sizing:border-box}body{font-family:Roboto,sans-serif;font-size:16px;line-height:1}*,:after,:before{box-sizing:inherit}a{color:#3c4fe0}a.reference:after{font-family:FontAwesome;font-size:12px;padding:0 4px}a.reference.external:after{content:""}a.reference.download:after{content:""}a:hover{color:#3c4fe0;font-weight:500}.headerlink{margin-left:5px;visibility:hidden}.toc-backref:hover{color:#23263b}h1,h2,h3,h4,h5,h6{font-family:Roboto,sans-serif;font-size:16px;font-weight:500;letter-spacing:.2px;line-height:24px;margin-bottom:16px}h1:hover>a.headerlink,h2:hover>a.headerlink,h3:hover>a.headerlink,h4:hover>a.headerlink,h5:hover>a.headerlink,h6:hover>a.headerlink{visibility:visible}h1 a,h2 a,h3 a,h4 a,h5 a,h6 a{color:inherit}h1{font-size:32px;font-weight:700;line-height:40px;margin-bottom:28px}h2{font-size:24px;line-height:32px}h3{font-size:20px}h4{font-size:18px}h5{font-size:16px}h6{font-weight:400}img{max-width:100%}button:focus{outline:0}blockquote{border:0;margin:0;padding:0}blockquote,blockquote p,cite{color:inherit}cite{display:inline;font-size:inherit}cite:before{content:""}.show{display:block!important}.centered{display:block;margin:0 auto}.break{flex-basis:100%;height:0}@media screen and (min-width:1024px){h1{font-size:36px}}.admonition-title:before,.contents.local>ul>li a:before,.scylla-icon,.secondary-side-nav__content li a:before{background-repeat:no-repeat;background-size:contain;display:inline-block;filter:brightness(0);vertical-align:middle}.scylla-icon--about-team{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMSwuY2xzLTJ7ZmlsbDpub25lO3N0cm9rZTpncmF5O3N0cm9rZS1taXRlcmxpbWl0OjEwfS5jbHMtMntzdHJva2UtbGluZWNhcDpyb3VuZH08L3N0eWxlPjwvZGVmcz48ZyBpZD0iQ2FscXVlXzQiIGRhdGEtbmFtZT0iQ2FscXVlIDQiPjxwYXRoIGNsYXNzPSJjbHMtMSIgZD0iTTQuNjYgOS44MSAyLjYzIDExYTIuMDggMi4wOCAwIDAgMC0xLjEzIDEuODN2Ny44MWMuMTkgMS4xMS41IDEuNTMgMS41IDEuNDdNNy4wNiA5Ljk0bDEuNDQuOTQiLz48cGF0aCBjbGFzcz0iY2xzLTIiIGQ9Ik0zLjUgMTguNXY1LjM0TTkuNSAxOC41djUuMzRNOC41NCAxOC40MnY1LjMzTTE1LjUgMTguNXY1LjM0TTE2LjUgMTguNXY1LjM0TTMuMzMgMjAuNTNoNS4wOE0xMS40NSA4Ljg0bC4wNi4wNmExLjY1IDEuNjUgMCAwIDAgMi4zNCAwaDAiLz48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Ik0xMi40MiA3LjVhMS44MSAxLjgxIDAgMCAxLTEuOTItMS43N1Y1YTEuOTQgMS45NCAwIDAgMSAxLjkyLTIgMi4wNyAyLjA3IDAgMCAxIDIuMDggMnYuNzdhMiAyIDAgMCAxLTIuMDggMS43M1pNMTEuNDIgOC43NCA5LjYzIDkuOWEyLjA3IDIuMDcgMCAwIDAtMS4xMyAxLjg1djcuODJBMS40NyAxLjQ3IDAgMCAwIDEwIDIxTTEzLjc1IDkuMThsMiAuNjVjLjcuMzUuNzYgMS4wNi43NiAxLjg0djcuOWMwIC43Ny0uMjMgMS4yNC0xIDEuMjQiLz48cGF0aCBjbGFzcz0iY2xzLTIiIGQ9Ik05LjkzIDE5LjVoNS40Ii8+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNMTkuNDIgOS4xMmEyLjA3IDIuMDcgMCAwIDAgMi4wOC0xLjkzdi0uNzdhMi4wNyAyLjA3IDAgMCAwLTIuMDgtMS45MiAxLjkzIDEuOTMgMCAwIDAtMS45MiAxLjkydi43N2ExLjk0IDEuOTQgMCAwIDAgMS45MiAxLjkzWk01LjU5IDkuMTJhMS45MyAxLjkzIDAgMCAwIDEuOTItMS45M3YtLjc3QTEuOTMgMS45MyAwIDAgMCA1LjU5IDQuNSAyLjA4IDIuMDggMCAwIDAgMy41IDYuNDJ2Ljc3YTIuMDggMi4wOCAwIDAgMCAyLjA5IDEuOTNaTTIwLjQ0IDkuODFsMiAxLjE3YTIuMDYgMi4wNiAwIDAgMSAxLjEzIDEuODV2Ny44MWMtLjE4IDEuMTEtLjQ3IDEuNTMtMS40NyAxLjQ3TTE4LjA0IDkuOTRsLTEuNDQuOTMiLz48cGF0aCBjbGFzcz0iY2xzLTIiIGQ9Ik0yMS42IDE4LjV2NS4zNE0yMS43NyAyMC41M2gtNS4wOCIvPjwvZz48L3N2Zz4=)}.scylla-icon--about-us{background-image:url(data:image/svg+xml;base64,PHN2ZyBpZD0iTGF5ZXJfMyIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB2aWV3Qm94PSIwIDAgMjAgMjAiPjxkZWZzPjxzdHlsZT4uY2xzLTF7ZmlsbDpub25lO3N0cm9rZTojMDAwO3N0cm9rZS1saW5lY2FwOnJvdW5kO3N0cm9rZS1saW5lam9pbjpyb3VuZDtzdHJva2Utd2lkdGg6LjhweH08L3N0eWxlPjwvZGVmcz48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Ik02LjI4IDE5LjQ4Yy0uMTIuMDgtLjA4LjA3LS4yMy4xLS41OC4wOS0xLjEyLS4yOC0xLjI1LS44NCAwIDAtMi4zLTkuMTgtMi4zLTExLjExQzIuNSAzLjYgNS44OC40NCAxMC4zOC40NFMxNy41IDMuNDggMTcuNSA3LjVjMCAxLjkzLTEuMzIgMTEuMjMtMS4zMiAxMS4yMy0uMTMuNTYtLjY3Ljk0LTEuMjUuODQtLjEyLS4wMi0uMTMgMC0uMjMtLjA3Ii8+PHBhdGggZD0iTTE1Ljc1IDE1Ljc1Yy0uMTcgMS4xNS0uMjIgMi4zNC0uNTUgMy40Ni0uMzcuODUtMS42MyAxLjA2LTIuMjIuMzMtLjI1LS4yOC4xOS0uNjguNDQtLjQuNDMuNDYgMS4yNC4xOCAxLjMxLS40NGwuMDYtLjM0Yy4xOS0uODkuMzUtMS43OS41Ny0yLjY4LjA1LS4yNC40Mi0uMTcuMzkuMDdaIi8+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNMTEuNSA3YzAgMS45LTEuNTYgMy41LTMuNDYgMy41UzQuNSA4LjkgNC41IDdzMS42NC0zLjUgMy41NC0zLjVTMTEuNSA1LjEgMTEuNSA3WiIvPjxwYXRoIGQ9Ik04LjU1IDQuNzVjLS41OS4xMi0uNzEgMS40Mi0uMzYgMS43OC4yMy4yMy43MS4zMS43MS40N3MtLjQ4LjI0LS43MS40N2MtLjM2LjM2LS4yNCAxLjY2LjM2IDEuNzguNzEuMTQgMS43OC0uNzEgMS43OC0yLjI1UzkuMjYgNC42MSA4LjU1IDQuNzVaTTYuNTEgMTIuMmMyLjEyLjMxIDQuMzQtLjIgNS42OC0xLjk2LjMyLS40MS45Ni4xMS42Mi41MS0uNzYuOS0xLjc4IDEuNjMtMi45MyAxLjk1LTEuMTQuMzMtMi4zMy4zMS0zLjQ2LjE2YS4zNC4zNCAwIDAgMS0uMjktLjM4Yy4wMi0uMTguMTktLjMxLjM3LS4yOVpNNy45NyAxOS41OWMtLjk5Ljk2LTIuMzYuMDgtMi4zNi0xLjE1LS4xMi0uOS0uMjctMS43OS0uMzctMi42OS0uMDEtLjExLjA3LS4yMS4xOC0uMjIuMS0uMDEuMTkuMDYuMjEuMTUuMjIuODguMzggMS43Ny41NiAyLjY2LjAxLjc4LjY4IDEuMzggMS4zNS44My4yNy0uMjcuNjkuMTYuNDIuNDNaIi8+PHBhdGggZD0iTTkuNzUgMTkuMjdjLS40Mi45LTEuOC45Ni0yLjMyLjExLS41LTEuMTMtLjMxLTIuNS0uNDctMy43MiAwLS4xMS4wOC0uMi4xOS0uMjEuMSAwIC4xOS4wNy4yMS4xNy4xNy45NS4yOCAxLjkxLjQyIDIuODcuMDEuNDUuMjMuNzQuNTcuODUuMzMuMS43MS0uMDUuODgtLjM2LjE4LS4zNC43MS0uMDUuNTIuMjlaTTE0LjAzIDE1LjY2Yy0uMTYgMS4yMy4wMyAyLjU3LS40NiAzLjcyLS41Mi44Ni0xLjkxLjc5LTIuMzItLjExLS4xNy0uMzQuMzUtLjYxLjUzLS4yOC40Mi43MSAxLjQ4LjM4IDEuNDUtLjQ5LjE0LS45Ni4yNS0xLjkyLjQyLTIuODcuMDQtLjI0LjQxLS4yLjQuMDRaIi8+PHBhdGggZD0iTTExLjg1IDE1LjU0Yy4wMi43OS4wMSAxLjU4LjAxIDIuMzctLjAyLjQxLjA3LjktLjE0IDEuMjktLjQzIDEuMDItMi4wMSAxLjAyLTIuNDUgMC0uMjEtLjM5LS4xMy0uODktLjE0LTEuMjkgMC0uNzkgMC0xLjU4LjAxLTIuMzcgMC0uMTEuMS0uMi4yMS0uMTkuMSAwIC4xOC4wOC4xOS4xOC4wNy43OS4xIDEuNTguMTUgMi4zNy4wMy4yNyAwIC44Mi4xMyAxLjA0LjEzLjI2LjQuNDMuNjguNDIuNDYgMCAuNzktLjQuNzctLjg3bC4wMy0uNTljLjA0LS43OS4wOC0xLjU4LjE1LTIuMzcuMDItLjI0LjQtLjIzLjQuMDFaIi8+PC9zdmc+)}.scylla-icon--about-us-m{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNi4zOCAzMi40MyI+PHBhdGggZD0iTTYuNTUgMzEuNjRjLS4yLjEzLS40My4yMi0uNjkuMjZhMS44MSAxLjgxIDAgMCAxLTIuMDYtMS4zOVMuNDkgMTQuOTkuNDkgMTEuODJDLjUgNS4xOSA1Ljc3LjUgMTMuMTkuNXMxMi42OSA0LjY5IDEyLjY5IDExLjMyYzAgMy4xOC0zLjMxIDE4LjY5LTMuMzEgMTguNjlhMS44MSAxLjgxIDAgMCAxLTIuNjIgMS4yIiBzdHlsZT0iZmlsbDpub25lO3N0cm9rZTojMDAwO3N0cm9rZS1saW5lY2FwOnJvdW5kO3N0cm9rZS1saW5lam9pbjpyb3VuZCIvPjxwYXRoIGQ9Ik0yMS44NiAyNS4zNmMtLjI4IDEuOS0uMzcgMy44Ni0uOTEgNS43MS0uNjEgMS40MS0yLjY4IDEuNzUtMy42Ni41NS0uNDEtLjQ3LjMxLTEuMTEuNzMtLjY2LjcxLjc2IDIuMDQuMjkgMi4xNi0uNzMuMzItMS42Ni42NS0zLjMzIDEuMDQtNC45OC4wOS0uMzkuNy0uMjguNjUuMTFaIi8+PHBhdGggZD0iTTE0LjggMTAuNTdjMCAzLjEzLTIuNTMgNS42Ni01LjY2IDUuNjZzLTUuNDctMi41My01LjQ3LTUuNjYgMi4zNC01LjY2IDUuNDctNS42NiA1LjY2IDIuNTMgNS42NiA1LjY2WiIgc3R5bGU9InN0cm9rZS13aWR0aDouOXB4O2ZpbGw6bm9uZTtzdHJva2U6IzAwMDtzdHJva2UtbGluZWNhcDpyb3VuZDtzdHJva2UtbGluZWpvaW46cm91bmQiLz48cGF0aCBkPSJNMTAuMzEgNi44NmMtLjk4LjItMS4xNyAyLjM0LS41OSAyLjkzLjM4LjM4IDEuMTcuNTEgMS4xNy43OHMtLjc5LjQtMS4xNy43OGMtLjU5LjU5LS4zOSAyLjczLjU5IDIuOTMgMS4xNi4yMyAyLjkzLTEuMTcgMi45My0zLjcxcy0xLjc2LTMuOTQtMi45My0zLjcxWk02LjgyIDE4LjUxYzMuNDkuODkgNi45Ny0uNSA5LjUxLTIuOTMuNDctLjQ0IDEuMTYuMzEuNjguNzQtMS4zOCAxLjIzLTIuOTggMi4yOS00Ljc5IDIuODctMS44LjU5LTMuNzcuNTgtNS41OC4xNGEuNDIxLjQyMSAwIDAgMS0uMzEtLjVjLjA1LS4yMi4yOC0uMzYuNS0uMzFaIi8+PHBhdGggZD0iTTE2LjczIDE2LjY3Yy0uMTItLjQ2LS41MS0uODMtLjk5LS44My0uNzUtLjAyLS41OS0xLjE3LjE0LS45OS44MS4xNiAxLjQzLjg1IDEuNSAxLjY2LjA4LjQtLjU0LjU0LS42NS4xNVpNOS4wMyAzMS43Yy0xLjI2IDEuMzYtMy42Mi40NS0zLjgtMS4zNWwtLjA5LS41NWMtLjIxLTEuNDgtLjQ1LTIuOTUtLjYtNC40NC0uMDItLjE4LjExLS4zNC4yOS0uMzYuMTctLjAyLjMyLjA5LjM1LjI1LjM5IDEuNjMuNzEgMy4yOCAxLjAzIDQuOTMuMDkgMS4wMiAxLjM4IDEuNTQgMi4xMi44MS40NS0uNDQgMS4xNC4yNi42OS43WiIvPjxwYXRoIGQ9Ik0xMS45NiAzMS4xNmMtMSAxLjk4LTQuMDQgMS4zLTQuMjEtLjg4LS4xNS0xLjY5LS4zLTMuMzgtLjM5LTUuMDcgMC0uMTguMTMtLjM0LjMxLS4zNC4xNyAwIC4zMS4xMS4zNC4yNy4yOCAxLjY3LjUgMy4zNS43MiA1LjAzLjA5IDEuMiAxLjc3IDEuNTkgMi4zNi41MS4zMS0uNTYgMS4xNi0uMDkuODcuNDdaTTE5LjAzIDI1LjIxYy0uMDggMS42OS0uMjQgMy4zOC0uMzkgNS4wNy0uMDQuMzctLjE3Ljc1LS4zOCAxLjA2LS44NiAxLjQtMy4xMSAxLjMxLTMuODMtLjE3LS4zLS41Ni41NS0xLjAzLjg2LS40OC41OSAxLjA4IDIuMjcuNjkgMi4zNS0uNTIuMjItMS42OC40My0zLjM2LjcyLTUuMDMuMDYtLjQuNjgtLjMzLjY1LjA3WiIvPjxwYXRoIGQ9Ik0xNS40MyAyNS4wMmMuMDQgMS4zMS4wMiAyLjYxLjAyIDMuOTEtLjAzLjY3LjExIDEuNDgtLjIzIDIuMTMtLjc0IDEuNjktMy4yOSAxLjY5LTQuMDMgMC0uMzQtLjY1LS4yMS0xLjQ3LS4yNC0yLjEzIDAtMS4zLS4wMi0yLjYxLjAyLTMuOTEgMC0uMTguMTYtLjMyLjM0LS4zMi4xNyAwIC4zLjE0LjMyLjMuMTEgMS4zLjE3IDIuNi4yNCAzLjkxLjA1LjQ1IDAgMS4zNS4yMSAxLjcyLjIxLjQzLjY2LjcxIDEuMTIuNy40Ni4wMi45MS0uMjcgMS4xMi0uNjkuMjItLjM2LjE2LTEuMjguMjEtMS43Mi4wNy0xLjMuMTMtMi42MS4yNC0zLjkxLjAyLS40LjY2LS4zOC42Ni4wMloiLz48L3N2Zz4=)}.scylla-icon--alternator{background-image:url(data:image/svg+xml;base64,PHN2ZyBpZD0iTGF5ZXJfMyIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB2aWV3Qm94PSIwIDAgMjAgMjAiPjxkZWZzPjxzdHlsZT4uY2xzLTF7ZmlsbDpub25lO3N0cm9rZTojMDAwO3N0cm9rZS1saW5lY2FwOnJvdW5kO3N0cm9rZS1saW5lam9pbjpyb3VuZH08L3N0eWxlPjwvZGVmcz48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Ik0xNy41IDIuOTFjMCAxLjI4LTMuNjcgMi41OS04IDIuNTlzLTgtMS4zMS04LTIuNTlTNS4wOS41IDkuNDIuNXM4LjA4IDEuMTMgOC4wOCAyLjQxWk0xNy41IDcuNjZjMCAxLjI4LTMuNjMgMi44LTcuOTYgMi44UzEuNSA4LjkzIDEuNSA3LjY2TTE3LjUgMTIuNDdjMCAxLjI4LTMuNjcgMy4wMy04IDMuMDNzLTgtMS43NS04LTMuMDNNMTcuNSAxNy4yOWMwIDEuMjgtMy43NSAyLjMtOC4wOCAyLjNzLTcuOTItMS4wMy03LjkyLTIuM00xLjUgMTcuMTlWMi45MU0xNy41IDE3LjE5VjIuOTEiLz48L3N2Zz4=)}.scylla-icon--apps{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyMSAxOSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOm5vbmU7c3Ryb2tlOiM0ZDRkNGQ7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJDYWxxdWVfNCIgZGF0YS1uYW1lPSJDYWxxdWUgNCI+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNLjUgMS41aDIwdjE0SC41ek03LjUgMTUuNzR2Mi44OU0xMi44MyAxNS42M3YyLjMyTTUuNSAxOC41aDkuMTQiLz48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Im0zLjY0IDUuNTYgNC41OCAyLjkxLTQuNTggMi45Mk05LjEgMTIuMDhoNC4zMiIvPjwvZz48L3N2Zz4=)}.scylla-icon--architecture{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMSwuY2xzLTIsLmNscy01e2ZpbGw6bm9uZTtzdHJva2U6Z3JheX0uY2xzLTF7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfS5jbHMtMiwuY2xzLTV7c3Ryb2tlLW1pdGVybGltaXQ6MTB9LmNscy0ye3N0cm9rZS13aWR0aDouOThweH0uY2xzLTV7c3Ryb2tlLXdpZHRoOi45OXB4fTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJDYWxxdWVfMiIgZGF0YS1uYW1lPSJDYWxxdWUgMiI+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNMS45IDEwLjI3YTEwLjgzIDEwLjgzIDAgMCAxIDguNzMtOC4zOE0xMC41MSAyMy4wOEExMC43OSAxMC43OSAwIDAgMSAxLjc3IDE0TTIzLjIzIDE0YTEwLjgxIDEwLjgxIDAgMCAxLTkgOS4xMU0xNC4yNyAxLjg4YTEwLjgxIDEwLjgxIDAgMCAxIDguODMgOC4zNyIvPjxjaXJjbGUgY2xhc3M9ImNscy0yIiBjeD0iMTIuMjUiIGN5PSIxLjc1IiByPSIxLjc1Ii8+PGNpcmNsZSBjbGFzcz0iY2xzLTIiIGN4PSIxMi4yNSIgY3k9IjIyLjc1IiByPSIxLjc1Ii8+PGNpcmNsZSBjeD0iNC45MiIgY3k9IjQuNzUiIHI9IjEuNzUiIHN0eWxlPSJzdHJva2Utd2lkdGg6Ljk5cHg7ZmlsbDpncmF5O3N0cm9rZS1taXRlcmxpbWl0OjEwO3N0cm9rZTpncmF5Ii8+PGNpcmNsZSBjeD0iMjAuMDkiIGN5PSIxOS45MSIgcj0iMS43NSIgc3R5bGU9InN0cm9rZS13aWR0aDouOTlweDtmaWxsOmdyYXk7c3Ryb2tlLW1pdGVybGltaXQ6MTA7c3Ryb2tlOmdyYXkiLz48Y2lyY2xlIGNsYXNzPSJjbHMtNSIgY3g9IjEuNzUiIGN5PSIxMi4yNSIgcj0iMS43NSIvPjxjaXJjbGUgY2xhc3M9ImNscy01IiBjeD0iMjMuMjUiIGN5PSIxMi4yNSIgcj0iMS43NSIvPjxjaXJjbGUgY3g9IjQuNzUiIGN5PSIxOS42NCIgcj0iMS43NSIgc3R5bGU9InN0cm9rZS13aWR0aDouOTlweDtmaWxsOmdyYXk7c3Ryb2tlLW1pdGVybGltaXQ6MTA7c3Ryb2tlOmdyYXkiLz48Y2lyY2xlIGN4PSIxOS45MSIgY3k9IjQuNDgiIHI9IjEuNzUiIHN0eWxlPSJzdHJva2Utd2lkdGg6Ljk5cHg7ZmlsbDpncmF5O3N0cm9rZS1taXRlcmxpbWl0OjEwO3N0cm9rZTpncmF5Ii8+PC9nPjwvc3ZnPg==)}.scylla-icon--benchmarks{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVqb2luOnJvdW5kO3N0cm9rZS13aWR0aDozcHh9PC9zdHlsZT48L2RlZnM+PGcgaWQ9IkNhbHF1ZV8yIiBkYXRhLW5hbWU9IkNhbHF1ZSAyIj48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Ik01LjUxIDI0Ljkxdi01Ljg1TTEyLjU3IDI0Ljkxdi05Ljc0TTE5LjYyIDI0LjkxVjEwLjE1Ii8+PHBhdGggc3R5bGU9InN0cm9rZS1saW5lY2FwOnJvdW5kO2ZpbGw6bm9uZTtzdHJva2U6Z3JheTtzdHJva2UtbGluZWpvaW46cm91bmQiIGQ9Im0uOTEgMTQuOTggNS4xMy03Ljk0IDYuMjUgNS44OEwyNCAxIi8+PHBhdGggc3R5bGU9ImZpbGw6Z3JheSIgZD0ibTI1IDUtNS01aDV2NXoiLz48L2c+PC9zdmc+)}.scylla-icon--blog{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJDYWxxdWVfNCIgZGF0YS1uYW1lPSJDYWxxdWUgNCI+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJtOSAxNS0yLjUtMS41IDgtMTJMMTcgMyA5IDE1eiIvPjxwYXRoIHN0eWxlPSJmaWxsOmdyYXk7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kIiBkPSJtNi41IDEzLjUtLjUgM0w5IDE1bC0yLjUtMS41eiIvPjxwYXRoIGNsYXNzPSJjbHMtMSIgZD0iTTE5LjI1IDIuNWg0LjI1djE2aC0xM3Y0LjE3TDYuNDYgMTguNWwtNC45Ni0uMDRWMi41aDguMzFNMTQuNSAyLjVsMS42NyAxLjMzIi8+PC9nPjwvc3ZnPg==)}.scylla-icon--careers{background-image:url(data:image/svg+xml;base64,PHN2ZyBpZD0iQ2FscXVlXzEiIGRhdGEtbmFtZT0iQ2FscXVlIDEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmlld0JveD0iMCAwIDI1IDI1Ij48ZGVmcz48c3R5bGU+LmNscy0xe2ZpbGw6bm9uZTtzdHJva2U6Z3JheTtzdHJva2UtbGluZWNhcDpyb3VuZDtzdHJva2UtbGluZWpvaW46cm91bmR9PC9zdHlsZT48L2RlZnM+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNMS41IDExLjU1djhjMCAuNTYgMS4wNyAyIDIgMmgxOGMuODkgMCAyLTEuNDQgMi0ydi04Ii8+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNMjMuMzEgMy41SDEuODFjLS40OCAwLTEuMzEuNTUtMS4zMSAxdjZsMTAgMmE4LjQ1IDguNDUgMCAwIDAgNCAwbDEwLTJ2LTZjMC0uNDUtLjcyLTEtMS4xOS0xWk0xNS42MiAzLjV2LTFjMC0uNzYtLjYxLTEtMS4zOC0xaC0zLjQ1Yy0uNzYgMC0xLjM4LjI0LTEuMzggMXYxIi8+PHJlY3QgeD0iMTAiIHk9IjExIiB3aWR0aD0iNSIgaGVpZ2h0PSIzLjk5IiByeD0iLjU1IiByeT0iLjU1IiBzdHlsZT0iZmlsbDpncmF5Ii8+PC9zdmc+)}.scylla-icon--chevron-left{background-image:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTAiIGhlaWdodD0iMTYiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZD0iTTguMDkyIDE2IDEwIDE0LjExMyAzLjgxNyA4IDEwIDEuODg3IDguMDkyIDAgMCA4bDguMDkyIDhaIiBmaWxsPSIjMDAwIi8+PC9zdmc+)}.contents.local>ul>li a:before,.scylla-icon--chevron-right,.secondary-side-nav__content li a:before{background-image:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTAiIGhlaWdodD0iMTYiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZD0iTTEuOTA4IDAgMCAxLjg4NyA2LjE4MyA4IDAgMTQuMTEzIDEuOTA4IDE2IDEwIDggMS45MDggMFoiIGZpbGw9IiMwMDAiLz48L3N2Zz4=)}.scylla-icon--circe{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAzOCAzMCI+PGRlZnM+PHN0eWxlPi5jbHMtMiwuY2xzLTN7ZmlsbDpub25lO3N0cm9rZTojNGQ0ZDRkO3N0cm9rZS1saW5lY2FwOnJvdW5kO3N0cm9rZS1saW5lam9pbjpyb3VuZH0uY2xzLTN7c3Ryb2tlLXdpZHRoOjEuMTFweH08L3N0eWxlPjwvZGVmcz48ZyBpZD0iQ2FscXVlXzQiIGRhdGEtbmFtZT0iQ2FscXVlIDQiPjxwYXRoIGQ9Ik0yMi4xIDEyaC02LjE2YTEuMDYgMS4wNiAwIDAgMS0uOTQtMS4wNy45My45MyAwIDAgMSAuOTQtLjkzaDYuMTZhLjkzLjkzIDAgMCAxIC45NC45M0ExLjA2IDEuMDYgMCAwIDEgMjIuMSAxMloiIHN0eWxlPSJmaWxsOiM0ZDRkNGQiLz48cGF0aCBjbGFzcz0iY2xzLTIiIGQ9Ik0xMy40NCA0LjQ5SDkuNTF2MjRoMTl2LTI0SDI0LjUiLz48cGF0aCBjbGFzcz0iY2xzLTMiIGQ9Ik0xMyAzLjQ5SDguNWwtLjA4IDI2LjFIMjkuNVYzLjM5SDI1Ii8+PHBhdGggY2xhc3M9ImNscy0yIiBkPSJNMTIuNSAxOC4zOGgxM00xMi41IDE1LjQ5aDEzTTEyLjUgMjEuNDNoMTNNMTIuNSAyNC40N2gxM00xMy41IDIuNWgxMXYzLjk4aC0xMXoiLz48cGF0aCBjbGFzcz0iY2xzLTMiIGQ9Ik0yMS41LjVoLTUuMDR2MS45NWw1LjA0LjA1di0yeiIvPjwvZz48L3N2Zz4=)}.scylla-icon--clock{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyMSAxOSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOm5vbmU7c3Ryb2tlOiM0ZDRkNGQ7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJDYWxxdWVfNCIgZGF0YS1uYW1lPSJDYWxxdWUgNCI+PGNpcmNsZSBjbGFzcz0iY2xzLTEiIGN4PSIxMC41IiBjeT0iOS41IiByPSI5Ii8+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNMTAuNSAzLjV2NmwzLjA2IDMiLz48L2c+PC9zdmc+)}.scylla-icon--close{background-image:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMzQiIGhlaWdodD0iMzQiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGcgY2xpcC1wYXRoPSJ1cmwoI2EpIiBmaWxsPSIjZmZmIj48cGF0aCBkPSJNMTEuNjcgMjIuMTNhLjU2NC41NjQgMCAwIDEtLjM5OC0uOTYybDkuODk2LTkuODk2YS41NjMuNTYzIDAgMSAxIC43OTcuNzk3bC05Ljg5NiA5Ljg5NmEuNTU5LjU1OSAwIDAgMS0uMzk5LjE2NVoiLz48cGF0aCBkPSJNMjEuNTY2IDIyLjEzYS41NTkuNTU5IDAgMCAxLS4zOTgtLjE2NWwtOS44OTYtOS44OTZhLjU2My41NjMgMCAxIDEgLjc5Ny0uNzk3bDkuODk2IDkuODk1YS41NjQuNTY0IDAgMCAxLS4zOTkuOTYzWiIvPjxwYXRoIGQ9Ik0xNi42MTkgMzMuMjM3QzcuNDU1IDMzLjIzNyAwIDI1Ljc4MiAwIDE2LjYxOSAwIDcuNDU2IDcuNDU1IDAgMTYuNjE5IDBzMTYuNjE5IDcuNDU1IDE2LjYxOSAxNi42MTktNy40NTYgMTYuNjE4LTE2LjYyIDE2LjYxOFptMC0zMi4xMWMtOC41NDIgMC0xNS40OTIgNi45NS0xNS40OTIgMTUuNDkyIDAgOC41NDIgNi45NSAxNS40OTIgMTUuNDkyIDE1LjQ5MiA4LjU0MiAwIDE1LjQ5Mi02Ljk1IDE1LjQ5Mi0xNS40OTIgMC04LjU0Mi02Ljk1LTE1LjQ5Mi0xNS40OTItMTUuNDkyWiIvPjwvZz48ZGVmcz48Y2xpcFBhdGggaWQ9ImEiPjxwYXRoIGZpbGw9IiNmZmYiIGQ9Ik0wIDBoMzMuMjM3djMzLjIzN0gweiIvPjwvY2xpcFBhdGg+PC9kZWZzPjwvc3ZnPg==)}.scylla-icon--cloud{background-image:url(data:image/svg+xml;base64,PHN2ZyBpZD0iTGF5ZXJfMiIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB2aWV3Qm94PSIwIDAgNDMuMDQgMzIuMDMiPjxkZWZzPjxzdHlsZT4uY2xzLTF7ZmlsbDpub25lO3N0cm9rZTojMWQxZDFiO3N0cm9rZS1saW5lY2FwOnJvdW5kO3N0cm9rZS1saW5lam9pbjpyb3VuZH08L3N0eWxlPjwvZGVmcz48ZyBpZD0iTGF5ZXJfMyI+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNNDIuNTQgNC4wNmMwIDEuNjgtMy42MyAyLjQ0LTkgMi40NHMtMTAtLjczLTEwLTIuNFMyNy42Ny41IDMzLjA0LjVzOS41IDEuODkgOS41IDMuNTZaTTQyLjU0IDkuNjNjMCAxLjY4LTMuNzYgMi45MS05LjEyIDIuOTFzLTkuODQtMS4yMy05Ljg0LTIuOTFNNDIuNTQgMTUuMzRjMCAxLjY4LTMuNjggMy4yNS05LjA0IDMuMjUtNCAwLTcuNi0uOTYtOS4wOS0yLjA0TTQyLjU0IDIwLjY1YzAgMS42OC0zLjcyIDIuOTctOS4wOCAyLjk3TTIzLjU0IDE1LjQ2VjQuMU00Mi41NCAyMC43N1Y0LjEiLz48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Ik0yOC4xMSAyMS4wOGMtLjg3IDAtMS42Ny4yMy0yLjM5LjYxIDAtLjA3LjAxLS4xNC4wMS0uMjEgMC00Ljg1LTMuODMtOC45LTguNjgtOC45cy04Ljg4IDQuMDUtOC44OCA4LjljMCAuMTcuMDIuMzQuMDMuNTEtLjg0LS41Ny0xLjg1LS45MS0yLjk1LS45MS0yLjg4IDAtNC43NCAyLjU3LTQuNzQgNS40NnMxLjg2IDQuOTkgNC43NCA0Ljk5aDIyLjg2YzIuODggMCA1LjUyLTIuMjcgNS41Mi01LjE2cy0yLjYzLTUuMjktNS41Mi01LjI5WiIvPjwvZz48L3N2Zz4=)}.scylla-icon--cloud-docs{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyMSAxOSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOm5vbmU7c3Ryb2tlOiM0ZDRkNGQ7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJDYWxxdWVfNCIgZGF0YS1uYW1lPSJDYWxxdWUgNCI+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNNi41IDExLjVoOHYxaC04ek0xNS42NSA2LjU1YTMuNDIgMy40MiAwIDAgMC0zLjE1IDIiLz48cGF0aCBkPSJNMTAuMDYgMi44QTUuMTcgNS4xNyAwIDAgMSAxNSA2LjM1aC4yNGE0Ljg0IDQuODQgMCAwIDEgMCA5LjY3aC0xMWEzLjQ1IDMuNDUgMCAwIDEgMC02LjlBMy4xNyAzLjE3IDAgMCAxIDUgOS4yIDUuMzMgNS4zMyAwIDAgMSA0Ljg2IDhhNS4yIDUuMiAwIDAgMSA1LjItNS4ybTAtLjhhNiA2IDAgMCAwLTYgNnYuMzFhNC4yNSA0LjI1IDAgMCAwIC4xOCA4LjQ5aDExYTUuNjMgNS42MyAwIDAgMCAuMy0xMS4yNkE2IDYgMCAwIDAgMTAuMDYgMloiIHN0eWxlPSJmaWxsOiM0ZDRkNGQiLz48L2c+PC9zdmc+)}.scylla-icon--comparison{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMSwuY2xzLTIsLmNscy00e2ZpbGw6bm9uZTtzdHJva2U6Z3JheX0uY2xzLTEsLmNscy0ye3N0cm9rZS1taXRlcmxpbWl0OjEwfS5jbHMtMiwuY2xzLTR7c3Ryb2tlLWxpbmVjYXA6cm91bmR9LmNscy00e3N0cm9rZS1saW5lam9pbjpyb3VuZH08L3N0eWxlPjwvZGVmcz48ZyBpZD0iQ2FscXVlXzQiIGRhdGEtbmFtZT0iQ2FscXVlIDQiPjxwYXRoIGNsYXNzPSJjbHMtMSIgZD0iTTQuNSAxMy42M3YyLjg4aDYuMDZNMjAuNSAxMy41NHYyLjk2bC01LjUuMDEiLz48cGF0aCBjbGFzcz0iY2xzLTIiIGQ9Ik0xMi41IDE4LjV2Mi43Mk03LjUgMjEuNWgxMCIvPjxjaXJjbGUgY3g9IjEyLjUiIGN5PSIxNi41IiByPSIyIiBzdHlsZT0iZmlsbDpncmF5O3N0cm9rZS13aWR0aDouOTVweDtzdHJva2UtbWl0ZXJsaW1pdDoxMDtzdHJva2U6Z3JheSIvPjxwYXRoIGNsYXNzPSJjbHMtNCIgZD0iTTUuMDYgMTMuNThIMy44OEEzLjEgMy4xIDAgMCAxIC41IDEwLjVoOGEzLjE2IDMuMTYgMCAwIDEtMy40NCAzLjA4Wk0yMSAxMy41OGgtMS4xN2EzLjA5IDMuMDkgMCAwIDEtMy4zNy0zLjA3aDhBMy4xNiAzLjE2IDAgMCAxIDIxIDEzLjU4Wk03LjQ2IDUuMTJjMCAuNTctMS4xLjQ2LTIuNzkuNDZTMS41OCA1LjYgMS41OCA1IDMgNC40IDQuNjkgNC40czIuNzcuMTYgMi43Ny43MlpNMS41IDkuODVWNS4zMU03LjUgMTAuMzVWNS44MU0yMy41IDUuMTJjMCAuNTctMS4xLjQ2LTIuNzkuNDZzLTMuMDkgMC0zLjA5LS41NFMxOSA0LjQgMjAuNzMgNC40czIuNzcuMTYgMi43Ny43MlpNMTcuNTQgOS44NVY1LjMxTTIzLjU0IDEwLjM1VjUuODEiLz48L2c+PC9zdmc+)}.scylla-icon--contact-us{background-image:url(data:image/svg+xml;base64,PHN2ZyBpZD0iQ2FscXVlXzEiIGRhdGEtbmFtZT0iQ2FscXVlIDEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmlld0JveD0iMCAwIDI1IDI1Ij48ZGVmcz48c3R5bGU+LmNscy0xe2ZpbGw6bm9uZTtzdHJva2U6Z3JheTtzdHJva2UtbGluZWNhcDpyb3VuZDtzdHJva2UtbGluZWpvaW46cm91bmQ7c3Ryb2tlLXdpZHRoOjEuMDZweH08L3N0eWxlPjwvZGVmcz48cGF0aCBjbGFzcz0iY2xzLTEiIHRyYW5zZm9ybT0icm90YXRlKC0yNy40OSAxNS41NTIgMTEuMDgzKSIgZD0iTTcuNzYgNi4wMWgxNS41OXYxMC4xM0g3Ljc2eiIvPjxwYXRoIGNsYXNzPSJjbHMtMSIgZD0ibTYuMyAxMC4xOCA4LjYzIDEuNTZhMS40MiAxLjQyIDAgMCAwIDEuNTMtLjc0bDMuNjctOE0xMS4wMiAxOS4wM2wxLjc0LTVNMjQuNTkgMTEuOTdsLTUuMDktMS40NU03LjA5IDE3LjU4IDMuOSAxOS4zNE02LjA2IDE1LjQxLjU0IDE4LjM2Ii8+PC9zdmc+)}.scylla-icon--developers-blog{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOmdyYXl9PC9zdHlsZT48L2RlZnM+PGcgaWQ9IkNhbHF1ZV80IiBkYXRhLW5hbWU9IkNhbHF1ZSA0Ij48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Im02LjQ4IDEwLjU5LS41LjE3LjUuMTZMMTEgMTIuMTZWMTRsLTctMi40OVYxMGw3LTIuNXYxLjgzWk0xNCA5LjMyVjcuNWw3IDIuNXYxLjU0TDE0IDE0di0xLjgzbDQuMTQtMS4zLjQ0LS4xMy0uNDMtLjE0WiIvPjxwYXRoIHN0eWxlPSJmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kO3N0cm9rZS13aWR0aDouOThweCIgZD0iTTEuNSAyLjVoMjJ2MTZoLTEzdjQuMTdMNi40NiAxOC41bC00Ljk2LS4wNFYyLjV6Ii8+PC9nPjwvc3ZnPg==)}.scylla-icon--docs{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfS5jbHMtMntmaWxsOmdyYXl9PC9zdHlsZT48L2RlZnM+PGcgaWQ9IkNhbHF1ZV80IiBkYXRhLW5hbWU9IkNhbHF1ZSA0Ij48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Ik0zLjUgMi41MWgxNi45NHYyMC45MUgzLjV6Ii8+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJtMjIuNDUgMjEuNS4wNS0yMWgtMTdhMi4xNiAyLjE2IDAgMCAwLTIgMiIvPjxwYXRoIGNsYXNzPSJjbHMtMiIgZD0iTTYgNmg3djJINnpNNiA5aDExdjJINnoiLz48L2c+PC9zdmc+)}.scylla-icon--enterprise{background-image:url(data:image/svg+xml;base64,PHN2ZyBpZD0iTGF5ZXJfMyIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB2aWV3Qm94PSIwIDAgMjAgMjAiPjxkZWZzPjxzdHlsZT4uY2xzLTEsLmNscy0ye2ZpbGw6bm9uZTtzdHJva2U6IzAwMDtzdHJva2UtbGluZWNhcDpyb3VuZDtzdHJva2UtbGluZWpvaW46cm91bmR9LmNscy0ye3N0cm9rZS13aWR0aDoxLjA3cHh9PC9zdHlsZT48L2RlZnM+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJtMTMuNjIgNy41IDEuODgtMS4wOCAyIDIuMDh2N2gxTTE1LjUgMTUuNXYtNSIvPjxwYXRoIGNsYXNzPSJjbHMtMiIgZD0iTTUuNSAxNS41di0xMmw0LTIgNCAydjEyTTkuNSAxNS41VjEuNk03LjUgNS41djEwTTExLjUgNS41djEwIi8+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNNS41IDguNTQgMy40NiA3LjVsLTEuOTYuOTZ2Ny4wNGgtMU0zLjUgMTAuNXY1TS41IDE3LjVoMTgiLz48L3N2Zz4=)}.scylla-icon--enterprise-m{background-image:url(data:image/svg+xml;base64,PHN2ZyB2ZXJzaW9uPSIxLjEiIGlkPSJMYXllcl8yXzAwMDAwMDE2NzY4MDY2MDE5MjYzMjMyNzcwMDAwMDA1NDc1ODA5NTExODI4NjY2MDM2XyIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4PSIwIiB5PSIwIiB2aWV3Qm94PSIwIDAgNDMgMzEiIHN0eWxlPSJlbmFibGUtYmFja2dyb3VuZDpuZXcgMCAwIDQzIDMxIiB4bWw6c3BhY2U9InByZXNlcnZlIj48c3R5bGU+LnN0MHtmaWxsOm5vbmU7c3Ryb2tlOiMxZDFkMWI7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfTwvc3R5bGU+PGcgaWQ9IkxheWVyXzMiPjxwYXRoIGNsYXNzPSJzdDAiIGQ9Im0yOS42IDkuNSA0LTIgNi45IDQuMXYxNS45aDJNMzMuNiAyNy41VjcuNk0xNC42IDI3LjVWNC44TDIyLjUuNSAyOS42IDV2MjIuNU0yMi41IDI3LjVWMU0yNC41IDUuNmwzIDJNMjQuNSA5LjZsMyAyTTI0LjUgMTMuNmwzIDJNMjQuNSAxNy41bDMgMk0yNC41IDIxLjVsMyAyTTM1LjQgMTEuNmwzIDJNMzUuNCAxNS42bDMgMS45TTM1LjQgMTkuNWwzIDJNMzUuNCAyMy41bDMgMS45TTE4LjUgNS44djIxLjdNMTQuNiA5LjdsLTQuMS0yLjUtOCA0LjR2MTUuOWgtMk0xMC41IDI3LjVWNy4yTTEyLjUgMTEuNmwyIDFNMTIuNSAxNS42bDIgLjlNMTIuNSAxOS41bDIgMU0xMi41IDIzLjVsMi4xIDFNNi40IDEyLjR2MTUuMU0uNSAzMC41aDQyIi8+PC9nPjwvc3ZnPg==)}.scylla-icon--events{background-image:url(data:image/svg+xml;base64,PHN2ZyBpZD0iQ2FscXVlXzEiIGRhdGEtbmFtZT0iQ2FscXVlIDEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmlld0JveD0iMCAwIDI1IDI1Ij48ZGVmcz48c3R5bGU+LmNscy0xe2ZpbGw6bm9uZTtzdHJva2U6Z3JheTtzdHJva2UtbGluZWNhcDpyb3VuZDtzdHJva2UtbGluZWpvaW46cm91bmR9LmNscy0ye2ZpbGw6Z3JheX08L3N0eWxlPjwvZGVmcz48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Ik0yMi41IDIzLjVoLTIxdi0yMGgyMnYxNS4yMSIvPjxwYXRoIGNsYXNzPSJjbHMtMSIgZD0iTTQuNDIgMy41YzAtMS4zNiAxLjA5LTIgMi40NS0yYTIuNDYgMi40NiAwIDEgMSAwIDQuOTEgMi42MSAyLjYxIDAgMCAxLTEtLjIxTTEwLjY3IDMuNWMwLTEuMzYgMS4xLTIgMi40Ni0yYTIuNDYgMi40NiAwIDAgMSAwIDQuOTEgMi42MSAyLjYxIDAgMCAxLTEtLjIxTTE2LjkzIDMuNWMwLTEuMzYgMS4xLTIgMi40NS0yYTIuNDYgMi40NiAwIDEgMSAwIDQuOTEgMi41MiAyLjUyIDAgMCAxLTEtLjIxIi8+PHBhdGggY2xhc3M9ImNscy0yIiBkPSJNNyA5aDN2M0g3ek0xMiA5aDN2M2gtM3pNMTcgOWgzdjNoLTN6TTcgMTRoM3YzSDd6TTEyIDE0aDN2M2gtM3pNMTcgMTRoM3YzaC0zeiIvPjxwYXRoIGNsYXNzPSJjbHMtMSIgZD0iTTMuNSAzLjY3djE2LjY2TTMuNSAyMC40M2MwIDEuMjkuNDQgMi4zMyAxLjczIDIuMzNzMi4zMy0xLjkgMi4zMy0zLjE5bDE2Ljk0LS4wN2MwIDEuMjktLjU1IDMuMTItMS44MyAzLjEySDYuMyIvPjwvc3ZnPg==)}.admonition.note .admonition-title:before,.admonition.tip .admonition-title:before,.scylla-icon--exclamation{background-image:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PG1hc2sgaWQ9ImEiIG1hc2stdHlwZT0iYWxwaGEiIG1hc2tVbml0cz0idXNlclNwYWNlT25Vc2UiIHg9IjEiIHk9IjEiIHdpZHRoPSIyMiIgaGVpZ2h0PSIyMiI+PHBhdGggZD0iTTEyIDIzQzUuOSAyMyAxIDE4LjEgMSAxMlM1LjkgMSAxMiAxczExIDQuOSAxMSAxMS00LjkgMTEtMTEgMTFabTAtMjBjLTUgMC05IDQtOSA5czQgOSA5IDkgOS00IDktOS00LTktOS05WiIgZmlsbD0iI2ZmZiIvPjxwYXRoIGQ9Ik0xMiAxM2MtLjYgMC0xLS40LTEtMVY4YzAtLjYuNC0xIDEtMXMxIC40IDEgMXY0YzAgLjYtLjQgMS0xIDFaTTEyIDE3Yy0uMyAwLS41LS4xLS43LS4zLS4yLS4yLS4zLS40LS4zLS43IDAtLjEgMC0uMy4xLS40LjEtLjEuMS0uMi4yLS4zLjMtLjMuNy0uNCAxLjEtLjIuMSAwIC4xIDAgLjIuMSAwIDAgLjEuMS4yLjEuMS4xLjIuMi4yLjN2LjRjMCAuMSAwIC4zLS4xLjQtLjEuMS0uMS4yLS4yLjMtLjIuMi0uNC4zLS43LjNaIiBmaWxsPSIjZmZmIi8+PC9tYXNrPjxnIG1hc2s9InVybCgjYSkiPjxwYXRoIGZpbGw9IiNmZmYiIGQ9Ik0wIDBoMjR2MjRIMHoiLz48L2c+PC9zdmc+)}.collapsible-button i,.scylla-icon--expand{background-image:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYuMDAxIiBoZWlnaHQ9IjE2IiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjxwYXRoIGQ9Ik01IDEzYTEgMSAwIDAgMS0uNzEtLjI5bC00LTRhMSAxIDAgMCAxIDAtMS40MWw0LTRhMSAxIDAgMCAxIDEuNDIgMS40MUwyLjQxIDhsMy4yOSAzLjI5QTEgMSAwIDAgMSA1IDEzeiIvPjxwYXRoIGQ9Ik0xMSA5SDFhMSAxIDAgMCAxIDAtMmgxMGExIDEgMCAwIDEgMCAyek0xNSAxNmExIDEgMCAwIDEtMS0xVjFhMSAxIDAgMCAxIDIgMHYxNGExIDEgMCAwIDEtMSAxeiIvPjwvc3ZnPg==)}.scylla-icon--forum{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSJjdXJyZW50Q29sb3IiIHN0cm9rZS13aWR0aD0iMS41IiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiIGNsYXNzPSJmZWF0aGVyIGZlYXRoZXItdXNlcnMiPjxwYXRoIGQ9Ik0xNyAyMXYtMmE0IDQgMCAwIDAtNC00SDVhNCA0IDAgMCAwLTQgNHYyIi8+PGNpcmNsZSBjeD0iOSIgY3k9IjciIHI9IjQiLz48cGF0aCBkPSJNMjMgMjF2LTJhNCA0IDAgMCAwLTMtMy44N00xNiAzLjEzYTQgNCAwIDAgMSAwIDcuNzUiLz48L3N2Zz4=)}.scylla-icon--home{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyMSAxOSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOm5vbmU7c3Ryb2tlOiM0ZDRkNGQ7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJMYXllcl81IiBkYXRhLW5hbWU9IkxheWVyIDUiPjxwYXRoIGNsYXNzPSJjbHMtMSIgZD0iTTMuNSA2LjE0djExYTEuMzggMS4zOCAwIDAgMCAxLjM3IDEuMzZoMTEuMjZhMS4zOCAxLjM4IDAgMCAwIDEuMzctMS4zN3YtMTEiLz48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Im0xOS41IDcuNS04LTYuMjVhMS41OSAxLjU5IDAgMCAwLTEuOTQgMEwxLjUgNy41TTEyLjczIDE4LjAydi03LjIxSDguMjd2Ny4yMSIvPjwvZz48L3N2Zz4=)}.scylla-icon--getting-started{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyMSAxOSI+PGcgZGF0YS1uYW1lPSJDYWxxdWUgNCI+PHBhdGggc3R5bGU9ImZpbGw6IzRkNGQ0ZCIgZD0ibTcgNC41IDguNTEgNS4wNUw3IDE0LjV2LTEweiIvPjxyZWN0IHg9IjEuNSIgeT0iLjUiIHdpZHRoPSIxOCIgaGVpZ2h0PSIxOCIgcng9IjIuNDMiIHN0eWxlPSJmaWxsOm5vbmU7c3Ryb2tlOiM0ZDRkNGQ7c3Ryb2tlLW1pdGVybGltaXQ6MTAiLz48L2c+PC9zdmc+)}.scylla-icon--glossary{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyMSAxOSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOm5vbmU7c3Ryb2tlOiM0ZDRkNGQ7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJDYWxxdWVfNCIgZGF0YS1uYW1lPSJDYWxxdWUgNCI+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNMi41IDIuNWgxM3YxNmgtMTN6Ii8+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNMTUuNTggMTcuMjFoMS45MlYuNWgtMTNhMi4zNCAyLjM0IDAgMCAwLTIgMiIvPjxwYXRoIGQ9Ik00LjggMTMuOTNhMSAxIDAgMCAwIC43NS0uNDMgNiA2IDAgMCAwIC41Mi0xLjA4bDIuODctNy4wN2guMzZsMi44OCA2Ljc5YTguOTIgOC45MiAwIDAgMCAuNzIgMS40Ny43Ni43NiAwIDAgMCAuNjguMzJ2LjMySDkuNHYtLjMyYTMuMjQgMy4yNCAwIDAgMCAuODMtLjExYy4xMy0uMDYuMi0uMTkuMi0uNDJhMS41OSAxLjU5IDAgMCAwLS4xLS40NmMwLS4xMi0uMS0uMjctLjE3LS40NGwtLjMzLS43OGgtMi45Yy0uMTkuNTEtLjMxLjg1LS4zNiAxYTIuMzggMi4zOCAwIDAgMC0uMTcuNzNjMCAuMTguMTIuMzIuMzcuNGEyLjU2IDIuNTYgMCAwIDAgLjY2LjA4di4zMkg0LjhabTQuODQtMi43Mi0xLjI0LTNoLS4xMWwtMS4xNiAzWiIgc3R5bGU9ImZpbGw6IzRkNGQ0ZCIvPjwvZz48L3N2Zz4=)}.scylla-icon--infoworld{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLW1pdGVybGltaXQ6MTB9PC9zdHlsZT48L2RlZnM+PGcgaWQ9IkNhbHF1ZV80IiBkYXRhLW5hbWU9IkNhbHF1ZSA0Ij48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Ik0xMiAyLjVINi41VjZjMCAzIC41NSA3LjE3IDUgOS41djQiLz48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Ik02LjQgNC40NGgtNFMyLjU2IDExIDguNSAxM00xOC41IDQuNWw0LS4wNnMtLjA2IDYuNTYtNiA4LjU2Ii8+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNMTIgMi41aDYuNVY2YzAgMi45NC0uNCA3LjA4LTUgOS41djRNOS41IDE5LjVoNnYyaC02eiIvPjxwYXRoIHN0eWxlPSJmaWxsOmdyYXk7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLW1pdGVybGltaXQ6MTAiIGQ9Ik03LjUgMjEuNWgxMHYxaC0xMHoiLz48L2c+PC9zdmc+)}.scylla-icon--integrations{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOm5vbmU7c3Ryb2tlOiM0ZDRkNGQ7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJDYWxxdWVfNCIgZGF0YS1uYW1lPSJDYWxxdWUgNCI+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJtMTQuNTYgMTIuNy0xLjI1LTEuNTctMS4zMS43NmE2IDYgMCAwIDAtMS42NS0xbC4wOC0xLjQ5LTItLjQtLjUzIDEuNDRhNS43MyA1LjczIDAgMCAwLTEuODcuMzFsLS44OC0xLjE5LTEuNzcgMUwzLjkyIDEyYTYuMyA2LjMgMCAwIDAtMS4yMiAxLjQxbC0xLjUtLjM1LS43NCAxLjg3IDEuMzguOGE2LjIzIDYuMjMgMCAwIDAgMCAxLjgzbC0xLjQxLjcyLjY0IDEuOTEgMS41OS0uMjhhNy42MyA3LjYzIDAgMCAwIC40OC42OCA1Ljg2IDUuODYgMCAwIDAgLjY3LjczbC0uNjIgMS40NiAxLjcyIDEgMS0xLjI0YTYuNDYgNi40NiAwIDAgMCAxLjc5LjM1bC40NiAxLjUyIDItLjN2LTEuNmE2LjQzIDYuNDMgMCAwIDAgMS42Mi0uODlsMS4zLjg1TDE0LjQzIDIxbC0xLTEuMmE2LjI0IDYuMjQgMCAwIDAgLjY4LTEuNzVsMS41MS0uMTkuMDUtMi0xLjUxLS4yNmE2LjA3IDYuMDcgMCAwIDAtLjYyLTEuODFabS01LjM1IDUuNTFhMS45MyAxLjkzIDAgMSAxIC4zMS0yLjcxIDEuOTIgMS45MiAwIDAgMS0uMzEgMi43MVoiLz48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Im0yNC4zMSA4LjA1LS4xMy0xLjY1LTEuMjUtLjA5YTUuMjYgNS4yNiAwIDAgMC0uNjctMS40NGwuNzUtMS0xLjE2LTEuMTctMSAuNzRhNS4xOCA1LjE4IDAgMCAwLTEuNDMtLjY2bC0uMDYtMS4yNC0xLjY1LS4xNy0uMzIgMS4yNWE1Ljc3IDUuNzcgMCAwIDAtMS41Mi4zOEwxNSAyLjFsLTEuMzcuOS41OCAxLjE4YTQuODggNC44OCAwIDAgMC0uODYgMS4yNWwtMS4zLS4xNi0uNDUgMS42IDEuMjIuNTVhNS4xNyA1LjE3IDAgMCAwIDAgLjY4QTQuMjggNC4yOCAwIDAgMCAxMyA5bC0xLjExLjcyLjY5IDEuNTEgMS4yOC0uMzdhNC45NCA0Ljk0IDAgMCAwIDEuMDcgMS4wN2wtLjM5IDEuMjYgMS41LjcxLjc0LTEuMDlhNS4wNyA1LjA3IDAgMCAwIDEuNTIuMTRsLjUgMS4xOSAxLjYxLS40MS0uMTMtMS4yOWE1LjE0IDUuMTQgMCAwIDAgMS4yNy0uODhsMS4xMi41NyAxLTEuMzUtLjkxLS44OGE0LjkgNC45IDAgMCAwIC40Mi0xLjUyWm0tNi4yIDEuNDNhMS43NCAxLjc0IDAgMSAxIDEuNi0xLjg2IDEuNzQgMS43NCAwIDAgMS0xLjYgMS44NloiLz48L2c+PC9zdmc+)}.scylla-icon--knowledge-base{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyMSAxOSI+PGRlZnM+PHN0eWxlPi5jbHMtMSwuY2xzLTJ7ZmlsbDpub25lO3N0cm9rZTojNGQ0ZDRkfS5jbHMtMXtzdHJva2UtbGluZWNhcDpyb3VuZDtzdHJva2UtbGluZWpvaW46cm91bmR9LmNscy0ye3N0cm9rZS1taXRlcmxpbWl0OjEwfTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJMYXllcl81IiBkYXRhLW5hbWU9IkxheWVyIDUiPjxwYXRoIGNsYXNzPSJjbHMtMSIgZD0iTTE2LjIxIDYuMzhhNS4zNiA1LjM2IDAgMCAxLTEuNTEgMy43MyA1IDUgMCAwIDAtMS40NSAzLjMxSDguNDdhNS40MSA1LjQxIDAgMCAwLTEuMjgtMy4xMSA1LjM3IDUuMzcgMCAxIDEgOS0zLjkzWk0xMy4yMyAxNS42N0g4LjQ1Ii8+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNMTMuMjQgMTMuNGgtNC44djQuMTZhLjcuNyAwIDAgMCAuNzEuN2gzLjM4YS43LjcgMCAwIDAgLjcxLS43WiIvPjxwYXRoIGNsYXNzPSJjbHMtMiIgZD0iTTEwLjg0IDguMjFhMS42NSAxLjY1IDAgMSAxIDEuNjQtMS42NSAxLjY1IDEuNjUgMCAwIDEtMS42NCAxLjY1Wk0xMC44NCA4LjY3djQuNjQiLz48L2c+PC9zdmc+)}.scylla-icon--less{background-image:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTciIGhlaWdodD0iMTciIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHJlY3Qgd2lkdGg9IjE3IiBoZWlnaHQ9IjE3IiByeD0iMSIgZmlsbD0iI0IzQkFDNSIvPjxwYXRoIGQ9Ik0xMyA4LjVhMSAxIDAgMCAxLTEgMUg1YTEgMSAwIDAgMSAwLTJoN2ExIDEgMCAwIDEgMSAxWiIgZmlsbD0iI2ZmZiIvPjxwYXRoIGQ9Ik0xMyA4LjVhMSAxIDAgMCAxLTEgMUg1YTEgMSAwIDAgMSAwLTJoN2ExIDEgMCAwIDEgMSAxWiIgZmlsbD0iI2ZmZiIvPjxwYXRoIGQ9Ik0xMyA4LjVhMSAxIDAgMCAxLTEgMUg1YTEgMSAwIDAgMSAwLTJoN2ExIDEgMCAwIDEgMSAxWiIgZmlsbD0iI2ZmZiIvPjxwYXRoIGQ9Ik0xMyA4LjVhMSAxIDAgMCAxLTEgMUg1YTEgMSAwIDAgMSAwLTJoN2ExIDEgMCAwIDEgMSAxWiIgZmlsbD0iI2ZmZiIvPjxwYXRoIGQ9Ik0xMyA4LjVhMSAxIDAgMCAxLTEgMUg1YTEgMSAwIDAgMSAwLTJoN2ExIDEgMCAwIDEgMSAxWiIgZmlsbD0iI2ZmZiIvPjwvc3ZnPg==);filter:none}.scylla-icon--live-test{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtNntmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLW1pdGVybGltaXQ6MTA7c3Ryb2tlLWxpbmVjYXA6cm91bmR9PC9zdHlsZT48L2RlZnM+PGcgaWQ9IkNhbHF1ZV80IiBkYXRhLW5hbWU9IkNhbHF1ZSA0Ij48Y2lyY2xlIGN4PSIxMi41IiBjeT0iMTUiIHI9IjkuNSIgc3R5bGU9InN0cm9rZS13aWR0aDoxLjVweDtzdHJva2UtbWl0ZXJsaW1pdDoxMDtmaWxsOm5vbmU7c3Ryb2tlOmdyYXkiLz48cGF0aCBzdHlsZT0ic3Ryb2tlLXdpZHRoOjEuMXB4O3N0cm9rZS1saW5lam9pbjpyb3VuZDtzdHJva2UtbGluZWNhcDpyb3VuZDtmaWxsOm5vbmU7c3Ryb2tlOmdyYXkiIGQ9Ik0xMCAuNWg1djJoLTV6Ii8+PHBhdGggc3R5bGU9InN0cm9rZS13aWR0aDoxLjExcHg7c3Ryb2tlLWxpbmVqb2luOnJvdW5kO3N0cm9rZS1saW5lY2FwOnJvdW5kO2ZpbGw6bm9uZTtzdHJva2U6Z3JheSIgZD0iTTUuOCA4LjIgNC4xMyA2LjUzbDEuOC0xLjgxTDcuNiA2LjQiLz48cGF0aCBzdHlsZT0ic3Ryb2tlLXdpZHRoOjEuMTNweDtzdHJva2UtbWl0ZXJsaW1pdDoxMDtmaWxsOm5vbmU7c3Ryb2tlOmdyYXkiIGQ9Ik0xMiA2VjIuNSIvPjxwYXRoIHN0eWxlPSJzdHJva2Utd2lkdGg6MS4wOHB4O3N0cm9rZS1taXRlcmxpbWl0OjEwO2ZpbGw6bm9uZTtzdHJva2U6Z3JheSIgZD0iTTEzIDZWMi41Ii8+PHBhdGggY2xhc3M9ImNscy02IiBkPSJNMTIuNSA4LjA2VjEwTTEyLjUgMjAuMDR2MS44OE03LjEzIDEwLjA4bDEuNzkgMS44OE0xNi4wNCAxNy4wOGwyIDEuODhNNyAxOC45MmwxLjg4LTEuODhNMTYuMTMgMTEuOTZsMS43OS0xLjgzIi8+PGVsbGlwc2UgY3g9IjEyLjUiIGN5PSIxNC4zNiIgcng9IjEuNSIgcnk9IjEuMzYiIHN0eWxlPSJmaWxsOmdyYXkiLz48cGF0aCBjbGFzcz0iY2xzLTYiIGQ9Im0xMi42MyAxNC41NCAyLjUgNi4zOCIvPjwvZz48L3N2Zz4=)}.scylla-icon--mail-list{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSJjdXJyZW50Q29sb3IiIHN0cm9rZS13aWR0aD0iMS41IiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiIGNsYXNzPSJmZWF0aGVyIGZlYXRoZXItbWFpbCI+PHBhdGggZD0iTTQgNGgxNmMxLjEgMCAyIC45IDIgMnYxMmMwIDEuMS0uOSAyLTIgMkg0Yy0xLjEgMC0yLS45LTItMlY2YzAtMS4xLjktMiAyLTJ6Ii8+PHBhdGggZD0ibTIyIDYtMTAgN0wyIDYiLz48L3N2Zz4=)}.scylla-icon--manager{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtM3tmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kO3N0cm9rZS13aWR0aDouOTdweH0uY2xzLTR7ZmlsbDpncmF5fTwvc3R5bGU+PC9kZWZzPjxwYXRoIHN0eWxlPSJmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kIiBkPSJNMTggMmg1djIySDNWMmg0LjkyIiBpZD0iQ2FscXVlXzIiIGRhdGEtbmFtZT0iQ2FscXVlIDIiLz48ZyBpZD0iQ2FscXVlXzQiIGRhdGEtbmFtZT0iQ2FscXVlIDQiPjxwYXRoIHN0eWxlPSJzdHJva2Utd2lkdGg6MS4wN3B4O2ZpbGw6bm9uZTtzdHJva2U6Z3JheTtzdHJva2UtbGluZWNhcDpyb3VuZDtzdHJva2UtbGluZWpvaW46cm91bmQiIGQ9Ik04IDBoMTB2NEg4eiIvPjxwYXRoIGNsYXNzPSJjbHMtMyIgZD0iTTcgOWgzdjNIN3pNNyAxNmgzdjNIN3oiLz48cGF0aCBjbGFzcz0iY2xzLTQiIGQ9Ik0xMi41IDkuNWg3djJoLTd6TTEyLjUgMTYuNWg3djJoLTd6Ii8+PC9nPjwvc3ZnPg==)}.scylla-icon--memory-management{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMSwuY2xzLTJ7ZmlsbDpub25lO3N0cm9rZTpncmF5O3N0cm9rZS1saW5lY2FwOnJvdW5kO3N0cm9rZS1saW5lam9pbjpyb3VuZH0uY2xzLTJ7c3Ryb2tlLXdpZHRoOjEuMTNweH08L3N0eWxlPjwvZGVmcz48ZyBpZD0iQ2FscXVlXzQiIGRhdGEtbmFtZT0iQ2FscXVlIDQiPjxyZWN0IGNsYXNzPSJjbHMtMSIgeD0iNS41IiB5PSI1LjUiIHdpZHRoPSIxNSIgaGVpZ2h0PSIxNSIgcng9IjIuNzQiIHJ5PSIyLjc0Ii8+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNOS41IDkuNWg3djdoLTd6Ii8+PHBhdGggY2xhc3M9ImNscy0yIiBkPSJNOC41IDUuNXYtNE0xMS41IDUuNXYtNE0xNC41IDUuNXYtNE0xNy41IDUuNXYtNE04LjUgMjQuNXYtNE0xMS41IDI0LjV2LTRNMTQuNSAyNC41di00TTE3LjUgMjQuNXYtNE0yMC41IDguNWg0TTIwLjUgMTEuNWg0TTIwLjUgMTQuNWg0TTIwLjUgMTcuNWg0TTEuNSA4LjVoNE0xLjUgMTEuNWg0TTEuNSAxNC41aDRNMS41IDE3LjVoNCIvPjwvZz48L3N2Zz4=)}.scylla-icon--monitoring{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGcgZGF0YS1uYW1lPSJDYWxxdWUgNCI+PHBhdGggZD0iTTUuNTUgMTAuODlhMy44MyAzLjgzIDAgMCAxLS4xNS0zLjc2IiBzdHlsZT0ic3Ryb2tlLWxpbmVqb2luOnJvdW5kO3N0cm9rZS1saW5lY2FwOnJvdW5kO3N0cm9rZTpncmF5O2ZpbGw6bm9uZSIvPjxyZWN0IHg9IjE3LjYzIiB5PSIxNC4wMSIgd2lkdGg9IjMuMDUiIGhlaWdodD0iMTAuOCIgcng9Ii41NyIgcnk9Ii41NyIgdHJhbnNmb3JtPSJyb3RhdGUoLTQ1IDE5LjE1OCAxOS40MDUpIiBzdHlsZT0ic3Ryb2tlLW1pdGVybGltaXQ6MTA7ZmlsbDpncmF5O3N0cm9rZS13aWR0aDouOTVweDtzdHJva2U6Z3JheSIvPjxjaXJjbGUgY3g9IjguNSIgY3k9IjkiIHI9IjciIHN0eWxlPSJzdHJva2Utd2lkdGg6MnB4O3N0cm9rZS1taXRlcmxpbWl0OjEwO3N0cm9rZTpncmF5O2ZpbGw6bm9uZSIvPjxwYXRoIHN0eWxlPSJzdHJva2UtbWl0ZXJsaW1pdDoxMDtzdHJva2UtbGluZWNhcDpyb3VuZDtzdHJva2U6Z3JheTtmaWxsOm5vbmUiIGQ9Im0xNi4wNSAxNi4zOS0yLjI4LTIuMjgiLz48L2c+PC9zdmc+)}.scylla-icon--networking{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMntmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLW1pdGVybGltaXQ6MTB9PC9zdHlsZT48L2RlZnM+PGcgaWQ9IkNhbHF1ZV80IiBkYXRhLW5hbWU9IkNhbHF1ZSA0Ij48Y2lyY2xlIGN4PSIxMi41IiBjeT0iMTIuNSIgcj0iNCIgc3R5bGU9InN0cm9rZS13aWR0aDouOTRweDtmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLW1pdGVybGltaXQ6MTAiLz48Y2lyY2xlIGNsYXNzPSJjbHMtMiIgY3g9IjUiIGN5PSIzIiByPSIyLjUiLz48Y2lyY2xlIGNsYXNzPSJjbHMtMiIgY3g9IjE5IiBjeT0iMjAiIHI9IjIuNSIvPjxjaXJjbGUgY2xhc3M9ImNscy0yIiBjeD0iMjIiIGN5PSI2LjYiIHI9IjIuNSIvPjxjaXJjbGUgY2xhc3M9ImNscy0yIiBjeD0iNC41IiBjeT0iMjIiIHI9IjIuNSIvPjxwYXRoIGNsYXNzPSJjbHMtMiIgZD0ibTYuODMgNS41IDMuMjUgNC4zM00yMC4yMyA3Ljg1IDE1LjMzIDExTTkuODMgMTUuMDhsLTQuMDkgNS44NE0xNC41OCAxNS4zM2wzIDMuMDkiLz48Y2lyY2xlIGN4PSIxMi41IiBjeT0iMTIuNSIgcj0iMS41IiBzdHlsZT0iZmlsbDpncmF5Ii8+PC9nPjwvc3ZnPg==)}.scylla-icon--news{background-image:url(data:image/svg+xml;base64,PHN2ZyBpZD0iQ2FscXVlXzEiIGRhdGEtbmFtZT0iQ2FscXVlIDEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmlld0JveD0iMCAwIDI1IDI1Ij48ZGVmcz48c3R5bGU+LmNscy0xe2ZpbGw6bm9uZTtzdHJva2U6Z3JheTtzdHJva2UtbGluZWNhcDpyb3VuZDtzdHJva2UtbGluZWpvaW46cm91bmR9PC9zdHlsZT48L2RlZnM+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNMyAxNS4xNyAxNi4zMSAzLjgyYTEuNDggMS40OCAwIDAgMSAyLjIyLjQ2bDUuMTUgOS42NWExLjQ2IDEuNDYgMCAwIDEtLjkzIDIuMTJMNS42OSAxOS45Wk04LjcxIDE5LjMzbC43NiAyLjIyYTEuNTEgMS41MSAwIDAgMCAxLjg1IDFsMy41OC0xLjA2YTEuNSAxLjUgMCAwIDAgMS0xLjg2TDE1LjQ1IDE4TTUuNTQgMjBsLTEuODMgMWEuOTIuOTIgMCAwIDEtMS4yNS0uMzdMLjYxIDE3LjQ5QS45Mi45MiAwIDAgMSAxIDE2LjI0bDEuODMtMU04LjUgMTRsNy4zOC01LjUiLz48L3N2Zz4=)}.scylla-icon--newsletter{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMSwuY2xzLTJ7ZmlsbDpub25lO3N0cm9rZTpncmF5O3N0cm9rZS1taXRlcmxpbWl0OjEwfS5jbHMtMntzdHJva2UtbGluZWNhcDpyb3VuZH08L3N0eWxlPjwvZGVmcz48ZyBpZD0iQ2FscXVlXzQiIGRhdGEtbmFtZT0iQ2FscXVlIDQiPjxwYXRoIGNsYXNzPSJjbHMtMSIgZD0iTTE5LjUgOS41aDN2MTJoLTIwdi0xMmgzIi8+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJtMi42NSA5Ljg0IDkuODUgNi44OCA4LjYzLTYuODgiLz48cGF0aCBjbGFzcz0iY2xzLTIiIGQ9Im01LjUgNy41LTMgMk0xNC4zNSAzLjg2bC0xLjQ2LTEuMDktMS40NyAxLjA5TTIxLjUgOS41bC0yLTJNMTkuNSAxMS41di03aC0xNHY3LjQ3Ii8+PC9nPjwvc3ZnPg==)}.scylla-icon--nsql-guides{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGcgZGF0YS1uYW1lPSJDYWxxdWUgNCI+PHJlY3QgeD0iNC4zNyIgeT0iMTMuNzEiIHdpZHRoPSIxLjE1IiBoZWlnaHQ9IjkuNzIiIHJ4PSIuNTQiIHJ5PSIuNTQiIHRyYW5zZm9ybT0icm90YXRlKDQ1IDQuOTQ4IDE4LjU3KSIgc3R5bGU9InN0cm9rZTpncmF5O3N0cm9rZS1taXRlcmxpbWl0OjEwO2ZpbGw6Z3JheTtzdHJva2Utd2lkdGg6MS4wOXB4Ii8+PGNpcmNsZSBjeD0iMTIuMjUiIGN5PSIxMi4yNSIgcj0iNC43NSIgc3R5bGU9InN0cm9rZS13aWR0aDoxLjVweDtmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLW1pdGVybGltaXQ6MTAiLz48cGF0aCBzdHlsZT0ic3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLXdpZHRoOjEuMDZweDtmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLW1pdGVybGltaXQ6MTAiIGQ9Ik04LjUgMjAuNXYzaDE1di0yMWgtMTV2MiIvPjwvZz48L3N2Zz4=)}.scylla-icon--open-source{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfS5jbHMtMntmaWxsOmdyYXl9PC9zdHlsZT48L2RlZnM+PGcgaWQ9IkNhbHF1ZV80IiBkYXRhLW5hbWU9IkNhbHF1ZSA0Ij48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Ik0uMzEgMjEuNTEgNSAxOS42OWEyLjM3IDIuMzcgMCAwIDEgMS44OC4xOWw1LjI0IDEuNjhhMi4yMyAyLjIzIDAgMCAwIDItLjEybDkuNS00Ljc1Yy44LS40NCAxLjY0LTEuMzEgMS4xMy0xLjkxYTIuMzQgMi4zNCAwIDAgMC0yLjY0LS40MkwxOCAxNi4wOSIvPjxwYXRoIGNsYXNzPSJjbHMtMSIgZD0ibS4yNSAxNS42OSA0Ljg4LTEuMjFjMS4yNS0uMyAyLjE3LS42MyAzLjQ0LS4xM2ExNS4yMSAxNS4yMSAwIDAgMCA0IDEuMWg0LjUyYy44NSAwIC45NS41NC45NSAxLjEzYTEgMSAwIDAgMS0xLjA4IDEgNjUuODYgNjUuODYgMCAwIDEtNy0uMzEiLz48cGF0aCBjbGFzcz0iY2xzLTIiIGQ9Ik04LjU2IDkuNjh2LS44MWMwLS45MS0uMzgtMS4yMS0xLjI5LTEuMjFIN1Y2LjNoLjMxYy45MSAwIDEuMjktLjMgMS4yOS0xLjIxdi0uODFjMC0xLjIuNjYtMS45MiAyLjgyLTIuM3YxLjE2Yy0xLjI0LjM1LTEuNDMuNjgtMS40MyAxLjR2Ljg3QTEuNTIgMS41MiAwIDAgMSA4Ljc1IDcgMS41MiAxLjUyIDAgMCAxIDEwIDguNTZ2Ljg3YzAgLjcxLjE5IDEgMS40MyAxLjRWMTJjLTIuMjEtLjM1LTIuODctMS4xMi0yLjg3LTIuMzJaTTE3LjQzIDQuM3YuODFjMCAuOTEuMzcgMS4yMSAxLjI5IDEuMjFIMTl2MS4zNmgtLjMxYy0uOTIgMC0xLjI5LjMtMS4yOSAxLjIxdi44MWMwIDEuMi0uNjUgMi0yLjgxIDIuMzV2LTEuMmMxLjI1LS4zNiAxLjQ0LS42OSAxLjQ0LTEuNHYtLjg3QTEuNTMgMS41MyAwIDAgMSAxNy4yNSA3IDEuNTMgMS41MyAwIDAgMSAxNiA1LjQzdi0uODdjMC0uNzItLjE5LTEtMS40NC0xLjRWMmMyLjIyLjM4IDIuODcgMS4xIDIuODcgMi4zWiIvPjwvZz48L3N2Zz4=)}.scylla-icon--operator{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjQuODEgMS4wMSAyOC4zMiAyNy42NCI+PHBhdGggZD0iTTMyLjUyIDE4cy0uMDkgMC0uMDktLjA1LS4wOCAwLS4xNyAwYTIuMTkgMi4xOSAwIDAgMC0uNTEgMCAuNDcuNDcgMCAwIDEtLjI2LS4wNSA5LjI5IDkuMjkgMCAwIDEtMS40OS0uMzIuNTQuNTQgMCAwIDEtLjMtLjMxbC0uMzQtLjA4YTExLjI1IDExLjI1IDAgMCAwLS4xOC0zLjc5IDExLjU1IDExLjU1IDAgMCAwLTEuNS0zLjUybC4yNi0uMjZhLjU5LjU5IDAgMCAxIC4xMy0uMzkgNy43MyA3LjczIDAgMCAxIDEuMi0uODZsLjI2LS4xMy40Ny0uM3MuMDkgMCAuMTMtLjA4IDAtLjA1IDAtLjA5YS44NC44NCAwIDAgMCAuMTctMS4yLjc4Ljc4IDAgMCAwLS42LS4zIDEgMSAwIDAgMC0uNi4yMWMtLjA1LjA1LS4wOS4wOS0uMTMuMDlhMy4wOCAzLjA4IDAgMCAwLS4zNS4zOWMwIC4wOC0uMTMuMTMtLjE3LjE3YTUuNjQgNS42NCAwIDAgMS0xLjA3Ljk0LjU4LjU4IDAgMCAxLS4yNi4wOS4yNS4yNSAwIDAgMS0uMTcgMGgtLjA1bC0uMzQuMjEtMS4wOC0xYTExIDExIDAgMCAwLTUuNjUtMi4yN3YtLjM0YS42LjYgMCAwIDEtLjIyLS4zNEE4LjE4IDguMTggMCAwIDEgMTkuNjYgM3YtLjI1YzAtLjA4LjA1LS4zNS4wOS0uNTJ2LS4zMWEuODIuODIgMCAwIDAtMS40Ni0uNi44Ni44NiAwIDAgMC0uMjYuNnYuMjJhMS44MiAxLjgyIDAgMCAwIC4wOS41MS41OS41OSAwIDAgMSAwIC4yNlYzYTguODIgOC44MiAwIDAgMSAuMDggMS40Ny41OS41OSAwIDAgMS0uMjEuMzRWNS4yNGMtLjQ4IDAtMSAuMTMtMS40Ny4yMmExMC4xNiAxMC4xNiAwIDAgMC01LjI4IDNMMTEgOC4yNGgtLjE3YS43My43MyAwIDAgMS0uMjYtLjA5IDcuOCA3LjggMCAwIDEtMS4wNy0xYzAtLjA4LS4xMy0uMTMtLjE3LS4xN3MtLjI1LS4yLS4zMy0uMzMtLjA4IDAtLjEzLS4wOHYtLjA1YTEgMSAwIDAgMC0uNi0uMjEuNjQuNjQgMCAwIDAtLjYuMy45MS45MSAwIDAgMCAuMTcgMS4yczAgLjA1IDAgLjA1LjA5LjA4LjEzLjA4YTUgNSAwIDAgMCAuNDcuMjZsLjI2LjEzYTYuNjEgNi42MSAwIDAgMSAxLjIxLjg2LjQ3LjQ3IDAgMCAxIC4xMy4zOXYtLjA1bC4yNS4yNmEyLjUzIDIuNTMgMCAwIDEtLjEzLjIyIDEwLjIgMTAuMiAwIDAgMC0xLjUgN2wtLjM1LjA5YzAgLjEzLS4xNy4yMS0uMy4zYTguNTYgOC41NiAwIDAgMS0xLjQ2LjI2LjU5LjU5IDAgMCAwLS4yNiAwaC0uNTJjLS4xOCAwLS4wOC4wNS0uMTcuMDVoLS4wOGEuODQuODQgMCAwIDAtLjY5IDEgLjc5Ljc5IDAgMCAwIC44Ni42LjM5LjM5IDAgMCAwIC4yMSAwSDYuMTJhMy42MSAzLjYxIDAgMCAwIC40Ny0uMTcuNjUuNjUgMCAwIDEgLjI2LS4wOCA3LjY1IDcuNjUgMCAwIDEgMS40Mi0uMzkuNDkuNDkgMCAwIDEgLjM1LjEzaC4zOWExMC4zMiAxMC4zMiAwIDAgMCAzLjUzIDUgNi4zMSA2LjMxIDAgMCAwIDEuMTYuNzdsLS4yMi4zYS41MS41MSAwIDAgMSAwIC40MyA2LjU0IDYuNTQgMCAwIDEtLjY5IDEuMjR2LjA1YS43OC43OCAwIDAgMS0uMTcuMjFjLS4wOS4wOS0uMTcuMjYtLjMuNDNzMCAuMDktLjA5LjEzIDAgLjA1IDAgLjA1YS44OC44OCAwIDAgMCAuMzQgMS4xNi45LjkgMCAwIDAgLjMuMDggMSAxIDAgMCAwIC44Mi0uNTFzMC0uMDguMDktLjEzLjEzLS4zLjE3LS40N2wuMDktLjI2YTcuMDcgNy4wNyAwIDAgMSAuNTYtMS4zMy42Mi42MiAwIDAgMSAuMzQtLjI2bC4xNy0uMzVhMTAuMDUgMTAuMDUgMCAwIDAgMy43NS42OSA4LjQ1IDguNDUgMCAwIDAgMi4zMi0uMyAxMS40NiAxMS40NiAwIDAgMCAxLjM3LS4zOWwuMTguMzFhLjYyLjYyIDAgMCAxIC4zNC4yNiA3LjA3IDcuMDcgMCAwIDEgLjU2IDEuMzNsLjA5LjI2YTEuMzEgMS4zMSAwIDAgMCAuMTcuNDdjMCAuMDUgMCAuMDkuMDkuMTNhMSAxIDAgMCAwIC44Mi41MSAxLjA1IDEuMDUgMCAwIDAgLjM0LS4wOC43Ni43NiAwIDAgMCAuMzktLjQ4IDEuMDggMS4wOCAwIDAgMC0uMDUtLjY0LjIuMiAwIDAgMC0uMDgtLjEzIDEuNTMgMS41MyAwIDAgMC0uMzEtLjQzLjY1LjY1IDAgMCAwLS4xNy0uMjJ2LS4wOWE1LjIyIDUuMjIgMCAwIDEtLjY5LTEuMjQuNTEuNTEgMCAwIDEgLjA1LS40M2wtLjEzLS4zNEExMC42OCAxMC42OCAwIDAgMCAyOSAxOC44MmwuMzQuMDV2LS4wNWEuNTQuNTQgMCAwIDEgLjM1LS4xMyA3LjgyIDcuODIgMCAwIDEgMS4zOC4zOS42Mi42MiAwIDAgMCAuMjYuMDkgMi40MiAyLjQyIDAgMCAwIC40Ny4yMXMuMDkgMCAuMTcgMGguMDlhLjM5LjM5IDAgMCAwIC4yMSAwIC45NC45NCAwIDAgMCAuODYtLjYgMSAxIDAgMCAwLS43Ny0uOVptLTEyLjQzLTEuMzMtMS4xNi41Ni0xLjE2LS41Ni0uMy0xLjI1LjgxLTFoMS4yOWwuODIgMVptNy0yLjc5YTggOCAwIDAgMSAuMTcgMi43MWwtNC4xNS0uNzVjLS4zOC0uMDgtLjY4LS45LS43MS0xLjIyYTQgNCAwIDAgMSAuMjEtLjc0bDMuNDUtMi41NGE4LjU4IDguNTggMCAwIDEgMS4wNCAyLjU0Wm0tMi4zMS00LjEzLTMuMjIgMi42OWExLjI4IDEuMjggMCAwIDEtMS4yNS0uMzdjLS4wOS0uMDktLjM3LS4yNS0uMzctLjM4VjcuNDNhOC4wNyA4LjA3IDAgMCAxIDQuODYgMi4zMlpNMTcgNy41NmwxLS4xOC0uMDYgNC4zMWMwIC4zOC0uNjQuNjgtMSAuNjhhMS4xMSAxLjExIDAgMCAxLS4zNS0uMDhMMTMgOS43NWE4LjQxIDguNDEgMCAwIDEgNC0yLjE5Wm0tNS4yNCAzLjc4IDMuMzcgMi40Ny4zMi41M2ExLjE0IDEuMTQgMCAwIDEtLjI1IDEgLjc4Ljc4IDAgMCAxLS4zOC4zMWwtNC4zMS45YTkgOSAwIDAgMSAxLjI0LTUuMjFaTTExIDE4LjYxbDQuMS0xLjIzYy4zNSAwIC44NC43MS44OSAxLjA2YS41MS41MSAwIDAgMS0uMDUuNDNsLTEuNjMgMy45NUE4LjQxIDguNDEgMCAwIDEgMTEgMTguNjFabTkuNzYgNS4zM2E4LjY3IDguNjcgMCAwIDEtMS44NS4yMSA5LjU5IDkuNTkgMCAwIDEtMi43MS0uNDNsMS42Ni00Yy4yMS0uMjYgMS0uMiAxLjMxIDBhMi40OCAyLjQ4IDAgMCAxIC4zNC4zbDIuMDcgMy43NGE1LjcyIDUuNzIgMCAwIDAtLjguMThaTTI2IDIwLjJhOC4zNiA4LjM2IDAgMCAxLTIuNTggMi41OGwtMS45Mi0zLjcyYTEuMTUgMS4xNSAwIDAgMSAuNDEtMWMuMjEtLjI1LjU5LS41OS43MS0uNTlsNC4yMiAxLjA2QTYuMjcgNi4yNyAwIDAgMSAyNiAyMC4yWiIgc3R5bGU9ImZpbGw6IzRkNGQ0ZCIgZGF0YS1uYW1lPSJDYWxxdWUgMiIvPjwvc3ZnPg==)}.scylla-icon--overview{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJDYWxxdWVfNCIgZGF0YS1uYW1lPSJDYWxxdWUgNCI+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNMjIuNjEgMy40NUMyMi42MSA1LjA2IDE4IDYuNSAxMi41IDYuNXMtMTAtMS40NC0xMC0zIDQuNS0zIDEwLTMgMTAuMTEgMS4zMyAxMC4xMSAyLjk1Wk0yMi42MSA5LjQ0YzAgMS42MS00LjY0IDMuMDYtMTAuMTEgMy4wNnMtMTAtMS40NS0xMC0zLjA2TTIyLjYxIDE1LjUxYzAgMS42Mi00LjY0IDMtMTAuMTEgM3MtMTAtMS4zNy0xMC0zTTIyLjYxIDIxLjU5YzAgMS42Mi00LjY0IDIuOTEtMTAuMTEgMi45MXMtMTAtMS4yOS0xMC0yLjkxTTIuNSAyMS40N1YzLjQ1TTIyLjUgMjEuNDdWMy40NSIvPjwvZz48L3N2Zz4=)}.scylla-icon--partners{background-image:url(data:image/svg+xml;base64,PHN2ZyBpZD0iQ2FscXVlXzEiIGRhdGEtbmFtZT0iQ2FscXVlIDEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmlld0JveD0iMCAwIDI1IDI1Ij48ZGVmcz48c3R5bGU+LmNscy0xe2ZpbGw6bm9uZTtzdHJva2U6Z3JheTtzdHJva2UtbGluZWNhcDpyb3VuZDtzdHJva2UtbGluZWpvaW46cm91bmR9PC9zdHlsZT48L2RlZnM+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNMTguNSA4LjI2aC00LjcybC0xLjIzIDEuMjdNMi4zOSAxNS4wOS4xNSAxMy43NGw0Ljg3LTguNDIgMi4yNCAxLjM0LTQuODcgOC40M3pNMjIuNTkgMTUuMDlsMi4yNC0xLjM1LTQuODYtOC40Mi0yLjI0IDEuMzQgNC44NiA4LjQzek0xMC43MSAxNS4yNmwtMi45MyAyLjIxTTEyLjE4IDE2LjRsLTIuOTMgMi4yMU0xMy42OCAxNy41M2wtMi45MyAyLjIyIi8+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNNi4zOCA4LjNoMy43OGEyLjI3IDIuMjcgMCAwIDEgMS4zNy40N2MxLjI2IDEgNC4wOSAzLjE4IDQuNDggMy41NnMtMS4xNCAxLjY4LTIuMjcgMS4xYTE4LjM0IDE4LjM0IDAgMCAwLTIuMTEtLjkyLjU3LjU3IDAgMCAwLS41Ni4wOWwtNC43OSAzLjg5TDEyLjMzIDIxbDkuNDYtNy4wOU0zLjI0IDE0LjIybDMuNCAxLjg1Ii8+PC9zdmc+)}.scylla-icon--plus{background-image:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTciIGhlaWdodD0iMTciIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHJlY3Qgd2lkdGg9IjE3IiBoZWlnaHQ9IjE3IiByeD0iMSIgZmlsbD0iI0IzQkFDNSIvPjxwYXRoIGZpbGwtcnVsZT0iZXZlbm9kZCIgY2xpcC1ydWxlPSJldmVub2RkIiBkPSJNOS41IDVhMSAxIDAgMSAwLTIgMHYyLjVINWExIDEgMCAxIDAgMCAyaDIuNVYxMmExIDEgMCAxIDAgMiAwVjkuNUgxMmExIDEgMCAxIDAgMC0ySDkuNVY1WiIgZmlsbD0iI2ZmZiIvPjxwYXRoIGZpbGwtcnVsZT0iZXZlbm9kZCIgY2xpcC1ydWxlPSJldmVub2RkIiBkPSJNOS41IDVhMSAxIDAgMSAwLTIgMHYyLjVINWExIDEgMCAxIDAgMCAyaDIuNVYxMmExIDEgMCAxIDAgMiAwVjkuNUgxMmExIDEgMCAxIDAgMC0ySDkuNVY1WiIgZmlsbD0iI2ZmZiIvPjxwYXRoIGZpbGwtcnVsZT0iZXZlbm9kZCIgY2xpcC1ydWxlPSJldmVub2RkIiBkPSJNOS41IDVhMSAxIDAgMSAwLTIgMHYyLjVINWExIDEgMCAxIDAgMCAyaDIuNVYxMmExIDEgMCAxIDAgMiAwVjkuNUgxMmExIDEgMCAxIDAgMC0ySDkuNVY1WiIgZmlsbD0iI2ZmZiIvPjxwYXRoIGZpbGwtcnVsZT0iZXZlbm9kZCIgY2xpcC1ydWxlPSJldmVub2RkIiBkPSJNOS41IDVhMSAxIDAgMSAwLTIgMHYyLjVINWExIDEgMCAxIDAgMCAyaDIuNVYxMmExIDEgMCAxIDAgMiAwVjkuNUgxMmExIDEgMCAxIDAgMC0ySDkuNVY1WiIgZmlsbD0iI2ZmZiIvPjxwYXRoIGZpbGwtcnVsZT0iZXZlbm9kZCIgY2xpcC1ydWxlPSJldmVub2RkIiBkPSJNOS41IDVhMSAxIDAgMSAwLTIgMHYyLjVINWExIDEgMCAxIDAgMCAyaDIuNVYxMmExIDEgMCAxIDAgMiAwVjkuNUgxMmExIDEgMCAxIDAgMC0ySDkuNVY1WiIgZmlsbD0iI2ZmZiIvPjwvc3ZnPg==);filter:none}.scylla-icon--pricing{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJDYWxxdWVfMiIgZGF0YS1uYW1lPSJDYWxxdWUgMiI+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJtMjEuNzMgNy0yLjQxLTUuMTJhMi41MiAyLjUyIDAgMCAwLTIuODItMWwtNi4wOCAyLjA0QTEuNjkgMS42OSAwIDAgMCA5LjUxIDRMMy45MyAxOS4yOWExLjA2IDEuMDYgMCAwIDAgLjY0IDEuMTdsMTAuMzQgMy43NmExIDEgMCAwIDAgMS4yMi0uNDNsNS41OC0xNS4zM0ExLjg3IDEuODcgMCAwIDAgMjEuNzMgN1oiLz48Y2lyY2xlIGNsYXNzPSJjbHMtMSIgY3g9IjE1LjczIiBjeT0iNS44OSIgcj0iMiIvPjx0ZXh0IHRyYW5zZm9ybT0icm90YXRlKDIwIC00OC4yNDQgMzAuNjcpIiBzdHlsZT0iZm9udC1zaXplOjEycHg7ZmlsbDpncmF5O2ZvbnQtZmFtaWx5OlJvYm90by1NZWRpdW0sUm9ib3RvIj4kPC90ZXh0PjwvZz48L3N2Zz4=)}.scylla-icon--release-note{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMntmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kO3N0cm9rZS13aWR0aDouOTFweH08L3N0eWxlPjwvZGVmcz48ZyBpZD0iQ2FscXVlXzIiIGRhdGEtbmFtZT0iQ2FscXVlIDIiPjxwYXRoIHN0eWxlPSJzdHJva2Utd2lkdGg6LjlweDtmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kIiBkPSJNMjEuNSAyNC41aC0xN1Y1LjdMOC45NS41NCAyMS41LjV2MjR6Ii8+PHBhdGggY2xhc3M9ImNscy0yIiBkPSJNNC42NSA1LjVIOS41VjFNNy41IDguNWgxMU03LjUgMTEuNWgxMU03LjUgMTQuNWgxMU03LjUgMTcuNWgxMU03LjUgMjAuNWgxMSIvPjwvZz48L3N2Zz4=)}.scylla-icon--resource-center{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfS5jbHMtMntmaWxsOmdyYXl9PC9zdHlsZT48L2RlZnM+PGcgaWQ9IkNhbHF1ZV80IiBkYXRhLW5hbWU9IkNhbHF1ZSA0Ij48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Ik01LjUgMi41aDYuOTFsLjA5IDIwaC03di0yMHoiLz48cGF0aCBjbGFzcz0iY2xzLTIiIGQ9Ik04IDRoMnYxMC45N0w4IDE1VjR6Ii8+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNNS4zNiAyLjI5IDIuNSAzLjV2MThsMi43OSAxLjE0Ii8+PHBhdGggc3R5bGU9InN0cm9rZS13aWR0aDouNjhweDtmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kIiBkPSJtMTIuNTcgMjEuODYgMS41Ny43NSIvPjxwYXRoIHN0eWxlPSJzdHJva2Utd2lkdGg6Ljg1cHg7ZmlsbDpub25lO3N0cm9rZTpncmF5O3N0cm9rZS1saW5lY2FwOnJvdW5kO3N0cm9rZS1saW5lam9pbjpyb3VuZCIgZD0ibTE0LjExIDIuNS0xLjU0LjU3Ii8+PGNpcmNsZSBjbGFzcz0iY2xzLTIiIGN4PSI5IiBjeT0iMTkiIHI9IjEiLz48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Ik0xNC41IDIuNWg2Ljk0bC4wNiAyMGgtN3YtMjB6Ii8+PHBhdGggY2xhc3M9ImNscy0yIiBkPSJNMTcgNGgydjEwLjk3TDE3IDE1VjR6Ii8+PGNpcmNsZSBjbGFzcz0iY2xzLTIiIGN4PSIxOCIgY3k9IjE5IiByPSIxIi8+PHBhdGggY2xhc3M9ImNscy0yIiBkPSJNMTIuNiAyLjczaDEuNjdWMjIuNkgxMi42ek0yLjU4IDIxLjVsMi43NSAxLjFWMi43M2wtMi42Ni45NC0uMDkgMTcuODN6Ii8+PC9nPjwvc3ZnPg==)}.scylla-icon--roadmap{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMSwuY2xzLTJ7ZmlsbDpub25lO3N0cm9rZTpncmF5fS5jbHMtMXtzdHJva2UtbGluZWNhcDpyb3VuZDtzdHJva2UtbGluZWpvaW46cm91bmQ7c3Ryb2tlLXdpZHRoOi45OHB4fS5jbHMtMntzdHJva2UtbWl0ZXJsaW1pdDoxMH0uY2xzLTN7ZmlsbDpncmF5fTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJDYWxxdWVfNCIgZGF0YS1uYW1lPSJDYWxxdWUgNCI+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJtLjUgNC41IDgtMyA4IDQgOC0zdjE3bC04IDMtOC00LTggM3YtMTd6TTguNSAxLjVWMThNMTYuNSA1LjVWMjIiLz48cGF0aCBjbGFzcz0iY2xzLTIiIGQ9Ik0yLjUgMTMgNyAxNi41TTcgMTJsLTQuNSA1LjVNMTguNSA4bDQuNSAzLjVNMjMgN2wtNC41IDUuNSIvPjxwYXRoIGNsYXNzPSJjbHMtMyIgZD0iTTEwIDEzaDF2MWgtMXpNMTIgMTJoMXYxaC0xek0xNCAxMWgxdjFoLTF6Ii8+PC9nPjwvc3ZnPg==)}.scylla-icon--search{background-image:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZD0iTTEwLjUgMThhNy41IDcuNSAwIDEgMCAwLTE1IDcuNSA3LjUgMCAwIDAgMCAxNVpNMjEgMjFsLTUuMi01LjIiIHN0cm9rZT0iIzAwMCIgc3Ryb2tlLXdpZHRoPSIyIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiLz48L3N2Zz4=)}.scylla-icon--slack{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0NDggNTEyIj48IS0tISBGb250IEF3ZXNvbWUgUHJvIDYuMC4wIGJ5IEBmb250YXdlc29tZSAtIGh0dHBzOi8vZm9udGF3ZXNvbWUuY29tIExpY2Vuc2UgLSBodHRwczovL2ZvbnRhd2Vzb21lLmNvbS9saWNlbnNlIChDb21tZXJjaWFsIExpY2Vuc2UpIENvcHlyaWdodCAyMDIyIEZvbnRpY29ucywgSW5jLi0tPjxwYXRoIGQ9Ik05NC4xMiAzMTUuMWMwIDI1LjktMjEuMTYgNDcuMDYtNDcuMDYgNDcuMDZTMCAzNDEgMCAzMTUuMWMwLTI1LjkgMjEuMTYtNDcuMDYgNDcuMDYtNDcuMDZoNDcuMDZ2NDcuMDZ6bTIzLjcyIDBjMC0yNS45IDIxLjE2LTQ3LjA2IDQ3LjA2LTQ3LjA2czQ3LjA2IDIxLjE2IDQ3LjA2IDQ3LjA2djExNy44NGMwIDI1LjktMjEuMTYgNDcuMDYtNDcuMDYgNDcuMDZzLTQ3LjA2LTIxLjE2LTQ3LjA2LTQ3LjA2VjMxNS4xem00Ny4wNi0xODguOThjLTI1LjkgMC00Ny4wNi0yMS4xNi00Ny4wNi00Ny4wNlMxMzkgMzIgMTY0LjkgMzJzNDcuMDYgMjEuMTYgNDcuMDYgNDcuMDZ2NDcuMDZIMTY0Ljl6bTAgMjMuNzJjMjUuOSAwIDQ3LjA2IDIxLjE2IDQ3LjA2IDQ3LjA2cy0yMS4xNiA0Ny4wNi00Ny4wNiA0Ny4wNkg0Ny4wNkMyMS4xNiAyNDMuOTYgMCAyMjIuOCAwIDE5Ni45czIxLjE2LTQ3LjA2IDQ3LjA2LTQ3LjA2SDE2NC45em0xODguOTggNDcuMDZjMC0yNS45IDIxLjE2LTQ3LjA2IDQ3LjA2LTQ3LjA2IDI1LjkgMCA0Ny4wNiAyMS4xNiA0Ny4wNiA0Ny4wNnMtMjEuMTYgNDcuMDYtNDcuMDYgNDcuMDZoLTQ3LjA2VjE5Ni45em0tMjMuNzIgMGMwIDI1LjktMjEuMTYgNDcuMDYtNDcuMDYgNDcuMDYtMjUuOSAwLTQ3LjA2LTIxLjE2LTQ3LjA2LTQ3LjA2Vjc5LjA2YzAtMjUuOSAyMS4xNi00Ny4wNiA0Ny4wNi00Ny4wNiAyNS45IDAgNDcuMDYgMjEuMTYgNDcuMDYgNDcuMDZWMTk2Ljl6TTI4My4xIDM4NS44OGMyNS45IDAgNDcuMDYgMjEuMTYgNDcuMDYgNDcuMDYgMCAyNS45LTIxLjE2IDQ3LjA2LTQ3LjA2IDQ3LjA2LTI1LjkgMC00Ny4wNi0yMS4xNi00Ny4wNi00Ny4wNnYtNDcuMDZoNDcuMDZ6bTAtMjMuNzJjLTI1LjkgMC00Ny4wNi0yMS4xNi00Ny4wNi00Ny4wNiAwLTI1LjkgMjEuMTYtNDcuMDYgNDcuMDYtNDcuMDZoMTE3Ljg0YzI1LjkgMCA0Ny4wNiAyMS4xNiA0Ny4wNiA0Ny4wNiAwIDI1LjktMjEuMTYgNDcuMDYtNDcuMDYgNDcuMDZIMjgzLjF6Ii8+PC9zdmc+)}.scylla-icon--stack-overflow{background-image:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjQiIGhlaWdodD0iMzEiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Im0yMS45NDkuMTEzIDIuMDQzIDExLjY3LTIuNTE0LjQzMkwxOS40MzUuNTQ1IDIxLjk1LjExNFptLTE3Ljk3MyAyNiAxMS45NDUtLjAwNS0uMDAyLTIuNTMtMTEuOTQ0LjAwNi4wMDEgMi41M1ptMTIuMjMyLTUuNzc3TDQuMzE1IDE5LjI1bC0uMjM1IDIuNTIgMTEuODk0IDEuMDg1LjIzNC0yLjUxOVptLTEwLjc1LTYuMzc1IDExLjUzNSAzLjA3NC0uNjYyIDIuNDQzLTExLjUzNS0zLjA3NS42NjItMi40NDJabTEzLjA0LjE4TDguMjEyIDguMTI2bC0xLjI5NyAyLjE3OCAxMC4yODkgNi4wMTcgMS4yOTYtMi4xNzhabS00LjIwNi0xMS41NiA2LjczIDkuNzg3LTIuMTA4IDEuNDI0LTYuNzMtOS43ODUgMi4xMDgtMS40MjVaIiBmaWxsPSIjMDAwIi8+PHBhdGggZD0iTTE3Ljk1IDE3Ljc4OVYyOC4xM0gyLjI4MlYxNy43ODlILjI0M3YxMi4zMjZIMTkuOThWMTcuNzg5aC0yLjAzWiIgZmlsbD0iIzAwMCIvPjwvc3ZnPg==)}.scylla-icon--summit{background-image:url(data:image/svg+xml;base64,PHN2ZyBpZD0iQ2FscXVlXzEiIGRhdGEtbmFtZT0iQ2FscXVlIDEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmlld0JveD0iMCAwIDI1IDI1Ij48ZGVmcz48c3R5bGU+LmNscy0xe2ZpbGw6bm9uZTtzdHJva2U6IzRkNGQ0ZDtzdHJva2UtbGluZWNhcDpyb3VuZDtzdHJva2UtbGluZWpvaW46cm91bmR9PC9zdHlsZT48L2RlZnM+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJtMTYuNSAyMiAxLTYuNS0xMCAuMDMgMSA2LjQzIi8+PHBhdGggZD0iTTMuNDYgMTJBNS42OSA1LjY5IDAgMCAxIDUgNy41IiBzdHlsZT0ic3Ryb2tlLXdpZHRoOjEuMXB4O3N0cm9rZTojNGQ0ZDRkO3N0cm9rZS1saW5lY2FwOnJvdW5kO3N0cm9rZS1saW5lam9pbjpyb3VuZDtmaWxsOm5vbmUiLz48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Ik0xNC42MiA1YTIuMzMgMi4zMyAwIDAgMS0yLjI1IDIuNWMtMS4zMyAwLTItMS4xMi0xLjk1LTIuNDRzLjctMi41IDItMi40OEEyLjI3IDIuMjcgMCAwIDEgMTQuNjIgNVpNMTcuNTggMTJhMy4yMyAzLjIzIDAgMCAwLTMuNDYtMy41SDExQTMuMjYgMy4yNiAwIDAgMCA3LjUgMTIiLz48Y2lyY2xlIGN4PSI0Ljk0IiBjeT0iNi45NiIgcj0iMS4wMSIgc3R5bGU9ImZpbGw6IzRkNGQ0ZDtzdHJva2Utd2lkdGg6MS4xcHg7c3Ryb2tlOiM0ZDRkNGQ7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kIi8+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNNy41NCAxOC41SDQuNWwtMi02aDIwbC0yIDZoLTMiLz48L3N2Zz4=)}.scylla-icon--support{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJDYWxxdWVfNCIgZGF0YS1uYW1lPSJDYWxxdWUgNCI+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNMTguMTkgNy41YTEwIDEwIDAgMCAxIC4yMSAyLjA3YzAgNC4zNi0yLjYzIDYuOTMtNS45IDYuOTNzLTUuOTQtMi41Ny01Ljk0LTYuOTNhMTAuNTEgMTAuNTEgMCAwIDEgLjIyLTIuMTIiLz48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Ik03LjY3IDIuMjNBNi41OCA2LjU4IDAgMCAxIDEyLjUuNWE1LjY1IDUuNjUgMCAwIDEgNC4yOSAxLjdjMS45MyAxLjk0IDIuMzUgNS4wNyAyLjQzIDYuNzJhMS40OSAxLjQ5IDAgMCAwLS43OS4wNSA4LjY4IDguNjggMCAwIDAtLjA4LTEuMTZoMGE1LjUzIDUuNTMgMCAwIDEtMS43Ny0yLjM0TDE2LjQ5IDVsLS4zOC4yMkExOSAxOSAwIDAgMSA2LjggNy4zOGEuNTIuNTIgMCAwIDAtLjQyLjE2Yy0uMjMuMjQtLjE1LjY1LS4wNyAxLjA4IDAgLjExIDAgLjIyLjA1LjMyYTEuNCAxLjQgMCAwIDAtLjU4IDBjLS4xLTEuNDUtLjA2LTQuNjggMS44OS02LjcxWk02LjM4IDljLS42NS0uMDgtMSAuMS0xLjE0Ljc5YTIuMDYgMi4wNiAwIDAgMCAxLjM3IDIuMjlNMTguNTYgOWMuNjUtLjA4IDEuMDUuMSAxLjE0Ljc5YTIuMDYgMi4wNiAwIDAgMS0xLjM3IDIuMjlNOS41IDE4LjIzVjE1LjVNMTUuNSAxNS41djIuNzNNMi41IDI0LjE2Yy4yNC0yIC41OS0zLjYzIDIuNDMtNC40OWEyNC4yOSAyNC4yOSAwIDAgMSA0LjgyLTEuMzdNMjIuNSAyNC4zM2MtLjI0LTItLjQyLTMuOC0yLjI2LTQuNjZhMjQuMjkgMjQuMjkgMCAwIDAtNC44Mi0xLjM3Ii8+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNMTUuMzkgMTguMzlhNC4zNyA0LjM3IDAgMCAxLTIuOTEgMS4wNyA0LjQyIDQuNDIgMCAwIDEtMi44OS0xLjA1Ii8+PHBhdGggc3R5bGU9ImZpbGw6Z3JheSIgZD0iTTExIDEzaDN2MmgtM3oiLz48cGF0aCBkPSJNMTguMDcgMTJhOS4yMSA5LjIxIDAgMCAxLTUuNTMgMi4wNyIgc3R5bGU9InN0cm9rZS1taXRlcmxpbWl0OjEwO2ZpbGw6bm9uZTtzdHJva2U6Z3JheSIvPjwvZz48L3N2Zz4=)}.scylla-icon--tech-talks{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJDYWxxdWVfNCIgZGF0YS1uYW1lPSJDYWxxdWUgNCI+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNOC4zOSA0LjVIMjMuNXYxM2gtMTUiLz48Y2lyY2xlIGN4PSI0LjUiIGN5PSI2LjUiIHI9IjIiIHN0eWxlPSJzdHJva2UtbWl0ZXJsaW1pdDoxMDtmaWxsOm5vbmU7c3Ryb2tlOmdyYXkiLz48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Ik0xLjUgOS41aDJsLjguODYuNy0uODZoNS41OGExIDEgMCAxIDEgMCAySDYuNXYxMC44OGExIDEgMCAwIDEtMSAxLjEyIDEgMSAwIDAgMS0xLTEgMSAxIDAgMCAxLTEgMSAuOTMuOTMgMCAwIDEtMS0xdi02Yy0uNzggMC0yLS40Ny0yLTF2LTVhMSAxIDAgMCAxIDEtMVoiLz48L2c+PC9zdmc+)}.scylla-icon--testing{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJDYWxxdWVfNCIgZGF0YS1uYW1lPSJDYWxxdWUgNCI+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNNi41IDYuNWgxMnYxMmgtMTJ6Ii8+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNNC41IDQuNWgxNnYxNmgtMTZ6Ii8+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJtOC41IDEwLjUgNSA1IDExLTEyIi8+PC9nPjwvc3ZnPg==)}.scylla-icon--thumbs-up{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSJjdXJyZW50Q29sb3IiIHN0cm9rZS13aWR0aD0iMiIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIiBjbGFzcz0iZmVhdGhlciBmZWF0aGVyLXRodW1icy11cCI+PHBhdGggZD0iTTE0IDlWNWEzIDMgMCAwIDAtMy0zbC00IDl2MTFoMTEuMjhhMiAyIDAgMCAwIDItMS43bDEuMzgtOWEyIDIgMCAwIDAtMi0yLjN6TTcgMjJINGEyIDIgMCAwIDEtMi0ydi03YTIgMiAwIDAgMSAyLTJoMyIvPjwvc3ZnPg==)}.scylla-icon--thumbs-down{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSJjdXJyZW50Q29sb3IiIHN0cm9rZS13aWR0aD0iMiIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIiBjbGFzcz0iZmVhdGhlciBmZWF0aGVyLXRodW1icy1kb3duIj48cGF0aCBkPSJNMTAgMTV2NGEzIDMgMCAwIDAgMyAzbDQtOVYySDUuNzJhMiAyIDAgMCAwLTIgMS43bC0xLjM4IDlhMiAyIDAgMCAwIDIgMi4zem03LTEzaDIuNjdBMi4zMSAyLjMxIDAgMCAxIDIyIDR2N2EyLjMxIDIuMzEgMCAwIDEtMi4zMyAySDE3Ii8+PC9zdmc+)}.scylla-icon--tip{background-image:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZD0iTTEyIDI0QzUuNCAyNCAwIDE4LjYgMCAxMlM1LjQgMCAxMiAwczEyIDUuNCAxMiAxMi01LjQgMTItMTIgMTJabTAtMjJDNi41IDIgMiA2LjUgMiAxMnM0LjUgMTAgMTAgMTAgMTAtNC41IDEwLTEwUzE3LjUgMiAxMiAyWiIgZmlsbD0iI2ZmZiIvPjxwYXRoIGQ9Ik0xMSAxNmMtLjMgMC0uNS0uMS0uNy0uM2wtMy0zYy0uNC0uNC0uNC0xIDAtMS40LjQtLjQgMS0uNCAxLjQgMGwzIDNjLjQuNC40IDEgMCAxLjQtLjIuMi0uNC4zLS43LjNaIiBmaWxsPSIjZmZmIi8+PHBhdGggZD0iTTExIDE2Yy0uMyAwLS41LS4xLS43LS4zLS40LS40LS40LTEgMC0xLjRsNi02Yy40LS40IDEtLjQgMS40IDAgLjQuNC40IDEgMCAxLjRsLTYgNmMtLjIuMi0uNC4zLS43LjNaIiBmaWxsPSIjZmZmIi8+PC9zdmc+)}.scylla-icon--training{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJDYWxxdWVfMiIgZGF0YS1uYW1lPSJDYWxxdWUgMiI+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNMTcuNSAxNS41SC41di0xM2gxOE01LjUgMjVsNC00LjMgNCA0LjMiLz48Y2lyY2xlIGN4PSIyMSIgY3k9IjQiIHI9IjIuNSIgc3R5bGU9InN0cm9rZS1taXRlcmxpbWl0OjEwO2ZpbGw6bm9uZTtzdHJva2U6Z3JheSIvPjxwYXRoIGNsYXNzPSJjbHMtMSIgZD0iTTIzLjQxIDcuNWgtMS41MkwyMSA5bC0uOS0xLjVIMTNBMS44IDEuOCAwIDAgMCAxMS41IDlhMS44IDEuOCAwIDAgMCAxLjUgMS41aDQuNXYxMy4yNEExLjQxIDEuNDEgMCAwIDAgMTkgMjVhMS40MiAxLjQyIDAgMCAwIDEuNS0xLjIyIDEuNTMgMS41MyAwIDAgMCAzIDB2LTcuMTFhMS4xMSAxLjExIDAgMCAwIDEuMDktMS4xOFY4LjY3YTEuMTggMS4xOCAwIDAgMC0xLjE4LTEuMTdaTTkuNSAxNS40NHY1LjM4Ii8+PC9nPjwvc3ZnPg==)}.collapsible-button .side-nav__content .toctree-checkbox:checked~label i,.collapsible-button .side-nav__content i,.scylla-icon--triangle-down,.side-nav__content .collapsible-button i,.side-nav__content .scylla-icon--expand,.side-nav__content .toctree-checkbox:checked~label .collapsible-button i,.side-nav__content .toctree-checkbox:checked~label .scylla-icon--expand{background-image:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTAiIGhlaWdodD0iNSIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cGF0aCBmaWxsLXJ1bGU9ImV2ZW5vZGQiIGNsaXAtcnVsZT0iZXZlbm9kZCIgZD0ibTAgMCA1IDUgNS01SDBaIiBmaWxsPSIjM0EyRDU1Ii8+PC9zdmc+)}.scylla-icon--university{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJDYWxxdWVfNCIgZGF0YS1uYW1lPSJDYWxxdWUgNCI+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJtMS41IDguNSAxMS00IDExIDR2M2wtMTEgNC0xMS00di0zeiIvPjxwYXRoIGNsYXNzPSJjbHMtMSIgZD0iTTUuNSAxMi41djVhMTIuNDYgMTIuNDYgMCAwIDAgNyAyIDExLjIgMTEuMiAwIDAgMCA3LTJ2LTUiLz48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Im0xMy41IDkuNSA4IDEuMjN2OC43N00yMi41IDE2LjV2MyIvPjwvZz48L3N2Zz4=)}.scylla-icon--users-blog{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMntmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJDYWxxdWVfNCIgZGF0YS1uYW1lPSJDYWxxdWUgNCI+PHBhdGggc3R5bGU9InN0cm9rZS13aWR0aDouOThweDtmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kIiBkPSJNMjMuNSAyLjVoLTIydjE2aDEzdjQuMTdsNC4wNC00LjE3IDQuOTYtLjA0VjIuNXoiLz48cGF0aCBjbGFzcz0iY2xzLTIiIGQ9Ik0xMC44NSA4QTEwLjM4IDEwLjM4IDAgMCAxIDExIDkuNWMwIDIuNDctMS4yMSA0LTMgNHMtMy41LTItMy41LTQuNWE0LjE4IDQuMTggMCAwIDEgMC0xIi8+PHBhdGggY2xhc3M9ImNscy0yIiBkPSJNNS4yIDUuMDdhMy4yMiAzLjIyIDAgMCAxIDIuNS0xIDMuMTYgMy4xNiAwIDAgMSAyLjQgMSA2LjIyIDYuMjIgMCAwIDEgMS4zIDMuODEuNzQuNzQgMCAwIDAtLjQyIDBjMC0uMjQgMC0uNDQtLjA1LS42NmgwQTMgMyAwIDAgMSAxMCA2Ljl2LS4yNGwtLjIxLjEyQTkuNjIgOS42MiAwIDAgMSA0LjczIDhhLjI1LjI1IDAgMCAwLS4yMi4wOWMtLjEzLjE0LS4wOS4zNyAwIC42MXYuMThhLjg1Ljg1IDAgMCAwLS4zMiAwQTUuMzcgNS4zNyAwIDAgMSA1LjIgNS4wN1pNNC41MSA4LjkzYy0uMzUgMC0uNTcuMDUtLjYxLjQ0YTEuMTcgMS4xNyAwIDAgMCAuNzMgMS4zTTExIDguOTNjLjM2IDAgLjU3LjA1LjYyLjQ0YTEuMTcgMS4xNyAwIDAgMS0uNzQgMS4zTTYuMzEgMTQuMTN2LS44NE05LjI1IDEzLjE5di45NE0yLjQyIDE4Yy4xMy0xLjE1LjU4LTIuNTIgMS41OC0zYTE0LjcxIDE0LjcxIDAgMCAxIDIuMzEtLjgyTTEzLjUgMThjLS4xMy0xLjE1LS41MS0yLjUyLTEuNS0zcy0yLjUtMS0yLjUtMSIvPjxwYXRoIGNsYXNzPSJjbHMtMiIgZD0iTTkuMzQgMTQuMjJhMi4yMyAyLjIzIDAgMCAxLTEuNTYuNjEgMi4zMiAyLjMyIDAgMCAxLTEuNTUtLjU5TTIxLjUgNi41aC03TTIxLjUgOS41aC03TTE4LjUgMTIuNWgtNCIvPjwvZz48L3N2Zz4=)}.admonition.caution .admonition-title:before,.admonition.warning .admonition-title:before,.scylla-icon--warning{background-image:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PG1hc2sgaWQ9ImEiIG1hc2stdHlwZT0iYWxwaGEiIG1hc2tVbml0cz0idXNlclNwYWNlT25Vc2UiIHg9IjAiIHk9IjEiIHdpZHRoPSIyNCIgaGVpZ2h0PSIyMSI+PHBhdGggZD0iTTMuNSAyMmMtLjUgMC0xLS4xLTEuNS0uNEMuNiAyMC44LjEgMTguOS45IDE3LjVMOS40IDMuM2MuMy0uNC42LS44IDEtMSAuNy0uNCAxLjUtLjUgMi4zLS4zLjguMiAxLjQuNyAxLjkgMS40TDIzIDE3LjVjLjMuNS40IDEgLjQgMS41IDAgLjgtLjMgMS42LS45IDIuMS0uNS42LTEuMi45LTIgLjloLTE3Wm03LjYtMTcuNkwyLjcgMTguNWMtLjMuNS0uMSAxLjEuNCAxLjQuMS4xLjMuMS40LjFoMTYuOWMuMyAwIC41LS4xLjctLjMuMi0uMi4zLS40LjMtLjcgMC0uMiAwLS4zLS4xLS41TDEyLjkgNC40Yy0uMy0uNS0uOS0uNi0xLjQtLjQtLjIuMS0uMy4yLS40LjRaIiBmaWxsPSIjMDYxOTM4Ii8+PHBhdGggZD0iTTEyIDE0Yy0uNiAwLTEtLjQtMS0xVjljMC0uNi40LTEgMS0xczEgLjQgMSAxdjRjMCAuNi0uNCAxLTEgMVpNMTIgMThjLS4zIDAtLjUtLjEtLjctLjMtLjItLjItLjMtLjQtLjMtLjcgMC0uMSAwLS4zLjEtLjQuMS0uMS4xLS4yLjItLjMuMS0uMS4yLS4yLjMtLjIuMi0uMS40LS4xLjYtLjEuMSAwIC4xIDAgLjIuMS4xIDAgLjEgMCAuMi4xIDAgMCAuMS4xLjIuMS4xLjEuMi4yLjIuMyAwIC4xLjEuMy4xLjQgMCAuMy0uMS41LS4zLjctLjMuMi0uNS4zLS44LjNaIiBmaWxsPSIjMDYxOTM4Ii8+PC9tYXNrPjxnIG1hc2s9InVybCgjYSkiPjxwYXRoIGZpbGw9IiMwNjE5MzgiIGQ9Ik0wIDBoMjR2MjRIMHoiLz48L2c+PC9zdmc+)}.scylla-icon--webinars{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMntmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJDYWxxdWVfNCIgZGF0YS1uYW1lPSJDYWxxdWUgNCI+PHBhdGggc3R5bGU9InN0cm9rZS1taXRlcmxpbWl0OjEwO2ZpbGw6bm9uZTtzdHJva2U6Z3JheSIgZD0iTTEuNSA1LjVoMjJ2MTRoLTIyeiIvPjxwYXRoIGNsYXNzPSJjbHMtMiIgZD0iTTkuNDcgMjAuNXYxLjg4TTE1LjUgMjAuNXYyTTYuNSAyMi41aDEyIi8+PHBhdGggc3R5bGU9ImZpbGw6Z3JheSIgZD0ibTkgOSA3LjUgMy41M0w5IDE2Vjl6Ii8+PC9nPjwvc3ZnPg==)}.scylla-icon--whitepapers{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMntmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJDYWxxdWVfNCIgZGF0YS1uYW1lPSJDYWxxdWUgNCI+PHBhdGggc3R5bGU9ImZpbGw6Z3JheSIgZD0iTTggOWg4djJIOHoiLz48cGF0aCBjbGFzcz0iY2xzLTIiIGQ9Ik0xNC4wNiAxLjUgMy41IDEuNTJWMjMuNWgxN1Y3bC02LjQ0LTUuNXoiLz48cGF0aCBkPSJNMTQuMzIgMS40MnYzLjM3YTIuMDYgMi4wNiAwIDAgMCAyLjA4IDIuMWgzLjY3IiBzdHlsZT0ic3Ryb2tlLW1pdGVybGltaXQ6MTA7ZmlsbDpub25lO3N0cm9rZTpncmF5Ii8+PHBhdGggY2xhc3M9ImNscy0yIiBkPSJNNi41IDE5LjVoNE0xMy41IDE5LjVoNE02LjUgMTYuNWg0TTEzLjUgMTYuNWg0TTYuNSAxMy41aDRNMTMuNSAxMy41aDQiLz48L2c+PC9zdmc+)}.scylla-icon--workshop{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMSwuY2xzLTJ7ZmlsbDpub25lO3N0cm9rZTojNGQ0ZDRkfS5jbHMtMXtzdHJva2UtbWl0ZXJsaW1pdDoxMH0uY2xzLTJ7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJDYWxxdWVfNCIgZGF0YS1uYW1lPSJDYWxxdWUgNCI+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNMS41IDUuNWgyMnYxNGgtMjJ6Ii8+PHBhdGggY2xhc3M9ImNscy0yIiBkPSJtOS41IDE5LjUtLjAzIDIuODhNMTUuNSAxOS41djNNNi41IDIyLjVoMTIiLz48cGF0aCBzdHlsZT0iZmlsbDojNGQ0ZDRkIiBkPSJtNCA4IDIgOCAuOTctMy45NUwxMSAxMiA0IDh6Ii8+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJtNi40NyAxMS4zNCAzLjM3IDQuMjgiLz48L2c+PC9zdmc+)}.button{background:transparent;border:1px solid #3a2d55;border-radius:4px;color:#3a2d55;display:inline;font-size:14px;letter-spacing:1px;line-height:21px;margin:0;padding:12px 14px}.button:focus,.button:hover{background:transparent;color:#3a2d55;text-decoration:none}.button--reverse{background:#fff;border:0}.button--reverse:focus,.button--reverse:hover{background:#fff}.tooltip{background-color:rgba(0,0,0,.56);border-radius:4px;font-size:12px;padding:6px}.tooltip:before{display:none!important}.tooltip:empty{display:none!important}.has-tip{border:0;cursor:pointer}.scylla-dropdown{color:#23263b;font-size:14px;line-height:20px}.scylla-dropdown a,.scylla-dropdown a:focus,.scylla-dropdown a:hover{color:#23263b!important;padding:0!important}.scylla-dropdown__item{font-size:16px;padding:15px}.scylla-dropdown__title{align-items:center;display:flex!important;position:static!important}.scylla-dropdown__title:after{display:none!important}.scylla-dropdown__title .chevron{min-height:5px;width:10px}.scylla-dropdown__content{background:#fff;border:0;border-radius:8px;box-shadow:0 4px 25px rgba(0,0,0,.15);font-size:16px;list-style:none;margin-top:15px;overflow:hidden;padding:16px 0;width:max-content}.scylla-dropdown__content li{padding:7px 16px}.scylla-dropdown__content .contents.local>ul>li a:before,.scylla-dropdown__content .secondary-side-nav__content li a:before,.scylla-dropdown__content li .admonition-title:before,.scylla-dropdown__content li .scylla-icon,.secondary-side-nav__content .scylla-dropdown__content li a:before{margin-right:10px}.enlarge-image{cursor:zoom-in}.enlarge-image-reveal{background:transparent;border:none;cursor:zoom-out;padding:0;text-align:center;width:fit-content}.enlarge-image-reveal img{background-color:#fff;padding:15px}.header{background-color:#fff;box-shadow:0 2px 22px rgba(74,93,166,.15);justify-content:space-between;padding:12.75px 0;position:fixed;width:100%;z-index:99}.header,.header-logo{align-items:center;display:flex}.header-logo{margin-left:20px;width:auto}.header-logo__img{width:110px}.header-logo__bar{background-color:#3a2d55;border-left:1px solid #3a2d55;height:11.56px;margin:0 7.5px;width:0}.header-logo__text{color:#3a2d55;font-size:10.11px;letter-spacing:.722408px;line-height:12px;text-transform:uppercase}.header-navigation{display:none}.header-button{display:none;margin-left:15px;text-transform:uppercase}.header-search-box{display:none;margin-right:20px;width:200px}.scylla-dropdown--header .scylla-dropdown__item{font-size:14px}.scylla-dropdown--header .scylla-dropdown__title{text-transform:uppercase}.scylla-dropdown--header .scylla-dropdown__title .chevron{margin-left:10px}.contents.local>ul>li .scylla-dropdown--header .scylla-dropdown__content a:before,.scylla-dropdown--header .scylla-dropdown__content .admonition-title:before,.scylla-dropdown--header .scylla-dropdown__content .contents.local>ul>li a:before,.scylla-dropdown--header .scylla-dropdown__content .scylla-icon,.scylla-dropdown--header .scylla-dropdown__content .secondary-side-nav__content li a:before,.secondary-side-nav__content li .scylla-dropdown--header .scylla-dropdown__content a:before{min-height:20px;width:20px}@media screen and (min-width:1024px){.header{padding:18px 0}.header-logo__img{width:152px}.header-logo__bar{height:16px;margin:0 10px}.header-logo__text{font-size:14px;letter-spacing:.722408px;line-height:12px;text-transform:uppercase}.header-navigation{align-items:center;display:flex;justify-content:center}.header-search-box{display:block}}@media screen and (min-width:1200px){.header-logo{margin-left:30px;width:357px}.header-search-box{margin-right:30px;max-width:20%;width:318px}.header-button{display:block}}.side-nav{background:#fff;display:none;height:100vh;left:0;line-height:24px;max-height:calc(100vh - 50px);overflow-y:auto;padding:20px 20px 0;position:fixed;top:50px;width:100%;z-index:100}.side-nav__title{font-weight:700;margin-bottom:20px}.side-nav__content{max-width:90%;overflow-wrap:break-word}.side-nav__content label,.side-nav__content label i{margin:0;padding:0}.side-nav__content label{font-size:inherit;line-height:1;margin-left:5px;max-height:5px}.collapsible-button .side-nav__content i,.side-nav__content .collapsible-button i,.side-nav__content .scylla-icon--expand{height:5px;vertical-align:top;width:10px}.side-nav__content .toctree-checkbox{display:none;position:absolute;right:20px}.side-nav__content .toctree-checkbox~ul{display:none;margin-right:20px}.side-nav__content .toctree-checkbox:checked~ul{display:block}.side-nav__content ul{margin:0}.side-nav__content a{color:#23263b}.side-nav__content a:hover{color:#3c4fe0;font-weight:400}.side-nav__content li{list-style:none;padding:0 0 24px}.side-nav__content li.has-children{align-items:center;display:flex;flex-wrap:wrap}.side-nav__content li.has-children>a{max-width:calc(100% - 15px)}.side-nav__content li.has-children.current{padding-bottom:20px}.side-nav__content li.has-children:hover>a{color:#3c4fe0}.side-nav__content li.has-children:hover>.toctree-checkbox~label i{filter:invert(38%) sepia(71%) saturate(6789%) hue-rotate(231deg) brightness(90%) contrast(95%)}.side-nav__content li.current-page>a{color:#3c4fe0}.side-nav__content li.current-page>.toctree-checkbox:checked~label i{filter:invert(38%) sepia(71%) saturate(6789%) hue-rotate(231deg) brightness(90%) contrast(95%)}.side-nav__content li ul{margin-top:18px;width:100%}.side-nav__content li ul li{border-left:1px solid #3c4fe0;padding:4px 0 4px 13px}.side-nav__content li ul ul{margin-left:0}.side-nav__content li .label{display:none}.side-nav__versions{max-width:90%}.side-nav__search,.side-nav__versions .dropdown{margin-bottom:20px}.collapsible-button{background:#fff;background-color:#fff;border:0;border-radius:8px;border-radius:50%;bottom:10px;box-shadow:0 4px 25px rgba(0,0,0,.15);cursor:pointer;display:none;font-size:0;left:300px;overflow:hidden;padding:13.5px;position:fixed}.collapsible-button i{height:16px;margin:0;width:16px}.side-nav--collapsed .collapsible-button{border-radius:0 20px 20px 0;left:-10px}.side-nav--collapsed .collapsible-button i{transform:rotate(180deg)}.layout--has-banner .side-nav{max-height:calc(100vh - 92.5px)}@media screen and (min-width:1024px){.side-nav{background-color:#f6f8ff;display:block;height:100%;left:auto;max-height:100vh;max-height:calc(100vh - 80px);padding:30px 40px;top:80px;width:286px;z-index:25}.side-nav__content{max-width:100%;padding-bottom:180px}.side-nav__search{display:none}.side-nav__versions{max-width:100%}.toctree-checkbox{right:40px}.layout--has-banner .side-nav{max-height:calc(100vh - 150px)}}@media screen and (min-width:1200px){.side-nav{width:357px}.side-nav--collapsed{background-color:transparent;padding-left:0;padding-right:0;width:126px}.side-nav--collapsed .side-nav-content{display:none}.collapsible-button{display:block}}.side-nav-toggle{cursor:pointer;display:block;margin-right:20px;position:relative;z-index:300}@media screen and (min-width:1024px){.side-nav-toggle{display:none}}.secondary-side-nav{display:none;height:100%;line-height:24px;padding:20px;width:100%}.secondary-side-nav__content{overflow-wrap:break-word}.secondary-side-nav__content ul{list-style:none;margin:0}.secondary-side-nav__content li{border-bottom:1px solid rgba(90,94,154,.1);display:none;padding:10px 0;word-break:break-word}.secondary-side-nav__content li:last-child{border:0}.secondary-side-nav__content li .label{display:none}.secondary-side-nav__content li a{align-items:baseline;color:#b3bac5;display:flex;font-size:14px}.secondary-side-nav__content li a:before{content:"";filter:invert(40%) sepia(11%) saturate(2157%) hue-rotate(198deg) brightness(89%) contrast(87%)!important;flex-shrink:0;margin-right:10px;min-height:10px;opacity:.5;width:6px}.secondary-side-nav__content li a.current,.secondary-side-nav__content li a:hover{color:#23263b;font-weight:400}.secondary-side-nav__content li a.current:before,.secondary-side-nav__content li a:hover:before{filter:brightness(0);opacity:1}.secondary-side-nav__content li a.current{font-weight:700}.secondary-side-nav__content>ul>li>ul>li{display:block}.secondary-side-nav__content>ul>li{border:0;display:block}.secondary-side-nav__content>ul>li>a{display:none}@media screen and (min-width:1200px){.secondary-side-nav{display:block;max-height:100vh;max-height:calc(100vh - 80px);overflow-y:auto;padding:60px 60px 60px 20px;position:fixed;top:80px;width:286px}.secondary-side-nav__content{padding-bottom:180px}.layout--has-banner .secondary-side-nav{max-height:calc(100vh - 150px)}}.layout{display:flex}.pre-content{align-items:center;display:flex;justify-content:space-between;margin-bottom:20px}.content{margin-top:50px;max-width:1440px;overflow-wrap:break-word;padding:20px;scroll-margin-top:50px;width:100%}.content .line-block,.content p{line-height:28px;margin-bottom:20px}.content ul{list-style:none}.content ul li:before{color:#b3bac5;content:"•";float:left;font-family:FontAwesome;font-size:20px;font-weight:700;margin-left:-1em;margin-top:-2px;width:1em}.content ul ul{list-style:circle}.content ul ul li:before{content:""}.content ol ol{list-style:lower-latin}.content img{margin-bottom:30px}.content section{margin-top:-50px;padding-top:50px}.content .inline-icon.fa-check{color:#42c4e6}.layout--full-width .content{max-width:100%;padding:0;width:100%}.layout--full-width .content .hero-wrapper,.layout--full-width .content .topics-grid{max-width:1190px}.layout--full-width .content.content--collapsed{margin-left:0}.layout--full-width:not(.layout--sidebar) .content{margin-left:0}.layout--has-banner .content{scroll-margin-top:92.5px}.layout--has-banner .content section{margin-top:-92.5px;padding-top:92.5px}.landing__content{padding:0 16px}@media screen and (min-width:1024px){.content{margin-left:286px;margin-top:80px;min-height:calc(100vh - 260px);padding-bottom:100px;scroll-margin-top:80px;width:calc(100% - 286px)}.content section{margin-top:-80px;padding-top:80px}}@media screen and (min-width:1200px){.content{margin-left:357px;padding:60px 40px 40px;width:calc(100% - 643px)}.content--collapsed{margin-left:126px;width:calc(100% - 412px)}.pre-content{margin-bottom:10px}.layout--has-banner .content{scroll-margin-top:150px}.layout--has-banner .content section{margin-top:-150px;padding-top:150px}.landing__content{padding:0 60px}.landing--floating .landing__content{position:relative;top:-70px}}.contents.local>ul{margin-bottom:30px;margin-left:0}.contents.local>ul>li{border-bottom:1px solid rgba(90,94,154,.1);padding:10px 0;word-break:break-word}.contents.local>ul>li:before{content:""}.contents.local>ul>li:last-child{border:0}.contents.local>ul>li ul{display:none}.contents.local>ul>li p{margin:0}.contents.local>ul>li a{font-size:14px}.contents.local>ul>li a:before{content:"";filter:invert(40%) sepia(11%) saturate(2157%) hue-rotate(198deg) brightness(89%) contrast(87%)!important;margin-right:10px;min-height:10px;opacity:.5;width:10px}.contents.local>ul>li a.current:before,.contents.local>ul>li a:hover:before{filter:brightness(0);opacity:1}.topic-title{color:rgba(35,38,59,.75);font-size:10px;letter-spacing:1.5px;margin-bottom:0;text-transform:uppercase}.notice{margin-top:40px}.footer{background-color:#fff;box-shadow:0 -4px 10px hsla(0,0%,82%,.25);padding:30px 0;position:relative;width:100%;z-index:50}.footer-group{margin:0 auto;max-width:1030px;padding:0 20px}.footer-top{align-items:center;border-bottom:1px solid rgba(0,0,0,.1);display:flex;flex-wrap:wrap;justify-content:space-between;padding-bottom:8px;text-align:center}.footer-logo{margin-bottom:30px;width:100%}.footer-logo img{float:left;height:36px}.footer-links{text-align:left}.footer-links__link{color:#333;font-size:12px;font-weight:500;letter-spacing:2.4px;margin-right:16px;text-transform:uppercase}.footer-actions{align-items:center;display:flex;justify-content:space-between;width:90px}.footer-actions__link{color:#000}.footer-actions__link img{height:23px}.footer-bottom{color:#979797;display:flex;flex-wrap:wrap;font-size:12px;font-style:normal;font-weight:400;justify-content:center;letter-spacing:1.4px;line-height:23px;padding:20px 0 10px;text-align:center;text-transform:uppercase}@media screen and (max-width:510px){.footer-links{margin-bottom:20px}}@media screen and (min-width:1024px){.footer{padding:30px 0}.footer-group{padding:0}.footer-top{padding-bottom:30px}.footer-logo{margin:0;width:auto}.footer-links{padding:0 40px}.footer-links__link{font-size:14px;margin-right:28px}.footer-actions{width:110px}.footer-actions__link img{height:28px}.footer-bottom .footer-bottom__copyright,.footer-bottom .footer-bottom__last-updated,.footer-bottom .footer-bottom__version{padding:0 10px}.footer-bottom .footer-bottom__copyright{border-left:none}}.not-found{background-color:#f6f8ff;height:100%;overflow:hidden}.not-found__icon{display:block;margin:40px auto;max-width:300px}.not-found__text{text-align:center}.not-found__text h1{font-size:60px;line-height:1}.not-found__text p{margin:30px 0;width:100%}.not-found__button{text-transform:uppercase}.admonition{border-radius:4px;box-shadow:0 4px 4px rgba(0,0,0,.12);color:rgba(0,0,0,.56);font-size:14px;line-height:20px;margin-bottom:30px;overflow:auto;padding:20px;position:relative}.admonition:before{bottom:0;content:" ";left:0;position:absolute;right:0;top:0;z-index:-1}.admonition-title{color:#23263b;margin-bottom:0!important}.admonition-title:before{content:"";margin-right:8px;min-height:24px;width:24px}.admonition p:not(.admonition-title){margin-bottom:0!important;margin-left:32px}.admonition.tip{border:1px solid #43a047}.admonition.tip:before{border-left:8px solid rgba(67,160,71,.4)}.admonition.tip .admonition-title:before{filter:invert(47%) sepia(11%) saturate(2286%) hue-rotate(73deg) brightness(109%) contrast(88%)}.admonition.note{border:1px solid #1976d2}.admonition.note:before{border-left:8px solid rgba(25,118,210,.4)}.admonition.note .admonition-title:before{filter:invert(44%) sepia(55%) saturate(2310%) hue-rotate(191deg) brightness(81%) contrast(103%)}.admonition.caution{border:1px solid #ffab00}.admonition.caution:before{border-left:8px solid rgba(255,171,0,.4)}.admonition.caution .admonition-title:before{filter:invert(77%) sepia(56%) saturate(3332%) hue-rotate(357deg) brightness(98%) contrast(108%)}.admonition.warning{border:1px solid #e74c3c}.admonition.warning:before{border-left:8px solid rgba(231,76,60,.4)}.admonition.warning .admonition-title:before{filter:invert(41%) sepia(42%) saturate(6427%) hue-rotate(343deg) brightness(99%) contrast(83%)}.breadcrumbs{margin-bottom:0;text-transform:uppercase}.breadcrumbs .bread__item,.breadcrumbs .bread__item:not(.bread__item--last):after,.breadcrumbs a{color:#23263b;font-size:12px;font-weight:400;letter-spacing:1.5px;line-height:2;margin:0;padding:0}.breadcrumbs .bread__item:before{display:none}.breadcrumbs .bread__item:not(.bread__item--last):after{content:"/";margin:0 5px;opacity:1;position:relative}.breadcrumbs .bread__highlight{color:#3c4fe0}.breadcrumbs .bread__highlight:hover{font-weight:700;text-decoration:none}code{background-color:#f7f8f9;border:none;border-radius:4px;color:#23263b;font-size:14px}code.download{background:none;color:#23263b}.highlight{background:transparent!important}.highlight pre{background-color:#f7f8f9;border-radius:8px;color:#23263b;font-size:14px;line-height:26px;margin-bottom:30px;overflow:auto;padding:16px}.highlight a.copybtn{right:1em;top:1em}.highlighttable{background-color:#f7f8f9;border-radius:16px;box-shadow:none}.highlighttable tbody{background-color:transparent;border:0}.highlighttable tbody td{padding:15px!important}.highlighttable tbody tr{border-top:none}.highlighttable .linenos{background-color:#f7f8f9;color:#5a7184;width:50px}.highlighttable .linenos span{line-height:26px}.highlighttable .highlight pre{background-color:transparent;margin:0;padding:0}.highlighttable .highlight a.copybtn{right:.2em;top:.2em}.hide-copy-button .copybtn{display:none}.sphinx_collapse__label{display:flex!important;flex-direction:row-reverse;font-size:medium;font-weight:700;justify-content:flex-end;margin-left:0!important}.sphinx_collapse__icon{margin-left:5px;margin-right:0}.sphinx_collapse__input:checked~.sphinx_collapse__label,.sphinx_collapse__label:hover{color:#3c4fe0}.sphinx_collapse__input:checked~.sphinx_collapse__label .sphinx_collapse__icon,.sphinx_collapse__label:hover .sphinx_collapse__icon{border-top-color:#3c4fe0}.sphinx_collapse__content{margin-top:10px}.contribute{margin:0 0 20px}.contribute__item{font-size:14px;list-style:none;padding-bottom:10px}.contribute__item .icon{margin-right:5px}.content-navigation{display:flex;justify-content:space-between;margin-top:40px}.navigation{max-width:50%;word-break:break-word}.navigation,.navigation__link{display:flex}.navigation__title{word-wrap:break-word;color:#23263b;font-size:12px;font-weight:500;letter-spacing:1.5px;line-height:24px;text-transform:uppercase}.navigation__title .colored{color:#42c4e6}.navigation__button{background:#fff;background-color:#fff;border:0;border-radius:8px;box-shadow:0 4px 25px rgba(0,0,0,.15);cursor:pointer;display:none;font-size:0;height:fit-content;overflow:hidden;padding:13.5px 16.5px}.navigation__button i{height:16px;margin:0;width:10px}.navigation--prev .navigation__title{margin-left:15px}.navigation--next .navigation__title{margin-right:15px;text-align:right}@media screen and (min-width:1200px){.navigation__title{display:inline-block}.navigation__button{display:block}.navigation--next .navigation__title{text-align:left}}.scylla-dropdown--versions .scylla-dropdown__item{background:#fff;border-radius:8px;box-shadow:0 28px 32px rgba(0,0,0,.06);width:100%}.scylla-dropdown--versions .scylla-dropdown__title{align-items:center;display:flex;justify-content:space-between}.scylla-dropdown--versions .scylla-dropdown__title .chevron{min-height:12px;transform:rotate(90deg);width:8px}@media screen and (min-width:1024px){.scylla-dropdown--versions .scylla-dropdown__item{box-shadow:none}}.feedback-container{font-size:16px;margin-top:40px;text-align:left}.feedback-container__title{font-weight:700;margin-bottom:5px!important}.feedback-container__button{background:#fff;border:0;border-radius:8px;box-shadow:0 4px 25px rgba(0,0,0,.15);cursor:pointer;margin:4px;overflow:hidden;padding:8px}.feedback-container__button.active{border:1px solid #3c4fe0}.feedback-container__icon{height:20px;width:20px}.feedback-container__message{font-size:16px;margin-top:10px}.hero{background:#f6f8ff;margin-bottom:30px;overflow:hidden;padding:30px 16px;text-align:left}.hero__title{font-size:28px;font-weight:500;line-height:38px;margin-bottom:14px;max-width:229px}.hero__text{font-size:16px;line-height:26px;max-width:343px}.hero__text a{border-bottom:1px dotted #23263b;color:#23263b}.hero__text p{margin-bottom:0!important}.hero__img{position:absolute;right:-18px;top:20px}.hero__img img{margin-bottom:0!important;width:124px}.hero__button{margin-top:20px;text-transform:uppercase}.hero__button .icon{margin-right:5px}.hero__search-box{box-shadow:0 4px 25px rgba(0,0,0,.02);margin-top:20px}.hero-wrapper{align-items:center;display:flex;justify-content:space-between;margin:0 auto;position:relative}@media screen and (min-width:640px){.hero{padding:60px 16px}.hero__title{font-size:32px;line-height:42px;max-width:482px}.hero__text{font-size:18px;line-height:26px;max-width:482px}.hero__img{display:block;position:static}.hero__img img{height:100%;width:295px}.hero .hero-wrapper{flex-direction:row-reverse}.hero .landing--floating .hero{padding:30px 16px 100px}}@media screen and (min-width:1024px){.hero{padding:60px}}.label{background-color:#23263b;border:0;border-radius:4px;color:#fff;font-size:inherit}.label--note{background-color:#1976d2}.label--tip{background-color:#43a047}.label--caution{background-color:#ffab00}.label--warning{background-color:#e74c3c}.last-updated{color:#4458a3;font-size:12px;letter-spacing:1.5px;margin:10px 0;text-transform:uppercase}.last-updated__icon{font-size:14px}@media screen and (min-width:1024px){.last-updated{float:right;margin:0}}.panel{border:0;border-radius:4px;margin-bottom:30px}.promo-banner{background-color:#4458a3;background-image:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTQ0MCIgaGVpZ2h0PSI3MCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48bWFzayBpZD0iYSIgbWFzay10eXBlPSJhbHBoYSIgbWFza1VuaXRzPSJ1c2VyU3BhY2VPblVzZSIgeD0iMCIgeT0iMCIgd2lkdGg9IjE0NDAiIGhlaWdodD0iNzAiPjxwYXRoIGZpbGw9IiM0NDU4QTMiIGQ9Ik0wIDBoMTQ0MHY3MEgweiIvPjwvbWFzaz48ZyBtYXNrPSJ1cmwoI2EpIiBmaWxsPSIjNTA2NEFFIj48cGF0aCBkPSJNLTE5MyAyMDEuODg0IDEuNS0xMzUgMzU3LjQzNiA3MC41bC0xOTQuNSAzMzYuODg0ek0xMDkyLjkyLTM4LjAwOSA5NzIuODAzLTI0Ni4wNTcgNDAyLjk5NiA4Mi45MiA1MjMuMTEzIDI5MC45N3oiLz48cGF0aCBkPSJtMTAzOC0zOC4wMDkgMTIwLjExNy0yMDguMDQ5IDU2OS44MDcgMzI4Ljk3OS0xMjAuMTE3IDIwOC4wNDl6Ii8+PC9nPjwvc3ZnPg==);background-position:50%;background-repeat:no-repeat;background-size:cover;display:none;overflow:hidden;position:fixed;top:0;width:100%;z-index:900}.promo-banner__icon{margin-right:15px}.promo-banner__icon img{height:40px}.promo-banner__title{color:#fff;font-size:12px;line-height:16px;margin-right:15px}.promo-banner__button{background:#fff;border-radius:4px;font-size:12px;min-width:max-content;padding:5px}.promo-banner__close{display:none;position:absolute;right:16px;top:16px}.contents.local>ul>li .promo-banner__close a:before,.promo-banner__close .admonition-title:before,.promo-banner__close .contents.local>ul>li a:before,.promo-banner__close .scylla-icon,.promo-banner__close .secondary-side-nav__content li a:before,.secondary-side-nav__content li .promo-banner__close a:before{filter:brightness(100%);height:34px;width:34px}.promo-banner__close:hover{cursor:pointer;filter:opacity(.8)}.promo-banner-wrapper{align-items:center;display:flex;justify-content:center;padding:5.85px 20px}@media(min-width:1024px){.promo-banner__title{font-size:18px;line-height:23px}.promo-banner__button{font-size:14px;padding:8.5px}.promo-banner__close{display:block}.promo-banner-wrapper{flex-direction:unset;padding:16px}}.custom-scroll-bar::-webkit-scrollbar{background-color:transparent;width:5px}.custom-scroll-bar::-webkit-scrollbar-thumb{background-color:#b3bac5;-webkit-border-radius:8px;border-radius:8px}.search-box{background:#f7f8f9;border-radius:4px;display:flex;padding:10px 15px}.search-box--hero{background-color:#fff;padding:12px 14px}.search-box:before{background-image:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZD0iTTEwLjUgMThhNy41IDcuNSAwIDEgMCAwLTE1IDcuNSA3LjUgMCAwIDAgMCAxNVpNMjEgMjFsLTUuMi01LjIiIHN0cm9rZT0iIzAwMCIgc3Ryb2tlLXdpZHRoPSIyIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiLz48L3N2Zz4=);background-repeat:no-repeat;background-size:contain;content:"";display:inline-block;filter:brightness(0);margin-top:2px;min-height:18px;min-width:18px;vertical-align:middle;width:20px}.search-box .er-dummy-search,.search-box .er-dummy-search-box,.search-box .er-search-form,.search-box ci-search,.search-box input{margin:0!important;width:100%!important}.search-box input{background:transparent!important;color:rgba(80,80,80,.5)!important;font-size:14px!important;padding:0!important}.search-box input::placeholder{color:rgba(80,80,80,.5)!important;opacity:1!important}.search-box button{display:none!important}.er_search_suggestions{background:#fff;border:0;border:0!important;border-radius:8px;box-shadow:0 4px 25px rgba(0,0,0,.15);overflow:hidden}.er_search_suggestions .er-search-result-box{border-width:1px!important;padding-bottom:10px!important;padding-top:10px!important}.er_search_suggestions .er-search-result-box:hover{background:#f7f8f9!important}.er_search_suggestions .er_more_result_btn{cursor:pointer}.er_search_suggestions h3{font-size:16px!important}.er-search-content{padding:20px!important}#er_search_results .er-search-result-box{display:block!important;margin:10px auto 0!important;width:100%!important}#er_search_results .text,#er_search_results .title a,#er_search_results .url a{max-width:100%!important}#search-result-input-form{max-width:800px!important}#er_search_button{text-align:center}#er_clear_input{right:0!important;top:0!important}.er-facet-header{background-color:transparent!important;border:0!important;padding:0 0 8px!important}.er-facet-val{padding:5px 2px!important}.er-facet-val input{display:block!important;margin:0}#er_search_pagination{margin-top:20px!important}#er_search_pagination li.er-paginator-list.er-active{border-bottom:0!important;font-weight:700}.er-suggestion-sm .er_search_input_dummy{margin:0!important}.er-suggestion-sm .er_search_button_dummy{border:0!important}#er_gcs_mobile_model_container .er-facet-values .er-facet-val{align-items:baseline}@media screen and (min-width:640px){.er-facets{display:none;max-width:300px!important;min-width:auto!important;width:auto!important}}@media screen and (min-width:1024px){.er-suggestions{left:15px!important}}@media screen and (min-width:1200px){.er-facets{display:block;position:fixed!important}.er-facet-count{display:none}}.sphinx-tabs{margin-bottom:30px}.sphinx-tabs-tab{border-bottom:1px solid rgba(0,0,0,.56);color:rgba(0,0,0,.56);cursor:pointer;font-size:14px;font-weight:500;line-height:13px;padding:20px 25px}.sphinx-tabs-tab[aria-selected=true]{border-bottom:2px solid #2196f3;color:#2196f3;padding-bottom:19px}.sphinx-tabs-panel{margin:30px 0}.table-wrapper{border:1px solid #e0e0e0;border-radius:4px;box-shadow:0 1px 2px rgba(0,0,0,.25);display:block;margin-bottom:30px;max-width:100%;overflow-x:auto}table{color:#000;font-size:14px;line-height:24px;margin:0;overflow:hidden}table p{margin:0!important}table caption{background:#f6f8ff;border-bottom:1px solid #e0e0e0;color:#23263b;padding:10px 25px}table thead{background:#f6f8ff;border:0;border-bottom:1px solid #4458a3}table thead th{color:#23263b;font-size:14px;font-weight:700}table td,table thead th{padding:20px 25px}table tbody tr{background-color:transparent!important;border-top:1px solid #e0e0e0;line-height:18px}table:not(.highlighttable) tbody tr:first-child{border-top:1px solid #4458a3}table.thead-border thead .row-odd th{color:#23263b}table.thead-border thead .row-even th{font-weight:400}table.thead-border thead th{border:1px solid #e0e0e0}table.thead-border thead tr:first-child th{border-top:none}table.thead-border thead tr:last-child th{border-bottom:none}table.thead-border thead tr th:first-child{border-left:none}table.thead-border thead tr th:last-child{border-right:none}.topics-grid{display:block;margin:0 auto 30px}.topics-grid__title{color:#23263b;font-size:24px;font-weight:700;line-height:32px;margin-bottom:6px}.topics-grid__text{color:#4458a3;font-size:18px;line-height:24px}.topics-grid--scrollable .hs{-ms-overflow-style:none;display:grid;grid-auto-flow:column;overflow-x:scroll;padding:20px 10px;scrollbar-width:none}.topics-grid--scrollable .hs::-webkit-scrollbar{display:none}.topics-grid--scrollable .hs .topic-box:last-child:after{content:"";width:20px}.topic-box{align-items:stretch;display:flex}.topic-box .card{background:#fff;border:1px solid transparent;border-radius:8px;box-shadow:0 4px 25px rgba(0,0,0,.15);display:flex;flex-direction:column;font-size:18px;margin:0 auto 30px;overflow:hidden;padding:20px;position:relative}.topic-box .card:hover{border:1px solid #4458a3;color:#23263b;font-weight:400}.topic-box__title{color:#23263b;font-size:16px;font-weight:700;line-height:24px;margin-bottom:0}.topic-box__title img{bottom:0;opacity:.3;position:absolute;right:0;top:0}.topic-box__body{color:#000;display:flex;flex-direction:column;flex-grow:1;max-width:80%}.topic-box__body .container{flex-grow:1;margin:0;padding:0}.topic-box__body .line-block,.topic-box__body p{font-size:16px;line-height:19px;margin-top:10px}.topic-box__anchor{color:#42c4e6;font-size:14px;font-weight:700;line-height:24px}.topic-box__icon{display:block;font-size:50px;margin-bottom:20px}.topic-box__icon i{filter:brightness(0);min-height:50px;width:100%}.topic-box__icon img{bottom:-12px;display:none;height:140px;margin:0;opacity:.3;position:absolute;right:-5px}.topic-box--product .card{box-shadow:none;padding:20px;text-align:center}.topic-box--product .card .topic-box__title{color:#23263b;font-size:14px}.topic-box--product .card .topic-box__body{display:flex;flex-direction:column;max-width:100%}.topic-box--product .card .topic-box__body .line-block,.topic-box--product .card .topic-box__body p{font-size:12px}.topic-box--product .card .topic-box__icon img{display:inline-block;max-height:84px;opacity:1;position:static}.topic-box--product .card:hover{background:#fff;border:0;border-radius:8px;box-shadow:0 4px 25px rgba(0,0,0,.15);overflow:hidden}@media screen and (max-width:1024px){.topics-grid--scrollable .topic-box{width:280px!important}.topic-box--product:nth-last-child(-n+2) .card{margin-bottom:0}}@media screen and (min-width:1024px){.topics-grid{margin-bottom:10px}.topics-grid__text{font-size:16px}.topics-grid--scrollable .hs{display:flex;overflow-x:initial;padding:0}.topics-grid--scrollable .hs .topic-box:last-child:after{display:none}.topic-box .card{margin-bottom:60px;padding:45px 30px}.topic-box__title{font-size:20px;line-height:32px}.topic-box__body .line-block,.topic-box__body p{font-size:18px;line-height:26px}.topic-box__anchor{font-size:20px;line-height:26px}.topic-box .topic-box__icon img{display:inline-block}.topic-box--product .card{padding:20px}.topic-box--product .card .topic-box__title{font-size:18px;line-height:24px}.topic-box--product .card .topic-box__body .line-block,.topic-box--product .card .topic-box__body p{font-size:14px}.topic-box--product .card .topic-box__icon img{max-height:111px}.landing .topics-grid--products{margin-bottom:40px}} \ No newline at end of file diff --git a/_static/doctools.js b/_static/doctools.js new file mode 100644 index 0000000000..8cbf1b161a --- /dev/null +++ b/_static/doctools.js @@ -0,0 +1,323 @@ +/* + * doctools.js + * ~~~~~~~~~~~ + * + * Sphinx JavaScript utilities for all documentation. + * + * :copyright: Copyright 2007-2021 by the Sphinx team, see AUTHORS. + * :license: BSD, see LICENSE for details. + * + */ + +/** + * select a different prefix for underscore + */ +$u = _.noConflict(); + +/** + * make the code below compatible with browsers without + * an installed firebug like debugger +if (!window.console || !console.firebug) { + var names = ["log", "debug", "info", "warn", "error", "assert", "dir", + "dirxml", "group", "groupEnd", "time", "timeEnd", "count", "trace", + "profile", "profileEnd"]; + window.console = {}; + for (var i = 0; i < names.length; ++i) + window.console[names[i]] = function() {}; +} + */ + +/** + * small helper function to urldecode strings + * + * See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/decodeURIComponent#Decoding_query_parameters_from_a_URL + */ +jQuery.urldecode = function(x) { + if (!x) { + return x + } + return decodeURIComponent(x.replace(/\+/g, ' ')); +}; + +/** + * small helper function to urlencode strings + */ +jQuery.urlencode = encodeURIComponent; + +/** + * This function returns the parsed url parameters of the + * current request. Multiple values per key are supported, + * it will always return arrays of strings for the value parts. + */ +jQuery.getQueryParameters = function(s) { + if (typeof s === 'undefined') + s = document.location.search; + var parts = s.substr(s.indexOf('?') + 1).split('&'); + var result = {}; + for (var i = 0; i < parts.length; i++) { + var tmp = parts[i].split('=', 2); + var key = jQuery.urldecode(tmp[0]); + var value = jQuery.urldecode(tmp[1]); + if (key in result) + result[key].push(value); + else + result[key] = [value]; + } + return result; +}; + +/** + * highlight a given string on a jquery object by wrapping it in + * span elements with the given class name. + */ +jQuery.fn.highlightText = function(text, className) { + function highlight(node, addItems) { + if (node.nodeType === 3) { + var val = node.nodeValue; + var pos = val.toLowerCase().indexOf(text); + if (pos >= 0 && + !jQuery(node.parentNode).hasClass(className) && + !jQuery(node.parentNode).hasClass("nohighlight")) { + var span; + var isInSVG = jQuery(node).closest("body, svg, foreignObject").is("svg"); + if (isInSVG) { + span = document.createElementNS("http://www.w3.org/2000/svg", "tspan"); + } else { + span = document.createElement("span"); + span.className = className; + } + span.appendChild(document.createTextNode(val.substr(pos, text.length))); + node.parentNode.insertBefore(span, node.parentNode.insertBefore( + document.createTextNode(val.substr(pos + text.length)), + node.nextSibling)); + node.nodeValue = val.substr(0, pos); + if (isInSVG) { + var rect = document.createElementNS("http://www.w3.org/2000/svg", "rect"); + var bbox = node.parentElement.getBBox(); + rect.x.baseVal.value = bbox.x; + rect.y.baseVal.value = bbox.y; + rect.width.baseVal.value = bbox.width; + rect.height.baseVal.value = bbox.height; + rect.setAttribute('class', className); + addItems.push({ + "parent": node.parentNode, + "target": rect}); + } + } + } + else if (!jQuery(node).is("button, select, textarea")) { + jQuery.each(node.childNodes, function() { + highlight(this, addItems); + }); + } + } + var addItems = []; + var result = this.each(function() { + highlight(this, addItems); + }); + for (var i = 0; i < addItems.length; ++i) { + jQuery(addItems[i].parent).before(addItems[i].target); + } + return result; +}; + +/* + * backward compatibility for jQuery.browser + * This will be supported until firefox bug is fixed. + */ +if (!jQuery.browser) { + jQuery.uaMatch = function(ua) { + ua = ua.toLowerCase(); + + var match = /(chrome)[ \/]([\w.]+)/.exec(ua) || + /(webkit)[ \/]([\w.]+)/.exec(ua) || + /(opera)(?:.*version|)[ \/]([\w.]+)/.exec(ua) || + /(msie) ([\w.]+)/.exec(ua) || + ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec(ua) || + []; + + return { + browser: match[ 1 ] || "", + version: match[ 2 ] || "0" + }; + }; + jQuery.browser = {}; + jQuery.browser[jQuery.uaMatch(navigator.userAgent).browser] = true; +} + +/** + * Small JavaScript module for the documentation. + */ +var Documentation = { + + init : function() { + this.fixFirefoxAnchorBug(); + this.highlightSearchWords(); + this.initIndexTable(); + if (DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS) { + this.initOnKeyListeners(); + } + }, + + /** + * i18n support + */ + TRANSLATIONS : {}, + PLURAL_EXPR : function(n) { return n === 1 ? 0 : 1; }, + LOCALE : 'unknown', + + // gettext and ngettext don't access this so that the functions + // can safely bound to a different name (_ = Documentation.gettext) + gettext : function(string) { + var translated = Documentation.TRANSLATIONS[string]; + if (typeof translated === 'undefined') + return string; + return (typeof translated === 'string') ? translated : translated[0]; + }, + + ngettext : function(singular, plural, n) { + var translated = Documentation.TRANSLATIONS[singular]; + if (typeof translated === 'undefined') + return (n == 1) ? singular : plural; + return translated[Documentation.PLURALEXPR(n)]; + }, + + addTranslations : function(catalog) { + for (var key in catalog.messages) + this.TRANSLATIONS[key] = catalog.messages[key]; + this.PLURAL_EXPR = new Function('n', 'return +(' + catalog.plural_expr + ')'); + this.LOCALE = catalog.locale; + }, + + /** + * add context elements like header anchor links + */ + addContextElements : function() { + $('div[id] > :header:first').each(function() { + $('\u00B6'). + attr('href', '#' + this.id). + attr('title', _('Permalink to this headline')). + appendTo(this); + }); + $('dt[id]').each(function() { + $('\u00B6'). + attr('href', '#' + this.id). + attr('title', _('Permalink to this definition')). + appendTo(this); + }); + }, + + /** + * workaround a firefox stupidity + * see: https://bugzilla.mozilla.org/show_bug.cgi?id=645075 + */ + fixFirefoxAnchorBug : function() { + if (document.location.hash && $.browser.mozilla) + window.setTimeout(function() { + document.location.href += ''; + }, 10); + }, + + /** + * highlight the search words provided in the url in the text + */ + highlightSearchWords : function() { + var params = $.getQueryParameters(); + var terms = (params.highlight) ? params.highlight[0].split(/\s+/) : []; + if (terms.length) { + var body = $('div.body'); + if (!body.length) { + body = $('body'); + } + window.setTimeout(function() { + $.each(terms, function() { + body.highlightText(this.toLowerCase(), 'highlighted'); + }); + }, 10); + $('') + .appendTo($('#searchbox')); + } + }, + + /** + * init the domain index toggle buttons + */ + initIndexTable : function() { + var togglers = $('img.toggler').click(function() { + var src = $(this).attr('src'); + var idnum = $(this).attr('id').substr(7); + $('tr.cg-' + idnum).toggle(); + if (src.substr(-9) === 'minus.png') + $(this).attr('src', src.substr(0, src.length-9) + 'plus.png'); + else + $(this).attr('src', src.substr(0, src.length-8) + 'minus.png'); + }).css('display', ''); + if (DOCUMENTATION_OPTIONS.COLLAPSE_INDEX) { + togglers.click(); + } + }, + + /** + * helper function to hide the search marks again + */ + hideSearchWords : function() { + $('#searchbox .highlight-link').fadeOut(300); + $('span.highlighted').removeClass('highlighted'); + }, + + /** + * make the url absolute + */ + makeURL : function(relativeURL) { + return DOCUMENTATION_OPTIONS.URL_ROOT + '/' + relativeURL; + }, + + /** + * get the current relative url + */ + getCurrentURL : function() { + var path = document.location.pathname; + var parts = path.split(/\//); + $.each(DOCUMENTATION_OPTIONS.URL_ROOT.split(/\//), function() { + if (this === '..') + parts.pop(); + }); + var url = parts.join('/'); + return path.substring(url.lastIndexOf('/') + 1, path.length - 1); + }, + + initOnKeyListeners: function() { + $(document).keydown(function(event) { + var activeElementType = document.activeElement.tagName; + // don't navigate when in search box, textarea, dropdown or button + if (activeElementType !== 'TEXTAREA' && activeElementType !== 'INPUT' && activeElementType !== 'SELECT' + && activeElementType !== 'BUTTON' && !event.altKey && !event.ctrlKey && !event.metaKey + && !event.shiftKey) { + switch (event.keyCode) { + case 37: // left + var prevHref = $('link[rel="prev"]').prop('href'); + if (prevHref) { + window.location.href = prevHref; + return false; + } + break; + case 39: // right + var nextHref = $('link[rel="next"]').prop('href'); + if (nextHref) { + window.location.href = nextHref; + return false; + } + break; + } + } + }); + } +}; + +// quick alias for translations +_ = Documentation.gettext; + +$(document).ready(function() { + Documentation.init(); +}); diff --git a/_static/documentation_options.js b/_static/documentation_options.js new file mode 100644 index 0000000000..c23c68c3e7 --- /dev/null +++ b/_static/documentation_options.js @@ -0,0 +1,12 @@ +var DOCUMENTATION_OPTIONS = { + URL_ROOT: document.getElementById("documentation_options").getAttribute('data-url_root'), + VERSION: '3.26.2', + LANGUAGE: 'None', + COLLAPSE_INDEX: false, + BUILDER: 'html', + FILE_SUFFIX: '.html', + LINK_SUFFIX: '.html', + HAS_SOURCE: true, + SOURCELINK_SUFFIX: '.txt', + NAVIGATION_WITH_KEYS: false +}; \ No newline at end of file diff --git a/_static/file.png b/_static/file.png new file mode 100644 index 0000000000..a858a410e4 Binary files /dev/null and b/_static/file.png differ diff --git a/_static/img/banner-background.svg b/_static/img/banner-background.svg new file mode 100644 index 0000000000..f8520d5b3e --- /dev/null +++ b/_static/img/banner-background.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/_static/img/favicon-228x228.png b/_static/img/favicon-228x228.png new file mode 100644 index 0000000000..f30770c7ed Binary files /dev/null and b/_static/img/favicon-228x228.png differ diff --git a/_static/img/favicon-32x32.png b/_static/img/favicon-32x32.png new file mode 100644 index 0000000000..aae1708f26 Binary files /dev/null and b/_static/img/favicon-32x32.png differ diff --git a/_static/img/favicon.ico b/_static/img/favicon.ico new file mode 100644 index 0000000000..6c7484f082 Binary files /dev/null and b/_static/img/favicon.ico differ diff --git a/_static/img/icons/icon-about-team.svg b/_static/img/icons/icon-about-team.svg new file mode 100644 index 0000000000..5448c7f007 --- /dev/null +++ b/_static/img/icons/icon-about-team.svg @@ -0,0 +1 @@ +icon-about-team diff --git a/_static/img/icons/icon-about-us-m.svg b/_static/img/icons/icon-about-us-m.svg new file mode 100644 index 0000000000..09107d9520 --- /dev/null +++ b/_static/img/icons/icon-about-us-m.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/_static/img/icons/icon-about-us.svg b/_static/img/icons/icon-about-us.svg new file mode 100644 index 0000000000..1b1fcc83e3 --- /dev/null +++ b/_static/img/icons/icon-about-us.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/_static/img/icons/icon-alternator.svg b/_static/img/icons/icon-alternator.svg new file mode 100644 index 0000000000..7c2b4ebae0 --- /dev/null +++ b/_static/img/icons/icon-alternator.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/_static/img/icons/icon-apps.svg b/_static/img/icons/icon-apps.svg new file mode 100644 index 0000000000..7e93612026 --- /dev/null +++ b/_static/img/icons/icon-apps.svg @@ -0,0 +1 @@ + diff --git a/_static/img/icons/icon-architecture.svg b/_static/img/icons/icon-architecture.svg new file mode 100644 index 0000000000..67ebbc2f38 --- /dev/null +++ b/_static/img/icons/icon-architecture.svg @@ -0,0 +1 @@ +icon-architecture diff --git a/_static/img/icons/icon-benchmarks.svg b/_static/img/icons/icon-benchmarks.svg new file mode 100644 index 0000000000..e1ce2c1d78 --- /dev/null +++ b/_static/img/icons/icon-benchmarks.svg @@ -0,0 +1 @@ +icon-benchmarks diff --git a/_static/img/icons/icon-blog.svg b/_static/img/icons/icon-blog.svg new file mode 100644 index 0000000000..f4096cbf11 --- /dev/null +++ b/_static/img/icons/icon-blog.svg @@ -0,0 +1 @@ +icon-blog2 diff --git a/_static/img/icons/icon-careers.svg b/_static/img/icons/icon-careers.svg new file mode 100644 index 0000000000..2a7c6ea0b7 --- /dev/null +++ b/_static/img/icons/icon-careers.svg @@ -0,0 +1 @@ +icon-careers diff --git a/_static/img/icons/icon-chevron-left.svg b/_static/img/icons/icon-chevron-left.svg new file mode 100644 index 0000000000..3afa25c481 --- /dev/null +++ b/_static/img/icons/icon-chevron-left.svg @@ -0,0 +1,3 @@ + + + diff --git a/_static/img/icons/icon-chevron-right.svg b/_static/img/icons/icon-chevron-right.svg new file mode 100644 index 0000000000..44eb829cdc --- /dev/null +++ b/_static/img/icons/icon-chevron-right.svg @@ -0,0 +1,3 @@ + + + diff --git a/_static/img/icons/icon-circe.svg b/_static/img/icons/icon-circe.svg new file mode 100644 index 0000000000..875e421670 --- /dev/null +++ b/_static/img/icons/icon-circe.svg @@ -0,0 +1 @@ + diff --git a/_static/img/icons/icon-clock.svg b/_static/img/icons/icon-clock.svg new file mode 100644 index 0000000000..8c92469808 --- /dev/null +++ b/_static/img/icons/icon-clock.svg @@ -0,0 +1 @@ + diff --git a/_static/img/icons/icon-close.svg b/_static/img/icons/icon-close.svg new file mode 100644 index 0000000000..d1162b73e7 --- /dev/null +++ b/_static/img/icons/icon-close.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/_static/img/icons/icon-cloud-docs.svg b/_static/img/icons/icon-cloud-docs.svg new file mode 100644 index 0000000000..a9069bb6e5 --- /dev/null +++ b/_static/img/icons/icon-cloud-docs.svg @@ -0,0 +1 @@ + diff --git a/_static/img/icons/icon-cloud.svg b/_static/img/icons/icon-cloud.svg new file mode 100644 index 0000000000..cfb2318dae --- /dev/null +++ b/_static/img/icons/icon-cloud.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/_static/img/icons/icon-comparison.svg b/_static/img/icons/icon-comparison.svg new file mode 100644 index 0000000000..49d809a5df --- /dev/null +++ b/_static/img/icons/icon-comparison.svg @@ -0,0 +1 @@ +icon-comparison diff --git a/_static/img/icons/icon-contact-us.svg b/_static/img/icons/icon-contact-us.svg new file mode 100644 index 0000000000..9df3145dd2 --- /dev/null +++ b/_static/img/icons/icon-contact-us.svg @@ -0,0 +1 @@ +icon-contact-us diff --git a/_static/img/icons/icon-developers-blog.svg b/_static/img/icons/icon-developers-blog.svg new file mode 100644 index 0000000000..ee804197a0 --- /dev/null +++ b/_static/img/icons/icon-developers-blog.svg @@ -0,0 +1 @@ +icon-developers-blog diff --git a/_static/img/icons/icon-docs.svg b/_static/img/icons/icon-docs.svg new file mode 100644 index 0000000000..5501492f3e --- /dev/null +++ b/_static/img/icons/icon-docs.svg @@ -0,0 +1 @@ +icon-docs diff --git a/_static/img/icons/icon-enterprise-m.svg b/_static/img/icons/icon-enterprise-m.svg new file mode 100644 index 0000000000..97be900b50 --- /dev/null +++ b/_static/img/icons/icon-enterprise-m.svg @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/_static/img/icons/icon-enterprise.svg b/_static/img/icons/icon-enterprise.svg new file mode 100644 index 0000000000..ee1ac26283 --- /dev/null +++ b/_static/img/icons/icon-enterprise.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/_static/img/icons/icon-events.svg b/_static/img/icons/icon-events.svg new file mode 100644 index 0000000000..ba5f211864 --- /dev/null +++ b/_static/img/icons/icon-events.svg @@ -0,0 +1 @@ +icon-events diff --git a/_static/img/icons/icon-exclamation.svg b/_static/img/icons/icon-exclamation.svg new file mode 100644 index 0000000000..a7eb4b77a4 --- /dev/null +++ b/_static/img/icons/icon-exclamation.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/_static/img/icons/icon-expand.svg b/_static/img/icons/icon-expand.svg new file mode 100644 index 0000000000..3806565367 --- /dev/null +++ b/_static/img/icons/icon-expand.svg @@ -0,0 +1,50 @@ + + + + + + + + + diff --git a/_static/img/icons/icon-forum.svg b/_static/img/icons/icon-forum.svg new file mode 100644 index 0000000000..37a709f7a8 --- /dev/null +++ b/_static/img/icons/icon-forum.svg @@ -0,0 +1 @@ + diff --git a/_static/img/icons/icon-getting-started.svg b/_static/img/icons/icon-getting-started.svg new file mode 100644 index 0000000000..702500be40 --- /dev/null +++ b/_static/img/icons/icon-getting-started.svg @@ -0,0 +1 @@ + diff --git a/_static/img/icons/icon-glossary.svg b/_static/img/icons/icon-glossary.svg new file mode 100644 index 0000000000..e8329c2afe --- /dev/null +++ b/_static/img/icons/icon-glossary.svg @@ -0,0 +1 @@ + diff --git a/_static/img/icons/icon-home.svg b/_static/img/icons/icon-home.svg new file mode 100644 index 0000000000..f0b9c25419 --- /dev/null +++ b/_static/img/icons/icon-home.svg @@ -0,0 +1 @@ + diff --git a/_static/img/icons/icon-infoworld.svg b/_static/img/icons/icon-infoworld.svg new file mode 100644 index 0000000000..906e87279c --- /dev/null +++ b/_static/img/icons/icon-infoworld.svg @@ -0,0 +1 @@ +icon-infoworld diff --git a/_static/img/icons/icon-integrations.svg b/_static/img/icons/icon-integrations.svg new file mode 100644 index 0000000000..1ef0920d49 --- /dev/null +++ b/_static/img/icons/icon-integrations.svg @@ -0,0 +1 @@ + diff --git a/_static/img/icons/icon-knowledge-base.svg b/_static/img/icons/icon-knowledge-base.svg new file mode 100644 index 0000000000..884451270d --- /dev/null +++ b/_static/img/icons/icon-knowledge-base.svg @@ -0,0 +1 @@ + diff --git a/_static/img/icons/icon-less.svg b/_static/img/icons/icon-less.svg new file mode 100644 index 0000000000..3094127dec --- /dev/null +++ b/_static/img/icons/icon-less.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/_static/img/icons/icon-live-test.svg b/_static/img/icons/icon-live-test.svg new file mode 100644 index 0000000000..dcb5916c26 --- /dev/null +++ b/_static/img/icons/icon-live-test.svg @@ -0,0 +1 @@ +icon-live-test diff --git a/_static/img/icons/icon-mail-list.svg b/_static/img/icons/icon-mail-list.svg new file mode 100644 index 0000000000..0e6192a352 --- /dev/null +++ b/_static/img/icons/icon-mail-list.svg @@ -0,0 +1 @@ + diff --git a/_static/img/icons/icon-manager.svg b/_static/img/icons/icon-manager.svg new file mode 100644 index 0000000000..02b4e425be --- /dev/null +++ b/_static/img/icons/icon-manager.svg @@ -0,0 +1 @@ +icon-manager diff --git a/_static/img/icons/icon-memory-management.svg b/_static/img/icons/icon-memory-management.svg new file mode 100644 index 0000000000..e34eb4504f --- /dev/null +++ b/_static/img/icons/icon-memory-management.svg @@ -0,0 +1 @@ +icon-memory-management diff --git a/_static/img/icons/icon-modeling.svg b/_static/img/icons/icon-modeling.svg new file mode 100644 index 0000000000..97fa3a0e21 --- /dev/null +++ b/_static/img/icons/icon-modeling.svg @@ -0,0 +1 @@ + diff --git a/_static/img/icons/icon-monitoring.svg b/_static/img/icons/icon-monitoring.svg new file mode 100644 index 0000000000..80b3787f66 --- /dev/null +++ b/_static/img/icons/icon-monitoring.svg @@ -0,0 +1 @@ +icon-monitoring diff --git a/_static/img/icons/icon-networking.svg b/_static/img/icons/icon-networking.svg new file mode 100644 index 0000000000..40a3fd5f6f --- /dev/null +++ b/_static/img/icons/icon-networking.svg @@ -0,0 +1 @@ +icon-networking diff --git a/_static/img/icons/icon-news.svg b/_static/img/icons/icon-news.svg new file mode 100644 index 0000000000..a952b59937 --- /dev/null +++ b/_static/img/icons/icon-news.svg @@ -0,0 +1 @@ +icon-news diff --git a/_static/img/icons/icon-newsletter.svg b/_static/img/icons/icon-newsletter.svg new file mode 100644 index 0000000000..5b8d47eb15 --- /dev/null +++ b/_static/img/icons/icon-newsletter.svg @@ -0,0 +1 @@ +icon-newsletter diff --git a/_static/img/icons/icon-nsql-guides.svg b/_static/img/icons/icon-nsql-guides.svg new file mode 100644 index 0000000000..60ebab3795 --- /dev/null +++ b/_static/img/icons/icon-nsql-guides.svg @@ -0,0 +1 @@ +icon-nsql-guides diff --git a/_static/img/icons/icon-open-source.svg b/_static/img/icons/icon-open-source.svg new file mode 100644 index 0000000000..98c2ea7d5b --- /dev/null +++ b/_static/img/icons/icon-open-source.svg @@ -0,0 +1 @@ +icon-open-source diff --git a/_static/img/icons/icon-operator.svg b/_static/img/icons/icon-operator.svg new file mode 100644 index 0000000000..bb7d8d3ea8 --- /dev/null +++ b/_static/img/icons/icon-operator.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/_static/img/icons/icon-overview.svg b/_static/img/icons/icon-overview.svg new file mode 100644 index 0000000000..515c1528a2 --- /dev/null +++ b/_static/img/icons/icon-overview.svg @@ -0,0 +1 @@ +icon-overview diff --git a/_static/img/icons/icon-partners.svg b/_static/img/icons/icon-partners.svg new file mode 100644 index 0000000000..d0146fc497 --- /dev/null +++ b/_static/img/icons/icon-partners.svg @@ -0,0 +1 @@ +icon-partners diff --git a/_static/img/icons/icon-plus.svg b/_static/img/icons/icon-plus.svg new file mode 100644 index 0000000000..5757435085 --- /dev/null +++ b/_static/img/icons/icon-plus.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/_static/img/icons/icon-pricing.svg b/_static/img/icons/icon-pricing.svg new file mode 100644 index 0000000000..74b01db168 --- /dev/null +++ b/_static/img/icons/icon-pricing.svg @@ -0,0 +1 @@ +icon-pricing$ diff --git a/_static/img/icons/icon-release-notes.svg b/_static/img/icons/icon-release-notes.svg new file mode 100644 index 0000000000..80c490c7b0 --- /dev/null +++ b/_static/img/icons/icon-release-notes.svg @@ -0,0 +1 @@ +icon-release-notes diff --git a/_static/img/icons/icon-resource-center.svg b/_static/img/icons/icon-resource-center.svg new file mode 100644 index 0000000000..6e3ab08e79 --- /dev/null +++ b/_static/img/icons/icon-resource-center.svg @@ -0,0 +1 @@ +icon-ressource-center diff --git a/_static/img/icons/icon-roadmap.svg b/_static/img/icons/icon-roadmap.svg new file mode 100644 index 0000000000..c8cbf67c8c --- /dev/null +++ b/_static/img/icons/icon-roadmap.svg @@ -0,0 +1 @@ +icon-roadmap-4 diff --git a/_static/img/icons/icon-search.svg b/_static/img/icons/icon-search.svg new file mode 100644 index 0000000000..81aae93eef --- /dev/null +++ b/_static/img/icons/icon-search.svg @@ -0,0 +1,4 @@ + + + + diff --git a/_static/img/icons/icon-slack.svg b/_static/img/icons/icon-slack.svg new file mode 100644 index 0000000000..fc164ea1e7 --- /dev/null +++ b/_static/img/icons/icon-slack.svg @@ -0,0 +1 @@ + diff --git a/_static/img/icons/icon-stack-overflow.svg b/_static/img/icons/icon-stack-overflow.svg new file mode 100644 index 0000000000..bebe9b8274 --- /dev/null +++ b/_static/img/icons/icon-stack-overflow.svg @@ -0,0 +1,4 @@ + + + + diff --git a/_static/img/icons/icon-summit.svg b/_static/img/icons/icon-summit.svg new file mode 100644 index 0000000000..4b900bd0c0 --- /dev/null +++ b/_static/img/icons/icon-summit.svg @@ -0,0 +1 @@ + diff --git a/_static/img/icons/icon-support.svg b/_static/img/icons/icon-support.svg new file mode 100644 index 0000000000..a4228b34e8 --- /dev/null +++ b/_static/img/icons/icon-support.svg @@ -0,0 +1 @@ +icon-support diff --git a/_static/img/icons/icon-tech-talks.svg b/_static/img/icons/icon-tech-talks.svg new file mode 100644 index 0000000000..df42b5522b --- /dev/null +++ b/_static/img/icons/icon-tech-talks.svg @@ -0,0 +1 @@ +icon-tech-talks diff --git a/_static/img/icons/icon-testing.svg b/_static/img/icons/icon-testing.svg new file mode 100644 index 0000000000..2fe54efdbc --- /dev/null +++ b/_static/img/icons/icon-testing.svg @@ -0,0 +1 @@ +icon-testing diff --git a/_static/img/icons/icon-thumbs-down.svg b/_static/img/icons/icon-thumbs-down.svg new file mode 100644 index 0000000000..3e7bcd6d90 --- /dev/null +++ b/_static/img/icons/icon-thumbs-down.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/_static/img/icons/icon-thumbs-up.svg b/_static/img/icons/icon-thumbs-up.svg new file mode 100644 index 0000000000..226c44d853 --- /dev/null +++ b/_static/img/icons/icon-thumbs-up.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/_static/img/icons/icon-tip.svg b/_static/img/icons/icon-tip.svg new file mode 100644 index 0000000000..bf7aa6af84 --- /dev/null +++ b/_static/img/icons/icon-tip.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/_static/img/icons/icon-training.svg b/_static/img/icons/icon-training.svg new file mode 100644 index 0000000000..08b95a88ed --- /dev/null +++ b/_static/img/icons/icon-training.svg @@ -0,0 +1 @@ +icon-training diff --git a/_static/img/icons/icon-triangle-down.svg b/_static/img/icons/icon-triangle-down.svg new file mode 100644 index 0000000000..e8ae088106 --- /dev/null +++ b/_static/img/icons/icon-triangle-down.svg @@ -0,0 +1,3 @@ + + + diff --git a/_static/img/icons/icon-university.svg b/_static/img/icons/icon-university.svg new file mode 100644 index 0000000000..f7547ab959 --- /dev/null +++ b/_static/img/icons/icon-university.svg @@ -0,0 +1 @@ +icon-university diff --git a/_static/img/icons/icon-users-blog.svg b/_static/img/icons/icon-users-blog.svg new file mode 100644 index 0000000000..47e56cddcf --- /dev/null +++ b/_static/img/icons/icon-users-blog.svg @@ -0,0 +1 @@ +icon-users-blog diff --git a/_static/img/icons/icon-warning.svg b/_static/img/icons/icon-warning.svg new file mode 100644 index 0000000000..e4b1d40331 --- /dev/null +++ b/_static/img/icons/icon-warning.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/_static/img/icons/icon-webinars.svg b/_static/img/icons/icon-webinars.svg new file mode 100644 index 0000000000..5e9f5cd427 --- /dev/null +++ b/_static/img/icons/icon-webinars.svg @@ -0,0 +1 @@ +icon-webinars diff --git a/_static/img/icons/icon-whitepapers.svg b/_static/img/icons/icon-whitepapers.svg new file mode 100644 index 0000000000..3351e51d23 --- /dev/null +++ b/_static/img/icons/icon-whitepapers.svg @@ -0,0 +1 @@ +icon-whitepapers diff --git a/_static/img/icons/icon-workshop.svg b/_static/img/icons/icon-workshop.svg new file mode 100644 index 0000000000..5206e58e98 --- /dev/null +++ b/_static/img/icons/icon-workshop.svg @@ -0,0 +1 @@ + diff --git a/_static/img/logo-docs.svg b/_static/img/logo-docs.svg new file mode 100644 index 0000000000..4fff669cb6 --- /dev/null +++ b/_static/img/logo-docs.svg @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/_static/img/logo-scylla-horizontal-RGB.svg b/_static/img/logo-scylla-horizontal-RGB.svg new file mode 100644 index 0000000000..b5022d7c4d --- /dev/null +++ b/_static/img/logo-scylla-horizontal-RGB.svg @@ -0,0 +1,74 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/_static/img/mascots/404.jpg b/_static/img/mascots/404.jpg new file mode 100644 index 0000000000..769fa0889f Binary files /dev/null and b/_static/img/mascots/404.jpg differ diff --git a/_static/img/mascots/scylla-3monsters.png b/_static/img/mascots/scylla-3monsters.png new file mode 100644 index 0000000000..7c06d01674 Binary files /dev/null and b/_static/img/mascots/scylla-3monsters.png differ diff --git a/_static/img/mascots/scylla-advisor-crystal.png b/_static/img/mascots/scylla-advisor-crystal.png new file mode 100644 index 0000000000..d33fddd62f Binary files /dev/null and b/_static/img/mascots/scylla-advisor-crystal.png differ diff --git a/_static/img/mascots/scylla-alternator.svg b/_static/img/mascots/scylla-alternator.svg new file mode 100644 index 0000000000..0462f893d5 --- /dev/null +++ b/_static/img/mascots/scylla-alternator.svg @@ -0,0 +1 @@ +scylla-alternator diff --git a/_static/img/mascots/scylla-cloud.svg b/_static/img/mascots/scylla-cloud.svg new file mode 100644 index 0000000000..a6c6a26fc9 --- /dev/null +++ b/_static/img/mascots/scylla-cloud.svg @@ -0,0 +1 @@ +scylla-cloud diff --git a/_static/img/mascots/scylla-computer-3-monsters.png b/_static/img/mascots/scylla-computer-3-monsters.png new file mode 100644 index 0000000000..d0368a7027 Binary files /dev/null and b/_static/img/mascots/scylla-computer-3-monsters.png differ diff --git a/_static/img/mascots/scylla-computer-headset.png b/_static/img/mascots/scylla-computer-headset.png new file mode 100644 index 0000000000..0cdadaa216 Binary files /dev/null and b/_static/img/mascots/scylla-computer-headset.png differ diff --git a/_static/img/mascots/scylla-cup-number-one.png b/_static/img/mascots/scylla-cup-number-one.png new file mode 100644 index 0000000000..e889f4e368 Binary files /dev/null and b/_static/img/mascots/scylla-cup-number-one.png differ diff --git a/_static/img/mascots/scylla-docs.svg b/_static/img/mascots/scylla-docs.svg new file mode 100644 index 0000000000..a5bce950c2 --- /dev/null +++ b/_static/img/mascots/scylla-docs.svg @@ -0,0 +1 @@ +scylla-docs diff --git a/_static/img/mascots/scylla-drivers.svg b/_static/img/mascots/scylla-drivers.svg new file mode 100644 index 0000000000..6012e71679 --- /dev/null +++ b/_static/img/mascots/scylla-drivers.svg @@ -0,0 +1 @@ +scylla-manager diff --git a/_static/img/mascots/scylla-enterprise.svg b/_static/img/mascots/scylla-enterprise.svg new file mode 100644 index 0000000000..a1aa0b46ac --- /dev/null +++ b/_static/img/mascots/scylla-enterprise.svg @@ -0,0 +1 @@ +scylla-enterprise diff --git a/_static/img/mascots/scylla-forklift-boxes.png b/_static/img/mascots/scylla-forklift-boxes.png new file mode 100644 index 0000000000..f64c29e6c7 Binary files /dev/null and b/_static/img/mascots/scylla-forklift-boxes.png differ diff --git a/_static/img/mascots/scylla-forklift-migration.png b/_static/img/mascots/scylla-forklift-migration.png new file mode 100644 index 0000000000..d2f645c645 Binary files /dev/null and b/_static/img/mascots/scylla-forklift-migration.png differ diff --git a/_static/img/mascots/scylla-gear.png b/_static/img/mascots/scylla-gear.png new file mode 100644 index 0000000000..0f53b26afa Binary files /dev/null and b/_static/img/mascots/scylla-gear.png differ diff --git a/_static/img/mascots/scylla-hardhat.png b/_static/img/mascots/scylla-hardhat.png new file mode 100644 index 0000000000..630f2d9094 Binary files /dev/null and b/_static/img/mascots/scylla-hardhat.png differ diff --git a/_static/img/mascots/scylla-headband.png b/_static/img/mascots/scylla-headband.png new file mode 100644 index 0000000000..c87abe684d Binary files /dev/null and b/_static/img/mascots/scylla-headband.png differ diff --git a/_static/img/mascots/scylla-headset.png b/_static/img/mascots/scylla-headset.png new file mode 100644 index 0000000000..ba52cd223d Binary files /dev/null and b/_static/img/mascots/scylla-headset.png differ diff --git a/_static/img/mascots/scylla-hearts.png b/_static/img/mascots/scylla-hearts.png new file mode 100644 index 0000000000..cef08c8654 Binary files /dev/null and b/_static/img/mascots/scylla-hearts.png differ diff --git a/_static/img/mascots/scylla-looking-down.png b/_static/img/mascots/scylla-looking-down.png new file mode 100644 index 0000000000..75cccbfdf1 Binary files /dev/null and b/_static/img/mascots/scylla-looking-down.png differ diff --git a/_static/img/mascots/scylla-looking-up.png b/_static/img/mascots/scylla-looking-up.png new file mode 100644 index 0000000000..6f10405f21 Binary files /dev/null and b/_static/img/mascots/scylla-looking-up.png differ diff --git a/_static/img/mascots/scylla-magnifying-glass-fronting.png b/_static/img/mascots/scylla-magnifying-glass-fronting.png new file mode 100644 index 0000000000..e368cae169 Binary files /dev/null and b/_static/img/mascots/scylla-magnifying-glass-fronting.png differ diff --git a/_static/img/mascots/scylla-magnifying-glass.png b/_static/img/mascots/scylla-magnifying-glass.png new file mode 100644 index 0000000000..74ad669500 Binary files /dev/null and b/_static/img/mascots/scylla-magnifying-glass.png differ diff --git a/_static/img/mascots/scylla-manager.svg b/_static/img/mascots/scylla-manager.svg new file mode 100644 index 0000000000..6ba9ed937c --- /dev/null +++ b/_static/img/mascots/scylla-manager.svg @@ -0,0 +1 @@ +scylla-manager-2 diff --git a/_static/img/mascots/scylla-monitor.svg b/_static/img/mascots/scylla-monitor.svg new file mode 100644 index 0000000000..48bec7dde3 --- /dev/null +++ b/_static/img/mascots/scylla-monitor.svg @@ -0,0 +1 @@ +scylla-monitor diff --git a/_static/img/mascots/scylla-movement-fast.png b/_static/img/mascots/scylla-movement-fast.png new file mode 100644 index 0000000000..956d1dd0e2 Binary files /dev/null and b/_static/img/mascots/scylla-movement-fast.png differ diff --git a/_static/img/mascots/scylla-movement.png b/_static/img/mascots/scylla-movement.png new file mode 100644 index 0000000000..7ee2b04338 Binary files /dev/null and b/_static/img/mascots/scylla-movement.png differ diff --git a/_static/img/mascots/scylla-onpremise.png b/_static/img/mascots/scylla-onpremise.png new file mode 100644 index 0000000000..3b2dc8f1a2 Binary files /dev/null and b/_static/img/mascots/scylla-onpremise.png differ diff --git a/_static/img/mascots/scylla-opensource.svg b/_static/img/mascots/scylla-opensource.svg new file mode 100644 index 0000000000..299e9cb995 --- /dev/null +++ b/_static/img/mascots/scylla-opensource.svg @@ -0,0 +1 @@ +Plan de travail 1 diff --git a/_static/img/mascots/scylla-operator.svg b/_static/img/mascots/scylla-operator.svg new file mode 100644 index 0000000000..655a450b2a --- /dev/null +++ b/_static/img/mascots/scylla-operator.svg @@ -0,0 +1 @@ +scylla-operator diff --git a/_static/img/mascots/scylla-plugin.png b/_static/img/mascots/scylla-plugin.png new file mode 100644 index 0000000000..b28dc857cc Binary files /dev/null and b/_static/img/mascots/scylla-plugin.png differ diff --git a/_static/img/mascots/scylla-release-mascot.png b/_static/img/mascots/scylla-release-mascot.png new file mode 100644 index 0000000000..09342ac687 Binary files /dev/null and b/_static/img/mascots/scylla-release-mascot.png differ diff --git a/_static/img/mascots/scylla-repair.png b/_static/img/mascots/scylla-repair.png new file mode 100644 index 0000000000..9b4c613e70 Binary files /dev/null and b/_static/img/mascots/scylla-repair.png differ diff --git a/_static/img/mascots/scylla-server.png b/_static/img/mascots/scylla-server.png new file mode 100644 index 0000000000..96dc785298 Binary files /dev/null and b/_static/img/mascots/scylla-server.png differ diff --git a/_static/img/mascots/scylla-sleeping.png b/_static/img/mascots/scylla-sleeping.png new file mode 100644 index 0000000000..f88598e05a Binary files /dev/null and b/_static/img/mascots/scylla-sleeping.png differ diff --git a/_static/img/mascots/scylla-tall-measure.png b/_static/img/mascots/scylla-tall-measure.png new file mode 100644 index 0000000000..6f0ca146c0 Binary files /dev/null and b/_static/img/mascots/scylla-tall-measure.png differ diff --git a/_static/img/mascots/scylla-university.png b/_static/img/mascots/scylla-university.png new file mode 100644 index 0000000000..b3d0621193 Binary files /dev/null and b/_static/img/mascots/scylla-university.png differ diff --git a/_static/img/mascots/scylla-weights.png b/_static/img/mascots/scylla-weights.png new file mode 100644 index 0000000000..b070bb022c Binary files /dev/null and b/_static/img/mascots/scylla-weights.png differ diff --git a/_static/img/mascots/scylla-window-cleaning.png b/_static/img/mascots/scylla-window-cleaning.png new file mode 100644 index 0000000000..6a8b16a6b4 Binary files /dev/null and b/_static/img/mascots/scylla-window-cleaning.png differ diff --git a/_static/img/mascots/scylla-with-computer-2.png b/_static/img/mascots/scylla-with-computer-2.png new file mode 100644 index 0000000000..f3b8b2984f Binary files /dev/null and b/_static/img/mascots/scylla-with-computer-2.png differ diff --git a/_static/img/mascots/scylla-with-computer.png b/_static/img/mascots/scylla-with-computer.png new file mode 100644 index 0000000000..b38a6fbbe0 Binary files /dev/null and b/_static/img/mascots/scylla-with-computer.png differ diff --git a/_static/img/mascots/scylla-with-linux.png b/_static/img/mascots/scylla-with-linux.png new file mode 100644 index 0000000000..954bf13bc2 Binary files /dev/null and b/_static/img/mascots/scylla-with-linux.png differ diff --git a/_static/img/mascots/scylla-writting.png b/_static/img/mascots/scylla-writting.png new file mode 100644 index 0000000000..d35a13d380 Binary files /dev/null and b/_static/img/mascots/scylla-writting.png differ diff --git a/_static/img/menu.svg b/_static/img/menu.svg new file mode 100644 index 0000000000..30ea1d901e --- /dev/null +++ b/_static/img/menu.svg @@ -0,0 +1,3 @@ + + + diff --git a/_static/jquery-3.5.1.js b/_static/jquery-3.5.1.js new file mode 100644 index 0000000000..50937333b9 --- /dev/null +++ b/_static/jquery-3.5.1.js @@ -0,0 +1,10872 @@ +/*! + * jQuery JavaScript Library v3.5.1 + * https://jquery.com/ + * + * Includes Sizzle.js + * https://sizzlejs.com/ + * + * Copyright JS Foundation and other contributors + * Released under the MIT license + * https://jquery.org/license + * + * Date: 2020-05-04T22:49Z + */ +( function( global, factory ) { + + "use strict"; + + if ( typeof module === "object" && typeof module.exports === "object" ) { + + // For CommonJS and CommonJS-like environments where a proper `window` + // is present, execute the factory and get jQuery. + // For environments that do not have a `window` with a `document` + // (such as Node.js), expose a factory as module.exports. + // This accentuates the need for the creation of a real `window`. + // e.g. var jQuery = require("jquery")(window); + // See ticket #14549 for more info. + module.exports = global.document ? + factory( global, true ) : + function( w ) { + if ( !w.document ) { + throw new Error( "jQuery requires a window with a document" ); + } + return factory( w ); + }; + } else { + factory( global ); + } + +// Pass this if window is not defined yet +} )( typeof window !== "undefined" ? window : this, function( window, noGlobal ) { + +// Edge <= 12 - 13+, Firefox <=18 - 45+, IE 10 - 11, Safari 5.1 - 9+, iOS 6 - 9.1 +// throw exceptions when non-strict code (e.g., ASP.NET 4.5) accesses strict mode +// arguments.callee.caller (trac-13335). But as of jQuery 3.0 (2016), strict mode should be common +// enough that all such attempts are guarded in a try block. +"use strict"; + +var arr = []; + +var getProto = Object.getPrototypeOf; + +var slice = arr.slice; + +var flat = arr.flat ? function( array ) { + return arr.flat.call( array ); +} : function( array ) { + return arr.concat.apply( [], array ); +}; + + +var push = arr.push; + +var indexOf = arr.indexOf; + +var class2type = {}; + +var toString = class2type.toString; + +var hasOwn = class2type.hasOwnProperty; + +var fnToString = hasOwn.toString; + +var ObjectFunctionString = fnToString.call( Object ); + +var support = {}; + +var isFunction = function isFunction( obj ) { + + // Support: Chrome <=57, Firefox <=52 + // In some browsers, typeof returns "function" for HTML elements + // (i.e., `typeof document.createElement( "object" ) === "function"`). + // We don't want to classify *any* DOM node as a function. + return typeof obj === "function" && typeof obj.nodeType !== "number"; + }; + + +var isWindow = function isWindow( obj ) { + return obj != null && obj === obj.window; + }; + + +var document = window.document; + + + + var preservedScriptAttributes = { + type: true, + src: true, + nonce: true, + noModule: true + }; + + function DOMEval( code, node, doc ) { + doc = doc || document; + + var i, val, + script = doc.createElement( "script" ); + + script.text = code; + if ( node ) { + for ( i in preservedScriptAttributes ) { + + // Support: Firefox 64+, Edge 18+ + // Some browsers don't support the "nonce" property on scripts. + // On the other hand, just using `getAttribute` is not enough as + // the `nonce` attribute is reset to an empty string whenever it + // becomes browsing-context connected. + // See https://github.com/whatwg/html/issues/2369 + // See https://html.spec.whatwg.org/#nonce-attributes + // The `node.getAttribute` check was added for the sake of + // `jQuery.globalEval` so that it can fake a nonce-containing node + // via an object. + val = node[ i ] || node.getAttribute && node.getAttribute( i ); + if ( val ) { + script.setAttribute( i, val ); + } + } + } + doc.head.appendChild( script ).parentNode.removeChild( script ); + } + + +function toType( obj ) { + if ( obj == null ) { + return obj + ""; + } + + // Support: Android <=2.3 only (functionish RegExp) + return typeof obj === "object" || typeof obj === "function" ? + class2type[ toString.call( obj ) ] || "object" : + typeof obj; +} +/* global Symbol */ +// Defining this global in .eslintrc.json would create a danger of using the global +// unguarded in another place, it seems safer to define global only for this module + + + +var + version = "3.5.1", + + // Define a local copy of jQuery + jQuery = function( selector, context ) { + + // The jQuery object is actually just the init constructor 'enhanced' + // Need init if jQuery is called (just allow error to be thrown if not included) + return new jQuery.fn.init( selector, context ); + }; + +jQuery.fn = jQuery.prototype = { + + // The current version of jQuery being used + jquery: version, + + constructor: jQuery, + + // The default length of a jQuery object is 0 + length: 0, + + toArray: function() { + return slice.call( this ); + }, + + // Get the Nth element in the matched element set OR + // Get the whole matched element set as a clean array + get: function( num ) { + + // Return all the elements in a clean array + if ( num == null ) { + return slice.call( this ); + } + + // Return just the one element from the set + return num < 0 ? this[ num + this.length ] : this[ num ]; + }, + + // Take an array of elements and push it onto the stack + // (returning the new matched element set) + pushStack: function( elems ) { + + // Build a new jQuery matched element set + var ret = jQuery.merge( this.constructor(), elems ); + + // Add the old object onto the stack (as a reference) + ret.prevObject = this; + + // Return the newly-formed element set + return ret; + }, + + // Execute a callback for every element in the matched set. + each: function( callback ) { + return jQuery.each( this, callback ); + }, + + map: function( callback ) { + return this.pushStack( jQuery.map( this, function( elem, i ) { + return callback.call( elem, i, elem ); + } ) ); + }, + + slice: function() { + return this.pushStack( slice.apply( this, arguments ) ); + }, + + first: function() { + return this.eq( 0 ); + }, + + last: function() { + return this.eq( -1 ); + }, + + even: function() { + return this.pushStack( jQuery.grep( this, function( _elem, i ) { + return ( i + 1 ) % 2; + } ) ); + }, + + odd: function() { + return this.pushStack( jQuery.grep( this, function( _elem, i ) { + return i % 2; + } ) ); + }, + + eq: function( i ) { + var len = this.length, + j = +i + ( i < 0 ? len : 0 ); + return this.pushStack( j >= 0 && j < len ? [ this[ j ] ] : [] ); + }, + + end: function() { + return this.prevObject || this.constructor(); + }, + + // For internal use only. + // Behaves like an Array's method, not like a jQuery method. + push: push, + sort: arr.sort, + splice: arr.splice +}; + +jQuery.extend = jQuery.fn.extend = function() { + var options, name, src, copy, copyIsArray, clone, + target = arguments[ 0 ] || {}, + i = 1, + length = arguments.length, + deep = false; + + // Handle a deep copy situation + if ( typeof target === "boolean" ) { + deep = target; + + // Skip the boolean and the target + target = arguments[ i ] || {}; + i++; + } + + // Handle case when target is a string or something (possible in deep copy) + if ( typeof target !== "object" && !isFunction( target ) ) { + target = {}; + } + + // Extend jQuery itself if only one argument is passed + if ( i === length ) { + target = this; + i--; + } + + for ( ; i < length; i++ ) { + + // Only deal with non-null/undefined values + if ( ( options = arguments[ i ] ) != null ) { + + // Extend the base object + for ( name in options ) { + copy = options[ name ]; + + // Prevent Object.prototype pollution + // Prevent never-ending loop + if ( name === "__proto__" || target === copy ) { + continue; + } + + // Recurse if we're merging plain objects or arrays + if ( deep && copy && ( jQuery.isPlainObject( copy ) || + ( copyIsArray = Array.isArray( copy ) ) ) ) { + src = target[ name ]; + + // Ensure proper type for the source value + if ( copyIsArray && !Array.isArray( src ) ) { + clone = []; + } else if ( !copyIsArray && !jQuery.isPlainObject( src ) ) { + clone = {}; + } else { + clone = src; + } + copyIsArray = false; + + // Never move original objects, clone them + target[ name ] = jQuery.extend( deep, clone, copy ); + + // Don't bring in undefined values + } else if ( copy !== undefined ) { + target[ name ] = copy; + } + } + } + } + + // Return the modified object + return target; +}; + +jQuery.extend( { + + // Unique for each copy of jQuery on the page + expando: "jQuery" + ( version + Math.random() ).replace( /\D/g, "" ), + + // Assume jQuery is ready without the ready module + isReady: true, + + error: function( msg ) { + throw new Error( msg ); + }, + + noop: function() {}, + + isPlainObject: function( obj ) { + var proto, Ctor; + + // Detect obvious negatives + // Use toString instead of jQuery.type to catch host objects + if ( !obj || toString.call( obj ) !== "[object Object]" ) { + return false; + } + + proto = getProto( obj ); + + // Objects with no prototype (e.g., `Object.create( null )`) are plain + if ( !proto ) { + return true; + } + + // Objects with prototype are plain iff they were constructed by a global Object function + Ctor = hasOwn.call( proto, "constructor" ) && proto.constructor; + return typeof Ctor === "function" && fnToString.call( Ctor ) === ObjectFunctionString; + }, + + isEmptyObject: function( obj ) { + var name; + + for ( name in obj ) { + return false; + } + return true; + }, + + // Evaluates a script in a provided context; falls back to the global one + // if not specified. + globalEval: function( code, options, doc ) { + DOMEval( code, { nonce: options && options.nonce }, doc ); + }, + + each: function( obj, callback ) { + var length, i = 0; + + if ( isArrayLike( obj ) ) { + length = obj.length; + for ( ; i < length; i++ ) { + if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) { + break; + } + } + } else { + for ( i in obj ) { + if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) { + break; + } + } + } + + return obj; + }, + + // results is for internal usage only + makeArray: function( arr, results ) { + var ret = results || []; + + if ( arr != null ) { + if ( isArrayLike( Object( arr ) ) ) { + jQuery.merge( ret, + typeof arr === "string" ? + [ arr ] : arr + ); + } else { + push.call( ret, arr ); + } + } + + return ret; + }, + + inArray: function( elem, arr, i ) { + return arr == null ? -1 : indexOf.call( arr, elem, i ); + }, + + // Support: Android <=4.0 only, PhantomJS 1 only + // push.apply(_, arraylike) throws on ancient WebKit + merge: function( first, second ) { + var len = +second.length, + j = 0, + i = first.length; + + for ( ; j < len; j++ ) { + first[ i++ ] = second[ j ]; + } + + first.length = i; + + return first; + }, + + grep: function( elems, callback, invert ) { + var callbackInverse, + matches = [], + i = 0, + length = elems.length, + callbackExpect = !invert; + + // Go through the array, only saving the items + // that pass the validator function + for ( ; i < length; i++ ) { + callbackInverse = !callback( elems[ i ], i ); + if ( callbackInverse !== callbackExpect ) { + matches.push( elems[ i ] ); + } + } + + return matches; + }, + + // arg is for internal usage only + map: function( elems, callback, arg ) { + var length, value, + i = 0, + ret = []; + + // Go through the array, translating each of the items to their new values + if ( isArrayLike( elems ) ) { + length = elems.length; + for ( ; i < length; i++ ) { + value = callback( elems[ i ], i, arg ); + + if ( value != null ) { + ret.push( value ); + } + } + + // Go through every key on the object, + } else { + for ( i in elems ) { + value = callback( elems[ i ], i, arg ); + + if ( value != null ) { + ret.push( value ); + } + } + } + + // Flatten any nested arrays + return flat( ret ); + }, + + // A global GUID counter for objects + guid: 1, + + // jQuery.support is not used in Core but other projects attach their + // properties to it so it needs to exist. + support: support +} ); + +if ( typeof Symbol === "function" ) { + jQuery.fn[ Symbol.iterator ] = arr[ Symbol.iterator ]; +} + +// Populate the class2type map +jQuery.each( "Boolean Number String Function Array Date RegExp Object Error Symbol".split( " " ), +function( _i, name ) { + class2type[ "[object " + name + "]" ] = name.toLowerCase(); +} ); + +function isArrayLike( obj ) { + + // Support: real iOS 8.2 only (not reproducible in simulator) + // `in` check used to prevent JIT error (gh-2145) + // hasOwn isn't used here due to false negatives + // regarding Nodelist length in IE + var length = !!obj && "length" in obj && obj.length, + type = toType( obj ); + + if ( isFunction( obj ) || isWindow( obj ) ) { + return false; + } + + return type === "array" || length === 0 || + typeof length === "number" && length > 0 && ( length - 1 ) in obj; +} +var Sizzle = +/*! + * Sizzle CSS Selector Engine v2.3.5 + * https://sizzlejs.com/ + * + * Copyright JS Foundation and other contributors + * Released under the MIT license + * https://js.foundation/ + * + * Date: 2020-03-14 + */ +( function( window ) { +var i, + support, + Expr, + getText, + isXML, + tokenize, + compile, + select, + outermostContext, + sortInput, + hasDuplicate, + + // Local document vars + setDocument, + document, + docElem, + documentIsHTML, + rbuggyQSA, + rbuggyMatches, + matches, + contains, + + // Instance-specific data + expando = "sizzle" + 1 * new Date(), + preferredDoc = window.document, + dirruns = 0, + done = 0, + classCache = createCache(), + tokenCache = createCache(), + compilerCache = createCache(), + nonnativeSelectorCache = createCache(), + sortOrder = function( a, b ) { + if ( a === b ) { + hasDuplicate = true; + } + return 0; + }, + + // Instance methods + hasOwn = ( {} ).hasOwnProperty, + arr = [], + pop = arr.pop, + pushNative = arr.push, + push = arr.push, + slice = arr.slice, + + // Use a stripped-down indexOf as it's faster than native + // https://jsperf.com/thor-indexof-vs-for/5 + indexOf = function( list, elem ) { + var i = 0, + len = list.length; + for ( ; i < len; i++ ) { + if ( list[ i ] === elem ) { + return i; + } + } + return -1; + }, + + booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|" + + "ismap|loop|multiple|open|readonly|required|scoped", + + // Regular expressions + + // http://www.w3.org/TR/css3-selectors/#whitespace + whitespace = "[\\x20\\t\\r\\n\\f]", + + // https://www.w3.org/TR/css-syntax-3/#ident-token-diagram + identifier = "(?:\\\\[\\da-fA-F]{1,6}" + whitespace + + "?|\\\\[^\\r\\n\\f]|[\\w-]|[^\0-\\x7f])+", + + // Attribute selectors: http://www.w3.org/TR/selectors/#attribute-selectors + attributes = "\\[" + whitespace + "*(" + identifier + ")(?:" + whitespace + + + // Operator (capture 2) + "*([*^$|!~]?=)" + whitespace + + + // "Attribute values must be CSS identifiers [capture 5] + // or strings [capture 3 or capture 4]" + "*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|(" + identifier + "))|)" + + whitespace + "*\\]", + + pseudos = ":(" + identifier + ")(?:\\((" + + + // To reduce the number of selectors needing tokenize in the preFilter, prefer arguments: + // 1. quoted (capture 3; capture 4 or capture 5) + "('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|" + + + // 2. simple (capture 6) + "((?:\\\\.|[^\\\\()[\\]]|" + attributes + ")*)|" + + + // 3. anything else (capture 2) + ".*" + + ")\\)|)", + + // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter + rwhitespace = new RegExp( whitespace + "+", "g" ), + rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + + whitespace + "+$", "g" ), + + rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ), + rcombinators = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + + "*" ), + rdescend = new RegExp( whitespace + "|>" ), + + rpseudo = new RegExp( pseudos ), + ridentifier = new RegExp( "^" + identifier + "$" ), + + matchExpr = { + "ID": new RegExp( "^#(" + identifier + ")" ), + "CLASS": new RegExp( "^\\.(" + identifier + ")" ), + "TAG": new RegExp( "^(" + identifier + "|[*])" ), + "ATTR": new RegExp( "^" + attributes ), + "PSEUDO": new RegExp( "^" + pseudos ), + "CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + + whitespace + "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + + whitespace + "*(\\d+)|))" + whitespace + "*\\)|)", "i" ), + "bool": new RegExp( "^(?:" + booleans + ")$", "i" ), + + // For use in libraries implementing .is() + // We use this for POS matching in `select` + "needsContext": new RegExp( "^" + whitespace + + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" + whitespace + + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" ) + }, + + rhtml = /HTML$/i, + rinputs = /^(?:input|select|textarea|button)$/i, + rheader = /^h\d$/i, + + rnative = /^[^{]+\{\s*\[native \w/, + + // Easily-parseable/retrievable ID or TAG or CLASS selectors + rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/, + + rsibling = /[+~]/, + + // CSS escapes + // http://www.w3.org/TR/CSS21/syndata.html#escaped-characters + runescape = new RegExp( "\\\\[\\da-fA-F]{1,6}" + whitespace + "?|\\\\([^\\r\\n\\f])", "g" ), + funescape = function( escape, nonHex ) { + var high = "0x" + escape.slice( 1 ) - 0x10000; + + return nonHex ? + + // Strip the backslash prefix from a non-hex escape sequence + nonHex : + + // Replace a hexadecimal escape sequence with the encoded Unicode code point + // Support: IE <=11+ + // For values outside the Basic Multilingual Plane (BMP), manually construct a + // surrogate pair + high < 0 ? + String.fromCharCode( high + 0x10000 ) : + String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 ); + }, + + // CSS string/identifier serialization + // https://drafts.csswg.org/cssom/#common-serializing-idioms + rcssescape = /([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g, + fcssescape = function( ch, asCodePoint ) { + if ( asCodePoint ) { + + // U+0000 NULL becomes U+FFFD REPLACEMENT CHARACTER + if ( ch === "\0" ) { + return "\uFFFD"; + } + + // Control characters and (dependent upon position) numbers get escaped as code points + return ch.slice( 0, -1 ) + "\\" + + ch.charCodeAt( ch.length - 1 ).toString( 16 ) + " "; + } + + // Other potentially-special ASCII characters get backslash-escaped + return "\\" + ch; + }, + + // Used for iframes + // See setDocument() + // Removing the function wrapper causes a "Permission Denied" + // error in IE + unloadHandler = function() { + setDocument(); + }, + + inDisabledFieldset = addCombinator( + function( elem ) { + return elem.disabled === true && elem.nodeName.toLowerCase() === "fieldset"; + }, + { dir: "parentNode", next: "legend" } + ); + +// Optimize for push.apply( _, NodeList ) +try { + push.apply( + ( arr = slice.call( preferredDoc.childNodes ) ), + preferredDoc.childNodes + ); + + // Support: Android<4.0 + // Detect silently failing push.apply + // eslint-disable-next-line no-unused-expressions + arr[ preferredDoc.childNodes.length ].nodeType; +} catch ( e ) { + push = { apply: arr.length ? + + // Leverage slice if possible + function( target, els ) { + pushNative.apply( target, slice.call( els ) ); + } : + + // Support: IE<9 + // Otherwise append directly + function( target, els ) { + var j = target.length, + i = 0; + + // Can't trust NodeList.length + while ( ( target[ j++ ] = els[ i++ ] ) ) {} + target.length = j - 1; + } + }; +} + +function Sizzle( selector, context, results, seed ) { + var m, i, elem, nid, match, groups, newSelector, + newContext = context && context.ownerDocument, + + // nodeType defaults to 9, since context defaults to document + nodeType = context ? context.nodeType : 9; + + results = results || []; + + // Return early from calls with invalid selector or context + if ( typeof selector !== "string" || !selector || + nodeType !== 1 && nodeType !== 9 && nodeType !== 11 ) { + + return results; + } + + // Try to shortcut find operations (as opposed to filters) in HTML documents + if ( !seed ) { + setDocument( context ); + context = context || document; + + if ( documentIsHTML ) { + + // If the selector is sufficiently simple, try using a "get*By*" DOM method + // (excepting DocumentFragment context, where the methods don't exist) + if ( nodeType !== 11 && ( match = rquickExpr.exec( selector ) ) ) { + + // ID selector + if ( ( m = match[ 1 ] ) ) { + + // Document context + if ( nodeType === 9 ) { + if ( ( elem = context.getElementById( m ) ) ) { + + // Support: IE, Opera, Webkit + // TODO: identify versions + // getElementById can match elements by name instead of ID + if ( elem.id === m ) { + results.push( elem ); + return results; + } + } else { + return results; + } + + // Element context + } else { + + // Support: IE, Opera, Webkit + // TODO: identify versions + // getElementById can match elements by name instead of ID + if ( newContext && ( elem = newContext.getElementById( m ) ) && + contains( context, elem ) && + elem.id === m ) { + + results.push( elem ); + return results; + } + } + + // Type selector + } else if ( match[ 2 ] ) { + push.apply( results, context.getElementsByTagName( selector ) ); + return results; + + // Class selector + } else if ( ( m = match[ 3 ] ) && support.getElementsByClassName && + context.getElementsByClassName ) { + + push.apply( results, context.getElementsByClassName( m ) ); + return results; + } + } + + // Take advantage of querySelectorAll + if ( support.qsa && + !nonnativeSelectorCache[ selector + " " ] && + ( !rbuggyQSA || !rbuggyQSA.test( selector ) ) && + + // Support: IE 8 only + // Exclude object elements + ( nodeType !== 1 || context.nodeName.toLowerCase() !== "object" ) ) { + + newSelector = selector; + newContext = context; + + // qSA considers elements outside a scoping root when evaluating child or + // descendant combinators, which is not what we want. + // In such cases, we work around the behavior by prefixing every selector in the + // list with an ID selector referencing the scope context. + // The technique has to be used as well when a leading combinator is used + // as such selectors are not recognized by querySelectorAll. + // Thanks to Andrew Dupont for this technique. + if ( nodeType === 1 && + ( rdescend.test( selector ) || rcombinators.test( selector ) ) ) { + + // Expand context for sibling selectors + newContext = rsibling.test( selector ) && testContext( context.parentNode ) || + context; + + // We can use :scope instead of the ID hack if the browser + // supports it & if we're not changing the context. + if ( newContext !== context || !support.scope ) { + + // Capture the context ID, setting it first if necessary + if ( ( nid = context.getAttribute( "id" ) ) ) { + nid = nid.replace( rcssescape, fcssescape ); + } else { + context.setAttribute( "id", ( nid = expando ) ); + } + } + + // Prefix every selector in the list + groups = tokenize( selector ); + i = groups.length; + while ( i-- ) { + groups[ i ] = ( nid ? "#" + nid : ":scope" ) + " " + + toSelector( groups[ i ] ); + } + newSelector = groups.join( "," ); + } + + try { + push.apply( results, + newContext.querySelectorAll( newSelector ) + ); + return results; + } catch ( qsaError ) { + nonnativeSelectorCache( selector, true ); + } finally { + if ( nid === expando ) { + context.removeAttribute( "id" ); + } + } + } + } + } + + // All others + return select( selector.replace( rtrim, "$1" ), context, results, seed ); +} + +/** + * Create key-value caches of limited size + * @returns {function(string, object)} Returns the Object data after storing it on itself with + * property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength) + * deleting the oldest entry + */ +function createCache() { + var keys = []; + + function cache( key, value ) { + + // Use (key + " ") to avoid collision with native prototype properties (see Issue #157) + if ( keys.push( key + " " ) > Expr.cacheLength ) { + + // Only keep the most recent entries + delete cache[ keys.shift() ]; + } + return ( cache[ key + " " ] = value ); + } + return cache; +} + +/** + * Mark a function for special use by Sizzle + * @param {Function} fn The function to mark + */ +function markFunction( fn ) { + fn[ expando ] = true; + return fn; +} + +/** + * Support testing using an element + * @param {Function} fn Passed the created element and returns a boolean result + */ +function assert( fn ) { + var el = document.createElement( "fieldset" ); + + try { + return !!fn( el ); + } catch ( e ) { + return false; + } finally { + + // Remove from its parent by default + if ( el.parentNode ) { + el.parentNode.removeChild( el ); + } + + // release memory in IE + el = null; + } +} + +/** + * Adds the same handler for all of the specified attrs + * @param {String} attrs Pipe-separated list of attributes + * @param {Function} handler The method that will be applied + */ +function addHandle( attrs, handler ) { + var arr = attrs.split( "|" ), + i = arr.length; + + while ( i-- ) { + Expr.attrHandle[ arr[ i ] ] = handler; + } +} + +/** + * Checks document order of two siblings + * @param {Element} a + * @param {Element} b + * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b + */ +function siblingCheck( a, b ) { + var cur = b && a, + diff = cur && a.nodeType === 1 && b.nodeType === 1 && + a.sourceIndex - b.sourceIndex; + + // Use IE sourceIndex if available on both nodes + if ( diff ) { + return diff; + } + + // Check if b follows a + if ( cur ) { + while ( ( cur = cur.nextSibling ) ) { + if ( cur === b ) { + return -1; + } + } + } + + return a ? 1 : -1; +} + +/** + * Returns a function to use in pseudos for input types + * @param {String} type + */ +function createInputPseudo( type ) { + return function( elem ) { + var name = elem.nodeName.toLowerCase(); + return name === "input" && elem.type === type; + }; +} + +/** + * Returns a function to use in pseudos for buttons + * @param {String} type + */ +function createButtonPseudo( type ) { + return function( elem ) { + var name = elem.nodeName.toLowerCase(); + return ( name === "input" || name === "button" ) && elem.type === type; + }; +} + +/** + * Returns a function to use in pseudos for :enabled/:disabled + * @param {Boolean} disabled true for :disabled; false for :enabled + */ +function createDisabledPseudo( disabled ) { + + // Known :disabled false positives: fieldset[disabled] > legend:nth-of-type(n+2) :can-disable + return function( elem ) { + + // Only certain elements can match :enabled or :disabled + // https://html.spec.whatwg.org/multipage/scripting.html#selector-enabled + // https://html.spec.whatwg.org/multipage/scripting.html#selector-disabled + if ( "form" in elem ) { + + // Check for inherited disabledness on relevant non-disabled elements: + // * listed form-associated elements in a disabled fieldset + // https://html.spec.whatwg.org/multipage/forms.html#category-listed + // https://html.spec.whatwg.org/multipage/forms.html#concept-fe-disabled + // * option elements in a disabled optgroup + // https://html.spec.whatwg.org/multipage/forms.html#concept-option-disabled + // All such elements have a "form" property. + if ( elem.parentNode && elem.disabled === false ) { + + // Option elements defer to a parent optgroup if present + if ( "label" in elem ) { + if ( "label" in elem.parentNode ) { + return elem.parentNode.disabled === disabled; + } else { + return elem.disabled === disabled; + } + } + + // Support: IE 6 - 11 + // Use the isDisabled shortcut property to check for disabled fieldset ancestors + return elem.isDisabled === disabled || + + // Where there is no isDisabled, check manually + /* jshint -W018 */ + elem.isDisabled !== !disabled && + inDisabledFieldset( elem ) === disabled; + } + + return elem.disabled === disabled; + + // Try to winnow out elements that can't be disabled before trusting the disabled property. + // Some victims get caught in our net (label, legend, menu, track), but it shouldn't + // even exist on them, let alone have a boolean value. + } else if ( "label" in elem ) { + return elem.disabled === disabled; + } + + // Remaining elements are neither :enabled nor :disabled + return false; + }; +} + +/** + * Returns a function to use in pseudos for positionals + * @param {Function} fn + */ +function createPositionalPseudo( fn ) { + return markFunction( function( argument ) { + argument = +argument; + return markFunction( function( seed, matches ) { + var j, + matchIndexes = fn( [], seed.length, argument ), + i = matchIndexes.length; + + // Match elements found at the specified indexes + while ( i-- ) { + if ( seed[ ( j = matchIndexes[ i ] ) ] ) { + seed[ j ] = !( matches[ j ] = seed[ j ] ); + } + } + } ); + } ); +} + +/** + * Checks a node for validity as a Sizzle context + * @param {Element|Object=} context + * @returns {Element|Object|Boolean} The input node if acceptable, otherwise a falsy value + */ +function testContext( context ) { + return context && typeof context.getElementsByTagName !== "undefined" && context; +} + +// Expose support vars for convenience +support = Sizzle.support = {}; + +/** + * Detects XML nodes + * @param {Element|Object} elem An element or a document + * @returns {Boolean} True iff elem is a non-HTML XML node + */ +isXML = Sizzle.isXML = function( elem ) { + var namespace = elem.namespaceURI, + docElem = ( elem.ownerDocument || elem ).documentElement; + + // Support: IE <=8 + // Assume HTML when documentElement doesn't yet exist, such as inside loading iframes + // https://bugs.jquery.com/ticket/4833 + return !rhtml.test( namespace || docElem && docElem.nodeName || "HTML" ); +}; + +/** + * Sets document-related variables once based on the current document + * @param {Element|Object} [doc] An element or document object to use to set the document + * @returns {Object} Returns the current document + */ +setDocument = Sizzle.setDocument = function( node ) { + var hasCompare, subWindow, + doc = node ? node.ownerDocument || node : preferredDoc; + + // Return early if doc is invalid or already selected + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( doc == document || doc.nodeType !== 9 || !doc.documentElement ) { + return document; + } + + // Update global variables + document = doc; + docElem = document.documentElement; + documentIsHTML = !isXML( document ); + + // Support: IE 9 - 11+, Edge 12 - 18+ + // Accessing iframe documents after unload throws "permission denied" errors (jQuery #13936) + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( preferredDoc != document && + ( subWindow = document.defaultView ) && subWindow.top !== subWindow ) { + + // Support: IE 11, Edge + if ( subWindow.addEventListener ) { + subWindow.addEventListener( "unload", unloadHandler, false ); + + // Support: IE 9 - 10 only + } else if ( subWindow.attachEvent ) { + subWindow.attachEvent( "onunload", unloadHandler ); + } + } + + // Support: IE 8 - 11+, Edge 12 - 18+, Chrome <=16 - 25 only, Firefox <=3.6 - 31 only, + // Safari 4 - 5 only, Opera <=11.6 - 12.x only + // IE/Edge & older browsers don't support the :scope pseudo-class. + // Support: Safari 6.0 only + // Safari 6.0 supports :scope but it's an alias of :root there. + support.scope = assert( function( el ) { + docElem.appendChild( el ).appendChild( document.createElement( "div" ) ); + return typeof el.querySelectorAll !== "undefined" && + !el.querySelectorAll( ":scope fieldset div" ).length; + } ); + + /* Attributes + ---------------------------------------------------------------------- */ + + // Support: IE<8 + // Verify that getAttribute really returns attributes and not properties + // (excepting IE8 booleans) + support.attributes = assert( function( el ) { + el.className = "i"; + return !el.getAttribute( "className" ); + } ); + + /* getElement(s)By* + ---------------------------------------------------------------------- */ + + // Check if getElementsByTagName("*") returns only elements + support.getElementsByTagName = assert( function( el ) { + el.appendChild( document.createComment( "" ) ); + return !el.getElementsByTagName( "*" ).length; + } ); + + // Support: IE<9 + support.getElementsByClassName = rnative.test( document.getElementsByClassName ); + + // Support: IE<10 + // Check if getElementById returns elements by name + // The broken getElementById methods don't pick up programmatically-set names, + // so use a roundabout getElementsByName test + support.getById = assert( function( el ) { + docElem.appendChild( el ).id = expando; + return !document.getElementsByName || !document.getElementsByName( expando ).length; + } ); + + // ID filter and find + if ( support.getById ) { + Expr.filter[ "ID" ] = function( id ) { + var attrId = id.replace( runescape, funescape ); + return function( elem ) { + return elem.getAttribute( "id" ) === attrId; + }; + }; + Expr.find[ "ID" ] = function( id, context ) { + if ( typeof context.getElementById !== "undefined" && documentIsHTML ) { + var elem = context.getElementById( id ); + return elem ? [ elem ] : []; + } + }; + } else { + Expr.filter[ "ID" ] = function( id ) { + var attrId = id.replace( runescape, funescape ); + return function( elem ) { + var node = typeof elem.getAttributeNode !== "undefined" && + elem.getAttributeNode( "id" ); + return node && node.value === attrId; + }; + }; + + // Support: IE 6 - 7 only + // getElementById is not reliable as a find shortcut + Expr.find[ "ID" ] = function( id, context ) { + if ( typeof context.getElementById !== "undefined" && documentIsHTML ) { + var node, i, elems, + elem = context.getElementById( id ); + + if ( elem ) { + + // Verify the id attribute + node = elem.getAttributeNode( "id" ); + if ( node && node.value === id ) { + return [ elem ]; + } + + // Fall back on getElementsByName + elems = context.getElementsByName( id ); + i = 0; + while ( ( elem = elems[ i++ ] ) ) { + node = elem.getAttributeNode( "id" ); + if ( node && node.value === id ) { + return [ elem ]; + } + } + } + + return []; + } + }; + } + + // Tag + Expr.find[ "TAG" ] = support.getElementsByTagName ? + function( tag, context ) { + if ( typeof context.getElementsByTagName !== "undefined" ) { + return context.getElementsByTagName( tag ); + + // DocumentFragment nodes don't have gEBTN + } else if ( support.qsa ) { + return context.querySelectorAll( tag ); + } + } : + + function( tag, context ) { + var elem, + tmp = [], + i = 0, + + // By happy coincidence, a (broken) gEBTN appears on DocumentFragment nodes too + results = context.getElementsByTagName( tag ); + + // Filter out possible comments + if ( tag === "*" ) { + while ( ( elem = results[ i++ ] ) ) { + if ( elem.nodeType === 1 ) { + tmp.push( elem ); + } + } + + return tmp; + } + return results; + }; + + // Class + Expr.find[ "CLASS" ] = support.getElementsByClassName && function( className, context ) { + if ( typeof context.getElementsByClassName !== "undefined" && documentIsHTML ) { + return context.getElementsByClassName( className ); + } + }; + + /* QSA/matchesSelector + ---------------------------------------------------------------------- */ + + // QSA and matchesSelector support + + // matchesSelector(:active) reports false when true (IE9/Opera 11.5) + rbuggyMatches = []; + + // qSa(:focus) reports false when true (Chrome 21) + // We allow this because of a bug in IE8/9 that throws an error + // whenever `document.activeElement` is accessed on an iframe + // So, we allow :focus to pass through QSA all the time to avoid the IE error + // See https://bugs.jquery.com/ticket/13378 + rbuggyQSA = []; + + if ( ( support.qsa = rnative.test( document.querySelectorAll ) ) ) { + + // Build QSA regex + // Regex strategy adopted from Diego Perini + assert( function( el ) { + + var input; + + // Select is set to empty string on purpose + // This is to test IE's treatment of not explicitly + // setting a boolean content attribute, + // since its presence should be enough + // https://bugs.jquery.com/ticket/12359 + docElem.appendChild( el ).innerHTML = "" + + ""; + + // Support: IE8, Opera 11-12.16 + // Nothing should be selected when empty strings follow ^= or $= or *= + // The test attribute must be unknown in Opera but "safe" for WinRT + // https://msdn.microsoft.com/en-us/library/ie/hh465388.aspx#attribute_section + if ( el.querySelectorAll( "[msallowcapture^='']" ).length ) { + rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:''|\"\")" ); + } + + // Support: IE8 + // Boolean attributes and "value" are not treated correctly + if ( !el.querySelectorAll( "[selected]" ).length ) { + rbuggyQSA.push( "\\[" + whitespace + "*(?:value|" + booleans + ")" ); + } + + // Support: Chrome<29, Android<4.4, Safari<7.0+, iOS<7.0+, PhantomJS<1.9.8+ + if ( !el.querySelectorAll( "[id~=" + expando + "-]" ).length ) { + rbuggyQSA.push( "~=" ); + } + + // Support: IE 11+, Edge 15 - 18+ + // IE 11/Edge don't find elements on a `[name='']` query in some cases. + // Adding a temporary attribute to the document before the selection works + // around the issue. + // Interestingly, IE 10 & older don't seem to have the issue. + input = document.createElement( "input" ); + input.setAttribute( "name", "" ); + el.appendChild( input ); + if ( !el.querySelectorAll( "[name='']" ).length ) { + rbuggyQSA.push( "\\[" + whitespace + "*name" + whitespace + "*=" + + whitespace + "*(?:''|\"\")" ); + } + + // Webkit/Opera - :checked should return selected option elements + // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked + // IE8 throws error here and will not see later tests + if ( !el.querySelectorAll( ":checked" ).length ) { + rbuggyQSA.push( ":checked" ); + } + + // Support: Safari 8+, iOS 8+ + // https://bugs.webkit.org/show_bug.cgi?id=136851 + // In-page `selector#id sibling-combinator selector` fails + if ( !el.querySelectorAll( "a#" + expando + "+*" ).length ) { + rbuggyQSA.push( ".#.+[+~]" ); + } + + // Support: Firefox <=3.6 - 5 only + // Old Firefox doesn't throw on a badly-escaped identifier. + el.querySelectorAll( "\\\f" ); + rbuggyQSA.push( "[\\r\\n\\f]" ); + } ); + + assert( function( el ) { + el.innerHTML = "" + + ""; + + // Support: Windows 8 Native Apps + // The type and name attributes are restricted during .innerHTML assignment + var input = document.createElement( "input" ); + input.setAttribute( "type", "hidden" ); + el.appendChild( input ).setAttribute( "name", "D" ); + + // Support: IE8 + // Enforce case-sensitivity of name attribute + if ( el.querySelectorAll( "[name=d]" ).length ) { + rbuggyQSA.push( "name" + whitespace + "*[*^$|!~]?=" ); + } + + // FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled) + // IE8 throws error here and will not see later tests + if ( el.querySelectorAll( ":enabled" ).length !== 2 ) { + rbuggyQSA.push( ":enabled", ":disabled" ); + } + + // Support: IE9-11+ + // IE's :disabled selector does not pick up the children of disabled fieldsets + docElem.appendChild( el ).disabled = true; + if ( el.querySelectorAll( ":disabled" ).length !== 2 ) { + rbuggyQSA.push( ":enabled", ":disabled" ); + } + + // Support: Opera 10 - 11 only + // Opera 10-11 does not throw on post-comma invalid pseudos + el.querySelectorAll( "*,:x" ); + rbuggyQSA.push( ",.*:" ); + } ); + } + + if ( ( support.matchesSelector = rnative.test( ( matches = docElem.matches || + docElem.webkitMatchesSelector || + docElem.mozMatchesSelector || + docElem.oMatchesSelector || + docElem.msMatchesSelector ) ) ) ) { + + assert( function( el ) { + + // Check to see if it's possible to do matchesSelector + // on a disconnected node (IE 9) + support.disconnectedMatch = matches.call( el, "*" ); + + // This should fail with an exception + // Gecko does not error, returns false instead + matches.call( el, "[s!='']:x" ); + rbuggyMatches.push( "!=", pseudos ); + } ); + } + + rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join( "|" ) ); + rbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join( "|" ) ); + + /* Contains + ---------------------------------------------------------------------- */ + hasCompare = rnative.test( docElem.compareDocumentPosition ); + + // Element contains another + // Purposefully self-exclusive + // As in, an element does not contain itself + contains = hasCompare || rnative.test( docElem.contains ) ? + function( a, b ) { + var adown = a.nodeType === 9 ? a.documentElement : a, + bup = b && b.parentNode; + return a === bup || !!( bup && bup.nodeType === 1 && ( + adown.contains ? + adown.contains( bup ) : + a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16 + ) ); + } : + function( a, b ) { + if ( b ) { + while ( ( b = b.parentNode ) ) { + if ( b === a ) { + return true; + } + } + } + return false; + }; + + /* Sorting + ---------------------------------------------------------------------- */ + + // Document order sorting + sortOrder = hasCompare ? + function( a, b ) { + + // Flag for duplicate removal + if ( a === b ) { + hasDuplicate = true; + return 0; + } + + // Sort on method existence if only one input has compareDocumentPosition + var compare = !a.compareDocumentPosition - !b.compareDocumentPosition; + if ( compare ) { + return compare; + } + + // Calculate position if both inputs belong to the same document + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + compare = ( a.ownerDocument || a ) == ( b.ownerDocument || b ) ? + a.compareDocumentPosition( b ) : + + // Otherwise we know they are disconnected + 1; + + // Disconnected nodes + if ( compare & 1 || + ( !support.sortDetached && b.compareDocumentPosition( a ) === compare ) ) { + + // Choose the first element that is related to our preferred document + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( a == document || a.ownerDocument == preferredDoc && + contains( preferredDoc, a ) ) { + return -1; + } + + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( b == document || b.ownerDocument == preferredDoc && + contains( preferredDoc, b ) ) { + return 1; + } + + // Maintain original order + return sortInput ? + ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) : + 0; + } + + return compare & 4 ? -1 : 1; + } : + function( a, b ) { + + // Exit early if the nodes are identical + if ( a === b ) { + hasDuplicate = true; + return 0; + } + + var cur, + i = 0, + aup = a.parentNode, + bup = b.parentNode, + ap = [ a ], + bp = [ b ]; + + // Parentless nodes are either documents or disconnected + if ( !aup || !bup ) { + + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + /* eslint-disable eqeqeq */ + return a == document ? -1 : + b == document ? 1 : + /* eslint-enable eqeqeq */ + aup ? -1 : + bup ? 1 : + sortInput ? + ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) : + 0; + + // If the nodes are siblings, we can do a quick check + } else if ( aup === bup ) { + return siblingCheck( a, b ); + } + + // Otherwise we need full lists of their ancestors for comparison + cur = a; + while ( ( cur = cur.parentNode ) ) { + ap.unshift( cur ); + } + cur = b; + while ( ( cur = cur.parentNode ) ) { + bp.unshift( cur ); + } + + // Walk down the tree looking for a discrepancy + while ( ap[ i ] === bp[ i ] ) { + i++; + } + + return i ? + + // Do a sibling check if the nodes have a common ancestor + siblingCheck( ap[ i ], bp[ i ] ) : + + // Otherwise nodes in our document sort first + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + /* eslint-disable eqeqeq */ + ap[ i ] == preferredDoc ? -1 : + bp[ i ] == preferredDoc ? 1 : + /* eslint-enable eqeqeq */ + 0; + }; + + return document; +}; + +Sizzle.matches = function( expr, elements ) { + return Sizzle( expr, null, null, elements ); +}; + +Sizzle.matchesSelector = function( elem, expr ) { + setDocument( elem ); + + if ( support.matchesSelector && documentIsHTML && + !nonnativeSelectorCache[ expr + " " ] && + ( !rbuggyMatches || !rbuggyMatches.test( expr ) ) && + ( !rbuggyQSA || !rbuggyQSA.test( expr ) ) ) { + + try { + var ret = matches.call( elem, expr ); + + // IE 9's matchesSelector returns false on disconnected nodes + if ( ret || support.disconnectedMatch || + + // As well, disconnected nodes are said to be in a document + // fragment in IE 9 + elem.document && elem.document.nodeType !== 11 ) { + return ret; + } + } catch ( e ) { + nonnativeSelectorCache( expr, true ); + } + } + + return Sizzle( expr, document, null, [ elem ] ).length > 0; +}; + +Sizzle.contains = function( context, elem ) { + + // Set document vars if needed + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( ( context.ownerDocument || context ) != document ) { + setDocument( context ); + } + return contains( context, elem ); +}; + +Sizzle.attr = function( elem, name ) { + + // Set document vars if needed + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( ( elem.ownerDocument || elem ) != document ) { + setDocument( elem ); + } + + var fn = Expr.attrHandle[ name.toLowerCase() ], + + // Don't get fooled by Object.prototype properties (jQuery #13807) + val = fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ? + fn( elem, name, !documentIsHTML ) : + undefined; + + return val !== undefined ? + val : + support.attributes || !documentIsHTML ? + elem.getAttribute( name ) : + ( val = elem.getAttributeNode( name ) ) && val.specified ? + val.value : + null; +}; + +Sizzle.escape = function( sel ) { + return ( sel + "" ).replace( rcssescape, fcssescape ); +}; + +Sizzle.error = function( msg ) { + throw new Error( "Syntax error, unrecognized expression: " + msg ); +}; + +/** + * Document sorting and removing duplicates + * @param {ArrayLike} results + */ +Sizzle.uniqueSort = function( results ) { + var elem, + duplicates = [], + j = 0, + i = 0; + + // Unless we *know* we can detect duplicates, assume their presence + hasDuplicate = !support.detectDuplicates; + sortInput = !support.sortStable && results.slice( 0 ); + results.sort( sortOrder ); + + if ( hasDuplicate ) { + while ( ( elem = results[ i++ ] ) ) { + if ( elem === results[ i ] ) { + j = duplicates.push( i ); + } + } + while ( j-- ) { + results.splice( duplicates[ j ], 1 ); + } + } + + // Clear input after sorting to release objects + // See https://github.com/jquery/sizzle/pull/225 + sortInput = null; + + return results; +}; + +/** + * Utility function for retrieving the text value of an array of DOM nodes + * @param {Array|Element} elem + */ +getText = Sizzle.getText = function( elem ) { + var node, + ret = "", + i = 0, + nodeType = elem.nodeType; + + if ( !nodeType ) { + + // If no nodeType, this is expected to be an array + while ( ( node = elem[ i++ ] ) ) { + + // Do not traverse comment nodes + ret += getText( node ); + } + } else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) { + + // Use textContent for elements + // innerText usage removed for consistency of new lines (jQuery #11153) + if ( typeof elem.textContent === "string" ) { + return elem.textContent; + } else { + + // Traverse its children + for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { + ret += getText( elem ); + } + } + } else if ( nodeType === 3 || nodeType === 4 ) { + return elem.nodeValue; + } + + // Do not include comment or processing instruction nodes + + return ret; +}; + +Expr = Sizzle.selectors = { + + // Can be adjusted by the user + cacheLength: 50, + + createPseudo: markFunction, + + match: matchExpr, + + attrHandle: {}, + + find: {}, + + relative: { + ">": { dir: "parentNode", first: true }, + " ": { dir: "parentNode" }, + "+": { dir: "previousSibling", first: true }, + "~": { dir: "previousSibling" } + }, + + preFilter: { + "ATTR": function( match ) { + match[ 1 ] = match[ 1 ].replace( runescape, funescape ); + + // Move the given value to match[3] whether quoted or unquoted + match[ 3 ] = ( match[ 3 ] || match[ 4 ] || + match[ 5 ] || "" ).replace( runescape, funescape ); + + if ( match[ 2 ] === "~=" ) { + match[ 3 ] = " " + match[ 3 ] + " "; + } + + return match.slice( 0, 4 ); + }, + + "CHILD": function( match ) { + + /* matches from matchExpr["CHILD"] + 1 type (only|nth|...) + 2 what (child|of-type) + 3 argument (even|odd|\d*|\d*n([+-]\d+)?|...) + 4 xn-component of xn+y argument ([+-]?\d*n|) + 5 sign of xn-component + 6 x of xn-component + 7 sign of y-component + 8 y of y-component + */ + match[ 1 ] = match[ 1 ].toLowerCase(); + + if ( match[ 1 ].slice( 0, 3 ) === "nth" ) { + + // nth-* requires argument + if ( !match[ 3 ] ) { + Sizzle.error( match[ 0 ] ); + } + + // numeric x and y parameters for Expr.filter.CHILD + // remember that false/true cast respectively to 0/1 + match[ 4 ] = +( match[ 4 ] ? + match[ 5 ] + ( match[ 6 ] || 1 ) : + 2 * ( match[ 3 ] === "even" || match[ 3 ] === "odd" ) ); + match[ 5 ] = +( ( match[ 7 ] + match[ 8 ] ) || match[ 3 ] === "odd" ); + + // other types prohibit arguments + } else if ( match[ 3 ] ) { + Sizzle.error( match[ 0 ] ); + } + + return match; + }, + + "PSEUDO": function( match ) { + var excess, + unquoted = !match[ 6 ] && match[ 2 ]; + + if ( matchExpr[ "CHILD" ].test( match[ 0 ] ) ) { + return null; + } + + // Accept quoted arguments as-is + if ( match[ 3 ] ) { + match[ 2 ] = match[ 4 ] || match[ 5 ] || ""; + + // Strip excess characters from unquoted arguments + } else if ( unquoted && rpseudo.test( unquoted ) && + + // Get excess from tokenize (recursively) + ( excess = tokenize( unquoted, true ) ) && + + // advance to the next closing parenthesis + ( excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length ) ) { + + // excess is a negative index + match[ 0 ] = match[ 0 ].slice( 0, excess ); + match[ 2 ] = unquoted.slice( 0, excess ); + } + + // Return only captures needed by the pseudo filter method (type and argument) + return match.slice( 0, 3 ); + } + }, + + filter: { + + "TAG": function( nodeNameSelector ) { + var nodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase(); + return nodeNameSelector === "*" ? + function() { + return true; + } : + function( elem ) { + return elem.nodeName && elem.nodeName.toLowerCase() === nodeName; + }; + }, + + "CLASS": function( className ) { + var pattern = classCache[ className + " " ]; + + return pattern || + ( pattern = new RegExp( "(^|" + whitespace + + ")" + className + "(" + whitespace + "|$)" ) ) && classCache( + className, function( elem ) { + return pattern.test( + typeof elem.className === "string" && elem.className || + typeof elem.getAttribute !== "undefined" && + elem.getAttribute( "class" ) || + "" + ); + } ); + }, + + "ATTR": function( name, operator, check ) { + return function( elem ) { + var result = Sizzle.attr( elem, name ); + + if ( result == null ) { + return operator === "!="; + } + if ( !operator ) { + return true; + } + + result += ""; + + /* eslint-disable max-len */ + + return operator === "=" ? result === check : + operator === "!=" ? result !== check : + operator === "^=" ? check && result.indexOf( check ) === 0 : + operator === "*=" ? check && result.indexOf( check ) > -1 : + operator === "$=" ? check && result.slice( -check.length ) === check : + operator === "~=" ? ( " " + result.replace( rwhitespace, " " ) + " " ).indexOf( check ) > -1 : + operator === "|=" ? result === check || result.slice( 0, check.length + 1 ) === check + "-" : + false; + /* eslint-enable max-len */ + + }; + }, + + "CHILD": function( type, what, _argument, first, last ) { + var simple = type.slice( 0, 3 ) !== "nth", + forward = type.slice( -4 ) !== "last", + ofType = what === "of-type"; + + return first === 1 && last === 0 ? + + // Shortcut for :nth-*(n) + function( elem ) { + return !!elem.parentNode; + } : + + function( elem, _context, xml ) { + var cache, uniqueCache, outerCache, node, nodeIndex, start, + dir = simple !== forward ? "nextSibling" : "previousSibling", + parent = elem.parentNode, + name = ofType && elem.nodeName.toLowerCase(), + useCache = !xml && !ofType, + diff = false; + + if ( parent ) { + + // :(first|last|only)-(child|of-type) + if ( simple ) { + while ( dir ) { + node = elem; + while ( ( node = node[ dir ] ) ) { + if ( ofType ? + node.nodeName.toLowerCase() === name : + node.nodeType === 1 ) { + + return false; + } + } + + // Reverse direction for :only-* (if we haven't yet done so) + start = dir = type === "only" && !start && "nextSibling"; + } + return true; + } + + start = [ forward ? parent.firstChild : parent.lastChild ]; + + // non-xml :nth-child(...) stores cache data on `parent` + if ( forward && useCache ) { + + // Seek `elem` from a previously-cached index + + // ...in a gzip-friendly way + node = parent; + outerCache = node[ expando ] || ( node[ expando ] = {} ); + + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ node.uniqueID ] || + ( outerCache[ node.uniqueID ] = {} ); + + cache = uniqueCache[ type ] || []; + nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ]; + diff = nodeIndex && cache[ 2 ]; + node = nodeIndex && parent.childNodes[ nodeIndex ]; + + while ( ( node = ++nodeIndex && node && node[ dir ] || + + // Fallback to seeking `elem` from the start + ( diff = nodeIndex = 0 ) || start.pop() ) ) { + + // When found, cache indexes on `parent` and break + if ( node.nodeType === 1 && ++diff && node === elem ) { + uniqueCache[ type ] = [ dirruns, nodeIndex, diff ]; + break; + } + } + + } else { + + // Use previously-cached element index if available + if ( useCache ) { + + // ...in a gzip-friendly way + node = elem; + outerCache = node[ expando ] || ( node[ expando ] = {} ); + + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ node.uniqueID ] || + ( outerCache[ node.uniqueID ] = {} ); + + cache = uniqueCache[ type ] || []; + nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ]; + diff = nodeIndex; + } + + // xml :nth-child(...) + // or :nth-last-child(...) or :nth(-last)?-of-type(...) + if ( diff === false ) { + + // Use the same loop as above to seek `elem` from the start + while ( ( node = ++nodeIndex && node && node[ dir ] || + ( diff = nodeIndex = 0 ) || start.pop() ) ) { + + if ( ( ofType ? + node.nodeName.toLowerCase() === name : + node.nodeType === 1 ) && + ++diff ) { + + // Cache the index of each encountered element + if ( useCache ) { + outerCache = node[ expando ] || + ( node[ expando ] = {} ); + + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ node.uniqueID ] || + ( outerCache[ node.uniqueID ] = {} ); + + uniqueCache[ type ] = [ dirruns, diff ]; + } + + if ( node === elem ) { + break; + } + } + } + } + } + + // Incorporate the offset, then check against cycle size + diff -= last; + return diff === first || ( diff % first === 0 && diff / first >= 0 ); + } + }; + }, + + "PSEUDO": function( pseudo, argument ) { + + // pseudo-class names are case-insensitive + // http://www.w3.org/TR/selectors/#pseudo-classes + // Prioritize by case sensitivity in case custom pseudos are added with uppercase letters + // Remember that setFilters inherits from pseudos + var args, + fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] || + Sizzle.error( "unsupported pseudo: " + pseudo ); + + // The user may use createPseudo to indicate that + // arguments are needed to create the filter function + // just as Sizzle does + if ( fn[ expando ] ) { + return fn( argument ); + } + + // But maintain support for old signatures + if ( fn.length > 1 ) { + args = [ pseudo, pseudo, "", argument ]; + return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ? + markFunction( function( seed, matches ) { + var idx, + matched = fn( seed, argument ), + i = matched.length; + while ( i-- ) { + idx = indexOf( seed, matched[ i ] ); + seed[ idx ] = !( matches[ idx ] = matched[ i ] ); + } + } ) : + function( elem ) { + return fn( elem, 0, args ); + }; + } + + return fn; + } + }, + + pseudos: { + + // Potentially complex pseudos + "not": markFunction( function( selector ) { + + // Trim the selector passed to compile + // to avoid treating leading and trailing + // spaces as combinators + var input = [], + results = [], + matcher = compile( selector.replace( rtrim, "$1" ) ); + + return matcher[ expando ] ? + markFunction( function( seed, matches, _context, xml ) { + var elem, + unmatched = matcher( seed, null, xml, [] ), + i = seed.length; + + // Match elements unmatched by `matcher` + while ( i-- ) { + if ( ( elem = unmatched[ i ] ) ) { + seed[ i ] = !( matches[ i ] = elem ); + } + } + } ) : + function( elem, _context, xml ) { + input[ 0 ] = elem; + matcher( input, null, xml, results ); + + // Don't keep the element (issue #299) + input[ 0 ] = null; + return !results.pop(); + }; + } ), + + "has": markFunction( function( selector ) { + return function( elem ) { + return Sizzle( selector, elem ).length > 0; + }; + } ), + + "contains": markFunction( function( text ) { + text = text.replace( runescape, funescape ); + return function( elem ) { + return ( elem.textContent || getText( elem ) ).indexOf( text ) > -1; + }; + } ), + + // "Whether an element is represented by a :lang() selector + // is based solely on the element's language value + // being equal to the identifier C, + // or beginning with the identifier C immediately followed by "-". + // The matching of C against the element's language value is performed case-insensitively. + // The identifier C does not have to be a valid language name." + // http://www.w3.org/TR/selectors/#lang-pseudo + "lang": markFunction( function( lang ) { + + // lang value must be a valid identifier + if ( !ridentifier.test( lang || "" ) ) { + Sizzle.error( "unsupported lang: " + lang ); + } + lang = lang.replace( runescape, funescape ).toLowerCase(); + return function( elem ) { + var elemLang; + do { + if ( ( elemLang = documentIsHTML ? + elem.lang : + elem.getAttribute( "xml:lang" ) || elem.getAttribute( "lang" ) ) ) { + + elemLang = elemLang.toLowerCase(); + return elemLang === lang || elemLang.indexOf( lang + "-" ) === 0; + } + } while ( ( elem = elem.parentNode ) && elem.nodeType === 1 ); + return false; + }; + } ), + + // Miscellaneous + "target": function( elem ) { + var hash = window.location && window.location.hash; + return hash && hash.slice( 1 ) === elem.id; + }, + + "root": function( elem ) { + return elem === docElem; + }, + + "focus": function( elem ) { + return elem === document.activeElement && + ( !document.hasFocus || document.hasFocus() ) && + !!( elem.type || elem.href || ~elem.tabIndex ); + }, + + // Boolean properties + "enabled": createDisabledPseudo( false ), + "disabled": createDisabledPseudo( true ), + + "checked": function( elem ) { + + // In CSS3, :checked should return both checked and selected elements + // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked + var nodeName = elem.nodeName.toLowerCase(); + return ( nodeName === "input" && !!elem.checked ) || + ( nodeName === "option" && !!elem.selected ); + }, + + "selected": function( elem ) { + + // Accessing this property makes selected-by-default + // options in Safari work properly + if ( elem.parentNode ) { + // eslint-disable-next-line no-unused-expressions + elem.parentNode.selectedIndex; + } + + return elem.selected === true; + }, + + // Contents + "empty": function( elem ) { + + // http://www.w3.org/TR/selectors/#empty-pseudo + // :empty is negated by element (1) or content nodes (text: 3; cdata: 4; entity ref: 5), + // but not by others (comment: 8; processing instruction: 7; etc.) + // nodeType < 6 works because attributes (2) do not appear as children + for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { + if ( elem.nodeType < 6 ) { + return false; + } + } + return true; + }, + + "parent": function( elem ) { + return !Expr.pseudos[ "empty" ]( elem ); + }, + + // Element/input types + "header": function( elem ) { + return rheader.test( elem.nodeName ); + }, + + "input": function( elem ) { + return rinputs.test( elem.nodeName ); + }, + + "button": function( elem ) { + var name = elem.nodeName.toLowerCase(); + return name === "input" && elem.type === "button" || name === "button"; + }, + + "text": function( elem ) { + var attr; + return elem.nodeName.toLowerCase() === "input" && + elem.type === "text" && + + // Support: IE<8 + // New HTML5 attribute values (e.g., "search") appear with elem.type === "text" + ( ( attr = elem.getAttribute( "type" ) ) == null || + attr.toLowerCase() === "text" ); + }, + + // Position-in-collection + "first": createPositionalPseudo( function() { + return [ 0 ]; + } ), + + "last": createPositionalPseudo( function( _matchIndexes, length ) { + return [ length - 1 ]; + } ), + + "eq": createPositionalPseudo( function( _matchIndexes, length, argument ) { + return [ argument < 0 ? argument + length : argument ]; + } ), + + "even": createPositionalPseudo( function( matchIndexes, length ) { + var i = 0; + for ( ; i < length; i += 2 ) { + matchIndexes.push( i ); + } + return matchIndexes; + } ), + + "odd": createPositionalPseudo( function( matchIndexes, length ) { + var i = 1; + for ( ; i < length; i += 2 ) { + matchIndexes.push( i ); + } + return matchIndexes; + } ), + + "lt": createPositionalPseudo( function( matchIndexes, length, argument ) { + var i = argument < 0 ? + argument + length : + argument > length ? + length : + argument; + for ( ; --i >= 0; ) { + matchIndexes.push( i ); + } + return matchIndexes; + } ), + + "gt": createPositionalPseudo( function( matchIndexes, length, argument ) { + var i = argument < 0 ? argument + length : argument; + for ( ; ++i < length; ) { + matchIndexes.push( i ); + } + return matchIndexes; + } ) + } +}; + +Expr.pseudos[ "nth" ] = Expr.pseudos[ "eq" ]; + +// Add button/input type pseudos +for ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) { + Expr.pseudos[ i ] = createInputPseudo( i ); +} +for ( i in { submit: true, reset: true } ) { + Expr.pseudos[ i ] = createButtonPseudo( i ); +} + +// Easy API for creating new setFilters +function setFilters() {} +setFilters.prototype = Expr.filters = Expr.pseudos; +Expr.setFilters = new setFilters(); + +tokenize = Sizzle.tokenize = function( selector, parseOnly ) { + var matched, match, tokens, type, + soFar, groups, preFilters, + cached = tokenCache[ selector + " " ]; + + if ( cached ) { + return parseOnly ? 0 : cached.slice( 0 ); + } + + soFar = selector; + groups = []; + preFilters = Expr.preFilter; + + while ( soFar ) { + + // Comma and first run + if ( !matched || ( match = rcomma.exec( soFar ) ) ) { + if ( match ) { + + // Don't consume trailing commas as valid + soFar = soFar.slice( match[ 0 ].length ) || soFar; + } + groups.push( ( tokens = [] ) ); + } + + matched = false; + + // Combinators + if ( ( match = rcombinators.exec( soFar ) ) ) { + matched = match.shift(); + tokens.push( { + value: matched, + + // Cast descendant combinators to space + type: match[ 0 ].replace( rtrim, " " ) + } ); + soFar = soFar.slice( matched.length ); + } + + // Filters + for ( type in Expr.filter ) { + if ( ( match = matchExpr[ type ].exec( soFar ) ) && ( !preFilters[ type ] || + ( match = preFilters[ type ]( match ) ) ) ) { + matched = match.shift(); + tokens.push( { + value: matched, + type: type, + matches: match + } ); + soFar = soFar.slice( matched.length ); + } + } + + if ( !matched ) { + break; + } + } + + // Return the length of the invalid excess + // if we're just parsing + // Otherwise, throw an error or return tokens + return parseOnly ? + soFar.length : + soFar ? + Sizzle.error( selector ) : + + // Cache the tokens + tokenCache( selector, groups ).slice( 0 ); +}; + +function toSelector( tokens ) { + var i = 0, + len = tokens.length, + selector = ""; + for ( ; i < len; i++ ) { + selector += tokens[ i ].value; + } + return selector; +} + +function addCombinator( matcher, combinator, base ) { + var dir = combinator.dir, + skip = combinator.next, + key = skip || dir, + checkNonElements = base && key === "parentNode", + doneName = done++; + + return combinator.first ? + + // Check against closest ancestor/preceding element + function( elem, context, xml ) { + while ( ( elem = elem[ dir ] ) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + return matcher( elem, context, xml ); + } + } + return false; + } : + + // Check against all ancestor/preceding elements + function( elem, context, xml ) { + var oldCache, uniqueCache, outerCache, + newCache = [ dirruns, doneName ]; + + // We can't set arbitrary data on XML nodes, so they don't benefit from combinator caching + if ( xml ) { + while ( ( elem = elem[ dir ] ) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + if ( matcher( elem, context, xml ) ) { + return true; + } + } + } + } else { + while ( ( elem = elem[ dir ] ) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + outerCache = elem[ expando ] || ( elem[ expando ] = {} ); + + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ elem.uniqueID ] || + ( outerCache[ elem.uniqueID ] = {} ); + + if ( skip && skip === elem.nodeName.toLowerCase() ) { + elem = elem[ dir ] || elem; + } else if ( ( oldCache = uniqueCache[ key ] ) && + oldCache[ 0 ] === dirruns && oldCache[ 1 ] === doneName ) { + + // Assign to newCache so results back-propagate to previous elements + return ( newCache[ 2 ] = oldCache[ 2 ] ); + } else { + + // Reuse newcache so results back-propagate to previous elements + uniqueCache[ key ] = newCache; + + // A match means we're done; a fail means we have to keep checking + if ( ( newCache[ 2 ] = matcher( elem, context, xml ) ) ) { + return true; + } + } + } + } + } + return false; + }; +} + +function elementMatcher( matchers ) { + return matchers.length > 1 ? + function( elem, context, xml ) { + var i = matchers.length; + while ( i-- ) { + if ( !matchers[ i ]( elem, context, xml ) ) { + return false; + } + } + return true; + } : + matchers[ 0 ]; +} + +function multipleContexts( selector, contexts, results ) { + var i = 0, + len = contexts.length; + for ( ; i < len; i++ ) { + Sizzle( selector, contexts[ i ], results ); + } + return results; +} + +function condense( unmatched, map, filter, context, xml ) { + var elem, + newUnmatched = [], + i = 0, + len = unmatched.length, + mapped = map != null; + + for ( ; i < len; i++ ) { + if ( ( elem = unmatched[ i ] ) ) { + if ( !filter || filter( elem, context, xml ) ) { + newUnmatched.push( elem ); + if ( mapped ) { + map.push( i ); + } + } + } + } + + return newUnmatched; +} + +function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) { + if ( postFilter && !postFilter[ expando ] ) { + postFilter = setMatcher( postFilter ); + } + if ( postFinder && !postFinder[ expando ] ) { + postFinder = setMatcher( postFinder, postSelector ); + } + return markFunction( function( seed, results, context, xml ) { + var temp, i, elem, + preMap = [], + postMap = [], + preexisting = results.length, + + // Get initial elements from seed or context + elems = seed || multipleContexts( + selector || "*", + context.nodeType ? [ context ] : context, + [] + ), + + // Prefilter to get matcher input, preserving a map for seed-results synchronization + matcherIn = preFilter && ( seed || !selector ) ? + condense( elems, preMap, preFilter, context, xml ) : + elems, + + matcherOut = matcher ? + + // If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results, + postFinder || ( seed ? preFilter : preexisting || postFilter ) ? + + // ...intermediate processing is necessary + [] : + + // ...otherwise use results directly + results : + matcherIn; + + // Find primary matches + if ( matcher ) { + matcher( matcherIn, matcherOut, context, xml ); + } + + // Apply postFilter + if ( postFilter ) { + temp = condense( matcherOut, postMap ); + postFilter( temp, [], context, xml ); + + // Un-match failing elements by moving them back to matcherIn + i = temp.length; + while ( i-- ) { + if ( ( elem = temp[ i ] ) ) { + matcherOut[ postMap[ i ] ] = !( matcherIn[ postMap[ i ] ] = elem ); + } + } + } + + if ( seed ) { + if ( postFinder || preFilter ) { + if ( postFinder ) { + + // Get the final matcherOut by condensing this intermediate into postFinder contexts + temp = []; + i = matcherOut.length; + while ( i-- ) { + if ( ( elem = matcherOut[ i ] ) ) { + + // Restore matcherIn since elem is not yet a final match + temp.push( ( matcherIn[ i ] = elem ) ); + } + } + postFinder( null, ( matcherOut = [] ), temp, xml ); + } + + // Move matched elements from seed to results to keep them synchronized + i = matcherOut.length; + while ( i-- ) { + if ( ( elem = matcherOut[ i ] ) && + ( temp = postFinder ? indexOf( seed, elem ) : preMap[ i ] ) > -1 ) { + + seed[ temp ] = !( results[ temp ] = elem ); + } + } + } + + // Add elements to results, through postFinder if defined + } else { + matcherOut = condense( + matcherOut === results ? + matcherOut.splice( preexisting, matcherOut.length ) : + matcherOut + ); + if ( postFinder ) { + postFinder( null, results, matcherOut, xml ); + } else { + push.apply( results, matcherOut ); + } + } + } ); +} + +function matcherFromTokens( tokens ) { + var checkContext, matcher, j, + len = tokens.length, + leadingRelative = Expr.relative[ tokens[ 0 ].type ], + implicitRelative = leadingRelative || Expr.relative[ " " ], + i = leadingRelative ? 1 : 0, + + // The foundational matcher ensures that elements are reachable from top-level context(s) + matchContext = addCombinator( function( elem ) { + return elem === checkContext; + }, implicitRelative, true ), + matchAnyContext = addCombinator( function( elem ) { + return indexOf( checkContext, elem ) > -1; + }, implicitRelative, true ), + matchers = [ function( elem, context, xml ) { + var ret = ( !leadingRelative && ( xml || context !== outermostContext ) ) || ( + ( checkContext = context ).nodeType ? + matchContext( elem, context, xml ) : + matchAnyContext( elem, context, xml ) ); + + // Avoid hanging onto element (issue #299) + checkContext = null; + return ret; + } ]; + + for ( ; i < len; i++ ) { + if ( ( matcher = Expr.relative[ tokens[ i ].type ] ) ) { + matchers = [ addCombinator( elementMatcher( matchers ), matcher ) ]; + } else { + matcher = Expr.filter[ tokens[ i ].type ].apply( null, tokens[ i ].matches ); + + // Return special upon seeing a positional matcher + if ( matcher[ expando ] ) { + + // Find the next relative operator (if any) for proper handling + j = ++i; + for ( ; j < len; j++ ) { + if ( Expr.relative[ tokens[ j ].type ] ) { + break; + } + } + return setMatcher( + i > 1 && elementMatcher( matchers ), + i > 1 && toSelector( + + // If the preceding token was a descendant combinator, insert an implicit any-element `*` + tokens + .slice( 0, i - 1 ) + .concat( { value: tokens[ i - 2 ].type === " " ? "*" : "" } ) + ).replace( rtrim, "$1" ), + matcher, + i < j && matcherFromTokens( tokens.slice( i, j ) ), + j < len && matcherFromTokens( ( tokens = tokens.slice( j ) ) ), + j < len && toSelector( tokens ) + ); + } + matchers.push( matcher ); + } + } + + return elementMatcher( matchers ); +} + +function matcherFromGroupMatchers( elementMatchers, setMatchers ) { + var bySet = setMatchers.length > 0, + byElement = elementMatchers.length > 0, + superMatcher = function( seed, context, xml, results, outermost ) { + var elem, j, matcher, + matchedCount = 0, + i = "0", + unmatched = seed && [], + setMatched = [], + contextBackup = outermostContext, + + // We must always have either seed elements or outermost context + elems = seed || byElement && Expr.find[ "TAG" ]( "*", outermost ), + + // Use integer dirruns iff this is the outermost matcher + dirrunsUnique = ( dirruns += contextBackup == null ? 1 : Math.random() || 0.1 ), + len = elems.length; + + if ( outermost ) { + + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + outermostContext = context == document || context || outermost; + } + + // Add elements passing elementMatchers directly to results + // Support: IE<9, Safari + // Tolerate NodeList properties (IE: "length"; Safari: ) matching elements by id + for ( ; i !== len && ( elem = elems[ i ] ) != null; i++ ) { + if ( byElement && elem ) { + j = 0; + + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( !context && elem.ownerDocument != document ) { + setDocument( elem ); + xml = !documentIsHTML; + } + while ( ( matcher = elementMatchers[ j++ ] ) ) { + if ( matcher( elem, context || document, xml ) ) { + results.push( elem ); + break; + } + } + if ( outermost ) { + dirruns = dirrunsUnique; + } + } + + // Track unmatched elements for set filters + if ( bySet ) { + + // They will have gone through all possible matchers + if ( ( elem = !matcher && elem ) ) { + matchedCount--; + } + + // Lengthen the array for every element, matched or not + if ( seed ) { + unmatched.push( elem ); + } + } + } + + // `i` is now the count of elements visited above, and adding it to `matchedCount` + // makes the latter nonnegative. + matchedCount += i; + + // Apply set filters to unmatched elements + // NOTE: This can be skipped if there are no unmatched elements (i.e., `matchedCount` + // equals `i`), unless we didn't visit _any_ elements in the above loop because we have + // no element matchers and no seed. + // Incrementing an initially-string "0" `i` allows `i` to remain a string only in that + // case, which will result in a "00" `matchedCount` that differs from `i` but is also + // numerically zero. + if ( bySet && i !== matchedCount ) { + j = 0; + while ( ( matcher = setMatchers[ j++ ] ) ) { + matcher( unmatched, setMatched, context, xml ); + } + + if ( seed ) { + + // Reintegrate element matches to eliminate the need for sorting + if ( matchedCount > 0 ) { + while ( i-- ) { + if ( !( unmatched[ i ] || setMatched[ i ] ) ) { + setMatched[ i ] = pop.call( results ); + } + } + } + + // Discard index placeholder values to get only actual matches + setMatched = condense( setMatched ); + } + + // Add matches to results + push.apply( results, setMatched ); + + // Seedless set matches succeeding multiple successful matchers stipulate sorting + if ( outermost && !seed && setMatched.length > 0 && + ( matchedCount + setMatchers.length ) > 1 ) { + + Sizzle.uniqueSort( results ); + } + } + + // Override manipulation of globals by nested matchers + if ( outermost ) { + dirruns = dirrunsUnique; + outermostContext = contextBackup; + } + + return unmatched; + }; + + return bySet ? + markFunction( superMatcher ) : + superMatcher; +} + +compile = Sizzle.compile = function( selector, match /* Internal Use Only */ ) { + var i, + setMatchers = [], + elementMatchers = [], + cached = compilerCache[ selector + " " ]; + + if ( !cached ) { + + // Generate a function of recursive functions that can be used to check each element + if ( !match ) { + match = tokenize( selector ); + } + i = match.length; + while ( i-- ) { + cached = matcherFromTokens( match[ i ] ); + if ( cached[ expando ] ) { + setMatchers.push( cached ); + } else { + elementMatchers.push( cached ); + } + } + + // Cache the compiled function + cached = compilerCache( + selector, + matcherFromGroupMatchers( elementMatchers, setMatchers ) + ); + + // Save selector and tokenization + cached.selector = selector; + } + return cached; +}; + +/** + * A low-level selection function that works with Sizzle's compiled + * selector functions + * @param {String|Function} selector A selector or a pre-compiled + * selector function built with Sizzle.compile + * @param {Element} context + * @param {Array} [results] + * @param {Array} [seed] A set of elements to match against + */ +select = Sizzle.select = function( selector, context, results, seed ) { + var i, tokens, token, type, find, + compiled = typeof selector === "function" && selector, + match = !seed && tokenize( ( selector = compiled.selector || selector ) ); + + results = results || []; + + // Try to minimize operations if there is only one selector in the list and no seed + // (the latter of which guarantees us context) + if ( match.length === 1 ) { + + // Reduce context if the leading compound selector is an ID + tokens = match[ 0 ] = match[ 0 ].slice( 0 ); + if ( tokens.length > 2 && ( token = tokens[ 0 ] ).type === "ID" && + context.nodeType === 9 && documentIsHTML && Expr.relative[ tokens[ 1 ].type ] ) { + + context = ( Expr.find[ "ID" ]( token.matches[ 0 ] + .replace( runescape, funescape ), context ) || [] )[ 0 ]; + if ( !context ) { + return results; + + // Precompiled matchers will still verify ancestry, so step up a level + } else if ( compiled ) { + context = context.parentNode; + } + + selector = selector.slice( tokens.shift().value.length ); + } + + // Fetch a seed set for right-to-left matching + i = matchExpr[ "needsContext" ].test( selector ) ? 0 : tokens.length; + while ( i-- ) { + token = tokens[ i ]; + + // Abort if we hit a combinator + if ( Expr.relative[ ( type = token.type ) ] ) { + break; + } + if ( ( find = Expr.find[ type ] ) ) { + + // Search, expanding context for leading sibling combinators + if ( ( seed = find( + token.matches[ 0 ].replace( runescape, funescape ), + rsibling.test( tokens[ 0 ].type ) && testContext( context.parentNode ) || + context + ) ) ) { + + // If seed is empty or no tokens remain, we can return early + tokens.splice( i, 1 ); + selector = seed.length && toSelector( tokens ); + if ( !selector ) { + push.apply( results, seed ); + return results; + } + + break; + } + } + } + } + + // Compile and execute a filtering function if one is not provided + // Provide `match` to avoid retokenization if we modified the selector above + ( compiled || compile( selector, match ) )( + seed, + context, + !documentIsHTML, + results, + !context || rsibling.test( selector ) && testContext( context.parentNode ) || context + ); + return results; +}; + +// One-time assignments + +// Sort stability +support.sortStable = expando.split( "" ).sort( sortOrder ).join( "" ) === expando; + +// Support: Chrome 14-35+ +// Always assume duplicates if they aren't passed to the comparison function +support.detectDuplicates = !!hasDuplicate; + +// Initialize against the default document +setDocument(); + +// Support: Webkit<537.32 - Safari 6.0.3/Chrome 25 (fixed in Chrome 27) +// Detached nodes confoundingly follow *each other* +support.sortDetached = assert( function( el ) { + + // Should return 1, but returns 4 (following) + return el.compareDocumentPosition( document.createElement( "fieldset" ) ) & 1; +} ); + +// Support: IE<8 +// Prevent attribute/property "interpolation" +// https://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx +if ( !assert( function( el ) { + el.innerHTML = ""; + return el.firstChild.getAttribute( "href" ) === "#"; +} ) ) { + addHandle( "type|href|height|width", function( elem, name, isXML ) { + if ( !isXML ) { + return elem.getAttribute( name, name.toLowerCase() === "type" ? 1 : 2 ); + } + } ); +} + +// Support: IE<9 +// Use defaultValue in place of getAttribute("value") +if ( !support.attributes || !assert( function( el ) { + el.innerHTML = ""; + el.firstChild.setAttribute( "value", "" ); + return el.firstChild.getAttribute( "value" ) === ""; +} ) ) { + addHandle( "value", function( elem, _name, isXML ) { + if ( !isXML && elem.nodeName.toLowerCase() === "input" ) { + return elem.defaultValue; + } + } ); +} + +// Support: IE<9 +// Use getAttributeNode to fetch booleans when getAttribute lies +if ( !assert( function( el ) { + return el.getAttribute( "disabled" ) == null; +} ) ) { + addHandle( booleans, function( elem, name, isXML ) { + var val; + if ( !isXML ) { + return elem[ name ] === true ? name.toLowerCase() : + ( val = elem.getAttributeNode( name ) ) && val.specified ? + val.value : + null; + } + } ); +} + +return Sizzle; + +} )( window ); + + + +jQuery.find = Sizzle; +jQuery.expr = Sizzle.selectors; + +// Deprecated +jQuery.expr[ ":" ] = jQuery.expr.pseudos; +jQuery.uniqueSort = jQuery.unique = Sizzle.uniqueSort; +jQuery.text = Sizzle.getText; +jQuery.isXMLDoc = Sizzle.isXML; +jQuery.contains = Sizzle.contains; +jQuery.escapeSelector = Sizzle.escape; + + + + +var dir = function( elem, dir, until ) { + var matched = [], + truncate = until !== undefined; + + while ( ( elem = elem[ dir ] ) && elem.nodeType !== 9 ) { + if ( elem.nodeType === 1 ) { + if ( truncate && jQuery( elem ).is( until ) ) { + break; + } + matched.push( elem ); + } + } + return matched; +}; + + +var siblings = function( n, elem ) { + var matched = []; + + for ( ; n; n = n.nextSibling ) { + if ( n.nodeType === 1 && n !== elem ) { + matched.push( n ); + } + } + + return matched; +}; + + +var rneedsContext = jQuery.expr.match.needsContext; + + + +function nodeName( elem, name ) { + + return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase(); + +}; +var rsingleTag = ( /^<([a-z][^\/\0>:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i ); + + + +// Implement the identical functionality for filter and not +function winnow( elements, qualifier, not ) { + if ( isFunction( qualifier ) ) { + return jQuery.grep( elements, function( elem, i ) { + return !!qualifier.call( elem, i, elem ) !== not; + } ); + } + + // Single element + if ( qualifier.nodeType ) { + return jQuery.grep( elements, function( elem ) { + return ( elem === qualifier ) !== not; + } ); + } + + // Arraylike of elements (jQuery, arguments, Array) + if ( typeof qualifier !== "string" ) { + return jQuery.grep( elements, function( elem ) { + return ( indexOf.call( qualifier, elem ) > -1 ) !== not; + } ); + } + + // Filtered directly for both simple and complex selectors + return jQuery.filter( qualifier, elements, not ); +} + +jQuery.filter = function( expr, elems, not ) { + var elem = elems[ 0 ]; + + if ( not ) { + expr = ":not(" + expr + ")"; + } + + if ( elems.length === 1 && elem.nodeType === 1 ) { + return jQuery.find.matchesSelector( elem, expr ) ? [ elem ] : []; + } + + return jQuery.find.matches( expr, jQuery.grep( elems, function( elem ) { + return elem.nodeType === 1; + } ) ); +}; + +jQuery.fn.extend( { + find: function( selector ) { + var i, ret, + len = this.length, + self = this; + + if ( typeof selector !== "string" ) { + return this.pushStack( jQuery( selector ).filter( function() { + for ( i = 0; i < len; i++ ) { + if ( jQuery.contains( self[ i ], this ) ) { + return true; + } + } + } ) ); + } + + ret = this.pushStack( [] ); + + for ( i = 0; i < len; i++ ) { + jQuery.find( selector, self[ i ], ret ); + } + + return len > 1 ? jQuery.uniqueSort( ret ) : ret; + }, + filter: function( selector ) { + return this.pushStack( winnow( this, selector || [], false ) ); + }, + not: function( selector ) { + return this.pushStack( winnow( this, selector || [], true ) ); + }, + is: function( selector ) { + return !!winnow( + this, + + // If this is a positional/relative selector, check membership in the returned set + // so $("p:first").is("p:last") won't return true for a doc with two "p". + typeof selector === "string" && rneedsContext.test( selector ) ? + jQuery( selector ) : + selector || [], + false + ).length; + } +} ); + + +// Initialize a jQuery object + + +// A central reference to the root jQuery(document) +var rootjQuery, + + // A simple way to check for HTML strings + // Prioritize #id over to avoid XSS via location.hash (#9521) + // Strict HTML recognition (#11290: must start with <) + // Shortcut simple #id case for speed + rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]+))$/, + + init = jQuery.fn.init = function( selector, context, root ) { + var match, elem; + + // HANDLE: $(""), $(null), $(undefined), $(false) + if ( !selector ) { + return this; + } + + // Method init() accepts an alternate rootjQuery + // so migrate can support jQuery.sub (gh-2101) + root = root || rootjQuery; + + // Handle HTML strings + if ( typeof selector === "string" ) { + if ( selector[ 0 ] === "<" && + selector[ selector.length - 1 ] === ">" && + selector.length >= 3 ) { + + // Assume that strings that start and end with <> are HTML and skip the regex check + match = [ null, selector, null ]; + + } else { + match = rquickExpr.exec( selector ); + } + + // Match html or make sure no context is specified for #id + if ( match && ( match[ 1 ] || !context ) ) { + + // HANDLE: $(html) -> $(array) + if ( match[ 1 ] ) { + context = context instanceof jQuery ? context[ 0 ] : context; + + // Option to run scripts is true for back-compat + // Intentionally let the error be thrown if parseHTML is not present + jQuery.merge( this, jQuery.parseHTML( + match[ 1 ], + context && context.nodeType ? context.ownerDocument || context : document, + true + ) ); + + // HANDLE: $(html, props) + if ( rsingleTag.test( match[ 1 ] ) && jQuery.isPlainObject( context ) ) { + for ( match in context ) { + + // Properties of context are called as methods if possible + if ( isFunction( this[ match ] ) ) { + this[ match ]( context[ match ] ); + + // ...and otherwise set as attributes + } else { + this.attr( match, context[ match ] ); + } + } + } + + return this; + + // HANDLE: $(#id) + } else { + elem = document.getElementById( match[ 2 ] ); + + if ( elem ) { + + // Inject the element directly into the jQuery object + this[ 0 ] = elem; + this.length = 1; + } + return this; + } + + // HANDLE: $(expr, $(...)) + } else if ( !context || context.jquery ) { + return ( context || root ).find( selector ); + + // HANDLE: $(expr, context) + // (which is just equivalent to: $(context).find(expr) + } else { + return this.constructor( context ).find( selector ); + } + + // HANDLE: $(DOMElement) + } else if ( selector.nodeType ) { + this[ 0 ] = selector; + this.length = 1; + return this; + + // HANDLE: $(function) + // Shortcut for document ready + } else if ( isFunction( selector ) ) { + return root.ready !== undefined ? + root.ready( selector ) : + + // Execute immediately if ready is not present + selector( jQuery ); + } + + return jQuery.makeArray( selector, this ); + }; + +// Give the init function the jQuery prototype for later instantiation +init.prototype = jQuery.fn; + +// Initialize central reference +rootjQuery = jQuery( document ); + + +var rparentsprev = /^(?:parents|prev(?:Until|All))/, + + // Methods guaranteed to produce a unique set when starting from a unique set + guaranteedUnique = { + children: true, + contents: true, + next: true, + prev: true + }; + +jQuery.fn.extend( { + has: function( target ) { + var targets = jQuery( target, this ), + l = targets.length; + + return this.filter( function() { + var i = 0; + for ( ; i < l; i++ ) { + if ( jQuery.contains( this, targets[ i ] ) ) { + return true; + } + } + } ); + }, + + closest: function( selectors, context ) { + var cur, + i = 0, + l = this.length, + matched = [], + targets = typeof selectors !== "string" && jQuery( selectors ); + + // Positional selectors never match, since there's no _selection_ context + if ( !rneedsContext.test( selectors ) ) { + for ( ; i < l; i++ ) { + for ( cur = this[ i ]; cur && cur !== context; cur = cur.parentNode ) { + + // Always skip document fragments + if ( cur.nodeType < 11 && ( targets ? + targets.index( cur ) > -1 : + + // Don't pass non-elements to Sizzle + cur.nodeType === 1 && + jQuery.find.matchesSelector( cur, selectors ) ) ) { + + matched.push( cur ); + break; + } + } + } + } + + return this.pushStack( matched.length > 1 ? jQuery.uniqueSort( matched ) : matched ); + }, + + // Determine the position of an element within the set + index: function( elem ) { + + // No argument, return index in parent + if ( !elem ) { + return ( this[ 0 ] && this[ 0 ].parentNode ) ? this.first().prevAll().length : -1; + } + + // Index in selector + if ( typeof elem === "string" ) { + return indexOf.call( jQuery( elem ), this[ 0 ] ); + } + + // Locate the position of the desired element + return indexOf.call( this, + + // If it receives a jQuery object, the first element is used + elem.jquery ? elem[ 0 ] : elem + ); + }, + + add: function( selector, context ) { + return this.pushStack( + jQuery.uniqueSort( + jQuery.merge( this.get(), jQuery( selector, context ) ) + ) + ); + }, + + addBack: function( selector ) { + return this.add( selector == null ? + this.prevObject : this.prevObject.filter( selector ) + ); + } +} ); + +function sibling( cur, dir ) { + while ( ( cur = cur[ dir ] ) && cur.nodeType !== 1 ) {} + return cur; +} + +jQuery.each( { + parent: function( elem ) { + var parent = elem.parentNode; + return parent && parent.nodeType !== 11 ? parent : null; + }, + parents: function( elem ) { + return dir( elem, "parentNode" ); + }, + parentsUntil: function( elem, _i, until ) { + return dir( elem, "parentNode", until ); + }, + next: function( elem ) { + return sibling( elem, "nextSibling" ); + }, + prev: function( elem ) { + return sibling( elem, "previousSibling" ); + }, + nextAll: function( elem ) { + return dir( elem, "nextSibling" ); + }, + prevAll: function( elem ) { + return dir( elem, "previousSibling" ); + }, + nextUntil: function( elem, _i, until ) { + return dir( elem, "nextSibling", until ); + }, + prevUntil: function( elem, _i, until ) { + return dir( elem, "previousSibling", until ); + }, + siblings: function( elem ) { + return siblings( ( elem.parentNode || {} ).firstChild, elem ); + }, + children: function( elem ) { + return siblings( elem.firstChild ); + }, + contents: function( elem ) { + if ( elem.contentDocument != null && + + // Support: IE 11+ + // elements with no `data` attribute has an object + // `contentDocument` with a `null` prototype. + getProto( elem.contentDocument ) ) { + + return elem.contentDocument; + } + + // Support: IE 9 - 11 only, iOS 7 only, Android Browser <=4.3 only + // Treat the template element as a regular one in browsers that + // don't support it. + if ( nodeName( elem, "template" ) ) { + elem = elem.content || elem; + } + + return jQuery.merge( [], elem.childNodes ); + } +}, function( name, fn ) { + jQuery.fn[ name ] = function( until, selector ) { + var matched = jQuery.map( this, fn, until ); + + if ( name.slice( -5 ) !== "Until" ) { + selector = until; + } + + if ( selector && typeof selector === "string" ) { + matched = jQuery.filter( selector, matched ); + } + + if ( this.length > 1 ) { + + // Remove duplicates + if ( !guaranteedUnique[ name ] ) { + jQuery.uniqueSort( matched ); + } + + // Reverse order for parents* and prev-derivatives + if ( rparentsprev.test( name ) ) { + matched.reverse(); + } + } + + return this.pushStack( matched ); + }; +} ); +var rnothtmlwhite = ( /[^\x20\t\r\n\f]+/g ); + + + +// Convert String-formatted options into Object-formatted ones +function createOptions( options ) { + var object = {}; + jQuery.each( options.match( rnothtmlwhite ) || [], function( _, flag ) { + object[ flag ] = true; + } ); + return object; +} + +/* + * Create a callback list using the following parameters: + * + * options: an optional list of space-separated options that will change how + * the callback list behaves or a more traditional option object + * + * By default a callback list will act like an event callback list and can be + * "fired" multiple times. + * + * Possible options: + * + * once: will ensure the callback list can only be fired once (like a Deferred) + * + * memory: will keep track of previous values and will call any callback added + * after the list has been fired right away with the latest "memorized" + * values (like a Deferred) + * + * unique: will ensure a callback can only be added once (no duplicate in the list) + * + * stopOnFalse: interrupt callings when a callback returns false + * + */ +jQuery.Callbacks = function( options ) { + + // Convert options from String-formatted to Object-formatted if needed + // (we check in cache first) + options = typeof options === "string" ? + createOptions( options ) : + jQuery.extend( {}, options ); + + var // Flag to know if list is currently firing + firing, + + // Last fire value for non-forgettable lists + memory, + + // Flag to know if list was already fired + fired, + + // Flag to prevent firing + locked, + + // Actual callback list + list = [], + + // Queue of execution data for repeatable lists + queue = [], + + // Index of currently firing callback (modified by add/remove as needed) + firingIndex = -1, + + // Fire callbacks + fire = function() { + + // Enforce single-firing + locked = locked || options.once; + + // Execute callbacks for all pending executions, + // respecting firingIndex overrides and runtime changes + fired = firing = true; + for ( ; queue.length; firingIndex = -1 ) { + memory = queue.shift(); + while ( ++firingIndex < list.length ) { + + // Run callback and check for early termination + if ( list[ firingIndex ].apply( memory[ 0 ], memory[ 1 ] ) === false && + options.stopOnFalse ) { + + // Jump to end and forget the data so .add doesn't re-fire + firingIndex = list.length; + memory = false; + } + } + } + + // Forget the data if we're done with it + if ( !options.memory ) { + memory = false; + } + + firing = false; + + // Clean up if we're done firing for good + if ( locked ) { + + // Keep an empty list if we have data for future add calls + if ( memory ) { + list = []; + + // Otherwise, this object is spent + } else { + list = ""; + } + } + }, + + // Actual Callbacks object + self = { + + // Add a callback or a collection of callbacks to the list + add: function() { + if ( list ) { + + // If we have memory from a past run, we should fire after adding + if ( memory && !firing ) { + firingIndex = list.length - 1; + queue.push( memory ); + } + + ( function add( args ) { + jQuery.each( args, function( _, arg ) { + if ( isFunction( arg ) ) { + if ( !options.unique || !self.has( arg ) ) { + list.push( arg ); + } + } else if ( arg && arg.length && toType( arg ) !== "string" ) { + + // Inspect recursively + add( arg ); + } + } ); + } )( arguments ); + + if ( memory && !firing ) { + fire(); + } + } + return this; + }, + + // Remove a callback from the list + remove: function() { + jQuery.each( arguments, function( _, arg ) { + var index; + while ( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) { + list.splice( index, 1 ); + + // Handle firing indexes + if ( index <= firingIndex ) { + firingIndex--; + } + } + } ); + return this; + }, + + // Check if a given callback is in the list. + // If no argument is given, return whether or not list has callbacks attached. + has: function( fn ) { + return fn ? + jQuery.inArray( fn, list ) > -1 : + list.length > 0; + }, + + // Remove all callbacks from the list + empty: function() { + if ( list ) { + list = []; + } + return this; + }, + + // Disable .fire and .add + // Abort any current/pending executions + // Clear all callbacks and values + disable: function() { + locked = queue = []; + list = memory = ""; + return this; + }, + disabled: function() { + return !list; + }, + + // Disable .fire + // Also disable .add unless we have memory (since it would have no effect) + // Abort any pending executions + lock: function() { + locked = queue = []; + if ( !memory && !firing ) { + list = memory = ""; + } + return this; + }, + locked: function() { + return !!locked; + }, + + // Call all callbacks with the given context and arguments + fireWith: function( context, args ) { + if ( !locked ) { + args = args || []; + args = [ context, args.slice ? args.slice() : args ]; + queue.push( args ); + if ( !firing ) { + fire(); + } + } + return this; + }, + + // Call all the callbacks with the given arguments + fire: function() { + self.fireWith( this, arguments ); + return this; + }, + + // To know if the callbacks have already been called at least once + fired: function() { + return !!fired; + } + }; + + return self; +}; + + +function Identity( v ) { + return v; +} +function Thrower( ex ) { + throw ex; +} + +function adoptValue( value, resolve, reject, noValue ) { + var method; + + try { + + // Check for promise aspect first to privilege synchronous behavior + if ( value && isFunction( ( method = value.promise ) ) ) { + method.call( value ).done( resolve ).fail( reject ); + + // Other thenables + } else if ( value && isFunction( ( method = value.then ) ) ) { + method.call( value, resolve, reject ); + + // Other non-thenables + } else { + + // Control `resolve` arguments by letting Array#slice cast boolean `noValue` to integer: + // * false: [ value ].slice( 0 ) => resolve( value ) + // * true: [ value ].slice( 1 ) => resolve() + resolve.apply( undefined, [ value ].slice( noValue ) ); + } + + // For Promises/A+, convert exceptions into rejections + // Since jQuery.when doesn't unwrap thenables, we can skip the extra checks appearing in + // Deferred#then to conditionally suppress rejection. + } catch ( value ) { + + // Support: Android 4.0 only + // Strict mode functions invoked without .call/.apply get global-object context + reject.apply( undefined, [ value ] ); + } +} + +jQuery.extend( { + + Deferred: function( func ) { + var tuples = [ + + // action, add listener, callbacks, + // ... .then handlers, argument index, [final state] + [ "notify", "progress", jQuery.Callbacks( "memory" ), + jQuery.Callbacks( "memory" ), 2 ], + [ "resolve", "done", jQuery.Callbacks( "once memory" ), + jQuery.Callbacks( "once memory" ), 0, "resolved" ], + [ "reject", "fail", jQuery.Callbacks( "once memory" ), + jQuery.Callbacks( "once memory" ), 1, "rejected" ] + ], + state = "pending", + promise = { + state: function() { + return state; + }, + always: function() { + deferred.done( arguments ).fail( arguments ); + return this; + }, + "catch": function( fn ) { + return promise.then( null, fn ); + }, + + // Keep pipe for back-compat + pipe: function( /* fnDone, fnFail, fnProgress */ ) { + var fns = arguments; + + return jQuery.Deferred( function( newDefer ) { + jQuery.each( tuples, function( _i, tuple ) { + + // Map tuples (progress, done, fail) to arguments (done, fail, progress) + var fn = isFunction( fns[ tuple[ 4 ] ] ) && fns[ tuple[ 4 ] ]; + + // deferred.progress(function() { bind to newDefer or newDefer.notify }) + // deferred.done(function() { bind to newDefer or newDefer.resolve }) + // deferred.fail(function() { bind to newDefer or newDefer.reject }) + deferred[ tuple[ 1 ] ]( function() { + var returned = fn && fn.apply( this, arguments ); + if ( returned && isFunction( returned.promise ) ) { + returned.promise() + .progress( newDefer.notify ) + .done( newDefer.resolve ) + .fail( newDefer.reject ); + } else { + newDefer[ tuple[ 0 ] + "With" ]( + this, + fn ? [ returned ] : arguments + ); + } + } ); + } ); + fns = null; + } ).promise(); + }, + then: function( onFulfilled, onRejected, onProgress ) { + var maxDepth = 0; + function resolve( depth, deferred, handler, special ) { + return function() { + var that = this, + args = arguments, + mightThrow = function() { + var returned, then; + + // Support: Promises/A+ section 2.3.3.3.3 + // https://promisesaplus.com/#point-59 + // Ignore double-resolution attempts + if ( depth < maxDepth ) { + return; + } + + returned = handler.apply( that, args ); + + // Support: Promises/A+ section 2.3.1 + // https://promisesaplus.com/#point-48 + if ( returned === deferred.promise() ) { + throw new TypeError( "Thenable self-resolution" ); + } + + // Support: Promises/A+ sections 2.3.3.1, 3.5 + // https://promisesaplus.com/#point-54 + // https://promisesaplus.com/#point-75 + // Retrieve `then` only once + then = returned && + + // Support: Promises/A+ section 2.3.4 + // https://promisesaplus.com/#point-64 + // Only check objects and functions for thenability + ( typeof returned === "object" || + typeof returned === "function" ) && + returned.then; + + // Handle a returned thenable + if ( isFunction( then ) ) { + + // Special processors (notify) just wait for resolution + if ( special ) { + then.call( + returned, + resolve( maxDepth, deferred, Identity, special ), + resolve( maxDepth, deferred, Thrower, special ) + ); + + // Normal processors (resolve) also hook into progress + } else { + + // ...and disregard older resolution values + maxDepth++; + + then.call( + returned, + resolve( maxDepth, deferred, Identity, special ), + resolve( maxDepth, deferred, Thrower, special ), + resolve( maxDepth, deferred, Identity, + deferred.notifyWith ) + ); + } + + // Handle all other returned values + } else { + + // Only substitute handlers pass on context + // and multiple values (non-spec behavior) + if ( handler !== Identity ) { + that = undefined; + args = [ returned ]; + } + + // Process the value(s) + // Default process is resolve + ( special || deferred.resolveWith )( that, args ); + } + }, + + // Only normal processors (resolve) catch and reject exceptions + process = special ? + mightThrow : + function() { + try { + mightThrow(); + } catch ( e ) { + + if ( jQuery.Deferred.exceptionHook ) { + jQuery.Deferred.exceptionHook( e, + process.stackTrace ); + } + + // Support: Promises/A+ section 2.3.3.3.4.1 + // https://promisesaplus.com/#point-61 + // Ignore post-resolution exceptions + if ( depth + 1 >= maxDepth ) { + + // Only substitute handlers pass on context + // and multiple values (non-spec behavior) + if ( handler !== Thrower ) { + that = undefined; + args = [ e ]; + } + + deferred.rejectWith( that, args ); + } + } + }; + + // Support: Promises/A+ section 2.3.3.3.1 + // https://promisesaplus.com/#point-57 + // Re-resolve promises immediately to dodge false rejection from + // subsequent errors + if ( depth ) { + process(); + } else { + + // Call an optional hook to record the stack, in case of exception + // since it's otherwise lost when execution goes async + if ( jQuery.Deferred.getStackHook ) { + process.stackTrace = jQuery.Deferred.getStackHook(); + } + window.setTimeout( process ); + } + }; + } + + return jQuery.Deferred( function( newDefer ) { + + // progress_handlers.add( ... ) + tuples[ 0 ][ 3 ].add( + resolve( + 0, + newDefer, + isFunction( onProgress ) ? + onProgress : + Identity, + newDefer.notifyWith + ) + ); + + // fulfilled_handlers.add( ... ) + tuples[ 1 ][ 3 ].add( + resolve( + 0, + newDefer, + isFunction( onFulfilled ) ? + onFulfilled : + Identity + ) + ); + + // rejected_handlers.add( ... ) + tuples[ 2 ][ 3 ].add( + resolve( + 0, + newDefer, + isFunction( onRejected ) ? + onRejected : + Thrower + ) + ); + } ).promise(); + }, + + // Get a promise for this deferred + // If obj is provided, the promise aspect is added to the object + promise: function( obj ) { + return obj != null ? jQuery.extend( obj, promise ) : promise; + } + }, + deferred = {}; + + // Add list-specific methods + jQuery.each( tuples, function( i, tuple ) { + var list = tuple[ 2 ], + stateString = tuple[ 5 ]; + + // promise.progress = list.add + // promise.done = list.add + // promise.fail = list.add + promise[ tuple[ 1 ] ] = list.add; + + // Handle state + if ( stateString ) { + list.add( + function() { + + // state = "resolved" (i.e., fulfilled) + // state = "rejected" + state = stateString; + }, + + // rejected_callbacks.disable + // fulfilled_callbacks.disable + tuples[ 3 - i ][ 2 ].disable, + + // rejected_handlers.disable + // fulfilled_handlers.disable + tuples[ 3 - i ][ 3 ].disable, + + // progress_callbacks.lock + tuples[ 0 ][ 2 ].lock, + + // progress_handlers.lock + tuples[ 0 ][ 3 ].lock + ); + } + + // progress_handlers.fire + // fulfilled_handlers.fire + // rejected_handlers.fire + list.add( tuple[ 3 ].fire ); + + // deferred.notify = function() { deferred.notifyWith(...) } + // deferred.resolve = function() { deferred.resolveWith(...) } + // deferred.reject = function() { deferred.rejectWith(...) } + deferred[ tuple[ 0 ] ] = function() { + deferred[ tuple[ 0 ] + "With" ]( this === deferred ? undefined : this, arguments ); + return this; + }; + + // deferred.notifyWith = list.fireWith + // deferred.resolveWith = list.fireWith + // deferred.rejectWith = list.fireWith + deferred[ tuple[ 0 ] + "With" ] = list.fireWith; + } ); + + // Make the deferred a promise + promise.promise( deferred ); + + // Call given func if any + if ( func ) { + func.call( deferred, deferred ); + } + + // All done! + return deferred; + }, + + // Deferred helper + when: function( singleValue ) { + var + + // count of uncompleted subordinates + remaining = arguments.length, + + // count of unprocessed arguments + i = remaining, + + // subordinate fulfillment data + resolveContexts = Array( i ), + resolveValues = slice.call( arguments ), + + // the master Deferred + master = jQuery.Deferred(), + + // subordinate callback factory + updateFunc = function( i ) { + return function( value ) { + resolveContexts[ i ] = this; + resolveValues[ i ] = arguments.length > 1 ? slice.call( arguments ) : value; + if ( !( --remaining ) ) { + master.resolveWith( resolveContexts, resolveValues ); + } + }; + }; + + // Single- and empty arguments are adopted like Promise.resolve + if ( remaining <= 1 ) { + adoptValue( singleValue, master.done( updateFunc( i ) ).resolve, master.reject, + !remaining ); + + // Use .then() to unwrap secondary thenables (cf. gh-3000) + if ( master.state() === "pending" || + isFunction( resolveValues[ i ] && resolveValues[ i ].then ) ) { + + return master.then(); + } + } + + // Multiple arguments are aggregated like Promise.all array elements + while ( i-- ) { + adoptValue( resolveValues[ i ], updateFunc( i ), master.reject ); + } + + return master.promise(); + } +} ); + + +// These usually indicate a programmer mistake during development, +// warn about them ASAP rather than swallowing them by default. +var rerrorNames = /^(Eval|Internal|Range|Reference|Syntax|Type|URI)Error$/; + +jQuery.Deferred.exceptionHook = function( error, stack ) { + + // Support: IE 8 - 9 only + // Console exists when dev tools are open, which can happen at any time + if ( window.console && window.console.warn && error && rerrorNames.test( error.name ) ) { + window.console.warn( "jQuery.Deferred exception: " + error.message, error.stack, stack ); + } +}; + + + + +jQuery.readyException = function( error ) { + window.setTimeout( function() { + throw error; + } ); +}; + + + + +// The deferred used on DOM ready +var readyList = jQuery.Deferred(); + +jQuery.fn.ready = function( fn ) { + + readyList + .then( fn ) + + // Wrap jQuery.readyException in a function so that the lookup + // happens at the time of error handling instead of callback + // registration. + .catch( function( error ) { + jQuery.readyException( error ); + } ); + + return this; +}; + +jQuery.extend( { + + // Is the DOM ready to be used? Set to true once it occurs. + isReady: false, + + // A counter to track how many items to wait for before + // the ready event fires. See #6781 + readyWait: 1, + + // Handle when the DOM is ready + ready: function( wait ) { + + // Abort if there are pending holds or we're already ready + if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) { + return; + } + + // Remember that the DOM is ready + jQuery.isReady = true; + + // If a normal DOM Ready event fired, decrement, and wait if need be + if ( wait !== true && --jQuery.readyWait > 0 ) { + return; + } + + // If there are functions bound, to execute + readyList.resolveWith( document, [ jQuery ] ); + } +} ); + +jQuery.ready.then = readyList.then; + +// The ready event handler and self cleanup method +function completed() { + document.removeEventListener( "DOMContentLoaded", completed ); + window.removeEventListener( "load", completed ); + jQuery.ready(); +} + +// Catch cases where $(document).ready() is called +// after the browser event has already occurred. +// Support: IE <=9 - 10 only +// Older IE sometimes signals "interactive" too soon +if ( document.readyState === "complete" || + ( document.readyState !== "loading" && !document.documentElement.doScroll ) ) { + + // Handle it asynchronously to allow scripts the opportunity to delay ready + window.setTimeout( jQuery.ready ); + +} else { + + // Use the handy event callback + document.addEventListener( "DOMContentLoaded", completed ); + + // A fallback to window.onload, that will always work + window.addEventListener( "load", completed ); +} + + + + +// Multifunctional method to get and set values of a collection +// The value/s can optionally be executed if it's a function +var access = function( elems, fn, key, value, chainable, emptyGet, raw ) { + var i = 0, + len = elems.length, + bulk = key == null; + + // Sets many values + if ( toType( key ) === "object" ) { + chainable = true; + for ( i in key ) { + access( elems, fn, i, key[ i ], true, emptyGet, raw ); + } + + // Sets one value + } else if ( value !== undefined ) { + chainable = true; + + if ( !isFunction( value ) ) { + raw = true; + } + + if ( bulk ) { + + // Bulk operations run against the entire set + if ( raw ) { + fn.call( elems, value ); + fn = null; + + // ...except when executing function values + } else { + bulk = fn; + fn = function( elem, _key, value ) { + return bulk.call( jQuery( elem ), value ); + }; + } + } + + if ( fn ) { + for ( ; i < len; i++ ) { + fn( + elems[ i ], key, raw ? + value : + value.call( elems[ i ], i, fn( elems[ i ], key ) ) + ); + } + } + } + + if ( chainable ) { + return elems; + } + + // Gets + if ( bulk ) { + return fn.call( elems ); + } + + return len ? fn( elems[ 0 ], key ) : emptyGet; +}; + + +// Matches dashed string for camelizing +var rmsPrefix = /^-ms-/, + rdashAlpha = /-([a-z])/g; + +// Used by camelCase as callback to replace() +function fcamelCase( _all, letter ) { + return letter.toUpperCase(); +} + +// Convert dashed to camelCase; used by the css and data modules +// Support: IE <=9 - 11, Edge 12 - 15 +// Microsoft forgot to hump their vendor prefix (#9572) +function camelCase( string ) { + return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase ); +} +var acceptData = function( owner ) { + + // Accepts only: + // - Node + // - Node.ELEMENT_NODE + // - Node.DOCUMENT_NODE + // - Object + // - Any + return owner.nodeType === 1 || owner.nodeType === 9 || !( +owner.nodeType ); +}; + + + + +function Data() { + this.expando = jQuery.expando + Data.uid++; +} + +Data.uid = 1; + +Data.prototype = { + + cache: function( owner ) { + + // Check if the owner object already has a cache + var value = owner[ this.expando ]; + + // If not, create one + if ( !value ) { + value = {}; + + // We can accept data for non-element nodes in modern browsers, + // but we should not, see #8335. + // Always return an empty object. + if ( acceptData( owner ) ) { + + // If it is a node unlikely to be stringify-ed or looped over + // use plain assignment + if ( owner.nodeType ) { + owner[ this.expando ] = value; + + // Otherwise secure it in a non-enumerable property + // configurable must be true to allow the property to be + // deleted when data is removed + } else { + Object.defineProperty( owner, this.expando, { + value: value, + configurable: true + } ); + } + } + } + + return value; + }, + set: function( owner, data, value ) { + var prop, + cache = this.cache( owner ); + + // Handle: [ owner, key, value ] args + // Always use camelCase key (gh-2257) + if ( typeof data === "string" ) { + cache[ camelCase( data ) ] = value; + + // Handle: [ owner, { properties } ] args + } else { + + // Copy the properties one-by-one to the cache object + for ( prop in data ) { + cache[ camelCase( prop ) ] = data[ prop ]; + } + } + return cache; + }, + get: function( owner, key ) { + return key === undefined ? + this.cache( owner ) : + + // Always use camelCase key (gh-2257) + owner[ this.expando ] && owner[ this.expando ][ camelCase( key ) ]; + }, + access: function( owner, key, value ) { + + // In cases where either: + // + // 1. No key was specified + // 2. A string key was specified, but no value provided + // + // Take the "read" path and allow the get method to determine + // which value to return, respectively either: + // + // 1. The entire cache object + // 2. The data stored at the key + // + if ( key === undefined || + ( ( key && typeof key === "string" ) && value === undefined ) ) { + + return this.get( owner, key ); + } + + // When the key is not a string, or both a key and value + // are specified, set or extend (existing objects) with either: + // + // 1. An object of properties + // 2. A key and value + // + this.set( owner, key, value ); + + // Since the "set" path can have two possible entry points + // return the expected data based on which path was taken[*] + return value !== undefined ? value : key; + }, + remove: function( owner, key ) { + var i, + cache = owner[ this.expando ]; + + if ( cache === undefined ) { + return; + } + + if ( key !== undefined ) { + + // Support array or space separated string of keys + if ( Array.isArray( key ) ) { + + // If key is an array of keys... + // We always set camelCase keys, so remove that. + key = key.map( camelCase ); + } else { + key = camelCase( key ); + + // If a key with the spaces exists, use it. + // Otherwise, create an array by matching non-whitespace + key = key in cache ? + [ key ] : + ( key.match( rnothtmlwhite ) || [] ); + } + + i = key.length; + + while ( i-- ) { + delete cache[ key[ i ] ]; + } + } + + // Remove the expando if there's no more data + if ( key === undefined || jQuery.isEmptyObject( cache ) ) { + + // Support: Chrome <=35 - 45 + // Webkit & Blink performance suffers when deleting properties + // from DOM nodes, so set to undefined instead + // https://bugs.chromium.org/p/chromium/issues/detail?id=378607 (bug restricted) + if ( owner.nodeType ) { + owner[ this.expando ] = undefined; + } else { + delete owner[ this.expando ]; + } + } + }, + hasData: function( owner ) { + var cache = owner[ this.expando ]; + return cache !== undefined && !jQuery.isEmptyObject( cache ); + } +}; +var dataPriv = new Data(); + +var dataUser = new Data(); + + + +// Implementation Summary +// +// 1. Enforce API surface and semantic compatibility with 1.9.x branch +// 2. Improve the module's maintainability by reducing the storage +// paths to a single mechanism. +// 3. Use the same single mechanism to support "private" and "user" data. +// 4. _Never_ expose "private" data to user code (TODO: Drop _data, _removeData) +// 5. Avoid exposing implementation details on user objects (eg. expando properties) +// 6. Provide a clear path for implementation upgrade to WeakMap in 2014 + +var rbrace = /^(?:\{[\w\W]*\}|\[[\w\W]*\])$/, + rmultiDash = /[A-Z]/g; + +function getData( data ) { + if ( data === "true" ) { + return true; + } + + if ( data === "false" ) { + return false; + } + + if ( data === "null" ) { + return null; + } + + // Only convert to a number if it doesn't change the string + if ( data === +data + "" ) { + return +data; + } + + if ( rbrace.test( data ) ) { + return JSON.parse( data ); + } + + return data; +} + +function dataAttr( elem, key, data ) { + var name; + + // If nothing was found internally, try to fetch any + // data from the HTML5 data-* attribute + if ( data === undefined && elem.nodeType === 1 ) { + name = "data-" + key.replace( rmultiDash, "-$&" ).toLowerCase(); + data = elem.getAttribute( name ); + + if ( typeof data === "string" ) { + try { + data = getData( data ); + } catch ( e ) {} + + // Make sure we set the data so it isn't changed later + dataUser.set( elem, key, data ); + } else { + data = undefined; + } + } + return data; +} + +jQuery.extend( { + hasData: function( elem ) { + return dataUser.hasData( elem ) || dataPriv.hasData( elem ); + }, + + data: function( elem, name, data ) { + return dataUser.access( elem, name, data ); + }, + + removeData: function( elem, name ) { + dataUser.remove( elem, name ); + }, + + // TODO: Now that all calls to _data and _removeData have been replaced + // with direct calls to dataPriv methods, these can be deprecated. + _data: function( elem, name, data ) { + return dataPriv.access( elem, name, data ); + }, + + _removeData: function( elem, name ) { + dataPriv.remove( elem, name ); + } +} ); + +jQuery.fn.extend( { + data: function( key, value ) { + var i, name, data, + elem = this[ 0 ], + attrs = elem && elem.attributes; + + // Gets all values + if ( key === undefined ) { + if ( this.length ) { + data = dataUser.get( elem ); + + if ( elem.nodeType === 1 && !dataPriv.get( elem, "hasDataAttrs" ) ) { + i = attrs.length; + while ( i-- ) { + + // Support: IE 11 only + // The attrs elements can be null (#14894) + if ( attrs[ i ] ) { + name = attrs[ i ].name; + if ( name.indexOf( "data-" ) === 0 ) { + name = camelCase( name.slice( 5 ) ); + dataAttr( elem, name, data[ name ] ); + } + } + } + dataPriv.set( elem, "hasDataAttrs", true ); + } + } + + return data; + } + + // Sets multiple values + if ( typeof key === "object" ) { + return this.each( function() { + dataUser.set( this, key ); + } ); + } + + return access( this, function( value ) { + var data; + + // The calling jQuery object (element matches) is not empty + // (and therefore has an element appears at this[ 0 ]) and the + // `value` parameter was not undefined. An empty jQuery object + // will result in `undefined` for elem = this[ 0 ] which will + // throw an exception if an attempt to read a data cache is made. + if ( elem && value === undefined ) { + + // Attempt to get data from the cache + // The key will always be camelCased in Data + data = dataUser.get( elem, key ); + if ( data !== undefined ) { + return data; + } + + // Attempt to "discover" the data in + // HTML5 custom data-* attrs + data = dataAttr( elem, key ); + if ( data !== undefined ) { + return data; + } + + // We tried really hard, but the data doesn't exist. + return; + } + + // Set the data... + this.each( function() { + + // We always store the camelCased key + dataUser.set( this, key, value ); + } ); + }, null, value, arguments.length > 1, null, true ); + }, + + removeData: function( key ) { + return this.each( function() { + dataUser.remove( this, key ); + } ); + } +} ); + + +jQuery.extend( { + queue: function( elem, type, data ) { + var queue; + + if ( elem ) { + type = ( type || "fx" ) + "queue"; + queue = dataPriv.get( elem, type ); + + // Speed up dequeue by getting out quickly if this is just a lookup + if ( data ) { + if ( !queue || Array.isArray( data ) ) { + queue = dataPriv.access( elem, type, jQuery.makeArray( data ) ); + } else { + queue.push( data ); + } + } + return queue || []; + } + }, + + dequeue: function( elem, type ) { + type = type || "fx"; + + var queue = jQuery.queue( elem, type ), + startLength = queue.length, + fn = queue.shift(), + hooks = jQuery._queueHooks( elem, type ), + next = function() { + jQuery.dequeue( elem, type ); + }; + + // If the fx queue is dequeued, always remove the progress sentinel + if ( fn === "inprogress" ) { + fn = queue.shift(); + startLength--; + } + + if ( fn ) { + + // Add a progress sentinel to prevent the fx queue from being + // automatically dequeued + if ( type === "fx" ) { + queue.unshift( "inprogress" ); + } + + // Clear up the last queue stop function + delete hooks.stop; + fn.call( elem, next, hooks ); + } + + if ( !startLength && hooks ) { + hooks.empty.fire(); + } + }, + + // Not public - generate a queueHooks object, or return the current one + _queueHooks: function( elem, type ) { + var key = type + "queueHooks"; + return dataPriv.get( elem, key ) || dataPriv.access( elem, key, { + empty: jQuery.Callbacks( "once memory" ).add( function() { + dataPriv.remove( elem, [ type + "queue", key ] ); + } ) + } ); + } +} ); + +jQuery.fn.extend( { + queue: function( type, data ) { + var setter = 2; + + if ( typeof type !== "string" ) { + data = type; + type = "fx"; + setter--; + } + + if ( arguments.length < setter ) { + return jQuery.queue( this[ 0 ], type ); + } + + return data === undefined ? + this : + this.each( function() { + var queue = jQuery.queue( this, type, data ); + + // Ensure a hooks for this queue + jQuery._queueHooks( this, type ); + + if ( type === "fx" && queue[ 0 ] !== "inprogress" ) { + jQuery.dequeue( this, type ); + } + } ); + }, + dequeue: function( type ) { + return this.each( function() { + jQuery.dequeue( this, type ); + } ); + }, + clearQueue: function( type ) { + return this.queue( type || "fx", [] ); + }, + + // Get a promise resolved when queues of a certain type + // are emptied (fx is the type by default) + promise: function( type, obj ) { + var tmp, + count = 1, + defer = jQuery.Deferred(), + elements = this, + i = this.length, + resolve = function() { + if ( !( --count ) ) { + defer.resolveWith( elements, [ elements ] ); + } + }; + + if ( typeof type !== "string" ) { + obj = type; + type = undefined; + } + type = type || "fx"; + + while ( i-- ) { + tmp = dataPriv.get( elements[ i ], type + "queueHooks" ); + if ( tmp && tmp.empty ) { + count++; + tmp.empty.add( resolve ); + } + } + resolve(); + return defer.promise( obj ); + } +} ); +var pnum = ( /[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/ ).source; + +var rcssNum = new RegExp( "^(?:([+-])=|)(" + pnum + ")([a-z%]*)$", "i" ); + + +var cssExpand = [ "Top", "Right", "Bottom", "Left" ]; + +var documentElement = document.documentElement; + + + + var isAttached = function( elem ) { + return jQuery.contains( elem.ownerDocument, elem ); + }, + composed = { composed: true }; + + // Support: IE 9 - 11+, Edge 12 - 18+, iOS 10.0 - 10.2 only + // Check attachment across shadow DOM boundaries when possible (gh-3504) + // Support: iOS 10.0-10.2 only + // Early iOS 10 versions support `attachShadow` but not `getRootNode`, + // leading to errors. We need to check for `getRootNode`. + if ( documentElement.getRootNode ) { + isAttached = function( elem ) { + return jQuery.contains( elem.ownerDocument, elem ) || + elem.getRootNode( composed ) === elem.ownerDocument; + }; + } +var isHiddenWithinTree = function( elem, el ) { + + // isHiddenWithinTree might be called from jQuery#filter function; + // in that case, element will be second argument + elem = el || elem; + + // Inline style trumps all + return elem.style.display === "none" || + elem.style.display === "" && + + // Otherwise, check computed style + // Support: Firefox <=43 - 45 + // Disconnected elements can have computed display: none, so first confirm that elem is + // in the document. + isAttached( elem ) && + + jQuery.css( elem, "display" ) === "none"; + }; + + + +function adjustCSS( elem, prop, valueParts, tween ) { + var adjusted, scale, + maxIterations = 20, + currentValue = tween ? + function() { + return tween.cur(); + } : + function() { + return jQuery.css( elem, prop, "" ); + }, + initial = currentValue(), + unit = valueParts && valueParts[ 3 ] || ( jQuery.cssNumber[ prop ] ? "" : "px" ), + + // Starting value computation is required for potential unit mismatches + initialInUnit = elem.nodeType && + ( jQuery.cssNumber[ prop ] || unit !== "px" && +initial ) && + rcssNum.exec( jQuery.css( elem, prop ) ); + + if ( initialInUnit && initialInUnit[ 3 ] !== unit ) { + + // Support: Firefox <=54 + // Halve the iteration target value to prevent interference from CSS upper bounds (gh-2144) + initial = initial / 2; + + // Trust units reported by jQuery.css + unit = unit || initialInUnit[ 3 ]; + + // Iteratively approximate from a nonzero starting point + initialInUnit = +initial || 1; + + while ( maxIterations-- ) { + + // Evaluate and update our best guess (doubling guesses that zero out). + // Finish if the scale equals or crosses 1 (making the old*new product non-positive). + jQuery.style( elem, prop, initialInUnit + unit ); + if ( ( 1 - scale ) * ( 1 - ( scale = currentValue() / initial || 0.5 ) ) <= 0 ) { + maxIterations = 0; + } + initialInUnit = initialInUnit / scale; + + } + + initialInUnit = initialInUnit * 2; + jQuery.style( elem, prop, initialInUnit + unit ); + + // Make sure we update the tween properties later on + valueParts = valueParts || []; + } + + if ( valueParts ) { + initialInUnit = +initialInUnit || +initial || 0; + + // Apply relative offset (+=/-=) if specified + adjusted = valueParts[ 1 ] ? + initialInUnit + ( valueParts[ 1 ] + 1 ) * valueParts[ 2 ] : + +valueParts[ 2 ]; + if ( tween ) { + tween.unit = unit; + tween.start = initialInUnit; + tween.end = adjusted; + } + } + return adjusted; +} + + +var defaultDisplayMap = {}; + +function getDefaultDisplay( elem ) { + var temp, + doc = elem.ownerDocument, + nodeName = elem.nodeName, + display = defaultDisplayMap[ nodeName ]; + + if ( display ) { + return display; + } + + temp = doc.body.appendChild( doc.createElement( nodeName ) ); + display = jQuery.css( temp, "display" ); + + temp.parentNode.removeChild( temp ); + + if ( display === "none" ) { + display = "block"; + } + defaultDisplayMap[ nodeName ] = display; + + return display; +} + +function showHide( elements, show ) { + var display, elem, + values = [], + index = 0, + length = elements.length; + + // Determine new display value for elements that need to change + for ( ; index < length; index++ ) { + elem = elements[ index ]; + if ( !elem.style ) { + continue; + } + + display = elem.style.display; + if ( show ) { + + // Since we force visibility upon cascade-hidden elements, an immediate (and slow) + // check is required in this first loop unless we have a nonempty display value (either + // inline or about-to-be-restored) + if ( display === "none" ) { + values[ index ] = dataPriv.get( elem, "display" ) || null; + if ( !values[ index ] ) { + elem.style.display = ""; + } + } + if ( elem.style.display === "" && isHiddenWithinTree( elem ) ) { + values[ index ] = getDefaultDisplay( elem ); + } + } else { + if ( display !== "none" ) { + values[ index ] = "none"; + + // Remember what we're overwriting + dataPriv.set( elem, "display", display ); + } + } + } + + // Set the display of the elements in a second loop to avoid constant reflow + for ( index = 0; index < length; index++ ) { + if ( values[ index ] != null ) { + elements[ index ].style.display = values[ index ]; + } + } + + return elements; +} + +jQuery.fn.extend( { + show: function() { + return showHide( this, true ); + }, + hide: function() { + return showHide( this ); + }, + toggle: function( state ) { + if ( typeof state === "boolean" ) { + return state ? this.show() : this.hide(); + } + + return this.each( function() { + if ( isHiddenWithinTree( this ) ) { + jQuery( this ).show(); + } else { + jQuery( this ).hide(); + } + } ); + } +} ); +var rcheckableType = ( /^(?:checkbox|radio)$/i ); + +var rtagName = ( /<([a-z][^\/\0>\x20\t\r\n\f]*)/i ); + +var rscriptType = ( /^$|^module$|\/(?:java|ecma)script/i ); + + + +( function() { + var fragment = document.createDocumentFragment(), + div = fragment.appendChild( document.createElement( "div" ) ), + input = document.createElement( "input" ); + + // Support: Android 4.0 - 4.3 only + // Check state lost if the name is set (#11217) + // Support: Windows Web Apps (WWA) + // `name` and `type` must use .setAttribute for WWA (#14901) + input.setAttribute( "type", "radio" ); + input.setAttribute( "checked", "checked" ); + input.setAttribute( "name", "t" ); + + div.appendChild( input ); + + // Support: Android <=4.1 only + // Older WebKit doesn't clone checked state correctly in fragments + support.checkClone = div.cloneNode( true ).cloneNode( true ).lastChild.checked; + + // Support: IE <=11 only + // Make sure textarea (and checkbox) defaultValue is properly cloned + div.innerHTML = ""; + support.noCloneChecked = !!div.cloneNode( true ).lastChild.defaultValue; + + // Support: IE <=9 only + // IE <=9 replaces "; + support.option = !!div.lastChild; +} )(); + + +// We have to close these tags to support XHTML (#13200) +var wrapMap = { + + // XHTML parsers do not magically insert elements in the + // same way that tag soup parsers do. So we cannot shorten + // this by omitting or other required elements. + thead: [ 1, "", "
" ], + col: [ 2, "", "
" ], + tr: [ 2, "", "
" ], + td: [ 3, "", "
" ], + + _default: [ 0, "", "" ] +}; + +wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; +wrapMap.th = wrapMap.td; + +// Support: IE <=9 only +if ( !support.option ) { + wrapMap.optgroup = wrapMap.option = [ 1, "" ]; +} + + +function getAll( context, tag ) { + + // Support: IE <=9 - 11 only + // Use typeof to avoid zero-argument method invocation on host objects (#15151) + var ret; + + if ( typeof context.getElementsByTagName !== "undefined" ) { + ret = context.getElementsByTagName( tag || "*" ); + + } else if ( typeof context.querySelectorAll !== "undefined" ) { + ret = context.querySelectorAll( tag || "*" ); + + } else { + ret = []; + } + + if ( tag === undefined || tag && nodeName( context, tag ) ) { + return jQuery.merge( [ context ], ret ); + } + + return ret; +} + + +// Mark scripts as having already been evaluated +function setGlobalEval( elems, refElements ) { + var i = 0, + l = elems.length; + + for ( ; i < l; i++ ) { + dataPriv.set( + elems[ i ], + "globalEval", + !refElements || dataPriv.get( refElements[ i ], "globalEval" ) + ); + } +} + + +var rhtml = /<|&#?\w+;/; + +function buildFragment( elems, context, scripts, selection, ignored ) { + var elem, tmp, tag, wrap, attached, j, + fragment = context.createDocumentFragment(), + nodes = [], + i = 0, + l = elems.length; + + for ( ; i < l; i++ ) { + elem = elems[ i ]; + + if ( elem || elem === 0 ) { + + // Add nodes directly + if ( toType( elem ) === "object" ) { + + // Support: Android <=4.0 only, PhantomJS 1 only + // push.apply(_, arraylike) throws on ancient WebKit + jQuery.merge( nodes, elem.nodeType ? [ elem ] : elem ); + + // Convert non-html into a text node + } else if ( !rhtml.test( elem ) ) { + nodes.push( context.createTextNode( elem ) ); + + // Convert html into DOM nodes + } else { + tmp = tmp || fragment.appendChild( context.createElement( "div" ) ); + + // Deserialize a standard representation + tag = ( rtagName.exec( elem ) || [ "", "" ] )[ 1 ].toLowerCase(); + wrap = wrapMap[ tag ] || wrapMap._default; + tmp.innerHTML = wrap[ 1 ] + jQuery.htmlPrefilter( elem ) + wrap[ 2 ]; + + // Descend through wrappers to the right content + j = wrap[ 0 ]; + while ( j-- ) { + tmp = tmp.lastChild; + } + + // Support: Android <=4.0 only, PhantomJS 1 only + // push.apply(_, arraylike) throws on ancient WebKit + jQuery.merge( nodes, tmp.childNodes ); + + // Remember the top-level container + tmp = fragment.firstChild; + + // Ensure the created nodes are orphaned (#12392) + tmp.textContent = ""; + } + } + } + + // Remove wrapper from fragment + fragment.textContent = ""; + + i = 0; + while ( ( elem = nodes[ i++ ] ) ) { + + // Skip elements already in the context collection (trac-4087) + if ( selection && jQuery.inArray( elem, selection ) > -1 ) { + if ( ignored ) { + ignored.push( elem ); + } + continue; + } + + attached = isAttached( elem ); + + // Append to fragment + tmp = getAll( fragment.appendChild( elem ), "script" ); + + // Preserve script evaluation history + if ( attached ) { + setGlobalEval( tmp ); + } + + // Capture executables + if ( scripts ) { + j = 0; + while ( ( elem = tmp[ j++ ] ) ) { + if ( rscriptType.test( elem.type || "" ) ) { + scripts.push( elem ); + } + } + } + } + + return fragment; +} + + +var + rkeyEvent = /^key/, + rmouseEvent = /^(?:mouse|pointer|contextmenu|drag|drop)|click/, + rtypenamespace = /^([^.]*)(?:\.(.+)|)/; + +function returnTrue() { + return true; +} + +function returnFalse() { + return false; +} + +// Support: IE <=9 - 11+ +// focus() and blur() are asynchronous, except when they are no-op. +// So expect focus to be synchronous when the element is already active, +// and blur to be synchronous when the element is not already active. +// (focus and blur are always synchronous in other supported browsers, +// this just defines when we can count on it). +function expectSync( elem, type ) { + return ( elem === safeActiveElement() ) === ( type === "focus" ); +} + +// Support: IE <=9 only +// Accessing document.activeElement can throw unexpectedly +// https://bugs.jquery.com/ticket/13393 +function safeActiveElement() { + try { + return document.activeElement; + } catch ( err ) { } +} + +function on( elem, types, selector, data, fn, one ) { + var origFn, type; + + // Types can be a map of types/handlers + if ( typeof types === "object" ) { + + // ( types-Object, selector, data ) + if ( typeof selector !== "string" ) { + + // ( types-Object, data ) + data = data || selector; + selector = undefined; + } + for ( type in types ) { + on( elem, type, selector, data, types[ type ], one ); + } + return elem; + } + + if ( data == null && fn == null ) { + + // ( types, fn ) + fn = selector; + data = selector = undefined; + } else if ( fn == null ) { + if ( typeof selector === "string" ) { + + // ( types, selector, fn ) + fn = data; + data = undefined; + } else { + + // ( types, data, fn ) + fn = data; + data = selector; + selector = undefined; + } + } + if ( fn === false ) { + fn = returnFalse; + } else if ( !fn ) { + return elem; + } + + if ( one === 1 ) { + origFn = fn; + fn = function( event ) { + + // Can use an empty set, since event contains the info + jQuery().off( event ); + return origFn.apply( this, arguments ); + }; + + // Use same guid so caller can remove using origFn + fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ ); + } + return elem.each( function() { + jQuery.event.add( this, types, fn, data, selector ); + } ); +} + +/* + * Helper functions for managing events -- not part of the public interface. + * Props to Dean Edwards' addEvent library for many of the ideas. + */ +jQuery.event = { + + global: {}, + + add: function( elem, types, handler, data, selector ) { + + var handleObjIn, eventHandle, tmp, + events, t, handleObj, + special, handlers, type, namespaces, origType, + elemData = dataPriv.get( elem ); + + // Only attach events to objects that accept data + if ( !acceptData( elem ) ) { + return; + } + + // Caller can pass in an object of custom data in lieu of the handler + if ( handler.handler ) { + handleObjIn = handler; + handler = handleObjIn.handler; + selector = handleObjIn.selector; + } + + // Ensure that invalid selectors throw exceptions at attach time + // Evaluate against documentElement in case elem is a non-element node (e.g., document) + if ( selector ) { + jQuery.find.matchesSelector( documentElement, selector ); + } + + // Make sure that the handler has a unique ID, used to find/remove it later + if ( !handler.guid ) { + handler.guid = jQuery.guid++; + } + + // Init the element's event structure and main handler, if this is the first + if ( !( events = elemData.events ) ) { + events = elemData.events = Object.create( null ); + } + if ( !( eventHandle = elemData.handle ) ) { + eventHandle = elemData.handle = function( e ) { + + // Discard the second event of a jQuery.event.trigger() and + // when an event is called after a page has unloaded + return typeof jQuery !== "undefined" && jQuery.event.triggered !== e.type ? + jQuery.event.dispatch.apply( elem, arguments ) : undefined; + }; + } + + // Handle multiple events separated by a space + types = ( types || "" ).match( rnothtmlwhite ) || [ "" ]; + t = types.length; + while ( t-- ) { + tmp = rtypenamespace.exec( types[ t ] ) || []; + type = origType = tmp[ 1 ]; + namespaces = ( tmp[ 2 ] || "" ).split( "." ).sort(); + + // There *must* be a type, no attaching namespace-only handlers + if ( !type ) { + continue; + } + + // If event changes its type, use the special event handlers for the changed type + special = jQuery.event.special[ type ] || {}; + + // If selector defined, determine special event api type, otherwise given type + type = ( selector ? special.delegateType : special.bindType ) || type; + + // Update special based on newly reset type + special = jQuery.event.special[ type ] || {}; + + // handleObj is passed to all event handlers + handleObj = jQuery.extend( { + type: type, + origType: origType, + data: data, + handler: handler, + guid: handler.guid, + selector: selector, + needsContext: selector && jQuery.expr.match.needsContext.test( selector ), + namespace: namespaces.join( "." ) + }, handleObjIn ); + + // Init the event handler queue if we're the first + if ( !( handlers = events[ type ] ) ) { + handlers = events[ type ] = []; + handlers.delegateCount = 0; + + // Only use addEventListener if the special events handler returns false + if ( !special.setup || + special.setup.call( elem, data, namespaces, eventHandle ) === false ) { + + if ( elem.addEventListener ) { + elem.addEventListener( type, eventHandle ); + } + } + } + + if ( special.add ) { + special.add.call( elem, handleObj ); + + if ( !handleObj.handler.guid ) { + handleObj.handler.guid = handler.guid; + } + } + + // Add to the element's handler list, delegates in front + if ( selector ) { + handlers.splice( handlers.delegateCount++, 0, handleObj ); + } else { + handlers.push( handleObj ); + } + + // Keep track of which events have ever been used, for event optimization + jQuery.event.global[ type ] = true; + } + + }, + + // Detach an event or set of events from an element + remove: function( elem, types, handler, selector, mappedTypes ) { + + var j, origCount, tmp, + events, t, handleObj, + special, handlers, type, namespaces, origType, + elemData = dataPriv.hasData( elem ) && dataPriv.get( elem ); + + if ( !elemData || !( events = elemData.events ) ) { + return; + } + + // Once for each type.namespace in types; type may be omitted + types = ( types || "" ).match( rnothtmlwhite ) || [ "" ]; + t = types.length; + while ( t-- ) { + tmp = rtypenamespace.exec( types[ t ] ) || []; + type = origType = tmp[ 1 ]; + namespaces = ( tmp[ 2 ] || "" ).split( "." ).sort(); + + // Unbind all events (on this namespace, if provided) for the element + if ( !type ) { + for ( type in events ) { + jQuery.event.remove( elem, type + types[ t ], handler, selector, true ); + } + continue; + } + + special = jQuery.event.special[ type ] || {}; + type = ( selector ? special.delegateType : special.bindType ) || type; + handlers = events[ type ] || []; + tmp = tmp[ 2 ] && + new RegExp( "(^|\\.)" + namespaces.join( "\\.(?:.*\\.|)" ) + "(\\.|$)" ); + + // Remove matching events + origCount = j = handlers.length; + while ( j-- ) { + handleObj = handlers[ j ]; + + if ( ( mappedTypes || origType === handleObj.origType ) && + ( !handler || handler.guid === handleObj.guid ) && + ( !tmp || tmp.test( handleObj.namespace ) ) && + ( !selector || selector === handleObj.selector || + selector === "**" && handleObj.selector ) ) { + handlers.splice( j, 1 ); + + if ( handleObj.selector ) { + handlers.delegateCount--; + } + if ( special.remove ) { + special.remove.call( elem, handleObj ); + } + } + } + + // Remove generic event handler if we removed something and no more handlers exist + // (avoids potential for endless recursion during removal of special event handlers) + if ( origCount && !handlers.length ) { + if ( !special.teardown || + special.teardown.call( elem, namespaces, elemData.handle ) === false ) { + + jQuery.removeEvent( elem, type, elemData.handle ); + } + + delete events[ type ]; + } + } + + // Remove data and the expando if it's no longer used + if ( jQuery.isEmptyObject( events ) ) { + dataPriv.remove( elem, "handle events" ); + } + }, + + dispatch: function( nativeEvent ) { + + var i, j, ret, matched, handleObj, handlerQueue, + args = new Array( arguments.length ), + + // Make a writable jQuery.Event from the native event object + event = jQuery.event.fix( nativeEvent ), + + handlers = ( + dataPriv.get( this, "events" ) || Object.create( null ) + )[ event.type ] || [], + special = jQuery.event.special[ event.type ] || {}; + + // Use the fix-ed jQuery.Event rather than the (read-only) native event + args[ 0 ] = event; + + for ( i = 1; i < arguments.length; i++ ) { + args[ i ] = arguments[ i ]; + } + + event.delegateTarget = this; + + // Call the preDispatch hook for the mapped type, and let it bail if desired + if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) { + return; + } + + // Determine handlers + handlerQueue = jQuery.event.handlers.call( this, event, handlers ); + + // Run delegates first; they may want to stop propagation beneath us + i = 0; + while ( ( matched = handlerQueue[ i++ ] ) && !event.isPropagationStopped() ) { + event.currentTarget = matched.elem; + + j = 0; + while ( ( handleObj = matched.handlers[ j++ ] ) && + !event.isImmediatePropagationStopped() ) { + + // If the event is namespaced, then each handler is only invoked if it is + // specially universal or its namespaces are a superset of the event's. + if ( !event.rnamespace || handleObj.namespace === false || + event.rnamespace.test( handleObj.namespace ) ) { + + event.handleObj = handleObj; + event.data = handleObj.data; + + ret = ( ( jQuery.event.special[ handleObj.origType ] || {} ).handle || + handleObj.handler ).apply( matched.elem, args ); + + if ( ret !== undefined ) { + if ( ( event.result = ret ) === false ) { + event.preventDefault(); + event.stopPropagation(); + } + } + } + } + } + + // Call the postDispatch hook for the mapped type + if ( special.postDispatch ) { + special.postDispatch.call( this, event ); + } + + return event.result; + }, + + handlers: function( event, handlers ) { + var i, handleObj, sel, matchedHandlers, matchedSelectors, + handlerQueue = [], + delegateCount = handlers.delegateCount, + cur = event.target; + + // Find delegate handlers + if ( delegateCount && + + // Support: IE <=9 + // Black-hole SVG instance trees (trac-13180) + cur.nodeType && + + // Support: Firefox <=42 + // Suppress spec-violating clicks indicating a non-primary pointer button (trac-3861) + // https://www.w3.org/TR/DOM-Level-3-Events/#event-type-click + // Support: IE 11 only + // ...but not arrow key "clicks" of radio inputs, which can have `button` -1 (gh-2343) + !( event.type === "click" && event.button >= 1 ) ) { + + for ( ; cur !== this; cur = cur.parentNode || this ) { + + // Don't check non-elements (#13208) + // Don't process clicks on disabled elements (#6911, #8165, #11382, #11764) + if ( cur.nodeType === 1 && !( event.type === "click" && cur.disabled === true ) ) { + matchedHandlers = []; + matchedSelectors = {}; + for ( i = 0; i < delegateCount; i++ ) { + handleObj = handlers[ i ]; + + // Don't conflict with Object.prototype properties (#13203) + sel = handleObj.selector + " "; + + if ( matchedSelectors[ sel ] === undefined ) { + matchedSelectors[ sel ] = handleObj.needsContext ? + jQuery( sel, this ).index( cur ) > -1 : + jQuery.find( sel, this, null, [ cur ] ).length; + } + if ( matchedSelectors[ sel ] ) { + matchedHandlers.push( handleObj ); + } + } + if ( matchedHandlers.length ) { + handlerQueue.push( { elem: cur, handlers: matchedHandlers } ); + } + } + } + } + + // Add the remaining (directly-bound) handlers + cur = this; + if ( delegateCount < handlers.length ) { + handlerQueue.push( { elem: cur, handlers: handlers.slice( delegateCount ) } ); + } + + return handlerQueue; + }, + + addProp: function( name, hook ) { + Object.defineProperty( jQuery.Event.prototype, name, { + enumerable: true, + configurable: true, + + get: isFunction( hook ) ? + function() { + if ( this.originalEvent ) { + return hook( this.originalEvent ); + } + } : + function() { + if ( this.originalEvent ) { + return this.originalEvent[ name ]; + } + }, + + set: function( value ) { + Object.defineProperty( this, name, { + enumerable: true, + configurable: true, + writable: true, + value: value + } ); + } + } ); + }, + + fix: function( originalEvent ) { + return originalEvent[ jQuery.expando ] ? + originalEvent : + new jQuery.Event( originalEvent ); + }, + + special: { + load: { + + // Prevent triggered image.load events from bubbling to window.load + noBubble: true + }, + click: { + + // Utilize native event to ensure correct state for checkable inputs + setup: function( data ) { + + // For mutual compressibility with _default, replace `this` access with a local var. + // `|| data` is dead code meant only to preserve the variable through minification. + var el = this || data; + + // Claim the first handler + if ( rcheckableType.test( el.type ) && + el.click && nodeName( el, "input" ) ) { + + // dataPriv.set( el, "click", ... ) + leverageNative( el, "click", returnTrue ); + } + + // Return false to allow normal processing in the caller + return false; + }, + trigger: function( data ) { + + // For mutual compressibility with _default, replace `this` access with a local var. + // `|| data` is dead code meant only to preserve the variable through minification. + var el = this || data; + + // Force setup before triggering a click + if ( rcheckableType.test( el.type ) && + el.click && nodeName( el, "input" ) ) { + + leverageNative( el, "click" ); + } + + // Return non-false to allow normal event-path propagation + return true; + }, + + // For cross-browser consistency, suppress native .click() on links + // Also prevent it if we're currently inside a leveraged native-event stack + _default: function( event ) { + var target = event.target; + return rcheckableType.test( target.type ) && + target.click && nodeName( target, "input" ) && + dataPriv.get( target, "click" ) || + nodeName( target, "a" ); + } + }, + + beforeunload: { + postDispatch: function( event ) { + + // Support: Firefox 20+ + // Firefox doesn't alert if the returnValue field is not set. + if ( event.result !== undefined && event.originalEvent ) { + event.originalEvent.returnValue = event.result; + } + } + } + } +}; + +// Ensure the presence of an event listener that handles manually-triggered +// synthetic events by interrupting progress until reinvoked in response to +// *native* events that it fires directly, ensuring that state changes have +// already occurred before other listeners are invoked. +function leverageNative( el, type, expectSync ) { + + // Missing expectSync indicates a trigger call, which must force setup through jQuery.event.add + if ( !expectSync ) { + if ( dataPriv.get( el, type ) === undefined ) { + jQuery.event.add( el, type, returnTrue ); + } + return; + } + + // Register the controller as a special universal handler for all event namespaces + dataPriv.set( el, type, false ); + jQuery.event.add( el, type, { + namespace: false, + handler: function( event ) { + var notAsync, result, + saved = dataPriv.get( this, type ); + + if ( ( event.isTrigger & 1 ) && this[ type ] ) { + + // Interrupt processing of the outer synthetic .trigger()ed event + // Saved data should be false in such cases, but might be a leftover capture object + // from an async native handler (gh-4350) + if ( !saved.length ) { + + // Store arguments for use when handling the inner native event + // There will always be at least one argument (an event object), so this array + // will not be confused with a leftover capture object. + saved = slice.call( arguments ); + dataPriv.set( this, type, saved ); + + // Trigger the native event and capture its result + // Support: IE <=9 - 11+ + // focus() and blur() are asynchronous + notAsync = expectSync( this, type ); + this[ type ](); + result = dataPriv.get( this, type ); + if ( saved !== result || notAsync ) { + dataPriv.set( this, type, false ); + } else { + result = {}; + } + if ( saved !== result ) { + + // Cancel the outer synthetic event + event.stopImmediatePropagation(); + event.preventDefault(); + return result.value; + } + + // If this is an inner synthetic event for an event with a bubbling surrogate + // (focus or blur), assume that the surrogate already propagated from triggering the + // native event and prevent that from happening again here. + // This technically gets the ordering wrong w.r.t. to `.trigger()` (in which the + // bubbling surrogate propagates *after* the non-bubbling base), but that seems + // less bad than duplication. + } else if ( ( jQuery.event.special[ type ] || {} ).delegateType ) { + event.stopPropagation(); + } + + // If this is a native event triggered above, everything is now in order + // Fire an inner synthetic event with the original arguments + } else if ( saved.length ) { + + // ...and capture the result + dataPriv.set( this, type, { + value: jQuery.event.trigger( + + // Support: IE <=9 - 11+ + // Extend with the prototype to reset the above stopImmediatePropagation() + jQuery.extend( saved[ 0 ], jQuery.Event.prototype ), + saved.slice( 1 ), + this + ) + } ); + + // Abort handling of the native event + event.stopImmediatePropagation(); + } + } + } ); +} + +jQuery.removeEvent = function( elem, type, handle ) { + + // This "if" is needed for plain objects + if ( elem.removeEventListener ) { + elem.removeEventListener( type, handle ); + } +}; + +jQuery.Event = function( src, props ) { + + // Allow instantiation without the 'new' keyword + if ( !( this instanceof jQuery.Event ) ) { + return new jQuery.Event( src, props ); + } + + // Event object + if ( src && src.type ) { + this.originalEvent = src; + this.type = src.type; + + // Events bubbling up the document may have been marked as prevented + // by a handler lower down the tree; reflect the correct value. + this.isDefaultPrevented = src.defaultPrevented || + src.defaultPrevented === undefined && + + // Support: Android <=2.3 only + src.returnValue === false ? + returnTrue : + returnFalse; + + // Create target properties + // Support: Safari <=6 - 7 only + // Target should not be a text node (#504, #13143) + this.target = ( src.target && src.target.nodeType === 3 ) ? + src.target.parentNode : + src.target; + + this.currentTarget = src.currentTarget; + this.relatedTarget = src.relatedTarget; + + // Event type + } else { + this.type = src; + } + + // Put explicitly provided properties onto the event object + if ( props ) { + jQuery.extend( this, props ); + } + + // Create a timestamp if incoming event doesn't have one + this.timeStamp = src && src.timeStamp || Date.now(); + + // Mark it as fixed + this[ jQuery.expando ] = true; +}; + +// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding +// https://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html +jQuery.Event.prototype = { + constructor: jQuery.Event, + isDefaultPrevented: returnFalse, + isPropagationStopped: returnFalse, + isImmediatePropagationStopped: returnFalse, + isSimulated: false, + + preventDefault: function() { + var e = this.originalEvent; + + this.isDefaultPrevented = returnTrue; + + if ( e && !this.isSimulated ) { + e.preventDefault(); + } + }, + stopPropagation: function() { + var e = this.originalEvent; + + this.isPropagationStopped = returnTrue; + + if ( e && !this.isSimulated ) { + e.stopPropagation(); + } + }, + stopImmediatePropagation: function() { + var e = this.originalEvent; + + this.isImmediatePropagationStopped = returnTrue; + + if ( e && !this.isSimulated ) { + e.stopImmediatePropagation(); + } + + this.stopPropagation(); + } +}; + +// Includes all common event props including KeyEvent and MouseEvent specific props +jQuery.each( { + altKey: true, + bubbles: true, + cancelable: true, + changedTouches: true, + ctrlKey: true, + detail: true, + eventPhase: true, + metaKey: true, + pageX: true, + pageY: true, + shiftKey: true, + view: true, + "char": true, + code: true, + charCode: true, + key: true, + keyCode: true, + button: true, + buttons: true, + clientX: true, + clientY: true, + offsetX: true, + offsetY: true, + pointerId: true, + pointerType: true, + screenX: true, + screenY: true, + targetTouches: true, + toElement: true, + touches: true, + + which: function( event ) { + var button = event.button; + + // Add which for key events + if ( event.which == null && rkeyEvent.test( event.type ) ) { + return event.charCode != null ? event.charCode : event.keyCode; + } + + // Add which for click: 1 === left; 2 === middle; 3 === right + if ( !event.which && button !== undefined && rmouseEvent.test( event.type ) ) { + if ( button & 1 ) { + return 1; + } + + if ( button & 2 ) { + return 3; + } + + if ( button & 4 ) { + return 2; + } + + return 0; + } + + return event.which; + } +}, jQuery.event.addProp ); + +jQuery.each( { focus: "focusin", blur: "focusout" }, function( type, delegateType ) { + jQuery.event.special[ type ] = { + + // Utilize native event if possible so blur/focus sequence is correct + setup: function() { + + // Claim the first handler + // dataPriv.set( this, "focus", ... ) + // dataPriv.set( this, "blur", ... ) + leverageNative( this, type, expectSync ); + + // Return false to allow normal processing in the caller + return false; + }, + trigger: function() { + + // Force setup before trigger + leverageNative( this, type ); + + // Return non-false to allow normal event-path propagation + return true; + }, + + delegateType: delegateType + }; +} ); + +// Create mouseenter/leave events using mouseover/out and event-time checks +// so that event delegation works in jQuery. +// Do the same for pointerenter/pointerleave and pointerover/pointerout +// +// Support: Safari 7 only +// Safari sends mouseenter too often; see: +// https://bugs.chromium.org/p/chromium/issues/detail?id=470258 +// for the description of the bug (it existed in older Chrome versions as well). +jQuery.each( { + mouseenter: "mouseover", + mouseleave: "mouseout", + pointerenter: "pointerover", + pointerleave: "pointerout" +}, function( orig, fix ) { + jQuery.event.special[ orig ] = { + delegateType: fix, + bindType: fix, + + handle: function( event ) { + var ret, + target = this, + related = event.relatedTarget, + handleObj = event.handleObj; + + // For mouseenter/leave call the handler if related is outside the target. + // NB: No relatedTarget if the mouse left/entered the browser window + if ( !related || ( related !== target && !jQuery.contains( target, related ) ) ) { + event.type = handleObj.origType; + ret = handleObj.handler.apply( this, arguments ); + event.type = fix; + } + return ret; + } + }; +} ); + +jQuery.fn.extend( { + + on: function( types, selector, data, fn ) { + return on( this, types, selector, data, fn ); + }, + one: function( types, selector, data, fn ) { + return on( this, types, selector, data, fn, 1 ); + }, + off: function( types, selector, fn ) { + var handleObj, type; + if ( types && types.preventDefault && types.handleObj ) { + + // ( event ) dispatched jQuery.Event + handleObj = types.handleObj; + jQuery( types.delegateTarget ).off( + handleObj.namespace ? + handleObj.origType + "." + handleObj.namespace : + handleObj.origType, + handleObj.selector, + handleObj.handler + ); + return this; + } + if ( typeof types === "object" ) { + + // ( types-object [, selector] ) + for ( type in types ) { + this.off( type, selector, types[ type ] ); + } + return this; + } + if ( selector === false || typeof selector === "function" ) { + + // ( types [, fn] ) + fn = selector; + selector = undefined; + } + if ( fn === false ) { + fn = returnFalse; + } + return this.each( function() { + jQuery.event.remove( this, types, fn, selector ); + } ); + } +} ); + + +var + + // Support: IE <=10 - 11, Edge 12 - 13 only + // In IE/Edge using regex groups here causes severe slowdowns. + // See https://connect.microsoft.com/IE/feedback/details/1736512/ + rnoInnerhtml = /\s*$/g; + +// Prefer a tbody over its parent table for containing new rows +function manipulationTarget( elem, content ) { + if ( nodeName( elem, "table" ) && + nodeName( content.nodeType !== 11 ? content : content.firstChild, "tr" ) ) { + + return jQuery( elem ).children( "tbody" )[ 0 ] || elem; + } + + return elem; +} + +// Replace/restore the type attribute of script elements for safe DOM manipulation +function disableScript( elem ) { + elem.type = ( elem.getAttribute( "type" ) !== null ) + "/" + elem.type; + return elem; +} +function restoreScript( elem ) { + if ( ( elem.type || "" ).slice( 0, 5 ) === "true/" ) { + elem.type = elem.type.slice( 5 ); + } else { + elem.removeAttribute( "type" ); + } + + return elem; +} + +function cloneCopyEvent( src, dest ) { + var i, l, type, pdataOld, udataOld, udataCur, events; + + if ( dest.nodeType !== 1 ) { + return; + } + + // 1. Copy private data: events, handlers, etc. + if ( dataPriv.hasData( src ) ) { + pdataOld = dataPriv.get( src ); + events = pdataOld.events; + + if ( events ) { + dataPriv.remove( dest, "handle events" ); + + for ( type in events ) { + for ( i = 0, l = events[ type ].length; i < l; i++ ) { + jQuery.event.add( dest, type, events[ type ][ i ] ); + } + } + } + } + + // 2. Copy user data + if ( dataUser.hasData( src ) ) { + udataOld = dataUser.access( src ); + udataCur = jQuery.extend( {}, udataOld ); + + dataUser.set( dest, udataCur ); + } +} + +// Fix IE bugs, see support tests +function fixInput( src, dest ) { + var nodeName = dest.nodeName.toLowerCase(); + + // Fails to persist the checked state of a cloned checkbox or radio button. + if ( nodeName === "input" && rcheckableType.test( src.type ) ) { + dest.checked = src.checked; + + // Fails to return the selected option to the default selected state when cloning options + } else if ( nodeName === "input" || nodeName === "textarea" ) { + dest.defaultValue = src.defaultValue; + } +} + +function domManip( collection, args, callback, ignored ) { + + // Flatten any nested arrays + args = flat( args ); + + var fragment, first, scripts, hasScripts, node, doc, + i = 0, + l = collection.length, + iNoClone = l - 1, + value = args[ 0 ], + valueIsFunction = isFunction( value ); + + // We can't cloneNode fragments that contain checked, in WebKit + if ( valueIsFunction || + ( l > 1 && typeof value === "string" && + !support.checkClone && rchecked.test( value ) ) ) { + return collection.each( function( index ) { + var self = collection.eq( index ); + if ( valueIsFunction ) { + args[ 0 ] = value.call( this, index, self.html() ); + } + domManip( self, args, callback, ignored ); + } ); + } + + if ( l ) { + fragment = buildFragment( args, collection[ 0 ].ownerDocument, false, collection, ignored ); + first = fragment.firstChild; + + if ( fragment.childNodes.length === 1 ) { + fragment = first; + } + + // Require either new content or an interest in ignored elements to invoke the callback + if ( first || ignored ) { + scripts = jQuery.map( getAll( fragment, "script" ), disableScript ); + hasScripts = scripts.length; + + // Use the original fragment for the last item + // instead of the first because it can end up + // being emptied incorrectly in certain situations (#8070). + for ( ; i < l; i++ ) { + node = fragment; + + if ( i !== iNoClone ) { + node = jQuery.clone( node, true, true ); + + // Keep references to cloned scripts for later restoration + if ( hasScripts ) { + + // Support: Android <=4.0 only, PhantomJS 1 only + // push.apply(_, arraylike) throws on ancient WebKit + jQuery.merge( scripts, getAll( node, "script" ) ); + } + } + + callback.call( collection[ i ], node, i ); + } + + if ( hasScripts ) { + doc = scripts[ scripts.length - 1 ].ownerDocument; + + // Reenable scripts + jQuery.map( scripts, restoreScript ); + + // Evaluate executable scripts on first document insertion + for ( i = 0; i < hasScripts; i++ ) { + node = scripts[ i ]; + if ( rscriptType.test( node.type || "" ) && + !dataPriv.access( node, "globalEval" ) && + jQuery.contains( doc, node ) ) { + + if ( node.src && ( node.type || "" ).toLowerCase() !== "module" ) { + + // Optional AJAX dependency, but won't run scripts if not present + if ( jQuery._evalUrl && !node.noModule ) { + jQuery._evalUrl( node.src, { + nonce: node.nonce || node.getAttribute( "nonce" ) + }, doc ); + } + } else { + DOMEval( node.textContent.replace( rcleanScript, "" ), node, doc ); + } + } + } + } + } + } + + return collection; +} + +function remove( elem, selector, keepData ) { + var node, + nodes = selector ? jQuery.filter( selector, elem ) : elem, + i = 0; + + for ( ; ( node = nodes[ i ] ) != null; i++ ) { + if ( !keepData && node.nodeType === 1 ) { + jQuery.cleanData( getAll( node ) ); + } + + if ( node.parentNode ) { + if ( keepData && isAttached( node ) ) { + setGlobalEval( getAll( node, "script" ) ); + } + node.parentNode.removeChild( node ); + } + } + + return elem; +} + +jQuery.extend( { + htmlPrefilter: function( html ) { + return html; + }, + + clone: function( elem, dataAndEvents, deepDataAndEvents ) { + var i, l, srcElements, destElements, + clone = elem.cloneNode( true ), + inPage = isAttached( elem ); + + // Fix IE cloning issues + if ( !support.noCloneChecked && ( elem.nodeType === 1 || elem.nodeType === 11 ) && + !jQuery.isXMLDoc( elem ) ) { + + // We eschew Sizzle here for performance reasons: https://jsperf.com/getall-vs-sizzle/2 + destElements = getAll( clone ); + srcElements = getAll( elem ); + + for ( i = 0, l = srcElements.length; i < l; i++ ) { + fixInput( srcElements[ i ], destElements[ i ] ); + } + } + + // Copy the events from the original to the clone + if ( dataAndEvents ) { + if ( deepDataAndEvents ) { + srcElements = srcElements || getAll( elem ); + destElements = destElements || getAll( clone ); + + for ( i = 0, l = srcElements.length; i < l; i++ ) { + cloneCopyEvent( srcElements[ i ], destElements[ i ] ); + } + } else { + cloneCopyEvent( elem, clone ); + } + } + + // Preserve script evaluation history + destElements = getAll( clone, "script" ); + if ( destElements.length > 0 ) { + setGlobalEval( destElements, !inPage && getAll( elem, "script" ) ); + } + + // Return the cloned set + return clone; + }, + + cleanData: function( elems ) { + var data, elem, type, + special = jQuery.event.special, + i = 0; + + for ( ; ( elem = elems[ i ] ) !== undefined; i++ ) { + if ( acceptData( elem ) ) { + if ( ( data = elem[ dataPriv.expando ] ) ) { + if ( data.events ) { + for ( type in data.events ) { + if ( special[ type ] ) { + jQuery.event.remove( elem, type ); + + // This is a shortcut to avoid jQuery.event.remove's overhead + } else { + jQuery.removeEvent( elem, type, data.handle ); + } + } + } + + // Support: Chrome <=35 - 45+ + // Assign undefined instead of using delete, see Data#remove + elem[ dataPriv.expando ] = undefined; + } + if ( elem[ dataUser.expando ] ) { + + // Support: Chrome <=35 - 45+ + // Assign undefined instead of using delete, see Data#remove + elem[ dataUser.expando ] = undefined; + } + } + } + } +} ); + +jQuery.fn.extend( { + detach: function( selector ) { + return remove( this, selector, true ); + }, + + remove: function( selector ) { + return remove( this, selector ); + }, + + text: function( value ) { + return access( this, function( value ) { + return value === undefined ? + jQuery.text( this ) : + this.empty().each( function() { + if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { + this.textContent = value; + } + } ); + }, null, value, arguments.length ); + }, + + append: function() { + return domManip( this, arguments, function( elem ) { + if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { + var target = manipulationTarget( this, elem ); + target.appendChild( elem ); + } + } ); + }, + + prepend: function() { + return domManip( this, arguments, function( elem ) { + if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { + var target = manipulationTarget( this, elem ); + target.insertBefore( elem, target.firstChild ); + } + } ); + }, + + before: function() { + return domManip( this, arguments, function( elem ) { + if ( this.parentNode ) { + this.parentNode.insertBefore( elem, this ); + } + } ); + }, + + after: function() { + return domManip( this, arguments, function( elem ) { + if ( this.parentNode ) { + this.parentNode.insertBefore( elem, this.nextSibling ); + } + } ); + }, + + empty: function() { + var elem, + i = 0; + + for ( ; ( elem = this[ i ] ) != null; i++ ) { + if ( elem.nodeType === 1 ) { + + // Prevent memory leaks + jQuery.cleanData( getAll( elem, false ) ); + + // Remove any remaining nodes + elem.textContent = ""; + } + } + + return this; + }, + + clone: function( dataAndEvents, deepDataAndEvents ) { + dataAndEvents = dataAndEvents == null ? false : dataAndEvents; + deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents; + + return this.map( function() { + return jQuery.clone( this, dataAndEvents, deepDataAndEvents ); + } ); + }, + + html: function( value ) { + return access( this, function( value ) { + var elem = this[ 0 ] || {}, + i = 0, + l = this.length; + + if ( value === undefined && elem.nodeType === 1 ) { + return elem.innerHTML; + } + + // See if we can take a shortcut and just use innerHTML + if ( typeof value === "string" && !rnoInnerhtml.test( value ) && + !wrapMap[ ( rtagName.exec( value ) || [ "", "" ] )[ 1 ].toLowerCase() ] ) { + + value = jQuery.htmlPrefilter( value ); + + try { + for ( ; i < l; i++ ) { + elem = this[ i ] || {}; + + // Remove element nodes and prevent memory leaks + if ( elem.nodeType === 1 ) { + jQuery.cleanData( getAll( elem, false ) ); + elem.innerHTML = value; + } + } + + elem = 0; + + // If using innerHTML throws an exception, use the fallback method + } catch ( e ) {} + } + + if ( elem ) { + this.empty().append( value ); + } + }, null, value, arguments.length ); + }, + + replaceWith: function() { + var ignored = []; + + // Make the changes, replacing each non-ignored context element with the new content + return domManip( this, arguments, function( elem ) { + var parent = this.parentNode; + + if ( jQuery.inArray( this, ignored ) < 0 ) { + jQuery.cleanData( getAll( this ) ); + if ( parent ) { + parent.replaceChild( elem, this ); + } + } + + // Force callback invocation + }, ignored ); + } +} ); + +jQuery.each( { + appendTo: "append", + prependTo: "prepend", + insertBefore: "before", + insertAfter: "after", + replaceAll: "replaceWith" +}, function( name, original ) { + jQuery.fn[ name ] = function( selector ) { + var elems, + ret = [], + insert = jQuery( selector ), + last = insert.length - 1, + i = 0; + + for ( ; i <= last; i++ ) { + elems = i === last ? this : this.clone( true ); + jQuery( insert[ i ] )[ original ]( elems ); + + // Support: Android <=4.0 only, PhantomJS 1 only + // .get() because push.apply(_, arraylike) throws on ancient WebKit + push.apply( ret, elems.get() ); + } + + return this.pushStack( ret ); + }; +} ); +var rnumnonpx = new RegExp( "^(" + pnum + ")(?!px)[a-z%]+$", "i" ); + +var getStyles = function( elem ) { + + // Support: IE <=11 only, Firefox <=30 (#15098, #14150) + // IE throws on elements created in popups + // FF meanwhile throws on frame elements through "defaultView.getComputedStyle" + var view = elem.ownerDocument.defaultView; + + if ( !view || !view.opener ) { + view = window; + } + + return view.getComputedStyle( elem ); + }; + +var swap = function( elem, options, callback ) { + var ret, name, + old = {}; + + // Remember the old values, and insert the new ones + for ( name in options ) { + old[ name ] = elem.style[ name ]; + elem.style[ name ] = options[ name ]; + } + + ret = callback.call( elem ); + + // Revert the old values + for ( name in options ) { + elem.style[ name ] = old[ name ]; + } + + return ret; +}; + + +var rboxStyle = new RegExp( cssExpand.join( "|" ), "i" ); + + + +( function() { + + // Executing both pixelPosition & boxSizingReliable tests require only one layout + // so they're executed at the same time to save the second computation. + function computeStyleTests() { + + // This is a singleton, we need to execute it only once + if ( !div ) { + return; + } + + container.style.cssText = "position:absolute;left:-11111px;width:60px;" + + "margin-top:1px;padding:0;border:0"; + div.style.cssText = + "position:relative;display:block;box-sizing:border-box;overflow:scroll;" + + "margin:auto;border:1px;padding:1px;" + + "width:60%;top:1%"; + documentElement.appendChild( container ).appendChild( div ); + + var divStyle = window.getComputedStyle( div ); + pixelPositionVal = divStyle.top !== "1%"; + + // Support: Android 4.0 - 4.3 only, Firefox <=3 - 44 + reliableMarginLeftVal = roundPixelMeasures( divStyle.marginLeft ) === 12; + + // Support: Android 4.0 - 4.3 only, Safari <=9.1 - 10.1, iOS <=7.0 - 9.3 + // Some styles come back with percentage values, even though they shouldn't + div.style.right = "60%"; + pixelBoxStylesVal = roundPixelMeasures( divStyle.right ) === 36; + + // Support: IE 9 - 11 only + // Detect misreporting of content dimensions for box-sizing:border-box elements + boxSizingReliableVal = roundPixelMeasures( divStyle.width ) === 36; + + // Support: IE 9 only + // Detect overflow:scroll screwiness (gh-3699) + // Support: Chrome <=64 + // Don't get tricked when zoom affects offsetWidth (gh-4029) + div.style.position = "absolute"; + scrollboxSizeVal = roundPixelMeasures( div.offsetWidth / 3 ) === 12; + + documentElement.removeChild( container ); + + // Nullify the div so it wouldn't be stored in the memory and + // it will also be a sign that checks already performed + div = null; + } + + function roundPixelMeasures( measure ) { + return Math.round( parseFloat( measure ) ); + } + + var pixelPositionVal, boxSizingReliableVal, scrollboxSizeVal, pixelBoxStylesVal, + reliableTrDimensionsVal, reliableMarginLeftVal, + container = document.createElement( "div" ), + div = document.createElement( "div" ); + + // Finish early in limited (non-browser) environments + if ( !div.style ) { + return; + } + + // Support: IE <=9 - 11 only + // Style of cloned element affects source element cloned (#8908) + div.style.backgroundClip = "content-box"; + div.cloneNode( true ).style.backgroundClip = ""; + support.clearCloneStyle = div.style.backgroundClip === "content-box"; + + jQuery.extend( support, { + boxSizingReliable: function() { + computeStyleTests(); + return boxSizingReliableVal; + }, + pixelBoxStyles: function() { + computeStyleTests(); + return pixelBoxStylesVal; + }, + pixelPosition: function() { + computeStyleTests(); + return pixelPositionVal; + }, + reliableMarginLeft: function() { + computeStyleTests(); + return reliableMarginLeftVal; + }, + scrollboxSize: function() { + computeStyleTests(); + return scrollboxSizeVal; + }, + + // Support: IE 9 - 11+, Edge 15 - 18+ + // IE/Edge misreport `getComputedStyle` of table rows with width/height + // set in CSS while `offset*` properties report correct values. + // Behavior in IE 9 is more subtle than in newer versions & it passes + // some versions of this test; make sure not to make it pass there! + reliableTrDimensions: function() { + var table, tr, trChild, trStyle; + if ( reliableTrDimensionsVal == null ) { + table = document.createElement( "table" ); + tr = document.createElement( "tr" ); + trChild = document.createElement( "div" ); + + table.style.cssText = "position:absolute;left:-11111px"; + tr.style.height = "1px"; + trChild.style.height = "9px"; + + documentElement + .appendChild( table ) + .appendChild( tr ) + .appendChild( trChild ); + + trStyle = window.getComputedStyle( tr ); + reliableTrDimensionsVal = parseInt( trStyle.height ) > 3; + + documentElement.removeChild( table ); + } + return reliableTrDimensionsVal; + } + } ); +} )(); + + +function curCSS( elem, name, computed ) { + var width, minWidth, maxWidth, ret, + + // Support: Firefox 51+ + // Retrieving style before computed somehow + // fixes an issue with getting wrong values + // on detached elements + style = elem.style; + + computed = computed || getStyles( elem ); + + // getPropertyValue is needed for: + // .css('filter') (IE 9 only, #12537) + // .css('--customProperty) (#3144) + if ( computed ) { + ret = computed.getPropertyValue( name ) || computed[ name ]; + + if ( ret === "" && !isAttached( elem ) ) { + ret = jQuery.style( elem, name ); + } + + // A tribute to the "awesome hack by Dean Edwards" + // Android Browser returns percentage for some values, + // but width seems to be reliably pixels. + // This is against the CSSOM draft spec: + // https://drafts.csswg.org/cssom/#resolved-values + if ( !support.pixelBoxStyles() && rnumnonpx.test( ret ) && rboxStyle.test( name ) ) { + + // Remember the original values + width = style.width; + minWidth = style.minWidth; + maxWidth = style.maxWidth; + + // Put in the new values to get a computed value out + style.minWidth = style.maxWidth = style.width = ret; + ret = computed.width; + + // Revert the changed values + style.width = width; + style.minWidth = minWidth; + style.maxWidth = maxWidth; + } + } + + return ret !== undefined ? + + // Support: IE <=9 - 11 only + // IE returns zIndex value as an integer. + ret + "" : + ret; +} + + +function addGetHookIf( conditionFn, hookFn ) { + + // Define the hook, we'll check on the first run if it's really needed. + return { + get: function() { + if ( conditionFn() ) { + + // Hook not needed (or it's not possible to use it due + // to missing dependency), remove it. + delete this.get; + return; + } + + // Hook needed; redefine it so that the support test is not executed again. + return ( this.get = hookFn ).apply( this, arguments ); + } + }; +} + + +var cssPrefixes = [ "Webkit", "Moz", "ms" ], + emptyStyle = document.createElement( "div" ).style, + vendorProps = {}; + +// Return a vendor-prefixed property or undefined +function vendorPropName( name ) { + + // Check for vendor prefixed names + var capName = name[ 0 ].toUpperCase() + name.slice( 1 ), + i = cssPrefixes.length; + + while ( i-- ) { + name = cssPrefixes[ i ] + capName; + if ( name in emptyStyle ) { + return name; + } + } +} + +// Return a potentially-mapped jQuery.cssProps or vendor prefixed property +function finalPropName( name ) { + var final = jQuery.cssProps[ name ] || vendorProps[ name ]; + + if ( final ) { + return final; + } + if ( name in emptyStyle ) { + return name; + } + return vendorProps[ name ] = vendorPropName( name ) || name; +} + + +var + + // Swappable if display is none or starts with table + // except "table", "table-cell", or "table-caption" + // See here for display values: https://developer.mozilla.org/en-US/docs/CSS/display + rdisplayswap = /^(none|table(?!-c[ea]).+)/, + rcustomProp = /^--/, + cssShow = { position: "absolute", visibility: "hidden", display: "block" }, + cssNormalTransform = { + letterSpacing: "0", + fontWeight: "400" + }; + +function setPositiveNumber( _elem, value, subtract ) { + + // Any relative (+/-) values have already been + // normalized at this point + var matches = rcssNum.exec( value ); + return matches ? + + // Guard against undefined "subtract", e.g., when used as in cssHooks + Math.max( 0, matches[ 2 ] - ( subtract || 0 ) ) + ( matches[ 3 ] || "px" ) : + value; +} + +function boxModelAdjustment( elem, dimension, box, isBorderBox, styles, computedVal ) { + var i = dimension === "width" ? 1 : 0, + extra = 0, + delta = 0; + + // Adjustment may not be necessary + if ( box === ( isBorderBox ? "border" : "content" ) ) { + return 0; + } + + for ( ; i < 4; i += 2 ) { + + // Both box models exclude margin + if ( box === "margin" ) { + delta += jQuery.css( elem, box + cssExpand[ i ], true, styles ); + } + + // If we get here with a content-box, we're seeking "padding" or "border" or "margin" + if ( !isBorderBox ) { + + // Add padding + delta += jQuery.css( elem, "padding" + cssExpand[ i ], true, styles ); + + // For "border" or "margin", add border + if ( box !== "padding" ) { + delta += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); + + // But still keep track of it otherwise + } else { + extra += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); + } + + // If we get here with a border-box (content + padding + border), we're seeking "content" or + // "padding" or "margin" + } else { + + // For "content", subtract padding + if ( box === "content" ) { + delta -= jQuery.css( elem, "padding" + cssExpand[ i ], true, styles ); + } + + // For "content" or "padding", subtract border + if ( box !== "margin" ) { + delta -= jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); + } + } + } + + // Account for positive content-box scroll gutter when requested by providing computedVal + if ( !isBorderBox && computedVal >= 0 ) { + + // offsetWidth/offsetHeight is a rounded sum of content, padding, scroll gutter, and border + // Assuming integer scroll gutter, subtract the rest and round down + delta += Math.max( 0, Math.ceil( + elem[ "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ) ] - + computedVal - + delta - + extra - + 0.5 + + // If offsetWidth/offsetHeight is unknown, then we can't determine content-box scroll gutter + // Use an explicit zero to avoid NaN (gh-3964) + ) ) || 0; + } + + return delta; +} + +function getWidthOrHeight( elem, dimension, extra ) { + + // Start with computed style + var styles = getStyles( elem ), + + // To avoid forcing a reflow, only fetch boxSizing if we need it (gh-4322). + // Fake content-box until we know it's needed to know the true value. + boxSizingNeeded = !support.boxSizingReliable() || extra, + isBorderBox = boxSizingNeeded && + jQuery.css( elem, "boxSizing", false, styles ) === "border-box", + valueIsBorderBox = isBorderBox, + + val = curCSS( elem, dimension, styles ), + offsetProp = "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ); + + // Support: Firefox <=54 + // Return a confounding non-pixel value or feign ignorance, as appropriate. + if ( rnumnonpx.test( val ) ) { + if ( !extra ) { + return val; + } + val = "auto"; + } + + + // Support: IE 9 - 11 only + // Use offsetWidth/offsetHeight for when box sizing is unreliable. + // In those cases, the computed value can be trusted to be border-box. + if ( ( !support.boxSizingReliable() && isBorderBox || + + // Support: IE 10 - 11+, Edge 15 - 18+ + // IE/Edge misreport `getComputedStyle` of table rows with width/height + // set in CSS while `offset*` properties report correct values. + // Interestingly, in some cases IE 9 doesn't suffer from this issue. + !support.reliableTrDimensions() && nodeName( elem, "tr" ) || + + // Fall back to offsetWidth/offsetHeight when value is "auto" + // This happens for inline elements with no explicit setting (gh-3571) + val === "auto" || + + // Support: Android <=4.1 - 4.3 only + // Also use offsetWidth/offsetHeight for misreported inline dimensions (gh-3602) + !parseFloat( val ) && jQuery.css( elem, "display", false, styles ) === "inline" ) && + + // Make sure the element is visible & connected + elem.getClientRects().length ) { + + isBorderBox = jQuery.css( elem, "boxSizing", false, styles ) === "border-box"; + + // Where available, offsetWidth/offsetHeight approximate border box dimensions. + // Where not available (e.g., SVG), assume unreliable box-sizing and interpret the + // retrieved value as a content box dimension. + valueIsBorderBox = offsetProp in elem; + if ( valueIsBorderBox ) { + val = elem[ offsetProp ]; + } + } + + // Normalize "" and auto + val = parseFloat( val ) || 0; + + // Adjust for the element's box model + return ( val + + boxModelAdjustment( + elem, + dimension, + extra || ( isBorderBox ? "border" : "content" ), + valueIsBorderBox, + styles, + + // Provide the current computed size to request scroll gutter calculation (gh-3589) + val + ) + ) + "px"; +} + +jQuery.extend( { + + // Add in style property hooks for overriding the default + // behavior of getting and setting a style property + cssHooks: { + opacity: { + get: function( elem, computed ) { + if ( computed ) { + + // We should always get a number back from opacity + var ret = curCSS( elem, "opacity" ); + return ret === "" ? "1" : ret; + } + } + } + }, + + // Don't automatically add "px" to these possibly-unitless properties + cssNumber: { + "animationIterationCount": true, + "columnCount": true, + "fillOpacity": true, + "flexGrow": true, + "flexShrink": true, + "fontWeight": true, + "gridArea": true, + "gridColumn": true, + "gridColumnEnd": true, + "gridColumnStart": true, + "gridRow": true, + "gridRowEnd": true, + "gridRowStart": true, + "lineHeight": true, + "opacity": true, + "order": true, + "orphans": true, + "widows": true, + "zIndex": true, + "zoom": true + }, + + // Add in properties whose names you wish to fix before + // setting or getting the value + cssProps: {}, + + // Get and set the style property on a DOM Node + style: function( elem, name, value, extra ) { + + // Don't set styles on text and comment nodes + if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) { + return; + } + + // Make sure that we're working with the right name + var ret, type, hooks, + origName = camelCase( name ), + isCustomProp = rcustomProp.test( name ), + style = elem.style; + + // Make sure that we're working with the right name. We don't + // want to query the value if it is a CSS custom property + // since they are user-defined. + if ( !isCustomProp ) { + name = finalPropName( origName ); + } + + // Gets hook for the prefixed version, then unprefixed version + hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ]; + + // Check if we're setting a value + if ( value !== undefined ) { + type = typeof value; + + // Convert "+=" or "-=" to relative numbers (#7345) + if ( type === "string" && ( ret = rcssNum.exec( value ) ) && ret[ 1 ] ) { + value = adjustCSS( elem, name, ret ); + + // Fixes bug #9237 + type = "number"; + } + + // Make sure that null and NaN values aren't set (#7116) + if ( value == null || value !== value ) { + return; + } + + // If a number was passed in, add the unit (except for certain CSS properties) + // The isCustomProp check can be removed in jQuery 4.0 when we only auto-append + // "px" to a few hardcoded values. + if ( type === "number" && !isCustomProp ) { + value += ret && ret[ 3 ] || ( jQuery.cssNumber[ origName ] ? "" : "px" ); + } + + // background-* props affect original clone's values + if ( !support.clearCloneStyle && value === "" && name.indexOf( "background" ) === 0 ) { + style[ name ] = "inherit"; + } + + // If a hook was provided, use that value, otherwise just set the specified value + if ( !hooks || !( "set" in hooks ) || + ( value = hooks.set( elem, value, extra ) ) !== undefined ) { + + if ( isCustomProp ) { + style.setProperty( name, value ); + } else { + style[ name ] = value; + } + } + + } else { + + // If a hook was provided get the non-computed value from there + if ( hooks && "get" in hooks && + ( ret = hooks.get( elem, false, extra ) ) !== undefined ) { + + return ret; + } + + // Otherwise just get the value from the style object + return style[ name ]; + } + }, + + css: function( elem, name, extra, styles ) { + var val, num, hooks, + origName = camelCase( name ), + isCustomProp = rcustomProp.test( name ); + + // Make sure that we're working with the right name. We don't + // want to modify the value if it is a CSS custom property + // since they are user-defined. + if ( !isCustomProp ) { + name = finalPropName( origName ); + } + + // Try prefixed name followed by the unprefixed name + hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ]; + + // If a hook was provided get the computed value from there + if ( hooks && "get" in hooks ) { + val = hooks.get( elem, true, extra ); + } + + // Otherwise, if a way to get the computed value exists, use that + if ( val === undefined ) { + val = curCSS( elem, name, styles ); + } + + // Convert "normal" to computed value + if ( val === "normal" && name in cssNormalTransform ) { + val = cssNormalTransform[ name ]; + } + + // Make numeric if forced or a qualifier was provided and val looks numeric + if ( extra === "" || extra ) { + num = parseFloat( val ); + return extra === true || isFinite( num ) ? num || 0 : val; + } + + return val; + } +} ); + +jQuery.each( [ "height", "width" ], function( _i, dimension ) { + jQuery.cssHooks[ dimension ] = { + get: function( elem, computed, extra ) { + if ( computed ) { + + // Certain elements can have dimension info if we invisibly show them + // but it must have a current display style that would benefit + return rdisplayswap.test( jQuery.css( elem, "display" ) ) && + + // Support: Safari 8+ + // Table columns in Safari have non-zero offsetWidth & zero + // getBoundingClientRect().width unless display is changed. + // Support: IE <=11 only + // Running getBoundingClientRect on a disconnected node + // in IE throws an error. + ( !elem.getClientRects().length || !elem.getBoundingClientRect().width ) ? + swap( elem, cssShow, function() { + return getWidthOrHeight( elem, dimension, extra ); + } ) : + getWidthOrHeight( elem, dimension, extra ); + } + }, + + set: function( elem, value, extra ) { + var matches, + styles = getStyles( elem ), + + // Only read styles.position if the test has a chance to fail + // to avoid forcing a reflow. + scrollboxSizeBuggy = !support.scrollboxSize() && + styles.position === "absolute", + + // To avoid forcing a reflow, only fetch boxSizing if we need it (gh-3991) + boxSizingNeeded = scrollboxSizeBuggy || extra, + isBorderBox = boxSizingNeeded && + jQuery.css( elem, "boxSizing", false, styles ) === "border-box", + subtract = extra ? + boxModelAdjustment( + elem, + dimension, + extra, + isBorderBox, + styles + ) : + 0; + + // Account for unreliable border-box dimensions by comparing offset* to computed and + // faking a content-box to get border and padding (gh-3699) + if ( isBorderBox && scrollboxSizeBuggy ) { + subtract -= Math.ceil( + elem[ "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ) ] - + parseFloat( styles[ dimension ] ) - + boxModelAdjustment( elem, dimension, "border", false, styles ) - + 0.5 + ); + } + + // Convert to pixels if value adjustment is needed + if ( subtract && ( matches = rcssNum.exec( value ) ) && + ( matches[ 3 ] || "px" ) !== "px" ) { + + elem.style[ dimension ] = value; + value = jQuery.css( elem, dimension ); + } + + return setPositiveNumber( elem, value, subtract ); + } + }; +} ); + +jQuery.cssHooks.marginLeft = addGetHookIf( support.reliableMarginLeft, + function( elem, computed ) { + if ( computed ) { + return ( parseFloat( curCSS( elem, "marginLeft" ) ) || + elem.getBoundingClientRect().left - + swap( elem, { marginLeft: 0 }, function() { + return elem.getBoundingClientRect().left; + } ) + ) + "px"; + } + } +); + +// These hooks are used by animate to expand properties +jQuery.each( { + margin: "", + padding: "", + border: "Width" +}, function( prefix, suffix ) { + jQuery.cssHooks[ prefix + suffix ] = { + expand: function( value ) { + var i = 0, + expanded = {}, + + // Assumes a single number if not a string + parts = typeof value === "string" ? value.split( " " ) : [ value ]; + + for ( ; i < 4; i++ ) { + expanded[ prefix + cssExpand[ i ] + suffix ] = + parts[ i ] || parts[ i - 2 ] || parts[ 0 ]; + } + + return expanded; + } + }; + + if ( prefix !== "margin" ) { + jQuery.cssHooks[ prefix + suffix ].set = setPositiveNumber; + } +} ); + +jQuery.fn.extend( { + css: function( name, value ) { + return access( this, function( elem, name, value ) { + var styles, len, + map = {}, + i = 0; + + if ( Array.isArray( name ) ) { + styles = getStyles( elem ); + len = name.length; + + for ( ; i < len; i++ ) { + map[ name[ i ] ] = jQuery.css( elem, name[ i ], false, styles ); + } + + return map; + } + + return value !== undefined ? + jQuery.style( elem, name, value ) : + jQuery.css( elem, name ); + }, name, value, arguments.length > 1 ); + } +} ); + + +function Tween( elem, options, prop, end, easing ) { + return new Tween.prototype.init( elem, options, prop, end, easing ); +} +jQuery.Tween = Tween; + +Tween.prototype = { + constructor: Tween, + init: function( elem, options, prop, end, easing, unit ) { + this.elem = elem; + this.prop = prop; + this.easing = easing || jQuery.easing._default; + this.options = options; + this.start = this.now = this.cur(); + this.end = end; + this.unit = unit || ( jQuery.cssNumber[ prop ] ? "" : "px" ); + }, + cur: function() { + var hooks = Tween.propHooks[ this.prop ]; + + return hooks && hooks.get ? + hooks.get( this ) : + Tween.propHooks._default.get( this ); + }, + run: function( percent ) { + var eased, + hooks = Tween.propHooks[ this.prop ]; + + if ( this.options.duration ) { + this.pos = eased = jQuery.easing[ this.easing ]( + percent, this.options.duration * percent, 0, 1, this.options.duration + ); + } else { + this.pos = eased = percent; + } + this.now = ( this.end - this.start ) * eased + this.start; + + if ( this.options.step ) { + this.options.step.call( this.elem, this.now, this ); + } + + if ( hooks && hooks.set ) { + hooks.set( this ); + } else { + Tween.propHooks._default.set( this ); + } + return this; + } +}; + +Tween.prototype.init.prototype = Tween.prototype; + +Tween.propHooks = { + _default: { + get: function( tween ) { + var result; + + // Use a property on the element directly when it is not a DOM element, + // or when there is no matching style property that exists. + if ( tween.elem.nodeType !== 1 || + tween.elem[ tween.prop ] != null && tween.elem.style[ tween.prop ] == null ) { + return tween.elem[ tween.prop ]; + } + + // Passing an empty string as a 3rd parameter to .css will automatically + // attempt a parseFloat and fallback to a string if the parse fails. + // Simple values such as "10px" are parsed to Float; + // complex values such as "rotate(1rad)" are returned as-is. + result = jQuery.css( tween.elem, tween.prop, "" ); + + // Empty strings, null, undefined and "auto" are converted to 0. + return !result || result === "auto" ? 0 : result; + }, + set: function( tween ) { + + // Use step hook for back compat. + // Use cssHook if its there. + // Use .style if available and use plain properties where available. + if ( jQuery.fx.step[ tween.prop ] ) { + jQuery.fx.step[ tween.prop ]( tween ); + } else if ( tween.elem.nodeType === 1 && ( + jQuery.cssHooks[ tween.prop ] || + tween.elem.style[ finalPropName( tween.prop ) ] != null ) ) { + jQuery.style( tween.elem, tween.prop, tween.now + tween.unit ); + } else { + tween.elem[ tween.prop ] = tween.now; + } + } + } +}; + +// Support: IE <=9 only +// Panic based approach to setting things on disconnected nodes +Tween.propHooks.scrollTop = Tween.propHooks.scrollLeft = { + set: function( tween ) { + if ( tween.elem.nodeType && tween.elem.parentNode ) { + tween.elem[ tween.prop ] = tween.now; + } + } +}; + +jQuery.easing = { + linear: function( p ) { + return p; + }, + swing: function( p ) { + return 0.5 - Math.cos( p * Math.PI ) / 2; + }, + _default: "swing" +}; + +jQuery.fx = Tween.prototype.init; + +// Back compat <1.8 extension point +jQuery.fx.step = {}; + + + + +var + fxNow, inProgress, + rfxtypes = /^(?:toggle|show|hide)$/, + rrun = /queueHooks$/; + +function schedule() { + if ( inProgress ) { + if ( document.hidden === false && window.requestAnimationFrame ) { + window.requestAnimationFrame( schedule ); + } else { + window.setTimeout( schedule, jQuery.fx.interval ); + } + + jQuery.fx.tick(); + } +} + +// Animations created synchronously will run synchronously +function createFxNow() { + window.setTimeout( function() { + fxNow = undefined; + } ); + return ( fxNow = Date.now() ); +} + +// Generate parameters to create a standard animation +function genFx( type, includeWidth ) { + var which, + i = 0, + attrs = { height: type }; + + // If we include width, step value is 1 to do all cssExpand values, + // otherwise step value is 2 to skip over Left and Right + includeWidth = includeWidth ? 1 : 0; + for ( ; i < 4; i += 2 - includeWidth ) { + which = cssExpand[ i ]; + attrs[ "margin" + which ] = attrs[ "padding" + which ] = type; + } + + if ( includeWidth ) { + attrs.opacity = attrs.width = type; + } + + return attrs; +} + +function createTween( value, prop, animation ) { + var tween, + collection = ( Animation.tweeners[ prop ] || [] ).concat( Animation.tweeners[ "*" ] ), + index = 0, + length = collection.length; + for ( ; index < length; index++ ) { + if ( ( tween = collection[ index ].call( animation, prop, value ) ) ) { + + // We're done with this property + return tween; + } + } +} + +function defaultPrefilter( elem, props, opts ) { + var prop, value, toggle, hooks, oldfire, propTween, restoreDisplay, display, + isBox = "width" in props || "height" in props, + anim = this, + orig = {}, + style = elem.style, + hidden = elem.nodeType && isHiddenWithinTree( elem ), + dataShow = dataPriv.get( elem, "fxshow" ); + + // Queue-skipping animations hijack the fx hooks + if ( !opts.queue ) { + hooks = jQuery._queueHooks( elem, "fx" ); + if ( hooks.unqueued == null ) { + hooks.unqueued = 0; + oldfire = hooks.empty.fire; + hooks.empty.fire = function() { + if ( !hooks.unqueued ) { + oldfire(); + } + }; + } + hooks.unqueued++; + + anim.always( function() { + + // Ensure the complete handler is called before this completes + anim.always( function() { + hooks.unqueued--; + if ( !jQuery.queue( elem, "fx" ).length ) { + hooks.empty.fire(); + } + } ); + } ); + } + + // Detect show/hide animations + for ( prop in props ) { + value = props[ prop ]; + if ( rfxtypes.test( value ) ) { + delete props[ prop ]; + toggle = toggle || value === "toggle"; + if ( value === ( hidden ? "hide" : "show" ) ) { + + // Pretend to be hidden if this is a "show" and + // there is still data from a stopped show/hide + if ( value === "show" && dataShow && dataShow[ prop ] !== undefined ) { + hidden = true; + + // Ignore all other no-op show/hide data + } else { + continue; + } + } + orig[ prop ] = dataShow && dataShow[ prop ] || jQuery.style( elem, prop ); + } + } + + // Bail out if this is a no-op like .hide().hide() + propTween = !jQuery.isEmptyObject( props ); + if ( !propTween && jQuery.isEmptyObject( orig ) ) { + return; + } + + // Restrict "overflow" and "display" styles during box animations + if ( isBox && elem.nodeType === 1 ) { + + // Support: IE <=9 - 11, Edge 12 - 15 + // Record all 3 overflow attributes because IE does not infer the shorthand + // from identically-valued overflowX and overflowY and Edge just mirrors + // the overflowX value there. + opts.overflow = [ style.overflow, style.overflowX, style.overflowY ]; + + // Identify a display type, preferring old show/hide data over the CSS cascade + restoreDisplay = dataShow && dataShow.display; + if ( restoreDisplay == null ) { + restoreDisplay = dataPriv.get( elem, "display" ); + } + display = jQuery.css( elem, "display" ); + if ( display === "none" ) { + if ( restoreDisplay ) { + display = restoreDisplay; + } else { + + // Get nonempty value(s) by temporarily forcing visibility + showHide( [ elem ], true ); + restoreDisplay = elem.style.display || restoreDisplay; + display = jQuery.css( elem, "display" ); + showHide( [ elem ] ); + } + } + + // Animate inline elements as inline-block + if ( display === "inline" || display === "inline-block" && restoreDisplay != null ) { + if ( jQuery.css( elem, "float" ) === "none" ) { + + // Restore the original display value at the end of pure show/hide animations + if ( !propTween ) { + anim.done( function() { + style.display = restoreDisplay; + } ); + if ( restoreDisplay == null ) { + display = style.display; + restoreDisplay = display === "none" ? "" : display; + } + } + style.display = "inline-block"; + } + } + } + + if ( opts.overflow ) { + style.overflow = "hidden"; + anim.always( function() { + style.overflow = opts.overflow[ 0 ]; + style.overflowX = opts.overflow[ 1 ]; + style.overflowY = opts.overflow[ 2 ]; + } ); + } + + // Implement show/hide animations + propTween = false; + for ( prop in orig ) { + + // General show/hide setup for this element animation + if ( !propTween ) { + if ( dataShow ) { + if ( "hidden" in dataShow ) { + hidden = dataShow.hidden; + } + } else { + dataShow = dataPriv.access( elem, "fxshow", { display: restoreDisplay } ); + } + + // Store hidden/visible for toggle so `.stop().toggle()` "reverses" + if ( toggle ) { + dataShow.hidden = !hidden; + } + + // Show elements before animating them + if ( hidden ) { + showHide( [ elem ], true ); + } + + /* eslint-disable no-loop-func */ + + anim.done( function() { + + /* eslint-enable no-loop-func */ + + // The final step of a "hide" animation is actually hiding the element + if ( !hidden ) { + showHide( [ elem ] ); + } + dataPriv.remove( elem, "fxshow" ); + for ( prop in orig ) { + jQuery.style( elem, prop, orig[ prop ] ); + } + } ); + } + + // Per-property setup + propTween = createTween( hidden ? dataShow[ prop ] : 0, prop, anim ); + if ( !( prop in dataShow ) ) { + dataShow[ prop ] = propTween.start; + if ( hidden ) { + propTween.end = propTween.start; + propTween.start = 0; + } + } + } +} + +function propFilter( props, specialEasing ) { + var index, name, easing, value, hooks; + + // camelCase, specialEasing and expand cssHook pass + for ( index in props ) { + name = camelCase( index ); + easing = specialEasing[ name ]; + value = props[ index ]; + if ( Array.isArray( value ) ) { + easing = value[ 1 ]; + value = props[ index ] = value[ 0 ]; + } + + if ( index !== name ) { + props[ name ] = value; + delete props[ index ]; + } + + hooks = jQuery.cssHooks[ name ]; + if ( hooks && "expand" in hooks ) { + value = hooks.expand( value ); + delete props[ name ]; + + // Not quite $.extend, this won't overwrite existing keys. + // Reusing 'index' because we have the correct "name" + for ( index in value ) { + if ( !( index in props ) ) { + props[ index ] = value[ index ]; + specialEasing[ index ] = easing; + } + } + } else { + specialEasing[ name ] = easing; + } + } +} + +function Animation( elem, properties, options ) { + var result, + stopped, + index = 0, + length = Animation.prefilters.length, + deferred = jQuery.Deferred().always( function() { + + // Don't match elem in the :animated selector + delete tick.elem; + } ), + tick = function() { + if ( stopped ) { + return false; + } + var currentTime = fxNow || createFxNow(), + remaining = Math.max( 0, animation.startTime + animation.duration - currentTime ), + + // Support: Android 2.3 only + // Archaic crash bug won't allow us to use `1 - ( 0.5 || 0 )` (#12497) + temp = remaining / animation.duration || 0, + percent = 1 - temp, + index = 0, + length = animation.tweens.length; + + for ( ; index < length; index++ ) { + animation.tweens[ index ].run( percent ); + } + + deferred.notifyWith( elem, [ animation, percent, remaining ] ); + + // If there's more to do, yield + if ( percent < 1 && length ) { + return remaining; + } + + // If this was an empty animation, synthesize a final progress notification + if ( !length ) { + deferred.notifyWith( elem, [ animation, 1, 0 ] ); + } + + // Resolve the animation and report its conclusion + deferred.resolveWith( elem, [ animation ] ); + return false; + }, + animation = deferred.promise( { + elem: elem, + props: jQuery.extend( {}, properties ), + opts: jQuery.extend( true, { + specialEasing: {}, + easing: jQuery.easing._default + }, options ), + originalProperties: properties, + originalOptions: options, + startTime: fxNow || createFxNow(), + duration: options.duration, + tweens: [], + createTween: function( prop, end ) { + var tween = jQuery.Tween( elem, animation.opts, prop, end, + animation.opts.specialEasing[ prop ] || animation.opts.easing ); + animation.tweens.push( tween ); + return tween; + }, + stop: function( gotoEnd ) { + var index = 0, + + // If we are going to the end, we want to run all the tweens + // otherwise we skip this part + length = gotoEnd ? animation.tweens.length : 0; + if ( stopped ) { + return this; + } + stopped = true; + for ( ; index < length; index++ ) { + animation.tweens[ index ].run( 1 ); + } + + // Resolve when we played the last frame; otherwise, reject + if ( gotoEnd ) { + deferred.notifyWith( elem, [ animation, 1, 0 ] ); + deferred.resolveWith( elem, [ animation, gotoEnd ] ); + } else { + deferred.rejectWith( elem, [ animation, gotoEnd ] ); + } + return this; + } + } ), + props = animation.props; + + propFilter( props, animation.opts.specialEasing ); + + for ( ; index < length; index++ ) { + result = Animation.prefilters[ index ].call( animation, elem, props, animation.opts ); + if ( result ) { + if ( isFunction( result.stop ) ) { + jQuery._queueHooks( animation.elem, animation.opts.queue ).stop = + result.stop.bind( result ); + } + return result; + } + } + + jQuery.map( props, createTween, animation ); + + if ( isFunction( animation.opts.start ) ) { + animation.opts.start.call( elem, animation ); + } + + // Attach callbacks from options + animation + .progress( animation.opts.progress ) + .done( animation.opts.done, animation.opts.complete ) + .fail( animation.opts.fail ) + .always( animation.opts.always ); + + jQuery.fx.timer( + jQuery.extend( tick, { + elem: elem, + anim: animation, + queue: animation.opts.queue + } ) + ); + + return animation; +} + +jQuery.Animation = jQuery.extend( Animation, { + + tweeners: { + "*": [ function( prop, value ) { + var tween = this.createTween( prop, value ); + adjustCSS( tween.elem, prop, rcssNum.exec( value ), tween ); + return tween; + } ] + }, + + tweener: function( props, callback ) { + if ( isFunction( props ) ) { + callback = props; + props = [ "*" ]; + } else { + props = props.match( rnothtmlwhite ); + } + + var prop, + index = 0, + length = props.length; + + for ( ; index < length; index++ ) { + prop = props[ index ]; + Animation.tweeners[ prop ] = Animation.tweeners[ prop ] || []; + Animation.tweeners[ prop ].unshift( callback ); + } + }, + + prefilters: [ defaultPrefilter ], + + prefilter: function( callback, prepend ) { + if ( prepend ) { + Animation.prefilters.unshift( callback ); + } else { + Animation.prefilters.push( callback ); + } + } +} ); + +jQuery.speed = function( speed, easing, fn ) { + var opt = speed && typeof speed === "object" ? jQuery.extend( {}, speed ) : { + complete: fn || !fn && easing || + isFunction( speed ) && speed, + duration: speed, + easing: fn && easing || easing && !isFunction( easing ) && easing + }; + + // Go to the end state if fx are off + if ( jQuery.fx.off ) { + opt.duration = 0; + + } else { + if ( typeof opt.duration !== "number" ) { + if ( opt.duration in jQuery.fx.speeds ) { + opt.duration = jQuery.fx.speeds[ opt.duration ]; + + } else { + opt.duration = jQuery.fx.speeds._default; + } + } + } + + // Normalize opt.queue - true/undefined/null -> "fx" + if ( opt.queue == null || opt.queue === true ) { + opt.queue = "fx"; + } + + // Queueing + opt.old = opt.complete; + + opt.complete = function() { + if ( isFunction( opt.old ) ) { + opt.old.call( this ); + } + + if ( opt.queue ) { + jQuery.dequeue( this, opt.queue ); + } + }; + + return opt; +}; + +jQuery.fn.extend( { + fadeTo: function( speed, to, easing, callback ) { + + // Show any hidden elements after setting opacity to 0 + return this.filter( isHiddenWithinTree ).css( "opacity", 0 ).show() + + // Animate to the value specified + .end().animate( { opacity: to }, speed, easing, callback ); + }, + animate: function( prop, speed, easing, callback ) { + var empty = jQuery.isEmptyObject( prop ), + optall = jQuery.speed( speed, easing, callback ), + doAnimation = function() { + + // Operate on a copy of prop so per-property easing won't be lost + var anim = Animation( this, jQuery.extend( {}, prop ), optall ); + + // Empty animations, or finishing resolves immediately + if ( empty || dataPriv.get( this, "finish" ) ) { + anim.stop( true ); + } + }; + doAnimation.finish = doAnimation; + + return empty || optall.queue === false ? + this.each( doAnimation ) : + this.queue( optall.queue, doAnimation ); + }, + stop: function( type, clearQueue, gotoEnd ) { + var stopQueue = function( hooks ) { + var stop = hooks.stop; + delete hooks.stop; + stop( gotoEnd ); + }; + + if ( typeof type !== "string" ) { + gotoEnd = clearQueue; + clearQueue = type; + type = undefined; + } + if ( clearQueue ) { + this.queue( type || "fx", [] ); + } + + return this.each( function() { + var dequeue = true, + index = type != null && type + "queueHooks", + timers = jQuery.timers, + data = dataPriv.get( this ); + + if ( index ) { + if ( data[ index ] && data[ index ].stop ) { + stopQueue( data[ index ] ); + } + } else { + for ( index in data ) { + if ( data[ index ] && data[ index ].stop && rrun.test( index ) ) { + stopQueue( data[ index ] ); + } + } + } + + for ( index = timers.length; index--; ) { + if ( timers[ index ].elem === this && + ( type == null || timers[ index ].queue === type ) ) { + + timers[ index ].anim.stop( gotoEnd ); + dequeue = false; + timers.splice( index, 1 ); + } + } + + // Start the next in the queue if the last step wasn't forced. + // Timers currently will call their complete callbacks, which + // will dequeue but only if they were gotoEnd. + if ( dequeue || !gotoEnd ) { + jQuery.dequeue( this, type ); + } + } ); + }, + finish: function( type ) { + if ( type !== false ) { + type = type || "fx"; + } + return this.each( function() { + var index, + data = dataPriv.get( this ), + queue = data[ type + "queue" ], + hooks = data[ type + "queueHooks" ], + timers = jQuery.timers, + length = queue ? queue.length : 0; + + // Enable finishing flag on private data + data.finish = true; + + // Empty the queue first + jQuery.queue( this, type, [] ); + + if ( hooks && hooks.stop ) { + hooks.stop.call( this, true ); + } + + // Look for any active animations, and finish them + for ( index = timers.length; index--; ) { + if ( timers[ index ].elem === this && timers[ index ].queue === type ) { + timers[ index ].anim.stop( true ); + timers.splice( index, 1 ); + } + } + + // Look for any animations in the old queue and finish them + for ( index = 0; index < length; index++ ) { + if ( queue[ index ] && queue[ index ].finish ) { + queue[ index ].finish.call( this ); + } + } + + // Turn off finishing flag + delete data.finish; + } ); + } +} ); + +jQuery.each( [ "toggle", "show", "hide" ], function( _i, name ) { + var cssFn = jQuery.fn[ name ]; + jQuery.fn[ name ] = function( speed, easing, callback ) { + return speed == null || typeof speed === "boolean" ? + cssFn.apply( this, arguments ) : + this.animate( genFx( name, true ), speed, easing, callback ); + }; +} ); + +// Generate shortcuts for custom animations +jQuery.each( { + slideDown: genFx( "show" ), + slideUp: genFx( "hide" ), + slideToggle: genFx( "toggle" ), + fadeIn: { opacity: "show" }, + fadeOut: { opacity: "hide" }, + fadeToggle: { opacity: "toggle" } +}, function( name, props ) { + jQuery.fn[ name ] = function( speed, easing, callback ) { + return this.animate( props, speed, easing, callback ); + }; +} ); + +jQuery.timers = []; +jQuery.fx.tick = function() { + var timer, + i = 0, + timers = jQuery.timers; + + fxNow = Date.now(); + + for ( ; i < timers.length; i++ ) { + timer = timers[ i ]; + + // Run the timer and safely remove it when done (allowing for external removal) + if ( !timer() && timers[ i ] === timer ) { + timers.splice( i--, 1 ); + } + } + + if ( !timers.length ) { + jQuery.fx.stop(); + } + fxNow = undefined; +}; + +jQuery.fx.timer = function( timer ) { + jQuery.timers.push( timer ); + jQuery.fx.start(); +}; + +jQuery.fx.interval = 13; +jQuery.fx.start = function() { + if ( inProgress ) { + return; + } + + inProgress = true; + schedule(); +}; + +jQuery.fx.stop = function() { + inProgress = null; +}; + +jQuery.fx.speeds = { + slow: 600, + fast: 200, + + // Default speed + _default: 400 +}; + + +// Based off of the plugin by Clint Helfers, with permission. +// https://web.archive.org/web/20100324014747/http://blindsignals.com/index.php/2009/07/jquery-delay/ +jQuery.fn.delay = function( time, type ) { + time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time; + type = type || "fx"; + + return this.queue( type, function( next, hooks ) { + var timeout = window.setTimeout( next, time ); + hooks.stop = function() { + window.clearTimeout( timeout ); + }; + } ); +}; + + +( function() { + var input = document.createElement( "input" ), + select = document.createElement( "select" ), + opt = select.appendChild( document.createElement( "option" ) ); + + input.type = "checkbox"; + + // Support: Android <=4.3 only + // Default value for a checkbox should be "on" + support.checkOn = input.value !== ""; + + // Support: IE <=11 only + // Must access selectedIndex to make default options select + support.optSelected = opt.selected; + + // Support: IE <=11 only + // An input loses its value after becoming a radio + input = document.createElement( "input" ); + input.value = "t"; + input.type = "radio"; + support.radioValue = input.value === "t"; +} )(); + + +var boolHook, + attrHandle = jQuery.expr.attrHandle; + +jQuery.fn.extend( { + attr: function( name, value ) { + return access( this, jQuery.attr, name, value, arguments.length > 1 ); + }, + + removeAttr: function( name ) { + return this.each( function() { + jQuery.removeAttr( this, name ); + } ); + } +} ); + +jQuery.extend( { + attr: function( elem, name, value ) { + var ret, hooks, + nType = elem.nodeType; + + // Don't get/set attributes on text, comment and attribute nodes + if ( nType === 3 || nType === 8 || nType === 2 ) { + return; + } + + // Fallback to prop when attributes are not supported + if ( typeof elem.getAttribute === "undefined" ) { + return jQuery.prop( elem, name, value ); + } + + // Attribute hooks are determined by the lowercase version + // Grab necessary hook if one is defined + if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) { + hooks = jQuery.attrHooks[ name.toLowerCase() ] || + ( jQuery.expr.match.bool.test( name ) ? boolHook : undefined ); + } + + if ( value !== undefined ) { + if ( value === null ) { + jQuery.removeAttr( elem, name ); + return; + } + + if ( hooks && "set" in hooks && + ( ret = hooks.set( elem, value, name ) ) !== undefined ) { + return ret; + } + + elem.setAttribute( name, value + "" ); + return value; + } + + if ( hooks && "get" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) { + return ret; + } + + ret = jQuery.find.attr( elem, name ); + + // Non-existent attributes return null, we normalize to undefined + return ret == null ? undefined : ret; + }, + + attrHooks: { + type: { + set: function( elem, value ) { + if ( !support.radioValue && value === "radio" && + nodeName( elem, "input" ) ) { + var val = elem.value; + elem.setAttribute( "type", value ); + if ( val ) { + elem.value = val; + } + return value; + } + } + } + }, + + removeAttr: function( elem, value ) { + var name, + i = 0, + + // Attribute names can contain non-HTML whitespace characters + // https://html.spec.whatwg.org/multipage/syntax.html#attributes-2 + attrNames = value && value.match( rnothtmlwhite ); + + if ( attrNames && elem.nodeType === 1 ) { + while ( ( name = attrNames[ i++ ] ) ) { + elem.removeAttribute( name ); + } + } + } +} ); + +// Hooks for boolean attributes +boolHook = { + set: function( elem, value, name ) { + if ( value === false ) { + + // Remove boolean attributes when set to false + jQuery.removeAttr( elem, name ); + } else { + elem.setAttribute( name, name ); + } + return name; + } +}; + +jQuery.each( jQuery.expr.match.bool.source.match( /\w+/g ), function( _i, name ) { + var getter = attrHandle[ name ] || jQuery.find.attr; + + attrHandle[ name ] = function( elem, name, isXML ) { + var ret, handle, + lowercaseName = name.toLowerCase(); + + if ( !isXML ) { + + // Avoid an infinite loop by temporarily removing this function from the getter + handle = attrHandle[ lowercaseName ]; + attrHandle[ lowercaseName ] = ret; + ret = getter( elem, name, isXML ) != null ? + lowercaseName : + null; + attrHandle[ lowercaseName ] = handle; + } + return ret; + }; +} ); + + + + +var rfocusable = /^(?:input|select|textarea|button)$/i, + rclickable = /^(?:a|area)$/i; + +jQuery.fn.extend( { + prop: function( name, value ) { + return access( this, jQuery.prop, name, value, arguments.length > 1 ); + }, + + removeProp: function( name ) { + return this.each( function() { + delete this[ jQuery.propFix[ name ] || name ]; + } ); + } +} ); + +jQuery.extend( { + prop: function( elem, name, value ) { + var ret, hooks, + nType = elem.nodeType; + + // Don't get/set properties on text, comment and attribute nodes + if ( nType === 3 || nType === 8 || nType === 2 ) { + return; + } + + if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) { + + // Fix name and attach hooks + name = jQuery.propFix[ name ] || name; + hooks = jQuery.propHooks[ name ]; + } + + if ( value !== undefined ) { + if ( hooks && "set" in hooks && + ( ret = hooks.set( elem, value, name ) ) !== undefined ) { + return ret; + } + + return ( elem[ name ] = value ); + } + + if ( hooks && "get" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) { + return ret; + } + + return elem[ name ]; + }, + + propHooks: { + tabIndex: { + get: function( elem ) { + + // Support: IE <=9 - 11 only + // elem.tabIndex doesn't always return the + // correct value when it hasn't been explicitly set + // https://web.archive.org/web/20141116233347/http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/ + // Use proper attribute retrieval(#12072) + var tabindex = jQuery.find.attr( elem, "tabindex" ); + + if ( tabindex ) { + return parseInt( tabindex, 10 ); + } + + if ( + rfocusable.test( elem.nodeName ) || + rclickable.test( elem.nodeName ) && + elem.href + ) { + return 0; + } + + return -1; + } + } + }, + + propFix: { + "for": "htmlFor", + "class": "className" + } +} ); + +// Support: IE <=11 only +// Accessing the selectedIndex property +// forces the browser to respect setting selected +// on the option +// The getter ensures a default option is selected +// when in an optgroup +// eslint rule "no-unused-expressions" is disabled for this code +// since it considers such accessions noop +if ( !support.optSelected ) { + jQuery.propHooks.selected = { + get: function( elem ) { + + /* eslint no-unused-expressions: "off" */ + + var parent = elem.parentNode; + if ( parent && parent.parentNode ) { + parent.parentNode.selectedIndex; + } + return null; + }, + set: function( elem ) { + + /* eslint no-unused-expressions: "off" */ + + var parent = elem.parentNode; + if ( parent ) { + parent.selectedIndex; + + if ( parent.parentNode ) { + parent.parentNode.selectedIndex; + } + } + } + }; +} + +jQuery.each( [ + "tabIndex", + "readOnly", + "maxLength", + "cellSpacing", + "cellPadding", + "rowSpan", + "colSpan", + "useMap", + "frameBorder", + "contentEditable" +], function() { + jQuery.propFix[ this.toLowerCase() ] = this; +} ); + + + + + // Strip and collapse whitespace according to HTML spec + // https://infra.spec.whatwg.org/#strip-and-collapse-ascii-whitespace + function stripAndCollapse( value ) { + var tokens = value.match( rnothtmlwhite ) || []; + return tokens.join( " " ); + } + + +function getClass( elem ) { + return elem.getAttribute && elem.getAttribute( "class" ) || ""; +} + +function classesToArray( value ) { + if ( Array.isArray( value ) ) { + return value; + } + if ( typeof value === "string" ) { + return value.match( rnothtmlwhite ) || []; + } + return []; +} + +jQuery.fn.extend( { + addClass: function( value ) { + var classes, elem, cur, curValue, clazz, j, finalValue, + i = 0; + + if ( isFunction( value ) ) { + return this.each( function( j ) { + jQuery( this ).addClass( value.call( this, j, getClass( this ) ) ); + } ); + } + + classes = classesToArray( value ); + + if ( classes.length ) { + while ( ( elem = this[ i++ ] ) ) { + curValue = getClass( elem ); + cur = elem.nodeType === 1 && ( " " + stripAndCollapse( curValue ) + " " ); + + if ( cur ) { + j = 0; + while ( ( clazz = classes[ j++ ] ) ) { + if ( cur.indexOf( " " + clazz + " " ) < 0 ) { + cur += clazz + " "; + } + } + + // Only assign if different to avoid unneeded rendering. + finalValue = stripAndCollapse( cur ); + if ( curValue !== finalValue ) { + elem.setAttribute( "class", finalValue ); + } + } + } + } + + return this; + }, + + removeClass: function( value ) { + var classes, elem, cur, curValue, clazz, j, finalValue, + i = 0; + + if ( isFunction( value ) ) { + return this.each( function( j ) { + jQuery( this ).removeClass( value.call( this, j, getClass( this ) ) ); + } ); + } + + if ( !arguments.length ) { + return this.attr( "class", "" ); + } + + classes = classesToArray( value ); + + if ( classes.length ) { + while ( ( elem = this[ i++ ] ) ) { + curValue = getClass( elem ); + + // This expression is here for better compressibility (see addClass) + cur = elem.nodeType === 1 && ( " " + stripAndCollapse( curValue ) + " " ); + + if ( cur ) { + j = 0; + while ( ( clazz = classes[ j++ ] ) ) { + + // Remove *all* instances + while ( cur.indexOf( " " + clazz + " " ) > -1 ) { + cur = cur.replace( " " + clazz + " ", " " ); + } + } + + // Only assign if different to avoid unneeded rendering. + finalValue = stripAndCollapse( cur ); + if ( curValue !== finalValue ) { + elem.setAttribute( "class", finalValue ); + } + } + } + } + + return this; + }, + + toggleClass: function( value, stateVal ) { + var type = typeof value, + isValidValue = type === "string" || Array.isArray( value ); + + if ( typeof stateVal === "boolean" && isValidValue ) { + return stateVal ? this.addClass( value ) : this.removeClass( value ); + } + + if ( isFunction( value ) ) { + return this.each( function( i ) { + jQuery( this ).toggleClass( + value.call( this, i, getClass( this ), stateVal ), + stateVal + ); + } ); + } + + return this.each( function() { + var className, i, self, classNames; + + if ( isValidValue ) { + + // Toggle individual class names + i = 0; + self = jQuery( this ); + classNames = classesToArray( value ); + + while ( ( className = classNames[ i++ ] ) ) { + + // Check each className given, space separated list + if ( self.hasClass( className ) ) { + self.removeClass( className ); + } else { + self.addClass( className ); + } + } + + // Toggle whole class name + } else if ( value === undefined || type === "boolean" ) { + className = getClass( this ); + if ( className ) { + + // Store className if set + dataPriv.set( this, "__className__", className ); + } + + // If the element has a class name or if we're passed `false`, + // then remove the whole classname (if there was one, the above saved it). + // Otherwise bring back whatever was previously saved (if anything), + // falling back to the empty string if nothing was stored. + if ( this.setAttribute ) { + this.setAttribute( "class", + className || value === false ? + "" : + dataPriv.get( this, "__className__" ) || "" + ); + } + } + } ); + }, + + hasClass: function( selector ) { + var className, elem, + i = 0; + + className = " " + selector + " "; + while ( ( elem = this[ i++ ] ) ) { + if ( elem.nodeType === 1 && + ( " " + stripAndCollapse( getClass( elem ) ) + " " ).indexOf( className ) > -1 ) { + return true; + } + } + + return false; + } +} ); + + + + +var rreturn = /\r/g; + +jQuery.fn.extend( { + val: function( value ) { + var hooks, ret, valueIsFunction, + elem = this[ 0 ]; + + if ( !arguments.length ) { + if ( elem ) { + hooks = jQuery.valHooks[ elem.type ] || + jQuery.valHooks[ elem.nodeName.toLowerCase() ]; + + if ( hooks && + "get" in hooks && + ( ret = hooks.get( elem, "value" ) ) !== undefined + ) { + return ret; + } + + ret = elem.value; + + // Handle most common string cases + if ( typeof ret === "string" ) { + return ret.replace( rreturn, "" ); + } + + // Handle cases where value is null/undef or number + return ret == null ? "" : ret; + } + + return; + } + + valueIsFunction = isFunction( value ); + + return this.each( function( i ) { + var val; + + if ( this.nodeType !== 1 ) { + return; + } + + if ( valueIsFunction ) { + val = value.call( this, i, jQuery( this ).val() ); + } else { + val = value; + } + + // Treat null/undefined as ""; convert numbers to string + if ( val == null ) { + val = ""; + + } else if ( typeof val === "number" ) { + val += ""; + + } else if ( Array.isArray( val ) ) { + val = jQuery.map( val, function( value ) { + return value == null ? "" : value + ""; + } ); + } + + hooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ]; + + // If set returns undefined, fall back to normal setting + if ( !hooks || !( "set" in hooks ) || hooks.set( this, val, "value" ) === undefined ) { + this.value = val; + } + } ); + } +} ); + +jQuery.extend( { + valHooks: { + option: { + get: function( elem ) { + + var val = jQuery.find.attr( elem, "value" ); + return val != null ? + val : + + // Support: IE <=10 - 11 only + // option.text throws exceptions (#14686, #14858) + // Strip and collapse whitespace + // https://html.spec.whatwg.org/#strip-and-collapse-whitespace + stripAndCollapse( jQuery.text( elem ) ); + } + }, + select: { + get: function( elem ) { + var value, option, i, + options = elem.options, + index = elem.selectedIndex, + one = elem.type === "select-one", + values = one ? null : [], + max = one ? index + 1 : options.length; + + if ( index < 0 ) { + i = max; + + } else { + i = one ? index : 0; + } + + // Loop through all the selected options + for ( ; i < max; i++ ) { + option = options[ i ]; + + // Support: IE <=9 only + // IE8-9 doesn't update selected after form reset (#2551) + if ( ( option.selected || i === index ) && + + // Don't return options that are disabled or in a disabled optgroup + !option.disabled && + ( !option.parentNode.disabled || + !nodeName( option.parentNode, "optgroup" ) ) ) { + + // Get the specific value for the option + value = jQuery( option ).val(); + + // We don't need an array for one selects + if ( one ) { + return value; + } + + // Multi-Selects return an array + values.push( value ); + } + } + + return values; + }, + + set: function( elem, value ) { + var optionSet, option, + options = elem.options, + values = jQuery.makeArray( value ), + i = options.length; + + while ( i-- ) { + option = options[ i ]; + + /* eslint-disable no-cond-assign */ + + if ( option.selected = + jQuery.inArray( jQuery.valHooks.option.get( option ), values ) > -1 + ) { + optionSet = true; + } + + /* eslint-enable no-cond-assign */ + } + + // Force browsers to behave consistently when non-matching value is set + if ( !optionSet ) { + elem.selectedIndex = -1; + } + return values; + } + } + } +} ); + +// Radios and checkboxes getter/setter +jQuery.each( [ "radio", "checkbox" ], function() { + jQuery.valHooks[ this ] = { + set: function( elem, value ) { + if ( Array.isArray( value ) ) { + return ( elem.checked = jQuery.inArray( jQuery( elem ).val(), value ) > -1 ); + } + } + }; + if ( !support.checkOn ) { + jQuery.valHooks[ this ].get = function( elem ) { + return elem.getAttribute( "value" ) === null ? "on" : elem.value; + }; + } +} ); + + + + +// Return jQuery for attributes-only inclusion + + +support.focusin = "onfocusin" in window; + + +var rfocusMorph = /^(?:focusinfocus|focusoutblur)$/, + stopPropagationCallback = function( e ) { + e.stopPropagation(); + }; + +jQuery.extend( jQuery.event, { + + trigger: function( event, data, elem, onlyHandlers ) { + + var i, cur, tmp, bubbleType, ontype, handle, special, lastElement, + eventPath = [ elem || document ], + type = hasOwn.call( event, "type" ) ? event.type : event, + namespaces = hasOwn.call( event, "namespace" ) ? event.namespace.split( "." ) : []; + + cur = lastElement = tmp = elem = elem || document; + + // Don't do events on text and comment nodes + if ( elem.nodeType === 3 || elem.nodeType === 8 ) { + return; + } + + // focus/blur morphs to focusin/out; ensure we're not firing them right now + if ( rfocusMorph.test( type + jQuery.event.triggered ) ) { + return; + } + + if ( type.indexOf( "." ) > -1 ) { + + // Namespaced trigger; create a regexp to match event type in handle() + namespaces = type.split( "." ); + type = namespaces.shift(); + namespaces.sort(); + } + ontype = type.indexOf( ":" ) < 0 && "on" + type; + + // Caller can pass in a jQuery.Event object, Object, or just an event type string + event = event[ jQuery.expando ] ? + event : + new jQuery.Event( type, typeof event === "object" && event ); + + // Trigger bitmask: & 1 for native handlers; & 2 for jQuery (always true) + event.isTrigger = onlyHandlers ? 2 : 3; + event.namespace = namespaces.join( "." ); + event.rnamespace = event.namespace ? + new RegExp( "(^|\\.)" + namespaces.join( "\\.(?:.*\\.|)" ) + "(\\.|$)" ) : + null; + + // Clean up the event in case it is being reused + event.result = undefined; + if ( !event.target ) { + event.target = elem; + } + + // Clone any incoming data and prepend the event, creating the handler arg list + data = data == null ? + [ event ] : + jQuery.makeArray( data, [ event ] ); + + // Allow special events to draw outside the lines + special = jQuery.event.special[ type ] || {}; + if ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) { + return; + } + + // Determine event propagation path in advance, per W3C events spec (#9951) + // Bubble up to document, then to window; watch for a global ownerDocument var (#9724) + if ( !onlyHandlers && !special.noBubble && !isWindow( elem ) ) { + + bubbleType = special.delegateType || type; + if ( !rfocusMorph.test( bubbleType + type ) ) { + cur = cur.parentNode; + } + for ( ; cur; cur = cur.parentNode ) { + eventPath.push( cur ); + tmp = cur; + } + + // Only add window if we got to document (e.g., not plain obj or detached DOM) + if ( tmp === ( elem.ownerDocument || document ) ) { + eventPath.push( tmp.defaultView || tmp.parentWindow || window ); + } + } + + // Fire handlers on the event path + i = 0; + while ( ( cur = eventPath[ i++ ] ) && !event.isPropagationStopped() ) { + lastElement = cur; + event.type = i > 1 ? + bubbleType : + special.bindType || type; + + // jQuery handler + handle = ( + dataPriv.get( cur, "events" ) || Object.create( null ) + )[ event.type ] && + dataPriv.get( cur, "handle" ); + if ( handle ) { + handle.apply( cur, data ); + } + + // Native handler + handle = ontype && cur[ ontype ]; + if ( handle && handle.apply && acceptData( cur ) ) { + event.result = handle.apply( cur, data ); + if ( event.result === false ) { + event.preventDefault(); + } + } + } + event.type = type; + + // If nobody prevented the default action, do it now + if ( !onlyHandlers && !event.isDefaultPrevented() ) { + + if ( ( !special._default || + special._default.apply( eventPath.pop(), data ) === false ) && + acceptData( elem ) ) { + + // Call a native DOM method on the target with the same name as the event. + // Don't do default actions on window, that's where global variables be (#6170) + if ( ontype && isFunction( elem[ type ] ) && !isWindow( elem ) ) { + + // Don't re-trigger an onFOO event when we call its FOO() method + tmp = elem[ ontype ]; + + if ( tmp ) { + elem[ ontype ] = null; + } + + // Prevent re-triggering of the same event, since we already bubbled it above + jQuery.event.triggered = type; + + if ( event.isPropagationStopped() ) { + lastElement.addEventListener( type, stopPropagationCallback ); + } + + elem[ type ](); + + if ( event.isPropagationStopped() ) { + lastElement.removeEventListener( type, stopPropagationCallback ); + } + + jQuery.event.triggered = undefined; + + if ( tmp ) { + elem[ ontype ] = tmp; + } + } + } + } + + return event.result; + }, + + // Piggyback on a donor event to simulate a different one + // Used only for `focus(in | out)` events + simulate: function( type, elem, event ) { + var e = jQuery.extend( + new jQuery.Event(), + event, + { + type: type, + isSimulated: true + } + ); + + jQuery.event.trigger( e, null, elem ); + } + +} ); + +jQuery.fn.extend( { + + trigger: function( type, data ) { + return this.each( function() { + jQuery.event.trigger( type, data, this ); + } ); + }, + triggerHandler: function( type, data ) { + var elem = this[ 0 ]; + if ( elem ) { + return jQuery.event.trigger( type, data, elem, true ); + } + } +} ); + + +// Support: Firefox <=44 +// Firefox doesn't have focus(in | out) events +// Related ticket - https://bugzilla.mozilla.org/show_bug.cgi?id=687787 +// +// Support: Chrome <=48 - 49, Safari <=9.0 - 9.1 +// focus(in | out) events fire after focus & blur events, +// which is spec violation - http://www.w3.org/TR/DOM-Level-3-Events/#events-focusevent-event-order +// Related ticket - https://bugs.chromium.org/p/chromium/issues/detail?id=449857 +if ( !support.focusin ) { + jQuery.each( { focus: "focusin", blur: "focusout" }, function( orig, fix ) { + + // Attach a single capturing handler on the document while someone wants focusin/focusout + var handler = function( event ) { + jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ) ); + }; + + jQuery.event.special[ fix ] = { + setup: function() { + + // Handle: regular nodes (via `this.ownerDocument`), window + // (via `this.document`) & document (via `this`). + var doc = this.ownerDocument || this.document || this, + attaches = dataPriv.access( doc, fix ); + + if ( !attaches ) { + doc.addEventListener( orig, handler, true ); + } + dataPriv.access( doc, fix, ( attaches || 0 ) + 1 ); + }, + teardown: function() { + var doc = this.ownerDocument || this.document || this, + attaches = dataPriv.access( doc, fix ) - 1; + + if ( !attaches ) { + doc.removeEventListener( orig, handler, true ); + dataPriv.remove( doc, fix ); + + } else { + dataPriv.access( doc, fix, attaches ); + } + } + }; + } ); +} +var location = window.location; + +var nonce = { guid: Date.now() }; + +var rquery = ( /\?/ ); + + + +// Cross-browser xml parsing +jQuery.parseXML = function( data ) { + var xml; + if ( !data || typeof data !== "string" ) { + return null; + } + + // Support: IE 9 - 11 only + // IE throws on parseFromString with invalid input. + try { + xml = ( new window.DOMParser() ).parseFromString( data, "text/xml" ); + } catch ( e ) { + xml = undefined; + } + + if ( !xml || xml.getElementsByTagName( "parsererror" ).length ) { + jQuery.error( "Invalid XML: " + data ); + } + return xml; +}; + + +var + rbracket = /\[\]$/, + rCRLF = /\r?\n/g, + rsubmitterTypes = /^(?:submit|button|image|reset|file)$/i, + rsubmittable = /^(?:input|select|textarea|keygen)/i; + +function buildParams( prefix, obj, traditional, add ) { + var name; + + if ( Array.isArray( obj ) ) { + + // Serialize array item. + jQuery.each( obj, function( i, v ) { + if ( traditional || rbracket.test( prefix ) ) { + + // Treat each array item as a scalar. + add( prefix, v ); + + } else { + + // Item is non-scalar (array or object), encode its numeric index. + buildParams( + prefix + "[" + ( typeof v === "object" && v != null ? i : "" ) + "]", + v, + traditional, + add + ); + } + } ); + + } else if ( !traditional && toType( obj ) === "object" ) { + + // Serialize object item. + for ( name in obj ) { + buildParams( prefix + "[" + name + "]", obj[ name ], traditional, add ); + } + + } else { + + // Serialize scalar item. + add( prefix, obj ); + } +} + +// Serialize an array of form elements or a set of +// key/values into a query string +jQuery.param = function( a, traditional ) { + var prefix, + s = [], + add = function( key, valueOrFunction ) { + + // If value is a function, invoke it and use its return value + var value = isFunction( valueOrFunction ) ? + valueOrFunction() : + valueOrFunction; + + s[ s.length ] = encodeURIComponent( key ) + "=" + + encodeURIComponent( value == null ? "" : value ); + }; + + if ( a == null ) { + return ""; + } + + // If an array was passed in, assume that it is an array of form elements. + if ( Array.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) { + + // Serialize the form elements + jQuery.each( a, function() { + add( this.name, this.value ); + } ); + + } else { + + // If traditional, encode the "old" way (the way 1.3.2 or older + // did it), otherwise encode params recursively. + for ( prefix in a ) { + buildParams( prefix, a[ prefix ], traditional, add ); + } + } + + // Return the resulting serialization + return s.join( "&" ); +}; + +jQuery.fn.extend( { + serialize: function() { + return jQuery.param( this.serializeArray() ); + }, + serializeArray: function() { + return this.map( function() { + + // Can add propHook for "elements" to filter or add form elements + var elements = jQuery.prop( this, "elements" ); + return elements ? jQuery.makeArray( elements ) : this; + } ) + .filter( function() { + var type = this.type; + + // Use .is( ":disabled" ) so that fieldset[disabled] works + return this.name && !jQuery( this ).is( ":disabled" ) && + rsubmittable.test( this.nodeName ) && !rsubmitterTypes.test( type ) && + ( this.checked || !rcheckableType.test( type ) ); + } ) + .map( function( _i, elem ) { + var val = jQuery( this ).val(); + + if ( val == null ) { + return null; + } + + if ( Array.isArray( val ) ) { + return jQuery.map( val, function( val ) { + return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) }; + } ); + } + + return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) }; + } ).get(); + } +} ); + + +var + r20 = /%20/g, + rhash = /#.*$/, + rantiCache = /([?&])_=[^&]*/, + rheaders = /^(.*?):[ \t]*([^\r\n]*)$/mg, + + // #7653, #8125, #8152: local protocol detection + rlocalProtocol = /^(?:about|app|app-storage|.+-extension|file|res|widget):$/, + rnoContent = /^(?:GET|HEAD)$/, + rprotocol = /^\/\//, + + /* Prefilters + * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example) + * 2) These are called: + * - BEFORE asking for a transport + * - AFTER param serialization (s.data is a string if s.processData is true) + * 3) key is the dataType + * 4) the catchall symbol "*" can be used + * 5) execution will start with transport dataType and THEN continue down to "*" if needed + */ + prefilters = {}, + + /* Transports bindings + * 1) key is the dataType + * 2) the catchall symbol "*" can be used + * 3) selection will start with transport dataType and THEN go to "*" if needed + */ + transports = {}, + + // Avoid comment-prolog char sequence (#10098); must appease lint and evade compression + allTypes = "*/".concat( "*" ), + + // Anchor tag for parsing the document origin + originAnchor = document.createElement( "a" ); + originAnchor.href = location.href; + +// Base "constructor" for jQuery.ajaxPrefilter and jQuery.ajaxTransport +function addToPrefiltersOrTransports( structure ) { + + // dataTypeExpression is optional and defaults to "*" + return function( dataTypeExpression, func ) { + + if ( typeof dataTypeExpression !== "string" ) { + func = dataTypeExpression; + dataTypeExpression = "*"; + } + + var dataType, + i = 0, + dataTypes = dataTypeExpression.toLowerCase().match( rnothtmlwhite ) || []; + + if ( isFunction( func ) ) { + + // For each dataType in the dataTypeExpression + while ( ( dataType = dataTypes[ i++ ] ) ) { + + // Prepend if requested + if ( dataType[ 0 ] === "+" ) { + dataType = dataType.slice( 1 ) || "*"; + ( structure[ dataType ] = structure[ dataType ] || [] ).unshift( func ); + + // Otherwise append + } else { + ( structure[ dataType ] = structure[ dataType ] || [] ).push( func ); + } + } + } + }; +} + +// Base inspection function for prefilters and transports +function inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR ) { + + var inspected = {}, + seekingTransport = ( structure === transports ); + + function inspect( dataType ) { + var selected; + inspected[ dataType ] = true; + jQuery.each( structure[ dataType ] || [], function( _, prefilterOrFactory ) { + var dataTypeOrTransport = prefilterOrFactory( options, originalOptions, jqXHR ); + if ( typeof dataTypeOrTransport === "string" && + !seekingTransport && !inspected[ dataTypeOrTransport ] ) { + + options.dataTypes.unshift( dataTypeOrTransport ); + inspect( dataTypeOrTransport ); + return false; + } else if ( seekingTransport ) { + return !( selected = dataTypeOrTransport ); + } + } ); + return selected; + } + + return inspect( options.dataTypes[ 0 ] ) || !inspected[ "*" ] && inspect( "*" ); +} + +// A special extend for ajax options +// that takes "flat" options (not to be deep extended) +// Fixes #9887 +function ajaxExtend( target, src ) { + var key, deep, + flatOptions = jQuery.ajaxSettings.flatOptions || {}; + + for ( key in src ) { + if ( src[ key ] !== undefined ) { + ( flatOptions[ key ] ? target : ( deep || ( deep = {} ) ) )[ key ] = src[ key ]; + } + } + if ( deep ) { + jQuery.extend( true, target, deep ); + } + + return target; +} + +/* Handles responses to an ajax request: + * - finds the right dataType (mediates between content-type and expected dataType) + * - returns the corresponding response + */ +function ajaxHandleResponses( s, jqXHR, responses ) { + + var ct, type, finalDataType, firstDataType, + contents = s.contents, + dataTypes = s.dataTypes; + + // Remove auto dataType and get content-type in the process + while ( dataTypes[ 0 ] === "*" ) { + dataTypes.shift(); + if ( ct === undefined ) { + ct = s.mimeType || jqXHR.getResponseHeader( "Content-Type" ); + } + } + + // Check if we're dealing with a known content-type + if ( ct ) { + for ( type in contents ) { + if ( contents[ type ] && contents[ type ].test( ct ) ) { + dataTypes.unshift( type ); + break; + } + } + } + + // Check to see if we have a response for the expected dataType + if ( dataTypes[ 0 ] in responses ) { + finalDataType = dataTypes[ 0 ]; + } else { + + // Try convertible dataTypes + for ( type in responses ) { + if ( !dataTypes[ 0 ] || s.converters[ type + " " + dataTypes[ 0 ] ] ) { + finalDataType = type; + break; + } + if ( !firstDataType ) { + firstDataType = type; + } + } + + // Or just use first one + finalDataType = finalDataType || firstDataType; + } + + // If we found a dataType + // We add the dataType to the list if needed + // and return the corresponding response + if ( finalDataType ) { + if ( finalDataType !== dataTypes[ 0 ] ) { + dataTypes.unshift( finalDataType ); + } + return responses[ finalDataType ]; + } +} + +/* Chain conversions given the request and the original response + * Also sets the responseXXX fields on the jqXHR instance + */ +function ajaxConvert( s, response, jqXHR, isSuccess ) { + var conv2, current, conv, tmp, prev, + converters = {}, + + // Work with a copy of dataTypes in case we need to modify it for conversion + dataTypes = s.dataTypes.slice(); + + // Create converters map with lowercased keys + if ( dataTypes[ 1 ] ) { + for ( conv in s.converters ) { + converters[ conv.toLowerCase() ] = s.converters[ conv ]; + } + } + + current = dataTypes.shift(); + + // Convert to each sequential dataType + while ( current ) { + + if ( s.responseFields[ current ] ) { + jqXHR[ s.responseFields[ current ] ] = response; + } + + // Apply the dataFilter if provided + if ( !prev && isSuccess && s.dataFilter ) { + response = s.dataFilter( response, s.dataType ); + } + + prev = current; + current = dataTypes.shift(); + + if ( current ) { + + // There's only work to do if current dataType is non-auto + if ( current === "*" ) { + + current = prev; + + // Convert response if prev dataType is non-auto and differs from current + } else if ( prev !== "*" && prev !== current ) { + + // Seek a direct converter + conv = converters[ prev + " " + current ] || converters[ "* " + current ]; + + // If none found, seek a pair + if ( !conv ) { + for ( conv2 in converters ) { + + // If conv2 outputs current + tmp = conv2.split( " " ); + if ( tmp[ 1 ] === current ) { + + // If prev can be converted to accepted input + conv = converters[ prev + " " + tmp[ 0 ] ] || + converters[ "* " + tmp[ 0 ] ]; + if ( conv ) { + + // Condense equivalence converters + if ( conv === true ) { + conv = converters[ conv2 ]; + + // Otherwise, insert the intermediate dataType + } else if ( converters[ conv2 ] !== true ) { + current = tmp[ 0 ]; + dataTypes.unshift( tmp[ 1 ] ); + } + break; + } + } + } + } + + // Apply converter (if not an equivalence) + if ( conv !== true ) { + + // Unless errors are allowed to bubble, catch and return them + if ( conv && s.throws ) { + response = conv( response ); + } else { + try { + response = conv( response ); + } catch ( e ) { + return { + state: "parsererror", + error: conv ? e : "No conversion from " + prev + " to " + current + }; + } + } + } + } + } + } + + return { state: "success", data: response }; +} + +jQuery.extend( { + + // Counter for holding the number of active queries + active: 0, + + // Last-Modified header cache for next request + lastModified: {}, + etag: {}, + + ajaxSettings: { + url: location.href, + type: "GET", + isLocal: rlocalProtocol.test( location.protocol ), + global: true, + processData: true, + async: true, + contentType: "application/x-www-form-urlencoded; charset=UTF-8", + + /* + timeout: 0, + data: null, + dataType: null, + username: null, + password: null, + cache: null, + throws: false, + traditional: false, + headers: {}, + */ + + accepts: { + "*": allTypes, + text: "text/plain", + html: "text/html", + xml: "application/xml, text/xml", + json: "application/json, text/javascript" + }, + + contents: { + xml: /\bxml\b/, + html: /\bhtml/, + json: /\bjson\b/ + }, + + responseFields: { + xml: "responseXML", + text: "responseText", + json: "responseJSON" + }, + + // Data converters + // Keys separate source (or catchall "*") and destination types with a single space + converters: { + + // Convert anything to text + "* text": String, + + // Text to html (true = no transformation) + "text html": true, + + // Evaluate text as a json expression + "text json": JSON.parse, + + // Parse text as xml + "text xml": jQuery.parseXML + }, + + // For options that shouldn't be deep extended: + // you can add your own custom options here if + // and when you create one that shouldn't be + // deep extended (see ajaxExtend) + flatOptions: { + url: true, + context: true + } + }, + + // Creates a full fledged settings object into target + // with both ajaxSettings and settings fields. + // If target is omitted, writes into ajaxSettings. + ajaxSetup: function( target, settings ) { + return settings ? + + // Building a settings object + ajaxExtend( ajaxExtend( target, jQuery.ajaxSettings ), settings ) : + + // Extending ajaxSettings + ajaxExtend( jQuery.ajaxSettings, target ); + }, + + ajaxPrefilter: addToPrefiltersOrTransports( prefilters ), + ajaxTransport: addToPrefiltersOrTransports( transports ), + + // Main method + ajax: function( url, options ) { + + // If url is an object, simulate pre-1.5 signature + if ( typeof url === "object" ) { + options = url; + url = undefined; + } + + // Force options to be an object + options = options || {}; + + var transport, + + // URL without anti-cache param + cacheURL, + + // Response headers + responseHeadersString, + responseHeaders, + + // timeout handle + timeoutTimer, + + // Url cleanup var + urlAnchor, + + // Request state (becomes false upon send and true upon completion) + completed, + + // To know if global events are to be dispatched + fireGlobals, + + // Loop variable + i, + + // uncached part of the url + uncached, + + // Create the final options object + s = jQuery.ajaxSetup( {}, options ), + + // Callbacks context + callbackContext = s.context || s, + + // Context for global events is callbackContext if it is a DOM node or jQuery collection + globalEventContext = s.context && + ( callbackContext.nodeType || callbackContext.jquery ) ? + jQuery( callbackContext ) : + jQuery.event, + + // Deferreds + deferred = jQuery.Deferred(), + completeDeferred = jQuery.Callbacks( "once memory" ), + + // Status-dependent callbacks + statusCode = s.statusCode || {}, + + // Headers (they are sent all at once) + requestHeaders = {}, + requestHeadersNames = {}, + + // Default abort message + strAbort = "canceled", + + // Fake xhr + jqXHR = { + readyState: 0, + + // Builds headers hashtable if needed + getResponseHeader: function( key ) { + var match; + if ( completed ) { + if ( !responseHeaders ) { + responseHeaders = {}; + while ( ( match = rheaders.exec( responseHeadersString ) ) ) { + responseHeaders[ match[ 1 ].toLowerCase() + " " ] = + ( responseHeaders[ match[ 1 ].toLowerCase() + " " ] || [] ) + .concat( match[ 2 ] ); + } + } + match = responseHeaders[ key.toLowerCase() + " " ]; + } + return match == null ? null : match.join( ", " ); + }, + + // Raw string + getAllResponseHeaders: function() { + return completed ? responseHeadersString : null; + }, + + // Caches the header + setRequestHeader: function( name, value ) { + if ( completed == null ) { + name = requestHeadersNames[ name.toLowerCase() ] = + requestHeadersNames[ name.toLowerCase() ] || name; + requestHeaders[ name ] = value; + } + return this; + }, + + // Overrides response content-type header + overrideMimeType: function( type ) { + if ( completed == null ) { + s.mimeType = type; + } + return this; + }, + + // Status-dependent callbacks + statusCode: function( map ) { + var code; + if ( map ) { + if ( completed ) { + + // Execute the appropriate callbacks + jqXHR.always( map[ jqXHR.status ] ); + } else { + + // Lazy-add the new callbacks in a way that preserves old ones + for ( code in map ) { + statusCode[ code ] = [ statusCode[ code ], map[ code ] ]; + } + } + } + return this; + }, + + // Cancel the request + abort: function( statusText ) { + var finalText = statusText || strAbort; + if ( transport ) { + transport.abort( finalText ); + } + done( 0, finalText ); + return this; + } + }; + + // Attach deferreds + deferred.promise( jqXHR ); + + // Add protocol if not provided (prefilters might expect it) + // Handle falsy url in the settings object (#10093: consistency with old signature) + // We also use the url parameter if available + s.url = ( ( url || s.url || location.href ) + "" ) + .replace( rprotocol, location.protocol + "//" ); + + // Alias method option to type as per ticket #12004 + s.type = options.method || options.type || s.method || s.type; + + // Extract dataTypes list + s.dataTypes = ( s.dataType || "*" ).toLowerCase().match( rnothtmlwhite ) || [ "" ]; + + // A cross-domain request is in order when the origin doesn't match the current origin. + if ( s.crossDomain == null ) { + urlAnchor = document.createElement( "a" ); + + // Support: IE <=8 - 11, Edge 12 - 15 + // IE throws exception on accessing the href property if url is malformed, + // e.g. http://example.com:80x/ + try { + urlAnchor.href = s.url; + + // Support: IE <=8 - 11 only + // Anchor's host property isn't correctly set when s.url is relative + urlAnchor.href = urlAnchor.href; + s.crossDomain = originAnchor.protocol + "//" + originAnchor.host !== + urlAnchor.protocol + "//" + urlAnchor.host; + } catch ( e ) { + + // If there is an error parsing the URL, assume it is crossDomain, + // it can be rejected by the transport if it is invalid + s.crossDomain = true; + } + } + + // Convert data if not already a string + if ( s.data && s.processData && typeof s.data !== "string" ) { + s.data = jQuery.param( s.data, s.traditional ); + } + + // Apply prefilters + inspectPrefiltersOrTransports( prefilters, s, options, jqXHR ); + + // If request was aborted inside a prefilter, stop there + if ( completed ) { + return jqXHR; + } + + // We can fire global events as of now if asked to + // Don't fire events if jQuery.event is undefined in an AMD-usage scenario (#15118) + fireGlobals = jQuery.event && s.global; + + // Watch for a new set of requests + if ( fireGlobals && jQuery.active++ === 0 ) { + jQuery.event.trigger( "ajaxStart" ); + } + + // Uppercase the type + s.type = s.type.toUpperCase(); + + // Determine if request has content + s.hasContent = !rnoContent.test( s.type ); + + // Save the URL in case we're toying with the If-Modified-Since + // and/or If-None-Match header later on + // Remove hash to simplify url manipulation + cacheURL = s.url.replace( rhash, "" ); + + // More options handling for requests with no content + if ( !s.hasContent ) { + + // Remember the hash so we can put it back + uncached = s.url.slice( cacheURL.length ); + + // If data is available and should be processed, append data to url + if ( s.data && ( s.processData || typeof s.data === "string" ) ) { + cacheURL += ( rquery.test( cacheURL ) ? "&" : "?" ) + s.data; + + // #9682: remove data so that it's not used in an eventual retry + delete s.data; + } + + // Add or update anti-cache param if needed + if ( s.cache === false ) { + cacheURL = cacheURL.replace( rantiCache, "$1" ); + uncached = ( rquery.test( cacheURL ) ? "&" : "?" ) + "_=" + ( nonce.guid++ ) + + uncached; + } + + // Put hash and anti-cache on the URL that will be requested (gh-1732) + s.url = cacheURL + uncached; + + // Change '%20' to '+' if this is encoded form body content (gh-2658) + } else if ( s.data && s.processData && + ( s.contentType || "" ).indexOf( "application/x-www-form-urlencoded" ) === 0 ) { + s.data = s.data.replace( r20, "+" ); + } + + // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode. + if ( s.ifModified ) { + if ( jQuery.lastModified[ cacheURL ] ) { + jqXHR.setRequestHeader( "If-Modified-Since", jQuery.lastModified[ cacheURL ] ); + } + if ( jQuery.etag[ cacheURL ] ) { + jqXHR.setRequestHeader( "If-None-Match", jQuery.etag[ cacheURL ] ); + } + } + + // Set the correct header, if data is being sent + if ( s.data && s.hasContent && s.contentType !== false || options.contentType ) { + jqXHR.setRequestHeader( "Content-Type", s.contentType ); + } + + // Set the Accepts header for the server, depending on the dataType + jqXHR.setRequestHeader( + "Accept", + s.dataTypes[ 0 ] && s.accepts[ s.dataTypes[ 0 ] ] ? + s.accepts[ s.dataTypes[ 0 ] ] + + ( s.dataTypes[ 0 ] !== "*" ? ", " + allTypes + "; q=0.01" : "" ) : + s.accepts[ "*" ] + ); + + // Check for headers option + for ( i in s.headers ) { + jqXHR.setRequestHeader( i, s.headers[ i ] ); + } + + // Allow custom headers/mimetypes and early abort + if ( s.beforeSend && + ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || completed ) ) { + + // Abort if not done already and return + return jqXHR.abort(); + } + + // Aborting is no longer a cancellation + strAbort = "abort"; + + // Install callbacks on deferreds + completeDeferred.add( s.complete ); + jqXHR.done( s.success ); + jqXHR.fail( s.error ); + + // Get transport + transport = inspectPrefiltersOrTransports( transports, s, options, jqXHR ); + + // If no transport, we auto-abort + if ( !transport ) { + done( -1, "No Transport" ); + } else { + jqXHR.readyState = 1; + + // Send global event + if ( fireGlobals ) { + globalEventContext.trigger( "ajaxSend", [ jqXHR, s ] ); + } + + // If request was aborted inside ajaxSend, stop there + if ( completed ) { + return jqXHR; + } + + // Timeout + if ( s.async && s.timeout > 0 ) { + timeoutTimer = window.setTimeout( function() { + jqXHR.abort( "timeout" ); + }, s.timeout ); + } + + try { + completed = false; + transport.send( requestHeaders, done ); + } catch ( e ) { + + // Rethrow post-completion exceptions + if ( completed ) { + throw e; + } + + // Propagate others as results + done( -1, e ); + } + } + + // Callback for when everything is done + function done( status, nativeStatusText, responses, headers ) { + var isSuccess, success, error, response, modified, + statusText = nativeStatusText; + + // Ignore repeat invocations + if ( completed ) { + return; + } + + completed = true; + + // Clear timeout if it exists + if ( timeoutTimer ) { + window.clearTimeout( timeoutTimer ); + } + + // Dereference transport for early garbage collection + // (no matter how long the jqXHR object will be used) + transport = undefined; + + // Cache response headers + responseHeadersString = headers || ""; + + // Set readyState + jqXHR.readyState = status > 0 ? 4 : 0; + + // Determine if successful + isSuccess = status >= 200 && status < 300 || status === 304; + + // Get response data + if ( responses ) { + response = ajaxHandleResponses( s, jqXHR, responses ); + } + + // Use a noop converter for missing script + if ( !isSuccess && jQuery.inArray( "script", s.dataTypes ) > -1 ) { + s.converters[ "text script" ] = function() {}; + } + + // Convert no matter what (that way responseXXX fields are always set) + response = ajaxConvert( s, response, jqXHR, isSuccess ); + + // If successful, handle type chaining + if ( isSuccess ) { + + // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode. + if ( s.ifModified ) { + modified = jqXHR.getResponseHeader( "Last-Modified" ); + if ( modified ) { + jQuery.lastModified[ cacheURL ] = modified; + } + modified = jqXHR.getResponseHeader( "etag" ); + if ( modified ) { + jQuery.etag[ cacheURL ] = modified; + } + } + + // if no content + if ( status === 204 || s.type === "HEAD" ) { + statusText = "nocontent"; + + // if not modified + } else if ( status === 304 ) { + statusText = "notmodified"; + + // If we have data, let's convert it + } else { + statusText = response.state; + success = response.data; + error = response.error; + isSuccess = !error; + } + } else { + + // Extract error from statusText and normalize for non-aborts + error = statusText; + if ( status || !statusText ) { + statusText = "error"; + if ( status < 0 ) { + status = 0; + } + } + } + + // Set data for the fake xhr object + jqXHR.status = status; + jqXHR.statusText = ( nativeStatusText || statusText ) + ""; + + // Success/Error + if ( isSuccess ) { + deferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] ); + } else { + deferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] ); + } + + // Status-dependent callbacks + jqXHR.statusCode( statusCode ); + statusCode = undefined; + + if ( fireGlobals ) { + globalEventContext.trigger( isSuccess ? "ajaxSuccess" : "ajaxError", + [ jqXHR, s, isSuccess ? success : error ] ); + } + + // Complete + completeDeferred.fireWith( callbackContext, [ jqXHR, statusText ] ); + + if ( fireGlobals ) { + globalEventContext.trigger( "ajaxComplete", [ jqXHR, s ] ); + + // Handle the global AJAX counter + if ( !( --jQuery.active ) ) { + jQuery.event.trigger( "ajaxStop" ); + } + } + } + + return jqXHR; + }, + + getJSON: function( url, data, callback ) { + return jQuery.get( url, data, callback, "json" ); + }, + + getScript: function( url, callback ) { + return jQuery.get( url, undefined, callback, "script" ); + } +} ); + +jQuery.each( [ "get", "post" ], function( _i, method ) { + jQuery[ method ] = function( url, data, callback, type ) { + + // Shift arguments if data argument was omitted + if ( isFunction( data ) ) { + type = type || callback; + callback = data; + data = undefined; + } + + // The url can be an options object (which then must have .url) + return jQuery.ajax( jQuery.extend( { + url: url, + type: method, + dataType: type, + data: data, + success: callback + }, jQuery.isPlainObject( url ) && url ) ); + }; +} ); + +jQuery.ajaxPrefilter( function( s ) { + var i; + for ( i in s.headers ) { + if ( i.toLowerCase() === "content-type" ) { + s.contentType = s.headers[ i ] || ""; + } + } +} ); + + +jQuery._evalUrl = function( url, options, doc ) { + return jQuery.ajax( { + url: url, + + // Make this explicit, since user can override this through ajaxSetup (#11264) + type: "GET", + dataType: "script", + cache: true, + async: false, + global: false, + + // Only evaluate the response if it is successful (gh-4126) + // dataFilter is not invoked for failure responses, so using it instead + // of the default converter is kludgy but it works. + converters: { + "text script": function() {} + }, + dataFilter: function( response ) { + jQuery.globalEval( response, options, doc ); + } + } ); +}; + + +jQuery.fn.extend( { + wrapAll: function( html ) { + var wrap; + + if ( this[ 0 ] ) { + if ( isFunction( html ) ) { + html = html.call( this[ 0 ] ); + } + + // The elements to wrap the target around + wrap = jQuery( html, this[ 0 ].ownerDocument ).eq( 0 ).clone( true ); + + if ( this[ 0 ].parentNode ) { + wrap.insertBefore( this[ 0 ] ); + } + + wrap.map( function() { + var elem = this; + + while ( elem.firstElementChild ) { + elem = elem.firstElementChild; + } + + return elem; + } ).append( this ); + } + + return this; + }, + + wrapInner: function( html ) { + if ( isFunction( html ) ) { + return this.each( function( i ) { + jQuery( this ).wrapInner( html.call( this, i ) ); + } ); + } + + return this.each( function() { + var self = jQuery( this ), + contents = self.contents(); + + if ( contents.length ) { + contents.wrapAll( html ); + + } else { + self.append( html ); + } + } ); + }, + + wrap: function( html ) { + var htmlIsFunction = isFunction( html ); + + return this.each( function( i ) { + jQuery( this ).wrapAll( htmlIsFunction ? html.call( this, i ) : html ); + } ); + }, + + unwrap: function( selector ) { + this.parent( selector ).not( "body" ).each( function() { + jQuery( this ).replaceWith( this.childNodes ); + } ); + return this; + } +} ); + + +jQuery.expr.pseudos.hidden = function( elem ) { + return !jQuery.expr.pseudos.visible( elem ); +}; +jQuery.expr.pseudos.visible = function( elem ) { + return !!( elem.offsetWidth || elem.offsetHeight || elem.getClientRects().length ); +}; + + + + +jQuery.ajaxSettings.xhr = function() { + try { + return new window.XMLHttpRequest(); + } catch ( e ) {} +}; + +var xhrSuccessStatus = { + + // File protocol always yields status code 0, assume 200 + 0: 200, + + // Support: IE <=9 only + // #1450: sometimes IE returns 1223 when it should be 204 + 1223: 204 + }, + xhrSupported = jQuery.ajaxSettings.xhr(); + +support.cors = !!xhrSupported && ( "withCredentials" in xhrSupported ); +support.ajax = xhrSupported = !!xhrSupported; + +jQuery.ajaxTransport( function( options ) { + var callback, errorCallback; + + // Cross domain only allowed if supported through XMLHttpRequest + if ( support.cors || xhrSupported && !options.crossDomain ) { + return { + send: function( headers, complete ) { + var i, + xhr = options.xhr(); + + xhr.open( + options.type, + options.url, + options.async, + options.username, + options.password + ); + + // Apply custom fields if provided + if ( options.xhrFields ) { + for ( i in options.xhrFields ) { + xhr[ i ] = options.xhrFields[ i ]; + } + } + + // Override mime type if needed + if ( options.mimeType && xhr.overrideMimeType ) { + xhr.overrideMimeType( options.mimeType ); + } + + // X-Requested-With header + // For cross-domain requests, seeing as conditions for a preflight are + // akin to a jigsaw puzzle, we simply never set it to be sure. + // (it can always be set on a per-request basis or even using ajaxSetup) + // For same-domain requests, won't change header if already provided. + if ( !options.crossDomain && !headers[ "X-Requested-With" ] ) { + headers[ "X-Requested-With" ] = "XMLHttpRequest"; + } + + // Set headers + for ( i in headers ) { + xhr.setRequestHeader( i, headers[ i ] ); + } + + // Callback + callback = function( type ) { + return function() { + if ( callback ) { + callback = errorCallback = xhr.onload = + xhr.onerror = xhr.onabort = xhr.ontimeout = + xhr.onreadystatechange = null; + + if ( type === "abort" ) { + xhr.abort(); + } else if ( type === "error" ) { + + // Support: IE <=9 only + // On a manual native abort, IE9 throws + // errors on any property access that is not readyState + if ( typeof xhr.status !== "number" ) { + complete( 0, "error" ); + } else { + complete( + + // File: protocol always yields status 0; see #8605, #14207 + xhr.status, + xhr.statusText + ); + } + } else { + complete( + xhrSuccessStatus[ xhr.status ] || xhr.status, + xhr.statusText, + + // Support: IE <=9 only + // IE9 has no XHR2 but throws on binary (trac-11426) + // For XHR2 non-text, let the caller handle it (gh-2498) + ( xhr.responseType || "text" ) !== "text" || + typeof xhr.responseText !== "string" ? + { binary: xhr.response } : + { text: xhr.responseText }, + xhr.getAllResponseHeaders() + ); + } + } + }; + }; + + // Listen to events + xhr.onload = callback(); + errorCallback = xhr.onerror = xhr.ontimeout = callback( "error" ); + + // Support: IE 9 only + // Use onreadystatechange to replace onabort + // to handle uncaught aborts + if ( xhr.onabort !== undefined ) { + xhr.onabort = errorCallback; + } else { + xhr.onreadystatechange = function() { + + // Check readyState before timeout as it changes + if ( xhr.readyState === 4 ) { + + // Allow onerror to be called first, + // but that will not handle a native abort + // Also, save errorCallback to a variable + // as xhr.onerror cannot be accessed + window.setTimeout( function() { + if ( callback ) { + errorCallback(); + } + } ); + } + }; + } + + // Create the abort callback + callback = callback( "abort" ); + + try { + + // Do send the request (this may raise an exception) + xhr.send( options.hasContent && options.data || null ); + } catch ( e ) { + + // #14683: Only rethrow if this hasn't been notified as an error yet + if ( callback ) { + throw e; + } + } + }, + + abort: function() { + if ( callback ) { + callback(); + } + } + }; + } +} ); + + + + +// Prevent auto-execution of scripts when no explicit dataType was provided (See gh-2432) +jQuery.ajaxPrefilter( function( s ) { + if ( s.crossDomain ) { + s.contents.script = false; + } +} ); + +// Install script dataType +jQuery.ajaxSetup( { + accepts: { + script: "text/javascript, application/javascript, " + + "application/ecmascript, application/x-ecmascript" + }, + contents: { + script: /\b(?:java|ecma)script\b/ + }, + converters: { + "text script": function( text ) { + jQuery.globalEval( text ); + return text; + } + } +} ); + +// Handle cache's special case and crossDomain +jQuery.ajaxPrefilter( "script", function( s ) { + if ( s.cache === undefined ) { + s.cache = false; + } + if ( s.crossDomain ) { + s.type = "GET"; + } +} ); + +// Bind script tag hack transport +jQuery.ajaxTransport( "script", function( s ) { + + // This transport only deals with cross domain or forced-by-attrs requests + if ( s.crossDomain || s.scriptAttrs ) { + var script, callback; + return { + send: function( _, complete ) { + script = jQuery( " + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for an unstable version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

CHANGELOG

+
+

3.26.0

+

March 13, 2023

+
+

Features

+
    +
  • Add support for execution profiles in execute_concurrent (PR 1122)

  • +
+
+
+

Bug Fixes

+
    +
  • Handle empty non-final result pages (PR 1110)

  • +
  • Do not re-use stream IDs for in-flight requests (PR 1114)

  • +
  • Asyncore race condition cause logging exception on shutdown (PYTHON-1266)

  • +
+
+
+

Others

+
    +
  • Fix deprecation warning in query tracing (PR 1103)

  • +
  • Remove mutable default values from some tests (PR 1116)

  • +
  • Remove dependency on unittest2 (PYTHON-1289)

  • +
  • Fix deprecation warnings for asyncio.coroutine annotation in asyncioreactor (PYTTHON-1290)

  • +
  • Fix typos in source files (PR 1126)

  • +
  • HostFilterPolicyInitTest fix for Python 3.11 (PR 1131)

  • +
  • Fix for DontPrepareOnIgnoredHostsTest (PYTHON-1287)

  • +
  • tests.integration.simulacron.test_connection failures (PYTHON-1304)

  • +
  • tests.integration.standard.test_single_interface.py appears to be failing for C* 4.0 (PYTHON-1329)

  • +
  • Authentication tests appear to be failing fraudulently (PYTHON-1328)

  • +
  • PreparedStatementTests.test_fail_if_different_query_id_on_reprepare() failing unexpectedly (PTYHON-1327)

  • +
  • Refactor deprecated unittest aliases for Python 3.11 compatibility (PR 1112)

  • +
+
+
+

Deprecations

+
    +
  • This release removes support for Python 2.7.x as well as Python 3.5.x and 3.6.x

  • +
+
+
+
+

3.25.0

+

March 18, 2021

+
+

Features

+
    +
  • Ensure the driver can connect when invalid peer hosts are in system.peers (PYTHON-1260)

  • +
  • Implement protocol v5 checksumming (PYTHON-1258)

  • +
  • Fix the default cqlengine connection mechanism to work with Astra (PYTHON-1265)

  • +
+
+
+

Bug Fixes

+
    +
  • Asyncore race condition cause logging exception on shutdown (PYTHON-1266)

  • +
  • Update list of reserved keywords (PYTHON-1269)

  • +
+
+
+

Others

+
    +
  • Drop Python 3.4 support (PYTHON-1220)

  • +
  • Update security documentation and examples to use PROTOCOL_TLS (PYTHON-1264)

  • +
+
+
+
+

3.24.0

+

June 18, 2020

+
+

Features

+
    +
  • Make geomet an optional dependency at runtime (PYTHON-1237)

  • +
  • Add use_default_tempdir cloud config options (PYTHON-1245)

  • +
  • Tcp flow control for libevreactor (PYTHON-1248)

  • +
+
+
+

Bug Fixes

+
    +
  • Unable to connect to a cloud cluster using Ubuntu 20.04 (PYTHON-1238)

  • +
  • PlainTextAuthProvider fails with unicode chars and Python3 (PYTHON-1241)

  • +
  • [GRAPH] Graph execution profiles consistency level are not set to LOCAL_QUORUM with a cloud cluster (PYTHON-1240)

  • +
  • [GRAPH] Can’t write data in a Boolean field using the Fluent API (PYTHON-1239)

  • +
  • [GRAPH] Fix elementMap() result deserialization (PYTHON-1233)

  • +
+
+
+

Others

+
    +
  • Bump geomet dependency version to 0.2 (PYTHON-1243)

  • +
  • Bump gremlinpython dependency version to 3.4.6 (PYTHON-1212)

  • +
  • Improve fluent graph documentation for core graphs (PYTHON-1244)

  • +
+
+
+
+

3.23.0

+

April 6, 2020

+
+

Features

+
    +
  • Transient Replication Support (PYTHON-1207)

  • +
  • Support system.peers_v2 and port discovery for C* 4.0 (PYTHON-700)

  • +
+
+
+

Bug Fixes

+
    +
  • Asyncore logging exception on shutdown (PYTHON-1228)

  • +
+
+
+
+

3.22.0

+

February 26, 2020

+
+

Features

+
    +
  • Add all() function to the ResultSet API (PYTHON-1203)

  • +
  • Parse new schema metadata in NGDG and generate table edges CQL syntax (PYTHON-996)

  • +
  • Add GraphSON3 support (PYTHON-788)

  • +
  • Use GraphSON3 as default for Native graphs (PYTHON-1004)

  • +
  • Add Tuple and UDT types for native graph (PYTHON-1005)

  • +
  • Add Duration type for native graph (PYTHON-1000)

  • +
  • Add gx:ByteBuffer graphson type support for Blob field (PYTHON-1027)

  • +
  • Enable Paging Through DSE Driver for Gremlin Traversals (PYTHON-1045)

  • +
  • Provide numerical wrappers to ensure proper graphson schema definition (PYTHON-1051)

  • +
  • Resolve the row_factory automatically for native graphs (PYTHON-1056)

  • +
  • Add g:TraversalMetrics/g:Metrics graph deserializers (PYTHON-1057)

  • +
  • Add g:BulkSet graph deserializers (PYTHON-1060)

  • +
  • Update Graph Engine names and the way to create a Classic/Native Graph (PYTHON-1090)

  • +
  • Update Native to Core Graph Engine

  • +
  • Add graphson3 and native graph support (PYTHON-1039)

  • +
  • Enable Paging Through DSE Driver for Gremlin Traversals (PYTHON-1045)

  • +
  • Expose filter predicates for cql collections (PYTHON-1019)

  • +
  • Add g:TraversalMetrics/Metrics deserializers (PYTHON-1057)

  • +
  • Make graph metadata handling more robust (PYTHON-1204)

  • +
+
+
+

Bug Fixes

+
    +
  • Make sure to only query the native_transport_address column with DSE (PYTHON-1205)

  • +
+
+
+
+

3.21.0

+

January 15, 2020

+
+

Features

+
    +
  • Unified driver: merge core and DSE drivers into a single package (PYTHON-1130)

  • +
  • Add Python 3.8 support (PYTHON-1189)

  • +
  • Allow passing ssl context for Twisted (PYTHON-1161)

  • +
  • Ssl context and cloud support for Eventlet (PYTHON-1162)

  • +
  • Cloud Twisted support (PYTHON-1163)

  • +
  • Add additional_write_policy and read_repair to system schema parsing (PYTHON-1048)

  • +
  • Flexible version parsing (PYTHON-1174)

  • +
  • Support NULL in collection deserializer (PYTHON-1123)

  • +
  • [GRAPH] Ability to execute Fluent Graph queries asynchronously (PYTHON-1129)

  • +
+
+
+

Bug Fixes

+
    +
  • Handle prepared id mismatch when repreparing on the fly (PYTHON-1124)

  • +
  • re-raising the CQLEngineException will fail on Python 3 (PYTHON-1166)

  • +
  • asyncio message chunks can be processed discontinuously (PYTHON-1185)

  • +
  • Reconnect attempts persist after downed node removed from peers (PYTHON-1181)

  • +
  • Connection fails to validate ssl certificate hostname when SSLContext.check_hostname is set (PYTHON-1186)

  • +
  • ResponseFuture._set_result crashes on connection error when used with PrepareMessage (PYTHON-1187)

  • +
  • Insights fail to serialize the startup message when the SSL Context is from PyOpenSSL (PYTHON-1192)

  • +
+
+
+

Others

+
    +
  • The driver has a new dependency: geomet. It comes from the dse-driver unification and +is used to support DSE geo types.

  • +
  • Remove *read_repair_chance table options (PYTHON-1140)

  • +
  • Avoid warnings about unspecified load balancing policy when connecting to a cloud cluster (PYTHON-1177)

  • +
  • Add new DSE CQL keywords (PYTHON-1122)

  • +
  • Publish binary wheel distributions (PYTHON-1013)

  • +
+
+
+

Deprecations

+
    +
  • DSELoadBalancingPolicy will be removed in the next major, consider using +the DefaultLoadBalancingPolicy.

  • +
+

Merged from dse-driver:

+
+
+

Features

+
    +
  • Insights integration (PYTHON-1047)

  • +
  • Graph execution profiles should preserve their graph_source when graph_options is overridden (PYTHON-1021)

  • +
  • Add NodeSync metadata (PYTHON-799)

  • +
  • Add new NodeSync failure values (PYTHON-934)

  • +
  • DETERMINISTIC and MONOTONIC Clauses for Functions and Aggregates (PYTHON-955)

  • +
  • GraphOptions should show a warning for unknown parameters (PYTHON-819)

  • +
  • DSE protocol version 2 and continous paging backpressure (PYTHON-798)

  • +
  • GraphSON2 Serialization/Deserialization Support (PYTHON-775)

  • +
  • Add graph-results payload option for GraphSON format (PYTHON-773)

  • +
  • Create an AuthProvider for the DSE transitional mode (PYTHON-831)

  • +
  • Implement serializers for the Graph String API (PYTHON-778)

  • +
  • Provide deserializers for GraphSON types (PYTHON-782)

  • +
  • Add Graph DurationType support (PYTHON-607)

  • +
  • Support DSE DateRange type (PYTHON-668)

  • +
  • RLAC CQL output for materialized views (PYTHON-682)

  • +
  • Add Geom Types wkt deserializer

  • +
  • DSE Graph Client timeouts in custom payload (PYTHON-589)

  • +
  • Make DSEGSSAPIAuthProvider accept principal name (PYTHON-574)

  • +
  • Add config profiles to DSE graph execution (PYTHON-570)

  • +
  • DSE Driver version checking (PYTHON-568)

  • +
  • Distinct default timeout for graph queries (PYTHON-477)

  • +
  • Graph result parsing for known types (PYTHON-479,487)

  • +
  • Distinct read/write CL for graph execution (PYTHON-509)

  • +
  • Target graph analytics query to spark master when available (PYTHON-510)

  • +
+
+
+

Bug Fixes

+
    +
  • Continuous paging sessions raise RuntimeError when results are not entirely consumed (PYTHON-1054)

  • +
  • GraphSON Property deserializer should return a dict instead of a set (PYTHON-1033)

  • +
  • ResponseFuture.has_more_pages may hold the wrong value (PYTHON-946)

  • +
  • DETERMINISTIC clause in AGGREGATE misplaced in CQL generation (PYTHON-963)

  • +
  • graph module import cause a DLL issue on Windows due to its cythonizing failure (PYTHON-900)

  • +
  • Update date serialization to isoformat in graph (PYTHON-805)

  • +
  • DateRange Parse Error (PYTHON-729)

  • +
  • MontonicTimestampGenerator.__init__ ignores class defaults (PYTHON-728)

  • +
  • metadata.get_host returning None unexpectedly (PYTHON-709)

  • +
  • Sockets associated with sessions not getting cleaned up on session.shutdown() (PYTHON-673)

  • +
  • Resolve FQDN from ip address and use that as host passed to SASLClient (PYTHON-566)

  • +
  • Geospatial type implementations don’t handle ‘EMPTY’ values. (PYTHON-481)

  • +
  • Correctly handle other types in geo type equality (PYTHON-508)

  • +
+
+
+

Other

+
    +
  • Add tests around cqlengine and continuous paging (PYTHON-872)

  • +
  • Add an abstract GraphStatement to handle different graph statements (PYTHON-789)

  • +
  • Write documentation examples for DSE 2.0 features (PYTHON-732)

  • +
  • DSE_V1 protocol should not include all of protocol v5 (PYTHON-694)

  • +
+
+
+
+

3.20.2

+

November 19, 2019

+
+

Bug Fixes

+
    +
  • Fix import error for old python installation without SSLContext (PYTHON-1183)

  • +
+
+
+
+

3.20.1

+

November 6, 2019

+
+

Bug Fixes

+
    +
  • ValueError: too many values to unpack (expected 2)” when there are two dashes in server version number (PYTHON-1172)

  • +
+
+
+
+

3.20.0

+

October 28, 2019

+
+

Features

+
    +
  • DataStax Astra Support (PYTHON-1074)

  • +
  • Use 4.0 schema parser in 4 alpha and snapshot builds (PYTHON-1158)

  • +
+
+
+

Bug Fixes

+
    +
  • Connection setup methods prevent using ExecutionProfile in cqlengine (PYTHON-1009)

  • +
  • Driver deadlock if all connections dropped by heartbeat whilst request in flight and request times out (PYTHON-1044)

  • +
  • Exception when use pk__token__gt filter In python 3.7 (PYTHON-1121)

  • +
+
+
+
+

3.19.0

+

August 26, 2019

+
+

Features

+
    +
  • Add Python 3.7 support (PYTHON-1016)

  • +
  • Future-proof Mapping imports (PYTHON-1023)

  • +
  • Include param values in cqlengine logging (PYTHON-1105)

  • +
  • NTS Token Replica Map Generation is slow (PYTHON-622)

  • +
+
+
+

Bug Fixes

+
    +
  • as_cql_query UDF/UDA parameters incorrectly includes “frozen” if arguments are collections (PYTHON-1031)

  • +
  • cqlengine does not currently support combining TTL and TIMESTAMP on INSERT (PYTHON-1093)

  • +
  • Fix incorrect metadata for compact counter tables (PYTHON-1100)

  • +
  • Call ConnectionException with correct kwargs (PYTHON-1117)

  • +
  • Can’t connect to clusters built from source because version parsing doesn’t handle ‘x.y-SNAPSHOT’ (PYTHON-1118)

  • +
  • Discovered node doesn´t honor the configured Cluster port on connection (PYTHON-1127)

  • +
  • Exception when use pk__token__gt filter In python 3.7 (PYTHON-1121)

  • +
+
+
+

Other

+
    +
  • Remove invalid warning in set_session when we initialize a default connection (PYTHON-1104)

  • +
  • Set the proper default ExecutionProfile.row_factory value (PYTHON-1119)

  • +
+
+
+
+

3.18.0

+

May 27, 2019

+
+

Features

+
    +
  • Abstract Host Connection information (PYTHON-1079)

  • +
  • Improve version parsing to support a non-integer 4th component (PYTHON-1091)

  • +
  • Expose on_request_error method in the RetryPolicy (PYTHON-1064)

  • +
  • Add jitter to ExponentialReconnectionPolicy (PYTHON-1065)

  • +
+
+
+

Bug Fixes

+
    +
  • Fix error when preparing queries with beta protocol v5 (PYTHON-1081)

  • +
  • Accept legacy empty strings as column names (PYTHON-1082)

  • +
  • Let util.SortedSet handle uncomparable elements (PYTHON-1087)

  • +
+
+
+
+

3.17.1

+

May 2, 2019

+
+

Bug Fixes

+
    +
  • Socket errors EAGAIN/EWOULDBLOCK are not handled properly and cause timeouts (PYTHON-1089)

  • +
+
+
+
+

3.17.0

+

February 19, 2019

+
+

Features

+
    +
  • Send driver name and version in startup message (PYTHON-1068)

  • +
  • Add Cluster ssl_context option to enable SSL (PYTHON-995)

  • +
  • Allow encrypted private keys for 2-way SSL cluster connections (PYTHON-995)

  • +
  • Introduce new method ConsistencyLevel.is_serial (PYTHON-1067)

  • +
  • Add Session.get_execution_profile (PYTHON-932)

  • +
  • Add host kwarg to Session.execute/execute_async APIs to send a query to a specific node (PYTHON-993)

  • +
+
+
+

Bug Fixes

+
    +
  • NoHostAvailable when all hosts are up and connectable (PYTHON-891)

  • +
  • Serial consistency level is not used (PYTHON-1007)

  • +
+
+
+

Other

+
    +
  • Fail faster on incorrect lz4 import (PYTHON-1042)

  • +
  • Bump Cython dependency version to 0.29 (PYTHON-1036)

  • +
  • Expand Driver SSL Documentation (PYTHON-740)

  • +
+
+
+

Deprecations

+
    +
  • Using Cluster.ssl_options to enable SSL is deprecated and will be removed in +the next major release, use ssl_context.

  • +
  • DowngradingConsistencyRetryPolicy is deprecated and will be +removed in the next major release. (PYTHON-937)

  • +
+
+
+
+

3.16.0

+

November 12, 2018

+
+

Bug Fixes

+
    +
  • Improve and fix socket error-catching code in nonblocking-socket reactors (PYTHON-1024)

  • +
  • Non-ASCII characters in schema break CQL string generation (PYTHON-1008)

  • +
  • Fix OSS driver’s virtual table support against DSE 6.0.X and future server releases (PYTHON-1020)

  • +
  • ResultSet.one() fails if the row_factory is using a generator (PYTHON-1026)

  • +
  • Log profile name on attempt to create existing profile (PYTHON-944)

  • +
  • Cluster instantiation fails if any contact points’ hostname resolution fails (PYTHON-895)

  • +
+
+
+

Other

+
    +
  • Fix tests when RF is not maintained if we decomission a node (PYTHON-1017)

  • +
  • Fix wrong use of ResultSet indexing (PYTHON-1015)

  • +
+
+
+
+

3.15.1

+

September 6, 2018

+
+

Bug Fixes

+
    +
  • C* 4.0 schema-parsing logic breaks running against DSE 6.0.X (PYTHON-1018)

  • +
+
+
+
+

3.15.0

+

August 30, 2018

+
+

Features

+
    +
  • Parse Virtual Keyspace Metadata (PYTHON-992)

  • +
+
+
+

Bug Fixes

+
    +
  • Tokenmap.get_replicas returns the wrong value if token coincides with the end of the range (PYTHON-978)

  • +
  • Python Driver fails with “more than 255 arguments” python exception when > 255 columns specified in query response (PYTHON-893)

  • +
  • Hang in integration.standard.test_cluster.ClusterTests.test_set_keyspace_twice (PYTHON-998)

  • +
  • Asyncore reactors should use a global variable instead of a class variable for the event loop (PYTHON-697)

  • +
+
+
+

Other

+
    +
  • Use global variable for libev loops so it can be subclassed (PYTHON-973)

  • +
  • Update SchemaParser for V4 (PYTHON-1006)

  • +
  • Bump Cython dependency version to 0.28 (PYTHON-1012)

  • +
+
+
+
+

3.14.0

+

April 17, 2018

+
+

Features

+
    +
  • Add one() function to the ResultSet API (PYTHON-947)

  • +
  • Create an utility function to fetch concurrently many keys from the same replica (PYTHON-647)

  • +
  • Allow filter queries with fields that have an index managed outside of cqlengine (PYTHON-966)

  • +
  • Twisted SSL Support (PYTHON-343)

  • +
  • Support IS NOT NULL operator in cqlengine (PYTHON-968)

  • +
+
+
+

Other

+
    +
  • Fix Broken Links in Docs (PYTHON-916)

  • +
  • Reevaluate MONKEY_PATCH_LOOP in test codebase (PYTHON-903)

  • +
  • Remove CASS_SERVER_VERSION and replace it for CASSANDRA_VERSION in tests (PYTHON-910)

  • +
  • Refactor CASSANDRA_VERSION to a some kind of version object (PYTHON-915)

  • +
  • Log warning when driver configures an authenticator, but server does not request authentication (PYTHON-940)

  • +
  • Warn users when using the deprecated Session.default_consistency_level (PYTHON-953)

  • +
  • Add DSE smoke test to OSS driver tests (PYTHON-894)

  • +
  • Document long compilation times and workarounds (PYTHON-868)

  • +
  • Improve error for batch WriteTimeouts (PYTHON-941)

  • +
  • Deprecate ResultSet indexing (PYTHON-945)

  • +
+
+
+
+

3.13.0

+

January 30, 2018

+
+

Features

+
    +
  • cqlengine: LIKE filter operator (PYTHON-512)

  • +
  • Support cassandra.query.BatchType with cqlengine BatchQuery (PYTHON-888)

  • +
+
+
+

Bug Fixes

+
    +
  • AttributeError: ‘NoneType’ object has no attribute ‘add_timer’ (PYTHON-862)

  • +
  • Support retry_policy in PreparedStatement (PYTHON-861)

  • +
  • __del__ method in Session is throwing an exception (PYTHON-813)

  • +
  • LZ4 import issue with recent versions (PYTHON-897)

  • +
  • ResponseFuture._connection can be None when returning request_id (PYTHON-853)

  • +
  • ResultSet.was_applied doesn’t support batch with LWT statements (PYTHON-848)

  • +
+
+
+

Other

+
    +
  • cqlengine: avoid warning when unregistering connection on shutdown (PYTHON-865)

  • +
  • Fix DeprecationWarning of log.warn (PYTHON-846)

  • +
  • Fix example_mapper.py for python3 (PYTHON-860)

  • +
  • Possible deadlock on cassandra.concurrent.execute_concurrent (PYTHON-768)

  • +
  • Add some known deprecated warnings for 4.x (PYTHON-877)

  • +
  • Remove copyright dates from copyright notices (PYTHON-863)

  • +
  • Remove “Experimental” tag from execution profiles documentation (PYTHON-840)

  • +
  • request_timer metrics descriptions are slightly incorrect (PYTHON-885)

  • +
  • Remove “Experimental” tag from cqlengine connections documentation (PYTHON-892)

  • +
  • Set in documentation default consistency for operations is LOCAL_ONE (PYTHON-901)

  • +
+
+
+
+

3.12.0

+

November 6, 2017

+
+

Features

+
    +
  • Send keyspace in QUERY, PREPARE, and BATCH messages (PYTHON-678)

  • +
  • Add IPv4Address/IPv6Address support for inet types (PYTHON-751)

  • +
  • WriteType.CDC and VIEW missing (PYTHON-794)

  • +
  • Warn on Cluster init if contact points are specified but LBP isn’t (legacy mode) (PYTHON-812)

  • +
  • Warn on Cluster init if contact points are specified but LBP isn’t (exection profile mode) (PYTHON-838)

  • +
  • Include hash of result set metadata in prepared stmt id (PYTHON-808)

  • +
  • Add NO_COMPACT startup option (PYTHON-839)

  • +
  • Add new exception type for CDC (PYTHON-837)

  • +
  • Allow 0ms in ConstantSpeculativeExecutionPolicy (PYTHON-836)

  • +
  • Add asyncio reactor (PYTHON-507)

  • +
+
+
+

Bug Fixes

+
    +
  • Both _set_final_exception/result called for the same ResponseFuture (PYTHON-630)

  • +
  • Use of DCAwareRoundRobinPolicy raises NoHostAvailable exception (PYTHON-781)

  • +
  • Not create two sessions by default in CQLEngine (PYTHON-814)

  • +
  • Bug when subclassing AyncoreConnection (PYTHON-827)

  • +
  • Error at cleanup when closing the asyncore connections (PYTHON-829)

  • +
  • Fix sites where sessions can change during iteration (PYTHON-793)

  • +
  • cqlengine: allow min_length=0 for Ascii and Text column types (PYTHON-735)

  • +
  • Rare exception when “sys.exit(0)” after query timeouts (PYTHON-752)

  • +
  • Dont set the session keyspace when preparing statements (PYTHON-843)

  • +
  • Use of DCAwareRoundRobinPolicy raises NoHostAvailable exception (PYTHON-781)

  • +
+
+
+

Other

+
    +
  • Remove DeprecationWarning when using WhiteListRoundRobinPolicy (PYTHON-810)

  • +
  • Bump Cython dependency version to 0.27 (PYTHON-833)

  • +
+
+
+
+

3.11.0

+

July 24, 2017

+
+

Features

+
    +
  • Add idle_heartbeat_timeout cluster option to tune how long to wait for heartbeat responses. (PYTHON-762)

  • +
  • Add HostFilterPolicy (PYTHON-761)

  • +
+
+
+

Bug Fixes

+
    +
  • is_idempotent flag is not propagated from PreparedStatement to BoundStatement (PYTHON-736)

  • +
  • Fix asyncore hang on exit (PYTHON-767)

  • +
  • Driver takes several minutes to remove a bad host from session (PYTHON-762)

  • +
  • Installation doesn’t always fall back to no cython in Windows (PYTHON-763)

  • +
  • Avoid to replace a connection that is supposed to shutdown (PYTHON-772)

  • +
  • request_ids may not be returned to the pool (PYTHON-739)

  • +
  • Fix murmur3 on big-endian systems (PYTHON-653)

  • +
  • Ensure unused connections are closed if a Session is deleted by the GC (PYTHON-774)

  • +
  • Fix .values_list by using db names internally (cqlengine) (PYTHON-785)

  • +
+
+
+

Other

+
    +
  • Bump Cython dependency version to 0.25.2 (PYTHON-754)

  • +
  • Fix DeprecationWarning when using lz4 (PYTHON-769)

  • +
  • Deprecate WhiteListRoundRobinPolicy (PYTHON-759)

  • +
  • Improve upgrade guide for materializing pages (PYTHON-464)

  • +
  • Documentation for time/date specifies timestamp inupt as microseconds (PYTHON-717)

  • +
  • Point to DSA Slack, not IRC, in docs index

  • +
+
+
+
+

3.10.0

+

May 24, 2017

+
+

Features

+
    +
  • Add Duration type to cqlengine (PYTHON-750)

  • +
  • Community PR review: Raise error on primary key update only if its value changed (PYTHON-705)

  • +
  • get_query_trace() contract is ambiguous (PYTHON-196)

  • +
+
+
+

Bug Fixes

+
    +
  • Queries using speculative execution policy timeout prematurely (PYTHON-755)

  • +
  • Fix map where results are not consumed (PYTHON-749)

  • +
  • Driver fails to encode Duration’s with large values (PYTHON-747)

  • +
  • UDT values are not updated correctly in CQLEngine (PYTHON-743)

  • +
  • UDT types are not validated in CQLEngine (PYTHON-742)

  • +
  • to_python is not implemented for types columns.Type and columns.Date in CQLEngine (PYTHON-741)

  • +
  • Clients spin infinitely trying to connect to a host that is drained (PYTHON-734)

  • +
  • Resulset.get_query_trace returns empty trace sometimes (PYTHON-730)

  • +
  • Memory grows and doesn’t get removed (PYTHON-720)

  • +
  • Fix RuntimeError caused by change dict size during iteration (PYTHON-708)

  • +
  • fix ExponentialReconnectionPolicy may throw OverflowError problem (PYTHON-707)

  • +
  • Avoid using nonexistent prepared statement in ResponseFuture (PYTHON-706)

  • +
+
+
+

Other

+
    +
  • Update README (PYTHON-746)

  • +
  • Test python versions 3.5 and 3.6 (PYTHON-737)

  • +
  • Docs Warning About Prepare select * (PYTHON-626)

  • +
  • Increase Coverage in CqlEngine Test Suite (PYTHON-505)

  • +
  • Example SSL connection code does not verify server certificates (PYTHON-469)

  • +
+
+
+
+

3.9.0

+
+

Features

+
    +
  • cqlengine: remove elements by key from a map (PYTHON-688)

  • +
+
+
+

Bug Fixes

+
    +
  • improve error handling when connecting to non-existent keyspace (PYTHON-665)

  • +
  • Sockets associated with sessions not getting cleaned up on session.shutdown() (PYTHON-673)

  • +
  • rare flake on integration.standard.test_cluster.ClusterTests.test_clone_shared_lbp (PYTHON-727)

  • +
  • MontonicTimestampGenerator.__init__ ignores class defaults (PYTHON-728)

  • +
  • race where callback or errback for request may not be called (PYTHON-733)

  • +
  • cqlengine: model.update() should not update columns with a default value that hasn’t changed (PYTHON-657)

  • +
  • cqlengine: field value manager’s explicit flag is True when queried back from cassandra (PYTHON-719)

  • +
+
+
+

Other

+
    +
  • Connection not closed in example_mapper (PYTHON-723)

  • +
  • Remove mention of pre-2.0 C* versions from OSS 3.0+ docs (PYTHON-710)

  • +
+
+
+
+

3.8.1

+

March 16, 2017

+
+

Bug Fixes

+
    +
  • implement __le__/__ge__/__ne__ on some custom types (PYTHON-714)

  • +
  • Fix bug in eventlet and gevent reactors that could cause hangs (PYTHON-721)

  • +
  • Fix DecimalType regression (PYTHON-724)

  • +
+
+
+
+

3.8.0

+
+

Features

+
    +
  • Quote index names in metadata CQL generation (PYTHON-616)

  • +
  • On column deserialization failure, keep error message consistent between python and cython (PYTHON-631)

  • +
  • TokenAwarePolicy always sends requests to the same replica for a given key (PYTHON-643)

  • +
  • Added cql types to result set (PYTHON-648)

  • +
  • Add __len__ to BatchStatement (PYTHON-650)

  • +
  • Duration Type for Cassandra (PYTHON-655)

  • +
  • Send flags with PREPARE message in v5 (PYTHON-684)

  • +
+
+
+

Bug Fixes

+
    +
  • Potential Timing issue if application exits prior to session pool initialization (PYTHON-636)

  • +
  • “Host X.X.X.X has been marked down” without any exceptions (PYTHON-640)

  • +
  • NoHostAvailable or OperationTimedOut when using execute_concurrent with a generator that inserts into more than one table (PYTHON-642)

  • +
  • ResponseFuture creates Timers and don’t cancel them even when result is received which leads to memory leaks (PYTHON-644)

  • +
  • Driver cannot connect to Cassandra version > 3 (PYTHON-646)

  • +
  • Unable to import model using UserType without setuping connection since 3.7 (PYTHON-649)

  • +
  • Don’t prepare queries on ignored hosts on_up (PYTHON-669)

  • +
  • Sockets associated with sessions not getting cleaned up on session.shutdown() (PYTHON-673)

  • +
  • Make client timestamps strictly monotonic (PYTHON-676)

  • +
  • cassandra.cqlengine.connection.register_connection broken when hosts=None (PYTHON-692)

  • +
+
+
+

Other

+
    +
  • Create a cqlengine doc section explaining None semantics (PYTHON-623)

  • +
  • Resolve warnings in documentation generation (PYTHON-645)

  • +
  • Cython dependency (PYTHON-686)

  • +
  • Drop Support for Python 2.6 (PYTHON-690)

  • +
+
+
+
+

3.7.1

+

October 26, 2016

+
+

Bug Fixes

+
    +
  • Cython upgrade has broken stable version of cassandra-driver (PYTHON-656)

  • +
+
+
+
+

3.7.0

+

September 13, 2016

+
+

Features

+
    +
  • Add v5 protocol failure map (PYTHON-619)

  • +
  • Don’t return from initial connect on first error (PYTHON-617)

  • +
  • Indicate failed column when deserialization fails (PYTHON-361)

  • +
  • Let Cluster.refresh_nodes force a token map rebuild (PYTHON-349)

  • +
  • Refresh UDTs after “keyspace updated” event with v1/v2 protocol (PYTHON-106)

  • +
  • EC2 Address Resolver (PYTHON-198)

  • +
  • Speculative query retries (PYTHON-218)

  • +
  • Expose paging state in API (PYTHON-200)

  • +
  • Don’t mark host down while one connection is active (PYTHON-498)

  • +
  • Query request size information (PYTHON-284)

  • +
  • Avoid quadratic ring processing with invalid replication factors (PYTHON-379)

  • +
  • Improve Connection/Pool creation concurrency on startup (PYTHON-82)

  • +
  • Add beta version native protocol flag (PYTHON-614)

  • +
  • cqlengine: Connections: support of multiple keyspaces and sessions (PYTHON-613)

  • +
+
+
+

Bug Fixes

+
    +
  • Race when adding a pool while setting keyspace (PYTHON-628)

  • +
  • Update results_metadata when prepared statement is reprepared (PYTHON-621)

  • +
  • CQL Export for Thrift Tables (PYTHON-213)

  • +
  • cqlengine: default value not applied to UserDefinedType (PYTHON-606)

  • +
  • cqlengine: columns are no longer hashable (PYTHON-618)

  • +
  • cqlengine: remove clustering keys from where clause when deleting only static columns (PYTHON-608)

  • +
+
+
+
+

3.6.0

+

August 1, 2016

+
+

Features

+
    +
  • Handle null values in NumpyProtocolHandler (PYTHON-553)

  • +
  • Collect greplin scales stats per cluster (PYTHON-561)

  • +
  • Update mock unit test dependency requirement (PYTHON-591)

  • +
  • Handle Missing CompositeType metadata following C* upgrade (PYTHON-562)

  • +
  • Improve Host.is_up state for HostDistance.IGNORED hosts (PYTHON-551)

  • +
  • Utilize v2 protocol’s ability to skip result set metadata for prepared statement execution (PYTHON-71)

  • +
  • Return from Cluster.connect() when first contact point connection(pool) is opened (PYTHON-105)

  • +
  • cqlengine: Add ContextQuery to allow cqlengine models to switch the keyspace context easily (PYTHON-598)

  • +
  • Standardize Validation between Ascii and Text types in Cqlengine (PYTHON-609)

  • +
+
+
+

Bug Fixes

+
    +
  • Fix geventreactor with SSL support (PYTHON-600)

  • +
  • Don’t downgrade protocol version if explicitly set (PYTHON-537)

  • +
  • Nonexistent contact point tries to connect indefinitely (PYTHON-549)

  • +
  • Execute_concurrent can exceed max recursion depth in failure mode (PYTHON-585)

  • +
  • Libev loop shutdown race (PYTHON-578)

  • +
  • Include aliases in DCT type string (PYTHON-579)

  • +
  • cqlengine: Comparison operators for Columns (PYTHON-595)

  • +
  • cqlengine: disentangle default_time_to_live table option from model query default TTL (PYTHON-538)

  • +
  • cqlengine: pk__token column name issue with the equality operator (PYTHON-584)

  • +
  • cqlengine: Fix “__in” filtering operator converts True to string “True” automatically (PYTHON-596)

  • +
  • cqlengine: Avoid LWTExceptions when updating columns that are part of the condition (PYTHON-580)

  • +
  • cqlengine: Cannot execute a query when the filter contains all columns (PYTHON-599)

  • +
  • cqlengine: routing key computation issue when a primary key column is overriden by model inheritance (PYTHON-576)

  • +
+
+
+
+

3.5.0

+

June 27, 2016

+
+

Features

+
    +
  • Optional Execution Profiles for the core driver (PYTHON-569)

  • +
  • API to get the host metadata associated with the control connection node (PYTHON-583)

  • +
  • Expose CDC option in table metadata CQL (PYTHON-593)

  • +
+
+
+

Bug Fixes

+
    +
  • Clean up Asyncore socket map when fork is detected (PYTHON-577)

  • +
  • cqlengine: QuerySet only() is not respected when there are deferred fields (PYTHON-560)

  • +
+
+
+
+

3.4.1

+

May 26, 2016

+
+

Bug Fixes

+
    +
  • Gevent connection closes on IO timeout (PYTHON-573)

  • +
  • “dictionary changed size during iteration” with Python 3 (PYTHON-572)

  • +
+
+
+
+

3.4.0

+

May 24, 2016

+
+

Features

+
    +
  • Include DSE version and workload in Host data (PYTHON-555)

  • +
  • Add a context manager to Cluster and Session (PYTHON-521)

  • +
  • Better Error Message for Unsupported Protocol Version (PYTHON-157)

  • +
  • Make the error message explicitly state when an error comes from the server (PYTHON-412)

  • +
  • Short Circuit meta refresh on topo change if NEW_NODE already exists (PYTHON-557)

  • +
  • Show warning when the wrong config is passed to SimpleStatement (PYTHON-219)

  • +
  • Return namedtuple result pairs from execute_concurrent (PYTHON-362)

  • +
  • BatchStatement should enforce batch size limit in a better way (PYTHON-151)

  • +
  • Validate min/max request thresholds for connection pool scaling (PYTHON-220)

  • +
  • Handle or warn about multiple hosts with the same rpc_address (PYTHON-365)

  • +
  • Write docs around working with datetime and timezones (PYTHON-394)

  • +
+
+
+

Bug Fixes

+
    +
  • High CPU utilization when using asyncore event loop (PYTHON-239)

  • +
  • Fix CQL Export for non-ASCII Identifiers (PYTHON-447)

  • +
  • Make stress scripts Python 2.6 compatible (PYTHON-434)

  • +
  • UnicodeDecodeError when unicode characters in key in BOP (PYTHON-559)

  • +
  • WhiteListRoundRobinPolicy should resolve hosts (PYTHON-565)

  • +
  • Cluster and Session do not GC after leaving scope (PYTHON-135)

  • +
  • Don’t wait for schema agreement on ignored nodes (PYTHON-531)

  • +
  • Reprepare on_up with many clients causes node overload (PYTHON-556)

  • +
  • None inserted into host map when control connection node is decommissioned (PYTHON-548)

  • +
  • weakref.ref does not accept keyword arguments (github #585)

  • +
+
+
+
+

3.3.0

+

May 2, 2016

+
+

Features

+
    +
  • Add an AddressTranslator interface (PYTHON-69)

  • +
  • New Retry Policy Decision - try next host (PYTHON-285)

  • +
  • Don’t mark host down on timeout (PYTHON-286)

  • +
  • SSL hostname verification (PYTHON-296)

  • +
  • Add C* version to metadata or cluster objects (PYTHON-301)

  • +
  • Options to Disable Schema, Token Metadata Processing (PYTHON-327)

  • +
  • Expose listen_address of node we get ring information from (PYTHON-332)

  • +
  • Use A-record with multiple IPs for contact points (PYTHON-415)

  • +
  • Custom consistency level for populating query traces (PYTHON-435)

  • +
  • Normalize Server Exception Types (PYTHON-443)

  • +
  • Propagate exception message when DDL schema agreement fails (PYTHON-444)

  • +
  • Specialized exceptions for metadata refresh methods failure (PYTHON-527)

  • +
+
+
+

Bug Fixes

+
    +
  • Resolve contact point hostnames to avoid duplicate hosts (PYTHON-103)

  • +
  • GeventConnection stalls requests when read is a multiple of the input buffer size (PYTHON-429)

  • +
  • named_tuple_factory breaks with duplicate “cleaned” col names (PYTHON-467)

  • +
  • Connection leak if Cluster.shutdown() happens during reconnection (PYTHON-482)

  • +
  • HostConnection.borrow_connection does not block when all request ids are used (PYTHON-514)

  • +
  • Empty field not being handled by the NumpyProtocolHandler (PYTHON-550)

  • +
+
+
+
+

3.2.2

+

April 19, 2016

+
    +
  • Fix counter save-after-no-update (PYTHON-547)

  • +
+
+
+

3.2.1

+

April 13, 2016

+
    +
  • Introduced an update to allow deserializer compilation with recently released Cython 0.24 (PYTHON-542)

  • +
+
+
+

3.2.0

+

April 12, 2016

+
+

Features

+
    +
  • cqlengine: Warn on sync_schema type mismatch (PYTHON-260)

  • +
  • cqlengine: Automatically defer fields with the ‘=’ operator (and immutable values) in select queries (PYTHON-520)

  • +
  • cqlengine: support non-equal conditions for LWT (PYTHON-528)

  • +
  • cqlengine: sync_table should validate the primary key composition (PYTHON-532)

  • +
  • cqlengine: token-aware routing for mapper statements (PYTHON-535)

  • +
+
+
+

Bug Fixes

+
    +
  • Deleting a column in a lightweight transaction raises a SyntaxException #325 (PYTHON-249)

  • +
  • cqlengine: make Token function works with named tables/columns #86 (PYTHON-272)

  • +
  • comparing models with datetime fields fail #79 (PYTHON-273)

  • +
  • cython date deserializer integer math should be aligned with CPython (PYTHON-480)

  • +
  • db_field is not always respected with UpdateStatement (PYTHON-530)

  • +
  • Sync_table fails on column.Set with secondary index (PYTHON-533)

  • +
+
+
+
+

3.1.1

+

March 14, 2016

+
+

Bug Fixes

+
    +
  • cqlengine: Fix performance issue related to additional “COUNT” queries (PYTHON-522)

  • +
+
+
+
+

3.1.0

+

March 10, 2016

+
+

Features

+
    +
  • Pass name of server auth class to AuthProvider (PYTHON-454)

  • +
  • Surface schema agreed flag for DDL statements (PYTHON-458)

  • +
  • Automatically convert float and int to Decimal on serialization (PYTHON-468)

  • +
  • Eventlet Reactor IO improvement (PYTHON-495)

  • +
  • Make pure Python ProtocolHandler available even when Cython is present (PYTHON-501)

  • +
  • Optional Cython deserializer for bytes as bytearray (PYTHON-503)

  • +
  • Add Session.default_serial_consistency_level (github #510)

  • +
  • cqlengine: Expose prior state information via cqlengine LWTException (github #343, PYTHON-336)

  • +
  • cqlengine: Collection datatype “contains” operators support (Cassandra 2.1) #278 (PYTHON-258)

  • +
  • cqlengine: Add DISTINCT query operator (PYTHON-266)

  • +
  • cqlengine: Tuple cqlengine api (PYTHON-306)

  • +
  • cqlengine: Add support for UPDATE/DELETE … IF EXISTS statements (PYTHON-432)

  • +
  • cqlengine: Allow nested container types (PYTHON-478)

  • +
  • cqlengine: Add ability to set query’s fetch_size and limit (PYTHON-323)

  • +
  • cqlengine: Internalize default keyspace from successive set_session (PYTHON-486)

  • +
  • cqlengine: Warn when Model.create() on Counters (to be deprecated) (PYTHON-333)

  • +
+
+
+

Bug Fixes

+
    +
  • Bus error (alignment issues) when running cython on some ARM platforms (PYTHON-450)

  • +
  • Overflow when decoding large collections (cython) (PYTHON-459)

  • +
  • Timer heap comparison issue with Python 3 (github #466)

  • +
  • Cython deserializer date overflow at 2^31 - 1 (PYTHON-452)

  • +
  • Decode error encountered when cython deserializing large map results (PYTHON-459)

  • +
  • Don’t require Cython for build if compiler or Python header not present (PYTHON-471)

  • +
  • Unorderable types in task scheduling with Python 3 (h(PYTHON-473)

  • +
  • cqlengine: Fix crash when updating a UDT column with a None value (github #467)

  • +
  • cqlengine: Race condition in ..connection.execute with lazy_connect (PYTHON-310)

  • +
  • cqlengine: doesn’t support case sensitive column family names (PYTHON-337)

  • +
  • cqlengine: UserDefinedType mandatory in create or update (PYTHON-344)

  • +
  • cqlengine: db_field breaks UserType (PYTHON-346)

  • +
  • cqlengine: UDT badly quoted (PYTHON-347)

  • +
  • cqlengine: Use of db_field on primary key prevents querying except while tracing. (PYTHON-351)

  • +
  • cqlengine: DateType.deserialize being called with one argument vs two (PYTHON-354)

  • +
  • cqlengine: Querying without setting up connection now throws AttributeError and not CQLEngineException (PYTHON-395)

  • +
  • cqlengine: BatchQuery multiple time executing execute statements. (PYTHON-445)

  • +
  • cqlengine: Better error for management functions when no connection set (PYTHON-451)

  • +
  • cqlengine: Handle None values for UDT attributes in cqlengine (PYTHON-470)

  • +
  • cqlengine: Fix inserting None for model save (PYTHON-475)

  • +
  • cqlengine: EQ doesn’t map to a QueryOperator (setup race condition) (PYTHON-476)

  • +
  • cqlengine: class.MultipleObjectsReturned has DoesNotExist as base class (PYTHON-489)

  • +
  • cqlengine: Typo in cqlengine UserType __len__ breaks attribute assignment (PYTHON-502)

  • +
+
+
+

Other

+
    +
  • cqlengine: a major improvement on queryset has been introduced. It +is a lot more efficient to iterate large datasets: the rows are +now fetched on demand using the driver pagination.

  • +
  • cqlengine: the queryset len() and count() behaviors have changed. It +now executes a “SELECT COUNT(*)” of the query rather than returning +the size of the internal result_cache (loaded rows). On large +queryset, you might want to avoid using them due to the performance +cost. Note that trying to access objects using list index/slicing +with negative indices also requires a count to be +executed.

  • +
+
+
+
+

3.0.0

+

November 24, 2015

+
+

Features

+
    +
  • Support datetime.date objects as a DateType (PYTHON-212)

  • +
  • Add Cluster.update_view_metadata (PYTHON-407)

  • +
  • QueryTrace option to populate partial trace sessions (PYTHON-438)

  • +
  • Attach column names to ResultSet (PYTHON-439)

  • +
  • Change default consistency level to LOCAL_ONE

  • +
+
+
+

Bug Fixes

+
    +
  • Properly SerDes nested collections when protocol_version < 3 (PYTHON-215)

  • +
  • Evict UDTs from UserType cache on change (PYTHON-226)

  • +
  • Make sure query strings are always encoded UTF-8 (PYTHON-334)

  • +
  • Track previous value of columns at instantiation in CQLengine (PYTHON-348)

  • +
  • UDT CQL encoding does not work for unicode values (PYTHON-353)

  • +
  • NetworkTopologyStrategy#make_token_replica_map does not account for multiple racks in a DC (PYTHON-378)

  • +
  • Cython integer overflow on decimal type deserialization (PYTHON-433)

  • +
  • Query trace: if session hasn’t been logged, query trace can throw exception (PYTHON-442)

  • +
+
+
+
+

3.0.0rc1

+

November 9, 2015

+
+

Features

+
    +
  • Process Modernized Schema Tables for Cassandra 3.0 (PYTHON-276, PYTHON-408, PYTHON-400, PYTHON-422)

  • +
  • Remove deprecated features (PYTHON-292)

  • +
  • Don’t assign trace data to Statements (PYTHON-318)

  • +
  • Normalize results return (PYTHON-368)

  • +
  • Process Materialized View Metadata/Events (PYTHON-371)

  • +
  • Remove blist as soft dependency (PYTHON-385)

  • +
  • Change default consistency level to LOCAL_QUORUM (PYTHON-416)

  • +
  • Normalize CQL query/export in metadata model (PYTHON-405)

  • +
+
+
+

Bug Fixes

+
    +
  • Implementation of named arguments bind is non-pythonic (PYTHON-178)

  • +
  • CQL encoding is incorrect for NaN and Infinity floats (PYTHON-282)

  • +
  • Protocol downgrade issue with C* 2.0.x, 2.1.x, and python3, with non-default logging (PYTHON-409)

  • +
  • ValueError when accessing usertype with non-alphanumeric field names (PYTHON-413)

  • +
  • NumpyProtocolHandler does not play well with PagedResult (PYTHON-430)

  • +
+
+
+
+

2.7.2

+

September 14, 2015

+
+

Bug Fixes

+
    +
  • Resolve CQL export error for UDF with zero parameters (PYTHON-392)

  • +
  • Remove futures dep. for Python 3 (PYTHON-393)

  • +
  • Avoid Python closure in cdef (supports earlier Cython compiler) (PYTHON-396)

  • +
  • Unit test runtime issues (PYTHON-397,398)

  • +
+
+
+
+

2.7.1

+

August 25, 2015

+
+

Bug Fixes

+
    +
  • Explicitly include extension source files in Manifest

  • +
+
+
+
+

2.7.0

+

August 25, 2015

+

Cython is introduced, providing compiled extensions for core modules, and +extensions for optimized results deserialization.

+
+

Features

+
    +
  • General Performance Improvements for Throughput (PYTHON-283)

  • +
  • Improve synchronous request performance with Timers (PYTHON-108)

  • +
  • Enable C Extensions for PyPy Runtime (PYTHON-357)

  • +
  • Refactor SerDes functionality for pluggable interface (PYTHON-313)

  • +
  • Cython SerDes Extension (PYTHON-377)

  • +
  • Accept iterators/generators for execute_concurrent() (PYTHON-123)

  • +
  • cythonize existing modules (PYTHON-342)

  • +
  • Pure Python murmur3 implementation (PYTHON-363)

  • +
  • Make driver tolerant of inconsistent metadata (PYTHON-370)

  • +
+
+
+

Bug Fixes

+
    +
  • Drop Events out-of-order Cause KeyError on Processing (PYTHON-358)

  • +
  • DowngradingConsistencyRetryPolicy doesn’t check response count on write timeouts (PYTHON-338)

  • +
  • Blocking connect does not use connect_timeout (PYTHON-381)

  • +
  • Properly protect partition key in CQL export (PYTHON-375)

  • +
  • Trigger error callbacks on timeout (PYTHON-294)

  • +
+
+
+
+

2.6.0

+

July 20, 2015

+
+

Bug Fixes

+
    +
  • Output proper CQL for compact tables with no clustering columns (PYTHON-360)

  • +
+
+
+
+

2.6.0c2

+

June 24, 2015

+
+

Features

+
    +
  • Automatic Protocol Version Downgrade (PYTHON-240)

  • +
  • cqlengine Python 2.6 compatibility (PYTHON-288)

  • +
  • Double-dollar string quote UDF body (PYTHON-345)

  • +
  • Set models.DEFAULT_KEYSPACE when calling set_session (github #352)

  • +
+
+
+

Bug Fixes

+
    +
  • Avoid stall while connecting to mixed version cluster (PYTHON-303)

  • +
  • Make SSL work with AsyncoreConnection in python 2.6.9 (PYTHON-322)

  • +
  • Fix Murmur3Token.from_key() on Windows (PYTHON-331)

  • +
  • Fix cqlengine TimeUUID rounding error for Windows (PYTHON-341)

  • +
  • Avoid invalid compaction options in CQL export for non-SizeTiered (PYTHON-352)

  • +
+
+
+
+

2.6.0c1

+

June 4, 2015

+

This release adds support for Cassandra 2.2 features, including version +4 of the native protocol.

+
+

Features

+
    +
  • Default load balancing policy to TokenAware(DCAware) (PYTHON-160)

  • +
  • Configuration option for connection timeout (PYTHON-206)

  • +
  • Support User Defined Function and Aggregate metadata in C* 2.2 (PYTHON-211)

  • +
  • Surface request client in QueryTrace for C* 2.2+ (PYTHON-235)

  • +
  • Implement new request failure messages in protocol v4+ (PYTHON-238)

  • +
  • Metadata model now maps index meta by index name (PYTHON-241)

  • +
  • Support new types in C* 2.2: date, time, smallint, tinyint (PYTHON-245, 295)

  • +
  • cqle: add Double column type and remove Float overload (PYTHON-246)

  • +
  • Use partition key column information in prepared response for protocol v4+ (PYTHON-277)

  • +
  • Support message custom payloads in protocol v4+ (PYTHON-280, PYTHON-329)

  • +
  • Deprecate refresh_schema and replace with functions for specific entities (PYTHON-291)

  • +
  • Save trace id even when trace complete times out (PYTHON-302)

  • +
  • Warn when registering client UDT class for protocol < v3 (PYTHON-305)

  • +
  • Support client warnings returned with messages in protocol v4+ (PYTHON-315)

  • +
  • Ability to distinguish between NULL and UNSET values in protocol v4+ (PYTHON-317)

  • +
  • Expose CQL keywords in API (PYTHON-324)

  • +
+
+
+

Bug Fixes

+
    +
  • IPv6 address support on Windows (PYTHON-20)

  • +
  • Convert exceptions during automatic re-preparation to nice exceptions (PYTHON-207)

  • +
  • cqle: Quote keywords properly in table management functions (PYTHON-244)

  • +
  • Don’t default to GeventConnection when gevent is loaded, but not monkey-patched (PYTHON-289)

  • +
  • Pass dynamic host from SaslAuthProvider to SaslAuthenticator (PYTHON-300)

  • +
  • Make protocol read_inet work for Windows (PYTHON-309)

  • +
  • cqle: Correct encoding for nested types (PYTHON-311)

  • +
  • Update list of CQL keywords used quoting identifiers (PYTHON-319)

  • +
  • Make ConstantReconnectionPolicy work with infinite retries (github #327, PYTHON-325)

  • +
  • Accept UUIDs with uppercase hex as valid in cqlengine (github #335)

  • +
+
+
+
+

2.5.1

+

April 23, 2015

+
+

Bug Fixes

+
    +
  • Fix thread safety in DC-aware load balancing policy (PYTHON-297)

  • +
  • Fix race condition in node/token rebuild (PYTHON-298)

  • +
  • Set and send serial consistency parameter (PYTHON-299)

  • +
+
+
+
+

2.5.0

+

March 30, 2015

+
+

Features

+
    +
  • Integrated cqlengine object mapping package

  • +
  • Utility functions for converting timeuuids and datetime (PYTHON-99)

  • +
  • Schema metadata fetch window randomized, config options added (PYTHON-202)

  • +
  • Support for new Date and Time Cassandra types (PYTHON-190)

  • +
+
+
+

Bug Fixes

+
    +
  • Fix index target for collection indexes (full(), keys()) (PYTHON-222)

  • +
  • Thread exception during GIL cleanup (PYTHON-229)

  • +
  • Workaround for rounding anomaly in datetime.utcfromtime (Python 3.4) (PYTHON-230)

  • +
  • Normalize text serialization for lookup in OrderedMap (PYTHON-231)

  • +
  • Support reading CompositeType data (PYTHON-234)

  • +
  • Preserve float precision in CQL encoding (PYTHON-243)

  • +
+
+
+
+

2.1.4

+

January 26, 2015

+
+

Features

+
    +
  • SaslAuthenticator for Kerberos support (PYTHON-109)

  • +
  • Heartbeat for network device keepalive and detecting failures on idle connections (PYTHON-197)

  • +
  • Support nested, frozen collections for Cassandra 2.1.3+ (PYTHON-186)

  • +
  • Schema agreement wait bypass config, new call for synchronous schema refresh (PYTHON-205)

  • +
  • Add eventlet connection support (PYTHON-194)

  • +
+
+
+

Bug Fixes

+
    +
  • Schema meta fix for complex thrift tables (PYTHON-191)

  • +
  • Support for ‘unknown’ replica placement strategies in schema meta (PYTHON-192)

  • +
  • Resolve stream ID leak on set_keyspace (PYTHON-195)

  • +
  • Remove implicit timestamp scaling on serialization of numeric timestamps (PYTHON-204)

  • +
  • Resolve stream id collision when using SASL auth (PYTHON-210)

  • +
  • Correct unhexlify usage for user defined type meta in Python3 (PYTHON-208)

  • +
+
+
+
+

2.1.3

+

December 16, 2014

+
+

Features

+
    +
  • INFO-level log confirmation that a connection was opened to a node that was marked up (PYTHON-116)

  • +
  • Avoid connecting to peer with incomplete metadata (PYTHON-163)

  • +
  • Add SSL support to gevent reactor (PYTHON-174)

  • +
  • Use control connection timeout in wait for schema agreement (PYTHON-175)

  • +
  • Better consistency level representation in unavailable+timeout exceptions (PYTHON-180)

  • +
  • Update schema metadata processing to accommodate coming schema modernization (PYTHON-185)

  • +
+
+
+

Bug Fixes

+
    +
  • Support large negative timestamps on Windows (PYTHON-119)

  • +
  • Fix schema agreement for clusters with peer rpc_addres 0.0.0.0 (PYTHON-166)

  • +
  • Retain table metadata following keyspace meta refresh (PYTHON-173)

  • +
  • Use a timeout when preparing a statement for all nodes (PYTHON-179)

  • +
  • Make TokenAware routing tolerant of statements with no keyspace (PYTHON-181)

  • +
  • Update add_collback to store/invoke multiple callbacks (PYTHON-182)

  • +
  • Correct routing key encoding for composite keys (PYTHON-184)

  • +
  • Include compression option in schema export string when disabled (PYTHON-187)

  • +
+
+
+
+

2.1.2

+

October 16, 2014

+
+

Features

+
    +
  • Allow DCAwareRoundRobinPolicy to be constructed without a local_dc, defaulting +instead to the DC of a contact_point (PYTHON-126)

  • +
  • Set routing key in BatchStatement.add() if none specified in batch (PYTHON-148)

  • +
  • Improved feedback on ValueError using named_tuple_factory with invalid column names (PYTHON-122)

  • +
+
+
+

Bug Fixes

+
    +
  • Make execute_concurrent compatible with Python 2.6 (PYTHON-159)

  • +
  • Handle Unauthorized message on schema_triggers query (PYTHON-155)

  • +
  • Pure Python sorted set in support of UDTs nested in collections (PYTON-167)

  • +
  • Support CUSTOM index metadata and string export (PYTHON-165)

  • +
+
+
+
+

2.1.1

+

September 11, 2014

+
+

Features

+
    +
  • Detect triggers and include them in CQL queries generated to recreate +the schema (github-189)

  • +
  • Support IPv6 addresses (PYTHON-144) (note: basic functionality added; Windows +platform not addressed (PYTHON-20))

  • +
+
+
+

Bug Fixes

+
    +
  • Fix NetworkTopologyStrategy.export_for_schema (PYTHON-120)

  • +
  • Keep timeout for paged results (PYTHON-150)

  • +
+
+
+

Other

+
    +
  • Add frozen<> type modifier to UDTs and tuples to handle CASSANDRA-7857

  • +
+
+
+
+

2.1.0

+

August 7, 2014

+
+

Bug Fixes

+
    +
  • Correctly serialize and deserialize null values in tuples and +user-defined types (PYTHON-110)

  • +
  • Include additional header and lib dirs, allowing libevwrapper to build +against Homebrew and Mac Ports installs of libev (PYTHON-112 and 804dea3)

  • +
+
+
+
+

2.1.0c1

+

July 25, 2014

+
+

Bug Fixes

+
    +
  • Properly specify UDTs for columns in CREATE TABLE statements

  • +
  • Avoid moving retries to a new host when using request ID zero (PYTHON-88)

  • +
  • Don’t ignore fetch_size arguments to Statement constructors (github-151)

  • +
  • Allow disabling automatic paging on a per-statement basis when it’s +enabled by default for the session (PYTHON-93)

  • +
  • Raise ValueError when tuple query parameters for prepared statements +have extra items (PYTHON-98)

  • +
  • Correctly encode nested tuples and UDTs for non-prepared statements (PYTHON-100)

  • +
  • Raise TypeError when a string is used for contact_points (github #164)

  • +
  • Include User Defined Types in KeyspaceMetadata.export_as_string() (PYTHON-96)

  • +
+
+
+

Other

+
    +
  • Return list collection columns as python lists instead of tuples +now that tuples are a specific Cassandra type

  • +
+
+
+
+

2.1.0b1

+

July 11, 2014

+

This release adds support for Cassandra 2.1 features, including version +3 of the native protocol.

+
+

Features

+
    +
  • When using the v3 protocol, only one connection is opened per-host, and +throughput is improved due to reduced pooling overhead and lock contention.

  • +
  • Support for user-defined types (Cassandra 2.1+)

  • +
  • Support for tuple type in (limited usage Cassandra 2.0.9, full usage +in Cassandra 2.1)

  • +
  • Protocol-level client-side timestamps (see Session.use_client_timestamp)

  • +
  • Overridable type encoding for non-prepared statements (see Session.encoders)

  • +
  • Configurable serial consistency levels for batch statements

  • +
  • Use io.BytesIO for reduced CPU consumption (github #143)

  • +
  • Support Twisted as a reactor. Note that a Twisted-compatible +API is not exposed (so no Deferreds), this is just a reactor +implementation. (github #135, PYTHON-8)

  • +
+
+
+

Bug Fixes

+
    +
  • Fix references to xrange that do not go through “six” in libevreactor and +geventreactor (github #138)

  • +
  • Make BoundStatements inherit fetch_size from their parent +PreparedStatement (PYTHON-80)

  • +
  • Clear reactor state in child process after forking to prevent errors with +multiprocessing when the parent process has connected a Cluster before +forking (github #141)

  • +
  • Don’t share prepared statement lock across Cluster instances

  • +
  • Format CompositeType and DynamicCompositeType columns correctly in +CREATE TABLE statements.

  • +
  • Fix cassandra.concurrent behavior when dealing with automatic paging +(PYTHON-81)

  • +
  • Properly defunct connections after protocol errors

  • +
  • Avoid UnicodeDecodeError when query string is unicode (PYTHON-76)

  • +
  • Correctly capture dclocal_read_repair_chance for tables and +use it when generating CREATE TABLE statements (PYTHON-84)

  • +
  • Avoid race condition with AsyncoreConnection that may cause messages +to fail to be written until a new message is pushed

  • +
  • Make sure cluster.metadata.partitioner and cluster.metadata.token_map +are populated when all nodes in the cluster are included in the +contact points (PYTHON-90)

  • +
  • Make Murmur3 hash match Cassandra’s hash for all values (PYTHON-89, +github #147)

  • +
  • Don’t attempt to reconnect to hosts that should be ignored (according +to the load balancing policy) when a notification is received that the +host is down.

  • +
  • Add CAS WriteType, avoiding KeyError on CAS write timeout (PYTHON-91)

  • +
+
+
+
+

2.0.2

+

June 10, 2014

+
+

Bug Fixes

+
    +
  • Add six to requirements.txt

  • +
  • Avoid KeyError during schema refresh when a keyspace is dropped +and TokenAwarePolicy is not in use

  • +
  • Avoid registering multiple atexit cleanup functions when the +asyncore event loop is restarted multiple times

  • +
  • Delay initialization of reactors in order to avoid problems +with shared state when using multiprocessing (PYTHON-60)

  • +
  • Add python-six to debian dependencies, move python-blist to recommends

  • +
  • Fix memory leak when libev connections are created and +destroyed (github #93)

  • +
  • Ensure token map is rebuilt when hosts are removed from the cluster

  • +
+
+
+
+

2.0.1

+

May 28, 2014

+
+

Bug Fixes

+
    +
  • Fix check for Cluster.is_shutdown in in @run_in_executor +decorator

  • +
+
+
+
+

2.0.0

+

May 28, 2014

+
+

Features

+
    +
  • Make libev C extension Python3-compatible (PYTHON-70)

  • +
  • Support v2 protocol authentication (PYTHON-73, github #125)

  • +
+
+
+

Bug Fixes

+
    +
  • Fix murmur3 C extension compilation under Python3.4 (github #124)

  • +
+
+
+

Merged From 1.x

+
+

Features

+
    +
  • Add Session.default_consistency_level (PYTHON-14)

  • +
+
+
+

Bug Fixes

+
    +
  • Don’t strip trailing underscores from column names when using the +named_tuple_factory (PYTHON-56)

  • +
  • Ensure replication factors are ints for NetworkTopologyStrategy +to avoid TypeErrors (github #120)

  • +
  • Pass WriteType instance to RetryPolicy.on_write_timeout() instead +of the string name of the write type. This caused write timeout +errors to always be rethrown instead of retrying. (github #123)

  • +
  • Avoid submitting tasks to the ThreadPoolExecutor after shutdown. With +retries enabled, this could cause Cluster.shutdown() to hang under +some circumstances.

  • +
  • Fix unintended rebuild of token replica map when keyspaces are +discovered (on startup), added, or updated and TokenAwarePolicy is not +in use.

  • +
  • Avoid rebuilding token metadata when cluster topology has not +actually changed

  • +
  • Avoid preparing queries for hosts that should be ignored (such as +remote hosts when using the DCAwareRoundRobinPolicy) (PYTHON-75)

  • +
+
+
+

Other

+
    +
  • Add 1 second timeout to join() call on event loop thread during +interpreter shutdown. This can help to prevent the process from +hanging during shutdown.

  • +
+
+
+
+
+

2.0.0b1

+

May 6, 2014

+
+

Upgrading from 1.x

+

Cluster.shutdown() should always be called when you are done with a +Cluster instance. If it is not called, there are no guarantees that the +driver will not hang. However, if you do have a reproduceable case +where Cluster.shutdown() is not called and the driver hangs, please +report it so that we can attempt to fix it.

+

If you’re using the 2.0 driver against Cassandra 1.2, you will need +to set your protocol version to 1. For example:

+
+

cluster = Cluster(…, protocol_version=1)

+
+
+
+

Features

+
    +
  • Support v2 of Cassandra’s native protocol, which includes the following +new features: automatic query paging support, protocol-level batch statements, +and lightweight transactions

  • +
  • Support for Python 3.3 and 3.4

  • +
  • Allow a default query timeout to be set per-Session

  • +
+
+
+

Bug Fixes

+
    +
  • Avoid errors during interpreter shutdown (the driver attempts to cleanup +daemonized worker threads before interpreter shutdown)

  • +
+
+
+

Deprecations

+

The following functions have moved from cassandra.decoder to cassandra.query. +The original functions have been left in place with a DeprecationWarning for +now:

+
    +
  • cassandra.decoder.tuple_factory has moved to cassandra.query.tuple_factory

  • +
  • cassandra.decoder.named_tuple_factory has moved to cassandra.query.named_tuple_factory

  • +
  • cassandra.decoder.dict_factory has moved to cassandra.query.dict_factory

  • +
  • cassandra.decoder.ordered_dict_factory has moved to cassandra.query.ordered_dict_factory

  • +
+

Exceptions that were in cassandra.decoder have been moved to cassandra.protocol. If +you handle any of these exceptions, you must adjust the code accordingly.

+
+
+
+

1.1.2

+

May 8, 2014

+
+

Features

+
    +
  • Allow a specific compression type to be requested for communications with +Cassandra and prefer lz4 if available

  • +
+
+
+

Bug Fixes

+
    +
  • Update token metadata (for TokenAware calculations) when a node is removed +from the ring

  • +
  • Fix file handle leak with gevent reactor due to blocking Greenlet kills when +closing excess connections

  • +
  • Avoid handling a node coming up multiple times due to a reconnection attempt +succeeding close to the same time that an UP notification is pushed

  • +
  • Fix duplicate node-up handling, which could result in multiple reconnectors +being started as well as the executor threads becoming deadlocked, preventing +future node up or node down handling from being executed.

  • +
  • Handle exhausted ReconnectionPolicy schedule correctly

  • +
+
+
+

Other

+
    +
  • Don’t log at ERROR when a connection is closed during the startup +communications

  • +
  • Mke scales, blist optional dependencies

  • +
+
+
+
+

1.1.1

+

April 16, 2014

+
+

Bug Fixes

+
    +
  • Fix unconditional import of nose in setup.py (github #111)

  • +
+
+
+
+

1.1.0

+

April 16, 2014

+
+

Features

+
    +
  • Gevent is now supported through monkey-patching the stdlib (PYTHON-7, +github issue #46)

  • +
  • Support static columns in schemas, which are available starting in +Cassandra 2.1. (github issue #91)

  • +
  • Add debian packaging (github issue #101)

  • +
  • Add utility methods for easy concurrent execution of statements. See +the new cassandra.concurrent module. (github issue #7)

  • +
+
+
+

Bug Fixes

+
    +
  • Correctly supply compaction and compression parameters in CREATE statements +for tables when working with Cassandra 2.0+

  • +
  • Lowercase boolean literals when generating schemas

  • +
  • Ignore SSL_ERROR_WANT_READ and SSL_ERROR_WANT_WRITE socket errors. Previously, +these resulted in the connection being defuncted, but they can safely be +ignored by the driver.

  • +
  • Don’t reconnect the control connection every time Cluster.connect() is +called

  • +
  • Avoid race condition that could leave ResponseFuture callbacks uncalled +if the callback was added outside of the event loop thread (github issue #95)

  • +
  • Properly escape keyspace name in Session.set_keyspace(). Previously, the +keyspace name was quoted, but any quotes in the string were not escaped.

  • +
  • Avoid adding hosts to the load balancing policy before their datacenter +and rack information has been set, if possible.

  • +
  • Avoid KeyError when updating metadata after droping a table (github issues +#97, #98)

  • +
  • Use tuples instead of sets for DCAwareLoadBalancingPolicy to ensure equal +distribution of requests

  • +
+
+
+

Other

+
    +
  • Don’t ignore column names when parsing typestrings. This is needed for +user-defined type support. (github issue #90)

  • +
  • Better error message when libevwrapper is not found

  • +
  • Only try to import scales when metrics are enabled (github issue #92)

  • +
  • Cut down on the number of queries executing when a new Cluster +connects and when the control connection has to reconnect (github issue #104, +PYTHON-59)

  • +
  • Issue warning log when schema versions do not match

  • +
+
+
+
+

1.0.2

+

March 4, 2014

+
+

Bug Fixes

+
    +
  • With asyncorereactor, correctly handle EAGAIN/EWOULDBLOCK when the message from +Cassandra is a multiple of the read buffer size. Previously, if no more data +became available to read on the socket, the message would never be processed, +resulting in an OperationTimedOut error.

  • +
  • Double quote keyspace, table and column names that require them (those using +uppercase characters or keywords) when generating CREATE statements through +KeyspaceMetadata and TableMetadata.

  • +
  • Decode TimestampType as DateType. (Cassandra replaced DateType with +TimestampType to fix sorting of pre-unix epoch dates in CASSANDRA-5723.)

  • +
  • Handle latest table options when parsing the schema and generating +CREATE statements.

  • +
  • Avoid ‘Set changed size during iteration’ during query plan generation +when hosts go up or down

  • +
+
+
+

Other

+
    +
  • Remove ignored tracing_enabled parameter for SimpleStatement. The +correct way to trace a query is by setting the trace argument to True +in Session.execute() and Session.execute_async().

  • +
  • Raise TypeError instead of cassandra.query.InvalidParameterTypeError when +a parameter for a prepared statement has the wrong type; remove +cassandra.query.InvalidParameterTypeError.

  • +
  • More consistent type checking for query parameters

  • +
  • Add option to a return special object for empty string values for non-string +columns

  • +
+
+
+
+

1.0.1

+

Feb 19, 2014

+
+

Bug Fixes

+
    +
  • Include table indexes in KeyspaceMetadata.export_as_string()

  • +
  • Fix broken token awareness on ByteOrderedPartitioner

  • +
  • Always close socket when defuncting error’ed connections to avoid a potential +file descriptor leak

  • +
  • Handle “custom” types (such as the replaced DateType) correctly

  • +
  • With libevreactor, correctly handle EAGAIN/EWOULDBLOCK when the message from +Cassandra is a multiple of the read buffer size. Previously, if no more data +became available to read on the socket, the message would never be processed, +resulting in an OperationTimedOut error.

  • +
  • Don’t break tracing when a Session’s row_factory is not the default +namedtuple_factory.

  • +
  • Handle data that is already utf8-encoded for UTF8Type values

  • +
  • Fix token-aware routing for tokens that fall before the first node token in +the ring and tokens that exactly match a node’s token

  • +
  • Tolerate null source_elapsed values for Trace events. These may not be +set when events complete after the main operation has already completed.

  • +
+
+
+

Other

+
    +
  • Skip sending OPTIONS message on connection creation if compression is +disabled or not available and a CQL version has not been explicitly +set

  • +
  • Add details about errors and the last queried host to OperationTimedOut

  • +
+
+
+
+

1.0.0 Final

+

Jan 29, 2014

+
+

Bug Fixes

+
    +
  • Prevent leak of Scheduler thread (even with proper shutdown)

  • +
  • Correctly handle ignored hosts, which are common with the +DCAwareRoundRobinPolicy

  • +
  • Hold strong reference to prepared statement while executing it to avoid +garbage collection

  • +
  • Add NullHandler logging handler to the cassandra package to avoid +warnings about there being no configured logger

  • +
  • Fix bad handling of nodes that have been removed from the cluster

  • +
  • Properly escape string types within cql collections

  • +
  • Handle setting the same keyspace twice in a row

  • +
  • Avoid race condition during schema agreement checks that could result +in schema update queries returning before all nodes had seen the change

  • +
  • Preserve millisecond-level precision in datetimes when performing inserts +with simple (non-prepared) statements

  • +
  • Properly defunct connections when libev reports an error by setting +errno instead of simply logging the error

  • +
  • Fix endless hanging of some requests when using the libev reactor

  • +
  • Always start a reconnection process when we fail to connect to +a newly bootstrapped node

  • +
  • Generators map to CQL lists, not key sequences

  • +
  • Always defunct connections when an internal operation fails

  • +
  • Correctly break from handle_write() if nothing was sent (asyncore +reactor only)

  • +
  • Avoid potential double-erroring of callbacks when a connection +becomes defunct

  • +
+
+
+

Features

+
    +
  • Add default query timeout to Session

  • +
  • Add timeout parameter to Session.execute()

  • +
  • Add WhiteListRoundRobinPolicy as a load balancing policy option

  • +
  • Support for consistency level LOCAL_ONE

  • +
  • Make the backoff for fetching traces exponentially increasing and +configurable

  • +
+
+
+

Other

+
    +
  • Raise Exception if TokenAwarePolicy is used against a cluster using the +Murmur3Partitioner if the murmur3 C extension has not been compiled

  • +
  • Add encoder mapping for OrderedDict

  • +
  • Use timeouts on all control connection queries

  • +
  • Benchmark improvements, including command line options and eay +multithreading support

  • +
  • Reduced lock contention when using the asyncore reactor

  • +
  • Warn when non-datetimes are used for ‘timestamp’ column values in +prepared statements

  • +
  • Add requirements.txt and test-requirements.txt

  • +
  • TravisCI integration for running unit tests against Python 2.6, +Python 2.7, and PyPy

  • +
+
+
+
+

1.0.0b7

+

Nov 12, 2013

+

This release makes many stability improvements, especially around +prepared statements and node failure handling. In particular, +several cases where a request would never be completed (and as a +result, leave the application hanging) have been resolved.

+
+

Features

+
    +
  • Add timeout kwarg to ResponseFuture.result()

  • +
  • Create connection pools to all hosts in parallel when initializing +new Sesssions.

  • +
+
+
+

Bug Fixes

+
    +
  • Properly set exception on ResponseFuture when a query fails +against all hosts

  • +
  • Improved cleanup and reconnection efforts when reconnection fails +on a node that has recently come up

  • +
  • Use correct consistency level when retrying failed operations +against a different host. (An invalid consistency level was being +used, causing the retry to fail.)

  • +
  • Better error messages for failed Session.prepare() opertaions

  • +
  • Prepare new statements against all hosts in parallel (formerly +sequential)

  • +
  • Fix failure to save the new current keyspace on connections. (This +could cause problems for prepared statements and lead to extra +operations to continuously re-set the keyspace.)

  • +
  • Avoid sharing LoadBalancingPolicies across Cluster instances. (When +a second Cluster was connected, it effectively mark nodes down for the +first Cluster.)

  • +
  • Better handling of failures during the re-preparation sequence for +unrecognized prepared statements

  • +
  • Throttle trashing of underutilized connections to avoid trashing newly +created connections

  • +
  • Fix race condition which could result in trashed connections being closed +before the last operations had completed

  • +
  • Avoid preparing statements on the event loop thread (which could lead to +deadlock)

  • +
  • Correctly mark up non-contact point nodes discovered by the control +connection. (This lead to prepared statements not being prepared +against those hosts, generating extra traffic later when the +statements were executed and unrecognized.)

  • +
  • Correctly handle large messages through libev

  • +
  • Add timeout to schema agreement check queries

  • +
  • More complete (and less contended) locking around manipulation of the +pending message deque for libev connections

  • +
+
+
+

Other

+
    +
  • Prepare statements in batches of 10. (When many prepared statements +are in use, this allows the driver to start utilizing nodes that +were restarted more quickly.)

  • +
  • Better debug logging around connection management

  • +
  • Don’t retain unreferenced prepared statements in the local cache. +(If many different prepared statements were created, this would +increase memory usage and greatly increase the amount of time +required to begin utilizing a node that was added or marked +up.)

  • +
+
+
+
+

1.0.0b6

+

Oct 22, 2013

+
+

Bug Fixes

+
    +
  • Use lazy string formatting when logging

  • +
  • Avoid several deadlock scenarios, especially when nodes go down

  • +
  • Avoid trashing newly created connections due to insufficient traffic

  • +
  • Gracefully handle un-handled Exceptions when erroring callbacks

  • +
+
+
+

Other

+
    +
  • Node state listeners (which are called when a node is added, removed, +goes down, or comes up) should now be registered through +Cluster.register_listener() instead of through a host’s HealthMonitor +(which has been removed)

  • +
+
+
+
+

1.0.0b5

+

Oct 10, 2013

+
+

Features

+
    +
  • SSL support

  • +
+
+
+

Bug Fixes

+
    +
  • Avoid KeyError when building replica map for NetworkTopologyStrategy

  • +
  • Work around python bug which causes deadlock when a thread imports +the utf8 module

  • +
  • Handle no blist library, which is not compatible with pypy

  • +
  • Avoid deadlock triggered by a keyspace being set on a connection (which +may happen automatically for new connections)

  • +
+
+
+

Other

+
    +
  • Switch packaging from Distribute to setuptools, improved C extension +support

  • +
  • Use PEP 386 compliant beta and post-release versions

  • +
+
+
+
+

1.0.0-beta4

+

Sep 24, 2013

+
+

Features

+
    +
  • Handle new blob syntax in Cassandra 2.0 by accepting bytearray +objects for blob values

  • +
  • Add cql_version kwarg to Cluster.__init__

  • +
+
+
+

Bug Fixes

+
    +
  • Fix KeyError when building token map with NetworkTopologyStrategy +keyspaces (this prevented a Cluster from successfully connecting +at all).

  • +
  • Don’t lose default consitency level from parent PreparedStatement +when creating BoundStatements

  • +
+
+
+
+

1.0.0-beta3

+

Sep 20, 2013

+
+

Features

+
    +
  • Support for LZ4 compression (Cassandra 2.0+)

  • +
  • Token-aware routing will now utilize all replicas for a query instead +of just the first replica

  • +
+
+
+

Bug Fixes

+
    +
  • Fix libev include path for CentOS

  • +
  • Fix varint packing of the value 0

  • +
  • Correctly pack unicode values

  • +
  • Don’t attempt to return failed connections to the pool when a final result +is set

  • +
  • Fix bad iteration of connection credentials

  • +
  • Use blist’s orderedset for set collections and OrderedDict for map +collections so that Cassandra’s ordering is preserved

  • +
  • Fix connection failure on Windows due to unavailability of inet_pton +and inet_ntop. (Note that IPv6 inet_address values are still not +supported on Windows.)

  • +
  • Boolean constants shouldn’t be surrounded by single quotes

  • +
  • Avoid a potential loss of precision on float constants due to string +formatting

  • +
  • Actually utilize non-standard ports set on Cluster objects

  • +
  • Fix export of schema as a set of CQL queries

  • +
+
+
+

Other

+
    +
  • Use cStringIO for connection buffer for better performance

  • +
  • Add __repr__ method for Statement classes

  • +
  • Raise InvalidTypeParameterError when parameters of the wrong +type are used with statements

  • +
  • Make all tests compatible with Python 2.6

  • +
  • Add 1s timeout for opening new connections

  • +
+
+
+
+

1.0.0-beta2

+

Aug 19, 2013

+
+

Bug Fixes

+
    +
  • Fix pip packaging

  • +
+
+
+
+

1.0.0-beta

+

Aug 16, 2013

+

Initial release

+
+
+ + +
+ + + + + +
+ + +
+
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/master/CNAME b/master/CNAME new file mode 100644 index 0000000000..9f3e01a070 --- /dev/null +++ b/master/CNAME @@ -0,0 +1 @@ +python-driver.docs.scylladb.com \ No newline at end of file diff --git a/master/_sources/CHANGELOG.rst.txt b/master/_sources/CHANGELOG.rst.txt new file mode 100644 index 0000000000..f6d642b27f --- /dev/null +++ b/master/_sources/CHANGELOG.rst.txt @@ -0,0 +1,7 @@ +:orphan: + +********* +CHANGELOG +********* + +.. include:: ../CHANGELOG.rst diff --git a/master/_sources/api/cassandra.rst.txt b/master/_sources/api/cassandra.rst.txt new file mode 100644 index 0000000000..d46aae56cb --- /dev/null +++ b/master/_sources/api/cassandra.rst.txt @@ -0,0 +1,77 @@ +:mod:`cassandra` - Exceptions and Enums +======================================= + +.. module:: cassandra + +.. data:: __version_info__ + + The version of the driver in a tuple format + +.. data:: __version__ + + The version of the driver in a string format + +.. autoclass:: ConsistencyLevel + :members: + +.. autoclass:: ProtocolVersion + :members: + +.. autoclass:: UserFunctionDescriptor + :members: + :inherited-members: + +.. autoclass:: UserAggregateDescriptor + :members: + :inherited-members: + +.. autoexception:: DriverException() + :members: + +.. autoexception:: RequestExecutionException() + :members: + +.. autoexception:: Unavailable() + :members: + +.. autoexception:: Timeout() + :members: + +.. autoexception:: ReadTimeout() + :members: + +.. autoexception:: WriteTimeout() + :members: + +.. autoexception:: CoordinationFailure() + :members: + +.. autoexception:: ReadFailure() + :members: + +.. autoexception:: WriteFailure() + :members: + +.. autoexception:: FunctionFailure() + :members: + +.. autoexception:: RequestValidationException() + :members: + +.. autoexception:: ConfigurationException() + :members: + +.. autoexception:: AlreadyExists() + :members: + +.. autoexception:: InvalidRequest() + :members: + +.. autoexception:: Unauthorized() + :members: + +.. autoexception:: AuthenticationFailed() + :members: + +.. autoexception:: OperationTimedOut() + :members: diff --git a/master/_sources/api/cassandra/auth.rst.txt b/master/_sources/api/cassandra/auth.rst.txt new file mode 100644 index 0000000000..58c964cf89 --- /dev/null +++ b/master/_sources/api/cassandra/auth.rst.txt @@ -0,0 +1,22 @@ +``cassandra.auth`` - Authentication +=================================== + +.. module:: cassandra.auth + +.. autoclass:: AuthProvider + :members: + +.. autoclass:: Authenticator + :members: + +.. autoclass:: PlainTextAuthProvider + :members: + +.. autoclass:: PlainTextAuthenticator + :members: + +.. autoclass:: SaslAuthProvider + :members: + +.. autoclass:: SaslAuthenticator + :members: diff --git a/master/_sources/api/cassandra/cluster.rst.txt b/master/_sources/api/cassandra/cluster.rst.txt new file mode 100644 index 0000000000..2b3d7828a8 --- /dev/null +++ b/master/_sources/api/cassandra/cluster.rst.txt @@ -0,0 +1,228 @@ +``cassandra.cluster`` - Clusters and Sessions +============================================= + +.. module:: cassandra.cluster + +.. autoclass:: Cluster ([contact_points=('127.0.0.1',)][, port=9042][, executor_threads=2], **attr_kwargs) + + .. autoattribute:: contact_points + + .. autoattribute:: port + + .. autoattribute:: cql_version + + .. autoattribute:: protocol_version + + .. autoattribute:: compression + + .. autoattribute:: auth_provider + + .. autoattribute:: load_balancing_policy + + .. autoattribute:: reconnection_policy + + .. autoattribute:: default_retry_policy + :annotation: = + + .. autoattribute:: conviction_policy_factory + + .. autoattribute:: address_translator + + .. autoattribute:: metrics_enabled + + .. autoattribute:: metrics + + .. autoattribute:: ssl_context + + .. autoattribute:: ssl_options + + .. autoattribute:: sockopts + + .. autoattribute:: max_schema_agreement_wait + + .. autoattribute:: metadata + + .. autoattribute:: connection_class + + .. autoattribute:: control_connection_timeout + + .. autoattribute:: idle_heartbeat_interval + + .. autoattribute:: idle_heartbeat_timeout + + .. autoattribute:: schema_event_refresh_window + + .. autoattribute:: topology_event_refresh_window + + .. autoattribute:: status_event_refresh_window + + .. autoattribute:: prepare_on_all_hosts + + .. autoattribute:: reprepare_on_up + + .. autoattribute:: connect_timeout + + .. autoattribute:: schema_metadata_enabled + :annotation: = True + + .. autoattribute:: token_metadata_enabled + :annotation: = True + + .. autoattribute:: timestamp_generator + + .. autoattribute:: endpoint_factory + + .. autoattribute:: cloud + + .. automethod:: connect + + .. automethod:: shutdown + + .. automethod:: register_user_type + + .. automethod:: register_listener + + .. automethod:: unregister_listener + + .. automethod:: add_execution_profile + + .. automethod:: set_max_requests_per_connection + + .. automethod:: get_max_requests_per_connection + + .. automethod:: set_min_requests_per_connection + + .. automethod:: get_min_requests_per_connection + + .. automethod:: get_core_connections_per_host + + .. automethod:: set_core_connections_per_host + + .. automethod:: get_max_connections_per_host + + .. automethod:: set_max_connections_per_host + + .. automethod:: get_control_connection_host + + .. automethod:: refresh_schema_metadata + + .. automethod:: refresh_keyspace_metadata + + .. automethod:: refresh_table_metadata + + .. automethod:: refresh_user_type_metadata + + .. automethod:: refresh_user_function_metadata + + .. automethod:: refresh_user_aggregate_metadata + + .. automethod:: refresh_nodes + + .. automethod:: set_meta_refresh_enabled + +.. autoclass:: ExecutionProfile (load_balancing_policy=, retry_policy=None, consistency_level=ConsistencyLevel.LOCAL_ONE, serial_consistency_level=None, request_timeout=10.0, row_factory=, speculative_execution_policy=None) + :members: + :exclude-members: consistency_level + + .. autoattribute:: consistency_level + :annotation: = LOCAL_ONE + +.. autoclass:: GraphExecutionProfile (load_balancing_policy=_NOT_SET, retry_policy=None, consistency_level=ConsistencyLevel.LOCAL_ONE, serial_consistency_level=None, request_timeout=30.0, row_factory=None, graph_options=None, continuous_paging_options=_NOT_SET) + :members: + +.. autoclass:: GraphAnalyticsExecutionProfile (load_balancing_policy=None, retry_policy=None, consistency_level=ConsistencyLevel.LOCAL_ONE, serial_consistency_level=None, request_timeout=3600. * 24. * 7., row_factory=None, graph_options=None) + :members: + +.. autodata:: EXEC_PROFILE_DEFAULT + :annotation: + +.. autodata:: EXEC_PROFILE_GRAPH_DEFAULT + :annotation: + +.. autodata:: EXEC_PROFILE_GRAPH_SYSTEM_DEFAULT + :annotation: + +.. autodata:: EXEC_PROFILE_GRAPH_ANALYTICS_DEFAULT + :annotation: + +.. autoclass:: Session () + + .. autoattribute:: default_timeout + :annotation: = 10.0 + + .. autoattribute:: default_consistency_level + :annotation: = LOCAL_ONE + + .. autoattribute:: default_serial_consistency_level + :annotation: = None + + .. autoattribute:: row_factory + :annotation: = + + .. autoattribute:: default_fetch_size + + .. autoattribute:: use_client_timestamp + + .. autoattribute:: timestamp_generator + + .. autoattribute:: encoder + + .. autoattribute:: client_protocol_handler + + .. automethod:: execute(statement[, parameters][, timeout][, trace][, custom_payload][, paging_state][, host][, execute_as]) + + .. automethod:: execute_async(statement[, parameters][, trace][, custom_payload][, paging_state][, host][, execute_as]) + + .. automethod:: execute_graph(statement[, parameters][, trace][, execution_profile=EXEC_PROFILE_GRAPH_DEFAULT][, execute_as]) + + .. automethod:: execute_graph_async(statement[, parameters][, trace][, execution_profile=EXEC_PROFILE_GRAPH_DEFAULT][, execute_as]) + + .. automethod:: prepare(statement) + + .. automethod:: shutdown() + + .. automethod:: set_keyspace(keyspace) + + .. automethod:: get_execution_profile + + .. automethod:: execution_profile_clone_update + + .. automethod:: add_request_init_listener + + .. automethod:: remove_request_init_listener + +.. autoclass:: ResponseFuture () + + .. autoattribute:: query + + .. automethod:: result() + + .. automethod:: get_query_trace() + + .. automethod:: get_all_query_traces() + + .. autoattribute:: custom_payload() + + .. autoattribute:: is_schema_agreed + + .. autoattribute:: has_more_pages + + .. autoattribute:: warnings + + .. automethod:: start_fetching_next_page() + + .. automethod:: add_callback(fn, *args, **kwargs) + + .. automethod:: add_errback(fn, *args, **kwargs) + + .. automethod:: add_callbacks(callback, errback, callback_args=(), callback_kwargs=None, errback_args=(), errback_args=None) + +.. autoclass:: ResultSet () + :members: + +.. autoexception:: QueryExhausted () + +.. autoexception:: NoHostAvailable () + :members: + +.. autoexception:: UserTypeDoesNotExist () diff --git a/master/_sources/api/cassandra/concurrent.rst.txt b/master/_sources/api/cassandra/concurrent.rst.txt new file mode 100644 index 0000000000..f4bab6f048 --- /dev/null +++ b/master/_sources/api/cassandra/concurrent.rst.txt @@ -0,0 +1,8 @@ +``cassandra.concurrent`` - Utilities for Concurrent Statement Execution +======================================================================= + +.. module:: cassandra.concurrent + +.. autofunction:: execute_concurrent + +.. autofunction:: execute_concurrent_with_args diff --git a/master/_sources/api/cassandra/connection.rst.txt b/master/_sources/api/cassandra/connection.rst.txt new file mode 100644 index 0000000000..32cca590c0 --- /dev/null +++ b/master/_sources/api/cassandra/connection.rst.txt @@ -0,0 +1,21 @@ +``cassandra.connection`` - Low Level Connection Info +==================================================== + +.. module:: cassandra.connection + +.. autoexception:: ConnectionException () +.. autoexception:: ConnectionShutdown () +.. autoexception:: ConnectionBusy () +.. autoexception:: ProtocolError () + +.. autoclass:: EndPoint + :members: + +.. autoclass:: EndPointFactory + :members: + +.. autoclass:: SniEndPoint + +.. autoclass:: SniEndPointFactory + +.. autoclass:: UnixSocketEndPoint diff --git a/master/_sources/api/cassandra/cqlengine/columns.rst.txt b/master/_sources/api/cassandra/cqlengine/columns.rst.txt new file mode 100644 index 0000000000..d44be8adb8 --- /dev/null +++ b/master/_sources/api/cassandra/cqlengine/columns.rst.txt @@ -0,0 +1,89 @@ +``cassandra.cqlengine.columns`` - Column types for object mapping models +======================================================================== + +.. module:: cassandra.cqlengine.columns + +Columns +------- + +Columns in your models map to columns in your CQL table. You define CQL columns by defining column attributes on your model classes. +For a model to be valid it needs at least one primary key column and one non-primary key column. + +Just as in CQL, the order you define your columns in is important, and is the same order they are defined in on a model's corresponding table. + +Each column on your model definitions needs to be an instance of a Column class. + +.. autoclass:: Column(**kwargs) + + .. autoattribute:: primary_key + + .. autoattribute:: partition_key + + .. autoattribute:: index + + .. autoattribute:: custom_index + + .. autoattribute:: db_field + + .. autoattribute:: default + + .. autoattribute:: required + + .. autoattribute:: clustering_order + + .. autoattribute:: discriminator_column + + .. autoattribute:: static + +Column Types +------------ + +Columns of all types are initialized by passing :class:`.Column` attributes to the constructor by keyword. + +.. autoclass:: Ascii(**kwargs) + +.. autoclass:: BigInt(**kwargs) + +.. autoclass:: Blob(**kwargs) + +.. autoclass:: Bytes(**kwargs) + +.. autoclass:: Boolean(**kwargs) + +.. autoclass:: Counter + +.. autoclass:: Date(**kwargs) + +.. autoclass:: DateTime(**kwargs) + + .. autoattribute:: truncate_microseconds + +.. autoclass:: Decimal(**kwargs) + +.. autoclass:: Double(**kwargs) + +.. autoclass:: Float + +.. autoclass:: Integer(**kwargs) + +.. autoclass:: List + +.. autoclass:: Map + +.. autoclass:: Set + +.. autoclass:: SmallInt(**kwargs) + +.. autoclass:: Text + +.. autoclass:: Time(**kwargs) + +.. autoclass:: TimeUUID(**kwargs) + +.. autoclass:: TinyInt(**kwargs) + +.. autoclass:: UserDefinedType + +.. autoclass:: UUID(**kwargs) + +.. autoclass:: VarInt(**kwargs) diff --git a/master/_sources/api/cassandra/cqlengine/connection.rst.txt b/master/_sources/api/cassandra/cqlengine/connection.rst.txt new file mode 100644 index 0000000000..0f584fcca2 --- /dev/null +++ b/master/_sources/api/cassandra/cqlengine/connection.rst.txt @@ -0,0 +1,16 @@ +``cassandra.cqlengine.connection`` - Connection management for cqlengine +======================================================================== + +.. module:: cassandra.cqlengine.connection + +.. autofunction:: default + +.. autofunction:: set_session + +.. autofunction:: setup + +.. autofunction:: register_connection + +.. autofunction:: unregister_connection + +.. autofunction:: set_default_connection diff --git a/master/_sources/api/cassandra/cqlengine/management.rst.txt b/master/_sources/api/cassandra/cqlengine/management.rst.txt new file mode 100644 index 0000000000..fb483abc81 --- /dev/null +++ b/master/_sources/api/cassandra/cqlengine/management.rst.txt @@ -0,0 +1,19 @@ +``cassandra.cqlengine.management`` - Schema management for cqlengine +======================================================================== + +.. module:: cassandra.cqlengine.management + +A collection of functions for managing keyspace and table schema. + +.. autofunction:: create_keyspace_simple + +.. autofunction:: create_keyspace_network_topology + +.. autofunction:: drop_keyspace + +.. autofunction:: sync_table + +.. autofunction:: sync_type + +.. autofunction:: drop_table + diff --git a/master/_sources/api/cassandra/cqlengine/models.rst.txt b/master/_sources/api/cassandra/cqlengine/models.rst.txt new file mode 100644 index 0000000000..60b1471184 --- /dev/null +++ b/master/_sources/api/cassandra/cqlengine/models.rst.txt @@ -0,0 +1,197 @@ +``cassandra.cqlengine.models`` - Table models for object mapping +================================================================ + +.. module:: cassandra.cqlengine.models + +Model +----- +.. autoclass:: Model(\*\*kwargs) + + The initializer creates an instance of the model. Pass in keyword arguments for columns you've defined on the model. + + .. code-block:: python + + class Person(Model): + id = columns.UUID(primary_key=True) + first_name = columns.Text() + last_name = columns.Text() + + person = Person(first_name='Blake', last_name='Eggleston') + person.first_name #returns 'Blake' + person.last_name #returns 'Eggleston' + + Model attributes define how the model maps to tables in the database. These are class variables that should be set + when defining Model deriviatives. + + .. autoattribute:: __abstract__ + :annotation: = False + + .. autoattribute:: __table_name__ + + .. autoattribute:: __table_name_case_sensitive__ + + .. autoattribute:: __keyspace__ + + .. autoattribute:: __connection__ + + .. attribute:: __default_ttl__ + :annotation: = None + + Will be deprecated in release 4.0. You can set the default ttl by configuring the table ``__options__``. See :ref:`ttl-change` for more details. + + .. autoattribute:: __discriminator_value__ + + See :ref:`model_inheritance` for usage examples. + + Each table can have its own set of configuration options, including compaction. Unspecified, these default to sensible values in + the server. To override defaults, set options using the model ``__options__`` attribute, which allows options specified a dict. + + When a table is synced, it will be altered to match the options set on your table. + This means that if you are changing settings manually they will be changed back on resync. + + Do not use the options settings of cqlengine if you want to manage your compaction settings manually. + + See the `list of supported table properties for more information + `_. + + .. attribute:: __options__ + + For example: + + .. code-block:: python + + class User(Model): + __options__ = {'compaction': {'class': 'LeveledCompactionStrategy', + 'sstable_size_in_mb': '64', + 'tombstone_threshold': '.2'}, + 'comment': 'User data stored here'} + + user_id = columns.UUID(primary_key=True) + name = columns.Text() + + or : + + .. code-block:: python + + class TimeData(Model): + __options__ = {'compaction': {'class': 'SizeTieredCompactionStrategy', + 'bucket_low': '.3', + 'bucket_high': '2', + 'min_threshold': '2', + 'max_threshold': '64', + 'tombstone_compaction_interval': '86400'}, + 'gc_grace_seconds': '0'} + + .. autoattribute:: __compute_routing_key__ + + + The base methods allow creating, storing, and querying modeled objects. + + .. automethod:: create + + .. method:: if_not_exists() + + Check the existence of an object before insertion. The existence of an + object is determined by its primary key(s). And please note using this flag + would incur performance cost. + + If the insertion isn't applied, a :class:`~cassandra.cqlengine.query.LWTException` is raised. + + .. code-block:: python + + try: + TestIfNotExistsModel.if_not_exists().create(id=id, count=9, text='111111111111') + except LWTException as e: + # handle failure case + print e.existing # dict containing LWT result fields + + This method is supported on Cassandra 2.0 or later. + + .. method:: if_exists() + + Check the existence of an object before an update or delete. The existence of an + object is determined by its primary key(s). And please note using this flag + would incur performance cost. + + If the update or delete isn't applied, a :class:`~cassandra.cqlengine.query.LWTException` is raised. + + .. code-block:: python + + try: + TestIfExistsModel.objects(id=id).if_exists().update(count=9, text='111111111111') + except LWTException as e: + # handle failure case + pass + + This method is supported on Cassandra 2.0 or later. + + .. automethod:: save + + .. automethod:: update + + .. method:: iff(**values) + + Checks to ensure that the values specified are correct on the Cassandra cluster. + Simply specify the column(s) and the expected value(s). As with if_not_exists, + this incurs a performance cost. + + If the insertion isn't applied, a :class:`~cassandra.cqlengine.query.LWTException` is raised. + + .. code-block:: python + + t = TestTransactionModel(text='some text', count=5) + try: + t.iff(count=5).update('other text') + except LWTException as e: + # handle failure case + print e.existing # existing object + + .. automethod:: get + + .. automethod:: filter + + .. automethod:: all + + .. automethod:: delete + + .. method:: batch(batch_object) + + Sets the batch object to run instance updates and inserts queries with. + + See :doc:`/cqlengine/batches` for usage examples + + .. automethod:: timeout + + .. method:: timestamp(timedelta_or_datetime) + + Sets the timestamp for the query + + .. method:: ttl(ttl_in_sec) + + Sets the ttl values to run instance updates and inserts queries with. + + .. method:: using(connection=None) + + Change the context on the fly of the model instance (keyspace, connection) + + .. automethod:: column_family_name + + Models also support dict-like access: + + .. method:: len(m) + + Returns the number of columns defined in the model + + .. method:: m[col_name] + + Returns the value of column ``col_name`` + + .. method:: m[col_name] = value + + Set ``m[col_name]`` to value + + .. automethod:: keys + + .. automethod:: values + + .. automethod:: items diff --git a/master/_sources/api/cassandra/cqlengine/query.rst.txt b/master/_sources/api/cassandra/cqlengine/query.rst.txt new file mode 100644 index 0000000000..ce8f764b6b --- /dev/null +++ b/master/_sources/api/cassandra/cqlengine/query.rst.txt @@ -0,0 +1,71 @@ +``cassandra.cqlengine.query`` - Query and filter model objects +================================================================= + +.. module:: cassandra.cqlengine.query + +QuerySet +-------- +QuerySet objects are typically obtained by calling :meth:`~.cassandra.cqlengine.models.Model.objects` on a model class. +The methods here are used to filter, order, and constrain results. + +.. autoclass:: ModelQuerySet + + .. automethod:: all + + .. automethod:: batch + + .. automethod:: consistency + + .. automethod:: count + + .. method:: len(queryset) + + Returns the number of rows matched by this query. This function uses :meth:`~.cassandra.cqlengine.query.ModelQuerySet.count` internally. + + *Note: This function executes a SELECT COUNT() and has a performance cost on large datasets* + + .. automethod:: distinct + + .. automethod:: filter + + .. automethod:: get + + .. automethod:: limit + + .. automethod:: fetch_size + + .. automethod:: if_not_exists + + .. automethod:: if_exists + + .. automethod:: order_by + + .. automethod:: allow_filtering + + .. automethod:: only + + .. automethod:: defer + + .. automethod:: timestamp + + .. automethod:: ttl + + .. automethod:: using + + .. _blind_updates: + + .. automethod:: update + +.. autoclass:: BatchQuery + :members: + + .. automethod:: add_query + .. automethod:: execute + +.. autoclass:: ContextQuery + +.. autoclass:: DoesNotExist + +.. autoclass:: MultipleObjectsReturned + +.. autoclass:: LWTException diff --git a/master/_sources/api/cassandra/cqlengine/usertype.rst.txt b/master/_sources/api/cassandra/cqlengine/usertype.rst.txt new file mode 100644 index 0000000000..ebed187da9 --- /dev/null +++ b/master/_sources/api/cassandra/cqlengine/usertype.rst.txt @@ -0,0 +1,10 @@ +``cassandra.cqlengine.usertype`` - Model classes for User Defined Types +======================================================================= + +.. module:: cassandra.cqlengine.usertype + +UserType +-------- +.. autoclass:: UserType + + .. autoattribute:: __type_name__ diff --git a/master/_sources/api/cassandra/datastax/graph/fluent/index.rst.txt b/master/_sources/api/cassandra/datastax/graph/fluent/index.rst.txt new file mode 100644 index 0000000000..5547e0fdd7 --- /dev/null +++ b/master/_sources/api/cassandra/datastax/graph/fluent/index.rst.txt @@ -0,0 +1,24 @@ +:mod:`cassandra.datastax.graph.fluent` +====================================== + +.. module:: cassandra.datastax.graph.fluent + +.. autoclass:: DseGraph + + .. autoattribute:: DSE_GRAPH_QUERY_LANGUAGE + + .. automethod:: create_execution_profile + + .. automethod:: query_from_traversal + + .. automethod:: traversal_source(session=None, graph_name=None, execution_profile=EXEC_PROFILE_GRAPH_DEFAULT, traversal_class=None) + + .. automethod:: batch(session=None, execution_profile=None) + +.. autoclass:: DSESessionRemoteGraphConnection(session[, graph_name, execution_profile]) + +.. autoclass:: BaseGraphRowFactory + +.. autoclass:: graph_traversal_row_factory + +.. autoclass:: graph_traversal_dse_object_row_factory diff --git a/master/_sources/api/cassandra/datastax/graph/fluent/predicates.rst.txt b/master/_sources/api/cassandra/datastax/graph/fluent/predicates.rst.txt new file mode 100644 index 0000000000..f6e86f6451 --- /dev/null +++ b/master/_sources/api/cassandra/datastax/graph/fluent/predicates.rst.txt @@ -0,0 +1,14 @@ +:mod:`cassandra.datastax.graph.fluent.predicates` +================================================= + +.. module:: cassandra.datastax.graph.fluent.predicates + + +.. autoclass:: Search + :members: + +.. autoclass:: CqlCollection + :members: + +.. autoclass:: Geo + :members: diff --git a/master/_sources/api/cassandra/datastax/graph/fluent/query.rst.txt b/master/_sources/api/cassandra/datastax/graph/fluent/query.rst.txt new file mode 100644 index 0000000000..3dd859f96e --- /dev/null +++ b/master/_sources/api/cassandra/datastax/graph/fluent/query.rst.txt @@ -0,0 +1,8 @@ +:mod:`cassandra.datastax.graph.fluent.query` +============================================ + +.. module:: cassandra.datastax.graph.fluent.query + + +.. autoclass:: TraversalBatch + :members: diff --git a/master/_sources/api/cassandra/datastax/graph/index.rst.txt b/master/_sources/api/cassandra/datastax/graph/index.rst.txt new file mode 100644 index 0000000000..a9b41cbdc2 --- /dev/null +++ b/master/_sources/api/cassandra/datastax/graph/index.rst.txt @@ -0,0 +1,133 @@ +``cassandra.datastax.graph`` - Graph Statements, Options, and Row Factories +=========================================================================== + +.. _api-datastax-graph: + +.. module:: cassandra.datastax.graph + +.. autofunction:: single_object_row_factory + +.. autofunction:: graph_result_row_factory + +.. autofunction:: graph_object_row_factory + +.. autofunction:: graph_graphson2_row_factory + +.. autofunction:: graph_graphson3_row_factory + +.. function:: to_int(value) + + Wraps a value to be explicitly serialized as a graphson Int. + +.. function:: to_bigint(value) + + Wraps a value to be explicitly serialized as a graphson Bigint. + +.. function:: to_smallint(value) + + Wraps a value to be explicitly serialized as a graphson Smallint. + +.. function:: to_float(value) + + Wraps a value to be explicitly serialized as a graphson Float. + +.. function:: to_double(value) + + Wraps a value to be explicitly serialized as a graphson Double. + +.. autoclass:: GraphProtocol + :members: + :noindex: + +.. autoclass:: GraphOptions + :noindex: + + .. autoattribute:: graph_name + + .. autoattribute:: graph_source + + .. autoattribute:: graph_language + + .. autoattribute:: graph_read_consistency_level + + .. autoattribute:: graph_write_consistency_level + + .. autoattribute:: is_default_source + + .. autoattribute:: is_analytics_source + + .. autoattribute:: is_graph_source + + .. automethod:: set_source_default + + .. automethod:: set_source_analytics + + .. automethod:: set_source_graph + + +.. autoclass:: SimpleGraphStatement + :members: + :noindex: + +.. autoclass:: Result + :members: + :noindex: + +.. autoclass:: Vertex + :members: + :noindex: + +.. autoclass:: VertexProperty + :members: + :noindex: + +.. autoclass:: Edge + :members: + :noindex: + +.. autoclass:: Path + :members: + :noindex: + +.. autoclass:: T + :members: + :noindex: + +.. autoclass:: GraphSON1Serializer + :members: + :noindex: + +.. autoclass:: GraphSON1Deserializer + :noindex: + + .. automethod:: deserialize_date + + .. automethod:: deserialize_timestamp + + .. automethod:: deserialize_time + + .. automethod:: deserialize_duration + + .. automethod:: deserialize_int + + .. automethod:: deserialize_bigint + + .. automethod:: deserialize_double + + .. automethod:: deserialize_float + + .. automethod:: deserialize_uuid + + .. automethod:: deserialize_blob + + .. automethod:: deserialize_decimal + + .. automethod:: deserialize_point + + .. automethod:: deserialize_linestring + + .. automethod:: deserialize_polygon + +.. autoclass:: GraphSON2Reader + :members: + :noindex: diff --git a/master/_sources/api/cassandra/decoder.rst.txt b/master/_sources/api/cassandra/decoder.rst.txt new file mode 100644 index 0000000000..e213cc6d74 --- /dev/null +++ b/master/_sources/api/cassandra/decoder.rst.txt @@ -0,0 +1,20 @@ +``cassandra.decoder`` - Data Return Formats +=========================================== + +.. module:: cassandra.decoder + +.. function:: tuple_factory + + **Deprecated in 2.0.0.** Use :meth:`cassandra.query.tuple_factory` + +.. function:: named_tuple_factory + + **Deprecated in 2.0.0.** Use :meth:`cassandra.query.named_tuple_factory` + +.. function:: dict_factory + + **Deprecated in 2.0.0.** Use :meth:`cassandra.query.dict_factory` + +.. function:: ordered_dict_factory + + **Deprecated in 2.0.0.** Use :meth:`cassandra.query.ordered_dict_factory` diff --git a/master/_sources/api/cassandra/encoder.rst.txt b/master/_sources/api/cassandra/encoder.rst.txt new file mode 100644 index 0000000000..de3b180510 --- /dev/null +++ b/master/_sources/api/cassandra/encoder.rst.txt @@ -0,0 +1,36 @@ +``cassandra.encoder`` - Encoders for non-prepared Statements +============================================================ + +.. module:: cassandra.encoder + +.. autoclass:: Encoder () + + .. autoattribute:: cassandra.encoder.Encoder.mapping + + .. automethod:: cassandra.encoder.Encoder.cql_encode_none () + + .. automethod:: cassandra.encoder.Encoder.cql_encode_object () + + .. automethod:: cassandra.encoder.Encoder.cql_encode_all_types () + + .. automethod:: cassandra.encoder.Encoder.cql_encode_sequence () + + .. automethod:: cassandra.encoder.Encoder.cql_encode_str () + + .. automethod:: cassandra.encoder.Encoder.cql_encode_unicode () + + .. automethod:: cassandra.encoder.Encoder.cql_encode_bytes () + + Converts strings, buffers, and bytearrays into CQL blob literals. + + .. automethod:: cassandra.encoder.Encoder.cql_encode_datetime () + + .. automethod:: cassandra.encoder.Encoder.cql_encode_date () + + .. automethod:: cassandra.encoder.Encoder.cql_encode_map_collection () + + .. automethod:: cassandra.encoder.Encoder.cql_encode_list_collection () + + .. automethod:: cassandra.encoder.Encoder.cql_encode_set_collection () + + .. automethod:: cql_encode_tuple () diff --git a/master/_sources/api/cassandra/graph.rst.txt b/master/_sources/api/cassandra/graph.rst.txt new file mode 100644 index 0000000000..43ddd3086c --- /dev/null +++ b/master/_sources/api/cassandra/graph.rst.txt @@ -0,0 +1,121 @@ +``cassandra.graph`` - Graph Statements, Options, and Row Factories +================================================================== + +.. note:: This module is only for backward compatibility for dse-driver users. Consider using :ref:`cassandra.datastax.graph `. + +.. module:: cassandra.graph + +.. autofunction:: single_object_row_factory + +.. autofunction:: graph_result_row_factory + +.. autofunction:: graph_object_row_factory + +.. autofunction:: graph_graphson2_row_factory + +.. autofunction:: graph_graphson3_row_factory + +.. function:: to_int(value) + + Wraps a value to be explicitly serialized as a graphson Int. + +.. function:: to_bigint(value) + + Wraps a value to be explicitly serialized as a graphson Bigint. + +.. function:: to_smallint(value) + + Wraps a value to be explicitly serialized as a graphson Smallint. + +.. function:: to_float(value) + + Wraps a value to be explicitly serialized as a graphson Float. + +.. function:: to_double(value) + + Wraps a value to be explicitly serialized as a graphson Double. + +.. autoclass:: GraphProtocol + :members: + +.. autoclass:: GraphOptions + + .. autoattribute:: graph_name + + .. autoattribute:: graph_source + + .. autoattribute:: graph_language + + .. autoattribute:: graph_read_consistency_level + + .. autoattribute:: graph_write_consistency_level + + .. autoattribute:: is_default_source + + .. autoattribute:: is_analytics_source + + .. autoattribute:: is_graph_source + + .. automethod:: set_source_default + + .. automethod:: set_source_analytics + + .. automethod:: set_source_graph + + +.. autoclass:: SimpleGraphStatement + :members: + +.. autoclass:: Result + :members: + +.. autoclass:: Vertex + :members: + +.. autoclass:: VertexProperty + :members: + +.. autoclass:: Edge + :members: + +.. autoclass:: Path + :members: + +.. autoclass:: GraphSON1Serializer + :members: + +.. autoclass:: GraphSON1Deserializer + + .. automethod:: deserialize_date + + .. automethod:: deserialize_timestamp + + .. automethod:: deserialize_time + + .. automethod:: deserialize_duration + + .. automethod:: deserialize_int + + .. automethod:: deserialize_bigint + + .. automethod:: deserialize_double + + .. automethod:: deserialize_float + + .. automethod:: deserialize_uuid + + .. automethod:: deserialize_blob + + .. automethod:: deserialize_decimal + + .. automethod:: deserialize_point + + .. automethod:: deserialize_linestring + + .. automethod:: deserialize_polygon + +.. autoclass:: GraphSON2Reader + :members: + +.. autoclass:: GraphSON3Reader + :members: diff --git a/master/_sources/api/cassandra/io/asyncioreactor.rst.txt b/master/_sources/api/cassandra/io/asyncioreactor.rst.txt new file mode 100644 index 0000000000..38ae63ca7f --- /dev/null +++ b/master/_sources/api/cassandra/io/asyncioreactor.rst.txt @@ -0,0 +1,7 @@ +``cassandra.io.asyncioreactor`` - ``asyncio`` Event Loop +===================================================================== + +.. module:: cassandra.io.asyncioreactor + +.. autoclass:: AsyncioConnection + :members: diff --git a/master/_sources/api/cassandra/io/asyncorereactor.rst.txt b/master/_sources/api/cassandra/io/asyncorereactor.rst.txt new file mode 100644 index 0000000000..ade7887e70 --- /dev/null +++ b/master/_sources/api/cassandra/io/asyncorereactor.rst.txt @@ -0,0 +1,7 @@ +``cassandra.io.asyncorereactor`` - ``asyncore`` Event Loop +========================================================== + +.. module:: cassandra.io.asyncorereactor + +.. autoclass:: AsyncoreConnection + :members: diff --git a/master/_sources/api/cassandra/io/eventletreactor.rst.txt b/master/_sources/api/cassandra/io/eventletreactor.rst.txt new file mode 100644 index 0000000000..1ba742c7e9 --- /dev/null +++ b/master/_sources/api/cassandra/io/eventletreactor.rst.txt @@ -0,0 +1,7 @@ +``cassandra.io.eventletreactor`` - ``eventlet``-compatible Connection +===================================================================== + +.. module:: cassandra.io.eventletreactor + +.. autoclass:: EventletConnection + :members: diff --git a/master/_sources/api/cassandra/io/geventreactor.rst.txt b/master/_sources/api/cassandra/io/geventreactor.rst.txt new file mode 100644 index 0000000000..603affe140 --- /dev/null +++ b/master/_sources/api/cassandra/io/geventreactor.rst.txt @@ -0,0 +1,7 @@ +``cassandra.io.geventreactor`` - ``gevent``-compatible Event Loop +================================================================= + +.. module:: cassandra.io.geventreactor + +.. autoclass:: GeventConnection + :members: diff --git a/master/_sources/api/cassandra/io/libevreactor.rst.txt b/master/_sources/api/cassandra/io/libevreactor.rst.txt new file mode 100644 index 0000000000..5b7288edf2 --- /dev/null +++ b/master/_sources/api/cassandra/io/libevreactor.rst.txt @@ -0,0 +1,6 @@ +``cassandra.io.libevreactor`` - ``libev`` Event Loop +==================================================== + +.. module:: cassandra.io.libevreactor + +.. autoclass:: LibevConnection diff --git a/master/_sources/api/cassandra/io/twistedreactor.rst.txt b/master/_sources/api/cassandra/io/twistedreactor.rst.txt new file mode 100644 index 0000000000..24e93bd432 --- /dev/null +++ b/master/_sources/api/cassandra/io/twistedreactor.rst.txt @@ -0,0 +1,9 @@ +``cassandra.io.twistedreactor`` - Twisted Event Loop +==================================================== + +.. module:: cassandra.io.twistedreactor + +.. class:: TwistedConnection + + An implementation of :class:`~cassandra.io.connection.Connection` that uses + Twisted's reactor as its event loop. diff --git a/master/_sources/api/cassandra/metadata.rst.txt b/master/_sources/api/cassandra/metadata.rst.txt new file mode 100644 index 0000000000..7c1280bcf7 --- /dev/null +++ b/master/_sources/api/cassandra/metadata.rst.txt @@ -0,0 +1,93 @@ +``cassandra.metadata`` - Schema and Ring Topology +================================================= + +.. module:: cassandra.metadata + +.. autodata:: cql_keywords + :annotation: + +.. autodata:: cql_keywords_unreserved + :annotation: + +.. autodata:: cql_keywords_reserved + :annotation: + +.. autoclass:: Metadata () + :members: + :exclude-members: rebuild_schema, rebuild_token_map, add_host, remove_host + +Schemas +------- + +.. autoclass:: KeyspaceMetadata () + :members: + +.. autoclass:: UserType () + :members: + +.. autoclass:: Function () + :members: + +.. autoclass:: Aggregate () + :members: + +.. autoclass:: TableMetadata () + :members: + +.. autoclass:: TableMetadataV3 () + :members: + +.. autoclass:: TableMetadataDSE68 () + :members: + +.. autoclass:: ColumnMetadata () + :members: + +.. autoclass:: IndexMetadata () + :members: + +.. autoclass:: MaterializedViewMetadata () + :members: + +.. autoclass:: VertexMetadata () + :members: + +.. autoclass:: EdgeMetadata () + :members: + +Tokens and Ring Topology +------------------------ + +.. autoclass:: TokenMap () + :members: + +.. autoclass:: Token () + :members: + +.. autoclass:: Murmur3Token + :members: + +.. autoclass:: MD5Token + :members: + +.. autoclass:: BytesToken + :members: + +.. autoclass:: ReplicationStrategy + :members: + +.. autoclass:: ReplicationFactor + :members: + :exclude-members: create + +.. autoclass:: SimpleStrategy + :members: + +.. autoclass:: NetworkTopologyStrategy + :members: + +.. autoclass:: LocalStrategy + :members: + +.. autofunction:: group_keys_by_replica + diff --git a/master/_sources/api/cassandra/metrics.rst.txt b/master/_sources/api/cassandra/metrics.rst.txt new file mode 100644 index 0000000000..0df7f8b5b9 --- /dev/null +++ b/master/_sources/api/cassandra/metrics.rst.txt @@ -0,0 +1,7 @@ +``cassandra.metrics`` - Performance Metrics +=========================================== + +.. module:: cassandra.metrics + +.. autoclass:: cassandra.metrics.Metrics () + :members: diff --git a/master/_sources/api/cassandra/policies.rst.txt b/master/_sources/api/cassandra/policies.rst.txt new file mode 100644 index 0000000000..387b19ed95 --- /dev/null +++ b/master/_sources/api/cassandra/policies.rst.txt @@ -0,0 +1,96 @@ +``cassandra.policies`` - Load balancing and Failure Handling Policies +===================================================================== + +.. module:: cassandra.policies + +Load Balancing +-------------- + +.. autoclass:: HostDistance + :members: + +.. autoclass:: LoadBalancingPolicy + :members: + +.. autoclass:: RoundRobinPolicy + :members: + +.. autoclass:: DCAwareRoundRobinPolicy + :members: + +.. autoclass:: WhiteListRoundRobinPolicy + :members: + +.. autoclass:: TokenAwarePolicy + :members: + +.. autoclass:: HostFilterPolicy + + .. we document these methods manually so we can specify a param to predicate + + .. automethod:: predicate(host) + .. automethod:: distance + .. automethod:: make_query_plan + +.. autoclass:: DefaultLoadBalancingPolicy + :members: + +.. autoclass:: DSELoadBalancingPolicy + :members: + +Translating Server Node Addresses +--------------------------------- + +.. autoclass:: AddressTranslator + :members: + +.. autoclass:: IdentityTranslator + :members: + +.. autoclass:: EC2MultiRegionTranslator + :members: + +Marking Hosts Up or Down +------------------------ + +.. autoclass:: ConvictionPolicy + :members: + +.. autoclass:: SimpleConvictionPolicy + :members: + +Reconnecting to Dead Hosts +-------------------------- + +.. autoclass:: ReconnectionPolicy + :members: + +.. autoclass:: ConstantReconnectionPolicy + :members: + +.. autoclass:: ExponentialReconnectionPolicy + :members: + +Retrying Failed Operations +-------------------------- + +.. autoclass:: WriteType + :members: + +.. autoclass:: RetryPolicy + :members: + +.. autoclass:: FallthroughRetryPolicy + :members: + +.. autoclass:: DowngradingConsistencyRetryPolicy + :members: + +Retrying Idempotent Operations +------------------------------ + +.. autoclass:: SpeculativeExecutionPolicy + :members: + +.. autoclass:: ConstantSpeculativeExecutionPolicy + :members: diff --git a/master/_sources/api/cassandra/pool.rst.txt b/master/_sources/api/cassandra/pool.rst.txt new file mode 100644 index 0000000000..b14d30e19c --- /dev/null +++ b/master/_sources/api/cassandra/pool.rst.txt @@ -0,0 +1,11 @@ +``cassandra.pool`` - Hosts and Connection Pools +=============================================== + +.. automodule:: cassandra.pool + +.. autoclass:: Host () + :members: + :exclude-members: set_location_info, get_and_set_reconnection_handler + +.. autoexception:: NoConnectionsAvailable + :members: diff --git a/master/_sources/api/cassandra/protocol.rst.txt b/master/_sources/api/cassandra/protocol.rst.txt new file mode 100644 index 0000000000..f615ab1a70 --- /dev/null +++ b/master/_sources/api/cassandra/protocol.rst.txt @@ -0,0 +1,55 @@ +``cassandra.protocol`` - Protocol Features +===================================================================== + +.. module:: cassandra.protocol + +.. _custom_payload: + +Custom Payloads +--------------- +Native protocol version 4+ allows for a custom payload to be sent between clients +and custom query handlers. The payload is specified as a string:binary_type dict +holding custom key/value pairs. + +By default these are ignored by the server. They can be useful for servers implementing +a custom QueryHandler. + +See :meth:`.Session.execute`, ::meth:`.Session.execute_async`, :attr:`.ResponseFuture.custom_payload`. + +.. autoclass:: _ProtocolHandler + + .. autoattribute:: message_types_by_opcode + :annotation: = {default mapping} + + .. automethod:: encode_message + + .. automethod:: decode_message + +.. _faster_deser: + +Faster Deserialization +---------------------- +When python-driver is compiled with Cython, it uses a Cython-based deserialization path +to deserialize messages. By default, the driver will use a Cython-based parser that returns +lists of rows similar to the pure-Python version. In addition, there are two additional +ProtocolHandler classes that can be used to deserialize response messages: ``LazyProtocolHandler`` +and ``NumpyProtocolHandler``. They can be used as follows: + +.. code:: python + + from cassandra.protocol import NumpyProtocolHandler, LazyProtocolHandler + from cassandra.query import tuple_factory + s.client_protocol_handler = LazyProtocolHandler # for a result iterator + s.row_factory = tuple_factory #required for Numpy results + s.client_protocol_handler = NumpyProtocolHandler # for a dict of NumPy arrays as result + +These protocol handlers comprise different parsers, and return results as described below: + +- ProtocolHandler: this default implementation is a drop-in replacement for the pure-Python version. + The rows are all parsed upfront, before results are returned. + +- LazyProtocolHandler: near drop-in replacement for the above, except that it returns an iterator over rows, + lazily decoded into the default row format (this is more efficient since all decoded results are not materialized at once) + +- NumpyProtocolHander: deserializes results directly into NumPy arrays. This facilitates efficient integration with + analysis toolkits such as Pandas. diff --git a/master/_sources/api/cassandra/query.rst.txt b/master/_sources/api/cassandra/query.rst.txt new file mode 100644 index 0000000000..fcd79739b9 --- /dev/null +++ b/master/_sources/api/cassandra/query.rst.txt @@ -0,0 +1,59 @@ +``cassandra.query`` - Prepared Statements, Batch Statements, Tracing, and Row Factories +======================================================================================= + +.. module:: cassandra.query + +.. autofunction:: tuple_factory + +.. autofunction:: named_tuple_factory + +.. autofunction:: dict_factory + +.. autofunction:: ordered_dict_factory + +.. autoclass:: SimpleStatement + :members: + +.. autoclass:: PreparedStatement () + :members: + +.. autoclass:: BoundStatement + :members: + +.. autoclass:: Statement () + :members: + +.. autodata:: UNSET_VALUE + :annotation: + +.. autoclass:: BatchStatement (batch_type=BatchType.LOGGED, retry_policy=None, consistency_level=None) + :members: + +.. autoclass:: BatchType () + + .. autoattribute:: LOGGED + + .. autoattribute:: UNLOGGED + + .. autoattribute:: COUNTER + +.. autoclass:: cassandra.query.ValueSequence + + A wrapper class that is used to specify that a sequence of values should + be treated as a CQL list of values instead of a single column collection when used + as part of the `parameters` argument for :meth:`.Session.execute()`. + + This is typically needed when supplying a list of keys to select. + For example:: + + >>> my_user_ids = ('alice', 'bob', 'charles') + >>> query = "SELECT * FROM users WHERE user_id IN %s" + >>> session.execute(query, parameters=[ValueSequence(my_user_ids)]) + +.. autoclass:: QueryTrace () + :members: + +.. autoclass:: TraceEvent () + :members: + +.. autoexception:: TraceUnavailable diff --git a/master/_sources/api/cassandra/timestamps.rst.txt b/master/_sources/api/cassandra/timestamps.rst.txt new file mode 100644 index 0000000000..00d25b06d9 --- /dev/null +++ b/master/_sources/api/cassandra/timestamps.rst.txt @@ -0,0 +1,14 @@ +``cassandra.timestamps`` - Timestamp Generation +=============================================== + +.. module:: cassandra.timestamps + +.. autoclass:: MonotonicTimestampGenerator (warn_on_drift=True, warning_threshold=0, warning_interval=0) + + .. autoattribute:: warn_on_drift + + .. autoattribute:: warning_threshold + + .. autoattribute:: warning_interval + + .. automethod:: _next_timestamp diff --git a/master/_sources/api/cassandra/util.rst.txt b/master/_sources/api/cassandra/util.rst.txt new file mode 100644 index 0000000000..848d4d5fc2 --- /dev/null +++ b/master/_sources/api/cassandra/util.rst.txt @@ -0,0 +1,5 @@ +``cassandra.util`` - Utilities +=================================== + +.. automodule:: cassandra.util + :members: diff --git a/master/_sources/api/index.rst.txt b/master/_sources/api/index.rst.txt new file mode 100644 index 0000000000..9e778d508c --- /dev/null +++ b/master/_sources/api/index.rst.txt @@ -0,0 +1,54 @@ +API Documentation +================= + +Core Driver +----------- +.. toctree:: + :maxdepth: 2 + + cassandra + cassandra/cluster + cassandra/policies + cassandra/auth + cassandra/graph + cassandra/metadata + cassandra/metrics + cassandra/query + cassandra/pool + cassandra/protocol + cassandra/encoder + cassandra/decoder + cassandra/concurrent + cassandra/connection + cassandra/util + cassandra/timestamps + cassandra/io/asyncioreactor + cassandra/io/asyncorereactor + cassandra/io/eventletreactor + cassandra/io/libevreactor + cassandra/io/geventreactor + cassandra/io/twistedreactor + +.. _om_api: + +Object Mapper +------------- +.. toctree:: + :maxdepth: 1 + + cassandra/cqlengine/models + cassandra/cqlengine/columns + cassandra/cqlengine/query + cassandra/cqlengine/connection + cassandra/cqlengine/management + cassandra/cqlengine/usertype + +DataStax Graph +-------------- +.. toctree:: + :maxdepth: 1 + + cassandra/datastax/graph/index + cassandra/datastax/graph/fluent/index + cassandra/datastax/graph/fluent/query + cassandra/datastax/graph/fluent/predicates diff --git a/master/_sources/cqlengine/batches.rst.txt b/master/_sources/cqlengine/batches.rst.txt new file mode 100644 index 0000000000..306e7d01a6 --- /dev/null +++ b/master/_sources/cqlengine/batches.rst.txt @@ -0,0 +1,108 @@ +============= +Batch Queries +============= + +cqlengine supports batch queries using the BatchQuery class. Batch queries can be started and stopped manually, or within a context manager. To add queries to the batch object, you just need to precede the create/save/delete call with a call to batch, and pass in the batch object. + + +Batch Query General Use Pattern +=============================== + +You can only create, update, and delete rows with a batch query, attempting to read rows out of the database with a batch query will fail. + +.. code-block:: python + + from cassandra.cqlengine.query import BatchQuery + + #using a context manager + with BatchQuery() as b: + now = datetime.now() + em1 = ExampleModel.batch(b).create(example_type=0, description="1", created_at=now) + em2 = ExampleModel.batch(b).create(example_type=0, description="2", created_at=now) + em3 = ExampleModel.batch(b).create(example_type=0, description="3", created_at=now) + + # -- or -- + + #manually + b = BatchQuery() + now = datetime.now() + em1 = ExampleModel.batch(b).create(example_type=0, description="1", created_at=now) + em2 = ExampleModel.batch(b).create(example_type=0, description="2", created_at=now) + em3 = ExampleModel.batch(b).create(example_type=0, description="3", created_at=now) + b.execute() + + # updating in a batch + + b = BatchQuery() + em1.description = "new description" + em1.batch(b).save() + em2.description = "another new description" + em2.batch(b).save() + b.execute() + + # deleting in a batch + b = BatchQuery() + ExampleModel.objects(id=some_id).batch(b).delete() + ExampleModel.objects(id=some_id2).batch(b).delete() + b.execute() + + +Typically you will not want the block to execute if an exception occurs inside the `with` block. However, in the case that this is desirable, it's achievable by using the following syntax: + +.. code-block:: python + + with BatchQuery(execute_on_exception=True) as b: + LogEntry.batch(b).create(k=1, v=1) + mystery_function() # exception thrown in here + LogEntry.batch(b).create(k=1, v=2) # this code is never reached due to the exception, but anything leading up to here will execute in the batch. + +If an exception is thrown somewhere in the block, any statements that have been added to the batch will still be executed. This is useful for some logging situations. + +Batch Query Execution Callbacks +=============================== + +In order to allow secondary tasks to be chained to the end of batch, BatchQuery instances allow callbacks to be +registered with the batch, to be executed immediately after the batch executes. + +Multiple callbacks can be attached to same BatchQuery instance, they are executed in the same order that they +are added to the batch. + +The callbacks attached to a given batch instance are executed only if the batch executes. If the batch is used as a +context manager and an exception is raised, the queued up callbacks will not be run. + +.. code-block:: python + + def my_callback(*args, **kwargs): + pass + + batch = BatchQuery() + + batch.add_callback(my_callback) + batch.add_callback(my_callback, 'positional arg', named_arg='named arg value') + + # if you need reference to the batch within the callback, + # just trap it in the arguments to be passed to the callback: + batch.add_callback(my_callback, cqlengine_batch=batch) + + # once the batch executes... + batch.execute() + + # the effect of the above scheduled callbacks will be similar to + my_callback() + my_callback('positional arg', named_arg='named arg value') + my_callback(cqlengine_batch=batch) + +Failure in any of the callbacks does not affect the batch's execution, as the callbacks are started after the execution +of the batch is complete. + +Logged vs Unlogged Batches +--------------------------- +By default, queries in cqlengine are LOGGED, which carries additional overhead from UNLOGGED. To explicitly state which batch type to use, simply: + + +.. code-block:: python + + from cassandra.cqlengine.query import BatchType + with BatchQuery(batch_type=BatchType.Unlogged) as b: + LogEntry.batch(b).create(k=1, v=1) + LogEntry.batch(b).create(k=1, v=2) diff --git a/master/_sources/cqlengine/connections.rst.txt b/master/_sources/cqlengine/connections.rst.txt new file mode 100644 index 0000000000..03ade27521 --- /dev/null +++ b/master/_sources/cqlengine/connections.rst.txt @@ -0,0 +1,137 @@ +=========== +Connections +=========== + +Connections aim to ease the use of multiple sessions with cqlengine. Connections can be set on a model class, per query or using a context manager. + + +Register a new connection +========================= + +To use cqlengine, you need at least a default connection. If you initialize cqlengine's connections with with :func:`connection.setup <.connection.setup>`, a connection will be created automatically. If you want to use another cluster/session, you need to register a new cqlengine connection. You register a connection with :func:`~.connection.register_connection`: + +.. code-block:: python + + from cassandra.cqlengine import connection + + connection.setup(['127.0.0.1') + connection.register_connection('cluster2', ['127.0.0.2']) + +:func:`~.connection.register_connection` can take a list of hosts, as shown above, in which case it will create a connection with a new session. It can also take a `session` argument if you've already created a session: + +.. code-block:: python + + from cassandra.cqlengine import connection + from cassandra.cluster import Cluster + + session = Cluster(['127.0.0.1']).connect() + connection.register_connection('cluster3', session=session) + + +Change the default connection +============================= + +You can change the default cqlengine connection on registration: + +.. code-block:: python + + from cassandra.cqlengine import connection + + connection.register_connection('cluster2', ['127.0.0.2'] default=True) + +or on the fly using :func:`~.connection.set_default_connection` + +.. code-block:: python + + connection.set_default_connection('cluster2') + +Unregister a connection +======================= + +You can unregister a connection using :func:`~.connection.unregister_connection`: + +.. code-block:: python + + connection.unregister_connection('cluster2') + +Management +========== + +When using multiples connections, you also need to sync your models on all connections (and keyspaces) that you need operate on. Management commands have been improved to ease this part. Here is an example: + +.. code-block:: python + + from cassandra.cqlengine import management + + keyspaces = ['ks1', 'ks2'] + conns = ['cluster1', 'cluster2'] + + # registers your connections + # ... + + # create all keyspaces on all connections + for ks in keyspaces: + management.create_simple_keyspace(ks, connections=conns) + + # define your Automobile model + # ... + + # sync your models + management.sync_table(Automobile, keyspaces=keyspaces, connections=conns) + + +Connection Selection +==================== + +cqlengine will select the default connection, unless your specify a connection using one of the following methods. + +Default Model Connection +------------------------ + +You can specify a default connection per model: + +.. code-block:: python + + class Automobile(Model): + __keyspace__ = 'test' + __connection__ = 'cluster2' + manufacturer = columns.Text(primary_key=True) + year = columns.Integer(primary_key=True) + model = columns.Text(primary_key=True) + + print len(Automobile.objects.all()) # executed on the connection 'cluster2' + +QuerySet and model instance +--------------------------- + +You can use the :attr:`using() <.query.ModelQuerySet.using>` method to select a connection (or keyspace): + +.. code-block:: python + + Automobile.objects.using(connection='cluster1').create(manufacturer='honda', year=2010, model='civic') + q = Automobile.objects.filter(manufacturer='Tesla') + autos = q.using(keyspace='ks2', connection='cluster2').all() + + for auto in autos: + auto.using(connection='cluster1').save() + +Context Manager +--------------- + +You can use the ContextQuery as well to select a connection: + +.. code-block:: python + + with ContextQuery(Automobile, connection='cluster1') as A: + A.objects.filter(manufacturer='honda').all() # executed on 'cluster1' + + +BatchQuery +---------- + +With a BatchQuery, you can select the connection with the context manager. Note that all operations in the batch need to use the same connection. + +.. code-block:: python + + with BatchQuery(connection='cluster1') as b: + Automobile.objects.batch(b).create(manufacturer='honda', year=2010, model='civic') diff --git a/master/_sources/cqlengine/faq.rst.txt b/master/_sources/cqlengine/faq.rst.txt new file mode 100644 index 0000000000..6c056d02ea --- /dev/null +++ b/master/_sources/cqlengine/faq.rst.txt @@ -0,0 +1,67 @@ +========================== +Frequently Asked Questions +========================== + +Why don't updates work correctly on models instantiated as Model(field=value, field2=value2)? +------------------------------------------------------------------------------------------------ + +The recommended way to create new rows is with the models .create method. The values passed into a model's init method are interpreted by the model as the values as they were read from a row. This allows the model to "know" which rows have changed since the row was read out of cassandra, and create suitable update statements. + +How to preserve ordering in batch query? +------------------------------------------- + +Statement Ordering is not supported by CQL3 batches. Therefore, +once cassandra needs resolving conflict(Updating the same column in one batch), +The algorithm below would be used. + +* If timestamps are different, pick the column with the largest timestamp (the value being a regular column or a tombstone) +* If timestamps are the same, and one of the columns in a tombstone ('null') - pick the tombstone +* If timestamps are the same, and none of the columns are tombstones, pick the column with the largest value + +Below is an example to show this scenario. + +.. code-block:: python + + class MyMode(Model): + id = columns.Integer(primary_key=True) + count = columns.Integer() + text = columns.Text() + + with BatchQuery() as b: + MyModel.batch(b).create(id=1, count=2, text='123') + MyModel.batch(b).create(id=1, count=3, text='111') + + assert MyModel.objects(id=1).first().count == 3 + assert MyModel.objects(id=1).first().text == '123' + +The largest value of count is 3, and the largest value of text would be '123'. + +The workaround is applying timestamp to each statement, then Cassandra would +resolve to the statement with the lastest timestamp. + +.. code-block:: python + + with BatchQuery() as b: + MyModel.timestamp(datetime.now()).batch(b).create(id=1, count=2, text='123') + MyModel.timestamp(datetime.now()).batch(b).create(id=1, count=3, text='111') + + assert MyModel.objects(id=1).first().count == 3 + assert MyModel.objects(id=1).first().text == '111' + +How can I delete individual values from a row? +------------------------------------------------- + +When inserting with CQLEngine, ``None`` is equivalent to CQL ``NULL`` or to +issuing a ``DELETE`` on that column. For example: + +.. code-block:: python + + class MyModel(Model): + id = columns.Integer(primary_key=True) + text = columns.Text() + + m = MyModel.create(id=1, text='We can delete this with None') + assert MyModel.objects(id=1).first().text is not None + + m.update(text=None) + assert MyModel.objects(id=1).first().text is None diff --git a/master/_sources/cqlengine/models.rst.txt b/master/_sources/cqlengine/models.rst.txt new file mode 100644 index 0000000000..c0ba390119 --- /dev/null +++ b/master/_sources/cqlengine/models.rst.txt @@ -0,0 +1,218 @@ +====== +Models +====== + +.. module:: cqlengine.models + +A model is a python class representing a CQL table. Models derive from :class:`Model`, and +define basic table properties and columns for a table. + +Columns in your models map to columns in your CQL table. You define CQL columns by defining column attributes on your model classes. +For a model to be valid it needs at least one primary key column and one non-primary key column. Just as in CQL, the order you define +your columns in is important, and is the same order they are defined in on a model's corresponding table. + +Some basic examples defining models are shown below. Consult the :doc:`Model API docs ` and :doc:`Column API docs ` for complete details. + +Example Definitions +=================== + +This example defines a ``Person`` table, with the columns ``first_name`` and ``last_name`` + +.. code-block:: python + + from cassandra.cqlengine import columns + from cassandra.cqlengine.models import Model + + class Person(Model): + id = columns.UUID(primary_key=True) + first_name = columns.Text() + last_name = columns.Text() + + +The Person model would create this CQL table: + +.. code-block:: sql + + CREATE TABLE cqlengine.person ( + id uuid, + first_name text, + last_name text, + PRIMARY KEY (id) + ); + +Here's an example of a comment table created with clustering keys, in descending order: + +.. code-block:: python + + from cassandra.cqlengine import columns + from cassandra.cqlengine.models import Model + + class Comment(Model): + photo_id = columns.UUID(primary_key=True) + comment_id = columns.TimeUUID(primary_key=True, clustering_order="DESC") + comment = columns.Text() + +The Comment model's ``create table`` would look like the following: + +.. code-block:: sql + + CREATE TABLE comment ( + photo_id uuid, + comment_id timeuuid, + comment text, + PRIMARY KEY (photo_id, comment_id) + ) WITH CLUSTERING ORDER BY (comment_id DESC); + +To sync the models to the database, you may do the following*: + +.. code-block:: python + + from cassandra.cqlengine.management import sync_table + sync_table(Person) + sync_table(Comment) + +\*Note: synchronizing models causes schema changes, and should be done with caution. +Please see the discussion in :doc:`/api/cassandra/cqlengine/management` for considerations. + +For examples on manipulating data and creating queries, see :doc:`queryset` + +Manipulating model instances as dictionaries +============================================ + +Model instances can be accessed like dictionaries. + +.. code-block:: python + + class Person(Model): + first_name = columns.Text() + last_name = columns.Text() + + kevin = Person.create(first_name="Kevin", last_name="Deldycke") + dict(kevin) # returns {'first_name': 'Kevin', 'last_name': 'Deldycke'} + kevin['first_name'] # returns 'Kevin' + kevin.keys() # returns ['first_name', 'last_name'] + kevin.values() # returns ['Kevin', 'Deldycke'] + kevin.items() # returns [('first_name', 'Kevin'), ('last_name', 'Deldycke')] + + kevin['first_name'] = 'KEVIN5000' # changes the models first name + +Extending Model Validation +========================== + +Each time you save a model instance in cqlengine, the data in the model is validated against the schema you've defined +for your model. Most of the validation is fairly straightforward, it basically checks that you're not trying to do +something like save text into an integer column, and it enforces the ``required`` flag set on column definitions. +It also performs any transformations needed to save the data properly. + +However, there are often additional constraints or transformations you want to impose on your data, beyond simply +making sure that Cassandra won't complain when you try to insert it. To define additional validation on a model, +extend the model's validation method: + +.. code-block:: python + + class Member(Model): + person_id = UUID(primary_key=True) + name = Text(required=True) + + def validate(self): + super(Member, self).validate() + if self.name == 'jon': + raise ValidationError('no jon\'s allowed') + +*Note*: while not required, the convention is to raise a ``ValidationError`` (``from cassandra.cqlengine import ValidationError``) +if validation fails. + +.. _model_inheritance: + +Model Inheritance +================= +It is possible to save and load different model classes using a single CQL table. +This is useful in situations where you have different object types that you want to store in a single cassandra row. + +For instance, suppose you want a table that stores rows of pets owned by an owner: + +.. code-block:: python + + class Pet(Model): + __table_name__ = 'pet' + owner_id = UUID(primary_key=True) + pet_id = UUID(primary_key=True) + pet_type = Text(discriminator_column=True) + name = Text() + + def eat(self, food): + pass + + def sleep(self, time): + pass + + class Cat(Pet): + __discriminator_value__ = 'cat' + cuteness = Float() + + def tear_up_couch(self): + pass + + class Dog(Pet): + __discriminator_value__ = 'dog' + fierceness = Float() + + def bark_all_night(self): + pass + +After calling ``sync_table`` on each of these tables, the columns defined in each model will be added to the +``pet`` table. Additionally, saving ``Cat`` and ``Dog`` models will save the meta data needed to identify each row +as either a cat or dog. + +To setup a model structure with inheritance, follow these steps + +1. Create a base model with a column set as the distriminator (``distriminator_column=True`` in the column definition) +2. Create subclass models, and define a unique ``__discriminator_value__`` value on each +3. Run ``sync_table`` on each of the sub tables + +**About the discriminator value** + +The discriminator value is what cqlengine uses under the covers to map logical cql rows to the appropriate model type. The +base model maintains a map of discriminator values to subclasses. When a specialized model is saved, its discriminator value is +automatically saved into the discriminator column. The discriminator column may be any column type except counter and container types. +Additionally, if you set ``index=True`` on your discriminator column, you can execute queries against specialized subclasses, and a +``WHERE`` clause will be automatically added to your query, returning only rows of that type. Note that you must +define a unique ``__discriminator_value__`` to each subclass, and that you can only assign a single discriminator column per model. + +.. _user_types: + +User Defined Types +================== +cqlengine models User Defined Types (UDTs) much like tables, with fields defined by column type attributes. However, UDT instances +are only created, presisted, and queried via table Models. A short example to introduce the pattern:: + + from cassandra.cqlengine.columns import * + from cassandra.cqlengine.models import Model + from cassandra.cqlengine.usertype import UserType + + class address(UserType): + street = Text() + zipcode = Integer() + + class users(Model): + __keyspace__ = 'account' + name = Text(primary_key=True) + addr = UserDefinedType(address) + + users.create(name="Joe", addr=address(street="Easy St.", zipcode=99999)) + user = users.objects(name="Joe")[0] + print user.name, user.addr + # Joe address(street=u'Easy St.', zipcode=99999) + +UDTs are modeled by inheriting :class:`~.usertype.UserType`, and setting column type attributes. Types are then used in defining +models by declaring a column of type :class:`~.columns.UserDefinedType`, with the ``UserType`` class as a parameter. + +``sync_table`` will implicitly +synchronize any types contained in the table. Alternatively :func:`~.management.sync_type` can be used to create/alter types +explicitly. + +Upon declaration, types are automatically registered with the driver, so query results return instances of your ``UserType`` +class*. + +***Note**: UDTs were not added to the native protocol until v3. When setting up the cqlengine connection, be sure to specify +``protocol_version=3``. If using an earlier version, UDT queries will still work, but the returned type will be a namedtuple. diff --git a/master/_sources/cqlengine/queryset.rst.txt b/master/_sources/cqlengine/queryset.rst.txt new file mode 100644 index 0000000000..375ea22316 --- /dev/null +++ b/master/_sources/cqlengine/queryset.rst.txt @@ -0,0 +1,419 @@ +============== +Making Queries +============== + +.. module:: cqlengine.queryset + +Retrieving objects +================== +Once you've populated Cassandra with data, you'll probably want to retrieve some of it. This is accomplished with QuerySet objects. This section will describe how to use QuerySet objects to retrieve the data you're looking for. + +Retrieving all objects +---------------------- +The simplest query you can make is to return all objects from a table. + +This is accomplished with the ``.all()`` method, which returns a QuerySet of all objects in a table + +Using the Person example model, we would get all Person objects like this: + +.. code-block:: python + + all_objects = Person.objects.all() + +.. _retrieving-objects-with-filters: + +Retrieving objects with filters +------------------------------- +Typically, you'll want to query only a subset of the records in your database. + +That can be accomplished with the QuerySet's ``.filter(\*\*)`` method. + +For example, given the model definition: + +.. code-block:: python + + class Automobile(Model): + manufacturer = columns.Text(primary_key=True) + year = columns.Integer(primary_key=True) + model = columns.Text() + price = columns.Decimal() + options = columns.Set(columns.Text) + +...and assuming the Automobile table contains a record of every car model manufactured in the last 20 years or so, we can retrieve only the cars made by a single manufacturer like this: + + +.. code-block:: python + + q = Automobile.objects.filter(manufacturer='Tesla') + +You can also use the more convenient syntax: + +.. code-block:: python + + q = Automobile.objects(Automobile.manufacturer == 'Tesla') + +We can then further filter our query with another call to **.filter** + +.. code-block:: python + + q = q.filter(year=2012) + +*Note: all queries involving any filtering MUST define either an '=' or an 'in' relation to either a primary key column, or an indexed column.* + +Accessing objects in a QuerySet +=============================== + +There are several methods for getting objects out of a queryset + +* iterating over the queryset + .. code-block:: python + + for car in Automobile.objects.all(): + #...do something to the car instance + pass + +* list index + .. code-block:: python + + q = Automobile.objects.all() + q[0] #returns the first result + q[1] #returns the second result + + .. note:: + + * CQL does not support specifying a start position in it's queries. Therefore, accessing elements using array indexing will load every result up to the index value requested + * Using negative indices requires a "SELECT COUNT()" to be executed. This has a performance cost on large datasets. + +* list slicing + .. code-block:: python + + q = Automobile.objects.all() + q[1:] #returns all results except the first + q[1:9] #returns a slice of the results + + .. note:: + + * CQL does not support specifying a start position in it's queries. Therefore, accessing elements using array slicing will load every result up to the index value requested + * Using negative indices requires a "SELECT COUNT()" to be executed. This has a performance cost on large datasets. + +* calling :attr:`get() ` on the queryset + .. code-block:: python + + q = Automobile.objects.filter(manufacturer='Tesla') + q = q.filter(year=2012) + car = q.get() + + this returns the object matching the queryset + +* calling :attr:`first() ` on the queryset + .. code-block:: python + + q = Automobile.objects.filter(manufacturer='Tesla') + q = q.filter(year=2012) + car = q.first() + + this returns the first value in the queryset + +.. _query-filtering-operators: + +Filtering Operators +=================== + +:attr:`Equal To ` + +The default filtering operator. + +.. code-block:: python + + q = Automobile.objects.filter(manufacturer='Tesla') + q = q.filter(year=2012) #year == 2012 + +In addition to simple equal to queries, cqlengine also supports querying with other operators by appending a ``__`` to the field name on the filtering call + +:attr:`in (__in) ` + +.. code-block:: python + + q = Automobile.objects.filter(manufacturer='Tesla') + q = q.filter(year__in=[2011, 2012]) + + +:attr:`> (__gt) ` + +.. code-block:: python + + q = Automobile.objects.filter(manufacturer='Tesla') + q = q.filter(year__gt=2010) # year > 2010 + + # or the nicer syntax + + q.filter(Automobile.year > 2010) + +:attr:`>= (__gte) ` + +.. code-block:: python + + q = Automobile.objects.filter(manufacturer='Tesla') + q = q.filter(year__gte=2010) # year >= 2010 + + # or the nicer syntax + + q.filter(Automobile.year >= 2010) + +:attr:`< (__lt) ` + +.. code-block:: python + + q = Automobile.objects.filter(manufacturer='Tesla') + q = q.filter(year__lt=2012) # year < 2012 + + # or... + + q.filter(Automobile.year < 2012) + +:attr:`<= (__lte) ` + +.. code-block:: python + + q = Automobile.objects.filter(manufacturer='Tesla') + q = q.filter(year__lte=2012) # year <= 2012 + + q.filter(Automobile.year <= 2012) + +:attr:`CONTAINS (__contains) ` + +The CONTAINS operator is available for all collection types (List, Set, Map). + +.. code-block:: python + + q = Automobile.objects.filter(manufacturer='Tesla') + q.filter(options__contains='backup camera').allow_filtering() + +Note that we need to use allow_filtering() since the *options* column has no secondary index. + +:attr:`LIKE (__like) ` + +The LIKE operator is available for text columns that have a SASI secondary index. + +.. code-block:: python + + q = Automobile.objects.filter(model__like='%Civic%').allow_filtering() + +:attr:`IS NOT NULL (IsNotNull(column_name)) ` + +The IS NOT NULL operator is not yet supported for C*. + +.. code-block:: python + + q = Automobile.objects.filter(IsNotNull('model')) + +Limitations: + +- Currently, cqlengine does not support SASI index creation. To use this feature, you need to create the SASI index using the core driver. +- Queries using LIKE must use allow_filtering() since the *model* column has no standard secondary index. Note that the server will use the SASI index properly when executing the query. + +TimeUUID Functions +================== + +In addition to querying using regular values, there are two functions you can pass in when querying TimeUUID columns to help make filtering by them easier. Note that these functions don't actually return a value, but instruct the cql interpreter to use the functions in it's query. + +.. class:: MinTimeUUID(datetime) + + returns the minimum time uuid value possible for the given datetime + +.. class:: MaxTimeUUID(datetime) + + returns the maximum time uuid value possible for the given datetime + +*Example* + +.. code-block:: python + + class DataStream(Model): + id = columns.UUID(partition_key=True) + time = columns.TimeUUID(primary_key=True) + data = columns.Bytes() + + min_time = datetime(1982, 1, 1) + max_time = datetime(1982, 3, 9) + + DataStream.filter(time__gt=functions.MinTimeUUID(min_time), time__lt=functions.MaxTimeUUID(max_time)) + +Token Function +============== + +Token functon may be used only on special, virtual column pk__token, representing token of partition key (it also works for composite partition keys). +Cassandra orders returned items by value of partition key token, so using cqlengine.Token we can easy paginate through all table rows. + +See http://cassandra.apache.org/doc/cql3/CQL-3.0.html#tokenFun + +*Example* + +.. code-block:: python + + class Items(Model): + id = columns.Text(primary_key=True) + data = columns.Bytes() + + query = Items.objects.all().limit(10) + + first_page = list(query); + last = first_page[-1] + next_page = list(query.filter(pk__token__gt=cqlengine.Token(last.pk))) + +QuerySets are immutable +======================= + +When calling any method that changes a queryset, the method does not actually change the queryset object it's called on, but returns a new queryset object with the attributes of the original queryset, plus the attributes added in the method call. + +*Example* + +.. code-block:: python + + #this produces 3 different querysets + #q does not change after it's initial definition + q = Automobiles.objects.filter(year=2012) + tesla2012 = q.filter(manufacturer='Tesla') + honda2012 = q.filter(manufacturer='Honda') + +Ordering QuerySets +================== + +Since Cassandra is essentially a distributed hash table on steroids, the order you get records back in will not be particularly predictable. + +However, you can set a column to order on with the ``.order_by(column_name)`` method. + +*Example* + +.. code-block:: python + + #sort ascending + q = Automobiles.objects.all().order_by('year') + #sort descending + q = Automobiles.objects.all().order_by('-year') + +*Note: Cassandra only supports ordering on a clustering key. In other words, to support ordering results, your model must have more than one primary key, and you must order on a primary key, excluding the first one.* + +*For instance, given our Automobile model, year is the only column we can order on.* + +Values Lists +============ + +There is a special QuerySet's method ``.values_list()`` - when called, QuerySet returns lists of values instead of model instances. It may significantly speedup things with lower memory footprint for large responses. +Each tuple contains the value from the respective field passed into the ``values_list()`` call — so the first item is the first field, etc. For example: + +.. code-block:: python + + items = list(range(20)) + random.shuffle(items) + for i in items: + TestModel.create(id=1, clustering_key=i) + + values = list(TestModel.objects.values_list('clustering_key', flat=True)) + # [19L, 18L, 17L, 16L, 15L, 14L, 13L, 12L, 11L, 10L, 9L, 8L, 7L, 6L, 5L, 4L, 3L, 2L, 1L, 0L] + +Per Query Timeouts +=================== + +By default all queries are executed with the timeout defined in `~cqlengine.connection.setup()` +The examples below show how to specify a per-query timeout. +A timeout is specified in seconds and can be an int, float or None. +None means no timeout. + + +.. code-block:: python + + class Row(Model): + id = columns.Integer(primary_key=True) + name = columns.Text() + + +Fetch all objects with a timeout of 5 seconds + +.. code-block:: python + + Row.objects().timeout(5).all() + +Create a single row with a 50ms timeout + +.. code-block:: python + + Row(id=1, name='Jon').timeout(0.05).create() + +Delete a single row with no timeout + +.. code-block:: python + + Row(id=1).timeout(None).delete() + +Update a single row with no timeout + +.. code-block:: python + + Row(id=1).timeout(None).update(name='Blake') + +Batch query timeouts + +.. code-block:: python + + with BatchQuery(timeout=10) as b: + Row(id=1, name='Jon').create() + + +NOTE: You cannot set both timeout and batch at the same time, batch will use the timeout defined in it's constructor. +Setting the timeout on the model is meaningless and will raise an AssertionError. + + +.. _ttl-change: + +Default TTL and Per Query TTL +============================= + +Model default TTL now relies on the *default_time_to_live* feature, introduced in Cassandra 2.0. It is not handled anymore in the CQLEngine Model (scylla-driver >=3.6). You can set the default TTL of a table like this: + +Example: + +.. code-block:: python + + class User(Model): + __options__ = {'default_time_to_live': 20} + + user_id = columns.UUID(primary_key=True) + ... + +You can set TTL per-query if needed. Here are a some examples: + +Example: + +.. code-block:: python + + class User(Model): + __options__ = {'default_time_to_live': 20} + + user_id = columns.UUID(primary_key=True) + ... + + user = User.objects.create(user_id=1) # Default TTL 20 will be set automatically on the server + + user.ttl(30).update(age=21) # Update the TTL to 30 + User.objects.ttl(10).create(user_id=1) # TTL 10 + User(user_id=1, age=21).ttl(10).save() # TTL 10 + + +Named Tables +=================== + +Named tables are a way of querying a table without creating an class. They're useful for querying system tables or exploring an unfamiliar database. + + +.. code-block:: python + + from cassandra.cqlengine.connection import setup + setup("127.0.0.1", "cqlengine_test") + + from cassandra.cqlengine.named import NamedTable + user = NamedTable("cqlengine_test", "user") + user.objects() + user.objects()[0] + + # {u'pk': 1, u't': datetime.datetime(2014, 6, 26, 17, 10, 31, 774000)} diff --git a/master/_sources/cqlengine/third-party.rst.txt b/master/_sources/cqlengine/third-party.rst.txt new file mode 100644 index 0000000000..20c26df304 --- /dev/null +++ b/master/_sources/cqlengine/third-party.rst.txt @@ -0,0 +1,64 @@ +======================== +Third party integrations +======================== + + +Celery +------ + +Here's how, in substance, CQLengine can be plugged to `Celery +`_: + +.. code-block:: python + + from celery import Celery + from celery.signals import worker_process_init, beat_init + from cassandra.cqlengine import connection + from cassandra.cqlengine.connection import ( + cluster as cql_cluster, session as cql_session) + + def cassandra_init(**kwargs): + """ Initialize a clean Cassandra connection. """ + if cql_cluster is not None: + cql_cluster.shutdown() + if cql_session is not None: + cql_session.shutdown() + connection.setup() + + # Initialize worker context for both standard and periodic tasks. + worker_process_init.connect(cassandra_init) + beat_init.connect(cassandra_init) + + app = Celery() + + +uWSGI +----- + +This is the code required for proper connection handling of CQLengine for a +`uWSGI `_-run application: + +.. code-block:: python + + from cassandra.cqlengine import connection + from cassandra.cqlengine.connection import ( + cluster as cql_cluster, session as cql_session) + + try: + from uwsgidecorators import postfork + except ImportError: + # We're not in a uWSGI context, no need to hook Cassandra session + # initialization to the postfork event. + pass + else: + @postfork + def cassandra_init(**kwargs): + """ Initialize a new Cassandra session in the context. + + Ensures that a new session is returned for every new request. + """ + if cql_cluster is not None: + cql_cluster.shutdown() + if cql_session is not None: + cql_session.shutdown() + connection.setup() diff --git a/master/_sources/cqlengine/upgrade-guide.rst.txt b/master/_sources/cqlengine/upgrade-guide.rst.txt new file mode 100644 index 0000000000..5a10ebb757 --- /dev/null +++ b/master/_sources/cqlengine/upgrade-guide.rst.txt @@ -0,0 +1,155 @@ +======================== +Upgrade Guide +======================== + +This is an overview of things that changed as the cqlengine project was merged into +scylla-driver. While efforts were taken to preserve the API and most functionality exactly, +conversion to this package will still require certain minimal updates (namely, imports). + +**THERE IS ONE FUNCTIONAL CHANGE**, described in the first section below. + +Functional Changes +================== +List Prepend Reversing +---------------------- +Legacy cqlengine included a workaround for a Cassandra bug in which prepended list segments were +reversed (`CASSANDRA-8733 `_). As of +this integration, this workaround is removed. The first released integrated version emits +a warning when prepend is used. Subsequent versions will have this warning removed. + +Date Column Type +---------------- +The Date column type in legacy cqlengine used a ``timestamp`` CQL type and truncated the time. +Going forward, the :class:`~.columns.Date` type represents a ``date`` for Cassandra 2.2+ +(`PYTHON-245 `_). +Users of the legacy functionality should convert models to use :class:`~.columns.DateTime` (which +uses ``timestamp`` internally), and use the build-in ``datetime.date`` for input values. + +Remove cqlengine +================ +To avoid confusion or mistakes using the legacy package in your application, it +is prudent to remove the cqlengine package when upgrading to the integrated version. + +The driver setup script will warn if the legacy package is detected during install, +but it will not prevent side-by-side installation. + +Organization +============ +Imports +------- +cqlengine is now integrated as a sub-package of the driver base package 'cassandra'. +Upgrading will require adjusting imports to cqlengine. For example:: + + from cassandra.cqlengine import columns + +is now:: + + from cassandra.cqlengine import columns + +Package-Level Aliases +--------------------- +Legacy cqlengine defined a number of aliases at the package level, which became redundant +when the package was integrated for a driver. These have been removed in favor of absolute +imports, and referring to cannonical definitions. For example, ``cqlengine.ONE`` was an alias +of ``cassandra.ConsistencyLevel.ONE``. In the integrated package, only the +:class:`cassandra.ConsistencyLevel` remains. + +Additionally, submodule aliases are removed from cqlengine in favor of absolute imports. + +These aliases are removed, and not deprecated because they should be straightforward to iron out +at module load time. + +Exceptions +---------- +The legacy cqlengine.exceptions module had a number of Exception classes that were variously +common to the package, or only used in specific modules. Common exceptions were relocated to +cqlengine, and specialized exceptions were placed in the module that raises them. Below is a +listing of updated locations: + +============================ ========== +Exception class New module +============================ ========== +CQLEngineException cassandra.cqlengine +ModelException cassandra.cqlengine.models +ValidationError cassandra.cqlengine +UndefinedKeyspaceException cassandra.cqlengine.connection +LWTException cassandra.cqlengine.query +IfNotExistsWithCounterColumn cassandra.cqlengine.query +============================ ========== + +UnicodeMixin Consolidation +-------------------------- +``class UnicodeMixin`` was defined in several cqlengine modules. This has been consolidated +to a single definition in the cqlengine package init file. This is not technically part of +the API, but noted here for completeness. + +API Deprecations +================ +This upgrade served as a good juncture to deprecate certain API features and invite users to upgrade +to new ones. The first released version does not change functionality -- only introduces deprecation +warnings. Future releases will remove these features in favor of the alternatives. + +Float/Double Overload +--------------------- +Previously there was no ``Double`` column type. Doubles were modeled by specifying ``Float(double_precision=True)``. +This inititializer parameter is now deprecated. Applications should use :class:`~.columns.Double` for CQL ``double``, and :class:`~.columns.Float` +for CQL ``float``. + +Schema Management +----------------- +``cassandra.cqlengine.management.create_keyspace`` is deprecated. Instead, use the new replication-strategy-specific +functions that accept explicit options for known strategies: + +- :func:`~.create_keyspace_simple` +- :func:`~.create_keyspace_network_topology` + +``cassandra.cqlengine.management.delete_keyspace`` is deprecated in favor of a new function, :func:`~.drop_keyspace`. The +intent is simply to make the function match the CQL verb it invokes. + +Model Inheritance +----------------- +The names for class attributes controlling model inheritance are changing. Changes are as follows: + +- Replace 'polymorphic_key' in the base class Column definition with :attr:`~.discriminator_column` +- Replace the '__polymorphic_key__' class attribute the derived classes with :attr:`~.__discriminator_value__` + +The functionality is unchanged -- the intent here is to make the names and language around these attributes more precise. +For now, the old names are just deprecated, and the mapper will emit warnings if they are used. The old names +will be removed in a future version. + +The example below shows a simple translation: + +Before:: + + class Pet(Model): + __table_name__ = 'pet' + owner_id = UUID(primary_key=True) + pet_id = UUID(primary_key=True) + pet_type = Text(polymorphic_key=True) + name = Text() + + class Cat(Pet): + __polymorphic_key__ = 'cat' + + class Dog(Pet): + __polymorphic_key__ = 'dog' + +After:: + + class Pet(models.Model): + __table_name__ = 'pet' + owner_id = UUID(primary_key=True) + pet_id = UUID(primary_key=True) + pet_type = Text(discriminator_column=True) + name = Text() + + class Cat(Pet): + __discriminator_value__ = 'cat' + + class Dog(Pet): + __discriminator_value__ = 'dog' + + +TimeUUID.from_datetime +---------------------- +This function is deprecated in favor of the core utility function :func:`~.uuid_from_time`. diff --git a/master/_sources/dates-and-times.rst.txt b/master/_sources/dates-and-times.rst.txt new file mode 100644 index 0000000000..7a89f77437 --- /dev/null +++ b/master/_sources/dates-and-times.rst.txt @@ -0,0 +1,87 @@ +Working with Dates and Times +============================ + +This document is meant to provide on overview of the assumptions and limitations of the driver time handling, the +reasoning behind it, and describe approaches to working with these types. + +timestamps (Cassandra DateType) +------------------------------- + +Timestamps in Cassandra are timezone-naive timestamps encoded as millseconds since UNIX epoch. Clients working with +timestamps in this database usually find it easiest to reason about them if they are always assumed to be UTC. To quote the +pytz documentation, "The preferred way of dealing with times is to always work in UTC, converting to localtime only when +generating output to be read by humans." The driver adheres to this tenant, and assumes UTC is always in the database. The +driver attempts to make this correct on the way in, and assumes no timezone on the way out. + +Write Path +~~~~~~~~~~ +When inserting timestamps, the driver handles serialization for the write path as follows: + +If the input is a ``datetime.datetime``, the serialization is normalized by starting with the ``utctimetuple()`` of the +value. + +- If the ``datetime`` object is timezone-aware, the timestamp is shifted, and represents the UTC timestamp equivalent. +- If the ``datetime`` object is timezone-naive, this results in no shift -- any ``datetime`` with no timezone information is assumed to be UTC + +Note the second point above applies even to "local" times created using ``now()``:: + + >>> d = datetime.now() + + >>> print(d.tzinfo) + None + + +These do not contain timezone information intrinsically, so they will be assumed to be UTC and not shifted. When generating +timestamps in the application, it is clearer to use ``datetime.utcnow()`` to be explicit about it. + +If the input for a timestamp is numeric, it is assumed to be a epoch-relative millisecond timestamp, as specified in the +CQL spec -- no scaling or conversion is done. + +Read Path +~~~~~~~~~ +The driver always assumes persisted timestamps are UTC and makes no attempt to localize them. Returned values are +timezone-naive ``datetime.datetime``. We follow this approach because the datetime API has deficiencies around daylight +saving time, and the defacto package for handling this is a third-party package (we try to minimize external dependencies +and not make decisions for the integrator). + +The decision for how to handle timezones is left to the application. For the most part it is straightforward to apply +localization to the ``datetime``\s returned by queries. One prevalent method is to use pytz for localization:: + + import pytz + user_tz = pytz.timezone('US/Central') + timestamp_naive = row.ts + timestamp_utc = pytz.utc.localize(timestamp_naive) + timestamp_presented = timestamp_utc.astimezone(user_tz) + +This is the most robust approach (likely refactored into a function). If it is deemed too cumbersome to apply for all call +sites in the application, it is possible to patch the driver with custom deserialization for this type. However, doing +this depends depends some on internal APIs and what extensions are present, so we will only mention the possibility, and +not spell it out here. + +date, time (Cassandra DateType) +------------------------------- +Date and time in Cassandra are idealized markers, much like ``datetime.date`` and ``datetime.time`` in the Python standard +library. Unlike these Python implementations, the Cassandra encoding supports much wider ranges. To accommodate these +ranges without overflow, this driver returns these data in custom types: :class:`.util.Date` and :class:`.util.Time`. + +Write Path +~~~~~~~~~~ +For simple (not prepared) statements, the input values for each of these can be either a string literal or an encoded +integer. See `Working with dates `_ +or `Working with time `_ for details +on the encoding or string formats. + +For prepared statements, the driver accepts anything that can be used to construct the :class:`.util.Date` or +:class:`.util.Time` classes. See the linked API docs for details. + +Read Path +~~~~~~~~~ +The driver always returns custom types for ``date`` and ``time``. + +The driver returns :class:`.util.Date` for ``date`` in order to accommodate the wider range of values without overflow. +For applications working within the supported range of [``datetime.MINYEAR``, ``datetime.MAXYEAR``], these are easily +converted to standard ``datetime.date`` insances using :meth:`.Date.date`. + +The driver returns :class:`.util.Time` for ``time`` in order to retain nanosecond precision stored in the database. +For applications not concerned with this level of precision, these are easily converted to standard ``datetime.time`` +insances using :meth:`.Time.time`. diff --git a/master/_sources/execution-profiles.rst.txt b/master/_sources/execution-profiles.rst.txt new file mode 100644 index 0000000000..7be1a85e3f --- /dev/null +++ b/master/_sources/execution-profiles.rst.txt @@ -0,0 +1,156 @@ +Execution Profiles +================== + +Execution profiles aim at making it easier to execute requests in different ways within +a single connected ``Session``. Execution profiles are being introduced to deal with the exploding number of +configuration options, especially as the database platform evolves more complex workloads. + +The legacy configuration remains intact, but legacy and Execution Profile APIs +cannot be used simultaneously on the same client ``Cluster``. Legacy configuration +will be removed in the next major release (4.0). + +An execution profile and its parameters should be unique across ``Cluster`` instances. +For example, an execution profile and its ``LoadBalancingPolicy`` should +not be applied to more than one ``Cluster`` instance. + +This document explains how Execution Profiles relate to existing settings, and shows how to use the new profiles for +request execution. + +Mapping Legacy Parameters to Profiles +------------------------------------- + +Execution profiles can inherit from :class:`.cluster.ExecutionProfile`, and currently provide the following options, +previously input from the noted attributes: + +- load_balancing_policy - :attr:`.Cluster.load_balancing_policy` +- request_timeout - :attr:`.Session.default_timeout`, optional :meth:`.Session.execute` parameter +- retry_policy - :attr:`.Cluster.default_retry_policy`, optional :attr:`.Statement.retry_policy` attribute +- consistency_level - :attr:`.Session.default_consistency_level`, optional :attr:`.Statement.consistency_level` attribute +- serial_consistency_level - :attr:`.Session.default_serial_consistency_level`, optional :attr:`.Statement.serial_consistency_level` attribute +- row_factory - :attr:`.Session.row_factory` attribute + +When using the new API, these parameters can be defined by instances of :class:`.cluster.ExecutionProfile`. + +Using Execution Profiles +------------------------ +Default +~~~~~~~ + +.. code:: python + + from cassandra.cluster import Cluster + cluster = Cluster() + session = cluster.connect() + local_query = 'SELECT rpc_address FROM system.local' + for _ in cluster.metadata.all_hosts(): + print session.execute(local_query)[0] + + +.. parsed-literal:: + + Row(rpc_address='127.0.0.2') + Row(rpc_address='127.0.0.1') + + +The default execution profile is built from Cluster parameters and default Session attributes. This profile matches existing default +parameters. + +Initializing cluster with profiles +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. code:: python + + from cassandra.cluster import ExecutionProfile + from cassandra.policies import WhiteListRoundRobinPolicy + + node1_profile = ExecutionProfile(load_balancing_policy=WhiteListRoundRobinPolicy(['127.0.0.1'])) + node2_profile = ExecutionProfile(load_balancing_policy=WhiteListRoundRobinPolicy(['127.0.0.2'])) + + profiles = {'node1': node1_profile, 'node2': node2_profile} + session = Cluster(execution_profiles=profiles).connect() + for _ in cluster.metadata.all_hosts(): + print session.execute(local_query, execution_profile='node1')[0] + + +.. parsed-literal:: + + Row(rpc_address='127.0.0.1') + Row(rpc_address='127.0.0.1') + + +.. code:: python + + for _ in cluster.metadata.all_hosts(): + print session.execute(local_query, execution_profile='node2')[0] + + +.. parsed-literal:: + + Row(rpc_address='127.0.0.2') + Row(rpc_address='127.0.0.2') + + +.. code:: python + + for _ in cluster.metadata.all_hosts(): + print session.execute(local_query)[0] + + +.. parsed-literal:: + + Row(rpc_address='127.0.0.2') + Row(rpc_address='127.0.0.1') + +Note that, even when custom profiles are injected, the default ``TokenAwarePolicy(DCAwareRoundRobinPolicy())`` is still +present. To override the default, specify a policy with the :data:`~.cluster.EXEC_PROFILE_DEFAULT` key. + +.. code:: python + + from cassandra.cluster import EXEC_PROFILE_DEFAULT + profile = ExecutionProfile(request_timeout=30) + cluster = Cluster(execution_profiles={EXEC_PROFILE_DEFAULT: profile}) + + +Adding named profiles +~~~~~~~~~~~~~~~~~~~~~ + +New profiles can be added constructing from scratch, or deriving from default: + +.. code:: python + + locked_execution = ExecutionProfile(load_balancing_policy=WhiteListRoundRobinPolicy(['127.0.0.1'])) + node1_profile = 'node1_whitelist' + cluster.add_execution_profile(node1_profile, locked_execution) + + for _ in cluster.metadata.all_hosts(): + print session.execute(local_query, execution_profile=node1_profile)[0] + + +.. parsed-literal:: + + Row(rpc_address='127.0.0.1') + Row(rpc_address='127.0.0.1') + +See :meth:`.Cluster.add_execution_profile` for details and optional parameters. + +Passing a profile instance without mapping +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +We also have the ability to pass profile instances to be used for execution, but not added to the mapping: + +.. code:: python + + from cassandra.query import tuple_factory + + tmp = session.execution_profile_clone_update('node1', request_timeout=100, row_factory=tuple_factory) + + print session.execute(local_query, execution_profile=tmp)[0] + print session.execute(local_query, execution_profile='node1')[0] + +.. parsed-literal:: + + ('127.0.0.1',) + Row(rpc_address='127.0.0.1') + +The new profile is a shallow copy, so the ``tmp`` profile shares a load balancing policy with one managed by the cluster. +If reference objects are to be updated in the clone, one would typically set those attributes to a new instance. diff --git a/master/_sources/faq.rst.txt b/master/_sources/faq.rst.txt new file mode 100644 index 0000000000..56cb648a24 --- /dev/null +++ b/master/_sources/faq.rst.txt @@ -0,0 +1,83 @@ +Frequently Asked Questions +========================== + +See also :doc:`cqlengine FAQ ` + +Why do connections or IO operations timeout in my WSGI application? +------------------------------------------------------------------- +Depending on your application process model, it may be forking after driver Session is created. Most IO reactors do not handle this, and problems will manifest as timeouts. + +To avoid this, make sure to create sessions per process, after the fork. Using uWSGI and Flask for example: + +.. code-block:: python + + from flask import Flask + from uwsgidecorators import postfork + from cassandra.cluster import Cluster + + session = None + prepared = None + + @postfork + def connect(): + global session, prepared + session = Cluster().connect() + prepared = session.prepare("SELECT release_version FROM system.local WHERE key=?") + + app = Flask(__name__) + + @app.route('/') + def server_version(): + row = session.execute(prepared, ('local',))[0] + return row.release_version + +uWSGI provides a ``postfork`` hook you can use to create sessions and prepared statements after the child process forks. + +How do I trace a request? +------------------------- +Request tracing can be turned on for any request by setting ``trace=True`` in :meth:`.Session.execute_async`. View the results by waiting on the future, then :meth:`.ResponseFuture.get_query_trace`. +Since tracing is done asynchronously to the request, this method polls until the trace is complete before querying data. + +.. code-block:: python + + >>> future = session.execute_async("SELECT * FROM system.local", trace=True) + >>> result = future.result() + >>> trace = future.get_query_trace() + >>> for e in trace.events: + >>> print e.source_elapsed, e.description + + 0:00:00.000077 Parsing select * from system.local + 0:00:00.000153 Preparing statement + 0:00:00.000309 Computing ranges to query + 0:00:00.000368 Submitting range requests on 1 ranges with a concurrency of 1 (279.77142 rows per range expected) + 0:00:00.000422 Submitted 1 concurrent range requests covering 1 ranges + 0:00:00.000480 Executing seq scan across 1 sstables for (min(-9223372036854775808), min(-9223372036854775808)) + 0:00:00.000669 Read 1 live and 0 tombstone cells + 0:00:00.000755 Scanned 1 rows and matched 1 + +``trace`` is a :class:`QueryTrace` object. + +How do I determine the replicas for a query? +---------------------------------------------- +With prepared statements, the replicas are obtained by ``routing_key``, based on current cluster token metadata: + +.. code-block:: python + + >>> prepared = session.prepare("SELECT * FROM example.t WHERE key=?") + >>> bound = prepared.bind((1,)) + >>> replicas = cluster.metadata.get_replicas(bound.keyspace, bound.routing_key) + >>> for h in replicas: + >>> print h.address + 127.0.0.1 + 127.0.0.2 + +``replicas`` is a list of :class:`Host` objects. + +How does the driver manage request retries? +------------------------------------------- +By default, retries are managed by the :attr:`.Cluster.default_retry_policy` set on the session Cluster. It can also +be specialized per statement by setting :attr:`.Statement.retry_policy`. + +Retries are presently attempted on the same coordinator, but this may change in the future. + +Please see :class:`.policies.RetryPolicy` for further details. diff --git a/master/_sources/getting-started.rst.txt b/master/_sources/getting-started.rst.txt new file mode 100644 index 0000000000..59a2acbd04 --- /dev/null +++ b/master/_sources/getting-started.rst.txt @@ -0,0 +1,479 @@ +Getting Started +=============== + +First, make sure you have the driver properly :doc:`installed `. + +Connecting to a Cluster +----------------------- +Before we can start executing any queries against a Cassandra cluster we need to setup +an instance of :class:`~.Cluster`. As the name suggests, you will typically have one +instance of :class:`~.Cluster` for each Cassandra cluster you want to interact +with. + +First, make sure you have the Cassandra driver properly :doc:`installed `. + +Connecting to Cassandra ++++++++++++++++++++++++ +The simplest way to create a :class:`~.Cluster` is like this: + +.. code-block:: python + + from cassandra.cluster import Cluster + + cluster = Cluster() + +This will attempt to connection to a Cassandra instance on your +local machine (127.0.0.1). You can also specify a list of IP +addresses for nodes in your cluster: + +.. code-block:: python + + from cassandra.cluster import Cluster + + cluster = Cluster(['192.168.0.1', '192.168.0.2']) + +The set of IP addresses we pass to the :class:`~.Cluster` is simply +an initial set of contact points. After the driver connects to one +of these nodes it will *automatically discover* the rest of the +nodes in the cluster and connect to them, so you don't need to list +every node in your cluster. + +If you need to use a non-standard port, use SSL, or customize the driver's +behavior in some other way, this is the place to do it: + +.. code-block:: python + + from cassandra.cluster import Cluster + cluster = Cluster(['192.168.0.1', '192.168.0.2'], port=..., ssl_context=...) + +Instantiating a :class:`~.Cluster` does not actually connect us to any nodes. +To establish connections and begin executing queries we need a +:class:`~.Session`, which is created by calling :meth:`.Cluster.connect()`: + +.. code-block:: python + + cluster = Cluster() + session = cluster.connect() + +Session Keyspace +---------------- +The :meth:`~.Cluster.connect()` method takes an optional ``keyspace`` argument +which sets the default keyspace for all queries made through that :class:`~.Session`: + +.. code-block:: python + + cluster = Cluster() + session = cluster.connect('mykeyspace') + +You can always change a Session's keyspace using :meth:`~.Session.set_keyspace` or +by executing a ``USE `` query: + +.. code-block:: python + + session.set_keyspace('users') + # or you can do this instead + session.execute('USE users') + +Execution Profiles +------------------ +Profiles are passed in by ``execution_profiles`` dict. + +In this case we can construct the base ``ExecutionProfile`` passing all attributes: + +.. code-block:: python + + from cassandra.cluster import Cluster, ExecutionProfile, EXEC_PROFILE_DEFAULT + from cassandra.policies import WhiteListRoundRobinPolicy, DowngradingConsistencyRetryPolicy + from cassandra.query import tuple_factory + + profile = ExecutionProfile( + load_balancing_policy=WhiteListRoundRobinPolicy(['127.0.0.1']), + retry_policy=DowngradingConsistencyRetryPolicy(), + consistency_level=ConsistencyLevel.LOCAL_QUORUM, + serial_consistency_level=ConsistencyLevel.LOCAL_SERIAL, + request_timeout=15, + row_factory=tuple_factory + ) + cluster = Cluster(execution_profiles={EXEC_PROFILE_DEFAULT: profile}) + session = cluster.connect() + + print(session.execute("SELECT release_version FROM system.local").one()) + +Users are free to setup additional profiles to be used by name: + +.. code-block:: python + + profile_long = ExecutionProfile(request_timeout=30) + cluster = Cluster(execution_profiles={'long': profile_long}) + session = cluster.connect() + session.execute(statement, execution_profile='long') + +Also, parameters passed to ``Session.execute`` or attached to ``Statement``\s are still honored as before. + +Executing Queries +----------------- +Now that we have a :class:`.Session` we can begin to execute queries. The simplest +way to execute a query is to use :meth:`~.Session.execute()`: + +.. code-block:: python + + rows = session.execute('SELECT name, age, email FROM users') + for user_row in rows: + print user_row.name, user_row.age, user_row.email + +This will transparently pick a Cassandra node to execute the query against +and handle any retries that are necessary if the operation fails. + +By default, each row in the result set will be a +`namedtuple `_. +Each row will have a matching attribute for each column defined in the schema, +such as ``name``, ``age``, and so on. You can also treat them as normal tuples +by unpacking them or accessing fields by position. The following three +examples are equivalent: + +.. code-block:: python + + rows = session.execute('SELECT name, age, email FROM users') + for row in rows: + print row.name, row.age, row.email + +.. code-block:: python + + rows = session.execute('SELECT name, age, email FROM users') + for (name, age, email) in rows: + print name, age, email + +.. code-block:: python + + rows = session.execute('SELECT name, age, email FROM users') + for row in rows: + print row[0], row[1], row[2] + +If you prefer another result format, such as a ``dict`` per row, you +can change the :attr:`~.Session.row_factory` attribute. + +As mentioned in our `Drivers Best Practices Guide `_, +it is highly recommended to use `Prepared statements <#prepared-statement>`_ for your +frequently run queries. + +.. _prepared-statement: + +Prepared Statements +------------------- +Prepared statements are queries that are parsed by Cassandra and then saved +for later use. When the driver uses a prepared statement, it only needs to +send the values of parameters to bind. This lowers network traffic +and CPU utilization within Cassandra because Cassandra does not have to +re-parse the query each time. + +To prepare a query, use :meth:`.Session.prepare()`: + +.. code-block:: python + + user_lookup_stmt = session.prepare("SELECT * FROM users WHERE user_id=?") + + users = [] + for user_id in user_ids_to_query: + user = session.execute(user_lookup_stmt, [user_id]) + users.append(user) + +:meth:`~.Session.prepare()` returns a :class:`~.PreparedStatement` instance +which can be used in place of :class:`~.SimpleStatement` instances or literal +string queries. It is automatically prepared against all nodes, and the driver +handles re-preparing against new nodes and restarted nodes when necessary. + +Note that the placeholders for prepared statements are ``?`` characters. This +is different than for simple, non-prepared statements (although future versions +of the driver may use the same placeholders for both). + +Passing Parameters to CQL Queries +--------------------------------- +Althought it is not recommended, you can also pass parameters to non-prepared +statements. The driver supports two forms of parameter place-holders: positional +and named. + +Positional parameters are used with a ``%s`` placeholder. For example, +when you execute: + +.. code-block:: python + + session.execute( + """ + INSERT INTO users (name, credits, user_id) + VALUES (%s, %s, %s) + """, + ("John O'Reilly", 42, uuid.uuid1()) + ) + +It is translated to the following CQL query:: + + INSERT INTO users (name, credits, user_id) + VALUES ('John O''Reilly', 42, 2644bada-852c-11e3-89fb-e0b9a54a6d93) + +Note that you should use ``%s`` for all types of arguments, not just strings. +For example, this would be **wrong**: + +.. code-block:: python + + session.execute("INSERT INTO USERS (name, age) VALUES (%s, %d)", ("bob", 42)) # wrong + +Instead, use ``%s`` for the age placeholder. + +If you need to use a literal ``%`` character, use ``%%``. + +**Note**: you must always use a sequence for the second argument, even if you are +only passing in a single variable: + +.. code-block:: python + + session.execute("INSERT INTO foo (bar) VALUES (%s)", "blah") # wrong + session.execute("INSERT INTO foo (bar) VALUES (%s)", ("blah")) # wrong + session.execute("INSERT INTO foo (bar) VALUES (%s)", ("blah", )) # right + session.execute("INSERT INTO foo (bar) VALUES (%s)", ["blah"]) # right + + +Note that the second line is incorrect because in Python, single-element tuples +require a comma. + +Named place-holders use the ``%(name)s`` form: + +.. code-block:: python + + session.execute( + """ + INSERT INTO users (name, credits, user_id, username) + VALUES (%(name)s, %(credits)s, %(user_id)s, %(name)s) + """, + {'name': "John O'Reilly", 'credits': 42, 'user_id': uuid.uuid1()} + ) + +Note that you can repeat placeholders with the same name, such as ``%(name)s`` +in the above example. + +Only data values should be supplied this way. Other items, such as keyspaces, +table names, and column names should be set ahead of time (typically using +normal string formatting). + +.. _type-conversions: + +Type Conversions +---------------- +For non-prepared statements, Python types are cast to CQL literals in the +following way: + +.. table:: + + +--------------------+-------------------------+ + | Python Type | CQL Literal Type | + +====================+=========================+ + | ``None`` | ``NULL`` | + +--------------------+-------------------------+ + | ``bool`` | ``boolean`` | + +--------------------+-------------------------+ + | ``float`` | | ``float`` | + | | | ``double`` | + +--------------------+-------------------------+ + | | ``int`` | | ``int`` | + | | ``long`` | | ``bigint`` | + | | | ``varint`` | + | | | ``smallint`` | + | | | ``tinyint`` | + | | | ``counter`` | + +--------------------+-------------------------+ + | ``decimal.Decimal``| ``decimal`` | + +--------------------+-------------------------+ + | | ``str`` | | ``ascii`` | + | | ``unicode`` | | ``varchar`` | + | | | ``text`` | + +--------------------+-------------------------+ + | | ``buffer`` | ``blob`` | + | | ``bytearray`` | | + +--------------------+-------------------------+ + | ``date`` | ``date`` | + +--------------------+-------------------------+ + | ``datetime`` | ``timestamp`` | + +--------------------+-------------------------+ + | ``time`` | ``time`` | + +--------------------+-------------------------+ + | | ``list`` | ``list`` | + | | ``tuple`` | | + | | generator | | + +--------------------+-------------------------+ + | | ``set`` | ``set`` | + | | ``frozenset`` | | + +--------------------+-------------------------+ + | | ``dict`` | ``map`` | + | | ``OrderedDict`` | | + +--------------------+-------------------------+ + | ``uuid.UUID`` | | ``timeuuid`` | + | | | ``uuid`` | + +--------------------+-------------------------+ + + +Asynchronous Queries +-------------------- +The driver supports asynchronous query execution through +:meth:`~.Session.execute_async()`. Instead of waiting for the query to +complete and returning rows directly, this method almost immediately +returns a :class:`~.ResponseFuture` object. There are two ways of +getting the final result from this object. + +The first is by calling :meth:`~.ResponseFuture.result()` on it. If +the query has not yet completed, this will block until it has and +then return the result or raise an Exception if an error occurred. +For example: + +.. code-block:: python + + from cassandra import ReadTimeout + + query = "SELECT * FROM users WHERE user_id=%s" + future = session.execute_async(query, [user_id]) + + # ... do some other work + + try: + rows = future.result() + user = rows[0] + print user.name, user.age + except ReadTimeout: + log.exception("Query timed out:") + +This works well for executing many queries concurrently: + +.. code-block:: python + + # build a list of futures + futures = [] + query = "SELECT * FROM users WHERE user_id=%s" + for user_id in ids_to_fetch: + futures.append(session.execute_async(query, [user_id]) + + # wait for them to complete and use the results + for future in futures: + rows = future.result() + print rows[0].name + +Alternatively, instead of calling :meth:`~.ResponseFuture.result()`, +you can attach callback and errback functions through the +:meth:`~.ResponseFuture.add_callback()`, +:meth:`~.ResponseFuture.add_errback()`, and +:meth:`~.ResponseFuture.add_callbacks()`, methods. If you have used +Twisted Python before, this is designed to be a lightweight version of +that: + +.. code-block:: python + + def handle_success(rows): + user = rows[0] + try: + process_user(user.name, user.age, user.id) + except Exception: + log.error("Failed to process user %s", user.id) + # don't re-raise errors in the callback + + def handle_error(exception): + log.error("Failed to fetch user info: %s", exception) + + + future = session.execute_async(query) + future.add_callbacks(handle_success, handle_error) + +There are a few important things to remember when working with callbacks: + * **Exceptions that are raised inside the callback functions will be logged and then ignored.** + * Your callback will be run on the event loop thread, so any long-running + operations will prevent other requests from being handled + + +Setting a Consistency Level +--------------------------- +The consistency level used for a query determines how many of the +replicas of the data you are interacting with need to respond for +the query to be considered a success. + +By default, :attr:`.ConsistencyLevel.LOCAL_ONE` will be used for all queries. +You can specify a different default by setting the :attr:`.ExecutionProfile.consistency_level` +for the execution profile with key :data:`~.cluster.EXEC_PROFILE_DEFAULT`. +To specify a different consistency level per request, wrap queries +in a :class:`~.SimpleStatement`: + +.. code-block:: python + + from cassandra import ConsistencyLevel + from cassandra.query import SimpleStatement + + query = SimpleStatement( + "INSERT INTO users (name, age) VALUES (%s, %s)", + consistency_level=ConsistencyLevel.QUORUM) + session.execute(query, ('John', 42)) + +Setting a Consistency Level with Prepared Statements +---------------------------------------------------- +To specify a consistency level for prepared statements, you have two options. + +The first is to set a default consistency level for every execution of the +prepared statement: + +.. code-block:: python + + from cassandra import ConsistencyLevel + + cluster = Cluster() + session = cluster.connect("mykeyspace") + user_lookup_stmt = session.prepare("SELECT * FROM users WHERE user_id=?") + user_lookup_stmt.consistency_level = ConsistencyLevel.QUORUM + + # these will both use QUORUM + user1 = session.execute(user_lookup_stmt, [user_id1])[0] + user2 = session.execute(user_lookup_stmt, [user_id2])[0] + +The second option is to create a :class:`~.BoundStatement` from the +:class:`~.PreparedStatement` and binding parameters and set a consistency +level on that: + +.. code-block:: python + + # override the QUORUM default + user3_lookup = user_lookup_stmt.bind([user_id3]) + user3_lookup.consistency_level = ConsistencyLevel.ALL + user3 = session.execute(user3_lookup) + +Speculative Execution +--------------------- + +Speculative execution is a way to minimize latency by preemptively executing several +instances of the same query against different nodes. For more details about this +technique, see `Speculative Execution with DataStax Drivers `_. + +To enable speculative execution: + +* Configure a :class:`~.policies.SpeculativeExecutionPolicy` with the ExecutionProfile +* Mark your query as idempotent, which mean it can be applied multiple + times without changing the result of the initial application. + See `Query Idempotence `_ for more details. + + +Example: + +.. code-block:: python + + from cassandra.cluster import Cluster, ExecutionProfile, EXEC_PROFILE_DEFAULT + from cassandra.policies import ConstantSpeculativeExecutionPolicy + from cassandra.query import SimpleStatement + + # Configure the speculative execution policy + ep = ExecutionProfile( + speculative_execution_policy=ConstantSpeculativeExecutionPolicy(delay=.5, max_attempts=10) + ) + cluster = Cluster(..., execution_profiles={EXEC_PROFILE_DEFAULT: ep}) + session = cluster.connect() + + # Mark the query idempotent + query = SimpleStatement( + "UPDATE my_table SET list_col = [1] WHERE pk = 1", + is_idempotent=True + ) + + # Execute. A new query will be sent to the server every 0.5 second + # until we receive a response, for a max number attempts of 10. + session.execute(query) diff --git a/master/_sources/index.rst.txt b/master/_sources/index.rst.txt new file mode 100644 index 0000000000..c21d293b6f --- /dev/null +++ b/master/_sources/index.rst.txt @@ -0,0 +1,107 @@ +Python Driver for Scylla and Apache Cassandra® +============================================== +A Python client driver for `Scylla `_. +This driver works exclusively with the Cassandra Query Language v3 (CQL3) +and Cassandra's native protocol. + +The driver supports Python 2.7, 3.5, 3.6, 3.7 and 3.8. + +This driver is open source under the +`Apache v2 License `_. +The source code for this driver can be found on `GitHub `_. + +Scylla Driver is a fork from `DataStax Python Driver `_, including some non-breaking changes for Scylla optimization, with more updates planned. + +Contents +-------- +:doc:`installation` + How to install the driver. + +:doc:`getting-started` + A guide through the first steps of connecting to Scylla and executing queries + +:doc:`scylla-specific` + A list of feature available only on ``scylla-driver`` + +:doc:`execution-profiles` + An introduction to a more flexible way of configuring request execution + +:doc:`lwt` + Working with results of conditional requests + +:doc:`object-mapper` + Introduction to the integrated object mapper, cqlengine + +:doc:`performance` + Tips for getting good performance. + +:doc:`query-paging` + Notes on paging large query results + +:doc:`security` + An overview of the security features of the driver + +:doc:`upgrading` + A guide to upgrading versions of the driver + +:doc:`user-defined-types` + Working with Scylla's user-defined types (UDT) + +:doc:`dates-and-times` + Some discussion on the driver's approach to working with timestamp, date, time types + +:doc:`scylla-cloud` + Connect to ScyllaDB Cloud + +:doc:`scylla-cloud-serverless` + Connect to ScyllaDB Cloud Serverless + +:doc:`CHANGELOG` + Log of changes to the driver, organized by version. + +:doc:`faq` + A collection of Frequently Asked Questions + +:doc:`api/index` + The API documentation. + +.. toctree:: + :hidden: + + api/index + installation + getting-started + scylla-specific + upgrading + execution-profiles + performance + query-paging + lwt + security + user-defined-types + object-mapper + dates-and-times + scylla-cloud + scylla-cloud-serverless + faq + +Getting Help +------------ +Visit the :doc:`FAQ section ` in this documentation. + +Please send questions to the Scylla `user list `_. + + +Reporting Issues +---------------- + +Please report any bugs and make any feature requests on the `Github project issues `_ + + +Copyright +--------- + +© 2013-2017 DataStax + +© 2016, The Apache Software Foundation. +Apache®, Apache Cassandra®, Cassandra®, the Apache feather logo and the Apache Cassandra® Eye logo are either registered trademarks or trademarks of the Apache Software Foundation in the United States and/or other countries. No endorsement by The Apache Software Foundation is implied by the use of these marks. diff --git a/master/_sources/installation.rst.txt b/master/_sources/installation.rst.txt new file mode 100644 index 0000000000..4996a02c1b --- /dev/null +++ b/master/_sources/installation.rst.txt @@ -0,0 +1,234 @@ +Installation +============ + +Supported Platforms +------------------- +Python 2.7, 3.5, 3.6, 3.7 and 3.8 are supported. Both CPython (the standard Python +implementation) and `PyPy `_ are supported and tested. + +Linux, OSX, and Windows are supported. + +Installation through pip +------------------------ +`pip `_ is the suggested tool for installing +packages. It will handle installing all Python dependencies for the driver at +the same time as the driver itself. To install the driver*:: + + pip install scylla-driver + +You can use ``pip install --pre scylla-driver`` if you need to install a beta version. + +***Note**: if intending to use optional extensions, install the `dependencies <#optional-non-python-dependencies>`_ first. The driver may need to be reinstalled if dependencies are added after the initial installation. + +Verifying your Installation +--------------------------- +To check if the installation was successful, you can run:: + + python -c 'import cassandra; print cassandra.__version__' + +It should print something like "3.22.0". + +.. _installation-datastax-graph: + +(*Optional*) Graph +--------------------------- +The driver provides an optional fluent graph API that depends on Apache TinkerPop (gremlinpython). It is +not installed by default. To be able to build Gremlin traversals, you need to install +the `graph` requirements:: + + pip install scylla-driver[graph] + +(*Optional*) Compression Support +-------------------------------- +Compression can optionally be used for communication between the driver and +Cassandra. There are currently two supported compression algorithms: +snappy (in Cassandra 1.2+) and LZ4 (only in Cassandra 2.0+). If either is +available for the driver and Cassandra also supports it, it will +be used automatically. + +For lz4 support:: + + pip install lz4 + +For snappy support:: + + pip install python-snappy + +(If using a Debian Linux derivative such as Ubuntu, it may be easier to +just run ``apt-get install python-snappy``.) + +(*Optional*) Metrics Support +---------------------------- +The driver has built-in support for capturing :attr:`.Cluster.metrics` about +the queries you run. However, the ``scales`` library is required to +support this:: + + pip install scales + + +Speeding Up Installation +^^^^^^^^^^^^^^^^^^^^^^^^ + +By default, installing the driver through ``pip`` uses a pre-compiled, platform-specific wheel when available. +If using a source distribution rather than a wheel, Cython is used to compile certain parts of the driver. +This makes those hot paths faster at runtime, but the Cython compilation +process can take a long time -- as long as 10 minutes in some environments. + +In environments where performance is less important, it may be worth it to +:ref:`disable Cython as documented below `. +You can also use ``CASS_DRIVER_BUILD_CONCURRENCY`` to increase the number of +threads used to build the driver and any C extensions: + +.. code-block:: bash + + $ # installing from source + $ CASS_DRIVER_BUILD_CONCURRENCY=8 python setup.py install + $ # installing from pip + $ CASS_DRIVER_BUILD_CONCURRENCY=8 pip install scylla-driver + +OSX Installation Error +^^^^^^^^^^^^^^^^^^^^^^ +If you're installing on OSX and have XCode 5.1 installed, you may see an error like this:: + + clang: error: unknown argument: '-mno-fused-madd' [-Wunused-command-line-argument-hard-error-in-future] + +To fix this, re-run the installation with an extra compilation flag: + +.. code-block:: bash + + ARCHFLAGS=-Wno-error=unused-command-line-argument-hard-error-in-future pip install scylla-driver + +.. _windows_build: + +Windows Installation Notes +-------------------------- +Installing the driver with extensions in Windows sometimes presents some challenges. A few notes about common +hang-ups: + +Setup requires a compiler. When using Python 2, this is as simple as installing `this package `_ +(this link is also emitted during install if setuptools is unable to find the resources it needs). Depending on your +system settings, this package may install as a user-specific application. Make sure to install for everyone, or at least +as the user that will be building the Python environment. + +It is also possible to run the build with your compiler of choice. Just make sure to have your environment setup with +the proper paths. Make sure the compiler target architecture matches the bitness of your Python runtime. +Perhaps the easiest way to do this is to run the build/install from a Visual Studio Command Prompt (a +shortcut installed with Visual Studio that sources the appropriate environment and presents a shell). + +Manual Installation +------------------- +You can always install the driver directly from a source checkout or tarball. +When installing manually, ensure the python dependencies are already +installed. You can find the list of dependencies in +`requirements.txt `_. + +Once the dependencies are installed, simply run:: + + python setup.py install + + +(*Optional*) Non-python Dependencies +------------------------------------ +The driver has several **optional** features that have non-Python dependencies. + +C Extensions +^^^^^^^^^^^^ +By default, a number of extensions are compiled, providing faster hashing +for token-aware routing with the ``Murmur3Partitioner``, +`libev `_ event loop integration, +and Cython optimized extensions. + +When installing manually through setup.py, you can disable both with +the ``--no-extensions`` option, or selectively disable them with +with ``--no-murmur3``, ``--no-libev``, or ``--no-cython``. + +To compile the extensions, ensure that GCC and the Python headers are available. + +On Ubuntu and Debian, this can be accomplished by running:: + + $ sudo apt-get install gcc python-dev + +On RedHat and RedHat-based systems like CentOS and Fedora:: + + $ sudo yum install gcc python-devel + +On OS X, homebrew installations of Python should provide the necessary headers. + +See :ref:`windows_build` for notes on configuring the build environment on Windows. + +.. _cython-extensions: + +Cython-based Extensions +~~~~~~~~~~~~~~~~~~~~~~~ +By default, this package uses `Cython `_ to optimize core modules and build custom extensions. +This is not a hard requirement, but is engaged by default to build extensions offering better performance than the +pure Python implementation. + +This is a costly build phase, especially in clean environments where the Cython compiler must be built +This build phase can be avoided using the build switch, or an environment variable:: + + python setup.py install --no-cython + +Alternatively, an environment variable can be used to switch this option regardless of +context:: + + CASS_DRIVER_NO_CYTHON=1 + - or, to disable all extensions: + CASS_DRIVER_NO_EXTENSIONS=1 + +This method is required when using pip, which provides no other way of injecting user options in a single command:: + + CASS_DRIVER_NO_CYTHON=1 pip install scylla-driver + CASS_DRIVER_NO_CYTHON=1 sudo -E pip install ~/python-driver + +The environment variable is the preferred option because it spans all invocations of setup.py, and will +prevent Cython from being materialized as a setup requirement. + +If your sudo configuration does not allow SETENV, you must push the option flag down via pip. However, pip +applies these options to all dependencies (which break on the custom flag). Therefore, you must first install +dependencies, then use install-option:: + + sudo pip install six futures + sudo pip install --install-option="--no-cython" + + +libev support +^^^^^^^^^^^^^ +The driver currently uses Python's ``asyncore`` module for its default +event loop. For better performance, ``libev`` is also supported through +a C extension. + +If you're on Linux, you should be able to install libev +through a package manager. For example, on Debian/Ubuntu:: + + $ sudo apt-get install libev4 libev-dev + +On RHEL/CentOS/Fedora:: + + $ sudo yum install libev libev-devel + +If you're on Mac OS X, you should be able to install libev +through `Homebrew `_. For example, on Mac OS X:: + + $ brew install libev + +The libev extension is not built for Windows (the build process is complex, and the Windows implementation uses +select anyway). + +If successful, you should be able to build and install the extension +(just using ``setup.py build`` or ``setup.py install``) and then use +the libev event loop by doing the following: + +.. code-block:: python + + >>> from cassandra.io.libevreactor import LibevConnection + >>> from cassandra.cluster import Cluster + + >>> cluster = Cluster() + >>> cluster.connection_class = LibevConnection + >>> session = cluster.connect() + +(*Optional*) Configuring SSL +----------------------------- +Andrew Mussey has published a thorough guide on +`Using SSL with the DataStax Python driver `_. diff --git a/master/_sources/lwt.rst.txt b/master/_sources/lwt.rst.txt new file mode 100644 index 0000000000..2cc272f350 --- /dev/null +++ b/master/_sources/lwt.rst.txt @@ -0,0 +1,91 @@ +Lightweight Transactions (Compare-and-set) +========================================== + +Lightweight Transactions (LWTs) are mostly pass-through CQL for the driver. However, +the server returns some specialized results indicating the outcome and optional state +preceding the transaction. + +For pertinent execution parameters, see :attr:`.Statement.serial_consistency_level`. + +This section discusses working with specialized result sets returned by the server for LWTs, +and how to work with them using the driver. + + +Specialized Results +------------------- +The result returned from a LWT request is always a single row result. It will always have +prepended a special column named ``[applied]``. How this value appears in your results depends +on the row factory in use. See below for examples. + +The value of this ``[applied]`` column is boolean value indicating whether or not the transaction was applied. +If ``True``, it is the only column in the result. If ``False``, the additional columns depend on the LWT operation being +executed: + +- When using a ``UPDATE ... IF "col" = ...`` clause, the result will contain the ``[applied]`` column, plus the existing columns + and values for any columns in the ``IF`` clause (and thus the value that caused the transaction to fail). + +- When using ``INSERT ... IF NOT EXISTS``, the result will contain the ``[applied]`` column, plus all columns and values + of the existing row that rejected the transaction. + +- ``UPDATE .. IF EXISTS`` never has additional columns, regardless of ``[applied]`` status. + +How the ``[applied]`` column manifests depends on the row factory in use. Considering the following (initially empty) table:: + + CREATE TABLE test.t ( + k int PRIMARY KEY, + v int, + x int + ) + +... the following sections show the expected result for a number of example statements, using the three base row factories. + +named_tuple_factory (default) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +The name ``[applied]`` is not a valid Python identifier, so the square brackets are actually removed +from the attribute for the resulting ``namedtuple``. The row always has a boolean column ``applied`` in position 0:: + + >>> session.execute("INSERT INTO t (k,v) VALUES (0,0) IF NOT EXISTS") + Row(applied=True) + + >>> session.execute("INSERT INTO t (k,v) VALUES (0,0) IF NOT EXISTS") + Row(applied=False, k=0, v=0, x=None) + + >>> session.execute("UPDATE t SET v = 1, x = 2 WHERE k = 0 IF v =0") + Row(applied=True) + + >>> session.execute("UPDATE t SET v = 1, x = 2 WHERE k = 0 IF v =0 AND x = 1") + Row(applied=False, v=1, x=2) + +tuple_factory +~~~~~~~~~~~~~ +This return type does not refer to names, but the boolean value ``applied`` is always present in position 0:: + + >>> session.execute("INSERT INTO t (k,v) VALUES (0,0) IF NOT EXISTS") + (True,) + + >>> session.execute("INSERT INTO t (k,v) VALUES (0,0) IF NOT EXISTS") + (False, 0, 0, None) + + >>> session.execute("UPDATE t SET v = 1, x = 2 WHERE k = 0 IF v =0") + (True,) + + >>> session.execute("UPDATE t SET v = 1, x = 2 WHERE k = 0 IF v =0 AND x = 1") + (False, 1, 2) + +dict_factory +~~~~~~~~~~~~ +The retuned ``dict`` contains the ``[applied]`` key:: + + >>> session.execute("INSERT INTO t (k,v) VALUES (0,0) IF NOT EXISTS") + {u'[applied]': True} + + >>> session.execute("INSERT INTO t (k,v) VALUES (0,0) IF NOT EXISTS") + {u'x': 2, u'[applied]': False, u'v': 1} + + >>> session.execute("UPDATE t SET v = 1, x = 2 WHERE k = 0 IF v =0") + {u'x': None, u'[applied]': False, u'k': 0, u'v': 0} + + >>> session.execute("UPDATE t SET v = 1, x = 2 WHERE k = 0 IF v =0 AND x = 1") + {u'[applied]': True} + + diff --git a/master/_sources/object-mapper.rst.txt b/master/_sources/object-mapper.rst.txt new file mode 100644 index 0000000000..421be246ac --- /dev/null +++ b/master/_sources/object-mapper.rst.txt @@ -0,0 +1,105 @@ +Object Mapper +============= + +cqlengine is the Cassandra CQL 3 Object Mapper packaged with this driver + +:ref:`Jump to Getting Started ` + +Contents +-------- +:doc:`cqlengine/upgrade-guide` + For migrating projects from legacy cqlengine, to the integrated product + +:doc:`cqlengine/models` + Examples defining models, and mapping them to tables + +:doc:`cqlengine/queryset` + Overview of query sets and filtering + +:doc:`cqlengine/batches` + Working with batch mutations + +:doc:`cqlengine/connections` + Working with multiple sessions + +:ref:`API Documentation ` + Index of API documentation + +:doc:`cqlengine/third-party` + High-level examples in Celery and uWSGI + +:doc:`cqlengine/faq` + +.. toctree:: + :hidden: + + cqlengine/upgrade-guide + cqlengine/models + cqlengine/queryset + cqlengine/batches + cqlengine/connections + cqlengine/third-party + cqlengine/faq + +.. _getting-started: + +Getting Started +--------------- + +.. code-block:: python + + import uuid + from cassandra.cqlengine import columns + from cassandra.cqlengine import connection + from datetime import datetime + from cassandra.cqlengine.management import sync_table + from cassandra.cqlengine.models import Model + + #first, define a model + class ExampleModel(Model): + example_id = columns.UUID(primary_key=True, default=uuid.uuid4) + example_type = columns.Integer(index=True) + created_at = columns.DateTime() + description = columns.Text(required=False) + + #next, setup the connection to your cassandra server(s)... + # see http://datastax.github.io/python-driver/api/cassandra/cluster.html for options + # the list of hosts will be passed to create a Cluster() instance + connection.setup(['127.0.0.1'], "cqlengine", protocol_version=3) + + #...and create your CQL table + >>> sync_table(ExampleModel) + + #now we can create some rows: + >>> em1 = ExampleModel.create(example_type=0, description="example1", created_at=datetime.now()) + >>> em2 = ExampleModel.create(example_type=0, description="example2", created_at=datetime.now()) + >>> em3 = ExampleModel.create(example_type=0, description="example3", created_at=datetime.now()) + >>> em4 = ExampleModel.create(example_type=0, description="example4", created_at=datetime.now()) + >>> em5 = ExampleModel.create(example_type=1, description="example5", created_at=datetime.now()) + >>> em6 = ExampleModel.create(example_type=1, description="example6", created_at=datetime.now()) + >>> em7 = ExampleModel.create(example_type=1, description="example7", created_at=datetime.now()) + >>> em8 = ExampleModel.create(example_type=1, description="example8", created_at=datetime.now()) + + #and now we can run some queries against our table + >>> ExampleModel.objects.count() + 8 + >>> q = ExampleModel.objects(example_type=1) + >>> q.count() + 4 + >>> for instance in q: + >>> print instance.description + example5 + example6 + example7 + example8 + + #here we are applying additional filtering to an existing query + #query objects are immutable, so calling filter returns a new + #query object + >>> q2 = q.filter(example_id=em5.example_id) + + >>> q2.count() + 1 + >>> for instance in q2: + >>> print instance.description + example5 diff --git a/master/_sources/performance.rst.txt b/master/_sources/performance.rst.txt new file mode 100644 index 0000000000..f7a3f49e0f --- /dev/null +++ b/master/_sources/performance.rst.txt @@ -0,0 +1,45 @@ +Performance Notes +================= +The Python driver for Cassandra offers several methods for executing queries. +You can synchronously block for queries to complete using +:meth:`.Session.execute()`, you can obtain asynchronous request futures through +:meth:`.Session.execute_async()`, and you can attach a callback to the future +with :meth:`.ResponseFuture.add_callback()`. + +Examples of multiple request patterns can be found in the benchmark scripts included in the driver project. + +The choice of execution pattern will depend on the application context. For applications dealing with multiple +requests in a given context, the recommended pattern is to use concurrent asynchronous +requests with callbacks. For many use cases, you don't need to implement this pattern yourself. +:meth:`cassandra.concurrent.execute_concurrent` and :meth:`cassandra.concurrent.execute_concurrent_with_args` +provide this pattern with a synchronous API and tunable concurrency. + +Due to the GIL and limited concurrency, the driver can become CPU-bound pretty quickly. The sections below +discuss further runtime and design considerations for mitigating this limitation. + +PyPy +---- +`PyPy `_ is an alternative Python runtime which uses a JIT compiler to +reduce CPU consumption. This leads to a huge improvement in the driver performance, +more than doubling throughput for many workloads. + +Cython Extensions +----------------- +`Cython `_ is an optimizing compiler and language that can be used to compile the core files and +optional extensions for the driver. Cython is not a strict dependency, but the extensions will be built by default. + +See :doc:`installation` for details on controlling this build. + +multiprocessing +--------------- +All of the patterns discussed above may be used over multiple processes using the +`multiprocessing `_ +module. Multiple processes will scale better than multiple threads, so if high throughput is your goal, +consider this option. + +Be sure to **never share any** :class:`~.Cluster`, :class:`~.Session`, +**or** :class:`~.ResponseFuture` **objects across multiple processes**. These +objects should all be created after forking the process, not before. + +For further discussion and simple examples using the driver with ``multiprocessing``, +see `this blog post `_. diff --git a/master/_sources/query-paging.rst.txt b/master/_sources/query-paging.rst.txt new file mode 100644 index 0000000000..23ee2c1129 --- /dev/null +++ b/master/_sources/query-paging.rst.txt @@ -0,0 +1,95 @@ +.. _query-paging: + +Paging Large Queries +==================== +Cassandra 2.0+ offers support for automatic query paging. Starting with +version 2.0 of the driver, if :attr:`~.Cluster.protocol_version` is greater than +:const:`2` (it is by default), queries returning large result sets will be +automatically paged. + +Controlling the Page Size +------------------------- +By default, :attr:`.Session.default_fetch_size` controls how many rows will +be fetched per page. This can be overridden per-query by setting +:attr:`~.fetch_size` on a :class:`~.Statement`. By default, each page +will contain at most 5000 rows. + +Handling Paged Results +---------------------- +Whenever the number of result rows for are query exceed the page size, an +instance of :class:`~.PagedResult` will be returned instead of a normal +list. This class implements the iterator interface, so you can treat +it like a normal iterator over rows:: + + from cassandra.query import SimpleStatement + query = "SELECT * FROM users" # users contains 100 rows + statement = SimpleStatement(query, fetch_size=10) + for user_row in session.execute(statement): + process_user(user_row) + +Whenever there are no more rows in the current page, the next page will +be fetched transparently. However, note that it *is* possible for +an :class:`Exception` to be raised while fetching the next page, just +like you might see on a normal call to ``session.execute()``. + +If you use :meth:`.Session.execute_async()` along with, +:meth:`.ResponseFuture.result()`, the first page will be fetched before +:meth:`~.ResponseFuture.result()` returns, but latter pages will be +transparently fetched synchronously while iterating the result. + +Handling Paged Results with Callbacks +------------------------------------- +If callbacks are attached to a query that returns a paged result, +the callback will be called once per page with a normal list of rows. + +Use :attr:`.ResponseFuture.has_more_pages` and +:meth:`.ResponseFuture.start_fetching_next_page()` to continue fetching +pages. For example:: + + class PagedResultHandler(object): + + def __init__(self, future): + self.error = None + self.finished_event = Event() + self.future = future + self.future.add_callbacks( + callback=self.handle_page, + errback=self.handle_err) + + def handle_page(self, rows): + for row in rows: + process_row(row) + + if self.future.has_more_pages: + self.future.start_fetching_next_page() + else: + self.finished_event.set() + + def handle_error(self, exc): + self.error = exc + self.finished_event.set() + + future = session.execute_async("SELECT * FROM users") + handler = PagedResultHandler(future) + handler.finished_event.wait() + if handler.error: + raise handler.error + +Resume Paged Results +-------------------- + +You can resume the pagination when executing a new query by using the :attr:`.ResultSet.paging_state`. This can be useful if you want to provide some stateless pagination capabilities to your application (ie. via http). For example:: + + from cassandra.query import SimpleStatement + query = "SELECT * FROM users" + statement = SimpleStatement(query, fetch_size=10) + results = session.execute(statement) + + # save the paging_state somewhere and return current results + web_session['paging_state'] = results.paging_state + + + # resume the pagination sometime later... + statement = SimpleStatement(query, fetch_size=10) + ps = web_session['paging_state'] + results = session.execute(statement, paging_state=ps) diff --git a/master/_sources/scylla-cloud-serverless.rst.txt b/master/_sources/scylla-cloud-serverless.rst.txt new file mode 100644 index 0000000000..4e0bafd1b8 --- /dev/null +++ b/master/_sources/scylla-cloud-serverless.rst.txt @@ -0,0 +1,49 @@ +ScyllaDB Cloud Serverless +------------------------- + +With ScyllaDB Cloud, you can deploy `serverless databases `_. +The Python driver allows you to connect to a serverless database by utilizing the connection bundle you can download via the **Connect>Python** tab in the Cloud application. +The connection bundle is a YAML file with connection and credential information for your cluster. + +Connecting to a ScyllaDB Cloud serverless database is very similar to a standard connection to a ScyllaDB database. + +Here’s a short program that connects to a ScyllaDB Cloud serverless database and prints metadata about the cluster: + +.. code-block:: python + + from cassandra.cluster import Cluster, ExecutionProfile, EXEC_PROFILE_DEFAULT + from cassandra.policies import DCAwareRoundRobinPolicy, TokenAwarePolicy + + PATH_TO_BUNDLE_YAML = '/file/downloaded/from/cloud/connect-bundle.yaml' + + + def get_cluster(): + profile = ExecutionProfile( + load_balancing_policy=TokenAwarePolicy( + DCAwareRoundRobinPolicy(local_dc='us-east-1') + ) + ) + + return Cluster( + execution_profiles={EXEC_PROFILE_DEFAULT: profile}, + scylla_cloud=PATH_TO_BUNDLE_YAML, + ) + + + print('Connecting to cluster') + cluster = get_cluster() + session = cluster.connect() + + print('Connected to cluster', cluster.metadata.cluster_name) + + print('Getting metadata') + for host in cluster.metadata.all_hosts(): + print('Datacenter: {}; Host: {}; Rack: {}'.format( + host.datacenter, host.address, host.rack) + ) + + cluster.shutdown() + +By providing the ``scylla_cloud`` parameter to the :class:`~.Cluster` constructor, +the driver can set up the connection based on the endpoint and credential information +stored in your downloaded ScyllaDB Cloud Serverless connection bundle. \ No newline at end of file diff --git a/master/_sources/scylla-cloud.rst.txt b/master/_sources/scylla-cloud.rst.txt new file mode 100644 index 0000000000..b5eb6df798 --- /dev/null +++ b/master/_sources/scylla-cloud.rst.txt @@ -0,0 +1,5 @@ +ScyllaDB Cloud +-------------- + +To connect to a `ScyllaDB Cloud `_ cluster, go to the Cluster Connect page, Python example. +For best performance, make sure to use the Scylla Driver. diff --git a/master/_sources/scylla-specific.rst.txt b/master/_sources/scylla-specific.rst.txt new file mode 100644 index 0000000000..101ddb534b --- /dev/null +++ b/master/_sources/scylla-specific.rst.txt @@ -0,0 +1,106 @@ +Scylla Specific Features +======================== + +Shard Awareness +--------------- + +**scylla-driver** is shard aware and contains extensions that work with the TokenAwarePolicy supported by Scylla 2.3 and onwards. Using this policy, the driver can select a connection to a particular shard based on the shard's token. +As a result, latency is significantly reduced because there is no need to pass data between the shards. + +Details on the scylla cql protocol extensions +https://github.com/scylladb/scylla/blob/master/docs/dev/protocol-extensions.md#intranode-sharding + +For using it you only need to enable ``TokenAwarePolicy`` on the ``Cluster`` + +See the configuration of ``native_shard_aware_transport_port`` and ``native_shard_aware_transport_port_ssl`` on scylla.yaml: +https://github.com/scylladb/scylla/blob/master/docs/dev/protocols.md#cql-client-protocol + +.. code:: python + + from cassandra.cluster import Cluster + from cassandra.policies import TokenAwarePolicy, RoundRobinPolicy + + cluster = Cluster(load_balancing_policy=TokenAwarePolicy(RoundRobinPolicy())) + + +New Cluster Helpers +------------------- + +* ``shard_aware_options`` + + Setting it to ``dict(disable=True)`` would disable the shard aware functionally, for cases favoring once connection per host (example, lots of processes connecting from one client host, generating a big load of connections + + Other option is to configure scylla by setting ``enable_shard_aware_drivers: false`` on scylla.yaml. + +.. code:: python + + from cassandra.cluster import Cluster + + cluster = Cluster(shard_aware_options=dict(disable=True)) + session = cluster.connect() + + assert not cluster.is_shard_aware(), "Shard aware should be disabled" + + # or just disable the shard aware port logic + cluster = Cluster(shard_aware_options=dict(disable_shardaware_port=True)) + session = cluster.connect() + +* ``cluster.is_shard_aware()`` + + New method available on ``Cluster`` allowing to check whether the remote cluster supports shard awareness (bool) + +.. code:: python + + from cassandra.cluster import Cluster + + cluster = Cluster() + session = cluster.connect() + + if cluster.is_shard_aware(): + print("connected to a scylla cluster") + +* ``cluster.shard_aware_stats()`` + + New method available on ``Cluster`` allowing to check the status of shard aware connections to all available hosts (dict) + +.. code:: python + + from cassandra.cluster import Cluster + + cluster = Cluster() + session = cluster.connect() + + stats = cluster.shard_aware_stats() + if all([v["shards_count"] == v["connected"] for v in stats.values()]): + print("successfully connected to all shards of all scylla nodes") + + +New Table Attributes +-------------------- + +* ``in_memory`` flag + + New flag available on ``TableMetadata.options`` to indicate that it is an `In Memory `_ table + +.. note:: in memory tables is a feature existing only in Scylla Enterprise + +.. code:: python + + from cassandra.cluster import Cluster + + cluster = Cluster() + session = cluster.connect() + session.execute(""" + CREATE KEYSPACE IF NOT EXISTS keyspace1 + WITH replication = {'class': 'SimpleStrategy', 'replication_factor': '1'}; + """) + + session.execute(""" + CREATE TABLE IF NOT EXISTS keyspace1.standard1 ( + key blob PRIMARY KEY, + "C0" blob + ) WITH in_memory=true AND compaction={'class': 'InMemoryCompactionStrategy'} + """) + + cluster.refresh_table_metadata("keyspace1", "standard1") + assert cluster.metadata.keyspaces["keyspace1"].tables["standard1"].options["in_memory"] == True diff --git a/master/_sources/security.rst.txt b/master/_sources/security.rst.txt new file mode 100644 index 0000000000..c30189562f --- /dev/null +++ b/master/_sources/security.rst.txt @@ -0,0 +1,421 @@ +.. _security: + +Security +======== +The two main security components you will use with the +Python driver are Authentication and SSL. + +Authentication +-------------- +Versions 2.0 and higher of the driver support a SASL-based +authentication mechanism when :attr:`~.Cluster.protocol_version` +is set to 2 or higher. To use this authentication, set +:attr:`~.Cluster.auth_provider` to an instance of a subclass +of :class:`~cassandra.auth.AuthProvider`. When working +with Cassandra's ``PasswordAuthenticator``, you can use +the :class:`~cassandra.auth.PlainTextAuthProvider` class. + +For example, suppose Cassandra is setup with its default +'cassandra' user with a password of 'cassandra': + +.. code-block:: python + + from cassandra.cluster import Cluster + from cassandra.auth import PlainTextAuthProvider + + auth_provider = PlainTextAuthProvider(username='cassandra', password='cassandra') + cluster = Cluster(auth_provider=auth_provider, protocol_version=2) + + + +Custom Authenticators +^^^^^^^^^^^^^^^^^^^^^ +If you're using something other than Cassandra's ``PasswordAuthenticator``, +:class:`~.SaslAuthProvider` is provided for generic SASL authentication mechanisms, +utilizing the ``pure-sasl`` package. +If these do not suit your needs, you may need to create your own subclasses of +:class:`~.AuthProvider` and :class:`~.Authenticator`. You can use the Sasl classes +as example implementations. + +Protocol v1 Authentication +^^^^^^^^^^^^^^^^^^^^^^^^^^ +When working with Cassandra 1.2 (or a higher version with +:attr:`~.Cluster.protocol_version` set to ``1``), you will not pass in +an :class:`~.AuthProvider` instance. Instead, you should pass in a +function that takes one argument, the IP address of a host, and returns +a dict of credentials with a ``username`` and ``password`` key: + +.. code-block:: python + + from cassandra.cluster import Cluster + + def get_credentials(host_address): + return {'username': 'joe', 'password': '1234'} + + cluster = Cluster(auth_provider=get_credentials, protocol_version=1) + +SSL +--- +SSL should be used when client encryption is enabled in Cassandra. + +To give you as much control as possible over your SSL configuration, our SSL +API takes a user-created `SSLContext` instance from the Python standard library. +These docs will include some examples for how to achieve common configurations, +but the `ssl.SSLContext `_ documentation +gives a more complete description of what is possible. + +To enable SSL with version 3.17.0 and higher, you will need to set :attr:`.Cluster.ssl_context` to a +``ssl.SSLContext`` instance to enable SSL. Optionally, you can also set :attr:`.Cluster.ssl_options` +to a dict of options. These will be passed as kwargs to ``ssl.SSLContext.wrap_socket()`` +when new sockets are created. + +If you create your SSLContext using `ssl.create_default_context `_, +be aware that SSLContext.check_hostname is set to True by default, so the hostname validation will be done +by Python and not the driver. For this reason, we need to set the server_hostname at best effort, which is the +resolved ip address. If this validation needs to be done against the FQDN, consider enabling it using the ssl_options +as described in the following examples or implement your own :class:`~.connection.EndPoint` and +:class:`~.connection.EndPointFactory`. + + +The following examples assume you have generated your Cassandra certificate and +keystore files with these intructions: + +* `Setup SSL Cert `_ + +It might be also useful to learn about the different levels of identity verification to understand the examples: + +* `Using SSL in DSE drivers `_ + +SSL with Twisted or Eventlet +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Twisted and Eventlet both use an alternative SSL implementation called pyOpenSSL, so if your `Cluster`'s connection class is +:class:`~cassandra.io.twistedreactor.TwistedConnection` or :class:`~cassandra.io.eventletreactor.EventletConnection`, you must pass a +`pyOpenSSL context `_ instead. +An example is provided in these docs, and more details can be found in the +`documentation `_. +pyOpenSSL is not installed by the driver and must be installed separately. + +SSL Configuration Examples +^^^^^^^^^^^^^^^^^^^^^^^^^^ +Here, we'll describe the server and driver configuration necessary to set up SSL to meet various goals, such as the client verifying the server and the server verifying the client. We'll also include Python code demonstrating how to use servers and drivers configured in these ways. + +.. _ssl-no-identify-verification: + +No identity verification +++++++++++++++++++++++++ + +No identity verification at all. Note that this is not recommended for for production deployments. + +The Cassandra configuration:: + + client_encryption_options: + enabled: true + keystore: /path/to/127.0.0.1.keystore + keystore_password: myStorePass + require_client_auth: false + +The driver configuration: + +.. code-block:: python + + from cassandra.cluster import Cluster, Session + from ssl import SSLContext, PROTOCOL_TLS + + ssl_context = SSLContext(PROTOCOL_TLS) + + cluster = Cluster(['127.0.0.1'], ssl_context=ssl_context) + session = cluster.connect() + +.. _ssl-client-verifies-server: + +Client verifies server +++++++++++++++++++++++ + +Ensure the python driver verifies the identity of the server. + +The Cassandra configuration:: + + client_encryption_options: + enabled: true + keystore: /path/to/127.0.0.1.keystore + keystore_password: myStorePass + require_client_auth: false + +For the driver configuration, it's very important to set `ssl_context.verify_mode` +to `CERT_REQUIRED`. Otherwise, the loaded verify certificate will have no effect: + +.. code-block:: python + + from cassandra.cluster import Cluster, Session + from ssl import SSLContext, PROTOCOL_TLS, CERT_REQUIRED + + ssl_context = SSLContext(PROTOCOL_TLS) + ssl_context.load_verify_locations('/path/to/rootca.crt') + ssl_context.verify_mode = CERT_REQUIRED + + cluster = Cluster(['127.0.0.1'], ssl_context=ssl_context) + session = cluster.connect() + +Additionally, you can also force the driver to verify the `hostname` of the server by passing additional options to `ssl_context.wrap_socket` via the `ssl_options` kwarg: + +.. code-block:: python + + from cassandra.cluster import Cluster, Session + from ssl import SSLContext, PROTOCOL_TLS, CERT_REQUIRED + + ssl_context = SSLContext(PROTOCOL_TLS) + ssl_context.load_verify_locations('/path/to/rootca.crt') + ssl_context.verify_mode = CERT_REQUIRED + ssl_context.check_hostname = True + ssl_options = {'server_hostname': '127.0.0.1'} + + cluster = Cluster(['127.0.0.1'], ssl_context=ssl_context, ssl_options=ssl_options) + session = cluster.connect() + +.. _ssl-server-verifies-client: + +Server verifies client +++++++++++++++++++++++ + +If Cassandra is configured to verify clients (``require_client_auth``), you need to generate +SSL key and certificate files. + +The cassandra configuration:: + + client_encryption_options: + enabled: true + keystore: /path/to/127.0.0.1.keystore + keystore_password: myStorePass + require_client_auth: true + truststore: /path/to/dse-truststore.jks + truststore_password: myStorePass + +The Python ``ssl`` APIs require the certificate in PEM format. First, create a certificate +conf file: + +.. code-block:: bash + + cat > gen_client_cert.conf <`__ +for more details about ``SSLContext`` configuration. + +**Server verifies client and client verifies server using Twisted and pyOpenSSL** + +.. code-block:: python + + from OpenSSL import SSL, crypto + from cassandra.cluster import Cluster + from cassandra.io.twistedreactor import TwistedConnection + + ssl_context = SSL.Context(SSL.TLSv1_2_METHOD) + ssl_context.set_verify(SSL.VERIFY_PEER, callback=lambda _1, _2, _3, _4, ok: ok) + ssl_context.use_certificate_file('/path/to/client.crt_signed') + ssl_context.use_privatekey_file('/path/to/client.key') + ssl_context.load_verify_locations('/path/to/rootca.crt') + + cluster = Cluster( + contact_points=['127.0.0.1'], + connection_class=TwistedConnection, + ssl_context=ssl_context, + ssl_options={'check_hostname': True} + ) + session = cluster.connect() + + +Connecting using Eventlet would look similar except instead of importing and using ``TwistedConnection``, you would +import and use ``EventletConnection``, including the appropriate monkey-patching. + +Versions 3.16.0 and lower +^^^^^^^^^^^^^^^^^^^^^^^^^ + +To enable SSL you will need to set :attr:`.Cluster.ssl_options` to a +dict of options. These will be passed as kwargs to ``ssl.wrap_socket()`` +when new sockets are created. Note that this use of ssl_options will be +deprecated in the next major release. + +By default, a ``ca_certs`` value should be supplied (the value should be +a string pointing to the location of the CA certs file), and you probably +want to specify ``ssl_version`` as ``ssl.PROTOCOL_TLS`` to match +Cassandra's default protocol. + +For example: + +.. code-block:: python + + from cassandra.cluster import Cluster + from ssl import PROTOCOL_TLS, CERT_REQUIRED + + ssl_opts = { + 'ca_certs': '/path/to/my/ca.certs', + 'ssl_version': PROTOCOL_TLS, + 'cert_reqs': CERT_REQUIRED # Certificates are required and validated + } + cluster = Cluster(ssl_options=ssl_opts) + +This is only an example to show how to pass the ssl parameters. Consider reading +the `python ssl documentation `__ for +your configuration. For further reading, Andrew Mussey has published a thorough guide on +`Using SSL with the DataStax Python driver `_. + +SSL with Twisted +++++++++++++++++ + +In case the twisted event loop is used pyOpenSSL must be installed or an exception will be risen. Also +to set the ``ssl_version`` and ``cert_reqs`` in ``ssl_opts`` the appropriate constants from pyOpenSSL are expected. + +DSE Authentication +------------------ +When authenticating against DSE, the Cassandra driver provides two auth providers that work both with legacy kerberos and Cassandra authenticators, +as well as the new DSE Unified Authentication. This allows client to configure this auth provider independently, +and in advance of any server upgrade. These auth providers are configured in the same way as any previous implementation:: + + from cassandra.auth import DSEGSSAPIAuthProvider + auth_provider = DSEGSSAPIAuthProvider(service='dse', qops=["auth"]) + cluster = Cluster(auth_provider=auth_provider) + session = cluster.connect() + +Implementations are :attr:`.DSEPlainTextAuthProvider`, :class:`.DSEGSSAPIAuthProvider` and :class:`.SaslAuthProvider`. + +DSE Unified Authentication +^^^^^^^^^^^^^^^^^^^^^^^^^^ + +With DSE (>=5.1), unified Authentication allows you to: + +* Proxy Login: Authenticate using a fixed set of authentication credentials but allow authorization of resources based another user id. +* Proxy Execute: Authenticate using a fixed set of authentication credentials but execute requests based on another user id. + +Proxy Login ++++++++++++ + +Proxy login allows you to authenticate with a user but act as another one. You need to ensure the authenticated user has the permission to use the authorization of resources of the other user. ie. this example will allow the `server` user to authenticate as usual but use the authorization of `user1`: + +.. code-block:: text + + GRANT PROXY.LOGIN on role user1 to server + +then you can do the proxy authentication.... + +.. code-block:: python + + from cassandra.cluster import Cluster + from cassandra.auth import SaslAuthProvider + + sasl_kwargs = { + "service": 'dse', + "mechanism":"PLAIN", + "username": 'server', + 'password': 'server', + 'authorization_id': 'user1' + } + + auth_provider = SaslAuthProvider(**sasl_kwargs) + c = Cluster(auth_provider=auth_provider) + s = c.connect() + s.execute(...) # all requests will be executed as 'user1' + +If you are using kerberos, you can use directly :class:`.DSEGSSAPIAuthProvider` and pass the authorization_id, like this: + +.. code-block:: python + + from cassandra.cluster import Cluster + from cassandra.auth import DSEGSSAPIAuthProvider + + # Ensure the kerberos ticket of the server user is set with the kinit utility. + auth_provider = DSEGSSAPIAuthProvider(service='dse', qops=["auth"], principal="server@DATASTAX.COM", + authorization_id='user1@DATASTAX.COM') + c = Cluster(auth_provider=auth_provider) + s = c.connect() + s.execute(...) # all requests will be executed as 'user1' + + +Proxy Execute ++++++++++++++ + +Proxy execute allows you to execute requests as another user than the authenticated one. You need to ensure the authenticated user has the permission to use the authorization of resources of the specified user. ie. this example will allow the `server` user to execute requests as `user1`: + +.. code-block:: text + + GRANT PROXY.EXECUTE on role user1 to server + +then you can do a proxy execute... + +.. code-block:: python + + from cassandra.cluster import Cluster + from cassandra.auth import DSEPlainTextAuthProvider, + + auth_provider = DSEPlainTextAuthProvider('server', 'server') + + c = Cluster(auth_provider=auth_provider) + s = c.connect() + s.execute('select * from k.t;', execute_as='user1') # the request will be executed as 'user1' + +Please see the `official documentation `_ for more details on the feature and configuration process. diff --git a/master/_sources/upgrading.rst.txt b/master/_sources/upgrading.rst.txt new file mode 100644 index 0000000000..6161b8c881 --- /dev/null +++ b/master/_sources/upgrading.rst.txt @@ -0,0 +1,380 @@ +Upgrading +========= + +.. toctree:: + :maxdepth: 1 + +Installation +^^^^^^^^^^^^ + +Only the `scylla-driver` package should be installed. `dse-driver` and `dse-graph` +are not required anymore:: + + pip install scylla-driver + +If you need the Graph *Fluent* API (features provided by dse-graph):: + + pip install scylla-driver[graph] + +See :doc:`installation` for more details. + +Import from the cassandra module +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +There is no `dse` module, so you should import from the `cassandra` module. You +need to change only the first module of your import statements, not the submodules. + +.. code-block:: python + + from dse.cluster import Cluster, EXEC_PROFILE_GRAPH_DEFAULT + from dse.auth import PlainTextAuthProvider + from dse.policies import WhiteListRoundRobinPolicy + + # becomes + + from cassandra.cluster import Cluster, EXEC_PROFILE_GRAPH_DEFAULT + from cassandra.auth import PlainTextAuthProvider + from cassandra.policies import WhiteListRoundRobinPolicy + +Also note that the cassandra.hosts module doesn't exist in scylla-driver. This +module is named cassandra.pool. + +dse-graph +^^^^^^^^^ + +dse-graph features are now built into scylla-driver. The only change you need +to do is your import statements: + +.. code-block:: python + + from dse_graph import .. + from dse_graph.query import .. + + # becomes + + from cassandra.datastax.graph.fluent import .. + from cassandra.datastax.graph.fluent.query import .. + +See :mod:`~.datastax.graph.fluent`. + +Session.execute and Session.execute_async API +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Although it is not common to use this API with positional arguments, it is +important to be aware that the `host` and `execute_as` parameters have had +their positional order swapped. This is only because `execute_as` was added +in dse-driver before `host`. + +See :meth:`.Session.execute`. + +Deprecations +^^^^^^^^^^^^ + +These changes are optional, but recommended: + +* Importing from `cassandra.graph` is deprecated. Consider importing from `cassandra.datastax.graph`. +* Use :class:`~.policies.DefaultLoadBalancingPolicy` instead of DSELoadBalancingPolicy. + +Upgrading to 3.0 +---------------- +Version 3.0 of the DataStax Python driver for Apache Cassandra +adds support for Cassandra 3.0 while maintaining support for +previously supported versions. In addition to substantial internal rework, +there are several updates to the API that integrators will need +to consider: + +Default consistency is now ``LOCAL_ONE`` +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Previous value was ``ONE``. The new value is introduced to mesh with the default +DC-aware load balancing policy and to match other drivers. + +Execution API Updates +^^^^^^^^^^^^^^^^^^^^^ +Result return normalization +~~~~~~~~~~~~~~~~~~~~~~~~~~~ +`PYTHON-368 `_ + +Previously results would be returned as a ``list`` of rows for result rows +up to ``fetch_size``, and ``PagedResult`` afterward. This could break +application code that assumed one type and got another. + +Now, all results are returned as an iterable :class:`~.ResultSet`. + +The preferred way to consume results of unknown size is to iterate through +them, letting automatic paging occur as they are consumed. + +.. code-block:: python + + results = session.execute("SELECT * FROM system.local") + for row in results: + process(row) + +If the expected size of the results is known, it is still possible to +materialize a list using the iterator: + +.. code-block:: python + + results = session.execute("SELECT * FROM system.local") + row_list = list(results) + +For backward compatibility, :class:`~.ResultSet` supports indexing. When +accessed at an index, a `~.ResultSet` object will materialize all its pages: + +.. code-block:: python + + results = session.execute("SELECT * FROM system.local") + first_result = results[0] # materializes results, fetching all pages + +This can send requests and load (possibly large) results into memory, so +`~.ResultSet` will log a warning on implicit materialization. + +Trace information is not attached to executed Statements +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +`PYTHON-318 `_ + +Previously trace data was attached to Statements if tracing was enabled. This +could lead to confusion if the same statement was used for multiple executions. + +Now, trace data is associated with the ``ResponseFuture`` and ``ResultSet`` +returned for each query: + +:meth:`.ResponseFuture.get_query_trace()` + +:meth:`.ResponseFuture.get_all_query_traces()` + +:meth:`.ResultSet.get_query_trace()` + +:meth:`.ResultSet.get_all_query_traces()` + +Binding named parameters now ignores extra names +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +`PYTHON-178 `_ + +Previously, :meth:`.BoundStatement.bind()` would raise if a mapping +was passed with extra names not found in the prepared statement. + +Behavior in 3.0+ is to ignore extra names. + +blist removed as soft dependency +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +`PYTHON-385 `_ + +Previously the driver had a soft dependency on ``blist sortedset``, using +that where available and using an internal fallback where possible. + +Now, the driver never chooses the ``blist`` variant, instead returning the +internal :class:`.util.SortedSet` for all ``set`` results. The class implements +all standard set operations, so no integration code should need to change unless +it explicitly checks for ``sortedset`` type. + +Metadata API Updates +^^^^^^^^^^^^^^^^^^^^ +`PYTHON-276 `_, `PYTHON-408 `_, `PYTHON-400 `_, `PYTHON-422 `_ + +Cassandra 3.0 brought a substantial overhaul to the internal schema metadata representation. +This version of the driver supports that metadata in addition to the legacy version. Doing so +also brought some changes to the metadata model. + +The present API is documented: :any:`cassandra.metadata`. Changes highlighted below: + +* All types are now exposed as CQL types instead of types derived from the internal server implementation +* Some metadata attributes have changed names to match current nomenclature (for example, :attr:`.Index.kind` in place of ``Index.type``). +* Some metadata attributes removed + + * ``TableMetadata.keyspace`` reference replaced with :attr:`.TableMetadata.keyspace_name` + * ``ColumnMetadata.index`` is removed table- and keyspace-level mappings are still maintained + +Several deprecated features are removed +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +`PYTHON-292 `_ + +* ``ResponseFuture.result`` timeout parameter is removed, use ``Session.execute`` timeout instead (`031ebb0 `_) +* ``Cluster.refresh_schema`` removed, use ``Cluster.refresh_*_metadata`` instead (`419fcdf `_) +* ``Cluster.submit_schema_refresh`` removed (`574266d `_) +* ``cqltypes`` time/date functions removed, use ``util`` entry points instead (`bb984ee `_) +* ``decoder`` module removed (`e16a073 `_) +* ``TableMetadata.keyspace`` attribute replaced with ``keyspace_name`` (`cc94073 `_) +* ``cqlengine.columns.TimeUUID.from_datetime`` removed, use ``util`` variant instead (`96489cc `_) +* ``cqlengine.columns.Float(double_precision)`` parameter removed, use ``columns.Double`` instead (`a2d3a98 `_) +* ``cqlengine`` keyspace management functions are removed in favor of the strategy-specific entry points (`4bd5909 `_) +* ``cqlengine.Model.__polymorphic_*__`` attributes removed, use ``__discriminator*`` attributes instead (`9d98c8e `_) +* ``cqlengine.statements`` will no longer warn about list list prepend behavior (`79efe97 `_) + + +Upgrading to 2.1 from 2.0 +------------------------- +Version 2.1 of the DataStax Python driver for Apache Cassandra +adds support for Cassandra 2.1 and version 3 of the native protocol. + +Cassandra 1.2, 2.0, and 2.1 are all supported. However, 1.2 only +supports protocol version 1, and 2.0 only supports versions 1 and +2, so some features may not be available. + +Using the v3 Native Protocol +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +By default, the driver will attempt to use version 2 of the +native protocol. To use version 3, you must explicitly +set the :attr:`~.Cluster.protocol_version`: + +.. code-block:: python + + from cassandra.cluster import Cluster + + cluster = Cluster(protocol_version=3) + +Note that protocol version 3 is only supported by Cassandra 2.1+. + +In future releases, the driver may default to using protocol version +3. + +Working with User-Defined Types +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Cassandra 2.1 introduced the ability to define new types:: + + USE KEYSPACE mykeyspace; + + CREATE TYPE address (street text, city text, zip int); + +The driver generally expects you to use instances of a specific +class to represent column values of this type. You can let the +driver know what class to use with :meth:`.Cluster.register_user_type`: + +.. code-block:: python + + cluster = Cluster() + + class Address(object): + + def __init__(self, street, city, zipcode): + self.street = street + self.city = text + self.zipcode = zipcode + + cluster.register_user_type('mykeyspace', 'address', Address) + +When inserting data for ``address`` columns, you should pass in +instances of ``Address``. When querying data, ``address`` column +values will be instances of ``Address``. + +If no class is registered for a user-defined type, query results +will use a ``namedtuple`` class and data may only be inserted +though prepared statements. + +See :ref:`udts` for more details. + +Customizing Encoders for Non-prepared Statements +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Starting with version 2.1 of the driver, it is possible to customize +how Python types are converted to CQL literals when working with +non-prepared statements. This is done on a per-:class:`~.Session` +basis through :attr:`.Session.encoder`: + +.. code-block:: python + + cluster = Cluster() + session = cluster.connect() + session.encoder.mapping[tuple] = session.encoder.cql_encode_tuple + +See :ref:`type-conversions` for the table of default CQL literal conversions. + +Using Client-Side Protocol-Level Timestamps +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +With version 3 of the native protocol, timestamps may be supplied by the +client at the protocol level. (Normally, if they are not specified within +the CQL query itself, a timestamp is generated server-side.) + +When :attr:`~.Cluster.protocol_version` is set to 3 or higher, the driver +will automatically use client-side timestamps with microsecond precision +unless :attr:`.Session.use_client_timestamp` is changed to :const:`False`. +If a timestamp is specified within the CQL query, it will override the +timestamp generated by the driver. + +Upgrading to 2.0 from 1.x +------------------------- +Version 2.0 of the DataStax Python driver for Apache Cassandra +includes some notable improvements over version 1.x. This version +of the driver supports Cassandra 1.2, 2.0, and 2.1. However, not +all features may be used with Cassandra 1.2, and some new features +in 2.1 are not yet supported. + +Using the v2 Native Protocol +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +By default, the driver will attempt to use version 2 of Cassandra's +native protocol. You can explicitly set the protocol version to +2, though: + +.. code-block:: python + + from cassandra.cluster import Cluster + + cluster = Cluster(protocol_version=2) + +When working with Cassandra 1.2, you will need to +explicitly set the :attr:`~.Cluster.protocol_version` to 1: + +.. code-block:: python + + from cassandra.cluster import Cluster + + cluster = Cluster(protocol_version=1) + +Automatic Query Paging +^^^^^^^^^^^^^^^^^^^^^^ +Version 2 of the native protocol adds support for automatic query +paging, which can make dealing with large result sets much simpler. + +See :ref:`query-paging` for full details. + +Protocol-Level Batch Statements +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +With version 1 of the native protocol, batching of statements required +using a `BATCH cql query `_. +With version 2 of the native protocol, you can now batch statements at +the protocol level. This allows you to use many different prepared +statements within a single batch. + +See :class:`~.query.BatchStatement` for details and usage examples. + +SASL-based Authentication +^^^^^^^^^^^^^^^^^^^^^^^^^ +Also new in version 2 of the native protocol is SASL-based authentication. +See the section on :ref:`security` for details and examples. + +Lightweight Transactions +^^^^^^^^^^^^^^^^^^^^^^^^ +`Lightweight transactions `_ are another new feature. To use lightweight transactions, add ``IF`` clauses +to your CQL queries and set the :attr:`~.Statement.serial_consistency_level` +on your statements. + +Calling Cluster.shutdown() +^^^^^^^^^^^^^^^^^^^^^^^^^^ +In order to fix some issues around garbage collection and unclean interpreter +shutdowns, version 2.0 of the driver requires you to call :meth:`.Cluster.shutdown()` +on your :class:`~.Cluster` objects when you are through with them. +This helps to guarantee a clean shutdown. + +Deprecations +^^^^^^^^^^^^ +The following functions have moved from ``cassandra.decoder`` to ``cassandra.query``. +The original functions have been left in place with a :exc:`DeprecationWarning` for +now: + +* :attr:`cassandra.decoder.tuple_factory` has moved to + :attr:`cassandra.query.tuple_factory` +* :attr:`cassandra.decoder.named_tuple_factory` has moved to + :attr:`cassandra.query.named_tuple_factory` +* :attr:`cassandra.decoder.dict_factory` has moved to + :attr:`cassandra.query.dict_factory` +* :attr:`cassandra.decoder.ordered_dict_factory` has moved to + :attr:`cassandra.query.ordered_dict_factory` + +Dependency Changes +^^^^^^^^^^^^^^^^^^ +The following dependencies have officially been made optional: + +* ``scales`` +* ``blist`` + +And one new dependency has been added (to enable Python 3 support): + +* ``six`` diff --git a/master/_sources/user-defined-types.rst.txt b/master/_sources/user-defined-types.rst.txt new file mode 100644 index 0000000000..32c03e37e8 --- /dev/null +++ b/master/_sources/user-defined-types.rst.txt @@ -0,0 +1,118 @@ +.. _udts: + +User Defined Types +================== +Cassandra 2.1 introduced user-defined types (UDTs). You can create a +new type through ``CREATE TYPE`` statements in CQL:: + + CREATE TYPE address (street text, zip int); + +Version 2.1 of the Python driver adds support for user-defined types. + +Registering a UDT +----------------- +You can tell the Python driver to return columns of a specific UDT as +instances of a class or a dict by registering them with your :class:`~.Cluster` +instance through :meth:`.Cluster.register_user_type`: + + +Map a Class to a UDT +++++++++++++++++++++ + +.. code-block:: python + + cluster = Cluster(protocol_version=3) + session = cluster.connect() + session.set_keyspace('mykeyspace') + session.execute("CREATE TYPE address (street text, zipcode int)") + session.execute("CREATE TABLE users (id int PRIMARY KEY, location frozen
)") + + # create a class to map to the "address" UDT + class Address(object): + + def __init__(self, street, zipcode): + self.street = street + self.zipcode = zipcode + + cluster.register_user_type('mykeyspace', 'address', Address) + + # insert a row using an instance of Address + session.execute("INSERT INTO users (id, location) VALUES (%s, %s)", + (0, Address("123 Main St.", 78723))) + + # results will include Address instances + results = session.execute("SELECT * FROM users") + row = results[0] + print(row.id, row.location.street, row.location.zipcode) + +Map a dict to a UDT ++++++++++++++++++++ + +.. code-block:: python + + cluster = Cluster(protocol_version=3) + session = cluster.connect() + session.set_keyspace('mykeyspace') + session.execute("CREATE TYPE address (street text, zipcode int)") + session.execute("CREATE TABLE users (id int PRIMARY KEY, location frozen
)") + + cluster.register_user_type('mykeyspace', 'address', dict) + + # insert a row using a prepared statement and a tuple + insert_statement = session.prepare("INSERT INTO mykeyspace.users (id, location) VALUES (?, ?)") + session.execute(insert_statement, [0, ("123 Main St.", 78723)]) + + # results will include dict instances + results = session.execute("SELECT * FROM users") + row = results[0] + print(row.id, row.location['street'], row.location['zipcode']) + +Using UDTs Without Registering Them +----------------------------------- +Although it is recommended to register your types with +:meth:`.Cluster.register_user_type`, the driver gives you some options +for working with unregistered UDTS. + +When you use prepared statements, the driver knows what data types to +expect for each placeholder. This allows you to pass any object you +want for a UDT, as long as it has attributes that match the field names +for the UDT: + +.. code-block:: python + + cluster = Cluster(protocol_version=3) + session = cluster.connect() + session.set_keyspace('mykeyspace') + session.execute("CREATE TYPE address (street text, zipcode int)") + session.execute("CREATE TABLE users (id int PRIMARY KEY, location frozen
)") + + class Foo(object): + + def __init__(self, street, zipcode, otherstuff): + self.street = street + self.zipcode = zipcode + self.otherstuff = otherstuff + + insert_statement = session.prepare("INSERT INTO users (id, location) VALUES (?, ?)") + + # since we're using a prepared statement, we don't *have* to register + # a class to map to the UDT to insert data. The object just needs to have + # "street" and "zipcode" attributes (which Foo does): + session.execute(insert_statement, [0, Foo("123 Main St.", 78723, "some other stuff")]) + + # when we query data, UDT columns that don't have a class registered + # will be returned as namedtuples: + results = session.execute("SELECT * FROM users") + first_row = results[0] + address = first_row.location + print(address) # prints "Address(street='123 Main St.', zipcode=78723)" + street = address.street + zipcode = address.street + +As shown in the code example, inserting data for UDT columns without registering +a class works fine for prepared statements. However, **you must register a +class to insert UDT columns with unprepared statements**.\* You can still query +UDT columns without registered classes using unprepared statements, they will +simply return ``namedtuple`` instances (just like prepared statements do). + +\* this applies to *parameterized* unprepared statements, in which the driver will be formatting parameters -- not statements with interpolated UDT literals. diff --git a/master/_static/basic.css b/master/_static/basic.css new file mode 100644 index 0000000000..603f6a8798 --- /dev/null +++ b/master/_static/basic.css @@ -0,0 +1,905 @@ +/* + * basic.css + * ~~~~~~~~~ + * + * Sphinx stylesheet -- basic theme. + * + * :copyright: Copyright 2007-2021 by the Sphinx team, see AUTHORS. + * :license: BSD, see LICENSE for details. + * + */ + +/* -- main layout ----------------------------------------------------------- */ + +div.clearer { + clear: both; +} + +div.section::after { + display: block; + content: ''; + clear: left; +} + +/* -- relbar ---------------------------------------------------------------- */ + +div.related { + width: 100%; + font-size: 90%; +} + +div.related h3 { + display: none; +} + +div.related ul { + margin: 0; + padding: 0 0 0 10px; + list-style: none; +} + +div.related li { + display: inline; +} + +div.related li.right { + float: right; + margin-right: 5px; +} + +/* -- sidebar --------------------------------------------------------------- */ + +div.sphinxsidebarwrapper { + padding: 10px 5px 0 10px; +} + +div.sphinxsidebar { + float: left; + width: 230px; + margin-left: -100%; + font-size: 90%; + word-wrap: break-word; + overflow-wrap : break-word; +} + +div.sphinxsidebar ul { + list-style: none; +} + +div.sphinxsidebar ul ul, +div.sphinxsidebar ul.want-points { + margin-left: 20px; + list-style: square; +} + +div.sphinxsidebar ul ul { + margin-top: 0; + margin-bottom: 0; +} + +div.sphinxsidebar form { + margin-top: 10px; +} + +div.sphinxsidebar input { + border: 1px solid #98dbcc; + font-family: sans-serif; + font-size: 1em; +} + +div.sphinxsidebar #searchbox form.search { + overflow: hidden; +} + +div.sphinxsidebar #searchbox input[type="text"] { + float: left; + width: 80%; + padding: 0.25em; + box-sizing: border-box; +} + +div.sphinxsidebar #searchbox input[type="submit"] { + float: left; + width: 20%; + border-left: none; + padding: 0.25em; + box-sizing: border-box; +} + + +img { + border: 0; + max-width: 100%; +} + +/* -- search page ----------------------------------------------------------- */ + +ul.search { + margin: 10px 0 0 20px; + padding: 0; +} + +ul.search li { + padding: 5px 0 5px 20px; + background-image: url(file.png); + background-repeat: no-repeat; + background-position: 0 7px; +} + +ul.search li a { + font-weight: bold; +} + +ul.search li p.context { + color: #888; + margin: 2px 0 0 30px; + text-align: left; +} + +ul.keywordmatches li.goodmatch a { + font-weight: bold; +} + +/* -- index page ------------------------------------------------------------ */ + +table.contentstable { + width: 90%; + margin-left: auto; + margin-right: auto; +} + +table.contentstable p.biglink { + line-height: 150%; +} + +a.biglink { + font-size: 1.3em; +} + +span.linkdescr { + font-style: italic; + padding-top: 5px; + font-size: 90%; +} + +/* -- general index --------------------------------------------------------- */ + +table.indextable { + width: 100%; +} + +table.indextable td { + text-align: left; + vertical-align: top; +} + +table.indextable ul { + margin-top: 0; + margin-bottom: 0; + list-style-type: none; +} + +table.indextable > tbody > tr > td > ul { + padding-left: 0em; +} + +table.indextable tr.pcap { + height: 10px; +} + +table.indextable tr.cap { + margin-top: 10px; + background-color: #f2f2f2; +} + +img.toggler { + margin-right: 3px; + margin-top: 3px; + cursor: pointer; +} + +div.modindex-jumpbox { + border-top: 1px solid #ddd; + border-bottom: 1px solid #ddd; + margin: 1em 0 1em 0; + padding: 0.4em; +} + +div.genindex-jumpbox { + border-top: 1px solid #ddd; + border-bottom: 1px solid #ddd; + margin: 1em 0 1em 0; + padding: 0.4em; +} + +/* -- domain module index --------------------------------------------------- */ + +table.modindextable td { + padding: 2px; + border-collapse: collapse; +} + +/* -- general body styles --------------------------------------------------- */ + +div.body { + min-width: 450px; + max-width: 800px; +} + +div.body p, div.body dd, div.body li, div.body blockquote { + -moz-hyphens: auto; + -ms-hyphens: auto; + -webkit-hyphens: auto; + hyphens: auto; +} + +a.headerlink { + visibility: hidden; +} + +a.brackets:before, +span.brackets > a:before{ + content: "["; +} + +a.brackets:after, +span.brackets > a:after { + content: "]"; +} + +h1:hover > a.headerlink, +h2:hover > a.headerlink, +h3:hover > a.headerlink, +h4:hover > a.headerlink, +h5:hover > a.headerlink, +h6:hover > a.headerlink, +dt:hover > a.headerlink, +caption:hover > a.headerlink, +p.caption:hover > a.headerlink, +div.code-block-caption:hover > a.headerlink { + visibility: visible; +} + +div.body p.caption { + text-align: inherit; +} + +div.body td { + text-align: left; +} + +.first { + margin-top: 0 !important; +} + +p.rubric { + margin-top: 30px; + font-weight: bold; +} + +img.align-left, figure.align-left, .figure.align-left, object.align-left { + clear: left; + float: left; + margin-right: 1em; +} + +img.align-right, figure.align-right, .figure.align-right, object.align-right { + clear: right; + float: right; + margin-left: 1em; +} + +img.align-center, figure.align-center, .figure.align-center, object.align-center { + display: block; + margin-left: auto; + margin-right: auto; +} + +img.align-default, figure.align-default, .figure.align-default { + display: block; + margin-left: auto; + margin-right: auto; +} + +.align-left { + text-align: left; +} + +.align-center { + text-align: center; +} + +.align-default { + text-align: center; +} + +.align-right { + text-align: right; +} + +/* -- sidebars -------------------------------------------------------------- */ + +div.sidebar, +aside.sidebar { + margin: 0 0 0.5em 1em; + border: 1px solid #ddb; + padding: 7px; + background-color: #ffe; + width: 40%; + float: right; + clear: right; + overflow-x: auto; +} + +p.sidebar-title { + font-weight: bold; +} + +div.admonition, div.topic, blockquote { + clear: left; +} + +/* -- topics ---------------------------------------------------------------- */ + +div.topic { + border: 1px solid #ccc; + padding: 7px; + margin: 10px 0 10px 0; +} + +p.topic-title { + font-size: 1.1em; + font-weight: bold; + margin-top: 10px; +} + +/* -- admonitions ----------------------------------------------------------- */ + +div.admonition { + margin-top: 10px; + margin-bottom: 10px; + padding: 7px; +} + +div.admonition dt { + font-weight: bold; +} + +p.admonition-title { + margin: 0px 10px 5px 0px; + font-weight: bold; +} + +div.body p.centered { + text-align: center; + margin-top: 25px; +} + +/* -- content of sidebars/topics/admonitions -------------------------------- */ + +div.sidebar > :last-child, +aside.sidebar > :last-child, +div.topic > :last-child, +div.admonition > :last-child { + margin-bottom: 0; +} + +div.sidebar::after, +aside.sidebar::after, +div.topic::after, +div.admonition::after, +blockquote::after { + display: block; + content: ''; + clear: both; +} + +/* -- tables ---------------------------------------------------------------- */ + +table.docutils { + margin-top: 10px; + margin-bottom: 10px; + border: 0; + border-collapse: collapse; +} + +table.align-center { + margin-left: auto; + margin-right: auto; +} + +table.align-default { + margin-left: auto; + margin-right: auto; +} + +table caption span.caption-number { + font-style: italic; +} + +table caption span.caption-text { +} + +table.docutils td, table.docutils th { + padding: 1px 8px 1px 5px; + border-top: 0; + border-left: 0; + border-right: 0; + border-bottom: 1px solid #aaa; +} + +table.footnote td, table.footnote th { + border: 0 !important; +} + +th { + text-align: left; + padding-right: 5px; +} + +table.citation { + border-left: solid 1px gray; + margin-left: 1px; +} + +table.citation td { + border-bottom: none; +} + +th > :first-child, +td > :first-child { + margin-top: 0px; +} + +th > :last-child, +td > :last-child { + margin-bottom: 0px; +} + +/* -- figures --------------------------------------------------------------- */ + +div.figure, figure { + margin: 0.5em; + padding: 0.5em; +} + +div.figure p.caption, figcaption { + padding: 0.3em; +} + +div.figure p.caption span.caption-number, +figcaption span.caption-number { + font-style: italic; +} + +div.figure p.caption span.caption-text, +figcaption span.caption-text { +} + +/* -- field list styles ----------------------------------------------------- */ + +table.field-list td, table.field-list th { + border: 0 !important; +} + +.field-list ul { + margin: 0; + padding-left: 1em; +} + +.field-list p { + margin: 0; +} + +.field-name { + -moz-hyphens: manual; + -ms-hyphens: manual; + -webkit-hyphens: manual; + hyphens: manual; +} + +/* -- hlist styles ---------------------------------------------------------- */ + +table.hlist { + margin: 1em 0; +} + +table.hlist td { + vertical-align: top; +} + +/* -- object description styles --------------------------------------------- */ + +.sig { + font-family: 'Consolas', 'Menlo', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace; +} + +.sig-name, code.descname { + background-color: transparent; + font-weight: bold; +} + +.sig-name { + font-size: 1.1em; +} + +code.descname { + font-size: 1.2em; +} + +.sig-prename, code.descclassname { + background-color: transparent; +} + +.optional { + font-size: 1.3em; +} + +.sig-paren { + font-size: larger; +} + +.sig-param.n { + font-style: italic; +} + +/* C++ specific styling */ + +.sig-inline.c-texpr, +.sig-inline.cpp-texpr { + font-family: unset; +} + +.sig.c .k, .sig.c .kt, +.sig.cpp .k, .sig.cpp .kt { + color: #0033B3; +} + +.sig.c .m, +.sig.cpp .m { + color: #1750EB; +} + +.sig.c .s, .sig.c .sc, +.sig.cpp .s, .sig.cpp .sc { + color: #067D17; +} + + +/* -- other body styles ----------------------------------------------------- */ + +ol.arabic { + list-style: decimal; +} + +ol.loweralpha { + list-style: lower-alpha; +} + +ol.upperalpha { + list-style: upper-alpha; +} + +ol.lowerroman { + list-style: lower-roman; +} + +ol.upperroman { + list-style: upper-roman; +} + +:not(li) > ol > li:first-child > :first-child, +:not(li) > ul > li:first-child > :first-child { + margin-top: 0px; +} + +:not(li) > ol > li:last-child > :last-child, +:not(li) > ul > li:last-child > :last-child { + margin-bottom: 0px; +} + +ol.simple ol p, +ol.simple ul p, +ul.simple ol p, +ul.simple ul p { + margin-top: 0; +} + +ol.simple > li:not(:first-child) > p, +ul.simple > li:not(:first-child) > p { + margin-top: 0; +} + +ol.simple p, +ul.simple p { + margin-bottom: 0; +} + +dl.footnote > dt, +dl.citation > dt { + float: left; + margin-right: 0.5em; +} + +dl.footnote > dd, +dl.citation > dd { + margin-bottom: 0em; +} + +dl.footnote > dd:after, +dl.citation > dd:after { + content: ""; + clear: both; +} + +dl.field-list { + display: grid; + grid-template-columns: fit-content(30%) auto; +} + +dl.field-list > dt { + font-weight: bold; + word-break: break-word; + padding-left: 0.5em; + padding-right: 5px; +} + +dl.field-list > dt:after { + content: ":"; +} + +dl.field-list > dd { + padding-left: 0.5em; + margin-top: 0em; + margin-left: 0em; + margin-bottom: 0em; +} + +dl { + margin-bottom: 15px; +} + +dd > :first-child { + margin-top: 0px; +} + +dd ul, dd table { + margin-bottom: 10px; +} + +dd { + margin-top: 3px; + margin-bottom: 10px; + margin-left: 30px; +} + +dl > dd:last-child, +dl > dd:last-child > :last-child { + margin-bottom: 0; +} + +dt:target, span.highlighted { + background-color: #fbe54e; +} + +rect.highlighted { + fill: #fbe54e; +} + +dl.glossary dt { + font-weight: bold; + font-size: 1.1em; +} + +.versionmodified { + font-style: italic; +} + +.system-message { + background-color: #fda; + padding: 5px; + border: 3px solid red; +} + +.footnote:target { + background-color: #ffa; +} + +.line-block { + display: block; + margin-top: 1em; + margin-bottom: 1em; +} + +.line-block .line-block { + margin-top: 0; + margin-bottom: 0; + margin-left: 1.5em; +} + +.guilabel, .menuselection { + font-family: sans-serif; +} + +.accelerator { + text-decoration: underline; +} + +.classifier { + font-style: oblique; +} + +.classifier:before { + font-style: normal; + margin: 0 0.5em; + content: ":"; + display: inline-block; +} + +abbr, acronym { + border-bottom: dotted 1px; + cursor: help; +} + +/* -- code displays --------------------------------------------------------- */ + +pre { + overflow: auto; + overflow-y: hidden; /* fixes display issues on Chrome browsers */ +} + +pre, div[class*="highlight-"] { + clear: both; +} + +span.pre { + -moz-hyphens: none; + -ms-hyphens: none; + -webkit-hyphens: none; + hyphens: none; +} + +div[class*="highlight-"] { + margin: 1em 0; +} + +td.linenos pre { + border: 0; + background-color: transparent; + color: #aaa; +} + +table.highlighttable { + display: block; +} + +table.highlighttable tbody { + display: block; +} + +table.highlighttable tr { + display: flex; +} + +table.highlighttable td { + margin: 0; + padding: 0; +} + +table.highlighttable td.linenos { + padding-right: 0.5em; +} + +table.highlighttable td.code { + flex: 1; + overflow: hidden; +} + +.highlight .hll { + display: block; +} + +div.highlight pre, +table.highlighttable pre { + margin: 0; +} + +div.code-block-caption + div { + margin-top: 0; +} + +div.code-block-caption { + margin-top: 1em; + padding: 2px 5px; + font-size: small; +} + +div.code-block-caption code { + background-color: transparent; +} + +table.highlighttable td.linenos, +span.linenos, +div.highlight span.gp { /* gp: Generic.Prompt */ + user-select: none; + -webkit-user-select: text; /* Safari fallback only */ + -webkit-user-select: none; /* Chrome/Safari */ + -moz-user-select: none; /* Firefox */ + -ms-user-select: none; /* IE10+ */ +} + +div.code-block-caption span.caption-number { + padding: 0.1em 0.3em; + font-style: italic; +} + +div.code-block-caption span.caption-text { +} + +div.literal-block-wrapper { + margin: 1em 0; +} + +code.xref, a code { + background-color: transparent; + font-weight: bold; +} + +h1 code, h2 code, h3 code, h4 code, h5 code, h6 code { + background-color: transparent; +} + +.viewcode-link { + float: right; +} + +.viewcode-back { + float: right; + font-family: sans-serif; +} + +div.viewcode-block:target { + margin: -1px -10px; + padding: 0 10px; +} + +/* -- math display ---------------------------------------------------------- */ + +img.math { + vertical-align: middle; +} + +div.body div.math p { + text-align: center; +} + +span.eqno { + float: right; +} + +span.eqno a.headerlink { + position: absolute; + z-index: 1; +} + +div.math:hover a.headerlink { + visibility: visible; +} + +/* -- printout stylesheet --------------------------------------------------- */ + +@media print { + div.document, + div.documentwrapper, + div.bodywrapper { + margin: 0 !important; + width: 100%; + } + + div.sphinxsidebar, + div.related, + div.footer, + #top-link { + display: none; + } +} \ No newline at end of file diff --git a/master/_static/check-solid.svg b/master/_static/check-solid.svg new file mode 100644 index 0000000000..92fad4b5c0 --- /dev/null +++ b/master/_static/check-solid.svg @@ -0,0 +1,4 @@ + + + + diff --git a/master/_static/clipboard.min.js b/master/_static/clipboard.min.js new file mode 100644 index 0000000000..54b3c46381 --- /dev/null +++ b/master/_static/clipboard.min.js @@ -0,0 +1,7 @@ +/*! + * clipboard.js v2.0.8 + * https://clipboardjs.com/ + * + * Licensed MIT © Zeno Rocha + */ +!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?exports.ClipboardJS=e():t.ClipboardJS=e()}(this,function(){return n={686:function(t,e,n){"use strict";n.d(e,{default:function(){return o}});var e=n(279),i=n.n(e),e=n(370),u=n.n(e),e=n(817),c=n.n(e);function a(t){try{return document.execCommand(t)}catch(t){return}}var f=function(t){t=c()(t);return a("cut"),t};var l=function(t){var e,n,o,r=1 + + + + diff --git a/master/_static/copybutton.css b/master/_static/copybutton.css new file mode 100644 index 0000000000..f1916ec7d1 --- /dev/null +++ b/master/_static/copybutton.css @@ -0,0 +1,94 @@ +/* Copy buttons */ +button.copybtn { + position: absolute; + display: flex; + top: .3em; + right: .3em; + width: 1.7em; + height: 1.7em; + opacity: 0; + transition: opacity 0.3s, border .3s, background-color .3s; + user-select: none; + padding: 0; + border: none; + outline: none; + border-radius: 0.4em; + /* The colors that GitHub uses */ + border: #1b1f2426 1px solid; + background-color: #f6f8fa; + color: #57606a; +} + +button.copybtn.success { + border-color: #22863a; + color: #22863a; +} + +button.copybtn svg { + stroke: currentColor; + width: 1.5em; + height: 1.5em; + padding: 0.1em; +} + +div.highlight { + position: relative; +} + +/* Show the copybutton */ +.highlight:hover button.copybtn, button.copybtn.success { + opacity: 1; +} + +.highlight button.copybtn:hover { + background-color: rgb(235, 235, 235); +} + +.highlight button.copybtn:active { + background-color: rgb(187, 187, 187); +} + +/** + * A minimal CSS-only tooltip copied from: + * https://codepen.io/mildrenben/pen/rVBrpK + * + * To use, write HTML like the following: + * + *

Short

+ */ + .o-tooltip--left { + position: relative; + } + + .o-tooltip--left:after { + opacity: 0; + visibility: hidden; + position: absolute; + content: attr(data-tooltip); + padding: .2em; + font-size: .8em; + left: -.2em; + background: grey; + color: white; + white-space: nowrap; + z-index: 2; + border-radius: 2px; + transform: translateX(-102%) translateY(0); + transition: opacity 0.2s cubic-bezier(0.64, 0.09, 0.08, 1), transform 0.2s cubic-bezier(0.64, 0.09, 0.08, 1); +} + +.o-tooltip--left:hover:after { + display: block; + opacity: 1; + visibility: visible; + transform: translateX(-100%) translateY(0); + transition: opacity 0.2s cubic-bezier(0.64, 0.09, 0.08, 1), transform 0.2s cubic-bezier(0.64, 0.09, 0.08, 1); + transition-delay: .5s; +} + +/* By default the copy button shouldn't show up when printing a page */ +@media print { + button.copybtn { + display: none; + } +} diff --git a/master/_static/copybutton.js b/master/_static/copybutton.js new file mode 100644 index 0000000000..2ea7ff3e21 --- /dev/null +++ b/master/_static/copybutton.js @@ -0,0 +1,248 @@ +// Localization support +const messages = { + 'en': { + 'copy': 'Copy', + 'copy_to_clipboard': 'Copy to clipboard', + 'copy_success': 'Copied!', + 'copy_failure': 'Failed to copy', + }, + 'es' : { + 'copy': 'Copiar', + 'copy_to_clipboard': 'Copiar al portapapeles', + 'copy_success': '¡Copiado!', + 'copy_failure': 'Error al copiar', + }, + 'de' : { + 'copy': 'Kopieren', + 'copy_to_clipboard': 'In die Zwischenablage kopieren', + 'copy_success': 'Kopiert!', + 'copy_failure': 'Fehler beim Kopieren', + }, + 'fr' : { + 'copy': 'Copier', + 'copy_to_clipboard': 'Copier dans le presse-papier', + 'copy_success': 'Copié !', + 'copy_failure': 'Échec de la copie', + }, + 'ru': { + 'copy': 'Скопировать', + 'copy_to_clipboard': 'Скопировать в буфер', + 'copy_success': 'Скопировано!', + 'copy_failure': 'Не удалось скопировать', + }, + 'zh-CN': { + 'copy': '复制', + 'copy_to_clipboard': '复制到剪贴板', + 'copy_success': '复制成功!', + 'copy_failure': '复制失败', + }, + 'it' : { + 'copy': 'Copiare', + 'copy_to_clipboard': 'Copiato negli appunti', + 'copy_success': 'Copiato!', + 'copy_failure': 'Errore durante la copia', + } +} + +let locale = 'en' +if( document.documentElement.lang !== undefined + && messages[document.documentElement.lang] !== undefined ) { + locale = document.documentElement.lang +} + +let doc_url_root = DOCUMENTATION_OPTIONS.URL_ROOT; +if (doc_url_root == '#') { + doc_url_root = ''; +} + +/** + * SVG files for our copy buttons + */ +let iconCheck = ` + ${messages[locale]['copy_success']} + + +` + +// If the user specified their own SVG use that, otherwise use the default +let iconCopy = ``; +if (!iconCopy) { + iconCopy = ` + ${messages[locale]['copy_to_clipboard']} + + + +` +} + +/** + * Set up copy/paste for code blocks + */ + +const runWhenDOMLoaded = cb => { + if (document.readyState != 'loading') { + cb() + } else if (document.addEventListener) { + document.addEventListener('DOMContentLoaded', cb) + } else { + document.attachEvent('onreadystatechange', function() { + if (document.readyState == 'complete') cb() + }) + } +} + +const codeCellId = index => `codecell${index}` + +// Clears selected text since ClipboardJS will select the text when copying +const clearSelection = () => { + if (window.getSelection) { + window.getSelection().removeAllRanges() + } else if (document.selection) { + document.selection.empty() + } +} + +// Changes tooltip text for a moment, then changes it back +// We want the timeout of our `success` class to be a bit shorter than the +// tooltip and icon change, so that we can hide the icon before changing back. +var timeoutIcon = 2000; +var timeoutSuccessClass = 1500; + +const temporarilyChangeTooltip = (el, oldText, newText) => { + el.setAttribute('data-tooltip', newText) + el.classList.add('success') + // Remove success a little bit sooner than we change the tooltip + // So that we can use CSS to hide the copybutton first + setTimeout(() => el.classList.remove('success'), timeoutSuccessClass) + setTimeout(() => el.setAttribute('data-tooltip', oldText), timeoutIcon) +} + +// Changes the copy button icon for two seconds, then changes it back +const temporarilyChangeIcon = (el) => { + el.innerHTML = iconCheck; + setTimeout(() => {el.innerHTML = iconCopy}, timeoutIcon) +} + +const addCopyButtonToCodeCells = () => { + // If ClipboardJS hasn't loaded, wait a bit and try again. This + // happens because we load ClipboardJS asynchronously. + if (window.ClipboardJS === undefined) { + setTimeout(addCopyButtonToCodeCells, 250) + return + } + + // Add copybuttons to all of our code cells + const COPYBUTTON_SELECTOR = 'div.highlight pre'; + const codeCells = document.querySelectorAll(COPYBUTTON_SELECTOR) + codeCells.forEach((codeCell, index) => { + const id = codeCellId(index) + codeCell.setAttribute('id', id) + + const clipboardButton = id => + `` + codeCell.insertAdjacentHTML('afterend', clipboardButton(id)) + }) + +function escapeRegExp(string) { + return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string +} + +/** + * Removes excluded text from a Node. + * + * @param {Node} target Node to filter. + * @param {string} exclude CSS selector of nodes to exclude. + * @returns {DOMString} Text from `target` with text removed. + */ +function filterText(target, exclude) { + const clone = target.cloneNode(true); // clone as to not modify the live DOM + if (exclude) { + // remove excluded nodes + clone.querySelectorAll(exclude).forEach(node => node.remove()); + } + return clone.innerText; +} + +// Callback when a copy button is clicked. Will be passed the node that was clicked +// should then grab the text and replace pieces of text that shouldn't be used in output +function formatCopyText(textContent, copybuttonPromptText, isRegexp = false, onlyCopyPromptLines = true, removePrompts = true, copyEmptyLines = true, lineContinuationChar = "", hereDocDelim = "") { + var regexp; + var match; + + // Do we check for line continuation characters and "HERE-documents"? + var useLineCont = !!lineContinuationChar + var useHereDoc = !!hereDocDelim + + // create regexp to capture prompt and remaining line + if (isRegexp) { + regexp = new RegExp('^(' + copybuttonPromptText + ')(.*)') + } else { + regexp = new RegExp('^(' + escapeRegExp(copybuttonPromptText) + ')(.*)') + } + + const outputLines = []; + var promptFound = false; + var gotLineCont = false; + var gotHereDoc = false; + const lineGotPrompt = []; + for (const line of textContent.split('\n')) { + match = line.match(regexp) + if (match || gotLineCont || gotHereDoc) { + promptFound = regexp.test(line) + lineGotPrompt.push(promptFound) + if (removePrompts && promptFound) { + outputLines.push(match[2]) + } else { + outputLines.push(line) + } + gotLineCont = line.endsWith(lineContinuationChar) & useLineCont + if (line.includes(hereDocDelim) & useHereDoc) + gotHereDoc = !gotHereDoc + } else if (!onlyCopyPromptLines) { + outputLines.push(line) + } else if (copyEmptyLines && line.trim() === '') { + outputLines.push(line) + } + } + + // If no lines with the prompt were found then just use original lines + if (lineGotPrompt.some(v => v === true)) { + textContent = outputLines.join('\n'); + } + + // Remove a trailing newline to avoid auto-running when pasting + if (textContent.endsWith("\n")) { + textContent = textContent.slice(0, -1) + } + return textContent +} + + +var copyTargetText = (trigger) => { + var target = document.querySelector(trigger.attributes['data-clipboard-target'].value); + + // get filtered text + let exclude = '.linenos'; + + let text = filterText(target, exclude); + return formatCopyText(text, '', false, true, true, true, '', '') +} + + // Initialize with a callback so we can modify the text before copy + const clipboard = new ClipboardJS('.copybtn', {text: copyTargetText}) + + // Update UI with error/success messages + clipboard.on('success', event => { + clearSelection() + temporarilyChangeTooltip(event.trigger, messages[locale]['copy'], messages[locale]['copy_success']) + temporarilyChangeIcon(event.trigger) + }) + + clipboard.on('error', event => { + temporarilyChangeTooltip(event.trigger, messages[locale]['copy'], messages[locale]['copy_failure']) + }) +} + +runWhenDOMLoaded(addCopyButtonToCodeCells) \ No newline at end of file diff --git a/master/_static/copybutton_funcs.js b/master/_static/copybutton_funcs.js new file mode 100644 index 0000000000..dbe1aaad79 --- /dev/null +++ b/master/_static/copybutton_funcs.js @@ -0,0 +1,73 @@ +function escapeRegExp(string) { + return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string +} + +/** + * Removes excluded text from a Node. + * + * @param {Node} target Node to filter. + * @param {string} exclude CSS selector of nodes to exclude. + * @returns {DOMString} Text from `target` with text removed. + */ +export function filterText(target, exclude) { + const clone = target.cloneNode(true); // clone as to not modify the live DOM + if (exclude) { + // remove excluded nodes + clone.querySelectorAll(exclude).forEach(node => node.remove()); + } + return clone.innerText; +} + +// Callback when a copy button is clicked. Will be passed the node that was clicked +// should then grab the text and replace pieces of text that shouldn't be used in output +export function formatCopyText(textContent, copybuttonPromptText, isRegexp = false, onlyCopyPromptLines = true, removePrompts = true, copyEmptyLines = true, lineContinuationChar = "", hereDocDelim = "") { + var regexp; + var match; + + // Do we check for line continuation characters and "HERE-documents"? + var useLineCont = !!lineContinuationChar + var useHereDoc = !!hereDocDelim + + // create regexp to capture prompt and remaining line + if (isRegexp) { + regexp = new RegExp('^(' + copybuttonPromptText + ')(.*)') + } else { + regexp = new RegExp('^(' + escapeRegExp(copybuttonPromptText) + ')(.*)') + } + + const outputLines = []; + var promptFound = false; + var gotLineCont = false; + var gotHereDoc = false; + const lineGotPrompt = []; + for (const line of textContent.split('\n')) { + match = line.match(regexp) + if (match || gotLineCont || gotHereDoc) { + promptFound = regexp.test(line) + lineGotPrompt.push(promptFound) + if (removePrompts && promptFound) { + outputLines.push(match[2]) + } else { + outputLines.push(line) + } + gotLineCont = line.endsWith(lineContinuationChar) & useLineCont + if (line.includes(hereDocDelim) & useHereDoc) + gotHereDoc = !gotHereDoc + } else if (!onlyCopyPromptLines) { + outputLines.push(line) + } else if (copyEmptyLines && line.trim() === '') { + outputLines.push(line) + } + } + + // If no lines with the prompt were found then just use original lines + if (lineGotPrompt.some(v => v === true)) { + textContent = outputLines.join('\n'); + } + + // Remove a trailing newline to avoid auto-running when pasting + if (textContent.endsWith("\n")) { + textContent = textContent.slice(0, -1) + } + return textContent +} diff --git a/master/_static/css/main.css b/master/_static/css/main.css new file mode 100644 index 0000000000..4ac0174528 --- /dev/null +++ b/master/_static/css/main.css @@ -0,0 +1 @@ +@media print,screen and (min-width:40em){.reveal,.reveal.large,.reveal.small,.reveal.tiny{left:auto;margin:0 auto;right:auto}}/*! normalize.css v8.0.0 | MIT License | github.com/necolas/normalize.css */html{-webkit-text-size-adjust:100%;line-height:1.15}h1{font-size:2em;margin:.67em 0}hr{-webkit-box-sizing:content-box;box-sizing:content-box;overflow:visible}pre{font-family:monospace,monospace;font-size:1em}a{background-color:transparent}abbr[title]{border-bottom:0;-webkit-text-decoration:underline dotted;text-decoration:underline dotted}b,strong{font-weight:bolder}code,kbd,samp{font-family:monospace,monospace;font-size:1em}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}img{border-style:none}button,input,optgroup,select,textarea{font-size:100%;line-height:1.15;margin:0}button,input{overflow:visible}button,select{text-transform:none}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button}[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner,button::-moz-focus-inner{border-style:none;padding:0}[type=button]:-moz-focusring,[type=reset]:-moz-focusring,[type=submit]:-moz-focusring,button:-moz-focusring{outline:1px dotted ButtonText}fieldset{padding:.35em .75em .625em}legend{-webkit-box-sizing:border-box;box-sizing:border-box;color:inherit;display:table;padding:0;white-space:normal}progress{vertical-align:baseline}textarea{overflow:auto}[type=checkbox],[type=radio]{-webkit-box-sizing:border-box;box-sizing:border-box;padding:0}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}details{display:block}summary{display:list-item}template{display:none}[hidden]{display:none}[data-whatinput=mouse] *,[data-whatinput=mouse] :focus,[data-whatinput=touch] *,[data-whatinput=touch] :focus,[data-whatintent=mouse] *,[data-whatintent=mouse] :focus,[data-whatintent=touch] *,[data-whatintent=touch] :focus{outline:0}[draggable=false]{-webkit-touch-callout:none;-webkit-user-select:none}.foundation-mq{font-family:"small=0em&medium=40em&large=64em&xlarge=75em&xxlarge=90em"}html{-webkit-box-sizing:border-box;font-size:100%}*,:after,:before{-webkit-box-sizing:inherit}body{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;background:#fefefe;color:#0a0a0a;font-family:Helvetica Neue,Helvetica,Roboto,Arial,sans-serif;font-weight:400;line-height:1.5;margin:0;padding:0}img{-ms-interpolation-mode:bicubic;display:inline-block;height:auto;vertical-align:middle}textarea{border-radius:0;height:auto;min-height:50px}select{-webkit-box-sizing:border-box;box-sizing:border-box;width:100%}.map_canvas embed,.map_canvas img,.map_canvas object,.mqa-display embed,.mqa-display img,.mqa-display object{max-width:none!important}button{-webkit-appearance:none;-moz-appearance:none;appearance:none;background:0 0;border:0;border-radius:0;cursor:auto;line-height:1;padding:0}[data-whatinput=mouse] button{outline:0}pre{-webkit-overflow-scrolling:touch;overflow:auto}button,input,optgroup,select,textarea{font-family:inherit}.is-visible{display:block!important}.is-hidden{display:none!important}[type=color],[type=date],[type=datetime-local],[type=datetime],[type=email],[type=month],[type=number],[type=password],[type=search],[type=tel],[type=text],[type=time],[type=url],[type=week],textarea{-webkit-appearance:none;-moz-appearance:none;appearance:none;background-color:#fefefe;border:1px solid #cacaca;border-radius:0;-webkit-box-shadow:inset 0 1px 2px hsla(0,0%,4%,.1);box-shadow:inset 0 1px 2px hsla(0,0%,4%,.1);-webkit-box-sizing:border-box;box-sizing:border-box;color:#0a0a0a;display:block;font-family:inherit;font-size:1rem;font-weight:400;height:2.4375rem;line-height:1.5;margin:0 0 1rem;padding:.5rem;-webkit-transition:border-color .25s ease-in-out,-webkit-box-shadow .5s;transition:border-color .25s ease-in-out,-webkit-box-shadow .5s;transition:box-shadow .5s,border-color .25s ease-in-out;transition:box-shadow .5s,border-color .25s ease-in-out,-webkit-box-shadow .5s;width:100%}[type=color]:focus,[type=date]:focus,[type=datetime-local]:focus,[type=datetime]:focus,[type=email]:focus,[type=month]:focus,[type=number]:focus,[type=password]:focus,[type=search]:focus,[type=tel]:focus,[type=text]:focus,[type=time]:focus,[type=url]:focus,[type=week]:focus,textarea:focus{background-color:#fefefe;border:1px solid #8a8a8a;-webkit-box-shadow:0 0 5px #cacaca;box-shadow:0 0 5px #cacaca;outline:0;-webkit-transition:border-color .25s ease-in-out,-webkit-box-shadow .5s;transition:border-color .25s ease-in-out,-webkit-box-shadow .5s;transition:box-shadow .5s,border-color .25s ease-in-out;transition:box-shadow .5s,border-color .25s ease-in-out,-webkit-box-shadow .5s}textarea{max-width:100%}textarea[rows]{height:auto}input:disabled,input[readonly],textarea:disabled,textarea[readonly]{background-color:#e6e6e6;cursor:not-allowed}[type=button],[type=submit]{-webkit-appearance:none;-moz-appearance:none;appearance:none;border-radius:0}input[type=search]{-webkit-box-sizing:border-box;box-sizing:border-box}::-webkit-input-placeholder{color:#cacaca}::-moz-placeholder{color:#cacaca}:-ms-input-placeholder{color:#cacaca}::-ms-input-placeholder{color:#cacaca}::placeholder{color:#cacaca}[type=checkbox],[type=file],[type=radio]{margin:0 0 1rem}[type=checkbox]+label,[type=radio]+label{display:inline-block;margin-bottom:0;margin-left:.5rem;margin-right:1rem;vertical-align:baseline}[type=checkbox]+label[for],[type=radio]+label[for]{cursor:pointer}label>[type=checkbox],label>[type=radio]{margin-right:.5rem}[type=file]{width:100%}label{color:#0a0a0a;display:block;font-size:.875rem;font-weight:400;line-height:1.8;margin:0}label.middle{line-height:1.5;margin:0 0 1rem;padding:.5625rem 0}.help-text{color:#0a0a0a;font-size:.8125rem;font-style:italic;margin-top:-.5rem}.input-group{-webkit-box-align:stretch;-ms-flex-align:stretch;-webkit-align-items:stretch;align-items:stretch;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;margin-bottom:1rem;width:100%}.input-group>:first-child,.input-group>:first-child.input-group-button>*{border-radius:0}.input-group>:last-child,.input-group>:last-child.input-group-button>*{border-radius:0}.input-group-button,.input-group-button a,.input-group-button button,.input-group-button input,.input-group-button label,.input-group-field,.input-group-label{margin:0;white-space:nowrap}.input-group-label{-webkit-box-flex:0;-webkit-box-align:center;-ms-flex-align:center;-webkit-align-items:center;align-items:center;background:#e6e6e6;border:1px solid #cacaca;color:#0a0a0a;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto;padding:0 1rem;text-align:center;white-space:nowrap}.input-group-label:first-child{border-right:0}.input-group-label:last-child{border-left:0}.input-group-field{-webkit-box-flex:1;border-radius:0;-webkit-flex:1 1 0px;-ms-flex:1 1 0px;flex:1 1 0px;min-width:0}.input-group-button{-webkit-box-flex:0;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto;padding-bottom:0;padding-top:0;text-align:center}.input-group-button a,.input-group-button button,.input-group-button input,.input-group-button label{-ms-flex-item-align:stretch;-webkit-align-self:stretch;align-self:stretch;font-size:1rem;height:auto;padding-bottom:0;padding-top:0}fieldset{border:0;margin:0;padding:0}legend{margin-bottom:.5rem;max-width:100%}.fieldset{border:1px solid #cacaca;margin:1.125rem 0;padding:1.25rem}.fieldset legend{margin:0 0 0 -.1875rem;padding:0 .1875rem}select{-webkit-appearance:none;-moz-appearance:none;appearance:none;background-color:#fefefe;background-image:url('data:image/svg+xml;utf8,');background-origin:content-box;background-position:right -1rem center;background-repeat:no-repeat;background-size:9px 6px;border:1px solid #cacaca;border-radius:0;color:#0a0a0a;font-family:inherit;font-size:1rem;font-weight:400;height:2.4375rem;line-height:1.5;margin:0 0 1rem;padding:.5rem 1.5rem .5rem .5rem;-webkit-transition:border-color .25s ease-in-out,-webkit-box-shadow .5s;transition:border-color .25s ease-in-out,-webkit-box-shadow .5s;transition:box-shadow .5s,border-color .25s ease-in-out;transition:box-shadow .5s,border-color .25s ease-in-out,-webkit-box-shadow .5s}@media screen and (min-width:0\0){select{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAYCAYAAACbU/80AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAIpJREFUeNrEkckNgDAMBBfRkEt0ObRBBdsGXUDgmQfK4XhH2m8czQAAy27R3tsw4Qfe2x8uOO6oYLb6GlOor3GF+swURAOmUJ+RwtEJs9WvTGEYxBXqI1MQAZhCfUQKRzDMVj+TwrAIV6jvSUEkYAr1LSkcyTBb/V+KYfX7xAeusq3sLDtGH3kEGACPWIflNZfhRQAAAABJRU5ErkJggg==)}}select:focus{background-color:#fefefe;border:1px solid #8a8a8a;-webkit-box-shadow:0 0 5px #cacaca;box-shadow:0 0 5px #cacaca;outline:0;-webkit-transition:border-color .25s ease-in-out,-webkit-box-shadow .5s;transition:border-color .25s ease-in-out,-webkit-box-shadow .5s;transition:box-shadow .5s,border-color .25s ease-in-out;transition:box-shadow .5s,border-color .25s ease-in-out,-webkit-box-shadow .5s}select:disabled{background-color:#e6e6e6;cursor:not-allowed}select::-ms-expand{display:none}select[multiple]{background-image:none;height:auto}select:not([multiple]){padding-bottom:0;padding-top:0}.is-invalid-input:not(:focus){background-color:#f9ecea;border-color:#cc4b37}.is-invalid-input:not(:focus)::-webkit-input-placeholder{color:#cc4b37}.is-invalid-input:not(:focus)::-moz-placeholder{color:#cc4b37}.is-invalid-input:not(:focus):-ms-input-placeholder{color:#cc4b37}.is-invalid-input:not(:focus)::-ms-input-placeholder{color:#cc4b37}.is-invalid-input:not(:focus)::placeholder{color:#cc4b37}.form-error,.is-invalid-label{color:#cc4b37}.form-error{display:none;font-size:.75rem;font-weight:700;margin-bottom:1rem;margin-top:-.5rem}.form-error.is-visible{display:block}blockquote,dd,div,dl,dt,form,h1,h2,h3,h4,h5,h6,li,ol,p,pre,td,th,ul{margin:0;padding:0}p{text-rendering:optimizeLegibility;font-size:inherit;line-height:1.6;margin-bottom:1rem}em,i{font-style:italic}b,em,i,strong{line-height:inherit}b,strong{font-weight:700}small{font-size:80%;line-height:inherit}.h1,.h2,.h3,.h4,.h5,.h6,h1,h2,h3,h4,h5,h6{text-rendering:optimizeLegibility;color:inherit;font-family:Helvetica Neue,Helvetica,Roboto,Arial,sans-serif;font-style:normal;font-weight:400}.h1 small,.h2 small,.h3 small,.h4 small,.h5 small,.h6 small,h1 small,h2 small,h3 small,h4 small,h5 small,h6 small{color:#cacaca;line-height:0}.h1,h1{font-size:1.5rem}.h1,.h2,h1,h2{line-height:1.4;margin-bottom:.5rem;margin-top:0}.h2,h2{font-size:1.25rem}.h3,h3{font-size:1.1875rem}.h3,.h4,h3,h4{line-height:1.4;margin-bottom:.5rem;margin-top:0}.h4,h4{font-size:1.125rem}.h5,h5{font-size:1.0625rem}.h5,.h6,h5,h6{line-height:1.4;margin-bottom:.5rem;margin-top:0}.h6,h6{font-size:1rem}@media print,screen and (min-width:40em){.h1,h1{font-size:3rem}.h2,h2{font-size:2.5rem}.h3,h3{font-size:1.9375rem}.h4,h4{font-size:1.5625rem}.h5,h5{font-size:1.25rem}.h6,h6{font-size:1rem}}a{color:#1779ba;cursor:pointer;line-height:inherit;text-decoration:none}a:focus,a:hover{color:#1468a0}a img,hr{border:0}hr{border-bottom:1px solid #cacaca;clear:both;height:0;margin:1.25rem auto;max-width:75rem}dl,ol,ul{line-height:1.6;list-style-position:outside;margin-bottom:1rem}li{font-size:inherit}ul{list-style-type:disc}ol,ul{margin-left:1.25rem}ol ol,ol ul,ul ol,ul ul{margin-bottom:0;margin-left:1.25rem}dl{margin-bottom:1rem}dl dt{font-weight:700;margin-bottom:.3rem}blockquote{border-left:1px solid #cacaca;margin:0 0 1rem;padding:.5625rem 1.25rem 0 1.1875rem}blockquote,blockquote p{color:#8a8a8a;line-height:1.6}abbr,abbr[title]{border-bottom:1px dotted #0a0a0a;cursor:help;text-decoration:none}figure,kbd{margin:0}kbd{background-color:#e6e6e6;color:#0a0a0a;font-family:Consolas,Liberation Mono,Courier,monospace;padding:.125rem .25rem 0}.subheader{color:#8a8a8a;font-weight:400;line-height:1.4;margin-bottom:.5rem;margin-top:.2rem}.lead{font-size:125%;line-height:1.6}.stat{font-size:2.5rem;line-height:1}p+.stat{margin-top:-1rem}ol.no-bullet,ul.no-bullet{list-style:none;margin-left:0}.cite-block,cite{color:#8a8a8a;display:block;font-size:.8125rem}.cite-block:before,cite:before{content:"— "}.code-inline,code{word-wrap:break-word;display:inline;max-width:100%;padding:.125rem .3125rem .0625rem}.code-block,.code-inline,code{background-color:#e6e6e6;border:1px solid #cacaca;color:#0a0a0a;font-family:Consolas,Liberation Mono,Courier,monospace;font-weight:400}.code-block{display:block;margin-bottom:1.5rem;overflow:auto;padding:1rem;white-space:pre}.text-left{text-align:left}.text-right{text-align:right}.text-center{text-align:center}.text-justify{text-align:justify}@media print,screen and (min-width:40em){.medium-text-left{text-align:left}.medium-text-right{text-align:right}.medium-text-center{text-align:center}.medium-text-justify{text-align:justify}}@media print,screen and (min-width:64em){.large-text-left{text-align:left}.large-text-right{text-align:right}.large-text-center{text-align:center}.large-text-justify{text-align:justify}}.show-for-print{display:none!important}@media print{*{-webkit-print-color-adjust:economy;background:0 0!important;-webkit-box-shadow:none!important;box-shadow:none!important;color:#000!important;color-adjust:economy;text-shadow:none!important}.show-for-print{display:block!important}.hide-for-print{display:none!important}table.show-for-print{display:table!important}thead.show-for-print{display:table-header-group!important}tbody.show-for-print{display:table-row-group!important}tr.show-for-print{display:table-row!important}td.show-for-print,th.show-for-print{display:table-cell!important}a,a:visited{text-decoration:underline}a[href]:after{content:" (" attr(href) ")"}.ir a:after,a[href^="#"]:after,a[href^="javascript:"]:after{content:""}abbr[title]:after{content:" (" attr(title) ")"}blockquote,pre{border:1px solid #8a8a8a;page-break-inside:avoid}thead{display:table-header-group}img,tr{page-break-inside:avoid}img{max-width:100%!important}@page{margin:.5cm}h2,h3,p{orphans:3;widows:3}h2,h3{page-break-after:avoid}.print-break-inside{page-break-inside:auto}}.grid-container{margin-left:auto;margin-right:auto;max-width:75rem;padding-left:.625rem;padding-right:.625rem}@media print,screen and (min-width:40em){.grid-container{padding-left:.9375rem;padding-right:.9375rem}}.grid-container.fluid{margin-left:auto;margin-right:auto;max-width:100%;padding-left:.625rem;padding-right:.625rem}@media print,screen and (min-width:40em){.grid-container.fluid{padding-left:.9375rem;padding-right:.9375rem}}.grid-container.full{margin-left:auto;margin-right:auto;max-width:100%;padding-left:0;padding-right:0}.grid-x{-webkit-box-orient:horizontal;-webkit-box-direction:normal;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-flow:row wrap;-ms-flex-flow:row wrap;flex-flow:row wrap}.cell{-webkit-box-flex:0;-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto;min-height:0;min-width:0;width:100%}.cell.auto{-webkit-box-flex:1;-webkit-flex:1 1 0;-ms-flex:1 1 0px;flex:1 1 0}.cell.shrink{-webkit-box-flex:0;-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto}.grid-x>.auto{width:auto}.grid-x>.shrink{width:auto}.grid-x>.small-1,.grid-x>.small-2,.grid-x>.small-3,.grid-x>.small-4,.grid-x>.small-5,.grid-x>.small-6,.grid-x>.small-7,.grid-x>.small-8,.grid-x>.small-9,.grid-x>.small-10,.grid-x>.small-11,.grid-x>.small-12,.grid-x>.small-full,.grid-x>.small-shrink{-ms-flex-preferred-size:auto;-webkit-flex-basis:auto;flex-basis:auto}@media print,screen and (min-width:40em){.grid-x>.medium-1,.grid-x>.medium-2,.grid-x>.medium-3,.grid-x>.medium-4,.grid-x>.medium-5,.grid-x>.medium-6,.grid-x>.medium-7,.grid-x>.medium-8,.grid-x>.medium-9,.grid-x>.medium-10,.grid-x>.medium-11,.grid-x>.medium-12,.grid-x>.medium-full,.grid-x>.medium-shrink{-ms-flex-preferred-size:auto;-webkit-flex-basis:auto;flex-basis:auto}}@media print,screen and (min-width:64em){.grid-x>.large-1,.grid-x>.large-2,.grid-x>.large-3,.grid-x>.large-4,.grid-x>.large-5,.grid-x>.large-6,.grid-x>.large-7,.grid-x>.large-8,.grid-x>.large-9,.grid-x>.large-10,.grid-x>.large-11,.grid-x>.large-12,.grid-x>.large-full,.grid-x>.large-shrink{-ms-flex-preferred-size:auto;-webkit-flex-basis:auto;flex-basis:auto}}.grid-x>.small-1,.grid-x>.small-2,.grid-x>.small-3,.grid-x>.small-4,.grid-x>.small-5,.grid-x>.small-6,.grid-x>.small-7,.grid-x>.small-8,.grid-x>.small-9,.grid-x>.small-10,.grid-x>.small-11,.grid-x>.small-12{-webkit-box-flex:0;-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto}.grid-x>.small-1{width:8.33333%}.grid-x>.small-2{width:16.66667%}.grid-x>.small-3{width:25%}.grid-x>.small-4{width:33.33333%}.grid-x>.small-5{width:41.66667%}.grid-x>.small-6{width:50%}.grid-x>.small-7{width:58.33333%}.grid-x>.small-8{width:66.66667%}.grid-x>.small-9{width:75%}.grid-x>.small-10{width:83.33333%}.grid-x>.small-11{width:91.66667%}.grid-x>.small-12{width:100%}@media print,screen and (min-width:40em){.grid-x>.medium-auto{-webkit-box-flex:1;-webkit-flex:1 1 0;-ms-flex:1 1 0px;flex:1 1 0;width:auto}.grid-x>.medium-1,.grid-x>.medium-2,.grid-x>.medium-3,.grid-x>.medium-4,.grid-x>.medium-5,.grid-x>.medium-6,.grid-x>.medium-7,.grid-x>.medium-8,.grid-x>.medium-9,.grid-x>.medium-10,.grid-x>.medium-11,.grid-x>.medium-12,.grid-x>.medium-shrink{-webkit-box-flex:0;-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto}.grid-x>.medium-shrink{width:auto}.grid-x>.medium-1{width:8.33333%}.grid-x>.medium-2{width:16.66667%}.grid-x>.medium-3{width:25%}.grid-x>.medium-4{width:33.33333%}.grid-x>.medium-5{width:41.66667%}.grid-x>.medium-6{width:50%}.grid-x>.medium-7{width:58.33333%}.grid-x>.medium-8{width:66.66667%}.grid-x>.medium-9{width:75%}.grid-x>.medium-10{width:83.33333%}.grid-x>.medium-11{width:91.66667%}.grid-x>.medium-12{width:100%}}@media print,screen and (min-width:64em){.grid-x>.large-auto{-webkit-box-flex:1;-webkit-flex:1 1 0;-ms-flex:1 1 0px;flex:1 1 0;width:auto}.grid-x>.large-1,.grid-x>.large-2,.grid-x>.large-3,.grid-x>.large-4,.grid-x>.large-5,.grid-x>.large-6,.grid-x>.large-7,.grid-x>.large-8,.grid-x>.large-9,.grid-x>.large-10,.grid-x>.large-11,.grid-x>.large-12,.grid-x>.large-shrink{-webkit-box-flex:0;-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto}.grid-x>.large-shrink{width:auto}.grid-x>.large-1{width:8.33333%}.grid-x>.large-2{width:16.66667%}.grid-x>.large-3{width:25%}.grid-x>.large-4{width:33.33333%}.grid-x>.large-5{width:41.66667%}.grid-x>.large-6{width:50%}.grid-x>.large-7{width:58.33333%}.grid-x>.large-8{width:66.66667%}.grid-x>.large-9{width:75%}.grid-x>.large-10{width:83.33333%}.grid-x>.large-11{width:91.66667%}.grid-x>.large-12{width:100%}}.grid-margin-x:not(.grid-x)>.cell{width:auto}.grid-margin-y:not(.grid-y)>.cell{height:auto}.grid-margin-x{margin-left:-.625rem;margin-right:-.625rem}@media print,screen and (min-width:40em){.grid-margin-x{margin-left:-.9375rem;margin-right:-.9375rem}}.grid-margin-x>.cell{margin-left:.625rem;margin-right:.625rem;width:calc(100% - 1.25rem)}@media print,screen and (min-width:40em){.grid-margin-x>.cell{margin-left:.9375rem;margin-right:.9375rem;width:calc(100% - 1.875rem)}}.grid-margin-x>.auto{width:auto}.grid-margin-x>.shrink{width:auto}.grid-margin-x>.small-1{width:calc(8.33333% - 1.25rem)}.grid-margin-x>.small-2{width:calc(16.66667% - 1.25rem)}.grid-margin-x>.small-3{width:calc(25% - 1.25rem)}.grid-margin-x>.small-4{width:calc(33.33333% - 1.25rem)}.grid-margin-x>.small-5{width:calc(41.66667% - 1.25rem)}.grid-margin-x>.small-6{width:calc(50% - 1.25rem)}.grid-margin-x>.small-7{width:calc(58.33333% - 1.25rem)}.grid-margin-x>.small-8{width:calc(66.66667% - 1.25rem)}.grid-margin-x>.small-9{width:calc(75% - 1.25rem)}.grid-margin-x>.small-10{width:calc(83.33333% - 1.25rem)}.grid-margin-x>.small-11{width:calc(91.66667% - 1.25rem)}.grid-margin-x>.small-12{width:calc(100% - 1.25rem)}@media print,screen and (min-width:40em){.grid-margin-x>.auto{width:auto}.grid-margin-x>.shrink{width:auto}.grid-margin-x>.small-1{width:calc(8.33333% - 1.875rem)}.grid-margin-x>.small-2{width:calc(16.66667% - 1.875rem)}.grid-margin-x>.small-3{width:calc(25% - 1.875rem)}.grid-margin-x>.small-4{width:calc(33.33333% - 1.875rem)}.grid-margin-x>.small-5{width:calc(41.66667% - 1.875rem)}.grid-margin-x>.small-6{width:calc(50% - 1.875rem)}.grid-margin-x>.small-7{width:calc(58.33333% - 1.875rem)}.grid-margin-x>.small-8{width:calc(66.66667% - 1.875rem)}.grid-margin-x>.small-9{width:calc(75% - 1.875rem)}.grid-margin-x>.small-10{width:calc(83.33333% - 1.875rem)}.grid-margin-x>.small-11{width:calc(91.66667% - 1.875rem)}.grid-margin-x>.small-12{width:calc(100% - 1.875rem)}.grid-margin-x>.medium-auto{width:auto}.grid-margin-x>.medium-shrink{width:auto}.grid-margin-x>.medium-1{width:calc(8.33333% - 1.875rem)}.grid-margin-x>.medium-2{width:calc(16.66667% - 1.875rem)}.grid-margin-x>.medium-3{width:calc(25% - 1.875rem)}.grid-margin-x>.medium-4{width:calc(33.33333% - 1.875rem)}.grid-margin-x>.medium-5{width:calc(41.66667% - 1.875rem)}.grid-margin-x>.medium-6{width:calc(50% - 1.875rem)}.grid-margin-x>.medium-7{width:calc(58.33333% - 1.875rem)}.grid-margin-x>.medium-8{width:calc(66.66667% - 1.875rem)}.grid-margin-x>.medium-9{width:calc(75% - 1.875rem)}.grid-margin-x>.medium-10{width:calc(83.33333% - 1.875rem)}.grid-margin-x>.medium-11{width:calc(91.66667% - 1.875rem)}.grid-margin-x>.medium-12{width:calc(100% - 1.875rem)}}@media print,screen and (min-width:64em){.grid-margin-x>.large-auto{width:auto}.grid-margin-x>.large-shrink{width:auto}.grid-margin-x>.large-1{width:calc(8.33333% - 1.875rem)}.grid-margin-x>.large-2{width:calc(16.66667% - 1.875rem)}.grid-margin-x>.large-3{width:calc(25% - 1.875rem)}.grid-margin-x>.large-4{width:calc(33.33333% - 1.875rem)}.grid-margin-x>.large-5{width:calc(41.66667% - 1.875rem)}.grid-margin-x>.large-6{width:calc(50% - 1.875rem)}.grid-margin-x>.large-7{width:calc(58.33333% - 1.875rem)}.grid-margin-x>.large-8{width:calc(66.66667% - 1.875rem)}.grid-margin-x>.large-9{width:calc(75% - 1.875rem)}.grid-margin-x>.large-10{width:calc(83.33333% - 1.875rem)}.grid-margin-x>.large-11{width:calc(91.66667% - 1.875rem)}.grid-margin-x>.large-12{width:calc(100% - 1.875rem)}}.grid-padding-x .grid-padding-x{margin-left:-.625rem;margin-right:-.625rem}@media print,screen and (min-width:40em){.grid-padding-x .grid-padding-x{margin-left:-.9375rem;margin-right:-.9375rem}}.grid-container:not(.full)>.grid-padding-x{margin-left:-.625rem;margin-right:-.625rem}@media print,screen and (min-width:40em){.grid-container:not(.full)>.grid-padding-x{margin-left:-.9375rem;margin-right:-.9375rem}}.grid-padding-x>.cell{padding-left:.625rem;padding-right:.625rem}@media print,screen and (min-width:40em){.grid-padding-x>.cell{padding-left:.9375rem;padding-right:.9375rem}}.small-up-1>.cell{width:100%}.small-up-2>.cell{width:50%}.small-up-3>.cell{width:33.33333%}.small-up-4>.cell{width:25%}.small-up-5>.cell{width:20%}.small-up-6>.cell{width:16.66667%}.small-up-7>.cell{width:14.28571%}.small-up-8>.cell{width:12.5%}@media print,screen and (min-width:40em){.medium-up-1>.cell{width:100%}.medium-up-2>.cell{width:50%}.medium-up-3>.cell{width:33.33333%}.medium-up-4>.cell{width:25%}.medium-up-5>.cell{width:20%}.medium-up-6>.cell{width:16.66667%}.medium-up-7>.cell{width:14.28571%}.medium-up-8>.cell{width:12.5%}}@media print,screen and (min-width:64em){.large-up-1>.cell{width:100%}.large-up-2>.cell{width:50%}.large-up-3>.cell{width:33.33333%}.large-up-4>.cell{width:25%}.large-up-5>.cell{width:20%}.large-up-6>.cell{width:16.66667%}.large-up-7>.cell{width:14.28571%}.large-up-8>.cell{width:12.5%}}.grid-margin-x.small-up-1>.cell{width:calc(100% - 1.25rem)}.grid-margin-x.small-up-2>.cell{width:calc(50% - 1.25rem)}.grid-margin-x.small-up-3>.cell{width:calc(33.33333% - 1.25rem)}.grid-margin-x.small-up-4>.cell{width:calc(25% - 1.25rem)}.grid-margin-x.small-up-5>.cell{width:calc(20% - 1.25rem)}.grid-margin-x.small-up-6>.cell{width:calc(16.66667% - 1.25rem)}.grid-margin-x.small-up-7>.cell{width:calc(14.28571% - 1.25rem)}.grid-margin-x.small-up-8>.cell{width:calc(12.5% - 1.25rem)}@media print,screen and (min-width:40em){.grid-margin-x.small-up-1>.cell{width:calc(100% - 1.875rem)}.grid-margin-x.small-up-2>.cell{width:calc(50% - 1.875rem)}.grid-margin-x.small-up-3>.cell{width:calc(33.33333% - 1.875rem)}.grid-margin-x.small-up-4>.cell{width:calc(25% - 1.875rem)}.grid-margin-x.small-up-5>.cell{width:calc(20% - 1.875rem)}.grid-margin-x.small-up-6>.cell{width:calc(16.66667% - 1.875rem)}.grid-margin-x.small-up-7>.cell{width:calc(14.28571% - 1.875rem)}.grid-margin-x.small-up-8>.cell{width:calc(12.5% - 1.875rem)}.grid-margin-x.medium-up-1>.cell{width:calc(100% - 1.875rem)}.grid-margin-x.medium-up-2>.cell{width:calc(50% - 1.875rem)}.grid-margin-x.medium-up-3>.cell{width:calc(33.33333% - 1.875rem)}.grid-margin-x.medium-up-4>.cell{width:calc(25% - 1.875rem)}.grid-margin-x.medium-up-5>.cell{width:calc(20% - 1.875rem)}.grid-margin-x.medium-up-6>.cell{width:calc(16.66667% - 1.875rem)}.grid-margin-x.medium-up-7>.cell{width:calc(14.28571% - 1.875rem)}.grid-margin-x.medium-up-8>.cell{width:calc(12.5% - 1.875rem)}}@media print,screen and (min-width:64em){.grid-margin-x.large-up-1>.cell{width:calc(100% - 1.875rem)}.grid-margin-x.large-up-2>.cell{width:calc(50% - 1.875rem)}.grid-margin-x.large-up-3>.cell{width:calc(33.33333% - 1.875rem)}.grid-margin-x.large-up-4>.cell{width:calc(25% - 1.875rem)}.grid-margin-x.large-up-5>.cell{width:calc(20% - 1.875rem)}.grid-margin-x.large-up-6>.cell{width:calc(16.66667% - 1.875rem)}.grid-margin-x.large-up-7>.cell{width:calc(14.28571% - 1.875rem)}.grid-margin-x.large-up-8>.cell{width:calc(12.5% - 1.875rem)}}.small-margin-collapse{margin-left:0;margin-right:0}.small-margin-collapse>.cell{margin-left:0;margin-right:0}.small-margin-collapse>.small-1{width:8.33333%}.small-margin-collapse>.small-2{width:16.66667%}.small-margin-collapse>.small-3{width:25%}.small-margin-collapse>.small-4{width:33.33333%}.small-margin-collapse>.small-5{width:41.66667%}.small-margin-collapse>.small-6{width:50%}.small-margin-collapse>.small-7{width:58.33333%}.small-margin-collapse>.small-8{width:66.66667%}.small-margin-collapse>.small-9{width:75%}.small-margin-collapse>.small-10{width:83.33333%}.small-margin-collapse>.small-11{width:91.66667%}.small-margin-collapse>.small-12{width:100%}@media print,screen and (min-width:40em){.small-margin-collapse>.medium-1{width:8.33333%}.small-margin-collapse>.medium-2{width:16.66667%}.small-margin-collapse>.medium-3{width:25%}.small-margin-collapse>.medium-4{width:33.33333%}.small-margin-collapse>.medium-5{width:41.66667%}.small-margin-collapse>.medium-6{width:50%}.small-margin-collapse>.medium-7{width:58.33333%}.small-margin-collapse>.medium-8{width:66.66667%}.small-margin-collapse>.medium-9{width:75%}.small-margin-collapse>.medium-10{width:83.33333%}.small-margin-collapse>.medium-11{width:91.66667%}.small-margin-collapse>.medium-12{width:100%}}@media print,screen and (min-width:64em){.small-margin-collapse>.large-1{width:8.33333%}.small-margin-collapse>.large-2{width:16.66667%}.small-margin-collapse>.large-3{width:25%}.small-margin-collapse>.large-4{width:33.33333%}.small-margin-collapse>.large-5{width:41.66667%}.small-margin-collapse>.large-6{width:50%}.small-margin-collapse>.large-7{width:58.33333%}.small-margin-collapse>.large-8{width:66.66667%}.small-margin-collapse>.large-9{width:75%}.small-margin-collapse>.large-10{width:83.33333%}.small-margin-collapse>.large-11{width:91.66667%}.small-margin-collapse>.large-12{width:100%}}.small-padding-collapse{margin-left:0;margin-right:0}.small-padding-collapse>.cell{padding-left:0;padding-right:0}@media print,screen and (min-width:40em){.medium-margin-collapse{margin-left:0;margin-right:0}.medium-margin-collapse>.cell{margin-left:0;margin-right:0}}@media print,screen and (min-width:40em){.medium-margin-collapse>.small-1{width:8.33333%}.medium-margin-collapse>.small-2{width:16.66667%}.medium-margin-collapse>.small-3{width:25%}.medium-margin-collapse>.small-4{width:33.33333%}.medium-margin-collapse>.small-5{width:41.66667%}.medium-margin-collapse>.small-6{width:50%}.medium-margin-collapse>.small-7{width:58.33333%}.medium-margin-collapse>.small-8{width:66.66667%}.medium-margin-collapse>.small-9{width:75%}.medium-margin-collapse>.small-10{width:83.33333%}.medium-margin-collapse>.small-11{width:91.66667%}.medium-margin-collapse>.small-12{width:100%}}@media print,screen and (min-width:40em){.medium-margin-collapse>.medium-1{width:8.33333%}.medium-margin-collapse>.medium-2{width:16.66667%}.medium-margin-collapse>.medium-3{width:25%}.medium-margin-collapse>.medium-4{width:33.33333%}.medium-margin-collapse>.medium-5{width:41.66667%}.medium-margin-collapse>.medium-6{width:50%}.medium-margin-collapse>.medium-7{width:58.33333%}.medium-margin-collapse>.medium-8{width:66.66667%}.medium-margin-collapse>.medium-9{width:75%}.medium-margin-collapse>.medium-10{width:83.33333%}.medium-margin-collapse>.medium-11{width:91.66667%}.medium-margin-collapse>.medium-12{width:100%}}@media print,screen and (min-width:64em){.medium-margin-collapse>.large-1{width:8.33333%}.medium-margin-collapse>.large-2{width:16.66667%}.medium-margin-collapse>.large-3{width:25%}.medium-margin-collapse>.large-4{width:33.33333%}.medium-margin-collapse>.large-5{width:41.66667%}.medium-margin-collapse>.large-6{width:50%}.medium-margin-collapse>.large-7{width:58.33333%}.medium-margin-collapse>.large-8{width:66.66667%}.medium-margin-collapse>.large-9{width:75%}.medium-margin-collapse>.large-10{width:83.33333%}.medium-margin-collapse>.large-11{width:91.66667%}.medium-margin-collapse>.large-12{width:100%}}@media print,screen and (min-width:40em){.medium-padding-collapse{margin-left:0;margin-right:0}.medium-padding-collapse>.cell{padding-left:0;padding-right:0}}@media print,screen and (min-width:64em){.large-margin-collapse{margin-left:0;margin-right:0}.large-margin-collapse>.cell{margin-left:0;margin-right:0}}@media print,screen and (min-width:64em){.large-margin-collapse>.small-1{width:8.33333%}.large-margin-collapse>.small-2{width:16.66667%}.large-margin-collapse>.small-3{width:25%}.large-margin-collapse>.small-4{width:33.33333%}.large-margin-collapse>.small-5{width:41.66667%}.large-margin-collapse>.small-6{width:50%}.large-margin-collapse>.small-7{width:58.33333%}.large-margin-collapse>.small-8{width:66.66667%}.large-margin-collapse>.small-9{width:75%}.large-margin-collapse>.small-10{width:83.33333%}.large-margin-collapse>.small-11{width:91.66667%}.large-margin-collapse>.small-12{width:100%}}@media print,screen and (min-width:64em){.large-margin-collapse>.medium-1{width:8.33333%}.large-margin-collapse>.medium-2{width:16.66667%}.large-margin-collapse>.medium-3{width:25%}.large-margin-collapse>.medium-4{width:33.33333%}.large-margin-collapse>.medium-5{width:41.66667%}.large-margin-collapse>.medium-6{width:50%}.large-margin-collapse>.medium-7{width:58.33333%}.large-margin-collapse>.medium-8{width:66.66667%}.large-margin-collapse>.medium-9{width:75%}.large-margin-collapse>.medium-10{width:83.33333%}.large-margin-collapse>.medium-11{width:91.66667%}.large-margin-collapse>.medium-12{width:100%}}@media print,screen and (min-width:64em){.large-margin-collapse>.large-1{width:8.33333%}.large-margin-collapse>.large-2{width:16.66667%}.large-margin-collapse>.large-3{width:25%}.large-margin-collapse>.large-4{width:33.33333%}.large-margin-collapse>.large-5{width:41.66667%}.large-margin-collapse>.large-6{width:50%}.large-margin-collapse>.large-7{width:58.33333%}.large-margin-collapse>.large-8{width:66.66667%}.large-margin-collapse>.large-9{width:75%}.large-margin-collapse>.large-10{width:83.33333%}.large-margin-collapse>.large-11{width:91.66667%}.large-margin-collapse>.large-12{width:100%}}@media print,screen and (min-width:64em){.large-padding-collapse{margin-left:0;margin-right:0}.large-padding-collapse>.cell{padding-left:0;padding-right:0}}.small-offset-0{margin-left:0}.grid-margin-x>.small-offset-0{margin-left:.625rem}.small-offset-1{margin-left:8.33333%}.grid-margin-x>.small-offset-1{margin-left:calc(8.33333% + .625rem)}.small-offset-2{margin-left:16.66667%}.grid-margin-x>.small-offset-2{margin-left:calc(16.66667% + .625rem)}.small-offset-3{margin-left:25%}.grid-margin-x>.small-offset-3{margin-left:calc(25% + .625rem)}.small-offset-4{margin-left:33.33333%}.grid-margin-x>.small-offset-4{margin-left:calc(33.33333% + .625rem)}.small-offset-5{margin-left:41.66667%}.grid-margin-x>.small-offset-5{margin-left:calc(41.66667% + .625rem)}.small-offset-6{margin-left:50%}.grid-margin-x>.small-offset-6{margin-left:calc(50% + .625rem)}.small-offset-7{margin-left:58.33333%}.grid-margin-x>.small-offset-7{margin-left:calc(58.33333% + .625rem)}.small-offset-8{margin-left:66.66667%}.grid-margin-x>.small-offset-8{margin-left:calc(66.66667% + .625rem)}.small-offset-9{margin-left:75%}.grid-margin-x>.small-offset-9{margin-left:calc(75% + .625rem)}.small-offset-10{margin-left:83.33333%}.grid-margin-x>.small-offset-10{margin-left:calc(83.33333% + .625rem)}.small-offset-11{margin-left:91.66667%}.grid-margin-x>.small-offset-11{margin-left:calc(91.66667% + .625rem)}@media print,screen and (min-width:40em){.medium-offset-0{margin-left:0}.grid-margin-x>.medium-offset-0{margin-left:.9375rem}.medium-offset-1{margin-left:8.33333%}.grid-margin-x>.medium-offset-1{margin-left:calc(8.33333% + .9375rem)}.medium-offset-2{margin-left:16.66667%}.grid-margin-x>.medium-offset-2{margin-left:calc(16.66667% + .9375rem)}.medium-offset-3{margin-left:25%}.grid-margin-x>.medium-offset-3{margin-left:calc(25% + .9375rem)}.medium-offset-4{margin-left:33.33333%}.grid-margin-x>.medium-offset-4{margin-left:calc(33.33333% + .9375rem)}.medium-offset-5{margin-left:41.66667%}.grid-margin-x>.medium-offset-5{margin-left:calc(41.66667% + .9375rem)}.medium-offset-6{margin-left:50%}.grid-margin-x>.medium-offset-6{margin-left:calc(50% + .9375rem)}.medium-offset-7{margin-left:58.33333%}.grid-margin-x>.medium-offset-7{margin-left:calc(58.33333% + .9375rem)}.medium-offset-8{margin-left:66.66667%}.grid-margin-x>.medium-offset-8{margin-left:calc(66.66667% + .9375rem)}.medium-offset-9{margin-left:75%}.grid-margin-x>.medium-offset-9{margin-left:calc(75% + .9375rem)}.medium-offset-10{margin-left:83.33333%}.grid-margin-x>.medium-offset-10{margin-left:calc(83.33333% + .9375rem)}.medium-offset-11{margin-left:91.66667%}.grid-margin-x>.medium-offset-11{margin-left:calc(91.66667% + .9375rem)}}@media print,screen and (min-width:64em){.large-offset-0{margin-left:0}.grid-margin-x>.large-offset-0{margin-left:.9375rem}.large-offset-1{margin-left:8.33333%}.grid-margin-x>.large-offset-1{margin-left:calc(8.33333% + .9375rem)}.large-offset-2{margin-left:16.66667%}.grid-margin-x>.large-offset-2{margin-left:calc(16.66667% + .9375rem)}.large-offset-3{margin-left:25%}.grid-margin-x>.large-offset-3{margin-left:calc(25% + .9375rem)}.large-offset-4{margin-left:33.33333%}.grid-margin-x>.large-offset-4{margin-left:calc(33.33333% + .9375rem)}.large-offset-5{margin-left:41.66667%}.grid-margin-x>.large-offset-5{margin-left:calc(41.66667% + .9375rem)}.large-offset-6{margin-left:50%}.grid-margin-x>.large-offset-6{margin-left:calc(50% + .9375rem)}.large-offset-7{margin-left:58.33333%}.grid-margin-x>.large-offset-7{margin-left:calc(58.33333% + .9375rem)}.large-offset-8{margin-left:66.66667%}.grid-margin-x>.large-offset-8{margin-left:calc(66.66667% + .9375rem)}.large-offset-9{margin-left:75%}.grid-margin-x>.large-offset-9{margin-left:calc(75% + .9375rem)}.large-offset-10{margin-left:83.33333%}.grid-margin-x>.large-offset-10{margin-left:calc(83.33333% + .9375rem)}.large-offset-11{margin-left:91.66667%}.grid-margin-x>.large-offset-11{margin-left:calc(91.66667% + .9375rem)}}.grid-y{-webkit-box-orient:vertical;-webkit-box-direction:normal;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-flow:column nowrap;-ms-flex-flow:column nowrap;flex-flow:column nowrap}.grid-y>.cell{height:auto;max-height:none}.grid-y>.auto{height:auto}.grid-y>.shrink{height:auto}.grid-y>.small-1,.grid-y>.small-2,.grid-y>.small-3,.grid-y>.small-4,.grid-y>.small-5,.grid-y>.small-6,.grid-y>.small-7,.grid-y>.small-8,.grid-y>.small-9,.grid-y>.small-10,.grid-y>.small-11,.grid-y>.small-12,.grid-y>.small-full,.grid-y>.small-shrink{-ms-flex-preferred-size:auto;-webkit-flex-basis:auto;flex-basis:auto}@media print,screen and (min-width:40em){.grid-y>.medium-1,.grid-y>.medium-2,.grid-y>.medium-3,.grid-y>.medium-4,.grid-y>.medium-5,.grid-y>.medium-6,.grid-y>.medium-7,.grid-y>.medium-8,.grid-y>.medium-9,.grid-y>.medium-10,.grid-y>.medium-11,.grid-y>.medium-12,.grid-y>.medium-full,.grid-y>.medium-shrink{-ms-flex-preferred-size:auto;-webkit-flex-basis:auto;flex-basis:auto}}@media print,screen and (min-width:64em){.grid-y>.large-1,.grid-y>.large-2,.grid-y>.large-3,.grid-y>.large-4,.grid-y>.large-5,.grid-y>.large-6,.grid-y>.large-7,.grid-y>.large-8,.grid-y>.large-9,.grid-y>.large-10,.grid-y>.large-11,.grid-y>.large-12,.grid-y>.large-full,.grid-y>.large-shrink{-ms-flex-preferred-size:auto;-webkit-flex-basis:auto;flex-basis:auto}}.grid-y>.small-1,.grid-y>.small-2,.grid-y>.small-3,.grid-y>.small-4,.grid-y>.small-5,.grid-y>.small-6,.grid-y>.small-7,.grid-y>.small-8,.grid-y>.small-9,.grid-y>.small-10,.grid-y>.small-11,.grid-y>.small-12{-webkit-box-flex:0;-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto}.grid-y>.small-1{height:8.33333%}.grid-y>.small-2{height:16.66667%}.grid-y>.small-3{height:25%}.grid-y>.small-4{height:33.33333%}.grid-y>.small-5{height:41.66667%}.grid-y>.small-6{height:50%}.grid-y>.small-7{height:58.33333%}.grid-y>.small-8{height:66.66667%}.grid-y>.small-9{height:75%}.grid-y>.small-10{height:83.33333%}.grid-y>.small-11{height:91.66667%}.grid-y>.small-12{height:100%}@media print,screen and (min-width:40em){.grid-y>.medium-auto{-webkit-box-flex:1;-webkit-flex:1 1 0;-ms-flex:1 1 0px;flex:1 1 0;height:auto}.grid-y>.medium-1,.grid-y>.medium-2,.grid-y>.medium-3,.grid-y>.medium-4,.grid-y>.medium-5,.grid-y>.medium-6,.grid-y>.medium-7,.grid-y>.medium-8,.grid-y>.medium-9,.grid-y>.medium-10,.grid-y>.medium-11,.grid-y>.medium-12,.grid-y>.medium-shrink{-webkit-box-flex:0;-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto}.grid-y>.medium-shrink{height:auto}.grid-y>.medium-1{height:8.33333%}.grid-y>.medium-2{height:16.66667%}.grid-y>.medium-3{height:25%}.grid-y>.medium-4{height:33.33333%}.grid-y>.medium-5{height:41.66667%}.grid-y>.medium-6{height:50%}.grid-y>.medium-7{height:58.33333%}.grid-y>.medium-8{height:66.66667%}.grid-y>.medium-9{height:75%}.grid-y>.medium-10{height:83.33333%}.grid-y>.medium-11{height:91.66667%}.grid-y>.medium-12{height:100%}}@media print,screen and (min-width:64em){.grid-y>.large-auto{-webkit-box-flex:1;-webkit-flex:1 1 0;-ms-flex:1 1 0px;flex:1 1 0;height:auto}.grid-y>.large-1,.grid-y>.large-2,.grid-y>.large-3,.grid-y>.large-4,.grid-y>.large-5,.grid-y>.large-6,.grid-y>.large-7,.grid-y>.large-8,.grid-y>.large-9,.grid-y>.large-10,.grid-y>.large-11,.grid-y>.large-12,.grid-y>.large-shrink{-webkit-box-flex:0;-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto}.grid-y>.large-shrink{height:auto}.grid-y>.large-1{height:8.33333%}.grid-y>.large-2{height:16.66667%}.grid-y>.large-3{height:25%}.grid-y>.large-4{height:33.33333%}.grid-y>.large-5{height:41.66667%}.grid-y>.large-6{height:50%}.grid-y>.large-7{height:58.33333%}.grid-y>.large-8{height:66.66667%}.grid-y>.large-9{height:75%}.grid-y>.large-10{height:83.33333%}.grid-y>.large-11{height:91.66667%}.grid-y>.large-12{height:100%}}.grid-padding-y .grid-padding-y{margin-bottom:-.625rem;margin-top:-.625rem}@media print,screen and (min-width:40em){.grid-padding-y .grid-padding-y{margin-bottom:-.9375rem;margin-top:-.9375rem}}.grid-padding-y>.cell{padding-bottom:.625rem;padding-top:.625rem}@media print,screen and (min-width:40em){.grid-padding-y>.cell{padding-bottom:.9375rem;padding-top:.9375rem}}.grid-frame{-webkit-box-align:stretch;-ms-flex-align:stretch;-webkit-align-items:stretch;align-items:stretch;-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap;overflow:hidden;position:relative;width:100vw}.cell .grid-frame{width:100%}.cell-block{max-width:100%;overflow-x:auto}.cell-block,.cell-block-y{-webkit-overflow-scrolling:touch;-ms-overflow-style:-ms-autohiding-scrollbar}.cell-block-y{max-height:100%;min-height:100%;overflow-y:auto}.cell-block-container{-webkit-box-orient:vertical;-webkit-box-direction:normal;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;max-height:100%}.cell-block-container>.grid-x{-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap;max-height:100%}@media print,screen and (min-width:40em){.medium-grid-frame{-webkit-box-align:stretch;-ms-flex-align:stretch;-webkit-align-items:stretch;align-items:stretch;-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap;overflow:hidden;position:relative;width:100vw}.cell .medium-grid-frame{width:100%}.medium-cell-block{-webkit-overflow-scrolling:touch;-ms-overflow-style:-ms-autohiding-scrollbar;max-width:100%;overflow-x:auto}.medium-cell-block-container{-webkit-box-orient:vertical;-webkit-box-direction:normal;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;max-height:100%}.medium-cell-block-container>.grid-x{-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap;max-height:100%}.medium-cell-block-y{-webkit-overflow-scrolling:touch;-ms-overflow-style:-ms-autohiding-scrollbar;max-height:100%;min-height:100%;overflow-y:auto}}@media print,screen and (min-width:64em){.large-grid-frame{-webkit-box-align:stretch;-ms-flex-align:stretch;-webkit-align-items:stretch;align-items:stretch;-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap;overflow:hidden;position:relative;width:100vw}.cell .large-grid-frame{width:100%}.large-cell-block{-webkit-overflow-scrolling:touch;-ms-overflow-style:-ms-autohiding-scrollbar;max-width:100%;overflow-x:auto}.large-cell-block-container{-webkit-box-orient:vertical;-webkit-box-direction:normal;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;max-height:100%}.large-cell-block-container>.grid-x{-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap;max-height:100%}.large-cell-block-y{-webkit-overflow-scrolling:touch;-ms-overflow-style:-ms-autohiding-scrollbar;max-height:100%;min-height:100%;overflow-y:auto}}.grid-y.grid-frame{-webkit-box-align:stretch;-ms-flex-align:stretch;-webkit-align-items:stretch;align-items:stretch;-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap;height:100vh;overflow:hidden;position:relative;width:auto}@media print,screen and (min-width:40em){.grid-y.medium-grid-frame{-webkit-box-align:stretch;-ms-flex-align:stretch;-webkit-align-items:stretch;align-items:stretch;-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap;height:100vh;overflow:hidden;position:relative;width:auto}}@media print,screen and (min-width:64em){.grid-y.large-grid-frame{-webkit-box-align:stretch;-ms-flex-align:stretch;-webkit-align-items:stretch;align-items:stretch;-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap;height:100vh;overflow:hidden;position:relative;width:auto}}.cell .grid-y.grid-frame{height:100%}@media print,screen and (min-width:40em){.cell .grid-y.medium-grid-frame{height:100%}}@media print,screen and (min-width:64em){.cell .grid-y.large-grid-frame{height:100%}}.grid-margin-y{margin-bottom:-.625rem;margin-top:-.625rem}@media print,screen and (min-width:40em){.grid-margin-y{margin-bottom:-.9375rem;margin-top:-.9375rem}}.grid-margin-y>.cell{height:calc(100% - 1.25rem);margin-bottom:.625rem;margin-top:.625rem}@media print,screen and (min-width:40em){.grid-margin-y>.cell{height:calc(100% - 1.875rem);margin-bottom:.9375rem;margin-top:.9375rem}}.grid-margin-y>.auto{height:auto}.grid-margin-y>.shrink{height:auto}.grid-margin-y>.small-1{height:calc(8.33333% - 1.25rem)}.grid-margin-y>.small-2{height:calc(16.66667% - 1.25rem)}.grid-margin-y>.small-3{height:calc(25% - 1.25rem)}.grid-margin-y>.small-4{height:calc(33.33333% - 1.25rem)}.grid-margin-y>.small-5{height:calc(41.66667% - 1.25rem)}.grid-margin-y>.small-6{height:calc(50% - 1.25rem)}.grid-margin-y>.small-7{height:calc(58.33333% - 1.25rem)}.grid-margin-y>.small-8{height:calc(66.66667% - 1.25rem)}.grid-margin-y>.small-9{height:calc(75% - 1.25rem)}.grid-margin-y>.small-10{height:calc(83.33333% - 1.25rem)}.grid-margin-y>.small-11{height:calc(91.66667% - 1.25rem)}.grid-margin-y>.small-12{height:calc(100% - 1.25rem)}@media print,screen and (min-width:40em){.grid-margin-y>.auto{height:auto}.grid-margin-y>.shrink{height:auto}.grid-margin-y>.small-1{height:calc(8.33333% - 1.875rem)}.grid-margin-y>.small-2{height:calc(16.66667% - 1.875rem)}.grid-margin-y>.small-3{height:calc(25% - 1.875rem)}.grid-margin-y>.small-4{height:calc(33.33333% - 1.875rem)}.grid-margin-y>.small-5{height:calc(41.66667% - 1.875rem)}.grid-margin-y>.small-6{height:calc(50% - 1.875rem)}.grid-margin-y>.small-7{height:calc(58.33333% - 1.875rem)}.grid-margin-y>.small-8{height:calc(66.66667% - 1.875rem)}.grid-margin-y>.small-9{height:calc(75% - 1.875rem)}.grid-margin-y>.small-10{height:calc(83.33333% - 1.875rem)}.grid-margin-y>.small-11{height:calc(91.66667% - 1.875rem)}.grid-margin-y>.small-12{height:calc(100% - 1.875rem)}.grid-margin-y>.medium-auto{height:auto}.grid-margin-y>.medium-shrink{height:auto}.grid-margin-y>.medium-1{height:calc(8.33333% - 1.875rem)}.grid-margin-y>.medium-2{height:calc(16.66667% - 1.875rem)}.grid-margin-y>.medium-3{height:calc(25% - 1.875rem)}.grid-margin-y>.medium-4{height:calc(33.33333% - 1.875rem)}.grid-margin-y>.medium-5{height:calc(41.66667% - 1.875rem)}.grid-margin-y>.medium-6{height:calc(50% - 1.875rem)}.grid-margin-y>.medium-7{height:calc(58.33333% - 1.875rem)}.grid-margin-y>.medium-8{height:calc(66.66667% - 1.875rem)}.grid-margin-y>.medium-9{height:calc(75% - 1.875rem)}.grid-margin-y>.medium-10{height:calc(83.33333% - 1.875rem)}.grid-margin-y>.medium-11{height:calc(91.66667% - 1.875rem)}.grid-margin-y>.medium-12{height:calc(100% - 1.875rem)}}@media print,screen and (min-width:64em){.grid-margin-y>.large-auto{height:auto}.grid-margin-y>.large-shrink{height:auto}.grid-margin-y>.large-1{height:calc(8.33333% - 1.875rem)}.grid-margin-y>.large-2{height:calc(16.66667% - 1.875rem)}.grid-margin-y>.large-3{height:calc(25% - 1.875rem)}.grid-margin-y>.large-4{height:calc(33.33333% - 1.875rem)}.grid-margin-y>.large-5{height:calc(41.66667% - 1.875rem)}.grid-margin-y>.large-6{height:calc(50% - 1.875rem)}.grid-margin-y>.large-7{height:calc(58.33333% - 1.875rem)}.grid-margin-y>.large-8{height:calc(66.66667% - 1.875rem)}.grid-margin-y>.large-9{height:calc(75% - 1.875rem)}.grid-margin-y>.large-10{height:calc(83.33333% - 1.875rem)}.grid-margin-y>.large-11{height:calc(91.66667% - 1.875rem)}.grid-margin-y>.large-12{height:calc(100% - 1.875rem)}}.grid-frame.grid-margin-y{height:calc(100vh + 1.25rem)}@media print,screen and (min-width:40em){.grid-frame.grid-margin-y{height:calc(100vh + 1.875rem)}}@media print,screen and (min-width:64em){.grid-frame.grid-margin-y{height:calc(100vh + 1.875rem)}}@media print,screen and (min-width:40em){.grid-margin-y.medium-grid-frame{height:calc(100vh + 1.875rem)}}@media print,screen and (min-width:64em){.grid-margin-y.large-grid-frame{height:calc(100vh + 1.875rem)}}.button{-webkit-appearance:none;border:1px solid transparent;border-radius:0;cursor:pointer;display:inline-block;font-family:inherit;font-size:.9rem;line-height:1;margin:0 0 1rem;padding:.85em 1em;text-align:center;-webkit-transition:background-color .25s ease-out,color .25s ease-out;transition:background-color .25s ease-out,color .25s ease-out;vertical-align:middle}[data-whatinput=mouse] .button{outline:0}.button.tiny{font-size:.6rem}.button.small{font-size:.75rem}.button.large{font-size:1.25rem}.button.expanded{display:block;margin-left:0;margin-right:0;width:100%}.button,.button.disabled,.button.disabled:focus,.button.disabled:hover,.button[disabled],.button[disabled]:focus,.button[disabled]:hover{background-color:#1779ba;color:#fefefe}.button:focus,.button:hover{background-color:#14679e;color:#fefefe}.button.primary,.button.primary.disabled,.button.primary.disabled:focus,.button.primary.disabled:hover,.button.primary[disabled],.button.primary[disabled]:focus,.button.primary[disabled]:hover{background-color:#1779ba;color:#fefefe}.button.primary:focus,.button.primary:hover{background-color:#126195;color:#fefefe}.button.secondary,.button.secondary.disabled,.button.secondary.disabled:focus,.button.secondary.disabled:hover,.button.secondary[disabled],.button.secondary[disabled]:focus,.button.secondary[disabled]:hover{background-color:#767676;color:#fefefe}.button.secondary:focus,.button.secondary:hover{background-color:#5e5e5e;color:#fefefe}.button.success,.button.success.disabled,.button.success.disabled:focus,.button.success.disabled:hover,.button.success[disabled],.button.success[disabled]:focus,.button.success[disabled]:hover{background-color:#3adb76;color:#0a0a0a}.button.success:focus,.button.success:hover{background-color:#22bb5b;color:#0a0a0a}.button.warning,.button.warning.disabled,.button.warning.disabled:focus,.button.warning.disabled:hover,.button.warning[disabled],.button.warning[disabled]:focus,.button.warning[disabled]:hover{background-color:#ffae00;color:#0a0a0a}.button.warning:focus,.button.warning:hover{background-color:#cc8b00;color:#0a0a0a}.button.alert,.button.alert.disabled,.button.alert.disabled:focus,.button.alert.disabled:hover,.button.alert[disabled],.button.alert[disabled]:focus,.button.alert[disabled]:hover{background-color:#cc4b37;color:#fefefe}.button.alert:focus,.button.alert:hover{background-color:#a53b2a;color:#fefefe}.button.hollow,.button.hollow.disabled,.button.hollow.disabled:focus,.button.hollow.disabled:hover,.button.hollow:focus,.button.hollow:hover,.button.hollow[disabled],.button.hollow[disabled]:focus,.button.hollow[disabled]:hover{background-color:transparent}.button.hollow,.button.hollow.disabled,.button.hollow.disabled:focus,.button.hollow.disabled:hover,.button.hollow[disabled],.button.hollow[disabled]:focus,.button.hollow[disabled]:hover{border:1px solid #1779ba;color:#1779ba}.button.hollow:focus,.button.hollow:hover{border-color:#0c3d5d;color:#0c3d5d}.button.hollow.primary,.button.hollow.primary.disabled,.button.hollow.primary.disabled:focus,.button.hollow.primary.disabled:hover,.button.hollow.primary[disabled],.button.hollow.primary[disabled]:focus,.button.hollow.primary[disabled]:hover{border:1px solid #1779ba;color:#1779ba}.button.hollow.primary:focus,.button.hollow.primary:hover{border-color:#0c3d5d;color:#0c3d5d}.button.hollow.secondary,.button.hollow.secondary.disabled,.button.hollow.secondary.disabled:focus,.button.hollow.secondary.disabled:hover,.button.hollow.secondary[disabled],.button.hollow.secondary[disabled]:focus,.button.hollow.secondary[disabled]:hover{border:1px solid #767676;color:#767676}.button.hollow.secondary:focus,.button.hollow.secondary:hover{border-color:#3b3b3b;color:#3b3b3b}.button.hollow.success,.button.hollow.success.disabled,.button.hollow.success.disabled:focus,.button.hollow.success.disabled:hover,.button.hollow.success[disabled],.button.hollow.success[disabled]:focus,.button.hollow.success[disabled]:hover{border:1px solid #3adb76;color:#3adb76}.button.hollow.success:focus,.button.hollow.success:hover{border-color:#157539;color:#157539}.button.hollow.warning,.button.hollow.warning.disabled,.button.hollow.warning.disabled:focus,.button.hollow.warning.disabled:hover,.button.hollow.warning[disabled],.button.hollow.warning[disabled]:focus,.button.hollow.warning[disabled]:hover{border:1px solid #ffae00;color:#ffae00}.button.hollow.warning:focus,.button.hollow.warning:hover{border-color:#805700;color:#805700}.button.hollow.alert,.button.hollow.alert.disabled,.button.hollow.alert.disabled:focus,.button.hollow.alert.disabled:hover,.button.hollow.alert[disabled],.button.hollow.alert[disabled]:focus,.button.hollow.alert[disabled]:hover{border:1px solid #cc4b37;color:#cc4b37}.button.hollow.alert:focus,.button.hollow.alert:hover{border-color:#67251a;color:#67251a}.button.clear,.button.clear.disabled,.button.clear.disabled:focus,.button.clear.disabled:hover,.button.clear:focus,.button.clear:hover,.button.clear[disabled],.button.clear[disabled]:focus,.button.clear[disabled]:hover{background-color:transparent;border-color:transparent}.button.clear,.button.clear.disabled,.button.clear.disabled:focus,.button.clear.disabled:hover,.button.clear[disabled],.button.clear[disabled]:focus,.button.clear[disabled]:hover{color:#1779ba}.button.clear:focus,.button.clear:hover{color:#0c3d5d}.button.clear.primary,.button.clear.primary.disabled,.button.clear.primary.disabled:focus,.button.clear.primary.disabled:hover,.button.clear.primary[disabled],.button.clear.primary[disabled]:focus,.button.clear.primary[disabled]:hover{color:#1779ba}.button.clear.primary:focus,.button.clear.primary:hover{color:#0c3d5d}.button.clear.secondary,.button.clear.secondary.disabled,.button.clear.secondary.disabled:focus,.button.clear.secondary.disabled:hover,.button.clear.secondary[disabled],.button.clear.secondary[disabled]:focus,.button.clear.secondary[disabled]:hover{color:#767676}.button.clear.secondary:focus,.button.clear.secondary:hover{color:#3b3b3b}.button.clear.success,.button.clear.success.disabled,.button.clear.success.disabled:focus,.button.clear.success.disabled:hover,.button.clear.success[disabled],.button.clear.success[disabled]:focus,.button.clear.success[disabled]:hover{color:#3adb76}.button.clear.success:focus,.button.clear.success:hover{color:#157539}.button.clear.warning,.button.clear.warning.disabled,.button.clear.warning.disabled:focus,.button.clear.warning.disabled:hover,.button.clear.warning[disabled],.button.clear.warning[disabled]:focus,.button.clear.warning[disabled]:hover{color:#ffae00}.button.clear.warning:focus,.button.clear.warning:hover{color:#805700}.button.clear.alert,.button.clear.alert.disabled,.button.clear.alert.disabled:focus,.button.clear.alert.disabled:hover,.button.clear.alert[disabled],.button.clear.alert[disabled]:focus,.button.clear.alert[disabled]:hover{color:#cc4b37}.button.clear.alert:focus,.button.clear.alert:hover{color:#67251a}.button.disabled,.button[disabled]{cursor:not-allowed;opacity:.25}.button.dropdown:after{border-color:#fefefe transparent transparent;border-style:solid;border-width:.4em .4em 0;content:"";display:block;display:inline-block;float:right;height:0;margin-left:1em;position:relative;top:.4em;width:0}.button.dropdown.clear:after,.button.dropdown.hollow:after{border-top-color:#1779ba}.button.dropdown.clear.primary:after,.button.dropdown.hollow.primary:after{border-top-color:#1779ba}.button.dropdown.clear.secondary:after,.button.dropdown.hollow.secondary:after{border-top-color:#767676}.button.dropdown.clear.success:after,.button.dropdown.hollow.success:after{border-top-color:#3adb76}.button.dropdown.clear.warning:after,.button.dropdown.hollow.warning:after{border-top-color:#ffae00}.button.dropdown.clear.alert:after,.button.dropdown.hollow.alert:after{border-top-color:#cc4b37}.button.arrow-only:after{float:none;margin-left:0;top:-.1em}a.button:focus,a.button:hover{text-decoration:none}.button-group{-webkit-box-align:stretch;-ms-flex-align:stretch;-webkit-box-flex:1;-ms-flex-positive:1;-webkit-align-items:stretch;align-items:stretch;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-grow:1;flex-grow:1;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;margin-bottom:1rem}.button-group:after,.button-group:before{-ms-flex-preferred-size:0;-webkit-box-ordinal-group:2;-ms-flex-order:1;content:" ";display:table;-webkit-flex-basis:0;flex-basis:0;-webkit-order:1;order:1}.button-group:after{clear:both}.button-group:after,.button-group:before{display:none}.button-group .button{-webkit-box-flex:0;-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto;font-size:.9rem;margin:0 1px 1px 0}.button-group .button:last-child{margin-right:0}.button-group.tiny .button{font-size:.6rem}.button-group.small .button{font-size:.75rem}.button-group.large .button{font-size:1.25rem}.button-group.expanded .button{-webkit-box-flex:1;-webkit-flex:1 1 0px;-ms-flex:1 1 0px;flex:1 1 0px}.button-group.primary .button,.button-group.primary .button.disabled,.button-group.primary .button.disabled:focus,.button-group.primary .button.disabled:hover,.button-group.primary .button[disabled],.button-group.primary .button[disabled]:focus,.button-group.primary .button[disabled]:hover{background-color:#1779ba;color:#fefefe}.button-group.primary .button:focus,.button-group.primary .button:hover{background-color:#126195;color:#fefefe}.button-group.secondary .button,.button-group.secondary .button.disabled,.button-group.secondary .button.disabled:focus,.button-group.secondary .button.disabled:hover,.button-group.secondary .button[disabled],.button-group.secondary .button[disabled]:focus,.button-group.secondary .button[disabled]:hover{background-color:#767676;color:#fefefe}.button-group.secondary .button:focus,.button-group.secondary .button:hover{background-color:#5e5e5e;color:#fefefe}.button-group.success .button,.button-group.success .button.disabled,.button-group.success .button.disabled:focus,.button-group.success .button.disabled:hover,.button-group.success .button[disabled],.button-group.success .button[disabled]:focus,.button-group.success .button[disabled]:hover{background-color:#3adb76;color:#0a0a0a}.button-group.success .button:focus,.button-group.success .button:hover{background-color:#22bb5b;color:#0a0a0a}.button-group.warning .button,.button-group.warning .button.disabled,.button-group.warning .button.disabled:focus,.button-group.warning .button.disabled:hover,.button-group.warning .button[disabled],.button-group.warning .button[disabled]:focus,.button-group.warning .button[disabled]:hover{background-color:#ffae00;color:#0a0a0a}.button-group.warning .button:focus,.button-group.warning .button:hover{background-color:#cc8b00;color:#0a0a0a}.button-group.alert .button,.button-group.alert .button.disabled,.button-group.alert .button.disabled:focus,.button-group.alert .button.disabled:hover,.button-group.alert .button[disabled],.button-group.alert .button[disabled]:focus,.button-group.alert .button[disabled]:hover{background-color:#cc4b37;color:#fefefe}.button-group.alert .button:focus,.button-group.alert .button:hover{background-color:#a53b2a;color:#fefefe}.button-group.hollow .button,.button-group.hollow .button.disabled,.button-group.hollow .button.disabled:focus,.button-group.hollow .button.disabled:hover,.button-group.hollow .button:focus,.button-group.hollow .button:hover,.button-group.hollow .button[disabled],.button-group.hollow .button[disabled]:focus,.button-group.hollow .button[disabled]:hover{background-color:transparent}.button-group.hollow .button,.button-group.hollow .button.disabled,.button-group.hollow .button.disabled:focus,.button-group.hollow .button.disabled:hover,.button-group.hollow .button[disabled],.button-group.hollow .button[disabled]:focus,.button-group.hollow .button[disabled]:hover{border:1px solid #1779ba;color:#1779ba}.button-group.hollow .button:focus,.button-group.hollow .button:hover{border-color:#0c3d5d;color:#0c3d5d}.button-group.hollow .button.primary,.button-group.hollow .button.primary.disabled,.button-group.hollow .button.primary.disabled:focus,.button-group.hollow .button.primary.disabled:hover,.button-group.hollow .button.primary[disabled],.button-group.hollow .button.primary[disabled]:focus,.button-group.hollow .button.primary[disabled]:hover,.button-group.hollow.primary .button,.button-group.hollow.primary .button.disabled,.button-group.hollow.primary .button.disabled:focus,.button-group.hollow.primary .button.disabled:hover,.button-group.hollow.primary .button[disabled],.button-group.hollow.primary .button[disabled]:focus,.button-group.hollow.primary .button[disabled]:hover{border:1px solid #1779ba;color:#1779ba}.button-group.hollow .button.primary:focus,.button-group.hollow .button.primary:hover,.button-group.hollow.primary .button:focus,.button-group.hollow.primary .button:hover{border-color:#0c3d5d;color:#0c3d5d}.button-group.hollow .button.secondary,.button-group.hollow .button.secondary.disabled,.button-group.hollow .button.secondary.disabled:focus,.button-group.hollow .button.secondary.disabled:hover,.button-group.hollow .button.secondary[disabled],.button-group.hollow .button.secondary[disabled]:focus,.button-group.hollow .button.secondary[disabled]:hover,.button-group.hollow.secondary .button,.button-group.hollow.secondary .button.disabled,.button-group.hollow.secondary .button.disabled:focus,.button-group.hollow.secondary .button.disabled:hover,.button-group.hollow.secondary .button[disabled],.button-group.hollow.secondary .button[disabled]:focus,.button-group.hollow.secondary .button[disabled]:hover{border:1px solid #767676;color:#767676}.button-group.hollow .button.secondary:focus,.button-group.hollow .button.secondary:hover,.button-group.hollow.secondary .button:focus,.button-group.hollow.secondary .button:hover{border-color:#3b3b3b;color:#3b3b3b}.button-group.hollow .button.success,.button-group.hollow .button.success.disabled,.button-group.hollow .button.success.disabled:focus,.button-group.hollow .button.success.disabled:hover,.button-group.hollow .button.success[disabled],.button-group.hollow .button.success[disabled]:focus,.button-group.hollow .button.success[disabled]:hover,.button-group.hollow.success .button,.button-group.hollow.success .button.disabled,.button-group.hollow.success .button.disabled:focus,.button-group.hollow.success .button.disabled:hover,.button-group.hollow.success .button[disabled],.button-group.hollow.success .button[disabled]:focus,.button-group.hollow.success .button[disabled]:hover{border:1px solid #3adb76;color:#3adb76}.button-group.hollow .button.success:focus,.button-group.hollow .button.success:hover,.button-group.hollow.success .button:focus,.button-group.hollow.success .button:hover{border-color:#157539;color:#157539}.button-group.hollow .button.warning,.button-group.hollow .button.warning.disabled,.button-group.hollow .button.warning.disabled:focus,.button-group.hollow .button.warning.disabled:hover,.button-group.hollow .button.warning[disabled],.button-group.hollow .button.warning[disabled]:focus,.button-group.hollow .button.warning[disabled]:hover,.button-group.hollow.warning .button,.button-group.hollow.warning .button.disabled,.button-group.hollow.warning .button.disabled:focus,.button-group.hollow.warning .button.disabled:hover,.button-group.hollow.warning .button[disabled],.button-group.hollow.warning .button[disabled]:focus,.button-group.hollow.warning .button[disabled]:hover{border:1px solid #ffae00;color:#ffae00}.button-group.hollow .button.warning:focus,.button-group.hollow .button.warning:hover,.button-group.hollow.warning .button:focus,.button-group.hollow.warning .button:hover{border-color:#805700;color:#805700}.button-group.hollow.alert .button,.button-group.hollow.alert .button.disabled,.button-group.hollow.alert .button.disabled:focus,.button-group.hollow.alert .button.disabled:hover,.button-group.hollow.alert .button[disabled],.button-group.hollow.alert .button[disabled]:focus,.button-group.hollow.alert .button[disabled]:hover,.button-group.hollow .button.alert,.button-group.hollow .button.alert.disabled,.button-group.hollow .button.alert.disabled:focus,.button-group.hollow .button.alert.disabled:hover,.button-group.hollow .button.alert[disabled],.button-group.hollow .button.alert[disabled]:focus,.button-group.hollow .button.alert[disabled]:hover{border:1px solid #cc4b37;color:#cc4b37}.button-group.hollow.alert .button:focus,.button-group.hollow.alert .button:hover,.button-group.hollow .button.alert:focus,.button-group.hollow .button.alert:hover{border-color:#67251a;color:#67251a}.button-group.clear .button,.button-group.clear .button.disabled,.button-group.clear .button.disabled:focus,.button-group.clear .button.disabled:hover,.button-group.clear .button:focus,.button-group.clear .button:hover,.button-group.clear .button[disabled],.button-group.clear .button[disabled]:focus,.button-group.clear .button[disabled]:hover{background-color:transparent;border-color:transparent}.button-group.clear .button,.button-group.clear .button.disabled,.button-group.clear .button.disabled:focus,.button-group.clear .button.disabled:hover,.button-group.clear .button[disabled],.button-group.clear .button[disabled]:focus,.button-group.clear .button[disabled]:hover{color:#1779ba}.button-group.clear .button:focus,.button-group.clear .button:hover{color:#0c3d5d}.button-group.clear .button.primary,.button-group.clear .button.primary.disabled,.button-group.clear .button.primary.disabled:focus,.button-group.clear .button.primary.disabled:hover,.button-group.clear .button.primary[disabled],.button-group.clear .button.primary[disabled]:focus,.button-group.clear .button.primary[disabled]:hover,.button-group.clear.primary .button,.button-group.clear.primary .button.disabled,.button-group.clear.primary .button.disabled:focus,.button-group.clear.primary .button.disabled:hover,.button-group.clear.primary .button[disabled],.button-group.clear.primary .button[disabled]:focus,.button-group.clear.primary .button[disabled]:hover{color:#1779ba}.button-group.clear .button.primary:focus,.button-group.clear .button.primary:hover,.button-group.clear.primary .button:focus,.button-group.clear.primary .button:hover{color:#0c3d5d}.button-group.clear .button.secondary,.button-group.clear .button.secondary.disabled,.button-group.clear .button.secondary.disabled:focus,.button-group.clear .button.secondary.disabled:hover,.button-group.clear .button.secondary[disabled],.button-group.clear .button.secondary[disabled]:focus,.button-group.clear .button.secondary[disabled]:hover,.button-group.clear.secondary .button,.button-group.clear.secondary .button.disabled,.button-group.clear.secondary .button.disabled:focus,.button-group.clear.secondary .button.disabled:hover,.button-group.clear.secondary .button[disabled],.button-group.clear.secondary .button[disabled]:focus,.button-group.clear.secondary .button[disabled]:hover{color:#767676}.button-group.clear .button.secondary:focus,.button-group.clear .button.secondary:hover,.button-group.clear.secondary .button:focus,.button-group.clear.secondary .button:hover{color:#3b3b3b}.button-group.clear .button.success,.button-group.clear .button.success.disabled,.button-group.clear .button.success.disabled:focus,.button-group.clear .button.success.disabled:hover,.button-group.clear .button.success[disabled],.button-group.clear .button.success[disabled]:focus,.button-group.clear .button.success[disabled]:hover,.button-group.clear.success .button,.button-group.clear.success .button.disabled,.button-group.clear.success .button.disabled:focus,.button-group.clear.success .button.disabled:hover,.button-group.clear.success .button[disabled],.button-group.clear.success .button[disabled]:focus,.button-group.clear.success .button[disabled]:hover{color:#3adb76}.button-group.clear .button.success:focus,.button-group.clear .button.success:hover,.button-group.clear.success .button:focus,.button-group.clear.success .button:hover{color:#157539}.button-group.clear .button.warning,.button-group.clear .button.warning.disabled,.button-group.clear .button.warning.disabled:focus,.button-group.clear .button.warning.disabled:hover,.button-group.clear .button.warning[disabled],.button-group.clear .button.warning[disabled]:focus,.button-group.clear .button.warning[disabled]:hover,.button-group.clear.warning .button,.button-group.clear.warning .button.disabled,.button-group.clear.warning .button.disabled:focus,.button-group.clear.warning .button.disabled:hover,.button-group.clear.warning .button[disabled],.button-group.clear.warning .button[disabled]:focus,.button-group.clear.warning .button[disabled]:hover{color:#ffae00}.button-group.clear .button.warning:focus,.button-group.clear .button.warning:hover,.button-group.clear.warning .button:focus,.button-group.clear.warning .button:hover{color:#805700}.button-group.clear.alert .button,.button-group.clear.alert .button.disabled,.button-group.clear.alert .button.disabled:focus,.button-group.clear.alert .button.disabled:hover,.button-group.clear.alert .button[disabled],.button-group.clear.alert .button[disabled]:focus,.button-group.clear.alert .button[disabled]:hover,.button-group.clear .button.alert,.button-group.clear .button.alert.disabled,.button-group.clear .button.alert.disabled:focus,.button-group.clear .button.alert.disabled:hover,.button-group.clear .button.alert[disabled],.button-group.clear .button.alert[disabled]:focus,.button-group.clear .button.alert[disabled]:hover{color:#cc4b37}.button-group.clear.alert .button:focus,.button-group.clear.alert .button:hover,.button-group.clear .button.alert:focus,.button-group.clear .button.alert:hover{color:#67251a}.button-group.no-gaps .button{margin-right:-.0625rem}.button-group.no-gaps .button+.button{border-left-color:transparent}.button-group.stacked,.button-group.stacked-for-medium,.button-group.stacked-for-small{-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap}.button-group.stacked-for-medium .button,.button-group.stacked-for-small .button,.button-group.stacked .button{-webkit-box-flex:0;-webkit-flex:0 0 100%;-ms-flex:0 0 100%;flex:0 0 100%}.button-group.stacked-for-medium .button:last-child,.button-group.stacked-for-small .button:last-child,.button-group.stacked .button:last-child{margin-bottom:0}.button-group.stacked-for-medium.expanded .button,.button-group.stacked-for-small.expanded .button,.button-group.stacked.expanded .button{-webkit-box-flex:1;-webkit-flex:1 1 0px;-ms-flex:1 1 0px;flex:1 1 0px}@media print,screen and (min-width:40em){.button-group.stacked-for-small .button{-webkit-box-flex:0;-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto;margin-bottom:0}}@media print,screen and (min-width:64em){.button-group.stacked-for-medium .button{-webkit-box-flex:0;-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto;margin-bottom:0}}@media print,screen and (max-width:39.99875em){.button-group.stacked-for-small.expanded{display:block}.button-group.stacked-for-small.expanded .button{display:block;margin-right:0}}@media print,screen and (max-width:63.99875em){.button-group.stacked-for-medium.expanded{display:block}.button-group.stacked-for-medium.expanded .button{display:block;margin-right:0}}.close-button{color:#8a8a8a;cursor:pointer;position:absolute;z-index:10}[data-whatinput=mouse] .close-button{outline:0}.close-button:focus,.close-button:hover{color:#0a0a0a}.close-button.small{font-size:1.5em;line-height:1;right:.66rem;top:.33em}.close-button,.close-button.medium{font-size:2em;line-height:1;right:1rem;top:.5rem}.label{border-radius:0;cursor:default;display:inline-block;font-size:.8rem;line-height:1;padding:.33333rem .5rem;white-space:nowrap}.label,.label.primary{background:#1779ba;color:#fefefe}.label.secondary{background:#767676;color:#fefefe}.label.success{background:#3adb76;color:#0a0a0a}.label.warning{background:#ffae00;color:#0a0a0a}.label.alert{background:#cc4b37;color:#fefefe}.progress{background-color:#cacaca;border-radius:0;height:1rem;margin-bottom:1rem}.progress.primary .progress-meter{background-color:#1779ba}.progress.secondary .progress-meter{background-color:#767676}.progress.success .progress-meter{background-color:#3adb76}.progress.warning .progress-meter{background-color:#ffae00}.progress.alert .progress-meter{background-color:#cc4b37}.progress-meter{background-color:#1779ba;display:block;height:100%;position:relative;width:0}.progress-meter-text{color:#fefefe;font-size:.75rem;font-weight:700;left:50%;margin:0;position:absolute;top:50%;-webkit-transform:translate(-50%,-50%);-ms-transform:translate(-50%,-50%);transform:translate(-50%,-50%);white-space:nowrap}.slider{background-color:#e6e6e6;cursor:pointer;height:.5rem;margin-bottom:2.25rem;margin-top:1.25rem;position:relative;-ms-touch-action:none;touch-action:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.slider-fill{background-color:#cacaca;display:inline-block;height:.5rem;left:0;max-width:100%;position:absolute;top:0;-webkit-transition:all .2s ease-in-out;transition:all .2s ease-in-out}.slider-fill.is-dragging{-webkit-transition:all 0s linear;transition:all 0s linear}.slider-handle{background-color:#1779ba;border-radius:0;cursor:-webkit-grab;cursor:grab;display:inline-block;height:1.4rem;left:0;position:absolute;top:50%;-ms-touch-action:manipulation;touch-action:manipulation;-webkit-transform:translateY(-50%);-ms-transform:translateY(-50%);transform:translateY(-50%);-webkit-transition:all .2s ease-in-out;transition:all .2s ease-in-out;width:1.4rem;z-index:1}[data-whatinput=mouse] .slider-handle{outline:0}.slider-handle:hover{background-color:#14679e}.slider-handle.is-dragging{cursor:-webkit-grabbing;cursor:grabbing;-webkit-transition:all 0s linear;transition:all 0s linear}.slider.disabled,.slider[disabled]{cursor:not-allowed;opacity:.25}.slider.vertical{display:inline-block;height:12.5rem;margin:0 1.25rem;-webkit-transform:scaleY(-1);-ms-transform:scaleY(-1);transform:scaleY(-1);width:.5rem}.slider.vertical .slider-fill{max-height:100%;top:0;width:.5rem}.slider.vertical .slider-handle{height:1.4rem;left:50%;position:absolute;top:0;-webkit-transform:translateX(-50%);-ms-transform:translateX(-50%);transform:translateX(-50%);width:1.4rem}.switch{color:#fefefe;font-size:.875rem;font-weight:700;height:2rem;margin-bottom:1rem;outline:0;position:relative;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.switch-input{margin-bottom:0;opacity:0;position:absolute}.switch-paddle{background:#cacaca;border-radius:0;color:inherit;cursor:pointer;display:block;font-weight:inherit;height:2rem;position:relative;-webkit-transition:all .25s ease-out;transition:all .25s ease-out;width:4rem}input+.switch-paddle{margin:0}.switch-paddle:after{background:#fefefe;border-radius:0;content:"";display:block;height:1.5rem;left:.25rem;position:absolute;top:.25rem;-webkit-transform:translateZ(0);transform:translateZ(0);-webkit-transition:all .25s ease-out;transition:all .25s ease-out;width:1.5rem}input:checked~.switch-paddle{background:#1779ba}input:checked~.switch-paddle:after{left:2.25rem}input:disabled~.switch-paddle{cursor:not-allowed;opacity:.5}[data-whatinput=mouse] input:focus~.switch-paddle{outline:0}.switch-active,.switch-inactive{position:absolute;top:50%;-webkit-transform:translateY(-50%);-ms-transform:translateY(-50%);transform:translateY(-50%)}.switch-active{display:none;left:8%}input:checked+label>.switch-active{display:block}.switch-inactive{right:15%}input:checked+label>.switch-inactive{display:none}.switch.tiny{height:1.5rem}.switch.tiny .switch-paddle{font-size:.625rem;height:1.5rem;width:3rem}.switch.tiny .switch-paddle:after{height:1rem;left:.25rem;top:.25rem;width:1rem}.switch.tiny input:checked~.switch-paddle:after{left:1.75rem}.switch.small{height:1.75rem}.switch.small .switch-paddle{font-size:.75rem;height:1.75rem;width:3.5rem}.switch.small .switch-paddle:after{height:1.25rem;left:.25rem;top:.25rem;width:1.25rem}.switch.small input:checked~.switch-paddle:after{left:2rem}.switch.large{height:2.5rem}.switch.large .switch-paddle{font-size:1rem;height:2.5rem;width:5rem}.switch.large .switch-paddle:after{height:2rem;left:.25rem;top:.25rem;width:2rem}.switch.large input:checked~.switch-paddle:after{left:2.75rem}table{border-collapse:collapse;border-radius:0;margin-bottom:1rem;width:100%}tbody,tfoot,thead{background-color:#fefefe;border:1px solid #f1f1f1}caption{font-weight:700;padding:.5rem .625rem .625rem}thead{background:#f8f8f8}tfoot,thead{color:#0a0a0a}tfoot{background:#f1f1f1}tfoot tr,thead tr{background:0 0}tfoot td,tfoot th,thead td,thead th{font-weight:700;padding:.5rem .625rem .625rem;text-align:left}tbody td,tbody th{padding:.5rem .625rem .625rem}tbody tr:nth-child(2n){background-color:#f1f1f1;border-bottom:0}table.unstriped tbody{background-color:#fefefe}table.unstriped tbody tr{background-color:#fefefe;border-bottom:1px solid #f1f1f1}@media print,screen and (max-width:63.99875em){table.stack tfoot,table.stack thead{display:none}table.stack td,table.stack th,table.stack tr{display:block}table.stack td{border-top:0}}table.scroll{display:block;overflow-x:auto;width:100%}table.hover thead tr:hover{background-color:#f3f3f3}table.hover tfoot tr:hover{background-color:#ececec}table.hover tbody tr:hover{background-color:#f9f9f9}table.hover:not(.unstriped) tr:nth-of-type(2n):hover{background-color:#ececec}.table-scroll{overflow-x:auto}.badge{border-radius:50%;display:inline-block;font-size:.6rem;min-width:2.1em;padding:.3em;text-align:center}.badge,.badge.primary{background:#1779ba;color:#fefefe}.badge.secondary{background:#767676;color:#fefefe}.badge.success{background:#3adb76;color:#0a0a0a}.badge.warning{background:#ffae00;color:#0a0a0a}.badge.alert{background:#cc4b37;color:#fefefe}.breadcrumbs{list-style:none;margin:0 0 1rem}.breadcrumbs:after,.breadcrumbs:before{-ms-flex-preferred-size:0;-webkit-box-ordinal-group:2;-ms-flex-order:1;content:" ";display:table;-webkit-flex-basis:0;flex-basis:0;-webkit-order:1;order:1}.breadcrumbs:after{clear:both}.breadcrumbs li{color:#0a0a0a;cursor:default;float:left;font-size:.6875rem;text-transform:uppercase}.breadcrumbs li:not(:last-child):after{color:#cacaca;content:"/";margin:0 .75rem;opacity:1;position:relative}.breadcrumbs a{color:#1779ba}.breadcrumbs a:hover{text-decoration:underline}.breadcrumbs .disabled{color:#cacaca;cursor:not-allowed}.callout{background-color:#fff;border:1px solid hsla(0,0%,4%,.25);border-radius:0;color:#0a0a0a;margin:0 0 1rem;padding:1rem;position:relative}.callout>:first-child{margin-top:0}.callout>:last-child{margin-bottom:0}.callout.primary{background-color:#d7ecfa;color:#0a0a0a}.callout.secondary{background-color:#eaeaea;color:#0a0a0a}.callout.success{background-color:#e1faea;color:#0a0a0a}.callout.warning{background-color:#fff3d9;color:#0a0a0a}.callout.alert{background-color:#f7e4e1;color:#0a0a0a}.callout.small{padding:.5rem}.callout.large{padding:3rem}.card{-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-box-flex:1;-ms-flex-positive:1;background:#fefefe;border:1px solid #e6e6e6;border-radius:0;-webkit-box-shadow:none;box-shadow:none;color:#0a0a0a;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;-webkit-flex-grow:1;flex-grow:1;margin-bottom:1rem;overflow:hidden}.card>:last-child{margin-bottom:0}.card-divider{-webkit-box-flex:0;background:#e6e6e6;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex:0 1 auto;-ms-flex:0 1 auto;flex:0 1 auto;padding:1rem}.card-divider>:last-child{margin-bottom:0}.card-section{-webkit-box-flex:1;-webkit-flex:1 0 auto;-ms-flex:1 0 auto;flex:1 0 auto;padding:1rem}.card-section>:last-child{margin-bottom:0}.card-image{min-height:1px}.dropdown-pane{background-color:#fefefe;border:1px solid #cacaca;border-radius:0;display:none;font-size:1rem;padding:1rem;position:absolute;visibility:hidden;width:300px;z-index:10}.dropdown-pane.is-opening{display:block}.dropdown-pane.is-open{display:block;visibility:visible}.dropdown-pane.tiny{width:100px}.dropdown-pane.small{width:200px}.dropdown-pane.large{width:400px}.pagination{margin-bottom:1rem;margin-left:0}.pagination:after,.pagination:before{-ms-flex-preferred-size:0;-webkit-box-ordinal-group:2;-ms-flex-order:1;content:" ";display:table;-webkit-flex-basis:0;flex-basis:0;-webkit-order:1;order:1}.pagination:after{clear:both}.pagination li{border-radius:0;display:none;font-size:.875rem;margin-right:.0625rem}.pagination li:first-child,.pagination li:last-child{display:inline-block}@media print,screen and (min-width:40em){.pagination li{display:inline-block}}.pagination a,.pagination button{border-radius:0;color:#0a0a0a;display:block;padding:.1875rem .625rem}.pagination a:hover,.pagination button:hover{background:#e6e6e6}.pagination .current{background:#1779ba;color:#fefefe;cursor:default;padding:.1875rem .625rem}.pagination .disabled{color:#cacaca;cursor:not-allowed;padding:.1875rem .625rem}.pagination .disabled:hover{background:0 0}.pagination .ellipsis:after{color:#0a0a0a;content:"…";padding:.1875rem .625rem}.pagination-previous.disabled:before,.pagination-previous a:before{content:"«";display:inline-block;margin-right:.5rem}.pagination-next.disabled:after,.pagination-next a:after{content:"»";display:inline-block;margin-left:.5rem}.has-tip{border-bottom:1px dotted #8a8a8a;cursor:help;display:inline-block;font-weight:700;position:relative}.tooltip{background-color:#0a0a0a;border-radius:0;color:#fefefe;font-size:80%;max-width:10rem;padding:.75rem;position:absolute;top:calc(100% + .6495rem);z-index:1200}.tooltip:before{position:absolute}.tooltip.bottom:before{border-color:transparent transparent #0a0a0a;border-style:solid;border-width:0 .75rem .75rem;bottom:100%;content:"";display:block;height:0;width:0}.tooltip.bottom.align-center:before{left:50%;-webkit-transform:translateX(-50%);-ms-transform:translateX(-50%);transform:translateX(-50%)}.tooltip.top:before{border-color:#0a0a0a transparent transparent;border-style:solid;border-width:.75rem .75rem 0;bottom:auto;content:"";display:block;height:0;top:100%;width:0}.tooltip.top.align-center:before{left:50%;-webkit-transform:translateX(-50%);-ms-transform:translateX(-50%);transform:translateX(-50%)}.tooltip.left:before{border-color:transparent transparent transparent #0a0a0a;border-style:solid;border-width:.75rem 0 .75rem .75rem;content:"";display:block;height:0;left:100%;width:0}.tooltip.left.align-center:before{bottom:auto;top:50%;-webkit-transform:translateY(-50%);-ms-transform:translateY(-50%);transform:translateY(-50%)}.tooltip.right:before{border-color:transparent #0a0a0a transparent transparent;border-style:solid;border-width:.75rem .75rem .75rem 0;content:"";display:block;height:0;left:auto;right:100%;width:0}.tooltip.right.align-center:before{bottom:auto;top:50%;-webkit-transform:translateY(-50%);-ms-transform:translateY(-50%);transform:translateY(-50%)}.tooltip.align-top:before{bottom:auto;top:10%}.tooltip.align-bottom:before{bottom:10%;top:auto}.tooltip.align-left:before{left:10%;right:auto}.tooltip.align-right:before{left:auto;right:10%}.accordion{background:#fefefe;list-style-type:none;margin-left:0}.accordion[disabled] .accordion-title{cursor:not-allowed}.accordion-item:first-child>:first-child{border-radius:0}.accordion-item:last-child>:last-child{border-radius:0}.accordion-title{border:1px solid #e6e6e6;border-bottom:0;color:#1779ba;display:block;font-size:.75rem;line-height:1;padding:1.25rem 1rem;position:relative}:last-child:not(.is-active)>.accordion-title{border-bottom:1px solid #e6e6e6;border-radius:0}.accordion-title:focus,.accordion-title:hover{background-color:#e6e6e6}.accordion-title:before{content:"+";margin-top:-.5rem;position:absolute;right:1rem;top:50%}.is-active>.accordion-title:before{content:"–"}.accordion-content{background-color:#fefefe;border:1px solid #e6e6e6;border-bottom:0;color:#0a0a0a;display:none;padding:1rem}:last-child>.accordion-content:last-child{border-bottom:1px solid #e6e6e6}.media-object{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap;margin-bottom:1rem}.media-object img{max-width:none}@media print,screen and (max-width:39.99875em){.media-object.stack-for-small{-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap}}.media-object-section{-webkit-box-flex:0;-webkit-flex:0 1 auto;-ms-flex:0 1 auto;flex:0 1 auto}.media-object-section:first-child{padding-right:1rem}.media-object-section:last-child:not(:nth-child(2)){padding-left:1rem}.media-object-section>:last-child{margin-bottom:0}@media print,screen and (max-width:39.99875em){.stack-for-small .media-object-section{-ms-flex-preferred-size:100%;-webkit-flex-basis:100%;flex-basis:100%;max-width:100%;padding:0 0 1rem}.stack-for-small .media-object-section img{width:100%}}.media-object-section.main-section{-webkit-box-flex:1;-webkit-flex:1 1 0px;-ms-flex:1 1 0px;flex:1 1 0px}.orbit,.orbit-container{position:relative}.orbit-container{height:0;list-style:none;margin:0;overflow:hidden}.orbit-slide{position:absolute;width:100%}.orbit-slide.no-motionui.is-active{left:0;top:0}.orbit-figure{margin:0}.orbit-image{margin:0;max-width:100%;width:100%}.orbit-caption{background-color:hsla(0,0%,4%,.5);bottom:0;margin-bottom:0;width:100%}.orbit-caption,.orbit-next,.orbit-previous{color:#fefefe;padding:1rem;position:absolute}.orbit-next,.orbit-previous{top:50%;-webkit-transform:translateY(-50%);-ms-transform:translateY(-50%);transform:translateY(-50%);z-index:10}[data-whatinput=mouse] .orbit-next,[data-whatinput=mouse] .orbit-previous{outline:0}.orbit-next:active,.orbit-next:focus,.orbit-next:hover,.orbit-previous:active,.orbit-previous:focus,.orbit-previous:hover{background-color:hsla(0,0%,4%,.5)}.orbit-previous{left:0}.orbit-next{left:auto;right:0}.orbit-bullets{margin-bottom:.8rem;margin-top:.8rem;position:relative;text-align:center}[data-whatinput=mouse] .orbit-bullets{outline:0}.orbit-bullets button{background-color:#cacaca;border-radius:50%;height:1.2rem;margin:.1rem;width:1.2rem}.orbit-bullets button:hover{background-color:#8a8a8a}.orbit-bullets button.is-active{background-color:#8a8a8a}.flex-video,.responsive-embed{height:0;margin-bottom:1rem;overflow:hidden;padding-bottom:75%;position:relative}.flex-video embed,.flex-video iframe,.flex-video object,.flex-video video,.responsive-embed embed,.responsive-embed iframe,.responsive-embed object,.responsive-embed video{height:100%;left:0;position:absolute;top:0;width:100%}.flex-video.widescreen,.responsive-embed.widescreen{padding-bottom:56.25%}.tabs{background:#fefefe;border:1px solid #e6e6e6;list-style-type:none;margin:0}.tabs:after,.tabs:before{-ms-flex-preferred-size:0;-webkit-box-ordinal-group:2;-ms-flex-order:1;content:" ";display:table;-webkit-flex-basis:0;flex-basis:0;-webkit-order:1;order:1}.tabs:after{clear:both}.tabs.vertical>li{display:block;float:none;width:auto}.tabs.simple>li>a{padding:0}.tabs.simple>li>a:hover{background:0 0}.tabs.primary{background:#1779ba}.tabs.primary>li>a{color:#fefefe}.tabs.primary>li>a:focus,.tabs.primary>li>a:hover{background:#1673b1}.tabs-title{float:left}.tabs-title>a{color:#1779ba;display:block;font-size:.75rem;line-height:1;padding:1.25rem 1.5rem}[data-whatinput=mouse] .tabs-title>a{outline:0}.tabs-title>a:hover{background:#fefefe;color:#1468a0}.tabs-title>a:focus,.tabs-title>a[aria-selected=true]{background:#e6e6e6;color:#1779ba}.tabs-content{background:#fefefe;border:1px solid #e6e6e6;border-top:0;color:#0a0a0a;-webkit-transition:all .5s ease;transition:all .5s ease}.tabs-content.vertical{border:1px solid #e6e6e6;border-left:0}.tabs-panel{display:none;padding:1rem}.tabs-panel.is-active{display:block}.thumbnail{border:4px solid #fefefe;border-radius:0;-webkit-box-shadow:0 0 0 1px hsla(0,0%,4%,.2);box-shadow:0 0 0 1px hsla(0,0%,4%,.2);display:inline-block;line-height:0;margin-bottom:1rem;max-width:100%}a.thumbnail{-webkit-transition:-webkit-box-shadow .2s ease-out;transition:-webkit-box-shadow .2s ease-out;transition:box-shadow .2s ease-out;transition:box-shadow .2s ease-out,-webkit-box-shadow .2s ease-out}a.thumbnail:focus,a.thumbnail:hover{-webkit-box-shadow:0 0 6px 1px rgba(23,121,186,.5);box-shadow:0 0 6px 1px rgba(23,121,186,.5)}a.thumbnail image{-webkit-box-shadow:none;box-shadow:none}.menu{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;list-style:none;margin:0;padding:0;position:relative}[data-whatinput=mouse] .menu li{outline:0}.menu .button,.menu a{display:block;line-height:1;padding:.7rem 1rem;text-decoration:none}.menu a,.menu button,.menu input,.menu select{margin-bottom:0}.menu input{display:inline-block}.menu,.menu.horizontal{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap}.menu.vertical{-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap}.menu.vertical.icon-bottom li a i,.menu.vertical.icon-bottom li a img,.menu.vertical.icon-bottom li a svg,.menu.vertical.icon-top li a i,.menu.vertical.icon-top li a img,.menu.vertical.icon-top li a svg{text-align:left}.menu.expanded li{-webkit-box-flex:1;-webkit-flex:1 1 0px;-ms-flex:1 1 0px;flex:1 1 0px}.menu.expanded.icon-bottom li a i,.menu.expanded.icon-bottom li a img,.menu.expanded.icon-bottom li a svg,.menu.expanded.icon-top li a i,.menu.expanded.icon-top li a img,.menu.expanded.icon-top li a svg{text-align:left}.menu.simple{-webkit-box-align:center;-ms-flex-align:center;-webkit-align-items:center;align-items:center}.menu.simple li+li{margin-left:1rem}.menu.simple a{padding:0}@media print,screen and (min-width:40em){.menu.medium-horizontal{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap}.menu.medium-vertical{-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap}.menu.medium-expanded li,.menu.medium-simple li{-webkit-box-flex:1;-webkit-flex:1 1 0px;-ms-flex:1 1 0px;flex:1 1 0px}}@media print,screen and (min-width:64em){.menu.large-horizontal{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap}.menu.large-vertical{-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap}.menu.large-expanded li,.menu.large-simple li{-webkit-box-flex:1;-webkit-flex:1 1 0px;-ms-flex:1 1 0px;flex:1 1 0px}}.menu.nested{margin-left:1rem;margin-right:0}.menu.icon-bottom a,.menu.icon-left a,.menu.icon-right a,.menu.icon-top a,.menu.icons a{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex}.menu.icon-left li a,.menu.nested.icon-left li a{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-flow:row nowrap;-ms-flex-flow:row nowrap;flex-flow:row nowrap}.menu.icon-left li a i,.menu.icon-left li a img,.menu.icon-left li a svg,.menu.nested.icon-left li a i,.menu.nested.icon-left li a img,.menu.nested.icon-left li a svg{margin-right:.25rem}.menu.icon-right li a,.menu.nested.icon-right li a{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-flow:row nowrap;-ms-flex-flow:row nowrap;flex-flow:row nowrap}.menu.icon-right li a i,.menu.icon-right li a img,.menu.icon-right li a svg,.menu.nested.icon-right li a i,.menu.nested.icon-right li a img,.menu.nested.icon-right li a svg{margin-left:.25rem}.menu.icon-top li a,.menu.nested.icon-top li a{-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-flow:column nowrap;-ms-flex-flow:column nowrap;flex-flow:column nowrap}.menu.icon-top li a i,.menu.icon-top li a img,.menu.icon-top li a svg,.menu.nested.icon-top li a i,.menu.nested.icon-top li a img,.menu.nested.icon-top li a svg{-ms-flex-item-align:stretch;-webkit-align-self:stretch;align-self:stretch;margin-bottom:.25rem;text-align:center}.menu.icon-bottom li a,.menu.nested.icon-bottom li a{-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-flow:column nowrap;-ms-flex-flow:column nowrap;flex-flow:column nowrap}.menu.icon-bottom li a i,.menu.icon-bottom li a img,.menu.icon-bottom li a svg,.menu.nested.icon-bottom li a i,.menu.nested.icon-bottom li a img,.menu.nested.icon-bottom li a svg{-ms-flex-item-align:stretch;-webkit-align-self:stretch;align-self:stretch;margin-bottom:.25rem;text-align:center}.menu .is-active>a{background:#1779ba;color:#fefefe}.menu .active>a{background:#1779ba;color:#fefefe}.menu.align-left{-webkit-box-pack:start;-ms-flex-pack:start;-webkit-justify-content:flex-start;justify-content:flex-start}.menu.align-right li{-webkit-box-pack:end;-ms-flex-pack:end;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-justify-content:flex-end;justify-content:flex-end}.menu.align-right li .submenu li{-webkit-box-pack:start;-ms-flex-pack:start;-webkit-justify-content:flex-start;justify-content:flex-start}.menu.align-right.vertical li{display:block;text-align:right}.menu.align-right.icon-bottom li a i,.menu.align-right.icon-bottom li a img,.menu.align-right.icon-bottom li a svg,.menu.align-right.icon-top li a i,.menu.align-right.icon-top li a img,.menu.align-right.icon-top li a svg,.menu.align-right.vertical li .submenu li{text-align:right}.menu.align-right .nested{margin-left:0;margin-right:1rem}.menu.align-center li{-webkit-box-pack:center;-ms-flex-pack:center;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-justify-content:center;justify-content:center}.menu.align-center li .submenu li{-webkit-box-pack:start;-ms-flex-pack:start;-webkit-justify-content:flex-start;justify-content:flex-start}.menu .menu-text{color:inherit;font-weight:700;line-height:1;padding:.7rem 1rem}.menu-centered>.menu{-webkit-box-pack:center;-ms-flex-pack:center;-webkit-justify-content:center;justify-content:center}.menu-centered>.menu li{-webkit-box-pack:center;-ms-flex-pack:center;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-justify-content:center;justify-content:center}.menu-centered>.menu li .submenu li{-webkit-box-pack:start;-ms-flex-pack:start;-webkit-justify-content:flex-start;justify-content:flex-start}.no-js [data-responsive-menu] ul{display:none}.menu-icon{cursor:pointer;display:inline-block;height:16px;position:relative;vertical-align:middle;width:20px}.menu-icon:after{background:#fefefe;-webkit-box-shadow:0 7px 0 #fefefe,0 14px 0 #fefefe;box-shadow:0 7px 0 #fefefe,0 14px 0 #fefefe;content:"";display:block;height:2px;left:0;position:absolute;top:0;width:100%}.menu-icon:hover:after{background:#cacaca;-webkit-box-shadow:0 7px 0 #cacaca,0 14px 0 #cacaca;box-shadow:0 7px 0 #cacaca,0 14px 0 #cacaca}.menu-icon.dark{cursor:pointer;display:inline-block;height:16px;position:relative;vertical-align:middle;width:20px}.menu-icon.dark:after{background:#0a0a0a;-webkit-box-shadow:0 7px 0 #0a0a0a,0 14px 0 #0a0a0a;box-shadow:0 7px 0 #0a0a0a,0 14px 0 #0a0a0a;content:"";display:block;height:2px;left:0;position:absolute;top:0;width:100%}.menu-icon.dark:hover:after{background:#8a8a8a;-webkit-box-shadow:0 7px 0 #8a8a8a,0 14px 0 #8a8a8a;box-shadow:0 7px 0 #8a8a8a,0 14px 0 #8a8a8a}.accordion-menu li{width:100%}.accordion-menu .is-accordion-submenu a,.accordion-menu a{padding:.7rem 1rem}.accordion-menu .nested.is-accordion-submenu{margin-left:1rem;margin-right:0}.accordion-menu.align-right .nested.is-accordion-submenu{margin-left:0;margin-right:1rem}.accordion-menu .is-accordion-submenu-parent:not(.has-submenu-toggle)>a{position:relative}.accordion-menu .is-accordion-submenu-parent:not(.has-submenu-toggle)>a:after{border-color:#1779ba transparent transparent;border-style:solid;border-width:6px 6px 0;content:"";display:block;height:0;margin-top:-3px;position:absolute;right:1rem;top:50%;width:0}.accordion-menu.align-left .is-accordion-submenu-parent>a:after{left:auto;right:1rem}.accordion-menu.align-right .is-accordion-submenu-parent>a:after{left:1rem;right:auto}.accordion-menu .is-accordion-submenu-parent[aria-expanded=true]>a:after{-webkit-transform:rotate(180deg);-ms-transform:rotate(180deg);transform:rotate(180deg);-webkit-transform-origin:50% 50%;-ms-transform-origin:50% 50%;transform-origin:50% 50%}.is-accordion-submenu-parent{position:relative}.has-submenu-toggle>a{margin-right:40px}.submenu-toggle{cursor:pointer;height:40px;position:absolute;right:0;top:0;width:40px}.submenu-toggle:after{border-color:#1779ba transparent transparent;border-style:solid;border-width:6px 6px 0;bottom:0;content:"";display:block;height:0;margin:auto;top:0;width:0}.submenu-toggle[aria-expanded=true]:after{-webkit-transform:scaleY(-1);-ms-transform:scaleY(-1);transform:scaleY(-1);-webkit-transform-origin:50% 50%;-ms-transform-origin:50% 50%;transform-origin:50% 50%}.submenu-toggle-text{clip:rect(0,0,0,0)!important;border:0!important;height:1px!important;overflow:hidden!important;padding:0!important;position:absolute!important;white-space:nowrap!important;width:1px!important}.is-drilldown{overflow:hidden;position:relative}.is-drilldown li{display:block}.is-drilldown.animate-height{-webkit-transition:height .5s;transition:height .5s}.drilldown a{background:#fefefe;padding:.7rem 1rem}.drilldown .is-drilldown-submenu{background:#fefefe;left:100%;position:absolute;top:0;-webkit-transition:-webkit-transform .15s linear;transition:-webkit-transform .15s linear;transition:transform .15s linear;transition:transform .15s linear,-webkit-transform .15s linear;width:100%;z-index:-1}.drilldown .is-drilldown-submenu.is-active{display:block;-webkit-transform:translateX(-100%);-ms-transform:translateX(-100%);transform:translateX(-100%);z-index:1}.drilldown .is-drilldown-submenu.is-closing{-webkit-transform:translateX(100%);-ms-transform:translateX(100%);transform:translateX(100%)}.drilldown .is-drilldown-submenu a{padding:.7rem 1rem}.drilldown .nested.is-drilldown-submenu{margin-left:0;margin-right:0}.drilldown .drilldown-submenu-cover-previous{min-height:100%}.drilldown .is-drilldown-submenu-parent>a{position:relative}.drilldown .is-drilldown-submenu-parent>a:after{border-color:transparent transparent transparent #1779ba;border-style:solid;border-width:6px 0 6px 6px;content:"";display:block;height:0;margin-top:-6px;position:absolute;right:1rem;top:50%;width:0}.drilldown.align-left .is-drilldown-submenu-parent>a:after{border-color:transparent transparent transparent #1779ba;border-style:solid;border-width:6px 0 6px 6px;content:"";display:block;height:0;left:auto;right:1rem;width:0}.drilldown.align-right .is-drilldown-submenu-parent>a:after{border-color:transparent #1779ba transparent transparent;border-style:solid;border-width:6px 6px 6px 0;content:"";display:block;height:0;left:1rem;right:auto;width:0}.drilldown .js-drilldown-back>a:before{border-color:transparent #1779ba transparent transparent;border-style:solid;border-width:6px 6px 6px 0;content:"";display:block;display:inline-block;height:0;margin-right:.75rem;vertical-align:middle;width:0}.dropdown.menu>li.opens-left>.is-dropdown-submenu{left:auto;right:0;top:100%}.dropdown.menu>li.opens-right>.is-dropdown-submenu{left:0;right:auto;top:100%}.dropdown.menu>li.is-dropdown-submenu-parent>a{padding-right:1.5rem;position:relative}.dropdown.menu>li.is-dropdown-submenu-parent>a:after{border-color:#1779ba transparent transparent;border-style:solid;border-width:6px 6px 0;content:"";display:block;height:0;left:auto;margin-top:-3px;right:5px;width:0}[data-whatinput=mouse] .dropdown.menu a{outline:0}.dropdown.menu>li>a{padding:.7rem 1rem}.dropdown.menu>li.is-active>a{background:0 0;color:#1779ba}.no-js .dropdown.menu ul{display:none}.dropdown.menu .nested.is-dropdown-submenu{margin-left:0;margin-right:0}.dropdown.menu.vertical>li .is-dropdown-submenu{top:0}.dropdown.menu.vertical>li.opens-left>.is-dropdown-submenu{left:auto;right:100%;top:0}.dropdown.menu.vertical>li.opens-right>.is-dropdown-submenu{left:100%;right:auto}.dropdown.menu.vertical>li>a:after{right:14px}.dropdown.menu.vertical>li.opens-left>a:after{border-color:transparent #1779ba transparent transparent;border-style:solid;border-width:6px 6px 6px 0;content:"";display:block;height:0;left:5px;right:auto;width:0}.dropdown.menu.vertical>li.opens-right>a:after{border-color:transparent transparent transparent #1779ba;border-style:solid;border-width:6px 0 6px 6px;content:"";display:block;height:0;width:0}@media print,screen and (min-width:40em){.dropdown.menu.medium-horizontal>li.opens-left>.is-dropdown-submenu{left:auto;right:0;top:100%}.dropdown.menu.medium-horizontal>li.opens-right>.is-dropdown-submenu{left:0;right:auto;top:100%}.dropdown.menu.medium-horizontal>li.is-dropdown-submenu-parent>a{padding-right:1.5rem;position:relative}.dropdown.menu.medium-horizontal>li.is-dropdown-submenu-parent>a:after{border-color:#1779ba transparent transparent;border-style:solid;border-width:6px 6px 0;content:"";display:block;height:0;left:auto;margin-top:-3px;right:5px;width:0}.dropdown.menu.medium-vertical>li .is-dropdown-submenu{top:0}.dropdown.menu.medium-vertical>li.opens-left>.is-dropdown-submenu{left:auto;right:100%;top:0}.dropdown.menu.medium-vertical>li.opens-right>.is-dropdown-submenu{left:100%;right:auto}.dropdown.menu.medium-vertical>li>a:after{right:14px}.dropdown.menu.medium-vertical>li.opens-left>a:after{border-color:transparent #1779ba transparent transparent;border-style:solid;border-width:6px 6px 6px 0;content:"";display:block;height:0;left:5px;right:auto;width:0}.dropdown.menu.medium-vertical>li.opens-right>a:after{border-color:transparent transparent transparent #1779ba;border-style:solid;border-width:6px 0 6px 6px;content:"";display:block;height:0;width:0}}@media print,screen and (min-width:64em){.dropdown.menu.large-horizontal>li.opens-left>.is-dropdown-submenu{left:auto;right:0;top:100%}.dropdown.menu.large-horizontal>li.opens-right>.is-dropdown-submenu{left:0;right:auto;top:100%}.dropdown.menu.large-horizontal>li.is-dropdown-submenu-parent>a{padding-right:1.5rem;position:relative}.dropdown.menu.large-horizontal>li.is-dropdown-submenu-parent>a:after{border-color:#1779ba transparent transparent;border-style:solid;border-width:6px 6px 0;content:"";display:block;height:0;left:auto;margin-top:-3px;right:5px;width:0}.dropdown.menu.large-vertical>li .is-dropdown-submenu{top:0}.dropdown.menu.large-vertical>li.opens-left>.is-dropdown-submenu{left:auto;right:100%;top:0}.dropdown.menu.large-vertical>li.opens-right>.is-dropdown-submenu{left:100%;right:auto}.dropdown.menu.large-vertical>li>a:after{right:14px}.dropdown.menu.large-vertical>li.opens-left>a:after{border-color:transparent #1779ba transparent transparent;border-style:solid;border-width:6px 6px 6px 0;content:"";display:block;height:0;left:5px;right:auto;width:0}.dropdown.menu.large-vertical>li.opens-right>a:after{border-color:transparent transparent transparent #1779ba;border-style:solid;border-width:6px 0 6px 6px;content:"";display:block;height:0;width:0}}.dropdown.menu.align-right .is-dropdown-submenu.first-sub{left:auto;right:0;top:100%}.is-dropdown-menu.vertical{width:100px}.is-dropdown-menu.vertical.align-right{float:right}.is-dropdown-submenu-parent{position:relative}.is-dropdown-submenu-parent a:after{left:auto;margin-top:-6px;position:absolute;right:5px;top:50%}.is-dropdown-submenu-parent.opens-inner>.is-dropdown-submenu{left:auto;top:100%}.is-dropdown-submenu-parent.opens-left>.is-dropdown-submenu{left:auto;right:100%}.is-dropdown-submenu-parent.opens-right>.is-dropdown-submenu{left:100%;right:auto}.is-dropdown-submenu{background:#fefefe;border:1px solid #cacaca;display:none;left:100%;min-width:200px;position:absolute;top:0;z-index:1}.dropdown .is-dropdown-submenu a{padding:.7rem 1rem}.is-dropdown-submenu .is-dropdown-submenu-parent>a:after{right:14px}.is-dropdown-submenu .is-dropdown-submenu-parent.opens-left>a:after{border-color:transparent #1779ba transparent transparent;border-style:solid;border-width:6px 6px 6px 0;content:"";display:block;height:0;left:5px;right:auto;width:0}.is-dropdown-submenu .is-dropdown-submenu-parent.opens-right>a:after{border-color:transparent transparent transparent #1779ba;border-style:solid;border-width:6px 0 6px 6px;content:"";display:block;height:0;width:0}.is-dropdown-submenu .is-dropdown-submenu{margin-top:-1px}.is-dropdown-submenu>li{width:100%}.is-dropdown-submenu.js-dropdown-active{display:block}.is-off-canvas-open{overflow:hidden}.js-off-canvas-overlay{background:hsla(0,0%,100%,.25);height:100%;left:0;opacity:0;overflow:hidden;position:absolute;top:0;-webkit-transition:opacity .5s ease,visibility .5s ease;transition:opacity .5s ease,visibility .5s ease;visibility:hidden;width:100%;z-index:11}.js-off-canvas-overlay.is-visible{opacity:1;visibility:visible}.js-off-canvas-overlay.is-closable{cursor:pointer}.js-off-canvas-overlay.is-overlay-absolute{position:absolute}.js-off-canvas-overlay.is-overlay-fixed{position:fixed}.off-canvas-wrapper{overflow:hidden;position:relative}.off-canvas{-webkit-backface-visibility:hidden;backface-visibility:hidden;background:#e6e6e6;position:fixed;-webkit-transition:-webkit-transform .5s ease;transition:-webkit-transform .5s ease;transition:transform .5s ease;transition:transform .5s ease,-webkit-transform .5s ease;z-index:12}[data-whatinput=mouse] .off-canvas{outline:0}.off-canvas.is-transition-push{z-index:12}.off-canvas.is-closed{visibility:hidden}.off-canvas.is-transition-overlap{z-index:13}.off-canvas.is-transition-overlap.is-open{-webkit-box-shadow:0 0 10px hsla(0,0%,4%,.7);box-shadow:0 0 10px hsla(0,0%,4%,.7)}.off-canvas.is-open{-webkit-transform:translate(0);-ms-transform:translate(0);transform:translate(0)}.off-canvas-absolute{-webkit-backface-visibility:hidden;backface-visibility:hidden;background:#e6e6e6;position:absolute;-webkit-transition:-webkit-transform .5s ease;transition:-webkit-transform .5s ease;transition:transform .5s ease;transition:transform .5s ease,-webkit-transform .5s ease;z-index:12}[data-whatinput=mouse] .off-canvas-absolute{outline:0}.off-canvas-absolute.is-transition-push{z-index:12}.off-canvas-absolute.is-closed{visibility:hidden}.off-canvas-absolute.is-transition-overlap{z-index:13}.off-canvas-absolute.is-transition-overlap.is-open{-webkit-box-shadow:0 0 10px hsla(0,0%,4%,.7);box-shadow:0 0 10px hsla(0,0%,4%,.7)}.off-canvas-absolute.is-open{-webkit-transform:translate(0);-ms-transform:translate(0);transform:translate(0)}.position-left{-webkit-overflow-scrolling:touch;height:100%;left:0;overflow-y:auto;top:0;width:250px}.off-canvas-content .off-canvas.position-left,.position-left{-webkit-transform:translateX(-250px);-ms-transform:translateX(-250px);transform:translateX(-250px)}.off-canvas-content .off-canvas.position-left.is-transition-overlap.is-open{-webkit-transform:translate(0);-ms-transform:translate(0);transform:translate(0)}.off-canvas-content.is-open-left.has-transition-push{-webkit-transform:translateX(250px);-ms-transform:translateX(250px);transform:translateX(250px)}.position-left.is-transition-push{-webkit-box-shadow:inset -13px 0 20px -13px hsla(0,0%,4%,.25);box-shadow:inset -13px 0 20px -13px hsla(0,0%,4%,.25)}.position-right{-webkit-overflow-scrolling:touch;height:100%;overflow-y:auto;right:0;top:0;width:250px}.off-canvas-content .off-canvas.position-right,.position-right{-webkit-transform:translateX(250px);-ms-transform:translateX(250px);transform:translateX(250px)}.off-canvas-content .off-canvas.position-right.is-transition-overlap.is-open{-webkit-transform:translate(0);-ms-transform:translate(0);transform:translate(0)}.off-canvas-content.is-open-right.has-transition-push{-webkit-transform:translateX(-250px);-ms-transform:translateX(-250px);transform:translateX(-250px)}.position-right.is-transition-push{-webkit-box-shadow:inset 13px 0 20px -13px hsla(0,0%,4%,.25);box-shadow:inset 13px 0 20px -13px hsla(0,0%,4%,.25)}.position-top{-webkit-overflow-scrolling:touch;height:250px;left:0;overflow-x:auto;top:0;width:100%}.off-canvas-content .off-canvas.position-top,.position-top{-webkit-transform:translateY(-250px);-ms-transform:translateY(-250px);transform:translateY(-250px)}.off-canvas-content .off-canvas.position-top.is-transition-overlap.is-open{-webkit-transform:translate(0);-ms-transform:translate(0);transform:translate(0)}.off-canvas-content.is-open-top.has-transition-push{-webkit-transform:translateY(250px);-ms-transform:translateY(250px);transform:translateY(250px)}.position-top.is-transition-push{-webkit-box-shadow:inset 0 -13px 20px -13px hsla(0,0%,4%,.25);box-shadow:inset 0 -13px 20px -13px hsla(0,0%,4%,.25)}.position-bottom{-webkit-overflow-scrolling:touch;bottom:0;height:250px;left:0;overflow-x:auto;width:100%}.off-canvas-content .off-canvas.position-bottom,.position-bottom{-webkit-transform:translateY(250px);-ms-transform:translateY(250px);transform:translateY(250px)}.off-canvas-content .off-canvas.position-bottom.is-transition-overlap.is-open{-webkit-transform:translate(0);-ms-transform:translate(0);transform:translate(0)}.off-canvas-content.is-open-bottom.has-transition-push{-webkit-transform:translateY(-250px);-ms-transform:translateY(-250px);transform:translateY(-250px)}.position-bottom.is-transition-push{-webkit-box-shadow:inset 0 13px 20px -13px hsla(0,0%,4%,.25);box-shadow:inset 0 13px 20px -13px hsla(0,0%,4%,.25)}.off-canvas-content{-webkit-backface-visibility:hidden;backface-visibility:hidden;-webkit-transform:none;-ms-transform:none;transform:none}.off-canvas-content.has-transition-overlap,.off-canvas-content.has-transition-push{-webkit-transition:-webkit-transform .5s ease;transition:-webkit-transform .5s ease;transition:transform .5s ease;transition:transform .5s ease,-webkit-transform .5s ease}.off-canvas-content.has-transition-push,.off-canvas-content .off-canvas.is-open{-webkit-transform:translate(0);-ms-transform:translate(0);transform:translate(0)}@media print,screen and (min-width:40em){.position-left.reveal-for-medium{-webkit-transform:none;-ms-transform:none;transform:none;-webkit-transition:none;transition:none;visibility:visible;z-index:12}.position-left.reveal-for-medium .close-button{display:none}.off-canvas-content .position-left.reveal-for-medium{-webkit-transform:none;-ms-transform:none;transform:none}.off-canvas-content.has-reveal-left{margin-left:250px}.position-left.reveal-for-medium~.off-canvas-content{margin-left:250px}.position-right.reveal-for-medium{-webkit-transform:none;-ms-transform:none;transform:none;-webkit-transition:none;transition:none;visibility:visible;z-index:12}.position-right.reveal-for-medium .close-button{display:none}.off-canvas-content .position-right.reveal-for-medium{-webkit-transform:none;-ms-transform:none;transform:none}.off-canvas-content.has-reveal-right{margin-right:250px}.position-right.reveal-for-medium~.off-canvas-content{margin-right:250px}.position-top.reveal-for-medium{-webkit-transform:none;-ms-transform:none;transform:none;-webkit-transition:none;transition:none;visibility:visible;z-index:12}.position-top.reveal-for-medium .close-button{display:none}.off-canvas-content .position-top.reveal-for-medium{-webkit-transform:none;-ms-transform:none;transform:none}.off-canvas-content.has-reveal-top{margin-top:250px}.position-top.reveal-for-medium~.off-canvas-content{margin-top:250px}.position-bottom.reveal-for-medium{-webkit-transform:none;-ms-transform:none;transform:none;-webkit-transition:none;transition:none;visibility:visible;z-index:12}.position-bottom.reveal-for-medium .close-button{display:none}.off-canvas-content .position-bottom.reveal-for-medium{-webkit-transform:none;-ms-transform:none;transform:none}.off-canvas-content.has-reveal-bottom{margin-bottom:250px}.position-bottom.reveal-for-medium~.off-canvas-content{margin-bottom:250px}}@media print,screen and (min-width:64em){.position-left.reveal-for-large{-webkit-transform:none;-ms-transform:none;transform:none;-webkit-transition:none;transition:none;visibility:visible;z-index:12}.position-left.reveal-for-large .close-button{display:none}.off-canvas-content .position-left.reveal-for-large{-webkit-transform:none;-ms-transform:none;transform:none}.off-canvas-content.has-reveal-left{margin-left:250px}.position-left.reveal-for-large~.off-canvas-content{margin-left:250px}.position-right.reveal-for-large{-webkit-transform:none;-ms-transform:none;transform:none;-webkit-transition:none;transition:none;visibility:visible;z-index:12}.position-right.reveal-for-large .close-button{display:none}.off-canvas-content .position-right.reveal-for-large{-webkit-transform:none;-ms-transform:none;transform:none}.off-canvas-content.has-reveal-right{margin-right:250px}.position-right.reveal-for-large~.off-canvas-content{margin-right:250px}.position-top.reveal-for-large{-webkit-transform:none;-ms-transform:none;transform:none;-webkit-transition:none;transition:none;visibility:visible;z-index:12}.position-top.reveal-for-large .close-button{display:none}.off-canvas-content .position-top.reveal-for-large{-webkit-transform:none;-ms-transform:none;transform:none}.off-canvas-content.has-reveal-top{margin-top:250px}.position-top.reveal-for-large~.off-canvas-content{margin-top:250px}.position-bottom.reveal-for-large{-webkit-transform:none;-ms-transform:none;transform:none;-webkit-transition:none;transition:none;visibility:visible;z-index:12}.position-bottom.reveal-for-large .close-button{display:none}.off-canvas-content .position-bottom.reveal-for-large{-webkit-transform:none;-ms-transform:none;transform:none}.off-canvas-content.has-reveal-bottom{margin-bottom:250px}.position-bottom.reveal-for-large~.off-canvas-content{margin-bottom:250px}}@media print,screen and (min-width:40em){.off-canvas.in-canvas-for-medium{background:0 0;height:auto;overflow:visible;position:static;-webkit-transition:none;transition:none;visibility:visible;width:auto}.off-canvas.in-canvas-for-medium.position-bottom,.off-canvas.in-canvas-for-medium.position-left,.off-canvas.in-canvas-for-medium.position-right,.off-canvas.in-canvas-for-medium.position-top{-webkit-box-shadow:none;box-shadow:none;-webkit-transform:none;-ms-transform:none;transform:none}.off-canvas.in-canvas-for-medium .close-button{display:none}}@media print,screen and (min-width:64em){.off-canvas.in-canvas-for-large{background:0 0;height:auto;overflow:visible;position:static;-webkit-transition:none;transition:none;visibility:visible;width:auto}.off-canvas.in-canvas-for-large.position-bottom,.off-canvas.in-canvas-for-large.position-left,.off-canvas.in-canvas-for-large.position-right,.off-canvas.in-canvas-for-large.position-top{-webkit-box-shadow:none;box-shadow:none;-webkit-transform:none;-ms-transform:none;transform:none}.off-canvas.in-canvas-for-large .close-button{display:none}}html.is-reveal-open{overflow-y:hidden;position:fixed;width:100%}html.is-reveal-open.zf-has-scroll{-webkit-overflow-scrolling:touch;overflow-y:scroll}html.is-reveal-open body{overflow-y:hidden}.reveal-overlay{background-color:hsla(0,0%,4%,.45);bottom:0;left:0;position:fixed;right:0;top:0;z-index:1005}.reveal,.reveal-overlay{-webkit-overflow-scrolling:touch;display:none;overflow-y:auto}.reveal{-webkit-backface-visibility:hidden;backface-visibility:hidden;background-color:#fefefe;border:1px solid #cacaca;border-radius:0;margin-left:auto;margin-right:auto;padding:1rem;position:relative;top:100px;z-index:1006}[data-whatinput=mouse] .reveal{outline:0}@media print,screen and (min-width:40em){.reveal{min-height:0}}.reveal .column{min-width:0}.reveal>:last-child{margin-bottom:0}@media print,screen and (min-width:40em){.reveal{max-width:75rem;width:600px}}.reveal.collapse{padding:0}@media print,screen and (min-width:40em){.reveal.tiny{max-width:75rem;width:30%}.reveal.small{max-width:75rem;width:50%}.reveal.large{max-width:75rem;width:90%}}.reveal.full{border:0;border-radius:0;bottom:0;height:100%;left:0;margin-left:0;max-width:none;min-height:100%;right:0;top:0;width:100%}@media print,screen and (max-width:39.99875em){.reveal{border:0;border-radius:0;bottom:0;height:100%;left:0;margin-left:0;max-width:none;min-height:100%;right:0;top:0;width:100%}}.reveal.without-overlay{position:fixed}.sticky,.sticky-container{position:relative}.sticky{-webkit-transform:translateZ(0);transform:translateZ(0);z-index:0}.sticky.is-stuck{position:fixed;width:100%;z-index:5}.sticky.is-stuck.is-at-top{top:0}.sticky.is-stuck.is-at-bottom{bottom:0}.sticky.is-anchored{left:auto;position:relative;right:auto}.sticky.is-anchored.is-at-bottom{bottom:0}.title-bar{-webkit-box-pack:start;-ms-flex-pack:start;-webkit-box-align:center;-ms-flex-align:center;-webkit-align-items:center;align-items:center;background:#0a0a0a;color:#fefefe;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-justify-content:flex-start;justify-content:flex-start;padding:.5rem}.title-bar .menu-icon{margin-left:.25rem;margin-right:.25rem}.title-bar-left,.title-bar-right{-webkit-box-flex:1;-webkit-flex:1 1 0px;-ms-flex:1 1 0px;flex:1 1 0px}.title-bar-right{text-align:right}.title-bar-title{display:inline-block;font-weight:700;vertical-align:middle}.top-bar{-webkit-box-pack:justify;-ms-flex-pack:justify;-webkit-box-align:center;-ms-flex-align:center;-webkit-align-items:center;align-items:center;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;-webkit-justify-content:space-between;justify-content:space-between;padding:.5rem}.top-bar,.top-bar ul{background-color:#e6e6e6}.top-bar input{margin-right:1rem;max-width:200px}.top-bar .input-group-field{margin-right:0;width:100%}.top-bar input.button{width:auto}.top-bar .top-bar-left,.top-bar .top-bar-right{-webkit-box-flex:0;-webkit-flex:0 0 100%;-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}@media print,screen and (min-width:40em){.top-bar{-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap}.top-bar .top-bar-left{-webkit-box-flex:1;-webkit-flex:1 1 auto;-ms-flex:1 1 auto;flex:1 1 auto;margin-right:auto}.top-bar .top-bar-right{-webkit-box-flex:0;-webkit-flex:0 1 auto;-ms-flex:0 1 auto;flex:0 1 auto;margin-left:auto}}@media print,screen and (max-width:63.99875em){.top-bar.stacked-for-medium{-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap}.top-bar.stacked-for-medium .top-bar-left,.top-bar.stacked-for-medium .top-bar-right{-webkit-box-flex:0;-webkit-flex:0 0 100%;-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}}@media print,screen and (max-width:74.99875em){.top-bar.stacked-for-large{-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap}.top-bar.stacked-for-large .top-bar-left,.top-bar.stacked-for-large .top-bar-right{-webkit-box-flex:0;-webkit-flex:0 0 100%;-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}}.top-bar-title{margin:.5rem 1rem .5rem 0}.top-bar-left,.top-bar-right,.top-bar-title{-webkit-box-flex:0;-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto}.float-left{float:left!important}.float-right{float:right!important}.float-center{display:block;margin-left:auto;margin-right:auto}.clearfix:after,.clearfix:before{-ms-flex-preferred-size:0;-webkit-box-ordinal-group:2;-ms-flex-order:1;content:" ";display:table;-webkit-flex-basis:0;flex-basis:0;-webkit-order:1;order:1}.clearfix:after{clear:both}.align-left{-webkit-box-pack:start;-ms-flex-pack:start;-webkit-justify-content:flex-start;justify-content:flex-start}.align-right{-webkit-box-pack:end;-ms-flex-pack:end;-webkit-justify-content:flex-end;justify-content:flex-end}.align-center{-webkit-box-pack:center;-ms-flex-pack:center;-webkit-justify-content:center;justify-content:center}.align-justify{-webkit-box-pack:justify;-ms-flex-pack:justify;-webkit-justify-content:space-between;justify-content:space-between}.align-spaced{-ms-flex-pack:distribute;-webkit-justify-content:space-around;justify-content:space-around}.align-left.vertical.menu>li>a{-webkit-box-pack:start;-ms-flex-pack:start;-webkit-justify-content:flex-start;justify-content:flex-start}.align-right.vertical.menu>li>a{-webkit-box-pack:end;-ms-flex-pack:end;-webkit-justify-content:flex-end;justify-content:flex-end}.align-center.vertical.menu>li>a{-webkit-box-pack:center;-ms-flex-pack:center;-webkit-justify-content:center;justify-content:center}.align-top{-webkit-box-align:start;-ms-flex-align:start;-webkit-align-items:flex-start;align-items:flex-start}.align-self-top{-ms-flex-item-align:start;-webkit-align-self:flex-start;align-self:flex-start}.align-bottom{-webkit-box-align:end;-ms-flex-align:end;-webkit-align-items:flex-end;align-items:flex-end}.align-self-bottom{-ms-flex-item-align:end;-webkit-align-self:flex-end;align-self:flex-end}.align-middle{-webkit-box-align:center;-ms-flex-align:center;-webkit-align-items:center;align-items:center}.align-self-middle{-ms-flex-item-align:center;-webkit-align-self:center;align-self:center}.align-stretch{-webkit-box-align:stretch;-ms-flex-align:stretch;-webkit-align-items:stretch;align-items:stretch}.align-self-stretch{-ms-flex-item-align:stretch;-webkit-align-self:stretch;align-self:stretch}.align-center-middle{-webkit-box-pack:center;-ms-flex-pack:center;-webkit-box-align:center;-ms-flex-align:center;-ms-flex-line-pack:center;-webkit-align-content:center;align-content:center;-webkit-align-items:center;align-items:center;-webkit-justify-content:center;justify-content:center}.small-order-1{-webkit-box-ordinal-group:2;-ms-flex-order:1;-webkit-order:1;order:1}.small-order-2{-webkit-box-ordinal-group:3;-ms-flex-order:2;-webkit-order:2;order:2}.small-order-3{-webkit-box-ordinal-group:4;-ms-flex-order:3;-webkit-order:3;order:3}.small-order-4{-webkit-box-ordinal-group:5;-ms-flex-order:4;-webkit-order:4;order:4}.small-order-5{-webkit-box-ordinal-group:6;-ms-flex-order:5;-webkit-order:5;order:5}.small-order-6{-webkit-box-ordinal-group:7;-ms-flex-order:6;-webkit-order:6;order:6}@media print,screen and (min-width:40em){.medium-order-1{-webkit-box-ordinal-group:2;-ms-flex-order:1;-webkit-order:1;order:1}.medium-order-2{-webkit-box-ordinal-group:3;-ms-flex-order:2;-webkit-order:2;order:2}.medium-order-3{-webkit-box-ordinal-group:4;-ms-flex-order:3;-webkit-order:3;order:3}.medium-order-4{-webkit-box-ordinal-group:5;-ms-flex-order:4;-webkit-order:4;order:4}.medium-order-5{-webkit-box-ordinal-group:6;-ms-flex-order:5;-webkit-order:5;order:5}.medium-order-6{-webkit-box-ordinal-group:7;-ms-flex-order:6;-webkit-order:6;order:6}}@media print,screen and (min-width:64em){.large-order-1{-webkit-box-ordinal-group:2;-ms-flex-order:1;-webkit-order:1;order:1}.large-order-2{-webkit-box-ordinal-group:3;-ms-flex-order:2;-webkit-order:2;order:2}.large-order-3{-webkit-box-ordinal-group:4;-ms-flex-order:3;-webkit-order:3;order:3}.large-order-4{-webkit-box-ordinal-group:5;-ms-flex-order:4;-webkit-order:4;order:4}.large-order-5{-webkit-box-ordinal-group:6;-ms-flex-order:5;-webkit-order:5;order:5}.large-order-6{-webkit-box-ordinal-group:7;-ms-flex-order:6;-webkit-order:6;order:6}}.flex-container{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex}.flex-child-auto{-webkit-box-flex:1;-webkit-flex:1 1 auto;-ms-flex:1 1 auto;flex:1 1 auto}.flex-child-grow{-webkit-box-flex:1;-webkit-flex:1 0 auto;-ms-flex:1 0 auto;flex:1 0 auto}.flex-child-shrink{-webkit-box-flex:0;-webkit-flex:0 1 auto;-ms-flex:0 1 auto;flex:0 1 auto}.flex-dir-row{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row}.flex-dir-row-reverse{-webkit-box-orient:horizontal;-webkit-box-direction:reverse;-webkit-flex-direction:row-reverse;-ms-flex-direction:row-reverse;flex-direction:row-reverse}.flex-dir-column{-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column}.flex-dir-column-reverse{-webkit-box-orient:vertical;-webkit-box-direction:reverse;-webkit-flex-direction:column-reverse;-ms-flex-direction:column-reverse;flex-direction:column-reverse}@media print,screen and (min-width:40em){.medium-flex-container{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex}.medium-flex-child-auto{-webkit-box-flex:1;-webkit-flex:1 1 auto;-ms-flex:1 1 auto;flex:1 1 auto}.medium-flex-child-grow{-webkit-box-flex:1;-webkit-flex:1 0 auto;-ms-flex:1 0 auto;flex:1 0 auto}.medium-flex-child-shrink{-webkit-box-flex:0;-webkit-flex:0 1 auto;-ms-flex:0 1 auto;flex:0 1 auto}.medium-flex-dir-row{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row}.medium-flex-dir-row-reverse{-webkit-box-orient:horizontal;-webkit-box-direction:reverse;-webkit-flex-direction:row-reverse;-ms-flex-direction:row-reverse;flex-direction:row-reverse}.medium-flex-dir-column{-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column}.medium-flex-dir-column-reverse{-webkit-box-orient:vertical;-webkit-box-direction:reverse;-webkit-flex-direction:column-reverse;-ms-flex-direction:column-reverse;flex-direction:column-reverse}}@media print,screen and (min-width:64em){.large-flex-container{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex}.large-flex-child-auto{-webkit-box-flex:1;-webkit-flex:1 1 auto;-ms-flex:1 1 auto;flex:1 1 auto}.large-flex-child-grow{-webkit-box-flex:1;-webkit-flex:1 0 auto;-ms-flex:1 0 auto;flex:1 0 auto}.large-flex-child-shrink{-webkit-box-flex:0;-webkit-flex:0 1 auto;-ms-flex:0 1 auto;flex:0 1 auto}.large-flex-dir-row{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row}.large-flex-dir-row-reverse{-webkit-box-orient:horizontal;-webkit-box-direction:reverse;-webkit-flex-direction:row-reverse;-ms-flex-direction:row-reverse;flex-direction:row-reverse}.large-flex-dir-column{-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column}.large-flex-dir-column-reverse{-webkit-box-orient:vertical;-webkit-box-direction:reverse;-webkit-flex-direction:column-reverse;-ms-flex-direction:column-reverse;flex-direction:column-reverse}}.hide{display:none!important}.invisible{visibility:hidden}.visible{visibility:visible}@media print,screen and (max-width:39.99875em){.hide-for-small-only{display:none!important}}@media screen and (max-width:0em),screen and (min-width:40em){.show-for-small-only{display:none!important}}@media print,screen and (min-width:40em){.hide-for-medium{display:none!important}}@media screen and (max-width:39.99875em){.show-for-medium{display:none!important}}@media print,screen and (min-width:40em)and (max-width:63.99875em){.hide-for-medium-only{display:none!important}}@media screen and (max-width:39.99875em),screen and (min-width:64em){.show-for-medium-only{display:none!important}}@media print,screen and (min-width:64em){.hide-for-large{display:none!important}}@media screen and (max-width:63.99875em){.show-for-large{display:none!important}}@media print,screen and (min-width:64em)and (max-width:74.99875em){.hide-for-large-only{display:none!important}}@media screen and (max-width:63.99875em),screen and (min-width:75em){.show-for-large-only{display:none!important}}.show-for-sr,.show-on-focus{clip:rect(0,0,0,0)!important;border:0!important;height:1px!important;overflow:hidden!important;padding:0!important;position:absolute!important;white-space:nowrap!important;width:1px!important}.show-on-focus:active,.show-on-focus:focus{clip:auto!important;height:auto!important;overflow:visible!important;position:static!important;white-space:normal!important;width:auto!important}.hide-for-portrait,.show-for-landscape{display:block!important}@media screen and (orientation:landscape){.hide-for-portrait,.show-for-landscape{display:block!important}}@media screen and (orientation:portrait){.hide-for-portrait,.show-for-landscape{display:none!important}}.hide-for-landscape,.show-for-portrait{display:none!important}@media screen and (orientation:landscape){.hide-for-landscape,.show-for-portrait{display:none!important}}@media screen and (orientation:portrait){.hide-for-landscape,.show-for-portrait{display:block!important}}.show-for-dark-mode{display:none}.hide-for-dark-mode{display:block}@media screen and (prefers-color-scheme:dark){.show-for-dark-mode{display:block!important}.hide-for-dark-mode{display:none!important}}.show-for-ie{display:none}@media (-ms-high-contrast:active),(-ms-high-contrast:none){.show-for-ie{display:block!important}.hide-for-ie{display:none!important}}.show-for-sticky{display:none}.is-stuck .show-for-sticky{display:block}.is-stuck .hide-for-sticky{display:none}@font-face{font-display:"swap";font-family:FontAwesome}html{box-sizing:border-box}body{font-family:Roboto,sans-serif;font-size:16px;line-height:1}*,:after,:before{box-sizing:inherit}a{color:#3c4fe0}a.reference:after{font-family:FontAwesome;font-size:12px;padding:0 4px}a.reference.external:after{content:""}a.reference.download:after{content:""}a:hover{color:#3c4fe0;font-weight:500}.headerlink{margin-left:5px;visibility:hidden}.toc-backref:hover{color:#23263b}h1,h2,h3,h4,h5,h6{font-family:Roboto,sans-serif;font-size:16px;font-weight:500;letter-spacing:.2px;line-height:24px;margin-bottom:16px}h1:hover>a.headerlink,h2:hover>a.headerlink,h3:hover>a.headerlink,h4:hover>a.headerlink,h5:hover>a.headerlink,h6:hover>a.headerlink{visibility:visible}h1 a,h2 a,h3 a,h4 a,h5 a,h6 a{color:inherit}h1{font-size:32px;font-weight:700;line-height:40px;margin-bottom:28px}h2{font-size:24px;line-height:32px}h3{font-size:20px}h4{font-size:18px}h5{font-size:16px}h6{font-weight:400}img{max-width:100%}button:focus{outline:0}blockquote{border:0;margin:0;padding:0}blockquote,blockquote p,cite{color:inherit}cite{display:inline;font-size:inherit}cite:before{content:""}.show{display:block!important}.centered{display:block;margin:0 auto}.break{flex-basis:100%;height:0}@media screen and (min-width:1024px){h1{font-size:36px}}.admonition-title:before,.contents.local>ul>li a:before,.scylla-icon,.secondary-side-nav__content li a:before{background-repeat:no-repeat;background-size:contain;display:inline-block;filter:brightness(0);vertical-align:middle}.scylla-icon--about-team{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMSwuY2xzLTJ7ZmlsbDpub25lO3N0cm9rZTpncmF5O3N0cm9rZS1taXRlcmxpbWl0OjEwfS5jbHMtMntzdHJva2UtbGluZWNhcDpyb3VuZH08L3N0eWxlPjwvZGVmcz48ZyBpZD0iQ2FscXVlXzQiIGRhdGEtbmFtZT0iQ2FscXVlIDQiPjxwYXRoIGNsYXNzPSJjbHMtMSIgZD0iTTQuNjYgOS44MSAyLjYzIDExYTIuMDggMi4wOCAwIDAgMC0xLjEzIDEuODN2Ny44MWMuMTkgMS4xMS41IDEuNTMgMS41IDEuNDdNNy4wNiA5Ljk0bDEuNDQuOTQiLz48cGF0aCBjbGFzcz0iY2xzLTIiIGQ9Ik0zLjUgMTguNXY1LjM0TTkuNSAxOC41djUuMzRNOC41NCAxOC40MnY1LjMzTTE1LjUgMTguNXY1LjM0TTE2LjUgMTguNXY1LjM0TTMuMzMgMjAuNTNoNS4wOE0xMS40NSA4Ljg0bC4wNi4wNmExLjY1IDEuNjUgMCAwIDAgMi4zNCAwaDAiLz48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Ik0xMi40MiA3LjVhMS44MSAxLjgxIDAgMCAxLTEuOTItMS43N1Y1YTEuOTQgMS45NCAwIDAgMSAxLjkyLTIgMi4wNyAyLjA3IDAgMCAxIDIuMDggMnYuNzdhMiAyIDAgMCAxLTIuMDggMS43M1pNMTEuNDIgOC43NCA5LjYzIDkuOWEyLjA3IDIuMDcgMCAwIDAtMS4xMyAxLjg1djcuODJBMS40NyAxLjQ3IDAgMCAwIDEwIDIxTTEzLjc1IDkuMThsMiAuNjVjLjcuMzUuNzYgMS4wNi43NiAxLjg0djcuOWMwIC43Ny0uMjMgMS4yNC0xIDEuMjQiLz48cGF0aCBjbGFzcz0iY2xzLTIiIGQ9Ik05LjkzIDE5LjVoNS40Ii8+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNMTkuNDIgOS4xMmEyLjA3IDIuMDcgMCAwIDAgMi4wOC0xLjkzdi0uNzdhMi4wNyAyLjA3IDAgMCAwLTIuMDgtMS45MiAxLjkzIDEuOTMgMCAwIDAtMS45MiAxLjkydi43N2ExLjk0IDEuOTQgMCAwIDAgMS45MiAxLjkzWk01LjU5IDkuMTJhMS45MyAxLjkzIDAgMCAwIDEuOTItMS45M3YtLjc3QTEuOTMgMS45MyAwIDAgMCA1LjU5IDQuNSAyLjA4IDIuMDggMCAwIDAgMy41IDYuNDJ2Ljc3YTIuMDggMi4wOCAwIDAgMCAyLjA5IDEuOTNaTTIwLjQ0IDkuODFsMiAxLjE3YTIuMDYgMi4wNiAwIDAgMSAxLjEzIDEuODV2Ny44MWMtLjE4IDEuMTEtLjQ3IDEuNTMtMS40NyAxLjQ3TTE4LjA0IDkuOTRsLTEuNDQuOTMiLz48cGF0aCBjbGFzcz0iY2xzLTIiIGQ9Ik0yMS42IDE4LjV2NS4zNE0yMS43NyAyMC41M2gtNS4wOCIvPjwvZz48L3N2Zz4=)}.scylla-icon--about-us{background-image:url(data:image/svg+xml;base64,PHN2ZyBpZD0iTGF5ZXJfMyIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB2aWV3Qm94PSIwIDAgMjAgMjAiPjxkZWZzPjxzdHlsZT4uY2xzLTF7ZmlsbDpub25lO3N0cm9rZTojMDAwO3N0cm9rZS1saW5lY2FwOnJvdW5kO3N0cm9rZS1saW5lam9pbjpyb3VuZDtzdHJva2Utd2lkdGg6LjhweH08L3N0eWxlPjwvZGVmcz48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Ik02LjI4IDE5LjQ4Yy0uMTIuMDgtLjA4LjA3LS4yMy4xLS41OC4wOS0xLjEyLS4yOC0xLjI1LS44NCAwIDAtMi4zLTkuMTgtMi4zLTExLjExQzIuNSAzLjYgNS44OC40NCAxMC4zOC40NFMxNy41IDMuNDggMTcuNSA3LjVjMCAxLjkzLTEuMzIgMTEuMjMtMS4zMiAxMS4yMy0uMTMuNTYtLjY3Ljk0LTEuMjUuODQtLjEyLS4wMi0uMTMgMC0uMjMtLjA3Ii8+PHBhdGggZD0iTTE1Ljc1IDE1Ljc1Yy0uMTcgMS4xNS0uMjIgMi4zNC0uNTUgMy40Ni0uMzcuODUtMS42MyAxLjA2LTIuMjIuMzMtLjI1LS4yOC4xOS0uNjguNDQtLjQuNDMuNDYgMS4yNC4xOCAxLjMxLS40NGwuMDYtLjM0Yy4xOS0uODkuMzUtMS43OS41Ny0yLjY4LjA1LS4yNC40Mi0uMTcuMzkuMDdaIi8+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNMTEuNSA3YzAgMS45LTEuNTYgMy41LTMuNDYgMy41UzQuNSA4LjkgNC41IDdzMS42NC0zLjUgMy41NC0zLjVTMTEuNSA1LjEgMTEuNSA3WiIvPjxwYXRoIGQ9Ik04LjU1IDQuNzVjLS41OS4xMi0uNzEgMS40Mi0uMzYgMS43OC4yMy4yMy43MS4zMS43MS40N3MtLjQ4LjI0LS43MS40N2MtLjM2LjM2LS4yNCAxLjY2LjM2IDEuNzguNzEuMTQgMS43OC0uNzEgMS43OC0yLjI1UzkuMjYgNC42MSA4LjU1IDQuNzVaTTYuNTEgMTIuMmMyLjEyLjMxIDQuMzQtLjIgNS42OC0xLjk2LjMyLS40MS45Ni4xMS42Mi41MS0uNzYuOS0xLjc4IDEuNjMtMi45MyAxLjk1LTEuMTQuMzMtMi4zMy4zMS0zLjQ2LjE2YS4zNC4zNCAwIDAgMS0uMjktLjM4Yy4wMi0uMTguMTktLjMxLjM3LS4yOVpNNy45NyAxOS41OWMtLjk5Ljk2LTIuMzYuMDgtMi4zNi0xLjE1LS4xMi0uOS0uMjctMS43OS0uMzctMi42OS0uMDEtLjExLjA3LS4yMS4xOC0uMjIuMS0uMDEuMTkuMDYuMjEuMTUuMjIuODguMzggMS43Ny41NiAyLjY2LjAxLjc4LjY4IDEuMzggMS4zNS44My4yNy0uMjcuNjkuMTYuNDIuNDNaIi8+PHBhdGggZD0iTTkuNzUgMTkuMjdjLS40Mi45LTEuOC45Ni0yLjMyLjExLS41LTEuMTMtLjMxLTIuNS0uNDctMy43MiAwLS4xMS4wOC0uMi4xOS0uMjEuMSAwIC4xOS4wNy4yMS4xNy4xNy45NS4yOCAxLjkxLjQyIDIuODcuMDEuNDUuMjMuNzQuNTcuODUuMzMuMS43MS0uMDUuODgtLjM2LjE4LS4zNC43MS0uMDUuNTIuMjlaTTE0LjAzIDE1LjY2Yy0uMTYgMS4yMy4wMyAyLjU3LS40NiAzLjcyLS41Mi44Ni0xLjkxLjc5LTIuMzItLjExLS4xNy0uMzQuMzUtLjYxLjUzLS4yOC40Mi43MSAxLjQ4LjM4IDEuNDUtLjQ5LjE0LS45Ni4yNS0xLjkyLjQyLTIuODcuMDQtLjI0LjQxLS4yLjQuMDRaIi8+PHBhdGggZD0iTTExLjg1IDE1LjU0Yy4wMi43OS4wMSAxLjU4LjAxIDIuMzctLjAyLjQxLjA3LjktLjE0IDEuMjktLjQzIDEuMDItMi4wMSAxLjAyLTIuNDUgMC0uMjEtLjM5LS4xMy0uODktLjE0LTEuMjkgMC0uNzkgMC0xLjU4LjAxLTIuMzcgMC0uMTEuMS0uMi4yMS0uMTkuMSAwIC4xOC4wOC4xOS4xOC4wNy43OS4xIDEuNTguMTUgMi4zNy4wMy4yNyAwIC44Mi4xMyAxLjA0LjEzLjI2LjQuNDMuNjguNDIuNDYgMCAuNzktLjQuNzctLjg3bC4wMy0uNTljLjA0LS43OS4wOC0xLjU4LjE1LTIuMzcuMDItLjI0LjQtLjIzLjQuMDFaIi8+PC9zdmc+)}.scylla-icon--about-us-m{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNi4zOCAzMi40MyI+PHBhdGggZD0iTTYuNTUgMzEuNjRjLS4yLjEzLS40My4yMi0uNjkuMjZhMS44MSAxLjgxIDAgMCAxLTIuMDYtMS4zOVMuNDkgMTQuOTkuNDkgMTEuODJDLjUgNS4xOSA1Ljc3LjUgMTMuMTkuNXMxMi42OSA0LjY5IDEyLjY5IDExLjMyYzAgMy4xOC0zLjMxIDE4LjY5LTMuMzEgMTguNjlhMS44MSAxLjgxIDAgMCAxLTIuNjIgMS4yIiBzdHlsZT0iZmlsbDpub25lO3N0cm9rZTojMDAwO3N0cm9rZS1saW5lY2FwOnJvdW5kO3N0cm9rZS1saW5lam9pbjpyb3VuZCIvPjxwYXRoIGQ9Ik0yMS44NiAyNS4zNmMtLjI4IDEuOS0uMzcgMy44Ni0uOTEgNS43MS0uNjEgMS40MS0yLjY4IDEuNzUtMy42Ni41NS0uNDEtLjQ3LjMxLTEuMTEuNzMtLjY2LjcxLjc2IDIuMDQuMjkgMi4xNi0uNzMuMzItMS42Ni42NS0zLjMzIDEuMDQtNC45OC4wOS0uMzkuNy0uMjguNjUuMTFaIi8+PHBhdGggZD0iTTE0LjggMTAuNTdjMCAzLjEzLTIuNTMgNS42Ni01LjY2IDUuNjZzLTUuNDctMi41My01LjQ3LTUuNjYgMi4zNC01LjY2IDUuNDctNS42NiA1LjY2IDIuNTMgNS42NiA1LjY2WiIgc3R5bGU9InN0cm9rZS13aWR0aDouOXB4O2ZpbGw6bm9uZTtzdHJva2U6IzAwMDtzdHJva2UtbGluZWNhcDpyb3VuZDtzdHJva2UtbGluZWpvaW46cm91bmQiLz48cGF0aCBkPSJNMTAuMzEgNi44NmMtLjk4LjItMS4xNyAyLjM0LS41OSAyLjkzLjM4LjM4IDEuMTcuNTEgMS4xNy43OHMtLjc5LjQtMS4xNy43OGMtLjU5LjU5LS4zOSAyLjczLjU5IDIuOTMgMS4xNi4yMyAyLjkzLTEuMTcgMi45My0zLjcxcy0xLjc2LTMuOTQtMi45My0zLjcxWk02LjgyIDE4LjUxYzMuNDkuODkgNi45Ny0uNSA5LjUxLTIuOTMuNDctLjQ0IDEuMTYuMzEuNjguNzQtMS4zOCAxLjIzLTIuOTggMi4yOS00Ljc5IDIuODctMS44LjU5LTMuNzcuNTgtNS41OC4xNGEuNDIxLjQyMSAwIDAgMS0uMzEtLjVjLjA1LS4yMi4yOC0uMzYuNS0uMzFaIi8+PHBhdGggZD0iTTE2LjczIDE2LjY3Yy0uMTItLjQ2LS41MS0uODMtLjk5LS44My0uNzUtLjAyLS41OS0xLjE3LjE0LS45OS44MS4xNiAxLjQzLjg1IDEuNSAxLjY2LjA4LjQtLjU0LjU0LS42NS4xNVpNOS4wMyAzMS43Yy0xLjI2IDEuMzYtMy42Mi40NS0zLjgtMS4zNWwtLjA5LS41NWMtLjIxLTEuNDgtLjQ1LTIuOTUtLjYtNC40NC0uMDItLjE4LjExLS4zNC4yOS0uMzYuMTctLjAyLjMyLjA5LjM1LjI1LjM5IDEuNjMuNzEgMy4yOCAxLjAzIDQuOTMuMDkgMS4wMiAxLjM4IDEuNTQgMi4xMi44MS40NS0uNDQgMS4xNC4yNi42OS43WiIvPjxwYXRoIGQ9Ik0xMS45NiAzMS4xNmMtMSAxLjk4LTQuMDQgMS4zLTQuMjEtLjg4LS4xNS0xLjY5LS4zLTMuMzgtLjM5LTUuMDcgMC0uMTguMTMtLjM0LjMxLS4zNC4xNyAwIC4zMS4xMS4zNC4yNy4yOCAxLjY3LjUgMy4zNS43MiA1LjAzLjA5IDEuMiAxLjc3IDEuNTkgMi4zNi41MS4zMS0uNTYgMS4xNi0uMDkuODcuNDdaTTE5LjAzIDI1LjIxYy0uMDggMS42OS0uMjQgMy4zOC0uMzkgNS4wNy0uMDQuMzctLjE3Ljc1LS4zOCAxLjA2LS44NiAxLjQtMy4xMSAxLjMxLTMuODMtLjE3LS4zLS41Ni41NS0xLjAzLjg2LS40OC41OSAxLjA4IDIuMjcuNjkgMi4zNS0uNTIuMjItMS42OC40My0zLjM2LjcyLTUuMDMuMDYtLjQuNjgtLjMzLjY1LjA3WiIvPjxwYXRoIGQ9Ik0xNS40MyAyNS4wMmMuMDQgMS4zMS4wMiAyLjYxLjAyIDMuOTEtLjAzLjY3LjExIDEuNDgtLjIzIDIuMTMtLjc0IDEuNjktMy4yOSAxLjY5LTQuMDMgMC0uMzQtLjY1LS4yMS0xLjQ3LS4yNC0yLjEzIDAtMS4zLS4wMi0yLjYxLjAyLTMuOTEgMC0uMTguMTYtLjMyLjM0LS4zMi4xNyAwIC4zLjE0LjMyLjMuMTEgMS4zLjE3IDIuNi4yNCAzLjkxLjA1LjQ1IDAgMS4zNS4yMSAxLjcyLjIxLjQzLjY2LjcxIDEuMTIuNy40Ni4wMi45MS0uMjcgMS4xMi0uNjkuMjItLjM2LjE2LTEuMjguMjEtMS43Mi4wNy0xLjMuMTMtMi42MS4yNC0zLjkxLjAyLS40LjY2LS4zOC42Ni4wMloiLz48L3N2Zz4=)}.scylla-icon--alternator{background-image:url(data:image/svg+xml;base64,PHN2ZyBpZD0iTGF5ZXJfMyIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB2aWV3Qm94PSIwIDAgMjAgMjAiPjxkZWZzPjxzdHlsZT4uY2xzLTF7ZmlsbDpub25lO3N0cm9rZTojMDAwO3N0cm9rZS1saW5lY2FwOnJvdW5kO3N0cm9rZS1saW5lam9pbjpyb3VuZH08L3N0eWxlPjwvZGVmcz48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Ik0xNy41IDIuOTFjMCAxLjI4LTMuNjcgMi41OS04IDIuNTlzLTgtMS4zMS04LTIuNTlTNS4wOS41IDkuNDIuNXM4LjA4IDEuMTMgOC4wOCAyLjQxWk0xNy41IDcuNjZjMCAxLjI4LTMuNjMgMi44LTcuOTYgMi44UzEuNSA4LjkzIDEuNSA3LjY2TTE3LjUgMTIuNDdjMCAxLjI4LTMuNjcgMy4wMy04IDMuMDNzLTgtMS43NS04LTMuMDNNMTcuNSAxNy4yOWMwIDEuMjgtMy43NSAyLjMtOC4wOCAyLjNzLTcuOTItMS4wMy03LjkyLTIuM00xLjUgMTcuMTlWMi45MU0xNy41IDE3LjE5VjIuOTEiLz48L3N2Zz4=)}.scylla-icon--apps{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyMSAxOSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOm5vbmU7c3Ryb2tlOiM0ZDRkNGQ7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJDYWxxdWVfNCIgZGF0YS1uYW1lPSJDYWxxdWUgNCI+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNLjUgMS41aDIwdjE0SC41ek03LjUgMTUuNzR2Mi44OU0xMi44MyAxNS42M3YyLjMyTTUuNSAxOC41aDkuMTQiLz48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Im0zLjY0IDUuNTYgNC41OCAyLjkxLTQuNTggMi45Mk05LjEgMTIuMDhoNC4zMiIvPjwvZz48L3N2Zz4=)}.scylla-icon--architecture{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMSwuY2xzLTIsLmNscy01e2ZpbGw6bm9uZTtzdHJva2U6Z3JheX0uY2xzLTF7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfS5jbHMtMiwuY2xzLTV7c3Ryb2tlLW1pdGVybGltaXQ6MTB9LmNscy0ye3N0cm9rZS13aWR0aDouOThweH0uY2xzLTV7c3Ryb2tlLXdpZHRoOi45OXB4fTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJDYWxxdWVfMiIgZGF0YS1uYW1lPSJDYWxxdWUgMiI+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNMS45IDEwLjI3YTEwLjgzIDEwLjgzIDAgMCAxIDguNzMtOC4zOE0xMC41MSAyMy4wOEExMC43OSAxMC43OSAwIDAgMSAxLjc3IDE0TTIzLjIzIDE0YTEwLjgxIDEwLjgxIDAgMCAxLTkgOS4xMU0xNC4yNyAxLjg4YTEwLjgxIDEwLjgxIDAgMCAxIDguODMgOC4zNyIvPjxjaXJjbGUgY2xhc3M9ImNscy0yIiBjeD0iMTIuMjUiIGN5PSIxLjc1IiByPSIxLjc1Ii8+PGNpcmNsZSBjbGFzcz0iY2xzLTIiIGN4PSIxMi4yNSIgY3k9IjIyLjc1IiByPSIxLjc1Ii8+PGNpcmNsZSBjeD0iNC45MiIgY3k9IjQuNzUiIHI9IjEuNzUiIHN0eWxlPSJzdHJva2Utd2lkdGg6Ljk5cHg7ZmlsbDpncmF5O3N0cm9rZS1taXRlcmxpbWl0OjEwO3N0cm9rZTpncmF5Ii8+PGNpcmNsZSBjeD0iMjAuMDkiIGN5PSIxOS45MSIgcj0iMS43NSIgc3R5bGU9InN0cm9rZS13aWR0aDouOTlweDtmaWxsOmdyYXk7c3Ryb2tlLW1pdGVybGltaXQ6MTA7c3Ryb2tlOmdyYXkiLz48Y2lyY2xlIGNsYXNzPSJjbHMtNSIgY3g9IjEuNzUiIGN5PSIxMi4yNSIgcj0iMS43NSIvPjxjaXJjbGUgY2xhc3M9ImNscy01IiBjeD0iMjMuMjUiIGN5PSIxMi4yNSIgcj0iMS43NSIvPjxjaXJjbGUgY3g9IjQuNzUiIGN5PSIxOS42NCIgcj0iMS43NSIgc3R5bGU9InN0cm9rZS13aWR0aDouOTlweDtmaWxsOmdyYXk7c3Ryb2tlLW1pdGVybGltaXQ6MTA7c3Ryb2tlOmdyYXkiLz48Y2lyY2xlIGN4PSIxOS45MSIgY3k9IjQuNDgiIHI9IjEuNzUiIHN0eWxlPSJzdHJva2Utd2lkdGg6Ljk5cHg7ZmlsbDpncmF5O3N0cm9rZS1taXRlcmxpbWl0OjEwO3N0cm9rZTpncmF5Ii8+PC9nPjwvc3ZnPg==)}.scylla-icon--benchmarks{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVqb2luOnJvdW5kO3N0cm9rZS13aWR0aDozcHh9PC9zdHlsZT48L2RlZnM+PGcgaWQ9IkNhbHF1ZV8yIiBkYXRhLW5hbWU9IkNhbHF1ZSAyIj48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Ik01LjUxIDI0Ljkxdi01Ljg1TTEyLjU3IDI0Ljkxdi05Ljc0TTE5LjYyIDI0LjkxVjEwLjE1Ii8+PHBhdGggc3R5bGU9InN0cm9rZS1saW5lY2FwOnJvdW5kO2ZpbGw6bm9uZTtzdHJva2U6Z3JheTtzdHJva2UtbGluZWpvaW46cm91bmQiIGQ9Im0uOTEgMTQuOTggNS4xMy03Ljk0IDYuMjUgNS44OEwyNCAxIi8+PHBhdGggc3R5bGU9ImZpbGw6Z3JheSIgZD0ibTI1IDUtNS01aDV2NXoiLz48L2c+PC9zdmc+)}.scylla-icon--blog{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJDYWxxdWVfNCIgZGF0YS1uYW1lPSJDYWxxdWUgNCI+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJtOSAxNS0yLjUtMS41IDgtMTJMMTcgMyA5IDE1eiIvPjxwYXRoIHN0eWxlPSJmaWxsOmdyYXk7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kIiBkPSJtNi41IDEzLjUtLjUgM0w5IDE1bC0yLjUtMS41eiIvPjxwYXRoIGNsYXNzPSJjbHMtMSIgZD0iTTE5LjI1IDIuNWg0LjI1djE2aC0xM3Y0LjE3TDYuNDYgMTguNWwtNC45Ni0uMDRWMi41aDguMzFNMTQuNSAyLjVsMS42NyAxLjMzIi8+PC9nPjwvc3ZnPg==)}.scylla-icon--careers{background-image:url(data:image/svg+xml;base64,PHN2ZyBpZD0iQ2FscXVlXzEiIGRhdGEtbmFtZT0iQ2FscXVlIDEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmlld0JveD0iMCAwIDI1IDI1Ij48ZGVmcz48c3R5bGU+LmNscy0xe2ZpbGw6bm9uZTtzdHJva2U6Z3JheTtzdHJva2UtbGluZWNhcDpyb3VuZDtzdHJva2UtbGluZWpvaW46cm91bmR9PC9zdHlsZT48L2RlZnM+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNMS41IDExLjU1djhjMCAuNTYgMS4wNyAyIDIgMmgxOGMuODkgMCAyLTEuNDQgMi0ydi04Ii8+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNMjMuMzEgMy41SDEuODFjLS40OCAwLTEuMzEuNTUtMS4zMSAxdjZsMTAgMmE4LjQ1IDguNDUgMCAwIDAgNCAwbDEwLTJ2LTZjMC0uNDUtLjcyLTEtMS4xOS0xWk0xNS42MiAzLjV2LTFjMC0uNzYtLjYxLTEtMS4zOC0xaC0zLjQ1Yy0uNzYgMC0xLjM4LjI0LTEuMzggMXYxIi8+PHJlY3QgeD0iMTAiIHk9IjExIiB3aWR0aD0iNSIgaGVpZ2h0PSIzLjk5IiByeD0iLjU1IiByeT0iLjU1IiBzdHlsZT0iZmlsbDpncmF5Ii8+PC9zdmc+)}.scylla-icon--chevron-left{background-image:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTAiIGhlaWdodD0iMTYiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZD0iTTguMDkyIDE2IDEwIDE0LjExMyAzLjgxNyA4IDEwIDEuODg3IDguMDkyIDAgMCA4bDguMDkyIDhaIiBmaWxsPSIjMDAwIi8+PC9zdmc+)}.contents.local>ul>li a:before,.scylla-icon--chevron-right,.secondary-side-nav__content li a:before{background-image:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTAiIGhlaWdodD0iMTYiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZD0iTTEuOTA4IDAgMCAxLjg4NyA2LjE4MyA4IDAgMTQuMTEzIDEuOTA4IDE2IDEwIDggMS45MDggMFoiIGZpbGw9IiMwMDAiLz48L3N2Zz4=)}.scylla-icon--circe{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAzOCAzMCI+PGRlZnM+PHN0eWxlPi5jbHMtMiwuY2xzLTN7ZmlsbDpub25lO3N0cm9rZTojNGQ0ZDRkO3N0cm9rZS1saW5lY2FwOnJvdW5kO3N0cm9rZS1saW5lam9pbjpyb3VuZH0uY2xzLTN7c3Ryb2tlLXdpZHRoOjEuMTFweH08L3N0eWxlPjwvZGVmcz48ZyBpZD0iQ2FscXVlXzQiIGRhdGEtbmFtZT0iQ2FscXVlIDQiPjxwYXRoIGQ9Ik0yMi4xIDEyaC02LjE2YTEuMDYgMS4wNiAwIDAgMS0uOTQtMS4wNy45My45MyAwIDAgMSAuOTQtLjkzaDYuMTZhLjkzLjkzIDAgMCAxIC45NC45M0ExLjA2IDEuMDYgMCAwIDEgMjIuMSAxMloiIHN0eWxlPSJmaWxsOiM0ZDRkNGQiLz48cGF0aCBjbGFzcz0iY2xzLTIiIGQ9Ik0xMy40NCA0LjQ5SDkuNTF2MjRoMTl2LTI0SDI0LjUiLz48cGF0aCBjbGFzcz0iY2xzLTMiIGQ9Ik0xMyAzLjQ5SDguNWwtLjA4IDI2LjFIMjkuNVYzLjM5SDI1Ii8+PHBhdGggY2xhc3M9ImNscy0yIiBkPSJNMTIuNSAxOC4zOGgxM00xMi41IDE1LjQ5aDEzTTEyLjUgMjEuNDNoMTNNMTIuNSAyNC40N2gxM00xMy41IDIuNWgxMXYzLjk4aC0xMXoiLz48cGF0aCBjbGFzcz0iY2xzLTMiIGQ9Ik0yMS41LjVoLTUuMDR2MS45NWw1LjA0LjA1di0yeiIvPjwvZz48L3N2Zz4=)}.scylla-icon--clock{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyMSAxOSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOm5vbmU7c3Ryb2tlOiM0ZDRkNGQ7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJDYWxxdWVfNCIgZGF0YS1uYW1lPSJDYWxxdWUgNCI+PGNpcmNsZSBjbGFzcz0iY2xzLTEiIGN4PSIxMC41IiBjeT0iOS41IiByPSI5Ii8+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNMTAuNSAzLjV2NmwzLjA2IDMiLz48L2c+PC9zdmc+)}.scylla-icon--close{background-image:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMzQiIGhlaWdodD0iMzQiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGcgY2xpcC1wYXRoPSJ1cmwoI2EpIiBmaWxsPSIjZmZmIj48cGF0aCBkPSJNMTEuNjcgMjIuMTNhLjU2NC41NjQgMCAwIDEtLjM5OC0uOTYybDkuODk2LTkuODk2YS41NjMuNTYzIDAgMSAxIC43OTcuNzk3bC05Ljg5NiA5Ljg5NmEuNTU5LjU1OSAwIDAgMS0uMzk5LjE2NVoiLz48cGF0aCBkPSJNMjEuNTY2IDIyLjEzYS41NTkuNTU5IDAgMCAxLS4zOTgtLjE2NWwtOS44OTYtOS44OTZhLjU2My41NjMgMCAxIDEgLjc5Ny0uNzk3bDkuODk2IDkuODk1YS41NjQuNTY0IDAgMCAxLS4zOTkuOTYzWiIvPjxwYXRoIGQ9Ik0xNi42MTkgMzMuMjM3QzcuNDU1IDMzLjIzNyAwIDI1Ljc4MiAwIDE2LjYxOSAwIDcuNDU2IDcuNDU1IDAgMTYuNjE5IDBzMTYuNjE5IDcuNDU1IDE2LjYxOSAxNi42MTktNy40NTYgMTYuNjE4LTE2LjYyIDE2LjYxOFptMC0zMi4xMWMtOC41NDIgMC0xNS40OTIgNi45NS0xNS40OTIgMTUuNDkyIDAgOC41NDIgNi45NSAxNS40OTIgMTUuNDkyIDE1LjQ5MiA4LjU0MiAwIDE1LjQ5Mi02Ljk1IDE1LjQ5Mi0xNS40OTIgMC04LjU0Mi02Ljk1LTE1LjQ5Mi0xNS40OTItMTUuNDkyWiIvPjwvZz48ZGVmcz48Y2xpcFBhdGggaWQ9ImEiPjxwYXRoIGZpbGw9IiNmZmYiIGQ9Ik0wIDBoMzMuMjM3djMzLjIzN0gweiIvPjwvY2xpcFBhdGg+PC9kZWZzPjwvc3ZnPg==)}.scylla-icon--cloud{background-image:url(data:image/svg+xml;base64,PHN2ZyBpZD0iTGF5ZXJfMiIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB2aWV3Qm94PSIwIDAgNDMuMDQgMzIuMDMiPjxkZWZzPjxzdHlsZT4uY2xzLTF7ZmlsbDpub25lO3N0cm9rZTojMWQxZDFiO3N0cm9rZS1saW5lY2FwOnJvdW5kO3N0cm9rZS1saW5lam9pbjpyb3VuZH08L3N0eWxlPjwvZGVmcz48ZyBpZD0iTGF5ZXJfMyI+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNNDIuNTQgNC4wNmMwIDEuNjgtMy42MyAyLjQ0LTkgMi40NHMtMTAtLjczLTEwLTIuNFMyNy42Ny41IDMzLjA0LjVzOS41IDEuODkgOS41IDMuNTZaTTQyLjU0IDkuNjNjMCAxLjY4LTMuNzYgMi45MS05LjEyIDIuOTFzLTkuODQtMS4yMy05Ljg0LTIuOTFNNDIuNTQgMTUuMzRjMCAxLjY4LTMuNjggMy4yNS05LjA0IDMuMjUtNCAwLTcuNi0uOTYtOS4wOS0yLjA0TTQyLjU0IDIwLjY1YzAgMS42OC0zLjcyIDIuOTctOS4wOCAyLjk3TTIzLjU0IDE1LjQ2VjQuMU00Mi41NCAyMC43N1Y0LjEiLz48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Ik0yOC4xMSAyMS4wOGMtLjg3IDAtMS42Ny4yMy0yLjM5LjYxIDAtLjA3LjAxLS4xNC4wMS0uMjEgMC00Ljg1LTMuODMtOC45LTguNjgtOC45cy04Ljg4IDQuMDUtOC44OCA4LjljMCAuMTcuMDIuMzQuMDMuNTEtLjg0LS41Ny0xLjg1LS45MS0yLjk1LS45MS0yLjg4IDAtNC43NCAyLjU3LTQuNzQgNS40NnMxLjg2IDQuOTkgNC43NCA0Ljk5aDIyLjg2YzIuODggMCA1LjUyLTIuMjcgNS41Mi01LjE2cy0yLjYzLTUuMjktNS41Mi01LjI5WiIvPjwvZz48L3N2Zz4=)}.scylla-icon--cloud-docs{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyMSAxOSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOm5vbmU7c3Ryb2tlOiM0ZDRkNGQ7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJDYWxxdWVfNCIgZGF0YS1uYW1lPSJDYWxxdWUgNCI+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNNi41IDExLjVoOHYxaC04ek0xNS42NSA2LjU1YTMuNDIgMy40MiAwIDAgMC0zLjE1IDIiLz48cGF0aCBkPSJNMTAuMDYgMi44QTUuMTcgNS4xNyAwIDAgMSAxNSA2LjM1aC4yNGE0Ljg0IDQuODQgMCAwIDEgMCA5LjY3aC0xMWEzLjQ1IDMuNDUgMCAwIDEgMC02LjlBMy4xNyAzLjE3IDAgMCAxIDUgOS4yIDUuMzMgNS4zMyAwIDAgMSA0Ljg2IDhhNS4yIDUuMiAwIDAgMSA1LjItNS4ybTAtLjhhNiA2IDAgMCAwLTYgNnYuMzFhNC4yNSA0LjI1IDAgMCAwIC4xOCA4LjQ5aDExYTUuNjMgNS42MyAwIDAgMCAuMy0xMS4yNkE2IDYgMCAwIDAgMTAuMDYgMloiIHN0eWxlPSJmaWxsOiM0ZDRkNGQiLz48L2c+PC9zdmc+)}.scylla-icon--comparison{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMSwuY2xzLTIsLmNscy00e2ZpbGw6bm9uZTtzdHJva2U6Z3JheX0uY2xzLTEsLmNscy0ye3N0cm9rZS1taXRlcmxpbWl0OjEwfS5jbHMtMiwuY2xzLTR7c3Ryb2tlLWxpbmVjYXA6cm91bmR9LmNscy00e3N0cm9rZS1saW5lam9pbjpyb3VuZH08L3N0eWxlPjwvZGVmcz48ZyBpZD0iQ2FscXVlXzQiIGRhdGEtbmFtZT0iQ2FscXVlIDQiPjxwYXRoIGNsYXNzPSJjbHMtMSIgZD0iTTQuNSAxMy42M3YyLjg4aDYuMDZNMjAuNSAxMy41NHYyLjk2bC01LjUuMDEiLz48cGF0aCBjbGFzcz0iY2xzLTIiIGQ9Ik0xMi41IDE4LjV2Mi43Mk03LjUgMjEuNWgxMCIvPjxjaXJjbGUgY3g9IjEyLjUiIGN5PSIxNi41IiByPSIyIiBzdHlsZT0iZmlsbDpncmF5O3N0cm9rZS13aWR0aDouOTVweDtzdHJva2UtbWl0ZXJsaW1pdDoxMDtzdHJva2U6Z3JheSIvPjxwYXRoIGNsYXNzPSJjbHMtNCIgZD0iTTUuMDYgMTMuNThIMy44OEEzLjEgMy4xIDAgMCAxIC41IDEwLjVoOGEzLjE2IDMuMTYgMCAwIDEtMy40NCAzLjA4Wk0yMSAxMy41OGgtMS4xN2EzLjA5IDMuMDkgMCAwIDEtMy4zNy0zLjA3aDhBMy4xNiAzLjE2IDAgMCAxIDIxIDEzLjU4Wk03LjQ2IDUuMTJjMCAuNTctMS4xLjQ2LTIuNzkuNDZTMS41OCA1LjYgMS41OCA1IDMgNC40IDQuNjkgNC40czIuNzcuMTYgMi43Ny43MlpNMS41IDkuODVWNS4zMU03LjUgMTAuMzVWNS44MU0yMy41IDUuMTJjMCAuNTctMS4xLjQ2LTIuNzkuNDZzLTMuMDkgMC0zLjA5LS41NFMxOSA0LjQgMjAuNzMgNC40czIuNzcuMTYgMi43Ny43MlpNMTcuNTQgOS44NVY1LjMxTTIzLjU0IDEwLjM1VjUuODEiLz48L2c+PC9zdmc+)}.scylla-icon--contact-us{background-image:url(data:image/svg+xml;base64,PHN2ZyBpZD0iQ2FscXVlXzEiIGRhdGEtbmFtZT0iQ2FscXVlIDEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmlld0JveD0iMCAwIDI1IDI1Ij48ZGVmcz48c3R5bGU+LmNscy0xe2ZpbGw6bm9uZTtzdHJva2U6Z3JheTtzdHJva2UtbGluZWNhcDpyb3VuZDtzdHJva2UtbGluZWpvaW46cm91bmQ7c3Ryb2tlLXdpZHRoOjEuMDZweH08L3N0eWxlPjwvZGVmcz48cGF0aCBjbGFzcz0iY2xzLTEiIHRyYW5zZm9ybT0icm90YXRlKC0yNy40OSAxNS41NTIgMTEuMDgzKSIgZD0iTTcuNzYgNi4wMWgxNS41OXYxMC4xM0g3Ljc2eiIvPjxwYXRoIGNsYXNzPSJjbHMtMSIgZD0ibTYuMyAxMC4xOCA4LjYzIDEuNTZhMS40MiAxLjQyIDAgMCAwIDEuNTMtLjc0bDMuNjctOE0xMS4wMiAxOS4wM2wxLjc0LTVNMjQuNTkgMTEuOTdsLTUuMDktMS40NU03LjA5IDE3LjU4IDMuOSAxOS4zNE02LjA2IDE1LjQxLjU0IDE4LjM2Ii8+PC9zdmc+)}.scylla-icon--developers-blog{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOmdyYXl9PC9zdHlsZT48L2RlZnM+PGcgaWQ9IkNhbHF1ZV80IiBkYXRhLW5hbWU9IkNhbHF1ZSA0Ij48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Im02LjQ4IDEwLjU5LS41LjE3LjUuMTZMMTEgMTIuMTZWMTRsLTctMi40OVYxMGw3LTIuNXYxLjgzWk0xNCA5LjMyVjcuNWw3IDIuNXYxLjU0TDE0IDE0di0xLjgzbDQuMTQtMS4zLjQ0LS4xMy0uNDMtLjE0WiIvPjxwYXRoIHN0eWxlPSJmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kO3N0cm9rZS13aWR0aDouOThweCIgZD0iTTEuNSAyLjVoMjJ2MTZoLTEzdjQuMTdMNi40NiAxOC41bC00Ljk2LS4wNFYyLjV6Ii8+PC9nPjwvc3ZnPg==)}.scylla-icon--docs{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfS5jbHMtMntmaWxsOmdyYXl9PC9zdHlsZT48L2RlZnM+PGcgaWQ9IkNhbHF1ZV80IiBkYXRhLW5hbWU9IkNhbHF1ZSA0Ij48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Ik0zLjUgMi41MWgxNi45NHYyMC45MUgzLjV6Ii8+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJtMjIuNDUgMjEuNS4wNS0yMWgtMTdhMi4xNiAyLjE2IDAgMCAwLTIgMiIvPjxwYXRoIGNsYXNzPSJjbHMtMiIgZD0iTTYgNmg3djJINnpNNiA5aDExdjJINnoiLz48L2c+PC9zdmc+)}.scylla-icon--enterprise{background-image:url(data:image/svg+xml;base64,PHN2ZyBpZD0iTGF5ZXJfMyIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB2aWV3Qm94PSIwIDAgMjAgMjAiPjxkZWZzPjxzdHlsZT4uY2xzLTEsLmNscy0ye2ZpbGw6bm9uZTtzdHJva2U6IzAwMDtzdHJva2UtbGluZWNhcDpyb3VuZDtzdHJva2UtbGluZWpvaW46cm91bmR9LmNscy0ye3N0cm9rZS13aWR0aDoxLjA3cHh9PC9zdHlsZT48L2RlZnM+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJtMTMuNjIgNy41IDEuODgtMS4wOCAyIDIuMDh2N2gxTTE1LjUgMTUuNXYtNSIvPjxwYXRoIGNsYXNzPSJjbHMtMiIgZD0iTTUuNSAxNS41di0xMmw0LTIgNCAydjEyTTkuNSAxNS41VjEuNk03LjUgNS41djEwTTExLjUgNS41djEwIi8+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNNS41IDguNTQgMy40NiA3LjVsLTEuOTYuOTZ2Ny4wNGgtMU0zLjUgMTAuNXY1TS41IDE3LjVoMTgiLz48L3N2Zz4=)}.scylla-icon--enterprise-m{background-image:url(data:image/svg+xml;base64,PHN2ZyB2ZXJzaW9uPSIxLjEiIGlkPSJMYXllcl8yXzAwMDAwMDE2NzY4MDY2MDE5MjYzMjMyNzcwMDAwMDA1NDc1ODA5NTExODI4NjY2MDM2XyIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4PSIwIiB5PSIwIiB2aWV3Qm94PSIwIDAgNDMgMzEiIHN0eWxlPSJlbmFibGUtYmFja2dyb3VuZDpuZXcgMCAwIDQzIDMxIiB4bWw6c3BhY2U9InByZXNlcnZlIj48c3R5bGU+LnN0MHtmaWxsOm5vbmU7c3Ryb2tlOiMxZDFkMWI7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfTwvc3R5bGU+PGcgaWQ9IkxheWVyXzMiPjxwYXRoIGNsYXNzPSJzdDAiIGQ9Im0yOS42IDkuNSA0LTIgNi45IDQuMXYxNS45aDJNMzMuNiAyNy41VjcuNk0xNC42IDI3LjVWNC44TDIyLjUuNSAyOS42IDV2MjIuNU0yMi41IDI3LjVWMU0yNC41IDUuNmwzIDJNMjQuNSA5LjZsMyAyTTI0LjUgMTMuNmwzIDJNMjQuNSAxNy41bDMgMk0yNC41IDIxLjVsMyAyTTM1LjQgMTEuNmwzIDJNMzUuNCAxNS42bDMgMS45TTM1LjQgMTkuNWwzIDJNMzUuNCAyMy41bDMgMS45TTE4LjUgNS44djIxLjdNMTQuNiA5LjdsLTQuMS0yLjUtOCA0LjR2MTUuOWgtMk0xMC41IDI3LjVWNy4yTTEyLjUgMTEuNmwyIDFNMTIuNSAxNS42bDIgLjlNMTIuNSAxOS41bDIgMU0xMi41IDIzLjVsMi4xIDFNNi40IDEyLjR2MTUuMU0uNSAzMC41aDQyIi8+PC9nPjwvc3ZnPg==)}.scylla-icon--events{background-image:url(data:image/svg+xml;base64,PHN2ZyBpZD0iQ2FscXVlXzEiIGRhdGEtbmFtZT0iQ2FscXVlIDEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmlld0JveD0iMCAwIDI1IDI1Ij48ZGVmcz48c3R5bGU+LmNscy0xe2ZpbGw6bm9uZTtzdHJva2U6Z3JheTtzdHJva2UtbGluZWNhcDpyb3VuZDtzdHJva2UtbGluZWpvaW46cm91bmR9LmNscy0ye2ZpbGw6Z3JheX08L3N0eWxlPjwvZGVmcz48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Ik0yMi41IDIzLjVoLTIxdi0yMGgyMnYxNS4yMSIvPjxwYXRoIGNsYXNzPSJjbHMtMSIgZD0iTTQuNDIgMy41YzAtMS4zNiAxLjA5LTIgMi40NS0yYTIuNDYgMi40NiAwIDEgMSAwIDQuOTEgMi42MSAyLjYxIDAgMCAxLTEtLjIxTTEwLjY3IDMuNWMwLTEuMzYgMS4xLTIgMi40Ni0yYTIuNDYgMi40NiAwIDAgMSAwIDQuOTEgMi42MSAyLjYxIDAgMCAxLTEtLjIxTTE2LjkzIDMuNWMwLTEuMzYgMS4xLTIgMi40NS0yYTIuNDYgMi40NiAwIDEgMSAwIDQuOTEgMi41MiAyLjUyIDAgMCAxLTEtLjIxIi8+PHBhdGggY2xhc3M9ImNscy0yIiBkPSJNNyA5aDN2M0g3ek0xMiA5aDN2M2gtM3pNMTcgOWgzdjNoLTN6TTcgMTRoM3YzSDd6TTEyIDE0aDN2M2gtM3pNMTcgMTRoM3YzaC0zeiIvPjxwYXRoIGNsYXNzPSJjbHMtMSIgZD0iTTMuNSAzLjY3djE2LjY2TTMuNSAyMC40M2MwIDEuMjkuNDQgMi4zMyAxLjczIDIuMzNzMi4zMy0xLjkgMi4zMy0zLjE5bDE2Ljk0LS4wN2MwIDEuMjktLjU1IDMuMTItMS44MyAzLjEySDYuMyIvPjwvc3ZnPg==)}.admonition.note .admonition-title:before,.admonition.tip .admonition-title:before,.scylla-icon--exclamation{background-image:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PG1hc2sgaWQ9ImEiIG1hc2stdHlwZT0iYWxwaGEiIG1hc2tVbml0cz0idXNlclNwYWNlT25Vc2UiIHg9IjEiIHk9IjEiIHdpZHRoPSIyMiIgaGVpZ2h0PSIyMiI+PHBhdGggZD0iTTEyIDIzQzUuOSAyMyAxIDE4LjEgMSAxMlM1LjkgMSAxMiAxczExIDQuOSAxMSAxMS00LjkgMTEtMTEgMTFabTAtMjBjLTUgMC05IDQtOSA5czQgOSA5IDkgOS00IDktOS00LTktOS05WiIgZmlsbD0iI2ZmZiIvPjxwYXRoIGQ9Ik0xMiAxM2MtLjYgMC0xLS40LTEtMVY4YzAtLjYuNC0xIDEtMXMxIC40IDEgMXY0YzAgLjYtLjQgMS0xIDFaTTEyIDE3Yy0uMyAwLS41LS4xLS43LS4zLS4yLS4yLS4zLS40LS4zLS43IDAtLjEgMC0uMy4xLS40LjEtLjEuMS0uMi4yLS4zLjMtLjMuNy0uNCAxLjEtLjIuMSAwIC4xIDAgLjIuMSAwIDAgLjEuMS4yLjEuMS4xLjIuMi4yLjN2LjRjMCAuMSAwIC4zLS4xLjQtLjEuMS0uMS4yLS4yLjMtLjIuMi0uNC4zLS43LjNaIiBmaWxsPSIjZmZmIi8+PC9tYXNrPjxnIG1hc2s9InVybCgjYSkiPjxwYXRoIGZpbGw9IiNmZmYiIGQ9Ik0wIDBoMjR2MjRIMHoiLz48L2c+PC9zdmc+)}.collapsible-button i,.scylla-icon--expand{background-image:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYuMDAxIiBoZWlnaHQ9IjE2IiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjxwYXRoIGQ9Ik01IDEzYTEgMSAwIDAgMS0uNzEtLjI5bC00LTRhMSAxIDAgMCAxIDAtMS40MWw0LTRhMSAxIDAgMCAxIDEuNDIgMS40MUwyLjQxIDhsMy4yOSAzLjI5QTEgMSAwIDAgMSA1IDEzeiIvPjxwYXRoIGQ9Ik0xMSA5SDFhMSAxIDAgMCAxIDAtMmgxMGExIDEgMCAwIDEgMCAyek0xNSAxNmExIDEgMCAwIDEtMS0xVjFhMSAxIDAgMCAxIDIgMHYxNGExIDEgMCAwIDEtMSAxeiIvPjwvc3ZnPg==)}.scylla-icon--forum{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSJjdXJyZW50Q29sb3IiIHN0cm9rZS13aWR0aD0iMS41IiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiIGNsYXNzPSJmZWF0aGVyIGZlYXRoZXItdXNlcnMiPjxwYXRoIGQ9Ik0xNyAyMXYtMmE0IDQgMCAwIDAtNC00SDVhNCA0IDAgMCAwLTQgNHYyIi8+PGNpcmNsZSBjeD0iOSIgY3k9IjciIHI9IjQiLz48cGF0aCBkPSJNMjMgMjF2LTJhNCA0IDAgMCAwLTMtMy44N00xNiAzLjEzYTQgNCAwIDAgMSAwIDcuNzUiLz48L3N2Zz4=)}.scylla-icon--home{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyMSAxOSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOm5vbmU7c3Ryb2tlOiM0ZDRkNGQ7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJMYXllcl81IiBkYXRhLW5hbWU9IkxheWVyIDUiPjxwYXRoIGNsYXNzPSJjbHMtMSIgZD0iTTMuNSA2LjE0djExYTEuMzggMS4zOCAwIDAgMCAxLjM3IDEuMzZoMTEuMjZhMS4zOCAxLjM4IDAgMCAwIDEuMzctMS4zN3YtMTEiLz48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Im0xOS41IDcuNS04LTYuMjVhMS41OSAxLjU5IDAgMCAwLTEuOTQgMEwxLjUgNy41TTEyLjczIDE4LjAydi03LjIxSDguMjd2Ny4yMSIvPjwvZz48L3N2Zz4=)}.scylla-icon--getting-started{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyMSAxOSI+PGcgZGF0YS1uYW1lPSJDYWxxdWUgNCI+PHBhdGggc3R5bGU9ImZpbGw6IzRkNGQ0ZCIgZD0ibTcgNC41IDguNTEgNS4wNUw3IDE0LjV2LTEweiIvPjxyZWN0IHg9IjEuNSIgeT0iLjUiIHdpZHRoPSIxOCIgaGVpZ2h0PSIxOCIgcng9IjIuNDMiIHN0eWxlPSJmaWxsOm5vbmU7c3Ryb2tlOiM0ZDRkNGQ7c3Ryb2tlLW1pdGVybGltaXQ6MTAiLz48L2c+PC9zdmc+)}.scylla-icon--glossary{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyMSAxOSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOm5vbmU7c3Ryb2tlOiM0ZDRkNGQ7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJDYWxxdWVfNCIgZGF0YS1uYW1lPSJDYWxxdWUgNCI+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNMi41IDIuNWgxM3YxNmgtMTN6Ii8+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNMTUuNTggMTcuMjFoMS45MlYuNWgtMTNhMi4zNCAyLjM0IDAgMCAwLTIgMiIvPjxwYXRoIGQ9Ik00LjggMTMuOTNhMSAxIDAgMCAwIC43NS0uNDMgNiA2IDAgMCAwIC41Mi0xLjA4bDIuODctNy4wN2guMzZsMi44OCA2Ljc5YTguOTIgOC45MiAwIDAgMCAuNzIgMS40Ny43Ni43NiAwIDAgMCAuNjguMzJ2LjMySDkuNHYtLjMyYTMuMjQgMy4yNCAwIDAgMCAuODMtLjExYy4xMy0uMDYuMi0uMTkuMi0uNDJhMS41OSAxLjU5IDAgMCAwLS4xLS40NmMwLS4xMi0uMS0uMjctLjE3LS40NGwtLjMzLS43OGgtMi45Yy0uMTkuNTEtLjMxLjg1LS4zNiAxYTIuMzggMi4zOCAwIDAgMC0uMTcuNzNjMCAuMTguMTIuMzIuMzcuNGEyLjU2IDIuNTYgMCAwIDAgLjY2LjA4di4zMkg0LjhabTQuODQtMi43Mi0xLjI0LTNoLS4xMWwtMS4xNiAzWiIgc3R5bGU9ImZpbGw6IzRkNGQ0ZCIvPjwvZz48L3N2Zz4=)}.scylla-icon--infoworld{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLW1pdGVybGltaXQ6MTB9PC9zdHlsZT48L2RlZnM+PGcgaWQ9IkNhbHF1ZV80IiBkYXRhLW5hbWU9IkNhbHF1ZSA0Ij48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Ik0xMiAyLjVINi41VjZjMCAzIC41NSA3LjE3IDUgOS41djQiLz48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Ik02LjQgNC40NGgtNFMyLjU2IDExIDguNSAxM00xOC41IDQuNWw0LS4wNnMtLjA2IDYuNTYtNiA4LjU2Ii8+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNMTIgMi41aDYuNVY2YzAgMi45NC0uNCA3LjA4LTUgOS41djRNOS41IDE5LjVoNnYyaC02eiIvPjxwYXRoIHN0eWxlPSJmaWxsOmdyYXk7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLW1pdGVybGltaXQ6MTAiIGQ9Ik03LjUgMjEuNWgxMHYxaC0xMHoiLz48L2c+PC9zdmc+)}.scylla-icon--integrations{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOm5vbmU7c3Ryb2tlOiM0ZDRkNGQ7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJDYWxxdWVfNCIgZGF0YS1uYW1lPSJDYWxxdWUgNCI+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJtMTQuNTYgMTIuNy0xLjI1LTEuNTctMS4zMS43NmE2IDYgMCAwIDAtMS42NS0xbC4wOC0xLjQ5LTItLjQtLjUzIDEuNDRhNS43MyA1LjczIDAgMCAwLTEuODcuMzFsLS44OC0xLjE5LTEuNzcgMUwzLjkyIDEyYTYuMyA2LjMgMCAwIDAtMS4yMiAxLjQxbC0xLjUtLjM1LS43NCAxLjg3IDEuMzguOGE2LjIzIDYuMjMgMCAwIDAgMCAxLjgzbC0xLjQxLjcyLjY0IDEuOTEgMS41OS0uMjhhNy42MyA3LjYzIDAgMCAwIC40OC42OCA1Ljg2IDUuODYgMCAwIDAgLjY3LjczbC0uNjIgMS40NiAxLjcyIDEgMS0xLjI0YTYuNDYgNi40NiAwIDAgMCAxLjc5LjM1bC40NiAxLjUyIDItLjN2LTEuNmE2LjQzIDYuNDMgMCAwIDAgMS42Mi0uODlsMS4zLjg1TDE0LjQzIDIxbC0xLTEuMmE2LjI0IDYuMjQgMCAwIDAgLjY4LTEuNzVsMS41MS0uMTkuMDUtMi0xLjUxLS4yNmE2LjA3IDYuMDcgMCAwIDAtLjYyLTEuODFabS01LjM1IDUuNTFhMS45MyAxLjkzIDAgMSAxIC4zMS0yLjcxIDEuOTIgMS45MiAwIDAgMS0uMzEgMi43MVoiLz48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Im0yNC4zMSA4LjA1LS4xMy0xLjY1LTEuMjUtLjA5YTUuMjYgNS4yNiAwIDAgMC0uNjctMS40NGwuNzUtMS0xLjE2LTEuMTctMSAuNzRhNS4xOCA1LjE4IDAgMCAwLTEuNDMtLjY2bC0uMDYtMS4yNC0xLjY1LS4xNy0uMzIgMS4yNWE1Ljc3IDUuNzcgMCAwIDAtMS41Mi4zOEwxNSAyLjFsLTEuMzcuOS41OCAxLjE4YTQuODggNC44OCAwIDAgMC0uODYgMS4yNWwtMS4zLS4xNi0uNDUgMS42IDEuMjIuNTVhNS4xNyA1LjE3IDAgMCAwIDAgLjY4QTQuMjggNC4yOCAwIDAgMCAxMyA5bC0xLjExLjcyLjY5IDEuNTEgMS4yOC0uMzdhNC45NCA0Ljk0IDAgMCAwIDEuMDcgMS4wN2wtLjM5IDEuMjYgMS41LjcxLjc0LTEuMDlhNS4wNyA1LjA3IDAgMCAwIDEuNTIuMTRsLjUgMS4xOSAxLjYxLS40MS0uMTMtMS4yOWE1LjE0IDUuMTQgMCAwIDAgMS4yNy0uODhsMS4xMi41NyAxLTEuMzUtLjkxLS44OGE0LjkgNC45IDAgMCAwIC40Mi0xLjUyWm0tNi4yIDEuNDNhMS43NCAxLjc0IDAgMSAxIDEuNi0xLjg2IDEuNzQgMS43NCAwIDAgMS0xLjYgMS44NloiLz48L2c+PC9zdmc+)}.scylla-icon--knowledge-base{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyMSAxOSI+PGRlZnM+PHN0eWxlPi5jbHMtMSwuY2xzLTJ7ZmlsbDpub25lO3N0cm9rZTojNGQ0ZDRkfS5jbHMtMXtzdHJva2UtbGluZWNhcDpyb3VuZDtzdHJva2UtbGluZWpvaW46cm91bmR9LmNscy0ye3N0cm9rZS1taXRlcmxpbWl0OjEwfTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJMYXllcl81IiBkYXRhLW5hbWU9IkxheWVyIDUiPjxwYXRoIGNsYXNzPSJjbHMtMSIgZD0iTTE2LjIxIDYuMzhhNS4zNiA1LjM2IDAgMCAxLTEuNTEgMy43MyA1IDUgMCAwIDAtMS40NSAzLjMxSDguNDdhNS40MSA1LjQxIDAgMCAwLTEuMjgtMy4xMSA1LjM3IDUuMzcgMCAxIDEgOS0zLjkzWk0xMy4yMyAxNS42N0g4LjQ1Ii8+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNMTMuMjQgMTMuNGgtNC44djQuMTZhLjcuNyAwIDAgMCAuNzEuN2gzLjM4YS43LjcgMCAwIDAgLjcxLS43WiIvPjxwYXRoIGNsYXNzPSJjbHMtMiIgZD0iTTEwLjg0IDguMjFhMS42NSAxLjY1IDAgMSAxIDEuNjQtMS42NSAxLjY1IDEuNjUgMCAwIDEtMS42NCAxLjY1Wk0xMC44NCA4LjY3djQuNjQiLz48L2c+PC9zdmc+)}.scylla-icon--less{background-image:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTciIGhlaWdodD0iMTciIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHJlY3Qgd2lkdGg9IjE3IiBoZWlnaHQ9IjE3IiByeD0iMSIgZmlsbD0iI0IzQkFDNSIvPjxwYXRoIGQ9Ik0xMyA4LjVhMSAxIDAgMCAxLTEgMUg1YTEgMSAwIDAgMSAwLTJoN2ExIDEgMCAwIDEgMSAxWiIgZmlsbD0iI2ZmZiIvPjxwYXRoIGQ9Ik0xMyA4LjVhMSAxIDAgMCAxLTEgMUg1YTEgMSAwIDAgMSAwLTJoN2ExIDEgMCAwIDEgMSAxWiIgZmlsbD0iI2ZmZiIvPjxwYXRoIGQ9Ik0xMyA4LjVhMSAxIDAgMCAxLTEgMUg1YTEgMSAwIDAgMSAwLTJoN2ExIDEgMCAwIDEgMSAxWiIgZmlsbD0iI2ZmZiIvPjxwYXRoIGQ9Ik0xMyA4LjVhMSAxIDAgMCAxLTEgMUg1YTEgMSAwIDAgMSAwLTJoN2ExIDEgMCAwIDEgMSAxWiIgZmlsbD0iI2ZmZiIvPjxwYXRoIGQ9Ik0xMyA4LjVhMSAxIDAgMCAxLTEgMUg1YTEgMSAwIDAgMSAwLTJoN2ExIDEgMCAwIDEgMSAxWiIgZmlsbD0iI2ZmZiIvPjwvc3ZnPg==);filter:none}.scylla-icon--live-test{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtNntmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLW1pdGVybGltaXQ6MTA7c3Ryb2tlLWxpbmVjYXA6cm91bmR9PC9zdHlsZT48L2RlZnM+PGcgaWQ9IkNhbHF1ZV80IiBkYXRhLW5hbWU9IkNhbHF1ZSA0Ij48Y2lyY2xlIGN4PSIxMi41IiBjeT0iMTUiIHI9IjkuNSIgc3R5bGU9InN0cm9rZS13aWR0aDoxLjVweDtzdHJva2UtbWl0ZXJsaW1pdDoxMDtmaWxsOm5vbmU7c3Ryb2tlOmdyYXkiLz48cGF0aCBzdHlsZT0ic3Ryb2tlLXdpZHRoOjEuMXB4O3N0cm9rZS1saW5lam9pbjpyb3VuZDtzdHJva2UtbGluZWNhcDpyb3VuZDtmaWxsOm5vbmU7c3Ryb2tlOmdyYXkiIGQ9Ik0xMCAuNWg1djJoLTV6Ii8+PHBhdGggc3R5bGU9InN0cm9rZS13aWR0aDoxLjExcHg7c3Ryb2tlLWxpbmVqb2luOnJvdW5kO3N0cm9rZS1saW5lY2FwOnJvdW5kO2ZpbGw6bm9uZTtzdHJva2U6Z3JheSIgZD0iTTUuOCA4LjIgNC4xMyA2LjUzbDEuOC0xLjgxTDcuNiA2LjQiLz48cGF0aCBzdHlsZT0ic3Ryb2tlLXdpZHRoOjEuMTNweDtzdHJva2UtbWl0ZXJsaW1pdDoxMDtmaWxsOm5vbmU7c3Ryb2tlOmdyYXkiIGQ9Ik0xMiA2VjIuNSIvPjxwYXRoIHN0eWxlPSJzdHJva2Utd2lkdGg6MS4wOHB4O3N0cm9rZS1taXRlcmxpbWl0OjEwO2ZpbGw6bm9uZTtzdHJva2U6Z3JheSIgZD0iTTEzIDZWMi41Ii8+PHBhdGggY2xhc3M9ImNscy02IiBkPSJNMTIuNSA4LjA2VjEwTTEyLjUgMjAuMDR2MS44OE03LjEzIDEwLjA4bDEuNzkgMS44OE0xNi4wNCAxNy4wOGwyIDEuODhNNyAxOC45MmwxLjg4LTEuODhNMTYuMTMgMTEuOTZsMS43OS0xLjgzIi8+PGVsbGlwc2UgY3g9IjEyLjUiIGN5PSIxNC4zNiIgcng9IjEuNSIgcnk9IjEuMzYiIHN0eWxlPSJmaWxsOmdyYXkiLz48cGF0aCBjbGFzcz0iY2xzLTYiIGQ9Im0xMi42MyAxNC41NCAyLjUgNi4zOCIvPjwvZz48L3N2Zz4=)}.scylla-icon--mail-list{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSJjdXJyZW50Q29sb3IiIHN0cm9rZS13aWR0aD0iMS41IiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiIGNsYXNzPSJmZWF0aGVyIGZlYXRoZXItbWFpbCI+PHBhdGggZD0iTTQgNGgxNmMxLjEgMCAyIC45IDIgMnYxMmMwIDEuMS0uOSAyLTIgMkg0Yy0xLjEgMC0yLS45LTItMlY2YzAtMS4xLjktMiAyLTJ6Ii8+PHBhdGggZD0ibTIyIDYtMTAgN0wyIDYiLz48L3N2Zz4=)}.scylla-icon--manager{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtM3tmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kO3N0cm9rZS13aWR0aDouOTdweH0uY2xzLTR7ZmlsbDpncmF5fTwvc3R5bGU+PC9kZWZzPjxwYXRoIHN0eWxlPSJmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kIiBkPSJNMTggMmg1djIySDNWMmg0LjkyIiBpZD0iQ2FscXVlXzIiIGRhdGEtbmFtZT0iQ2FscXVlIDIiLz48ZyBpZD0iQ2FscXVlXzQiIGRhdGEtbmFtZT0iQ2FscXVlIDQiPjxwYXRoIHN0eWxlPSJzdHJva2Utd2lkdGg6MS4wN3B4O2ZpbGw6bm9uZTtzdHJva2U6Z3JheTtzdHJva2UtbGluZWNhcDpyb3VuZDtzdHJva2UtbGluZWpvaW46cm91bmQiIGQ9Ik04IDBoMTB2NEg4eiIvPjxwYXRoIGNsYXNzPSJjbHMtMyIgZD0iTTcgOWgzdjNIN3pNNyAxNmgzdjNIN3oiLz48cGF0aCBjbGFzcz0iY2xzLTQiIGQ9Ik0xMi41IDkuNWg3djJoLTd6TTEyLjUgMTYuNWg3djJoLTd6Ii8+PC9nPjwvc3ZnPg==)}.scylla-icon--memory-management{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMSwuY2xzLTJ7ZmlsbDpub25lO3N0cm9rZTpncmF5O3N0cm9rZS1saW5lY2FwOnJvdW5kO3N0cm9rZS1saW5lam9pbjpyb3VuZH0uY2xzLTJ7c3Ryb2tlLXdpZHRoOjEuMTNweH08L3N0eWxlPjwvZGVmcz48ZyBpZD0iQ2FscXVlXzQiIGRhdGEtbmFtZT0iQ2FscXVlIDQiPjxyZWN0IGNsYXNzPSJjbHMtMSIgeD0iNS41IiB5PSI1LjUiIHdpZHRoPSIxNSIgaGVpZ2h0PSIxNSIgcng9IjIuNzQiIHJ5PSIyLjc0Ii8+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNOS41IDkuNWg3djdoLTd6Ii8+PHBhdGggY2xhc3M9ImNscy0yIiBkPSJNOC41IDUuNXYtNE0xMS41IDUuNXYtNE0xNC41IDUuNXYtNE0xNy41IDUuNXYtNE04LjUgMjQuNXYtNE0xMS41IDI0LjV2LTRNMTQuNSAyNC41di00TTE3LjUgMjQuNXYtNE0yMC41IDguNWg0TTIwLjUgMTEuNWg0TTIwLjUgMTQuNWg0TTIwLjUgMTcuNWg0TTEuNSA4LjVoNE0xLjUgMTEuNWg0TTEuNSAxNC41aDRNMS41IDE3LjVoNCIvPjwvZz48L3N2Zz4=)}.scylla-icon--monitoring{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGcgZGF0YS1uYW1lPSJDYWxxdWUgNCI+PHBhdGggZD0iTTUuNTUgMTAuODlhMy44MyAzLjgzIDAgMCAxLS4xNS0zLjc2IiBzdHlsZT0ic3Ryb2tlLWxpbmVqb2luOnJvdW5kO3N0cm9rZS1saW5lY2FwOnJvdW5kO3N0cm9rZTpncmF5O2ZpbGw6bm9uZSIvPjxyZWN0IHg9IjE3LjYzIiB5PSIxNC4wMSIgd2lkdGg9IjMuMDUiIGhlaWdodD0iMTAuOCIgcng9Ii41NyIgcnk9Ii41NyIgdHJhbnNmb3JtPSJyb3RhdGUoLTQ1IDE5LjE1OCAxOS40MDUpIiBzdHlsZT0ic3Ryb2tlLW1pdGVybGltaXQ6MTA7ZmlsbDpncmF5O3N0cm9rZS13aWR0aDouOTVweDtzdHJva2U6Z3JheSIvPjxjaXJjbGUgY3g9IjguNSIgY3k9IjkiIHI9IjciIHN0eWxlPSJzdHJva2Utd2lkdGg6MnB4O3N0cm9rZS1taXRlcmxpbWl0OjEwO3N0cm9rZTpncmF5O2ZpbGw6bm9uZSIvPjxwYXRoIHN0eWxlPSJzdHJva2UtbWl0ZXJsaW1pdDoxMDtzdHJva2UtbGluZWNhcDpyb3VuZDtzdHJva2U6Z3JheTtmaWxsOm5vbmUiIGQ9Im0xNi4wNSAxNi4zOS0yLjI4LTIuMjgiLz48L2c+PC9zdmc+)}.scylla-icon--networking{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMntmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLW1pdGVybGltaXQ6MTB9PC9zdHlsZT48L2RlZnM+PGcgaWQ9IkNhbHF1ZV80IiBkYXRhLW5hbWU9IkNhbHF1ZSA0Ij48Y2lyY2xlIGN4PSIxMi41IiBjeT0iMTIuNSIgcj0iNCIgc3R5bGU9InN0cm9rZS13aWR0aDouOTRweDtmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLW1pdGVybGltaXQ6MTAiLz48Y2lyY2xlIGNsYXNzPSJjbHMtMiIgY3g9IjUiIGN5PSIzIiByPSIyLjUiLz48Y2lyY2xlIGNsYXNzPSJjbHMtMiIgY3g9IjE5IiBjeT0iMjAiIHI9IjIuNSIvPjxjaXJjbGUgY2xhc3M9ImNscy0yIiBjeD0iMjIiIGN5PSI2LjYiIHI9IjIuNSIvPjxjaXJjbGUgY2xhc3M9ImNscy0yIiBjeD0iNC41IiBjeT0iMjIiIHI9IjIuNSIvPjxwYXRoIGNsYXNzPSJjbHMtMiIgZD0ibTYuODMgNS41IDMuMjUgNC4zM00yMC4yMyA3Ljg1IDE1LjMzIDExTTkuODMgMTUuMDhsLTQuMDkgNS44NE0xNC41OCAxNS4zM2wzIDMuMDkiLz48Y2lyY2xlIGN4PSIxMi41IiBjeT0iMTIuNSIgcj0iMS41IiBzdHlsZT0iZmlsbDpncmF5Ii8+PC9nPjwvc3ZnPg==)}.scylla-icon--news{background-image:url(data:image/svg+xml;base64,PHN2ZyBpZD0iQ2FscXVlXzEiIGRhdGEtbmFtZT0iQ2FscXVlIDEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmlld0JveD0iMCAwIDI1IDI1Ij48ZGVmcz48c3R5bGU+LmNscy0xe2ZpbGw6bm9uZTtzdHJva2U6Z3JheTtzdHJva2UtbGluZWNhcDpyb3VuZDtzdHJva2UtbGluZWpvaW46cm91bmR9PC9zdHlsZT48L2RlZnM+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNMyAxNS4xNyAxNi4zMSAzLjgyYTEuNDggMS40OCAwIDAgMSAyLjIyLjQ2bDUuMTUgOS42NWExLjQ2IDEuNDYgMCAwIDEtLjkzIDIuMTJMNS42OSAxOS45Wk04LjcxIDE5LjMzbC43NiAyLjIyYTEuNTEgMS41MSAwIDAgMCAxLjg1IDFsMy41OC0xLjA2YTEuNSAxLjUgMCAwIDAgMS0xLjg2TDE1LjQ1IDE4TTUuNTQgMjBsLTEuODMgMWEuOTIuOTIgMCAwIDEtMS4yNS0uMzdMLjYxIDE3LjQ5QS45Mi45MiAwIDAgMSAxIDE2LjI0bDEuODMtMU04LjUgMTRsNy4zOC01LjUiLz48L3N2Zz4=)}.scylla-icon--newsletter{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMSwuY2xzLTJ7ZmlsbDpub25lO3N0cm9rZTpncmF5O3N0cm9rZS1taXRlcmxpbWl0OjEwfS5jbHMtMntzdHJva2UtbGluZWNhcDpyb3VuZH08L3N0eWxlPjwvZGVmcz48ZyBpZD0iQ2FscXVlXzQiIGRhdGEtbmFtZT0iQ2FscXVlIDQiPjxwYXRoIGNsYXNzPSJjbHMtMSIgZD0iTTE5LjUgOS41aDN2MTJoLTIwdi0xMmgzIi8+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJtMi42NSA5Ljg0IDkuODUgNi44OCA4LjYzLTYuODgiLz48cGF0aCBjbGFzcz0iY2xzLTIiIGQ9Im01LjUgNy41LTMgMk0xNC4zNSAzLjg2bC0xLjQ2LTEuMDktMS40NyAxLjA5TTIxLjUgOS41bC0yLTJNMTkuNSAxMS41di03aC0xNHY3LjQ3Ii8+PC9nPjwvc3ZnPg==)}.scylla-icon--nsql-guides{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGcgZGF0YS1uYW1lPSJDYWxxdWUgNCI+PHJlY3QgeD0iNC4zNyIgeT0iMTMuNzEiIHdpZHRoPSIxLjE1IiBoZWlnaHQ9IjkuNzIiIHJ4PSIuNTQiIHJ5PSIuNTQiIHRyYW5zZm9ybT0icm90YXRlKDQ1IDQuOTQ4IDE4LjU3KSIgc3R5bGU9InN0cm9rZTpncmF5O3N0cm9rZS1taXRlcmxpbWl0OjEwO2ZpbGw6Z3JheTtzdHJva2Utd2lkdGg6MS4wOXB4Ii8+PGNpcmNsZSBjeD0iMTIuMjUiIGN5PSIxMi4yNSIgcj0iNC43NSIgc3R5bGU9InN0cm9rZS13aWR0aDoxLjVweDtmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLW1pdGVybGltaXQ6MTAiLz48cGF0aCBzdHlsZT0ic3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLXdpZHRoOjEuMDZweDtmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLW1pdGVybGltaXQ6MTAiIGQ9Ik04LjUgMjAuNXYzaDE1di0yMWgtMTV2MiIvPjwvZz48L3N2Zz4=)}.scylla-icon--open-source{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfS5jbHMtMntmaWxsOmdyYXl9PC9zdHlsZT48L2RlZnM+PGcgaWQ9IkNhbHF1ZV80IiBkYXRhLW5hbWU9IkNhbHF1ZSA0Ij48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Ik0uMzEgMjEuNTEgNSAxOS42OWEyLjM3IDIuMzcgMCAwIDEgMS44OC4xOWw1LjI0IDEuNjhhMi4yMyAyLjIzIDAgMCAwIDItLjEybDkuNS00Ljc1Yy44LS40NCAxLjY0LTEuMzEgMS4xMy0xLjkxYTIuMzQgMi4zNCAwIDAgMC0yLjY0LS40MkwxOCAxNi4wOSIvPjxwYXRoIGNsYXNzPSJjbHMtMSIgZD0ibS4yNSAxNS42OSA0Ljg4LTEuMjFjMS4yNS0uMyAyLjE3LS42MyAzLjQ0LS4xM2ExNS4yMSAxNS4yMSAwIDAgMCA0IDEuMWg0LjUyYy44NSAwIC45NS41NC45NSAxLjEzYTEgMSAwIDAgMS0xLjA4IDEgNjUuODYgNjUuODYgMCAwIDEtNy0uMzEiLz48cGF0aCBjbGFzcz0iY2xzLTIiIGQ9Ik04LjU2IDkuNjh2LS44MWMwLS45MS0uMzgtMS4yMS0xLjI5LTEuMjFIN1Y2LjNoLjMxYy45MSAwIDEuMjktLjMgMS4yOS0xLjIxdi0uODFjMC0xLjIuNjYtMS45MiAyLjgyLTIuM3YxLjE2Yy0xLjI0LjM1LTEuNDMuNjgtMS40MyAxLjR2Ljg3QTEuNTIgMS41MiAwIDAgMSA4Ljc1IDcgMS41MiAxLjUyIDAgMCAxIDEwIDguNTZ2Ljg3YzAgLjcxLjE5IDEgMS40MyAxLjRWMTJjLTIuMjEtLjM1LTIuODctMS4xMi0yLjg3LTIuMzJaTTE3LjQzIDQuM3YuODFjMCAuOTEuMzcgMS4yMSAxLjI5IDEuMjFIMTl2MS4zNmgtLjMxYy0uOTIgMC0xLjI5LjMtMS4yOSAxLjIxdi44MWMwIDEuMi0uNjUgMi0yLjgxIDIuMzV2LTEuMmMxLjI1LS4zNiAxLjQ0LS42OSAxLjQ0LTEuNHYtLjg3QTEuNTMgMS41MyAwIDAgMSAxNy4yNSA3IDEuNTMgMS41MyAwIDAgMSAxNiA1LjQzdi0uODdjMC0uNzItLjE5LTEtMS40NC0xLjRWMmMyLjIyLjM4IDIuODcgMS4xIDIuODcgMi4zWiIvPjwvZz48L3N2Zz4=)}.scylla-icon--operator{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjQuODEgMS4wMSAyOC4zMiAyNy42NCI+PHBhdGggZD0iTTMyLjUyIDE4cy0uMDkgMC0uMDktLjA1LS4wOCAwLS4xNyAwYTIuMTkgMi4xOSAwIDAgMC0uNTEgMCAuNDcuNDcgMCAwIDEtLjI2LS4wNSA5LjI5IDkuMjkgMCAwIDEtMS40OS0uMzIuNTQuNTQgMCAwIDEtLjMtLjMxbC0uMzQtLjA4YTExLjI1IDExLjI1IDAgMCAwLS4xOC0zLjc5IDExLjU1IDExLjU1IDAgMCAwLTEuNS0zLjUybC4yNi0uMjZhLjU5LjU5IDAgMCAxIC4xMy0uMzkgNy43MyA3LjczIDAgMCAxIDEuMi0uODZsLjI2LS4xMy40Ny0uM3MuMDkgMCAuMTMtLjA4IDAtLjA1IDAtLjA5YS44NC44NCAwIDAgMCAuMTctMS4yLjc4Ljc4IDAgMCAwLS42LS4zIDEgMSAwIDAgMC0uNi4yMWMtLjA1LjA1LS4wOS4wOS0uMTMuMDlhMy4wOCAzLjA4IDAgMCAwLS4zNS4zOWMwIC4wOC0uMTMuMTMtLjE3LjE3YTUuNjQgNS42NCAwIDAgMS0xLjA3Ljk0LjU4LjU4IDAgMCAxLS4yNi4wOS4yNS4yNSAwIDAgMS0uMTcgMGgtLjA1bC0uMzQuMjEtMS4wOC0xYTExIDExIDAgMCAwLTUuNjUtMi4yN3YtLjM0YS42LjYgMCAwIDEtLjIyLS4zNEE4LjE4IDguMTggMCAwIDEgMTkuNjYgM3YtLjI1YzAtLjA4LjA1LS4zNS4wOS0uNTJ2LS4zMWEuODIuODIgMCAwIDAtMS40Ni0uNi44Ni44NiAwIDAgMC0uMjYuNnYuMjJhMS44MiAxLjgyIDAgMCAwIC4wOS41MS41OS41OSAwIDAgMSAwIC4yNlYzYTguODIgOC44MiAwIDAgMSAuMDggMS40Ny41OS41OSAwIDAgMS0uMjEuMzRWNS4yNGMtLjQ4IDAtMSAuMTMtMS40Ny4yMmExMC4xNiAxMC4xNiAwIDAgMC01LjI4IDNMMTEgOC4yNGgtLjE3YS43My43MyAwIDAgMS0uMjYtLjA5IDcuOCA3LjggMCAwIDEtMS4wNy0xYzAtLjA4LS4xMy0uMTMtLjE3LS4xN3MtLjI1LS4yLS4zMy0uMzMtLjA4IDAtLjEzLS4wOHYtLjA1YTEgMSAwIDAgMC0uNi0uMjEuNjQuNjQgMCAwIDAtLjYuMy45MS45MSAwIDAgMCAuMTcgMS4yczAgLjA1IDAgLjA1LjA5LjA4LjEzLjA4YTUgNSAwIDAgMCAuNDcuMjZsLjI2LjEzYTYuNjEgNi42MSAwIDAgMSAxLjIxLjg2LjQ3LjQ3IDAgMCAxIC4xMy4zOXYtLjA1bC4yNS4yNmEyLjUzIDIuNTMgMCAwIDEtLjEzLjIyIDEwLjIgMTAuMiAwIDAgMC0xLjUgN2wtLjM1LjA5YzAgLjEzLS4xNy4yMS0uMy4zYTguNTYgOC41NiAwIDAgMS0xLjQ2LjI2LjU5LjU5IDAgMCAwLS4yNiAwaC0uNTJjLS4xOCAwLS4wOC4wNS0uMTcuMDVoLS4wOGEuODQuODQgMCAwIDAtLjY5IDEgLjc5Ljc5IDAgMCAwIC44Ni42LjM5LjM5IDAgMCAwIC4yMSAwSDYuMTJhMy42MSAzLjYxIDAgMCAwIC40Ny0uMTcuNjUuNjUgMCAwIDEgLjI2LS4wOCA3LjY1IDcuNjUgMCAwIDEgMS40Mi0uMzkuNDkuNDkgMCAwIDEgLjM1LjEzaC4zOWExMC4zMiAxMC4zMiAwIDAgMCAzLjUzIDUgNi4zMSA2LjMxIDAgMCAwIDEuMTYuNzdsLS4yMi4zYS41MS41MSAwIDAgMSAwIC40MyA2LjU0IDYuNTQgMCAwIDEtLjY5IDEuMjR2LjA1YS43OC43OCAwIDAgMS0uMTcuMjFjLS4wOS4wOS0uMTcuMjYtLjMuNDNzMCAuMDktLjA5LjEzIDAgLjA1IDAgLjA1YS44OC44OCAwIDAgMCAuMzQgMS4xNi45LjkgMCAwIDAgLjMuMDggMSAxIDAgMCAwIC44Mi0uNTFzMC0uMDguMDktLjEzLjEzLS4zLjE3LS40N2wuMDktLjI2YTcuMDcgNy4wNyAwIDAgMSAuNTYtMS4zMy42Mi42MiAwIDAgMSAuMzQtLjI2bC4xNy0uMzVhMTAuMDUgMTAuMDUgMCAwIDAgMy43NS42OSA4LjQ1IDguNDUgMCAwIDAgMi4zMi0uMyAxMS40NiAxMS40NiAwIDAgMCAxLjM3LS4zOWwuMTguMzFhLjYyLjYyIDAgMCAxIC4zNC4yNiA3LjA3IDcuMDcgMCAwIDEgLjU2IDEuMzNsLjA5LjI2YTEuMzEgMS4zMSAwIDAgMCAuMTcuNDdjMCAuMDUgMCAuMDkuMDkuMTNhMSAxIDAgMCAwIC44Mi41MSAxLjA1IDEuMDUgMCAwIDAgLjM0LS4wOC43Ni43NiAwIDAgMCAuMzktLjQ4IDEuMDggMS4wOCAwIDAgMC0uMDUtLjY0LjIuMiAwIDAgMC0uMDgtLjEzIDEuNTMgMS41MyAwIDAgMC0uMzEtLjQzLjY1LjY1IDAgMCAwLS4xNy0uMjJ2LS4wOWE1LjIyIDUuMjIgMCAwIDEtLjY5LTEuMjQuNTEuNTEgMCAwIDEgLjA1LS40M2wtLjEzLS4zNEExMC42OCAxMC42OCAwIDAgMCAyOSAxOC44MmwuMzQuMDV2LS4wNWEuNTQuNTQgMCAwIDEgLjM1LS4xMyA3LjgyIDcuODIgMCAwIDEgMS4zOC4zOS42Mi42MiAwIDAgMCAuMjYuMDkgMi40MiAyLjQyIDAgMCAwIC40Ny4yMXMuMDkgMCAuMTcgMGguMDlhLjM5LjM5IDAgMCAwIC4yMSAwIC45NC45NCAwIDAgMCAuODYtLjYgMSAxIDAgMCAwLS43Ny0uOVptLTEyLjQzLTEuMzMtMS4xNi41Ni0xLjE2LS41Ni0uMy0xLjI1LjgxLTFoMS4yOWwuODIgMVptNy0yLjc5YTggOCAwIDAgMSAuMTcgMi43MWwtNC4xNS0uNzVjLS4zOC0uMDgtLjY4LS45LS43MS0xLjIyYTQgNCAwIDAgMSAuMjEtLjc0bDMuNDUtMi41NGE4LjU4IDguNTggMCAwIDEgMS4wNCAyLjU0Wm0tMi4zMS00LjEzLTMuMjIgMi42OWExLjI4IDEuMjggMCAwIDEtMS4yNS0uMzdjLS4wOS0uMDktLjM3LS4yNS0uMzctLjM4VjcuNDNhOC4wNyA4LjA3IDAgMCAxIDQuODYgMi4zMlpNMTcgNy41NmwxLS4xOC0uMDYgNC4zMWMwIC4zOC0uNjQuNjgtMSAuNjhhMS4xMSAxLjExIDAgMCAxLS4zNS0uMDhMMTMgOS43NWE4LjQxIDguNDEgMCAwIDEgNC0yLjE5Wm0tNS4yNCAzLjc4IDMuMzcgMi40Ny4zMi41M2ExLjE0IDEuMTQgMCAwIDEtLjI1IDEgLjc4Ljc4IDAgMCAxLS4zOC4zMWwtNC4zMS45YTkgOSAwIDAgMSAxLjI0LTUuMjFaTTExIDE4LjYxbDQuMS0xLjIzYy4zNSAwIC44NC43MS44OSAxLjA2YS41MS41MSAwIDAgMS0uMDUuNDNsLTEuNjMgMy45NUE4LjQxIDguNDEgMCAwIDEgMTEgMTguNjFabTkuNzYgNS4zM2E4LjY3IDguNjcgMCAwIDEtMS44NS4yMSA5LjU5IDkuNTkgMCAwIDEtMi43MS0uNDNsMS42Ni00Yy4yMS0uMjYgMS0uMiAxLjMxIDBhMi40OCAyLjQ4IDAgMCAxIC4zNC4zbDIuMDcgMy43NGE1LjcyIDUuNzIgMCAwIDAtLjguMThaTTI2IDIwLjJhOC4zNiA4LjM2IDAgMCAxLTIuNTggMi41OGwtMS45Mi0zLjcyYTEuMTUgMS4xNSAwIDAgMSAuNDEtMWMuMjEtLjI1LjU5LS41OS43MS0uNTlsNC4yMiAxLjA2QTYuMjcgNi4yNyAwIDAgMSAyNiAyMC4yWiIgc3R5bGU9ImZpbGw6IzRkNGQ0ZCIgZGF0YS1uYW1lPSJDYWxxdWUgMiIvPjwvc3ZnPg==)}.scylla-icon--overview{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJDYWxxdWVfNCIgZGF0YS1uYW1lPSJDYWxxdWUgNCI+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNMjIuNjEgMy40NUMyMi42MSA1LjA2IDE4IDYuNSAxMi41IDYuNXMtMTAtMS40NC0xMC0zIDQuNS0zIDEwLTMgMTAuMTEgMS4zMyAxMC4xMSAyLjk1Wk0yMi42MSA5LjQ0YzAgMS42MS00LjY0IDMuMDYtMTAuMTEgMy4wNnMtMTAtMS40NS0xMC0zLjA2TTIyLjYxIDE1LjUxYzAgMS42Mi00LjY0IDMtMTAuMTEgM3MtMTAtMS4zNy0xMC0zTTIyLjYxIDIxLjU5YzAgMS42Mi00LjY0IDIuOTEtMTAuMTEgMi45MXMtMTAtMS4yOS0xMC0yLjkxTTIuNSAyMS40N1YzLjQ1TTIyLjUgMjEuNDdWMy40NSIvPjwvZz48L3N2Zz4=)}.scylla-icon--partners{background-image:url(data:image/svg+xml;base64,PHN2ZyBpZD0iQ2FscXVlXzEiIGRhdGEtbmFtZT0iQ2FscXVlIDEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmlld0JveD0iMCAwIDI1IDI1Ij48ZGVmcz48c3R5bGU+LmNscy0xe2ZpbGw6bm9uZTtzdHJva2U6Z3JheTtzdHJva2UtbGluZWNhcDpyb3VuZDtzdHJva2UtbGluZWpvaW46cm91bmR9PC9zdHlsZT48L2RlZnM+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNMTguNSA4LjI2aC00LjcybC0xLjIzIDEuMjdNMi4zOSAxNS4wOS4xNSAxMy43NGw0Ljg3LTguNDIgMi4yNCAxLjM0LTQuODcgOC40M3pNMjIuNTkgMTUuMDlsMi4yNC0xLjM1LTQuODYtOC40Mi0yLjI0IDEuMzQgNC44NiA4LjQzek0xMC43MSAxNS4yNmwtMi45MyAyLjIxTTEyLjE4IDE2LjRsLTIuOTMgMi4yMU0xMy42OCAxNy41M2wtMi45MyAyLjIyIi8+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNNi4zOCA4LjNoMy43OGEyLjI3IDIuMjcgMCAwIDEgMS4zNy40N2MxLjI2IDEgNC4wOSAzLjE4IDQuNDggMy41NnMtMS4xNCAxLjY4LTIuMjcgMS4xYTE4LjM0IDE4LjM0IDAgMCAwLTIuMTEtLjkyLjU3LjU3IDAgMCAwLS41Ni4wOWwtNC43OSAzLjg5TDEyLjMzIDIxbDkuNDYtNy4wOU0zLjI0IDE0LjIybDMuNCAxLjg1Ii8+PC9zdmc+)}.scylla-icon--plus{background-image:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTciIGhlaWdodD0iMTciIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHJlY3Qgd2lkdGg9IjE3IiBoZWlnaHQ9IjE3IiByeD0iMSIgZmlsbD0iI0IzQkFDNSIvPjxwYXRoIGZpbGwtcnVsZT0iZXZlbm9kZCIgY2xpcC1ydWxlPSJldmVub2RkIiBkPSJNOS41IDVhMSAxIDAgMSAwLTIgMHYyLjVINWExIDEgMCAxIDAgMCAyaDIuNVYxMmExIDEgMCAxIDAgMiAwVjkuNUgxMmExIDEgMCAxIDAgMC0ySDkuNVY1WiIgZmlsbD0iI2ZmZiIvPjxwYXRoIGZpbGwtcnVsZT0iZXZlbm9kZCIgY2xpcC1ydWxlPSJldmVub2RkIiBkPSJNOS41IDVhMSAxIDAgMSAwLTIgMHYyLjVINWExIDEgMCAxIDAgMCAyaDIuNVYxMmExIDEgMCAxIDAgMiAwVjkuNUgxMmExIDEgMCAxIDAgMC0ySDkuNVY1WiIgZmlsbD0iI2ZmZiIvPjxwYXRoIGZpbGwtcnVsZT0iZXZlbm9kZCIgY2xpcC1ydWxlPSJldmVub2RkIiBkPSJNOS41IDVhMSAxIDAgMSAwLTIgMHYyLjVINWExIDEgMCAxIDAgMCAyaDIuNVYxMmExIDEgMCAxIDAgMiAwVjkuNUgxMmExIDEgMCAxIDAgMC0ySDkuNVY1WiIgZmlsbD0iI2ZmZiIvPjxwYXRoIGZpbGwtcnVsZT0iZXZlbm9kZCIgY2xpcC1ydWxlPSJldmVub2RkIiBkPSJNOS41IDVhMSAxIDAgMSAwLTIgMHYyLjVINWExIDEgMCAxIDAgMCAyaDIuNVYxMmExIDEgMCAxIDAgMiAwVjkuNUgxMmExIDEgMCAxIDAgMC0ySDkuNVY1WiIgZmlsbD0iI2ZmZiIvPjxwYXRoIGZpbGwtcnVsZT0iZXZlbm9kZCIgY2xpcC1ydWxlPSJldmVub2RkIiBkPSJNOS41IDVhMSAxIDAgMSAwLTIgMHYyLjVINWExIDEgMCAxIDAgMCAyaDIuNVYxMmExIDEgMCAxIDAgMiAwVjkuNUgxMmExIDEgMCAxIDAgMC0ySDkuNVY1WiIgZmlsbD0iI2ZmZiIvPjwvc3ZnPg==);filter:none}.scylla-icon--pricing{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJDYWxxdWVfMiIgZGF0YS1uYW1lPSJDYWxxdWUgMiI+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJtMjEuNzMgNy0yLjQxLTUuMTJhMi41MiAyLjUyIDAgMCAwLTIuODItMWwtNi4wOCAyLjA0QTEuNjkgMS42OSAwIDAgMCA5LjUxIDRMMy45MyAxOS4yOWExLjA2IDEuMDYgMCAwIDAgLjY0IDEuMTdsMTAuMzQgMy43NmExIDEgMCAwIDAgMS4yMi0uNDNsNS41OC0xNS4zM0ExLjg3IDEuODcgMCAwIDAgMjEuNzMgN1oiLz48Y2lyY2xlIGNsYXNzPSJjbHMtMSIgY3g9IjE1LjczIiBjeT0iNS44OSIgcj0iMiIvPjx0ZXh0IHRyYW5zZm9ybT0icm90YXRlKDIwIC00OC4yNDQgMzAuNjcpIiBzdHlsZT0iZm9udC1zaXplOjEycHg7ZmlsbDpncmF5O2ZvbnQtZmFtaWx5OlJvYm90by1NZWRpdW0sUm9ib3RvIj4kPC90ZXh0PjwvZz48L3N2Zz4=)}.scylla-icon--release-note{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMntmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kO3N0cm9rZS13aWR0aDouOTFweH08L3N0eWxlPjwvZGVmcz48ZyBpZD0iQ2FscXVlXzIiIGRhdGEtbmFtZT0iQ2FscXVlIDIiPjxwYXRoIHN0eWxlPSJzdHJva2Utd2lkdGg6LjlweDtmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kIiBkPSJNMjEuNSAyNC41aC0xN1Y1LjdMOC45NS41NCAyMS41LjV2MjR6Ii8+PHBhdGggY2xhc3M9ImNscy0yIiBkPSJNNC42NSA1LjVIOS41VjFNNy41IDguNWgxMU03LjUgMTEuNWgxMU03LjUgMTQuNWgxMU03LjUgMTcuNWgxMU03LjUgMjAuNWgxMSIvPjwvZz48L3N2Zz4=)}.scylla-icon--resource-center{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfS5jbHMtMntmaWxsOmdyYXl9PC9zdHlsZT48L2RlZnM+PGcgaWQ9IkNhbHF1ZV80IiBkYXRhLW5hbWU9IkNhbHF1ZSA0Ij48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Ik01LjUgMi41aDYuOTFsLjA5IDIwaC03di0yMHoiLz48cGF0aCBjbGFzcz0iY2xzLTIiIGQ9Ik04IDRoMnYxMC45N0w4IDE1VjR6Ii8+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNNS4zNiAyLjI5IDIuNSAzLjV2MThsMi43OSAxLjE0Ii8+PHBhdGggc3R5bGU9InN0cm9rZS13aWR0aDouNjhweDtmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kIiBkPSJtMTIuNTcgMjEuODYgMS41Ny43NSIvPjxwYXRoIHN0eWxlPSJzdHJva2Utd2lkdGg6Ljg1cHg7ZmlsbDpub25lO3N0cm9rZTpncmF5O3N0cm9rZS1saW5lY2FwOnJvdW5kO3N0cm9rZS1saW5lam9pbjpyb3VuZCIgZD0ibTE0LjExIDIuNS0xLjU0LjU3Ii8+PGNpcmNsZSBjbGFzcz0iY2xzLTIiIGN4PSI5IiBjeT0iMTkiIHI9IjEiLz48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Ik0xNC41IDIuNWg2Ljk0bC4wNiAyMGgtN3YtMjB6Ii8+PHBhdGggY2xhc3M9ImNscy0yIiBkPSJNMTcgNGgydjEwLjk3TDE3IDE1VjR6Ii8+PGNpcmNsZSBjbGFzcz0iY2xzLTIiIGN4PSIxOCIgY3k9IjE5IiByPSIxIi8+PHBhdGggY2xhc3M9ImNscy0yIiBkPSJNMTIuNiAyLjczaDEuNjdWMjIuNkgxMi42ek0yLjU4IDIxLjVsMi43NSAxLjFWMi43M2wtMi42Ni45NC0uMDkgMTcuODN6Ii8+PC9nPjwvc3ZnPg==)}.scylla-icon--roadmap{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMSwuY2xzLTJ7ZmlsbDpub25lO3N0cm9rZTpncmF5fS5jbHMtMXtzdHJva2UtbGluZWNhcDpyb3VuZDtzdHJva2UtbGluZWpvaW46cm91bmQ7c3Ryb2tlLXdpZHRoOi45OHB4fS5jbHMtMntzdHJva2UtbWl0ZXJsaW1pdDoxMH0uY2xzLTN7ZmlsbDpncmF5fTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJDYWxxdWVfNCIgZGF0YS1uYW1lPSJDYWxxdWUgNCI+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJtLjUgNC41IDgtMyA4IDQgOC0zdjE3bC04IDMtOC00LTggM3YtMTd6TTguNSAxLjVWMThNMTYuNSA1LjVWMjIiLz48cGF0aCBjbGFzcz0iY2xzLTIiIGQ9Ik0yLjUgMTMgNyAxNi41TTcgMTJsLTQuNSA1LjVNMTguNSA4bDQuNSAzLjVNMjMgN2wtNC41IDUuNSIvPjxwYXRoIGNsYXNzPSJjbHMtMyIgZD0iTTEwIDEzaDF2MWgtMXpNMTIgMTJoMXYxaC0xek0xNCAxMWgxdjFoLTF6Ii8+PC9nPjwvc3ZnPg==)}.scylla-icon--search{background-image:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZD0iTTEwLjUgMThhNy41IDcuNSAwIDEgMCAwLTE1IDcuNSA3LjUgMCAwIDAgMCAxNVpNMjEgMjFsLTUuMi01LjIiIHN0cm9rZT0iIzAwMCIgc3Ryb2tlLXdpZHRoPSIyIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiLz48L3N2Zz4=)}.scylla-icon--slack{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0NDggNTEyIj48IS0tISBGb250IEF3ZXNvbWUgUHJvIDYuMC4wIGJ5IEBmb250YXdlc29tZSAtIGh0dHBzOi8vZm9udGF3ZXNvbWUuY29tIExpY2Vuc2UgLSBodHRwczovL2ZvbnRhd2Vzb21lLmNvbS9saWNlbnNlIChDb21tZXJjaWFsIExpY2Vuc2UpIENvcHlyaWdodCAyMDIyIEZvbnRpY29ucywgSW5jLi0tPjxwYXRoIGQ9Ik05NC4xMiAzMTUuMWMwIDI1LjktMjEuMTYgNDcuMDYtNDcuMDYgNDcuMDZTMCAzNDEgMCAzMTUuMWMwLTI1LjkgMjEuMTYtNDcuMDYgNDcuMDYtNDcuMDZoNDcuMDZ2NDcuMDZ6bTIzLjcyIDBjMC0yNS45IDIxLjE2LTQ3LjA2IDQ3LjA2LTQ3LjA2czQ3LjA2IDIxLjE2IDQ3LjA2IDQ3LjA2djExNy44NGMwIDI1LjktMjEuMTYgNDcuMDYtNDcuMDYgNDcuMDZzLTQ3LjA2LTIxLjE2LTQ3LjA2LTQ3LjA2VjMxNS4xem00Ny4wNi0xODguOThjLTI1LjkgMC00Ny4wNi0yMS4xNi00Ny4wNi00Ny4wNlMxMzkgMzIgMTY0LjkgMzJzNDcuMDYgMjEuMTYgNDcuMDYgNDcuMDZ2NDcuMDZIMTY0Ljl6bTAgMjMuNzJjMjUuOSAwIDQ3LjA2IDIxLjE2IDQ3LjA2IDQ3LjA2cy0yMS4xNiA0Ny4wNi00Ny4wNiA0Ny4wNkg0Ny4wNkMyMS4xNiAyNDMuOTYgMCAyMjIuOCAwIDE5Ni45czIxLjE2LTQ3LjA2IDQ3LjA2LTQ3LjA2SDE2NC45em0xODguOTggNDcuMDZjMC0yNS45IDIxLjE2LTQ3LjA2IDQ3LjA2LTQ3LjA2IDI1LjkgMCA0Ny4wNiAyMS4xNiA0Ny4wNiA0Ny4wNnMtMjEuMTYgNDcuMDYtNDcuMDYgNDcuMDZoLTQ3LjA2VjE5Ni45em0tMjMuNzIgMGMwIDI1LjktMjEuMTYgNDcuMDYtNDcuMDYgNDcuMDYtMjUuOSAwLTQ3LjA2LTIxLjE2LTQ3LjA2LTQ3LjA2Vjc5LjA2YzAtMjUuOSAyMS4xNi00Ny4wNiA0Ny4wNi00Ny4wNiAyNS45IDAgNDcuMDYgMjEuMTYgNDcuMDYgNDcuMDZWMTk2Ljl6TTI4My4xIDM4NS44OGMyNS45IDAgNDcuMDYgMjEuMTYgNDcuMDYgNDcuMDYgMCAyNS45LTIxLjE2IDQ3LjA2LTQ3LjA2IDQ3LjA2LTI1LjkgMC00Ny4wNi0yMS4xNi00Ny4wNi00Ny4wNnYtNDcuMDZoNDcuMDZ6bTAtMjMuNzJjLTI1LjkgMC00Ny4wNi0yMS4xNi00Ny4wNi00Ny4wNiAwLTI1LjkgMjEuMTYtNDcuMDYgNDcuMDYtNDcuMDZoMTE3Ljg0YzI1LjkgMCA0Ny4wNiAyMS4xNiA0Ny4wNiA0Ny4wNiAwIDI1LjktMjEuMTYgNDcuMDYtNDcuMDYgNDcuMDZIMjgzLjF6Ii8+PC9zdmc+)}.scylla-icon--stack-overflow{background-image:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjQiIGhlaWdodD0iMzEiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Im0yMS45NDkuMTEzIDIuMDQzIDExLjY3LTIuNTE0LjQzMkwxOS40MzUuNTQ1IDIxLjk1LjExNFptLTE3Ljk3MyAyNiAxMS45NDUtLjAwNS0uMDAyLTIuNTMtMTEuOTQ0LjAwNi4wMDEgMi41M1ptMTIuMjMyLTUuNzc3TDQuMzE1IDE5LjI1bC0uMjM1IDIuNTIgMTEuODk0IDEuMDg1LjIzNC0yLjUxOVptLTEwLjc1LTYuMzc1IDExLjUzNSAzLjA3NC0uNjYyIDIuNDQzLTExLjUzNS0zLjA3NS42NjItMi40NDJabTEzLjA0LjE4TDguMjEyIDguMTI2bC0xLjI5NyAyLjE3OCAxMC4yODkgNi4wMTcgMS4yOTYtMi4xNzhabS00LjIwNi0xMS41NiA2LjczIDkuNzg3LTIuMTA4IDEuNDI0LTYuNzMtOS43ODUgMi4xMDgtMS40MjVaIiBmaWxsPSIjMDAwIi8+PHBhdGggZD0iTTE3Ljk1IDE3Ljc4OVYyOC4xM0gyLjI4MlYxNy43ODlILjI0M3YxMi4zMjZIMTkuOThWMTcuNzg5aC0yLjAzWiIgZmlsbD0iIzAwMCIvPjwvc3ZnPg==)}.scylla-icon--summit{background-image:url(data:image/svg+xml;base64,PHN2ZyBpZD0iQ2FscXVlXzEiIGRhdGEtbmFtZT0iQ2FscXVlIDEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmlld0JveD0iMCAwIDI1IDI1Ij48ZGVmcz48c3R5bGU+LmNscy0xe2ZpbGw6bm9uZTtzdHJva2U6IzRkNGQ0ZDtzdHJva2UtbGluZWNhcDpyb3VuZDtzdHJva2UtbGluZWpvaW46cm91bmR9PC9zdHlsZT48L2RlZnM+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJtMTYuNSAyMiAxLTYuNS0xMCAuMDMgMSA2LjQzIi8+PHBhdGggZD0iTTMuNDYgMTJBNS42OSA1LjY5IDAgMCAxIDUgNy41IiBzdHlsZT0ic3Ryb2tlLXdpZHRoOjEuMXB4O3N0cm9rZTojNGQ0ZDRkO3N0cm9rZS1saW5lY2FwOnJvdW5kO3N0cm9rZS1saW5lam9pbjpyb3VuZDtmaWxsOm5vbmUiLz48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Ik0xNC42MiA1YTIuMzMgMi4zMyAwIDAgMS0yLjI1IDIuNWMtMS4zMyAwLTItMS4xMi0xLjk1LTIuNDRzLjctMi41IDItMi40OEEyLjI3IDIuMjcgMCAwIDEgMTQuNjIgNVpNMTcuNTggMTJhMy4yMyAzLjIzIDAgMCAwLTMuNDYtMy41SDExQTMuMjYgMy4yNiAwIDAgMCA3LjUgMTIiLz48Y2lyY2xlIGN4PSI0Ljk0IiBjeT0iNi45NiIgcj0iMS4wMSIgc3R5bGU9ImZpbGw6IzRkNGQ0ZDtzdHJva2Utd2lkdGg6MS4xcHg7c3Ryb2tlOiM0ZDRkNGQ7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kIi8+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNNy41NCAxOC41SDQuNWwtMi02aDIwbC0yIDZoLTMiLz48L3N2Zz4=)}.scylla-icon--support{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJDYWxxdWVfNCIgZGF0YS1uYW1lPSJDYWxxdWUgNCI+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNMTguMTkgNy41YTEwIDEwIDAgMCAxIC4yMSAyLjA3YzAgNC4zNi0yLjYzIDYuOTMtNS45IDYuOTNzLTUuOTQtMi41Ny01Ljk0LTYuOTNhMTAuNTEgMTAuNTEgMCAwIDEgLjIyLTIuMTIiLz48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Ik03LjY3IDIuMjNBNi41OCA2LjU4IDAgMCAxIDEyLjUuNWE1LjY1IDUuNjUgMCAwIDEgNC4yOSAxLjdjMS45MyAxLjk0IDIuMzUgNS4wNyAyLjQzIDYuNzJhMS40OSAxLjQ5IDAgMCAwLS43OS4wNSA4LjY4IDguNjggMCAwIDAtLjA4LTEuMTZoMGE1LjUzIDUuNTMgMCAwIDEtMS43Ny0yLjM0TDE2LjQ5IDVsLS4zOC4yMkExOSAxOSAwIDAgMSA2LjggNy4zOGEuNTIuNTIgMCAwIDAtLjQyLjE2Yy0uMjMuMjQtLjE1LjY1LS4wNyAxLjA4IDAgLjExIDAgLjIyLjA1LjMyYTEuNCAxLjQgMCAwIDAtLjU4IDBjLS4xLTEuNDUtLjA2LTQuNjggMS44OS02LjcxWk02LjM4IDljLS42NS0uMDgtMSAuMS0xLjE0Ljc5YTIuMDYgMi4wNiAwIDAgMCAxLjM3IDIuMjlNMTguNTYgOWMuNjUtLjA4IDEuMDUuMSAxLjE0Ljc5YTIuMDYgMi4wNiAwIDAgMS0xLjM3IDIuMjlNOS41IDE4LjIzVjE1LjVNMTUuNSAxNS41djIuNzNNMi41IDI0LjE2Yy4yNC0yIC41OS0zLjYzIDIuNDMtNC40OWEyNC4yOSAyNC4yOSAwIDAgMSA0LjgyLTEuMzdNMjIuNSAyNC4zM2MtLjI0LTItLjQyLTMuOC0yLjI2LTQuNjZhMjQuMjkgMjQuMjkgMCAwIDAtNC44Mi0xLjM3Ii8+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNMTUuMzkgMTguMzlhNC4zNyA0LjM3IDAgMCAxLTIuOTEgMS4wNyA0LjQyIDQuNDIgMCAwIDEtMi44OS0xLjA1Ii8+PHBhdGggc3R5bGU9ImZpbGw6Z3JheSIgZD0iTTExIDEzaDN2MmgtM3oiLz48cGF0aCBkPSJNMTguMDcgMTJhOS4yMSA5LjIxIDAgMCAxLTUuNTMgMi4wNyIgc3R5bGU9InN0cm9rZS1taXRlcmxpbWl0OjEwO2ZpbGw6bm9uZTtzdHJva2U6Z3JheSIvPjwvZz48L3N2Zz4=)}.scylla-icon--tech-talks{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJDYWxxdWVfNCIgZGF0YS1uYW1lPSJDYWxxdWUgNCI+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNOC4zOSA0LjVIMjMuNXYxM2gtMTUiLz48Y2lyY2xlIGN4PSI0LjUiIGN5PSI2LjUiIHI9IjIiIHN0eWxlPSJzdHJva2UtbWl0ZXJsaW1pdDoxMDtmaWxsOm5vbmU7c3Ryb2tlOmdyYXkiLz48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Ik0xLjUgOS41aDJsLjguODYuNy0uODZoNS41OGExIDEgMCAxIDEgMCAySDYuNXYxMC44OGExIDEgMCAwIDEtMSAxLjEyIDEgMSAwIDAgMS0xLTEgMSAxIDAgMCAxLTEgMSAuOTMuOTMgMCAwIDEtMS0xdi02Yy0uNzggMC0yLS40Ny0yLTF2LTVhMSAxIDAgMCAxIDEtMVoiLz48L2c+PC9zdmc+)}.scylla-icon--testing{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJDYWxxdWVfNCIgZGF0YS1uYW1lPSJDYWxxdWUgNCI+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNNi41IDYuNWgxMnYxMmgtMTJ6Ii8+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNNC41IDQuNWgxNnYxNmgtMTZ6Ii8+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJtOC41IDEwLjUgNSA1IDExLTEyIi8+PC9nPjwvc3ZnPg==)}.scylla-icon--thumbs-up{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSJjdXJyZW50Q29sb3IiIHN0cm9rZS13aWR0aD0iMiIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIiBjbGFzcz0iZmVhdGhlciBmZWF0aGVyLXRodW1icy11cCI+PHBhdGggZD0iTTE0IDlWNWEzIDMgMCAwIDAtMy0zbC00IDl2MTFoMTEuMjhhMiAyIDAgMCAwIDItMS43bDEuMzgtOWEyIDIgMCAwIDAtMi0yLjN6TTcgMjJINGEyIDIgMCAwIDEtMi0ydi03YTIgMiAwIDAgMSAyLTJoMyIvPjwvc3ZnPg==)}.scylla-icon--thumbs-down{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSJjdXJyZW50Q29sb3IiIHN0cm9rZS13aWR0aD0iMiIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIiBjbGFzcz0iZmVhdGhlciBmZWF0aGVyLXRodW1icy1kb3duIj48cGF0aCBkPSJNMTAgMTV2NGEzIDMgMCAwIDAgMyAzbDQtOVYySDUuNzJhMiAyIDAgMCAwLTIgMS43bC0xLjM4IDlhMiAyIDAgMCAwIDIgMi4zem03LTEzaDIuNjdBMi4zMSAyLjMxIDAgMCAxIDIyIDR2N2EyLjMxIDIuMzEgMCAwIDEtMi4zMyAySDE3Ii8+PC9zdmc+)}.scylla-icon--tip{background-image:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZD0iTTEyIDI0QzUuNCAyNCAwIDE4LjYgMCAxMlM1LjQgMCAxMiAwczEyIDUuNCAxMiAxMi01LjQgMTItMTIgMTJabTAtMjJDNi41IDIgMiA2LjUgMiAxMnM0LjUgMTAgMTAgMTAgMTAtNC41IDEwLTEwUzE3LjUgMiAxMiAyWiIgZmlsbD0iI2ZmZiIvPjxwYXRoIGQ9Ik0xMSAxNmMtLjMgMC0uNS0uMS0uNy0uM2wtMy0zYy0uNC0uNC0uNC0xIDAtMS40LjQtLjQgMS0uNCAxLjQgMGwzIDNjLjQuNC40IDEgMCAxLjQtLjIuMi0uNC4zLS43LjNaIiBmaWxsPSIjZmZmIi8+PHBhdGggZD0iTTExIDE2Yy0uMyAwLS41LS4xLS43LS4zLS40LS40LS40LTEgMC0xLjRsNi02Yy40LS40IDEtLjQgMS40IDAgLjQuNC40IDEgMCAxLjRsLTYgNmMtLjIuMi0uNC4zLS43LjNaIiBmaWxsPSIjZmZmIi8+PC9zdmc+)}.scylla-icon--training{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJDYWxxdWVfMiIgZGF0YS1uYW1lPSJDYWxxdWUgMiI+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNMTcuNSAxNS41SC41di0xM2gxOE01LjUgMjVsNC00LjMgNCA0LjMiLz48Y2lyY2xlIGN4PSIyMSIgY3k9IjQiIHI9IjIuNSIgc3R5bGU9InN0cm9rZS1taXRlcmxpbWl0OjEwO2ZpbGw6bm9uZTtzdHJva2U6Z3JheSIvPjxwYXRoIGNsYXNzPSJjbHMtMSIgZD0iTTIzLjQxIDcuNWgtMS41MkwyMSA5bC0uOS0xLjVIMTNBMS44IDEuOCAwIDAgMCAxMS41IDlhMS44IDEuOCAwIDAgMCAxLjUgMS41aDQuNXYxMy4yNEExLjQxIDEuNDEgMCAwIDAgMTkgMjVhMS40MiAxLjQyIDAgMCAwIDEuNS0xLjIyIDEuNTMgMS41MyAwIDAgMCAzIDB2LTcuMTFhMS4xMSAxLjExIDAgMCAwIDEuMDktMS4xOFY4LjY3YTEuMTggMS4xOCAwIDAgMC0xLjE4LTEuMTdaTTkuNSAxNS40NHY1LjM4Ii8+PC9nPjwvc3ZnPg==)}.collapsible-button .side-nav__content .toctree-checkbox:checked~label i,.collapsible-button .side-nav__content i,.scylla-icon--triangle-down,.side-nav__content .collapsible-button i,.side-nav__content .scylla-icon--expand,.side-nav__content .toctree-checkbox:checked~label .collapsible-button i,.side-nav__content .toctree-checkbox:checked~label .scylla-icon--expand{background-image:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTAiIGhlaWdodD0iNSIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cGF0aCBmaWxsLXJ1bGU9ImV2ZW5vZGQiIGNsaXAtcnVsZT0iZXZlbm9kZCIgZD0ibTAgMCA1IDUgNS01SDBaIiBmaWxsPSIjM0EyRDU1Ii8+PC9zdmc+)}.scylla-icon--university{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJDYWxxdWVfNCIgZGF0YS1uYW1lPSJDYWxxdWUgNCI+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJtMS41IDguNSAxMS00IDExIDR2M2wtMTEgNC0xMS00di0zeiIvPjxwYXRoIGNsYXNzPSJjbHMtMSIgZD0iTTUuNSAxMi41djVhMTIuNDYgMTIuNDYgMCAwIDAgNyAyIDExLjIgMTEuMiAwIDAgMCA3LTJ2LTUiLz48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Im0xMy41IDkuNSA4IDEuMjN2OC43N00yMi41IDE2LjV2MyIvPjwvZz48L3N2Zz4=)}.scylla-icon--users-blog{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMntmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJDYWxxdWVfNCIgZGF0YS1uYW1lPSJDYWxxdWUgNCI+PHBhdGggc3R5bGU9InN0cm9rZS13aWR0aDouOThweDtmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kIiBkPSJNMjMuNSAyLjVoLTIydjE2aDEzdjQuMTdsNC4wNC00LjE3IDQuOTYtLjA0VjIuNXoiLz48cGF0aCBjbGFzcz0iY2xzLTIiIGQ9Ik0xMC44NSA4QTEwLjM4IDEwLjM4IDAgMCAxIDExIDkuNWMwIDIuNDctMS4yMSA0LTMgNHMtMy41LTItMy41LTQuNWE0LjE4IDQuMTggMCAwIDEgMC0xIi8+PHBhdGggY2xhc3M9ImNscy0yIiBkPSJNNS4yIDUuMDdhMy4yMiAzLjIyIDAgMCAxIDIuNS0xIDMuMTYgMy4xNiAwIDAgMSAyLjQgMSA2LjIyIDYuMjIgMCAwIDEgMS4zIDMuODEuNzQuNzQgMCAwIDAtLjQyIDBjMC0uMjQgMC0uNDQtLjA1LS42NmgwQTMgMyAwIDAgMSAxMCA2Ljl2LS4yNGwtLjIxLjEyQTkuNjIgOS42MiAwIDAgMSA0LjczIDhhLjI1LjI1IDAgMCAwLS4yMi4wOWMtLjEzLjE0LS4wOS4zNyAwIC42MXYuMThhLjg1Ljg1IDAgMCAwLS4zMiAwQTUuMzcgNS4zNyAwIDAgMSA1LjIgNS4wN1pNNC41MSA4LjkzYy0uMzUgMC0uNTcuMDUtLjYxLjQ0YTEuMTcgMS4xNyAwIDAgMCAuNzMgMS4zTTExIDguOTNjLjM2IDAgLjU3LjA1LjYyLjQ0YTEuMTcgMS4xNyAwIDAgMS0uNzQgMS4zTTYuMzEgMTQuMTN2LS44NE05LjI1IDEzLjE5di45NE0yLjQyIDE4Yy4xMy0xLjE1LjU4LTIuNTIgMS41OC0zYTE0LjcxIDE0LjcxIDAgMCAxIDIuMzEtLjgyTTEzLjUgMThjLS4xMy0xLjE1LS41MS0yLjUyLTEuNS0zcy0yLjUtMS0yLjUtMSIvPjxwYXRoIGNsYXNzPSJjbHMtMiIgZD0iTTkuMzQgMTQuMjJhMi4yMyAyLjIzIDAgMCAxLTEuNTYuNjEgMi4zMiAyLjMyIDAgMCAxLTEuNTUtLjU5TTIxLjUgNi41aC03TTIxLjUgOS41aC03TTE4LjUgMTIuNWgtNCIvPjwvZz48L3N2Zz4=)}.admonition.caution .admonition-title:before,.admonition.warning .admonition-title:before,.scylla-icon--warning{background-image:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PG1hc2sgaWQ9ImEiIG1hc2stdHlwZT0iYWxwaGEiIG1hc2tVbml0cz0idXNlclNwYWNlT25Vc2UiIHg9IjAiIHk9IjEiIHdpZHRoPSIyNCIgaGVpZ2h0PSIyMSI+PHBhdGggZD0iTTMuNSAyMmMtLjUgMC0xLS4xLTEuNS0uNEMuNiAyMC44LjEgMTguOS45IDE3LjVMOS40IDMuM2MuMy0uNC42LS44IDEtMSAuNy0uNCAxLjUtLjUgMi4zLS4zLjguMiAxLjQuNyAxLjkgMS40TDIzIDE3LjVjLjMuNS40IDEgLjQgMS41IDAgLjgtLjMgMS42LS45IDIuMS0uNS42LTEuMi45LTIgLjloLTE3Wm03LjYtMTcuNkwyLjcgMTguNWMtLjMuNS0uMSAxLjEuNCAxLjQuMS4xLjMuMS40LjFoMTYuOWMuMyAwIC41LS4xLjctLjMuMi0uMi4zLS40LjMtLjcgMC0uMiAwLS4zLS4xLS41TDEyLjkgNC40Yy0uMy0uNS0uOS0uNi0xLjQtLjQtLjIuMS0uMy4yLS40LjRaIiBmaWxsPSIjMDYxOTM4Ii8+PHBhdGggZD0iTTEyIDE0Yy0uNiAwLTEtLjQtMS0xVjljMC0uNi40LTEgMS0xczEgLjQgMSAxdjRjMCAuNi0uNCAxLTEgMVpNMTIgMThjLS4zIDAtLjUtLjEtLjctLjMtLjItLjItLjMtLjQtLjMtLjcgMC0uMSAwLS4zLjEtLjQuMS0uMS4xLS4yLjItLjMuMS0uMS4yLS4yLjMtLjIuMi0uMS40LS4xLjYtLjEuMSAwIC4xIDAgLjIuMS4xIDAgLjEgMCAuMi4xIDAgMCAuMS4xLjIuMS4xLjEuMi4yLjIuMyAwIC4xLjEuMy4xLjQgMCAuMy0uMS41LS4zLjctLjMuMi0uNS4zLS44LjNaIiBmaWxsPSIjMDYxOTM4Ii8+PC9tYXNrPjxnIG1hc2s9InVybCgjYSkiPjxwYXRoIGZpbGw9IiMwNjE5MzgiIGQ9Ik0wIDBoMjR2MjRIMHoiLz48L2c+PC9zdmc+)}.scylla-icon--webinars{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMntmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJDYWxxdWVfNCIgZGF0YS1uYW1lPSJDYWxxdWUgNCI+PHBhdGggc3R5bGU9InN0cm9rZS1taXRlcmxpbWl0OjEwO2ZpbGw6bm9uZTtzdHJva2U6Z3JheSIgZD0iTTEuNSA1LjVoMjJ2MTRoLTIyeiIvPjxwYXRoIGNsYXNzPSJjbHMtMiIgZD0iTTkuNDcgMjAuNXYxLjg4TTE1LjUgMjAuNXYyTTYuNSAyMi41aDEyIi8+PHBhdGggc3R5bGU9ImZpbGw6Z3JheSIgZD0ibTkgOSA3LjUgMy41M0w5IDE2Vjl6Ii8+PC9nPjwvc3ZnPg==)}.scylla-icon--whitepapers{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMntmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJDYWxxdWVfNCIgZGF0YS1uYW1lPSJDYWxxdWUgNCI+PHBhdGggc3R5bGU9ImZpbGw6Z3JheSIgZD0iTTggOWg4djJIOHoiLz48cGF0aCBjbGFzcz0iY2xzLTIiIGQ9Ik0xNC4wNiAxLjUgMy41IDEuNTJWMjMuNWgxN1Y3bC02LjQ0LTUuNXoiLz48cGF0aCBkPSJNMTQuMzIgMS40MnYzLjM3YTIuMDYgMi4wNiAwIDAgMCAyLjA4IDIuMWgzLjY3IiBzdHlsZT0ic3Ryb2tlLW1pdGVybGltaXQ6MTA7ZmlsbDpub25lO3N0cm9rZTpncmF5Ii8+PHBhdGggY2xhc3M9ImNscy0yIiBkPSJNNi41IDE5LjVoNE0xMy41IDE5LjVoNE02LjUgMTYuNWg0TTEzLjUgMTYuNWg0TTYuNSAxMy41aDRNMTMuNSAxMy41aDQiLz48L2c+PC9zdmc+)}.scylla-icon--workshop{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMSwuY2xzLTJ7ZmlsbDpub25lO3N0cm9rZTojNGQ0ZDRkfS5jbHMtMXtzdHJva2UtbWl0ZXJsaW1pdDoxMH0uY2xzLTJ7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJDYWxxdWVfNCIgZGF0YS1uYW1lPSJDYWxxdWUgNCI+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNMS41IDUuNWgyMnYxNGgtMjJ6Ii8+PHBhdGggY2xhc3M9ImNscy0yIiBkPSJtOS41IDE5LjUtLjAzIDIuODhNMTUuNSAxOS41djNNNi41IDIyLjVoMTIiLz48cGF0aCBzdHlsZT0iZmlsbDojNGQ0ZDRkIiBkPSJtNCA4IDIgOCAuOTctMy45NUwxMSAxMiA0IDh6Ii8+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJtNi40NyAxMS4zNCAzLjM3IDQuMjgiLz48L2c+PC9zdmc+)}.button{background:transparent;border:1px solid #3a2d55;border-radius:4px;color:#3a2d55;display:inline;font-size:14px;letter-spacing:1px;line-height:21px;margin:0;padding:12px 14px}.button:focus,.button:hover{background:transparent;color:#3a2d55;text-decoration:none}.button--reverse{background:#fff;border:0}.button--reverse:focus,.button--reverse:hover{background:#fff}.tooltip{background-color:rgba(0,0,0,.56);border-radius:4px;font-size:12px;padding:6px}.tooltip:before{display:none!important}.tooltip:empty{display:none!important}.has-tip{border:0;cursor:pointer}.scylla-dropdown{color:#23263b;font-size:14px;line-height:20px}.scylla-dropdown a,.scylla-dropdown a:focus,.scylla-dropdown a:hover{color:#23263b!important;padding:0!important}.scylla-dropdown__item{font-size:16px;padding:15px}.scylla-dropdown__title{align-items:center;display:flex!important;position:static!important}.scylla-dropdown__title:after{display:none!important}.scylla-dropdown__title .chevron{min-height:5px;width:10px}.scylla-dropdown__content{background:#fff;border:0;border-radius:8px;box-shadow:0 4px 25px rgba(0,0,0,.15);font-size:16px;list-style:none;margin-top:15px;overflow:hidden;padding:16px 0;width:max-content}.scylla-dropdown__content li{padding:7px 16px}.scylla-dropdown__content .contents.local>ul>li a:before,.scylla-dropdown__content .secondary-side-nav__content li a:before,.scylla-dropdown__content li .admonition-title:before,.scylla-dropdown__content li .scylla-icon,.secondary-side-nav__content .scylla-dropdown__content li a:before{margin-right:10px}.enlarge-image{cursor:zoom-in}.enlarge-image-reveal{background:transparent;border:none;cursor:zoom-out;padding:0;text-align:center;width:fit-content}.enlarge-image-reveal img{background-color:#fff;padding:15px}.header{background-color:#fff;box-shadow:0 2px 22px rgba(74,93,166,.15);justify-content:space-between;padding:12.75px 0;position:fixed;width:100%;z-index:99}.header,.header-logo{align-items:center;display:flex}.header-logo{margin-left:20px;width:auto}.header-logo__img{width:110px}.header-logo__bar{background-color:#3a2d55;border-left:1px solid #3a2d55;height:11.56px;margin:0 7.5px;width:0}.header-logo__text{color:#3a2d55;font-size:10.11px;letter-spacing:.722408px;line-height:12px;text-transform:uppercase}.header-navigation{display:none}.header-button{display:none;margin-left:15px;text-transform:uppercase}.header-search-box{display:none;margin-right:20px;width:200px}.scylla-dropdown--header .scylla-dropdown__item{font-size:14px}.scylla-dropdown--header .scylla-dropdown__title{text-transform:uppercase}.scylla-dropdown--header .scylla-dropdown__title .chevron{margin-left:10px}.contents.local>ul>li .scylla-dropdown--header .scylla-dropdown__content a:before,.scylla-dropdown--header .scylla-dropdown__content .admonition-title:before,.scylla-dropdown--header .scylla-dropdown__content .contents.local>ul>li a:before,.scylla-dropdown--header .scylla-dropdown__content .scylla-icon,.scylla-dropdown--header .scylla-dropdown__content .secondary-side-nav__content li a:before,.secondary-side-nav__content li .scylla-dropdown--header .scylla-dropdown__content a:before{min-height:20px;width:20px}@media screen and (min-width:1024px){.header{padding:18px 0}.header-logo__img{width:152px}.header-logo__bar{height:16px;margin:0 10px}.header-logo__text{font-size:14px;letter-spacing:.722408px;line-height:12px;text-transform:uppercase}.header-navigation{align-items:center;display:flex;justify-content:center}.header-search-box{display:block}}@media screen and (min-width:1200px){.header-logo{margin-left:30px;width:357px}.header-search-box{margin-right:30px;max-width:20%;width:318px}.header-button{display:block}}.side-nav{background:#fff;display:none;height:100vh;left:0;line-height:24px;max-height:calc(100vh - 50px);overflow-y:auto;padding:20px 20px 0;position:fixed;top:50px;width:100%;z-index:100}.side-nav__title{font-weight:700;margin-bottom:20px}.side-nav__content{max-width:90%;overflow-wrap:break-word}.side-nav__content label,.side-nav__content label i{margin:0;padding:0}.side-nav__content label{font-size:inherit;line-height:1;margin-left:5px;max-height:5px}.collapsible-button .side-nav__content i,.side-nav__content .collapsible-button i,.side-nav__content .scylla-icon--expand{height:5px;vertical-align:top;width:10px}.side-nav__content .toctree-checkbox{display:none;position:absolute;right:20px}.side-nav__content .toctree-checkbox~ul{display:none;margin-right:20px}.side-nav__content .toctree-checkbox:checked~ul{display:block}.side-nav__content ul{margin:0}.side-nav__content a{color:#23263b}.side-nav__content a:hover{color:#3c4fe0;font-weight:400}.side-nav__content li{list-style:none;padding:0 0 24px}.side-nav__content li.has-children{align-items:center;display:flex;flex-wrap:wrap}.side-nav__content li.has-children>a{max-width:calc(100% - 15px)}.side-nav__content li.has-children.current{padding-bottom:20px}.side-nav__content li.has-children:hover>a{color:#3c4fe0}.side-nav__content li.has-children:hover>.toctree-checkbox~label i{filter:invert(38%) sepia(71%) saturate(6789%) hue-rotate(231deg) brightness(90%) contrast(95%)}.side-nav__content li.current-page>a{color:#3c4fe0}.side-nav__content li.current-page>.toctree-checkbox:checked~label i{filter:invert(38%) sepia(71%) saturate(6789%) hue-rotate(231deg) brightness(90%) contrast(95%)}.side-nav__content li ul{margin-top:18px;width:100%}.side-nav__content li ul li{border-left:1px solid #3c4fe0;padding:4px 0 4px 13px}.side-nav__content li ul ul{margin-left:0}.side-nav__content li .label{display:none}.side-nav__versions{max-width:90%}.side-nav__search,.side-nav__versions .dropdown{margin-bottom:20px}.collapsible-button{background:#fff;background-color:#fff;border:0;border-radius:8px;border-radius:50%;bottom:10px;box-shadow:0 4px 25px rgba(0,0,0,.15);cursor:pointer;display:none;font-size:0;left:300px;overflow:hidden;padding:13.5px;position:fixed}.collapsible-button i{height:16px;margin:0;width:16px}.side-nav--collapsed .collapsible-button{border-radius:0 20px 20px 0;left:-10px}.side-nav--collapsed .collapsible-button i{transform:rotate(180deg)}.layout--has-banner .side-nav{max-height:calc(100vh - 92.5px)}@media screen and (min-width:1024px){.side-nav{background-color:#f6f8ff;display:block;height:100%;left:auto;max-height:100vh;max-height:calc(100vh - 80px);padding:30px 40px;top:80px;width:286px;z-index:25}.side-nav__content{max-width:100%;padding-bottom:180px}.side-nav__search{display:none}.side-nav__versions{max-width:100%}.toctree-checkbox{right:40px}.layout--has-banner .side-nav{max-height:calc(100vh - 150px)}}@media screen and (min-width:1200px){.side-nav{width:357px}.side-nav--collapsed{background-color:transparent;padding-left:0;padding-right:0;width:126px}.side-nav--collapsed .side-nav-content{display:none}.collapsible-button{display:block}}.side-nav-toggle{cursor:pointer;display:block;margin-right:20px;position:relative;z-index:300}@media screen and (min-width:1024px){.side-nav-toggle{display:none}}.secondary-side-nav{display:none;height:100%;line-height:24px;padding:20px;width:100%}.secondary-side-nav__content{overflow-wrap:break-word}.secondary-side-nav__content ul{list-style:none;margin:0}.secondary-side-nav__content li{border-bottom:1px solid rgba(90,94,154,.1);display:none;padding:10px 0;word-break:break-word}.secondary-side-nav__content li:last-child{border:0}.secondary-side-nav__content li .label{display:none}.secondary-side-nav__content li a{align-items:baseline;color:#b3bac5;display:flex;font-size:14px}.secondary-side-nav__content li a:before{content:"";filter:invert(40%) sepia(11%) saturate(2157%) hue-rotate(198deg) brightness(89%) contrast(87%)!important;flex-shrink:0;margin-right:10px;min-height:10px;opacity:.5;width:6px}.secondary-side-nav__content li a.current,.secondary-side-nav__content li a:hover{color:#23263b;font-weight:400}.secondary-side-nav__content li a.current:before,.secondary-side-nav__content li a:hover:before{filter:brightness(0);opacity:1}.secondary-side-nav__content li a.current{font-weight:700}.secondary-side-nav__content>ul>li>ul>li{display:block}.secondary-side-nav__content>ul>li{border:0;display:block}.secondary-side-nav__content>ul>li>a{display:none}@media screen and (min-width:1200px){.secondary-side-nav{display:block;max-height:100vh;max-height:calc(100vh - 80px);overflow-y:auto;padding:60px 60px 60px 20px;position:fixed;top:80px;width:286px}.secondary-side-nav__content{padding-bottom:180px}.layout--has-banner .secondary-side-nav{max-height:calc(100vh - 150px)}}.layout{display:flex}.pre-content{align-items:center;display:flex;justify-content:space-between;margin-bottom:20px}.content{margin-top:50px;max-width:1440px;overflow-wrap:break-word;padding:20px;scroll-margin-top:50px;width:100%}.content .line-block,.content p{line-height:28px;margin-bottom:20px}.content ul{list-style:none}.content ul li:before{color:#b3bac5;content:"•";float:left;font-family:FontAwesome;font-size:20px;font-weight:700;margin-left:-1em;margin-top:-2px;width:1em}.content ul ul{list-style:circle}.content ul ul li:before{content:""}.content ol ol{list-style:lower-latin}.content img{margin-bottom:30px}.content section{margin-top:-50px;padding-top:50px}.content .inline-icon.fa-check{color:#42c4e6}.layout--full-width .content{max-width:100%;padding:0;width:100%}.layout--full-width .content .hero-wrapper,.layout--full-width .content .topics-grid{max-width:1190px}.layout--full-width .content.content--collapsed{margin-left:0}.layout--full-width:not(.layout--sidebar) .content{margin-left:0}.layout--has-banner .content{scroll-margin-top:92.5px}.layout--has-banner .content section{margin-top:-92.5px;padding-top:92.5px}.landing__content{padding:0 16px}@media screen and (min-width:1024px){.content{margin-left:286px;margin-top:80px;min-height:calc(100vh - 260px);padding-bottom:100px;scroll-margin-top:80px;width:calc(100% - 286px)}.content section{margin-top:-80px;padding-top:80px}}@media screen and (min-width:1200px){.content{margin-left:357px;padding:60px 40px 40px;width:calc(100% - 643px)}.content--collapsed{margin-left:126px;width:calc(100% - 412px)}.pre-content{margin-bottom:10px}.layout--has-banner .content{scroll-margin-top:150px}.layout--has-banner .content section{margin-top:-150px;padding-top:150px}.landing__content{padding:0 60px}.landing--floating .landing__content{position:relative;top:-70px}}.contents.local>ul{margin-bottom:30px;margin-left:0}.contents.local>ul>li{border-bottom:1px solid rgba(90,94,154,.1);padding:10px 0;word-break:break-word}.contents.local>ul>li:before{content:""}.contents.local>ul>li:last-child{border:0}.contents.local>ul>li ul{display:none}.contents.local>ul>li p{margin:0}.contents.local>ul>li a{font-size:14px}.contents.local>ul>li a:before{content:"";filter:invert(40%) sepia(11%) saturate(2157%) hue-rotate(198deg) brightness(89%) contrast(87%)!important;margin-right:10px;min-height:10px;opacity:.5;width:10px}.contents.local>ul>li a.current:before,.contents.local>ul>li a:hover:before{filter:brightness(0);opacity:1}.topic-title{color:rgba(35,38,59,.75);font-size:10px;letter-spacing:1.5px;margin-bottom:0;text-transform:uppercase}.notice{margin-top:40px}.footer{background-color:#fff;box-shadow:0 -4px 10px hsla(0,0%,82%,.25);padding:30px 0;position:relative;width:100%;z-index:50}.footer-group{margin:0 auto;max-width:1030px;padding:0 20px}.footer-top{align-items:center;border-bottom:1px solid rgba(0,0,0,.1);display:flex;flex-wrap:wrap;justify-content:space-between;padding-bottom:8px;text-align:center}.footer-logo{margin-bottom:30px;width:100%}.footer-logo img{float:left;height:36px}.footer-links{text-align:left}.footer-links__link{color:#333;font-size:12px;font-weight:500;letter-spacing:2.4px;margin-right:16px;text-transform:uppercase}.footer-actions{align-items:center;display:flex;justify-content:space-between;width:90px}.footer-actions__link{color:#000}.footer-actions__link img{height:23px}.footer-bottom{color:#979797;display:flex;flex-wrap:wrap;font-size:12px;font-style:normal;font-weight:400;justify-content:center;letter-spacing:1.4px;line-height:23px;padding:20px 0 10px;text-align:center;text-transform:uppercase}@media screen and (max-width:510px){.footer-links{margin-bottom:20px}}@media screen and (min-width:1024px){.footer{padding:30px 0}.footer-group{padding:0}.footer-top{padding-bottom:30px}.footer-logo{margin:0;width:auto}.footer-links{padding:0 40px}.footer-links__link{font-size:14px;margin-right:28px}.footer-actions{width:110px}.footer-actions__link img{height:28px}.footer-bottom .footer-bottom__copyright,.footer-bottom .footer-bottom__last-updated,.footer-bottom .footer-bottom__version{padding:0 10px}.footer-bottom .footer-bottom__copyright{border-left:none}}.not-found{background-color:#f6f8ff;height:100%;overflow:hidden}.not-found__icon{display:block;margin:40px auto;max-width:300px}.not-found__text{text-align:center}.not-found__text h1{font-size:60px;line-height:1}.not-found__text p{margin:30px 0;width:100%}.not-found__button{text-transform:uppercase}.admonition{border-radius:4px;box-shadow:0 4px 4px rgba(0,0,0,.12);color:rgba(0,0,0,.56);font-size:14px;line-height:20px;margin-bottom:30px;overflow:auto;padding:20px;position:relative}.admonition:before{bottom:0;content:" ";left:0;position:absolute;right:0;top:0;z-index:-1}.admonition-title{color:#23263b;margin-bottom:0!important}.admonition-title:before{content:"";margin-right:8px;min-height:24px;width:24px}.admonition p:not(.admonition-title){margin-bottom:0!important;margin-left:32px}.admonition.tip{border:1px solid #43a047}.admonition.tip:before{border-left:8px solid rgba(67,160,71,.4)}.admonition.tip .admonition-title:before{filter:invert(47%) sepia(11%) saturate(2286%) hue-rotate(73deg) brightness(109%) contrast(88%)}.admonition.note{border:1px solid #1976d2}.admonition.note:before{border-left:8px solid rgba(25,118,210,.4)}.admonition.note .admonition-title:before{filter:invert(44%) sepia(55%) saturate(2310%) hue-rotate(191deg) brightness(81%) contrast(103%)}.admonition.caution{border:1px solid #ffab00}.admonition.caution:before{border-left:8px solid rgba(255,171,0,.4)}.admonition.caution .admonition-title:before{filter:invert(77%) sepia(56%) saturate(3332%) hue-rotate(357deg) brightness(98%) contrast(108%)}.admonition.warning{border:1px solid #e74c3c}.admonition.warning:before{border-left:8px solid rgba(231,76,60,.4)}.admonition.warning .admonition-title:before{filter:invert(41%) sepia(42%) saturate(6427%) hue-rotate(343deg) brightness(99%) contrast(83%)}.breadcrumbs{margin-bottom:0;text-transform:uppercase}.breadcrumbs .bread__item,.breadcrumbs .bread__item:not(.bread__item--last):after,.breadcrumbs a{color:#23263b;font-size:12px;font-weight:400;letter-spacing:1.5px;line-height:2;margin:0;padding:0}.breadcrumbs .bread__item:before{display:none}.breadcrumbs .bread__item:not(.bread__item--last):after{content:"/";margin:0 5px;opacity:1;position:relative}.breadcrumbs .bread__highlight{color:#3c4fe0}.breadcrumbs .bread__highlight:hover{font-weight:700;text-decoration:none}code{background-color:#f7f8f9;border:none;border-radius:4px;color:#23263b;font-size:14px}code.download{background:none;color:#23263b}.highlight{background:transparent!important}.highlight pre{background-color:#f7f8f9;border-radius:8px;color:#23263b;font-size:14px;line-height:26px;margin-bottom:30px;overflow:auto;padding:16px}.highlight a.copybtn{right:1em;top:1em}.highlighttable{background-color:#f7f8f9;border-radius:16px;box-shadow:none}.highlighttable tbody{background-color:transparent;border:0}.highlighttable tbody td{padding:15px!important}.highlighttable tbody tr{border-top:none}.highlighttable .linenos{background-color:#f7f8f9;color:#5a7184;width:50px}.highlighttable .linenos span{line-height:26px}.highlighttable .highlight pre{background-color:transparent;margin:0;padding:0}.highlighttable .highlight a.copybtn{right:.2em;top:.2em}.hide-copy-button .copybtn{display:none}.sphinx_collapse__label{display:flex!important;flex-direction:row-reverse;font-size:medium;font-weight:700;justify-content:flex-end;margin-left:0!important}.sphinx_collapse__icon{margin-left:5px;margin-right:0}.sphinx_collapse__input:checked~.sphinx_collapse__label,.sphinx_collapse__label:hover{color:#3c4fe0}.sphinx_collapse__input:checked~.sphinx_collapse__label .sphinx_collapse__icon,.sphinx_collapse__label:hover .sphinx_collapse__icon{border-top-color:#3c4fe0}.sphinx_collapse__content{margin-top:10px}.contribute{margin:0 0 20px}.contribute__item{font-size:14px;list-style:none;padding-bottom:10px}.contribute__item .icon{margin-right:5px}.content-navigation{display:flex;justify-content:space-between;margin-top:40px}.navigation{max-width:50%;word-break:break-word}.navigation,.navigation__link{display:flex}.navigation__title{word-wrap:break-word;color:#23263b;font-size:12px;font-weight:500;letter-spacing:1.5px;line-height:24px;text-transform:uppercase}.navigation__title .colored{color:#42c4e6}.navigation__button{background:#fff;background-color:#fff;border:0;border-radius:8px;box-shadow:0 4px 25px rgba(0,0,0,.15);cursor:pointer;display:none;font-size:0;height:fit-content;overflow:hidden;padding:13.5px 16.5px}.navigation__button i{height:16px;margin:0;width:10px}.navigation--prev .navigation__title{margin-left:15px}.navigation--next .navigation__title{margin-right:15px;text-align:right}@media screen and (min-width:1200px){.navigation__title{display:inline-block}.navigation__button{display:block}.navigation--next .navigation__title{text-align:left}}.scylla-dropdown--versions .scylla-dropdown__item{background:#fff;border-radius:8px;box-shadow:0 28px 32px rgba(0,0,0,.06);width:100%}.scylla-dropdown--versions .scylla-dropdown__title{align-items:center;display:flex;justify-content:space-between}.scylla-dropdown--versions .scylla-dropdown__title .chevron{min-height:12px;transform:rotate(90deg);width:8px}@media screen and (min-width:1024px){.scylla-dropdown--versions .scylla-dropdown__item{box-shadow:none}}.feedback-container{font-size:16px;margin-top:40px;text-align:left}.feedback-container__title{font-weight:700;margin-bottom:5px!important}.feedback-container__button{background:#fff;border:0;border-radius:8px;box-shadow:0 4px 25px rgba(0,0,0,.15);cursor:pointer;margin:4px;overflow:hidden;padding:8px}.feedback-container__button.active{border:1px solid #3c4fe0}.feedback-container__icon{height:20px;width:20px}.feedback-container__message{font-size:16px;margin-top:10px}.hero{background:#f6f8ff;margin-bottom:30px;overflow:hidden;padding:30px 16px;text-align:left}.hero__title{font-size:28px;font-weight:500;line-height:38px;margin-bottom:14px;max-width:229px}.hero__text{font-size:16px;line-height:26px;max-width:343px}.hero__text a{border-bottom:1px dotted #23263b;color:#23263b}.hero__text p{margin-bottom:0!important}.hero__img{position:absolute;right:-18px;top:20px}.hero__img img{margin-bottom:0!important;width:124px}.hero__button{margin-top:20px;text-transform:uppercase}.hero__button .icon{margin-right:5px}.hero__search-box{box-shadow:0 4px 25px rgba(0,0,0,.02);margin-top:20px}.hero-wrapper{align-items:center;display:flex;justify-content:space-between;margin:0 auto;position:relative}@media screen and (min-width:640px){.hero{padding:60px 16px}.hero__title{font-size:32px;line-height:42px;max-width:482px}.hero__text{font-size:18px;line-height:26px;max-width:482px}.hero__img{display:block;position:static}.hero__img img{height:100%;width:295px}.hero .hero-wrapper{flex-direction:row-reverse}.hero .landing--floating .hero{padding:30px 16px 100px}}@media screen and (min-width:1024px){.hero{padding:60px}}.label{background-color:#23263b;border:0;border-radius:4px;color:#fff;font-size:inherit}.label--note{background-color:#1976d2}.label--tip{background-color:#43a047}.label--caution{background-color:#ffab00}.label--warning{background-color:#e74c3c}.last-updated{color:#4458a3;font-size:12px;letter-spacing:1.5px;margin:10px 0;text-transform:uppercase}.last-updated__icon{font-size:14px}@media screen and (min-width:1024px){.last-updated{float:right;margin:0}}.panel{border:0;border-radius:4px;margin-bottom:30px}.promo-banner{background-color:#4458a3;background-image:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTQ0MCIgaGVpZ2h0PSI3MCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48bWFzayBpZD0iYSIgbWFzay10eXBlPSJhbHBoYSIgbWFza1VuaXRzPSJ1c2VyU3BhY2VPblVzZSIgeD0iMCIgeT0iMCIgd2lkdGg9IjE0NDAiIGhlaWdodD0iNzAiPjxwYXRoIGZpbGw9IiM0NDU4QTMiIGQ9Ik0wIDBoMTQ0MHY3MEgweiIvPjwvbWFzaz48ZyBtYXNrPSJ1cmwoI2EpIiBmaWxsPSIjNTA2NEFFIj48cGF0aCBkPSJNLTE5MyAyMDEuODg0IDEuNS0xMzUgMzU3LjQzNiA3MC41bC0xOTQuNSAzMzYuODg0ek0xMDkyLjkyLTM4LjAwOSA5NzIuODAzLTI0Ni4wNTcgNDAyLjk5NiA4Mi45MiA1MjMuMTEzIDI5MC45N3oiLz48cGF0aCBkPSJtMTAzOC0zOC4wMDkgMTIwLjExNy0yMDguMDQ5IDU2OS44MDcgMzI4Ljk3OS0xMjAuMTE3IDIwOC4wNDl6Ii8+PC9nPjwvc3ZnPg==);background-position:50%;background-repeat:no-repeat;background-size:cover;display:none;overflow:hidden;position:fixed;top:0;width:100%;z-index:900}.promo-banner__icon{margin-right:15px}.promo-banner__icon img{height:40px}.promo-banner__title{color:#fff;font-size:12px;line-height:16px;margin-right:15px}.promo-banner__button{background:#fff;border-radius:4px;font-size:12px;min-width:max-content;padding:5px}.promo-banner__close{display:none;position:absolute;right:16px;top:16px}.contents.local>ul>li .promo-banner__close a:before,.promo-banner__close .admonition-title:before,.promo-banner__close .contents.local>ul>li a:before,.promo-banner__close .scylla-icon,.promo-banner__close .secondary-side-nav__content li a:before,.secondary-side-nav__content li .promo-banner__close a:before{filter:brightness(100%);height:34px;width:34px}.promo-banner__close:hover{cursor:pointer;filter:opacity(.8)}.promo-banner-wrapper{align-items:center;display:flex;justify-content:center;padding:5.85px 20px}@media(min-width:1024px){.promo-banner__title{font-size:18px;line-height:23px}.promo-banner__button{font-size:14px;padding:8.5px}.promo-banner__close{display:block}.promo-banner-wrapper{flex-direction:unset;padding:16px}}.custom-scroll-bar::-webkit-scrollbar{background-color:transparent;width:5px}.custom-scroll-bar::-webkit-scrollbar-thumb{background-color:#b3bac5;-webkit-border-radius:8px;border-radius:8px}.search-box{background:#f7f8f9;border-radius:4px;display:flex;padding:10px 15px}.search-box--hero{background-color:#fff;padding:12px 14px}.search-box:before{background-image:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZD0iTTEwLjUgMThhNy41IDcuNSAwIDEgMCAwLTE1IDcuNSA3LjUgMCAwIDAgMCAxNVpNMjEgMjFsLTUuMi01LjIiIHN0cm9rZT0iIzAwMCIgc3Ryb2tlLXdpZHRoPSIyIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiLz48L3N2Zz4=);background-repeat:no-repeat;background-size:contain;content:"";display:inline-block;filter:brightness(0);margin-top:2px;min-height:18px;min-width:18px;vertical-align:middle;width:20px}.search-box .er-dummy-search,.search-box .er-dummy-search-box,.search-box .er-search-form,.search-box ci-search,.search-box input{margin:0!important;width:100%!important}.search-box input{background:transparent!important;color:rgba(80,80,80,.5)!important;font-size:14px!important;padding:0!important}.search-box input::placeholder{color:rgba(80,80,80,.5)!important;opacity:1!important}.search-box button{display:none!important}.er_search_suggestions{background:#fff;border:0;border:0!important;border-radius:8px;box-shadow:0 4px 25px rgba(0,0,0,.15);overflow:hidden}.er_search_suggestions .er-search-result-box{border-width:1px!important;padding-bottom:10px!important;padding-top:10px!important}.er_search_suggestions .er-search-result-box:hover{background:#f7f8f9!important}.er_search_suggestions .er_more_result_btn{cursor:pointer}.er_search_suggestions h3{font-size:16px!important}.er-search-content{padding:20px!important}#er_search_results .er-search-result-box{display:block!important;margin:10px auto 0!important;width:100%!important}#er_search_results .text,#er_search_results .title a,#er_search_results .url a{max-width:100%!important}#search-result-input-form{max-width:800px!important}#er_search_button{text-align:center}#er_clear_input{right:0!important;top:0!important}.er-facet-header{background-color:transparent!important;border:0!important;padding:0 0 8px!important}.er-facet-val{padding:5px 2px!important}.er-facet-val input{display:block!important;margin:0}#er_search_pagination{margin-top:20px!important}#er_search_pagination li.er-paginator-list.er-active{border-bottom:0!important;font-weight:700}.er-suggestion-sm .er_search_input_dummy{margin:0!important}.er-suggestion-sm .er_search_button_dummy{border:0!important}#er_gcs_mobile_model_container .er-facet-values .er-facet-val{align-items:baseline}@media screen and (min-width:640px){.er-facets{display:none;max-width:300px!important;min-width:auto!important;width:auto!important}}@media screen and (min-width:1024px){.er-suggestions{left:15px!important}}@media screen and (min-width:1200px){.er-facets{display:block;position:fixed!important}.er-facet-count{display:none}}.sphinx-tabs{margin-bottom:30px}.sphinx-tabs-tab{border-bottom:1px solid rgba(0,0,0,.56);color:rgba(0,0,0,.56);cursor:pointer;font-size:14px;font-weight:500;line-height:13px;padding:20px 25px}.sphinx-tabs-tab[aria-selected=true]{border-bottom:2px solid #2196f3;color:#2196f3;padding-bottom:19px}.sphinx-tabs-panel{margin:30px 0}.table-wrapper{border:1px solid #e0e0e0;border-radius:4px;box-shadow:0 1px 2px rgba(0,0,0,.25);display:block;margin-bottom:30px;max-width:100%;overflow-x:auto}table{color:#000;font-size:14px;line-height:24px;margin:0;overflow:hidden}table p{margin:0!important}table caption{background:#f6f8ff;border-bottom:1px solid #e0e0e0;color:#23263b;padding:10px 25px}table thead{background:#f6f8ff;border:0;border-bottom:1px solid #4458a3}table thead th{color:#23263b;font-size:14px;font-weight:700}table td,table thead th{padding:20px 25px}table tbody tr{background-color:transparent!important;border-top:1px solid #e0e0e0;line-height:18px}table:not(.highlighttable) tbody tr:first-child{border-top:1px solid #4458a3}table.thead-border thead .row-odd th{color:#23263b}table.thead-border thead .row-even th{font-weight:400}table.thead-border thead th{border:1px solid #e0e0e0}table.thead-border thead tr:first-child th{border-top:none}table.thead-border thead tr:last-child th{border-bottom:none}table.thead-border thead tr th:first-child{border-left:none}table.thead-border thead tr th:last-child{border-right:none}.topics-grid{display:block;margin:0 auto 30px}.topics-grid__title{color:#23263b;font-size:24px;font-weight:700;line-height:32px;margin-bottom:6px}.topics-grid__text{color:#4458a3;font-size:18px;line-height:24px}.topics-grid--scrollable .hs{-ms-overflow-style:none;display:grid;grid-auto-flow:column;overflow-x:scroll;padding:20px 10px;scrollbar-width:none}.topics-grid--scrollable .hs::-webkit-scrollbar{display:none}.topics-grid--scrollable .hs .topic-box:last-child:after{content:"";width:20px}.topic-box{align-items:stretch;display:flex}.topic-box .card{background:#fff;border:1px solid transparent;border-radius:8px;box-shadow:0 4px 25px rgba(0,0,0,.15);display:flex;flex-direction:column;font-size:18px;margin:0 auto 30px;overflow:hidden;padding:20px;position:relative}.topic-box .card:hover{border:1px solid #4458a3;color:#23263b;font-weight:400}.topic-box__title{color:#23263b;font-size:16px;font-weight:700;line-height:24px;margin-bottom:0}.topic-box__title img{bottom:0;opacity:.3;position:absolute;right:0;top:0}.topic-box__body{color:#000;display:flex;flex-direction:column;flex-grow:1;max-width:80%}.topic-box__body .container{flex-grow:1;margin:0;padding:0}.topic-box__body .line-block,.topic-box__body p{font-size:16px;line-height:19px;margin-top:10px}.topic-box__anchor{color:#42c4e6;font-size:14px;font-weight:700;line-height:24px}.topic-box__icon{display:block;font-size:50px;margin-bottom:20px}.topic-box__icon i{filter:brightness(0);min-height:50px;width:100%}.topic-box__icon img{bottom:-12px;display:none;height:140px;margin:0;opacity:.3;position:absolute;right:-5px}.topic-box--product .card{box-shadow:none;padding:20px;text-align:center}.topic-box--product .card .topic-box__title{color:#23263b;font-size:14px}.topic-box--product .card .topic-box__body{display:flex;flex-direction:column;max-width:100%}.topic-box--product .card .topic-box__body .line-block,.topic-box--product .card .topic-box__body p{font-size:12px}.topic-box--product .card .topic-box__icon img{display:inline-block;max-height:84px;opacity:1;position:static}.topic-box--product .card:hover{background:#fff;border:0;border-radius:8px;box-shadow:0 4px 25px rgba(0,0,0,.15);overflow:hidden}@media screen and (max-width:1024px){.topics-grid--scrollable .topic-box{width:280px!important}.topic-box--product:nth-last-child(-n+2) .card{margin-bottom:0}}@media screen and (min-width:1024px){.topics-grid{margin-bottom:10px}.topics-grid__text{font-size:16px}.topics-grid--scrollable .hs{display:flex;overflow-x:initial;padding:0}.topics-grid--scrollable .hs .topic-box:last-child:after{display:none}.topic-box .card{margin-bottom:60px;padding:45px 30px}.topic-box__title{font-size:20px;line-height:32px}.topic-box__body .line-block,.topic-box__body p{font-size:18px;line-height:26px}.topic-box__anchor{font-size:20px;line-height:26px}.topic-box .topic-box__icon img{display:inline-block}.topic-box--product .card{padding:20px}.topic-box--product .card .topic-box__title{font-size:18px;line-height:24px}.topic-box--product .card .topic-box__body .line-block,.topic-box--product .card .topic-box__body p{font-size:14px}.topic-box--product .card .topic-box__icon img{max-height:111px}.landing .topics-grid--products{margin-bottom:40px}} \ No newline at end of file diff --git a/master/_static/doctools.js b/master/_static/doctools.js new file mode 100644 index 0000000000..8cbf1b161a --- /dev/null +++ b/master/_static/doctools.js @@ -0,0 +1,323 @@ +/* + * doctools.js + * ~~~~~~~~~~~ + * + * Sphinx JavaScript utilities for all documentation. + * + * :copyright: Copyright 2007-2021 by the Sphinx team, see AUTHORS. + * :license: BSD, see LICENSE for details. + * + */ + +/** + * select a different prefix for underscore + */ +$u = _.noConflict(); + +/** + * make the code below compatible with browsers without + * an installed firebug like debugger +if (!window.console || !console.firebug) { + var names = ["log", "debug", "info", "warn", "error", "assert", "dir", + "dirxml", "group", "groupEnd", "time", "timeEnd", "count", "trace", + "profile", "profileEnd"]; + window.console = {}; + for (var i = 0; i < names.length; ++i) + window.console[names[i]] = function() {}; +} + */ + +/** + * small helper function to urldecode strings + * + * See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/decodeURIComponent#Decoding_query_parameters_from_a_URL + */ +jQuery.urldecode = function(x) { + if (!x) { + return x + } + return decodeURIComponent(x.replace(/\+/g, ' ')); +}; + +/** + * small helper function to urlencode strings + */ +jQuery.urlencode = encodeURIComponent; + +/** + * This function returns the parsed url parameters of the + * current request. Multiple values per key are supported, + * it will always return arrays of strings for the value parts. + */ +jQuery.getQueryParameters = function(s) { + if (typeof s === 'undefined') + s = document.location.search; + var parts = s.substr(s.indexOf('?') + 1).split('&'); + var result = {}; + for (var i = 0; i < parts.length; i++) { + var tmp = parts[i].split('=', 2); + var key = jQuery.urldecode(tmp[0]); + var value = jQuery.urldecode(tmp[1]); + if (key in result) + result[key].push(value); + else + result[key] = [value]; + } + return result; +}; + +/** + * highlight a given string on a jquery object by wrapping it in + * span elements with the given class name. + */ +jQuery.fn.highlightText = function(text, className) { + function highlight(node, addItems) { + if (node.nodeType === 3) { + var val = node.nodeValue; + var pos = val.toLowerCase().indexOf(text); + if (pos >= 0 && + !jQuery(node.parentNode).hasClass(className) && + !jQuery(node.parentNode).hasClass("nohighlight")) { + var span; + var isInSVG = jQuery(node).closest("body, svg, foreignObject").is("svg"); + if (isInSVG) { + span = document.createElementNS("http://www.w3.org/2000/svg", "tspan"); + } else { + span = document.createElement("span"); + span.className = className; + } + span.appendChild(document.createTextNode(val.substr(pos, text.length))); + node.parentNode.insertBefore(span, node.parentNode.insertBefore( + document.createTextNode(val.substr(pos + text.length)), + node.nextSibling)); + node.nodeValue = val.substr(0, pos); + if (isInSVG) { + var rect = document.createElementNS("http://www.w3.org/2000/svg", "rect"); + var bbox = node.parentElement.getBBox(); + rect.x.baseVal.value = bbox.x; + rect.y.baseVal.value = bbox.y; + rect.width.baseVal.value = bbox.width; + rect.height.baseVal.value = bbox.height; + rect.setAttribute('class', className); + addItems.push({ + "parent": node.parentNode, + "target": rect}); + } + } + } + else if (!jQuery(node).is("button, select, textarea")) { + jQuery.each(node.childNodes, function() { + highlight(this, addItems); + }); + } + } + var addItems = []; + var result = this.each(function() { + highlight(this, addItems); + }); + for (var i = 0; i < addItems.length; ++i) { + jQuery(addItems[i].parent).before(addItems[i].target); + } + return result; +}; + +/* + * backward compatibility for jQuery.browser + * This will be supported until firefox bug is fixed. + */ +if (!jQuery.browser) { + jQuery.uaMatch = function(ua) { + ua = ua.toLowerCase(); + + var match = /(chrome)[ \/]([\w.]+)/.exec(ua) || + /(webkit)[ \/]([\w.]+)/.exec(ua) || + /(opera)(?:.*version|)[ \/]([\w.]+)/.exec(ua) || + /(msie) ([\w.]+)/.exec(ua) || + ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec(ua) || + []; + + return { + browser: match[ 1 ] || "", + version: match[ 2 ] || "0" + }; + }; + jQuery.browser = {}; + jQuery.browser[jQuery.uaMatch(navigator.userAgent).browser] = true; +} + +/** + * Small JavaScript module for the documentation. + */ +var Documentation = { + + init : function() { + this.fixFirefoxAnchorBug(); + this.highlightSearchWords(); + this.initIndexTable(); + if (DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS) { + this.initOnKeyListeners(); + } + }, + + /** + * i18n support + */ + TRANSLATIONS : {}, + PLURAL_EXPR : function(n) { return n === 1 ? 0 : 1; }, + LOCALE : 'unknown', + + // gettext and ngettext don't access this so that the functions + // can safely bound to a different name (_ = Documentation.gettext) + gettext : function(string) { + var translated = Documentation.TRANSLATIONS[string]; + if (typeof translated === 'undefined') + return string; + return (typeof translated === 'string') ? translated : translated[0]; + }, + + ngettext : function(singular, plural, n) { + var translated = Documentation.TRANSLATIONS[singular]; + if (typeof translated === 'undefined') + return (n == 1) ? singular : plural; + return translated[Documentation.PLURALEXPR(n)]; + }, + + addTranslations : function(catalog) { + for (var key in catalog.messages) + this.TRANSLATIONS[key] = catalog.messages[key]; + this.PLURAL_EXPR = new Function('n', 'return +(' + catalog.plural_expr + ')'); + this.LOCALE = catalog.locale; + }, + + /** + * add context elements like header anchor links + */ + addContextElements : function() { + $('div[id] > :header:first').each(function() { + $('\u00B6'). + attr('href', '#' + this.id). + attr('title', _('Permalink to this headline')). + appendTo(this); + }); + $('dt[id]').each(function() { + $('\u00B6'). + attr('href', '#' + this.id). + attr('title', _('Permalink to this definition')). + appendTo(this); + }); + }, + + /** + * workaround a firefox stupidity + * see: https://bugzilla.mozilla.org/show_bug.cgi?id=645075 + */ + fixFirefoxAnchorBug : function() { + if (document.location.hash && $.browser.mozilla) + window.setTimeout(function() { + document.location.href += ''; + }, 10); + }, + + /** + * highlight the search words provided in the url in the text + */ + highlightSearchWords : function() { + var params = $.getQueryParameters(); + var terms = (params.highlight) ? params.highlight[0].split(/\s+/) : []; + if (terms.length) { + var body = $('div.body'); + if (!body.length) { + body = $('body'); + } + window.setTimeout(function() { + $.each(terms, function() { + body.highlightText(this.toLowerCase(), 'highlighted'); + }); + }, 10); + $('') + .appendTo($('#searchbox')); + } + }, + + /** + * init the domain index toggle buttons + */ + initIndexTable : function() { + var togglers = $('img.toggler').click(function() { + var src = $(this).attr('src'); + var idnum = $(this).attr('id').substr(7); + $('tr.cg-' + idnum).toggle(); + if (src.substr(-9) === 'minus.png') + $(this).attr('src', src.substr(0, src.length-9) + 'plus.png'); + else + $(this).attr('src', src.substr(0, src.length-8) + 'minus.png'); + }).css('display', ''); + if (DOCUMENTATION_OPTIONS.COLLAPSE_INDEX) { + togglers.click(); + } + }, + + /** + * helper function to hide the search marks again + */ + hideSearchWords : function() { + $('#searchbox .highlight-link').fadeOut(300); + $('span.highlighted').removeClass('highlighted'); + }, + + /** + * make the url absolute + */ + makeURL : function(relativeURL) { + return DOCUMENTATION_OPTIONS.URL_ROOT + '/' + relativeURL; + }, + + /** + * get the current relative url + */ + getCurrentURL : function() { + var path = document.location.pathname; + var parts = path.split(/\//); + $.each(DOCUMENTATION_OPTIONS.URL_ROOT.split(/\//), function() { + if (this === '..') + parts.pop(); + }); + var url = parts.join('/'); + return path.substring(url.lastIndexOf('/') + 1, path.length - 1); + }, + + initOnKeyListeners: function() { + $(document).keydown(function(event) { + var activeElementType = document.activeElement.tagName; + // don't navigate when in search box, textarea, dropdown or button + if (activeElementType !== 'TEXTAREA' && activeElementType !== 'INPUT' && activeElementType !== 'SELECT' + && activeElementType !== 'BUTTON' && !event.altKey && !event.ctrlKey && !event.metaKey + && !event.shiftKey) { + switch (event.keyCode) { + case 37: // left + var prevHref = $('link[rel="prev"]').prop('href'); + if (prevHref) { + window.location.href = prevHref; + return false; + } + break; + case 39: // right + var nextHref = $('link[rel="next"]').prop('href'); + if (nextHref) { + window.location.href = nextHref; + return false; + } + break; + } + } + }); + } +}; + +// quick alias for translations +_ = Documentation.gettext; + +$(document).ready(function() { + Documentation.init(); +}); diff --git a/master/_static/documentation_options.js b/master/_static/documentation_options.js new file mode 100644 index 0000000000..c23c68c3e7 --- /dev/null +++ b/master/_static/documentation_options.js @@ -0,0 +1,12 @@ +var DOCUMENTATION_OPTIONS = { + URL_ROOT: document.getElementById("documentation_options").getAttribute('data-url_root'), + VERSION: '3.26.2', + LANGUAGE: 'None', + COLLAPSE_INDEX: false, + BUILDER: 'html', + FILE_SUFFIX: '.html', + LINK_SUFFIX: '.html', + HAS_SOURCE: true, + SOURCELINK_SUFFIX: '.txt', + NAVIGATION_WITH_KEYS: false +}; \ No newline at end of file diff --git a/master/_static/file.png b/master/_static/file.png new file mode 100644 index 0000000000..a858a410e4 Binary files /dev/null and b/master/_static/file.png differ diff --git a/master/_static/img/banner-background.svg b/master/_static/img/banner-background.svg new file mode 100644 index 0000000000..f8520d5b3e --- /dev/null +++ b/master/_static/img/banner-background.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/master/_static/img/favicon-228x228.png b/master/_static/img/favicon-228x228.png new file mode 100644 index 0000000000..f30770c7ed Binary files /dev/null and b/master/_static/img/favicon-228x228.png differ diff --git a/master/_static/img/favicon-32x32.png b/master/_static/img/favicon-32x32.png new file mode 100644 index 0000000000..aae1708f26 Binary files /dev/null and b/master/_static/img/favicon-32x32.png differ diff --git a/master/_static/img/favicon.ico b/master/_static/img/favicon.ico new file mode 100644 index 0000000000..6c7484f082 Binary files /dev/null and b/master/_static/img/favicon.ico differ diff --git a/master/_static/img/icons/icon-about-team.svg b/master/_static/img/icons/icon-about-team.svg new file mode 100644 index 0000000000..5448c7f007 --- /dev/null +++ b/master/_static/img/icons/icon-about-team.svg @@ -0,0 +1 @@ +icon-about-team diff --git a/master/_static/img/icons/icon-about-us-m.svg b/master/_static/img/icons/icon-about-us-m.svg new file mode 100644 index 0000000000..09107d9520 --- /dev/null +++ b/master/_static/img/icons/icon-about-us-m.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/master/_static/img/icons/icon-about-us.svg b/master/_static/img/icons/icon-about-us.svg new file mode 100644 index 0000000000..1b1fcc83e3 --- /dev/null +++ b/master/_static/img/icons/icon-about-us.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/master/_static/img/icons/icon-alternator.svg b/master/_static/img/icons/icon-alternator.svg new file mode 100644 index 0000000000..7c2b4ebae0 --- /dev/null +++ b/master/_static/img/icons/icon-alternator.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/master/_static/img/icons/icon-apps.svg b/master/_static/img/icons/icon-apps.svg new file mode 100644 index 0000000000..7e93612026 --- /dev/null +++ b/master/_static/img/icons/icon-apps.svg @@ -0,0 +1 @@ + diff --git a/master/_static/img/icons/icon-architecture.svg b/master/_static/img/icons/icon-architecture.svg new file mode 100644 index 0000000000..67ebbc2f38 --- /dev/null +++ b/master/_static/img/icons/icon-architecture.svg @@ -0,0 +1 @@ +icon-architecture diff --git a/master/_static/img/icons/icon-benchmarks.svg b/master/_static/img/icons/icon-benchmarks.svg new file mode 100644 index 0000000000..e1ce2c1d78 --- /dev/null +++ b/master/_static/img/icons/icon-benchmarks.svg @@ -0,0 +1 @@ +icon-benchmarks diff --git a/master/_static/img/icons/icon-blog.svg b/master/_static/img/icons/icon-blog.svg new file mode 100644 index 0000000000..f4096cbf11 --- /dev/null +++ b/master/_static/img/icons/icon-blog.svg @@ -0,0 +1 @@ +icon-blog2 diff --git a/master/_static/img/icons/icon-careers.svg b/master/_static/img/icons/icon-careers.svg new file mode 100644 index 0000000000..2a7c6ea0b7 --- /dev/null +++ b/master/_static/img/icons/icon-careers.svg @@ -0,0 +1 @@ +icon-careers diff --git a/master/_static/img/icons/icon-chevron-left.svg b/master/_static/img/icons/icon-chevron-left.svg new file mode 100644 index 0000000000..3afa25c481 --- /dev/null +++ b/master/_static/img/icons/icon-chevron-left.svg @@ -0,0 +1,3 @@ + + + diff --git a/master/_static/img/icons/icon-chevron-right.svg b/master/_static/img/icons/icon-chevron-right.svg new file mode 100644 index 0000000000..44eb829cdc --- /dev/null +++ b/master/_static/img/icons/icon-chevron-right.svg @@ -0,0 +1,3 @@ + + + diff --git a/master/_static/img/icons/icon-circe.svg b/master/_static/img/icons/icon-circe.svg new file mode 100644 index 0000000000..875e421670 --- /dev/null +++ b/master/_static/img/icons/icon-circe.svg @@ -0,0 +1 @@ + diff --git a/master/_static/img/icons/icon-clock.svg b/master/_static/img/icons/icon-clock.svg new file mode 100644 index 0000000000..8c92469808 --- /dev/null +++ b/master/_static/img/icons/icon-clock.svg @@ -0,0 +1 @@ + diff --git a/master/_static/img/icons/icon-close.svg b/master/_static/img/icons/icon-close.svg new file mode 100644 index 0000000000..d1162b73e7 --- /dev/null +++ b/master/_static/img/icons/icon-close.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/master/_static/img/icons/icon-cloud-docs.svg b/master/_static/img/icons/icon-cloud-docs.svg new file mode 100644 index 0000000000..a9069bb6e5 --- /dev/null +++ b/master/_static/img/icons/icon-cloud-docs.svg @@ -0,0 +1 @@ + diff --git a/master/_static/img/icons/icon-cloud.svg b/master/_static/img/icons/icon-cloud.svg new file mode 100644 index 0000000000..cfb2318dae --- /dev/null +++ b/master/_static/img/icons/icon-cloud.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/master/_static/img/icons/icon-comparison.svg b/master/_static/img/icons/icon-comparison.svg new file mode 100644 index 0000000000..49d809a5df --- /dev/null +++ b/master/_static/img/icons/icon-comparison.svg @@ -0,0 +1 @@ +icon-comparison diff --git a/master/_static/img/icons/icon-contact-us.svg b/master/_static/img/icons/icon-contact-us.svg new file mode 100644 index 0000000000..9df3145dd2 --- /dev/null +++ b/master/_static/img/icons/icon-contact-us.svg @@ -0,0 +1 @@ +icon-contact-us diff --git a/master/_static/img/icons/icon-developers-blog.svg b/master/_static/img/icons/icon-developers-blog.svg new file mode 100644 index 0000000000..ee804197a0 --- /dev/null +++ b/master/_static/img/icons/icon-developers-blog.svg @@ -0,0 +1 @@ +icon-developers-blog diff --git a/master/_static/img/icons/icon-docs.svg b/master/_static/img/icons/icon-docs.svg new file mode 100644 index 0000000000..5501492f3e --- /dev/null +++ b/master/_static/img/icons/icon-docs.svg @@ -0,0 +1 @@ +icon-docs diff --git a/master/_static/img/icons/icon-enterprise-m.svg b/master/_static/img/icons/icon-enterprise-m.svg new file mode 100644 index 0000000000..97be900b50 --- /dev/null +++ b/master/_static/img/icons/icon-enterprise-m.svg @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/master/_static/img/icons/icon-enterprise.svg b/master/_static/img/icons/icon-enterprise.svg new file mode 100644 index 0000000000..ee1ac26283 --- /dev/null +++ b/master/_static/img/icons/icon-enterprise.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/master/_static/img/icons/icon-events.svg b/master/_static/img/icons/icon-events.svg new file mode 100644 index 0000000000..ba5f211864 --- /dev/null +++ b/master/_static/img/icons/icon-events.svg @@ -0,0 +1 @@ +icon-events diff --git a/master/_static/img/icons/icon-exclamation.svg b/master/_static/img/icons/icon-exclamation.svg new file mode 100644 index 0000000000..a7eb4b77a4 --- /dev/null +++ b/master/_static/img/icons/icon-exclamation.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/master/_static/img/icons/icon-expand.svg b/master/_static/img/icons/icon-expand.svg new file mode 100644 index 0000000000..3806565367 --- /dev/null +++ b/master/_static/img/icons/icon-expand.svg @@ -0,0 +1,50 @@ + + + + + + + + + diff --git a/master/_static/img/icons/icon-forum.svg b/master/_static/img/icons/icon-forum.svg new file mode 100644 index 0000000000..37a709f7a8 --- /dev/null +++ b/master/_static/img/icons/icon-forum.svg @@ -0,0 +1 @@ + diff --git a/master/_static/img/icons/icon-getting-started.svg b/master/_static/img/icons/icon-getting-started.svg new file mode 100644 index 0000000000..702500be40 --- /dev/null +++ b/master/_static/img/icons/icon-getting-started.svg @@ -0,0 +1 @@ + diff --git a/master/_static/img/icons/icon-glossary.svg b/master/_static/img/icons/icon-glossary.svg new file mode 100644 index 0000000000..e8329c2afe --- /dev/null +++ b/master/_static/img/icons/icon-glossary.svg @@ -0,0 +1 @@ + diff --git a/master/_static/img/icons/icon-home.svg b/master/_static/img/icons/icon-home.svg new file mode 100644 index 0000000000..f0b9c25419 --- /dev/null +++ b/master/_static/img/icons/icon-home.svg @@ -0,0 +1 @@ + diff --git a/master/_static/img/icons/icon-infoworld.svg b/master/_static/img/icons/icon-infoworld.svg new file mode 100644 index 0000000000..906e87279c --- /dev/null +++ b/master/_static/img/icons/icon-infoworld.svg @@ -0,0 +1 @@ +icon-infoworld diff --git a/master/_static/img/icons/icon-integrations.svg b/master/_static/img/icons/icon-integrations.svg new file mode 100644 index 0000000000..1ef0920d49 --- /dev/null +++ b/master/_static/img/icons/icon-integrations.svg @@ -0,0 +1 @@ + diff --git a/master/_static/img/icons/icon-knowledge-base.svg b/master/_static/img/icons/icon-knowledge-base.svg new file mode 100644 index 0000000000..884451270d --- /dev/null +++ b/master/_static/img/icons/icon-knowledge-base.svg @@ -0,0 +1 @@ + diff --git a/master/_static/img/icons/icon-less.svg b/master/_static/img/icons/icon-less.svg new file mode 100644 index 0000000000..3094127dec --- /dev/null +++ b/master/_static/img/icons/icon-less.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/master/_static/img/icons/icon-live-test.svg b/master/_static/img/icons/icon-live-test.svg new file mode 100644 index 0000000000..dcb5916c26 --- /dev/null +++ b/master/_static/img/icons/icon-live-test.svg @@ -0,0 +1 @@ +icon-live-test diff --git a/master/_static/img/icons/icon-mail-list.svg b/master/_static/img/icons/icon-mail-list.svg new file mode 100644 index 0000000000..0e6192a352 --- /dev/null +++ b/master/_static/img/icons/icon-mail-list.svg @@ -0,0 +1 @@ + diff --git a/master/_static/img/icons/icon-manager.svg b/master/_static/img/icons/icon-manager.svg new file mode 100644 index 0000000000..02b4e425be --- /dev/null +++ b/master/_static/img/icons/icon-manager.svg @@ -0,0 +1 @@ +icon-manager diff --git a/master/_static/img/icons/icon-memory-management.svg b/master/_static/img/icons/icon-memory-management.svg new file mode 100644 index 0000000000..e34eb4504f --- /dev/null +++ b/master/_static/img/icons/icon-memory-management.svg @@ -0,0 +1 @@ +icon-memory-management diff --git a/master/_static/img/icons/icon-modeling.svg b/master/_static/img/icons/icon-modeling.svg new file mode 100644 index 0000000000..97fa3a0e21 --- /dev/null +++ b/master/_static/img/icons/icon-modeling.svg @@ -0,0 +1 @@ + diff --git a/master/_static/img/icons/icon-monitoring.svg b/master/_static/img/icons/icon-monitoring.svg new file mode 100644 index 0000000000..80b3787f66 --- /dev/null +++ b/master/_static/img/icons/icon-monitoring.svg @@ -0,0 +1 @@ +icon-monitoring diff --git a/master/_static/img/icons/icon-networking.svg b/master/_static/img/icons/icon-networking.svg new file mode 100644 index 0000000000..40a3fd5f6f --- /dev/null +++ b/master/_static/img/icons/icon-networking.svg @@ -0,0 +1 @@ +icon-networking diff --git a/master/_static/img/icons/icon-news.svg b/master/_static/img/icons/icon-news.svg new file mode 100644 index 0000000000..a952b59937 --- /dev/null +++ b/master/_static/img/icons/icon-news.svg @@ -0,0 +1 @@ +icon-news diff --git a/master/_static/img/icons/icon-newsletter.svg b/master/_static/img/icons/icon-newsletter.svg new file mode 100644 index 0000000000..5b8d47eb15 --- /dev/null +++ b/master/_static/img/icons/icon-newsletter.svg @@ -0,0 +1 @@ +icon-newsletter diff --git a/master/_static/img/icons/icon-nsql-guides.svg b/master/_static/img/icons/icon-nsql-guides.svg new file mode 100644 index 0000000000..60ebab3795 --- /dev/null +++ b/master/_static/img/icons/icon-nsql-guides.svg @@ -0,0 +1 @@ +icon-nsql-guides diff --git a/master/_static/img/icons/icon-open-source.svg b/master/_static/img/icons/icon-open-source.svg new file mode 100644 index 0000000000..98c2ea7d5b --- /dev/null +++ b/master/_static/img/icons/icon-open-source.svg @@ -0,0 +1 @@ +icon-open-source diff --git a/master/_static/img/icons/icon-operator.svg b/master/_static/img/icons/icon-operator.svg new file mode 100644 index 0000000000..bb7d8d3ea8 --- /dev/null +++ b/master/_static/img/icons/icon-operator.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/master/_static/img/icons/icon-overview.svg b/master/_static/img/icons/icon-overview.svg new file mode 100644 index 0000000000..515c1528a2 --- /dev/null +++ b/master/_static/img/icons/icon-overview.svg @@ -0,0 +1 @@ +icon-overview diff --git a/master/_static/img/icons/icon-partners.svg b/master/_static/img/icons/icon-partners.svg new file mode 100644 index 0000000000..d0146fc497 --- /dev/null +++ b/master/_static/img/icons/icon-partners.svg @@ -0,0 +1 @@ +icon-partners diff --git a/master/_static/img/icons/icon-plus.svg b/master/_static/img/icons/icon-plus.svg new file mode 100644 index 0000000000..5757435085 --- /dev/null +++ b/master/_static/img/icons/icon-plus.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/master/_static/img/icons/icon-pricing.svg b/master/_static/img/icons/icon-pricing.svg new file mode 100644 index 0000000000..74b01db168 --- /dev/null +++ b/master/_static/img/icons/icon-pricing.svg @@ -0,0 +1 @@ +icon-pricing$ diff --git a/master/_static/img/icons/icon-release-notes.svg b/master/_static/img/icons/icon-release-notes.svg new file mode 100644 index 0000000000..80c490c7b0 --- /dev/null +++ b/master/_static/img/icons/icon-release-notes.svg @@ -0,0 +1 @@ +icon-release-notes diff --git a/master/_static/img/icons/icon-resource-center.svg b/master/_static/img/icons/icon-resource-center.svg new file mode 100644 index 0000000000..6e3ab08e79 --- /dev/null +++ b/master/_static/img/icons/icon-resource-center.svg @@ -0,0 +1 @@ +icon-ressource-center diff --git a/master/_static/img/icons/icon-roadmap.svg b/master/_static/img/icons/icon-roadmap.svg new file mode 100644 index 0000000000..c8cbf67c8c --- /dev/null +++ b/master/_static/img/icons/icon-roadmap.svg @@ -0,0 +1 @@ +icon-roadmap-4 diff --git a/master/_static/img/icons/icon-search.svg b/master/_static/img/icons/icon-search.svg new file mode 100644 index 0000000000..81aae93eef --- /dev/null +++ b/master/_static/img/icons/icon-search.svg @@ -0,0 +1,4 @@ + + + + diff --git a/master/_static/img/icons/icon-slack.svg b/master/_static/img/icons/icon-slack.svg new file mode 100644 index 0000000000..fc164ea1e7 --- /dev/null +++ b/master/_static/img/icons/icon-slack.svg @@ -0,0 +1 @@ + diff --git a/master/_static/img/icons/icon-stack-overflow.svg b/master/_static/img/icons/icon-stack-overflow.svg new file mode 100644 index 0000000000..bebe9b8274 --- /dev/null +++ b/master/_static/img/icons/icon-stack-overflow.svg @@ -0,0 +1,4 @@ + + + + diff --git a/master/_static/img/icons/icon-summit.svg b/master/_static/img/icons/icon-summit.svg new file mode 100644 index 0000000000..4b900bd0c0 --- /dev/null +++ b/master/_static/img/icons/icon-summit.svg @@ -0,0 +1 @@ + diff --git a/master/_static/img/icons/icon-support.svg b/master/_static/img/icons/icon-support.svg new file mode 100644 index 0000000000..a4228b34e8 --- /dev/null +++ b/master/_static/img/icons/icon-support.svg @@ -0,0 +1 @@ +icon-support diff --git a/master/_static/img/icons/icon-tech-talks.svg b/master/_static/img/icons/icon-tech-talks.svg new file mode 100644 index 0000000000..df42b5522b --- /dev/null +++ b/master/_static/img/icons/icon-tech-talks.svg @@ -0,0 +1 @@ +icon-tech-talks diff --git a/master/_static/img/icons/icon-testing.svg b/master/_static/img/icons/icon-testing.svg new file mode 100644 index 0000000000..2fe54efdbc --- /dev/null +++ b/master/_static/img/icons/icon-testing.svg @@ -0,0 +1 @@ +icon-testing diff --git a/master/_static/img/icons/icon-thumbs-down.svg b/master/_static/img/icons/icon-thumbs-down.svg new file mode 100644 index 0000000000..3e7bcd6d90 --- /dev/null +++ b/master/_static/img/icons/icon-thumbs-down.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/master/_static/img/icons/icon-thumbs-up.svg b/master/_static/img/icons/icon-thumbs-up.svg new file mode 100644 index 0000000000..226c44d853 --- /dev/null +++ b/master/_static/img/icons/icon-thumbs-up.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/master/_static/img/icons/icon-tip.svg b/master/_static/img/icons/icon-tip.svg new file mode 100644 index 0000000000..bf7aa6af84 --- /dev/null +++ b/master/_static/img/icons/icon-tip.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/master/_static/img/icons/icon-training.svg b/master/_static/img/icons/icon-training.svg new file mode 100644 index 0000000000..08b95a88ed --- /dev/null +++ b/master/_static/img/icons/icon-training.svg @@ -0,0 +1 @@ +icon-training diff --git a/master/_static/img/icons/icon-triangle-down.svg b/master/_static/img/icons/icon-triangle-down.svg new file mode 100644 index 0000000000..e8ae088106 --- /dev/null +++ b/master/_static/img/icons/icon-triangle-down.svg @@ -0,0 +1,3 @@ + + + diff --git a/master/_static/img/icons/icon-university.svg b/master/_static/img/icons/icon-university.svg new file mode 100644 index 0000000000..f7547ab959 --- /dev/null +++ b/master/_static/img/icons/icon-university.svg @@ -0,0 +1 @@ +icon-university diff --git a/master/_static/img/icons/icon-users-blog.svg b/master/_static/img/icons/icon-users-blog.svg new file mode 100644 index 0000000000..47e56cddcf --- /dev/null +++ b/master/_static/img/icons/icon-users-blog.svg @@ -0,0 +1 @@ +icon-users-blog diff --git a/master/_static/img/icons/icon-warning.svg b/master/_static/img/icons/icon-warning.svg new file mode 100644 index 0000000000..e4b1d40331 --- /dev/null +++ b/master/_static/img/icons/icon-warning.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/master/_static/img/icons/icon-webinars.svg b/master/_static/img/icons/icon-webinars.svg new file mode 100644 index 0000000000..5e9f5cd427 --- /dev/null +++ b/master/_static/img/icons/icon-webinars.svg @@ -0,0 +1 @@ +icon-webinars diff --git a/master/_static/img/icons/icon-whitepapers.svg b/master/_static/img/icons/icon-whitepapers.svg new file mode 100644 index 0000000000..3351e51d23 --- /dev/null +++ b/master/_static/img/icons/icon-whitepapers.svg @@ -0,0 +1 @@ +icon-whitepapers diff --git a/master/_static/img/icons/icon-workshop.svg b/master/_static/img/icons/icon-workshop.svg new file mode 100644 index 0000000000..5206e58e98 --- /dev/null +++ b/master/_static/img/icons/icon-workshop.svg @@ -0,0 +1 @@ + diff --git a/master/_static/img/logo-docs.svg b/master/_static/img/logo-docs.svg new file mode 100644 index 0000000000..4fff669cb6 --- /dev/null +++ b/master/_static/img/logo-docs.svg @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/master/_static/img/logo-scylla-horizontal-RGB.svg b/master/_static/img/logo-scylla-horizontal-RGB.svg new file mode 100644 index 0000000000..b5022d7c4d --- /dev/null +++ b/master/_static/img/logo-scylla-horizontal-RGB.svg @@ -0,0 +1,74 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/master/_static/img/mascots/404.jpg b/master/_static/img/mascots/404.jpg new file mode 100644 index 0000000000..769fa0889f Binary files /dev/null and b/master/_static/img/mascots/404.jpg differ diff --git a/master/_static/img/mascots/scylla-3monsters.png b/master/_static/img/mascots/scylla-3monsters.png new file mode 100644 index 0000000000..7c06d01674 Binary files /dev/null and b/master/_static/img/mascots/scylla-3monsters.png differ diff --git a/master/_static/img/mascots/scylla-advisor-crystal.png b/master/_static/img/mascots/scylla-advisor-crystal.png new file mode 100644 index 0000000000..d33fddd62f Binary files /dev/null and b/master/_static/img/mascots/scylla-advisor-crystal.png differ diff --git a/master/_static/img/mascots/scylla-alternator.svg b/master/_static/img/mascots/scylla-alternator.svg new file mode 100644 index 0000000000..0462f893d5 --- /dev/null +++ b/master/_static/img/mascots/scylla-alternator.svg @@ -0,0 +1 @@ +scylla-alternator diff --git a/master/_static/img/mascots/scylla-cloud.svg b/master/_static/img/mascots/scylla-cloud.svg new file mode 100644 index 0000000000..a6c6a26fc9 --- /dev/null +++ b/master/_static/img/mascots/scylla-cloud.svg @@ -0,0 +1 @@ +scylla-cloud diff --git a/master/_static/img/mascots/scylla-computer-3-monsters.png b/master/_static/img/mascots/scylla-computer-3-monsters.png new file mode 100644 index 0000000000..d0368a7027 Binary files /dev/null and b/master/_static/img/mascots/scylla-computer-3-monsters.png differ diff --git a/master/_static/img/mascots/scylla-computer-headset.png b/master/_static/img/mascots/scylla-computer-headset.png new file mode 100644 index 0000000000..0cdadaa216 Binary files /dev/null and b/master/_static/img/mascots/scylla-computer-headset.png differ diff --git a/master/_static/img/mascots/scylla-cup-number-one.png b/master/_static/img/mascots/scylla-cup-number-one.png new file mode 100644 index 0000000000..e889f4e368 Binary files /dev/null and b/master/_static/img/mascots/scylla-cup-number-one.png differ diff --git a/master/_static/img/mascots/scylla-docs.svg b/master/_static/img/mascots/scylla-docs.svg new file mode 100644 index 0000000000..a5bce950c2 --- /dev/null +++ b/master/_static/img/mascots/scylla-docs.svg @@ -0,0 +1 @@ +scylla-docs diff --git a/master/_static/img/mascots/scylla-drivers.svg b/master/_static/img/mascots/scylla-drivers.svg new file mode 100644 index 0000000000..6012e71679 --- /dev/null +++ b/master/_static/img/mascots/scylla-drivers.svg @@ -0,0 +1 @@ +scylla-manager diff --git a/master/_static/img/mascots/scylla-enterprise.svg b/master/_static/img/mascots/scylla-enterprise.svg new file mode 100644 index 0000000000..a1aa0b46ac --- /dev/null +++ b/master/_static/img/mascots/scylla-enterprise.svg @@ -0,0 +1 @@ +scylla-enterprise diff --git a/master/_static/img/mascots/scylla-forklift-boxes.png b/master/_static/img/mascots/scylla-forklift-boxes.png new file mode 100644 index 0000000000..f64c29e6c7 Binary files /dev/null and b/master/_static/img/mascots/scylla-forklift-boxes.png differ diff --git a/master/_static/img/mascots/scylla-forklift-migration.png b/master/_static/img/mascots/scylla-forklift-migration.png new file mode 100644 index 0000000000..d2f645c645 Binary files /dev/null and b/master/_static/img/mascots/scylla-forklift-migration.png differ diff --git a/master/_static/img/mascots/scylla-gear.png b/master/_static/img/mascots/scylla-gear.png new file mode 100644 index 0000000000..0f53b26afa Binary files /dev/null and b/master/_static/img/mascots/scylla-gear.png differ diff --git a/master/_static/img/mascots/scylla-hardhat.png b/master/_static/img/mascots/scylla-hardhat.png new file mode 100644 index 0000000000..630f2d9094 Binary files /dev/null and b/master/_static/img/mascots/scylla-hardhat.png differ diff --git a/master/_static/img/mascots/scylla-headband.png b/master/_static/img/mascots/scylla-headband.png new file mode 100644 index 0000000000..c87abe684d Binary files /dev/null and b/master/_static/img/mascots/scylla-headband.png differ diff --git a/master/_static/img/mascots/scylla-headset.png b/master/_static/img/mascots/scylla-headset.png new file mode 100644 index 0000000000..ba52cd223d Binary files /dev/null and b/master/_static/img/mascots/scylla-headset.png differ diff --git a/master/_static/img/mascots/scylla-hearts.png b/master/_static/img/mascots/scylla-hearts.png new file mode 100644 index 0000000000..cef08c8654 Binary files /dev/null and b/master/_static/img/mascots/scylla-hearts.png differ diff --git a/master/_static/img/mascots/scylla-looking-down.png b/master/_static/img/mascots/scylla-looking-down.png new file mode 100644 index 0000000000..75cccbfdf1 Binary files /dev/null and b/master/_static/img/mascots/scylla-looking-down.png differ diff --git a/master/_static/img/mascots/scylla-looking-up.png b/master/_static/img/mascots/scylla-looking-up.png new file mode 100644 index 0000000000..6f10405f21 Binary files /dev/null and b/master/_static/img/mascots/scylla-looking-up.png differ diff --git a/master/_static/img/mascots/scylla-magnifying-glass-fronting.png b/master/_static/img/mascots/scylla-magnifying-glass-fronting.png new file mode 100644 index 0000000000..e368cae169 Binary files /dev/null and b/master/_static/img/mascots/scylla-magnifying-glass-fronting.png differ diff --git a/master/_static/img/mascots/scylla-magnifying-glass.png b/master/_static/img/mascots/scylla-magnifying-glass.png new file mode 100644 index 0000000000..74ad669500 Binary files /dev/null and b/master/_static/img/mascots/scylla-magnifying-glass.png differ diff --git a/master/_static/img/mascots/scylla-manager.svg b/master/_static/img/mascots/scylla-manager.svg new file mode 100644 index 0000000000..6ba9ed937c --- /dev/null +++ b/master/_static/img/mascots/scylla-manager.svg @@ -0,0 +1 @@ +scylla-manager-2 diff --git a/master/_static/img/mascots/scylla-monitor.svg b/master/_static/img/mascots/scylla-monitor.svg new file mode 100644 index 0000000000..48bec7dde3 --- /dev/null +++ b/master/_static/img/mascots/scylla-monitor.svg @@ -0,0 +1 @@ +scylla-monitor diff --git a/master/_static/img/mascots/scylla-movement-fast.png b/master/_static/img/mascots/scylla-movement-fast.png new file mode 100644 index 0000000000..956d1dd0e2 Binary files /dev/null and b/master/_static/img/mascots/scylla-movement-fast.png differ diff --git a/master/_static/img/mascots/scylla-movement.png b/master/_static/img/mascots/scylla-movement.png new file mode 100644 index 0000000000..7ee2b04338 Binary files /dev/null and b/master/_static/img/mascots/scylla-movement.png differ diff --git a/master/_static/img/mascots/scylla-onpremise.png b/master/_static/img/mascots/scylla-onpremise.png new file mode 100644 index 0000000000..3b2dc8f1a2 Binary files /dev/null and b/master/_static/img/mascots/scylla-onpremise.png differ diff --git a/master/_static/img/mascots/scylla-opensource.svg b/master/_static/img/mascots/scylla-opensource.svg new file mode 100644 index 0000000000..299e9cb995 --- /dev/null +++ b/master/_static/img/mascots/scylla-opensource.svg @@ -0,0 +1 @@ +Plan de travail 1 diff --git a/master/_static/img/mascots/scylla-operator.svg b/master/_static/img/mascots/scylla-operator.svg new file mode 100644 index 0000000000..655a450b2a --- /dev/null +++ b/master/_static/img/mascots/scylla-operator.svg @@ -0,0 +1 @@ +scylla-operator diff --git a/master/_static/img/mascots/scylla-plugin.png b/master/_static/img/mascots/scylla-plugin.png new file mode 100644 index 0000000000..b28dc857cc Binary files /dev/null and b/master/_static/img/mascots/scylla-plugin.png differ diff --git a/master/_static/img/mascots/scylla-release-mascot.png b/master/_static/img/mascots/scylla-release-mascot.png new file mode 100644 index 0000000000..09342ac687 Binary files /dev/null and b/master/_static/img/mascots/scylla-release-mascot.png differ diff --git a/master/_static/img/mascots/scylla-repair.png b/master/_static/img/mascots/scylla-repair.png new file mode 100644 index 0000000000..9b4c613e70 Binary files /dev/null and b/master/_static/img/mascots/scylla-repair.png differ diff --git a/master/_static/img/mascots/scylla-server.png b/master/_static/img/mascots/scylla-server.png new file mode 100644 index 0000000000..96dc785298 Binary files /dev/null and b/master/_static/img/mascots/scylla-server.png differ diff --git a/master/_static/img/mascots/scylla-sleeping.png b/master/_static/img/mascots/scylla-sleeping.png new file mode 100644 index 0000000000..f88598e05a Binary files /dev/null and b/master/_static/img/mascots/scylla-sleeping.png differ diff --git a/master/_static/img/mascots/scylla-tall-measure.png b/master/_static/img/mascots/scylla-tall-measure.png new file mode 100644 index 0000000000..6f0ca146c0 Binary files /dev/null and b/master/_static/img/mascots/scylla-tall-measure.png differ diff --git a/master/_static/img/mascots/scylla-university.png b/master/_static/img/mascots/scylla-university.png new file mode 100644 index 0000000000..b3d0621193 Binary files /dev/null and b/master/_static/img/mascots/scylla-university.png differ diff --git a/master/_static/img/mascots/scylla-weights.png b/master/_static/img/mascots/scylla-weights.png new file mode 100644 index 0000000000..b070bb022c Binary files /dev/null and b/master/_static/img/mascots/scylla-weights.png differ diff --git a/master/_static/img/mascots/scylla-window-cleaning.png b/master/_static/img/mascots/scylla-window-cleaning.png new file mode 100644 index 0000000000..6a8b16a6b4 Binary files /dev/null and b/master/_static/img/mascots/scylla-window-cleaning.png differ diff --git a/master/_static/img/mascots/scylla-with-computer-2.png b/master/_static/img/mascots/scylla-with-computer-2.png new file mode 100644 index 0000000000..f3b8b2984f Binary files /dev/null and b/master/_static/img/mascots/scylla-with-computer-2.png differ diff --git a/master/_static/img/mascots/scylla-with-computer.png b/master/_static/img/mascots/scylla-with-computer.png new file mode 100644 index 0000000000..b38a6fbbe0 Binary files /dev/null and b/master/_static/img/mascots/scylla-with-computer.png differ diff --git a/master/_static/img/mascots/scylla-with-linux.png b/master/_static/img/mascots/scylla-with-linux.png new file mode 100644 index 0000000000..954bf13bc2 Binary files /dev/null and b/master/_static/img/mascots/scylla-with-linux.png differ diff --git a/master/_static/img/mascots/scylla-writting.png b/master/_static/img/mascots/scylla-writting.png new file mode 100644 index 0000000000..d35a13d380 Binary files /dev/null and b/master/_static/img/mascots/scylla-writting.png differ diff --git a/master/_static/img/menu.svg b/master/_static/img/menu.svg new file mode 100644 index 0000000000..30ea1d901e --- /dev/null +++ b/master/_static/img/menu.svg @@ -0,0 +1,3 @@ + + + diff --git a/master/_static/jquery-3.5.1.js b/master/_static/jquery-3.5.1.js new file mode 100644 index 0000000000..50937333b9 --- /dev/null +++ b/master/_static/jquery-3.5.1.js @@ -0,0 +1,10872 @@ +/*! + * jQuery JavaScript Library v3.5.1 + * https://jquery.com/ + * + * Includes Sizzle.js + * https://sizzlejs.com/ + * + * Copyright JS Foundation and other contributors + * Released under the MIT license + * https://jquery.org/license + * + * Date: 2020-05-04T22:49Z + */ +( function( global, factory ) { + + "use strict"; + + if ( typeof module === "object" && typeof module.exports === "object" ) { + + // For CommonJS and CommonJS-like environments where a proper `window` + // is present, execute the factory and get jQuery. + // For environments that do not have a `window` with a `document` + // (such as Node.js), expose a factory as module.exports. + // This accentuates the need for the creation of a real `window`. + // e.g. var jQuery = require("jquery")(window); + // See ticket #14549 for more info. + module.exports = global.document ? + factory( global, true ) : + function( w ) { + if ( !w.document ) { + throw new Error( "jQuery requires a window with a document" ); + } + return factory( w ); + }; + } else { + factory( global ); + } + +// Pass this if window is not defined yet +} )( typeof window !== "undefined" ? window : this, function( window, noGlobal ) { + +// Edge <= 12 - 13+, Firefox <=18 - 45+, IE 10 - 11, Safari 5.1 - 9+, iOS 6 - 9.1 +// throw exceptions when non-strict code (e.g., ASP.NET 4.5) accesses strict mode +// arguments.callee.caller (trac-13335). But as of jQuery 3.0 (2016), strict mode should be common +// enough that all such attempts are guarded in a try block. +"use strict"; + +var arr = []; + +var getProto = Object.getPrototypeOf; + +var slice = arr.slice; + +var flat = arr.flat ? function( array ) { + return arr.flat.call( array ); +} : function( array ) { + return arr.concat.apply( [], array ); +}; + + +var push = arr.push; + +var indexOf = arr.indexOf; + +var class2type = {}; + +var toString = class2type.toString; + +var hasOwn = class2type.hasOwnProperty; + +var fnToString = hasOwn.toString; + +var ObjectFunctionString = fnToString.call( Object ); + +var support = {}; + +var isFunction = function isFunction( obj ) { + + // Support: Chrome <=57, Firefox <=52 + // In some browsers, typeof returns "function" for HTML elements + // (i.e., `typeof document.createElement( "object" ) === "function"`). + // We don't want to classify *any* DOM node as a function. + return typeof obj === "function" && typeof obj.nodeType !== "number"; + }; + + +var isWindow = function isWindow( obj ) { + return obj != null && obj === obj.window; + }; + + +var document = window.document; + + + + var preservedScriptAttributes = { + type: true, + src: true, + nonce: true, + noModule: true + }; + + function DOMEval( code, node, doc ) { + doc = doc || document; + + var i, val, + script = doc.createElement( "script" ); + + script.text = code; + if ( node ) { + for ( i in preservedScriptAttributes ) { + + // Support: Firefox 64+, Edge 18+ + // Some browsers don't support the "nonce" property on scripts. + // On the other hand, just using `getAttribute` is not enough as + // the `nonce` attribute is reset to an empty string whenever it + // becomes browsing-context connected. + // See https://github.com/whatwg/html/issues/2369 + // See https://html.spec.whatwg.org/#nonce-attributes + // The `node.getAttribute` check was added for the sake of + // `jQuery.globalEval` so that it can fake a nonce-containing node + // via an object. + val = node[ i ] || node.getAttribute && node.getAttribute( i ); + if ( val ) { + script.setAttribute( i, val ); + } + } + } + doc.head.appendChild( script ).parentNode.removeChild( script ); + } + + +function toType( obj ) { + if ( obj == null ) { + return obj + ""; + } + + // Support: Android <=2.3 only (functionish RegExp) + return typeof obj === "object" || typeof obj === "function" ? + class2type[ toString.call( obj ) ] || "object" : + typeof obj; +} +/* global Symbol */ +// Defining this global in .eslintrc.json would create a danger of using the global +// unguarded in another place, it seems safer to define global only for this module + + + +var + version = "3.5.1", + + // Define a local copy of jQuery + jQuery = function( selector, context ) { + + // The jQuery object is actually just the init constructor 'enhanced' + // Need init if jQuery is called (just allow error to be thrown if not included) + return new jQuery.fn.init( selector, context ); + }; + +jQuery.fn = jQuery.prototype = { + + // The current version of jQuery being used + jquery: version, + + constructor: jQuery, + + // The default length of a jQuery object is 0 + length: 0, + + toArray: function() { + return slice.call( this ); + }, + + // Get the Nth element in the matched element set OR + // Get the whole matched element set as a clean array + get: function( num ) { + + // Return all the elements in a clean array + if ( num == null ) { + return slice.call( this ); + } + + // Return just the one element from the set + return num < 0 ? this[ num + this.length ] : this[ num ]; + }, + + // Take an array of elements and push it onto the stack + // (returning the new matched element set) + pushStack: function( elems ) { + + // Build a new jQuery matched element set + var ret = jQuery.merge( this.constructor(), elems ); + + // Add the old object onto the stack (as a reference) + ret.prevObject = this; + + // Return the newly-formed element set + return ret; + }, + + // Execute a callback for every element in the matched set. + each: function( callback ) { + return jQuery.each( this, callback ); + }, + + map: function( callback ) { + return this.pushStack( jQuery.map( this, function( elem, i ) { + return callback.call( elem, i, elem ); + } ) ); + }, + + slice: function() { + return this.pushStack( slice.apply( this, arguments ) ); + }, + + first: function() { + return this.eq( 0 ); + }, + + last: function() { + return this.eq( -1 ); + }, + + even: function() { + return this.pushStack( jQuery.grep( this, function( _elem, i ) { + return ( i + 1 ) % 2; + } ) ); + }, + + odd: function() { + return this.pushStack( jQuery.grep( this, function( _elem, i ) { + return i % 2; + } ) ); + }, + + eq: function( i ) { + var len = this.length, + j = +i + ( i < 0 ? len : 0 ); + return this.pushStack( j >= 0 && j < len ? [ this[ j ] ] : [] ); + }, + + end: function() { + return this.prevObject || this.constructor(); + }, + + // For internal use only. + // Behaves like an Array's method, not like a jQuery method. + push: push, + sort: arr.sort, + splice: arr.splice +}; + +jQuery.extend = jQuery.fn.extend = function() { + var options, name, src, copy, copyIsArray, clone, + target = arguments[ 0 ] || {}, + i = 1, + length = arguments.length, + deep = false; + + // Handle a deep copy situation + if ( typeof target === "boolean" ) { + deep = target; + + // Skip the boolean and the target + target = arguments[ i ] || {}; + i++; + } + + // Handle case when target is a string or something (possible in deep copy) + if ( typeof target !== "object" && !isFunction( target ) ) { + target = {}; + } + + // Extend jQuery itself if only one argument is passed + if ( i === length ) { + target = this; + i--; + } + + for ( ; i < length; i++ ) { + + // Only deal with non-null/undefined values + if ( ( options = arguments[ i ] ) != null ) { + + // Extend the base object + for ( name in options ) { + copy = options[ name ]; + + // Prevent Object.prototype pollution + // Prevent never-ending loop + if ( name === "__proto__" || target === copy ) { + continue; + } + + // Recurse if we're merging plain objects or arrays + if ( deep && copy && ( jQuery.isPlainObject( copy ) || + ( copyIsArray = Array.isArray( copy ) ) ) ) { + src = target[ name ]; + + // Ensure proper type for the source value + if ( copyIsArray && !Array.isArray( src ) ) { + clone = []; + } else if ( !copyIsArray && !jQuery.isPlainObject( src ) ) { + clone = {}; + } else { + clone = src; + } + copyIsArray = false; + + // Never move original objects, clone them + target[ name ] = jQuery.extend( deep, clone, copy ); + + // Don't bring in undefined values + } else if ( copy !== undefined ) { + target[ name ] = copy; + } + } + } + } + + // Return the modified object + return target; +}; + +jQuery.extend( { + + // Unique for each copy of jQuery on the page + expando: "jQuery" + ( version + Math.random() ).replace( /\D/g, "" ), + + // Assume jQuery is ready without the ready module + isReady: true, + + error: function( msg ) { + throw new Error( msg ); + }, + + noop: function() {}, + + isPlainObject: function( obj ) { + var proto, Ctor; + + // Detect obvious negatives + // Use toString instead of jQuery.type to catch host objects + if ( !obj || toString.call( obj ) !== "[object Object]" ) { + return false; + } + + proto = getProto( obj ); + + // Objects with no prototype (e.g., `Object.create( null )`) are plain + if ( !proto ) { + return true; + } + + // Objects with prototype are plain iff they were constructed by a global Object function + Ctor = hasOwn.call( proto, "constructor" ) && proto.constructor; + return typeof Ctor === "function" && fnToString.call( Ctor ) === ObjectFunctionString; + }, + + isEmptyObject: function( obj ) { + var name; + + for ( name in obj ) { + return false; + } + return true; + }, + + // Evaluates a script in a provided context; falls back to the global one + // if not specified. + globalEval: function( code, options, doc ) { + DOMEval( code, { nonce: options && options.nonce }, doc ); + }, + + each: function( obj, callback ) { + var length, i = 0; + + if ( isArrayLike( obj ) ) { + length = obj.length; + for ( ; i < length; i++ ) { + if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) { + break; + } + } + } else { + for ( i in obj ) { + if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) { + break; + } + } + } + + return obj; + }, + + // results is for internal usage only + makeArray: function( arr, results ) { + var ret = results || []; + + if ( arr != null ) { + if ( isArrayLike( Object( arr ) ) ) { + jQuery.merge( ret, + typeof arr === "string" ? + [ arr ] : arr + ); + } else { + push.call( ret, arr ); + } + } + + return ret; + }, + + inArray: function( elem, arr, i ) { + return arr == null ? -1 : indexOf.call( arr, elem, i ); + }, + + // Support: Android <=4.0 only, PhantomJS 1 only + // push.apply(_, arraylike) throws on ancient WebKit + merge: function( first, second ) { + var len = +second.length, + j = 0, + i = first.length; + + for ( ; j < len; j++ ) { + first[ i++ ] = second[ j ]; + } + + first.length = i; + + return first; + }, + + grep: function( elems, callback, invert ) { + var callbackInverse, + matches = [], + i = 0, + length = elems.length, + callbackExpect = !invert; + + // Go through the array, only saving the items + // that pass the validator function + for ( ; i < length; i++ ) { + callbackInverse = !callback( elems[ i ], i ); + if ( callbackInverse !== callbackExpect ) { + matches.push( elems[ i ] ); + } + } + + return matches; + }, + + // arg is for internal usage only + map: function( elems, callback, arg ) { + var length, value, + i = 0, + ret = []; + + // Go through the array, translating each of the items to their new values + if ( isArrayLike( elems ) ) { + length = elems.length; + for ( ; i < length; i++ ) { + value = callback( elems[ i ], i, arg ); + + if ( value != null ) { + ret.push( value ); + } + } + + // Go through every key on the object, + } else { + for ( i in elems ) { + value = callback( elems[ i ], i, arg ); + + if ( value != null ) { + ret.push( value ); + } + } + } + + // Flatten any nested arrays + return flat( ret ); + }, + + // A global GUID counter for objects + guid: 1, + + // jQuery.support is not used in Core but other projects attach their + // properties to it so it needs to exist. + support: support +} ); + +if ( typeof Symbol === "function" ) { + jQuery.fn[ Symbol.iterator ] = arr[ Symbol.iterator ]; +} + +// Populate the class2type map +jQuery.each( "Boolean Number String Function Array Date RegExp Object Error Symbol".split( " " ), +function( _i, name ) { + class2type[ "[object " + name + "]" ] = name.toLowerCase(); +} ); + +function isArrayLike( obj ) { + + // Support: real iOS 8.2 only (not reproducible in simulator) + // `in` check used to prevent JIT error (gh-2145) + // hasOwn isn't used here due to false negatives + // regarding Nodelist length in IE + var length = !!obj && "length" in obj && obj.length, + type = toType( obj ); + + if ( isFunction( obj ) || isWindow( obj ) ) { + return false; + } + + return type === "array" || length === 0 || + typeof length === "number" && length > 0 && ( length - 1 ) in obj; +} +var Sizzle = +/*! + * Sizzle CSS Selector Engine v2.3.5 + * https://sizzlejs.com/ + * + * Copyright JS Foundation and other contributors + * Released under the MIT license + * https://js.foundation/ + * + * Date: 2020-03-14 + */ +( function( window ) { +var i, + support, + Expr, + getText, + isXML, + tokenize, + compile, + select, + outermostContext, + sortInput, + hasDuplicate, + + // Local document vars + setDocument, + document, + docElem, + documentIsHTML, + rbuggyQSA, + rbuggyMatches, + matches, + contains, + + // Instance-specific data + expando = "sizzle" + 1 * new Date(), + preferredDoc = window.document, + dirruns = 0, + done = 0, + classCache = createCache(), + tokenCache = createCache(), + compilerCache = createCache(), + nonnativeSelectorCache = createCache(), + sortOrder = function( a, b ) { + if ( a === b ) { + hasDuplicate = true; + } + return 0; + }, + + // Instance methods + hasOwn = ( {} ).hasOwnProperty, + arr = [], + pop = arr.pop, + pushNative = arr.push, + push = arr.push, + slice = arr.slice, + + // Use a stripped-down indexOf as it's faster than native + // https://jsperf.com/thor-indexof-vs-for/5 + indexOf = function( list, elem ) { + var i = 0, + len = list.length; + for ( ; i < len; i++ ) { + if ( list[ i ] === elem ) { + return i; + } + } + return -1; + }, + + booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|" + + "ismap|loop|multiple|open|readonly|required|scoped", + + // Regular expressions + + // http://www.w3.org/TR/css3-selectors/#whitespace + whitespace = "[\\x20\\t\\r\\n\\f]", + + // https://www.w3.org/TR/css-syntax-3/#ident-token-diagram + identifier = "(?:\\\\[\\da-fA-F]{1,6}" + whitespace + + "?|\\\\[^\\r\\n\\f]|[\\w-]|[^\0-\\x7f])+", + + // Attribute selectors: http://www.w3.org/TR/selectors/#attribute-selectors + attributes = "\\[" + whitespace + "*(" + identifier + ")(?:" + whitespace + + + // Operator (capture 2) + "*([*^$|!~]?=)" + whitespace + + + // "Attribute values must be CSS identifiers [capture 5] + // or strings [capture 3 or capture 4]" + "*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|(" + identifier + "))|)" + + whitespace + "*\\]", + + pseudos = ":(" + identifier + ")(?:\\((" + + + // To reduce the number of selectors needing tokenize in the preFilter, prefer arguments: + // 1. quoted (capture 3; capture 4 or capture 5) + "('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|" + + + // 2. simple (capture 6) + "((?:\\\\.|[^\\\\()[\\]]|" + attributes + ")*)|" + + + // 3. anything else (capture 2) + ".*" + + ")\\)|)", + + // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter + rwhitespace = new RegExp( whitespace + "+", "g" ), + rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + + whitespace + "+$", "g" ), + + rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ), + rcombinators = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + + "*" ), + rdescend = new RegExp( whitespace + "|>" ), + + rpseudo = new RegExp( pseudos ), + ridentifier = new RegExp( "^" + identifier + "$" ), + + matchExpr = { + "ID": new RegExp( "^#(" + identifier + ")" ), + "CLASS": new RegExp( "^\\.(" + identifier + ")" ), + "TAG": new RegExp( "^(" + identifier + "|[*])" ), + "ATTR": new RegExp( "^" + attributes ), + "PSEUDO": new RegExp( "^" + pseudos ), + "CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + + whitespace + "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + + whitespace + "*(\\d+)|))" + whitespace + "*\\)|)", "i" ), + "bool": new RegExp( "^(?:" + booleans + ")$", "i" ), + + // For use in libraries implementing .is() + // We use this for POS matching in `select` + "needsContext": new RegExp( "^" + whitespace + + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" + whitespace + + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" ) + }, + + rhtml = /HTML$/i, + rinputs = /^(?:input|select|textarea|button)$/i, + rheader = /^h\d$/i, + + rnative = /^[^{]+\{\s*\[native \w/, + + // Easily-parseable/retrievable ID or TAG or CLASS selectors + rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/, + + rsibling = /[+~]/, + + // CSS escapes + // http://www.w3.org/TR/CSS21/syndata.html#escaped-characters + runescape = new RegExp( "\\\\[\\da-fA-F]{1,6}" + whitespace + "?|\\\\([^\\r\\n\\f])", "g" ), + funescape = function( escape, nonHex ) { + var high = "0x" + escape.slice( 1 ) - 0x10000; + + return nonHex ? + + // Strip the backslash prefix from a non-hex escape sequence + nonHex : + + // Replace a hexadecimal escape sequence with the encoded Unicode code point + // Support: IE <=11+ + // For values outside the Basic Multilingual Plane (BMP), manually construct a + // surrogate pair + high < 0 ? + String.fromCharCode( high + 0x10000 ) : + String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 ); + }, + + // CSS string/identifier serialization + // https://drafts.csswg.org/cssom/#common-serializing-idioms + rcssescape = /([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g, + fcssescape = function( ch, asCodePoint ) { + if ( asCodePoint ) { + + // U+0000 NULL becomes U+FFFD REPLACEMENT CHARACTER + if ( ch === "\0" ) { + return "\uFFFD"; + } + + // Control characters and (dependent upon position) numbers get escaped as code points + return ch.slice( 0, -1 ) + "\\" + + ch.charCodeAt( ch.length - 1 ).toString( 16 ) + " "; + } + + // Other potentially-special ASCII characters get backslash-escaped + return "\\" + ch; + }, + + // Used for iframes + // See setDocument() + // Removing the function wrapper causes a "Permission Denied" + // error in IE + unloadHandler = function() { + setDocument(); + }, + + inDisabledFieldset = addCombinator( + function( elem ) { + return elem.disabled === true && elem.nodeName.toLowerCase() === "fieldset"; + }, + { dir: "parentNode", next: "legend" } + ); + +// Optimize for push.apply( _, NodeList ) +try { + push.apply( + ( arr = slice.call( preferredDoc.childNodes ) ), + preferredDoc.childNodes + ); + + // Support: Android<4.0 + // Detect silently failing push.apply + // eslint-disable-next-line no-unused-expressions + arr[ preferredDoc.childNodes.length ].nodeType; +} catch ( e ) { + push = { apply: arr.length ? + + // Leverage slice if possible + function( target, els ) { + pushNative.apply( target, slice.call( els ) ); + } : + + // Support: IE<9 + // Otherwise append directly + function( target, els ) { + var j = target.length, + i = 0; + + // Can't trust NodeList.length + while ( ( target[ j++ ] = els[ i++ ] ) ) {} + target.length = j - 1; + } + }; +} + +function Sizzle( selector, context, results, seed ) { + var m, i, elem, nid, match, groups, newSelector, + newContext = context && context.ownerDocument, + + // nodeType defaults to 9, since context defaults to document + nodeType = context ? context.nodeType : 9; + + results = results || []; + + // Return early from calls with invalid selector or context + if ( typeof selector !== "string" || !selector || + nodeType !== 1 && nodeType !== 9 && nodeType !== 11 ) { + + return results; + } + + // Try to shortcut find operations (as opposed to filters) in HTML documents + if ( !seed ) { + setDocument( context ); + context = context || document; + + if ( documentIsHTML ) { + + // If the selector is sufficiently simple, try using a "get*By*" DOM method + // (excepting DocumentFragment context, where the methods don't exist) + if ( nodeType !== 11 && ( match = rquickExpr.exec( selector ) ) ) { + + // ID selector + if ( ( m = match[ 1 ] ) ) { + + // Document context + if ( nodeType === 9 ) { + if ( ( elem = context.getElementById( m ) ) ) { + + // Support: IE, Opera, Webkit + // TODO: identify versions + // getElementById can match elements by name instead of ID + if ( elem.id === m ) { + results.push( elem ); + return results; + } + } else { + return results; + } + + // Element context + } else { + + // Support: IE, Opera, Webkit + // TODO: identify versions + // getElementById can match elements by name instead of ID + if ( newContext && ( elem = newContext.getElementById( m ) ) && + contains( context, elem ) && + elem.id === m ) { + + results.push( elem ); + return results; + } + } + + // Type selector + } else if ( match[ 2 ] ) { + push.apply( results, context.getElementsByTagName( selector ) ); + return results; + + // Class selector + } else if ( ( m = match[ 3 ] ) && support.getElementsByClassName && + context.getElementsByClassName ) { + + push.apply( results, context.getElementsByClassName( m ) ); + return results; + } + } + + // Take advantage of querySelectorAll + if ( support.qsa && + !nonnativeSelectorCache[ selector + " " ] && + ( !rbuggyQSA || !rbuggyQSA.test( selector ) ) && + + // Support: IE 8 only + // Exclude object elements + ( nodeType !== 1 || context.nodeName.toLowerCase() !== "object" ) ) { + + newSelector = selector; + newContext = context; + + // qSA considers elements outside a scoping root when evaluating child or + // descendant combinators, which is not what we want. + // In such cases, we work around the behavior by prefixing every selector in the + // list with an ID selector referencing the scope context. + // The technique has to be used as well when a leading combinator is used + // as such selectors are not recognized by querySelectorAll. + // Thanks to Andrew Dupont for this technique. + if ( nodeType === 1 && + ( rdescend.test( selector ) || rcombinators.test( selector ) ) ) { + + // Expand context for sibling selectors + newContext = rsibling.test( selector ) && testContext( context.parentNode ) || + context; + + // We can use :scope instead of the ID hack if the browser + // supports it & if we're not changing the context. + if ( newContext !== context || !support.scope ) { + + // Capture the context ID, setting it first if necessary + if ( ( nid = context.getAttribute( "id" ) ) ) { + nid = nid.replace( rcssescape, fcssescape ); + } else { + context.setAttribute( "id", ( nid = expando ) ); + } + } + + // Prefix every selector in the list + groups = tokenize( selector ); + i = groups.length; + while ( i-- ) { + groups[ i ] = ( nid ? "#" + nid : ":scope" ) + " " + + toSelector( groups[ i ] ); + } + newSelector = groups.join( "," ); + } + + try { + push.apply( results, + newContext.querySelectorAll( newSelector ) + ); + return results; + } catch ( qsaError ) { + nonnativeSelectorCache( selector, true ); + } finally { + if ( nid === expando ) { + context.removeAttribute( "id" ); + } + } + } + } + } + + // All others + return select( selector.replace( rtrim, "$1" ), context, results, seed ); +} + +/** + * Create key-value caches of limited size + * @returns {function(string, object)} Returns the Object data after storing it on itself with + * property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength) + * deleting the oldest entry + */ +function createCache() { + var keys = []; + + function cache( key, value ) { + + // Use (key + " ") to avoid collision with native prototype properties (see Issue #157) + if ( keys.push( key + " " ) > Expr.cacheLength ) { + + // Only keep the most recent entries + delete cache[ keys.shift() ]; + } + return ( cache[ key + " " ] = value ); + } + return cache; +} + +/** + * Mark a function for special use by Sizzle + * @param {Function} fn The function to mark + */ +function markFunction( fn ) { + fn[ expando ] = true; + return fn; +} + +/** + * Support testing using an element + * @param {Function} fn Passed the created element and returns a boolean result + */ +function assert( fn ) { + var el = document.createElement( "fieldset" ); + + try { + return !!fn( el ); + } catch ( e ) { + return false; + } finally { + + // Remove from its parent by default + if ( el.parentNode ) { + el.parentNode.removeChild( el ); + } + + // release memory in IE + el = null; + } +} + +/** + * Adds the same handler for all of the specified attrs + * @param {String} attrs Pipe-separated list of attributes + * @param {Function} handler The method that will be applied + */ +function addHandle( attrs, handler ) { + var arr = attrs.split( "|" ), + i = arr.length; + + while ( i-- ) { + Expr.attrHandle[ arr[ i ] ] = handler; + } +} + +/** + * Checks document order of two siblings + * @param {Element} a + * @param {Element} b + * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b + */ +function siblingCheck( a, b ) { + var cur = b && a, + diff = cur && a.nodeType === 1 && b.nodeType === 1 && + a.sourceIndex - b.sourceIndex; + + // Use IE sourceIndex if available on both nodes + if ( diff ) { + return diff; + } + + // Check if b follows a + if ( cur ) { + while ( ( cur = cur.nextSibling ) ) { + if ( cur === b ) { + return -1; + } + } + } + + return a ? 1 : -1; +} + +/** + * Returns a function to use in pseudos for input types + * @param {String} type + */ +function createInputPseudo( type ) { + return function( elem ) { + var name = elem.nodeName.toLowerCase(); + return name === "input" && elem.type === type; + }; +} + +/** + * Returns a function to use in pseudos for buttons + * @param {String} type + */ +function createButtonPseudo( type ) { + return function( elem ) { + var name = elem.nodeName.toLowerCase(); + return ( name === "input" || name === "button" ) && elem.type === type; + }; +} + +/** + * Returns a function to use in pseudos for :enabled/:disabled + * @param {Boolean} disabled true for :disabled; false for :enabled + */ +function createDisabledPseudo( disabled ) { + + // Known :disabled false positives: fieldset[disabled] > legend:nth-of-type(n+2) :can-disable + return function( elem ) { + + // Only certain elements can match :enabled or :disabled + // https://html.spec.whatwg.org/multipage/scripting.html#selector-enabled + // https://html.spec.whatwg.org/multipage/scripting.html#selector-disabled + if ( "form" in elem ) { + + // Check for inherited disabledness on relevant non-disabled elements: + // * listed form-associated elements in a disabled fieldset + // https://html.spec.whatwg.org/multipage/forms.html#category-listed + // https://html.spec.whatwg.org/multipage/forms.html#concept-fe-disabled + // * option elements in a disabled optgroup + // https://html.spec.whatwg.org/multipage/forms.html#concept-option-disabled + // All such elements have a "form" property. + if ( elem.parentNode && elem.disabled === false ) { + + // Option elements defer to a parent optgroup if present + if ( "label" in elem ) { + if ( "label" in elem.parentNode ) { + return elem.parentNode.disabled === disabled; + } else { + return elem.disabled === disabled; + } + } + + // Support: IE 6 - 11 + // Use the isDisabled shortcut property to check for disabled fieldset ancestors + return elem.isDisabled === disabled || + + // Where there is no isDisabled, check manually + /* jshint -W018 */ + elem.isDisabled !== !disabled && + inDisabledFieldset( elem ) === disabled; + } + + return elem.disabled === disabled; + + // Try to winnow out elements that can't be disabled before trusting the disabled property. + // Some victims get caught in our net (label, legend, menu, track), but it shouldn't + // even exist on them, let alone have a boolean value. + } else if ( "label" in elem ) { + return elem.disabled === disabled; + } + + // Remaining elements are neither :enabled nor :disabled + return false; + }; +} + +/** + * Returns a function to use in pseudos for positionals + * @param {Function} fn + */ +function createPositionalPseudo( fn ) { + return markFunction( function( argument ) { + argument = +argument; + return markFunction( function( seed, matches ) { + var j, + matchIndexes = fn( [], seed.length, argument ), + i = matchIndexes.length; + + // Match elements found at the specified indexes + while ( i-- ) { + if ( seed[ ( j = matchIndexes[ i ] ) ] ) { + seed[ j ] = !( matches[ j ] = seed[ j ] ); + } + } + } ); + } ); +} + +/** + * Checks a node for validity as a Sizzle context + * @param {Element|Object=} context + * @returns {Element|Object|Boolean} The input node if acceptable, otherwise a falsy value + */ +function testContext( context ) { + return context && typeof context.getElementsByTagName !== "undefined" && context; +} + +// Expose support vars for convenience +support = Sizzle.support = {}; + +/** + * Detects XML nodes + * @param {Element|Object} elem An element or a document + * @returns {Boolean} True iff elem is a non-HTML XML node + */ +isXML = Sizzle.isXML = function( elem ) { + var namespace = elem.namespaceURI, + docElem = ( elem.ownerDocument || elem ).documentElement; + + // Support: IE <=8 + // Assume HTML when documentElement doesn't yet exist, such as inside loading iframes + // https://bugs.jquery.com/ticket/4833 + return !rhtml.test( namespace || docElem && docElem.nodeName || "HTML" ); +}; + +/** + * Sets document-related variables once based on the current document + * @param {Element|Object} [doc] An element or document object to use to set the document + * @returns {Object} Returns the current document + */ +setDocument = Sizzle.setDocument = function( node ) { + var hasCompare, subWindow, + doc = node ? node.ownerDocument || node : preferredDoc; + + // Return early if doc is invalid or already selected + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( doc == document || doc.nodeType !== 9 || !doc.documentElement ) { + return document; + } + + // Update global variables + document = doc; + docElem = document.documentElement; + documentIsHTML = !isXML( document ); + + // Support: IE 9 - 11+, Edge 12 - 18+ + // Accessing iframe documents after unload throws "permission denied" errors (jQuery #13936) + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( preferredDoc != document && + ( subWindow = document.defaultView ) && subWindow.top !== subWindow ) { + + // Support: IE 11, Edge + if ( subWindow.addEventListener ) { + subWindow.addEventListener( "unload", unloadHandler, false ); + + // Support: IE 9 - 10 only + } else if ( subWindow.attachEvent ) { + subWindow.attachEvent( "onunload", unloadHandler ); + } + } + + // Support: IE 8 - 11+, Edge 12 - 18+, Chrome <=16 - 25 only, Firefox <=3.6 - 31 only, + // Safari 4 - 5 only, Opera <=11.6 - 12.x only + // IE/Edge & older browsers don't support the :scope pseudo-class. + // Support: Safari 6.0 only + // Safari 6.0 supports :scope but it's an alias of :root there. + support.scope = assert( function( el ) { + docElem.appendChild( el ).appendChild( document.createElement( "div" ) ); + return typeof el.querySelectorAll !== "undefined" && + !el.querySelectorAll( ":scope fieldset div" ).length; + } ); + + /* Attributes + ---------------------------------------------------------------------- */ + + // Support: IE<8 + // Verify that getAttribute really returns attributes and not properties + // (excepting IE8 booleans) + support.attributes = assert( function( el ) { + el.className = "i"; + return !el.getAttribute( "className" ); + } ); + + /* getElement(s)By* + ---------------------------------------------------------------------- */ + + // Check if getElementsByTagName("*") returns only elements + support.getElementsByTagName = assert( function( el ) { + el.appendChild( document.createComment( "" ) ); + return !el.getElementsByTagName( "*" ).length; + } ); + + // Support: IE<9 + support.getElementsByClassName = rnative.test( document.getElementsByClassName ); + + // Support: IE<10 + // Check if getElementById returns elements by name + // The broken getElementById methods don't pick up programmatically-set names, + // so use a roundabout getElementsByName test + support.getById = assert( function( el ) { + docElem.appendChild( el ).id = expando; + return !document.getElementsByName || !document.getElementsByName( expando ).length; + } ); + + // ID filter and find + if ( support.getById ) { + Expr.filter[ "ID" ] = function( id ) { + var attrId = id.replace( runescape, funescape ); + return function( elem ) { + return elem.getAttribute( "id" ) === attrId; + }; + }; + Expr.find[ "ID" ] = function( id, context ) { + if ( typeof context.getElementById !== "undefined" && documentIsHTML ) { + var elem = context.getElementById( id ); + return elem ? [ elem ] : []; + } + }; + } else { + Expr.filter[ "ID" ] = function( id ) { + var attrId = id.replace( runescape, funescape ); + return function( elem ) { + var node = typeof elem.getAttributeNode !== "undefined" && + elem.getAttributeNode( "id" ); + return node && node.value === attrId; + }; + }; + + // Support: IE 6 - 7 only + // getElementById is not reliable as a find shortcut + Expr.find[ "ID" ] = function( id, context ) { + if ( typeof context.getElementById !== "undefined" && documentIsHTML ) { + var node, i, elems, + elem = context.getElementById( id ); + + if ( elem ) { + + // Verify the id attribute + node = elem.getAttributeNode( "id" ); + if ( node && node.value === id ) { + return [ elem ]; + } + + // Fall back on getElementsByName + elems = context.getElementsByName( id ); + i = 0; + while ( ( elem = elems[ i++ ] ) ) { + node = elem.getAttributeNode( "id" ); + if ( node && node.value === id ) { + return [ elem ]; + } + } + } + + return []; + } + }; + } + + // Tag + Expr.find[ "TAG" ] = support.getElementsByTagName ? + function( tag, context ) { + if ( typeof context.getElementsByTagName !== "undefined" ) { + return context.getElementsByTagName( tag ); + + // DocumentFragment nodes don't have gEBTN + } else if ( support.qsa ) { + return context.querySelectorAll( tag ); + } + } : + + function( tag, context ) { + var elem, + tmp = [], + i = 0, + + // By happy coincidence, a (broken) gEBTN appears on DocumentFragment nodes too + results = context.getElementsByTagName( tag ); + + // Filter out possible comments + if ( tag === "*" ) { + while ( ( elem = results[ i++ ] ) ) { + if ( elem.nodeType === 1 ) { + tmp.push( elem ); + } + } + + return tmp; + } + return results; + }; + + // Class + Expr.find[ "CLASS" ] = support.getElementsByClassName && function( className, context ) { + if ( typeof context.getElementsByClassName !== "undefined" && documentIsHTML ) { + return context.getElementsByClassName( className ); + } + }; + + /* QSA/matchesSelector + ---------------------------------------------------------------------- */ + + // QSA and matchesSelector support + + // matchesSelector(:active) reports false when true (IE9/Opera 11.5) + rbuggyMatches = []; + + // qSa(:focus) reports false when true (Chrome 21) + // We allow this because of a bug in IE8/9 that throws an error + // whenever `document.activeElement` is accessed on an iframe + // So, we allow :focus to pass through QSA all the time to avoid the IE error + // See https://bugs.jquery.com/ticket/13378 + rbuggyQSA = []; + + if ( ( support.qsa = rnative.test( document.querySelectorAll ) ) ) { + + // Build QSA regex + // Regex strategy adopted from Diego Perini + assert( function( el ) { + + var input; + + // Select is set to empty string on purpose + // This is to test IE's treatment of not explicitly + // setting a boolean content attribute, + // since its presence should be enough + // https://bugs.jquery.com/ticket/12359 + docElem.appendChild( el ).innerHTML = "" + + ""; + + // Support: IE8, Opera 11-12.16 + // Nothing should be selected when empty strings follow ^= or $= or *= + // The test attribute must be unknown in Opera but "safe" for WinRT + // https://msdn.microsoft.com/en-us/library/ie/hh465388.aspx#attribute_section + if ( el.querySelectorAll( "[msallowcapture^='']" ).length ) { + rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:''|\"\")" ); + } + + // Support: IE8 + // Boolean attributes and "value" are not treated correctly + if ( !el.querySelectorAll( "[selected]" ).length ) { + rbuggyQSA.push( "\\[" + whitespace + "*(?:value|" + booleans + ")" ); + } + + // Support: Chrome<29, Android<4.4, Safari<7.0+, iOS<7.0+, PhantomJS<1.9.8+ + if ( !el.querySelectorAll( "[id~=" + expando + "-]" ).length ) { + rbuggyQSA.push( "~=" ); + } + + // Support: IE 11+, Edge 15 - 18+ + // IE 11/Edge don't find elements on a `[name='']` query in some cases. + // Adding a temporary attribute to the document before the selection works + // around the issue. + // Interestingly, IE 10 & older don't seem to have the issue. + input = document.createElement( "input" ); + input.setAttribute( "name", "" ); + el.appendChild( input ); + if ( !el.querySelectorAll( "[name='']" ).length ) { + rbuggyQSA.push( "\\[" + whitespace + "*name" + whitespace + "*=" + + whitespace + "*(?:''|\"\")" ); + } + + // Webkit/Opera - :checked should return selected option elements + // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked + // IE8 throws error here and will not see later tests + if ( !el.querySelectorAll( ":checked" ).length ) { + rbuggyQSA.push( ":checked" ); + } + + // Support: Safari 8+, iOS 8+ + // https://bugs.webkit.org/show_bug.cgi?id=136851 + // In-page `selector#id sibling-combinator selector` fails + if ( !el.querySelectorAll( "a#" + expando + "+*" ).length ) { + rbuggyQSA.push( ".#.+[+~]" ); + } + + // Support: Firefox <=3.6 - 5 only + // Old Firefox doesn't throw on a badly-escaped identifier. + el.querySelectorAll( "\\\f" ); + rbuggyQSA.push( "[\\r\\n\\f]" ); + } ); + + assert( function( el ) { + el.innerHTML = "" + + ""; + + // Support: Windows 8 Native Apps + // The type and name attributes are restricted during .innerHTML assignment + var input = document.createElement( "input" ); + input.setAttribute( "type", "hidden" ); + el.appendChild( input ).setAttribute( "name", "D" ); + + // Support: IE8 + // Enforce case-sensitivity of name attribute + if ( el.querySelectorAll( "[name=d]" ).length ) { + rbuggyQSA.push( "name" + whitespace + "*[*^$|!~]?=" ); + } + + // FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled) + // IE8 throws error here and will not see later tests + if ( el.querySelectorAll( ":enabled" ).length !== 2 ) { + rbuggyQSA.push( ":enabled", ":disabled" ); + } + + // Support: IE9-11+ + // IE's :disabled selector does not pick up the children of disabled fieldsets + docElem.appendChild( el ).disabled = true; + if ( el.querySelectorAll( ":disabled" ).length !== 2 ) { + rbuggyQSA.push( ":enabled", ":disabled" ); + } + + // Support: Opera 10 - 11 only + // Opera 10-11 does not throw on post-comma invalid pseudos + el.querySelectorAll( "*,:x" ); + rbuggyQSA.push( ",.*:" ); + } ); + } + + if ( ( support.matchesSelector = rnative.test( ( matches = docElem.matches || + docElem.webkitMatchesSelector || + docElem.mozMatchesSelector || + docElem.oMatchesSelector || + docElem.msMatchesSelector ) ) ) ) { + + assert( function( el ) { + + // Check to see if it's possible to do matchesSelector + // on a disconnected node (IE 9) + support.disconnectedMatch = matches.call( el, "*" ); + + // This should fail with an exception + // Gecko does not error, returns false instead + matches.call( el, "[s!='']:x" ); + rbuggyMatches.push( "!=", pseudos ); + } ); + } + + rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join( "|" ) ); + rbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join( "|" ) ); + + /* Contains + ---------------------------------------------------------------------- */ + hasCompare = rnative.test( docElem.compareDocumentPosition ); + + // Element contains another + // Purposefully self-exclusive + // As in, an element does not contain itself + contains = hasCompare || rnative.test( docElem.contains ) ? + function( a, b ) { + var adown = a.nodeType === 9 ? a.documentElement : a, + bup = b && b.parentNode; + return a === bup || !!( bup && bup.nodeType === 1 && ( + adown.contains ? + adown.contains( bup ) : + a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16 + ) ); + } : + function( a, b ) { + if ( b ) { + while ( ( b = b.parentNode ) ) { + if ( b === a ) { + return true; + } + } + } + return false; + }; + + /* Sorting + ---------------------------------------------------------------------- */ + + // Document order sorting + sortOrder = hasCompare ? + function( a, b ) { + + // Flag for duplicate removal + if ( a === b ) { + hasDuplicate = true; + return 0; + } + + // Sort on method existence if only one input has compareDocumentPosition + var compare = !a.compareDocumentPosition - !b.compareDocumentPosition; + if ( compare ) { + return compare; + } + + // Calculate position if both inputs belong to the same document + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + compare = ( a.ownerDocument || a ) == ( b.ownerDocument || b ) ? + a.compareDocumentPosition( b ) : + + // Otherwise we know they are disconnected + 1; + + // Disconnected nodes + if ( compare & 1 || + ( !support.sortDetached && b.compareDocumentPosition( a ) === compare ) ) { + + // Choose the first element that is related to our preferred document + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( a == document || a.ownerDocument == preferredDoc && + contains( preferredDoc, a ) ) { + return -1; + } + + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( b == document || b.ownerDocument == preferredDoc && + contains( preferredDoc, b ) ) { + return 1; + } + + // Maintain original order + return sortInput ? + ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) : + 0; + } + + return compare & 4 ? -1 : 1; + } : + function( a, b ) { + + // Exit early if the nodes are identical + if ( a === b ) { + hasDuplicate = true; + return 0; + } + + var cur, + i = 0, + aup = a.parentNode, + bup = b.parentNode, + ap = [ a ], + bp = [ b ]; + + // Parentless nodes are either documents or disconnected + if ( !aup || !bup ) { + + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + /* eslint-disable eqeqeq */ + return a == document ? -1 : + b == document ? 1 : + /* eslint-enable eqeqeq */ + aup ? -1 : + bup ? 1 : + sortInput ? + ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) : + 0; + + // If the nodes are siblings, we can do a quick check + } else if ( aup === bup ) { + return siblingCheck( a, b ); + } + + // Otherwise we need full lists of their ancestors for comparison + cur = a; + while ( ( cur = cur.parentNode ) ) { + ap.unshift( cur ); + } + cur = b; + while ( ( cur = cur.parentNode ) ) { + bp.unshift( cur ); + } + + // Walk down the tree looking for a discrepancy + while ( ap[ i ] === bp[ i ] ) { + i++; + } + + return i ? + + // Do a sibling check if the nodes have a common ancestor + siblingCheck( ap[ i ], bp[ i ] ) : + + // Otherwise nodes in our document sort first + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + /* eslint-disable eqeqeq */ + ap[ i ] == preferredDoc ? -1 : + bp[ i ] == preferredDoc ? 1 : + /* eslint-enable eqeqeq */ + 0; + }; + + return document; +}; + +Sizzle.matches = function( expr, elements ) { + return Sizzle( expr, null, null, elements ); +}; + +Sizzle.matchesSelector = function( elem, expr ) { + setDocument( elem ); + + if ( support.matchesSelector && documentIsHTML && + !nonnativeSelectorCache[ expr + " " ] && + ( !rbuggyMatches || !rbuggyMatches.test( expr ) ) && + ( !rbuggyQSA || !rbuggyQSA.test( expr ) ) ) { + + try { + var ret = matches.call( elem, expr ); + + // IE 9's matchesSelector returns false on disconnected nodes + if ( ret || support.disconnectedMatch || + + // As well, disconnected nodes are said to be in a document + // fragment in IE 9 + elem.document && elem.document.nodeType !== 11 ) { + return ret; + } + } catch ( e ) { + nonnativeSelectorCache( expr, true ); + } + } + + return Sizzle( expr, document, null, [ elem ] ).length > 0; +}; + +Sizzle.contains = function( context, elem ) { + + // Set document vars if needed + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( ( context.ownerDocument || context ) != document ) { + setDocument( context ); + } + return contains( context, elem ); +}; + +Sizzle.attr = function( elem, name ) { + + // Set document vars if needed + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( ( elem.ownerDocument || elem ) != document ) { + setDocument( elem ); + } + + var fn = Expr.attrHandle[ name.toLowerCase() ], + + // Don't get fooled by Object.prototype properties (jQuery #13807) + val = fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ? + fn( elem, name, !documentIsHTML ) : + undefined; + + return val !== undefined ? + val : + support.attributes || !documentIsHTML ? + elem.getAttribute( name ) : + ( val = elem.getAttributeNode( name ) ) && val.specified ? + val.value : + null; +}; + +Sizzle.escape = function( sel ) { + return ( sel + "" ).replace( rcssescape, fcssescape ); +}; + +Sizzle.error = function( msg ) { + throw new Error( "Syntax error, unrecognized expression: " + msg ); +}; + +/** + * Document sorting and removing duplicates + * @param {ArrayLike} results + */ +Sizzle.uniqueSort = function( results ) { + var elem, + duplicates = [], + j = 0, + i = 0; + + // Unless we *know* we can detect duplicates, assume their presence + hasDuplicate = !support.detectDuplicates; + sortInput = !support.sortStable && results.slice( 0 ); + results.sort( sortOrder ); + + if ( hasDuplicate ) { + while ( ( elem = results[ i++ ] ) ) { + if ( elem === results[ i ] ) { + j = duplicates.push( i ); + } + } + while ( j-- ) { + results.splice( duplicates[ j ], 1 ); + } + } + + // Clear input after sorting to release objects + // See https://github.com/jquery/sizzle/pull/225 + sortInput = null; + + return results; +}; + +/** + * Utility function for retrieving the text value of an array of DOM nodes + * @param {Array|Element} elem + */ +getText = Sizzle.getText = function( elem ) { + var node, + ret = "", + i = 0, + nodeType = elem.nodeType; + + if ( !nodeType ) { + + // If no nodeType, this is expected to be an array + while ( ( node = elem[ i++ ] ) ) { + + // Do not traverse comment nodes + ret += getText( node ); + } + } else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) { + + // Use textContent for elements + // innerText usage removed for consistency of new lines (jQuery #11153) + if ( typeof elem.textContent === "string" ) { + return elem.textContent; + } else { + + // Traverse its children + for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { + ret += getText( elem ); + } + } + } else if ( nodeType === 3 || nodeType === 4 ) { + return elem.nodeValue; + } + + // Do not include comment or processing instruction nodes + + return ret; +}; + +Expr = Sizzle.selectors = { + + // Can be adjusted by the user + cacheLength: 50, + + createPseudo: markFunction, + + match: matchExpr, + + attrHandle: {}, + + find: {}, + + relative: { + ">": { dir: "parentNode", first: true }, + " ": { dir: "parentNode" }, + "+": { dir: "previousSibling", first: true }, + "~": { dir: "previousSibling" } + }, + + preFilter: { + "ATTR": function( match ) { + match[ 1 ] = match[ 1 ].replace( runescape, funescape ); + + // Move the given value to match[3] whether quoted or unquoted + match[ 3 ] = ( match[ 3 ] || match[ 4 ] || + match[ 5 ] || "" ).replace( runescape, funescape ); + + if ( match[ 2 ] === "~=" ) { + match[ 3 ] = " " + match[ 3 ] + " "; + } + + return match.slice( 0, 4 ); + }, + + "CHILD": function( match ) { + + /* matches from matchExpr["CHILD"] + 1 type (only|nth|...) + 2 what (child|of-type) + 3 argument (even|odd|\d*|\d*n([+-]\d+)?|...) + 4 xn-component of xn+y argument ([+-]?\d*n|) + 5 sign of xn-component + 6 x of xn-component + 7 sign of y-component + 8 y of y-component + */ + match[ 1 ] = match[ 1 ].toLowerCase(); + + if ( match[ 1 ].slice( 0, 3 ) === "nth" ) { + + // nth-* requires argument + if ( !match[ 3 ] ) { + Sizzle.error( match[ 0 ] ); + } + + // numeric x and y parameters for Expr.filter.CHILD + // remember that false/true cast respectively to 0/1 + match[ 4 ] = +( match[ 4 ] ? + match[ 5 ] + ( match[ 6 ] || 1 ) : + 2 * ( match[ 3 ] === "even" || match[ 3 ] === "odd" ) ); + match[ 5 ] = +( ( match[ 7 ] + match[ 8 ] ) || match[ 3 ] === "odd" ); + + // other types prohibit arguments + } else if ( match[ 3 ] ) { + Sizzle.error( match[ 0 ] ); + } + + return match; + }, + + "PSEUDO": function( match ) { + var excess, + unquoted = !match[ 6 ] && match[ 2 ]; + + if ( matchExpr[ "CHILD" ].test( match[ 0 ] ) ) { + return null; + } + + // Accept quoted arguments as-is + if ( match[ 3 ] ) { + match[ 2 ] = match[ 4 ] || match[ 5 ] || ""; + + // Strip excess characters from unquoted arguments + } else if ( unquoted && rpseudo.test( unquoted ) && + + // Get excess from tokenize (recursively) + ( excess = tokenize( unquoted, true ) ) && + + // advance to the next closing parenthesis + ( excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length ) ) { + + // excess is a negative index + match[ 0 ] = match[ 0 ].slice( 0, excess ); + match[ 2 ] = unquoted.slice( 0, excess ); + } + + // Return only captures needed by the pseudo filter method (type and argument) + return match.slice( 0, 3 ); + } + }, + + filter: { + + "TAG": function( nodeNameSelector ) { + var nodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase(); + return nodeNameSelector === "*" ? + function() { + return true; + } : + function( elem ) { + return elem.nodeName && elem.nodeName.toLowerCase() === nodeName; + }; + }, + + "CLASS": function( className ) { + var pattern = classCache[ className + " " ]; + + return pattern || + ( pattern = new RegExp( "(^|" + whitespace + + ")" + className + "(" + whitespace + "|$)" ) ) && classCache( + className, function( elem ) { + return pattern.test( + typeof elem.className === "string" && elem.className || + typeof elem.getAttribute !== "undefined" && + elem.getAttribute( "class" ) || + "" + ); + } ); + }, + + "ATTR": function( name, operator, check ) { + return function( elem ) { + var result = Sizzle.attr( elem, name ); + + if ( result == null ) { + return operator === "!="; + } + if ( !operator ) { + return true; + } + + result += ""; + + /* eslint-disable max-len */ + + return operator === "=" ? result === check : + operator === "!=" ? result !== check : + operator === "^=" ? check && result.indexOf( check ) === 0 : + operator === "*=" ? check && result.indexOf( check ) > -1 : + operator === "$=" ? check && result.slice( -check.length ) === check : + operator === "~=" ? ( " " + result.replace( rwhitespace, " " ) + " " ).indexOf( check ) > -1 : + operator === "|=" ? result === check || result.slice( 0, check.length + 1 ) === check + "-" : + false; + /* eslint-enable max-len */ + + }; + }, + + "CHILD": function( type, what, _argument, first, last ) { + var simple = type.slice( 0, 3 ) !== "nth", + forward = type.slice( -4 ) !== "last", + ofType = what === "of-type"; + + return first === 1 && last === 0 ? + + // Shortcut for :nth-*(n) + function( elem ) { + return !!elem.parentNode; + } : + + function( elem, _context, xml ) { + var cache, uniqueCache, outerCache, node, nodeIndex, start, + dir = simple !== forward ? "nextSibling" : "previousSibling", + parent = elem.parentNode, + name = ofType && elem.nodeName.toLowerCase(), + useCache = !xml && !ofType, + diff = false; + + if ( parent ) { + + // :(first|last|only)-(child|of-type) + if ( simple ) { + while ( dir ) { + node = elem; + while ( ( node = node[ dir ] ) ) { + if ( ofType ? + node.nodeName.toLowerCase() === name : + node.nodeType === 1 ) { + + return false; + } + } + + // Reverse direction for :only-* (if we haven't yet done so) + start = dir = type === "only" && !start && "nextSibling"; + } + return true; + } + + start = [ forward ? parent.firstChild : parent.lastChild ]; + + // non-xml :nth-child(...) stores cache data on `parent` + if ( forward && useCache ) { + + // Seek `elem` from a previously-cached index + + // ...in a gzip-friendly way + node = parent; + outerCache = node[ expando ] || ( node[ expando ] = {} ); + + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ node.uniqueID ] || + ( outerCache[ node.uniqueID ] = {} ); + + cache = uniqueCache[ type ] || []; + nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ]; + diff = nodeIndex && cache[ 2 ]; + node = nodeIndex && parent.childNodes[ nodeIndex ]; + + while ( ( node = ++nodeIndex && node && node[ dir ] || + + // Fallback to seeking `elem` from the start + ( diff = nodeIndex = 0 ) || start.pop() ) ) { + + // When found, cache indexes on `parent` and break + if ( node.nodeType === 1 && ++diff && node === elem ) { + uniqueCache[ type ] = [ dirruns, nodeIndex, diff ]; + break; + } + } + + } else { + + // Use previously-cached element index if available + if ( useCache ) { + + // ...in a gzip-friendly way + node = elem; + outerCache = node[ expando ] || ( node[ expando ] = {} ); + + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ node.uniqueID ] || + ( outerCache[ node.uniqueID ] = {} ); + + cache = uniqueCache[ type ] || []; + nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ]; + diff = nodeIndex; + } + + // xml :nth-child(...) + // or :nth-last-child(...) or :nth(-last)?-of-type(...) + if ( diff === false ) { + + // Use the same loop as above to seek `elem` from the start + while ( ( node = ++nodeIndex && node && node[ dir ] || + ( diff = nodeIndex = 0 ) || start.pop() ) ) { + + if ( ( ofType ? + node.nodeName.toLowerCase() === name : + node.nodeType === 1 ) && + ++diff ) { + + // Cache the index of each encountered element + if ( useCache ) { + outerCache = node[ expando ] || + ( node[ expando ] = {} ); + + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ node.uniqueID ] || + ( outerCache[ node.uniqueID ] = {} ); + + uniqueCache[ type ] = [ dirruns, diff ]; + } + + if ( node === elem ) { + break; + } + } + } + } + } + + // Incorporate the offset, then check against cycle size + diff -= last; + return diff === first || ( diff % first === 0 && diff / first >= 0 ); + } + }; + }, + + "PSEUDO": function( pseudo, argument ) { + + // pseudo-class names are case-insensitive + // http://www.w3.org/TR/selectors/#pseudo-classes + // Prioritize by case sensitivity in case custom pseudos are added with uppercase letters + // Remember that setFilters inherits from pseudos + var args, + fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] || + Sizzle.error( "unsupported pseudo: " + pseudo ); + + // The user may use createPseudo to indicate that + // arguments are needed to create the filter function + // just as Sizzle does + if ( fn[ expando ] ) { + return fn( argument ); + } + + // But maintain support for old signatures + if ( fn.length > 1 ) { + args = [ pseudo, pseudo, "", argument ]; + return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ? + markFunction( function( seed, matches ) { + var idx, + matched = fn( seed, argument ), + i = matched.length; + while ( i-- ) { + idx = indexOf( seed, matched[ i ] ); + seed[ idx ] = !( matches[ idx ] = matched[ i ] ); + } + } ) : + function( elem ) { + return fn( elem, 0, args ); + }; + } + + return fn; + } + }, + + pseudos: { + + // Potentially complex pseudos + "not": markFunction( function( selector ) { + + // Trim the selector passed to compile + // to avoid treating leading and trailing + // spaces as combinators + var input = [], + results = [], + matcher = compile( selector.replace( rtrim, "$1" ) ); + + return matcher[ expando ] ? + markFunction( function( seed, matches, _context, xml ) { + var elem, + unmatched = matcher( seed, null, xml, [] ), + i = seed.length; + + // Match elements unmatched by `matcher` + while ( i-- ) { + if ( ( elem = unmatched[ i ] ) ) { + seed[ i ] = !( matches[ i ] = elem ); + } + } + } ) : + function( elem, _context, xml ) { + input[ 0 ] = elem; + matcher( input, null, xml, results ); + + // Don't keep the element (issue #299) + input[ 0 ] = null; + return !results.pop(); + }; + } ), + + "has": markFunction( function( selector ) { + return function( elem ) { + return Sizzle( selector, elem ).length > 0; + }; + } ), + + "contains": markFunction( function( text ) { + text = text.replace( runescape, funescape ); + return function( elem ) { + return ( elem.textContent || getText( elem ) ).indexOf( text ) > -1; + }; + } ), + + // "Whether an element is represented by a :lang() selector + // is based solely on the element's language value + // being equal to the identifier C, + // or beginning with the identifier C immediately followed by "-". + // The matching of C against the element's language value is performed case-insensitively. + // The identifier C does not have to be a valid language name." + // http://www.w3.org/TR/selectors/#lang-pseudo + "lang": markFunction( function( lang ) { + + // lang value must be a valid identifier + if ( !ridentifier.test( lang || "" ) ) { + Sizzle.error( "unsupported lang: " + lang ); + } + lang = lang.replace( runescape, funescape ).toLowerCase(); + return function( elem ) { + var elemLang; + do { + if ( ( elemLang = documentIsHTML ? + elem.lang : + elem.getAttribute( "xml:lang" ) || elem.getAttribute( "lang" ) ) ) { + + elemLang = elemLang.toLowerCase(); + return elemLang === lang || elemLang.indexOf( lang + "-" ) === 0; + } + } while ( ( elem = elem.parentNode ) && elem.nodeType === 1 ); + return false; + }; + } ), + + // Miscellaneous + "target": function( elem ) { + var hash = window.location && window.location.hash; + return hash && hash.slice( 1 ) === elem.id; + }, + + "root": function( elem ) { + return elem === docElem; + }, + + "focus": function( elem ) { + return elem === document.activeElement && + ( !document.hasFocus || document.hasFocus() ) && + !!( elem.type || elem.href || ~elem.tabIndex ); + }, + + // Boolean properties + "enabled": createDisabledPseudo( false ), + "disabled": createDisabledPseudo( true ), + + "checked": function( elem ) { + + // In CSS3, :checked should return both checked and selected elements + // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked + var nodeName = elem.nodeName.toLowerCase(); + return ( nodeName === "input" && !!elem.checked ) || + ( nodeName === "option" && !!elem.selected ); + }, + + "selected": function( elem ) { + + // Accessing this property makes selected-by-default + // options in Safari work properly + if ( elem.parentNode ) { + // eslint-disable-next-line no-unused-expressions + elem.parentNode.selectedIndex; + } + + return elem.selected === true; + }, + + // Contents + "empty": function( elem ) { + + // http://www.w3.org/TR/selectors/#empty-pseudo + // :empty is negated by element (1) or content nodes (text: 3; cdata: 4; entity ref: 5), + // but not by others (comment: 8; processing instruction: 7; etc.) + // nodeType < 6 works because attributes (2) do not appear as children + for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { + if ( elem.nodeType < 6 ) { + return false; + } + } + return true; + }, + + "parent": function( elem ) { + return !Expr.pseudos[ "empty" ]( elem ); + }, + + // Element/input types + "header": function( elem ) { + return rheader.test( elem.nodeName ); + }, + + "input": function( elem ) { + return rinputs.test( elem.nodeName ); + }, + + "button": function( elem ) { + var name = elem.nodeName.toLowerCase(); + return name === "input" && elem.type === "button" || name === "button"; + }, + + "text": function( elem ) { + var attr; + return elem.nodeName.toLowerCase() === "input" && + elem.type === "text" && + + // Support: IE<8 + // New HTML5 attribute values (e.g., "search") appear with elem.type === "text" + ( ( attr = elem.getAttribute( "type" ) ) == null || + attr.toLowerCase() === "text" ); + }, + + // Position-in-collection + "first": createPositionalPseudo( function() { + return [ 0 ]; + } ), + + "last": createPositionalPseudo( function( _matchIndexes, length ) { + return [ length - 1 ]; + } ), + + "eq": createPositionalPseudo( function( _matchIndexes, length, argument ) { + return [ argument < 0 ? argument + length : argument ]; + } ), + + "even": createPositionalPseudo( function( matchIndexes, length ) { + var i = 0; + for ( ; i < length; i += 2 ) { + matchIndexes.push( i ); + } + return matchIndexes; + } ), + + "odd": createPositionalPseudo( function( matchIndexes, length ) { + var i = 1; + for ( ; i < length; i += 2 ) { + matchIndexes.push( i ); + } + return matchIndexes; + } ), + + "lt": createPositionalPseudo( function( matchIndexes, length, argument ) { + var i = argument < 0 ? + argument + length : + argument > length ? + length : + argument; + for ( ; --i >= 0; ) { + matchIndexes.push( i ); + } + return matchIndexes; + } ), + + "gt": createPositionalPseudo( function( matchIndexes, length, argument ) { + var i = argument < 0 ? argument + length : argument; + for ( ; ++i < length; ) { + matchIndexes.push( i ); + } + return matchIndexes; + } ) + } +}; + +Expr.pseudos[ "nth" ] = Expr.pseudos[ "eq" ]; + +// Add button/input type pseudos +for ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) { + Expr.pseudos[ i ] = createInputPseudo( i ); +} +for ( i in { submit: true, reset: true } ) { + Expr.pseudos[ i ] = createButtonPseudo( i ); +} + +// Easy API for creating new setFilters +function setFilters() {} +setFilters.prototype = Expr.filters = Expr.pseudos; +Expr.setFilters = new setFilters(); + +tokenize = Sizzle.tokenize = function( selector, parseOnly ) { + var matched, match, tokens, type, + soFar, groups, preFilters, + cached = tokenCache[ selector + " " ]; + + if ( cached ) { + return parseOnly ? 0 : cached.slice( 0 ); + } + + soFar = selector; + groups = []; + preFilters = Expr.preFilter; + + while ( soFar ) { + + // Comma and first run + if ( !matched || ( match = rcomma.exec( soFar ) ) ) { + if ( match ) { + + // Don't consume trailing commas as valid + soFar = soFar.slice( match[ 0 ].length ) || soFar; + } + groups.push( ( tokens = [] ) ); + } + + matched = false; + + // Combinators + if ( ( match = rcombinators.exec( soFar ) ) ) { + matched = match.shift(); + tokens.push( { + value: matched, + + // Cast descendant combinators to space + type: match[ 0 ].replace( rtrim, " " ) + } ); + soFar = soFar.slice( matched.length ); + } + + // Filters + for ( type in Expr.filter ) { + if ( ( match = matchExpr[ type ].exec( soFar ) ) && ( !preFilters[ type ] || + ( match = preFilters[ type ]( match ) ) ) ) { + matched = match.shift(); + tokens.push( { + value: matched, + type: type, + matches: match + } ); + soFar = soFar.slice( matched.length ); + } + } + + if ( !matched ) { + break; + } + } + + // Return the length of the invalid excess + // if we're just parsing + // Otherwise, throw an error or return tokens + return parseOnly ? + soFar.length : + soFar ? + Sizzle.error( selector ) : + + // Cache the tokens + tokenCache( selector, groups ).slice( 0 ); +}; + +function toSelector( tokens ) { + var i = 0, + len = tokens.length, + selector = ""; + for ( ; i < len; i++ ) { + selector += tokens[ i ].value; + } + return selector; +} + +function addCombinator( matcher, combinator, base ) { + var dir = combinator.dir, + skip = combinator.next, + key = skip || dir, + checkNonElements = base && key === "parentNode", + doneName = done++; + + return combinator.first ? + + // Check against closest ancestor/preceding element + function( elem, context, xml ) { + while ( ( elem = elem[ dir ] ) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + return matcher( elem, context, xml ); + } + } + return false; + } : + + // Check against all ancestor/preceding elements + function( elem, context, xml ) { + var oldCache, uniqueCache, outerCache, + newCache = [ dirruns, doneName ]; + + // We can't set arbitrary data on XML nodes, so they don't benefit from combinator caching + if ( xml ) { + while ( ( elem = elem[ dir ] ) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + if ( matcher( elem, context, xml ) ) { + return true; + } + } + } + } else { + while ( ( elem = elem[ dir ] ) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + outerCache = elem[ expando ] || ( elem[ expando ] = {} ); + + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ elem.uniqueID ] || + ( outerCache[ elem.uniqueID ] = {} ); + + if ( skip && skip === elem.nodeName.toLowerCase() ) { + elem = elem[ dir ] || elem; + } else if ( ( oldCache = uniqueCache[ key ] ) && + oldCache[ 0 ] === dirruns && oldCache[ 1 ] === doneName ) { + + // Assign to newCache so results back-propagate to previous elements + return ( newCache[ 2 ] = oldCache[ 2 ] ); + } else { + + // Reuse newcache so results back-propagate to previous elements + uniqueCache[ key ] = newCache; + + // A match means we're done; a fail means we have to keep checking + if ( ( newCache[ 2 ] = matcher( elem, context, xml ) ) ) { + return true; + } + } + } + } + } + return false; + }; +} + +function elementMatcher( matchers ) { + return matchers.length > 1 ? + function( elem, context, xml ) { + var i = matchers.length; + while ( i-- ) { + if ( !matchers[ i ]( elem, context, xml ) ) { + return false; + } + } + return true; + } : + matchers[ 0 ]; +} + +function multipleContexts( selector, contexts, results ) { + var i = 0, + len = contexts.length; + for ( ; i < len; i++ ) { + Sizzle( selector, contexts[ i ], results ); + } + return results; +} + +function condense( unmatched, map, filter, context, xml ) { + var elem, + newUnmatched = [], + i = 0, + len = unmatched.length, + mapped = map != null; + + for ( ; i < len; i++ ) { + if ( ( elem = unmatched[ i ] ) ) { + if ( !filter || filter( elem, context, xml ) ) { + newUnmatched.push( elem ); + if ( mapped ) { + map.push( i ); + } + } + } + } + + return newUnmatched; +} + +function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) { + if ( postFilter && !postFilter[ expando ] ) { + postFilter = setMatcher( postFilter ); + } + if ( postFinder && !postFinder[ expando ] ) { + postFinder = setMatcher( postFinder, postSelector ); + } + return markFunction( function( seed, results, context, xml ) { + var temp, i, elem, + preMap = [], + postMap = [], + preexisting = results.length, + + // Get initial elements from seed or context + elems = seed || multipleContexts( + selector || "*", + context.nodeType ? [ context ] : context, + [] + ), + + // Prefilter to get matcher input, preserving a map for seed-results synchronization + matcherIn = preFilter && ( seed || !selector ) ? + condense( elems, preMap, preFilter, context, xml ) : + elems, + + matcherOut = matcher ? + + // If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results, + postFinder || ( seed ? preFilter : preexisting || postFilter ) ? + + // ...intermediate processing is necessary + [] : + + // ...otherwise use results directly + results : + matcherIn; + + // Find primary matches + if ( matcher ) { + matcher( matcherIn, matcherOut, context, xml ); + } + + // Apply postFilter + if ( postFilter ) { + temp = condense( matcherOut, postMap ); + postFilter( temp, [], context, xml ); + + // Un-match failing elements by moving them back to matcherIn + i = temp.length; + while ( i-- ) { + if ( ( elem = temp[ i ] ) ) { + matcherOut[ postMap[ i ] ] = !( matcherIn[ postMap[ i ] ] = elem ); + } + } + } + + if ( seed ) { + if ( postFinder || preFilter ) { + if ( postFinder ) { + + // Get the final matcherOut by condensing this intermediate into postFinder contexts + temp = []; + i = matcherOut.length; + while ( i-- ) { + if ( ( elem = matcherOut[ i ] ) ) { + + // Restore matcherIn since elem is not yet a final match + temp.push( ( matcherIn[ i ] = elem ) ); + } + } + postFinder( null, ( matcherOut = [] ), temp, xml ); + } + + // Move matched elements from seed to results to keep them synchronized + i = matcherOut.length; + while ( i-- ) { + if ( ( elem = matcherOut[ i ] ) && + ( temp = postFinder ? indexOf( seed, elem ) : preMap[ i ] ) > -1 ) { + + seed[ temp ] = !( results[ temp ] = elem ); + } + } + } + + // Add elements to results, through postFinder if defined + } else { + matcherOut = condense( + matcherOut === results ? + matcherOut.splice( preexisting, matcherOut.length ) : + matcherOut + ); + if ( postFinder ) { + postFinder( null, results, matcherOut, xml ); + } else { + push.apply( results, matcherOut ); + } + } + } ); +} + +function matcherFromTokens( tokens ) { + var checkContext, matcher, j, + len = tokens.length, + leadingRelative = Expr.relative[ tokens[ 0 ].type ], + implicitRelative = leadingRelative || Expr.relative[ " " ], + i = leadingRelative ? 1 : 0, + + // The foundational matcher ensures that elements are reachable from top-level context(s) + matchContext = addCombinator( function( elem ) { + return elem === checkContext; + }, implicitRelative, true ), + matchAnyContext = addCombinator( function( elem ) { + return indexOf( checkContext, elem ) > -1; + }, implicitRelative, true ), + matchers = [ function( elem, context, xml ) { + var ret = ( !leadingRelative && ( xml || context !== outermostContext ) ) || ( + ( checkContext = context ).nodeType ? + matchContext( elem, context, xml ) : + matchAnyContext( elem, context, xml ) ); + + // Avoid hanging onto element (issue #299) + checkContext = null; + return ret; + } ]; + + for ( ; i < len; i++ ) { + if ( ( matcher = Expr.relative[ tokens[ i ].type ] ) ) { + matchers = [ addCombinator( elementMatcher( matchers ), matcher ) ]; + } else { + matcher = Expr.filter[ tokens[ i ].type ].apply( null, tokens[ i ].matches ); + + // Return special upon seeing a positional matcher + if ( matcher[ expando ] ) { + + // Find the next relative operator (if any) for proper handling + j = ++i; + for ( ; j < len; j++ ) { + if ( Expr.relative[ tokens[ j ].type ] ) { + break; + } + } + return setMatcher( + i > 1 && elementMatcher( matchers ), + i > 1 && toSelector( + + // If the preceding token was a descendant combinator, insert an implicit any-element `*` + tokens + .slice( 0, i - 1 ) + .concat( { value: tokens[ i - 2 ].type === " " ? "*" : "" } ) + ).replace( rtrim, "$1" ), + matcher, + i < j && matcherFromTokens( tokens.slice( i, j ) ), + j < len && matcherFromTokens( ( tokens = tokens.slice( j ) ) ), + j < len && toSelector( tokens ) + ); + } + matchers.push( matcher ); + } + } + + return elementMatcher( matchers ); +} + +function matcherFromGroupMatchers( elementMatchers, setMatchers ) { + var bySet = setMatchers.length > 0, + byElement = elementMatchers.length > 0, + superMatcher = function( seed, context, xml, results, outermost ) { + var elem, j, matcher, + matchedCount = 0, + i = "0", + unmatched = seed && [], + setMatched = [], + contextBackup = outermostContext, + + // We must always have either seed elements or outermost context + elems = seed || byElement && Expr.find[ "TAG" ]( "*", outermost ), + + // Use integer dirruns iff this is the outermost matcher + dirrunsUnique = ( dirruns += contextBackup == null ? 1 : Math.random() || 0.1 ), + len = elems.length; + + if ( outermost ) { + + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + outermostContext = context == document || context || outermost; + } + + // Add elements passing elementMatchers directly to results + // Support: IE<9, Safari + // Tolerate NodeList properties (IE: "length"; Safari: ) matching elements by id + for ( ; i !== len && ( elem = elems[ i ] ) != null; i++ ) { + if ( byElement && elem ) { + j = 0; + + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( !context && elem.ownerDocument != document ) { + setDocument( elem ); + xml = !documentIsHTML; + } + while ( ( matcher = elementMatchers[ j++ ] ) ) { + if ( matcher( elem, context || document, xml ) ) { + results.push( elem ); + break; + } + } + if ( outermost ) { + dirruns = dirrunsUnique; + } + } + + // Track unmatched elements for set filters + if ( bySet ) { + + // They will have gone through all possible matchers + if ( ( elem = !matcher && elem ) ) { + matchedCount--; + } + + // Lengthen the array for every element, matched or not + if ( seed ) { + unmatched.push( elem ); + } + } + } + + // `i` is now the count of elements visited above, and adding it to `matchedCount` + // makes the latter nonnegative. + matchedCount += i; + + // Apply set filters to unmatched elements + // NOTE: This can be skipped if there are no unmatched elements (i.e., `matchedCount` + // equals `i`), unless we didn't visit _any_ elements in the above loop because we have + // no element matchers and no seed. + // Incrementing an initially-string "0" `i` allows `i` to remain a string only in that + // case, which will result in a "00" `matchedCount` that differs from `i` but is also + // numerically zero. + if ( bySet && i !== matchedCount ) { + j = 0; + while ( ( matcher = setMatchers[ j++ ] ) ) { + matcher( unmatched, setMatched, context, xml ); + } + + if ( seed ) { + + // Reintegrate element matches to eliminate the need for sorting + if ( matchedCount > 0 ) { + while ( i-- ) { + if ( !( unmatched[ i ] || setMatched[ i ] ) ) { + setMatched[ i ] = pop.call( results ); + } + } + } + + // Discard index placeholder values to get only actual matches + setMatched = condense( setMatched ); + } + + // Add matches to results + push.apply( results, setMatched ); + + // Seedless set matches succeeding multiple successful matchers stipulate sorting + if ( outermost && !seed && setMatched.length > 0 && + ( matchedCount + setMatchers.length ) > 1 ) { + + Sizzle.uniqueSort( results ); + } + } + + // Override manipulation of globals by nested matchers + if ( outermost ) { + dirruns = dirrunsUnique; + outermostContext = contextBackup; + } + + return unmatched; + }; + + return bySet ? + markFunction( superMatcher ) : + superMatcher; +} + +compile = Sizzle.compile = function( selector, match /* Internal Use Only */ ) { + var i, + setMatchers = [], + elementMatchers = [], + cached = compilerCache[ selector + " " ]; + + if ( !cached ) { + + // Generate a function of recursive functions that can be used to check each element + if ( !match ) { + match = tokenize( selector ); + } + i = match.length; + while ( i-- ) { + cached = matcherFromTokens( match[ i ] ); + if ( cached[ expando ] ) { + setMatchers.push( cached ); + } else { + elementMatchers.push( cached ); + } + } + + // Cache the compiled function + cached = compilerCache( + selector, + matcherFromGroupMatchers( elementMatchers, setMatchers ) + ); + + // Save selector and tokenization + cached.selector = selector; + } + return cached; +}; + +/** + * A low-level selection function that works with Sizzle's compiled + * selector functions + * @param {String|Function} selector A selector or a pre-compiled + * selector function built with Sizzle.compile + * @param {Element} context + * @param {Array} [results] + * @param {Array} [seed] A set of elements to match against + */ +select = Sizzle.select = function( selector, context, results, seed ) { + var i, tokens, token, type, find, + compiled = typeof selector === "function" && selector, + match = !seed && tokenize( ( selector = compiled.selector || selector ) ); + + results = results || []; + + // Try to minimize operations if there is only one selector in the list and no seed + // (the latter of which guarantees us context) + if ( match.length === 1 ) { + + // Reduce context if the leading compound selector is an ID + tokens = match[ 0 ] = match[ 0 ].slice( 0 ); + if ( tokens.length > 2 && ( token = tokens[ 0 ] ).type === "ID" && + context.nodeType === 9 && documentIsHTML && Expr.relative[ tokens[ 1 ].type ] ) { + + context = ( Expr.find[ "ID" ]( token.matches[ 0 ] + .replace( runescape, funescape ), context ) || [] )[ 0 ]; + if ( !context ) { + return results; + + // Precompiled matchers will still verify ancestry, so step up a level + } else if ( compiled ) { + context = context.parentNode; + } + + selector = selector.slice( tokens.shift().value.length ); + } + + // Fetch a seed set for right-to-left matching + i = matchExpr[ "needsContext" ].test( selector ) ? 0 : tokens.length; + while ( i-- ) { + token = tokens[ i ]; + + // Abort if we hit a combinator + if ( Expr.relative[ ( type = token.type ) ] ) { + break; + } + if ( ( find = Expr.find[ type ] ) ) { + + // Search, expanding context for leading sibling combinators + if ( ( seed = find( + token.matches[ 0 ].replace( runescape, funescape ), + rsibling.test( tokens[ 0 ].type ) && testContext( context.parentNode ) || + context + ) ) ) { + + // If seed is empty or no tokens remain, we can return early + tokens.splice( i, 1 ); + selector = seed.length && toSelector( tokens ); + if ( !selector ) { + push.apply( results, seed ); + return results; + } + + break; + } + } + } + } + + // Compile and execute a filtering function if one is not provided + // Provide `match` to avoid retokenization if we modified the selector above + ( compiled || compile( selector, match ) )( + seed, + context, + !documentIsHTML, + results, + !context || rsibling.test( selector ) && testContext( context.parentNode ) || context + ); + return results; +}; + +// One-time assignments + +// Sort stability +support.sortStable = expando.split( "" ).sort( sortOrder ).join( "" ) === expando; + +// Support: Chrome 14-35+ +// Always assume duplicates if they aren't passed to the comparison function +support.detectDuplicates = !!hasDuplicate; + +// Initialize against the default document +setDocument(); + +// Support: Webkit<537.32 - Safari 6.0.3/Chrome 25 (fixed in Chrome 27) +// Detached nodes confoundingly follow *each other* +support.sortDetached = assert( function( el ) { + + // Should return 1, but returns 4 (following) + return el.compareDocumentPosition( document.createElement( "fieldset" ) ) & 1; +} ); + +// Support: IE<8 +// Prevent attribute/property "interpolation" +// https://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx +if ( !assert( function( el ) { + el.innerHTML = ""; + return el.firstChild.getAttribute( "href" ) === "#"; +} ) ) { + addHandle( "type|href|height|width", function( elem, name, isXML ) { + if ( !isXML ) { + return elem.getAttribute( name, name.toLowerCase() === "type" ? 1 : 2 ); + } + } ); +} + +// Support: IE<9 +// Use defaultValue in place of getAttribute("value") +if ( !support.attributes || !assert( function( el ) { + el.innerHTML = ""; + el.firstChild.setAttribute( "value", "" ); + return el.firstChild.getAttribute( "value" ) === ""; +} ) ) { + addHandle( "value", function( elem, _name, isXML ) { + if ( !isXML && elem.nodeName.toLowerCase() === "input" ) { + return elem.defaultValue; + } + } ); +} + +// Support: IE<9 +// Use getAttributeNode to fetch booleans when getAttribute lies +if ( !assert( function( el ) { + return el.getAttribute( "disabled" ) == null; +} ) ) { + addHandle( booleans, function( elem, name, isXML ) { + var val; + if ( !isXML ) { + return elem[ name ] === true ? name.toLowerCase() : + ( val = elem.getAttributeNode( name ) ) && val.specified ? + val.value : + null; + } + } ); +} + +return Sizzle; + +} )( window ); + + + +jQuery.find = Sizzle; +jQuery.expr = Sizzle.selectors; + +// Deprecated +jQuery.expr[ ":" ] = jQuery.expr.pseudos; +jQuery.uniqueSort = jQuery.unique = Sizzle.uniqueSort; +jQuery.text = Sizzle.getText; +jQuery.isXMLDoc = Sizzle.isXML; +jQuery.contains = Sizzle.contains; +jQuery.escapeSelector = Sizzle.escape; + + + + +var dir = function( elem, dir, until ) { + var matched = [], + truncate = until !== undefined; + + while ( ( elem = elem[ dir ] ) && elem.nodeType !== 9 ) { + if ( elem.nodeType === 1 ) { + if ( truncate && jQuery( elem ).is( until ) ) { + break; + } + matched.push( elem ); + } + } + return matched; +}; + + +var siblings = function( n, elem ) { + var matched = []; + + for ( ; n; n = n.nextSibling ) { + if ( n.nodeType === 1 && n !== elem ) { + matched.push( n ); + } + } + + return matched; +}; + + +var rneedsContext = jQuery.expr.match.needsContext; + + + +function nodeName( elem, name ) { + + return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase(); + +}; +var rsingleTag = ( /^<([a-z][^\/\0>:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i ); + + + +// Implement the identical functionality for filter and not +function winnow( elements, qualifier, not ) { + if ( isFunction( qualifier ) ) { + return jQuery.grep( elements, function( elem, i ) { + return !!qualifier.call( elem, i, elem ) !== not; + } ); + } + + // Single element + if ( qualifier.nodeType ) { + return jQuery.grep( elements, function( elem ) { + return ( elem === qualifier ) !== not; + } ); + } + + // Arraylike of elements (jQuery, arguments, Array) + if ( typeof qualifier !== "string" ) { + return jQuery.grep( elements, function( elem ) { + return ( indexOf.call( qualifier, elem ) > -1 ) !== not; + } ); + } + + // Filtered directly for both simple and complex selectors + return jQuery.filter( qualifier, elements, not ); +} + +jQuery.filter = function( expr, elems, not ) { + var elem = elems[ 0 ]; + + if ( not ) { + expr = ":not(" + expr + ")"; + } + + if ( elems.length === 1 && elem.nodeType === 1 ) { + return jQuery.find.matchesSelector( elem, expr ) ? [ elem ] : []; + } + + return jQuery.find.matches( expr, jQuery.grep( elems, function( elem ) { + return elem.nodeType === 1; + } ) ); +}; + +jQuery.fn.extend( { + find: function( selector ) { + var i, ret, + len = this.length, + self = this; + + if ( typeof selector !== "string" ) { + return this.pushStack( jQuery( selector ).filter( function() { + for ( i = 0; i < len; i++ ) { + if ( jQuery.contains( self[ i ], this ) ) { + return true; + } + } + } ) ); + } + + ret = this.pushStack( [] ); + + for ( i = 0; i < len; i++ ) { + jQuery.find( selector, self[ i ], ret ); + } + + return len > 1 ? jQuery.uniqueSort( ret ) : ret; + }, + filter: function( selector ) { + return this.pushStack( winnow( this, selector || [], false ) ); + }, + not: function( selector ) { + return this.pushStack( winnow( this, selector || [], true ) ); + }, + is: function( selector ) { + return !!winnow( + this, + + // If this is a positional/relative selector, check membership in the returned set + // so $("p:first").is("p:last") won't return true for a doc with two "p". + typeof selector === "string" && rneedsContext.test( selector ) ? + jQuery( selector ) : + selector || [], + false + ).length; + } +} ); + + +// Initialize a jQuery object + + +// A central reference to the root jQuery(document) +var rootjQuery, + + // A simple way to check for HTML strings + // Prioritize #id over to avoid XSS via location.hash (#9521) + // Strict HTML recognition (#11290: must start with <) + // Shortcut simple #id case for speed + rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]+))$/, + + init = jQuery.fn.init = function( selector, context, root ) { + var match, elem; + + // HANDLE: $(""), $(null), $(undefined), $(false) + if ( !selector ) { + return this; + } + + // Method init() accepts an alternate rootjQuery + // so migrate can support jQuery.sub (gh-2101) + root = root || rootjQuery; + + // Handle HTML strings + if ( typeof selector === "string" ) { + if ( selector[ 0 ] === "<" && + selector[ selector.length - 1 ] === ">" && + selector.length >= 3 ) { + + // Assume that strings that start and end with <> are HTML and skip the regex check + match = [ null, selector, null ]; + + } else { + match = rquickExpr.exec( selector ); + } + + // Match html or make sure no context is specified for #id + if ( match && ( match[ 1 ] || !context ) ) { + + // HANDLE: $(html) -> $(array) + if ( match[ 1 ] ) { + context = context instanceof jQuery ? context[ 0 ] : context; + + // Option to run scripts is true for back-compat + // Intentionally let the error be thrown if parseHTML is not present + jQuery.merge( this, jQuery.parseHTML( + match[ 1 ], + context && context.nodeType ? context.ownerDocument || context : document, + true + ) ); + + // HANDLE: $(html, props) + if ( rsingleTag.test( match[ 1 ] ) && jQuery.isPlainObject( context ) ) { + for ( match in context ) { + + // Properties of context are called as methods if possible + if ( isFunction( this[ match ] ) ) { + this[ match ]( context[ match ] ); + + // ...and otherwise set as attributes + } else { + this.attr( match, context[ match ] ); + } + } + } + + return this; + + // HANDLE: $(#id) + } else { + elem = document.getElementById( match[ 2 ] ); + + if ( elem ) { + + // Inject the element directly into the jQuery object + this[ 0 ] = elem; + this.length = 1; + } + return this; + } + + // HANDLE: $(expr, $(...)) + } else if ( !context || context.jquery ) { + return ( context || root ).find( selector ); + + // HANDLE: $(expr, context) + // (which is just equivalent to: $(context).find(expr) + } else { + return this.constructor( context ).find( selector ); + } + + // HANDLE: $(DOMElement) + } else if ( selector.nodeType ) { + this[ 0 ] = selector; + this.length = 1; + return this; + + // HANDLE: $(function) + // Shortcut for document ready + } else if ( isFunction( selector ) ) { + return root.ready !== undefined ? + root.ready( selector ) : + + // Execute immediately if ready is not present + selector( jQuery ); + } + + return jQuery.makeArray( selector, this ); + }; + +// Give the init function the jQuery prototype for later instantiation +init.prototype = jQuery.fn; + +// Initialize central reference +rootjQuery = jQuery( document ); + + +var rparentsprev = /^(?:parents|prev(?:Until|All))/, + + // Methods guaranteed to produce a unique set when starting from a unique set + guaranteedUnique = { + children: true, + contents: true, + next: true, + prev: true + }; + +jQuery.fn.extend( { + has: function( target ) { + var targets = jQuery( target, this ), + l = targets.length; + + return this.filter( function() { + var i = 0; + for ( ; i < l; i++ ) { + if ( jQuery.contains( this, targets[ i ] ) ) { + return true; + } + } + } ); + }, + + closest: function( selectors, context ) { + var cur, + i = 0, + l = this.length, + matched = [], + targets = typeof selectors !== "string" && jQuery( selectors ); + + // Positional selectors never match, since there's no _selection_ context + if ( !rneedsContext.test( selectors ) ) { + for ( ; i < l; i++ ) { + for ( cur = this[ i ]; cur && cur !== context; cur = cur.parentNode ) { + + // Always skip document fragments + if ( cur.nodeType < 11 && ( targets ? + targets.index( cur ) > -1 : + + // Don't pass non-elements to Sizzle + cur.nodeType === 1 && + jQuery.find.matchesSelector( cur, selectors ) ) ) { + + matched.push( cur ); + break; + } + } + } + } + + return this.pushStack( matched.length > 1 ? jQuery.uniqueSort( matched ) : matched ); + }, + + // Determine the position of an element within the set + index: function( elem ) { + + // No argument, return index in parent + if ( !elem ) { + return ( this[ 0 ] && this[ 0 ].parentNode ) ? this.first().prevAll().length : -1; + } + + // Index in selector + if ( typeof elem === "string" ) { + return indexOf.call( jQuery( elem ), this[ 0 ] ); + } + + // Locate the position of the desired element + return indexOf.call( this, + + // If it receives a jQuery object, the first element is used + elem.jquery ? elem[ 0 ] : elem + ); + }, + + add: function( selector, context ) { + return this.pushStack( + jQuery.uniqueSort( + jQuery.merge( this.get(), jQuery( selector, context ) ) + ) + ); + }, + + addBack: function( selector ) { + return this.add( selector == null ? + this.prevObject : this.prevObject.filter( selector ) + ); + } +} ); + +function sibling( cur, dir ) { + while ( ( cur = cur[ dir ] ) && cur.nodeType !== 1 ) {} + return cur; +} + +jQuery.each( { + parent: function( elem ) { + var parent = elem.parentNode; + return parent && parent.nodeType !== 11 ? parent : null; + }, + parents: function( elem ) { + return dir( elem, "parentNode" ); + }, + parentsUntil: function( elem, _i, until ) { + return dir( elem, "parentNode", until ); + }, + next: function( elem ) { + return sibling( elem, "nextSibling" ); + }, + prev: function( elem ) { + return sibling( elem, "previousSibling" ); + }, + nextAll: function( elem ) { + return dir( elem, "nextSibling" ); + }, + prevAll: function( elem ) { + return dir( elem, "previousSibling" ); + }, + nextUntil: function( elem, _i, until ) { + return dir( elem, "nextSibling", until ); + }, + prevUntil: function( elem, _i, until ) { + return dir( elem, "previousSibling", until ); + }, + siblings: function( elem ) { + return siblings( ( elem.parentNode || {} ).firstChild, elem ); + }, + children: function( elem ) { + return siblings( elem.firstChild ); + }, + contents: function( elem ) { + if ( elem.contentDocument != null && + + // Support: IE 11+ + // elements with no `data` attribute has an object + // `contentDocument` with a `null` prototype. + getProto( elem.contentDocument ) ) { + + return elem.contentDocument; + } + + // Support: IE 9 - 11 only, iOS 7 only, Android Browser <=4.3 only + // Treat the template element as a regular one in browsers that + // don't support it. + if ( nodeName( elem, "template" ) ) { + elem = elem.content || elem; + } + + return jQuery.merge( [], elem.childNodes ); + } +}, function( name, fn ) { + jQuery.fn[ name ] = function( until, selector ) { + var matched = jQuery.map( this, fn, until ); + + if ( name.slice( -5 ) !== "Until" ) { + selector = until; + } + + if ( selector && typeof selector === "string" ) { + matched = jQuery.filter( selector, matched ); + } + + if ( this.length > 1 ) { + + // Remove duplicates + if ( !guaranteedUnique[ name ] ) { + jQuery.uniqueSort( matched ); + } + + // Reverse order for parents* and prev-derivatives + if ( rparentsprev.test( name ) ) { + matched.reverse(); + } + } + + return this.pushStack( matched ); + }; +} ); +var rnothtmlwhite = ( /[^\x20\t\r\n\f]+/g ); + + + +// Convert String-formatted options into Object-formatted ones +function createOptions( options ) { + var object = {}; + jQuery.each( options.match( rnothtmlwhite ) || [], function( _, flag ) { + object[ flag ] = true; + } ); + return object; +} + +/* + * Create a callback list using the following parameters: + * + * options: an optional list of space-separated options that will change how + * the callback list behaves or a more traditional option object + * + * By default a callback list will act like an event callback list and can be + * "fired" multiple times. + * + * Possible options: + * + * once: will ensure the callback list can only be fired once (like a Deferred) + * + * memory: will keep track of previous values and will call any callback added + * after the list has been fired right away with the latest "memorized" + * values (like a Deferred) + * + * unique: will ensure a callback can only be added once (no duplicate in the list) + * + * stopOnFalse: interrupt callings when a callback returns false + * + */ +jQuery.Callbacks = function( options ) { + + // Convert options from String-formatted to Object-formatted if needed + // (we check in cache first) + options = typeof options === "string" ? + createOptions( options ) : + jQuery.extend( {}, options ); + + var // Flag to know if list is currently firing + firing, + + // Last fire value for non-forgettable lists + memory, + + // Flag to know if list was already fired + fired, + + // Flag to prevent firing + locked, + + // Actual callback list + list = [], + + // Queue of execution data for repeatable lists + queue = [], + + // Index of currently firing callback (modified by add/remove as needed) + firingIndex = -1, + + // Fire callbacks + fire = function() { + + // Enforce single-firing + locked = locked || options.once; + + // Execute callbacks for all pending executions, + // respecting firingIndex overrides and runtime changes + fired = firing = true; + for ( ; queue.length; firingIndex = -1 ) { + memory = queue.shift(); + while ( ++firingIndex < list.length ) { + + // Run callback and check for early termination + if ( list[ firingIndex ].apply( memory[ 0 ], memory[ 1 ] ) === false && + options.stopOnFalse ) { + + // Jump to end and forget the data so .add doesn't re-fire + firingIndex = list.length; + memory = false; + } + } + } + + // Forget the data if we're done with it + if ( !options.memory ) { + memory = false; + } + + firing = false; + + // Clean up if we're done firing for good + if ( locked ) { + + // Keep an empty list if we have data for future add calls + if ( memory ) { + list = []; + + // Otherwise, this object is spent + } else { + list = ""; + } + } + }, + + // Actual Callbacks object + self = { + + // Add a callback or a collection of callbacks to the list + add: function() { + if ( list ) { + + // If we have memory from a past run, we should fire after adding + if ( memory && !firing ) { + firingIndex = list.length - 1; + queue.push( memory ); + } + + ( function add( args ) { + jQuery.each( args, function( _, arg ) { + if ( isFunction( arg ) ) { + if ( !options.unique || !self.has( arg ) ) { + list.push( arg ); + } + } else if ( arg && arg.length && toType( arg ) !== "string" ) { + + // Inspect recursively + add( arg ); + } + } ); + } )( arguments ); + + if ( memory && !firing ) { + fire(); + } + } + return this; + }, + + // Remove a callback from the list + remove: function() { + jQuery.each( arguments, function( _, arg ) { + var index; + while ( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) { + list.splice( index, 1 ); + + // Handle firing indexes + if ( index <= firingIndex ) { + firingIndex--; + } + } + } ); + return this; + }, + + // Check if a given callback is in the list. + // If no argument is given, return whether or not list has callbacks attached. + has: function( fn ) { + return fn ? + jQuery.inArray( fn, list ) > -1 : + list.length > 0; + }, + + // Remove all callbacks from the list + empty: function() { + if ( list ) { + list = []; + } + return this; + }, + + // Disable .fire and .add + // Abort any current/pending executions + // Clear all callbacks and values + disable: function() { + locked = queue = []; + list = memory = ""; + return this; + }, + disabled: function() { + return !list; + }, + + // Disable .fire + // Also disable .add unless we have memory (since it would have no effect) + // Abort any pending executions + lock: function() { + locked = queue = []; + if ( !memory && !firing ) { + list = memory = ""; + } + return this; + }, + locked: function() { + return !!locked; + }, + + // Call all callbacks with the given context and arguments + fireWith: function( context, args ) { + if ( !locked ) { + args = args || []; + args = [ context, args.slice ? args.slice() : args ]; + queue.push( args ); + if ( !firing ) { + fire(); + } + } + return this; + }, + + // Call all the callbacks with the given arguments + fire: function() { + self.fireWith( this, arguments ); + return this; + }, + + // To know if the callbacks have already been called at least once + fired: function() { + return !!fired; + } + }; + + return self; +}; + + +function Identity( v ) { + return v; +} +function Thrower( ex ) { + throw ex; +} + +function adoptValue( value, resolve, reject, noValue ) { + var method; + + try { + + // Check for promise aspect first to privilege synchronous behavior + if ( value && isFunction( ( method = value.promise ) ) ) { + method.call( value ).done( resolve ).fail( reject ); + + // Other thenables + } else if ( value && isFunction( ( method = value.then ) ) ) { + method.call( value, resolve, reject ); + + // Other non-thenables + } else { + + // Control `resolve` arguments by letting Array#slice cast boolean `noValue` to integer: + // * false: [ value ].slice( 0 ) => resolve( value ) + // * true: [ value ].slice( 1 ) => resolve() + resolve.apply( undefined, [ value ].slice( noValue ) ); + } + + // For Promises/A+, convert exceptions into rejections + // Since jQuery.when doesn't unwrap thenables, we can skip the extra checks appearing in + // Deferred#then to conditionally suppress rejection. + } catch ( value ) { + + // Support: Android 4.0 only + // Strict mode functions invoked without .call/.apply get global-object context + reject.apply( undefined, [ value ] ); + } +} + +jQuery.extend( { + + Deferred: function( func ) { + var tuples = [ + + // action, add listener, callbacks, + // ... .then handlers, argument index, [final state] + [ "notify", "progress", jQuery.Callbacks( "memory" ), + jQuery.Callbacks( "memory" ), 2 ], + [ "resolve", "done", jQuery.Callbacks( "once memory" ), + jQuery.Callbacks( "once memory" ), 0, "resolved" ], + [ "reject", "fail", jQuery.Callbacks( "once memory" ), + jQuery.Callbacks( "once memory" ), 1, "rejected" ] + ], + state = "pending", + promise = { + state: function() { + return state; + }, + always: function() { + deferred.done( arguments ).fail( arguments ); + return this; + }, + "catch": function( fn ) { + return promise.then( null, fn ); + }, + + // Keep pipe for back-compat + pipe: function( /* fnDone, fnFail, fnProgress */ ) { + var fns = arguments; + + return jQuery.Deferred( function( newDefer ) { + jQuery.each( tuples, function( _i, tuple ) { + + // Map tuples (progress, done, fail) to arguments (done, fail, progress) + var fn = isFunction( fns[ tuple[ 4 ] ] ) && fns[ tuple[ 4 ] ]; + + // deferred.progress(function() { bind to newDefer or newDefer.notify }) + // deferred.done(function() { bind to newDefer or newDefer.resolve }) + // deferred.fail(function() { bind to newDefer or newDefer.reject }) + deferred[ tuple[ 1 ] ]( function() { + var returned = fn && fn.apply( this, arguments ); + if ( returned && isFunction( returned.promise ) ) { + returned.promise() + .progress( newDefer.notify ) + .done( newDefer.resolve ) + .fail( newDefer.reject ); + } else { + newDefer[ tuple[ 0 ] + "With" ]( + this, + fn ? [ returned ] : arguments + ); + } + } ); + } ); + fns = null; + } ).promise(); + }, + then: function( onFulfilled, onRejected, onProgress ) { + var maxDepth = 0; + function resolve( depth, deferred, handler, special ) { + return function() { + var that = this, + args = arguments, + mightThrow = function() { + var returned, then; + + // Support: Promises/A+ section 2.3.3.3.3 + // https://promisesaplus.com/#point-59 + // Ignore double-resolution attempts + if ( depth < maxDepth ) { + return; + } + + returned = handler.apply( that, args ); + + // Support: Promises/A+ section 2.3.1 + // https://promisesaplus.com/#point-48 + if ( returned === deferred.promise() ) { + throw new TypeError( "Thenable self-resolution" ); + } + + // Support: Promises/A+ sections 2.3.3.1, 3.5 + // https://promisesaplus.com/#point-54 + // https://promisesaplus.com/#point-75 + // Retrieve `then` only once + then = returned && + + // Support: Promises/A+ section 2.3.4 + // https://promisesaplus.com/#point-64 + // Only check objects and functions for thenability + ( typeof returned === "object" || + typeof returned === "function" ) && + returned.then; + + // Handle a returned thenable + if ( isFunction( then ) ) { + + // Special processors (notify) just wait for resolution + if ( special ) { + then.call( + returned, + resolve( maxDepth, deferred, Identity, special ), + resolve( maxDepth, deferred, Thrower, special ) + ); + + // Normal processors (resolve) also hook into progress + } else { + + // ...and disregard older resolution values + maxDepth++; + + then.call( + returned, + resolve( maxDepth, deferred, Identity, special ), + resolve( maxDepth, deferred, Thrower, special ), + resolve( maxDepth, deferred, Identity, + deferred.notifyWith ) + ); + } + + // Handle all other returned values + } else { + + // Only substitute handlers pass on context + // and multiple values (non-spec behavior) + if ( handler !== Identity ) { + that = undefined; + args = [ returned ]; + } + + // Process the value(s) + // Default process is resolve + ( special || deferred.resolveWith )( that, args ); + } + }, + + // Only normal processors (resolve) catch and reject exceptions + process = special ? + mightThrow : + function() { + try { + mightThrow(); + } catch ( e ) { + + if ( jQuery.Deferred.exceptionHook ) { + jQuery.Deferred.exceptionHook( e, + process.stackTrace ); + } + + // Support: Promises/A+ section 2.3.3.3.4.1 + // https://promisesaplus.com/#point-61 + // Ignore post-resolution exceptions + if ( depth + 1 >= maxDepth ) { + + // Only substitute handlers pass on context + // and multiple values (non-spec behavior) + if ( handler !== Thrower ) { + that = undefined; + args = [ e ]; + } + + deferred.rejectWith( that, args ); + } + } + }; + + // Support: Promises/A+ section 2.3.3.3.1 + // https://promisesaplus.com/#point-57 + // Re-resolve promises immediately to dodge false rejection from + // subsequent errors + if ( depth ) { + process(); + } else { + + // Call an optional hook to record the stack, in case of exception + // since it's otherwise lost when execution goes async + if ( jQuery.Deferred.getStackHook ) { + process.stackTrace = jQuery.Deferred.getStackHook(); + } + window.setTimeout( process ); + } + }; + } + + return jQuery.Deferred( function( newDefer ) { + + // progress_handlers.add( ... ) + tuples[ 0 ][ 3 ].add( + resolve( + 0, + newDefer, + isFunction( onProgress ) ? + onProgress : + Identity, + newDefer.notifyWith + ) + ); + + // fulfilled_handlers.add( ... ) + tuples[ 1 ][ 3 ].add( + resolve( + 0, + newDefer, + isFunction( onFulfilled ) ? + onFulfilled : + Identity + ) + ); + + // rejected_handlers.add( ... ) + tuples[ 2 ][ 3 ].add( + resolve( + 0, + newDefer, + isFunction( onRejected ) ? + onRejected : + Thrower + ) + ); + } ).promise(); + }, + + // Get a promise for this deferred + // If obj is provided, the promise aspect is added to the object + promise: function( obj ) { + return obj != null ? jQuery.extend( obj, promise ) : promise; + } + }, + deferred = {}; + + // Add list-specific methods + jQuery.each( tuples, function( i, tuple ) { + var list = tuple[ 2 ], + stateString = tuple[ 5 ]; + + // promise.progress = list.add + // promise.done = list.add + // promise.fail = list.add + promise[ tuple[ 1 ] ] = list.add; + + // Handle state + if ( stateString ) { + list.add( + function() { + + // state = "resolved" (i.e., fulfilled) + // state = "rejected" + state = stateString; + }, + + // rejected_callbacks.disable + // fulfilled_callbacks.disable + tuples[ 3 - i ][ 2 ].disable, + + // rejected_handlers.disable + // fulfilled_handlers.disable + tuples[ 3 - i ][ 3 ].disable, + + // progress_callbacks.lock + tuples[ 0 ][ 2 ].lock, + + // progress_handlers.lock + tuples[ 0 ][ 3 ].lock + ); + } + + // progress_handlers.fire + // fulfilled_handlers.fire + // rejected_handlers.fire + list.add( tuple[ 3 ].fire ); + + // deferred.notify = function() { deferred.notifyWith(...) } + // deferred.resolve = function() { deferred.resolveWith(...) } + // deferred.reject = function() { deferred.rejectWith(...) } + deferred[ tuple[ 0 ] ] = function() { + deferred[ tuple[ 0 ] + "With" ]( this === deferred ? undefined : this, arguments ); + return this; + }; + + // deferred.notifyWith = list.fireWith + // deferred.resolveWith = list.fireWith + // deferred.rejectWith = list.fireWith + deferred[ tuple[ 0 ] + "With" ] = list.fireWith; + } ); + + // Make the deferred a promise + promise.promise( deferred ); + + // Call given func if any + if ( func ) { + func.call( deferred, deferred ); + } + + // All done! + return deferred; + }, + + // Deferred helper + when: function( singleValue ) { + var + + // count of uncompleted subordinates + remaining = arguments.length, + + // count of unprocessed arguments + i = remaining, + + // subordinate fulfillment data + resolveContexts = Array( i ), + resolveValues = slice.call( arguments ), + + // the master Deferred + master = jQuery.Deferred(), + + // subordinate callback factory + updateFunc = function( i ) { + return function( value ) { + resolveContexts[ i ] = this; + resolveValues[ i ] = arguments.length > 1 ? slice.call( arguments ) : value; + if ( !( --remaining ) ) { + master.resolveWith( resolveContexts, resolveValues ); + } + }; + }; + + // Single- and empty arguments are adopted like Promise.resolve + if ( remaining <= 1 ) { + adoptValue( singleValue, master.done( updateFunc( i ) ).resolve, master.reject, + !remaining ); + + // Use .then() to unwrap secondary thenables (cf. gh-3000) + if ( master.state() === "pending" || + isFunction( resolveValues[ i ] && resolveValues[ i ].then ) ) { + + return master.then(); + } + } + + // Multiple arguments are aggregated like Promise.all array elements + while ( i-- ) { + adoptValue( resolveValues[ i ], updateFunc( i ), master.reject ); + } + + return master.promise(); + } +} ); + + +// These usually indicate a programmer mistake during development, +// warn about them ASAP rather than swallowing them by default. +var rerrorNames = /^(Eval|Internal|Range|Reference|Syntax|Type|URI)Error$/; + +jQuery.Deferred.exceptionHook = function( error, stack ) { + + // Support: IE 8 - 9 only + // Console exists when dev tools are open, which can happen at any time + if ( window.console && window.console.warn && error && rerrorNames.test( error.name ) ) { + window.console.warn( "jQuery.Deferred exception: " + error.message, error.stack, stack ); + } +}; + + + + +jQuery.readyException = function( error ) { + window.setTimeout( function() { + throw error; + } ); +}; + + + + +// The deferred used on DOM ready +var readyList = jQuery.Deferred(); + +jQuery.fn.ready = function( fn ) { + + readyList + .then( fn ) + + // Wrap jQuery.readyException in a function so that the lookup + // happens at the time of error handling instead of callback + // registration. + .catch( function( error ) { + jQuery.readyException( error ); + } ); + + return this; +}; + +jQuery.extend( { + + // Is the DOM ready to be used? Set to true once it occurs. + isReady: false, + + // A counter to track how many items to wait for before + // the ready event fires. See #6781 + readyWait: 1, + + // Handle when the DOM is ready + ready: function( wait ) { + + // Abort if there are pending holds or we're already ready + if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) { + return; + } + + // Remember that the DOM is ready + jQuery.isReady = true; + + // If a normal DOM Ready event fired, decrement, and wait if need be + if ( wait !== true && --jQuery.readyWait > 0 ) { + return; + } + + // If there are functions bound, to execute + readyList.resolveWith( document, [ jQuery ] ); + } +} ); + +jQuery.ready.then = readyList.then; + +// The ready event handler and self cleanup method +function completed() { + document.removeEventListener( "DOMContentLoaded", completed ); + window.removeEventListener( "load", completed ); + jQuery.ready(); +} + +// Catch cases where $(document).ready() is called +// after the browser event has already occurred. +// Support: IE <=9 - 10 only +// Older IE sometimes signals "interactive" too soon +if ( document.readyState === "complete" || + ( document.readyState !== "loading" && !document.documentElement.doScroll ) ) { + + // Handle it asynchronously to allow scripts the opportunity to delay ready + window.setTimeout( jQuery.ready ); + +} else { + + // Use the handy event callback + document.addEventListener( "DOMContentLoaded", completed ); + + // A fallback to window.onload, that will always work + window.addEventListener( "load", completed ); +} + + + + +// Multifunctional method to get and set values of a collection +// The value/s can optionally be executed if it's a function +var access = function( elems, fn, key, value, chainable, emptyGet, raw ) { + var i = 0, + len = elems.length, + bulk = key == null; + + // Sets many values + if ( toType( key ) === "object" ) { + chainable = true; + for ( i in key ) { + access( elems, fn, i, key[ i ], true, emptyGet, raw ); + } + + // Sets one value + } else if ( value !== undefined ) { + chainable = true; + + if ( !isFunction( value ) ) { + raw = true; + } + + if ( bulk ) { + + // Bulk operations run against the entire set + if ( raw ) { + fn.call( elems, value ); + fn = null; + + // ...except when executing function values + } else { + bulk = fn; + fn = function( elem, _key, value ) { + return bulk.call( jQuery( elem ), value ); + }; + } + } + + if ( fn ) { + for ( ; i < len; i++ ) { + fn( + elems[ i ], key, raw ? + value : + value.call( elems[ i ], i, fn( elems[ i ], key ) ) + ); + } + } + } + + if ( chainable ) { + return elems; + } + + // Gets + if ( bulk ) { + return fn.call( elems ); + } + + return len ? fn( elems[ 0 ], key ) : emptyGet; +}; + + +// Matches dashed string for camelizing +var rmsPrefix = /^-ms-/, + rdashAlpha = /-([a-z])/g; + +// Used by camelCase as callback to replace() +function fcamelCase( _all, letter ) { + return letter.toUpperCase(); +} + +// Convert dashed to camelCase; used by the css and data modules +// Support: IE <=9 - 11, Edge 12 - 15 +// Microsoft forgot to hump their vendor prefix (#9572) +function camelCase( string ) { + return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase ); +} +var acceptData = function( owner ) { + + // Accepts only: + // - Node + // - Node.ELEMENT_NODE + // - Node.DOCUMENT_NODE + // - Object + // - Any + return owner.nodeType === 1 || owner.nodeType === 9 || !( +owner.nodeType ); +}; + + + + +function Data() { + this.expando = jQuery.expando + Data.uid++; +} + +Data.uid = 1; + +Data.prototype = { + + cache: function( owner ) { + + // Check if the owner object already has a cache + var value = owner[ this.expando ]; + + // If not, create one + if ( !value ) { + value = {}; + + // We can accept data for non-element nodes in modern browsers, + // but we should not, see #8335. + // Always return an empty object. + if ( acceptData( owner ) ) { + + // If it is a node unlikely to be stringify-ed or looped over + // use plain assignment + if ( owner.nodeType ) { + owner[ this.expando ] = value; + + // Otherwise secure it in a non-enumerable property + // configurable must be true to allow the property to be + // deleted when data is removed + } else { + Object.defineProperty( owner, this.expando, { + value: value, + configurable: true + } ); + } + } + } + + return value; + }, + set: function( owner, data, value ) { + var prop, + cache = this.cache( owner ); + + // Handle: [ owner, key, value ] args + // Always use camelCase key (gh-2257) + if ( typeof data === "string" ) { + cache[ camelCase( data ) ] = value; + + // Handle: [ owner, { properties } ] args + } else { + + // Copy the properties one-by-one to the cache object + for ( prop in data ) { + cache[ camelCase( prop ) ] = data[ prop ]; + } + } + return cache; + }, + get: function( owner, key ) { + return key === undefined ? + this.cache( owner ) : + + // Always use camelCase key (gh-2257) + owner[ this.expando ] && owner[ this.expando ][ camelCase( key ) ]; + }, + access: function( owner, key, value ) { + + // In cases where either: + // + // 1. No key was specified + // 2. A string key was specified, but no value provided + // + // Take the "read" path and allow the get method to determine + // which value to return, respectively either: + // + // 1. The entire cache object + // 2. The data stored at the key + // + if ( key === undefined || + ( ( key && typeof key === "string" ) && value === undefined ) ) { + + return this.get( owner, key ); + } + + // When the key is not a string, or both a key and value + // are specified, set or extend (existing objects) with either: + // + // 1. An object of properties + // 2. A key and value + // + this.set( owner, key, value ); + + // Since the "set" path can have two possible entry points + // return the expected data based on which path was taken[*] + return value !== undefined ? value : key; + }, + remove: function( owner, key ) { + var i, + cache = owner[ this.expando ]; + + if ( cache === undefined ) { + return; + } + + if ( key !== undefined ) { + + // Support array or space separated string of keys + if ( Array.isArray( key ) ) { + + // If key is an array of keys... + // We always set camelCase keys, so remove that. + key = key.map( camelCase ); + } else { + key = camelCase( key ); + + // If a key with the spaces exists, use it. + // Otherwise, create an array by matching non-whitespace + key = key in cache ? + [ key ] : + ( key.match( rnothtmlwhite ) || [] ); + } + + i = key.length; + + while ( i-- ) { + delete cache[ key[ i ] ]; + } + } + + // Remove the expando if there's no more data + if ( key === undefined || jQuery.isEmptyObject( cache ) ) { + + // Support: Chrome <=35 - 45 + // Webkit & Blink performance suffers when deleting properties + // from DOM nodes, so set to undefined instead + // https://bugs.chromium.org/p/chromium/issues/detail?id=378607 (bug restricted) + if ( owner.nodeType ) { + owner[ this.expando ] = undefined; + } else { + delete owner[ this.expando ]; + } + } + }, + hasData: function( owner ) { + var cache = owner[ this.expando ]; + return cache !== undefined && !jQuery.isEmptyObject( cache ); + } +}; +var dataPriv = new Data(); + +var dataUser = new Data(); + + + +// Implementation Summary +// +// 1. Enforce API surface and semantic compatibility with 1.9.x branch +// 2. Improve the module's maintainability by reducing the storage +// paths to a single mechanism. +// 3. Use the same single mechanism to support "private" and "user" data. +// 4. _Never_ expose "private" data to user code (TODO: Drop _data, _removeData) +// 5. Avoid exposing implementation details on user objects (eg. expando properties) +// 6. Provide a clear path for implementation upgrade to WeakMap in 2014 + +var rbrace = /^(?:\{[\w\W]*\}|\[[\w\W]*\])$/, + rmultiDash = /[A-Z]/g; + +function getData( data ) { + if ( data === "true" ) { + return true; + } + + if ( data === "false" ) { + return false; + } + + if ( data === "null" ) { + return null; + } + + // Only convert to a number if it doesn't change the string + if ( data === +data + "" ) { + return +data; + } + + if ( rbrace.test( data ) ) { + return JSON.parse( data ); + } + + return data; +} + +function dataAttr( elem, key, data ) { + var name; + + // If nothing was found internally, try to fetch any + // data from the HTML5 data-* attribute + if ( data === undefined && elem.nodeType === 1 ) { + name = "data-" + key.replace( rmultiDash, "-$&" ).toLowerCase(); + data = elem.getAttribute( name ); + + if ( typeof data === "string" ) { + try { + data = getData( data ); + } catch ( e ) {} + + // Make sure we set the data so it isn't changed later + dataUser.set( elem, key, data ); + } else { + data = undefined; + } + } + return data; +} + +jQuery.extend( { + hasData: function( elem ) { + return dataUser.hasData( elem ) || dataPriv.hasData( elem ); + }, + + data: function( elem, name, data ) { + return dataUser.access( elem, name, data ); + }, + + removeData: function( elem, name ) { + dataUser.remove( elem, name ); + }, + + // TODO: Now that all calls to _data and _removeData have been replaced + // with direct calls to dataPriv methods, these can be deprecated. + _data: function( elem, name, data ) { + return dataPriv.access( elem, name, data ); + }, + + _removeData: function( elem, name ) { + dataPriv.remove( elem, name ); + } +} ); + +jQuery.fn.extend( { + data: function( key, value ) { + var i, name, data, + elem = this[ 0 ], + attrs = elem && elem.attributes; + + // Gets all values + if ( key === undefined ) { + if ( this.length ) { + data = dataUser.get( elem ); + + if ( elem.nodeType === 1 && !dataPriv.get( elem, "hasDataAttrs" ) ) { + i = attrs.length; + while ( i-- ) { + + // Support: IE 11 only + // The attrs elements can be null (#14894) + if ( attrs[ i ] ) { + name = attrs[ i ].name; + if ( name.indexOf( "data-" ) === 0 ) { + name = camelCase( name.slice( 5 ) ); + dataAttr( elem, name, data[ name ] ); + } + } + } + dataPriv.set( elem, "hasDataAttrs", true ); + } + } + + return data; + } + + // Sets multiple values + if ( typeof key === "object" ) { + return this.each( function() { + dataUser.set( this, key ); + } ); + } + + return access( this, function( value ) { + var data; + + // The calling jQuery object (element matches) is not empty + // (and therefore has an element appears at this[ 0 ]) and the + // `value` parameter was not undefined. An empty jQuery object + // will result in `undefined` for elem = this[ 0 ] which will + // throw an exception if an attempt to read a data cache is made. + if ( elem && value === undefined ) { + + // Attempt to get data from the cache + // The key will always be camelCased in Data + data = dataUser.get( elem, key ); + if ( data !== undefined ) { + return data; + } + + // Attempt to "discover" the data in + // HTML5 custom data-* attrs + data = dataAttr( elem, key ); + if ( data !== undefined ) { + return data; + } + + // We tried really hard, but the data doesn't exist. + return; + } + + // Set the data... + this.each( function() { + + // We always store the camelCased key + dataUser.set( this, key, value ); + } ); + }, null, value, arguments.length > 1, null, true ); + }, + + removeData: function( key ) { + return this.each( function() { + dataUser.remove( this, key ); + } ); + } +} ); + + +jQuery.extend( { + queue: function( elem, type, data ) { + var queue; + + if ( elem ) { + type = ( type || "fx" ) + "queue"; + queue = dataPriv.get( elem, type ); + + // Speed up dequeue by getting out quickly if this is just a lookup + if ( data ) { + if ( !queue || Array.isArray( data ) ) { + queue = dataPriv.access( elem, type, jQuery.makeArray( data ) ); + } else { + queue.push( data ); + } + } + return queue || []; + } + }, + + dequeue: function( elem, type ) { + type = type || "fx"; + + var queue = jQuery.queue( elem, type ), + startLength = queue.length, + fn = queue.shift(), + hooks = jQuery._queueHooks( elem, type ), + next = function() { + jQuery.dequeue( elem, type ); + }; + + // If the fx queue is dequeued, always remove the progress sentinel + if ( fn === "inprogress" ) { + fn = queue.shift(); + startLength--; + } + + if ( fn ) { + + // Add a progress sentinel to prevent the fx queue from being + // automatically dequeued + if ( type === "fx" ) { + queue.unshift( "inprogress" ); + } + + // Clear up the last queue stop function + delete hooks.stop; + fn.call( elem, next, hooks ); + } + + if ( !startLength && hooks ) { + hooks.empty.fire(); + } + }, + + // Not public - generate a queueHooks object, or return the current one + _queueHooks: function( elem, type ) { + var key = type + "queueHooks"; + return dataPriv.get( elem, key ) || dataPriv.access( elem, key, { + empty: jQuery.Callbacks( "once memory" ).add( function() { + dataPriv.remove( elem, [ type + "queue", key ] ); + } ) + } ); + } +} ); + +jQuery.fn.extend( { + queue: function( type, data ) { + var setter = 2; + + if ( typeof type !== "string" ) { + data = type; + type = "fx"; + setter--; + } + + if ( arguments.length < setter ) { + return jQuery.queue( this[ 0 ], type ); + } + + return data === undefined ? + this : + this.each( function() { + var queue = jQuery.queue( this, type, data ); + + // Ensure a hooks for this queue + jQuery._queueHooks( this, type ); + + if ( type === "fx" && queue[ 0 ] !== "inprogress" ) { + jQuery.dequeue( this, type ); + } + } ); + }, + dequeue: function( type ) { + return this.each( function() { + jQuery.dequeue( this, type ); + } ); + }, + clearQueue: function( type ) { + return this.queue( type || "fx", [] ); + }, + + // Get a promise resolved when queues of a certain type + // are emptied (fx is the type by default) + promise: function( type, obj ) { + var tmp, + count = 1, + defer = jQuery.Deferred(), + elements = this, + i = this.length, + resolve = function() { + if ( !( --count ) ) { + defer.resolveWith( elements, [ elements ] ); + } + }; + + if ( typeof type !== "string" ) { + obj = type; + type = undefined; + } + type = type || "fx"; + + while ( i-- ) { + tmp = dataPriv.get( elements[ i ], type + "queueHooks" ); + if ( tmp && tmp.empty ) { + count++; + tmp.empty.add( resolve ); + } + } + resolve(); + return defer.promise( obj ); + } +} ); +var pnum = ( /[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/ ).source; + +var rcssNum = new RegExp( "^(?:([+-])=|)(" + pnum + ")([a-z%]*)$", "i" ); + + +var cssExpand = [ "Top", "Right", "Bottom", "Left" ]; + +var documentElement = document.documentElement; + + + + var isAttached = function( elem ) { + return jQuery.contains( elem.ownerDocument, elem ); + }, + composed = { composed: true }; + + // Support: IE 9 - 11+, Edge 12 - 18+, iOS 10.0 - 10.2 only + // Check attachment across shadow DOM boundaries when possible (gh-3504) + // Support: iOS 10.0-10.2 only + // Early iOS 10 versions support `attachShadow` but not `getRootNode`, + // leading to errors. We need to check for `getRootNode`. + if ( documentElement.getRootNode ) { + isAttached = function( elem ) { + return jQuery.contains( elem.ownerDocument, elem ) || + elem.getRootNode( composed ) === elem.ownerDocument; + }; + } +var isHiddenWithinTree = function( elem, el ) { + + // isHiddenWithinTree might be called from jQuery#filter function; + // in that case, element will be second argument + elem = el || elem; + + // Inline style trumps all + return elem.style.display === "none" || + elem.style.display === "" && + + // Otherwise, check computed style + // Support: Firefox <=43 - 45 + // Disconnected elements can have computed display: none, so first confirm that elem is + // in the document. + isAttached( elem ) && + + jQuery.css( elem, "display" ) === "none"; + }; + + + +function adjustCSS( elem, prop, valueParts, tween ) { + var adjusted, scale, + maxIterations = 20, + currentValue = tween ? + function() { + return tween.cur(); + } : + function() { + return jQuery.css( elem, prop, "" ); + }, + initial = currentValue(), + unit = valueParts && valueParts[ 3 ] || ( jQuery.cssNumber[ prop ] ? "" : "px" ), + + // Starting value computation is required for potential unit mismatches + initialInUnit = elem.nodeType && + ( jQuery.cssNumber[ prop ] || unit !== "px" && +initial ) && + rcssNum.exec( jQuery.css( elem, prop ) ); + + if ( initialInUnit && initialInUnit[ 3 ] !== unit ) { + + // Support: Firefox <=54 + // Halve the iteration target value to prevent interference from CSS upper bounds (gh-2144) + initial = initial / 2; + + // Trust units reported by jQuery.css + unit = unit || initialInUnit[ 3 ]; + + // Iteratively approximate from a nonzero starting point + initialInUnit = +initial || 1; + + while ( maxIterations-- ) { + + // Evaluate and update our best guess (doubling guesses that zero out). + // Finish if the scale equals or crosses 1 (making the old*new product non-positive). + jQuery.style( elem, prop, initialInUnit + unit ); + if ( ( 1 - scale ) * ( 1 - ( scale = currentValue() / initial || 0.5 ) ) <= 0 ) { + maxIterations = 0; + } + initialInUnit = initialInUnit / scale; + + } + + initialInUnit = initialInUnit * 2; + jQuery.style( elem, prop, initialInUnit + unit ); + + // Make sure we update the tween properties later on + valueParts = valueParts || []; + } + + if ( valueParts ) { + initialInUnit = +initialInUnit || +initial || 0; + + // Apply relative offset (+=/-=) if specified + adjusted = valueParts[ 1 ] ? + initialInUnit + ( valueParts[ 1 ] + 1 ) * valueParts[ 2 ] : + +valueParts[ 2 ]; + if ( tween ) { + tween.unit = unit; + tween.start = initialInUnit; + tween.end = adjusted; + } + } + return adjusted; +} + + +var defaultDisplayMap = {}; + +function getDefaultDisplay( elem ) { + var temp, + doc = elem.ownerDocument, + nodeName = elem.nodeName, + display = defaultDisplayMap[ nodeName ]; + + if ( display ) { + return display; + } + + temp = doc.body.appendChild( doc.createElement( nodeName ) ); + display = jQuery.css( temp, "display" ); + + temp.parentNode.removeChild( temp ); + + if ( display === "none" ) { + display = "block"; + } + defaultDisplayMap[ nodeName ] = display; + + return display; +} + +function showHide( elements, show ) { + var display, elem, + values = [], + index = 0, + length = elements.length; + + // Determine new display value for elements that need to change + for ( ; index < length; index++ ) { + elem = elements[ index ]; + if ( !elem.style ) { + continue; + } + + display = elem.style.display; + if ( show ) { + + // Since we force visibility upon cascade-hidden elements, an immediate (and slow) + // check is required in this first loop unless we have a nonempty display value (either + // inline or about-to-be-restored) + if ( display === "none" ) { + values[ index ] = dataPriv.get( elem, "display" ) || null; + if ( !values[ index ] ) { + elem.style.display = ""; + } + } + if ( elem.style.display === "" && isHiddenWithinTree( elem ) ) { + values[ index ] = getDefaultDisplay( elem ); + } + } else { + if ( display !== "none" ) { + values[ index ] = "none"; + + // Remember what we're overwriting + dataPriv.set( elem, "display", display ); + } + } + } + + // Set the display of the elements in a second loop to avoid constant reflow + for ( index = 0; index < length; index++ ) { + if ( values[ index ] != null ) { + elements[ index ].style.display = values[ index ]; + } + } + + return elements; +} + +jQuery.fn.extend( { + show: function() { + return showHide( this, true ); + }, + hide: function() { + return showHide( this ); + }, + toggle: function( state ) { + if ( typeof state === "boolean" ) { + return state ? this.show() : this.hide(); + } + + return this.each( function() { + if ( isHiddenWithinTree( this ) ) { + jQuery( this ).show(); + } else { + jQuery( this ).hide(); + } + } ); + } +} ); +var rcheckableType = ( /^(?:checkbox|radio)$/i ); + +var rtagName = ( /<([a-z][^\/\0>\x20\t\r\n\f]*)/i ); + +var rscriptType = ( /^$|^module$|\/(?:java|ecma)script/i ); + + + +( function() { + var fragment = document.createDocumentFragment(), + div = fragment.appendChild( document.createElement( "div" ) ), + input = document.createElement( "input" ); + + // Support: Android 4.0 - 4.3 only + // Check state lost if the name is set (#11217) + // Support: Windows Web Apps (WWA) + // `name` and `type` must use .setAttribute for WWA (#14901) + input.setAttribute( "type", "radio" ); + input.setAttribute( "checked", "checked" ); + input.setAttribute( "name", "t" ); + + div.appendChild( input ); + + // Support: Android <=4.1 only + // Older WebKit doesn't clone checked state correctly in fragments + support.checkClone = div.cloneNode( true ).cloneNode( true ).lastChild.checked; + + // Support: IE <=11 only + // Make sure textarea (and checkbox) defaultValue is properly cloned + div.innerHTML = ""; + support.noCloneChecked = !!div.cloneNode( true ).lastChild.defaultValue; + + // Support: IE <=9 only + // IE <=9 replaces "; + support.option = !!div.lastChild; +} )(); + + +// We have to close these tags to support XHTML (#13200) +var wrapMap = { + + // XHTML parsers do not magically insert elements in the + // same way that tag soup parsers do. So we cannot shorten + // this by omitting or other required elements. + thead: [ 1, "", "
" ], + col: [ 2, "", "
" ], + tr: [ 2, "", "
" ], + td: [ 3, "", "
" ], + + _default: [ 0, "", "" ] +}; + +wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; +wrapMap.th = wrapMap.td; + +// Support: IE <=9 only +if ( !support.option ) { + wrapMap.optgroup = wrapMap.option = [ 1, "" ]; +} + + +function getAll( context, tag ) { + + // Support: IE <=9 - 11 only + // Use typeof to avoid zero-argument method invocation on host objects (#15151) + var ret; + + if ( typeof context.getElementsByTagName !== "undefined" ) { + ret = context.getElementsByTagName( tag || "*" ); + + } else if ( typeof context.querySelectorAll !== "undefined" ) { + ret = context.querySelectorAll( tag || "*" ); + + } else { + ret = []; + } + + if ( tag === undefined || tag && nodeName( context, tag ) ) { + return jQuery.merge( [ context ], ret ); + } + + return ret; +} + + +// Mark scripts as having already been evaluated +function setGlobalEval( elems, refElements ) { + var i = 0, + l = elems.length; + + for ( ; i < l; i++ ) { + dataPriv.set( + elems[ i ], + "globalEval", + !refElements || dataPriv.get( refElements[ i ], "globalEval" ) + ); + } +} + + +var rhtml = /<|&#?\w+;/; + +function buildFragment( elems, context, scripts, selection, ignored ) { + var elem, tmp, tag, wrap, attached, j, + fragment = context.createDocumentFragment(), + nodes = [], + i = 0, + l = elems.length; + + for ( ; i < l; i++ ) { + elem = elems[ i ]; + + if ( elem || elem === 0 ) { + + // Add nodes directly + if ( toType( elem ) === "object" ) { + + // Support: Android <=4.0 only, PhantomJS 1 only + // push.apply(_, arraylike) throws on ancient WebKit + jQuery.merge( nodes, elem.nodeType ? [ elem ] : elem ); + + // Convert non-html into a text node + } else if ( !rhtml.test( elem ) ) { + nodes.push( context.createTextNode( elem ) ); + + // Convert html into DOM nodes + } else { + tmp = tmp || fragment.appendChild( context.createElement( "div" ) ); + + // Deserialize a standard representation + tag = ( rtagName.exec( elem ) || [ "", "" ] )[ 1 ].toLowerCase(); + wrap = wrapMap[ tag ] || wrapMap._default; + tmp.innerHTML = wrap[ 1 ] + jQuery.htmlPrefilter( elem ) + wrap[ 2 ]; + + // Descend through wrappers to the right content + j = wrap[ 0 ]; + while ( j-- ) { + tmp = tmp.lastChild; + } + + // Support: Android <=4.0 only, PhantomJS 1 only + // push.apply(_, arraylike) throws on ancient WebKit + jQuery.merge( nodes, tmp.childNodes ); + + // Remember the top-level container + tmp = fragment.firstChild; + + // Ensure the created nodes are orphaned (#12392) + tmp.textContent = ""; + } + } + } + + // Remove wrapper from fragment + fragment.textContent = ""; + + i = 0; + while ( ( elem = nodes[ i++ ] ) ) { + + // Skip elements already in the context collection (trac-4087) + if ( selection && jQuery.inArray( elem, selection ) > -1 ) { + if ( ignored ) { + ignored.push( elem ); + } + continue; + } + + attached = isAttached( elem ); + + // Append to fragment + tmp = getAll( fragment.appendChild( elem ), "script" ); + + // Preserve script evaluation history + if ( attached ) { + setGlobalEval( tmp ); + } + + // Capture executables + if ( scripts ) { + j = 0; + while ( ( elem = tmp[ j++ ] ) ) { + if ( rscriptType.test( elem.type || "" ) ) { + scripts.push( elem ); + } + } + } + } + + return fragment; +} + + +var + rkeyEvent = /^key/, + rmouseEvent = /^(?:mouse|pointer|contextmenu|drag|drop)|click/, + rtypenamespace = /^([^.]*)(?:\.(.+)|)/; + +function returnTrue() { + return true; +} + +function returnFalse() { + return false; +} + +// Support: IE <=9 - 11+ +// focus() and blur() are asynchronous, except when they are no-op. +// So expect focus to be synchronous when the element is already active, +// and blur to be synchronous when the element is not already active. +// (focus and blur are always synchronous in other supported browsers, +// this just defines when we can count on it). +function expectSync( elem, type ) { + return ( elem === safeActiveElement() ) === ( type === "focus" ); +} + +// Support: IE <=9 only +// Accessing document.activeElement can throw unexpectedly +// https://bugs.jquery.com/ticket/13393 +function safeActiveElement() { + try { + return document.activeElement; + } catch ( err ) { } +} + +function on( elem, types, selector, data, fn, one ) { + var origFn, type; + + // Types can be a map of types/handlers + if ( typeof types === "object" ) { + + // ( types-Object, selector, data ) + if ( typeof selector !== "string" ) { + + // ( types-Object, data ) + data = data || selector; + selector = undefined; + } + for ( type in types ) { + on( elem, type, selector, data, types[ type ], one ); + } + return elem; + } + + if ( data == null && fn == null ) { + + // ( types, fn ) + fn = selector; + data = selector = undefined; + } else if ( fn == null ) { + if ( typeof selector === "string" ) { + + // ( types, selector, fn ) + fn = data; + data = undefined; + } else { + + // ( types, data, fn ) + fn = data; + data = selector; + selector = undefined; + } + } + if ( fn === false ) { + fn = returnFalse; + } else if ( !fn ) { + return elem; + } + + if ( one === 1 ) { + origFn = fn; + fn = function( event ) { + + // Can use an empty set, since event contains the info + jQuery().off( event ); + return origFn.apply( this, arguments ); + }; + + // Use same guid so caller can remove using origFn + fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ ); + } + return elem.each( function() { + jQuery.event.add( this, types, fn, data, selector ); + } ); +} + +/* + * Helper functions for managing events -- not part of the public interface. + * Props to Dean Edwards' addEvent library for many of the ideas. + */ +jQuery.event = { + + global: {}, + + add: function( elem, types, handler, data, selector ) { + + var handleObjIn, eventHandle, tmp, + events, t, handleObj, + special, handlers, type, namespaces, origType, + elemData = dataPriv.get( elem ); + + // Only attach events to objects that accept data + if ( !acceptData( elem ) ) { + return; + } + + // Caller can pass in an object of custom data in lieu of the handler + if ( handler.handler ) { + handleObjIn = handler; + handler = handleObjIn.handler; + selector = handleObjIn.selector; + } + + // Ensure that invalid selectors throw exceptions at attach time + // Evaluate against documentElement in case elem is a non-element node (e.g., document) + if ( selector ) { + jQuery.find.matchesSelector( documentElement, selector ); + } + + // Make sure that the handler has a unique ID, used to find/remove it later + if ( !handler.guid ) { + handler.guid = jQuery.guid++; + } + + // Init the element's event structure and main handler, if this is the first + if ( !( events = elemData.events ) ) { + events = elemData.events = Object.create( null ); + } + if ( !( eventHandle = elemData.handle ) ) { + eventHandle = elemData.handle = function( e ) { + + // Discard the second event of a jQuery.event.trigger() and + // when an event is called after a page has unloaded + return typeof jQuery !== "undefined" && jQuery.event.triggered !== e.type ? + jQuery.event.dispatch.apply( elem, arguments ) : undefined; + }; + } + + // Handle multiple events separated by a space + types = ( types || "" ).match( rnothtmlwhite ) || [ "" ]; + t = types.length; + while ( t-- ) { + tmp = rtypenamespace.exec( types[ t ] ) || []; + type = origType = tmp[ 1 ]; + namespaces = ( tmp[ 2 ] || "" ).split( "." ).sort(); + + // There *must* be a type, no attaching namespace-only handlers + if ( !type ) { + continue; + } + + // If event changes its type, use the special event handlers for the changed type + special = jQuery.event.special[ type ] || {}; + + // If selector defined, determine special event api type, otherwise given type + type = ( selector ? special.delegateType : special.bindType ) || type; + + // Update special based on newly reset type + special = jQuery.event.special[ type ] || {}; + + // handleObj is passed to all event handlers + handleObj = jQuery.extend( { + type: type, + origType: origType, + data: data, + handler: handler, + guid: handler.guid, + selector: selector, + needsContext: selector && jQuery.expr.match.needsContext.test( selector ), + namespace: namespaces.join( "." ) + }, handleObjIn ); + + // Init the event handler queue if we're the first + if ( !( handlers = events[ type ] ) ) { + handlers = events[ type ] = []; + handlers.delegateCount = 0; + + // Only use addEventListener if the special events handler returns false + if ( !special.setup || + special.setup.call( elem, data, namespaces, eventHandle ) === false ) { + + if ( elem.addEventListener ) { + elem.addEventListener( type, eventHandle ); + } + } + } + + if ( special.add ) { + special.add.call( elem, handleObj ); + + if ( !handleObj.handler.guid ) { + handleObj.handler.guid = handler.guid; + } + } + + // Add to the element's handler list, delegates in front + if ( selector ) { + handlers.splice( handlers.delegateCount++, 0, handleObj ); + } else { + handlers.push( handleObj ); + } + + // Keep track of which events have ever been used, for event optimization + jQuery.event.global[ type ] = true; + } + + }, + + // Detach an event or set of events from an element + remove: function( elem, types, handler, selector, mappedTypes ) { + + var j, origCount, tmp, + events, t, handleObj, + special, handlers, type, namespaces, origType, + elemData = dataPriv.hasData( elem ) && dataPriv.get( elem ); + + if ( !elemData || !( events = elemData.events ) ) { + return; + } + + // Once for each type.namespace in types; type may be omitted + types = ( types || "" ).match( rnothtmlwhite ) || [ "" ]; + t = types.length; + while ( t-- ) { + tmp = rtypenamespace.exec( types[ t ] ) || []; + type = origType = tmp[ 1 ]; + namespaces = ( tmp[ 2 ] || "" ).split( "." ).sort(); + + // Unbind all events (on this namespace, if provided) for the element + if ( !type ) { + for ( type in events ) { + jQuery.event.remove( elem, type + types[ t ], handler, selector, true ); + } + continue; + } + + special = jQuery.event.special[ type ] || {}; + type = ( selector ? special.delegateType : special.bindType ) || type; + handlers = events[ type ] || []; + tmp = tmp[ 2 ] && + new RegExp( "(^|\\.)" + namespaces.join( "\\.(?:.*\\.|)" ) + "(\\.|$)" ); + + // Remove matching events + origCount = j = handlers.length; + while ( j-- ) { + handleObj = handlers[ j ]; + + if ( ( mappedTypes || origType === handleObj.origType ) && + ( !handler || handler.guid === handleObj.guid ) && + ( !tmp || tmp.test( handleObj.namespace ) ) && + ( !selector || selector === handleObj.selector || + selector === "**" && handleObj.selector ) ) { + handlers.splice( j, 1 ); + + if ( handleObj.selector ) { + handlers.delegateCount--; + } + if ( special.remove ) { + special.remove.call( elem, handleObj ); + } + } + } + + // Remove generic event handler if we removed something and no more handlers exist + // (avoids potential for endless recursion during removal of special event handlers) + if ( origCount && !handlers.length ) { + if ( !special.teardown || + special.teardown.call( elem, namespaces, elemData.handle ) === false ) { + + jQuery.removeEvent( elem, type, elemData.handle ); + } + + delete events[ type ]; + } + } + + // Remove data and the expando if it's no longer used + if ( jQuery.isEmptyObject( events ) ) { + dataPriv.remove( elem, "handle events" ); + } + }, + + dispatch: function( nativeEvent ) { + + var i, j, ret, matched, handleObj, handlerQueue, + args = new Array( arguments.length ), + + // Make a writable jQuery.Event from the native event object + event = jQuery.event.fix( nativeEvent ), + + handlers = ( + dataPriv.get( this, "events" ) || Object.create( null ) + )[ event.type ] || [], + special = jQuery.event.special[ event.type ] || {}; + + // Use the fix-ed jQuery.Event rather than the (read-only) native event + args[ 0 ] = event; + + for ( i = 1; i < arguments.length; i++ ) { + args[ i ] = arguments[ i ]; + } + + event.delegateTarget = this; + + // Call the preDispatch hook for the mapped type, and let it bail if desired + if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) { + return; + } + + // Determine handlers + handlerQueue = jQuery.event.handlers.call( this, event, handlers ); + + // Run delegates first; they may want to stop propagation beneath us + i = 0; + while ( ( matched = handlerQueue[ i++ ] ) && !event.isPropagationStopped() ) { + event.currentTarget = matched.elem; + + j = 0; + while ( ( handleObj = matched.handlers[ j++ ] ) && + !event.isImmediatePropagationStopped() ) { + + // If the event is namespaced, then each handler is only invoked if it is + // specially universal or its namespaces are a superset of the event's. + if ( !event.rnamespace || handleObj.namespace === false || + event.rnamespace.test( handleObj.namespace ) ) { + + event.handleObj = handleObj; + event.data = handleObj.data; + + ret = ( ( jQuery.event.special[ handleObj.origType ] || {} ).handle || + handleObj.handler ).apply( matched.elem, args ); + + if ( ret !== undefined ) { + if ( ( event.result = ret ) === false ) { + event.preventDefault(); + event.stopPropagation(); + } + } + } + } + } + + // Call the postDispatch hook for the mapped type + if ( special.postDispatch ) { + special.postDispatch.call( this, event ); + } + + return event.result; + }, + + handlers: function( event, handlers ) { + var i, handleObj, sel, matchedHandlers, matchedSelectors, + handlerQueue = [], + delegateCount = handlers.delegateCount, + cur = event.target; + + // Find delegate handlers + if ( delegateCount && + + // Support: IE <=9 + // Black-hole SVG instance trees (trac-13180) + cur.nodeType && + + // Support: Firefox <=42 + // Suppress spec-violating clicks indicating a non-primary pointer button (trac-3861) + // https://www.w3.org/TR/DOM-Level-3-Events/#event-type-click + // Support: IE 11 only + // ...but not arrow key "clicks" of radio inputs, which can have `button` -1 (gh-2343) + !( event.type === "click" && event.button >= 1 ) ) { + + for ( ; cur !== this; cur = cur.parentNode || this ) { + + // Don't check non-elements (#13208) + // Don't process clicks on disabled elements (#6911, #8165, #11382, #11764) + if ( cur.nodeType === 1 && !( event.type === "click" && cur.disabled === true ) ) { + matchedHandlers = []; + matchedSelectors = {}; + for ( i = 0; i < delegateCount; i++ ) { + handleObj = handlers[ i ]; + + // Don't conflict with Object.prototype properties (#13203) + sel = handleObj.selector + " "; + + if ( matchedSelectors[ sel ] === undefined ) { + matchedSelectors[ sel ] = handleObj.needsContext ? + jQuery( sel, this ).index( cur ) > -1 : + jQuery.find( sel, this, null, [ cur ] ).length; + } + if ( matchedSelectors[ sel ] ) { + matchedHandlers.push( handleObj ); + } + } + if ( matchedHandlers.length ) { + handlerQueue.push( { elem: cur, handlers: matchedHandlers } ); + } + } + } + } + + // Add the remaining (directly-bound) handlers + cur = this; + if ( delegateCount < handlers.length ) { + handlerQueue.push( { elem: cur, handlers: handlers.slice( delegateCount ) } ); + } + + return handlerQueue; + }, + + addProp: function( name, hook ) { + Object.defineProperty( jQuery.Event.prototype, name, { + enumerable: true, + configurable: true, + + get: isFunction( hook ) ? + function() { + if ( this.originalEvent ) { + return hook( this.originalEvent ); + } + } : + function() { + if ( this.originalEvent ) { + return this.originalEvent[ name ]; + } + }, + + set: function( value ) { + Object.defineProperty( this, name, { + enumerable: true, + configurable: true, + writable: true, + value: value + } ); + } + } ); + }, + + fix: function( originalEvent ) { + return originalEvent[ jQuery.expando ] ? + originalEvent : + new jQuery.Event( originalEvent ); + }, + + special: { + load: { + + // Prevent triggered image.load events from bubbling to window.load + noBubble: true + }, + click: { + + // Utilize native event to ensure correct state for checkable inputs + setup: function( data ) { + + // For mutual compressibility with _default, replace `this` access with a local var. + // `|| data` is dead code meant only to preserve the variable through minification. + var el = this || data; + + // Claim the first handler + if ( rcheckableType.test( el.type ) && + el.click && nodeName( el, "input" ) ) { + + // dataPriv.set( el, "click", ... ) + leverageNative( el, "click", returnTrue ); + } + + // Return false to allow normal processing in the caller + return false; + }, + trigger: function( data ) { + + // For mutual compressibility with _default, replace `this` access with a local var. + // `|| data` is dead code meant only to preserve the variable through minification. + var el = this || data; + + // Force setup before triggering a click + if ( rcheckableType.test( el.type ) && + el.click && nodeName( el, "input" ) ) { + + leverageNative( el, "click" ); + } + + // Return non-false to allow normal event-path propagation + return true; + }, + + // For cross-browser consistency, suppress native .click() on links + // Also prevent it if we're currently inside a leveraged native-event stack + _default: function( event ) { + var target = event.target; + return rcheckableType.test( target.type ) && + target.click && nodeName( target, "input" ) && + dataPriv.get( target, "click" ) || + nodeName( target, "a" ); + } + }, + + beforeunload: { + postDispatch: function( event ) { + + // Support: Firefox 20+ + // Firefox doesn't alert if the returnValue field is not set. + if ( event.result !== undefined && event.originalEvent ) { + event.originalEvent.returnValue = event.result; + } + } + } + } +}; + +// Ensure the presence of an event listener that handles manually-triggered +// synthetic events by interrupting progress until reinvoked in response to +// *native* events that it fires directly, ensuring that state changes have +// already occurred before other listeners are invoked. +function leverageNative( el, type, expectSync ) { + + // Missing expectSync indicates a trigger call, which must force setup through jQuery.event.add + if ( !expectSync ) { + if ( dataPriv.get( el, type ) === undefined ) { + jQuery.event.add( el, type, returnTrue ); + } + return; + } + + // Register the controller as a special universal handler for all event namespaces + dataPriv.set( el, type, false ); + jQuery.event.add( el, type, { + namespace: false, + handler: function( event ) { + var notAsync, result, + saved = dataPriv.get( this, type ); + + if ( ( event.isTrigger & 1 ) && this[ type ] ) { + + // Interrupt processing of the outer synthetic .trigger()ed event + // Saved data should be false in such cases, but might be a leftover capture object + // from an async native handler (gh-4350) + if ( !saved.length ) { + + // Store arguments for use when handling the inner native event + // There will always be at least one argument (an event object), so this array + // will not be confused with a leftover capture object. + saved = slice.call( arguments ); + dataPriv.set( this, type, saved ); + + // Trigger the native event and capture its result + // Support: IE <=9 - 11+ + // focus() and blur() are asynchronous + notAsync = expectSync( this, type ); + this[ type ](); + result = dataPriv.get( this, type ); + if ( saved !== result || notAsync ) { + dataPriv.set( this, type, false ); + } else { + result = {}; + } + if ( saved !== result ) { + + // Cancel the outer synthetic event + event.stopImmediatePropagation(); + event.preventDefault(); + return result.value; + } + + // If this is an inner synthetic event for an event with a bubbling surrogate + // (focus or blur), assume that the surrogate already propagated from triggering the + // native event and prevent that from happening again here. + // This technically gets the ordering wrong w.r.t. to `.trigger()` (in which the + // bubbling surrogate propagates *after* the non-bubbling base), but that seems + // less bad than duplication. + } else if ( ( jQuery.event.special[ type ] || {} ).delegateType ) { + event.stopPropagation(); + } + + // If this is a native event triggered above, everything is now in order + // Fire an inner synthetic event with the original arguments + } else if ( saved.length ) { + + // ...and capture the result + dataPriv.set( this, type, { + value: jQuery.event.trigger( + + // Support: IE <=9 - 11+ + // Extend with the prototype to reset the above stopImmediatePropagation() + jQuery.extend( saved[ 0 ], jQuery.Event.prototype ), + saved.slice( 1 ), + this + ) + } ); + + // Abort handling of the native event + event.stopImmediatePropagation(); + } + } + } ); +} + +jQuery.removeEvent = function( elem, type, handle ) { + + // This "if" is needed for plain objects + if ( elem.removeEventListener ) { + elem.removeEventListener( type, handle ); + } +}; + +jQuery.Event = function( src, props ) { + + // Allow instantiation without the 'new' keyword + if ( !( this instanceof jQuery.Event ) ) { + return new jQuery.Event( src, props ); + } + + // Event object + if ( src && src.type ) { + this.originalEvent = src; + this.type = src.type; + + // Events bubbling up the document may have been marked as prevented + // by a handler lower down the tree; reflect the correct value. + this.isDefaultPrevented = src.defaultPrevented || + src.defaultPrevented === undefined && + + // Support: Android <=2.3 only + src.returnValue === false ? + returnTrue : + returnFalse; + + // Create target properties + // Support: Safari <=6 - 7 only + // Target should not be a text node (#504, #13143) + this.target = ( src.target && src.target.nodeType === 3 ) ? + src.target.parentNode : + src.target; + + this.currentTarget = src.currentTarget; + this.relatedTarget = src.relatedTarget; + + // Event type + } else { + this.type = src; + } + + // Put explicitly provided properties onto the event object + if ( props ) { + jQuery.extend( this, props ); + } + + // Create a timestamp if incoming event doesn't have one + this.timeStamp = src && src.timeStamp || Date.now(); + + // Mark it as fixed + this[ jQuery.expando ] = true; +}; + +// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding +// https://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html +jQuery.Event.prototype = { + constructor: jQuery.Event, + isDefaultPrevented: returnFalse, + isPropagationStopped: returnFalse, + isImmediatePropagationStopped: returnFalse, + isSimulated: false, + + preventDefault: function() { + var e = this.originalEvent; + + this.isDefaultPrevented = returnTrue; + + if ( e && !this.isSimulated ) { + e.preventDefault(); + } + }, + stopPropagation: function() { + var e = this.originalEvent; + + this.isPropagationStopped = returnTrue; + + if ( e && !this.isSimulated ) { + e.stopPropagation(); + } + }, + stopImmediatePropagation: function() { + var e = this.originalEvent; + + this.isImmediatePropagationStopped = returnTrue; + + if ( e && !this.isSimulated ) { + e.stopImmediatePropagation(); + } + + this.stopPropagation(); + } +}; + +// Includes all common event props including KeyEvent and MouseEvent specific props +jQuery.each( { + altKey: true, + bubbles: true, + cancelable: true, + changedTouches: true, + ctrlKey: true, + detail: true, + eventPhase: true, + metaKey: true, + pageX: true, + pageY: true, + shiftKey: true, + view: true, + "char": true, + code: true, + charCode: true, + key: true, + keyCode: true, + button: true, + buttons: true, + clientX: true, + clientY: true, + offsetX: true, + offsetY: true, + pointerId: true, + pointerType: true, + screenX: true, + screenY: true, + targetTouches: true, + toElement: true, + touches: true, + + which: function( event ) { + var button = event.button; + + // Add which for key events + if ( event.which == null && rkeyEvent.test( event.type ) ) { + return event.charCode != null ? event.charCode : event.keyCode; + } + + // Add which for click: 1 === left; 2 === middle; 3 === right + if ( !event.which && button !== undefined && rmouseEvent.test( event.type ) ) { + if ( button & 1 ) { + return 1; + } + + if ( button & 2 ) { + return 3; + } + + if ( button & 4 ) { + return 2; + } + + return 0; + } + + return event.which; + } +}, jQuery.event.addProp ); + +jQuery.each( { focus: "focusin", blur: "focusout" }, function( type, delegateType ) { + jQuery.event.special[ type ] = { + + // Utilize native event if possible so blur/focus sequence is correct + setup: function() { + + // Claim the first handler + // dataPriv.set( this, "focus", ... ) + // dataPriv.set( this, "blur", ... ) + leverageNative( this, type, expectSync ); + + // Return false to allow normal processing in the caller + return false; + }, + trigger: function() { + + // Force setup before trigger + leverageNative( this, type ); + + // Return non-false to allow normal event-path propagation + return true; + }, + + delegateType: delegateType + }; +} ); + +// Create mouseenter/leave events using mouseover/out and event-time checks +// so that event delegation works in jQuery. +// Do the same for pointerenter/pointerleave and pointerover/pointerout +// +// Support: Safari 7 only +// Safari sends mouseenter too often; see: +// https://bugs.chromium.org/p/chromium/issues/detail?id=470258 +// for the description of the bug (it existed in older Chrome versions as well). +jQuery.each( { + mouseenter: "mouseover", + mouseleave: "mouseout", + pointerenter: "pointerover", + pointerleave: "pointerout" +}, function( orig, fix ) { + jQuery.event.special[ orig ] = { + delegateType: fix, + bindType: fix, + + handle: function( event ) { + var ret, + target = this, + related = event.relatedTarget, + handleObj = event.handleObj; + + // For mouseenter/leave call the handler if related is outside the target. + // NB: No relatedTarget if the mouse left/entered the browser window + if ( !related || ( related !== target && !jQuery.contains( target, related ) ) ) { + event.type = handleObj.origType; + ret = handleObj.handler.apply( this, arguments ); + event.type = fix; + } + return ret; + } + }; +} ); + +jQuery.fn.extend( { + + on: function( types, selector, data, fn ) { + return on( this, types, selector, data, fn ); + }, + one: function( types, selector, data, fn ) { + return on( this, types, selector, data, fn, 1 ); + }, + off: function( types, selector, fn ) { + var handleObj, type; + if ( types && types.preventDefault && types.handleObj ) { + + // ( event ) dispatched jQuery.Event + handleObj = types.handleObj; + jQuery( types.delegateTarget ).off( + handleObj.namespace ? + handleObj.origType + "." + handleObj.namespace : + handleObj.origType, + handleObj.selector, + handleObj.handler + ); + return this; + } + if ( typeof types === "object" ) { + + // ( types-object [, selector] ) + for ( type in types ) { + this.off( type, selector, types[ type ] ); + } + return this; + } + if ( selector === false || typeof selector === "function" ) { + + // ( types [, fn] ) + fn = selector; + selector = undefined; + } + if ( fn === false ) { + fn = returnFalse; + } + return this.each( function() { + jQuery.event.remove( this, types, fn, selector ); + } ); + } +} ); + + +var + + // Support: IE <=10 - 11, Edge 12 - 13 only + // In IE/Edge using regex groups here causes severe slowdowns. + // See https://connect.microsoft.com/IE/feedback/details/1736512/ + rnoInnerhtml = /\s*$/g; + +// Prefer a tbody over its parent table for containing new rows +function manipulationTarget( elem, content ) { + if ( nodeName( elem, "table" ) && + nodeName( content.nodeType !== 11 ? content : content.firstChild, "tr" ) ) { + + return jQuery( elem ).children( "tbody" )[ 0 ] || elem; + } + + return elem; +} + +// Replace/restore the type attribute of script elements for safe DOM manipulation +function disableScript( elem ) { + elem.type = ( elem.getAttribute( "type" ) !== null ) + "/" + elem.type; + return elem; +} +function restoreScript( elem ) { + if ( ( elem.type || "" ).slice( 0, 5 ) === "true/" ) { + elem.type = elem.type.slice( 5 ); + } else { + elem.removeAttribute( "type" ); + } + + return elem; +} + +function cloneCopyEvent( src, dest ) { + var i, l, type, pdataOld, udataOld, udataCur, events; + + if ( dest.nodeType !== 1 ) { + return; + } + + // 1. Copy private data: events, handlers, etc. + if ( dataPriv.hasData( src ) ) { + pdataOld = dataPriv.get( src ); + events = pdataOld.events; + + if ( events ) { + dataPriv.remove( dest, "handle events" ); + + for ( type in events ) { + for ( i = 0, l = events[ type ].length; i < l; i++ ) { + jQuery.event.add( dest, type, events[ type ][ i ] ); + } + } + } + } + + // 2. Copy user data + if ( dataUser.hasData( src ) ) { + udataOld = dataUser.access( src ); + udataCur = jQuery.extend( {}, udataOld ); + + dataUser.set( dest, udataCur ); + } +} + +// Fix IE bugs, see support tests +function fixInput( src, dest ) { + var nodeName = dest.nodeName.toLowerCase(); + + // Fails to persist the checked state of a cloned checkbox or radio button. + if ( nodeName === "input" && rcheckableType.test( src.type ) ) { + dest.checked = src.checked; + + // Fails to return the selected option to the default selected state when cloning options + } else if ( nodeName === "input" || nodeName === "textarea" ) { + dest.defaultValue = src.defaultValue; + } +} + +function domManip( collection, args, callback, ignored ) { + + // Flatten any nested arrays + args = flat( args ); + + var fragment, first, scripts, hasScripts, node, doc, + i = 0, + l = collection.length, + iNoClone = l - 1, + value = args[ 0 ], + valueIsFunction = isFunction( value ); + + // We can't cloneNode fragments that contain checked, in WebKit + if ( valueIsFunction || + ( l > 1 && typeof value === "string" && + !support.checkClone && rchecked.test( value ) ) ) { + return collection.each( function( index ) { + var self = collection.eq( index ); + if ( valueIsFunction ) { + args[ 0 ] = value.call( this, index, self.html() ); + } + domManip( self, args, callback, ignored ); + } ); + } + + if ( l ) { + fragment = buildFragment( args, collection[ 0 ].ownerDocument, false, collection, ignored ); + first = fragment.firstChild; + + if ( fragment.childNodes.length === 1 ) { + fragment = first; + } + + // Require either new content or an interest in ignored elements to invoke the callback + if ( first || ignored ) { + scripts = jQuery.map( getAll( fragment, "script" ), disableScript ); + hasScripts = scripts.length; + + // Use the original fragment for the last item + // instead of the first because it can end up + // being emptied incorrectly in certain situations (#8070). + for ( ; i < l; i++ ) { + node = fragment; + + if ( i !== iNoClone ) { + node = jQuery.clone( node, true, true ); + + // Keep references to cloned scripts for later restoration + if ( hasScripts ) { + + // Support: Android <=4.0 only, PhantomJS 1 only + // push.apply(_, arraylike) throws on ancient WebKit + jQuery.merge( scripts, getAll( node, "script" ) ); + } + } + + callback.call( collection[ i ], node, i ); + } + + if ( hasScripts ) { + doc = scripts[ scripts.length - 1 ].ownerDocument; + + // Reenable scripts + jQuery.map( scripts, restoreScript ); + + // Evaluate executable scripts on first document insertion + for ( i = 0; i < hasScripts; i++ ) { + node = scripts[ i ]; + if ( rscriptType.test( node.type || "" ) && + !dataPriv.access( node, "globalEval" ) && + jQuery.contains( doc, node ) ) { + + if ( node.src && ( node.type || "" ).toLowerCase() !== "module" ) { + + // Optional AJAX dependency, but won't run scripts if not present + if ( jQuery._evalUrl && !node.noModule ) { + jQuery._evalUrl( node.src, { + nonce: node.nonce || node.getAttribute( "nonce" ) + }, doc ); + } + } else { + DOMEval( node.textContent.replace( rcleanScript, "" ), node, doc ); + } + } + } + } + } + } + + return collection; +} + +function remove( elem, selector, keepData ) { + var node, + nodes = selector ? jQuery.filter( selector, elem ) : elem, + i = 0; + + for ( ; ( node = nodes[ i ] ) != null; i++ ) { + if ( !keepData && node.nodeType === 1 ) { + jQuery.cleanData( getAll( node ) ); + } + + if ( node.parentNode ) { + if ( keepData && isAttached( node ) ) { + setGlobalEval( getAll( node, "script" ) ); + } + node.parentNode.removeChild( node ); + } + } + + return elem; +} + +jQuery.extend( { + htmlPrefilter: function( html ) { + return html; + }, + + clone: function( elem, dataAndEvents, deepDataAndEvents ) { + var i, l, srcElements, destElements, + clone = elem.cloneNode( true ), + inPage = isAttached( elem ); + + // Fix IE cloning issues + if ( !support.noCloneChecked && ( elem.nodeType === 1 || elem.nodeType === 11 ) && + !jQuery.isXMLDoc( elem ) ) { + + // We eschew Sizzle here for performance reasons: https://jsperf.com/getall-vs-sizzle/2 + destElements = getAll( clone ); + srcElements = getAll( elem ); + + for ( i = 0, l = srcElements.length; i < l; i++ ) { + fixInput( srcElements[ i ], destElements[ i ] ); + } + } + + // Copy the events from the original to the clone + if ( dataAndEvents ) { + if ( deepDataAndEvents ) { + srcElements = srcElements || getAll( elem ); + destElements = destElements || getAll( clone ); + + for ( i = 0, l = srcElements.length; i < l; i++ ) { + cloneCopyEvent( srcElements[ i ], destElements[ i ] ); + } + } else { + cloneCopyEvent( elem, clone ); + } + } + + // Preserve script evaluation history + destElements = getAll( clone, "script" ); + if ( destElements.length > 0 ) { + setGlobalEval( destElements, !inPage && getAll( elem, "script" ) ); + } + + // Return the cloned set + return clone; + }, + + cleanData: function( elems ) { + var data, elem, type, + special = jQuery.event.special, + i = 0; + + for ( ; ( elem = elems[ i ] ) !== undefined; i++ ) { + if ( acceptData( elem ) ) { + if ( ( data = elem[ dataPriv.expando ] ) ) { + if ( data.events ) { + for ( type in data.events ) { + if ( special[ type ] ) { + jQuery.event.remove( elem, type ); + + // This is a shortcut to avoid jQuery.event.remove's overhead + } else { + jQuery.removeEvent( elem, type, data.handle ); + } + } + } + + // Support: Chrome <=35 - 45+ + // Assign undefined instead of using delete, see Data#remove + elem[ dataPriv.expando ] = undefined; + } + if ( elem[ dataUser.expando ] ) { + + // Support: Chrome <=35 - 45+ + // Assign undefined instead of using delete, see Data#remove + elem[ dataUser.expando ] = undefined; + } + } + } + } +} ); + +jQuery.fn.extend( { + detach: function( selector ) { + return remove( this, selector, true ); + }, + + remove: function( selector ) { + return remove( this, selector ); + }, + + text: function( value ) { + return access( this, function( value ) { + return value === undefined ? + jQuery.text( this ) : + this.empty().each( function() { + if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { + this.textContent = value; + } + } ); + }, null, value, arguments.length ); + }, + + append: function() { + return domManip( this, arguments, function( elem ) { + if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { + var target = manipulationTarget( this, elem ); + target.appendChild( elem ); + } + } ); + }, + + prepend: function() { + return domManip( this, arguments, function( elem ) { + if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { + var target = manipulationTarget( this, elem ); + target.insertBefore( elem, target.firstChild ); + } + } ); + }, + + before: function() { + return domManip( this, arguments, function( elem ) { + if ( this.parentNode ) { + this.parentNode.insertBefore( elem, this ); + } + } ); + }, + + after: function() { + return domManip( this, arguments, function( elem ) { + if ( this.parentNode ) { + this.parentNode.insertBefore( elem, this.nextSibling ); + } + } ); + }, + + empty: function() { + var elem, + i = 0; + + for ( ; ( elem = this[ i ] ) != null; i++ ) { + if ( elem.nodeType === 1 ) { + + // Prevent memory leaks + jQuery.cleanData( getAll( elem, false ) ); + + // Remove any remaining nodes + elem.textContent = ""; + } + } + + return this; + }, + + clone: function( dataAndEvents, deepDataAndEvents ) { + dataAndEvents = dataAndEvents == null ? false : dataAndEvents; + deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents; + + return this.map( function() { + return jQuery.clone( this, dataAndEvents, deepDataAndEvents ); + } ); + }, + + html: function( value ) { + return access( this, function( value ) { + var elem = this[ 0 ] || {}, + i = 0, + l = this.length; + + if ( value === undefined && elem.nodeType === 1 ) { + return elem.innerHTML; + } + + // See if we can take a shortcut and just use innerHTML + if ( typeof value === "string" && !rnoInnerhtml.test( value ) && + !wrapMap[ ( rtagName.exec( value ) || [ "", "" ] )[ 1 ].toLowerCase() ] ) { + + value = jQuery.htmlPrefilter( value ); + + try { + for ( ; i < l; i++ ) { + elem = this[ i ] || {}; + + // Remove element nodes and prevent memory leaks + if ( elem.nodeType === 1 ) { + jQuery.cleanData( getAll( elem, false ) ); + elem.innerHTML = value; + } + } + + elem = 0; + + // If using innerHTML throws an exception, use the fallback method + } catch ( e ) {} + } + + if ( elem ) { + this.empty().append( value ); + } + }, null, value, arguments.length ); + }, + + replaceWith: function() { + var ignored = []; + + // Make the changes, replacing each non-ignored context element with the new content + return domManip( this, arguments, function( elem ) { + var parent = this.parentNode; + + if ( jQuery.inArray( this, ignored ) < 0 ) { + jQuery.cleanData( getAll( this ) ); + if ( parent ) { + parent.replaceChild( elem, this ); + } + } + + // Force callback invocation + }, ignored ); + } +} ); + +jQuery.each( { + appendTo: "append", + prependTo: "prepend", + insertBefore: "before", + insertAfter: "after", + replaceAll: "replaceWith" +}, function( name, original ) { + jQuery.fn[ name ] = function( selector ) { + var elems, + ret = [], + insert = jQuery( selector ), + last = insert.length - 1, + i = 0; + + for ( ; i <= last; i++ ) { + elems = i === last ? this : this.clone( true ); + jQuery( insert[ i ] )[ original ]( elems ); + + // Support: Android <=4.0 only, PhantomJS 1 only + // .get() because push.apply(_, arraylike) throws on ancient WebKit + push.apply( ret, elems.get() ); + } + + return this.pushStack( ret ); + }; +} ); +var rnumnonpx = new RegExp( "^(" + pnum + ")(?!px)[a-z%]+$", "i" ); + +var getStyles = function( elem ) { + + // Support: IE <=11 only, Firefox <=30 (#15098, #14150) + // IE throws on elements created in popups + // FF meanwhile throws on frame elements through "defaultView.getComputedStyle" + var view = elem.ownerDocument.defaultView; + + if ( !view || !view.opener ) { + view = window; + } + + return view.getComputedStyle( elem ); + }; + +var swap = function( elem, options, callback ) { + var ret, name, + old = {}; + + // Remember the old values, and insert the new ones + for ( name in options ) { + old[ name ] = elem.style[ name ]; + elem.style[ name ] = options[ name ]; + } + + ret = callback.call( elem ); + + // Revert the old values + for ( name in options ) { + elem.style[ name ] = old[ name ]; + } + + return ret; +}; + + +var rboxStyle = new RegExp( cssExpand.join( "|" ), "i" ); + + + +( function() { + + // Executing both pixelPosition & boxSizingReliable tests require only one layout + // so they're executed at the same time to save the second computation. + function computeStyleTests() { + + // This is a singleton, we need to execute it only once + if ( !div ) { + return; + } + + container.style.cssText = "position:absolute;left:-11111px;width:60px;" + + "margin-top:1px;padding:0;border:0"; + div.style.cssText = + "position:relative;display:block;box-sizing:border-box;overflow:scroll;" + + "margin:auto;border:1px;padding:1px;" + + "width:60%;top:1%"; + documentElement.appendChild( container ).appendChild( div ); + + var divStyle = window.getComputedStyle( div ); + pixelPositionVal = divStyle.top !== "1%"; + + // Support: Android 4.0 - 4.3 only, Firefox <=3 - 44 + reliableMarginLeftVal = roundPixelMeasures( divStyle.marginLeft ) === 12; + + // Support: Android 4.0 - 4.3 only, Safari <=9.1 - 10.1, iOS <=7.0 - 9.3 + // Some styles come back with percentage values, even though they shouldn't + div.style.right = "60%"; + pixelBoxStylesVal = roundPixelMeasures( divStyle.right ) === 36; + + // Support: IE 9 - 11 only + // Detect misreporting of content dimensions for box-sizing:border-box elements + boxSizingReliableVal = roundPixelMeasures( divStyle.width ) === 36; + + // Support: IE 9 only + // Detect overflow:scroll screwiness (gh-3699) + // Support: Chrome <=64 + // Don't get tricked when zoom affects offsetWidth (gh-4029) + div.style.position = "absolute"; + scrollboxSizeVal = roundPixelMeasures( div.offsetWidth / 3 ) === 12; + + documentElement.removeChild( container ); + + // Nullify the div so it wouldn't be stored in the memory and + // it will also be a sign that checks already performed + div = null; + } + + function roundPixelMeasures( measure ) { + return Math.round( parseFloat( measure ) ); + } + + var pixelPositionVal, boxSizingReliableVal, scrollboxSizeVal, pixelBoxStylesVal, + reliableTrDimensionsVal, reliableMarginLeftVal, + container = document.createElement( "div" ), + div = document.createElement( "div" ); + + // Finish early in limited (non-browser) environments + if ( !div.style ) { + return; + } + + // Support: IE <=9 - 11 only + // Style of cloned element affects source element cloned (#8908) + div.style.backgroundClip = "content-box"; + div.cloneNode( true ).style.backgroundClip = ""; + support.clearCloneStyle = div.style.backgroundClip === "content-box"; + + jQuery.extend( support, { + boxSizingReliable: function() { + computeStyleTests(); + return boxSizingReliableVal; + }, + pixelBoxStyles: function() { + computeStyleTests(); + return pixelBoxStylesVal; + }, + pixelPosition: function() { + computeStyleTests(); + return pixelPositionVal; + }, + reliableMarginLeft: function() { + computeStyleTests(); + return reliableMarginLeftVal; + }, + scrollboxSize: function() { + computeStyleTests(); + return scrollboxSizeVal; + }, + + // Support: IE 9 - 11+, Edge 15 - 18+ + // IE/Edge misreport `getComputedStyle` of table rows with width/height + // set in CSS while `offset*` properties report correct values. + // Behavior in IE 9 is more subtle than in newer versions & it passes + // some versions of this test; make sure not to make it pass there! + reliableTrDimensions: function() { + var table, tr, trChild, trStyle; + if ( reliableTrDimensionsVal == null ) { + table = document.createElement( "table" ); + tr = document.createElement( "tr" ); + trChild = document.createElement( "div" ); + + table.style.cssText = "position:absolute;left:-11111px"; + tr.style.height = "1px"; + trChild.style.height = "9px"; + + documentElement + .appendChild( table ) + .appendChild( tr ) + .appendChild( trChild ); + + trStyle = window.getComputedStyle( tr ); + reliableTrDimensionsVal = parseInt( trStyle.height ) > 3; + + documentElement.removeChild( table ); + } + return reliableTrDimensionsVal; + } + } ); +} )(); + + +function curCSS( elem, name, computed ) { + var width, minWidth, maxWidth, ret, + + // Support: Firefox 51+ + // Retrieving style before computed somehow + // fixes an issue with getting wrong values + // on detached elements + style = elem.style; + + computed = computed || getStyles( elem ); + + // getPropertyValue is needed for: + // .css('filter') (IE 9 only, #12537) + // .css('--customProperty) (#3144) + if ( computed ) { + ret = computed.getPropertyValue( name ) || computed[ name ]; + + if ( ret === "" && !isAttached( elem ) ) { + ret = jQuery.style( elem, name ); + } + + // A tribute to the "awesome hack by Dean Edwards" + // Android Browser returns percentage for some values, + // but width seems to be reliably pixels. + // This is against the CSSOM draft spec: + // https://drafts.csswg.org/cssom/#resolved-values + if ( !support.pixelBoxStyles() && rnumnonpx.test( ret ) && rboxStyle.test( name ) ) { + + // Remember the original values + width = style.width; + minWidth = style.minWidth; + maxWidth = style.maxWidth; + + // Put in the new values to get a computed value out + style.minWidth = style.maxWidth = style.width = ret; + ret = computed.width; + + // Revert the changed values + style.width = width; + style.minWidth = minWidth; + style.maxWidth = maxWidth; + } + } + + return ret !== undefined ? + + // Support: IE <=9 - 11 only + // IE returns zIndex value as an integer. + ret + "" : + ret; +} + + +function addGetHookIf( conditionFn, hookFn ) { + + // Define the hook, we'll check on the first run if it's really needed. + return { + get: function() { + if ( conditionFn() ) { + + // Hook not needed (or it's not possible to use it due + // to missing dependency), remove it. + delete this.get; + return; + } + + // Hook needed; redefine it so that the support test is not executed again. + return ( this.get = hookFn ).apply( this, arguments ); + } + }; +} + + +var cssPrefixes = [ "Webkit", "Moz", "ms" ], + emptyStyle = document.createElement( "div" ).style, + vendorProps = {}; + +// Return a vendor-prefixed property or undefined +function vendorPropName( name ) { + + // Check for vendor prefixed names + var capName = name[ 0 ].toUpperCase() + name.slice( 1 ), + i = cssPrefixes.length; + + while ( i-- ) { + name = cssPrefixes[ i ] + capName; + if ( name in emptyStyle ) { + return name; + } + } +} + +// Return a potentially-mapped jQuery.cssProps or vendor prefixed property +function finalPropName( name ) { + var final = jQuery.cssProps[ name ] || vendorProps[ name ]; + + if ( final ) { + return final; + } + if ( name in emptyStyle ) { + return name; + } + return vendorProps[ name ] = vendorPropName( name ) || name; +} + + +var + + // Swappable if display is none or starts with table + // except "table", "table-cell", or "table-caption" + // See here for display values: https://developer.mozilla.org/en-US/docs/CSS/display + rdisplayswap = /^(none|table(?!-c[ea]).+)/, + rcustomProp = /^--/, + cssShow = { position: "absolute", visibility: "hidden", display: "block" }, + cssNormalTransform = { + letterSpacing: "0", + fontWeight: "400" + }; + +function setPositiveNumber( _elem, value, subtract ) { + + // Any relative (+/-) values have already been + // normalized at this point + var matches = rcssNum.exec( value ); + return matches ? + + // Guard against undefined "subtract", e.g., when used as in cssHooks + Math.max( 0, matches[ 2 ] - ( subtract || 0 ) ) + ( matches[ 3 ] || "px" ) : + value; +} + +function boxModelAdjustment( elem, dimension, box, isBorderBox, styles, computedVal ) { + var i = dimension === "width" ? 1 : 0, + extra = 0, + delta = 0; + + // Adjustment may not be necessary + if ( box === ( isBorderBox ? "border" : "content" ) ) { + return 0; + } + + for ( ; i < 4; i += 2 ) { + + // Both box models exclude margin + if ( box === "margin" ) { + delta += jQuery.css( elem, box + cssExpand[ i ], true, styles ); + } + + // If we get here with a content-box, we're seeking "padding" or "border" or "margin" + if ( !isBorderBox ) { + + // Add padding + delta += jQuery.css( elem, "padding" + cssExpand[ i ], true, styles ); + + // For "border" or "margin", add border + if ( box !== "padding" ) { + delta += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); + + // But still keep track of it otherwise + } else { + extra += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); + } + + // If we get here with a border-box (content + padding + border), we're seeking "content" or + // "padding" or "margin" + } else { + + // For "content", subtract padding + if ( box === "content" ) { + delta -= jQuery.css( elem, "padding" + cssExpand[ i ], true, styles ); + } + + // For "content" or "padding", subtract border + if ( box !== "margin" ) { + delta -= jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); + } + } + } + + // Account for positive content-box scroll gutter when requested by providing computedVal + if ( !isBorderBox && computedVal >= 0 ) { + + // offsetWidth/offsetHeight is a rounded sum of content, padding, scroll gutter, and border + // Assuming integer scroll gutter, subtract the rest and round down + delta += Math.max( 0, Math.ceil( + elem[ "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ) ] - + computedVal - + delta - + extra - + 0.5 + + // If offsetWidth/offsetHeight is unknown, then we can't determine content-box scroll gutter + // Use an explicit zero to avoid NaN (gh-3964) + ) ) || 0; + } + + return delta; +} + +function getWidthOrHeight( elem, dimension, extra ) { + + // Start with computed style + var styles = getStyles( elem ), + + // To avoid forcing a reflow, only fetch boxSizing if we need it (gh-4322). + // Fake content-box until we know it's needed to know the true value. + boxSizingNeeded = !support.boxSizingReliable() || extra, + isBorderBox = boxSizingNeeded && + jQuery.css( elem, "boxSizing", false, styles ) === "border-box", + valueIsBorderBox = isBorderBox, + + val = curCSS( elem, dimension, styles ), + offsetProp = "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ); + + // Support: Firefox <=54 + // Return a confounding non-pixel value or feign ignorance, as appropriate. + if ( rnumnonpx.test( val ) ) { + if ( !extra ) { + return val; + } + val = "auto"; + } + + + // Support: IE 9 - 11 only + // Use offsetWidth/offsetHeight for when box sizing is unreliable. + // In those cases, the computed value can be trusted to be border-box. + if ( ( !support.boxSizingReliable() && isBorderBox || + + // Support: IE 10 - 11+, Edge 15 - 18+ + // IE/Edge misreport `getComputedStyle` of table rows with width/height + // set in CSS while `offset*` properties report correct values. + // Interestingly, in some cases IE 9 doesn't suffer from this issue. + !support.reliableTrDimensions() && nodeName( elem, "tr" ) || + + // Fall back to offsetWidth/offsetHeight when value is "auto" + // This happens for inline elements with no explicit setting (gh-3571) + val === "auto" || + + // Support: Android <=4.1 - 4.3 only + // Also use offsetWidth/offsetHeight for misreported inline dimensions (gh-3602) + !parseFloat( val ) && jQuery.css( elem, "display", false, styles ) === "inline" ) && + + // Make sure the element is visible & connected + elem.getClientRects().length ) { + + isBorderBox = jQuery.css( elem, "boxSizing", false, styles ) === "border-box"; + + // Where available, offsetWidth/offsetHeight approximate border box dimensions. + // Where not available (e.g., SVG), assume unreliable box-sizing and interpret the + // retrieved value as a content box dimension. + valueIsBorderBox = offsetProp in elem; + if ( valueIsBorderBox ) { + val = elem[ offsetProp ]; + } + } + + // Normalize "" and auto + val = parseFloat( val ) || 0; + + // Adjust for the element's box model + return ( val + + boxModelAdjustment( + elem, + dimension, + extra || ( isBorderBox ? "border" : "content" ), + valueIsBorderBox, + styles, + + // Provide the current computed size to request scroll gutter calculation (gh-3589) + val + ) + ) + "px"; +} + +jQuery.extend( { + + // Add in style property hooks for overriding the default + // behavior of getting and setting a style property + cssHooks: { + opacity: { + get: function( elem, computed ) { + if ( computed ) { + + // We should always get a number back from opacity + var ret = curCSS( elem, "opacity" ); + return ret === "" ? "1" : ret; + } + } + } + }, + + // Don't automatically add "px" to these possibly-unitless properties + cssNumber: { + "animationIterationCount": true, + "columnCount": true, + "fillOpacity": true, + "flexGrow": true, + "flexShrink": true, + "fontWeight": true, + "gridArea": true, + "gridColumn": true, + "gridColumnEnd": true, + "gridColumnStart": true, + "gridRow": true, + "gridRowEnd": true, + "gridRowStart": true, + "lineHeight": true, + "opacity": true, + "order": true, + "orphans": true, + "widows": true, + "zIndex": true, + "zoom": true + }, + + // Add in properties whose names you wish to fix before + // setting or getting the value + cssProps: {}, + + // Get and set the style property on a DOM Node + style: function( elem, name, value, extra ) { + + // Don't set styles on text and comment nodes + if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) { + return; + } + + // Make sure that we're working with the right name + var ret, type, hooks, + origName = camelCase( name ), + isCustomProp = rcustomProp.test( name ), + style = elem.style; + + // Make sure that we're working with the right name. We don't + // want to query the value if it is a CSS custom property + // since they are user-defined. + if ( !isCustomProp ) { + name = finalPropName( origName ); + } + + // Gets hook for the prefixed version, then unprefixed version + hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ]; + + // Check if we're setting a value + if ( value !== undefined ) { + type = typeof value; + + // Convert "+=" or "-=" to relative numbers (#7345) + if ( type === "string" && ( ret = rcssNum.exec( value ) ) && ret[ 1 ] ) { + value = adjustCSS( elem, name, ret ); + + // Fixes bug #9237 + type = "number"; + } + + // Make sure that null and NaN values aren't set (#7116) + if ( value == null || value !== value ) { + return; + } + + // If a number was passed in, add the unit (except for certain CSS properties) + // The isCustomProp check can be removed in jQuery 4.0 when we only auto-append + // "px" to a few hardcoded values. + if ( type === "number" && !isCustomProp ) { + value += ret && ret[ 3 ] || ( jQuery.cssNumber[ origName ] ? "" : "px" ); + } + + // background-* props affect original clone's values + if ( !support.clearCloneStyle && value === "" && name.indexOf( "background" ) === 0 ) { + style[ name ] = "inherit"; + } + + // If a hook was provided, use that value, otherwise just set the specified value + if ( !hooks || !( "set" in hooks ) || + ( value = hooks.set( elem, value, extra ) ) !== undefined ) { + + if ( isCustomProp ) { + style.setProperty( name, value ); + } else { + style[ name ] = value; + } + } + + } else { + + // If a hook was provided get the non-computed value from there + if ( hooks && "get" in hooks && + ( ret = hooks.get( elem, false, extra ) ) !== undefined ) { + + return ret; + } + + // Otherwise just get the value from the style object + return style[ name ]; + } + }, + + css: function( elem, name, extra, styles ) { + var val, num, hooks, + origName = camelCase( name ), + isCustomProp = rcustomProp.test( name ); + + // Make sure that we're working with the right name. We don't + // want to modify the value if it is a CSS custom property + // since they are user-defined. + if ( !isCustomProp ) { + name = finalPropName( origName ); + } + + // Try prefixed name followed by the unprefixed name + hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ]; + + // If a hook was provided get the computed value from there + if ( hooks && "get" in hooks ) { + val = hooks.get( elem, true, extra ); + } + + // Otherwise, if a way to get the computed value exists, use that + if ( val === undefined ) { + val = curCSS( elem, name, styles ); + } + + // Convert "normal" to computed value + if ( val === "normal" && name in cssNormalTransform ) { + val = cssNormalTransform[ name ]; + } + + // Make numeric if forced or a qualifier was provided and val looks numeric + if ( extra === "" || extra ) { + num = parseFloat( val ); + return extra === true || isFinite( num ) ? num || 0 : val; + } + + return val; + } +} ); + +jQuery.each( [ "height", "width" ], function( _i, dimension ) { + jQuery.cssHooks[ dimension ] = { + get: function( elem, computed, extra ) { + if ( computed ) { + + // Certain elements can have dimension info if we invisibly show them + // but it must have a current display style that would benefit + return rdisplayswap.test( jQuery.css( elem, "display" ) ) && + + // Support: Safari 8+ + // Table columns in Safari have non-zero offsetWidth & zero + // getBoundingClientRect().width unless display is changed. + // Support: IE <=11 only + // Running getBoundingClientRect on a disconnected node + // in IE throws an error. + ( !elem.getClientRects().length || !elem.getBoundingClientRect().width ) ? + swap( elem, cssShow, function() { + return getWidthOrHeight( elem, dimension, extra ); + } ) : + getWidthOrHeight( elem, dimension, extra ); + } + }, + + set: function( elem, value, extra ) { + var matches, + styles = getStyles( elem ), + + // Only read styles.position if the test has a chance to fail + // to avoid forcing a reflow. + scrollboxSizeBuggy = !support.scrollboxSize() && + styles.position === "absolute", + + // To avoid forcing a reflow, only fetch boxSizing if we need it (gh-3991) + boxSizingNeeded = scrollboxSizeBuggy || extra, + isBorderBox = boxSizingNeeded && + jQuery.css( elem, "boxSizing", false, styles ) === "border-box", + subtract = extra ? + boxModelAdjustment( + elem, + dimension, + extra, + isBorderBox, + styles + ) : + 0; + + // Account for unreliable border-box dimensions by comparing offset* to computed and + // faking a content-box to get border and padding (gh-3699) + if ( isBorderBox && scrollboxSizeBuggy ) { + subtract -= Math.ceil( + elem[ "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ) ] - + parseFloat( styles[ dimension ] ) - + boxModelAdjustment( elem, dimension, "border", false, styles ) - + 0.5 + ); + } + + // Convert to pixels if value adjustment is needed + if ( subtract && ( matches = rcssNum.exec( value ) ) && + ( matches[ 3 ] || "px" ) !== "px" ) { + + elem.style[ dimension ] = value; + value = jQuery.css( elem, dimension ); + } + + return setPositiveNumber( elem, value, subtract ); + } + }; +} ); + +jQuery.cssHooks.marginLeft = addGetHookIf( support.reliableMarginLeft, + function( elem, computed ) { + if ( computed ) { + return ( parseFloat( curCSS( elem, "marginLeft" ) ) || + elem.getBoundingClientRect().left - + swap( elem, { marginLeft: 0 }, function() { + return elem.getBoundingClientRect().left; + } ) + ) + "px"; + } + } +); + +// These hooks are used by animate to expand properties +jQuery.each( { + margin: "", + padding: "", + border: "Width" +}, function( prefix, suffix ) { + jQuery.cssHooks[ prefix + suffix ] = { + expand: function( value ) { + var i = 0, + expanded = {}, + + // Assumes a single number if not a string + parts = typeof value === "string" ? value.split( " " ) : [ value ]; + + for ( ; i < 4; i++ ) { + expanded[ prefix + cssExpand[ i ] + suffix ] = + parts[ i ] || parts[ i - 2 ] || parts[ 0 ]; + } + + return expanded; + } + }; + + if ( prefix !== "margin" ) { + jQuery.cssHooks[ prefix + suffix ].set = setPositiveNumber; + } +} ); + +jQuery.fn.extend( { + css: function( name, value ) { + return access( this, function( elem, name, value ) { + var styles, len, + map = {}, + i = 0; + + if ( Array.isArray( name ) ) { + styles = getStyles( elem ); + len = name.length; + + for ( ; i < len; i++ ) { + map[ name[ i ] ] = jQuery.css( elem, name[ i ], false, styles ); + } + + return map; + } + + return value !== undefined ? + jQuery.style( elem, name, value ) : + jQuery.css( elem, name ); + }, name, value, arguments.length > 1 ); + } +} ); + + +function Tween( elem, options, prop, end, easing ) { + return new Tween.prototype.init( elem, options, prop, end, easing ); +} +jQuery.Tween = Tween; + +Tween.prototype = { + constructor: Tween, + init: function( elem, options, prop, end, easing, unit ) { + this.elem = elem; + this.prop = prop; + this.easing = easing || jQuery.easing._default; + this.options = options; + this.start = this.now = this.cur(); + this.end = end; + this.unit = unit || ( jQuery.cssNumber[ prop ] ? "" : "px" ); + }, + cur: function() { + var hooks = Tween.propHooks[ this.prop ]; + + return hooks && hooks.get ? + hooks.get( this ) : + Tween.propHooks._default.get( this ); + }, + run: function( percent ) { + var eased, + hooks = Tween.propHooks[ this.prop ]; + + if ( this.options.duration ) { + this.pos = eased = jQuery.easing[ this.easing ]( + percent, this.options.duration * percent, 0, 1, this.options.duration + ); + } else { + this.pos = eased = percent; + } + this.now = ( this.end - this.start ) * eased + this.start; + + if ( this.options.step ) { + this.options.step.call( this.elem, this.now, this ); + } + + if ( hooks && hooks.set ) { + hooks.set( this ); + } else { + Tween.propHooks._default.set( this ); + } + return this; + } +}; + +Tween.prototype.init.prototype = Tween.prototype; + +Tween.propHooks = { + _default: { + get: function( tween ) { + var result; + + // Use a property on the element directly when it is not a DOM element, + // or when there is no matching style property that exists. + if ( tween.elem.nodeType !== 1 || + tween.elem[ tween.prop ] != null && tween.elem.style[ tween.prop ] == null ) { + return tween.elem[ tween.prop ]; + } + + // Passing an empty string as a 3rd parameter to .css will automatically + // attempt a parseFloat and fallback to a string if the parse fails. + // Simple values such as "10px" are parsed to Float; + // complex values such as "rotate(1rad)" are returned as-is. + result = jQuery.css( tween.elem, tween.prop, "" ); + + // Empty strings, null, undefined and "auto" are converted to 0. + return !result || result === "auto" ? 0 : result; + }, + set: function( tween ) { + + // Use step hook for back compat. + // Use cssHook if its there. + // Use .style if available and use plain properties where available. + if ( jQuery.fx.step[ tween.prop ] ) { + jQuery.fx.step[ tween.prop ]( tween ); + } else if ( tween.elem.nodeType === 1 && ( + jQuery.cssHooks[ tween.prop ] || + tween.elem.style[ finalPropName( tween.prop ) ] != null ) ) { + jQuery.style( tween.elem, tween.prop, tween.now + tween.unit ); + } else { + tween.elem[ tween.prop ] = tween.now; + } + } + } +}; + +// Support: IE <=9 only +// Panic based approach to setting things on disconnected nodes +Tween.propHooks.scrollTop = Tween.propHooks.scrollLeft = { + set: function( tween ) { + if ( tween.elem.nodeType && tween.elem.parentNode ) { + tween.elem[ tween.prop ] = tween.now; + } + } +}; + +jQuery.easing = { + linear: function( p ) { + return p; + }, + swing: function( p ) { + return 0.5 - Math.cos( p * Math.PI ) / 2; + }, + _default: "swing" +}; + +jQuery.fx = Tween.prototype.init; + +// Back compat <1.8 extension point +jQuery.fx.step = {}; + + + + +var + fxNow, inProgress, + rfxtypes = /^(?:toggle|show|hide)$/, + rrun = /queueHooks$/; + +function schedule() { + if ( inProgress ) { + if ( document.hidden === false && window.requestAnimationFrame ) { + window.requestAnimationFrame( schedule ); + } else { + window.setTimeout( schedule, jQuery.fx.interval ); + } + + jQuery.fx.tick(); + } +} + +// Animations created synchronously will run synchronously +function createFxNow() { + window.setTimeout( function() { + fxNow = undefined; + } ); + return ( fxNow = Date.now() ); +} + +// Generate parameters to create a standard animation +function genFx( type, includeWidth ) { + var which, + i = 0, + attrs = { height: type }; + + // If we include width, step value is 1 to do all cssExpand values, + // otherwise step value is 2 to skip over Left and Right + includeWidth = includeWidth ? 1 : 0; + for ( ; i < 4; i += 2 - includeWidth ) { + which = cssExpand[ i ]; + attrs[ "margin" + which ] = attrs[ "padding" + which ] = type; + } + + if ( includeWidth ) { + attrs.opacity = attrs.width = type; + } + + return attrs; +} + +function createTween( value, prop, animation ) { + var tween, + collection = ( Animation.tweeners[ prop ] || [] ).concat( Animation.tweeners[ "*" ] ), + index = 0, + length = collection.length; + for ( ; index < length; index++ ) { + if ( ( tween = collection[ index ].call( animation, prop, value ) ) ) { + + // We're done with this property + return tween; + } + } +} + +function defaultPrefilter( elem, props, opts ) { + var prop, value, toggle, hooks, oldfire, propTween, restoreDisplay, display, + isBox = "width" in props || "height" in props, + anim = this, + orig = {}, + style = elem.style, + hidden = elem.nodeType && isHiddenWithinTree( elem ), + dataShow = dataPriv.get( elem, "fxshow" ); + + // Queue-skipping animations hijack the fx hooks + if ( !opts.queue ) { + hooks = jQuery._queueHooks( elem, "fx" ); + if ( hooks.unqueued == null ) { + hooks.unqueued = 0; + oldfire = hooks.empty.fire; + hooks.empty.fire = function() { + if ( !hooks.unqueued ) { + oldfire(); + } + }; + } + hooks.unqueued++; + + anim.always( function() { + + // Ensure the complete handler is called before this completes + anim.always( function() { + hooks.unqueued--; + if ( !jQuery.queue( elem, "fx" ).length ) { + hooks.empty.fire(); + } + } ); + } ); + } + + // Detect show/hide animations + for ( prop in props ) { + value = props[ prop ]; + if ( rfxtypes.test( value ) ) { + delete props[ prop ]; + toggle = toggle || value === "toggle"; + if ( value === ( hidden ? "hide" : "show" ) ) { + + // Pretend to be hidden if this is a "show" and + // there is still data from a stopped show/hide + if ( value === "show" && dataShow && dataShow[ prop ] !== undefined ) { + hidden = true; + + // Ignore all other no-op show/hide data + } else { + continue; + } + } + orig[ prop ] = dataShow && dataShow[ prop ] || jQuery.style( elem, prop ); + } + } + + // Bail out if this is a no-op like .hide().hide() + propTween = !jQuery.isEmptyObject( props ); + if ( !propTween && jQuery.isEmptyObject( orig ) ) { + return; + } + + // Restrict "overflow" and "display" styles during box animations + if ( isBox && elem.nodeType === 1 ) { + + // Support: IE <=9 - 11, Edge 12 - 15 + // Record all 3 overflow attributes because IE does not infer the shorthand + // from identically-valued overflowX and overflowY and Edge just mirrors + // the overflowX value there. + opts.overflow = [ style.overflow, style.overflowX, style.overflowY ]; + + // Identify a display type, preferring old show/hide data over the CSS cascade + restoreDisplay = dataShow && dataShow.display; + if ( restoreDisplay == null ) { + restoreDisplay = dataPriv.get( elem, "display" ); + } + display = jQuery.css( elem, "display" ); + if ( display === "none" ) { + if ( restoreDisplay ) { + display = restoreDisplay; + } else { + + // Get nonempty value(s) by temporarily forcing visibility + showHide( [ elem ], true ); + restoreDisplay = elem.style.display || restoreDisplay; + display = jQuery.css( elem, "display" ); + showHide( [ elem ] ); + } + } + + // Animate inline elements as inline-block + if ( display === "inline" || display === "inline-block" && restoreDisplay != null ) { + if ( jQuery.css( elem, "float" ) === "none" ) { + + // Restore the original display value at the end of pure show/hide animations + if ( !propTween ) { + anim.done( function() { + style.display = restoreDisplay; + } ); + if ( restoreDisplay == null ) { + display = style.display; + restoreDisplay = display === "none" ? "" : display; + } + } + style.display = "inline-block"; + } + } + } + + if ( opts.overflow ) { + style.overflow = "hidden"; + anim.always( function() { + style.overflow = opts.overflow[ 0 ]; + style.overflowX = opts.overflow[ 1 ]; + style.overflowY = opts.overflow[ 2 ]; + } ); + } + + // Implement show/hide animations + propTween = false; + for ( prop in orig ) { + + // General show/hide setup for this element animation + if ( !propTween ) { + if ( dataShow ) { + if ( "hidden" in dataShow ) { + hidden = dataShow.hidden; + } + } else { + dataShow = dataPriv.access( elem, "fxshow", { display: restoreDisplay } ); + } + + // Store hidden/visible for toggle so `.stop().toggle()` "reverses" + if ( toggle ) { + dataShow.hidden = !hidden; + } + + // Show elements before animating them + if ( hidden ) { + showHide( [ elem ], true ); + } + + /* eslint-disable no-loop-func */ + + anim.done( function() { + + /* eslint-enable no-loop-func */ + + // The final step of a "hide" animation is actually hiding the element + if ( !hidden ) { + showHide( [ elem ] ); + } + dataPriv.remove( elem, "fxshow" ); + for ( prop in orig ) { + jQuery.style( elem, prop, orig[ prop ] ); + } + } ); + } + + // Per-property setup + propTween = createTween( hidden ? dataShow[ prop ] : 0, prop, anim ); + if ( !( prop in dataShow ) ) { + dataShow[ prop ] = propTween.start; + if ( hidden ) { + propTween.end = propTween.start; + propTween.start = 0; + } + } + } +} + +function propFilter( props, specialEasing ) { + var index, name, easing, value, hooks; + + // camelCase, specialEasing and expand cssHook pass + for ( index in props ) { + name = camelCase( index ); + easing = specialEasing[ name ]; + value = props[ index ]; + if ( Array.isArray( value ) ) { + easing = value[ 1 ]; + value = props[ index ] = value[ 0 ]; + } + + if ( index !== name ) { + props[ name ] = value; + delete props[ index ]; + } + + hooks = jQuery.cssHooks[ name ]; + if ( hooks && "expand" in hooks ) { + value = hooks.expand( value ); + delete props[ name ]; + + // Not quite $.extend, this won't overwrite existing keys. + // Reusing 'index' because we have the correct "name" + for ( index in value ) { + if ( !( index in props ) ) { + props[ index ] = value[ index ]; + specialEasing[ index ] = easing; + } + } + } else { + specialEasing[ name ] = easing; + } + } +} + +function Animation( elem, properties, options ) { + var result, + stopped, + index = 0, + length = Animation.prefilters.length, + deferred = jQuery.Deferred().always( function() { + + // Don't match elem in the :animated selector + delete tick.elem; + } ), + tick = function() { + if ( stopped ) { + return false; + } + var currentTime = fxNow || createFxNow(), + remaining = Math.max( 0, animation.startTime + animation.duration - currentTime ), + + // Support: Android 2.3 only + // Archaic crash bug won't allow us to use `1 - ( 0.5 || 0 )` (#12497) + temp = remaining / animation.duration || 0, + percent = 1 - temp, + index = 0, + length = animation.tweens.length; + + for ( ; index < length; index++ ) { + animation.tweens[ index ].run( percent ); + } + + deferred.notifyWith( elem, [ animation, percent, remaining ] ); + + // If there's more to do, yield + if ( percent < 1 && length ) { + return remaining; + } + + // If this was an empty animation, synthesize a final progress notification + if ( !length ) { + deferred.notifyWith( elem, [ animation, 1, 0 ] ); + } + + // Resolve the animation and report its conclusion + deferred.resolveWith( elem, [ animation ] ); + return false; + }, + animation = deferred.promise( { + elem: elem, + props: jQuery.extend( {}, properties ), + opts: jQuery.extend( true, { + specialEasing: {}, + easing: jQuery.easing._default + }, options ), + originalProperties: properties, + originalOptions: options, + startTime: fxNow || createFxNow(), + duration: options.duration, + tweens: [], + createTween: function( prop, end ) { + var tween = jQuery.Tween( elem, animation.opts, prop, end, + animation.opts.specialEasing[ prop ] || animation.opts.easing ); + animation.tweens.push( tween ); + return tween; + }, + stop: function( gotoEnd ) { + var index = 0, + + // If we are going to the end, we want to run all the tweens + // otherwise we skip this part + length = gotoEnd ? animation.tweens.length : 0; + if ( stopped ) { + return this; + } + stopped = true; + for ( ; index < length; index++ ) { + animation.tweens[ index ].run( 1 ); + } + + // Resolve when we played the last frame; otherwise, reject + if ( gotoEnd ) { + deferred.notifyWith( elem, [ animation, 1, 0 ] ); + deferred.resolveWith( elem, [ animation, gotoEnd ] ); + } else { + deferred.rejectWith( elem, [ animation, gotoEnd ] ); + } + return this; + } + } ), + props = animation.props; + + propFilter( props, animation.opts.specialEasing ); + + for ( ; index < length; index++ ) { + result = Animation.prefilters[ index ].call( animation, elem, props, animation.opts ); + if ( result ) { + if ( isFunction( result.stop ) ) { + jQuery._queueHooks( animation.elem, animation.opts.queue ).stop = + result.stop.bind( result ); + } + return result; + } + } + + jQuery.map( props, createTween, animation ); + + if ( isFunction( animation.opts.start ) ) { + animation.opts.start.call( elem, animation ); + } + + // Attach callbacks from options + animation + .progress( animation.opts.progress ) + .done( animation.opts.done, animation.opts.complete ) + .fail( animation.opts.fail ) + .always( animation.opts.always ); + + jQuery.fx.timer( + jQuery.extend( tick, { + elem: elem, + anim: animation, + queue: animation.opts.queue + } ) + ); + + return animation; +} + +jQuery.Animation = jQuery.extend( Animation, { + + tweeners: { + "*": [ function( prop, value ) { + var tween = this.createTween( prop, value ); + adjustCSS( tween.elem, prop, rcssNum.exec( value ), tween ); + return tween; + } ] + }, + + tweener: function( props, callback ) { + if ( isFunction( props ) ) { + callback = props; + props = [ "*" ]; + } else { + props = props.match( rnothtmlwhite ); + } + + var prop, + index = 0, + length = props.length; + + for ( ; index < length; index++ ) { + prop = props[ index ]; + Animation.tweeners[ prop ] = Animation.tweeners[ prop ] || []; + Animation.tweeners[ prop ].unshift( callback ); + } + }, + + prefilters: [ defaultPrefilter ], + + prefilter: function( callback, prepend ) { + if ( prepend ) { + Animation.prefilters.unshift( callback ); + } else { + Animation.prefilters.push( callback ); + } + } +} ); + +jQuery.speed = function( speed, easing, fn ) { + var opt = speed && typeof speed === "object" ? jQuery.extend( {}, speed ) : { + complete: fn || !fn && easing || + isFunction( speed ) && speed, + duration: speed, + easing: fn && easing || easing && !isFunction( easing ) && easing + }; + + // Go to the end state if fx are off + if ( jQuery.fx.off ) { + opt.duration = 0; + + } else { + if ( typeof opt.duration !== "number" ) { + if ( opt.duration in jQuery.fx.speeds ) { + opt.duration = jQuery.fx.speeds[ opt.duration ]; + + } else { + opt.duration = jQuery.fx.speeds._default; + } + } + } + + // Normalize opt.queue - true/undefined/null -> "fx" + if ( opt.queue == null || opt.queue === true ) { + opt.queue = "fx"; + } + + // Queueing + opt.old = opt.complete; + + opt.complete = function() { + if ( isFunction( opt.old ) ) { + opt.old.call( this ); + } + + if ( opt.queue ) { + jQuery.dequeue( this, opt.queue ); + } + }; + + return opt; +}; + +jQuery.fn.extend( { + fadeTo: function( speed, to, easing, callback ) { + + // Show any hidden elements after setting opacity to 0 + return this.filter( isHiddenWithinTree ).css( "opacity", 0 ).show() + + // Animate to the value specified + .end().animate( { opacity: to }, speed, easing, callback ); + }, + animate: function( prop, speed, easing, callback ) { + var empty = jQuery.isEmptyObject( prop ), + optall = jQuery.speed( speed, easing, callback ), + doAnimation = function() { + + // Operate on a copy of prop so per-property easing won't be lost + var anim = Animation( this, jQuery.extend( {}, prop ), optall ); + + // Empty animations, or finishing resolves immediately + if ( empty || dataPriv.get( this, "finish" ) ) { + anim.stop( true ); + } + }; + doAnimation.finish = doAnimation; + + return empty || optall.queue === false ? + this.each( doAnimation ) : + this.queue( optall.queue, doAnimation ); + }, + stop: function( type, clearQueue, gotoEnd ) { + var stopQueue = function( hooks ) { + var stop = hooks.stop; + delete hooks.stop; + stop( gotoEnd ); + }; + + if ( typeof type !== "string" ) { + gotoEnd = clearQueue; + clearQueue = type; + type = undefined; + } + if ( clearQueue ) { + this.queue( type || "fx", [] ); + } + + return this.each( function() { + var dequeue = true, + index = type != null && type + "queueHooks", + timers = jQuery.timers, + data = dataPriv.get( this ); + + if ( index ) { + if ( data[ index ] && data[ index ].stop ) { + stopQueue( data[ index ] ); + } + } else { + for ( index in data ) { + if ( data[ index ] && data[ index ].stop && rrun.test( index ) ) { + stopQueue( data[ index ] ); + } + } + } + + for ( index = timers.length; index--; ) { + if ( timers[ index ].elem === this && + ( type == null || timers[ index ].queue === type ) ) { + + timers[ index ].anim.stop( gotoEnd ); + dequeue = false; + timers.splice( index, 1 ); + } + } + + // Start the next in the queue if the last step wasn't forced. + // Timers currently will call their complete callbacks, which + // will dequeue but only if they were gotoEnd. + if ( dequeue || !gotoEnd ) { + jQuery.dequeue( this, type ); + } + } ); + }, + finish: function( type ) { + if ( type !== false ) { + type = type || "fx"; + } + return this.each( function() { + var index, + data = dataPriv.get( this ), + queue = data[ type + "queue" ], + hooks = data[ type + "queueHooks" ], + timers = jQuery.timers, + length = queue ? queue.length : 0; + + // Enable finishing flag on private data + data.finish = true; + + // Empty the queue first + jQuery.queue( this, type, [] ); + + if ( hooks && hooks.stop ) { + hooks.stop.call( this, true ); + } + + // Look for any active animations, and finish them + for ( index = timers.length; index--; ) { + if ( timers[ index ].elem === this && timers[ index ].queue === type ) { + timers[ index ].anim.stop( true ); + timers.splice( index, 1 ); + } + } + + // Look for any animations in the old queue and finish them + for ( index = 0; index < length; index++ ) { + if ( queue[ index ] && queue[ index ].finish ) { + queue[ index ].finish.call( this ); + } + } + + // Turn off finishing flag + delete data.finish; + } ); + } +} ); + +jQuery.each( [ "toggle", "show", "hide" ], function( _i, name ) { + var cssFn = jQuery.fn[ name ]; + jQuery.fn[ name ] = function( speed, easing, callback ) { + return speed == null || typeof speed === "boolean" ? + cssFn.apply( this, arguments ) : + this.animate( genFx( name, true ), speed, easing, callback ); + }; +} ); + +// Generate shortcuts for custom animations +jQuery.each( { + slideDown: genFx( "show" ), + slideUp: genFx( "hide" ), + slideToggle: genFx( "toggle" ), + fadeIn: { opacity: "show" }, + fadeOut: { opacity: "hide" }, + fadeToggle: { opacity: "toggle" } +}, function( name, props ) { + jQuery.fn[ name ] = function( speed, easing, callback ) { + return this.animate( props, speed, easing, callback ); + }; +} ); + +jQuery.timers = []; +jQuery.fx.tick = function() { + var timer, + i = 0, + timers = jQuery.timers; + + fxNow = Date.now(); + + for ( ; i < timers.length; i++ ) { + timer = timers[ i ]; + + // Run the timer and safely remove it when done (allowing for external removal) + if ( !timer() && timers[ i ] === timer ) { + timers.splice( i--, 1 ); + } + } + + if ( !timers.length ) { + jQuery.fx.stop(); + } + fxNow = undefined; +}; + +jQuery.fx.timer = function( timer ) { + jQuery.timers.push( timer ); + jQuery.fx.start(); +}; + +jQuery.fx.interval = 13; +jQuery.fx.start = function() { + if ( inProgress ) { + return; + } + + inProgress = true; + schedule(); +}; + +jQuery.fx.stop = function() { + inProgress = null; +}; + +jQuery.fx.speeds = { + slow: 600, + fast: 200, + + // Default speed + _default: 400 +}; + + +// Based off of the plugin by Clint Helfers, with permission. +// https://web.archive.org/web/20100324014747/http://blindsignals.com/index.php/2009/07/jquery-delay/ +jQuery.fn.delay = function( time, type ) { + time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time; + type = type || "fx"; + + return this.queue( type, function( next, hooks ) { + var timeout = window.setTimeout( next, time ); + hooks.stop = function() { + window.clearTimeout( timeout ); + }; + } ); +}; + + +( function() { + var input = document.createElement( "input" ), + select = document.createElement( "select" ), + opt = select.appendChild( document.createElement( "option" ) ); + + input.type = "checkbox"; + + // Support: Android <=4.3 only + // Default value for a checkbox should be "on" + support.checkOn = input.value !== ""; + + // Support: IE <=11 only + // Must access selectedIndex to make default options select + support.optSelected = opt.selected; + + // Support: IE <=11 only + // An input loses its value after becoming a radio + input = document.createElement( "input" ); + input.value = "t"; + input.type = "radio"; + support.radioValue = input.value === "t"; +} )(); + + +var boolHook, + attrHandle = jQuery.expr.attrHandle; + +jQuery.fn.extend( { + attr: function( name, value ) { + return access( this, jQuery.attr, name, value, arguments.length > 1 ); + }, + + removeAttr: function( name ) { + return this.each( function() { + jQuery.removeAttr( this, name ); + } ); + } +} ); + +jQuery.extend( { + attr: function( elem, name, value ) { + var ret, hooks, + nType = elem.nodeType; + + // Don't get/set attributes on text, comment and attribute nodes + if ( nType === 3 || nType === 8 || nType === 2 ) { + return; + } + + // Fallback to prop when attributes are not supported + if ( typeof elem.getAttribute === "undefined" ) { + return jQuery.prop( elem, name, value ); + } + + // Attribute hooks are determined by the lowercase version + // Grab necessary hook if one is defined + if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) { + hooks = jQuery.attrHooks[ name.toLowerCase() ] || + ( jQuery.expr.match.bool.test( name ) ? boolHook : undefined ); + } + + if ( value !== undefined ) { + if ( value === null ) { + jQuery.removeAttr( elem, name ); + return; + } + + if ( hooks && "set" in hooks && + ( ret = hooks.set( elem, value, name ) ) !== undefined ) { + return ret; + } + + elem.setAttribute( name, value + "" ); + return value; + } + + if ( hooks && "get" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) { + return ret; + } + + ret = jQuery.find.attr( elem, name ); + + // Non-existent attributes return null, we normalize to undefined + return ret == null ? undefined : ret; + }, + + attrHooks: { + type: { + set: function( elem, value ) { + if ( !support.radioValue && value === "radio" && + nodeName( elem, "input" ) ) { + var val = elem.value; + elem.setAttribute( "type", value ); + if ( val ) { + elem.value = val; + } + return value; + } + } + } + }, + + removeAttr: function( elem, value ) { + var name, + i = 0, + + // Attribute names can contain non-HTML whitespace characters + // https://html.spec.whatwg.org/multipage/syntax.html#attributes-2 + attrNames = value && value.match( rnothtmlwhite ); + + if ( attrNames && elem.nodeType === 1 ) { + while ( ( name = attrNames[ i++ ] ) ) { + elem.removeAttribute( name ); + } + } + } +} ); + +// Hooks for boolean attributes +boolHook = { + set: function( elem, value, name ) { + if ( value === false ) { + + // Remove boolean attributes when set to false + jQuery.removeAttr( elem, name ); + } else { + elem.setAttribute( name, name ); + } + return name; + } +}; + +jQuery.each( jQuery.expr.match.bool.source.match( /\w+/g ), function( _i, name ) { + var getter = attrHandle[ name ] || jQuery.find.attr; + + attrHandle[ name ] = function( elem, name, isXML ) { + var ret, handle, + lowercaseName = name.toLowerCase(); + + if ( !isXML ) { + + // Avoid an infinite loop by temporarily removing this function from the getter + handle = attrHandle[ lowercaseName ]; + attrHandle[ lowercaseName ] = ret; + ret = getter( elem, name, isXML ) != null ? + lowercaseName : + null; + attrHandle[ lowercaseName ] = handle; + } + return ret; + }; +} ); + + + + +var rfocusable = /^(?:input|select|textarea|button)$/i, + rclickable = /^(?:a|area)$/i; + +jQuery.fn.extend( { + prop: function( name, value ) { + return access( this, jQuery.prop, name, value, arguments.length > 1 ); + }, + + removeProp: function( name ) { + return this.each( function() { + delete this[ jQuery.propFix[ name ] || name ]; + } ); + } +} ); + +jQuery.extend( { + prop: function( elem, name, value ) { + var ret, hooks, + nType = elem.nodeType; + + // Don't get/set properties on text, comment and attribute nodes + if ( nType === 3 || nType === 8 || nType === 2 ) { + return; + } + + if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) { + + // Fix name and attach hooks + name = jQuery.propFix[ name ] || name; + hooks = jQuery.propHooks[ name ]; + } + + if ( value !== undefined ) { + if ( hooks && "set" in hooks && + ( ret = hooks.set( elem, value, name ) ) !== undefined ) { + return ret; + } + + return ( elem[ name ] = value ); + } + + if ( hooks && "get" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) { + return ret; + } + + return elem[ name ]; + }, + + propHooks: { + tabIndex: { + get: function( elem ) { + + // Support: IE <=9 - 11 only + // elem.tabIndex doesn't always return the + // correct value when it hasn't been explicitly set + // https://web.archive.org/web/20141116233347/http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/ + // Use proper attribute retrieval(#12072) + var tabindex = jQuery.find.attr( elem, "tabindex" ); + + if ( tabindex ) { + return parseInt( tabindex, 10 ); + } + + if ( + rfocusable.test( elem.nodeName ) || + rclickable.test( elem.nodeName ) && + elem.href + ) { + return 0; + } + + return -1; + } + } + }, + + propFix: { + "for": "htmlFor", + "class": "className" + } +} ); + +// Support: IE <=11 only +// Accessing the selectedIndex property +// forces the browser to respect setting selected +// on the option +// The getter ensures a default option is selected +// when in an optgroup +// eslint rule "no-unused-expressions" is disabled for this code +// since it considers such accessions noop +if ( !support.optSelected ) { + jQuery.propHooks.selected = { + get: function( elem ) { + + /* eslint no-unused-expressions: "off" */ + + var parent = elem.parentNode; + if ( parent && parent.parentNode ) { + parent.parentNode.selectedIndex; + } + return null; + }, + set: function( elem ) { + + /* eslint no-unused-expressions: "off" */ + + var parent = elem.parentNode; + if ( parent ) { + parent.selectedIndex; + + if ( parent.parentNode ) { + parent.parentNode.selectedIndex; + } + } + } + }; +} + +jQuery.each( [ + "tabIndex", + "readOnly", + "maxLength", + "cellSpacing", + "cellPadding", + "rowSpan", + "colSpan", + "useMap", + "frameBorder", + "contentEditable" +], function() { + jQuery.propFix[ this.toLowerCase() ] = this; +} ); + + + + + // Strip and collapse whitespace according to HTML spec + // https://infra.spec.whatwg.org/#strip-and-collapse-ascii-whitespace + function stripAndCollapse( value ) { + var tokens = value.match( rnothtmlwhite ) || []; + return tokens.join( " " ); + } + + +function getClass( elem ) { + return elem.getAttribute && elem.getAttribute( "class" ) || ""; +} + +function classesToArray( value ) { + if ( Array.isArray( value ) ) { + return value; + } + if ( typeof value === "string" ) { + return value.match( rnothtmlwhite ) || []; + } + return []; +} + +jQuery.fn.extend( { + addClass: function( value ) { + var classes, elem, cur, curValue, clazz, j, finalValue, + i = 0; + + if ( isFunction( value ) ) { + return this.each( function( j ) { + jQuery( this ).addClass( value.call( this, j, getClass( this ) ) ); + } ); + } + + classes = classesToArray( value ); + + if ( classes.length ) { + while ( ( elem = this[ i++ ] ) ) { + curValue = getClass( elem ); + cur = elem.nodeType === 1 && ( " " + stripAndCollapse( curValue ) + " " ); + + if ( cur ) { + j = 0; + while ( ( clazz = classes[ j++ ] ) ) { + if ( cur.indexOf( " " + clazz + " " ) < 0 ) { + cur += clazz + " "; + } + } + + // Only assign if different to avoid unneeded rendering. + finalValue = stripAndCollapse( cur ); + if ( curValue !== finalValue ) { + elem.setAttribute( "class", finalValue ); + } + } + } + } + + return this; + }, + + removeClass: function( value ) { + var classes, elem, cur, curValue, clazz, j, finalValue, + i = 0; + + if ( isFunction( value ) ) { + return this.each( function( j ) { + jQuery( this ).removeClass( value.call( this, j, getClass( this ) ) ); + } ); + } + + if ( !arguments.length ) { + return this.attr( "class", "" ); + } + + classes = classesToArray( value ); + + if ( classes.length ) { + while ( ( elem = this[ i++ ] ) ) { + curValue = getClass( elem ); + + // This expression is here for better compressibility (see addClass) + cur = elem.nodeType === 1 && ( " " + stripAndCollapse( curValue ) + " " ); + + if ( cur ) { + j = 0; + while ( ( clazz = classes[ j++ ] ) ) { + + // Remove *all* instances + while ( cur.indexOf( " " + clazz + " " ) > -1 ) { + cur = cur.replace( " " + clazz + " ", " " ); + } + } + + // Only assign if different to avoid unneeded rendering. + finalValue = stripAndCollapse( cur ); + if ( curValue !== finalValue ) { + elem.setAttribute( "class", finalValue ); + } + } + } + } + + return this; + }, + + toggleClass: function( value, stateVal ) { + var type = typeof value, + isValidValue = type === "string" || Array.isArray( value ); + + if ( typeof stateVal === "boolean" && isValidValue ) { + return stateVal ? this.addClass( value ) : this.removeClass( value ); + } + + if ( isFunction( value ) ) { + return this.each( function( i ) { + jQuery( this ).toggleClass( + value.call( this, i, getClass( this ), stateVal ), + stateVal + ); + } ); + } + + return this.each( function() { + var className, i, self, classNames; + + if ( isValidValue ) { + + // Toggle individual class names + i = 0; + self = jQuery( this ); + classNames = classesToArray( value ); + + while ( ( className = classNames[ i++ ] ) ) { + + // Check each className given, space separated list + if ( self.hasClass( className ) ) { + self.removeClass( className ); + } else { + self.addClass( className ); + } + } + + // Toggle whole class name + } else if ( value === undefined || type === "boolean" ) { + className = getClass( this ); + if ( className ) { + + // Store className if set + dataPriv.set( this, "__className__", className ); + } + + // If the element has a class name or if we're passed `false`, + // then remove the whole classname (if there was one, the above saved it). + // Otherwise bring back whatever was previously saved (if anything), + // falling back to the empty string if nothing was stored. + if ( this.setAttribute ) { + this.setAttribute( "class", + className || value === false ? + "" : + dataPriv.get( this, "__className__" ) || "" + ); + } + } + } ); + }, + + hasClass: function( selector ) { + var className, elem, + i = 0; + + className = " " + selector + " "; + while ( ( elem = this[ i++ ] ) ) { + if ( elem.nodeType === 1 && + ( " " + stripAndCollapse( getClass( elem ) ) + " " ).indexOf( className ) > -1 ) { + return true; + } + } + + return false; + } +} ); + + + + +var rreturn = /\r/g; + +jQuery.fn.extend( { + val: function( value ) { + var hooks, ret, valueIsFunction, + elem = this[ 0 ]; + + if ( !arguments.length ) { + if ( elem ) { + hooks = jQuery.valHooks[ elem.type ] || + jQuery.valHooks[ elem.nodeName.toLowerCase() ]; + + if ( hooks && + "get" in hooks && + ( ret = hooks.get( elem, "value" ) ) !== undefined + ) { + return ret; + } + + ret = elem.value; + + // Handle most common string cases + if ( typeof ret === "string" ) { + return ret.replace( rreturn, "" ); + } + + // Handle cases where value is null/undef or number + return ret == null ? "" : ret; + } + + return; + } + + valueIsFunction = isFunction( value ); + + return this.each( function( i ) { + var val; + + if ( this.nodeType !== 1 ) { + return; + } + + if ( valueIsFunction ) { + val = value.call( this, i, jQuery( this ).val() ); + } else { + val = value; + } + + // Treat null/undefined as ""; convert numbers to string + if ( val == null ) { + val = ""; + + } else if ( typeof val === "number" ) { + val += ""; + + } else if ( Array.isArray( val ) ) { + val = jQuery.map( val, function( value ) { + return value == null ? "" : value + ""; + } ); + } + + hooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ]; + + // If set returns undefined, fall back to normal setting + if ( !hooks || !( "set" in hooks ) || hooks.set( this, val, "value" ) === undefined ) { + this.value = val; + } + } ); + } +} ); + +jQuery.extend( { + valHooks: { + option: { + get: function( elem ) { + + var val = jQuery.find.attr( elem, "value" ); + return val != null ? + val : + + // Support: IE <=10 - 11 only + // option.text throws exceptions (#14686, #14858) + // Strip and collapse whitespace + // https://html.spec.whatwg.org/#strip-and-collapse-whitespace + stripAndCollapse( jQuery.text( elem ) ); + } + }, + select: { + get: function( elem ) { + var value, option, i, + options = elem.options, + index = elem.selectedIndex, + one = elem.type === "select-one", + values = one ? null : [], + max = one ? index + 1 : options.length; + + if ( index < 0 ) { + i = max; + + } else { + i = one ? index : 0; + } + + // Loop through all the selected options + for ( ; i < max; i++ ) { + option = options[ i ]; + + // Support: IE <=9 only + // IE8-9 doesn't update selected after form reset (#2551) + if ( ( option.selected || i === index ) && + + // Don't return options that are disabled or in a disabled optgroup + !option.disabled && + ( !option.parentNode.disabled || + !nodeName( option.parentNode, "optgroup" ) ) ) { + + // Get the specific value for the option + value = jQuery( option ).val(); + + // We don't need an array for one selects + if ( one ) { + return value; + } + + // Multi-Selects return an array + values.push( value ); + } + } + + return values; + }, + + set: function( elem, value ) { + var optionSet, option, + options = elem.options, + values = jQuery.makeArray( value ), + i = options.length; + + while ( i-- ) { + option = options[ i ]; + + /* eslint-disable no-cond-assign */ + + if ( option.selected = + jQuery.inArray( jQuery.valHooks.option.get( option ), values ) > -1 + ) { + optionSet = true; + } + + /* eslint-enable no-cond-assign */ + } + + // Force browsers to behave consistently when non-matching value is set + if ( !optionSet ) { + elem.selectedIndex = -1; + } + return values; + } + } + } +} ); + +// Radios and checkboxes getter/setter +jQuery.each( [ "radio", "checkbox" ], function() { + jQuery.valHooks[ this ] = { + set: function( elem, value ) { + if ( Array.isArray( value ) ) { + return ( elem.checked = jQuery.inArray( jQuery( elem ).val(), value ) > -1 ); + } + } + }; + if ( !support.checkOn ) { + jQuery.valHooks[ this ].get = function( elem ) { + return elem.getAttribute( "value" ) === null ? "on" : elem.value; + }; + } +} ); + + + + +// Return jQuery for attributes-only inclusion + + +support.focusin = "onfocusin" in window; + + +var rfocusMorph = /^(?:focusinfocus|focusoutblur)$/, + stopPropagationCallback = function( e ) { + e.stopPropagation(); + }; + +jQuery.extend( jQuery.event, { + + trigger: function( event, data, elem, onlyHandlers ) { + + var i, cur, tmp, bubbleType, ontype, handle, special, lastElement, + eventPath = [ elem || document ], + type = hasOwn.call( event, "type" ) ? event.type : event, + namespaces = hasOwn.call( event, "namespace" ) ? event.namespace.split( "." ) : []; + + cur = lastElement = tmp = elem = elem || document; + + // Don't do events on text and comment nodes + if ( elem.nodeType === 3 || elem.nodeType === 8 ) { + return; + } + + // focus/blur morphs to focusin/out; ensure we're not firing them right now + if ( rfocusMorph.test( type + jQuery.event.triggered ) ) { + return; + } + + if ( type.indexOf( "." ) > -1 ) { + + // Namespaced trigger; create a regexp to match event type in handle() + namespaces = type.split( "." ); + type = namespaces.shift(); + namespaces.sort(); + } + ontype = type.indexOf( ":" ) < 0 && "on" + type; + + // Caller can pass in a jQuery.Event object, Object, or just an event type string + event = event[ jQuery.expando ] ? + event : + new jQuery.Event( type, typeof event === "object" && event ); + + // Trigger bitmask: & 1 for native handlers; & 2 for jQuery (always true) + event.isTrigger = onlyHandlers ? 2 : 3; + event.namespace = namespaces.join( "." ); + event.rnamespace = event.namespace ? + new RegExp( "(^|\\.)" + namespaces.join( "\\.(?:.*\\.|)" ) + "(\\.|$)" ) : + null; + + // Clean up the event in case it is being reused + event.result = undefined; + if ( !event.target ) { + event.target = elem; + } + + // Clone any incoming data and prepend the event, creating the handler arg list + data = data == null ? + [ event ] : + jQuery.makeArray( data, [ event ] ); + + // Allow special events to draw outside the lines + special = jQuery.event.special[ type ] || {}; + if ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) { + return; + } + + // Determine event propagation path in advance, per W3C events spec (#9951) + // Bubble up to document, then to window; watch for a global ownerDocument var (#9724) + if ( !onlyHandlers && !special.noBubble && !isWindow( elem ) ) { + + bubbleType = special.delegateType || type; + if ( !rfocusMorph.test( bubbleType + type ) ) { + cur = cur.parentNode; + } + for ( ; cur; cur = cur.parentNode ) { + eventPath.push( cur ); + tmp = cur; + } + + // Only add window if we got to document (e.g., not plain obj or detached DOM) + if ( tmp === ( elem.ownerDocument || document ) ) { + eventPath.push( tmp.defaultView || tmp.parentWindow || window ); + } + } + + // Fire handlers on the event path + i = 0; + while ( ( cur = eventPath[ i++ ] ) && !event.isPropagationStopped() ) { + lastElement = cur; + event.type = i > 1 ? + bubbleType : + special.bindType || type; + + // jQuery handler + handle = ( + dataPriv.get( cur, "events" ) || Object.create( null ) + )[ event.type ] && + dataPriv.get( cur, "handle" ); + if ( handle ) { + handle.apply( cur, data ); + } + + // Native handler + handle = ontype && cur[ ontype ]; + if ( handle && handle.apply && acceptData( cur ) ) { + event.result = handle.apply( cur, data ); + if ( event.result === false ) { + event.preventDefault(); + } + } + } + event.type = type; + + // If nobody prevented the default action, do it now + if ( !onlyHandlers && !event.isDefaultPrevented() ) { + + if ( ( !special._default || + special._default.apply( eventPath.pop(), data ) === false ) && + acceptData( elem ) ) { + + // Call a native DOM method on the target with the same name as the event. + // Don't do default actions on window, that's where global variables be (#6170) + if ( ontype && isFunction( elem[ type ] ) && !isWindow( elem ) ) { + + // Don't re-trigger an onFOO event when we call its FOO() method + tmp = elem[ ontype ]; + + if ( tmp ) { + elem[ ontype ] = null; + } + + // Prevent re-triggering of the same event, since we already bubbled it above + jQuery.event.triggered = type; + + if ( event.isPropagationStopped() ) { + lastElement.addEventListener( type, stopPropagationCallback ); + } + + elem[ type ](); + + if ( event.isPropagationStopped() ) { + lastElement.removeEventListener( type, stopPropagationCallback ); + } + + jQuery.event.triggered = undefined; + + if ( tmp ) { + elem[ ontype ] = tmp; + } + } + } + } + + return event.result; + }, + + // Piggyback on a donor event to simulate a different one + // Used only for `focus(in | out)` events + simulate: function( type, elem, event ) { + var e = jQuery.extend( + new jQuery.Event(), + event, + { + type: type, + isSimulated: true + } + ); + + jQuery.event.trigger( e, null, elem ); + } + +} ); + +jQuery.fn.extend( { + + trigger: function( type, data ) { + return this.each( function() { + jQuery.event.trigger( type, data, this ); + } ); + }, + triggerHandler: function( type, data ) { + var elem = this[ 0 ]; + if ( elem ) { + return jQuery.event.trigger( type, data, elem, true ); + } + } +} ); + + +// Support: Firefox <=44 +// Firefox doesn't have focus(in | out) events +// Related ticket - https://bugzilla.mozilla.org/show_bug.cgi?id=687787 +// +// Support: Chrome <=48 - 49, Safari <=9.0 - 9.1 +// focus(in | out) events fire after focus & blur events, +// which is spec violation - http://www.w3.org/TR/DOM-Level-3-Events/#events-focusevent-event-order +// Related ticket - https://bugs.chromium.org/p/chromium/issues/detail?id=449857 +if ( !support.focusin ) { + jQuery.each( { focus: "focusin", blur: "focusout" }, function( orig, fix ) { + + // Attach a single capturing handler on the document while someone wants focusin/focusout + var handler = function( event ) { + jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ) ); + }; + + jQuery.event.special[ fix ] = { + setup: function() { + + // Handle: regular nodes (via `this.ownerDocument`), window + // (via `this.document`) & document (via `this`). + var doc = this.ownerDocument || this.document || this, + attaches = dataPriv.access( doc, fix ); + + if ( !attaches ) { + doc.addEventListener( orig, handler, true ); + } + dataPriv.access( doc, fix, ( attaches || 0 ) + 1 ); + }, + teardown: function() { + var doc = this.ownerDocument || this.document || this, + attaches = dataPriv.access( doc, fix ) - 1; + + if ( !attaches ) { + doc.removeEventListener( orig, handler, true ); + dataPriv.remove( doc, fix ); + + } else { + dataPriv.access( doc, fix, attaches ); + } + } + }; + } ); +} +var location = window.location; + +var nonce = { guid: Date.now() }; + +var rquery = ( /\?/ ); + + + +// Cross-browser xml parsing +jQuery.parseXML = function( data ) { + var xml; + if ( !data || typeof data !== "string" ) { + return null; + } + + // Support: IE 9 - 11 only + // IE throws on parseFromString with invalid input. + try { + xml = ( new window.DOMParser() ).parseFromString( data, "text/xml" ); + } catch ( e ) { + xml = undefined; + } + + if ( !xml || xml.getElementsByTagName( "parsererror" ).length ) { + jQuery.error( "Invalid XML: " + data ); + } + return xml; +}; + + +var + rbracket = /\[\]$/, + rCRLF = /\r?\n/g, + rsubmitterTypes = /^(?:submit|button|image|reset|file)$/i, + rsubmittable = /^(?:input|select|textarea|keygen)/i; + +function buildParams( prefix, obj, traditional, add ) { + var name; + + if ( Array.isArray( obj ) ) { + + // Serialize array item. + jQuery.each( obj, function( i, v ) { + if ( traditional || rbracket.test( prefix ) ) { + + // Treat each array item as a scalar. + add( prefix, v ); + + } else { + + // Item is non-scalar (array or object), encode its numeric index. + buildParams( + prefix + "[" + ( typeof v === "object" && v != null ? i : "" ) + "]", + v, + traditional, + add + ); + } + } ); + + } else if ( !traditional && toType( obj ) === "object" ) { + + // Serialize object item. + for ( name in obj ) { + buildParams( prefix + "[" + name + "]", obj[ name ], traditional, add ); + } + + } else { + + // Serialize scalar item. + add( prefix, obj ); + } +} + +// Serialize an array of form elements or a set of +// key/values into a query string +jQuery.param = function( a, traditional ) { + var prefix, + s = [], + add = function( key, valueOrFunction ) { + + // If value is a function, invoke it and use its return value + var value = isFunction( valueOrFunction ) ? + valueOrFunction() : + valueOrFunction; + + s[ s.length ] = encodeURIComponent( key ) + "=" + + encodeURIComponent( value == null ? "" : value ); + }; + + if ( a == null ) { + return ""; + } + + // If an array was passed in, assume that it is an array of form elements. + if ( Array.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) { + + // Serialize the form elements + jQuery.each( a, function() { + add( this.name, this.value ); + } ); + + } else { + + // If traditional, encode the "old" way (the way 1.3.2 or older + // did it), otherwise encode params recursively. + for ( prefix in a ) { + buildParams( prefix, a[ prefix ], traditional, add ); + } + } + + // Return the resulting serialization + return s.join( "&" ); +}; + +jQuery.fn.extend( { + serialize: function() { + return jQuery.param( this.serializeArray() ); + }, + serializeArray: function() { + return this.map( function() { + + // Can add propHook for "elements" to filter or add form elements + var elements = jQuery.prop( this, "elements" ); + return elements ? jQuery.makeArray( elements ) : this; + } ) + .filter( function() { + var type = this.type; + + // Use .is( ":disabled" ) so that fieldset[disabled] works + return this.name && !jQuery( this ).is( ":disabled" ) && + rsubmittable.test( this.nodeName ) && !rsubmitterTypes.test( type ) && + ( this.checked || !rcheckableType.test( type ) ); + } ) + .map( function( _i, elem ) { + var val = jQuery( this ).val(); + + if ( val == null ) { + return null; + } + + if ( Array.isArray( val ) ) { + return jQuery.map( val, function( val ) { + return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) }; + } ); + } + + return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) }; + } ).get(); + } +} ); + + +var + r20 = /%20/g, + rhash = /#.*$/, + rantiCache = /([?&])_=[^&]*/, + rheaders = /^(.*?):[ \t]*([^\r\n]*)$/mg, + + // #7653, #8125, #8152: local protocol detection + rlocalProtocol = /^(?:about|app|app-storage|.+-extension|file|res|widget):$/, + rnoContent = /^(?:GET|HEAD)$/, + rprotocol = /^\/\//, + + /* Prefilters + * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example) + * 2) These are called: + * - BEFORE asking for a transport + * - AFTER param serialization (s.data is a string if s.processData is true) + * 3) key is the dataType + * 4) the catchall symbol "*" can be used + * 5) execution will start with transport dataType and THEN continue down to "*" if needed + */ + prefilters = {}, + + /* Transports bindings + * 1) key is the dataType + * 2) the catchall symbol "*" can be used + * 3) selection will start with transport dataType and THEN go to "*" if needed + */ + transports = {}, + + // Avoid comment-prolog char sequence (#10098); must appease lint and evade compression + allTypes = "*/".concat( "*" ), + + // Anchor tag for parsing the document origin + originAnchor = document.createElement( "a" ); + originAnchor.href = location.href; + +// Base "constructor" for jQuery.ajaxPrefilter and jQuery.ajaxTransport +function addToPrefiltersOrTransports( structure ) { + + // dataTypeExpression is optional and defaults to "*" + return function( dataTypeExpression, func ) { + + if ( typeof dataTypeExpression !== "string" ) { + func = dataTypeExpression; + dataTypeExpression = "*"; + } + + var dataType, + i = 0, + dataTypes = dataTypeExpression.toLowerCase().match( rnothtmlwhite ) || []; + + if ( isFunction( func ) ) { + + // For each dataType in the dataTypeExpression + while ( ( dataType = dataTypes[ i++ ] ) ) { + + // Prepend if requested + if ( dataType[ 0 ] === "+" ) { + dataType = dataType.slice( 1 ) || "*"; + ( structure[ dataType ] = structure[ dataType ] || [] ).unshift( func ); + + // Otherwise append + } else { + ( structure[ dataType ] = structure[ dataType ] || [] ).push( func ); + } + } + } + }; +} + +// Base inspection function for prefilters and transports +function inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR ) { + + var inspected = {}, + seekingTransport = ( structure === transports ); + + function inspect( dataType ) { + var selected; + inspected[ dataType ] = true; + jQuery.each( structure[ dataType ] || [], function( _, prefilterOrFactory ) { + var dataTypeOrTransport = prefilterOrFactory( options, originalOptions, jqXHR ); + if ( typeof dataTypeOrTransport === "string" && + !seekingTransport && !inspected[ dataTypeOrTransport ] ) { + + options.dataTypes.unshift( dataTypeOrTransport ); + inspect( dataTypeOrTransport ); + return false; + } else if ( seekingTransport ) { + return !( selected = dataTypeOrTransport ); + } + } ); + return selected; + } + + return inspect( options.dataTypes[ 0 ] ) || !inspected[ "*" ] && inspect( "*" ); +} + +// A special extend for ajax options +// that takes "flat" options (not to be deep extended) +// Fixes #9887 +function ajaxExtend( target, src ) { + var key, deep, + flatOptions = jQuery.ajaxSettings.flatOptions || {}; + + for ( key in src ) { + if ( src[ key ] !== undefined ) { + ( flatOptions[ key ] ? target : ( deep || ( deep = {} ) ) )[ key ] = src[ key ]; + } + } + if ( deep ) { + jQuery.extend( true, target, deep ); + } + + return target; +} + +/* Handles responses to an ajax request: + * - finds the right dataType (mediates between content-type and expected dataType) + * - returns the corresponding response + */ +function ajaxHandleResponses( s, jqXHR, responses ) { + + var ct, type, finalDataType, firstDataType, + contents = s.contents, + dataTypes = s.dataTypes; + + // Remove auto dataType and get content-type in the process + while ( dataTypes[ 0 ] === "*" ) { + dataTypes.shift(); + if ( ct === undefined ) { + ct = s.mimeType || jqXHR.getResponseHeader( "Content-Type" ); + } + } + + // Check if we're dealing with a known content-type + if ( ct ) { + for ( type in contents ) { + if ( contents[ type ] && contents[ type ].test( ct ) ) { + dataTypes.unshift( type ); + break; + } + } + } + + // Check to see if we have a response for the expected dataType + if ( dataTypes[ 0 ] in responses ) { + finalDataType = dataTypes[ 0 ]; + } else { + + // Try convertible dataTypes + for ( type in responses ) { + if ( !dataTypes[ 0 ] || s.converters[ type + " " + dataTypes[ 0 ] ] ) { + finalDataType = type; + break; + } + if ( !firstDataType ) { + firstDataType = type; + } + } + + // Or just use first one + finalDataType = finalDataType || firstDataType; + } + + // If we found a dataType + // We add the dataType to the list if needed + // and return the corresponding response + if ( finalDataType ) { + if ( finalDataType !== dataTypes[ 0 ] ) { + dataTypes.unshift( finalDataType ); + } + return responses[ finalDataType ]; + } +} + +/* Chain conversions given the request and the original response + * Also sets the responseXXX fields on the jqXHR instance + */ +function ajaxConvert( s, response, jqXHR, isSuccess ) { + var conv2, current, conv, tmp, prev, + converters = {}, + + // Work with a copy of dataTypes in case we need to modify it for conversion + dataTypes = s.dataTypes.slice(); + + // Create converters map with lowercased keys + if ( dataTypes[ 1 ] ) { + for ( conv in s.converters ) { + converters[ conv.toLowerCase() ] = s.converters[ conv ]; + } + } + + current = dataTypes.shift(); + + // Convert to each sequential dataType + while ( current ) { + + if ( s.responseFields[ current ] ) { + jqXHR[ s.responseFields[ current ] ] = response; + } + + // Apply the dataFilter if provided + if ( !prev && isSuccess && s.dataFilter ) { + response = s.dataFilter( response, s.dataType ); + } + + prev = current; + current = dataTypes.shift(); + + if ( current ) { + + // There's only work to do if current dataType is non-auto + if ( current === "*" ) { + + current = prev; + + // Convert response if prev dataType is non-auto and differs from current + } else if ( prev !== "*" && prev !== current ) { + + // Seek a direct converter + conv = converters[ prev + " " + current ] || converters[ "* " + current ]; + + // If none found, seek a pair + if ( !conv ) { + for ( conv2 in converters ) { + + // If conv2 outputs current + tmp = conv2.split( " " ); + if ( tmp[ 1 ] === current ) { + + // If prev can be converted to accepted input + conv = converters[ prev + " " + tmp[ 0 ] ] || + converters[ "* " + tmp[ 0 ] ]; + if ( conv ) { + + // Condense equivalence converters + if ( conv === true ) { + conv = converters[ conv2 ]; + + // Otherwise, insert the intermediate dataType + } else if ( converters[ conv2 ] !== true ) { + current = tmp[ 0 ]; + dataTypes.unshift( tmp[ 1 ] ); + } + break; + } + } + } + } + + // Apply converter (if not an equivalence) + if ( conv !== true ) { + + // Unless errors are allowed to bubble, catch and return them + if ( conv && s.throws ) { + response = conv( response ); + } else { + try { + response = conv( response ); + } catch ( e ) { + return { + state: "parsererror", + error: conv ? e : "No conversion from " + prev + " to " + current + }; + } + } + } + } + } + } + + return { state: "success", data: response }; +} + +jQuery.extend( { + + // Counter for holding the number of active queries + active: 0, + + // Last-Modified header cache for next request + lastModified: {}, + etag: {}, + + ajaxSettings: { + url: location.href, + type: "GET", + isLocal: rlocalProtocol.test( location.protocol ), + global: true, + processData: true, + async: true, + contentType: "application/x-www-form-urlencoded; charset=UTF-8", + + /* + timeout: 0, + data: null, + dataType: null, + username: null, + password: null, + cache: null, + throws: false, + traditional: false, + headers: {}, + */ + + accepts: { + "*": allTypes, + text: "text/plain", + html: "text/html", + xml: "application/xml, text/xml", + json: "application/json, text/javascript" + }, + + contents: { + xml: /\bxml\b/, + html: /\bhtml/, + json: /\bjson\b/ + }, + + responseFields: { + xml: "responseXML", + text: "responseText", + json: "responseJSON" + }, + + // Data converters + // Keys separate source (or catchall "*") and destination types with a single space + converters: { + + // Convert anything to text + "* text": String, + + // Text to html (true = no transformation) + "text html": true, + + // Evaluate text as a json expression + "text json": JSON.parse, + + // Parse text as xml + "text xml": jQuery.parseXML + }, + + // For options that shouldn't be deep extended: + // you can add your own custom options here if + // and when you create one that shouldn't be + // deep extended (see ajaxExtend) + flatOptions: { + url: true, + context: true + } + }, + + // Creates a full fledged settings object into target + // with both ajaxSettings and settings fields. + // If target is omitted, writes into ajaxSettings. + ajaxSetup: function( target, settings ) { + return settings ? + + // Building a settings object + ajaxExtend( ajaxExtend( target, jQuery.ajaxSettings ), settings ) : + + // Extending ajaxSettings + ajaxExtend( jQuery.ajaxSettings, target ); + }, + + ajaxPrefilter: addToPrefiltersOrTransports( prefilters ), + ajaxTransport: addToPrefiltersOrTransports( transports ), + + // Main method + ajax: function( url, options ) { + + // If url is an object, simulate pre-1.5 signature + if ( typeof url === "object" ) { + options = url; + url = undefined; + } + + // Force options to be an object + options = options || {}; + + var transport, + + // URL without anti-cache param + cacheURL, + + // Response headers + responseHeadersString, + responseHeaders, + + // timeout handle + timeoutTimer, + + // Url cleanup var + urlAnchor, + + // Request state (becomes false upon send and true upon completion) + completed, + + // To know if global events are to be dispatched + fireGlobals, + + // Loop variable + i, + + // uncached part of the url + uncached, + + // Create the final options object + s = jQuery.ajaxSetup( {}, options ), + + // Callbacks context + callbackContext = s.context || s, + + // Context for global events is callbackContext if it is a DOM node or jQuery collection + globalEventContext = s.context && + ( callbackContext.nodeType || callbackContext.jquery ) ? + jQuery( callbackContext ) : + jQuery.event, + + // Deferreds + deferred = jQuery.Deferred(), + completeDeferred = jQuery.Callbacks( "once memory" ), + + // Status-dependent callbacks + statusCode = s.statusCode || {}, + + // Headers (they are sent all at once) + requestHeaders = {}, + requestHeadersNames = {}, + + // Default abort message + strAbort = "canceled", + + // Fake xhr + jqXHR = { + readyState: 0, + + // Builds headers hashtable if needed + getResponseHeader: function( key ) { + var match; + if ( completed ) { + if ( !responseHeaders ) { + responseHeaders = {}; + while ( ( match = rheaders.exec( responseHeadersString ) ) ) { + responseHeaders[ match[ 1 ].toLowerCase() + " " ] = + ( responseHeaders[ match[ 1 ].toLowerCase() + " " ] || [] ) + .concat( match[ 2 ] ); + } + } + match = responseHeaders[ key.toLowerCase() + " " ]; + } + return match == null ? null : match.join( ", " ); + }, + + // Raw string + getAllResponseHeaders: function() { + return completed ? responseHeadersString : null; + }, + + // Caches the header + setRequestHeader: function( name, value ) { + if ( completed == null ) { + name = requestHeadersNames[ name.toLowerCase() ] = + requestHeadersNames[ name.toLowerCase() ] || name; + requestHeaders[ name ] = value; + } + return this; + }, + + // Overrides response content-type header + overrideMimeType: function( type ) { + if ( completed == null ) { + s.mimeType = type; + } + return this; + }, + + // Status-dependent callbacks + statusCode: function( map ) { + var code; + if ( map ) { + if ( completed ) { + + // Execute the appropriate callbacks + jqXHR.always( map[ jqXHR.status ] ); + } else { + + // Lazy-add the new callbacks in a way that preserves old ones + for ( code in map ) { + statusCode[ code ] = [ statusCode[ code ], map[ code ] ]; + } + } + } + return this; + }, + + // Cancel the request + abort: function( statusText ) { + var finalText = statusText || strAbort; + if ( transport ) { + transport.abort( finalText ); + } + done( 0, finalText ); + return this; + } + }; + + // Attach deferreds + deferred.promise( jqXHR ); + + // Add protocol if not provided (prefilters might expect it) + // Handle falsy url in the settings object (#10093: consistency with old signature) + // We also use the url parameter if available + s.url = ( ( url || s.url || location.href ) + "" ) + .replace( rprotocol, location.protocol + "//" ); + + // Alias method option to type as per ticket #12004 + s.type = options.method || options.type || s.method || s.type; + + // Extract dataTypes list + s.dataTypes = ( s.dataType || "*" ).toLowerCase().match( rnothtmlwhite ) || [ "" ]; + + // A cross-domain request is in order when the origin doesn't match the current origin. + if ( s.crossDomain == null ) { + urlAnchor = document.createElement( "a" ); + + // Support: IE <=8 - 11, Edge 12 - 15 + // IE throws exception on accessing the href property if url is malformed, + // e.g. http://example.com:80x/ + try { + urlAnchor.href = s.url; + + // Support: IE <=8 - 11 only + // Anchor's host property isn't correctly set when s.url is relative + urlAnchor.href = urlAnchor.href; + s.crossDomain = originAnchor.protocol + "//" + originAnchor.host !== + urlAnchor.protocol + "//" + urlAnchor.host; + } catch ( e ) { + + // If there is an error parsing the URL, assume it is crossDomain, + // it can be rejected by the transport if it is invalid + s.crossDomain = true; + } + } + + // Convert data if not already a string + if ( s.data && s.processData && typeof s.data !== "string" ) { + s.data = jQuery.param( s.data, s.traditional ); + } + + // Apply prefilters + inspectPrefiltersOrTransports( prefilters, s, options, jqXHR ); + + // If request was aborted inside a prefilter, stop there + if ( completed ) { + return jqXHR; + } + + // We can fire global events as of now if asked to + // Don't fire events if jQuery.event is undefined in an AMD-usage scenario (#15118) + fireGlobals = jQuery.event && s.global; + + // Watch for a new set of requests + if ( fireGlobals && jQuery.active++ === 0 ) { + jQuery.event.trigger( "ajaxStart" ); + } + + // Uppercase the type + s.type = s.type.toUpperCase(); + + // Determine if request has content + s.hasContent = !rnoContent.test( s.type ); + + // Save the URL in case we're toying with the If-Modified-Since + // and/or If-None-Match header later on + // Remove hash to simplify url manipulation + cacheURL = s.url.replace( rhash, "" ); + + // More options handling for requests with no content + if ( !s.hasContent ) { + + // Remember the hash so we can put it back + uncached = s.url.slice( cacheURL.length ); + + // If data is available and should be processed, append data to url + if ( s.data && ( s.processData || typeof s.data === "string" ) ) { + cacheURL += ( rquery.test( cacheURL ) ? "&" : "?" ) + s.data; + + // #9682: remove data so that it's not used in an eventual retry + delete s.data; + } + + // Add or update anti-cache param if needed + if ( s.cache === false ) { + cacheURL = cacheURL.replace( rantiCache, "$1" ); + uncached = ( rquery.test( cacheURL ) ? "&" : "?" ) + "_=" + ( nonce.guid++ ) + + uncached; + } + + // Put hash and anti-cache on the URL that will be requested (gh-1732) + s.url = cacheURL + uncached; + + // Change '%20' to '+' if this is encoded form body content (gh-2658) + } else if ( s.data && s.processData && + ( s.contentType || "" ).indexOf( "application/x-www-form-urlencoded" ) === 0 ) { + s.data = s.data.replace( r20, "+" ); + } + + // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode. + if ( s.ifModified ) { + if ( jQuery.lastModified[ cacheURL ] ) { + jqXHR.setRequestHeader( "If-Modified-Since", jQuery.lastModified[ cacheURL ] ); + } + if ( jQuery.etag[ cacheURL ] ) { + jqXHR.setRequestHeader( "If-None-Match", jQuery.etag[ cacheURL ] ); + } + } + + // Set the correct header, if data is being sent + if ( s.data && s.hasContent && s.contentType !== false || options.contentType ) { + jqXHR.setRequestHeader( "Content-Type", s.contentType ); + } + + // Set the Accepts header for the server, depending on the dataType + jqXHR.setRequestHeader( + "Accept", + s.dataTypes[ 0 ] && s.accepts[ s.dataTypes[ 0 ] ] ? + s.accepts[ s.dataTypes[ 0 ] ] + + ( s.dataTypes[ 0 ] !== "*" ? ", " + allTypes + "; q=0.01" : "" ) : + s.accepts[ "*" ] + ); + + // Check for headers option + for ( i in s.headers ) { + jqXHR.setRequestHeader( i, s.headers[ i ] ); + } + + // Allow custom headers/mimetypes and early abort + if ( s.beforeSend && + ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || completed ) ) { + + // Abort if not done already and return + return jqXHR.abort(); + } + + // Aborting is no longer a cancellation + strAbort = "abort"; + + // Install callbacks on deferreds + completeDeferred.add( s.complete ); + jqXHR.done( s.success ); + jqXHR.fail( s.error ); + + // Get transport + transport = inspectPrefiltersOrTransports( transports, s, options, jqXHR ); + + // If no transport, we auto-abort + if ( !transport ) { + done( -1, "No Transport" ); + } else { + jqXHR.readyState = 1; + + // Send global event + if ( fireGlobals ) { + globalEventContext.trigger( "ajaxSend", [ jqXHR, s ] ); + } + + // If request was aborted inside ajaxSend, stop there + if ( completed ) { + return jqXHR; + } + + // Timeout + if ( s.async && s.timeout > 0 ) { + timeoutTimer = window.setTimeout( function() { + jqXHR.abort( "timeout" ); + }, s.timeout ); + } + + try { + completed = false; + transport.send( requestHeaders, done ); + } catch ( e ) { + + // Rethrow post-completion exceptions + if ( completed ) { + throw e; + } + + // Propagate others as results + done( -1, e ); + } + } + + // Callback for when everything is done + function done( status, nativeStatusText, responses, headers ) { + var isSuccess, success, error, response, modified, + statusText = nativeStatusText; + + // Ignore repeat invocations + if ( completed ) { + return; + } + + completed = true; + + // Clear timeout if it exists + if ( timeoutTimer ) { + window.clearTimeout( timeoutTimer ); + } + + // Dereference transport for early garbage collection + // (no matter how long the jqXHR object will be used) + transport = undefined; + + // Cache response headers + responseHeadersString = headers || ""; + + // Set readyState + jqXHR.readyState = status > 0 ? 4 : 0; + + // Determine if successful + isSuccess = status >= 200 && status < 300 || status === 304; + + // Get response data + if ( responses ) { + response = ajaxHandleResponses( s, jqXHR, responses ); + } + + // Use a noop converter for missing script + if ( !isSuccess && jQuery.inArray( "script", s.dataTypes ) > -1 ) { + s.converters[ "text script" ] = function() {}; + } + + // Convert no matter what (that way responseXXX fields are always set) + response = ajaxConvert( s, response, jqXHR, isSuccess ); + + // If successful, handle type chaining + if ( isSuccess ) { + + // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode. + if ( s.ifModified ) { + modified = jqXHR.getResponseHeader( "Last-Modified" ); + if ( modified ) { + jQuery.lastModified[ cacheURL ] = modified; + } + modified = jqXHR.getResponseHeader( "etag" ); + if ( modified ) { + jQuery.etag[ cacheURL ] = modified; + } + } + + // if no content + if ( status === 204 || s.type === "HEAD" ) { + statusText = "nocontent"; + + // if not modified + } else if ( status === 304 ) { + statusText = "notmodified"; + + // If we have data, let's convert it + } else { + statusText = response.state; + success = response.data; + error = response.error; + isSuccess = !error; + } + } else { + + // Extract error from statusText and normalize for non-aborts + error = statusText; + if ( status || !statusText ) { + statusText = "error"; + if ( status < 0 ) { + status = 0; + } + } + } + + // Set data for the fake xhr object + jqXHR.status = status; + jqXHR.statusText = ( nativeStatusText || statusText ) + ""; + + // Success/Error + if ( isSuccess ) { + deferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] ); + } else { + deferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] ); + } + + // Status-dependent callbacks + jqXHR.statusCode( statusCode ); + statusCode = undefined; + + if ( fireGlobals ) { + globalEventContext.trigger( isSuccess ? "ajaxSuccess" : "ajaxError", + [ jqXHR, s, isSuccess ? success : error ] ); + } + + // Complete + completeDeferred.fireWith( callbackContext, [ jqXHR, statusText ] ); + + if ( fireGlobals ) { + globalEventContext.trigger( "ajaxComplete", [ jqXHR, s ] ); + + // Handle the global AJAX counter + if ( !( --jQuery.active ) ) { + jQuery.event.trigger( "ajaxStop" ); + } + } + } + + return jqXHR; + }, + + getJSON: function( url, data, callback ) { + return jQuery.get( url, data, callback, "json" ); + }, + + getScript: function( url, callback ) { + return jQuery.get( url, undefined, callback, "script" ); + } +} ); + +jQuery.each( [ "get", "post" ], function( _i, method ) { + jQuery[ method ] = function( url, data, callback, type ) { + + // Shift arguments if data argument was omitted + if ( isFunction( data ) ) { + type = type || callback; + callback = data; + data = undefined; + } + + // The url can be an options object (which then must have .url) + return jQuery.ajax( jQuery.extend( { + url: url, + type: method, + dataType: type, + data: data, + success: callback + }, jQuery.isPlainObject( url ) && url ) ); + }; +} ); + +jQuery.ajaxPrefilter( function( s ) { + var i; + for ( i in s.headers ) { + if ( i.toLowerCase() === "content-type" ) { + s.contentType = s.headers[ i ] || ""; + } + } +} ); + + +jQuery._evalUrl = function( url, options, doc ) { + return jQuery.ajax( { + url: url, + + // Make this explicit, since user can override this through ajaxSetup (#11264) + type: "GET", + dataType: "script", + cache: true, + async: false, + global: false, + + // Only evaluate the response if it is successful (gh-4126) + // dataFilter is not invoked for failure responses, so using it instead + // of the default converter is kludgy but it works. + converters: { + "text script": function() {} + }, + dataFilter: function( response ) { + jQuery.globalEval( response, options, doc ); + } + } ); +}; + + +jQuery.fn.extend( { + wrapAll: function( html ) { + var wrap; + + if ( this[ 0 ] ) { + if ( isFunction( html ) ) { + html = html.call( this[ 0 ] ); + } + + // The elements to wrap the target around + wrap = jQuery( html, this[ 0 ].ownerDocument ).eq( 0 ).clone( true ); + + if ( this[ 0 ].parentNode ) { + wrap.insertBefore( this[ 0 ] ); + } + + wrap.map( function() { + var elem = this; + + while ( elem.firstElementChild ) { + elem = elem.firstElementChild; + } + + return elem; + } ).append( this ); + } + + return this; + }, + + wrapInner: function( html ) { + if ( isFunction( html ) ) { + return this.each( function( i ) { + jQuery( this ).wrapInner( html.call( this, i ) ); + } ); + } + + return this.each( function() { + var self = jQuery( this ), + contents = self.contents(); + + if ( contents.length ) { + contents.wrapAll( html ); + + } else { + self.append( html ); + } + } ); + }, + + wrap: function( html ) { + var htmlIsFunction = isFunction( html ); + + return this.each( function( i ) { + jQuery( this ).wrapAll( htmlIsFunction ? html.call( this, i ) : html ); + } ); + }, + + unwrap: function( selector ) { + this.parent( selector ).not( "body" ).each( function() { + jQuery( this ).replaceWith( this.childNodes ); + } ); + return this; + } +} ); + + +jQuery.expr.pseudos.hidden = function( elem ) { + return !jQuery.expr.pseudos.visible( elem ); +}; +jQuery.expr.pseudos.visible = function( elem ) { + return !!( elem.offsetWidth || elem.offsetHeight || elem.getClientRects().length ); +}; + + + + +jQuery.ajaxSettings.xhr = function() { + try { + return new window.XMLHttpRequest(); + } catch ( e ) {} +}; + +var xhrSuccessStatus = { + + // File protocol always yields status code 0, assume 200 + 0: 200, + + // Support: IE <=9 only + // #1450: sometimes IE returns 1223 when it should be 204 + 1223: 204 + }, + xhrSupported = jQuery.ajaxSettings.xhr(); + +support.cors = !!xhrSupported && ( "withCredentials" in xhrSupported ); +support.ajax = xhrSupported = !!xhrSupported; + +jQuery.ajaxTransport( function( options ) { + var callback, errorCallback; + + // Cross domain only allowed if supported through XMLHttpRequest + if ( support.cors || xhrSupported && !options.crossDomain ) { + return { + send: function( headers, complete ) { + var i, + xhr = options.xhr(); + + xhr.open( + options.type, + options.url, + options.async, + options.username, + options.password + ); + + // Apply custom fields if provided + if ( options.xhrFields ) { + for ( i in options.xhrFields ) { + xhr[ i ] = options.xhrFields[ i ]; + } + } + + // Override mime type if needed + if ( options.mimeType && xhr.overrideMimeType ) { + xhr.overrideMimeType( options.mimeType ); + } + + // X-Requested-With header + // For cross-domain requests, seeing as conditions for a preflight are + // akin to a jigsaw puzzle, we simply never set it to be sure. + // (it can always be set on a per-request basis or even using ajaxSetup) + // For same-domain requests, won't change header if already provided. + if ( !options.crossDomain && !headers[ "X-Requested-With" ] ) { + headers[ "X-Requested-With" ] = "XMLHttpRequest"; + } + + // Set headers + for ( i in headers ) { + xhr.setRequestHeader( i, headers[ i ] ); + } + + // Callback + callback = function( type ) { + return function() { + if ( callback ) { + callback = errorCallback = xhr.onload = + xhr.onerror = xhr.onabort = xhr.ontimeout = + xhr.onreadystatechange = null; + + if ( type === "abort" ) { + xhr.abort(); + } else if ( type === "error" ) { + + // Support: IE <=9 only + // On a manual native abort, IE9 throws + // errors on any property access that is not readyState + if ( typeof xhr.status !== "number" ) { + complete( 0, "error" ); + } else { + complete( + + // File: protocol always yields status 0; see #8605, #14207 + xhr.status, + xhr.statusText + ); + } + } else { + complete( + xhrSuccessStatus[ xhr.status ] || xhr.status, + xhr.statusText, + + // Support: IE <=9 only + // IE9 has no XHR2 but throws on binary (trac-11426) + // For XHR2 non-text, let the caller handle it (gh-2498) + ( xhr.responseType || "text" ) !== "text" || + typeof xhr.responseText !== "string" ? + { binary: xhr.response } : + { text: xhr.responseText }, + xhr.getAllResponseHeaders() + ); + } + } + }; + }; + + // Listen to events + xhr.onload = callback(); + errorCallback = xhr.onerror = xhr.ontimeout = callback( "error" ); + + // Support: IE 9 only + // Use onreadystatechange to replace onabort + // to handle uncaught aborts + if ( xhr.onabort !== undefined ) { + xhr.onabort = errorCallback; + } else { + xhr.onreadystatechange = function() { + + // Check readyState before timeout as it changes + if ( xhr.readyState === 4 ) { + + // Allow onerror to be called first, + // but that will not handle a native abort + // Also, save errorCallback to a variable + // as xhr.onerror cannot be accessed + window.setTimeout( function() { + if ( callback ) { + errorCallback(); + } + } ); + } + }; + } + + // Create the abort callback + callback = callback( "abort" ); + + try { + + // Do send the request (this may raise an exception) + xhr.send( options.hasContent && options.data || null ); + } catch ( e ) { + + // #14683: Only rethrow if this hasn't been notified as an error yet + if ( callback ) { + throw e; + } + } + }, + + abort: function() { + if ( callback ) { + callback(); + } + } + }; + } +} ); + + + + +// Prevent auto-execution of scripts when no explicit dataType was provided (See gh-2432) +jQuery.ajaxPrefilter( function( s ) { + if ( s.crossDomain ) { + s.contents.script = false; + } +} ); + +// Install script dataType +jQuery.ajaxSetup( { + accepts: { + script: "text/javascript, application/javascript, " + + "application/ecmascript, application/x-ecmascript" + }, + contents: { + script: /\b(?:java|ecma)script\b/ + }, + converters: { + "text script": function( text ) { + jQuery.globalEval( text ); + return text; + } + } +} ); + +// Handle cache's special case and crossDomain +jQuery.ajaxPrefilter( "script", function( s ) { + if ( s.cache === undefined ) { + s.cache = false; + } + if ( s.crossDomain ) { + s.type = "GET"; + } +} ); + +// Bind script tag hack transport +jQuery.ajaxTransport( "script", function( s ) { + + // This transport only deals with cross domain or forced-by-attrs requests + if ( s.crossDomain || s.scriptAttrs ) { + var script, callback; + return { + send: function( _, complete ) { + script = jQuery( " + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for an unstable version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra - Exceptions and Enums

+
+
+cassandra.__version_info__
+

The version of the driver in a tuple format

+
+ +
+
+cassandra.__version__
+

The version of the driver in a string format

+
+ +
+
+class cassandra.ConsistencyLevel
+

Spcifies how many replicas must respond for an operation to be considered +a success. By default, ONE is used for all operations.

+
+
+ANY = 0
+

Only requires that one replica receives the write or the coordinator +stores a hint to replay later. Valid only for writes.

+
+ +
+
+ONE = 1
+

Only one replica needs to respond to consider the operation a success

+
+ +
+
+TWO = 2
+

Two replicas must respond to consider the operation a success

+
+ +
+
+THREE = 3
+

Three replicas must respond to consider the operation a success

+
+ +
+
+QUORUM = 4
+

ceil(RF/2) + 1 replicas must respond to consider the operation a success

+
+ +
+
+ALL = 5
+

All replicas must respond to consider the operation a success

+
+ +
+
+LOCAL_QUORUM = 6
+

Requires a quorum of replicas in the local datacenter

+
+ +
+
+EACH_QUORUM = 7
+

Requires a quorum of replicas in each datacenter

+
+ +
+
+SERIAL = 8
+

For conditional inserts/updates that utilize Cassandra’s lightweight +transactions, this requires consensus among all replicas for the +modified data.

+
+ +
+
+LOCAL_SERIAL = 9
+

Like SERIAL, but only requires consensus +among replicas in the local datacenter.

+
+ +
+
+LOCAL_ONE = 10
+

Sends a request only to replicas in the local datacenter and waits for +one response.

+
+ +
+ +
+
+class cassandra.ProtocolVersion
+

Defines native protocol versions supported by this driver.

+
+
+V1 = 1
+

v1, supported in Cassandra 1.2–>2.2

+
+ +
+
+V2 = 2
+

v2, supported in Cassandra 2.0–>2.2; +added support for lightweight transactions, batch operations, and automatic query paging.

+
+ +
+
+V3 = 3
+

v3, supported in Cassandra 2.1–>3.x+; +added support for protocol-level client-side timestamps (see Session.use_client_timestamp), +serial consistency levels for BatchStatement, and an improved connection pool.

+
+ +
+
+V4 = 4
+

v4, supported in Cassandra 2.2–>3.x+; +added a number of new types, server warnings, new failure messages, and custom payloads. Details in the +project docs

+
+ +
+
+V5 = 5
+

v5, in beta from 3.x+. Finalised in 4.0-beta5

+
+ +
+
+V6 = 6
+

v6, in beta from 4.0-beta5

+
+ +
+
+DSE_V1 = 65
+

DSE private protocol v1, supported in DSE 5.1+

+
+ +
+
+DSE_V2 = 66
+

DSE private protocol v2, supported in DSE 6.0+

+
+ +
+
+SUPPORTED_VERSIONS = (66, 65, 6, 5, 4, 3, 2, 1)
+

A tuple of all supported protocol versions

+
+ +
+
+BETA_VERSIONS = (6,)
+

A tuple of all beta protocol versions

+
+ +
+
+MIN_SUPPORTED = 1
+

Minimum protocol version supported by this driver.

+
+ +
+
+MAX_SUPPORTED = 66
+

Maximum protocol version supported by this driver.

+
+ +
+
+classmethod get_lower_supported(previous_version)
+

Return the lower supported protocol version. Beta versions are omitted.

+
+ +
+ +
+
+class cassandra.UserFunctionDescriptor(name, argument_types)
+

Describes a User function by name and argument signature

+
+
+name = None
+

name of the function

+
+ +
+
+argument_types = None
+

Ordered list of CQL argument type names comprising the type signature

+
+ +
+
+property signature
+

function signature string in the form ‘name([type0[,type1[…]]])’

+

can be used to uniquely identify overloaded function names within a keyspace

+
+ +
+ +
+
+class cassandra.UserAggregateDescriptor(name, argument_types)
+

Describes a User aggregate function by name and argument signature

+
+
+name = None
+

name of the aggregate

+
+ +
+
+argument_types = None
+

Ordered list of CQL argument type names comprising the type signature

+
+ +
+
+property signature
+

function signature string in the form ‘name([type0[,type1[…]]])’

+

can be used to uniquely identify overloaded function names within a keyspace

+
+ +
+ +
+
+exception cassandra.DriverException
+

Base for all exceptions explicitly raised by the driver.

+
+ +
+
+exception cassandra.RequestExecutionException
+

Base for request execution exceptions returned from the server.

+
+ +
+
+exception cassandra.Unavailable
+

There were not enough live replicas to satisfy the requested consistency +level, so the coordinator node immediately failed the request without +forwarding it to any replicas.

+
+
+consistency = None
+

The requested ConsistencyLevel

+
+ +
+
+required_replicas = None
+

The number of replicas that needed to be live to complete the operation

+
+ +
+
+alive_replicas = None
+

The number of replicas that were actually alive

+
+ +
+ +
+
+exception cassandra.Timeout
+

Replicas failed to respond to the coordinator node before timing out.

+
+
+consistency = None
+

The requested ConsistencyLevel

+
+ +
+
+required_responses = None
+

The number of required replica responses

+
+ +
+
+received_responses = None
+

The number of replicas that responded before the coordinator timed out +the operation

+
+ +
+ +
+
+exception cassandra.ReadTimeout
+

A subclass of Timeout for read operations.

+

This indicates that the replicas failed to respond to the coordinator +node before the configured timeout. This timeout is configured in +cassandra.yaml with the read_request_timeout_in_ms +and range_request_timeout_in_ms options.

+
+
+data_retrieved = None
+

A boolean indicating whether the requested data was retrieved +by the coordinator from any replicas before it timed out the +operation

+
+ +
+ +
+
+exception cassandra.WriteTimeout
+

A subclass of Timeout for write operations.

+

This indicates that the replicas failed to respond to the coordinator +node before the configured timeout. This timeout is configured in +cassandra.yaml with the write_request_timeout_in_ms +option.

+
+
+write_type = None
+

The type of write operation, enum on WriteType

+
+ +
+ +
+
+exception cassandra.CoordinationFailure
+

Replicas sent a failure to the coordinator.

+
+
+consistency = None
+

The requested ConsistencyLevel

+
+ +
+
+required_responses = None
+

The number of required replica responses

+
+ +
+
+received_responses = None
+

The number of replicas that responded before the coordinator timed out +the operation

+
+ +
+
+failures = None
+

The number of replicas that sent a failure message

+
+ +
+
+error_code_map = None
+

A map of inet addresses to error codes representing replicas that sent +a failure message. Only set when protocol_version is 5 or higher.

+
+ +
+ +
+
+exception cassandra.ReadFailure
+

A subclass of CoordinationFailure for read operations.

+

This indicates that the replicas sent a failure message to the coordinator.

+
+
+data_retrieved = None
+

A boolean indicating whether the requested data was retrieved +by the coordinator from any replicas before it timed out the +operation

+
+ +
+ +
+
+exception cassandra.WriteFailure
+

A subclass of CoordinationFailure for write operations.

+

This indicates that the replicas sent a failure message to the coordinator.

+
+
+write_type = None
+

The type of write operation, enum on WriteType

+
+ +
+ +
+
+exception cassandra.FunctionFailure
+

User Defined Function failed during execution

+
+
+keyspace = None
+

Keyspace of the function

+
+ +
+
+function = None
+

Name of the function

+
+ +
+
+arg_types = None
+

List of argument type names of the function

+
+ +
+ +
+
+exception cassandra.RequestValidationException
+

Server request validation failed

+
+ +
+
+exception cassandra.ConfigurationException
+

Server indicated request errro due to current configuration

+
+ +
+
+exception cassandra.AlreadyExists
+

An attempt was made to create a keyspace or table that already exists.

+
+
+keyspace = None
+

The name of the keyspace that already exists, or, if an attempt was +made to create a new table, the keyspace that the table is in.

+
+ +
+
+table = None
+

The name of the table that already exists, or, if an attempt was +make to create a keyspace, None.

+
+ +
+ +
+
+exception cassandra.InvalidRequest
+

A query was made that was invalid for some reason, such as trying to set +the keyspace for a connection to a nonexistent keyspace.

+
+ +
+
+exception cassandra.Unauthorized
+

The current user is not authorized to perform the requested operation.

+
+ +
+
+exception cassandra.AuthenticationFailed
+

Failed to authenticate.

+
+ +
+
+exception cassandra.OperationTimedOut
+

The operation took longer than the specified (client-side) timeout +to complete. This is not an error generated by Cassandra, only +the driver.

+
+
+errors = None
+

A dict of errors keyed by the Host against which they occurred.

+
+ +
+
+last_host = None
+

The last Host this operation was attempted against.

+
+ +
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/master/api/cassandra/auth.html b/master/api/cassandra/auth.html new file mode 100644 index 0000000000..6515f85b4e --- /dev/null +++ b/master/api/cassandra/auth.html @@ -0,0 +1,807 @@ + + + + + + + + + + + + + cassandra.auth - Authentication | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for an unstable version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.auth - Authentication

+
+
+class cassandra.auth.AuthProvider
+

An abstract class that defines the interface that will be used for +creating Authenticator instances when opening new +connections to Cassandra.

+
+

New in version 2.0.0.

+
+
+
+new_authenticator(host)
+

Implementations of this class should return a new instance +of Authenticator or one of its subclasses.

+
+ +
+ +
+
+class cassandra.auth.Authenticator
+

An abstract class that handles SASL authentication with Cassandra servers.

+

Each time a new connection is created and the server requires authentication, +a new instance of this class will be created by the corresponding +AuthProvider to handler that authentication. The lifecycle of the +new Authenticator will the be:

+

1) The initial_response() method will be called. The return +value will be sent to the server to initiate the handshake.

+

2) The server will respond to each client response by either issuing a +challenge or indicating that the authentication is complete (successful or not). +If a new challenge is issued, evaluate_challenge() +will be called to produce a response that will be sent to the +server. This challenge/response negotiation will continue until the server +responds that authentication is successful (or an AuthenticationFailed +is raised).

+

3) When the server indicates that authentication is successful, +on_authentication_success() will be called a token string that +that the server may optionally have sent.

+

The exact nature of the negotiation between the client and server is specific +to the authentication mechanism configured server-side.

+
+

New in version 2.0.0.

+
+
+
+server_authenticator_class = None
+

Set during the connection AUTHENTICATE phase

+
+ +
+
+initial_response()
+

Returns an message to send to the server to initiate the SASL handshake. +None may be returned to send an empty message.

+
+ +
+
+evaluate_challenge(challenge)
+

Called when the server sends a challenge message. Generally, this method +should return None when authentication is complete from a +client perspective. Otherwise, a string should be returned.

+
+ +
+
+on_authentication_success(token)
+

Called when the server indicates that authentication was successful. +Depending on the authentication mechanism, token may be None +or a string.

+
+ +
+ +
+
+class cassandra.auth.PlainTextAuthProvider(username, password)
+

An AuthProvider that works with Cassandra’s PasswordAuthenticator.

+

Example usage:

+
from cassandra.cluster import Cluster
+from cassandra.auth import PlainTextAuthProvider
+
+auth_provider = PlainTextAuthProvider(
+        username='cassandra', password='cassandra')
+cluster = Cluster(auth_provider=auth_provider)
+
+
+
+

New in version 2.0.0.

+
+
+
+new_authenticator(host)
+

Implementations of this class should return a new instance +of Authenticator or one of its subclasses.

+
+ +
+ +
+
+class cassandra.auth.PlainTextAuthenticator(username, password)
+
+
+evaluate_challenge(challenge)
+

Called when the server sends a challenge message. Generally, this method +should return None when authentication is complete from a +client perspective. Otherwise, a string should be returned.

+
+ +
+ +
+
+class cassandra.auth.SaslAuthProvider(**sasl_kwargs)
+

An AuthProvider supporting general SASL auth mechanisms

+

Suitable for GSSAPI or other SASL mechanisms

+

Example usage:

+
from cassandra.cluster import Cluster
+from cassandra.auth import SaslAuthProvider
+
+sasl_kwargs = {'service': 'something',
+               'mechanism': 'GSSAPI',
+               'qops': 'auth'.split(',')}
+auth_provider = SaslAuthProvider(**sasl_kwargs)
+cluster = Cluster(auth_provider=auth_provider)
+
+
+
+

New in version 2.1.4.

+
+
+
+new_authenticator(host)
+

Implementations of this class should return a new instance +of Authenticator or one of its subclasses.

+
+ +
+ +
+
+class cassandra.auth.SaslAuthenticator(host, service, mechanism='GSSAPI', **sasl_kwargs)
+

A pass-through Authenticator using the third party package +‘pure-sasl’ for authentication

+
+

New in version 2.1.4.

+
+
+
+initial_response()
+

Returns an message to send to the server to initiate the SASL handshake. +None may be returned to send an empty message.

+
+ +
+
+evaluate_challenge(challenge)
+

Called when the server sends a challenge message. Generally, this method +should return None when authentication is complete from a +client perspective. Otherwise, a string should be returned.

+
+ +
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/master/api/cassandra/cluster.html b/master/api/cassandra/cluster.html new file mode 100644 index 0000000000..e02accb8d0 --- /dev/null +++ b/master/api/cassandra/cluster.html @@ -0,0 +1,1779 @@ + + + + + + + + + + + + + cassandra.cluster - Clusters and Sessions | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for an unstable version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.cluster - Clusters and Sessions

+
+
+class cassandra.cluster.Cluster([contact_points=('127.0.0.1',)][, port=9042][, executor_threads=2], **attr_kwargs)
+

The main class to use when interacting with a Cassandra cluster. +Typically, one instance of this class will be created for each +separate Cassandra cluster that your application interacts with.

+

Example usage:

+
>>> from cassandra.cluster import Cluster
+>>> cluster = Cluster(['192.168.1.1', '192.168.1.2'])
+>>> session = cluster.connect()
+>>> session.execute("CREATE KEYSPACE ...")
+>>> ...
+>>> cluster.shutdown()
+
+
+

Cluster and Session also provide context management functions +which implicitly handle shutdown when leaving scope.

+

executor_threads defines the number of threads in a pool for handling asynchronous tasks such as +extablishing connection pools or refreshing metadata.

+

Any of the mutable Cluster attributes may be set as keyword arguments to the constructor.

+
+
+contact_points = ['127.0.0.1']
+
+ +
+
+port = 9042
+
+ +
+
+cql_version = None
+
+ +
+
+protocol_version = 66
+
+ +
+
+compression = True
+
+ +
+
+auth_provider
+

When protocol_version is 2 or higher, this should +be an instance of a subclass of AuthProvider, +such as PlainTextAuthProvider.

+

When protocol_version is 1, this should be +a function that accepts one argument, the IP address of a node, +and returns a dict of credentials for that node.

+

When not using authentication, this should be left as None.

+
+ +
+
+load_balancing_policy
+

An instance of policies.LoadBalancingPolicy or +one of its subclasses.

+
+

Changed in version 2.6.0.

+
+

Defaults to TokenAwarePolicy (DCAwareRoundRobinPolicy). +when using CPython (where the murmur3 extension is available). DCAwareRoundRobinPolicy +otherwise. Default local DC will be chosen from contact points.

+

Please see DCAwareRoundRobinPolicy for a discussion on default behavior with respect to +DC locality and remote nodes.

+
+ +
+
+reconnection_policy = <cassandra.policies.ExponentialReconnectionPolicy object>
+
+ +
+
+default_retry_policy = <cassandra.policies.RetryPolicy object>
+

A default policies.RetryPolicy instance to use for all +Statement objects which do not have a retry_policy +explicitly set.

+
+ +
+
+conviction_policy_factory = <class 'cassandra.policies.SimpleConvictionPolicy'>
+
+ +
+
+address_translator = <cassandra.policies.IdentityTranslator object>
+
+ +
+
+metrics_enabled = False
+
+ +
+
+metrics = None
+
+ +
+
+ssl_context = None
+
+ +
+
+ssl_options = None
+
+ +
+
+sockopts = None
+
+ +
+
+max_schema_agreement_wait = 10
+
+ +
+
+metadata = None
+
+ +
+
+connection_class = <class 'cassandra.io.libevreactor.LibevConnection'>
+
+ +
+
+control_connection_timeout = 2.0
+
+ +
+
+idle_heartbeat_interval = 30
+
+ +
+
+idle_heartbeat_timeout = 30
+
+ +
+
+schema_event_refresh_window = 2
+
+ +
+
+topology_event_refresh_window = 10
+
+ +
+
+status_event_refresh_window = 2
+
+ +
+
+prepare_on_all_hosts = True
+
+ +
+
+reprepare_on_up = True
+
+ +
+
+connect_timeout = 5
+
+ +
+
+schema_metadata_enabled = True
+

Flag indicating whether internal schema metadata is updated.

+

When disabled, the driver does not populate Cluster.metadata.keyspaces on connect, or on schema change events. This +can be used to speed initial connection, and reduce load on client and server during operation. Turning this off +gives away token aware request routing, and programmatic inspection of the metadata model.

+
+ +
+
+token_metadata_enabled = True
+

Flag indicating whether internal token metadata is updated.

+

When disabled, the driver does not query node token information on connect, or on topology change events. This +can be used to speed initial connection, and reduce load on client and server during operation. It is most useful +in large clusters using vnodes, where the token map can be expensive to compute. Turning this off +gives away token aware request routing, and programmatic inspection of the token ring.

+
+ +
+
+timestamp_generator = None
+
+ +
+
+endpoint_factory = None
+
+ +
+
+cloud = None
+
+ +
+
+connect(keyspace=None, wait_for_all_pools=False)
+

Creates and returns a new Session object.

+

If keyspace is specified, that keyspace will be the default keyspace for +operations on the Session.

+

wait_for_all_pools specifies whether this call should wait for all connection pools to be +established or attempted. Default is False, which means it will return when the first +successful connection is established. Remaining pools are added asynchronously.

+
+ +
+
+shutdown()
+

Closes all sessions and connection associated with this Cluster. +To ensure all connections are properly closed, you should always +call shutdown() on a Cluster instance when you are done with it.

+

Once shutdown, a Cluster should not be used for any purpose.

+
+ +
+
+register_user_type(keyspace, user_type, klass)
+

Registers a class to use to represent a particular user-defined type. +Query parameters for this user-defined type will be assumed to be +instances of klass. Result sets for this user-defined type will +be instances of klass. If no class is registered for a user-defined +type, a namedtuple will be used for result sets, and non-prepared +statements may not encode parameters for this type correctly.

+

keyspace is the name of the keyspace that the UDT is defined in.

+

user_type is the string name of the UDT to register the mapping +for.

+

klass should be a class with attributes whose names match the +fields of the user-defined type. The constructor must accepts kwargs +for each of the fields in the UDT.

+

This method should only be called after the type has been created +within Cassandra.

+

Example:

+
cluster = Cluster(protocol_version=3)
+session = cluster.connect()
+session.set_keyspace('mykeyspace')
+session.execute("CREATE TYPE address (street text, zipcode int)")
+session.execute("CREATE TABLE users (id int PRIMARY KEY, location address)")
+
+# create a class to map to the "address" UDT
+class Address(object):
+
+    def __init__(self, street, zipcode):
+        self.street = street
+        self.zipcode = zipcode
+
+cluster.register_user_type('mykeyspace', 'address', Address)
+
+# insert a row using an instance of Address
+session.execute("INSERT INTO users (id, location) VALUES (%s, %s)",
+                (0, Address("123 Main St.", 78723)))
+
+# results will include Address instances
+results = session.execute("SELECT * FROM users")
+row = results[0]
+print row.id, row.location.street, row.location.zipcode
+
+
+
+ +
+
+register_listener(listener)
+

Adds a cassandra.policies.HostStateListener subclass instance to +the list of listeners to be notified when a host is added, removed, +marked up, or marked down.

+
+ +
+
+unregister_listener(listener)
+

Removes a registered listener.

+
+ +
+
+add_execution_profile(name, profile, pool_wait_timeout=5)
+

Adds an ExecutionProfile to the cluster. This makes it available for use by name in Session.execute() +and Session.execute_async(). This method will raise if the profile already exists.

+

Normally profiles will be injected at cluster initialization via Cluster(execution_profiles). This method +provides a way of adding them dynamically.

+

Adding a new profile updates the connection pools according to the specified load_balancing_policy. By default, +this method will wait up to five seconds for the pool creation to complete, so the profile can be used immediately +upon return. This behavior can be controlled using pool_wait_timeout (see +concurrent.futures.wait +for timeout semantics).

+
+ +
+
+set_max_requests_per_connection(host_distance, max_requests)
+

Sets a threshold for concurrent requests per connection, above which new +connections will be created to a host (up to max connections; +see set_max_connections_per_host()).

+

Pertains to connection pool management in protocol versions {1,2}.

+
+ +
+
+get_max_requests_per_connection(host_distance)
+
+ +
+
+set_min_requests_per_connection(host_distance, min_requests)
+

Sets a threshold for concurrent requests per connection, below which +connections will be considered for disposal (down to core connections; +see set_core_connections_per_host()).

+

Pertains to connection pool management in protocol versions {1,2}.

+
+ +
+
+get_min_requests_per_connection(host_distance)
+
+ +
+
+get_core_connections_per_host(host_distance)
+

Gets the minimum number of connections per Session that will be opened +for each host with HostDistance equal to host_distance. +The default is 2 for LOCAL and 1 for +REMOTE.

+

This property is ignored if protocol_version is +3 or higher.

+
+ +
+
+set_core_connections_per_host(host_distance, core_connections)
+

Sets the minimum number of connections per Session that will be opened +for each host with HostDistance equal to host_distance. +The default is 2 for LOCAL and 1 for +REMOTE.

+

Protocol version 1 and 2 are limited in the number of concurrent +requests they can send per connection. The driver implements connection +pooling to support higher levels of concurrency.

+

If protocol_version is set to 3 or higher, this +is not supported (there is always one connection per host, unless +the host is remote and connect_to_remote_hosts is False) +and using this will result in an UnsupportedOperation.

+
+ +
+
+get_max_connections_per_host(host_distance)
+

Gets the maximum number of connections per Session that will be opened +for each host with HostDistance equal to host_distance. +The default is 8 for LOCAL and 2 for +REMOTE.

+

This property is ignored if protocol_version is +3 or higher.

+
+ +
+
+set_max_connections_per_host(host_distance, max_connections)
+

Sets the maximum number of connections per Session that will be opened +for each host with HostDistance equal to host_distance. +The default is 2 for LOCAL and 1 for +REMOTE.

+

If protocol_version is set to 3 or higher, this +is not supported (there is always one connection per host, unless +the host is remote and connect_to_remote_hosts is False) +and using this will result in an UnsupportedOperation.

+
+ +
+
+get_control_connection_host()
+

Returns the control connection host metadata.

+
+ +
+
+refresh_schema_metadata(max_schema_agreement_wait=None)
+

Synchronously refresh all schema metadata.

+

By default, the timeout for this operation is governed by max_schema_agreement_wait +and control_connection_timeout.

+

Passing max_schema_agreement_wait here overrides max_schema_agreement_wait.

+

Setting max_schema_agreement_wait <= 0 will bypass schema agreement and refresh schema immediately.

+

An Exception is raised if schema refresh fails for any reason.

+
+ +
+
+refresh_keyspace_metadata(keyspace, max_schema_agreement_wait=None)
+

Synchronously refresh keyspace metadata. This applies to keyspace-level information such as replication +and durability settings. It does not refresh tables, types, etc. contained in the keyspace.

+

See refresh_schema_metadata() for description of max_schema_agreement_wait behavior

+
+ +
+
+refresh_table_metadata(keyspace, table, max_schema_agreement_wait=None)
+

Synchronously refresh table metadata. This applies to a table, and any triggers or indexes attached +to the table.

+

See refresh_schema_metadata() for description of max_schema_agreement_wait behavior

+
+ +
+
+refresh_user_type_metadata(keyspace, user_type, max_schema_agreement_wait=None)
+

Synchronously refresh user defined type metadata.

+

See refresh_schema_metadata() for description of max_schema_agreement_wait behavior

+
+ +
+
+refresh_user_function_metadata(keyspace, function, max_schema_agreement_wait=None)
+

Synchronously refresh user defined function metadata.

+

function is a cassandra.UserFunctionDescriptor.

+

See refresh_schema_metadata() for description of max_schema_agreement_wait behavior

+
+ +
+
+refresh_user_aggregate_metadata(keyspace, aggregate, max_schema_agreement_wait=None)
+

Synchronously refresh user defined aggregate metadata.

+

aggregate is a cassandra.UserAggregateDescriptor.

+

See refresh_schema_metadata() for description of max_schema_agreement_wait behavior

+
+ +
+
+refresh_nodes(force_token_rebuild=False)
+

Synchronously refresh the node list and token metadata

+

force_token_rebuild can be used to rebuild the token map metadata, even if no new nodes are discovered.

+

An Exception is raised if node refresh fails for any reason.

+
+ +
+
+set_meta_refresh_enabled(enabled)
+

Deprecated: set schema_metadata_enabled token_metadata_enabled instead

+

Sets a flag to enable (True) or disable (False) all metadata refresh queries. +This applies to both schema and node topology.

+

Disabling this is useful to minimize refreshes during multiple changes.

+

Meta refresh must be enabled for the driver to become aware of any cluster +topology changes or schema updates.

+
+ +
+ +
+
+class cassandra.cluster.ExecutionProfile(load_balancing_policy=<object object>, retry_policy=None, consistency_level=ConsistencyLevel.LOCAL_ONE, serial_consistency_level=None, request_timeout=10.0, row_factory=<function named_tuple_factory>, speculative_execution_policy=None)
+
+
+consistency_level = LOCAL_ONE
+
+ +
+
+static row_factory(colnames, rows)
+

Returns each row as a namedtuple. +This is the default row factory.

+

Example:

+
>>> from cassandra.query import named_tuple_factory
+>>> session = cluster.connect('mykeyspace')
+>>> session.row_factory = named_tuple_factory
+>>> rows = session.execute("SELECT name, age FROM users LIMIT 1")
+>>> user = rows[0]
+
+>>> # you can access field by their name:
+>>> print "name: %s, age: %d" % (user.name, user.age)
+name: Bob, age: 42
+
+>>> # or you can access fields by their position (like a tuple)
+>>> name, age = user
+>>> print "name: %s, age: %d" % (name, age)
+name: Bob, age: 42
+>>> name = user[0]
+>>> age = user[1]
+>>> print "name: %s, age: %d" % (name, age)
+name: Bob, age: 42
+
+
+
+

Changed in version 2.0.0: moved from cassandra.decoder to cassandra.query

+
+
+ +
+ +
+
+class cassandra.cluster.GraphExecutionProfile(load_balancing_policy=_NOT_SET, retry_policy=None, consistency_level=ConsistencyLevel.LOCAL_ONE, serial_consistency_level=None, request_timeout=30.0, row_factory=None, graph_options=None, continuous_paging_options=_NOT_SET)
+

Default execution profile for graph execution.

+

See ExecutionProfile for base attributes. Note that if not explicitly set, +the row_factory and graph_options.graph_protocol are resolved during the query execution. +These options will resolve to graph_graphson3_row_factory and GraphProtocol.GRAPHSON_3_0 +for the core graph engine (DSE 6.8+), otherwise graph_object_row_factory and GraphProtocol.GRAPHSON_1_0

+

In addition to default parameters shown in the signature, this profile also defaults retry_policy to +cassandra.policies.NeverRetryPolicy.

+
+ +
+
+class cassandra.cluster.GraphAnalyticsExecutionProfile(load_balancing_policy=None, retry_policy=None, consistency_level=ConsistencyLevel.LOCAL_ONE, serial_consistency_level=None, request_timeout=3600.0 * 24.0 * 7.0, row_factory=None, graph_options=None)
+

Execution profile with timeout and load balancing appropriate for graph analytics queries.

+

See also GraphExecutionPolicy.

+

In addition to default parameters shown in the signature, this profile also defaults retry_policy to +cassandra.policies.NeverRetryPolicy, and load_balancing_policy to one that targets the current Spark +master.

+

Note: The graph_options.graph_source is set automatically to b’a’ (analytics) +when using GraphAnalyticsExecutionProfile. This is mandatory to target analytics nodes.

+
+ +
+
+cassandra.cluster.EXEC_PROFILE_DEFAULT
+

The most base type

+
+ +
+
+cassandra.cluster.EXEC_PROFILE_GRAPH_DEFAULT
+

The most base type

+
+ +
+
+cassandra.cluster.EXEC_PROFILE_GRAPH_SYSTEM_DEFAULT
+

The most base type

+
+ +
+
+cassandra.cluster.EXEC_PROFILE_GRAPH_ANALYTICS_DEFAULT
+

The most base type

+
+ +
+
+class cassandra.cluster.Session
+

A collection of connection pools for each host in the cluster. +Instances of this class should not be created directly, only +using Cluster.connect().

+

Queries and statements can be executed through Session instances +using the execute() and execute_async() +methods.

+

Example usage:

+
>>> session = cluster.connect()
+>>> session.set_keyspace("mykeyspace")
+>>> session.execute("SELECT * FROM mycf")
+
+
+
+
+default_timeout = 10.0
+

A default timeout, measured in seconds, for queries executed through +execute() or execute_async(). This default may be +overridden with the timeout parameter for either of those methods.

+

Setting this to None will cause no timeouts to be set by default.

+

Please see ResponseFuture.result() for details on the scope and +effect of this timeout.

+
+

New in version 2.0.0.

+
+
+ +
+
+default_consistency_level = LOCAL_ONE
+

Deprecated: use execution profiles instead +The default ConsistencyLevel for operations executed through +this session. This default may be overridden by setting the +consistency_level on individual statements.

+
+

New in version 1.2.0.

+
+
+

Changed in version 3.0.0: default changed from ONE to LOCAL_ONE

+
+
+ +
+
+default_serial_consistency_level = None
+

The default ConsistencyLevel for serial phase of conditional updates executed through +this session. This default may be overridden by setting the +serial_consistency_level on individual statements.

+

Only valid for protocol_version >= 2.

+
+ +
+
+row_factory = <function named_tuple_factory>
+

The format to return row results in. By default, each +returned row will be a named tuple. You can alternatively +use any of the following:

+ +
+ +
+
+default_fetch_size = 5000
+
+ +
+
+use_client_timestamp = True
+
+ +
+
+timestamp_generator = None
+
+ +
+
+encoder = None
+
+ +
+
+client_protocol_handler = <class 'cassandra.protocol.cython_protocol_handler.<locals>.CythonProtocolHandler'>
+
+ +
+
+execute(statement[, parameters][, timeout][, trace][, custom_payload][, paging_state][, host][, execute_as])
+

Execute the given query and synchronously wait for the response.

+

If an error is encountered while executing the query, an Exception +will be raised.

+

query may be a query string or an instance of cassandra.query.Statement.

+

parameters may be a sequence or dict of parameters to bind. If a +sequence is used, %s should be used the placeholder for each +argument. If a dict is used, %(name)s style placeholders must +be used.

+

timeout should specify a floating-point timeout (in seconds) after +which an OperationTimedOut exception will be raised if the query +has not completed. If not set, the timeout defaults to the request_timeout of the selected execution_profile. +If set to None, there is no timeout. Please see ResponseFuture.result() for details on +the scope and effect of this timeout.

+

If trace is set to True, the query will be sent with tracing enabled. +The trace details can be obtained using the returned ResultSet object.

+

custom_payload is a Custom Payloads dict to be passed to the server. +If query is a Statement with its own custom_payload. The message payload +will be a union of the two, with the values specified here taking precedence.

+

execution_profile is the execution profile to use for this request. It can be a key to a profile configured +via Cluster.add_execution_profile() or an instance (from Session.execution_profile_clone_update(), +for example

+

paging_state is an optional paging state, reused from a previous ResultSet.

+

host is the cassandra.pool.Host that should handle the query. If the host specified is down or +not yet connected, the query will fail with NoHostAvailable. Using this is +discouraged except in a few cases, e.g., querying node-local tables and applying schema changes.

+

execute_as the user that will be used on the server to execute the request. This is only available +on a DSE cluster.

+
+ +
+
+execute_async(statement[, parameters][, trace][, custom_payload][, paging_state][, host][, execute_as])
+

Execute the given query and return a ResponseFuture object +which callbacks may be attached to for asynchronous response +delivery. You may also call result() +on the ResponseFuture to synchronously block for results at +any time.

+

See Session.execute() for parameter definitions.

+

Example usage:

+
>>> session = cluster.connect()
+>>> future = session.execute_async("SELECT * FROM mycf")
+
+>>> def log_results(results):
+...     for row in results:
+...         log.info("Results: %s", row)
+
+>>> def log_error(exc):
+>>>     log.error("Operation failed: %s", exc)
+
+>>> future.add_callbacks(log_results, log_error)
+
+
+

Async execution with blocking wait for results:

+
>>> future = session.execute_async("SELECT * FROM mycf")
+>>> # do other stuff...
+
+>>> try:
+...     results = future.result()
+... except Exception:
+...     log.exception("Operation failed:")
+
+
+
+ +
+
+execute_graph(statement[, parameters][, trace][, execution_profile=EXEC_PROFILE_GRAPH_DEFAULT][, execute_as])
+

Executes a Gremlin query string or GraphStatement synchronously, +and returns a ResultSet from this execution.

+

parameters is dict of named parameters to bind. The values must be +JSON-serializable.

+

execution_profile: Selects an execution profile for the request.

+

execute_as the user that will be used on the server to execute the request.

+
+ +
+
+execute_graph_async(statement[, parameters][, trace][, execution_profile=EXEC_PROFILE_GRAPH_DEFAULT][, execute_as])
+

Execute the graph query and return a ResponseFuture +object which callbacks may be attached to for asynchronous response delivery. You may also call ResponseFuture.result() to synchronously block for +results at any time.

+
+ +
+
+prepare(statement)
+

Prepares a query string, returning a PreparedStatement +instance which can be used as follows:

+
>>> session = cluster.connect("mykeyspace")
+>>> query = "INSERT INTO users (id, name, age) VALUES (?, ?, ?)"
+>>> prepared = session.prepare(query)
+>>> session.execute(prepared, (user.id, user.name, user.age))
+
+
+

Or you may bind values to the prepared statement ahead of time:

+
>>> prepared = session.prepare(query)
+>>> bound_stmt = prepared.bind((user.id, user.name, user.age))
+>>> session.execute(bound_stmt)
+
+
+

Of course, prepared statements may (and should) be reused:

+
>>> prepared = session.prepare(query)
+>>> for user in users:
+...     bound = prepared.bind((user.id, user.name, user.age))
+...     session.execute(bound)
+
+
+

Alternatively, if protocol_version is 5 or higher +(requires Cassandra 4.0+), the keyspace can be specified as a +parameter. This will allow you to avoid specifying the keyspace in the +query without specifying a keyspace in connect(). It +even will let you prepare and use statements against a keyspace other +than the one originally specified on connection:

+
>>> analyticskeyspace_prepared = session.prepare(
+...     "INSERT INTO user_activity id, last_activity VALUES (?, ?)",
+...     keyspace="analyticskeyspace")  # note the different keyspace
+
+
+

Important: PreparedStatements should be prepared only once. +Preparing the same query more than once will likely affect performance.

+

custom_payload is a key value map to be passed along with the prepare +message. See Custom Payloads.

+
+ +
+
+shutdown()
+

Close all connections. Session instances should not be used +for any purpose after being shutdown.

+
+ +
+
+set_keyspace(keyspace)
+

Set the default keyspace for all queries made through this Session. +This operation blocks until complete.

+
+ +
+
+get_execution_profile(name)
+

Returns the execution profile associated with the provided name.

+
+
Parameters
+

name – The name (or key) of the execution profile.

+
+
+
+ +
+
+execution_profile_clone_update(ep, **kwargs)
+

Returns a clone of the ep profile. kwargs can be specified to update attributes +of the returned profile.

+

This is a shallow clone, so any objects referenced by the profile are shared. This means Load Balancing Policy +is maintained by inclusion in the active profiles. It also means updating any other rich objects will be seen +by the active profile. In cases where this is not desirable, be sure to replace the instance instead of manipulating +the shared object.

+
+ +
+
+add_request_init_listener(fn, *args, **kwargs)
+

Adds a callback with arguments to be called when any request is created.

+

It will be invoked as fn(response_future, *args, **kwargs) after each client request is created, +and before the request is sent. This can be used to create extensions by adding result callbacks to the +response future.

+

response_future is the ResponseFuture for the request.

+

Note that the init callback is done on the client thread creating the request, so you may need to consider +synchronization if you have multiple threads. Any callbacks added to the response future will be executed +on the event loop thread, so the normal advice about minimizing cycles and avoiding blocking apply (see Note in +ResponseFuture.add_callbacks().

+

See this example in the +source tree for an example.

+
+ +
+
+remove_request_init_listener(fn, *args, **kwargs)
+

Removes a callback and arguments from the list.

+

See Session.add_request_init_listener().

+
+ +
+ +
+
+class cassandra.cluster.ResponseFuture
+

An asynchronous response delivery mechanism that is returned from calls +to Session.execute_async().

+
+
There are two ways for results to be delivered:
+
+
+
+
+query = None
+
+ +
+
+result()
+

Return the final result or raise an Exception if errors were +encountered. If the final result or error has not been set +yet, this method will block until it is set, or the timeout +set for the request expires.

+

Timeout is specified in the Session request execution functions. +If the timeout is exceeded, an cassandra.OperationTimedOut will be raised. +This is a client-side timeout. For more information +about server-side coordinator timeouts, see policies.RetryPolicy.

+

Example usage:

+
>>> future = session.execute_async("SELECT * FROM mycf")
+>>> # do other stuff...
+
+>>> try:
+...     rows = future.result()
+...     for row in rows:
+...         ... # process results
+... except Exception:
+...     log.exception("Operation failed:")
+
+
+
+ +
+
+get_query_trace()
+

Fetches and returns the query trace of the last response, or None if tracing was +not enabled.

+

Note that this may raise an exception if there are problems retrieving the trace +details from Cassandra. If the trace is not available after max_wait, +cassandra.query.TraceUnavailable will be raised.

+

If the ResponseFuture is not done (async execution) and you try to retrieve the trace, +cassandra.query.TraceUnavailable will be raised.

+

query_cl is the consistency level used to poll the trace tables.

+
+ +
+
+get_all_query_traces()
+

Fetches and returns the query traces for all query pages, if tracing was enabled.

+

See note in get_query_trace() regarding possible exceptions.

+
+ +
+
+custom_payload
+

The custom payload returned from the server, if any. This will only be +set by Cassandra servers implementing a custom QueryHandler, and only +for protocol_version 4+.

+

Ensure the future is complete before trying to access this property +(call result(), or after callback is invoked). +Otherwise it may throw if the response has not been received.

+
+
Returns
+

Custom Payloads.

+
+
+
+ +
+
+is_schema_agreed = True
+
+ +
+
+has_more_pages
+

Returns True if there are more pages left in the +query results, False otherwise. This should only +be checked after the first page has been returned.

+
+

New in version 2.0.0.

+
+
+ +
+
+warnings
+

Warnings returned from the server, if any. This will only be +set for protocol_version 4+.

+

Warnings may be returned for such things as oversized batches, +or too many tombstones in slice queries.

+

Ensure the future is complete before trying to access this property +(call result(), or after callback is invoked). +Otherwise it may throw if the response has not been received.

+
+ +
+
+start_fetching_next_page()
+

If there are more pages left in the query result, this asynchronously +starts fetching the next page. If there are no pages left, QueryExhausted +is raised. Also see has_more_pages.

+

This should only be called after the first page has been returned.

+
+

New in version 2.0.0.

+
+
+ +
+
+add_callback(fn, *args, **kwargs)
+

Attaches a callback function to be called when the final results arrive.

+

By default, fn will be called with the results as the first and only +argument. If *args or **kwargs are supplied, they will be passed +through as additional positional or keyword arguments to fn.

+

If an error is hit while executing the operation, a callback attached +here will not be called. Use add_errback() or add_callbacks() +if you wish to handle that case.

+

If the final result has already been seen when this method is called, +the callback will be called immediately (before this method returns).

+

Note: in the case that the result is not available when the callback is added, +the callback is executed by IO event thread. This means that the callback +should not block or attempt further synchronous requests, because no further +IO will be processed until the callback returns.

+

Important: if the callback you attach results in an exception being +raised, the exception will be ignored, so please ensure your +callback handles all error cases that you care about.

+

Usage example:

+
>>> session = cluster.connect("mykeyspace")
+
+>>> def handle_results(rows, start_time, should_log=False):
+...     if should_log:
+...         log.info("Total time: %f", time.time() - start_time)
+...     ...
+
+>>> future = session.execute_async("SELECT * FROM users")
+>>> future.add_callback(handle_results, time.time(), should_log=True)
+
+
+
+ +
+
+add_errback(fn, *args, **kwargs)
+

Like add_callback(), but handles error cases. +An Exception instance will be passed as the first positional argument +to fn.

+
+ +
+
+ResponseFuture.add_callbacks(callback, errback, callback_args=(), callback_kwargs=None, errback_args=(), errback_args=None)
+

A convenient combination of add_callback() and +add_errback().

+

Example usage:

+
>>> session = cluster.connect()
+>>> query = "SELECT * FROM mycf"
+>>> future = session.execute_async(query)
+
+>>> def log_results(results, level='debug'):
+...     for row in results:
+...         log.log(level, "Result: %s", row)
+
+>>> def log_error(exc, query):
+...     log.error("Query '%s' failed: %s", query, exc)
+
+>>> future.add_callbacks(
+...     callback=log_results, callback_kwargs={'level': 'info'},
+...     errback=log_error, errback_args=(query,))
+
+
+
+ +
+ +
+
+class cassandra.cluster.ResultSet
+

An iterator over the rows from a query result. Also supplies basic equality +and indexing methods for backward-compatability. These methods materialize +the entire result set (loading all pages), and should only be used if the +total result size is understood. Warnings are emitted when paged results +are materialized in this fashion.

+

You can treat this as a normal iterator over rows:

+
>>> from cassandra.query import SimpleStatement
+>>> statement = SimpleStatement("SELECT * FROM users", fetch_size=10)
+>>> for user_row in session.execute(statement):
+...     process_user(user_row)
+
+
+

Whenever there are no more rows in the current page, the next page will +be fetched transparently. However, note that it is possible for +an Exception to be raised while fetching the next page, just +like you might see on a normal call to session.execute().

+
+
+all()
+

Returns all the remaining rows as a list. This is basically +a convenient shortcut to list(result_set).

+

This function is not recommended for queries that return a large number of elements.

+
+ +
+
+property current_rows
+

The list of current page rows. May be empty if the result was empty, +or this is the last page.

+
+ +
+
+fetch_next_page()
+

Manually, synchronously fetch the next page. Supplied for manually retrieving pages +and inspecting current_page(). It is not necessary to call this when iterating +through results; paging happens implicitly in iteration.

+
+ +
+
+get_all_query_traces(max_wait_sec_per=None)
+

Gets all query traces from the associated future. +See ResponseFuture.get_all_query_traces() for details.

+
+ +
+
+get_query_trace(max_wait_sec=None)
+

Gets the last query trace from the associated future. +See ResponseFuture.get_query_trace() for details.

+
+ +
+
+property has_more_pages
+

True if the last response indicated more pages; False otherwise

+
+ +
+
+one()
+

Return a single row of the results or None if empty. This is basically +a shortcut to result_set.current_rows[0] and should only be used when +you know a query returns a single row. Consider using an iterator if the +ResultSet contains more than one row.

+
+ +
+
+property paging_state
+

Server paging state of the query. Can be None if the query was not paged.

+

The driver treats paging state as opaque, but it may contain primary key data, so applications may want to +avoid sending this to untrusted parties.

+
+ +
+
+property was_applied
+

For LWT results, returns whether the transaction was applied.

+

Result is indeterminate if called on a result that was not an LWT request or on +a query.BatchStatement containing LWT. In the latter case either all the batch +succeeds or fails.

+

Only valid when one of the of the internal row factories is in use.

+
+ +
+ +
+
+exception cassandra.cluster.QueryExhausted
+

Raised when ResponseFuture.start_fetching_next_page() is called and +there are no more pages. You can check ResponseFuture.has_more_pages +before calling to avoid this.

+
+

New in version 2.0.0.

+
+
+ +
+
+exception cassandra.cluster.NoHostAvailable
+

Raised when an operation is attempted but all connections are +busy, defunct, closed, or resulted in errors when used.

+
+ +
+
+exception cassandra.cluster.UserTypeDoesNotExist
+

An attempt was made to use a user-defined type that does not exist.

+
+

New in version 2.1.0.

+
+
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/master/api/cassandra/concurrent.html b/master/api/cassandra/concurrent.html new file mode 100644 index 0000000000..e770148f45 --- /dev/null +++ b/master/api/cassandra/concurrent.html @@ -0,0 +1,711 @@ + + + + + + + + + + + + + cassandra.concurrent - Utilities for Concurrent Statement Execution | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for an unstable version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.concurrent - Utilities for Concurrent Statement Execution

+
+
+cassandra.concurrent.execute_concurrent(session, statements_and_parameters, concurrency=100, raise_on_first_error=True, results_generator=False, execution_profile=<object object>)
+

Executes a sequence of (statement, parameters) tuples concurrently. Each +parameters item must be a sequence or None.

+

The concurrency parameter controls how many statements will be executed +concurrently. When Cluster.protocol_version is set to 1 or 2, +it is recommended that this be kept below 100 times the number of +core connections per host times the number of connected hosts (see +Cluster.set_core_connections_per_host()). If that amount is exceeded, +the event loop thread may attempt to block on new connection creation, +substantially impacting throughput. If protocol_version +is 3 or higher, you can safely experiment with higher levels of concurrency.

+

If raise_on_first_error is left as True, execution will stop +after the first failed statement and the corresponding exception will be +raised.

+

results_generator controls how the results are returned.

+
    +
  • If False, the results are returned only after all requests have completed.

  • +
  • If True, a generator expression is returned. Using a generator results in a constrained +memory footprint when the results set will be large – results are yielded +as they return instead of materializing the entire list at once. The trade for lower memory +footprint is marginal CPU overhead (more thread coordination and sorting out-of-order results +on-the-fly).

  • +
+

execution_profile argument is the execution profile to use for this +request, it is passed directly to Session.execute_async().

+

A sequence of ExecutionResult(success, result_or_exc) namedtuples is returned +in the same order that the statements were passed in. If success is False, +there was an error executing the statement, and result_or_exc will be +an Exception. If success is True, result_or_exc +will be the query result.

+

Example usage:

+
select_statement = session.prepare("SELECT * FROM users WHERE id=?")
+
+statements_and_params = []
+for user_id in user_ids:
+    params = (user_id, )
+    statements_and_params.append((select_statement, params))
+
+results = execute_concurrent(
+    session, statements_and_params, raise_on_first_error=False)
+
+for (success, result) in results:
+    if not success:
+        handle_error(result)  # result will be an Exception
+    else:
+        process_user(result[0])  # result will be a list of rows
+
+
+

Note: in the case that generators are used, it is important to ensure the consumers do not +block or attempt further synchronous requests, because no further IO will be processed until +the consumer returns. This may also produce a deadlock in the IO event thread.

+
+ +
+
+cassandra.concurrent.execute_concurrent_with_args(session, statement, parameters, *args, **kwargs)
+

Like execute_concurrent(), but takes a single +statement and a sequence of parameters. Each item in parameters +should be a sequence or None.

+

Example usage:

+
statement = session.prepare("INSERT INTO mytable (a, b) VALUES (1, ?)")
+parameters = [(x,) for x in range(1000)]
+execute_concurrent_with_args(session, statement, parameters, concurrency=50)
+
+
+
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/master/api/cassandra/connection.html b/master/api/cassandra/connection.html new file mode 100644 index 0000000000..df86631f81 --- /dev/null +++ b/master/api/cassandra/connection.html @@ -0,0 +1,739 @@ + + + + + + + + + + + + + cassandra.connection - Low Level Connection Info | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for an unstable version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.connection - Low Level Connection Info

+
+
+exception cassandra.connection.ConnectionException
+

An unrecoverable error was hit when attempting to use a connection, +or the connection was already closed or defunct.

+
+ +
+
+exception cassandra.connection.ConnectionShutdown
+

Raised when a connection has been marked as defunct or has been closed.

+
+ +
+
+exception cassandra.connection.ConnectionBusy
+

An attempt was made to send a message through a Connection that +was already at the max number of in-flight operations.

+
+ +
+
+exception cassandra.connection.ProtocolError
+

Communication did not match the protocol that this driver expects.

+
+ +
+
+class cassandra.connection.EndPoint
+

Represents the information to connect to a cassandra node.

+
+
+property address
+

The IP address of the node. This is the RPC address the driver uses when connecting to the node

+
+ +
+
+property port
+

The port of the node.

+
+ +
+
+resolve()
+

Resolve the endpoint to an address/port. This is called +only on socket connection.

+
+ +
+
+property socket_family
+

The socket family of the endpoint.

+
+ +
+
+property ssl_options
+

SSL options specific to this endpoint.

+
+ +
+ +
+
+class cassandra.connection.EndPointFactory
+
+
+configure(cluster)
+

This is called by the cluster during its initialization.

+
+ +
+
+create(row)
+

Create an EndPoint from a system.peers row.

+
+ +
+ +
+
+class cassandra.connection.SniEndPoint(proxy_address, server_name, port=9042)
+

SNI Proxy EndPoint implementation.

+
+ +
+
+class cassandra.connection.SniEndPointFactory(proxy_address, port, node_domain=None)
+
+ +
+
+class cassandra.connection.UnixSocketEndPoint(unix_socket_path)
+

Unix Socket EndPoint implementation.

+
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/master/api/cassandra/cqlengine/columns.html b/master/api/cassandra/cqlengine/columns.html new file mode 100644 index 0000000000..cd495226ae --- /dev/null +++ b/master/api/cassandra/cqlengine/columns.html @@ -0,0 +1,957 @@ + + + + + + + + + + + + + cassandra.cqlengine.columns - Column types for object mapping models | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for an unstable version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.cqlengine.columns - Column types for object mapping models

+
+

Columns

+

Columns in your models map to columns in your CQL table. You define CQL columns by defining column attributes on your model classes. +For a model to be valid it needs at least one primary key column and one non-primary key column.

+

Just as in CQL, the order you define your columns in is important, and is the same order they are defined in on a model’s corresponding table.

+

Each column on your model definitions needs to be an instance of a Column class.

+
+
+class cassandra.cqlengine.columns.Column(**kwargs)
+
+
+primary_key = False
+

bool flag, indicates this column is a primary key. The first primary key defined +on a model is the partition key (unless partition keys are set), all others are cluster keys

+
+ +
+
+partition_key = False
+

indicates that this column should be the partition key, defining +more than one partition key column creates a compound partition key

+
+ +
+
+index = False
+

bool flag, indicates an index should be created for this column

+
+ +
+
+custom_index = False
+

bool flag, indicates an index is managed outside of cqlengine. This is +useful if you want to do filter queries on fields that have custom +indexes.

+
+ +
+
+db_field = None
+

the fieldname this field will map to in the database

+
+ +
+
+default = None
+

the default value, can be a value or a callable (no args)

+
+ +
+
+required = False
+

boolean, is the field required? Model validation will raise and +exception if required is set to True and there is a None value assigned

+
+ +
+
+clustering_order = None
+

only applicable on clustering keys (primary keys that are not partition keys) +determines the order that the clustering keys are sorted on disk

+
+ +
+
+discriminator_column = False
+

boolean, if set to True, this column will be used for discriminating records +of inherited models.

+

Should only be set on a column of an abstract model being used for inheritance.

+

There may only be one discriminator column per model. See __discriminator_value__ +for how to specify the value of this column on specialized models.

+
+ +
+
+static = False
+

boolean, if set to True, this is a static column, with a single value per partition

+
+ +
+ +
+
+

Column Types

+

Columns of all types are initialized by passing Column attributes to the constructor by keyword.

+
+
+class cassandra.cqlengine.columns.Ascii(**kwargs)
+

Stores a US-ASCII character string

+
+
Parameters
+
    +
  • min_length (int) – Sets the minimum length of this string, for validation purposes. +Defaults to 1 if this is a required column. Otherwise, None.

  • +
  • max_length (int) – Sets the maximum length of this string, for validation purposes.

  • +
+
+
+
+ +
+
+class cassandra.cqlengine.columns.BigInt(**kwargs)
+

Stores a 64-bit signed integer value

+
+ +
+
+class cassandra.cqlengine.columns.Blob(**kwargs)
+

Stores a raw binary value

+
+ +
+
+cassandra.cqlengine.columns.Bytes
+

alias of cassandra.cqlengine.columns.Blob

+
+ +
+
+class cassandra.cqlengine.columns.Boolean(**kwargs)
+

Stores a boolean True or False value

+
+ +
+
+class cassandra.cqlengine.columns.Counter(index=False, db_field=None, required=False)
+

Stores a counter that can be incremented and decremented

+
+ +
+
+class cassandra.cqlengine.columns.Date(**kwargs)
+

Stores a simple date, with no time-of-day

+
+

Changed in version 2.6.0: removed overload of Date and DateTime. DateTime is a drop-in replacement for legacy models

+
+

requires C* 2.2+ and protocol v4+

+
+ +
+
+class cassandra.cqlengine.columns.DateTime(**kwargs)
+

Stores a datetime value

+
+
+truncate_microseconds = False
+

Set this True to have model instances truncate the date, quantizing it in the same way it will be in the database. +This allows equality comparison between assigned values and values read back from the database:

+
DateTime.truncate_microseconds = True
+assert Model.create(id=0, d=datetime.utcnow()) == Model.objects(id=0).first()
+
+
+

Defaults to False to preserve legacy behavior. May change in the future.

+
+ +
+ +
+
+class cassandra.cqlengine.columns.Decimal(**kwargs)
+

Stores a variable precision decimal value

+
+ +
+
+class cassandra.cqlengine.columns.Double(**kwargs)
+

Stores a double-precision floating-point value

+
+ +
+
+class cassandra.cqlengine.columns.Float(primary_key=False, partition_key=False, index=False, db_field=None, default=None, required=False, clustering_order=None, discriminator_column=False, static=False, custom_index=False)
+

Stores a single-precision floating-point value

+
+ +
+
+class cassandra.cqlengine.columns.Integer(**kwargs)
+

Stores a 32-bit signed integer value

+
+ +
+
+class cassandra.cqlengine.columns.List(value_type, default=<class 'list'>, **kwargs)
+

Stores a list of ordered values

+

http://www.datastax.com/documentation/cql/3.1/cql/cql_using/use_list_t.html

+
+
Parameters
+

value_type – a column class indicating the types of the value

+
+
+
+ +
+
+class cassandra.cqlengine.columns.Map(key_type, value_type, default=<class 'dict'>, **kwargs)
+

Stores a key -> value map (dictionary)

+

https://docs.datastax.com/en/dse/6.7/cql/cql/cql_using/useMap.html

+
+
Parameters
+
    +
  • key_type – a column class indicating the types of the key

  • +
  • value_type – a column class indicating the types of the value

  • +
+
+
+
+ +
+
+class cassandra.cqlengine.columns.Set(value_type, strict=True, default=<class 'set'>, **kwargs)
+

Stores a set of unordered, unique values

+

http://www.datastax.com/documentation/cql/3.1/cql/cql_using/use_set_t.html

+
+
Parameters
+
    +
  • value_type – a column class indicating the types of the value

  • +
  • strict – sets whether non set values will be coerced to set +type on validation, or raise a validation error, defaults to True

  • +
+
+
+
+ +
+
+class cassandra.cqlengine.columns.SmallInt(**kwargs)
+

Stores a 16-bit signed integer value

+
+

New in version 2.6.0.

+
+

requires C* 2.2+ and protocol v4+

+
+ +
+
+class cassandra.cqlengine.columns.Text(min_length=None, max_length=None, **kwargs)
+

Stores a UTF-8 encoded string

+
+
Parameters
+
    +
  • min_length (int) – Sets the minimum length of this string, for validation purposes. +Defaults to 1 if this is a required column. Otherwise, None.

  • +
  • max_length (int) – Sets the maximum length of this string, for validation purposes.

  • +
+
+
+
+ +
+
+class cassandra.cqlengine.columns.Time(**kwargs)
+

Stores a timezone-naive time-of-day, with nanosecond precision

+
+

New in version 2.6.0.

+
+

requires C* 2.2+ and protocol v4+

+
+ +
+
+class cassandra.cqlengine.columns.TimeUUID(**kwargs)
+

UUID containing timestamp

+
+ +
+
+class cassandra.cqlengine.columns.TinyInt(**kwargs)
+

Stores an 8-bit signed integer value

+
+

New in version 2.6.0.

+
+

requires C* 2.2+ and protocol v4+

+
+ +
+
+class cassandra.cqlengine.columns.UserDefinedType(user_type, **kwargs)
+

User Defined Type column

+

http://www.datastax.com/documentation/cql/3.1/cql/cql_using/cqlUseUDT.html

+

These columns are represented by a specialization of cassandra.cqlengine.usertype.UserType.

+

Please see User Defined Types for examples and discussion.

+
+
Parameters
+

user_type (type) – specifies the UserType model of the column

+
+
+
+ +
+
+class cassandra.cqlengine.columns.UUID(**kwargs)
+

Stores a type 1 or 4 UUID

+
+ +
+
+class cassandra.cqlengine.columns.VarInt(**kwargs)
+

Stores an arbitrary-precision integer

+
+ +
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/master/api/cassandra/cqlengine/connection.html b/master/api/cassandra/cqlengine/connection.html new file mode 100644 index 0000000000..ec961d9f1a --- /dev/null +++ b/master/api/cassandra/cqlengine/connection.html @@ -0,0 +1,718 @@ + + + + + + + + + + + + + cassandra.cqlengine.connection - Connection management for cqlengine | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for an unstable version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.cqlengine.connection - Connection management for cqlengine

+
+
+cassandra.cqlengine.connection.default()
+

Configures the default connection to localhost, using the driver defaults +(except for row_factory)

+
+ +
+
+cassandra.cqlengine.connection.set_session(s)
+

Configures the default connection with a preexisting cassandra.cluster.Session

+

Note: the mapper presently requires a Session cassandra.cluster.Session.row_factory set to dict_factory. +This may be relaxed in the future

+
+ +
+
+cassandra.cqlengine.connection.setup(hosts, default_keyspace, consistency=None, lazy_connect=False, retry_connect=False, **kwargs)
+

Setup a the driver connection used by the mapper

+
+
Parameters
+
    +
  • hosts (list) – list of hosts, (contact_points for cassandra.cluster.Cluster)

  • +
  • default_keyspace (str) – The default keyspace to use

  • +
  • consistency (int) – The global default ConsistencyLevel - default is the same as Session.default_consistency_level

  • +
  • lazy_connect (bool) – True if should not connect until first use

  • +
  • retry_connect (bool) – True if we should retry to connect even if there was a connection failure initially

  • +
  • **kwargs – Pass-through keyword arguments for cassandra.cluster.Cluster

  • +
+
+
+
+ +
+
+cassandra.cqlengine.connection.register_connection(name, hosts=None, consistency=None, lazy_connect=False, retry_connect=False, cluster_options=None, default=False, session=None)
+

Add a connection to the connection registry. hosts and session are +mutually exclusive, and consistency, lazy_connect, +retry_connect, and cluster_options only work with hosts. Using +hosts will create a new cassandra.cluster.Cluster and +cassandra.cluster.Session.

+
+
Parameters
+
    +
  • hosts (list) – list of hosts, (contact_points for cassandra.cluster.Cluster).

  • +
  • consistency (int) – The default ConsistencyLevel for the +registered connection’s new session. Default is the same as +Session.default_consistency_level. For use with hosts only; +will fail when used with session.

  • +
  • lazy_connect (bool) – True if should not connect until first use. For +use with hosts only; will fail when used with session.

  • +
  • retry_connect (bool) – True if we should retry to connect even if there +was a connection failure initially. For use with hosts only; will +fail when used with session.

  • +
  • cluster_options (dict) – A dict of options to be used as keyword +arguments to cassandra.cluster.Cluster. For use with hosts +only; will fail when used with session.

  • +
  • default (bool) – If True, set the new connection as the cqlengine +default

  • +
  • session (Session) – A cassandra.cluster.Session to be used in +the created connection.

  • +
+
+
+
+ +
+
+cassandra.cqlengine.connection.unregister_connection(name)
+
+ +
+
+cassandra.cqlengine.connection.set_default_connection(name)
+
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/master/api/cassandra/cqlengine/management.html b/master/api/cassandra/cqlengine/management.html new file mode 100644 index 0000000000..12ed2965e7 --- /dev/null +++ b/master/api/cassandra/cqlengine/management.html @@ -0,0 +1,740 @@ + + + + + + + + + + + + + cassandra.cqlengine.management - Schema management for cqlengine | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for an unstable version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.cqlengine.management - Schema management for cqlengine

+

A collection of functions for managing keyspace and table schema.

+
+
+cassandra.cqlengine.management.create_keyspace_simple(name, replication_factor, durable_writes=True, connections=None)
+

Creates a keyspace with SimpleStrategy for replica placement

+

If the keyspace already exists, it will not be modified.

+

This function should be used with caution, especially in production environments. +Take care to execute schema modifications in a single context (i.e. not concurrently with other clients).

+

There are plans to guard schema-modifying functions with an environment-driven conditional.

+
+
Parameters
+
    +
  • name (str) – name of keyspace to create

  • +
  • replication_factor (int) – keyspace replication factor, used with SimpleStrategy

  • +
  • durable_writes (bool) – Write log is bypassed if set to False

  • +
  • connections (list) – List of connection names

  • +
+
+
+
+ +
+
+cassandra.cqlengine.management.create_keyspace_network_topology(name, dc_replication_map, durable_writes=True, connections=None)
+

Creates a keyspace with NetworkTopologyStrategy for replica placement

+

If the keyspace already exists, it will not be modified.

+

This function should be used with caution, especially in production environments. +Take care to execute schema modifications in a single context (i.e. not concurrently with other clients).

+

There are plans to guard schema-modifying functions with an environment-driven conditional.

+
+
Parameters
+
    +
  • name (str) – name of keyspace to create

  • +
  • dc_replication_map (dict) – map of dc_names: replication_factor

  • +
  • durable_writes (bool) – Write log is bypassed if set to False

  • +
  • connections (list) – List of connection names

  • +
+
+
+
+ +
+
+cassandra.cqlengine.management.drop_keyspace(name, connections=None)
+

Drops a keyspace, if it exists.

+

There are plans to guard schema-modifying functions with an environment-driven conditional.

+

This function should be used with caution, especially in production environments. +Take care to execute schema modifications in a single context (i.e. not concurrently with other clients).

+
+
Parameters
+
    +
  • name (str) – name of keyspace to drop

  • +
  • connections (list) – List of connection names

  • +
+
+
+
+ +
+
+cassandra.cqlengine.management.sync_table(model, keyspaces=None, connections=None)
+

Inspects the model and creates / updates the corresponding table and columns.

+

If keyspaces is specified, the table will be synched for all specified keyspaces. +Note that the Model.__keyspace__ is ignored in that case.

+

If connections is specified, the table will be synched for all specified connections. Note that the Model.__connection__ is ignored in that case. +If not specified, it will try to get the connection from the Model.

+

Any User Defined Types used in the table are implicitly synchronized.

+

This function can only add fields that are not part of the primary key.

+

Note that the attributes removed from the model are not deleted on the database. +They become effectively ignored by (will not show up on) the model.

+

This function should be used with caution, especially in production environments. +Take care to execute schema modifications in a single context (i.e. not concurrently with other clients).

+

There are plans to guard schema-modifying functions with an environment-driven conditional.

+
+ +
+
+cassandra.cqlengine.management.sync_type(ks_name, type_model, connection=None)
+

Inspects the type_model and creates / updates the corresponding type.

+

Note that the attributes removed from the type_model are not deleted on the database (this operation is not supported). +They become effectively ignored by (will not show up on) the type_model.

+

This function should be used with caution, especially in production environments. +Take care to execute schema modifications in a single context (i.e. not concurrently with other clients).

+

There are plans to guard schema-modifying functions with an environment-driven conditional.

+
+ +
+
+cassandra.cqlengine.management.drop_table(model, keyspaces=None, connections=None)
+

Drops the table indicated by the model, if it exists.

+

If keyspaces is specified, the table will be dropped for all specified keyspaces. Note that the Model.__keyspace__ is ignored in that case.

+

If connections is specified, the table will be synched for all specified connections. Note that the Model.__connection__ is ignored in that case. +If not specified, it will try to get the connection from the Model.

+

This function should be used with caution, especially in production environments. +Take care to execute schema modifications in a single context (i.e. not concurrently with other clients).

+

There are plans to guard schema-modifying functions with an environment-driven conditional.

+
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/master/api/cassandra/cqlengine/models.html b/master/api/cassandra/cqlengine/models.html new file mode 100644 index 0000000000..e0d23974bc --- /dev/null +++ b/master/api/cassandra/cqlengine/models.html @@ -0,0 +1,945 @@ + + + + + + + + + + + + + cassandra.cqlengine.models - Table models for object mapping | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for an unstable version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.cqlengine.models - Table models for object mapping

+
+

Model

+
+
+class cassandra.cqlengine.models.Model(\*\*kwargs)
+

The initializer creates an instance of the model. Pass in keyword arguments for columns you’ve defined on the model.

+
class Person(Model):
+    id = columns.UUID(primary_key=True)
+    first_name  = columns.Text()
+    last_name = columns.Text()
+
+person = Person(first_name='Blake', last_name='Eggleston')
+person.first_name  #returns 'Blake'
+person.last_name  #returns 'Eggleston'
+
+
+

Model attributes define how the model maps to tables in the database. These are class variables that should be set +when defining Model deriviatives.

+
+
+__abstract__ = False
+

Optional. Indicates that this model is only intended to be used as a base class for other models. +You can’t create tables for abstract models, but checks around schema validity are skipped during class construction.

+
+ +
+
+__table_name__ = None
+

Optional. Sets the name of the CQL table for this model. If left blank, the table name will be the name of the model, with it’s module name as it’s prefix. Manually defined table names are not inherited.

+
+ +
+
+__table_name_case_sensitive__ = False
+

Optional. By default, __table_name__ is case insensitive. Set this to True if you want to preserve the case sensitivity.

+
+ +
+
+__keyspace__ = None
+

Sets the name of the keyspace used by this model.

+
+ +
+
+__connection__ = None
+

Sets the name of the default connection used by this model.

+
+ +
+
+__default_ttl__ = None
+

Will be deprecated in release 4.0. You can set the default ttl by configuring the table __options__. See Default TTL and Per Query TTL for more details.

+
+ +
+
+__discriminator_value__ = None
+

Optional Specifies a value for the discriminator column when using model inheritance.

+

See Model Inheritance for usage examples.

+
+ +

Each table can have its own set of configuration options, including compaction. Unspecified, these default to sensible values in +the server. To override defaults, set options using the model __options__ attribute, which allows options specified a dict.

+

When a table is synced, it will be altered to match the options set on your table. +This means that if you are changing settings manually they will be changed back on resync.

+

Do not use the options settings of cqlengine if you want to manage your compaction settings manually.

+

See the list of supported table properties for more information.

+
+
+__options__
+

For example:

+
class User(Model):
+    __options__ = {'compaction': {'class': 'LeveledCompactionStrategy',
+                                  'sstable_size_in_mb': '64',
+                                  'tombstone_threshold': '.2'},
+                   'comment': 'User data stored here'}
+
+    user_id = columns.UUID(primary_key=True)
+    name = columns.Text()
+
+
+

or :

+
class TimeData(Model):
+    __options__ = {'compaction': {'class': 'SizeTieredCompactionStrategy',
+                                  'bucket_low': '.3',
+                                  'bucket_high': '2',
+                                  'min_threshold': '2',
+                                  'max_threshold': '64',
+                                  'tombstone_compaction_interval': '86400'},
+                   'gc_grace_seconds': '0'}
+
+
+
+ +
+
+__compute_routing_key__ = True
+

Optional Setting False disables computing the routing key for TokenAwareRouting

+
+ +

The base methods allow creating, storing, and querying modeled objects.

+
+
+classmethod create(**kwargs)
+

Create an instance of this model in the database.

+

Takes the model column values as keyword arguments. Setting a value to +None is equivalent to running a CQL DELETE on that column.

+

Returns the instance.

+
+ +
+
+if_not_exists()
+

Check the existence of an object before insertion. The existence of an +object is determined by its primary key(s). And please note using this flag +would incur performance cost.

+

If the insertion isn’t applied, a LWTException is raised.

+
try:
+    TestIfNotExistsModel.if_not_exists().create(id=id, count=9, text='111111111111')
+except LWTException as e:
+    # handle failure case
+    print e.existing  # dict containing LWT result fields
+
+
+

This method is supported on Cassandra 2.0 or later.

+
+ +
+
+if_exists()
+

Check the existence of an object before an update or delete. The existence of an +object is determined by its primary key(s). And please note using this flag +would incur performance cost.

+

If the update or delete isn’t applied, a LWTException is raised.

+
try:
+    TestIfExistsModel.objects(id=id).if_exists().update(count=9, text='111111111111')
+except LWTException as e:
+    # handle failure case
+    pass
+
+
+

This method is supported on Cassandra 2.0 or later.

+
+ +
+
+save()
+

Saves an object to the database.

+
#create a person instance
+person = Person(first_name='Kimberly', last_name='Eggleston')
+#saves it to Cassandra
+person.save()
+
+
+
+ +
+
+update(**values)
+

Performs an update on the model instance. You can pass in values to set on the model +for updating, or you can call without values to execute an update against any modified +fields. If no fields on the model have been modified since loading, no query will be +performed. Model validation is performed normally. Setting a value to None is +equivalent to running a CQL DELETE on that column.

+

It is possible to do a blind update, that is, to update a field without having first selected the object out of the database. +See Blind Updates

+
+ +
+
+iff(**values)
+

Checks to ensure that the values specified are correct on the Cassandra cluster. +Simply specify the column(s) and the expected value(s). As with if_not_exists, +this incurs a performance cost.

+

If the insertion isn’t applied, a LWTException is raised.

+
t = TestTransactionModel(text='some text', count=5)
+try:
+     t.iff(count=5).update('other text')
+except LWTException as e:
+    # handle failure case
+    print e.existing # existing object
+
+
+
+ +
+
+classmethod get(*args, **kwargs)
+

Returns a single object based on the passed filter constraints.

+

This is a pass-through to the model objects().:method:~cqlengine.queries.get.

+
+ +
+
+classmethod filter(*args, **kwargs)
+

Returns a queryset based on filter parameters.

+

This is a pass-through to the model objects().:method:~cqlengine.queries.filter.

+
+ +
+
+classmethod all()
+

Returns a queryset representing all stored objects

+

This is a pass-through to the model objects().all()

+
+ +
+
+delete()
+

Deletes the object from the database

+
+ +
+
+batch(batch_object)
+

Sets the batch object to run instance updates and inserts queries with.

+

See Batch Queries for usage examples

+
+ +
+
+timeout(timeout)
+

Sets a timeout for use in save(), update(), and delete() +operations

+
+ +
+
+timestamp(timedelta_or_datetime)
+

Sets the timestamp for the query

+
+ +
+
+ttl(ttl_in_sec)
+

Sets the ttl values to run instance updates and inserts queries with.

+
+ +
+
+using(connection=None)
+

Change the context on the fly of the model instance (keyspace, connection)

+
+ +
+
+classmethod column_family_name(include_keyspace=True)
+

Returns the column family name if it’s been defined +otherwise, it creates it from the module and class name

+
+ +

Models also support dict-like access:

+
+
+len(m)
+

Returns the number of columns defined in the model

+
+ +
+
+m[col_name]
+

Returns the value of column col_name

+
+ +
+
+m[col_name] = value
+

Set m[col_name] to value

+
+ +
+
+keys()
+

Returns a list of column IDs.

+
+ +
+
+values()
+

Returns list of column values.

+
+ +
+
+items()
+

Returns a list of column ID/value tuples.

+
+ +
+ +
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/master/api/cassandra/cqlengine/query.html b/master/api/cassandra/cqlengine/query.html new file mode 100644 index 0000000000..44f7b0c5dc --- /dev/null +++ b/master/api/cassandra/cqlengine/query.html @@ -0,0 +1,1041 @@ + + + + + + + + + + + + + cassandra.cqlengine.query - Query and filter model objects | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for an unstable version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.cqlengine.query - Query and filter model objects

+
+

QuerySet

+

QuerySet objects are typically obtained by calling objects() on a model class. +The methods here are used to filter, order, and constrain results.

+
+
+class cassandra.cqlengine.query.ModelQuerySet(model)
+
+
+all()
+

Returns a queryset matching all rows

+
for user in User.objects().all():
+    print(user)
+
+
+
+ +
+
+batch(batch_obj)
+

Set a batch object to run the query on.

+

Note: running a select query with a batch object will raise an exception

+
+ +
+
+consistency(consistency)
+

Sets the consistency level for the operation. See ConsistencyLevel.

+
for user in User.objects(id=3).consistency(CL.ONE):
+    print(user)
+
+
+
+ +
+
+count()
+

Returns the number of rows matched by this query.

+

Note: This function executes a SELECT COUNT() and has a performance cost on large datasets

+
+ +
+
+len(queryset)
+

Returns the number of rows matched by this query. This function uses count() internally.

+

Note: This function executes a SELECT COUNT() and has a performance cost on large datasets

+
+ +
+
+distinct(distinct_fields=None)
+

Returns the DISTINCT rows matched by this query.

+

distinct_fields default to the partition key fields if not specified.

+

Note: distinct_fields must be a partition key or a static column

+
class Automobile(Model):
+    manufacturer = columns.Text(partition_key=True)
+    year = columns.Integer(primary_key=True)
+    model = columns.Text(primary_key=True)
+    price = columns.Decimal()
+
+sync_table(Automobile)
+
+# create rows
+
+Automobile.objects.distinct()
+
+# or
+
+Automobile.objects.distinct(['manufacturer'])
+
+
+
+ +
+
+filter(*args, **kwargs)
+

Adds WHERE arguments to the queryset, returning a new queryset

+

See Retrieving objects with filters

+

Returns a QuerySet filtered on the keyword arguments

+
+ +
+
+get(*args, **kwargs)
+

Returns a single instance matching this query, optionally with additional filter kwargs.

+

See Retrieving objects with filters

+

Returns a single object matching the QuerySet.

+
user = User.get(id=1)
+
+
+

If no objects are matched, a DoesNotExist exception is raised.

+

If more than one object is found, a MultipleObjectsReturned exception is raised.

+
+ +
+
+limit(v)
+

Limits the number of results returned by Cassandra. Use 0 or None to disable.

+

Note that CQL’s default limit is 10,000, so all queries without a limit set explicitly will have an implicit limit of 10,000

+
# Fetch 100 users
+for user in User.objects().limit(100):
+    print(user)
+
+# Fetch all users
+for user in User.objects().limit(None):
+    print(user)
+
+
+
+ +
+
+fetch_size(v)
+

Sets the number of rows that are fetched at a time.

+

Note that driver’s default fetch size is 5000.

+
for user in User.objects().fetch_size(500):
+    print(user)
+
+
+
+ +
+
+if_not_exists()
+

Check the existence of an object before insertion.

+

If the insertion isn’t applied, a LWTException is raised.

+
+ +
+
+if_exists()
+

Check the existence of an object before an update or delete.

+

If the update or delete isn’t applied, a LWTException is raised.

+
+ +
+
+order_by(*colnames)
+

Sets the column(s) to be used for ordering

+

Default order is ascending, prepend a ‘-’ to any column name for descending

+

Note: column names must be a clustering key

+
from uuid import uuid1,uuid4
+
+class Comment(Model):
+    photo_id = UUID(primary_key=True)
+    comment_id = TimeUUID(primary_key=True, default=uuid1) # second primary key component is a clustering key
+    comment = Text()
+
+sync_table(Comment)
+
+u = uuid4()
+for x in range(5):
+    Comment.create(photo_id=u, comment="test %d" % x)
+
+print("Normal")
+for comment in Comment.objects(photo_id=u):
+    print comment.comment_id
+
+print("Reversed")
+for comment in Comment.objects(photo_id=u).order_by("-comment_id"):
+    print comment.comment_id
+
+
+
+ +
+
+allow_filtering()
+

Enables the (usually) unwise practive of querying on a clustering key without also defining a partition key

+
+ +
+
+only(fields)
+

Load only these fields for the returned query

+
+ +
+
+defer(fields)
+

Don’t load these fields for the returned query

+
+ +
+
+timestamp(timestamp)
+

Allows for custom timestamps to be saved with the record.

+
+ +
+
+ttl(ttl)
+

Sets the ttl (in seconds) for modified data.

+

Note that running a select query with a ttl value will raise an exception

+
+ +
+
+using(keyspace=None, connection=None)
+

Change the context on-the-fly of the Model class (keyspace, connection)

+
+ +
+
+update(**values)
+

Performs an update on the row selected by the queryset. Include values to update in the +update like so:

+
Model.objects(key=n).update(value='x')
+
+
+

Passing in updates for columns which are not part of the model will raise a ValidationError.

+

Per column validation will be performed, but instance level validation will not +(i.e., Model.validate is not called). This is sometimes referred to as a blind update.

+

For example:

+
class User(Model):
+    id = Integer(primary_key=True)
+    name = Text()
+
+setup(["localhost"], "test")
+sync_table(User)
+
+u = User.create(id=1, name="jon")
+
+User.objects(id=1).update(name="Steve")
+
+# sets name to null
+User.objects(id=1).update(name=None)
+
+
+

Also supported is blindly adding and removing elements from container columns, +without loading a model instance from Cassandra.

+

Using the syntax .update(column_name={x, y, z}) will overwrite the contents of the container, like updating a +non container column. However, adding __<operation> to the end of the keyword arg, makes the update call add +or remove items from the collection, without overwriting then entire column.

+

Given the model below, here are the operations that can be performed on the different container columns:

+
class Row(Model):
+    row_id      = columns.Integer(primary_key=True)
+    set_column  = columns.Set(Integer)
+    list_column = columns.List(Integer)
+    map_column  = columns.Map(Integer, Integer)
+
+
+

Set

+
    +
  • add: adds the elements of the given set to the column

  • +
  • remove: removes the elements of the given set to the column

  • +
+
# add elements to a set
+Row.objects(row_id=5).update(set_column__add={6})
+
+# remove elements to a set
+Row.objects(row_id=5).update(set_column__remove={4})
+
+
+

List

+
    +
  • append: appends the elements of the given list to the end of the column

  • +
  • prepend: prepends the elements of the given list to the beginning of the column

  • +
+
# append items to a list
+Row.objects(row_id=5).update(list_column__append=[6, 7])
+
+# prepend items to a list
+Row.objects(row_id=5).update(list_column__prepend=[1, 2])
+
+
+

Map

+
    +
  • update: adds the given keys/values to the columns, creating new entries if they didn’t exist, and overwriting old ones if they did

  • +
+
# add items to a map
+Row.objects(row_id=5).update(map_column__update={1: 2, 3: 4})
+
+# remove items from a map
+Row.objects(row_id=5).update(map_column__remove={1, 2})
+
+
+
+ +
+ +
+
+class cassandra.cqlengine.query.BatchQuery(batch_type=None, timestamp=None, consistency=None, execute_on_exception=False, timeout=<object object>, connection=None)
+

Handles the batching of queries

+

http://docs.datastax.com/en/cql/3.0/cql/cql_reference/batch_r.html

+

See Batch Queries for more details.

+
+
Parameters
+
    +
  • batch_type (BatchType, str or None) – (optional) One of batch type values available through BatchType enum

  • +
  • timestamp (datetime or timedelta or None) – (optional) A datetime or timedelta object with desired timestamp to be applied +to the batch conditional.

  • +
  • consistency (The ConsistencyLevel to be used for the batch query, or None.) – (optional) One of consistency values (“ANY”, “ONE”, “QUORUM” etc)

  • +
  • execute_on_exception (bool) – (Defaults to False) Indicates that when the BatchQuery instance is used +as a context manager the queries accumulated within the context must be executed despite +encountering an error within the context. By default, any exception raised from within +the context scope will cause the batched queries not to be executed.

  • +
  • timeout (float or None) – (optional) Timeout for the entire batch (in seconds), if not specified fallback +to default session timeout

  • +
  • connection (str) – Connection name to use for the batch execution

  • +
+
+
+
+
+add_query(query)
+
+ +
+
+execute()
+
+ +
+
+add_callback(fn, *args, **kwargs)
+

Add a function and arguments to be passed to it to be executed after the batch executes.

+

A batch can support multiple callbacks.

+

Note, that if the batch does not execute, the callbacks are not executed. +A callback, thus, is an “on batch success” handler.

+
+
Parameters
+
    +
  • fn (callable) – Callable object

  • +
  • *args – Positional arguments to be passed to the callback at the time of execution

  • +
  • **kwargs – Named arguments to be passed to the callback at the time of execution

  • +
+
+
+
+ +
+ +
+
+class cassandra.cqlengine.query.ContextQuery(*args, **kwargs)
+

A Context manager to allow a Model to switch context easily. Presently, the context only +specifies a keyspace for model IO.

+
+
Parameters
+
    +
  • *args – One or more models. A model should be a class type, not an instance.

  • +
  • **kwargs – (optional) Context parameters: can be keyspace or connection

  • +
+
+
+

For example:

+
with ContextQuery(Automobile, keyspace='test2') as A:
+    A.objects.create(manufacturer='honda', year=2008, model='civic')
+    print len(A.objects.all())  # 1 result
+
+with ContextQuery(Automobile, keyspace='test4') as A:
+    print len(A.objects.all())  # 0 result
+
+# Multiple models
+with ContextQuery(Automobile, Automobile2, connection='cluster2') as (A, A2):
+    print len(A.objects.all())
+    print len(A2.objects.all())
+
+
+
+ +
+
+class cassandra.cqlengine.query.DoesNotExist
+
+ +
+
+class cassandra.cqlengine.query.MultipleObjectsReturned
+
+ +
+
+class cassandra.cqlengine.query.LWTException(existing)
+

Lightweight conditional exception.

+

This exception will be raised when a write using an IF clause could not be +applied due to existing data violating the condition. The existing data is +available through the existing attribute.

+
+
Parameters
+

existing – The current state of the data which prevented the write.

+
+
+
+ +
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/master/api/cassandra/cqlengine/usertype.html b/master/api/cassandra/cqlengine/usertype.html new file mode 100644 index 0000000000..c899cff0a2 --- /dev/null +++ b/master/api/cassandra/cqlengine/usertype.html @@ -0,0 +1,684 @@ + + + + + + + + + + + + + cassandra.cqlengine.usertype - Model classes for User Defined Types | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for an unstable version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.cqlengine.usertype - Model classes for User Defined Types

+
+

UserType

+
+
+class cassandra.cqlengine.usertype.UserType(**values)
+

This class is used to model User Defined Types. To define a type, declare a class inheriting from this, +and assign field types as class attributes:

+
# connect with default keyspace ...
+
+from cassandra.cqlengine.columns import Text, Integer
+from cassandra.cqlengine.usertype import UserType
+
+class address(UserType):
+    street = Text()
+    zipcode = Integer()
+
+from cassandra.cqlengine import management
+management.sync_type(address)
+
+
+

Please see User Defined Types for a complete example and discussion.

+
+
+__type_name__ = None
+

Optional. Sets the name of the CQL type for this type.

+

If not specified, the type name will be the name of the class, with it’s module name as it’s prefix.

+
+ +
+ +
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/master/api/cassandra/datastax/graph/fluent/index.html b/master/api/cassandra/datastax/graph/fluent/index.html new file mode 100644 index 0000000000..c86f8f23da --- /dev/null +++ b/master/api/cassandra/datastax/graph/fluent/index.html @@ -0,0 +1,758 @@ + + + + + + + + + + + + + cassandra.datastax.graph.fluent | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for an unstable version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.datastax.graph.fluent

+
+
+class cassandra.datastax.graph.fluent.DseGraph
+

Dse Graph utility class for GraphTraversal construction and execution.

+
+
+DSE_GRAPH_QUERY_LANGUAGE = 'bytecode-json'
+

Graph query language, Default is ‘bytecode-json’ (GraphSON).

+
+ +
+
+static create_execution_profile(graph_name, graph_protocol=b'graphson-2.0', **kwargs)
+

Creates an ExecutionProfile for GraphTraversal execution. You need to register that execution profile to the +cluster by using cluster.add_execution_profile.

+
+
Parameters
+
    +
  • graph_name – The graph name

  • +
  • graph_protocol – (Optional) The graph protocol, default is DSE_GRAPH_QUERY_PROTOCOL.

  • +
+
+
+
+ +
+
+static query_from_traversal(traversal, graph_protocol=b'graphson-2.0', context=None)
+

From a GraphTraversal, return a query string based on the language specified in DseGraph.DSE_GRAPH_QUERY_LANGUAGE.

+
+
Parameters
+
    +
  • traversal – The GraphTraversal object

  • +
  • graph_protocol – The graph protocol. Default is DseGraph.DSE_GRAPH_QUERY_PROTOCOL.

  • +
  • context – The dict of the serialization context, needed for GraphSON3 (tuple, udt). +e.g: {‘cluster’: cluster, ‘graph_name’: name}

  • +
+
+
+
+ +
+
+static traversal_source(session=None, graph_name=None, execution_profile=EXEC_PROFILE_GRAPH_DEFAULT, traversal_class=None)
+

Returns a TinkerPop GraphTraversalSource binded to the session and graph_name if provided.

+
+
Parameters
+
    +
  • session – (Optional) A DSE session

  • +
  • graph_name – (Optional) DSE Graph name

  • +
  • execution_profile – (Optional) Execution profile for traversal queries. Default is set to EXEC_PROFILE_GRAPH_DEFAULT.

  • +
  • traversal_class – (Optional) The GraphTraversalSource class to use (DSL).

  • +
+
+
+
from cassandra.cluster import Cluster
+from cassandra.datastax.graph.fluent import DseGraph
+
+c = Cluster()
+session = c.connect()
+
+g = DseGraph.traversal_source(session, 'my_graph')
+print g.V().valueMap().toList()
+
+
+
+ +
+
+static batch(session=None, execution_profile=None)
+

Returns the cassandra.datastax.graph.fluent.query.TraversalBatch object allowing to +execute multiple traversals in the same transaction.

+
+ +
+ +
+
+class cassandra.datastax.graph.fluent.DSESessionRemoteGraphConnection(session[, graph_name, execution_profile])
+

A Tinkerpop RemoteConnection to execute traversal queries on DSE.

+
+
Parameters
+
    +
  • session – A DSE session

  • +
  • graph_name – (Optional) DSE Graph name.

  • +
  • execution_profile – (Optional) Execution profile for traversal queries. Default is set to EXEC_PROFILE_GRAPH_DEFAULT.

  • +
+
+
+
+ +
+
+class cassandra.datastax.graph.fluent.BaseGraphRowFactory(cluster)
+

Base row factory for graph traversal. This class basically wraps a +graphson reader function to handle additional features of Gremlin/DSE +and is callable as a normal row factory.

+
+
Currently supported:
    +
  • bulk results

  • +
+
+
+
+ +
+
+cassandra.datastax.graph.fluent.graph_traversal_row_factory
+

alias of cassandra.datastax.graph.fluent._GremlinGraphSON2RowFactory

+
+ +
+
+cassandra.datastax.graph.fluent.graph_traversal_dse_object_row_factory
+

alias of cassandra.datastax.graph.fluent._DseGraphSON2RowFactory

+
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/master/api/cassandra/datastax/graph/fluent/predicates.html b/master/api/cassandra/datastax/graph/fluent/predicates.html new file mode 100644 index 0000000000..d45d297844 --- /dev/null +++ b/master/api/cassandra/datastax/graph/fluent/predicates.html @@ -0,0 +1,754 @@ + + + + + + + + + + + + + cassandra.datastax.graph.fluent.predicates | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for an unstable version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.datastax.graph.fluent.predicates

+
+
+class cassandra.datastax.graph.fluent.predicates.Search
+
+
+static token(value)
+

Search any instance of a certain token within the text property targeted. +:param value: the value to look for.

+
+ +
+
+static token_prefix(value)
+

Search any instance of a certain token prefix withing the text property targeted. +:param value: the value to look for.

+
+ +
+
+static token_regex(value)
+

Search any instance of the provided regular expression for the targeted property. +:param value: the value to look for.

+
+ +
+
+static prefix(value)
+

Search for a specific prefix at the beginning of the text property targeted. +:param value: the value to look for.

+
+ +
+
+static regex(value)
+

Search for this regular expression inside the text property targeted. +:param value: the value to look for.

+
+ +
+
+static fuzzy(value, distance)
+

Search for a fuzzy string inside the text property targeted. +:param value: the value to look for. +:param distance: The distance for the fuzzy search. ie. 1, to allow a one-letter misspellings.

+
+ +
+
+static token_fuzzy(value, distance)
+

Search for a token fuzzy inside the text property targeted. +:param value: the value to look for. +:param distance: The distance for the token fuzzy search. ie. 1, to allow a one-letter misspellings.

+
+ +
+
+static phrase(value, proximity)
+

Search for a phrase inside the text property targeted. +:param value: the value to look for. +:param proximity: The proximity for the phrase search. ie. phrase(‘David Felcey’, 2).. to find ‘David Felcey’ with up to two middle names.

+
+ +
+ +
+
+class cassandra.datastax.graph.fluent.predicates.CqlCollection
+
+
+static contains(value)
+

Search for a value inside a cql list/set column. +:param value: the value to look for.

+
+ +
+
+static contains_value(value)
+

Search for a map value. +:param value: the value to look for.

+
+ +
+
+static contains_key(value)
+

Search for a map key. +:param value: the value to look for.

+
+ +
+
+static entry_eq(value)
+

Search for a map entry. +:param value: the value to look for.

+
+ +
+ +
+
+class cassandra.datastax.graph.fluent.predicates.Geo
+
+
+static inside(value, units=1)
+

Search any instance of geometry inside the Distance targeted. +:param value: A Distance to look for. +:param units: The units for value. See GeoUnit enum. (Can also +provide an integer to use as a multiplier to convert value to +degrees.)

+
+ +
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/master/api/cassandra/datastax/graph/fluent/query.html b/master/api/cassandra/datastax/graph/fluent/query.html new file mode 100644 index 0000000000..e5d05d1f83 --- /dev/null +++ b/master/api/cassandra/datastax/graph/fluent/query.html @@ -0,0 +1,705 @@ + + + + + + + + + + + + + cassandra.datastax.graph.fluent.query | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for an unstable version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.datastax.graph.fluent.query

+
+
+class cassandra.datastax.graph.fluent.query.TraversalBatch(session=None, execution_profile=None)
+

A TraversalBatch is used to execute multiple graph traversals in a +single transaction. If any traversal in the batch fails, the entire +batch will fail to apply.

+

If a TraversalBatch is bounded to a DSE session, it can be executed using +traversal_batch.execute().

+
+
Parameters
+
    +
  • session – (Optional) A DSE session

  • +
  • execution_profile – (Optional) The execution profile to use for the batch execution

  • +
+
+
+
+
+add(traversal)
+

Add a traversal to the batch.

+
+
Parameters
+

traversal – A gremlin GraphTraversal

+
+
+
+ +
+
+add_all(traversals)
+

Adds a sequence of traversals to the batch.

+
+
Parameters
+

traversals – A sequence of gremlin GraphTraversal

+
+
+
+ +
+
+execute()
+

Execute the traversal batch if bounded to a DSE Session.

+
+ +
+
+as_graph_statement(graph_protocol=b'graphson-2.0')
+

Return the traversal batch as GraphStatement.

+
+
Parameters
+

graph_protocol – The graph protocol for the GraphSONWriter. Default is GraphProtocol.GRAPHSON_2_0.

+
+
+
+ +
+
+clear()
+

Clear a traversal batch for reuse.

+
+ +
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/master/api/cassandra/datastax/graph/index.html b/master/api/cassandra/datastax/graph/index.html new file mode 100644 index 0000000000..77ee090c70 --- /dev/null +++ b/master/api/cassandra/datastax/graph/index.html @@ -0,0 +1,1036 @@ + + + + + + + + + + + + + cassandra.datastax.graph - Graph Statements, Options, and Row Factories | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for an unstable version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.datastax.graph - Graph Statements, Options, and Row Factories

+
+
+cassandra.datastax.graph.single_object_row_factory(column_names, rows)
+

returns the JSON string value of graph results

+
+ +
+
+cassandra.datastax.graph.graph_result_row_factory(column_names, rows)
+

Returns a Result object that can load graph results and produce specific types. +The Result JSON is deserialized and unpacked from the top-level ‘result’ dict.

+
+ +
+
+cassandra.datastax.graph.graph_object_row_factory(column_names, rows)
+

Like graph_result_row_factory(), except known element types (Vertex, Edge) are +converted to their simplified objects. Some low-level metadata is shed in this conversion. Unknown result types are +still returned as Result.

+
+ +
+
+cassandra.datastax.graph.graph_graphson2_row_factory(cluster)
+

Row factory to deserialize GraphSON2 results.

+
+ +
+
+cassandra.datastax.graph.graph_graphson3_row_factory(cluster)
+

Row factory to deserialize GraphSON3 results.

+
+ +
+
+cassandra.datastax.graph.to_int(value)
+

Wraps a value to be explicitly serialized as a graphson Int.

+
+ +
+
+cassandra.datastax.graph.to_bigint(value)
+

Wraps a value to be explicitly serialized as a graphson Bigint.

+
+ +
+
+cassandra.datastax.graph.to_smallint(value)
+

Wraps a value to be explicitly serialized as a graphson Smallint.

+
+ +
+
+cassandra.datastax.graph.to_float(value)
+

Wraps a value to be explicitly serialized as a graphson Float.

+
+ +
+
+cassandra.datastax.graph.to_double(value)
+

Wraps a value to be explicitly serialized as a graphson Double.

+
+ +
+
+class cassandra.datastax.graph.GraphProtocol
+
+
+GRAPHSON_1_0 = b'graphson-1.0'
+

GraphSON1

+
+ +
+
+GRAPHSON_2_0 = b'graphson-2.0'
+

GraphSON2

+
+ +
+
+GRAPHSON_3_0 = b'graphson-3.0'
+

GraphSON3

+
+ +
+ +
+
+class cassandra.datastax.graph.GraphOptions(**kwargs)
+

Options for DSE Graph Query handler.

+
+
+graph_name
+

name of the targeted graph.

+
+ +
+
+graph_source
+

choose the graph traversal source, configured on the server side.

+
+ +
+
+graph_language
+

the language used in the queries (default “gremlin-groovy”)

+
+ +
+
+graph_read_consistency_level
+

read cassandra.ConsistencyLevel for graph queries (if distinct from session default). +Setting this overrides the native Statement.consistency_level for read operations from Cassandra persistence

+
+ +
+
+graph_write_consistency_level
+

write cassandra.ConsistencyLevel for graph queries (if distinct from session default). +Setting this overrides the native Statement.consistency_level for write operations to Cassandra persistence.

+
+ +
+
+is_default_source
+
+ +
+
+is_analytics_source
+

True if graph_source is set to the server-defined analytics traversal source (‘a’)

+
+ +
+
+is_graph_source
+

True if graph_source is set to the server-defined graph traversal source (‘g’)

+
+ +
+
+set_source_default()
+

Sets graph_source to the server-defined default traversal source (‘default’)

+
+ +
+
+set_source_analytics()
+

Sets graph_source to the server-defined analytic traversal source (‘a’)

+
+ +
+
+set_source_graph()
+

Sets graph_source to the server-defined graph traversal source (‘g’)

+
+ +
+ +
+
+class cassandra.datastax.graph.SimpleGraphStatement(query_string, retry_policy=None, consistency_level=None, routing_key=None, serial_consistency_level=None, fetch_size=<object object>, keyspace=None, custom_payload=None, is_idempotent=False)
+

Simple graph statement for Session.execute_graph(). +Takes the same parameters as SimpleStatement.

+

query_string should be a literal CQL statement with the exception +of parameter placeholders that will be filled through the +parameters argument of Session.execute().

+

See Statement attributes for a description of the other parameters.

+
+ +
+
+class cassandra.datastax.graph.Result(value)
+

Represents deserialized graph results. +Property and item getters are provided for convenience.

+
+
+value = None
+

Deserialized value from the result

+
+ +
+
+as_vertex()
+

Return a Vertex parsed from this result

+

Raises TypeError if parsing fails (i.e. the result structure is not valid).

+
+ +
+
+as_edge()
+

Return a Edge parsed from this result

+

Raises TypeError if parsing fails (i.e. the result structure is not valid).

+
+ +
+
+as_path()
+

Return a Path parsed from this result

+

Raises TypeError if parsing fails (i.e. the result structure is not valid).

+
+ +
+ +
+
+class cassandra.datastax.graph.Vertex(id, label, type, properties)
+

Represents a Vertex element from a graph query.

+

Vertex properties are extracted into a dict of property names to list of VertexProperty (list +because they are always encoded that way, and sometimes have multiple cardinality; VertexProperty because sometimes +the properties themselves have property maps).

+
+ +
+
+class cassandra.datastax.graph.VertexProperty(label, value, properties=None)
+

Vertex properties have a top-level value and an optional dict of properties.

+
+
+label = None
+

label of the property

+
+ +
+
+value = None
+

Value of the property

+
+ +
+
+properties = None
+

dict of properties attached to the property

+
+ +
+ +
+
+class cassandra.datastax.graph.Edge(id, label, type, properties, inV, inVLabel, outV, outVLabel)
+

Represents an Edge element from a graph query.

+

Attributes match initializer parameters.

+
+ +
+
+class cassandra.datastax.graph.Path(labels, objects)
+

Represents a graph path.

+

Labels list is taken verbatim from the results.

+

Objects are either Result or Vertex/Edge for recognized types

+
+
+labels = None
+

List of labels in the path

+
+ +
+
+objects = None
+

List of objects in the path

+
+ +
+ +
+
+class cassandra.datastax.graph.T(name, val)
+

Represents a collection of tokens for more concise Traversal definitions.

+
+
+id = T.id
+
+ +
+
+key = T.key
+
+ +
+
+label = T.label
+
+ +
+
+value = T.value
+
+ +
+ +
+
+class cassandra.datastax.graph.GraphSON1Serializer
+

Serialize python objects to graphson types.

+
+ +
+
+class cassandra.datastax.graph.GraphSON1Deserializer
+

Deserialize graphson1 types to python objects.

+
+
+classmethod deserialize_date(value)
+
+ +
+
+classmethod deserialize_timestamp(value)
+
+ +
+
+classmethod deserialize_time(value)
+
+ +
+
+classmethod deserialize_duration(value)
+
+ +
+
+classmethod deserialize_int(value)
+
+ +
+
+classmethod deserialize_bigint(value)
+
+ +
+
+classmethod deserialize_double(value)
+
+ +
+
+classmethod deserialize_float(value)
+
+ +
+
+classmethod deserialize_uuid(value)
+
+ +
+
+classmethod deserialize_blob(value)
+
+ +
+
+classmethod deserialize_decimal(value)
+
+ +
+
+classmethod deserialize_point(value)
+
+ +
+
+classmethod deserialize_linestring(value)
+
+ +
+
+classmethod deserialize_polygon(value)
+
+ +
+ +
+
+class cassandra.datastax.graph.GraphSON2Reader(context, extra_deserializer_map=None)
+

GraphSON2 Reader that parse json and deserialize to python objects.

+
+
Parameters
+

extra_deserializer_map – map from GraphSON type tag to deserializer instance implementing deserialize

+
+
+
+
+read(json_data)
+

Read and deserialize json_data.

+
+ +
+
+deserialize(obj)
+

Deserialize GraphSON type-tagged dict values into objects mapped in self.deserializers

+
+ +
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/master/api/cassandra/decoder.html b/master/api/cassandra/decoder.html new file mode 100644 index 0000000000..3e3b0d3c8c --- /dev/null +++ b/master/api/cassandra/decoder.html @@ -0,0 +1,666 @@ + + + + + + + + + + + + + cassandra.decoder - Data Return Formats | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for an unstable version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.decoder - Data Return Formats

+
+
+cassandra.decoder.tuple_factory()
+

Deprecated in 2.0.0. Use cassandra.query.tuple_factory()

+
+ +
+
+cassandra.decoder.named_tuple_factory()
+

Deprecated in 2.0.0. Use cassandra.query.named_tuple_factory()

+
+ +
+
+cassandra.decoder.dict_factory()
+

Deprecated in 2.0.0. Use cassandra.query.dict_factory()

+
+ +
+
+cassandra.decoder.ordered_dict_factory()
+

Deprecated in 2.0.0. Use cassandra.query.ordered_dict_factory()

+
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/master/api/cassandra/encoder.html b/master/api/cassandra/encoder.html new file mode 100644 index 0000000000..f0bb241a94 --- /dev/null +++ b/master/api/cassandra/encoder.html @@ -0,0 +1,743 @@ + + + + + + + + + + + + + cassandra.encoder - Encoders for non-prepared Statements | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for an unstable version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.encoder - Encoders for non-prepared Statements

+
+
+class cassandra.encoder.Encoder
+

A container for mapping python types to CQL string literals when working +with non-prepared statements. The type mapping can be +directly customized by users.

+
+
+mapping = None
+

A map of python types to encoder functions.

+
+ +
+
+cql_encode_none()
+

Converts None to the string ‘NULL’.

+
+ +
+
+cql_encode_object()
+

Default encoder for all objects that do not have a specific encoder function +registered. This function simply calls str() on the object.

+
+ +
+
+cql_encode_all_types()
+

Converts any type into a CQL string, defaulting to cql_encode_object +if mapping does not contain an entry for the type.

+
+ +
+
+cql_encode_sequence()
+

Converts a sequence to a string of the form (item1, item2, ...). This +is suitable for IN value lists.

+
+ +
+
+cql_encode_str()
+

Escapes quotes in str objects.

+
+ +
+
+cql_encode_unicode()
+

Converts unicode objects to UTF-8 encoded strings with quote escaping.

+
+ +
+
+cql_encode_bytes()
+

Converts strings, buffers, and bytearrays into CQL blob literals.

+
+ +
+
+cql_encode_datetime()
+

Converts a datetime.datetime object to a (string) integer timestamp +with millisecond precision.

+
+ +
+
+cql_encode_date()
+

Converts a datetime.date object to a string with format +YYYY-MM-DD.

+
+ +
+
+cql_encode_map_collection()
+

Converts a dict into a string of the form {key1: val1, key2: val2, ...}. +This is suitable for map type columns.

+
+ +
+
+cql_encode_list_collection()
+

Converts a sequence to a string of the form [item1, item2, ...]. This +is suitable for list type columns.

+
+ +
+
+cql_encode_set_collection()
+

Converts a sequence to a string of the form {item1, item2, ...}. This +is suitable for set type columns.

+
+ +
+
+cql_encode_tuple()
+

Converts a sequence to a string of the form (item1, item2, ...). This +is suitable for tuple type columns.

+
+ +
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/master/api/cassandra/graph.html b/master/api/cassandra/graph.html new file mode 100644 index 0000000000..22cde23c5d --- /dev/null +++ b/master/api/cassandra/graph.html @@ -0,0 +1,1029 @@ + + + + + + + + + + + + + cassandra.graph - Graph Statements, Options, and Row Factories | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for an unstable version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.graph - Graph Statements, Options, and Row Factories

+
+

Note

+

This module is only for backward compatibility for dse-driver users. Consider using cassandra.datastax.graph.

+
+
+
+cassandra.graph.single_object_row_factory(column_names, rows)
+

returns the JSON string value of graph results

+
+ +
+
+cassandra.graph.graph_result_row_factory(column_names, rows)
+

Returns a Result object that can load graph results and produce specific types. +The Result JSON is deserialized and unpacked from the top-level ‘result’ dict.

+
+ +
+
+cassandra.graph.graph_object_row_factory(column_names, rows)
+

Like graph_result_row_factory(), except known element types (Vertex, Edge) are +converted to their simplified objects. Some low-level metadata is shed in this conversion. Unknown result types are +still returned as Result.

+
+ +
+
+cassandra.graph.graph_graphson2_row_factory(cluster)
+

Row factory to deserialize GraphSON2 results.

+
+ +
+
+cassandra.graph.graph_graphson3_row_factory(cluster)
+

Row factory to deserialize GraphSON3 results.

+
+ +
+
+cassandra.graph.to_int(value)
+

Wraps a value to be explicitly serialized as a graphson Int.

+
+ +
+
+cassandra.graph.to_bigint(value)
+

Wraps a value to be explicitly serialized as a graphson Bigint.

+
+ +
+
+cassandra.graph.to_smallint(value)
+

Wraps a value to be explicitly serialized as a graphson Smallint.

+
+ +
+
+cassandra.graph.to_float(value)
+

Wraps a value to be explicitly serialized as a graphson Float.

+
+ +
+
+cassandra.graph.to_double(value)
+

Wraps a value to be explicitly serialized as a graphson Double.

+
+ +
+
+class cassandra.graph.GraphProtocol
+
+
+GRAPHSON_1_0 = b'graphson-1.0'
+

GraphSON1

+
+ +
+
+GRAPHSON_2_0 = b'graphson-2.0'
+

GraphSON2

+
+ +
+
+GRAPHSON_3_0 = b'graphson-3.0'
+

GraphSON3

+
+ +
+ +
+
+class cassandra.graph.GraphOptions(**kwargs)
+

Options for DSE Graph Query handler.

+
+
+graph_name
+

name of the targeted graph.

+
+ +
+
+graph_source
+

choose the graph traversal source, configured on the server side.

+
+ +
+
+graph_language
+

the language used in the queries (default “gremlin-groovy”)

+
+ +
+
+graph_read_consistency_level
+

read cassandra.ConsistencyLevel for graph queries (if distinct from session default). +Setting this overrides the native Statement.consistency_level for read operations from Cassandra persistence

+
+ +
+
+graph_write_consistency_level
+

write cassandra.ConsistencyLevel for graph queries (if distinct from session default). +Setting this overrides the native Statement.consistency_level for write operations to Cassandra persistence.

+
+ +
+
+is_default_source
+
+ +
+
+is_analytics_source
+

True if graph_source is set to the server-defined analytics traversal source (‘a’)

+
+ +
+
+is_graph_source
+

True if graph_source is set to the server-defined graph traversal source (‘g’)

+
+ +
+
+set_source_default()
+

Sets graph_source to the server-defined default traversal source (‘default’)

+
+ +
+
+set_source_analytics()
+

Sets graph_source to the server-defined analytic traversal source (‘a’)

+
+ +
+
+set_source_graph()
+

Sets graph_source to the server-defined graph traversal source (‘g’)

+
+ +
+ +
+
+class cassandra.graph.SimpleGraphStatement(query_string, retry_policy=None, consistency_level=None, routing_key=None, serial_consistency_level=None, fetch_size=<object object>, keyspace=None, custom_payload=None, is_idempotent=False)
+

Simple graph statement for Session.execute_graph(). +Takes the same parameters as SimpleStatement.

+

query_string should be a literal CQL statement with the exception +of parameter placeholders that will be filled through the +parameters argument of Session.execute().

+

See Statement attributes for a description of the other parameters.

+
+ +
+
+class cassandra.graph.Result(value)
+

Represents deserialized graph results. +Property and item getters are provided for convenience.

+
+
+value = None
+

Deserialized value from the result

+
+ +
+
+as_vertex()
+

Return a Vertex parsed from this result

+

Raises TypeError if parsing fails (i.e. the result structure is not valid).

+
+ +
+
+as_edge()
+

Return a Edge parsed from this result

+

Raises TypeError if parsing fails (i.e. the result structure is not valid).

+
+ +
+
+as_path()
+

Return a Path parsed from this result

+

Raises TypeError if parsing fails (i.e. the result structure is not valid).

+
+ +
+ +
+
+class cassandra.graph.Vertex(id, label, type, properties)
+

Represents a Vertex element from a graph query.

+

Vertex properties are extracted into a dict of property names to list of VertexProperty (list +because they are always encoded that way, and sometimes have multiple cardinality; VertexProperty because sometimes +the properties themselves have property maps).

+
+ +
+
+class cassandra.graph.VertexProperty(label, value, properties=None)
+

Vertex properties have a top-level value and an optional dict of properties.

+
+
+label = None
+

label of the property

+
+ +
+
+value = None
+

Value of the property

+
+ +
+
+properties = None
+

dict of properties attached to the property

+
+ +
+ +
+
+class cassandra.graph.Edge(id, label, type, properties, inV, inVLabel, outV, outVLabel)
+

Represents an Edge element from a graph query.

+

Attributes match initializer parameters.

+
+ +
+
+class cassandra.graph.Path(labels, objects)
+

Represents a graph path.

+

Labels list is taken verbatim from the results.

+

Objects are either Result or Vertex/Edge for recognized types

+
+
+labels = None
+

List of labels in the path

+
+ +
+
+objects = None
+

List of objects in the path

+
+ +
+ +
+
+class cassandra.graph.GraphSON1Serializer
+

Serialize python objects to graphson types.

+
+ +
+
+class cassandra.graph.GraphSON1Deserializer
+

Deserialize graphson1 types to python objects.

+
+
+classmethod deserialize_date(value)
+
+ +
+
+classmethod deserialize_timestamp(value)
+
+ +
+
+classmethod deserialize_time(value)
+
+ +
+
+classmethod deserialize_duration(value)
+
+ +
+
+classmethod deserialize_int(value)
+
+ +
+
+classmethod deserialize_bigint(value)
+
+ +
+
+classmethod deserialize_double(value)
+
+ +
+
+classmethod deserialize_float(value)
+
+ +
+
+classmethod deserialize_uuid(value)
+
+ +
+
+classmethod deserialize_blob(value)
+
+ +
+
+classmethod deserialize_decimal(value)
+
+ +
+
+classmethod deserialize_point(value)
+
+ +
+
+classmethod deserialize_linestring(value)
+
+ +
+
+classmethod deserialize_polygon(value)
+
+ +
+ +
+
+class cassandra.graph.GraphSON2Reader(context, extra_deserializer_map=None)
+

GraphSON2 Reader that parse json and deserialize to python objects.

+
+
Parameters
+

extra_deserializer_map – map from GraphSON type tag to deserializer instance implementing deserialize

+
+
+
+
+read(json_data)
+

Read and deserialize json_data.

+
+ +
+
+deserialize(obj)
+

Deserialize GraphSON type-tagged dict values into objects mapped in self.deserializers

+
+ +
+ +
+
+class cassandra.graph.GraphSON3Reader(context, extra_deserializer_map=None)
+

GraphSON3 Reader that parse json and deserialize to python objects.

+
+
Parameters
+
    +
  • context – A dict of the context, mostly used as context for udt deserialization.

  • +
  • extra_deserializer_map – map from GraphSON type tag to deserializer instance implementing deserialize

  • +
+
+
+
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/master/api/cassandra/io/asyncioreactor.html b/master/api/cassandra/io/asyncioreactor.html new file mode 100644 index 0000000000..9b339ee719 --- /dev/null +++ b/master/api/cassandra/io/asyncioreactor.html @@ -0,0 +1,658 @@ + + + + + + + + + + + + + cassandra.io.asyncioreactor - asyncio Event Loop | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for an unstable version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.io.asyncioreactor - asyncio Event Loop

+
+
+class cassandra.io.asyncioreactor.AsyncioConnection(*args, **kwargs)
+

An experimental implementation of Connection that uses the +asyncio module in the Python standard library for its event loop.

+

Note that it requires asyncio features that were only introduced in the +3.4 line in 3.4.6, and in the 3.5 line in 3.5.1.

+
+
+classmethod initialize_reactor()
+

Called once by Cluster.connect(). This should be used by implementations +to set up any resources that will be shared across connections.

+
+ +
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/master/api/cassandra/io/asyncorereactor.html b/master/api/cassandra/io/asyncorereactor.html new file mode 100644 index 0000000000..88dee86e08 --- /dev/null +++ b/master/api/cassandra/io/asyncorereactor.html @@ -0,0 +1,663 @@ + + + + + + + + + + + + + cassandra.io.asyncorereactor - asyncore Event Loop | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for an unstable version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.io.asyncorereactor - asyncore Event Loop

+
+
+class cassandra.io.asyncorereactor.AsyncoreConnection(*args, **kwargs)
+

An implementation of Connection that uses the asyncore +module in the Python standard library for its event loop.

+
+
+classmethod initialize_reactor()
+

Called once by Cluster.connect(). This should be used by implementations +to set up any resources that will be shared across connections.

+
+ +
+
+classmethod handle_fork()
+

Called after a forking. This should cleanup any remaining reactor state +from the parent process.

+
+ +
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/master/api/cassandra/io/eventletreactor.html b/master/api/cassandra/io/eventletreactor.html new file mode 100644 index 0000000000..d210b26082 --- /dev/null +++ b/master/api/cassandra/io/eventletreactor.html @@ -0,0 +1,665 @@ + + + + + + + + + + + + + cassandra.io.eventletreactor - eventlet-compatible Connection | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for an unstable version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.io.eventletreactor - eventlet-compatible Connection

+
+
+class cassandra.io.eventletreactor.EventletConnection(*args, **kwargs)
+

An implementation of Connection that utilizes eventlet.

+

This implementation assumes all eventlet monkey patching is active. It is not tested with partial patching.

+
+
+classmethod initialize_reactor()
+

Called once by Cluster.connect(). This should be used by implementations +to set up any resources that will be shared across connections.

+
+ +
+
+classmethod service_timeouts()
+

cls._timeout_watcher runs in this loop forever. +It is usually waiting for the next timeout on the cls._new_timer Event. +When new timers are added, that event is set so that the watcher can +wake up and possibly set an earlier timeout.

+
+ +
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/master/api/cassandra/io/geventreactor.html b/master/api/cassandra/io/geventreactor.html new file mode 100644 index 0000000000..fe41f9cd9b --- /dev/null +++ b/master/api/cassandra/io/geventreactor.html @@ -0,0 +1,656 @@ + + + + + + + + + + + + + cassandra.io.geventreactor - gevent-compatible Event Loop | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for an unstable version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.io.geventreactor - gevent-compatible Event Loop

+
+
+class cassandra.io.geventreactor.GeventConnection(*args, **kwargs)
+

An implementation of Connection that utilizes gevent.

+

This implementation assumes all gevent monkey patching is active. It is not tested with partial patching.

+
+
+classmethod initialize_reactor()
+

Called once by Cluster.connect(). This should be used by implementations +to set up any resources that will be shared across connections.

+
+ +
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/master/api/cassandra/io/libevreactor.html b/master/api/cassandra/io/libevreactor.html new file mode 100644 index 0000000000..122eebc948 --- /dev/null +++ b/master/api/cassandra/io/libevreactor.html @@ -0,0 +1,648 @@ + + + + + + + + + + + + + cassandra.io.libevreactor - libev Event Loop | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for an unstable version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.io.libevreactor - libev Event Loop

+
+
+class cassandra.io.libevreactor.LibevConnection(*args, **kwargs)
+

An implementation of Connection that uses libev for its event loop.

+
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/master/api/cassandra/io/twistedreactor.html b/master/api/cassandra/io/twistedreactor.html new file mode 100644 index 0000000000..4c6ff1a38d --- /dev/null +++ b/master/api/cassandra/io/twistedreactor.html @@ -0,0 +1,649 @@ + + + + + + + + + + + + + cassandra.io.twistedreactor - Twisted Event Loop | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for an unstable version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.io.twistedreactor - Twisted Event Loop

+
+
+class cassandra.io.twistedreactor.TwistedConnection
+

An implementation of Connection that uses +Twisted’s reactor as its event loop.

+
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/master/api/cassandra/metadata.html b/master/api/cassandra/metadata.html new file mode 100644 index 0000000000..1d9e336eeb --- /dev/null +++ b/master/api/cassandra/metadata.html @@ -0,0 +1,1033 @@ + + + + + + + + + + + + + cassandra.metadata - Schema and Ring Topology | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for an unstable version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.metadata - Schema and Ring Topology

+
+
+cassandra.metadata.cql_keywords
+

set() -> new empty set object +set(iterable) -> new set object

+

Build an unordered collection of unique elements.

+
+ +
+
+cassandra.metadata.cql_keywords_unreserved
+

set() -> new empty set object +set(iterable) -> new set object

+

Build an unordered collection of unique elements.

+
+ +
+
+cassandra.metadata.cql_keywords_reserved
+

set() -> new empty set object +set(iterable) -> new set object

+

Build an unordered collection of unique elements.

+
+ +
+
+class cassandra.metadata.Metadata
+

Holds a representation of the cluster schema and topology.

+
+
+add_or_return_host(host)
+

Returns a tuple (host, new), where host is a Host +instance, and new is a bool indicating whether +the host was newly added.

+
+ +
+
+all_hosts()
+

Returns a list of all known Host instances in the cluster.

+
+ +
+
+export_schema_as_string()
+

Returns a string that can be executed as a query in order to recreate +the entire schema. The string is formatted to be human readable.

+
+ +
+
+get_host(endpoint_or_address, port=None)
+

Find a host in the metadata for a specific endpoint. If a string inet address and port are passed, +iterate all hosts to match the broadcast_rpc_address and +broadcast_rpc_port attributes.

+
+ +
+
+get_host_by_host_id(host_id)
+

Same as get_host() but use host_id for lookup.

+
+ +
+
+get_replicas(keyspace, key)
+

Returns a list of Host instances that are replicas for a given +partition key.

+
+ +
+ +
+

Schemas

+
+
+class cassandra.metadata.KeyspaceMetadata
+

A representation of the schema for a single keyspace.

+
+
+as_cql_query()
+

Returns a CQL query string that can be used to recreate just this keyspace, +not including user-defined types and tables.

+
+ +
+
+export_as_string()
+

Returns a CQL query string that can be used to recreate the entire keyspace, +including user-defined types and tables.

+
+ +
+ +
+
+class cassandra.metadata.UserType
+

A user defined type, as created by CREATE TYPE statements.

+

User-defined types were introduced in Cassandra 2.1.

+
+

New in version 2.1.0.

+
+
+
+as_cql_query(formatted=False)
+

Returns a CQL query that can be used to recreate this type. +If formatted is set to True, extra whitespace will +be added to make the query more readable.

+
+ +
+ +
+
+class cassandra.metadata.Function
+

A user defined function, as created by CREATE FUNCTION statements.

+

User-defined functions were introduced in Cassandra 2.2

+
+

New in version 2.6.0.

+
+
+
+as_cql_query(formatted=False)
+

Returns a CQL query that can be used to recreate this function. +If formatted is set to True, extra whitespace will +be added to make the query more readable.

+
+ +
+ +
+
+class cassandra.metadata.Aggregate
+

A user defined aggregate function, as created by CREATE AGGREGATE statements.

+

Aggregate functions were introduced in Cassandra 2.2

+
+

New in version 2.6.0.

+
+
+
+as_cql_query(formatted=False)
+

Returns a CQL query that can be used to recreate this aggregate. +If formatted is set to True, extra whitespace will +be added to make the query more readable.

+
+ +
+ +
+
+class cassandra.metadata.TableMetadata
+

A representation of the schema for a single table.

+
+
+as_cql_query(formatted=False)
+

Returns a CQL query that can be used to recreate this table (index +creations are not included). If formatted is set to True, +extra whitespace will be added to make the query human readable.

+
+ +
+
+export_as_string()
+

Returns a string of CQL queries that can be used to recreate this table +along with all indexes on it. The returned string is formatted to +be human readable.

+
+ +
+
+property is_cql_compatible
+

A boolean indicating if this table can be represented as CQL in export

+
+ +
+
+property primary_key
+

A list of ColumnMetadata representing the components of +the primary key for this table.

+
+ +
+ +
+
+class cassandra.metadata.TableMetadataV3
+

For C* 3.0+. option_maps take a superset of map names, so if nothing +changes structurally, new option maps can just be appended to the list.

+
+
+property is_cql_compatible
+

A boolean indicating if this table can be represented as CQL in export

+
+ +
+ +
+
+class cassandra.metadata.TableMetadataDSE68
+
+
+as_cql_query(formatted=False)
+

Returns a CQL query that can be used to recreate this table (index +creations are not included). If formatted is set to True, +extra whitespace will be added to make the query human readable.

+
+ +
+ +
+
+class cassandra.metadata.ColumnMetadata
+

A representation of a single column in a table.

+
+ +
+
+class cassandra.metadata.IndexMetadata
+

A representation of a secondary index on a column.

+
+
+as_cql_query()
+

Returns a CQL query that can be used to recreate this index.

+
+ +
+
+export_as_string()
+

Returns a CQL query string that can be used to recreate this index.

+
+ +
+ +
+
+class cassandra.metadata.MaterializedViewMetadata
+

A representation of a materialized view on a table

+
+
+as_cql_query(formatted=False)
+

Returns a CQL query that can be used to recreate this function. +If formatted is set to True, extra whitespace will +be added to make the query more readable.

+
+ +
+ +
+
+class cassandra.metadata.VertexMetadata
+

A representation of a vertex on a table

+
+ +
+
+class cassandra.metadata.EdgeMetadata
+

A representation of an edge on a table

+
+ +
+
+

Tokens and Ring Topology

+
+
+class cassandra.metadata.TokenMap
+

Information about the layout of the ring.

+
+
+get_replicas(keyspace, token)
+

Get a set of Host instances representing all of the +replica nodes for a given Token.

+
+ +
+ +
+
+class cassandra.metadata.Token
+

Abstract class representing a token.

+
+ +
+
+class cassandra.metadata.Murmur3Token(token)
+

A token for Murmur3Partitioner.

+

token is an int or string representing the token.

+
+ +
+
+class cassandra.metadata.MD5Token(token)
+

A token for RandomPartitioner.

+
+ +
+
+class cassandra.metadata.BytesToken(token)
+

A token for ByteOrderedPartitioner.

+
+
+classmethod from_string(token_string)
+

token_string should be the string representation from the server.

+
+ +
+ +
+
+cassandra.metadata.ReplicationStrategy
+

alias of cassandra.metadata._ReplicationStrategy

+
+ +
+
+class cassandra.metadata.ReplicationFactor(all_replicas, transient_replicas=None)
+

Represent the replication factor of a keyspace.

+
+ +
+
+class cassandra.metadata.SimpleStrategy(options_map)
+
+
+export_for_schema()
+

Returns a string version of these replication options which are +suitable for use in a CREATE KEYSPACE statement.

+
+ +
+
+property replication_factor
+

The replication factor for this keyspace.

+

For backward compatibility, this returns the +cassandra.metadata.ReplicationFactor.full_replicas value of +cassandra.metadata.SimpleStrategy.replication_factor_info.

+
+ +
+ +
+
+class cassandra.metadata.NetworkTopologyStrategy(dc_replication_factors)
+
+
+export_for_schema()
+

Returns a string version of these replication options which are +suitable for use in a CREATE KEYSPACE statement.

+
+ +
+ +
+
+class cassandra.metadata.LocalStrategy(options_map)
+
+
+export_for_schema()
+

Returns a string version of these replication options which are +suitable for use in a CREATE KEYSPACE statement.

+
+ +
+ +
+
+cassandra.metadata.group_keys_by_replica(session, keyspace, table, keys)
+

Returns a dict with the keys grouped per host. This can be +used to more accurately group by IN clause or to batch the keys per host.

+

If a valid replica is not found for a particular key it will be grouped under +NO_VALID_REPLICA

+

Example usage:

+
>>> result = group_keys_by_replica(
+...     session, "system", "peers",
+...     (("127.0.0.1", ), ("127.0.0.2", )))
+
+
+
+ +
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/master/api/cassandra/metrics.html b/master/api/cassandra/metrics.html new file mode 100644 index 0000000000..6c04b71df3 --- /dev/null +++ b/master/api/cassandra/metrics.html @@ -0,0 +1,756 @@ + + + + + + + + + + + + + cassandra.metrics - Performance Metrics | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for an unstable version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.metrics - Performance Metrics

+
+
+class cassandra.metrics.Metrics
+

A collection of timers and counters for various performance metrics.

+

Timer metrics are represented as floating point seconds.

+
+
+request_timer = None
+

A greplin.scales.PmfStat timer for requests. This is a dict-like +object with the following keys:

+
    +
  • count - number of requests that have been timed

  • +
  • min - min latency

  • +
  • max - max latency

  • +
  • mean - mean latency

  • +
  • stddev - standard deviation for latencies

  • +
  • median - median latency

  • +
  • 75percentile - 75th percentile latencies

  • +
  • 95percentile - 95th percentile latencies

  • +
  • 98percentile - 98th percentile latencies

  • +
  • 99percentile - 99th percentile latencies

  • +
  • 999percentile - 99.9th percentile latencies

  • +
+
+ +
+
+connection_errors = None
+

A greplin.scales.IntStat count of the number of times that a +request to a Cassandra node has failed due to a connection problem.

+
+ +
+
+write_timeouts = None
+

A greplin.scales.IntStat count of write requests that resulted +in a timeout.

+
+ +
+
+read_timeouts = None
+

A greplin.scales.IntStat count of read requests that resulted +in a timeout.

+
+ +
+
+unavailables = None
+

A greplin.scales.IntStat count of write or read requests that +failed due to an insufficient number of replicas being alive to meet +the requested ConsistencyLevel.

+
+ +
+
+other_errors = None
+

A greplin.scales.IntStat count of all other request failures, +including failures caused by invalid requests, bootstrapping nodes, +overloaded nodes, etc.

+
+ +
+
+retries = None
+

A greplin.scales.IntStat count of the number of times a +request was retried based on the RetryPolicy decision.

+
+ +
+
+ignores = None
+

A greplin.scales.IntStat count of the number of times a +failed request was ignored based on the RetryPolicy decision.

+
+ +
+
+known_hosts = None
+

A greplin.scales.IntStat count of the number of nodes in +the cluster that the driver is aware of, regardless of whether any +connections are opened to those nodes.

+
+ +
+
+connected_to = None
+

A greplin.scales.IntStat count of the number of nodes that +the driver currently has at least one connection open to.

+
+ +
+
+open_connections = None
+

A greplin.scales.IntStat count of the number connections +the driver currently has open.

+
+ +
+
+get_stats()
+

Returns the metrics for the registered cluster instance.

+
+ +
+
+set_stats_name(stats_name)
+

Set the metrics stats name. +The stats_name is a string used to access the metris through scales: scales.getStats()[<stats_name>] +Default is ‘cassandra-<num>’.

+
+ +
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/master/api/cassandra/policies.html b/master/api/cassandra/policies.html new file mode 100644 index 0000000000..412e56c0a5 --- /dev/null +++ b/master/api/cassandra/policies.html @@ -0,0 +1,1743 @@ + + + + + + + + + + + + + cassandra.policies - Load balancing and Failure Handling Policies | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for an unstable version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.policies - Load balancing and Failure Handling Policies

+
+

Load Balancing

+
+
+class cassandra.policies.HostDistance
+

A measure of how “distant” a node is from the client, which +may influence how the load balancer distributes requests +and how many connections are opened to the node.

+
+
+IGNORED = -1
+

A node with this distance should never be queried or have +connections opened to it.

+
+ +
+
+LOCAL = 0
+

Nodes with LOCAL distance will be preferred for operations +under some load balancing policies (such as DCAwareRoundRobinPolicy) +and will have a greater number of connections opened against +them by default.

+

This distance is typically used for nodes within the same +datacenter as the client.

+
+ +
+
+REMOTE = 1
+

Nodes with REMOTE distance will be treated as a last resort +by some load balancing policies (such as DCAwareRoundRobinPolicy) +and will have a smaller number of connections opened against +them by default.

+

This distance is typically used for nodes outside of the +datacenter that the client is running in.

+
+ +
+ +
+
+class cassandra.policies.LoadBalancingPolicy
+

Load balancing policies are used to decide how to distribute +requests among all possible coordinator nodes in the cluster.

+

In particular, they may focus on querying “near” nodes (those +in a local datacenter) or on querying nodes who happen to +be replicas for the requested data.

+

You may also use subclasses of LoadBalancingPolicy for +custom behavior.

+
+
+distance(host)
+

Returns a measure of how remote a Host is in +terms of the HostDistance enums.

+
+ +
+
+populate(cluster, hosts)
+

This method is called to initialize the load balancing +policy with a set of Host instances before its +first use. The cluster parameter is an instance of +Cluster.

+
+ +
+
+make_query_plan(working_keyspace=None, query=None)
+

Given a Statement instance, return a iterable +of Host instances which should be queried in that +order. A generator may work well for custom implementations +of this method.

+

Note that the query argument may be None when preparing +statements.

+

working_keyspace should be the string name of the current keyspace, +as set through Session.set_keyspace() or with a USE +statement.

+
+ +
+
+check_supported()
+

This will be called after the cluster Metadata has been initialized. +If the load balancing policy implementation cannot be supported for +some reason (such as a missing C extension), this is the point at +which it should raise an exception.

+
+ +
+ +
+
+class cassandra.policies.RoundRobinPolicy
+

A subclass of LoadBalancingPolicy which evenly +distributes queries across all nodes in the cluster, +regardless of what datacenter the nodes may be in.

+
+
+populate(cluster, hosts)
+

This method is called to initialize the load balancing +policy with a set of Host instances before its +first use. The cluster parameter is an instance of +Cluster.

+
+ +
+
+distance(host)
+

Returns a measure of how remote a Host is in +terms of the HostDistance enums.

+
+ +
+
+make_query_plan(working_keyspace=None, query=None)
+

Given a Statement instance, return a iterable +of Host instances which should be queried in that +order. A generator may work well for custom implementations +of this method.

+

Note that the query argument may be None when preparing +statements.

+

working_keyspace should be the string name of the current keyspace, +as set through Session.set_keyspace() or with a USE +statement.

+
+ +
+
+on_up(host)
+

Called when a node is marked up.

+
+ +
+
+on_down(host)
+

Called when a node is marked down.

+
+ +
+
+on_add(host)
+

Called when a node is added to the cluster. The newly added node +should be considered up.

+
+ +
+
+on_remove(host)
+

Called when a node is removed from the cluster.

+
+ +
+ +
+
+class cassandra.policies.DCAwareRoundRobinPolicy(local_dc='', used_hosts_per_remote_dc=0)
+

Similar to RoundRobinPolicy, but prefers hosts +in the local datacenter and only uses nodes in remote +datacenters as a last resort.

+

The local_dc parameter should be the name of the datacenter +(such as is reported by nodetool ring) that should +be considered local. If not specified, the driver will choose +a local_dc based on the first host among Cluster.contact_points +having a valid DC. If relying on this mechanism, all specified +contact points should be nodes in a single, local DC.

+

used_hosts_per_remote_dc controls how many nodes in +each remote datacenter will have connections opened +against them. In other words, used_hosts_per_remote_dc hosts +will be considered REMOTE and the +rest will be considered IGNORED. +By default, all remote hosts are ignored.

+
+
+populate(cluster, hosts)
+

This method is called to initialize the load balancing +policy with a set of Host instances before its +first use. The cluster parameter is an instance of +Cluster.

+
+ +
+
+distance(host)
+

Returns a measure of how remote a Host is in +terms of the HostDistance enums.

+
+ +
+
+make_query_plan(working_keyspace=None, query=None)
+

Given a Statement instance, return a iterable +of Host instances which should be queried in that +order. A generator may work well for custom implementations +of this method.

+

Note that the query argument may be None when preparing +statements.

+

working_keyspace should be the string name of the current keyspace, +as set through Session.set_keyspace() or with a USE +statement.

+
+ +
+
+on_up(host)
+

Called when a node is marked up.

+
+ +
+
+on_down(host)
+

Called when a node is marked down.

+
+ +
+
+on_add(host)
+

Called when a node is added to the cluster. The newly added node +should be considered up.

+
+ +
+
+on_remove(host)
+

Called when a node is removed from the cluster.

+
+ +
+ +
+
+class cassandra.policies.WhiteListRoundRobinPolicy(hosts)
+

A subclass of RoundRobinPolicy which evenly +distributes queries across all nodes in the cluster, +regardless of what datacenter the nodes may be in, but +only if that node exists in the list of allowed nodes

+

This policy is addresses the issue described in +https://datastax-oss.atlassian.net/browse/JAVA-145 +Where connection errors occur when connection +attempts are made to private IP addresses remotely

+

The hosts parameter should be a sequence of hosts to permit +connections to.

+
+
+populate(cluster, hosts)
+

This method is called to initialize the load balancing +policy with a set of Host instances before its +first use. The cluster parameter is an instance of +Cluster.

+
+ +
+
+distance(host)
+

Returns a measure of how remote a Host is in +terms of the HostDistance enums.

+
+ +
+
+on_up(host)
+

Called when a node is marked up.

+
+ +
+
+on_add(host)
+

Called when a node is added to the cluster. The newly added node +should be considered up.

+
+ +
+ +
+
+class cassandra.policies.TokenAwarePolicy(child_policy, shuffle_replicas=False)
+

A LoadBalancingPolicy wrapper that adds token awareness to +a child policy.

+

This alters the child policy’s behavior so that it first attempts to +send queries to LOCAL replicas (as determined +by the child policy) based on the Statement’s +routing_key. If shuffle_replicas is +truthy, these replicas will be yielded in a random order. Once those +hosts are exhausted, the remaining hosts in the child policy’s query +plan will be used in the order provided by the child policy.

+

If no routing_key is set on the query, the child +policy’s query plan will be used as is.

+
+
+shuffle_replicas = False
+

Yield local replicas in a random order.

+
+ +
+
+populate(cluster, hosts)
+

This method is called to initialize the load balancing +policy with a set of Host instances before its +first use. The cluster parameter is an instance of +Cluster.

+
+ +
+
+check_supported()
+

This will be called after the cluster Metadata has been initialized. +If the load balancing policy implementation cannot be supported for +some reason (such as a missing C extension), this is the point at +which it should raise an exception.

+
+ +
+
+distance(*args, **kwargs)
+

Returns a measure of how remote a Host is in +terms of the HostDistance enums.

+
+ +
+
+make_query_plan(working_keyspace=None, query=None)
+

Given a Statement instance, return a iterable +of Host instances which should be queried in that +order. A generator may work well for custom implementations +of this method.

+

Note that the query argument may be None when preparing +statements.

+

working_keyspace should be the string name of the current keyspace, +as set through Session.set_keyspace() or with a USE +statement.

+
+ +
+
+on_up(*args, **kwargs)
+

Called when a node is marked up.

+
+ +
+
+on_down(*args, **kwargs)
+

Called when a node is marked down.

+
+ +
+
+on_add(*args, **kwargs)
+

Called when a node is added to the cluster. The newly added node +should be considered up.

+
+ +
+
+on_remove(*args, **kwargs)
+

Called when a node is removed from the cluster.

+
+ +
+ +
+
+class cassandra.policies.HostFilterPolicy(child_policy, predicate)
+

A LoadBalancingPolicy subclass configured with a child policy, +and a single-argument predicate. This policy defers to the child policy for +hosts where predicate(host) is truthy. Hosts for which +predicate(host) is falsey will be considered IGNORED, and will +not be used in a query plan.

+

This can be used in the cases where you need a whitelist or blacklist +policy, e.g. to prepare for decommissioning nodes or for testing:

+
def address_is_ignored(host):
+    return host.address in [ignored_address0, ignored_address1]
+
+blacklist_filter_policy = HostFilterPolicy(
+    child_policy=RoundRobinPolicy(),
+    predicate=address_is_ignored
+)
+
+cluster = Cluster(
+    primary_host,
+    load_balancing_policy=blacklist_filter_policy,
+)
+
+
+

See the note in the make_query_plan() documentation for a caveat on +how wrapping ordering polices (e.g. RoundRobinPolicy) may break +desirable properties of the wrapped policy.

+

Please note that whitelist and blacklist policies are not recommended for +general, day-to-day use. You probably want something like +DCAwareRoundRobinPolicy, which prefers a local DC but has +fallbacks, over a brute-force method like whitelisting or blacklisting.

+
+
Parameters
+
    +
  • child_policy – an instantiated LoadBalancingPolicy +that this one will defer to.

  • +
  • predicate – a one-parameter function that takes a Host. +If it returns a falsey value, the Host will +be IGNORED and not returned in query plans.

  • +
+
+
+
+
+predicate(host)
+

A predicate, set on object initialization, that takes a Host +and returns a value. If the value is falsy, the Host is +IGNORED. If the value is truthy, +HostFilterPolicy defers to the child policy to determine the +host’s distance.

+

This is a read-only value set in __init__, implemented as a +property.

+
+ +
+
+distance(host)
+

Checks if predicate(host), then returns +IGNORED if falsey, and defers to the child policy +otherwise.

+
+ +
+
+make_query_plan(working_keyspace=None, query=None)
+

Defers to the child policy’s +LoadBalancingPolicy.make_query_plan() and filters the results.

+

Note that this filtering may break desirable properties of the wrapped +policy in some cases. For instance, imagine if you configure this +policy to filter out host2, and to wrap a round-robin policy that +rotates through three hosts in the order host1, host2, host3, +host2, host3, host1, host3, host1, host2, repeating. This +policy will yield host1, host3, host3, host1, host3, host1, +disproportionately favoring host3.

+
+ +
+ +
+
+class cassandra.policies.DefaultLoadBalancingPolicy(child_policy)
+

A LoadBalancingPolicy wrapper that adds the ability to target a specific host first.

+

If no host is set on the query, the child policy’s query plan will be used as is.

+
+
+populate(cluster, hosts)
+

This method is called to initialize the load balancing +policy with a set of Host instances before its +first use. The cluster parameter is an instance of +Cluster.

+
+ +
+
+make_query_plan(working_keyspace=None, query=None)
+

Given a Statement instance, return a iterable +of Host instances which should be queried in that +order. A generator may work well for custom implementations +of this method.

+

Note that the query argument may be None when preparing +statements.

+

working_keyspace should be the string name of the current keyspace, +as set through Session.set_keyspace() or with a USE +statement.

+
+ +
+ +
+
+class cassandra.policies.DSELoadBalancingPolicy(*args, **kwargs)
+

Deprecated: This will be removed in the next major release, +consider using DefaultLoadBalancingPolicy.

+
+ +
+
+

Translating Server Node Addresses

+
+
+class cassandra.policies.AddressTranslator
+

Interface for translating cluster-defined endpoints.

+

The driver discovers nodes using server metadata and topology change events. Normally, +the endpoint defined by the server is the right way to connect to a node. In some environments, +these addresses may not be reachable, or not preferred (public vs. private IPs in cloud environments, +suboptimal routing, etc). This interface allows for translating from server defined endpoints to +preferred addresses for driver connections.

+

Note: contact_points provided while creating the Cluster instance are not +translated using this mechanism – only addresses received from Cassandra nodes are.

+
+
+translate(addr)
+

Accepts the node ip address, and returns a translated address to be used connecting to this node.

+
+ +
+ +
+
+class cassandra.policies.IdentityTranslator
+

Returns the endpoint with no translation

+
+
+translate(addr)
+

Accepts the node ip address, and returns a translated address to be used connecting to this node.

+
+ +
+ +
+
+class cassandra.policies.EC2MultiRegionTranslator
+

Resolves private ips of the hosts in the same datacenter as the client, and public ips of hosts in other datacenters.

+
+
+translate(addr)
+

Reverse DNS the public broadcast_address, then lookup that hostname to get the AWS-resolved IP, which +will point to the private IP address within the same datacenter.

+
+ +
+ +
+
+

Marking Hosts Up or Down

+
+
+class cassandra.policies.ConvictionPolicy(host)
+

A policy which decides when hosts should be considered down +based on the types of failures and the number of failures.

+

If custom behavior is needed, this class may be subclassed.

+

host is an instance of Host.

+
+
+add_failure(connection_exc)
+

Implementations should return True if the host should be +convicted, False otherwise.

+
+ +
+
+reset()
+

Implementations should clear out any convictions or state regarding +the host.

+
+ +
+ +
+
+class cassandra.policies.SimpleConvictionPolicy(host)
+

The default implementation of ConvictionPolicy, +which simply marks a host as down after the first failure +of any kind.

+

host is an instance of Host.

+
+
+add_failure(connection_exc)
+

Implementations should return True if the host should be +convicted, False otherwise.

+
+ +
+
+reset()
+

Implementations should clear out any convictions or state regarding +the host.

+
+ +
+ +
+
+

Reconnecting to Dead Hosts

+
+
+class cassandra.policies.ReconnectionPolicy
+

This class and its subclasses govern how frequently an attempt is made +to reconnect to nodes that are marked as dead.

+

If custom behavior is needed, this class may be subclassed.

+
+
+new_schedule()
+

This should return a finite or infinite iterable of delays (each as a +floating point number of seconds) inbetween each failed reconnection +attempt. Note that if the iterable is finite, reconnection attempts +will cease once the iterable is exhausted.

+
+ +
+ +
+
+class cassandra.policies.ConstantReconnectionPolicy(delay, max_attempts=64)
+

A ReconnectionPolicy subclass which sleeps for a fixed delay +inbetween each reconnection attempt.

+

delay should be a floating point number of seconds to wait inbetween +each attempt.

+

max_attempts should be a total number of attempts to be made before +giving up, or None to continue reconnection attempts forever. +The default is 64.

+
+
+new_schedule()
+

This should return a finite or infinite iterable of delays (each as a +floating point number of seconds) inbetween each failed reconnection +attempt. Note that if the iterable is finite, reconnection attempts +will cease once the iterable is exhausted.

+
+ +
+ +
+
+class cassandra.policies.ExponentialReconnectionPolicy(base_delay, max_delay, max_attempts=64)
+

A ReconnectionPolicy subclass which exponentially increases +the length of the delay inbetween each reconnection attempt up to +a set maximum delay.

+

A random amount of jitter (+/- 15%) will be added to the pure exponential +delay value to avoid the situations where many reconnection handlers are +trying to reconnect at exactly the same time.

+

base_delay and max_delay should be in floating point units of +seconds.

+

max_attempts should be a total number of attempts to be made before +giving up, or None to continue reconnection attempts forever. +The default is 64.

+
+
+new_schedule()
+

This should return a finite or infinite iterable of delays (each as a +floating point number of seconds) inbetween each failed reconnection +attempt. Note that if the iterable is finite, reconnection attempts +will cease once the iterable is exhausted.

+
+ +
+ +
+
+

Retrying Failed Operations

+
+
+class cassandra.policies.WriteType
+

For usage with RetryPolicy, this describe a type +of write operation.

+
+
+SIMPLE = 0
+

A write to a single partition key. Such writes are guaranteed to be atomic +and isolated.

+
+ +
+
+BATCH = 1
+

A write to multiple partition keys that used the distributed batch log to +ensure atomicity.

+
+ +
+
+UNLOGGED_BATCH = 2
+

A write to multiple partition keys that did not use the distributed batch +log. Atomicity for such writes is not guaranteed.

+
+ +
+
+COUNTER = 3
+

A counter write (for one or multiple partition keys). Such writes should +not be replayed in order to avoid overcount.

+
+ +
+
+BATCH_LOG = 4
+

The initial write to the distributed batch log that Cassandra performs +internally before a BATCH write.

+
+ +
+
+CAS = 5
+

A lighweight-transaction write, such as “DELETE … IF EXISTS”.

+
+ +
+
+VIEW = 6
+

This WriteType is only seen in results for requests that were unable to +complete MV operations.

+
+ +
+
+CDC = 7
+

This WriteType is only seen in results for requests that were unable to +complete CDC operations.

+
+ +
+ +
+
+class cassandra.policies.RetryPolicy
+

A policy that describes whether to retry, rethrow, or ignore coordinator +timeout and unavailable failures. These are failures reported from the +server side. Timeouts are configured by +settings in cassandra.yaml. +Unavailable failures occur when the coordinator cannot acheive the consistency +level for a request. For further information see the method descriptions +below.

+

To specify a default retry policy, set the +Cluster.default_retry_policy attribute to an instance of this +class or one of its subclasses.

+

To specify a retry policy per query, set the Statement.retry_policy +attribute to an instance of this class or one of its subclasses.

+

If custom behavior is needed for retrying certain operations, +this class may be subclassed.

+
+
+RETRY = 0
+

This should be returned from the below methods if the operation +should be retried on the same connection.

+
+ +
+
+RETHROW = 1
+

This should be returned from the below methods if the failure +should be propagated and no more retries attempted.

+
+ +
+
+IGNORE = 2
+

This should be returned from the below methods if the failure +should be ignored but no more retries should be attempted.

+
+ +
+
+RETRY_NEXT_HOST = 3
+

This should be returned from the below methods if the operation +should be retried on another connection.

+
+ +
+
+on_read_timeout(query, consistency, required_responses, received_responses, data_retrieved, retry_num)
+

This is called when a read operation times out from the coordinator’s +perspective (i.e. a replica did not respond to the coordinator in time). +It should return a tuple with two items: one of the class enums (such +as RETRY) and a ConsistencyLevel to retry the +operation at or None to keep the same consistency level.

+

query is the Statement that timed out.

+

consistency is the ConsistencyLevel that the operation was +attempted at.

+

The required_responses and received_responses parameters describe +how many replicas needed to respond to meet the requested consistency +level and how many actually did respond before the coordinator timed +out the request. data_retrieved is a boolean indicating whether +any of those responses contained data (as opposed to just a digest).

+

retry_num counts how many times the operation has been retried, so +the first time this method is called, retry_num will be 0.

+

By default, operations will be retried at most once, and only if +a sufficient number of replicas responded (with data digests).

+
+ +
+
+on_write_timeout(query, consistency, write_type, required_responses, received_responses, retry_num)
+

This is called when a write operation times out from the coordinator’s +perspective (i.e. a replica did not respond to the coordinator in time).

+

query is the Statement that timed out.

+

consistency is the ConsistencyLevel that the operation was +attempted at.

+

write_type is one of the WriteType enums describing the +type of write operation.

+

The required_responses and received_responses parameters describe +how many replicas needed to acknowledge the write to meet the requested +consistency level and how many replicas actually did acknowledge the +write before the coordinator timed out the request.

+

retry_num counts how many times the operation has been retried, so +the first time this method is called, retry_num will be 0.

+

By default, failed write operations will retried at most once, and +they will only be retried if the write_type was +BATCH_LOG.

+
+ +
+
+on_unavailable(query, consistency, required_replicas, alive_replicas, retry_num)
+

This is called when the coordinator node determines that a read or +write operation cannot be successful because the number of live +replicas are too low to meet the requested ConsistencyLevel. +This means that the read or write operation was never forwarded to +any replicas.

+

query is the Statement that failed.

+

consistency is the ConsistencyLevel that the operation was +attempted at.

+

required_replicas is the number of replicas that would have needed to +acknowledge the operation to meet the requested consistency level. +alive_replicas is the number of replicas that the coordinator +considered alive at the time of the request.

+

retry_num counts how many times the operation has been retried, so +the first time this method is called, retry_num will be 0.

+

By default, if this is the first retry, it triggers a retry on the next +host in the query plan with the same consistency level. If this is not the +first retry, no retries will be attempted and the error will be re-raised.

+
+ +
+
+on_request_error(query, consistency, error, retry_num)
+

This is called when an unexpected error happens. This can be in the +following situations:

+
    +
  • On a connection error

  • +
  • On server errors: overloaded, isBootstrapping, serverError, etc.

  • +
+

query is the Statement that timed out.

+

consistency is the ConsistencyLevel that the operation was +attempted at.

+

error the instance of the exception.

+

retry_num counts how many times the operation has been retried, so +the first time this method is called, retry_num will be 0.

+

The default, it triggers a retry on the next host in the query plan +with the same consistency level.

+
+ +
+ +
+
+class cassandra.policies.FallthroughRetryPolicy
+

A retry policy that never retries and always propagates failures to +the application.

+
+
+on_read_timeout(*args, **kwargs)
+

This is called when a read operation times out from the coordinator’s +perspective (i.e. a replica did not respond to the coordinator in time). +It should return a tuple with two items: one of the class enums (such +as RETRY) and a ConsistencyLevel to retry the +operation at or None to keep the same consistency level.

+

query is the Statement that timed out.

+

consistency is the ConsistencyLevel that the operation was +attempted at.

+

The required_responses and received_responses parameters describe +how many replicas needed to respond to meet the requested consistency +level and how many actually did respond before the coordinator timed +out the request. data_retrieved is a boolean indicating whether +any of those responses contained data (as opposed to just a digest).

+

retry_num counts how many times the operation has been retried, so +the first time this method is called, retry_num will be 0.

+

By default, operations will be retried at most once, and only if +a sufficient number of replicas responded (with data digests).

+
+ +
+
+on_write_timeout(*args, **kwargs)
+

This is called when a write operation times out from the coordinator’s +perspective (i.e. a replica did not respond to the coordinator in time).

+

query is the Statement that timed out.

+

consistency is the ConsistencyLevel that the operation was +attempted at.

+

write_type is one of the WriteType enums describing the +type of write operation.

+

The required_responses and received_responses parameters describe +how many replicas needed to acknowledge the write to meet the requested +consistency level and how many replicas actually did acknowledge the +write before the coordinator timed out the request.

+

retry_num counts how many times the operation has been retried, so +the first time this method is called, retry_num will be 0.

+

By default, failed write operations will retried at most once, and +they will only be retried if the write_type was +BATCH_LOG.

+
+ +
+
+on_unavailable(*args, **kwargs)
+

This is called when the coordinator node determines that a read or +write operation cannot be successful because the number of live +replicas are too low to meet the requested ConsistencyLevel. +This means that the read or write operation was never forwarded to +any replicas.

+

query is the Statement that failed.

+

consistency is the ConsistencyLevel that the operation was +attempted at.

+

required_replicas is the number of replicas that would have needed to +acknowledge the operation to meet the requested consistency level. +alive_replicas is the number of replicas that the coordinator +considered alive at the time of the request.

+

retry_num counts how many times the operation has been retried, so +the first time this method is called, retry_num will be 0.

+

By default, if this is the first retry, it triggers a retry on the next +host in the query plan with the same consistency level. If this is not the +first retry, no retries will be attempted and the error will be re-raised.

+
+ +
+
+on_request_error(*args, **kwargs)
+

This is called when an unexpected error happens. This can be in the +following situations:

+
    +
  • On a connection error

  • +
  • On server errors: overloaded, isBootstrapping, serverError, etc.

  • +
+

query is the Statement that timed out.

+

consistency is the ConsistencyLevel that the operation was +attempted at.

+

error the instance of the exception.

+

retry_num counts how many times the operation has been retried, so +the first time this method is called, retry_num will be 0.

+

The default, it triggers a retry on the next host in the query plan +with the same consistency level.

+
+ +
+ +
+
+class cassandra.policies.DowngradingConsistencyRetryPolicy(*args, **kwargs)
+

Deprecated: This retry policy will be removed in the next major release.

+

A retry policy that sometimes retries with a lower consistency level than +the one initially requested.

+

BEWARE: This policy may retry queries using a lower consistency +level than the one initially requested. By doing so, it may break +consistency guarantees. In other words, if you use this retry policy, +there are cases (documented below) where a read at QUORUM +may not see a preceding write at QUORUM. Do not use this +policy unless you have understood the cases where this can happen and +are ok with that. It is also recommended to subclass this class so +that queries that required a consistency level downgrade can be +recorded (so that repairs can be made later, etc).

+

This policy implements the same retries as RetryPolicy, +but on top of that, it also retries in the following cases:

+
    +
  • On a read timeout: if the number of replicas that responded is +greater than one but lower than is required by the requested +consistency level, the operation is retried at a lower consistency +level.

  • +
  • On a write timeout: if the operation is an UNLOGGED_BATCH +and at least one replica acknowledged the write, the operation is +retried at a lower consistency level. Furthermore, for other +write types, if at least one replica acknowledged the write, the +timeout is ignored.

  • +
  • On an unavailable exception: if at least one replica is alive, the +operation is retried at a lower consistency level.

  • +
+

The reasoning behind this retry policy is as follows: if, based +on the information the Cassandra coordinator node returns, retrying the +operation with the initially requested consistency has a chance to +succeed, do it. Otherwise, if based on that information we know the +initially requested consistency level cannot be achieved currently, then:

+
    +
  • For writes, ignore the exception (thus silently failing the +consistency requirement) if we know the write has been persisted on at +least one replica.

  • +
  • For reads, try reading at a lower consistency level (thus silently +failing the consistency requirement).

  • +
+

In other words, this policy implements the idea that if the requested +consistency level cannot be achieved, the next best thing for writes is +to make sure the data is persisted, and that reading something is better +than reading nothing, even if there is a risk of reading stale data.

+
+
+on_read_timeout(query, consistency, required_responses, received_responses, data_retrieved, retry_num)
+

This is called when a read operation times out from the coordinator’s +perspective (i.e. a replica did not respond to the coordinator in time). +It should return a tuple with two items: one of the class enums (such +as RETRY) and a ConsistencyLevel to retry the +operation at or None to keep the same consistency level.

+

query is the Statement that timed out.

+

consistency is the ConsistencyLevel that the operation was +attempted at.

+

The required_responses and received_responses parameters describe +how many replicas needed to respond to meet the requested consistency +level and how many actually did respond before the coordinator timed +out the request. data_retrieved is a boolean indicating whether +any of those responses contained data (as opposed to just a digest).

+

retry_num counts how many times the operation has been retried, so +the first time this method is called, retry_num will be 0.

+

By default, operations will be retried at most once, and only if +a sufficient number of replicas responded (with data digests).

+
+ +
+
+on_write_timeout(query, consistency, write_type, required_responses, received_responses, retry_num)
+

This is called when a write operation times out from the coordinator’s +perspective (i.e. a replica did not respond to the coordinator in time).

+

query is the Statement that timed out.

+

consistency is the ConsistencyLevel that the operation was +attempted at.

+

write_type is one of the WriteType enums describing the +type of write operation.

+

The required_responses and received_responses parameters describe +how many replicas needed to acknowledge the write to meet the requested +consistency level and how many replicas actually did acknowledge the +write before the coordinator timed out the request.

+

retry_num counts how many times the operation has been retried, so +the first time this method is called, retry_num will be 0.

+

By default, failed write operations will retried at most once, and +they will only be retried if the write_type was +BATCH_LOG.

+
+ +
+
+on_unavailable(query, consistency, required_replicas, alive_replicas, retry_num)
+

This is called when the coordinator node determines that a read or +write operation cannot be successful because the number of live +replicas are too low to meet the requested ConsistencyLevel. +This means that the read or write operation was never forwarded to +any replicas.

+

query is the Statement that failed.

+

consistency is the ConsistencyLevel that the operation was +attempted at.

+

required_replicas is the number of replicas that would have needed to +acknowledge the operation to meet the requested consistency level. +alive_replicas is the number of replicas that the coordinator +considered alive at the time of the request.

+

retry_num counts how many times the operation has been retried, so +the first time this method is called, retry_num will be 0.

+

By default, if this is the first retry, it triggers a retry on the next +host in the query plan with the same consistency level. If this is not the +first retry, no retries will be attempted and the error will be re-raised.

+
+ +
+ +
+
+

Retrying Idempotent Operations

+
+
+class cassandra.policies.SpeculativeExecutionPolicy
+

Interface for specifying speculative execution plans

+
+
+new_plan(keyspace, statement)
+

Returns

+
+
Parameters
+
    +
  • keyspace

  • +
  • statement

  • +
+
+
Returns
+

+
+
+
+ +
+ +
+
+class cassandra.policies.ConstantSpeculativeExecutionPolicy(delay, max_attempts)
+

A speculative execution policy that sends a new query every X seconds (delay) for a maximum of Y attempts (max_attempts).

+
+
+new_plan(keyspace, statement)
+

Returns

+
+
Parameters
+
    +
  • keyspace

  • +
  • statement

  • +
+
+
Returns
+

+
+
+
+ +
+ +
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/master/api/cassandra/pool.html b/master/api/cassandra/pool.html new file mode 100644 index 0000000000..757e38e730 --- /dev/null +++ b/master/api/cassandra/pool.html @@ -0,0 +1,674 @@ + + + + + + + + + + + + + cassandra.pool - Hosts and Connection Pools | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for an unstable version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.pool - Hosts and Connection Pools

+

Connection pooling and host management.

+
+
+class cassandra.pool.Host
+

Represents a single Cassandra node.

+
+
+property address
+

The IP address of the endpoint. This is the RPC address the driver uses when connecting to the node.

+
+ +
+
+property datacenter
+

The datacenter the node is in.

+
+ +
+
+property rack
+

The rack the node is in.

+
+ +
+ +
+
+exception cassandra.pool.NoConnectionsAvailable
+

All existing connections to a given host are busy, or there are +no open connections.

+
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/master/api/cassandra/protocol.html b/master/api/cassandra/protocol.html new file mode 100644 index 0000000000..f1a428c189 --- /dev/null +++ b/master/api/cassandra/protocol.html @@ -0,0 +1,740 @@ + + + + + + + + + + + + + cassandra.protocol - Protocol Features | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for an unstable version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.protocol - Protocol Features

+
+

Custom Payloads

+

Native protocol version 4+ allows for a custom payload to be sent between clients +and custom query handlers. The payload is specified as a string:binary_type dict +holding custom key/value pairs.

+

By default these are ignored by the server. They can be useful for servers implementing +a custom QueryHandler.

+

See Session.execute(), :Session.execute_async(), ResponseFuture.custom_payload.

+
+
+class cassandra.protocol._ProtocolHandler
+

_ProtocolHander handles encoding and decoding messages.

+

This class can be specialized to compose Handlers which implement alternative +result decoding or type deserialization. Class definitions are passed to cassandra.cluster.Cluster +on initialization.

+

Contracted class methods are _ProtocolHandler.encode_message() and _ProtocolHandler.decode_message().

+
+
+message_types_by_opcode = {default mapping}
+
+ +
+
+classmethod encode_message(msg, stream_id, protocol_version, compressor, allow_beta_protocol_version)
+

Encodes a message using the specified frame parameters, and compressor

+
+
Parameters
+
    +
  • msg – the message, typically of cassandra.protocol._MessageType, generated by the driver

  • +
  • stream_id – protocol stream id for the frame header

  • +
  • protocol_version – version for the frame header, and used encoding contents

  • +
  • compressor – optional compression function to be used on the body

  • +
+
+
+
+ +
+
+classmethod decode_message(protocol_version, user_type_map, stream_id, flags, opcode, body, decompressor, result_metadata)
+

Decodes a native protocol message body

+
+
Parameters
+
    +
  • protocol_version – version to use decoding contents

  • +
  • user_type_map – map[keyspace name] = map[type name] = custom type to instantiate when deserializing this type

  • +
  • stream_id – native protocol stream id from the frame header

  • +
  • flags – native protocol flags bitmap from the header

  • +
  • opcode – native protocol opcode from the header

  • +
  • body – frame body

  • +
  • decompressor – optional decompression function to inflate the body

  • +
+
+
Returns
+

a message decoded from the body and frame attributes

+
+
+
+ +
+ +
+
+

Faster Deserialization

+

When python-driver is compiled with Cython, it uses a Cython-based deserialization path +to deserialize messages. By default, the driver will use a Cython-based parser that returns +lists of rows similar to the pure-Python version. In addition, there are two additional +ProtocolHandler classes that can be used to deserialize response messages: LazyProtocolHandler +and NumpyProtocolHandler. They can be used as follows:

+
from cassandra.protocol import NumpyProtocolHandler, LazyProtocolHandler
+from cassandra.query import tuple_factory
+s.client_protocol_handler = LazyProtocolHandler   # for a result iterator
+s.row_factory = tuple_factory  #required for Numpy results
+s.client_protocol_handler = NumpyProtocolHandler  # for a dict of NumPy arrays as result
+
+
+

These protocol handlers comprise different parsers, and return results as described below:

+
    +
  • ProtocolHandler: this default implementation is a drop-in replacement for the pure-Python version. +The rows are all parsed upfront, before results are returned.

  • +
  • LazyProtocolHandler: near drop-in replacement for the above, except that it returns an iterator over rows, +lazily decoded into the default row format (this is more efficient since all decoded results are not materialized at once)

  • +
  • NumpyProtocolHander: deserializes results directly into NumPy arrays. This facilitates efficient integration with +analysis toolkits such as Pandas.

  • +
+
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/master/api/cassandra/query.html b/master/api/cassandra/query.html new file mode 100644 index 0000000000..6d403ed895 --- /dev/null +++ b/master/api/cassandra/query.html @@ -0,0 +1,1003 @@ + + + + + + + + + + + + + cassandra.query - Prepared Statements, Batch Statements, Tracing, and Row Factories | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for an unstable version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.query - Prepared Statements, Batch Statements, Tracing, and Row Factories

+
+
+cassandra.query.tuple_factory(colnames, rows)
+

Returns each row as a tuple

+

Example:

+
>>> from cassandra.query import tuple_factory
+>>> session = cluster.connect('mykeyspace')
+>>> session.row_factory = tuple_factory
+>>> rows = session.execute("SELECT name, age FROM users LIMIT 1")
+>>> print rows[0]
+('Bob', 42)
+
+
+
+

Changed in version 2.0.0: moved from cassandra.decoder to cassandra.query

+
+
+ +
+
+cassandra.query.named_tuple_factory(colnames, rows)
+

Returns each row as a namedtuple. +This is the default row factory.

+

Example:

+
>>> from cassandra.query import named_tuple_factory
+>>> session = cluster.connect('mykeyspace')
+>>> session.row_factory = named_tuple_factory
+>>> rows = session.execute("SELECT name, age FROM users LIMIT 1")
+>>> user = rows[0]
+
+>>> # you can access field by their name:
+>>> print "name: %s, age: %d" % (user.name, user.age)
+name: Bob, age: 42
+
+>>> # or you can access fields by their position (like a tuple)
+>>> name, age = user
+>>> print "name: %s, age: %d" % (name, age)
+name: Bob, age: 42
+>>> name = user[0]
+>>> age = user[1]
+>>> print "name: %s, age: %d" % (name, age)
+name: Bob, age: 42
+
+
+
+

Changed in version 2.0.0: moved from cassandra.decoder to cassandra.query

+
+
+ +
+
+cassandra.query.dict_factory(colnames, rows)
+

Returns each row as a dict.

+

Example:

+
>>> from cassandra.query import dict_factory
+>>> session = cluster.connect('mykeyspace')
+>>> session.row_factory = dict_factory
+>>> rows = session.execute("SELECT name, age FROM users LIMIT 1")
+>>> print rows[0]
+{u'age': 42, u'name': u'Bob'}
+
+
+
+

Changed in version 2.0.0: moved from cassandra.decoder to cassandra.query

+
+
+ +
+
+cassandra.query.ordered_dict_factory(colnames, rows)
+

Like dict_factory(), but returns each row as an OrderedDict, +so the order of the columns is preserved.

+
+

Changed in version 2.0.0: moved from cassandra.decoder to cassandra.query

+
+
+ +
+
+class cassandra.query.SimpleStatement(query_string, retry_policy=None, consistency_level=None, routing_key=None, serial_consistency_level=None, fetch_size=<object object>, keyspace=None, custom_payload=None, is_idempotent=False)
+

A simple, un-prepared query.

+

query_string should be a literal CQL statement with the exception +of parameter placeholders that will be filled through the +parameters argument of Session.execute().

+

See Statement attributes for a description of the other parameters.

+
+ +
+
+class cassandra.query.PreparedStatement
+

A statement that has been prepared against at least one Cassandra node. +Instances of this class should not be created directly, but through +Session.prepare().

+

A PreparedStatement should be prepared only once. Re-preparing a statement +may affect performance (as the operation requires a network roundtrip).

+

A note about * in prepared statements: Do not use * in prepared statements if you might +change the schema of the table being queried. The driver and server each +maintain a map between metadata for a schema and statements that were +prepared against that schema. When a user changes a schema, e.g. by adding +or removing a column, the server invalidates its mappings involving that +schema. However, there is currently no way to propagate that invalidation +to drivers. Thus, after a schema change, the driver will incorrectly +interpret the results of SELECT * queries prepared before the schema +change. This is currently being addressed in CASSANDRA-10786.

+
+
+bind(values)
+

Creates and returns a BoundStatement instance using values.

+

See BoundStatement.bind() for rules on input values.

+
+ +
+ +
+
+class cassandra.query.BoundStatement(prepared_statement, retry_policy=None, consistency_level=None, routing_key=None, serial_consistency_level=None, fetch_size=<object object>, keyspace=None, custom_payload=None)
+

A prepared statement that has been bound to a particular set of values. +These may be created directly or through PreparedStatement.bind().

+

prepared_statement should be an instance of PreparedStatement.

+

See Statement attributes for a description of the other parameters.

+
+
+bind(values)
+

Binds a sequence of values for the prepared statement parameters +and returns this instance. Note that values must be:

+
    +
  • a sequence, even if you are only binding one value, or

  • +
  • a dict that relates 1-to-1 between dict keys and columns

  • +
+
+

Changed in version 2.6.0: UNSET_VALUE was introduced. These can be bound as positional parameters +in a sequence, or by name in a dict. Additionally, when using protocol v4+:

+
    +
  • short sequences will be extended to match bind parameters with UNSET_VALUE

  • +
  • names may be omitted from a dict with UNSET_VALUE implied.

  • +
+
+
+

Changed in version 3.0.0: method will not throw if extra keys are present in bound dict (PYTHON-178)

+
+
+ +
+
+property routing_key
+

The partition_key portion of the primary key, +which can be used to determine which nodes are replicas for the query.

+

If the partition key is a composite, a list or tuple must be passed in. +Each key component should be in its packed (binary) format, so all +components should be strings.

+
+ +
+ +
+
+class cassandra.query.Statement
+

An abstract class representing a single query. There are three subclasses: +SimpleStatement, BoundStatement, and BatchStatement. +These can be passed to Session.execute().

+
+
+property routing_key
+

The partition_key portion of the primary key, +which can be used to determine which nodes are replicas for the query.

+

If the partition key is a composite, a list or tuple must be passed in. +Each key component should be in its packed (binary) format, so all +components should be strings.

+
+ +
+
+property serial_consistency_level
+

The serial consistency level is only used by conditional updates +(INSERT, UPDATE and DELETE with an IF condition). For +those, the serial_consistency_level defines the consistency level of +the serial phase (or “paxos” phase) while the normal +consistency_level defines the consistency for the “learn” phase, +i.e. what type of reads will be guaranteed to see the update right away. +For example, if a conditional write has a consistency_level of +QUORUM (and is successful), then a +QUORUM read is guaranteed to see that write. +But if the regular consistency_level of that write is +ANY, then only a read with a +consistency_level of SERIAL is +guaranteed to see it (even a read with consistency +ALL is not guaranteed to be enough).

+

The serial consistency can only be one of SERIAL +or LOCAL_SERIAL. While SERIAL guarantees full +linearizability (with other SERIAL updates), LOCAL_SERIAL only +guarantees it in the local data center.

+

The serial consistency level is ignored for any query that is not a +conditional update. Serial reads should use the regular +consistency_level.

+

Serial consistency levels may only be used against Cassandra 2.0+ +and the protocol_version must be set to 2 or higher.

+

See Lightweight Transactions (Compare-and-set) for a discussion on how to work with results returned from +conditional statements.

+
+

New in version 2.0.0.

+
+
+ +
+ +
+
+cassandra.query.UNSET_VALUE
+

The most base type

+
+ +
+
+class cassandra.query.BatchStatement(batch_type=BatchType.LOGGED, retry_policy=None, consistency_level=None)
+

A protocol-level batch of operations which are applied atomically +by default.

+
+

New in version 2.0.0.

+
+

batch_type specifies The BatchType for the batch operation. +Defaults to BatchType.LOGGED.

+

retry_policy should be a RetryPolicy instance for +controlling retries on the operation.

+

consistency_level should be a ConsistencyLevel value +to be used for all operations in the batch.

+

custom_payload is a Custom Payloads passed to the server. +Note: as Statement objects are added to the batch, this map is +updated with any values found in their custom payloads. These are +only allowed when using protocol version 4 or higher.

+

Example usage:

+
insert_user = session.prepare("INSERT INTO users (name, age) VALUES (?, ?)")
+batch = BatchStatement(consistency_level=ConsistencyLevel.QUORUM)
+
+for (name, age) in users_to_insert:
+    batch.add(insert_user, (name, age))
+
+session.execute(batch)
+
+
+

You can also mix different types of operations within a batch:

+
batch = BatchStatement()
+batch.add(SimpleStatement("INSERT INTO users (name, age) VALUES (%s, %s)"), (name, age))
+batch.add(SimpleStatement("DELETE FROM pending_users WHERE name=%s"), (name,))
+session.execute(batch)
+
+
+
+

New in version 2.0.0.

+
+
+

Changed in version 2.1.0: Added serial_consistency_level as a parameter

+
+
+

Changed in version 2.6.0: Added custom_payload as a parameter

+
+
+
+add(statement, parameters=None)
+

Adds a Statement and optional sequence of parameters +to be used with the statement to the batch.

+

Like with other statements, parameters must be a sequence, even +if there is only one item.

+
+ +
+
+add_all(statements, parameters)
+

Adds a sequence of Statement objects and a matching sequence +of parameters to the batch. Statement and parameter sequences must be of equal length or +one will be truncated. None can be used in the parameters position where are needed.

+
+ +
+
+clear()
+

This is a convenience method to clear a batch statement for reuse.

+

Note: it should not be used concurrently with uncompleted execution futures executing the same +BatchStatement.

+
+ +
+
+serial_consistency_level = None
+
+ +
+ +
+
+class cassandra.query.BatchType
+

A BatchType is used with BatchStatement instances to control +the atomicity of the batch operation.

+
+

New in version 2.0.0.

+
+
+
+LOGGED = BatchType.LOGGED
+
+ +
+
+UNLOGGED = BatchType.UNLOGGED
+
+ +
+
+COUNTER = BatchType.COUNTER
+
+ +
+ +
+
+class cassandra.query.ValueSequence(iterable=(), /)
+

A wrapper class that is used to specify that a sequence of values should +be treated as a CQL list of values instead of a single column collection when used +as part of the parameters argument for Session.execute().

+

This is typically needed when supplying a list of keys to select. +For example:

+
>>> my_user_ids = ('alice', 'bob', 'charles')
+>>> query = "SELECT * FROM users WHERE user_id IN %s"
+>>> session.execute(query, parameters=[ValueSequence(my_user_ids)])
+
+
+
+ +
+
+class cassandra.query.QueryTrace
+

A trace of the duration and events that occurred when executing +an operation.

+
+
+populate(max_wait=2.0, wait_for_complete=True, query_cl=None)
+

Retrieves the actual tracing details from Cassandra and populates the +attributes of this instance. Because tracing details are stored +asynchronously by Cassandra, this may need to retry the session +detail fetch. If the trace is still not available after max_wait +seconds, TraceUnavailable will be raised; if max_wait is +None, this will retry forever.

+

wait_for_complete=False bypasses the wait for duration to be populated. +This can be used to query events from partial sessions.

+

query_cl specifies a consistency level to use for polling the trace tables, +if it should be different than the session default.

+
+ +
+ +
+
+class cassandra.query.TraceEvent
+

Representation of a single event within a query trace.

+
+ +
+
+exception cassandra.query.TraceUnavailable
+

Raised when complete trace details cannot be fetched from Cassandra.

+
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/master/api/cassandra/timestamps.html b/master/api/cassandra/timestamps.html new file mode 100644 index 0000000000..7df424de7c --- /dev/null +++ b/master/api/cassandra/timestamps.html @@ -0,0 +1,696 @@ + + + + + + + + + + + + + cassandra.timestamps - Timestamp Generation | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for an unstable version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.timestamps - Timestamp Generation

+
+
+class cassandra.timestamps.MonotonicTimestampGenerator(warn_on_drift=True, warning_threshold=0, warning_interval=0)
+

An object that, when called, returns int(time.time() * 1e6) when +possible, but, if the value returned by time.time doesn’t increase, +drifts into the future and logs warnings. +Exposed configuration attributes can be configured with arguments to +__init__ or by changing attributes on an initialized object.

+
+

New in version 3.8.0.

+
+
+
+warn_on_drift = True
+

If true, log warnings when timestamps drift into the future as allowed by +warning_threshold and warning_interval.

+
+ +
+
+warning_threshold = 1
+

This object will only issue warnings when the returned timestamp drifts +more than warning_threshold seconds into the future. +Defaults to 1 second.

+
+ +
+
+warning_interval = 1
+

This object will only issue warnings every warning_interval seconds. +Defaults to 1 second.

+
+ +
+
+_next_timestamp(now, last)
+

Returns the timestamp that should be used if now is the current +time and last is the last timestamp returned by this object. +Intended for internal and testing use only; to generate timestamps, +call an instantiated MonotonicTimestampGenerator object.

+
+
Parameters
+
    +
  • now (int) – an integer to be used as the current time, typically +representing the current time in microseconds since the UNIX epoch

  • +
  • last (int) – an integer representing the last timestamp returned by +this object

  • +
+
+
+
+ +
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/master/api/cassandra/util.html b/master/api/cassandra/util.html new file mode 100644 index 0000000000..e973852624 --- /dev/null +++ b/master/api/cassandra/util.html @@ -0,0 +1,1031 @@ + + + + + + + + + + + + + cassandra.util - Utilities | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for an unstable version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

cassandra.util - Utilities

+
+
+class cassandra.util.Date(value)
+

Idealized date: year, month, day

+

Offers wider year range than datetime.date. For Dates that cannot be represented +as a datetime.date (because datetime.MINYEAR, datetime.MAXYEAR), this type falls back +to printing days_from_epoch offset.

+

Initializer value can be:

+
    +
  • integer_type: absolute days from epoch (1970, 1, 1). Can be negative.

  • +
  • datetime.date: built-in date

  • +
  • string_type: a string time of the form “yyyy-mm-dd”

  • +
+
+
+date()
+

Return a built-in datetime.date for Dates falling in the years [datetime.MINYEAR, datetime.MAXYEAR]

+

ValueError is raised for Dates outside this range.

+
+ +
+
+property seconds
+

Absolute seconds from epoch (can be negative)

+
+ +
+ +
+
+class cassandra.util.DateRange(lower_bound=None, upper_bound=None, value=None)
+

DSE DateRange Type

+
+
+lower_bound
+

DateRangeBound representing the lower bound of a bounded range.

+
+ +
+
+upper_bound
+

DateRangeBound representing the upper bound of a bounded range.

+
+ +
+
+value
+

DateRangeBound representing the value of a single-value range.

+
+ +

As noted in its documentation, DateRangeBound uses a millisecond +offset from the UNIX epoch to allow DateRange to represent values +datetime.datetime cannot. For such values, string representions will show +this offset rather than the CQL representation.

+
+
Parameters
+
+
+
+
+ +
+
+class cassandra.util.DateRangeBound(value, precision)
+

Represents a single date value and its precision for DateRange.

+
+
+milliseconds
+

Integer representing milliseconds since the UNIX epoch. May be negative.

+
+ +
+
+precision
+

String representing the precision of a bound. Must be a valid +DateRangePrecision member.

+
+ +

DateRangeBound uses a millisecond offset from the UNIX epoch to +allow DateRange to represent values datetime.datetime cannot. +For such values, string representions will show this offset rather than the +CQL representation.

+
+
Parameters
+
    +
  • value – a value representing ms since the epoch. Accepts an +integer or a datetime.

  • +
  • precision – a string representing precision

  • +
+
+
+
+
+datetime()
+

Return milliseconds as a datetime.datetime if possible. +Raises an OverflowError if the value is out of range.

+
+ +
+
+classmethod from_value(value)
+

Construct a new DateRangeBound from a given value. If +possible, use the value[‘milliseconds’] and value[‘precision’] keys +of the argument. Otherwise, use the argument as a (milliseconds, +precision) iterable.

+
+
Parameters
+

value – a dictlike or iterable object

+
+
+
+ +
+ +
+
+class cassandra.util.DateRangePrecision
+

An “enum” representing the valid values for DateRange.precision.

+
+ +
+
+class cassandra.util.Distance(x=nan, y=nan, radius=nan)
+

Represents a Distance geometry for DSE

+
+
+static from_wkt(s)
+

Parse a Distance geometry from a wkt string and return a new Distance object.

+
+ +
+ +
+
+class cassandra.util.Duration(months=0, days=0, nanoseconds=0)
+

Cassandra Duration Type

+
+ +
+
+class cassandra.util.LineString(coords=())
+

Represents a linestring geometry for DSE

+

‘coords`: a sequence of (x, y) coordinates of points in the linestring

+
+
+static from_wkt(s)
+

Parse a LineString geometry from a wkt string and return a new LineString object.

+
+ +
+ +
+
+class cassandra.util.OrderedMap(*args, **kwargs)
+

An ordered map that accepts non-hashable types for keys. It also maintains the +insertion order of items, behaving as OrderedDict in that regard. These maps +are constructed and read just as normal mapping types, except that they may +contain arbitrary collections and other non-hashable items as keys:

+
>>> od = OrderedMap([({'one': 1, 'two': 2}, 'value'),
+...                  ({'three': 3, 'four': 4}, 'value2')])
+>>> list(od.keys())
+[{'two': 2, 'one': 1}, {'three': 3, 'four': 4}]
+>>> list(od.values())
+['value', 'value2']
+
+
+

These constructs are needed to support nested collections in Cassandra 2.1.3+, +where frozen collections can be specified as parameters to others:

+
CREATE TABLE example (
+    ...
+    value map<frozen<map<int, int>>, double>
+    ...
+)
+
+
+

This class derives from the (immutable) Mapping API. Objects in these maps +are not intended be modified.

+
+ +
+
+class cassandra.util.OrderedMapSerializedKey(cass_type, protocol_version)
+
+ +
+
+class cassandra.util.Point(x=nan, y=nan)
+

Represents a point geometry for DSE

+
+
+static from_wkt(s)
+

Parse a Point geometry from a wkt string and return a new Point object.

+
+ +
+ +
+
+class cassandra.util.Polygon(exterior=(), interiors=None)
+

Represents a polygon geometry for DSE

+

‘exterior`: a sequence of (x, y) coordinates of points in the linestring +interiors: None, or a sequence of sequences or (x, y) coordinates of points describing interior linear rings

+
+
+static from_wkt(s)
+

Parse a Polygon geometry from a wkt string and return a new Polygon object.

+
+ +
+ +
+
+class cassandra.util.SortedSet(iterable=())
+

A sorted set based on sorted list

+

A sorted set implementation is used in this case because it does not +require its elements to be immutable/hashable.

+

#Not implemented: update functions, inplace operators

+
+ +
+
+class cassandra.util.Time(value)
+

Idealized time, independent of day.

+

Up to nanosecond resolution

+

Initializer value can be:

+
    +
  • integer_type: absolute nanoseconds in the day

  • +
  • datetime.time: built-in time

  • +
  • string_type: a string time of the form “HH:MM:SS[.mmmuuunnn]”

  • +
+
+
+property hour
+

The hour component of this time (0-23)

+
+ +
+
+property minute
+

The minute component of this time (0-59)

+
+ +
+
+property nanosecond
+

The fractional seconds component of the time, in nanoseconds

+
+ +
+
+property second
+

The second component of this time (0-59)

+
+ +
+
+time()
+

Return a built-in datetime.time (nanosecond precision truncated to micros).

+
+ +
+ +
+
+class cassandra.util.Version(version)
+

Internal minimalist class to compare versions. +A valid version is: <int>.<int>.<int>.<int or str>.

+

TODO: when python2 support is removed, use packaging.version.

+
+ +
+
+cassandra.util.datetime_from_timestamp(timestamp)
+

Creates a timezone-agnostic datetime from timestamp (in seconds) in a consistent manner. +Works around a Windows issue with large negative timestamps (PYTHON-119), +and rounding differences in Python 3.4 (PYTHON-340).

+
+
Parameters
+

timestamp – a unix timestamp, in seconds

+
+
+
+ +
+
+cassandra.util.datetime_from_uuid1(uuid_arg)
+

Creates a timezone-agnostic datetime from the timestamp in the +specified type-1 UUID.

+
+
Parameters
+

uuid_arg – a version 1 UUID

+
+
+
+ +
+
+cassandra.util.max_uuid_from_time(timestamp)
+

Generates the maximum TimeUUID (type 1) for a given timestamp, as compared by Cassandra.

+

See uuid_from_time() for argument and return types.

+
+ +
+
+cassandra.util.min_uuid_from_time(timestamp)
+

Generates the minimum TimeUUID (type 1) for a given timestamp, as compared by Cassandra.

+

See uuid_from_time() for argument and return types.

+
+ +
+
+cassandra.util.ms_timestamp_from_datetime(dt)
+

Converts a datetime to a timestamp expressed in milliseconds.

+
+
Parameters
+

dt – a datetime.datetime

+
+
+
+ +
+
+cassandra.util.sortedset
+

alias of cassandra.util.SortedSet

+
+ +
+
+cassandra.util.unix_time_from_uuid1(uuid_arg)
+

Converts a version 1 uuid.UUID to a timestamp with the same precision +as time.time() returns. This is useful for examining the +results of queries returning a v1 UUID.

+
+
Parameters
+

uuid_arg – a version 1 UUID

+
+
+
+ +
+
+cassandra.util.utc_datetime_from_ms_timestamp(timestamp)
+

Creates a UTC datetime from a timestamp in milliseconds. See +datetime_from_timestamp().

+

Raises an OverflowError if the timestamp is out of range for +datetime.

+
+
Parameters
+

timestamp – timestamp, in milliseconds

+
+
+
+ +
+
+cassandra.util.uuid_from_time(time_arg, node=None, clock_seq=None)
+

Converts a datetime or timestamp to a type 1 uuid.UUID.

+
+
Parameters
+
    +
  • time_arg – The time to use for the timestamp portion of the UUID. +This can either be a datetime object or a timestamp +in seconds (as returned from time.time()).

  • +
  • node (long) – None integer for the UUID (up to 48 bits). If not specified, this +field is randomized.

  • +
  • clock_seq (int) – Clock sequence field for the UUID (up to 14 bits). If not specified, +a random sequence is generated.

  • +
+
+
Return type
+

uuid.UUID

+
+
+
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/master/api/index.html b/master/api/index.html new file mode 100644 index 0000000000..bcfb3a862b --- /dev/null +++ b/master/api/index.html @@ -0,0 +1,717 @@ + + + + + + + + + + + + + API Documentation | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for an unstable version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

API Documentation

+
+

Core Driver

+ +
+
+

Object Mapper

+ +
+
+

DataStax Graph

+ +
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/master/cqlengine/batches.html b/master/cqlengine/batches.html new file mode 100644 index 0000000000..4a58586449 --- /dev/null +++ b/master/cqlengine/batches.html @@ -0,0 +1,747 @@ + + + + + + + + + + + + + Batch Queries | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for an unstable version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + + + +
+

Batch Queries

+

cqlengine supports batch queries using the BatchQuery class. Batch queries can be started and stopped manually, or within a context manager. To add queries to the batch object, you just need to precede the create/save/delete call with a call to batch, and pass in the batch object.

+
+

Batch Query General Use Pattern

+

You can only create, update, and delete rows with a batch query, attempting to read rows out of the database with a batch query will fail.

+
from cassandra.cqlengine.query import BatchQuery
+
+#using a context manager
+with BatchQuery() as b:
+    now = datetime.now()
+    em1 = ExampleModel.batch(b).create(example_type=0, description="1", created_at=now)
+    em2 = ExampleModel.batch(b).create(example_type=0, description="2", created_at=now)
+    em3 = ExampleModel.batch(b).create(example_type=0, description="3", created_at=now)
+
+# -- or --
+
+#manually
+b = BatchQuery()
+now = datetime.now()
+em1 = ExampleModel.batch(b).create(example_type=0, description="1", created_at=now)
+em2 = ExampleModel.batch(b).create(example_type=0, description="2", created_at=now)
+em3 = ExampleModel.batch(b).create(example_type=0, description="3", created_at=now)
+b.execute()
+
+# updating in a batch
+
+b = BatchQuery()
+em1.description = "new description"
+em1.batch(b).save()
+em2.description = "another new description"
+em2.batch(b).save()
+b.execute()
+
+# deleting in a batch
+b = BatchQuery()
+ExampleModel.objects(id=some_id).batch(b).delete()
+ExampleModel.objects(id=some_id2).batch(b).delete()
+b.execute()
+
+
+

Typically you will not want the block to execute if an exception occurs inside the with block. However, in the case that this is desirable, it’s achievable by using the following syntax:

+
with BatchQuery(execute_on_exception=True) as b:
+    LogEntry.batch(b).create(k=1, v=1)
+    mystery_function() # exception thrown in here
+    LogEntry.batch(b).create(k=1, v=2) # this code is never reached due to the exception, but anything leading up to here will execute in the batch.
+
+
+

If an exception is thrown somewhere in the block, any statements that have been added to the batch will still be executed. This is useful for some logging situations.

+
+
+

Batch Query Execution Callbacks

+

In order to allow secondary tasks to be chained to the end of batch, BatchQuery instances allow callbacks to be +registered with the batch, to be executed immediately after the batch executes.

+

Multiple callbacks can be attached to same BatchQuery instance, they are executed in the same order that they +are added to the batch.

+

The callbacks attached to a given batch instance are executed only if the batch executes. If the batch is used as a +context manager and an exception is raised, the queued up callbacks will not be run.

+
def my_callback(*args, **kwargs):
+    pass
+
+batch = BatchQuery()
+
+batch.add_callback(my_callback)
+batch.add_callback(my_callback, 'positional arg', named_arg='named arg value')
+
+# if you need reference to the batch within the callback,
+# just trap it in the arguments to be passed to the callback:
+batch.add_callback(my_callback, cqlengine_batch=batch)
+
+# once the batch executes...
+batch.execute()
+
+# the effect of the above scheduled callbacks will be similar to
+my_callback()
+my_callback('positional arg', named_arg='named arg value')
+my_callback(cqlengine_batch=batch)
+
+
+

Failure in any of the callbacks does not affect the batch’s execution, as the callbacks are started after the execution +of the batch is complete.

+
+

Logged vs Unlogged Batches

+

By default, queries in cqlengine are LOGGED, which carries additional overhead from UNLOGGED. To explicitly state which batch type to use, simply:

+
from cassandra.cqlengine.query import BatchType
+with BatchQuery(batch_type=BatchType.Unlogged) as b:
+    LogEntry.batch(b).create(k=1, v=1)
+    LogEntry.batch(b).create(k=1, v=2)
+
+
+
+
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/master/cqlengine/connections.html b/master/cqlengine/connections.html new file mode 100644 index 0000000000..b44c61be0e --- /dev/null +++ b/master/cqlengine/connections.html @@ -0,0 +1,771 @@ + + + + + + + + + + + + + Connections | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for an unstable version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + + + +
+

Connections

+

Connections aim to ease the use of multiple sessions with cqlengine. Connections can be set on a model class, per query or using a context manager.

+
+

Register a new connection

+

To use cqlengine, you need at least a default connection. If you initialize cqlengine’s connections with with connection.setup, a connection will be created automatically. If you want to use another cluster/session, you need to register a new cqlengine connection. You register a connection with register_connection():

+
from cassandra.cqlengine import connection
+
+connection.setup(['127.0.0.1')
+connection.register_connection('cluster2', ['127.0.0.2'])
+
+
+

register_connection() can take a list of hosts, as shown above, in which case it will create a connection with a new session. It can also take a session argument if you’ve already created a session:

+
from cassandra.cqlengine import connection
+from cassandra.cluster import Cluster
+
+session = Cluster(['127.0.0.1']).connect()
+connection.register_connection('cluster3', session=session)
+
+
+
+
+

Change the default connection

+

You can change the default cqlengine connection on registration:

+
from cassandra.cqlengine import connection
+
+connection.register_connection('cluster2', ['127.0.0.2'] default=True)
+
+
+

or on the fly using set_default_connection()

+
connection.set_default_connection('cluster2')
+
+
+
+
+

Unregister a connection

+

You can unregister a connection using unregister_connection():

+
connection.unregister_connection('cluster2')
+
+
+
+
+

Management

+

When using multiples connections, you also need to sync your models on all connections (and keyspaces) that you need operate on. Management commands have been improved to ease this part. Here is an example:

+
from cassandra.cqlengine import management
+
+keyspaces = ['ks1', 'ks2']
+conns = ['cluster1', 'cluster2']
+
+# registers your connections
+# ...
+
+# create all keyspaces on all connections
+for ks in keyspaces:
+    management.create_simple_keyspace(ks, connections=conns)
+
+# define your Automobile model
+# ...
+
+# sync your models
+management.sync_table(Automobile, keyspaces=keyspaces, connections=conns)
+
+
+
+
+

Connection Selection

+

cqlengine will select the default connection, unless your specify a connection using one of the following methods.

+
+

Default Model Connection

+

You can specify a default connection per model:

+
class Automobile(Model):
+    __keyspace__ = 'test'
+    __connection__ = 'cluster2'
+    manufacturer = columns.Text(primary_key=True)
+    year = columns.Integer(primary_key=True)
+    model = columns.Text(primary_key=True)
+
+print len(Automobile.objects.all())  # executed on the connection 'cluster2'
+
+
+
+
+

QuerySet and model instance

+

You can use the using() method to select a connection (or keyspace):

+
Automobile.objects.using(connection='cluster1').create(manufacturer='honda', year=2010, model='civic')
+q = Automobile.objects.filter(manufacturer='Tesla')
+autos = q.using(keyspace='ks2', connection='cluster2').all()
+
+for auto in autos:
+    auto.using(connection='cluster1').save()
+
+
+
+
+

Context Manager

+

You can use the ContextQuery as well to select a connection:

+
with ContextQuery(Automobile, connection='cluster1') as A:
+    A.objects.filter(manufacturer='honda').all()  # executed on 'cluster1'
+
+
+
+
+

BatchQuery

+

With a BatchQuery, you can select the connection with the context manager. Note that all operations in the batch need to use the same connection.

+
with BatchQuery(connection='cluster1') as b:
+    Automobile.objects.batch(b).create(manufacturer='honda', year=2010, model='civic')
+
+
+
+
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/master/cqlengine/faq.html b/master/cqlengine/faq.html new file mode 100644 index 0000000000..d8ff13174e --- /dev/null +++ b/master/cqlengine/faq.html @@ -0,0 +1,711 @@ + + + + + + + + + + + + + Frequently Asked Questions | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for an unstable version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

Frequently Asked Questions

+
+

Why don’t updates work correctly on models instantiated as Model(field=value, field2=value2)?

+

The recommended way to create new rows is with the models .create method. The values passed into a model’s init method are interpreted by the model as the values as they were read from a row. This allows the model to “know” which rows have changed since the row was read out of cassandra, and create suitable update statements.

+
+
+

How to preserve ordering in batch query?

+

Statement Ordering is not supported by CQL3 batches. Therefore, +once cassandra needs resolving conflict(Updating the same column in one batch), +The algorithm below would be used.

+
    +
  • If timestamps are different, pick the column with the largest timestamp (the value being a regular column or a tombstone)

  • +
  • If timestamps are the same, and one of the columns in a tombstone (‘null’) - pick the tombstone

  • +
  • If timestamps are the same, and none of the columns are tombstones, pick the column with the largest value

  • +
+

Below is an example to show this scenario.

+
class MyMode(Model):
+    id    = columns.Integer(primary_key=True)
+    count = columns.Integer()
+    text  = columns.Text()
+
+with BatchQuery() as b:
+   MyModel.batch(b).create(id=1, count=2, text='123')
+   MyModel.batch(b).create(id=1, count=3, text='111')
+
+assert MyModel.objects(id=1).first().count == 3
+assert MyModel.objects(id=1).first().text  == '123'
+
+
+

The largest value of count is 3, and the largest value of text would be ‘123’.

+

The workaround is applying timestamp to each statement, then Cassandra would +resolve to the statement with the lastest timestamp.

+
with BatchQuery() as b:
+    MyModel.timestamp(datetime.now()).batch(b).create(id=1, count=2, text='123')
+    MyModel.timestamp(datetime.now()).batch(b).create(id=1, count=3, text='111')
+
+assert MyModel.objects(id=1).first().count == 3
+assert MyModel.objects(id=1).first().text  == '111'
+
+
+
+
+

How can I delete individual values from a row?

+

When inserting with CQLEngine, None is equivalent to CQL NULL or to +issuing a DELETE on that column. For example:

+
class MyModel(Model):
+    id    = columns.Integer(primary_key=True)
+    text  = columns.Text()
+
+m = MyModel.create(id=1, text='We can delete this with None')
+assert MyModel.objects(id=1).first().text is not None
+
+m.update(text=None)
+assert MyModel.objects(id=1).first().text is None
+
+
+
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/master/cqlengine/models.html b/master/cqlengine/models.html new file mode 100644 index 0000000000..a2b3de4abb --- /dev/null +++ b/master/cqlengine/models.html @@ -0,0 +1,836 @@ + + + + + + + + + + + + + Models | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for an unstable version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + + + +
+

Models

+

A model is a python class representing a CQL table. Models derive from Model, and +define basic table properties and columns for a table.

+

Columns in your models map to columns in your CQL table. You define CQL columns by defining column attributes on your model classes. +For a model to be valid it needs at least one primary key column and one non-primary key column. Just as in CQL, the order you define +your columns in is important, and is the same order they are defined in on a model’s corresponding table.

+

Some basic examples defining models are shown below. Consult the Model API docs and Column API docs for complete details.

+
+

Example Definitions

+

This example defines a Person table, with the columns first_name and last_name

+
from cassandra.cqlengine import columns
+from cassandra.cqlengine.models import Model
+
+ class Person(Model):
+     id = columns.UUID(primary_key=True)
+     first_name  = columns.Text()
+     last_name = columns.Text()
+
+
+

The Person model would create this CQL table:

+
CREATE TABLE cqlengine.person (
+    id uuid,
+    first_name text,
+    last_name text,
+    PRIMARY KEY (id)
+);
+
+
+

Here’s an example of a comment table created with clustering keys, in descending order:

+
from cassandra.cqlengine import columns
+from cassandra.cqlengine.models import Model
+
+class Comment(Model):
+    photo_id = columns.UUID(primary_key=True)
+    comment_id = columns.TimeUUID(primary_key=True, clustering_order="DESC")
+    comment = columns.Text()
+
+
+

The Comment model’s create table would look like the following:

+
CREATE TABLE comment (
+  photo_id uuid,
+  comment_id timeuuid,
+  comment text,
+  PRIMARY KEY (photo_id, comment_id)
+) WITH CLUSTERING ORDER BY (comment_id DESC);
+
+
+

To sync the models to the database, you may do the following*:

+
from cassandra.cqlengine.management import sync_table
+sync_table(Person)
+sync_table(Comment)
+
+
+

*Note: synchronizing models causes schema changes, and should be done with caution. +Please see the discussion in cassandra.cqlengine.management - Schema management for cqlengine for considerations.

+

For examples on manipulating data and creating queries, see Making Queries

+
+
+

Manipulating model instances as dictionaries

+

Model instances can be accessed like dictionaries.

+
class Person(Model):
+    first_name  = columns.Text()
+    last_name = columns.Text()
+
+kevin = Person.create(first_name="Kevin", last_name="Deldycke")
+dict(kevin)  # returns {'first_name': 'Kevin', 'last_name': 'Deldycke'}
+kevin['first_name']  # returns 'Kevin'
+kevin.keys()  # returns ['first_name', 'last_name']
+kevin.values()  # returns ['Kevin', 'Deldycke']
+kevin.items()  # returns [('first_name', 'Kevin'), ('last_name', 'Deldycke')]
+
+kevin['first_name'] = 'KEVIN5000'  # changes the models first name
+
+
+
+
+

Extending Model Validation

+

Each time you save a model instance in cqlengine, the data in the model is validated against the schema you’ve defined +for your model. Most of the validation is fairly straightforward, it basically checks that you’re not trying to do +something like save text into an integer column, and it enforces the required flag set on column definitions. +It also performs any transformations needed to save the data properly.

+

However, there are often additional constraints or transformations you want to impose on your data, beyond simply +making sure that Cassandra won’t complain when you try to insert it. To define additional validation on a model, +extend the model’s validation method:

+
class Member(Model):
+    person_id = UUID(primary_key=True)
+    name = Text(required=True)
+
+    def validate(self):
+        super(Member, self).validate()
+        if self.name == 'jon':
+            raise ValidationError('no jon\'s allowed')
+
+
+

Note: while not required, the convention is to raise a ValidationError (from cassandra.cqlengine import ValidationError) +if validation fails.

+
+
+

Model Inheritance

+

It is possible to save and load different model classes using a single CQL table. +This is useful in situations where you have different object types that you want to store in a single cassandra row.

+

For instance, suppose you want a table that stores rows of pets owned by an owner:

+
class Pet(Model):
+    __table_name__ = 'pet'
+    owner_id = UUID(primary_key=True)
+    pet_id = UUID(primary_key=True)
+    pet_type = Text(discriminator_column=True)
+    name = Text()
+
+    def eat(self, food):
+        pass
+
+    def sleep(self, time):
+        pass
+
+class Cat(Pet):
+    __discriminator_value__ = 'cat'
+    cuteness = Float()
+
+    def tear_up_couch(self):
+        pass
+
+class Dog(Pet):
+    __discriminator_value__ = 'dog'
+    fierceness = Float()
+
+    def bark_all_night(self):
+        pass
+
+
+

After calling sync_table on each of these tables, the columns defined in each model will be added to the +pet table. Additionally, saving Cat and Dog models will save the meta data needed to identify each row +as either a cat or dog.

+

To setup a model structure with inheritance, follow these steps

+
    +
  1. Create a base model with a column set as the distriminator (distriminator_column=True in the column definition)

  2. +
  3. Create subclass models, and define a unique __discriminator_value__ value on each

  4. +
  5. Run sync_table on each of the sub tables

  6. +
+

About the discriminator value

+

The discriminator value is what cqlengine uses under the covers to map logical cql rows to the appropriate model type. The +base model maintains a map of discriminator values to subclasses. When a specialized model is saved, its discriminator value is +automatically saved into the discriminator column. The discriminator column may be any column type except counter and container types. +Additionally, if you set index=True on your discriminator column, you can execute queries against specialized subclasses, and a +WHERE clause will be automatically added to your query, returning only rows of that type. Note that you must +define a unique __discriminator_value__ to each subclass, and that you can only assign a single discriminator column per model.

+
+
+

User Defined Types

+

cqlengine models User Defined Types (UDTs) much like tables, with fields defined by column type attributes. However, UDT instances +are only created, presisted, and queried via table Models. A short example to introduce the pattern:

+
from cassandra.cqlengine.columns import *
+from cassandra.cqlengine.models import Model
+from cassandra.cqlengine.usertype import UserType
+
+class address(UserType):
+    street = Text()
+    zipcode = Integer()
+
+class users(Model):
+    __keyspace__ = 'account'
+    name = Text(primary_key=True)
+    addr = UserDefinedType(address)
+
+users.create(name="Joe", addr=address(street="Easy St.", zipcode=99999))
+user = users.objects(name="Joe")[0]
+print user.name, user.addr
+# Joe address(street=u'Easy St.', zipcode=99999)
+
+
+

UDTs are modeled by inheriting UserType, and setting column type attributes. Types are then used in defining +models by declaring a column of type UserDefinedType, with the UserType class as a parameter.

+

sync_table will implicitly +synchronize any types contained in the table. Alternatively sync_type() can be used to create/alter types +explicitly.

+

Upon declaration, types are automatically registered with the driver, so query results return instances of your UserType +class*.

+

*Note: UDTs were not added to the native protocol until v3. When setting up the cqlengine connection, be sure to specify +protocol_version=3. If using an earlier version, UDT queries will still work, but the returned type will be a namedtuple.

+
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/master/cqlengine/queryset.html b/master/cqlengine/queryset.html new file mode 100644 index 0000000000..ba5a30edb1 --- /dev/null +++ b/master/cqlengine/queryset.html @@ -0,0 +1,1008 @@ + + + + + + + + + + + + + Making Queries | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for an unstable version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

Making Queries

+
+

Retrieving objects

+

Once you’ve populated Cassandra with data, you’ll probably want to retrieve some of it. This is accomplished with QuerySet objects. This section will describe how to use QuerySet objects to retrieve the data you’re looking for.

+
+

Retrieving all objects

+

The simplest query you can make is to return all objects from a table.

+

This is accomplished with the .all() method, which returns a QuerySet of all objects in a table

+

Using the Person example model, we would get all Person objects like this:

+
all_objects = Person.objects.all()
+
+
+
+
+

Retrieving objects with filters

+

Typically, you’ll want to query only a subset of the records in your database.

+

That can be accomplished with the QuerySet’s .filter(\*\*) method.

+

For example, given the model definition:

+
class Automobile(Model):
+    manufacturer = columns.Text(primary_key=True)
+    year = columns.Integer(primary_key=True)
+    model = columns.Text()
+    price = columns.Decimal()
+    options = columns.Set(columns.Text)
+
+
+

…and assuming the Automobile table contains a record of every car model manufactured in the last 20 years or so, we can retrieve only the cars made by a single manufacturer like this:

+
q = Automobile.objects.filter(manufacturer='Tesla')
+
+
+

You can also use the more convenient syntax:

+
q = Automobile.objects(Automobile.manufacturer == 'Tesla')
+
+
+

We can then further filter our query with another call to .filter

+
q = q.filter(year=2012)
+
+
+

Note: all queries involving any filtering MUST define either an ‘=’ or an ‘in’ relation to either a primary key column, or an indexed column.

+
+
+
+

Accessing objects in a QuerySet

+

There are several methods for getting objects out of a queryset

+
    +
  • +
    iterating over the queryset
    for car in Automobile.objects.all():
    +    #...do something to the car instance
    +    pass
    +
    +
    +
    +
    +
  • +
  • +
    list index
    q = Automobile.objects.all()
    +q[0] #returns the first result
    +q[1] #returns the second result
    +
    +
    +
    +

    Note

    +
      +
    • CQL does not support specifying a start position in it’s queries. Therefore, accessing elements using array indexing will load every result up to the index value requested

    • +
    • Using negative indices requires a “SELECT COUNT()” to be executed. This has a performance cost on large datasets.

    • +
    +
    +
    +
    +
  • +
  • +
    list slicing
    q = Automobile.objects.all()
    +q[1:] #returns all results except the first
    +q[1:9] #returns a slice of the results
    +
    +
    +
    +

    Note

    +
      +
    • CQL does not support specifying a start position in it’s queries. Therefore, accessing elements using array slicing will load every result up to the index value requested

    • +
    • Using negative indices requires a “SELECT COUNT()” to be executed. This has a performance cost on large datasets.

    • +
    +
    +
    +
    +
  • +
  • +
    calling get() on the queryset
    q = Automobile.objects.filter(manufacturer='Tesla')
    +q = q.filter(year=2012)
    +car = q.get()
    +
    +
    +

    this returns the object matching the queryset

    +
    +
    +
  • +
  • +
    calling first() on the queryset
    q = Automobile.objects.filter(manufacturer='Tesla')
    +q = q.filter(year=2012)
    +car = q.first()
    +
    +
    +

    this returns the first value in the queryset

    +
    +
    +
  • +
+
+
+

Filtering Operators

+

Equal To

+

The default filtering operator.

+
q = Automobile.objects.filter(manufacturer='Tesla')
+q = q.filter(year=2012)  #year == 2012
+
+
+

In addition to simple equal to queries, cqlengine also supports querying with other operators by appending a __<op> to the field name on the filtering call

+

in (__in)

+
q = Automobile.objects.filter(manufacturer='Tesla')
+q = q.filter(year__in=[2011, 2012])
+
+
+

> (__gt)

+
q = Automobile.objects.filter(manufacturer='Tesla')
+q = q.filter(year__gt=2010)  # year > 2010
+
+# or the nicer syntax
+
+q.filter(Automobile.year > 2010)
+
+
+

>= (__gte)

+
q = Automobile.objects.filter(manufacturer='Tesla')
+q = q.filter(year__gte=2010)  # year >= 2010
+
+# or the nicer syntax
+
+q.filter(Automobile.year >= 2010)
+
+
+

< (__lt)

+
q = Automobile.objects.filter(manufacturer='Tesla')
+q = q.filter(year__lt=2012)  # year < 2012
+
+# or...
+
+q.filter(Automobile.year < 2012)
+
+
+

<= (__lte)

+
q = Automobile.objects.filter(manufacturer='Tesla')
+q = q.filter(year__lte=2012)  # year <= 2012
+
+q.filter(Automobile.year <= 2012)
+
+
+

CONTAINS (__contains)

+

The CONTAINS operator is available for all collection types (List, Set, Map).

+
q = Automobile.objects.filter(manufacturer='Tesla')
+q.filter(options__contains='backup camera').allow_filtering()
+
+
+

Note that we need to use allow_filtering() since the options column has no secondary index.

+

LIKE (__like)

+

The LIKE operator is available for text columns that have a SASI secondary index.

+
q = Automobile.objects.filter(model__like='%Civic%').allow_filtering()
+
+
+

IS NOT NULL (IsNotNull(column_name))

+

The IS NOT NULL operator is not yet supported for C*.

+
q = Automobile.objects.filter(IsNotNull('model'))
+
+
+

Limitations:

+
    +
  • Currently, cqlengine does not support SASI index creation. To use this feature, you need to create the SASI index using the core driver.

  • +
  • Queries using LIKE must use allow_filtering() since the model column has no standard secondary index. Note that the server will use the SASI index properly when executing the query.

  • +
+
+
+

TimeUUID Functions

+

In addition to querying using regular values, there are two functions you can pass in when querying TimeUUID columns to help make filtering by them easier. Note that these functions don’t actually return a value, but instruct the cql interpreter to use the functions in it’s query.

+
+
+class cqlengine.queryset.MinTimeUUID(datetime)
+

returns the minimum time uuid value possible for the given datetime

+
+ +
+
+class cqlengine.queryset.MaxTimeUUID(datetime)
+

returns the maximum time uuid value possible for the given datetime

+
+ +

Example

+
class DataStream(Model):
+    id      = columns.UUID(partition_key=True)
+    time    = columns.TimeUUID(primary_key=True)
+    data    = columns.Bytes()
+
+min_time = datetime(1982, 1, 1)
+max_time = datetime(1982, 3, 9)
+
+DataStream.filter(time__gt=functions.MinTimeUUID(min_time), time__lt=functions.MaxTimeUUID(max_time))
+
+
+
+
+

Token Function

+

Token functon may be used only on special, virtual column pk__token, representing token of partition key (it also works for composite partition keys). +Cassandra orders returned items by value of partition key token, so using cqlengine.Token we can easy paginate through all table rows.

+

See http://cassandra.apache.org/doc/cql3/CQL-3.0.html#tokenFun

+

Example

+
class Items(Model):
+    id      = columns.Text(primary_key=True)
+    data    = columns.Bytes()
+
+query = Items.objects.all().limit(10)
+
+first_page = list(query);
+last = first_page[-1]
+next_page = list(query.filter(pk__token__gt=cqlengine.Token(last.pk)))
+
+
+
+
+

QuerySets are immutable

+

When calling any method that changes a queryset, the method does not actually change the queryset object it’s called on, but returns a new queryset object with the attributes of the original queryset, plus the attributes added in the method call.

+

Example

+
#this produces 3 different querysets
+#q does not change after it's initial definition
+q = Automobiles.objects.filter(year=2012)
+tesla2012 = q.filter(manufacturer='Tesla')
+honda2012 = q.filter(manufacturer='Honda')
+
+
+
+
+

Ordering QuerySets

+

Since Cassandra is essentially a distributed hash table on steroids, the order you get records back in will not be particularly predictable.

+

However, you can set a column to order on with the .order_by(column_name) method.

+

Example

+
#sort ascending
+q = Automobiles.objects.all().order_by('year')
+#sort descending
+q = Automobiles.objects.all().order_by('-year')
+
+
+

Note: Cassandra only supports ordering on a clustering key. In other words, to support ordering results, your model must have more than one primary key, and you must order on a primary key, excluding the first one.

+

For instance, given our Automobile model, year is the only column we can order on.

+
+
+

Values Lists

+

There is a special QuerySet’s method .values_list() - when called, QuerySet returns lists of values instead of model instances. It may significantly speedup things with lower memory footprint for large responses. +Each tuple contains the value from the respective field passed into the values_list() call — so the first item is the first field, etc. For example:

+
items = list(range(20))
+random.shuffle(items)
+for i in items:
+    TestModel.create(id=1, clustering_key=i)
+
+values = list(TestModel.objects.values_list('clustering_key', flat=True))
+# [19L, 18L, 17L, 16L, 15L, 14L, 13L, 12L, 11L, 10L, 9L, 8L, 7L, 6L, 5L, 4L, 3L, 2L, 1L, 0L]
+
+
+
+
+

Per Query Timeouts

+

By default all queries are executed with the timeout defined in ~cqlengine.connection.setup() +The examples below show how to specify a per-query timeout. +A timeout is specified in seconds and can be an int, float or None. +None means no timeout.

+
class Row(Model):
+    id = columns.Integer(primary_key=True)
+    name = columns.Text()
+
+
+

Fetch all objects with a timeout of 5 seconds

+
Row.objects().timeout(5).all()
+
+
+

Create a single row with a 50ms timeout

+
Row(id=1, name='Jon').timeout(0.05).create()
+
+
+

Delete a single row with no timeout

+
Row(id=1).timeout(None).delete()
+
+
+

Update a single row with no timeout

+
Row(id=1).timeout(None).update(name='Blake')
+
+
+

Batch query timeouts

+
with BatchQuery(timeout=10) as b:
+    Row(id=1, name='Jon').create()
+
+
+

NOTE: You cannot set both timeout and batch at the same time, batch will use the timeout defined in it’s constructor. +Setting the timeout on the model is meaningless and will raise an AssertionError.

+
+
+

Default TTL and Per Query TTL

+

Model default TTL now relies on the default_time_to_live feature, introduced in Cassandra 2.0. It is not handled anymore in the CQLEngine Model (scylla-driver >=3.6). You can set the default TTL of a table like this:

+

Example:

+
class User(Model):
+    __options__ = {'default_time_to_live': 20}
+
+    user_id = columns.UUID(primary_key=True)
+    ...
+
+
+

You can set TTL per-query if needed. Here are a some examples:

+

Example:

+
class User(Model):
+    __options__ = {'default_time_to_live': 20}
+
+    user_id = columns.UUID(primary_key=True)
+    ...
+
+user = User.objects.create(user_id=1)  # Default TTL 20 will be set automatically on the server
+
+user.ttl(30).update(age=21)            # Update the TTL to 30
+User.objects.ttl(10).create(user_id=1)  # TTL 10
+User(user_id=1, age=21).ttl(10).save()  # TTL 10
+
+
+
+
+

Named Tables

+

Named tables are a way of querying a table without creating an class. They’re useful for querying system tables or exploring an unfamiliar database.

+
from cassandra.cqlengine.connection import setup
+setup("127.0.0.1", "cqlengine_test")
+
+from cassandra.cqlengine.named import NamedTable
+user = NamedTable("cqlengine_test", "user")
+user.objects()
+user.objects()[0]
+
+# {u'pk': 1, u't': datetime.datetime(2014, 6, 26, 17, 10, 31, 774000)}
+
+
+
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/master/cqlengine/third-party.html b/master/cqlengine/third-party.html new file mode 100644 index 0000000000..4a293e3306 --- /dev/null +++ b/master/cqlengine/third-party.html @@ -0,0 +1,708 @@ + + + + + + + + + + + + + Third party integrations | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for an unstable version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

Third party integrations

+
+

Celery

+

Here’s how, in substance, CQLengine can be plugged to Celery:

+
from celery import Celery
+from celery.signals import worker_process_init, beat_init
+from cassandra.cqlengine import connection
+from cassandra.cqlengine.connection import (
+    cluster as cql_cluster, session as cql_session)
+
+def cassandra_init(**kwargs):
+    """ Initialize a clean Cassandra connection. """
+    if cql_cluster is not None:
+        cql_cluster.shutdown()
+    if cql_session is not None:
+        cql_session.shutdown()
+    connection.setup()
+
+# Initialize worker context for both standard and periodic tasks.
+worker_process_init.connect(cassandra_init)
+beat_init.connect(cassandra_init)
+
+app = Celery()
+
+
+
+
+

uWSGI

+

This is the code required for proper connection handling of CQLengine for a +uWSGI-run application:

+
from cassandra.cqlengine import connection
+from cassandra.cqlengine.connection import (
+    cluster as cql_cluster, session as cql_session)
+
+try:
+    from uwsgidecorators import postfork
+except ImportError:
+    # We're not in a uWSGI context, no need to hook Cassandra session
+    # initialization to the postfork event.
+    pass
+else:
+    @postfork
+    def cassandra_init(**kwargs):
+        """ Initialize a new Cassandra session in the context.
+
+        Ensures that a new session is returned for every new request.
+        """
+        if cql_cluster is not None:
+            cql_cluster.shutdown()
+        if cql_session is not None:
+            cql_session.shutdown()
+        connection.setup()
+
+
+
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/master/cqlengine/upgrade-guide.html b/master/cqlengine/upgrade-guide.html new file mode 100644 index 0000000000..cd6b12fc7b --- /dev/null +++ b/master/cqlengine/upgrade-guide.html @@ -0,0 +1,840 @@ + + + + + + + + + + + + + Upgrade Guide | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for an unstable version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + + + +
+

Upgrade Guide

+

This is an overview of things that changed as the cqlengine project was merged into +scylla-driver. While efforts were taken to preserve the API and most functionality exactly, +conversion to this package will still require certain minimal updates (namely, imports).

+

THERE IS ONE FUNCTIONAL CHANGE, described in the first section below.

+
+

Functional Changes

+
+

List Prepend Reversing

+

Legacy cqlengine included a workaround for a Cassandra bug in which prepended list segments were +reversed (CASSANDRA-8733). As of +this integration, this workaround is removed. The first released integrated version emits +a warning when prepend is used. Subsequent versions will have this warning removed.

+
+
+

Date Column Type

+

The Date column type in legacy cqlengine used a timestamp CQL type and truncated the time. +Going forward, the Date type represents a date for Cassandra 2.2+ +(PYTHON-245). +Users of the legacy functionality should convert models to use DateTime (which +uses timestamp internally), and use the build-in datetime.date for input values.

+
+
+
+

Remove cqlengine

+

To avoid confusion or mistakes using the legacy package in your application, it +is prudent to remove the cqlengine package when upgrading to the integrated version.

+

The driver setup script will warn if the legacy package is detected during install, +but it will not prevent side-by-side installation.

+
+
+

Organization

+
+

Imports

+

cqlengine is now integrated as a sub-package of the driver base package ‘cassandra’. +Upgrading will require adjusting imports to cqlengine. For example:

+
from cassandra.cqlengine import columns
+
+
+

is now:

+
from cassandra.cqlengine import columns
+
+
+
+
+

Package-Level Aliases

+

Legacy cqlengine defined a number of aliases at the package level, which became redundant +when the package was integrated for a driver. These have been removed in favor of absolute +imports, and referring to cannonical definitions. For example, cqlengine.ONE was an alias +of cassandra.ConsistencyLevel.ONE. In the integrated package, only the +cassandra.ConsistencyLevel remains.

+

Additionally, submodule aliases are removed from cqlengine in favor of absolute imports.

+

These aliases are removed, and not deprecated because they should be straightforward to iron out +at module load time.

+
+
+

Exceptions

+

The legacy cqlengine.exceptions module had a number of Exception classes that were variously +common to the package, or only used in specific modules. Common exceptions were relocated to +cqlengine, and specialized exceptions were placed in the module that raises them. Below is a +listing of updated locations:

+ ++++ + + + + + + + + + + + + + + + + + + + + + + + + + +

Exception class

New module

CQLEngineException

cassandra.cqlengine

ModelException

cassandra.cqlengine.models

ValidationError

cassandra.cqlengine

UndefinedKeyspaceException

cassandra.cqlengine.connection

LWTException

cassandra.cqlengine.query

IfNotExistsWithCounterColumn

cassandra.cqlengine.query

+
+
+

UnicodeMixin Consolidation

+

class UnicodeMixin was defined in several cqlengine modules. This has been consolidated +to a single definition in the cqlengine package init file. This is not technically part of +the API, but noted here for completeness.

+
+
+
+

API Deprecations

+

This upgrade served as a good juncture to deprecate certain API features and invite users to upgrade +to new ones. The first released version does not change functionality – only introduces deprecation +warnings. Future releases will remove these features in favor of the alternatives.

+
+

Float/Double Overload

+

Previously there was no Double column type. Doubles were modeled by specifying Float(double_precision=True). +This inititializer parameter is now deprecated. Applications should use Double for CQL double, and Float +for CQL float.

+
+
+

Schema Management

+

cassandra.cqlengine.management.create_keyspace is deprecated. Instead, use the new replication-strategy-specific +functions that accept explicit options for known strategies:

+ +

cassandra.cqlengine.management.delete_keyspace is deprecated in favor of a new function, drop_keyspace(). The +intent is simply to make the function match the CQL verb it invokes.

+
+
+

Model Inheritance

+

The names for class attributes controlling model inheritance are changing. Changes are as follows:

+ +

The functionality is unchanged – the intent here is to make the names and language around these attributes more precise. +For now, the old names are just deprecated, and the mapper will emit warnings if they are used. The old names +will be removed in a future version.

+

The example below shows a simple translation:

+

Before:

+
class Pet(Model):
+    __table_name__ = 'pet'
+    owner_id = UUID(primary_key=True)
+    pet_id = UUID(primary_key=True)
+    pet_type = Text(polymorphic_key=True)
+    name = Text()
+
+class Cat(Pet):
+    __polymorphic_key__ = 'cat'
+
+class Dog(Pet):
+    __polymorphic_key__ = 'dog'
+
+
+

After:

+
class Pet(models.Model):
+    __table_name__ = 'pet'
+    owner_id = UUID(primary_key=True)
+    pet_id = UUID(primary_key=True)
+    pet_type = Text(discriminator_column=True)
+    name = Text()
+
+class Cat(Pet):
+    __discriminator_value__ = 'cat'
+
+class Dog(Pet):
+    __discriminator_value__ = 'dog'
+
+
+
+
+

TimeUUID.from_datetime

+

This function is deprecated in favor of the core utility function uuid_from_time().

+
+
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/master/dates-and-times.html b/master/dates-and-times.html new file mode 100644 index 0000000000..1a80789cfe --- /dev/null +++ b/master/dates-and-times.html @@ -0,0 +1,732 @@ + + + + + + + + + + + + + Working with Dates and Times | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for an unstable version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

Working with Dates and Times

+

This document is meant to provide on overview of the assumptions and limitations of the driver time handling, the +reasoning behind it, and describe approaches to working with these types.

+
+

timestamps (Cassandra DateType)

+

Timestamps in Cassandra are timezone-naive timestamps encoded as millseconds since UNIX epoch. Clients working with +timestamps in this database usually find it easiest to reason about them if they are always assumed to be UTC. To quote the +pytz documentation, “The preferred way of dealing with times is to always work in UTC, converting to localtime only when +generating output to be read by humans.” The driver adheres to this tenant, and assumes UTC is always in the database. The +driver attempts to make this correct on the way in, and assumes no timezone on the way out.

+
+

Write Path

+

When inserting timestamps, the driver handles serialization for the write path as follows:

+

If the input is a datetime.datetime, the serialization is normalized by starting with the utctimetuple() of the +value.

+
    +
  • If the datetime object is timezone-aware, the timestamp is shifted, and represents the UTC timestamp equivalent.

  • +
  • If the datetime object is timezone-naive, this results in no shift – any datetime with no timezone information is assumed to be UTC

  • +
+

Note the second point above applies even to “local” times created using now():

+
>>> d = datetime.now()
+
+>>> print(d.tzinfo)
+None
+
+
+

These do not contain timezone information intrinsically, so they will be assumed to be UTC and not shifted. When generating +timestamps in the application, it is clearer to use datetime.utcnow() to be explicit about it.

+

If the input for a timestamp is numeric, it is assumed to be a epoch-relative millisecond timestamp, as specified in the +CQL spec – no scaling or conversion is done.

+
+
+

Read Path

+

The driver always assumes persisted timestamps are UTC and makes no attempt to localize them. Returned values are +timezone-naive datetime.datetime. We follow this approach because the datetime API has deficiencies around daylight +saving time, and the defacto package for handling this is a third-party package (we try to minimize external dependencies +and not make decisions for the integrator).

+

The decision for how to handle timezones is left to the application. For the most part it is straightforward to apply +localization to the datetimes returned by queries. One prevalent method is to use pytz for localization:

+
import pytz
+user_tz = pytz.timezone('US/Central')
+timestamp_naive = row.ts
+timestamp_utc = pytz.utc.localize(timestamp_naive)
+timestamp_presented = timestamp_utc.astimezone(user_tz)
+
+
+

This is the most robust approach (likely refactored into a function). If it is deemed too cumbersome to apply for all call +sites in the application, it is possible to patch the driver with custom deserialization for this type. However, doing +this depends depends some on internal APIs and what extensions are present, so we will only mention the possibility, and +not spell it out here.

+
+
+
+

date, time (Cassandra DateType)

+

Date and time in Cassandra are idealized markers, much like datetime.date and datetime.time in the Python standard +library. Unlike these Python implementations, the Cassandra encoding supports much wider ranges. To accommodate these +ranges without overflow, this driver returns these data in custom types: util.Date and util.Time.

+
+

Write Path

+

For simple (not prepared) statements, the input values for each of these can be either a string literal or an encoded +integer. See Working with dates +or Working with time for details +on the encoding or string formats.

+

For prepared statements, the driver accepts anything that can be used to construct the util.Date or +util.Time classes. See the linked API docs for details.

+
+
+

Read Path

+

The driver always returns custom types for date and time.

+

The driver returns util.Date for date in order to accommodate the wider range of values without overflow. +For applications working within the supported range of [datetime.MINYEAR, datetime.MAXYEAR], these are easily +converted to standard datetime.date insances using Date.date().

+

The driver returns util.Time for time in order to retain nanosecond precision stored in the database. +For applications not concerned with this level of precision, these are easily converted to standard datetime.time +insances using Time.time().

+
+
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/master/execution-profiles.html b/master/execution-profiles.html new file mode 100644 index 0000000000..82e7459668 --- /dev/null +++ b/master/execution-profiles.html @@ -0,0 +1,776 @@ + + + + + + + + + + + + + Execution Profiles | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for an unstable version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

Execution Profiles

+

Execution profiles aim at making it easier to execute requests in different ways within +a single connected Session. Execution profiles are being introduced to deal with the exploding number of +configuration options, especially as the database platform evolves more complex workloads.

+

The legacy configuration remains intact, but legacy and Execution Profile APIs +cannot be used simultaneously on the same client Cluster. Legacy configuration +will be removed in the next major release (4.0).

+

An execution profile and its parameters should be unique across Cluster instances. +For example, an execution profile and its LoadBalancingPolicy should +not be applied to more than one Cluster instance.

+

This document explains how Execution Profiles relate to existing settings, and shows how to use the new profiles for +request execution.

+
+

Mapping Legacy Parameters to Profiles

+

Execution profiles can inherit from cluster.ExecutionProfile, and currently provide the following options, +previously input from the noted attributes:

+ +

When using the new API, these parameters can be defined by instances of cluster.ExecutionProfile.

+
+
+

Using Execution Profiles

+
+

Default

+
from cassandra.cluster import Cluster
+cluster = Cluster()
+session = cluster.connect()
+local_query = 'SELECT rpc_address FROM system.local'
+for _ in cluster.metadata.all_hosts():
+    print session.execute(local_query)[0]
+
+
+
Row(rpc_address='127.0.0.2')
+Row(rpc_address='127.0.0.1')
+
+
+

The default execution profile is built from Cluster parameters and default Session attributes. This profile matches existing default +parameters.

+
+
+

Initializing cluster with profiles

+
from cassandra.cluster import ExecutionProfile
+from cassandra.policies import WhiteListRoundRobinPolicy
+
+node1_profile = ExecutionProfile(load_balancing_policy=WhiteListRoundRobinPolicy(['127.0.0.1']))
+node2_profile = ExecutionProfile(load_balancing_policy=WhiteListRoundRobinPolicy(['127.0.0.2']))
+
+profiles = {'node1': node1_profile, 'node2': node2_profile}
+session = Cluster(execution_profiles=profiles).connect()
+for _ in cluster.metadata.all_hosts():
+    print session.execute(local_query, execution_profile='node1')[0]
+
+
+
Row(rpc_address='127.0.0.1')
+Row(rpc_address='127.0.0.1')
+
+
+
for _ in cluster.metadata.all_hosts():
+    print session.execute(local_query, execution_profile='node2')[0]
+
+
+
Row(rpc_address='127.0.0.2')
+Row(rpc_address='127.0.0.2')
+
+
+
for _ in cluster.metadata.all_hosts():
+    print session.execute(local_query)[0]
+
+
+
Row(rpc_address='127.0.0.2')
+Row(rpc_address='127.0.0.1')
+
+
+

Note that, even when custom profiles are injected, the default TokenAwarePolicy(DCAwareRoundRobinPolicy()) is still +present. To override the default, specify a policy with the EXEC_PROFILE_DEFAULT key.

+
from cassandra.cluster import EXEC_PROFILE_DEFAULT
+profile = ExecutionProfile(request_timeout=30)
+cluster = Cluster(execution_profiles={EXEC_PROFILE_DEFAULT: profile})
+
+
+
+
+

Adding named profiles

+

New profiles can be added constructing from scratch, or deriving from default:

+
locked_execution = ExecutionProfile(load_balancing_policy=WhiteListRoundRobinPolicy(['127.0.0.1']))
+node1_profile = 'node1_whitelist'
+cluster.add_execution_profile(node1_profile, locked_execution)
+
+for _ in cluster.metadata.all_hosts():
+    print session.execute(local_query, execution_profile=node1_profile)[0]
+
+
+
Row(rpc_address='127.0.0.1')
+Row(rpc_address='127.0.0.1')
+
+
+

See Cluster.add_execution_profile() for details and optional parameters.

+
+
+

Passing a profile instance without mapping

+

We also have the ability to pass profile instances to be used for execution, but not added to the mapping:

+
from cassandra.query import tuple_factory
+
+tmp = session.execution_profile_clone_update('node1', request_timeout=100, row_factory=tuple_factory)
+
+print session.execute(local_query, execution_profile=tmp)[0]
+print session.execute(local_query, execution_profile='node1')[0]
+
+
+
('127.0.0.1',)
+Row(rpc_address='127.0.0.1')
+
+
+

The new profile is a shallow copy, so the tmp profile shares a load balancing policy with one managed by the cluster. +If reference objects are to be updated in the clone, one would typically set those attributes to a new instance.

+
+
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/master/faq.html b/master/faq.html new file mode 100644 index 0000000000..1c40088f05 --- /dev/null +++ b/master/faq.html @@ -0,0 +1,712 @@ + + + + + + + + + + + + + Frequently Asked Questions | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for an unstable version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

Frequently Asked Questions

+

See also cqlengine FAQ

+
+

Why do connections or IO operations timeout in my WSGI application?

+

Depending on your application process model, it may be forking after driver Session is created. Most IO reactors do not handle this, and problems will manifest as timeouts.

+

To avoid this, make sure to create sessions per process, after the fork. Using uWSGI and Flask for example:

+
from flask import Flask
+from uwsgidecorators import postfork
+from cassandra.cluster import Cluster
+
+session = None
+prepared = None
+
+@postfork
+def connect():
+    global session, prepared
+    session = Cluster().connect()
+    prepared = session.prepare("SELECT release_version FROM system.local WHERE key=?")
+
+app = Flask(__name__)
+
+@app.route('/')
+def server_version():
+    row = session.execute(prepared, ('local',))[0]
+    return row.release_version
+
+
+

uWSGI provides a postfork hook you can use to create sessions and prepared statements after the child process forks.

+
+
+

How do I trace a request?

+

Request tracing can be turned on for any request by setting trace=True in Session.execute_async(). View the results by waiting on the future, then ResponseFuture.get_query_trace(). +Since tracing is done asynchronously to the request, this method polls until the trace is complete before querying data.

+
>>> future = session.execute_async("SELECT * FROM system.local", trace=True)
+>>> result = future.result()
+>>> trace = future.get_query_trace()
+>>> for e in trace.events:
+>>>     print e.source_elapsed, e.description
+
+0:00:00.000077 Parsing select * from system.local
+0:00:00.000153 Preparing statement
+0:00:00.000309 Computing ranges to query
+0:00:00.000368 Submitting range requests on 1 ranges with a concurrency of 1 (279.77142 rows per range expected)
+0:00:00.000422 Submitted 1 concurrent range requests covering 1 ranges
+0:00:00.000480 Executing seq scan across 1 sstables for (min(-9223372036854775808), min(-9223372036854775808))
+0:00:00.000669 Read 1 live and 0 tombstone cells
+0:00:00.000755 Scanned 1 rows and matched 1
+
+
+

trace is a QueryTrace object.

+
+
+

How do I determine the replicas for a query?

+

With prepared statements, the replicas are obtained by routing_key, based on current cluster token metadata:

+
>>> prepared = session.prepare("SELECT * FROM example.t WHERE key=?")
+>>> bound = prepared.bind((1,))
+>>> replicas = cluster.metadata.get_replicas(bound.keyspace, bound.routing_key)
+>>> for h in replicas:
+>>>   print h.address
+127.0.0.1
+127.0.0.2
+
+
+

replicas is a list of Host objects.

+
+
+

How does the driver manage request retries?

+

By default, retries are managed by the Cluster.default_retry_policy set on the session Cluster. It can also +be specialized per statement by setting Statement.retry_policy.

+

Retries are presently attempted on the same coordinator, but this may change in the future.

+

Please see policies.RetryPolicy for further details.

+
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/master/getting-started.html b/master/getting-started.html new file mode 100644 index 0000000000..760fc59ff6 --- /dev/null +++ b/master/getting-started.html @@ -0,0 +1,1127 @@ + + + + + + + + + + + + + Getting Started | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for an unstable version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

Getting Started

+

First, make sure you have the driver properly installed.

+
+

Connecting to a Cluster

+

Before we can start executing any queries against a Cassandra cluster we need to setup +an instance of Cluster. As the name suggests, you will typically have one +instance of Cluster for each Cassandra cluster you want to interact +with.

+

First, make sure you have the Cassandra driver properly installed.

+
+

Connecting to Cassandra

+

The simplest way to create a Cluster is like this:

+
from cassandra.cluster import Cluster
+
+cluster = Cluster()
+
+
+

This will attempt to connection to a Cassandra instance on your +local machine (127.0.0.1). You can also specify a list of IP +addresses for nodes in your cluster:

+
from cassandra.cluster import Cluster
+
+cluster = Cluster(['192.168.0.1', '192.168.0.2'])
+
+
+

The set of IP addresses we pass to the Cluster is simply +an initial set of contact points. After the driver connects to one +of these nodes it will automatically discover the rest of the +nodes in the cluster and connect to them, so you don’t need to list +every node in your cluster.

+

If you need to use a non-standard port, use SSL, or customize the driver’s +behavior in some other way, this is the place to do it:

+
from cassandra.cluster import Cluster
+cluster = Cluster(['192.168.0.1', '192.168.0.2'], port=..., ssl_context=...)
+
+
+

Instantiating a Cluster does not actually connect us to any nodes. +To establish connections and begin executing queries we need a +Session, which is created by calling Cluster.connect():

+
cluster = Cluster()
+session = cluster.connect()
+
+
+
+
+
+

Session Keyspace

+

The connect() method takes an optional keyspace argument +which sets the default keyspace for all queries made through that Session:

+
cluster = Cluster()
+session = cluster.connect('mykeyspace')
+
+
+

You can always change a Session’s keyspace using set_keyspace() or +by executing a USE <keyspace> query:

+
session.set_keyspace('users')
+# or you can do this instead
+session.execute('USE users')
+
+
+
+
+

Execution Profiles

+

Profiles are passed in by execution_profiles dict.

+

In this case we can construct the base ExecutionProfile passing all attributes:

+
from cassandra.cluster import Cluster, ExecutionProfile, EXEC_PROFILE_DEFAULT
+from cassandra.policies import WhiteListRoundRobinPolicy, DowngradingConsistencyRetryPolicy
+from cassandra.query import tuple_factory
+
+profile = ExecutionProfile(
+    load_balancing_policy=WhiteListRoundRobinPolicy(['127.0.0.1']),
+    retry_policy=DowngradingConsistencyRetryPolicy(),
+    consistency_level=ConsistencyLevel.LOCAL_QUORUM,
+    serial_consistency_level=ConsistencyLevel.LOCAL_SERIAL,
+    request_timeout=15,
+    row_factory=tuple_factory
+)
+cluster = Cluster(execution_profiles={EXEC_PROFILE_DEFAULT: profile})
+session = cluster.connect()
+
+print(session.execute("SELECT release_version FROM system.local").one())
+
+
+

Users are free to setup additional profiles to be used by name:

+
profile_long = ExecutionProfile(request_timeout=30)
+cluster = Cluster(execution_profiles={'long': profile_long})
+session = cluster.connect()
+session.execute(statement, execution_profile='long')
+
+
+

Also, parameters passed to Session.execute or attached to Statements are still honored as before.

+
+
+

Executing Queries

+

Now that we have a Session we can begin to execute queries. The simplest +way to execute a query is to use execute():

+
rows = session.execute('SELECT name, age, email FROM users')
+for user_row in rows:
+    print user_row.name, user_row.age, user_row.email
+
+
+

This will transparently pick a Cassandra node to execute the query against +and handle any retries that are necessary if the operation fails.

+

By default, each row in the result set will be a +namedtuple. +Each row will have a matching attribute for each column defined in the schema, +such as name, age, and so on. You can also treat them as normal tuples +by unpacking them or accessing fields by position. The following three +examples are equivalent:

+
rows = session.execute('SELECT name, age, email FROM users')
+for row in rows:
+    print row.name, row.age, row.email
+
+
+
rows = session.execute('SELECT name, age, email FROM users')
+for (name, age, email) in rows:
+    print name, age, email
+
+
+
rows = session.execute('SELECT name, age, email FROM users')
+for row in rows:
+    print row[0], row[1], row[2]
+
+
+

If you prefer another result format, such as a dict per row, you +can change the row_factory attribute.

+

As mentioned in our Drivers Best Practices Guide, +it is highly recommended to use Prepared statements for your +frequently run queries.

+
+
+

Prepared Statements

+

Prepared statements are queries that are parsed by Cassandra and then saved +for later use. When the driver uses a prepared statement, it only needs to +send the values of parameters to bind. This lowers network traffic +and CPU utilization within Cassandra because Cassandra does not have to +re-parse the query each time.

+

To prepare a query, use Session.prepare():

+
user_lookup_stmt = session.prepare("SELECT * FROM users WHERE user_id=?")
+
+users = []
+for user_id in user_ids_to_query:
+    user = session.execute(user_lookup_stmt, [user_id])
+    users.append(user)
+
+
+

prepare() returns a PreparedStatement instance +which can be used in place of SimpleStatement instances or literal +string queries. It is automatically prepared against all nodes, and the driver +handles re-preparing against new nodes and restarted nodes when necessary.

+

Note that the placeholders for prepared statements are ? characters. This +is different than for simple, non-prepared statements (although future versions +of the driver may use the same placeholders for both).

+
+
+

Passing Parameters to CQL Queries

+

Althought it is not recommended, you can also pass parameters to non-prepared +statements. The driver supports two forms of parameter place-holders: positional +and named.

+

Positional parameters are used with a %s placeholder. For example, +when you execute:

+
session.execute(
+    """
+    INSERT INTO users (name, credits, user_id)
+    VALUES (%s, %s, %s)
+    """,
+    ("John O'Reilly", 42, uuid.uuid1())
+)
+
+
+

It is translated to the following CQL query:

+
INSERT INTO users (name, credits, user_id)
+VALUES ('John O''Reilly', 42, 2644bada-852c-11e3-89fb-e0b9a54a6d93)
+
+
+

Note that you should use %s for all types of arguments, not just strings. +For example, this would be wrong:

+
session.execute("INSERT INTO USERS (name, age) VALUES (%s, %d)", ("bob", 42))  # wrong
+
+
+

Instead, use %s for the age placeholder.

+

If you need to use a literal % character, use %%.

+

Note: you must always use a sequence for the second argument, even if you are +only passing in a single variable:

+
session.execute("INSERT INTO foo (bar) VALUES (%s)", "blah")  # wrong
+session.execute("INSERT INTO foo (bar) VALUES (%s)", ("blah"))  # wrong
+session.execute("INSERT INTO foo (bar) VALUES (%s)", ("blah", ))  # right
+session.execute("INSERT INTO foo (bar) VALUES (%s)", ["blah"])  # right
+
+
+

Note that the second line is incorrect because in Python, single-element tuples +require a comma.

+

Named place-holders use the %(name)s form:

+
session.execute(
+    """
+    INSERT INTO users (name, credits, user_id, username)
+    VALUES (%(name)s, %(credits)s, %(user_id)s, %(name)s)
+    """,
+    {'name': "John O'Reilly", 'credits': 42, 'user_id': uuid.uuid1()}
+)
+
+
+

Note that you can repeat placeholders with the same name, such as %(name)s +in the above example.

+

Only data values should be supplied this way. Other items, such as keyspaces, +table names, and column names should be set ahead of time (typically using +normal string formatting).

+
+
+

Type Conversions

+

For non-prepared statements, Python types are cast to CQL literals in the +following way:

+ ++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Python Type

CQL Literal Type

None

NULL

bool

boolean

float

+
float
+
double
+
+
+
int
+
long
+
+
+
int
+
bigint
+
varint
+
smallint
+
tinyint
+
counter
+
+

decimal.Decimal

decimal

+
str
+
unicode
+
+
+
ascii
+
varchar
+
text
+
+
+
buffer
+
bytearray
+
+

blob

date

date

datetime

timestamp

time

time

+
list
+
tuple
+
generator
+
+

list

+
set
+
frozenset
+
+

set

+
dict
+
OrderedDict
+
+

map

uuid.UUID

+
timeuuid
+
uuid
+
+
+
+
+

Asynchronous Queries

+

The driver supports asynchronous query execution through +execute_async(). Instead of waiting for the query to +complete and returning rows directly, this method almost immediately +returns a ResponseFuture object. There are two ways of +getting the final result from this object.

+

The first is by calling result() on it. If +the query has not yet completed, this will block until it has and +then return the result or raise an Exception if an error occurred. +For example:

+
from cassandra import ReadTimeout
+
+query = "SELECT * FROM users WHERE user_id=%s"
+future = session.execute_async(query, [user_id])
+
+# ... do some other work
+
+try:
+    rows = future.result()
+    user = rows[0]
+    print user.name, user.age
+except ReadTimeout:
+    log.exception("Query timed out:")
+
+
+

This works well for executing many queries concurrently:

+
# build a list of futures
+futures = []
+query = "SELECT * FROM users WHERE user_id=%s"
+for user_id in ids_to_fetch:
+    futures.append(session.execute_async(query, [user_id])
+
+# wait for them to complete and use the results
+for future in futures:
+    rows = future.result()
+    print rows[0].name
+
+
+

Alternatively, instead of calling result(), +you can attach callback and errback functions through the +add_callback(), +add_errback(), and +add_callbacks(), methods. If you have used +Twisted Python before, this is designed to be a lightweight version of +that:

+
def handle_success(rows):
+    user = rows[0]
+    try:
+        process_user(user.name, user.age, user.id)
+    except Exception:
+        log.error("Failed to process user %s", user.id)
+        # don't re-raise errors in the callback
+
+def handle_error(exception):
+    log.error("Failed to fetch user info: %s", exception)
+
+
+future = session.execute_async(query)
+future.add_callbacks(handle_success, handle_error)
+
+
+
+
There are a few important things to remember when working with callbacks:
    +
  • Exceptions that are raised inside the callback functions will be logged and then ignored.

  • +
  • Your callback will be run on the event loop thread, so any long-running +operations will prevent other requests from being handled

  • +
+
+
+
+
+

Setting a Consistency Level

+

The consistency level used for a query determines how many of the +replicas of the data you are interacting with need to respond for +the query to be considered a success.

+

By default, ConsistencyLevel.LOCAL_ONE will be used for all queries. +You can specify a different default by setting the ExecutionProfile.consistency_level +for the execution profile with key EXEC_PROFILE_DEFAULT. +To specify a different consistency level per request, wrap queries +in a SimpleStatement:

+
from cassandra import ConsistencyLevel
+from cassandra.query import SimpleStatement
+
+query = SimpleStatement(
+    "INSERT INTO users (name, age) VALUES (%s, %s)",
+    consistency_level=ConsistencyLevel.QUORUM)
+session.execute(query, ('John', 42))
+
+
+
+
+

Setting a Consistency Level with Prepared Statements

+

To specify a consistency level for prepared statements, you have two options.

+

The first is to set a default consistency level for every execution of the +prepared statement:

+
from cassandra import ConsistencyLevel
+
+cluster = Cluster()
+session = cluster.connect("mykeyspace")
+user_lookup_stmt = session.prepare("SELECT * FROM users WHERE user_id=?")
+user_lookup_stmt.consistency_level = ConsistencyLevel.QUORUM
+
+# these will both use QUORUM
+user1 = session.execute(user_lookup_stmt, [user_id1])[0]
+user2 = session.execute(user_lookup_stmt, [user_id2])[0]
+
+
+

The second option is to create a BoundStatement from the +PreparedStatement and binding parameters and set a consistency +level on that:

+
# override the QUORUM default
+user3_lookup = user_lookup_stmt.bind([user_id3])
+user3_lookup.consistency_level = ConsistencyLevel.ALL
+user3 = session.execute(user3_lookup)
+
+
+
+
+

Speculative Execution

+

Speculative execution is a way to minimize latency by preemptively executing several +instances of the same query against different nodes. For more details about this +technique, see Speculative Execution with DataStax Drivers.

+

To enable speculative execution:

+
    +
  • Configure a SpeculativeExecutionPolicy with the ExecutionProfile

  • +
  • Mark your query as idempotent, which mean it can be applied multiple +times without changing the result of the initial application. +See Query Idempotence for more details.

  • +
+

Example:

+
from cassandra.cluster import Cluster, ExecutionProfile, EXEC_PROFILE_DEFAULT
+from cassandra.policies import ConstantSpeculativeExecutionPolicy
+from cassandra.query import SimpleStatement
+
+# Configure the speculative execution policy
+ep = ExecutionProfile(
+    speculative_execution_policy=ConstantSpeculativeExecutionPolicy(delay=.5, max_attempts=10)
+)
+cluster = Cluster(..., execution_profiles={EXEC_PROFILE_DEFAULT: ep})
+session = cluster.connect()
+
+# Mark the query idempotent
+query = SimpleStatement(
+    "UPDATE my_table SET list_col = [1] WHERE pk = 1",
+    is_idempotent=True
+)
+
+# Execute. A new query will be sent to the server every 0.5 second
+# until we receive a response, for a max number attempts of 10.
+session.execute(query)
+
+
+
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/master/index.html b/master/index.html new file mode 100644 index 0000000000..cb000e0d9b --- /dev/null +++ b/master/index.html @@ -0,0 +1,704 @@ + + + + + + + + + + + + + Python Driver for Scylla and Apache Cassandra® | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for an unstable version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

Python Driver for Scylla and Apache Cassandra®

+

A Python client driver for Scylla. +This driver works exclusively with the Cassandra Query Language v3 (CQL3) +and Cassandra’s native protocol.

+

The driver supports Python 2.7, 3.5, 3.6, 3.7 and 3.8.

+

This driver is open source under the +Apache v2 License. +The source code for this driver can be found on GitHub.

+

Scylla Driver is a fork from DataStax Python Driver, including some non-breaking changes for Scylla optimization, with more updates planned.

+
+

Contents

+
+
Installation

How to install the driver.

+
+
Getting Started

A guide through the first steps of connecting to Scylla and executing queries

+
+
Scylla Specific Features

A list of feature available only on scylla-driver

+
+
Execution Profiles

An introduction to a more flexible way of configuring request execution

+
+
Lightweight Transactions (Compare-and-set)

Working with results of conditional requests

+
+
Object Mapper

Introduction to the integrated object mapper, cqlengine

+
+
Performance Notes

Tips for getting good performance.

+
+
Paging Large Queries

Notes on paging large query results

+
+
Security

An overview of the security features of the driver

+
+
Upgrading

A guide to upgrading versions of the driver

+
+
User Defined Types

Working with Scylla’s user-defined types (UDT)

+
+
Working with Dates and Times

Some discussion on the driver’s approach to working with timestamp, date, time types

+
+
ScyllaDB Cloud

Connect to ScyllaDB Cloud

+
+
ScyllaDB Cloud Serverless

Connect to ScyllaDB Cloud Serverless

+
+
CHANGELOG

Log of changes to the driver, organized by version.

+
+
Frequently Asked Questions

A collection of Frequently Asked Questions

+
+
API Documentation

The API documentation.

+
+
+
+
+
+
+

Getting Help

+

Visit the FAQ section in this documentation.

+

Please send questions to the Scylla user list.

+
+
+

Reporting Issues

+

Please report any bugs and make any feature requests on the Github project issues

+
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/master/installation.html b/master/installation.html new file mode 100644 index 0000000000..dec92de03e --- /dev/null +++ b/master/installation.html @@ -0,0 +1,875 @@ + + + + + + + + + + + + + Installation | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for an unstable version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

Installation

+
+

Supported Platforms

+

Python 2.7, 3.5, 3.6, 3.7 and 3.8 are supported. Both CPython (the standard Python +implementation) and PyPy are supported and tested.

+

Linux, OSX, and Windows are supported.

+
+
+

Installation through pip

+

pip is the suggested tool for installing +packages. It will handle installing all Python dependencies for the driver at +the same time as the driver itself. To install the driver*:

+
pip install scylla-driver
+
+
+

You can use pip install --pre scylla-driver if you need to install a beta version.

+

*Note: if intending to use optional extensions, install the dependencies first. The driver may need to be reinstalled if dependencies are added after the initial installation.

+
+
+

Verifying your Installation

+

To check if the installation was successful, you can run:

+
python -c 'import cassandra; print cassandra.__version__'
+
+
+

It should print something like “3.22.0”.

+
+
+

(Optional) Graph

+

The driver provides an optional fluent graph API that depends on Apache TinkerPop (gremlinpython). It is +not installed by default. To be able to build Gremlin traversals, you need to install +the graph requirements:

+
pip install scylla-driver[graph]
+
+
+
+
+

(Optional) Compression Support

+

Compression can optionally be used for communication between the driver and +Cassandra. There are currently two supported compression algorithms: +snappy (in Cassandra 1.2+) and LZ4 (only in Cassandra 2.0+). If either is +available for the driver and Cassandra also supports it, it will +be used automatically.

+

For lz4 support:

+
pip install lz4
+
+
+

For snappy support:

+
pip install python-snappy
+
+
+

(If using a Debian Linux derivative such as Ubuntu, it may be easier to +just run apt-get install python-snappy.)

+
+
+

(Optional) Metrics Support

+

The driver has built-in support for capturing Cluster.metrics about +the queries you run. However, the scales library is required to +support this:

+
pip install scales
+
+
+
+

Speeding Up Installation

+

By default, installing the driver through pip uses a pre-compiled, platform-specific wheel when available. +If using a source distribution rather than a wheel, Cython is used to compile certain parts of the driver. +This makes those hot paths faster at runtime, but the Cython compilation +process can take a long time – as long as 10 minutes in some environments.

+

In environments where performance is less important, it may be worth it to +disable Cython as documented below. +You can also use CASS_DRIVER_BUILD_CONCURRENCY to increase the number of +threads used to build the driver and any C extensions:

+
$ # installing from source
+$ CASS_DRIVER_BUILD_CONCURRENCY=8 python setup.py install
+$ # installing from pip
+$ CASS_DRIVER_BUILD_CONCURRENCY=8 pip install scylla-driver
+
+
+
+
+

OSX Installation Error

+

If you’re installing on OSX and have XCode 5.1 installed, you may see an error like this:

+
clang: error: unknown argument: '-mno-fused-madd' [-Wunused-command-line-argument-hard-error-in-future]
+
+
+

To fix this, re-run the installation with an extra compilation flag:

+
ARCHFLAGS=-Wno-error=unused-command-line-argument-hard-error-in-future pip install scylla-driver
+
+
+
+
+
+

Windows Installation Notes

+

Installing the driver with extensions in Windows sometimes presents some challenges. A few notes about common +hang-ups:

+

Setup requires a compiler. When using Python 2, this is as simple as installing this package +(this link is also emitted during install if setuptools is unable to find the resources it needs). Depending on your +system settings, this package may install as a user-specific application. Make sure to install for everyone, or at least +as the user that will be building the Python environment.

+

It is also possible to run the build with your compiler of choice. Just make sure to have your environment setup with +the proper paths. Make sure the compiler target architecture matches the bitness of your Python runtime. +Perhaps the easiest way to do this is to run the build/install from a Visual Studio Command Prompt (a +shortcut installed with Visual Studio that sources the appropriate environment and presents a shell).

+
+
+

Manual Installation

+

You can always install the driver directly from a source checkout or tarball. +When installing manually, ensure the python dependencies are already +installed. You can find the list of dependencies in +requirements.txt.

+

Once the dependencies are installed, simply run:

+
python setup.py install
+
+
+
+
+

(Optional) Non-python Dependencies

+

The driver has several optional features that have non-Python dependencies.

+
+

C Extensions

+

By default, a number of extensions are compiled, providing faster hashing +for token-aware routing with the Murmur3Partitioner, +libev event loop integration, +and Cython optimized extensions.

+

When installing manually through setup.py, you can disable both with +the --no-extensions option, or selectively disable them with +with --no-murmur3, --no-libev, or --no-cython.

+

To compile the extensions, ensure that GCC and the Python headers are available.

+

On Ubuntu and Debian, this can be accomplished by running:

+
$ sudo apt-get install gcc python-dev
+
+
+

On RedHat and RedHat-based systems like CentOS and Fedora:

+
$ sudo yum install gcc python-devel
+
+
+

On OS X, homebrew installations of Python should provide the necessary headers.

+

See Windows Installation Notes for notes on configuring the build environment on Windows.

+
+

Cython-based Extensions

+

By default, this package uses Cython to optimize core modules and build custom extensions. +This is not a hard requirement, but is engaged by default to build extensions offering better performance than the +pure Python implementation.

+

This is a costly build phase, especially in clean environments where the Cython compiler must be built +This build phase can be avoided using the build switch, or an environment variable:

+
python setup.py install --no-cython
+
+
+

Alternatively, an environment variable can be used to switch this option regardless of +context:

+
CASS_DRIVER_NO_CYTHON=1 <your script here>
+- or, to disable all extensions:
+CASS_DRIVER_NO_EXTENSIONS=1 <your script here>
+
+
+

This method is required when using pip, which provides no other way of injecting user options in a single command:

+
CASS_DRIVER_NO_CYTHON=1 pip install scylla-driver
+CASS_DRIVER_NO_CYTHON=1 sudo -E pip install ~/python-driver
+
+
+

The environment variable is the preferred option because it spans all invocations of setup.py, and will +prevent Cython from being materialized as a setup requirement.

+

If your sudo configuration does not allow SETENV, you must push the option flag down via pip. However, pip +applies these options to all dependencies (which break on the custom flag). Therefore, you must first install +dependencies, then use install-option:

+
sudo pip install six futures
+sudo pip install --install-option="--no-cython"
+
+
+
+
+
+

libev support

+

The driver currently uses Python’s asyncore module for its default +event loop. For better performance, libev is also supported through +a C extension.

+

If you’re on Linux, you should be able to install libev +through a package manager. For example, on Debian/Ubuntu:

+
$ sudo apt-get install libev4 libev-dev
+
+
+

On RHEL/CentOS/Fedora:

+
$ sudo yum install libev libev-devel
+
+
+

If you’re on Mac OS X, you should be able to install libev +through Homebrew. For example, on Mac OS X:

+
$ brew install libev
+
+
+

The libev extension is not built for Windows (the build process is complex, and the Windows implementation uses +select anyway).

+

If successful, you should be able to build and install the extension +(just using setup.py build or setup.py install) and then use +the libev event loop by doing the following:

+
>>> from cassandra.io.libevreactor import LibevConnection
+>>> from cassandra.cluster import Cluster
+
+>>> cluster = Cluster()
+>>> cluster.connection_class = LibevConnection
+>>> session = cluster.connect()
+
+
+
+
+
+

(Optional) Configuring SSL

+

Andrew Mussey has published a thorough guide on +Using SSL with the DataStax Python driver.

+
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/master/lwt.html b/master/lwt.html new file mode 100644 index 0000000000..499c676a4f --- /dev/null +++ b/master/lwt.html @@ -0,0 +1,735 @@ + + + + + + + + + + + + + Lightweight Transactions (Compare-and-set) | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for an unstable version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

Lightweight Transactions (Compare-and-set)

+

Lightweight Transactions (LWTs) are mostly pass-through CQL for the driver. However, +the server returns some specialized results indicating the outcome and optional state +preceding the transaction.

+

For pertinent execution parameters, see Statement.serial_consistency_level.

+

This section discusses working with specialized result sets returned by the server for LWTs, +and how to work with them using the driver.

+
+

Specialized Results

+

The result returned from a LWT request is always a single row result. It will always have +prepended a special column named [applied]. How this value appears in your results depends +on the row factory in use. See below for examples.

+

The value of this [applied] column is boolean value indicating whether or not the transaction was applied. +If True, it is the only column in the result. If False, the additional columns depend on the LWT operation being +executed:

+
    +
  • When using a UPDATE ... IF "col" = ... clause, the result will contain the [applied] column, plus the existing columns +and values for any columns in the IF clause (and thus the value that caused the transaction to fail).

  • +
  • When using INSERT ... IF NOT EXISTS, the result will contain the [applied] column, plus all columns and values +of the existing row that rejected the transaction.

  • +
  • UPDATE .. IF EXISTS never has additional columns, regardless of [applied] status.

  • +
+

How the [applied] column manifests depends on the row factory in use. Considering the following (initially empty) table:

+
CREATE TABLE test.t (
+    k int PRIMARY KEY,
+    v int,
+    x int
+)
+
+
+

… the following sections show the expected result for a number of example statements, using the three base row factories.

+
+

named_tuple_factory (default)

+

The name [applied] is not a valid Python identifier, so the square brackets are actually removed +from the attribute for the resulting namedtuple. The row always has a boolean column applied in position 0:

+
>>> session.execute("INSERT INTO t (k,v) VALUES (0,0) IF NOT EXISTS")
+Row(applied=True)
+
+>>> session.execute("INSERT INTO t (k,v) VALUES (0,0) IF NOT EXISTS")
+Row(applied=False, k=0, v=0, x=None)
+
+>>> session.execute("UPDATE t SET v = 1, x = 2 WHERE k = 0 IF v =0")
+Row(applied=True)
+
+>>> session.execute("UPDATE t SET v = 1, x = 2 WHERE k = 0 IF v =0 AND x = 1")
+Row(applied=False, v=1, x=2)
+
+
+
+
+

tuple_factory

+

This return type does not refer to names, but the boolean value applied is always present in position 0:

+
>>> session.execute("INSERT INTO t (k,v) VALUES (0,0) IF NOT EXISTS")
+(True,)
+
+>>> session.execute("INSERT INTO t (k,v) VALUES (0,0) IF NOT EXISTS")
+(False, 0, 0, None)
+
+>>> session.execute("UPDATE t SET v = 1, x = 2 WHERE k = 0 IF v =0")
+(True,)
+
+>>> session.execute("UPDATE t SET v = 1, x = 2 WHERE k = 0 IF v =0 AND x = 1")
+(False, 1, 2)
+
+
+
+
+

dict_factory

+

The retuned dict contains the [applied] key:

+
>>> session.execute("INSERT INTO t (k,v) VALUES (0,0) IF NOT EXISTS")
+{u'[applied]': True}
+
+>>> session.execute("INSERT INTO t (k,v) VALUES (0,0) IF NOT EXISTS")
+{u'x': 2, u'[applied]': False, u'v': 1}
+
+>>> session.execute("UPDATE t SET v = 1, x = 2 WHERE k = 0 IF v =0")
+{u'x': None, u'[applied]': False, u'k': 0, u'v': 0}
+
+>>> session.execute("UPDATE t SET v = 1, x = 2 WHERE k = 0 IF v =0 AND x = 1")
+{u'[applied]': True}
+
+
+
+
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/master/object-mapper.html b/master/object-mapper.html new file mode 100644 index 0000000000..ee990ecb13 --- /dev/null +++ b/master/object-mapper.html @@ -0,0 +1,732 @@ + + + + + + + + + + + + + Object Mapper | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for an unstable version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

Object Mapper

+

cqlengine is the Cassandra CQL 3 Object Mapper packaged with this driver

+

Jump to Getting Started

+
+

Contents

+
+
Upgrade Guide

For migrating projects from legacy cqlengine, to the integrated product

+
+
Models

Examples defining models, and mapping them to tables

+
+
Making Queries

Overview of query sets and filtering

+
+
Batch Queries

Working with batch mutations

+
+
Connections

Working with multiple sessions

+
+
API Documentation

Index of API documentation

+
+
Third party integrations

High-level examples in Celery and uWSGI

+
+
+

Frequently Asked Questions

+
+
+
+
+

Getting Started

+
import uuid
+from cassandra.cqlengine import columns
+from cassandra.cqlengine import connection
+from datetime import datetime
+from cassandra.cqlengine.management import sync_table
+from cassandra.cqlengine.models import Model
+
+#first, define a model
+class ExampleModel(Model):
+    example_id      = columns.UUID(primary_key=True, default=uuid.uuid4)
+    example_type    = columns.Integer(index=True)
+    created_at      = columns.DateTime()
+    description     = columns.Text(required=False)
+
+#next, setup the connection to your cassandra server(s)...
+# see http://datastax.github.io/python-driver/api/cassandra/cluster.html for options
+# the list of hosts will be passed to create a Cluster() instance
+connection.setup(['127.0.0.1'], "cqlengine", protocol_version=3)
+
+#...and create your CQL table
+>>> sync_table(ExampleModel)
+
+#now we can create some rows:
+>>> em1 = ExampleModel.create(example_type=0, description="example1", created_at=datetime.now())
+>>> em2 = ExampleModel.create(example_type=0, description="example2", created_at=datetime.now())
+>>> em3 = ExampleModel.create(example_type=0, description="example3", created_at=datetime.now())
+>>> em4 = ExampleModel.create(example_type=0, description="example4", created_at=datetime.now())
+>>> em5 = ExampleModel.create(example_type=1, description="example5", created_at=datetime.now())
+>>> em6 = ExampleModel.create(example_type=1, description="example6", created_at=datetime.now())
+>>> em7 = ExampleModel.create(example_type=1, description="example7", created_at=datetime.now())
+>>> em8 = ExampleModel.create(example_type=1, description="example8", created_at=datetime.now())
+
+#and now we can run some queries against our table
+>>> ExampleModel.objects.count()
+8
+>>> q = ExampleModel.objects(example_type=1)
+>>> q.count()
+4
+>>> for instance in q:
+>>>     print instance.description
+example5
+example6
+example7
+example8
+
+#here we are applying additional filtering to an existing query
+#query objects are immutable, so calling filter returns a new
+#query object
+>>> q2 = q.filter(example_id=em5.example_id)
+
+>>> q2.count()
+1
+>>> for instance in q2:
+>>>     print instance.description
+example5
+
+
+
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/master/objects.inv b/master/objects.inv new file mode 100644 index 0000000000..0ea4f4d635 Binary files /dev/null and b/master/objects.inv differ diff --git a/master/performance.html b/master/performance.html new file mode 100644 index 0000000000..e789791e0b --- /dev/null +++ b/master/performance.html @@ -0,0 +1,686 @@ + + + + + + + + + + + + + Performance Notes | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for an unstable version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

Performance Notes

+

The Python driver for Cassandra offers several methods for executing queries. +You can synchronously block for queries to complete using +Session.execute(), you can obtain asynchronous request futures through +Session.execute_async(), and you can attach a callback to the future +with ResponseFuture.add_callback().

+

Examples of multiple request patterns can be found in the benchmark scripts included in the driver project.

+

The choice of execution pattern will depend on the application context. For applications dealing with multiple +requests in a given context, the recommended pattern is to use concurrent asynchronous +requests with callbacks. For many use cases, you don’t need to implement this pattern yourself. +cassandra.concurrent.execute_concurrent() and cassandra.concurrent.execute_concurrent_with_args() +provide this pattern with a synchronous API and tunable concurrency.

+

Due to the GIL and limited concurrency, the driver can become CPU-bound pretty quickly. The sections below +discuss further runtime and design considerations for mitigating this limitation.

+
+

PyPy

+

PyPy is an alternative Python runtime which uses a JIT compiler to +reduce CPU consumption. This leads to a huge improvement in the driver performance, +more than doubling throughput for many workloads.

+
+
+

Cython Extensions

+

Cython is an optimizing compiler and language that can be used to compile the core files and +optional extensions for the driver. Cython is not a strict dependency, but the extensions will be built by default.

+

See Installation for details on controlling this build.

+
+
+

multiprocessing

+

All of the patterns discussed above may be used over multiple processes using the +multiprocessing +module. Multiple processes will scale better than multiple threads, so if high throughput is your goal, +consider this option.

+

Be sure to never share any Cluster, Session, +or ResponseFuture objects across multiple processes. These +objects should all be created after forking the process, not before.

+

For further discussion and simple examples using the driver with multiprocessing, +see this blog post.

+
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/master/py-modindex.html b/master/py-modindex.html new file mode 100644 index 0000000000..77f43c9331 --- /dev/null +++ b/master/py-modindex.html @@ -0,0 +1,619 @@ + + + + + + + + + + + + + Python Module Index | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for an unstable version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ + + +
+ + + + + +
+ + +
+
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/master/query-paging.html b/master/query-paging.html new file mode 100644 index 0000000000..6d6d02aaa7 --- /dev/null +++ b/master/query-paging.html @@ -0,0 +1,740 @@ + + + + + + + + + + + + + Paging Large Queries | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for an unstable version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

Paging Large Queries

+

Cassandra 2.0+ offers support for automatic query paging. Starting with +version 2.0 of the driver, if protocol_version is greater than +2 (it is by default), queries returning large result sets will be +automatically paged.

+
+

Controlling the Page Size

+

By default, Session.default_fetch_size controls how many rows will +be fetched per page. This can be overridden per-query by setting +fetch_size on a Statement. By default, each page +will contain at most 5000 rows.

+
+
+

Handling Paged Results

+

Whenever the number of result rows for are query exceed the page size, an +instance of PagedResult will be returned instead of a normal +list. This class implements the iterator interface, so you can treat +it like a normal iterator over rows:

+
from cassandra.query import SimpleStatement
+query = "SELECT * FROM users"  # users contains 100 rows
+statement = SimpleStatement(query, fetch_size=10)
+for user_row in session.execute(statement):
+    process_user(user_row)
+
+
+

Whenever there are no more rows in the current page, the next page will +be fetched transparently. However, note that it is possible for +an Exception to be raised while fetching the next page, just +like you might see on a normal call to session.execute().

+

If you use Session.execute_async() along with, +ResponseFuture.result(), the first page will be fetched before +result() returns, but latter pages will be +transparently fetched synchronously while iterating the result.

+
+
+

Handling Paged Results with Callbacks

+

If callbacks are attached to a query that returns a paged result, +the callback will be called once per page with a normal list of rows.

+

Use ResponseFuture.has_more_pages and +ResponseFuture.start_fetching_next_page() to continue fetching +pages. For example:

+
class PagedResultHandler(object):
+
+    def __init__(self, future):
+        self.error = None
+        self.finished_event = Event()
+        self.future = future
+        self.future.add_callbacks(
+            callback=self.handle_page,
+            errback=self.handle_err)
+
+    def handle_page(self, rows):
+        for row in rows:
+            process_row(row)
+
+        if self.future.has_more_pages:
+            self.future.start_fetching_next_page()
+        else:
+            self.finished_event.set()
+
+    def handle_error(self, exc):
+        self.error = exc
+        self.finished_event.set()
+
+future = session.execute_async("SELECT * FROM users")
+handler = PagedResultHandler(future)
+handler.finished_event.wait()
+if handler.error:
+    raise handler.error
+
+
+
+
+

Resume Paged Results

+

You can resume the pagination when executing a new query by using the ResultSet.paging_state. This can be useful if you want to provide some stateless pagination capabilities to your application (ie. via http). For example:

+
from cassandra.query import SimpleStatement
+query = "SELECT * FROM users"
+statement = SimpleStatement(query, fetch_size=10)
+results = session.execute(statement)
+
+# save the paging_state somewhere and return current results
+web_session['paging_state'] = results.paging_state
+
+
+# resume the pagination sometime later...
+statement = SimpleStatement(query, fetch_size=10)
+ps = web_session['paging_state']
+results = session.execute(statement, paging_state=ps)
+
+
+
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/master/scylla-cloud-serverless.html b/master/scylla-cloud-serverless.html new file mode 100644 index 0000000000..fb37ee7ca4 --- /dev/null +++ b/master/scylla-cloud-serverless.html @@ -0,0 +1,678 @@ + + + + + + + + + + + + + ScyllaDB Cloud Serverless | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for an unstable version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

ScyllaDB Cloud Serverless

+

With ScyllaDB Cloud, you can deploy serverless databases. +The Python driver allows you to connect to a serverless database by utilizing the connection bundle you can download via the Connect>Python tab in the Cloud application. +The connection bundle is a YAML file with connection and credential information for your cluster.

+

Connecting to a ScyllaDB Cloud serverless database is very similar to a standard connection to a ScyllaDB database.

+

Here’s a short program that connects to a ScyllaDB Cloud serverless database and prints metadata about the cluster:

+
from cassandra.cluster import Cluster, ExecutionProfile, EXEC_PROFILE_DEFAULT
+from cassandra.policies import DCAwareRoundRobinPolicy, TokenAwarePolicy
+
+PATH_TO_BUNDLE_YAML = '/file/downloaded/from/cloud/connect-bundle.yaml'
+
+
+def get_cluster():
+    profile = ExecutionProfile(
+        load_balancing_policy=TokenAwarePolicy(
+            DCAwareRoundRobinPolicy(local_dc='us-east-1')
+        )
+    )
+
+    return Cluster(
+        execution_profiles={EXEC_PROFILE_DEFAULT: profile},
+        scylla_cloud=PATH_TO_BUNDLE_YAML,
+    )
+
+
+print('Connecting to cluster')
+cluster = get_cluster()
+session = cluster.connect()
+
+print('Connected to cluster', cluster.metadata.cluster_name)
+
+print('Getting metadata')
+for host in cluster.metadata.all_hosts():
+    print('Datacenter: {}; Host: {}; Rack: {}'.format(
+        host.datacenter, host.address, host.rack)
+    )
+
+cluster.shutdown()
+
+
+

By providing the scylla_cloud parameter to the Cluster constructor, +the driver can set up the connection based on the endpoint and credential information +stored in your downloaded ScyllaDB Cloud Serverless connection bundle.

+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/master/scylla-cloud.html b/master/scylla-cloud.html new file mode 100644 index 0000000000..0e04c5dbd9 --- /dev/null +++ b/master/scylla-cloud.html @@ -0,0 +1,638 @@ + + + + + + + + + + + + + ScyllaDB Cloud | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for an unstable version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

ScyllaDB Cloud

+

To connect to a ScyllaDB Cloud cluster, go to the Cluster Connect page, Python example. +For best performance, make sure to use the Scylla Driver.

+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/master/scylla-specific.html b/master/scylla-specific.html new file mode 100644 index 0000000000..47ed01b6d3 --- /dev/null +++ b/master/scylla-specific.html @@ -0,0 +1,747 @@ + + + + + + + + + + + + + Scylla Specific Features | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for an unstable version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

Scylla Specific Features

+
+

Shard Awareness

+

scylla-driver is shard aware and contains extensions that work with the TokenAwarePolicy supported by Scylla 2.3 and onwards. Using this policy, the driver can select a connection to a particular shard based on the shard’s token. +As a result, latency is significantly reduced because there is no need to pass data between the shards.

+

Details on the scylla cql protocol extensions +https://github.com/scylladb/scylla/blob/master/docs/dev/protocol-extensions.md#intranode-sharding

+

For using it you only need to enable TokenAwarePolicy on the Cluster

+

See the configuration of native_shard_aware_transport_port and native_shard_aware_transport_port_ssl on scylla.yaml: +https://github.com/scylladb/scylla/blob/master/docs/dev/protocols.md#cql-client-protocol

+
from cassandra.cluster import Cluster
+from cassandra.policies import TokenAwarePolicy, RoundRobinPolicy
+
+cluster = Cluster(load_balancing_policy=TokenAwarePolicy(RoundRobinPolicy()))
+
+
+
+
+

New Cluster Helpers

+
    +
  • shard_aware_options

    +

    Setting it to dict(disable=True) would disable the shard aware functionally, for cases favoring once connection per host (example, lots of processes connecting from one client host, generating a big load of connections

    +

    Other option is to configure scylla by setting enable_shard_aware_drivers: false on scylla.yaml.

    +
  • +
+
from cassandra.cluster import Cluster
+
+cluster = Cluster(shard_aware_options=dict(disable=True))
+session = cluster.connect()
+
+assert not cluster.is_shard_aware(), "Shard aware should be disabled"
+
+# or just disable the shard aware port logic
+cluster = Cluster(shard_aware_options=dict(disable_shardaware_port=True))
+session = cluster.connect()
+
+
+
    +
  • cluster.is_shard_aware()

    +

    New method available on Cluster allowing to check whether the remote cluster supports shard awareness (bool)

    +
  • +
+
from cassandra.cluster import Cluster
+
+cluster = Cluster()
+session = cluster.connect()
+
+if cluster.is_shard_aware():
+    print("connected to a scylla cluster")
+
+
+
    +
  • cluster.shard_aware_stats()

    +

    New method available on Cluster allowing to check the status of shard aware connections to all available hosts (dict)

    +
  • +
+
from cassandra.cluster import Cluster
+
+cluster = Cluster()
+session = cluster.connect()
+
+stats = cluster.shard_aware_stats()
+if all([v["shards_count"] == v["connected"] for v in stats.values()]):
+    print("successfully connected to all shards of all scylla nodes")
+
+
+
+
+

New Table Attributes

+
    +
  • in_memory flag

    +

    New flag available on TableMetadata.options to indicate that it is an In Memory table

    +
  • +
+
+

Note

+

in memory tables is a feature existing only in Scylla Enterprise

+
+
from cassandra.cluster import Cluster
+
+cluster = Cluster()
+session = cluster.connect()
+session.execute("""
+    CREATE KEYSPACE IF NOT EXISTS keyspace1
+    WITH replication = {'class': 'SimpleStrategy', 'replication_factor': '1'};
+""")
+
+session.execute("""
+    CREATE TABLE IF NOT EXISTS keyspace1.standard1 (
+        key blob PRIMARY KEY,
+        "C0" blob
+    ) WITH in_memory=true AND compaction={'class': 'InMemoryCompactionStrategy'}
+""")
+
+cluster.refresh_table_metadata("keyspace1", "standard1")
+assert cluster.metadata.keyspaces["keyspace1"].tables["standard1"].options["in_memory"] == True
+
+
+
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/master/search.html b/master/search.html new file mode 100644 index 0000000000..bf617c1a21 --- /dev/null +++ b/master/search.html @@ -0,0 +1,622 @@ + + + + + + + + + + + + + Search | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for an unstable version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + + + + + +
+ + + + + +
+ + +
+
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/master/searchindex.js b/master/searchindex.js new file mode 100644 index 0000000000..663c47bbad --- /dev/null +++ b/master/searchindex.js @@ -0,0 +1 @@ +Search.setIndex({docnames:["CHANGELOG","api/cassandra","api/cassandra/auth","api/cassandra/cluster","api/cassandra/concurrent","api/cassandra/connection","api/cassandra/cqlengine/columns","api/cassandra/cqlengine/connection","api/cassandra/cqlengine/management","api/cassandra/cqlengine/models","api/cassandra/cqlengine/query","api/cassandra/cqlengine/usertype","api/cassandra/datastax/graph/fluent/index","api/cassandra/datastax/graph/fluent/predicates","api/cassandra/datastax/graph/fluent/query","api/cassandra/datastax/graph/index","api/cassandra/decoder","api/cassandra/encoder","api/cassandra/graph","api/cassandra/io/asyncioreactor","api/cassandra/io/asyncorereactor","api/cassandra/io/eventletreactor","api/cassandra/io/geventreactor","api/cassandra/io/libevreactor","api/cassandra/io/twistedreactor","api/cassandra/metadata","api/cassandra/metrics","api/cassandra/policies","api/cassandra/pool","api/cassandra/protocol","api/cassandra/query","api/cassandra/timestamps","api/cassandra/util","api/index","cqlengine/batches","cqlengine/connections","cqlengine/faq","cqlengine/models","cqlengine/queryset","cqlengine/third-party","cqlengine/upgrade-guide","dates-and-times","execution-profiles","faq","getting-started","index","installation","lwt","object-mapper","performance","query-paging","scylla-cloud","scylla-cloud-serverless","scylla-specific","security","upgrading","user-defined-types"],envversion:{"sphinx.domains.c":2,"sphinx.domains.changeset":1,"sphinx.domains.citation":1,"sphinx.domains.cpp":4,"sphinx.domains.index":1,"sphinx.domains.javascript":2,"sphinx.domains.math":2,"sphinx.domains.python":3,"sphinx.domains.rst":2,"sphinx.domains.std":2,"sphinx.ext.todo":2,sphinx:56},filenames:["CHANGELOG.rst","api/cassandra.rst","api/cassandra/auth.rst","api/cassandra/cluster.rst","api/cassandra/concurrent.rst","api/cassandra/connection.rst","api/cassandra/cqlengine/columns.rst","api/cassandra/cqlengine/connection.rst","api/cassandra/cqlengine/management.rst","api/cassandra/cqlengine/models.rst","api/cassandra/cqlengine/query.rst","api/cassandra/cqlengine/usertype.rst","api/cassandra/datastax/graph/fluent/index.rst","api/cassandra/datastax/graph/fluent/predicates.rst","api/cassandra/datastax/graph/fluent/query.rst","api/cassandra/datastax/graph/index.rst","api/cassandra/decoder.rst","api/cassandra/encoder.rst","api/cassandra/graph.rst","api/cassandra/io/asyncioreactor.rst","api/cassandra/io/asyncorereactor.rst","api/cassandra/io/eventletreactor.rst","api/cassandra/io/geventreactor.rst","api/cassandra/io/libevreactor.rst","api/cassandra/io/twistedreactor.rst","api/cassandra/metadata.rst","api/cassandra/metrics.rst","api/cassandra/policies.rst","api/cassandra/pool.rst","api/cassandra/protocol.rst","api/cassandra/query.rst","api/cassandra/timestamps.rst","api/cassandra/util.rst","api/index.rst","cqlengine/batches.rst","cqlengine/connections.rst","cqlengine/faq.rst","cqlengine/models.rst","cqlengine/queryset.rst","cqlengine/third-party.rst","cqlengine/upgrade-guide.rst","dates-and-times.rst","execution-profiles.rst","faq.rst","getting-started.rst","index.rst","installation.rst","lwt.rst","object-mapper.rst","performance.rst","query-paging.rst","scylla-cloud.rst","scylla-cloud-serverless.rst","scylla-specific.rst","security.rst","upgrading.rst","user-defined-types.rst"],objects:{"":[[1,0,0,"-","cassandra"]],"cassandra.AlreadyExists":[[1,2,1,"","keyspace"],[1,2,1,"","table"]],"cassandra.ConsistencyLevel":[[1,2,1,"","ALL"],[1,2,1,"","ANY"],[1,2,1,"","EACH_QUORUM"],[1,2,1,"","LOCAL_ONE"],[1,2,1,"","LOCAL_QUORUM"],[1,2,1,"","LOCAL_SERIAL"],[1,2,1,"","ONE"],[1,2,1,"","QUORUM"],[1,2,1,"","SERIAL"],[1,2,1,"","THREE"],[1,2,1,"","TWO"]],"cassandra.CoordinationFailure":[[1,2,1,"","consistency"],[1,2,1,"","error_code_map"],[1,2,1,"","failures"],[1,2,1,"","received_responses"],[1,2,1,"","required_responses"]],"cassandra.FunctionFailure":[[1,2,1,"","arg_types"],[1,2,1,"","function"],[1,2,1,"","keyspace"]],"cassandra.OperationTimedOut":[[1,2,1,"","errors"],[1,2,1,"","last_host"]],"cassandra.ProtocolVersion":[[1,2,1,"","BETA_VERSIONS"],[1,2,1,"","DSE_V1"],[1,2,1,"","DSE_V2"],[1,2,1,"","MAX_SUPPORTED"],[1,2,1,"","MIN_SUPPORTED"],[1,2,1,"","SUPPORTED_VERSIONS"],[1,2,1,"","V1"],[1,2,1,"","V2"],[1,2,1,"","V3"],[1,2,1,"","V4"],[1,2,1,"","V5"],[1,2,1,"","V6"],[1,4,1,"","get_lower_supported"]],"cassandra.ReadFailure":[[1,2,1,"","data_retrieved"]],"cassandra.ReadTimeout":[[1,2,1,"","data_retrieved"]],"cassandra.Timeout":[[1,2,1,"","consistency"],[1,2,1,"","received_responses"],[1,2,1,"","required_responses"]],"cassandra.Unavailable":[[1,2,1,"","alive_replicas"],[1,2,1,"","consistency"],[1,2,1,"","required_replicas"]],"cassandra.UserAggregateDescriptor":[[1,2,1,"","argument_types"],[1,2,1,"","name"],[1,5,1,"","signature"]],"cassandra.UserFunctionDescriptor":[[1,2,1,"","argument_types"],[1,2,1,"","name"],[1,5,1,"","signature"]],"cassandra.WriteFailure":[[1,2,1,"","write_type"]],"cassandra.WriteTimeout":[[1,2,1,"","write_type"]],"cassandra.auth":[[2,3,1,"","AuthProvider"],[2,3,1,"","Authenticator"],[2,3,1,"","PlainTextAuthProvider"],[2,3,1,"","PlainTextAuthenticator"],[2,3,1,"","SaslAuthProvider"],[2,3,1,"","SaslAuthenticator"]],"cassandra.auth.AuthProvider":[[2,4,1,"","new_authenticator"]],"cassandra.auth.Authenticator":[[2,4,1,"","evaluate_challenge"],[2,4,1,"","initial_response"],[2,4,1,"","on_authentication_success"],[2,2,1,"","server_authenticator_class"]],"cassandra.auth.PlainTextAuthProvider":[[2,4,1,"","new_authenticator"]],"cassandra.auth.PlainTextAuthenticator":[[2,4,1,"","evaluate_challenge"]],"cassandra.auth.SaslAuthProvider":[[2,4,1,"","new_authenticator"]],"cassandra.auth.SaslAuthenticator":[[2,4,1,"","evaluate_challenge"],[2,4,1,"","initial_response"]],"cassandra.cluster":[[3,3,1,"","Cluster"],[3,6,1,"","EXEC_PROFILE_DEFAULT"],[3,6,1,"","EXEC_PROFILE_GRAPH_ANALYTICS_DEFAULT"],[3,6,1,"","EXEC_PROFILE_GRAPH_DEFAULT"],[3,6,1,"","EXEC_PROFILE_GRAPH_SYSTEM_DEFAULT"],[3,3,1,"","ExecutionProfile"],[3,3,1,"","GraphAnalyticsExecutionProfile"],[3,3,1,"","GraphExecutionProfile"],[3,1,1,"","NoHostAvailable"],[3,1,1,"","QueryExhausted"],[3,3,1,"","ResponseFuture"],[3,3,1,"","ResultSet"],[3,3,1,"","Session"],[3,1,1,"","UserTypeDoesNotExist"]],"cassandra.cluster.Cluster":[[3,4,1,"","add_execution_profile"],[3,2,1,"","address_translator"],[3,2,1,"","auth_provider"],[3,2,1,"","cloud"],[3,2,1,"","compression"],[3,4,1,"","connect"],[3,2,1,"","connect_timeout"],[3,2,1,"","connection_class"],[3,2,1,"","contact_points"],[3,2,1,"","control_connection_timeout"],[3,2,1,"","conviction_policy_factory"],[3,2,1,"","cql_version"],[3,2,1,"","default_retry_policy"],[3,2,1,"","endpoint_factory"],[3,4,1,"","get_control_connection_host"],[3,4,1,"","get_core_connections_per_host"],[3,4,1,"","get_max_connections_per_host"],[3,4,1,"","get_max_requests_per_connection"],[3,4,1,"","get_min_requests_per_connection"],[3,2,1,"","idle_heartbeat_interval"],[3,2,1,"","idle_heartbeat_timeout"],[3,2,1,"","load_balancing_policy"],[3,2,1,"","max_schema_agreement_wait"],[3,2,1,"","metadata"],[3,2,1,"","metrics"],[3,2,1,"","metrics_enabled"],[3,2,1,"","port"],[3,2,1,"","prepare_on_all_hosts"],[3,2,1,"","protocol_version"],[3,2,1,"","reconnection_policy"],[3,4,1,"","refresh_keyspace_metadata"],[3,4,1,"","refresh_nodes"],[3,4,1,"","refresh_schema_metadata"],[3,4,1,"","refresh_table_metadata"],[3,4,1,"","refresh_user_aggregate_metadata"],[3,4,1,"","refresh_user_function_metadata"],[3,4,1,"","refresh_user_type_metadata"],[3,4,1,"","register_listener"],[3,4,1,"","register_user_type"],[3,2,1,"","reprepare_on_up"],[3,2,1,"","schema_event_refresh_window"],[3,2,1,"","schema_metadata_enabled"],[3,4,1,"","set_core_connections_per_host"],[3,4,1,"","set_max_connections_per_host"],[3,4,1,"","set_max_requests_per_connection"],[3,4,1,"","set_meta_refresh_enabled"],[3,4,1,"","set_min_requests_per_connection"],[3,4,1,"","shutdown"],[3,2,1,"","sockopts"],[3,2,1,"","ssl_context"],[3,2,1,"","ssl_options"],[3,2,1,"","status_event_refresh_window"],[3,2,1,"","timestamp_generator"],[3,2,1,"","token_metadata_enabled"],[3,2,1,"","topology_event_refresh_window"],[3,4,1,"","unregister_listener"]],"cassandra.cluster.ExecutionProfile":[[3,2,1,"","consistency_level"],[3,4,1,"","row_factory"]],"cassandra.cluster.ResponseFuture":[[3,4,1,"","add_callback"],[3,4,1,"","add_errback"],[3,2,1,"","custom_payload"],[3,4,1,"","get_all_query_traces"],[3,4,1,"","get_query_trace"],[3,2,1,"","has_more_pages"],[3,2,1,"","is_schema_agreed"],[3,2,1,"","query"],[3,4,1,"","result"],[3,4,1,"","start_fetching_next_page"],[3,2,1,"","warnings"]],"cassandra.cluster.ResultSet":[[3,4,1,"","all"],[3,5,1,"","current_rows"],[3,4,1,"","fetch_next_page"],[3,4,1,"","get_all_query_traces"],[3,4,1,"","get_query_trace"],[3,5,1,"","has_more_pages"],[3,4,1,"","one"],[3,5,1,"","paging_state"],[3,5,1,"","was_applied"]],"cassandra.cluster.Session":[[3,4,1,"","add_request_init_listener"],[3,2,1,"","client_protocol_handler"],[3,2,1,"","default_consistency_level"],[3,2,1,"","default_fetch_size"],[3,2,1,"","default_serial_consistency_level"],[3,2,1,"","default_timeout"],[3,2,1,"","encoder"],[3,4,1,"","execute"],[3,4,1,"","execute_async"],[3,4,1,"","execute_graph"],[3,4,1,"","execute_graph_async"],[3,4,1,"","execution_profile_clone_update"],[3,4,1,"","get_execution_profile"],[3,4,1,"","prepare"],[3,4,1,"","remove_request_init_listener"],[3,2,1,"","row_factory"],[3,4,1,"","set_keyspace"],[3,4,1,"","shutdown"],[3,2,1,"","timestamp_generator"],[3,2,1,"","use_client_timestamp"]],"cassandra.concurrent":[[4,7,1,"","execute_concurrent"],[4,7,1,"","execute_concurrent_with_args"]],"cassandra.connection":[[5,1,1,"","ConnectionBusy"],[5,1,1,"","ConnectionException"],[5,1,1,"","ConnectionShutdown"],[5,3,1,"","EndPoint"],[5,3,1,"","EndPointFactory"],[5,1,1,"","ProtocolError"],[5,3,1,"","SniEndPoint"],[5,3,1,"","SniEndPointFactory"],[5,3,1,"","UnixSocketEndPoint"]],"cassandra.connection.EndPoint":[[5,5,1,"","address"],[5,5,1,"","port"],[5,4,1,"","resolve"],[5,5,1,"","socket_family"],[5,5,1,"","ssl_options"]],"cassandra.connection.EndPointFactory":[[5,4,1,"","configure"],[5,4,1,"","create"]],"cassandra.cqlengine":[[6,0,0,"-","columns"],[7,0,0,"-","connection"],[8,0,0,"-","management"],[9,0,0,"-","models"],[10,0,0,"-","query"],[11,0,0,"-","usertype"]],"cassandra.cqlengine.columns":[[6,3,1,"","Ascii"],[6,3,1,"","BigInt"],[6,3,1,"","Blob"],[6,3,1,"","Boolean"],[6,2,1,"","Bytes"],[6,3,1,"","Column"],[6,3,1,"","Counter"],[6,3,1,"","Date"],[6,3,1,"","DateTime"],[6,3,1,"","Decimal"],[6,3,1,"","Double"],[6,3,1,"","Float"],[6,3,1,"","Integer"],[6,3,1,"","List"],[6,3,1,"","Map"],[6,3,1,"","Set"],[6,3,1,"","SmallInt"],[6,3,1,"","Text"],[6,3,1,"","Time"],[6,3,1,"","TimeUUID"],[6,3,1,"","TinyInt"],[6,3,1,"","UUID"],[6,3,1,"","UserDefinedType"],[6,3,1,"","VarInt"]],"cassandra.cqlengine.columns.Column":[[6,2,1,"","clustering_order"],[6,2,1,"","custom_index"],[6,2,1,"","db_field"],[6,2,1,"","default"],[6,2,1,"","discriminator_column"],[6,2,1,"","index"],[6,2,1,"","partition_key"],[6,2,1,"","primary_key"],[6,2,1,"","required"],[6,2,1,"","static"]],"cassandra.cqlengine.columns.DateTime":[[6,2,1,"","truncate_microseconds"]],"cassandra.cqlengine.connection":[[7,7,1,"","default"],[7,7,1,"","register_connection"],[7,7,1,"","set_default_connection"],[7,7,1,"","set_session"],[7,7,1,"","setup"],[7,7,1,"","unregister_connection"]],"cassandra.cqlengine.management":[[8,7,1,"","create_keyspace_network_topology"],[8,7,1,"","create_keyspace_simple"],[8,7,1,"","drop_keyspace"],[8,7,1,"","drop_table"],[8,7,1,"","sync_table"],[8,7,1,"","sync_type"]],"cassandra.cqlengine.models":[[9,3,1,"","Model"]],"cassandra.cqlengine.models.Model":[[9,2,1,"","__abstract__"],[9,2,1,"","__compute_routing_key__"],[9,2,1,"","__connection__"],[9,2,1,"","__default_ttl__"],[9,2,1,"","__discriminator_value__"],[9,2,1,"","__keyspace__"],[9,2,1,"","__options__"],[9,2,1,"","__table_name__"],[9,2,1,"","__table_name_case_sensitive__"],[9,4,1,"","all"],[9,4,1,"","batch"],[9,4,1,"","column_family_name"],[9,4,1,"","create"],[9,4,1,"","delete"],[9,4,1,"","filter"],[9,4,1,"","get"],[9,4,1,"","if_exists"],[9,4,1,"","if_not_exists"],[9,4,1,"","iff"],[9,4,1,"","items"],[9,4,1,"","keys"],[9,4,1,"","len"],[9,4,1,"","save"],[9,4,1,"","timeout"],[9,4,1,"","timestamp"],[9,4,1,"","ttl"],[9,4,1,"","update"],[9,4,1,"","using"],[9,4,1,"","values"]],"cassandra.cqlengine.query":[[10,3,1,"","BatchQuery"],[10,3,1,"","ContextQuery"],[10,3,1,"","DoesNotExist"],[10,3,1,"","LWTException"],[10,3,1,"","ModelQuerySet"],[10,3,1,"","MultipleObjectsReturned"]],"cassandra.cqlengine.query.BatchQuery":[[10,4,1,"","add_callback"],[10,4,1,"","add_query"],[10,4,1,"","execute"]],"cassandra.cqlengine.query.ModelQuerySet":[[10,4,1,"","all"],[10,4,1,"","allow_filtering"],[10,4,1,"","batch"],[10,4,1,"","consistency"],[10,4,1,"","count"],[10,4,1,"","defer"],[10,4,1,"","distinct"],[10,4,1,"","fetch_size"],[10,4,1,"","filter"],[10,4,1,"","get"],[10,4,1,"","if_exists"],[10,4,1,"","if_not_exists"],[10,4,1,"","len"],[10,4,1,"","limit"],[10,4,1,"","only"],[10,4,1,"","order_by"],[10,4,1,"","timestamp"],[10,4,1,"","ttl"],[10,4,1,"","update"],[10,4,1,"","using"]],"cassandra.cqlengine.usertype":[[11,3,1,"","UserType"]],"cassandra.cqlengine.usertype.UserType":[[11,2,1,"","__type_name__"]],"cassandra.datastax":[[15,0,0,"-","graph"]],"cassandra.datastax.graph":[[12,0,0,"-","fluent"],[15,7,1,"","graph_graphson2_row_factory"],[15,7,1,"","graph_graphson3_row_factory"],[15,7,1,"","graph_object_row_factory"],[15,7,1,"","graph_result_row_factory"],[15,7,1,"","single_object_row_factory"],[15,7,1,"","to_bigint"],[15,7,1,"","to_double"],[15,7,1,"","to_float"],[15,7,1,"","to_int"],[15,7,1,"","to_smallint"]],"cassandra.datastax.graph.GraphOptions":[[15,2,1,"","graph_language"],[15,2,1,"","graph_name"],[15,2,1,"","graph_read_consistency_level"],[15,2,1,"","graph_source"],[15,2,1,"","graph_write_consistency_level"],[15,2,1,"","is_analytics_source"],[15,2,1,"","is_default_source"],[15,2,1,"","is_graph_source"],[15,4,1,"","set_source_analytics"],[15,4,1,"","set_source_default"],[15,4,1,"","set_source_graph"]],"cassandra.datastax.graph.GraphSON1Deserializer":[[15,4,1,"","deserialize_bigint"],[15,4,1,"","deserialize_blob"],[15,4,1,"","deserialize_date"],[15,4,1,"","deserialize_decimal"],[15,4,1,"","deserialize_double"],[15,4,1,"","deserialize_duration"],[15,4,1,"","deserialize_float"],[15,4,1,"","deserialize_int"],[15,4,1,"","deserialize_linestring"],[15,4,1,"","deserialize_point"],[15,4,1,"","deserialize_polygon"],[15,4,1,"","deserialize_time"],[15,4,1,"","deserialize_timestamp"],[15,4,1,"","deserialize_uuid"]],"cassandra.datastax.graph.fluent":[[12,3,1,"","BaseGraphRowFactory"],[12,3,1,"","DSESessionRemoteGraphConnection"],[12,3,1,"","DseGraph"],[12,2,1,"","graph_traversal_dse_object_row_factory"],[12,2,1,"","graph_traversal_row_factory"],[13,0,0,"-","predicates"],[14,0,0,"-","query"]],"cassandra.datastax.graph.fluent.DseGraph":[[12,2,1,"","DSE_GRAPH_QUERY_LANGUAGE"],[12,4,1,"","batch"],[12,4,1,"","create_execution_profile"],[12,4,1,"","query_from_traversal"],[12,4,1,"","traversal_source"]],"cassandra.datastax.graph.fluent.predicates":[[13,3,1,"","CqlCollection"],[13,3,1,"","Geo"],[13,3,1,"","Search"]],"cassandra.datastax.graph.fluent.predicates.CqlCollection":[[13,4,1,"","contains"],[13,4,1,"","contains_key"],[13,4,1,"","contains_value"],[13,4,1,"","entry_eq"]],"cassandra.datastax.graph.fluent.predicates.Geo":[[13,4,1,"","inside"]],"cassandra.datastax.graph.fluent.predicates.Search":[[13,4,1,"","fuzzy"],[13,4,1,"","phrase"],[13,4,1,"","prefix"],[13,4,1,"","regex"],[13,4,1,"","token"],[13,4,1,"","token_fuzzy"],[13,4,1,"","token_prefix"],[13,4,1,"","token_regex"]],"cassandra.datastax.graph.fluent.query":[[14,3,1,"","TraversalBatch"]],"cassandra.datastax.graph.fluent.query.TraversalBatch":[[14,4,1,"","add"],[14,4,1,"","add_all"],[14,4,1,"","as_graph_statement"],[14,4,1,"","clear"],[14,4,1,"","execute"]],"cassandra.decoder":[[16,7,1,"","dict_factory"],[16,7,1,"","named_tuple_factory"],[16,7,1,"","ordered_dict_factory"],[16,7,1,"","tuple_factory"]],"cassandra.encoder":[[17,3,1,"","Encoder"]],"cassandra.encoder.Encoder":[[17,4,1,"","cql_encode_all_types"],[17,4,1,"","cql_encode_bytes"],[17,4,1,"","cql_encode_date"],[17,4,1,"","cql_encode_datetime"],[17,4,1,"","cql_encode_list_collection"],[17,4,1,"","cql_encode_map_collection"],[17,4,1,"","cql_encode_none"],[17,4,1,"","cql_encode_object"],[17,4,1,"","cql_encode_sequence"],[17,4,1,"","cql_encode_set_collection"],[17,4,1,"","cql_encode_str"],[17,4,1,"","cql_encode_tuple"],[17,4,1,"","cql_encode_unicode"],[17,2,1,"","mapping"]],"cassandra.graph":[[18,3,1,"","Edge"],[18,3,1,"","GraphOptions"],[18,3,1,"","GraphProtocol"],[18,3,1,"","GraphSON1Deserializer"],[18,3,1,"","GraphSON1Serializer"],[18,3,1,"","GraphSON2Reader"],[18,3,1,"","GraphSON3Reader"],[18,3,1,"","Path"],[18,3,1,"","Result"],[18,3,1,"","SimpleGraphStatement"],[18,3,1,"","Vertex"],[18,3,1,"","VertexProperty"],[18,7,1,"","graph_graphson2_row_factory"],[18,7,1,"","graph_graphson3_row_factory"],[18,7,1,"","graph_object_row_factory"],[18,7,1,"","graph_result_row_factory"],[18,7,1,"","single_object_row_factory"],[18,7,1,"","to_bigint"],[18,7,1,"","to_double"],[18,7,1,"","to_float"],[18,7,1,"","to_int"],[18,7,1,"","to_smallint"]],"cassandra.graph.GraphOptions":[[18,2,1,"","graph_language"],[18,2,1,"","graph_name"],[18,2,1,"","graph_read_consistency_level"],[18,2,1,"","graph_source"],[18,2,1,"","graph_write_consistency_level"],[18,2,1,"","is_analytics_source"],[18,2,1,"","is_default_source"],[18,2,1,"","is_graph_source"],[18,4,1,"","set_source_analytics"],[18,4,1,"","set_source_default"],[18,4,1,"","set_source_graph"]],"cassandra.graph.GraphProtocol":[[18,2,1,"","GRAPHSON_1_0"],[18,2,1,"","GRAPHSON_2_0"],[18,2,1,"","GRAPHSON_3_0"]],"cassandra.graph.GraphSON1Deserializer":[[18,4,1,"","deserialize_bigint"],[18,4,1,"","deserialize_blob"],[18,4,1,"","deserialize_date"],[18,4,1,"","deserialize_decimal"],[18,4,1,"","deserialize_double"],[18,4,1,"","deserialize_duration"],[18,4,1,"","deserialize_float"],[18,4,1,"","deserialize_int"],[18,4,1,"","deserialize_linestring"],[18,4,1,"","deserialize_point"],[18,4,1,"","deserialize_polygon"],[18,4,1,"","deserialize_time"],[18,4,1,"","deserialize_timestamp"],[18,4,1,"","deserialize_uuid"]],"cassandra.graph.GraphSON2Reader":[[18,4,1,"","deserialize"],[18,4,1,"","read"]],"cassandra.graph.Path":[[18,2,1,"","labels"],[18,2,1,"","objects"]],"cassandra.graph.Result":[[18,4,1,"","as_edge"],[18,4,1,"","as_path"],[18,4,1,"","as_vertex"],[18,2,1,"","value"]],"cassandra.graph.VertexProperty":[[18,2,1,"","label"],[18,2,1,"","properties"],[18,2,1,"","value"]],"cassandra.io":[[19,0,0,"-","asyncioreactor"],[20,0,0,"-","asyncorereactor"],[21,0,0,"-","eventletreactor"],[22,0,0,"-","geventreactor"],[23,0,0,"-","libevreactor"],[24,0,0,"-","twistedreactor"]],"cassandra.io.asyncioreactor":[[19,3,1,"","AsyncioConnection"]],"cassandra.io.asyncioreactor.AsyncioConnection":[[19,4,1,"","initialize_reactor"]],"cassandra.io.asyncorereactor":[[20,3,1,"","AsyncoreConnection"]],"cassandra.io.asyncorereactor.AsyncoreConnection":[[20,4,1,"","handle_fork"],[20,4,1,"","initialize_reactor"]],"cassandra.io.eventletreactor":[[21,3,1,"","EventletConnection"]],"cassandra.io.eventletreactor.EventletConnection":[[21,4,1,"","initialize_reactor"],[21,4,1,"","service_timeouts"]],"cassandra.io.geventreactor":[[22,3,1,"","GeventConnection"]],"cassandra.io.geventreactor.GeventConnection":[[22,4,1,"","initialize_reactor"]],"cassandra.io.libevreactor":[[23,3,1,"","LibevConnection"]],"cassandra.io.twistedreactor":[[24,3,1,"","TwistedConnection"]],"cassandra.metadata":[[25,3,1,"","Aggregate"],[25,3,1,"","BytesToken"],[25,3,1,"","ColumnMetadata"],[25,3,1,"","EdgeMetadata"],[25,3,1,"","Function"],[25,3,1,"","IndexMetadata"],[25,3,1,"","KeyspaceMetadata"],[25,3,1,"","LocalStrategy"],[25,3,1,"","MD5Token"],[25,3,1,"","MaterializedViewMetadata"],[25,3,1,"","Metadata"],[25,3,1,"","Murmur3Token"],[25,3,1,"","NetworkTopologyStrategy"],[25,3,1,"","ReplicationFactor"],[25,2,1,"","ReplicationStrategy"],[25,3,1,"","SimpleStrategy"],[25,3,1,"","TableMetadata"],[25,3,1,"","TableMetadataDSE68"],[25,3,1,"","TableMetadataV3"],[25,3,1,"","Token"],[25,3,1,"","TokenMap"],[25,3,1,"","UserType"],[25,3,1,"","VertexMetadata"],[25,6,1,"","cql_keywords"],[25,6,1,"","cql_keywords_reserved"],[25,6,1,"","cql_keywords_unreserved"],[25,7,1,"","group_keys_by_replica"]],"cassandra.metadata.Aggregate":[[25,4,1,"","as_cql_query"]],"cassandra.metadata.BytesToken":[[25,4,1,"","from_string"]],"cassandra.metadata.Function":[[25,4,1,"","as_cql_query"]],"cassandra.metadata.IndexMetadata":[[25,4,1,"","as_cql_query"],[25,4,1,"","export_as_string"]],"cassandra.metadata.KeyspaceMetadata":[[25,4,1,"","as_cql_query"],[25,4,1,"","export_as_string"]],"cassandra.metadata.LocalStrategy":[[25,4,1,"","export_for_schema"]],"cassandra.metadata.MaterializedViewMetadata":[[25,4,1,"","as_cql_query"]],"cassandra.metadata.Metadata":[[25,4,1,"","add_or_return_host"],[25,4,1,"","all_hosts"],[25,4,1,"","export_schema_as_string"],[25,4,1,"","get_host"],[25,4,1,"","get_host_by_host_id"],[25,4,1,"","get_replicas"]],"cassandra.metadata.NetworkTopologyStrategy":[[25,4,1,"","export_for_schema"]],"cassandra.metadata.SimpleStrategy":[[25,4,1,"","export_for_schema"],[25,5,1,"","replication_factor"]],"cassandra.metadata.TableMetadata":[[25,4,1,"","as_cql_query"],[25,4,1,"","export_as_string"],[25,5,1,"","is_cql_compatible"],[25,5,1,"","primary_key"]],"cassandra.metadata.TableMetadataDSE68":[[25,4,1,"","as_cql_query"]],"cassandra.metadata.TableMetadataV3":[[25,5,1,"","is_cql_compatible"]],"cassandra.metadata.TokenMap":[[25,4,1,"","get_replicas"]],"cassandra.metadata.UserType":[[25,4,1,"","as_cql_query"]],"cassandra.metrics":[[26,3,1,"","Metrics"]],"cassandra.metrics.Metrics":[[26,2,1,"","connected_to"],[26,2,1,"","connection_errors"],[26,4,1,"","get_stats"],[26,2,1,"","ignores"],[26,2,1,"","known_hosts"],[26,2,1,"","open_connections"],[26,2,1,"","other_errors"],[26,2,1,"","read_timeouts"],[26,2,1,"","request_timer"],[26,2,1,"","retries"],[26,4,1,"","set_stats_name"],[26,2,1,"","unavailables"],[26,2,1,"","write_timeouts"]],"cassandra.policies":[[27,3,1,"","AddressTranslator"],[27,3,1,"","ConstantReconnectionPolicy"],[27,3,1,"","ConstantSpeculativeExecutionPolicy"],[27,3,1,"","ConvictionPolicy"],[27,3,1,"","DCAwareRoundRobinPolicy"],[27,3,1,"","DSELoadBalancingPolicy"],[27,3,1,"","DefaultLoadBalancingPolicy"],[27,3,1,"","DowngradingConsistencyRetryPolicy"],[27,3,1,"","EC2MultiRegionTranslator"],[27,3,1,"","ExponentialReconnectionPolicy"],[27,3,1,"","FallthroughRetryPolicy"],[27,3,1,"","HostDistance"],[27,3,1,"","HostFilterPolicy"],[27,3,1,"","IdentityTranslator"],[27,3,1,"","LoadBalancingPolicy"],[27,3,1,"","ReconnectionPolicy"],[27,3,1,"","RetryPolicy"],[27,3,1,"","RoundRobinPolicy"],[27,3,1,"","SimpleConvictionPolicy"],[27,3,1,"","SpeculativeExecutionPolicy"],[27,3,1,"","TokenAwarePolicy"],[27,3,1,"","WhiteListRoundRobinPolicy"],[27,3,1,"","WriteType"]],"cassandra.policies.AddressTranslator":[[27,4,1,"","translate"]],"cassandra.policies.ConstantReconnectionPolicy":[[27,4,1,"","new_schedule"]],"cassandra.policies.ConstantSpeculativeExecutionPolicy":[[27,4,1,"","new_plan"]],"cassandra.policies.ConvictionPolicy":[[27,4,1,"","add_failure"],[27,4,1,"","reset"]],"cassandra.policies.DCAwareRoundRobinPolicy":[[27,4,1,"","distance"],[27,4,1,"","make_query_plan"],[27,4,1,"","on_add"],[27,4,1,"","on_down"],[27,4,1,"","on_remove"],[27,4,1,"","on_up"],[27,4,1,"","populate"]],"cassandra.policies.DefaultLoadBalancingPolicy":[[27,4,1,"","make_query_plan"],[27,4,1,"","populate"]],"cassandra.policies.DowngradingConsistencyRetryPolicy":[[27,4,1,"","on_read_timeout"],[27,4,1,"","on_unavailable"],[27,4,1,"","on_write_timeout"]],"cassandra.policies.EC2MultiRegionTranslator":[[27,4,1,"","translate"]],"cassandra.policies.ExponentialReconnectionPolicy":[[27,4,1,"","new_schedule"]],"cassandra.policies.FallthroughRetryPolicy":[[27,4,1,"","on_read_timeout"],[27,4,1,"","on_request_error"],[27,4,1,"","on_unavailable"],[27,4,1,"","on_write_timeout"]],"cassandra.policies.HostDistance":[[27,2,1,"","IGNORED"],[27,2,1,"","LOCAL"],[27,2,1,"","REMOTE"]],"cassandra.policies.HostFilterPolicy":[[27,4,1,"","distance"],[27,4,1,"","make_query_plan"],[27,4,1,"","predicate"]],"cassandra.policies.IdentityTranslator":[[27,4,1,"","translate"]],"cassandra.policies.LoadBalancingPolicy":[[27,4,1,"","check_supported"],[27,4,1,"","distance"],[27,4,1,"","make_query_plan"],[27,4,1,"","populate"]],"cassandra.policies.ReconnectionPolicy":[[27,4,1,"","new_schedule"]],"cassandra.policies.RetryPolicy":[[27,2,1,"","IGNORE"],[27,2,1,"","RETHROW"],[27,2,1,"","RETRY"],[27,2,1,"","RETRY_NEXT_HOST"],[27,4,1,"","on_read_timeout"],[27,4,1,"","on_request_error"],[27,4,1,"","on_unavailable"],[27,4,1,"","on_write_timeout"]],"cassandra.policies.RoundRobinPolicy":[[27,4,1,"","distance"],[27,4,1,"","make_query_plan"],[27,4,1,"","on_add"],[27,4,1,"","on_down"],[27,4,1,"","on_remove"],[27,4,1,"","on_up"],[27,4,1,"","populate"]],"cassandra.policies.SimpleConvictionPolicy":[[27,4,1,"","add_failure"],[27,4,1,"","reset"]],"cassandra.policies.SpeculativeExecutionPolicy":[[27,4,1,"","new_plan"]],"cassandra.policies.TokenAwarePolicy":[[27,4,1,"","check_supported"],[27,4,1,"","distance"],[27,4,1,"","make_query_plan"],[27,4,1,"","on_add"],[27,4,1,"","on_down"],[27,4,1,"","on_remove"],[27,4,1,"","on_up"],[27,4,1,"","populate"],[27,2,1,"","shuffle_replicas"]],"cassandra.policies.WhiteListRoundRobinPolicy":[[27,4,1,"","distance"],[27,4,1,"","on_add"],[27,4,1,"","on_up"],[27,4,1,"","populate"]],"cassandra.policies.WriteType":[[27,2,1,"","BATCH"],[27,2,1,"","BATCH_LOG"],[27,2,1,"","CAS"],[27,2,1,"","CDC"],[27,2,1,"","COUNTER"],[27,2,1,"","SIMPLE"],[27,2,1,"","UNLOGGED_BATCH"],[27,2,1,"","VIEW"]],"cassandra.pool":[[28,3,1,"","Host"],[28,1,1,"","NoConnectionsAvailable"]],"cassandra.pool.Host":[[28,5,1,"","address"],[28,5,1,"","datacenter"],[28,5,1,"","rack"]],"cassandra.protocol":[[29,3,1,"","_ProtocolHandler"]],"cassandra.protocol._ProtocolHandler":[[29,4,1,"","decode_message"],[29,4,1,"","encode_message"],[29,2,1,"","message_types_by_opcode"]],"cassandra.query":[[30,3,1,"","BatchStatement"],[30,3,1,"","BatchType"],[30,3,1,"","BoundStatement"],[30,3,1,"","PreparedStatement"],[30,3,1,"","QueryTrace"],[30,3,1,"","SimpleStatement"],[30,3,1,"","Statement"],[30,3,1,"","TraceEvent"],[30,1,1,"","TraceUnavailable"],[30,6,1,"","UNSET_VALUE"],[30,3,1,"","ValueSequence"],[30,7,1,"","dict_factory"],[30,7,1,"","named_tuple_factory"],[30,7,1,"","ordered_dict_factory"],[30,7,1,"","tuple_factory"]],"cassandra.query.BatchStatement":[[30,4,1,"","add"],[30,4,1,"","add_all"],[30,4,1,"","clear"],[30,2,1,"","serial_consistency_level"]],"cassandra.query.BatchType":[[30,2,1,"","COUNTER"],[30,2,1,"","LOGGED"],[30,2,1,"","UNLOGGED"]],"cassandra.query.BoundStatement":[[30,4,1,"","bind"],[30,5,1,"","routing_key"]],"cassandra.query.PreparedStatement":[[30,4,1,"","bind"]],"cassandra.query.QueryTrace":[[30,4,1,"","populate"]],"cassandra.query.Statement":[[30,5,1,"","routing_key"],[30,5,1,"","serial_consistency_level"]],"cassandra.timestamps":[[31,3,1,"","MonotonicTimestampGenerator"]],"cassandra.timestamps.MonotonicTimestampGenerator":[[31,4,1,"","_next_timestamp"],[31,2,1,"","warn_on_drift"],[31,2,1,"","warning_interval"],[31,2,1,"","warning_threshold"]],"cassandra.util":[[32,3,1,"","Date"],[32,3,1,"","DateRange"],[32,3,1,"","DateRangeBound"],[32,3,1,"","DateRangePrecision"],[32,3,1,"","Distance"],[32,3,1,"","Duration"],[32,3,1,"","LineString"],[32,3,1,"","OrderedMap"],[32,3,1,"","OrderedMapSerializedKey"],[32,3,1,"","Point"],[32,3,1,"","Polygon"],[32,3,1,"","SortedSet"],[32,3,1,"","Time"],[32,3,1,"","Version"],[32,7,1,"","datetime_from_timestamp"],[32,7,1,"","datetime_from_uuid1"],[32,7,1,"","max_uuid_from_time"],[32,7,1,"","min_uuid_from_time"],[32,7,1,"","ms_timestamp_from_datetime"],[32,2,1,"","sortedset"],[32,7,1,"","unix_time_from_uuid1"],[32,7,1,"","utc_datetime_from_ms_timestamp"],[32,7,1,"","uuid_from_time"]],"cassandra.util.Date":[[32,4,1,"","date"],[32,5,1,"","seconds"]],"cassandra.util.DateRange":[[32,2,1,"","lower_bound"],[32,2,1,"","upper_bound"],[32,2,1,"","value"]],"cassandra.util.DateRangeBound":[[32,4,1,"","datetime"],[32,4,1,"","from_value"],[32,2,1,"","milliseconds"],[32,2,1,"","precision"]],"cassandra.util.Distance":[[32,4,1,"","from_wkt"]],"cassandra.util.LineString":[[32,4,1,"","from_wkt"]],"cassandra.util.Point":[[32,4,1,"","from_wkt"]],"cassandra.util.Polygon":[[32,4,1,"","from_wkt"]],"cassandra.util.Time":[[32,5,1,"","hour"],[32,5,1,"","minute"],[32,5,1,"","nanosecond"],[32,5,1,"","second"],[32,4,1,"","time"]],"cqlengine.queryset":[[38,3,1,"","MaxTimeUUID"],[38,3,1,"","MinTimeUUID"]],cassandra:[[1,1,1,"","AlreadyExists"],[1,1,1,"","AuthenticationFailed"],[1,1,1,"","ConfigurationException"],[1,3,1,"","ConsistencyLevel"],[1,1,1,"","CoordinationFailure"],[1,1,1,"","DriverException"],[1,1,1,"","FunctionFailure"],[1,1,1,"","InvalidRequest"],[1,1,1,"","OperationTimedOut"],[1,3,1,"","ProtocolVersion"],[1,1,1,"","ReadFailure"],[1,1,1,"","ReadTimeout"],[1,1,1,"","RequestExecutionException"],[1,1,1,"","RequestValidationException"],[1,1,1,"","Timeout"],[1,1,1,"","Unauthorized"],[1,1,1,"","Unavailable"],[1,3,1,"","UserAggregateDescriptor"],[1,3,1,"","UserFunctionDescriptor"],[1,1,1,"","WriteFailure"],[1,1,1,"","WriteTimeout"],[1,6,1,"","__version__"],[1,6,1,"","__version_info__"],[2,0,0,"-","auth"],[3,0,0,"-","cluster"],[4,0,0,"-","concurrent"],[5,0,0,"-","connection"],[16,0,0,"-","decoder"],[17,0,0,"-","encoder"],[18,0,0,"-","graph"],[25,0,0,"-","metadata"],[26,0,0,"-","metrics"],[27,0,0,"-","policies"],[28,0,0,"-","pool"],[29,0,0,"-","protocol"],[30,0,0,"-","query"],[31,0,0,"-","timestamps"],[32,0,0,"-","util"]],cqlengine:[[37,0,0,"-","models"],[38,0,0,"-","queryset"]]},objnames:{"0":["py","module","Python module"],"1":["py","exception","Python exception"],"2":["py","attribute","Python attribute"],"3":["py","class","Python class"],"4":["py","method","Python method"],"5":["py","property","Python property"],"6":["py","data","Python data"],"7":["py","function","Python function"]},objtypes:{"0":"py:module","1":"py:exception","2":"py:attribute","3":"py:class","4":"py:method","5":"py:property","6":"py:data","7":"py:function"},terms:{"0":[1,2,3,4,6,9,10,12,14,15,16,18,25,27,30,31,32,34,35,37,38,42,43,44,46,47,48,50,56],"00":43,"000":10,"000077":43,"000153":43,"000309":43,"000368":43,"000422":43,"000480":43,"000669":43,"000755":43,"031ebb0":55,"04":0,"05":38,"0l":38,"0m":0,"1":[1,2,3,4,6,10,13,15,18,19,25,27,30,31,32,34,35,36,38,42,43,44,46,47,48,52,53,54,56],"10":[1,3,10,38,44,46,50],"100":[0,4,10,42,50],"1000":[0,4],"1004":0,"1005":0,"1006":0,"1007":0,"1008":0,"1009":0,"101":0,"1012":0,"1013":0,"1015":0,"1016":0,"1017":0,"1018":0,"1019":0,"1020":0,"1021":0,"1023":0,"1024":0,"1026":0,"1027":0,"103":0,"1031":0,"1033":0,"1036":0,"1039":0,"104":0,"1042":0,"1044":0,"1045":0,"1047":0,"1048":0,"105":0,"1051":0,"1054":0,"1056":0,"1057":0,"106":0,"1060":0,"1064":0,"1065":0,"1067":0,"1068":0,"1074":0,"10786":30,"1079":0,"108":0,"1081":0,"1082":0,"1087":0,"1089":0,"109":0,"1090":0,"1091":0,"1093":0,"10l":38,"110":0,"1100":0,"1103":0,"1104":0,"1105":0,"111":[0,36],"1110":0,"111111111111":9,"1112":0,"1114":0,"1116":0,"1117":0,"1118":0,"1119":0,"112":0,"1121":0,"1122":0,"1123":0,"1124":0,"1126":0,"1127":0,"1129":0,"1130":0,"1131":0,"1140":0,"1158":0,"116":0,"1161":0,"1162":0,"1163":0,"1166":0,"1172":0,"1174":0,"1177":0,"1181":0,"1183":0,"1185":0,"1186":0,"1187":0,"1189":0,"119":[0,32],"1192":0,"11e3":44,"11l":38,"120":0,"1203":0,"1204":0,"1205":0,"1207":0,"1212":0,"122":0,"1220":0,"1228":0,"123":[0,3,36,56],"1233":0,"1234":54,"1237":0,"1238":0,"1239":0,"124":0,"1240":0,"1241":0,"1243":0,"1244":0,"1245":0,"1248":0,"125":0,"1258":0,"126":0,"1260":0,"1264":0,"1265":0,"1266":0,"1269":0,"127":[3,25,35,38,42,43,44,48,54],"1287":0,"1289":0,"1290":0,"12l":38,"1304":0,"1327":0,"1328":0,"1329":0,"135":0,"138":0,"13l":38,"14":32,"141":0,"143":0,"144":0,"145":27,"147":0,"148":0,"14l":38,"15":[27,44],"150":0,"151":0,"155":0,"157":0,"159":0,"15l":38,"16":6,"160":0,"163":0,"164":0,"165":0,"166":0,"167":0,"168":[3,44],"16l":38,"17":[38,54],"173":0,"174":0,"175":0,"178":[0,30,55],"179":0,"17l":38,"180":0,"181":0,"182":0,"184":0,"185":0,"186":0,"187":0,"189":0,"18l":38,"190":0,"191":0,"192":[0,3,44],"194":0,"195":0,"196":0,"197":0,"1970":32,"198":0,"1982":38,"19l":38,"1e6":31,"1l":38,"1s":0,"2":[1,2,3,4,6,9,10,12,13,14,15,16,18,25,27,30,32,34,35,36,38,40,42,43,44,45,46,47,50,53,54,56],"20":38,"200":0,"2008":10,"2010":[35,38],"2011":38,"2012":38,"2013":[0,45],"2014":[0,38],"2015":0,"2016":[0,45],"2017":[0,45],"2018":0,"2019":0,"202":0,"2020":0,"2021":0,"2023":0,"204":0,"2048":54,"205":0,"206":0,"207":0,"208":0,"21":38,"210":0,"211":0,"212":0,"213":0,"215":0,"218":0,"219":0,"22":46,"220":0,"222":0,"226":0,"229":0,"23":32,"230":0,"231":0,"234":0,"235":0,"238":0,"239":0,"24":3,"240":0,"241":0,"243":0,"244":0,"245":[0,40],"246":0,"249":0,"255":0,"258":0,"26":38,"260":0,"2644bada":44,"266":0,"27":0,"272":0,"273":0,"276":[0,55],"277":0,"278":0,"279":43,"28":0,"280":0,"282":0,"283":0,"284":0,"285":0,"286":0,"288":0,"289":0,"29":0,"291":0,"292":[0,55],"294":0,"295":0,"296":0,"297":0,"298":0,"299":0,"2l":38,"3":[1,2,3,4,6,9,10,15,18,19,25,27,30,31,32,34,36,37,38,45,46,48,53,56],"30":[0,3,38,42,44],"300":0,"301":0,"302":0,"303":0,"305":0,"306":0,"309":0,"31":[0,38],"310":0,"311":0,"313":0,"315":0,"317":0,"318":[0,55],"319":0,"32":6,"322":0,"323":0,"324":0,"325":0,"327":0,"329":0,"331":0,"332":0,"333":0,"334":0,"335":0,"336":0,"337":0,"338":0,"340":32,"341":0,"342":0,"343":0,"344":0,"345":0,"346":0,"347":0,"348":0,"349":0,"351":0,"352":0,"353":0,"354":0,"357":0,"358":0,"360":0,"3600":3,"361":0,"362":0,"363":0,"365":0,"368":[0,55],"370":0,"371":0,"375":0,"377":0,"378":0,"379":0,"381":0,"385":[0,55],"386":0,"392":0,"393":0,"394":0,"395":0,"396":0,"397":0,"398":0,"3l":38,"4":[1,2,3,6,9,10,19,27,29,30,32,42,48],"400":[0,55],"405":0,"407":0,"408":[0,55],"409":0,"412":0,"413":0,"415":0,"416":0,"419fcdf":55,"42":[3,30,44],"422":[0,55],"429":0,"430":0,"432":0,"433":0,"434":0,"435":0,"438":0,"439":0,"442":0,"443":0,"444":0,"445":0,"447":0,"450":0,"451":0,"452":0,"454":0,"458":0,"459":0,"46":0,"464":0,"466":0,"467":0,"468":0,"469":0,"470":0,"471":0,"473":0,"475":0,"476":0,"477":0,"478":0,"479":0,"48":32,"480":0,"481":0,"482":0,"486":0,"487":0,"489":0,"495":0,"498":0,"4bd5909":55,"4l":38,"4th":0,"5":[1,3,9,10,19,27,38,44,45,46,54],"50":4,"500":10,"5000":[3,10,50],"501":0,"502":0,"503":0,"505":0,"507":0,"508":0,"509":0,"50m":38,"510":0,"512":0,"514":0,"520":0,"521":0,"522":0,"527":0,"528":0,"530":0,"531":0,"532":0,"533":0,"535":0,"537":0,"538":0,"542":0,"547":0,"548":0,"549":0,"550":0,"551":0,"553":0,"555":0,"556":0,"557":0,"559":0,"56":0,"560":0,"561":0,"562":0,"565":0,"566":0,"568":0,"569":0,"570":0,"572":0,"5723":0,"573":0,"574":0,"574266d":55,"576":0,"577":0,"578":0,"579":0,"580":0,"583":0,"584":0,"585":0,"589":0,"59":[0,32],"591":0,"593":0,"595":0,"596":0,"598":0,"599":0,"5l":38,"6":[1,3,6,10,19,25,27,30,38,45,46],"60":0,"600":0,"606":0,"607":0,"608":0,"609":0,"613":0,"614":0,"616":0,"617":0,"618":0,"619":0,"621":0,"622":0,"623":0,"626":0,"628":0,"630":0,"631":0,"636":0,"64":[6,9,27],"640":0,"642":0,"643":0,"644":0,"645":0,"646":0,"647":0,"648":0,"649":0,"65":1,"650":0,"653":0,"655":0,"656":0,"657":0,"66":[1,3],"665":0,"668":0,"669":0,"673":0,"676":0,"678":0,"682":0,"684":0,"686":0,"688":0,"69":0,"690":0,"692":0,"694":0,"697":0,"6l":38,"7":[1,3,6,10,27,45,46],"70":0,"700":0,"705":0,"706":0,"707":0,"708":0,"709":0,"71":0,"710":0,"714":0,"717":0,"719":0,"720":0,"721":0,"723":0,"724":0,"727":0,"728":0,"729":0,"73":0,"730":0,"732":0,"733":0,"734":0,"735":0,"736":0,"737":0,"739":0,"740":0,"741":0,"742":0,"743":0,"746":0,"747":0,"749":0,"75":0,"750":0,"751":0,"752":0,"754":0,"755":0,"759":0,"75percentil":26,"75th":26,"76":0,"761":0,"762":0,"763":0,"767":0,"768":0,"769":0,"77142":43,"772":0,"773":0,"774":0,"774000":38,"775":0,"778":0,"781":0,"782":0,"785":0,"7857":0,"78723":[3,56],"788":0,"789":0,"79":0,"793":0,"794":0,"798":0,"799":0,"79efe97":55,"7l":38,"8":[1,3,6,17,31,45,46,48],"80":0,"804dea3":0,"805":0,"808":0,"81":0,"810":0,"812":0,"813":0,"814":0,"819":0,"82":0,"827":0,"829":0,"831":0,"833":0,"836":0,"837":0,"838":0,"839":0,"84":0,"840":0,"843":0,"846":0,"848":0,"852c":44,"853":0,"86":0,"860":0,"861":0,"862":0,"863":0,"86400":9,"865":0,"868":0,"872":0,"8733":40,"877":0,"88":0,"885":0,"888":0,"89":0,"891":0,"892":0,"893":0,"894":0,"895":0,"897":0,"89fb":44,"8l":38,"9":[1,9,38],"90":0,"900":0,"901":0,"903":0,"9042":[3,5],"91":0,"910":0,"915":0,"916":0,"92":0,"9223372036854775808":43,"93":0,"932":0,"934":0,"937":0,"940":0,"941":0,"944":0,"945":0,"946":0,"947":0,"95":0,"953":0,"955":0,"95percentil":26,"95th":26,"96":0,"963":0,"96489cc":55,"966":0,"968":0,"97":0,"973":0,"978":0,"98":0,"98percentil":26,"98th":26,"99":[0,26],"992":0,"993":0,"995":0,"996":0,"998":0,"99999":37,"999percentil":26,"99percentil":26,"99th":26,"9d98c8e":55,"9l":38,"9th":26,"abstract":[0,2,6,9,25,30],"boolean":[0,1,6,25,27,44,47],"break":[0,27,45,46,55],"byte":[0,6,38],"case":[0,3,4,8,9,27,32,34,35,44,49,53,54],"catch":0,"char":0,"class":[0,1,2,3,5,6,9,10,12,13,14,15,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,40,41,48,50,53,54,55],"default":[0,1,3,6,7,9,10,11,12,14,15,17,18,26,27,29,30,31,34,43,44,46,48,49,50,54],"do":[0,3,4,6,9,17,27,30,37,38,41,44,46,54,55,56],"enum":[10,13,27,32,33],"export":[0,25],"final":[3,44,54],"float":[0,3,6,10,15,18,26,27,37,38,44,55],"function":[0,1,3,8,10,12,17,25,27,29,32,41,44,53,54,55],"import":[0,2,3,4,6,10,11,12,29,30,34,35,37,38,39,41,42,43,44,46,48,50,52,53,54],"int":[0,3,6,7,8,15,18,25,31,32,38,44,47,55,56],"long":[0,32,44,46,56],"new":[0,1,2,3,4,6,7,10,21,25,27,30,31,32,34,36,38,39,40,42,44,48,50,54,55,56],"null":[0,10,17,36,38,44],"public":27,"return":[0,1,2,3,4,9,10,12,14,15,18,25,26,27,29,30,31,32,33,37,38,39,41,43,44,47,48,50,52,54,55,56],"short":[0,30,37,52],"static":[0,3,6,10,12,13,32],"super":37,"switch":[0,10,46],"throw":[0,3,30],"transient":0,"true":[0,3,4,6,7,8,9,10,15,18,25,27,30,31,34,35,36,37,38,40,43,44,47,48,53,54],"try":[0,1,3,8,9,27,37,39,41,44],"while":[0,3,27,30,37,40,50,55],A:[0,1,2,3,4,7,8,10,12,13,14,17,18,25,26,27,30,32,35,37,38,44,45,46],AND:[47,53],And:[9,54,55],As:[9,32,40,44,53,56],BY:37,Be:49,But:30,By:[1,3,9,10,27,29,34,38,43,44,46,50,52,54,55],For:[0,1,3,6,7,9,10,25,27,30,32,36,37,38,40,41,42,44,46,47,48,49,50,51,53,54,55],IF:[0,10,27,30,47,53,55],IN:[17,25,30],INTO:[3,4,30,44,47,56],IS:[0,38,40],If:[0,2,3,4,7,8,9,10,11,14,25,27,30,31,32,34,35,36,37,41,42,44,46,47,50,54,55],In:[0,3,27,29,34,38,40,44,46,53,54,55],It:[0,3,9,21,22,27,32,35,37,38,43,44,46,47,54],NOT:[0,38,47,53],No:45,Not:[0,32],ONE:[1,3,10,40,55],Of:3,On:[0,27,46],One:[10,41],Or:3,Such:27,THERE:40,That:38,The:[0,1,2,3,4,5,6,7,9,10,12,13,14,15,17,18,25,26,27,28,29,30,32,34,36,37,38,40,41,42,44,45,46,47,49,52,54,55,56],Then:54,There:[1,3,6,8,30,38,44,46,55],These:[0,3,6,9,27,29,30,32,40,41,49,54,55],To:[3,9,11,27,34,35,37,38,40,41,42,43,44,46,51,54,55],WITH:[37,53],Will:9,With:[0,35,43,52,54,55],_1:54,_2:54,_3:54,_4:54,_:42,__:[10,38,55],__abstract__:9,__compute_routing_key__:9,__connection__:[8,9,35],__contain:38,__default_ttl__:9,__del__:0,__discrimin:55,__discriminator_value__:[6,9,37,40],__ge__:0,__gt:38,__gte:38,__in:[0,38],__init__:[0,3,27,31,50,55,56],__keyspace__:[8,9,35,37],__le__:0,__len__:0,__like:38,__lt:38,__lte:38,__name__:43,__ne__:0,__options__:[9,38],__polymorphic_:55,__polymorphic_key__:40,__repr__:0,__table_name__:[9,37,40],__table_name_case_sensitive__:9,__type_name__:11,__version__:[1,46],__version_info__:1,_connect:0,_dsegraphson2rowfactori:12,_gremlingraphson2rowfactori:12,_messagetyp:29,_metadata:55,_new_tim:21,_next_timestamp:31,_not_set:3,_protocolhand:29,_protocolhandl:29,_replicationstrategi:25,_set_final_except:0,_set_result:0,_timeout_watch:21,a2:10,a2d3a98:55,abil:[0,27,42,55],abl:46,about:[0,3,25,30,37,41,44,46,52,54,55],abov:[3,29,34,35,41,44,49],absolut:[32,40],accept:[0,3,27,32,40,41],access:[0,3,9,26,30,37,44,55],accommod:[0,41],accomplish:[38,46],accord:[0,3],accordingli:0,account:[0,37],accumul:10,accur:25,acheiv:27,achiev:[27,34,54],acknowledg:27,across:[0,19,20,21,22,27,42,43,49],act:54,activ:[0,3,21,22],actual:[0,1,27,30,38,44,47],ad:[0,1,3,10,21,25,27,30,34,37,38,46,55],add:[0,3,7,8,10,14,27,30,34,55,56],add_al:[14,30],add_callback:[3,10,34,44,49,50],add_collback:0,add_errback:[3,44],add_execution_profil:[3,12,42],add_failur:27,add_or_return_host:25,add_queri:10,add_request_init_listen:3,add_tim:0,addit:[0,3,10,12,29,34,37,38,44,47,48,54,55],addition:[30,37,40,54],additional_write_polici:0,addr:[27,37],address:[0,1,3,5,11,25,28,30,33,37,43,44,52,54,55,56],address_is_ignor:27,address_transl:3,addresstransl:[0,27],adher:41,adjust:[0,40],advanc:54,advic:3,affect:[3,30,34],after:[0,3,4,10,20,27,30,34,37,38,40,43,44,46,49],afterward:55,ag:[3,30,38,44],against:[0,1,3,9,27,30,37,44,48,54],aggreg:[0,1,3,25],agnost:32,agre:0,agreement:[0,3],ahead:[3,44],aim:[35,42],algorithm:[36,46],alia:[6,12,25,32,40],alias:0,alic:30,align:0,aliv:[1,26,27],alive_replica:[1,27],all:[0,1,3,4,6,8,9,10,17,21,22,25,26,27,28,29,30,35,41,44,46,47,49,53,54,55],all_host:[25,42,52],all_object:38,all_replica:25,allow:[0,3,6,9,10,12,13,27,29,30,31,32,34,36,37,46,52,53,54,55,56],allow_beta_protocol_vers:29,allow_filt:[10,38],almost:44,along:[3,25,50],alpha:0,alphanumer:0,alreadi:[0,1,3,5,8,35,46],alreadyexist:1,also:[0,3,4,9,10,13,27,30,32,35,37,38,42,43,44,46,54,55],alter:[9,27,37],altern:[3,29,37,40,44,46,49,54],although:[44,55,56],althought:44,alwai:[0,3,15,18,27,41,44,46,47],ambigu:0,among:[1,27],amount:[0,4,27],an:[0,1,2,3,4,5,6,8,9,10,12,13,15,17,18,19,20,21,22,23,24,25,26,27,29,30,31,32,34,35,36,37,38,40,41,42,44,45,46,48,49,50,53,54,55,56],analysi:29,analyt:[0,3,15,18],analyticskeyspac:3,analyticskeyspace_prepar:3,andrew:[46,54],ani:[0,1,3,8,9,10,13,14,17,19,20,21,22,26,27,30,34,37,38,41,43,44,45,46,47,49,54,56],annot:0,anomali:0,anoth:[27,34,35,38,44,54,55],anymor:[38,55],anyth:[34,41],anywai:46,apach:[38,46,55],api:[0,32,37,41,42,45,46,48,49,54],app:[39,43],appear:[0,47],append:[4,10,25,38,44],appli:[0,3,9,10,14,30,36,41,42,44,46,47,48,56],applic:[0,3,6,27,39,40,41,44,46,49,50,52,55],approach:[41,45],appropri:[3,37,46,54],april:0,apt:46,ar:[0,1,3,4,6,7,8,9,10,15,18,21,25,26,27,28,29,30,32,34,36,37,40,41,42,43,44,45,46,47,48,50,54],arbitrari:[6,32],archflag:46,architectur:46,arg:[3,4,6,9,10,19,20,21,22,23,27,32,34],arg_typ:1,argument:[0,1,3,4,7,9,10,15,18,27,30,31,32,34,35,44,46,54,55],argument_typ:1,arm:0,around:[0,9,32,40,41,55],arrai:[29,38],arriv:3,as_cql_queri:[0,25],as_edg:[15,18],as_graph_stat:14,as_path:[15,18],as_vertex:[15,18],ascend:[10,38],ascii:[0,6,44],ask:[45,48],assert:[6,36,53],assertionerror:38,assign:[0,6,11,37],associ:[0,3,55],assum:[3,21,22,38,41,54,55],assumpt:41,astimezon:41,astra:0,async:3,asynchron:[0,3,30,43,49],asyncio:[0,33],asyncioconnect:19,asyncioreactor:[0,33],asyncor:[0,33,46],asyncoreconnect:[0,20],asyncorereactor:[0,33],atexit:0,atlassian:27,atom:[27,30],attach:[0,3,15,18,34,44,49,50,55],attempt:[0,1,3,4,5,27,34,41,43,44,55],attr_kwarg:3,attribut:[0,3,6,8,9,10,11,15,18,25,27,29,30,31,37,38,40,42,44,47,55,56],attributeerror:0,aug:0,august:0,auth:[0,33,54,55],auth_provid:[2,3,54],authent:[0,1,3,33],authenticationfail:[1,2],author:[1,54],authorization_id:54,authprovid:[0,2,3,54],auto:35,automat:[0,1,3,35,37,38,44,46,50],automobil:[10,35,38],automobile2:10,avail:[0,3,10,30,38,45,46,53,55],avoid:[0,3,27,40,43,46],aw:27,awai:[3,30],awar:[0,3,26,27,41,46,54,55],ayncoreconnect:0,b:[3,4,12,14,15,18,34,35,36,38],back:[0,6,9,32,38],backoff:0,backpressur:0,backup:38,backward:[3,18,25,55],bad:0,badli:0,balanc:[0,3,33,42,55],bar:44,bark_all_night:37,base:[0,1,3,9,12,26,27,29,30,32,37,40,43,44,47,52,53,54],base_delai:27,basegraphrowfactori:12,basi:[0,55],basic:[0,3,12,37],batch:[0,1,3,9,10,12,14,25,27,33,35,38,48],batch_log:27,batch_obj:10,batch_object:9,batch_r:10,batch_typ:[10,30,34],batchqueri:[0,10,34,36,38],batchstat:[0,1,3,30,55],batchtyp:[0,10,30,34],bb984ee:55,beat_init:39,becam:[0,40],becaus:[0,3,4,15,18,27,30,32,40,41,44,46,53,55],becom:[0,3,8,49,55],been:[0,3,5,9,26,27,30,34,35,40,55],befor:[0,1,3,9,10,27,29,30,40,43,44,49,50,55],begin:[0,10,13,44],behav:32,behavior:[0,3,6,27,44,55],behind:[27,41],being:[0,3,6,26,30,36,42,44,46,47],below:[3,4,10,27,29,36,37,38,40,46,47,49,55],benchmark:[0,49],best:[27,44,51,54],beta5:1,beta:[1,46],beta_vers:1,better:[0,27,46,49],between:[0,2,6,29,30,46,53],bewar:27,beyond:37,big:[0,53],bigint:[6,15,18,44],binari:[0,6,30],binary_typ:29,bind:[0,3,12,30,43,44,55],bit:[6,32,46],bitmap:29,blacklist:27,blacklist_filter_polici:27,blah:44,blake:[9,38],blank:9,blind:[9,10],blindli:10,blist:0,blob:[0,6,17,44,53],block:[0,3,4,34,44,49],blog:49,bob:[3,30,44],bodi:[0,29],bool:[6,7,8,10,25,44,53],bootstrap:[0,26],bop:0,borrow_connect:0,both:[0,3,38,39,44,46,54],bound:[3,14,30,32,43,49],bound_stmt:3,boundstat:[0,30,44,55],bracket:47,brew:46,broadcast_address:27,broadcast_rpc_address:25,broadcast_rpc_port:25,broken:0,brought:55,brows:27,brute:27,bu:0,bucket_high:9,bucket_low:9,buffer:[0,17,44],bug:[40,45],build:[0,25,40,44,46,49],built:[0,32,42,46,49,55],bulk:12,bulkset:0,bump:0,bundl:52,busi:[3,28],bypass:[0,3,8,30],bytearrai:[0,17,44],bytebuff:0,bytecod:12,byteorderedpartition:[0,25],bytesio:0,bytestoken:25,c0:53,c:[0,6,12,25,27,38,54],ca:[0,27,54],ca_cert:54,cach:0,cacreateseri:54,cakei:54,calcul:0,call:[0,2,3,5,9,10,17,19,20,21,22,27,31,34,37,38,41,44,48,50,54],callabl:[6,10,12],callback:[0,3,10,44,49,54],callback_arg:3,callback_kwarg:3,camera:38,can:[0,1,3,4,6,8,9,10,13,14,15,17,18,21,25,27,29,30,31,32,34,35,37,38,39,41,42,43,44,45,46,48,49,50,52,53,54,55,56],cancel:0,cannon:40,cannot:[0,27,30,32,38,42],capabl:50,captur:[0,46],car:38,cardin:[15,18],care:[3,8],carri:34,cass_driver_build_concurr:46,cass_driver_no_cython:46,cass_driver_no_extens:46,cass_server_vers:0,cass_typ:32,cassandra:[0,33,34,35,36,37,38,39,40,42,43,46,48,49,50,52,53,54,56],cassandra_init:39,cassandra_vers:0,cast:44,cat:[37,40,54],caus:[0,3,10,26,37,47],caution:[8,37],caveat:27,cc94073:55,cdc:[0,27],cdef:0,ceas:27,ceil:1,celeri:48,cell:43,center:30,cento:[0,46],central:41,cert:54,cert_countri:54,cert_org_nam:54,cert_ou:54,cert_req:54,cert_requir:54,cert_valid:54,certain:[13,27,40,46],certfil:54,certif:[0,54],chain:34,challeng:[2,46],chanc:27,chang:[0,3,6,9,10,25,27,30,31,36,37,38,43,44,45],changelog:45,charact:[0,6,44],charl:30,check:[0,3,9,10,27,37,46,53,55],check_hostnam:[0,54],check_support:27,checkout:46,checksum:0,child:[0,27,43],child_polici:27,choic:[46,49],choos:[15,18,27,55],chosen:3,chunk:0,circuit:0,circumst:0,citi:55,civic:[10,35,38],cl:[0,10,21],clang:46,classic:0,classmethod:[1,9,15,18,19,20,21,22,25,29,32],claus:[0,10,25,37,47,55],clean:[0,39,46,55],cleanup:[0,20],clear:[0,14,27,30],clearer:41,client:[0,1,2,3,8,27,29,41,42,45,53],client_encryption_opt:54,client_protocol_handl:[3,29],clock:32,clock_seq:32,clone:[3,42],close:[0,3,5],closur:0,cloud:[0,3,27,45],cluster1:35,cluster2:[10,35],cluster3:35,cluster:[0,2,4,5,6,7,9,10,12,15,18,19,20,21,22,25,26,27,29,30,33,35,37,38,39,43,46,48,49,51,52,54,56],cluster_nam:52,cluster_opt:7,clustering_kei:38,clustering_ord:[6,37],clustertest:0,cn:54,code:[0,1,34,39,45,54,55,56],codebas:0,coerc:6,coincid:0,col:[0,47],col_nam:9,collect:[0,3,8,10,15,25,26,30,32,38,45,55],collis:0,colnam:[3,10,30],column:[0,8,9,10,11,13,17,25,30,33,35,36,37,38,44,47,48,55,56],column_family_nam:9,column_nam:[10,15,18,38],columnmetadata:[25,55],com:[6,10,53,54],combin:[0,3],come:0,comma:44,command:[0,35,46],comment:[9,10,37],comment_id:[10,37],common:[0,40,46,54,55],commun:[0,5,46],compact:[0,9,53],compar:[0,30,32,45],comparison:[0,6],compat:[0,3,18,25,33,55],compil:[0,29,46,49],complain:37,complet:[0,1,2,3,4,11,27,30,34,37,40,43,44,49,54],complex:[0,42,46],compliant:0,compon:[0,10,25,30,32,54],compos:29,composit:[0,30,38],compositetyp:0,compound:6,compress:[0,3,29],compressor:29,compris:[1,29],comput:[0,3,9,43],concern:41,concis:15,concurr:[0,3,8,30,33,43,44,49],condit:[0,1,3,8,10,30,45],conf:54,config:[0,54],configur:[0,1,2,3,5,7,9,15,18,27,31,42,44,45,53],configurationexcept:1,confirm:0,conflict:36,confus:[40,55],conn:35,connect:[0,1,2,3,4,8,9,10,11,12,19,20,22,23,24,26,27,30,33,37,38,39,40,42,45,46,48,51,52,53,54,55,56],connect_timeout:[0,3],connect_to_remote_host:3,connected_to:26,connection_class:[3,46,54],connection_error:26,connection_exc:27,connectionbusi:5,connectionexcept:[0,5],connectionshutdown:5,consensu:1,consid:[0,1,3,18,27,44,47,49,54,55],consider:[37,49],consist:[0,1,3,7,10,27,30,32],consistency_level:[3,15,18,30,42,44],consistencylevel:[0,1,3,7,10,15,18,26,27,30,40,44],consit:0,constant:[0,54],constantreconnectionpolici:[0,27],constantspeculativeexecutionpolici:[0,27,44],constrain:[4,10],constraint:[9,37],construct:[0,9,12,32,41,42,44],constructor:[0,3,6,38,52],consult:37,consum:[0,4,55],consumpt:[0,49],contact:[0,3,27,44],contact_point:[0,3,7,27,54],contain:[0,3,6,9,10,13,17,27,32,37,38,41,47,50,53],contains_kei:13,contains_valu:13,contend:0,content:[0,10,29],context:[0,3,8,9,10,12,15,18,34,39,46,49,54],contextqueri:[0,10,35],contin:0,continu:[0,2,27,50],continuous_paging_opt:3,contract:[0,29],control:[0,3,4,27,30,40,49,54],control_connection_timeout:3,conveni:[3,15,18,30,38],convent:37,convers:[15,18,40,41,55],convert:[0,13,15,17,18,32,40,41,55],convict:27,conviction_policy_factori:3,convictionpolici:27,coord:32,coordin:[1,3,4,27,32,43],coordinationfailur:1,copi:42,copyright:0,core:[0,3,4,38,40,46,49],core_connect:3,coroutin:0,correct:[0,9,41],correctli:[0,3],correspond:[2,4,6,8,37],cost:[0,9,10,38],costli:46,could:[0,10,55],count:[0,9,10,26,27,36,38,48],counter:[0,6,26,27,30,37,44],countri:45,cours:3,cover:[37,43],coverag:0,cpu:[0,4,44,49],cpython:[0,3,46],cql3:[36,38,45],cql:[0,1,6,9,10,11,13,15,17,18,25,30,32,36,37,38,40,41,47,48,53,55,56],cql_cluster:39,cql_encode_all_typ:17,cql_encode_byt:17,cql_encode_d:17,cql_encode_datetim:17,cql_encode_list_collect:17,cql_encode_map_collect:17,cql_encode_non:17,cql_encode_object:17,cql_encode_sequ:17,cql_encode_set_collect:17,cql_encode_str:17,cql_encode_tupl:[17,55],cql_encode_unicod:17,cql_keyword:25,cql_keywords_reserv:25,cql_keywords_unreserv:25,cql_refer:10,cql_session:39,cql_use:6,cql_version:[0,3],cqlcollect:13,cqle:0,cqlengin:[0,33,34,35,36,37,38,39,43,45,48,55],cqlengine_batch:34,cqlengine_test:38,cqlengineexcept:[0,40],cqltype:55,cqluseudt:6,crash:0,creat:[0,1,2,3,5,6,7,8,9,10,12,25,27,30,32,34,35,36,37,38,41,43,44,47,48,49,53,54,55,56],create_default_context:54,create_execution_profil:12,create_keyspac:40,create_keyspace_network_topolog:[8,40],create_keyspace_simpl:[8,40],create_simple_keyspac:35,created_at:[34,48],creation:[0,3,4,25,38],credenti:[0,3,52,54],credit:44,crt:54,crt_sign:54,crypto:54,csr:54,cstringio:0,cumbersom:41,current:[0,1,3,10,12,26,27,30,31,38,42,43,46,50,55],current_pag:3,current_row:3,custom:[0,1,3,6,10,17,27,30,33,41,42,44,46],custom_index:6,custom_payload:[3,15,18,29,30],cut:0,cute:37,cycl:3,cython:[0,29],cython_protocol_handl:3,cythonprotocolhandl:3,d:[3,6,10,30,41,44],daemon:0,dai:[6,27,32,54],dash:0,data:[0,1,3,9,10,27,30,33,37,38,41,43,44,53,55,56],data_retriev:[1,27],databas:[6,8,9,34,37,38,41,42,52],datacent:[0,1,27,28,52],dataset:[0,10,38],datastax:[0,6,10,18,27,44,45,46,48,54,55],datastream:38,datatyp:0,date:[0,6,17,32,44,45,55],daterang:[0,32],daterangebound:32,daterangeprecis:32,datetim:[0,6,10,17,32,34,36,38,40,41,44,48],datetime_from_timestamp:32,datetime_from_uuid1:32,datetyp:0,david:13,daylight:41,days_from_epoch:32,db:0,db_field:[0,6],dc:[0,3,27,55],dc_name:8,dc_replication_factor:25,dc_replication_map:8,dcawar:0,dcawareloadbalancingpolici:0,dcawareroundrobinpolici:[0,3,27,42,52],dclocal_read_repair_ch:0,dct:0,dd:[17,32],ddl:0,dead:33,deadlock:[0,4],deal:[0,41,42,49,55],debian:[0,46],debug:[0,3],decemb:0,decid:27,decim:[0,6,10,38,44],decimaltyp:0,decis:[0,26,41],declar:[11,37],decod:[0,3,29,30,33,55],decode_messag:29,decomiss:0,decommiss:[0,27],decompress:29,decompressor:29,decor:0,decrement:6,deem:41,def:[3,27,34,37,39,43,44,50,52,54,55,56],defacto:41,default_bit:54,default_consistency_level:[0,3,7,42],default_fetch_s:[3,50],default_keyspac:[0,7],default_retry_polici:[3,27,42,43],default_serial_consistency_level:[0,3,42],default_time_to_l:[0,38],default_timeout:[3,42],defaultloadbalancingpolici:[0,27,55],defer:[0,10,27],defici:41,defin:[0,1,2,3,6,8,9,10,15,18,25,27,30,33,35,38,40,42,44,45,48],definit:[0,3,6,15,29,38,40],defunct:[0,3,5],degre:13,delai:[0,27,44],deldyck:37,delet:[0,8,9,10,27,30,34,38],delete_keyspac:40,deliv:3,deliveri:3,demand:0,demonstr:54,dep:0,depend:[0,2,41,43,47,49],deploi:52,deploy:54,deprec:[3,9,16,27,54],deprecationwarn:[0,55],depth:0,dequ:0,deriv:[32,37,40,42,46,55],derivi:9,desc:37,descend:[10,37,38],describ:[1,27,29,32,38,40,41,54],descript:[0,3,15,18,27,30,34,43,48,54],descriptor:0,deseri:[0,15,18,33,41],deserialize_bigint:[15,18],deserialize_blob:[15,18],deserialize_d:[15,18],deserialize_decim:[15,18],deserialize_doubl:[15,18],deserialize_dur:[15,18],deserialize_float:[15,18],deserialize_int:[15,18],deserialize_linestr:[15,18],deserialize_point:[15,18],deserialize_polygon:[15,18],deserialize_tim:[15,18],deserialize_timestamp:[15,18],deserialize_uuid:[15,18],design:[44,49],desir:[3,10,27,34],despit:10,destroi:0,detail:[0,1,3,9,10,30,37,41,42,43,44,49,53,54,55],detect:[0,40],determin:[6,9,27,30,44],determinist:0,dev:[46,53],devel:46,deviat:26,devic:0,dict:[0,1,3,6,7,8,9,12,15,17,18,25,26,29,30,37,44,47,53,54],dict_factori:[0,3,7,16,30,55],dictionari:[0,6],dictlik:32,did:[5,10,27],didn:10,differ:[0,3,10,29,30,32,36,37,38,42,44,54,55],digest:27,dir:0,directli:[3,4,17,29,30,44,46,54],disabl:[0,3,9,10,46,53],disable_shardaware_port:53,discontinu:0,discourag:3,discov:[0,3,27,44],discoveri:0,discrimin:[6,9,37],discriminator_column:[6,37,40],discuss:[3,6,11,30,37,45,47,49],disentangl:0,disk:6,dispos:3,disproportion:27,distanc:[13,27,32],distant:27,distinct:[0,10,15,18],distinct_field:10,distinguish:0,distinguished_nam:54,distribut:[0,27,38,46],distrimin:37,distriminator_column:37,dll:0,dn:27,doc:[0,1,6,10,37,38,41,53,54],document:[0,6,27,32,41,42,45,46,48,54,55],doe:[0,3,10,17,32,34,38,40,44,46,47,56],doesn:[0,31,55],doesnotexist:[0,10],dog:[37,40],dollar:0,don:[0,10,38,44,49,56],done:[0,3,37,41,43,54,55],dont:0,dontprepareonignoredhoststest:0,doubl:[0,6,15,18,32,44,49,55],double_precis:[40,55],down:[0,3,33,46],downgrad:[0,27],downgradingconsistencyretrypolici:[0,27,44],download:52,drain:0,drift:31,driven:8,driver:[0,1,3,5,7,10,18,26,27,28,29,30,37,38,40,41,44,46,47,48,49,50,51,52,53,54,55,56],driverexcept:1,drop:[0,6,8,29],drop_keyspac:[8,40],drop_tabl:8,drope:0,dsa:0,dse:[0,1,3,6,12,14,15,18,32],dse_graph:55,dse_graph_query_languag:12,dse_graph_query_protocol:12,dse_v1:[0,1],dse_v2:1,dsegraph:12,dsegssapiauthprovid:[0,54],dseloadbalancingpolici:[0,27,55],dseplaintextauthprovid:54,dsesessionremotegraphconnect:12,dsl:12,dt:32,due:[0,1,10,26,34,49],duplic:0,durabl:3,durable_writ:8,durat:[0,30,32],durationtyp:0,dure:[0,1,2,3,5,9,40,46],dynam:[0,3],dynamiccompositetyp:0,e0b9a54a6d93:44,e16a073:55,e:[3,8,9,10,12,15,18,27,30,43,46],each:[1,2,3,4,6,9,27,30,36,37,38,41,44,50,55,56],each_quorum:1,eagain:0,eai:0,earlier:[0,21,37],eas:35,easi:[0,37,38],easier:[38,42,46],easiest:[41,46],easili:[0,10,41],east:52,eat:37,ec2:0,ec2multiregiontransl:27,ed:0,edg:[0,15,18,25],edgemetadata:25,effect:[0,3,8,34,54],effici:[0,29],effort:[0,40,54],eggleston:9,either:[2,3,15,18,32,37,38,41,45,46],element:[0,3,10,15,18,25,32,38,44],elementmap:0,els:[4,39,50],em1:[34,48],em2:[34,48],em3:[34,48],em4:48,em5:48,em6:48,em7:48,em8:48,email:44,emit:[3,40,46],empti:[0,2,3,25,47],en:[6,10],enabl:[0,3,10,44,53,54,55],enable_shard_aware_driv:53,encod:[0,3,6,15,18,29,33,41],encode_messag:29,encount:[0,3,10],encrypt:[0,54],end:[0,10,34],endian:0,endless:0,endors:45,endpoint:[5,25,27,28,52,54],endpoint_factori:3,endpoint_or_address:25,endpointfactori:[5,54],enforc:[0,37],engag:46,engin:[0,3],enough:[1,30],ensur:[0,3,4,9,27,39,46,54],enterpris:53,entir:[0,3,4,10,14,25],entiti:0,entri:[10,13,17,55],entry_eq:13,environ:[8,27,46],eof:54,ep:[3,44],epoch:[0,31,32,41],eq:0,equal:[0,3,6,30,38],equival:[9,36,41,44],errback:[0,3,44,50],errback_arg:3,errno:0,error:[0,1,3,4,5,6,10,27,44,50],error_code_map:1,errro:1,escap:[0,17],especi:[0,8,42,46],essenti:38,establish:[3,44],etc:[3,10,26,27,38],evaluate_challeng:2,even:[0,3,7,27,30,41,42,44],evenli:27,event:[0,3,4,21,27,30,33,39,43,44,46,50,54],eventlet:[0,33],eventletconnect:[21,54],eventletreactor:33,everi:[0,27,31,38,39,44],everyon:46,evict:0,evolv:42,ewouldblock:0,exact:2,exactli:[0,27,40],examin:32,exampl:[0,2,3,4,6,9,10,11,25,30,32,35,36,38,40,42,43,44,46,47,48,49,50,51,53,55,56],example1:48,example2:48,example3:48,example4:48,example5:48,example6:48,example7:48,example8:48,example_id:48,example_mapp:0,example_typ:[34,48],examplemodel:[34,48],exc:[3,50],exce:[0,50],exceed:[3,4],except:[0,3,4,5,6,7,9,10,15,18,27,28,29,30,32,33,34,37,38,39,44,50,54],excess:0,exclud:38,exclus:[7,32,45],exec_profile_default:[3,42,44,52],exec_profile_graph_analytics_default:3,exec_profile_graph_default:[3,12,55],exec_profile_graph_system_default:3,exect:0,execut:[0,1,3,8,9,10,12,14,15,18,25,27,29,30,33,35,37,38,43,45,47,49,50,53,56],execute_a:[3,54,55],execute_async:[0,3,4,29,43,44,49,50],execute_concurr:[0,4,49],execute_concurrent_with_arg:[4,49],execute_graph:[3,15,18],execute_graph_async:3,execute_on_except:[10,34],execution_profil:[3,4,12,14,42,44,52],execution_profile_clone_upd:[3,42],executionprofil:[0,3,12,42,44,52],executionresult:4,executor:0,executor_thread:3,exhaust:[0,27],exist:[0,1,3,8,9,10,27,28,42,47,48,53,55],exit:0,expand:0,expect:[0,5,9,43,47,54,55,56],expens:3,experi:4,experiment:[0,19],expir:3,explain:[0,42],explicit:[0,40,41],explicitli:[0,1,3,10,15,18,34,37,55],explod:42,explor:38,exponenti:[0,27],exponentialreconnectionpolici:[0,3,27],export_as_str:[0,25],export_for_schema:[0,25],export_schema_as_str:25,expos:[0,31,55],express:[4,13,32],extablish:3,extend:30,extens:[0,3,27,41,53],exterior:32,extern:41,extra:[0,25,30,46,55],extra_deserializer_map:[15,18],extract:[15,18],ey:45,f:3,facilit:29,factor:[0,8,25],factori:[3,12,33,47],fail:[0,1,3,4,7,14,15,18,26,33,34,37,44,47],failur:[0,1,7,9,26,33,34],fairli:37,fall:[0,32],fallback:[10,27,55],fallthroughretrypolici:27,fals:[3,4,6,7,8,9,10,15,18,25,27,30,47,48,53,54,55],falsei:27,falsi:27,famili:[0,5,9],faq:[43,45],fashion:3,faster:[0,33,46],favor:[27,40,53,55],feather:45,featur:[12,19,33,38,40,45,46,54],feb:0,februari:0,fedora:46,feedback:0,felcei:13,fetch:[0,3,10,30,38,44,50,55],fetch_next_pag:3,fetch_siz:[0,3,10,15,18,30,50,55],few:[3,44,46],field:[0,3,6,8,9,10,11,30,32,37,38,44,56],fieldnam:6,fierc:37,file:[0,40,49,52,54],fill:[15,18,30],filter:[0,6,9,27,33,35,48],finalis:1,find:[13,25,41,46],fine:56,finished_ev:50,finit:27,first:[0,3,4,6,7,9,27,36,37,38,40,44,45,46,48,50,54,55],first_nam:[9,37],first_pag:38,first_result:55,first_row:56,five:3,fix:[27,46,54,55],flag:[0,3,6,9,29,37,46,53],flake:0,flask:43,flat:38,flexibl:[0,45],flight:[0,5],flow:0,fluent:[0,33,46,55],fly:[0,4,9,10,35],fn:[3,10],focu:27,follow:[0,3,26,27,29,34,35,37,40,41,42,44,46,47,54,55],foo:[44,56],food:37,footprint:[4,38],forc:[0,27,54],force_token_rebuild:3,forev:[21,27,30],fork:[0,20,43,45,49],form:[1,17,32,44],format:[0,1,3,17,25,29,30,33,41,44,52,54,56],formerli:0,forward:[1,27,40],found:[0,10,25,30,45,49,54,55],foundat:45,four:32,fqdn:[0,54],fraction:32,frame:29,fraudul:0,free:44,frequent:[27,44,45,48],from:[1,2,3,4,5,6,8,9,10,11,12,15,18,20,25,27,29,30,32,34,35,37,38,39,40,42,43,44,45,46,47,48,50,52,53,54,56],from_datetim:55,from_kei:0,from_str:25,from_valu:32,from_wkt:32,frozen:[0,32,56],frozenset:44,full:[0,30,55],full_replica:25,functionfailur:1,functon:38,further:[3,4,27,38,43,49,54],furthermor:27,fuse:46,futur:[0,3,6,7,30,31,40,43,44,46,49,50,55],fuzzi:13,g:[0,3,12,15,18,27,30],garbag:[0,55],gc:0,gc_grace_second:9,gcc:46,gen_client_cert:54,gener:[0,1,2,4,27,29,32,33,41,44,53,54,55],geo:[0,13],geom:0,geomet:0,geometri:[13,32],geospati:0,geounit:13,get:[0,3,8,9,10,25,27,38,46,52],get_all_query_trac:[3,55],get_clust:52,get_control_connection_host:3,get_core_connections_per_host:3,get_credenti:54,get_execution_profil:[0,3],get_host:[0,25],get_host_by_host_id:25,get_lower_support:1,get_max_connections_per_host:3,get_max_requests_per_connect:3,get_min_requests_per_connect:3,get_query_trac:[0,3,43,55],get_replica:[0,25,43],get_stat:26,getstat:26,getter:[15,18],gevent:[0,33],geventconnect:[0,22],geventreactor:[0,33],gil:[0,49],github:[0,45,48,53],give:[3,27,54,56],given:[0,3,10,25,27,28,32,34,38,49],global:[0,7,43],go:[0,40,51],goal:[49,54],goe:0,good:[40,45],got:55,govern:[3,27],gracefulli:0,grant:54,graph:[0,3],graph_graphson2_row_factori:[15,18],graph_graphson3_row_factori:[3,15,18],graph_languag:[15,18],graph_nam:[12,15,18],graph_object_row_factori:[3,15,18],graph_opt:[0,3],graph_protocol:[3,12,14],graph_read_consistency_level:[15,18],graph_result_row_factori:[15,18],graph_sourc:[0,3,15,18],graph_traversal_dse_object_row_factori:12,graph_traversal_row_factori:12,graph_write_consistency_level:[15,18],graphanalyticsexecutionprofil:3,graphexecutionpolici:3,graphexecutionprofil:3,graphopt:[0,15,18],graphprotocol:[3,14,15,18],graphson1:[15,18],graphson1deseri:[15,18],graphson1seri:[15,18],graphson2:[0,15,18],graphson2read:[15,18],graphson3:[0,12,15,18],graphson3read:18,graphson:[0,12,14,15,18],graphson_1_0:[3,15,18],graphson_2_0:[14,15,18],graphson_3_0:[3,15,18],graphsonwrit:14,graphstat:[0,3,14],graphtravers:[12,14],graphtraversalsourc:12,greater:[27,50],greatli:0,greenlet:0,gremlin:[0,3,12,14,15,18,46],gremlinpython:[0,46],greplin:[0,26],groovi:[15,18],group:25,group_keys_by_replica:25,grow:0,gssapi:2,guarante:[0,27,30,55],guard:8,guid:[0,44,45,46,48,54],gx:0,h:[0,43],ha:[0,3,5,10,26,27,30,38,40,41,44,46,47,54,55,56],had:[0,40,55],handl:[0,2,3,9,10,12,29,33,38,39,41,43,44,46],handle_err:50,handle_error:[4,44,50],handle_fork:20,handle_pag:50,handle_result:3,handle_success:44,handle_writ:0,handler:[0,2,10,15,18,27,29,50],handshak:2,hang:[0,46],happen:[0,3,27],hard:46,has_more_pag:[0,3,50],hash:[0,38,46],hashabl:[0,32],hasn:0,have:[0,2,3,4,6,9,10,15,17,18,26,27,34,35,36,37,38,40,42,44,46,47,54,55,56],header:[0,29,46],healthmonitor:0,heap:0,heartbeat:0,help:[0,38,55],here:[3,9,10,34,35,37,38,39,40,41,46,48,52,54],hex:0,hh:32,high:[0,48,49],higher:[1,3,4,30,54,55],highli:44,highlight:55,hint:1,hit:[3,5],hold:[0,25,29],holder:44,homebrew:[0,46],honda2012:38,honda:[10,35,38],honor:[0,44],hook:[39,43],host1:27,host2:27,host3:27,host:[0,1,2,3,4,7,25,33,35,43,48,52,53,54,55],host_address:54,host_dist:3,host_id:25,hostconnect:0,hostdist:[0,3,27],hostfilterpolici:[0,27],hostfilterpolicyinittest:0,hostnam:[0,27,54],hoststatelisten:3,hot:46,hour:32,how:[0,1,4,6,9,27,30,38,39,41,42,44,45,47,50,54,55],howev:[0,3,10,30,34,37,38,41,46,47,50,55,56],html:[6,10,38,48],http:[6,10,27,38,48,50,53],huge:49,human:[25,41],i:[8,10,15,18,27,30,38],id:[0,3,4,6,9,10,15,18,29,34,36,37,38,44,54,56],idea:27,ideal:[32,41],idempot:[33,44],identifi:[0,1,37,47],identitytransl:[3,27],idl:0,idle_heartbeat_interv:3,idle_heartbeat_timeout:[0,3],ids_to_fetch:44,ie:[13,50,54],if_exist:[9,10],if_not_exist:[9,10],iff:9,ifnotexistswithcountercolumn:40,ignor:[0,3,8,26,27,29,30,44,55],ignored_address0:27,ignored_address1:27,imagin:27,immedi:[1,3,34,44],immut:[0,32,48],impact:4,implement:[0,2,3,5,15,18,19,20,21,22,23,24,27,29,32,41,46,49,50,54,55],impli:[30,45],implicit:[0,10,55],implicitli:[3,8,37],importerror:39,impos:37,improv:[0,1,35,49,55],in_memori:53,inbetween:27,includ:[0,3,9,10,25,26,40,45,49,54,55,56],include_keyspac:9,inclus:3,incomplet:0,inconsist:0,incorrect:[0,44],incorrectli:[0,30],increas:[0,27,31,46],increment:6,incur:9,indefinit:0,independ:[32,54],indetermin:3,index:[0,3,6,25,37,38,48,55],indexmetadata:25,indic:[0,1,2,3,6,8,9,10,25,27,38,47,53],individu:3,inet:[0,1,25],inet_address:0,inet_ntop:0,inet_pton:0,infin:0,infinit:[0,27],inflat:29,influenc:27,info:[0,3,33,44],inform:[0,3,5,9,25,27,41,52],inherit:[0,6,9,11,42],init:[0,3,36,40],initi:[0,2,3,5,6,7,9,15,18,27,29,31,32,35,38,39,44,46,47,54],initial_respons:2,initialize_reactor:[19,20,21,22],inititi:40,inject:[3,42,46],inmemorycompactionstrategi:53,inplac:32,input:[0,30,40,41,42],insanc:41,insensit:9,insert:[0,1,3,4,9,10,30,32,36,37,41,44,47,55,56],insert_stat:56,insert_us:30,insid:[13,34,44],insight:0,inspect:[3,8],instal:[0,40,44,45,49,54],instanc:[0,2,3,6,9,10,13,15,18,25,26,27,30,34,38,44,48,50,54,55,56],instanti:[0,27,29,31,44],instead:[0,3,4,30,38,40,44,50,54,55],instruct:38,insuffici:[0,26],intact:42,integ:[0,6,10,11,13,17,31,32,35,36,37,38,41,48],integer_typ:32,integr:[0,29,40,41,45,46,48,55],intend:[9,31,32,46],intent:40,interact:[3,44],interfac:[0,2,27,50],interior:32,intern:[0,3,10,27,31,32,40,41,55],interpol:56,interpret:[0,30,36,38,55],intranod:53,intrins:41,introduc:[0,19,25,30,37,38,40,42,55,56],introduct:45,intruct:54,intstat:26,inupt:0,inv:[15,18],invalid:[0,1,26,30],invalidparametertypeerror:0,invalidrequest:1,invalidtypeparametererror:0,invit:40,invlabel:[15,18],invoc:46,invok:[0,3,40],involv:[30,38],io:[0,3,4,10,33,46,48,54],ip:[0,3,5,27,28,44,54],ipv4address:0,ipv6:0,ipv6address:0,irc:0,iron:40,is_analytics_sourc:[15,18],is_cql_compat:25,is_default_sourc:[15,18],is_graph_sourc:[15,18],is_idempot:[0,15,18,30,44],is_schema_agre:3,is_seri:0,is_shard_awar:53,is_shutdown:0,is_up:0,isbootstrap:27,isn:[0,9,10],isnotnul:38,isoformat:0,isol:27,issu:[0,2,27,31,32,36,55],item1:17,item2:17,item:[0,4,9,10,15,18,27,30,32,37,38,44],iter:[0,3,25,27,29,30,32,38,50,55],its:[0,2,3,5,9,19,20,23,24,27,30,32,37,42,46,54,55],itself:[46,55],jan:0,januari:0,java:27,jit:49,jitter:[0,27],jk:54,joe:[37,54],john:44,join:0,jon:[10,37,38],json:[3,12,15,18],json_data:[15,18],juli:0,jump:48,junctur:40,june:0,just:[0,3,6,25,27,32,34,37,40,44,46,50,53,56],k:[34,47,54],keep:[0,27],keepal:0,kei:[0,1,3,6,8,9,10,13,15,25,26,27,29,30,32,37,38,42,43,44,47,53,54,56],kept:4,kerbero:[0,54],kevin5000:37,kevin:37,key1:17,key2:17,key_typ:6,keyerror:0,keyfil:54,keyout:54,keyspac:[0,1,3,7,8,9,10,11,15,18,25,27,29,30,35,43,53,55],keyspace1:53,keyspace_nam:55,keyspacemetadata:[0,25],keystor:54,keystore_password:54,keyword:[0,3,6,7,9,10],kill:0,kimberli:9,kind:[0,27,55],kinit:54,klass:3,know:[3,27,36,55,56],known:[0,15,18,25,40,55],known_host:26,ks1:35,ks2:35,ks:35,ks_name:8,kwarg:[0,3,4,6,7,9,10,12,15,18,19,20,21,22,23,27,32,34,39,54],label:[15,18],lambda:54,languag:[12,15,18,40,45,49],larg:[0,3,4,10,32,38,45,55],largest:36,last:[0,1,3,27,31,38],last_act:3,last_host:1,last_nam:[9,37],lastest:36,latenc:[26,44,53],later:[0,1,9,27,44,50],latest:0,latter:[3,50],layout:25,lazi:0,lazili:29,lazy_connect:[0,7],lazyprotocolhandl:29,lbp:0,lead:[0,34,49,55],leak:0,learn:[30,54],least:[6,26,27,30,35,37,46],leav:[0,3],left:[0,3,4,9,41,55],legaci:[0,6,40,48,54,55],len:[0,9,10,35],length:[6,27,30],less:[0,46],let:[0,3,55],letter:13,level:[0,1,3,4,10,15,18,27,30,33,41,48,54],leveledcompactionstrategi:9,lib:0,libev4:46,libev:[0,33],libevconnect:[3,23,46],libevreactor:[0,3,33,46],libevwrapp:0,librari:[0,19,20,41,46,54],licens:45,lifecycl:2,lightweight:[0,1,10,30,44,45],lighweight:27,like:[0,1,3,4,9,10,15,18,26,27,30,37,38,41,44,46,50,54,56],limit:[0,3,10,30,38,41,49],line:[0,19,44,46],linear:32,lineariz:30,linestr:32,link:[0,41,46],linux:46,list:[0,1,3,4,6,7,8,9,10,13,15,17,18,25,27,29,30,32,35,43,44,45,46,48,50,55],list_col:44,list_column:10,list_column__append:10,list_column__prepend:10,listen:[0,3],listen_address:0,liter:[0,15,17,18,30,41,44,55,56],live:[1,27,43],ll:[38,54],load:[0,3,9,10,15,18,33,37,38,40,42,53,54,55],load_balancing_polici:[3,27,42,44,52,53],load_cert_chain:54,load_verify_loc:54,loadbalancingpolici:[0,3,27,42],local:[0,1,3,27,30,41,42,43,44,55],local_dc:[0,27,52],local_on:[0,1,3,44],local_queri:42,local_quorum:[0,1,44],local_seri:[1,30,44],localhost:[7,10],localstrategi:25,localtim:41,locat:[3,40,54,56],lock:0,locked_execut:42,log:[0,3,8,27,30,31,44,45,55],log_error:3,log_result:3,logentri:34,logger:0,logic:[0,37,53],logo:45,longer:[0,1,55],look:[13,37,38,54],lookup:[0,25,27],loop:[0,3,4,21,33,44,46,54],lose:0,loss:0,lot:[0,53],low:[15,18,27,33],lower:[1,4,27,32,38,44],lower_bound:32,lowercas:0,lwt:[0,3,9,47],lwtexcept:[0,9,10,40],lz4:[0,46],m:[9,36],mac:[0,46],machin:44,madd:46,made:[1,3,5,27,38,44,55],mai:[0,2,3,4,6,7,27,30,32,37,38,43,44,46,49,54,55],main:[0,3,54,56],maintain:[0,3,30,32,37,55],major:[0,27,42,54],make:[0,1,3,10,25,27,37,40,41,42,43,44,45,46,48,51,54,55],make_query_plan:27,make_token_replica_map:0,manag:[0,3,6,9,10,11,28,33,34,37,42,46,48,55],mandatori:[0,3],mani:[0,1,3,4,27,44,49,50,54,55],manifest:[0,43,47],manipul:[0,3],manner:32,manual:[3,9,34],manufactur:[10,35,38],map:[0,1,3,8,10,13,15,17,18,25,29,30,32,33,37,38,44,48,55],map_column:10,map_column__remov:10,map_column__upd:10,mapper:[0,7,40,45],march:0,margin:4,mark:[0,3,5,33,44,45],marker:41,master:[0,3,53],match:[0,3,5,9,10,15,18,25,30,38,40,42,43,44,46,54,55,56],materi:[0,3,4,25,29,46,55],materializedviewmetadata:25,math:0,max:[0,3,5,26,44],max_attempt:[27,44],max_connect:3,max_delai:27,max_length:6,max_request:3,max_schema_agreement_wait:3,max_support:1,max_threshold:9,max_tim:38,max_uuid_from_tim:32,max_wait:[3,30],max_wait_sec:3,max_wait_sec_p:3,maximum:[1,3,6,27,32,38],maxtimeuuid:38,maxyear:[32,41],md5token:25,md:53,mean:[3,9,26,27,38,44],meaningless:38,meant:41,measur:[3,27],mechan:[0,2,3,27,54],median:26,meet:[26,27,54],member:[32,37],memori:[0,4,38,53,55],mention:[0,41,44],merg:40,mesh:55,messag:[0,1,2,3,5,29],message_types_by_opcod:29,meta:[0,3,37],metadata:[0,3,15,18,27,30,33,42,43,52,53],method:[0,2,3,9,10,27,29,30,35,36,37,38,41,43,44,46,49,53],metri:26,metric:[0,3,33],metrics_en:3,micro:32,microsecond:[0,31,55],middl:13,might:[0,3,30,50,54],migrat:48,millisecond:[0,17,32,41],millsecond:41,min:[0,26,43],min_length:[0,6],min_request:3,min_support:1,min_threshold:9,min_tim:38,min_uuid_from_tim:32,minim:[3,40,41,44],minimalist:32,minimum:[1,3,6,32,38],mintimeuuid:38,minut:[0,32,46],minyear:[32,41],mismatch:0,misplac:0,miss:[0,27],misspel:13,mistak:40,mitig:49,mix:[0,30],mke:0,mm:[17,32],mmmuuunnn:32,mno:46,mock:0,mode:0,model:[0,3,8,33,38,43,48,55],model__lik:38,modelexcept:40,modelqueryset:10,modern:0,modif:8,modifi:[0,1,8,9,10,32],modul:[0,9,11,18,19,20,40,46,49],monkei:[0,21,22,54],monkey_patch_loop:0,monoton:0,monotonictimestampgener:31,month:32,montonictimestampgener:0,more:[0,3,4,6,9,10,15,25,27,29,31,38,40,42,44,45,49,50,54,55],most:[3,27,30,37,40,41,43,50],mostli:[18,47],move:[0,3,30,55],ms:32,ms_timestamp_from_datetim:32,msg:29,much:[37,41,54,55],multipl:[0,3,10,12,14,15,18,27,34,35,44,48,49,55],multipleobjectsreturn:[0,10],multipli:13,multiprocess:0,multithread:0,murmur3:[0,3,46],murmur3partition:[0,25,46],murmur3token:[0,25],mussei:[46,54],must:[0,1,3,4,10,30,32,37,38,44,46,54,55,56],mutabl:[0,3],mutat:48,mutual:[7,32],mv:27,my:54,my_callback:34,my_graph:12,my_tabl:44,my_user_id:30,mycf:3,mykeyspac:[3,30,44,55,56],mymod:36,mymodel:36,mystery_funct:34,mystorepass:54,mytabl:4,n:10,naiv:[6,41],name:[0,1,3,7,8,9,10,11,12,13,15,18,25,26,27,29,30,34,37,40,44,47,55,56],named_arg:34,named_tuple_factori:[0,3,16,30,55],namedt:38,namedtupl:[0,3,4,30,37,44,47,55,56],namedtuple_factori:0,nan:[0,32],nanosecond:[6,32,41],nativ:[0,1,15,18,29,37,45],native_shard_aware_transport_port:53,native_shard_aware_transport_port_ssl:53,native_transport_address:0,natur:2,necessari:[3,44,46,54],need:[0,1,3,6,12,27,30,32,34,35,36,37,38,39,44,46,49,53,54,55,56],neg:[0,32,38],negoti:2,nest:[0,32],net:27,network:[0,30,44],networktopologystrategi:[0,8,25],never:[0,27,34,47,49,55],neverretrypolici:3,new_authent:2,new_nod:0,new_plan:27,new_schedul:27,newkei:54,newli:[0,25,27],next:[0,3,21,27,42,48,50,54],next_pag:38,ngdg:0,nice:0,nicer:38,no_compact:0,no_valid_replica:25,noconnectionsavail:28,node1:42,node1_profil:42,node1_whitelist:42,node2:42,node2_profil:42,node:[0,1,3,5,25,26,28,30,32,33,44,53,54],node_domain:5,nodesync:0,nodetool:27,nohostavail:[0,3],nomenclatur:55,non:[0,3,6,10,32,33,37,44,45],nonblock:0,none:[0,1,2,3,4,5,6,7,8,9,10,11,12,14,15,17,18,25,26,27,30,32,36,38,39,41,43,44,47,50],nonetyp:0,nonexist:[0,1],normal:[0,3,9,10,12,27,30,32,41,44,50,55],nose:0,notabl:55,note:[0,3,4,7,8,9,10,19,27,30,32,35,37,38,40,41,42,44,45,50,54,55],noth:[0,25,27],notic:0,notif:0,notifi:3,nov:0,novemb:0,now:[0,31,34,36,38,40,41,44,48],nt:0,nullhandl:0,num:26,number:[0,1,3,4,5,9,10,26,27,40,42,44,46,47,50],numer:[0,41],numpi:29,numpyprotocolhand:29,numpyprotocolhandl:[0,29],o:[44,54],obj:[15,18],object:[0,3,4,12,15,17,18,25,26,27,30,31,32,34,35,36,37,41,42,43,44,45,49,50,55,56],obtain:[3,10,43,49],occur:[1,27,30,34,44,55],oct:0,octob:0,od:32,off:3,offer:[32,46,49,50],offici:[54,55],offset:32,often:37,ok:[27,54],old:[0,10,40],omit:[1,30],on_add:27,on_authentication_success:2,on_down:27,on_read_timeout:27,on_remov:27,on_request_error:[0,27],on_unavail:27,on_up:[0,27],on_write_timeout:[0,27],onc:[3,4,19,20,21,22,27,29,30,34,36,38,46,50,53],one:[0,1,2,3,6,10,13,26,27,30,32,35,36,37,38,42,44,53,54,55],ones:[10,40],onli:[0,1,3,4,5,6,7,8,9,10,18,19,27,30,31,34,37,38,40,41,44,45,46,47,53,54,55],onward:53,op:38,opaqu:3,opcod:29,open:[0,2,3,26,27,28,32,45],open_connect:26,openssl:54,oper:[0,1,3,5,8,9,10,15,18,30,32,33,35,44,47,55],operationtimedout:[0,1,3],opertaion:0,oppos:27,optim:[0,45,46,49],option:[0,1,2,3,5,7,9,10,11,12,14,25,29,30,33,38,40,42,44,47,48,49,53,54,55,56],option_map:25,options__contain:38,options_map:25,order:[0,1,4,6,10,25,27,30,32,34,37,41,55],order_bi:[10,38],ordered_dict_factori:[0,3,16,30,55],ordereddict:[0,3,30,32,44],orderedmap:[0,32],orderedmapserializedkei:32,orderedset:0,org:38,organ:45,origin:[0,3,38,55],os:46,oss:[0,27],other:[2,3,6,8,9,15,18,26,27,30,32,38,44,45,46,53,54,55,56],other_error:26,otherstuff:56,otherwis:[2,3,6,9,27,32,54],ou:54,our:[38,44,48,54],out:[0,1,4,9,27,32,34,36,38,40,41,44,54],outcom:47,output:[0,41],output_password:54,outsid:[0,6,27,32],outv:[15,18],outvlabel:[15,18],over:[3,27,29,38,49,50,54,55],overcount:27,overflow:[0,41],overflowerror:[0,32],overhaul:55,overhead:[0,4,34],overload:[0,1,6,26,27],overrid:[0,3,9,15,18,42,44,55],overridden:[0,3,50],overriden:0,overs:3,overview:[40,41,45,48],overwrit:10,own:[3,9,37,54],owner:37,owner_id:[37,40],pack:[0,30],packag:[0,2,32,41,46,48,54,55],page:[0,1,3,45,51],pagedresult:[0,50,55],pagedresulthandl:50,pagin:[0,38,50],paging_st:[3,50],pair:[0,29],panda:29,parallel:0,param:[0,4,13],paramet:[0,3,4,6,7,8,9,10,12,14,15,18,27,29,30,31,32,37,40,47,52,54,55,56],parameter:56,parent:[0,20],pars:[0,15,18,29,32,43,44],parser:[0,29],part:[0,8,10,30,35,40,41,46],parti:[2,3,41,48],partial:[0,21,22,30],particular:[0,3,25,27,30,53],particularli:38,partit:[0,6,10,25,27,30,38],partition:0,partition_kei:[6,10,30,38],pass:[0,2,3,4,6,7,9,10,25,29,30,34,36,37,38,39,47,48,53,54,55,56],passin:54,password:[2,54],passwordauthent:[2,54],patch:[0,21,22,41,54],path:[0,15,18,29,46,54],path_to_bundle_yaml:52,pattern:[37,49],paxo:30,payload:[0,1,3,30,33],peer:[0,5,25],peers_v2:0,pem:54,pend:0,pending_us:30,pep:0,per:[0,3,4,6,9,10,25,27,35,37,43,44,50,53,55],percentil:26,perform:[0,1,3,9,10,27,30,33,37,38,45,46,51],perhap:46,period:39,permiss:54,permit:27,persist:[0,15,18,27,41],person:[9,37,38],person_id:37,perspect:[2,27],pertain:3,pertin:47,pet:[37,40],pet_id:[37,40],pet_typ:[37,40],phase:[2,3,30,46],photo_id:[10,37],phrase:13,pick:[36,44],pip:[0,55],pk:[38,44],pk__token:[0,38],pk__token__gt:[0,38],place:[0,40,44,55],placehold:[3,15,18,30,44,56],placement:[0,8],plai:0,plain:54,plaintextauthent:2,plaintextauthprovid:[0,2,3,54,55],plan:[0,8,27,45],platform:[0,42],pleas:[0,3,6,9,11,27,37,43,45,54],plu:[38,47],plug:39,pluggabl:0,pmfstat:26,point:[0,3,6,26,27,32,41,44,54,55],polic:27,polici:[0,3,33,42,43,44,52,53,55],poll:[3,30,43],polygon:32,polymorphic_kei:40,pool:[0,1,3,33,55],pool_wait_timeout:3,popul:[0,3,27,30,38],port:[0,3,5,25,44,53],portion:[30,32],posit:[3,10,30,34,38,44,47,55],possibl:[0,3,9,21,27,31,32,37,38,41,46,50,54,55],post:[0,49],postfork:[39,43],potenti:0,pr:0,practic:44,practiv:10,pre:[0,46],preced:[3,27,34,47],precis:[0,6,17,32,40,41,55],predic:[0,27,33],predict:38,preemptiv:44,preexist:7,prefer:[0,27,41,44,46,55],prefix:[9,11,13],prematur:0,prepar:[0,3,4,27,33,41,43,54,56],prepare_on_all_host:3,prepared_stat:30,preparedstat:[0,3,30,44],preparedstatementtest:0,preparemessag:0,prepend:[10,47,55],present:[0,7,10,30,41,42,43,46,47,55],preserv:[0,6,9,30,40],presist:37,pretti:49,preval:41,prevent:[0,10,40,44,46],previou:[0,3,54,55],previous:[0,40,42,55],previous_vers:1,price:[10,38],primari:[0,3,6,8,9,10,25,30,37,38,47,53,56],primary_host:27,primary_kei:[6,9,10,25,35,36,37,38,40,48],princip:[0,54],print:[3,9,10,12,30,32,35,37,41,42,43,44,46,48,52,53,56],prior:0,privat:[0,1,27],probabl:[27,38,54],problem:[0,3,26,43],process:[0,3,4,20,43,44,46,49,53,54,55],process_row:50,process_us:[3,4,44,50],produc:[2,4,15,18,38],product:[8,48,54],profil:[0,3,4,12,14,45,52],profile_long:44,program:52,programmat:3,project:[1,40,45,48,49],prompt:[46,54],proof:0,propag:[0,27,30],proper:[0,39,46],properli:[0,3,37,38,44],properti:[0,1,3,5,9,13,15,18,25,27,28,30,32,37],protect:0,protocol:[0,1,3,5,6,12,14,30,33,37,45,53],protocol_tl:[0,54],protocol_vers:[0,1,3,4,29,30,32,37,48,50,54,55,56],protocolerror:5,protocolhandl:[0,29],protocolvers:1,provid:[0,3,12,13,15,18,27,41,42,43,46,49,50,52,54,55],proxi:5,proxim:13,proxy_address:5,prudent:40,ps:50,ptyhon:0,publish:[0,46,54],pure:[0,2,27,29,46,54],purpos:[3,6],push:[0,46],py:[0,46],pyopenssl:[0,54],pypi:[0,46],python2:32,python3:0,python:[0,15,17,18,19,20,29,30,32,37,40,41,44,47,48,49,51,52,54,55,56],pyton:0,pytthon:0,pytz:41,q2:48,q:[35,38,48],qop:[2,54],quadrat:0,quantiz:6,queri:[0,1,3,4,6,9,12,15,16,18,25,27,29,32,33,35,37,40,41,42,45,46,48,49,56],query_cl:[3,30],query_from_travers:12,query_str:[15,18,30],queryexhaust:3,queryhandl:[3,29],queryoper:0,queryset:[0,9],querytrac:[0,30,43],question:[45,48],queu:34,quickli:[0,49],quorum:[1,10,27,30,44],quot:[0,17,41],race:0,rack:[0,28,52],radiu:32,rais:[0,1,2,3,4,5,6,9,10,15,18,27,30,32,34,37,38,40,44,50,55],raise_on_first_error:4,random:[0,27,32,38],randompartition:25,rang:[0,4,10,32,38,41,43],range_request_timeout_in_m:1,rare:0,rather:[0,32,46],raw:6,re:[0,27,30,37,38,39,44,46,54,56],reach:34,reachabl:27,reactor:[0,20,24,43],read:[0,1,6,15,18,26,27,30,32,34,36,43,54],read_inet:0,read_repair:0,read_repair_ch:0,read_request_timeout_in_m:1,read_timeout:26,readabl:25,reader:[12,15,18],readfailur:1,readm:0,readtimeout:[1,44],reason:[1,3,27,41,54],rebuild:[0,3],rebuilt:0,receiv:[0,1,3,27,44],received_respons:[1,27],recent:0,recogn:[15,18],recommend:[0,3,4,27,36,44,49,54,55,56],reconnect:[0,33],reconnection_polici:3,reconnectionpolici:[0,27],reconnector:0,record:[0,6,10,27,38],recreat:[0,25],recurs:0,redhat:46,reduc:[0,3,49,53],redund:40,reevalu:0,ref:0,refactor:[0,41],refer:[0,10,34,40,42,47,55],referenc:3,refresh:[0,3],refresh_:55,refresh_keyspace_metadata:3,refresh_nod:[0,3],refresh_schema:[0,55],refresh_schema_metadata:3,refresh_table_metadata:[3,53],refresh_user_aggregate_metadata:3,refresh_user_function_metadata:3,refresh_user_type_metadata:3,regard:[3,27,32],regardless:[26,27,46,47],regex:13,regist:[0,3,7,12,17,26,34,37,45,55],register_connect:[0,7,35],register_listen:[0,3],register_user_typ:[3,55,56],registr:35,registri:7,regress:0,regular:[13,30,36,38],reilli:44,reinstal:46,reject:47,rel:41,relat:[0,30,38,42],relax:7,releas:[0,9,27,40,42,54,55],release_vers:[43,44],reli:[27,38],reloc:40,remain:[3,20,27,40,42],rememb:44,remot:[0,3,27,53],remoteconnect:12,remov:[0,3,6,8,10,27,30,32,42,47],remove_request_init_listen:3,repair:27,repeat:[27,44],replac:[0,3,6,29,40,54,55],replai:[1,27],replic:[0,3,8,25,40,53],replica:[0,1,8,25,26,27,30,44],replication_factor:[8,25,53],replication_factor_info:25,replicationfactor:25,replicationstrategi:25,report:[0,27],reprepar:0,reprepare_on_up:3,repres:[1,3,5,6,9,15,18,25,26,28,30,31,32,37,38,40,41,55],represent:[0,25,30,32,55],reproduc:0,req:54,req_distinguished_nam:54,request:[0,1,3,4,26,27,38,39,42,44,45,47,49,54,55],request_id:0,request_tim:[0,26],request_timeout:[3,42,44],requestexecutionexcept:1,requestvalidationexcept:1,requir:[0,1,2,3,6,7,19,27,29,30,32,37,38,39,40,44,46,48,54,55],require_client_auth:54,required_replica:[1,27],required_respons:[1,27],reserv:0,reset:27,resolut:[0,32],resolv:[0,3,5,27,36,54],resort:27,resourc:[19,20,21,22,46,54],respect:[0,3,38],respond:[1,2,27,44],respons:[0,1,2,3,27,29,38,44],response_futur:3,responsefutur:[0,3,29,43,44,49,50,55],rest:[27,44],restart:[0,44],resulset:0,result:[0,3,4,9,10,12,15,18,25,26,27,29,30,32,37,38,41,43,44,45,53,55,56],result_cach:0,result_metadata:29,result_or_exc:4,result_set:3,results_gener:4,results_metadata:0,resultset:[0,3,50,55],resync:9,retain:[0,41],rethrow:27,rethrown:0,retri:[0,7,26,30,33,44],retriev:[1,3,10,30],retry_connect:7,retry_next_host:27,retry_num:27,retry_polici:[0,3,15,18,27,30,42,43,44],retrypolici:[0,3,26,27,30,43],retun:47,reus:[3,14,30],revers:[10,27],review:0,rework:55,rf:[0,1],rhel:46,rich:3,right:[27,30,44],ring:[0,3,27,32,33],risen:54,risk:27,rlac:0,robin:27,robust:[0,41],role:54,root:54,root_ca_base_nam:54,root_cert_pass:54,rootca:54,rotat:27,round:[0,27,32],roundrobinpolici:[27,53],roundtrip:30,rout:[0,3,9,27,43,46],routing_kei:[15,18,27,30,43],row:[0,3,4,5,10,12,29,33,34,37,38,41,42,43,44,47,48,50,55,56],row_factori:[0,3,7,29,30,42,44],row_id:10,row_list:55,rpc:[5,28],rpc_addr:0,rpc_address:[0,42],rsa:54,rule:30,run:[0,9,10,21,27,34,37,39,44,46,48],run_in_executor:0,runtim:[0,46,49],runtimeerror:0,s:[0,1,2,3,6,7,9,10,11,24,27,29,30,32,34,35,36,37,38,39,41,44,45,46,48,52,53,54,55,56],safe:[0,4],safeti:0,same:[0,3,4,6,7,12,15,18,25,27,30,32,34,35,36,37,38,42,43,44,46,54,55],sasi:38,sasl:[0,2,54],sasl_kwarg:[2,54],saslauthent:[0,2],saslauthprovid:[0,2,54],saslclient:0,satisfi:1,save:[0,9,10,34,35,37,38,41,44,50],scale:[0,26,41,46,49,55],scan:43,scenario:[0,36],schedul:[0,34],schema:[0,3,9,30,33,37,44,55],schema_event_refresh_window:3,schema_metadata_en:3,schema_trigg:0,schemapars:0,scope:[0,3,10],scratch:42,script:[0,40,46,49],scylla:[38,40,46,51,55],scylla_cloud:52,scylladb:[45,53],search:13,second:[0,3,10,26,27,30,31,32,38,41,44],secondari:[0,25,34,38],section:[0,38,40,45,47,49,54,55],secur:[0,45,55],see:[0,1,3,4,6,9,10,11,13,15,18,27,29,30,32,37,38,41,42,43,44,46,47,48,49,50,53,54,55],seen:[0,3,27],segment:40,select:[0,3,4,9,10,30,38,42,43,44,46,50,53,54,55,56],select_stat:4,self:[3,15,18,37,50,55,56],semant:[0,3],send:[0,1,2,3,5,27,44,45,55],sensibl:9,sensit:[0,9],sent:[0,1,2,3,29,44],sep:0,separ:[3,54],septemb:0,seq:43,sequenc:[0,3,4,14,17,27,30,32,44],sequenti:0,serd:0,serial:[0,1,3,12,15,18,30,41],serial_consistency_level:[3,15,18,30,42,44,47,55],serializ:3,serv:40,server:[0,1,2,3,9,15,18,25,29,30,33,38,44,47,48,55],server_authenticator_class:2,server_hostnam:54,server_nam:5,server_vers:43,servererror:27,serverless:45,servic:[2,54],service_timeout:21,session:[0,1,4,7,10,12,14,15,18,25,27,29,30,33,35,39,42,43,46,47,48,49,50,52,53,54,56],sesssion:0,set:[0,1,2,3,4,6,7,8,9,10,11,12,13,15,17,18,19,20,21,22,25,26,27,30,32,35,37,38,42,43,45,46,48,50,52,53,54,55],set_column:10,set_column__add:10,set_column__remov:10,set_core_connections_per_host:[3,4],set_default_connect:[7,35],set_keyspac:[0,3,27,44,56],set_max_connections_per_host:3,set_max_requests_per_connect:3,set_meta_refresh_en:3,set_min_requests_per_connect:3,set_sess:[0,7],set_source_analyt:[15,18],set_source_default:[15,18],set_source_graph:[15,18],set_stats_nam:26,set_verifi:54,setenv:46,setup:[0,7,10,35,37,38,39,40,44,46,48,54],setuptool:[0,46],sever:[0,38,40,44,46,49],shallow:[3,42],shard_aware_opt:53,shard_aware_stat:53,shards_count:53,share:[0,3,19,20,21,22,42,49],shed:[15,18],shell:46,shift:41,shortcut:[3,46],should:[0,2,3,4,6,7,8,9,10,15,18,19,20,21,22,25,27,30,31,37,40,42,44,46,49,53,54,55],should_log:3,shouldn:0,show:[0,8,32,36,38,40,42,47,54],shown:[3,35,37,56],shuffl:38,shuffle_replica:27,shutdown:[0,3,39,52],side:[0,1,2,3,15,18,27,40],sign:[6,54],signal:39,signatur:[1,3],significantli:[38,53],silent:27,similar:[27,29,34,52,54],simpl:[0,6,15,18,27,30,38,40,41,44,46,49],simpleconvictionpolici:[3,27],simplegraphstat:[15,18],simpler:55,simplest:[38,44],simplestat:[0,3,15,18,30,44,50],simplestrategi:[8,25,53],simpli:[0,9,17,27,34,37,40,44,46,56],simplifi:[15,18],simulacron:0,simultan:42,sinc:[0,9,29,31,32,36,38,41,43,56],singl:[0,3,4,6,8,9,10,14,25,27,28,30,32,37,38,40,42,44,46,47,55],single_object_row_factori:[15,18],site:[0,41],situat:[27,34,37],six:[0,46,55],size:[0,3,10,55],sizeti:0,sizetieredcompactionstrategi:9,skip:[0,9],slack:0,sleep:[27,37],slice:[0,3,38],slightli:0,slow:0,smaller:27,smallint:[0,6,15,18,44],smoke:0,snappi:46,snapshot:0,sni:5,sniendpoint:5,sniendpointfactori:5,so:[0,1,3,10,21,25,27,30,37,38,41,42,44,47,48,49,50,54,55],socket:[0,5,54],socket_famili:5,sockopt:3,soft:0,softwar:45,some:[0,1,9,15,18,27,34,37,38,41,44,45,46,47,48,50,54,55,56],some_id2:34,some_id:34,someth:[2,27,37,38,46,54],sometim:[0,10,15,18,27,46,50],somewher:[34,50],sort:[0,4,6,32,38],sortedset:[0,32,55],sourc:[0,3,15,18,45,46],source_elaps:[0,43],span:46,spark:[0,3],spcifi:1,spec:41,special:[0,6,29,37,38,40,43],specif:[0,2,5,13,15,17,18,25,27,40,45,46,55,56],specifi:[0,1,3,6,8,9,10,11,12,27,29,30,32,35,37,38,40,41,42,44,54,55],specul:[0,27],speculative_execution_polici:[3,44],speculativeexecutionpolici:[27,44],speed:3,speedup:38,spell:41,spin:0,split:2,squar:47,ss:32,ssl:[0,5,44],ssl_context:[0,3,44,54],ssl_error_want_read:0,ssl_error_want_writ:0,ssl_opt:54,ssl_option:[0,3,5,54],ssl_version:54,sslcontext:[0,54],sstabl:43,sstable_size_in_mb:9,st:[3,37,56],stabil:0,stabl:0,stale:27,stall:0,standard1:53,standard:[0,19,20,26,38,39,41,44,46,52,54,55],start:[0,3,34,38,41,45,50,55],start_fetching_next_pag:[3,50],start_tim:3,startup:0,stat:[0,26,53],state:[0,3,10,20,27,34,45,47],stateless:50,statement:[0,3,25,27,33,34,36,41,42,43,47,50,56],statements_and_param:4,statements_and_paramet:4,stats_nam:26,statu:[47,53],status_event_refresh_window:3,stddev:26,stdlib:0,step:[37,45],steroid:38,steve:10,still:[0,15,18,30,34,37,40,42,44,55,56],stmt:0,stop:[4,34],store:[0,1,6,9,30,37,41,52],str:[7,8,10,17,32,44],straightforward:[37,40,41],strategi:[0,40,55],stream:[0,29],stream_id:29,street:[3,11,37,55,56],stress:0,strict:[6,49],strictli:0,string:[0,1,2,3,6,12,13,15,17,18,25,26,27,29,30,32,41,44,54],string_typ:32,strip:0,strong:0,structur:[15,18,25,37],studio:46,stuff:[3,56],style:3,sub:[37,40],subclass:[0,1,2,3,27,30,37,54],submit:[0,43],submit_schema_refresh:55,submodul:[40,55],suboptim:27,subsequ:40,subset:38,substanc:39,substanti:[4,55],succe:[3,27],succeed:0,success:[0,1,2,3,4,10,27,30,44,46],successfulli:[0,53],sudo:46,suffici:27,suggest:[44,46],suit:[0,54],suitabl:[2,17,25,36],superset:25,suppli:[0,3,30,44,54,55],support:[0,1,2,3,8,9,10,12,27,32,34,36,38,41,44,45,50,53,54,55,56],supported_vers:1,suppos:[0,37,54],sure:[0,3,27,37,43,44,46,49,51,54],surfac:0,surround:0,swap:55,sy:0,sync:[9,35,37],sync_schema:0,sync_tabl:[0,8,10,35,37,48],sync_typ:[8,11,37],synch:8,synchron:[0,3,4,8,37,49,50],syntax:[0,10,34,38],syntaxexcept:0,system:[0,5,25,38,42,43,44,46,55],t:[0,9,10,15,31,37,38,43,44,47,49,54,55,56],tab:52,tabl:[0,1,3,6,8,25,30,32,33,37,44,47,48,55,56],tablemetadata:[0,25,53,55],tablemetadatadse68:25,tablemetadatav3:25,tag:[0,15,18],take:[0,3,4,8,9,15,18,25,27,35,44,46,54],taken:[15,18,40],tarbal:46,target:[0,3,13,15,18,27,46],task:[0,3,34,39],tcp:0,tear_up_couch:37,technic:40,techniqu:44,tell:56,tenant:41,term:27,tesla2012:38,tesla:[35,38],test2:10,test4:10,test:[0,10,21,22,27,31,35,46,47],test_clone_shared_lbp:0,test_clust:0,test_connect:0,test_fail_if_different_query_id_on_reprepar:0,test_set_keyspace_twic:0,test_single_interfac:0,testifexistsmodel:9,testifnotexistsmodel:9,testmodel:38,testtransactionmodel:9,text:[0,3,6,9,10,11,13,35,36,37,38,40,44,48,55,56],than:[0,1,3,6,10,27,30,31,32,38,42,44,46,49,50,54],thei:[0,1,3,4,6,8,9,10,15,18,27,29,32,34,36,37,38,40,41,55,56],them:[0,3,27,38,40,41,44,46,47,48,55],themselv:[15,18],therefor:[36,38,46],thi:[0,1,2,3,4,5,6,7,8,9,10,11,12,13,15,17,18,19,20,21,22,25,26,27,28,29,30,31,32,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,53,54,55,56],thing:[3,27,38,40,44],third:[2,41,48],thorough:[46,54],those:[0,3,26,27,30,42,46],though:55,thread:[0,3,4,44,46,49],threadpoolexecutor:0,three:[1,27,30,32,44,47],threshold:[0,3],thrift:0,throttl:0,through:[0,2,3,5,7,9,10,15,18,26,27,30,38,44,45,47,49,55,56],throughput:[0,4,49],thrown:34,thu:[10,27,30,47],ticket:54,time:[0,1,2,3,4,6,10,26,27,31,32,37,38,40,44,45,46,55],time__gt:38,time__lt:38,time_arg:32,timedata:9,timedelta:10,timedelta_or_datetim:9,timeout:[0,1,3,9,10,21,26,27,55],timer:[0,21,26],timestamp:[0,1,6,9,10,17,32,33,36,40,44,45],timestamp_gener:3,timestamp_na:41,timestamp_pres:41,timestamp_utc:41,timestamptyp:0,timeuuid:[0,6,10,32,37,44,55],timezon:[0,6,32,41],tinkerpop:[12,46],tinyint:[0,6,44],tip:45,tlsv1_2_method:54,tmp:42,to_bigint:[15,18],to_doubl:[15,18],to_float:[15,18],to_int:[15,18],to_python:0,to_smallint:[15,18],todo:32,token:[0,2,3,13,15,27,33,43,46,53],token_fuzzi:13,token_map:0,token_metadata_en:3,token_prefix:13,token_regex:13,token_str:25,tokenawar:0,tokenawarepolici:[0,3,27,42,52,53],tokenawarerout:9,tokenfun:38,tokenmap:[0,25],toler:0,tolist:12,tombston:[3,36,43],tombstone_compaction_interv:9,tombstone_threshold:9,too:[0,3,27,41],took:1,tool:46,toolkit:29,top:[15,18,27],topo:0,topolog:[0,3,27,33],topology_event_refresh_window:3,total:[3,27],trace:[0,3,33,55],traceev:30,traceunavail:[3,30],tracing_en:0,track:0,trade:4,trademark:45,traffic:[0,44],trail:0,transact:[0,1,3,12,14,27,30,45],transform:37,transient_replica:25,transit:0,translat:[33,40,44],transpar:[3,44,50],trap:34,trash:0,travers:[0,12,14,15,18,46],traversal_batch:14,traversal_class:12,traversal_sourc:12,traversalbatch:[12,14],traversalmetr:0,travisci:0,treat:[3,27,30,44,50],tree:3,tri:0,trigger:[0,3,27],truncat:[6,30,32,40],truncate_microsecond:6,truststor:54,truststore_password:54,truthi:27,ts:41,ttl:[0,9,10],ttl_in_sec:9,tunabl:49,tune:0,tupl:[0,1,3,4,9,12,17,25,27,30,38,44,55,56],tuple_factori:[0,3,16,29,30,42,44,55],turn:[3,43],twice:0,twist:[0,33,44],twistedconnect:[24,54],twistedreactor:[33,54],two:[0,1,3,13,27,29,32,38,44,46,54],txt:[0,46],type0:1,type1:1,type:[0,1,3,8,10,15,17,18,25,27,29,30,32,33,34,38,41,45,47],type_model:8,typeerror:[0,15,18],typestr:0,typic:[3,10,27,29,30,31,34,38,42,44],typo:0,tzinfo:41,u:[10,30,37,38,47],ubuntu:[0,46],uda:0,udf:0,udt:[0,3,12,18,37,45],un:[0,30],unabl:[0,27,46],unauthor:[0,1],unavail:[0,1,26,27],uncal:0,unchang:40,unclean:55,uncompar:0,uncomplet:30,uncondit:0,undefinedkeyspaceexcept:40,under:[0,25,27,37,45],underscor:0,understand:54,understood:[3,27],underutil:0,unexpect:27,unexpectedli:0,unfamiliar:38,unhexlifi:0,unicod:[0,17,44],unicodedecodeerror:0,unif:0,unifi:0,unintend:0,union:3,uniqu:[1,6,25,37,42],unit:[0,13,27,45],unittest2:0,unittest:0,unix:[0,5,31,32,41],unix_socket_path:5,unix_time_from_uuid1:32,unixsocketendpoint:5,unknown:[0,15,18,46,55],unless:[3,6,27,35,55],unlik:41,unlog:30,unlogged_batch:27,unord:[6,25],unorder:0,unpack:[0,15,18,44],unprepar:56,unrecogn:0,unrecover:5,unreferenc:0,unregist:[0,56],unregister_connect:[7,35],unregister_listen:3,unset:0,unset_valu:30,unspecifi:[0,9],unsupport:0,unsupportedoper:3,until:[0,2,3,4,7,37,43,44],untrust:3,unus:[0,46],unwis:10,up:[0,3,8,13,19,20,21,22,32,33,34,37,38,52,54,55],updat:[0,1,3,8,9,10,30,32,34,38,40,42,44,45,47],update_view_metadata:0,updatestat:0,upfront:29,upgrad:[45,48,54],upon:[3,37],upper:32,upper_bound:32,uppercas:0,us:[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,35,36,37,38,40,41,43,44,45,46,47,49,50,51,52,53,54],usag:[0,2,3,4,9,25,27,30,55],use_certificate_fil:54,use_client_timestamp:[0,1,3,55],use_default_tempdir:0,use_list_t:6,use_privatekey_fil:54,use_set_t:6,used_hosts_per_remote_dc:27,usemap:6,user1:[44,54],user2:44,user3:44,user3_lookup:44,user:[0,1,3,4,6,8,9,10,17,18,25,30,33,38,40,44,45,46,50,54],user_act:3,user_id1:44,user_id2:44,user_id3:44,user_id:[4,9,30,38,44],user_ids_to_queri:44,user_lookup_stmt:44,user_row:[3,44,50],user_typ:[3,6],user_type_map:29,user_tz:41,useraggregatedescriptor:[1,3],userdefinedtyp:[0,6,37],userfunctiondescriptor:[1,3],usernam:[2,44,54],users_to_insert:30,usertyp:[0,6,25,33,37],usertypedoesnotexist:3,usual:[10,21,41,54],utc:[32,41],utc_datetime_from_ms_timestamp:32,utcfromtim:0,utcnow:[6,41],utctimetupl:41,utf8:0,utf8typ:0,utf:[0,6,17],util:[0,1,12,21,22,33,40,41,44,52,54,55],uuid1:[10,44],uuid4:[10,48],uuid:[0,6,9,10,32,37,38,40,44,48],uuid_arg:32,uuid_from_tim:[32,40],uwsgi:[43,48],uwsgidecor:[39,43],v1:[0,1,32],v2:[0,1,45],v3:[0,1,37,45],v4:[0,1,6,30],v5:[0,1],v6:1,v:[10,12,34,47,53],val1:17,val2:17,val:15,valid:[0,1,3,6,9,10,15,18,25,27,32,47,54],validationerror:[10,37,40],valu:[0,2,3,4,6,9,10,11,13,15,17,18,25,27,29,30,31,32,34,37,40,41,44,47,53,54,55,56],value2:32,value_typ:6,valueerror:[0,32],valuemap:12,values_list:[0,38],valuesequ:30,varchar:44,variabl:[0,6,9,44,46,54],variant:55,varint:[0,6,44],variou:[26,54],various:40,ve:[9,35,37,38],verb:40,verbatim:[15,18],veri:[52,54],verif:0,verifi:0,verify_mod:54,verify_p:54,version:[0,1,2,3,6,25,29,30,31,32,37,40,44,45,46,50,55,56],vertex:[15,18,25],vertexmetadata:25,vertexproperti:[15,18],via:[0,3,37,46,50,52,54],view:[0,25,27,43],violat:10,virtual:[0,38],visit:45,visual:46,vnode:3,vs:[0,27],wa:[0,1,2,3,4,5,7,25,26,27,30,36,40,46,47,55],wai:[0,3,6,15,18,27,30,36,38,41,42,44,45,46,54,55],wait:[0,1,3,21,27,30,43,44,50],wait_for_all_pool:3,wait_for_complet:30,wake:21,want:[0,3,6,9,27,34,35,37,38,44,50,54,56],warn:[0,1,3,31,40,55],warn_on_drift:31,warning_interv:31,warning_threshold:31,was_appli:[0,3],watcher:21,we:[0,7,27,36,38,39,41,42,44,48,54,56],weakref:0,web_sess:50,well:[0,27,35,44,54],were:[0,1,3,4,19,25,27,30,36,37,40],what:[27,30,37,41,54,55,56],wheel:[0,46],when:[0,1,2,3,4,5,7,9,10,17,21,27,28,29,30,31,32,35,36,37,38,40,41,42,44,46,47,50,54,55,56],whenev:[3,50],where:[0,3,4,10,25,27,30,32,37,43,44,46,47,55],whether:[1,3,6,25,26,27,47,53],which:[0,1,3,9,10,25,27,29,30,34,35,36,38,40,44,46,49,54,55,56],whilst:0,whitelist:27,whitelistroundrobinpolici:[0,27,42,44,55],whitespac:25,who:27,whose:3,wider:[32,41],window:[0,32],wish:3,within:[0,1,3,10,13,27,30,34,41,42,44,55],withing:13,without:[0,1,3,9,10,38,41,44],wkt:[0,32],wno:46,won:37,word:[27,38],work:[0,2,7,17,27,30,32,37,38,44,45,47,48,53,54,56],workaround:[0,36,40],worker:[0,39],worker_process_init:39,working_keyspac:27,workload:[0,42,49],worth:46,would:[0,9,27,36,37,38,42,44,53,54,55],wrap:[12,15,18,27,44],wrap_socket:54,wrapper:[0,27,30],write:[0,1,8,10,15,18,26,27,30],write_request_timeout_in_m:1,write_timeout:26,write_typ:[1,27],writefailur:1,writetimeout:[0,1],writetyp:[0,1,27],written:0,wrong:[0,44],wunus:46,www:6,x509:54,x:[1,4,10,27,32,46,47],xcode:46,xrang:0,y:[0,10,27,32],yaml:[1,27,52,53],year:[10,32,35,38],year__gt:38,year__in:38,year__lt:38,yet:[3,38,44,55],yield:[4,27],you:[0,3,4,6,9,12,27,30,34,35,37,38,43,44,46,49,50,52,53,54,55,56],your:[0,3,6,9,35,37,38,40,43,44,47,48,49,50,52,54,55,56],yourself:49,yum:46,yyyi:[17,32],z:10,zero:0,zip:[55,56],zipcod:[3,11,37,55,56]},titles:["CHANGELOG","cassandra - Exceptions and Enums","cassandra.auth - Authentication","cassandra.cluster - Clusters and Sessions","cassandra.concurrent - Utilities for Concurrent Statement Execution","cassandra.connection - Low Level Connection Info","cassandra.cqlengine.columns - Column types for object mapping models","cassandra.cqlengine.connection - Connection management for cqlengine","cassandra.cqlengine.management - Schema management for cqlengine","cassandra.cqlengine.models - Table models for object mapping","cassandra.cqlengine.query - Query and filter model objects","cassandra.cqlengine.usertype - Model classes for User Defined Types","cassandra.datastax.graph.fluent","cassandra.datastax.graph.fluent.predicates","cassandra.datastax.graph.fluent.query","cassandra.datastax.graph - Graph Statements, Options, and Row Factories","cassandra.decoder - Data Return Formats","cassandra.encoder - Encoders for non-prepared Statements","cassandra.graph - Graph Statements, Options, and Row Factories","cassandra.io.asyncioreactor - asyncio Event Loop","cassandra.io.asyncorereactor - asyncore Event Loop","cassandra.io.eventletreactor - eventlet-compatible Connection","cassandra.io.geventreactor - gevent-compatible Event Loop","cassandra.io.libevreactor - libev Event Loop","cassandra.io.twistedreactor - Twisted Event Loop","cassandra.metadata - Schema and Ring Topology","cassandra.metrics - Performance Metrics","cassandra.policies - Load balancing and Failure Handling Policies","cassandra.pool - Hosts and Connection Pools","cassandra.protocol - Protocol Features","cassandra.query - Prepared Statements, Batch Statements, Tracing, and Row Factories","cassandra.timestamps - Timestamp Generation","cassandra.util - Utilities","API Documentation","Batch Queries","Connections","Frequently Asked Questions","Models","Making Queries","Third party integrations","Upgrade Guide","Working with Dates and Times","Execution Profiles","Frequently Asked Questions","Getting Started","Python Driver for Scylla and Apache Cassandra\u00ae","Installation","Lightweight Transactions (Compare-and-set)","Object Mapper","Performance Notes","Paging Large Queries","ScyllaDB Cloud","ScyllaDB Cloud Serverless","Scylla Specific Features","Security","Upgrading","User Defined Types"],titleterms:{"0":[0,54,55],"0b1":0,"0b5":0,"0b6":0,"0b7":0,"0c1":0,"0c2":0,"0rc1":0,"1":[0,55],"10":0,"11":0,"12":0,"13":0,"14":0,"15":0,"16":[0,54],"17":0,"18":0,"19":0,"2":[0,55],"20":0,"21":0,"22":0,"23":0,"24":0,"25":0,"26":0,"3":[0,54,55],"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"class":[11,56],"default":[35,38,42,47,55],"do":43,"enum":1,"final":0,"float":40,"function":[38,40],"import":[40,55],"new":[35,53],"return":16,No:54,access:38,ad:42,address:27,alias:40,all:38,apach:45,api:[33,40,55],applic:43,ar:[38,55],ask:[36,43],asynchron:44,asyncio:19,asyncioreactor:19,asyncor:20,asyncorereactor:20,attribut:53,auth:2,authent:[2,54,55],automat:55,awar:53,balanc:27,base:[46,55],batch:[30,34,36,55],batchqueri:35,beta2:0,beta3:0,beta4:0,beta:0,blist:55,bug:0,c:46,call:55,callback:[34,50],can:36,cassandra:[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,41,44,45,55],celeri:39,chang:[35,40,55],changelog:0,client:[54,55],cloud:[51,52],cluster:[3,42,44,53,55],column:[6,40],compar:47,compat:[21,22],compress:46,concurr:4,configur:[46,54],connect:[5,7,21,28,35,43,44],consist:[44,55],consolid:40,content:[45,48],context:35,control:50,convers:44,copyright:45,core:33,correctli:36,cql:44,cqlengin:[6,7,8,9,10,11,40],custom:[29,54,55],cython:[46,49],data:16,datastax:[12,13,14,15,33],date:[40,41],datetyp:41,dead:27,decod:16,defin:[11,37,55,56],definit:37,delet:36,depend:[46,55],deprec:[0,40,55],deseri:29,determin:43,dict:56,dict_factori:47,dictionari:37,document:33,doe:43,don:36,doubl:40,down:27,driver:[33,43,45],dse:[54,55],encod:[17,55],error:46,event:[19,20,22,23,24],eventlet:[21,54],eventletreactor:21,exampl:[37,54],except:[1,40],execut:[4,34,42,44,54,55],execute_async:55,extend:37,extens:[46,49],factori:[15,18,30],fail:27,failur:27,faster:29,featur:[0,29,53,55],field2:36,field:36,filter:[10,38],fix:0,fluent:[12,13,14],format:16,frequent:[36,43],from:[0,36,55],from_datetim:40,gener:[31,34],get:[44,45,48],gevent:22,geventreactor:22,graph:[12,13,14,15,18,33,46,55],guid:40,handl:[27,50],help:45,helper:53,host:[27,28],how:[36,43],i:[36,43],idempot:27,ident:54,immut:38,individu:36,info:5,inherit:[37,40],initi:42,instal:[46,55],instanc:[35,37,42],instanti:36,integr:39,io:[19,20,21,22,23,24,43],issu:45,keyspac:44,larg:50,legaci:42,level:[5,40,44,55],libev:[23,46],libevreactor:23,lightweight:[47,55],list:[38,40],load:27,local_on:55,log:34,login:54,loop:[19,20,22,23,24],low:5,lower:54,make:38,manag:[7,8,35,40,43],manipul:37,manual:46,map:[6,9,42,56],mapper:[33,48],mark:27,merg:0,metadata:[25,55],metric:[26,46],model:[6,9,10,11,35,36,37,40],modul:55,multiprocess:49,my:43,name:[38,42],named_tuple_factori:47,nativ:55,node:27,non:[17,46,55],note:[46,49],now:55,object:[6,9,10,33,38,48],oper:[27,38,43],option:[15,18,46],order:[36,38],organ:40,osx:46,other:0,overload:40,packag:40,page:[50,55],paramet:[42,44],parti:39,pass:[42,44],path:41,pattern:34,payload:29,per:38,perform:[26,49],pip:46,platform:46,polici:27,pool:28,predic:13,prepar:[17,30,44,55],prepend:40,preserv:36,profil:[42,44],protocol:[29,54,55],proxi:54,pypi:49,python:[45,46],queri:[10,14,30,34,36,38,43,44,50,55],queryset:[10,35,38],question:[36,43],read:41,reconnect:27,regist:[35,56],remov:[40,55],replica:43,report:45,request:43,result:[47,50],resum:50,retri:[27,43],retriev:38,revers:40,ring:25,row:[15,18,30,36],sasl:55,schema:[8,25,40],scylla:[45,53],scylladb:[51,52],secur:54,select:35,server:[27,54],serverless:52,session:[3,44,55],set:[44,47],sever:55,shard:53,shutdown:55,side:55,size:50,soft:55,special:47,specif:53,specul:44,speed:46,ssl:[46,54],start:[44,48],statement:[4,15,17,18,30,44,55],support:46,t:36,tabl:[9,38,53],them:56,third:39,through:46,time:41,timeout:[38,43],timestamp:[31,41,55],timeuuid:[38,40],token:[25,38],topolog:25,trace:[30,43],transact:[47,55],translat:27,ttl:38,tuple_factori:47,twist:[24,54],twistedreactor:24,type:[6,11,37,40,44,55,56],udt:56,unicodemixin:40,unifi:54,unlog:34,unregist:35,up:[27,46],updat:[36,55],upgrad:[0,40,55],us:[34,42,55,56],user:[11,37,55,56],usertyp:11,util:[4,32],uwsgi:39,v1:54,v2:55,v3:55,valid:37,valu:[36,38],value2:36,verif:54,verifi:[46,54],version:54,vs:34,why:[36,43],window:46,without:[42,56],work:[36,41,55],write:41,wsgi:43,x:[0,55],your:46}}) \ No newline at end of file diff --git a/master/security.html b/master/security.html new file mode 100644 index 0000000000..66b84f70e3 --- /dev/null +++ b/master/security.html @@ -0,0 +1,1030 @@ + + + + + + + + + + + + + Security | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for an unstable version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

Security

+

The two main security components you will use with the +Python driver are Authentication and SSL.

+
+

Authentication

+

Versions 2.0 and higher of the driver support a SASL-based +authentication mechanism when protocol_version +is set to 2 or higher. To use this authentication, set +auth_provider to an instance of a subclass +of AuthProvider. When working +with Cassandra’s PasswordAuthenticator, you can use +the PlainTextAuthProvider class.

+

For example, suppose Cassandra is setup with its default +‘cassandra’ user with a password of ‘cassandra’:

+
from cassandra.cluster import Cluster
+from cassandra.auth import PlainTextAuthProvider
+
+auth_provider = PlainTextAuthProvider(username='cassandra', password='cassandra')
+cluster = Cluster(auth_provider=auth_provider, protocol_version=2)
+
+
+
+

Custom Authenticators

+

If you’re using something other than Cassandra’s PasswordAuthenticator, +SaslAuthProvider is provided for generic SASL authentication mechanisms, +utilizing the pure-sasl package. +If these do not suit your needs, you may need to create your own subclasses of +AuthProvider and Authenticator. You can use the Sasl classes +as example implementations.

+
+
+

Protocol v1 Authentication

+

When working with Cassandra 1.2 (or a higher version with +protocol_version set to 1), you will not pass in +an AuthProvider instance. Instead, you should pass in a +function that takes one argument, the IP address of a host, and returns +a dict of credentials with a username and password key:

+
from cassandra.cluster import Cluster
+
+def get_credentials(host_address):
+    return {'username': 'joe', 'password': '1234'}
+
+cluster = Cluster(auth_provider=get_credentials, protocol_version=1)
+
+
+
+
+
+

SSL

+

SSL should be used when client encryption is enabled in Cassandra.

+

To give you as much control as possible over your SSL configuration, our SSL +API takes a user-created SSLContext instance from the Python standard library. +These docs will include some examples for how to achieve common configurations, +but the ssl.SSLContext documentation +gives a more complete description of what is possible.

+

To enable SSL with version 3.17.0 and higher, you will need to set Cluster.ssl_context to a +ssl.SSLContext instance to enable SSL. Optionally, you can also set Cluster.ssl_options +to a dict of options. These will be passed as kwargs to ssl.SSLContext.wrap_socket() +when new sockets are created.

+

If you create your SSLContext using ssl.create_default_context, +be aware that SSLContext.check_hostname is set to True by default, so the hostname validation will be done +by Python and not the driver. For this reason, we need to set the server_hostname at best effort, which is the +resolved ip address. If this validation needs to be done against the FQDN, consider enabling it using the ssl_options +as described in the following examples or implement your own EndPoint and +EndPointFactory.

+

The following examples assume you have generated your Cassandra certificate and +keystore files with these intructions:

+ +

It might be also useful to learn about the different levels of identity verification to understand the examples:

+ +
+

SSL with Twisted or Eventlet

+

Twisted and Eventlet both use an alternative SSL implementation called pyOpenSSL, so if your Cluster’s connection class is +TwistedConnection or EventletConnection, you must pass a +pyOpenSSL context instead. +An example is provided in these docs, and more details can be found in the +documentation. +pyOpenSSL is not installed by the driver and must be installed separately.

+
+
+

SSL Configuration Examples

+

Here, we’ll describe the server and driver configuration necessary to set up SSL to meet various goals, such as the client verifying the server and the server verifying the client. We’ll also include Python code demonstrating how to use servers and drivers configured in these ways.

+
+

No identity verification

+

No identity verification at all. Note that this is not recommended for for production deployments.

+

The Cassandra configuration:

+
client_encryption_options:
+  enabled: true
+  keystore: /path/to/127.0.0.1.keystore
+  keystore_password: myStorePass
+  require_client_auth: false
+
+
+

The driver configuration:

+
from cassandra.cluster import Cluster, Session
+from ssl import SSLContext, PROTOCOL_TLS
+
+ssl_context = SSLContext(PROTOCOL_TLS)
+
+cluster = Cluster(['127.0.0.1'], ssl_context=ssl_context)
+session = cluster.connect()
+
+
+
+
+

Client verifies server

+

Ensure the python driver verifies the identity of the server.

+

The Cassandra configuration:

+
client_encryption_options:
+  enabled: true
+  keystore: /path/to/127.0.0.1.keystore
+  keystore_password: myStorePass
+  require_client_auth: false
+
+
+

For the driver configuration, it’s very important to set ssl_context.verify_mode +to CERT_REQUIRED. Otherwise, the loaded verify certificate will have no effect:

+
from cassandra.cluster import Cluster, Session
+from ssl import SSLContext, PROTOCOL_TLS, CERT_REQUIRED
+
+ssl_context = SSLContext(PROTOCOL_TLS)
+ssl_context.load_verify_locations('/path/to/rootca.crt')
+ssl_context.verify_mode = CERT_REQUIRED
+
+cluster = Cluster(['127.0.0.1'], ssl_context=ssl_context)
+session = cluster.connect()
+
+
+

Additionally, you can also force the driver to verify the hostname of the server by passing additional options to ssl_context.wrap_socket via the ssl_options kwarg:

+
from cassandra.cluster import Cluster, Session
+from ssl import SSLContext, PROTOCOL_TLS, CERT_REQUIRED
+
+ssl_context = SSLContext(PROTOCOL_TLS)
+ssl_context.load_verify_locations('/path/to/rootca.crt')
+ssl_context.verify_mode = CERT_REQUIRED
+ssl_context.check_hostname = True
+ssl_options = {'server_hostname': '127.0.0.1'}
+
+cluster = Cluster(['127.0.0.1'], ssl_context=ssl_context, ssl_options=ssl_options)
+session = cluster.connect()
+
+
+
+
+

Server verifies client

+

If Cassandra is configured to verify clients (require_client_auth), you need to generate +SSL key and certificate files.

+

The cassandra configuration:

+
client_encryption_options:
+  enabled: true
+  keystore: /path/to/127.0.0.1.keystore
+  keystore_password: myStorePass
+  require_client_auth: true
+  truststore: /path/to/dse-truststore.jks
+  truststore_password: myStorePass
+
+
+

The Python ssl APIs require the certificate in PEM format. First, create a certificate +conf file:

+
cat > gen_client_cert.conf <<EOF
+[ req ]
+distinguished_name = req_distinguished_name
+prompt = no
+output_password = ${ROOT_CERT_PASS}
+default_bits = 2048
+
+[ req_distinguished_name ]
+C = ${CERT_COUNTRY}
+O = ${CERT_ORG_NAME}
+OU = ${CERT_OU}
+CN = client
+EOF
+
+
+

Make sure you replaced the variables with the same values you used for the initial +root CA certificate. Then, generate the key:

+
openssl req -newkey rsa:2048 -nodes -keyout client.key -out client.csr -config gen_client_cert.conf
+
+
+

And generate the client signed certificate:

+
openssl x509 -req -CA ${ROOT_CA_BASE_NAME}.crt -CAkey ${ROOT_CA_BASE_NAME}.key -passin pass:${ROOT_CERT_PASS} \
+    -in client.csr -out client.crt_signed -days ${CERT_VALIDITY} -CAcreateserial
+
+
+

Finally, you can use that configuration with the following driver code:

+
from cassandra.cluster import Cluster, Session
+from ssl import SSLContext, PROTOCOL_TLS
+
+ssl_context = SSLContext(PROTOCOL_TLS)
+ssl_context.load_cert_chain(
+    certfile='/path/to/client.crt_signed',
+    keyfile='/path/to/client.key')
+
+cluster = Cluster(['127.0.0.1'], ssl_context=ssl_context)
+session = cluster.connect()
+
+
+
+
+

Server verifies client and client verifies server

+

See the previous section for examples of Cassandra configuration and preparing +the client certificates.

+

The following driver code specifies that the connection should use two-way verification:

+
from cassandra.cluster import Cluster, Session
+from ssl import SSLContext, PROTOCOL_TLS, CERT_REQUIRED
+
+ssl_context = SSLContext(PROTOCOL_TLS)
+ssl_context.load_verify_locations('/path/to/rootca.crt')
+ssl_context.verify_mode = CERT_REQUIRED
+ssl_context.load_cert_chain(
+    certfile='/path/to/client.crt_signed',
+    keyfile='/path/to/client.key')
+
+cluster = Cluster(['127.0.0.1'], ssl_context=ssl_context)
+session = cluster.connect()
+
+
+

The driver uses SSLContext directly to give you many other options in configuring SSL. Consider reading the Python SSL documentation +for more details about SSLContext configuration.

+

Server verifies client and client verifies server using Twisted and pyOpenSSL

+
from OpenSSL import SSL, crypto
+from cassandra.cluster import Cluster
+from cassandra.io.twistedreactor import TwistedConnection
+
+ssl_context = SSL.Context(SSL.TLSv1_2_METHOD)
+ssl_context.set_verify(SSL.VERIFY_PEER, callback=lambda _1, _2, _3, _4, ok: ok)
+ssl_context.use_certificate_file('/path/to/client.crt_signed')
+ssl_context.use_privatekey_file('/path/to/client.key')
+ssl_context.load_verify_locations('/path/to/rootca.crt')
+
+cluster = Cluster(
+    contact_points=['127.0.0.1'],
+    connection_class=TwistedConnection,
+    ssl_context=ssl_context,
+    ssl_options={'check_hostname': True}
+)
+session = cluster.connect()
+
+
+

Connecting using Eventlet would look similar except instead of importing and using TwistedConnection, you would +import and use EventletConnection, including the appropriate monkey-patching.

+
+
+
+

Versions 3.16.0 and lower

+

To enable SSL you will need to set Cluster.ssl_options to a +dict of options. These will be passed as kwargs to ssl.wrap_socket() +when new sockets are created. Note that this use of ssl_options will be +deprecated in the next major release.

+

By default, a ca_certs value should be supplied (the value should be +a string pointing to the location of the CA certs file), and you probably +want to specify ssl_version as ssl.PROTOCOL_TLS to match +Cassandra’s default protocol.

+

For example:

+
from cassandra.cluster import Cluster
+from ssl import PROTOCOL_TLS, CERT_REQUIRED
+
+ssl_opts = {
+    'ca_certs': '/path/to/my/ca.certs',
+    'ssl_version': PROTOCOL_TLS,
+    'cert_reqs': CERT_REQUIRED  # Certificates are required and validated
+}
+cluster = Cluster(ssl_options=ssl_opts)
+
+
+

This is only an example to show how to pass the ssl parameters. Consider reading +the python ssl documentation for +your configuration. For further reading, Andrew Mussey has published a thorough guide on +Using SSL with the DataStax Python driver.

+
+

SSL with Twisted

+

In case the twisted event loop is used pyOpenSSL must be installed or an exception will be risen. Also +to set the ssl_version and cert_reqs in ssl_opts the appropriate constants from pyOpenSSL are expected.

+
+
+
+
+

DSE Authentication

+

When authenticating against DSE, the Cassandra driver provides two auth providers that work both with legacy kerberos and Cassandra authenticators, +as well as the new DSE Unified Authentication. This allows client to configure this auth provider independently, +and in advance of any server upgrade. These auth providers are configured in the same way as any previous implementation:

+
from cassandra.auth import DSEGSSAPIAuthProvider
+auth_provider = DSEGSSAPIAuthProvider(service='dse', qops=["auth"])
+cluster = Cluster(auth_provider=auth_provider)
+session = cluster.connect()
+
+
+

Implementations are DSEPlainTextAuthProvider, DSEGSSAPIAuthProvider and SaslAuthProvider.

+
+

DSE Unified Authentication

+

With DSE (>=5.1), unified Authentication allows you to:

+
    +
  • Proxy Login: Authenticate using a fixed set of authentication credentials but allow authorization of resources based another user id.

  • +
  • Proxy Execute: Authenticate using a fixed set of authentication credentials but execute requests based on another user id.

  • +
+
+

Proxy Login

+

Proxy login allows you to authenticate with a user but act as another one. You need to ensure the authenticated user has the permission to use the authorization of resources of the other user. ie. this example will allow the server user to authenticate as usual but use the authorization of user1:

+
GRANT PROXY.LOGIN on role user1 to server
+
+
+

then you can do the proxy authentication….

+
from cassandra.cluster import Cluster
+from cassandra.auth import SaslAuthProvider
+
+sasl_kwargs = {
+  "service": 'dse',
+  "mechanism":"PLAIN",
+  "username": 'server',
+  'password': 'server',
+  'authorization_id': 'user1'
+}
+
+auth_provider = SaslAuthProvider(**sasl_kwargs)
+c = Cluster(auth_provider=auth_provider)
+s = c.connect()
+s.execute(...)  # all requests will be executed as 'user1'
+
+
+

If you are using kerberos, you can use directly DSEGSSAPIAuthProvider and pass the authorization_id, like this:

+
from cassandra.cluster import Cluster
+from cassandra.auth import DSEGSSAPIAuthProvider
+
+# Ensure the kerberos ticket of the server user is set with the kinit utility.
+auth_provider = DSEGSSAPIAuthProvider(service='dse', qops=["auth"], principal="server@DATASTAX.COM",
+                                      authorization_id='user1@DATASTAX.COM')
+c = Cluster(auth_provider=auth_provider)
+s = c.connect()
+s.execute(...)  # all requests will be executed as 'user1'
+
+
+
+
+

Proxy Execute

+

Proxy execute allows you to execute requests as another user than the authenticated one. You need to ensure the authenticated user has the permission to use the authorization of resources of the specified user. ie. this example will allow the server user to execute requests as user1:

+
GRANT PROXY.EXECUTE on role user1 to server
+
+
+

then you can do a proxy execute…

+
from cassandra.cluster import Cluster
+from cassandra.auth import DSEPlainTextAuthProvider,
+
+auth_provider = DSEPlainTextAuthProvider('server', 'server')
+
+c = Cluster(auth_provider=auth_provider)
+s = c.connect()
+s.execute('select * from k.t;', execute_as='user1')  # the request will be executed as 'user1'
+
+
+

Please see the official documentation for more details on the feature and configuration process.

+
+
+
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/master/sitemap.xml b/master/sitemap.xml new file mode 100644 index 0000000000..bcdebfda06 --- /dev/null +++ b/master/sitemap.xml @@ -0,0 +1,2 @@ + +https://python-driver.docs.scylladb.com/stable/CHANGELOG.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/auth.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/cluster.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/concurrent.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/connection.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/cqlengine/columns.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/cqlengine/connection.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/cqlengine/management.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/cqlengine/models.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/cqlengine/query.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/cqlengine/usertype.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/datastax/graph/fluent/index.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/datastax/graph/fluent/predicates.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/datastax/graph/fluent/query.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/datastax/graph/index.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/decoder.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/encoder.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/graph.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/io/asyncioreactor.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/io/asyncorereactor.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/io/eventletreactor.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/io/geventreactor.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/io/libevreactor.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/io/twistedreactor.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/metadata.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/metrics.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/policies.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/pool.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/protocol.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/query.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/timestamps.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/util.htmlhttps://python-driver.docs.scylladb.com/stable/api/index.htmlhttps://python-driver.docs.scylladb.com/stable/cqlengine/batches.htmlhttps://python-driver.docs.scylladb.com/stable/cqlengine/connections.htmlhttps://python-driver.docs.scylladb.com/stable/cqlengine/faq.htmlhttps://python-driver.docs.scylladb.com/stable/cqlengine/models.htmlhttps://python-driver.docs.scylladb.com/stable/cqlengine/queryset.htmlhttps://python-driver.docs.scylladb.com/stable/cqlengine/third-party.htmlhttps://python-driver.docs.scylladb.com/stable/cqlengine/upgrade-guide.htmlhttps://python-driver.docs.scylladb.com/stable/dates-and-times.htmlhttps://python-driver.docs.scylladb.com/stable/execution-profiles.htmlhttps://python-driver.docs.scylladb.com/stable/faq.htmlhttps://python-driver.docs.scylladb.com/stable/getting-started.htmlhttps://python-driver.docs.scylladb.com/stable/index.htmlhttps://python-driver.docs.scylladb.com/stable/installation.htmlhttps://python-driver.docs.scylladb.com/stable/lwt.htmlhttps://python-driver.docs.scylladb.com/stable/object-mapper.htmlhttps://python-driver.docs.scylladb.com/stable/performance.htmlhttps://python-driver.docs.scylladb.com/stable/query-paging.htmlhttps://python-driver.docs.scylladb.com/stable/scylla-cloud.htmlhttps://python-driver.docs.scylladb.com/stable/scylla-cloud-serverless.htmlhttps://python-driver.docs.scylladb.com/stable/scylla-specific.htmlhttps://python-driver.docs.scylladb.com/stable/security.htmlhttps://python-driver.docs.scylladb.com/stable/upgrading.htmlhttps://python-driver.docs.scylladb.com/stable/user-defined-types.htmlhttps://python-driver.docs.scylladb.com/stable/py-modindex.htmlhttps://python-driver.docs.scylladb.com/stable/404.htmlhttps://python-driver.docs.scylladb.com/stable/search.html \ No newline at end of file diff --git a/master/upgrading.html b/master/upgrading.html new file mode 100644 index 0000000000..1f832b9513 --- /dev/null +++ b/master/upgrading.html @@ -0,0 +1,1005 @@ + + + + + + + + + + + + + Upgrading | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for an unstable version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

Upgrading

+
+
+
+

Installation

+

Only the scylla-driver package should be installed. dse-driver and dse-graph +are not required anymore:

+
pip install scylla-driver
+
+
+

If you need the Graph Fluent API (features provided by dse-graph):

+
pip install scylla-driver[graph]
+
+
+

See Installation for more details.

+
+
+

Import from the cassandra module

+

There is no dse module, so you should import from the cassandra module. You +need to change only the first module of your import statements, not the submodules.

+
from dse.cluster import Cluster, EXEC_PROFILE_GRAPH_DEFAULT
+from dse.auth import PlainTextAuthProvider
+from dse.policies import WhiteListRoundRobinPolicy
+
+# becomes
+
+from cassandra.cluster import Cluster, EXEC_PROFILE_GRAPH_DEFAULT
+from cassandra.auth import PlainTextAuthProvider
+from cassandra.policies import WhiteListRoundRobinPolicy
+
+
+

Also note that the cassandra.hosts module doesn’t exist in scylla-driver. This +module is named cassandra.pool.

+
+
+

dse-graph

+

dse-graph features are now built into scylla-driver. The only change you need +to do is your import statements:

+
from dse_graph import ..
+from dse_graph.query import ..
+
+# becomes
+
+from cassandra.datastax.graph.fluent import ..
+from cassandra.datastax.graph.fluent.query import ..
+
+
+

See fluent.

+
+
+

Session.execute and Session.execute_async API

+

Although it is not common to use this API with positional arguments, it is +important to be aware that the host and execute_as parameters have had +their positional order swapped. This is only because execute_as was added +in dse-driver before host.

+

See Session.execute().

+
+
+

Deprecations

+

These changes are optional, but recommended:

+
    +
  • Importing from cassandra.graph is deprecated. Consider importing from cassandra.datastax.graph.

  • +
  • Use DefaultLoadBalancingPolicy instead of DSELoadBalancingPolicy.

  • +
+
+

Upgrading to 3.0

+

Version 3.0 of the DataStax Python driver for Apache Cassandra +adds support for Cassandra 3.0 while maintaining support for +previously supported versions. In addition to substantial internal rework, +there are several updates to the API that integrators will need +to consider:

+
+
+
+

Default consistency is now LOCAL_ONE

+

Previous value was ONE. The new value is introduced to mesh with the default +DC-aware load balancing policy and to match other drivers.

+
+
+

Execution API Updates

+

PYTHON-368

+

Previously results would be returned as a list of rows for result rows +up to fetch_size, and PagedResult afterward. This could break +application code that assumed one type and got another.

+

Now, all results are returned as an iterable ResultSet.

+

The preferred way to consume results of unknown size is to iterate through +them, letting automatic paging occur as they are consumed.

+
results = session.execute("SELECT * FROM system.local")
+for row in results:
+    process(row)
+
+
+

If the expected size of the results is known, it is still possible to +materialize a list using the iterator:

+
results = session.execute("SELECT * FROM system.local")
+row_list = list(results)
+
+
+

For backward compatibility, ResultSet supports indexing. When +accessed at an index, a ~.ResultSet object will materialize all its pages:

+
results = session.execute("SELECT * FROM system.local")
+first_result = results[0]  # materializes results, fetching all pages
+
+
+

This can send requests and load (possibly large) results into memory, so +~.ResultSet will log a warning on implicit materialization.

+

PYTHON-318

+

Previously trace data was attached to Statements if tracing was enabled. This +could lead to confusion if the same statement was used for multiple executions.

+

Now, trace data is associated with the ResponseFuture and ResultSet +returned for each query:

+

ResponseFuture.get_query_trace()

+

ResponseFuture.get_all_query_traces()

+

ResultSet.get_query_trace()

+

ResultSet.get_all_query_traces()

+

PYTHON-178

+

Previously, BoundStatement.bind() would raise if a mapping +was passed with extra names not found in the prepared statement.

+

Behavior in 3.0+ is to ignore extra names.

+
+
+

blist removed as soft dependency

+

PYTHON-385

+

Previously the driver had a soft dependency on blist sortedset, using +that where available and using an internal fallback where possible.

+

Now, the driver never chooses the blist variant, instead returning the +internal util.SortedSet for all set results. The class implements +all standard set operations, so no integration code should need to change unless +it explicitly checks for sortedset type.

+
+
+

Metadata API Updates

+

PYTHON-276, PYTHON-408, PYTHON-400, PYTHON-422

+

Cassandra 3.0 brought a substantial overhaul to the internal schema metadata representation. +This version of the driver supports that metadata in addition to the legacy version. Doing so +also brought some changes to the metadata model.

+

The present API is documented: cassandra.metadata. Changes highlighted below:

+
    +
  • All types are now exposed as CQL types instead of types derived from the internal server implementation

  • +
  • Some metadata attributes have changed names to match current nomenclature (for example, Index.kind in place of Index.type).

  • +
  • Some metadata attributes removed

    +
      +
    • TableMetadata.keyspace reference replaced with TableMetadata.keyspace_name

    • +
    • ColumnMetadata.index is removed table- and keyspace-level mappings are still maintained

    • +
    +
  • +
+
+
+

Several deprecated features are removed

+

PYTHON-292

+
    +
  • ResponseFuture.result timeout parameter is removed, use Session.execute timeout instead (031ebb0)

  • +
  • Cluster.refresh_schema removed, use Cluster.refresh_*_metadata instead (419fcdf)

  • +
  • Cluster.submit_schema_refresh removed (574266d)

  • +
  • cqltypes time/date functions removed, use util entry points instead (bb984ee)

  • +
  • decoder module removed (e16a073)

  • +
  • TableMetadata.keyspace attribute replaced with keyspace_name (cc94073)

  • +
  • cqlengine.columns.TimeUUID.from_datetime removed, use util variant instead (96489cc)

  • +
  • cqlengine.columns.Float(double_precision) parameter removed, use columns.Double instead (a2d3a98)

  • +
  • cqlengine keyspace management functions are removed in favor of the strategy-specific entry points (4bd5909)

  • +
  • cqlengine.Model.__polymorphic_*__ attributes removed, use __discriminator* attributes instead (9d98c8e)

  • +
  • cqlengine.statements will no longer warn about list list prepend behavior (79efe97)

  • +
+
+

Upgrading to 2.1 from 2.0

+

Version 2.1 of the DataStax Python driver for Apache Cassandra +adds support for Cassandra 2.1 and version 3 of the native protocol.

+

Cassandra 1.2, 2.0, and 2.1 are all supported. However, 1.2 only +supports protocol version 1, and 2.0 only supports versions 1 and +2, so some features may not be available.

+
+
+
+

Using the v3 Native Protocol

+

By default, the driver will attempt to use version 2 of the +native protocol. To use version 3, you must explicitly +set the protocol_version:

+
from cassandra.cluster import Cluster
+
+cluster = Cluster(protocol_version=3)
+
+
+

Note that protocol version 3 is only supported by Cassandra 2.1+.

+

In future releases, the driver may default to using protocol version +3.

+
+
+

Working with User-Defined Types

+

Cassandra 2.1 introduced the ability to define new types:

+
USE KEYSPACE mykeyspace;
+
+CREATE TYPE address (street text, city text, zip int);
+
+
+

The driver generally expects you to use instances of a specific +class to represent column values of this type. You can let the +driver know what class to use with Cluster.register_user_type():

+
cluster = Cluster()
+
+class Address(object):
+
+    def __init__(self, street, city, zipcode):
+        self.street = street
+        self.city = text
+        self.zipcode = zipcode
+
+cluster.register_user_type('mykeyspace', 'address', Address)
+
+
+

When inserting data for address columns, you should pass in +instances of Address. When querying data, address column +values will be instances of Address.

+

If no class is registered for a user-defined type, query results +will use a namedtuple class and data may only be inserted +though prepared statements.

+

See User Defined Types for more details.

+
+
+

Customizing Encoders for Non-prepared Statements

+

Starting with version 2.1 of the driver, it is possible to customize +how Python types are converted to CQL literals when working with +non-prepared statements. This is done on a per-Session +basis through Session.encoder:

+
cluster = Cluster()
+session = cluster.connect()
+session.encoder.mapping[tuple] = session.encoder.cql_encode_tuple
+
+
+

See Type Conversions for the table of default CQL literal conversions.

+
+
+

Using Client-Side Protocol-Level Timestamps

+

With version 3 of the native protocol, timestamps may be supplied by the +client at the protocol level. (Normally, if they are not specified within +the CQL query itself, a timestamp is generated server-side.)

+

When protocol_version is set to 3 or higher, the driver +will automatically use client-side timestamps with microsecond precision +unless Session.use_client_timestamp is changed to False. +If a timestamp is specified within the CQL query, it will override the +timestamp generated by the driver.

+
+

Upgrading to 2.0 from 1.x

+

Version 2.0 of the DataStax Python driver for Apache Cassandra +includes some notable improvements over version 1.x. This version +of the driver supports Cassandra 1.2, 2.0, and 2.1. However, not +all features may be used with Cassandra 1.2, and some new features +in 2.1 are not yet supported.

+
+
+
+

Using the v2 Native Protocol

+

By default, the driver will attempt to use version 2 of Cassandra’s +native protocol. You can explicitly set the protocol version to +2, though:

+
from cassandra.cluster import Cluster
+
+cluster = Cluster(protocol_version=2)
+
+
+

When working with Cassandra 1.2, you will need to +explicitly set the protocol_version to 1:

+
from cassandra.cluster import Cluster
+
+cluster = Cluster(protocol_version=1)
+
+
+
+
+

Automatic Query Paging

+

Version 2 of the native protocol adds support for automatic query +paging, which can make dealing with large result sets much simpler.

+

See Paging Large Queries for full details.

+
+
+

Protocol-Level Batch Statements

+

With version 1 of the native protocol, batching of statements required +using a BATCH cql query. +With version 2 of the native protocol, you can now batch statements at +the protocol level. This allows you to use many different prepared +statements within a single batch.

+

See BatchStatement for details and usage examples.

+
+
+

SASL-based Authentication

+

Also new in version 2 of the native protocol is SASL-based authentication. +See the section on Security for details and examples.

+
+
+

Lightweight Transactions

+

Lightweight transactions are another new feature. To use lightweight transactions, add IF clauses +to your CQL queries and set the serial_consistency_level +on your statements.

+
+
+

Calling Cluster.shutdown()

+

In order to fix some issues around garbage collection and unclean interpreter +shutdowns, version 2.0 of the driver requires you to call Cluster.shutdown() +on your Cluster objects when you are through with them. +This helps to guarantee a clean shutdown.

+
+
+

Deprecations

+

The following functions have moved from cassandra.decoder to cassandra.query. +The original functions have been left in place with a DeprecationWarning for +now:

+ +
+
+

Dependency Changes

+

The following dependencies have officially been made optional:

+
    +
  • scales

  • +
  • blist

  • +
+

And one new dependency has been added (to enable Python 3 support):

+
    +
  • six

  • +
+
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/master/user-defined-types.html b/master/user-defined-types.html new file mode 100644 index 0000000000..a5959e5954 --- /dev/null +++ b/master/user-defined-types.html @@ -0,0 +1,759 @@ + + + + + + + + + + + + + User Defined Types | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + +
+

Caution

+

+ + You're viewing documentation for an unstable version of Scylla Python Driver. + + Switch to the latest stable version. +

+
+ + + +
+ +
+ +
+

User Defined Types

+

Cassandra 2.1 introduced user-defined types (UDTs). You can create a +new type through CREATE TYPE statements in CQL:

+
CREATE TYPE address (street text, zip int);
+
+
+

Version 2.1 of the Python driver adds support for user-defined types.

+
+

Registering a UDT

+

You can tell the Python driver to return columns of a specific UDT as +instances of a class or a dict by registering them with your Cluster +instance through Cluster.register_user_type():

+
+

Map a Class to a UDT

+
cluster = Cluster(protocol_version=3)
+session = cluster.connect()
+session.set_keyspace('mykeyspace')
+session.execute("CREATE TYPE address (street text, zipcode int)")
+session.execute("CREATE TABLE users (id int PRIMARY KEY, location frozen<address>)")
+
+# create a class to map to the "address" UDT
+class Address(object):
+
+    def __init__(self, street, zipcode):
+        self.street = street
+        self.zipcode = zipcode
+
+cluster.register_user_type('mykeyspace', 'address', Address)
+
+# insert a row using an instance of Address
+session.execute("INSERT INTO users (id, location) VALUES (%s, %s)",
+                (0, Address("123 Main St.", 78723)))
+
+# results will include Address instances
+results = session.execute("SELECT * FROM users")
+row = results[0]
+print(row.id, row.location.street, row.location.zipcode)
+
+
+
+
+

Map a dict to a UDT

+
cluster = Cluster(protocol_version=3)
+session = cluster.connect()
+session.set_keyspace('mykeyspace')
+session.execute("CREATE TYPE address (street text, zipcode int)")
+session.execute("CREATE TABLE users (id int PRIMARY KEY, location frozen<address>)")
+
+cluster.register_user_type('mykeyspace', 'address', dict)
+
+# insert a row using a prepared statement and a tuple
+insert_statement = session.prepare("INSERT INTO mykeyspace.users (id, location) VALUES (?, ?)")
+session.execute(insert_statement, [0, ("123 Main St.", 78723)])
+
+# results will include dict instances
+results = session.execute("SELECT * FROM users")
+row = results[0]
+print(row.id, row.location['street'], row.location['zipcode'])
+
+
+
+
+
+

Using UDTs Without Registering Them

+

Although it is recommended to register your types with +Cluster.register_user_type(), the driver gives you some options +for working with unregistered UDTS.

+

When you use prepared statements, the driver knows what data types to +expect for each placeholder. This allows you to pass any object you +want for a UDT, as long as it has attributes that match the field names +for the UDT:

+
cluster = Cluster(protocol_version=3)
+session = cluster.connect()
+session.set_keyspace('mykeyspace')
+session.execute("CREATE TYPE address (street text, zipcode int)")
+session.execute("CREATE TABLE users (id int PRIMARY KEY, location frozen<address>)")
+
+class Foo(object):
+
+    def __init__(self, street, zipcode, otherstuff):
+        self.street = street
+        self.zipcode = zipcode
+        self.otherstuff = otherstuff
+
+insert_statement = session.prepare("INSERT INTO users (id, location) VALUES (?, ?)")
+
+# since we're using a prepared statement, we don't *have* to register
+# a class to map to the UDT to insert data.  The object just needs to have
+# "street" and "zipcode" attributes (which Foo does):
+session.execute(insert_statement, [0, Foo("123 Main St.", 78723, "some other stuff")])
+
+# when we query data, UDT columns that don't have a class registered
+# will be returned as namedtuples:
+results = session.execute("SELECT * FROM users")
+first_row = results[0]
+address = first_row.location
+print(address)  # prints "Address(street='123 Main St.', zipcode=78723)"
+street = address.street
+zipcode = address.street
+
+
+

As shown in the code example, inserting data for UDT columns without registering +a class works fine for prepared statements. However, you must register a +class to insert UDT columns with unprepared statements.* You can still query +UDT columns without registered classes using unprepared statements, they will +simply return namedtuple instances (just like prepared statements do).

+

* this applies to parameterized unprepared statements, in which the driver will be formatting parameters – not statements with interpolated UDT literals.

+
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/stable/.buildinfo b/stable/.buildinfo new file mode 100644 index 0000000000..7f4cb20925 --- /dev/null +++ b/stable/.buildinfo @@ -0,0 +1,4 @@ +# Sphinx build info version 1 +# This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done. +config: cfc961d6ca3409e87cb3e7d1c552b73f +tags: 645f666f9bcd5a90fca523b33c5a78b7 diff --git a/stable/.doctrees/CHANGELOG.doctree b/stable/.doctrees/CHANGELOG.doctree new file mode 100644 index 0000000000..d33e3c5c2d Binary files /dev/null and b/stable/.doctrees/CHANGELOG.doctree differ diff --git a/stable/.doctrees/api/cassandra.doctree b/stable/.doctrees/api/cassandra.doctree new file mode 100644 index 0000000000..5e12608782 Binary files /dev/null and b/stable/.doctrees/api/cassandra.doctree differ diff --git a/stable/.doctrees/api/cassandra/auth.doctree b/stable/.doctrees/api/cassandra/auth.doctree new file mode 100644 index 0000000000..c57613c769 Binary files /dev/null and b/stable/.doctrees/api/cassandra/auth.doctree differ diff --git a/stable/.doctrees/api/cassandra/cluster.doctree b/stable/.doctrees/api/cassandra/cluster.doctree new file mode 100644 index 0000000000..550b263ae5 Binary files /dev/null and b/stable/.doctrees/api/cassandra/cluster.doctree differ diff --git a/stable/.doctrees/api/cassandra/concurrent.doctree b/stable/.doctrees/api/cassandra/concurrent.doctree new file mode 100644 index 0000000000..c3809aa7dc Binary files /dev/null and b/stable/.doctrees/api/cassandra/concurrent.doctree differ diff --git a/stable/.doctrees/api/cassandra/connection.doctree b/stable/.doctrees/api/cassandra/connection.doctree new file mode 100644 index 0000000000..3b1e0f26ea Binary files /dev/null and b/stable/.doctrees/api/cassandra/connection.doctree differ diff --git a/stable/.doctrees/api/cassandra/cqlengine/columns.doctree b/stable/.doctrees/api/cassandra/cqlengine/columns.doctree new file mode 100644 index 0000000000..654fde2ed5 Binary files /dev/null and b/stable/.doctrees/api/cassandra/cqlengine/columns.doctree differ diff --git a/stable/.doctrees/api/cassandra/cqlengine/connection.doctree b/stable/.doctrees/api/cassandra/cqlengine/connection.doctree new file mode 100644 index 0000000000..1d3db8b023 Binary files /dev/null and b/stable/.doctrees/api/cassandra/cqlengine/connection.doctree differ diff --git a/stable/.doctrees/api/cassandra/cqlengine/management.doctree b/stable/.doctrees/api/cassandra/cqlengine/management.doctree new file mode 100644 index 0000000000..0bfe36d49e Binary files /dev/null and b/stable/.doctrees/api/cassandra/cqlengine/management.doctree differ diff --git a/stable/.doctrees/api/cassandra/cqlengine/models.doctree b/stable/.doctrees/api/cassandra/cqlengine/models.doctree new file mode 100644 index 0000000000..a2297472c0 Binary files /dev/null and b/stable/.doctrees/api/cassandra/cqlengine/models.doctree differ diff --git a/stable/.doctrees/api/cassandra/cqlengine/query.doctree b/stable/.doctrees/api/cassandra/cqlengine/query.doctree new file mode 100644 index 0000000000..cfddd049e9 Binary files /dev/null and b/stable/.doctrees/api/cassandra/cqlengine/query.doctree differ diff --git a/stable/.doctrees/api/cassandra/cqlengine/usertype.doctree b/stable/.doctrees/api/cassandra/cqlengine/usertype.doctree new file mode 100644 index 0000000000..d87bd3fbce Binary files /dev/null and b/stable/.doctrees/api/cassandra/cqlengine/usertype.doctree differ diff --git a/stable/.doctrees/api/cassandra/datastax/graph/fluent/index.doctree b/stable/.doctrees/api/cassandra/datastax/graph/fluent/index.doctree new file mode 100644 index 0000000000..5132230c72 Binary files /dev/null and b/stable/.doctrees/api/cassandra/datastax/graph/fluent/index.doctree differ diff --git a/stable/.doctrees/api/cassandra/datastax/graph/fluent/predicates.doctree b/stable/.doctrees/api/cassandra/datastax/graph/fluent/predicates.doctree new file mode 100644 index 0000000000..ff3ad8e6db Binary files /dev/null and b/stable/.doctrees/api/cassandra/datastax/graph/fluent/predicates.doctree differ diff --git a/stable/.doctrees/api/cassandra/datastax/graph/fluent/query.doctree b/stable/.doctrees/api/cassandra/datastax/graph/fluent/query.doctree new file mode 100644 index 0000000000..0e89648ef4 Binary files /dev/null and b/stable/.doctrees/api/cassandra/datastax/graph/fluent/query.doctree differ diff --git a/stable/.doctrees/api/cassandra/datastax/graph/index.doctree b/stable/.doctrees/api/cassandra/datastax/graph/index.doctree new file mode 100644 index 0000000000..ee7ad60e72 Binary files /dev/null and b/stable/.doctrees/api/cassandra/datastax/graph/index.doctree differ diff --git a/stable/.doctrees/api/cassandra/decoder.doctree b/stable/.doctrees/api/cassandra/decoder.doctree new file mode 100644 index 0000000000..bc05d8b530 Binary files /dev/null and b/stable/.doctrees/api/cassandra/decoder.doctree differ diff --git a/stable/.doctrees/api/cassandra/encoder.doctree b/stable/.doctrees/api/cassandra/encoder.doctree new file mode 100644 index 0000000000..b7157d3b84 Binary files /dev/null and b/stable/.doctrees/api/cassandra/encoder.doctree differ diff --git a/stable/.doctrees/api/cassandra/graph.doctree b/stable/.doctrees/api/cassandra/graph.doctree new file mode 100644 index 0000000000..02b62fe7ae Binary files /dev/null and b/stable/.doctrees/api/cassandra/graph.doctree differ diff --git a/stable/.doctrees/api/cassandra/io/asyncioreactor.doctree b/stable/.doctrees/api/cassandra/io/asyncioreactor.doctree new file mode 100644 index 0000000000..6c1d5ded7a Binary files /dev/null and b/stable/.doctrees/api/cassandra/io/asyncioreactor.doctree differ diff --git a/stable/.doctrees/api/cassandra/io/asyncorereactor.doctree b/stable/.doctrees/api/cassandra/io/asyncorereactor.doctree new file mode 100644 index 0000000000..a00c8cfa7d Binary files /dev/null and b/stable/.doctrees/api/cassandra/io/asyncorereactor.doctree differ diff --git a/stable/.doctrees/api/cassandra/io/eventletreactor.doctree b/stable/.doctrees/api/cassandra/io/eventletreactor.doctree new file mode 100644 index 0000000000..ff3b7b9ecf Binary files /dev/null and b/stable/.doctrees/api/cassandra/io/eventletreactor.doctree differ diff --git a/stable/.doctrees/api/cassandra/io/geventreactor.doctree b/stable/.doctrees/api/cassandra/io/geventreactor.doctree new file mode 100644 index 0000000000..568203ae54 Binary files /dev/null and b/stable/.doctrees/api/cassandra/io/geventreactor.doctree differ diff --git a/stable/.doctrees/api/cassandra/io/libevreactor.doctree b/stable/.doctrees/api/cassandra/io/libevreactor.doctree new file mode 100644 index 0000000000..bc45531d44 Binary files /dev/null and b/stable/.doctrees/api/cassandra/io/libevreactor.doctree differ diff --git a/stable/.doctrees/api/cassandra/io/twistedreactor.doctree b/stable/.doctrees/api/cassandra/io/twistedreactor.doctree new file mode 100644 index 0000000000..b18af8287d Binary files /dev/null and b/stable/.doctrees/api/cassandra/io/twistedreactor.doctree differ diff --git a/stable/.doctrees/api/cassandra/metadata.doctree b/stable/.doctrees/api/cassandra/metadata.doctree new file mode 100644 index 0000000000..143e87d588 Binary files /dev/null and b/stable/.doctrees/api/cassandra/metadata.doctree differ diff --git a/stable/.doctrees/api/cassandra/metrics.doctree b/stable/.doctrees/api/cassandra/metrics.doctree new file mode 100644 index 0000000000..4e3d0169b1 Binary files /dev/null and b/stable/.doctrees/api/cassandra/metrics.doctree differ diff --git a/stable/.doctrees/api/cassandra/policies.doctree b/stable/.doctrees/api/cassandra/policies.doctree new file mode 100644 index 0000000000..06c33aa472 Binary files /dev/null and b/stable/.doctrees/api/cassandra/policies.doctree differ diff --git a/stable/.doctrees/api/cassandra/pool.doctree b/stable/.doctrees/api/cassandra/pool.doctree new file mode 100644 index 0000000000..1ca8048ddc Binary files /dev/null and b/stable/.doctrees/api/cassandra/pool.doctree differ diff --git a/stable/.doctrees/api/cassandra/protocol.doctree b/stable/.doctrees/api/cassandra/protocol.doctree new file mode 100644 index 0000000000..c3be592ba7 Binary files /dev/null and b/stable/.doctrees/api/cassandra/protocol.doctree differ diff --git a/stable/.doctrees/api/cassandra/query.doctree b/stable/.doctrees/api/cassandra/query.doctree new file mode 100644 index 0000000000..cbc6843a56 Binary files /dev/null and b/stable/.doctrees/api/cassandra/query.doctree differ diff --git a/stable/.doctrees/api/cassandra/timestamps.doctree b/stable/.doctrees/api/cassandra/timestamps.doctree new file mode 100644 index 0000000000..671d88e005 Binary files /dev/null and b/stable/.doctrees/api/cassandra/timestamps.doctree differ diff --git a/stable/.doctrees/api/cassandra/util.doctree b/stable/.doctrees/api/cassandra/util.doctree new file mode 100644 index 0000000000..410c1adf8c Binary files /dev/null and b/stable/.doctrees/api/cassandra/util.doctree differ diff --git a/stable/.doctrees/api/index.doctree b/stable/.doctrees/api/index.doctree new file mode 100644 index 0000000000..cecb227392 Binary files /dev/null and b/stable/.doctrees/api/index.doctree differ diff --git a/stable/.doctrees/cqlengine/batches.doctree b/stable/.doctrees/cqlengine/batches.doctree new file mode 100644 index 0000000000..0f5fff949b Binary files /dev/null and b/stable/.doctrees/cqlengine/batches.doctree differ diff --git a/stable/.doctrees/cqlengine/connections.doctree b/stable/.doctrees/cqlengine/connections.doctree new file mode 100644 index 0000000000..fb04993514 Binary files /dev/null and b/stable/.doctrees/cqlengine/connections.doctree differ diff --git a/stable/.doctrees/cqlengine/faq.doctree b/stable/.doctrees/cqlengine/faq.doctree new file mode 100644 index 0000000000..4dc14023e2 Binary files /dev/null and b/stable/.doctrees/cqlengine/faq.doctree differ diff --git a/stable/.doctrees/cqlengine/models.doctree b/stable/.doctrees/cqlengine/models.doctree new file mode 100644 index 0000000000..fd4f453d9b Binary files /dev/null and b/stable/.doctrees/cqlengine/models.doctree differ diff --git a/stable/.doctrees/cqlengine/queryset.doctree b/stable/.doctrees/cqlengine/queryset.doctree new file mode 100644 index 0000000000..c97bea64ff Binary files /dev/null and b/stable/.doctrees/cqlengine/queryset.doctree differ diff --git a/stable/.doctrees/cqlengine/third-party.doctree b/stable/.doctrees/cqlengine/third-party.doctree new file mode 100644 index 0000000000..7d7e01a930 Binary files /dev/null and b/stable/.doctrees/cqlengine/third-party.doctree differ diff --git a/stable/.doctrees/cqlengine/upgrade-guide.doctree b/stable/.doctrees/cqlengine/upgrade-guide.doctree new file mode 100644 index 0000000000..b2669ecf01 Binary files /dev/null and b/stable/.doctrees/cqlengine/upgrade-guide.doctree differ diff --git a/stable/.doctrees/dates-and-times.doctree b/stable/.doctrees/dates-and-times.doctree new file mode 100644 index 0000000000..586b4615f7 Binary files /dev/null and b/stable/.doctrees/dates-and-times.doctree differ diff --git a/stable/.doctrees/environment.pickle b/stable/.doctrees/environment.pickle new file mode 100644 index 0000000000..85e3dbc0f8 Binary files /dev/null and b/stable/.doctrees/environment.pickle differ diff --git a/stable/.doctrees/execution-profiles.doctree b/stable/.doctrees/execution-profiles.doctree new file mode 100644 index 0000000000..f55d6e09f5 Binary files /dev/null and b/stable/.doctrees/execution-profiles.doctree differ diff --git a/stable/.doctrees/faq.doctree b/stable/.doctrees/faq.doctree new file mode 100644 index 0000000000..7795d9d1f6 Binary files /dev/null and b/stable/.doctrees/faq.doctree differ diff --git a/stable/.doctrees/getting-started.doctree b/stable/.doctrees/getting-started.doctree new file mode 100644 index 0000000000..1f903a41ef Binary files /dev/null and b/stable/.doctrees/getting-started.doctree differ diff --git a/stable/.doctrees/index.doctree b/stable/.doctrees/index.doctree new file mode 100644 index 0000000000..f15f9de0db Binary files /dev/null and b/stable/.doctrees/index.doctree differ diff --git a/stable/.doctrees/installation.doctree b/stable/.doctrees/installation.doctree new file mode 100644 index 0000000000..c11d6b4f22 Binary files /dev/null and b/stable/.doctrees/installation.doctree differ diff --git a/stable/.doctrees/lwt.doctree b/stable/.doctrees/lwt.doctree new file mode 100644 index 0000000000..0825cae638 Binary files /dev/null and b/stable/.doctrees/lwt.doctree differ diff --git a/stable/.doctrees/object-mapper.doctree b/stable/.doctrees/object-mapper.doctree new file mode 100644 index 0000000000..8231ef523d Binary files /dev/null and b/stable/.doctrees/object-mapper.doctree differ diff --git a/stable/.doctrees/performance.doctree b/stable/.doctrees/performance.doctree new file mode 100644 index 0000000000..7ff82a323b Binary files /dev/null and b/stable/.doctrees/performance.doctree differ diff --git a/stable/.doctrees/query-paging.doctree b/stable/.doctrees/query-paging.doctree new file mode 100644 index 0000000000..1b96796b0d Binary files /dev/null and b/stable/.doctrees/query-paging.doctree differ diff --git a/stable/.doctrees/scylla-cloud-serverless.doctree b/stable/.doctrees/scylla-cloud-serverless.doctree new file mode 100644 index 0000000000..323103c0a5 Binary files /dev/null and b/stable/.doctrees/scylla-cloud-serverless.doctree differ diff --git a/stable/.doctrees/scylla-cloud.doctree b/stable/.doctrees/scylla-cloud.doctree new file mode 100644 index 0000000000..c563f04221 Binary files /dev/null and b/stable/.doctrees/scylla-cloud.doctree differ diff --git a/stable/.doctrees/scylla-specific.doctree b/stable/.doctrees/scylla-specific.doctree new file mode 100644 index 0000000000..358639eda0 Binary files /dev/null and b/stable/.doctrees/scylla-specific.doctree differ diff --git a/stable/.doctrees/security.doctree b/stable/.doctrees/security.doctree new file mode 100644 index 0000000000..3024b87af6 Binary files /dev/null and b/stable/.doctrees/security.doctree differ diff --git a/stable/.doctrees/upgrading.doctree b/stable/.doctrees/upgrading.doctree new file mode 100644 index 0000000000..9e84beb1f2 Binary files /dev/null and b/stable/.doctrees/upgrading.doctree differ diff --git a/stable/.doctrees/user-defined-types.doctree b/stable/.doctrees/user-defined-types.doctree new file mode 100644 index 0000000000..903f45bdba Binary files /dev/null and b/stable/.doctrees/user-defined-types.doctree differ diff --git a/stable/.nojekyll b/stable/.nojekyll new file mode 100644 index 0000000000..e69de29bb2 diff --git a/stable/404.html b/stable/404.html new file mode 100644 index 0000000000..d60936cbfe --- /dev/null +++ b/stable/404.html @@ -0,0 +1,31 @@ + + + + + + + + + ScyllaDB + + + + + + + + + + + +
+

404

+

The ScyllaDB monster ate your page!

+

+ Home +

+
+ + + \ No newline at end of file diff --git a/stable/CHANGELOG.html b/stable/CHANGELOG.html new file mode 100644 index 0000000000..c84e597664 --- /dev/null +++ b/stable/CHANGELOG.html @@ -0,0 +1,2957 @@ + + + + + + + + + + + + + CHANGELOG | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + + + +
+ +
+ +
+

CHANGELOG

+
+

3.26.0

+

March 13, 2023

+
+

Features

+
    +
  • Add support for execution profiles in execute_concurrent (PR 1122)

  • +
+
+
+

Bug Fixes

+
    +
  • Handle empty non-final result pages (PR 1110)

  • +
  • Do not re-use stream IDs for in-flight requests (PR 1114)

  • +
  • Asyncore race condition cause logging exception on shutdown (PYTHON-1266)

  • +
+
+
+

Others

+
    +
  • Fix deprecation warning in query tracing (PR 1103)

  • +
  • Remove mutable default values from some tests (PR 1116)

  • +
  • Remove dependency on unittest2 (PYTHON-1289)

  • +
  • Fix deprecation warnings for asyncio.coroutine annotation in asyncioreactor (PYTTHON-1290)

  • +
  • Fix typos in source files (PR 1126)

  • +
  • HostFilterPolicyInitTest fix for Python 3.11 (PR 1131)

  • +
  • Fix for DontPrepareOnIgnoredHostsTest (PYTHON-1287)

  • +
  • tests.integration.simulacron.test_connection failures (PYTHON-1304)

  • +
  • tests.integration.standard.test_single_interface.py appears to be failing for C* 4.0 (PYTHON-1329)

  • +
  • Authentication tests appear to be failing fraudulently (PYTHON-1328)

  • +
  • PreparedStatementTests.test_fail_if_different_query_id_on_reprepare() failing unexpectedly (PTYHON-1327)

  • +
  • Refactor deprecated unittest aliases for Python 3.11 compatibility (PR 1112)

  • +
+
+
+

Deprecations

+
    +
  • This release removes support for Python 2.7.x as well as Python 3.5.x and 3.6.x

  • +
+
+
+
+

3.25.0

+

March 18, 2021

+
+

Features

+
    +
  • Ensure the driver can connect when invalid peer hosts are in system.peers (PYTHON-1260)

  • +
  • Implement protocol v5 checksumming (PYTHON-1258)

  • +
  • Fix the default cqlengine connection mechanism to work with Astra (PYTHON-1265)

  • +
+
+
+

Bug Fixes

+
    +
  • Asyncore race condition cause logging exception on shutdown (PYTHON-1266)

  • +
  • Update list of reserved keywords (PYTHON-1269)

  • +
+
+
+

Others

+
    +
  • Drop Python 3.4 support (PYTHON-1220)

  • +
  • Update security documentation and examples to use PROTOCOL_TLS (PYTHON-1264)

  • +
+
+
+
+

3.24.0

+

June 18, 2020

+
+

Features

+
    +
  • Make geomet an optional dependency at runtime (PYTHON-1237)

  • +
  • Add use_default_tempdir cloud config options (PYTHON-1245)

  • +
  • Tcp flow control for libevreactor (PYTHON-1248)

  • +
+
+
+

Bug Fixes

+
    +
  • Unable to connect to a cloud cluster using Ubuntu 20.04 (PYTHON-1238)

  • +
  • PlainTextAuthProvider fails with unicode chars and Python3 (PYTHON-1241)

  • +
  • [GRAPH] Graph execution profiles consistency level are not set to LOCAL_QUORUM with a cloud cluster (PYTHON-1240)

  • +
  • [GRAPH] Can’t write data in a Boolean field using the Fluent API (PYTHON-1239)

  • +
  • [GRAPH] Fix elementMap() result deserialization (PYTHON-1233)

  • +
+
+
+

Others

+
    +
  • Bump geomet dependency version to 0.2 (PYTHON-1243)

  • +
  • Bump gremlinpython dependency version to 3.4.6 (PYTHON-1212)

  • +
  • Improve fluent graph documentation for core graphs (PYTHON-1244)

  • +
+
+
+
+

3.23.0

+

April 6, 2020

+
+

Features

+
    +
  • Transient Replication Support (PYTHON-1207)

  • +
  • Support system.peers_v2 and port discovery for C* 4.0 (PYTHON-700)

  • +
+
+
+

Bug Fixes

+
    +
  • Asyncore logging exception on shutdown (PYTHON-1228)

  • +
+
+
+
+

3.22.0

+

February 26, 2020

+
+

Features

+
    +
  • Add all() function to the ResultSet API (PYTHON-1203)

  • +
  • Parse new schema metadata in NGDG and generate table edges CQL syntax (PYTHON-996)

  • +
  • Add GraphSON3 support (PYTHON-788)

  • +
  • Use GraphSON3 as default for Native graphs (PYTHON-1004)

  • +
  • Add Tuple and UDT types for native graph (PYTHON-1005)

  • +
  • Add Duration type for native graph (PYTHON-1000)

  • +
  • Add gx:ByteBuffer graphson type support for Blob field (PYTHON-1027)

  • +
  • Enable Paging Through DSE Driver for Gremlin Traversals (PYTHON-1045)

  • +
  • Provide numerical wrappers to ensure proper graphson schema definition (PYTHON-1051)

  • +
  • Resolve the row_factory automatically for native graphs (PYTHON-1056)

  • +
  • Add g:TraversalMetrics/g:Metrics graph deserializers (PYTHON-1057)

  • +
  • Add g:BulkSet graph deserializers (PYTHON-1060)

  • +
  • Update Graph Engine names and the way to create a Classic/Native Graph (PYTHON-1090)

  • +
  • Update Native to Core Graph Engine

  • +
  • Add graphson3 and native graph support (PYTHON-1039)

  • +
  • Enable Paging Through DSE Driver for Gremlin Traversals (PYTHON-1045)

  • +
  • Expose filter predicates for cql collections (PYTHON-1019)

  • +
  • Add g:TraversalMetrics/Metrics deserializers (PYTHON-1057)

  • +
  • Make graph metadata handling more robust (PYTHON-1204)

  • +
+
+
+

Bug Fixes

+
    +
  • Make sure to only query the native_transport_address column with DSE (PYTHON-1205)

  • +
+
+
+
+

3.21.0

+

January 15, 2020

+
+

Features

+
    +
  • Unified driver: merge core and DSE drivers into a single package (PYTHON-1130)

  • +
  • Add Python 3.8 support (PYTHON-1189)

  • +
  • Allow passing ssl context for Twisted (PYTHON-1161)

  • +
  • Ssl context and cloud support for Eventlet (PYTHON-1162)

  • +
  • Cloud Twisted support (PYTHON-1163)

  • +
  • Add additional_write_policy and read_repair to system schema parsing (PYTHON-1048)

  • +
  • Flexible version parsing (PYTHON-1174)

  • +
  • Support NULL in collection deserializer (PYTHON-1123)

  • +
  • [GRAPH] Ability to execute Fluent Graph queries asynchronously (PYTHON-1129)

  • +
+
+
+

Bug Fixes

+
    +
  • Handle prepared id mismatch when repreparing on the fly (PYTHON-1124)

  • +
  • re-raising the CQLEngineException will fail on Python 3 (PYTHON-1166)

  • +
  • asyncio message chunks can be processed discontinuously (PYTHON-1185)

  • +
  • Reconnect attempts persist after downed node removed from peers (PYTHON-1181)

  • +
  • Connection fails to validate ssl certificate hostname when SSLContext.check_hostname is set (PYTHON-1186)

  • +
  • ResponseFuture._set_result crashes on connection error when used with PrepareMessage (PYTHON-1187)

  • +
  • Insights fail to serialize the startup message when the SSL Context is from PyOpenSSL (PYTHON-1192)

  • +
+
+
+

Others

+
    +
  • The driver has a new dependency: geomet. It comes from the dse-driver unification and +is used to support DSE geo types.

  • +
  • Remove *read_repair_chance table options (PYTHON-1140)

  • +
  • Avoid warnings about unspecified load balancing policy when connecting to a cloud cluster (PYTHON-1177)

  • +
  • Add new DSE CQL keywords (PYTHON-1122)

  • +
  • Publish binary wheel distributions (PYTHON-1013)

  • +
+
+
+

Deprecations

+
    +
  • DSELoadBalancingPolicy will be removed in the next major, consider using +the DefaultLoadBalancingPolicy.

  • +
+

Merged from dse-driver:

+
+
+

Features

+
    +
  • Insights integration (PYTHON-1047)

  • +
  • Graph execution profiles should preserve their graph_source when graph_options is overridden (PYTHON-1021)

  • +
  • Add NodeSync metadata (PYTHON-799)

  • +
  • Add new NodeSync failure values (PYTHON-934)

  • +
  • DETERMINISTIC and MONOTONIC Clauses for Functions and Aggregates (PYTHON-955)

  • +
  • GraphOptions should show a warning for unknown parameters (PYTHON-819)

  • +
  • DSE protocol version 2 and continous paging backpressure (PYTHON-798)

  • +
  • GraphSON2 Serialization/Deserialization Support (PYTHON-775)

  • +
  • Add graph-results payload option for GraphSON format (PYTHON-773)

  • +
  • Create an AuthProvider for the DSE transitional mode (PYTHON-831)

  • +
  • Implement serializers for the Graph String API (PYTHON-778)

  • +
  • Provide deserializers for GraphSON types (PYTHON-782)

  • +
  • Add Graph DurationType support (PYTHON-607)

  • +
  • Support DSE DateRange type (PYTHON-668)

  • +
  • RLAC CQL output for materialized views (PYTHON-682)

  • +
  • Add Geom Types wkt deserializer

  • +
  • DSE Graph Client timeouts in custom payload (PYTHON-589)

  • +
  • Make DSEGSSAPIAuthProvider accept principal name (PYTHON-574)

  • +
  • Add config profiles to DSE graph execution (PYTHON-570)

  • +
  • DSE Driver version checking (PYTHON-568)

  • +
  • Distinct default timeout for graph queries (PYTHON-477)

  • +
  • Graph result parsing for known types (PYTHON-479,487)

  • +
  • Distinct read/write CL for graph execution (PYTHON-509)

  • +
  • Target graph analytics query to spark master when available (PYTHON-510)

  • +
+
+
+

Bug Fixes

+
    +
  • Continuous paging sessions raise RuntimeError when results are not entirely consumed (PYTHON-1054)

  • +
  • GraphSON Property deserializer should return a dict instead of a set (PYTHON-1033)

  • +
  • ResponseFuture.has_more_pages may hold the wrong value (PYTHON-946)

  • +
  • DETERMINISTIC clause in AGGREGATE misplaced in CQL generation (PYTHON-963)

  • +
  • graph module import cause a DLL issue on Windows due to its cythonizing failure (PYTHON-900)

  • +
  • Update date serialization to isoformat in graph (PYTHON-805)

  • +
  • DateRange Parse Error (PYTHON-729)

  • +
  • MontonicTimestampGenerator.__init__ ignores class defaults (PYTHON-728)

  • +
  • metadata.get_host returning None unexpectedly (PYTHON-709)

  • +
  • Sockets associated with sessions not getting cleaned up on session.shutdown() (PYTHON-673)

  • +
  • Resolve FQDN from ip address and use that as host passed to SASLClient (PYTHON-566)

  • +
  • Geospatial type implementations don’t handle ‘EMPTY’ values. (PYTHON-481)

  • +
  • Correctly handle other types in geo type equality (PYTHON-508)

  • +
+
+
+

Other

+
    +
  • Add tests around cqlengine and continuous paging (PYTHON-872)

  • +
  • Add an abstract GraphStatement to handle different graph statements (PYTHON-789)

  • +
  • Write documentation examples for DSE 2.0 features (PYTHON-732)

  • +
  • DSE_V1 protocol should not include all of protocol v5 (PYTHON-694)

  • +
+
+
+
+

3.20.2

+

November 19, 2019

+
+

Bug Fixes

+
    +
  • Fix import error for old python installation without SSLContext (PYTHON-1183)

  • +
+
+
+
+

3.20.1

+

November 6, 2019

+
+

Bug Fixes

+
    +
  • ValueError: too many values to unpack (expected 2)” when there are two dashes in server version number (PYTHON-1172)

  • +
+
+
+
+

3.20.0

+

October 28, 2019

+
+

Features

+
    +
  • DataStax Astra Support (PYTHON-1074)

  • +
  • Use 4.0 schema parser in 4 alpha and snapshot builds (PYTHON-1158)

  • +
+
+
+

Bug Fixes

+
    +
  • Connection setup methods prevent using ExecutionProfile in cqlengine (PYTHON-1009)

  • +
  • Driver deadlock if all connections dropped by heartbeat whilst request in flight and request times out (PYTHON-1044)

  • +
  • Exception when use pk__token__gt filter In python 3.7 (PYTHON-1121)

  • +
+
+
+
+

3.19.0

+

August 26, 2019

+
+

Features

+
    +
  • Add Python 3.7 support (PYTHON-1016)

  • +
  • Future-proof Mapping imports (PYTHON-1023)

  • +
  • Include param values in cqlengine logging (PYTHON-1105)

  • +
  • NTS Token Replica Map Generation is slow (PYTHON-622)

  • +
+
+
+

Bug Fixes

+
    +
  • as_cql_query UDF/UDA parameters incorrectly includes “frozen” if arguments are collections (PYTHON-1031)

  • +
  • cqlengine does not currently support combining TTL and TIMESTAMP on INSERT (PYTHON-1093)

  • +
  • Fix incorrect metadata for compact counter tables (PYTHON-1100)

  • +
  • Call ConnectionException with correct kwargs (PYTHON-1117)

  • +
  • Can’t connect to clusters built from source because version parsing doesn’t handle ‘x.y-SNAPSHOT’ (PYTHON-1118)

  • +
  • Discovered node doesn´t honor the configured Cluster port on connection (PYTHON-1127)

  • +
  • Exception when use pk__token__gt filter In python 3.7 (PYTHON-1121)

  • +
+
+
+

Other

+
    +
  • Remove invalid warning in set_session when we initialize a default connection (PYTHON-1104)

  • +
  • Set the proper default ExecutionProfile.row_factory value (PYTHON-1119)

  • +
+
+
+
+

3.18.0

+

May 27, 2019

+
+

Features

+
    +
  • Abstract Host Connection information (PYTHON-1079)

  • +
  • Improve version parsing to support a non-integer 4th component (PYTHON-1091)

  • +
  • Expose on_request_error method in the RetryPolicy (PYTHON-1064)

  • +
  • Add jitter to ExponentialReconnectionPolicy (PYTHON-1065)

  • +
+
+
+

Bug Fixes

+
    +
  • Fix error when preparing queries with beta protocol v5 (PYTHON-1081)

  • +
  • Accept legacy empty strings as column names (PYTHON-1082)

  • +
  • Let util.SortedSet handle uncomparable elements (PYTHON-1087)

  • +
+
+
+
+

3.17.1

+

May 2, 2019

+
+

Bug Fixes

+
    +
  • Socket errors EAGAIN/EWOULDBLOCK are not handled properly and cause timeouts (PYTHON-1089)

  • +
+
+
+
+

3.17.0

+

February 19, 2019

+
+

Features

+
    +
  • Send driver name and version in startup message (PYTHON-1068)

  • +
  • Add Cluster ssl_context option to enable SSL (PYTHON-995)

  • +
  • Allow encrypted private keys for 2-way SSL cluster connections (PYTHON-995)

  • +
  • Introduce new method ConsistencyLevel.is_serial (PYTHON-1067)

  • +
  • Add Session.get_execution_profile (PYTHON-932)

  • +
  • Add host kwarg to Session.execute/execute_async APIs to send a query to a specific node (PYTHON-993)

  • +
+
+
+

Bug Fixes

+
    +
  • NoHostAvailable when all hosts are up and connectable (PYTHON-891)

  • +
  • Serial consistency level is not used (PYTHON-1007)

  • +
+
+
+

Other

+
    +
  • Fail faster on incorrect lz4 import (PYTHON-1042)

  • +
  • Bump Cython dependency version to 0.29 (PYTHON-1036)

  • +
  • Expand Driver SSL Documentation (PYTHON-740)

  • +
+
+
+

Deprecations

+
    +
  • Using Cluster.ssl_options to enable SSL is deprecated and will be removed in +the next major release, use ssl_context.

  • +
  • DowngradingConsistencyRetryPolicy is deprecated and will be +removed in the next major release. (PYTHON-937)

  • +
+
+
+
+

3.16.0

+

November 12, 2018

+
+

Bug Fixes

+
    +
  • Improve and fix socket error-catching code in nonblocking-socket reactors (PYTHON-1024)

  • +
  • Non-ASCII characters in schema break CQL string generation (PYTHON-1008)

  • +
  • Fix OSS driver’s virtual table support against DSE 6.0.X and future server releases (PYTHON-1020)

  • +
  • ResultSet.one() fails if the row_factory is using a generator (PYTHON-1026)

  • +
  • Log profile name on attempt to create existing profile (PYTHON-944)

  • +
  • Cluster instantiation fails if any contact points’ hostname resolution fails (PYTHON-895)

  • +
+
+
+

Other

+
    +
  • Fix tests when RF is not maintained if we decomission a node (PYTHON-1017)

  • +
  • Fix wrong use of ResultSet indexing (PYTHON-1015)

  • +
+
+
+
+

3.15.1

+

September 6, 2018

+
+

Bug Fixes

+
    +
  • C* 4.0 schema-parsing logic breaks running against DSE 6.0.X (PYTHON-1018)

  • +
+
+
+
+

3.15.0

+

August 30, 2018

+
+

Features

+
    +
  • Parse Virtual Keyspace Metadata (PYTHON-992)

  • +
+
+
+

Bug Fixes

+
    +
  • Tokenmap.get_replicas returns the wrong value if token coincides with the end of the range (PYTHON-978)

  • +
  • Python Driver fails with “more than 255 arguments” python exception when > 255 columns specified in query response (PYTHON-893)

  • +
  • Hang in integration.standard.test_cluster.ClusterTests.test_set_keyspace_twice (PYTHON-998)

  • +
  • Asyncore reactors should use a global variable instead of a class variable for the event loop (PYTHON-697)

  • +
+
+
+

Other

+
    +
  • Use global variable for libev loops so it can be subclassed (PYTHON-973)

  • +
  • Update SchemaParser for V4 (PYTHON-1006)

  • +
  • Bump Cython dependency version to 0.28 (PYTHON-1012)

  • +
+
+
+
+

3.14.0

+

April 17, 2018

+
+

Features

+
    +
  • Add one() function to the ResultSet API (PYTHON-947)

  • +
  • Create an utility function to fetch concurrently many keys from the same replica (PYTHON-647)

  • +
  • Allow filter queries with fields that have an index managed outside of cqlengine (PYTHON-966)

  • +
  • Twisted SSL Support (PYTHON-343)

  • +
  • Support IS NOT NULL operator in cqlengine (PYTHON-968)

  • +
+
+
+

Other

+
    +
  • Fix Broken Links in Docs (PYTHON-916)

  • +
  • Reevaluate MONKEY_PATCH_LOOP in test codebase (PYTHON-903)

  • +
  • Remove CASS_SERVER_VERSION and replace it for CASSANDRA_VERSION in tests (PYTHON-910)

  • +
  • Refactor CASSANDRA_VERSION to a some kind of version object (PYTHON-915)

  • +
  • Log warning when driver configures an authenticator, but server does not request authentication (PYTHON-940)

  • +
  • Warn users when using the deprecated Session.default_consistency_level (PYTHON-953)

  • +
  • Add DSE smoke test to OSS driver tests (PYTHON-894)

  • +
  • Document long compilation times and workarounds (PYTHON-868)

  • +
  • Improve error for batch WriteTimeouts (PYTHON-941)

  • +
  • Deprecate ResultSet indexing (PYTHON-945)

  • +
+
+
+
+

3.13.0

+

January 30, 2018

+
+

Features

+
    +
  • cqlengine: LIKE filter operator (PYTHON-512)

  • +
  • Support cassandra.query.BatchType with cqlengine BatchQuery (PYTHON-888)

  • +
+
+
+

Bug Fixes

+
    +
  • AttributeError: ‘NoneType’ object has no attribute ‘add_timer’ (PYTHON-862)

  • +
  • Support retry_policy in PreparedStatement (PYTHON-861)

  • +
  • __del__ method in Session is throwing an exception (PYTHON-813)

  • +
  • LZ4 import issue with recent versions (PYTHON-897)

  • +
  • ResponseFuture._connection can be None when returning request_id (PYTHON-853)

  • +
  • ResultSet.was_applied doesn’t support batch with LWT statements (PYTHON-848)

  • +
+
+
+

Other

+
    +
  • cqlengine: avoid warning when unregistering connection on shutdown (PYTHON-865)

  • +
  • Fix DeprecationWarning of log.warn (PYTHON-846)

  • +
  • Fix example_mapper.py for python3 (PYTHON-860)

  • +
  • Possible deadlock on cassandra.concurrent.execute_concurrent (PYTHON-768)

  • +
  • Add some known deprecated warnings for 4.x (PYTHON-877)

  • +
  • Remove copyright dates from copyright notices (PYTHON-863)

  • +
  • Remove “Experimental” tag from execution profiles documentation (PYTHON-840)

  • +
  • request_timer metrics descriptions are slightly incorrect (PYTHON-885)

  • +
  • Remove “Experimental” tag from cqlengine connections documentation (PYTHON-892)

  • +
  • Set in documentation default consistency for operations is LOCAL_ONE (PYTHON-901)

  • +
+
+
+
+

3.12.0

+

November 6, 2017

+
+

Features

+
    +
  • Send keyspace in QUERY, PREPARE, and BATCH messages (PYTHON-678)

  • +
  • Add IPv4Address/IPv6Address support for inet types (PYTHON-751)

  • +
  • WriteType.CDC and VIEW missing (PYTHON-794)

  • +
  • Warn on Cluster init if contact points are specified but LBP isn’t (legacy mode) (PYTHON-812)

  • +
  • Warn on Cluster init if contact points are specified but LBP isn’t (exection profile mode) (PYTHON-838)

  • +
  • Include hash of result set metadata in prepared stmt id (PYTHON-808)

  • +
  • Add NO_COMPACT startup option (PYTHON-839)

  • +
  • Add new exception type for CDC (PYTHON-837)

  • +
  • Allow 0ms in ConstantSpeculativeExecutionPolicy (PYTHON-836)

  • +
  • Add asyncio reactor (PYTHON-507)

  • +
+
+
+

Bug Fixes

+
    +
  • Both _set_final_exception/result called for the same ResponseFuture (PYTHON-630)

  • +
  • Use of DCAwareRoundRobinPolicy raises NoHostAvailable exception (PYTHON-781)

  • +
  • Not create two sessions by default in CQLEngine (PYTHON-814)

  • +
  • Bug when subclassing AyncoreConnection (PYTHON-827)

  • +
  • Error at cleanup when closing the asyncore connections (PYTHON-829)

  • +
  • Fix sites where sessions can change during iteration (PYTHON-793)

  • +
  • cqlengine: allow min_length=0 for Ascii and Text column types (PYTHON-735)

  • +
  • Rare exception when “sys.exit(0)” after query timeouts (PYTHON-752)

  • +
  • Dont set the session keyspace when preparing statements (PYTHON-843)

  • +
  • Use of DCAwareRoundRobinPolicy raises NoHostAvailable exception (PYTHON-781)

  • +
+
+
+

Other

+
    +
  • Remove DeprecationWarning when using WhiteListRoundRobinPolicy (PYTHON-810)

  • +
  • Bump Cython dependency version to 0.27 (PYTHON-833)

  • +
+
+
+
+

3.11.0

+

July 24, 2017

+
+

Features

+
    +
  • Add idle_heartbeat_timeout cluster option to tune how long to wait for heartbeat responses. (PYTHON-762)

  • +
  • Add HostFilterPolicy (PYTHON-761)

  • +
+
+
+

Bug Fixes

+
    +
  • is_idempotent flag is not propagated from PreparedStatement to BoundStatement (PYTHON-736)

  • +
  • Fix asyncore hang on exit (PYTHON-767)

  • +
  • Driver takes several minutes to remove a bad host from session (PYTHON-762)

  • +
  • Installation doesn’t always fall back to no cython in Windows (PYTHON-763)

  • +
  • Avoid to replace a connection that is supposed to shutdown (PYTHON-772)

  • +
  • request_ids may not be returned to the pool (PYTHON-739)

  • +
  • Fix murmur3 on big-endian systems (PYTHON-653)

  • +
  • Ensure unused connections are closed if a Session is deleted by the GC (PYTHON-774)

  • +
  • Fix .values_list by using db names internally (cqlengine) (PYTHON-785)

  • +
+
+
+

Other

+
    +
  • Bump Cython dependency version to 0.25.2 (PYTHON-754)

  • +
  • Fix DeprecationWarning when using lz4 (PYTHON-769)

  • +
  • Deprecate WhiteListRoundRobinPolicy (PYTHON-759)

  • +
  • Improve upgrade guide for materializing pages (PYTHON-464)

  • +
  • Documentation for time/date specifies timestamp inupt as microseconds (PYTHON-717)

  • +
  • Point to DSA Slack, not IRC, in docs index

  • +
+
+
+
+

3.10.0

+

May 24, 2017

+
+

Features

+
    +
  • Add Duration type to cqlengine (PYTHON-750)

  • +
  • Community PR review: Raise error on primary key update only if its value changed (PYTHON-705)

  • +
  • get_query_trace() contract is ambiguous (PYTHON-196)

  • +
+
+
+

Bug Fixes

+
    +
  • Queries using speculative execution policy timeout prematurely (PYTHON-755)

  • +
  • Fix map where results are not consumed (PYTHON-749)

  • +
  • Driver fails to encode Duration’s with large values (PYTHON-747)

  • +
  • UDT values are not updated correctly in CQLEngine (PYTHON-743)

  • +
  • UDT types are not validated in CQLEngine (PYTHON-742)

  • +
  • to_python is not implemented for types columns.Type and columns.Date in CQLEngine (PYTHON-741)

  • +
  • Clients spin infinitely trying to connect to a host that is drained (PYTHON-734)

  • +
  • Resulset.get_query_trace returns empty trace sometimes (PYTHON-730)

  • +
  • Memory grows and doesn’t get removed (PYTHON-720)

  • +
  • Fix RuntimeError caused by change dict size during iteration (PYTHON-708)

  • +
  • fix ExponentialReconnectionPolicy may throw OverflowError problem (PYTHON-707)

  • +
  • Avoid using nonexistent prepared statement in ResponseFuture (PYTHON-706)

  • +
+
+
+

Other

+
    +
  • Update README (PYTHON-746)

  • +
  • Test python versions 3.5 and 3.6 (PYTHON-737)

  • +
  • Docs Warning About Prepare select * (PYTHON-626)

  • +
  • Increase Coverage in CqlEngine Test Suite (PYTHON-505)

  • +
  • Example SSL connection code does not verify server certificates (PYTHON-469)

  • +
+
+
+
+

3.9.0

+
+

Features

+
    +
  • cqlengine: remove elements by key from a map (PYTHON-688)

  • +
+
+
+

Bug Fixes

+
    +
  • improve error handling when connecting to non-existent keyspace (PYTHON-665)

  • +
  • Sockets associated with sessions not getting cleaned up on session.shutdown() (PYTHON-673)

  • +
  • rare flake on integration.standard.test_cluster.ClusterTests.test_clone_shared_lbp (PYTHON-727)

  • +
  • MontonicTimestampGenerator.__init__ ignores class defaults (PYTHON-728)

  • +
  • race where callback or errback for request may not be called (PYTHON-733)

  • +
  • cqlengine: model.update() should not update columns with a default value that hasn’t changed (PYTHON-657)

  • +
  • cqlengine: field value manager’s explicit flag is True when queried back from cassandra (PYTHON-719)

  • +
+
+
+

Other

+
    +
  • Connection not closed in example_mapper (PYTHON-723)

  • +
  • Remove mention of pre-2.0 C* versions from OSS 3.0+ docs (PYTHON-710)

  • +
+
+
+
+

3.8.1

+

March 16, 2017

+
+

Bug Fixes

+
    +
  • implement __le__/__ge__/__ne__ on some custom types (PYTHON-714)

  • +
  • Fix bug in eventlet and gevent reactors that could cause hangs (PYTHON-721)

  • +
  • Fix DecimalType regression (PYTHON-724)

  • +
+
+
+
+

3.8.0

+
+

Features

+
    +
  • Quote index names in metadata CQL generation (PYTHON-616)

  • +
  • On column deserialization failure, keep error message consistent between python and cython (PYTHON-631)

  • +
  • TokenAwarePolicy always sends requests to the same replica for a given key (PYTHON-643)

  • +
  • Added cql types to result set (PYTHON-648)

  • +
  • Add __len__ to BatchStatement (PYTHON-650)

  • +
  • Duration Type for Cassandra (PYTHON-655)

  • +
  • Send flags with PREPARE message in v5 (PYTHON-684)

  • +
+
+
+

Bug Fixes

+
    +
  • Potential Timing issue if application exits prior to session pool initialization (PYTHON-636)

  • +
  • “Host X.X.X.X has been marked down” without any exceptions (PYTHON-640)

  • +
  • NoHostAvailable or OperationTimedOut when using execute_concurrent with a generator that inserts into more than one table (PYTHON-642)

  • +
  • ResponseFuture creates Timers and don’t cancel them even when result is received which leads to memory leaks (PYTHON-644)

  • +
  • Driver cannot connect to Cassandra version > 3 (PYTHON-646)

  • +
  • Unable to import model using UserType without setuping connection since 3.7 (PYTHON-649)

  • +
  • Don’t prepare queries on ignored hosts on_up (PYTHON-669)

  • +
  • Sockets associated with sessions not getting cleaned up on session.shutdown() (PYTHON-673)

  • +
  • Make client timestamps strictly monotonic (PYTHON-676)

  • +
  • cassandra.cqlengine.connection.register_connection broken when hosts=None (PYTHON-692)

  • +
+
+
+

Other

+
    +
  • Create a cqlengine doc section explaining None semantics (PYTHON-623)

  • +
  • Resolve warnings in documentation generation (PYTHON-645)

  • +
  • Cython dependency (PYTHON-686)

  • +
  • Drop Support for Python 2.6 (PYTHON-690)

  • +
+
+
+
+

3.7.1

+

October 26, 2016

+
+

Bug Fixes

+
    +
  • Cython upgrade has broken stable version of cassandra-driver (PYTHON-656)

  • +
+
+
+
+

3.7.0

+

September 13, 2016

+
+

Features

+
    +
  • Add v5 protocol failure map (PYTHON-619)

  • +
  • Don’t return from initial connect on first error (PYTHON-617)

  • +
  • Indicate failed column when deserialization fails (PYTHON-361)

  • +
  • Let Cluster.refresh_nodes force a token map rebuild (PYTHON-349)

  • +
  • Refresh UDTs after “keyspace updated” event with v1/v2 protocol (PYTHON-106)

  • +
  • EC2 Address Resolver (PYTHON-198)

  • +
  • Speculative query retries (PYTHON-218)

  • +
  • Expose paging state in API (PYTHON-200)

  • +
  • Don’t mark host down while one connection is active (PYTHON-498)

  • +
  • Query request size information (PYTHON-284)

  • +
  • Avoid quadratic ring processing with invalid replication factors (PYTHON-379)

  • +
  • Improve Connection/Pool creation concurrency on startup (PYTHON-82)

  • +
  • Add beta version native protocol flag (PYTHON-614)

  • +
  • cqlengine: Connections: support of multiple keyspaces and sessions (PYTHON-613)

  • +
+
+
+

Bug Fixes

+
    +
  • Race when adding a pool while setting keyspace (PYTHON-628)

  • +
  • Update results_metadata when prepared statement is reprepared (PYTHON-621)

  • +
  • CQL Export for Thrift Tables (PYTHON-213)

  • +
  • cqlengine: default value not applied to UserDefinedType (PYTHON-606)

  • +
  • cqlengine: columns are no longer hashable (PYTHON-618)

  • +
  • cqlengine: remove clustering keys from where clause when deleting only static columns (PYTHON-608)

  • +
+
+
+
+

3.6.0

+

August 1, 2016

+
+

Features

+
    +
  • Handle null values in NumpyProtocolHandler (PYTHON-553)

  • +
  • Collect greplin scales stats per cluster (PYTHON-561)

  • +
  • Update mock unit test dependency requirement (PYTHON-591)

  • +
  • Handle Missing CompositeType metadata following C* upgrade (PYTHON-562)

  • +
  • Improve Host.is_up state for HostDistance.IGNORED hosts (PYTHON-551)

  • +
  • Utilize v2 protocol’s ability to skip result set metadata for prepared statement execution (PYTHON-71)

  • +
  • Return from Cluster.connect() when first contact point connection(pool) is opened (PYTHON-105)

  • +
  • cqlengine: Add ContextQuery to allow cqlengine models to switch the keyspace context easily (PYTHON-598)

  • +
  • Standardize Validation between Ascii and Text types in Cqlengine (PYTHON-609)

  • +
+
+
+

Bug Fixes

+
    +
  • Fix geventreactor with SSL support (PYTHON-600)

  • +
  • Don’t downgrade protocol version if explicitly set (PYTHON-537)

  • +
  • Nonexistent contact point tries to connect indefinitely (PYTHON-549)

  • +
  • Execute_concurrent can exceed max recursion depth in failure mode (PYTHON-585)

  • +
  • Libev loop shutdown race (PYTHON-578)

  • +
  • Include aliases in DCT type string (PYTHON-579)

  • +
  • cqlengine: Comparison operators for Columns (PYTHON-595)

  • +
  • cqlengine: disentangle default_time_to_live table option from model query default TTL (PYTHON-538)

  • +
  • cqlengine: pk__token column name issue with the equality operator (PYTHON-584)

  • +
  • cqlengine: Fix “__in” filtering operator converts True to string “True” automatically (PYTHON-596)

  • +
  • cqlengine: Avoid LWTExceptions when updating columns that are part of the condition (PYTHON-580)

  • +
  • cqlengine: Cannot execute a query when the filter contains all columns (PYTHON-599)

  • +
  • cqlengine: routing key computation issue when a primary key column is overriden by model inheritance (PYTHON-576)

  • +
+
+
+
+

3.5.0

+

June 27, 2016

+
+

Features

+
    +
  • Optional Execution Profiles for the core driver (PYTHON-569)

  • +
  • API to get the host metadata associated with the control connection node (PYTHON-583)

  • +
  • Expose CDC option in table metadata CQL (PYTHON-593)

  • +
+
+
+

Bug Fixes

+
    +
  • Clean up Asyncore socket map when fork is detected (PYTHON-577)

  • +
  • cqlengine: QuerySet only() is not respected when there are deferred fields (PYTHON-560)

  • +
+
+
+
+

3.4.1

+

May 26, 2016

+
+

Bug Fixes

+
    +
  • Gevent connection closes on IO timeout (PYTHON-573)

  • +
  • “dictionary changed size during iteration” with Python 3 (PYTHON-572)

  • +
+
+
+
+

3.4.0

+

May 24, 2016

+
+

Features

+
    +
  • Include DSE version and workload in Host data (PYTHON-555)

  • +
  • Add a context manager to Cluster and Session (PYTHON-521)

  • +
  • Better Error Message for Unsupported Protocol Version (PYTHON-157)

  • +
  • Make the error message explicitly state when an error comes from the server (PYTHON-412)

  • +
  • Short Circuit meta refresh on topo change if NEW_NODE already exists (PYTHON-557)

  • +
  • Show warning when the wrong config is passed to SimpleStatement (PYTHON-219)

  • +
  • Return namedtuple result pairs from execute_concurrent (PYTHON-362)

  • +
  • BatchStatement should enforce batch size limit in a better way (PYTHON-151)

  • +
  • Validate min/max request thresholds for connection pool scaling (PYTHON-220)

  • +
  • Handle or warn about multiple hosts with the same rpc_address (PYTHON-365)

  • +
  • Write docs around working with datetime and timezones (PYTHON-394)

  • +
+
+
+

Bug Fixes

+
    +
  • High CPU utilization when using asyncore event loop (PYTHON-239)

  • +
  • Fix CQL Export for non-ASCII Identifiers (PYTHON-447)

  • +
  • Make stress scripts Python 2.6 compatible (PYTHON-434)

  • +
  • UnicodeDecodeError when unicode characters in key in BOP (PYTHON-559)

  • +
  • WhiteListRoundRobinPolicy should resolve hosts (PYTHON-565)

  • +
  • Cluster and Session do not GC after leaving scope (PYTHON-135)

  • +
  • Don’t wait for schema agreement on ignored nodes (PYTHON-531)

  • +
  • Reprepare on_up with many clients causes node overload (PYTHON-556)

  • +
  • None inserted into host map when control connection node is decommissioned (PYTHON-548)

  • +
  • weakref.ref does not accept keyword arguments (github #585)

  • +
+
+
+
+

3.3.0

+

May 2, 2016

+
+

Features

+
    +
  • Add an AddressTranslator interface (PYTHON-69)

  • +
  • New Retry Policy Decision - try next host (PYTHON-285)

  • +
  • Don’t mark host down on timeout (PYTHON-286)

  • +
  • SSL hostname verification (PYTHON-296)

  • +
  • Add C* version to metadata or cluster objects (PYTHON-301)

  • +
  • Options to Disable Schema, Token Metadata Processing (PYTHON-327)

  • +
  • Expose listen_address of node we get ring information from (PYTHON-332)

  • +
  • Use A-record with multiple IPs for contact points (PYTHON-415)

  • +
  • Custom consistency level for populating query traces (PYTHON-435)

  • +
  • Normalize Server Exception Types (PYTHON-443)

  • +
  • Propagate exception message when DDL schema agreement fails (PYTHON-444)

  • +
  • Specialized exceptions for metadata refresh methods failure (PYTHON-527)

  • +
+
+
+

Bug Fixes

+
    +
  • Resolve contact point hostnames to avoid duplicate hosts (PYTHON-103)

  • +
  • GeventConnection stalls requests when read is a multiple of the input buffer size (PYTHON-429)

  • +
  • named_tuple_factory breaks with duplicate “cleaned” col names (PYTHON-467)

  • +
  • Connection leak if Cluster.shutdown() happens during reconnection (PYTHON-482)

  • +
  • HostConnection.borrow_connection does not block when all request ids are used (PYTHON-514)

  • +
  • Empty field not being handled by the NumpyProtocolHandler (PYTHON-550)

  • +
+
+
+
+

3.2.2

+

April 19, 2016

+
    +
  • Fix counter save-after-no-update (PYTHON-547)

  • +
+
+
+

3.2.1

+

April 13, 2016

+
    +
  • Introduced an update to allow deserializer compilation with recently released Cython 0.24 (PYTHON-542)

  • +
+
+
+

3.2.0

+

April 12, 2016

+
+

Features

+
    +
  • cqlengine: Warn on sync_schema type mismatch (PYTHON-260)

  • +
  • cqlengine: Automatically defer fields with the ‘=’ operator (and immutable values) in select queries (PYTHON-520)

  • +
  • cqlengine: support non-equal conditions for LWT (PYTHON-528)

  • +
  • cqlengine: sync_table should validate the primary key composition (PYTHON-532)

  • +
  • cqlengine: token-aware routing for mapper statements (PYTHON-535)

  • +
+
+
+

Bug Fixes

+
    +
  • Deleting a column in a lightweight transaction raises a SyntaxException #325 (PYTHON-249)

  • +
  • cqlengine: make Token function works with named tables/columns #86 (PYTHON-272)

  • +
  • comparing models with datetime fields fail #79 (PYTHON-273)

  • +
  • cython date deserializer integer math should be aligned with CPython (PYTHON-480)

  • +
  • db_field is not always respected with UpdateStatement (PYTHON-530)

  • +
  • Sync_table fails on column.Set with secondary index (PYTHON-533)

  • +
+
+
+
+

3.1.1

+

March 14, 2016

+
+

Bug Fixes

+
    +
  • cqlengine: Fix performance issue related to additional “COUNT” queries (PYTHON-522)

  • +
+
+
+
+

3.1.0

+

March 10, 2016

+
+

Features

+
    +
  • Pass name of server auth class to AuthProvider (PYTHON-454)

  • +
  • Surface schema agreed flag for DDL statements (PYTHON-458)

  • +
  • Automatically convert float and int to Decimal on serialization (PYTHON-468)

  • +
  • Eventlet Reactor IO improvement (PYTHON-495)

  • +
  • Make pure Python ProtocolHandler available even when Cython is present (PYTHON-501)

  • +
  • Optional Cython deserializer for bytes as bytearray (PYTHON-503)

  • +
  • Add Session.default_serial_consistency_level (github #510)

  • +
  • cqlengine: Expose prior state information via cqlengine LWTException (github #343, PYTHON-336)

  • +
  • cqlengine: Collection datatype “contains” operators support (Cassandra 2.1) #278 (PYTHON-258)

  • +
  • cqlengine: Add DISTINCT query operator (PYTHON-266)

  • +
  • cqlengine: Tuple cqlengine api (PYTHON-306)

  • +
  • cqlengine: Add support for UPDATE/DELETE … IF EXISTS statements (PYTHON-432)

  • +
  • cqlengine: Allow nested container types (PYTHON-478)

  • +
  • cqlengine: Add ability to set query’s fetch_size and limit (PYTHON-323)

  • +
  • cqlengine: Internalize default keyspace from successive set_session (PYTHON-486)

  • +
  • cqlengine: Warn when Model.create() on Counters (to be deprecated) (PYTHON-333)

  • +
+
+
+

Bug Fixes

+
    +
  • Bus error (alignment issues) when running cython on some ARM platforms (PYTHON-450)

  • +
  • Overflow when decoding large collections (cython) (PYTHON-459)

  • +
  • Timer heap comparison issue with Python 3 (github #466)

  • +
  • Cython deserializer date overflow at 2^31 - 1 (PYTHON-452)

  • +
  • Decode error encountered when cython deserializing large map results (PYTHON-459)

  • +
  • Don’t require Cython for build if compiler or Python header not present (PYTHON-471)

  • +
  • Unorderable types in task scheduling with Python 3 (h(PYTHON-473)

  • +
  • cqlengine: Fix crash when updating a UDT column with a None value (github #467)

  • +
  • cqlengine: Race condition in ..connection.execute with lazy_connect (PYTHON-310)

  • +
  • cqlengine: doesn’t support case sensitive column family names (PYTHON-337)

  • +
  • cqlengine: UserDefinedType mandatory in create or update (PYTHON-344)

  • +
  • cqlengine: db_field breaks UserType (PYTHON-346)

  • +
  • cqlengine: UDT badly quoted (PYTHON-347)

  • +
  • cqlengine: Use of db_field on primary key prevents querying except while tracing. (PYTHON-351)

  • +
  • cqlengine: DateType.deserialize being called with one argument vs two (PYTHON-354)

  • +
  • cqlengine: Querying without setting up connection now throws AttributeError and not CQLEngineException (PYTHON-395)

  • +
  • cqlengine: BatchQuery multiple time executing execute statements. (PYTHON-445)

  • +
  • cqlengine: Better error for management functions when no connection set (PYTHON-451)

  • +
  • cqlengine: Handle None values for UDT attributes in cqlengine (PYTHON-470)

  • +
  • cqlengine: Fix inserting None for model save (PYTHON-475)

  • +
  • cqlengine: EQ doesn’t map to a QueryOperator (setup race condition) (PYTHON-476)

  • +
  • cqlengine: class.MultipleObjectsReturned has DoesNotExist as base class (PYTHON-489)

  • +
  • cqlengine: Typo in cqlengine UserType __len__ breaks attribute assignment (PYTHON-502)

  • +
+
+
+

Other

+
    +
  • cqlengine: a major improvement on queryset has been introduced. It +is a lot more efficient to iterate large datasets: the rows are +now fetched on demand using the driver pagination.

  • +
  • cqlengine: the queryset len() and count() behaviors have changed. It +now executes a “SELECT COUNT(*)” of the query rather than returning +the size of the internal result_cache (loaded rows). On large +queryset, you might want to avoid using them due to the performance +cost. Note that trying to access objects using list index/slicing +with negative indices also requires a count to be +executed.

  • +
+
+
+
+

3.0.0

+

November 24, 2015

+
+

Features

+
    +
  • Support datetime.date objects as a DateType (PYTHON-212)

  • +
  • Add Cluster.update_view_metadata (PYTHON-407)

  • +
  • QueryTrace option to populate partial trace sessions (PYTHON-438)

  • +
  • Attach column names to ResultSet (PYTHON-439)

  • +
  • Change default consistency level to LOCAL_ONE

  • +
+
+
+

Bug Fixes

+
    +
  • Properly SerDes nested collections when protocol_version < 3 (PYTHON-215)

  • +
  • Evict UDTs from UserType cache on change (PYTHON-226)

  • +
  • Make sure query strings are always encoded UTF-8 (PYTHON-334)

  • +
  • Track previous value of columns at instantiation in CQLengine (PYTHON-348)

  • +
  • UDT CQL encoding does not work for unicode values (PYTHON-353)

  • +
  • NetworkTopologyStrategy#make_token_replica_map does not account for multiple racks in a DC (PYTHON-378)

  • +
  • Cython integer overflow on decimal type deserialization (PYTHON-433)

  • +
  • Query trace: if session hasn’t been logged, query trace can throw exception (PYTHON-442)

  • +
+
+
+
+

3.0.0rc1

+

November 9, 2015

+
+

Features

+
    +
  • Process Modernized Schema Tables for Cassandra 3.0 (PYTHON-276, PYTHON-408, PYTHON-400, PYTHON-422)

  • +
  • Remove deprecated features (PYTHON-292)

  • +
  • Don’t assign trace data to Statements (PYTHON-318)

  • +
  • Normalize results return (PYTHON-368)

  • +
  • Process Materialized View Metadata/Events (PYTHON-371)

  • +
  • Remove blist as soft dependency (PYTHON-385)

  • +
  • Change default consistency level to LOCAL_QUORUM (PYTHON-416)

  • +
  • Normalize CQL query/export in metadata model (PYTHON-405)

  • +
+
+
+

Bug Fixes

+
    +
  • Implementation of named arguments bind is non-pythonic (PYTHON-178)

  • +
  • CQL encoding is incorrect for NaN and Infinity floats (PYTHON-282)

  • +
  • Protocol downgrade issue with C* 2.0.x, 2.1.x, and python3, with non-default logging (PYTHON-409)

  • +
  • ValueError when accessing usertype with non-alphanumeric field names (PYTHON-413)

  • +
  • NumpyProtocolHandler does not play well with PagedResult (PYTHON-430)

  • +
+
+
+
+

2.7.2

+

September 14, 2015

+
+

Bug Fixes

+
    +
  • Resolve CQL export error for UDF with zero parameters (PYTHON-392)

  • +
  • Remove futures dep. for Python 3 (PYTHON-393)

  • +
  • Avoid Python closure in cdef (supports earlier Cython compiler) (PYTHON-396)

  • +
  • Unit test runtime issues (PYTHON-397,398)

  • +
+
+
+
+

2.7.1

+

August 25, 2015

+
+

Bug Fixes

+
    +
  • Explicitly include extension source files in Manifest

  • +
+
+
+
+

2.7.0

+

August 25, 2015

+

Cython is introduced, providing compiled extensions for core modules, and +extensions for optimized results deserialization.

+
+

Features

+
    +
  • General Performance Improvements for Throughput (PYTHON-283)

  • +
  • Improve synchronous request performance with Timers (PYTHON-108)

  • +
  • Enable C Extensions for PyPy Runtime (PYTHON-357)

  • +
  • Refactor SerDes functionality for pluggable interface (PYTHON-313)

  • +
  • Cython SerDes Extension (PYTHON-377)

  • +
  • Accept iterators/generators for execute_concurrent() (PYTHON-123)

  • +
  • cythonize existing modules (PYTHON-342)

  • +
  • Pure Python murmur3 implementation (PYTHON-363)

  • +
  • Make driver tolerant of inconsistent metadata (PYTHON-370)

  • +
+
+
+

Bug Fixes

+
    +
  • Drop Events out-of-order Cause KeyError on Processing (PYTHON-358)

  • +
  • DowngradingConsistencyRetryPolicy doesn’t check response count on write timeouts (PYTHON-338)

  • +
  • Blocking connect does not use connect_timeout (PYTHON-381)

  • +
  • Properly protect partition key in CQL export (PYTHON-375)

  • +
  • Trigger error callbacks on timeout (PYTHON-294)

  • +
+
+
+
+

2.6.0

+

July 20, 2015

+
+

Bug Fixes

+
    +
  • Output proper CQL for compact tables with no clustering columns (PYTHON-360)

  • +
+
+
+
+

2.6.0c2

+

June 24, 2015

+
+

Features

+
    +
  • Automatic Protocol Version Downgrade (PYTHON-240)

  • +
  • cqlengine Python 2.6 compatibility (PYTHON-288)

  • +
  • Double-dollar string quote UDF body (PYTHON-345)

  • +
  • Set models.DEFAULT_KEYSPACE when calling set_session (github #352)

  • +
+
+
+

Bug Fixes

+
    +
  • Avoid stall while connecting to mixed version cluster (PYTHON-303)

  • +
  • Make SSL work with AsyncoreConnection in python 2.6.9 (PYTHON-322)

  • +
  • Fix Murmur3Token.from_key() on Windows (PYTHON-331)

  • +
  • Fix cqlengine TimeUUID rounding error for Windows (PYTHON-341)

  • +
  • Avoid invalid compaction options in CQL export for non-SizeTiered (PYTHON-352)

  • +
+
+
+
+

2.6.0c1

+

June 4, 2015

+

This release adds support for Cassandra 2.2 features, including version +4 of the native protocol.

+
+

Features

+
    +
  • Default load balancing policy to TokenAware(DCAware) (PYTHON-160)

  • +
  • Configuration option for connection timeout (PYTHON-206)

  • +
  • Support User Defined Function and Aggregate metadata in C* 2.2 (PYTHON-211)

  • +
  • Surface request client in QueryTrace for C* 2.2+ (PYTHON-235)

  • +
  • Implement new request failure messages in protocol v4+ (PYTHON-238)

  • +
  • Metadata model now maps index meta by index name (PYTHON-241)

  • +
  • Support new types in C* 2.2: date, time, smallint, tinyint (PYTHON-245, 295)

  • +
  • cqle: add Double column type and remove Float overload (PYTHON-246)

  • +
  • Use partition key column information in prepared response for protocol v4+ (PYTHON-277)

  • +
  • Support message custom payloads in protocol v4+ (PYTHON-280, PYTHON-329)

  • +
  • Deprecate refresh_schema and replace with functions for specific entities (PYTHON-291)

  • +
  • Save trace id even when trace complete times out (PYTHON-302)

  • +
  • Warn when registering client UDT class for protocol < v3 (PYTHON-305)

  • +
  • Support client warnings returned with messages in protocol v4+ (PYTHON-315)

  • +
  • Ability to distinguish between NULL and UNSET values in protocol v4+ (PYTHON-317)

  • +
  • Expose CQL keywords in API (PYTHON-324)

  • +
+
+
+

Bug Fixes

+
    +
  • IPv6 address support on Windows (PYTHON-20)

  • +
  • Convert exceptions during automatic re-preparation to nice exceptions (PYTHON-207)

  • +
  • cqle: Quote keywords properly in table management functions (PYTHON-244)

  • +
  • Don’t default to GeventConnection when gevent is loaded, but not monkey-patched (PYTHON-289)

  • +
  • Pass dynamic host from SaslAuthProvider to SaslAuthenticator (PYTHON-300)

  • +
  • Make protocol read_inet work for Windows (PYTHON-309)

  • +
  • cqle: Correct encoding for nested types (PYTHON-311)

  • +
  • Update list of CQL keywords used quoting identifiers (PYTHON-319)

  • +
  • Make ConstantReconnectionPolicy work with infinite retries (github #327, PYTHON-325)

  • +
  • Accept UUIDs with uppercase hex as valid in cqlengine (github #335)

  • +
+
+
+
+

2.5.1

+

April 23, 2015

+
+

Bug Fixes

+
    +
  • Fix thread safety in DC-aware load balancing policy (PYTHON-297)

  • +
  • Fix race condition in node/token rebuild (PYTHON-298)

  • +
  • Set and send serial consistency parameter (PYTHON-299)

  • +
+
+
+
+

2.5.0

+

March 30, 2015

+
+

Features

+
    +
  • Integrated cqlengine object mapping package

  • +
  • Utility functions for converting timeuuids and datetime (PYTHON-99)

  • +
  • Schema metadata fetch window randomized, config options added (PYTHON-202)

  • +
  • Support for new Date and Time Cassandra types (PYTHON-190)

  • +
+
+
+

Bug Fixes

+
    +
  • Fix index target for collection indexes (full(), keys()) (PYTHON-222)

  • +
  • Thread exception during GIL cleanup (PYTHON-229)

  • +
  • Workaround for rounding anomaly in datetime.utcfromtime (Python 3.4) (PYTHON-230)

  • +
  • Normalize text serialization for lookup in OrderedMap (PYTHON-231)

  • +
  • Support reading CompositeType data (PYTHON-234)

  • +
  • Preserve float precision in CQL encoding (PYTHON-243)

  • +
+
+
+
+

2.1.4

+

January 26, 2015

+
+

Features

+
    +
  • SaslAuthenticator for Kerberos support (PYTHON-109)

  • +
  • Heartbeat for network device keepalive and detecting failures on idle connections (PYTHON-197)

  • +
  • Support nested, frozen collections for Cassandra 2.1.3+ (PYTHON-186)

  • +
  • Schema agreement wait bypass config, new call for synchronous schema refresh (PYTHON-205)

  • +
  • Add eventlet connection support (PYTHON-194)

  • +
+
+
+

Bug Fixes

+
    +
  • Schema meta fix for complex thrift tables (PYTHON-191)

  • +
  • Support for ‘unknown’ replica placement strategies in schema meta (PYTHON-192)

  • +
  • Resolve stream ID leak on set_keyspace (PYTHON-195)

  • +
  • Remove implicit timestamp scaling on serialization of numeric timestamps (PYTHON-204)

  • +
  • Resolve stream id collision when using SASL auth (PYTHON-210)

  • +
  • Correct unhexlify usage for user defined type meta in Python3 (PYTHON-208)

  • +
+
+
+
+

2.1.3

+

December 16, 2014

+
+

Features

+
    +
  • INFO-level log confirmation that a connection was opened to a node that was marked up (PYTHON-116)

  • +
  • Avoid connecting to peer with incomplete metadata (PYTHON-163)

  • +
  • Add SSL support to gevent reactor (PYTHON-174)

  • +
  • Use control connection timeout in wait for schema agreement (PYTHON-175)

  • +
  • Better consistency level representation in unavailable+timeout exceptions (PYTHON-180)

  • +
  • Update schema metadata processing to accommodate coming schema modernization (PYTHON-185)

  • +
+
+
+

Bug Fixes

+
    +
  • Support large negative timestamps on Windows (PYTHON-119)

  • +
  • Fix schema agreement for clusters with peer rpc_addres 0.0.0.0 (PYTHON-166)

  • +
  • Retain table metadata following keyspace meta refresh (PYTHON-173)

  • +
  • Use a timeout when preparing a statement for all nodes (PYTHON-179)

  • +
  • Make TokenAware routing tolerant of statements with no keyspace (PYTHON-181)

  • +
  • Update add_collback to store/invoke multiple callbacks (PYTHON-182)

  • +
  • Correct routing key encoding for composite keys (PYTHON-184)

  • +
  • Include compression option in schema export string when disabled (PYTHON-187)

  • +
+
+
+
+

2.1.2

+

October 16, 2014

+
+

Features

+
    +
  • Allow DCAwareRoundRobinPolicy to be constructed without a local_dc, defaulting +instead to the DC of a contact_point (PYTHON-126)

  • +
  • Set routing key in BatchStatement.add() if none specified in batch (PYTHON-148)

  • +
  • Improved feedback on ValueError using named_tuple_factory with invalid column names (PYTHON-122)

  • +
+
+
+

Bug Fixes

+
    +
  • Make execute_concurrent compatible with Python 2.6 (PYTHON-159)

  • +
  • Handle Unauthorized message on schema_triggers query (PYTHON-155)

  • +
  • Pure Python sorted set in support of UDTs nested in collections (PYTON-167)

  • +
  • Support CUSTOM index metadata and string export (PYTHON-165)

  • +
+
+
+
+

2.1.1

+

September 11, 2014

+
+

Features

+
    +
  • Detect triggers and include them in CQL queries generated to recreate +the schema (github-189)

  • +
  • Support IPv6 addresses (PYTHON-144) (note: basic functionality added; Windows +platform not addressed (PYTHON-20))

  • +
+
+
+

Bug Fixes

+
    +
  • Fix NetworkTopologyStrategy.export_for_schema (PYTHON-120)

  • +
  • Keep timeout for paged results (PYTHON-150)

  • +
+
+
+

Other

+
    +
  • Add frozen<> type modifier to UDTs and tuples to handle CASSANDRA-7857

  • +
+
+
+
+

2.1.0

+

August 7, 2014

+
+

Bug Fixes

+
    +
  • Correctly serialize and deserialize null values in tuples and +user-defined types (PYTHON-110)

  • +
  • Include additional header and lib dirs, allowing libevwrapper to build +against Homebrew and Mac Ports installs of libev (PYTHON-112 and 804dea3)

  • +
+
+
+
+

2.1.0c1

+

July 25, 2014

+
+

Bug Fixes

+
    +
  • Properly specify UDTs for columns in CREATE TABLE statements

  • +
  • Avoid moving retries to a new host when using request ID zero (PYTHON-88)

  • +
  • Don’t ignore fetch_size arguments to Statement constructors (github-151)

  • +
  • Allow disabling automatic paging on a per-statement basis when it’s +enabled by default for the session (PYTHON-93)

  • +
  • Raise ValueError when tuple query parameters for prepared statements +have extra items (PYTHON-98)

  • +
  • Correctly encode nested tuples and UDTs for non-prepared statements (PYTHON-100)

  • +
  • Raise TypeError when a string is used for contact_points (github #164)

  • +
  • Include User Defined Types in KeyspaceMetadata.export_as_string() (PYTHON-96)

  • +
+
+
+

Other

+
    +
  • Return list collection columns as python lists instead of tuples +now that tuples are a specific Cassandra type

  • +
+
+
+
+

2.1.0b1

+

July 11, 2014

+

This release adds support for Cassandra 2.1 features, including version +3 of the native protocol.

+
+

Features

+
    +
  • When using the v3 protocol, only one connection is opened per-host, and +throughput is improved due to reduced pooling overhead and lock contention.

  • +
  • Support for user-defined types (Cassandra 2.1+)

  • +
  • Support for tuple type in (limited usage Cassandra 2.0.9, full usage +in Cassandra 2.1)

  • +
  • Protocol-level client-side timestamps (see Session.use_client_timestamp)

  • +
  • Overridable type encoding for non-prepared statements (see Session.encoders)

  • +
  • Configurable serial consistency levels for batch statements

  • +
  • Use io.BytesIO for reduced CPU consumption (github #143)

  • +
  • Support Twisted as a reactor. Note that a Twisted-compatible +API is not exposed (so no Deferreds), this is just a reactor +implementation. (github #135, PYTHON-8)

  • +
+
+
+

Bug Fixes

+
    +
  • Fix references to xrange that do not go through “six” in libevreactor and +geventreactor (github #138)

  • +
  • Make BoundStatements inherit fetch_size from their parent +PreparedStatement (PYTHON-80)

  • +
  • Clear reactor state in child process after forking to prevent errors with +multiprocessing when the parent process has connected a Cluster before +forking (github #141)

  • +
  • Don’t share prepared statement lock across Cluster instances

  • +
  • Format CompositeType and DynamicCompositeType columns correctly in +CREATE TABLE statements.

  • +
  • Fix cassandra.concurrent behavior when dealing with automatic paging +(PYTHON-81)

  • +
  • Properly defunct connections after protocol errors

  • +
  • Avoid UnicodeDecodeError when query string is unicode (PYTHON-76)

  • +
  • Correctly capture dclocal_read_repair_chance for tables and +use it when generating CREATE TABLE statements (PYTHON-84)

  • +
  • Avoid race condition with AsyncoreConnection that may cause messages +to fail to be written until a new message is pushed

  • +
  • Make sure cluster.metadata.partitioner and cluster.metadata.token_map +are populated when all nodes in the cluster are included in the +contact points (PYTHON-90)

  • +
  • Make Murmur3 hash match Cassandra’s hash for all values (PYTHON-89, +github #147)

  • +
  • Don’t attempt to reconnect to hosts that should be ignored (according +to the load balancing policy) when a notification is received that the +host is down.

  • +
  • Add CAS WriteType, avoiding KeyError on CAS write timeout (PYTHON-91)

  • +
+
+
+
+

2.0.2

+

June 10, 2014

+
+

Bug Fixes

+
    +
  • Add six to requirements.txt

  • +
  • Avoid KeyError during schema refresh when a keyspace is dropped +and TokenAwarePolicy is not in use

  • +
  • Avoid registering multiple atexit cleanup functions when the +asyncore event loop is restarted multiple times

  • +
  • Delay initialization of reactors in order to avoid problems +with shared state when using multiprocessing (PYTHON-60)

  • +
  • Add python-six to debian dependencies, move python-blist to recommends

  • +
  • Fix memory leak when libev connections are created and +destroyed (github #93)

  • +
  • Ensure token map is rebuilt when hosts are removed from the cluster

  • +
+
+
+
+

2.0.1

+

May 28, 2014

+
+

Bug Fixes

+
    +
  • Fix check for Cluster.is_shutdown in in @run_in_executor +decorator

  • +
+
+
+
+

2.0.0

+

May 28, 2014

+
+

Features

+
    +
  • Make libev C extension Python3-compatible (PYTHON-70)

  • +
  • Support v2 protocol authentication (PYTHON-73, github #125)

  • +
+
+
+

Bug Fixes

+
    +
  • Fix murmur3 C extension compilation under Python3.4 (github #124)

  • +
+
+
+

Merged From 1.x

+
+

Features

+
    +
  • Add Session.default_consistency_level (PYTHON-14)

  • +
+
+
+

Bug Fixes

+
    +
  • Don’t strip trailing underscores from column names when using the +named_tuple_factory (PYTHON-56)

  • +
  • Ensure replication factors are ints for NetworkTopologyStrategy +to avoid TypeErrors (github #120)

  • +
  • Pass WriteType instance to RetryPolicy.on_write_timeout() instead +of the string name of the write type. This caused write timeout +errors to always be rethrown instead of retrying. (github #123)

  • +
  • Avoid submitting tasks to the ThreadPoolExecutor after shutdown. With +retries enabled, this could cause Cluster.shutdown() to hang under +some circumstances.

  • +
  • Fix unintended rebuild of token replica map when keyspaces are +discovered (on startup), added, or updated and TokenAwarePolicy is not +in use.

  • +
  • Avoid rebuilding token metadata when cluster topology has not +actually changed

  • +
  • Avoid preparing queries for hosts that should be ignored (such as +remote hosts when using the DCAwareRoundRobinPolicy) (PYTHON-75)

  • +
+
+
+

Other

+
    +
  • Add 1 second timeout to join() call on event loop thread during +interpreter shutdown. This can help to prevent the process from +hanging during shutdown.

  • +
+
+
+
+
+

2.0.0b1

+

May 6, 2014

+
+

Upgrading from 1.x

+

Cluster.shutdown() should always be called when you are done with a +Cluster instance. If it is not called, there are no guarantees that the +driver will not hang. However, if you do have a reproduceable case +where Cluster.shutdown() is not called and the driver hangs, please +report it so that we can attempt to fix it.

+

If you’re using the 2.0 driver against Cassandra 1.2, you will need +to set your protocol version to 1. For example:

+
+

cluster = Cluster(…, protocol_version=1)

+
+
+
+

Features

+
    +
  • Support v2 of Cassandra’s native protocol, which includes the following +new features: automatic query paging support, protocol-level batch statements, +and lightweight transactions

  • +
  • Support for Python 3.3 and 3.4

  • +
  • Allow a default query timeout to be set per-Session

  • +
+
+
+

Bug Fixes

+
    +
  • Avoid errors during interpreter shutdown (the driver attempts to cleanup +daemonized worker threads before interpreter shutdown)

  • +
+
+
+

Deprecations

+

The following functions have moved from cassandra.decoder to cassandra.query. +The original functions have been left in place with a DeprecationWarning for +now:

+
    +
  • cassandra.decoder.tuple_factory has moved to cassandra.query.tuple_factory

  • +
  • cassandra.decoder.named_tuple_factory has moved to cassandra.query.named_tuple_factory

  • +
  • cassandra.decoder.dict_factory has moved to cassandra.query.dict_factory

  • +
  • cassandra.decoder.ordered_dict_factory has moved to cassandra.query.ordered_dict_factory

  • +
+

Exceptions that were in cassandra.decoder have been moved to cassandra.protocol. If +you handle any of these exceptions, you must adjust the code accordingly.

+
+
+
+

1.1.2

+

May 8, 2014

+
+

Features

+
    +
  • Allow a specific compression type to be requested for communications with +Cassandra and prefer lz4 if available

  • +
+
+
+

Bug Fixes

+
    +
  • Update token metadata (for TokenAware calculations) when a node is removed +from the ring

  • +
  • Fix file handle leak with gevent reactor due to blocking Greenlet kills when +closing excess connections

  • +
  • Avoid handling a node coming up multiple times due to a reconnection attempt +succeeding close to the same time that an UP notification is pushed

  • +
  • Fix duplicate node-up handling, which could result in multiple reconnectors +being started as well as the executor threads becoming deadlocked, preventing +future node up or node down handling from being executed.

  • +
  • Handle exhausted ReconnectionPolicy schedule correctly

  • +
+
+
+

Other

+
    +
  • Don’t log at ERROR when a connection is closed during the startup +communications

  • +
  • Mke scales, blist optional dependencies

  • +
+
+
+
+

1.1.1

+

April 16, 2014

+
+

Bug Fixes

+
    +
  • Fix unconditional import of nose in setup.py (github #111)

  • +
+
+
+
+

1.1.0

+

April 16, 2014

+
+

Features

+
    +
  • Gevent is now supported through monkey-patching the stdlib (PYTHON-7, +github issue #46)

  • +
  • Support static columns in schemas, which are available starting in +Cassandra 2.1. (github issue #91)

  • +
  • Add debian packaging (github issue #101)

  • +
  • Add utility methods for easy concurrent execution of statements. See +the new cassandra.concurrent module. (github issue #7)

  • +
+
+
+

Bug Fixes

+
    +
  • Correctly supply compaction and compression parameters in CREATE statements +for tables when working with Cassandra 2.0+

  • +
  • Lowercase boolean literals when generating schemas

  • +
  • Ignore SSL_ERROR_WANT_READ and SSL_ERROR_WANT_WRITE socket errors. Previously, +these resulted in the connection being defuncted, but they can safely be +ignored by the driver.

  • +
  • Don’t reconnect the control connection every time Cluster.connect() is +called

  • +
  • Avoid race condition that could leave ResponseFuture callbacks uncalled +if the callback was added outside of the event loop thread (github issue #95)

  • +
  • Properly escape keyspace name in Session.set_keyspace(). Previously, the +keyspace name was quoted, but any quotes in the string were not escaped.

  • +
  • Avoid adding hosts to the load balancing policy before their datacenter +and rack information has been set, if possible.

  • +
  • Avoid KeyError when updating metadata after droping a table (github issues +#97, #98)

  • +
  • Use tuples instead of sets for DCAwareLoadBalancingPolicy to ensure equal +distribution of requests

  • +
+
+
+

Other

+
    +
  • Don’t ignore column names when parsing typestrings. This is needed for +user-defined type support. (github issue #90)

  • +
  • Better error message when libevwrapper is not found

  • +
  • Only try to import scales when metrics are enabled (github issue #92)

  • +
  • Cut down on the number of queries executing when a new Cluster +connects and when the control connection has to reconnect (github issue #104, +PYTHON-59)

  • +
  • Issue warning log when schema versions do not match

  • +
+
+
+
+

1.0.2

+

March 4, 2014

+
+

Bug Fixes

+
    +
  • With asyncorereactor, correctly handle EAGAIN/EWOULDBLOCK when the message from +Cassandra is a multiple of the read buffer size. Previously, if no more data +became available to read on the socket, the message would never be processed, +resulting in an OperationTimedOut error.

  • +
  • Double quote keyspace, table and column names that require them (those using +uppercase characters or keywords) when generating CREATE statements through +KeyspaceMetadata and TableMetadata.

  • +
  • Decode TimestampType as DateType. (Cassandra replaced DateType with +TimestampType to fix sorting of pre-unix epoch dates in CASSANDRA-5723.)

  • +
  • Handle latest table options when parsing the schema and generating +CREATE statements.

  • +
  • Avoid ‘Set changed size during iteration’ during query plan generation +when hosts go up or down

  • +
+
+
+

Other

+
    +
  • Remove ignored tracing_enabled parameter for SimpleStatement. The +correct way to trace a query is by setting the trace argument to True +in Session.execute() and Session.execute_async().

  • +
  • Raise TypeError instead of cassandra.query.InvalidParameterTypeError when +a parameter for a prepared statement has the wrong type; remove +cassandra.query.InvalidParameterTypeError.

  • +
  • More consistent type checking for query parameters

  • +
  • Add option to a return special object for empty string values for non-string +columns

  • +
+
+
+
+

1.0.1

+

Feb 19, 2014

+
+

Bug Fixes

+
    +
  • Include table indexes in KeyspaceMetadata.export_as_string()

  • +
  • Fix broken token awareness on ByteOrderedPartitioner

  • +
  • Always close socket when defuncting error’ed connections to avoid a potential +file descriptor leak

  • +
  • Handle “custom” types (such as the replaced DateType) correctly

  • +
  • With libevreactor, correctly handle EAGAIN/EWOULDBLOCK when the message from +Cassandra is a multiple of the read buffer size. Previously, if no more data +became available to read on the socket, the message would never be processed, +resulting in an OperationTimedOut error.

  • +
  • Don’t break tracing when a Session’s row_factory is not the default +namedtuple_factory.

  • +
  • Handle data that is already utf8-encoded for UTF8Type values

  • +
  • Fix token-aware routing for tokens that fall before the first node token in +the ring and tokens that exactly match a node’s token

  • +
  • Tolerate null source_elapsed values for Trace events. These may not be +set when events complete after the main operation has already completed.

  • +
+
+
+

Other

+
    +
  • Skip sending OPTIONS message on connection creation if compression is +disabled or not available and a CQL version has not been explicitly +set

  • +
  • Add details about errors and the last queried host to OperationTimedOut

  • +
+
+
+
+

1.0.0 Final

+

Jan 29, 2014

+
+

Bug Fixes

+
    +
  • Prevent leak of Scheduler thread (even with proper shutdown)

  • +
  • Correctly handle ignored hosts, which are common with the +DCAwareRoundRobinPolicy

  • +
  • Hold strong reference to prepared statement while executing it to avoid +garbage collection

  • +
  • Add NullHandler logging handler to the cassandra package to avoid +warnings about there being no configured logger

  • +
  • Fix bad handling of nodes that have been removed from the cluster

  • +
  • Properly escape string types within cql collections

  • +
  • Handle setting the same keyspace twice in a row

  • +
  • Avoid race condition during schema agreement checks that could result +in schema update queries returning before all nodes had seen the change

  • +
  • Preserve millisecond-level precision in datetimes when performing inserts +with simple (non-prepared) statements

  • +
  • Properly defunct connections when libev reports an error by setting +errno instead of simply logging the error

  • +
  • Fix endless hanging of some requests when using the libev reactor

  • +
  • Always start a reconnection process when we fail to connect to +a newly bootstrapped node

  • +
  • Generators map to CQL lists, not key sequences

  • +
  • Always defunct connections when an internal operation fails

  • +
  • Correctly break from handle_write() if nothing was sent (asyncore +reactor only)

  • +
  • Avoid potential double-erroring of callbacks when a connection +becomes defunct

  • +
+
+
+

Features

+
    +
  • Add default query timeout to Session

  • +
  • Add timeout parameter to Session.execute()

  • +
  • Add WhiteListRoundRobinPolicy as a load balancing policy option

  • +
  • Support for consistency level LOCAL_ONE

  • +
  • Make the backoff for fetching traces exponentially increasing and +configurable

  • +
+
+
+

Other

+
    +
  • Raise Exception if TokenAwarePolicy is used against a cluster using the +Murmur3Partitioner if the murmur3 C extension has not been compiled

  • +
  • Add encoder mapping for OrderedDict

  • +
  • Use timeouts on all control connection queries

  • +
  • Benchmark improvements, including command line options and eay +multithreading support

  • +
  • Reduced lock contention when using the asyncore reactor

  • +
  • Warn when non-datetimes are used for ‘timestamp’ column values in +prepared statements

  • +
  • Add requirements.txt and test-requirements.txt

  • +
  • TravisCI integration for running unit tests against Python 2.6, +Python 2.7, and PyPy

  • +
+
+
+
+

1.0.0b7

+

Nov 12, 2013

+

This release makes many stability improvements, especially around +prepared statements and node failure handling. In particular, +several cases where a request would never be completed (and as a +result, leave the application hanging) have been resolved.

+
+

Features

+
    +
  • Add timeout kwarg to ResponseFuture.result()

  • +
  • Create connection pools to all hosts in parallel when initializing +new Sesssions.

  • +
+
+
+

Bug Fixes

+
    +
  • Properly set exception on ResponseFuture when a query fails +against all hosts

  • +
  • Improved cleanup and reconnection efforts when reconnection fails +on a node that has recently come up

  • +
  • Use correct consistency level when retrying failed operations +against a different host. (An invalid consistency level was being +used, causing the retry to fail.)

  • +
  • Better error messages for failed Session.prepare() opertaions

  • +
  • Prepare new statements against all hosts in parallel (formerly +sequential)

  • +
  • Fix failure to save the new current keyspace on connections. (This +could cause problems for prepared statements and lead to extra +operations to continuously re-set the keyspace.)

  • +
  • Avoid sharing LoadBalancingPolicies across Cluster instances. (When +a second Cluster was connected, it effectively mark nodes down for the +first Cluster.)

  • +
  • Better handling of failures during the re-preparation sequence for +unrecognized prepared statements

  • +
  • Throttle trashing of underutilized connections to avoid trashing newly +created connections

  • +
  • Fix race condition which could result in trashed connections being closed +before the last operations had completed

  • +
  • Avoid preparing statements on the event loop thread (which could lead to +deadlock)

  • +
  • Correctly mark up non-contact point nodes discovered by the control +connection. (This lead to prepared statements not being prepared +against those hosts, generating extra traffic later when the +statements were executed and unrecognized.)

  • +
  • Correctly handle large messages through libev

  • +
  • Add timeout to schema agreement check queries

  • +
  • More complete (and less contended) locking around manipulation of the +pending message deque for libev connections

  • +
+
+
+

Other

+
    +
  • Prepare statements in batches of 10. (When many prepared statements +are in use, this allows the driver to start utilizing nodes that +were restarted more quickly.)

  • +
  • Better debug logging around connection management

  • +
  • Don’t retain unreferenced prepared statements in the local cache. +(If many different prepared statements were created, this would +increase memory usage and greatly increase the amount of time +required to begin utilizing a node that was added or marked +up.)

  • +
+
+
+
+

1.0.0b6

+

Oct 22, 2013

+
+

Bug Fixes

+
    +
  • Use lazy string formatting when logging

  • +
  • Avoid several deadlock scenarios, especially when nodes go down

  • +
  • Avoid trashing newly created connections due to insufficient traffic

  • +
  • Gracefully handle un-handled Exceptions when erroring callbacks

  • +
+
+
+

Other

+
    +
  • Node state listeners (which are called when a node is added, removed, +goes down, or comes up) should now be registered through +Cluster.register_listener() instead of through a host’s HealthMonitor +(which has been removed)

  • +
+
+
+
+

1.0.0b5

+

Oct 10, 2013

+
+

Features

+
    +
  • SSL support

  • +
+
+
+

Bug Fixes

+
    +
  • Avoid KeyError when building replica map for NetworkTopologyStrategy

  • +
  • Work around python bug which causes deadlock when a thread imports +the utf8 module

  • +
  • Handle no blist library, which is not compatible with pypy

  • +
  • Avoid deadlock triggered by a keyspace being set on a connection (which +may happen automatically for new connections)

  • +
+
+
+

Other

+
    +
  • Switch packaging from Distribute to setuptools, improved C extension +support

  • +
  • Use PEP 386 compliant beta and post-release versions

  • +
+
+
+
+

1.0.0-beta4

+

Sep 24, 2013

+
+

Features

+
    +
  • Handle new blob syntax in Cassandra 2.0 by accepting bytearray +objects for blob values

  • +
  • Add cql_version kwarg to Cluster.__init__

  • +
+
+
+

Bug Fixes

+
    +
  • Fix KeyError when building token map with NetworkTopologyStrategy +keyspaces (this prevented a Cluster from successfully connecting +at all).

  • +
  • Don’t lose default consitency level from parent PreparedStatement +when creating BoundStatements

  • +
+
+
+
+

1.0.0-beta3

+

Sep 20, 2013

+
+

Features

+
    +
  • Support for LZ4 compression (Cassandra 2.0+)

  • +
  • Token-aware routing will now utilize all replicas for a query instead +of just the first replica

  • +
+
+
+

Bug Fixes

+
    +
  • Fix libev include path for CentOS

  • +
  • Fix varint packing of the value 0

  • +
  • Correctly pack unicode values

  • +
  • Don’t attempt to return failed connections to the pool when a final result +is set

  • +
  • Fix bad iteration of connection credentials

  • +
  • Use blist’s orderedset for set collections and OrderedDict for map +collections so that Cassandra’s ordering is preserved

  • +
  • Fix connection failure on Windows due to unavailability of inet_pton +and inet_ntop. (Note that IPv6 inet_address values are still not +supported on Windows.)

  • +
  • Boolean constants shouldn’t be surrounded by single quotes

  • +
  • Avoid a potential loss of precision on float constants due to string +formatting

  • +
  • Actually utilize non-standard ports set on Cluster objects

  • +
  • Fix export of schema as a set of CQL queries

  • +
+
+
+

Other

+
    +
  • Use cStringIO for connection buffer for better performance

  • +
  • Add __repr__ method for Statement classes

  • +
  • Raise InvalidTypeParameterError when parameters of the wrong +type are used with statements

  • +
  • Make all tests compatible with Python 2.6

  • +
  • Add 1s timeout for opening new connections

  • +
+
+
+
+

1.0.0-beta2

+

Aug 19, 2013

+
+

Bug Fixes

+
    +
  • Fix pip packaging

  • +
+
+
+
+

1.0.0-beta

+

Aug 16, 2013

+

Initial release

+
+
+ + +
+ + + + + +
+ + +
+
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/stable/CNAME b/stable/CNAME new file mode 100644 index 0000000000..9f3e01a070 --- /dev/null +++ b/stable/CNAME @@ -0,0 +1 @@ +python-driver.docs.scylladb.com \ No newline at end of file diff --git a/stable/_sources/CHANGELOG.rst.txt b/stable/_sources/CHANGELOG.rst.txt new file mode 100644 index 0000000000..f6d642b27f --- /dev/null +++ b/stable/_sources/CHANGELOG.rst.txt @@ -0,0 +1,7 @@ +:orphan: + +********* +CHANGELOG +********* + +.. include:: ../CHANGELOG.rst diff --git a/stable/_sources/api/cassandra.rst.txt b/stable/_sources/api/cassandra.rst.txt new file mode 100644 index 0000000000..d46aae56cb --- /dev/null +++ b/stable/_sources/api/cassandra.rst.txt @@ -0,0 +1,77 @@ +:mod:`cassandra` - Exceptions and Enums +======================================= + +.. module:: cassandra + +.. data:: __version_info__ + + The version of the driver in a tuple format + +.. data:: __version__ + + The version of the driver in a string format + +.. autoclass:: ConsistencyLevel + :members: + +.. autoclass:: ProtocolVersion + :members: + +.. autoclass:: UserFunctionDescriptor + :members: + :inherited-members: + +.. autoclass:: UserAggregateDescriptor + :members: + :inherited-members: + +.. autoexception:: DriverException() + :members: + +.. autoexception:: RequestExecutionException() + :members: + +.. autoexception:: Unavailable() + :members: + +.. autoexception:: Timeout() + :members: + +.. autoexception:: ReadTimeout() + :members: + +.. autoexception:: WriteTimeout() + :members: + +.. autoexception:: CoordinationFailure() + :members: + +.. autoexception:: ReadFailure() + :members: + +.. autoexception:: WriteFailure() + :members: + +.. autoexception:: FunctionFailure() + :members: + +.. autoexception:: RequestValidationException() + :members: + +.. autoexception:: ConfigurationException() + :members: + +.. autoexception:: AlreadyExists() + :members: + +.. autoexception:: InvalidRequest() + :members: + +.. autoexception:: Unauthorized() + :members: + +.. autoexception:: AuthenticationFailed() + :members: + +.. autoexception:: OperationTimedOut() + :members: diff --git a/stable/_sources/api/cassandra/auth.rst.txt b/stable/_sources/api/cassandra/auth.rst.txt new file mode 100644 index 0000000000..58c964cf89 --- /dev/null +++ b/stable/_sources/api/cassandra/auth.rst.txt @@ -0,0 +1,22 @@ +``cassandra.auth`` - Authentication +=================================== + +.. module:: cassandra.auth + +.. autoclass:: AuthProvider + :members: + +.. autoclass:: Authenticator + :members: + +.. autoclass:: PlainTextAuthProvider + :members: + +.. autoclass:: PlainTextAuthenticator + :members: + +.. autoclass:: SaslAuthProvider + :members: + +.. autoclass:: SaslAuthenticator + :members: diff --git a/stable/_sources/api/cassandra/cluster.rst.txt b/stable/_sources/api/cassandra/cluster.rst.txt new file mode 100644 index 0000000000..2b3d7828a8 --- /dev/null +++ b/stable/_sources/api/cassandra/cluster.rst.txt @@ -0,0 +1,228 @@ +``cassandra.cluster`` - Clusters and Sessions +============================================= + +.. module:: cassandra.cluster + +.. autoclass:: Cluster ([contact_points=('127.0.0.1',)][, port=9042][, executor_threads=2], **attr_kwargs) + + .. autoattribute:: contact_points + + .. autoattribute:: port + + .. autoattribute:: cql_version + + .. autoattribute:: protocol_version + + .. autoattribute:: compression + + .. autoattribute:: auth_provider + + .. autoattribute:: load_balancing_policy + + .. autoattribute:: reconnection_policy + + .. autoattribute:: default_retry_policy + :annotation: = + + .. autoattribute:: conviction_policy_factory + + .. autoattribute:: address_translator + + .. autoattribute:: metrics_enabled + + .. autoattribute:: metrics + + .. autoattribute:: ssl_context + + .. autoattribute:: ssl_options + + .. autoattribute:: sockopts + + .. autoattribute:: max_schema_agreement_wait + + .. autoattribute:: metadata + + .. autoattribute:: connection_class + + .. autoattribute:: control_connection_timeout + + .. autoattribute:: idle_heartbeat_interval + + .. autoattribute:: idle_heartbeat_timeout + + .. autoattribute:: schema_event_refresh_window + + .. autoattribute:: topology_event_refresh_window + + .. autoattribute:: status_event_refresh_window + + .. autoattribute:: prepare_on_all_hosts + + .. autoattribute:: reprepare_on_up + + .. autoattribute:: connect_timeout + + .. autoattribute:: schema_metadata_enabled + :annotation: = True + + .. autoattribute:: token_metadata_enabled + :annotation: = True + + .. autoattribute:: timestamp_generator + + .. autoattribute:: endpoint_factory + + .. autoattribute:: cloud + + .. automethod:: connect + + .. automethod:: shutdown + + .. automethod:: register_user_type + + .. automethod:: register_listener + + .. automethod:: unregister_listener + + .. automethod:: add_execution_profile + + .. automethod:: set_max_requests_per_connection + + .. automethod:: get_max_requests_per_connection + + .. automethod:: set_min_requests_per_connection + + .. automethod:: get_min_requests_per_connection + + .. automethod:: get_core_connections_per_host + + .. automethod:: set_core_connections_per_host + + .. automethod:: get_max_connections_per_host + + .. automethod:: set_max_connections_per_host + + .. automethod:: get_control_connection_host + + .. automethod:: refresh_schema_metadata + + .. automethod:: refresh_keyspace_metadata + + .. automethod:: refresh_table_metadata + + .. automethod:: refresh_user_type_metadata + + .. automethod:: refresh_user_function_metadata + + .. automethod:: refresh_user_aggregate_metadata + + .. automethod:: refresh_nodes + + .. automethod:: set_meta_refresh_enabled + +.. autoclass:: ExecutionProfile (load_balancing_policy=, retry_policy=None, consistency_level=ConsistencyLevel.LOCAL_ONE, serial_consistency_level=None, request_timeout=10.0, row_factory=, speculative_execution_policy=None) + :members: + :exclude-members: consistency_level + + .. autoattribute:: consistency_level + :annotation: = LOCAL_ONE + +.. autoclass:: GraphExecutionProfile (load_balancing_policy=_NOT_SET, retry_policy=None, consistency_level=ConsistencyLevel.LOCAL_ONE, serial_consistency_level=None, request_timeout=30.0, row_factory=None, graph_options=None, continuous_paging_options=_NOT_SET) + :members: + +.. autoclass:: GraphAnalyticsExecutionProfile (load_balancing_policy=None, retry_policy=None, consistency_level=ConsistencyLevel.LOCAL_ONE, serial_consistency_level=None, request_timeout=3600. * 24. * 7., row_factory=None, graph_options=None) + :members: + +.. autodata:: EXEC_PROFILE_DEFAULT + :annotation: + +.. autodata:: EXEC_PROFILE_GRAPH_DEFAULT + :annotation: + +.. autodata:: EXEC_PROFILE_GRAPH_SYSTEM_DEFAULT + :annotation: + +.. autodata:: EXEC_PROFILE_GRAPH_ANALYTICS_DEFAULT + :annotation: + +.. autoclass:: Session () + + .. autoattribute:: default_timeout + :annotation: = 10.0 + + .. autoattribute:: default_consistency_level + :annotation: = LOCAL_ONE + + .. autoattribute:: default_serial_consistency_level + :annotation: = None + + .. autoattribute:: row_factory + :annotation: = + + .. autoattribute:: default_fetch_size + + .. autoattribute:: use_client_timestamp + + .. autoattribute:: timestamp_generator + + .. autoattribute:: encoder + + .. autoattribute:: client_protocol_handler + + .. automethod:: execute(statement[, parameters][, timeout][, trace][, custom_payload][, paging_state][, host][, execute_as]) + + .. automethod:: execute_async(statement[, parameters][, trace][, custom_payload][, paging_state][, host][, execute_as]) + + .. automethod:: execute_graph(statement[, parameters][, trace][, execution_profile=EXEC_PROFILE_GRAPH_DEFAULT][, execute_as]) + + .. automethod:: execute_graph_async(statement[, parameters][, trace][, execution_profile=EXEC_PROFILE_GRAPH_DEFAULT][, execute_as]) + + .. automethod:: prepare(statement) + + .. automethod:: shutdown() + + .. automethod:: set_keyspace(keyspace) + + .. automethod:: get_execution_profile + + .. automethod:: execution_profile_clone_update + + .. automethod:: add_request_init_listener + + .. automethod:: remove_request_init_listener + +.. autoclass:: ResponseFuture () + + .. autoattribute:: query + + .. automethod:: result() + + .. automethod:: get_query_trace() + + .. automethod:: get_all_query_traces() + + .. autoattribute:: custom_payload() + + .. autoattribute:: is_schema_agreed + + .. autoattribute:: has_more_pages + + .. autoattribute:: warnings + + .. automethod:: start_fetching_next_page() + + .. automethod:: add_callback(fn, *args, **kwargs) + + .. automethod:: add_errback(fn, *args, **kwargs) + + .. automethod:: add_callbacks(callback, errback, callback_args=(), callback_kwargs=None, errback_args=(), errback_args=None) + +.. autoclass:: ResultSet () + :members: + +.. autoexception:: QueryExhausted () + +.. autoexception:: NoHostAvailable () + :members: + +.. autoexception:: UserTypeDoesNotExist () diff --git a/stable/_sources/api/cassandra/concurrent.rst.txt b/stable/_sources/api/cassandra/concurrent.rst.txt new file mode 100644 index 0000000000..f4bab6f048 --- /dev/null +++ b/stable/_sources/api/cassandra/concurrent.rst.txt @@ -0,0 +1,8 @@ +``cassandra.concurrent`` - Utilities for Concurrent Statement Execution +======================================================================= + +.. module:: cassandra.concurrent + +.. autofunction:: execute_concurrent + +.. autofunction:: execute_concurrent_with_args diff --git a/stable/_sources/api/cassandra/connection.rst.txt b/stable/_sources/api/cassandra/connection.rst.txt new file mode 100644 index 0000000000..32cca590c0 --- /dev/null +++ b/stable/_sources/api/cassandra/connection.rst.txt @@ -0,0 +1,21 @@ +``cassandra.connection`` - Low Level Connection Info +==================================================== + +.. module:: cassandra.connection + +.. autoexception:: ConnectionException () +.. autoexception:: ConnectionShutdown () +.. autoexception:: ConnectionBusy () +.. autoexception:: ProtocolError () + +.. autoclass:: EndPoint + :members: + +.. autoclass:: EndPointFactory + :members: + +.. autoclass:: SniEndPoint + +.. autoclass:: SniEndPointFactory + +.. autoclass:: UnixSocketEndPoint diff --git a/stable/_sources/api/cassandra/cqlengine/columns.rst.txt b/stable/_sources/api/cassandra/cqlengine/columns.rst.txt new file mode 100644 index 0000000000..d44be8adb8 --- /dev/null +++ b/stable/_sources/api/cassandra/cqlengine/columns.rst.txt @@ -0,0 +1,89 @@ +``cassandra.cqlengine.columns`` - Column types for object mapping models +======================================================================== + +.. module:: cassandra.cqlengine.columns + +Columns +------- + +Columns in your models map to columns in your CQL table. You define CQL columns by defining column attributes on your model classes. +For a model to be valid it needs at least one primary key column and one non-primary key column. + +Just as in CQL, the order you define your columns in is important, and is the same order they are defined in on a model's corresponding table. + +Each column on your model definitions needs to be an instance of a Column class. + +.. autoclass:: Column(**kwargs) + + .. autoattribute:: primary_key + + .. autoattribute:: partition_key + + .. autoattribute:: index + + .. autoattribute:: custom_index + + .. autoattribute:: db_field + + .. autoattribute:: default + + .. autoattribute:: required + + .. autoattribute:: clustering_order + + .. autoattribute:: discriminator_column + + .. autoattribute:: static + +Column Types +------------ + +Columns of all types are initialized by passing :class:`.Column` attributes to the constructor by keyword. + +.. autoclass:: Ascii(**kwargs) + +.. autoclass:: BigInt(**kwargs) + +.. autoclass:: Blob(**kwargs) + +.. autoclass:: Bytes(**kwargs) + +.. autoclass:: Boolean(**kwargs) + +.. autoclass:: Counter + +.. autoclass:: Date(**kwargs) + +.. autoclass:: DateTime(**kwargs) + + .. autoattribute:: truncate_microseconds + +.. autoclass:: Decimal(**kwargs) + +.. autoclass:: Double(**kwargs) + +.. autoclass:: Float + +.. autoclass:: Integer(**kwargs) + +.. autoclass:: List + +.. autoclass:: Map + +.. autoclass:: Set + +.. autoclass:: SmallInt(**kwargs) + +.. autoclass:: Text + +.. autoclass:: Time(**kwargs) + +.. autoclass:: TimeUUID(**kwargs) + +.. autoclass:: TinyInt(**kwargs) + +.. autoclass:: UserDefinedType + +.. autoclass:: UUID(**kwargs) + +.. autoclass:: VarInt(**kwargs) diff --git a/stable/_sources/api/cassandra/cqlengine/connection.rst.txt b/stable/_sources/api/cassandra/cqlengine/connection.rst.txt new file mode 100644 index 0000000000..0f584fcca2 --- /dev/null +++ b/stable/_sources/api/cassandra/cqlengine/connection.rst.txt @@ -0,0 +1,16 @@ +``cassandra.cqlengine.connection`` - Connection management for cqlengine +======================================================================== + +.. module:: cassandra.cqlengine.connection + +.. autofunction:: default + +.. autofunction:: set_session + +.. autofunction:: setup + +.. autofunction:: register_connection + +.. autofunction:: unregister_connection + +.. autofunction:: set_default_connection diff --git a/stable/_sources/api/cassandra/cqlengine/management.rst.txt b/stable/_sources/api/cassandra/cqlengine/management.rst.txt new file mode 100644 index 0000000000..fb483abc81 --- /dev/null +++ b/stable/_sources/api/cassandra/cqlengine/management.rst.txt @@ -0,0 +1,19 @@ +``cassandra.cqlengine.management`` - Schema management for cqlengine +======================================================================== + +.. module:: cassandra.cqlengine.management + +A collection of functions for managing keyspace and table schema. + +.. autofunction:: create_keyspace_simple + +.. autofunction:: create_keyspace_network_topology + +.. autofunction:: drop_keyspace + +.. autofunction:: sync_table + +.. autofunction:: sync_type + +.. autofunction:: drop_table + diff --git a/stable/_sources/api/cassandra/cqlengine/models.rst.txt b/stable/_sources/api/cassandra/cqlengine/models.rst.txt new file mode 100644 index 0000000000..60b1471184 --- /dev/null +++ b/stable/_sources/api/cassandra/cqlengine/models.rst.txt @@ -0,0 +1,197 @@ +``cassandra.cqlengine.models`` - Table models for object mapping +================================================================ + +.. module:: cassandra.cqlengine.models + +Model +----- +.. autoclass:: Model(\*\*kwargs) + + The initializer creates an instance of the model. Pass in keyword arguments for columns you've defined on the model. + + .. code-block:: python + + class Person(Model): + id = columns.UUID(primary_key=True) + first_name = columns.Text() + last_name = columns.Text() + + person = Person(first_name='Blake', last_name='Eggleston') + person.first_name #returns 'Blake' + person.last_name #returns 'Eggleston' + + Model attributes define how the model maps to tables in the database. These are class variables that should be set + when defining Model deriviatives. + + .. autoattribute:: __abstract__ + :annotation: = False + + .. autoattribute:: __table_name__ + + .. autoattribute:: __table_name_case_sensitive__ + + .. autoattribute:: __keyspace__ + + .. autoattribute:: __connection__ + + .. attribute:: __default_ttl__ + :annotation: = None + + Will be deprecated in release 4.0. You can set the default ttl by configuring the table ``__options__``. See :ref:`ttl-change` for more details. + + .. autoattribute:: __discriminator_value__ + + See :ref:`model_inheritance` for usage examples. + + Each table can have its own set of configuration options, including compaction. Unspecified, these default to sensible values in + the server. To override defaults, set options using the model ``__options__`` attribute, which allows options specified a dict. + + When a table is synced, it will be altered to match the options set on your table. + This means that if you are changing settings manually they will be changed back on resync. + + Do not use the options settings of cqlengine if you want to manage your compaction settings manually. + + See the `list of supported table properties for more information + `_. + + .. attribute:: __options__ + + For example: + + .. code-block:: python + + class User(Model): + __options__ = {'compaction': {'class': 'LeveledCompactionStrategy', + 'sstable_size_in_mb': '64', + 'tombstone_threshold': '.2'}, + 'comment': 'User data stored here'} + + user_id = columns.UUID(primary_key=True) + name = columns.Text() + + or : + + .. code-block:: python + + class TimeData(Model): + __options__ = {'compaction': {'class': 'SizeTieredCompactionStrategy', + 'bucket_low': '.3', + 'bucket_high': '2', + 'min_threshold': '2', + 'max_threshold': '64', + 'tombstone_compaction_interval': '86400'}, + 'gc_grace_seconds': '0'} + + .. autoattribute:: __compute_routing_key__ + + + The base methods allow creating, storing, and querying modeled objects. + + .. automethod:: create + + .. method:: if_not_exists() + + Check the existence of an object before insertion. The existence of an + object is determined by its primary key(s). And please note using this flag + would incur performance cost. + + If the insertion isn't applied, a :class:`~cassandra.cqlengine.query.LWTException` is raised. + + .. code-block:: python + + try: + TestIfNotExistsModel.if_not_exists().create(id=id, count=9, text='111111111111') + except LWTException as e: + # handle failure case + print e.existing # dict containing LWT result fields + + This method is supported on Cassandra 2.0 or later. + + .. method:: if_exists() + + Check the existence of an object before an update or delete. The existence of an + object is determined by its primary key(s). And please note using this flag + would incur performance cost. + + If the update or delete isn't applied, a :class:`~cassandra.cqlengine.query.LWTException` is raised. + + .. code-block:: python + + try: + TestIfExistsModel.objects(id=id).if_exists().update(count=9, text='111111111111') + except LWTException as e: + # handle failure case + pass + + This method is supported on Cassandra 2.0 or later. + + .. automethod:: save + + .. automethod:: update + + .. method:: iff(**values) + + Checks to ensure that the values specified are correct on the Cassandra cluster. + Simply specify the column(s) and the expected value(s). As with if_not_exists, + this incurs a performance cost. + + If the insertion isn't applied, a :class:`~cassandra.cqlengine.query.LWTException` is raised. + + .. code-block:: python + + t = TestTransactionModel(text='some text', count=5) + try: + t.iff(count=5).update('other text') + except LWTException as e: + # handle failure case + print e.existing # existing object + + .. automethod:: get + + .. automethod:: filter + + .. automethod:: all + + .. automethod:: delete + + .. method:: batch(batch_object) + + Sets the batch object to run instance updates and inserts queries with. + + See :doc:`/cqlengine/batches` for usage examples + + .. automethod:: timeout + + .. method:: timestamp(timedelta_or_datetime) + + Sets the timestamp for the query + + .. method:: ttl(ttl_in_sec) + + Sets the ttl values to run instance updates and inserts queries with. + + .. method:: using(connection=None) + + Change the context on the fly of the model instance (keyspace, connection) + + .. automethod:: column_family_name + + Models also support dict-like access: + + .. method:: len(m) + + Returns the number of columns defined in the model + + .. method:: m[col_name] + + Returns the value of column ``col_name`` + + .. method:: m[col_name] = value + + Set ``m[col_name]`` to value + + .. automethod:: keys + + .. automethod:: values + + .. automethod:: items diff --git a/stable/_sources/api/cassandra/cqlengine/query.rst.txt b/stable/_sources/api/cassandra/cqlengine/query.rst.txt new file mode 100644 index 0000000000..ce8f764b6b --- /dev/null +++ b/stable/_sources/api/cassandra/cqlengine/query.rst.txt @@ -0,0 +1,71 @@ +``cassandra.cqlengine.query`` - Query and filter model objects +================================================================= + +.. module:: cassandra.cqlengine.query + +QuerySet +-------- +QuerySet objects are typically obtained by calling :meth:`~.cassandra.cqlengine.models.Model.objects` on a model class. +The methods here are used to filter, order, and constrain results. + +.. autoclass:: ModelQuerySet + + .. automethod:: all + + .. automethod:: batch + + .. automethod:: consistency + + .. automethod:: count + + .. method:: len(queryset) + + Returns the number of rows matched by this query. This function uses :meth:`~.cassandra.cqlengine.query.ModelQuerySet.count` internally. + + *Note: This function executes a SELECT COUNT() and has a performance cost on large datasets* + + .. automethod:: distinct + + .. automethod:: filter + + .. automethod:: get + + .. automethod:: limit + + .. automethod:: fetch_size + + .. automethod:: if_not_exists + + .. automethod:: if_exists + + .. automethod:: order_by + + .. automethod:: allow_filtering + + .. automethod:: only + + .. automethod:: defer + + .. automethod:: timestamp + + .. automethod:: ttl + + .. automethod:: using + + .. _blind_updates: + + .. automethod:: update + +.. autoclass:: BatchQuery + :members: + + .. automethod:: add_query + .. automethod:: execute + +.. autoclass:: ContextQuery + +.. autoclass:: DoesNotExist + +.. autoclass:: MultipleObjectsReturned + +.. autoclass:: LWTException diff --git a/stable/_sources/api/cassandra/cqlengine/usertype.rst.txt b/stable/_sources/api/cassandra/cqlengine/usertype.rst.txt new file mode 100644 index 0000000000..ebed187da9 --- /dev/null +++ b/stable/_sources/api/cassandra/cqlengine/usertype.rst.txt @@ -0,0 +1,10 @@ +``cassandra.cqlengine.usertype`` - Model classes for User Defined Types +======================================================================= + +.. module:: cassandra.cqlengine.usertype + +UserType +-------- +.. autoclass:: UserType + + .. autoattribute:: __type_name__ diff --git a/stable/_sources/api/cassandra/datastax/graph/fluent/index.rst.txt b/stable/_sources/api/cassandra/datastax/graph/fluent/index.rst.txt new file mode 100644 index 0000000000..5547e0fdd7 --- /dev/null +++ b/stable/_sources/api/cassandra/datastax/graph/fluent/index.rst.txt @@ -0,0 +1,24 @@ +:mod:`cassandra.datastax.graph.fluent` +====================================== + +.. module:: cassandra.datastax.graph.fluent + +.. autoclass:: DseGraph + + .. autoattribute:: DSE_GRAPH_QUERY_LANGUAGE + + .. automethod:: create_execution_profile + + .. automethod:: query_from_traversal + + .. automethod:: traversal_source(session=None, graph_name=None, execution_profile=EXEC_PROFILE_GRAPH_DEFAULT, traversal_class=None) + + .. automethod:: batch(session=None, execution_profile=None) + +.. autoclass:: DSESessionRemoteGraphConnection(session[, graph_name, execution_profile]) + +.. autoclass:: BaseGraphRowFactory + +.. autoclass:: graph_traversal_row_factory + +.. autoclass:: graph_traversal_dse_object_row_factory diff --git a/stable/_sources/api/cassandra/datastax/graph/fluent/predicates.rst.txt b/stable/_sources/api/cassandra/datastax/graph/fluent/predicates.rst.txt new file mode 100644 index 0000000000..f6e86f6451 --- /dev/null +++ b/stable/_sources/api/cassandra/datastax/graph/fluent/predicates.rst.txt @@ -0,0 +1,14 @@ +:mod:`cassandra.datastax.graph.fluent.predicates` +================================================= + +.. module:: cassandra.datastax.graph.fluent.predicates + + +.. autoclass:: Search + :members: + +.. autoclass:: CqlCollection + :members: + +.. autoclass:: Geo + :members: diff --git a/stable/_sources/api/cassandra/datastax/graph/fluent/query.rst.txt b/stable/_sources/api/cassandra/datastax/graph/fluent/query.rst.txt new file mode 100644 index 0000000000..3dd859f96e --- /dev/null +++ b/stable/_sources/api/cassandra/datastax/graph/fluent/query.rst.txt @@ -0,0 +1,8 @@ +:mod:`cassandra.datastax.graph.fluent.query` +============================================ + +.. module:: cassandra.datastax.graph.fluent.query + + +.. autoclass:: TraversalBatch + :members: diff --git a/stable/_sources/api/cassandra/datastax/graph/index.rst.txt b/stable/_sources/api/cassandra/datastax/graph/index.rst.txt new file mode 100644 index 0000000000..a9b41cbdc2 --- /dev/null +++ b/stable/_sources/api/cassandra/datastax/graph/index.rst.txt @@ -0,0 +1,133 @@ +``cassandra.datastax.graph`` - Graph Statements, Options, and Row Factories +=========================================================================== + +.. _api-datastax-graph: + +.. module:: cassandra.datastax.graph + +.. autofunction:: single_object_row_factory + +.. autofunction:: graph_result_row_factory + +.. autofunction:: graph_object_row_factory + +.. autofunction:: graph_graphson2_row_factory + +.. autofunction:: graph_graphson3_row_factory + +.. function:: to_int(value) + + Wraps a value to be explicitly serialized as a graphson Int. + +.. function:: to_bigint(value) + + Wraps a value to be explicitly serialized as a graphson Bigint. + +.. function:: to_smallint(value) + + Wraps a value to be explicitly serialized as a graphson Smallint. + +.. function:: to_float(value) + + Wraps a value to be explicitly serialized as a graphson Float. + +.. function:: to_double(value) + + Wraps a value to be explicitly serialized as a graphson Double. + +.. autoclass:: GraphProtocol + :members: + :noindex: + +.. autoclass:: GraphOptions + :noindex: + + .. autoattribute:: graph_name + + .. autoattribute:: graph_source + + .. autoattribute:: graph_language + + .. autoattribute:: graph_read_consistency_level + + .. autoattribute:: graph_write_consistency_level + + .. autoattribute:: is_default_source + + .. autoattribute:: is_analytics_source + + .. autoattribute:: is_graph_source + + .. automethod:: set_source_default + + .. automethod:: set_source_analytics + + .. automethod:: set_source_graph + + +.. autoclass:: SimpleGraphStatement + :members: + :noindex: + +.. autoclass:: Result + :members: + :noindex: + +.. autoclass:: Vertex + :members: + :noindex: + +.. autoclass:: VertexProperty + :members: + :noindex: + +.. autoclass:: Edge + :members: + :noindex: + +.. autoclass:: Path + :members: + :noindex: + +.. autoclass:: T + :members: + :noindex: + +.. autoclass:: GraphSON1Serializer + :members: + :noindex: + +.. autoclass:: GraphSON1Deserializer + :noindex: + + .. automethod:: deserialize_date + + .. automethod:: deserialize_timestamp + + .. automethod:: deserialize_time + + .. automethod:: deserialize_duration + + .. automethod:: deserialize_int + + .. automethod:: deserialize_bigint + + .. automethod:: deserialize_double + + .. automethod:: deserialize_float + + .. automethod:: deserialize_uuid + + .. automethod:: deserialize_blob + + .. automethod:: deserialize_decimal + + .. automethod:: deserialize_point + + .. automethod:: deserialize_linestring + + .. automethod:: deserialize_polygon + +.. autoclass:: GraphSON2Reader + :members: + :noindex: diff --git a/stable/_sources/api/cassandra/decoder.rst.txt b/stable/_sources/api/cassandra/decoder.rst.txt new file mode 100644 index 0000000000..e213cc6d74 --- /dev/null +++ b/stable/_sources/api/cassandra/decoder.rst.txt @@ -0,0 +1,20 @@ +``cassandra.decoder`` - Data Return Formats +=========================================== + +.. module:: cassandra.decoder + +.. function:: tuple_factory + + **Deprecated in 2.0.0.** Use :meth:`cassandra.query.tuple_factory` + +.. function:: named_tuple_factory + + **Deprecated in 2.0.0.** Use :meth:`cassandra.query.named_tuple_factory` + +.. function:: dict_factory + + **Deprecated in 2.0.0.** Use :meth:`cassandra.query.dict_factory` + +.. function:: ordered_dict_factory + + **Deprecated in 2.0.0.** Use :meth:`cassandra.query.ordered_dict_factory` diff --git a/stable/_sources/api/cassandra/encoder.rst.txt b/stable/_sources/api/cassandra/encoder.rst.txt new file mode 100644 index 0000000000..de3b180510 --- /dev/null +++ b/stable/_sources/api/cassandra/encoder.rst.txt @@ -0,0 +1,36 @@ +``cassandra.encoder`` - Encoders for non-prepared Statements +============================================================ + +.. module:: cassandra.encoder + +.. autoclass:: Encoder () + + .. autoattribute:: cassandra.encoder.Encoder.mapping + + .. automethod:: cassandra.encoder.Encoder.cql_encode_none () + + .. automethod:: cassandra.encoder.Encoder.cql_encode_object () + + .. automethod:: cassandra.encoder.Encoder.cql_encode_all_types () + + .. automethod:: cassandra.encoder.Encoder.cql_encode_sequence () + + .. automethod:: cassandra.encoder.Encoder.cql_encode_str () + + .. automethod:: cassandra.encoder.Encoder.cql_encode_unicode () + + .. automethod:: cassandra.encoder.Encoder.cql_encode_bytes () + + Converts strings, buffers, and bytearrays into CQL blob literals. + + .. automethod:: cassandra.encoder.Encoder.cql_encode_datetime () + + .. automethod:: cassandra.encoder.Encoder.cql_encode_date () + + .. automethod:: cassandra.encoder.Encoder.cql_encode_map_collection () + + .. automethod:: cassandra.encoder.Encoder.cql_encode_list_collection () + + .. automethod:: cassandra.encoder.Encoder.cql_encode_set_collection () + + .. automethod:: cql_encode_tuple () diff --git a/stable/_sources/api/cassandra/graph.rst.txt b/stable/_sources/api/cassandra/graph.rst.txt new file mode 100644 index 0000000000..43ddd3086c --- /dev/null +++ b/stable/_sources/api/cassandra/graph.rst.txt @@ -0,0 +1,121 @@ +``cassandra.graph`` - Graph Statements, Options, and Row Factories +================================================================== + +.. note:: This module is only for backward compatibility for dse-driver users. Consider using :ref:`cassandra.datastax.graph `. + +.. module:: cassandra.graph + +.. autofunction:: single_object_row_factory + +.. autofunction:: graph_result_row_factory + +.. autofunction:: graph_object_row_factory + +.. autofunction:: graph_graphson2_row_factory + +.. autofunction:: graph_graphson3_row_factory + +.. function:: to_int(value) + + Wraps a value to be explicitly serialized as a graphson Int. + +.. function:: to_bigint(value) + + Wraps a value to be explicitly serialized as a graphson Bigint. + +.. function:: to_smallint(value) + + Wraps a value to be explicitly serialized as a graphson Smallint. + +.. function:: to_float(value) + + Wraps a value to be explicitly serialized as a graphson Float. + +.. function:: to_double(value) + + Wraps a value to be explicitly serialized as a graphson Double. + +.. autoclass:: GraphProtocol + :members: + +.. autoclass:: GraphOptions + + .. autoattribute:: graph_name + + .. autoattribute:: graph_source + + .. autoattribute:: graph_language + + .. autoattribute:: graph_read_consistency_level + + .. autoattribute:: graph_write_consistency_level + + .. autoattribute:: is_default_source + + .. autoattribute:: is_analytics_source + + .. autoattribute:: is_graph_source + + .. automethod:: set_source_default + + .. automethod:: set_source_analytics + + .. automethod:: set_source_graph + + +.. autoclass:: SimpleGraphStatement + :members: + +.. autoclass:: Result + :members: + +.. autoclass:: Vertex + :members: + +.. autoclass:: VertexProperty + :members: + +.. autoclass:: Edge + :members: + +.. autoclass:: Path + :members: + +.. autoclass:: GraphSON1Serializer + :members: + +.. autoclass:: GraphSON1Deserializer + + .. automethod:: deserialize_date + + .. automethod:: deserialize_timestamp + + .. automethod:: deserialize_time + + .. automethod:: deserialize_duration + + .. automethod:: deserialize_int + + .. automethod:: deserialize_bigint + + .. automethod:: deserialize_double + + .. automethod:: deserialize_float + + .. automethod:: deserialize_uuid + + .. automethod:: deserialize_blob + + .. automethod:: deserialize_decimal + + .. automethod:: deserialize_point + + .. automethod:: deserialize_linestring + + .. automethod:: deserialize_polygon + +.. autoclass:: GraphSON2Reader + :members: + +.. autoclass:: GraphSON3Reader + :members: diff --git a/stable/_sources/api/cassandra/io/asyncioreactor.rst.txt b/stable/_sources/api/cassandra/io/asyncioreactor.rst.txt new file mode 100644 index 0000000000..38ae63ca7f --- /dev/null +++ b/stable/_sources/api/cassandra/io/asyncioreactor.rst.txt @@ -0,0 +1,7 @@ +``cassandra.io.asyncioreactor`` - ``asyncio`` Event Loop +===================================================================== + +.. module:: cassandra.io.asyncioreactor + +.. autoclass:: AsyncioConnection + :members: diff --git a/stable/_sources/api/cassandra/io/asyncorereactor.rst.txt b/stable/_sources/api/cassandra/io/asyncorereactor.rst.txt new file mode 100644 index 0000000000..ade7887e70 --- /dev/null +++ b/stable/_sources/api/cassandra/io/asyncorereactor.rst.txt @@ -0,0 +1,7 @@ +``cassandra.io.asyncorereactor`` - ``asyncore`` Event Loop +========================================================== + +.. module:: cassandra.io.asyncorereactor + +.. autoclass:: AsyncoreConnection + :members: diff --git a/stable/_sources/api/cassandra/io/eventletreactor.rst.txt b/stable/_sources/api/cassandra/io/eventletreactor.rst.txt new file mode 100644 index 0000000000..1ba742c7e9 --- /dev/null +++ b/stable/_sources/api/cassandra/io/eventletreactor.rst.txt @@ -0,0 +1,7 @@ +``cassandra.io.eventletreactor`` - ``eventlet``-compatible Connection +===================================================================== + +.. module:: cassandra.io.eventletreactor + +.. autoclass:: EventletConnection + :members: diff --git a/stable/_sources/api/cassandra/io/geventreactor.rst.txt b/stable/_sources/api/cassandra/io/geventreactor.rst.txt new file mode 100644 index 0000000000..603affe140 --- /dev/null +++ b/stable/_sources/api/cassandra/io/geventreactor.rst.txt @@ -0,0 +1,7 @@ +``cassandra.io.geventreactor`` - ``gevent``-compatible Event Loop +================================================================= + +.. module:: cassandra.io.geventreactor + +.. autoclass:: GeventConnection + :members: diff --git a/stable/_sources/api/cassandra/io/libevreactor.rst.txt b/stable/_sources/api/cassandra/io/libevreactor.rst.txt new file mode 100644 index 0000000000..5b7288edf2 --- /dev/null +++ b/stable/_sources/api/cassandra/io/libevreactor.rst.txt @@ -0,0 +1,6 @@ +``cassandra.io.libevreactor`` - ``libev`` Event Loop +==================================================== + +.. module:: cassandra.io.libevreactor + +.. autoclass:: LibevConnection diff --git a/stable/_sources/api/cassandra/io/twistedreactor.rst.txt b/stable/_sources/api/cassandra/io/twistedreactor.rst.txt new file mode 100644 index 0000000000..24e93bd432 --- /dev/null +++ b/stable/_sources/api/cassandra/io/twistedreactor.rst.txt @@ -0,0 +1,9 @@ +``cassandra.io.twistedreactor`` - Twisted Event Loop +==================================================== + +.. module:: cassandra.io.twistedreactor + +.. class:: TwistedConnection + + An implementation of :class:`~cassandra.io.connection.Connection` that uses + Twisted's reactor as its event loop. diff --git a/stable/_sources/api/cassandra/metadata.rst.txt b/stable/_sources/api/cassandra/metadata.rst.txt new file mode 100644 index 0000000000..7c1280bcf7 --- /dev/null +++ b/stable/_sources/api/cassandra/metadata.rst.txt @@ -0,0 +1,93 @@ +``cassandra.metadata`` - Schema and Ring Topology +================================================= + +.. module:: cassandra.metadata + +.. autodata:: cql_keywords + :annotation: + +.. autodata:: cql_keywords_unreserved + :annotation: + +.. autodata:: cql_keywords_reserved + :annotation: + +.. autoclass:: Metadata () + :members: + :exclude-members: rebuild_schema, rebuild_token_map, add_host, remove_host + +Schemas +------- + +.. autoclass:: KeyspaceMetadata () + :members: + +.. autoclass:: UserType () + :members: + +.. autoclass:: Function () + :members: + +.. autoclass:: Aggregate () + :members: + +.. autoclass:: TableMetadata () + :members: + +.. autoclass:: TableMetadataV3 () + :members: + +.. autoclass:: TableMetadataDSE68 () + :members: + +.. autoclass:: ColumnMetadata () + :members: + +.. autoclass:: IndexMetadata () + :members: + +.. autoclass:: MaterializedViewMetadata () + :members: + +.. autoclass:: VertexMetadata () + :members: + +.. autoclass:: EdgeMetadata () + :members: + +Tokens and Ring Topology +------------------------ + +.. autoclass:: TokenMap () + :members: + +.. autoclass:: Token () + :members: + +.. autoclass:: Murmur3Token + :members: + +.. autoclass:: MD5Token + :members: + +.. autoclass:: BytesToken + :members: + +.. autoclass:: ReplicationStrategy + :members: + +.. autoclass:: ReplicationFactor + :members: + :exclude-members: create + +.. autoclass:: SimpleStrategy + :members: + +.. autoclass:: NetworkTopologyStrategy + :members: + +.. autoclass:: LocalStrategy + :members: + +.. autofunction:: group_keys_by_replica + diff --git a/stable/_sources/api/cassandra/metrics.rst.txt b/stable/_sources/api/cassandra/metrics.rst.txt new file mode 100644 index 0000000000..0df7f8b5b9 --- /dev/null +++ b/stable/_sources/api/cassandra/metrics.rst.txt @@ -0,0 +1,7 @@ +``cassandra.metrics`` - Performance Metrics +=========================================== + +.. module:: cassandra.metrics + +.. autoclass:: cassandra.metrics.Metrics () + :members: diff --git a/stable/_sources/api/cassandra/policies.rst.txt b/stable/_sources/api/cassandra/policies.rst.txt new file mode 100644 index 0000000000..387b19ed95 --- /dev/null +++ b/stable/_sources/api/cassandra/policies.rst.txt @@ -0,0 +1,96 @@ +``cassandra.policies`` - Load balancing and Failure Handling Policies +===================================================================== + +.. module:: cassandra.policies + +Load Balancing +-------------- + +.. autoclass:: HostDistance + :members: + +.. autoclass:: LoadBalancingPolicy + :members: + +.. autoclass:: RoundRobinPolicy + :members: + +.. autoclass:: DCAwareRoundRobinPolicy + :members: + +.. autoclass:: WhiteListRoundRobinPolicy + :members: + +.. autoclass:: TokenAwarePolicy + :members: + +.. autoclass:: HostFilterPolicy + + .. we document these methods manually so we can specify a param to predicate + + .. automethod:: predicate(host) + .. automethod:: distance + .. automethod:: make_query_plan + +.. autoclass:: DefaultLoadBalancingPolicy + :members: + +.. autoclass:: DSELoadBalancingPolicy + :members: + +Translating Server Node Addresses +--------------------------------- + +.. autoclass:: AddressTranslator + :members: + +.. autoclass:: IdentityTranslator + :members: + +.. autoclass:: EC2MultiRegionTranslator + :members: + +Marking Hosts Up or Down +------------------------ + +.. autoclass:: ConvictionPolicy + :members: + +.. autoclass:: SimpleConvictionPolicy + :members: + +Reconnecting to Dead Hosts +-------------------------- + +.. autoclass:: ReconnectionPolicy + :members: + +.. autoclass:: ConstantReconnectionPolicy + :members: + +.. autoclass:: ExponentialReconnectionPolicy + :members: + +Retrying Failed Operations +-------------------------- + +.. autoclass:: WriteType + :members: + +.. autoclass:: RetryPolicy + :members: + +.. autoclass:: FallthroughRetryPolicy + :members: + +.. autoclass:: DowngradingConsistencyRetryPolicy + :members: + +Retrying Idempotent Operations +------------------------------ + +.. autoclass:: SpeculativeExecutionPolicy + :members: + +.. autoclass:: ConstantSpeculativeExecutionPolicy + :members: diff --git a/stable/_sources/api/cassandra/pool.rst.txt b/stable/_sources/api/cassandra/pool.rst.txt new file mode 100644 index 0000000000..b14d30e19c --- /dev/null +++ b/stable/_sources/api/cassandra/pool.rst.txt @@ -0,0 +1,11 @@ +``cassandra.pool`` - Hosts and Connection Pools +=============================================== + +.. automodule:: cassandra.pool + +.. autoclass:: Host () + :members: + :exclude-members: set_location_info, get_and_set_reconnection_handler + +.. autoexception:: NoConnectionsAvailable + :members: diff --git a/stable/_sources/api/cassandra/protocol.rst.txt b/stable/_sources/api/cassandra/protocol.rst.txt new file mode 100644 index 0000000000..f615ab1a70 --- /dev/null +++ b/stable/_sources/api/cassandra/protocol.rst.txt @@ -0,0 +1,55 @@ +``cassandra.protocol`` - Protocol Features +===================================================================== + +.. module:: cassandra.protocol + +.. _custom_payload: + +Custom Payloads +--------------- +Native protocol version 4+ allows for a custom payload to be sent between clients +and custom query handlers. The payload is specified as a string:binary_type dict +holding custom key/value pairs. + +By default these are ignored by the server. They can be useful for servers implementing +a custom QueryHandler. + +See :meth:`.Session.execute`, ::meth:`.Session.execute_async`, :attr:`.ResponseFuture.custom_payload`. + +.. autoclass:: _ProtocolHandler + + .. autoattribute:: message_types_by_opcode + :annotation: = {default mapping} + + .. automethod:: encode_message + + .. automethod:: decode_message + +.. _faster_deser: + +Faster Deserialization +---------------------- +When python-driver is compiled with Cython, it uses a Cython-based deserialization path +to deserialize messages. By default, the driver will use a Cython-based parser that returns +lists of rows similar to the pure-Python version. In addition, there are two additional +ProtocolHandler classes that can be used to deserialize response messages: ``LazyProtocolHandler`` +and ``NumpyProtocolHandler``. They can be used as follows: + +.. code:: python + + from cassandra.protocol import NumpyProtocolHandler, LazyProtocolHandler + from cassandra.query import tuple_factory + s.client_protocol_handler = LazyProtocolHandler # for a result iterator + s.row_factory = tuple_factory #required for Numpy results + s.client_protocol_handler = NumpyProtocolHandler # for a dict of NumPy arrays as result + +These protocol handlers comprise different parsers, and return results as described below: + +- ProtocolHandler: this default implementation is a drop-in replacement for the pure-Python version. + The rows are all parsed upfront, before results are returned. + +- LazyProtocolHandler: near drop-in replacement for the above, except that it returns an iterator over rows, + lazily decoded into the default row format (this is more efficient since all decoded results are not materialized at once) + +- NumpyProtocolHander: deserializes results directly into NumPy arrays. This facilitates efficient integration with + analysis toolkits such as Pandas. diff --git a/stable/_sources/api/cassandra/query.rst.txt b/stable/_sources/api/cassandra/query.rst.txt new file mode 100644 index 0000000000..fcd79739b9 --- /dev/null +++ b/stable/_sources/api/cassandra/query.rst.txt @@ -0,0 +1,59 @@ +``cassandra.query`` - Prepared Statements, Batch Statements, Tracing, and Row Factories +======================================================================================= + +.. module:: cassandra.query + +.. autofunction:: tuple_factory + +.. autofunction:: named_tuple_factory + +.. autofunction:: dict_factory + +.. autofunction:: ordered_dict_factory + +.. autoclass:: SimpleStatement + :members: + +.. autoclass:: PreparedStatement () + :members: + +.. autoclass:: BoundStatement + :members: + +.. autoclass:: Statement () + :members: + +.. autodata:: UNSET_VALUE + :annotation: + +.. autoclass:: BatchStatement (batch_type=BatchType.LOGGED, retry_policy=None, consistency_level=None) + :members: + +.. autoclass:: BatchType () + + .. autoattribute:: LOGGED + + .. autoattribute:: UNLOGGED + + .. autoattribute:: COUNTER + +.. autoclass:: cassandra.query.ValueSequence + + A wrapper class that is used to specify that a sequence of values should + be treated as a CQL list of values instead of a single column collection when used + as part of the `parameters` argument for :meth:`.Session.execute()`. + + This is typically needed when supplying a list of keys to select. + For example:: + + >>> my_user_ids = ('alice', 'bob', 'charles') + >>> query = "SELECT * FROM users WHERE user_id IN %s" + >>> session.execute(query, parameters=[ValueSequence(my_user_ids)]) + +.. autoclass:: QueryTrace () + :members: + +.. autoclass:: TraceEvent () + :members: + +.. autoexception:: TraceUnavailable diff --git a/stable/_sources/api/cassandra/timestamps.rst.txt b/stable/_sources/api/cassandra/timestamps.rst.txt new file mode 100644 index 0000000000..00d25b06d9 --- /dev/null +++ b/stable/_sources/api/cassandra/timestamps.rst.txt @@ -0,0 +1,14 @@ +``cassandra.timestamps`` - Timestamp Generation +=============================================== + +.. module:: cassandra.timestamps + +.. autoclass:: MonotonicTimestampGenerator (warn_on_drift=True, warning_threshold=0, warning_interval=0) + + .. autoattribute:: warn_on_drift + + .. autoattribute:: warning_threshold + + .. autoattribute:: warning_interval + + .. automethod:: _next_timestamp diff --git a/stable/_sources/api/cassandra/util.rst.txt b/stable/_sources/api/cassandra/util.rst.txt new file mode 100644 index 0000000000..848d4d5fc2 --- /dev/null +++ b/stable/_sources/api/cassandra/util.rst.txt @@ -0,0 +1,5 @@ +``cassandra.util`` - Utilities +=================================== + +.. automodule:: cassandra.util + :members: diff --git a/stable/_sources/api/index.rst.txt b/stable/_sources/api/index.rst.txt new file mode 100644 index 0000000000..9e778d508c --- /dev/null +++ b/stable/_sources/api/index.rst.txt @@ -0,0 +1,54 @@ +API Documentation +================= + +Core Driver +----------- +.. toctree:: + :maxdepth: 2 + + cassandra + cassandra/cluster + cassandra/policies + cassandra/auth + cassandra/graph + cassandra/metadata + cassandra/metrics + cassandra/query + cassandra/pool + cassandra/protocol + cassandra/encoder + cassandra/decoder + cassandra/concurrent + cassandra/connection + cassandra/util + cassandra/timestamps + cassandra/io/asyncioreactor + cassandra/io/asyncorereactor + cassandra/io/eventletreactor + cassandra/io/libevreactor + cassandra/io/geventreactor + cassandra/io/twistedreactor + +.. _om_api: + +Object Mapper +------------- +.. toctree:: + :maxdepth: 1 + + cassandra/cqlengine/models + cassandra/cqlengine/columns + cassandra/cqlengine/query + cassandra/cqlengine/connection + cassandra/cqlengine/management + cassandra/cqlengine/usertype + +DataStax Graph +-------------- +.. toctree:: + :maxdepth: 1 + + cassandra/datastax/graph/index + cassandra/datastax/graph/fluent/index + cassandra/datastax/graph/fluent/query + cassandra/datastax/graph/fluent/predicates diff --git a/stable/_sources/cqlengine/batches.rst.txt b/stable/_sources/cqlengine/batches.rst.txt new file mode 100644 index 0000000000..306e7d01a6 --- /dev/null +++ b/stable/_sources/cqlengine/batches.rst.txt @@ -0,0 +1,108 @@ +============= +Batch Queries +============= + +cqlengine supports batch queries using the BatchQuery class. Batch queries can be started and stopped manually, or within a context manager. To add queries to the batch object, you just need to precede the create/save/delete call with a call to batch, and pass in the batch object. + + +Batch Query General Use Pattern +=============================== + +You can only create, update, and delete rows with a batch query, attempting to read rows out of the database with a batch query will fail. + +.. code-block:: python + + from cassandra.cqlengine.query import BatchQuery + + #using a context manager + with BatchQuery() as b: + now = datetime.now() + em1 = ExampleModel.batch(b).create(example_type=0, description="1", created_at=now) + em2 = ExampleModel.batch(b).create(example_type=0, description="2", created_at=now) + em3 = ExampleModel.batch(b).create(example_type=0, description="3", created_at=now) + + # -- or -- + + #manually + b = BatchQuery() + now = datetime.now() + em1 = ExampleModel.batch(b).create(example_type=0, description="1", created_at=now) + em2 = ExampleModel.batch(b).create(example_type=0, description="2", created_at=now) + em3 = ExampleModel.batch(b).create(example_type=0, description="3", created_at=now) + b.execute() + + # updating in a batch + + b = BatchQuery() + em1.description = "new description" + em1.batch(b).save() + em2.description = "another new description" + em2.batch(b).save() + b.execute() + + # deleting in a batch + b = BatchQuery() + ExampleModel.objects(id=some_id).batch(b).delete() + ExampleModel.objects(id=some_id2).batch(b).delete() + b.execute() + + +Typically you will not want the block to execute if an exception occurs inside the `with` block. However, in the case that this is desirable, it's achievable by using the following syntax: + +.. code-block:: python + + with BatchQuery(execute_on_exception=True) as b: + LogEntry.batch(b).create(k=1, v=1) + mystery_function() # exception thrown in here + LogEntry.batch(b).create(k=1, v=2) # this code is never reached due to the exception, but anything leading up to here will execute in the batch. + +If an exception is thrown somewhere in the block, any statements that have been added to the batch will still be executed. This is useful for some logging situations. + +Batch Query Execution Callbacks +=============================== + +In order to allow secondary tasks to be chained to the end of batch, BatchQuery instances allow callbacks to be +registered with the batch, to be executed immediately after the batch executes. + +Multiple callbacks can be attached to same BatchQuery instance, they are executed in the same order that they +are added to the batch. + +The callbacks attached to a given batch instance are executed only if the batch executes. If the batch is used as a +context manager and an exception is raised, the queued up callbacks will not be run. + +.. code-block:: python + + def my_callback(*args, **kwargs): + pass + + batch = BatchQuery() + + batch.add_callback(my_callback) + batch.add_callback(my_callback, 'positional arg', named_arg='named arg value') + + # if you need reference to the batch within the callback, + # just trap it in the arguments to be passed to the callback: + batch.add_callback(my_callback, cqlengine_batch=batch) + + # once the batch executes... + batch.execute() + + # the effect of the above scheduled callbacks will be similar to + my_callback() + my_callback('positional arg', named_arg='named arg value') + my_callback(cqlengine_batch=batch) + +Failure in any of the callbacks does not affect the batch's execution, as the callbacks are started after the execution +of the batch is complete. + +Logged vs Unlogged Batches +--------------------------- +By default, queries in cqlengine are LOGGED, which carries additional overhead from UNLOGGED. To explicitly state which batch type to use, simply: + + +.. code-block:: python + + from cassandra.cqlengine.query import BatchType + with BatchQuery(batch_type=BatchType.Unlogged) as b: + LogEntry.batch(b).create(k=1, v=1) + LogEntry.batch(b).create(k=1, v=2) diff --git a/stable/_sources/cqlengine/connections.rst.txt b/stable/_sources/cqlengine/connections.rst.txt new file mode 100644 index 0000000000..03ade27521 --- /dev/null +++ b/stable/_sources/cqlengine/connections.rst.txt @@ -0,0 +1,137 @@ +=========== +Connections +=========== + +Connections aim to ease the use of multiple sessions with cqlengine. Connections can be set on a model class, per query or using a context manager. + + +Register a new connection +========================= + +To use cqlengine, you need at least a default connection. If you initialize cqlengine's connections with with :func:`connection.setup <.connection.setup>`, a connection will be created automatically. If you want to use another cluster/session, you need to register a new cqlengine connection. You register a connection with :func:`~.connection.register_connection`: + +.. code-block:: python + + from cassandra.cqlengine import connection + + connection.setup(['127.0.0.1') + connection.register_connection('cluster2', ['127.0.0.2']) + +:func:`~.connection.register_connection` can take a list of hosts, as shown above, in which case it will create a connection with a new session. It can also take a `session` argument if you've already created a session: + +.. code-block:: python + + from cassandra.cqlengine import connection + from cassandra.cluster import Cluster + + session = Cluster(['127.0.0.1']).connect() + connection.register_connection('cluster3', session=session) + + +Change the default connection +============================= + +You can change the default cqlengine connection on registration: + +.. code-block:: python + + from cassandra.cqlengine import connection + + connection.register_connection('cluster2', ['127.0.0.2'] default=True) + +or on the fly using :func:`~.connection.set_default_connection` + +.. code-block:: python + + connection.set_default_connection('cluster2') + +Unregister a connection +======================= + +You can unregister a connection using :func:`~.connection.unregister_connection`: + +.. code-block:: python + + connection.unregister_connection('cluster2') + +Management +========== + +When using multiples connections, you also need to sync your models on all connections (and keyspaces) that you need operate on. Management commands have been improved to ease this part. Here is an example: + +.. code-block:: python + + from cassandra.cqlengine import management + + keyspaces = ['ks1', 'ks2'] + conns = ['cluster1', 'cluster2'] + + # registers your connections + # ... + + # create all keyspaces on all connections + for ks in keyspaces: + management.create_simple_keyspace(ks, connections=conns) + + # define your Automobile model + # ... + + # sync your models + management.sync_table(Automobile, keyspaces=keyspaces, connections=conns) + + +Connection Selection +==================== + +cqlengine will select the default connection, unless your specify a connection using one of the following methods. + +Default Model Connection +------------------------ + +You can specify a default connection per model: + +.. code-block:: python + + class Automobile(Model): + __keyspace__ = 'test' + __connection__ = 'cluster2' + manufacturer = columns.Text(primary_key=True) + year = columns.Integer(primary_key=True) + model = columns.Text(primary_key=True) + + print len(Automobile.objects.all()) # executed on the connection 'cluster2' + +QuerySet and model instance +--------------------------- + +You can use the :attr:`using() <.query.ModelQuerySet.using>` method to select a connection (or keyspace): + +.. code-block:: python + + Automobile.objects.using(connection='cluster1').create(manufacturer='honda', year=2010, model='civic') + q = Automobile.objects.filter(manufacturer='Tesla') + autos = q.using(keyspace='ks2', connection='cluster2').all() + + for auto in autos: + auto.using(connection='cluster1').save() + +Context Manager +--------------- + +You can use the ContextQuery as well to select a connection: + +.. code-block:: python + + with ContextQuery(Automobile, connection='cluster1') as A: + A.objects.filter(manufacturer='honda').all() # executed on 'cluster1' + + +BatchQuery +---------- + +With a BatchQuery, you can select the connection with the context manager. Note that all operations in the batch need to use the same connection. + +.. code-block:: python + + with BatchQuery(connection='cluster1') as b: + Automobile.objects.batch(b).create(manufacturer='honda', year=2010, model='civic') diff --git a/stable/_sources/cqlengine/faq.rst.txt b/stable/_sources/cqlengine/faq.rst.txt new file mode 100644 index 0000000000..6c056d02ea --- /dev/null +++ b/stable/_sources/cqlengine/faq.rst.txt @@ -0,0 +1,67 @@ +========================== +Frequently Asked Questions +========================== + +Why don't updates work correctly on models instantiated as Model(field=value, field2=value2)? +------------------------------------------------------------------------------------------------ + +The recommended way to create new rows is with the models .create method. The values passed into a model's init method are interpreted by the model as the values as they were read from a row. This allows the model to "know" which rows have changed since the row was read out of cassandra, and create suitable update statements. + +How to preserve ordering in batch query? +------------------------------------------- + +Statement Ordering is not supported by CQL3 batches. Therefore, +once cassandra needs resolving conflict(Updating the same column in one batch), +The algorithm below would be used. + +* If timestamps are different, pick the column with the largest timestamp (the value being a regular column or a tombstone) +* If timestamps are the same, and one of the columns in a tombstone ('null') - pick the tombstone +* If timestamps are the same, and none of the columns are tombstones, pick the column with the largest value + +Below is an example to show this scenario. + +.. code-block:: python + + class MyMode(Model): + id = columns.Integer(primary_key=True) + count = columns.Integer() + text = columns.Text() + + with BatchQuery() as b: + MyModel.batch(b).create(id=1, count=2, text='123') + MyModel.batch(b).create(id=1, count=3, text='111') + + assert MyModel.objects(id=1).first().count == 3 + assert MyModel.objects(id=1).first().text == '123' + +The largest value of count is 3, and the largest value of text would be '123'. + +The workaround is applying timestamp to each statement, then Cassandra would +resolve to the statement with the lastest timestamp. + +.. code-block:: python + + with BatchQuery() as b: + MyModel.timestamp(datetime.now()).batch(b).create(id=1, count=2, text='123') + MyModel.timestamp(datetime.now()).batch(b).create(id=1, count=3, text='111') + + assert MyModel.objects(id=1).first().count == 3 + assert MyModel.objects(id=1).first().text == '111' + +How can I delete individual values from a row? +------------------------------------------------- + +When inserting with CQLEngine, ``None`` is equivalent to CQL ``NULL`` or to +issuing a ``DELETE`` on that column. For example: + +.. code-block:: python + + class MyModel(Model): + id = columns.Integer(primary_key=True) + text = columns.Text() + + m = MyModel.create(id=1, text='We can delete this with None') + assert MyModel.objects(id=1).first().text is not None + + m.update(text=None) + assert MyModel.objects(id=1).first().text is None diff --git a/stable/_sources/cqlengine/models.rst.txt b/stable/_sources/cqlengine/models.rst.txt new file mode 100644 index 0000000000..c0ba390119 --- /dev/null +++ b/stable/_sources/cqlengine/models.rst.txt @@ -0,0 +1,218 @@ +====== +Models +====== + +.. module:: cqlengine.models + +A model is a python class representing a CQL table. Models derive from :class:`Model`, and +define basic table properties and columns for a table. + +Columns in your models map to columns in your CQL table. You define CQL columns by defining column attributes on your model classes. +For a model to be valid it needs at least one primary key column and one non-primary key column. Just as in CQL, the order you define +your columns in is important, and is the same order they are defined in on a model's corresponding table. + +Some basic examples defining models are shown below. Consult the :doc:`Model API docs ` and :doc:`Column API docs ` for complete details. + +Example Definitions +=================== + +This example defines a ``Person`` table, with the columns ``first_name`` and ``last_name`` + +.. code-block:: python + + from cassandra.cqlengine import columns + from cassandra.cqlengine.models import Model + + class Person(Model): + id = columns.UUID(primary_key=True) + first_name = columns.Text() + last_name = columns.Text() + + +The Person model would create this CQL table: + +.. code-block:: sql + + CREATE TABLE cqlengine.person ( + id uuid, + first_name text, + last_name text, + PRIMARY KEY (id) + ); + +Here's an example of a comment table created with clustering keys, in descending order: + +.. code-block:: python + + from cassandra.cqlengine import columns + from cassandra.cqlengine.models import Model + + class Comment(Model): + photo_id = columns.UUID(primary_key=True) + comment_id = columns.TimeUUID(primary_key=True, clustering_order="DESC") + comment = columns.Text() + +The Comment model's ``create table`` would look like the following: + +.. code-block:: sql + + CREATE TABLE comment ( + photo_id uuid, + comment_id timeuuid, + comment text, + PRIMARY KEY (photo_id, comment_id) + ) WITH CLUSTERING ORDER BY (comment_id DESC); + +To sync the models to the database, you may do the following*: + +.. code-block:: python + + from cassandra.cqlengine.management import sync_table + sync_table(Person) + sync_table(Comment) + +\*Note: synchronizing models causes schema changes, and should be done with caution. +Please see the discussion in :doc:`/api/cassandra/cqlengine/management` for considerations. + +For examples on manipulating data and creating queries, see :doc:`queryset` + +Manipulating model instances as dictionaries +============================================ + +Model instances can be accessed like dictionaries. + +.. code-block:: python + + class Person(Model): + first_name = columns.Text() + last_name = columns.Text() + + kevin = Person.create(first_name="Kevin", last_name="Deldycke") + dict(kevin) # returns {'first_name': 'Kevin', 'last_name': 'Deldycke'} + kevin['first_name'] # returns 'Kevin' + kevin.keys() # returns ['first_name', 'last_name'] + kevin.values() # returns ['Kevin', 'Deldycke'] + kevin.items() # returns [('first_name', 'Kevin'), ('last_name', 'Deldycke')] + + kevin['first_name'] = 'KEVIN5000' # changes the models first name + +Extending Model Validation +========================== + +Each time you save a model instance in cqlengine, the data in the model is validated against the schema you've defined +for your model. Most of the validation is fairly straightforward, it basically checks that you're not trying to do +something like save text into an integer column, and it enforces the ``required`` flag set on column definitions. +It also performs any transformations needed to save the data properly. + +However, there are often additional constraints or transformations you want to impose on your data, beyond simply +making sure that Cassandra won't complain when you try to insert it. To define additional validation on a model, +extend the model's validation method: + +.. code-block:: python + + class Member(Model): + person_id = UUID(primary_key=True) + name = Text(required=True) + + def validate(self): + super(Member, self).validate() + if self.name == 'jon': + raise ValidationError('no jon\'s allowed') + +*Note*: while not required, the convention is to raise a ``ValidationError`` (``from cassandra.cqlengine import ValidationError``) +if validation fails. + +.. _model_inheritance: + +Model Inheritance +================= +It is possible to save and load different model classes using a single CQL table. +This is useful in situations where you have different object types that you want to store in a single cassandra row. + +For instance, suppose you want a table that stores rows of pets owned by an owner: + +.. code-block:: python + + class Pet(Model): + __table_name__ = 'pet' + owner_id = UUID(primary_key=True) + pet_id = UUID(primary_key=True) + pet_type = Text(discriminator_column=True) + name = Text() + + def eat(self, food): + pass + + def sleep(self, time): + pass + + class Cat(Pet): + __discriminator_value__ = 'cat' + cuteness = Float() + + def tear_up_couch(self): + pass + + class Dog(Pet): + __discriminator_value__ = 'dog' + fierceness = Float() + + def bark_all_night(self): + pass + +After calling ``sync_table`` on each of these tables, the columns defined in each model will be added to the +``pet`` table. Additionally, saving ``Cat`` and ``Dog`` models will save the meta data needed to identify each row +as either a cat or dog. + +To setup a model structure with inheritance, follow these steps + +1. Create a base model with a column set as the distriminator (``distriminator_column=True`` in the column definition) +2. Create subclass models, and define a unique ``__discriminator_value__`` value on each +3. Run ``sync_table`` on each of the sub tables + +**About the discriminator value** + +The discriminator value is what cqlengine uses under the covers to map logical cql rows to the appropriate model type. The +base model maintains a map of discriminator values to subclasses. When a specialized model is saved, its discriminator value is +automatically saved into the discriminator column. The discriminator column may be any column type except counter and container types. +Additionally, if you set ``index=True`` on your discriminator column, you can execute queries against specialized subclasses, and a +``WHERE`` clause will be automatically added to your query, returning only rows of that type. Note that you must +define a unique ``__discriminator_value__`` to each subclass, and that you can only assign a single discriminator column per model. + +.. _user_types: + +User Defined Types +================== +cqlengine models User Defined Types (UDTs) much like tables, with fields defined by column type attributes. However, UDT instances +are only created, presisted, and queried via table Models. A short example to introduce the pattern:: + + from cassandra.cqlengine.columns import * + from cassandra.cqlengine.models import Model + from cassandra.cqlengine.usertype import UserType + + class address(UserType): + street = Text() + zipcode = Integer() + + class users(Model): + __keyspace__ = 'account' + name = Text(primary_key=True) + addr = UserDefinedType(address) + + users.create(name="Joe", addr=address(street="Easy St.", zipcode=99999)) + user = users.objects(name="Joe")[0] + print user.name, user.addr + # Joe address(street=u'Easy St.', zipcode=99999) + +UDTs are modeled by inheriting :class:`~.usertype.UserType`, and setting column type attributes. Types are then used in defining +models by declaring a column of type :class:`~.columns.UserDefinedType`, with the ``UserType`` class as a parameter. + +``sync_table`` will implicitly +synchronize any types contained in the table. Alternatively :func:`~.management.sync_type` can be used to create/alter types +explicitly. + +Upon declaration, types are automatically registered with the driver, so query results return instances of your ``UserType`` +class*. + +***Note**: UDTs were not added to the native protocol until v3. When setting up the cqlengine connection, be sure to specify +``protocol_version=3``. If using an earlier version, UDT queries will still work, but the returned type will be a namedtuple. diff --git a/stable/_sources/cqlengine/queryset.rst.txt b/stable/_sources/cqlengine/queryset.rst.txt new file mode 100644 index 0000000000..375ea22316 --- /dev/null +++ b/stable/_sources/cqlengine/queryset.rst.txt @@ -0,0 +1,419 @@ +============== +Making Queries +============== + +.. module:: cqlengine.queryset + +Retrieving objects +================== +Once you've populated Cassandra with data, you'll probably want to retrieve some of it. This is accomplished with QuerySet objects. This section will describe how to use QuerySet objects to retrieve the data you're looking for. + +Retrieving all objects +---------------------- +The simplest query you can make is to return all objects from a table. + +This is accomplished with the ``.all()`` method, which returns a QuerySet of all objects in a table + +Using the Person example model, we would get all Person objects like this: + +.. code-block:: python + + all_objects = Person.objects.all() + +.. _retrieving-objects-with-filters: + +Retrieving objects with filters +------------------------------- +Typically, you'll want to query only a subset of the records in your database. + +That can be accomplished with the QuerySet's ``.filter(\*\*)`` method. + +For example, given the model definition: + +.. code-block:: python + + class Automobile(Model): + manufacturer = columns.Text(primary_key=True) + year = columns.Integer(primary_key=True) + model = columns.Text() + price = columns.Decimal() + options = columns.Set(columns.Text) + +...and assuming the Automobile table contains a record of every car model manufactured in the last 20 years or so, we can retrieve only the cars made by a single manufacturer like this: + + +.. code-block:: python + + q = Automobile.objects.filter(manufacturer='Tesla') + +You can also use the more convenient syntax: + +.. code-block:: python + + q = Automobile.objects(Automobile.manufacturer == 'Tesla') + +We can then further filter our query with another call to **.filter** + +.. code-block:: python + + q = q.filter(year=2012) + +*Note: all queries involving any filtering MUST define either an '=' or an 'in' relation to either a primary key column, or an indexed column.* + +Accessing objects in a QuerySet +=============================== + +There are several methods for getting objects out of a queryset + +* iterating over the queryset + .. code-block:: python + + for car in Automobile.objects.all(): + #...do something to the car instance + pass + +* list index + .. code-block:: python + + q = Automobile.objects.all() + q[0] #returns the first result + q[1] #returns the second result + + .. note:: + + * CQL does not support specifying a start position in it's queries. Therefore, accessing elements using array indexing will load every result up to the index value requested + * Using negative indices requires a "SELECT COUNT()" to be executed. This has a performance cost on large datasets. + +* list slicing + .. code-block:: python + + q = Automobile.objects.all() + q[1:] #returns all results except the first + q[1:9] #returns a slice of the results + + .. note:: + + * CQL does not support specifying a start position in it's queries. Therefore, accessing elements using array slicing will load every result up to the index value requested + * Using negative indices requires a "SELECT COUNT()" to be executed. This has a performance cost on large datasets. + +* calling :attr:`get() ` on the queryset + .. code-block:: python + + q = Automobile.objects.filter(manufacturer='Tesla') + q = q.filter(year=2012) + car = q.get() + + this returns the object matching the queryset + +* calling :attr:`first() ` on the queryset + .. code-block:: python + + q = Automobile.objects.filter(manufacturer='Tesla') + q = q.filter(year=2012) + car = q.first() + + this returns the first value in the queryset + +.. _query-filtering-operators: + +Filtering Operators +=================== + +:attr:`Equal To ` + +The default filtering operator. + +.. code-block:: python + + q = Automobile.objects.filter(manufacturer='Tesla') + q = q.filter(year=2012) #year == 2012 + +In addition to simple equal to queries, cqlengine also supports querying with other operators by appending a ``__`` to the field name on the filtering call + +:attr:`in (__in) ` + +.. code-block:: python + + q = Automobile.objects.filter(manufacturer='Tesla') + q = q.filter(year__in=[2011, 2012]) + + +:attr:`> (__gt) ` + +.. code-block:: python + + q = Automobile.objects.filter(manufacturer='Tesla') + q = q.filter(year__gt=2010) # year > 2010 + + # or the nicer syntax + + q.filter(Automobile.year > 2010) + +:attr:`>= (__gte) ` + +.. code-block:: python + + q = Automobile.objects.filter(manufacturer='Tesla') + q = q.filter(year__gte=2010) # year >= 2010 + + # or the nicer syntax + + q.filter(Automobile.year >= 2010) + +:attr:`< (__lt) ` + +.. code-block:: python + + q = Automobile.objects.filter(manufacturer='Tesla') + q = q.filter(year__lt=2012) # year < 2012 + + # or... + + q.filter(Automobile.year < 2012) + +:attr:`<= (__lte) ` + +.. code-block:: python + + q = Automobile.objects.filter(manufacturer='Tesla') + q = q.filter(year__lte=2012) # year <= 2012 + + q.filter(Automobile.year <= 2012) + +:attr:`CONTAINS (__contains) ` + +The CONTAINS operator is available for all collection types (List, Set, Map). + +.. code-block:: python + + q = Automobile.objects.filter(manufacturer='Tesla') + q.filter(options__contains='backup camera').allow_filtering() + +Note that we need to use allow_filtering() since the *options* column has no secondary index. + +:attr:`LIKE (__like) ` + +The LIKE operator is available for text columns that have a SASI secondary index. + +.. code-block:: python + + q = Automobile.objects.filter(model__like='%Civic%').allow_filtering() + +:attr:`IS NOT NULL (IsNotNull(column_name)) ` + +The IS NOT NULL operator is not yet supported for C*. + +.. code-block:: python + + q = Automobile.objects.filter(IsNotNull('model')) + +Limitations: + +- Currently, cqlengine does not support SASI index creation. To use this feature, you need to create the SASI index using the core driver. +- Queries using LIKE must use allow_filtering() since the *model* column has no standard secondary index. Note that the server will use the SASI index properly when executing the query. + +TimeUUID Functions +================== + +In addition to querying using regular values, there are two functions you can pass in when querying TimeUUID columns to help make filtering by them easier. Note that these functions don't actually return a value, but instruct the cql interpreter to use the functions in it's query. + +.. class:: MinTimeUUID(datetime) + + returns the minimum time uuid value possible for the given datetime + +.. class:: MaxTimeUUID(datetime) + + returns the maximum time uuid value possible for the given datetime + +*Example* + +.. code-block:: python + + class DataStream(Model): + id = columns.UUID(partition_key=True) + time = columns.TimeUUID(primary_key=True) + data = columns.Bytes() + + min_time = datetime(1982, 1, 1) + max_time = datetime(1982, 3, 9) + + DataStream.filter(time__gt=functions.MinTimeUUID(min_time), time__lt=functions.MaxTimeUUID(max_time)) + +Token Function +============== + +Token functon may be used only on special, virtual column pk__token, representing token of partition key (it also works for composite partition keys). +Cassandra orders returned items by value of partition key token, so using cqlengine.Token we can easy paginate through all table rows. + +See http://cassandra.apache.org/doc/cql3/CQL-3.0.html#tokenFun + +*Example* + +.. code-block:: python + + class Items(Model): + id = columns.Text(primary_key=True) + data = columns.Bytes() + + query = Items.objects.all().limit(10) + + first_page = list(query); + last = first_page[-1] + next_page = list(query.filter(pk__token__gt=cqlengine.Token(last.pk))) + +QuerySets are immutable +======================= + +When calling any method that changes a queryset, the method does not actually change the queryset object it's called on, but returns a new queryset object with the attributes of the original queryset, plus the attributes added in the method call. + +*Example* + +.. code-block:: python + + #this produces 3 different querysets + #q does not change after it's initial definition + q = Automobiles.objects.filter(year=2012) + tesla2012 = q.filter(manufacturer='Tesla') + honda2012 = q.filter(manufacturer='Honda') + +Ordering QuerySets +================== + +Since Cassandra is essentially a distributed hash table on steroids, the order you get records back in will not be particularly predictable. + +However, you can set a column to order on with the ``.order_by(column_name)`` method. + +*Example* + +.. code-block:: python + + #sort ascending + q = Automobiles.objects.all().order_by('year') + #sort descending + q = Automobiles.objects.all().order_by('-year') + +*Note: Cassandra only supports ordering on a clustering key. In other words, to support ordering results, your model must have more than one primary key, and you must order on a primary key, excluding the first one.* + +*For instance, given our Automobile model, year is the only column we can order on.* + +Values Lists +============ + +There is a special QuerySet's method ``.values_list()`` - when called, QuerySet returns lists of values instead of model instances. It may significantly speedup things with lower memory footprint for large responses. +Each tuple contains the value from the respective field passed into the ``values_list()`` call — so the first item is the first field, etc. For example: + +.. code-block:: python + + items = list(range(20)) + random.shuffle(items) + for i in items: + TestModel.create(id=1, clustering_key=i) + + values = list(TestModel.objects.values_list('clustering_key', flat=True)) + # [19L, 18L, 17L, 16L, 15L, 14L, 13L, 12L, 11L, 10L, 9L, 8L, 7L, 6L, 5L, 4L, 3L, 2L, 1L, 0L] + +Per Query Timeouts +=================== + +By default all queries are executed with the timeout defined in `~cqlengine.connection.setup()` +The examples below show how to specify a per-query timeout. +A timeout is specified in seconds and can be an int, float or None. +None means no timeout. + + +.. code-block:: python + + class Row(Model): + id = columns.Integer(primary_key=True) + name = columns.Text() + + +Fetch all objects with a timeout of 5 seconds + +.. code-block:: python + + Row.objects().timeout(5).all() + +Create a single row with a 50ms timeout + +.. code-block:: python + + Row(id=1, name='Jon').timeout(0.05).create() + +Delete a single row with no timeout + +.. code-block:: python + + Row(id=1).timeout(None).delete() + +Update a single row with no timeout + +.. code-block:: python + + Row(id=1).timeout(None).update(name='Blake') + +Batch query timeouts + +.. code-block:: python + + with BatchQuery(timeout=10) as b: + Row(id=1, name='Jon').create() + + +NOTE: You cannot set both timeout and batch at the same time, batch will use the timeout defined in it's constructor. +Setting the timeout on the model is meaningless and will raise an AssertionError. + + +.. _ttl-change: + +Default TTL and Per Query TTL +============================= + +Model default TTL now relies on the *default_time_to_live* feature, introduced in Cassandra 2.0. It is not handled anymore in the CQLEngine Model (scylla-driver >=3.6). You can set the default TTL of a table like this: + +Example: + +.. code-block:: python + + class User(Model): + __options__ = {'default_time_to_live': 20} + + user_id = columns.UUID(primary_key=True) + ... + +You can set TTL per-query if needed. Here are a some examples: + +Example: + +.. code-block:: python + + class User(Model): + __options__ = {'default_time_to_live': 20} + + user_id = columns.UUID(primary_key=True) + ... + + user = User.objects.create(user_id=1) # Default TTL 20 will be set automatically on the server + + user.ttl(30).update(age=21) # Update the TTL to 30 + User.objects.ttl(10).create(user_id=1) # TTL 10 + User(user_id=1, age=21).ttl(10).save() # TTL 10 + + +Named Tables +=================== + +Named tables are a way of querying a table without creating an class. They're useful for querying system tables or exploring an unfamiliar database. + + +.. code-block:: python + + from cassandra.cqlengine.connection import setup + setup("127.0.0.1", "cqlengine_test") + + from cassandra.cqlengine.named import NamedTable + user = NamedTable("cqlengine_test", "user") + user.objects() + user.objects()[0] + + # {u'pk': 1, u't': datetime.datetime(2014, 6, 26, 17, 10, 31, 774000)} diff --git a/stable/_sources/cqlengine/third-party.rst.txt b/stable/_sources/cqlengine/third-party.rst.txt new file mode 100644 index 0000000000..20c26df304 --- /dev/null +++ b/stable/_sources/cqlengine/third-party.rst.txt @@ -0,0 +1,64 @@ +======================== +Third party integrations +======================== + + +Celery +------ + +Here's how, in substance, CQLengine can be plugged to `Celery +`_: + +.. code-block:: python + + from celery import Celery + from celery.signals import worker_process_init, beat_init + from cassandra.cqlengine import connection + from cassandra.cqlengine.connection import ( + cluster as cql_cluster, session as cql_session) + + def cassandra_init(**kwargs): + """ Initialize a clean Cassandra connection. """ + if cql_cluster is not None: + cql_cluster.shutdown() + if cql_session is not None: + cql_session.shutdown() + connection.setup() + + # Initialize worker context for both standard and periodic tasks. + worker_process_init.connect(cassandra_init) + beat_init.connect(cassandra_init) + + app = Celery() + + +uWSGI +----- + +This is the code required for proper connection handling of CQLengine for a +`uWSGI `_-run application: + +.. code-block:: python + + from cassandra.cqlengine import connection + from cassandra.cqlengine.connection import ( + cluster as cql_cluster, session as cql_session) + + try: + from uwsgidecorators import postfork + except ImportError: + # We're not in a uWSGI context, no need to hook Cassandra session + # initialization to the postfork event. + pass + else: + @postfork + def cassandra_init(**kwargs): + """ Initialize a new Cassandra session in the context. + + Ensures that a new session is returned for every new request. + """ + if cql_cluster is not None: + cql_cluster.shutdown() + if cql_session is not None: + cql_session.shutdown() + connection.setup() diff --git a/stable/_sources/cqlengine/upgrade-guide.rst.txt b/stable/_sources/cqlengine/upgrade-guide.rst.txt new file mode 100644 index 0000000000..5a10ebb757 --- /dev/null +++ b/stable/_sources/cqlengine/upgrade-guide.rst.txt @@ -0,0 +1,155 @@ +======================== +Upgrade Guide +======================== + +This is an overview of things that changed as the cqlengine project was merged into +scylla-driver. While efforts were taken to preserve the API and most functionality exactly, +conversion to this package will still require certain minimal updates (namely, imports). + +**THERE IS ONE FUNCTIONAL CHANGE**, described in the first section below. + +Functional Changes +================== +List Prepend Reversing +---------------------- +Legacy cqlengine included a workaround for a Cassandra bug in which prepended list segments were +reversed (`CASSANDRA-8733 `_). As of +this integration, this workaround is removed. The first released integrated version emits +a warning when prepend is used. Subsequent versions will have this warning removed. + +Date Column Type +---------------- +The Date column type in legacy cqlengine used a ``timestamp`` CQL type and truncated the time. +Going forward, the :class:`~.columns.Date` type represents a ``date`` for Cassandra 2.2+ +(`PYTHON-245 `_). +Users of the legacy functionality should convert models to use :class:`~.columns.DateTime` (which +uses ``timestamp`` internally), and use the build-in ``datetime.date`` for input values. + +Remove cqlengine +================ +To avoid confusion or mistakes using the legacy package in your application, it +is prudent to remove the cqlengine package when upgrading to the integrated version. + +The driver setup script will warn if the legacy package is detected during install, +but it will not prevent side-by-side installation. + +Organization +============ +Imports +------- +cqlengine is now integrated as a sub-package of the driver base package 'cassandra'. +Upgrading will require adjusting imports to cqlengine. For example:: + + from cassandra.cqlengine import columns + +is now:: + + from cassandra.cqlengine import columns + +Package-Level Aliases +--------------------- +Legacy cqlengine defined a number of aliases at the package level, which became redundant +when the package was integrated for a driver. These have been removed in favor of absolute +imports, and referring to cannonical definitions. For example, ``cqlengine.ONE`` was an alias +of ``cassandra.ConsistencyLevel.ONE``. In the integrated package, only the +:class:`cassandra.ConsistencyLevel` remains. + +Additionally, submodule aliases are removed from cqlengine in favor of absolute imports. + +These aliases are removed, and not deprecated because they should be straightforward to iron out +at module load time. + +Exceptions +---------- +The legacy cqlengine.exceptions module had a number of Exception classes that were variously +common to the package, or only used in specific modules. Common exceptions were relocated to +cqlengine, and specialized exceptions were placed in the module that raises them. Below is a +listing of updated locations: + +============================ ========== +Exception class New module +============================ ========== +CQLEngineException cassandra.cqlengine +ModelException cassandra.cqlengine.models +ValidationError cassandra.cqlengine +UndefinedKeyspaceException cassandra.cqlengine.connection +LWTException cassandra.cqlengine.query +IfNotExistsWithCounterColumn cassandra.cqlengine.query +============================ ========== + +UnicodeMixin Consolidation +-------------------------- +``class UnicodeMixin`` was defined in several cqlengine modules. This has been consolidated +to a single definition in the cqlengine package init file. This is not technically part of +the API, but noted here for completeness. + +API Deprecations +================ +This upgrade served as a good juncture to deprecate certain API features and invite users to upgrade +to new ones. The first released version does not change functionality -- only introduces deprecation +warnings. Future releases will remove these features in favor of the alternatives. + +Float/Double Overload +--------------------- +Previously there was no ``Double`` column type. Doubles were modeled by specifying ``Float(double_precision=True)``. +This inititializer parameter is now deprecated. Applications should use :class:`~.columns.Double` for CQL ``double``, and :class:`~.columns.Float` +for CQL ``float``. + +Schema Management +----------------- +``cassandra.cqlengine.management.create_keyspace`` is deprecated. Instead, use the new replication-strategy-specific +functions that accept explicit options for known strategies: + +- :func:`~.create_keyspace_simple` +- :func:`~.create_keyspace_network_topology` + +``cassandra.cqlengine.management.delete_keyspace`` is deprecated in favor of a new function, :func:`~.drop_keyspace`. The +intent is simply to make the function match the CQL verb it invokes. + +Model Inheritance +----------------- +The names for class attributes controlling model inheritance are changing. Changes are as follows: + +- Replace 'polymorphic_key' in the base class Column definition with :attr:`~.discriminator_column` +- Replace the '__polymorphic_key__' class attribute the derived classes with :attr:`~.__discriminator_value__` + +The functionality is unchanged -- the intent here is to make the names and language around these attributes more precise. +For now, the old names are just deprecated, and the mapper will emit warnings if they are used. The old names +will be removed in a future version. + +The example below shows a simple translation: + +Before:: + + class Pet(Model): + __table_name__ = 'pet' + owner_id = UUID(primary_key=True) + pet_id = UUID(primary_key=True) + pet_type = Text(polymorphic_key=True) + name = Text() + + class Cat(Pet): + __polymorphic_key__ = 'cat' + + class Dog(Pet): + __polymorphic_key__ = 'dog' + +After:: + + class Pet(models.Model): + __table_name__ = 'pet' + owner_id = UUID(primary_key=True) + pet_id = UUID(primary_key=True) + pet_type = Text(discriminator_column=True) + name = Text() + + class Cat(Pet): + __discriminator_value__ = 'cat' + + class Dog(Pet): + __discriminator_value__ = 'dog' + + +TimeUUID.from_datetime +---------------------- +This function is deprecated in favor of the core utility function :func:`~.uuid_from_time`. diff --git a/stable/_sources/dates-and-times.rst.txt b/stable/_sources/dates-and-times.rst.txt new file mode 100644 index 0000000000..7a89f77437 --- /dev/null +++ b/stable/_sources/dates-and-times.rst.txt @@ -0,0 +1,87 @@ +Working with Dates and Times +============================ + +This document is meant to provide on overview of the assumptions and limitations of the driver time handling, the +reasoning behind it, and describe approaches to working with these types. + +timestamps (Cassandra DateType) +------------------------------- + +Timestamps in Cassandra are timezone-naive timestamps encoded as millseconds since UNIX epoch. Clients working with +timestamps in this database usually find it easiest to reason about them if they are always assumed to be UTC. To quote the +pytz documentation, "The preferred way of dealing with times is to always work in UTC, converting to localtime only when +generating output to be read by humans." The driver adheres to this tenant, and assumes UTC is always in the database. The +driver attempts to make this correct on the way in, and assumes no timezone on the way out. + +Write Path +~~~~~~~~~~ +When inserting timestamps, the driver handles serialization for the write path as follows: + +If the input is a ``datetime.datetime``, the serialization is normalized by starting with the ``utctimetuple()`` of the +value. + +- If the ``datetime`` object is timezone-aware, the timestamp is shifted, and represents the UTC timestamp equivalent. +- If the ``datetime`` object is timezone-naive, this results in no shift -- any ``datetime`` with no timezone information is assumed to be UTC + +Note the second point above applies even to "local" times created using ``now()``:: + + >>> d = datetime.now() + + >>> print(d.tzinfo) + None + + +These do not contain timezone information intrinsically, so they will be assumed to be UTC and not shifted. When generating +timestamps in the application, it is clearer to use ``datetime.utcnow()`` to be explicit about it. + +If the input for a timestamp is numeric, it is assumed to be a epoch-relative millisecond timestamp, as specified in the +CQL spec -- no scaling or conversion is done. + +Read Path +~~~~~~~~~ +The driver always assumes persisted timestamps are UTC and makes no attempt to localize them. Returned values are +timezone-naive ``datetime.datetime``. We follow this approach because the datetime API has deficiencies around daylight +saving time, and the defacto package for handling this is a third-party package (we try to minimize external dependencies +and not make decisions for the integrator). + +The decision for how to handle timezones is left to the application. For the most part it is straightforward to apply +localization to the ``datetime``\s returned by queries. One prevalent method is to use pytz for localization:: + + import pytz + user_tz = pytz.timezone('US/Central') + timestamp_naive = row.ts + timestamp_utc = pytz.utc.localize(timestamp_naive) + timestamp_presented = timestamp_utc.astimezone(user_tz) + +This is the most robust approach (likely refactored into a function). If it is deemed too cumbersome to apply for all call +sites in the application, it is possible to patch the driver with custom deserialization for this type. However, doing +this depends depends some on internal APIs and what extensions are present, so we will only mention the possibility, and +not spell it out here. + +date, time (Cassandra DateType) +------------------------------- +Date and time in Cassandra are idealized markers, much like ``datetime.date`` and ``datetime.time`` in the Python standard +library. Unlike these Python implementations, the Cassandra encoding supports much wider ranges. To accommodate these +ranges without overflow, this driver returns these data in custom types: :class:`.util.Date` and :class:`.util.Time`. + +Write Path +~~~~~~~~~~ +For simple (not prepared) statements, the input values for each of these can be either a string literal or an encoded +integer. See `Working with dates `_ +or `Working with time `_ for details +on the encoding or string formats. + +For prepared statements, the driver accepts anything that can be used to construct the :class:`.util.Date` or +:class:`.util.Time` classes. See the linked API docs for details. + +Read Path +~~~~~~~~~ +The driver always returns custom types for ``date`` and ``time``. + +The driver returns :class:`.util.Date` for ``date`` in order to accommodate the wider range of values without overflow. +For applications working within the supported range of [``datetime.MINYEAR``, ``datetime.MAXYEAR``], these are easily +converted to standard ``datetime.date`` insances using :meth:`.Date.date`. + +The driver returns :class:`.util.Time` for ``time`` in order to retain nanosecond precision stored in the database. +For applications not concerned with this level of precision, these are easily converted to standard ``datetime.time`` +insances using :meth:`.Time.time`. diff --git a/stable/_sources/execution-profiles.rst.txt b/stable/_sources/execution-profiles.rst.txt new file mode 100644 index 0000000000..7be1a85e3f --- /dev/null +++ b/stable/_sources/execution-profiles.rst.txt @@ -0,0 +1,156 @@ +Execution Profiles +================== + +Execution profiles aim at making it easier to execute requests in different ways within +a single connected ``Session``. Execution profiles are being introduced to deal with the exploding number of +configuration options, especially as the database platform evolves more complex workloads. + +The legacy configuration remains intact, but legacy and Execution Profile APIs +cannot be used simultaneously on the same client ``Cluster``. Legacy configuration +will be removed in the next major release (4.0). + +An execution profile and its parameters should be unique across ``Cluster`` instances. +For example, an execution profile and its ``LoadBalancingPolicy`` should +not be applied to more than one ``Cluster`` instance. + +This document explains how Execution Profiles relate to existing settings, and shows how to use the new profiles for +request execution. + +Mapping Legacy Parameters to Profiles +------------------------------------- + +Execution profiles can inherit from :class:`.cluster.ExecutionProfile`, and currently provide the following options, +previously input from the noted attributes: + +- load_balancing_policy - :attr:`.Cluster.load_balancing_policy` +- request_timeout - :attr:`.Session.default_timeout`, optional :meth:`.Session.execute` parameter +- retry_policy - :attr:`.Cluster.default_retry_policy`, optional :attr:`.Statement.retry_policy` attribute +- consistency_level - :attr:`.Session.default_consistency_level`, optional :attr:`.Statement.consistency_level` attribute +- serial_consistency_level - :attr:`.Session.default_serial_consistency_level`, optional :attr:`.Statement.serial_consistency_level` attribute +- row_factory - :attr:`.Session.row_factory` attribute + +When using the new API, these parameters can be defined by instances of :class:`.cluster.ExecutionProfile`. + +Using Execution Profiles +------------------------ +Default +~~~~~~~ + +.. code:: python + + from cassandra.cluster import Cluster + cluster = Cluster() + session = cluster.connect() + local_query = 'SELECT rpc_address FROM system.local' + for _ in cluster.metadata.all_hosts(): + print session.execute(local_query)[0] + + +.. parsed-literal:: + + Row(rpc_address='127.0.0.2') + Row(rpc_address='127.0.0.1') + + +The default execution profile is built from Cluster parameters and default Session attributes. This profile matches existing default +parameters. + +Initializing cluster with profiles +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. code:: python + + from cassandra.cluster import ExecutionProfile + from cassandra.policies import WhiteListRoundRobinPolicy + + node1_profile = ExecutionProfile(load_balancing_policy=WhiteListRoundRobinPolicy(['127.0.0.1'])) + node2_profile = ExecutionProfile(load_balancing_policy=WhiteListRoundRobinPolicy(['127.0.0.2'])) + + profiles = {'node1': node1_profile, 'node2': node2_profile} + session = Cluster(execution_profiles=profiles).connect() + for _ in cluster.metadata.all_hosts(): + print session.execute(local_query, execution_profile='node1')[0] + + +.. parsed-literal:: + + Row(rpc_address='127.0.0.1') + Row(rpc_address='127.0.0.1') + + +.. code:: python + + for _ in cluster.metadata.all_hosts(): + print session.execute(local_query, execution_profile='node2')[0] + + +.. parsed-literal:: + + Row(rpc_address='127.0.0.2') + Row(rpc_address='127.0.0.2') + + +.. code:: python + + for _ in cluster.metadata.all_hosts(): + print session.execute(local_query)[0] + + +.. parsed-literal:: + + Row(rpc_address='127.0.0.2') + Row(rpc_address='127.0.0.1') + +Note that, even when custom profiles are injected, the default ``TokenAwarePolicy(DCAwareRoundRobinPolicy())`` is still +present. To override the default, specify a policy with the :data:`~.cluster.EXEC_PROFILE_DEFAULT` key. + +.. code:: python + + from cassandra.cluster import EXEC_PROFILE_DEFAULT + profile = ExecutionProfile(request_timeout=30) + cluster = Cluster(execution_profiles={EXEC_PROFILE_DEFAULT: profile}) + + +Adding named profiles +~~~~~~~~~~~~~~~~~~~~~ + +New profiles can be added constructing from scratch, or deriving from default: + +.. code:: python + + locked_execution = ExecutionProfile(load_balancing_policy=WhiteListRoundRobinPolicy(['127.0.0.1'])) + node1_profile = 'node1_whitelist' + cluster.add_execution_profile(node1_profile, locked_execution) + + for _ in cluster.metadata.all_hosts(): + print session.execute(local_query, execution_profile=node1_profile)[0] + + +.. parsed-literal:: + + Row(rpc_address='127.0.0.1') + Row(rpc_address='127.0.0.1') + +See :meth:`.Cluster.add_execution_profile` for details and optional parameters. + +Passing a profile instance without mapping +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +We also have the ability to pass profile instances to be used for execution, but not added to the mapping: + +.. code:: python + + from cassandra.query import tuple_factory + + tmp = session.execution_profile_clone_update('node1', request_timeout=100, row_factory=tuple_factory) + + print session.execute(local_query, execution_profile=tmp)[0] + print session.execute(local_query, execution_profile='node1')[0] + +.. parsed-literal:: + + ('127.0.0.1',) + Row(rpc_address='127.0.0.1') + +The new profile is a shallow copy, so the ``tmp`` profile shares a load balancing policy with one managed by the cluster. +If reference objects are to be updated in the clone, one would typically set those attributes to a new instance. diff --git a/stable/_sources/faq.rst.txt b/stable/_sources/faq.rst.txt new file mode 100644 index 0000000000..56cb648a24 --- /dev/null +++ b/stable/_sources/faq.rst.txt @@ -0,0 +1,83 @@ +Frequently Asked Questions +========================== + +See also :doc:`cqlengine FAQ ` + +Why do connections or IO operations timeout in my WSGI application? +------------------------------------------------------------------- +Depending on your application process model, it may be forking after driver Session is created. Most IO reactors do not handle this, and problems will manifest as timeouts. + +To avoid this, make sure to create sessions per process, after the fork. Using uWSGI and Flask for example: + +.. code-block:: python + + from flask import Flask + from uwsgidecorators import postfork + from cassandra.cluster import Cluster + + session = None + prepared = None + + @postfork + def connect(): + global session, prepared + session = Cluster().connect() + prepared = session.prepare("SELECT release_version FROM system.local WHERE key=?") + + app = Flask(__name__) + + @app.route('/') + def server_version(): + row = session.execute(prepared, ('local',))[0] + return row.release_version + +uWSGI provides a ``postfork`` hook you can use to create sessions and prepared statements after the child process forks. + +How do I trace a request? +------------------------- +Request tracing can be turned on for any request by setting ``trace=True`` in :meth:`.Session.execute_async`. View the results by waiting on the future, then :meth:`.ResponseFuture.get_query_trace`. +Since tracing is done asynchronously to the request, this method polls until the trace is complete before querying data. + +.. code-block:: python + + >>> future = session.execute_async("SELECT * FROM system.local", trace=True) + >>> result = future.result() + >>> trace = future.get_query_trace() + >>> for e in trace.events: + >>> print e.source_elapsed, e.description + + 0:00:00.000077 Parsing select * from system.local + 0:00:00.000153 Preparing statement + 0:00:00.000309 Computing ranges to query + 0:00:00.000368 Submitting range requests on 1 ranges with a concurrency of 1 (279.77142 rows per range expected) + 0:00:00.000422 Submitted 1 concurrent range requests covering 1 ranges + 0:00:00.000480 Executing seq scan across 1 sstables for (min(-9223372036854775808), min(-9223372036854775808)) + 0:00:00.000669 Read 1 live and 0 tombstone cells + 0:00:00.000755 Scanned 1 rows and matched 1 + +``trace`` is a :class:`QueryTrace` object. + +How do I determine the replicas for a query? +---------------------------------------------- +With prepared statements, the replicas are obtained by ``routing_key``, based on current cluster token metadata: + +.. code-block:: python + + >>> prepared = session.prepare("SELECT * FROM example.t WHERE key=?") + >>> bound = prepared.bind((1,)) + >>> replicas = cluster.metadata.get_replicas(bound.keyspace, bound.routing_key) + >>> for h in replicas: + >>> print h.address + 127.0.0.1 + 127.0.0.2 + +``replicas`` is a list of :class:`Host` objects. + +How does the driver manage request retries? +------------------------------------------- +By default, retries are managed by the :attr:`.Cluster.default_retry_policy` set on the session Cluster. It can also +be specialized per statement by setting :attr:`.Statement.retry_policy`. + +Retries are presently attempted on the same coordinator, but this may change in the future. + +Please see :class:`.policies.RetryPolicy` for further details. diff --git a/stable/_sources/getting-started.rst.txt b/stable/_sources/getting-started.rst.txt new file mode 100644 index 0000000000..59a2acbd04 --- /dev/null +++ b/stable/_sources/getting-started.rst.txt @@ -0,0 +1,479 @@ +Getting Started +=============== + +First, make sure you have the driver properly :doc:`installed `. + +Connecting to a Cluster +----------------------- +Before we can start executing any queries against a Cassandra cluster we need to setup +an instance of :class:`~.Cluster`. As the name suggests, you will typically have one +instance of :class:`~.Cluster` for each Cassandra cluster you want to interact +with. + +First, make sure you have the Cassandra driver properly :doc:`installed `. + +Connecting to Cassandra ++++++++++++++++++++++++ +The simplest way to create a :class:`~.Cluster` is like this: + +.. code-block:: python + + from cassandra.cluster import Cluster + + cluster = Cluster() + +This will attempt to connection to a Cassandra instance on your +local machine (127.0.0.1). You can also specify a list of IP +addresses for nodes in your cluster: + +.. code-block:: python + + from cassandra.cluster import Cluster + + cluster = Cluster(['192.168.0.1', '192.168.0.2']) + +The set of IP addresses we pass to the :class:`~.Cluster` is simply +an initial set of contact points. After the driver connects to one +of these nodes it will *automatically discover* the rest of the +nodes in the cluster and connect to them, so you don't need to list +every node in your cluster. + +If you need to use a non-standard port, use SSL, or customize the driver's +behavior in some other way, this is the place to do it: + +.. code-block:: python + + from cassandra.cluster import Cluster + cluster = Cluster(['192.168.0.1', '192.168.0.2'], port=..., ssl_context=...) + +Instantiating a :class:`~.Cluster` does not actually connect us to any nodes. +To establish connections and begin executing queries we need a +:class:`~.Session`, which is created by calling :meth:`.Cluster.connect()`: + +.. code-block:: python + + cluster = Cluster() + session = cluster.connect() + +Session Keyspace +---------------- +The :meth:`~.Cluster.connect()` method takes an optional ``keyspace`` argument +which sets the default keyspace for all queries made through that :class:`~.Session`: + +.. code-block:: python + + cluster = Cluster() + session = cluster.connect('mykeyspace') + +You can always change a Session's keyspace using :meth:`~.Session.set_keyspace` or +by executing a ``USE `` query: + +.. code-block:: python + + session.set_keyspace('users') + # or you can do this instead + session.execute('USE users') + +Execution Profiles +------------------ +Profiles are passed in by ``execution_profiles`` dict. + +In this case we can construct the base ``ExecutionProfile`` passing all attributes: + +.. code-block:: python + + from cassandra.cluster import Cluster, ExecutionProfile, EXEC_PROFILE_DEFAULT + from cassandra.policies import WhiteListRoundRobinPolicy, DowngradingConsistencyRetryPolicy + from cassandra.query import tuple_factory + + profile = ExecutionProfile( + load_balancing_policy=WhiteListRoundRobinPolicy(['127.0.0.1']), + retry_policy=DowngradingConsistencyRetryPolicy(), + consistency_level=ConsistencyLevel.LOCAL_QUORUM, + serial_consistency_level=ConsistencyLevel.LOCAL_SERIAL, + request_timeout=15, + row_factory=tuple_factory + ) + cluster = Cluster(execution_profiles={EXEC_PROFILE_DEFAULT: profile}) + session = cluster.connect() + + print(session.execute("SELECT release_version FROM system.local").one()) + +Users are free to setup additional profiles to be used by name: + +.. code-block:: python + + profile_long = ExecutionProfile(request_timeout=30) + cluster = Cluster(execution_profiles={'long': profile_long}) + session = cluster.connect() + session.execute(statement, execution_profile='long') + +Also, parameters passed to ``Session.execute`` or attached to ``Statement``\s are still honored as before. + +Executing Queries +----------------- +Now that we have a :class:`.Session` we can begin to execute queries. The simplest +way to execute a query is to use :meth:`~.Session.execute()`: + +.. code-block:: python + + rows = session.execute('SELECT name, age, email FROM users') + for user_row in rows: + print user_row.name, user_row.age, user_row.email + +This will transparently pick a Cassandra node to execute the query against +and handle any retries that are necessary if the operation fails. + +By default, each row in the result set will be a +`namedtuple `_. +Each row will have a matching attribute for each column defined in the schema, +such as ``name``, ``age``, and so on. You can also treat them as normal tuples +by unpacking them or accessing fields by position. The following three +examples are equivalent: + +.. code-block:: python + + rows = session.execute('SELECT name, age, email FROM users') + for row in rows: + print row.name, row.age, row.email + +.. code-block:: python + + rows = session.execute('SELECT name, age, email FROM users') + for (name, age, email) in rows: + print name, age, email + +.. code-block:: python + + rows = session.execute('SELECT name, age, email FROM users') + for row in rows: + print row[0], row[1], row[2] + +If you prefer another result format, such as a ``dict`` per row, you +can change the :attr:`~.Session.row_factory` attribute. + +As mentioned in our `Drivers Best Practices Guide `_, +it is highly recommended to use `Prepared statements <#prepared-statement>`_ for your +frequently run queries. + +.. _prepared-statement: + +Prepared Statements +------------------- +Prepared statements are queries that are parsed by Cassandra and then saved +for later use. When the driver uses a prepared statement, it only needs to +send the values of parameters to bind. This lowers network traffic +and CPU utilization within Cassandra because Cassandra does not have to +re-parse the query each time. + +To prepare a query, use :meth:`.Session.prepare()`: + +.. code-block:: python + + user_lookup_stmt = session.prepare("SELECT * FROM users WHERE user_id=?") + + users = [] + for user_id in user_ids_to_query: + user = session.execute(user_lookup_stmt, [user_id]) + users.append(user) + +:meth:`~.Session.prepare()` returns a :class:`~.PreparedStatement` instance +which can be used in place of :class:`~.SimpleStatement` instances or literal +string queries. It is automatically prepared against all nodes, and the driver +handles re-preparing against new nodes and restarted nodes when necessary. + +Note that the placeholders for prepared statements are ``?`` characters. This +is different than for simple, non-prepared statements (although future versions +of the driver may use the same placeholders for both). + +Passing Parameters to CQL Queries +--------------------------------- +Althought it is not recommended, you can also pass parameters to non-prepared +statements. The driver supports two forms of parameter place-holders: positional +and named. + +Positional parameters are used with a ``%s`` placeholder. For example, +when you execute: + +.. code-block:: python + + session.execute( + """ + INSERT INTO users (name, credits, user_id) + VALUES (%s, %s, %s) + """, + ("John O'Reilly", 42, uuid.uuid1()) + ) + +It is translated to the following CQL query:: + + INSERT INTO users (name, credits, user_id) + VALUES ('John O''Reilly', 42, 2644bada-852c-11e3-89fb-e0b9a54a6d93) + +Note that you should use ``%s`` for all types of arguments, not just strings. +For example, this would be **wrong**: + +.. code-block:: python + + session.execute("INSERT INTO USERS (name, age) VALUES (%s, %d)", ("bob", 42)) # wrong + +Instead, use ``%s`` for the age placeholder. + +If you need to use a literal ``%`` character, use ``%%``. + +**Note**: you must always use a sequence for the second argument, even if you are +only passing in a single variable: + +.. code-block:: python + + session.execute("INSERT INTO foo (bar) VALUES (%s)", "blah") # wrong + session.execute("INSERT INTO foo (bar) VALUES (%s)", ("blah")) # wrong + session.execute("INSERT INTO foo (bar) VALUES (%s)", ("blah", )) # right + session.execute("INSERT INTO foo (bar) VALUES (%s)", ["blah"]) # right + + +Note that the second line is incorrect because in Python, single-element tuples +require a comma. + +Named place-holders use the ``%(name)s`` form: + +.. code-block:: python + + session.execute( + """ + INSERT INTO users (name, credits, user_id, username) + VALUES (%(name)s, %(credits)s, %(user_id)s, %(name)s) + """, + {'name': "John O'Reilly", 'credits': 42, 'user_id': uuid.uuid1()} + ) + +Note that you can repeat placeholders with the same name, such as ``%(name)s`` +in the above example. + +Only data values should be supplied this way. Other items, such as keyspaces, +table names, and column names should be set ahead of time (typically using +normal string formatting). + +.. _type-conversions: + +Type Conversions +---------------- +For non-prepared statements, Python types are cast to CQL literals in the +following way: + +.. table:: + + +--------------------+-------------------------+ + | Python Type | CQL Literal Type | + +====================+=========================+ + | ``None`` | ``NULL`` | + +--------------------+-------------------------+ + | ``bool`` | ``boolean`` | + +--------------------+-------------------------+ + | ``float`` | | ``float`` | + | | | ``double`` | + +--------------------+-------------------------+ + | | ``int`` | | ``int`` | + | | ``long`` | | ``bigint`` | + | | | ``varint`` | + | | | ``smallint`` | + | | | ``tinyint`` | + | | | ``counter`` | + +--------------------+-------------------------+ + | ``decimal.Decimal``| ``decimal`` | + +--------------------+-------------------------+ + | | ``str`` | | ``ascii`` | + | | ``unicode`` | | ``varchar`` | + | | | ``text`` | + +--------------------+-------------------------+ + | | ``buffer`` | ``blob`` | + | | ``bytearray`` | | + +--------------------+-------------------------+ + | ``date`` | ``date`` | + +--------------------+-------------------------+ + | ``datetime`` | ``timestamp`` | + +--------------------+-------------------------+ + | ``time`` | ``time`` | + +--------------------+-------------------------+ + | | ``list`` | ``list`` | + | | ``tuple`` | | + | | generator | | + +--------------------+-------------------------+ + | | ``set`` | ``set`` | + | | ``frozenset`` | | + +--------------------+-------------------------+ + | | ``dict`` | ``map`` | + | | ``OrderedDict`` | | + +--------------------+-------------------------+ + | ``uuid.UUID`` | | ``timeuuid`` | + | | | ``uuid`` | + +--------------------+-------------------------+ + + +Asynchronous Queries +-------------------- +The driver supports asynchronous query execution through +:meth:`~.Session.execute_async()`. Instead of waiting for the query to +complete and returning rows directly, this method almost immediately +returns a :class:`~.ResponseFuture` object. There are two ways of +getting the final result from this object. + +The first is by calling :meth:`~.ResponseFuture.result()` on it. If +the query has not yet completed, this will block until it has and +then return the result or raise an Exception if an error occurred. +For example: + +.. code-block:: python + + from cassandra import ReadTimeout + + query = "SELECT * FROM users WHERE user_id=%s" + future = session.execute_async(query, [user_id]) + + # ... do some other work + + try: + rows = future.result() + user = rows[0] + print user.name, user.age + except ReadTimeout: + log.exception("Query timed out:") + +This works well for executing many queries concurrently: + +.. code-block:: python + + # build a list of futures + futures = [] + query = "SELECT * FROM users WHERE user_id=%s" + for user_id in ids_to_fetch: + futures.append(session.execute_async(query, [user_id]) + + # wait for them to complete and use the results + for future in futures: + rows = future.result() + print rows[0].name + +Alternatively, instead of calling :meth:`~.ResponseFuture.result()`, +you can attach callback and errback functions through the +:meth:`~.ResponseFuture.add_callback()`, +:meth:`~.ResponseFuture.add_errback()`, and +:meth:`~.ResponseFuture.add_callbacks()`, methods. If you have used +Twisted Python before, this is designed to be a lightweight version of +that: + +.. code-block:: python + + def handle_success(rows): + user = rows[0] + try: + process_user(user.name, user.age, user.id) + except Exception: + log.error("Failed to process user %s", user.id) + # don't re-raise errors in the callback + + def handle_error(exception): + log.error("Failed to fetch user info: %s", exception) + + + future = session.execute_async(query) + future.add_callbacks(handle_success, handle_error) + +There are a few important things to remember when working with callbacks: + * **Exceptions that are raised inside the callback functions will be logged and then ignored.** + * Your callback will be run on the event loop thread, so any long-running + operations will prevent other requests from being handled + + +Setting a Consistency Level +--------------------------- +The consistency level used for a query determines how many of the +replicas of the data you are interacting with need to respond for +the query to be considered a success. + +By default, :attr:`.ConsistencyLevel.LOCAL_ONE` will be used for all queries. +You can specify a different default by setting the :attr:`.ExecutionProfile.consistency_level` +for the execution profile with key :data:`~.cluster.EXEC_PROFILE_DEFAULT`. +To specify a different consistency level per request, wrap queries +in a :class:`~.SimpleStatement`: + +.. code-block:: python + + from cassandra import ConsistencyLevel + from cassandra.query import SimpleStatement + + query = SimpleStatement( + "INSERT INTO users (name, age) VALUES (%s, %s)", + consistency_level=ConsistencyLevel.QUORUM) + session.execute(query, ('John', 42)) + +Setting a Consistency Level with Prepared Statements +---------------------------------------------------- +To specify a consistency level for prepared statements, you have two options. + +The first is to set a default consistency level for every execution of the +prepared statement: + +.. code-block:: python + + from cassandra import ConsistencyLevel + + cluster = Cluster() + session = cluster.connect("mykeyspace") + user_lookup_stmt = session.prepare("SELECT * FROM users WHERE user_id=?") + user_lookup_stmt.consistency_level = ConsistencyLevel.QUORUM + + # these will both use QUORUM + user1 = session.execute(user_lookup_stmt, [user_id1])[0] + user2 = session.execute(user_lookup_stmt, [user_id2])[0] + +The second option is to create a :class:`~.BoundStatement` from the +:class:`~.PreparedStatement` and binding parameters and set a consistency +level on that: + +.. code-block:: python + + # override the QUORUM default + user3_lookup = user_lookup_stmt.bind([user_id3]) + user3_lookup.consistency_level = ConsistencyLevel.ALL + user3 = session.execute(user3_lookup) + +Speculative Execution +--------------------- + +Speculative execution is a way to minimize latency by preemptively executing several +instances of the same query against different nodes. For more details about this +technique, see `Speculative Execution with DataStax Drivers `_. + +To enable speculative execution: + +* Configure a :class:`~.policies.SpeculativeExecutionPolicy` with the ExecutionProfile +* Mark your query as idempotent, which mean it can be applied multiple + times without changing the result of the initial application. + See `Query Idempotence `_ for more details. + + +Example: + +.. code-block:: python + + from cassandra.cluster import Cluster, ExecutionProfile, EXEC_PROFILE_DEFAULT + from cassandra.policies import ConstantSpeculativeExecutionPolicy + from cassandra.query import SimpleStatement + + # Configure the speculative execution policy + ep = ExecutionProfile( + speculative_execution_policy=ConstantSpeculativeExecutionPolicy(delay=.5, max_attempts=10) + ) + cluster = Cluster(..., execution_profiles={EXEC_PROFILE_DEFAULT: ep}) + session = cluster.connect() + + # Mark the query idempotent + query = SimpleStatement( + "UPDATE my_table SET list_col = [1] WHERE pk = 1", + is_idempotent=True + ) + + # Execute. A new query will be sent to the server every 0.5 second + # until we receive a response, for a max number attempts of 10. + session.execute(query) diff --git a/stable/_sources/index.rst.txt b/stable/_sources/index.rst.txt new file mode 100644 index 0000000000..c21d293b6f --- /dev/null +++ b/stable/_sources/index.rst.txt @@ -0,0 +1,107 @@ +Python Driver for Scylla and Apache Cassandra® +============================================== +A Python client driver for `Scylla `_. +This driver works exclusively with the Cassandra Query Language v3 (CQL3) +and Cassandra's native protocol. + +The driver supports Python 2.7, 3.5, 3.6, 3.7 and 3.8. + +This driver is open source under the +`Apache v2 License `_. +The source code for this driver can be found on `GitHub `_. + +Scylla Driver is a fork from `DataStax Python Driver `_, including some non-breaking changes for Scylla optimization, with more updates planned. + +Contents +-------- +:doc:`installation` + How to install the driver. + +:doc:`getting-started` + A guide through the first steps of connecting to Scylla and executing queries + +:doc:`scylla-specific` + A list of feature available only on ``scylla-driver`` + +:doc:`execution-profiles` + An introduction to a more flexible way of configuring request execution + +:doc:`lwt` + Working with results of conditional requests + +:doc:`object-mapper` + Introduction to the integrated object mapper, cqlengine + +:doc:`performance` + Tips for getting good performance. + +:doc:`query-paging` + Notes on paging large query results + +:doc:`security` + An overview of the security features of the driver + +:doc:`upgrading` + A guide to upgrading versions of the driver + +:doc:`user-defined-types` + Working with Scylla's user-defined types (UDT) + +:doc:`dates-and-times` + Some discussion on the driver's approach to working with timestamp, date, time types + +:doc:`scylla-cloud` + Connect to ScyllaDB Cloud + +:doc:`scylla-cloud-serverless` + Connect to ScyllaDB Cloud Serverless + +:doc:`CHANGELOG` + Log of changes to the driver, organized by version. + +:doc:`faq` + A collection of Frequently Asked Questions + +:doc:`api/index` + The API documentation. + +.. toctree:: + :hidden: + + api/index + installation + getting-started + scylla-specific + upgrading + execution-profiles + performance + query-paging + lwt + security + user-defined-types + object-mapper + dates-and-times + scylla-cloud + scylla-cloud-serverless + faq + +Getting Help +------------ +Visit the :doc:`FAQ section ` in this documentation. + +Please send questions to the Scylla `user list `_. + + +Reporting Issues +---------------- + +Please report any bugs and make any feature requests on the `Github project issues `_ + + +Copyright +--------- + +© 2013-2017 DataStax + +© 2016, The Apache Software Foundation. +Apache®, Apache Cassandra®, Cassandra®, the Apache feather logo and the Apache Cassandra® Eye logo are either registered trademarks or trademarks of the Apache Software Foundation in the United States and/or other countries. No endorsement by The Apache Software Foundation is implied by the use of these marks. diff --git a/stable/_sources/installation.rst.txt b/stable/_sources/installation.rst.txt new file mode 100644 index 0000000000..4996a02c1b --- /dev/null +++ b/stable/_sources/installation.rst.txt @@ -0,0 +1,234 @@ +Installation +============ + +Supported Platforms +------------------- +Python 2.7, 3.5, 3.6, 3.7 and 3.8 are supported. Both CPython (the standard Python +implementation) and `PyPy `_ are supported and tested. + +Linux, OSX, and Windows are supported. + +Installation through pip +------------------------ +`pip `_ is the suggested tool for installing +packages. It will handle installing all Python dependencies for the driver at +the same time as the driver itself. To install the driver*:: + + pip install scylla-driver + +You can use ``pip install --pre scylla-driver`` if you need to install a beta version. + +***Note**: if intending to use optional extensions, install the `dependencies <#optional-non-python-dependencies>`_ first. The driver may need to be reinstalled if dependencies are added after the initial installation. + +Verifying your Installation +--------------------------- +To check if the installation was successful, you can run:: + + python -c 'import cassandra; print cassandra.__version__' + +It should print something like "3.22.0". + +.. _installation-datastax-graph: + +(*Optional*) Graph +--------------------------- +The driver provides an optional fluent graph API that depends on Apache TinkerPop (gremlinpython). It is +not installed by default. To be able to build Gremlin traversals, you need to install +the `graph` requirements:: + + pip install scylla-driver[graph] + +(*Optional*) Compression Support +-------------------------------- +Compression can optionally be used for communication between the driver and +Cassandra. There are currently two supported compression algorithms: +snappy (in Cassandra 1.2+) and LZ4 (only in Cassandra 2.0+). If either is +available for the driver and Cassandra also supports it, it will +be used automatically. + +For lz4 support:: + + pip install lz4 + +For snappy support:: + + pip install python-snappy + +(If using a Debian Linux derivative such as Ubuntu, it may be easier to +just run ``apt-get install python-snappy``.) + +(*Optional*) Metrics Support +---------------------------- +The driver has built-in support for capturing :attr:`.Cluster.metrics` about +the queries you run. However, the ``scales`` library is required to +support this:: + + pip install scales + + +Speeding Up Installation +^^^^^^^^^^^^^^^^^^^^^^^^ + +By default, installing the driver through ``pip`` uses a pre-compiled, platform-specific wheel when available. +If using a source distribution rather than a wheel, Cython is used to compile certain parts of the driver. +This makes those hot paths faster at runtime, but the Cython compilation +process can take a long time -- as long as 10 minutes in some environments. + +In environments where performance is less important, it may be worth it to +:ref:`disable Cython as documented below `. +You can also use ``CASS_DRIVER_BUILD_CONCURRENCY`` to increase the number of +threads used to build the driver and any C extensions: + +.. code-block:: bash + + $ # installing from source + $ CASS_DRIVER_BUILD_CONCURRENCY=8 python setup.py install + $ # installing from pip + $ CASS_DRIVER_BUILD_CONCURRENCY=8 pip install scylla-driver + +OSX Installation Error +^^^^^^^^^^^^^^^^^^^^^^ +If you're installing on OSX and have XCode 5.1 installed, you may see an error like this:: + + clang: error: unknown argument: '-mno-fused-madd' [-Wunused-command-line-argument-hard-error-in-future] + +To fix this, re-run the installation with an extra compilation flag: + +.. code-block:: bash + + ARCHFLAGS=-Wno-error=unused-command-line-argument-hard-error-in-future pip install scylla-driver + +.. _windows_build: + +Windows Installation Notes +-------------------------- +Installing the driver with extensions in Windows sometimes presents some challenges. A few notes about common +hang-ups: + +Setup requires a compiler. When using Python 2, this is as simple as installing `this package `_ +(this link is also emitted during install if setuptools is unable to find the resources it needs). Depending on your +system settings, this package may install as a user-specific application. Make sure to install for everyone, or at least +as the user that will be building the Python environment. + +It is also possible to run the build with your compiler of choice. Just make sure to have your environment setup with +the proper paths. Make sure the compiler target architecture matches the bitness of your Python runtime. +Perhaps the easiest way to do this is to run the build/install from a Visual Studio Command Prompt (a +shortcut installed with Visual Studio that sources the appropriate environment and presents a shell). + +Manual Installation +------------------- +You can always install the driver directly from a source checkout or tarball. +When installing manually, ensure the python dependencies are already +installed. You can find the list of dependencies in +`requirements.txt `_. + +Once the dependencies are installed, simply run:: + + python setup.py install + + +(*Optional*) Non-python Dependencies +------------------------------------ +The driver has several **optional** features that have non-Python dependencies. + +C Extensions +^^^^^^^^^^^^ +By default, a number of extensions are compiled, providing faster hashing +for token-aware routing with the ``Murmur3Partitioner``, +`libev `_ event loop integration, +and Cython optimized extensions. + +When installing manually through setup.py, you can disable both with +the ``--no-extensions`` option, or selectively disable them with +with ``--no-murmur3``, ``--no-libev``, or ``--no-cython``. + +To compile the extensions, ensure that GCC and the Python headers are available. + +On Ubuntu and Debian, this can be accomplished by running:: + + $ sudo apt-get install gcc python-dev + +On RedHat and RedHat-based systems like CentOS and Fedora:: + + $ sudo yum install gcc python-devel + +On OS X, homebrew installations of Python should provide the necessary headers. + +See :ref:`windows_build` for notes on configuring the build environment on Windows. + +.. _cython-extensions: + +Cython-based Extensions +~~~~~~~~~~~~~~~~~~~~~~~ +By default, this package uses `Cython `_ to optimize core modules and build custom extensions. +This is not a hard requirement, but is engaged by default to build extensions offering better performance than the +pure Python implementation. + +This is a costly build phase, especially in clean environments where the Cython compiler must be built +This build phase can be avoided using the build switch, or an environment variable:: + + python setup.py install --no-cython + +Alternatively, an environment variable can be used to switch this option regardless of +context:: + + CASS_DRIVER_NO_CYTHON=1 + - or, to disable all extensions: + CASS_DRIVER_NO_EXTENSIONS=1 + +This method is required when using pip, which provides no other way of injecting user options in a single command:: + + CASS_DRIVER_NO_CYTHON=1 pip install scylla-driver + CASS_DRIVER_NO_CYTHON=1 sudo -E pip install ~/python-driver + +The environment variable is the preferred option because it spans all invocations of setup.py, and will +prevent Cython from being materialized as a setup requirement. + +If your sudo configuration does not allow SETENV, you must push the option flag down via pip. However, pip +applies these options to all dependencies (which break on the custom flag). Therefore, you must first install +dependencies, then use install-option:: + + sudo pip install six futures + sudo pip install --install-option="--no-cython" + + +libev support +^^^^^^^^^^^^^ +The driver currently uses Python's ``asyncore`` module for its default +event loop. For better performance, ``libev`` is also supported through +a C extension. + +If you're on Linux, you should be able to install libev +through a package manager. For example, on Debian/Ubuntu:: + + $ sudo apt-get install libev4 libev-dev + +On RHEL/CentOS/Fedora:: + + $ sudo yum install libev libev-devel + +If you're on Mac OS X, you should be able to install libev +through `Homebrew `_. For example, on Mac OS X:: + + $ brew install libev + +The libev extension is not built for Windows (the build process is complex, and the Windows implementation uses +select anyway). + +If successful, you should be able to build and install the extension +(just using ``setup.py build`` or ``setup.py install``) and then use +the libev event loop by doing the following: + +.. code-block:: python + + >>> from cassandra.io.libevreactor import LibevConnection + >>> from cassandra.cluster import Cluster + + >>> cluster = Cluster() + >>> cluster.connection_class = LibevConnection + >>> session = cluster.connect() + +(*Optional*) Configuring SSL +----------------------------- +Andrew Mussey has published a thorough guide on +`Using SSL with the DataStax Python driver `_. diff --git a/stable/_sources/lwt.rst.txt b/stable/_sources/lwt.rst.txt new file mode 100644 index 0000000000..2cc272f350 --- /dev/null +++ b/stable/_sources/lwt.rst.txt @@ -0,0 +1,91 @@ +Lightweight Transactions (Compare-and-set) +========================================== + +Lightweight Transactions (LWTs) are mostly pass-through CQL for the driver. However, +the server returns some specialized results indicating the outcome and optional state +preceding the transaction. + +For pertinent execution parameters, see :attr:`.Statement.serial_consistency_level`. + +This section discusses working with specialized result sets returned by the server for LWTs, +and how to work with them using the driver. + + +Specialized Results +------------------- +The result returned from a LWT request is always a single row result. It will always have +prepended a special column named ``[applied]``. How this value appears in your results depends +on the row factory in use. See below for examples. + +The value of this ``[applied]`` column is boolean value indicating whether or not the transaction was applied. +If ``True``, it is the only column in the result. If ``False``, the additional columns depend on the LWT operation being +executed: + +- When using a ``UPDATE ... IF "col" = ...`` clause, the result will contain the ``[applied]`` column, plus the existing columns + and values for any columns in the ``IF`` clause (and thus the value that caused the transaction to fail). + +- When using ``INSERT ... IF NOT EXISTS``, the result will contain the ``[applied]`` column, plus all columns and values + of the existing row that rejected the transaction. + +- ``UPDATE .. IF EXISTS`` never has additional columns, regardless of ``[applied]`` status. + +How the ``[applied]`` column manifests depends on the row factory in use. Considering the following (initially empty) table:: + + CREATE TABLE test.t ( + k int PRIMARY KEY, + v int, + x int + ) + +... the following sections show the expected result for a number of example statements, using the three base row factories. + +named_tuple_factory (default) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +The name ``[applied]`` is not a valid Python identifier, so the square brackets are actually removed +from the attribute for the resulting ``namedtuple``. The row always has a boolean column ``applied`` in position 0:: + + >>> session.execute("INSERT INTO t (k,v) VALUES (0,0) IF NOT EXISTS") + Row(applied=True) + + >>> session.execute("INSERT INTO t (k,v) VALUES (0,0) IF NOT EXISTS") + Row(applied=False, k=0, v=0, x=None) + + >>> session.execute("UPDATE t SET v = 1, x = 2 WHERE k = 0 IF v =0") + Row(applied=True) + + >>> session.execute("UPDATE t SET v = 1, x = 2 WHERE k = 0 IF v =0 AND x = 1") + Row(applied=False, v=1, x=2) + +tuple_factory +~~~~~~~~~~~~~ +This return type does not refer to names, but the boolean value ``applied`` is always present in position 0:: + + >>> session.execute("INSERT INTO t (k,v) VALUES (0,0) IF NOT EXISTS") + (True,) + + >>> session.execute("INSERT INTO t (k,v) VALUES (0,0) IF NOT EXISTS") + (False, 0, 0, None) + + >>> session.execute("UPDATE t SET v = 1, x = 2 WHERE k = 0 IF v =0") + (True,) + + >>> session.execute("UPDATE t SET v = 1, x = 2 WHERE k = 0 IF v =0 AND x = 1") + (False, 1, 2) + +dict_factory +~~~~~~~~~~~~ +The retuned ``dict`` contains the ``[applied]`` key:: + + >>> session.execute("INSERT INTO t (k,v) VALUES (0,0) IF NOT EXISTS") + {u'[applied]': True} + + >>> session.execute("INSERT INTO t (k,v) VALUES (0,0) IF NOT EXISTS") + {u'x': 2, u'[applied]': False, u'v': 1} + + >>> session.execute("UPDATE t SET v = 1, x = 2 WHERE k = 0 IF v =0") + {u'x': None, u'[applied]': False, u'k': 0, u'v': 0} + + >>> session.execute("UPDATE t SET v = 1, x = 2 WHERE k = 0 IF v =0 AND x = 1") + {u'[applied]': True} + + diff --git a/stable/_sources/object-mapper.rst.txt b/stable/_sources/object-mapper.rst.txt new file mode 100644 index 0000000000..421be246ac --- /dev/null +++ b/stable/_sources/object-mapper.rst.txt @@ -0,0 +1,105 @@ +Object Mapper +============= + +cqlengine is the Cassandra CQL 3 Object Mapper packaged with this driver + +:ref:`Jump to Getting Started ` + +Contents +-------- +:doc:`cqlengine/upgrade-guide` + For migrating projects from legacy cqlengine, to the integrated product + +:doc:`cqlengine/models` + Examples defining models, and mapping them to tables + +:doc:`cqlengine/queryset` + Overview of query sets and filtering + +:doc:`cqlengine/batches` + Working with batch mutations + +:doc:`cqlengine/connections` + Working with multiple sessions + +:ref:`API Documentation ` + Index of API documentation + +:doc:`cqlengine/third-party` + High-level examples in Celery and uWSGI + +:doc:`cqlengine/faq` + +.. toctree:: + :hidden: + + cqlengine/upgrade-guide + cqlengine/models + cqlengine/queryset + cqlengine/batches + cqlengine/connections + cqlengine/third-party + cqlengine/faq + +.. _getting-started: + +Getting Started +--------------- + +.. code-block:: python + + import uuid + from cassandra.cqlengine import columns + from cassandra.cqlengine import connection + from datetime import datetime + from cassandra.cqlengine.management import sync_table + from cassandra.cqlengine.models import Model + + #first, define a model + class ExampleModel(Model): + example_id = columns.UUID(primary_key=True, default=uuid.uuid4) + example_type = columns.Integer(index=True) + created_at = columns.DateTime() + description = columns.Text(required=False) + + #next, setup the connection to your cassandra server(s)... + # see http://datastax.github.io/python-driver/api/cassandra/cluster.html for options + # the list of hosts will be passed to create a Cluster() instance + connection.setup(['127.0.0.1'], "cqlengine", protocol_version=3) + + #...and create your CQL table + >>> sync_table(ExampleModel) + + #now we can create some rows: + >>> em1 = ExampleModel.create(example_type=0, description="example1", created_at=datetime.now()) + >>> em2 = ExampleModel.create(example_type=0, description="example2", created_at=datetime.now()) + >>> em3 = ExampleModel.create(example_type=0, description="example3", created_at=datetime.now()) + >>> em4 = ExampleModel.create(example_type=0, description="example4", created_at=datetime.now()) + >>> em5 = ExampleModel.create(example_type=1, description="example5", created_at=datetime.now()) + >>> em6 = ExampleModel.create(example_type=1, description="example6", created_at=datetime.now()) + >>> em7 = ExampleModel.create(example_type=1, description="example7", created_at=datetime.now()) + >>> em8 = ExampleModel.create(example_type=1, description="example8", created_at=datetime.now()) + + #and now we can run some queries against our table + >>> ExampleModel.objects.count() + 8 + >>> q = ExampleModel.objects(example_type=1) + >>> q.count() + 4 + >>> for instance in q: + >>> print instance.description + example5 + example6 + example7 + example8 + + #here we are applying additional filtering to an existing query + #query objects are immutable, so calling filter returns a new + #query object + >>> q2 = q.filter(example_id=em5.example_id) + + >>> q2.count() + 1 + >>> for instance in q2: + >>> print instance.description + example5 diff --git a/stable/_sources/performance.rst.txt b/stable/_sources/performance.rst.txt new file mode 100644 index 0000000000..f7a3f49e0f --- /dev/null +++ b/stable/_sources/performance.rst.txt @@ -0,0 +1,45 @@ +Performance Notes +================= +The Python driver for Cassandra offers several methods for executing queries. +You can synchronously block for queries to complete using +:meth:`.Session.execute()`, you can obtain asynchronous request futures through +:meth:`.Session.execute_async()`, and you can attach a callback to the future +with :meth:`.ResponseFuture.add_callback()`. + +Examples of multiple request patterns can be found in the benchmark scripts included in the driver project. + +The choice of execution pattern will depend on the application context. For applications dealing with multiple +requests in a given context, the recommended pattern is to use concurrent asynchronous +requests with callbacks. For many use cases, you don't need to implement this pattern yourself. +:meth:`cassandra.concurrent.execute_concurrent` and :meth:`cassandra.concurrent.execute_concurrent_with_args` +provide this pattern with a synchronous API and tunable concurrency. + +Due to the GIL and limited concurrency, the driver can become CPU-bound pretty quickly. The sections below +discuss further runtime and design considerations for mitigating this limitation. + +PyPy +---- +`PyPy `_ is an alternative Python runtime which uses a JIT compiler to +reduce CPU consumption. This leads to a huge improvement in the driver performance, +more than doubling throughput for many workloads. + +Cython Extensions +----------------- +`Cython `_ is an optimizing compiler and language that can be used to compile the core files and +optional extensions for the driver. Cython is not a strict dependency, but the extensions will be built by default. + +See :doc:`installation` for details on controlling this build. + +multiprocessing +--------------- +All of the patterns discussed above may be used over multiple processes using the +`multiprocessing `_ +module. Multiple processes will scale better than multiple threads, so if high throughput is your goal, +consider this option. + +Be sure to **never share any** :class:`~.Cluster`, :class:`~.Session`, +**or** :class:`~.ResponseFuture` **objects across multiple processes**. These +objects should all be created after forking the process, not before. + +For further discussion and simple examples using the driver with ``multiprocessing``, +see `this blog post `_. diff --git a/stable/_sources/query-paging.rst.txt b/stable/_sources/query-paging.rst.txt new file mode 100644 index 0000000000..23ee2c1129 --- /dev/null +++ b/stable/_sources/query-paging.rst.txt @@ -0,0 +1,95 @@ +.. _query-paging: + +Paging Large Queries +==================== +Cassandra 2.0+ offers support for automatic query paging. Starting with +version 2.0 of the driver, if :attr:`~.Cluster.protocol_version` is greater than +:const:`2` (it is by default), queries returning large result sets will be +automatically paged. + +Controlling the Page Size +------------------------- +By default, :attr:`.Session.default_fetch_size` controls how many rows will +be fetched per page. This can be overridden per-query by setting +:attr:`~.fetch_size` on a :class:`~.Statement`. By default, each page +will contain at most 5000 rows. + +Handling Paged Results +---------------------- +Whenever the number of result rows for are query exceed the page size, an +instance of :class:`~.PagedResult` will be returned instead of a normal +list. This class implements the iterator interface, so you can treat +it like a normal iterator over rows:: + + from cassandra.query import SimpleStatement + query = "SELECT * FROM users" # users contains 100 rows + statement = SimpleStatement(query, fetch_size=10) + for user_row in session.execute(statement): + process_user(user_row) + +Whenever there are no more rows in the current page, the next page will +be fetched transparently. However, note that it *is* possible for +an :class:`Exception` to be raised while fetching the next page, just +like you might see on a normal call to ``session.execute()``. + +If you use :meth:`.Session.execute_async()` along with, +:meth:`.ResponseFuture.result()`, the first page will be fetched before +:meth:`~.ResponseFuture.result()` returns, but latter pages will be +transparently fetched synchronously while iterating the result. + +Handling Paged Results with Callbacks +------------------------------------- +If callbacks are attached to a query that returns a paged result, +the callback will be called once per page with a normal list of rows. + +Use :attr:`.ResponseFuture.has_more_pages` and +:meth:`.ResponseFuture.start_fetching_next_page()` to continue fetching +pages. For example:: + + class PagedResultHandler(object): + + def __init__(self, future): + self.error = None + self.finished_event = Event() + self.future = future + self.future.add_callbacks( + callback=self.handle_page, + errback=self.handle_err) + + def handle_page(self, rows): + for row in rows: + process_row(row) + + if self.future.has_more_pages: + self.future.start_fetching_next_page() + else: + self.finished_event.set() + + def handle_error(self, exc): + self.error = exc + self.finished_event.set() + + future = session.execute_async("SELECT * FROM users") + handler = PagedResultHandler(future) + handler.finished_event.wait() + if handler.error: + raise handler.error + +Resume Paged Results +-------------------- + +You can resume the pagination when executing a new query by using the :attr:`.ResultSet.paging_state`. This can be useful if you want to provide some stateless pagination capabilities to your application (ie. via http). For example:: + + from cassandra.query import SimpleStatement + query = "SELECT * FROM users" + statement = SimpleStatement(query, fetch_size=10) + results = session.execute(statement) + + # save the paging_state somewhere and return current results + web_session['paging_state'] = results.paging_state + + + # resume the pagination sometime later... + statement = SimpleStatement(query, fetch_size=10) + ps = web_session['paging_state'] + results = session.execute(statement, paging_state=ps) diff --git a/stable/_sources/scylla-cloud-serverless.rst.txt b/stable/_sources/scylla-cloud-serverless.rst.txt new file mode 100644 index 0000000000..4e0bafd1b8 --- /dev/null +++ b/stable/_sources/scylla-cloud-serverless.rst.txt @@ -0,0 +1,49 @@ +ScyllaDB Cloud Serverless +------------------------- + +With ScyllaDB Cloud, you can deploy `serverless databases `_. +The Python driver allows you to connect to a serverless database by utilizing the connection bundle you can download via the **Connect>Python** tab in the Cloud application. +The connection bundle is a YAML file with connection and credential information for your cluster. + +Connecting to a ScyllaDB Cloud serverless database is very similar to a standard connection to a ScyllaDB database. + +Here’s a short program that connects to a ScyllaDB Cloud serverless database and prints metadata about the cluster: + +.. code-block:: python + + from cassandra.cluster import Cluster, ExecutionProfile, EXEC_PROFILE_DEFAULT + from cassandra.policies import DCAwareRoundRobinPolicy, TokenAwarePolicy + + PATH_TO_BUNDLE_YAML = '/file/downloaded/from/cloud/connect-bundle.yaml' + + + def get_cluster(): + profile = ExecutionProfile( + load_balancing_policy=TokenAwarePolicy( + DCAwareRoundRobinPolicy(local_dc='us-east-1') + ) + ) + + return Cluster( + execution_profiles={EXEC_PROFILE_DEFAULT: profile}, + scylla_cloud=PATH_TO_BUNDLE_YAML, + ) + + + print('Connecting to cluster') + cluster = get_cluster() + session = cluster.connect() + + print('Connected to cluster', cluster.metadata.cluster_name) + + print('Getting metadata') + for host in cluster.metadata.all_hosts(): + print('Datacenter: {}; Host: {}; Rack: {}'.format( + host.datacenter, host.address, host.rack) + ) + + cluster.shutdown() + +By providing the ``scylla_cloud`` parameter to the :class:`~.Cluster` constructor, +the driver can set up the connection based on the endpoint and credential information +stored in your downloaded ScyllaDB Cloud Serverless connection bundle. \ No newline at end of file diff --git a/stable/_sources/scylla-cloud.rst.txt b/stable/_sources/scylla-cloud.rst.txt new file mode 100644 index 0000000000..b5eb6df798 --- /dev/null +++ b/stable/_sources/scylla-cloud.rst.txt @@ -0,0 +1,5 @@ +ScyllaDB Cloud +-------------- + +To connect to a `ScyllaDB Cloud `_ cluster, go to the Cluster Connect page, Python example. +For best performance, make sure to use the Scylla Driver. diff --git a/stable/_sources/scylla-specific.rst.txt b/stable/_sources/scylla-specific.rst.txt new file mode 100644 index 0000000000..101ddb534b --- /dev/null +++ b/stable/_sources/scylla-specific.rst.txt @@ -0,0 +1,106 @@ +Scylla Specific Features +======================== + +Shard Awareness +--------------- + +**scylla-driver** is shard aware and contains extensions that work with the TokenAwarePolicy supported by Scylla 2.3 and onwards. Using this policy, the driver can select a connection to a particular shard based on the shard's token. +As a result, latency is significantly reduced because there is no need to pass data between the shards. + +Details on the scylla cql protocol extensions +https://github.com/scylladb/scylla/blob/master/docs/dev/protocol-extensions.md#intranode-sharding + +For using it you only need to enable ``TokenAwarePolicy`` on the ``Cluster`` + +See the configuration of ``native_shard_aware_transport_port`` and ``native_shard_aware_transport_port_ssl`` on scylla.yaml: +https://github.com/scylladb/scylla/blob/master/docs/dev/protocols.md#cql-client-protocol + +.. code:: python + + from cassandra.cluster import Cluster + from cassandra.policies import TokenAwarePolicy, RoundRobinPolicy + + cluster = Cluster(load_balancing_policy=TokenAwarePolicy(RoundRobinPolicy())) + + +New Cluster Helpers +------------------- + +* ``shard_aware_options`` + + Setting it to ``dict(disable=True)`` would disable the shard aware functionally, for cases favoring once connection per host (example, lots of processes connecting from one client host, generating a big load of connections + + Other option is to configure scylla by setting ``enable_shard_aware_drivers: false`` on scylla.yaml. + +.. code:: python + + from cassandra.cluster import Cluster + + cluster = Cluster(shard_aware_options=dict(disable=True)) + session = cluster.connect() + + assert not cluster.is_shard_aware(), "Shard aware should be disabled" + + # or just disable the shard aware port logic + cluster = Cluster(shard_aware_options=dict(disable_shardaware_port=True)) + session = cluster.connect() + +* ``cluster.is_shard_aware()`` + + New method available on ``Cluster`` allowing to check whether the remote cluster supports shard awareness (bool) + +.. code:: python + + from cassandra.cluster import Cluster + + cluster = Cluster() + session = cluster.connect() + + if cluster.is_shard_aware(): + print("connected to a scylla cluster") + +* ``cluster.shard_aware_stats()`` + + New method available on ``Cluster`` allowing to check the status of shard aware connections to all available hosts (dict) + +.. code:: python + + from cassandra.cluster import Cluster + + cluster = Cluster() + session = cluster.connect() + + stats = cluster.shard_aware_stats() + if all([v["shards_count"] == v["connected"] for v in stats.values()]): + print("successfully connected to all shards of all scylla nodes") + + +New Table Attributes +-------------------- + +* ``in_memory`` flag + + New flag available on ``TableMetadata.options`` to indicate that it is an `In Memory `_ table + +.. note:: in memory tables is a feature existing only in Scylla Enterprise + +.. code:: python + + from cassandra.cluster import Cluster + + cluster = Cluster() + session = cluster.connect() + session.execute(""" + CREATE KEYSPACE IF NOT EXISTS keyspace1 + WITH replication = {'class': 'SimpleStrategy', 'replication_factor': '1'}; + """) + + session.execute(""" + CREATE TABLE IF NOT EXISTS keyspace1.standard1 ( + key blob PRIMARY KEY, + "C0" blob + ) WITH in_memory=true AND compaction={'class': 'InMemoryCompactionStrategy'} + """) + + cluster.refresh_table_metadata("keyspace1", "standard1") + assert cluster.metadata.keyspaces["keyspace1"].tables["standard1"].options["in_memory"] == True diff --git a/stable/_sources/security.rst.txt b/stable/_sources/security.rst.txt new file mode 100644 index 0000000000..c30189562f --- /dev/null +++ b/stable/_sources/security.rst.txt @@ -0,0 +1,421 @@ +.. _security: + +Security +======== +The two main security components you will use with the +Python driver are Authentication and SSL. + +Authentication +-------------- +Versions 2.0 and higher of the driver support a SASL-based +authentication mechanism when :attr:`~.Cluster.protocol_version` +is set to 2 or higher. To use this authentication, set +:attr:`~.Cluster.auth_provider` to an instance of a subclass +of :class:`~cassandra.auth.AuthProvider`. When working +with Cassandra's ``PasswordAuthenticator``, you can use +the :class:`~cassandra.auth.PlainTextAuthProvider` class. + +For example, suppose Cassandra is setup with its default +'cassandra' user with a password of 'cassandra': + +.. code-block:: python + + from cassandra.cluster import Cluster + from cassandra.auth import PlainTextAuthProvider + + auth_provider = PlainTextAuthProvider(username='cassandra', password='cassandra') + cluster = Cluster(auth_provider=auth_provider, protocol_version=2) + + + +Custom Authenticators +^^^^^^^^^^^^^^^^^^^^^ +If you're using something other than Cassandra's ``PasswordAuthenticator``, +:class:`~.SaslAuthProvider` is provided for generic SASL authentication mechanisms, +utilizing the ``pure-sasl`` package. +If these do not suit your needs, you may need to create your own subclasses of +:class:`~.AuthProvider` and :class:`~.Authenticator`. You can use the Sasl classes +as example implementations. + +Protocol v1 Authentication +^^^^^^^^^^^^^^^^^^^^^^^^^^ +When working with Cassandra 1.2 (or a higher version with +:attr:`~.Cluster.protocol_version` set to ``1``), you will not pass in +an :class:`~.AuthProvider` instance. Instead, you should pass in a +function that takes one argument, the IP address of a host, and returns +a dict of credentials with a ``username`` and ``password`` key: + +.. code-block:: python + + from cassandra.cluster import Cluster + + def get_credentials(host_address): + return {'username': 'joe', 'password': '1234'} + + cluster = Cluster(auth_provider=get_credentials, protocol_version=1) + +SSL +--- +SSL should be used when client encryption is enabled in Cassandra. + +To give you as much control as possible over your SSL configuration, our SSL +API takes a user-created `SSLContext` instance from the Python standard library. +These docs will include some examples for how to achieve common configurations, +but the `ssl.SSLContext `_ documentation +gives a more complete description of what is possible. + +To enable SSL with version 3.17.0 and higher, you will need to set :attr:`.Cluster.ssl_context` to a +``ssl.SSLContext`` instance to enable SSL. Optionally, you can also set :attr:`.Cluster.ssl_options` +to a dict of options. These will be passed as kwargs to ``ssl.SSLContext.wrap_socket()`` +when new sockets are created. + +If you create your SSLContext using `ssl.create_default_context `_, +be aware that SSLContext.check_hostname is set to True by default, so the hostname validation will be done +by Python and not the driver. For this reason, we need to set the server_hostname at best effort, which is the +resolved ip address. If this validation needs to be done against the FQDN, consider enabling it using the ssl_options +as described in the following examples or implement your own :class:`~.connection.EndPoint` and +:class:`~.connection.EndPointFactory`. + + +The following examples assume you have generated your Cassandra certificate and +keystore files with these intructions: + +* `Setup SSL Cert `_ + +It might be also useful to learn about the different levels of identity verification to understand the examples: + +* `Using SSL in DSE drivers `_ + +SSL with Twisted or Eventlet +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Twisted and Eventlet both use an alternative SSL implementation called pyOpenSSL, so if your `Cluster`'s connection class is +:class:`~cassandra.io.twistedreactor.TwistedConnection` or :class:`~cassandra.io.eventletreactor.EventletConnection`, you must pass a +`pyOpenSSL context `_ instead. +An example is provided in these docs, and more details can be found in the +`documentation `_. +pyOpenSSL is not installed by the driver and must be installed separately. + +SSL Configuration Examples +^^^^^^^^^^^^^^^^^^^^^^^^^^ +Here, we'll describe the server and driver configuration necessary to set up SSL to meet various goals, such as the client verifying the server and the server verifying the client. We'll also include Python code demonstrating how to use servers and drivers configured in these ways. + +.. _ssl-no-identify-verification: + +No identity verification +++++++++++++++++++++++++ + +No identity verification at all. Note that this is not recommended for for production deployments. + +The Cassandra configuration:: + + client_encryption_options: + enabled: true + keystore: /path/to/127.0.0.1.keystore + keystore_password: myStorePass + require_client_auth: false + +The driver configuration: + +.. code-block:: python + + from cassandra.cluster import Cluster, Session + from ssl import SSLContext, PROTOCOL_TLS + + ssl_context = SSLContext(PROTOCOL_TLS) + + cluster = Cluster(['127.0.0.1'], ssl_context=ssl_context) + session = cluster.connect() + +.. _ssl-client-verifies-server: + +Client verifies server +++++++++++++++++++++++ + +Ensure the python driver verifies the identity of the server. + +The Cassandra configuration:: + + client_encryption_options: + enabled: true + keystore: /path/to/127.0.0.1.keystore + keystore_password: myStorePass + require_client_auth: false + +For the driver configuration, it's very important to set `ssl_context.verify_mode` +to `CERT_REQUIRED`. Otherwise, the loaded verify certificate will have no effect: + +.. code-block:: python + + from cassandra.cluster import Cluster, Session + from ssl import SSLContext, PROTOCOL_TLS, CERT_REQUIRED + + ssl_context = SSLContext(PROTOCOL_TLS) + ssl_context.load_verify_locations('/path/to/rootca.crt') + ssl_context.verify_mode = CERT_REQUIRED + + cluster = Cluster(['127.0.0.1'], ssl_context=ssl_context) + session = cluster.connect() + +Additionally, you can also force the driver to verify the `hostname` of the server by passing additional options to `ssl_context.wrap_socket` via the `ssl_options` kwarg: + +.. code-block:: python + + from cassandra.cluster import Cluster, Session + from ssl import SSLContext, PROTOCOL_TLS, CERT_REQUIRED + + ssl_context = SSLContext(PROTOCOL_TLS) + ssl_context.load_verify_locations('/path/to/rootca.crt') + ssl_context.verify_mode = CERT_REQUIRED + ssl_context.check_hostname = True + ssl_options = {'server_hostname': '127.0.0.1'} + + cluster = Cluster(['127.0.0.1'], ssl_context=ssl_context, ssl_options=ssl_options) + session = cluster.connect() + +.. _ssl-server-verifies-client: + +Server verifies client +++++++++++++++++++++++ + +If Cassandra is configured to verify clients (``require_client_auth``), you need to generate +SSL key and certificate files. + +The cassandra configuration:: + + client_encryption_options: + enabled: true + keystore: /path/to/127.0.0.1.keystore + keystore_password: myStorePass + require_client_auth: true + truststore: /path/to/dse-truststore.jks + truststore_password: myStorePass + +The Python ``ssl`` APIs require the certificate in PEM format. First, create a certificate +conf file: + +.. code-block:: bash + + cat > gen_client_cert.conf <`__ +for more details about ``SSLContext`` configuration. + +**Server verifies client and client verifies server using Twisted and pyOpenSSL** + +.. code-block:: python + + from OpenSSL import SSL, crypto + from cassandra.cluster import Cluster + from cassandra.io.twistedreactor import TwistedConnection + + ssl_context = SSL.Context(SSL.TLSv1_2_METHOD) + ssl_context.set_verify(SSL.VERIFY_PEER, callback=lambda _1, _2, _3, _4, ok: ok) + ssl_context.use_certificate_file('/path/to/client.crt_signed') + ssl_context.use_privatekey_file('/path/to/client.key') + ssl_context.load_verify_locations('/path/to/rootca.crt') + + cluster = Cluster( + contact_points=['127.0.0.1'], + connection_class=TwistedConnection, + ssl_context=ssl_context, + ssl_options={'check_hostname': True} + ) + session = cluster.connect() + + +Connecting using Eventlet would look similar except instead of importing and using ``TwistedConnection``, you would +import and use ``EventletConnection``, including the appropriate monkey-patching. + +Versions 3.16.0 and lower +^^^^^^^^^^^^^^^^^^^^^^^^^ + +To enable SSL you will need to set :attr:`.Cluster.ssl_options` to a +dict of options. These will be passed as kwargs to ``ssl.wrap_socket()`` +when new sockets are created. Note that this use of ssl_options will be +deprecated in the next major release. + +By default, a ``ca_certs`` value should be supplied (the value should be +a string pointing to the location of the CA certs file), and you probably +want to specify ``ssl_version`` as ``ssl.PROTOCOL_TLS`` to match +Cassandra's default protocol. + +For example: + +.. code-block:: python + + from cassandra.cluster import Cluster + from ssl import PROTOCOL_TLS, CERT_REQUIRED + + ssl_opts = { + 'ca_certs': '/path/to/my/ca.certs', + 'ssl_version': PROTOCOL_TLS, + 'cert_reqs': CERT_REQUIRED # Certificates are required and validated + } + cluster = Cluster(ssl_options=ssl_opts) + +This is only an example to show how to pass the ssl parameters. Consider reading +the `python ssl documentation `__ for +your configuration. For further reading, Andrew Mussey has published a thorough guide on +`Using SSL with the DataStax Python driver `_. + +SSL with Twisted +++++++++++++++++ + +In case the twisted event loop is used pyOpenSSL must be installed or an exception will be risen. Also +to set the ``ssl_version`` and ``cert_reqs`` in ``ssl_opts`` the appropriate constants from pyOpenSSL are expected. + +DSE Authentication +------------------ +When authenticating against DSE, the Cassandra driver provides two auth providers that work both with legacy kerberos and Cassandra authenticators, +as well as the new DSE Unified Authentication. This allows client to configure this auth provider independently, +and in advance of any server upgrade. These auth providers are configured in the same way as any previous implementation:: + + from cassandra.auth import DSEGSSAPIAuthProvider + auth_provider = DSEGSSAPIAuthProvider(service='dse', qops=["auth"]) + cluster = Cluster(auth_provider=auth_provider) + session = cluster.connect() + +Implementations are :attr:`.DSEPlainTextAuthProvider`, :class:`.DSEGSSAPIAuthProvider` and :class:`.SaslAuthProvider`. + +DSE Unified Authentication +^^^^^^^^^^^^^^^^^^^^^^^^^^ + +With DSE (>=5.1), unified Authentication allows you to: + +* Proxy Login: Authenticate using a fixed set of authentication credentials but allow authorization of resources based another user id. +* Proxy Execute: Authenticate using a fixed set of authentication credentials but execute requests based on another user id. + +Proxy Login ++++++++++++ + +Proxy login allows you to authenticate with a user but act as another one. You need to ensure the authenticated user has the permission to use the authorization of resources of the other user. ie. this example will allow the `server` user to authenticate as usual but use the authorization of `user1`: + +.. code-block:: text + + GRANT PROXY.LOGIN on role user1 to server + +then you can do the proxy authentication.... + +.. code-block:: python + + from cassandra.cluster import Cluster + from cassandra.auth import SaslAuthProvider + + sasl_kwargs = { + "service": 'dse', + "mechanism":"PLAIN", + "username": 'server', + 'password': 'server', + 'authorization_id': 'user1' + } + + auth_provider = SaslAuthProvider(**sasl_kwargs) + c = Cluster(auth_provider=auth_provider) + s = c.connect() + s.execute(...) # all requests will be executed as 'user1' + +If you are using kerberos, you can use directly :class:`.DSEGSSAPIAuthProvider` and pass the authorization_id, like this: + +.. code-block:: python + + from cassandra.cluster import Cluster + from cassandra.auth import DSEGSSAPIAuthProvider + + # Ensure the kerberos ticket of the server user is set with the kinit utility. + auth_provider = DSEGSSAPIAuthProvider(service='dse', qops=["auth"], principal="server@DATASTAX.COM", + authorization_id='user1@DATASTAX.COM') + c = Cluster(auth_provider=auth_provider) + s = c.connect() + s.execute(...) # all requests will be executed as 'user1' + + +Proxy Execute ++++++++++++++ + +Proxy execute allows you to execute requests as another user than the authenticated one. You need to ensure the authenticated user has the permission to use the authorization of resources of the specified user. ie. this example will allow the `server` user to execute requests as `user1`: + +.. code-block:: text + + GRANT PROXY.EXECUTE on role user1 to server + +then you can do a proxy execute... + +.. code-block:: python + + from cassandra.cluster import Cluster + from cassandra.auth import DSEPlainTextAuthProvider, + + auth_provider = DSEPlainTextAuthProvider('server', 'server') + + c = Cluster(auth_provider=auth_provider) + s = c.connect() + s.execute('select * from k.t;', execute_as='user1') # the request will be executed as 'user1' + +Please see the `official documentation `_ for more details on the feature and configuration process. diff --git a/stable/_sources/upgrading.rst.txt b/stable/_sources/upgrading.rst.txt new file mode 100644 index 0000000000..9559fa3579 --- /dev/null +++ b/stable/_sources/upgrading.rst.txt @@ -0,0 +1,388 @@ +Upgrading +========= + +.. toctree:: + :maxdepth: 1 + +Upgrading from dse-driver +------------------------- + +Since 3.21.0, scylla-driver fully supports DataStax products. dse-driver and +dse-graph users should now migrate to scylla-driver to benefit from latest bug fixes +and new features. The upgrade to this new unified driver version is straightforward +with no major API changes. + +Installation +^^^^^^^^^^^^ + +Only the `scylla-driver` package should be installed. `dse-driver` and `dse-graph` +are not required anymore:: + + pip install scylla-driver + +If you need the Graph *Fluent* API (features provided by dse-graph):: + + pip install scylla-driver[graph] + +See :doc:`installation` for more details. + +Import from the cassandra module +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +There is no `dse` module, so you should import from the `cassandra` module. You +need to change only the first module of your import statements, not the submodules. + +.. code-block:: python + + from dse.cluster import Cluster, EXEC_PROFILE_GRAPH_DEFAULT + from dse.auth import PlainTextAuthProvider + from dse.policies import WhiteListRoundRobinPolicy + + # becomes + + from cassandra.cluster import Cluster, EXEC_PROFILE_GRAPH_DEFAULT + from cassandra.auth import PlainTextAuthProvider + from cassandra.policies import WhiteListRoundRobinPolicy + +Also note that the cassandra.hosts module doesn't exist in scylla-driver. This +module is named cassandra.pool. + +dse-graph +^^^^^^^^^ + +dse-graph features are now built into scylla-driver. The only change you need +to do is your import statements: + +.. code-block:: python + + from dse_graph import .. + from dse_graph.query import .. + + # becomes + + from cassandra.datastax.graph.fluent import .. + from cassandra.datastax.graph.fluent.query import .. + +See :mod:`~.datastax.graph.fluent`. + +Session.execute and Session.execute_async API +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Although it is not common to use this API with positional arguments, it is +important to be aware that the `host` and `execute_as` parameters have had +their positional order swapped. This is only because `execute_as` was added +in dse-driver before `host`. + +See :meth:`.Session.execute`. + +Deprecations +^^^^^^^^^^^^ + +These changes are optional, but recommended: + +* Importing from `cassandra.graph` is deprecated. Consider importing from `cassandra.datastax.graph`. +* Use :class:`~.policies.DefaultLoadBalancingPolicy` instead of DSELoadBalancingPolicy. + +Upgrading to 3.0 +---------------- +Version 3.0 of the DataStax Python driver for Apache Cassandra +adds support for Cassandra 3.0 while maintaining support for +previously supported versions. In addition to substantial internal rework, +there are several updates to the API that integrators will need +to consider: + +Default consistency is now ``LOCAL_ONE`` +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Previous value was ``ONE``. The new value is introduced to mesh with the default +DC-aware load balancing policy and to match other drivers. + +Execution API Updates +^^^^^^^^^^^^^^^^^^^^^ +Result return normalization +~~~~~~~~~~~~~~~~~~~~~~~~~~~ +`PYTHON-368 `_ + +Previously results would be returned as a ``list`` of rows for result rows +up to ``fetch_size``, and ``PagedResult`` afterward. This could break +application code that assumed one type and got another. + +Now, all results are returned as an iterable :class:`~.ResultSet`. + +The preferred way to consume results of unknown size is to iterate through +them, letting automatic paging occur as they are consumed. + +.. code-block:: python + + results = session.execute("SELECT * FROM system.local") + for row in results: + process(row) + +If the expected size of the results is known, it is still possible to +materialize a list using the iterator: + +.. code-block:: python + + results = session.execute("SELECT * FROM system.local") + row_list = list(results) + +For backward compatibility, :class:`~.ResultSet` supports indexing. When +accessed at an index, a `~.ResultSet` object will materialize all its pages: + +.. code-block:: python + + results = session.execute("SELECT * FROM system.local") + first_result = results[0] # materializes results, fetching all pages + +This can send requests and load (possibly large) results into memory, so +`~.ResultSet` will log a warning on implicit materialization. + +Trace information is not attached to executed Statements +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +`PYTHON-318 `_ + +Previously trace data was attached to Statements if tracing was enabled. This +could lead to confusion if the same statement was used for multiple executions. + +Now, trace data is associated with the ``ResponseFuture`` and ``ResultSet`` +returned for each query: + +:meth:`.ResponseFuture.get_query_trace()` + +:meth:`.ResponseFuture.get_all_query_traces()` + +:meth:`.ResultSet.get_query_trace()` + +:meth:`.ResultSet.get_all_query_traces()` + +Binding named parameters now ignores extra names +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +`PYTHON-178 `_ + +Previously, :meth:`.BoundStatement.bind()` would raise if a mapping +was passed with extra names not found in the prepared statement. + +Behavior in 3.0+ is to ignore extra names. + +blist removed as soft dependency +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +`PYTHON-385 `_ + +Previously the driver had a soft dependency on ``blist sortedset``, using +that where available and using an internal fallback where possible. + +Now, the driver never chooses the ``blist`` variant, instead returning the +internal :class:`.util.SortedSet` for all ``set`` results. The class implements +all standard set operations, so no integration code should need to change unless +it explicitly checks for ``sortedset`` type. + +Metadata API Updates +^^^^^^^^^^^^^^^^^^^^ +`PYTHON-276 `_, `PYTHON-408 `_, `PYTHON-400 `_, `PYTHON-422 `_ + +Cassandra 3.0 brought a substantial overhaul to the internal schema metadata representation. +This version of the driver supports that metadata in addition to the legacy version. Doing so +also brought some changes to the metadata model. + +The present API is documented: :any:`cassandra.metadata`. Changes highlighted below: + +* All types are now exposed as CQL types instead of types derived from the internal server implementation +* Some metadata attributes have changed names to match current nomenclature (for example, :attr:`.Index.kind` in place of ``Index.type``). +* Some metadata attributes removed + + * ``TableMetadata.keyspace`` reference replaced with :attr:`.TableMetadata.keyspace_name` + * ``ColumnMetadata.index`` is removed table- and keyspace-level mappings are still maintained + +Several deprecated features are removed +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +`PYTHON-292 `_ + +* ``ResponseFuture.result`` timeout parameter is removed, use ``Session.execute`` timeout instead (`031ebb0 `_) +* ``Cluster.refresh_schema`` removed, use ``Cluster.refresh_*_metadata`` instead (`419fcdf `_) +* ``Cluster.submit_schema_refresh`` removed (`574266d `_) +* ``cqltypes`` time/date functions removed, use ``util`` entry points instead (`bb984ee `_) +* ``decoder`` module removed (`e16a073 `_) +* ``TableMetadata.keyspace`` attribute replaced with ``keyspace_name`` (`cc94073 `_) +* ``cqlengine.columns.TimeUUID.from_datetime`` removed, use ``util`` variant instead (`96489cc `_) +* ``cqlengine.columns.Float(double_precision)`` parameter removed, use ``columns.Double`` instead (`a2d3a98 `_) +* ``cqlengine`` keyspace management functions are removed in favor of the strategy-specific entry points (`4bd5909 `_) +* ``cqlengine.Model.__polymorphic_*__`` attributes removed, use ``__discriminator*`` attributes instead (`9d98c8e `_) +* ``cqlengine.statements`` will no longer warn about list list prepend behavior (`79efe97 `_) + + +Upgrading to 2.1 from 2.0 +------------------------- +Version 2.1 of the DataStax Python driver for Apache Cassandra +adds support for Cassandra 2.1 and version 3 of the native protocol. + +Cassandra 1.2, 2.0, and 2.1 are all supported. However, 1.2 only +supports protocol version 1, and 2.0 only supports versions 1 and +2, so some features may not be available. + +Using the v3 Native Protocol +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +By default, the driver will attempt to use version 2 of the +native protocol. To use version 3, you must explicitly +set the :attr:`~.Cluster.protocol_version`: + +.. code-block:: python + + from cassandra.cluster import Cluster + + cluster = Cluster(protocol_version=3) + +Note that protocol version 3 is only supported by Cassandra 2.1+. + +In future releases, the driver may default to using protocol version +3. + +Working with User-Defined Types +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Cassandra 2.1 introduced the ability to define new types:: + + USE KEYSPACE mykeyspace; + + CREATE TYPE address (street text, city text, zip int); + +The driver generally expects you to use instances of a specific +class to represent column values of this type. You can let the +driver know what class to use with :meth:`.Cluster.register_user_type`: + +.. code-block:: python + + cluster = Cluster() + + class Address(object): + + def __init__(self, street, city, zipcode): + self.street = street + self.city = text + self.zipcode = zipcode + + cluster.register_user_type('mykeyspace', 'address', Address) + +When inserting data for ``address`` columns, you should pass in +instances of ``Address``. When querying data, ``address`` column +values will be instances of ``Address``. + +If no class is registered for a user-defined type, query results +will use a ``namedtuple`` class and data may only be inserted +though prepared statements. + +See :ref:`udts` for more details. + +Customizing Encoders for Non-prepared Statements +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Starting with version 2.1 of the driver, it is possible to customize +how Python types are converted to CQL literals when working with +non-prepared statements. This is done on a per-:class:`~.Session` +basis through :attr:`.Session.encoder`: + +.. code-block:: python + + cluster = Cluster() + session = cluster.connect() + session.encoder.mapping[tuple] = session.encoder.cql_encode_tuple + +See :ref:`type-conversions` for the table of default CQL literal conversions. + +Using Client-Side Protocol-Level Timestamps +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +With version 3 of the native protocol, timestamps may be supplied by the +client at the protocol level. (Normally, if they are not specified within +the CQL query itself, a timestamp is generated server-side.) + +When :attr:`~.Cluster.protocol_version` is set to 3 or higher, the driver +will automatically use client-side timestamps with microsecond precision +unless :attr:`.Session.use_client_timestamp` is changed to :const:`False`. +If a timestamp is specified within the CQL query, it will override the +timestamp generated by the driver. + +Upgrading to 2.0 from 1.x +------------------------- +Version 2.0 of the DataStax Python driver for Apache Cassandra +includes some notable improvements over version 1.x. This version +of the driver supports Cassandra 1.2, 2.0, and 2.1. However, not +all features may be used with Cassandra 1.2, and some new features +in 2.1 are not yet supported. + +Using the v2 Native Protocol +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +By default, the driver will attempt to use version 2 of Cassandra's +native protocol. You can explicitly set the protocol version to +2, though: + +.. code-block:: python + + from cassandra.cluster import Cluster + + cluster = Cluster(protocol_version=2) + +When working with Cassandra 1.2, you will need to +explicitly set the :attr:`~.Cluster.protocol_version` to 1: + +.. code-block:: python + + from cassandra.cluster import Cluster + + cluster = Cluster(protocol_version=1) + +Automatic Query Paging +^^^^^^^^^^^^^^^^^^^^^^ +Version 2 of the native protocol adds support for automatic query +paging, which can make dealing with large result sets much simpler. + +See :ref:`query-paging` for full details. + +Protocol-Level Batch Statements +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +With version 1 of the native protocol, batching of statements required +using a `BATCH cql query `_. +With version 2 of the native protocol, you can now batch statements at +the protocol level. This allows you to use many different prepared +statements within a single batch. + +See :class:`~.query.BatchStatement` for details and usage examples. + +SASL-based Authentication +^^^^^^^^^^^^^^^^^^^^^^^^^ +Also new in version 2 of the native protocol is SASL-based authentication. +See the section on :ref:`security` for details and examples. + +Lightweight Transactions +^^^^^^^^^^^^^^^^^^^^^^^^ +`Lightweight transactions `_ are another new feature. To use lightweight transactions, add ``IF`` clauses +to your CQL queries and set the :attr:`~.Statement.serial_consistency_level` +on your statements. + +Calling Cluster.shutdown() +^^^^^^^^^^^^^^^^^^^^^^^^^^ +In order to fix some issues around garbage collection and unclean interpreter +shutdowns, version 2.0 of the driver requires you to call :meth:`.Cluster.shutdown()` +on your :class:`~.Cluster` objects when you are through with them. +This helps to guarantee a clean shutdown. + +Deprecations +^^^^^^^^^^^^ +The following functions have moved from ``cassandra.decoder`` to ``cassandra.query``. +The original functions have been left in place with a :exc:`DeprecationWarning` for +now: + +* :attr:`cassandra.decoder.tuple_factory` has moved to + :attr:`cassandra.query.tuple_factory` +* :attr:`cassandra.decoder.named_tuple_factory` has moved to + :attr:`cassandra.query.named_tuple_factory` +* :attr:`cassandra.decoder.dict_factory` has moved to + :attr:`cassandra.query.dict_factory` +* :attr:`cassandra.decoder.ordered_dict_factory` has moved to + :attr:`cassandra.query.ordered_dict_factory` + +Dependency Changes +^^^^^^^^^^^^^^^^^^ +The following dependencies have officially been made optional: + +* ``scales`` +* ``blist`` + +And one new dependency has been added (to enable Python 3 support): + +* ``six`` diff --git a/stable/_sources/user-defined-types.rst.txt b/stable/_sources/user-defined-types.rst.txt new file mode 100644 index 0000000000..32c03e37e8 --- /dev/null +++ b/stable/_sources/user-defined-types.rst.txt @@ -0,0 +1,118 @@ +.. _udts: + +User Defined Types +================== +Cassandra 2.1 introduced user-defined types (UDTs). You can create a +new type through ``CREATE TYPE`` statements in CQL:: + + CREATE TYPE address (street text, zip int); + +Version 2.1 of the Python driver adds support for user-defined types. + +Registering a UDT +----------------- +You can tell the Python driver to return columns of a specific UDT as +instances of a class or a dict by registering them with your :class:`~.Cluster` +instance through :meth:`.Cluster.register_user_type`: + + +Map a Class to a UDT +++++++++++++++++++++ + +.. code-block:: python + + cluster = Cluster(protocol_version=3) + session = cluster.connect() + session.set_keyspace('mykeyspace') + session.execute("CREATE TYPE address (street text, zipcode int)") + session.execute("CREATE TABLE users (id int PRIMARY KEY, location frozen
)") + + # create a class to map to the "address" UDT + class Address(object): + + def __init__(self, street, zipcode): + self.street = street + self.zipcode = zipcode + + cluster.register_user_type('mykeyspace', 'address', Address) + + # insert a row using an instance of Address + session.execute("INSERT INTO users (id, location) VALUES (%s, %s)", + (0, Address("123 Main St.", 78723))) + + # results will include Address instances + results = session.execute("SELECT * FROM users") + row = results[0] + print(row.id, row.location.street, row.location.zipcode) + +Map a dict to a UDT ++++++++++++++++++++ + +.. code-block:: python + + cluster = Cluster(protocol_version=3) + session = cluster.connect() + session.set_keyspace('mykeyspace') + session.execute("CREATE TYPE address (street text, zipcode int)") + session.execute("CREATE TABLE users (id int PRIMARY KEY, location frozen
)") + + cluster.register_user_type('mykeyspace', 'address', dict) + + # insert a row using a prepared statement and a tuple + insert_statement = session.prepare("INSERT INTO mykeyspace.users (id, location) VALUES (?, ?)") + session.execute(insert_statement, [0, ("123 Main St.", 78723)]) + + # results will include dict instances + results = session.execute("SELECT * FROM users") + row = results[0] + print(row.id, row.location['street'], row.location['zipcode']) + +Using UDTs Without Registering Them +----------------------------------- +Although it is recommended to register your types with +:meth:`.Cluster.register_user_type`, the driver gives you some options +for working with unregistered UDTS. + +When you use prepared statements, the driver knows what data types to +expect for each placeholder. This allows you to pass any object you +want for a UDT, as long as it has attributes that match the field names +for the UDT: + +.. code-block:: python + + cluster = Cluster(protocol_version=3) + session = cluster.connect() + session.set_keyspace('mykeyspace') + session.execute("CREATE TYPE address (street text, zipcode int)") + session.execute("CREATE TABLE users (id int PRIMARY KEY, location frozen
)") + + class Foo(object): + + def __init__(self, street, zipcode, otherstuff): + self.street = street + self.zipcode = zipcode + self.otherstuff = otherstuff + + insert_statement = session.prepare("INSERT INTO users (id, location) VALUES (?, ?)") + + # since we're using a prepared statement, we don't *have* to register + # a class to map to the UDT to insert data. The object just needs to have + # "street" and "zipcode" attributes (which Foo does): + session.execute(insert_statement, [0, Foo("123 Main St.", 78723, "some other stuff")]) + + # when we query data, UDT columns that don't have a class registered + # will be returned as namedtuples: + results = session.execute("SELECT * FROM users") + first_row = results[0] + address = first_row.location + print(address) # prints "Address(street='123 Main St.', zipcode=78723)" + street = address.street + zipcode = address.street + +As shown in the code example, inserting data for UDT columns without registering +a class works fine for prepared statements. However, **you must register a +class to insert UDT columns with unprepared statements**.\* You can still query +UDT columns without registered classes using unprepared statements, they will +simply return ``namedtuple`` instances (just like prepared statements do). + +\* this applies to *parameterized* unprepared statements, in which the driver will be formatting parameters -- not statements with interpolated UDT literals. diff --git a/stable/_static/basic.css b/stable/_static/basic.css new file mode 100644 index 0000000000..603f6a8798 --- /dev/null +++ b/stable/_static/basic.css @@ -0,0 +1,905 @@ +/* + * basic.css + * ~~~~~~~~~ + * + * Sphinx stylesheet -- basic theme. + * + * :copyright: Copyright 2007-2021 by the Sphinx team, see AUTHORS. + * :license: BSD, see LICENSE for details. + * + */ + +/* -- main layout ----------------------------------------------------------- */ + +div.clearer { + clear: both; +} + +div.section::after { + display: block; + content: ''; + clear: left; +} + +/* -- relbar ---------------------------------------------------------------- */ + +div.related { + width: 100%; + font-size: 90%; +} + +div.related h3 { + display: none; +} + +div.related ul { + margin: 0; + padding: 0 0 0 10px; + list-style: none; +} + +div.related li { + display: inline; +} + +div.related li.right { + float: right; + margin-right: 5px; +} + +/* -- sidebar --------------------------------------------------------------- */ + +div.sphinxsidebarwrapper { + padding: 10px 5px 0 10px; +} + +div.sphinxsidebar { + float: left; + width: 230px; + margin-left: -100%; + font-size: 90%; + word-wrap: break-word; + overflow-wrap : break-word; +} + +div.sphinxsidebar ul { + list-style: none; +} + +div.sphinxsidebar ul ul, +div.sphinxsidebar ul.want-points { + margin-left: 20px; + list-style: square; +} + +div.sphinxsidebar ul ul { + margin-top: 0; + margin-bottom: 0; +} + +div.sphinxsidebar form { + margin-top: 10px; +} + +div.sphinxsidebar input { + border: 1px solid #98dbcc; + font-family: sans-serif; + font-size: 1em; +} + +div.sphinxsidebar #searchbox form.search { + overflow: hidden; +} + +div.sphinxsidebar #searchbox input[type="text"] { + float: left; + width: 80%; + padding: 0.25em; + box-sizing: border-box; +} + +div.sphinxsidebar #searchbox input[type="submit"] { + float: left; + width: 20%; + border-left: none; + padding: 0.25em; + box-sizing: border-box; +} + + +img { + border: 0; + max-width: 100%; +} + +/* -- search page ----------------------------------------------------------- */ + +ul.search { + margin: 10px 0 0 20px; + padding: 0; +} + +ul.search li { + padding: 5px 0 5px 20px; + background-image: url(file.png); + background-repeat: no-repeat; + background-position: 0 7px; +} + +ul.search li a { + font-weight: bold; +} + +ul.search li p.context { + color: #888; + margin: 2px 0 0 30px; + text-align: left; +} + +ul.keywordmatches li.goodmatch a { + font-weight: bold; +} + +/* -- index page ------------------------------------------------------------ */ + +table.contentstable { + width: 90%; + margin-left: auto; + margin-right: auto; +} + +table.contentstable p.biglink { + line-height: 150%; +} + +a.biglink { + font-size: 1.3em; +} + +span.linkdescr { + font-style: italic; + padding-top: 5px; + font-size: 90%; +} + +/* -- general index --------------------------------------------------------- */ + +table.indextable { + width: 100%; +} + +table.indextable td { + text-align: left; + vertical-align: top; +} + +table.indextable ul { + margin-top: 0; + margin-bottom: 0; + list-style-type: none; +} + +table.indextable > tbody > tr > td > ul { + padding-left: 0em; +} + +table.indextable tr.pcap { + height: 10px; +} + +table.indextable tr.cap { + margin-top: 10px; + background-color: #f2f2f2; +} + +img.toggler { + margin-right: 3px; + margin-top: 3px; + cursor: pointer; +} + +div.modindex-jumpbox { + border-top: 1px solid #ddd; + border-bottom: 1px solid #ddd; + margin: 1em 0 1em 0; + padding: 0.4em; +} + +div.genindex-jumpbox { + border-top: 1px solid #ddd; + border-bottom: 1px solid #ddd; + margin: 1em 0 1em 0; + padding: 0.4em; +} + +/* -- domain module index --------------------------------------------------- */ + +table.modindextable td { + padding: 2px; + border-collapse: collapse; +} + +/* -- general body styles --------------------------------------------------- */ + +div.body { + min-width: 450px; + max-width: 800px; +} + +div.body p, div.body dd, div.body li, div.body blockquote { + -moz-hyphens: auto; + -ms-hyphens: auto; + -webkit-hyphens: auto; + hyphens: auto; +} + +a.headerlink { + visibility: hidden; +} + +a.brackets:before, +span.brackets > a:before{ + content: "["; +} + +a.brackets:after, +span.brackets > a:after { + content: "]"; +} + +h1:hover > a.headerlink, +h2:hover > a.headerlink, +h3:hover > a.headerlink, +h4:hover > a.headerlink, +h5:hover > a.headerlink, +h6:hover > a.headerlink, +dt:hover > a.headerlink, +caption:hover > a.headerlink, +p.caption:hover > a.headerlink, +div.code-block-caption:hover > a.headerlink { + visibility: visible; +} + +div.body p.caption { + text-align: inherit; +} + +div.body td { + text-align: left; +} + +.first { + margin-top: 0 !important; +} + +p.rubric { + margin-top: 30px; + font-weight: bold; +} + +img.align-left, figure.align-left, .figure.align-left, object.align-left { + clear: left; + float: left; + margin-right: 1em; +} + +img.align-right, figure.align-right, .figure.align-right, object.align-right { + clear: right; + float: right; + margin-left: 1em; +} + +img.align-center, figure.align-center, .figure.align-center, object.align-center { + display: block; + margin-left: auto; + margin-right: auto; +} + +img.align-default, figure.align-default, .figure.align-default { + display: block; + margin-left: auto; + margin-right: auto; +} + +.align-left { + text-align: left; +} + +.align-center { + text-align: center; +} + +.align-default { + text-align: center; +} + +.align-right { + text-align: right; +} + +/* -- sidebars -------------------------------------------------------------- */ + +div.sidebar, +aside.sidebar { + margin: 0 0 0.5em 1em; + border: 1px solid #ddb; + padding: 7px; + background-color: #ffe; + width: 40%; + float: right; + clear: right; + overflow-x: auto; +} + +p.sidebar-title { + font-weight: bold; +} + +div.admonition, div.topic, blockquote { + clear: left; +} + +/* -- topics ---------------------------------------------------------------- */ + +div.topic { + border: 1px solid #ccc; + padding: 7px; + margin: 10px 0 10px 0; +} + +p.topic-title { + font-size: 1.1em; + font-weight: bold; + margin-top: 10px; +} + +/* -- admonitions ----------------------------------------------------------- */ + +div.admonition { + margin-top: 10px; + margin-bottom: 10px; + padding: 7px; +} + +div.admonition dt { + font-weight: bold; +} + +p.admonition-title { + margin: 0px 10px 5px 0px; + font-weight: bold; +} + +div.body p.centered { + text-align: center; + margin-top: 25px; +} + +/* -- content of sidebars/topics/admonitions -------------------------------- */ + +div.sidebar > :last-child, +aside.sidebar > :last-child, +div.topic > :last-child, +div.admonition > :last-child { + margin-bottom: 0; +} + +div.sidebar::after, +aside.sidebar::after, +div.topic::after, +div.admonition::after, +blockquote::after { + display: block; + content: ''; + clear: both; +} + +/* -- tables ---------------------------------------------------------------- */ + +table.docutils { + margin-top: 10px; + margin-bottom: 10px; + border: 0; + border-collapse: collapse; +} + +table.align-center { + margin-left: auto; + margin-right: auto; +} + +table.align-default { + margin-left: auto; + margin-right: auto; +} + +table caption span.caption-number { + font-style: italic; +} + +table caption span.caption-text { +} + +table.docutils td, table.docutils th { + padding: 1px 8px 1px 5px; + border-top: 0; + border-left: 0; + border-right: 0; + border-bottom: 1px solid #aaa; +} + +table.footnote td, table.footnote th { + border: 0 !important; +} + +th { + text-align: left; + padding-right: 5px; +} + +table.citation { + border-left: solid 1px gray; + margin-left: 1px; +} + +table.citation td { + border-bottom: none; +} + +th > :first-child, +td > :first-child { + margin-top: 0px; +} + +th > :last-child, +td > :last-child { + margin-bottom: 0px; +} + +/* -- figures --------------------------------------------------------------- */ + +div.figure, figure { + margin: 0.5em; + padding: 0.5em; +} + +div.figure p.caption, figcaption { + padding: 0.3em; +} + +div.figure p.caption span.caption-number, +figcaption span.caption-number { + font-style: italic; +} + +div.figure p.caption span.caption-text, +figcaption span.caption-text { +} + +/* -- field list styles ----------------------------------------------------- */ + +table.field-list td, table.field-list th { + border: 0 !important; +} + +.field-list ul { + margin: 0; + padding-left: 1em; +} + +.field-list p { + margin: 0; +} + +.field-name { + -moz-hyphens: manual; + -ms-hyphens: manual; + -webkit-hyphens: manual; + hyphens: manual; +} + +/* -- hlist styles ---------------------------------------------------------- */ + +table.hlist { + margin: 1em 0; +} + +table.hlist td { + vertical-align: top; +} + +/* -- object description styles --------------------------------------------- */ + +.sig { + font-family: 'Consolas', 'Menlo', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace; +} + +.sig-name, code.descname { + background-color: transparent; + font-weight: bold; +} + +.sig-name { + font-size: 1.1em; +} + +code.descname { + font-size: 1.2em; +} + +.sig-prename, code.descclassname { + background-color: transparent; +} + +.optional { + font-size: 1.3em; +} + +.sig-paren { + font-size: larger; +} + +.sig-param.n { + font-style: italic; +} + +/* C++ specific styling */ + +.sig-inline.c-texpr, +.sig-inline.cpp-texpr { + font-family: unset; +} + +.sig.c .k, .sig.c .kt, +.sig.cpp .k, .sig.cpp .kt { + color: #0033B3; +} + +.sig.c .m, +.sig.cpp .m { + color: #1750EB; +} + +.sig.c .s, .sig.c .sc, +.sig.cpp .s, .sig.cpp .sc { + color: #067D17; +} + + +/* -- other body styles ----------------------------------------------------- */ + +ol.arabic { + list-style: decimal; +} + +ol.loweralpha { + list-style: lower-alpha; +} + +ol.upperalpha { + list-style: upper-alpha; +} + +ol.lowerroman { + list-style: lower-roman; +} + +ol.upperroman { + list-style: upper-roman; +} + +:not(li) > ol > li:first-child > :first-child, +:not(li) > ul > li:first-child > :first-child { + margin-top: 0px; +} + +:not(li) > ol > li:last-child > :last-child, +:not(li) > ul > li:last-child > :last-child { + margin-bottom: 0px; +} + +ol.simple ol p, +ol.simple ul p, +ul.simple ol p, +ul.simple ul p { + margin-top: 0; +} + +ol.simple > li:not(:first-child) > p, +ul.simple > li:not(:first-child) > p { + margin-top: 0; +} + +ol.simple p, +ul.simple p { + margin-bottom: 0; +} + +dl.footnote > dt, +dl.citation > dt { + float: left; + margin-right: 0.5em; +} + +dl.footnote > dd, +dl.citation > dd { + margin-bottom: 0em; +} + +dl.footnote > dd:after, +dl.citation > dd:after { + content: ""; + clear: both; +} + +dl.field-list { + display: grid; + grid-template-columns: fit-content(30%) auto; +} + +dl.field-list > dt { + font-weight: bold; + word-break: break-word; + padding-left: 0.5em; + padding-right: 5px; +} + +dl.field-list > dt:after { + content: ":"; +} + +dl.field-list > dd { + padding-left: 0.5em; + margin-top: 0em; + margin-left: 0em; + margin-bottom: 0em; +} + +dl { + margin-bottom: 15px; +} + +dd > :first-child { + margin-top: 0px; +} + +dd ul, dd table { + margin-bottom: 10px; +} + +dd { + margin-top: 3px; + margin-bottom: 10px; + margin-left: 30px; +} + +dl > dd:last-child, +dl > dd:last-child > :last-child { + margin-bottom: 0; +} + +dt:target, span.highlighted { + background-color: #fbe54e; +} + +rect.highlighted { + fill: #fbe54e; +} + +dl.glossary dt { + font-weight: bold; + font-size: 1.1em; +} + +.versionmodified { + font-style: italic; +} + +.system-message { + background-color: #fda; + padding: 5px; + border: 3px solid red; +} + +.footnote:target { + background-color: #ffa; +} + +.line-block { + display: block; + margin-top: 1em; + margin-bottom: 1em; +} + +.line-block .line-block { + margin-top: 0; + margin-bottom: 0; + margin-left: 1.5em; +} + +.guilabel, .menuselection { + font-family: sans-serif; +} + +.accelerator { + text-decoration: underline; +} + +.classifier { + font-style: oblique; +} + +.classifier:before { + font-style: normal; + margin: 0 0.5em; + content: ":"; + display: inline-block; +} + +abbr, acronym { + border-bottom: dotted 1px; + cursor: help; +} + +/* -- code displays --------------------------------------------------------- */ + +pre { + overflow: auto; + overflow-y: hidden; /* fixes display issues on Chrome browsers */ +} + +pre, div[class*="highlight-"] { + clear: both; +} + +span.pre { + -moz-hyphens: none; + -ms-hyphens: none; + -webkit-hyphens: none; + hyphens: none; +} + +div[class*="highlight-"] { + margin: 1em 0; +} + +td.linenos pre { + border: 0; + background-color: transparent; + color: #aaa; +} + +table.highlighttable { + display: block; +} + +table.highlighttable tbody { + display: block; +} + +table.highlighttable tr { + display: flex; +} + +table.highlighttable td { + margin: 0; + padding: 0; +} + +table.highlighttable td.linenos { + padding-right: 0.5em; +} + +table.highlighttable td.code { + flex: 1; + overflow: hidden; +} + +.highlight .hll { + display: block; +} + +div.highlight pre, +table.highlighttable pre { + margin: 0; +} + +div.code-block-caption + div { + margin-top: 0; +} + +div.code-block-caption { + margin-top: 1em; + padding: 2px 5px; + font-size: small; +} + +div.code-block-caption code { + background-color: transparent; +} + +table.highlighttable td.linenos, +span.linenos, +div.highlight span.gp { /* gp: Generic.Prompt */ + user-select: none; + -webkit-user-select: text; /* Safari fallback only */ + -webkit-user-select: none; /* Chrome/Safari */ + -moz-user-select: none; /* Firefox */ + -ms-user-select: none; /* IE10+ */ +} + +div.code-block-caption span.caption-number { + padding: 0.1em 0.3em; + font-style: italic; +} + +div.code-block-caption span.caption-text { +} + +div.literal-block-wrapper { + margin: 1em 0; +} + +code.xref, a code { + background-color: transparent; + font-weight: bold; +} + +h1 code, h2 code, h3 code, h4 code, h5 code, h6 code { + background-color: transparent; +} + +.viewcode-link { + float: right; +} + +.viewcode-back { + float: right; + font-family: sans-serif; +} + +div.viewcode-block:target { + margin: -1px -10px; + padding: 0 10px; +} + +/* -- math display ---------------------------------------------------------- */ + +img.math { + vertical-align: middle; +} + +div.body div.math p { + text-align: center; +} + +span.eqno { + float: right; +} + +span.eqno a.headerlink { + position: absolute; + z-index: 1; +} + +div.math:hover a.headerlink { + visibility: visible; +} + +/* -- printout stylesheet --------------------------------------------------- */ + +@media print { + div.document, + div.documentwrapper, + div.bodywrapper { + margin: 0 !important; + width: 100%; + } + + div.sphinxsidebar, + div.related, + div.footer, + #top-link { + display: none; + } +} \ No newline at end of file diff --git a/stable/_static/check-solid.svg b/stable/_static/check-solid.svg new file mode 100644 index 0000000000..92fad4b5c0 --- /dev/null +++ b/stable/_static/check-solid.svg @@ -0,0 +1,4 @@ + + + + diff --git a/stable/_static/clipboard.min.js b/stable/_static/clipboard.min.js new file mode 100644 index 0000000000..54b3c46381 --- /dev/null +++ b/stable/_static/clipboard.min.js @@ -0,0 +1,7 @@ +/*! + * clipboard.js v2.0.8 + * https://clipboardjs.com/ + * + * Licensed MIT © Zeno Rocha + */ +!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?exports.ClipboardJS=e():t.ClipboardJS=e()}(this,function(){return n={686:function(t,e,n){"use strict";n.d(e,{default:function(){return o}});var e=n(279),i=n.n(e),e=n(370),u=n.n(e),e=n(817),c=n.n(e);function a(t){try{return document.execCommand(t)}catch(t){return}}var f=function(t){t=c()(t);return a("cut"),t};var l=function(t){var e,n,o,r=1 + + + + diff --git a/stable/_static/copybutton.css b/stable/_static/copybutton.css new file mode 100644 index 0000000000..f1916ec7d1 --- /dev/null +++ b/stable/_static/copybutton.css @@ -0,0 +1,94 @@ +/* Copy buttons */ +button.copybtn { + position: absolute; + display: flex; + top: .3em; + right: .3em; + width: 1.7em; + height: 1.7em; + opacity: 0; + transition: opacity 0.3s, border .3s, background-color .3s; + user-select: none; + padding: 0; + border: none; + outline: none; + border-radius: 0.4em; + /* The colors that GitHub uses */ + border: #1b1f2426 1px solid; + background-color: #f6f8fa; + color: #57606a; +} + +button.copybtn.success { + border-color: #22863a; + color: #22863a; +} + +button.copybtn svg { + stroke: currentColor; + width: 1.5em; + height: 1.5em; + padding: 0.1em; +} + +div.highlight { + position: relative; +} + +/* Show the copybutton */ +.highlight:hover button.copybtn, button.copybtn.success { + opacity: 1; +} + +.highlight button.copybtn:hover { + background-color: rgb(235, 235, 235); +} + +.highlight button.copybtn:active { + background-color: rgb(187, 187, 187); +} + +/** + * A minimal CSS-only tooltip copied from: + * https://codepen.io/mildrenben/pen/rVBrpK + * + * To use, write HTML like the following: + * + *

Short

+ */ + .o-tooltip--left { + position: relative; + } + + .o-tooltip--left:after { + opacity: 0; + visibility: hidden; + position: absolute; + content: attr(data-tooltip); + padding: .2em; + font-size: .8em; + left: -.2em; + background: grey; + color: white; + white-space: nowrap; + z-index: 2; + border-radius: 2px; + transform: translateX(-102%) translateY(0); + transition: opacity 0.2s cubic-bezier(0.64, 0.09, 0.08, 1), transform 0.2s cubic-bezier(0.64, 0.09, 0.08, 1); +} + +.o-tooltip--left:hover:after { + display: block; + opacity: 1; + visibility: visible; + transform: translateX(-100%) translateY(0); + transition: opacity 0.2s cubic-bezier(0.64, 0.09, 0.08, 1), transform 0.2s cubic-bezier(0.64, 0.09, 0.08, 1); + transition-delay: .5s; +} + +/* By default the copy button shouldn't show up when printing a page */ +@media print { + button.copybtn { + display: none; + } +} diff --git a/stable/_static/copybutton.js b/stable/_static/copybutton.js new file mode 100644 index 0000000000..2ea7ff3e21 --- /dev/null +++ b/stable/_static/copybutton.js @@ -0,0 +1,248 @@ +// Localization support +const messages = { + 'en': { + 'copy': 'Copy', + 'copy_to_clipboard': 'Copy to clipboard', + 'copy_success': 'Copied!', + 'copy_failure': 'Failed to copy', + }, + 'es' : { + 'copy': 'Copiar', + 'copy_to_clipboard': 'Copiar al portapapeles', + 'copy_success': '¡Copiado!', + 'copy_failure': 'Error al copiar', + }, + 'de' : { + 'copy': 'Kopieren', + 'copy_to_clipboard': 'In die Zwischenablage kopieren', + 'copy_success': 'Kopiert!', + 'copy_failure': 'Fehler beim Kopieren', + }, + 'fr' : { + 'copy': 'Copier', + 'copy_to_clipboard': 'Copier dans le presse-papier', + 'copy_success': 'Copié !', + 'copy_failure': 'Échec de la copie', + }, + 'ru': { + 'copy': 'Скопировать', + 'copy_to_clipboard': 'Скопировать в буфер', + 'copy_success': 'Скопировано!', + 'copy_failure': 'Не удалось скопировать', + }, + 'zh-CN': { + 'copy': '复制', + 'copy_to_clipboard': '复制到剪贴板', + 'copy_success': '复制成功!', + 'copy_failure': '复制失败', + }, + 'it' : { + 'copy': 'Copiare', + 'copy_to_clipboard': 'Copiato negli appunti', + 'copy_success': 'Copiato!', + 'copy_failure': 'Errore durante la copia', + } +} + +let locale = 'en' +if( document.documentElement.lang !== undefined + && messages[document.documentElement.lang] !== undefined ) { + locale = document.documentElement.lang +} + +let doc_url_root = DOCUMENTATION_OPTIONS.URL_ROOT; +if (doc_url_root == '#') { + doc_url_root = ''; +} + +/** + * SVG files for our copy buttons + */ +let iconCheck = ` + ${messages[locale]['copy_success']} + + +` + +// If the user specified their own SVG use that, otherwise use the default +let iconCopy = ``; +if (!iconCopy) { + iconCopy = ` + ${messages[locale]['copy_to_clipboard']} + + + +` +} + +/** + * Set up copy/paste for code blocks + */ + +const runWhenDOMLoaded = cb => { + if (document.readyState != 'loading') { + cb() + } else if (document.addEventListener) { + document.addEventListener('DOMContentLoaded', cb) + } else { + document.attachEvent('onreadystatechange', function() { + if (document.readyState == 'complete') cb() + }) + } +} + +const codeCellId = index => `codecell${index}` + +// Clears selected text since ClipboardJS will select the text when copying +const clearSelection = () => { + if (window.getSelection) { + window.getSelection().removeAllRanges() + } else if (document.selection) { + document.selection.empty() + } +} + +// Changes tooltip text for a moment, then changes it back +// We want the timeout of our `success` class to be a bit shorter than the +// tooltip and icon change, so that we can hide the icon before changing back. +var timeoutIcon = 2000; +var timeoutSuccessClass = 1500; + +const temporarilyChangeTooltip = (el, oldText, newText) => { + el.setAttribute('data-tooltip', newText) + el.classList.add('success') + // Remove success a little bit sooner than we change the tooltip + // So that we can use CSS to hide the copybutton first + setTimeout(() => el.classList.remove('success'), timeoutSuccessClass) + setTimeout(() => el.setAttribute('data-tooltip', oldText), timeoutIcon) +} + +// Changes the copy button icon for two seconds, then changes it back +const temporarilyChangeIcon = (el) => { + el.innerHTML = iconCheck; + setTimeout(() => {el.innerHTML = iconCopy}, timeoutIcon) +} + +const addCopyButtonToCodeCells = () => { + // If ClipboardJS hasn't loaded, wait a bit and try again. This + // happens because we load ClipboardJS asynchronously. + if (window.ClipboardJS === undefined) { + setTimeout(addCopyButtonToCodeCells, 250) + return + } + + // Add copybuttons to all of our code cells + const COPYBUTTON_SELECTOR = 'div.highlight pre'; + const codeCells = document.querySelectorAll(COPYBUTTON_SELECTOR) + codeCells.forEach((codeCell, index) => { + const id = codeCellId(index) + codeCell.setAttribute('id', id) + + const clipboardButton = id => + `` + codeCell.insertAdjacentHTML('afterend', clipboardButton(id)) + }) + +function escapeRegExp(string) { + return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string +} + +/** + * Removes excluded text from a Node. + * + * @param {Node} target Node to filter. + * @param {string} exclude CSS selector of nodes to exclude. + * @returns {DOMString} Text from `target` with text removed. + */ +function filterText(target, exclude) { + const clone = target.cloneNode(true); // clone as to not modify the live DOM + if (exclude) { + // remove excluded nodes + clone.querySelectorAll(exclude).forEach(node => node.remove()); + } + return clone.innerText; +} + +// Callback when a copy button is clicked. Will be passed the node that was clicked +// should then grab the text and replace pieces of text that shouldn't be used in output +function formatCopyText(textContent, copybuttonPromptText, isRegexp = false, onlyCopyPromptLines = true, removePrompts = true, copyEmptyLines = true, lineContinuationChar = "", hereDocDelim = "") { + var regexp; + var match; + + // Do we check for line continuation characters and "HERE-documents"? + var useLineCont = !!lineContinuationChar + var useHereDoc = !!hereDocDelim + + // create regexp to capture prompt and remaining line + if (isRegexp) { + regexp = new RegExp('^(' + copybuttonPromptText + ')(.*)') + } else { + regexp = new RegExp('^(' + escapeRegExp(copybuttonPromptText) + ')(.*)') + } + + const outputLines = []; + var promptFound = false; + var gotLineCont = false; + var gotHereDoc = false; + const lineGotPrompt = []; + for (const line of textContent.split('\n')) { + match = line.match(regexp) + if (match || gotLineCont || gotHereDoc) { + promptFound = regexp.test(line) + lineGotPrompt.push(promptFound) + if (removePrompts && promptFound) { + outputLines.push(match[2]) + } else { + outputLines.push(line) + } + gotLineCont = line.endsWith(lineContinuationChar) & useLineCont + if (line.includes(hereDocDelim) & useHereDoc) + gotHereDoc = !gotHereDoc + } else if (!onlyCopyPromptLines) { + outputLines.push(line) + } else if (copyEmptyLines && line.trim() === '') { + outputLines.push(line) + } + } + + // If no lines with the prompt were found then just use original lines + if (lineGotPrompt.some(v => v === true)) { + textContent = outputLines.join('\n'); + } + + // Remove a trailing newline to avoid auto-running when pasting + if (textContent.endsWith("\n")) { + textContent = textContent.slice(0, -1) + } + return textContent +} + + +var copyTargetText = (trigger) => { + var target = document.querySelector(trigger.attributes['data-clipboard-target'].value); + + // get filtered text + let exclude = '.linenos'; + + let text = filterText(target, exclude); + return formatCopyText(text, '', false, true, true, true, '', '') +} + + // Initialize with a callback so we can modify the text before copy + const clipboard = new ClipboardJS('.copybtn', {text: copyTargetText}) + + // Update UI with error/success messages + clipboard.on('success', event => { + clearSelection() + temporarilyChangeTooltip(event.trigger, messages[locale]['copy'], messages[locale]['copy_success']) + temporarilyChangeIcon(event.trigger) + }) + + clipboard.on('error', event => { + temporarilyChangeTooltip(event.trigger, messages[locale]['copy'], messages[locale]['copy_failure']) + }) +} + +runWhenDOMLoaded(addCopyButtonToCodeCells) \ No newline at end of file diff --git a/stable/_static/copybutton_funcs.js b/stable/_static/copybutton_funcs.js new file mode 100644 index 0000000000..dbe1aaad79 --- /dev/null +++ b/stable/_static/copybutton_funcs.js @@ -0,0 +1,73 @@ +function escapeRegExp(string) { + return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string +} + +/** + * Removes excluded text from a Node. + * + * @param {Node} target Node to filter. + * @param {string} exclude CSS selector of nodes to exclude. + * @returns {DOMString} Text from `target` with text removed. + */ +export function filterText(target, exclude) { + const clone = target.cloneNode(true); // clone as to not modify the live DOM + if (exclude) { + // remove excluded nodes + clone.querySelectorAll(exclude).forEach(node => node.remove()); + } + return clone.innerText; +} + +// Callback when a copy button is clicked. Will be passed the node that was clicked +// should then grab the text and replace pieces of text that shouldn't be used in output +export function formatCopyText(textContent, copybuttonPromptText, isRegexp = false, onlyCopyPromptLines = true, removePrompts = true, copyEmptyLines = true, lineContinuationChar = "", hereDocDelim = "") { + var regexp; + var match; + + // Do we check for line continuation characters and "HERE-documents"? + var useLineCont = !!lineContinuationChar + var useHereDoc = !!hereDocDelim + + // create regexp to capture prompt and remaining line + if (isRegexp) { + regexp = new RegExp('^(' + copybuttonPromptText + ')(.*)') + } else { + regexp = new RegExp('^(' + escapeRegExp(copybuttonPromptText) + ')(.*)') + } + + const outputLines = []; + var promptFound = false; + var gotLineCont = false; + var gotHereDoc = false; + const lineGotPrompt = []; + for (const line of textContent.split('\n')) { + match = line.match(regexp) + if (match || gotLineCont || gotHereDoc) { + promptFound = regexp.test(line) + lineGotPrompt.push(promptFound) + if (removePrompts && promptFound) { + outputLines.push(match[2]) + } else { + outputLines.push(line) + } + gotLineCont = line.endsWith(lineContinuationChar) & useLineCont + if (line.includes(hereDocDelim) & useHereDoc) + gotHereDoc = !gotHereDoc + } else if (!onlyCopyPromptLines) { + outputLines.push(line) + } else if (copyEmptyLines && line.trim() === '') { + outputLines.push(line) + } + } + + // If no lines with the prompt were found then just use original lines + if (lineGotPrompt.some(v => v === true)) { + textContent = outputLines.join('\n'); + } + + // Remove a trailing newline to avoid auto-running when pasting + if (textContent.endsWith("\n")) { + textContent = textContent.slice(0, -1) + } + return textContent +} diff --git a/stable/_static/css/main.css b/stable/_static/css/main.css new file mode 100644 index 0000000000..4ac0174528 --- /dev/null +++ b/stable/_static/css/main.css @@ -0,0 +1 @@ +@media print,screen and (min-width:40em){.reveal,.reveal.large,.reveal.small,.reveal.tiny{left:auto;margin:0 auto;right:auto}}/*! normalize.css v8.0.0 | MIT License | github.com/necolas/normalize.css */html{-webkit-text-size-adjust:100%;line-height:1.15}h1{font-size:2em;margin:.67em 0}hr{-webkit-box-sizing:content-box;box-sizing:content-box;overflow:visible}pre{font-family:monospace,monospace;font-size:1em}a{background-color:transparent}abbr[title]{border-bottom:0;-webkit-text-decoration:underline dotted;text-decoration:underline dotted}b,strong{font-weight:bolder}code,kbd,samp{font-family:monospace,monospace;font-size:1em}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}img{border-style:none}button,input,optgroup,select,textarea{font-size:100%;line-height:1.15;margin:0}button,input{overflow:visible}button,select{text-transform:none}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button}[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner,button::-moz-focus-inner{border-style:none;padding:0}[type=button]:-moz-focusring,[type=reset]:-moz-focusring,[type=submit]:-moz-focusring,button:-moz-focusring{outline:1px dotted ButtonText}fieldset{padding:.35em .75em .625em}legend{-webkit-box-sizing:border-box;box-sizing:border-box;color:inherit;display:table;padding:0;white-space:normal}progress{vertical-align:baseline}textarea{overflow:auto}[type=checkbox],[type=radio]{-webkit-box-sizing:border-box;box-sizing:border-box;padding:0}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}details{display:block}summary{display:list-item}template{display:none}[hidden]{display:none}[data-whatinput=mouse] *,[data-whatinput=mouse] :focus,[data-whatinput=touch] *,[data-whatinput=touch] :focus,[data-whatintent=mouse] *,[data-whatintent=mouse] :focus,[data-whatintent=touch] *,[data-whatintent=touch] :focus{outline:0}[draggable=false]{-webkit-touch-callout:none;-webkit-user-select:none}.foundation-mq{font-family:"small=0em&medium=40em&large=64em&xlarge=75em&xxlarge=90em"}html{-webkit-box-sizing:border-box;font-size:100%}*,:after,:before{-webkit-box-sizing:inherit}body{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;background:#fefefe;color:#0a0a0a;font-family:Helvetica Neue,Helvetica,Roboto,Arial,sans-serif;font-weight:400;line-height:1.5;margin:0;padding:0}img{-ms-interpolation-mode:bicubic;display:inline-block;height:auto;vertical-align:middle}textarea{border-radius:0;height:auto;min-height:50px}select{-webkit-box-sizing:border-box;box-sizing:border-box;width:100%}.map_canvas embed,.map_canvas img,.map_canvas object,.mqa-display embed,.mqa-display img,.mqa-display object{max-width:none!important}button{-webkit-appearance:none;-moz-appearance:none;appearance:none;background:0 0;border:0;border-radius:0;cursor:auto;line-height:1;padding:0}[data-whatinput=mouse] button{outline:0}pre{-webkit-overflow-scrolling:touch;overflow:auto}button,input,optgroup,select,textarea{font-family:inherit}.is-visible{display:block!important}.is-hidden{display:none!important}[type=color],[type=date],[type=datetime-local],[type=datetime],[type=email],[type=month],[type=number],[type=password],[type=search],[type=tel],[type=text],[type=time],[type=url],[type=week],textarea{-webkit-appearance:none;-moz-appearance:none;appearance:none;background-color:#fefefe;border:1px solid #cacaca;border-radius:0;-webkit-box-shadow:inset 0 1px 2px hsla(0,0%,4%,.1);box-shadow:inset 0 1px 2px hsla(0,0%,4%,.1);-webkit-box-sizing:border-box;box-sizing:border-box;color:#0a0a0a;display:block;font-family:inherit;font-size:1rem;font-weight:400;height:2.4375rem;line-height:1.5;margin:0 0 1rem;padding:.5rem;-webkit-transition:border-color .25s ease-in-out,-webkit-box-shadow .5s;transition:border-color .25s ease-in-out,-webkit-box-shadow .5s;transition:box-shadow .5s,border-color .25s ease-in-out;transition:box-shadow .5s,border-color .25s ease-in-out,-webkit-box-shadow .5s;width:100%}[type=color]:focus,[type=date]:focus,[type=datetime-local]:focus,[type=datetime]:focus,[type=email]:focus,[type=month]:focus,[type=number]:focus,[type=password]:focus,[type=search]:focus,[type=tel]:focus,[type=text]:focus,[type=time]:focus,[type=url]:focus,[type=week]:focus,textarea:focus{background-color:#fefefe;border:1px solid #8a8a8a;-webkit-box-shadow:0 0 5px #cacaca;box-shadow:0 0 5px #cacaca;outline:0;-webkit-transition:border-color .25s ease-in-out,-webkit-box-shadow .5s;transition:border-color .25s ease-in-out,-webkit-box-shadow .5s;transition:box-shadow .5s,border-color .25s ease-in-out;transition:box-shadow .5s,border-color .25s ease-in-out,-webkit-box-shadow .5s}textarea{max-width:100%}textarea[rows]{height:auto}input:disabled,input[readonly],textarea:disabled,textarea[readonly]{background-color:#e6e6e6;cursor:not-allowed}[type=button],[type=submit]{-webkit-appearance:none;-moz-appearance:none;appearance:none;border-radius:0}input[type=search]{-webkit-box-sizing:border-box;box-sizing:border-box}::-webkit-input-placeholder{color:#cacaca}::-moz-placeholder{color:#cacaca}:-ms-input-placeholder{color:#cacaca}::-ms-input-placeholder{color:#cacaca}::placeholder{color:#cacaca}[type=checkbox],[type=file],[type=radio]{margin:0 0 1rem}[type=checkbox]+label,[type=radio]+label{display:inline-block;margin-bottom:0;margin-left:.5rem;margin-right:1rem;vertical-align:baseline}[type=checkbox]+label[for],[type=radio]+label[for]{cursor:pointer}label>[type=checkbox],label>[type=radio]{margin-right:.5rem}[type=file]{width:100%}label{color:#0a0a0a;display:block;font-size:.875rem;font-weight:400;line-height:1.8;margin:0}label.middle{line-height:1.5;margin:0 0 1rem;padding:.5625rem 0}.help-text{color:#0a0a0a;font-size:.8125rem;font-style:italic;margin-top:-.5rem}.input-group{-webkit-box-align:stretch;-ms-flex-align:stretch;-webkit-align-items:stretch;align-items:stretch;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;margin-bottom:1rem;width:100%}.input-group>:first-child,.input-group>:first-child.input-group-button>*{border-radius:0}.input-group>:last-child,.input-group>:last-child.input-group-button>*{border-radius:0}.input-group-button,.input-group-button a,.input-group-button button,.input-group-button input,.input-group-button label,.input-group-field,.input-group-label{margin:0;white-space:nowrap}.input-group-label{-webkit-box-flex:0;-webkit-box-align:center;-ms-flex-align:center;-webkit-align-items:center;align-items:center;background:#e6e6e6;border:1px solid #cacaca;color:#0a0a0a;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto;padding:0 1rem;text-align:center;white-space:nowrap}.input-group-label:first-child{border-right:0}.input-group-label:last-child{border-left:0}.input-group-field{-webkit-box-flex:1;border-radius:0;-webkit-flex:1 1 0px;-ms-flex:1 1 0px;flex:1 1 0px;min-width:0}.input-group-button{-webkit-box-flex:0;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto;padding-bottom:0;padding-top:0;text-align:center}.input-group-button a,.input-group-button button,.input-group-button input,.input-group-button label{-ms-flex-item-align:stretch;-webkit-align-self:stretch;align-self:stretch;font-size:1rem;height:auto;padding-bottom:0;padding-top:0}fieldset{border:0;margin:0;padding:0}legend{margin-bottom:.5rem;max-width:100%}.fieldset{border:1px solid #cacaca;margin:1.125rem 0;padding:1.25rem}.fieldset legend{margin:0 0 0 -.1875rem;padding:0 .1875rem}select{-webkit-appearance:none;-moz-appearance:none;appearance:none;background-color:#fefefe;background-image:url('data:image/svg+xml;utf8,');background-origin:content-box;background-position:right -1rem center;background-repeat:no-repeat;background-size:9px 6px;border:1px solid #cacaca;border-radius:0;color:#0a0a0a;font-family:inherit;font-size:1rem;font-weight:400;height:2.4375rem;line-height:1.5;margin:0 0 1rem;padding:.5rem 1.5rem .5rem .5rem;-webkit-transition:border-color .25s ease-in-out,-webkit-box-shadow .5s;transition:border-color .25s ease-in-out,-webkit-box-shadow .5s;transition:box-shadow .5s,border-color .25s ease-in-out;transition:box-shadow .5s,border-color .25s ease-in-out,-webkit-box-shadow .5s}@media screen and (min-width:0\0){select{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAYCAYAAACbU/80AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAIpJREFUeNrEkckNgDAMBBfRkEt0ObRBBdsGXUDgmQfK4XhH2m8czQAAy27R3tsw4Qfe2x8uOO6oYLb6GlOor3GF+swURAOmUJ+RwtEJs9WvTGEYxBXqI1MQAZhCfUQKRzDMVj+TwrAIV6jvSUEkYAr1LSkcyTBb/V+KYfX7xAeusq3sLDtGH3kEGACPWIflNZfhRQAAAABJRU5ErkJggg==)}}select:focus{background-color:#fefefe;border:1px solid #8a8a8a;-webkit-box-shadow:0 0 5px #cacaca;box-shadow:0 0 5px #cacaca;outline:0;-webkit-transition:border-color .25s ease-in-out,-webkit-box-shadow .5s;transition:border-color .25s ease-in-out,-webkit-box-shadow .5s;transition:box-shadow .5s,border-color .25s ease-in-out;transition:box-shadow .5s,border-color .25s ease-in-out,-webkit-box-shadow .5s}select:disabled{background-color:#e6e6e6;cursor:not-allowed}select::-ms-expand{display:none}select[multiple]{background-image:none;height:auto}select:not([multiple]){padding-bottom:0;padding-top:0}.is-invalid-input:not(:focus){background-color:#f9ecea;border-color:#cc4b37}.is-invalid-input:not(:focus)::-webkit-input-placeholder{color:#cc4b37}.is-invalid-input:not(:focus)::-moz-placeholder{color:#cc4b37}.is-invalid-input:not(:focus):-ms-input-placeholder{color:#cc4b37}.is-invalid-input:not(:focus)::-ms-input-placeholder{color:#cc4b37}.is-invalid-input:not(:focus)::placeholder{color:#cc4b37}.form-error,.is-invalid-label{color:#cc4b37}.form-error{display:none;font-size:.75rem;font-weight:700;margin-bottom:1rem;margin-top:-.5rem}.form-error.is-visible{display:block}blockquote,dd,div,dl,dt,form,h1,h2,h3,h4,h5,h6,li,ol,p,pre,td,th,ul{margin:0;padding:0}p{text-rendering:optimizeLegibility;font-size:inherit;line-height:1.6;margin-bottom:1rem}em,i{font-style:italic}b,em,i,strong{line-height:inherit}b,strong{font-weight:700}small{font-size:80%;line-height:inherit}.h1,.h2,.h3,.h4,.h5,.h6,h1,h2,h3,h4,h5,h6{text-rendering:optimizeLegibility;color:inherit;font-family:Helvetica Neue,Helvetica,Roboto,Arial,sans-serif;font-style:normal;font-weight:400}.h1 small,.h2 small,.h3 small,.h4 small,.h5 small,.h6 small,h1 small,h2 small,h3 small,h4 small,h5 small,h6 small{color:#cacaca;line-height:0}.h1,h1{font-size:1.5rem}.h1,.h2,h1,h2{line-height:1.4;margin-bottom:.5rem;margin-top:0}.h2,h2{font-size:1.25rem}.h3,h3{font-size:1.1875rem}.h3,.h4,h3,h4{line-height:1.4;margin-bottom:.5rem;margin-top:0}.h4,h4{font-size:1.125rem}.h5,h5{font-size:1.0625rem}.h5,.h6,h5,h6{line-height:1.4;margin-bottom:.5rem;margin-top:0}.h6,h6{font-size:1rem}@media print,screen and (min-width:40em){.h1,h1{font-size:3rem}.h2,h2{font-size:2.5rem}.h3,h3{font-size:1.9375rem}.h4,h4{font-size:1.5625rem}.h5,h5{font-size:1.25rem}.h6,h6{font-size:1rem}}a{color:#1779ba;cursor:pointer;line-height:inherit;text-decoration:none}a:focus,a:hover{color:#1468a0}a img,hr{border:0}hr{border-bottom:1px solid #cacaca;clear:both;height:0;margin:1.25rem auto;max-width:75rem}dl,ol,ul{line-height:1.6;list-style-position:outside;margin-bottom:1rem}li{font-size:inherit}ul{list-style-type:disc}ol,ul{margin-left:1.25rem}ol ol,ol ul,ul ol,ul ul{margin-bottom:0;margin-left:1.25rem}dl{margin-bottom:1rem}dl dt{font-weight:700;margin-bottom:.3rem}blockquote{border-left:1px solid #cacaca;margin:0 0 1rem;padding:.5625rem 1.25rem 0 1.1875rem}blockquote,blockquote p{color:#8a8a8a;line-height:1.6}abbr,abbr[title]{border-bottom:1px dotted #0a0a0a;cursor:help;text-decoration:none}figure,kbd{margin:0}kbd{background-color:#e6e6e6;color:#0a0a0a;font-family:Consolas,Liberation Mono,Courier,monospace;padding:.125rem .25rem 0}.subheader{color:#8a8a8a;font-weight:400;line-height:1.4;margin-bottom:.5rem;margin-top:.2rem}.lead{font-size:125%;line-height:1.6}.stat{font-size:2.5rem;line-height:1}p+.stat{margin-top:-1rem}ol.no-bullet,ul.no-bullet{list-style:none;margin-left:0}.cite-block,cite{color:#8a8a8a;display:block;font-size:.8125rem}.cite-block:before,cite:before{content:"— "}.code-inline,code{word-wrap:break-word;display:inline;max-width:100%;padding:.125rem .3125rem .0625rem}.code-block,.code-inline,code{background-color:#e6e6e6;border:1px solid #cacaca;color:#0a0a0a;font-family:Consolas,Liberation Mono,Courier,monospace;font-weight:400}.code-block{display:block;margin-bottom:1.5rem;overflow:auto;padding:1rem;white-space:pre}.text-left{text-align:left}.text-right{text-align:right}.text-center{text-align:center}.text-justify{text-align:justify}@media print,screen and (min-width:40em){.medium-text-left{text-align:left}.medium-text-right{text-align:right}.medium-text-center{text-align:center}.medium-text-justify{text-align:justify}}@media print,screen and (min-width:64em){.large-text-left{text-align:left}.large-text-right{text-align:right}.large-text-center{text-align:center}.large-text-justify{text-align:justify}}.show-for-print{display:none!important}@media print{*{-webkit-print-color-adjust:economy;background:0 0!important;-webkit-box-shadow:none!important;box-shadow:none!important;color:#000!important;color-adjust:economy;text-shadow:none!important}.show-for-print{display:block!important}.hide-for-print{display:none!important}table.show-for-print{display:table!important}thead.show-for-print{display:table-header-group!important}tbody.show-for-print{display:table-row-group!important}tr.show-for-print{display:table-row!important}td.show-for-print,th.show-for-print{display:table-cell!important}a,a:visited{text-decoration:underline}a[href]:after{content:" (" attr(href) ")"}.ir a:after,a[href^="#"]:after,a[href^="javascript:"]:after{content:""}abbr[title]:after{content:" (" attr(title) ")"}blockquote,pre{border:1px solid #8a8a8a;page-break-inside:avoid}thead{display:table-header-group}img,tr{page-break-inside:avoid}img{max-width:100%!important}@page{margin:.5cm}h2,h3,p{orphans:3;widows:3}h2,h3{page-break-after:avoid}.print-break-inside{page-break-inside:auto}}.grid-container{margin-left:auto;margin-right:auto;max-width:75rem;padding-left:.625rem;padding-right:.625rem}@media print,screen and (min-width:40em){.grid-container{padding-left:.9375rem;padding-right:.9375rem}}.grid-container.fluid{margin-left:auto;margin-right:auto;max-width:100%;padding-left:.625rem;padding-right:.625rem}@media print,screen and (min-width:40em){.grid-container.fluid{padding-left:.9375rem;padding-right:.9375rem}}.grid-container.full{margin-left:auto;margin-right:auto;max-width:100%;padding-left:0;padding-right:0}.grid-x{-webkit-box-orient:horizontal;-webkit-box-direction:normal;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-flow:row wrap;-ms-flex-flow:row wrap;flex-flow:row wrap}.cell{-webkit-box-flex:0;-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto;min-height:0;min-width:0;width:100%}.cell.auto{-webkit-box-flex:1;-webkit-flex:1 1 0;-ms-flex:1 1 0px;flex:1 1 0}.cell.shrink{-webkit-box-flex:0;-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto}.grid-x>.auto{width:auto}.grid-x>.shrink{width:auto}.grid-x>.small-1,.grid-x>.small-2,.grid-x>.small-3,.grid-x>.small-4,.grid-x>.small-5,.grid-x>.small-6,.grid-x>.small-7,.grid-x>.small-8,.grid-x>.small-9,.grid-x>.small-10,.grid-x>.small-11,.grid-x>.small-12,.grid-x>.small-full,.grid-x>.small-shrink{-ms-flex-preferred-size:auto;-webkit-flex-basis:auto;flex-basis:auto}@media print,screen and (min-width:40em){.grid-x>.medium-1,.grid-x>.medium-2,.grid-x>.medium-3,.grid-x>.medium-4,.grid-x>.medium-5,.grid-x>.medium-6,.grid-x>.medium-7,.grid-x>.medium-8,.grid-x>.medium-9,.grid-x>.medium-10,.grid-x>.medium-11,.grid-x>.medium-12,.grid-x>.medium-full,.grid-x>.medium-shrink{-ms-flex-preferred-size:auto;-webkit-flex-basis:auto;flex-basis:auto}}@media print,screen and (min-width:64em){.grid-x>.large-1,.grid-x>.large-2,.grid-x>.large-3,.grid-x>.large-4,.grid-x>.large-5,.grid-x>.large-6,.grid-x>.large-7,.grid-x>.large-8,.grid-x>.large-9,.grid-x>.large-10,.grid-x>.large-11,.grid-x>.large-12,.grid-x>.large-full,.grid-x>.large-shrink{-ms-flex-preferred-size:auto;-webkit-flex-basis:auto;flex-basis:auto}}.grid-x>.small-1,.grid-x>.small-2,.grid-x>.small-3,.grid-x>.small-4,.grid-x>.small-5,.grid-x>.small-6,.grid-x>.small-7,.grid-x>.small-8,.grid-x>.small-9,.grid-x>.small-10,.grid-x>.small-11,.grid-x>.small-12{-webkit-box-flex:0;-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto}.grid-x>.small-1{width:8.33333%}.grid-x>.small-2{width:16.66667%}.grid-x>.small-3{width:25%}.grid-x>.small-4{width:33.33333%}.grid-x>.small-5{width:41.66667%}.grid-x>.small-6{width:50%}.grid-x>.small-7{width:58.33333%}.grid-x>.small-8{width:66.66667%}.grid-x>.small-9{width:75%}.grid-x>.small-10{width:83.33333%}.grid-x>.small-11{width:91.66667%}.grid-x>.small-12{width:100%}@media print,screen and (min-width:40em){.grid-x>.medium-auto{-webkit-box-flex:1;-webkit-flex:1 1 0;-ms-flex:1 1 0px;flex:1 1 0;width:auto}.grid-x>.medium-1,.grid-x>.medium-2,.grid-x>.medium-3,.grid-x>.medium-4,.grid-x>.medium-5,.grid-x>.medium-6,.grid-x>.medium-7,.grid-x>.medium-8,.grid-x>.medium-9,.grid-x>.medium-10,.grid-x>.medium-11,.grid-x>.medium-12,.grid-x>.medium-shrink{-webkit-box-flex:0;-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto}.grid-x>.medium-shrink{width:auto}.grid-x>.medium-1{width:8.33333%}.grid-x>.medium-2{width:16.66667%}.grid-x>.medium-3{width:25%}.grid-x>.medium-4{width:33.33333%}.grid-x>.medium-5{width:41.66667%}.grid-x>.medium-6{width:50%}.grid-x>.medium-7{width:58.33333%}.grid-x>.medium-8{width:66.66667%}.grid-x>.medium-9{width:75%}.grid-x>.medium-10{width:83.33333%}.grid-x>.medium-11{width:91.66667%}.grid-x>.medium-12{width:100%}}@media print,screen and (min-width:64em){.grid-x>.large-auto{-webkit-box-flex:1;-webkit-flex:1 1 0;-ms-flex:1 1 0px;flex:1 1 0;width:auto}.grid-x>.large-1,.grid-x>.large-2,.grid-x>.large-3,.grid-x>.large-4,.grid-x>.large-5,.grid-x>.large-6,.grid-x>.large-7,.grid-x>.large-8,.grid-x>.large-9,.grid-x>.large-10,.grid-x>.large-11,.grid-x>.large-12,.grid-x>.large-shrink{-webkit-box-flex:0;-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto}.grid-x>.large-shrink{width:auto}.grid-x>.large-1{width:8.33333%}.grid-x>.large-2{width:16.66667%}.grid-x>.large-3{width:25%}.grid-x>.large-4{width:33.33333%}.grid-x>.large-5{width:41.66667%}.grid-x>.large-6{width:50%}.grid-x>.large-7{width:58.33333%}.grid-x>.large-8{width:66.66667%}.grid-x>.large-9{width:75%}.grid-x>.large-10{width:83.33333%}.grid-x>.large-11{width:91.66667%}.grid-x>.large-12{width:100%}}.grid-margin-x:not(.grid-x)>.cell{width:auto}.grid-margin-y:not(.grid-y)>.cell{height:auto}.grid-margin-x{margin-left:-.625rem;margin-right:-.625rem}@media print,screen and (min-width:40em){.grid-margin-x{margin-left:-.9375rem;margin-right:-.9375rem}}.grid-margin-x>.cell{margin-left:.625rem;margin-right:.625rem;width:calc(100% - 1.25rem)}@media print,screen and (min-width:40em){.grid-margin-x>.cell{margin-left:.9375rem;margin-right:.9375rem;width:calc(100% - 1.875rem)}}.grid-margin-x>.auto{width:auto}.grid-margin-x>.shrink{width:auto}.grid-margin-x>.small-1{width:calc(8.33333% - 1.25rem)}.grid-margin-x>.small-2{width:calc(16.66667% - 1.25rem)}.grid-margin-x>.small-3{width:calc(25% - 1.25rem)}.grid-margin-x>.small-4{width:calc(33.33333% - 1.25rem)}.grid-margin-x>.small-5{width:calc(41.66667% - 1.25rem)}.grid-margin-x>.small-6{width:calc(50% - 1.25rem)}.grid-margin-x>.small-7{width:calc(58.33333% - 1.25rem)}.grid-margin-x>.small-8{width:calc(66.66667% - 1.25rem)}.grid-margin-x>.small-9{width:calc(75% - 1.25rem)}.grid-margin-x>.small-10{width:calc(83.33333% - 1.25rem)}.grid-margin-x>.small-11{width:calc(91.66667% - 1.25rem)}.grid-margin-x>.small-12{width:calc(100% - 1.25rem)}@media print,screen and (min-width:40em){.grid-margin-x>.auto{width:auto}.grid-margin-x>.shrink{width:auto}.grid-margin-x>.small-1{width:calc(8.33333% - 1.875rem)}.grid-margin-x>.small-2{width:calc(16.66667% - 1.875rem)}.grid-margin-x>.small-3{width:calc(25% - 1.875rem)}.grid-margin-x>.small-4{width:calc(33.33333% - 1.875rem)}.grid-margin-x>.small-5{width:calc(41.66667% - 1.875rem)}.grid-margin-x>.small-6{width:calc(50% - 1.875rem)}.grid-margin-x>.small-7{width:calc(58.33333% - 1.875rem)}.grid-margin-x>.small-8{width:calc(66.66667% - 1.875rem)}.grid-margin-x>.small-9{width:calc(75% - 1.875rem)}.grid-margin-x>.small-10{width:calc(83.33333% - 1.875rem)}.grid-margin-x>.small-11{width:calc(91.66667% - 1.875rem)}.grid-margin-x>.small-12{width:calc(100% - 1.875rem)}.grid-margin-x>.medium-auto{width:auto}.grid-margin-x>.medium-shrink{width:auto}.grid-margin-x>.medium-1{width:calc(8.33333% - 1.875rem)}.grid-margin-x>.medium-2{width:calc(16.66667% - 1.875rem)}.grid-margin-x>.medium-3{width:calc(25% - 1.875rem)}.grid-margin-x>.medium-4{width:calc(33.33333% - 1.875rem)}.grid-margin-x>.medium-5{width:calc(41.66667% - 1.875rem)}.grid-margin-x>.medium-6{width:calc(50% - 1.875rem)}.grid-margin-x>.medium-7{width:calc(58.33333% - 1.875rem)}.grid-margin-x>.medium-8{width:calc(66.66667% - 1.875rem)}.grid-margin-x>.medium-9{width:calc(75% - 1.875rem)}.grid-margin-x>.medium-10{width:calc(83.33333% - 1.875rem)}.grid-margin-x>.medium-11{width:calc(91.66667% - 1.875rem)}.grid-margin-x>.medium-12{width:calc(100% - 1.875rem)}}@media print,screen and (min-width:64em){.grid-margin-x>.large-auto{width:auto}.grid-margin-x>.large-shrink{width:auto}.grid-margin-x>.large-1{width:calc(8.33333% - 1.875rem)}.grid-margin-x>.large-2{width:calc(16.66667% - 1.875rem)}.grid-margin-x>.large-3{width:calc(25% - 1.875rem)}.grid-margin-x>.large-4{width:calc(33.33333% - 1.875rem)}.grid-margin-x>.large-5{width:calc(41.66667% - 1.875rem)}.grid-margin-x>.large-6{width:calc(50% - 1.875rem)}.grid-margin-x>.large-7{width:calc(58.33333% - 1.875rem)}.grid-margin-x>.large-8{width:calc(66.66667% - 1.875rem)}.grid-margin-x>.large-9{width:calc(75% - 1.875rem)}.grid-margin-x>.large-10{width:calc(83.33333% - 1.875rem)}.grid-margin-x>.large-11{width:calc(91.66667% - 1.875rem)}.grid-margin-x>.large-12{width:calc(100% - 1.875rem)}}.grid-padding-x .grid-padding-x{margin-left:-.625rem;margin-right:-.625rem}@media print,screen and (min-width:40em){.grid-padding-x .grid-padding-x{margin-left:-.9375rem;margin-right:-.9375rem}}.grid-container:not(.full)>.grid-padding-x{margin-left:-.625rem;margin-right:-.625rem}@media print,screen and (min-width:40em){.grid-container:not(.full)>.grid-padding-x{margin-left:-.9375rem;margin-right:-.9375rem}}.grid-padding-x>.cell{padding-left:.625rem;padding-right:.625rem}@media print,screen and (min-width:40em){.grid-padding-x>.cell{padding-left:.9375rem;padding-right:.9375rem}}.small-up-1>.cell{width:100%}.small-up-2>.cell{width:50%}.small-up-3>.cell{width:33.33333%}.small-up-4>.cell{width:25%}.small-up-5>.cell{width:20%}.small-up-6>.cell{width:16.66667%}.small-up-7>.cell{width:14.28571%}.small-up-8>.cell{width:12.5%}@media print,screen and (min-width:40em){.medium-up-1>.cell{width:100%}.medium-up-2>.cell{width:50%}.medium-up-3>.cell{width:33.33333%}.medium-up-4>.cell{width:25%}.medium-up-5>.cell{width:20%}.medium-up-6>.cell{width:16.66667%}.medium-up-7>.cell{width:14.28571%}.medium-up-8>.cell{width:12.5%}}@media print,screen and (min-width:64em){.large-up-1>.cell{width:100%}.large-up-2>.cell{width:50%}.large-up-3>.cell{width:33.33333%}.large-up-4>.cell{width:25%}.large-up-5>.cell{width:20%}.large-up-6>.cell{width:16.66667%}.large-up-7>.cell{width:14.28571%}.large-up-8>.cell{width:12.5%}}.grid-margin-x.small-up-1>.cell{width:calc(100% - 1.25rem)}.grid-margin-x.small-up-2>.cell{width:calc(50% - 1.25rem)}.grid-margin-x.small-up-3>.cell{width:calc(33.33333% - 1.25rem)}.grid-margin-x.small-up-4>.cell{width:calc(25% - 1.25rem)}.grid-margin-x.small-up-5>.cell{width:calc(20% - 1.25rem)}.grid-margin-x.small-up-6>.cell{width:calc(16.66667% - 1.25rem)}.grid-margin-x.small-up-7>.cell{width:calc(14.28571% - 1.25rem)}.grid-margin-x.small-up-8>.cell{width:calc(12.5% - 1.25rem)}@media print,screen and (min-width:40em){.grid-margin-x.small-up-1>.cell{width:calc(100% - 1.875rem)}.grid-margin-x.small-up-2>.cell{width:calc(50% - 1.875rem)}.grid-margin-x.small-up-3>.cell{width:calc(33.33333% - 1.875rem)}.grid-margin-x.small-up-4>.cell{width:calc(25% - 1.875rem)}.grid-margin-x.small-up-5>.cell{width:calc(20% - 1.875rem)}.grid-margin-x.small-up-6>.cell{width:calc(16.66667% - 1.875rem)}.grid-margin-x.small-up-7>.cell{width:calc(14.28571% - 1.875rem)}.grid-margin-x.small-up-8>.cell{width:calc(12.5% - 1.875rem)}.grid-margin-x.medium-up-1>.cell{width:calc(100% - 1.875rem)}.grid-margin-x.medium-up-2>.cell{width:calc(50% - 1.875rem)}.grid-margin-x.medium-up-3>.cell{width:calc(33.33333% - 1.875rem)}.grid-margin-x.medium-up-4>.cell{width:calc(25% - 1.875rem)}.grid-margin-x.medium-up-5>.cell{width:calc(20% - 1.875rem)}.grid-margin-x.medium-up-6>.cell{width:calc(16.66667% - 1.875rem)}.grid-margin-x.medium-up-7>.cell{width:calc(14.28571% - 1.875rem)}.grid-margin-x.medium-up-8>.cell{width:calc(12.5% - 1.875rem)}}@media print,screen and (min-width:64em){.grid-margin-x.large-up-1>.cell{width:calc(100% - 1.875rem)}.grid-margin-x.large-up-2>.cell{width:calc(50% - 1.875rem)}.grid-margin-x.large-up-3>.cell{width:calc(33.33333% - 1.875rem)}.grid-margin-x.large-up-4>.cell{width:calc(25% - 1.875rem)}.grid-margin-x.large-up-5>.cell{width:calc(20% - 1.875rem)}.grid-margin-x.large-up-6>.cell{width:calc(16.66667% - 1.875rem)}.grid-margin-x.large-up-7>.cell{width:calc(14.28571% - 1.875rem)}.grid-margin-x.large-up-8>.cell{width:calc(12.5% - 1.875rem)}}.small-margin-collapse{margin-left:0;margin-right:0}.small-margin-collapse>.cell{margin-left:0;margin-right:0}.small-margin-collapse>.small-1{width:8.33333%}.small-margin-collapse>.small-2{width:16.66667%}.small-margin-collapse>.small-3{width:25%}.small-margin-collapse>.small-4{width:33.33333%}.small-margin-collapse>.small-5{width:41.66667%}.small-margin-collapse>.small-6{width:50%}.small-margin-collapse>.small-7{width:58.33333%}.small-margin-collapse>.small-8{width:66.66667%}.small-margin-collapse>.small-9{width:75%}.small-margin-collapse>.small-10{width:83.33333%}.small-margin-collapse>.small-11{width:91.66667%}.small-margin-collapse>.small-12{width:100%}@media print,screen and (min-width:40em){.small-margin-collapse>.medium-1{width:8.33333%}.small-margin-collapse>.medium-2{width:16.66667%}.small-margin-collapse>.medium-3{width:25%}.small-margin-collapse>.medium-4{width:33.33333%}.small-margin-collapse>.medium-5{width:41.66667%}.small-margin-collapse>.medium-6{width:50%}.small-margin-collapse>.medium-7{width:58.33333%}.small-margin-collapse>.medium-8{width:66.66667%}.small-margin-collapse>.medium-9{width:75%}.small-margin-collapse>.medium-10{width:83.33333%}.small-margin-collapse>.medium-11{width:91.66667%}.small-margin-collapse>.medium-12{width:100%}}@media print,screen and (min-width:64em){.small-margin-collapse>.large-1{width:8.33333%}.small-margin-collapse>.large-2{width:16.66667%}.small-margin-collapse>.large-3{width:25%}.small-margin-collapse>.large-4{width:33.33333%}.small-margin-collapse>.large-5{width:41.66667%}.small-margin-collapse>.large-6{width:50%}.small-margin-collapse>.large-7{width:58.33333%}.small-margin-collapse>.large-8{width:66.66667%}.small-margin-collapse>.large-9{width:75%}.small-margin-collapse>.large-10{width:83.33333%}.small-margin-collapse>.large-11{width:91.66667%}.small-margin-collapse>.large-12{width:100%}}.small-padding-collapse{margin-left:0;margin-right:0}.small-padding-collapse>.cell{padding-left:0;padding-right:0}@media print,screen and (min-width:40em){.medium-margin-collapse{margin-left:0;margin-right:0}.medium-margin-collapse>.cell{margin-left:0;margin-right:0}}@media print,screen and (min-width:40em){.medium-margin-collapse>.small-1{width:8.33333%}.medium-margin-collapse>.small-2{width:16.66667%}.medium-margin-collapse>.small-3{width:25%}.medium-margin-collapse>.small-4{width:33.33333%}.medium-margin-collapse>.small-5{width:41.66667%}.medium-margin-collapse>.small-6{width:50%}.medium-margin-collapse>.small-7{width:58.33333%}.medium-margin-collapse>.small-8{width:66.66667%}.medium-margin-collapse>.small-9{width:75%}.medium-margin-collapse>.small-10{width:83.33333%}.medium-margin-collapse>.small-11{width:91.66667%}.medium-margin-collapse>.small-12{width:100%}}@media print,screen and (min-width:40em){.medium-margin-collapse>.medium-1{width:8.33333%}.medium-margin-collapse>.medium-2{width:16.66667%}.medium-margin-collapse>.medium-3{width:25%}.medium-margin-collapse>.medium-4{width:33.33333%}.medium-margin-collapse>.medium-5{width:41.66667%}.medium-margin-collapse>.medium-6{width:50%}.medium-margin-collapse>.medium-7{width:58.33333%}.medium-margin-collapse>.medium-8{width:66.66667%}.medium-margin-collapse>.medium-9{width:75%}.medium-margin-collapse>.medium-10{width:83.33333%}.medium-margin-collapse>.medium-11{width:91.66667%}.medium-margin-collapse>.medium-12{width:100%}}@media print,screen and (min-width:64em){.medium-margin-collapse>.large-1{width:8.33333%}.medium-margin-collapse>.large-2{width:16.66667%}.medium-margin-collapse>.large-3{width:25%}.medium-margin-collapse>.large-4{width:33.33333%}.medium-margin-collapse>.large-5{width:41.66667%}.medium-margin-collapse>.large-6{width:50%}.medium-margin-collapse>.large-7{width:58.33333%}.medium-margin-collapse>.large-8{width:66.66667%}.medium-margin-collapse>.large-9{width:75%}.medium-margin-collapse>.large-10{width:83.33333%}.medium-margin-collapse>.large-11{width:91.66667%}.medium-margin-collapse>.large-12{width:100%}}@media print,screen and (min-width:40em){.medium-padding-collapse{margin-left:0;margin-right:0}.medium-padding-collapse>.cell{padding-left:0;padding-right:0}}@media print,screen and (min-width:64em){.large-margin-collapse{margin-left:0;margin-right:0}.large-margin-collapse>.cell{margin-left:0;margin-right:0}}@media print,screen and (min-width:64em){.large-margin-collapse>.small-1{width:8.33333%}.large-margin-collapse>.small-2{width:16.66667%}.large-margin-collapse>.small-3{width:25%}.large-margin-collapse>.small-4{width:33.33333%}.large-margin-collapse>.small-5{width:41.66667%}.large-margin-collapse>.small-6{width:50%}.large-margin-collapse>.small-7{width:58.33333%}.large-margin-collapse>.small-8{width:66.66667%}.large-margin-collapse>.small-9{width:75%}.large-margin-collapse>.small-10{width:83.33333%}.large-margin-collapse>.small-11{width:91.66667%}.large-margin-collapse>.small-12{width:100%}}@media print,screen and (min-width:64em){.large-margin-collapse>.medium-1{width:8.33333%}.large-margin-collapse>.medium-2{width:16.66667%}.large-margin-collapse>.medium-3{width:25%}.large-margin-collapse>.medium-4{width:33.33333%}.large-margin-collapse>.medium-5{width:41.66667%}.large-margin-collapse>.medium-6{width:50%}.large-margin-collapse>.medium-7{width:58.33333%}.large-margin-collapse>.medium-8{width:66.66667%}.large-margin-collapse>.medium-9{width:75%}.large-margin-collapse>.medium-10{width:83.33333%}.large-margin-collapse>.medium-11{width:91.66667%}.large-margin-collapse>.medium-12{width:100%}}@media print,screen and (min-width:64em){.large-margin-collapse>.large-1{width:8.33333%}.large-margin-collapse>.large-2{width:16.66667%}.large-margin-collapse>.large-3{width:25%}.large-margin-collapse>.large-4{width:33.33333%}.large-margin-collapse>.large-5{width:41.66667%}.large-margin-collapse>.large-6{width:50%}.large-margin-collapse>.large-7{width:58.33333%}.large-margin-collapse>.large-8{width:66.66667%}.large-margin-collapse>.large-9{width:75%}.large-margin-collapse>.large-10{width:83.33333%}.large-margin-collapse>.large-11{width:91.66667%}.large-margin-collapse>.large-12{width:100%}}@media print,screen and (min-width:64em){.large-padding-collapse{margin-left:0;margin-right:0}.large-padding-collapse>.cell{padding-left:0;padding-right:0}}.small-offset-0{margin-left:0}.grid-margin-x>.small-offset-0{margin-left:.625rem}.small-offset-1{margin-left:8.33333%}.grid-margin-x>.small-offset-1{margin-left:calc(8.33333% + .625rem)}.small-offset-2{margin-left:16.66667%}.grid-margin-x>.small-offset-2{margin-left:calc(16.66667% + .625rem)}.small-offset-3{margin-left:25%}.grid-margin-x>.small-offset-3{margin-left:calc(25% + .625rem)}.small-offset-4{margin-left:33.33333%}.grid-margin-x>.small-offset-4{margin-left:calc(33.33333% + .625rem)}.small-offset-5{margin-left:41.66667%}.grid-margin-x>.small-offset-5{margin-left:calc(41.66667% + .625rem)}.small-offset-6{margin-left:50%}.grid-margin-x>.small-offset-6{margin-left:calc(50% + .625rem)}.small-offset-7{margin-left:58.33333%}.grid-margin-x>.small-offset-7{margin-left:calc(58.33333% + .625rem)}.small-offset-8{margin-left:66.66667%}.grid-margin-x>.small-offset-8{margin-left:calc(66.66667% + .625rem)}.small-offset-9{margin-left:75%}.grid-margin-x>.small-offset-9{margin-left:calc(75% + .625rem)}.small-offset-10{margin-left:83.33333%}.grid-margin-x>.small-offset-10{margin-left:calc(83.33333% + .625rem)}.small-offset-11{margin-left:91.66667%}.grid-margin-x>.small-offset-11{margin-left:calc(91.66667% + .625rem)}@media print,screen and (min-width:40em){.medium-offset-0{margin-left:0}.grid-margin-x>.medium-offset-0{margin-left:.9375rem}.medium-offset-1{margin-left:8.33333%}.grid-margin-x>.medium-offset-1{margin-left:calc(8.33333% + .9375rem)}.medium-offset-2{margin-left:16.66667%}.grid-margin-x>.medium-offset-2{margin-left:calc(16.66667% + .9375rem)}.medium-offset-3{margin-left:25%}.grid-margin-x>.medium-offset-3{margin-left:calc(25% + .9375rem)}.medium-offset-4{margin-left:33.33333%}.grid-margin-x>.medium-offset-4{margin-left:calc(33.33333% + .9375rem)}.medium-offset-5{margin-left:41.66667%}.grid-margin-x>.medium-offset-5{margin-left:calc(41.66667% + .9375rem)}.medium-offset-6{margin-left:50%}.grid-margin-x>.medium-offset-6{margin-left:calc(50% + .9375rem)}.medium-offset-7{margin-left:58.33333%}.grid-margin-x>.medium-offset-7{margin-left:calc(58.33333% + .9375rem)}.medium-offset-8{margin-left:66.66667%}.grid-margin-x>.medium-offset-8{margin-left:calc(66.66667% + .9375rem)}.medium-offset-9{margin-left:75%}.grid-margin-x>.medium-offset-9{margin-left:calc(75% + .9375rem)}.medium-offset-10{margin-left:83.33333%}.grid-margin-x>.medium-offset-10{margin-left:calc(83.33333% + .9375rem)}.medium-offset-11{margin-left:91.66667%}.grid-margin-x>.medium-offset-11{margin-left:calc(91.66667% + .9375rem)}}@media print,screen and (min-width:64em){.large-offset-0{margin-left:0}.grid-margin-x>.large-offset-0{margin-left:.9375rem}.large-offset-1{margin-left:8.33333%}.grid-margin-x>.large-offset-1{margin-left:calc(8.33333% + .9375rem)}.large-offset-2{margin-left:16.66667%}.grid-margin-x>.large-offset-2{margin-left:calc(16.66667% + .9375rem)}.large-offset-3{margin-left:25%}.grid-margin-x>.large-offset-3{margin-left:calc(25% + .9375rem)}.large-offset-4{margin-left:33.33333%}.grid-margin-x>.large-offset-4{margin-left:calc(33.33333% + .9375rem)}.large-offset-5{margin-left:41.66667%}.grid-margin-x>.large-offset-5{margin-left:calc(41.66667% + .9375rem)}.large-offset-6{margin-left:50%}.grid-margin-x>.large-offset-6{margin-left:calc(50% + .9375rem)}.large-offset-7{margin-left:58.33333%}.grid-margin-x>.large-offset-7{margin-left:calc(58.33333% + .9375rem)}.large-offset-8{margin-left:66.66667%}.grid-margin-x>.large-offset-8{margin-left:calc(66.66667% + .9375rem)}.large-offset-9{margin-left:75%}.grid-margin-x>.large-offset-9{margin-left:calc(75% + .9375rem)}.large-offset-10{margin-left:83.33333%}.grid-margin-x>.large-offset-10{margin-left:calc(83.33333% + .9375rem)}.large-offset-11{margin-left:91.66667%}.grid-margin-x>.large-offset-11{margin-left:calc(91.66667% + .9375rem)}}.grid-y{-webkit-box-orient:vertical;-webkit-box-direction:normal;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-flow:column nowrap;-ms-flex-flow:column nowrap;flex-flow:column nowrap}.grid-y>.cell{height:auto;max-height:none}.grid-y>.auto{height:auto}.grid-y>.shrink{height:auto}.grid-y>.small-1,.grid-y>.small-2,.grid-y>.small-3,.grid-y>.small-4,.grid-y>.small-5,.grid-y>.small-6,.grid-y>.small-7,.grid-y>.small-8,.grid-y>.small-9,.grid-y>.small-10,.grid-y>.small-11,.grid-y>.small-12,.grid-y>.small-full,.grid-y>.small-shrink{-ms-flex-preferred-size:auto;-webkit-flex-basis:auto;flex-basis:auto}@media print,screen and (min-width:40em){.grid-y>.medium-1,.grid-y>.medium-2,.grid-y>.medium-3,.grid-y>.medium-4,.grid-y>.medium-5,.grid-y>.medium-6,.grid-y>.medium-7,.grid-y>.medium-8,.grid-y>.medium-9,.grid-y>.medium-10,.grid-y>.medium-11,.grid-y>.medium-12,.grid-y>.medium-full,.grid-y>.medium-shrink{-ms-flex-preferred-size:auto;-webkit-flex-basis:auto;flex-basis:auto}}@media print,screen and (min-width:64em){.grid-y>.large-1,.grid-y>.large-2,.grid-y>.large-3,.grid-y>.large-4,.grid-y>.large-5,.grid-y>.large-6,.grid-y>.large-7,.grid-y>.large-8,.grid-y>.large-9,.grid-y>.large-10,.grid-y>.large-11,.grid-y>.large-12,.grid-y>.large-full,.grid-y>.large-shrink{-ms-flex-preferred-size:auto;-webkit-flex-basis:auto;flex-basis:auto}}.grid-y>.small-1,.grid-y>.small-2,.grid-y>.small-3,.grid-y>.small-4,.grid-y>.small-5,.grid-y>.small-6,.grid-y>.small-7,.grid-y>.small-8,.grid-y>.small-9,.grid-y>.small-10,.grid-y>.small-11,.grid-y>.small-12{-webkit-box-flex:0;-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto}.grid-y>.small-1{height:8.33333%}.grid-y>.small-2{height:16.66667%}.grid-y>.small-3{height:25%}.grid-y>.small-4{height:33.33333%}.grid-y>.small-5{height:41.66667%}.grid-y>.small-6{height:50%}.grid-y>.small-7{height:58.33333%}.grid-y>.small-8{height:66.66667%}.grid-y>.small-9{height:75%}.grid-y>.small-10{height:83.33333%}.grid-y>.small-11{height:91.66667%}.grid-y>.small-12{height:100%}@media print,screen and (min-width:40em){.grid-y>.medium-auto{-webkit-box-flex:1;-webkit-flex:1 1 0;-ms-flex:1 1 0px;flex:1 1 0;height:auto}.grid-y>.medium-1,.grid-y>.medium-2,.grid-y>.medium-3,.grid-y>.medium-4,.grid-y>.medium-5,.grid-y>.medium-6,.grid-y>.medium-7,.grid-y>.medium-8,.grid-y>.medium-9,.grid-y>.medium-10,.grid-y>.medium-11,.grid-y>.medium-12,.grid-y>.medium-shrink{-webkit-box-flex:0;-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto}.grid-y>.medium-shrink{height:auto}.grid-y>.medium-1{height:8.33333%}.grid-y>.medium-2{height:16.66667%}.grid-y>.medium-3{height:25%}.grid-y>.medium-4{height:33.33333%}.grid-y>.medium-5{height:41.66667%}.grid-y>.medium-6{height:50%}.grid-y>.medium-7{height:58.33333%}.grid-y>.medium-8{height:66.66667%}.grid-y>.medium-9{height:75%}.grid-y>.medium-10{height:83.33333%}.grid-y>.medium-11{height:91.66667%}.grid-y>.medium-12{height:100%}}@media print,screen and (min-width:64em){.grid-y>.large-auto{-webkit-box-flex:1;-webkit-flex:1 1 0;-ms-flex:1 1 0px;flex:1 1 0;height:auto}.grid-y>.large-1,.grid-y>.large-2,.grid-y>.large-3,.grid-y>.large-4,.grid-y>.large-5,.grid-y>.large-6,.grid-y>.large-7,.grid-y>.large-8,.grid-y>.large-9,.grid-y>.large-10,.grid-y>.large-11,.grid-y>.large-12,.grid-y>.large-shrink{-webkit-box-flex:0;-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto}.grid-y>.large-shrink{height:auto}.grid-y>.large-1{height:8.33333%}.grid-y>.large-2{height:16.66667%}.grid-y>.large-3{height:25%}.grid-y>.large-4{height:33.33333%}.grid-y>.large-5{height:41.66667%}.grid-y>.large-6{height:50%}.grid-y>.large-7{height:58.33333%}.grid-y>.large-8{height:66.66667%}.grid-y>.large-9{height:75%}.grid-y>.large-10{height:83.33333%}.grid-y>.large-11{height:91.66667%}.grid-y>.large-12{height:100%}}.grid-padding-y .grid-padding-y{margin-bottom:-.625rem;margin-top:-.625rem}@media print,screen and (min-width:40em){.grid-padding-y .grid-padding-y{margin-bottom:-.9375rem;margin-top:-.9375rem}}.grid-padding-y>.cell{padding-bottom:.625rem;padding-top:.625rem}@media print,screen and (min-width:40em){.grid-padding-y>.cell{padding-bottom:.9375rem;padding-top:.9375rem}}.grid-frame{-webkit-box-align:stretch;-ms-flex-align:stretch;-webkit-align-items:stretch;align-items:stretch;-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap;overflow:hidden;position:relative;width:100vw}.cell .grid-frame{width:100%}.cell-block{max-width:100%;overflow-x:auto}.cell-block,.cell-block-y{-webkit-overflow-scrolling:touch;-ms-overflow-style:-ms-autohiding-scrollbar}.cell-block-y{max-height:100%;min-height:100%;overflow-y:auto}.cell-block-container{-webkit-box-orient:vertical;-webkit-box-direction:normal;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;max-height:100%}.cell-block-container>.grid-x{-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap;max-height:100%}@media print,screen and (min-width:40em){.medium-grid-frame{-webkit-box-align:stretch;-ms-flex-align:stretch;-webkit-align-items:stretch;align-items:stretch;-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap;overflow:hidden;position:relative;width:100vw}.cell .medium-grid-frame{width:100%}.medium-cell-block{-webkit-overflow-scrolling:touch;-ms-overflow-style:-ms-autohiding-scrollbar;max-width:100%;overflow-x:auto}.medium-cell-block-container{-webkit-box-orient:vertical;-webkit-box-direction:normal;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;max-height:100%}.medium-cell-block-container>.grid-x{-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap;max-height:100%}.medium-cell-block-y{-webkit-overflow-scrolling:touch;-ms-overflow-style:-ms-autohiding-scrollbar;max-height:100%;min-height:100%;overflow-y:auto}}@media print,screen and (min-width:64em){.large-grid-frame{-webkit-box-align:stretch;-ms-flex-align:stretch;-webkit-align-items:stretch;align-items:stretch;-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap;overflow:hidden;position:relative;width:100vw}.cell .large-grid-frame{width:100%}.large-cell-block{-webkit-overflow-scrolling:touch;-ms-overflow-style:-ms-autohiding-scrollbar;max-width:100%;overflow-x:auto}.large-cell-block-container{-webkit-box-orient:vertical;-webkit-box-direction:normal;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;max-height:100%}.large-cell-block-container>.grid-x{-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap;max-height:100%}.large-cell-block-y{-webkit-overflow-scrolling:touch;-ms-overflow-style:-ms-autohiding-scrollbar;max-height:100%;min-height:100%;overflow-y:auto}}.grid-y.grid-frame{-webkit-box-align:stretch;-ms-flex-align:stretch;-webkit-align-items:stretch;align-items:stretch;-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap;height:100vh;overflow:hidden;position:relative;width:auto}@media print,screen and (min-width:40em){.grid-y.medium-grid-frame{-webkit-box-align:stretch;-ms-flex-align:stretch;-webkit-align-items:stretch;align-items:stretch;-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap;height:100vh;overflow:hidden;position:relative;width:auto}}@media print,screen and (min-width:64em){.grid-y.large-grid-frame{-webkit-box-align:stretch;-ms-flex-align:stretch;-webkit-align-items:stretch;align-items:stretch;-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap;height:100vh;overflow:hidden;position:relative;width:auto}}.cell .grid-y.grid-frame{height:100%}@media print,screen and (min-width:40em){.cell .grid-y.medium-grid-frame{height:100%}}@media print,screen and (min-width:64em){.cell .grid-y.large-grid-frame{height:100%}}.grid-margin-y{margin-bottom:-.625rem;margin-top:-.625rem}@media print,screen and (min-width:40em){.grid-margin-y{margin-bottom:-.9375rem;margin-top:-.9375rem}}.grid-margin-y>.cell{height:calc(100% - 1.25rem);margin-bottom:.625rem;margin-top:.625rem}@media print,screen and (min-width:40em){.grid-margin-y>.cell{height:calc(100% - 1.875rem);margin-bottom:.9375rem;margin-top:.9375rem}}.grid-margin-y>.auto{height:auto}.grid-margin-y>.shrink{height:auto}.grid-margin-y>.small-1{height:calc(8.33333% - 1.25rem)}.grid-margin-y>.small-2{height:calc(16.66667% - 1.25rem)}.grid-margin-y>.small-3{height:calc(25% - 1.25rem)}.grid-margin-y>.small-4{height:calc(33.33333% - 1.25rem)}.grid-margin-y>.small-5{height:calc(41.66667% - 1.25rem)}.grid-margin-y>.small-6{height:calc(50% - 1.25rem)}.grid-margin-y>.small-7{height:calc(58.33333% - 1.25rem)}.grid-margin-y>.small-8{height:calc(66.66667% - 1.25rem)}.grid-margin-y>.small-9{height:calc(75% - 1.25rem)}.grid-margin-y>.small-10{height:calc(83.33333% - 1.25rem)}.grid-margin-y>.small-11{height:calc(91.66667% - 1.25rem)}.grid-margin-y>.small-12{height:calc(100% - 1.25rem)}@media print,screen and (min-width:40em){.grid-margin-y>.auto{height:auto}.grid-margin-y>.shrink{height:auto}.grid-margin-y>.small-1{height:calc(8.33333% - 1.875rem)}.grid-margin-y>.small-2{height:calc(16.66667% - 1.875rem)}.grid-margin-y>.small-3{height:calc(25% - 1.875rem)}.grid-margin-y>.small-4{height:calc(33.33333% - 1.875rem)}.grid-margin-y>.small-5{height:calc(41.66667% - 1.875rem)}.grid-margin-y>.small-6{height:calc(50% - 1.875rem)}.grid-margin-y>.small-7{height:calc(58.33333% - 1.875rem)}.grid-margin-y>.small-8{height:calc(66.66667% - 1.875rem)}.grid-margin-y>.small-9{height:calc(75% - 1.875rem)}.grid-margin-y>.small-10{height:calc(83.33333% - 1.875rem)}.grid-margin-y>.small-11{height:calc(91.66667% - 1.875rem)}.grid-margin-y>.small-12{height:calc(100% - 1.875rem)}.grid-margin-y>.medium-auto{height:auto}.grid-margin-y>.medium-shrink{height:auto}.grid-margin-y>.medium-1{height:calc(8.33333% - 1.875rem)}.grid-margin-y>.medium-2{height:calc(16.66667% - 1.875rem)}.grid-margin-y>.medium-3{height:calc(25% - 1.875rem)}.grid-margin-y>.medium-4{height:calc(33.33333% - 1.875rem)}.grid-margin-y>.medium-5{height:calc(41.66667% - 1.875rem)}.grid-margin-y>.medium-6{height:calc(50% - 1.875rem)}.grid-margin-y>.medium-7{height:calc(58.33333% - 1.875rem)}.grid-margin-y>.medium-8{height:calc(66.66667% - 1.875rem)}.grid-margin-y>.medium-9{height:calc(75% - 1.875rem)}.grid-margin-y>.medium-10{height:calc(83.33333% - 1.875rem)}.grid-margin-y>.medium-11{height:calc(91.66667% - 1.875rem)}.grid-margin-y>.medium-12{height:calc(100% - 1.875rem)}}@media print,screen and (min-width:64em){.grid-margin-y>.large-auto{height:auto}.grid-margin-y>.large-shrink{height:auto}.grid-margin-y>.large-1{height:calc(8.33333% - 1.875rem)}.grid-margin-y>.large-2{height:calc(16.66667% - 1.875rem)}.grid-margin-y>.large-3{height:calc(25% - 1.875rem)}.grid-margin-y>.large-4{height:calc(33.33333% - 1.875rem)}.grid-margin-y>.large-5{height:calc(41.66667% - 1.875rem)}.grid-margin-y>.large-6{height:calc(50% - 1.875rem)}.grid-margin-y>.large-7{height:calc(58.33333% - 1.875rem)}.grid-margin-y>.large-8{height:calc(66.66667% - 1.875rem)}.grid-margin-y>.large-9{height:calc(75% - 1.875rem)}.grid-margin-y>.large-10{height:calc(83.33333% - 1.875rem)}.grid-margin-y>.large-11{height:calc(91.66667% - 1.875rem)}.grid-margin-y>.large-12{height:calc(100% - 1.875rem)}}.grid-frame.grid-margin-y{height:calc(100vh + 1.25rem)}@media print,screen and (min-width:40em){.grid-frame.grid-margin-y{height:calc(100vh + 1.875rem)}}@media print,screen and (min-width:64em){.grid-frame.grid-margin-y{height:calc(100vh + 1.875rem)}}@media print,screen and (min-width:40em){.grid-margin-y.medium-grid-frame{height:calc(100vh + 1.875rem)}}@media print,screen and (min-width:64em){.grid-margin-y.large-grid-frame{height:calc(100vh + 1.875rem)}}.button{-webkit-appearance:none;border:1px solid transparent;border-radius:0;cursor:pointer;display:inline-block;font-family:inherit;font-size:.9rem;line-height:1;margin:0 0 1rem;padding:.85em 1em;text-align:center;-webkit-transition:background-color .25s ease-out,color .25s ease-out;transition:background-color .25s ease-out,color .25s ease-out;vertical-align:middle}[data-whatinput=mouse] .button{outline:0}.button.tiny{font-size:.6rem}.button.small{font-size:.75rem}.button.large{font-size:1.25rem}.button.expanded{display:block;margin-left:0;margin-right:0;width:100%}.button,.button.disabled,.button.disabled:focus,.button.disabled:hover,.button[disabled],.button[disabled]:focus,.button[disabled]:hover{background-color:#1779ba;color:#fefefe}.button:focus,.button:hover{background-color:#14679e;color:#fefefe}.button.primary,.button.primary.disabled,.button.primary.disabled:focus,.button.primary.disabled:hover,.button.primary[disabled],.button.primary[disabled]:focus,.button.primary[disabled]:hover{background-color:#1779ba;color:#fefefe}.button.primary:focus,.button.primary:hover{background-color:#126195;color:#fefefe}.button.secondary,.button.secondary.disabled,.button.secondary.disabled:focus,.button.secondary.disabled:hover,.button.secondary[disabled],.button.secondary[disabled]:focus,.button.secondary[disabled]:hover{background-color:#767676;color:#fefefe}.button.secondary:focus,.button.secondary:hover{background-color:#5e5e5e;color:#fefefe}.button.success,.button.success.disabled,.button.success.disabled:focus,.button.success.disabled:hover,.button.success[disabled],.button.success[disabled]:focus,.button.success[disabled]:hover{background-color:#3adb76;color:#0a0a0a}.button.success:focus,.button.success:hover{background-color:#22bb5b;color:#0a0a0a}.button.warning,.button.warning.disabled,.button.warning.disabled:focus,.button.warning.disabled:hover,.button.warning[disabled],.button.warning[disabled]:focus,.button.warning[disabled]:hover{background-color:#ffae00;color:#0a0a0a}.button.warning:focus,.button.warning:hover{background-color:#cc8b00;color:#0a0a0a}.button.alert,.button.alert.disabled,.button.alert.disabled:focus,.button.alert.disabled:hover,.button.alert[disabled],.button.alert[disabled]:focus,.button.alert[disabled]:hover{background-color:#cc4b37;color:#fefefe}.button.alert:focus,.button.alert:hover{background-color:#a53b2a;color:#fefefe}.button.hollow,.button.hollow.disabled,.button.hollow.disabled:focus,.button.hollow.disabled:hover,.button.hollow:focus,.button.hollow:hover,.button.hollow[disabled],.button.hollow[disabled]:focus,.button.hollow[disabled]:hover{background-color:transparent}.button.hollow,.button.hollow.disabled,.button.hollow.disabled:focus,.button.hollow.disabled:hover,.button.hollow[disabled],.button.hollow[disabled]:focus,.button.hollow[disabled]:hover{border:1px solid #1779ba;color:#1779ba}.button.hollow:focus,.button.hollow:hover{border-color:#0c3d5d;color:#0c3d5d}.button.hollow.primary,.button.hollow.primary.disabled,.button.hollow.primary.disabled:focus,.button.hollow.primary.disabled:hover,.button.hollow.primary[disabled],.button.hollow.primary[disabled]:focus,.button.hollow.primary[disabled]:hover{border:1px solid #1779ba;color:#1779ba}.button.hollow.primary:focus,.button.hollow.primary:hover{border-color:#0c3d5d;color:#0c3d5d}.button.hollow.secondary,.button.hollow.secondary.disabled,.button.hollow.secondary.disabled:focus,.button.hollow.secondary.disabled:hover,.button.hollow.secondary[disabled],.button.hollow.secondary[disabled]:focus,.button.hollow.secondary[disabled]:hover{border:1px solid #767676;color:#767676}.button.hollow.secondary:focus,.button.hollow.secondary:hover{border-color:#3b3b3b;color:#3b3b3b}.button.hollow.success,.button.hollow.success.disabled,.button.hollow.success.disabled:focus,.button.hollow.success.disabled:hover,.button.hollow.success[disabled],.button.hollow.success[disabled]:focus,.button.hollow.success[disabled]:hover{border:1px solid #3adb76;color:#3adb76}.button.hollow.success:focus,.button.hollow.success:hover{border-color:#157539;color:#157539}.button.hollow.warning,.button.hollow.warning.disabled,.button.hollow.warning.disabled:focus,.button.hollow.warning.disabled:hover,.button.hollow.warning[disabled],.button.hollow.warning[disabled]:focus,.button.hollow.warning[disabled]:hover{border:1px solid #ffae00;color:#ffae00}.button.hollow.warning:focus,.button.hollow.warning:hover{border-color:#805700;color:#805700}.button.hollow.alert,.button.hollow.alert.disabled,.button.hollow.alert.disabled:focus,.button.hollow.alert.disabled:hover,.button.hollow.alert[disabled],.button.hollow.alert[disabled]:focus,.button.hollow.alert[disabled]:hover{border:1px solid #cc4b37;color:#cc4b37}.button.hollow.alert:focus,.button.hollow.alert:hover{border-color:#67251a;color:#67251a}.button.clear,.button.clear.disabled,.button.clear.disabled:focus,.button.clear.disabled:hover,.button.clear:focus,.button.clear:hover,.button.clear[disabled],.button.clear[disabled]:focus,.button.clear[disabled]:hover{background-color:transparent;border-color:transparent}.button.clear,.button.clear.disabled,.button.clear.disabled:focus,.button.clear.disabled:hover,.button.clear[disabled],.button.clear[disabled]:focus,.button.clear[disabled]:hover{color:#1779ba}.button.clear:focus,.button.clear:hover{color:#0c3d5d}.button.clear.primary,.button.clear.primary.disabled,.button.clear.primary.disabled:focus,.button.clear.primary.disabled:hover,.button.clear.primary[disabled],.button.clear.primary[disabled]:focus,.button.clear.primary[disabled]:hover{color:#1779ba}.button.clear.primary:focus,.button.clear.primary:hover{color:#0c3d5d}.button.clear.secondary,.button.clear.secondary.disabled,.button.clear.secondary.disabled:focus,.button.clear.secondary.disabled:hover,.button.clear.secondary[disabled],.button.clear.secondary[disabled]:focus,.button.clear.secondary[disabled]:hover{color:#767676}.button.clear.secondary:focus,.button.clear.secondary:hover{color:#3b3b3b}.button.clear.success,.button.clear.success.disabled,.button.clear.success.disabled:focus,.button.clear.success.disabled:hover,.button.clear.success[disabled],.button.clear.success[disabled]:focus,.button.clear.success[disabled]:hover{color:#3adb76}.button.clear.success:focus,.button.clear.success:hover{color:#157539}.button.clear.warning,.button.clear.warning.disabled,.button.clear.warning.disabled:focus,.button.clear.warning.disabled:hover,.button.clear.warning[disabled],.button.clear.warning[disabled]:focus,.button.clear.warning[disabled]:hover{color:#ffae00}.button.clear.warning:focus,.button.clear.warning:hover{color:#805700}.button.clear.alert,.button.clear.alert.disabled,.button.clear.alert.disabled:focus,.button.clear.alert.disabled:hover,.button.clear.alert[disabled],.button.clear.alert[disabled]:focus,.button.clear.alert[disabled]:hover{color:#cc4b37}.button.clear.alert:focus,.button.clear.alert:hover{color:#67251a}.button.disabled,.button[disabled]{cursor:not-allowed;opacity:.25}.button.dropdown:after{border-color:#fefefe transparent transparent;border-style:solid;border-width:.4em .4em 0;content:"";display:block;display:inline-block;float:right;height:0;margin-left:1em;position:relative;top:.4em;width:0}.button.dropdown.clear:after,.button.dropdown.hollow:after{border-top-color:#1779ba}.button.dropdown.clear.primary:after,.button.dropdown.hollow.primary:after{border-top-color:#1779ba}.button.dropdown.clear.secondary:after,.button.dropdown.hollow.secondary:after{border-top-color:#767676}.button.dropdown.clear.success:after,.button.dropdown.hollow.success:after{border-top-color:#3adb76}.button.dropdown.clear.warning:after,.button.dropdown.hollow.warning:after{border-top-color:#ffae00}.button.dropdown.clear.alert:after,.button.dropdown.hollow.alert:after{border-top-color:#cc4b37}.button.arrow-only:after{float:none;margin-left:0;top:-.1em}a.button:focus,a.button:hover{text-decoration:none}.button-group{-webkit-box-align:stretch;-ms-flex-align:stretch;-webkit-box-flex:1;-ms-flex-positive:1;-webkit-align-items:stretch;align-items:stretch;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-grow:1;flex-grow:1;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;margin-bottom:1rem}.button-group:after,.button-group:before{-ms-flex-preferred-size:0;-webkit-box-ordinal-group:2;-ms-flex-order:1;content:" ";display:table;-webkit-flex-basis:0;flex-basis:0;-webkit-order:1;order:1}.button-group:after{clear:both}.button-group:after,.button-group:before{display:none}.button-group .button{-webkit-box-flex:0;-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto;font-size:.9rem;margin:0 1px 1px 0}.button-group .button:last-child{margin-right:0}.button-group.tiny .button{font-size:.6rem}.button-group.small .button{font-size:.75rem}.button-group.large .button{font-size:1.25rem}.button-group.expanded .button{-webkit-box-flex:1;-webkit-flex:1 1 0px;-ms-flex:1 1 0px;flex:1 1 0px}.button-group.primary .button,.button-group.primary .button.disabled,.button-group.primary .button.disabled:focus,.button-group.primary .button.disabled:hover,.button-group.primary .button[disabled],.button-group.primary .button[disabled]:focus,.button-group.primary .button[disabled]:hover{background-color:#1779ba;color:#fefefe}.button-group.primary .button:focus,.button-group.primary .button:hover{background-color:#126195;color:#fefefe}.button-group.secondary .button,.button-group.secondary .button.disabled,.button-group.secondary .button.disabled:focus,.button-group.secondary .button.disabled:hover,.button-group.secondary .button[disabled],.button-group.secondary .button[disabled]:focus,.button-group.secondary .button[disabled]:hover{background-color:#767676;color:#fefefe}.button-group.secondary .button:focus,.button-group.secondary .button:hover{background-color:#5e5e5e;color:#fefefe}.button-group.success .button,.button-group.success .button.disabled,.button-group.success .button.disabled:focus,.button-group.success .button.disabled:hover,.button-group.success .button[disabled],.button-group.success .button[disabled]:focus,.button-group.success .button[disabled]:hover{background-color:#3adb76;color:#0a0a0a}.button-group.success .button:focus,.button-group.success .button:hover{background-color:#22bb5b;color:#0a0a0a}.button-group.warning .button,.button-group.warning .button.disabled,.button-group.warning .button.disabled:focus,.button-group.warning .button.disabled:hover,.button-group.warning .button[disabled],.button-group.warning .button[disabled]:focus,.button-group.warning .button[disabled]:hover{background-color:#ffae00;color:#0a0a0a}.button-group.warning .button:focus,.button-group.warning .button:hover{background-color:#cc8b00;color:#0a0a0a}.button-group.alert .button,.button-group.alert .button.disabled,.button-group.alert .button.disabled:focus,.button-group.alert .button.disabled:hover,.button-group.alert .button[disabled],.button-group.alert .button[disabled]:focus,.button-group.alert .button[disabled]:hover{background-color:#cc4b37;color:#fefefe}.button-group.alert .button:focus,.button-group.alert .button:hover{background-color:#a53b2a;color:#fefefe}.button-group.hollow .button,.button-group.hollow .button.disabled,.button-group.hollow .button.disabled:focus,.button-group.hollow .button.disabled:hover,.button-group.hollow .button:focus,.button-group.hollow .button:hover,.button-group.hollow .button[disabled],.button-group.hollow .button[disabled]:focus,.button-group.hollow .button[disabled]:hover{background-color:transparent}.button-group.hollow .button,.button-group.hollow .button.disabled,.button-group.hollow .button.disabled:focus,.button-group.hollow .button.disabled:hover,.button-group.hollow .button[disabled],.button-group.hollow .button[disabled]:focus,.button-group.hollow .button[disabled]:hover{border:1px solid #1779ba;color:#1779ba}.button-group.hollow .button:focus,.button-group.hollow .button:hover{border-color:#0c3d5d;color:#0c3d5d}.button-group.hollow .button.primary,.button-group.hollow .button.primary.disabled,.button-group.hollow .button.primary.disabled:focus,.button-group.hollow .button.primary.disabled:hover,.button-group.hollow .button.primary[disabled],.button-group.hollow .button.primary[disabled]:focus,.button-group.hollow .button.primary[disabled]:hover,.button-group.hollow.primary .button,.button-group.hollow.primary .button.disabled,.button-group.hollow.primary .button.disabled:focus,.button-group.hollow.primary .button.disabled:hover,.button-group.hollow.primary .button[disabled],.button-group.hollow.primary .button[disabled]:focus,.button-group.hollow.primary .button[disabled]:hover{border:1px solid #1779ba;color:#1779ba}.button-group.hollow .button.primary:focus,.button-group.hollow .button.primary:hover,.button-group.hollow.primary .button:focus,.button-group.hollow.primary .button:hover{border-color:#0c3d5d;color:#0c3d5d}.button-group.hollow .button.secondary,.button-group.hollow .button.secondary.disabled,.button-group.hollow .button.secondary.disabled:focus,.button-group.hollow .button.secondary.disabled:hover,.button-group.hollow .button.secondary[disabled],.button-group.hollow .button.secondary[disabled]:focus,.button-group.hollow .button.secondary[disabled]:hover,.button-group.hollow.secondary .button,.button-group.hollow.secondary .button.disabled,.button-group.hollow.secondary .button.disabled:focus,.button-group.hollow.secondary .button.disabled:hover,.button-group.hollow.secondary .button[disabled],.button-group.hollow.secondary .button[disabled]:focus,.button-group.hollow.secondary .button[disabled]:hover{border:1px solid #767676;color:#767676}.button-group.hollow .button.secondary:focus,.button-group.hollow .button.secondary:hover,.button-group.hollow.secondary .button:focus,.button-group.hollow.secondary .button:hover{border-color:#3b3b3b;color:#3b3b3b}.button-group.hollow .button.success,.button-group.hollow .button.success.disabled,.button-group.hollow .button.success.disabled:focus,.button-group.hollow .button.success.disabled:hover,.button-group.hollow .button.success[disabled],.button-group.hollow .button.success[disabled]:focus,.button-group.hollow .button.success[disabled]:hover,.button-group.hollow.success .button,.button-group.hollow.success .button.disabled,.button-group.hollow.success .button.disabled:focus,.button-group.hollow.success .button.disabled:hover,.button-group.hollow.success .button[disabled],.button-group.hollow.success .button[disabled]:focus,.button-group.hollow.success .button[disabled]:hover{border:1px solid #3adb76;color:#3adb76}.button-group.hollow .button.success:focus,.button-group.hollow .button.success:hover,.button-group.hollow.success .button:focus,.button-group.hollow.success .button:hover{border-color:#157539;color:#157539}.button-group.hollow .button.warning,.button-group.hollow .button.warning.disabled,.button-group.hollow .button.warning.disabled:focus,.button-group.hollow .button.warning.disabled:hover,.button-group.hollow .button.warning[disabled],.button-group.hollow .button.warning[disabled]:focus,.button-group.hollow .button.warning[disabled]:hover,.button-group.hollow.warning .button,.button-group.hollow.warning .button.disabled,.button-group.hollow.warning .button.disabled:focus,.button-group.hollow.warning .button.disabled:hover,.button-group.hollow.warning .button[disabled],.button-group.hollow.warning .button[disabled]:focus,.button-group.hollow.warning .button[disabled]:hover{border:1px solid #ffae00;color:#ffae00}.button-group.hollow .button.warning:focus,.button-group.hollow .button.warning:hover,.button-group.hollow.warning .button:focus,.button-group.hollow.warning .button:hover{border-color:#805700;color:#805700}.button-group.hollow.alert .button,.button-group.hollow.alert .button.disabled,.button-group.hollow.alert .button.disabled:focus,.button-group.hollow.alert .button.disabled:hover,.button-group.hollow.alert .button[disabled],.button-group.hollow.alert .button[disabled]:focus,.button-group.hollow.alert .button[disabled]:hover,.button-group.hollow .button.alert,.button-group.hollow .button.alert.disabled,.button-group.hollow .button.alert.disabled:focus,.button-group.hollow .button.alert.disabled:hover,.button-group.hollow .button.alert[disabled],.button-group.hollow .button.alert[disabled]:focus,.button-group.hollow .button.alert[disabled]:hover{border:1px solid #cc4b37;color:#cc4b37}.button-group.hollow.alert .button:focus,.button-group.hollow.alert .button:hover,.button-group.hollow .button.alert:focus,.button-group.hollow .button.alert:hover{border-color:#67251a;color:#67251a}.button-group.clear .button,.button-group.clear .button.disabled,.button-group.clear .button.disabled:focus,.button-group.clear .button.disabled:hover,.button-group.clear .button:focus,.button-group.clear .button:hover,.button-group.clear .button[disabled],.button-group.clear .button[disabled]:focus,.button-group.clear .button[disabled]:hover{background-color:transparent;border-color:transparent}.button-group.clear .button,.button-group.clear .button.disabled,.button-group.clear .button.disabled:focus,.button-group.clear .button.disabled:hover,.button-group.clear .button[disabled],.button-group.clear .button[disabled]:focus,.button-group.clear .button[disabled]:hover{color:#1779ba}.button-group.clear .button:focus,.button-group.clear .button:hover{color:#0c3d5d}.button-group.clear .button.primary,.button-group.clear .button.primary.disabled,.button-group.clear .button.primary.disabled:focus,.button-group.clear .button.primary.disabled:hover,.button-group.clear .button.primary[disabled],.button-group.clear .button.primary[disabled]:focus,.button-group.clear .button.primary[disabled]:hover,.button-group.clear.primary .button,.button-group.clear.primary .button.disabled,.button-group.clear.primary .button.disabled:focus,.button-group.clear.primary .button.disabled:hover,.button-group.clear.primary .button[disabled],.button-group.clear.primary .button[disabled]:focus,.button-group.clear.primary .button[disabled]:hover{color:#1779ba}.button-group.clear .button.primary:focus,.button-group.clear .button.primary:hover,.button-group.clear.primary .button:focus,.button-group.clear.primary .button:hover{color:#0c3d5d}.button-group.clear .button.secondary,.button-group.clear .button.secondary.disabled,.button-group.clear .button.secondary.disabled:focus,.button-group.clear .button.secondary.disabled:hover,.button-group.clear .button.secondary[disabled],.button-group.clear .button.secondary[disabled]:focus,.button-group.clear .button.secondary[disabled]:hover,.button-group.clear.secondary .button,.button-group.clear.secondary .button.disabled,.button-group.clear.secondary .button.disabled:focus,.button-group.clear.secondary .button.disabled:hover,.button-group.clear.secondary .button[disabled],.button-group.clear.secondary .button[disabled]:focus,.button-group.clear.secondary .button[disabled]:hover{color:#767676}.button-group.clear .button.secondary:focus,.button-group.clear .button.secondary:hover,.button-group.clear.secondary .button:focus,.button-group.clear.secondary .button:hover{color:#3b3b3b}.button-group.clear .button.success,.button-group.clear .button.success.disabled,.button-group.clear .button.success.disabled:focus,.button-group.clear .button.success.disabled:hover,.button-group.clear .button.success[disabled],.button-group.clear .button.success[disabled]:focus,.button-group.clear .button.success[disabled]:hover,.button-group.clear.success .button,.button-group.clear.success .button.disabled,.button-group.clear.success .button.disabled:focus,.button-group.clear.success .button.disabled:hover,.button-group.clear.success .button[disabled],.button-group.clear.success .button[disabled]:focus,.button-group.clear.success .button[disabled]:hover{color:#3adb76}.button-group.clear .button.success:focus,.button-group.clear .button.success:hover,.button-group.clear.success .button:focus,.button-group.clear.success .button:hover{color:#157539}.button-group.clear .button.warning,.button-group.clear .button.warning.disabled,.button-group.clear .button.warning.disabled:focus,.button-group.clear .button.warning.disabled:hover,.button-group.clear .button.warning[disabled],.button-group.clear .button.warning[disabled]:focus,.button-group.clear .button.warning[disabled]:hover,.button-group.clear.warning .button,.button-group.clear.warning .button.disabled,.button-group.clear.warning .button.disabled:focus,.button-group.clear.warning .button.disabled:hover,.button-group.clear.warning .button[disabled],.button-group.clear.warning .button[disabled]:focus,.button-group.clear.warning .button[disabled]:hover{color:#ffae00}.button-group.clear .button.warning:focus,.button-group.clear .button.warning:hover,.button-group.clear.warning .button:focus,.button-group.clear.warning .button:hover{color:#805700}.button-group.clear.alert .button,.button-group.clear.alert .button.disabled,.button-group.clear.alert .button.disabled:focus,.button-group.clear.alert .button.disabled:hover,.button-group.clear.alert .button[disabled],.button-group.clear.alert .button[disabled]:focus,.button-group.clear.alert .button[disabled]:hover,.button-group.clear .button.alert,.button-group.clear .button.alert.disabled,.button-group.clear .button.alert.disabled:focus,.button-group.clear .button.alert.disabled:hover,.button-group.clear .button.alert[disabled],.button-group.clear .button.alert[disabled]:focus,.button-group.clear .button.alert[disabled]:hover{color:#cc4b37}.button-group.clear.alert .button:focus,.button-group.clear.alert .button:hover,.button-group.clear .button.alert:focus,.button-group.clear .button.alert:hover{color:#67251a}.button-group.no-gaps .button{margin-right:-.0625rem}.button-group.no-gaps .button+.button{border-left-color:transparent}.button-group.stacked,.button-group.stacked-for-medium,.button-group.stacked-for-small{-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap}.button-group.stacked-for-medium .button,.button-group.stacked-for-small .button,.button-group.stacked .button{-webkit-box-flex:0;-webkit-flex:0 0 100%;-ms-flex:0 0 100%;flex:0 0 100%}.button-group.stacked-for-medium .button:last-child,.button-group.stacked-for-small .button:last-child,.button-group.stacked .button:last-child{margin-bottom:0}.button-group.stacked-for-medium.expanded .button,.button-group.stacked-for-small.expanded .button,.button-group.stacked.expanded .button{-webkit-box-flex:1;-webkit-flex:1 1 0px;-ms-flex:1 1 0px;flex:1 1 0px}@media print,screen and (min-width:40em){.button-group.stacked-for-small .button{-webkit-box-flex:0;-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto;margin-bottom:0}}@media print,screen and (min-width:64em){.button-group.stacked-for-medium .button{-webkit-box-flex:0;-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto;margin-bottom:0}}@media print,screen and (max-width:39.99875em){.button-group.stacked-for-small.expanded{display:block}.button-group.stacked-for-small.expanded .button{display:block;margin-right:0}}@media print,screen and (max-width:63.99875em){.button-group.stacked-for-medium.expanded{display:block}.button-group.stacked-for-medium.expanded .button{display:block;margin-right:0}}.close-button{color:#8a8a8a;cursor:pointer;position:absolute;z-index:10}[data-whatinput=mouse] .close-button{outline:0}.close-button:focus,.close-button:hover{color:#0a0a0a}.close-button.small{font-size:1.5em;line-height:1;right:.66rem;top:.33em}.close-button,.close-button.medium{font-size:2em;line-height:1;right:1rem;top:.5rem}.label{border-radius:0;cursor:default;display:inline-block;font-size:.8rem;line-height:1;padding:.33333rem .5rem;white-space:nowrap}.label,.label.primary{background:#1779ba;color:#fefefe}.label.secondary{background:#767676;color:#fefefe}.label.success{background:#3adb76;color:#0a0a0a}.label.warning{background:#ffae00;color:#0a0a0a}.label.alert{background:#cc4b37;color:#fefefe}.progress{background-color:#cacaca;border-radius:0;height:1rem;margin-bottom:1rem}.progress.primary .progress-meter{background-color:#1779ba}.progress.secondary .progress-meter{background-color:#767676}.progress.success .progress-meter{background-color:#3adb76}.progress.warning .progress-meter{background-color:#ffae00}.progress.alert .progress-meter{background-color:#cc4b37}.progress-meter{background-color:#1779ba;display:block;height:100%;position:relative;width:0}.progress-meter-text{color:#fefefe;font-size:.75rem;font-weight:700;left:50%;margin:0;position:absolute;top:50%;-webkit-transform:translate(-50%,-50%);-ms-transform:translate(-50%,-50%);transform:translate(-50%,-50%);white-space:nowrap}.slider{background-color:#e6e6e6;cursor:pointer;height:.5rem;margin-bottom:2.25rem;margin-top:1.25rem;position:relative;-ms-touch-action:none;touch-action:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.slider-fill{background-color:#cacaca;display:inline-block;height:.5rem;left:0;max-width:100%;position:absolute;top:0;-webkit-transition:all .2s ease-in-out;transition:all .2s ease-in-out}.slider-fill.is-dragging{-webkit-transition:all 0s linear;transition:all 0s linear}.slider-handle{background-color:#1779ba;border-radius:0;cursor:-webkit-grab;cursor:grab;display:inline-block;height:1.4rem;left:0;position:absolute;top:50%;-ms-touch-action:manipulation;touch-action:manipulation;-webkit-transform:translateY(-50%);-ms-transform:translateY(-50%);transform:translateY(-50%);-webkit-transition:all .2s ease-in-out;transition:all .2s ease-in-out;width:1.4rem;z-index:1}[data-whatinput=mouse] .slider-handle{outline:0}.slider-handle:hover{background-color:#14679e}.slider-handle.is-dragging{cursor:-webkit-grabbing;cursor:grabbing;-webkit-transition:all 0s linear;transition:all 0s linear}.slider.disabled,.slider[disabled]{cursor:not-allowed;opacity:.25}.slider.vertical{display:inline-block;height:12.5rem;margin:0 1.25rem;-webkit-transform:scaleY(-1);-ms-transform:scaleY(-1);transform:scaleY(-1);width:.5rem}.slider.vertical .slider-fill{max-height:100%;top:0;width:.5rem}.slider.vertical .slider-handle{height:1.4rem;left:50%;position:absolute;top:0;-webkit-transform:translateX(-50%);-ms-transform:translateX(-50%);transform:translateX(-50%);width:1.4rem}.switch{color:#fefefe;font-size:.875rem;font-weight:700;height:2rem;margin-bottom:1rem;outline:0;position:relative;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.switch-input{margin-bottom:0;opacity:0;position:absolute}.switch-paddle{background:#cacaca;border-radius:0;color:inherit;cursor:pointer;display:block;font-weight:inherit;height:2rem;position:relative;-webkit-transition:all .25s ease-out;transition:all .25s ease-out;width:4rem}input+.switch-paddle{margin:0}.switch-paddle:after{background:#fefefe;border-radius:0;content:"";display:block;height:1.5rem;left:.25rem;position:absolute;top:.25rem;-webkit-transform:translateZ(0);transform:translateZ(0);-webkit-transition:all .25s ease-out;transition:all .25s ease-out;width:1.5rem}input:checked~.switch-paddle{background:#1779ba}input:checked~.switch-paddle:after{left:2.25rem}input:disabled~.switch-paddle{cursor:not-allowed;opacity:.5}[data-whatinput=mouse] input:focus~.switch-paddle{outline:0}.switch-active,.switch-inactive{position:absolute;top:50%;-webkit-transform:translateY(-50%);-ms-transform:translateY(-50%);transform:translateY(-50%)}.switch-active{display:none;left:8%}input:checked+label>.switch-active{display:block}.switch-inactive{right:15%}input:checked+label>.switch-inactive{display:none}.switch.tiny{height:1.5rem}.switch.tiny .switch-paddle{font-size:.625rem;height:1.5rem;width:3rem}.switch.tiny .switch-paddle:after{height:1rem;left:.25rem;top:.25rem;width:1rem}.switch.tiny input:checked~.switch-paddle:after{left:1.75rem}.switch.small{height:1.75rem}.switch.small .switch-paddle{font-size:.75rem;height:1.75rem;width:3.5rem}.switch.small .switch-paddle:after{height:1.25rem;left:.25rem;top:.25rem;width:1.25rem}.switch.small input:checked~.switch-paddle:after{left:2rem}.switch.large{height:2.5rem}.switch.large .switch-paddle{font-size:1rem;height:2.5rem;width:5rem}.switch.large .switch-paddle:after{height:2rem;left:.25rem;top:.25rem;width:2rem}.switch.large input:checked~.switch-paddle:after{left:2.75rem}table{border-collapse:collapse;border-radius:0;margin-bottom:1rem;width:100%}tbody,tfoot,thead{background-color:#fefefe;border:1px solid #f1f1f1}caption{font-weight:700;padding:.5rem .625rem .625rem}thead{background:#f8f8f8}tfoot,thead{color:#0a0a0a}tfoot{background:#f1f1f1}tfoot tr,thead tr{background:0 0}tfoot td,tfoot th,thead td,thead th{font-weight:700;padding:.5rem .625rem .625rem;text-align:left}tbody td,tbody th{padding:.5rem .625rem .625rem}tbody tr:nth-child(2n){background-color:#f1f1f1;border-bottom:0}table.unstriped tbody{background-color:#fefefe}table.unstriped tbody tr{background-color:#fefefe;border-bottom:1px solid #f1f1f1}@media print,screen and (max-width:63.99875em){table.stack tfoot,table.stack thead{display:none}table.stack td,table.stack th,table.stack tr{display:block}table.stack td{border-top:0}}table.scroll{display:block;overflow-x:auto;width:100%}table.hover thead tr:hover{background-color:#f3f3f3}table.hover tfoot tr:hover{background-color:#ececec}table.hover tbody tr:hover{background-color:#f9f9f9}table.hover:not(.unstriped) tr:nth-of-type(2n):hover{background-color:#ececec}.table-scroll{overflow-x:auto}.badge{border-radius:50%;display:inline-block;font-size:.6rem;min-width:2.1em;padding:.3em;text-align:center}.badge,.badge.primary{background:#1779ba;color:#fefefe}.badge.secondary{background:#767676;color:#fefefe}.badge.success{background:#3adb76;color:#0a0a0a}.badge.warning{background:#ffae00;color:#0a0a0a}.badge.alert{background:#cc4b37;color:#fefefe}.breadcrumbs{list-style:none;margin:0 0 1rem}.breadcrumbs:after,.breadcrumbs:before{-ms-flex-preferred-size:0;-webkit-box-ordinal-group:2;-ms-flex-order:1;content:" ";display:table;-webkit-flex-basis:0;flex-basis:0;-webkit-order:1;order:1}.breadcrumbs:after{clear:both}.breadcrumbs li{color:#0a0a0a;cursor:default;float:left;font-size:.6875rem;text-transform:uppercase}.breadcrumbs li:not(:last-child):after{color:#cacaca;content:"/";margin:0 .75rem;opacity:1;position:relative}.breadcrumbs a{color:#1779ba}.breadcrumbs a:hover{text-decoration:underline}.breadcrumbs .disabled{color:#cacaca;cursor:not-allowed}.callout{background-color:#fff;border:1px solid hsla(0,0%,4%,.25);border-radius:0;color:#0a0a0a;margin:0 0 1rem;padding:1rem;position:relative}.callout>:first-child{margin-top:0}.callout>:last-child{margin-bottom:0}.callout.primary{background-color:#d7ecfa;color:#0a0a0a}.callout.secondary{background-color:#eaeaea;color:#0a0a0a}.callout.success{background-color:#e1faea;color:#0a0a0a}.callout.warning{background-color:#fff3d9;color:#0a0a0a}.callout.alert{background-color:#f7e4e1;color:#0a0a0a}.callout.small{padding:.5rem}.callout.large{padding:3rem}.card{-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-box-flex:1;-ms-flex-positive:1;background:#fefefe;border:1px solid #e6e6e6;border-radius:0;-webkit-box-shadow:none;box-shadow:none;color:#0a0a0a;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;-webkit-flex-grow:1;flex-grow:1;margin-bottom:1rem;overflow:hidden}.card>:last-child{margin-bottom:0}.card-divider{-webkit-box-flex:0;background:#e6e6e6;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex:0 1 auto;-ms-flex:0 1 auto;flex:0 1 auto;padding:1rem}.card-divider>:last-child{margin-bottom:0}.card-section{-webkit-box-flex:1;-webkit-flex:1 0 auto;-ms-flex:1 0 auto;flex:1 0 auto;padding:1rem}.card-section>:last-child{margin-bottom:0}.card-image{min-height:1px}.dropdown-pane{background-color:#fefefe;border:1px solid #cacaca;border-radius:0;display:none;font-size:1rem;padding:1rem;position:absolute;visibility:hidden;width:300px;z-index:10}.dropdown-pane.is-opening{display:block}.dropdown-pane.is-open{display:block;visibility:visible}.dropdown-pane.tiny{width:100px}.dropdown-pane.small{width:200px}.dropdown-pane.large{width:400px}.pagination{margin-bottom:1rem;margin-left:0}.pagination:after,.pagination:before{-ms-flex-preferred-size:0;-webkit-box-ordinal-group:2;-ms-flex-order:1;content:" ";display:table;-webkit-flex-basis:0;flex-basis:0;-webkit-order:1;order:1}.pagination:after{clear:both}.pagination li{border-radius:0;display:none;font-size:.875rem;margin-right:.0625rem}.pagination li:first-child,.pagination li:last-child{display:inline-block}@media print,screen and (min-width:40em){.pagination li{display:inline-block}}.pagination a,.pagination button{border-radius:0;color:#0a0a0a;display:block;padding:.1875rem .625rem}.pagination a:hover,.pagination button:hover{background:#e6e6e6}.pagination .current{background:#1779ba;color:#fefefe;cursor:default;padding:.1875rem .625rem}.pagination .disabled{color:#cacaca;cursor:not-allowed;padding:.1875rem .625rem}.pagination .disabled:hover{background:0 0}.pagination .ellipsis:after{color:#0a0a0a;content:"…";padding:.1875rem .625rem}.pagination-previous.disabled:before,.pagination-previous a:before{content:"«";display:inline-block;margin-right:.5rem}.pagination-next.disabled:after,.pagination-next a:after{content:"»";display:inline-block;margin-left:.5rem}.has-tip{border-bottom:1px dotted #8a8a8a;cursor:help;display:inline-block;font-weight:700;position:relative}.tooltip{background-color:#0a0a0a;border-radius:0;color:#fefefe;font-size:80%;max-width:10rem;padding:.75rem;position:absolute;top:calc(100% + .6495rem);z-index:1200}.tooltip:before{position:absolute}.tooltip.bottom:before{border-color:transparent transparent #0a0a0a;border-style:solid;border-width:0 .75rem .75rem;bottom:100%;content:"";display:block;height:0;width:0}.tooltip.bottom.align-center:before{left:50%;-webkit-transform:translateX(-50%);-ms-transform:translateX(-50%);transform:translateX(-50%)}.tooltip.top:before{border-color:#0a0a0a transparent transparent;border-style:solid;border-width:.75rem .75rem 0;bottom:auto;content:"";display:block;height:0;top:100%;width:0}.tooltip.top.align-center:before{left:50%;-webkit-transform:translateX(-50%);-ms-transform:translateX(-50%);transform:translateX(-50%)}.tooltip.left:before{border-color:transparent transparent transparent #0a0a0a;border-style:solid;border-width:.75rem 0 .75rem .75rem;content:"";display:block;height:0;left:100%;width:0}.tooltip.left.align-center:before{bottom:auto;top:50%;-webkit-transform:translateY(-50%);-ms-transform:translateY(-50%);transform:translateY(-50%)}.tooltip.right:before{border-color:transparent #0a0a0a transparent transparent;border-style:solid;border-width:.75rem .75rem .75rem 0;content:"";display:block;height:0;left:auto;right:100%;width:0}.tooltip.right.align-center:before{bottom:auto;top:50%;-webkit-transform:translateY(-50%);-ms-transform:translateY(-50%);transform:translateY(-50%)}.tooltip.align-top:before{bottom:auto;top:10%}.tooltip.align-bottom:before{bottom:10%;top:auto}.tooltip.align-left:before{left:10%;right:auto}.tooltip.align-right:before{left:auto;right:10%}.accordion{background:#fefefe;list-style-type:none;margin-left:0}.accordion[disabled] .accordion-title{cursor:not-allowed}.accordion-item:first-child>:first-child{border-radius:0}.accordion-item:last-child>:last-child{border-radius:0}.accordion-title{border:1px solid #e6e6e6;border-bottom:0;color:#1779ba;display:block;font-size:.75rem;line-height:1;padding:1.25rem 1rem;position:relative}:last-child:not(.is-active)>.accordion-title{border-bottom:1px solid #e6e6e6;border-radius:0}.accordion-title:focus,.accordion-title:hover{background-color:#e6e6e6}.accordion-title:before{content:"+";margin-top:-.5rem;position:absolute;right:1rem;top:50%}.is-active>.accordion-title:before{content:"–"}.accordion-content{background-color:#fefefe;border:1px solid #e6e6e6;border-bottom:0;color:#0a0a0a;display:none;padding:1rem}:last-child>.accordion-content:last-child{border-bottom:1px solid #e6e6e6}.media-object{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap;margin-bottom:1rem}.media-object img{max-width:none}@media print,screen and (max-width:39.99875em){.media-object.stack-for-small{-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap}}.media-object-section{-webkit-box-flex:0;-webkit-flex:0 1 auto;-ms-flex:0 1 auto;flex:0 1 auto}.media-object-section:first-child{padding-right:1rem}.media-object-section:last-child:not(:nth-child(2)){padding-left:1rem}.media-object-section>:last-child{margin-bottom:0}@media print,screen and (max-width:39.99875em){.stack-for-small .media-object-section{-ms-flex-preferred-size:100%;-webkit-flex-basis:100%;flex-basis:100%;max-width:100%;padding:0 0 1rem}.stack-for-small .media-object-section img{width:100%}}.media-object-section.main-section{-webkit-box-flex:1;-webkit-flex:1 1 0px;-ms-flex:1 1 0px;flex:1 1 0px}.orbit,.orbit-container{position:relative}.orbit-container{height:0;list-style:none;margin:0;overflow:hidden}.orbit-slide{position:absolute;width:100%}.orbit-slide.no-motionui.is-active{left:0;top:0}.orbit-figure{margin:0}.orbit-image{margin:0;max-width:100%;width:100%}.orbit-caption{background-color:hsla(0,0%,4%,.5);bottom:0;margin-bottom:0;width:100%}.orbit-caption,.orbit-next,.orbit-previous{color:#fefefe;padding:1rem;position:absolute}.orbit-next,.orbit-previous{top:50%;-webkit-transform:translateY(-50%);-ms-transform:translateY(-50%);transform:translateY(-50%);z-index:10}[data-whatinput=mouse] .orbit-next,[data-whatinput=mouse] .orbit-previous{outline:0}.orbit-next:active,.orbit-next:focus,.orbit-next:hover,.orbit-previous:active,.orbit-previous:focus,.orbit-previous:hover{background-color:hsla(0,0%,4%,.5)}.orbit-previous{left:0}.orbit-next{left:auto;right:0}.orbit-bullets{margin-bottom:.8rem;margin-top:.8rem;position:relative;text-align:center}[data-whatinput=mouse] .orbit-bullets{outline:0}.orbit-bullets button{background-color:#cacaca;border-radius:50%;height:1.2rem;margin:.1rem;width:1.2rem}.orbit-bullets button:hover{background-color:#8a8a8a}.orbit-bullets button.is-active{background-color:#8a8a8a}.flex-video,.responsive-embed{height:0;margin-bottom:1rem;overflow:hidden;padding-bottom:75%;position:relative}.flex-video embed,.flex-video iframe,.flex-video object,.flex-video video,.responsive-embed embed,.responsive-embed iframe,.responsive-embed object,.responsive-embed video{height:100%;left:0;position:absolute;top:0;width:100%}.flex-video.widescreen,.responsive-embed.widescreen{padding-bottom:56.25%}.tabs{background:#fefefe;border:1px solid #e6e6e6;list-style-type:none;margin:0}.tabs:after,.tabs:before{-ms-flex-preferred-size:0;-webkit-box-ordinal-group:2;-ms-flex-order:1;content:" ";display:table;-webkit-flex-basis:0;flex-basis:0;-webkit-order:1;order:1}.tabs:after{clear:both}.tabs.vertical>li{display:block;float:none;width:auto}.tabs.simple>li>a{padding:0}.tabs.simple>li>a:hover{background:0 0}.tabs.primary{background:#1779ba}.tabs.primary>li>a{color:#fefefe}.tabs.primary>li>a:focus,.tabs.primary>li>a:hover{background:#1673b1}.tabs-title{float:left}.tabs-title>a{color:#1779ba;display:block;font-size:.75rem;line-height:1;padding:1.25rem 1.5rem}[data-whatinput=mouse] .tabs-title>a{outline:0}.tabs-title>a:hover{background:#fefefe;color:#1468a0}.tabs-title>a:focus,.tabs-title>a[aria-selected=true]{background:#e6e6e6;color:#1779ba}.tabs-content{background:#fefefe;border:1px solid #e6e6e6;border-top:0;color:#0a0a0a;-webkit-transition:all .5s ease;transition:all .5s ease}.tabs-content.vertical{border:1px solid #e6e6e6;border-left:0}.tabs-panel{display:none;padding:1rem}.tabs-panel.is-active{display:block}.thumbnail{border:4px solid #fefefe;border-radius:0;-webkit-box-shadow:0 0 0 1px hsla(0,0%,4%,.2);box-shadow:0 0 0 1px hsla(0,0%,4%,.2);display:inline-block;line-height:0;margin-bottom:1rem;max-width:100%}a.thumbnail{-webkit-transition:-webkit-box-shadow .2s ease-out;transition:-webkit-box-shadow .2s ease-out;transition:box-shadow .2s ease-out;transition:box-shadow .2s ease-out,-webkit-box-shadow .2s ease-out}a.thumbnail:focus,a.thumbnail:hover{-webkit-box-shadow:0 0 6px 1px rgba(23,121,186,.5);box-shadow:0 0 6px 1px rgba(23,121,186,.5)}a.thumbnail image{-webkit-box-shadow:none;box-shadow:none}.menu{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;list-style:none;margin:0;padding:0;position:relative}[data-whatinput=mouse] .menu li{outline:0}.menu .button,.menu a{display:block;line-height:1;padding:.7rem 1rem;text-decoration:none}.menu a,.menu button,.menu input,.menu select{margin-bottom:0}.menu input{display:inline-block}.menu,.menu.horizontal{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap}.menu.vertical{-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap}.menu.vertical.icon-bottom li a i,.menu.vertical.icon-bottom li a img,.menu.vertical.icon-bottom li a svg,.menu.vertical.icon-top li a i,.menu.vertical.icon-top li a img,.menu.vertical.icon-top li a svg{text-align:left}.menu.expanded li{-webkit-box-flex:1;-webkit-flex:1 1 0px;-ms-flex:1 1 0px;flex:1 1 0px}.menu.expanded.icon-bottom li a i,.menu.expanded.icon-bottom li a img,.menu.expanded.icon-bottom li a svg,.menu.expanded.icon-top li a i,.menu.expanded.icon-top li a img,.menu.expanded.icon-top li a svg{text-align:left}.menu.simple{-webkit-box-align:center;-ms-flex-align:center;-webkit-align-items:center;align-items:center}.menu.simple li+li{margin-left:1rem}.menu.simple a{padding:0}@media print,screen and (min-width:40em){.menu.medium-horizontal{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap}.menu.medium-vertical{-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap}.menu.medium-expanded li,.menu.medium-simple li{-webkit-box-flex:1;-webkit-flex:1 1 0px;-ms-flex:1 1 0px;flex:1 1 0px}}@media print,screen and (min-width:64em){.menu.large-horizontal{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap}.menu.large-vertical{-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap}.menu.large-expanded li,.menu.large-simple li{-webkit-box-flex:1;-webkit-flex:1 1 0px;-ms-flex:1 1 0px;flex:1 1 0px}}.menu.nested{margin-left:1rem;margin-right:0}.menu.icon-bottom a,.menu.icon-left a,.menu.icon-right a,.menu.icon-top a,.menu.icons a{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex}.menu.icon-left li a,.menu.nested.icon-left li a{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-flow:row nowrap;-ms-flex-flow:row nowrap;flex-flow:row nowrap}.menu.icon-left li a i,.menu.icon-left li a img,.menu.icon-left li a svg,.menu.nested.icon-left li a i,.menu.nested.icon-left li a img,.menu.nested.icon-left li a svg{margin-right:.25rem}.menu.icon-right li a,.menu.nested.icon-right li a{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-flow:row nowrap;-ms-flex-flow:row nowrap;flex-flow:row nowrap}.menu.icon-right li a i,.menu.icon-right li a img,.menu.icon-right li a svg,.menu.nested.icon-right li a i,.menu.nested.icon-right li a img,.menu.nested.icon-right li a svg{margin-left:.25rem}.menu.icon-top li a,.menu.nested.icon-top li a{-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-flow:column nowrap;-ms-flex-flow:column nowrap;flex-flow:column nowrap}.menu.icon-top li a i,.menu.icon-top li a img,.menu.icon-top li a svg,.menu.nested.icon-top li a i,.menu.nested.icon-top li a img,.menu.nested.icon-top li a svg{-ms-flex-item-align:stretch;-webkit-align-self:stretch;align-self:stretch;margin-bottom:.25rem;text-align:center}.menu.icon-bottom li a,.menu.nested.icon-bottom li a{-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-flow:column nowrap;-ms-flex-flow:column nowrap;flex-flow:column nowrap}.menu.icon-bottom li a i,.menu.icon-bottom li a img,.menu.icon-bottom li a svg,.menu.nested.icon-bottom li a i,.menu.nested.icon-bottom li a img,.menu.nested.icon-bottom li a svg{-ms-flex-item-align:stretch;-webkit-align-self:stretch;align-self:stretch;margin-bottom:.25rem;text-align:center}.menu .is-active>a{background:#1779ba;color:#fefefe}.menu .active>a{background:#1779ba;color:#fefefe}.menu.align-left{-webkit-box-pack:start;-ms-flex-pack:start;-webkit-justify-content:flex-start;justify-content:flex-start}.menu.align-right li{-webkit-box-pack:end;-ms-flex-pack:end;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-justify-content:flex-end;justify-content:flex-end}.menu.align-right li .submenu li{-webkit-box-pack:start;-ms-flex-pack:start;-webkit-justify-content:flex-start;justify-content:flex-start}.menu.align-right.vertical li{display:block;text-align:right}.menu.align-right.icon-bottom li a i,.menu.align-right.icon-bottom li a img,.menu.align-right.icon-bottom li a svg,.menu.align-right.icon-top li a i,.menu.align-right.icon-top li a img,.menu.align-right.icon-top li a svg,.menu.align-right.vertical li .submenu li{text-align:right}.menu.align-right .nested{margin-left:0;margin-right:1rem}.menu.align-center li{-webkit-box-pack:center;-ms-flex-pack:center;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-justify-content:center;justify-content:center}.menu.align-center li .submenu li{-webkit-box-pack:start;-ms-flex-pack:start;-webkit-justify-content:flex-start;justify-content:flex-start}.menu .menu-text{color:inherit;font-weight:700;line-height:1;padding:.7rem 1rem}.menu-centered>.menu{-webkit-box-pack:center;-ms-flex-pack:center;-webkit-justify-content:center;justify-content:center}.menu-centered>.menu li{-webkit-box-pack:center;-ms-flex-pack:center;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-justify-content:center;justify-content:center}.menu-centered>.menu li .submenu li{-webkit-box-pack:start;-ms-flex-pack:start;-webkit-justify-content:flex-start;justify-content:flex-start}.no-js [data-responsive-menu] ul{display:none}.menu-icon{cursor:pointer;display:inline-block;height:16px;position:relative;vertical-align:middle;width:20px}.menu-icon:after{background:#fefefe;-webkit-box-shadow:0 7px 0 #fefefe,0 14px 0 #fefefe;box-shadow:0 7px 0 #fefefe,0 14px 0 #fefefe;content:"";display:block;height:2px;left:0;position:absolute;top:0;width:100%}.menu-icon:hover:after{background:#cacaca;-webkit-box-shadow:0 7px 0 #cacaca,0 14px 0 #cacaca;box-shadow:0 7px 0 #cacaca,0 14px 0 #cacaca}.menu-icon.dark{cursor:pointer;display:inline-block;height:16px;position:relative;vertical-align:middle;width:20px}.menu-icon.dark:after{background:#0a0a0a;-webkit-box-shadow:0 7px 0 #0a0a0a,0 14px 0 #0a0a0a;box-shadow:0 7px 0 #0a0a0a,0 14px 0 #0a0a0a;content:"";display:block;height:2px;left:0;position:absolute;top:0;width:100%}.menu-icon.dark:hover:after{background:#8a8a8a;-webkit-box-shadow:0 7px 0 #8a8a8a,0 14px 0 #8a8a8a;box-shadow:0 7px 0 #8a8a8a,0 14px 0 #8a8a8a}.accordion-menu li{width:100%}.accordion-menu .is-accordion-submenu a,.accordion-menu a{padding:.7rem 1rem}.accordion-menu .nested.is-accordion-submenu{margin-left:1rem;margin-right:0}.accordion-menu.align-right .nested.is-accordion-submenu{margin-left:0;margin-right:1rem}.accordion-menu .is-accordion-submenu-parent:not(.has-submenu-toggle)>a{position:relative}.accordion-menu .is-accordion-submenu-parent:not(.has-submenu-toggle)>a:after{border-color:#1779ba transparent transparent;border-style:solid;border-width:6px 6px 0;content:"";display:block;height:0;margin-top:-3px;position:absolute;right:1rem;top:50%;width:0}.accordion-menu.align-left .is-accordion-submenu-parent>a:after{left:auto;right:1rem}.accordion-menu.align-right .is-accordion-submenu-parent>a:after{left:1rem;right:auto}.accordion-menu .is-accordion-submenu-parent[aria-expanded=true]>a:after{-webkit-transform:rotate(180deg);-ms-transform:rotate(180deg);transform:rotate(180deg);-webkit-transform-origin:50% 50%;-ms-transform-origin:50% 50%;transform-origin:50% 50%}.is-accordion-submenu-parent{position:relative}.has-submenu-toggle>a{margin-right:40px}.submenu-toggle{cursor:pointer;height:40px;position:absolute;right:0;top:0;width:40px}.submenu-toggle:after{border-color:#1779ba transparent transparent;border-style:solid;border-width:6px 6px 0;bottom:0;content:"";display:block;height:0;margin:auto;top:0;width:0}.submenu-toggle[aria-expanded=true]:after{-webkit-transform:scaleY(-1);-ms-transform:scaleY(-1);transform:scaleY(-1);-webkit-transform-origin:50% 50%;-ms-transform-origin:50% 50%;transform-origin:50% 50%}.submenu-toggle-text{clip:rect(0,0,0,0)!important;border:0!important;height:1px!important;overflow:hidden!important;padding:0!important;position:absolute!important;white-space:nowrap!important;width:1px!important}.is-drilldown{overflow:hidden;position:relative}.is-drilldown li{display:block}.is-drilldown.animate-height{-webkit-transition:height .5s;transition:height .5s}.drilldown a{background:#fefefe;padding:.7rem 1rem}.drilldown .is-drilldown-submenu{background:#fefefe;left:100%;position:absolute;top:0;-webkit-transition:-webkit-transform .15s linear;transition:-webkit-transform .15s linear;transition:transform .15s linear;transition:transform .15s linear,-webkit-transform .15s linear;width:100%;z-index:-1}.drilldown .is-drilldown-submenu.is-active{display:block;-webkit-transform:translateX(-100%);-ms-transform:translateX(-100%);transform:translateX(-100%);z-index:1}.drilldown .is-drilldown-submenu.is-closing{-webkit-transform:translateX(100%);-ms-transform:translateX(100%);transform:translateX(100%)}.drilldown .is-drilldown-submenu a{padding:.7rem 1rem}.drilldown .nested.is-drilldown-submenu{margin-left:0;margin-right:0}.drilldown .drilldown-submenu-cover-previous{min-height:100%}.drilldown .is-drilldown-submenu-parent>a{position:relative}.drilldown .is-drilldown-submenu-parent>a:after{border-color:transparent transparent transparent #1779ba;border-style:solid;border-width:6px 0 6px 6px;content:"";display:block;height:0;margin-top:-6px;position:absolute;right:1rem;top:50%;width:0}.drilldown.align-left .is-drilldown-submenu-parent>a:after{border-color:transparent transparent transparent #1779ba;border-style:solid;border-width:6px 0 6px 6px;content:"";display:block;height:0;left:auto;right:1rem;width:0}.drilldown.align-right .is-drilldown-submenu-parent>a:after{border-color:transparent #1779ba transparent transparent;border-style:solid;border-width:6px 6px 6px 0;content:"";display:block;height:0;left:1rem;right:auto;width:0}.drilldown .js-drilldown-back>a:before{border-color:transparent #1779ba transparent transparent;border-style:solid;border-width:6px 6px 6px 0;content:"";display:block;display:inline-block;height:0;margin-right:.75rem;vertical-align:middle;width:0}.dropdown.menu>li.opens-left>.is-dropdown-submenu{left:auto;right:0;top:100%}.dropdown.menu>li.opens-right>.is-dropdown-submenu{left:0;right:auto;top:100%}.dropdown.menu>li.is-dropdown-submenu-parent>a{padding-right:1.5rem;position:relative}.dropdown.menu>li.is-dropdown-submenu-parent>a:after{border-color:#1779ba transparent transparent;border-style:solid;border-width:6px 6px 0;content:"";display:block;height:0;left:auto;margin-top:-3px;right:5px;width:0}[data-whatinput=mouse] .dropdown.menu a{outline:0}.dropdown.menu>li>a{padding:.7rem 1rem}.dropdown.menu>li.is-active>a{background:0 0;color:#1779ba}.no-js .dropdown.menu ul{display:none}.dropdown.menu .nested.is-dropdown-submenu{margin-left:0;margin-right:0}.dropdown.menu.vertical>li .is-dropdown-submenu{top:0}.dropdown.menu.vertical>li.opens-left>.is-dropdown-submenu{left:auto;right:100%;top:0}.dropdown.menu.vertical>li.opens-right>.is-dropdown-submenu{left:100%;right:auto}.dropdown.menu.vertical>li>a:after{right:14px}.dropdown.menu.vertical>li.opens-left>a:after{border-color:transparent #1779ba transparent transparent;border-style:solid;border-width:6px 6px 6px 0;content:"";display:block;height:0;left:5px;right:auto;width:0}.dropdown.menu.vertical>li.opens-right>a:after{border-color:transparent transparent transparent #1779ba;border-style:solid;border-width:6px 0 6px 6px;content:"";display:block;height:0;width:0}@media print,screen and (min-width:40em){.dropdown.menu.medium-horizontal>li.opens-left>.is-dropdown-submenu{left:auto;right:0;top:100%}.dropdown.menu.medium-horizontal>li.opens-right>.is-dropdown-submenu{left:0;right:auto;top:100%}.dropdown.menu.medium-horizontal>li.is-dropdown-submenu-parent>a{padding-right:1.5rem;position:relative}.dropdown.menu.medium-horizontal>li.is-dropdown-submenu-parent>a:after{border-color:#1779ba transparent transparent;border-style:solid;border-width:6px 6px 0;content:"";display:block;height:0;left:auto;margin-top:-3px;right:5px;width:0}.dropdown.menu.medium-vertical>li .is-dropdown-submenu{top:0}.dropdown.menu.medium-vertical>li.opens-left>.is-dropdown-submenu{left:auto;right:100%;top:0}.dropdown.menu.medium-vertical>li.opens-right>.is-dropdown-submenu{left:100%;right:auto}.dropdown.menu.medium-vertical>li>a:after{right:14px}.dropdown.menu.medium-vertical>li.opens-left>a:after{border-color:transparent #1779ba transparent transparent;border-style:solid;border-width:6px 6px 6px 0;content:"";display:block;height:0;left:5px;right:auto;width:0}.dropdown.menu.medium-vertical>li.opens-right>a:after{border-color:transparent transparent transparent #1779ba;border-style:solid;border-width:6px 0 6px 6px;content:"";display:block;height:0;width:0}}@media print,screen and (min-width:64em){.dropdown.menu.large-horizontal>li.opens-left>.is-dropdown-submenu{left:auto;right:0;top:100%}.dropdown.menu.large-horizontal>li.opens-right>.is-dropdown-submenu{left:0;right:auto;top:100%}.dropdown.menu.large-horizontal>li.is-dropdown-submenu-parent>a{padding-right:1.5rem;position:relative}.dropdown.menu.large-horizontal>li.is-dropdown-submenu-parent>a:after{border-color:#1779ba transparent transparent;border-style:solid;border-width:6px 6px 0;content:"";display:block;height:0;left:auto;margin-top:-3px;right:5px;width:0}.dropdown.menu.large-vertical>li .is-dropdown-submenu{top:0}.dropdown.menu.large-vertical>li.opens-left>.is-dropdown-submenu{left:auto;right:100%;top:0}.dropdown.menu.large-vertical>li.opens-right>.is-dropdown-submenu{left:100%;right:auto}.dropdown.menu.large-vertical>li>a:after{right:14px}.dropdown.menu.large-vertical>li.opens-left>a:after{border-color:transparent #1779ba transparent transparent;border-style:solid;border-width:6px 6px 6px 0;content:"";display:block;height:0;left:5px;right:auto;width:0}.dropdown.menu.large-vertical>li.opens-right>a:after{border-color:transparent transparent transparent #1779ba;border-style:solid;border-width:6px 0 6px 6px;content:"";display:block;height:0;width:0}}.dropdown.menu.align-right .is-dropdown-submenu.first-sub{left:auto;right:0;top:100%}.is-dropdown-menu.vertical{width:100px}.is-dropdown-menu.vertical.align-right{float:right}.is-dropdown-submenu-parent{position:relative}.is-dropdown-submenu-parent a:after{left:auto;margin-top:-6px;position:absolute;right:5px;top:50%}.is-dropdown-submenu-parent.opens-inner>.is-dropdown-submenu{left:auto;top:100%}.is-dropdown-submenu-parent.opens-left>.is-dropdown-submenu{left:auto;right:100%}.is-dropdown-submenu-parent.opens-right>.is-dropdown-submenu{left:100%;right:auto}.is-dropdown-submenu{background:#fefefe;border:1px solid #cacaca;display:none;left:100%;min-width:200px;position:absolute;top:0;z-index:1}.dropdown .is-dropdown-submenu a{padding:.7rem 1rem}.is-dropdown-submenu .is-dropdown-submenu-parent>a:after{right:14px}.is-dropdown-submenu .is-dropdown-submenu-parent.opens-left>a:after{border-color:transparent #1779ba transparent transparent;border-style:solid;border-width:6px 6px 6px 0;content:"";display:block;height:0;left:5px;right:auto;width:0}.is-dropdown-submenu .is-dropdown-submenu-parent.opens-right>a:after{border-color:transparent transparent transparent #1779ba;border-style:solid;border-width:6px 0 6px 6px;content:"";display:block;height:0;width:0}.is-dropdown-submenu .is-dropdown-submenu{margin-top:-1px}.is-dropdown-submenu>li{width:100%}.is-dropdown-submenu.js-dropdown-active{display:block}.is-off-canvas-open{overflow:hidden}.js-off-canvas-overlay{background:hsla(0,0%,100%,.25);height:100%;left:0;opacity:0;overflow:hidden;position:absolute;top:0;-webkit-transition:opacity .5s ease,visibility .5s ease;transition:opacity .5s ease,visibility .5s ease;visibility:hidden;width:100%;z-index:11}.js-off-canvas-overlay.is-visible{opacity:1;visibility:visible}.js-off-canvas-overlay.is-closable{cursor:pointer}.js-off-canvas-overlay.is-overlay-absolute{position:absolute}.js-off-canvas-overlay.is-overlay-fixed{position:fixed}.off-canvas-wrapper{overflow:hidden;position:relative}.off-canvas{-webkit-backface-visibility:hidden;backface-visibility:hidden;background:#e6e6e6;position:fixed;-webkit-transition:-webkit-transform .5s ease;transition:-webkit-transform .5s ease;transition:transform .5s ease;transition:transform .5s ease,-webkit-transform .5s ease;z-index:12}[data-whatinput=mouse] .off-canvas{outline:0}.off-canvas.is-transition-push{z-index:12}.off-canvas.is-closed{visibility:hidden}.off-canvas.is-transition-overlap{z-index:13}.off-canvas.is-transition-overlap.is-open{-webkit-box-shadow:0 0 10px hsla(0,0%,4%,.7);box-shadow:0 0 10px hsla(0,0%,4%,.7)}.off-canvas.is-open{-webkit-transform:translate(0);-ms-transform:translate(0);transform:translate(0)}.off-canvas-absolute{-webkit-backface-visibility:hidden;backface-visibility:hidden;background:#e6e6e6;position:absolute;-webkit-transition:-webkit-transform .5s ease;transition:-webkit-transform .5s ease;transition:transform .5s ease;transition:transform .5s ease,-webkit-transform .5s ease;z-index:12}[data-whatinput=mouse] .off-canvas-absolute{outline:0}.off-canvas-absolute.is-transition-push{z-index:12}.off-canvas-absolute.is-closed{visibility:hidden}.off-canvas-absolute.is-transition-overlap{z-index:13}.off-canvas-absolute.is-transition-overlap.is-open{-webkit-box-shadow:0 0 10px hsla(0,0%,4%,.7);box-shadow:0 0 10px hsla(0,0%,4%,.7)}.off-canvas-absolute.is-open{-webkit-transform:translate(0);-ms-transform:translate(0);transform:translate(0)}.position-left{-webkit-overflow-scrolling:touch;height:100%;left:0;overflow-y:auto;top:0;width:250px}.off-canvas-content .off-canvas.position-left,.position-left{-webkit-transform:translateX(-250px);-ms-transform:translateX(-250px);transform:translateX(-250px)}.off-canvas-content .off-canvas.position-left.is-transition-overlap.is-open{-webkit-transform:translate(0);-ms-transform:translate(0);transform:translate(0)}.off-canvas-content.is-open-left.has-transition-push{-webkit-transform:translateX(250px);-ms-transform:translateX(250px);transform:translateX(250px)}.position-left.is-transition-push{-webkit-box-shadow:inset -13px 0 20px -13px hsla(0,0%,4%,.25);box-shadow:inset -13px 0 20px -13px hsla(0,0%,4%,.25)}.position-right{-webkit-overflow-scrolling:touch;height:100%;overflow-y:auto;right:0;top:0;width:250px}.off-canvas-content .off-canvas.position-right,.position-right{-webkit-transform:translateX(250px);-ms-transform:translateX(250px);transform:translateX(250px)}.off-canvas-content .off-canvas.position-right.is-transition-overlap.is-open{-webkit-transform:translate(0);-ms-transform:translate(0);transform:translate(0)}.off-canvas-content.is-open-right.has-transition-push{-webkit-transform:translateX(-250px);-ms-transform:translateX(-250px);transform:translateX(-250px)}.position-right.is-transition-push{-webkit-box-shadow:inset 13px 0 20px -13px hsla(0,0%,4%,.25);box-shadow:inset 13px 0 20px -13px hsla(0,0%,4%,.25)}.position-top{-webkit-overflow-scrolling:touch;height:250px;left:0;overflow-x:auto;top:0;width:100%}.off-canvas-content .off-canvas.position-top,.position-top{-webkit-transform:translateY(-250px);-ms-transform:translateY(-250px);transform:translateY(-250px)}.off-canvas-content .off-canvas.position-top.is-transition-overlap.is-open{-webkit-transform:translate(0);-ms-transform:translate(0);transform:translate(0)}.off-canvas-content.is-open-top.has-transition-push{-webkit-transform:translateY(250px);-ms-transform:translateY(250px);transform:translateY(250px)}.position-top.is-transition-push{-webkit-box-shadow:inset 0 -13px 20px -13px hsla(0,0%,4%,.25);box-shadow:inset 0 -13px 20px -13px hsla(0,0%,4%,.25)}.position-bottom{-webkit-overflow-scrolling:touch;bottom:0;height:250px;left:0;overflow-x:auto;width:100%}.off-canvas-content .off-canvas.position-bottom,.position-bottom{-webkit-transform:translateY(250px);-ms-transform:translateY(250px);transform:translateY(250px)}.off-canvas-content .off-canvas.position-bottom.is-transition-overlap.is-open{-webkit-transform:translate(0);-ms-transform:translate(0);transform:translate(0)}.off-canvas-content.is-open-bottom.has-transition-push{-webkit-transform:translateY(-250px);-ms-transform:translateY(-250px);transform:translateY(-250px)}.position-bottom.is-transition-push{-webkit-box-shadow:inset 0 13px 20px -13px hsla(0,0%,4%,.25);box-shadow:inset 0 13px 20px -13px hsla(0,0%,4%,.25)}.off-canvas-content{-webkit-backface-visibility:hidden;backface-visibility:hidden;-webkit-transform:none;-ms-transform:none;transform:none}.off-canvas-content.has-transition-overlap,.off-canvas-content.has-transition-push{-webkit-transition:-webkit-transform .5s ease;transition:-webkit-transform .5s ease;transition:transform .5s ease;transition:transform .5s ease,-webkit-transform .5s ease}.off-canvas-content.has-transition-push,.off-canvas-content .off-canvas.is-open{-webkit-transform:translate(0);-ms-transform:translate(0);transform:translate(0)}@media print,screen and (min-width:40em){.position-left.reveal-for-medium{-webkit-transform:none;-ms-transform:none;transform:none;-webkit-transition:none;transition:none;visibility:visible;z-index:12}.position-left.reveal-for-medium .close-button{display:none}.off-canvas-content .position-left.reveal-for-medium{-webkit-transform:none;-ms-transform:none;transform:none}.off-canvas-content.has-reveal-left{margin-left:250px}.position-left.reveal-for-medium~.off-canvas-content{margin-left:250px}.position-right.reveal-for-medium{-webkit-transform:none;-ms-transform:none;transform:none;-webkit-transition:none;transition:none;visibility:visible;z-index:12}.position-right.reveal-for-medium .close-button{display:none}.off-canvas-content .position-right.reveal-for-medium{-webkit-transform:none;-ms-transform:none;transform:none}.off-canvas-content.has-reveal-right{margin-right:250px}.position-right.reveal-for-medium~.off-canvas-content{margin-right:250px}.position-top.reveal-for-medium{-webkit-transform:none;-ms-transform:none;transform:none;-webkit-transition:none;transition:none;visibility:visible;z-index:12}.position-top.reveal-for-medium .close-button{display:none}.off-canvas-content .position-top.reveal-for-medium{-webkit-transform:none;-ms-transform:none;transform:none}.off-canvas-content.has-reveal-top{margin-top:250px}.position-top.reveal-for-medium~.off-canvas-content{margin-top:250px}.position-bottom.reveal-for-medium{-webkit-transform:none;-ms-transform:none;transform:none;-webkit-transition:none;transition:none;visibility:visible;z-index:12}.position-bottom.reveal-for-medium .close-button{display:none}.off-canvas-content .position-bottom.reveal-for-medium{-webkit-transform:none;-ms-transform:none;transform:none}.off-canvas-content.has-reveal-bottom{margin-bottom:250px}.position-bottom.reveal-for-medium~.off-canvas-content{margin-bottom:250px}}@media print,screen and (min-width:64em){.position-left.reveal-for-large{-webkit-transform:none;-ms-transform:none;transform:none;-webkit-transition:none;transition:none;visibility:visible;z-index:12}.position-left.reveal-for-large .close-button{display:none}.off-canvas-content .position-left.reveal-for-large{-webkit-transform:none;-ms-transform:none;transform:none}.off-canvas-content.has-reveal-left{margin-left:250px}.position-left.reveal-for-large~.off-canvas-content{margin-left:250px}.position-right.reveal-for-large{-webkit-transform:none;-ms-transform:none;transform:none;-webkit-transition:none;transition:none;visibility:visible;z-index:12}.position-right.reveal-for-large .close-button{display:none}.off-canvas-content .position-right.reveal-for-large{-webkit-transform:none;-ms-transform:none;transform:none}.off-canvas-content.has-reveal-right{margin-right:250px}.position-right.reveal-for-large~.off-canvas-content{margin-right:250px}.position-top.reveal-for-large{-webkit-transform:none;-ms-transform:none;transform:none;-webkit-transition:none;transition:none;visibility:visible;z-index:12}.position-top.reveal-for-large .close-button{display:none}.off-canvas-content .position-top.reveal-for-large{-webkit-transform:none;-ms-transform:none;transform:none}.off-canvas-content.has-reveal-top{margin-top:250px}.position-top.reveal-for-large~.off-canvas-content{margin-top:250px}.position-bottom.reveal-for-large{-webkit-transform:none;-ms-transform:none;transform:none;-webkit-transition:none;transition:none;visibility:visible;z-index:12}.position-bottom.reveal-for-large .close-button{display:none}.off-canvas-content .position-bottom.reveal-for-large{-webkit-transform:none;-ms-transform:none;transform:none}.off-canvas-content.has-reveal-bottom{margin-bottom:250px}.position-bottom.reveal-for-large~.off-canvas-content{margin-bottom:250px}}@media print,screen and (min-width:40em){.off-canvas.in-canvas-for-medium{background:0 0;height:auto;overflow:visible;position:static;-webkit-transition:none;transition:none;visibility:visible;width:auto}.off-canvas.in-canvas-for-medium.position-bottom,.off-canvas.in-canvas-for-medium.position-left,.off-canvas.in-canvas-for-medium.position-right,.off-canvas.in-canvas-for-medium.position-top{-webkit-box-shadow:none;box-shadow:none;-webkit-transform:none;-ms-transform:none;transform:none}.off-canvas.in-canvas-for-medium .close-button{display:none}}@media print,screen and (min-width:64em){.off-canvas.in-canvas-for-large{background:0 0;height:auto;overflow:visible;position:static;-webkit-transition:none;transition:none;visibility:visible;width:auto}.off-canvas.in-canvas-for-large.position-bottom,.off-canvas.in-canvas-for-large.position-left,.off-canvas.in-canvas-for-large.position-right,.off-canvas.in-canvas-for-large.position-top{-webkit-box-shadow:none;box-shadow:none;-webkit-transform:none;-ms-transform:none;transform:none}.off-canvas.in-canvas-for-large .close-button{display:none}}html.is-reveal-open{overflow-y:hidden;position:fixed;width:100%}html.is-reveal-open.zf-has-scroll{-webkit-overflow-scrolling:touch;overflow-y:scroll}html.is-reveal-open body{overflow-y:hidden}.reveal-overlay{background-color:hsla(0,0%,4%,.45);bottom:0;left:0;position:fixed;right:0;top:0;z-index:1005}.reveal,.reveal-overlay{-webkit-overflow-scrolling:touch;display:none;overflow-y:auto}.reveal{-webkit-backface-visibility:hidden;backface-visibility:hidden;background-color:#fefefe;border:1px solid #cacaca;border-radius:0;margin-left:auto;margin-right:auto;padding:1rem;position:relative;top:100px;z-index:1006}[data-whatinput=mouse] .reveal{outline:0}@media print,screen and (min-width:40em){.reveal{min-height:0}}.reveal .column{min-width:0}.reveal>:last-child{margin-bottom:0}@media print,screen and (min-width:40em){.reveal{max-width:75rem;width:600px}}.reveal.collapse{padding:0}@media print,screen and (min-width:40em){.reveal.tiny{max-width:75rem;width:30%}.reveal.small{max-width:75rem;width:50%}.reveal.large{max-width:75rem;width:90%}}.reveal.full{border:0;border-radius:0;bottom:0;height:100%;left:0;margin-left:0;max-width:none;min-height:100%;right:0;top:0;width:100%}@media print,screen and (max-width:39.99875em){.reveal{border:0;border-radius:0;bottom:0;height:100%;left:0;margin-left:0;max-width:none;min-height:100%;right:0;top:0;width:100%}}.reveal.without-overlay{position:fixed}.sticky,.sticky-container{position:relative}.sticky{-webkit-transform:translateZ(0);transform:translateZ(0);z-index:0}.sticky.is-stuck{position:fixed;width:100%;z-index:5}.sticky.is-stuck.is-at-top{top:0}.sticky.is-stuck.is-at-bottom{bottom:0}.sticky.is-anchored{left:auto;position:relative;right:auto}.sticky.is-anchored.is-at-bottom{bottom:0}.title-bar{-webkit-box-pack:start;-ms-flex-pack:start;-webkit-box-align:center;-ms-flex-align:center;-webkit-align-items:center;align-items:center;background:#0a0a0a;color:#fefefe;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-justify-content:flex-start;justify-content:flex-start;padding:.5rem}.title-bar .menu-icon{margin-left:.25rem;margin-right:.25rem}.title-bar-left,.title-bar-right{-webkit-box-flex:1;-webkit-flex:1 1 0px;-ms-flex:1 1 0px;flex:1 1 0px}.title-bar-right{text-align:right}.title-bar-title{display:inline-block;font-weight:700;vertical-align:middle}.top-bar{-webkit-box-pack:justify;-ms-flex-pack:justify;-webkit-box-align:center;-ms-flex-align:center;-webkit-align-items:center;align-items:center;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;-webkit-justify-content:space-between;justify-content:space-between;padding:.5rem}.top-bar,.top-bar ul{background-color:#e6e6e6}.top-bar input{margin-right:1rem;max-width:200px}.top-bar .input-group-field{margin-right:0;width:100%}.top-bar input.button{width:auto}.top-bar .top-bar-left,.top-bar .top-bar-right{-webkit-box-flex:0;-webkit-flex:0 0 100%;-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}@media print,screen and (min-width:40em){.top-bar{-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap}.top-bar .top-bar-left{-webkit-box-flex:1;-webkit-flex:1 1 auto;-ms-flex:1 1 auto;flex:1 1 auto;margin-right:auto}.top-bar .top-bar-right{-webkit-box-flex:0;-webkit-flex:0 1 auto;-ms-flex:0 1 auto;flex:0 1 auto;margin-left:auto}}@media print,screen and (max-width:63.99875em){.top-bar.stacked-for-medium{-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap}.top-bar.stacked-for-medium .top-bar-left,.top-bar.stacked-for-medium .top-bar-right{-webkit-box-flex:0;-webkit-flex:0 0 100%;-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}}@media print,screen and (max-width:74.99875em){.top-bar.stacked-for-large{-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap}.top-bar.stacked-for-large .top-bar-left,.top-bar.stacked-for-large .top-bar-right{-webkit-box-flex:0;-webkit-flex:0 0 100%;-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}}.top-bar-title{margin:.5rem 1rem .5rem 0}.top-bar-left,.top-bar-right,.top-bar-title{-webkit-box-flex:0;-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto}.float-left{float:left!important}.float-right{float:right!important}.float-center{display:block;margin-left:auto;margin-right:auto}.clearfix:after,.clearfix:before{-ms-flex-preferred-size:0;-webkit-box-ordinal-group:2;-ms-flex-order:1;content:" ";display:table;-webkit-flex-basis:0;flex-basis:0;-webkit-order:1;order:1}.clearfix:after{clear:both}.align-left{-webkit-box-pack:start;-ms-flex-pack:start;-webkit-justify-content:flex-start;justify-content:flex-start}.align-right{-webkit-box-pack:end;-ms-flex-pack:end;-webkit-justify-content:flex-end;justify-content:flex-end}.align-center{-webkit-box-pack:center;-ms-flex-pack:center;-webkit-justify-content:center;justify-content:center}.align-justify{-webkit-box-pack:justify;-ms-flex-pack:justify;-webkit-justify-content:space-between;justify-content:space-between}.align-spaced{-ms-flex-pack:distribute;-webkit-justify-content:space-around;justify-content:space-around}.align-left.vertical.menu>li>a{-webkit-box-pack:start;-ms-flex-pack:start;-webkit-justify-content:flex-start;justify-content:flex-start}.align-right.vertical.menu>li>a{-webkit-box-pack:end;-ms-flex-pack:end;-webkit-justify-content:flex-end;justify-content:flex-end}.align-center.vertical.menu>li>a{-webkit-box-pack:center;-ms-flex-pack:center;-webkit-justify-content:center;justify-content:center}.align-top{-webkit-box-align:start;-ms-flex-align:start;-webkit-align-items:flex-start;align-items:flex-start}.align-self-top{-ms-flex-item-align:start;-webkit-align-self:flex-start;align-self:flex-start}.align-bottom{-webkit-box-align:end;-ms-flex-align:end;-webkit-align-items:flex-end;align-items:flex-end}.align-self-bottom{-ms-flex-item-align:end;-webkit-align-self:flex-end;align-self:flex-end}.align-middle{-webkit-box-align:center;-ms-flex-align:center;-webkit-align-items:center;align-items:center}.align-self-middle{-ms-flex-item-align:center;-webkit-align-self:center;align-self:center}.align-stretch{-webkit-box-align:stretch;-ms-flex-align:stretch;-webkit-align-items:stretch;align-items:stretch}.align-self-stretch{-ms-flex-item-align:stretch;-webkit-align-self:stretch;align-self:stretch}.align-center-middle{-webkit-box-pack:center;-ms-flex-pack:center;-webkit-box-align:center;-ms-flex-align:center;-ms-flex-line-pack:center;-webkit-align-content:center;align-content:center;-webkit-align-items:center;align-items:center;-webkit-justify-content:center;justify-content:center}.small-order-1{-webkit-box-ordinal-group:2;-ms-flex-order:1;-webkit-order:1;order:1}.small-order-2{-webkit-box-ordinal-group:3;-ms-flex-order:2;-webkit-order:2;order:2}.small-order-3{-webkit-box-ordinal-group:4;-ms-flex-order:3;-webkit-order:3;order:3}.small-order-4{-webkit-box-ordinal-group:5;-ms-flex-order:4;-webkit-order:4;order:4}.small-order-5{-webkit-box-ordinal-group:6;-ms-flex-order:5;-webkit-order:5;order:5}.small-order-6{-webkit-box-ordinal-group:7;-ms-flex-order:6;-webkit-order:6;order:6}@media print,screen and (min-width:40em){.medium-order-1{-webkit-box-ordinal-group:2;-ms-flex-order:1;-webkit-order:1;order:1}.medium-order-2{-webkit-box-ordinal-group:3;-ms-flex-order:2;-webkit-order:2;order:2}.medium-order-3{-webkit-box-ordinal-group:4;-ms-flex-order:3;-webkit-order:3;order:3}.medium-order-4{-webkit-box-ordinal-group:5;-ms-flex-order:4;-webkit-order:4;order:4}.medium-order-5{-webkit-box-ordinal-group:6;-ms-flex-order:5;-webkit-order:5;order:5}.medium-order-6{-webkit-box-ordinal-group:7;-ms-flex-order:6;-webkit-order:6;order:6}}@media print,screen and (min-width:64em){.large-order-1{-webkit-box-ordinal-group:2;-ms-flex-order:1;-webkit-order:1;order:1}.large-order-2{-webkit-box-ordinal-group:3;-ms-flex-order:2;-webkit-order:2;order:2}.large-order-3{-webkit-box-ordinal-group:4;-ms-flex-order:3;-webkit-order:3;order:3}.large-order-4{-webkit-box-ordinal-group:5;-ms-flex-order:4;-webkit-order:4;order:4}.large-order-5{-webkit-box-ordinal-group:6;-ms-flex-order:5;-webkit-order:5;order:5}.large-order-6{-webkit-box-ordinal-group:7;-ms-flex-order:6;-webkit-order:6;order:6}}.flex-container{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex}.flex-child-auto{-webkit-box-flex:1;-webkit-flex:1 1 auto;-ms-flex:1 1 auto;flex:1 1 auto}.flex-child-grow{-webkit-box-flex:1;-webkit-flex:1 0 auto;-ms-flex:1 0 auto;flex:1 0 auto}.flex-child-shrink{-webkit-box-flex:0;-webkit-flex:0 1 auto;-ms-flex:0 1 auto;flex:0 1 auto}.flex-dir-row{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row}.flex-dir-row-reverse{-webkit-box-orient:horizontal;-webkit-box-direction:reverse;-webkit-flex-direction:row-reverse;-ms-flex-direction:row-reverse;flex-direction:row-reverse}.flex-dir-column{-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column}.flex-dir-column-reverse{-webkit-box-orient:vertical;-webkit-box-direction:reverse;-webkit-flex-direction:column-reverse;-ms-flex-direction:column-reverse;flex-direction:column-reverse}@media print,screen and (min-width:40em){.medium-flex-container{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex}.medium-flex-child-auto{-webkit-box-flex:1;-webkit-flex:1 1 auto;-ms-flex:1 1 auto;flex:1 1 auto}.medium-flex-child-grow{-webkit-box-flex:1;-webkit-flex:1 0 auto;-ms-flex:1 0 auto;flex:1 0 auto}.medium-flex-child-shrink{-webkit-box-flex:0;-webkit-flex:0 1 auto;-ms-flex:0 1 auto;flex:0 1 auto}.medium-flex-dir-row{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row}.medium-flex-dir-row-reverse{-webkit-box-orient:horizontal;-webkit-box-direction:reverse;-webkit-flex-direction:row-reverse;-ms-flex-direction:row-reverse;flex-direction:row-reverse}.medium-flex-dir-column{-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column}.medium-flex-dir-column-reverse{-webkit-box-orient:vertical;-webkit-box-direction:reverse;-webkit-flex-direction:column-reverse;-ms-flex-direction:column-reverse;flex-direction:column-reverse}}@media print,screen and (min-width:64em){.large-flex-container{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex}.large-flex-child-auto{-webkit-box-flex:1;-webkit-flex:1 1 auto;-ms-flex:1 1 auto;flex:1 1 auto}.large-flex-child-grow{-webkit-box-flex:1;-webkit-flex:1 0 auto;-ms-flex:1 0 auto;flex:1 0 auto}.large-flex-child-shrink{-webkit-box-flex:0;-webkit-flex:0 1 auto;-ms-flex:0 1 auto;flex:0 1 auto}.large-flex-dir-row{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row}.large-flex-dir-row-reverse{-webkit-box-orient:horizontal;-webkit-box-direction:reverse;-webkit-flex-direction:row-reverse;-ms-flex-direction:row-reverse;flex-direction:row-reverse}.large-flex-dir-column{-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column}.large-flex-dir-column-reverse{-webkit-box-orient:vertical;-webkit-box-direction:reverse;-webkit-flex-direction:column-reverse;-ms-flex-direction:column-reverse;flex-direction:column-reverse}}.hide{display:none!important}.invisible{visibility:hidden}.visible{visibility:visible}@media print,screen and (max-width:39.99875em){.hide-for-small-only{display:none!important}}@media screen and (max-width:0em),screen and (min-width:40em){.show-for-small-only{display:none!important}}@media print,screen and (min-width:40em){.hide-for-medium{display:none!important}}@media screen and (max-width:39.99875em){.show-for-medium{display:none!important}}@media print,screen and (min-width:40em)and (max-width:63.99875em){.hide-for-medium-only{display:none!important}}@media screen and (max-width:39.99875em),screen and (min-width:64em){.show-for-medium-only{display:none!important}}@media print,screen and (min-width:64em){.hide-for-large{display:none!important}}@media screen and (max-width:63.99875em){.show-for-large{display:none!important}}@media print,screen and (min-width:64em)and (max-width:74.99875em){.hide-for-large-only{display:none!important}}@media screen and (max-width:63.99875em),screen and (min-width:75em){.show-for-large-only{display:none!important}}.show-for-sr,.show-on-focus{clip:rect(0,0,0,0)!important;border:0!important;height:1px!important;overflow:hidden!important;padding:0!important;position:absolute!important;white-space:nowrap!important;width:1px!important}.show-on-focus:active,.show-on-focus:focus{clip:auto!important;height:auto!important;overflow:visible!important;position:static!important;white-space:normal!important;width:auto!important}.hide-for-portrait,.show-for-landscape{display:block!important}@media screen and (orientation:landscape){.hide-for-portrait,.show-for-landscape{display:block!important}}@media screen and (orientation:portrait){.hide-for-portrait,.show-for-landscape{display:none!important}}.hide-for-landscape,.show-for-portrait{display:none!important}@media screen and (orientation:landscape){.hide-for-landscape,.show-for-portrait{display:none!important}}@media screen and (orientation:portrait){.hide-for-landscape,.show-for-portrait{display:block!important}}.show-for-dark-mode{display:none}.hide-for-dark-mode{display:block}@media screen and (prefers-color-scheme:dark){.show-for-dark-mode{display:block!important}.hide-for-dark-mode{display:none!important}}.show-for-ie{display:none}@media (-ms-high-contrast:active),(-ms-high-contrast:none){.show-for-ie{display:block!important}.hide-for-ie{display:none!important}}.show-for-sticky{display:none}.is-stuck .show-for-sticky{display:block}.is-stuck .hide-for-sticky{display:none}@font-face{font-display:"swap";font-family:FontAwesome}html{box-sizing:border-box}body{font-family:Roboto,sans-serif;font-size:16px;line-height:1}*,:after,:before{box-sizing:inherit}a{color:#3c4fe0}a.reference:after{font-family:FontAwesome;font-size:12px;padding:0 4px}a.reference.external:after{content:""}a.reference.download:after{content:""}a:hover{color:#3c4fe0;font-weight:500}.headerlink{margin-left:5px;visibility:hidden}.toc-backref:hover{color:#23263b}h1,h2,h3,h4,h5,h6{font-family:Roboto,sans-serif;font-size:16px;font-weight:500;letter-spacing:.2px;line-height:24px;margin-bottom:16px}h1:hover>a.headerlink,h2:hover>a.headerlink,h3:hover>a.headerlink,h4:hover>a.headerlink,h5:hover>a.headerlink,h6:hover>a.headerlink{visibility:visible}h1 a,h2 a,h3 a,h4 a,h5 a,h6 a{color:inherit}h1{font-size:32px;font-weight:700;line-height:40px;margin-bottom:28px}h2{font-size:24px;line-height:32px}h3{font-size:20px}h4{font-size:18px}h5{font-size:16px}h6{font-weight:400}img{max-width:100%}button:focus{outline:0}blockquote{border:0;margin:0;padding:0}blockquote,blockquote p,cite{color:inherit}cite{display:inline;font-size:inherit}cite:before{content:""}.show{display:block!important}.centered{display:block;margin:0 auto}.break{flex-basis:100%;height:0}@media screen and (min-width:1024px){h1{font-size:36px}}.admonition-title:before,.contents.local>ul>li a:before,.scylla-icon,.secondary-side-nav__content li a:before{background-repeat:no-repeat;background-size:contain;display:inline-block;filter:brightness(0);vertical-align:middle}.scylla-icon--about-team{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMSwuY2xzLTJ7ZmlsbDpub25lO3N0cm9rZTpncmF5O3N0cm9rZS1taXRlcmxpbWl0OjEwfS5jbHMtMntzdHJva2UtbGluZWNhcDpyb3VuZH08L3N0eWxlPjwvZGVmcz48ZyBpZD0iQ2FscXVlXzQiIGRhdGEtbmFtZT0iQ2FscXVlIDQiPjxwYXRoIGNsYXNzPSJjbHMtMSIgZD0iTTQuNjYgOS44MSAyLjYzIDExYTIuMDggMi4wOCAwIDAgMC0xLjEzIDEuODN2Ny44MWMuMTkgMS4xMS41IDEuNTMgMS41IDEuNDdNNy4wNiA5Ljk0bDEuNDQuOTQiLz48cGF0aCBjbGFzcz0iY2xzLTIiIGQ9Ik0zLjUgMTguNXY1LjM0TTkuNSAxOC41djUuMzRNOC41NCAxOC40MnY1LjMzTTE1LjUgMTguNXY1LjM0TTE2LjUgMTguNXY1LjM0TTMuMzMgMjAuNTNoNS4wOE0xMS40NSA4Ljg0bC4wNi4wNmExLjY1IDEuNjUgMCAwIDAgMi4zNCAwaDAiLz48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Ik0xMi40MiA3LjVhMS44MSAxLjgxIDAgMCAxLTEuOTItMS43N1Y1YTEuOTQgMS45NCAwIDAgMSAxLjkyLTIgMi4wNyAyLjA3IDAgMCAxIDIuMDggMnYuNzdhMiAyIDAgMCAxLTIuMDggMS43M1pNMTEuNDIgOC43NCA5LjYzIDkuOWEyLjA3IDIuMDcgMCAwIDAtMS4xMyAxLjg1djcuODJBMS40NyAxLjQ3IDAgMCAwIDEwIDIxTTEzLjc1IDkuMThsMiAuNjVjLjcuMzUuNzYgMS4wNi43NiAxLjg0djcuOWMwIC43Ny0uMjMgMS4yNC0xIDEuMjQiLz48cGF0aCBjbGFzcz0iY2xzLTIiIGQ9Ik05LjkzIDE5LjVoNS40Ii8+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNMTkuNDIgOS4xMmEyLjA3IDIuMDcgMCAwIDAgMi4wOC0xLjkzdi0uNzdhMi4wNyAyLjA3IDAgMCAwLTIuMDgtMS45MiAxLjkzIDEuOTMgMCAwIDAtMS45MiAxLjkydi43N2ExLjk0IDEuOTQgMCAwIDAgMS45MiAxLjkzWk01LjU5IDkuMTJhMS45MyAxLjkzIDAgMCAwIDEuOTItMS45M3YtLjc3QTEuOTMgMS45MyAwIDAgMCA1LjU5IDQuNSAyLjA4IDIuMDggMCAwIDAgMy41IDYuNDJ2Ljc3YTIuMDggMi4wOCAwIDAgMCAyLjA5IDEuOTNaTTIwLjQ0IDkuODFsMiAxLjE3YTIuMDYgMi4wNiAwIDAgMSAxLjEzIDEuODV2Ny44MWMtLjE4IDEuMTEtLjQ3IDEuNTMtMS40NyAxLjQ3TTE4LjA0IDkuOTRsLTEuNDQuOTMiLz48cGF0aCBjbGFzcz0iY2xzLTIiIGQ9Ik0yMS42IDE4LjV2NS4zNE0yMS43NyAyMC41M2gtNS4wOCIvPjwvZz48L3N2Zz4=)}.scylla-icon--about-us{background-image:url(data:image/svg+xml;base64,PHN2ZyBpZD0iTGF5ZXJfMyIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB2aWV3Qm94PSIwIDAgMjAgMjAiPjxkZWZzPjxzdHlsZT4uY2xzLTF7ZmlsbDpub25lO3N0cm9rZTojMDAwO3N0cm9rZS1saW5lY2FwOnJvdW5kO3N0cm9rZS1saW5lam9pbjpyb3VuZDtzdHJva2Utd2lkdGg6LjhweH08L3N0eWxlPjwvZGVmcz48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Ik02LjI4IDE5LjQ4Yy0uMTIuMDgtLjA4LjA3LS4yMy4xLS41OC4wOS0xLjEyLS4yOC0xLjI1LS44NCAwIDAtMi4zLTkuMTgtMi4zLTExLjExQzIuNSAzLjYgNS44OC40NCAxMC4zOC40NFMxNy41IDMuNDggMTcuNSA3LjVjMCAxLjkzLTEuMzIgMTEuMjMtMS4zMiAxMS4yMy0uMTMuNTYtLjY3Ljk0LTEuMjUuODQtLjEyLS4wMi0uMTMgMC0uMjMtLjA3Ii8+PHBhdGggZD0iTTE1Ljc1IDE1Ljc1Yy0uMTcgMS4xNS0uMjIgMi4zNC0uNTUgMy40Ni0uMzcuODUtMS42MyAxLjA2LTIuMjIuMzMtLjI1LS4yOC4xOS0uNjguNDQtLjQuNDMuNDYgMS4yNC4xOCAxLjMxLS40NGwuMDYtLjM0Yy4xOS0uODkuMzUtMS43OS41Ny0yLjY4LjA1LS4yNC40Mi0uMTcuMzkuMDdaIi8+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNMTEuNSA3YzAgMS45LTEuNTYgMy41LTMuNDYgMy41UzQuNSA4LjkgNC41IDdzMS42NC0zLjUgMy41NC0zLjVTMTEuNSA1LjEgMTEuNSA3WiIvPjxwYXRoIGQ9Ik04LjU1IDQuNzVjLS41OS4xMi0uNzEgMS40Mi0uMzYgMS43OC4yMy4yMy43MS4zMS43MS40N3MtLjQ4LjI0LS43MS40N2MtLjM2LjM2LS4yNCAxLjY2LjM2IDEuNzguNzEuMTQgMS43OC0uNzEgMS43OC0yLjI1UzkuMjYgNC42MSA4LjU1IDQuNzVaTTYuNTEgMTIuMmMyLjEyLjMxIDQuMzQtLjIgNS42OC0xLjk2LjMyLS40MS45Ni4xMS42Mi41MS0uNzYuOS0xLjc4IDEuNjMtMi45MyAxLjk1LTEuMTQuMzMtMi4zMy4zMS0zLjQ2LjE2YS4zNC4zNCAwIDAgMS0uMjktLjM4Yy4wMi0uMTguMTktLjMxLjM3LS4yOVpNNy45NyAxOS41OWMtLjk5Ljk2LTIuMzYuMDgtMi4zNi0xLjE1LS4xMi0uOS0uMjctMS43OS0uMzctMi42OS0uMDEtLjExLjA3LS4yMS4xOC0uMjIuMS0uMDEuMTkuMDYuMjEuMTUuMjIuODguMzggMS43Ny41NiAyLjY2LjAxLjc4LjY4IDEuMzggMS4zNS44My4yNy0uMjcuNjkuMTYuNDIuNDNaIi8+PHBhdGggZD0iTTkuNzUgMTkuMjdjLS40Mi45LTEuOC45Ni0yLjMyLjExLS41LTEuMTMtLjMxLTIuNS0uNDctMy43MiAwLS4xMS4wOC0uMi4xOS0uMjEuMSAwIC4xOS4wNy4yMS4xNy4xNy45NS4yOCAxLjkxLjQyIDIuODcuMDEuNDUuMjMuNzQuNTcuODUuMzMuMS43MS0uMDUuODgtLjM2LjE4LS4zNC43MS0uMDUuNTIuMjlaTTE0LjAzIDE1LjY2Yy0uMTYgMS4yMy4wMyAyLjU3LS40NiAzLjcyLS41Mi44Ni0xLjkxLjc5LTIuMzItLjExLS4xNy0uMzQuMzUtLjYxLjUzLS4yOC40Mi43MSAxLjQ4LjM4IDEuNDUtLjQ5LjE0LS45Ni4yNS0xLjkyLjQyLTIuODcuMDQtLjI0LjQxLS4yLjQuMDRaIi8+PHBhdGggZD0iTTExLjg1IDE1LjU0Yy4wMi43OS4wMSAxLjU4LjAxIDIuMzctLjAyLjQxLjA3LjktLjE0IDEuMjktLjQzIDEuMDItMi4wMSAxLjAyLTIuNDUgMC0uMjEtLjM5LS4xMy0uODktLjE0LTEuMjkgMC0uNzkgMC0xLjU4LjAxLTIuMzcgMC0uMTEuMS0uMi4yMS0uMTkuMSAwIC4xOC4wOC4xOS4xOC4wNy43OS4xIDEuNTguMTUgMi4zNy4wMy4yNyAwIC44Mi4xMyAxLjA0LjEzLjI2LjQuNDMuNjguNDIuNDYgMCAuNzktLjQuNzctLjg3bC4wMy0uNTljLjA0LS43OS4wOC0xLjU4LjE1LTIuMzcuMDItLjI0LjQtLjIzLjQuMDFaIi8+PC9zdmc+)}.scylla-icon--about-us-m{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNi4zOCAzMi40MyI+PHBhdGggZD0iTTYuNTUgMzEuNjRjLS4yLjEzLS40My4yMi0uNjkuMjZhMS44MSAxLjgxIDAgMCAxLTIuMDYtMS4zOVMuNDkgMTQuOTkuNDkgMTEuODJDLjUgNS4xOSA1Ljc3LjUgMTMuMTkuNXMxMi42OSA0LjY5IDEyLjY5IDExLjMyYzAgMy4xOC0zLjMxIDE4LjY5LTMuMzEgMTguNjlhMS44MSAxLjgxIDAgMCAxLTIuNjIgMS4yIiBzdHlsZT0iZmlsbDpub25lO3N0cm9rZTojMDAwO3N0cm9rZS1saW5lY2FwOnJvdW5kO3N0cm9rZS1saW5lam9pbjpyb3VuZCIvPjxwYXRoIGQ9Ik0yMS44NiAyNS4zNmMtLjI4IDEuOS0uMzcgMy44Ni0uOTEgNS43MS0uNjEgMS40MS0yLjY4IDEuNzUtMy42Ni41NS0uNDEtLjQ3LjMxLTEuMTEuNzMtLjY2LjcxLjc2IDIuMDQuMjkgMi4xNi0uNzMuMzItMS42Ni42NS0zLjMzIDEuMDQtNC45OC4wOS0uMzkuNy0uMjguNjUuMTFaIi8+PHBhdGggZD0iTTE0LjggMTAuNTdjMCAzLjEzLTIuNTMgNS42Ni01LjY2IDUuNjZzLTUuNDctMi41My01LjQ3LTUuNjYgMi4zNC01LjY2IDUuNDctNS42NiA1LjY2IDIuNTMgNS42NiA1LjY2WiIgc3R5bGU9InN0cm9rZS13aWR0aDouOXB4O2ZpbGw6bm9uZTtzdHJva2U6IzAwMDtzdHJva2UtbGluZWNhcDpyb3VuZDtzdHJva2UtbGluZWpvaW46cm91bmQiLz48cGF0aCBkPSJNMTAuMzEgNi44NmMtLjk4LjItMS4xNyAyLjM0LS41OSAyLjkzLjM4LjM4IDEuMTcuNTEgMS4xNy43OHMtLjc5LjQtMS4xNy43OGMtLjU5LjU5LS4zOSAyLjczLjU5IDIuOTMgMS4xNi4yMyAyLjkzLTEuMTcgMi45My0zLjcxcy0xLjc2LTMuOTQtMi45My0zLjcxWk02LjgyIDE4LjUxYzMuNDkuODkgNi45Ny0uNSA5LjUxLTIuOTMuNDctLjQ0IDEuMTYuMzEuNjguNzQtMS4zOCAxLjIzLTIuOTggMi4yOS00Ljc5IDIuODctMS44LjU5LTMuNzcuNTgtNS41OC4xNGEuNDIxLjQyMSAwIDAgMS0uMzEtLjVjLjA1LS4yMi4yOC0uMzYuNS0uMzFaIi8+PHBhdGggZD0iTTE2LjczIDE2LjY3Yy0uMTItLjQ2LS41MS0uODMtLjk5LS44My0uNzUtLjAyLS41OS0xLjE3LjE0LS45OS44MS4xNiAxLjQzLjg1IDEuNSAxLjY2LjA4LjQtLjU0LjU0LS42NS4xNVpNOS4wMyAzMS43Yy0xLjI2IDEuMzYtMy42Mi40NS0zLjgtMS4zNWwtLjA5LS41NWMtLjIxLTEuNDgtLjQ1LTIuOTUtLjYtNC40NC0uMDItLjE4LjExLS4zNC4yOS0uMzYuMTctLjAyLjMyLjA5LjM1LjI1LjM5IDEuNjMuNzEgMy4yOCAxLjAzIDQuOTMuMDkgMS4wMiAxLjM4IDEuNTQgMi4xMi44MS40NS0uNDQgMS4xNC4yNi42OS43WiIvPjxwYXRoIGQ9Ik0xMS45NiAzMS4xNmMtMSAxLjk4LTQuMDQgMS4zLTQuMjEtLjg4LS4xNS0xLjY5LS4zLTMuMzgtLjM5LTUuMDcgMC0uMTguMTMtLjM0LjMxLS4zNC4xNyAwIC4zMS4xMS4zNC4yNy4yOCAxLjY3LjUgMy4zNS43MiA1LjAzLjA5IDEuMiAxLjc3IDEuNTkgMi4zNi41MS4zMS0uNTYgMS4xNi0uMDkuODcuNDdaTTE5LjAzIDI1LjIxYy0uMDggMS42OS0uMjQgMy4zOC0uMzkgNS4wNy0uMDQuMzctLjE3Ljc1LS4zOCAxLjA2LS44NiAxLjQtMy4xMSAxLjMxLTMuODMtLjE3LS4zLS41Ni41NS0xLjAzLjg2LS40OC41OSAxLjA4IDIuMjcuNjkgMi4zNS0uNTIuMjItMS42OC40My0zLjM2LjcyLTUuMDMuMDYtLjQuNjgtLjMzLjY1LjA3WiIvPjxwYXRoIGQ9Ik0xNS40MyAyNS4wMmMuMDQgMS4zMS4wMiAyLjYxLjAyIDMuOTEtLjAzLjY3LjExIDEuNDgtLjIzIDIuMTMtLjc0IDEuNjktMy4yOSAxLjY5LTQuMDMgMC0uMzQtLjY1LS4yMS0xLjQ3LS4yNC0yLjEzIDAtMS4zLS4wMi0yLjYxLjAyLTMuOTEgMC0uMTguMTYtLjMyLjM0LS4zMi4xNyAwIC4zLjE0LjMyLjMuMTEgMS4zLjE3IDIuNi4yNCAzLjkxLjA1LjQ1IDAgMS4zNS4yMSAxLjcyLjIxLjQzLjY2LjcxIDEuMTIuNy40Ni4wMi45MS0uMjcgMS4xMi0uNjkuMjItLjM2LjE2LTEuMjguMjEtMS43Mi4wNy0xLjMuMTMtMi42MS4yNC0zLjkxLjAyLS40LjY2LS4zOC42Ni4wMloiLz48L3N2Zz4=)}.scylla-icon--alternator{background-image:url(data:image/svg+xml;base64,PHN2ZyBpZD0iTGF5ZXJfMyIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB2aWV3Qm94PSIwIDAgMjAgMjAiPjxkZWZzPjxzdHlsZT4uY2xzLTF7ZmlsbDpub25lO3N0cm9rZTojMDAwO3N0cm9rZS1saW5lY2FwOnJvdW5kO3N0cm9rZS1saW5lam9pbjpyb3VuZH08L3N0eWxlPjwvZGVmcz48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Ik0xNy41IDIuOTFjMCAxLjI4LTMuNjcgMi41OS04IDIuNTlzLTgtMS4zMS04LTIuNTlTNS4wOS41IDkuNDIuNXM4LjA4IDEuMTMgOC4wOCAyLjQxWk0xNy41IDcuNjZjMCAxLjI4LTMuNjMgMi44LTcuOTYgMi44UzEuNSA4LjkzIDEuNSA3LjY2TTE3LjUgMTIuNDdjMCAxLjI4LTMuNjcgMy4wMy04IDMuMDNzLTgtMS43NS04LTMuMDNNMTcuNSAxNy4yOWMwIDEuMjgtMy43NSAyLjMtOC4wOCAyLjNzLTcuOTItMS4wMy03LjkyLTIuM00xLjUgMTcuMTlWMi45MU0xNy41IDE3LjE5VjIuOTEiLz48L3N2Zz4=)}.scylla-icon--apps{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyMSAxOSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOm5vbmU7c3Ryb2tlOiM0ZDRkNGQ7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJDYWxxdWVfNCIgZGF0YS1uYW1lPSJDYWxxdWUgNCI+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNLjUgMS41aDIwdjE0SC41ek03LjUgMTUuNzR2Mi44OU0xMi44MyAxNS42M3YyLjMyTTUuNSAxOC41aDkuMTQiLz48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Im0zLjY0IDUuNTYgNC41OCAyLjkxLTQuNTggMi45Mk05LjEgMTIuMDhoNC4zMiIvPjwvZz48L3N2Zz4=)}.scylla-icon--architecture{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMSwuY2xzLTIsLmNscy01e2ZpbGw6bm9uZTtzdHJva2U6Z3JheX0uY2xzLTF7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfS5jbHMtMiwuY2xzLTV7c3Ryb2tlLW1pdGVybGltaXQ6MTB9LmNscy0ye3N0cm9rZS13aWR0aDouOThweH0uY2xzLTV7c3Ryb2tlLXdpZHRoOi45OXB4fTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJDYWxxdWVfMiIgZGF0YS1uYW1lPSJDYWxxdWUgMiI+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNMS45IDEwLjI3YTEwLjgzIDEwLjgzIDAgMCAxIDguNzMtOC4zOE0xMC41MSAyMy4wOEExMC43OSAxMC43OSAwIDAgMSAxLjc3IDE0TTIzLjIzIDE0YTEwLjgxIDEwLjgxIDAgMCAxLTkgOS4xMU0xNC4yNyAxLjg4YTEwLjgxIDEwLjgxIDAgMCAxIDguODMgOC4zNyIvPjxjaXJjbGUgY2xhc3M9ImNscy0yIiBjeD0iMTIuMjUiIGN5PSIxLjc1IiByPSIxLjc1Ii8+PGNpcmNsZSBjbGFzcz0iY2xzLTIiIGN4PSIxMi4yNSIgY3k9IjIyLjc1IiByPSIxLjc1Ii8+PGNpcmNsZSBjeD0iNC45MiIgY3k9IjQuNzUiIHI9IjEuNzUiIHN0eWxlPSJzdHJva2Utd2lkdGg6Ljk5cHg7ZmlsbDpncmF5O3N0cm9rZS1taXRlcmxpbWl0OjEwO3N0cm9rZTpncmF5Ii8+PGNpcmNsZSBjeD0iMjAuMDkiIGN5PSIxOS45MSIgcj0iMS43NSIgc3R5bGU9InN0cm9rZS13aWR0aDouOTlweDtmaWxsOmdyYXk7c3Ryb2tlLW1pdGVybGltaXQ6MTA7c3Ryb2tlOmdyYXkiLz48Y2lyY2xlIGNsYXNzPSJjbHMtNSIgY3g9IjEuNzUiIGN5PSIxMi4yNSIgcj0iMS43NSIvPjxjaXJjbGUgY2xhc3M9ImNscy01IiBjeD0iMjMuMjUiIGN5PSIxMi4yNSIgcj0iMS43NSIvPjxjaXJjbGUgY3g9IjQuNzUiIGN5PSIxOS42NCIgcj0iMS43NSIgc3R5bGU9InN0cm9rZS13aWR0aDouOTlweDtmaWxsOmdyYXk7c3Ryb2tlLW1pdGVybGltaXQ6MTA7c3Ryb2tlOmdyYXkiLz48Y2lyY2xlIGN4PSIxOS45MSIgY3k9IjQuNDgiIHI9IjEuNzUiIHN0eWxlPSJzdHJva2Utd2lkdGg6Ljk5cHg7ZmlsbDpncmF5O3N0cm9rZS1taXRlcmxpbWl0OjEwO3N0cm9rZTpncmF5Ii8+PC9nPjwvc3ZnPg==)}.scylla-icon--benchmarks{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVqb2luOnJvdW5kO3N0cm9rZS13aWR0aDozcHh9PC9zdHlsZT48L2RlZnM+PGcgaWQ9IkNhbHF1ZV8yIiBkYXRhLW5hbWU9IkNhbHF1ZSAyIj48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Ik01LjUxIDI0Ljkxdi01Ljg1TTEyLjU3IDI0Ljkxdi05Ljc0TTE5LjYyIDI0LjkxVjEwLjE1Ii8+PHBhdGggc3R5bGU9InN0cm9rZS1saW5lY2FwOnJvdW5kO2ZpbGw6bm9uZTtzdHJva2U6Z3JheTtzdHJva2UtbGluZWpvaW46cm91bmQiIGQ9Im0uOTEgMTQuOTggNS4xMy03Ljk0IDYuMjUgNS44OEwyNCAxIi8+PHBhdGggc3R5bGU9ImZpbGw6Z3JheSIgZD0ibTI1IDUtNS01aDV2NXoiLz48L2c+PC9zdmc+)}.scylla-icon--blog{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJDYWxxdWVfNCIgZGF0YS1uYW1lPSJDYWxxdWUgNCI+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJtOSAxNS0yLjUtMS41IDgtMTJMMTcgMyA5IDE1eiIvPjxwYXRoIHN0eWxlPSJmaWxsOmdyYXk7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kIiBkPSJtNi41IDEzLjUtLjUgM0w5IDE1bC0yLjUtMS41eiIvPjxwYXRoIGNsYXNzPSJjbHMtMSIgZD0iTTE5LjI1IDIuNWg0LjI1djE2aC0xM3Y0LjE3TDYuNDYgMTguNWwtNC45Ni0uMDRWMi41aDguMzFNMTQuNSAyLjVsMS42NyAxLjMzIi8+PC9nPjwvc3ZnPg==)}.scylla-icon--careers{background-image:url(data:image/svg+xml;base64,PHN2ZyBpZD0iQ2FscXVlXzEiIGRhdGEtbmFtZT0iQ2FscXVlIDEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmlld0JveD0iMCAwIDI1IDI1Ij48ZGVmcz48c3R5bGU+LmNscy0xe2ZpbGw6bm9uZTtzdHJva2U6Z3JheTtzdHJva2UtbGluZWNhcDpyb3VuZDtzdHJva2UtbGluZWpvaW46cm91bmR9PC9zdHlsZT48L2RlZnM+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNMS41IDExLjU1djhjMCAuNTYgMS4wNyAyIDIgMmgxOGMuODkgMCAyLTEuNDQgMi0ydi04Ii8+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNMjMuMzEgMy41SDEuODFjLS40OCAwLTEuMzEuNTUtMS4zMSAxdjZsMTAgMmE4LjQ1IDguNDUgMCAwIDAgNCAwbDEwLTJ2LTZjMC0uNDUtLjcyLTEtMS4xOS0xWk0xNS42MiAzLjV2LTFjMC0uNzYtLjYxLTEtMS4zOC0xaC0zLjQ1Yy0uNzYgMC0xLjM4LjI0LTEuMzggMXYxIi8+PHJlY3QgeD0iMTAiIHk9IjExIiB3aWR0aD0iNSIgaGVpZ2h0PSIzLjk5IiByeD0iLjU1IiByeT0iLjU1IiBzdHlsZT0iZmlsbDpncmF5Ii8+PC9zdmc+)}.scylla-icon--chevron-left{background-image:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTAiIGhlaWdodD0iMTYiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZD0iTTguMDkyIDE2IDEwIDE0LjExMyAzLjgxNyA4IDEwIDEuODg3IDguMDkyIDAgMCA4bDguMDkyIDhaIiBmaWxsPSIjMDAwIi8+PC9zdmc+)}.contents.local>ul>li a:before,.scylla-icon--chevron-right,.secondary-side-nav__content li a:before{background-image:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTAiIGhlaWdodD0iMTYiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZD0iTTEuOTA4IDAgMCAxLjg4NyA2LjE4MyA4IDAgMTQuMTEzIDEuOTA4IDE2IDEwIDggMS45MDggMFoiIGZpbGw9IiMwMDAiLz48L3N2Zz4=)}.scylla-icon--circe{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAzOCAzMCI+PGRlZnM+PHN0eWxlPi5jbHMtMiwuY2xzLTN7ZmlsbDpub25lO3N0cm9rZTojNGQ0ZDRkO3N0cm9rZS1saW5lY2FwOnJvdW5kO3N0cm9rZS1saW5lam9pbjpyb3VuZH0uY2xzLTN7c3Ryb2tlLXdpZHRoOjEuMTFweH08L3N0eWxlPjwvZGVmcz48ZyBpZD0iQ2FscXVlXzQiIGRhdGEtbmFtZT0iQ2FscXVlIDQiPjxwYXRoIGQ9Ik0yMi4xIDEyaC02LjE2YTEuMDYgMS4wNiAwIDAgMS0uOTQtMS4wNy45My45MyAwIDAgMSAuOTQtLjkzaDYuMTZhLjkzLjkzIDAgMCAxIC45NC45M0ExLjA2IDEuMDYgMCAwIDEgMjIuMSAxMloiIHN0eWxlPSJmaWxsOiM0ZDRkNGQiLz48cGF0aCBjbGFzcz0iY2xzLTIiIGQ9Ik0xMy40NCA0LjQ5SDkuNTF2MjRoMTl2LTI0SDI0LjUiLz48cGF0aCBjbGFzcz0iY2xzLTMiIGQ9Ik0xMyAzLjQ5SDguNWwtLjA4IDI2LjFIMjkuNVYzLjM5SDI1Ii8+PHBhdGggY2xhc3M9ImNscy0yIiBkPSJNMTIuNSAxOC4zOGgxM00xMi41IDE1LjQ5aDEzTTEyLjUgMjEuNDNoMTNNMTIuNSAyNC40N2gxM00xMy41IDIuNWgxMXYzLjk4aC0xMXoiLz48cGF0aCBjbGFzcz0iY2xzLTMiIGQ9Ik0yMS41LjVoLTUuMDR2MS45NWw1LjA0LjA1di0yeiIvPjwvZz48L3N2Zz4=)}.scylla-icon--clock{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyMSAxOSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOm5vbmU7c3Ryb2tlOiM0ZDRkNGQ7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJDYWxxdWVfNCIgZGF0YS1uYW1lPSJDYWxxdWUgNCI+PGNpcmNsZSBjbGFzcz0iY2xzLTEiIGN4PSIxMC41IiBjeT0iOS41IiByPSI5Ii8+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNMTAuNSAzLjV2NmwzLjA2IDMiLz48L2c+PC9zdmc+)}.scylla-icon--close{background-image:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMzQiIGhlaWdodD0iMzQiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGcgY2xpcC1wYXRoPSJ1cmwoI2EpIiBmaWxsPSIjZmZmIj48cGF0aCBkPSJNMTEuNjcgMjIuMTNhLjU2NC41NjQgMCAwIDEtLjM5OC0uOTYybDkuODk2LTkuODk2YS41NjMuNTYzIDAgMSAxIC43OTcuNzk3bC05Ljg5NiA5Ljg5NmEuNTU5LjU1OSAwIDAgMS0uMzk5LjE2NVoiLz48cGF0aCBkPSJNMjEuNTY2IDIyLjEzYS41NTkuNTU5IDAgMCAxLS4zOTgtLjE2NWwtOS44OTYtOS44OTZhLjU2My41NjMgMCAxIDEgLjc5Ny0uNzk3bDkuODk2IDkuODk1YS41NjQuNTY0IDAgMCAxLS4zOTkuOTYzWiIvPjxwYXRoIGQ9Ik0xNi42MTkgMzMuMjM3QzcuNDU1IDMzLjIzNyAwIDI1Ljc4MiAwIDE2LjYxOSAwIDcuNDU2IDcuNDU1IDAgMTYuNjE5IDBzMTYuNjE5IDcuNDU1IDE2LjYxOSAxNi42MTktNy40NTYgMTYuNjE4LTE2LjYyIDE2LjYxOFptMC0zMi4xMWMtOC41NDIgMC0xNS40OTIgNi45NS0xNS40OTIgMTUuNDkyIDAgOC41NDIgNi45NSAxNS40OTIgMTUuNDkyIDE1LjQ5MiA4LjU0MiAwIDE1LjQ5Mi02Ljk1IDE1LjQ5Mi0xNS40OTIgMC04LjU0Mi02Ljk1LTE1LjQ5Mi0xNS40OTItMTUuNDkyWiIvPjwvZz48ZGVmcz48Y2xpcFBhdGggaWQ9ImEiPjxwYXRoIGZpbGw9IiNmZmYiIGQ9Ik0wIDBoMzMuMjM3djMzLjIzN0gweiIvPjwvY2xpcFBhdGg+PC9kZWZzPjwvc3ZnPg==)}.scylla-icon--cloud{background-image:url(data:image/svg+xml;base64,PHN2ZyBpZD0iTGF5ZXJfMiIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB2aWV3Qm94PSIwIDAgNDMuMDQgMzIuMDMiPjxkZWZzPjxzdHlsZT4uY2xzLTF7ZmlsbDpub25lO3N0cm9rZTojMWQxZDFiO3N0cm9rZS1saW5lY2FwOnJvdW5kO3N0cm9rZS1saW5lam9pbjpyb3VuZH08L3N0eWxlPjwvZGVmcz48ZyBpZD0iTGF5ZXJfMyI+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNNDIuNTQgNC4wNmMwIDEuNjgtMy42MyAyLjQ0LTkgMi40NHMtMTAtLjczLTEwLTIuNFMyNy42Ny41IDMzLjA0LjVzOS41IDEuODkgOS41IDMuNTZaTTQyLjU0IDkuNjNjMCAxLjY4LTMuNzYgMi45MS05LjEyIDIuOTFzLTkuODQtMS4yMy05Ljg0LTIuOTFNNDIuNTQgMTUuMzRjMCAxLjY4LTMuNjggMy4yNS05LjA0IDMuMjUtNCAwLTcuNi0uOTYtOS4wOS0yLjA0TTQyLjU0IDIwLjY1YzAgMS42OC0zLjcyIDIuOTctOS4wOCAyLjk3TTIzLjU0IDE1LjQ2VjQuMU00Mi41NCAyMC43N1Y0LjEiLz48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Ik0yOC4xMSAyMS4wOGMtLjg3IDAtMS42Ny4yMy0yLjM5LjYxIDAtLjA3LjAxLS4xNC4wMS0uMjEgMC00Ljg1LTMuODMtOC45LTguNjgtOC45cy04Ljg4IDQuMDUtOC44OCA4LjljMCAuMTcuMDIuMzQuMDMuNTEtLjg0LS41Ny0xLjg1LS45MS0yLjk1LS45MS0yLjg4IDAtNC43NCAyLjU3LTQuNzQgNS40NnMxLjg2IDQuOTkgNC43NCA0Ljk5aDIyLjg2YzIuODggMCA1LjUyLTIuMjcgNS41Mi01LjE2cy0yLjYzLTUuMjktNS41Mi01LjI5WiIvPjwvZz48L3N2Zz4=)}.scylla-icon--cloud-docs{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyMSAxOSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOm5vbmU7c3Ryb2tlOiM0ZDRkNGQ7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJDYWxxdWVfNCIgZGF0YS1uYW1lPSJDYWxxdWUgNCI+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNNi41IDExLjVoOHYxaC04ek0xNS42NSA2LjU1YTMuNDIgMy40MiAwIDAgMC0zLjE1IDIiLz48cGF0aCBkPSJNMTAuMDYgMi44QTUuMTcgNS4xNyAwIDAgMSAxNSA2LjM1aC4yNGE0Ljg0IDQuODQgMCAwIDEgMCA5LjY3aC0xMWEzLjQ1IDMuNDUgMCAwIDEgMC02LjlBMy4xNyAzLjE3IDAgMCAxIDUgOS4yIDUuMzMgNS4zMyAwIDAgMSA0Ljg2IDhhNS4yIDUuMiAwIDAgMSA1LjItNS4ybTAtLjhhNiA2IDAgMCAwLTYgNnYuMzFhNC4yNSA0LjI1IDAgMCAwIC4xOCA4LjQ5aDExYTUuNjMgNS42MyAwIDAgMCAuMy0xMS4yNkE2IDYgMCAwIDAgMTAuMDYgMloiIHN0eWxlPSJmaWxsOiM0ZDRkNGQiLz48L2c+PC9zdmc+)}.scylla-icon--comparison{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMSwuY2xzLTIsLmNscy00e2ZpbGw6bm9uZTtzdHJva2U6Z3JheX0uY2xzLTEsLmNscy0ye3N0cm9rZS1taXRlcmxpbWl0OjEwfS5jbHMtMiwuY2xzLTR7c3Ryb2tlLWxpbmVjYXA6cm91bmR9LmNscy00e3N0cm9rZS1saW5lam9pbjpyb3VuZH08L3N0eWxlPjwvZGVmcz48ZyBpZD0iQ2FscXVlXzQiIGRhdGEtbmFtZT0iQ2FscXVlIDQiPjxwYXRoIGNsYXNzPSJjbHMtMSIgZD0iTTQuNSAxMy42M3YyLjg4aDYuMDZNMjAuNSAxMy41NHYyLjk2bC01LjUuMDEiLz48cGF0aCBjbGFzcz0iY2xzLTIiIGQ9Ik0xMi41IDE4LjV2Mi43Mk03LjUgMjEuNWgxMCIvPjxjaXJjbGUgY3g9IjEyLjUiIGN5PSIxNi41IiByPSIyIiBzdHlsZT0iZmlsbDpncmF5O3N0cm9rZS13aWR0aDouOTVweDtzdHJva2UtbWl0ZXJsaW1pdDoxMDtzdHJva2U6Z3JheSIvPjxwYXRoIGNsYXNzPSJjbHMtNCIgZD0iTTUuMDYgMTMuNThIMy44OEEzLjEgMy4xIDAgMCAxIC41IDEwLjVoOGEzLjE2IDMuMTYgMCAwIDEtMy40NCAzLjA4Wk0yMSAxMy41OGgtMS4xN2EzLjA5IDMuMDkgMCAwIDEtMy4zNy0zLjA3aDhBMy4xNiAzLjE2IDAgMCAxIDIxIDEzLjU4Wk03LjQ2IDUuMTJjMCAuNTctMS4xLjQ2LTIuNzkuNDZTMS41OCA1LjYgMS41OCA1IDMgNC40IDQuNjkgNC40czIuNzcuMTYgMi43Ny43MlpNMS41IDkuODVWNS4zMU03LjUgMTAuMzVWNS44MU0yMy41IDUuMTJjMCAuNTctMS4xLjQ2LTIuNzkuNDZzLTMuMDkgMC0zLjA5LS41NFMxOSA0LjQgMjAuNzMgNC40czIuNzcuMTYgMi43Ny43MlpNMTcuNTQgOS44NVY1LjMxTTIzLjU0IDEwLjM1VjUuODEiLz48L2c+PC9zdmc+)}.scylla-icon--contact-us{background-image:url(data:image/svg+xml;base64,PHN2ZyBpZD0iQ2FscXVlXzEiIGRhdGEtbmFtZT0iQ2FscXVlIDEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmlld0JveD0iMCAwIDI1IDI1Ij48ZGVmcz48c3R5bGU+LmNscy0xe2ZpbGw6bm9uZTtzdHJva2U6Z3JheTtzdHJva2UtbGluZWNhcDpyb3VuZDtzdHJva2UtbGluZWpvaW46cm91bmQ7c3Ryb2tlLXdpZHRoOjEuMDZweH08L3N0eWxlPjwvZGVmcz48cGF0aCBjbGFzcz0iY2xzLTEiIHRyYW5zZm9ybT0icm90YXRlKC0yNy40OSAxNS41NTIgMTEuMDgzKSIgZD0iTTcuNzYgNi4wMWgxNS41OXYxMC4xM0g3Ljc2eiIvPjxwYXRoIGNsYXNzPSJjbHMtMSIgZD0ibTYuMyAxMC4xOCA4LjYzIDEuNTZhMS40MiAxLjQyIDAgMCAwIDEuNTMtLjc0bDMuNjctOE0xMS4wMiAxOS4wM2wxLjc0LTVNMjQuNTkgMTEuOTdsLTUuMDktMS40NU03LjA5IDE3LjU4IDMuOSAxOS4zNE02LjA2IDE1LjQxLjU0IDE4LjM2Ii8+PC9zdmc+)}.scylla-icon--developers-blog{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOmdyYXl9PC9zdHlsZT48L2RlZnM+PGcgaWQ9IkNhbHF1ZV80IiBkYXRhLW5hbWU9IkNhbHF1ZSA0Ij48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Im02LjQ4IDEwLjU5LS41LjE3LjUuMTZMMTEgMTIuMTZWMTRsLTctMi40OVYxMGw3LTIuNXYxLjgzWk0xNCA5LjMyVjcuNWw3IDIuNXYxLjU0TDE0IDE0di0xLjgzbDQuMTQtMS4zLjQ0LS4xMy0uNDMtLjE0WiIvPjxwYXRoIHN0eWxlPSJmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kO3N0cm9rZS13aWR0aDouOThweCIgZD0iTTEuNSAyLjVoMjJ2MTZoLTEzdjQuMTdMNi40NiAxOC41bC00Ljk2LS4wNFYyLjV6Ii8+PC9nPjwvc3ZnPg==)}.scylla-icon--docs{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfS5jbHMtMntmaWxsOmdyYXl9PC9zdHlsZT48L2RlZnM+PGcgaWQ9IkNhbHF1ZV80IiBkYXRhLW5hbWU9IkNhbHF1ZSA0Ij48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Ik0zLjUgMi41MWgxNi45NHYyMC45MUgzLjV6Ii8+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJtMjIuNDUgMjEuNS4wNS0yMWgtMTdhMi4xNiAyLjE2IDAgMCAwLTIgMiIvPjxwYXRoIGNsYXNzPSJjbHMtMiIgZD0iTTYgNmg3djJINnpNNiA5aDExdjJINnoiLz48L2c+PC9zdmc+)}.scylla-icon--enterprise{background-image:url(data:image/svg+xml;base64,PHN2ZyBpZD0iTGF5ZXJfMyIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB2aWV3Qm94PSIwIDAgMjAgMjAiPjxkZWZzPjxzdHlsZT4uY2xzLTEsLmNscy0ye2ZpbGw6bm9uZTtzdHJva2U6IzAwMDtzdHJva2UtbGluZWNhcDpyb3VuZDtzdHJva2UtbGluZWpvaW46cm91bmR9LmNscy0ye3N0cm9rZS13aWR0aDoxLjA3cHh9PC9zdHlsZT48L2RlZnM+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJtMTMuNjIgNy41IDEuODgtMS4wOCAyIDIuMDh2N2gxTTE1LjUgMTUuNXYtNSIvPjxwYXRoIGNsYXNzPSJjbHMtMiIgZD0iTTUuNSAxNS41di0xMmw0LTIgNCAydjEyTTkuNSAxNS41VjEuNk03LjUgNS41djEwTTExLjUgNS41djEwIi8+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNNS41IDguNTQgMy40NiA3LjVsLTEuOTYuOTZ2Ny4wNGgtMU0zLjUgMTAuNXY1TS41IDE3LjVoMTgiLz48L3N2Zz4=)}.scylla-icon--enterprise-m{background-image:url(data:image/svg+xml;base64,PHN2ZyB2ZXJzaW9uPSIxLjEiIGlkPSJMYXllcl8yXzAwMDAwMDE2NzY4MDY2MDE5MjYzMjMyNzcwMDAwMDA1NDc1ODA5NTExODI4NjY2MDM2XyIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4PSIwIiB5PSIwIiB2aWV3Qm94PSIwIDAgNDMgMzEiIHN0eWxlPSJlbmFibGUtYmFja2dyb3VuZDpuZXcgMCAwIDQzIDMxIiB4bWw6c3BhY2U9InByZXNlcnZlIj48c3R5bGU+LnN0MHtmaWxsOm5vbmU7c3Ryb2tlOiMxZDFkMWI7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfTwvc3R5bGU+PGcgaWQ9IkxheWVyXzMiPjxwYXRoIGNsYXNzPSJzdDAiIGQ9Im0yOS42IDkuNSA0LTIgNi45IDQuMXYxNS45aDJNMzMuNiAyNy41VjcuNk0xNC42IDI3LjVWNC44TDIyLjUuNSAyOS42IDV2MjIuNU0yMi41IDI3LjVWMU0yNC41IDUuNmwzIDJNMjQuNSA5LjZsMyAyTTI0LjUgMTMuNmwzIDJNMjQuNSAxNy41bDMgMk0yNC41IDIxLjVsMyAyTTM1LjQgMTEuNmwzIDJNMzUuNCAxNS42bDMgMS45TTM1LjQgMTkuNWwzIDJNMzUuNCAyMy41bDMgMS45TTE4LjUgNS44djIxLjdNMTQuNiA5LjdsLTQuMS0yLjUtOCA0LjR2MTUuOWgtMk0xMC41IDI3LjVWNy4yTTEyLjUgMTEuNmwyIDFNMTIuNSAxNS42bDIgLjlNMTIuNSAxOS41bDIgMU0xMi41IDIzLjVsMi4xIDFNNi40IDEyLjR2MTUuMU0uNSAzMC41aDQyIi8+PC9nPjwvc3ZnPg==)}.scylla-icon--events{background-image:url(data:image/svg+xml;base64,PHN2ZyBpZD0iQ2FscXVlXzEiIGRhdGEtbmFtZT0iQ2FscXVlIDEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmlld0JveD0iMCAwIDI1IDI1Ij48ZGVmcz48c3R5bGU+LmNscy0xe2ZpbGw6bm9uZTtzdHJva2U6Z3JheTtzdHJva2UtbGluZWNhcDpyb3VuZDtzdHJva2UtbGluZWpvaW46cm91bmR9LmNscy0ye2ZpbGw6Z3JheX08L3N0eWxlPjwvZGVmcz48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Ik0yMi41IDIzLjVoLTIxdi0yMGgyMnYxNS4yMSIvPjxwYXRoIGNsYXNzPSJjbHMtMSIgZD0iTTQuNDIgMy41YzAtMS4zNiAxLjA5LTIgMi40NS0yYTIuNDYgMi40NiAwIDEgMSAwIDQuOTEgMi42MSAyLjYxIDAgMCAxLTEtLjIxTTEwLjY3IDMuNWMwLTEuMzYgMS4xLTIgMi40Ni0yYTIuNDYgMi40NiAwIDAgMSAwIDQuOTEgMi42MSAyLjYxIDAgMCAxLTEtLjIxTTE2LjkzIDMuNWMwLTEuMzYgMS4xLTIgMi40NS0yYTIuNDYgMi40NiAwIDEgMSAwIDQuOTEgMi41MiAyLjUyIDAgMCAxLTEtLjIxIi8+PHBhdGggY2xhc3M9ImNscy0yIiBkPSJNNyA5aDN2M0g3ek0xMiA5aDN2M2gtM3pNMTcgOWgzdjNoLTN6TTcgMTRoM3YzSDd6TTEyIDE0aDN2M2gtM3pNMTcgMTRoM3YzaC0zeiIvPjxwYXRoIGNsYXNzPSJjbHMtMSIgZD0iTTMuNSAzLjY3djE2LjY2TTMuNSAyMC40M2MwIDEuMjkuNDQgMi4zMyAxLjczIDIuMzNzMi4zMy0xLjkgMi4zMy0zLjE5bDE2Ljk0LS4wN2MwIDEuMjktLjU1IDMuMTItMS44MyAzLjEySDYuMyIvPjwvc3ZnPg==)}.admonition.note .admonition-title:before,.admonition.tip .admonition-title:before,.scylla-icon--exclamation{background-image:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PG1hc2sgaWQ9ImEiIG1hc2stdHlwZT0iYWxwaGEiIG1hc2tVbml0cz0idXNlclNwYWNlT25Vc2UiIHg9IjEiIHk9IjEiIHdpZHRoPSIyMiIgaGVpZ2h0PSIyMiI+PHBhdGggZD0iTTEyIDIzQzUuOSAyMyAxIDE4LjEgMSAxMlM1LjkgMSAxMiAxczExIDQuOSAxMSAxMS00LjkgMTEtMTEgMTFabTAtMjBjLTUgMC05IDQtOSA5czQgOSA5IDkgOS00IDktOS00LTktOS05WiIgZmlsbD0iI2ZmZiIvPjxwYXRoIGQ9Ik0xMiAxM2MtLjYgMC0xLS40LTEtMVY4YzAtLjYuNC0xIDEtMXMxIC40IDEgMXY0YzAgLjYtLjQgMS0xIDFaTTEyIDE3Yy0uMyAwLS41LS4xLS43LS4zLS4yLS4yLS4zLS40LS4zLS43IDAtLjEgMC0uMy4xLS40LjEtLjEuMS0uMi4yLS4zLjMtLjMuNy0uNCAxLjEtLjIuMSAwIC4xIDAgLjIuMSAwIDAgLjEuMS4yLjEuMS4xLjIuMi4yLjN2LjRjMCAuMSAwIC4zLS4xLjQtLjEuMS0uMS4yLS4yLjMtLjIuMi0uNC4zLS43LjNaIiBmaWxsPSIjZmZmIi8+PC9tYXNrPjxnIG1hc2s9InVybCgjYSkiPjxwYXRoIGZpbGw9IiNmZmYiIGQ9Ik0wIDBoMjR2MjRIMHoiLz48L2c+PC9zdmc+)}.collapsible-button i,.scylla-icon--expand{background-image:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYuMDAxIiBoZWlnaHQ9IjE2IiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjxwYXRoIGQ9Ik01IDEzYTEgMSAwIDAgMS0uNzEtLjI5bC00LTRhMSAxIDAgMCAxIDAtMS40MWw0LTRhMSAxIDAgMCAxIDEuNDIgMS40MUwyLjQxIDhsMy4yOSAzLjI5QTEgMSAwIDAgMSA1IDEzeiIvPjxwYXRoIGQ9Ik0xMSA5SDFhMSAxIDAgMCAxIDAtMmgxMGExIDEgMCAwIDEgMCAyek0xNSAxNmExIDEgMCAwIDEtMS0xVjFhMSAxIDAgMCAxIDIgMHYxNGExIDEgMCAwIDEtMSAxeiIvPjwvc3ZnPg==)}.scylla-icon--forum{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSJjdXJyZW50Q29sb3IiIHN0cm9rZS13aWR0aD0iMS41IiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiIGNsYXNzPSJmZWF0aGVyIGZlYXRoZXItdXNlcnMiPjxwYXRoIGQ9Ik0xNyAyMXYtMmE0IDQgMCAwIDAtNC00SDVhNCA0IDAgMCAwLTQgNHYyIi8+PGNpcmNsZSBjeD0iOSIgY3k9IjciIHI9IjQiLz48cGF0aCBkPSJNMjMgMjF2LTJhNCA0IDAgMCAwLTMtMy44N00xNiAzLjEzYTQgNCAwIDAgMSAwIDcuNzUiLz48L3N2Zz4=)}.scylla-icon--home{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyMSAxOSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOm5vbmU7c3Ryb2tlOiM0ZDRkNGQ7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJMYXllcl81IiBkYXRhLW5hbWU9IkxheWVyIDUiPjxwYXRoIGNsYXNzPSJjbHMtMSIgZD0iTTMuNSA2LjE0djExYTEuMzggMS4zOCAwIDAgMCAxLjM3IDEuMzZoMTEuMjZhMS4zOCAxLjM4IDAgMCAwIDEuMzctMS4zN3YtMTEiLz48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Im0xOS41IDcuNS04LTYuMjVhMS41OSAxLjU5IDAgMCAwLTEuOTQgMEwxLjUgNy41TTEyLjczIDE4LjAydi03LjIxSDguMjd2Ny4yMSIvPjwvZz48L3N2Zz4=)}.scylla-icon--getting-started{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyMSAxOSI+PGcgZGF0YS1uYW1lPSJDYWxxdWUgNCI+PHBhdGggc3R5bGU9ImZpbGw6IzRkNGQ0ZCIgZD0ibTcgNC41IDguNTEgNS4wNUw3IDE0LjV2LTEweiIvPjxyZWN0IHg9IjEuNSIgeT0iLjUiIHdpZHRoPSIxOCIgaGVpZ2h0PSIxOCIgcng9IjIuNDMiIHN0eWxlPSJmaWxsOm5vbmU7c3Ryb2tlOiM0ZDRkNGQ7c3Ryb2tlLW1pdGVybGltaXQ6MTAiLz48L2c+PC9zdmc+)}.scylla-icon--glossary{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyMSAxOSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOm5vbmU7c3Ryb2tlOiM0ZDRkNGQ7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJDYWxxdWVfNCIgZGF0YS1uYW1lPSJDYWxxdWUgNCI+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNMi41IDIuNWgxM3YxNmgtMTN6Ii8+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNMTUuNTggMTcuMjFoMS45MlYuNWgtMTNhMi4zNCAyLjM0IDAgMCAwLTIgMiIvPjxwYXRoIGQ9Ik00LjggMTMuOTNhMSAxIDAgMCAwIC43NS0uNDMgNiA2IDAgMCAwIC41Mi0xLjA4bDIuODctNy4wN2guMzZsMi44OCA2Ljc5YTguOTIgOC45MiAwIDAgMCAuNzIgMS40Ny43Ni43NiAwIDAgMCAuNjguMzJ2LjMySDkuNHYtLjMyYTMuMjQgMy4yNCAwIDAgMCAuODMtLjExYy4xMy0uMDYuMi0uMTkuMi0uNDJhMS41OSAxLjU5IDAgMCAwLS4xLS40NmMwLS4xMi0uMS0uMjctLjE3LS40NGwtLjMzLS43OGgtMi45Yy0uMTkuNTEtLjMxLjg1LS4zNiAxYTIuMzggMi4zOCAwIDAgMC0uMTcuNzNjMCAuMTguMTIuMzIuMzcuNGEyLjU2IDIuNTYgMCAwIDAgLjY2LjA4di4zMkg0LjhabTQuODQtMi43Mi0xLjI0LTNoLS4xMWwtMS4xNiAzWiIgc3R5bGU9ImZpbGw6IzRkNGQ0ZCIvPjwvZz48L3N2Zz4=)}.scylla-icon--infoworld{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLW1pdGVybGltaXQ6MTB9PC9zdHlsZT48L2RlZnM+PGcgaWQ9IkNhbHF1ZV80IiBkYXRhLW5hbWU9IkNhbHF1ZSA0Ij48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Ik0xMiAyLjVINi41VjZjMCAzIC41NSA3LjE3IDUgOS41djQiLz48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Ik02LjQgNC40NGgtNFMyLjU2IDExIDguNSAxM00xOC41IDQuNWw0LS4wNnMtLjA2IDYuNTYtNiA4LjU2Ii8+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNMTIgMi41aDYuNVY2YzAgMi45NC0uNCA3LjA4LTUgOS41djRNOS41IDE5LjVoNnYyaC02eiIvPjxwYXRoIHN0eWxlPSJmaWxsOmdyYXk7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLW1pdGVybGltaXQ6MTAiIGQ9Ik03LjUgMjEuNWgxMHYxaC0xMHoiLz48L2c+PC9zdmc+)}.scylla-icon--integrations{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOm5vbmU7c3Ryb2tlOiM0ZDRkNGQ7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJDYWxxdWVfNCIgZGF0YS1uYW1lPSJDYWxxdWUgNCI+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJtMTQuNTYgMTIuNy0xLjI1LTEuNTctMS4zMS43NmE2IDYgMCAwIDAtMS42NS0xbC4wOC0xLjQ5LTItLjQtLjUzIDEuNDRhNS43MyA1LjczIDAgMCAwLTEuODcuMzFsLS44OC0xLjE5LTEuNzcgMUwzLjkyIDEyYTYuMyA2LjMgMCAwIDAtMS4yMiAxLjQxbC0xLjUtLjM1LS43NCAxLjg3IDEuMzguOGE2LjIzIDYuMjMgMCAwIDAgMCAxLjgzbC0xLjQxLjcyLjY0IDEuOTEgMS41OS0uMjhhNy42MyA3LjYzIDAgMCAwIC40OC42OCA1Ljg2IDUuODYgMCAwIDAgLjY3LjczbC0uNjIgMS40NiAxLjcyIDEgMS0xLjI0YTYuNDYgNi40NiAwIDAgMCAxLjc5LjM1bC40NiAxLjUyIDItLjN2LTEuNmE2LjQzIDYuNDMgMCAwIDAgMS42Mi0uODlsMS4zLjg1TDE0LjQzIDIxbC0xLTEuMmE2LjI0IDYuMjQgMCAwIDAgLjY4LTEuNzVsMS41MS0uMTkuMDUtMi0xLjUxLS4yNmE2LjA3IDYuMDcgMCAwIDAtLjYyLTEuODFabS01LjM1IDUuNTFhMS45MyAxLjkzIDAgMSAxIC4zMS0yLjcxIDEuOTIgMS45MiAwIDAgMS0uMzEgMi43MVoiLz48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Im0yNC4zMSA4LjA1LS4xMy0xLjY1LTEuMjUtLjA5YTUuMjYgNS4yNiAwIDAgMC0uNjctMS40NGwuNzUtMS0xLjE2LTEuMTctMSAuNzRhNS4xOCA1LjE4IDAgMCAwLTEuNDMtLjY2bC0uMDYtMS4yNC0xLjY1LS4xNy0uMzIgMS4yNWE1Ljc3IDUuNzcgMCAwIDAtMS41Mi4zOEwxNSAyLjFsLTEuMzcuOS41OCAxLjE4YTQuODggNC44OCAwIDAgMC0uODYgMS4yNWwtMS4zLS4xNi0uNDUgMS42IDEuMjIuNTVhNS4xNyA1LjE3IDAgMCAwIDAgLjY4QTQuMjggNC4yOCAwIDAgMCAxMyA5bC0xLjExLjcyLjY5IDEuNTEgMS4yOC0uMzdhNC45NCA0Ljk0IDAgMCAwIDEuMDcgMS4wN2wtLjM5IDEuMjYgMS41LjcxLjc0LTEuMDlhNS4wNyA1LjA3IDAgMCAwIDEuNTIuMTRsLjUgMS4xOSAxLjYxLS40MS0uMTMtMS4yOWE1LjE0IDUuMTQgMCAwIDAgMS4yNy0uODhsMS4xMi41NyAxLTEuMzUtLjkxLS44OGE0LjkgNC45IDAgMCAwIC40Mi0xLjUyWm0tNi4yIDEuNDNhMS43NCAxLjc0IDAgMSAxIDEuNi0xLjg2IDEuNzQgMS43NCAwIDAgMS0xLjYgMS44NloiLz48L2c+PC9zdmc+)}.scylla-icon--knowledge-base{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyMSAxOSI+PGRlZnM+PHN0eWxlPi5jbHMtMSwuY2xzLTJ7ZmlsbDpub25lO3N0cm9rZTojNGQ0ZDRkfS5jbHMtMXtzdHJva2UtbGluZWNhcDpyb3VuZDtzdHJva2UtbGluZWpvaW46cm91bmR9LmNscy0ye3N0cm9rZS1taXRlcmxpbWl0OjEwfTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJMYXllcl81IiBkYXRhLW5hbWU9IkxheWVyIDUiPjxwYXRoIGNsYXNzPSJjbHMtMSIgZD0iTTE2LjIxIDYuMzhhNS4zNiA1LjM2IDAgMCAxLTEuNTEgMy43MyA1IDUgMCAwIDAtMS40NSAzLjMxSDguNDdhNS40MSA1LjQxIDAgMCAwLTEuMjgtMy4xMSA1LjM3IDUuMzcgMCAxIDEgOS0zLjkzWk0xMy4yMyAxNS42N0g4LjQ1Ii8+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNMTMuMjQgMTMuNGgtNC44djQuMTZhLjcuNyAwIDAgMCAuNzEuN2gzLjM4YS43LjcgMCAwIDAgLjcxLS43WiIvPjxwYXRoIGNsYXNzPSJjbHMtMiIgZD0iTTEwLjg0IDguMjFhMS42NSAxLjY1IDAgMSAxIDEuNjQtMS42NSAxLjY1IDEuNjUgMCAwIDEtMS42NCAxLjY1Wk0xMC44NCA4LjY3djQuNjQiLz48L2c+PC9zdmc+)}.scylla-icon--less{background-image:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTciIGhlaWdodD0iMTciIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHJlY3Qgd2lkdGg9IjE3IiBoZWlnaHQ9IjE3IiByeD0iMSIgZmlsbD0iI0IzQkFDNSIvPjxwYXRoIGQ9Ik0xMyA4LjVhMSAxIDAgMCAxLTEgMUg1YTEgMSAwIDAgMSAwLTJoN2ExIDEgMCAwIDEgMSAxWiIgZmlsbD0iI2ZmZiIvPjxwYXRoIGQ9Ik0xMyA4LjVhMSAxIDAgMCAxLTEgMUg1YTEgMSAwIDAgMSAwLTJoN2ExIDEgMCAwIDEgMSAxWiIgZmlsbD0iI2ZmZiIvPjxwYXRoIGQ9Ik0xMyA4LjVhMSAxIDAgMCAxLTEgMUg1YTEgMSAwIDAgMSAwLTJoN2ExIDEgMCAwIDEgMSAxWiIgZmlsbD0iI2ZmZiIvPjxwYXRoIGQ9Ik0xMyA4LjVhMSAxIDAgMCAxLTEgMUg1YTEgMSAwIDAgMSAwLTJoN2ExIDEgMCAwIDEgMSAxWiIgZmlsbD0iI2ZmZiIvPjxwYXRoIGQ9Ik0xMyA4LjVhMSAxIDAgMCAxLTEgMUg1YTEgMSAwIDAgMSAwLTJoN2ExIDEgMCAwIDEgMSAxWiIgZmlsbD0iI2ZmZiIvPjwvc3ZnPg==);filter:none}.scylla-icon--live-test{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtNntmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLW1pdGVybGltaXQ6MTA7c3Ryb2tlLWxpbmVjYXA6cm91bmR9PC9zdHlsZT48L2RlZnM+PGcgaWQ9IkNhbHF1ZV80IiBkYXRhLW5hbWU9IkNhbHF1ZSA0Ij48Y2lyY2xlIGN4PSIxMi41IiBjeT0iMTUiIHI9IjkuNSIgc3R5bGU9InN0cm9rZS13aWR0aDoxLjVweDtzdHJva2UtbWl0ZXJsaW1pdDoxMDtmaWxsOm5vbmU7c3Ryb2tlOmdyYXkiLz48cGF0aCBzdHlsZT0ic3Ryb2tlLXdpZHRoOjEuMXB4O3N0cm9rZS1saW5lam9pbjpyb3VuZDtzdHJva2UtbGluZWNhcDpyb3VuZDtmaWxsOm5vbmU7c3Ryb2tlOmdyYXkiIGQ9Ik0xMCAuNWg1djJoLTV6Ii8+PHBhdGggc3R5bGU9InN0cm9rZS13aWR0aDoxLjExcHg7c3Ryb2tlLWxpbmVqb2luOnJvdW5kO3N0cm9rZS1saW5lY2FwOnJvdW5kO2ZpbGw6bm9uZTtzdHJva2U6Z3JheSIgZD0iTTUuOCA4LjIgNC4xMyA2LjUzbDEuOC0xLjgxTDcuNiA2LjQiLz48cGF0aCBzdHlsZT0ic3Ryb2tlLXdpZHRoOjEuMTNweDtzdHJva2UtbWl0ZXJsaW1pdDoxMDtmaWxsOm5vbmU7c3Ryb2tlOmdyYXkiIGQ9Ik0xMiA2VjIuNSIvPjxwYXRoIHN0eWxlPSJzdHJva2Utd2lkdGg6MS4wOHB4O3N0cm9rZS1taXRlcmxpbWl0OjEwO2ZpbGw6bm9uZTtzdHJva2U6Z3JheSIgZD0iTTEzIDZWMi41Ii8+PHBhdGggY2xhc3M9ImNscy02IiBkPSJNMTIuNSA4LjA2VjEwTTEyLjUgMjAuMDR2MS44OE03LjEzIDEwLjA4bDEuNzkgMS44OE0xNi4wNCAxNy4wOGwyIDEuODhNNyAxOC45MmwxLjg4LTEuODhNMTYuMTMgMTEuOTZsMS43OS0xLjgzIi8+PGVsbGlwc2UgY3g9IjEyLjUiIGN5PSIxNC4zNiIgcng9IjEuNSIgcnk9IjEuMzYiIHN0eWxlPSJmaWxsOmdyYXkiLz48cGF0aCBjbGFzcz0iY2xzLTYiIGQ9Im0xMi42MyAxNC41NCAyLjUgNi4zOCIvPjwvZz48L3N2Zz4=)}.scylla-icon--mail-list{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSJjdXJyZW50Q29sb3IiIHN0cm9rZS13aWR0aD0iMS41IiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiIGNsYXNzPSJmZWF0aGVyIGZlYXRoZXItbWFpbCI+PHBhdGggZD0iTTQgNGgxNmMxLjEgMCAyIC45IDIgMnYxMmMwIDEuMS0uOSAyLTIgMkg0Yy0xLjEgMC0yLS45LTItMlY2YzAtMS4xLjktMiAyLTJ6Ii8+PHBhdGggZD0ibTIyIDYtMTAgN0wyIDYiLz48L3N2Zz4=)}.scylla-icon--manager{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtM3tmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kO3N0cm9rZS13aWR0aDouOTdweH0uY2xzLTR7ZmlsbDpncmF5fTwvc3R5bGU+PC9kZWZzPjxwYXRoIHN0eWxlPSJmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kIiBkPSJNMTggMmg1djIySDNWMmg0LjkyIiBpZD0iQ2FscXVlXzIiIGRhdGEtbmFtZT0iQ2FscXVlIDIiLz48ZyBpZD0iQ2FscXVlXzQiIGRhdGEtbmFtZT0iQ2FscXVlIDQiPjxwYXRoIHN0eWxlPSJzdHJva2Utd2lkdGg6MS4wN3B4O2ZpbGw6bm9uZTtzdHJva2U6Z3JheTtzdHJva2UtbGluZWNhcDpyb3VuZDtzdHJva2UtbGluZWpvaW46cm91bmQiIGQ9Ik04IDBoMTB2NEg4eiIvPjxwYXRoIGNsYXNzPSJjbHMtMyIgZD0iTTcgOWgzdjNIN3pNNyAxNmgzdjNIN3oiLz48cGF0aCBjbGFzcz0iY2xzLTQiIGQ9Ik0xMi41IDkuNWg3djJoLTd6TTEyLjUgMTYuNWg3djJoLTd6Ii8+PC9nPjwvc3ZnPg==)}.scylla-icon--memory-management{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMSwuY2xzLTJ7ZmlsbDpub25lO3N0cm9rZTpncmF5O3N0cm9rZS1saW5lY2FwOnJvdW5kO3N0cm9rZS1saW5lam9pbjpyb3VuZH0uY2xzLTJ7c3Ryb2tlLXdpZHRoOjEuMTNweH08L3N0eWxlPjwvZGVmcz48ZyBpZD0iQ2FscXVlXzQiIGRhdGEtbmFtZT0iQ2FscXVlIDQiPjxyZWN0IGNsYXNzPSJjbHMtMSIgeD0iNS41IiB5PSI1LjUiIHdpZHRoPSIxNSIgaGVpZ2h0PSIxNSIgcng9IjIuNzQiIHJ5PSIyLjc0Ii8+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNOS41IDkuNWg3djdoLTd6Ii8+PHBhdGggY2xhc3M9ImNscy0yIiBkPSJNOC41IDUuNXYtNE0xMS41IDUuNXYtNE0xNC41IDUuNXYtNE0xNy41IDUuNXYtNE04LjUgMjQuNXYtNE0xMS41IDI0LjV2LTRNMTQuNSAyNC41di00TTE3LjUgMjQuNXYtNE0yMC41IDguNWg0TTIwLjUgMTEuNWg0TTIwLjUgMTQuNWg0TTIwLjUgMTcuNWg0TTEuNSA4LjVoNE0xLjUgMTEuNWg0TTEuNSAxNC41aDRNMS41IDE3LjVoNCIvPjwvZz48L3N2Zz4=)}.scylla-icon--monitoring{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGcgZGF0YS1uYW1lPSJDYWxxdWUgNCI+PHBhdGggZD0iTTUuNTUgMTAuODlhMy44MyAzLjgzIDAgMCAxLS4xNS0zLjc2IiBzdHlsZT0ic3Ryb2tlLWxpbmVqb2luOnJvdW5kO3N0cm9rZS1saW5lY2FwOnJvdW5kO3N0cm9rZTpncmF5O2ZpbGw6bm9uZSIvPjxyZWN0IHg9IjE3LjYzIiB5PSIxNC4wMSIgd2lkdGg9IjMuMDUiIGhlaWdodD0iMTAuOCIgcng9Ii41NyIgcnk9Ii41NyIgdHJhbnNmb3JtPSJyb3RhdGUoLTQ1IDE5LjE1OCAxOS40MDUpIiBzdHlsZT0ic3Ryb2tlLW1pdGVybGltaXQ6MTA7ZmlsbDpncmF5O3N0cm9rZS13aWR0aDouOTVweDtzdHJva2U6Z3JheSIvPjxjaXJjbGUgY3g9IjguNSIgY3k9IjkiIHI9IjciIHN0eWxlPSJzdHJva2Utd2lkdGg6MnB4O3N0cm9rZS1taXRlcmxpbWl0OjEwO3N0cm9rZTpncmF5O2ZpbGw6bm9uZSIvPjxwYXRoIHN0eWxlPSJzdHJva2UtbWl0ZXJsaW1pdDoxMDtzdHJva2UtbGluZWNhcDpyb3VuZDtzdHJva2U6Z3JheTtmaWxsOm5vbmUiIGQ9Im0xNi4wNSAxNi4zOS0yLjI4LTIuMjgiLz48L2c+PC9zdmc+)}.scylla-icon--networking{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMntmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLW1pdGVybGltaXQ6MTB9PC9zdHlsZT48L2RlZnM+PGcgaWQ9IkNhbHF1ZV80IiBkYXRhLW5hbWU9IkNhbHF1ZSA0Ij48Y2lyY2xlIGN4PSIxMi41IiBjeT0iMTIuNSIgcj0iNCIgc3R5bGU9InN0cm9rZS13aWR0aDouOTRweDtmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLW1pdGVybGltaXQ6MTAiLz48Y2lyY2xlIGNsYXNzPSJjbHMtMiIgY3g9IjUiIGN5PSIzIiByPSIyLjUiLz48Y2lyY2xlIGNsYXNzPSJjbHMtMiIgY3g9IjE5IiBjeT0iMjAiIHI9IjIuNSIvPjxjaXJjbGUgY2xhc3M9ImNscy0yIiBjeD0iMjIiIGN5PSI2LjYiIHI9IjIuNSIvPjxjaXJjbGUgY2xhc3M9ImNscy0yIiBjeD0iNC41IiBjeT0iMjIiIHI9IjIuNSIvPjxwYXRoIGNsYXNzPSJjbHMtMiIgZD0ibTYuODMgNS41IDMuMjUgNC4zM00yMC4yMyA3Ljg1IDE1LjMzIDExTTkuODMgMTUuMDhsLTQuMDkgNS44NE0xNC41OCAxNS4zM2wzIDMuMDkiLz48Y2lyY2xlIGN4PSIxMi41IiBjeT0iMTIuNSIgcj0iMS41IiBzdHlsZT0iZmlsbDpncmF5Ii8+PC9nPjwvc3ZnPg==)}.scylla-icon--news{background-image:url(data:image/svg+xml;base64,PHN2ZyBpZD0iQ2FscXVlXzEiIGRhdGEtbmFtZT0iQ2FscXVlIDEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmlld0JveD0iMCAwIDI1IDI1Ij48ZGVmcz48c3R5bGU+LmNscy0xe2ZpbGw6bm9uZTtzdHJva2U6Z3JheTtzdHJva2UtbGluZWNhcDpyb3VuZDtzdHJva2UtbGluZWpvaW46cm91bmR9PC9zdHlsZT48L2RlZnM+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNMyAxNS4xNyAxNi4zMSAzLjgyYTEuNDggMS40OCAwIDAgMSAyLjIyLjQ2bDUuMTUgOS42NWExLjQ2IDEuNDYgMCAwIDEtLjkzIDIuMTJMNS42OSAxOS45Wk04LjcxIDE5LjMzbC43NiAyLjIyYTEuNTEgMS41MSAwIDAgMCAxLjg1IDFsMy41OC0xLjA2YTEuNSAxLjUgMCAwIDAgMS0xLjg2TDE1LjQ1IDE4TTUuNTQgMjBsLTEuODMgMWEuOTIuOTIgMCAwIDEtMS4yNS0uMzdMLjYxIDE3LjQ5QS45Mi45MiAwIDAgMSAxIDE2LjI0bDEuODMtMU04LjUgMTRsNy4zOC01LjUiLz48L3N2Zz4=)}.scylla-icon--newsletter{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMSwuY2xzLTJ7ZmlsbDpub25lO3N0cm9rZTpncmF5O3N0cm9rZS1taXRlcmxpbWl0OjEwfS5jbHMtMntzdHJva2UtbGluZWNhcDpyb3VuZH08L3N0eWxlPjwvZGVmcz48ZyBpZD0iQ2FscXVlXzQiIGRhdGEtbmFtZT0iQ2FscXVlIDQiPjxwYXRoIGNsYXNzPSJjbHMtMSIgZD0iTTE5LjUgOS41aDN2MTJoLTIwdi0xMmgzIi8+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJtMi42NSA5Ljg0IDkuODUgNi44OCA4LjYzLTYuODgiLz48cGF0aCBjbGFzcz0iY2xzLTIiIGQ9Im01LjUgNy41LTMgMk0xNC4zNSAzLjg2bC0xLjQ2LTEuMDktMS40NyAxLjA5TTIxLjUgOS41bC0yLTJNMTkuNSAxMS41di03aC0xNHY3LjQ3Ii8+PC9nPjwvc3ZnPg==)}.scylla-icon--nsql-guides{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGcgZGF0YS1uYW1lPSJDYWxxdWUgNCI+PHJlY3QgeD0iNC4zNyIgeT0iMTMuNzEiIHdpZHRoPSIxLjE1IiBoZWlnaHQ9IjkuNzIiIHJ4PSIuNTQiIHJ5PSIuNTQiIHRyYW5zZm9ybT0icm90YXRlKDQ1IDQuOTQ4IDE4LjU3KSIgc3R5bGU9InN0cm9rZTpncmF5O3N0cm9rZS1taXRlcmxpbWl0OjEwO2ZpbGw6Z3JheTtzdHJva2Utd2lkdGg6MS4wOXB4Ii8+PGNpcmNsZSBjeD0iMTIuMjUiIGN5PSIxMi4yNSIgcj0iNC43NSIgc3R5bGU9InN0cm9rZS13aWR0aDoxLjVweDtmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLW1pdGVybGltaXQ6MTAiLz48cGF0aCBzdHlsZT0ic3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLXdpZHRoOjEuMDZweDtmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLW1pdGVybGltaXQ6MTAiIGQ9Ik04LjUgMjAuNXYzaDE1di0yMWgtMTV2MiIvPjwvZz48L3N2Zz4=)}.scylla-icon--open-source{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfS5jbHMtMntmaWxsOmdyYXl9PC9zdHlsZT48L2RlZnM+PGcgaWQ9IkNhbHF1ZV80IiBkYXRhLW5hbWU9IkNhbHF1ZSA0Ij48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Ik0uMzEgMjEuNTEgNSAxOS42OWEyLjM3IDIuMzcgMCAwIDEgMS44OC4xOWw1LjI0IDEuNjhhMi4yMyAyLjIzIDAgMCAwIDItLjEybDkuNS00Ljc1Yy44LS40NCAxLjY0LTEuMzEgMS4xMy0xLjkxYTIuMzQgMi4zNCAwIDAgMC0yLjY0LS40MkwxOCAxNi4wOSIvPjxwYXRoIGNsYXNzPSJjbHMtMSIgZD0ibS4yNSAxNS42OSA0Ljg4LTEuMjFjMS4yNS0uMyAyLjE3LS42MyAzLjQ0LS4xM2ExNS4yMSAxNS4yMSAwIDAgMCA0IDEuMWg0LjUyYy44NSAwIC45NS41NC45NSAxLjEzYTEgMSAwIDAgMS0xLjA4IDEgNjUuODYgNjUuODYgMCAwIDEtNy0uMzEiLz48cGF0aCBjbGFzcz0iY2xzLTIiIGQ9Ik04LjU2IDkuNjh2LS44MWMwLS45MS0uMzgtMS4yMS0xLjI5LTEuMjFIN1Y2LjNoLjMxYy45MSAwIDEuMjktLjMgMS4yOS0xLjIxdi0uODFjMC0xLjIuNjYtMS45MiAyLjgyLTIuM3YxLjE2Yy0xLjI0LjM1LTEuNDMuNjgtMS40MyAxLjR2Ljg3QTEuNTIgMS41MiAwIDAgMSA4Ljc1IDcgMS41MiAxLjUyIDAgMCAxIDEwIDguNTZ2Ljg3YzAgLjcxLjE5IDEgMS40MyAxLjRWMTJjLTIuMjEtLjM1LTIuODctMS4xMi0yLjg3LTIuMzJaTTE3LjQzIDQuM3YuODFjMCAuOTEuMzcgMS4yMSAxLjI5IDEuMjFIMTl2MS4zNmgtLjMxYy0uOTIgMC0xLjI5LjMtMS4yOSAxLjIxdi44MWMwIDEuMi0uNjUgMi0yLjgxIDIuMzV2LTEuMmMxLjI1LS4zNiAxLjQ0LS42OSAxLjQ0LTEuNHYtLjg3QTEuNTMgMS41MyAwIDAgMSAxNy4yNSA3IDEuNTMgMS41MyAwIDAgMSAxNiA1LjQzdi0uODdjMC0uNzItLjE5LTEtMS40NC0xLjRWMmMyLjIyLjM4IDIuODcgMS4xIDIuODcgMi4zWiIvPjwvZz48L3N2Zz4=)}.scylla-icon--operator{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjQuODEgMS4wMSAyOC4zMiAyNy42NCI+PHBhdGggZD0iTTMyLjUyIDE4cy0uMDkgMC0uMDktLjA1LS4wOCAwLS4xNyAwYTIuMTkgMi4xOSAwIDAgMC0uNTEgMCAuNDcuNDcgMCAwIDEtLjI2LS4wNSA5LjI5IDkuMjkgMCAwIDEtMS40OS0uMzIuNTQuNTQgMCAwIDEtLjMtLjMxbC0uMzQtLjA4YTExLjI1IDExLjI1IDAgMCAwLS4xOC0zLjc5IDExLjU1IDExLjU1IDAgMCAwLTEuNS0zLjUybC4yNi0uMjZhLjU5LjU5IDAgMCAxIC4xMy0uMzkgNy43MyA3LjczIDAgMCAxIDEuMi0uODZsLjI2LS4xMy40Ny0uM3MuMDkgMCAuMTMtLjA4IDAtLjA1IDAtLjA5YS44NC44NCAwIDAgMCAuMTctMS4yLjc4Ljc4IDAgMCAwLS42LS4zIDEgMSAwIDAgMC0uNi4yMWMtLjA1LjA1LS4wOS4wOS0uMTMuMDlhMy4wOCAzLjA4IDAgMCAwLS4zNS4zOWMwIC4wOC0uMTMuMTMtLjE3LjE3YTUuNjQgNS42NCAwIDAgMS0xLjA3Ljk0LjU4LjU4IDAgMCAxLS4yNi4wOS4yNS4yNSAwIDAgMS0uMTcgMGgtLjA1bC0uMzQuMjEtMS4wOC0xYTExIDExIDAgMCAwLTUuNjUtMi4yN3YtLjM0YS42LjYgMCAwIDEtLjIyLS4zNEE4LjE4IDguMTggMCAwIDEgMTkuNjYgM3YtLjI1YzAtLjA4LjA1LS4zNS4wOS0uNTJ2LS4zMWEuODIuODIgMCAwIDAtMS40Ni0uNi44Ni44NiAwIDAgMC0uMjYuNnYuMjJhMS44MiAxLjgyIDAgMCAwIC4wOS41MS41OS41OSAwIDAgMSAwIC4yNlYzYTguODIgOC44MiAwIDAgMSAuMDggMS40Ny41OS41OSAwIDAgMS0uMjEuMzRWNS4yNGMtLjQ4IDAtMSAuMTMtMS40Ny4yMmExMC4xNiAxMC4xNiAwIDAgMC01LjI4IDNMMTEgOC4yNGgtLjE3YS43My43MyAwIDAgMS0uMjYtLjA5IDcuOCA3LjggMCAwIDEtMS4wNy0xYzAtLjA4LS4xMy0uMTMtLjE3LS4xN3MtLjI1LS4yLS4zMy0uMzMtLjA4IDAtLjEzLS4wOHYtLjA1YTEgMSAwIDAgMC0uNi0uMjEuNjQuNjQgMCAwIDAtLjYuMy45MS45MSAwIDAgMCAuMTcgMS4yczAgLjA1IDAgLjA1LjA5LjA4LjEzLjA4YTUgNSAwIDAgMCAuNDcuMjZsLjI2LjEzYTYuNjEgNi42MSAwIDAgMSAxLjIxLjg2LjQ3LjQ3IDAgMCAxIC4xMy4zOXYtLjA1bC4yNS4yNmEyLjUzIDIuNTMgMCAwIDEtLjEzLjIyIDEwLjIgMTAuMiAwIDAgMC0xLjUgN2wtLjM1LjA5YzAgLjEzLS4xNy4yMS0uMy4zYTguNTYgOC41NiAwIDAgMS0xLjQ2LjI2LjU5LjU5IDAgMCAwLS4yNiAwaC0uNTJjLS4xOCAwLS4wOC4wNS0uMTcuMDVoLS4wOGEuODQuODQgMCAwIDAtLjY5IDEgLjc5Ljc5IDAgMCAwIC44Ni42LjM5LjM5IDAgMCAwIC4yMSAwSDYuMTJhMy42MSAzLjYxIDAgMCAwIC40Ny0uMTcuNjUuNjUgMCAwIDEgLjI2LS4wOCA3LjY1IDcuNjUgMCAwIDEgMS40Mi0uMzkuNDkuNDkgMCAwIDEgLjM1LjEzaC4zOWExMC4zMiAxMC4zMiAwIDAgMCAzLjUzIDUgNi4zMSA2LjMxIDAgMCAwIDEuMTYuNzdsLS4yMi4zYS41MS41MSAwIDAgMSAwIC40MyA2LjU0IDYuNTQgMCAwIDEtLjY5IDEuMjR2LjA1YS43OC43OCAwIDAgMS0uMTcuMjFjLS4wOS4wOS0uMTcuMjYtLjMuNDNzMCAuMDktLjA5LjEzIDAgLjA1IDAgLjA1YS44OC44OCAwIDAgMCAuMzQgMS4xNi45LjkgMCAwIDAgLjMuMDggMSAxIDAgMCAwIC44Mi0uNTFzMC0uMDguMDktLjEzLjEzLS4zLjE3LS40N2wuMDktLjI2YTcuMDcgNy4wNyAwIDAgMSAuNTYtMS4zMy42Mi42MiAwIDAgMSAuMzQtLjI2bC4xNy0uMzVhMTAuMDUgMTAuMDUgMCAwIDAgMy43NS42OSA4LjQ1IDguNDUgMCAwIDAgMi4zMi0uMyAxMS40NiAxMS40NiAwIDAgMCAxLjM3LS4zOWwuMTguMzFhLjYyLjYyIDAgMCAxIC4zNC4yNiA3LjA3IDcuMDcgMCAwIDEgLjU2IDEuMzNsLjA5LjI2YTEuMzEgMS4zMSAwIDAgMCAuMTcuNDdjMCAuMDUgMCAuMDkuMDkuMTNhMSAxIDAgMCAwIC44Mi41MSAxLjA1IDEuMDUgMCAwIDAgLjM0LS4wOC43Ni43NiAwIDAgMCAuMzktLjQ4IDEuMDggMS4wOCAwIDAgMC0uMDUtLjY0LjIuMiAwIDAgMC0uMDgtLjEzIDEuNTMgMS41MyAwIDAgMC0uMzEtLjQzLjY1LjY1IDAgMCAwLS4xNy0uMjJ2LS4wOWE1LjIyIDUuMjIgMCAwIDEtLjY5LTEuMjQuNTEuNTEgMCAwIDEgLjA1LS40M2wtLjEzLS4zNEExMC42OCAxMC42OCAwIDAgMCAyOSAxOC44MmwuMzQuMDV2LS4wNWEuNTQuNTQgMCAwIDEgLjM1LS4xMyA3LjgyIDcuODIgMCAwIDEgMS4zOC4zOS42Mi42MiAwIDAgMCAuMjYuMDkgMi40MiAyLjQyIDAgMCAwIC40Ny4yMXMuMDkgMCAuMTcgMGguMDlhLjM5LjM5IDAgMCAwIC4yMSAwIC45NC45NCAwIDAgMCAuODYtLjYgMSAxIDAgMCAwLS43Ny0uOVptLTEyLjQzLTEuMzMtMS4xNi41Ni0xLjE2LS41Ni0uMy0xLjI1LjgxLTFoMS4yOWwuODIgMVptNy0yLjc5YTggOCAwIDAgMSAuMTcgMi43MWwtNC4xNS0uNzVjLS4zOC0uMDgtLjY4LS45LS43MS0xLjIyYTQgNCAwIDAgMSAuMjEtLjc0bDMuNDUtMi41NGE4LjU4IDguNTggMCAwIDEgMS4wNCAyLjU0Wm0tMi4zMS00LjEzLTMuMjIgMi42OWExLjI4IDEuMjggMCAwIDEtMS4yNS0uMzdjLS4wOS0uMDktLjM3LS4yNS0uMzctLjM4VjcuNDNhOC4wNyA4LjA3IDAgMCAxIDQuODYgMi4zMlpNMTcgNy41NmwxLS4xOC0uMDYgNC4zMWMwIC4zOC0uNjQuNjgtMSAuNjhhMS4xMSAxLjExIDAgMCAxLS4zNS0uMDhMMTMgOS43NWE4LjQxIDguNDEgMCAwIDEgNC0yLjE5Wm0tNS4yNCAzLjc4IDMuMzcgMi40Ny4zMi41M2ExLjE0IDEuMTQgMCAwIDEtLjI1IDEgLjc4Ljc4IDAgMCAxLS4zOC4zMWwtNC4zMS45YTkgOSAwIDAgMSAxLjI0LTUuMjFaTTExIDE4LjYxbDQuMS0xLjIzYy4zNSAwIC44NC43MS44OSAxLjA2YS41MS41MSAwIDAgMS0uMDUuNDNsLTEuNjMgMy45NUE4LjQxIDguNDEgMCAwIDEgMTEgMTguNjFabTkuNzYgNS4zM2E4LjY3IDguNjcgMCAwIDEtMS44NS4yMSA5LjU5IDkuNTkgMCAwIDEtMi43MS0uNDNsMS42Ni00Yy4yMS0uMjYgMS0uMiAxLjMxIDBhMi40OCAyLjQ4IDAgMCAxIC4zNC4zbDIuMDcgMy43NGE1LjcyIDUuNzIgMCAwIDAtLjguMThaTTI2IDIwLjJhOC4zNiA4LjM2IDAgMCAxLTIuNTggMi41OGwtMS45Mi0zLjcyYTEuMTUgMS4xNSAwIDAgMSAuNDEtMWMuMjEtLjI1LjU5LS41OS43MS0uNTlsNC4yMiAxLjA2QTYuMjcgNi4yNyAwIDAgMSAyNiAyMC4yWiIgc3R5bGU9ImZpbGw6IzRkNGQ0ZCIgZGF0YS1uYW1lPSJDYWxxdWUgMiIvPjwvc3ZnPg==)}.scylla-icon--overview{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJDYWxxdWVfNCIgZGF0YS1uYW1lPSJDYWxxdWUgNCI+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNMjIuNjEgMy40NUMyMi42MSA1LjA2IDE4IDYuNSAxMi41IDYuNXMtMTAtMS40NC0xMC0zIDQuNS0zIDEwLTMgMTAuMTEgMS4zMyAxMC4xMSAyLjk1Wk0yMi42MSA5LjQ0YzAgMS42MS00LjY0IDMuMDYtMTAuMTEgMy4wNnMtMTAtMS40NS0xMC0zLjA2TTIyLjYxIDE1LjUxYzAgMS42Mi00LjY0IDMtMTAuMTEgM3MtMTAtMS4zNy0xMC0zTTIyLjYxIDIxLjU5YzAgMS42Mi00LjY0IDIuOTEtMTAuMTEgMi45MXMtMTAtMS4yOS0xMC0yLjkxTTIuNSAyMS40N1YzLjQ1TTIyLjUgMjEuNDdWMy40NSIvPjwvZz48L3N2Zz4=)}.scylla-icon--partners{background-image:url(data:image/svg+xml;base64,PHN2ZyBpZD0iQ2FscXVlXzEiIGRhdGEtbmFtZT0iQ2FscXVlIDEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmlld0JveD0iMCAwIDI1IDI1Ij48ZGVmcz48c3R5bGU+LmNscy0xe2ZpbGw6bm9uZTtzdHJva2U6Z3JheTtzdHJva2UtbGluZWNhcDpyb3VuZDtzdHJva2UtbGluZWpvaW46cm91bmR9PC9zdHlsZT48L2RlZnM+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNMTguNSA4LjI2aC00LjcybC0xLjIzIDEuMjdNMi4zOSAxNS4wOS4xNSAxMy43NGw0Ljg3LTguNDIgMi4yNCAxLjM0LTQuODcgOC40M3pNMjIuNTkgMTUuMDlsMi4yNC0xLjM1LTQuODYtOC40Mi0yLjI0IDEuMzQgNC44NiA4LjQzek0xMC43MSAxNS4yNmwtMi45MyAyLjIxTTEyLjE4IDE2LjRsLTIuOTMgMi4yMU0xMy42OCAxNy41M2wtMi45MyAyLjIyIi8+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNNi4zOCA4LjNoMy43OGEyLjI3IDIuMjcgMCAwIDEgMS4zNy40N2MxLjI2IDEgNC4wOSAzLjE4IDQuNDggMy41NnMtMS4xNCAxLjY4LTIuMjcgMS4xYTE4LjM0IDE4LjM0IDAgMCAwLTIuMTEtLjkyLjU3LjU3IDAgMCAwLS41Ni4wOWwtNC43OSAzLjg5TDEyLjMzIDIxbDkuNDYtNy4wOU0zLjI0IDE0LjIybDMuNCAxLjg1Ii8+PC9zdmc+)}.scylla-icon--plus{background-image:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTciIGhlaWdodD0iMTciIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHJlY3Qgd2lkdGg9IjE3IiBoZWlnaHQ9IjE3IiByeD0iMSIgZmlsbD0iI0IzQkFDNSIvPjxwYXRoIGZpbGwtcnVsZT0iZXZlbm9kZCIgY2xpcC1ydWxlPSJldmVub2RkIiBkPSJNOS41IDVhMSAxIDAgMSAwLTIgMHYyLjVINWExIDEgMCAxIDAgMCAyaDIuNVYxMmExIDEgMCAxIDAgMiAwVjkuNUgxMmExIDEgMCAxIDAgMC0ySDkuNVY1WiIgZmlsbD0iI2ZmZiIvPjxwYXRoIGZpbGwtcnVsZT0iZXZlbm9kZCIgY2xpcC1ydWxlPSJldmVub2RkIiBkPSJNOS41IDVhMSAxIDAgMSAwLTIgMHYyLjVINWExIDEgMCAxIDAgMCAyaDIuNVYxMmExIDEgMCAxIDAgMiAwVjkuNUgxMmExIDEgMCAxIDAgMC0ySDkuNVY1WiIgZmlsbD0iI2ZmZiIvPjxwYXRoIGZpbGwtcnVsZT0iZXZlbm9kZCIgY2xpcC1ydWxlPSJldmVub2RkIiBkPSJNOS41IDVhMSAxIDAgMSAwLTIgMHYyLjVINWExIDEgMCAxIDAgMCAyaDIuNVYxMmExIDEgMCAxIDAgMiAwVjkuNUgxMmExIDEgMCAxIDAgMC0ySDkuNVY1WiIgZmlsbD0iI2ZmZiIvPjxwYXRoIGZpbGwtcnVsZT0iZXZlbm9kZCIgY2xpcC1ydWxlPSJldmVub2RkIiBkPSJNOS41IDVhMSAxIDAgMSAwLTIgMHYyLjVINWExIDEgMCAxIDAgMCAyaDIuNVYxMmExIDEgMCAxIDAgMiAwVjkuNUgxMmExIDEgMCAxIDAgMC0ySDkuNVY1WiIgZmlsbD0iI2ZmZiIvPjxwYXRoIGZpbGwtcnVsZT0iZXZlbm9kZCIgY2xpcC1ydWxlPSJldmVub2RkIiBkPSJNOS41IDVhMSAxIDAgMSAwLTIgMHYyLjVINWExIDEgMCAxIDAgMCAyaDIuNVYxMmExIDEgMCAxIDAgMiAwVjkuNUgxMmExIDEgMCAxIDAgMC0ySDkuNVY1WiIgZmlsbD0iI2ZmZiIvPjwvc3ZnPg==);filter:none}.scylla-icon--pricing{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJDYWxxdWVfMiIgZGF0YS1uYW1lPSJDYWxxdWUgMiI+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJtMjEuNzMgNy0yLjQxLTUuMTJhMi41MiAyLjUyIDAgMCAwLTIuODItMWwtNi4wOCAyLjA0QTEuNjkgMS42OSAwIDAgMCA5LjUxIDRMMy45MyAxOS4yOWExLjA2IDEuMDYgMCAwIDAgLjY0IDEuMTdsMTAuMzQgMy43NmExIDEgMCAwIDAgMS4yMi0uNDNsNS41OC0xNS4zM0ExLjg3IDEuODcgMCAwIDAgMjEuNzMgN1oiLz48Y2lyY2xlIGNsYXNzPSJjbHMtMSIgY3g9IjE1LjczIiBjeT0iNS44OSIgcj0iMiIvPjx0ZXh0IHRyYW5zZm9ybT0icm90YXRlKDIwIC00OC4yNDQgMzAuNjcpIiBzdHlsZT0iZm9udC1zaXplOjEycHg7ZmlsbDpncmF5O2ZvbnQtZmFtaWx5OlJvYm90by1NZWRpdW0sUm9ib3RvIj4kPC90ZXh0PjwvZz48L3N2Zz4=)}.scylla-icon--release-note{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMntmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kO3N0cm9rZS13aWR0aDouOTFweH08L3N0eWxlPjwvZGVmcz48ZyBpZD0iQ2FscXVlXzIiIGRhdGEtbmFtZT0iQ2FscXVlIDIiPjxwYXRoIHN0eWxlPSJzdHJva2Utd2lkdGg6LjlweDtmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kIiBkPSJNMjEuNSAyNC41aC0xN1Y1LjdMOC45NS41NCAyMS41LjV2MjR6Ii8+PHBhdGggY2xhc3M9ImNscy0yIiBkPSJNNC42NSA1LjVIOS41VjFNNy41IDguNWgxMU03LjUgMTEuNWgxMU03LjUgMTQuNWgxMU03LjUgMTcuNWgxMU03LjUgMjAuNWgxMSIvPjwvZz48L3N2Zz4=)}.scylla-icon--resource-center{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfS5jbHMtMntmaWxsOmdyYXl9PC9zdHlsZT48L2RlZnM+PGcgaWQ9IkNhbHF1ZV80IiBkYXRhLW5hbWU9IkNhbHF1ZSA0Ij48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Ik01LjUgMi41aDYuOTFsLjA5IDIwaC03di0yMHoiLz48cGF0aCBjbGFzcz0iY2xzLTIiIGQ9Ik04IDRoMnYxMC45N0w4IDE1VjR6Ii8+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNNS4zNiAyLjI5IDIuNSAzLjV2MThsMi43OSAxLjE0Ii8+PHBhdGggc3R5bGU9InN0cm9rZS13aWR0aDouNjhweDtmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kIiBkPSJtMTIuNTcgMjEuODYgMS41Ny43NSIvPjxwYXRoIHN0eWxlPSJzdHJva2Utd2lkdGg6Ljg1cHg7ZmlsbDpub25lO3N0cm9rZTpncmF5O3N0cm9rZS1saW5lY2FwOnJvdW5kO3N0cm9rZS1saW5lam9pbjpyb3VuZCIgZD0ibTE0LjExIDIuNS0xLjU0LjU3Ii8+PGNpcmNsZSBjbGFzcz0iY2xzLTIiIGN4PSI5IiBjeT0iMTkiIHI9IjEiLz48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Ik0xNC41IDIuNWg2Ljk0bC4wNiAyMGgtN3YtMjB6Ii8+PHBhdGggY2xhc3M9ImNscy0yIiBkPSJNMTcgNGgydjEwLjk3TDE3IDE1VjR6Ii8+PGNpcmNsZSBjbGFzcz0iY2xzLTIiIGN4PSIxOCIgY3k9IjE5IiByPSIxIi8+PHBhdGggY2xhc3M9ImNscy0yIiBkPSJNMTIuNiAyLjczaDEuNjdWMjIuNkgxMi42ek0yLjU4IDIxLjVsMi43NSAxLjFWMi43M2wtMi42Ni45NC0uMDkgMTcuODN6Ii8+PC9nPjwvc3ZnPg==)}.scylla-icon--roadmap{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMSwuY2xzLTJ7ZmlsbDpub25lO3N0cm9rZTpncmF5fS5jbHMtMXtzdHJva2UtbGluZWNhcDpyb3VuZDtzdHJva2UtbGluZWpvaW46cm91bmQ7c3Ryb2tlLXdpZHRoOi45OHB4fS5jbHMtMntzdHJva2UtbWl0ZXJsaW1pdDoxMH0uY2xzLTN7ZmlsbDpncmF5fTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJDYWxxdWVfNCIgZGF0YS1uYW1lPSJDYWxxdWUgNCI+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJtLjUgNC41IDgtMyA4IDQgOC0zdjE3bC04IDMtOC00LTggM3YtMTd6TTguNSAxLjVWMThNMTYuNSA1LjVWMjIiLz48cGF0aCBjbGFzcz0iY2xzLTIiIGQ9Ik0yLjUgMTMgNyAxNi41TTcgMTJsLTQuNSA1LjVNMTguNSA4bDQuNSAzLjVNMjMgN2wtNC41IDUuNSIvPjxwYXRoIGNsYXNzPSJjbHMtMyIgZD0iTTEwIDEzaDF2MWgtMXpNMTIgMTJoMXYxaC0xek0xNCAxMWgxdjFoLTF6Ii8+PC9nPjwvc3ZnPg==)}.scylla-icon--search{background-image:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZD0iTTEwLjUgMThhNy41IDcuNSAwIDEgMCAwLTE1IDcuNSA3LjUgMCAwIDAgMCAxNVpNMjEgMjFsLTUuMi01LjIiIHN0cm9rZT0iIzAwMCIgc3Ryb2tlLXdpZHRoPSIyIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiLz48L3N2Zz4=)}.scylla-icon--slack{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0NDggNTEyIj48IS0tISBGb250IEF3ZXNvbWUgUHJvIDYuMC4wIGJ5IEBmb250YXdlc29tZSAtIGh0dHBzOi8vZm9udGF3ZXNvbWUuY29tIExpY2Vuc2UgLSBodHRwczovL2ZvbnRhd2Vzb21lLmNvbS9saWNlbnNlIChDb21tZXJjaWFsIExpY2Vuc2UpIENvcHlyaWdodCAyMDIyIEZvbnRpY29ucywgSW5jLi0tPjxwYXRoIGQ9Ik05NC4xMiAzMTUuMWMwIDI1LjktMjEuMTYgNDcuMDYtNDcuMDYgNDcuMDZTMCAzNDEgMCAzMTUuMWMwLTI1LjkgMjEuMTYtNDcuMDYgNDcuMDYtNDcuMDZoNDcuMDZ2NDcuMDZ6bTIzLjcyIDBjMC0yNS45IDIxLjE2LTQ3LjA2IDQ3LjA2LTQ3LjA2czQ3LjA2IDIxLjE2IDQ3LjA2IDQ3LjA2djExNy44NGMwIDI1LjktMjEuMTYgNDcuMDYtNDcuMDYgNDcuMDZzLTQ3LjA2LTIxLjE2LTQ3LjA2LTQ3LjA2VjMxNS4xem00Ny4wNi0xODguOThjLTI1LjkgMC00Ny4wNi0yMS4xNi00Ny4wNi00Ny4wNlMxMzkgMzIgMTY0LjkgMzJzNDcuMDYgMjEuMTYgNDcuMDYgNDcuMDZ2NDcuMDZIMTY0Ljl6bTAgMjMuNzJjMjUuOSAwIDQ3LjA2IDIxLjE2IDQ3LjA2IDQ3LjA2cy0yMS4xNiA0Ny4wNi00Ny4wNiA0Ny4wNkg0Ny4wNkMyMS4xNiAyNDMuOTYgMCAyMjIuOCAwIDE5Ni45czIxLjE2LTQ3LjA2IDQ3LjA2LTQ3LjA2SDE2NC45em0xODguOTggNDcuMDZjMC0yNS45IDIxLjE2LTQ3LjA2IDQ3LjA2LTQ3LjA2IDI1LjkgMCA0Ny4wNiAyMS4xNiA0Ny4wNiA0Ny4wNnMtMjEuMTYgNDcuMDYtNDcuMDYgNDcuMDZoLTQ3LjA2VjE5Ni45em0tMjMuNzIgMGMwIDI1LjktMjEuMTYgNDcuMDYtNDcuMDYgNDcuMDYtMjUuOSAwLTQ3LjA2LTIxLjE2LTQ3LjA2LTQ3LjA2Vjc5LjA2YzAtMjUuOSAyMS4xNi00Ny4wNiA0Ny4wNi00Ny4wNiAyNS45IDAgNDcuMDYgMjEuMTYgNDcuMDYgNDcuMDZWMTk2Ljl6TTI4My4xIDM4NS44OGMyNS45IDAgNDcuMDYgMjEuMTYgNDcuMDYgNDcuMDYgMCAyNS45LTIxLjE2IDQ3LjA2LTQ3LjA2IDQ3LjA2LTI1LjkgMC00Ny4wNi0yMS4xNi00Ny4wNi00Ny4wNnYtNDcuMDZoNDcuMDZ6bTAtMjMuNzJjLTI1LjkgMC00Ny4wNi0yMS4xNi00Ny4wNi00Ny4wNiAwLTI1LjkgMjEuMTYtNDcuMDYgNDcuMDYtNDcuMDZoMTE3Ljg0YzI1LjkgMCA0Ny4wNiAyMS4xNiA0Ny4wNiA0Ny4wNiAwIDI1LjktMjEuMTYgNDcuMDYtNDcuMDYgNDcuMDZIMjgzLjF6Ii8+PC9zdmc+)}.scylla-icon--stack-overflow{background-image:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjQiIGhlaWdodD0iMzEiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Im0yMS45NDkuMTEzIDIuMDQzIDExLjY3LTIuNTE0LjQzMkwxOS40MzUuNTQ1IDIxLjk1LjExNFptLTE3Ljk3MyAyNiAxMS45NDUtLjAwNS0uMDAyLTIuNTMtMTEuOTQ0LjAwNi4wMDEgMi41M1ptMTIuMjMyLTUuNzc3TDQuMzE1IDE5LjI1bC0uMjM1IDIuNTIgMTEuODk0IDEuMDg1LjIzNC0yLjUxOVptLTEwLjc1LTYuMzc1IDExLjUzNSAzLjA3NC0uNjYyIDIuNDQzLTExLjUzNS0zLjA3NS42NjItMi40NDJabTEzLjA0LjE4TDguMjEyIDguMTI2bC0xLjI5NyAyLjE3OCAxMC4yODkgNi4wMTcgMS4yOTYtMi4xNzhabS00LjIwNi0xMS41NiA2LjczIDkuNzg3LTIuMTA4IDEuNDI0LTYuNzMtOS43ODUgMi4xMDgtMS40MjVaIiBmaWxsPSIjMDAwIi8+PHBhdGggZD0iTTE3Ljk1IDE3Ljc4OVYyOC4xM0gyLjI4MlYxNy43ODlILjI0M3YxMi4zMjZIMTkuOThWMTcuNzg5aC0yLjAzWiIgZmlsbD0iIzAwMCIvPjwvc3ZnPg==)}.scylla-icon--summit{background-image:url(data:image/svg+xml;base64,PHN2ZyBpZD0iQ2FscXVlXzEiIGRhdGEtbmFtZT0iQ2FscXVlIDEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmlld0JveD0iMCAwIDI1IDI1Ij48ZGVmcz48c3R5bGU+LmNscy0xe2ZpbGw6bm9uZTtzdHJva2U6IzRkNGQ0ZDtzdHJva2UtbGluZWNhcDpyb3VuZDtzdHJva2UtbGluZWpvaW46cm91bmR9PC9zdHlsZT48L2RlZnM+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJtMTYuNSAyMiAxLTYuNS0xMCAuMDMgMSA2LjQzIi8+PHBhdGggZD0iTTMuNDYgMTJBNS42OSA1LjY5IDAgMCAxIDUgNy41IiBzdHlsZT0ic3Ryb2tlLXdpZHRoOjEuMXB4O3N0cm9rZTojNGQ0ZDRkO3N0cm9rZS1saW5lY2FwOnJvdW5kO3N0cm9rZS1saW5lam9pbjpyb3VuZDtmaWxsOm5vbmUiLz48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Ik0xNC42MiA1YTIuMzMgMi4zMyAwIDAgMS0yLjI1IDIuNWMtMS4zMyAwLTItMS4xMi0xLjk1LTIuNDRzLjctMi41IDItMi40OEEyLjI3IDIuMjcgMCAwIDEgMTQuNjIgNVpNMTcuNTggMTJhMy4yMyAzLjIzIDAgMCAwLTMuNDYtMy41SDExQTMuMjYgMy4yNiAwIDAgMCA3LjUgMTIiLz48Y2lyY2xlIGN4PSI0Ljk0IiBjeT0iNi45NiIgcj0iMS4wMSIgc3R5bGU9ImZpbGw6IzRkNGQ0ZDtzdHJva2Utd2lkdGg6MS4xcHg7c3Ryb2tlOiM0ZDRkNGQ7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kIi8+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNNy41NCAxOC41SDQuNWwtMi02aDIwbC0yIDZoLTMiLz48L3N2Zz4=)}.scylla-icon--support{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJDYWxxdWVfNCIgZGF0YS1uYW1lPSJDYWxxdWUgNCI+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNMTguMTkgNy41YTEwIDEwIDAgMCAxIC4yMSAyLjA3YzAgNC4zNi0yLjYzIDYuOTMtNS45IDYuOTNzLTUuOTQtMi41Ny01Ljk0LTYuOTNhMTAuNTEgMTAuNTEgMCAwIDEgLjIyLTIuMTIiLz48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Ik03LjY3IDIuMjNBNi41OCA2LjU4IDAgMCAxIDEyLjUuNWE1LjY1IDUuNjUgMCAwIDEgNC4yOSAxLjdjMS45MyAxLjk0IDIuMzUgNS4wNyAyLjQzIDYuNzJhMS40OSAxLjQ5IDAgMCAwLS43OS4wNSA4LjY4IDguNjggMCAwIDAtLjA4LTEuMTZoMGE1LjUzIDUuNTMgMCAwIDEtMS43Ny0yLjM0TDE2LjQ5IDVsLS4zOC4yMkExOSAxOSAwIDAgMSA2LjggNy4zOGEuNTIuNTIgMCAwIDAtLjQyLjE2Yy0uMjMuMjQtLjE1LjY1LS4wNyAxLjA4IDAgLjExIDAgLjIyLjA1LjMyYTEuNCAxLjQgMCAwIDAtLjU4IDBjLS4xLTEuNDUtLjA2LTQuNjggMS44OS02LjcxWk02LjM4IDljLS42NS0uMDgtMSAuMS0xLjE0Ljc5YTIuMDYgMi4wNiAwIDAgMCAxLjM3IDIuMjlNMTguNTYgOWMuNjUtLjA4IDEuMDUuMSAxLjE0Ljc5YTIuMDYgMi4wNiAwIDAgMS0xLjM3IDIuMjlNOS41IDE4LjIzVjE1LjVNMTUuNSAxNS41djIuNzNNMi41IDI0LjE2Yy4yNC0yIC41OS0zLjYzIDIuNDMtNC40OWEyNC4yOSAyNC4yOSAwIDAgMSA0LjgyLTEuMzdNMjIuNSAyNC4zM2MtLjI0LTItLjQyLTMuOC0yLjI2LTQuNjZhMjQuMjkgMjQuMjkgMCAwIDAtNC44Mi0xLjM3Ii8+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNMTUuMzkgMTguMzlhNC4zNyA0LjM3IDAgMCAxLTIuOTEgMS4wNyA0LjQyIDQuNDIgMCAwIDEtMi44OS0xLjA1Ii8+PHBhdGggc3R5bGU9ImZpbGw6Z3JheSIgZD0iTTExIDEzaDN2MmgtM3oiLz48cGF0aCBkPSJNMTguMDcgMTJhOS4yMSA5LjIxIDAgMCAxLTUuNTMgMi4wNyIgc3R5bGU9InN0cm9rZS1taXRlcmxpbWl0OjEwO2ZpbGw6bm9uZTtzdHJva2U6Z3JheSIvPjwvZz48L3N2Zz4=)}.scylla-icon--tech-talks{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJDYWxxdWVfNCIgZGF0YS1uYW1lPSJDYWxxdWUgNCI+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNOC4zOSA0LjVIMjMuNXYxM2gtMTUiLz48Y2lyY2xlIGN4PSI0LjUiIGN5PSI2LjUiIHI9IjIiIHN0eWxlPSJzdHJva2UtbWl0ZXJsaW1pdDoxMDtmaWxsOm5vbmU7c3Ryb2tlOmdyYXkiLz48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Ik0xLjUgOS41aDJsLjguODYuNy0uODZoNS41OGExIDEgMCAxIDEgMCAySDYuNXYxMC44OGExIDEgMCAwIDEtMSAxLjEyIDEgMSAwIDAgMS0xLTEgMSAxIDAgMCAxLTEgMSAuOTMuOTMgMCAwIDEtMS0xdi02Yy0uNzggMC0yLS40Ny0yLTF2LTVhMSAxIDAgMCAxIDEtMVoiLz48L2c+PC9zdmc+)}.scylla-icon--testing{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJDYWxxdWVfNCIgZGF0YS1uYW1lPSJDYWxxdWUgNCI+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNNi41IDYuNWgxMnYxMmgtMTJ6Ii8+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNNC41IDQuNWgxNnYxNmgtMTZ6Ii8+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJtOC41IDEwLjUgNSA1IDExLTEyIi8+PC9nPjwvc3ZnPg==)}.scylla-icon--thumbs-up{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSJjdXJyZW50Q29sb3IiIHN0cm9rZS13aWR0aD0iMiIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIiBjbGFzcz0iZmVhdGhlciBmZWF0aGVyLXRodW1icy11cCI+PHBhdGggZD0iTTE0IDlWNWEzIDMgMCAwIDAtMy0zbC00IDl2MTFoMTEuMjhhMiAyIDAgMCAwIDItMS43bDEuMzgtOWEyIDIgMCAwIDAtMi0yLjN6TTcgMjJINGEyIDIgMCAwIDEtMi0ydi03YTIgMiAwIDAgMSAyLTJoMyIvPjwvc3ZnPg==)}.scylla-icon--thumbs-down{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSJjdXJyZW50Q29sb3IiIHN0cm9rZS13aWR0aD0iMiIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIiBjbGFzcz0iZmVhdGhlciBmZWF0aGVyLXRodW1icy1kb3duIj48cGF0aCBkPSJNMTAgMTV2NGEzIDMgMCAwIDAgMyAzbDQtOVYySDUuNzJhMiAyIDAgMCAwLTIgMS43bC0xLjM4IDlhMiAyIDAgMCAwIDIgMi4zem03LTEzaDIuNjdBMi4zMSAyLjMxIDAgMCAxIDIyIDR2N2EyLjMxIDIuMzEgMCAwIDEtMi4zMyAySDE3Ii8+PC9zdmc+)}.scylla-icon--tip{background-image:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZD0iTTEyIDI0QzUuNCAyNCAwIDE4LjYgMCAxMlM1LjQgMCAxMiAwczEyIDUuNCAxMiAxMi01LjQgMTItMTIgMTJabTAtMjJDNi41IDIgMiA2LjUgMiAxMnM0LjUgMTAgMTAgMTAgMTAtNC41IDEwLTEwUzE3LjUgMiAxMiAyWiIgZmlsbD0iI2ZmZiIvPjxwYXRoIGQ9Ik0xMSAxNmMtLjMgMC0uNS0uMS0uNy0uM2wtMy0zYy0uNC0uNC0uNC0xIDAtMS40LjQtLjQgMS0uNCAxLjQgMGwzIDNjLjQuNC40IDEgMCAxLjQtLjIuMi0uNC4zLS43LjNaIiBmaWxsPSIjZmZmIi8+PHBhdGggZD0iTTExIDE2Yy0uMyAwLS41LS4xLS43LS4zLS40LS40LS40LTEgMC0xLjRsNi02Yy40LS40IDEtLjQgMS40IDAgLjQuNC40IDEgMCAxLjRsLTYgNmMtLjIuMi0uNC4zLS43LjNaIiBmaWxsPSIjZmZmIi8+PC9zdmc+)}.scylla-icon--training{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJDYWxxdWVfMiIgZGF0YS1uYW1lPSJDYWxxdWUgMiI+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNMTcuNSAxNS41SC41di0xM2gxOE01LjUgMjVsNC00LjMgNCA0LjMiLz48Y2lyY2xlIGN4PSIyMSIgY3k9IjQiIHI9IjIuNSIgc3R5bGU9InN0cm9rZS1taXRlcmxpbWl0OjEwO2ZpbGw6bm9uZTtzdHJva2U6Z3JheSIvPjxwYXRoIGNsYXNzPSJjbHMtMSIgZD0iTTIzLjQxIDcuNWgtMS41MkwyMSA5bC0uOS0xLjVIMTNBMS44IDEuOCAwIDAgMCAxMS41IDlhMS44IDEuOCAwIDAgMCAxLjUgMS41aDQuNXYxMy4yNEExLjQxIDEuNDEgMCAwIDAgMTkgMjVhMS40MiAxLjQyIDAgMCAwIDEuNS0xLjIyIDEuNTMgMS41MyAwIDAgMCAzIDB2LTcuMTFhMS4xMSAxLjExIDAgMCAwIDEuMDktMS4xOFY4LjY3YTEuMTggMS4xOCAwIDAgMC0xLjE4LTEuMTdaTTkuNSAxNS40NHY1LjM4Ii8+PC9nPjwvc3ZnPg==)}.collapsible-button .side-nav__content .toctree-checkbox:checked~label i,.collapsible-button .side-nav__content i,.scylla-icon--triangle-down,.side-nav__content .collapsible-button i,.side-nav__content .scylla-icon--expand,.side-nav__content .toctree-checkbox:checked~label .collapsible-button i,.side-nav__content .toctree-checkbox:checked~label .scylla-icon--expand{background-image:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTAiIGhlaWdodD0iNSIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cGF0aCBmaWxsLXJ1bGU9ImV2ZW5vZGQiIGNsaXAtcnVsZT0iZXZlbm9kZCIgZD0ibTAgMCA1IDUgNS01SDBaIiBmaWxsPSIjM0EyRDU1Ii8+PC9zdmc+)}.scylla-icon--university{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJDYWxxdWVfNCIgZGF0YS1uYW1lPSJDYWxxdWUgNCI+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJtMS41IDguNSAxMS00IDExIDR2M2wtMTEgNC0xMS00di0zeiIvPjxwYXRoIGNsYXNzPSJjbHMtMSIgZD0iTTUuNSAxMi41djVhMTIuNDYgMTIuNDYgMCAwIDAgNyAyIDExLjIgMTEuMiAwIDAgMCA3LTJ2LTUiLz48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Im0xMy41IDkuNSA4IDEuMjN2OC43N00yMi41IDE2LjV2MyIvPjwvZz48L3N2Zz4=)}.scylla-icon--users-blog{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMntmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJDYWxxdWVfNCIgZGF0YS1uYW1lPSJDYWxxdWUgNCI+PHBhdGggc3R5bGU9InN0cm9rZS13aWR0aDouOThweDtmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kIiBkPSJNMjMuNSAyLjVoLTIydjE2aDEzdjQuMTdsNC4wNC00LjE3IDQuOTYtLjA0VjIuNXoiLz48cGF0aCBjbGFzcz0iY2xzLTIiIGQ9Ik0xMC44NSA4QTEwLjM4IDEwLjM4IDAgMCAxIDExIDkuNWMwIDIuNDctMS4yMSA0LTMgNHMtMy41LTItMy41LTQuNWE0LjE4IDQuMTggMCAwIDEgMC0xIi8+PHBhdGggY2xhc3M9ImNscy0yIiBkPSJNNS4yIDUuMDdhMy4yMiAzLjIyIDAgMCAxIDIuNS0xIDMuMTYgMy4xNiAwIDAgMSAyLjQgMSA2LjIyIDYuMjIgMCAwIDEgMS4zIDMuODEuNzQuNzQgMCAwIDAtLjQyIDBjMC0uMjQgMC0uNDQtLjA1LS42NmgwQTMgMyAwIDAgMSAxMCA2Ljl2LS4yNGwtLjIxLjEyQTkuNjIgOS42MiAwIDAgMSA0LjczIDhhLjI1LjI1IDAgMCAwLS4yMi4wOWMtLjEzLjE0LS4wOS4zNyAwIC42MXYuMThhLjg1Ljg1IDAgMCAwLS4zMiAwQTUuMzcgNS4zNyAwIDAgMSA1LjIgNS4wN1pNNC41MSA4LjkzYy0uMzUgMC0uNTcuMDUtLjYxLjQ0YTEuMTcgMS4xNyAwIDAgMCAuNzMgMS4zTTExIDguOTNjLjM2IDAgLjU3LjA1LjYyLjQ0YTEuMTcgMS4xNyAwIDAgMS0uNzQgMS4zTTYuMzEgMTQuMTN2LS44NE05LjI1IDEzLjE5di45NE0yLjQyIDE4Yy4xMy0xLjE1LjU4LTIuNTIgMS41OC0zYTE0LjcxIDE0LjcxIDAgMCAxIDIuMzEtLjgyTTEzLjUgMThjLS4xMy0xLjE1LS41MS0yLjUyLTEuNS0zcy0yLjUtMS0yLjUtMSIvPjxwYXRoIGNsYXNzPSJjbHMtMiIgZD0iTTkuMzQgMTQuMjJhMi4yMyAyLjIzIDAgMCAxLTEuNTYuNjEgMi4zMiAyLjMyIDAgMCAxLTEuNTUtLjU5TTIxLjUgNi41aC03TTIxLjUgOS41aC03TTE4LjUgMTIuNWgtNCIvPjwvZz48L3N2Zz4=)}.admonition.caution .admonition-title:before,.admonition.warning .admonition-title:before,.scylla-icon--warning{background-image:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PG1hc2sgaWQ9ImEiIG1hc2stdHlwZT0iYWxwaGEiIG1hc2tVbml0cz0idXNlclNwYWNlT25Vc2UiIHg9IjAiIHk9IjEiIHdpZHRoPSIyNCIgaGVpZ2h0PSIyMSI+PHBhdGggZD0iTTMuNSAyMmMtLjUgMC0xLS4xLTEuNS0uNEMuNiAyMC44LjEgMTguOS45IDE3LjVMOS40IDMuM2MuMy0uNC42LS44IDEtMSAuNy0uNCAxLjUtLjUgMi4zLS4zLjguMiAxLjQuNyAxLjkgMS40TDIzIDE3LjVjLjMuNS40IDEgLjQgMS41IDAgLjgtLjMgMS42LS45IDIuMS0uNS42LTEuMi45LTIgLjloLTE3Wm03LjYtMTcuNkwyLjcgMTguNWMtLjMuNS0uMSAxLjEuNCAxLjQuMS4xLjMuMS40LjFoMTYuOWMuMyAwIC41LS4xLjctLjMuMi0uMi4zLS40LjMtLjcgMC0uMiAwLS4zLS4xLS41TDEyLjkgNC40Yy0uMy0uNS0uOS0uNi0xLjQtLjQtLjIuMS0uMy4yLS40LjRaIiBmaWxsPSIjMDYxOTM4Ii8+PHBhdGggZD0iTTEyIDE0Yy0uNiAwLTEtLjQtMS0xVjljMC0uNi40LTEgMS0xczEgLjQgMSAxdjRjMCAuNi0uNCAxLTEgMVpNMTIgMThjLS4zIDAtLjUtLjEtLjctLjMtLjItLjItLjMtLjQtLjMtLjcgMC0uMSAwLS4zLjEtLjQuMS0uMS4xLS4yLjItLjMuMS0uMS4yLS4yLjMtLjIuMi0uMS40LS4xLjYtLjEuMSAwIC4xIDAgLjIuMS4xIDAgLjEgMCAuMi4xIDAgMCAuMS4xLjIuMS4xLjEuMi4yLjIuMyAwIC4xLjEuMy4xLjQgMCAuMy0uMS41LS4zLjctLjMuMi0uNS4zLS44LjNaIiBmaWxsPSIjMDYxOTM4Ii8+PC9tYXNrPjxnIG1hc2s9InVybCgjYSkiPjxwYXRoIGZpbGw9IiMwNjE5MzgiIGQ9Ik0wIDBoMjR2MjRIMHoiLz48L2c+PC9zdmc+)}.scylla-icon--webinars{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMntmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJDYWxxdWVfNCIgZGF0YS1uYW1lPSJDYWxxdWUgNCI+PHBhdGggc3R5bGU9InN0cm9rZS1taXRlcmxpbWl0OjEwO2ZpbGw6bm9uZTtzdHJva2U6Z3JheSIgZD0iTTEuNSA1LjVoMjJ2MTRoLTIyeiIvPjxwYXRoIGNsYXNzPSJjbHMtMiIgZD0iTTkuNDcgMjAuNXYxLjg4TTE1LjUgMjAuNXYyTTYuNSAyMi41aDEyIi8+PHBhdGggc3R5bGU9ImZpbGw6Z3JheSIgZD0ibTkgOSA3LjUgMy41M0w5IDE2Vjl6Ii8+PC9nPjwvc3ZnPg==)}.scylla-icon--whitepapers{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMntmaWxsOm5vbmU7c3Ryb2tlOmdyYXk7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJDYWxxdWVfNCIgZGF0YS1uYW1lPSJDYWxxdWUgNCI+PHBhdGggc3R5bGU9ImZpbGw6Z3JheSIgZD0iTTggOWg4djJIOHoiLz48cGF0aCBjbGFzcz0iY2xzLTIiIGQ9Ik0xNC4wNiAxLjUgMy41IDEuNTJWMjMuNWgxN1Y3bC02LjQ0LTUuNXoiLz48cGF0aCBkPSJNMTQuMzIgMS40MnYzLjM3YTIuMDYgMi4wNiAwIDAgMCAyLjA4IDIuMWgzLjY3IiBzdHlsZT0ic3Ryb2tlLW1pdGVybGltaXQ6MTA7ZmlsbDpub25lO3N0cm9rZTpncmF5Ii8+PHBhdGggY2xhc3M9ImNscy0yIiBkPSJNNi41IDE5LjVoNE0xMy41IDE5LjVoNE02LjUgMTYuNWg0TTEzLjUgMTYuNWg0TTYuNSAxMy41aDRNMTMuNSAxMy41aDQiLz48L2c+PC9zdmc+)}.scylla-icon--workshop{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNSAyNSI+PGRlZnM+PHN0eWxlPi5jbHMtMSwuY2xzLTJ7ZmlsbDpub25lO3N0cm9rZTojNGQ0ZDRkfS5jbHMtMXtzdHJva2UtbWl0ZXJsaW1pdDoxMH0uY2xzLTJ7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kfTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJDYWxxdWVfNCIgZGF0YS1uYW1lPSJDYWxxdWUgNCI+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNMS41IDUuNWgyMnYxNGgtMjJ6Ii8+PHBhdGggY2xhc3M9ImNscy0yIiBkPSJtOS41IDE5LjUtLjAzIDIuODhNMTUuNSAxOS41djNNNi41IDIyLjVoMTIiLz48cGF0aCBzdHlsZT0iZmlsbDojNGQ0ZDRkIiBkPSJtNCA4IDIgOCAuOTctMy45NUwxMSAxMiA0IDh6Ii8+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJtNi40NyAxMS4zNCAzLjM3IDQuMjgiLz48L2c+PC9zdmc+)}.button{background:transparent;border:1px solid #3a2d55;border-radius:4px;color:#3a2d55;display:inline;font-size:14px;letter-spacing:1px;line-height:21px;margin:0;padding:12px 14px}.button:focus,.button:hover{background:transparent;color:#3a2d55;text-decoration:none}.button--reverse{background:#fff;border:0}.button--reverse:focus,.button--reverse:hover{background:#fff}.tooltip{background-color:rgba(0,0,0,.56);border-radius:4px;font-size:12px;padding:6px}.tooltip:before{display:none!important}.tooltip:empty{display:none!important}.has-tip{border:0;cursor:pointer}.scylla-dropdown{color:#23263b;font-size:14px;line-height:20px}.scylla-dropdown a,.scylla-dropdown a:focus,.scylla-dropdown a:hover{color:#23263b!important;padding:0!important}.scylla-dropdown__item{font-size:16px;padding:15px}.scylla-dropdown__title{align-items:center;display:flex!important;position:static!important}.scylla-dropdown__title:after{display:none!important}.scylla-dropdown__title .chevron{min-height:5px;width:10px}.scylla-dropdown__content{background:#fff;border:0;border-radius:8px;box-shadow:0 4px 25px rgba(0,0,0,.15);font-size:16px;list-style:none;margin-top:15px;overflow:hidden;padding:16px 0;width:max-content}.scylla-dropdown__content li{padding:7px 16px}.scylla-dropdown__content .contents.local>ul>li a:before,.scylla-dropdown__content .secondary-side-nav__content li a:before,.scylla-dropdown__content li .admonition-title:before,.scylla-dropdown__content li .scylla-icon,.secondary-side-nav__content .scylla-dropdown__content li a:before{margin-right:10px}.enlarge-image{cursor:zoom-in}.enlarge-image-reveal{background:transparent;border:none;cursor:zoom-out;padding:0;text-align:center;width:fit-content}.enlarge-image-reveal img{background-color:#fff;padding:15px}.header{background-color:#fff;box-shadow:0 2px 22px rgba(74,93,166,.15);justify-content:space-between;padding:12.75px 0;position:fixed;width:100%;z-index:99}.header,.header-logo{align-items:center;display:flex}.header-logo{margin-left:20px;width:auto}.header-logo__img{width:110px}.header-logo__bar{background-color:#3a2d55;border-left:1px solid #3a2d55;height:11.56px;margin:0 7.5px;width:0}.header-logo__text{color:#3a2d55;font-size:10.11px;letter-spacing:.722408px;line-height:12px;text-transform:uppercase}.header-navigation{display:none}.header-button{display:none;margin-left:15px;text-transform:uppercase}.header-search-box{display:none;margin-right:20px;width:200px}.scylla-dropdown--header .scylla-dropdown__item{font-size:14px}.scylla-dropdown--header .scylla-dropdown__title{text-transform:uppercase}.scylla-dropdown--header .scylla-dropdown__title .chevron{margin-left:10px}.contents.local>ul>li .scylla-dropdown--header .scylla-dropdown__content a:before,.scylla-dropdown--header .scylla-dropdown__content .admonition-title:before,.scylla-dropdown--header .scylla-dropdown__content .contents.local>ul>li a:before,.scylla-dropdown--header .scylla-dropdown__content .scylla-icon,.scylla-dropdown--header .scylla-dropdown__content .secondary-side-nav__content li a:before,.secondary-side-nav__content li .scylla-dropdown--header .scylla-dropdown__content a:before{min-height:20px;width:20px}@media screen and (min-width:1024px){.header{padding:18px 0}.header-logo__img{width:152px}.header-logo__bar{height:16px;margin:0 10px}.header-logo__text{font-size:14px;letter-spacing:.722408px;line-height:12px;text-transform:uppercase}.header-navigation{align-items:center;display:flex;justify-content:center}.header-search-box{display:block}}@media screen and (min-width:1200px){.header-logo{margin-left:30px;width:357px}.header-search-box{margin-right:30px;max-width:20%;width:318px}.header-button{display:block}}.side-nav{background:#fff;display:none;height:100vh;left:0;line-height:24px;max-height:calc(100vh - 50px);overflow-y:auto;padding:20px 20px 0;position:fixed;top:50px;width:100%;z-index:100}.side-nav__title{font-weight:700;margin-bottom:20px}.side-nav__content{max-width:90%;overflow-wrap:break-word}.side-nav__content label,.side-nav__content label i{margin:0;padding:0}.side-nav__content label{font-size:inherit;line-height:1;margin-left:5px;max-height:5px}.collapsible-button .side-nav__content i,.side-nav__content .collapsible-button i,.side-nav__content .scylla-icon--expand{height:5px;vertical-align:top;width:10px}.side-nav__content .toctree-checkbox{display:none;position:absolute;right:20px}.side-nav__content .toctree-checkbox~ul{display:none;margin-right:20px}.side-nav__content .toctree-checkbox:checked~ul{display:block}.side-nav__content ul{margin:0}.side-nav__content a{color:#23263b}.side-nav__content a:hover{color:#3c4fe0;font-weight:400}.side-nav__content li{list-style:none;padding:0 0 24px}.side-nav__content li.has-children{align-items:center;display:flex;flex-wrap:wrap}.side-nav__content li.has-children>a{max-width:calc(100% - 15px)}.side-nav__content li.has-children.current{padding-bottom:20px}.side-nav__content li.has-children:hover>a{color:#3c4fe0}.side-nav__content li.has-children:hover>.toctree-checkbox~label i{filter:invert(38%) sepia(71%) saturate(6789%) hue-rotate(231deg) brightness(90%) contrast(95%)}.side-nav__content li.current-page>a{color:#3c4fe0}.side-nav__content li.current-page>.toctree-checkbox:checked~label i{filter:invert(38%) sepia(71%) saturate(6789%) hue-rotate(231deg) brightness(90%) contrast(95%)}.side-nav__content li ul{margin-top:18px;width:100%}.side-nav__content li ul li{border-left:1px solid #3c4fe0;padding:4px 0 4px 13px}.side-nav__content li ul ul{margin-left:0}.side-nav__content li .label{display:none}.side-nav__versions{max-width:90%}.side-nav__search,.side-nav__versions .dropdown{margin-bottom:20px}.collapsible-button{background:#fff;background-color:#fff;border:0;border-radius:8px;border-radius:50%;bottom:10px;box-shadow:0 4px 25px rgba(0,0,0,.15);cursor:pointer;display:none;font-size:0;left:300px;overflow:hidden;padding:13.5px;position:fixed}.collapsible-button i{height:16px;margin:0;width:16px}.side-nav--collapsed .collapsible-button{border-radius:0 20px 20px 0;left:-10px}.side-nav--collapsed .collapsible-button i{transform:rotate(180deg)}.layout--has-banner .side-nav{max-height:calc(100vh - 92.5px)}@media screen and (min-width:1024px){.side-nav{background-color:#f6f8ff;display:block;height:100%;left:auto;max-height:100vh;max-height:calc(100vh - 80px);padding:30px 40px;top:80px;width:286px;z-index:25}.side-nav__content{max-width:100%;padding-bottom:180px}.side-nav__search{display:none}.side-nav__versions{max-width:100%}.toctree-checkbox{right:40px}.layout--has-banner .side-nav{max-height:calc(100vh - 150px)}}@media screen and (min-width:1200px){.side-nav{width:357px}.side-nav--collapsed{background-color:transparent;padding-left:0;padding-right:0;width:126px}.side-nav--collapsed .side-nav-content{display:none}.collapsible-button{display:block}}.side-nav-toggle{cursor:pointer;display:block;margin-right:20px;position:relative;z-index:300}@media screen and (min-width:1024px){.side-nav-toggle{display:none}}.secondary-side-nav{display:none;height:100%;line-height:24px;padding:20px;width:100%}.secondary-side-nav__content{overflow-wrap:break-word}.secondary-side-nav__content ul{list-style:none;margin:0}.secondary-side-nav__content li{border-bottom:1px solid rgba(90,94,154,.1);display:none;padding:10px 0;word-break:break-word}.secondary-side-nav__content li:last-child{border:0}.secondary-side-nav__content li .label{display:none}.secondary-side-nav__content li a{align-items:baseline;color:#b3bac5;display:flex;font-size:14px}.secondary-side-nav__content li a:before{content:"";filter:invert(40%) sepia(11%) saturate(2157%) hue-rotate(198deg) brightness(89%) contrast(87%)!important;flex-shrink:0;margin-right:10px;min-height:10px;opacity:.5;width:6px}.secondary-side-nav__content li a.current,.secondary-side-nav__content li a:hover{color:#23263b;font-weight:400}.secondary-side-nav__content li a.current:before,.secondary-side-nav__content li a:hover:before{filter:brightness(0);opacity:1}.secondary-side-nav__content li a.current{font-weight:700}.secondary-side-nav__content>ul>li>ul>li{display:block}.secondary-side-nav__content>ul>li{border:0;display:block}.secondary-side-nav__content>ul>li>a{display:none}@media screen and (min-width:1200px){.secondary-side-nav{display:block;max-height:100vh;max-height:calc(100vh - 80px);overflow-y:auto;padding:60px 60px 60px 20px;position:fixed;top:80px;width:286px}.secondary-side-nav__content{padding-bottom:180px}.layout--has-banner .secondary-side-nav{max-height:calc(100vh - 150px)}}.layout{display:flex}.pre-content{align-items:center;display:flex;justify-content:space-between;margin-bottom:20px}.content{margin-top:50px;max-width:1440px;overflow-wrap:break-word;padding:20px;scroll-margin-top:50px;width:100%}.content .line-block,.content p{line-height:28px;margin-bottom:20px}.content ul{list-style:none}.content ul li:before{color:#b3bac5;content:"•";float:left;font-family:FontAwesome;font-size:20px;font-weight:700;margin-left:-1em;margin-top:-2px;width:1em}.content ul ul{list-style:circle}.content ul ul li:before{content:""}.content ol ol{list-style:lower-latin}.content img{margin-bottom:30px}.content section{margin-top:-50px;padding-top:50px}.content .inline-icon.fa-check{color:#42c4e6}.layout--full-width .content{max-width:100%;padding:0;width:100%}.layout--full-width .content .hero-wrapper,.layout--full-width .content .topics-grid{max-width:1190px}.layout--full-width .content.content--collapsed{margin-left:0}.layout--full-width:not(.layout--sidebar) .content{margin-left:0}.layout--has-banner .content{scroll-margin-top:92.5px}.layout--has-banner .content section{margin-top:-92.5px;padding-top:92.5px}.landing__content{padding:0 16px}@media screen and (min-width:1024px){.content{margin-left:286px;margin-top:80px;min-height:calc(100vh - 260px);padding-bottom:100px;scroll-margin-top:80px;width:calc(100% - 286px)}.content section{margin-top:-80px;padding-top:80px}}@media screen and (min-width:1200px){.content{margin-left:357px;padding:60px 40px 40px;width:calc(100% - 643px)}.content--collapsed{margin-left:126px;width:calc(100% - 412px)}.pre-content{margin-bottom:10px}.layout--has-banner .content{scroll-margin-top:150px}.layout--has-banner .content section{margin-top:-150px;padding-top:150px}.landing__content{padding:0 60px}.landing--floating .landing__content{position:relative;top:-70px}}.contents.local>ul{margin-bottom:30px;margin-left:0}.contents.local>ul>li{border-bottom:1px solid rgba(90,94,154,.1);padding:10px 0;word-break:break-word}.contents.local>ul>li:before{content:""}.contents.local>ul>li:last-child{border:0}.contents.local>ul>li ul{display:none}.contents.local>ul>li p{margin:0}.contents.local>ul>li a{font-size:14px}.contents.local>ul>li a:before{content:"";filter:invert(40%) sepia(11%) saturate(2157%) hue-rotate(198deg) brightness(89%) contrast(87%)!important;margin-right:10px;min-height:10px;opacity:.5;width:10px}.contents.local>ul>li a.current:before,.contents.local>ul>li a:hover:before{filter:brightness(0);opacity:1}.topic-title{color:rgba(35,38,59,.75);font-size:10px;letter-spacing:1.5px;margin-bottom:0;text-transform:uppercase}.notice{margin-top:40px}.footer{background-color:#fff;box-shadow:0 -4px 10px hsla(0,0%,82%,.25);padding:30px 0;position:relative;width:100%;z-index:50}.footer-group{margin:0 auto;max-width:1030px;padding:0 20px}.footer-top{align-items:center;border-bottom:1px solid rgba(0,0,0,.1);display:flex;flex-wrap:wrap;justify-content:space-between;padding-bottom:8px;text-align:center}.footer-logo{margin-bottom:30px;width:100%}.footer-logo img{float:left;height:36px}.footer-links{text-align:left}.footer-links__link{color:#333;font-size:12px;font-weight:500;letter-spacing:2.4px;margin-right:16px;text-transform:uppercase}.footer-actions{align-items:center;display:flex;justify-content:space-between;width:90px}.footer-actions__link{color:#000}.footer-actions__link img{height:23px}.footer-bottom{color:#979797;display:flex;flex-wrap:wrap;font-size:12px;font-style:normal;font-weight:400;justify-content:center;letter-spacing:1.4px;line-height:23px;padding:20px 0 10px;text-align:center;text-transform:uppercase}@media screen and (max-width:510px){.footer-links{margin-bottom:20px}}@media screen and (min-width:1024px){.footer{padding:30px 0}.footer-group{padding:0}.footer-top{padding-bottom:30px}.footer-logo{margin:0;width:auto}.footer-links{padding:0 40px}.footer-links__link{font-size:14px;margin-right:28px}.footer-actions{width:110px}.footer-actions__link img{height:28px}.footer-bottom .footer-bottom__copyright,.footer-bottom .footer-bottom__last-updated,.footer-bottom .footer-bottom__version{padding:0 10px}.footer-bottom .footer-bottom__copyright{border-left:none}}.not-found{background-color:#f6f8ff;height:100%;overflow:hidden}.not-found__icon{display:block;margin:40px auto;max-width:300px}.not-found__text{text-align:center}.not-found__text h1{font-size:60px;line-height:1}.not-found__text p{margin:30px 0;width:100%}.not-found__button{text-transform:uppercase}.admonition{border-radius:4px;box-shadow:0 4px 4px rgba(0,0,0,.12);color:rgba(0,0,0,.56);font-size:14px;line-height:20px;margin-bottom:30px;overflow:auto;padding:20px;position:relative}.admonition:before{bottom:0;content:" ";left:0;position:absolute;right:0;top:0;z-index:-1}.admonition-title{color:#23263b;margin-bottom:0!important}.admonition-title:before{content:"";margin-right:8px;min-height:24px;width:24px}.admonition p:not(.admonition-title){margin-bottom:0!important;margin-left:32px}.admonition.tip{border:1px solid #43a047}.admonition.tip:before{border-left:8px solid rgba(67,160,71,.4)}.admonition.tip .admonition-title:before{filter:invert(47%) sepia(11%) saturate(2286%) hue-rotate(73deg) brightness(109%) contrast(88%)}.admonition.note{border:1px solid #1976d2}.admonition.note:before{border-left:8px solid rgba(25,118,210,.4)}.admonition.note .admonition-title:before{filter:invert(44%) sepia(55%) saturate(2310%) hue-rotate(191deg) brightness(81%) contrast(103%)}.admonition.caution{border:1px solid #ffab00}.admonition.caution:before{border-left:8px solid rgba(255,171,0,.4)}.admonition.caution .admonition-title:before{filter:invert(77%) sepia(56%) saturate(3332%) hue-rotate(357deg) brightness(98%) contrast(108%)}.admonition.warning{border:1px solid #e74c3c}.admonition.warning:before{border-left:8px solid rgba(231,76,60,.4)}.admonition.warning .admonition-title:before{filter:invert(41%) sepia(42%) saturate(6427%) hue-rotate(343deg) brightness(99%) contrast(83%)}.breadcrumbs{margin-bottom:0;text-transform:uppercase}.breadcrumbs .bread__item,.breadcrumbs .bread__item:not(.bread__item--last):after,.breadcrumbs a{color:#23263b;font-size:12px;font-weight:400;letter-spacing:1.5px;line-height:2;margin:0;padding:0}.breadcrumbs .bread__item:before{display:none}.breadcrumbs .bread__item:not(.bread__item--last):after{content:"/";margin:0 5px;opacity:1;position:relative}.breadcrumbs .bread__highlight{color:#3c4fe0}.breadcrumbs .bread__highlight:hover{font-weight:700;text-decoration:none}code{background-color:#f7f8f9;border:none;border-radius:4px;color:#23263b;font-size:14px}code.download{background:none;color:#23263b}.highlight{background:transparent!important}.highlight pre{background-color:#f7f8f9;border-radius:8px;color:#23263b;font-size:14px;line-height:26px;margin-bottom:30px;overflow:auto;padding:16px}.highlight a.copybtn{right:1em;top:1em}.highlighttable{background-color:#f7f8f9;border-radius:16px;box-shadow:none}.highlighttable tbody{background-color:transparent;border:0}.highlighttable tbody td{padding:15px!important}.highlighttable tbody tr{border-top:none}.highlighttable .linenos{background-color:#f7f8f9;color:#5a7184;width:50px}.highlighttable .linenos span{line-height:26px}.highlighttable .highlight pre{background-color:transparent;margin:0;padding:0}.highlighttable .highlight a.copybtn{right:.2em;top:.2em}.hide-copy-button .copybtn{display:none}.sphinx_collapse__label{display:flex!important;flex-direction:row-reverse;font-size:medium;font-weight:700;justify-content:flex-end;margin-left:0!important}.sphinx_collapse__icon{margin-left:5px;margin-right:0}.sphinx_collapse__input:checked~.sphinx_collapse__label,.sphinx_collapse__label:hover{color:#3c4fe0}.sphinx_collapse__input:checked~.sphinx_collapse__label .sphinx_collapse__icon,.sphinx_collapse__label:hover .sphinx_collapse__icon{border-top-color:#3c4fe0}.sphinx_collapse__content{margin-top:10px}.contribute{margin:0 0 20px}.contribute__item{font-size:14px;list-style:none;padding-bottom:10px}.contribute__item .icon{margin-right:5px}.content-navigation{display:flex;justify-content:space-between;margin-top:40px}.navigation{max-width:50%;word-break:break-word}.navigation,.navigation__link{display:flex}.navigation__title{word-wrap:break-word;color:#23263b;font-size:12px;font-weight:500;letter-spacing:1.5px;line-height:24px;text-transform:uppercase}.navigation__title .colored{color:#42c4e6}.navigation__button{background:#fff;background-color:#fff;border:0;border-radius:8px;box-shadow:0 4px 25px rgba(0,0,0,.15);cursor:pointer;display:none;font-size:0;height:fit-content;overflow:hidden;padding:13.5px 16.5px}.navigation__button i{height:16px;margin:0;width:10px}.navigation--prev .navigation__title{margin-left:15px}.navigation--next .navigation__title{margin-right:15px;text-align:right}@media screen and (min-width:1200px){.navigation__title{display:inline-block}.navigation__button{display:block}.navigation--next .navigation__title{text-align:left}}.scylla-dropdown--versions .scylla-dropdown__item{background:#fff;border-radius:8px;box-shadow:0 28px 32px rgba(0,0,0,.06);width:100%}.scylla-dropdown--versions .scylla-dropdown__title{align-items:center;display:flex;justify-content:space-between}.scylla-dropdown--versions .scylla-dropdown__title .chevron{min-height:12px;transform:rotate(90deg);width:8px}@media screen and (min-width:1024px){.scylla-dropdown--versions .scylla-dropdown__item{box-shadow:none}}.feedback-container{font-size:16px;margin-top:40px;text-align:left}.feedback-container__title{font-weight:700;margin-bottom:5px!important}.feedback-container__button{background:#fff;border:0;border-radius:8px;box-shadow:0 4px 25px rgba(0,0,0,.15);cursor:pointer;margin:4px;overflow:hidden;padding:8px}.feedback-container__button.active{border:1px solid #3c4fe0}.feedback-container__icon{height:20px;width:20px}.feedback-container__message{font-size:16px;margin-top:10px}.hero{background:#f6f8ff;margin-bottom:30px;overflow:hidden;padding:30px 16px;text-align:left}.hero__title{font-size:28px;font-weight:500;line-height:38px;margin-bottom:14px;max-width:229px}.hero__text{font-size:16px;line-height:26px;max-width:343px}.hero__text a{border-bottom:1px dotted #23263b;color:#23263b}.hero__text p{margin-bottom:0!important}.hero__img{position:absolute;right:-18px;top:20px}.hero__img img{margin-bottom:0!important;width:124px}.hero__button{margin-top:20px;text-transform:uppercase}.hero__button .icon{margin-right:5px}.hero__search-box{box-shadow:0 4px 25px rgba(0,0,0,.02);margin-top:20px}.hero-wrapper{align-items:center;display:flex;justify-content:space-between;margin:0 auto;position:relative}@media screen and (min-width:640px){.hero{padding:60px 16px}.hero__title{font-size:32px;line-height:42px;max-width:482px}.hero__text{font-size:18px;line-height:26px;max-width:482px}.hero__img{display:block;position:static}.hero__img img{height:100%;width:295px}.hero .hero-wrapper{flex-direction:row-reverse}.hero .landing--floating .hero{padding:30px 16px 100px}}@media screen and (min-width:1024px){.hero{padding:60px}}.label{background-color:#23263b;border:0;border-radius:4px;color:#fff;font-size:inherit}.label--note{background-color:#1976d2}.label--tip{background-color:#43a047}.label--caution{background-color:#ffab00}.label--warning{background-color:#e74c3c}.last-updated{color:#4458a3;font-size:12px;letter-spacing:1.5px;margin:10px 0;text-transform:uppercase}.last-updated__icon{font-size:14px}@media screen and (min-width:1024px){.last-updated{float:right;margin:0}}.panel{border:0;border-radius:4px;margin-bottom:30px}.promo-banner{background-color:#4458a3;background-image:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTQ0MCIgaGVpZ2h0PSI3MCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48bWFzayBpZD0iYSIgbWFzay10eXBlPSJhbHBoYSIgbWFza1VuaXRzPSJ1c2VyU3BhY2VPblVzZSIgeD0iMCIgeT0iMCIgd2lkdGg9IjE0NDAiIGhlaWdodD0iNzAiPjxwYXRoIGZpbGw9IiM0NDU4QTMiIGQ9Ik0wIDBoMTQ0MHY3MEgweiIvPjwvbWFzaz48ZyBtYXNrPSJ1cmwoI2EpIiBmaWxsPSIjNTA2NEFFIj48cGF0aCBkPSJNLTE5MyAyMDEuODg0IDEuNS0xMzUgMzU3LjQzNiA3MC41bC0xOTQuNSAzMzYuODg0ek0xMDkyLjkyLTM4LjAwOSA5NzIuODAzLTI0Ni4wNTcgNDAyLjk5NiA4Mi45MiA1MjMuMTEzIDI5MC45N3oiLz48cGF0aCBkPSJtMTAzOC0zOC4wMDkgMTIwLjExNy0yMDguMDQ5IDU2OS44MDcgMzI4Ljk3OS0xMjAuMTE3IDIwOC4wNDl6Ii8+PC9nPjwvc3ZnPg==);background-position:50%;background-repeat:no-repeat;background-size:cover;display:none;overflow:hidden;position:fixed;top:0;width:100%;z-index:900}.promo-banner__icon{margin-right:15px}.promo-banner__icon img{height:40px}.promo-banner__title{color:#fff;font-size:12px;line-height:16px;margin-right:15px}.promo-banner__button{background:#fff;border-radius:4px;font-size:12px;min-width:max-content;padding:5px}.promo-banner__close{display:none;position:absolute;right:16px;top:16px}.contents.local>ul>li .promo-banner__close a:before,.promo-banner__close .admonition-title:before,.promo-banner__close .contents.local>ul>li a:before,.promo-banner__close .scylla-icon,.promo-banner__close .secondary-side-nav__content li a:before,.secondary-side-nav__content li .promo-banner__close a:before{filter:brightness(100%);height:34px;width:34px}.promo-banner__close:hover{cursor:pointer;filter:opacity(.8)}.promo-banner-wrapper{align-items:center;display:flex;justify-content:center;padding:5.85px 20px}@media(min-width:1024px){.promo-banner__title{font-size:18px;line-height:23px}.promo-banner__button{font-size:14px;padding:8.5px}.promo-banner__close{display:block}.promo-banner-wrapper{flex-direction:unset;padding:16px}}.custom-scroll-bar::-webkit-scrollbar{background-color:transparent;width:5px}.custom-scroll-bar::-webkit-scrollbar-thumb{background-color:#b3bac5;-webkit-border-radius:8px;border-radius:8px}.search-box{background:#f7f8f9;border-radius:4px;display:flex;padding:10px 15px}.search-box--hero{background-color:#fff;padding:12px 14px}.search-box:before{background-image:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZD0iTTEwLjUgMThhNy41IDcuNSAwIDEgMCAwLTE1IDcuNSA3LjUgMCAwIDAgMCAxNVpNMjEgMjFsLTUuMi01LjIiIHN0cm9rZT0iIzAwMCIgc3Ryb2tlLXdpZHRoPSIyIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiLz48L3N2Zz4=);background-repeat:no-repeat;background-size:contain;content:"";display:inline-block;filter:brightness(0);margin-top:2px;min-height:18px;min-width:18px;vertical-align:middle;width:20px}.search-box .er-dummy-search,.search-box .er-dummy-search-box,.search-box .er-search-form,.search-box ci-search,.search-box input{margin:0!important;width:100%!important}.search-box input{background:transparent!important;color:rgba(80,80,80,.5)!important;font-size:14px!important;padding:0!important}.search-box input::placeholder{color:rgba(80,80,80,.5)!important;opacity:1!important}.search-box button{display:none!important}.er_search_suggestions{background:#fff;border:0;border:0!important;border-radius:8px;box-shadow:0 4px 25px rgba(0,0,0,.15);overflow:hidden}.er_search_suggestions .er-search-result-box{border-width:1px!important;padding-bottom:10px!important;padding-top:10px!important}.er_search_suggestions .er-search-result-box:hover{background:#f7f8f9!important}.er_search_suggestions .er_more_result_btn{cursor:pointer}.er_search_suggestions h3{font-size:16px!important}.er-search-content{padding:20px!important}#er_search_results .er-search-result-box{display:block!important;margin:10px auto 0!important;width:100%!important}#er_search_results .text,#er_search_results .title a,#er_search_results .url a{max-width:100%!important}#search-result-input-form{max-width:800px!important}#er_search_button{text-align:center}#er_clear_input{right:0!important;top:0!important}.er-facet-header{background-color:transparent!important;border:0!important;padding:0 0 8px!important}.er-facet-val{padding:5px 2px!important}.er-facet-val input{display:block!important;margin:0}#er_search_pagination{margin-top:20px!important}#er_search_pagination li.er-paginator-list.er-active{border-bottom:0!important;font-weight:700}.er-suggestion-sm .er_search_input_dummy{margin:0!important}.er-suggestion-sm .er_search_button_dummy{border:0!important}#er_gcs_mobile_model_container .er-facet-values .er-facet-val{align-items:baseline}@media screen and (min-width:640px){.er-facets{display:none;max-width:300px!important;min-width:auto!important;width:auto!important}}@media screen and (min-width:1024px){.er-suggestions{left:15px!important}}@media screen and (min-width:1200px){.er-facets{display:block;position:fixed!important}.er-facet-count{display:none}}.sphinx-tabs{margin-bottom:30px}.sphinx-tabs-tab{border-bottom:1px solid rgba(0,0,0,.56);color:rgba(0,0,0,.56);cursor:pointer;font-size:14px;font-weight:500;line-height:13px;padding:20px 25px}.sphinx-tabs-tab[aria-selected=true]{border-bottom:2px solid #2196f3;color:#2196f3;padding-bottom:19px}.sphinx-tabs-panel{margin:30px 0}.table-wrapper{border:1px solid #e0e0e0;border-radius:4px;box-shadow:0 1px 2px rgba(0,0,0,.25);display:block;margin-bottom:30px;max-width:100%;overflow-x:auto}table{color:#000;font-size:14px;line-height:24px;margin:0;overflow:hidden}table p{margin:0!important}table caption{background:#f6f8ff;border-bottom:1px solid #e0e0e0;color:#23263b;padding:10px 25px}table thead{background:#f6f8ff;border:0;border-bottom:1px solid #4458a3}table thead th{color:#23263b;font-size:14px;font-weight:700}table td,table thead th{padding:20px 25px}table tbody tr{background-color:transparent!important;border-top:1px solid #e0e0e0;line-height:18px}table:not(.highlighttable) tbody tr:first-child{border-top:1px solid #4458a3}table.thead-border thead .row-odd th{color:#23263b}table.thead-border thead .row-even th{font-weight:400}table.thead-border thead th{border:1px solid #e0e0e0}table.thead-border thead tr:first-child th{border-top:none}table.thead-border thead tr:last-child th{border-bottom:none}table.thead-border thead tr th:first-child{border-left:none}table.thead-border thead tr th:last-child{border-right:none}.topics-grid{display:block;margin:0 auto 30px}.topics-grid__title{color:#23263b;font-size:24px;font-weight:700;line-height:32px;margin-bottom:6px}.topics-grid__text{color:#4458a3;font-size:18px;line-height:24px}.topics-grid--scrollable .hs{-ms-overflow-style:none;display:grid;grid-auto-flow:column;overflow-x:scroll;padding:20px 10px;scrollbar-width:none}.topics-grid--scrollable .hs::-webkit-scrollbar{display:none}.topics-grid--scrollable .hs .topic-box:last-child:after{content:"";width:20px}.topic-box{align-items:stretch;display:flex}.topic-box .card{background:#fff;border:1px solid transparent;border-radius:8px;box-shadow:0 4px 25px rgba(0,0,0,.15);display:flex;flex-direction:column;font-size:18px;margin:0 auto 30px;overflow:hidden;padding:20px;position:relative}.topic-box .card:hover{border:1px solid #4458a3;color:#23263b;font-weight:400}.topic-box__title{color:#23263b;font-size:16px;font-weight:700;line-height:24px;margin-bottom:0}.topic-box__title img{bottom:0;opacity:.3;position:absolute;right:0;top:0}.topic-box__body{color:#000;display:flex;flex-direction:column;flex-grow:1;max-width:80%}.topic-box__body .container{flex-grow:1;margin:0;padding:0}.topic-box__body .line-block,.topic-box__body p{font-size:16px;line-height:19px;margin-top:10px}.topic-box__anchor{color:#42c4e6;font-size:14px;font-weight:700;line-height:24px}.topic-box__icon{display:block;font-size:50px;margin-bottom:20px}.topic-box__icon i{filter:brightness(0);min-height:50px;width:100%}.topic-box__icon img{bottom:-12px;display:none;height:140px;margin:0;opacity:.3;position:absolute;right:-5px}.topic-box--product .card{box-shadow:none;padding:20px;text-align:center}.topic-box--product .card .topic-box__title{color:#23263b;font-size:14px}.topic-box--product .card .topic-box__body{display:flex;flex-direction:column;max-width:100%}.topic-box--product .card .topic-box__body .line-block,.topic-box--product .card .topic-box__body p{font-size:12px}.topic-box--product .card .topic-box__icon img{display:inline-block;max-height:84px;opacity:1;position:static}.topic-box--product .card:hover{background:#fff;border:0;border-radius:8px;box-shadow:0 4px 25px rgba(0,0,0,.15);overflow:hidden}@media screen and (max-width:1024px){.topics-grid--scrollable .topic-box{width:280px!important}.topic-box--product:nth-last-child(-n+2) .card{margin-bottom:0}}@media screen and (min-width:1024px){.topics-grid{margin-bottom:10px}.topics-grid__text{font-size:16px}.topics-grid--scrollable .hs{display:flex;overflow-x:initial;padding:0}.topics-grid--scrollable .hs .topic-box:last-child:after{display:none}.topic-box .card{margin-bottom:60px;padding:45px 30px}.topic-box__title{font-size:20px;line-height:32px}.topic-box__body .line-block,.topic-box__body p{font-size:18px;line-height:26px}.topic-box__anchor{font-size:20px;line-height:26px}.topic-box .topic-box__icon img{display:inline-block}.topic-box--product .card{padding:20px}.topic-box--product .card .topic-box__title{font-size:18px;line-height:24px}.topic-box--product .card .topic-box__body .line-block,.topic-box--product .card .topic-box__body p{font-size:14px}.topic-box--product .card .topic-box__icon img{max-height:111px}.landing .topics-grid--products{margin-bottom:40px}} \ No newline at end of file diff --git a/stable/_static/doctools.js b/stable/_static/doctools.js new file mode 100644 index 0000000000..8cbf1b161a --- /dev/null +++ b/stable/_static/doctools.js @@ -0,0 +1,323 @@ +/* + * doctools.js + * ~~~~~~~~~~~ + * + * Sphinx JavaScript utilities for all documentation. + * + * :copyright: Copyright 2007-2021 by the Sphinx team, see AUTHORS. + * :license: BSD, see LICENSE for details. + * + */ + +/** + * select a different prefix for underscore + */ +$u = _.noConflict(); + +/** + * make the code below compatible with browsers without + * an installed firebug like debugger +if (!window.console || !console.firebug) { + var names = ["log", "debug", "info", "warn", "error", "assert", "dir", + "dirxml", "group", "groupEnd", "time", "timeEnd", "count", "trace", + "profile", "profileEnd"]; + window.console = {}; + for (var i = 0; i < names.length; ++i) + window.console[names[i]] = function() {}; +} + */ + +/** + * small helper function to urldecode strings + * + * See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/decodeURIComponent#Decoding_query_parameters_from_a_URL + */ +jQuery.urldecode = function(x) { + if (!x) { + return x + } + return decodeURIComponent(x.replace(/\+/g, ' ')); +}; + +/** + * small helper function to urlencode strings + */ +jQuery.urlencode = encodeURIComponent; + +/** + * This function returns the parsed url parameters of the + * current request. Multiple values per key are supported, + * it will always return arrays of strings for the value parts. + */ +jQuery.getQueryParameters = function(s) { + if (typeof s === 'undefined') + s = document.location.search; + var parts = s.substr(s.indexOf('?') + 1).split('&'); + var result = {}; + for (var i = 0; i < parts.length; i++) { + var tmp = parts[i].split('=', 2); + var key = jQuery.urldecode(tmp[0]); + var value = jQuery.urldecode(tmp[1]); + if (key in result) + result[key].push(value); + else + result[key] = [value]; + } + return result; +}; + +/** + * highlight a given string on a jquery object by wrapping it in + * span elements with the given class name. + */ +jQuery.fn.highlightText = function(text, className) { + function highlight(node, addItems) { + if (node.nodeType === 3) { + var val = node.nodeValue; + var pos = val.toLowerCase().indexOf(text); + if (pos >= 0 && + !jQuery(node.parentNode).hasClass(className) && + !jQuery(node.parentNode).hasClass("nohighlight")) { + var span; + var isInSVG = jQuery(node).closest("body, svg, foreignObject").is("svg"); + if (isInSVG) { + span = document.createElementNS("http://www.w3.org/2000/svg", "tspan"); + } else { + span = document.createElement("span"); + span.className = className; + } + span.appendChild(document.createTextNode(val.substr(pos, text.length))); + node.parentNode.insertBefore(span, node.parentNode.insertBefore( + document.createTextNode(val.substr(pos + text.length)), + node.nextSibling)); + node.nodeValue = val.substr(0, pos); + if (isInSVG) { + var rect = document.createElementNS("http://www.w3.org/2000/svg", "rect"); + var bbox = node.parentElement.getBBox(); + rect.x.baseVal.value = bbox.x; + rect.y.baseVal.value = bbox.y; + rect.width.baseVal.value = bbox.width; + rect.height.baseVal.value = bbox.height; + rect.setAttribute('class', className); + addItems.push({ + "parent": node.parentNode, + "target": rect}); + } + } + } + else if (!jQuery(node).is("button, select, textarea")) { + jQuery.each(node.childNodes, function() { + highlight(this, addItems); + }); + } + } + var addItems = []; + var result = this.each(function() { + highlight(this, addItems); + }); + for (var i = 0; i < addItems.length; ++i) { + jQuery(addItems[i].parent).before(addItems[i].target); + } + return result; +}; + +/* + * backward compatibility for jQuery.browser + * This will be supported until firefox bug is fixed. + */ +if (!jQuery.browser) { + jQuery.uaMatch = function(ua) { + ua = ua.toLowerCase(); + + var match = /(chrome)[ \/]([\w.]+)/.exec(ua) || + /(webkit)[ \/]([\w.]+)/.exec(ua) || + /(opera)(?:.*version|)[ \/]([\w.]+)/.exec(ua) || + /(msie) ([\w.]+)/.exec(ua) || + ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec(ua) || + []; + + return { + browser: match[ 1 ] || "", + version: match[ 2 ] || "0" + }; + }; + jQuery.browser = {}; + jQuery.browser[jQuery.uaMatch(navigator.userAgent).browser] = true; +} + +/** + * Small JavaScript module for the documentation. + */ +var Documentation = { + + init : function() { + this.fixFirefoxAnchorBug(); + this.highlightSearchWords(); + this.initIndexTable(); + if (DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS) { + this.initOnKeyListeners(); + } + }, + + /** + * i18n support + */ + TRANSLATIONS : {}, + PLURAL_EXPR : function(n) { return n === 1 ? 0 : 1; }, + LOCALE : 'unknown', + + // gettext and ngettext don't access this so that the functions + // can safely bound to a different name (_ = Documentation.gettext) + gettext : function(string) { + var translated = Documentation.TRANSLATIONS[string]; + if (typeof translated === 'undefined') + return string; + return (typeof translated === 'string') ? translated : translated[0]; + }, + + ngettext : function(singular, plural, n) { + var translated = Documentation.TRANSLATIONS[singular]; + if (typeof translated === 'undefined') + return (n == 1) ? singular : plural; + return translated[Documentation.PLURALEXPR(n)]; + }, + + addTranslations : function(catalog) { + for (var key in catalog.messages) + this.TRANSLATIONS[key] = catalog.messages[key]; + this.PLURAL_EXPR = new Function('n', 'return +(' + catalog.plural_expr + ')'); + this.LOCALE = catalog.locale; + }, + + /** + * add context elements like header anchor links + */ + addContextElements : function() { + $('div[id] > :header:first').each(function() { + $('\u00B6'). + attr('href', '#' + this.id). + attr('title', _('Permalink to this headline')). + appendTo(this); + }); + $('dt[id]').each(function() { + $('\u00B6'). + attr('href', '#' + this.id). + attr('title', _('Permalink to this definition')). + appendTo(this); + }); + }, + + /** + * workaround a firefox stupidity + * see: https://bugzilla.mozilla.org/show_bug.cgi?id=645075 + */ + fixFirefoxAnchorBug : function() { + if (document.location.hash && $.browser.mozilla) + window.setTimeout(function() { + document.location.href += ''; + }, 10); + }, + + /** + * highlight the search words provided in the url in the text + */ + highlightSearchWords : function() { + var params = $.getQueryParameters(); + var terms = (params.highlight) ? params.highlight[0].split(/\s+/) : []; + if (terms.length) { + var body = $('div.body'); + if (!body.length) { + body = $('body'); + } + window.setTimeout(function() { + $.each(terms, function() { + body.highlightText(this.toLowerCase(), 'highlighted'); + }); + }, 10); + $('') + .appendTo($('#searchbox')); + } + }, + + /** + * init the domain index toggle buttons + */ + initIndexTable : function() { + var togglers = $('img.toggler').click(function() { + var src = $(this).attr('src'); + var idnum = $(this).attr('id').substr(7); + $('tr.cg-' + idnum).toggle(); + if (src.substr(-9) === 'minus.png') + $(this).attr('src', src.substr(0, src.length-9) + 'plus.png'); + else + $(this).attr('src', src.substr(0, src.length-8) + 'minus.png'); + }).css('display', ''); + if (DOCUMENTATION_OPTIONS.COLLAPSE_INDEX) { + togglers.click(); + } + }, + + /** + * helper function to hide the search marks again + */ + hideSearchWords : function() { + $('#searchbox .highlight-link').fadeOut(300); + $('span.highlighted').removeClass('highlighted'); + }, + + /** + * make the url absolute + */ + makeURL : function(relativeURL) { + return DOCUMENTATION_OPTIONS.URL_ROOT + '/' + relativeURL; + }, + + /** + * get the current relative url + */ + getCurrentURL : function() { + var path = document.location.pathname; + var parts = path.split(/\//); + $.each(DOCUMENTATION_OPTIONS.URL_ROOT.split(/\//), function() { + if (this === '..') + parts.pop(); + }); + var url = parts.join('/'); + return path.substring(url.lastIndexOf('/') + 1, path.length - 1); + }, + + initOnKeyListeners: function() { + $(document).keydown(function(event) { + var activeElementType = document.activeElement.tagName; + // don't navigate when in search box, textarea, dropdown or button + if (activeElementType !== 'TEXTAREA' && activeElementType !== 'INPUT' && activeElementType !== 'SELECT' + && activeElementType !== 'BUTTON' && !event.altKey && !event.ctrlKey && !event.metaKey + && !event.shiftKey) { + switch (event.keyCode) { + case 37: // left + var prevHref = $('link[rel="prev"]').prop('href'); + if (prevHref) { + window.location.href = prevHref; + return false; + } + break; + case 39: // right + var nextHref = $('link[rel="next"]').prop('href'); + if (nextHref) { + window.location.href = nextHref; + return false; + } + break; + } + } + }); + } +}; + +// quick alias for translations +_ = Documentation.gettext; + +$(document).ready(function() { + Documentation.init(); +}); diff --git a/stable/_static/documentation_options.js b/stable/_static/documentation_options.js new file mode 100644 index 0000000000..c23c68c3e7 --- /dev/null +++ b/stable/_static/documentation_options.js @@ -0,0 +1,12 @@ +var DOCUMENTATION_OPTIONS = { + URL_ROOT: document.getElementById("documentation_options").getAttribute('data-url_root'), + VERSION: '3.26.2', + LANGUAGE: 'None', + COLLAPSE_INDEX: false, + BUILDER: 'html', + FILE_SUFFIX: '.html', + LINK_SUFFIX: '.html', + HAS_SOURCE: true, + SOURCELINK_SUFFIX: '.txt', + NAVIGATION_WITH_KEYS: false +}; \ No newline at end of file diff --git a/stable/_static/file.png b/stable/_static/file.png new file mode 100644 index 0000000000..a858a410e4 Binary files /dev/null and b/stable/_static/file.png differ diff --git a/stable/_static/img/banner-background.svg b/stable/_static/img/banner-background.svg new file mode 100644 index 0000000000..f8520d5b3e --- /dev/null +++ b/stable/_static/img/banner-background.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/stable/_static/img/favicon-228x228.png b/stable/_static/img/favicon-228x228.png new file mode 100644 index 0000000000..f30770c7ed Binary files /dev/null and b/stable/_static/img/favicon-228x228.png differ diff --git a/stable/_static/img/favicon-32x32.png b/stable/_static/img/favicon-32x32.png new file mode 100644 index 0000000000..aae1708f26 Binary files /dev/null and b/stable/_static/img/favicon-32x32.png differ diff --git a/stable/_static/img/favicon.ico b/stable/_static/img/favicon.ico new file mode 100644 index 0000000000..6c7484f082 Binary files /dev/null and b/stable/_static/img/favicon.ico differ diff --git a/stable/_static/img/icons/icon-about-team.svg b/stable/_static/img/icons/icon-about-team.svg new file mode 100644 index 0000000000..5448c7f007 --- /dev/null +++ b/stable/_static/img/icons/icon-about-team.svg @@ -0,0 +1 @@ +icon-about-team diff --git a/stable/_static/img/icons/icon-about-us-m.svg b/stable/_static/img/icons/icon-about-us-m.svg new file mode 100644 index 0000000000..09107d9520 --- /dev/null +++ b/stable/_static/img/icons/icon-about-us-m.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/stable/_static/img/icons/icon-about-us.svg b/stable/_static/img/icons/icon-about-us.svg new file mode 100644 index 0000000000..1b1fcc83e3 --- /dev/null +++ b/stable/_static/img/icons/icon-about-us.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/stable/_static/img/icons/icon-alternator.svg b/stable/_static/img/icons/icon-alternator.svg new file mode 100644 index 0000000000..7c2b4ebae0 --- /dev/null +++ b/stable/_static/img/icons/icon-alternator.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/stable/_static/img/icons/icon-apps.svg b/stable/_static/img/icons/icon-apps.svg new file mode 100644 index 0000000000..7e93612026 --- /dev/null +++ b/stable/_static/img/icons/icon-apps.svg @@ -0,0 +1 @@ + diff --git a/stable/_static/img/icons/icon-architecture.svg b/stable/_static/img/icons/icon-architecture.svg new file mode 100644 index 0000000000..67ebbc2f38 --- /dev/null +++ b/stable/_static/img/icons/icon-architecture.svg @@ -0,0 +1 @@ +icon-architecture diff --git a/stable/_static/img/icons/icon-benchmarks.svg b/stable/_static/img/icons/icon-benchmarks.svg new file mode 100644 index 0000000000..e1ce2c1d78 --- /dev/null +++ b/stable/_static/img/icons/icon-benchmarks.svg @@ -0,0 +1 @@ +icon-benchmarks diff --git a/stable/_static/img/icons/icon-blog.svg b/stable/_static/img/icons/icon-blog.svg new file mode 100644 index 0000000000..f4096cbf11 --- /dev/null +++ b/stable/_static/img/icons/icon-blog.svg @@ -0,0 +1 @@ +icon-blog2 diff --git a/stable/_static/img/icons/icon-careers.svg b/stable/_static/img/icons/icon-careers.svg new file mode 100644 index 0000000000..2a7c6ea0b7 --- /dev/null +++ b/stable/_static/img/icons/icon-careers.svg @@ -0,0 +1 @@ +icon-careers diff --git a/stable/_static/img/icons/icon-chevron-left.svg b/stable/_static/img/icons/icon-chevron-left.svg new file mode 100644 index 0000000000..3afa25c481 --- /dev/null +++ b/stable/_static/img/icons/icon-chevron-left.svg @@ -0,0 +1,3 @@ + + + diff --git a/stable/_static/img/icons/icon-chevron-right.svg b/stable/_static/img/icons/icon-chevron-right.svg new file mode 100644 index 0000000000..44eb829cdc --- /dev/null +++ b/stable/_static/img/icons/icon-chevron-right.svg @@ -0,0 +1,3 @@ + + + diff --git a/stable/_static/img/icons/icon-circe.svg b/stable/_static/img/icons/icon-circe.svg new file mode 100644 index 0000000000..875e421670 --- /dev/null +++ b/stable/_static/img/icons/icon-circe.svg @@ -0,0 +1 @@ + diff --git a/stable/_static/img/icons/icon-clock.svg b/stable/_static/img/icons/icon-clock.svg new file mode 100644 index 0000000000..8c92469808 --- /dev/null +++ b/stable/_static/img/icons/icon-clock.svg @@ -0,0 +1 @@ + diff --git a/stable/_static/img/icons/icon-close.svg b/stable/_static/img/icons/icon-close.svg new file mode 100644 index 0000000000..d1162b73e7 --- /dev/null +++ b/stable/_static/img/icons/icon-close.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/stable/_static/img/icons/icon-cloud-docs.svg b/stable/_static/img/icons/icon-cloud-docs.svg new file mode 100644 index 0000000000..a9069bb6e5 --- /dev/null +++ b/stable/_static/img/icons/icon-cloud-docs.svg @@ -0,0 +1 @@ + diff --git a/stable/_static/img/icons/icon-cloud.svg b/stable/_static/img/icons/icon-cloud.svg new file mode 100644 index 0000000000..cfb2318dae --- /dev/null +++ b/stable/_static/img/icons/icon-cloud.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/stable/_static/img/icons/icon-comparison.svg b/stable/_static/img/icons/icon-comparison.svg new file mode 100644 index 0000000000..49d809a5df --- /dev/null +++ b/stable/_static/img/icons/icon-comparison.svg @@ -0,0 +1 @@ +icon-comparison diff --git a/stable/_static/img/icons/icon-contact-us.svg b/stable/_static/img/icons/icon-contact-us.svg new file mode 100644 index 0000000000..9df3145dd2 --- /dev/null +++ b/stable/_static/img/icons/icon-contact-us.svg @@ -0,0 +1 @@ +icon-contact-us diff --git a/stable/_static/img/icons/icon-developers-blog.svg b/stable/_static/img/icons/icon-developers-blog.svg new file mode 100644 index 0000000000..ee804197a0 --- /dev/null +++ b/stable/_static/img/icons/icon-developers-blog.svg @@ -0,0 +1 @@ +icon-developers-blog diff --git a/stable/_static/img/icons/icon-docs.svg b/stable/_static/img/icons/icon-docs.svg new file mode 100644 index 0000000000..5501492f3e --- /dev/null +++ b/stable/_static/img/icons/icon-docs.svg @@ -0,0 +1 @@ +icon-docs diff --git a/stable/_static/img/icons/icon-enterprise-m.svg b/stable/_static/img/icons/icon-enterprise-m.svg new file mode 100644 index 0000000000..97be900b50 --- /dev/null +++ b/stable/_static/img/icons/icon-enterprise-m.svg @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/stable/_static/img/icons/icon-enterprise.svg b/stable/_static/img/icons/icon-enterprise.svg new file mode 100644 index 0000000000..ee1ac26283 --- /dev/null +++ b/stable/_static/img/icons/icon-enterprise.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/stable/_static/img/icons/icon-events.svg b/stable/_static/img/icons/icon-events.svg new file mode 100644 index 0000000000..ba5f211864 --- /dev/null +++ b/stable/_static/img/icons/icon-events.svg @@ -0,0 +1 @@ +icon-events diff --git a/stable/_static/img/icons/icon-exclamation.svg b/stable/_static/img/icons/icon-exclamation.svg new file mode 100644 index 0000000000..a7eb4b77a4 --- /dev/null +++ b/stable/_static/img/icons/icon-exclamation.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/stable/_static/img/icons/icon-expand.svg b/stable/_static/img/icons/icon-expand.svg new file mode 100644 index 0000000000..3806565367 --- /dev/null +++ b/stable/_static/img/icons/icon-expand.svg @@ -0,0 +1,50 @@ + + + + + + + + + diff --git a/stable/_static/img/icons/icon-forum.svg b/stable/_static/img/icons/icon-forum.svg new file mode 100644 index 0000000000..37a709f7a8 --- /dev/null +++ b/stable/_static/img/icons/icon-forum.svg @@ -0,0 +1 @@ + diff --git a/stable/_static/img/icons/icon-getting-started.svg b/stable/_static/img/icons/icon-getting-started.svg new file mode 100644 index 0000000000..702500be40 --- /dev/null +++ b/stable/_static/img/icons/icon-getting-started.svg @@ -0,0 +1 @@ + diff --git a/stable/_static/img/icons/icon-glossary.svg b/stable/_static/img/icons/icon-glossary.svg new file mode 100644 index 0000000000..e8329c2afe --- /dev/null +++ b/stable/_static/img/icons/icon-glossary.svg @@ -0,0 +1 @@ + diff --git a/stable/_static/img/icons/icon-home.svg b/stable/_static/img/icons/icon-home.svg new file mode 100644 index 0000000000..f0b9c25419 --- /dev/null +++ b/stable/_static/img/icons/icon-home.svg @@ -0,0 +1 @@ + diff --git a/stable/_static/img/icons/icon-infoworld.svg b/stable/_static/img/icons/icon-infoworld.svg new file mode 100644 index 0000000000..906e87279c --- /dev/null +++ b/stable/_static/img/icons/icon-infoworld.svg @@ -0,0 +1 @@ +icon-infoworld diff --git a/stable/_static/img/icons/icon-integrations.svg b/stable/_static/img/icons/icon-integrations.svg new file mode 100644 index 0000000000..1ef0920d49 --- /dev/null +++ b/stable/_static/img/icons/icon-integrations.svg @@ -0,0 +1 @@ + diff --git a/stable/_static/img/icons/icon-knowledge-base.svg b/stable/_static/img/icons/icon-knowledge-base.svg new file mode 100644 index 0000000000..884451270d --- /dev/null +++ b/stable/_static/img/icons/icon-knowledge-base.svg @@ -0,0 +1 @@ + diff --git a/stable/_static/img/icons/icon-less.svg b/stable/_static/img/icons/icon-less.svg new file mode 100644 index 0000000000..3094127dec --- /dev/null +++ b/stable/_static/img/icons/icon-less.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/stable/_static/img/icons/icon-live-test.svg b/stable/_static/img/icons/icon-live-test.svg new file mode 100644 index 0000000000..dcb5916c26 --- /dev/null +++ b/stable/_static/img/icons/icon-live-test.svg @@ -0,0 +1 @@ +icon-live-test diff --git a/stable/_static/img/icons/icon-mail-list.svg b/stable/_static/img/icons/icon-mail-list.svg new file mode 100644 index 0000000000..0e6192a352 --- /dev/null +++ b/stable/_static/img/icons/icon-mail-list.svg @@ -0,0 +1 @@ + diff --git a/stable/_static/img/icons/icon-manager.svg b/stable/_static/img/icons/icon-manager.svg new file mode 100644 index 0000000000..02b4e425be --- /dev/null +++ b/stable/_static/img/icons/icon-manager.svg @@ -0,0 +1 @@ +icon-manager diff --git a/stable/_static/img/icons/icon-memory-management.svg b/stable/_static/img/icons/icon-memory-management.svg new file mode 100644 index 0000000000..e34eb4504f --- /dev/null +++ b/stable/_static/img/icons/icon-memory-management.svg @@ -0,0 +1 @@ +icon-memory-management diff --git a/stable/_static/img/icons/icon-modeling.svg b/stable/_static/img/icons/icon-modeling.svg new file mode 100644 index 0000000000..97fa3a0e21 --- /dev/null +++ b/stable/_static/img/icons/icon-modeling.svg @@ -0,0 +1 @@ + diff --git a/stable/_static/img/icons/icon-monitoring.svg b/stable/_static/img/icons/icon-monitoring.svg new file mode 100644 index 0000000000..80b3787f66 --- /dev/null +++ b/stable/_static/img/icons/icon-monitoring.svg @@ -0,0 +1 @@ +icon-monitoring diff --git a/stable/_static/img/icons/icon-networking.svg b/stable/_static/img/icons/icon-networking.svg new file mode 100644 index 0000000000..40a3fd5f6f --- /dev/null +++ b/stable/_static/img/icons/icon-networking.svg @@ -0,0 +1 @@ +icon-networking diff --git a/stable/_static/img/icons/icon-news.svg b/stable/_static/img/icons/icon-news.svg new file mode 100644 index 0000000000..a952b59937 --- /dev/null +++ b/stable/_static/img/icons/icon-news.svg @@ -0,0 +1 @@ +icon-news diff --git a/stable/_static/img/icons/icon-newsletter.svg b/stable/_static/img/icons/icon-newsletter.svg new file mode 100644 index 0000000000..5b8d47eb15 --- /dev/null +++ b/stable/_static/img/icons/icon-newsletter.svg @@ -0,0 +1 @@ +icon-newsletter diff --git a/stable/_static/img/icons/icon-nsql-guides.svg b/stable/_static/img/icons/icon-nsql-guides.svg new file mode 100644 index 0000000000..60ebab3795 --- /dev/null +++ b/stable/_static/img/icons/icon-nsql-guides.svg @@ -0,0 +1 @@ +icon-nsql-guides diff --git a/stable/_static/img/icons/icon-open-source.svg b/stable/_static/img/icons/icon-open-source.svg new file mode 100644 index 0000000000..98c2ea7d5b --- /dev/null +++ b/stable/_static/img/icons/icon-open-source.svg @@ -0,0 +1 @@ +icon-open-source diff --git a/stable/_static/img/icons/icon-operator.svg b/stable/_static/img/icons/icon-operator.svg new file mode 100644 index 0000000000..bb7d8d3ea8 --- /dev/null +++ b/stable/_static/img/icons/icon-operator.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/stable/_static/img/icons/icon-overview.svg b/stable/_static/img/icons/icon-overview.svg new file mode 100644 index 0000000000..515c1528a2 --- /dev/null +++ b/stable/_static/img/icons/icon-overview.svg @@ -0,0 +1 @@ +icon-overview diff --git a/stable/_static/img/icons/icon-partners.svg b/stable/_static/img/icons/icon-partners.svg new file mode 100644 index 0000000000..d0146fc497 --- /dev/null +++ b/stable/_static/img/icons/icon-partners.svg @@ -0,0 +1 @@ +icon-partners diff --git a/stable/_static/img/icons/icon-plus.svg b/stable/_static/img/icons/icon-plus.svg new file mode 100644 index 0000000000..5757435085 --- /dev/null +++ b/stable/_static/img/icons/icon-plus.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/stable/_static/img/icons/icon-pricing.svg b/stable/_static/img/icons/icon-pricing.svg new file mode 100644 index 0000000000..74b01db168 --- /dev/null +++ b/stable/_static/img/icons/icon-pricing.svg @@ -0,0 +1 @@ +icon-pricing$ diff --git a/stable/_static/img/icons/icon-release-notes.svg b/stable/_static/img/icons/icon-release-notes.svg new file mode 100644 index 0000000000..80c490c7b0 --- /dev/null +++ b/stable/_static/img/icons/icon-release-notes.svg @@ -0,0 +1 @@ +icon-release-notes diff --git a/stable/_static/img/icons/icon-resource-center.svg b/stable/_static/img/icons/icon-resource-center.svg new file mode 100644 index 0000000000..6e3ab08e79 --- /dev/null +++ b/stable/_static/img/icons/icon-resource-center.svg @@ -0,0 +1 @@ +icon-ressource-center diff --git a/stable/_static/img/icons/icon-roadmap.svg b/stable/_static/img/icons/icon-roadmap.svg new file mode 100644 index 0000000000..c8cbf67c8c --- /dev/null +++ b/stable/_static/img/icons/icon-roadmap.svg @@ -0,0 +1 @@ +icon-roadmap-4 diff --git a/stable/_static/img/icons/icon-search.svg b/stable/_static/img/icons/icon-search.svg new file mode 100644 index 0000000000..81aae93eef --- /dev/null +++ b/stable/_static/img/icons/icon-search.svg @@ -0,0 +1,4 @@ + + + + diff --git a/stable/_static/img/icons/icon-slack.svg b/stable/_static/img/icons/icon-slack.svg new file mode 100644 index 0000000000..fc164ea1e7 --- /dev/null +++ b/stable/_static/img/icons/icon-slack.svg @@ -0,0 +1 @@ + diff --git a/stable/_static/img/icons/icon-stack-overflow.svg b/stable/_static/img/icons/icon-stack-overflow.svg new file mode 100644 index 0000000000..bebe9b8274 --- /dev/null +++ b/stable/_static/img/icons/icon-stack-overflow.svg @@ -0,0 +1,4 @@ + + + + diff --git a/stable/_static/img/icons/icon-summit.svg b/stable/_static/img/icons/icon-summit.svg new file mode 100644 index 0000000000..4b900bd0c0 --- /dev/null +++ b/stable/_static/img/icons/icon-summit.svg @@ -0,0 +1 @@ + diff --git a/stable/_static/img/icons/icon-support.svg b/stable/_static/img/icons/icon-support.svg new file mode 100644 index 0000000000..a4228b34e8 --- /dev/null +++ b/stable/_static/img/icons/icon-support.svg @@ -0,0 +1 @@ +icon-support diff --git a/stable/_static/img/icons/icon-tech-talks.svg b/stable/_static/img/icons/icon-tech-talks.svg new file mode 100644 index 0000000000..df42b5522b --- /dev/null +++ b/stable/_static/img/icons/icon-tech-talks.svg @@ -0,0 +1 @@ +icon-tech-talks diff --git a/stable/_static/img/icons/icon-testing.svg b/stable/_static/img/icons/icon-testing.svg new file mode 100644 index 0000000000..2fe54efdbc --- /dev/null +++ b/stable/_static/img/icons/icon-testing.svg @@ -0,0 +1 @@ +icon-testing diff --git a/stable/_static/img/icons/icon-thumbs-down.svg b/stable/_static/img/icons/icon-thumbs-down.svg new file mode 100644 index 0000000000..3e7bcd6d90 --- /dev/null +++ b/stable/_static/img/icons/icon-thumbs-down.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/stable/_static/img/icons/icon-thumbs-up.svg b/stable/_static/img/icons/icon-thumbs-up.svg new file mode 100644 index 0000000000..226c44d853 --- /dev/null +++ b/stable/_static/img/icons/icon-thumbs-up.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/stable/_static/img/icons/icon-tip.svg b/stable/_static/img/icons/icon-tip.svg new file mode 100644 index 0000000000..bf7aa6af84 --- /dev/null +++ b/stable/_static/img/icons/icon-tip.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/stable/_static/img/icons/icon-training.svg b/stable/_static/img/icons/icon-training.svg new file mode 100644 index 0000000000..08b95a88ed --- /dev/null +++ b/stable/_static/img/icons/icon-training.svg @@ -0,0 +1 @@ +icon-training diff --git a/stable/_static/img/icons/icon-triangle-down.svg b/stable/_static/img/icons/icon-triangle-down.svg new file mode 100644 index 0000000000..e8ae088106 --- /dev/null +++ b/stable/_static/img/icons/icon-triangle-down.svg @@ -0,0 +1,3 @@ + + + diff --git a/stable/_static/img/icons/icon-university.svg b/stable/_static/img/icons/icon-university.svg new file mode 100644 index 0000000000..f7547ab959 --- /dev/null +++ b/stable/_static/img/icons/icon-university.svg @@ -0,0 +1 @@ +icon-university diff --git a/stable/_static/img/icons/icon-users-blog.svg b/stable/_static/img/icons/icon-users-blog.svg new file mode 100644 index 0000000000..47e56cddcf --- /dev/null +++ b/stable/_static/img/icons/icon-users-blog.svg @@ -0,0 +1 @@ +icon-users-blog diff --git a/stable/_static/img/icons/icon-warning.svg b/stable/_static/img/icons/icon-warning.svg new file mode 100644 index 0000000000..e4b1d40331 --- /dev/null +++ b/stable/_static/img/icons/icon-warning.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/stable/_static/img/icons/icon-webinars.svg b/stable/_static/img/icons/icon-webinars.svg new file mode 100644 index 0000000000..5e9f5cd427 --- /dev/null +++ b/stable/_static/img/icons/icon-webinars.svg @@ -0,0 +1 @@ +icon-webinars diff --git a/stable/_static/img/icons/icon-whitepapers.svg b/stable/_static/img/icons/icon-whitepapers.svg new file mode 100644 index 0000000000..3351e51d23 --- /dev/null +++ b/stable/_static/img/icons/icon-whitepapers.svg @@ -0,0 +1 @@ +icon-whitepapers diff --git a/stable/_static/img/icons/icon-workshop.svg b/stable/_static/img/icons/icon-workshop.svg new file mode 100644 index 0000000000..5206e58e98 --- /dev/null +++ b/stable/_static/img/icons/icon-workshop.svg @@ -0,0 +1 @@ + diff --git a/stable/_static/img/logo-docs.svg b/stable/_static/img/logo-docs.svg new file mode 100644 index 0000000000..4fff669cb6 --- /dev/null +++ b/stable/_static/img/logo-docs.svg @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/stable/_static/img/logo-scylla-horizontal-RGB.svg b/stable/_static/img/logo-scylla-horizontal-RGB.svg new file mode 100644 index 0000000000..b5022d7c4d --- /dev/null +++ b/stable/_static/img/logo-scylla-horizontal-RGB.svg @@ -0,0 +1,74 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/stable/_static/img/mascots/404.jpg b/stable/_static/img/mascots/404.jpg new file mode 100644 index 0000000000..769fa0889f Binary files /dev/null and b/stable/_static/img/mascots/404.jpg differ diff --git a/stable/_static/img/mascots/scylla-3monsters.png b/stable/_static/img/mascots/scylla-3monsters.png new file mode 100644 index 0000000000..7c06d01674 Binary files /dev/null and b/stable/_static/img/mascots/scylla-3monsters.png differ diff --git a/stable/_static/img/mascots/scylla-advisor-crystal.png b/stable/_static/img/mascots/scylla-advisor-crystal.png new file mode 100644 index 0000000000..d33fddd62f Binary files /dev/null and b/stable/_static/img/mascots/scylla-advisor-crystal.png differ diff --git a/stable/_static/img/mascots/scylla-alternator.svg b/stable/_static/img/mascots/scylla-alternator.svg new file mode 100644 index 0000000000..0462f893d5 --- /dev/null +++ b/stable/_static/img/mascots/scylla-alternator.svg @@ -0,0 +1 @@ +scylla-alternator diff --git a/stable/_static/img/mascots/scylla-cloud.svg b/stable/_static/img/mascots/scylla-cloud.svg new file mode 100644 index 0000000000..a6c6a26fc9 --- /dev/null +++ b/stable/_static/img/mascots/scylla-cloud.svg @@ -0,0 +1 @@ +scylla-cloud diff --git a/stable/_static/img/mascots/scylla-computer-3-monsters.png b/stable/_static/img/mascots/scylla-computer-3-monsters.png new file mode 100644 index 0000000000..d0368a7027 Binary files /dev/null and b/stable/_static/img/mascots/scylla-computer-3-monsters.png differ diff --git a/stable/_static/img/mascots/scylla-computer-headset.png b/stable/_static/img/mascots/scylla-computer-headset.png new file mode 100644 index 0000000000..0cdadaa216 Binary files /dev/null and b/stable/_static/img/mascots/scylla-computer-headset.png differ diff --git a/stable/_static/img/mascots/scylla-cup-number-one.png b/stable/_static/img/mascots/scylla-cup-number-one.png new file mode 100644 index 0000000000..e889f4e368 Binary files /dev/null and b/stable/_static/img/mascots/scylla-cup-number-one.png differ diff --git a/stable/_static/img/mascots/scylla-docs.svg b/stable/_static/img/mascots/scylla-docs.svg new file mode 100644 index 0000000000..a5bce950c2 --- /dev/null +++ b/stable/_static/img/mascots/scylla-docs.svg @@ -0,0 +1 @@ +scylla-docs diff --git a/stable/_static/img/mascots/scylla-drivers.svg b/stable/_static/img/mascots/scylla-drivers.svg new file mode 100644 index 0000000000..6012e71679 --- /dev/null +++ b/stable/_static/img/mascots/scylla-drivers.svg @@ -0,0 +1 @@ +scylla-manager diff --git a/stable/_static/img/mascots/scylla-enterprise.svg b/stable/_static/img/mascots/scylla-enterprise.svg new file mode 100644 index 0000000000..a1aa0b46ac --- /dev/null +++ b/stable/_static/img/mascots/scylla-enterprise.svg @@ -0,0 +1 @@ +scylla-enterprise diff --git a/stable/_static/img/mascots/scylla-forklift-boxes.png b/stable/_static/img/mascots/scylla-forklift-boxes.png new file mode 100644 index 0000000000..f64c29e6c7 Binary files /dev/null and b/stable/_static/img/mascots/scylla-forklift-boxes.png differ diff --git a/stable/_static/img/mascots/scylla-forklift-migration.png b/stable/_static/img/mascots/scylla-forklift-migration.png new file mode 100644 index 0000000000..d2f645c645 Binary files /dev/null and b/stable/_static/img/mascots/scylla-forklift-migration.png differ diff --git a/stable/_static/img/mascots/scylla-gear.png b/stable/_static/img/mascots/scylla-gear.png new file mode 100644 index 0000000000..0f53b26afa Binary files /dev/null and b/stable/_static/img/mascots/scylla-gear.png differ diff --git a/stable/_static/img/mascots/scylla-hardhat.png b/stable/_static/img/mascots/scylla-hardhat.png new file mode 100644 index 0000000000..630f2d9094 Binary files /dev/null and b/stable/_static/img/mascots/scylla-hardhat.png differ diff --git a/stable/_static/img/mascots/scylla-headband.png b/stable/_static/img/mascots/scylla-headband.png new file mode 100644 index 0000000000..c87abe684d Binary files /dev/null and b/stable/_static/img/mascots/scylla-headband.png differ diff --git a/stable/_static/img/mascots/scylla-headset.png b/stable/_static/img/mascots/scylla-headset.png new file mode 100644 index 0000000000..ba52cd223d Binary files /dev/null and b/stable/_static/img/mascots/scylla-headset.png differ diff --git a/stable/_static/img/mascots/scylla-hearts.png b/stable/_static/img/mascots/scylla-hearts.png new file mode 100644 index 0000000000..cef08c8654 Binary files /dev/null and b/stable/_static/img/mascots/scylla-hearts.png differ diff --git a/stable/_static/img/mascots/scylla-looking-down.png b/stable/_static/img/mascots/scylla-looking-down.png new file mode 100644 index 0000000000..75cccbfdf1 Binary files /dev/null and b/stable/_static/img/mascots/scylla-looking-down.png differ diff --git a/stable/_static/img/mascots/scylla-looking-up.png b/stable/_static/img/mascots/scylla-looking-up.png new file mode 100644 index 0000000000..6f10405f21 Binary files /dev/null and b/stable/_static/img/mascots/scylla-looking-up.png differ diff --git a/stable/_static/img/mascots/scylla-magnifying-glass-fronting.png b/stable/_static/img/mascots/scylla-magnifying-glass-fronting.png new file mode 100644 index 0000000000..e368cae169 Binary files /dev/null and b/stable/_static/img/mascots/scylla-magnifying-glass-fronting.png differ diff --git a/stable/_static/img/mascots/scylla-magnifying-glass.png b/stable/_static/img/mascots/scylla-magnifying-glass.png new file mode 100644 index 0000000000..74ad669500 Binary files /dev/null and b/stable/_static/img/mascots/scylla-magnifying-glass.png differ diff --git a/stable/_static/img/mascots/scylla-manager.svg b/stable/_static/img/mascots/scylla-manager.svg new file mode 100644 index 0000000000..6ba9ed937c --- /dev/null +++ b/stable/_static/img/mascots/scylla-manager.svg @@ -0,0 +1 @@ +scylla-manager-2 diff --git a/stable/_static/img/mascots/scylla-monitor.svg b/stable/_static/img/mascots/scylla-monitor.svg new file mode 100644 index 0000000000..48bec7dde3 --- /dev/null +++ b/stable/_static/img/mascots/scylla-monitor.svg @@ -0,0 +1 @@ +scylla-monitor diff --git a/stable/_static/img/mascots/scylla-movement-fast.png b/stable/_static/img/mascots/scylla-movement-fast.png new file mode 100644 index 0000000000..956d1dd0e2 Binary files /dev/null and b/stable/_static/img/mascots/scylla-movement-fast.png differ diff --git a/stable/_static/img/mascots/scylla-movement.png b/stable/_static/img/mascots/scylla-movement.png new file mode 100644 index 0000000000..7ee2b04338 Binary files /dev/null and b/stable/_static/img/mascots/scylla-movement.png differ diff --git a/stable/_static/img/mascots/scylla-onpremise.png b/stable/_static/img/mascots/scylla-onpremise.png new file mode 100644 index 0000000000..3b2dc8f1a2 Binary files /dev/null and b/stable/_static/img/mascots/scylla-onpremise.png differ diff --git a/stable/_static/img/mascots/scylla-opensource.svg b/stable/_static/img/mascots/scylla-opensource.svg new file mode 100644 index 0000000000..299e9cb995 --- /dev/null +++ b/stable/_static/img/mascots/scylla-opensource.svg @@ -0,0 +1 @@ +Plan de travail 1 diff --git a/stable/_static/img/mascots/scylla-operator.svg b/stable/_static/img/mascots/scylla-operator.svg new file mode 100644 index 0000000000..655a450b2a --- /dev/null +++ b/stable/_static/img/mascots/scylla-operator.svg @@ -0,0 +1 @@ +scylla-operator diff --git a/stable/_static/img/mascots/scylla-plugin.png b/stable/_static/img/mascots/scylla-plugin.png new file mode 100644 index 0000000000..b28dc857cc Binary files /dev/null and b/stable/_static/img/mascots/scylla-plugin.png differ diff --git a/stable/_static/img/mascots/scylla-release-mascot.png b/stable/_static/img/mascots/scylla-release-mascot.png new file mode 100644 index 0000000000..09342ac687 Binary files /dev/null and b/stable/_static/img/mascots/scylla-release-mascot.png differ diff --git a/stable/_static/img/mascots/scylla-repair.png b/stable/_static/img/mascots/scylla-repair.png new file mode 100644 index 0000000000..9b4c613e70 Binary files /dev/null and b/stable/_static/img/mascots/scylla-repair.png differ diff --git a/stable/_static/img/mascots/scylla-server.png b/stable/_static/img/mascots/scylla-server.png new file mode 100644 index 0000000000..96dc785298 Binary files /dev/null and b/stable/_static/img/mascots/scylla-server.png differ diff --git a/stable/_static/img/mascots/scylla-sleeping.png b/stable/_static/img/mascots/scylla-sleeping.png new file mode 100644 index 0000000000..f88598e05a Binary files /dev/null and b/stable/_static/img/mascots/scylla-sleeping.png differ diff --git a/stable/_static/img/mascots/scylla-tall-measure.png b/stable/_static/img/mascots/scylla-tall-measure.png new file mode 100644 index 0000000000..6f0ca146c0 Binary files /dev/null and b/stable/_static/img/mascots/scylla-tall-measure.png differ diff --git a/stable/_static/img/mascots/scylla-university.png b/stable/_static/img/mascots/scylla-university.png new file mode 100644 index 0000000000..b3d0621193 Binary files /dev/null and b/stable/_static/img/mascots/scylla-university.png differ diff --git a/stable/_static/img/mascots/scylla-weights.png b/stable/_static/img/mascots/scylla-weights.png new file mode 100644 index 0000000000..b070bb022c Binary files /dev/null and b/stable/_static/img/mascots/scylla-weights.png differ diff --git a/stable/_static/img/mascots/scylla-window-cleaning.png b/stable/_static/img/mascots/scylla-window-cleaning.png new file mode 100644 index 0000000000..6a8b16a6b4 Binary files /dev/null and b/stable/_static/img/mascots/scylla-window-cleaning.png differ diff --git a/stable/_static/img/mascots/scylla-with-computer-2.png b/stable/_static/img/mascots/scylla-with-computer-2.png new file mode 100644 index 0000000000..f3b8b2984f Binary files /dev/null and b/stable/_static/img/mascots/scylla-with-computer-2.png differ diff --git a/stable/_static/img/mascots/scylla-with-computer.png b/stable/_static/img/mascots/scylla-with-computer.png new file mode 100644 index 0000000000..b38a6fbbe0 Binary files /dev/null and b/stable/_static/img/mascots/scylla-with-computer.png differ diff --git a/stable/_static/img/mascots/scylla-with-linux.png b/stable/_static/img/mascots/scylla-with-linux.png new file mode 100644 index 0000000000..954bf13bc2 Binary files /dev/null and b/stable/_static/img/mascots/scylla-with-linux.png differ diff --git a/stable/_static/img/mascots/scylla-writting.png b/stable/_static/img/mascots/scylla-writting.png new file mode 100644 index 0000000000..d35a13d380 Binary files /dev/null and b/stable/_static/img/mascots/scylla-writting.png differ diff --git a/stable/_static/img/menu.svg b/stable/_static/img/menu.svg new file mode 100644 index 0000000000..30ea1d901e --- /dev/null +++ b/stable/_static/img/menu.svg @@ -0,0 +1,3 @@ + + + diff --git a/stable/_static/jquery-3.5.1.js b/stable/_static/jquery-3.5.1.js new file mode 100644 index 0000000000..50937333b9 --- /dev/null +++ b/stable/_static/jquery-3.5.1.js @@ -0,0 +1,10872 @@ +/*! + * jQuery JavaScript Library v3.5.1 + * https://jquery.com/ + * + * Includes Sizzle.js + * https://sizzlejs.com/ + * + * Copyright JS Foundation and other contributors + * Released under the MIT license + * https://jquery.org/license + * + * Date: 2020-05-04T22:49Z + */ +( function( global, factory ) { + + "use strict"; + + if ( typeof module === "object" && typeof module.exports === "object" ) { + + // For CommonJS and CommonJS-like environments where a proper `window` + // is present, execute the factory and get jQuery. + // For environments that do not have a `window` with a `document` + // (such as Node.js), expose a factory as module.exports. + // This accentuates the need for the creation of a real `window`. + // e.g. var jQuery = require("jquery")(window); + // See ticket #14549 for more info. + module.exports = global.document ? + factory( global, true ) : + function( w ) { + if ( !w.document ) { + throw new Error( "jQuery requires a window with a document" ); + } + return factory( w ); + }; + } else { + factory( global ); + } + +// Pass this if window is not defined yet +} )( typeof window !== "undefined" ? window : this, function( window, noGlobal ) { + +// Edge <= 12 - 13+, Firefox <=18 - 45+, IE 10 - 11, Safari 5.1 - 9+, iOS 6 - 9.1 +// throw exceptions when non-strict code (e.g., ASP.NET 4.5) accesses strict mode +// arguments.callee.caller (trac-13335). But as of jQuery 3.0 (2016), strict mode should be common +// enough that all such attempts are guarded in a try block. +"use strict"; + +var arr = []; + +var getProto = Object.getPrototypeOf; + +var slice = arr.slice; + +var flat = arr.flat ? function( array ) { + return arr.flat.call( array ); +} : function( array ) { + return arr.concat.apply( [], array ); +}; + + +var push = arr.push; + +var indexOf = arr.indexOf; + +var class2type = {}; + +var toString = class2type.toString; + +var hasOwn = class2type.hasOwnProperty; + +var fnToString = hasOwn.toString; + +var ObjectFunctionString = fnToString.call( Object ); + +var support = {}; + +var isFunction = function isFunction( obj ) { + + // Support: Chrome <=57, Firefox <=52 + // In some browsers, typeof returns "function" for HTML elements + // (i.e., `typeof document.createElement( "object" ) === "function"`). + // We don't want to classify *any* DOM node as a function. + return typeof obj === "function" && typeof obj.nodeType !== "number"; + }; + + +var isWindow = function isWindow( obj ) { + return obj != null && obj === obj.window; + }; + + +var document = window.document; + + + + var preservedScriptAttributes = { + type: true, + src: true, + nonce: true, + noModule: true + }; + + function DOMEval( code, node, doc ) { + doc = doc || document; + + var i, val, + script = doc.createElement( "script" ); + + script.text = code; + if ( node ) { + for ( i in preservedScriptAttributes ) { + + // Support: Firefox 64+, Edge 18+ + // Some browsers don't support the "nonce" property on scripts. + // On the other hand, just using `getAttribute` is not enough as + // the `nonce` attribute is reset to an empty string whenever it + // becomes browsing-context connected. + // See https://github.com/whatwg/html/issues/2369 + // See https://html.spec.whatwg.org/#nonce-attributes + // The `node.getAttribute` check was added for the sake of + // `jQuery.globalEval` so that it can fake a nonce-containing node + // via an object. + val = node[ i ] || node.getAttribute && node.getAttribute( i ); + if ( val ) { + script.setAttribute( i, val ); + } + } + } + doc.head.appendChild( script ).parentNode.removeChild( script ); + } + + +function toType( obj ) { + if ( obj == null ) { + return obj + ""; + } + + // Support: Android <=2.3 only (functionish RegExp) + return typeof obj === "object" || typeof obj === "function" ? + class2type[ toString.call( obj ) ] || "object" : + typeof obj; +} +/* global Symbol */ +// Defining this global in .eslintrc.json would create a danger of using the global +// unguarded in another place, it seems safer to define global only for this module + + + +var + version = "3.5.1", + + // Define a local copy of jQuery + jQuery = function( selector, context ) { + + // The jQuery object is actually just the init constructor 'enhanced' + // Need init if jQuery is called (just allow error to be thrown if not included) + return new jQuery.fn.init( selector, context ); + }; + +jQuery.fn = jQuery.prototype = { + + // The current version of jQuery being used + jquery: version, + + constructor: jQuery, + + // The default length of a jQuery object is 0 + length: 0, + + toArray: function() { + return slice.call( this ); + }, + + // Get the Nth element in the matched element set OR + // Get the whole matched element set as a clean array + get: function( num ) { + + // Return all the elements in a clean array + if ( num == null ) { + return slice.call( this ); + } + + // Return just the one element from the set + return num < 0 ? this[ num + this.length ] : this[ num ]; + }, + + // Take an array of elements and push it onto the stack + // (returning the new matched element set) + pushStack: function( elems ) { + + // Build a new jQuery matched element set + var ret = jQuery.merge( this.constructor(), elems ); + + // Add the old object onto the stack (as a reference) + ret.prevObject = this; + + // Return the newly-formed element set + return ret; + }, + + // Execute a callback for every element in the matched set. + each: function( callback ) { + return jQuery.each( this, callback ); + }, + + map: function( callback ) { + return this.pushStack( jQuery.map( this, function( elem, i ) { + return callback.call( elem, i, elem ); + } ) ); + }, + + slice: function() { + return this.pushStack( slice.apply( this, arguments ) ); + }, + + first: function() { + return this.eq( 0 ); + }, + + last: function() { + return this.eq( -1 ); + }, + + even: function() { + return this.pushStack( jQuery.grep( this, function( _elem, i ) { + return ( i + 1 ) % 2; + } ) ); + }, + + odd: function() { + return this.pushStack( jQuery.grep( this, function( _elem, i ) { + return i % 2; + } ) ); + }, + + eq: function( i ) { + var len = this.length, + j = +i + ( i < 0 ? len : 0 ); + return this.pushStack( j >= 0 && j < len ? [ this[ j ] ] : [] ); + }, + + end: function() { + return this.prevObject || this.constructor(); + }, + + // For internal use only. + // Behaves like an Array's method, not like a jQuery method. + push: push, + sort: arr.sort, + splice: arr.splice +}; + +jQuery.extend = jQuery.fn.extend = function() { + var options, name, src, copy, copyIsArray, clone, + target = arguments[ 0 ] || {}, + i = 1, + length = arguments.length, + deep = false; + + // Handle a deep copy situation + if ( typeof target === "boolean" ) { + deep = target; + + // Skip the boolean and the target + target = arguments[ i ] || {}; + i++; + } + + // Handle case when target is a string or something (possible in deep copy) + if ( typeof target !== "object" && !isFunction( target ) ) { + target = {}; + } + + // Extend jQuery itself if only one argument is passed + if ( i === length ) { + target = this; + i--; + } + + for ( ; i < length; i++ ) { + + // Only deal with non-null/undefined values + if ( ( options = arguments[ i ] ) != null ) { + + // Extend the base object + for ( name in options ) { + copy = options[ name ]; + + // Prevent Object.prototype pollution + // Prevent never-ending loop + if ( name === "__proto__" || target === copy ) { + continue; + } + + // Recurse if we're merging plain objects or arrays + if ( deep && copy && ( jQuery.isPlainObject( copy ) || + ( copyIsArray = Array.isArray( copy ) ) ) ) { + src = target[ name ]; + + // Ensure proper type for the source value + if ( copyIsArray && !Array.isArray( src ) ) { + clone = []; + } else if ( !copyIsArray && !jQuery.isPlainObject( src ) ) { + clone = {}; + } else { + clone = src; + } + copyIsArray = false; + + // Never move original objects, clone them + target[ name ] = jQuery.extend( deep, clone, copy ); + + // Don't bring in undefined values + } else if ( copy !== undefined ) { + target[ name ] = copy; + } + } + } + } + + // Return the modified object + return target; +}; + +jQuery.extend( { + + // Unique for each copy of jQuery on the page + expando: "jQuery" + ( version + Math.random() ).replace( /\D/g, "" ), + + // Assume jQuery is ready without the ready module + isReady: true, + + error: function( msg ) { + throw new Error( msg ); + }, + + noop: function() {}, + + isPlainObject: function( obj ) { + var proto, Ctor; + + // Detect obvious negatives + // Use toString instead of jQuery.type to catch host objects + if ( !obj || toString.call( obj ) !== "[object Object]" ) { + return false; + } + + proto = getProto( obj ); + + // Objects with no prototype (e.g., `Object.create( null )`) are plain + if ( !proto ) { + return true; + } + + // Objects with prototype are plain iff they were constructed by a global Object function + Ctor = hasOwn.call( proto, "constructor" ) && proto.constructor; + return typeof Ctor === "function" && fnToString.call( Ctor ) === ObjectFunctionString; + }, + + isEmptyObject: function( obj ) { + var name; + + for ( name in obj ) { + return false; + } + return true; + }, + + // Evaluates a script in a provided context; falls back to the global one + // if not specified. + globalEval: function( code, options, doc ) { + DOMEval( code, { nonce: options && options.nonce }, doc ); + }, + + each: function( obj, callback ) { + var length, i = 0; + + if ( isArrayLike( obj ) ) { + length = obj.length; + for ( ; i < length; i++ ) { + if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) { + break; + } + } + } else { + for ( i in obj ) { + if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) { + break; + } + } + } + + return obj; + }, + + // results is for internal usage only + makeArray: function( arr, results ) { + var ret = results || []; + + if ( arr != null ) { + if ( isArrayLike( Object( arr ) ) ) { + jQuery.merge( ret, + typeof arr === "string" ? + [ arr ] : arr + ); + } else { + push.call( ret, arr ); + } + } + + return ret; + }, + + inArray: function( elem, arr, i ) { + return arr == null ? -1 : indexOf.call( arr, elem, i ); + }, + + // Support: Android <=4.0 only, PhantomJS 1 only + // push.apply(_, arraylike) throws on ancient WebKit + merge: function( first, second ) { + var len = +second.length, + j = 0, + i = first.length; + + for ( ; j < len; j++ ) { + first[ i++ ] = second[ j ]; + } + + first.length = i; + + return first; + }, + + grep: function( elems, callback, invert ) { + var callbackInverse, + matches = [], + i = 0, + length = elems.length, + callbackExpect = !invert; + + // Go through the array, only saving the items + // that pass the validator function + for ( ; i < length; i++ ) { + callbackInverse = !callback( elems[ i ], i ); + if ( callbackInverse !== callbackExpect ) { + matches.push( elems[ i ] ); + } + } + + return matches; + }, + + // arg is for internal usage only + map: function( elems, callback, arg ) { + var length, value, + i = 0, + ret = []; + + // Go through the array, translating each of the items to their new values + if ( isArrayLike( elems ) ) { + length = elems.length; + for ( ; i < length; i++ ) { + value = callback( elems[ i ], i, arg ); + + if ( value != null ) { + ret.push( value ); + } + } + + // Go through every key on the object, + } else { + for ( i in elems ) { + value = callback( elems[ i ], i, arg ); + + if ( value != null ) { + ret.push( value ); + } + } + } + + // Flatten any nested arrays + return flat( ret ); + }, + + // A global GUID counter for objects + guid: 1, + + // jQuery.support is not used in Core but other projects attach their + // properties to it so it needs to exist. + support: support +} ); + +if ( typeof Symbol === "function" ) { + jQuery.fn[ Symbol.iterator ] = arr[ Symbol.iterator ]; +} + +// Populate the class2type map +jQuery.each( "Boolean Number String Function Array Date RegExp Object Error Symbol".split( " " ), +function( _i, name ) { + class2type[ "[object " + name + "]" ] = name.toLowerCase(); +} ); + +function isArrayLike( obj ) { + + // Support: real iOS 8.2 only (not reproducible in simulator) + // `in` check used to prevent JIT error (gh-2145) + // hasOwn isn't used here due to false negatives + // regarding Nodelist length in IE + var length = !!obj && "length" in obj && obj.length, + type = toType( obj ); + + if ( isFunction( obj ) || isWindow( obj ) ) { + return false; + } + + return type === "array" || length === 0 || + typeof length === "number" && length > 0 && ( length - 1 ) in obj; +} +var Sizzle = +/*! + * Sizzle CSS Selector Engine v2.3.5 + * https://sizzlejs.com/ + * + * Copyright JS Foundation and other contributors + * Released under the MIT license + * https://js.foundation/ + * + * Date: 2020-03-14 + */ +( function( window ) { +var i, + support, + Expr, + getText, + isXML, + tokenize, + compile, + select, + outermostContext, + sortInput, + hasDuplicate, + + // Local document vars + setDocument, + document, + docElem, + documentIsHTML, + rbuggyQSA, + rbuggyMatches, + matches, + contains, + + // Instance-specific data + expando = "sizzle" + 1 * new Date(), + preferredDoc = window.document, + dirruns = 0, + done = 0, + classCache = createCache(), + tokenCache = createCache(), + compilerCache = createCache(), + nonnativeSelectorCache = createCache(), + sortOrder = function( a, b ) { + if ( a === b ) { + hasDuplicate = true; + } + return 0; + }, + + // Instance methods + hasOwn = ( {} ).hasOwnProperty, + arr = [], + pop = arr.pop, + pushNative = arr.push, + push = arr.push, + slice = arr.slice, + + // Use a stripped-down indexOf as it's faster than native + // https://jsperf.com/thor-indexof-vs-for/5 + indexOf = function( list, elem ) { + var i = 0, + len = list.length; + for ( ; i < len; i++ ) { + if ( list[ i ] === elem ) { + return i; + } + } + return -1; + }, + + booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|" + + "ismap|loop|multiple|open|readonly|required|scoped", + + // Regular expressions + + // http://www.w3.org/TR/css3-selectors/#whitespace + whitespace = "[\\x20\\t\\r\\n\\f]", + + // https://www.w3.org/TR/css-syntax-3/#ident-token-diagram + identifier = "(?:\\\\[\\da-fA-F]{1,6}" + whitespace + + "?|\\\\[^\\r\\n\\f]|[\\w-]|[^\0-\\x7f])+", + + // Attribute selectors: http://www.w3.org/TR/selectors/#attribute-selectors + attributes = "\\[" + whitespace + "*(" + identifier + ")(?:" + whitespace + + + // Operator (capture 2) + "*([*^$|!~]?=)" + whitespace + + + // "Attribute values must be CSS identifiers [capture 5] + // or strings [capture 3 or capture 4]" + "*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|(" + identifier + "))|)" + + whitespace + "*\\]", + + pseudos = ":(" + identifier + ")(?:\\((" + + + // To reduce the number of selectors needing tokenize in the preFilter, prefer arguments: + // 1. quoted (capture 3; capture 4 or capture 5) + "('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|" + + + // 2. simple (capture 6) + "((?:\\\\.|[^\\\\()[\\]]|" + attributes + ")*)|" + + + // 3. anything else (capture 2) + ".*" + + ")\\)|)", + + // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter + rwhitespace = new RegExp( whitespace + "+", "g" ), + rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + + whitespace + "+$", "g" ), + + rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ), + rcombinators = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + + "*" ), + rdescend = new RegExp( whitespace + "|>" ), + + rpseudo = new RegExp( pseudos ), + ridentifier = new RegExp( "^" + identifier + "$" ), + + matchExpr = { + "ID": new RegExp( "^#(" + identifier + ")" ), + "CLASS": new RegExp( "^\\.(" + identifier + ")" ), + "TAG": new RegExp( "^(" + identifier + "|[*])" ), + "ATTR": new RegExp( "^" + attributes ), + "PSEUDO": new RegExp( "^" + pseudos ), + "CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + + whitespace + "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + + whitespace + "*(\\d+)|))" + whitespace + "*\\)|)", "i" ), + "bool": new RegExp( "^(?:" + booleans + ")$", "i" ), + + // For use in libraries implementing .is() + // We use this for POS matching in `select` + "needsContext": new RegExp( "^" + whitespace + + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" + whitespace + + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" ) + }, + + rhtml = /HTML$/i, + rinputs = /^(?:input|select|textarea|button)$/i, + rheader = /^h\d$/i, + + rnative = /^[^{]+\{\s*\[native \w/, + + // Easily-parseable/retrievable ID or TAG or CLASS selectors + rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/, + + rsibling = /[+~]/, + + // CSS escapes + // http://www.w3.org/TR/CSS21/syndata.html#escaped-characters + runescape = new RegExp( "\\\\[\\da-fA-F]{1,6}" + whitespace + "?|\\\\([^\\r\\n\\f])", "g" ), + funescape = function( escape, nonHex ) { + var high = "0x" + escape.slice( 1 ) - 0x10000; + + return nonHex ? + + // Strip the backslash prefix from a non-hex escape sequence + nonHex : + + // Replace a hexadecimal escape sequence with the encoded Unicode code point + // Support: IE <=11+ + // For values outside the Basic Multilingual Plane (BMP), manually construct a + // surrogate pair + high < 0 ? + String.fromCharCode( high + 0x10000 ) : + String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 ); + }, + + // CSS string/identifier serialization + // https://drafts.csswg.org/cssom/#common-serializing-idioms + rcssescape = /([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g, + fcssescape = function( ch, asCodePoint ) { + if ( asCodePoint ) { + + // U+0000 NULL becomes U+FFFD REPLACEMENT CHARACTER + if ( ch === "\0" ) { + return "\uFFFD"; + } + + // Control characters and (dependent upon position) numbers get escaped as code points + return ch.slice( 0, -1 ) + "\\" + + ch.charCodeAt( ch.length - 1 ).toString( 16 ) + " "; + } + + // Other potentially-special ASCII characters get backslash-escaped + return "\\" + ch; + }, + + // Used for iframes + // See setDocument() + // Removing the function wrapper causes a "Permission Denied" + // error in IE + unloadHandler = function() { + setDocument(); + }, + + inDisabledFieldset = addCombinator( + function( elem ) { + return elem.disabled === true && elem.nodeName.toLowerCase() === "fieldset"; + }, + { dir: "parentNode", next: "legend" } + ); + +// Optimize for push.apply( _, NodeList ) +try { + push.apply( + ( arr = slice.call( preferredDoc.childNodes ) ), + preferredDoc.childNodes + ); + + // Support: Android<4.0 + // Detect silently failing push.apply + // eslint-disable-next-line no-unused-expressions + arr[ preferredDoc.childNodes.length ].nodeType; +} catch ( e ) { + push = { apply: arr.length ? + + // Leverage slice if possible + function( target, els ) { + pushNative.apply( target, slice.call( els ) ); + } : + + // Support: IE<9 + // Otherwise append directly + function( target, els ) { + var j = target.length, + i = 0; + + // Can't trust NodeList.length + while ( ( target[ j++ ] = els[ i++ ] ) ) {} + target.length = j - 1; + } + }; +} + +function Sizzle( selector, context, results, seed ) { + var m, i, elem, nid, match, groups, newSelector, + newContext = context && context.ownerDocument, + + // nodeType defaults to 9, since context defaults to document + nodeType = context ? context.nodeType : 9; + + results = results || []; + + // Return early from calls with invalid selector or context + if ( typeof selector !== "string" || !selector || + nodeType !== 1 && nodeType !== 9 && nodeType !== 11 ) { + + return results; + } + + // Try to shortcut find operations (as opposed to filters) in HTML documents + if ( !seed ) { + setDocument( context ); + context = context || document; + + if ( documentIsHTML ) { + + // If the selector is sufficiently simple, try using a "get*By*" DOM method + // (excepting DocumentFragment context, where the methods don't exist) + if ( nodeType !== 11 && ( match = rquickExpr.exec( selector ) ) ) { + + // ID selector + if ( ( m = match[ 1 ] ) ) { + + // Document context + if ( nodeType === 9 ) { + if ( ( elem = context.getElementById( m ) ) ) { + + // Support: IE, Opera, Webkit + // TODO: identify versions + // getElementById can match elements by name instead of ID + if ( elem.id === m ) { + results.push( elem ); + return results; + } + } else { + return results; + } + + // Element context + } else { + + // Support: IE, Opera, Webkit + // TODO: identify versions + // getElementById can match elements by name instead of ID + if ( newContext && ( elem = newContext.getElementById( m ) ) && + contains( context, elem ) && + elem.id === m ) { + + results.push( elem ); + return results; + } + } + + // Type selector + } else if ( match[ 2 ] ) { + push.apply( results, context.getElementsByTagName( selector ) ); + return results; + + // Class selector + } else if ( ( m = match[ 3 ] ) && support.getElementsByClassName && + context.getElementsByClassName ) { + + push.apply( results, context.getElementsByClassName( m ) ); + return results; + } + } + + // Take advantage of querySelectorAll + if ( support.qsa && + !nonnativeSelectorCache[ selector + " " ] && + ( !rbuggyQSA || !rbuggyQSA.test( selector ) ) && + + // Support: IE 8 only + // Exclude object elements + ( nodeType !== 1 || context.nodeName.toLowerCase() !== "object" ) ) { + + newSelector = selector; + newContext = context; + + // qSA considers elements outside a scoping root when evaluating child or + // descendant combinators, which is not what we want. + // In such cases, we work around the behavior by prefixing every selector in the + // list with an ID selector referencing the scope context. + // The technique has to be used as well when a leading combinator is used + // as such selectors are not recognized by querySelectorAll. + // Thanks to Andrew Dupont for this technique. + if ( nodeType === 1 && + ( rdescend.test( selector ) || rcombinators.test( selector ) ) ) { + + // Expand context for sibling selectors + newContext = rsibling.test( selector ) && testContext( context.parentNode ) || + context; + + // We can use :scope instead of the ID hack if the browser + // supports it & if we're not changing the context. + if ( newContext !== context || !support.scope ) { + + // Capture the context ID, setting it first if necessary + if ( ( nid = context.getAttribute( "id" ) ) ) { + nid = nid.replace( rcssescape, fcssescape ); + } else { + context.setAttribute( "id", ( nid = expando ) ); + } + } + + // Prefix every selector in the list + groups = tokenize( selector ); + i = groups.length; + while ( i-- ) { + groups[ i ] = ( nid ? "#" + nid : ":scope" ) + " " + + toSelector( groups[ i ] ); + } + newSelector = groups.join( "," ); + } + + try { + push.apply( results, + newContext.querySelectorAll( newSelector ) + ); + return results; + } catch ( qsaError ) { + nonnativeSelectorCache( selector, true ); + } finally { + if ( nid === expando ) { + context.removeAttribute( "id" ); + } + } + } + } + } + + // All others + return select( selector.replace( rtrim, "$1" ), context, results, seed ); +} + +/** + * Create key-value caches of limited size + * @returns {function(string, object)} Returns the Object data after storing it on itself with + * property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength) + * deleting the oldest entry + */ +function createCache() { + var keys = []; + + function cache( key, value ) { + + // Use (key + " ") to avoid collision with native prototype properties (see Issue #157) + if ( keys.push( key + " " ) > Expr.cacheLength ) { + + // Only keep the most recent entries + delete cache[ keys.shift() ]; + } + return ( cache[ key + " " ] = value ); + } + return cache; +} + +/** + * Mark a function for special use by Sizzle + * @param {Function} fn The function to mark + */ +function markFunction( fn ) { + fn[ expando ] = true; + return fn; +} + +/** + * Support testing using an element + * @param {Function} fn Passed the created element and returns a boolean result + */ +function assert( fn ) { + var el = document.createElement( "fieldset" ); + + try { + return !!fn( el ); + } catch ( e ) { + return false; + } finally { + + // Remove from its parent by default + if ( el.parentNode ) { + el.parentNode.removeChild( el ); + } + + // release memory in IE + el = null; + } +} + +/** + * Adds the same handler for all of the specified attrs + * @param {String} attrs Pipe-separated list of attributes + * @param {Function} handler The method that will be applied + */ +function addHandle( attrs, handler ) { + var arr = attrs.split( "|" ), + i = arr.length; + + while ( i-- ) { + Expr.attrHandle[ arr[ i ] ] = handler; + } +} + +/** + * Checks document order of two siblings + * @param {Element} a + * @param {Element} b + * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b + */ +function siblingCheck( a, b ) { + var cur = b && a, + diff = cur && a.nodeType === 1 && b.nodeType === 1 && + a.sourceIndex - b.sourceIndex; + + // Use IE sourceIndex if available on both nodes + if ( diff ) { + return diff; + } + + // Check if b follows a + if ( cur ) { + while ( ( cur = cur.nextSibling ) ) { + if ( cur === b ) { + return -1; + } + } + } + + return a ? 1 : -1; +} + +/** + * Returns a function to use in pseudos for input types + * @param {String} type + */ +function createInputPseudo( type ) { + return function( elem ) { + var name = elem.nodeName.toLowerCase(); + return name === "input" && elem.type === type; + }; +} + +/** + * Returns a function to use in pseudos for buttons + * @param {String} type + */ +function createButtonPseudo( type ) { + return function( elem ) { + var name = elem.nodeName.toLowerCase(); + return ( name === "input" || name === "button" ) && elem.type === type; + }; +} + +/** + * Returns a function to use in pseudos for :enabled/:disabled + * @param {Boolean} disabled true for :disabled; false for :enabled + */ +function createDisabledPseudo( disabled ) { + + // Known :disabled false positives: fieldset[disabled] > legend:nth-of-type(n+2) :can-disable + return function( elem ) { + + // Only certain elements can match :enabled or :disabled + // https://html.spec.whatwg.org/multipage/scripting.html#selector-enabled + // https://html.spec.whatwg.org/multipage/scripting.html#selector-disabled + if ( "form" in elem ) { + + // Check for inherited disabledness on relevant non-disabled elements: + // * listed form-associated elements in a disabled fieldset + // https://html.spec.whatwg.org/multipage/forms.html#category-listed + // https://html.spec.whatwg.org/multipage/forms.html#concept-fe-disabled + // * option elements in a disabled optgroup + // https://html.spec.whatwg.org/multipage/forms.html#concept-option-disabled + // All such elements have a "form" property. + if ( elem.parentNode && elem.disabled === false ) { + + // Option elements defer to a parent optgroup if present + if ( "label" in elem ) { + if ( "label" in elem.parentNode ) { + return elem.parentNode.disabled === disabled; + } else { + return elem.disabled === disabled; + } + } + + // Support: IE 6 - 11 + // Use the isDisabled shortcut property to check for disabled fieldset ancestors + return elem.isDisabled === disabled || + + // Where there is no isDisabled, check manually + /* jshint -W018 */ + elem.isDisabled !== !disabled && + inDisabledFieldset( elem ) === disabled; + } + + return elem.disabled === disabled; + + // Try to winnow out elements that can't be disabled before trusting the disabled property. + // Some victims get caught in our net (label, legend, menu, track), but it shouldn't + // even exist on them, let alone have a boolean value. + } else if ( "label" in elem ) { + return elem.disabled === disabled; + } + + // Remaining elements are neither :enabled nor :disabled + return false; + }; +} + +/** + * Returns a function to use in pseudos for positionals + * @param {Function} fn + */ +function createPositionalPseudo( fn ) { + return markFunction( function( argument ) { + argument = +argument; + return markFunction( function( seed, matches ) { + var j, + matchIndexes = fn( [], seed.length, argument ), + i = matchIndexes.length; + + // Match elements found at the specified indexes + while ( i-- ) { + if ( seed[ ( j = matchIndexes[ i ] ) ] ) { + seed[ j ] = !( matches[ j ] = seed[ j ] ); + } + } + } ); + } ); +} + +/** + * Checks a node for validity as a Sizzle context + * @param {Element|Object=} context + * @returns {Element|Object|Boolean} The input node if acceptable, otherwise a falsy value + */ +function testContext( context ) { + return context && typeof context.getElementsByTagName !== "undefined" && context; +} + +// Expose support vars for convenience +support = Sizzle.support = {}; + +/** + * Detects XML nodes + * @param {Element|Object} elem An element or a document + * @returns {Boolean} True iff elem is a non-HTML XML node + */ +isXML = Sizzle.isXML = function( elem ) { + var namespace = elem.namespaceURI, + docElem = ( elem.ownerDocument || elem ).documentElement; + + // Support: IE <=8 + // Assume HTML when documentElement doesn't yet exist, such as inside loading iframes + // https://bugs.jquery.com/ticket/4833 + return !rhtml.test( namespace || docElem && docElem.nodeName || "HTML" ); +}; + +/** + * Sets document-related variables once based on the current document + * @param {Element|Object} [doc] An element or document object to use to set the document + * @returns {Object} Returns the current document + */ +setDocument = Sizzle.setDocument = function( node ) { + var hasCompare, subWindow, + doc = node ? node.ownerDocument || node : preferredDoc; + + // Return early if doc is invalid or already selected + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( doc == document || doc.nodeType !== 9 || !doc.documentElement ) { + return document; + } + + // Update global variables + document = doc; + docElem = document.documentElement; + documentIsHTML = !isXML( document ); + + // Support: IE 9 - 11+, Edge 12 - 18+ + // Accessing iframe documents after unload throws "permission denied" errors (jQuery #13936) + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( preferredDoc != document && + ( subWindow = document.defaultView ) && subWindow.top !== subWindow ) { + + // Support: IE 11, Edge + if ( subWindow.addEventListener ) { + subWindow.addEventListener( "unload", unloadHandler, false ); + + // Support: IE 9 - 10 only + } else if ( subWindow.attachEvent ) { + subWindow.attachEvent( "onunload", unloadHandler ); + } + } + + // Support: IE 8 - 11+, Edge 12 - 18+, Chrome <=16 - 25 only, Firefox <=3.6 - 31 only, + // Safari 4 - 5 only, Opera <=11.6 - 12.x only + // IE/Edge & older browsers don't support the :scope pseudo-class. + // Support: Safari 6.0 only + // Safari 6.0 supports :scope but it's an alias of :root there. + support.scope = assert( function( el ) { + docElem.appendChild( el ).appendChild( document.createElement( "div" ) ); + return typeof el.querySelectorAll !== "undefined" && + !el.querySelectorAll( ":scope fieldset div" ).length; + } ); + + /* Attributes + ---------------------------------------------------------------------- */ + + // Support: IE<8 + // Verify that getAttribute really returns attributes and not properties + // (excepting IE8 booleans) + support.attributes = assert( function( el ) { + el.className = "i"; + return !el.getAttribute( "className" ); + } ); + + /* getElement(s)By* + ---------------------------------------------------------------------- */ + + // Check if getElementsByTagName("*") returns only elements + support.getElementsByTagName = assert( function( el ) { + el.appendChild( document.createComment( "" ) ); + return !el.getElementsByTagName( "*" ).length; + } ); + + // Support: IE<9 + support.getElementsByClassName = rnative.test( document.getElementsByClassName ); + + // Support: IE<10 + // Check if getElementById returns elements by name + // The broken getElementById methods don't pick up programmatically-set names, + // so use a roundabout getElementsByName test + support.getById = assert( function( el ) { + docElem.appendChild( el ).id = expando; + return !document.getElementsByName || !document.getElementsByName( expando ).length; + } ); + + // ID filter and find + if ( support.getById ) { + Expr.filter[ "ID" ] = function( id ) { + var attrId = id.replace( runescape, funescape ); + return function( elem ) { + return elem.getAttribute( "id" ) === attrId; + }; + }; + Expr.find[ "ID" ] = function( id, context ) { + if ( typeof context.getElementById !== "undefined" && documentIsHTML ) { + var elem = context.getElementById( id ); + return elem ? [ elem ] : []; + } + }; + } else { + Expr.filter[ "ID" ] = function( id ) { + var attrId = id.replace( runescape, funescape ); + return function( elem ) { + var node = typeof elem.getAttributeNode !== "undefined" && + elem.getAttributeNode( "id" ); + return node && node.value === attrId; + }; + }; + + // Support: IE 6 - 7 only + // getElementById is not reliable as a find shortcut + Expr.find[ "ID" ] = function( id, context ) { + if ( typeof context.getElementById !== "undefined" && documentIsHTML ) { + var node, i, elems, + elem = context.getElementById( id ); + + if ( elem ) { + + // Verify the id attribute + node = elem.getAttributeNode( "id" ); + if ( node && node.value === id ) { + return [ elem ]; + } + + // Fall back on getElementsByName + elems = context.getElementsByName( id ); + i = 0; + while ( ( elem = elems[ i++ ] ) ) { + node = elem.getAttributeNode( "id" ); + if ( node && node.value === id ) { + return [ elem ]; + } + } + } + + return []; + } + }; + } + + // Tag + Expr.find[ "TAG" ] = support.getElementsByTagName ? + function( tag, context ) { + if ( typeof context.getElementsByTagName !== "undefined" ) { + return context.getElementsByTagName( tag ); + + // DocumentFragment nodes don't have gEBTN + } else if ( support.qsa ) { + return context.querySelectorAll( tag ); + } + } : + + function( tag, context ) { + var elem, + tmp = [], + i = 0, + + // By happy coincidence, a (broken) gEBTN appears on DocumentFragment nodes too + results = context.getElementsByTagName( tag ); + + // Filter out possible comments + if ( tag === "*" ) { + while ( ( elem = results[ i++ ] ) ) { + if ( elem.nodeType === 1 ) { + tmp.push( elem ); + } + } + + return tmp; + } + return results; + }; + + // Class + Expr.find[ "CLASS" ] = support.getElementsByClassName && function( className, context ) { + if ( typeof context.getElementsByClassName !== "undefined" && documentIsHTML ) { + return context.getElementsByClassName( className ); + } + }; + + /* QSA/matchesSelector + ---------------------------------------------------------------------- */ + + // QSA and matchesSelector support + + // matchesSelector(:active) reports false when true (IE9/Opera 11.5) + rbuggyMatches = []; + + // qSa(:focus) reports false when true (Chrome 21) + // We allow this because of a bug in IE8/9 that throws an error + // whenever `document.activeElement` is accessed on an iframe + // So, we allow :focus to pass through QSA all the time to avoid the IE error + // See https://bugs.jquery.com/ticket/13378 + rbuggyQSA = []; + + if ( ( support.qsa = rnative.test( document.querySelectorAll ) ) ) { + + // Build QSA regex + // Regex strategy adopted from Diego Perini + assert( function( el ) { + + var input; + + // Select is set to empty string on purpose + // This is to test IE's treatment of not explicitly + // setting a boolean content attribute, + // since its presence should be enough + // https://bugs.jquery.com/ticket/12359 + docElem.appendChild( el ).innerHTML = "" + + ""; + + // Support: IE8, Opera 11-12.16 + // Nothing should be selected when empty strings follow ^= or $= or *= + // The test attribute must be unknown in Opera but "safe" for WinRT + // https://msdn.microsoft.com/en-us/library/ie/hh465388.aspx#attribute_section + if ( el.querySelectorAll( "[msallowcapture^='']" ).length ) { + rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:''|\"\")" ); + } + + // Support: IE8 + // Boolean attributes and "value" are not treated correctly + if ( !el.querySelectorAll( "[selected]" ).length ) { + rbuggyQSA.push( "\\[" + whitespace + "*(?:value|" + booleans + ")" ); + } + + // Support: Chrome<29, Android<4.4, Safari<7.0+, iOS<7.0+, PhantomJS<1.9.8+ + if ( !el.querySelectorAll( "[id~=" + expando + "-]" ).length ) { + rbuggyQSA.push( "~=" ); + } + + // Support: IE 11+, Edge 15 - 18+ + // IE 11/Edge don't find elements on a `[name='']` query in some cases. + // Adding a temporary attribute to the document before the selection works + // around the issue. + // Interestingly, IE 10 & older don't seem to have the issue. + input = document.createElement( "input" ); + input.setAttribute( "name", "" ); + el.appendChild( input ); + if ( !el.querySelectorAll( "[name='']" ).length ) { + rbuggyQSA.push( "\\[" + whitespace + "*name" + whitespace + "*=" + + whitespace + "*(?:''|\"\")" ); + } + + // Webkit/Opera - :checked should return selected option elements + // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked + // IE8 throws error here and will not see later tests + if ( !el.querySelectorAll( ":checked" ).length ) { + rbuggyQSA.push( ":checked" ); + } + + // Support: Safari 8+, iOS 8+ + // https://bugs.webkit.org/show_bug.cgi?id=136851 + // In-page `selector#id sibling-combinator selector` fails + if ( !el.querySelectorAll( "a#" + expando + "+*" ).length ) { + rbuggyQSA.push( ".#.+[+~]" ); + } + + // Support: Firefox <=3.6 - 5 only + // Old Firefox doesn't throw on a badly-escaped identifier. + el.querySelectorAll( "\\\f" ); + rbuggyQSA.push( "[\\r\\n\\f]" ); + } ); + + assert( function( el ) { + el.innerHTML = "" + + ""; + + // Support: Windows 8 Native Apps + // The type and name attributes are restricted during .innerHTML assignment + var input = document.createElement( "input" ); + input.setAttribute( "type", "hidden" ); + el.appendChild( input ).setAttribute( "name", "D" ); + + // Support: IE8 + // Enforce case-sensitivity of name attribute + if ( el.querySelectorAll( "[name=d]" ).length ) { + rbuggyQSA.push( "name" + whitespace + "*[*^$|!~]?=" ); + } + + // FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled) + // IE8 throws error here and will not see later tests + if ( el.querySelectorAll( ":enabled" ).length !== 2 ) { + rbuggyQSA.push( ":enabled", ":disabled" ); + } + + // Support: IE9-11+ + // IE's :disabled selector does not pick up the children of disabled fieldsets + docElem.appendChild( el ).disabled = true; + if ( el.querySelectorAll( ":disabled" ).length !== 2 ) { + rbuggyQSA.push( ":enabled", ":disabled" ); + } + + // Support: Opera 10 - 11 only + // Opera 10-11 does not throw on post-comma invalid pseudos + el.querySelectorAll( "*,:x" ); + rbuggyQSA.push( ",.*:" ); + } ); + } + + if ( ( support.matchesSelector = rnative.test( ( matches = docElem.matches || + docElem.webkitMatchesSelector || + docElem.mozMatchesSelector || + docElem.oMatchesSelector || + docElem.msMatchesSelector ) ) ) ) { + + assert( function( el ) { + + // Check to see if it's possible to do matchesSelector + // on a disconnected node (IE 9) + support.disconnectedMatch = matches.call( el, "*" ); + + // This should fail with an exception + // Gecko does not error, returns false instead + matches.call( el, "[s!='']:x" ); + rbuggyMatches.push( "!=", pseudos ); + } ); + } + + rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join( "|" ) ); + rbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join( "|" ) ); + + /* Contains + ---------------------------------------------------------------------- */ + hasCompare = rnative.test( docElem.compareDocumentPosition ); + + // Element contains another + // Purposefully self-exclusive + // As in, an element does not contain itself + contains = hasCompare || rnative.test( docElem.contains ) ? + function( a, b ) { + var adown = a.nodeType === 9 ? a.documentElement : a, + bup = b && b.parentNode; + return a === bup || !!( bup && bup.nodeType === 1 && ( + adown.contains ? + adown.contains( bup ) : + a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16 + ) ); + } : + function( a, b ) { + if ( b ) { + while ( ( b = b.parentNode ) ) { + if ( b === a ) { + return true; + } + } + } + return false; + }; + + /* Sorting + ---------------------------------------------------------------------- */ + + // Document order sorting + sortOrder = hasCompare ? + function( a, b ) { + + // Flag for duplicate removal + if ( a === b ) { + hasDuplicate = true; + return 0; + } + + // Sort on method existence if only one input has compareDocumentPosition + var compare = !a.compareDocumentPosition - !b.compareDocumentPosition; + if ( compare ) { + return compare; + } + + // Calculate position if both inputs belong to the same document + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + compare = ( a.ownerDocument || a ) == ( b.ownerDocument || b ) ? + a.compareDocumentPosition( b ) : + + // Otherwise we know they are disconnected + 1; + + // Disconnected nodes + if ( compare & 1 || + ( !support.sortDetached && b.compareDocumentPosition( a ) === compare ) ) { + + // Choose the first element that is related to our preferred document + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( a == document || a.ownerDocument == preferredDoc && + contains( preferredDoc, a ) ) { + return -1; + } + + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( b == document || b.ownerDocument == preferredDoc && + contains( preferredDoc, b ) ) { + return 1; + } + + // Maintain original order + return sortInput ? + ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) : + 0; + } + + return compare & 4 ? -1 : 1; + } : + function( a, b ) { + + // Exit early if the nodes are identical + if ( a === b ) { + hasDuplicate = true; + return 0; + } + + var cur, + i = 0, + aup = a.parentNode, + bup = b.parentNode, + ap = [ a ], + bp = [ b ]; + + // Parentless nodes are either documents or disconnected + if ( !aup || !bup ) { + + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + /* eslint-disable eqeqeq */ + return a == document ? -1 : + b == document ? 1 : + /* eslint-enable eqeqeq */ + aup ? -1 : + bup ? 1 : + sortInput ? + ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) : + 0; + + // If the nodes are siblings, we can do a quick check + } else if ( aup === bup ) { + return siblingCheck( a, b ); + } + + // Otherwise we need full lists of their ancestors for comparison + cur = a; + while ( ( cur = cur.parentNode ) ) { + ap.unshift( cur ); + } + cur = b; + while ( ( cur = cur.parentNode ) ) { + bp.unshift( cur ); + } + + // Walk down the tree looking for a discrepancy + while ( ap[ i ] === bp[ i ] ) { + i++; + } + + return i ? + + // Do a sibling check if the nodes have a common ancestor + siblingCheck( ap[ i ], bp[ i ] ) : + + // Otherwise nodes in our document sort first + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + /* eslint-disable eqeqeq */ + ap[ i ] == preferredDoc ? -1 : + bp[ i ] == preferredDoc ? 1 : + /* eslint-enable eqeqeq */ + 0; + }; + + return document; +}; + +Sizzle.matches = function( expr, elements ) { + return Sizzle( expr, null, null, elements ); +}; + +Sizzle.matchesSelector = function( elem, expr ) { + setDocument( elem ); + + if ( support.matchesSelector && documentIsHTML && + !nonnativeSelectorCache[ expr + " " ] && + ( !rbuggyMatches || !rbuggyMatches.test( expr ) ) && + ( !rbuggyQSA || !rbuggyQSA.test( expr ) ) ) { + + try { + var ret = matches.call( elem, expr ); + + // IE 9's matchesSelector returns false on disconnected nodes + if ( ret || support.disconnectedMatch || + + // As well, disconnected nodes are said to be in a document + // fragment in IE 9 + elem.document && elem.document.nodeType !== 11 ) { + return ret; + } + } catch ( e ) { + nonnativeSelectorCache( expr, true ); + } + } + + return Sizzle( expr, document, null, [ elem ] ).length > 0; +}; + +Sizzle.contains = function( context, elem ) { + + // Set document vars if needed + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( ( context.ownerDocument || context ) != document ) { + setDocument( context ); + } + return contains( context, elem ); +}; + +Sizzle.attr = function( elem, name ) { + + // Set document vars if needed + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( ( elem.ownerDocument || elem ) != document ) { + setDocument( elem ); + } + + var fn = Expr.attrHandle[ name.toLowerCase() ], + + // Don't get fooled by Object.prototype properties (jQuery #13807) + val = fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ? + fn( elem, name, !documentIsHTML ) : + undefined; + + return val !== undefined ? + val : + support.attributes || !documentIsHTML ? + elem.getAttribute( name ) : + ( val = elem.getAttributeNode( name ) ) && val.specified ? + val.value : + null; +}; + +Sizzle.escape = function( sel ) { + return ( sel + "" ).replace( rcssescape, fcssescape ); +}; + +Sizzle.error = function( msg ) { + throw new Error( "Syntax error, unrecognized expression: " + msg ); +}; + +/** + * Document sorting and removing duplicates + * @param {ArrayLike} results + */ +Sizzle.uniqueSort = function( results ) { + var elem, + duplicates = [], + j = 0, + i = 0; + + // Unless we *know* we can detect duplicates, assume their presence + hasDuplicate = !support.detectDuplicates; + sortInput = !support.sortStable && results.slice( 0 ); + results.sort( sortOrder ); + + if ( hasDuplicate ) { + while ( ( elem = results[ i++ ] ) ) { + if ( elem === results[ i ] ) { + j = duplicates.push( i ); + } + } + while ( j-- ) { + results.splice( duplicates[ j ], 1 ); + } + } + + // Clear input after sorting to release objects + // See https://github.com/jquery/sizzle/pull/225 + sortInput = null; + + return results; +}; + +/** + * Utility function for retrieving the text value of an array of DOM nodes + * @param {Array|Element} elem + */ +getText = Sizzle.getText = function( elem ) { + var node, + ret = "", + i = 0, + nodeType = elem.nodeType; + + if ( !nodeType ) { + + // If no nodeType, this is expected to be an array + while ( ( node = elem[ i++ ] ) ) { + + // Do not traverse comment nodes + ret += getText( node ); + } + } else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) { + + // Use textContent for elements + // innerText usage removed for consistency of new lines (jQuery #11153) + if ( typeof elem.textContent === "string" ) { + return elem.textContent; + } else { + + // Traverse its children + for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { + ret += getText( elem ); + } + } + } else if ( nodeType === 3 || nodeType === 4 ) { + return elem.nodeValue; + } + + // Do not include comment or processing instruction nodes + + return ret; +}; + +Expr = Sizzle.selectors = { + + // Can be adjusted by the user + cacheLength: 50, + + createPseudo: markFunction, + + match: matchExpr, + + attrHandle: {}, + + find: {}, + + relative: { + ">": { dir: "parentNode", first: true }, + " ": { dir: "parentNode" }, + "+": { dir: "previousSibling", first: true }, + "~": { dir: "previousSibling" } + }, + + preFilter: { + "ATTR": function( match ) { + match[ 1 ] = match[ 1 ].replace( runescape, funescape ); + + // Move the given value to match[3] whether quoted or unquoted + match[ 3 ] = ( match[ 3 ] || match[ 4 ] || + match[ 5 ] || "" ).replace( runescape, funescape ); + + if ( match[ 2 ] === "~=" ) { + match[ 3 ] = " " + match[ 3 ] + " "; + } + + return match.slice( 0, 4 ); + }, + + "CHILD": function( match ) { + + /* matches from matchExpr["CHILD"] + 1 type (only|nth|...) + 2 what (child|of-type) + 3 argument (even|odd|\d*|\d*n([+-]\d+)?|...) + 4 xn-component of xn+y argument ([+-]?\d*n|) + 5 sign of xn-component + 6 x of xn-component + 7 sign of y-component + 8 y of y-component + */ + match[ 1 ] = match[ 1 ].toLowerCase(); + + if ( match[ 1 ].slice( 0, 3 ) === "nth" ) { + + // nth-* requires argument + if ( !match[ 3 ] ) { + Sizzle.error( match[ 0 ] ); + } + + // numeric x and y parameters for Expr.filter.CHILD + // remember that false/true cast respectively to 0/1 + match[ 4 ] = +( match[ 4 ] ? + match[ 5 ] + ( match[ 6 ] || 1 ) : + 2 * ( match[ 3 ] === "even" || match[ 3 ] === "odd" ) ); + match[ 5 ] = +( ( match[ 7 ] + match[ 8 ] ) || match[ 3 ] === "odd" ); + + // other types prohibit arguments + } else if ( match[ 3 ] ) { + Sizzle.error( match[ 0 ] ); + } + + return match; + }, + + "PSEUDO": function( match ) { + var excess, + unquoted = !match[ 6 ] && match[ 2 ]; + + if ( matchExpr[ "CHILD" ].test( match[ 0 ] ) ) { + return null; + } + + // Accept quoted arguments as-is + if ( match[ 3 ] ) { + match[ 2 ] = match[ 4 ] || match[ 5 ] || ""; + + // Strip excess characters from unquoted arguments + } else if ( unquoted && rpseudo.test( unquoted ) && + + // Get excess from tokenize (recursively) + ( excess = tokenize( unquoted, true ) ) && + + // advance to the next closing parenthesis + ( excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length ) ) { + + // excess is a negative index + match[ 0 ] = match[ 0 ].slice( 0, excess ); + match[ 2 ] = unquoted.slice( 0, excess ); + } + + // Return only captures needed by the pseudo filter method (type and argument) + return match.slice( 0, 3 ); + } + }, + + filter: { + + "TAG": function( nodeNameSelector ) { + var nodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase(); + return nodeNameSelector === "*" ? + function() { + return true; + } : + function( elem ) { + return elem.nodeName && elem.nodeName.toLowerCase() === nodeName; + }; + }, + + "CLASS": function( className ) { + var pattern = classCache[ className + " " ]; + + return pattern || + ( pattern = new RegExp( "(^|" + whitespace + + ")" + className + "(" + whitespace + "|$)" ) ) && classCache( + className, function( elem ) { + return pattern.test( + typeof elem.className === "string" && elem.className || + typeof elem.getAttribute !== "undefined" && + elem.getAttribute( "class" ) || + "" + ); + } ); + }, + + "ATTR": function( name, operator, check ) { + return function( elem ) { + var result = Sizzle.attr( elem, name ); + + if ( result == null ) { + return operator === "!="; + } + if ( !operator ) { + return true; + } + + result += ""; + + /* eslint-disable max-len */ + + return operator === "=" ? result === check : + operator === "!=" ? result !== check : + operator === "^=" ? check && result.indexOf( check ) === 0 : + operator === "*=" ? check && result.indexOf( check ) > -1 : + operator === "$=" ? check && result.slice( -check.length ) === check : + operator === "~=" ? ( " " + result.replace( rwhitespace, " " ) + " " ).indexOf( check ) > -1 : + operator === "|=" ? result === check || result.slice( 0, check.length + 1 ) === check + "-" : + false; + /* eslint-enable max-len */ + + }; + }, + + "CHILD": function( type, what, _argument, first, last ) { + var simple = type.slice( 0, 3 ) !== "nth", + forward = type.slice( -4 ) !== "last", + ofType = what === "of-type"; + + return first === 1 && last === 0 ? + + // Shortcut for :nth-*(n) + function( elem ) { + return !!elem.parentNode; + } : + + function( elem, _context, xml ) { + var cache, uniqueCache, outerCache, node, nodeIndex, start, + dir = simple !== forward ? "nextSibling" : "previousSibling", + parent = elem.parentNode, + name = ofType && elem.nodeName.toLowerCase(), + useCache = !xml && !ofType, + diff = false; + + if ( parent ) { + + // :(first|last|only)-(child|of-type) + if ( simple ) { + while ( dir ) { + node = elem; + while ( ( node = node[ dir ] ) ) { + if ( ofType ? + node.nodeName.toLowerCase() === name : + node.nodeType === 1 ) { + + return false; + } + } + + // Reverse direction for :only-* (if we haven't yet done so) + start = dir = type === "only" && !start && "nextSibling"; + } + return true; + } + + start = [ forward ? parent.firstChild : parent.lastChild ]; + + // non-xml :nth-child(...) stores cache data on `parent` + if ( forward && useCache ) { + + // Seek `elem` from a previously-cached index + + // ...in a gzip-friendly way + node = parent; + outerCache = node[ expando ] || ( node[ expando ] = {} ); + + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ node.uniqueID ] || + ( outerCache[ node.uniqueID ] = {} ); + + cache = uniqueCache[ type ] || []; + nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ]; + diff = nodeIndex && cache[ 2 ]; + node = nodeIndex && parent.childNodes[ nodeIndex ]; + + while ( ( node = ++nodeIndex && node && node[ dir ] || + + // Fallback to seeking `elem` from the start + ( diff = nodeIndex = 0 ) || start.pop() ) ) { + + // When found, cache indexes on `parent` and break + if ( node.nodeType === 1 && ++diff && node === elem ) { + uniqueCache[ type ] = [ dirruns, nodeIndex, diff ]; + break; + } + } + + } else { + + // Use previously-cached element index if available + if ( useCache ) { + + // ...in a gzip-friendly way + node = elem; + outerCache = node[ expando ] || ( node[ expando ] = {} ); + + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ node.uniqueID ] || + ( outerCache[ node.uniqueID ] = {} ); + + cache = uniqueCache[ type ] || []; + nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ]; + diff = nodeIndex; + } + + // xml :nth-child(...) + // or :nth-last-child(...) or :nth(-last)?-of-type(...) + if ( diff === false ) { + + // Use the same loop as above to seek `elem` from the start + while ( ( node = ++nodeIndex && node && node[ dir ] || + ( diff = nodeIndex = 0 ) || start.pop() ) ) { + + if ( ( ofType ? + node.nodeName.toLowerCase() === name : + node.nodeType === 1 ) && + ++diff ) { + + // Cache the index of each encountered element + if ( useCache ) { + outerCache = node[ expando ] || + ( node[ expando ] = {} ); + + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ node.uniqueID ] || + ( outerCache[ node.uniqueID ] = {} ); + + uniqueCache[ type ] = [ dirruns, diff ]; + } + + if ( node === elem ) { + break; + } + } + } + } + } + + // Incorporate the offset, then check against cycle size + diff -= last; + return diff === first || ( diff % first === 0 && diff / first >= 0 ); + } + }; + }, + + "PSEUDO": function( pseudo, argument ) { + + // pseudo-class names are case-insensitive + // http://www.w3.org/TR/selectors/#pseudo-classes + // Prioritize by case sensitivity in case custom pseudos are added with uppercase letters + // Remember that setFilters inherits from pseudos + var args, + fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] || + Sizzle.error( "unsupported pseudo: " + pseudo ); + + // The user may use createPseudo to indicate that + // arguments are needed to create the filter function + // just as Sizzle does + if ( fn[ expando ] ) { + return fn( argument ); + } + + // But maintain support for old signatures + if ( fn.length > 1 ) { + args = [ pseudo, pseudo, "", argument ]; + return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ? + markFunction( function( seed, matches ) { + var idx, + matched = fn( seed, argument ), + i = matched.length; + while ( i-- ) { + idx = indexOf( seed, matched[ i ] ); + seed[ idx ] = !( matches[ idx ] = matched[ i ] ); + } + } ) : + function( elem ) { + return fn( elem, 0, args ); + }; + } + + return fn; + } + }, + + pseudos: { + + // Potentially complex pseudos + "not": markFunction( function( selector ) { + + // Trim the selector passed to compile + // to avoid treating leading and trailing + // spaces as combinators + var input = [], + results = [], + matcher = compile( selector.replace( rtrim, "$1" ) ); + + return matcher[ expando ] ? + markFunction( function( seed, matches, _context, xml ) { + var elem, + unmatched = matcher( seed, null, xml, [] ), + i = seed.length; + + // Match elements unmatched by `matcher` + while ( i-- ) { + if ( ( elem = unmatched[ i ] ) ) { + seed[ i ] = !( matches[ i ] = elem ); + } + } + } ) : + function( elem, _context, xml ) { + input[ 0 ] = elem; + matcher( input, null, xml, results ); + + // Don't keep the element (issue #299) + input[ 0 ] = null; + return !results.pop(); + }; + } ), + + "has": markFunction( function( selector ) { + return function( elem ) { + return Sizzle( selector, elem ).length > 0; + }; + } ), + + "contains": markFunction( function( text ) { + text = text.replace( runescape, funescape ); + return function( elem ) { + return ( elem.textContent || getText( elem ) ).indexOf( text ) > -1; + }; + } ), + + // "Whether an element is represented by a :lang() selector + // is based solely on the element's language value + // being equal to the identifier C, + // or beginning with the identifier C immediately followed by "-". + // The matching of C against the element's language value is performed case-insensitively. + // The identifier C does not have to be a valid language name." + // http://www.w3.org/TR/selectors/#lang-pseudo + "lang": markFunction( function( lang ) { + + // lang value must be a valid identifier + if ( !ridentifier.test( lang || "" ) ) { + Sizzle.error( "unsupported lang: " + lang ); + } + lang = lang.replace( runescape, funescape ).toLowerCase(); + return function( elem ) { + var elemLang; + do { + if ( ( elemLang = documentIsHTML ? + elem.lang : + elem.getAttribute( "xml:lang" ) || elem.getAttribute( "lang" ) ) ) { + + elemLang = elemLang.toLowerCase(); + return elemLang === lang || elemLang.indexOf( lang + "-" ) === 0; + } + } while ( ( elem = elem.parentNode ) && elem.nodeType === 1 ); + return false; + }; + } ), + + // Miscellaneous + "target": function( elem ) { + var hash = window.location && window.location.hash; + return hash && hash.slice( 1 ) === elem.id; + }, + + "root": function( elem ) { + return elem === docElem; + }, + + "focus": function( elem ) { + return elem === document.activeElement && + ( !document.hasFocus || document.hasFocus() ) && + !!( elem.type || elem.href || ~elem.tabIndex ); + }, + + // Boolean properties + "enabled": createDisabledPseudo( false ), + "disabled": createDisabledPseudo( true ), + + "checked": function( elem ) { + + // In CSS3, :checked should return both checked and selected elements + // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked + var nodeName = elem.nodeName.toLowerCase(); + return ( nodeName === "input" && !!elem.checked ) || + ( nodeName === "option" && !!elem.selected ); + }, + + "selected": function( elem ) { + + // Accessing this property makes selected-by-default + // options in Safari work properly + if ( elem.parentNode ) { + // eslint-disable-next-line no-unused-expressions + elem.parentNode.selectedIndex; + } + + return elem.selected === true; + }, + + // Contents + "empty": function( elem ) { + + // http://www.w3.org/TR/selectors/#empty-pseudo + // :empty is negated by element (1) or content nodes (text: 3; cdata: 4; entity ref: 5), + // but not by others (comment: 8; processing instruction: 7; etc.) + // nodeType < 6 works because attributes (2) do not appear as children + for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { + if ( elem.nodeType < 6 ) { + return false; + } + } + return true; + }, + + "parent": function( elem ) { + return !Expr.pseudos[ "empty" ]( elem ); + }, + + // Element/input types + "header": function( elem ) { + return rheader.test( elem.nodeName ); + }, + + "input": function( elem ) { + return rinputs.test( elem.nodeName ); + }, + + "button": function( elem ) { + var name = elem.nodeName.toLowerCase(); + return name === "input" && elem.type === "button" || name === "button"; + }, + + "text": function( elem ) { + var attr; + return elem.nodeName.toLowerCase() === "input" && + elem.type === "text" && + + // Support: IE<8 + // New HTML5 attribute values (e.g., "search") appear with elem.type === "text" + ( ( attr = elem.getAttribute( "type" ) ) == null || + attr.toLowerCase() === "text" ); + }, + + // Position-in-collection + "first": createPositionalPseudo( function() { + return [ 0 ]; + } ), + + "last": createPositionalPseudo( function( _matchIndexes, length ) { + return [ length - 1 ]; + } ), + + "eq": createPositionalPseudo( function( _matchIndexes, length, argument ) { + return [ argument < 0 ? argument + length : argument ]; + } ), + + "even": createPositionalPseudo( function( matchIndexes, length ) { + var i = 0; + for ( ; i < length; i += 2 ) { + matchIndexes.push( i ); + } + return matchIndexes; + } ), + + "odd": createPositionalPseudo( function( matchIndexes, length ) { + var i = 1; + for ( ; i < length; i += 2 ) { + matchIndexes.push( i ); + } + return matchIndexes; + } ), + + "lt": createPositionalPseudo( function( matchIndexes, length, argument ) { + var i = argument < 0 ? + argument + length : + argument > length ? + length : + argument; + for ( ; --i >= 0; ) { + matchIndexes.push( i ); + } + return matchIndexes; + } ), + + "gt": createPositionalPseudo( function( matchIndexes, length, argument ) { + var i = argument < 0 ? argument + length : argument; + for ( ; ++i < length; ) { + matchIndexes.push( i ); + } + return matchIndexes; + } ) + } +}; + +Expr.pseudos[ "nth" ] = Expr.pseudos[ "eq" ]; + +// Add button/input type pseudos +for ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) { + Expr.pseudos[ i ] = createInputPseudo( i ); +} +for ( i in { submit: true, reset: true } ) { + Expr.pseudos[ i ] = createButtonPseudo( i ); +} + +// Easy API for creating new setFilters +function setFilters() {} +setFilters.prototype = Expr.filters = Expr.pseudos; +Expr.setFilters = new setFilters(); + +tokenize = Sizzle.tokenize = function( selector, parseOnly ) { + var matched, match, tokens, type, + soFar, groups, preFilters, + cached = tokenCache[ selector + " " ]; + + if ( cached ) { + return parseOnly ? 0 : cached.slice( 0 ); + } + + soFar = selector; + groups = []; + preFilters = Expr.preFilter; + + while ( soFar ) { + + // Comma and first run + if ( !matched || ( match = rcomma.exec( soFar ) ) ) { + if ( match ) { + + // Don't consume trailing commas as valid + soFar = soFar.slice( match[ 0 ].length ) || soFar; + } + groups.push( ( tokens = [] ) ); + } + + matched = false; + + // Combinators + if ( ( match = rcombinators.exec( soFar ) ) ) { + matched = match.shift(); + tokens.push( { + value: matched, + + // Cast descendant combinators to space + type: match[ 0 ].replace( rtrim, " " ) + } ); + soFar = soFar.slice( matched.length ); + } + + // Filters + for ( type in Expr.filter ) { + if ( ( match = matchExpr[ type ].exec( soFar ) ) && ( !preFilters[ type ] || + ( match = preFilters[ type ]( match ) ) ) ) { + matched = match.shift(); + tokens.push( { + value: matched, + type: type, + matches: match + } ); + soFar = soFar.slice( matched.length ); + } + } + + if ( !matched ) { + break; + } + } + + // Return the length of the invalid excess + // if we're just parsing + // Otherwise, throw an error or return tokens + return parseOnly ? + soFar.length : + soFar ? + Sizzle.error( selector ) : + + // Cache the tokens + tokenCache( selector, groups ).slice( 0 ); +}; + +function toSelector( tokens ) { + var i = 0, + len = tokens.length, + selector = ""; + for ( ; i < len; i++ ) { + selector += tokens[ i ].value; + } + return selector; +} + +function addCombinator( matcher, combinator, base ) { + var dir = combinator.dir, + skip = combinator.next, + key = skip || dir, + checkNonElements = base && key === "parentNode", + doneName = done++; + + return combinator.first ? + + // Check against closest ancestor/preceding element + function( elem, context, xml ) { + while ( ( elem = elem[ dir ] ) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + return matcher( elem, context, xml ); + } + } + return false; + } : + + // Check against all ancestor/preceding elements + function( elem, context, xml ) { + var oldCache, uniqueCache, outerCache, + newCache = [ dirruns, doneName ]; + + // We can't set arbitrary data on XML nodes, so they don't benefit from combinator caching + if ( xml ) { + while ( ( elem = elem[ dir ] ) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + if ( matcher( elem, context, xml ) ) { + return true; + } + } + } + } else { + while ( ( elem = elem[ dir ] ) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + outerCache = elem[ expando ] || ( elem[ expando ] = {} ); + + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ elem.uniqueID ] || + ( outerCache[ elem.uniqueID ] = {} ); + + if ( skip && skip === elem.nodeName.toLowerCase() ) { + elem = elem[ dir ] || elem; + } else if ( ( oldCache = uniqueCache[ key ] ) && + oldCache[ 0 ] === dirruns && oldCache[ 1 ] === doneName ) { + + // Assign to newCache so results back-propagate to previous elements + return ( newCache[ 2 ] = oldCache[ 2 ] ); + } else { + + // Reuse newcache so results back-propagate to previous elements + uniqueCache[ key ] = newCache; + + // A match means we're done; a fail means we have to keep checking + if ( ( newCache[ 2 ] = matcher( elem, context, xml ) ) ) { + return true; + } + } + } + } + } + return false; + }; +} + +function elementMatcher( matchers ) { + return matchers.length > 1 ? + function( elem, context, xml ) { + var i = matchers.length; + while ( i-- ) { + if ( !matchers[ i ]( elem, context, xml ) ) { + return false; + } + } + return true; + } : + matchers[ 0 ]; +} + +function multipleContexts( selector, contexts, results ) { + var i = 0, + len = contexts.length; + for ( ; i < len; i++ ) { + Sizzle( selector, contexts[ i ], results ); + } + return results; +} + +function condense( unmatched, map, filter, context, xml ) { + var elem, + newUnmatched = [], + i = 0, + len = unmatched.length, + mapped = map != null; + + for ( ; i < len; i++ ) { + if ( ( elem = unmatched[ i ] ) ) { + if ( !filter || filter( elem, context, xml ) ) { + newUnmatched.push( elem ); + if ( mapped ) { + map.push( i ); + } + } + } + } + + return newUnmatched; +} + +function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) { + if ( postFilter && !postFilter[ expando ] ) { + postFilter = setMatcher( postFilter ); + } + if ( postFinder && !postFinder[ expando ] ) { + postFinder = setMatcher( postFinder, postSelector ); + } + return markFunction( function( seed, results, context, xml ) { + var temp, i, elem, + preMap = [], + postMap = [], + preexisting = results.length, + + // Get initial elements from seed or context + elems = seed || multipleContexts( + selector || "*", + context.nodeType ? [ context ] : context, + [] + ), + + // Prefilter to get matcher input, preserving a map for seed-results synchronization + matcherIn = preFilter && ( seed || !selector ) ? + condense( elems, preMap, preFilter, context, xml ) : + elems, + + matcherOut = matcher ? + + // If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results, + postFinder || ( seed ? preFilter : preexisting || postFilter ) ? + + // ...intermediate processing is necessary + [] : + + // ...otherwise use results directly + results : + matcherIn; + + // Find primary matches + if ( matcher ) { + matcher( matcherIn, matcherOut, context, xml ); + } + + // Apply postFilter + if ( postFilter ) { + temp = condense( matcherOut, postMap ); + postFilter( temp, [], context, xml ); + + // Un-match failing elements by moving them back to matcherIn + i = temp.length; + while ( i-- ) { + if ( ( elem = temp[ i ] ) ) { + matcherOut[ postMap[ i ] ] = !( matcherIn[ postMap[ i ] ] = elem ); + } + } + } + + if ( seed ) { + if ( postFinder || preFilter ) { + if ( postFinder ) { + + // Get the final matcherOut by condensing this intermediate into postFinder contexts + temp = []; + i = matcherOut.length; + while ( i-- ) { + if ( ( elem = matcherOut[ i ] ) ) { + + // Restore matcherIn since elem is not yet a final match + temp.push( ( matcherIn[ i ] = elem ) ); + } + } + postFinder( null, ( matcherOut = [] ), temp, xml ); + } + + // Move matched elements from seed to results to keep them synchronized + i = matcherOut.length; + while ( i-- ) { + if ( ( elem = matcherOut[ i ] ) && + ( temp = postFinder ? indexOf( seed, elem ) : preMap[ i ] ) > -1 ) { + + seed[ temp ] = !( results[ temp ] = elem ); + } + } + } + + // Add elements to results, through postFinder if defined + } else { + matcherOut = condense( + matcherOut === results ? + matcherOut.splice( preexisting, matcherOut.length ) : + matcherOut + ); + if ( postFinder ) { + postFinder( null, results, matcherOut, xml ); + } else { + push.apply( results, matcherOut ); + } + } + } ); +} + +function matcherFromTokens( tokens ) { + var checkContext, matcher, j, + len = tokens.length, + leadingRelative = Expr.relative[ tokens[ 0 ].type ], + implicitRelative = leadingRelative || Expr.relative[ " " ], + i = leadingRelative ? 1 : 0, + + // The foundational matcher ensures that elements are reachable from top-level context(s) + matchContext = addCombinator( function( elem ) { + return elem === checkContext; + }, implicitRelative, true ), + matchAnyContext = addCombinator( function( elem ) { + return indexOf( checkContext, elem ) > -1; + }, implicitRelative, true ), + matchers = [ function( elem, context, xml ) { + var ret = ( !leadingRelative && ( xml || context !== outermostContext ) ) || ( + ( checkContext = context ).nodeType ? + matchContext( elem, context, xml ) : + matchAnyContext( elem, context, xml ) ); + + // Avoid hanging onto element (issue #299) + checkContext = null; + return ret; + } ]; + + for ( ; i < len; i++ ) { + if ( ( matcher = Expr.relative[ tokens[ i ].type ] ) ) { + matchers = [ addCombinator( elementMatcher( matchers ), matcher ) ]; + } else { + matcher = Expr.filter[ tokens[ i ].type ].apply( null, tokens[ i ].matches ); + + // Return special upon seeing a positional matcher + if ( matcher[ expando ] ) { + + // Find the next relative operator (if any) for proper handling + j = ++i; + for ( ; j < len; j++ ) { + if ( Expr.relative[ tokens[ j ].type ] ) { + break; + } + } + return setMatcher( + i > 1 && elementMatcher( matchers ), + i > 1 && toSelector( + + // If the preceding token was a descendant combinator, insert an implicit any-element `*` + tokens + .slice( 0, i - 1 ) + .concat( { value: tokens[ i - 2 ].type === " " ? "*" : "" } ) + ).replace( rtrim, "$1" ), + matcher, + i < j && matcherFromTokens( tokens.slice( i, j ) ), + j < len && matcherFromTokens( ( tokens = tokens.slice( j ) ) ), + j < len && toSelector( tokens ) + ); + } + matchers.push( matcher ); + } + } + + return elementMatcher( matchers ); +} + +function matcherFromGroupMatchers( elementMatchers, setMatchers ) { + var bySet = setMatchers.length > 0, + byElement = elementMatchers.length > 0, + superMatcher = function( seed, context, xml, results, outermost ) { + var elem, j, matcher, + matchedCount = 0, + i = "0", + unmatched = seed && [], + setMatched = [], + contextBackup = outermostContext, + + // We must always have either seed elements or outermost context + elems = seed || byElement && Expr.find[ "TAG" ]( "*", outermost ), + + // Use integer dirruns iff this is the outermost matcher + dirrunsUnique = ( dirruns += contextBackup == null ? 1 : Math.random() || 0.1 ), + len = elems.length; + + if ( outermost ) { + + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + outermostContext = context == document || context || outermost; + } + + // Add elements passing elementMatchers directly to results + // Support: IE<9, Safari + // Tolerate NodeList properties (IE: "length"; Safari: ) matching elements by id + for ( ; i !== len && ( elem = elems[ i ] ) != null; i++ ) { + if ( byElement && elem ) { + j = 0; + + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( !context && elem.ownerDocument != document ) { + setDocument( elem ); + xml = !documentIsHTML; + } + while ( ( matcher = elementMatchers[ j++ ] ) ) { + if ( matcher( elem, context || document, xml ) ) { + results.push( elem ); + break; + } + } + if ( outermost ) { + dirruns = dirrunsUnique; + } + } + + // Track unmatched elements for set filters + if ( bySet ) { + + // They will have gone through all possible matchers + if ( ( elem = !matcher && elem ) ) { + matchedCount--; + } + + // Lengthen the array for every element, matched or not + if ( seed ) { + unmatched.push( elem ); + } + } + } + + // `i` is now the count of elements visited above, and adding it to `matchedCount` + // makes the latter nonnegative. + matchedCount += i; + + // Apply set filters to unmatched elements + // NOTE: This can be skipped if there are no unmatched elements (i.e., `matchedCount` + // equals `i`), unless we didn't visit _any_ elements in the above loop because we have + // no element matchers and no seed. + // Incrementing an initially-string "0" `i` allows `i` to remain a string only in that + // case, which will result in a "00" `matchedCount` that differs from `i` but is also + // numerically zero. + if ( bySet && i !== matchedCount ) { + j = 0; + while ( ( matcher = setMatchers[ j++ ] ) ) { + matcher( unmatched, setMatched, context, xml ); + } + + if ( seed ) { + + // Reintegrate element matches to eliminate the need for sorting + if ( matchedCount > 0 ) { + while ( i-- ) { + if ( !( unmatched[ i ] || setMatched[ i ] ) ) { + setMatched[ i ] = pop.call( results ); + } + } + } + + // Discard index placeholder values to get only actual matches + setMatched = condense( setMatched ); + } + + // Add matches to results + push.apply( results, setMatched ); + + // Seedless set matches succeeding multiple successful matchers stipulate sorting + if ( outermost && !seed && setMatched.length > 0 && + ( matchedCount + setMatchers.length ) > 1 ) { + + Sizzle.uniqueSort( results ); + } + } + + // Override manipulation of globals by nested matchers + if ( outermost ) { + dirruns = dirrunsUnique; + outermostContext = contextBackup; + } + + return unmatched; + }; + + return bySet ? + markFunction( superMatcher ) : + superMatcher; +} + +compile = Sizzle.compile = function( selector, match /* Internal Use Only */ ) { + var i, + setMatchers = [], + elementMatchers = [], + cached = compilerCache[ selector + " " ]; + + if ( !cached ) { + + // Generate a function of recursive functions that can be used to check each element + if ( !match ) { + match = tokenize( selector ); + } + i = match.length; + while ( i-- ) { + cached = matcherFromTokens( match[ i ] ); + if ( cached[ expando ] ) { + setMatchers.push( cached ); + } else { + elementMatchers.push( cached ); + } + } + + // Cache the compiled function + cached = compilerCache( + selector, + matcherFromGroupMatchers( elementMatchers, setMatchers ) + ); + + // Save selector and tokenization + cached.selector = selector; + } + return cached; +}; + +/** + * A low-level selection function that works with Sizzle's compiled + * selector functions + * @param {String|Function} selector A selector or a pre-compiled + * selector function built with Sizzle.compile + * @param {Element} context + * @param {Array} [results] + * @param {Array} [seed] A set of elements to match against + */ +select = Sizzle.select = function( selector, context, results, seed ) { + var i, tokens, token, type, find, + compiled = typeof selector === "function" && selector, + match = !seed && tokenize( ( selector = compiled.selector || selector ) ); + + results = results || []; + + // Try to minimize operations if there is only one selector in the list and no seed + // (the latter of which guarantees us context) + if ( match.length === 1 ) { + + // Reduce context if the leading compound selector is an ID + tokens = match[ 0 ] = match[ 0 ].slice( 0 ); + if ( tokens.length > 2 && ( token = tokens[ 0 ] ).type === "ID" && + context.nodeType === 9 && documentIsHTML && Expr.relative[ tokens[ 1 ].type ] ) { + + context = ( Expr.find[ "ID" ]( token.matches[ 0 ] + .replace( runescape, funescape ), context ) || [] )[ 0 ]; + if ( !context ) { + return results; + + // Precompiled matchers will still verify ancestry, so step up a level + } else if ( compiled ) { + context = context.parentNode; + } + + selector = selector.slice( tokens.shift().value.length ); + } + + // Fetch a seed set for right-to-left matching + i = matchExpr[ "needsContext" ].test( selector ) ? 0 : tokens.length; + while ( i-- ) { + token = tokens[ i ]; + + // Abort if we hit a combinator + if ( Expr.relative[ ( type = token.type ) ] ) { + break; + } + if ( ( find = Expr.find[ type ] ) ) { + + // Search, expanding context for leading sibling combinators + if ( ( seed = find( + token.matches[ 0 ].replace( runescape, funescape ), + rsibling.test( tokens[ 0 ].type ) && testContext( context.parentNode ) || + context + ) ) ) { + + // If seed is empty or no tokens remain, we can return early + tokens.splice( i, 1 ); + selector = seed.length && toSelector( tokens ); + if ( !selector ) { + push.apply( results, seed ); + return results; + } + + break; + } + } + } + } + + // Compile and execute a filtering function if one is not provided + // Provide `match` to avoid retokenization if we modified the selector above + ( compiled || compile( selector, match ) )( + seed, + context, + !documentIsHTML, + results, + !context || rsibling.test( selector ) && testContext( context.parentNode ) || context + ); + return results; +}; + +// One-time assignments + +// Sort stability +support.sortStable = expando.split( "" ).sort( sortOrder ).join( "" ) === expando; + +// Support: Chrome 14-35+ +// Always assume duplicates if they aren't passed to the comparison function +support.detectDuplicates = !!hasDuplicate; + +// Initialize against the default document +setDocument(); + +// Support: Webkit<537.32 - Safari 6.0.3/Chrome 25 (fixed in Chrome 27) +// Detached nodes confoundingly follow *each other* +support.sortDetached = assert( function( el ) { + + // Should return 1, but returns 4 (following) + return el.compareDocumentPosition( document.createElement( "fieldset" ) ) & 1; +} ); + +// Support: IE<8 +// Prevent attribute/property "interpolation" +// https://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx +if ( !assert( function( el ) { + el.innerHTML = ""; + return el.firstChild.getAttribute( "href" ) === "#"; +} ) ) { + addHandle( "type|href|height|width", function( elem, name, isXML ) { + if ( !isXML ) { + return elem.getAttribute( name, name.toLowerCase() === "type" ? 1 : 2 ); + } + } ); +} + +// Support: IE<9 +// Use defaultValue in place of getAttribute("value") +if ( !support.attributes || !assert( function( el ) { + el.innerHTML = ""; + el.firstChild.setAttribute( "value", "" ); + return el.firstChild.getAttribute( "value" ) === ""; +} ) ) { + addHandle( "value", function( elem, _name, isXML ) { + if ( !isXML && elem.nodeName.toLowerCase() === "input" ) { + return elem.defaultValue; + } + } ); +} + +// Support: IE<9 +// Use getAttributeNode to fetch booleans when getAttribute lies +if ( !assert( function( el ) { + return el.getAttribute( "disabled" ) == null; +} ) ) { + addHandle( booleans, function( elem, name, isXML ) { + var val; + if ( !isXML ) { + return elem[ name ] === true ? name.toLowerCase() : + ( val = elem.getAttributeNode( name ) ) && val.specified ? + val.value : + null; + } + } ); +} + +return Sizzle; + +} )( window ); + + + +jQuery.find = Sizzle; +jQuery.expr = Sizzle.selectors; + +// Deprecated +jQuery.expr[ ":" ] = jQuery.expr.pseudos; +jQuery.uniqueSort = jQuery.unique = Sizzle.uniqueSort; +jQuery.text = Sizzle.getText; +jQuery.isXMLDoc = Sizzle.isXML; +jQuery.contains = Sizzle.contains; +jQuery.escapeSelector = Sizzle.escape; + + + + +var dir = function( elem, dir, until ) { + var matched = [], + truncate = until !== undefined; + + while ( ( elem = elem[ dir ] ) && elem.nodeType !== 9 ) { + if ( elem.nodeType === 1 ) { + if ( truncate && jQuery( elem ).is( until ) ) { + break; + } + matched.push( elem ); + } + } + return matched; +}; + + +var siblings = function( n, elem ) { + var matched = []; + + for ( ; n; n = n.nextSibling ) { + if ( n.nodeType === 1 && n !== elem ) { + matched.push( n ); + } + } + + return matched; +}; + + +var rneedsContext = jQuery.expr.match.needsContext; + + + +function nodeName( elem, name ) { + + return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase(); + +}; +var rsingleTag = ( /^<([a-z][^\/\0>:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i ); + + + +// Implement the identical functionality for filter and not +function winnow( elements, qualifier, not ) { + if ( isFunction( qualifier ) ) { + return jQuery.grep( elements, function( elem, i ) { + return !!qualifier.call( elem, i, elem ) !== not; + } ); + } + + // Single element + if ( qualifier.nodeType ) { + return jQuery.grep( elements, function( elem ) { + return ( elem === qualifier ) !== not; + } ); + } + + // Arraylike of elements (jQuery, arguments, Array) + if ( typeof qualifier !== "string" ) { + return jQuery.grep( elements, function( elem ) { + return ( indexOf.call( qualifier, elem ) > -1 ) !== not; + } ); + } + + // Filtered directly for both simple and complex selectors + return jQuery.filter( qualifier, elements, not ); +} + +jQuery.filter = function( expr, elems, not ) { + var elem = elems[ 0 ]; + + if ( not ) { + expr = ":not(" + expr + ")"; + } + + if ( elems.length === 1 && elem.nodeType === 1 ) { + return jQuery.find.matchesSelector( elem, expr ) ? [ elem ] : []; + } + + return jQuery.find.matches( expr, jQuery.grep( elems, function( elem ) { + return elem.nodeType === 1; + } ) ); +}; + +jQuery.fn.extend( { + find: function( selector ) { + var i, ret, + len = this.length, + self = this; + + if ( typeof selector !== "string" ) { + return this.pushStack( jQuery( selector ).filter( function() { + for ( i = 0; i < len; i++ ) { + if ( jQuery.contains( self[ i ], this ) ) { + return true; + } + } + } ) ); + } + + ret = this.pushStack( [] ); + + for ( i = 0; i < len; i++ ) { + jQuery.find( selector, self[ i ], ret ); + } + + return len > 1 ? jQuery.uniqueSort( ret ) : ret; + }, + filter: function( selector ) { + return this.pushStack( winnow( this, selector || [], false ) ); + }, + not: function( selector ) { + return this.pushStack( winnow( this, selector || [], true ) ); + }, + is: function( selector ) { + return !!winnow( + this, + + // If this is a positional/relative selector, check membership in the returned set + // so $("p:first").is("p:last") won't return true for a doc with two "p". + typeof selector === "string" && rneedsContext.test( selector ) ? + jQuery( selector ) : + selector || [], + false + ).length; + } +} ); + + +// Initialize a jQuery object + + +// A central reference to the root jQuery(document) +var rootjQuery, + + // A simple way to check for HTML strings + // Prioritize #id over to avoid XSS via location.hash (#9521) + // Strict HTML recognition (#11290: must start with <) + // Shortcut simple #id case for speed + rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]+))$/, + + init = jQuery.fn.init = function( selector, context, root ) { + var match, elem; + + // HANDLE: $(""), $(null), $(undefined), $(false) + if ( !selector ) { + return this; + } + + // Method init() accepts an alternate rootjQuery + // so migrate can support jQuery.sub (gh-2101) + root = root || rootjQuery; + + // Handle HTML strings + if ( typeof selector === "string" ) { + if ( selector[ 0 ] === "<" && + selector[ selector.length - 1 ] === ">" && + selector.length >= 3 ) { + + // Assume that strings that start and end with <> are HTML and skip the regex check + match = [ null, selector, null ]; + + } else { + match = rquickExpr.exec( selector ); + } + + // Match html or make sure no context is specified for #id + if ( match && ( match[ 1 ] || !context ) ) { + + // HANDLE: $(html) -> $(array) + if ( match[ 1 ] ) { + context = context instanceof jQuery ? context[ 0 ] : context; + + // Option to run scripts is true for back-compat + // Intentionally let the error be thrown if parseHTML is not present + jQuery.merge( this, jQuery.parseHTML( + match[ 1 ], + context && context.nodeType ? context.ownerDocument || context : document, + true + ) ); + + // HANDLE: $(html, props) + if ( rsingleTag.test( match[ 1 ] ) && jQuery.isPlainObject( context ) ) { + for ( match in context ) { + + // Properties of context are called as methods if possible + if ( isFunction( this[ match ] ) ) { + this[ match ]( context[ match ] ); + + // ...and otherwise set as attributes + } else { + this.attr( match, context[ match ] ); + } + } + } + + return this; + + // HANDLE: $(#id) + } else { + elem = document.getElementById( match[ 2 ] ); + + if ( elem ) { + + // Inject the element directly into the jQuery object + this[ 0 ] = elem; + this.length = 1; + } + return this; + } + + // HANDLE: $(expr, $(...)) + } else if ( !context || context.jquery ) { + return ( context || root ).find( selector ); + + // HANDLE: $(expr, context) + // (which is just equivalent to: $(context).find(expr) + } else { + return this.constructor( context ).find( selector ); + } + + // HANDLE: $(DOMElement) + } else if ( selector.nodeType ) { + this[ 0 ] = selector; + this.length = 1; + return this; + + // HANDLE: $(function) + // Shortcut for document ready + } else if ( isFunction( selector ) ) { + return root.ready !== undefined ? + root.ready( selector ) : + + // Execute immediately if ready is not present + selector( jQuery ); + } + + return jQuery.makeArray( selector, this ); + }; + +// Give the init function the jQuery prototype for later instantiation +init.prototype = jQuery.fn; + +// Initialize central reference +rootjQuery = jQuery( document ); + + +var rparentsprev = /^(?:parents|prev(?:Until|All))/, + + // Methods guaranteed to produce a unique set when starting from a unique set + guaranteedUnique = { + children: true, + contents: true, + next: true, + prev: true + }; + +jQuery.fn.extend( { + has: function( target ) { + var targets = jQuery( target, this ), + l = targets.length; + + return this.filter( function() { + var i = 0; + for ( ; i < l; i++ ) { + if ( jQuery.contains( this, targets[ i ] ) ) { + return true; + } + } + } ); + }, + + closest: function( selectors, context ) { + var cur, + i = 0, + l = this.length, + matched = [], + targets = typeof selectors !== "string" && jQuery( selectors ); + + // Positional selectors never match, since there's no _selection_ context + if ( !rneedsContext.test( selectors ) ) { + for ( ; i < l; i++ ) { + for ( cur = this[ i ]; cur && cur !== context; cur = cur.parentNode ) { + + // Always skip document fragments + if ( cur.nodeType < 11 && ( targets ? + targets.index( cur ) > -1 : + + // Don't pass non-elements to Sizzle + cur.nodeType === 1 && + jQuery.find.matchesSelector( cur, selectors ) ) ) { + + matched.push( cur ); + break; + } + } + } + } + + return this.pushStack( matched.length > 1 ? jQuery.uniqueSort( matched ) : matched ); + }, + + // Determine the position of an element within the set + index: function( elem ) { + + // No argument, return index in parent + if ( !elem ) { + return ( this[ 0 ] && this[ 0 ].parentNode ) ? this.first().prevAll().length : -1; + } + + // Index in selector + if ( typeof elem === "string" ) { + return indexOf.call( jQuery( elem ), this[ 0 ] ); + } + + // Locate the position of the desired element + return indexOf.call( this, + + // If it receives a jQuery object, the first element is used + elem.jquery ? elem[ 0 ] : elem + ); + }, + + add: function( selector, context ) { + return this.pushStack( + jQuery.uniqueSort( + jQuery.merge( this.get(), jQuery( selector, context ) ) + ) + ); + }, + + addBack: function( selector ) { + return this.add( selector == null ? + this.prevObject : this.prevObject.filter( selector ) + ); + } +} ); + +function sibling( cur, dir ) { + while ( ( cur = cur[ dir ] ) && cur.nodeType !== 1 ) {} + return cur; +} + +jQuery.each( { + parent: function( elem ) { + var parent = elem.parentNode; + return parent && parent.nodeType !== 11 ? parent : null; + }, + parents: function( elem ) { + return dir( elem, "parentNode" ); + }, + parentsUntil: function( elem, _i, until ) { + return dir( elem, "parentNode", until ); + }, + next: function( elem ) { + return sibling( elem, "nextSibling" ); + }, + prev: function( elem ) { + return sibling( elem, "previousSibling" ); + }, + nextAll: function( elem ) { + return dir( elem, "nextSibling" ); + }, + prevAll: function( elem ) { + return dir( elem, "previousSibling" ); + }, + nextUntil: function( elem, _i, until ) { + return dir( elem, "nextSibling", until ); + }, + prevUntil: function( elem, _i, until ) { + return dir( elem, "previousSibling", until ); + }, + siblings: function( elem ) { + return siblings( ( elem.parentNode || {} ).firstChild, elem ); + }, + children: function( elem ) { + return siblings( elem.firstChild ); + }, + contents: function( elem ) { + if ( elem.contentDocument != null && + + // Support: IE 11+ + // elements with no `data` attribute has an object + // `contentDocument` with a `null` prototype. + getProto( elem.contentDocument ) ) { + + return elem.contentDocument; + } + + // Support: IE 9 - 11 only, iOS 7 only, Android Browser <=4.3 only + // Treat the template element as a regular one in browsers that + // don't support it. + if ( nodeName( elem, "template" ) ) { + elem = elem.content || elem; + } + + return jQuery.merge( [], elem.childNodes ); + } +}, function( name, fn ) { + jQuery.fn[ name ] = function( until, selector ) { + var matched = jQuery.map( this, fn, until ); + + if ( name.slice( -5 ) !== "Until" ) { + selector = until; + } + + if ( selector && typeof selector === "string" ) { + matched = jQuery.filter( selector, matched ); + } + + if ( this.length > 1 ) { + + // Remove duplicates + if ( !guaranteedUnique[ name ] ) { + jQuery.uniqueSort( matched ); + } + + // Reverse order for parents* and prev-derivatives + if ( rparentsprev.test( name ) ) { + matched.reverse(); + } + } + + return this.pushStack( matched ); + }; +} ); +var rnothtmlwhite = ( /[^\x20\t\r\n\f]+/g ); + + + +// Convert String-formatted options into Object-formatted ones +function createOptions( options ) { + var object = {}; + jQuery.each( options.match( rnothtmlwhite ) || [], function( _, flag ) { + object[ flag ] = true; + } ); + return object; +} + +/* + * Create a callback list using the following parameters: + * + * options: an optional list of space-separated options that will change how + * the callback list behaves or a more traditional option object + * + * By default a callback list will act like an event callback list and can be + * "fired" multiple times. + * + * Possible options: + * + * once: will ensure the callback list can only be fired once (like a Deferred) + * + * memory: will keep track of previous values and will call any callback added + * after the list has been fired right away with the latest "memorized" + * values (like a Deferred) + * + * unique: will ensure a callback can only be added once (no duplicate in the list) + * + * stopOnFalse: interrupt callings when a callback returns false + * + */ +jQuery.Callbacks = function( options ) { + + // Convert options from String-formatted to Object-formatted if needed + // (we check in cache first) + options = typeof options === "string" ? + createOptions( options ) : + jQuery.extend( {}, options ); + + var // Flag to know if list is currently firing + firing, + + // Last fire value for non-forgettable lists + memory, + + // Flag to know if list was already fired + fired, + + // Flag to prevent firing + locked, + + // Actual callback list + list = [], + + // Queue of execution data for repeatable lists + queue = [], + + // Index of currently firing callback (modified by add/remove as needed) + firingIndex = -1, + + // Fire callbacks + fire = function() { + + // Enforce single-firing + locked = locked || options.once; + + // Execute callbacks for all pending executions, + // respecting firingIndex overrides and runtime changes + fired = firing = true; + for ( ; queue.length; firingIndex = -1 ) { + memory = queue.shift(); + while ( ++firingIndex < list.length ) { + + // Run callback and check for early termination + if ( list[ firingIndex ].apply( memory[ 0 ], memory[ 1 ] ) === false && + options.stopOnFalse ) { + + // Jump to end and forget the data so .add doesn't re-fire + firingIndex = list.length; + memory = false; + } + } + } + + // Forget the data if we're done with it + if ( !options.memory ) { + memory = false; + } + + firing = false; + + // Clean up if we're done firing for good + if ( locked ) { + + // Keep an empty list if we have data for future add calls + if ( memory ) { + list = []; + + // Otherwise, this object is spent + } else { + list = ""; + } + } + }, + + // Actual Callbacks object + self = { + + // Add a callback or a collection of callbacks to the list + add: function() { + if ( list ) { + + // If we have memory from a past run, we should fire after adding + if ( memory && !firing ) { + firingIndex = list.length - 1; + queue.push( memory ); + } + + ( function add( args ) { + jQuery.each( args, function( _, arg ) { + if ( isFunction( arg ) ) { + if ( !options.unique || !self.has( arg ) ) { + list.push( arg ); + } + } else if ( arg && arg.length && toType( arg ) !== "string" ) { + + // Inspect recursively + add( arg ); + } + } ); + } )( arguments ); + + if ( memory && !firing ) { + fire(); + } + } + return this; + }, + + // Remove a callback from the list + remove: function() { + jQuery.each( arguments, function( _, arg ) { + var index; + while ( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) { + list.splice( index, 1 ); + + // Handle firing indexes + if ( index <= firingIndex ) { + firingIndex--; + } + } + } ); + return this; + }, + + // Check if a given callback is in the list. + // If no argument is given, return whether or not list has callbacks attached. + has: function( fn ) { + return fn ? + jQuery.inArray( fn, list ) > -1 : + list.length > 0; + }, + + // Remove all callbacks from the list + empty: function() { + if ( list ) { + list = []; + } + return this; + }, + + // Disable .fire and .add + // Abort any current/pending executions + // Clear all callbacks and values + disable: function() { + locked = queue = []; + list = memory = ""; + return this; + }, + disabled: function() { + return !list; + }, + + // Disable .fire + // Also disable .add unless we have memory (since it would have no effect) + // Abort any pending executions + lock: function() { + locked = queue = []; + if ( !memory && !firing ) { + list = memory = ""; + } + return this; + }, + locked: function() { + return !!locked; + }, + + // Call all callbacks with the given context and arguments + fireWith: function( context, args ) { + if ( !locked ) { + args = args || []; + args = [ context, args.slice ? args.slice() : args ]; + queue.push( args ); + if ( !firing ) { + fire(); + } + } + return this; + }, + + // Call all the callbacks with the given arguments + fire: function() { + self.fireWith( this, arguments ); + return this; + }, + + // To know if the callbacks have already been called at least once + fired: function() { + return !!fired; + } + }; + + return self; +}; + + +function Identity( v ) { + return v; +} +function Thrower( ex ) { + throw ex; +} + +function adoptValue( value, resolve, reject, noValue ) { + var method; + + try { + + // Check for promise aspect first to privilege synchronous behavior + if ( value && isFunction( ( method = value.promise ) ) ) { + method.call( value ).done( resolve ).fail( reject ); + + // Other thenables + } else if ( value && isFunction( ( method = value.then ) ) ) { + method.call( value, resolve, reject ); + + // Other non-thenables + } else { + + // Control `resolve` arguments by letting Array#slice cast boolean `noValue` to integer: + // * false: [ value ].slice( 0 ) => resolve( value ) + // * true: [ value ].slice( 1 ) => resolve() + resolve.apply( undefined, [ value ].slice( noValue ) ); + } + + // For Promises/A+, convert exceptions into rejections + // Since jQuery.when doesn't unwrap thenables, we can skip the extra checks appearing in + // Deferred#then to conditionally suppress rejection. + } catch ( value ) { + + // Support: Android 4.0 only + // Strict mode functions invoked without .call/.apply get global-object context + reject.apply( undefined, [ value ] ); + } +} + +jQuery.extend( { + + Deferred: function( func ) { + var tuples = [ + + // action, add listener, callbacks, + // ... .then handlers, argument index, [final state] + [ "notify", "progress", jQuery.Callbacks( "memory" ), + jQuery.Callbacks( "memory" ), 2 ], + [ "resolve", "done", jQuery.Callbacks( "once memory" ), + jQuery.Callbacks( "once memory" ), 0, "resolved" ], + [ "reject", "fail", jQuery.Callbacks( "once memory" ), + jQuery.Callbacks( "once memory" ), 1, "rejected" ] + ], + state = "pending", + promise = { + state: function() { + return state; + }, + always: function() { + deferred.done( arguments ).fail( arguments ); + return this; + }, + "catch": function( fn ) { + return promise.then( null, fn ); + }, + + // Keep pipe for back-compat + pipe: function( /* fnDone, fnFail, fnProgress */ ) { + var fns = arguments; + + return jQuery.Deferred( function( newDefer ) { + jQuery.each( tuples, function( _i, tuple ) { + + // Map tuples (progress, done, fail) to arguments (done, fail, progress) + var fn = isFunction( fns[ tuple[ 4 ] ] ) && fns[ tuple[ 4 ] ]; + + // deferred.progress(function() { bind to newDefer or newDefer.notify }) + // deferred.done(function() { bind to newDefer or newDefer.resolve }) + // deferred.fail(function() { bind to newDefer or newDefer.reject }) + deferred[ tuple[ 1 ] ]( function() { + var returned = fn && fn.apply( this, arguments ); + if ( returned && isFunction( returned.promise ) ) { + returned.promise() + .progress( newDefer.notify ) + .done( newDefer.resolve ) + .fail( newDefer.reject ); + } else { + newDefer[ tuple[ 0 ] + "With" ]( + this, + fn ? [ returned ] : arguments + ); + } + } ); + } ); + fns = null; + } ).promise(); + }, + then: function( onFulfilled, onRejected, onProgress ) { + var maxDepth = 0; + function resolve( depth, deferred, handler, special ) { + return function() { + var that = this, + args = arguments, + mightThrow = function() { + var returned, then; + + // Support: Promises/A+ section 2.3.3.3.3 + // https://promisesaplus.com/#point-59 + // Ignore double-resolution attempts + if ( depth < maxDepth ) { + return; + } + + returned = handler.apply( that, args ); + + // Support: Promises/A+ section 2.3.1 + // https://promisesaplus.com/#point-48 + if ( returned === deferred.promise() ) { + throw new TypeError( "Thenable self-resolution" ); + } + + // Support: Promises/A+ sections 2.3.3.1, 3.5 + // https://promisesaplus.com/#point-54 + // https://promisesaplus.com/#point-75 + // Retrieve `then` only once + then = returned && + + // Support: Promises/A+ section 2.3.4 + // https://promisesaplus.com/#point-64 + // Only check objects and functions for thenability + ( typeof returned === "object" || + typeof returned === "function" ) && + returned.then; + + // Handle a returned thenable + if ( isFunction( then ) ) { + + // Special processors (notify) just wait for resolution + if ( special ) { + then.call( + returned, + resolve( maxDepth, deferred, Identity, special ), + resolve( maxDepth, deferred, Thrower, special ) + ); + + // Normal processors (resolve) also hook into progress + } else { + + // ...and disregard older resolution values + maxDepth++; + + then.call( + returned, + resolve( maxDepth, deferred, Identity, special ), + resolve( maxDepth, deferred, Thrower, special ), + resolve( maxDepth, deferred, Identity, + deferred.notifyWith ) + ); + } + + // Handle all other returned values + } else { + + // Only substitute handlers pass on context + // and multiple values (non-spec behavior) + if ( handler !== Identity ) { + that = undefined; + args = [ returned ]; + } + + // Process the value(s) + // Default process is resolve + ( special || deferred.resolveWith )( that, args ); + } + }, + + // Only normal processors (resolve) catch and reject exceptions + process = special ? + mightThrow : + function() { + try { + mightThrow(); + } catch ( e ) { + + if ( jQuery.Deferred.exceptionHook ) { + jQuery.Deferred.exceptionHook( e, + process.stackTrace ); + } + + // Support: Promises/A+ section 2.3.3.3.4.1 + // https://promisesaplus.com/#point-61 + // Ignore post-resolution exceptions + if ( depth + 1 >= maxDepth ) { + + // Only substitute handlers pass on context + // and multiple values (non-spec behavior) + if ( handler !== Thrower ) { + that = undefined; + args = [ e ]; + } + + deferred.rejectWith( that, args ); + } + } + }; + + // Support: Promises/A+ section 2.3.3.3.1 + // https://promisesaplus.com/#point-57 + // Re-resolve promises immediately to dodge false rejection from + // subsequent errors + if ( depth ) { + process(); + } else { + + // Call an optional hook to record the stack, in case of exception + // since it's otherwise lost when execution goes async + if ( jQuery.Deferred.getStackHook ) { + process.stackTrace = jQuery.Deferred.getStackHook(); + } + window.setTimeout( process ); + } + }; + } + + return jQuery.Deferred( function( newDefer ) { + + // progress_handlers.add( ... ) + tuples[ 0 ][ 3 ].add( + resolve( + 0, + newDefer, + isFunction( onProgress ) ? + onProgress : + Identity, + newDefer.notifyWith + ) + ); + + // fulfilled_handlers.add( ... ) + tuples[ 1 ][ 3 ].add( + resolve( + 0, + newDefer, + isFunction( onFulfilled ) ? + onFulfilled : + Identity + ) + ); + + // rejected_handlers.add( ... ) + tuples[ 2 ][ 3 ].add( + resolve( + 0, + newDefer, + isFunction( onRejected ) ? + onRejected : + Thrower + ) + ); + } ).promise(); + }, + + // Get a promise for this deferred + // If obj is provided, the promise aspect is added to the object + promise: function( obj ) { + return obj != null ? jQuery.extend( obj, promise ) : promise; + } + }, + deferred = {}; + + // Add list-specific methods + jQuery.each( tuples, function( i, tuple ) { + var list = tuple[ 2 ], + stateString = tuple[ 5 ]; + + // promise.progress = list.add + // promise.done = list.add + // promise.fail = list.add + promise[ tuple[ 1 ] ] = list.add; + + // Handle state + if ( stateString ) { + list.add( + function() { + + // state = "resolved" (i.e., fulfilled) + // state = "rejected" + state = stateString; + }, + + // rejected_callbacks.disable + // fulfilled_callbacks.disable + tuples[ 3 - i ][ 2 ].disable, + + // rejected_handlers.disable + // fulfilled_handlers.disable + tuples[ 3 - i ][ 3 ].disable, + + // progress_callbacks.lock + tuples[ 0 ][ 2 ].lock, + + // progress_handlers.lock + tuples[ 0 ][ 3 ].lock + ); + } + + // progress_handlers.fire + // fulfilled_handlers.fire + // rejected_handlers.fire + list.add( tuple[ 3 ].fire ); + + // deferred.notify = function() { deferred.notifyWith(...) } + // deferred.resolve = function() { deferred.resolveWith(...) } + // deferred.reject = function() { deferred.rejectWith(...) } + deferred[ tuple[ 0 ] ] = function() { + deferred[ tuple[ 0 ] + "With" ]( this === deferred ? undefined : this, arguments ); + return this; + }; + + // deferred.notifyWith = list.fireWith + // deferred.resolveWith = list.fireWith + // deferred.rejectWith = list.fireWith + deferred[ tuple[ 0 ] + "With" ] = list.fireWith; + } ); + + // Make the deferred a promise + promise.promise( deferred ); + + // Call given func if any + if ( func ) { + func.call( deferred, deferred ); + } + + // All done! + return deferred; + }, + + // Deferred helper + when: function( singleValue ) { + var + + // count of uncompleted subordinates + remaining = arguments.length, + + // count of unprocessed arguments + i = remaining, + + // subordinate fulfillment data + resolveContexts = Array( i ), + resolveValues = slice.call( arguments ), + + // the master Deferred + master = jQuery.Deferred(), + + // subordinate callback factory + updateFunc = function( i ) { + return function( value ) { + resolveContexts[ i ] = this; + resolveValues[ i ] = arguments.length > 1 ? slice.call( arguments ) : value; + if ( !( --remaining ) ) { + master.resolveWith( resolveContexts, resolveValues ); + } + }; + }; + + // Single- and empty arguments are adopted like Promise.resolve + if ( remaining <= 1 ) { + adoptValue( singleValue, master.done( updateFunc( i ) ).resolve, master.reject, + !remaining ); + + // Use .then() to unwrap secondary thenables (cf. gh-3000) + if ( master.state() === "pending" || + isFunction( resolveValues[ i ] && resolveValues[ i ].then ) ) { + + return master.then(); + } + } + + // Multiple arguments are aggregated like Promise.all array elements + while ( i-- ) { + adoptValue( resolveValues[ i ], updateFunc( i ), master.reject ); + } + + return master.promise(); + } +} ); + + +// These usually indicate a programmer mistake during development, +// warn about them ASAP rather than swallowing them by default. +var rerrorNames = /^(Eval|Internal|Range|Reference|Syntax|Type|URI)Error$/; + +jQuery.Deferred.exceptionHook = function( error, stack ) { + + // Support: IE 8 - 9 only + // Console exists when dev tools are open, which can happen at any time + if ( window.console && window.console.warn && error && rerrorNames.test( error.name ) ) { + window.console.warn( "jQuery.Deferred exception: " + error.message, error.stack, stack ); + } +}; + + + + +jQuery.readyException = function( error ) { + window.setTimeout( function() { + throw error; + } ); +}; + + + + +// The deferred used on DOM ready +var readyList = jQuery.Deferred(); + +jQuery.fn.ready = function( fn ) { + + readyList + .then( fn ) + + // Wrap jQuery.readyException in a function so that the lookup + // happens at the time of error handling instead of callback + // registration. + .catch( function( error ) { + jQuery.readyException( error ); + } ); + + return this; +}; + +jQuery.extend( { + + // Is the DOM ready to be used? Set to true once it occurs. + isReady: false, + + // A counter to track how many items to wait for before + // the ready event fires. See #6781 + readyWait: 1, + + // Handle when the DOM is ready + ready: function( wait ) { + + // Abort if there are pending holds or we're already ready + if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) { + return; + } + + // Remember that the DOM is ready + jQuery.isReady = true; + + // If a normal DOM Ready event fired, decrement, and wait if need be + if ( wait !== true && --jQuery.readyWait > 0 ) { + return; + } + + // If there are functions bound, to execute + readyList.resolveWith( document, [ jQuery ] ); + } +} ); + +jQuery.ready.then = readyList.then; + +// The ready event handler and self cleanup method +function completed() { + document.removeEventListener( "DOMContentLoaded", completed ); + window.removeEventListener( "load", completed ); + jQuery.ready(); +} + +// Catch cases where $(document).ready() is called +// after the browser event has already occurred. +// Support: IE <=9 - 10 only +// Older IE sometimes signals "interactive" too soon +if ( document.readyState === "complete" || + ( document.readyState !== "loading" && !document.documentElement.doScroll ) ) { + + // Handle it asynchronously to allow scripts the opportunity to delay ready + window.setTimeout( jQuery.ready ); + +} else { + + // Use the handy event callback + document.addEventListener( "DOMContentLoaded", completed ); + + // A fallback to window.onload, that will always work + window.addEventListener( "load", completed ); +} + + + + +// Multifunctional method to get and set values of a collection +// The value/s can optionally be executed if it's a function +var access = function( elems, fn, key, value, chainable, emptyGet, raw ) { + var i = 0, + len = elems.length, + bulk = key == null; + + // Sets many values + if ( toType( key ) === "object" ) { + chainable = true; + for ( i in key ) { + access( elems, fn, i, key[ i ], true, emptyGet, raw ); + } + + // Sets one value + } else if ( value !== undefined ) { + chainable = true; + + if ( !isFunction( value ) ) { + raw = true; + } + + if ( bulk ) { + + // Bulk operations run against the entire set + if ( raw ) { + fn.call( elems, value ); + fn = null; + + // ...except when executing function values + } else { + bulk = fn; + fn = function( elem, _key, value ) { + return bulk.call( jQuery( elem ), value ); + }; + } + } + + if ( fn ) { + for ( ; i < len; i++ ) { + fn( + elems[ i ], key, raw ? + value : + value.call( elems[ i ], i, fn( elems[ i ], key ) ) + ); + } + } + } + + if ( chainable ) { + return elems; + } + + // Gets + if ( bulk ) { + return fn.call( elems ); + } + + return len ? fn( elems[ 0 ], key ) : emptyGet; +}; + + +// Matches dashed string for camelizing +var rmsPrefix = /^-ms-/, + rdashAlpha = /-([a-z])/g; + +// Used by camelCase as callback to replace() +function fcamelCase( _all, letter ) { + return letter.toUpperCase(); +} + +// Convert dashed to camelCase; used by the css and data modules +// Support: IE <=9 - 11, Edge 12 - 15 +// Microsoft forgot to hump their vendor prefix (#9572) +function camelCase( string ) { + return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase ); +} +var acceptData = function( owner ) { + + // Accepts only: + // - Node + // - Node.ELEMENT_NODE + // - Node.DOCUMENT_NODE + // - Object + // - Any + return owner.nodeType === 1 || owner.nodeType === 9 || !( +owner.nodeType ); +}; + + + + +function Data() { + this.expando = jQuery.expando + Data.uid++; +} + +Data.uid = 1; + +Data.prototype = { + + cache: function( owner ) { + + // Check if the owner object already has a cache + var value = owner[ this.expando ]; + + // If not, create one + if ( !value ) { + value = {}; + + // We can accept data for non-element nodes in modern browsers, + // but we should not, see #8335. + // Always return an empty object. + if ( acceptData( owner ) ) { + + // If it is a node unlikely to be stringify-ed or looped over + // use plain assignment + if ( owner.nodeType ) { + owner[ this.expando ] = value; + + // Otherwise secure it in a non-enumerable property + // configurable must be true to allow the property to be + // deleted when data is removed + } else { + Object.defineProperty( owner, this.expando, { + value: value, + configurable: true + } ); + } + } + } + + return value; + }, + set: function( owner, data, value ) { + var prop, + cache = this.cache( owner ); + + // Handle: [ owner, key, value ] args + // Always use camelCase key (gh-2257) + if ( typeof data === "string" ) { + cache[ camelCase( data ) ] = value; + + // Handle: [ owner, { properties } ] args + } else { + + // Copy the properties one-by-one to the cache object + for ( prop in data ) { + cache[ camelCase( prop ) ] = data[ prop ]; + } + } + return cache; + }, + get: function( owner, key ) { + return key === undefined ? + this.cache( owner ) : + + // Always use camelCase key (gh-2257) + owner[ this.expando ] && owner[ this.expando ][ camelCase( key ) ]; + }, + access: function( owner, key, value ) { + + // In cases where either: + // + // 1. No key was specified + // 2. A string key was specified, but no value provided + // + // Take the "read" path and allow the get method to determine + // which value to return, respectively either: + // + // 1. The entire cache object + // 2. The data stored at the key + // + if ( key === undefined || + ( ( key && typeof key === "string" ) && value === undefined ) ) { + + return this.get( owner, key ); + } + + // When the key is not a string, or both a key and value + // are specified, set or extend (existing objects) with either: + // + // 1. An object of properties + // 2. A key and value + // + this.set( owner, key, value ); + + // Since the "set" path can have two possible entry points + // return the expected data based on which path was taken[*] + return value !== undefined ? value : key; + }, + remove: function( owner, key ) { + var i, + cache = owner[ this.expando ]; + + if ( cache === undefined ) { + return; + } + + if ( key !== undefined ) { + + // Support array or space separated string of keys + if ( Array.isArray( key ) ) { + + // If key is an array of keys... + // We always set camelCase keys, so remove that. + key = key.map( camelCase ); + } else { + key = camelCase( key ); + + // If a key with the spaces exists, use it. + // Otherwise, create an array by matching non-whitespace + key = key in cache ? + [ key ] : + ( key.match( rnothtmlwhite ) || [] ); + } + + i = key.length; + + while ( i-- ) { + delete cache[ key[ i ] ]; + } + } + + // Remove the expando if there's no more data + if ( key === undefined || jQuery.isEmptyObject( cache ) ) { + + // Support: Chrome <=35 - 45 + // Webkit & Blink performance suffers when deleting properties + // from DOM nodes, so set to undefined instead + // https://bugs.chromium.org/p/chromium/issues/detail?id=378607 (bug restricted) + if ( owner.nodeType ) { + owner[ this.expando ] = undefined; + } else { + delete owner[ this.expando ]; + } + } + }, + hasData: function( owner ) { + var cache = owner[ this.expando ]; + return cache !== undefined && !jQuery.isEmptyObject( cache ); + } +}; +var dataPriv = new Data(); + +var dataUser = new Data(); + + + +// Implementation Summary +// +// 1. Enforce API surface and semantic compatibility with 1.9.x branch +// 2. Improve the module's maintainability by reducing the storage +// paths to a single mechanism. +// 3. Use the same single mechanism to support "private" and "user" data. +// 4. _Never_ expose "private" data to user code (TODO: Drop _data, _removeData) +// 5. Avoid exposing implementation details on user objects (eg. expando properties) +// 6. Provide a clear path for implementation upgrade to WeakMap in 2014 + +var rbrace = /^(?:\{[\w\W]*\}|\[[\w\W]*\])$/, + rmultiDash = /[A-Z]/g; + +function getData( data ) { + if ( data === "true" ) { + return true; + } + + if ( data === "false" ) { + return false; + } + + if ( data === "null" ) { + return null; + } + + // Only convert to a number if it doesn't change the string + if ( data === +data + "" ) { + return +data; + } + + if ( rbrace.test( data ) ) { + return JSON.parse( data ); + } + + return data; +} + +function dataAttr( elem, key, data ) { + var name; + + // If nothing was found internally, try to fetch any + // data from the HTML5 data-* attribute + if ( data === undefined && elem.nodeType === 1 ) { + name = "data-" + key.replace( rmultiDash, "-$&" ).toLowerCase(); + data = elem.getAttribute( name ); + + if ( typeof data === "string" ) { + try { + data = getData( data ); + } catch ( e ) {} + + // Make sure we set the data so it isn't changed later + dataUser.set( elem, key, data ); + } else { + data = undefined; + } + } + return data; +} + +jQuery.extend( { + hasData: function( elem ) { + return dataUser.hasData( elem ) || dataPriv.hasData( elem ); + }, + + data: function( elem, name, data ) { + return dataUser.access( elem, name, data ); + }, + + removeData: function( elem, name ) { + dataUser.remove( elem, name ); + }, + + // TODO: Now that all calls to _data and _removeData have been replaced + // with direct calls to dataPriv methods, these can be deprecated. + _data: function( elem, name, data ) { + return dataPriv.access( elem, name, data ); + }, + + _removeData: function( elem, name ) { + dataPriv.remove( elem, name ); + } +} ); + +jQuery.fn.extend( { + data: function( key, value ) { + var i, name, data, + elem = this[ 0 ], + attrs = elem && elem.attributes; + + // Gets all values + if ( key === undefined ) { + if ( this.length ) { + data = dataUser.get( elem ); + + if ( elem.nodeType === 1 && !dataPriv.get( elem, "hasDataAttrs" ) ) { + i = attrs.length; + while ( i-- ) { + + // Support: IE 11 only + // The attrs elements can be null (#14894) + if ( attrs[ i ] ) { + name = attrs[ i ].name; + if ( name.indexOf( "data-" ) === 0 ) { + name = camelCase( name.slice( 5 ) ); + dataAttr( elem, name, data[ name ] ); + } + } + } + dataPriv.set( elem, "hasDataAttrs", true ); + } + } + + return data; + } + + // Sets multiple values + if ( typeof key === "object" ) { + return this.each( function() { + dataUser.set( this, key ); + } ); + } + + return access( this, function( value ) { + var data; + + // The calling jQuery object (element matches) is not empty + // (and therefore has an element appears at this[ 0 ]) and the + // `value` parameter was not undefined. An empty jQuery object + // will result in `undefined` for elem = this[ 0 ] which will + // throw an exception if an attempt to read a data cache is made. + if ( elem && value === undefined ) { + + // Attempt to get data from the cache + // The key will always be camelCased in Data + data = dataUser.get( elem, key ); + if ( data !== undefined ) { + return data; + } + + // Attempt to "discover" the data in + // HTML5 custom data-* attrs + data = dataAttr( elem, key ); + if ( data !== undefined ) { + return data; + } + + // We tried really hard, but the data doesn't exist. + return; + } + + // Set the data... + this.each( function() { + + // We always store the camelCased key + dataUser.set( this, key, value ); + } ); + }, null, value, arguments.length > 1, null, true ); + }, + + removeData: function( key ) { + return this.each( function() { + dataUser.remove( this, key ); + } ); + } +} ); + + +jQuery.extend( { + queue: function( elem, type, data ) { + var queue; + + if ( elem ) { + type = ( type || "fx" ) + "queue"; + queue = dataPriv.get( elem, type ); + + // Speed up dequeue by getting out quickly if this is just a lookup + if ( data ) { + if ( !queue || Array.isArray( data ) ) { + queue = dataPriv.access( elem, type, jQuery.makeArray( data ) ); + } else { + queue.push( data ); + } + } + return queue || []; + } + }, + + dequeue: function( elem, type ) { + type = type || "fx"; + + var queue = jQuery.queue( elem, type ), + startLength = queue.length, + fn = queue.shift(), + hooks = jQuery._queueHooks( elem, type ), + next = function() { + jQuery.dequeue( elem, type ); + }; + + // If the fx queue is dequeued, always remove the progress sentinel + if ( fn === "inprogress" ) { + fn = queue.shift(); + startLength--; + } + + if ( fn ) { + + // Add a progress sentinel to prevent the fx queue from being + // automatically dequeued + if ( type === "fx" ) { + queue.unshift( "inprogress" ); + } + + // Clear up the last queue stop function + delete hooks.stop; + fn.call( elem, next, hooks ); + } + + if ( !startLength && hooks ) { + hooks.empty.fire(); + } + }, + + // Not public - generate a queueHooks object, or return the current one + _queueHooks: function( elem, type ) { + var key = type + "queueHooks"; + return dataPriv.get( elem, key ) || dataPriv.access( elem, key, { + empty: jQuery.Callbacks( "once memory" ).add( function() { + dataPriv.remove( elem, [ type + "queue", key ] ); + } ) + } ); + } +} ); + +jQuery.fn.extend( { + queue: function( type, data ) { + var setter = 2; + + if ( typeof type !== "string" ) { + data = type; + type = "fx"; + setter--; + } + + if ( arguments.length < setter ) { + return jQuery.queue( this[ 0 ], type ); + } + + return data === undefined ? + this : + this.each( function() { + var queue = jQuery.queue( this, type, data ); + + // Ensure a hooks for this queue + jQuery._queueHooks( this, type ); + + if ( type === "fx" && queue[ 0 ] !== "inprogress" ) { + jQuery.dequeue( this, type ); + } + } ); + }, + dequeue: function( type ) { + return this.each( function() { + jQuery.dequeue( this, type ); + } ); + }, + clearQueue: function( type ) { + return this.queue( type || "fx", [] ); + }, + + // Get a promise resolved when queues of a certain type + // are emptied (fx is the type by default) + promise: function( type, obj ) { + var tmp, + count = 1, + defer = jQuery.Deferred(), + elements = this, + i = this.length, + resolve = function() { + if ( !( --count ) ) { + defer.resolveWith( elements, [ elements ] ); + } + }; + + if ( typeof type !== "string" ) { + obj = type; + type = undefined; + } + type = type || "fx"; + + while ( i-- ) { + tmp = dataPriv.get( elements[ i ], type + "queueHooks" ); + if ( tmp && tmp.empty ) { + count++; + tmp.empty.add( resolve ); + } + } + resolve(); + return defer.promise( obj ); + } +} ); +var pnum = ( /[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/ ).source; + +var rcssNum = new RegExp( "^(?:([+-])=|)(" + pnum + ")([a-z%]*)$", "i" ); + + +var cssExpand = [ "Top", "Right", "Bottom", "Left" ]; + +var documentElement = document.documentElement; + + + + var isAttached = function( elem ) { + return jQuery.contains( elem.ownerDocument, elem ); + }, + composed = { composed: true }; + + // Support: IE 9 - 11+, Edge 12 - 18+, iOS 10.0 - 10.2 only + // Check attachment across shadow DOM boundaries when possible (gh-3504) + // Support: iOS 10.0-10.2 only + // Early iOS 10 versions support `attachShadow` but not `getRootNode`, + // leading to errors. We need to check for `getRootNode`. + if ( documentElement.getRootNode ) { + isAttached = function( elem ) { + return jQuery.contains( elem.ownerDocument, elem ) || + elem.getRootNode( composed ) === elem.ownerDocument; + }; + } +var isHiddenWithinTree = function( elem, el ) { + + // isHiddenWithinTree might be called from jQuery#filter function; + // in that case, element will be second argument + elem = el || elem; + + // Inline style trumps all + return elem.style.display === "none" || + elem.style.display === "" && + + // Otherwise, check computed style + // Support: Firefox <=43 - 45 + // Disconnected elements can have computed display: none, so first confirm that elem is + // in the document. + isAttached( elem ) && + + jQuery.css( elem, "display" ) === "none"; + }; + + + +function adjustCSS( elem, prop, valueParts, tween ) { + var adjusted, scale, + maxIterations = 20, + currentValue = tween ? + function() { + return tween.cur(); + } : + function() { + return jQuery.css( elem, prop, "" ); + }, + initial = currentValue(), + unit = valueParts && valueParts[ 3 ] || ( jQuery.cssNumber[ prop ] ? "" : "px" ), + + // Starting value computation is required for potential unit mismatches + initialInUnit = elem.nodeType && + ( jQuery.cssNumber[ prop ] || unit !== "px" && +initial ) && + rcssNum.exec( jQuery.css( elem, prop ) ); + + if ( initialInUnit && initialInUnit[ 3 ] !== unit ) { + + // Support: Firefox <=54 + // Halve the iteration target value to prevent interference from CSS upper bounds (gh-2144) + initial = initial / 2; + + // Trust units reported by jQuery.css + unit = unit || initialInUnit[ 3 ]; + + // Iteratively approximate from a nonzero starting point + initialInUnit = +initial || 1; + + while ( maxIterations-- ) { + + // Evaluate and update our best guess (doubling guesses that zero out). + // Finish if the scale equals or crosses 1 (making the old*new product non-positive). + jQuery.style( elem, prop, initialInUnit + unit ); + if ( ( 1 - scale ) * ( 1 - ( scale = currentValue() / initial || 0.5 ) ) <= 0 ) { + maxIterations = 0; + } + initialInUnit = initialInUnit / scale; + + } + + initialInUnit = initialInUnit * 2; + jQuery.style( elem, prop, initialInUnit + unit ); + + // Make sure we update the tween properties later on + valueParts = valueParts || []; + } + + if ( valueParts ) { + initialInUnit = +initialInUnit || +initial || 0; + + // Apply relative offset (+=/-=) if specified + adjusted = valueParts[ 1 ] ? + initialInUnit + ( valueParts[ 1 ] + 1 ) * valueParts[ 2 ] : + +valueParts[ 2 ]; + if ( tween ) { + tween.unit = unit; + tween.start = initialInUnit; + tween.end = adjusted; + } + } + return adjusted; +} + + +var defaultDisplayMap = {}; + +function getDefaultDisplay( elem ) { + var temp, + doc = elem.ownerDocument, + nodeName = elem.nodeName, + display = defaultDisplayMap[ nodeName ]; + + if ( display ) { + return display; + } + + temp = doc.body.appendChild( doc.createElement( nodeName ) ); + display = jQuery.css( temp, "display" ); + + temp.parentNode.removeChild( temp ); + + if ( display === "none" ) { + display = "block"; + } + defaultDisplayMap[ nodeName ] = display; + + return display; +} + +function showHide( elements, show ) { + var display, elem, + values = [], + index = 0, + length = elements.length; + + // Determine new display value for elements that need to change + for ( ; index < length; index++ ) { + elem = elements[ index ]; + if ( !elem.style ) { + continue; + } + + display = elem.style.display; + if ( show ) { + + // Since we force visibility upon cascade-hidden elements, an immediate (and slow) + // check is required in this first loop unless we have a nonempty display value (either + // inline or about-to-be-restored) + if ( display === "none" ) { + values[ index ] = dataPriv.get( elem, "display" ) || null; + if ( !values[ index ] ) { + elem.style.display = ""; + } + } + if ( elem.style.display === "" && isHiddenWithinTree( elem ) ) { + values[ index ] = getDefaultDisplay( elem ); + } + } else { + if ( display !== "none" ) { + values[ index ] = "none"; + + // Remember what we're overwriting + dataPriv.set( elem, "display", display ); + } + } + } + + // Set the display of the elements in a second loop to avoid constant reflow + for ( index = 0; index < length; index++ ) { + if ( values[ index ] != null ) { + elements[ index ].style.display = values[ index ]; + } + } + + return elements; +} + +jQuery.fn.extend( { + show: function() { + return showHide( this, true ); + }, + hide: function() { + return showHide( this ); + }, + toggle: function( state ) { + if ( typeof state === "boolean" ) { + return state ? this.show() : this.hide(); + } + + return this.each( function() { + if ( isHiddenWithinTree( this ) ) { + jQuery( this ).show(); + } else { + jQuery( this ).hide(); + } + } ); + } +} ); +var rcheckableType = ( /^(?:checkbox|radio)$/i ); + +var rtagName = ( /<([a-z][^\/\0>\x20\t\r\n\f]*)/i ); + +var rscriptType = ( /^$|^module$|\/(?:java|ecma)script/i ); + + + +( function() { + var fragment = document.createDocumentFragment(), + div = fragment.appendChild( document.createElement( "div" ) ), + input = document.createElement( "input" ); + + // Support: Android 4.0 - 4.3 only + // Check state lost if the name is set (#11217) + // Support: Windows Web Apps (WWA) + // `name` and `type` must use .setAttribute for WWA (#14901) + input.setAttribute( "type", "radio" ); + input.setAttribute( "checked", "checked" ); + input.setAttribute( "name", "t" ); + + div.appendChild( input ); + + // Support: Android <=4.1 only + // Older WebKit doesn't clone checked state correctly in fragments + support.checkClone = div.cloneNode( true ).cloneNode( true ).lastChild.checked; + + // Support: IE <=11 only + // Make sure textarea (and checkbox) defaultValue is properly cloned + div.innerHTML = ""; + support.noCloneChecked = !!div.cloneNode( true ).lastChild.defaultValue; + + // Support: IE <=9 only + // IE <=9 replaces "; + support.option = !!div.lastChild; +} )(); + + +// We have to close these tags to support XHTML (#13200) +var wrapMap = { + + // XHTML parsers do not magically insert elements in the + // same way that tag soup parsers do. So we cannot shorten + // this by omitting or other required elements. + thead: [ 1, "", "
" ], + col: [ 2, "", "
" ], + tr: [ 2, "", "
" ], + td: [ 3, "", "
" ], + + _default: [ 0, "", "" ] +}; + +wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; +wrapMap.th = wrapMap.td; + +// Support: IE <=9 only +if ( !support.option ) { + wrapMap.optgroup = wrapMap.option = [ 1, "" ]; +} + + +function getAll( context, tag ) { + + // Support: IE <=9 - 11 only + // Use typeof to avoid zero-argument method invocation on host objects (#15151) + var ret; + + if ( typeof context.getElementsByTagName !== "undefined" ) { + ret = context.getElementsByTagName( tag || "*" ); + + } else if ( typeof context.querySelectorAll !== "undefined" ) { + ret = context.querySelectorAll( tag || "*" ); + + } else { + ret = []; + } + + if ( tag === undefined || tag && nodeName( context, tag ) ) { + return jQuery.merge( [ context ], ret ); + } + + return ret; +} + + +// Mark scripts as having already been evaluated +function setGlobalEval( elems, refElements ) { + var i = 0, + l = elems.length; + + for ( ; i < l; i++ ) { + dataPriv.set( + elems[ i ], + "globalEval", + !refElements || dataPriv.get( refElements[ i ], "globalEval" ) + ); + } +} + + +var rhtml = /<|&#?\w+;/; + +function buildFragment( elems, context, scripts, selection, ignored ) { + var elem, tmp, tag, wrap, attached, j, + fragment = context.createDocumentFragment(), + nodes = [], + i = 0, + l = elems.length; + + for ( ; i < l; i++ ) { + elem = elems[ i ]; + + if ( elem || elem === 0 ) { + + // Add nodes directly + if ( toType( elem ) === "object" ) { + + // Support: Android <=4.0 only, PhantomJS 1 only + // push.apply(_, arraylike) throws on ancient WebKit + jQuery.merge( nodes, elem.nodeType ? [ elem ] : elem ); + + // Convert non-html into a text node + } else if ( !rhtml.test( elem ) ) { + nodes.push( context.createTextNode( elem ) ); + + // Convert html into DOM nodes + } else { + tmp = tmp || fragment.appendChild( context.createElement( "div" ) ); + + // Deserialize a standard representation + tag = ( rtagName.exec( elem ) || [ "", "" ] )[ 1 ].toLowerCase(); + wrap = wrapMap[ tag ] || wrapMap._default; + tmp.innerHTML = wrap[ 1 ] + jQuery.htmlPrefilter( elem ) + wrap[ 2 ]; + + // Descend through wrappers to the right content + j = wrap[ 0 ]; + while ( j-- ) { + tmp = tmp.lastChild; + } + + // Support: Android <=4.0 only, PhantomJS 1 only + // push.apply(_, arraylike) throws on ancient WebKit + jQuery.merge( nodes, tmp.childNodes ); + + // Remember the top-level container + tmp = fragment.firstChild; + + // Ensure the created nodes are orphaned (#12392) + tmp.textContent = ""; + } + } + } + + // Remove wrapper from fragment + fragment.textContent = ""; + + i = 0; + while ( ( elem = nodes[ i++ ] ) ) { + + // Skip elements already in the context collection (trac-4087) + if ( selection && jQuery.inArray( elem, selection ) > -1 ) { + if ( ignored ) { + ignored.push( elem ); + } + continue; + } + + attached = isAttached( elem ); + + // Append to fragment + tmp = getAll( fragment.appendChild( elem ), "script" ); + + // Preserve script evaluation history + if ( attached ) { + setGlobalEval( tmp ); + } + + // Capture executables + if ( scripts ) { + j = 0; + while ( ( elem = tmp[ j++ ] ) ) { + if ( rscriptType.test( elem.type || "" ) ) { + scripts.push( elem ); + } + } + } + } + + return fragment; +} + + +var + rkeyEvent = /^key/, + rmouseEvent = /^(?:mouse|pointer|contextmenu|drag|drop)|click/, + rtypenamespace = /^([^.]*)(?:\.(.+)|)/; + +function returnTrue() { + return true; +} + +function returnFalse() { + return false; +} + +// Support: IE <=9 - 11+ +// focus() and blur() are asynchronous, except when they are no-op. +// So expect focus to be synchronous when the element is already active, +// and blur to be synchronous when the element is not already active. +// (focus and blur are always synchronous in other supported browsers, +// this just defines when we can count on it). +function expectSync( elem, type ) { + return ( elem === safeActiveElement() ) === ( type === "focus" ); +} + +// Support: IE <=9 only +// Accessing document.activeElement can throw unexpectedly +// https://bugs.jquery.com/ticket/13393 +function safeActiveElement() { + try { + return document.activeElement; + } catch ( err ) { } +} + +function on( elem, types, selector, data, fn, one ) { + var origFn, type; + + // Types can be a map of types/handlers + if ( typeof types === "object" ) { + + // ( types-Object, selector, data ) + if ( typeof selector !== "string" ) { + + // ( types-Object, data ) + data = data || selector; + selector = undefined; + } + for ( type in types ) { + on( elem, type, selector, data, types[ type ], one ); + } + return elem; + } + + if ( data == null && fn == null ) { + + // ( types, fn ) + fn = selector; + data = selector = undefined; + } else if ( fn == null ) { + if ( typeof selector === "string" ) { + + // ( types, selector, fn ) + fn = data; + data = undefined; + } else { + + // ( types, data, fn ) + fn = data; + data = selector; + selector = undefined; + } + } + if ( fn === false ) { + fn = returnFalse; + } else if ( !fn ) { + return elem; + } + + if ( one === 1 ) { + origFn = fn; + fn = function( event ) { + + // Can use an empty set, since event contains the info + jQuery().off( event ); + return origFn.apply( this, arguments ); + }; + + // Use same guid so caller can remove using origFn + fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ ); + } + return elem.each( function() { + jQuery.event.add( this, types, fn, data, selector ); + } ); +} + +/* + * Helper functions for managing events -- not part of the public interface. + * Props to Dean Edwards' addEvent library for many of the ideas. + */ +jQuery.event = { + + global: {}, + + add: function( elem, types, handler, data, selector ) { + + var handleObjIn, eventHandle, tmp, + events, t, handleObj, + special, handlers, type, namespaces, origType, + elemData = dataPriv.get( elem ); + + // Only attach events to objects that accept data + if ( !acceptData( elem ) ) { + return; + } + + // Caller can pass in an object of custom data in lieu of the handler + if ( handler.handler ) { + handleObjIn = handler; + handler = handleObjIn.handler; + selector = handleObjIn.selector; + } + + // Ensure that invalid selectors throw exceptions at attach time + // Evaluate against documentElement in case elem is a non-element node (e.g., document) + if ( selector ) { + jQuery.find.matchesSelector( documentElement, selector ); + } + + // Make sure that the handler has a unique ID, used to find/remove it later + if ( !handler.guid ) { + handler.guid = jQuery.guid++; + } + + // Init the element's event structure and main handler, if this is the first + if ( !( events = elemData.events ) ) { + events = elemData.events = Object.create( null ); + } + if ( !( eventHandle = elemData.handle ) ) { + eventHandle = elemData.handle = function( e ) { + + // Discard the second event of a jQuery.event.trigger() and + // when an event is called after a page has unloaded + return typeof jQuery !== "undefined" && jQuery.event.triggered !== e.type ? + jQuery.event.dispatch.apply( elem, arguments ) : undefined; + }; + } + + // Handle multiple events separated by a space + types = ( types || "" ).match( rnothtmlwhite ) || [ "" ]; + t = types.length; + while ( t-- ) { + tmp = rtypenamespace.exec( types[ t ] ) || []; + type = origType = tmp[ 1 ]; + namespaces = ( tmp[ 2 ] || "" ).split( "." ).sort(); + + // There *must* be a type, no attaching namespace-only handlers + if ( !type ) { + continue; + } + + // If event changes its type, use the special event handlers for the changed type + special = jQuery.event.special[ type ] || {}; + + // If selector defined, determine special event api type, otherwise given type + type = ( selector ? special.delegateType : special.bindType ) || type; + + // Update special based on newly reset type + special = jQuery.event.special[ type ] || {}; + + // handleObj is passed to all event handlers + handleObj = jQuery.extend( { + type: type, + origType: origType, + data: data, + handler: handler, + guid: handler.guid, + selector: selector, + needsContext: selector && jQuery.expr.match.needsContext.test( selector ), + namespace: namespaces.join( "." ) + }, handleObjIn ); + + // Init the event handler queue if we're the first + if ( !( handlers = events[ type ] ) ) { + handlers = events[ type ] = []; + handlers.delegateCount = 0; + + // Only use addEventListener if the special events handler returns false + if ( !special.setup || + special.setup.call( elem, data, namespaces, eventHandle ) === false ) { + + if ( elem.addEventListener ) { + elem.addEventListener( type, eventHandle ); + } + } + } + + if ( special.add ) { + special.add.call( elem, handleObj ); + + if ( !handleObj.handler.guid ) { + handleObj.handler.guid = handler.guid; + } + } + + // Add to the element's handler list, delegates in front + if ( selector ) { + handlers.splice( handlers.delegateCount++, 0, handleObj ); + } else { + handlers.push( handleObj ); + } + + // Keep track of which events have ever been used, for event optimization + jQuery.event.global[ type ] = true; + } + + }, + + // Detach an event or set of events from an element + remove: function( elem, types, handler, selector, mappedTypes ) { + + var j, origCount, tmp, + events, t, handleObj, + special, handlers, type, namespaces, origType, + elemData = dataPriv.hasData( elem ) && dataPriv.get( elem ); + + if ( !elemData || !( events = elemData.events ) ) { + return; + } + + // Once for each type.namespace in types; type may be omitted + types = ( types || "" ).match( rnothtmlwhite ) || [ "" ]; + t = types.length; + while ( t-- ) { + tmp = rtypenamespace.exec( types[ t ] ) || []; + type = origType = tmp[ 1 ]; + namespaces = ( tmp[ 2 ] || "" ).split( "." ).sort(); + + // Unbind all events (on this namespace, if provided) for the element + if ( !type ) { + for ( type in events ) { + jQuery.event.remove( elem, type + types[ t ], handler, selector, true ); + } + continue; + } + + special = jQuery.event.special[ type ] || {}; + type = ( selector ? special.delegateType : special.bindType ) || type; + handlers = events[ type ] || []; + tmp = tmp[ 2 ] && + new RegExp( "(^|\\.)" + namespaces.join( "\\.(?:.*\\.|)" ) + "(\\.|$)" ); + + // Remove matching events + origCount = j = handlers.length; + while ( j-- ) { + handleObj = handlers[ j ]; + + if ( ( mappedTypes || origType === handleObj.origType ) && + ( !handler || handler.guid === handleObj.guid ) && + ( !tmp || tmp.test( handleObj.namespace ) ) && + ( !selector || selector === handleObj.selector || + selector === "**" && handleObj.selector ) ) { + handlers.splice( j, 1 ); + + if ( handleObj.selector ) { + handlers.delegateCount--; + } + if ( special.remove ) { + special.remove.call( elem, handleObj ); + } + } + } + + // Remove generic event handler if we removed something and no more handlers exist + // (avoids potential for endless recursion during removal of special event handlers) + if ( origCount && !handlers.length ) { + if ( !special.teardown || + special.teardown.call( elem, namespaces, elemData.handle ) === false ) { + + jQuery.removeEvent( elem, type, elemData.handle ); + } + + delete events[ type ]; + } + } + + // Remove data and the expando if it's no longer used + if ( jQuery.isEmptyObject( events ) ) { + dataPriv.remove( elem, "handle events" ); + } + }, + + dispatch: function( nativeEvent ) { + + var i, j, ret, matched, handleObj, handlerQueue, + args = new Array( arguments.length ), + + // Make a writable jQuery.Event from the native event object + event = jQuery.event.fix( nativeEvent ), + + handlers = ( + dataPriv.get( this, "events" ) || Object.create( null ) + )[ event.type ] || [], + special = jQuery.event.special[ event.type ] || {}; + + // Use the fix-ed jQuery.Event rather than the (read-only) native event + args[ 0 ] = event; + + for ( i = 1; i < arguments.length; i++ ) { + args[ i ] = arguments[ i ]; + } + + event.delegateTarget = this; + + // Call the preDispatch hook for the mapped type, and let it bail if desired + if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) { + return; + } + + // Determine handlers + handlerQueue = jQuery.event.handlers.call( this, event, handlers ); + + // Run delegates first; they may want to stop propagation beneath us + i = 0; + while ( ( matched = handlerQueue[ i++ ] ) && !event.isPropagationStopped() ) { + event.currentTarget = matched.elem; + + j = 0; + while ( ( handleObj = matched.handlers[ j++ ] ) && + !event.isImmediatePropagationStopped() ) { + + // If the event is namespaced, then each handler is only invoked if it is + // specially universal or its namespaces are a superset of the event's. + if ( !event.rnamespace || handleObj.namespace === false || + event.rnamespace.test( handleObj.namespace ) ) { + + event.handleObj = handleObj; + event.data = handleObj.data; + + ret = ( ( jQuery.event.special[ handleObj.origType ] || {} ).handle || + handleObj.handler ).apply( matched.elem, args ); + + if ( ret !== undefined ) { + if ( ( event.result = ret ) === false ) { + event.preventDefault(); + event.stopPropagation(); + } + } + } + } + } + + // Call the postDispatch hook for the mapped type + if ( special.postDispatch ) { + special.postDispatch.call( this, event ); + } + + return event.result; + }, + + handlers: function( event, handlers ) { + var i, handleObj, sel, matchedHandlers, matchedSelectors, + handlerQueue = [], + delegateCount = handlers.delegateCount, + cur = event.target; + + // Find delegate handlers + if ( delegateCount && + + // Support: IE <=9 + // Black-hole SVG instance trees (trac-13180) + cur.nodeType && + + // Support: Firefox <=42 + // Suppress spec-violating clicks indicating a non-primary pointer button (trac-3861) + // https://www.w3.org/TR/DOM-Level-3-Events/#event-type-click + // Support: IE 11 only + // ...but not arrow key "clicks" of radio inputs, which can have `button` -1 (gh-2343) + !( event.type === "click" && event.button >= 1 ) ) { + + for ( ; cur !== this; cur = cur.parentNode || this ) { + + // Don't check non-elements (#13208) + // Don't process clicks on disabled elements (#6911, #8165, #11382, #11764) + if ( cur.nodeType === 1 && !( event.type === "click" && cur.disabled === true ) ) { + matchedHandlers = []; + matchedSelectors = {}; + for ( i = 0; i < delegateCount; i++ ) { + handleObj = handlers[ i ]; + + // Don't conflict with Object.prototype properties (#13203) + sel = handleObj.selector + " "; + + if ( matchedSelectors[ sel ] === undefined ) { + matchedSelectors[ sel ] = handleObj.needsContext ? + jQuery( sel, this ).index( cur ) > -1 : + jQuery.find( sel, this, null, [ cur ] ).length; + } + if ( matchedSelectors[ sel ] ) { + matchedHandlers.push( handleObj ); + } + } + if ( matchedHandlers.length ) { + handlerQueue.push( { elem: cur, handlers: matchedHandlers } ); + } + } + } + } + + // Add the remaining (directly-bound) handlers + cur = this; + if ( delegateCount < handlers.length ) { + handlerQueue.push( { elem: cur, handlers: handlers.slice( delegateCount ) } ); + } + + return handlerQueue; + }, + + addProp: function( name, hook ) { + Object.defineProperty( jQuery.Event.prototype, name, { + enumerable: true, + configurable: true, + + get: isFunction( hook ) ? + function() { + if ( this.originalEvent ) { + return hook( this.originalEvent ); + } + } : + function() { + if ( this.originalEvent ) { + return this.originalEvent[ name ]; + } + }, + + set: function( value ) { + Object.defineProperty( this, name, { + enumerable: true, + configurable: true, + writable: true, + value: value + } ); + } + } ); + }, + + fix: function( originalEvent ) { + return originalEvent[ jQuery.expando ] ? + originalEvent : + new jQuery.Event( originalEvent ); + }, + + special: { + load: { + + // Prevent triggered image.load events from bubbling to window.load + noBubble: true + }, + click: { + + // Utilize native event to ensure correct state for checkable inputs + setup: function( data ) { + + // For mutual compressibility with _default, replace `this` access with a local var. + // `|| data` is dead code meant only to preserve the variable through minification. + var el = this || data; + + // Claim the first handler + if ( rcheckableType.test( el.type ) && + el.click && nodeName( el, "input" ) ) { + + // dataPriv.set( el, "click", ... ) + leverageNative( el, "click", returnTrue ); + } + + // Return false to allow normal processing in the caller + return false; + }, + trigger: function( data ) { + + // For mutual compressibility with _default, replace `this` access with a local var. + // `|| data` is dead code meant only to preserve the variable through minification. + var el = this || data; + + // Force setup before triggering a click + if ( rcheckableType.test( el.type ) && + el.click && nodeName( el, "input" ) ) { + + leverageNative( el, "click" ); + } + + // Return non-false to allow normal event-path propagation + return true; + }, + + // For cross-browser consistency, suppress native .click() on links + // Also prevent it if we're currently inside a leveraged native-event stack + _default: function( event ) { + var target = event.target; + return rcheckableType.test( target.type ) && + target.click && nodeName( target, "input" ) && + dataPriv.get( target, "click" ) || + nodeName( target, "a" ); + } + }, + + beforeunload: { + postDispatch: function( event ) { + + // Support: Firefox 20+ + // Firefox doesn't alert if the returnValue field is not set. + if ( event.result !== undefined && event.originalEvent ) { + event.originalEvent.returnValue = event.result; + } + } + } + } +}; + +// Ensure the presence of an event listener that handles manually-triggered +// synthetic events by interrupting progress until reinvoked in response to +// *native* events that it fires directly, ensuring that state changes have +// already occurred before other listeners are invoked. +function leverageNative( el, type, expectSync ) { + + // Missing expectSync indicates a trigger call, which must force setup through jQuery.event.add + if ( !expectSync ) { + if ( dataPriv.get( el, type ) === undefined ) { + jQuery.event.add( el, type, returnTrue ); + } + return; + } + + // Register the controller as a special universal handler for all event namespaces + dataPriv.set( el, type, false ); + jQuery.event.add( el, type, { + namespace: false, + handler: function( event ) { + var notAsync, result, + saved = dataPriv.get( this, type ); + + if ( ( event.isTrigger & 1 ) && this[ type ] ) { + + // Interrupt processing of the outer synthetic .trigger()ed event + // Saved data should be false in such cases, but might be a leftover capture object + // from an async native handler (gh-4350) + if ( !saved.length ) { + + // Store arguments for use when handling the inner native event + // There will always be at least one argument (an event object), so this array + // will not be confused with a leftover capture object. + saved = slice.call( arguments ); + dataPriv.set( this, type, saved ); + + // Trigger the native event and capture its result + // Support: IE <=9 - 11+ + // focus() and blur() are asynchronous + notAsync = expectSync( this, type ); + this[ type ](); + result = dataPriv.get( this, type ); + if ( saved !== result || notAsync ) { + dataPriv.set( this, type, false ); + } else { + result = {}; + } + if ( saved !== result ) { + + // Cancel the outer synthetic event + event.stopImmediatePropagation(); + event.preventDefault(); + return result.value; + } + + // If this is an inner synthetic event for an event with a bubbling surrogate + // (focus or blur), assume that the surrogate already propagated from triggering the + // native event and prevent that from happening again here. + // This technically gets the ordering wrong w.r.t. to `.trigger()` (in which the + // bubbling surrogate propagates *after* the non-bubbling base), but that seems + // less bad than duplication. + } else if ( ( jQuery.event.special[ type ] || {} ).delegateType ) { + event.stopPropagation(); + } + + // If this is a native event triggered above, everything is now in order + // Fire an inner synthetic event with the original arguments + } else if ( saved.length ) { + + // ...and capture the result + dataPriv.set( this, type, { + value: jQuery.event.trigger( + + // Support: IE <=9 - 11+ + // Extend with the prototype to reset the above stopImmediatePropagation() + jQuery.extend( saved[ 0 ], jQuery.Event.prototype ), + saved.slice( 1 ), + this + ) + } ); + + // Abort handling of the native event + event.stopImmediatePropagation(); + } + } + } ); +} + +jQuery.removeEvent = function( elem, type, handle ) { + + // This "if" is needed for plain objects + if ( elem.removeEventListener ) { + elem.removeEventListener( type, handle ); + } +}; + +jQuery.Event = function( src, props ) { + + // Allow instantiation without the 'new' keyword + if ( !( this instanceof jQuery.Event ) ) { + return new jQuery.Event( src, props ); + } + + // Event object + if ( src && src.type ) { + this.originalEvent = src; + this.type = src.type; + + // Events bubbling up the document may have been marked as prevented + // by a handler lower down the tree; reflect the correct value. + this.isDefaultPrevented = src.defaultPrevented || + src.defaultPrevented === undefined && + + // Support: Android <=2.3 only + src.returnValue === false ? + returnTrue : + returnFalse; + + // Create target properties + // Support: Safari <=6 - 7 only + // Target should not be a text node (#504, #13143) + this.target = ( src.target && src.target.nodeType === 3 ) ? + src.target.parentNode : + src.target; + + this.currentTarget = src.currentTarget; + this.relatedTarget = src.relatedTarget; + + // Event type + } else { + this.type = src; + } + + // Put explicitly provided properties onto the event object + if ( props ) { + jQuery.extend( this, props ); + } + + // Create a timestamp if incoming event doesn't have one + this.timeStamp = src && src.timeStamp || Date.now(); + + // Mark it as fixed + this[ jQuery.expando ] = true; +}; + +// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding +// https://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html +jQuery.Event.prototype = { + constructor: jQuery.Event, + isDefaultPrevented: returnFalse, + isPropagationStopped: returnFalse, + isImmediatePropagationStopped: returnFalse, + isSimulated: false, + + preventDefault: function() { + var e = this.originalEvent; + + this.isDefaultPrevented = returnTrue; + + if ( e && !this.isSimulated ) { + e.preventDefault(); + } + }, + stopPropagation: function() { + var e = this.originalEvent; + + this.isPropagationStopped = returnTrue; + + if ( e && !this.isSimulated ) { + e.stopPropagation(); + } + }, + stopImmediatePropagation: function() { + var e = this.originalEvent; + + this.isImmediatePropagationStopped = returnTrue; + + if ( e && !this.isSimulated ) { + e.stopImmediatePropagation(); + } + + this.stopPropagation(); + } +}; + +// Includes all common event props including KeyEvent and MouseEvent specific props +jQuery.each( { + altKey: true, + bubbles: true, + cancelable: true, + changedTouches: true, + ctrlKey: true, + detail: true, + eventPhase: true, + metaKey: true, + pageX: true, + pageY: true, + shiftKey: true, + view: true, + "char": true, + code: true, + charCode: true, + key: true, + keyCode: true, + button: true, + buttons: true, + clientX: true, + clientY: true, + offsetX: true, + offsetY: true, + pointerId: true, + pointerType: true, + screenX: true, + screenY: true, + targetTouches: true, + toElement: true, + touches: true, + + which: function( event ) { + var button = event.button; + + // Add which for key events + if ( event.which == null && rkeyEvent.test( event.type ) ) { + return event.charCode != null ? event.charCode : event.keyCode; + } + + // Add which for click: 1 === left; 2 === middle; 3 === right + if ( !event.which && button !== undefined && rmouseEvent.test( event.type ) ) { + if ( button & 1 ) { + return 1; + } + + if ( button & 2 ) { + return 3; + } + + if ( button & 4 ) { + return 2; + } + + return 0; + } + + return event.which; + } +}, jQuery.event.addProp ); + +jQuery.each( { focus: "focusin", blur: "focusout" }, function( type, delegateType ) { + jQuery.event.special[ type ] = { + + // Utilize native event if possible so blur/focus sequence is correct + setup: function() { + + // Claim the first handler + // dataPriv.set( this, "focus", ... ) + // dataPriv.set( this, "blur", ... ) + leverageNative( this, type, expectSync ); + + // Return false to allow normal processing in the caller + return false; + }, + trigger: function() { + + // Force setup before trigger + leverageNative( this, type ); + + // Return non-false to allow normal event-path propagation + return true; + }, + + delegateType: delegateType + }; +} ); + +// Create mouseenter/leave events using mouseover/out and event-time checks +// so that event delegation works in jQuery. +// Do the same for pointerenter/pointerleave and pointerover/pointerout +// +// Support: Safari 7 only +// Safari sends mouseenter too often; see: +// https://bugs.chromium.org/p/chromium/issues/detail?id=470258 +// for the description of the bug (it existed in older Chrome versions as well). +jQuery.each( { + mouseenter: "mouseover", + mouseleave: "mouseout", + pointerenter: "pointerover", + pointerleave: "pointerout" +}, function( orig, fix ) { + jQuery.event.special[ orig ] = { + delegateType: fix, + bindType: fix, + + handle: function( event ) { + var ret, + target = this, + related = event.relatedTarget, + handleObj = event.handleObj; + + // For mouseenter/leave call the handler if related is outside the target. + // NB: No relatedTarget if the mouse left/entered the browser window + if ( !related || ( related !== target && !jQuery.contains( target, related ) ) ) { + event.type = handleObj.origType; + ret = handleObj.handler.apply( this, arguments ); + event.type = fix; + } + return ret; + } + }; +} ); + +jQuery.fn.extend( { + + on: function( types, selector, data, fn ) { + return on( this, types, selector, data, fn ); + }, + one: function( types, selector, data, fn ) { + return on( this, types, selector, data, fn, 1 ); + }, + off: function( types, selector, fn ) { + var handleObj, type; + if ( types && types.preventDefault && types.handleObj ) { + + // ( event ) dispatched jQuery.Event + handleObj = types.handleObj; + jQuery( types.delegateTarget ).off( + handleObj.namespace ? + handleObj.origType + "." + handleObj.namespace : + handleObj.origType, + handleObj.selector, + handleObj.handler + ); + return this; + } + if ( typeof types === "object" ) { + + // ( types-object [, selector] ) + for ( type in types ) { + this.off( type, selector, types[ type ] ); + } + return this; + } + if ( selector === false || typeof selector === "function" ) { + + // ( types [, fn] ) + fn = selector; + selector = undefined; + } + if ( fn === false ) { + fn = returnFalse; + } + return this.each( function() { + jQuery.event.remove( this, types, fn, selector ); + } ); + } +} ); + + +var + + // Support: IE <=10 - 11, Edge 12 - 13 only + // In IE/Edge using regex groups here causes severe slowdowns. + // See https://connect.microsoft.com/IE/feedback/details/1736512/ + rnoInnerhtml = /\s*$/g; + +// Prefer a tbody over its parent table for containing new rows +function manipulationTarget( elem, content ) { + if ( nodeName( elem, "table" ) && + nodeName( content.nodeType !== 11 ? content : content.firstChild, "tr" ) ) { + + return jQuery( elem ).children( "tbody" )[ 0 ] || elem; + } + + return elem; +} + +// Replace/restore the type attribute of script elements for safe DOM manipulation +function disableScript( elem ) { + elem.type = ( elem.getAttribute( "type" ) !== null ) + "/" + elem.type; + return elem; +} +function restoreScript( elem ) { + if ( ( elem.type || "" ).slice( 0, 5 ) === "true/" ) { + elem.type = elem.type.slice( 5 ); + } else { + elem.removeAttribute( "type" ); + } + + return elem; +} + +function cloneCopyEvent( src, dest ) { + var i, l, type, pdataOld, udataOld, udataCur, events; + + if ( dest.nodeType !== 1 ) { + return; + } + + // 1. Copy private data: events, handlers, etc. + if ( dataPriv.hasData( src ) ) { + pdataOld = dataPriv.get( src ); + events = pdataOld.events; + + if ( events ) { + dataPriv.remove( dest, "handle events" ); + + for ( type in events ) { + for ( i = 0, l = events[ type ].length; i < l; i++ ) { + jQuery.event.add( dest, type, events[ type ][ i ] ); + } + } + } + } + + // 2. Copy user data + if ( dataUser.hasData( src ) ) { + udataOld = dataUser.access( src ); + udataCur = jQuery.extend( {}, udataOld ); + + dataUser.set( dest, udataCur ); + } +} + +// Fix IE bugs, see support tests +function fixInput( src, dest ) { + var nodeName = dest.nodeName.toLowerCase(); + + // Fails to persist the checked state of a cloned checkbox or radio button. + if ( nodeName === "input" && rcheckableType.test( src.type ) ) { + dest.checked = src.checked; + + // Fails to return the selected option to the default selected state when cloning options + } else if ( nodeName === "input" || nodeName === "textarea" ) { + dest.defaultValue = src.defaultValue; + } +} + +function domManip( collection, args, callback, ignored ) { + + // Flatten any nested arrays + args = flat( args ); + + var fragment, first, scripts, hasScripts, node, doc, + i = 0, + l = collection.length, + iNoClone = l - 1, + value = args[ 0 ], + valueIsFunction = isFunction( value ); + + // We can't cloneNode fragments that contain checked, in WebKit + if ( valueIsFunction || + ( l > 1 && typeof value === "string" && + !support.checkClone && rchecked.test( value ) ) ) { + return collection.each( function( index ) { + var self = collection.eq( index ); + if ( valueIsFunction ) { + args[ 0 ] = value.call( this, index, self.html() ); + } + domManip( self, args, callback, ignored ); + } ); + } + + if ( l ) { + fragment = buildFragment( args, collection[ 0 ].ownerDocument, false, collection, ignored ); + first = fragment.firstChild; + + if ( fragment.childNodes.length === 1 ) { + fragment = first; + } + + // Require either new content or an interest in ignored elements to invoke the callback + if ( first || ignored ) { + scripts = jQuery.map( getAll( fragment, "script" ), disableScript ); + hasScripts = scripts.length; + + // Use the original fragment for the last item + // instead of the first because it can end up + // being emptied incorrectly in certain situations (#8070). + for ( ; i < l; i++ ) { + node = fragment; + + if ( i !== iNoClone ) { + node = jQuery.clone( node, true, true ); + + // Keep references to cloned scripts for later restoration + if ( hasScripts ) { + + // Support: Android <=4.0 only, PhantomJS 1 only + // push.apply(_, arraylike) throws on ancient WebKit + jQuery.merge( scripts, getAll( node, "script" ) ); + } + } + + callback.call( collection[ i ], node, i ); + } + + if ( hasScripts ) { + doc = scripts[ scripts.length - 1 ].ownerDocument; + + // Reenable scripts + jQuery.map( scripts, restoreScript ); + + // Evaluate executable scripts on first document insertion + for ( i = 0; i < hasScripts; i++ ) { + node = scripts[ i ]; + if ( rscriptType.test( node.type || "" ) && + !dataPriv.access( node, "globalEval" ) && + jQuery.contains( doc, node ) ) { + + if ( node.src && ( node.type || "" ).toLowerCase() !== "module" ) { + + // Optional AJAX dependency, but won't run scripts if not present + if ( jQuery._evalUrl && !node.noModule ) { + jQuery._evalUrl( node.src, { + nonce: node.nonce || node.getAttribute( "nonce" ) + }, doc ); + } + } else { + DOMEval( node.textContent.replace( rcleanScript, "" ), node, doc ); + } + } + } + } + } + } + + return collection; +} + +function remove( elem, selector, keepData ) { + var node, + nodes = selector ? jQuery.filter( selector, elem ) : elem, + i = 0; + + for ( ; ( node = nodes[ i ] ) != null; i++ ) { + if ( !keepData && node.nodeType === 1 ) { + jQuery.cleanData( getAll( node ) ); + } + + if ( node.parentNode ) { + if ( keepData && isAttached( node ) ) { + setGlobalEval( getAll( node, "script" ) ); + } + node.parentNode.removeChild( node ); + } + } + + return elem; +} + +jQuery.extend( { + htmlPrefilter: function( html ) { + return html; + }, + + clone: function( elem, dataAndEvents, deepDataAndEvents ) { + var i, l, srcElements, destElements, + clone = elem.cloneNode( true ), + inPage = isAttached( elem ); + + // Fix IE cloning issues + if ( !support.noCloneChecked && ( elem.nodeType === 1 || elem.nodeType === 11 ) && + !jQuery.isXMLDoc( elem ) ) { + + // We eschew Sizzle here for performance reasons: https://jsperf.com/getall-vs-sizzle/2 + destElements = getAll( clone ); + srcElements = getAll( elem ); + + for ( i = 0, l = srcElements.length; i < l; i++ ) { + fixInput( srcElements[ i ], destElements[ i ] ); + } + } + + // Copy the events from the original to the clone + if ( dataAndEvents ) { + if ( deepDataAndEvents ) { + srcElements = srcElements || getAll( elem ); + destElements = destElements || getAll( clone ); + + for ( i = 0, l = srcElements.length; i < l; i++ ) { + cloneCopyEvent( srcElements[ i ], destElements[ i ] ); + } + } else { + cloneCopyEvent( elem, clone ); + } + } + + // Preserve script evaluation history + destElements = getAll( clone, "script" ); + if ( destElements.length > 0 ) { + setGlobalEval( destElements, !inPage && getAll( elem, "script" ) ); + } + + // Return the cloned set + return clone; + }, + + cleanData: function( elems ) { + var data, elem, type, + special = jQuery.event.special, + i = 0; + + for ( ; ( elem = elems[ i ] ) !== undefined; i++ ) { + if ( acceptData( elem ) ) { + if ( ( data = elem[ dataPriv.expando ] ) ) { + if ( data.events ) { + for ( type in data.events ) { + if ( special[ type ] ) { + jQuery.event.remove( elem, type ); + + // This is a shortcut to avoid jQuery.event.remove's overhead + } else { + jQuery.removeEvent( elem, type, data.handle ); + } + } + } + + // Support: Chrome <=35 - 45+ + // Assign undefined instead of using delete, see Data#remove + elem[ dataPriv.expando ] = undefined; + } + if ( elem[ dataUser.expando ] ) { + + // Support: Chrome <=35 - 45+ + // Assign undefined instead of using delete, see Data#remove + elem[ dataUser.expando ] = undefined; + } + } + } + } +} ); + +jQuery.fn.extend( { + detach: function( selector ) { + return remove( this, selector, true ); + }, + + remove: function( selector ) { + return remove( this, selector ); + }, + + text: function( value ) { + return access( this, function( value ) { + return value === undefined ? + jQuery.text( this ) : + this.empty().each( function() { + if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { + this.textContent = value; + } + } ); + }, null, value, arguments.length ); + }, + + append: function() { + return domManip( this, arguments, function( elem ) { + if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { + var target = manipulationTarget( this, elem ); + target.appendChild( elem ); + } + } ); + }, + + prepend: function() { + return domManip( this, arguments, function( elem ) { + if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { + var target = manipulationTarget( this, elem ); + target.insertBefore( elem, target.firstChild ); + } + } ); + }, + + before: function() { + return domManip( this, arguments, function( elem ) { + if ( this.parentNode ) { + this.parentNode.insertBefore( elem, this ); + } + } ); + }, + + after: function() { + return domManip( this, arguments, function( elem ) { + if ( this.parentNode ) { + this.parentNode.insertBefore( elem, this.nextSibling ); + } + } ); + }, + + empty: function() { + var elem, + i = 0; + + for ( ; ( elem = this[ i ] ) != null; i++ ) { + if ( elem.nodeType === 1 ) { + + // Prevent memory leaks + jQuery.cleanData( getAll( elem, false ) ); + + // Remove any remaining nodes + elem.textContent = ""; + } + } + + return this; + }, + + clone: function( dataAndEvents, deepDataAndEvents ) { + dataAndEvents = dataAndEvents == null ? false : dataAndEvents; + deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents; + + return this.map( function() { + return jQuery.clone( this, dataAndEvents, deepDataAndEvents ); + } ); + }, + + html: function( value ) { + return access( this, function( value ) { + var elem = this[ 0 ] || {}, + i = 0, + l = this.length; + + if ( value === undefined && elem.nodeType === 1 ) { + return elem.innerHTML; + } + + // See if we can take a shortcut and just use innerHTML + if ( typeof value === "string" && !rnoInnerhtml.test( value ) && + !wrapMap[ ( rtagName.exec( value ) || [ "", "" ] )[ 1 ].toLowerCase() ] ) { + + value = jQuery.htmlPrefilter( value ); + + try { + for ( ; i < l; i++ ) { + elem = this[ i ] || {}; + + // Remove element nodes and prevent memory leaks + if ( elem.nodeType === 1 ) { + jQuery.cleanData( getAll( elem, false ) ); + elem.innerHTML = value; + } + } + + elem = 0; + + // If using innerHTML throws an exception, use the fallback method + } catch ( e ) {} + } + + if ( elem ) { + this.empty().append( value ); + } + }, null, value, arguments.length ); + }, + + replaceWith: function() { + var ignored = []; + + // Make the changes, replacing each non-ignored context element with the new content + return domManip( this, arguments, function( elem ) { + var parent = this.parentNode; + + if ( jQuery.inArray( this, ignored ) < 0 ) { + jQuery.cleanData( getAll( this ) ); + if ( parent ) { + parent.replaceChild( elem, this ); + } + } + + // Force callback invocation + }, ignored ); + } +} ); + +jQuery.each( { + appendTo: "append", + prependTo: "prepend", + insertBefore: "before", + insertAfter: "after", + replaceAll: "replaceWith" +}, function( name, original ) { + jQuery.fn[ name ] = function( selector ) { + var elems, + ret = [], + insert = jQuery( selector ), + last = insert.length - 1, + i = 0; + + for ( ; i <= last; i++ ) { + elems = i === last ? this : this.clone( true ); + jQuery( insert[ i ] )[ original ]( elems ); + + // Support: Android <=4.0 only, PhantomJS 1 only + // .get() because push.apply(_, arraylike) throws on ancient WebKit + push.apply( ret, elems.get() ); + } + + return this.pushStack( ret ); + }; +} ); +var rnumnonpx = new RegExp( "^(" + pnum + ")(?!px)[a-z%]+$", "i" ); + +var getStyles = function( elem ) { + + // Support: IE <=11 only, Firefox <=30 (#15098, #14150) + // IE throws on elements created in popups + // FF meanwhile throws on frame elements through "defaultView.getComputedStyle" + var view = elem.ownerDocument.defaultView; + + if ( !view || !view.opener ) { + view = window; + } + + return view.getComputedStyle( elem ); + }; + +var swap = function( elem, options, callback ) { + var ret, name, + old = {}; + + // Remember the old values, and insert the new ones + for ( name in options ) { + old[ name ] = elem.style[ name ]; + elem.style[ name ] = options[ name ]; + } + + ret = callback.call( elem ); + + // Revert the old values + for ( name in options ) { + elem.style[ name ] = old[ name ]; + } + + return ret; +}; + + +var rboxStyle = new RegExp( cssExpand.join( "|" ), "i" ); + + + +( function() { + + // Executing both pixelPosition & boxSizingReliable tests require only one layout + // so they're executed at the same time to save the second computation. + function computeStyleTests() { + + // This is a singleton, we need to execute it only once + if ( !div ) { + return; + } + + container.style.cssText = "position:absolute;left:-11111px;width:60px;" + + "margin-top:1px;padding:0;border:0"; + div.style.cssText = + "position:relative;display:block;box-sizing:border-box;overflow:scroll;" + + "margin:auto;border:1px;padding:1px;" + + "width:60%;top:1%"; + documentElement.appendChild( container ).appendChild( div ); + + var divStyle = window.getComputedStyle( div ); + pixelPositionVal = divStyle.top !== "1%"; + + // Support: Android 4.0 - 4.3 only, Firefox <=3 - 44 + reliableMarginLeftVal = roundPixelMeasures( divStyle.marginLeft ) === 12; + + // Support: Android 4.0 - 4.3 only, Safari <=9.1 - 10.1, iOS <=7.0 - 9.3 + // Some styles come back with percentage values, even though they shouldn't + div.style.right = "60%"; + pixelBoxStylesVal = roundPixelMeasures( divStyle.right ) === 36; + + // Support: IE 9 - 11 only + // Detect misreporting of content dimensions for box-sizing:border-box elements + boxSizingReliableVal = roundPixelMeasures( divStyle.width ) === 36; + + // Support: IE 9 only + // Detect overflow:scroll screwiness (gh-3699) + // Support: Chrome <=64 + // Don't get tricked when zoom affects offsetWidth (gh-4029) + div.style.position = "absolute"; + scrollboxSizeVal = roundPixelMeasures( div.offsetWidth / 3 ) === 12; + + documentElement.removeChild( container ); + + // Nullify the div so it wouldn't be stored in the memory and + // it will also be a sign that checks already performed + div = null; + } + + function roundPixelMeasures( measure ) { + return Math.round( parseFloat( measure ) ); + } + + var pixelPositionVal, boxSizingReliableVal, scrollboxSizeVal, pixelBoxStylesVal, + reliableTrDimensionsVal, reliableMarginLeftVal, + container = document.createElement( "div" ), + div = document.createElement( "div" ); + + // Finish early in limited (non-browser) environments + if ( !div.style ) { + return; + } + + // Support: IE <=9 - 11 only + // Style of cloned element affects source element cloned (#8908) + div.style.backgroundClip = "content-box"; + div.cloneNode( true ).style.backgroundClip = ""; + support.clearCloneStyle = div.style.backgroundClip === "content-box"; + + jQuery.extend( support, { + boxSizingReliable: function() { + computeStyleTests(); + return boxSizingReliableVal; + }, + pixelBoxStyles: function() { + computeStyleTests(); + return pixelBoxStylesVal; + }, + pixelPosition: function() { + computeStyleTests(); + return pixelPositionVal; + }, + reliableMarginLeft: function() { + computeStyleTests(); + return reliableMarginLeftVal; + }, + scrollboxSize: function() { + computeStyleTests(); + return scrollboxSizeVal; + }, + + // Support: IE 9 - 11+, Edge 15 - 18+ + // IE/Edge misreport `getComputedStyle` of table rows with width/height + // set in CSS while `offset*` properties report correct values. + // Behavior in IE 9 is more subtle than in newer versions & it passes + // some versions of this test; make sure not to make it pass there! + reliableTrDimensions: function() { + var table, tr, trChild, trStyle; + if ( reliableTrDimensionsVal == null ) { + table = document.createElement( "table" ); + tr = document.createElement( "tr" ); + trChild = document.createElement( "div" ); + + table.style.cssText = "position:absolute;left:-11111px"; + tr.style.height = "1px"; + trChild.style.height = "9px"; + + documentElement + .appendChild( table ) + .appendChild( tr ) + .appendChild( trChild ); + + trStyle = window.getComputedStyle( tr ); + reliableTrDimensionsVal = parseInt( trStyle.height ) > 3; + + documentElement.removeChild( table ); + } + return reliableTrDimensionsVal; + } + } ); +} )(); + + +function curCSS( elem, name, computed ) { + var width, minWidth, maxWidth, ret, + + // Support: Firefox 51+ + // Retrieving style before computed somehow + // fixes an issue with getting wrong values + // on detached elements + style = elem.style; + + computed = computed || getStyles( elem ); + + // getPropertyValue is needed for: + // .css('filter') (IE 9 only, #12537) + // .css('--customProperty) (#3144) + if ( computed ) { + ret = computed.getPropertyValue( name ) || computed[ name ]; + + if ( ret === "" && !isAttached( elem ) ) { + ret = jQuery.style( elem, name ); + } + + // A tribute to the "awesome hack by Dean Edwards" + // Android Browser returns percentage for some values, + // but width seems to be reliably pixels. + // This is against the CSSOM draft spec: + // https://drafts.csswg.org/cssom/#resolved-values + if ( !support.pixelBoxStyles() && rnumnonpx.test( ret ) && rboxStyle.test( name ) ) { + + // Remember the original values + width = style.width; + minWidth = style.minWidth; + maxWidth = style.maxWidth; + + // Put in the new values to get a computed value out + style.minWidth = style.maxWidth = style.width = ret; + ret = computed.width; + + // Revert the changed values + style.width = width; + style.minWidth = minWidth; + style.maxWidth = maxWidth; + } + } + + return ret !== undefined ? + + // Support: IE <=9 - 11 only + // IE returns zIndex value as an integer. + ret + "" : + ret; +} + + +function addGetHookIf( conditionFn, hookFn ) { + + // Define the hook, we'll check on the first run if it's really needed. + return { + get: function() { + if ( conditionFn() ) { + + // Hook not needed (or it's not possible to use it due + // to missing dependency), remove it. + delete this.get; + return; + } + + // Hook needed; redefine it so that the support test is not executed again. + return ( this.get = hookFn ).apply( this, arguments ); + } + }; +} + + +var cssPrefixes = [ "Webkit", "Moz", "ms" ], + emptyStyle = document.createElement( "div" ).style, + vendorProps = {}; + +// Return a vendor-prefixed property or undefined +function vendorPropName( name ) { + + // Check for vendor prefixed names + var capName = name[ 0 ].toUpperCase() + name.slice( 1 ), + i = cssPrefixes.length; + + while ( i-- ) { + name = cssPrefixes[ i ] + capName; + if ( name in emptyStyle ) { + return name; + } + } +} + +// Return a potentially-mapped jQuery.cssProps or vendor prefixed property +function finalPropName( name ) { + var final = jQuery.cssProps[ name ] || vendorProps[ name ]; + + if ( final ) { + return final; + } + if ( name in emptyStyle ) { + return name; + } + return vendorProps[ name ] = vendorPropName( name ) || name; +} + + +var + + // Swappable if display is none or starts with table + // except "table", "table-cell", or "table-caption" + // See here for display values: https://developer.mozilla.org/en-US/docs/CSS/display + rdisplayswap = /^(none|table(?!-c[ea]).+)/, + rcustomProp = /^--/, + cssShow = { position: "absolute", visibility: "hidden", display: "block" }, + cssNormalTransform = { + letterSpacing: "0", + fontWeight: "400" + }; + +function setPositiveNumber( _elem, value, subtract ) { + + // Any relative (+/-) values have already been + // normalized at this point + var matches = rcssNum.exec( value ); + return matches ? + + // Guard against undefined "subtract", e.g., when used as in cssHooks + Math.max( 0, matches[ 2 ] - ( subtract || 0 ) ) + ( matches[ 3 ] || "px" ) : + value; +} + +function boxModelAdjustment( elem, dimension, box, isBorderBox, styles, computedVal ) { + var i = dimension === "width" ? 1 : 0, + extra = 0, + delta = 0; + + // Adjustment may not be necessary + if ( box === ( isBorderBox ? "border" : "content" ) ) { + return 0; + } + + for ( ; i < 4; i += 2 ) { + + // Both box models exclude margin + if ( box === "margin" ) { + delta += jQuery.css( elem, box + cssExpand[ i ], true, styles ); + } + + // If we get here with a content-box, we're seeking "padding" or "border" or "margin" + if ( !isBorderBox ) { + + // Add padding + delta += jQuery.css( elem, "padding" + cssExpand[ i ], true, styles ); + + // For "border" or "margin", add border + if ( box !== "padding" ) { + delta += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); + + // But still keep track of it otherwise + } else { + extra += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); + } + + // If we get here with a border-box (content + padding + border), we're seeking "content" or + // "padding" or "margin" + } else { + + // For "content", subtract padding + if ( box === "content" ) { + delta -= jQuery.css( elem, "padding" + cssExpand[ i ], true, styles ); + } + + // For "content" or "padding", subtract border + if ( box !== "margin" ) { + delta -= jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); + } + } + } + + // Account for positive content-box scroll gutter when requested by providing computedVal + if ( !isBorderBox && computedVal >= 0 ) { + + // offsetWidth/offsetHeight is a rounded sum of content, padding, scroll gutter, and border + // Assuming integer scroll gutter, subtract the rest and round down + delta += Math.max( 0, Math.ceil( + elem[ "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ) ] - + computedVal - + delta - + extra - + 0.5 + + // If offsetWidth/offsetHeight is unknown, then we can't determine content-box scroll gutter + // Use an explicit zero to avoid NaN (gh-3964) + ) ) || 0; + } + + return delta; +} + +function getWidthOrHeight( elem, dimension, extra ) { + + // Start with computed style + var styles = getStyles( elem ), + + // To avoid forcing a reflow, only fetch boxSizing if we need it (gh-4322). + // Fake content-box until we know it's needed to know the true value. + boxSizingNeeded = !support.boxSizingReliable() || extra, + isBorderBox = boxSizingNeeded && + jQuery.css( elem, "boxSizing", false, styles ) === "border-box", + valueIsBorderBox = isBorderBox, + + val = curCSS( elem, dimension, styles ), + offsetProp = "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ); + + // Support: Firefox <=54 + // Return a confounding non-pixel value or feign ignorance, as appropriate. + if ( rnumnonpx.test( val ) ) { + if ( !extra ) { + return val; + } + val = "auto"; + } + + + // Support: IE 9 - 11 only + // Use offsetWidth/offsetHeight for when box sizing is unreliable. + // In those cases, the computed value can be trusted to be border-box. + if ( ( !support.boxSizingReliable() && isBorderBox || + + // Support: IE 10 - 11+, Edge 15 - 18+ + // IE/Edge misreport `getComputedStyle` of table rows with width/height + // set in CSS while `offset*` properties report correct values. + // Interestingly, in some cases IE 9 doesn't suffer from this issue. + !support.reliableTrDimensions() && nodeName( elem, "tr" ) || + + // Fall back to offsetWidth/offsetHeight when value is "auto" + // This happens for inline elements with no explicit setting (gh-3571) + val === "auto" || + + // Support: Android <=4.1 - 4.3 only + // Also use offsetWidth/offsetHeight for misreported inline dimensions (gh-3602) + !parseFloat( val ) && jQuery.css( elem, "display", false, styles ) === "inline" ) && + + // Make sure the element is visible & connected + elem.getClientRects().length ) { + + isBorderBox = jQuery.css( elem, "boxSizing", false, styles ) === "border-box"; + + // Where available, offsetWidth/offsetHeight approximate border box dimensions. + // Where not available (e.g., SVG), assume unreliable box-sizing and interpret the + // retrieved value as a content box dimension. + valueIsBorderBox = offsetProp in elem; + if ( valueIsBorderBox ) { + val = elem[ offsetProp ]; + } + } + + // Normalize "" and auto + val = parseFloat( val ) || 0; + + // Adjust for the element's box model + return ( val + + boxModelAdjustment( + elem, + dimension, + extra || ( isBorderBox ? "border" : "content" ), + valueIsBorderBox, + styles, + + // Provide the current computed size to request scroll gutter calculation (gh-3589) + val + ) + ) + "px"; +} + +jQuery.extend( { + + // Add in style property hooks for overriding the default + // behavior of getting and setting a style property + cssHooks: { + opacity: { + get: function( elem, computed ) { + if ( computed ) { + + // We should always get a number back from opacity + var ret = curCSS( elem, "opacity" ); + return ret === "" ? "1" : ret; + } + } + } + }, + + // Don't automatically add "px" to these possibly-unitless properties + cssNumber: { + "animationIterationCount": true, + "columnCount": true, + "fillOpacity": true, + "flexGrow": true, + "flexShrink": true, + "fontWeight": true, + "gridArea": true, + "gridColumn": true, + "gridColumnEnd": true, + "gridColumnStart": true, + "gridRow": true, + "gridRowEnd": true, + "gridRowStart": true, + "lineHeight": true, + "opacity": true, + "order": true, + "orphans": true, + "widows": true, + "zIndex": true, + "zoom": true + }, + + // Add in properties whose names you wish to fix before + // setting or getting the value + cssProps: {}, + + // Get and set the style property on a DOM Node + style: function( elem, name, value, extra ) { + + // Don't set styles on text and comment nodes + if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) { + return; + } + + // Make sure that we're working with the right name + var ret, type, hooks, + origName = camelCase( name ), + isCustomProp = rcustomProp.test( name ), + style = elem.style; + + // Make sure that we're working with the right name. We don't + // want to query the value if it is a CSS custom property + // since they are user-defined. + if ( !isCustomProp ) { + name = finalPropName( origName ); + } + + // Gets hook for the prefixed version, then unprefixed version + hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ]; + + // Check if we're setting a value + if ( value !== undefined ) { + type = typeof value; + + // Convert "+=" or "-=" to relative numbers (#7345) + if ( type === "string" && ( ret = rcssNum.exec( value ) ) && ret[ 1 ] ) { + value = adjustCSS( elem, name, ret ); + + // Fixes bug #9237 + type = "number"; + } + + // Make sure that null and NaN values aren't set (#7116) + if ( value == null || value !== value ) { + return; + } + + // If a number was passed in, add the unit (except for certain CSS properties) + // The isCustomProp check can be removed in jQuery 4.0 when we only auto-append + // "px" to a few hardcoded values. + if ( type === "number" && !isCustomProp ) { + value += ret && ret[ 3 ] || ( jQuery.cssNumber[ origName ] ? "" : "px" ); + } + + // background-* props affect original clone's values + if ( !support.clearCloneStyle && value === "" && name.indexOf( "background" ) === 0 ) { + style[ name ] = "inherit"; + } + + // If a hook was provided, use that value, otherwise just set the specified value + if ( !hooks || !( "set" in hooks ) || + ( value = hooks.set( elem, value, extra ) ) !== undefined ) { + + if ( isCustomProp ) { + style.setProperty( name, value ); + } else { + style[ name ] = value; + } + } + + } else { + + // If a hook was provided get the non-computed value from there + if ( hooks && "get" in hooks && + ( ret = hooks.get( elem, false, extra ) ) !== undefined ) { + + return ret; + } + + // Otherwise just get the value from the style object + return style[ name ]; + } + }, + + css: function( elem, name, extra, styles ) { + var val, num, hooks, + origName = camelCase( name ), + isCustomProp = rcustomProp.test( name ); + + // Make sure that we're working with the right name. We don't + // want to modify the value if it is a CSS custom property + // since they are user-defined. + if ( !isCustomProp ) { + name = finalPropName( origName ); + } + + // Try prefixed name followed by the unprefixed name + hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ]; + + // If a hook was provided get the computed value from there + if ( hooks && "get" in hooks ) { + val = hooks.get( elem, true, extra ); + } + + // Otherwise, if a way to get the computed value exists, use that + if ( val === undefined ) { + val = curCSS( elem, name, styles ); + } + + // Convert "normal" to computed value + if ( val === "normal" && name in cssNormalTransform ) { + val = cssNormalTransform[ name ]; + } + + // Make numeric if forced or a qualifier was provided and val looks numeric + if ( extra === "" || extra ) { + num = parseFloat( val ); + return extra === true || isFinite( num ) ? num || 0 : val; + } + + return val; + } +} ); + +jQuery.each( [ "height", "width" ], function( _i, dimension ) { + jQuery.cssHooks[ dimension ] = { + get: function( elem, computed, extra ) { + if ( computed ) { + + // Certain elements can have dimension info if we invisibly show them + // but it must have a current display style that would benefit + return rdisplayswap.test( jQuery.css( elem, "display" ) ) && + + // Support: Safari 8+ + // Table columns in Safari have non-zero offsetWidth & zero + // getBoundingClientRect().width unless display is changed. + // Support: IE <=11 only + // Running getBoundingClientRect on a disconnected node + // in IE throws an error. + ( !elem.getClientRects().length || !elem.getBoundingClientRect().width ) ? + swap( elem, cssShow, function() { + return getWidthOrHeight( elem, dimension, extra ); + } ) : + getWidthOrHeight( elem, dimension, extra ); + } + }, + + set: function( elem, value, extra ) { + var matches, + styles = getStyles( elem ), + + // Only read styles.position if the test has a chance to fail + // to avoid forcing a reflow. + scrollboxSizeBuggy = !support.scrollboxSize() && + styles.position === "absolute", + + // To avoid forcing a reflow, only fetch boxSizing if we need it (gh-3991) + boxSizingNeeded = scrollboxSizeBuggy || extra, + isBorderBox = boxSizingNeeded && + jQuery.css( elem, "boxSizing", false, styles ) === "border-box", + subtract = extra ? + boxModelAdjustment( + elem, + dimension, + extra, + isBorderBox, + styles + ) : + 0; + + // Account for unreliable border-box dimensions by comparing offset* to computed and + // faking a content-box to get border and padding (gh-3699) + if ( isBorderBox && scrollboxSizeBuggy ) { + subtract -= Math.ceil( + elem[ "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ) ] - + parseFloat( styles[ dimension ] ) - + boxModelAdjustment( elem, dimension, "border", false, styles ) - + 0.5 + ); + } + + // Convert to pixels if value adjustment is needed + if ( subtract && ( matches = rcssNum.exec( value ) ) && + ( matches[ 3 ] || "px" ) !== "px" ) { + + elem.style[ dimension ] = value; + value = jQuery.css( elem, dimension ); + } + + return setPositiveNumber( elem, value, subtract ); + } + }; +} ); + +jQuery.cssHooks.marginLeft = addGetHookIf( support.reliableMarginLeft, + function( elem, computed ) { + if ( computed ) { + return ( parseFloat( curCSS( elem, "marginLeft" ) ) || + elem.getBoundingClientRect().left - + swap( elem, { marginLeft: 0 }, function() { + return elem.getBoundingClientRect().left; + } ) + ) + "px"; + } + } +); + +// These hooks are used by animate to expand properties +jQuery.each( { + margin: "", + padding: "", + border: "Width" +}, function( prefix, suffix ) { + jQuery.cssHooks[ prefix + suffix ] = { + expand: function( value ) { + var i = 0, + expanded = {}, + + // Assumes a single number if not a string + parts = typeof value === "string" ? value.split( " " ) : [ value ]; + + for ( ; i < 4; i++ ) { + expanded[ prefix + cssExpand[ i ] + suffix ] = + parts[ i ] || parts[ i - 2 ] || parts[ 0 ]; + } + + return expanded; + } + }; + + if ( prefix !== "margin" ) { + jQuery.cssHooks[ prefix + suffix ].set = setPositiveNumber; + } +} ); + +jQuery.fn.extend( { + css: function( name, value ) { + return access( this, function( elem, name, value ) { + var styles, len, + map = {}, + i = 0; + + if ( Array.isArray( name ) ) { + styles = getStyles( elem ); + len = name.length; + + for ( ; i < len; i++ ) { + map[ name[ i ] ] = jQuery.css( elem, name[ i ], false, styles ); + } + + return map; + } + + return value !== undefined ? + jQuery.style( elem, name, value ) : + jQuery.css( elem, name ); + }, name, value, arguments.length > 1 ); + } +} ); + + +function Tween( elem, options, prop, end, easing ) { + return new Tween.prototype.init( elem, options, prop, end, easing ); +} +jQuery.Tween = Tween; + +Tween.prototype = { + constructor: Tween, + init: function( elem, options, prop, end, easing, unit ) { + this.elem = elem; + this.prop = prop; + this.easing = easing || jQuery.easing._default; + this.options = options; + this.start = this.now = this.cur(); + this.end = end; + this.unit = unit || ( jQuery.cssNumber[ prop ] ? "" : "px" ); + }, + cur: function() { + var hooks = Tween.propHooks[ this.prop ]; + + return hooks && hooks.get ? + hooks.get( this ) : + Tween.propHooks._default.get( this ); + }, + run: function( percent ) { + var eased, + hooks = Tween.propHooks[ this.prop ]; + + if ( this.options.duration ) { + this.pos = eased = jQuery.easing[ this.easing ]( + percent, this.options.duration * percent, 0, 1, this.options.duration + ); + } else { + this.pos = eased = percent; + } + this.now = ( this.end - this.start ) * eased + this.start; + + if ( this.options.step ) { + this.options.step.call( this.elem, this.now, this ); + } + + if ( hooks && hooks.set ) { + hooks.set( this ); + } else { + Tween.propHooks._default.set( this ); + } + return this; + } +}; + +Tween.prototype.init.prototype = Tween.prototype; + +Tween.propHooks = { + _default: { + get: function( tween ) { + var result; + + // Use a property on the element directly when it is not a DOM element, + // or when there is no matching style property that exists. + if ( tween.elem.nodeType !== 1 || + tween.elem[ tween.prop ] != null && tween.elem.style[ tween.prop ] == null ) { + return tween.elem[ tween.prop ]; + } + + // Passing an empty string as a 3rd parameter to .css will automatically + // attempt a parseFloat and fallback to a string if the parse fails. + // Simple values such as "10px" are parsed to Float; + // complex values such as "rotate(1rad)" are returned as-is. + result = jQuery.css( tween.elem, tween.prop, "" ); + + // Empty strings, null, undefined and "auto" are converted to 0. + return !result || result === "auto" ? 0 : result; + }, + set: function( tween ) { + + // Use step hook for back compat. + // Use cssHook if its there. + // Use .style if available and use plain properties where available. + if ( jQuery.fx.step[ tween.prop ] ) { + jQuery.fx.step[ tween.prop ]( tween ); + } else if ( tween.elem.nodeType === 1 && ( + jQuery.cssHooks[ tween.prop ] || + tween.elem.style[ finalPropName( tween.prop ) ] != null ) ) { + jQuery.style( tween.elem, tween.prop, tween.now + tween.unit ); + } else { + tween.elem[ tween.prop ] = tween.now; + } + } + } +}; + +// Support: IE <=9 only +// Panic based approach to setting things on disconnected nodes +Tween.propHooks.scrollTop = Tween.propHooks.scrollLeft = { + set: function( tween ) { + if ( tween.elem.nodeType && tween.elem.parentNode ) { + tween.elem[ tween.prop ] = tween.now; + } + } +}; + +jQuery.easing = { + linear: function( p ) { + return p; + }, + swing: function( p ) { + return 0.5 - Math.cos( p * Math.PI ) / 2; + }, + _default: "swing" +}; + +jQuery.fx = Tween.prototype.init; + +// Back compat <1.8 extension point +jQuery.fx.step = {}; + + + + +var + fxNow, inProgress, + rfxtypes = /^(?:toggle|show|hide)$/, + rrun = /queueHooks$/; + +function schedule() { + if ( inProgress ) { + if ( document.hidden === false && window.requestAnimationFrame ) { + window.requestAnimationFrame( schedule ); + } else { + window.setTimeout( schedule, jQuery.fx.interval ); + } + + jQuery.fx.tick(); + } +} + +// Animations created synchronously will run synchronously +function createFxNow() { + window.setTimeout( function() { + fxNow = undefined; + } ); + return ( fxNow = Date.now() ); +} + +// Generate parameters to create a standard animation +function genFx( type, includeWidth ) { + var which, + i = 0, + attrs = { height: type }; + + // If we include width, step value is 1 to do all cssExpand values, + // otherwise step value is 2 to skip over Left and Right + includeWidth = includeWidth ? 1 : 0; + for ( ; i < 4; i += 2 - includeWidth ) { + which = cssExpand[ i ]; + attrs[ "margin" + which ] = attrs[ "padding" + which ] = type; + } + + if ( includeWidth ) { + attrs.opacity = attrs.width = type; + } + + return attrs; +} + +function createTween( value, prop, animation ) { + var tween, + collection = ( Animation.tweeners[ prop ] || [] ).concat( Animation.tweeners[ "*" ] ), + index = 0, + length = collection.length; + for ( ; index < length; index++ ) { + if ( ( tween = collection[ index ].call( animation, prop, value ) ) ) { + + // We're done with this property + return tween; + } + } +} + +function defaultPrefilter( elem, props, opts ) { + var prop, value, toggle, hooks, oldfire, propTween, restoreDisplay, display, + isBox = "width" in props || "height" in props, + anim = this, + orig = {}, + style = elem.style, + hidden = elem.nodeType && isHiddenWithinTree( elem ), + dataShow = dataPriv.get( elem, "fxshow" ); + + // Queue-skipping animations hijack the fx hooks + if ( !opts.queue ) { + hooks = jQuery._queueHooks( elem, "fx" ); + if ( hooks.unqueued == null ) { + hooks.unqueued = 0; + oldfire = hooks.empty.fire; + hooks.empty.fire = function() { + if ( !hooks.unqueued ) { + oldfire(); + } + }; + } + hooks.unqueued++; + + anim.always( function() { + + // Ensure the complete handler is called before this completes + anim.always( function() { + hooks.unqueued--; + if ( !jQuery.queue( elem, "fx" ).length ) { + hooks.empty.fire(); + } + } ); + } ); + } + + // Detect show/hide animations + for ( prop in props ) { + value = props[ prop ]; + if ( rfxtypes.test( value ) ) { + delete props[ prop ]; + toggle = toggle || value === "toggle"; + if ( value === ( hidden ? "hide" : "show" ) ) { + + // Pretend to be hidden if this is a "show" and + // there is still data from a stopped show/hide + if ( value === "show" && dataShow && dataShow[ prop ] !== undefined ) { + hidden = true; + + // Ignore all other no-op show/hide data + } else { + continue; + } + } + orig[ prop ] = dataShow && dataShow[ prop ] || jQuery.style( elem, prop ); + } + } + + // Bail out if this is a no-op like .hide().hide() + propTween = !jQuery.isEmptyObject( props ); + if ( !propTween && jQuery.isEmptyObject( orig ) ) { + return; + } + + // Restrict "overflow" and "display" styles during box animations + if ( isBox && elem.nodeType === 1 ) { + + // Support: IE <=9 - 11, Edge 12 - 15 + // Record all 3 overflow attributes because IE does not infer the shorthand + // from identically-valued overflowX and overflowY and Edge just mirrors + // the overflowX value there. + opts.overflow = [ style.overflow, style.overflowX, style.overflowY ]; + + // Identify a display type, preferring old show/hide data over the CSS cascade + restoreDisplay = dataShow && dataShow.display; + if ( restoreDisplay == null ) { + restoreDisplay = dataPriv.get( elem, "display" ); + } + display = jQuery.css( elem, "display" ); + if ( display === "none" ) { + if ( restoreDisplay ) { + display = restoreDisplay; + } else { + + // Get nonempty value(s) by temporarily forcing visibility + showHide( [ elem ], true ); + restoreDisplay = elem.style.display || restoreDisplay; + display = jQuery.css( elem, "display" ); + showHide( [ elem ] ); + } + } + + // Animate inline elements as inline-block + if ( display === "inline" || display === "inline-block" && restoreDisplay != null ) { + if ( jQuery.css( elem, "float" ) === "none" ) { + + // Restore the original display value at the end of pure show/hide animations + if ( !propTween ) { + anim.done( function() { + style.display = restoreDisplay; + } ); + if ( restoreDisplay == null ) { + display = style.display; + restoreDisplay = display === "none" ? "" : display; + } + } + style.display = "inline-block"; + } + } + } + + if ( opts.overflow ) { + style.overflow = "hidden"; + anim.always( function() { + style.overflow = opts.overflow[ 0 ]; + style.overflowX = opts.overflow[ 1 ]; + style.overflowY = opts.overflow[ 2 ]; + } ); + } + + // Implement show/hide animations + propTween = false; + for ( prop in orig ) { + + // General show/hide setup for this element animation + if ( !propTween ) { + if ( dataShow ) { + if ( "hidden" in dataShow ) { + hidden = dataShow.hidden; + } + } else { + dataShow = dataPriv.access( elem, "fxshow", { display: restoreDisplay } ); + } + + // Store hidden/visible for toggle so `.stop().toggle()` "reverses" + if ( toggle ) { + dataShow.hidden = !hidden; + } + + // Show elements before animating them + if ( hidden ) { + showHide( [ elem ], true ); + } + + /* eslint-disable no-loop-func */ + + anim.done( function() { + + /* eslint-enable no-loop-func */ + + // The final step of a "hide" animation is actually hiding the element + if ( !hidden ) { + showHide( [ elem ] ); + } + dataPriv.remove( elem, "fxshow" ); + for ( prop in orig ) { + jQuery.style( elem, prop, orig[ prop ] ); + } + } ); + } + + // Per-property setup + propTween = createTween( hidden ? dataShow[ prop ] : 0, prop, anim ); + if ( !( prop in dataShow ) ) { + dataShow[ prop ] = propTween.start; + if ( hidden ) { + propTween.end = propTween.start; + propTween.start = 0; + } + } + } +} + +function propFilter( props, specialEasing ) { + var index, name, easing, value, hooks; + + // camelCase, specialEasing and expand cssHook pass + for ( index in props ) { + name = camelCase( index ); + easing = specialEasing[ name ]; + value = props[ index ]; + if ( Array.isArray( value ) ) { + easing = value[ 1 ]; + value = props[ index ] = value[ 0 ]; + } + + if ( index !== name ) { + props[ name ] = value; + delete props[ index ]; + } + + hooks = jQuery.cssHooks[ name ]; + if ( hooks && "expand" in hooks ) { + value = hooks.expand( value ); + delete props[ name ]; + + // Not quite $.extend, this won't overwrite existing keys. + // Reusing 'index' because we have the correct "name" + for ( index in value ) { + if ( !( index in props ) ) { + props[ index ] = value[ index ]; + specialEasing[ index ] = easing; + } + } + } else { + specialEasing[ name ] = easing; + } + } +} + +function Animation( elem, properties, options ) { + var result, + stopped, + index = 0, + length = Animation.prefilters.length, + deferred = jQuery.Deferred().always( function() { + + // Don't match elem in the :animated selector + delete tick.elem; + } ), + tick = function() { + if ( stopped ) { + return false; + } + var currentTime = fxNow || createFxNow(), + remaining = Math.max( 0, animation.startTime + animation.duration - currentTime ), + + // Support: Android 2.3 only + // Archaic crash bug won't allow us to use `1 - ( 0.5 || 0 )` (#12497) + temp = remaining / animation.duration || 0, + percent = 1 - temp, + index = 0, + length = animation.tweens.length; + + for ( ; index < length; index++ ) { + animation.tweens[ index ].run( percent ); + } + + deferred.notifyWith( elem, [ animation, percent, remaining ] ); + + // If there's more to do, yield + if ( percent < 1 && length ) { + return remaining; + } + + // If this was an empty animation, synthesize a final progress notification + if ( !length ) { + deferred.notifyWith( elem, [ animation, 1, 0 ] ); + } + + // Resolve the animation and report its conclusion + deferred.resolveWith( elem, [ animation ] ); + return false; + }, + animation = deferred.promise( { + elem: elem, + props: jQuery.extend( {}, properties ), + opts: jQuery.extend( true, { + specialEasing: {}, + easing: jQuery.easing._default + }, options ), + originalProperties: properties, + originalOptions: options, + startTime: fxNow || createFxNow(), + duration: options.duration, + tweens: [], + createTween: function( prop, end ) { + var tween = jQuery.Tween( elem, animation.opts, prop, end, + animation.opts.specialEasing[ prop ] || animation.opts.easing ); + animation.tweens.push( tween ); + return tween; + }, + stop: function( gotoEnd ) { + var index = 0, + + // If we are going to the end, we want to run all the tweens + // otherwise we skip this part + length = gotoEnd ? animation.tweens.length : 0; + if ( stopped ) { + return this; + } + stopped = true; + for ( ; index < length; index++ ) { + animation.tweens[ index ].run( 1 ); + } + + // Resolve when we played the last frame; otherwise, reject + if ( gotoEnd ) { + deferred.notifyWith( elem, [ animation, 1, 0 ] ); + deferred.resolveWith( elem, [ animation, gotoEnd ] ); + } else { + deferred.rejectWith( elem, [ animation, gotoEnd ] ); + } + return this; + } + } ), + props = animation.props; + + propFilter( props, animation.opts.specialEasing ); + + for ( ; index < length; index++ ) { + result = Animation.prefilters[ index ].call( animation, elem, props, animation.opts ); + if ( result ) { + if ( isFunction( result.stop ) ) { + jQuery._queueHooks( animation.elem, animation.opts.queue ).stop = + result.stop.bind( result ); + } + return result; + } + } + + jQuery.map( props, createTween, animation ); + + if ( isFunction( animation.opts.start ) ) { + animation.opts.start.call( elem, animation ); + } + + // Attach callbacks from options + animation + .progress( animation.opts.progress ) + .done( animation.opts.done, animation.opts.complete ) + .fail( animation.opts.fail ) + .always( animation.opts.always ); + + jQuery.fx.timer( + jQuery.extend( tick, { + elem: elem, + anim: animation, + queue: animation.opts.queue + } ) + ); + + return animation; +} + +jQuery.Animation = jQuery.extend( Animation, { + + tweeners: { + "*": [ function( prop, value ) { + var tween = this.createTween( prop, value ); + adjustCSS( tween.elem, prop, rcssNum.exec( value ), tween ); + return tween; + } ] + }, + + tweener: function( props, callback ) { + if ( isFunction( props ) ) { + callback = props; + props = [ "*" ]; + } else { + props = props.match( rnothtmlwhite ); + } + + var prop, + index = 0, + length = props.length; + + for ( ; index < length; index++ ) { + prop = props[ index ]; + Animation.tweeners[ prop ] = Animation.tweeners[ prop ] || []; + Animation.tweeners[ prop ].unshift( callback ); + } + }, + + prefilters: [ defaultPrefilter ], + + prefilter: function( callback, prepend ) { + if ( prepend ) { + Animation.prefilters.unshift( callback ); + } else { + Animation.prefilters.push( callback ); + } + } +} ); + +jQuery.speed = function( speed, easing, fn ) { + var opt = speed && typeof speed === "object" ? jQuery.extend( {}, speed ) : { + complete: fn || !fn && easing || + isFunction( speed ) && speed, + duration: speed, + easing: fn && easing || easing && !isFunction( easing ) && easing + }; + + // Go to the end state if fx are off + if ( jQuery.fx.off ) { + opt.duration = 0; + + } else { + if ( typeof opt.duration !== "number" ) { + if ( opt.duration in jQuery.fx.speeds ) { + opt.duration = jQuery.fx.speeds[ opt.duration ]; + + } else { + opt.duration = jQuery.fx.speeds._default; + } + } + } + + // Normalize opt.queue - true/undefined/null -> "fx" + if ( opt.queue == null || opt.queue === true ) { + opt.queue = "fx"; + } + + // Queueing + opt.old = opt.complete; + + opt.complete = function() { + if ( isFunction( opt.old ) ) { + opt.old.call( this ); + } + + if ( opt.queue ) { + jQuery.dequeue( this, opt.queue ); + } + }; + + return opt; +}; + +jQuery.fn.extend( { + fadeTo: function( speed, to, easing, callback ) { + + // Show any hidden elements after setting opacity to 0 + return this.filter( isHiddenWithinTree ).css( "opacity", 0 ).show() + + // Animate to the value specified + .end().animate( { opacity: to }, speed, easing, callback ); + }, + animate: function( prop, speed, easing, callback ) { + var empty = jQuery.isEmptyObject( prop ), + optall = jQuery.speed( speed, easing, callback ), + doAnimation = function() { + + // Operate on a copy of prop so per-property easing won't be lost + var anim = Animation( this, jQuery.extend( {}, prop ), optall ); + + // Empty animations, or finishing resolves immediately + if ( empty || dataPriv.get( this, "finish" ) ) { + anim.stop( true ); + } + }; + doAnimation.finish = doAnimation; + + return empty || optall.queue === false ? + this.each( doAnimation ) : + this.queue( optall.queue, doAnimation ); + }, + stop: function( type, clearQueue, gotoEnd ) { + var stopQueue = function( hooks ) { + var stop = hooks.stop; + delete hooks.stop; + stop( gotoEnd ); + }; + + if ( typeof type !== "string" ) { + gotoEnd = clearQueue; + clearQueue = type; + type = undefined; + } + if ( clearQueue ) { + this.queue( type || "fx", [] ); + } + + return this.each( function() { + var dequeue = true, + index = type != null && type + "queueHooks", + timers = jQuery.timers, + data = dataPriv.get( this ); + + if ( index ) { + if ( data[ index ] && data[ index ].stop ) { + stopQueue( data[ index ] ); + } + } else { + for ( index in data ) { + if ( data[ index ] && data[ index ].stop && rrun.test( index ) ) { + stopQueue( data[ index ] ); + } + } + } + + for ( index = timers.length; index--; ) { + if ( timers[ index ].elem === this && + ( type == null || timers[ index ].queue === type ) ) { + + timers[ index ].anim.stop( gotoEnd ); + dequeue = false; + timers.splice( index, 1 ); + } + } + + // Start the next in the queue if the last step wasn't forced. + // Timers currently will call their complete callbacks, which + // will dequeue but only if they were gotoEnd. + if ( dequeue || !gotoEnd ) { + jQuery.dequeue( this, type ); + } + } ); + }, + finish: function( type ) { + if ( type !== false ) { + type = type || "fx"; + } + return this.each( function() { + var index, + data = dataPriv.get( this ), + queue = data[ type + "queue" ], + hooks = data[ type + "queueHooks" ], + timers = jQuery.timers, + length = queue ? queue.length : 0; + + // Enable finishing flag on private data + data.finish = true; + + // Empty the queue first + jQuery.queue( this, type, [] ); + + if ( hooks && hooks.stop ) { + hooks.stop.call( this, true ); + } + + // Look for any active animations, and finish them + for ( index = timers.length; index--; ) { + if ( timers[ index ].elem === this && timers[ index ].queue === type ) { + timers[ index ].anim.stop( true ); + timers.splice( index, 1 ); + } + } + + // Look for any animations in the old queue and finish them + for ( index = 0; index < length; index++ ) { + if ( queue[ index ] && queue[ index ].finish ) { + queue[ index ].finish.call( this ); + } + } + + // Turn off finishing flag + delete data.finish; + } ); + } +} ); + +jQuery.each( [ "toggle", "show", "hide" ], function( _i, name ) { + var cssFn = jQuery.fn[ name ]; + jQuery.fn[ name ] = function( speed, easing, callback ) { + return speed == null || typeof speed === "boolean" ? + cssFn.apply( this, arguments ) : + this.animate( genFx( name, true ), speed, easing, callback ); + }; +} ); + +// Generate shortcuts for custom animations +jQuery.each( { + slideDown: genFx( "show" ), + slideUp: genFx( "hide" ), + slideToggle: genFx( "toggle" ), + fadeIn: { opacity: "show" }, + fadeOut: { opacity: "hide" }, + fadeToggle: { opacity: "toggle" } +}, function( name, props ) { + jQuery.fn[ name ] = function( speed, easing, callback ) { + return this.animate( props, speed, easing, callback ); + }; +} ); + +jQuery.timers = []; +jQuery.fx.tick = function() { + var timer, + i = 0, + timers = jQuery.timers; + + fxNow = Date.now(); + + for ( ; i < timers.length; i++ ) { + timer = timers[ i ]; + + // Run the timer and safely remove it when done (allowing for external removal) + if ( !timer() && timers[ i ] === timer ) { + timers.splice( i--, 1 ); + } + } + + if ( !timers.length ) { + jQuery.fx.stop(); + } + fxNow = undefined; +}; + +jQuery.fx.timer = function( timer ) { + jQuery.timers.push( timer ); + jQuery.fx.start(); +}; + +jQuery.fx.interval = 13; +jQuery.fx.start = function() { + if ( inProgress ) { + return; + } + + inProgress = true; + schedule(); +}; + +jQuery.fx.stop = function() { + inProgress = null; +}; + +jQuery.fx.speeds = { + slow: 600, + fast: 200, + + // Default speed + _default: 400 +}; + + +// Based off of the plugin by Clint Helfers, with permission. +// https://web.archive.org/web/20100324014747/http://blindsignals.com/index.php/2009/07/jquery-delay/ +jQuery.fn.delay = function( time, type ) { + time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time; + type = type || "fx"; + + return this.queue( type, function( next, hooks ) { + var timeout = window.setTimeout( next, time ); + hooks.stop = function() { + window.clearTimeout( timeout ); + }; + } ); +}; + + +( function() { + var input = document.createElement( "input" ), + select = document.createElement( "select" ), + opt = select.appendChild( document.createElement( "option" ) ); + + input.type = "checkbox"; + + // Support: Android <=4.3 only + // Default value for a checkbox should be "on" + support.checkOn = input.value !== ""; + + // Support: IE <=11 only + // Must access selectedIndex to make default options select + support.optSelected = opt.selected; + + // Support: IE <=11 only + // An input loses its value after becoming a radio + input = document.createElement( "input" ); + input.value = "t"; + input.type = "radio"; + support.radioValue = input.value === "t"; +} )(); + + +var boolHook, + attrHandle = jQuery.expr.attrHandle; + +jQuery.fn.extend( { + attr: function( name, value ) { + return access( this, jQuery.attr, name, value, arguments.length > 1 ); + }, + + removeAttr: function( name ) { + return this.each( function() { + jQuery.removeAttr( this, name ); + } ); + } +} ); + +jQuery.extend( { + attr: function( elem, name, value ) { + var ret, hooks, + nType = elem.nodeType; + + // Don't get/set attributes on text, comment and attribute nodes + if ( nType === 3 || nType === 8 || nType === 2 ) { + return; + } + + // Fallback to prop when attributes are not supported + if ( typeof elem.getAttribute === "undefined" ) { + return jQuery.prop( elem, name, value ); + } + + // Attribute hooks are determined by the lowercase version + // Grab necessary hook if one is defined + if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) { + hooks = jQuery.attrHooks[ name.toLowerCase() ] || + ( jQuery.expr.match.bool.test( name ) ? boolHook : undefined ); + } + + if ( value !== undefined ) { + if ( value === null ) { + jQuery.removeAttr( elem, name ); + return; + } + + if ( hooks && "set" in hooks && + ( ret = hooks.set( elem, value, name ) ) !== undefined ) { + return ret; + } + + elem.setAttribute( name, value + "" ); + return value; + } + + if ( hooks && "get" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) { + return ret; + } + + ret = jQuery.find.attr( elem, name ); + + // Non-existent attributes return null, we normalize to undefined + return ret == null ? undefined : ret; + }, + + attrHooks: { + type: { + set: function( elem, value ) { + if ( !support.radioValue && value === "radio" && + nodeName( elem, "input" ) ) { + var val = elem.value; + elem.setAttribute( "type", value ); + if ( val ) { + elem.value = val; + } + return value; + } + } + } + }, + + removeAttr: function( elem, value ) { + var name, + i = 0, + + // Attribute names can contain non-HTML whitespace characters + // https://html.spec.whatwg.org/multipage/syntax.html#attributes-2 + attrNames = value && value.match( rnothtmlwhite ); + + if ( attrNames && elem.nodeType === 1 ) { + while ( ( name = attrNames[ i++ ] ) ) { + elem.removeAttribute( name ); + } + } + } +} ); + +// Hooks for boolean attributes +boolHook = { + set: function( elem, value, name ) { + if ( value === false ) { + + // Remove boolean attributes when set to false + jQuery.removeAttr( elem, name ); + } else { + elem.setAttribute( name, name ); + } + return name; + } +}; + +jQuery.each( jQuery.expr.match.bool.source.match( /\w+/g ), function( _i, name ) { + var getter = attrHandle[ name ] || jQuery.find.attr; + + attrHandle[ name ] = function( elem, name, isXML ) { + var ret, handle, + lowercaseName = name.toLowerCase(); + + if ( !isXML ) { + + // Avoid an infinite loop by temporarily removing this function from the getter + handle = attrHandle[ lowercaseName ]; + attrHandle[ lowercaseName ] = ret; + ret = getter( elem, name, isXML ) != null ? + lowercaseName : + null; + attrHandle[ lowercaseName ] = handle; + } + return ret; + }; +} ); + + + + +var rfocusable = /^(?:input|select|textarea|button)$/i, + rclickable = /^(?:a|area)$/i; + +jQuery.fn.extend( { + prop: function( name, value ) { + return access( this, jQuery.prop, name, value, arguments.length > 1 ); + }, + + removeProp: function( name ) { + return this.each( function() { + delete this[ jQuery.propFix[ name ] || name ]; + } ); + } +} ); + +jQuery.extend( { + prop: function( elem, name, value ) { + var ret, hooks, + nType = elem.nodeType; + + // Don't get/set properties on text, comment and attribute nodes + if ( nType === 3 || nType === 8 || nType === 2 ) { + return; + } + + if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) { + + // Fix name and attach hooks + name = jQuery.propFix[ name ] || name; + hooks = jQuery.propHooks[ name ]; + } + + if ( value !== undefined ) { + if ( hooks && "set" in hooks && + ( ret = hooks.set( elem, value, name ) ) !== undefined ) { + return ret; + } + + return ( elem[ name ] = value ); + } + + if ( hooks && "get" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) { + return ret; + } + + return elem[ name ]; + }, + + propHooks: { + tabIndex: { + get: function( elem ) { + + // Support: IE <=9 - 11 only + // elem.tabIndex doesn't always return the + // correct value when it hasn't been explicitly set + // https://web.archive.org/web/20141116233347/http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/ + // Use proper attribute retrieval(#12072) + var tabindex = jQuery.find.attr( elem, "tabindex" ); + + if ( tabindex ) { + return parseInt( tabindex, 10 ); + } + + if ( + rfocusable.test( elem.nodeName ) || + rclickable.test( elem.nodeName ) && + elem.href + ) { + return 0; + } + + return -1; + } + } + }, + + propFix: { + "for": "htmlFor", + "class": "className" + } +} ); + +// Support: IE <=11 only +// Accessing the selectedIndex property +// forces the browser to respect setting selected +// on the option +// The getter ensures a default option is selected +// when in an optgroup +// eslint rule "no-unused-expressions" is disabled for this code +// since it considers such accessions noop +if ( !support.optSelected ) { + jQuery.propHooks.selected = { + get: function( elem ) { + + /* eslint no-unused-expressions: "off" */ + + var parent = elem.parentNode; + if ( parent && parent.parentNode ) { + parent.parentNode.selectedIndex; + } + return null; + }, + set: function( elem ) { + + /* eslint no-unused-expressions: "off" */ + + var parent = elem.parentNode; + if ( parent ) { + parent.selectedIndex; + + if ( parent.parentNode ) { + parent.parentNode.selectedIndex; + } + } + } + }; +} + +jQuery.each( [ + "tabIndex", + "readOnly", + "maxLength", + "cellSpacing", + "cellPadding", + "rowSpan", + "colSpan", + "useMap", + "frameBorder", + "contentEditable" +], function() { + jQuery.propFix[ this.toLowerCase() ] = this; +} ); + + + + + // Strip and collapse whitespace according to HTML spec + // https://infra.spec.whatwg.org/#strip-and-collapse-ascii-whitespace + function stripAndCollapse( value ) { + var tokens = value.match( rnothtmlwhite ) || []; + return tokens.join( " " ); + } + + +function getClass( elem ) { + return elem.getAttribute && elem.getAttribute( "class" ) || ""; +} + +function classesToArray( value ) { + if ( Array.isArray( value ) ) { + return value; + } + if ( typeof value === "string" ) { + return value.match( rnothtmlwhite ) || []; + } + return []; +} + +jQuery.fn.extend( { + addClass: function( value ) { + var classes, elem, cur, curValue, clazz, j, finalValue, + i = 0; + + if ( isFunction( value ) ) { + return this.each( function( j ) { + jQuery( this ).addClass( value.call( this, j, getClass( this ) ) ); + } ); + } + + classes = classesToArray( value ); + + if ( classes.length ) { + while ( ( elem = this[ i++ ] ) ) { + curValue = getClass( elem ); + cur = elem.nodeType === 1 && ( " " + stripAndCollapse( curValue ) + " " ); + + if ( cur ) { + j = 0; + while ( ( clazz = classes[ j++ ] ) ) { + if ( cur.indexOf( " " + clazz + " " ) < 0 ) { + cur += clazz + " "; + } + } + + // Only assign if different to avoid unneeded rendering. + finalValue = stripAndCollapse( cur ); + if ( curValue !== finalValue ) { + elem.setAttribute( "class", finalValue ); + } + } + } + } + + return this; + }, + + removeClass: function( value ) { + var classes, elem, cur, curValue, clazz, j, finalValue, + i = 0; + + if ( isFunction( value ) ) { + return this.each( function( j ) { + jQuery( this ).removeClass( value.call( this, j, getClass( this ) ) ); + } ); + } + + if ( !arguments.length ) { + return this.attr( "class", "" ); + } + + classes = classesToArray( value ); + + if ( classes.length ) { + while ( ( elem = this[ i++ ] ) ) { + curValue = getClass( elem ); + + // This expression is here for better compressibility (see addClass) + cur = elem.nodeType === 1 && ( " " + stripAndCollapse( curValue ) + " " ); + + if ( cur ) { + j = 0; + while ( ( clazz = classes[ j++ ] ) ) { + + // Remove *all* instances + while ( cur.indexOf( " " + clazz + " " ) > -1 ) { + cur = cur.replace( " " + clazz + " ", " " ); + } + } + + // Only assign if different to avoid unneeded rendering. + finalValue = stripAndCollapse( cur ); + if ( curValue !== finalValue ) { + elem.setAttribute( "class", finalValue ); + } + } + } + } + + return this; + }, + + toggleClass: function( value, stateVal ) { + var type = typeof value, + isValidValue = type === "string" || Array.isArray( value ); + + if ( typeof stateVal === "boolean" && isValidValue ) { + return stateVal ? this.addClass( value ) : this.removeClass( value ); + } + + if ( isFunction( value ) ) { + return this.each( function( i ) { + jQuery( this ).toggleClass( + value.call( this, i, getClass( this ), stateVal ), + stateVal + ); + } ); + } + + return this.each( function() { + var className, i, self, classNames; + + if ( isValidValue ) { + + // Toggle individual class names + i = 0; + self = jQuery( this ); + classNames = classesToArray( value ); + + while ( ( className = classNames[ i++ ] ) ) { + + // Check each className given, space separated list + if ( self.hasClass( className ) ) { + self.removeClass( className ); + } else { + self.addClass( className ); + } + } + + // Toggle whole class name + } else if ( value === undefined || type === "boolean" ) { + className = getClass( this ); + if ( className ) { + + // Store className if set + dataPriv.set( this, "__className__", className ); + } + + // If the element has a class name or if we're passed `false`, + // then remove the whole classname (if there was one, the above saved it). + // Otherwise bring back whatever was previously saved (if anything), + // falling back to the empty string if nothing was stored. + if ( this.setAttribute ) { + this.setAttribute( "class", + className || value === false ? + "" : + dataPriv.get( this, "__className__" ) || "" + ); + } + } + } ); + }, + + hasClass: function( selector ) { + var className, elem, + i = 0; + + className = " " + selector + " "; + while ( ( elem = this[ i++ ] ) ) { + if ( elem.nodeType === 1 && + ( " " + stripAndCollapse( getClass( elem ) ) + " " ).indexOf( className ) > -1 ) { + return true; + } + } + + return false; + } +} ); + + + + +var rreturn = /\r/g; + +jQuery.fn.extend( { + val: function( value ) { + var hooks, ret, valueIsFunction, + elem = this[ 0 ]; + + if ( !arguments.length ) { + if ( elem ) { + hooks = jQuery.valHooks[ elem.type ] || + jQuery.valHooks[ elem.nodeName.toLowerCase() ]; + + if ( hooks && + "get" in hooks && + ( ret = hooks.get( elem, "value" ) ) !== undefined + ) { + return ret; + } + + ret = elem.value; + + // Handle most common string cases + if ( typeof ret === "string" ) { + return ret.replace( rreturn, "" ); + } + + // Handle cases where value is null/undef or number + return ret == null ? "" : ret; + } + + return; + } + + valueIsFunction = isFunction( value ); + + return this.each( function( i ) { + var val; + + if ( this.nodeType !== 1 ) { + return; + } + + if ( valueIsFunction ) { + val = value.call( this, i, jQuery( this ).val() ); + } else { + val = value; + } + + // Treat null/undefined as ""; convert numbers to string + if ( val == null ) { + val = ""; + + } else if ( typeof val === "number" ) { + val += ""; + + } else if ( Array.isArray( val ) ) { + val = jQuery.map( val, function( value ) { + return value == null ? "" : value + ""; + } ); + } + + hooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ]; + + // If set returns undefined, fall back to normal setting + if ( !hooks || !( "set" in hooks ) || hooks.set( this, val, "value" ) === undefined ) { + this.value = val; + } + } ); + } +} ); + +jQuery.extend( { + valHooks: { + option: { + get: function( elem ) { + + var val = jQuery.find.attr( elem, "value" ); + return val != null ? + val : + + // Support: IE <=10 - 11 only + // option.text throws exceptions (#14686, #14858) + // Strip and collapse whitespace + // https://html.spec.whatwg.org/#strip-and-collapse-whitespace + stripAndCollapse( jQuery.text( elem ) ); + } + }, + select: { + get: function( elem ) { + var value, option, i, + options = elem.options, + index = elem.selectedIndex, + one = elem.type === "select-one", + values = one ? null : [], + max = one ? index + 1 : options.length; + + if ( index < 0 ) { + i = max; + + } else { + i = one ? index : 0; + } + + // Loop through all the selected options + for ( ; i < max; i++ ) { + option = options[ i ]; + + // Support: IE <=9 only + // IE8-9 doesn't update selected after form reset (#2551) + if ( ( option.selected || i === index ) && + + // Don't return options that are disabled or in a disabled optgroup + !option.disabled && + ( !option.parentNode.disabled || + !nodeName( option.parentNode, "optgroup" ) ) ) { + + // Get the specific value for the option + value = jQuery( option ).val(); + + // We don't need an array for one selects + if ( one ) { + return value; + } + + // Multi-Selects return an array + values.push( value ); + } + } + + return values; + }, + + set: function( elem, value ) { + var optionSet, option, + options = elem.options, + values = jQuery.makeArray( value ), + i = options.length; + + while ( i-- ) { + option = options[ i ]; + + /* eslint-disable no-cond-assign */ + + if ( option.selected = + jQuery.inArray( jQuery.valHooks.option.get( option ), values ) > -1 + ) { + optionSet = true; + } + + /* eslint-enable no-cond-assign */ + } + + // Force browsers to behave consistently when non-matching value is set + if ( !optionSet ) { + elem.selectedIndex = -1; + } + return values; + } + } + } +} ); + +// Radios and checkboxes getter/setter +jQuery.each( [ "radio", "checkbox" ], function() { + jQuery.valHooks[ this ] = { + set: function( elem, value ) { + if ( Array.isArray( value ) ) { + return ( elem.checked = jQuery.inArray( jQuery( elem ).val(), value ) > -1 ); + } + } + }; + if ( !support.checkOn ) { + jQuery.valHooks[ this ].get = function( elem ) { + return elem.getAttribute( "value" ) === null ? "on" : elem.value; + }; + } +} ); + + + + +// Return jQuery for attributes-only inclusion + + +support.focusin = "onfocusin" in window; + + +var rfocusMorph = /^(?:focusinfocus|focusoutblur)$/, + stopPropagationCallback = function( e ) { + e.stopPropagation(); + }; + +jQuery.extend( jQuery.event, { + + trigger: function( event, data, elem, onlyHandlers ) { + + var i, cur, tmp, bubbleType, ontype, handle, special, lastElement, + eventPath = [ elem || document ], + type = hasOwn.call( event, "type" ) ? event.type : event, + namespaces = hasOwn.call( event, "namespace" ) ? event.namespace.split( "." ) : []; + + cur = lastElement = tmp = elem = elem || document; + + // Don't do events on text and comment nodes + if ( elem.nodeType === 3 || elem.nodeType === 8 ) { + return; + } + + // focus/blur morphs to focusin/out; ensure we're not firing them right now + if ( rfocusMorph.test( type + jQuery.event.triggered ) ) { + return; + } + + if ( type.indexOf( "." ) > -1 ) { + + // Namespaced trigger; create a regexp to match event type in handle() + namespaces = type.split( "." ); + type = namespaces.shift(); + namespaces.sort(); + } + ontype = type.indexOf( ":" ) < 0 && "on" + type; + + // Caller can pass in a jQuery.Event object, Object, or just an event type string + event = event[ jQuery.expando ] ? + event : + new jQuery.Event( type, typeof event === "object" && event ); + + // Trigger bitmask: & 1 for native handlers; & 2 for jQuery (always true) + event.isTrigger = onlyHandlers ? 2 : 3; + event.namespace = namespaces.join( "." ); + event.rnamespace = event.namespace ? + new RegExp( "(^|\\.)" + namespaces.join( "\\.(?:.*\\.|)" ) + "(\\.|$)" ) : + null; + + // Clean up the event in case it is being reused + event.result = undefined; + if ( !event.target ) { + event.target = elem; + } + + // Clone any incoming data and prepend the event, creating the handler arg list + data = data == null ? + [ event ] : + jQuery.makeArray( data, [ event ] ); + + // Allow special events to draw outside the lines + special = jQuery.event.special[ type ] || {}; + if ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) { + return; + } + + // Determine event propagation path in advance, per W3C events spec (#9951) + // Bubble up to document, then to window; watch for a global ownerDocument var (#9724) + if ( !onlyHandlers && !special.noBubble && !isWindow( elem ) ) { + + bubbleType = special.delegateType || type; + if ( !rfocusMorph.test( bubbleType + type ) ) { + cur = cur.parentNode; + } + for ( ; cur; cur = cur.parentNode ) { + eventPath.push( cur ); + tmp = cur; + } + + // Only add window if we got to document (e.g., not plain obj or detached DOM) + if ( tmp === ( elem.ownerDocument || document ) ) { + eventPath.push( tmp.defaultView || tmp.parentWindow || window ); + } + } + + // Fire handlers on the event path + i = 0; + while ( ( cur = eventPath[ i++ ] ) && !event.isPropagationStopped() ) { + lastElement = cur; + event.type = i > 1 ? + bubbleType : + special.bindType || type; + + // jQuery handler + handle = ( + dataPriv.get( cur, "events" ) || Object.create( null ) + )[ event.type ] && + dataPriv.get( cur, "handle" ); + if ( handle ) { + handle.apply( cur, data ); + } + + // Native handler + handle = ontype && cur[ ontype ]; + if ( handle && handle.apply && acceptData( cur ) ) { + event.result = handle.apply( cur, data ); + if ( event.result === false ) { + event.preventDefault(); + } + } + } + event.type = type; + + // If nobody prevented the default action, do it now + if ( !onlyHandlers && !event.isDefaultPrevented() ) { + + if ( ( !special._default || + special._default.apply( eventPath.pop(), data ) === false ) && + acceptData( elem ) ) { + + // Call a native DOM method on the target with the same name as the event. + // Don't do default actions on window, that's where global variables be (#6170) + if ( ontype && isFunction( elem[ type ] ) && !isWindow( elem ) ) { + + // Don't re-trigger an onFOO event when we call its FOO() method + tmp = elem[ ontype ]; + + if ( tmp ) { + elem[ ontype ] = null; + } + + // Prevent re-triggering of the same event, since we already bubbled it above + jQuery.event.triggered = type; + + if ( event.isPropagationStopped() ) { + lastElement.addEventListener( type, stopPropagationCallback ); + } + + elem[ type ](); + + if ( event.isPropagationStopped() ) { + lastElement.removeEventListener( type, stopPropagationCallback ); + } + + jQuery.event.triggered = undefined; + + if ( tmp ) { + elem[ ontype ] = tmp; + } + } + } + } + + return event.result; + }, + + // Piggyback on a donor event to simulate a different one + // Used only for `focus(in | out)` events + simulate: function( type, elem, event ) { + var e = jQuery.extend( + new jQuery.Event(), + event, + { + type: type, + isSimulated: true + } + ); + + jQuery.event.trigger( e, null, elem ); + } + +} ); + +jQuery.fn.extend( { + + trigger: function( type, data ) { + return this.each( function() { + jQuery.event.trigger( type, data, this ); + } ); + }, + triggerHandler: function( type, data ) { + var elem = this[ 0 ]; + if ( elem ) { + return jQuery.event.trigger( type, data, elem, true ); + } + } +} ); + + +// Support: Firefox <=44 +// Firefox doesn't have focus(in | out) events +// Related ticket - https://bugzilla.mozilla.org/show_bug.cgi?id=687787 +// +// Support: Chrome <=48 - 49, Safari <=9.0 - 9.1 +// focus(in | out) events fire after focus & blur events, +// which is spec violation - http://www.w3.org/TR/DOM-Level-3-Events/#events-focusevent-event-order +// Related ticket - https://bugs.chromium.org/p/chromium/issues/detail?id=449857 +if ( !support.focusin ) { + jQuery.each( { focus: "focusin", blur: "focusout" }, function( orig, fix ) { + + // Attach a single capturing handler on the document while someone wants focusin/focusout + var handler = function( event ) { + jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ) ); + }; + + jQuery.event.special[ fix ] = { + setup: function() { + + // Handle: regular nodes (via `this.ownerDocument`), window + // (via `this.document`) & document (via `this`). + var doc = this.ownerDocument || this.document || this, + attaches = dataPriv.access( doc, fix ); + + if ( !attaches ) { + doc.addEventListener( orig, handler, true ); + } + dataPriv.access( doc, fix, ( attaches || 0 ) + 1 ); + }, + teardown: function() { + var doc = this.ownerDocument || this.document || this, + attaches = dataPriv.access( doc, fix ) - 1; + + if ( !attaches ) { + doc.removeEventListener( orig, handler, true ); + dataPriv.remove( doc, fix ); + + } else { + dataPriv.access( doc, fix, attaches ); + } + } + }; + } ); +} +var location = window.location; + +var nonce = { guid: Date.now() }; + +var rquery = ( /\?/ ); + + + +// Cross-browser xml parsing +jQuery.parseXML = function( data ) { + var xml; + if ( !data || typeof data !== "string" ) { + return null; + } + + // Support: IE 9 - 11 only + // IE throws on parseFromString with invalid input. + try { + xml = ( new window.DOMParser() ).parseFromString( data, "text/xml" ); + } catch ( e ) { + xml = undefined; + } + + if ( !xml || xml.getElementsByTagName( "parsererror" ).length ) { + jQuery.error( "Invalid XML: " + data ); + } + return xml; +}; + + +var + rbracket = /\[\]$/, + rCRLF = /\r?\n/g, + rsubmitterTypes = /^(?:submit|button|image|reset|file)$/i, + rsubmittable = /^(?:input|select|textarea|keygen)/i; + +function buildParams( prefix, obj, traditional, add ) { + var name; + + if ( Array.isArray( obj ) ) { + + // Serialize array item. + jQuery.each( obj, function( i, v ) { + if ( traditional || rbracket.test( prefix ) ) { + + // Treat each array item as a scalar. + add( prefix, v ); + + } else { + + // Item is non-scalar (array or object), encode its numeric index. + buildParams( + prefix + "[" + ( typeof v === "object" && v != null ? i : "" ) + "]", + v, + traditional, + add + ); + } + } ); + + } else if ( !traditional && toType( obj ) === "object" ) { + + // Serialize object item. + for ( name in obj ) { + buildParams( prefix + "[" + name + "]", obj[ name ], traditional, add ); + } + + } else { + + // Serialize scalar item. + add( prefix, obj ); + } +} + +// Serialize an array of form elements or a set of +// key/values into a query string +jQuery.param = function( a, traditional ) { + var prefix, + s = [], + add = function( key, valueOrFunction ) { + + // If value is a function, invoke it and use its return value + var value = isFunction( valueOrFunction ) ? + valueOrFunction() : + valueOrFunction; + + s[ s.length ] = encodeURIComponent( key ) + "=" + + encodeURIComponent( value == null ? "" : value ); + }; + + if ( a == null ) { + return ""; + } + + // If an array was passed in, assume that it is an array of form elements. + if ( Array.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) { + + // Serialize the form elements + jQuery.each( a, function() { + add( this.name, this.value ); + } ); + + } else { + + // If traditional, encode the "old" way (the way 1.3.2 or older + // did it), otherwise encode params recursively. + for ( prefix in a ) { + buildParams( prefix, a[ prefix ], traditional, add ); + } + } + + // Return the resulting serialization + return s.join( "&" ); +}; + +jQuery.fn.extend( { + serialize: function() { + return jQuery.param( this.serializeArray() ); + }, + serializeArray: function() { + return this.map( function() { + + // Can add propHook for "elements" to filter or add form elements + var elements = jQuery.prop( this, "elements" ); + return elements ? jQuery.makeArray( elements ) : this; + } ) + .filter( function() { + var type = this.type; + + // Use .is( ":disabled" ) so that fieldset[disabled] works + return this.name && !jQuery( this ).is( ":disabled" ) && + rsubmittable.test( this.nodeName ) && !rsubmitterTypes.test( type ) && + ( this.checked || !rcheckableType.test( type ) ); + } ) + .map( function( _i, elem ) { + var val = jQuery( this ).val(); + + if ( val == null ) { + return null; + } + + if ( Array.isArray( val ) ) { + return jQuery.map( val, function( val ) { + return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) }; + } ); + } + + return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) }; + } ).get(); + } +} ); + + +var + r20 = /%20/g, + rhash = /#.*$/, + rantiCache = /([?&])_=[^&]*/, + rheaders = /^(.*?):[ \t]*([^\r\n]*)$/mg, + + // #7653, #8125, #8152: local protocol detection + rlocalProtocol = /^(?:about|app|app-storage|.+-extension|file|res|widget):$/, + rnoContent = /^(?:GET|HEAD)$/, + rprotocol = /^\/\//, + + /* Prefilters + * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example) + * 2) These are called: + * - BEFORE asking for a transport + * - AFTER param serialization (s.data is a string if s.processData is true) + * 3) key is the dataType + * 4) the catchall symbol "*" can be used + * 5) execution will start with transport dataType and THEN continue down to "*" if needed + */ + prefilters = {}, + + /* Transports bindings + * 1) key is the dataType + * 2) the catchall symbol "*" can be used + * 3) selection will start with transport dataType and THEN go to "*" if needed + */ + transports = {}, + + // Avoid comment-prolog char sequence (#10098); must appease lint and evade compression + allTypes = "*/".concat( "*" ), + + // Anchor tag for parsing the document origin + originAnchor = document.createElement( "a" ); + originAnchor.href = location.href; + +// Base "constructor" for jQuery.ajaxPrefilter and jQuery.ajaxTransport +function addToPrefiltersOrTransports( structure ) { + + // dataTypeExpression is optional and defaults to "*" + return function( dataTypeExpression, func ) { + + if ( typeof dataTypeExpression !== "string" ) { + func = dataTypeExpression; + dataTypeExpression = "*"; + } + + var dataType, + i = 0, + dataTypes = dataTypeExpression.toLowerCase().match( rnothtmlwhite ) || []; + + if ( isFunction( func ) ) { + + // For each dataType in the dataTypeExpression + while ( ( dataType = dataTypes[ i++ ] ) ) { + + // Prepend if requested + if ( dataType[ 0 ] === "+" ) { + dataType = dataType.slice( 1 ) || "*"; + ( structure[ dataType ] = structure[ dataType ] || [] ).unshift( func ); + + // Otherwise append + } else { + ( structure[ dataType ] = structure[ dataType ] || [] ).push( func ); + } + } + } + }; +} + +// Base inspection function for prefilters and transports +function inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR ) { + + var inspected = {}, + seekingTransport = ( structure === transports ); + + function inspect( dataType ) { + var selected; + inspected[ dataType ] = true; + jQuery.each( structure[ dataType ] || [], function( _, prefilterOrFactory ) { + var dataTypeOrTransport = prefilterOrFactory( options, originalOptions, jqXHR ); + if ( typeof dataTypeOrTransport === "string" && + !seekingTransport && !inspected[ dataTypeOrTransport ] ) { + + options.dataTypes.unshift( dataTypeOrTransport ); + inspect( dataTypeOrTransport ); + return false; + } else if ( seekingTransport ) { + return !( selected = dataTypeOrTransport ); + } + } ); + return selected; + } + + return inspect( options.dataTypes[ 0 ] ) || !inspected[ "*" ] && inspect( "*" ); +} + +// A special extend for ajax options +// that takes "flat" options (not to be deep extended) +// Fixes #9887 +function ajaxExtend( target, src ) { + var key, deep, + flatOptions = jQuery.ajaxSettings.flatOptions || {}; + + for ( key in src ) { + if ( src[ key ] !== undefined ) { + ( flatOptions[ key ] ? target : ( deep || ( deep = {} ) ) )[ key ] = src[ key ]; + } + } + if ( deep ) { + jQuery.extend( true, target, deep ); + } + + return target; +} + +/* Handles responses to an ajax request: + * - finds the right dataType (mediates between content-type and expected dataType) + * - returns the corresponding response + */ +function ajaxHandleResponses( s, jqXHR, responses ) { + + var ct, type, finalDataType, firstDataType, + contents = s.contents, + dataTypes = s.dataTypes; + + // Remove auto dataType and get content-type in the process + while ( dataTypes[ 0 ] === "*" ) { + dataTypes.shift(); + if ( ct === undefined ) { + ct = s.mimeType || jqXHR.getResponseHeader( "Content-Type" ); + } + } + + // Check if we're dealing with a known content-type + if ( ct ) { + for ( type in contents ) { + if ( contents[ type ] && contents[ type ].test( ct ) ) { + dataTypes.unshift( type ); + break; + } + } + } + + // Check to see if we have a response for the expected dataType + if ( dataTypes[ 0 ] in responses ) { + finalDataType = dataTypes[ 0 ]; + } else { + + // Try convertible dataTypes + for ( type in responses ) { + if ( !dataTypes[ 0 ] || s.converters[ type + " " + dataTypes[ 0 ] ] ) { + finalDataType = type; + break; + } + if ( !firstDataType ) { + firstDataType = type; + } + } + + // Or just use first one + finalDataType = finalDataType || firstDataType; + } + + // If we found a dataType + // We add the dataType to the list if needed + // and return the corresponding response + if ( finalDataType ) { + if ( finalDataType !== dataTypes[ 0 ] ) { + dataTypes.unshift( finalDataType ); + } + return responses[ finalDataType ]; + } +} + +/* Chain conversions given the request and the original response + * Also sets the responseXXX fields on the jqXHR instance + */ +function ajaxConvert( s, response, jqXHR, isSuccess ) { + var conv2, current, conv, tmp, prev, + converters = {}, + + // Work with a copy of dataTypes in case we need to modify it for conversion + dataTypes = s.dataTypes.slice(); + + // Create converters map with lowercased keys + if ( dataTypes[ 1 ] ) { + for ( conv in s.converters ) { + converters[ conv.toLowerCase() ] = s.converters[ conv ]; + } + } + + current = dataTypes.shift(); + + // Convert to each sequential dataType + while ( current ) { + + if ( s.responseFields[ current ] ) { + jqXHR[ s.responseFields[ current ] ] = response; + } + + // Apply the dataFilter if provided + if ( !prev && isSuccess && s.dataFilter ) { + response = s.dataFilter( response, s.dataType ); + } + + prev = current; + current = dataTypes.shift(); + + if ( current ) { + + // There's only work to do if current dataType is non-auto + if ( current === "*" ) { + + current = prev; + + // Convert response if prev dataType is non-auto and differs from current + } else if ( prev !== "*" && prev !== current ) { + + // Seek a direct converter + conv = converters[ prev + " " + current ] || converters[ "* " + current ]; + + // If none found, seek a pair + if ( !conv ) { + for ( conv2 in converters ) { + + // If conv2 outputs current + tmp = conv2.split( " " ); + if ( tmp[ 1 ] === current ) { + + // If prev can be converted to accepted input + conv = converters[ prev + " " + tmp[ 0 ] ] || + converters[ "* " + tmp[ 0 ] ]; + if ( conv ) { + + // Condense equivalence converters + if ( conv === true ) { + conv = converters[ conv2 ]; + + // Otherwise, insert the intermediate dataType + } else if ( converters[ conv2 ] !== true ) { + current = tmp[ 0 ]; + dataTypes.unshift( tmp[ 1 ] ); + } + break; + } + } + } + } + + // Apply converter (if not an equivalence) + if ( conv !== true ) { + + // Unless errors are allowed to bubble, catch and return them + if ( conv && s.throws ) { + response = conv( response ); + } else { + try { + response = conv( response ); + } catch ( e ) { + return { + state: "parsererror", + error: conv ? e : "No conversion from " + prev + " to " + current + }; + } + } + } + } + } + } + + return { state: "success", data: response }; +} + +jQuery.extend( { + + // Counter for holding the number of active queries + active: 0, + + // Last-Modified header cache for next request + lastModified: {}, + etag: {}, + + ajaxSettings: { + url: location.href, + type: "GET", + isLocal: rlocalProtocol.test( location.protocol ), + global: true, + processData: true, + async: true, + contentType: "application/x-www-form-urlencoded; charset=UTF-8", + + /* + timeout: 0, + data: null, + dataType: null, + username: null, + password: null, + cache: null, + throws: false, + traditional: false, + headers: {}, + */ + + accepts: { + "*": allTypes, + text: "text/plain", + html: "text/html", + xml: "application/xml, text/xml", + json: "application/json, text/javascript" + }, + + contents: { + xml: /\bxml\b/, + html: /\bhtml/, + json: /\bjson\b/ + }, + + responseFields: { + xml: "responseXML", + text: "responseText", + json: "responseJSON" + }, + + // Data converters + // Keys separate source (or catchall "*") and destination types with a single space + converters: { + + // Convert anything to text + "* text": String, + + // Text to html (true = no transformation) + "text html": true, + + // Evaluate text as a json expression + "text json": JSON.parse, + + // Parse text as xml + "text xml": jQuery.parseXML + }, + + // For options that shouldn't be deep extended: + // you can add your own custom options here if + // and when you create one that shouldn't be + // deep extended (see ajaxExtend) + flatOptions: { + url: true, + context: true + } + }, + + // Creates a full fledged settings object into target + // with both ajaxSettings and settings fields. + // If target is omitted, writes into ajaxSettings. + ajaxSetup: function( target, settings ) { + return settings ? + + // Building a settings object + ajaxExtend( ajaxExtend( target, jQuery.ajaxSettings ), settings ) : + + // Extending ajaxSettings + ajaxExtend( jQuery.ajaxSettings, target ); + }, + + ajaxPrefilter: addToPrefiltersOrTransports( prefilters ), + ajaxTransport: addToPrefiltersOrTransports( transports ), + + // Main method + ajax: function( url, options ) { + + // If url is an object, simulate pre-1.5 signature + if ( typeof url === "object" ) { + options = url; + url = undefined; + } + + // Force options to be an object + options = options || {}; + + var transport, + + // URL without anti-cache param + cacheURL, + + // Response headers + responseHeadersString, + responseHeaders, + + // timeout handle + timeoutTimer, + + // Url cleanup var + urlAnchor, + + // Request state (becomes false upon send and true upon completion) + completed, + + // To know if global events are to be dispatched + fireGlobals, + + // Loop variable + i, + + // uncached part of the url + uncached, + + // Create the final options object + s = jQuery.ajaxSetup( {}, options ), + + // Callbacks context + callbackContext = s.context || s, + + // Context for global events is callbackContext if it is a DOM node or jQuery collection + globalEventContext = s.context && + ( callbackContext.nodeType || callbackContext.jquery ) ? + jQuery( callbackContext ) : + jQuery.event, + + // Deferreds + deferred = jQuery.Deferred(), + completeDeferred = jQuery.Callbacks( "once memory" ), + + // Status-dependent callbacks + statusCode = s.statusCode || {}, + + // Headers (they are sent all at once) + requestHeaders = {}, + requestHeadersNames = {}, + + // Default abort message + strAbort = "canceled", + + // Fake xhr + jqXHR = { + readyState: 0, + + // Builds headers hashtable if needed + getResponseHeader: function( key ) { + var match; + if ( completed ) { + if ( !responseHeaders ) { + responseHeaders = {}; + while ( ( match = rheaders.exec( responseHeadersString ) ) ) { + responseHeaders[ match[ 1 ].toLowerCase() + " " ] = + ( responseHeaders[ match[ 1 ].toLowerCase() + " " ] || [] ) + .concat( match[ 2 ] ); + } + } + match = responseHeaders[ key.toLowerCase() + " " ]; + } + return match == null ? null : match.join( ", " ); + }, + + // Raw string + getAllResponseHeaders: function() { + return completed ? responseHeadersString : null; + }, + + // Caches the header + setRequestHeader: function( name, value ) { + if ( completed == null ) { + name = requestHeadersNames[ name.toLowerCase() ] = + requestHeadersNames[ name.toLowerCase() ] || name; + requestHeaders[ name ] = value; + } + return this; + }, + + // Overrides response content-type header + overrideMimeType: function( type ) { + if ( completed == null ) { + s.mimeType = type; + } + return this; + }, + + // Status-dependent callbacks + statusCode: function( map ) { + var code; + if ( map ) { + if ( completed ) { + + // Execute the appropriate callbacks + jqXHR.always( map[ jqXHR.status ] ); + } else { + + // Lazy-add the new callbacks in a way that preserves old ones + for ( code in map ) { + statusCode[ code ] = [ statusCode[ code ], map[ code ] ]; + } + } + } + return this; + }, + + // Cancel the request + abort: function( statusText ) { + var finalText = statusText || strAbort; + if ( transport ) { + transport.abort( finalText ); + } + done( 0, finalText ); + return this; + } + }; + + // Attach deferreds + deferred.promise( jqXHR ); + + // Add protocol if not provided (prefilters might expect it) + // Handle falsy url in the settings object (#10093: consistency with old signature) + // We also use the url parameter if available + s.url = ( ( url || s.url || location.href ) + "" ) + .replace( rprotocol, location.protocol + "//" ); + + // Alias method option to type as per ticket #12004 + s.type = options.method || options.type || s.method || s.type; + + // Extract dataTypes list + s.dataTypes = ( s.dataType || "*" ).toLowerCase().match( rnothtmlwhite ) || [ "" ]; + + // A cross-domain request is in order when the origin doesn't match the current origin. + if ( s.crossDomain == null ) { + urlAnchor = document.createElement( "a" ); + + // Support: IE <=8 - 11, Edge 12 - 15 + // IE throws exception on accessing the href property if url is malformed, + // e.g. http://example.com:80x/ + try { + urlAnchor.href = s.url; + + // Support: IE <=8 - 11 only + // Anchor's host property isn't correctly set when s.url is relative + urlAnchor.href = urlAnchor.href; + s.crossDomain = originAnchor.protocol + "//" + originAnchor.host !== + urlAnchor.protocol + "//" + urlAnchor.host; + } catch ( e ) { + + // If there is an error parsing the URL, assume it is crossDomain, + // it can be rejected by the transport if it is invalid + s.crossDomain = true; + } + } + + // Convert data if not already a string + if ( s.data && s.processData && typeof s.data !== "string" ) { + s.data = jQuery.param( s.data, s.traditional ); + } + + // Apply prefilters + inspectPrefiltersOrTransports( prefilters, s, options, jqXHR ); + + // If request was aborted inside a prefilter, stop there + if ( completed ) { + return jqXHR; + } + + // We can fire global events as of now if asked to + // Don't fire events if jQuery.event is undefined in an AMD-usage scenario (#15118) + fireGlobals = jQuery.event && s.global; + + // Watch for a new set of requests + if ( fireGlobals && jQuery.active++ === 0 ) { + jQuery.event.trigger( "ajaxStart" ); + } + + // Uppercase the type + s.type = s.type.toUpperCase(); + + // Determine if request has content + s.hasContent = !rnoContent.test( s.type ); + + // Save the URL in case we're toying with the If-Modified-Since + // and/or If-None-Match header later on + // Remove hash to simplify url manipulation + cacheURL = s.url.replace( rhash, "" ); + + // More options handling for requests with no content + if ( !s.hasContent ) { + + // Remember the hash so we can put it back + uncached = s.url.slice( cacheURL.length ); + + // If data is available and should be processed, append data to url + if ( s.data && ( s.processData || typeof s.data === "string" ) ) { + cacheURL += ( rquery.test( cacheURL ) ? "&" : "?" ) + s.data; + + // #9682: remove data so that it's not used in an eventual retry + delete s.data; + } + + // Add or update anti-cache param if needed + if ( s.cache === false ) { + cacheURL = cacheURL.replace( rantiCache, "$1" ); + uncached = ( rquery.test( cacheURL ) ? "&" : "?" ) + "_=" + ( nonce.guid++ ) + + uncached; + } + + // Put hash and anti-cache on the URL that will be requested (gh-1732) + s.url = cacheURL + uncached; + + // Change '%20' to '+' if this is encoded form body content (gh-2658) + } else if ( s.data && s.processData && + ( s.contentType || "" ).indexOf( "application/x-www-form-urlencoded" ) === 0 ) { + s.data = s.data.replace( r20, "+" ); + } + + // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode. + if ( s.ifModified ) { + if ( jQuery.lastModified[ cacheURL ] ) { + jqXHR.setRequestHeader( "If-Modified-Since", jQuery.lastModified[ cacheURL ] ); + } + if ( jQuery.etag[ cacheURL ] ) { + jqXHR.setRequestHeader( "If-None-Match", jQuery.etag[ cacheURL ] ); + } + } + + // Set the correct header, if data is being sent + if ( s.data && s.hasContent && s.contentType !== false || options.contentType ) { + jqXHR.setRequestHeader( "Content-Type", s.contentType ); + } + + // Set the Accepts header for the server, depending on the dataType + jqXHR.setRequestHeader( + "Accept", + s.dataTypes[ 0 ] && s.accepts[ s.dataTypes[ 0 ] ] ? + s.accepts[ s.dataTypes[ 0 ] ] + + ( s.dataTypes[ 0 ] !== "*" ? ", " + allTypes + "; q=0.01" : "" ) : + s.accepts[ "*" ] + ); + + // Check for headers option + for ( i in s.headers ) { + jqXHR.setRequestHeader( i, s.headers[ i ] ); + } + + // Allow custom headers/mimetypes and early abort + if ( s.beforeSend && + ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || completed ) ) { + + // Abort if not done already and return + return jqXHR.abort(); + } + + // Aborting is no longer a cancellation + strAbort = "abort"; + + // Install callbacks on deferreds + completeDeferred.add( s.complete ); + jqXHR.done( s.success ); + jqXHR.fail( s.error ); + + // Get transport + transport = inspectPrefiltersOrTransports( transports, s, options, jqXHR ); + + // If no transport, we auto-abort + if ( !transport ) { + done( -1, "No Transport" ); + } else { + jqXHR.readyState = 1; + + // Send global event + if ( fireGlobals ) { + globalEventContext.trigger( "ajaxSend", [ jqXHR, s ] ); + } + + // If request was aborted inside ajaxSend, stop there + if ( completed ) { + return jqXHR; + } + + // Timeout + if ( s.async && s.timeout > 0 ) { + timeoutTimer = window.setTimeout( function() { + jqXHR.abort( "timeout" ); + }, s.timeout ); + } + + try { + completed = false; + transport.send( requestHeaders, done ); + } catch ( e ) { + + // Rethrow post-completion exceptions + if ( completed ) { + throw e; + } + + // Propagate others as results + done( -1, e ); + } + } + + // Callback for when everything is done + function done( status, nativeStatusText, responses, headers ) { + var isSuccess, success, error, response, modified, + statusText = nativeStatusText; + + // Ignore repeat invocations + if ( completed ) { + return; + } + + completed = true; + + // Clear timeout if it exists + if ( timeoutTimer ) { + window.clearTimeout( timeoutTimer ); + } + + // Dereference transport for early garbage collection + // (no matter how long the jqXHR object will be used) + transport = undefined; + + // Cache response headers + responseHeadersString = headers || ""; + + // Set readyState + jqXHR.readyState = status > 0 ? 4 : 0; + + // Determine if successful + isSuccess = status >= 200 && status < 300 || status === 304; + + // Get response data + if ( responses ) { + response = ajaxHandleResponses( s, jqXHR, responses ); + } + + // Use a noop converter for missing script + if ( !isSuccess && jQuery.inArray( "script", s.dataTypes ) > -1 ) { + s.converters[ "text script" ] = function() {}; + } + + // Convert no matter what (that way responseXXX fields are always set) + response = ajaxConvert( s, response, jqXHR, isSuccess ); + + // If successful, handle type chaining + if ( isSuccess ) { + + // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode. + if ( s.ifModified ) { + modified = jqXHR.getResponseHeader( "Last-Modified" ); + if ( modified ) { + jQuery.lastModified[ cacheURL ] = modified; + } + modified = jqXHR.getResponseHeader( "etag" ); + if ( modified ) { + jQuery.etag[ cacheURL ] = modified; + } + } + + // if no content + if ( status === 204 || s.type === "HEAD" ) { + statusText = "nocontent"; + + // if not modified + } else if ( status === 304 ) { + statusText = "notmodified"; + + // If we have data, let's convert it + } else { + statusText = response.state; + success = response.data; + error = response.error; + isSuccess = !error; + } + } else { + + // Extract error from statusText and normalize for non-aborts + error = statusText; + if ( status || !statusText ) { + statusText = "error"; + if ( status < 0 ) { + status = 0; + } + } + } + + // Set data for the fake xhr object + jqXHR.status = status; + jqXHR.statusText = ( nativeStatusText || statusText ) + ""; + + // Success/Error + if ( isSuccess ) { + deferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] ); + } else { + deferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] ); + } + + // Status-dependent callbacks + jqXHR.statusCode( statusCode ); + statusCode = undefined; + + if ( fireGlobals ) { + globalEventContext.trigger( isSuccess ? "ajaxSuccess" : "ajaxError", + [ jqXHR, s, isSuccess ? success : error ] ); + } + + // Complete + completeDeferred.fireWith( callbackContext, [ jqXHR, statusText ] ); + + if ( fireGlobals ) { + globalEventContext.trigger( "ajaxComplete", [ jqXHR, s ] ); + + // Handle the global AJAX counter + if ( !( --jQuery.active ) ) { + jQuery.event.trigger( "ajaxStop" ); + } + } + } + + return jqXHR; + }, + + getJSON: function( url, data, callback ) { + return jQuery.get( url, data, callback, "json" ); + }, + + getScript: function( url, callback ) { + return jQuery.get( url, undefined, callback, "script" ); + } +} ); + +jQuery.each( [ "get", "post" ], function( _i, method ) { + jQuery[ method ] = function( url, data, callback, type ) { + + // Shift arguments if data argument was omitted + if ( isFunction( data ) ) { + type = type || callback; + callback = data; + data = undefined; + } + + // The url can be an options object (which then must have .url) + return jQuery.ajax( jQuery.extend( { + url: url, + type: method, + dataType: type, + data: data, + success: callback + }, jQuery.isPlainObject( url ) && url ) ); + }; +} ); + +jQuery.ajaxPrefilter( function( s ) { + var i; + for ( i in s.headers ) { + if ( i.toLowerCase() === "content-type" ) { + s.contentType = s.headers[ i ] || ""; + } + } +} ); + + +jQuery._evalUrl = function( url, options, doc ) { + return jQuery.ajax( { + url: url, + + // Make this explicit, since user can override this through ajaxSetup (#11264) + type: "GET", + dataType: "script", + cache: true, + async: false, + global: false, + + // Only evaluate the response if it is successful (gh-4126) + // dataFilter is not invoked for failure responses, so using it instead + // of the default converter is kludgy but it works. + converters: { + "text script": function() {} + }, + dataFilter: function( response ) { + jQuery.globalEval( response, options, doc ); + } + } ); +}; + + +jQuery.fn.extend( { + wrapAll: function( html ) { + var wrap; + + if ( this[ 0 ] ) { + if ( isFunction( html ) ) { + html = html.call( this[ 0 ] ); + } + + // The elements to wrap the target around + wrap = jQuery( html, this[ 0 ].ownerDocument ).eq( 0 ).clone( true ); + + if ( this[ 0 ].parentNode ) { + wrap.insertBefore( this[ 0 ] ); + } + + wrap.map( function() { + var elem = this; + + while ( elem.firstElementChild ) { + elem = elem.firstElementChild; + } + + return elem; + } ).append( this ); + } + + return this; + }, + + wrapInner: function( html ) { + if ( isFunction( html ) ) { + return this.each( function( i ) { + jQuery( this ).wrapInner( html.call( this, i ) ); + } ); + } + + return this.each( function() { + var self = jQuery( this ), + contents = self.contents(); + + if ( contents.length ) { + contents.wrapAll( html ); + + } else { + self.append( html ); + } + } ); + }, + + wrap: function( html ) { + var htmlIsFunction = isFunction( html ); + + return this.each( function( i ) { + jQuery( this ).wrapAll( htmlIsFunction ? html.call( this, i ) : html ); + } ); + }, + + unwrap: function( selector ) { + this.parent( selector ).not( "body" ).each( function() { + jQuery( this ).replaceWith( this.childNodes ); + } ); + return this; + } +} ); + + +jQuery.expr.pseudos.hidden = function( elem ) { + return !jQuery.expr.pseudos.visible( elem ); +}; +jQuery.expr.pseudos.visible = function( elem ) { + return !!( elem.offsetWidth || elem.offsetHeight || elem.getClientRects().length ); +}; + + + + +jQuery.ajaxSettings.xhr = function() { + try { + return new window.XMLHttpRequest(); + } catch ( e ) {} +}; + +var xhrSuccessStatus = { + + // File protocol always yields status code 0, assume 200 + 0: 200, + + // Support: IE <=9 only + // #1450: sometimes IE returns 1223 when it should be 204 + 1223: 204 + }, + xhrSupported = jQuery.ajaxSettings.xhr(); + +support.cors = !!xhrSupported && ( "withCredentials" in xhrSupported ); +support.ajax = xhrSupported = !!xhrSupported; + +jQuery.ajaxTransport( function( options ) { + var callback, errorCallback; + + // Cross domain only allowed if supported through XMLHttpRequest + if ( support.cors || xhrSupported && !options.crossDomain ) { + return { + send: function( headers, complete ) { + var i, + xhr = options.xhr(); + + xhr.open( + options.type, + options.url, + options.async, + options.username, + options.password + ); + + // Apply custom fields if provided + if ( options.xhrFields ) { + for ( i in options.xhrFields ) { + xhr[ i ] = options.xhrFields[ i ]; + } + } + + // Override mime type if needed + if ( options.mimeType && xhr.overrideMimeType ) { + xhr.overrideMimeType( options.mimeType ); + } + + // X-Requested-With header + // For cross-domain requests, seeing as conditions for a preflight are + // akin to a jigsaw puzzle, we simply never set it to be sure. + // (it can always be set on a per-request basis or even using ajaxSetup) + // For same-domain requests, won't change header if already provided. + if ( !options.crossDomain && !headers[ "X-Requested-With" ] ) { + headers[ "X-Requested-With" ] = "XMLHttpRequest"; + } + + // Set headers + for ( i in headers ) { + xhr.setRequestHeader( i, headers[ i ] ); + } + + // Callback + callback = function( type ) { + return function() { + if ( callback ) { + callback = errorCallback = xhr.onload = + xhr.onerror = xhr.onabort = xhr.ontimeout = + xhr.onreadystatechange = null; + + if ( type === "abort" ) { + xhr.abort(); + } else if ( type === "error" ) { + + // Support: IE <=9 only + // On a manual native abort, IE9 throws + // errors on any property access that is not readyState + if ( typeof xhr.status !== "number" ) { + complete( 0, "error" ); + } else { + complete( + + // File: protocol always yields status 0; see #8605, #14207 + xhr.status, + xhr.statusText + ); + } + } else { + complete( + xhrSuccessStatus[ xhr.status ] || xhr.status, + xhr.statusText, + + // Support: IE <=9 only + // IE9 has no XHR2 but throws on binary (trac-11426) + // For XHR2 non-text, let the caller handle it (gh-2498) + ( xhr.responseType || "text" ) !== "text" || + typeof xhr.responseText !== "string" ? + { binary: xhr.response } : + { text: xhr.responseText }, + xhr.getAllResponseHeaders() + ); + } + } + }; + }; + + // Listen to events + xhr.onload = callback(); + errorCallback = xhr.onerror = xhr.ontimeout = callback( "error" ); + + // Support: IE 9 only + // Use onreadystatechange to replace onabort + // to handle uncaught aborts + if ( xhr.onabort !== undefined ) { + xhr.onabort = errorCallback; + } else { + xhr.onreadystatechange = function() { + + // Check readyState before timeout as it changes + if ( xhr.readyState === 4 ) { + + // Allow onerror to be called first, + // but that will not handle a native abort + // Also, save errorCallback to a variable + // as xhr.onerror cannot be accessed + window.setTimeout( function() { + if ( callback ) { + errorCallback(); + } + } ); + } + }; + } + + // Create the abort callback + callback = callback( "abort" ); + + try { + + // Do send the request (this may raise an exception) + xhr.send( options.hasContent && options.data || null ); + } catch ( e ) { + + // #14683: Only rethrow if this hasn't been notified as an error yet + if ( callback ) { + throw e; + } + } + }, + + abort: function() { + if ( callback ) { + callback(); + } + } + }; + } +} ); + + + + +// Prevent auto-execution of scripts when no explicit dataType was provided (See gh-2432) +jQuery.ajaxPrefilter( function( s ) { + if ( s.crossDomain ) { + s.contents.script = false; + } +} ); + +// Install script dataType +jQuery.ajaxSetup( { + accepts: { + script: "text/javascript, application/javascript, " + + "application/ecmascript, application/x-ecmascript" + }, + contents: { + script: /\b(?:java|ecma)script\b/ + }, + converters: { + "text script": function( text ) { + jQuery.globalEval( text ); + return text; + } + } +} ); + +// Handle cache's special case and crossDomain +jQuery.ajaxPrefilter( "script", function( s ) { + if ( s.cache === undefined ) { + s.cache = false; + } + if ( s.crossDomain ) { + s.type = "GET"; + } +} ); + +// Bind script tag hack transport +jQuery.ajaxTransport( "script", function( s ) { + + // This transport only deals with cross domain or forced-by-attrs requests + if ( s.crossDomain || s.scriptAttrs ) { + var script, callback; + return { + send: function( _, complete ) { + script = jQuery( " + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + + + +
+ +
+ +
+

cassandra - Exceptions and Enums

+
+
+cassandra.__version_info__
+

The version of the driver in a tuple format

+
+ +
+
+cassandra.__version__
+

The version of the driver in a string format

+
+ +
+
+class cassandra.ConsistencyLevel
+

Spcifies how many replicas must respond for an operation to be considered +a success. By default, ONE is used for all operations.

+
+
+ANY = 0
+

Only requires that one replica receives the write or the coordinator +stores a hint to replay later. Valid only for writes.

+
+ +
+
+ONE = 1
+

Only one replica needs to respond to consider the operation a success

+
+ +
+
+TWO = 2
+

Two replicas must respond to consider the operation a success

+
+ +
+
+THREE = 3
+

Three replicas must respond to consider the operation a success

+
+ +
+
+QUORUM = 4
+

ceil(RF/2) + 1 replicas must respond to consider the operation a success

+
+ +
+
+ALL = 5
+

All replicas must respond to consider the operation a success

+
+ +
+
+LOCAL_QUORUM = 6
+

Requires a quorum of replicas in the local datacenter

+
+ +
+
+EACH_QUORUM = 7
+

Requires a quorum of replicas in each datacenter

+
+ +
+
+SERIAL = 8
+

For conditional inserts/updates that utilize Cassandra’s lightweight +transactions, this requires consensus among all replicas for the +modified data.

+
+ +
+
+LOCAL_SERIAL = 9
+

Like SERIAL, but only requires consensus +among replicas in the local datacenter.

+
+ +
+
+LOCAL_ONE = 10
+

Sends a request only to replicas in the local datacenter and waits for +one response.

+
+ +
+ +
+
+class cassandra.ProtocolVersion
+

Defines native protocol versions supported by this driver.

+
+
+V1 = 1
+

v1, supported in Cassandra 1.2–>2.2

+
+ +
+
+V2 = 2
+

v2, supported in Cassandra 2.0–>2.2; +added support for lightweight transactions, batch operations, and automatic query paging.

+
+ +
+
+V3 = 3
+

v3, supported in Cassandra 2.1–>3.x+; +added support for protocol-level client-side timestamps (see Session.use_client_timestamp), +serial consistency levels for BatchStatement, and an improved connection pool.

+
+ +
+
+V4 = 4
+

v4, supported in Cassandra 2.2–>3.x+; +added a number of new types, server warnings, new failure messages, and custom payloads. Details in the +project docs

+
+ +
+
+V5 = 5
+

v5, in beta from 3.x+. Finalised in 4.0-beta5

+
+ +
+
+V6 = 6
+

v6, in beta from 4.0-beta5

+
+ +
+
+DSE_V1 = 65
+

DSE private protocol v1, supported in DSE 5.1+

+
+ +
+
+DSE_V2 = 66
+

DSE private protocol v2, supported in DSE 6.0+

+
+ +
+
+SUPPORTED_VERSIONS = (66, 65, 6, 5, 4, 3, 2, 1)
+

A tuple of all supported protocol versions

+
+ +
+
+BETA_VERSIONS = (6,)
+

A tuple of all beta protocol versions

+
+ +
+
+MIN_SUPPORTED = 1
+

Minimum protocol version supported by this driver.

+
+ +
+
+MAX_SUPPORTED = 66
+

Maximum protocol version supported by this driver.

+
+ +
+
+classmethod get_lower_supported(previous_version)
+

Return the lower supported protocol version. Beta versions are omitted.

+
+ +
+ +
+
+class cassandra.UserFunctionDescriptor(name, argument_types)
+

Describes a User function by name and argument signature

+
+
+name = None
+

name of the function

+
+ +
+
+argument_types = None
+

Ordered list of CQL argument type names comprising the type signature

+
+ +
+
+property signature
+

function signature string in the form ‘name([type0[,type1[…]]])’

+

can be used to uniquely identify overloaded function names within a keyspace

+
+ +
+ +
+
+class cassandra.UserAggregateDescriptor(name, argument_types)
+

Describes a User aggregate function by name and argument signature

+
+
+name = None
+

name of the aggregate

+
+ +
+
+argument_types = None
+

Ordered list of CQL argument type names comprising the type signature

+
+ +
+
+property signature
+

function signature string in the form ‘name([type0[,type1[…]]])’

+

can be used to uniquely identify overloaded function names within a keyspace

+
+ +
+ +
+
+exception cassandra.DriverException
+

Base for all exceptions explicitly raised by the driver.

+
+ +
+
+exception cassandra.RequestExecutionException
+

Base for request execution exceptions returned from the server.

+
+ +
+
+exception cassandra.Unavailable
+

There were not enough live replicas to satisfy the requested consistency +level, so the coordinator node immediately failed the request without +forwarding it to any replicas.

+
+
+consistency = None
+

The requested ConsistencyLevel

+
+ +
+
+required_replicas = None
+

The number of replicas that needed to be live to complete the operation

+
+ +
+
+alive_replicas = None
+

The number of replicas that were actually alive

+
+ +
+ +
+
+exception cassandra.Timeout
+

Replicas failed to respond to the coordinator node before timing out.

+
+
+consistency = None
+

The requested ConsistencyLevel

+
+ +
+
+required_responses = None
+

The number of required replica responses

+
+ +
+
+received_responses = None
+

The number of replicas that responded before the coordinator timed out +the operation

+
+ +
+ +
+
+exception cassandra.ReadTimeout
+

A subclass of Timeout for read operations.

+

This indicates that the replicas failed to respond to the coordinator +node before the configured timeout. This timeout is configured in +cassandra.yaml with the read_request_timeout_in_ms +and range_request_timeout_in_ms options.

+
+
+data_retrieved = None
+

A boolean indicating whether the requested data was retrieved +by the coordinator from any replicas before it timed out the +operation

+
+ +
+ +
+
+exception cassandra.WriteTimeout
+

A subclass of Timeout for write operations.

+

This indicates that the replicas failed to respond to the coordinator +node before the configured timeout. This timeout is configured in +cassandra.yaml with the write_request_timeout_in_ms +option.

+
+
+write_type = None
+

The type of write operation, enum on WriteType

+
+ +
+ +
+
+exception cassandra.CoordinationFailure
+

Replicas sent a failure to the coordinator.

+
+
+consistency = None
+

The requested ConsistencyLevel

+
+ +
+
+required_responses = None
+

The number of required replica responses

+
+ +
+
+received_responses = None
+

The number of replicas that responded before the coordinator timed out +the operation

+
+ +
+
+failures = None
+

The number of replicas that sent a failure message

+
+ +
+
+error_code_map = None
+

A map of inet addresses to error codes representing replicas that sent +a failure message. Only set when protocol_version is 5 or higher.

+
+ +
+ +
+
+exception cassandra.ReadFailure
+

A subclass of CoordinationFailure for read operations.

+

This indicates that the replicas sent a failure message to the coordinator.

+
+
+data_retrieved = None
+

A boolean indicating whether the requested data was retrieved +by the coordinator from any replicas before it timed out the +operation

+
+ +
+ +
+
+exception cassandra.WriteFailure
+

A subclass of CoordinationFailure for write operations.

+

This indicates that the replicas sent a failure message to the coordinator.

+
+
+write_type = None
+

The type of write operation, enum on WriteType

+
+ +
+ +
+
+exception cassandra.FunctionFailure
+

User Defined Function failed during execution

+
+
+keyspace = None
+

Keyspace of the function

+
+ +
+
+function = None
+

Name of the function

+
+ +
+
+arg_types = None
+

List of argument type names of the function

+
+ +
+ +
+
+exception cassandra.RequestValidationException
+

Server request validation failed

+
+ +
+
+exception cassandra.ConfigurationException
+

Server indicated request errro due to current configuration

+
+ +
+
+exception cassandra.AlreadyExists
+

An attempt was made to create a keyspace or table that already exists.

+
+
+keyspace = None
+

The name of the keyspace that already exists, or, if an attempt was +made to create a new table, the keyspace that the table is in.

+
+ +
+
+table = None
+

The name of the table that already exists, or, if an attempt was +make to create a keyspace, None.

+
+ +
+ +
+
+exception cassandra.InvalidRequest
+

A query was made that was invalid for some reason, such as trying to set +the keyspace for a connection to a nonexistent keyspace.

+
+ +
+
+exception cassandra.Unauthorized
+

The current user is not authorized to perform the requested operation.

+
+ +
+
+exception cassandra.AuthenticationFailed
+

Failed to authenticate.

+
+ +
+
+exception cassandra.OperationTimedOut
+

The operation took longer than the specified (client-side) timeout +to complete. This is not an error generated by Cassandra, only +the driver.

+
+
+errors = None
+

A dict of errors keyed by the Host against which they occurred.

+
+ +
+
+last_host = None
+

The last Host this operation was attempted against.

+
+ +
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/stable/api/cassandra/auth.html b/stable/api/cassandra/auth.html new file mode 100644 index 0000000000..e39e858ff0 --- /dev/null +++ b/stable/api/cassandra/auth.html @@ -0,0 +1,797 @@ + + + + + + + + + + + + + cassandra.auth - Authentication | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + + + +
+ +
+ +
+

cassandra.auth - Authentication

+
+
+class cassandra.auth.AuthProvider
+

An abstract class that defines the interface that will be used for +creating Authenticator instances when opening new +connections to Cassandra.

+
+

New in version 2.0.0.

+
+
+
+new_authenticator(host)
+

Implementations of this class should return a new instance +of Authenticator or one of its subclasses.

+
+ +
+ +
+
+class cassandra.auth.Authenticator
+

An abstract class that handles SASL authentication with Cassandra servers.

+

Each time a new connection is created and the server requires authentication, +a new instance of this class will be created by the corresponding +AuthProvider to handler that authentication. The lifecycle of the +new Authenticator will the be:

+

1) The initial_response() method will be called. The return +value will be sent to the server to initiate the handshake.

+

2) The server will respond to each client response by either issuing a +challenge or indicating that the authentication is complete (successful or not). +If a new challenge is issued, evaluate_challenge() +will be called to produce a response that will be sent to the +server. This challenge/response negotiation will continue until the server +responds that authentication is successful (or an AuthenticationFailed +is raised).

+

3) When the server indicates that authentication is successful, +on_authentication_success() will be called a token string that +that the server may optionally have sent.

+

The exact nature of the negotiation between the client and server is specific +to the authentication mechanism configured server-side.

+
+

New in version 2.0.0.

+
+
+
+server_authenticator_class = None
+

Set during the connection AUTHENTICATE phase

+
+ +
+
+initial_response()
+

Returns an message to send to the server to initiate the SASL handshake. +None may be returned to send an empty message.

+
+ +
+
+evaluate_challenge(challenge)
+

Called when the server sends a challenge message. Generally, this method +should return None when authentication is complete from a +client perspective. Otherwise, a string should be returned.

+
+ +
+
+on_authentication_success(token)
+

Called when the server indicates that authentication was successful. +Depending on the authentication mechanism, token may be None +or a string.

+
+ +
+ +
+
+class cassandra.auth.PlainTextAuthProvider(username, password)
+

An AuthProvider that works with Cassandra’s PasswordAuthenticator.

+

Example usage:

+
from cassandra.cluster import Cluster
+from cassandra.auth import PlainTextAuthProvider
+
+auth_provider = PlainTextAuthProvider(
+        username='cassandra', password='cassandra')
+cluster = Cluster(auth_provider=auth_provider)
+
+
+
+

New in version 2.0.0.

+
+
+
+new_authenticator(host)
+

Implementations of this class should return a new instance +of Authenticator or one of its subclasses.

+
+ +
+ +
+
+class cassandra.auth.PlainTextAuthenticator(username, password)
+
+
+evaluate_challenge(challenge)
+

Called when the server sends a challenge message. Generally, this method +should return None when authentication is complete from a +client perspective. Otherwise, a string should be returned.

+
+ +
+ +
+
+class cassandra.auth.SaslAuthProvider(**sasl_kwargs)
+

An AuthProvider supporting general SASL auth mechanisms

+

Suitable for GSSAPI or other SASL mechanisms

+

Example usage:

+
from cassandra.cluster import Cluster
+from cassandra.auth import SaslAuthProvider
+
+sasl_kwargs = {'service': 'something',
+               'mechanism': 'GSSAPI',
+               'qops': 'auth'.split(',')}
+auth_provider = SaslAuthProvider(**sasl_kwargs)
+cluster = Cluster(auth_provider=auth_provider)
+
+
+
+

New in version 2.1.4.

+
+
+
+new_authenticator(host)
+

Implementations of this class should return a new instance +of Authenticator or one of its subclasses.

+
+ +
+ +
+
+class cassandra.auth.SaslAuthenticator(host, service, mechanism='GSSAPI', **sasl_kwargs)
+

A pass-through Authenticator using the third party package +‘pure-sasl’ for authentication

+
+

New in version 2.1.4.

+
+
+
+initial_response()
+

Returns an message to send to the server to initiate the SASL handshake. +None may be returned to send an empty message.

+
+ +
+
+evaluate_challenge(challenge)
+

Called when the server sends a challenge message. Generally, this method +should return None when authentication is complete from a +client perspective. Otherwise, a string should be returned.

+
+ +
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/stable/api/cassandra/cluster.html b/stable/api/cassandra/cluster.html new file mode 100644 index 0000000000..143bdd4cbd --- /dev/null +++ b/stable/api/cassandra/cluster.html @@ -0,0 +1,1769 @@ + + + + + + + + + + + + + cassandra.cluster - Clusters and Sessions | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + + + +
+ +
+ +
+

cassandra.cluster - Clusters and Sessions

+
+
+class cassandra.cluster.Cluster([contact_points=('127.0.0.1',)][, port=9042][, executor_threads=2], **attr_kwargs)
+

The main class to use when interacting with a Cassandra cluster. +Typically, one instance of this class will be created for each +separate Cassandra cluster that your application interacts with.

+

Example usage:

+
>>> from cassandra.cluster import Cluster
+>>> cluster = Cluster(['192.168.1.1', '192.168.1.2'])
+>>> session = cluster.connect()
+>>> session.execute("CREATE KEYSPACE ...")
+>>> ...
+>>> cluster.shutdown()
+
+
+

Cluster and Session also provide context management functions +which implicitly handle shutdown when leaving scope.

+

executor_threads defines the number of threads in a pool for handling asynchronous tasks such as +extablishing connection pools or refreshing metadata.

+

Any of the mutable Cluster attributes may be set as keyword arguments to the constructor.

+
+
+contact_points = ['127.0.0.1']
+
+ +
+
+port = 9042
+
+ +
+
+cql_version = None
+
+ +
+
+protocol_version = 66
+
+ +
+
+compression = True
+
+ +
+
+auth_provider
+

When protocol_version is 2 or higher, this should +be an instance of a subclass of AuthProvider, +such as PlainTextAuthProvider.

+

When protocol_version is 1, this should be +a function that accepts one argument, the IP address of a node, +and returns a dict of credentials for that node.

+

When not using authentication, this should be left as None.

+
+ +
+
+load_balancing_policy
+

An instance of policies.LoadBalancingPolicy or +one of its subclasses.

+
+

Changed in version 2.6.0.

+
+

Defaults to TokenAwarePolicy (DCAwareRoundRobinPolicy). +when using CPython (where the murmur3 extension is available). DCAwareRoundRobinPolicy +otherwise. Default local DC will be chosen from contact points.

+

Please see DCAwareRoundRobinPolicy for a discussion on default behavior with respect to +DC locality and remote nodes.

+
+ +
+
+reconnection_policy = <cassandra.policies.ExponentialReconnectionPolicy object>
+
+ +
+
+default_retry_policy = <cassandra.policies.RetryPolicy object>
+

A default policies.RetryPolicy instance to use for all +Statement objects which do not have a retry_policy +explicitly set.

+
+ +
+
+conviction_policy_factory = <class 'cassandra.policies.SimpleConvictionPolicy'>
+
+ +
+
+address_translator = <cassandra.policies.IdentityTranslator object>
+
+ +
+
+metrics_enabled = False
+
+ +
+
+metrics = None
+
+ +
+
+ssl_context = None
+
+ +
+
+ssl_options = None
+
+ +
+
+sockopts = None
+
+ +
+
+max_schema_agreement_wait = 10
+
+ +
+
+metadata = None
+
+ +
+
+connection_class = <class 'cassandra.io.libevreactor.LibevConnection'>
+
+ +
+
+control_connection_timeout = 2.0
+
+ +
+
+idle_heartbeat_interval = 30
+
+ +
+
+idle_heartbeat_timeout = 30
+
+ +
+
+schema_event_refresh_window = 2
+
+ +
+
+topology_event_refresh_window = 10
+
+ +
+
+status_event_refresh_window = 2
+
+ +
+
+prepare_on_all_hosts = True
+
+ +
+
+reprepare_on_up = True
+
+ +
+
+connect_timeout = 5
+
+ +
+
+schema_metadata_enabled = True
+

Flag indicating whether internal schema metadata is updated.

+

When disabled, the driver does not populate Cluster.metadata.keyspaces on connect, or on schema change events. This +can be used to speed initial connection, and reduce load on client and server during operation. Turning this off +gives away token aware request routing, and programmatic inspection of the metadata model.

+
+ +
+
+token_metadata_enabled = True
+

Flag indicating whether internal token metadata is updated.

+

When disabled, the driver does not query node token information on connect, or on topology change events. This +can be used to speed initial connection, and reduce load on client and server during operation. It is most useful +in large clusters using vnodes, where the token map can be expensive to compute. Turning this off +gives away token aware request routing, and programmatic inspection of the token ring.

+
+ +
+
+timestamp_generator = None
+
+ +
+
+endpoint_factory = None
+
+ +
+
+cloud = None
+
+ +
+
+connect(keyspace=None, wait_for_all_pools=False)
+

Creates and returns a new Session object.

+

If keyspace is specified, that keyspace will be the default keyspace for +operations on the Session.

+

wait_for_all_pools specifies whether this call should wait for all connection pools to be +established or attempted. Default is False, which means it will return when the first +successful connection is established. Remaining pools are added asynchronously.

+
+ +
+
+shutdown()
+

Closes all sessions and connection associated with this Cluster. +To ensure all connections are properly closed, you should always +call shutdown() on a Cluster instance when you are done with it.

+

Once shutdown, a Cluster should not be used for any purpose.

+
+ +
+
+register_user_type(keyspace, user_type, klass)
+

Registers a class to use to represent a particular user-defined type. +Query parameters for this user-defined type will be assumed to be +instances of klass. Result sets for this user-defined type will +be instances of klass. If no class is registered for a user-defined +type, a namedtuple will be used for result sets, and non-prepared +statements may not encode parameters for this type correctly.

+

keyspace is the name of the keyspace that the UDT is defined in.

+

user_type is the string name of the UDT to register the mapping +for.

+

klass should be a class with attributes whose names match the +fields of the user-defined type. The constructor must accepts kwargs +for each of the fields in the UDT.

+

This method should only be called after the type has been created +within Cassandra.

+

Example:

+
cluster = Cluster(protocol_version=3)
+session = cluster.connect()
+session.set_keyspace('mykeyspace')
+session.execute("CREATE TYPE address (street text, zipcode int)")
+session.execute("CREATE TABLE users (id int PRIMARY KEY, location address)")
+
+# create a class to map to the "address" UDT
+class Address(object):
+
+    def __init__(self, street, zipcode):
+        self.street = street
+        self.zipcode = zipcode
+
+cluster.register_user_type('mykeyspace', 'address', Address)
+
+# insert a row using an instance of Address
+session.execute("INSERT INTO users (id, location) VALUES (%s, %s)",
+                (0, Address("123 Main St.", 78723)))
+
+# results will include Address instances
+results = session.execute("SELECT * FROM users")
+row = results[0]
+print row.id, row.location.street, row.location.zipcode
+
+
+
+ +
+
+register_listener(listener)
+

Adds a cassandra.policies.HostStateListener subclass instance to +the list of listeners to be notified when a host is added, removed, +marked up, or marked down.

+
+ +
+
+unregister_listener(listener)
+

Removes a registered listener.

+
+ +
+
+add_execution_profile(name, profile, pool_wait_timeout=5)
+

Adds an ExecutionProfile to the cluster. This makes it available for use by name in Session.execute() +and Session.execute_async(). This method will raise if the profile already exists.

+

Normally profiles will be injected at cluster initialization via Cluster(execution_profiles). This method +provides a way of adding them dynamically.

+

Adding a new profile updates the connection pools according to the specified load_balancing_policy. By default, +this method will wait up to five seconds for the pool creation to complete, so the profile can be used immediately +upon return. This behavior can be controlled using pool_wait_timeout (see +concurrent.futures.wait +for timeout semantics).

+
+ +
+
+set_max_requests_per_connection(host_distance, max_requests)
+

Sets a threshold for concurrent requests per connection, above which new +connections will be created to a host (up to max connections; +see set_max_connections_per_host()).

+

Pertains to connection pool management in protocol versions {1,2}.

+
+ +
+
+get_max_requests_per_connection(host_distance)
+
+ +
+
+set_min_requests_per_connection(host_distance, min_requests)
+

Sets a threshold for concurrent requests per connection, below which +connections will be considered for disposal (down to core connections; +see set_core_connections_per_host()).

+

Pertains to connection pool management in protocol versions {1,2}.

+
+ +
+
+get_min_requests_per_connection(host_distance)
+
+ +
+
+get_core_connections_per_host(host_distance)
+

Gets the minimum number of connections per Session that will be opened +for each host with HostDistance equal to host_distance. +The default is 2 for LOCAL and 1 for +REMOTE.

+

This property is ignored if protocol_version is +3 or higher.

+
+ +
+
+set_core_connections_per_host(host_distance, core_connections)
+

Sets the minimum number of connections per Session that will be opened +for each host with HostDistance equal to host_distance. +The default is 2 for LOCAL and 1 for +REMOTE.

+

Protocol version 1 and 2 are limited in the number of concurrent +requests they can send per connection. The driver implements connection +pooling to support higher levels of concurrency.

+

If protocol_version is set to 3 or higher, this +is not supported (there is always one connection per host, unless +the host is remote and connect_to_remote_hosts is False) +and using this will result in an UnsupportedOperation.

+
+ +
+
+get_max_connections_per_host(host_distance)
+

Gets the maximum number of connections per Session that will be opened +for each host with HostDistance equal to host_distance. +The default is 8 for LOCAL and 2 for +REMOTE.

+

This property is ignored if protocol_version is +3 or higher.

+
+ +
+
+set_max_connections_per_host(host_distance, max_connections)
+

Sets the maximum number of connections per Session that will be opened +for each host with HostDistance equal to host_distance. +The default is 2 for LOCAL and 1 for +REMOTE.

+

If protocol_version is set to 3 or higher, this +is not supported (there is always one connection per host, unless +the host is remote and connect_to_remote_hosts is False) +and using this will result in an UnsupportedOperation.

+
+ +
+
+get_control_connection_host()
+

Returns the control connection host metadata.

+
+ +
+
+refresh_schema_metadata(max_schema_agreement_wait=None)
+

Synchronously refresh all schema metadata.

+

By default, the timeout for this operation is governed by max_schema_agreement_wait +and control_connection_timeout.

+

Passing max_schema_agreement_wait here overrides max_schema_agreement_wait.

+

Setting max_schema_agreement_wait <= 0 will bypass schema agreement and refresh schema immediately.

+

An Exception is raised if schema refresh fails for any reason.

+
+ +
+
+refresh_keyspace_metadata(keyspace, max_schema_agreement_wait=None)
+

Synchronously refresh keyspace metadata. This applies to keyspace-level information such as replication +and durability settings. It does not refresh tables, types, etc. contained in the keyspace.

+

See refresh_schema_metadata() for description of max_schema_agreement_wait behavior

+
+ +
+
+refresh_table_metadata(keyspace, table, max_schema_agreement_wait=None)
+

Synchronously refresh table metadata. This applies to a table, and any triggers or indexes attached +to the table.

+

See refresh_schema_metadata() for description of max_schema_agreement_wait behavior

+
+ +
+
+refresh_user_type_metadata(keyspace, user_type, max_schema_agreement_wait=None)
+

Synchronously refresh user defined type metadata.

+

See refresh_schema_metadata() for description of max_schema_agreement_wait behavior

+
+ +
+
+refresh_user_function_metadata(keyspace, function, max_schema_agreement_wait=None)
+

Synchronously refresh user defined function metadata.

+

function is a cassandra.UserFunctionDescriptor.

+

See refresh_schema_metadata() for description of max_schema_agreement_wait behavior

+
+ +
+
+refresh_user_aggregate_metadata(keyspace, aggregate, max_schema_agreement_wait=None)
+

Synchronously refresh user defined aggregate metadata.

+

aggregate is a cassandra.UserAggregateDescriptor.

+

See refresh_schema_metadata() for description of max_schema_agreement_wait behavior

+
+ +
+
+refresh_nodes(force_token_rebuild=False)
+

Synchronously refresh the node list and token metadata

+

force_token_rebuild can be used to rebuild the token map metadata, even if no new nodes are discovered.

+

An Exception is raised if node refresh fails for any reason.

+
+ +
+
+set_meta_refresh_enabled(enabled)
+

Deprecated: set schema_metadata_enabled token_metadata_enabled instead

+

Sets a flag to enable (True) or disable (False) all metadata refresh queries. +This applies to both schema and node topology.

+

Disabling this is useful to minimize refreshes during multiple changes.

+

Meta refresh must be enabled for the driver to become aware of any cluster +topology changes or schema updates.

+
+ +
+ +
+
+class cassandra.cluster.ExecutionProfile(load_balancing_policy=<object object>, retry_policy=None, consistency_level=ConsistencyLevel.LOCAL_ONE, serial_consistency_level=None, request_timeout=10.0, row_factory=<function named_tuple_factory>, speculative_execution_policy=None)
+
+
+consistency_level = LOCAL_ONE
+
+ +
+
+static row_factory(colnames, rows)
+

Returns each row as a namedtuple. +This is the default row factory.

+

Example:

+
>>> from cassandra.query import named_tuple_factory
+>>> session = cluster.connect('mykeyspace')
+>>> session.row_factory = named_tuple_factory
+>>> rows = session.execute("SELECT name, age FROM users LIMIT 1")
+>>> user = rows[0]
+
+>>> # you can access field by their name:
+>>> print "name: %s, age: %d" % (user.name, user.age)
+name: Bob, age: 42
+
+>>> # or you can access fields by their position (like a tuple)
+>>> name, age = user
+>>> print "name: %s, age: %d" % (name, age)
+name: Bob, age: 42
+>>> name = user[0]
+>>> age = user[1]
+>>> print "name: %s, age: %d" % (name, age)
+name: Bob, age: 42
+
+
+
+

Changed in version 2.0.0: moved from cassandra.decoder to cassandra.query

+
+
+ +
+ +
+
+class cassandra.cluster.GraphExecutionProfile(load_balancing_policy=_NOT_SET, retry_policy=None, consistency_level=ConsistencyLevel.LOCAL_ONE, serial_consistency_level=None, request_timeout=30.0, row_factory=None, graph_options=None, continuous_paging_options=_NOT_SET)
+

Default execution profile for graph execution.

+

See ExecutionProfile for base attributes. Note that if not explicitly set, +the row_factory and graph_options.graph_protocol are resolved during the query execution. +These options will resolve to graph_graphson3_row_factory and GraphProtocol.GRAPHSON_3_0 +for the core graph engine (DSE 6.8+), otherwise graph_object_row_factory and GraphProtocol.GRAPHSON_1_0

+

In addition to default parameters shown in the signature, this profile also defaults retry_policy to +cassandra.policies.NeverRetryPolicy.

+
+ +
+
+class cassandra.cluster.GraphAnalyticsExecutionProfile(load_balancing_policy=None, retry_policy=None, consistency_level=ConsistencyLevel.LOCAL_ONE, serial_consistency_level=None, request_timeout=3600.0 * 24.0 * 7.0, row_factory=None, graph_options=None)
+

Execution profile with timeout and load balancing appropriate for graph analytics queries.

+

See also GraphExecutionPolicy.

+

In addition to default parameters shown in the signature, this profile also defaults retry_policy to +cassandra.policies.NeverRetryPolicy, and load_balancing_policy to one that targets the current Spark +master.

+

Note: The graph_options.graph_source is set automatically to b’a’ (analytics) +when using GraphAnalyticsExecutionProfile. This is mandatory to target analytics nodes.

+
+ +
+
+cassandra.cluster.EXEC_PROFILE_DEFAULT
+

The most base type

+
+ +
+
+cassandra.cluster.EXEC_PROFILE_GRAPH_DEFAULT
+

The most base type

+
+ +
+
+cassandra.cluster.EXEC_PROFILE_GRAPH_SYSTEM_DEFAULT
+

The most base type

+
+ +
+
+cassandra.cluster.EXEC_PROFILE_GRAPH_ANALYTICS_DEFAULT
+

The most base type

+
+ +
+
+class cassandra.cluster.Session
+

A collection of connection pools for each host in the cluster. +Instances of this class should not be created directly, only +using Cluster.connect().

+

Queries and statements can be executed through Session instances +using the execute() and execute_async() +methods.

+

Example usage:

+
>>> session = cluster.connect()
+>>> session.set_keyspace("mykeyspace")
+>>> session.execute("SELECT * FROM mycf")
+
+
+
+
+default_timeout = 10.0
+

A default timeout, measured in seconds, for queries executed through +execute() or execute_async(). This default may be +overridden with the timeout parameter for either of those methods.

+

Setting this to None will cause no timeouts to be set by default.

+

Please see ResponseFuture.result() for details on the scope and +effect of this timeout.

+
+

New in version 2.0.0.

+
+
+ +
+
+default_consistency_level = LOCAL_ONE
+

Deprecated: use execution profiles instead +The default ConsistencyLevel for operations executed through +this session. This default may be overridden by setting the +consistency_level on individual statements.

+
+

New in version 1.2.0.

+
+
+

Changed in version 3.0.0: default changed from ONE to LOCAL_ONE

+
+
+ +
+
+default_serial_consistency_level = None
+

The default ConsistencyLevel for serial phase of conditional updates executed through +this session. This default may be overridden by setting the +serial_consistency_level on individual statements.

+

Only valid for protocol_version >= 2.

+
+ +
+
+row_factory = <function named_tuple_factory>
+

The format to return row results in. By default, each +returned row will be a named tuple. You can alternatively +use any of the following:

+ +
+ +
+
+default_fetch_size = 5000
+
+ +
+
+use_client_timestamp = True
+
+ +
+
+timestamp_generator = None
+
+ +
+
+encoder = None
+
+ +
+
+client_protocol_handler = <class 'cassandra.protocol.cython_protocol_handler.<locals>.CythonProtocolHandler'>
+
+ +
+
+execute(statement[, parameters][, timeout][, trace][, custom_payload][, paging_state][, host][, execute_as])
+

Execute the given query and synchronously wait for the response.

+

If an error is encountered while executing the query, an Exception +will be raised.

+

query may be a query string or an instance of cassandra.query.Statement.

+

parameters may be a sequence or dict of parameters to bind. If a +sequence is used, %s should be used the placeholder for each +argument. If a dict is used, %(name)s style placeholders must +be used.

+

timeout should specify a floating-point timeout (in seconds) after +which an OperationTimedOut exception will be raised if the query +has not completed. If not set, the timeout defaults to the request_timeout of the selected execution_profile. +If set to None, there is no timeout. Please see ResponseFuture.result() for details on +the scope and effect of this timeout.

+

If trace is set to True, the query will be sent with tracing enabled. +The trace details can be obtained using the returned ResultSet object.

+

custom_payload is a Custom Payloads dict to be passed to the server. +If query is a Statement with its own custom_payload. The message payload +will be a union of the two, with the values specified here taking precedence.

+

execution_profile is the execution profile to use for this request. It can be a key to a profile configured +via Cluster.add_execution_profile() or an instance (from Session.execution_profile_clone_update(), +for example

+

paging_state is an optional paging state, reused from a previous ResultSet.

+

host is the cassandra.pool.Host that should handle the query. If the host specified is down or +not yet connected, the query will fail with NoHostAvailable. Using this is +discouraged except in a few cases, e.g., querying node-local tables and applying schema changes.

+

execute_as the user that will be used on the server to execute the request. This is only available +on a DSE cluster.

+
+ +
+
+execute_async(statement[, parameters][, trace][, custom_payload][, paging_state][, host][, execute_as])
+

Execute the given query and return a ResponseFuture object +which callbacks may be attached to for asynchronous response +delivery. You may also call result() +on the ResponseFuture to synchronously block for results at +any time.

+

See Session.execute() for parameter definitions.

+

Example usage:

+
>>> session = cluster.connect()
+>>> future = session.execute_async("SELECT * FROM mycf")
+
+>>> def log_results(results):
+...     for row in results:
+...         log.info("Results: %s", row)
+
+>>> def log_error(exc):
+>>>     log.error("Operation failed: %s", exc)
+
+>>> future.add_callbacks(log_results, log_error)
+
+
+

Async execution with blocking wait for results:

+
>>> future = session.execute_async("SELECT * FROM mycf")
+>>> # do other stuff...
+
+>>> try:
+...     results = future.result()
+... except Exception:
+...     log.exception("Operation failed:")
+
+
+
+ +
+
+execute_graph(statement[, parameters][, trace][, execution_profile=EXEC_PROFILE_GRAPH_DEFAULT][, execute_as])
+

Executes a Gremlin query string or GraphStatement synchronously, +and returns a ResultSet from this execution.

+

parameters is dict of named parameters to bind. The values must be +JSON-serializable.

+

execution_profile: Selects an execution profile for the request.

+

execute_as the user that will be used on the server to execute the request.

+
+ +
+
+execute_graph_async(statement[, parameters][, trace][, execution_profile=EXEC_PROFILE_GRAPH_DEFAULT][, execute_as])
+

Execute the graph query and return a ResponseFuture +object which callbacks may be attached to for asynchronous response delivery. You may also call ResponseFuture.result() to synchronously block for +results at any time.

+
+ +
+
+prepare(statement)
+

Prepares a query string, returning a PreparedStatement +instance which can be used as follows:

+
>>> session = cluster.connect("mykeyspace")
+>>> query = "INSERT INTO users (id, name, age) VALUES (?, ?, ?)"
+>>> prepared = session.prepare(query)
+>>> session.execute(prepared, (user.id, user.name, user.age))
+
+
+

Or you may bind values to the prepared statement ahead of time:

+
>>> prepared = session.prepare(query)
+>>> bound_stmt = prepared.bind((user.id, user.name, user.age))
+>>> session.execute(bound_stmt)
+
+
+

Of course, prepared statements may (and should) be reused:

+
>>> prepared = session.prepare(query)
+>>> for user in users:
+...     bound = prepared.bind((user.id, user.name, user.age))
+...     session.execute(bound)
+
+
+

Alternatively, if protocol_version is 5 or higher +(requires Cassandra 4.0+), the keyspace can be specified as a +parameter. This will allow you to avoid specifying the keyspace in the +query without specifying a keyspace in connect(). It +even will let you prepare and use statements against a keyspace other +than the one originally specified on connection:

+
>>> analyticskeyspace_prepared = session.prepare(
+...     "INSERT INTO user_activity id, last_activity VALUES (?, ?)",
+...     keyspace="analyticskeyspace")  # note the different keyspace
+
+
+

Important: PreparedStatements should be prepared only once. +Preparing the same query more than once will likely affect performance.

+

custom_payload is a key value map to be passed along with the prepare +message. See Custom Payloads.

+
+ +
+
+shutdown()
+

Close all connections. Session instances should not be used +for any purpose after being shutdown.

+
+ +
+
+set_keyspace(keyspace)
+

Set the default keyspace for all queries made through this Session. +This operation blocks until complete.

+
+ +
+
+get_execution_profile(name)
+

Returns the execution profile associated with the provided name.

+
+
Parameters
+

name – The name (or key) of the execution profile.

+
+
+
+ +
+
+execution_profile_clone_update(ep, **kwargs)
+

Returns a clone of the ep profile. kwargs can be specified to update attributes +of the returned profile.

+

This is a shallow clone, so any objects referenced by the profile are shared. This means Load Balancing Policy +is maintained by inclusion in the active profiles. It also means updating any other rich objects will be seen +by the active profile. In cases where this is not desirable, be sure to replace the instance instead of manipulating +the shared object.

+
+ +
+
+add_request_init_listener(fn, *args, **kwargs)
+

Adds a callback with arguments to be called when any request is created.

+

It will be invoked as fn(response_future, *args, **kwargs) after each client request is created, +and before the request is sent. This can be used to create extensions by adding result callbacks to the +response future.

+

response_future is the ResponseFuture for the request.

+

Note that the init callback is done on the client thread creating the request, so you may need to consider +synchronization if you have multiple threads. Any callbacks added to the response future will be executed +on the event loop thread, so the normal advice about minimizing cycles and avoiding blocking apply (see Note in +ResponseFuture.add_callbacks().

+

See this example in the +source tree for an example.

+
+ +
+
+remove_request_init_listener(fn, *args, **kwargs)
+

Removes a callback and arguments from the list.

+

See Session.add_request_init_listener().

+
+ +
+ +
+
+class cassandra.cluster.ResponseFuture
+

An asynchronous response delivery mechanism that is returned from calls +to Session.execute_async().

+
+
There are two ways for results to be delivered:
+
+
+
+
+query = None
+
+ +
+
+result()
+

Return the final result or raise an Exception if errors were +encountered. If the final result or error has not been set +yet, this method will block until it is set, or the timeout +set for the request expires.

+

Timeout is specified in the Session request execution functions. +If the timeout is exceeded, an cassandra.OperationTimedOut will be raised. +This is a client-side timeout. For more information +about server-side coordinator timeouts, see policies.RetryPolicy.

+

Example usage:

+
>>> future = session.execute_async("SELECT * FROM mycf")
+>>> # do other stuff...
+
+>>> try:
+...     rows = future.result()
+...     for row in rows:
+...         ... # process results
+... except Exception:
+...     log.exception("Operation failed:")
+
+
+
+ +
+
+get_query_trace()
+

Fetches and returns the query trace of the last response, or None if tracing was +not enabled.

+

Note that this may raise an exception if there are problems retrieving the trace +details from Cassandra. If the trace is not available after max_wait, +cassandra.query.TraceUnavailable will be raised.

+

If the ResponseFuture is not done (async execution) and you try to retrieve the trace, +cassandra.query.TraceUnavailable will be raised.

+

query_cl is the consistency level used to poll the trace tables.

+
+ +
+
+get_all_query_traces()
+

Fetches and returns the query traces for all query pages, if tracing was enabled.

+

See note in get_query_trace() regarding possible exceptions.

+
+ +
+
+custom_payload
+

The custom payload returned from the server, if any. This will only be +set by Cassandra servers implementing a custom QueryHandler, and only +for protocol_version 4+.

+

Ensure the future is complete before trying to access this property +(call result(), or after callback is invoked). +Otherwise it may throw if the response has not been received.

+
+
Returns
+

Custom Payloads.

+
+
+
+ +
+
+is_schema_agreed = True
+
+ +
+
+has_more_pages
+

Returns True if there are more pages left in the +query results, False otherwise. This should only +be checked after the first page has been returned.

+
+

New in version 2.0.0.

+
+
+ +
+
+warnings
+

Warnings returned from the server, if any. This will only be +set for protocol_version 4+.

+

Warnings may be returned for such things as oversized batches, +or too many tombstones in slice queries.

+

Ensure the future is complete before trying to access this property +(call result(), or after callback is invoked). +Otherwise it may throw if the response has not been received.

+
+ +
+
+start_fetching_next_page()
+

If there are more pages left in the query result, this asynchronously +starts fetching the next page. If there are no pages left, QueryExhausted +is raised. Also see has_more_pages.

+

This should only be called after the first page has been returned.

+
+

New in version 2.0.0.

+
+
+ +
+
+add_callback(fn, *args, **kwargs)
+

Attaches a callback function to be called when the final results arrive.

+

By default, fn will be called with the results as the first and only +argument. If *args or **kwargs are supplied, they will be passed +through as additional positional or keyword arguments to fn.

+

If an error is hit while executing the operation, a callback attached +here will not be called. Use add_errback() or add_callbacks() +if you wish to handle that case.

+

If the final result has already been seen when this method is called, +the callback will be called immediately (before this method returns).

+

Note: in the case that the result is not available when the callback is added, +the callback is executed by IO event thread. This means that the callback +should not block or attempt further synchronous requests, because no further +IO will be processed until the callback returns.

+

Important: if the callback you attach results in an exception being +raised, the exception will be ignored, so please ensure your +callback handles all error cases that you care about.

+

Usage example:

+
>>> session = cluster.connect("mykeyspace")
+
+>>> def handle_results(rows, start_time, should_log=False):
+...     if should_log:
+...         log.info("Total time: %f", time.time() - start_time)
+...     ...
+
+>>> future = session.execute_async("SELECT * FROM users")
+>>> future.add_callback(handle_results, time.time(), should_log=True)
+
+
+
+ +
+
+add_errback(fn, *args, **kwargs)
+

Like add_callback(), but handles error cases. +An Exception instance will be passed as the first positional argument +to fn.

+
+ +
+
+ResponseFuture.add_callbacks(callback, errback, callback_args=(), callback_kwargs=None, errback_args=(), errback_args=None)
+

A convenient combination of add_callback() and +add_errback().

+

Example usage:

+
>>> session = cluster.connect()
+>>> query = "SELECT * FROM mycf"
+>>> future = session.execute_async(query)
+
+>>> def log_results(results, level='debug'):
+...     for row in results:
+...         log.log(level, "Result: %s", row)
+
+>>> def log_error(exc, query):
+...     log.error("Query '%s' failed: %s", query, exc)
+
+>>> future.add_callbacks(
+...     callback=log_results, callback_kwargs={'level': 'info'},
+...     errback=log_error, errback_args=(query,))
+
+
+
+ +
+ +
+
+class cassandra.cluster.ResultSet
+

An iterator over the rows from a query result. Also supplies basic equality +and indexing methods for backward-compatability. These methods materialize +the entire result set (loading all pages), and should only be used if the +total result size is understood. Warnings are emitted when paged results +are materialized in this fashion.

+

You can treat this as a normal iterator over rows:

+
>>> from cassandra.query import SimpleStatement
+>>> statement = SimpleStatement("SELECT * FROM users", fetch_size=10)
+>>> for user_row in session.execute(statement):
+...     process_user(user_row)
+
+
+

Whenever there are no more rows in the current page, the next page will +be fetched transparently. However, note that it is possible for +an Exception to be raised while fetching the next page, just +like you might see on a normal call to session.execute().

+
+
+all()
+

Returns all the remaining rows as a list. This is basically +a convenient shortcut to list(result_set).

+

This function is not recommended for queries that return a large number of elements.

+
+ +
+
+property current_rows
+

The list of current page rows. May be empty if the result was empty, +or this is the last page.

+
+ +
+
+fetch_next_page()
+

Manually, synchronously fetch the next page. Supplied for manually retrieving pages +and inspecting current_page(). It is not necessary to call this when iterating +through results; paging happens implicitly in iteration.

+
+ +
+
+get_all_query_traces(max_wait_sec_per=None)
+

Gets all query traces from the associated future. +See ResponseFuture.get_all_query_traces() for details.

+
+ +
+
+get_query_trace(max_wait_sec=None)
+

Gets the last query trace from the associated future. +See ResponseFuture.get_query_trace() for details.

+
+ +
+
+property has_more_pages
+

True if the last response indicated more pages; False otherwise

+
+ +
+
+one()
+

Return a single row of the results or None if empty. This is basically +a shortcut to result_set.current_rows[0] and should only be used when +you know a query returns a single row. Consider using an iterator if the +ResultSet contains more than one row.

+
+ +
+
+property paging_state
+

Server paging state of the query. Can be None if the query was not paged.

+

The driver treats paging state as opaque, but it may contain primary key data, so applications may want to +avoid sending this to untrusted parties.

+
+ +
+
+property was_applied
+

For LWT results, returns whether the transaction was applied.

+

Result is indeterminate if called on a result that was not an LWT request or on +a query.BatchStatement containing LWT. In the latter case either all the batch +succeeds or fails.

+

Only valid when one of the of the internal row factories is in use.

+
+ +
+ +
+
+exception cassandra.cluster.QueryExhausted
+

Raised when ResponseFuture.start_fetching_next_page() is called and +there are no more pages. You can check ResponseFuture.has_more_pages +before calling to avoid this.

+
+

New in version 2.0.0.

+
+
+ +
+
+exception cassandra.cluster.NoHostAvailable
+

Raised when an operation is attempted but all connections are +busy, defunct, closed, or resulted in errors when used.

+
+ +
+
+exception cassandra.cluster.UserTypeDoesNotExist
+

An attempt was made to use a user-defined type that does not exist.

+
+

New in version 2.1.0.

+
+
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/stable/api/cassandra/concurrent.html b/stable/api/cassandra/concurrent.html new file mode 100644 index 0000000000..e0703d9591 --- /dev/null +++ b/stable/api/cassandra/concurrent.html @@ -0,0 +1,701 @@ + + + + + + + + + + + + + cassandra.concurrent - Utilities for Concurrent Statement Execution | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + + + +
+ +
+ +
+

cassandra.concurrent - Utilities for Concurrent Statement Execution

+
+
+cassandra.concurrent.execute_concurrent(session, statements_and_parameters, concurrency=100, raise_on_first_error=True, results_generator=False, execution_profile=<object object>)
+

Executes a sequence of (statement, parameters) tuples concurrently. Each +parameters item must be a sequence or None.

+

The concurrency parameter controls how many statements will be executed +concurrently. When Cluster.protocol_version is set to 1 or 2, +it is recommended that this be kept below 100 times the number of +core connections per host times the number of connected hosts (see +Cluster.set_core_connections_per_host()). If that amount is exceeded, +the event loop thread may attempt to block on new connection creation, +substantially impacting throughput. If protocol_version +is 3 or higher, you can safely experiment with higher levels of concurrency.

+

If raise_on_first_error is left as True, execution will stop +after the first failed statement and the corresponding exception will be +raised.

+

results_generator controls how the results are returned.

+
    +
  • If False, the results are returned only after all requests have completed.

  • +
  • If True, a generator expression is returned. Using a generator results in a constrained +memory footprint when the results set will be large – results are yielded +as they return instead of materializing the entire list at once. The trade for lower memory +footprint is marginal CPU overhead (more thread coordination and sorting out-of-order results +on-the-fly).

  • +
+

execution_profile argument is the execution profile to use for this +request, it is passed directly to Session.execute_async().

+

A sequence of ExecutionResult(success, result_or_exc) namedtuples is returned +in the same order that the statements were passed in. If success is False, +there was an error executing the statement, and result_or_exc will be +an Exception. If success is True, result_or_exc +will be the query result.

+

Example usage:

+
select_statement = session.prepare("SELECT * FROM users WHERE id=?")
+
+statements_and_params = []
+for user_id in user_ids:
+    params = (user_id, )
+    statements_and_params.append((select_statement, params))
+
+results = execute_concurrent(
+    session, statements_and_params, raise_on_first_error=False)
+
+for (success, result) in results:
+    if not success:
+        handle_error(result)  # result will be an Exception
+    else:
+        process_user(result[0])  # result will be a list of rows
+
+
+

Note: in the case that generators are used, it is important to ensure the consumers do not +block or attempt further synchronous requests, because no further IO will be processed until +the consumer returns. This may also produce a deadlock in the IO event thread.

+
+ +
+
+cassandra.concurrent.execute_concurrent_with_args(session, statement, parameters, *args, **kwargs)
+

Like execute_concurrent(), but takes a single +statement and a sequence of parameters. Each item in parameters +should be a sequence or None.

+

Example usage:

+
statement = session.prepare("INSERT INTO mytable (a, b) VALUES (1, ?)")
+parameters = [(x,) for x in range(1000)]
+execute_concurrent_with_args(session, statement, parameters, concurrency=50)
+
+
+
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/stable/api/cassandra/connection.html b/stable/api/cassandra/connection.html new file mode 100644 index 0000000000..c36e16834f --- /dev/null +++ b/stable/api/cassandra/connection.html @@ -0,0 +1,729 @@ + + + + + + + + + + + + + cassandra.connection - Low Level Connection Info | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + + + +
+ +
+ +
+

cassandra.connection - Low Level Connection Info

+
+
+exception cassandra.connection.ConnectionException
+

An unrecoverable error was hit when attempting to use a connection, +or the connection was already closed or defunct.

+
+ +
+
+exception cassandra.connection.ConnectionShutdown
+

Raised when a connection has been marked as defunct or has been closed.

+
+ +
+
+exception cassandra.connection.ConnectionBusy
+

An attempt was made to send a message through a Connection that +was already at the max number of in-flight operations.

+
+ +
+
+exception cassandra.connection.ProtocolError
+

Communication did not match the protocol that this driver expects.

+
+ +
+
+class cassandra.connection.EndPoint
+

Represents the information to connect to a cassandra node.

+
+
+property address
+

The IP address of the node. This is the RPC address the driver uses when connecting to the node

+
+ +
+
+property port
+

The port of the node.

+
+ +
+
+resolve()
+

Resolve the endpoint to an address/port. This is called +only on socket connection.

+
+ +
+
+property socket_family
+

The socket family of the endpoint.

+
+ +
+
+property ssl_options
+

SSL options specific to this endpoint.

+
+ +
+ +
+
+class cassandra.connection.EndPointFactory
+
+
+configure(cluster)
+

This is called by the cluster during its initialization.

+
+ +
+
+create(row)
+

Create an EndPoint from a system.peers row.

+
+ +
+ +
+
+class cassandra.connection.SniEndPoint(proxy_address, server_name, port=9042)
+

SNI Proxy EndPoint implementation.

+
+ +
+
+class cassandra.connection.SniEndPointFactory(proxy_address, port, node_domain=None)
+
+ +
+
+class cassandra.connection.UnixSocketEndPoint(unix_socket_path)
+

Unix Socket EndPoint implementation.

+
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/stable/api/cassandra/cqlengine/columns.html b/stable/api/cassandra/cqlengine/columns.html new file mode 100644 index 0000000000..b7e7583043 --- /dev/null +++ b/stable/api/cassandra/cqlengine/columns.html @@ -0,0 +1,947 @@ + + + + + + + + + + + + + cassandra.cqlengine.columns - Column types for object mapping models | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + + + +
+ +
+ +
+

cassandra.cqlengine.columns - Column types for object mapping models

+
+

Columns

+

Columns in your models map to columns in your CQL table. You define CQL columns by defining column attributes on your model classes. +For a model to be valid it needs at least one primary key column and one non-primary key column.

+

Just as in CQL, the order you define your columns in is important, and is the same order they are defined in on a model’s corresponding table.

+

Each column on your model definitions needs to be an instance of a Column class.

+
+
+class cassandra.cqlengine.columns.Column(**kwargs)
+
+
+primary_key = False
+

bool flag, indicates this column is a primary key. The first primary key defined +on a model is the partition key (unless partition keys are set), all others are cluster keys

+
+ +
+
+partition_key = False
+

indicates that this column should be the partition key, defining +more than one partition key column creates a compound partition key

+
+ +
+
+index = False
+

bool flag, indicates an index should be created for this column

+
+ +
+
+custom_index = False
+

bool flag, indicates an index is managed outside of cqlengine. This is +useful if you want to do filter queries on fields that have custom +indexes.

+
+ +
+
+db_field = None
+

the fieldname this field will map to in the database

+
+ +
+
+default = None
+

the default value, can be a value or a callable (no args)

+
+ +
+
+required = False
+

boolean, is the field required? Model validation will raise and +exception if required is set to True and there is a None value assigned

+
+ +
+
+clustering_order = None
+

only applicable on clustering keys (primary keys that are not partition keys) +determines the order that the clustering keys are sorted on disk

+
+ +
+
+discriminator_column = False
+

boolean, if set to True, this column will be used for discriminating records +of inherited models.

+

Should only be set on a column of an abstract model being used for inheritance.

+

There may only be one discriminator column per model. See __discriminator_value__ +for how to specify the value of this column on specialized models.

+
+ +
+
+static = False
+

boolean, if set to True, this is a static column, with a single value per partition

+
+ +
+ +
+
+

Column Types

+

Columns of all types are initialized by passing Column attributes to the constructor by keyword.

+
+
+class cassandra.cqlengine.columns.Ascii(**kwargs)
+

Stores a US-ASCII character string

+
+
Parameters
+
    +
  • min_length (int) – Sets the minimum length of this string, for validation purposes. +Defaults to 1 if this is a required column. Otherwise, None.

  • +
  • max_length (int) – Sets the maximum length of this string, for validation purposes.

  • +
+
+
+
+ +
+
+class cassandra.cqlengine.columns.BigInt(**kwargs)
+

Stores a 64-bit signed integer value

+
+ +
+
+class cassandra.cqlengine.columns.Blob(**kwargs)
+

Stores a raw binary value

+
+ +
+
+cassandra.cqlengine.columns.Bytes
+

alias of cassandra.cqlengine.columns.Blob

+
+ +
+
+class cassandra.cqlengine.columns.Boolean(**kwargs)
+

Stores a boolean True or False value

+
+ +
+
+class cassandra.cqlengine.columns.Counter(index=False, db_field=None, required=False)
+

Stores a counter that can be incremented and decremented

+
+ +
+
+class cassandra.cqlengine.columns.Date(**kwargs)
+

Stores a simple date, with no time-of-day

+
+

Changed in version 2.6.0: removed overload of Date and DateTime. DateTime is a drop-in replacement for legacy models

+
+

requires C* 2.2+ and protocol v4+

+
+ +
+
+class cassandra.cqlengine.columns.DateTime(**kwargs)
+

Stores a datetime value

+
+
+truncate_microseconds = False
+

Set this True to have model instances truncate the date, quantizing it in the same way it will be in the database. +This allows equality comparison between assigned values and values read back from the database:

+
DateTime.truncate_microseconds = True
+assert Model.create(id=0, d=datetime.utcnow()) == Model.objects(id=0).first()
+
+
+

Defaults to False to preserve legacy behavior. May change in the future.

+
+ +
+ +
+
+class cassandra.cqlengine.columns.Decimal(**kwargs)
+

Stores a variable precision decimal value

+
+ +
+
+class cassandra.cqlengine.columns.Double(**kwargs)
+

Stores a double-precision floating-point value

+
+ +
+
+class cassandra.cqlengine.columns.Float(primary_key=False, partition_key=False, index=False, db_field=None, default=None, required=False, clustering_order=None, discriminator_column=False, static=False, custom_index=False)
+

Stores a single-precision floating-point value

+
+ +
+
+class cassandra.cqlengine.columns.Integer(**kwargs)
+

Stores a 32-bit signed integer value

+
+ +
+
+class cassandra.cqlengine.columns.List(value_type, default=<class 'list'>, **kwargs)
+

Stores a list of ordered values

+

http://www.datastax.com/documentation/cql/3.1/cql/cql_using/use_list_t.html

+
+
Parameters
+

value_type – a column class indicating the types of the value

+
+
+
+ +
+
+class cassandra.cqlengine.columns.Map(key_type, value_type, default=<class 'dict'>, **kwargs)
+

Stores a key -> value map (dictionary)

+

https://docs.datastax.com/en/dse/6.7/cql/cql/cql_using/useMap.html

+
+
Parameters
+
    +
  • key_type – a column class indicating the types of the key

  • +
  • value_type – a column class indicating the types of the value

  • +
+
+
+
+ +
+
+class cassandra.cqlengine.columns.Set(value_type, strict=True, default=<class 'set'>, **kwargs)
+

Stores a set of unordered, unique values

+

http://www.datastax.com/documentation/cql/3.1/cql/cql_using/use_set_t.html

+
+
Parameters
+
    +
  • value_type – a column class indicating the types of the value

  • +
  • strict – sets whether non set values will be coerced to set +type on validation, or raise a validation error, defaults to True

  • +
+
+
+
+ +
+
+class cassandra.cqlengine.columns.SmallInt(**kwargs)
+

Stores a 16-bit signed integer value

+
+

New in version 2.6.0.

+
+

requires C* 2.2+ and protocol v4+

+
+ +
+
+class cassandra.cqlengine.columns.Text(min_length=None, max_length=None, **kwargs)
+

Stores a UTF-8 encoded string

+
+
Parameters
+
    +
  • min_length (int) – Sets the minimum length of this string, for validation purposes. +Defaults to 1 if this is a required column. Otherwise, None.

  • +
  • max_length (int) – Sets the maximum length of this string, for validation purposes.

  • +
+
+
+
+ +
+
+class cassandra.cqlengine.columns.Time(**kwargs)
+

Stores a timezone-naive time-of-day, with nanosecond precision

+
+

New in version 2.6.0.

+
+

requires C* 2.2+ and protocol v4+

+
+ +
+
+class cassandra.cqlengine.columns.TimeUUID(**kwargs)
+

UUID containing timestamp

+
+ +
+
+class cassandra.cqlengine.columns.TinyInt(**kwargs)
+

Stores an 8-bit signed integer value

+
+

New in version 2.6.0.

+
+

requires C* 2.2+ and protocol v4+

+
+ +
+
+class cassandra.cqlengine.columns.UserDefinedType(user_type, **kwargs)
+

User Defined Type column

+

http://www.datastax.com/documentation/cql/3.1/cql/cql_using/cqlUseUDT.html

+

These columns are represented by a specialization of cassandra.cqlengine.usertype.UserType.

+

Please see User Defined Types for examples and discussion.

+
+
Parameters
+

user_type (type) – specifies the UserType model of the column

+
+
+
+ +
+
+class cassandra.cqlengine.columns.UUID(**kwargs)
+

Stores a type 1 or 4 UUID

+
+ +
+
+class cassandra.cqlengine.columns.VarInt(**kwargs)
+

Stores an arbitrary-precision integer

+
+ +
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/stable/api/cassandra/cqlengine/connection.html b/stable/api/cassandra/cqlengine/connection.html new file mode 100644 index 0000000000..1afa408540 --- /dev/null +++ b/stable/api/cassandra/cqlengine/connection.html @@ -0,0 +1,708 @@ + + + + + + + + + + + + + cassandra.cqlengine.connection - Connection management for cqlengine | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + + + +
+ +
+ +
+

cassandra.cqlengine.connection - Connection management for cqlengine

+
+
+cassandra.cqlengine.connection.default()
+

Configures the default connection to localhost, using the driver defaults +(except for row_factory)

+
+ +
+
+cassandra.cqlengine.connection.set_session(s)
+

Configures the default connection with a preexisting cassandra.cluster.Session

+

Note: the mapper presently requires a Session cassandra.cluster.Session.row_factory set to dict_factory. +This may be relaxed in the future

+
+ +
+
+cassandra.cqlengine.connection.setup(hosts, default_keyspace, consistency=None, lazy_connect=False, retry_connect=False, **kwargs)
+

Setup a the driver connection used by the mapper

+
+
Parameters
+
    +
  • hosts (list) – list of hosts, (contact_points for cassandra.cluster.Cluster)

  • +
  • default_keyspace (str) – The default keyspace to use

  • +
  • consistency (int) – The global default ConsistencyLevel - default is the same as Session.default_consistency_level

  • +
  • lazy_connect (bool) – True if should not connect until first use

  • +
  • retry_connect (bool) – True if we should retry to connect even if there was a connection failure initially

  • +
  • **kwargs – Pass-through keyword arguments for cassandra.cluster.Cluster

  • +
+
+
+
+ +
+
+cassandra.cqlengine.connection.register_connection(name, hosts=None, consistency=None, lazy_connect=False, retry_connect=False, cluster_options=None, default=False, session=None)
+

Add a connection to the connection registry. hosts and session are +mutually exclusive, and consistency, lazy_connect, +retry_connect, and cluster_options only work with hosts. Using +hosts will create a new cassandra.cluster.Cluster and +cassandra.cluster.Session.

+
+
Parameters
+
    +
  • hosts (list) – list of hosts, (contact_points for cassandra.cluster.Cluster).

  • +
  • consistency (int) – The default ConsistencyLevel for the +registered connection’s new session. Default is the same as +Session.default_consistency_level. For use with hosts only; +will fail when used with session.

  • +
  • lazy_connect (bool) – True if should not connect until first use. For +use with hosts only; will fail when used with session.

  • +
  • retry_connect (bool) – True if we should retry to connect even if there +was a connection failure initially. For use with hosts only; will +fail when used with session.

  • +
  • cluster_options (dict) – A dict of options to be used as keyword +arguments to cassandra.cluster.Cluster. For use with hosts +only; will fail when used with session.

  • +
  • default (bool) – If True, set the new connection as the cqlengine +default

  • +
  • session (Session) – A cassandra.cluster.Session to be used in +the created connection.

  • +
+
+
+
+ +
+
+cassandra.cqlengine.connection.unregister_connection(name)
+
+ +
+
+cassandra.cqlengine.connection.set_default_connection(name)
+
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/stable/api/cassandra/cqlengine/management.html b/stable/api/cassandra/cqlengine/management.html new file mode 100644 index 0000000000..0a04504ccc --- /dev/null +++ b/stable/api/cassandra/cqlengine/management.html @@ -0,0 +1,730 @@ + + + + + + + + + + + + + cassandra.cqlengine.management - Schema management for cqlengine | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + + + +
+ +
+ +
+

cassandra.cqlengine.management - Schema management for cqlengine

+

A collection of functions for managing keyspace and table schema.

+
+
+cassandra.cqlengine.management.create_keyspace_simple(name, replication_factor, durable_writes=True, connections=None)
+

Creates a keyspace with SimpleStrategy for replica placement

+

If the keyspace already exists, it will not be modified.

+

This function should be used with caution, especially in production environments. +Take care to execute schema modifications in a single context (i.e. not concurrently with other clients).

+

There are plans to guard schema-modifying functions with an environment-driven conditional.

+
+
Parameters
+
    +
  • name (str) – name of keyspace to create

  • +
  • replication_factor (int) – keyspace replication factor, used with SimpleStrategy

  • +
  • durable_writes (bool) – Write log is bypassed if set to False

  • +
  • connections (list) – List of connection names

  • +
+
+
+
+ +
+
+cassandra.cqlengine.management.create_keyspace_network_topology(name, dc_replication_map, durable_writes=True, connections=None)
+

Creates a keyspace with NetworkTopologyStrategy for replica placement

+

If the keyspace already exists, it will not be modified.

+

This function should be used with caution, especially in production environments. +Take care to execute schema modifications in a single context (i.e. not concurrently with other clients).

+

There are plans to guard schema-modifying functions with an environment-driven conditional.

+
+
Parameters
+
    +
  • name (str) – name of keyspace to create

  • +
  • dc_replication_map (dict) – map of dc_names: replication_factor

  • +
  • durable_writes (bool) – Write log is bypassed if set to False

  • +
  • connections (list) – List of connection names

  • +
+
+
+
+ +
+
+cassandra.cqlengine.management.drop_keyspace(name, connections=None)
+

Drops a keyspace, if it exists.

+

There are plans to guard schema-modifying functions with an environment-driven conditional.

+

This function should be used with caution, especially in production environments. +Take care to execute schema modifications in a single context (i.e. not concurrently with other clients).

+
+
Parameters
+
    +
  • name (str) – name of keyspace to drop

  • +
  • connections (list) – List of connection names

  • +
+
+
+
+ +
+
+cassandra.cqlengine.management.sync_table(model, keyspaces=None, connections=None)
+

Inspects the model and creates / updates the corresponding table and columns.

+

If keyspaces is specified, the table will be synched for all specified keyspaces. +Note that the Model.__keyspace__ is ignored in that case.

+

If connections is specified, the table will be synched for all specified connections. Note that the Model.__connection__ is ignored in that case. +If not specified, it will try to get the connection from the Model.

+

Any User Defined Types used in the table are implicitly synchronized.

+

This function can only add fields that are not part of the primary key.

+

Note that the attributes removed from the model are not deleted on the database. +They become effectively ignored by (will not show up on) the model.

+

This function should be used with caution, especially in production environments. +Take care to execute schema modifications in a single context (i.e. not concurrently with other clients).

+

There are plans to guard schema-modifying functions with an environment-driven conditional.

+
+ +
+
+cassandra.cqlengine.management.sync_type(ks_name, type_model, connection=None)
+

Inspects the type_model and creates / updates the corresponding type.

+

Note that the attributes removed from the type_model are not deleted on the database (this operation is not supported). +They become effectively ignored by (will not show up on) the type_model.

+

This function should be used with caution, especially in production environments. +Take care to execute schema modifications in a single context (i.e. not concurrently with other clients).

+

There are plans to guard schema-modifying functions with an environment-driven conditional.

+
+ +
+
+cassandra.cqlengine.management.drop_table(model, keyspaces=None, connections=None)
+

Drops the table indicated by the model, if it exists.

+

If keyspaces is specified, the table will be dropped for all specified keyspaces. Note that the Model.__keyspace__ is ignored in that case.

+

If connections is specified, the table will be synched for all specified connections. Note that the Model.__connection__ is ignored in that case. +If not specified, it will try to get the connection from the Model.

+

This function should be used with caution, especially in production environments. +Take care to execute schema modifications in a single context (i.e. not concurrently with other clients).

+

There are plans to guard schema-modifying functions with an environment-driven conditional.

+
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/stable/api/cassandra/cqlengine/models.html b/stable/api/cassandra/cqlengine/models.html new file mode 100644 index 0000000000..1d0bd2e00e --- /dev/null +++ b/stable/api/cassandra/cqlengine/models.html @@ -0,0 +1,935 @@ + + + + + + + + + + + + + cassandra.cqlengine.models - Table models for object mapping | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + + + +
+ +
+ +
+

cassandra.cqlengine.models - Table models for object mapping

+
+

Model

+
+
+class cassandra.cqlengine.models.Model(\*\*kwargs)
+

The initializer creates an instance of the model. Pass in keyword arguments for columns you’ve defined on the model.

+
class Person(Model):
+    id = columns.UUID(primary_key=True)
+    first_name  = columns.Text()
+    last_name = columns.Text()
+
+person = Person(first_name='Blake', last_name='Eggleston')
+person.first_name  #returns 'Blake'
+person.last_name  #returns 'Eggleston'
+
+
+

Model attributes define how the model maps to tables in the database. These are class variables that should be set +when defining Model deriviatives.

+
+
+__abstract__ = False
+

Optional. Indicates that this model is only intended to be used as a base class for other models. +You can’t create tables for abstract models, but checks around schema validity are skipped during class construction.

+
+ +
+
+__table_name__ = None
+

Optional. Sets the name of the CQL table for this model. If left blank, the table name will be the name of the model, with it’s module name as it’s prefix. Manually defined table names are not inherited.

+
+ +
+
+__table_name_case_sensitive__ = False
+

Optional. By default, __table_name__ is case insensitive. Set this to True if you want to preserve the case sensitivity.

+
+ +
+
+__keyspace__ = None
+

Sets the name of the keyspace used by this model.

+
+ +
+
+__connection__ = None
+

Sets the name of the default connection used by this model.

+
+ +
+
+__default_ttl__ = None
+

Will be deprecated in release 4.0. You can set the default ttl by configuring the table __options__. See Default TTL and Per Query TTL for more details.

+
+ +
+
+__discriminator_value__ = None
+

Optional Specifies a value for the discriminator column when using model inheritance.

+

See Model Inheritance for usage examples.

+
+ +

Each table can have its own set of configuration options, including compaction. Unspecified, these default to sensible values in +the server. To override defaults, set options using the model __options__ attribute, which allows options specified a dict.

+

When a table is synced, it will be altered to match the options set on your table. +This means that if you are changing settings manually they will be changed back on resync.

+

Do not use the options settings of cqlengine if you want to manage your compaction settings manually.

+

See the list of supported table properties for more information.

+
+
+__options__
+

For example:

+
class User(Model):
+    __options__ = {'compaction': {'class': 'LeveledCompactionStrategy',
+                                  'sstable_size_in_mb': '64',
+                                  'tombstone_threshold': '.2'},
+                   'comment': 'User data stored here'}
+
+    user_id = columns.UUID(primary_key=True)
+    name = columns.Text()
+
+
+

or :

+
class TimeData(Model):
+    __options__ = {'compaction': {'class': 'SizeTieredCompactionStrategy',
+                                  'bucket_low': '.3',
+                                  'bucket_high': '2',
+                                  'min_threshold': '2',
+                                  'max_threshold': '64',
+                                  'tombstone_compaction_interval': '86400'},
+                   'gc_grace_seconds': '0'}
+
+
+
+ +
+
+__compute_routing_key__ = True
+

Optional Setting False disables computing the routing key for TokenAwareRouting

+
+ +

The base methods allow creating, storing, and querying modeled objects.

+
+
+classmethod create(**kwargs)
+

Create an instance of this model in the database.

+

Takes the model column values as keyword arguments. Setting a value to +None is equivalent to running a CQL DELETE on that column.

+

Returns the instance.

+
+ +
+
+if_not_exists()
+

Check the existence of an object before insertion. The existence of an +object is determined by its primary key(s). And please note using this flag +would incur performance cost.

+

If the insertion isn’t applied, a LWTException is raised.

+
try:
+    TestIfNotExistsModel.if_not_exists().create(id=id, count=9, text='111111111111')
+except LWTException as e:
+    # handle failure case
+    print e.existing  # dict containing LWT result fields
+
+
+

This method is supported on Cassandra 2.0 or later.

+
+ +
+
+if_exists()
+

Check the existence of an object before an update or delete. The existence of an +object is determined by its primary key(s). And please note using this flag +would incur performance cost.

+

If the update or delete isn’t applied, a LWTException is raised.

+
try:
+    TestIfExistsModel.objects(id=id).if_exists().update(count=9, text='111111111111')
+except LWTException as e:
+    # handle failure case
+    pass
+
+
+

This method is supported on Cassandra 2.0 or later.

+
+ +
+
+save()
+

Saves an object to the database.

+
#create a person instance
+person = Person(first_name='Kimberly', last_name='Eggleston')
+#saves it to Cassandra
+person.save()
+
+
+
+ +
+
+update(**values)
+

Performs an update on the model instance. You can pass in values to set on the model +for updating, or you can call without values to execute an update against any modified +fields. If no fields on the model have been modified since loading, no query will be +performed. Model validation is performed normally. Setting a value to None is +equivalent to running a CQL DELETE on that column.

+

It is possible to do a blind update, that is, to update a field without having first selected the object out of the database. +See Blind Updates

+
+ +
+
+iff(**values)
+

Checks to ensure that the values specified are correct on the Cassandra cluster. +Simply specify the column(s) and the expected value(s). As with if_not_exists, +this incurs a performance cost.

+

If the insertion isn’t applied, a LWTException is raised.

+
t = TestTransactionModel(text='some text', count=5)
+try:
+     t.iff(count=5).update('other text')
+except LWTException as e:
+    # handle failure case
+    print e.existing # existing object
+
+
+
+ +
+
+classmethod get(*args, **kwargs)
+

Returns a single object based on the passed filter constraints.

+

This is a pass-through to the model objects().:method:~cqlengine.queries.get.

+
+ +
+
+classmethod filter(*args, **kwargs)
+

Returns a queryset based on filter parameters.

+

This is a pass-through to the model objects().:method:~cqlengine.queries.filter.

+
+ +
+
+classmethod all()
+

Returns a queryset representing all stored objects

+

This is a pass-through to the model objects().all()

+
+ +
+
+delete()
+

Deletes the object from the database

+
+ +
+
+batch(batch_object)
+

Sets the batch object to run instance updates and inserts queries with.

+

See Batch Queries for usage examples

+
+ +
+
+timeout(timeout)
+

Sets a timeout for use in save(), update(), and delete() +operations

+
+ +
+
+timestamp(timedelta_or_datetime)
+

Sets the timestamp for the query

+
+ +
+
+ttl(ttl_in_sec)
+

Sets the ttl values to run instance updates and inserts queries with.

+
+ +
+
+using(connection=None)
+

Change the context on the fly of the model instance (keyspace, connection)

+
+ +
+
+classmethod column_family_name(include_keyspace=True)
+

Returns the column family name if it’s been defined +otherwise, it creates it from the module and class name

+
+ +

Models also support dict-like access:

+
+
+len(m)
+

Returns the number of columns defined in the model

+
+ +
+
+m[col_name]
+

Returns the value of column col_name

+
+ +
+
+m[col_name] = value
+

Set m[col_name] to value

+
+ +
+
+keys()
+

Returns a list of column IDs.

+
+ +
+
+values()
+

Returns list of column values.

+
+ +
+
+items()
+

Returns a list of column ID/value tuples.

+
+ +
+ +
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/stable/api/cassandra/cqlengine/query.html b/stable/api/cassandra/cqlengine/query.html new file mode 100644 index 0000000000..6eef3ab682 --- /dev/null +++ b/stable/api/cassandra/cqlengine/query.html @@ -0,0 +1,1031 @@ + + + + + + + + + + + + + cassandra.cqlengine.query - Query and filter model objects | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + + + +
+ +
+ +
+

cassandra.cqlengine.query - Query and filter model objects

+
+

QuerySet

+

QuerySet objects are typically obtained by calling objects() on a model class. +The methods here are used to filter, order, and constrain results.

+
+
+class cassandra.cqlengine.query.ModelQuerySet(model)
+
+
+all()
+

Returns a queryset matching all rows

+
for user in User.objects().all():
+    print(user)
+
+
+
+ +
+
+batch(batch_obj)
+

Set a batch object to run the query on.

+

Note: running a select query with a batch object will raise an exception

+
+ +
+
+consistency(consistency)
+

Sets the consistency level for the operation. See ConsistencyLevel.

+
for user in User.objects(id=3).consistency(CL.ONE):
+    print(user)
+
+
+
+ +
+
+count()
+

Returns the number of rows matched by this query.

+

Note: This function executes a SELECT COUNT() and has a performance cost on large datasets

+
+ +
+
+len(queryset)
+

Returns the number of rows matched by this query. This function uses count() internally.

+

Note: This function executes a SELECT COUNT() and has a performance cost on large datasets

+
+ +
+
+distinct(distinct_fields=None)
+

Returns the DISTINCT rows matched by this query.

+

distinct_fields default to the partition key fields if not specified.

+

Note: distinct_fields must be a partition key or a static column

+
class Automobile(Model):
+    manufacturer = columns.Text(partition_key=True)
+    year = columns.Integer(primary_key=True)
+    model = columns.Text(primary_key=True)
+    price = columns.Decimal()
+
+sync_table(Automobile)
+
+# create rows
+
+Automobile.objects.distinct()
+
+# or
+
+Automobile.objects.distinct(['manufacturer'])
+
+
+
+ +
+
+filter(*args, **kwargs)
+

Adds WHERE arguments to the queryset, returning a new queryset

+

See Retrieving objects with filters

+

Returns a QuerySet filtered on the keyword arguments

+
+ +
+
+get(*args, **kwargs)
+

Returns a single instance matching this query, optionally with additional filter kwargs.

+

See Retrieving objects with filters

+

Returns a single object matching the QuerySet.

+
user = User.get(id=1)
+
+
+

If no objects are matched, a DoesNotExist exception is raised.

+

If more than one object is found, a MultipleObjectsReturned exception is raised.

+
+ +
+
+limit(v)
+

Limits the number of results returned by Cassandra. Use 0 or None to disable.

+

Note that CQL’s default limit is 10,000, so all queries without a limit set explicitly will have an implicit limit of 10,000

+
# Fetch 100 users
+for user in User.objects().limit(100):
+    print(user)
+
+# Fetch all users
+for user in User.objects().limit(None):
+    print(user)
+
+
+
+ +
+
+fetch_size(v)
+

Sets the number of rows that are fetched at a time.

+

Note that driver’s default fetch size is 5000.

+
for user in User.objects().fetch_size(500):
+    print(user)
+
+
+
+ +
+
+if_not_exists()
+

Check the existence of an object before insertion.

+

If the insertion isn’t applied, a LWTException is raised.

+
+ +
+
+if_exists()
+

Check the existence of an object before an update or delete.

+

If the update or delete isn’t applied, a LWTException is raised.

+
+ +
+
+order_by(*colnames)
+

Sets the column(s) to be used for ordering

+

Default order is ascending, prepend a ‘-’ to any column name for descending

+

Note: column names must be a clustering key

+
from uuid import uuid1,uuid4
+
+class Comment(Model):
+    photo_id = UUID(primary_key=True)
+    comment_id = TimeUUID(primary_key=True, default=uuid1) # second primary key component is a clustering key
+    comment = Text()
+
+sync_table(Comment)
+
+u = uuid4()
+for x in range(5):
+    Comment.create(photo_id=u, comment="test %d" % x)
+
+print("Normal")
+for comment in Comment.objects(photo_id=u):
+    print comment.comment_id
+
+print("Reversed")
+for comment in Comment.objects(photo_id=u).order_by("-comment_id"):
+    print comment.comment_id
+
+
+
+ +
+
+allow_filtering()
+

Enables the (usually) unwise practive of querying on a clustering key without also defining a partition key

+
+ +
+
+only(fields)
+

Load only these fields for the returned query

+
+ +
+
+defer(fields)
+

Don’t load these fields for the returned query

+
+ +
+
+timestamp(timestamp)
+

Allows for custom timestamps to be saved with the record.

+
+ +
+
+ttl(ttl)
+

Sets the ttl (in seconds) for modified data.

+

Note that running a select query with a ttl value will raise an exception

+
+ +
+
+using(keyspace=None, connection=None)
+

Change the context on-the-fly of the Model class (keyspace, connection)

+
+ +
+
+update(**values)
+

Performs an update on the row selected by the queryset. Include values to update in the +update like so:

+
Model.objects(key=n).update(value='x')
+
+
+

Passing in updates for columns which are not part of the model will raise a ValidationError.

+

Per column validation will be performed, but instance level validation will not +(i.e., Model.validate is not called). This is sometimes referred to as a blind update.

+

For example:

+
class User(Model):
+    id = Integer(primary_key=True)
+    name = Text()
+
+setup(["localhost"], "test")
+sync_table(User)
+
+u = User.create(id=1, name="jon")
+
+User.objects(id=1).update(name="Steve")
+
+# sets name to null
+User.objects(id=1).update(name=None)
+
+
+

Also supported is blindly adding and removing elements from container columns, +without loading a model instance from Cassandra.

+

Using the syntax .update(column_name={x, y, z}) will overwrite the contents of the container, like updating a +non container column. However, adding __<operation> to the end of the keyword arg, makes the update call add +or remove items from the collection, without overwriting then entire column.

+

Given the model below, here are the operations that can be performed on the different container columns:

+
class Row(Model):
+    row_id      = columns.Integer(primary_key=True)
+    set_column  = columns.Set(Integer)
+    list_column = columns.List(Integer)
+    map_column  = columns.Map(Integer, Integer)
+
+
+

Set

+
    +
  • add: adds the elements of the given set to the column

  • +
  • remove: removes the elements of the given set to the column

  • +
+
# add elements to a set
+Row.objects(row_id=5).update(set_column__add={6})
+
+# remove elements to a set
+Row.objects(row_id=5).update(set_column__remove={4})
+
+
+

List

+
    +
  • append: appends the elements of the given list to the end of the column

  • +
  • prepend: prepends the elements of the given list to the beginning of the column

  • +
+
# append items to a list
+Row.objects(row_id=5).update(list_column__append=[6, 7])
+
+# prepend items to a list
+Row.objects(row_id=5).update(list_column__prepend=[1, 2])
+
+
+

Map

+
    +
  • update: adds the given keys/values to the columns, creating new entries if they didn’t exist, and overwriting old ones if they did

  • +
+
# add items to a map
+Row.objects(row_id=5).update(map_column__update={1: 2, 3: 4})
+
+# remove items from a map
+Row.objects(row_id=5).update(map_column__remove={1, 2})
+
+
+
+ +
+ +
+
+class cassandra.cqlengine.query.BatchQuery(batch_type=None, timestamp=None, consistency=None, execute_on_exception=False, timeout=<object object>, connection=None)
+

Handles the batching of queries

+

http://docs.datastax.com/en/cql/3.0/cql/cql_reference/batch_r.html

+

See Batch Queries for more details.

+
+
Parameters
+
    +
  • batch_type (BatchType, str or None) – (optional) One of batch type values available through BatchType enum

  • +
  • timestamp (datetime or timedelta or None) – (optional) A datetime or timedelta object with desired timestamp to be applied +to the batch conditional.

  • +
  • consistency (The ConsistencyLevel to be used for the batch query, or None.) – (optional) One of consistency values (“ANY”, “ONE”, “QUORUM” etc)

  • +
  • execute_on_exception (bool) – (Defaults to False) Indicates that when the BatchQuery instance is used +as a context manager the queries accumulated within the context must be executed despite +encountering an error within the context. By default, any exception raised from within +the context scope will cause the batched queries not to be executed.

  • +
  • timeout (float or None) – (optional) Timeout for the entire batch (in seconds), if not specified fallback +to default session timeout

  • +
  • connection (str) – Connection name to use for the batch execution

  • +
+
+
+
+
+add_query(query)
+
+ +
+
+execute()
+
+ +
+
+add_callback(fn, *args, **kwargs)
+

Add a function and arguments to be passed to it to be executed after the batch executes.

+

A batch can support multiple callbacks.

+

Note, that if the batch does not execute, the callbacks are not executed. +A callback, thus, is an “on batch success” handler.

+
+
Parameters
+
    +
  • fn (callable) – Callable object

  • +
  • *args – Positional arguments to be passed to the callback at the time of execution

  • +
  • **kwargs – Named arguments to be passed to the callback at the time of execution

  • +
+
+
+
+ +
+ +
+
+class cassandra.cqlengine.query.ContextQuery(*args, **kwargs)
+

A Context manager to allow a Model to switch context easily. Presently, the context only +specifies a keyspace for model IO.

+
+
Parameters
+
    +
  • *args – One or more models. A model should be a class type, not an instance.

  • +
  • **kwargs – (optional) Context parameters: can be keyspace or connection

  • +
+
+
+

For example:

+
with ContextQuery(Automobile, keyspace='test2') as A:
+    A.objects.create(manufacturer='honda', year=2008, model='civic')
+    print len(A.objects.all())  # 1 result
+
+with ContextQuery(Automobile, keyspace='test4') as A:
+    print len(A.objects.all())  # 0 result
+
+# Multiple models
+with ContextQuery(Automobile, Automobile2, connection='cluster2') as (A, A2):
+    print len(A.objects.all())
+    print len(A2.objects.all())
+
+
+
+ +
+
+class cassandra.cqlengine.query.DoesNotExist
+
+ +
+
+class cassandra.cqlengine.query.MultipleObjectsReturned
+
+ +
+
+class cassandra.cqlengine.query.LWTException(existing)
+

Lightweight conditional exception.

+

This exception will be raised when a write using an IF clause could not be +applied due to existing data violating the condition. The existing data is +available through the existing attribute.

+
+
Parameters
+

existing – The current state of the data which prevented the write.

+
+
+
+ +
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/stable/api/cassandra/cqlengine/usertype.html b/stable/api/cassandra/cqlengine/usertype.html new file mode 100644 index 0000000000..9f63dbba70 --- /dev/null +++ b/stable/api/cassandra/cqlengine/usertype.html @@ -0,0 +1,674 @@ + + + + + + + + + + + + + cassandra.cqlengine.usertype - Model classes for User Defined Types | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + + + +
+ +
+ +
+

cassandra.cqlengine.usertype - Model classes for User Defined Types

+
+

UserType

+
+
+class cassandra.cqlengine.usertype.UserType(**values)
+

This class is used to model User Defined Types. To define a type, declare a class inheriting from this, +and assign field types as class attributes:

+
# connect with default keyspace ...
+
+from cassandra.cqlengine.columns import Text, Integer
+from cassandra.cqlengine.usertype import UserType
+
+class address(UserType):
+    street = Text()
+    zipcode = Integer()
+
+from cassandra.cqlengine import management
+management.sync_type(address)
+
+
+

Please see User Defined Types for a complete example and discussion.

+
+
+__type_name__ = None
+

Optional. Sets the name of the CQL type for this type.

+

If not specified, the type name will be the name of the class, with it’s module name as it’s prefix.

+
+ +
+ +
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/stable/api/cassandra/datastax/graph/fluent/index.html b/stable/api/cassandra/datastax/graph/fluent/index.html new file mode 100644 index 0000000000..f84447d2ca --- /dev/null +++ b/stable/api/cassandra/datastax/graph/fluent/index.html @@ -0,0 +1,748 @@ + + + + + + + + + + + + + cassandra.datastax.graph.fluent | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + + + +
+ +
+ +
+

cassandra.datastax.graph.fluent

+
+
+class cassandra.datastax.graph.fluent.DseGraph
+

Dse Graph utility class for GraphTraversal construction and execution.

+
+
+DSE_GRAPH_QUERY_LANGUAGE = 'bytecode-json'
+

Graph query language, Default is ‘bytecode-json’ (GraphSON).

+
+ +
+
+static create_execution_profile(graph_name, graph_protocol=b'graphson-2.0', **kwargs)
+

Creates an ExecutionProfile for GraphTraversal execution. You need to register that execution profile to the +cluster by using cluster.add_execution_profile.

+
+
Parameters
+
    +
  • graph_name – The graph name

  • +
  • graph_protocol – (Optional) The graph protocol, default is DSE_GRAPH_QUERY_PROTOCOL.

  • +
+
+
+
+ +
+
+static query_from_traversal(traversal, graph_protocol=b'graphson-2.0', context=None)
+

From a GraphTraversal, return a query string based on the language specified in DseGraph.DSE_GRAPH_QUERY_LANGUAGE.

+
+
Parameters
+
    +
  • traversal – The GraphTraversal object

  • +
  • graph_protocol – The graph protocol. Default is DseGraph.DSE_GRAPH_QUERY_PROTOCOL.

  • +
  • context – The dict of the serialization context, needed for GraphSON3 (tuple, udt). +e.g: {‘cluster’: cluster, ‘graph_name’: name}

  • +
+
+
+
+ +
+
+static traversal_source(session=None, graph_name=None, execution_profile=EXEC_PROFILE_GRAPH_DEFAULT, traversal_class=None)
+

Returns a TinkerPop GraphTraversalSource binded to the session and graph_name if provided.

+
+
Parameters
+
    +
  • session – (Optional) A DSE session

  • +
  • graph_name – (Optional) DSE Graph name

  • +
  • execution_profile – (Optional) Execution profile for traversal queries. Default is set to EXEC_PROFILE_GRAPH_DEFAULT.

  • +
  • traversal_class – (Optional) The GraphTraversalSource class to use (DSL).

  • +
+
+
+
from cassandra.cluster import Cluster
+from cassandra.datastax.graph.fluent import DseGraph
+
+c = Cluster()
+session = c.connect()
+
+g = DseGraph.traversal_source(session, 'my_graph')
+print g.V().valueMap().toList()
+
+
+
+ +
+
+static batch(session=None, execution_profile=None)
+

Returns the cassandra.datastax.graph.fluent.query.TraversalBatch object allowing to +execute multiple traversals in the same transaction.

+
+ +
+ +
+
+class cassandra.datastax.graph.fluent.DSESessionRemoteGraphConnection(session[, graph_name, execution_profile])
+

A Tinkerpop RemoteConnection to execute traversal queries on DSE.

+
+
Parameters
+
    +
  • session – A DSE session

  • +
  • graph_name – (Optional) DSE Graph name.

  • +
  • execution_profile – (Optional) Execution profile for traversal queries. Default is set to EXEC_PROFILE_GRAPH_DEFAULT.

  • +
+
+
+
+ +
+
+class cassandra.datastax.graph.fluent.BaseGraphRowFactory(cluster)
+

Base row factory for graph traversal. This class basically wraps a +graphson reader function to handle additional features of Gremlin/DSE +and is callable as a normal row factory.

+
+
Currently supported:
    +
  • bulk results

  • +
+
+
+
+ +
+
+cassandra.datastax.graph.fluent.graph_traversal_row_factory
+

alias of cassandra.datastax.graph.fluent._GremlinGraphSON2RowFactory

+
+ +
+
+cassandra.datastax.graph.fluent.graph_traversal_dse_object_row_factory
+

alias of cassandra.datastax.graph.fluent._DseGraphSON2RowFactory

+
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/stable/api/cassandra/datastax/graph/fluent/predicates.html b/stable/api/cassandra/datastax/graph/fluent/predicates.html new file mode 100644 index 0000000000..ad7cad230c --- /dev/null +++ b/stable/api/cassandra/datastax/graph/fluent/predicates.html @@ -0,0 +1,744 @@ + + + + + + + + + + + + + cassandra.datastax.graph.fluent.predicates | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + + + +
+ +
+ +
+

cassandra.datastax.graph.fluent.predicates

+
+
+class cassandra.datastax.graph.fluent.predicates.Search
+
+
+static token(value)
+

Search any instance of a certain token within the text property targeted. +:param value: the value to look for.

+
+ +
+
+static token_prefix(value)
+

Search any instance of a certain token prefix withing the text property targeted. +:param value: the value to look for.

+
+ +
+
+static token_regex(value)
+

Search any instance of the provided regular expression for the targeted property. +:param value: the value to look for.

+
+ +
+
+static prefix(value)
+

Search for a specific prefix at the beginning of the text property targeted. +:param value: the value to look for.

+
+ +
+
+static regex(value)
+

Search for this regular expression inside the text property targeted. +:param value: the value to look for.

+
+ +
+
+static fuzzy(value, distance)
+

Search for a fuzzy string inside the text property targeted. +:param value: the value to look for. +:param distance: The distance for the fuzzy search. ie. 1, to allow a one-letter misspellings.

+
+ +
+
+static token_fuzzy(value, distance)
+

Search for a token fuzzy inside the text property targeted. +:param value: the value to look for. +:param distance: The distance for the token fuzzy search. ie. 1, to allow a one-letter misspellings.

+
+ +
+
+static phrase(value, proximity)
+

Search for a phrase inside the text property targeted. +:param value: the value to look for. +:param proximity: The proximity for the phrase search. ie. phrase(‘David Felcey’, 2).. to find ‘David Felcey’ with up to two middle names.

+
+ +
+ +
+
+class cassandra.datastax.graph.fluent.predicates.CqlCollection
+
+
+static contains(value)
+

Search for a value inside a cql list/set column. +:param value: the value to look for.

+
+ +
+
+static contains_value(value)
+

Search for a map value. +:param value: the value to look for.

+
+ +
+
+static contains_key(value)
+

Search for a map key. +:param value: the value to look for.

+
+ +
+
+static entry_eq(value)
+

Search for a map entry. +:param value: the value to look for.

+
+ +
+ +
+
+class cassandra.datastax.graph.fluent.predicates.Geo
+
+
+static inside(value, units=1)
+

Search any instance of geometry inside the Distance targeted. +:param value: A Distance to look for. +:param units: The units for value. See GeoUnit enum. (Can also +provide an integer to use as a multiplier to convert value to +degrees.)

+
+ +
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/stable/api/cassandra/datastax/graph/fluent/query.html b/stable/api/cassandra/datastax/graph/fluent/query.html new file mode 100644 index 0000000000..d7ed43bfb3 --- /dev/null +++ b/stable/api/cassandra/datastax/graph/fluent/query.html @@ -0,0 +1,695 @@ + + + + + + + + + + + + + cassandra.datastax.graph.fluent.query | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + + + +
+ +
+ +
+

cassandra.datastax.graph.fluent.query

+
+
+class cassandra.datastax.graph.fluent.query.TraversalBatch(session=None, execution_profile=None)
+

A TraversalBatch is used to execute multiple graph traversals in a +single transaction. If any traversal in the batch fails, the entire +batch will fail to apply.

+

If a TraversalBatch is bounded to a DSE session, it can be executed using +traversal_batch.execute().

+
+
Parameters
+
    +
  • session – (Optional) A DSE session

  • +
  • execution_profile – (Optional) The execution profile to use for the batch execution

  • +
+
+
+
+
+add(traversal)
+

Add a traversal to the batch.

+
+
Parameters
+

traversal – A gremlin GraphTraversal

+
+
+
+ +
+
+add_all(traversals)
+

Adds a sequence of traversals to the batch.

+
+
Parameters
+

traversals – A sequence of gremlin GraphTraversal

+
+
+
+ +
+
+execute()
+

Execute the traversal batch if bounded to a DSE Session.

+
+ +
+
+as_graph_statement(graph_protocol=b'graphson-2.0')
+

Return the traversal batch as GraphStatement.

+
+
Parameters
+

graph_protocol – The graph protocol for the GraphSONWriter. Default is GraphProtocol.GRAPHSON_2_0.

+
+
+
+ +
+
+clear()
+

Clear a traversal batch for reuse.

+
+ +
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/stable/api/cassandra/datastax/graph/index.html b/stable/api/cassandra/datastax/graph/index.html new file mode 100644 index 0000000000..9a0ea62ae3 --- /dev/null +++ b/stable/api/cassandra/datastax/graph/index.html @@ -0,0 +1,1026 @@ + + + + + + + + + + + + + cassandra.datastax.graph - Graph Statements, Options, and Row Factories | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + + + +
+ +
+ +
+

cassandra.datastax.graph - Graph Statements, Options, and Row Factories

+
+
+cassandra.datastax.graph.single_object_row_factory(column_names, rows)
+

returns the JSON string value of graph results

+
+ +
+
+cassandra.datastax.graph.graph_result_row_factory(column_names, rows)
+

Returns a Result object that can load graph results and produce specific types. +The Result JSON is deserialized and unpacked from the top-level ‘result’ dict.

+
+ +
+
+cassandra.datastax.graph.graph_object_row_factory(column_names, rows)
+

Like graph_result_row_factory(), except known element types (Vertex, Edge) are +converted to their simplified objects. Some low-level metadata is shed in this conversion. Unknown result types are +still returned as Result.

+
+ +
+
+cassandra.datastax.graph.graph_graphson2_row_factory(cluster)
+

Row factory to deserialize GraphSON2 results.

+
+ +
+
+cassandra.datastax.graph.graph_graphson3_row_factory(cluster)
+

Row factory to deserialize GraphSON3 results.

+
+ +
+
+cassandra.datastax.graph.to_int(value)
+

Wraps a value to be explicitly serialized as a graphson Int.

+
+ +
+
+cassandra.datastax.graph.to_bigint(value)
+

Wraps a value to be explicitly serialized as a graphson Bigint.

+
+ +
+
+cassandra.datastax.graph.to_smallint(value)
+

Wraps a value to be explicitly serialized as a graphson Smallint.

+
+ +
+
+cassandra.datastax.graph.to_float(value)
+

Wraps a value to be explicitly serialized as a graphson Float.

+
+ +
+
+cassandra.datastax.graph.to_double(value)
+

Wraps a value to be explicitly serialized as a graphson Double.

+
+ +
+
+class cassandra.datastax.graph.GraphProtocol
+
+
+GRAPHSON_1_0 = b'graphson-1.0'
+

GraphSON1

+
+ +
+
+GRAPHSON_2_0 = b'graphson-2.0'
+

GraphSON2

+
+ +
+
+GRAPHSON_3_0 = b'graphson-3.0'
+

GraphSON3

+
+ +
+ +
+
+class cassandra.datastax.graph.GraphOptions(**kwargs)
+

Options for DSE Graph Query handler.

+
+
+graph_name
+

name of the targeted graph.

+
+ +
+
+graph_source
+

choose the graph traversal source, configured on the server side.

+
+ +
+
+graph_language
+

the language used in the queries (default “gremlin-groovy”)

+
+ +
+
+graph_read_consistency_level
+

read cassandra.ConsistencyLevel for graph queries (if distinct from session default). +Setting this overrides the native Statement.consistency_level for read operations from Cassandra persistence

+
+ +
+
+graph_write_consistency_level
+

write cassandra.ConsistencyLevel for graph queries (if distinct from session default). +Setting this overrides the native Statement.consistency_level for write operations to Cassandra persistence.

+
+ +
+
+is_default_source
+
+ +
+
+is_analytics_source
+

True if graph_source is set to the server-defined analytics traversal source (‘a’)

+
+ +
+
+is_graph_source
+

True if graph_source is set to the server-defined graph traversal source (‘g’)

+
+ +
+
+set_source_default()
+

Sets graph_source to the server-defined default traversal source (‘default’)

+
+ +
+
+set_source_analytics()
+

Sets graph_source to the server-defined analytic traversal source (‘a’)

+
+ +
+
+set_source_graph()
+

Sets graph_source to the server-defined graph traversal source (‘g’)

+
+ +
+ +
+
+class cassandra.datastax.graph.SimpleGraphStatement(query_string, retry_policy=None, consistency_level=None, routing_key=None, serial_consistency_level=None, fetch_size=<object object>, keyspace=None, custom_payload=None, is_idempotent=False)
+

Simple graph statement for Session.execute_graph(). +Takes the same parameters as SimpleStatement.

+

query_string should be a literal CQL statement with the exception +of parameter placeholders that will be filled through the +parameters argument of Session.execute().

+

See Statement attributes for a description of the other parameters.

+
+ +
+
+class cassandra.datastax.graph.Result(value)
+

Represents deserialized graph results. +Property and item getters are provided for convenience.

+
+
+value = None
+

Deserialized value from the result

+
+ +
+
+as_vertex()
+

Return a Vertex parsed from this result

+

Raises TypeError if parsing fails (i.e. the result structure is not valid).

+
+ +
+
+as_edge()
+

Return a Edge parsed from this result

+

Raises TypeError if parsing fails (i.e. the result structure is not valid).

+
+ +
+
+as_path()
+

Return a Path parsed from this result

+

Raises TypeError if parsing fails (i.e. the result structure is not valid).

+
+ +
+ +
+
+class cassandra.datastax.graph.Vertex(id, label, type, properties)
+

Represents a Vertex element from a graph query.

+

Vertex properties are extracted into a dict of property names to list of VertexProperty (list +because they are always encoded that way, and sometimes have multiple cardinality; VertexProperty because sometimes +the properties themselves have property maps).

+
+ +
+
+class cassandra.datastax.graph.VertexProperty(label, value, properties=None)
+

Vertex properties have a top-level value and an optional dict of properties.

+
+
+label = None
+

label of the property

+
+ +
+
+value = None
+

Value of the property

+
+ +
+
+properties = None
+

dict of properties attached to the property

+
+ +
+ +
+
+class cassandra.datastax.graph.Edge(id, label, type, properties, inV, inVLabel, outV, outVLabel)
+

Represents an Edge element from a graph query.

+

Attributes match initializer parameters.

+
+ +
+
+class cassandra.datastax.graph.Path(labels, objects)
+

Represents a graph path.

+

Labels list is taken verbatim from the results.

+

Objects are either Result or Vertex/Edge for recognized types

+
+
+labels = None
+

List of labels in the path

+
+ +
+
+objects = None
+

List of objects in the path

+
+ +
+ +
+
+class cassandra.datastax.graph.T(name, val)
+

Represents a collection of tokens for more concise Traversal definitions.

+
+
+id = T.id
+
+ +
+
+key = T.key
+
+ +
+
+label = T.label
+
+ +
+
+value = T.value
+
+ +
+ +
+
+class cassandra.datastax.graph.GraphSON1Serializer
+

Serialize python objects to graphson types.

+
+ +
+
+class cassandra.datastax.graph.GraphSON1Deserializer
+

Deserialize graphson1 types to python objects.

+
+
+classmethod deserialize_date(value)
+
+ +
+
+classmethod deserialize_timestamp(value)
+
+ +
+
+classmethod deserialize_time(value)
+
+ +
+
+classmethod deserialize_duration(value)
+
+ +
+
+classmethod deserialize_int(value)
+
+ +
+
+classmethod deserialize_bigint(value)
+
+ +
+
+classmethod deserialize_double(value)
+
+ +
+
+classmethod deserialize_float(value)
+
+ +
+
+classmethod deserialize_uuid(value)
+
+ +
+
+classmethod deserialize_blob(value)
+
+ +
+
+classmethod deserialize_decimal(value)
+
+ +
+
+classmethod deserialize_point(value)
+
+ +
+
+classmethod deserialize_linestring(value)
+
+ +
+
+classmethod deserialize_polygon(value)
+
+ +
+ +
+
+class cassandra.datastax.graph.GraphSON2Reader(context, extra_deserializer_map=None)
+

GraphSON2 Reader that parse json and deserialize to python objects.

+
+
Parameters
+

extra_deserializer_map – map from GraphSON type tag to deserializer instance implementing deserialize

+
+
+
+
+read(json_data)
+

Read and deserialize json_data.

+
+ +
+
+deserialize(obj)
+

Deserialize GraphSON type-tagged dict values into objects mapped in self.deserializers

+
+ +
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/stable/api/cassandra/decoder.html b/stable/api/cassandra/decoder.html new file mode 100644 index 0000000000..98ba97340d --- /dev/null +++ b/stable/api/cassandra/decoder.html @@ -0,0 +1,656 @@ + + + + + + + + + + + + + cassandra.decoder - Data Return Formats | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + + + +
+ +
+ +
+

cassandra.decoder - Data Return Formats

+
+
+cassandra.decoder.tuple_factory()
+

Deprecated in 2.0.0. Use cassandra.query.tuple_factory()

+
+ +
+
+cassandra.decoder.named_tuple_factory()
+

Deprecated in 2.0.0. Use cassandra.query.named_tuple_factory()

+
+ +
+
+cassandra.decoder.dict_factory()
+

Deprecated in 2.0.0. Use cassandra.query.dict_factory()

+
+ +
+
+cassandra.decoder.ordered_dict_factory()
+

Deprecated in 2.0.0. Use cassandra.query.ordered_dict_factory()

+
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/stable/api/cassandra/encoder.html b/stable/api/cassandra/encoder.html new file mode 100644 index 0000000000..98627bcb3d --- /dev/null +++ b/stable/api/cassandra/encoder.html @@ -0,0 +1,733 @@ + + + + + + + + + + + + + cassandra.encoder - Encoders for non-prepared Statements | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + + + +
+ +
+ +
+

cassandra.encoder - Encoders for non-prepared Statements

+
+
+class cassandra.encoder.Encoder
+

A container for mapping python types to CQL string literals when working +with non-prepared statements. The type mapping can be +directly customized by users.

+
+
+mapping = None
+

A map of python types to encoder functions.

+
+ +
+
+cql_encode_none()
+

Converts None to the string ‘NULL’.

+
+ +
+
+cql_encode_object()
+

Default encoder for all objects that do not have a specific encoder function +registered. This function simply calls str() on the object.

+
+ +
+
+cql_encode_all_types()
+

Converts any type into a CQL string, defaulting to cql_encode_object +if mapping does not contain an entry for the type.

+
+ +
+
+cql_encode_sequence()
+

Converts a sequence to a string of the form (item1, item2, ...). This +is suitable for IN value lists.

+
+ +
+
+cql_encode_str()
+

Escapes quotes in str objects.

+
+ +
+
+cql_encode_unicode()
+

Converts unicode objects to UTF-8 encoded strings with quote escaping.

+
+ +
+
+cql_encode_bytes()
+

Converts strings, buffers, and bytearrays into CQL blob literals.

+
+ +
+
+cql_encode_datetime()
+

Converts a datetime.datetime object to a (string) integer timestamp +with millisecond precision.

+
+ +
+
+cql_encode_date()
+

Converts a datetime.date object to a string with format +YYYY-MM-DD.

+
+ +
+
+cql_encode_map_collection()
+

Converts a dict into a string of the form {key1: val1, key2: val2, ...}. +This is suitable for map type columns.

+
+ +
+
+cql_encode_list_collection()
+

Converts a sequence to a string of the form [item1, item2, ...]. This +is suitable for list type columns.

+
+ +
+
+cql_encode_set_collection()
+

Converts a sequence to a string of the form {item1, item2, ...}. This +is suitable for set type columns.

+
+ +
+
+cql_encode_tuple()
+

Converts a sequence to a string of the form (item1, item2, ...). This +is suitable for tuple type columns.

+
+ +
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/stable/api/cassandra/graph.html b/stable/api/cassandra/graph.html new file mode 100644 index 0000000000..22caee0996 --- /dev/null +++ b/stable/api/cassandra/graph.html @@ -0,0 +1,1019 @@ + + + + + + + + + + + + + cassandra.graph - Graph Statements, Options, and Row Factories | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + + + +
+ +
+ +
+

cassandra.graph - Graph Statements, Options, and Row Factories

+
+

Note

+

This module is only for backward compatibility for dse-driver users. Consider using cassandra.datastax.graph.

+
+
+
+cassandra.graph.single_object_row_factory(column_names, rows)
+

returns the JSON string value of graph results

+
+ +
+
+cassandra.graph.graph_result_row_factory(column_names, rows)
+

Returns a Result object that can load graph results and produce specific types. +The Result JSON is deserialized and unpacked from the top-level ‘result’ dict.

+
+ +
+
+cassandra.graph.graph_object_row_factory(column_names, rows)
+

Like graph_result_row_factory(), except known element types (Vertex, Edge) are +converted to their simplified objects. Some low-level metadata is shed in this conversion. Unknown result types are +still returned as Result.

+
+ +
+
+cassandra.graph.graph_graphson2_row_factory(cluster)
+

Row factory to deserialize GraphSON2 results.

+
+ +
+
+cassandra.graph.graph_graphson3_row_factory(cluster)
+

Row factory to deserialize GraphSON3 results.

+
+ +
+
+cassandra.graph.to_int(value)
+

Wraps a value to be explicitly serialized as a graphson Int.

+
+ +
+
+cassandra.graph.to_bigint(value)
+

Wraps a value to be explicitly serialized as a graphson Bigint.

+
+ +
+
+cassandra.graph.to_smallint(value)
+

Wraps a value to be explicitly serialized as a graphson Smallint.

+
+ +
+
+cassandra.graph.to_float(value)
+

Wraps a value to be explicitly serialized as a graphson Float.

+
+ +
+
+cassandra.graph.to_double(value)
+

Wraps a value to be explicitly serialized as a graphson Double.

+
+ +
+
+class cassandra.graph.GraphProtocol
+
+
+GRAPHSON_1_0 = b'graphson-1.0'
+

GraphSON1

+
+ +
+
+GRAPHSON_2_0 = b'graphson-2.0'
+

GraphSON2

+
+ +
+
+GRAPHSON_3_0 = b'graphson-3.0'
+

GraphSON3

+
+ +
+ +
+
+class cassandra.graph.GraphOptions(**kwargs)
+

Options for DSE Graph Query handler.

+
+
+graph_name
+

name of the targeted graph.

+
+ +
+
+graph_source
+

choose the graph traversal source, configured on the server side.

+
+ +
+
+graph_language
+

the language used in the queries (default “gremlin-groovy”)

+
+ +
+
+graph_read_consistency_level
+

read cassandra.ConsistencyLevel for graph queries (if distinct from session default). +Setting this overrides the native Statement.consistency_level for read operations from Cassandra persistence

+
+ +
+
+graph_write_consistency_level
+

write cassandra.ConsistencyLevel for graph queries (if distinct from session default). +Setting this overrides the native Statement.consistency_level for write operations to Cassandra persistence.

+
+ +
+
+is_default_source
+
+ +
+
+is_analytics_source
+

True if graph_source is set to the server-defined analytics traversal source (‘a’)

+
+ +
+
+is_graph_source
+

True if graph_source is set to the server-defined graph traversal source (‘g’)

+
+ +
+
+set_source_default()
+

Sets graph_source to the server-defined default traversal source (‘default’)

+
+ +
+
+set_source_analytics()
+

Sets graph_source to the server-defined analytic traversal source (‘a’)

+
+ +
+
+set_source_graph()
+

Sets graph_source to the server-defined graph traversal source (‘g’)

+
+ +
+ +
+
+class cassandra.graph.SimpleGraphStatement(query_string, retry_policy=None, consistency_level=None, routing_key=None, serial_consistency_level=None, fetch_size=<object object>, keyspace=None, custom_payload=None, is_idempotent=False)
+

Simple graph statement for Session.execute_graph(). +Takes the same parameters as SimpleStatement.

+

query_string should be a literal CQL statement with the exception +of parameter placeholders that will be filled through the +parameters argument of Session.execute().

+

See Statement attributes for a description of the other parameters.

+
+ +
+
+class cassandra.graph.Result(value)
+

Represents deserialized graph results. +Property and item getters are provided for convenience.

+
+
+value = None
+

Deserialized value from the result

+
+ +
+
+as_vertex()
+

Return a Vertex parsed from this result

+

Raises TypeError if parsing fails (i.e. the result structure is not valid).

+
+ +
+
+as_edge()
+

Return a Edge parsed from this result

+

Raises TypeError if parsing fails (i.e. the result structure is not valid).

+
+ +
+
+as_path()
+

Return a Path parsed from this result

+

Raises TypeError if parsing fails (i.e. the result structure is not valid).

+
+ +
+ +
+
+class cassandra.graph.Vertex(id, label, type, properties)
+

Represents a Vertex element from a graph query.

+

Vertex properties are extracted into a dict of property names to list of VertexProperty (list +because they are always encoded that way, and sometimes have multiple cardinality; VertexProperty because sometimes +the properties themselves have property maps).

+
+ +
+
+class cassandra.graph.VertexProperty(label, value, properties=None)
+

Vertex properties have a top-level value and an optional dict of properties.

+
+
+label = None
+

label of the property

+
+ +
+
+value = None
+

Value of the property

+
+ +
+
+properties = None
+

dict of properties attached to the property

+
+ +
+ +
+
+class cassandra.graph.Edge(id, label, type, properties, inV, inVLabel, outV, outVLabel)
+

Represents an Edge element from a graph query.

+

Attributes match initializer parameters.

+
+ +
+
+class cassandra.graph.Path(labels, objects)
+

Represents a graph path.

+

Labels list is taken verbatim from the results.

+

Objects are either Result or Vertex/Edge for recognized types

+
+
+labels = None
+

List of labels in the path

+
+ +
+
+objects = None
+

List of objects in the path

+
+ +
+ +
+
+class cassandra.graph.GraphSON1Serializer
+

Serialize python objects to graphson types.

+
+ +
+
+class cassandra.graph.GraphSON1Deserializer
+

Deserialize graphson1 types to python objects.

+
+
+classmethod deserialize_date(value)
+
+ +
+
+classmethod deserialize_timestamp(value)
+
+ +
+
+classmethod deserialize_time(value)
+
+ +
+
+classmethod deserialize_duration(value)
+
+ +
+
+classmethod deserialize_int(value)
+
+ +
+
+classmethod deserialize_bigint(value)
+
+ +
+
+classmethod deserialize_double(value)
+
+ +
+
+classmethod deserialize_float(value)
+
+ +
+
+classmethod deserialize_uuid(value)
+
+ +
+
+classmethod deserialize_blob(value)
+
+ +
+
+classmethod deserialize_decimal(value)
+
+ +
+
+classmethod deserialize_point(value)
+
+ +
+
+classmethod deserialize_linestring(value)
+
+ +
+
+classmethod deserialize_polygon(value)
+
+ +
+ +
+
+class cassandra.graph.GraphSON2Reader(context, extra_deserializer_map=None)
+

GraphSON2 Reader that parse json and deserialize to python objects.

+
+
Parameters
+

extra_deserializer_map – map from GraphSON type tag to deserializer instance implementing deserialize

+
+
+
+
+read(json_data)
+

Read and deserialize json_data.

+
+ +
+
+deserialize(obj)
+

Deserialize GraphSON type-tagged dict values into objects mapped in self.deserializers

+
+ +
+ +
+
+class cassandra.graph.GraphSON3Reader(context, extra_deserializer_map=None)
+

GraphSON3 Reader that parse json and deserialize to python objects.

+
+
Parameters
+
    +
  • context – A dict of the context, mostly used as context for udt deserialization.

  • +
  • extra_deserializer_map – map from GraphSON type tag to deserializer instance implementing deserialize

  • +
+
+
+
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/stable/api/cassandra/io/asyncioreactor.html b/stable/api/cassandra/io/asyncioreactor.html new file mode 100644 index 0000000000..7a84df30e5 --- /dev/null +++ b/stable/api/cassandra/io/asyncioreactor.html @@ -0,0 +1,648 @@ + + + + + + + + + + + + + cassandra.io.asyncioreactor - asyncio Event Loop | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + + + +
+ +
+ +
+

cassandra.io.asyncioreactor - asyncio Event Loop

+
+
+class cassandra.io.asyncioreactor.AsyncioConnection(*args, **kwargs)
+

An experimental implementation of Connection that uses the +asyncio module in the Python standard library for its event loop.

+

Note that it requires asyncio features that were only introduced in the +3.4 line in 3.4.6, and in the 3.5 line in 3.5.1.

+
+
+classmethod initialize_reactor()
+

Called once by Cluster.connect(). This should be used by implementations +to set up any resources that will be shared across connections.

+
+ +
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/stable/api/cassandra/io/asyncorereactor.html b/stable/api/cassandra/io/asyncorereactor.html new file mode 100644 index 0000000000..194895bc8f --- /dev/null +++ b/stable/api/cassandra/io/asyncorereactor.html @@ -0,0 +1,653 @@ + + + + + + + + + + + + + cassandra.io.asyncorereactor - asyncore Event Loop | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + + + +
+ +
+ +
+

cassandra.io.asyncorereactor - asyncore Event Loop

+
+
+class cassandra.io.asyncorereactor.AsyncoreConnection(*args, **kwargs)
+

An implementation of Connection that uses the asyncore +module in the Python standard library for its event loop.

+
+
+classmethod initialize_reactor()
+

Called once by Cluster.connect(). This should be used by implementations +to set up any resources that will be shared across connections.

+
+ +
+
+classmethod handle_fork()
+

Called after a forking. This should cleanup any remaining reactor state +from the parent process.

+
+ +
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/stable/api/cassandra/io/eventletreactor.html b/stable/api/cassandra/io/eventletreactor.html new file mode 100644 index 0000000000..3086314943 --- /dev/null +++ b/stable/api/cassandra/io/eventletreactor.html @@ -0,0 +1,655 @@ + + + + + + + + + + + + + cassandra.io.eventletreactor - eventlet-compatible Connection | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + + + +
+ +
+ +
+

cassandra.io.eventletreactor - eventlet-compatible Connection

+
+
+class cassandra.io.eventletreactor.EventletConnection(*args, **kwargs)
+

An implementation of Connection that utilizes eventlet.

+

This implementation assumes all eventlet monkey patching is active. It is not tested with partial patching.

+
+
+classmethod initialize_reactor()
+

Called once by Cluster.connect(). This should be used by implementations +to set up any resources that will be shared across connections.

+
+ +
+
+classmethod service_timeouts()
+

cls._timeout_watcher runs in this loop forever. +It is usually waiting for the next timeout on the cls._new_timer Event. +When new timers are added, that event is set so that the watcher can +wake up and possibly set an earlier timeout.

+
+ +
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/stable/api/cassandra/io/geventreactor.html b/stable/api/cassandra/io/geventreactor.html new file mode 100644 index 0000000000..0e7c87c005 --- /dev/null +++ b/stable/api/cassandra/io/geventreactor.html @@ -0,0 +1,646 @@ + + + + + + + + + + + + + cassandra.io.geventreactor - gevent-compatible Event Loop | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + + + +
+ +
+ +
+

cassandra.io.geventreactor - gevent-compatible Event Loop

+
+
+class cassandra.io.geventreactor.GeventConnection(*args, **kwargs)
+

An implementation of Connection that utilizes gevent.

+

This implementation assumes all gevent monkey patching is active. It is not tested with partial patching.

+
+
+classmethod initialize_reactor()
+

Called once by Cluster.connect(). This should be used by implementations +to set up any resources that will be shared across connections.

+
+ +
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/stable/api/cassandra/io/libevreactor.html b/stable/api/cassandra/io/libevreactor.html new file mode 100644 index 0000000000..b353911eff --- /dev/null +++ b/stable/api/cassandra/io/libevreactor.html @@ -0,0 +1,638 @@ + + + + + + + + + + + + + cassandra.io.libevreactor - libev Event Loop | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + + + +
+ +
+ +
+

cassandra.io.libevreactor - libev Event Loop

+
+
+class cassandra.io.libevreactor.LibevConnection(*args, **kwargs)
+

An implementation of Connection that uses libev for its event loop.

+
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/stable/api/cassandra/io/twistedreactor.html b/stable/api/cassandra/io/twistedreactor.html new file mode 100644 index 0000000000..a41178f50a --- /dev/null +++ b/stable/api/cassandra/io/twistedreactor.html @@ -0,0 +1,639 @@ + + + + + + + + + + + + + cassandra.io.twistedreactor - Twisted Event Loop | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + + + +
+ +
+ +
+

cassandra.io.twistedreactor - Twisted Event Loop

+
+
+class cassandra.io.twistedreactor.TwistedConnection
+

An implementation of Connection that uses +Twisted’s reactor as its event loop.

+
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/stable/api/cassandra/metadata.html b/stable/api/cassandra/metadata.html new file mode 100644 index 0000000000..71748d7cb5 --- /dev/null +++ b/stable/api/cassandra/metadata.html @@ -0,0 +1,1023 @@ + + + + + + + + + + + + + cassandra.metadata - Schema and Ring Topology | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + + + +
+ +
+ +
+

cassandra.metadata - Schema and Ring Topology

+
+
+cassandra.metadata.cql_keywords
+

set() -> new empty set object +set(iterable) -> new set object

+

Build an unordered collection of unique elements.

+
+ +
+
+cassandra.metadata.cql_keywords_unreserved
+

set() -> new empty set object +set(iterable) -> new set object

+

Build an unordered collection of unique elements.

+
+ +
+
+cassandra.metadata.cql_keywords_reserved
+

set() -> new empty set object +set(iterable) -> new set object

+

Build an unordered collection of unique elements.

+
+ +
+
+class cassandra.metadata.Metadata
+

Holds a representation of the cluster schema and topology.

+
+
+add_or_return_host(host)
+

Returns a tuple (host, new), where host is a Host +instance, and new is a bool indicating whether +the host was newly added.

+
+ +
+
+all_hosts()
+

Returns a list of all known Host instances in the cluster.

+
+ +
+
+export_schema_as_string()
+

Returns a string that can be executed as a query in order to recreate +the entire schema. The string is formatted to be human readable.

+
+ +
+
+get_host(endpoint_or_address, port=None)
+

Find a host in the metadata for a specific endpoint. If a string inet address and port are passed, +iterate all hosts to match the broadcast_rpc_address and +broadcast_rpc_port attributes.

+
+ +
+
+get_host_by_host_id(host_id)
+

Same as get_host() but use host_id for lookup.

+
+ +
+
+get_replicas(keyspace, key)
+

Returns a list of Host instances that are replicas for a given +partition key.

+
+ +
+ +
+

Schemas

+
+
+class cassandra.metadata.KeyspaceMetadata
+

A representation of the schema for a single keyspace.

+
+
+as_cql_query()
+

Returns a CQL query string that can be used to recreate just this keyspace, +not including user-defined types and tables.

+
+ +
+
+export_as_string()
+

Returns a CQL query string that can be used to recreate the entire keyspace, +including user-defined types and tables.

+
+ +
+ +
+
+class cassandra.metadata.UserType
+

A user defined type, as created by CREATE TYPE statements.

+

User-defined types were introduced in Cassandra 2.1.

+
+

New in version 2.1.0.

+
+
+
+as_cql_query(formatted=False)
+

Returns a CQL query that can be used to recreate this type. +If formatted is set to True, extra whitespace will +be added to make the query more readable.

+
+ +
+ +
+
+class cassandra.metadata.Function
+

A user defined function, as created by CREATE FUNCTION statements.

+

User-defined functions were introduced in Cassandra 2.2

+
+

New in version 2.6.0.

+
+
+
+as_cql_query(formatted=False)
+

Returns a CQL query that can be used to recreate this function. +If formatted is set to True, extra whitespace will +be added to make the query more readable.

+
+ +
+ +
+
+class cassandra.metadata.Aggregate
+

A user defined aggregate function, as created by CREATE AGGREGATE statements.

+

Aggregate functions were introduced in Cassandra 2.2

+
+

New in version 2.6.0.

+
+
+
+as_cql_query(formatted=False)
+

Returns a CQL query that can be used to recreate this aggregate. +If formatted is set to True, extra whitespace will +be added to make the query more readable.

+
+ +
+ +
+
+class cassandra.metadata.TableMetadata
+

A representation of the schema for a single table.

+
+
+as_cql_query(formatted=False)
+

Returns a CQL query that can be used to recreate this table (index +creations are not included). If formatted is set to True, +extra whitespace will be added to make the query human readable.

+
+ +
+
+export_as_string()
+

Returns a string of CQL queries that can be used to recreate this table +along with all indexes on it. The returned string is formatted to +be human readable.

+
+ +
+
+property is_cql_compatible
+

A boolean indicating if this table can be represented as CQL in export

+
+ +
+
+property primary_key
+

A list of ColumnMetadata representing the components of +the primary key for this table.

+
+ +
+ +
+
+class cassandra.metadata.TableMetadataV3
+

For C* 3.0+. option_maps take a superset of map names, so if nothing +changes structurally, new option maps can just be appended to the list.

+
+
+property is_cql_compatible
+

A boolean indicating if this table can be represented as CQL in export

+
+ +
+ +
+
+class cassandra.metadata.TableMetadataDSE68
+
+
+as_cql_query(formatted=False)
+

Returns a CQL query that can be used to recreate this table (index +creations are not included). If formatted is set to True, +extra whitespace will be added to make the query human readable.

+
+ +
+ +
+
+class cassandra.metadata.ColumnMetadata
+

A representation of a single column in a table.

+
+ +
+
+class cassandra.metadata.IndexMetadata
+

A representation of a secondary index on a column.

+
+
+as_cql_query()
+

Returns a CQL query that can be used to recreate this index.

+
+ +
+
+export_as_string()
+

Returns a CQL query string that can be used to recreate this index.

+
+ +
+ +
+
+class cassandra.metadata.MaterializedViewMetadata
+

A representation of a materialized view on a table

+
+
+as_cql_query(formatted=False)
+

Returns a CQL query that can be used to recreate this function. +If formatted is set to True, extra whitespace will +be added to make the query more readable.

+
+ +
+ +
+
+class cassandra.metadata.VertexMetadata
+

A representation of a vertex on a table

+
+ +
+
+class cassandra.metadata.EdgeMetadata
+

A representation of an edge on a table

+
+ +
+
+

Tokens and Ring Topology

+
+
+class cassandra.metadata.TokenMap
+

Information about the layout of the ring.

+
+
+get_replicas(keyspace, token)
+

Get a set of Host instances representing all of the +replica nodes for a given Token.

+
+ +
+ +
+
+class cassandra.metadata.Token
+

Abstract class representing a token.

+
+ +
+
+class cassandra.metadata.Murmur3Token(token)
+

A token for Murmur3Partitioner.

+

token is an int or string representing the token.

+
+ +
+
+class cassandra.metadata.MD5Token(token)
+

A token for RandomPartitioner.

+
+ +
+
+class cassandra.metadata.BytesToken(token)
+

A token for ByteOrderedPartitioner.

+
+
+classmethod from_string(token_string)
+

token_string should be the string representation from the server.

+
+ +
+ +
+
+cassandra.metadata.ReplicationStrategy
+

alias of cassandra.metadata._ReplicationStrategy

+
+ +
+
+class cassandra.metadata.ReplicationFactor(all_replicas, transient_replicas=None)
+

Represent the replication factor of a keyspace.

+
+ +
+
+class cassandra.metadata.SimpleStrategy(options_map)
+
+
+export_for_schema()
+

Returns a string version of these replication options which are +suitable for use in a CREATE KEYSPACE statement.

+
+ +
+
+property replication_factor
+

The replication factor for this keyspace.

+

For backward compatibility, this returns the +cassandra.metadata.ReplicationFactor.full_replicas value of +cassandra.metadata.SimpleStrategy.replication_factor_info.

+
+ +
+ +
+
+class cassandra.metadata.NetworkTopologyStrategy(dc_replication_factors)
+
+
+export_for_schema()
+

Returns a string version of these replication options which are +suitable for use in a CREATE KEYSPACE statement.

+
+ +
+ +
+
+class cassandra.metadata.LocalStrategy(options_map)
+
+
+export_for_schema()
+

Returns a string version of these replication options which are +suitable for use in a CREATE KEYSPACE statement.

+
+ +
+ +
+
+cassandra.metadata.group_keys_by_replica(session, keyspace, table, keys)
+

Returns a dict with the keys grouped per host. This can be +used to more accurately group by IN clause or to batch the keys per host.

+

If a valid replica is not found for a particular key it will be grouped under +NO_VALID_REPLICA

+

Example usage:

+
>>> result = group_keys_by_replica(
+...     session, "system", "peers",
+...     (("127.0.0.1", ), ("127.0.0.2", )))
+
+
+
+ +
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/stable/api/cassandra/metrics.html b/stable/api/cassandra/metrics.html new file mode 100644 index 0000000000..7cdf34db82 --- /dev/null +++ b/stable/api/cassandra/metrics.html @@ -0,0 +1,746 @@ + + + + + + + + + + + + + cassandra.metrics - Performance Metrics | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + + + +
+ +
+ +
+

cassandra.metrics - Performance Metrics

+
+
+class cassandra.metrics.Metrics
+

A collection of timers and counters for various performance metrics.

+

Timer metrics are represented as floating point seconds.

+
+
+request_timer = None
+

A greplin.scales.PmfStat timer for requests. This is a dict-like +object with the following keys:

+
    +
  • count - number of requests that have been timed

  • +
  • min - min latency

  • +
  • max - max latency

  • +
  • mean - mean latency

  • +
  • stddev - standard deviation for latencies

  • +
  • median - median latency

  • +
  • 75percentile - 75th percentile latencies

  • +
  • 95percentile - 95th percentile latencies

  • +
  • 98percentile - 98th percentile latencies

  • +
  • 99percentile - 99th percentile latencies

  • +
  • 999percentile - 99.9th percentile latencies

  • +
+
+ +
+
+connection_errors = None
+

A greplin.scales.IntStat count of the number of times that a +request to a Cassandra node has failed due to a connection problem.

+
+ +
+
+write_timeouts = None
+

A greplin.scales.IntStat count of write requests that resulted +in a timeout.

+
+ +
+
+read_timeouts = None
+

A greplin.scales.IntStat count of read requests that resulted +in a timeout.

+
+ +
+
+unavailables = None
+

A greplin.scales.IntStat count of write or read requests that +failed due to an insufficient number of replicas being alive to meet +the requested ConsistencyLevel.

+
+ +
+
+other_errors = None
+

A greplin.scales.IntStat count of all other request failures, +including failures caused by invalid requests, bootstrapping nodes, +overloaded nodes, etc.

+
+ +
+
+retries = None
+

A greplin.scales.IntStat count of the number of times a +request was retried based on the RetryPolicy decision.

+
+ +
+
+ignores = None
+

A greplin.scales.IntStat count of the number of times a +failed request was ignored based on the RetryPolicy decision.

+
+ +
+
+known_hosts = None
+

A greplin.scales.IntStat count of the number of nodes in +the cluster that the driver is aware of, regardless of whether any +connections are opened to those nodes.

+
+ +
+
+connected_to = None
+

A greplin.scales.IntStat count of the number of nodes that +the driver currently has at least one connection open to.

+
+ +
+
+open_connections = None
+

A greplin.scales.IntStat count of the number connections +the driver currently has open.

+
+ +
+
+get_stats()
+

Returns the metrics for the registered cluster instance.

+
+ +
+
+set_stats_name(stats_name)
+

Set the metrics stats name. +The stats_name is a string used to access the metris through scales: scales.getStats()[<stats_name>] +Default is ‘cassandra-<num>’.

+
+ +
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/stable/api/cassandra/policies.html b/stable/api/cassandra/policies.html new file mode 100644 index 0000000000..150e1b016c --- /dev/null +++ b/stable/api/cassandra/policies.html @@ -0,0 +1,1733 @@ + + + + + + + + + + + + + cassandra.policies - Load balancing and Failure Handling Policies | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + + + +
+ +
+ +
+

cassandra.policies - Load balancing and Failure Handling Policies

+
+

Load Balancing

+
+
+class cassandra.policies.HostDistance
+

A measure of how “distant” a node is from the client, which +may influence how the load balancer distributes requests +and how many connections are opened to the node.

+
+
+IGNORED = -1
+

A node with this distance should never be queried or have +connections opened to it.

+
+ +
+
+LOCAL = 0
+

Nodes with LOCAL distance will be preferred for operations +under some load balancing policies (such as DCAwareRoundRobinPolicy) +and will have a greater number of connections opened against +them by default.

+

This distance is typically used for nodes within the same +datacenter as the client.

+
+ +
+
+REMOTE = 1
+

Nodes with REMOTE distance will be treated as a last resort +by some load balancing policies (such as DCAwareRoundRobinPolicy) +and will have a smaller number of connections opened against +them by default.

+

This distance is typically used for nodes outside of the +datacenter that the client is running in.

+
+ +
+ +
+
+class cassandra.policies.LoadBalancingPolicy
+

Load balancing policies are used to decide how to distribute +requests among all possible coordinator nodes in the cluster.

+

In particular, they may focus on querying “near” nodes (those +in a local datacenter) or on querying nodes who happen to +be replicas for the requested data.

+

You may also use subclasses of LoadBalancingPolicy for +custom behavior.

+
+
+distance(host)
+

Returns a measure of how remote a Host is in +terms of the HostDistance enums.

+
+ +
+
+populate(cluster, hosts)
+

This method is called to initialize the load balancing +policy with a set of Host instances before its +first use. The cluster parameter is an instance of +Cluster.

+
+ +
+
+make_query_plan(working_keyspace=None, query=None)
+

Given a Statement instance, return a iterable +of Host instances which should be queried in that +order. A generator may work well for custom implementations +of this method.

+

Note that the query argument may be None when preparing +statements.

+

working_keyspace should be the string name of the current keyspace, +as set through Session.set_keyspace() or with a USE +statement.

+
+ +
+
+check_supported()
+

This will be called after the cluster Metadata has been initialized. +If the load balancing policy implementation cannot be supported for +some reason (such as a missing C extension), this is the point at +which it should raise an exception.

+
+ +
+ +
+
+class cassandra.policies.RoundRobinPolicy
+

A subclass of LoadBalancingPolicy which evenly +distributes queries across all nodes in the cluster, +regardless of what datacenter the nodes may be in.

+
+
+populate(cluster, hosts)
+

This method is called to initialize the load balancing +policy with a set of Host instances before its +first use. The cluster parameter is an instance of +Cluster.

+
+ +
+
+distance(host)
+

Returns a measure of how remote a Host is in +terms of the HostDistance enums.

+
+ +
+
+make_query_plan(working_keyspace=None, query=None)
+

Given a Statement instance, return a iterable +of Host instances which should be queried in that +order. A generator may work well for custom implementations +of this method.

+

Note that the query argument may be None when preparing +statements.

+

working_keyspace should be the string name of the current keyspace, +as set through Session.set_keyspace() or with a USE +statement.

+
+ +
+
+on_up(host)
+

Called when a node is marked up.

+
+ +
+
+on_down(host)
+

Called when a node is marked down.

+
+ +
+
+on_add(host)
+

Called when a node is added to the cluster. The newly added node +should be considered up.

+
+ +
+
+on_remove(host)
+

Called when a node is removed from the cluster.

+
+ +
+ +
+
+class cassandra.policies.DCAwareRoundRobinPolicy(local_dc='', used_hosts_per_remote_dc=0)
+

Similar to RoundRobinPolicy, but prefers hosts +in the local datacenter and only uses nodes in remote +datacenters as a last resort.

+

The local_dc parameter should be the name of the datacenter +(such as is reported by nodetool ring) that should +be considered local. If not specified, the driver will choose +a local_dc based on the first host among Cluster.contact_points +having a valid DC. If relying on this mechanism, all specified +contact points should be nodes in a single, local DC.

+

used_hosts_per_remote_dc controls how many nodes in +each remote datacenter will have connections opened +against them. In other words, used_hosts_per_remote_dc hosts +will be considered REMOTE and the +rest will be considered IGNORED. +By default, all remote hosts are ignored.

+
+
+populate(cluster, hosts)
+

This method is called to initialize the load balancing +policy with a set of Host instances before its +first use. The cluster parameter is an instance of +Cluster.

+
+ +
+
+distance(host)
+

Returns a measure of how remote a Host is in +terms of the HostDistance enums.

+
+ +
+
+make_query_plan(working_keyspace=None, query=None)
+

Given a Statement instance, return a iterable +of Host instances which should be queried in that +order. A generator may work well for custom implementations +of this method.

+

Note that the query argument may be None when preparing +statements.

+

working_keyspace should be the string name of the current keyspace, +as set through Session.set_keyspace() or with a USE +statement.

+
+ +
+
+on_up(host)
+

Called when a node is marked up.

+
+ +
+
+on_down(host)
+

Called when a node is marked down.

+
+ +
+
+on_add(host)
+

Called when a node is added to the cluster. The newly added node +should be considered up.

+
+ +
+
+on_remove(host)
+

Called when a node is removed from the cluster.

+
+ +
+ +
+
+class cassandra.policies.WhiteListRoundRobinPolicy(hosts)
+

A subclass of RoundRobinPolicy which evenly +distributes queries across all nodes in the cluster, +regardless of what datacenter the nodes may be in, but +only if that node exists in the list of allowed nodes

+

This policy is addresses the issue described in +https://datastax-oss.atlassian.net/browse/JAVA-145 +Where connection errors occur when connection +attempts are made to private IP addresses remotely

+

The hosts parameter should be a sequence of hosts to permit +connections to.

+
+
+populate(cluster, hosts)
+

This method is called to initialize the load balancing +policy with a set of Host instances before its +first use. The cluster parameter is an instance of +Cluster.

+
+ +
+
+distance(host)
+

Returns a measure of how remote a Host is in +terms of the HostDistance enums.

+
+ +
+
+on_up(host)
+

Called when a node is marked up.

+
+ +
+
+on_add(host)
+

Called when a node is added to the cluster. The newly added node +should be considered up.

+
+ +
+ +
+
+class cassandra.policies.TokenAwarePolicy(child_policy, shuffle_replicas=False)
+

A LoadBalancingPolicy wrapper that adds token awareness to +a child policy.

+

This alters the child policy’s behavior so that it first attempts to +send queries to LOCAL replicas (as determined +by the child policy) based on the Statement’s +routing_key. If shuffle_replicas is +truthy, these replicas will be yielded in a random order. Once those +hosts are exhausted, the remaining hosts in the child policy’s query +plan will be used in the order provided by the child policy.

+

If no routing_key is set on the query, the child +policy’s query plan will be used as is.

+
+
+shuffle_replicas = False
+

Yield local replicas in a random order.

+
+ +
+
+populate(cluster, hosts)
+

This method is called to initialize the load balancing +policy with a set of Host instances before its +first use. The cluster parameter is an instance of +Cluster.

+
+ +
+
+check_supported()
+

This will be called after the cluster Metadata has been initialized. +If the load balancing policy implementation cannot be supported for +some reason (such as a missing C extension), this is the point at +which it should raise an exception.

+
+ +
+
+distance(*args, **kwargs)
+

Returns a measure of how remote a Host is in +terms of the HostDistance enums.

+
+ +
+
+make_query_plan(working_keyspace=None, query=None)
+

Given a Statement instance, return a iterable +of Host instances which should be queried in that +order. A generator may work well for custom implementations +of this method.

+

Note that the query argument may be None when preparing +statements.

+

working_keyspace should be the string name of the current keyspace, +as set through Session.set_keyspace() or with a USE +statement.

+
+ +
+
+on_up(*args, **kwargs)
+

Called when a node is marked up.

+
+ +
+
+on_down(*args, **kwargs)
+

Called when a node is marked down.

+
+ +
+
+on_add(*args, **kwargs)
+

Called when a node is added to the cluster. The newly added node +should be considered up.

+
+ +
+
+on_remove(*args, **kwargs)
+

Called when a node is removed from the cluster.

+
+ +
+ +
+
+class cassandra.policies.HostFilterPolicy(child_policy, predicate)
+

A LoadBalancingPolicy subclass configured with a child policy, +and a single-argument predicate. This policy defers to the child policy for +hosts where predicate(host) is truthy. Hosts for which +predicate(host) is falsey will be considered IGNORED, and will +not be used in a query plan.

+

This can be used in the cases where you need a whitelist or blacklist +policy, e.g. to prepare for decommissioning nodes or for testing:

+
def address_is_ignored(host):
+    return host.address in [ignored_address0, ignored_address1]
+
+blacklist_filter_policy = HostFilterPolicy(
+    child_policy=RoundRobinPolicy(),
+    predicate=address_is_ignored
+)
+
+cluster = Cluster(
+    primary_host,
+    load_balancing_policy=blacklist_filter_policy,
+)
+
+
+

See the note in the make_query_plan() documentation for a caveat on +how wrapping ordering polices (e.g. RoundRobinPolicy) may break +desirable properties of the wrapped policy.

+

Please note that whitelist and blacklist policies are not recommended for +general, day-to-day use. You probably want something like +DCAwareRoundRobinPolicy, which prefers a local DC but has +fallbacks, over a brute-force method like whitelisting or blacklisting.

+
+
Parameters
+
    +
  • child_policy – an instantiated LoadBalancingPolicy +that this one will defer to.

  • +
  • predicate – a one-parameter function that takes a Host. +If it returns a falsey value, the Host will +be IGNORED and not returned in query plans.

  • +
+
+
+
+
+predicate(host)
+

A predicate, set on object initialization, that takes a Host +and returns a value. If the value is falsy, the Host is +IGNORED. If the value is truthy, +HostFilterPolicy defers to the child policy to determine the +host’s distance.

+

This is a read-only value set in __init__, implemented as a +property.

+
+ +
+
+distance(host)
+

Checks if predicate(host), then returns +IGNORED if falsey, and defers to the child policy +otherwise.

+
+ +
+
+make_query_plan(working_keyspace=None, query=None)
+

Defers to the child policy’s +LoadBalancingPolicy.make_query_plan() and filters the results.

+

Note that this filtering may break desirable properties of the wrapped +policy in some cases. For instance, imagine if you configure this +policy to filter out host2, and to wrap a round-robin policy that +rotates through three hosts in the order host1, host2, host3, +host2, host3, host1, host3, host1, host2, repeating. This +policy will yield host1, host3, host3, host1, host3, host1, +disproportionately favoring host3.

+
+ +
+ +
+
+class cassandra.policies.DefaultLoadBalancingPolicy(child_policy)
+

A LoadBalancingPolicy wrapper that adds the ability to target a specific host first.

+

If no host is set on the query, the child policy’s query plan will be used as is.

+
+
+populate(cluster, hosts)
+

This method is called to initialize the load balancing +policy with a set of Host instances before its +first use. The cluster parameter is an instance of +Cluster.

+
+ +
+
+make_query_plan(working_keyspace=None, query=None)
+

Given a Statement instance, return a iterable +of Host instances which should be queried in that +order. A generator may work well for custom implementations +of this method.

+

Note that the query argument may be None when preparing +statements.

+

working_keyspace should be the string name of the current keyspace, +as set through Session.set_keyspace() or with a USE +statement.

+
+ +
+ +
+
+class cassandra.policies.DSELoadBalancingPolicy(*args, **kwargs)
+

Deprecated: This will be removed in the next major release, +consider using DefaultLoadBalancingPolicy.

+
+ +
+
+

Translating Server Node Addresses

+
+
+class cassandra.policies.AddressTranslator
+

Interface for translating cluster-defined endpoints.

+

The driver discovers nodes using server metadata and topology change events. Normally, +the endpoint defined by the server is the right way to connect to a node. In some environments, +these addresses may not be reachable, or not preferred (public vs. private IPs in cloud environments, +suboptimal routing, etc). This interface allows for translating from server defined endpoints to +preferred addresses for driver connections.

+

Note: contact_points provided while creating the Cluster instance are not +translated using this mechanism – only addresses received from Cassandra nodes are.

+
+
+translate(addr)
+

Accepts the node ip address, and returns a translated address to be used connecting to this node.

+
+ +
+ +
+
+class cassandra.policies.IdentityTranslator
+

Returns the endpoint with no translation

+
+
+translate(addr)
+

Accepts the node ip address, and returns a translated address to be used connecting to this node.

+
+ +
+ +
+
+class cassandra.policies.EC2MultiRegionTranslator
+

Resolves private ips of the hosts in the same datacenter as the client, and public ips of hosts in other datacenters.

+
+
+translate(addr)
+

Reverse DNS the public broadcast_address, then lookup that hostname to get the AWS-resolved IP, which +will point to the private IP address within the same datacenter.

+
+ +
+ +
+
+

Marking Hosts Up or Down

+
+
+class cassandra.policies.ConvictionPolicy(host)
+

A policy which decides when hosts should be considered down +based on the types of failures and the number of failures.

+

If custom behavior is needed, this class may be subclassed.

+

host is an instance of Host.

+
+
+add_failure(connection_exc)
+

Implementations should return True if the host should be +convicted, False otherwise.

+
+ +
+
+reset()
+

Implementations should clear out any convictions or state regarding +the host.

+
+ +
+ +
+
+class cassandra.policies.SimpleConvictionPolicy(host)
+

The default implementation of ConvictionPolicy, +which simply marks a host as down after the first failure +of any kind.

+

host is an instance of Host.

+
+
+add_failure(connection_exc)
+

Implementations should return True if the host should be +convicted, False otherwise.

+
+ +
+
+reset()
+

Implementations should clear out any convictions or state regarding +the host.

+
+ +
+ +
+
+

Reconnecting to Dead Hosts

+
+
+class cassandra.policies.ReconnectionPolicy
+

This class and its subclasses govern how frequently an attempt is made +to reconnect to nodes that are marked as dead.

+

If custom behavior is needed, this class may be subclassed.

+
+
+new_schedule()
+

This should return a finite or infinite iterable of delays (each as a +floating point number of seconds) inbetween each failed reconnection +attempt. Note that if the iterable is finite, reconnection attempts +will cease once the iterable is exhausted.

+
+ +
+ +
+
+class cassandra.policies.ConstantReconnectionPolicy(delay, max_attempts=64)
+

A ReconnectionPolicy subclass which sleeps for a fixed delay +inbetween each reconnection attempt.

+

delay should be a floating point number of seconds to wait inbetween +each attempt.

+

max_attempts should be a total number of attempts to be made before +giving up, or None to continue reconnection attempts forever. +The default is 64.

+
+
+new_schedule()
+

This should return a finite or infinite iterable of delays (each as a +floating point number of seconds) inbetween each failed reconnection +attempt. Note that if the iterable is finite, reconnection attempts +will cease once the iterable is exhausted.

+
+ +
+ +
+
+class cassandra.policies.ExponentialReconnectionPolicy(base_delay, max_delay, max_attempts=64)
+

A ReconnectionPolicy subclass which exponentially increases +the length of the delay inbetween each reconnection attempt up to +a set maximum delay.

+

A random amount of jitter (+/- 15%) will be added to the pure exponential +delay value to avoid the situations where many reconnection handlers are +trying to reconnect at exactly the same time.

+

base_delay and max_delay should be in floating point units of +seconds.

+

max_attempts should be a total number of attempts to be made before +giving up, or None to continue reconnection attempts forever. +The default is 64.

+
+
+new_schedule()
+

This should return a finite or infinite iterable of delays (each as a +floating point number of seconds) inbetween each failed reconnection +attempt. Note that if the iterable is finite, reconnection attempts +will cease once the iterable is exhausted.

+
+ +
+ +
+
+

Retrying Failed Operations

+
+
+class cassandra.policies.WriteType
+

For usage with RetryPolicy, this describe a type +of write operation.

+
+
+SIMPLE = 0
+

A write to a single partition key. Such writes are guaranteed to be atomic +and isolated.

+
+ +
+
+BATCH = 1
+

A write to multiple partition keys that used the distributed batch log to +ensure atomicity.

+
+ +
+
+UNLOGGED_BATCH = 2
+

A write to multiple partition keys that did not use the distributed batch +log. Atomicity for such writes is not guaranteed.

+
+ +
+
+COUNTER = 3
+

A counter write (for one or multiple partition keys). Such writes should +not be replayed in order to avoid overcount.

+
+ +
+
+BATCH_LOG = 4
+

The initial write to the distributed batch log that Cassandra performs +internally before a BATCH write.

+
+ +
+
+CAS = 5
+

A lighweight-transaction write, such as “DELETE … IF EXISTS”.

+
+ +
+
+VIEW = 6
+

This WriteType is only seen in results for requests that were unable to +complete MV operations.

+
+ +
+
+CDC = 7
+

This WriteType is only seen in results for requests that were unable to +complete CDC operations.

+
+ +
+ +
+
+class cassandra.policies.RetryPolicy
+

A policy that describes whether to retry, rethrow, or ignore coordinator +timeout and unavailable failures. These are failures reported from the +server side. Timeouts are configured by +settings in cassandra.yaml. +Unavailable failures occur when the coordinator cannot acheive the consistency +level for a request. For further information see the method descriptions +below.

+

To specify a default retry policy, set the +Cluster.default_retry_policy attribute to an instance of this +class or one of its subclasses.

+

To specify a retry policy per query, set the Statement.retry_policy +attribute to an instance of this class or one of its subclasses.

+

If custom behavior is needed for retrying certain operations, +this class may be subclassed.

+
+
+RETRY = 0
+

This should be returned from the below methods if the operation +should be retried on the same connection.

+
+ +
+
+RETHROW = 1
+

This should be returned from the below methods if the failure +should be propagated and no more retries attempted.

+
+ +
+
+IGNORE = 2
+

This should be returned from the below methods if the failure +should be ignored but no more retries should be attempted.

+
+ +
+
+RETRY_NEXT_HOST = 3
+

This should be returned from the below methods if the operation +should be retried on another connection.

+
+ +
+
+on_read_timeout(query, consistency, required_responses, received_responses, data_retrieved, retry_num)
+

This is called when a read operation times out from the coordinator’s +perspective (i.e. a replica did not respond to the coordinator in time). +It should return a tuple with two items: one of the class enums (such +as RETRY) and a ConsistencyLevel to retry the +operation at or None to keep the same consistency level.

+

query is the Statement that timed out.

+

consistency is the ConsistencyLevel that the operation was +attempted at.

+

The required_responses and received_responses parameters describe +how many replicas needed to respond to meet the requested consistency +level and how many actually did respond before the coordinator timed +out the request. data_retrieved is a boolean indicating whether +any of those responses contained data (as opposed to just a digest).

+

retry_num counts how many times the operation has been retried, so +the first time this method is called, retry_num will be 0.

+

By default, operations will be retried at most once, and only if +a sufficient number of replicas responded (with data digests).

+
+ +
+
+on_write_timeout(query, consistency, write_type, required_responses, received_responses, retry_num)
+

This is called when a write operation times out from the coordinator’s +perspective (i.e. a replica did not respond to the coordinator in time).

+

query is the Statement that timed out.

+

consistency is the ConsistencyLevel that the operation was +attempted at.

+

write_type is one of the WriteType enums describing the +type of write operation.

+

The required_responses and received_responses parameters describe +how many replicas needed to acknowledge the write to meet the requested +consistency level and how many replicas actually did acknowledge the +write before the coordinator timed out the request.

+

retry_num counts how many times the operation has been retried, so +the first time this method is called, retry_num will be 0.

+

By default, failed write operations will retried at most once, and +they will only be retried if the write_type was +BATCH_LOG.

+
+ +
+
+on_unavailable(query, consistency, required_replicas, alive_replicas, retry_num)
+

This is called when the coordinator node determines that a read or +write operation cannot be successful because the number of live +replicas are too low to meet the requested ConsistencyLevel. +This means that the read or write operation was never forwarded to +any replicas.

+

query is the Statement that failed.

+

consistency is the ConsistencyLevel that the operation was +attempted at.

+

required_replicas is the number of replicas that would have needed to +acknowledge the operation to meet the requested consistency level. +alive_replicas is the number of replicas that the coordinator +considered alive at the time of the request.

+

retry_num counts how many times the operation has been retried, so +the first time this method is called, retry_num will be 0.

+

By default, if this is the first retry, it triggers a retry on the next +host in the query plan with the same consistency level. If this is not the +first retry, no retries will be attempted and the error will be re-raised.

+
+ +
+
+on_request_error(query, consistency, error, retry_num)
+

This is called when an unexpected error happens. This can be in the +following situations:

+
    +
  • On a connection error

  • +
  • On server errors: overloaded, isBootstrapping, serverError, etc.

  • +
+

query is the Statement that timed out.

+

consistency is the ConsistencyLevel that the operation was +attempted at.

+

error the instance of the exception.

+

retry_num counts how many times the operation has been retried, so +the first time this method is called, retry_num will be 0.

+

The default, it triggers a retry on the next host in the query plan +with the same consistency level.

+
+ +
+ +
+
+class cassandra.policies.FallthroughRetryPolicy
+

A retry policy that never retries and always propagates failures to +the application.

+
+
+on_read_timeout(*args, **kwargs)
+

This is called when a read operation times out from the coordinator’s +perspective (i.e. a replica did not respond to the coordinator in time). +It should return a tuple with two items: one of the class enums (such +as RETRY) and a ConsistencyLevel to retry the +operation at or None to keep the same consistency level.

+

query is the Statement that timed out.

+

consistency is the ConsistencyLevel that the operation was +attempted at.

+

The required_responses and received_responses parameters describe +how many replicas needed to respond to meet the requested consistency +level and how many actually did respond before the coordinator timed +out the request. data_retrieved is a boolean indicating whether +any of those responses contained data (as opposed to just a digest).

+

retry_num counts how many times the operation has been retried, so +the first time this method is called, retry_num will be 0.

+

By default, operations will be retried at most once, and only if +a sufficient number of replicas responded (with data digests).

+
+ +
+
+on_write_timeout(*args, **kwargs)
+

This is called when a write operation times out from the coordinator’s +perspective (i.e. a replica did not respond to the coordinator in time).

+

query is the Statement that timed out.

+

consistency is the ConsistencyLevel that the operation was +attempted at.

+

write_type is one of the WriteType enums describing the +type of write operation.

+

The required_responses and received_responses parameters describe +how many replicas needed to acknowledge the write to meet the requested +consistency level and how many replicas actually did acknowledge the +write before the coordinator timed out the request.

+

retry_num counts how many times the operation has been retried, so +the first time this method is called, retry_num will be 0.

+

By default, failed write operations will retried at most once, and +they will only be retried if the write_type was +BATCH_LOG.

+
+ +
+
+on_unavailable(*args, **kwargs)
+

This is called when the coordinator node determines that a read or +write operation cannot be successful because the number of live +replicas are too low to meet the requested ConsistencyLevel. +This means that the read or write operation was never forwarded to +any replicas.

+

query is the Statement that failed.

+

consistency is the ConsistencyLevel that the operation was +attempted at.

+

required_replicas is the number of replicas that would have needed to +acknowledge the operation to meet the requested consistency level. +alive_replicas is the number of replicas that the coordinator +considered alive at the time of the request.

+

retry_num counts how many times the operation has been retried, so +the first time this method is called, retry_num will be 0.

+

By default, if this is the first retry, it triggers a retry on the next +host in the query plan with the same consistency level. If this is not the +first retry, no retries will be attempted and the error will be re-raised.

+
+ +
+
+on_request_error(*args, **kwargs)
+

This is called when an unexpected error happens. This can be in the +following situations:

+
    +
  • On a connection error

  • +
  • On server errors: overloaded, isBootstrapping, serverError, etc.

  • +
+

query is the Statement that timed out.

+

consistency is the ConsistencyLevel that the operation was +attempted at.

+

error the instance of the exception.

+

retry_num counts how many times the operation has been retried, so +the first time this method is called, retry_num will be 0.

+

The default, it triggers a retry on the next host in the query plan +with the same consistency level.

+
+ +
+ +
+
+class cassandra.policies.DowngradingConsistencyRetryPolicy(*args, **kwargs)
+

Deprecated: This retry policy will be removed in the next major release.

+

A retry policy that sometimes retries with a lower consistency level than +the one initially requested.

+

BEWARE: This policy may retry queries using a lower consistency +level than the one initially requested. By doing so, it may break +consistency guarantees. In other words, if you use this retry policy, +there are cases (documented below) where a read at QUORUM +may not see a preceding write at QUORUM. Do not use this +policy unless you have understood the cases where this can happen and +are ok with that. It is also recommended to subclass this class so +that queries that required a consistency level downgrade can be +recorded (so that repairs can be made later, etc).

+

This policy implements the same retries as RetryPolicy, +but on top of that, it also retries in the following cases:

+
    +
  • On a read timeout: if the number of replicas that responded is +greater than one but lower than is required by the requested +consistency level, the operation is retried at a lower consistency +level.

  • +
  • On a write timeout: if the operation is an UNLOGGED_BATCH +and at least one replica acknowledged the write, the operation is +retried at a lower consistency level. Furthermore, for other +write types, if at least one replica acknowledged the write, the +timeout is ignored.

  • +
  • On an unavailable exception: if at least one replica is alive, the +operation is retried at a lower consistency level.

  • +
+

The reasoning behind this retry policy is as follows: if, based +on the information the Cassandra coordinator node returns, retrying the +operation with the initially requested consistency has a chance to +succeed, do it. Otherwise, if based on that information we know the +initially requested consistency level cannot be achieved currently, then:

+
    +
  • For writes, ignore the exception (thus silently failing the +consistency requirement) if we know the write has been persisted on at +least one replica.

  • +
  • For reads, try reading at a lower consistency level (thus silently +failing the consistency requirement).

  • +
+

In other words, this policy implements the idea that if the requested +consistency level cannot be achieved, the next best thing for writes is +to make sure the data is persisted, and that reading something is better +than reading nothing, even if there is a risk of reading stale data.

+
+
+on_read_timeout(query, consistency, required_responses, received_responses, data_retrieved, retry_num)
+

This is called when a read operation times out from the coordinator’s +perspective (i.e. a replica did not respond to the coordinator in time). +It should return a tuple with two items: one of the class enums (such +as RETRY) and a ConsistencyLevel to retry the +operation at or None to keep the same consistency level.

+

query is the Statement that timed out.

+

consistency is the ConsistencyLevel that the operation was +attempted at.

+

The required_responses and received_responses parameters describe +how many replicas needed to respond to meet the requested consistency +level and how many actually did respond before the coordinator timed +out the request. data_retrieved is a boolean indicating whether +any of those responses contained data (as opposed to just a digest).

+

retry_num counts how many times the operation has been retried, so +the first time this method is called, retry_num will be 0.

+

By default, operations will be retried at most once, and only if +a sufficient number of replicas responded (with data digests).

+
+ +
+
+on_write_timeout(query, consistency, write_type, required_responses, received_responses, retry_num)
+

This is called when a write operation times out from the coordinator’s +perspective (i.e. a replica did not respond to the coordinator in time).

+

query is the Statement that timed out.

+

consistency is the ConsistencyLevel that the operation was +attempted at.

+

write_type is one of the WriteType enums describing the +type of write operation.

+

The required_responses and received_responses parameters describe +how many replicas needed to acknowledge the write to meet the requested +consistency level and how many replicas actually did acknowledge the +write before the coordinator timed out the request.

+

retry_num counts how many times the operation has been retried, so +the first time this method is called, retry_num will be 0.

+

By default, failed write operations will retried at most once, and +they will only be retried if the write_type was +BATCH_LOG.

+
+ +
+
+on_unavailable(query, consistency, required_replicas, alive_replicas, retry_num)
+

This is called when the coordinator node determines that a read or +write operation cannot be successful because the number of live +replicas are too low to meet the requested ConsistencyLevel. +This means that the read or write operation was never forwarded to +any replicas.

+

query is the Statement that failed.

+

consistency is the ConsistencyLevel that the operation was +attempted at.

+

required_replicas is the number of replicas that would have needed to +acknowledge the operation to meet the requested consistency level. +alive_replicas is the number of replicas that the coordinator +considered alive at the time of the request.

+

retry_num counts how many times the operation has been retried, so +the first time this method is called, retry_num will be 0.

+

By default, if this is the first retry, it triggers a retry on the next +host in the query plan with the same consistency level. If this is not the +first retry, no retries will be attempted and the error will be re-raised.

+
+ +
+ +
+
+

Retrying Idempotent Operations

+
+
+class cassandra.policies.SpeculativeExecutionPolicy
+

Interface for specifying speculative execution plans

+
+
+new_plan(keyspace, statement)
+

Returns

+
+
Parameters
+
    +
  • keyspace

  • +
  • statement

  • +
+
+
Returns
+

+
+
+
+ +
+ +
+
+class cassandra.policies.ConstantSpeculativeExecutionPolicy(delay, max_attempts)
+

A speculative execution policy that sends a new query every X seconds (delay) for a maximum of Y attempts (max_attempts).

+
+
+new_plan(keyspace, statement)
+

Returns

+
+
Parameters
+
    +
  • keyspace

  • +
  • statement

  • +
+
+
Returns
+

+
+
+
+ +
+ +
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/stable/api/cassandra/pool.html b/stable/api/cassandra/pool.html new file mode 100644 index 0000000000..d856e490c1 --- /dev/null +++ b/stable/api/cassandra/pool.html @@ -0,0 +1,664 @@ + + + + + + + + + + + + + cassandra.pool - Hosts and Connection Pools | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + + + +
+ +
+ +
+

cassandra.pool - Hosts and Connection Pools

+

Connection pooling and host management.

+
+
+class cassandra.pool.Host
+

Represents a single Cassandra node.

+
+
+property address
+

The IP address of the endpoint. This is the RPC address the driver uses when connecting to the node.

+
+ +
+
+property datacenter
+

The datacenter the node is in.

+
+ +
+
+property rack
+

The rack the node is in.

+
+ +
+ +
+
+exception cassandra.pool.NoConnectionsAvailable
+

All existing connections to a given host are busy, or there are +no open connections.

+
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/stable/api/cassandra/protocol.html b/stable/api/cassandra/protocol.html new file mode 100644 index 0000000000..d97b6275df --- /dev/null +++ b/stable/api/cassandra/protocol.html @@ -0,0 +1,730 @@ + + + + + + + + + + + + + cassandra.protocol - Protocol Features | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + + + +
+ +
+ +
+

cassandra.protocol - Protocol Features

+
+

Custom Payloads

+

Native protocol version 4+ allows for a custom payload to be sent between clients +and custom query handlers. The payload is specified as a string:binary_type dict +holding custom key/value pairs.

+

By default these are ignored by the server. They can be useful for servers implementing +a custom QueryHandler.

+

See Session.execute(), :Session.execute_async(), ResponseFuture.custom_payload.

+
+
+class cassandra.protocol._ProtocolHandler
+

_ProtocolHander handles encoding and decoding messages.

+

This class can be specialized to compose Handlers which implement alternative +result decoding or type deserialization. Class definitions are passed to cassandra.cluster.Cluster +on initialization.

+

Contracted class methods are _ProtocolHandler.encode_message() and _ProtocolHandler.decode_message().

+
+
+message_types_by_opcode = {default mapping}
+
+ +
+
+classmethod encode_message(msg, stream_id, protocol_version, compressor, allow_beta_protocol_version)
+

Encodes a message using the specified frame parameters, and compressor

+
+
Parameters
+
    +
  • msg – the message, typically of cassandra.protocol._MessageType, generated by the driver

  • +
  • stream_id – protocol stream id for the frame header

  • +
  • protocol_version – version for the frame header, and used encoding contents

  • +
  • compressor – optional compression function to be used on the body

  • +
+
+
+
+ +
+
+classmethod decode_message(protocol_version, user_type_map, stream_id, flags, opcode, body, decompressor, result_metadata)
+

Decodes a native protocol message body

+
+
Parameters
+
    +
  • protocol_version – version to use decoding contents

  • +
  • user_type_map – map[keyspace name] = map[type name] = custom type to instantiate when deserializing this type

  • +
  • stream_id – native protocol stream id from the frame header

  • +
  • flags – native protocol flags bitmap from the header

  • +
  • opcode – native protocol opcode from the header

  • +
  • body – frame body

  • +
  • decompressor – optional decompression function to inflate the body

  • +
+
+
Returns
+

a message decoded from the body and frame attributes

+
+
+
+ +
+ +
+
+

Faster Deserialization

+

When python-driver is compiled with Cython, it uses a Cython-based deserialization path +to deserialize messages. By default, the driver will use a Cython-based parser that returns +lists of rows similar to the pure-Python version. In addition, there are two additional +ProtocolHandler classes that can be used to deserialize response messages: LazyProtocolHandler +and NumpyProtocolHandler. They can be used as follows:

+
from cassandra.protocol import NumpyProtocolHandler, LazyProtocolHandler
+from cassandra.query import tuple_factory
+s.client_protocol_handler = LazyProtocolHandler   # for a result iterator
+s.row_factory = tuple_factory  #required for Numpy results
+s.client_protocol_handler = NumpyProtocolHandler  # for a dict of NumPy arrays as result
+
+
+

These protocol handlers comprise different parsers, and return results as described below:

+
    +
  • ProtocolHandler: this default implementation is a drop-in replacement for the pure-Python version. +The rows are all parsed upfront, before results are returned.

  • +
  • LazyProtocolHandler: near drop-in replacement for the above, except that it returns an iterator over rows, +lazily decoded into the default row format (this is more efficient since all decoded results are not materialized at once)

  • +
  • NumpyProtocolHander: deserializes results directly into NumPy arrays. This facilitates efficient integration with +analysis toolkits such as Pandas.

  • +
+
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/stable/api/cassandra/query.html b/stable/api/cassandra/query.html new file mode 100644 index 0000000000..729a6d57c6 --- /dev/null +++ b/stable/api/cassandra/query.html @@ -0,0 +1,993 @@ + + + + + + + + + + + + + cassandra.query - Prepared Statements, Batch Statements, Tracing, and Row Factories | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + + + +
+ +
+ +
+

cassandra.query - Prepared Statements, Batch Statements, Tracing, and Row Factories

+
+
+cassandra.query.tuple_factory(colnames, rows)
+

Returns each row as a tuple

+

Example:

+
>>> from cassandra.query import tuple_factory
+>>> session = cluster.connect('mykeyspace')
+>>> session.row_factory = tuple_factory
+>>> rows = session.execute("SELECT name, age FROM users LIMIT 1")
+>>> print rows[0]
+('Bob', 42)
+
+
+
+

Changed in version 2.0.0: moved from cassandra.decoder to cassandra.query

+
+
+ +
+
+cassandra.query.named_tuple_factory(colnames, rows)
+

Returns each row as a namedtuple. +This is the default row factory.

+

Example:

+
>>> from cassandra.query import named_tuple_factory
+>>> session = cluster.connect('mykeyspace')
+>>> session.row_factory = named_tuple_factory
+>>> rows = session.execute("SELECT name, age FROM users LIMIT 1")
+>>> user = rows[0]
+
+>>> # you can access field by their name:
+>>> print "name: %s, age: %d" % (user.name, user.age)
+name: Bob, age: 42
+
+>>> # or you can access fields by their position (like a tuple)
+>>> name, age = user
+>>> print "name: %s, age: %d" % (name, age)
+name: Bob, age: 42
+>>> name = user[0]
+>>> age = user[1]
+>>> print "name: %s, age: %d" % (name, age)
+name: Bob, age: 42
+
+
+
+

Changed in version 2.0.0: moved from cassandra.decoder to cassandra.query

+
+
+ +
+
+cassandra.query.dict_factory(colnames, rows)
+

Returns each row as a dict.

+

Example:

+
>>> from cassandra.query import dict_factory
+>>> session = cluster.connect('mykeyspace')
+>>> session.row_factory = dict_factory
+>>> rows = session.execute("SELECT name, age FROM users LIMIT 1")
+>>> print rows[0]
+{u'age': 42, u'name': u'Bob'}
+
+
+
+

Changed in version 2.0.0: moved from cassandra.decoder to cassandra.query

+
+
+ +
+
+cassandra.query.ordered_dict_factory(colnames, rows)
+

Like dict_factory(), but returns each row as an OrderedDict, +so the order of the columns is preserved.

+
+

Changed in version 2.0.0: moved from cassandra.decoder to cassandra.query

+
+
+ +
+
+class cassandra.query.SimpleStatement(query_string, retry_policy=None, consistency_level=None, routing_key=None, serial_consistency_level=None, fetch_size=<object object>, keyspace=None, custom_payload=None, is_idempotent=False)
+

A simple, un-prepared query.

+

query_string should be a literal CQL statement with the exception +of parameter placeholders that will be filled through the +parameters argument of Session.execute().

+

See Statement attributes for a description of the other parameters.

+
+ +
+
+class cassandra.query.PreparedStatement
+

A statement that has been prepared against at least one Cassandra node. +Instances of this class should not be created directly, but through +Session.prepare().

+

A PreparedStatement should be prepared only once. Re-preparing a statement +may affect performance (as the operation requires a network roundtrip).

+

A note about * in prepared statements: Do not use * in prepared statements if you might +change the schema of the table being queried. The driver and server each +maintain a map between metadata for a schema and statements that were +prepared against that schema. When a user changes a schema, e.g. by adding +or removing a column, the server invalidates its mappings involving that +schema. However, there is currently no way to propagate that invalidation +to drivers. Thus, after a schema change, the driver will incorrectly +interpret the results of SELECT * queries prepared before the schema +change. This is currently being addressed in CASSANDRA-10786.

+
+
+bind(values)
+

Creates and returns a BoundStatement instance using values.

+

See BoundStatement.bind() for rules on input values.

+
+ +
+ +
+
+class cassandra.query.BoundStatement(prepared_statement, retry_policy=None, consistency_level=None, routing_key=None, serial_consistency_level=None, fetch_size=<object object>, keyspace=None, custom_payload=None)
+

A prepared statement that has been bound to a particular set of values. +These may be created directly or through PreparedStatement.bind().

+

prepared_statement should be an instance of PreparedStatement.

+

See Statement attributes for a description of the other parameters.

+
+
+bind(values)
+

Binds a sequence of values for the prepared statement parameters +and returns this instance. Note that values must be:

+
    +
  • a sequence, even if you are only binding one value, or

  • +
  • a dict that relates 1-to-1 between dict keys and columns

  • +
+
+

Changed in version 2.6.0: UNSET_VALUE was introduced. These can be bound as positional parameters +in a sequence, or by name in a dict. Additionally, when using protocol v4+:

+
    +
  • short sequences will be extended to match bind parameters with UNSET_VALUE

  • +
  • names may be omitted from a dict with UNSET_VALUE implied.

  • +
+
+
+

Changed in version 3.0.0: method will not throw if extra keys are present in bound dict (PYTHON-178)

+
+
+ +
+
+property routing_key
+

The partition_key portion of the primary key, +which can be used to determine which nodes are replicas for the query.

+

If the partition key is a composite, a list or tuple must be passed in. +Each key component should be in its packed (binary) format, so all +components should be strings.

+
+ +
+ +
+
+class cassandra.query.Statement
+

An abstract class representing a single query. There are three subclasses: +SimpleStatement, BoundStatement, and BatchStatement. +These can be passed to Session.execute().

+
+
+property routing_key
+

The partition_key portion of the primary key, +which can be used to determine which nodes are replicas for the query.

+

If the partition key is a composite, a list or tuple must be passed in. +Each key component should be in its packed (binary) format, so all +components should be strings.

+
+ +
+
+property serial_consistency_level
+

The serial consistency level is only used by conditional updates +(INSERT, UPDATE and DELETE with an IF condition). For +those, the serial_consistency_level defines the consistency level of +the serial phase (or “paxos” phase) while the normal +consistency_level defines the consistency for the “learn” phase, +i.e. what type of reads will be guaranteed to see the update right away. +For example, if a conditional write has a consistency_level of +QUORUM (and is successful), then a +QUORUM read is guaranteed to see that write. +But if the regular consistency_level of that write is +ANY, then only a read with a +consistency_level of SERIAL is +guaranteed to see it (even a read with consistency +ALL is not guaranteed to be enough).

+

The serial consistency can only be one of SERIAL +or LOCAL_SERIAL. While SERIAL guarantees full +linearizability (with other SERIAL updates), LOCAL_SERIAL only +guarantees it in the local data center.

+

The serial consistency level is ignored for any query that is not a +conditional update. Serial reads should use the regular +consistency_level.

+

Serial consistency levels may only be used against Cassandra 2.0+ +and the protocol_version must be set to 2 or higher.

+

See Lightweight Transactions (Compare-and-set) for a discussion on how to work with results returned from +conditional statements.

+
+

New in version 2.0.0.

+
+
+ +
+ +
+
+cassandra.query.UNSET_VALUE
+

The most base type

+
+ +
+
+class cassandra.query.BatchStatement(batch_type=BatchType.LOGGED, retry_policy=None, consistency_level=None)
+

A protocol-level batch of operations which are applied atomically +by default.

+
+

New in version 2.0.0.

+
+

batch_type specifies The BatchType for the batch operation. +Defaults to BatchType.LOGGED.

+

retry_policy should be a RetryPolicy instance for +controlling retries on the operation.

+

consistency_level should be a ConsistencyLevel value +to be used for all operations in the batch.

+

custom_payload is a Custom Payloads passed to the server. +Note: as Statement objects are added to the batch, this map is +updated with any values found in their custom payloads. These are +only allowed when using protocol version 4 or higher.

+

Example usage:

+
insert_user = session.prepare("INSERT INTO users (name, age) VALUES (?, ?)")
+batch = BatchStatement(consistency_level=ConsistencyLevel.QUORUM)
+
+for (name, age) in users_to_insert:
+    batch.add(insert_user, (name, age))
+
+session.execute(batch)
+
+
+

You can also mix different types of operations within a batch:

+
batch = BatchStatement()
+batch.add(SimpleStatement("INSERT INTO users (name, age) VALUES (%s, %s)"), (name, age))
+batch.add(SimpleStatement("DELETE FROM pending_users WHERE name=%s"), (name,))
+session.execute(batch)
+
+
+
+

New in version 2.0.0.

+
+
+

Changed in version 2.1.0: Added serial_consistency_level as a parameter

+
+
+

Changed in version 2.6.0: Added custom_payload as a parameter

+
+
+
+add(statement, parameters=None)
+

Adds a Statement and optional sequence of parameters +to be used with the statement to the batch.

+

Like with other statements, parameters must be a sequence, even +if there is only one item.

+
+ +
+
+add_all(statements, parameters)
+

Adds a sequence of Statement objects and a matching sequence +of parameters to the batch. Statement and parameter sequences must be of equal length or +one will be truncated. None can be used in the parameters position where are needed.

+
+ +
+
+clear()
+

This is a convenience method to clear a batch statement for reuse.

+

Note: it should not be used concurrently with uncompleted execution futures executing the same +BatchStatement.

+
+ +
+
+serial_consistency_level = None
+
+ +
+ +
+
+class cassandra.query.BatchType
+

A BatchType is used with BatchStatement instances to control +the atomicity of the batch operation.

+
+

New in version 2.0.0.

+
+
+
+LOGGED = BatchType.LOGGED
+
+ +
+
+UNLOGGED = BatchType.UNLOGGED
+
+ +
+
+COUNTER = BatchType.COUNTER
+
+ +
+ +
+
+class cassandra.query.ValueSequence(iterable=(), /)
+

A wrapper class that is used to specify that a sequence of values should +be treated as a CQL list of values instead of a single column collection when used +as part of the parameters argument for Session.execute().

+

This is typically needed when supplying a list of keys to select. +For example:

+
>>> my_user_ids = ('alice', 'bob', 'charles')
+>>> query = "SELECT * FROM users WHERE user_id IN %s"
+>>> session.execute(query, parameters=[ValueSequence(my_user_ids)])
+
+
+
+ +
+
+class cassandra.query.QueryTrace
+

A trace of the duration and events that occurred when executing +an operation.

+
+
+populate(max_wait=2.0, wait_for_complete=True, query_cl=None)
+

Retrieves the actual tracing details from Cassandra and populates the +attributes of this instance. Because tracing details are stored +asynchronously by Cassandra, this may need to retry the session +detail fetch. If the trace is still not available after max_wait +seconds, TraceUnavailable will be raised; if max_wait is +None, this will retry forever.

+

wait_for_complete=False bypasses the wait for duration to be populated. +This can be used to query events from partial sessions.

+

query_cl specifies a consistency level to use for polling the trace tables, +if it should be different than the session default.

+
+ +
+ +
+
+class cassandra.query.TraceEvent
+

Representation of a single event within a query trace.

+
+ +
+
+exception cassandra.query.TraceUnavailable
+

Raised when complete trace details cannot be fetched from Cassandra.

+
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/stable/api/cassandra/timestamps.html b/stable/api/cassandra/timestamps.html new file mode 100644 index 0000000000..7aa904e54e --- /dev/null +++ b/stable/api/cassandra/timestamps.html @@ -0,0 +1,686 @@ + + + + + + + + + + + + + cassandra.timestamps - Timestamp Generation | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + + + +
+ +
+ +
+

cassandra.timestamps - Timestamp Generation

+
+
+class cassandra.timestamps.MonotonicTimestampGenerator(warn_on_drift=True, warning_threshold=0, warning_interval=0)
+

An object that, when called, returns int(time.time() * 1e6) when +possible, but, if the value returned by time.time doesn’t increase, +drifts into the future and logs warnings. +Exposed configuration attributes can be configured with arguments to +__init__ or by changing attributes on an initialized object.

+
+

New in version 3.8.0.

+
+
+
+warn_on_drift = True
+

If true, log warnings when timestamps drift into the future as allowed by +warning_threshold and warning_interval.

+
+ +
+
+warning_threshold = 1
+

This object will only issue warnings when the returned timestamp drifts +more than warning_threshold seconds into the future. +Defaults to 1 second.

+
+ +
+
+warning_interval = 1
+

This object will only issue warnings every warning_interval seconds. +Defaults to 1 second.

+
+ +
+
+_next_timestamp(now, last)
+

Returns the timestamp that should be used if now is the current +time and last is the last timestamp returned by this object. +Intended for internal and testing use only; to generate timestamps, +call an instantiated MonotonicTimestampGenerator object.

+
+
Parameters
+
    +
  • now (int) – an integer to be used as the current time, typically +representing the current time in microseconds since the UNIX epoch

  • +
  • last (int) – an integer representing the last timestamp returned by +this object

  • +
+
+
+
+ +
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/stable/api/cassandra/util.html b/stable/api/cassandra/util.html new file mode 100644 index 0000000000..b1d76aacf9 --- /dev/null +++ b/stable/api/cassandra/util.html @@ -0,0 +1,1021 @@ + + + + + + + + + + + + + cassandra.util - Utilities | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + + + +
+ +
+ +
+

cassandra.util - Utilities

+
+
+class cassandra.util.Date(value)
+

Idealized date: year, month, day

+

Offers wider year range than datetime.date. For Dates that cannot be represented +as a datetime.date (because datetime.MINYEAR, datetime.MAXYEAR), this type falls back +to printing days_from_epoch offset.

+

Initializer value can be:

+
    +
  • integer_type: absolute days from epoch (1970, 1, 1). Can be negative.

  • +
  • datetime.date: built-in date

  • +
  • string_type: a string time of the form “yyyy-mm-dd”

  • +
+
+
+date()
+

Return a built-in datetime.date for Dates falling in the years [datetime.MINYEAR, datetime.MAXYEAR]

+

ValueError is raised for Dates outside this range.

+
+ +
+
+property seconds
+

Absolute seconds from epoch (can be negative)

+
+ +
+ +
+
+class cassandra.util.DateRange(lower_bound=None, upper_bound=None, value=None)
+

DSE DateRange Type

+
+
+lower_bound
+

DateRangeBound representing the lower bound of a bounded range.

+
+ +
+
+upper_bound
+

DateRangeBound representing the upper bound of a bounded range.

+
+ +
+
+value
+

DateRangeBound representing the value of a single-value range.

+
+ +

As noted in its documentation, DateRangeBound uses a millisecond +offset from the UNIX epoch to allow DateRange to represent values +datetime.datetime cannot. For such values, string representions will show +this offset rather than the CQL representation.

+
+
Parameters
+
+
+
+
+ +
+
+class cassandra.util.DateRangeBound(value, precision)
+

Represents a single date value and its precision for DateRange.

+
+
+milliseconds
+

Integer representing milliseconds since the UNIX epoch. May be negative.

+
+ +
+
+precision
+

String representing the precision of a bound. Must be a valid +DateRangePrecision member.

+
+ +

DateRangeBound uses a millisecond offset from the UNIX epoch to +allow DateRange to represent values datetime.datetime cannot. +For such values, string representions will show this offset rather than the +CQL representation.

+
+
Parameters
+
    +
  • value – a value representing ms since the epoch. Accepts an +integer or a datetime.

  • +
  • precision – a string representing precision

  • +
+
+
+
+
+datetime()
+

Return milliseconds as a datetime.datetime if possible. +Raises an OverflowError if the value is out of range.

+
+ +
+
+classmethod from_value(value)
+

Construct a new DateRangeBound from a given value. If +possible, use the value[‘milliseconds’] and value[‘precision’] keys +of the argument. Otherwise, use the argument as a (milliseconds, +precision) iterable.

+
+
Parameters
+

value – a dictlike or iterable object

+
+
+
+ +
+ +
+
+class cassandra.util.DateRangePrecision
+

An “enum” representing the valid values for DateRange.precision.

+
+ +
+
+class cassandra.util.Distance(x=nan, y=nan, radius=nan)
+

Represents a Distance geometry for DSE

+
+
+static from_wkt(s)
+

Parse a Distance geometry from a wkt string and return a new Distance object.

+
+ +
+ +
+
+class cassandra.util.Duration(months=0, days=0, nanoseconds=0)
+

Cassandra Duration Type

+
+ +
+
+class cassandra.util.LineString(coords=())
+

Represents a linestring geometry for DSE

+

‘coords`: a sequence of (x, y) coordinates of points in the linestring

+
+
+static from_wkt(s)
+

Parse a LineString geometry from a wkt string and return a new LineString object.

+
+ +
+ +
+
+class cassandra.util.OrderedMap(*args, **kwargs)
+

An ordered map that accepts non-hashable types for keys. It also maintains the +insertion order of items, behaving as OrderedDict in that regard. These maps +are constructed and read just as normal mapping types, except that they may +contain arbitrary collections and other non-hashable items as keys:

+
>>> od = OrderedMap([({'one': 1, 'two': 2}, 'value'),
+...                  ({'three': 3, 'four': 4}, 'value2')])
+>>> list(od.keys())
+[{'two': 2, 'one': 1}, {'three': 3, 'four': 4}]
+>>> list(od.values())
+['value', 'value2']
+
+
+

These constructs are needed to support nested collections in Cassandra 2.1.3+, +where frozen collections can be specified as parameters to others:

+
CREATE TABLE example (
+    ...
+    value map<frozen<map<int, int>>, double>
+    ...
+)
+
+
+

This class derives from the (immutable) Mapping API. Objects in these maps +are not intended be modified.

+
+ +
+
+class cassandra.util.OrderedMapSerializedKey(cass_type, protocol_version)
+
+ +
+
+class cassandra.util.Point(x=nan, y=nan)
+

Represents a point geometry for DSE

+
+
+static from_wkt(s)
+

Parse a Point geometry from a wkt string and return a new Point object.

+
+ +
+ +
+
+class cassandra.util.Polygon(exterior=(), interiors=None)
+

Represents a polygon geometry for DSE

+

‘exterior`: a sequence of (x, y) coordinates of points in the linestring +interiors: None, or a sequence of sequences or (x, y) coordinates of points describing interior linear rings

+
+
+static from_wkt(s)
+

Parse a Polygon geometry from a wkt string and return a new Polygon object.

+
+ +
+ +
+
+class cassandra.util.SortedSet(iterable=())
+

A sorted set based on sorted list

+

A sorted set implementation is used in this case because it does not +require its elements to be immutable/hashable.

+

#Not implemented: update functions, inplace operators

+
+ +
+
+class cassandra.util.Time(value)
+

Idealized time, independent of day.

+

Up to nanosecond resolution

+

Initializer value can be:

+
    +
  • integer_type: absolute nanoseconds in the day

  • +
  • datetime.time: built-in time

  • +
  • string_type: a string time of the form “HH:MM:SS[.mmmuuunnn]”

  • +
+
+
+property hour
+

The hour component of this time (0-23)

+
+ +
+
+property minute
+

The minute component of this time (0-59)

+
+ +
+
+property nanosecond
+

The fractional seconds component of the time, in nanoseconds

+
+ +
+
+property second
+

The second component of this time (0-59)

+
+ +
+
+time()
+

Return a built-in datetime.time (nanosecond precision truncated to micros).

+
+ +
+ +
+
+class cassandra.util.Version(version)
+

Internal minimalist class to compare versions. +A valid version is: <int>.<int>.<int>.<int or str>.

+

TODO: when python2 support is removed, use packaging.version.

+
+ +
+
+cassandra.util.datetime_from_timestamp(timestamp)
+

Creates a timezone-agnostic datetime from timestamp (in seconds) in a consistent manner. +Works around a Windows issue with large negative timestamps (PYTHON-119), +and rounding differences in Python 3.4 (PYTHON-340).

+
+
Parameters
+

timestamp – a unix timestamp, in seconds

+
+
+
+ +
+
+cassandra.util.datetime_from_uuid1(uuid_arg)
+

Creates a timezone-agnostic datetime from the timestamp in the +specified type-1 UUID.

+
+
Parameters
+

uuid_arg – a version 1 UUID

+
+
+
+ +
+
+cassandra.util.max_uuid_from_time(timestamp)
+

Generates the maximum TimeUUID (type 1) for a given timestamp, as compared by Cassandra.

+

See uuid_from_time() for argument and return types.

+
+ +
+
+cassandra.util.min_uuid_from_time(timestamp)
+

Generates the minimum TimeUUID (type 1) for a given timestamp, as compared by Cassandra.

+

See uuid_from_time() for argument and return types.

+
+ +
+
+cassandra.util.ms_timestamp_from_datetime(dt)
+

Converts a datetime to a timestamp expressed in milliseconds.

+
+
Parameters
+

dt – a datetime.datetime

+
+
+
+ +
+
+cassandra.util.sortedset
+

alias of cassandra.util.SortedSet

+
+ +
+
+cassandra.util.unix_time_from_uuid1(uuid_arg)
+

Converts a version 1 uuid.UUID to a timestamp with the same precision +as time.time() returns. This is useful for examining the +results of queries returning a v1 UUID.

+
+
Parameters
+

uuid_arg – a version 1 UUID

+
+
+
+ +
+
+cassandra.util.utc_datetime_from_ms_timestamp(timestamp)
+

Creates a UTC datetime from a timestamp in milliseconds. See +datetime_from_timestamp().

+

Raises an OverflowError if the timestamp is out of range for +datetime.

+
+
Parameters
+

timestamp – timestamp, in milliseconds

+
+
+
+ +
+
+cassandra.util.uuid_from_time(time_arg, node=None, clock_seq=None)
+

Converts a datetime or timestamp to a type 1 uuid.UUID.

+
+
Parameters
+
    +
  • time_arg – The time to use for the timestamp portion of the UUID. +This can either be a datetime object or a timestamp +in seconds (as returned from time.time()).

  • +
  • node (long) – None integer for the UUID (up to 48 bits). If not specified, this +field is randomized.

  • +
  • clock_seq (int) – Clock sequence field for the UUID (up to 14 bits). If not specified, +a random sequence is generated.

  • +
+
+
Return type
+

uuid.UUID

+
+
+
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/stable/api/index.html b/stable/api/index.html new file mode 100644 index 0000000000..f85685a257 --- /dev/null +++ b/stable/api/index.html @@ -0,0 +1,707 @@ + + + + + + + + + + + + + API Documentation | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + + + +
+ +
+ +
+

API Documentation

+
+

Core Driver

+ +
+
+

Object Mapper

+ +
+
+

DataStax Graph

+ +
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/stable/cqlengine/batches.html b/stable/cqlengine/batches.html new file mode 100644 index 0000000000..4112cbda98 --- /dev/null +++ b/stable/cqlengine/batches.html @@ -0,0 +1,737 @@ + + + + + + + + + + + + + Batch Queries | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + + + + + +
+

Batch Queries

+

cqlengine supports batch queries using the BatchQuery class. Batch queries can be started and stopped manually, or within a context manager. To add queries to the batch object, you just need to precede the create/save/delete call with a call to batch, and pass in the batch object.

+
+

Batch Query General Use Pattern

+

You can only create, update, and delete rows with a batch query, attempting to read rows out of the database with a batch query will fail.

+
from cassandra.cqlengine.query import BatchQuery
+
+#using a context manager
+with BatchQuery() as b:
+    now = datetime.now()
+    em1 = ExampleModel.batch(b).create(example_type=0, description="1", created_at=now)
+    em2 = ExampleModel.batch(b).create(example_type=0, description="2", created_at=now)
+    em3 = ExampleModel.batch(b).create(example_type=0, description="3", created_at=now)
+
+# -- or --
+
+#manually
+b = BatchQuery()
+now = datetime.now()
+em1 = ExampleModel.batch(b).create(example_type=0, description="1", created_at=now)
+em2 = ExampleModel.batch(b).create(example_type=0, description="2", created_at=now)
+em3 = ExampleModel.batch(b).create(example_type=0, description="3", created_at=now)
+b.execute()
+
+# updating in a batch
+
+b = BatchQuery()
+em1.description = "new description"
+em1.batch(b).save()
+em2.description = "another new description"
+em2.batch(b).save()
+b.execute()
+
+# deleting in a batch
+b = BatchQuery()
+ExampleModel.objects(id=some_id).batch(b).delete()
+ExampleModel.objects(id=some_id2).batch(b).delete()
+b.execute()
+
+
+

Typically you will not want the block to execute if an exception occurs inside the with block. However, in the case that this is desirable, it’s achievable by using the following syntax:

+
with BatchQuery(execute_on_exception=True) as b:
+    LogEntry.batch(b).create(k=1, v=1)
+    mystery_function() # exception thrown in here
+    LogEntry.batch(b).create(k=1, v=2) # this code is never reached due to the exception, but anything leading up to here will execute in the batch.
+
+
+

If an exception is thrown somewhere in the block, any statements that have been added to the batch will still be executed. This is useful for some logging situations.

+
+
+

Batch Query Execution Callbacks

+

In order to allow secondary tasks to be chained to the end of batch, BatchQuery instances allow callbacks to be +registered with the batch, to be executed immediately after the batch executes.

+

Multiple callbacks can be attached to same BatchQuery instance, they are executed in the same order that they +are added to the batch.

+

The callbacks attached to a given batch instance are executed only if the batch executes. If the batch is used as a +context manager and an exception is raised, the queued up callbacks will not be run.

+
def my_callback(*args, **kwargs):
+    pass
+
+batch = BatchQuery()
+
+batch.add_callback(my_callback)
+batch.add_callback(my_callback, 'positional arg', named_arg='named arg value')
+
+# if you need reference to the batch within the callback,
+# just trap it in the arguments to be passed to the callback:
+batch.add_callback(my_callback, cqlengine_batch=batch)
+
+# once the batch executes...
+batch.execute()
+
+# the effect of the above scheduled callbacks will be similar to
+my_callback()
+my_callback('positional arg', named_arg='named arg value')
+my_callback(cqlengine_batch=batch)
+
+
+

Failure in any of the callbacks does not affect the batch’s execution, as the callbacks are started after the execution +of the batch is complete.

+
+

Logged vs Unlogged Batches

+

By default, queries in cqlengine are LOGGED, which carries additional overhead from UNLOGGED. To explicitly state which batch type to use, simply:

+
from cassandra.cqlengine.query import BatchType
+with BatchQuery(batch_type=BatchType.Unlogged) as b:
+    LogEntry.batch(b).create(k=1, v=1)
+    LogEntry.batch(b).create(k=1, v=2)
+
+
+
+
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/stable/cqlengine/connections.html b/stable/cqlengine/connections.html new file mode 100644 index 0000000000..b3c4712d1b --- /dev/null +++ b/stable/cqlengine/connections.html @@ -0,0 +1,761 @@ + + + + + + + + + + + + + Connections | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + + + + + +
+

Connections

+

Connections aim to ease the use of multiple sessions with cqlengine. Connections can be set on a model class, per query or using a context manager.

+
+

Register a new connection

+

To use cqlengine, you need at least a default connection. If you initialize cqlengine’s connections with with connection.setup, a connection will be created automatically. If you want to use another cluster/session, you need to register a new cqlengine connection. You register a connection with register_connection():

+
from cassandra.cqlengine import connection
+
+connection.setup(['127.0.0.1')
+connection.register_connection('cluster2', ['127.0.0.2'])
+
+
+

register_connection() can take a list of hosts, as shown above, in which case it will create a connection with a new session. It can also take a session argument if you’ve already created a session:

+
from cassandra.cqlengine import connection
+from cassandra.cluster import Cluster
+
+session = Cluster(['127.0.0.1']).connect()
+connection.register_connection('cluster3', session=session)
+
+
+
+
+

Change the default connection

+

You can change the default cqlengine connection on registration:

+
from cassandra.cqlengine import connection
+
+connection.register_connection('cluster2', ['127.0.0.2'] default=True)
+
+
+

or on the fly using set_default_connection()

+
connection.set_default_connection('cluster2')
+
+
+
+
+

Unregister a connection

+

You can unregister a connection using unregister_connection():

+
connection.unregister_connection('cluster2')
+
+
+
+
+

Management

+

When using multiples connections, you also need to sync your models on all connections (and keyspaces) that you need operate on. Management commands have been improved to ease this part. Here is an example:

+
from cassandra.cqlengine import management
+
+keyspaces = ['ks1', 'ks2']
+conns = ['cluster1', 'cluster2']
+
+# registers your connections
+# ...
+
+# create all keyspaces on all connections
+for ks in keyspaces:
+    management.create_simple_keyspace(ks, connections=conns)
+
+# define your Automobile model
+# ...
+
+# sync your models
+management.sync_table(Automobile, keyspaces=keyspaces, connections=conns)
+
+
+
+
+

Connection Selection

+

cqlengine will select the default connection, unless your specify a connection using one of the following methods.

+
+

Default Model Connection

+

You can specify a default connection per model:

+
class Automobile(Model):
+    __keyspace__ = 'test'
+    __connection__ = 'cluster2'
+    manufacturer = columns.Text(primary_key=True)
+    year = columns.Integer(primary_key=True)
+    model = columns.Text(primary_key=True)
+
+print len(Automobile.objects.all())  # executed on the connection 'cluster2'
+
+
+
+
+

QuerySet and model instance

+

You can use the using() method to select a connection (or keyspace):

+
Automobile.objects.using(connection='cluster1').create(manufacturer='honda', year=2010, model='civic')
+q = Automobile.objects.filter(manufacturer='Tesla')
+autos = q.using(keyspace='ks2', connection='cluster2').all()
+
+for auto in autos:
+    auto.using(connection='cluster1').save()
+
+
+
+
+

Context Manager

+

You can use the ContextQuery as well to select a connection:

+
with ContextQuery(Automobile, connection='cluster1') as A:
+    A.objects.filter(manufacturer='honda').all()  # executed on 'cluster1'
+
+
+
+
+

BatchQuery

+

With a BatchQuery, you can select the connection with the context manager. Note that all operations in the batch need to use the same connection.

+
with BatchQuery(connection='cluster1') as b:
+    Automobile.objects.batch(b).create(manufacturer='honda', year=2010, model='civic')
+
+
+
+
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/stable/cqlengine/faq.html b/stable/cqlengine/faq.html new file mode 100644 index 0000000000..0bf71e8186 --- /dev/null +++ b/stable/cqlengine/faq.html @@ -0,0 +1,701 @@ + + + + + + + + + + + + + Frequently Asked Questions | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + + + +
+ +
+ +
+

Frequently Asked Questions

+
+

Why don’t updates work correctly on models instantiated as Model(field=value, field2=value2)?

+

The recommended way to create new rows is with the models .create method. The values passed into a model’s init method are interpreted by the model as the values as they were read from a row. This allows the model to “know” which rows have changed since the row was read out of cassandra, and create suitable update statements.

+
+
+

How to preserve ordering in batch query?

+

Statement Ordering is not supported by CQL3 batches. Therefore, +once cassandra needs resolving conflict(Updating the same column in one batch), +The algorithm below would be used.

+
    +
  • If timestamps are different, pick the column with the largest timestamp (the value being a regular column or a tombstone)

  • +
  • If timestamps are the same, and one of the columns in a tombstone (‘null’) - pick the tombstone

  • +
  • If timestamps are the same, and none of the columns are tombstones, pick the column with the largest value

  • +
+

Below is an example to show this scenario.

+
class MyMode(Model):
+    id    = columns.Integer(primary_key=True)
+    count = columns.Integer()
+    text  = columns.Text()
+
+with BatchQuery() as b:
+   MyModel.batch(b).create(id=1, count=2, text='123')
+   MyModel.batch(b).create(id=1, count=3, text='111')
+
+assert MyModel.objects(id=1).first().count == 3
+assert MyModel.objects(id=1).first().text  == '123'
+
+
+

The largest value of count is 3, and the largest value of text would be ‘123’.

+

The workaround is applying timestamp to each statement, then Cassandra would +resolve to the statement with the lastest timestamp.

+
with BatchQuery() as b:
+    MyModel.timestamp(datetime.now()).batch(b).create(id=1, count=2, text='123')
+    MyModel.timestamp(datetime.now()).batch(b).create(id=1, count=3, text='111')
+
+assert MyModel.objects(id=1).first().count == 3
+assert MyModel.objects(id=1).first().text  == '111'
+
+
+
+
+

How can I delete individual values from a row?

+

When inserting with CQLEngine, None is equivalent to CQL NULL or to +issuing a DELETE on that column. For example:

+
class MyModel(Model):
+    id    = columns.Integer(primary_key=True)
+    text  = columns.Text()
+
+m = MyModel.create(id=1, text='We can delete this with None')
+assert MyModel.objects(id=1).first().text is not None
+
+m.update(text=None)
+assert MyModel.objects(id=1).first().text is None
+
+
+
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/stable/cqlengine/models.html b/stable/cqlengine/models.html new file mode 100644 index 0000000000..0764fe29a6 --- /dev/null +++ b/stable/cqlengine/models.html @@ -0,0 +1,826 @@ + + + + + + + + + + + + + Models | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + + + + + +
+

Models

+

A model is a python class representing a CQL table. Models derive from Model, and +define basic table properties and columns for a table.

+

Columns in your models map to columns in your CQL table. You define CQL columns by defining column attributes on your model classes. +For a model to be valid it needs at least one primary key column and one non-primary key column. Just as in CQL, the order you define +your columns in is important, and is the same order they are defined in on a model’s corresponding table.

+

Some basic examples defining models are shown below. Consult the Model API docs and Column API docs for complete details.

+
+

Example Definitions

+

This example defines a Person table, with the columns first_name and last_name

+
from cassandra.cqlengine import columns
+from cassandra.cqlengine.models import Model
+
+ class Person(Model):
+     id = columns.UUID(primary_key=True)
+     first_name  = columns.Text()
+     last_name = columns.Text()
+
+
+

The Person model would create this CQL table:

+
CREATE TABLE cqlengine.person (
+    id uuid,
+    first_name text,
+    last_name text,
+    PRIMARY KEY (id)
+);
+
+
+

Here’s an example of a comment table created with clustering keys, in descending order:

+
from cassandra.cqlengine import columns
+from cassandra.cqlengine.models import Model
+
+class Comment(Model):
+    photo_id = columns.UUID(primary_key=True)
+    comment_id = columns.TimeUUID(primary_key=True, clustering_order="DESC")
+    comment = columns.Text()
+
+
+

The Comment model’s create table would look like the following:

+
CREATE TABLE comment (
+  photo_id uuid,
+  comment_id timeuuid,
+  comment text,
+  PRIMARY KEY (photo_id, comment_id)
+) WITH CLUSTERING ORDER BY (comment_id DESC);
+
+
+

To sync the models to the database, you may do the following*:

+
from cassandra.cqlengine.management import sync_table
+sync_table(Person)
+sync_table(Comment)
+
+
+

*Note: synchronizing models causes schema changes, and should be done with caution. +Please see the discussion in cassandra.cqlengine.management - Schema management for cqlengine for considerations.

+

For examples on manipulating data and creating queries, see Making Queries

+
+
+

Manipulating model instances as dictionaries

+

Model instances can be accessed like dictionaries.

+
class Person(Model):
+    first_name  = columns.Text()
+    last_name = columns.Text()
+
+kevin = Person.create(first_name="Kevin", last_name="Deldycke")
+dict(kevin)  # returns {'first_name': 'Kevin', 'last_name': 'Deldycke'}
+kevin['first_name']  # returns 'Kevin'
+kevin.keys()  # returns ['first_name', 'last_name']
+kevin.values()  # returns ['Kevin', 'Deldycke']
+kevin.items()  # returns [('first_name', 'Kevin'), ('last_name', 'Deldycke')]
+
+kevin['first_name'] = 'KEVIN5000'  # changes the models first name
+
+
+
+
+

Extending Model Validation

+

Each time you save a model instance in cqlengine, the data in the model is validated against the schema you’ve defined +for your model. Most of the validation is fairly straightforward, it basically checks that you’re not trying to do +something like save text into an integer column, and it enforces the required flag set on column definitions. +It also performs any transformations needed to save the data properly.

+

However, there are often additional constraints or transformations you want to impose on your data, beyond simply +making sure that Cassandra won’t complain when you try to insert it. To define additional validation on a model, +extend the model’s validation method:

+
class Member(Model):
+    person_id = UUID(primary_key=True)
+    name = Text(required=True)
+
+    def validate(self):
+        super(Member, self).validate()
+        if self.name == 'jon':
+            raise ValidationError('no jon\'s allowed')
+
+
+

Note: while not required, the convention is to raise a ValidationError (from cassandra.cqlengine import ValidationError) +if validation fails.

+
+
+

Model Inheritance

+

It is possible to save and load different model classes using a single CQL table. +This is useful in situations where you have different object types that you want to store in a single cassandra row.

+

For instance, suppose you want a table that stores rows of pets owned by an owner:

+
class Pet(Model):
+    __table_name__ = 'pet'
+    owner_id = UUID(primary_key=True)
+    pet_id = UUID(primary_key=True)
+    pet_type = Text(discriminator_column=True)
+    name = Text()
+
+    def eat(self, food):
+        pass
+
+    def sleep(self, time):
+        pass
+
+class Cat(Pet):
+    __discriminator_value__ = 'cat'
+    cuteness = Float()
+
+    def tear_up_couch(self):
+        pass
+
+class Dog(Pet):
+    __discriminator_value__ = 'dog'
+    fierceness = Float()
+
+    def bark_all_night(self):
+        pass
+
+
+

After calling sync_table on each of these tables, the columns defined in each model will be added to the +pet table. Additionally, saving Cat and Dog models will save the meta data needed to identify each row +as either a cat or dog.

+

To setup a model structure with inheritance, follow these steps

+
    +
  1. Create a base model with a column set as the distriminator (distriminator_column=True in the column definition)

  2. +
  3. Create subclass models, and define a unique __discriminator_value__ value on each

  4. +
  5. Run sync_table on each of the sub tables

  6. +
+

About the discriminator value

+

The discriminator value is what cqlengine uses under the covers to map logical cql rows to the appropriate model type. The +base model maintains a map of discriminator values to subclasses. When a specialized model is saved, its discriminator value is +automatically saved into the discriminator column. The discriminator column may be any column type except counter and container types. +Additionally, if you set index=True on your discriminator column, you can execute queries against specialized subclasses, and a +WHERE clause will be automatically added to your query, returning only rows of that type. Note that you must +define a unique __discriminator_value__ to each subclass, and that you can only assign a single discriminator column per model.

+
+
+

User Defined Types

+

cqlengine models User Defined Types (UDTs) much like tables, with fields defined by column type attributes. However, UDT instances +are only created, presisted, and queried via table Models. A short example to introduce the pattern:

+
from cassandra.cqlengine.columns import *
+from cassandra.cqlengine.models import Model
+from cassandra.cqlengine.usertype import UserType
+
+class address(UserType):
+    street = Text()
+    zipcode = Integer()
+
+class users(Model):
+    __keyspace__ = 'account'
+    name = Text(primary_key=True)
+    addr = UserDefinedType(address)
+
+users.create(name="Joe", addr=address(street="Easy St.", zipcode=99999))
+user = users.objects(name="Joe")[0]
+print user.name, user.addr
+# Joe address(street=u'Easy St.', zipcode=99999)
+
+
+

UDTs are modeled by inheriting UserType, and setting column type attributes. Types are then used in defining +models by declaring a column of type UserDefinedType, with the UserType class as a parameter.

+

sync_table will implicitly +synchronize any types contained in the table. Alternatively sync_type() can be used to create/alter types +explicitly.

+

Upon declaration, types are automatically registered with the driver, so query results return instances of your UserType +class*.

+

*Note: UDTs were not added to the native protocol until v3. When setting up the cqlengine connection, be sure to specify +protocol_version=3. If using an earlier version, UDT queries will still work, but the returned type will be a namedtuple.

+
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/stable/cqlengine/queryset.html b/stable/cqlengine/queryset.html new file mode 100644 index 0000000000..196599ae35 --- /dev/null +++ b/stable/cqlengine/queryset.html @@ -0,0 +1,998 @@ + + + + + + + + + + + + + Making Queries | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + + + +
+ +
+ +
+

Making Queries

+
+

Retrieving objects

+

Once you’ve populated Cassandra with data, you’ll probably want to retrieve some of it. This is accomplished with QuerySet objects. This section will describe how to use QuerySet objects to retrieve the data you’re looking for.

+
+

Retrieving all objects

+

The simplest query you can make is to return all objects from a table.

+

This is accomplished with the .all() method, which returns a QuerySet of all objects in a table

+

Using the Person example model, we would get all Person objects like this:

+
all_objects = Person.objects.all()
+
+
+
+
+

Retrieving objects with filters

+

Typically, you’ll want to query only a subset of the records in your database.

+

That can be accomplished with the QuerySet’s .filter(\*\*) method.

+

For example, given the model definition:

+
class Automobile(Model):
+    manufacturer = columns.Text(primary_key=True)
+    year = columns.Integer(primary_key=True)
+    model = columns.Text()
+    price = columns.Decimal()
+    options = columns.Set(columns.Text)
+
+
+

…and assuming the Automobile table contains a record of every car model manufactured in the last 20 years or so, we can retrieve only the cars made by a single manufacturer like this:

+
q = Automobile.objects.filter(manufacturer='Tesla')
+
+
+

You can also use the more convenient syntax:

+
q = Automobile.objects(Automobile.manufacturer == 'Tesla')
+
+
+

We can then further filter our query with another call to .filter

+
q = q.filter(year=2012)
+
+
+

Note: all queries involving any filtering MUST define either an ‘=’ or an ‘in’ relation to either a primary key column, or an indexed column.

+
+
+
+

Accessing objects in a QuerySet

+

There are several methods for getting objects out of a queryset

+
    +
  • +
    iterating over the queryset
    for car in Automobile.objects.all():
    +    #...do something to the car instance
    +    pass
    +
    +
    +
    +
    +
  • +
  • +
    list index
    q = Automobile.objects.all()
    +q[0] #returns the first result
    +q[1] #returns the second result
    +
    +
    +
    +

    Note

    +
      +
    • CQL does not support specifying a start position in it’s queries. Therefore, accessing elements using array indexing will load every result up to the index value requested

    • +
    • Using negative indices requires a “SELECT COUNT()” to be executed. This has a performance cost on large datasets.

    • +
    +
    +
    +
    +
  • +
  • +
    list slicing
    q = Automobile.objects.all()
    +q[1:] #returns all results except the first
    +q[1:9] #returns a slice of the results
    +
    +
    +
    +

    Note

    +
      +
    • CQL does not support specifying a start position in it’s queries. Therefore, accessing elements using array slicing will load every result up to the index value requested

    • +
    • Using negative indices requires a “SELECT COUNT()” to be executed. This has a performance cost on large datasets.

    • +
    +
    +
    +
    +
  • +
  • +
    calling get() on the queryset
    q = Automobile.objects.filter(manufacturer='Tesla')
    +q = q.filter(year=2012)
    +car = q.get()
    +
    +
    +

    this returns the object matching the queryset

    +
    +
    +
  • +
  • +
    calling first() on the queryset
    q = Automobile.objects.filter(manufacturer='Tesla')
    +q = q.filter(year=2012)
    +car = q.first()
    +
    +
    +

    this returns the first value in the queryset

    +
    +
    +
  • +
+
+
+

Filtering Operators

+

Equal To

+

The default filtering operator.

+
q = Automobile.objects.filter(manufacturer='Tesla')
+q = q.filter(year=2012)  #year == 2012
+
+
+

In addition to simple equal to queries, cqlengine also supports querying with other operators by appending a __<op> to the field name on the filtering call

+

in (__in)

+
q = Automobile.objects.filter(manufacturer='Tesla')
+q = q.filter(year__in=[2011, 2012])
+
+
+

> (__gt)

+
q = Automobile.objects.filter(manufacturer='Tesla')
+q = q.filter(year__gt=2010)  # year > 2010
+
+# or the nicer syntax
+
+q.filter(Automobile.year > 2010)
+
+
+

>= (__gte)

+
q = Automobile.objects.filter(manufacturer='Tesla')
+q = q.filter(year__gte=2010)  # year >= 2010
+
+# or the nicer syntax
+
+q.filter(Automobile.year >= 2010)
+
+
+

< (__lt)

+
q = Automobile.objects.filter(manufacturer='Tesla')
+q = q.filter(year__lt=2012)  # year < 2012
+
+# or...
+
+q.filter(Automobile.year < 2012)
+
+
+

<= (__lte)

+
q = Automobile.objects.filter(manufacturer='Tesla')
+q = q.filter(year__lte=2012)  # year <= 2012
+
+q.filter(Automobile.year <= 2012)
+
+
+

CONTAINS (__contains)

+

The CONTAINS operator is available for all collection types (List, Set, Map).

+
q = Automobile.objects.filter(manufacturer='Tesla')
+q.filter(options__contains='backup camera').allow_filtering()
+
+
+

Note that we need to use allow_filtering() since the options column has no secondary index.

+

LIKE (__like)

+

The LIKE operator is available for text columns that have a SASI secondary index.

+
q = Automobile.objects.filter(model__like='%Civic%').allow_filtering()
+
+
+

IS NOT NULL (IsNotNull(column_name))

+

The IS NOT NULL operator is not yet supported for C*.

+
q = Automobile.objects.filter(IsNotNull('model'))
+
+
+

Limitations:

+
    +
  • Currently, cqlengine does not support SASI index creation. To use this feature, you need to create the SASI index using the core driver.

  • +
  • Queries using LIKE must use allow_filtering() since the model column has no standard secondary index. Note that the server will use the SASI index properly when executing the query.

  • +
+
+
+

TimeUUID Functions

+

In addition to querying using regular values, there are two functions you can pass in when querying TimeUUID columns to help make filtering by them easier. Note that these functions don’t actually return a value, but instruct the cql interpreter to use the functions in it’s query.

+
+
+class cqlengine.queryset.MinTimeUUID(datetime)
+

returns the minimum time uuid value possible for the given datetime

+
+ +
+
+class cqlengine.queryset.MaxTimeUUID(datetime)
+

returns the maximum time uuid value possible for the given datetime

+
+ +

Example

+
class DataStream(Model):
+    id      = columns.UUID(partition_key=True)
+    time    = columns.TimeUUID(primary_key=True)
+    data    = columns.Bytes()
+
+min_time = datetime(1982, 1, 1)
+max_time = datetime(1982, 3, 9)
+
+DataStream.filter(time__gt=functions.MinTimeUUID(min_time), time__lt=functions.MaxTimeUUID(max_time))
+
+
+
+
+

Token Function

+

Token functon may be used only on special, virtual column pk__token, representing token of partition key (it also works for composite partition keys). +Cassandra orders returned items by value of partition key token, so using cqlengine.Token we can easy paginate through all table rows.

+

See http://cassandra.apache.org/doc/cql3/CQL-3.0.html#tokenFun

+

Example

+
class Items(Model):
+    id      = columns.Text(primary_key=True)
+    data    = columns.Bytes()
+
+query = Items.objects.all().limit(10)
+
+first_page = list(query);
+last = first_page[-1]
+next_page = list(query.filter(pk__token__gt=cqlengine.Token(last.pk)))
+
+
+
+
+

QuerySets are immutable

+

When calling any method that changes a queryset, the method does not actually change the queryset object it’s called on, but returns a new queryset object with the attributes of the original queryset, plus the attributes added in the method call.

+

Example

+
#this produces 3 different querysets
+#q does not change after it's initial definition
+q = Automobiles.objects.filter(year=2012)
+tesla2012 = q.filter(manufacturer='Tesla')
+honda2012 = q.filter(manufacturer='Honda')
+
+
+
+
+

Ordering QuerySets

+

Since Cassandra is essentially a distributed hash table on steroids, the order you get records back in will not be particularly predictable.

+

However, you can set a column to order on with the .order_by(column_name) method.

+

Example

+
#sort ascending
+q = Automobiles.objects.all().order_by('year')
+#sort descending
+q = Automobiles.objects.all().order_by('-year')
+
+
+

Note: Cassandra only supports ordering on a clustering key. In other words, to support ordering results, your model must have more than one primary key, and you must order on a primary key, excluding the first one.

+

For instance, given our Automobile model, year is the only column we can order on.

+
+
+

Values Lists

+

There is a special QuerySet’s method .values_list() - when called, QuerySet returns lists of values instead of model instances. It may significantly speedup things with lower memory footprint for large responses. +Each tuple contains the value from the respective field passed into the values_list() call — so the first item is the first field, etc. For example:

+
items = list(range(20))
+random.shuffle(items)
+for i in items:
+    TestModel.create(id=1, clustering_key=i)
+
+values = list(TestModel.objects.values_list('clustering_key', flat=True))
+# [19L, 18L, 17L, 16L, 15L, 14L, 13L, 12L, 11L, 10L, 9L, 8L, 7L, 6L, 5L, 4L, 3L, 2L, 1L, 0L]
+
+
+
+
+

Per Query Timeouts

+

By default all queries are executed with the timeout defined in ~cqlengine.connection.setup() +The examples below show how to specify a per-query timeout. +A timeout is specified in seconds and can be an int, float or None. +None means no timeout.

+
class Row(Model):
+    id = columns.Integer(primary_key=True)
+    name = columns.Text()
+
+
+

Fetch all objects with a timeout of 5 seconds

+
Row.objects().timeout(5).all()
+
+
+

Create a single row with a 50ms timeout

+
Row(id=1, name='Jon').timeout(0.05).create()
+
+
+

Delete a single row with no timeout

+
Row(id=1).timeout(None).delete()
+
+
+

Update a single row with no timeout

+
Row(id=1).timeout(None).update(name='Blake')
+
+
+

Batch query timeouts

+
with BatchQuery(timeout=10) as b:
+    Row(id=1, name='Jon').create()
+
+
+

NOTE: You cannot set both timeout and batch at the same time, batch will use the timeout defined in it’s constructor. +Setting the timeout on the model is meaningless and will raise an AssertionError.

+
+
+

Default TTL and Per Query TTL

+

Model default TTL now relies on the default_time_to_live feature, introduced in Cassandra 2.0. It is not handled anymore in the CQLEngine Model (scylla-driver >=3.6). You can set the default TTL of a table like this:

+

Example:

+
class User(Model):
+    __options__ = {'default_time_to_live': 20}
+
+    user_id = columns.UUID(primary_key=True)
+    ...
+
+
+

You can set TTL per-query if needed. Here are a some examples:

+

Example:

+
class User(Model):
+    __options__ = {'default_time_to_live': 20}
+
+    user_id = columns.UUID(primary_key=True)
+    ...
+
+user = User.objects.create(user_id=1)  # Default TTL 20 will be set automatically on the server
+
+user.ttl(30).update(age=21)            # Update the TTL to 30
+User.objects.ttl(10).create(user_id=1)  # TTL 10
+User(user_id=1, age=21).ttl(10).save()  # TTL 10
+
+
+
+
+

Named Tables

+

Named tables are a way of querying a table without creating an class. They’re useful for querying system tables or exploring an unfamiliar database.

+
from cassandra.cqlengine.connection import setup
+setup("127.0.0.1", "cqlengine_test")
+
+from cassandra.cqlengine.named import NamedTable
+user = NamedTable("cqlengine_test", "user")
+user.objects()
+user.objects()[0]
+
+# {u'pk': 1, u't': datetime.datetime(2014, 6, 26, 17, 10, 31, 774000)}
+
+
+
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/stable/cqlengine/third-party.html b/stable/cqlengine/third-party.html new file mode 100644 index 0000000000..ca367f6370 --- /dev/null +++ b/stable/cqlengine/third-party.html @@ -0,0 +1,698 @@ + + + + + + + + + + + + + Third party integrations | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + + + +
+ +
+ +
+

Third party integrations

+
+

Celery

+

Here’s how, in substance, CQLengine can be plugged to Celery:

+
from celery import Celery
+from celery.signals import worker_process_init, beat_init
+from cassandra.cqlengine import connection
+from cassandra.cqlengine.connection import (
+    cluster as cql_cluster, session as cql_session)
+
+def cassandra_init(**kwargs):
+    """ Initialize a clean Cassandra connection. """
+    if cql_cluster is not None:
+        cql_cluster.shutdown()
+    if cql_session is not None:
+        cql_session.shutdown()
+    connection.setup()
+
+# Initialize worker context for both standard and periodic tasks.
+worker_process_init.connect(cassandra_init)
+beat_init.connect(cassandra_init)
+
+app = Celery()
+
+
+
+
+

uWSGI

+

This is the code required for proper connection handling of CQLengine for a +uWSGI-run application:

+
from cassandra.cqlengine import connection
+from cassandra.cqlengine.connection import (
+    cluster as cql_cluster, session as cql_session)
+
+try:
+    from uwsgidecorators import postfork
+except ImportError:
+    # We're not in a uWSGI context, no need to hook Cassandra session
+    # initialization to the postfork event.
+    pass
+else:
+    @postfork
+    def cassandra_init(**kwargs):
+        """ Initialize a new Cassandra session in the context.
+
+        Ensures that a new session is returned for every new request.
+        """
+        if cql_cluster is not None:
+            cql_cluster.shutdown()
+        if cql_session is not None:
+            cql_session.shutdown()
+        connection.setup()
+
+
+
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/stable/cqlengine/upgrade-guide.html b/stable/cqlengine/upgrade-guide.html new file mode 100644 index 0000000000..78e837ac6c --- /dev/null +++ b/stable/cqlengine/upgrade-guide.html @@ -0,0 +1,830 @@ + + + + + + + + + + + + + Upgrade Guide | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + + + + + +
+

Upgrade Guide

+

This is an overview of things that changed as the cqlengine project was merged into +scylla-driver. While efforts were taken to preserve the API and most functionality exactly, +conversion to this package will still require certain minimal updates (namely, imports).

+

THERE IS ONE FUNCTIONAL CHANGE, described in the first section below.

+
+

Functional Changes

+
+

List Prepend Reversing

+

Legacy cqlengine included a workaround for a Cassandra bug in which prepended list segments were +reversed (CASSANDRA-8733). As of +this integration, this workaround is removed. The first released integrated version emits +a warning when prepend is used. Subsequent versions will have this warning removed.

+
+
+

Date Column Type

+

The Date column type in legacy cqlengine used a timestamp CQL type and truncated the time. +Going forward, the Date type represents a date for Cassandra 2.2+ +(PYTHON-245). +Users of the legacy functionality should convert models to use DateTime (which +uses timestamp internally), and use the build-in datetime.date for input values.

+
+
+
+

Remove cqlengine

+

To avoid confusion or mistakes using the legacy package in your application, it +is prudent to remove the cqlengine package when upgrading to the integrated version.

+

The driver setup script will warn if the legacy package is detected during install, +but it will not prevent side-by-side installation.

+
+
+

Organization

+
+

Imports

+

cqlengine is now integrated as a sub-package of the driver base package ‘cassandra’. +Upgrading will require adjusting imports to cqlengine. For example:

+
from cassandra.cqlengine import columns
+
+
+

is now:

+
from cassandra.cqlengine import columns
+
+
+
+
+

Package-Level Aliases

+

Legacy cqlengine defined a number of aliases at the package level, which became redundant +when the package was integrated for a driver. These have been removed in favor of absolute +imports, and referring to cannonical definitions. For example, cqlengine.ONE was an alias +of cassandra.ConsistencyLevel.ONE. In the integrated package, only the +cassandra.ConsistencyLevel remains.

+

Additionally, submodule aliases are removed from cqlengine in favor of absolute imports.

+

These aliases are removed, and not deprecated because they should be straightforward to iron out +at module load time.

+
+
+

Exceptions

+

The legacy cqlengine.exceptions module had a number of Exception classes that were variously +common to the package, or only used in specific modules. Common exceptions were relocated to +cqlengine, and specialized exceptions were placed in the module that raises them. Below is a +listing of updated locations:

+ ++++ + + + + + + + + + + + + + + + + + + + + + + + + + +

Exception class

New module

CQLEngineException

cassandra.cqlengine

ModelException

cassandra.cqlengine.models

ValidationError

cassandra.cqlengine

UndefinedKeyspaceException

cassandra.cqlengine.connection

LWTException

cassandra.cqlengine.query

IfNotExistsWithCounterColumn

cassandra.cqlengine.query

+
+
+

UnicodeMixin Consolidation

+

class UnicodeMixin was defined in several cqlengine modules. This has been consolidated +to a single definition in the cqlengine package init file. This is not technically part of +the API, but noted here for completeness.

+
+
+
+

API Deprecations

+

This upgrade served as a good juncture to deprecate certain API features and invite users to upgrade +to new ones. The first released version does not change functionality – only introduces deprecation +warnings. Future releases will remove these features in favor of the alternatives.

+
+

Float/Double Overload

+

Previously there was no Double column type. Doubles were modeled by specifying Float(double_precision=True). +This inititializer parameter is now deprecated. Applications should use Double for CQL double, and Float +for CQL float.

+
+
+

Schema Management

+

cassandra.cqlengine.management.create_keyspace is deprecated. Instead, use the new replication-strategy-specific +functions that accept explicit options for known strategies:

+ +

cassandra.cqlengine.management.delete_keyspace is deprecated in favor of a new function, drop_keyspace(). The +intent is simply to make the function match the CQL verb it invokes.

+
+
+

Model Inheritance

+

The names for class attributes controlling model inheritance are changing. Changes are as follows:

+ +

The functionality is unchanged – the intent here is to make the names and language around these attributes more precise. +For now, the old names are just deprecated, and the mapper will emit warnings if they are used. The old names +will be removed in a future version.

+

The example below shows a simple translation:

+

Before:

+
class Pet(Model):
+    __table_name__ = 'pet'
+    owner_id = UUID(primary_key=True)
+    pet_id = UUID(primary_key=True)
+    pet_type = Text(polymorphic_key=True)
+    name = Text()
+
+class Cat(Pet):
+    __polymorphic_key__ = 'cat'
+
+class Dog(Pet):
+    __polymorphic_key__ = 'dog'
+
+
+

After:

+
class Pet(models.Model):
+    __table_name__ = 'pet'
+    owner_id = UUID(primary_key=True)
+    pet_id = UUID(primary_key=True)
+    pet_type = Text(discriminator_column=True)
+    name = Text()
+
+class Cat(Pet):
+    __discriminator_value__ = 'cat'
+
+class Dog(Pet):
+    __discriminator_value__ = 'dog'
+
+
+
+
+

TimeUUID.from_datetime

+

This function is deprecated in favor of the core utility function uuid_from_time().

+
+
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/stable/dates-and-times.html b/stable/dates-and-times.html new file mode 100644 index 0000000000..36236ab3be --- /dev/null +++ b/stable/dates-and-times.html @@ -0,0 +1,722 @@ + + + + + + + + + + + + + Working with Dates and Times | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + + + +
+ +
+ +
+

Working with Dates and Times

+

This document is meant to provide on overview of the assumptions and limitations of the driver time handling, the +reasoning behind it, and describe approaches to working with these types.

+
+

timestamps (Cassandra DateType)

+

Timestamps in Cassandra are timezone-naive timestamps encoded as millseconds since UNIX epoch. Clients working with +timestamps in this database usually find it easiest to reason about them if they are always assumed to be UTC. To quote the +pytz documentation, “The preferred way of dealing with times is to always work in UTC, converting to localtime only when +generating output to be read by humans.” The driver adheres to this tenant, and assumes UTC is always in the database. The +driver attempts to make this correct on the way in, and assumes no timezone on the way out.

+
+

Write Path

+

When inserting timestamps, the driver handles serialization for the write path as follows:

+

If the input is a datetime.datetime, the serialization is normalized by starting with the utctimetuple() of the +value.

+
    +
  • If the datetime object is timezone-aware, the timestamp is shifted, and represents the UTC timestamp equivalent.

  • +
  • If the datetime object is timezone-naive, this results in no shift – any datetime with no timezone information is assumed to be UTC

  • +
+

Note the second point above applies even to “local” times created using now():

+
>>> d = datetime.now()
+
+>>> print(d.tzinfo)
+None
+
+
+

These do not contain timezone information intrinsically, so they will be assumed to be UTC and not shifted. When generating +timestamps in the application, it is clearer to use datetime.utcnow() to be explicit about it.

+

If the input for a timestamp is numeric, it is assumed to be a epoch-relative millisecond timestamp, as specified in the +CQL spec – no scaling or conversion is done.

+
+
+

Read Path

+

The driver always assumes persisted timestamps are UTC and makes no attempt to localize them. Returned values are +timezone-naive datetime.datetime. We follow this approach because the datetime API has deficiencies around daylight +saving time, and the defacto package for handling this is a third-party package (we try to minimize external dependencies +and not make decisions for the integrator).

+

The decision for how to handle timezones is left to the application. For the most part it is straightforward to apply +localization to the datetimes returned by queries. One prevalent method is to use pytz for localization:

+
import pytz
+user_tz = pytz.timezone('US/Central')
+timestamp_naive = row.ts
+timestamp_utc = pytz.utc.localize(timestamp_naive)
+timestamp_presented = timestamp_utc.astimezone(user_tz)
+
+
+

This is the most robust approach (likely refactored into a function). If it is deemed too cumbersome to apply for all call +sites in the application, it is possible to patch the driver with custom deserialization for this type. However, doing +this depends depends some on internal APIs and what extensions are present, so we will only mention the possibility, and +not spell it out here.

+
+
+
+

date, time (Cassandra DateType)

+

Date and time in Cassandra are idealized markers, much like datetime.date and datetime.time in the Python standard +library. Unlike these Python implementations, the Cassandra encoding supports much wider ranges. To accommodate these +ranges without overflow, this driver returns these data in custom types: util.Date and util.Time.

+
+

Write Path

+

For simple (not prepared) statements, the input values for each of these can be either a string literal or an encoded +integer. See Working with dates +or Working with time for details +on the encoding or string formats.

+

For prepared statements, the driver accepts anything that can be used to construct the util.Date or +util.Time classes. See the linked API docs for details.

+
+
+

Read Path

+

The driver always returns custom types for date and time.

+

The driver returns util.Date for date in order to accommodate the wider range of values without overflow. +For applications working within the supported range of [datetime.MINYEAR, datetime.MAXYEAR], these are easily +converted to standard datetime.date insances using Date.date().

+

The driver returns util.Time for time in order to retain nanosecond precision stored in the database. +For applications not concerned with this level of precision, these are easily converted to standard datetime.time +insances using Time.time().

+
+
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/stable/execution-profiles.html b/stable/execution-profiles.html new file mode 100644 index 0000000000..a181436d2a --- /dev/null +++ b/stable/execution-profiles.html @@ -0,0 +1,766 @@ + + + + + + + + + + + + + Execution Profiles | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + + + +
+ +
+ +
+

Execution Profiles

+

Execution profiles aim at making it easier to execute requests in different ways within +a single connected Session. Execution profiles are being introduced to deal with the exploding number of +configuration options, especially as the database platform evolves more complex workloads.

+

The legacy configuration remains intact, but legacy and Execution Profile APIs +cannot be used simultaneously on the same client Cluster. Legacy configuration +will be removed in the next major release (4.0).

+

An execution profile and its parameters should be unique across Cluster instances. +For example, an execution profile and its LoadBalancingPolicy should +not be applied to more than one Cluster instance.

+

This document explains how Execution Profiles relate to existing settings, and shows how to use the new profiles for +request execution.

+
+

Mapping Legacy Parameters to Profiles

+

Execution profiles can inherit from cluster.ExecutionProfile, and currently provide the following options, +previously input from the noted attributes:

+ +

When using the new API, these parameters can be defined by instances of cluster.ExecutionProfile.

+
+
+

Using Execution Profiles

+
+

Default

+
from cassandra.cluster import Cluster
+cluster = Cluster()
+session = cluster.connect()
+local_query = 'SELECT rpc_address FROM system.local'
+for _ in cluster.metadata.all_hosts():
+    print session.execute(local_query)[0]
+
+
+
Row(rpc_address='127.0.0.2')
+Row(rpc_address='127.0.0.1')
+
+
+

The default execution profile is built from Cluster parameters and default Session attributes. This profile matches existing default +parameters.

+
+
+

Initializing cluster with profiles

+
from cassandra.cluster import ExecutionProfile
+from cassandra.policies import WhiteListRoundRobinPolicy
+
+node1_profile = ExecutionProfile(load_balancing_policy=WhiteListRoundRobinPolicy(['127.0.0.1']))
+node2_profile = ExecutionProfile(load_balancing_policy=WhiteListRoundRobinPolicy(['127.0.0.2']))
+
+profiles = {'node1': node1_profile, 'node2': node2_profile}
+session = Cluster(execution_profiles=profiles).connect()
+for _ in cluster.metadata.all_hosts():
+    print session.execute(local_query, execution_profile='node1')[0]
+
+
+
Row(rpc_address='127.0.0.1')
+Row(rpc_address='127.0.0.1')
+
+
+
for _ in cluster.metadata.all_hosts():
+    print session.execute(local_query, execution_profile='node2')[0]
+
+
+
Row(rpc_address='127.0.0.2')
+Row(rpc_address='127.0.0.2')
+
+
+
for _ in cluster.metadata.all_hosts():
+    print session.execute(local_query)[0]
+
+
+
Row(rpc_address='127.0.0.2')
+Row(rpc_address='127.0.0.1')
+
+
+

Note that, even when custom profiles are injected, the default TokenAwarePolicy(DCAwareRoundRobinPolicy()) is still +present. To override the default, specify a policy with the EXEC_PROFILE_DEFAULT key.

+
from cassandra.cluster import EXEC_PROFILE_DEFAULT
+profile = ExecutionProfile(request_timeout=30)
+cluster = Cluster(execution_profiles={EXEC_PROFILE_DEFAULT: profile})
+
+
+
+
+

Adding named profiles

+

New profiles can be added constructing from scratch, or deriving from default:

+
locked_execution = ExecutionProfile(load_balancing_policy=WhiteListRoundRobinPolicy(['127.0.0.1']))
+node1_profile = 'node1_whitelist'
+cluster.add_execution_profile(node1_profile, locked_execution)
+
+for _ in cluster.metadata.all_hosts():
+    print session.execute(local_query, execution_profile=node1_profile)[0]
+
+
+
Row(rpc_address='127.0.0.1')
+Row(rpc_address='127.0.0.1')
+
+
+

See Cluster.add_execution_profile() for details and optional parameters.

+
+
+

Passing a profile instance without mapping

+

We also have the ability to pass profile instances to be used for execution, but not added to the mapping:

+
from cassandra.query import tuple_factory
+
+tmp = session.execution_profile_clone_update('node1', request_timeout=100, row_factory=tuple_factory)
+
+print session.execute(local_query, execution_profile=tmp)[0]
+print session.execute(local_query, execution_profile='node1')[0]
+
+
+
('127.0.0.1',)
+Row(rpc_address='127.0.0.1')
+
+
+

The new profile is a shallow copy, so the tmp profile shares a load balancing policy with one managed by the cluster. +If reference objects are to be updated in the clone, one would typically set those attributes to a new instance.

+
+
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/stable/faq.html b/stable/faq.html new file mode 100644 index 0000000000..3e0d44a260 --- /dev/null +++ b/stable/faq.html @@ -0,0 +1,702 @@ + + + + + + + + + + + + + Frequently Asked Questions | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + + + +
+ +
+ +
+

Frequently Asked Questions

+

See also cqlengine FAQ

+
+

Why do connections or IO operations timeout in my WSGI application?

+

Depending on your application process model, it may be forking after driver Session is created. Most IO reactors do not handle this, and problems will manifest as timeouts.

+

To avoid this, make sure to create sessions per process, after the fork. Using uWSGI and Flask for example:

+
from flask import Flask
+from uwsgidecorators import postfork
+from cassandra.cluster import Cluster
+
+session = None
+prepared = None
+
+@postfork
+def connect():
+    global session, prepared
+    session = Cluster().connect()
+    prepared = session.prepare("SELECT release_version FROM system.local WHERE key=?")
+
+app = Flask(__name__)
+
+@app.route('/')
+def server_version():
+    row = session.execute(prepared, ('local',))[0]
+    return row.release_version
+
+
+

uWSGI provides a postfork hook you can use to create sessions and prepared statements after the child process forks.

+
+
+

How do I trace a request?

+

Request tracing can be turned on for any request by setting trace=True in Session.execute_async(). View the results by waiting on the future, then ResponseFuture.get_query_trace(). +Since tracing is done asynchronously to the request, this method polls until the trace is complete before querying data.

+
>>> future = session.execute_async("SELECT * FROM system.local", trace=True)
+>>> result = future.result()
+>>> trace = future.get_query_trace()
+>>> for e in trace.events:
+>>>     print e.source_elapsed, e.description
+
+0:00:00.000077 Parsing select * from system.local
+0:00:00.000153 Preparing statement
+0:00:00.000309 Computing ranges to query
+0:00:00.000368 Submitting range requests on 1 ranges with a concurrency of 1 (279.77142 rows per range expected)
+0:00:00.000422 Submitted 1 concurrent range requests covering 1 ranges
+0:00:00.000480 Executing seq scan across 1 sstables for (min(-9223372036854775808), min(-9223372036854775808))
+0:00:00.000669 Read 1 live and 0 tombstone cells
+0:00:00.000755 Scanned 1 rows and matched 1
+
+
+

trace is a QueryTrace object.

+
+
+

How do I determine the replicas for a query?

+

With prepared statements, the replicas are obtained by routing_key, based on current cluster token metadata:

+
>>> prepared = session.prepare("SELECT * FROM example.t WHERE key=?")
+>>> bound = prepared.bind((1,))
+>>> replicas = cluster.metadata.get_replicas(bound.keyspace, bound.routing_key)
+>>> for h in replicas:
+>>>   print h.address
+127.0.0.1
+127.0.0.2
+
+
+

replicas is a list of Host objects.

+
+
+

How does the driver manage request retries?

+

By default, retries are managed by the Cluster.default_retry_policy set on the session Cluster. It can also +be specialized per statement by setting Statement.retry_policy.

+

Retries are presently attempted on the same coordinator, but this may change in the future.

+

Please see policies.RetryPolicy for further details.

+
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/stable/getting-started.html b/stable/getting-started.html new file mode 100644 index 0000000000..54d690f145 --- /dev/null +++ b/stable/getting-started.html @@ -0,0 +1,1117 @@ + + + + + + + + + + + + + Getting Started | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + + + +
+ +
+ +
+

Getting Started

+

First, make sure you have the driver properly installed.

+
+

Connecting to a Cluster

+

Before we can start executing any queries against a Cassandra cluster we need to setup +an instance of Cluster. As the name suggests, you will typically have one +instance of Cluster for each Cassandra cluster you want to interact +with.

+

First, make sure you have the Cassandra driver properly installed.

+
+

Connecting to Cassandra

+

The simplest way to create a Cluster is like this:

+
from cassandra.cluster import Cluster
+
+cluster = Cluster()
+
+
+

This will attempt to connection to a Cassandra instance on your +local machine (127.0.0.1). You can also specify a list of IP +addresses for nodes in your cluster:

+
from cassandra.cluster import Cluster
+
+cluster = Cluster(['192.168.0.1', '192.168.0.2'])
+
+
+

The set of IP addresses we pass to the Cluster is simply +an initial set of contact points. After the driver connects to one +of these nodes it will automatically discover the rest of the +nodes in the cluster and connect to them, so you don’t need to list +every node in your cluster.

+

If you need to use a non-standard port, use SSL, or customize the driver’s +behavior in some other way, this is the place to do it:

+
from cassandra.cluster import Cluster
+cluster = Cluster(['192.168.0.1', '192.168.0.2'], port=..., ssl_context=...)
+
+
+

Instantiating a Cluster does not actually connect us to any nodes. +To establish connections and begin executing queries we need a +Session, which is created by calling Cluster.connect():

+
cluster = Cluster()
+session = cluster.connect()
+
+
+
+
+
+

Session Keyspace

+

The connect() method takes an optional keyspace argument +which sets the default keyspace for all queries made through that Session:

+
cluster = Cluster()
+session = cluster.connect('mykeyspace')
+
+
+

You can always change a Session’s keyspace using set_keyspace() or +by executing a USE <keyspace> query:

+
session.set_keyspace('users')
+# or you can do this instead
+session.execute('USE users')
+
+
+
+
+

Execution Profiles

+

Profiles are passed in by execution_profiles dict.

+

In this case we can construct the base ExecutionProfile passing all attributes:

+
from cassandra.cluster import Cluster, ExecutionProfile, EXEC_PROFILE_DEFAULT
+from cassandra.policies import WhiteListRoundRobinPolicy, DowngradingConsistencyRetryPolicy
+from cassandra.query import tuple_factory
+
+profile = ExecutionProfile(
+    load_balancing_policy=WhiteListRoundRobinPolicy(['127.0.0.1']),
+    retry_policy=DowngradingConsistencyRetryPolicy(),
+    consistency_level=ConsistencyLevel.LOCAL_QUORUM,
+    serial_consistency_level=ConsistencyLevel.LOCAL_SERIAL,
+    request_timeout=15,
+    row_factory=tuple_factory
+)
+cluster = Cluster(execution_profiles={EXEC_PROFILE_DEFAULT: profile})
+session = cluster.connect()
+
+print(session.execute("SELECT release_version FROM system.local").one())
+
+
+

Users are free to setup additional profiles to be used by name:

+
profile_long = ExecutionProfile(request_timeout=30)
+cluster = Cluster(execution_profiles={'long': profile_long})
+session = cluster.connect()
+session.execute(statement, execution_profile='long')
+
+
+

Also, parameters passed to Session.execute or attached to Statements are still honored as before.

+
+
+

Executing Queries

+

Now that we have a Session we can begin to execute queries. The simplest +way to execute a query is to use execute():

+
rows = session.execute('SELECT name, age, email FROM users')
+for user_row in rows:
+    print user_row.name, user_row.age, user_row.email
+
+
+

This will transparently pick a Cassandra node to execute the query against +and handle any retries that are necessary if the operation fails.

+

By default, each row in the result set will be a +namedtuple. +Each row will have a matching attribute for each column defined in the schema, +such as name, age, and so on. You can also treat them as normal tuples +by unpacking them or accessing fields by position. The following three +examples are equivalent:

+
rows = session.execute('SELECT name, age, email FROM users')
+for row in rows:
+    print row.name, row.age, row.email
+
+
+
rows = session.execute('SELECT name, age, email FROM users')
+for (name, age, email) in rows:
+    print name, age, email
+
+
+
rows = session.execute('SELECT name, age, email FROM users')
+for row in rows:
+    print row[0], row[1], row[2]
+
+
+

If you prefer another result format, such as a dict per row, you +can change the row_factory attribute.

+

As mentioned in our Drivers Best Practices Guide, +it is highly recommended to use Prepared statements for your +frequently run queries.

+
+
+

Prepared Statements

+

Prepared statements are queries that are parsed by Cassandra and then saved +for later use. When the driver uses a prepared statement, it only needs to +send the values of parameters to bind. This lowers network traffic +and CPU utilization within Cassandra because Cassandra does not have to +re-parse the query each time.

+

To prepare a query, use Session.prepare():

+
user_lookup_stmt = session.prepare("SELECT * FROM users WHERE user_id=?")
+
+users = []
+for user_id in user_ids_to_query:
+    user = session.execute(user_lookup_stmt, [user_id])
+    users.append(user)
+
+
+

prepare() returns a PreparedStatement instance +which can be used in place of SimpleStatement instances or literal +string queries. It is automatically prepared against all nodes, and the driver +handles re-preparing against new nodes and restarted nodes when necessary.

+

Note that the placeholders for prepared statements are ? characters. This +is different than for simple, non-prepared statements (although future versions +of the driver may use the same placeholders for both).

+
+
+

Passing Parameters to CQL Queries

+

Althought it is not recommended, you can also pass parameters to non-prepared +statements. The driver supports two forms of parameter place-holders: positional +and named.

+

Positional parameters are used with a %s placeholder. For example, +when you execute:

+
session.execute(
+    """
+    INSERT INTO users (name, credits, user_id)
+    VALUES (%s, %s, %s)
+    """,
+    ("John O'Reilly", 42, uuid.uuid1())
+)
+
+
+

It is translated to the following CQL query:

+
INSERT INTO users (name, credits, user_id)
+VALUES ('John O''Reilly', 42, 2644bada-852c-11e3-89fb-e0b9a54a6d93)
+
+
+

Note that you should use %s for all types of arguments, not just strings. +For example, this would be wrong:

+
session.execute("INSERT INTO USERS (name, age) VALUES (%s, %d)", ("bob", 42))  # wrong
+
+
+

Instead, use %s for the age placeholder.

+

If you need to use a literal % character, use %%.

+

Note: you must always use a sequence for the second argument, even if you are +only passing in a single variable:

+
session.execute("INSERT INTO foo (bar) VALUES (%s)", "blah")  # wrong
+session.execute("INSERT INTO foo (bar) VALUES (%s)", ("blah"))  # wrong
+session.execute("INSERT INTO foo (bar) VALUES (%s)", ("blah", ))  # right
+session.execute("INSERT INTO foo (bar) VALUES (%s)", ["blah"])  # right
+
+
+

Note that the second line is incorrect because in Python, single-element tuples +require a comma.

+

Named place-holders use the %(name)s form:

+
session.execute(
+    """
+    INSERT INTO users (name, credits, user_id, username)
+    VALUES (%(name)s, %(credits)s, %(user_id)s, %(name)s)
+    """,
+    {'name': "John O'Reilly", 'credits': 42, 'user_id': uuid.uuid1()}
+)
+
+
+

Note that you can repeat placeholders with the same name, such as %(name)s +in the above example.

+

Only data values should be supplied this way. Other items, such as keyspaces, +table names, and column names should be set ahead of time (typically using +normal string formatting).

+
+
+

Type Conversions

+

For non-prepared statements, Python types are cast to CQL literals in the +following way:

+ ++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Python Type

CQL Literal Type

None

NULL

bool

boolean

float

+
float
+
double
+
+
+
int
+
long
+
+
+
int
+
bigint
+
varint
+
smallint
+
tinyint
+
counter
+
+

decimal.Decimal

decimal

+
str
+
unicode
+
+
+
ascii
+
varchar
+
text
+
+
+
buffer
+
bytearray
+
+

blob

date

date

datetime

timestamp

time

time

+
list
+
tuple
+
generator
+
+

list

+
set
+
frozenset
+
+

set

+
dict
+
OrderedDict
+
+

map

uuid.UUID

+
timeuuid
+
uuid
+
+
+
+
+

Asynchronous Queries

+

The driver supports asynchronous query execution through +execute_async(). Instead of waiting for the query to +complete and returning rows directly, this method almost immediately +returns a ResponseFuture object. There are two ways of +getting the final result from this object.

+

The first is by calling result() on it. If +the query has not yet completed, this will block until it has and +then return the result or raise an Exception if an error occurred. +For example:

+
from cassandra import ReadTimeout
+
+query = "SELECT * FROM users WHERE user_id=%s"
+future = session.execute_async(query, [user_id])
+
+# ... do some other work
+
+try:
+    rows = future.result()
+    user = rows[0]
+    print user.name, user.age
+except ReadTimeout:
+    log.exception("Query timed out:")
+
+
+

This works well for executing many queries concurrently:

+
# build a list of futures
+futures = []
+query = "SELECT * FROM users WHERE user_id=%s"
+for user_id in ids_to_fetch:
+    futures.append(session.execute_async(query, [user_id])
+
+# wait for them to complete and use the results
+for future in futures:
+    rows = future.result()
+    print rows[0].name
+
+
+

Alternatively, instead of calling result(), +you can attach callback and errback functions through the +add_callback(), +add_errback(), and +add_callbacks(), methods. If you have used +Twisted Python before, this is designed to be a lightweight version of +that:

+
def handle_success(rows):
+    user = rows[0]
+    try:
+        process_user(user.name, user.age, user.id)
+    except Exception:
+        log.error("Failed to process user %s", user.id)
+        # don't re-raise errors in the callback
+
+def handle_error(exception):
+    log.error("Failed to fetch user info: %s", exception)
+
+
+future = session.execute_async(query)
+future.add_callbacks(handle_success, handle_error)
+
+
+
+
There are a few important things to remember when working with callbacks:
    +
  • Exceptions that are raised inside the callback functions will be logged and then ignored.

  • +
  • Your callback will be run on the event loop thread, so any long-running +operations will prevent other requests from being handled

  • +
+
+
+
+
+

Setting a Consistency Level

+

The consistency level used for a query determines how many of the +replicas of the data you are interacting with need to respond for +the query to be considered a success.

+

By default, ConsistencyLevel.LOCAL_ONE will be used for all queries. +You can specify a different default by setting the ExecutionProfile.consistency_level +for the execution profile with key EXEC_PROFILE_DEFAULT. +To specify a different consistency level per request, wrap queries +in a SimpleStatement:

+
from cassandra import ConsistencyLevel
+from cassandra.query import SimpleStatement
+
+query = SimpleStatement(
+    "INSERT INTO users (name, age) VALUES (%s, %s)",
+    consistency_level=ConsistencyLevel.QUORUM)
+session.execute(query, ('John', 42))
+
+
+
+
+

Setting a Consistency Level with Prepared Statements

+

To specify a consistency level for prepared statements, you have two options.

+

The first is to set a default consistency level for every execution of the +prepared statement:

+
from cassandra import ConsistencyLevel
+
+cluster = Cluster()
+session = cluster.connect("mykeyspace")
+user_lookup_stmt = session.prepare("SELECT * FROM users WHERE user_id=?")
+user_lookup_stmt.consistency_level = ConsistencyLevel.QUORUM
+
+# these will both use QUORUM
+user1 = session.execute(user_lookup_stmt, [user_id1])[0]
+user2 = session.execute(user_lookup_stmt, [user_id2])[0]
+
+
+

The second option is to create a BoundStatement from the +PreparedStatement and binding parameters and set a consistency +level on that:

+
# override the QUORUM default
+user3_lookup = user_lookup_stmt.bind([user_id3])
+user3_lookup.consistency_level = ConsistencyLevel.ALL
+user3 = session.execute(user3_lookup)
+
+
+
+
+

Speculative Execution

+

Speculative execution is a way to minimize latency by preemptively executing several +instances of the same query against different nodes. For more details about this +technique, see Speculative Execution with DataStax Drivers.

+

To enable speculative execution:

+
    +
  • Configure a SpeculativeExecutionPolicy with the ExecutionProfile

  • +
  • Mark your query as idempotent, which mean it can be applied multiple +times without changing the result of the initial application. +See Query Idempotence for more details.

  • +
+

Example:

+
from cassandra.cluster import Cluster, ExecutionProfile, EXEC_PROFILE_DEFAULT
+from cassandra.policies import ConstantSpeculativeExecutionPolicy
+from cassandra.query import SimpleStatement
+
+# Configure the speculative execution policy
+ep = ExecutionProfile(
+    speculative_execution_policy=ConstantSpeculativeExecutionPolicy(delay=.5, max_attempts=10)
+)
+cluster = Cluster(..., execution_profiles={EXEC_PROFILE_DEFAULT: ep})
+session = cluster.connect()
+
+# Mark the query idempotent
+query = SimpleStatement(
+    "UPDATE my_table SET list_col = [1] WHERE pk = 1",
+    is_idempotent=True
+)
+
+# Execute. A new query will be sent to the server every 0.5 second
+# until we receive a response, for a max number attempts of 10.
+session.execute(query)
+
+
+
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/stable/index.html b/stable/index.html new file mode 100644 index 0000000000..951dc39070 --- /dev/null +++ b/stable/index.html @@ -0,0 +1,694 @@ + + + + + + + + + + + + + Python Driver for Scylla and Apache Cassandra® | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + + + +
+ +
+ +
+

Python Driver for Scylla and Apache Cassandra®

+

A Python client driver for Scylla. +This driver works exclusively with the Cassandra Query Language v3 (CQL3) +and Cassandra’s native protocol.

+

The driver supports Python 2.7, 3.5, 3.6, 3.7 and 3.8.

+

This driver is open source under the +Apache v2 License. +The source code for this driver can be found on GitHub.

+

Scylla Driver is a fork from DataStax Python Driver, including some non-breaking changes for Scylla optimization, with more updates planned.

+
+

Contents

+
+
Installation

How to install the driver.

+
+
Getting Started

A guide through the first steps of connecting to Scylla and executing queries

+
+
Scylla Specific Features

A list of feature available only on scylla-driver

+
+
Execution Profiles

An introduction to a more flexible way of configuring request execution

+
+
Lightweight Transactions (Compare-and-set)

Working with results of conditional requests

+
+
Object Mapper

Introduction to the integrated object mapper, cqlengine

+
+
Performance Notes

Tips for getting good performance.

+
+
Paging Large Queries

Notes on paging large query results

+
+
Security

An overview of the security features of the driver

+
+
Upgrading

A guide to upgrading versions of the driver

+
+
User Defined Types

Working with Scylla’s user-defined types (UDT)

+
+
Working with Dates and Times

Some discussion on the driver’s approach to working with timestamp, date, time types

+
+
ScyllaDB Cloud

Connect to ScyllaDB Cloud

+
+
ScyllaDB Cloud Serverless

Connect to ScyllaDB Cloud Serverless

+
+
CHANGELOG

Log of changes to the driver, organized by version.

+
+
Frequently Asked Questions

A collection of Frequently Asked Questions

+
+
API Documentation

The API documentation.

+
+
+
+
+
+
+

Getting Help

+

Visit the FAQ section in this documentation.

+

Please send questions to the Scylla user list.

+
+
+

Reporting Issues

+

Please report any bugs and make any feature requests on the Github project issues

+
+ +
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/stable/installation.html b/stable/installation.html new file mode 100644 index 0000000000..573a715eeb --- /dev/null +++ b/stable/installation.html @@ -0,0 +1,865 @@ + + + + + + + + + + + + + Installation | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + + + +
+ +
+ +
+

Installation

+
+

Supported Platforms

+

Python 2.7, 3.5, 3.6, 3.7 and 3.8 are supported. Both CPython (the standard Python +implementation) and PyPy are supported and tested.

+

Linux, OSX, and Windows are supported.

+
+
+

Installation through pip

+

pip is the suggested tool for installing +packages. It will handle installing all Python dependencies for the driver at +the same time as the driver itself. To install the driver*:

+
pip install scylla-driver
+
+
+

You can use pip install --pre scylla-driver if you need to install a beta version.

+

*Note: if intending to use optional extensions, install the dependencies first. The driver may need to be reinstalled if dependencies are added after the initial installation.

+
+
+

Verifying your Installation

+

To check if the installation was successful, you can run:

+
python -c 'import cassandra; print cassandra.__version__'
+
+
+

It should print something like “3.22.0”.

+
+
+

(Optional) Graph

+

The driver provides an optional fluent graph API that depends on Apache TinkerPop (gremlinpython). It is +not installed by default. To be able to build Gremlin traversals, you need to install +the graph requirements:

+
pip install scylla-driver[graph]
+
+
+
+
+

(Optional) Compression Support

+

Compression can optionally be used for communication between the driver and +Cassandra. There are currently two supported compression algorithms: +snappy (in Cassandra 1.2+) and LZ4 (only in Cassandra 2.0+). If either is +available for the driver and Cassandra also supports it, it will +be used automatically.

+

For lz4 support:

+
pip install lz4
+
+
+

For snappy support:

+
pip install python-snappy
+
+
+

(If using a Debian Linux derivative such as Ubuntu, it may be easier to +just run apt-get install python-snappy.)

+
+
+

(Optional) Metrics Support

+

The driver has built-in support for capturing Cluster.metrics about +the queries you run. However, the scales library is required to +support this:

+
pip install scales
+
+
+
+

Speeding Up Installation

+

By default, installing the driver through pip uses a pre-compiled, platform-specific wheel when available. +If using a source distribution rather than a wheel, Cython is used to compile certain parts of the driver. +This makes those hot paths faster at runtime, but the Cython compilation +process can take a long time – as long as 10 minutes in some environments.

+

In environments where performance is less important, it may be worth it to +disable Cython as documented below. +You can also use CASS_DRIVER_BUILD_CONCURRENCY to increase the number of +threads used to build the driver and any C extensions:

+
$ # installing from source
+$ CASS_DRIVER_BUILD_CONCURRENCY=8 python setup.py install
+$ # installing from pip
+$ CASS_DRIVER_BUILD_CONCURRENCY=8 pip install scylla-driver
+
+
+
+
+

OSX Installation Error

+

If you’re installing on OSX and have XCode 5.1 installed, you may see an error like this:

+
clang: error: unknown argument: '-mno-fused-madd' [-Wunused-command-line-argument-hard-error-in-future]
+
+
+

To fix this, re-run the installation with an extra compilation flag:

+
ARCHFLAGS=-Wno-error=unused-command-line-argument-hard-error-in-future pip install scylla-driver
+
+
+
+
+
+

Windows Installation Notes

+

Installing the driver with extensions in Windows sometimes presents some challenges. A few notes about common +hang-ups:

+

Setup requires a compiler. When using Python 2, this is as simple as installing this package +(this link is also emitted during install if setuptools is unable to find the resources it needs). Depending on your +system settings, this package may install as a user-specific application. Make sure to install for everyone, or at least +as the user that will be building the Python environment.

+

It is also possible to run the build with your compiler of choice. Just make sure to have your environment setup with +the proper paths. Make sure the compiler target architecture matches the bitness of your Python runtime. +Perhaps the easiest way to do this is to run the build/install from a Visual Studio Command Prompt (a +shortcut installed with Visual Studio that sources the appropriate environment and presents a shell).

+
+
+

Manual Installation

+

You can always install the driver directly from a source checkout or tarball. +When installing manually, ensure the python dependencies are already +installed. You can find the list of dependencies in +requirements.txt.

+

Once the dependencies are installed, simply run:

+
python setup.py install
+
+
+
+
+

(Optional) Non-python Dependencies

+

The driver has several optional features that have non-Python dependencies.

+
+

C Extensions

+

By default, a number of extensions are compiled, providing faster hashing +for token-aware routing with the Murmur3Partitioner, +libev event loop integration, +and Cython optimized extensions.

+

When installing manually through setup.py, you can disable both with +the --no-extensions option, or selectively disable them with +with --no-murmur3, --no-libev, or --no-cython.

+

To compile the extensions, ensure that GCC and the Python headers are available.

+

On Ubuntu and Debian, this can be accomplished by running:

+
$ sudo apt-get install gcc python-dev
+
+
+

On RedHat and RedHat-based systems like CentOS and Fedora:

+
$ sudo yum install gcc python-devel
+
+
+

On OS X, homebrew installations of Python should provide the necessary headers.

+

See Windows Installation Notes for notes on configuring the build environment on Windows.

+
+

Cython-based Extensions

+

By default, this package uses Cython to optimize core modules and build custom extensions. +This is not a hard requirement, but is engaged by default to build extensions offering better performance than the +pure Python implementation.

+

This is a costly build phase, especially in clean environments where the Cython compiler must be built +This build phase can be avoided using the build switch, or an environment variable:

+
python setup.py install --no-cython
+
+
+

Alternatively, an environment variable can be used to switch this option regardless of +context:

+
CASS_DRIVER_NO_CYTHON=1 <your script here>
+- or, to disable all extensions:
+CASS_DRIVER_NO_EXTENSIONS=1 <your script here>
+
+
+

This method is required when using pip, which provides no other way of injecting user options in a single command:

+
CASS_DRIVER_NO_CYTHON=1 pip install scylla-driver
+CASS_DRIVER_NO_CYTHON=1 sudo -E pip install ~/python-driver
+
+
+

The environment variable is the preferred option because it spans all invocations of setup.py, and will +prevent Cython from being materialized as a setup requirement.

+

If your sudo configuration does not allow SETENV, you must push the option flag down via pip. However, pip +applies these options to all dependencies (which break on the custom flag). Therefore, you must first install +dependencies, then use install-option:

+
sudo pip install six futures
+sudo pip install --install-option="--no-cython"
+
+
+
+
+
+

libev support

+

The driver currently uses Python’s asyncore module for its default +event loop. For better performance, libev is also supported through +a C extension.

+

If you’re on Linux, you should be able to install libev +through a package manager. For example, on Debian/Ubuntu:

+
$ sudo apt-get install libev4 libev-dev
+
+
+

On RHEL/CentOS/Fedora:

+
$ sudo yum install libev libev-devel
+
+
+

If you’re on Mac OS X, you should be able to install libev +through Homebrew. For example, on Mac OS X:

+
$ brew install libev
+
+
+

The libev extension is not built for Windows (the build process is complex, and the Windows implementation uses +select anyway).

+

If successful, you should be able to build and install the extension +(just using setup.py build or setup.py install) and then use +the libev event loop by doing the following:

+
>>> from cassandra.io.libevreactor import LibevConnection
+>>> from cassandra.cluster import Cluster
+
+>>> cluster = Cluster()
+>>> cluster.connection_class = LibevConnection
+>>> session = cluster.connect()
+
+
+
+
+
+

(Optional) Configuring SSL

+

Andrew Mussey has published a thorough guide on +Using SSL with the DataStax Python driver.

+
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/stable/lwt.html b/stable/lwt.html new file mode 100644 index 0000000000..cb00b62276 --- /dev/null +++ b/stable/lwt.html @@ -0,0 +1,725 @@ + + + + + + + + + + + + + Lightweight Transactions (Compare-and-set) | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + + + +
+ +
+ +
+

Lightweight Transactions (Compare-and-set)

+

Lightweight Transactions (LWTs) are mostly pass-through CQL for the driver. However, +the server returns some specialized results indicating the outcome and optional state +preceding the transaction.

+

For pertinent execution parameters, see Statement.serial_consistency_level.

+

This section discusses working with specialized result sets returned by the server for LWTs, +and how to work with them using the driver.

+
+

Specialized Results

+

The result returned from a LWT request is always a single row result. It will always have +prepended a special column named [applied]. How this value appears in your results depends +on the row factory in use. See below for examples.

+

The value of this [applied] column is boolean value indicating whether or not the transaction was applied. +If True, it is the only column in the result. If False, the additional columns depend on the LWT operation being +executed:

+
    +
  • When using a UPDATE ... IF "col" = ... clause, the result will contain the [applied] column, plus the existing columns +and values for any columns in the IF clause (and thus the value that caused the transaction to fail).

  • +
  • When using INSERT ... IF NOT EXISTS, the result will contain the [applied] column, plus all columns and values +of the existing row that rejected the transaction.

  • +
  • UPDATE .. IF EXISTS never has additional columns, regardless of [applied] status.

  • +
+

How the [applied] column manifests depends on the row factory in use. Considering the following (initially empty) table:

+
CREATE TABLE test.t (
+    k int PRIMARY KEY,
+    v int,
+    x int
+)
+
+
+

… the following sections show the expected result for a number of example statements, using the three base row factories.

+
+

named_tuple_factory (default)

+

The name [applied] is not a valid Python identifier, so the square brackets are actually removed +from the attribute for the resulting namedtuple. The row always has a boolean column applied in position 0:

+
>>> session.execute("INSERT INTO t (k,v) VALUES (0,0) IF NOT EXISTS")
+Row(applied=True)
+
+>>> session.execute("INSERT INTO t (k,v) VALUES (0,0) IF NOT EXISTS")
+Row(applied=False, k=0, v=0, x=None)
+
+>>> session.execute("UPDATE t SET v = 1, x = 2 WHERE k = 0 IF v =0")
+Row(applied=True)
+
+>>> session.execute("UPDATE t SET v = 1, x = 2 WHERE k = 0 IF v =0 AND x = 1")
+Row(applied=False, v=1, x=2)
+
+
+
+
+

tuple_factory

+

This return type does not refer to names, but the boolean value applied is always present in position 0:

+
>>> session.execute("INSERT INTO t (k,v) VALUES (0,0) IF NOT EXISTS")
+(True,)
+
+>>> session.execute("INSERT INTO t (k,v) VALUES (0,0) IF NOT EXISTS")
+(False, 0, 0, None)
+
+>>> session.execute("UPDATE t SET v = 1, x = 2 WHERE k = 0 IF v =0")
+(True,)
+
+>>> session.execute("UPDATE t SET v = 1, x = 2 WHERE k = 0 IF v =0 AND x = 1")
+(False, 1, 2)
+
+
+
+
+

dict_factory

+

The retuned dict contains the [applied] key:

+
>>> session.execute("INSERT INTO t (k,v) VALUES (0,0) IF NOT EXISTS")
+{u'[applied]': True}
+
+>>> session.execute("INSERT INTO t (k,v) VALUES (0,0) IF NOT EXISTS")
+{u'x': 2, u'[applied]': False, u'v': 1}
+
+>>> session.execute("UPDATE t SET v = 1, x = 2 WHERE k = 0 IF v =0")
+{u'x': None, u'[applied]': False, u'k': 0, u'v': 0}
+
+>>> session.execute("UPDATE t SET v = 1, x = 2 WHERE k = 0 IF v =0 AND x = 1")
+{u'[applied]': True}
+
+
+
+
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/stable/object-mapper.html b/stable/object-mapper.html new file mode 100644 index 0000000000..22849c9f17 --- /dev/null +++ b/stable/object-mapper.html @@ -0,0 +1,722 @@ + + + + + + + + + + + + + Object Mapper | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + + + +
+ +
+ +
+

Object Mapper

+

cqlengine is the Cassandra CQL 3 Object Mapper packaged with this driver

+

Jump to Getting Started

+
+

Contents

+
+
Upgrade Guide

For migrating projects from legacy cqlengine, to the integrated product

+
+
Models

Examples defining models, and mapping them to tables

+
+
Making Queries

Overview of query sets and filtering

+
+
Batch Queries

Working with batch mutations

+
+
Connections

Working with multiple sessions

+
+
API Documentation

Index of API documentation

+
+
Third party integrations

High-level examples in Celery and uWSGI

+
+
+

Frequently Asked Questions

+
+
+
+
+

Getting Started

+
import uuid
+from cassandra.cqlengine import columns
+from cassandra.cqlengine import connection
+from datetime import datetime
+from cassandra.cqlengine.management import sync_table
+from cassandra.cqlengine.models import Model
+
+#first, define a model
+class ExampleModel(Model):
+    example_id      = columns.UUID(primary_key=True, default=uuid.uuid4)
+    example_type    = columns.Integer(index=True)
+    created_at      = columns.DateTime()
+    description     = columns.Text(required=False)
+
+#next, setup the connection to your cassandra server(s)...
+# see http://datastax.github.io/python-driver/api/cassandra/cluster.html for options
+# the list of hosts will be passed to create a Cluster() instance
+connection.setup(['127.0.0.1'], "cqlengine", protocol_version=3)
+
+#...and create your CQL table
+>>> sync_table(ExampleModel)
+
+#now we can create some rows:
+>>> em1 = ExampleModel.create(example_type=0, description="example1", created_at=datetime.now())
+>>> em2 = ExampleModel.create(example_type=0, description="example2", created_at=datetime.now())
+>>> em3 = ExampleModel.create(example_type=0, description="example3", created_at=datetime.now())
+>>> em4 = ExampleModel.create(example_type=0, description="example4", created_at=datetime.now())
+>>> em5 = ExampleModel.create(example_type=1, description="example5", created_at=datetime.now())
+>>> em6 = ExampleModel.create(example_type=1, description="example6", created_at=datetime.now())
+>>> em7 = ExampleModel.create(example_type=1, description="example7", created_at=datetime.now())
+>>> em8 = ExampleModel.create(example_type=1, description="example8", created_at=datetime.now())
+
+#and now we can run some queries against our table
+>>> ExampleModel.objects.count()
+8
+>>> q = ExampleModel.objects(example_type=1)
+>>> q.count()
+4
+>>> for instance in q:
+>>>     print instance.description
+example5
+example6
+example7
+example8
+
+#here we are applying additional filtering to an existing query
+#query objects are immutable, so calling filter returns a new
+#query object
+>>> q2 = q.filter(example_id=em5.example_id)
+
+>>> q2.count()
+1
+>>> for instance in q2:
+>>>     print instance.description
+example5
+
+
+
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/stable/objects.inv b/stable/objects.inv new file mode 100644 index 0000000000..0ea4f4d635 Binary files /dev/null and b/stable/objects.inv differ diff --git a/stable/performance.html b/stable/performance.html new file mode 100644 index 0000000000..244b27c48a --- /dev/null +++ b/stable/performance.html @@ -0,0 +1,676 @@ + + + + + + + + + + + + + Performance Notes | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + + + +
+ +
+ +
+

Performance Notes

+

The Python driver for Cassandra offers several methods for executing queries. +You can synchronously block for queries to complete using +Session.execute(), you can obtain asynchronous request futures through +Session.execute_async(), and you can attach a callback to the future +with ResponseFuture.add_callback().

+

Examples of multiple request patterns can be found in the benchmark scripts included in the driver project.

+

The choice of execution pattern will depend on the application context. For applications dealing with multiple +requests in a given context, the recommended pattern is to use concurrent asynchronous +requests with callbacks. For many use cases, you don’t need to implement this pattern yourself. +cassandra.concurrent.execute_concurrent() and cassandra.concurrent.execute_concurrent_with_args() +provide this pattern with a synchronous API and tunable concurrency.

+

Due to the GIL and limited concurrency, the driver can become CPU-bound pretty quickly. The sections below +discuss further runtime and design considerations for mitigating this limitation.

+
+

PyPy

+

PyPy is an alternative Python runtime which uses a JIT compiler to +reduce CPU consumption. This leads to a huge improvement in the driver performance, +more than doubling throughput for many workloads.

+
+
+

Cython Extensions

+

Cython is an optimizing compiler and language that can be used to compile the core files and +optional extensions for the driver. Cython is not a strict dependency, but the extensions will be built by default.

+

See Installation for details on controlling this build.

+
+
+

multiprocessing

+

All of the patterns discussed above may be used over multiple processes using the +multiprocessing +module. Multiple processes will scale better than multiple threads, so if high throughput is your goal, +consider this option.

+

Be sure to never share any Cluster, Session, +or ResponseFuture objects across multiple processes. These +objects should all be created after forking the process, not before.

+

For further discussion and simple examples using the driver with multiprocessing, +see this blog post.

+
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/stable/py-modindex.html b/stable/py-modindex.html new file mode 100644 index 0000000000..5ada38f9e2 --- /dev/null +++ b/stable/py-modindex.html @@ -0,0 +1,609 @@ + + + + + + + + + + + + + Python Module Index | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + + + +
+ +
+ + + +
+ + + + + +
+ + +
+
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/stable/query-paging.html b/stable/query-paging.html new file mode 100644 index 0000000000..83ed96388c --- /dev/null +++ b/stable/query-paging.html @@ -0,0 +1,730 @@ + + + + + + + + + + + + + Paging Large Queries | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + + + +
+ +
+ +
+

Paging Large Queries

+

Cassandra 2.0+ offers support for automatic query paging. Starting with +version 2.0 of the driver, if protocol_version is greater than +2 (it is by default), queries returning large result sets will be +automatically paged.

+
+

Controlling the Page Size

+

By default, Session.default_fetch_size controls how many rows will +be fetched per page. This can be overridden per-query by setting +fetch_size on a Statement. By default, each page +will contain at most 5000 rows.

+
+
+

Handling Paged Results

+

Whenever the number of result rows for are query exceed the page size, an +instance of PagedResult will be returned instead of a normal +list. This class implements the iterator interface, so you can treat +it like a normal iterator over rows:

+
from cassandra.query import SimpleStatement
+query = "SELECT * FROM users"  # users contains 100 rows
+statement = SimpleStatement(query, fetch_size=10)
+for user_row in session.execute(statement):
+    process_user(user_row)
+
+
+

Whenever there are no more rows in the current page, the next page will +be fetched transparently. However, note that it is possible for +an Exception to be raised while fetching the next page, just +like you might see on a normal call to session.execute().

+

If you use Session.execute_async() along with, +ResponseFuture.result(), the first page will be fetched before +result() returns, but latter pages will be +transparently fetched synchronously while iterating the result.

+
+
+

Handling Paged Results with Callbacks

+

If callbacks are attached to a query that returns a paged result, +the callback will be called once per page with a normal list of rows.

+

Use ResponseFuture.has_more_pages and +ResponseFuture.start_fetching_next_page() to continue fetching +pages. For example:

+
class PagedResultHandler(object):
+
+    def __init__(self, future):
+        self.error = None
+        self.finished_event = Event()
+        self.future = future
+        self.future.add_callbacks(
+            callback=self.handle_page,
+            errback=self.handle_err)
+
+    def handle_page(self, rows):
+        for row in rows:
+            process_row(row)
+
+        if self.future.has_more_pages:
+            self.future.start_fetching_next_page()
+        else:
+            self.finished_event.set()
+
+    def handle_error(self, exc):
+        self.error = exc
+        self.finished_event.set()
+
+future = session.execute_async("SELECT * FROM users")
+handler = PagedResultHandler(future)
+handler.finished_event.wait()
+if handler.error:
+    raise handler.error
+
+
+
+
+

Resume Paged Results

+

You can resume the pagination when executing a new query by using the ResultSet.paging_state. This can be useful if you want to provide some stateless pagination capabilities to your application (ie. via http). For example:

+
from cassandra.query import SimpleStatement
+query = "SELECT * FROM users"
+statement = SimpleStatement(query, fetch_size=10)
+results = session.execute(statement)
+
+# save the paging_state somewhere and return current results
+web_session['paging_state'] = results.paging_state
+
+
+# resume the pagination sometime later...
+statement = SimpleStatement(query, fetch_size=10)
+ps = web_session['paging_state']
+results = session.execute(statement, paging_state=ps)
+
+
+
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/stable/scylla-cloud-serverless.html b/stable/scylla-cloud-serverless.html new file mode 100644 index 0000000000..cfe907bd96 --- /dev/null +++ b/stable/scylla-cloud-serverless.html @@ -0,0 +1,668 @@ + + + + + + + + + + + + + ScyllaDB Cloud Serverless | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + + + +
+ +
+ +
+

ScyllaDB Cloud Serverless

+

With ScyllaDB Cloud, you can deploy serverless databases. +The Python driver allows you to connect to a serverless database by utilizing the connection bundle you can download via the Connect>Python tab in the Cloud application. +The connection bundle is a YAML file with connection and credential information for your cluster.

+

Connecting to a ScyllaDB Cloud serverless database is very similar to a standard connection to a ScyllaDB database.

+

Here’s a short program that connects to a ScyllaDB Cloud serverless database and prints metadata about the cluster:

+
from cassandra.cluster import Cluster, ExecutionProfile, EXEC_PROFILE_DEFAULT
+from cassandra.policies import DCAwareRoundRobinPolicy, TokenAwarePolicy
+
+PATH_TO_BUNDLE_YAML = '/file/downloaded/from/cloud/connect-bundle.yaml'
+
+
+def get_cluster():
+    profile = ExecutionProfile(
+        load_balancing_policy=TokenAwarePolicy(
+            DCAwareRoundRobinPolicy(local_dc='us-east-1')
+        )
+    )
+
+    return Cluster(
+        execution_profiles={EXEC_PROFILE_DEFAULT: profile},
+        scylla_cloud=PATH_TO_BUNDLE_YAML,
+    )
+
+
+print('Connecting to cluster')
+cluster = get_cluster()
+session = cluster.connect()
+
+print('Connected to cluster', cluster.metadata.cluster_name)
+
+print('Getting metadata')
+for host in cluster.metadata.all_hosts():
+    print('Datacenter: {}; Host: {}; Rack: {}'.format(
+        host.datacenter, host.address, host.rack)
+    )
+
+cluster.shutdown()
+
+
+

By providing the scylla_cloud parameter to the Cluster constructor, +the driver can set up the connection based on the endpoint and credential information +stored in your downloaded ScyllaDB Cloud Serverless connection bundle.

+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/stable/scylla-cloud.html b/stable/scylla-cloud.html new file mode 100644 index 0000000000..2aa9e75589 --- /dev/null +++ b/stable/scylla-cloud.html @@ -0,0 +1,628 @@ + + + + + + + + + + + + + ScyllaDB Cloud | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + + + +
+ +
+ +
+

ScyllaDB Cloud

+

To connect to a ScyllaDB Cloud cluster, go to the Cluster Connect page, Python example. +For best performance, make sure to use the Scylla Driver.

+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/stable/scylla-specific.html b/stable/scylla-specific.html new file mode 100644 index 0000000000..f0322313db --- /dev/null +++ b/stable/scylla-specific.html @@ -0,0 +1,737 @@ + + + + + + + + + + + + + Scylla Specific Features | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + + + +
+ +
+ +
+

Scylla Specific Features

+
+

Shard Awareness

+

scylla-driver is shard aware and contains extensions that work with the TokenAwarePolicy supported by Scylla 2.3 and onwards. Using this policy, the driver can select a connection to a particular shard based on the shard’s token. +As a result, latency is significantly reduced because there is no need to pass data between the shards.

+

Details on the scylla cql protocol extensions +https://github.com/scylladb/scylla/blob/master/docs/dev/protocol-extensions.md#intranode-sharding

+

For using it you only need to enable TokenAwarePolicy on the Cluster

+

See the configuration of native_shard_aware_transport_port and native_shard_aware_transport_port_ssl on scylla.yaml: +https://github.com/scylladb/scylla/blob/master/docs/dev/protocols.md#cql-client-protocol

+
from cassandra.cluster import Cluster
+from cassandra.policies import TokenAwarePolicy, RoundRobinPolicy
+
+cluster = Cluster(load_balancing_policy=TokenAwarePolicy(RoundRobinPolicy()))
+
+
+
+
+

New Cluster Helpers

+
    +
  • shard_aware_options

    +

    Setting it to dict(disable=True) would disable the shard aware functionally, for cases favoring once connection per host (example, lots of processes connecting from one client host, generating a big load of connections

    +

    Other option is to configure scylla by setting enable_shard_aware_drivers: false on scylla.yaml.

    +
  • +
+
from cassandra.cluster import Cluster
+
+cluster = Cluster(shard_aware_options=dict(disable=True))
+session = cluster.connect()
+
+assert not cluster.is_shard_aware(), "Shard aware should be disabled"
+
+# or just disable the shard aware port logic
+cluster = Cluster(shard_aware_options=dict(disable_shardaware_port=True))
+session = cluster.connect()
+
+
+
    +
  • cluster.is_shard_aware()

    +

    New method available on Cluster allowing to check whether the remote cluster supports shard awareness (bool)

    +
  • +
+
from cassandra.cluster import Cluster
+
+cluster = Cluster()
+session = cluster.connect()
+
+if cluster.is_shard_aware():
+    print("connected to a scylla cluster")
+
+
+
    +
  • cluster.shard_aware_stats()

    +

    New method available on Cluster allowing to check the status of shard aware connections to all available hosts (dict)

    +
  • +
+
from cassandra.cluster import Cluster
+
+cluster = Cluster()
+session = cluster.connect()
+
+stats = cluster.shard_aware_stats()
+if all([v["shards_count"] == v["connected"] for v in stats.values()]):
+    print("successfully connected to all shards of all scylla nodes")
+
+
+
+
+

New Table Attributes

+
    +
  • in_memory flag

    +

    New flag available on TableMetadata.options to indicate that it is an In Memory table

    +
  • +
+
+

Note

+

in memory tables is a feature existing only in Scylla Enterprise

+
+
from cassandra.cluster import Cluster
+
+cluster = Cluster()
+session = cluster.connect()
+session.execute("""
+    CREATE KEYSPACE IF NOT EXISTS keyspace1
+    WITH replication = {'class': 'SimpleStrategy', 'replication_factor': '1'};
+""")
+
+session.execute("""
+    CREATE TABLE IF NOT EXISTS keyspace1.standard1 (
+        key blob PRIMARY KEY,
+        "C0" blob
+    ) WITH in_memory=true AND compaction={'class': 'InMemoryCompactionStrategy'}
+""")
+
+cluster.refresh_table_metadata("keyspace1", "standard1")
+assert cluster.metadata.keyspaces["keyspace1"].tables["standard1"].options["in_memory"] == True
+
+
+
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/stable/search.html b/stable/search.html new file mode 100644 index 0000000000..0fc56e5a4a --- /dev/null +++ b/stable/search.html @@ -0,0 +1,612 @@ + + + + + + + + + + + + + Search | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + + + + + + + +
+ + + + + +
+ + +
+
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/stable/searchindex.js b/stable/searchindex.js new file mode 100644 index 0000000000..d4a52413be --- /dev/null +++ b/stable/searchindex.js @@ -0,0 +1 @@ +Search.setIndex({docnames:["CHANGELOG","api/cassandra","api/cassandra/auth","api/cassandra/cluster","api/cassandra/concurrent","api/cassandra/connection","api/cassandra/cqlengine/columns","api/cassandra/cqlengine/connection","api/cassandra/cqlengine/management","api/cassandra/cqlengine/models","api/cassandra/cqlengine/query","api/cassandra/cqlengine/usertype","api/cassandra/datastax/graph/fluent/index","api/cassandra/datastax/graph/fluent/predicates","api/cassandra/datastax/graph/fluent/query","api/cassandra/datastax/graph/index","api/cassandra/decoder","api/cassandra/encoder","api/cassandra/graph","api/cassandra/io/asyncioreactor","api/cassandra/io/asyncorereactor","api/cassandra/io/eventletreactor","api/cassandra/io/geventreactor","api/cassandra/io/libevreactor","api/cassandra/io/twistedreactor","api/cassandra/metadata","api/cassandra/metrics","api/cassandra/policies","api/cassandra/pool","api/cassandra/protocol","api/cassandra/query","api/cassandra/timestamps","api/cassandra/util","api/index","cqlengine/batches","cqlengine/connections","cqlengine/faq","cqlengine/models","cqlengine/queryset","cqlengine/third-party","cqlengine/upgrade-guide","dates-and-times","execution-profiles","faq","getting-started","index","installation","lwt","object-mapper","performance","query-paging","scylla-cloud","scylla-cloud-serverless","scylla-specific","security","upgrading","user-defined-types"],envversion:{"sphinx.domains.c":2,"sphinx.domains.changeset":1,"sphinx.domains.citation":1,"sphinx.domains.cpp":4,"sphinx.domains.index":1,"sphinx.domains.javascript":2,"sphinx.domains.math":2,"sphinx.domains.python":3,"sphinx.domains.rst":2,"sphinx.domains.std":2,"sphinx.ext.todo":2,sphinx:56},filenames:["CHANGELOG.rst","api/cassandra.rst","api/cassandra/auth.rst","api/cassandra/cluster.rst","api/cassandra/concurrent.rst","api/cassandra/connection.rst","api/cassandra/cqlengine/columns.rst","api/cassandra/cqlengine/connection.rst","api/cassandra/cqlengine/management.rst","api/cassandra/cqlengine/models.rst","api/cassandra/cqlengine/query.rst","api/cassandra/cqlengine/usertype.rst","api/cassandra/datastax/graph/fluent/index.rst","api/cassandra/datastax/graph/fluent/predicates.rst","api/cassandra/datastax/graph/fluent/query.rst","api/cassandra/datastax/graph/index.rst","api/cassandra/decoder.rst","api/cassandra/encoder.rst","api/cassandra/graph.rst","api/cassandra/io/asyncioreactor.rst","api/cassandra/io/asyncorereactor.rst","api/cassandra/io/eventletreactor.rst","api/cassandra/io/geventreactor.rst","api/cassandra/io/libevreactor.rst","api/cassandra/io/twistedreactor.rst","api/cassandra/metadata.rst","api/cassandra/metrics.rst","api/cassandra/policies.rst","api/cassandra/pool.rst","api/cassandra/protocol.rst","api/cassandra/query.rst","api/cassandra/timestamps.rst","api/cassandra/util.rst","api/index.rst","cqlengine/batches.rst","cqlengine/connections.rst","cqlengine/faq.rst","cqlengine/models.rst","cqlengine/queryset.rst","cqlengine/third-party.rst","cqlengine/upgrade-guide.rst","dates-and-times.rst","execution-profiles.rst","faq.rst","getting-started.rst","index.rst","installation.rst","lwt.rst","object-mapper.rst","performance.rst","query-paging.rst","scylla-cloud.rst","scylla-cloud-serverless.rst","scylla-specific.rst","security.rst","upgrading.rst","user-defined-types.rst"],objects:{"":[[1,0,0,"-","cassandra"]],"cassandra.AlreadyExists":[[1,2,1,"","keyspace"],[1,2,1,"","table"]],"cassandra.ConsistencyLevel":[[1,2,1,"","ALL"],[1,2,1,"","ANY"],[1,2,1,"","EACH_QUORUM"],[1,2,1,"","LOCAL_ONE"],[1,2,1,"","LOCAL_QUORUM"],[1,2,1,"","LOCAL_SERIAL"],[1,2,1,"","ONE"],[1,2,1,"","QUORUM"],[1,2,1,"","SERIAL"],[1,2,1,"","THREE"],[1,2,1,"","TWO"]],"cassandra.CoordinationFailure":[[1,2,1,"","consistency"],[1,2,1,"","error_code_map"],[1,2,1,"","failures"],[1,2,1,"","received_responses"],[1,2,1,"","required_responses"]],"cassandra.FunctionFailure":[[1,2,1,"","arg_types"],[1,2,1,"","function"],[1,2,1,"","keyspace"]],"cassandra.OperationTimedOut":[[1,2,1,"","errors"],[1,2,1,"","last_host"]],"cassandra.ProtocolVersion":[[1,2,1,"","BETA_VERSIONS"],[1,2,1,"","DSE_V1"],[1,2,1,"","DSE_V2"],[1,2,1,"","MAX_SUPPORTED"],[1,2,1,"","MIN_SUPPORTED"],[1,2,1,"","SUPPORTED_VERSIONS"],[1,2,1,"","V1"],[1,2,1,"","V2"],[1,2,1,"","V3"],[1,2,1,"","V4"],[1,2,1,"","V5"],[1,2,1,"","V6"],[1,4,1,"","get_lower_supported"]],"cassandra.ReadFailure":[[1,2,1,"","data_retrieved"]],"cassandra.ReadTimeout":[[1,2,1,"","data_retrieved"]],"cassandra.Timeout":[[1,2,1,"","consistency"],[1,2,1,"","received_responses"],[1,2,1,"","required_responses"]],"cassandra.Unavailable":[[1,2,1,"","alive_replicas"],[1,2,1,"","consistency"],[1,2,1,"","required_replicas"]],"cassandra.UserAggregateDescriptor":[[1,2,1,"","argument_types"],[1,2,1,"","name"],[1,5,1,"","signature"]],"cassandra.UserFunctionDescriptor":[[1,2,1,"","argument_types"],[1,2,1,"","name"],[1,5,1,"","signature"]],"cassandra.WriteFailure":[[1,2,1,"","write_type"]],"cassandra.WriteTimeout":[[1,2,1,"","write_type"]],"cassandra.auth":[[2,3,1,"","AuthProvider"],[2,3,1,"","Authenticator"],[2,3,1,"","PlainTextAuthProvider"],[2,3,1,"","PlainTextAuthenticator"],[2,3,1,"","SaslAuthProvider"],[2,3,1,"","SaslAuthenticator"]],"cassandra.auth.AuthProvider":[[2,4,1,"","new_authenticator"]],"cassandra.auth.Authenticator":[[2,4,1,"","evaluate_challenge"],[2,4,1,"","initial_response"],[2,4,1,"","on_authentication_success"],[2,2,1,"","server_authenticator_class"]],"cassandra.auth.PlainTextAuthProvider":[[2,4,1,"","new_authenticator"]],"cassandra.auth.PlainTextAuthenticator":[[2,4,1,"","evaluate_challenge"]],"cassandra.auth.SaslAuthProvider":[[2,4,1,"","new_authenticator"]],"cassandra.auth.SaslAuthenticator":[[2,4,1,"","evaluate_challenge"],[2,4,1,"","initial_response"]],"cassandra.cluster":[[3,3,1,"","Cluster"],[3,6,1,"","EXEC_PROFILE_DEFAULT"],[3,6,1,"","EXEC_PROFILE_GRAPH_ANALYTICS_DEFAULT"],[3,6,1,"","EXEC_PROFILE_GRAPH_DEFAULT"],[3,6,1,"","EXEC_PROFILE_GRAPH_SYSTEM_DEFAULT"],[3,3,1,"","ExecutionProfile"],[3,3,1,"","GraphAnalyticsExecutionProfile"],[3,3,1,"","GraphExecutionProfile"],[3,1,1,"","NoHostAvailable"],[3,1,1,"","QueryExhausted"],[3,3,1,"","ResponseFuture"],[3,3,1,"","ResultSet"],[3,3,1,"","Session"],[3,1,1,"","UserTypeDoesNotExist"]],"cassandra.cluster.Cluster":[[3,4,1,"","add_execution_profile"],[3,2,1,"","address_translator"],[3,2,1,"","auth_provider"],[3,2,1,"","cloud"],[3,2,1,"","compression"],[3,4,1,"","connect"],[3,2,1,"","connect_timeout"],[3,2,1,"","connection_class"],[3,2,1,"","contact_points"],[3,2,1,"","control_connection_timeout"],[3,2,1,"","conviction_policy_factory"],[3,2,1,"","cql_version"],[3,2,1,"","default_retry_policy"],[3,2,1,"","endpoint_factory"],[3,4,1,"","get_control_connection_host"],[3,4,1,"","get_core_connections_per_host"],[3,4,1,"","get_max_connections_per_host"],[3,4,1,"","get_max_requests_per_connection"],[3,4,1,"","get_min_requests_per_connection"],[3,2,1,"","idle_heartbeat_interval"],[3,2,1,"","idle_heartbeat_timeout"],[3,2,1,"","load_balancing_policy"],[3,2,1,"","max_schema_agreement_wait"],[3,2,1,"","metadata"],[3,2,1,"","metrics"],[3,2,1,"","metrics_enabled"],[3,2,1,"","port"],[3,2,1,"","prepare_on_all_hosts"],[3,2,1,"","protocol_version"],[3,2,1,"","reconnection_policy"],[3,4,1,"","refresh_keyspace_metadata"],[3,4,1,"","refresh_nodes"],[3,4,1,"","refresh_schema_metadata"],[3,4,1,"","refresh_table_metadata"],[3,4,1,"","refresh_user_aggregate_metadata"],[3,4,1,"","refresh_user_function_metadata"],[3,4,1,"","refresh_user_type_metadata"],[3,4,1,"","register_listener"],[3,4,1,"","register_user_type"],[3,2,1,"","reprepare_on_up"],[3,2,1,"","schema_event_refresh_window"],[3,2,1,"","schema_metadata_enabled"],[3,4,1,"","set_core_connections_per_host"],[3,4,1,"","set_max_connections_per_host"],[3,4,1,"","set_max_requests_per_connection"],[3,4,1,"","set_meta_refresh_enabled"],[3,4,1,"","set_min_requests_per_connection"],[3,4,1,"","shutdown"],[3,2,1,"","sockopts"],[3,2,1,"","ssl_context"],[3,2,1,"","ssl_options"],[3,2,1,"","status_event_refresh_window"],[3,2,1,"","timestamp_generator"],[3,2,1,"","token_metadata_enabled"],[3,2,1,"","topology_event_refresh_window"],[3,4,1,"","unregister_listener"]],"cassandra.cluster.ExecutionProfile":[[3,2,1,"","consistency_level"],[3,4,1,"","row_factory"]],"cassandra.cluster.ResponseFuture":[[3,4,1,"","add_callback"],[3,4,1,"","add_errback"],[3,2,1,"","custom_payload"],[3,4,1,"","get_all_query_traces"],[3,4,1,"","get_query_trace"],[3,2,1,"","has_more_pages"],[3,2,1,"","is_schema_agreed"],[3,2,1,"","query"],[3,4,1,"","result"],[3,4,1,"","start_fetching_next_page"],[3,2,1,"","warnings"]],"cassandra.cluster.ResultSet":[[3,4,1,"","all"],[3,5,1,"","current_rows"],[3,4,1,"","fetch_next_page"],[3,4,1,"","get_all_query_traces"],[3,4,1,"","get_query_trace"],[3,5,1,"","has_more_pages"],[3,4,1,"","one"],[3,5,1,"","paging_state"],[3,5,1,"","was_applied"]],"cassandra.cluster.Session":[[3,4,1,"","add_request_init_listener"],[3,2,1,"","client_protocol_handler"],[3,2,1,"","default_consistency_level"],[3,2,1,"","default_fetch_size"],[3,2,1,"","default_serial_consistency_level"],[3,2,1,"","default_timeout"],[3,2,1,"","encoder"],[3,4,1,"","execute"],[3,4,1,"","execute_async"],[3,4,1,"","execute_graph"],[3,4,1,"","execute_graph_async"],[3,4,1,"","execution_profile_clone_update"],[3,4,1,"","get_execution_profile"],[3,4,1,"","prepare"],[3,4,1,"","remove_request_init_listener"],[3,2,1,"","row_factory"],[3,4,1,"","set_keyspace"],[3,4,1,"","shutdown"],[3,2,1,"","timestamp_generator"],[3,2,1,"","use_client_timestamp"]],"cassandra.concurrent":[[4,7,1,"","execute_concurrent"],[4,7,1,"","execute_concurrent_with_args"]],"cassandra.connection":[[5,1,1,"","ConnectionBusy"],[5,1,1,"","ConnectionException"],[5,1,1,"","ConnectionShutdown"],[5,3,1,"","EndPoint"],[5,3,1,"","EndPointFactory"],[5,1,1,"","ProtocolError"],[5,3,1,"","SniEndPoint"],[5,3,1,"","SniEndPointFactory"],[5,3,1,"","UnixSocketEndPoint"]],"cassandra.connection.EndPoint":[[5,5,1,"","address"],[5,5,1,"","port"],[5,4,1,"","resolve"],[5,5,1,"","socket_family"],[5,5,1,"","ssl_options"]],"cassandra.connection.EndPointFactory":[[5,4,1,"","configure"],[5,4,1,"","create"]],"cassandra.cqlengine":[[6,0,0,"-","columns"],[7,0,0,"-","connection"],[8,0,0,"-","management"],[9,0,0,"-","models"],[10,0,0,"-","query"],[11,0,0,"-","usertype"]],"cassandra.cqlengine.columns":[[6,3,1,"","Ascii"],[6,3,1,"","BigInt"],[6,3,1,"","Blob"],[6,3,1,"","Boolean"],[6,2,1,"","Bytes"],[6,3,1,"","Column"],[6,3,1,"","Counter"],[6,3,1,"","Date"],[6,3,1,"","DateTime"],[6,3,1,"","Decimal"],[6,3,1,"","Double"],[6,3,1,"","Float"],[6,3,1,"","Integer"],[6,3,1,"","List"],[6,3,1,"","Map"],[6,3,1,"","Set"],[6,3,1,"","SmallInt"],[6,3,1,"","Text"],[6,3,1,"","Time"],[6,3,1,"","TimeUUID"],[6,3,1,"","TinyInt"],[6,3,1,"","UUID"],[6,3,1,"","UserDefinedType"],[6,3,1,"","VarInt"]],"cassandra.cqlengine.columns.Column":[[6,2,1,"","clustering_order"],[6,2,1,"","custom_index"],[6,2,1,"","db_field"],[6,2,1,"","default"],[6,2,1,"","discriminator_column"],[6,2,1,"","index"],[6,2,1,"","partition_key"],[6,2,1,"","primary_key"],[6,2,1,"","required"],[6,2,1,"","static"]],"cassandra.cqlengine.columns.DateTime":[[6,2,1,"","truncate_microseconds"]],"cassandra.cqlengine.connection":[[7,7,1,"","default"],[7,7,1,"","register_connection"],[7,7,1,"","set_default_connection"],[7,7,1,"","set_session"],[7,7,1,"","setup"],[7,7,1,"","unregister_connection"]],"cassandra.cqlengine.management":[[8,7,1,"","create_keyspace_network_topology"],[8,7,1,"","create_keyspace_simple"],[8,7,1,"","drop_keyspace"],[8,7,1,"","drop_table"],[8,7,1,"","sync_table"],[8,7,1,"","sync_type"]],"cassandra.cqlengine.models":[[9,3,1,"","Model"]],"cassandra.cqlengine.models.Model":[[9,2,1,"","__abstract__"],[9,2,1,"","__compute_routing_key__"],[9,2,1,"","__connection__"],[9,2,1,"","__default_ttl__"],[9,2,1,"","__discriminator_value__"],[9,2,1,"","__keyspace__"],[9,2,1,"","__options__"],[9,2,1,"","__table_name__"],[9,2,1,"","__table_name_case_sensitive__"],[9,4,1,"","all"],[9,4,1,"","batch"],[9,4,1,"","column_family_name"],[9,4,1,"","create"],[9,4,1,"","delete"],[9,4,1,"","filter"],[9,4,1,"","get"],[9,4,1,"","if_exists"],[9,4,1,"","if_not_exists"],[9,4,1,"","iff"],[9,4,1,"","items"],[9,4,1,"","keys"],[9,4,1,"","len"],[9,4,1,"","save"],[9,4,1,"","timeout"],[9,4,1,"","timestamp"],[9,4,1,"","ttl"],[9,4,1,"","update"],[9,4,1,"","using"],[9,4,1,"","values"]],"cassandra.cqlengine.query":[[10,3,1,"","BatchQuery"],[10,3,1,"","ContextQuery"],[10,3,1,"","DoesNotExist"],[10,3,1,"","LWTException"],[10,3,1,"","ModelQuerySet"],[10,3,1,"","MultipleObjectsReturned"]],"cassandra.cqlengine.query.BatchQuery":[[10,4,1,"","add_callback"],[10,4,1,"","add_query"],[10,4,1,"","execute"]],"cassandra.cqlengine.query.ModelQuerySet":[[10,4,1,"","all"],[10,4,1,"","allow_filtering"],[10,4,1,"","batch"],[10,4,1,"","consistency"],[10,4,1,"","count"],[10,4,1,"","defer"],[10,4,1,"","distinct"],[10,4,1,"","fetch_size"],[10,4,1,"","filter"],[10,4,1,"","get"],[10,4,1,"","if_exists"],[10,4,1,"","if_not_exists"],[10,4,1,"","len"],[10,4,1,"","limit"],[10,4,1,"","only"],[10,4,1,"","order_by"],[10,4,1,"","timestamp"],[10,4,1,"","ttl"],[10,4,1,"","update"],[10,4,1,"","using"]],"cassandra.cqlengine.usertype":[[11,3,1,"","UserType"]],"cassandra.cqlengine.usertype.UserType":[[11,2,1,"","__type_name__"]],"cassandra.datastax":[[15,0,0,"-","graph"]],"cassandra.datastax.graph":[[12,0,0,"-","fluent"],[15,7,1,"","graph_graphson2_row_factory"],[15,7,1,"","graph_graphson3_row_factory"],[15,7,1,"","graph_object_row_factory"],[15,7,1,"","graph_result_row_factory"],[15,7,1,"","single_object_row_factory"],[15,7,1,"","to_bigint"],[15,7,1,"","to_double"],[15,7,1,"","to_float"],[15,7,1,"","to_int"],[15,7,1,"","to_smallint"]],"cassandra.datastax.graph.GraphOptions":[[15,2,1,"","graph_language"],[15,2,1,"","graph_name"],[15,2,1,"","graph_read_consistency_level"],[15,2,1,"","graph_source"],[15,2,1,"","graph_write_consistency_level"],[15,2,1,"","is_analytics_source"],[15,2,1,"","is_default_source"],[15,2,1,"","is_graph_source"],[15,4,1,"","set_source_analytics"],[15,4,1,"","set_source_default"],[15,4,1,"","set_source_graph"]],"cassandra.datastax.graph.GraphSON1Deserializer":[[15,4,1,"","deserialize_bigint"],[15,4,1,"","deserialize_blob"],[15,4,1,"","deserialize_date"],[15,4,1,"","deserialize_decimal"],[15,4,1,"","deserialize_double"],[15,4,1,"","deserialize_duration"],[15,4,1,"","deserialize_float"],[15,4,1,"","deserialize_int"],[15,4,1,"","deserialize_linestring"],[15,4,1,"","deserialize_point"],[15,4,1,"","deserialize_polygon"],[15,4,1,"","deserialize_time"],[15,4,1,"","deserialize_timestamp"],[15,4,1,"","deserialize_uuid"]],"cassandra.datastax.graph.fluent":[[12,3,1,"","BaseGraphRowFactory"],[12,3,1,"","DSESessionRemoteGraphConnection"],[12,3,1,"","DseGraph"],[12,2,1,"","graph_traversal_dse_object_row_factory"],[12,2,1,"","graph_traversal_row_factory"],[13,0,0,"-","predicates"],[14,0,0,"-","query"]],"cassandra.datastax.graph.fluent.DseGraph":[[12,2,1,"","DSE_GRAPH_QUERY_LANGUAGE"],[12,4,1,"","batch"],[12,4,1,"","create_execution_profile"],[12,4,1,"","query_from_traversal"],[12,4,1,"","traversal_source"]],"cassandra.datastax.graph.fluent.predicates":[[13,3,1,"","CqlCollection"],[13,3,1,"","Geo"],[13,3,1,"","Search"]],"cassandra.datastax.graph.fluent.predicates.CqlCollection":[[13,4,1,"","contains"],[13,4,1,"","contains_key"],[13,4,1,"","contains_value"],[13,4,1,"","entry_eq"]],"cassandra.datastax.graph.fluent.predicates.Geo":[[13,4,1,"","inside"]],"cassandra.datastax.graph.fluent.predicates.Search":[[13,4,1,"","fuzzy"],[13,4,1,"","phrase"],[13,4,1,"","prefix"],[13,4,1,"","regex"],[13,4,1,"","token"],[13,4,1,"","token_fuzzy"],[13,4,1,"","token_prefix"],[13,4,1,"","token_regex"]],"cassandra.datastax.graph.fluent.query":[[14,3,1,"","TraversalBatch"]],"cassandra.datastax.graph.fluent.query.TraversalBatch":[[14,4,1,"","add"],[14,4,1,"","add_all"],[14,4,1,"","as_graph_statement"],[14,4,1,"","clear"],[14,4,1,"","execute"]],"cassandra.decoder":[[16,7,1,"","dict_factory"],[16,7,1,"","named_tuple_factory"],[16,7,1,"","ordered_dict_factory"],[16,7,1,"","tuple_factory"]],"cassandra.encoder":[[17,3,1,"","Encoder"]],"cassandra.encoder.Encoder":[[17,4,1,"","cql_encode_all_types"],[17,4,1,"","cql_encode_bytes"],[17,4,1,"","cql_encode_date"],[17,4,1,"","cql_encode_datetime"],[17,4,1,"","cql_encode_list_collection"],[17,4,1,"","cql_encode_map_collection"],[17,4,1,"","cql_encode_none"],[17,4,1,"","cql_encode_object"],[17,4,1,"","cql_encode_sequence"],[17,4,1,"","cql_encode_set_collection"],[17,4,1,"","cql_encode_str"],[17,4,1,"","cql_encode_tuple"],[17,4,1,"","cql_encode_unicode"],[17,2,1,"","mapping"]],"cassandra.graph":[[18,3,1,"","Edge"],[18,3,1,"","GraphOptions"],[18,3,1,"","GraphProtocol"],[18,3,1,"","GraphSON1Deserializer"],[18,3,1,"","GraphSON1Serializer"],[18,3,1,"","GraphSON2Reader"],[18,3,1,"","GraphSON3Reader"],[18,3,1,"","Path"],[18,3,1,"","Result"],[18,3,1,"","SimpleGraphStatement"],[18,3,1,"","Vertex"],[18,3,1,"","VertexProperty"],[18,7,1,"","graph_graphson2_row_factory"],[18,7,1,"","graph_graphson3_row_factory"],[18,7,1,"","graph_object_row_factory"],[18,7,1,"","graph_result_row_factory"],[18,7,1,"","single_object_row_factory"],[18,7,1,"","to_bigint"],[18,7,1,"","to_double"],[18,7,1,"","to_float"],[18,7,1,"","to_int"],[18,7,1,"","to_smallint"]],"cassandra.graph.GraphOptions":[[18,2,1,"","graph_language"],[18,2,1,"","graph_name"],[18,2,1,"","graph_read_consistency_level"],[18,2,1,"","graph_source"],[18,2,1,"","graph_write_consistency_level"],[18,2,1,"","is_analytics_source"],[18,2,1,"","is_default_source"],[18,2,1,"","is_graph_source"],[18,4,1,"","set_source_analytics"],[18,4,1,"","set_source_default"],[18,4,1,"","set_source_graph"]],"cassandra.graph.GraphProtocol":[[18,2,1,"","GRAPHSON_1_0"],[18,2,1,"","GRAPHSON_2_0"],[18,2,1,"","GRAPHSON_3_0"]],"cassandra.graph.GraphSON1Deserializer":[[18,4,1,"","deserialize_bigint"],[18,4,1,"","deserialize_blob"],[18,4,1,"","deserialize_date"],[18,4,1,"","deserialize_decimal"],[18,4,1,"","deserialize_double"],[18,4,1,"","deserialize_duration"],[18,4,1,"","deserialize_float"],[18,4,1,"","deserialize_int"],[18,4,1,"","deserialize_linestring"],[18,4,1,"","deserialize_point"],[18,4,1,"","deserialize_polygon"],[18,4,1,"","deserialize_time"],[18,4,1,"","deserialize_timestamp"],[18,4,1,"","deserialize_uuid"]],"cassandra.graph.GraphSON2Reader":[[18,4,1,"","deserialize"],[18,4,1,"","read"]],"cassandra.graph.Path":[[18,2,1,"","labels"],[18,2,1,"","objects"]],"cassandra.graph.Result":[[18,4,1,"","as_edge"],[18,4,1,"","as_path"],[18,4,1,"","as_vertex"],[18,2,1,"","value"]],"cassandra.graph.VertexProperty":[[18,2,1,"","label"],[18,2,1,"","properties"],[18,2,1,"","value"]],"cassandra.io":[[19,0,0,"-","asyncioreactor"],[20,0,0,"-","asyncorereactor"],[21,0,0,"-","eventletreactor"],[22,0,0,"-","geventreactor"],[23,0,0,"-","libevreactor"],[24,0,0,"-","twistedreactor"]],"cassandra.io.asyncioreactor":[[19,3,1,"","AsyncioConnection"]],"cassandra.io.asyncioreactor.AsyncioConnection":[[19,4,1,"","initialize_reactor"]],"cassandra.io.asyncorereactor":[[20,3,1,"","AsyncoreConnection"]],"cassandra.io.asyncorereactor.AsyncoreConnection":[[20,4,1,"","handle_fork"],[20,4,1,"","initialize_reactor"]],"cassandra.io.eventletreactor":[[21,3,1,"","EventletConnection"]],"cassandra.io.eventletreactor.EventletConnection":[[21,4,1,"","initialize_reactor"],[21,4,1,"","service_timeouts"]],"cassandra.io.geventreactor":[[22,3,1,"","GeventConnection"]],"cassandra.io.geventreactor.GeventConnection":[[22,4,1,"","initialize_reactor"]],"cassandra.io.libevreactor":[[23,3,1,"","LibevConnection"]],"cassandra.io.twistedreactor":[[24,3,1,"","TwistedConnection"]],"cassandra.metadata":[[25,3,1,"","Aggregate"],[25,3,1,"","BytesToken"],[25,3,1,"","ColumnMetadata"],[25,3,1,"","EdgeMetadata"],[25,3,1,"","Function"],[25,3,1,"","IndexMetadata"],[25,3,1,"","KeyspaceMetadata"],[25,3,1,"","LocalStrategy"],[25,3,1,"","MD5Token"],[25,3,1,"","MaterializedViewMetadata"],[25,3,1,"","Metadata"],[25,3,1,"","Murmur3Token"],[25,3,1,"","NetworkTopologyStrategy"],[25,3,1,"","ReplicationFactor"],[25,2,1,"","ReplicationStrategy"],[25,3,1,"","SimpleStrategy"],[25,3,1,"","TableMetadata"],[25,3,1,"","TableMetadataDSE68"],[25,3,1,"","TableMetadataV3"],[25,3,1,"","Token"],[25,3,1,"","TokenMap"],[25,3,1,"","UserType"],[25,3,1,"","VertexMetadata"],[25,6,1,"","cql_keywords"],[25,6,1,"","cql_keywords_reserved"],[25,6,1,"","cql_keywords_unreserved"],[25,7,1,"","group_keys_by_replica"]],"cassandra.metadata.Aggregate":[[25,4,1,"","as_cql_query"]],"cassandra.metadata.BytesToken":[[25,4,1,"","from_string"]],"cassandra.metadata.Function":[[25,4,1,"","as_cql_query"]],"cassandra.metadata.IndexMetadata":[[25,4,1,"","as_cql_query"],[25,4,1,"","export_as_string"]],"cassandra.metadata.KeyspaceMetadata":[[25,4,1,"","as_cql_query"],[25,4,1,"","export_as_string"]],"cassandra.metadata.LocalStrategy":[[25,4,1,"","export_for_schema"]],"cassandra.metadata.MaterializedViewMetadata":[[25,4,1,"","as_cql_query"]],"cassandra.metadata.Metadata":[[25,4,1,"","add_or_return_host"],[25,4,1,"","all_hosts"],[25,4,1,"","export_schema_as_string"],[25,4,1,"","get_host"],[25,4,1,"","get_host_by_host_id"],[25,4,1,"","get_replicas"]],"cassandra.metadata.NetworkTopologyStrategy":[[25,4,1,"","export_for_schema"]],"cassandra.metadata.SimpleStrategy":[[25,4,1,"","export_for_schema"],[25,5,1,"","replication_factor"]],"cassandra.metadata.TableMetadata":[[25,4,1,"","as_cql_query"],[25,4,1,"","export_as_string"],[25,5,1,"","is_cql_compatible"],[25,5,1,"","primary_key"]],"cassandra.metadata.TableMetadataDSE68":[[25,4,1,"","as_cql_query"]],"cassandra.metadata.TableMetadataV3":[[25,5,1,"","is_cql_compatible"]],"cassandra.metadata.TokenMap":[[25,4,1,"","get_replicas"]],"cassandra.metadata.UserType":[[25,4,1,"","as_cql_query"]],"cassandra.metrics":[[26,3,1,"","Metrics"]],"cassandra.metrics.Metrics":[[26,2,1,"","connected_to"],[26,2,1,"","connection_errors"],[26,4,1,"","get_stats"],[26,2,1,"","ignores"],[26,2,1,"","known_hosts"],[26,2,1,"","open_connections"],[26,2,1,"","other_errors"],[26,2,1,"","read_timeouts"],[26,2,1,"","request_timer"],[26,2,1,"","retries"],[26,4,1,"","set_stats_name"],[26,2,1,"","unavailables"],[26,2,1,"","write_timeouts"]],"cassandra.policies":[[27,3,1,"","AddressTranslator"],[27,3,1,"","ConstantReconnectionPolicy"],[27,3,1,"","ConstantSpeculativeExecutionPolicy"],[27,3,1,"","ConvictionPolicy"],[27,3,1,"","DCAwareRoundRobinPolicy"],[27,3,1,"","DSELoadBalancingPolicy"],[27,3,1,"","DefaultLoadBalancingPolicy"],[27,3,1,"","DowngradingConsistencyRetryPolicy"],[27,3,1,"","EC2MultiRegionTranslator"],[27,3,1,"","ExponentialReconnectionPolicy"],[27,3,1,"","FallthroughRetryPolicy"],[27,3,1,"","HostDistance"],[27,3,1,"","HostFilterPolicy"],[27,3,1,"","IdentityTranslator"],[27,3,1,"","LoadBalancingPolicy"],[27,3,1,"","ReconnectionPolicy"],[27,3,1,"","RetryPolicy"],[27,3,1,"","RoundRobinPolicy"],[27,3,1,"","SimpleConvictionPolicy"],[27,3,1,"","SpeculativeExecutionPolicy"],[27,3,1,"","TokenAwarePolicy"],[27,3,1,"","WhiteListRoundRobinPolicy"],[27,3,1,"","WriteType"]],"cassandra.policies.AddressTranslator":[[27,4,1,"","translate"]],"cassandra.policies.ConstantReconnectionPolicy":[[27,4,1,"","new_schedule"]],"cassandra.policies.ConstantSpeculativeExecutionPolicy":[[27,4,1,"","new_plan"]],"cassandra.policies.ConvictionPolicy":[[27,4,1,"","add_failure"],[27,4,1,"","reset"]],"cassandra.policies.DCAwareRoundRobinPolicy":[[27,4,1,"","distance"],[27,4,1,"","make_query_plan"],[27,4,1,"","on_add"],[27,4,1,"","on_down"],[27,4,1,"","on_remove"],[27,4,1,"","on_up"],[27,4,1,"","populate"]],"cassandra.policies.DefaultLoadBalancingPolicy":[[27,4,1,"","make_query_plan"],[27,4,1,"","populate"]],"cassandra.policies.DowngradingConsistencyRetryPolicy":[[27,4,1,"","on_read_timeout"],[27,4,1,"","on_unavailable"],[27,4,1,"","on_write_timeout"]],"cassandra.policies.EC2MultiRegionTranslator":[[27,4,1,"","translate"]],"cassandra.policies.ExponentialReconnectionPolicy":[[27,4,1,"","new_schedule"]],"cassandra.policies.FallthroughRetryPolicy":[[27,4,1,"","on_read_timeout"],[27,4,1,"","on_request_error"],[27,4,1,"","on_unavailable"],[27,4,1,"","on_write_timeout"]],"cassandra.policies.HostDistance":[[27,2,1,"","IGNORED"],[27,2,1,"","LOCAL"],[27,2,1,"","REMOTE"]],"cassandra.policies.HostFilterPolicy":[[27,4,1,"","distance"],[27,4,1,"","make_query_plan"],[27,4,1,"","predicate"]],"cassandra.policies.IdentityTranslator":[[27,4,1,"","translate"]],"cassandra.policies.LoadBalancingPolicy":[[27,4,1,"","check_supported"],[27,4,1,"","distance"],[27,4,1,"","make_query_plan"],[27,4,1,"","populate"]],"cassandra.policies.ReconnectionPolicy":[[27,4,1,"","new_schedule"]],"cassandra.policies.RetryPolicy":[[27,2,1,"","IGNORE"],[27,2,1,"","RETHROW"],[27,2,1,"","RETRY"],[27,2,1,"","RETRY_NEXT_HOST"],[27,4,1,"","on_read_timeout"],[27,4,1,"","on_request_error"],[27,4,1,"","on_unavailable"],[27,4,1,"","on_write_timeout"]],"cassandra.policies.RoundRobinPolicy":[[27,4,1,"","distance"],[27,4,1,"","make_query_plan"],[27,4,1,"","on_add"],[27,4,1,"","on_down"],[27,4,1,"","on_remove"],[27,4,1,"","on_up"],[27,4,1,"","populate"]],"cassandra.policies.SimpleConvictionPolicy":[[27,4,1,"","add_failure"],[27,4,1,"","reset"]],"cassandra.policies.SpeculativeExecutionPolicy":[[27,4,1,"","new_plan"]],"cassandra.policies.TokenAwarePolicy":[[27,4,1,"","check_supported"],[27,4,1,"","distance"],[27,4,1,"","make_query_plan"],[27,4,1,"","on_add"],[27,4,1,"","on_down"],[27,4,1,"","on_remove"],[27,4,1,"","on_up"],[27,4,1,"","populate"],[27,2,1,"","shuffle_replicas"]],"cassandra.policies.WhiteListRoundRobinPolicy":[[27,4,1,"","distance"],[27,4,1,"","on_add"],[27,4,1,"","on_up"],[27,4,1,"","populate"]],"cassandra.policies.WriteType":[[27,2,1,"","BATCH"],[27,2,1,"","BATCH_LOG"],[27,2,1,"","CAS"],[27,2,1,"","CDC"],[27,2,1,"","COUNTER"],[27,2,1,"","SIMPLE"],[27,2,1,"","UNLOGGED_BATCH"],[27,2,1,"","VIEW"]],"cassandra.pool":[[28,3,1,"","Host"],[28,1,1,"","NoConnectionsAvailable"]],"cassandra.pool.Host":[[28,5,1,"","address"],[28,5,1,"","datacenter"],[28,5,1,"","rack"]],"cassandra.protocol":[[29,3,1,"","_ProtocolHandler"]],"cassandra.protocol._ProtocolHandler":[[29,4,1,"","decode_message"],[29,4,1,"","encode_message"],[29,2,1,"","message_types_by_opcode"]],"cassandra.query":[[30,3,1,"","BatchStatement"],[30,3,1,"","BatchType"],[30,3,1,"","BoundStatement"],[30,3,1,"","PreparedStatement"],[30,3,1,"","QueryTrace"],[30,3,1,"","SimpleStatement"],[30,3,1,"","Statement"],[30,3,1,"","TraceEvent"],[30,1,1,"","TraceUnavailable"],[30,6,1,"","UNSET_VALUE"],[30,3,1,"","ValueSequence"],[30,7,1,"","dict_factory"],[30,7,1,"","named_tuple_factory"],[30,7,1,"","ordered_dict_factory"],[30,7,1,"","tuple_factory"]],"cassandra.query.BatchStatement":[[30,4,1,"","add"],[30,4,1,"","add_all"],[30,4,1,"","clear"],[30,2,1,"","serial_consistency_level"]],"cassandra.query.BatchType":[[30,2,1,"","COUNTER"],[30,2,1,"","LOGGED"],[30,2,1,"","UNLOGGED"]],"cassandra.query.BoundStatement":[[30,4,1,"","bind"],[30,5,1,"","routing_key"]],"cassandra.query.PreparedStatement":[[30,4,1,"","bind"]],"cassandra.query.QueryTrace":[[30,4,1,"","populate"]],"cassandra.query.Statement":[[30,5,1,"","routing_key"],[30,5,1,"","serial_consistency_level"]],"cassandra.timestamps":[[31,3,1,"","MonotonicTimestampGenerator"]],"cassandra.timestamps.MonotonicTimestampGenerator":[[31,4,1,"","_next_timestamp"],[31,2,1,"","warn_on_drift"],[31,2,1,"","warning_interval"],[31,2,1,"","warning_threshold"]],"cassandra.util":[[32,3,1,"","Date"],[32,3,1,"","DateRange"],[32,3,1,"","DateRangeBound"],[32,3,1,"","DateRangePrecision"],[32,3,1,"","Distance"],[32,3,1,"","Duration"],[32,3,1,"","LineString"],[32,3,1,"","OrderedMap"],[32,3,1,"","OrderedMapSerializedKey"],[32,3,1,"","Point"],[32,3,1,"","Polygon"],[32,3,1,"","SortedSet"],[32,3,1,"","Time"],[32,3,1,"","Version"],[32,7,1,"","datetime_from_timestamp"],[32,7,1,"","datetime_from_uuid1"],[32,7,1,"","max_uuid_from_time"],[32,7,1,"","min_uuid_from_time"],[32,7,1,"","ms_timestamp_from_datetime"],[32,2,1,"","sortedset"],[32,7,1,"","unix_time_from_uuid1"],[32,7,1,"","utc_datetime_from_ms_timestamp"],[32,7,1,"","uuid_from_time"]],"cassandra.util.Date":[[32,4,1,"","date"],[32,5,1,"","seconds"]],"cassandra.util.DateRange":[[32,2,1,"","lower_bound"],[32,2,1,"","upper_bound"],[32,2,1,"","value"]],"cassandra.util.DateRangeBound":[[32,4,1,"","datetime"],[32,4,1,"","from_value"],[32,2,1,"","milliseconds"],[32,2,1,"","precision"]],"cassandra.util.Distance":[[32,4,1,"","from_wkt"]],"cassandra.util.LineString":[[32,4,1,"","from_wkt"]],"cassandra.util.Point":[[32,4,1,"","from_wkt"]],"cassandra.util.Polygon":[[32,4,1,"","from_wkt"]],"cassandra.util.Time":[[32,5,1,"","hour"],[32,5,1,"","minute"],[32,5,1,"","nanosecond"],[32,5,1,"","second"],[32,4,1,"","time"]],"cqlengine.queryset":[[38,3,1,"","MaxTimeUUID"],[38,3,1,"","MinTimeUUID"]],cassandra:[[1,1,1,"","AlreadyExists"],[1,1,1,"","AuthenticationFailed"],[1,1,1,"","ConfigurationException"],[1,3,1,"","ConsistencyLevel"],[1,1,1,"","CoordinationFailure"],[1,1,1,"","DriverException"],[1,1,1,"","FunctionFailure"],[1,1,1,"","InvalidRequest"],[1,1,1,"","OperationTimedOut"],[1,3,1,"","ProtocolVersion"],[1,1,1,"","ReadFailure"],[1,1,1,"","ReadTimeout"],[1,1,1,"","RequestExecutionException"],[1,1,1,"","RequestValidationException"],[1,1,1,"","Timeout"],[1,1,1,"","Unauthorized"],[1,1,1,"","Unavailable"],[1,3,1,"","UserAggregateDescriptor"],[1,3,1,"","UserFunctionDescriptor"],[1,1,1,"","WriteFailure"],[1,1,1,"","WriteTimeout"],[1,6,1,"","__version__"],[1,6,1,"","__version_info__"],[2,0,0,"-","auth"],[3,0,0,"-","cluster"],[4,0,0,"-","concurrent"],[5,0,0,"-","connection"],[16,0,0,"-","decoder"],[17,0,0,"-","encoder"],[18,0,0,"-","graph"],[25,0,0,"-","metadata"],[26,0,0,"-","metrics"],[27,0,0,"-","policies"],[28,0,0,"-","pool"],[29,0,0,"-","protocol"],[30,0,0,"-","query"],[31,0,0,"-","timestamps"],[32,0,0,"-","util"]],cqlengine:[[37,0,0,"-","models"],[38,0,0,"-","queryset"]]},objnames:{"0":["py","module","Python module"],"1":["py","exception","Python exception"],"2":["py","attribute","Python attribute"],"3":["py","class","Python class"],"4":["py","method","Python method"],"5":["py","property","Python property"],"6":["py","data","Python data"],"7":["py","function","Python function"]},objtypes:{"0":"py:module","1":"py:exception","2":"py:attribute","3":"py:class","4":"py:method","5":"py:property","6":"py:data","7":"py:function"},terms:{"0":[1,2,3,4,6,9,10,12,14,15,16,18,25,27,30,31,32,34,35,37,38,42,43,44,46,47,48,50,56],"00":43,"000":10,"000077":43,"000153":43,"000309":43,"000368":43,"000422":43,"000480":43,"000669":43,"000755":43,"031ebb0":55,"04":0,"05":38,"0l":38,"0m":0,"1":[1,2,3,4,6,10,13,15,18,19,25,27,30,31,32,34,35,36,38,42,43,44,46,47,48,52,53,54,56],"10":[1,3,10,38,44,46,50],"100":[0,4,10,42,50],"1000":[0,4],"1004":0,"1005":0,"1006":0,"1007":0,"1008":0,"1009":0,"101":0,"1012":0,"1013":0,"1015":0,"1016":0,"1017":0,"1018":0,"1019":0,"1020":0,"1021":0,"1023":0,"1024":0,"1026":0,"1027":0,"103":0,"1031":0,"1033":0,"1036":0,"1039":0,"104":0,"1042":0,"1044":0,"1045":0,"1047":0,"1048":0,"105":0,"1051":0,"1054":0,"1056":0,"1057":0,"106":0,"1060":0,"1064":0,"1065":0,"1067":0,"1068":0,"1074":0,"10786":30,"1079":0,"108":0,"1081":0,"1082":0,"1087":0,"1089":0,"109":0,"1090":0,"1091":0,"1093":0,"10l":38,"110":0,"1100":0,"1103":0,"1104":0,"1105":0,"111":[0,36],"1110":0,"111111111111":9,"1112":0,"1114":0,"1116":0,"1117":0,"1118":0,"1119":0,"112":0,"1121":0,"1122":0,"1123":0,"1124":0,"1126":0,"1127":0,"1129":0,"1130":0,"1131":0,"1140":0,"1158":0,"116":0,"1161":0,"1162":0,"1163":0,"1166":0,"1172":0,"1174":0,"1177":0,"1181":0,"1183":0,"1185":0,"1186":0,"1187":0,"1189":0,"119":[0,32],"1192":0,"11e3":44,"11l":38,"120":0,"1203":0,"1204":0,"1205":0,"1207":0,"1212":0,"122":0,"1220":0,"1228":0,"123":[0,3,36,56],"1233":0,"1234":54,"1237":0,"1238":0,"1239":0,"124":0,"1240":0,"1241":0,"1243":0,"1244":0,"1245":0,"1248":0,"125":0,"1258":0,"126":0,"1260":0,"1264":0,"1265":0,"1266":0,"1269":0,"127":[3,25,35,38,42,43,44,48,54],"1287":0,"1289":0,"1290":0,"12l":38,"1304":0,"1327":0,"1328":0,"1329":0,"135":0,"138":0,"13l":38,"14":32,"141":0,"143":0,"144":0,"145":27,"147":0,"148":0,"14l":38,"15":[27,44],"150":0,"151":0,"155":0,"157":0,"159":0,"15l":38,"16":6,"160":0,"163":0,"164":0,"165":0,"166":0,"167":0,"168":[3,44],"16l":38,"17":[38,54],"173":0,"174":0,"175":0,"178":[0,30,55],"179":0,"17l":38,"180":0,"181":0,"182":0,"184":0,"185":0,"186":0,"187":0,"189":0,"18l":38,"190":0,"191":0,"192":[0,3,44],"194":0,"195":0,"196":0,"197":0,"1970":32,"198":0,"1982":38,"19l":38,"1e6":31,"1l":38,"1s":0,"2":[1,2,3,4,6,9,10,12,13,14,15,16,18,25,27,30,32,34,35,36,38,40,42,43,44,45,46,47,50,53,54,56],"20":38,"200":0,"2008":10,"2010":[35,38],"2011":38,"2012":38,"2013":[0,45],"2014":[0,38],"2015":0,"2016":[0,45],"2017":[0,45],"2018":0,"2019":0,"202":0,"2020":0,"2021":0,"2023":0,"204":0,"2048":54,"205":0,"206":0,"207":0,"208":0,"21":[38,55],"210":0,"211":0,"212":0,"213":0,"215":0,"218":0,"219":0,"22":46,"220":0,"222":0,"226":0,"229":0,"23":32,"230":0,"231":0,"234":0,"235":0,"238":0,"239":0,"24":3,"240":0,"241":0,"243":0,"244":0,"245":[0,40],"246":0,"249":0,"255":0,"258":0,"26":38,"260":0,"2644bada":44,"266":0,"27":0,"272":0,"273":0,"276":[0,55],"277":0,"278":0,"279":43,"28":0,"280":0,"282":0,"283":0,"284":0,"285":0,"286":0,"288":0,"289":0,"29":0,"291":0,"292":[0,55],"294":0,"295":0,"296":0,"297":0,"298":0,"299":0,"2l":38,"3":[1,2,3,4,6,9,10,15,18,19,25,27,30,31,32,34,36,37,38,45,46,48,53,56],"30":[0,3,38,42,44],"300":0,"301":0,"302":0,"303":0,"305":0,"306":0,"309":0,"31":[0,38],"310":0,"311":0,"313":0,"315":0,"317":0,"318":[0,55],"319":0,"32":6,"322":0,"323":0,"324":0,"325":0,"327":0,"329":0,"331":0,"332":0,"333":0,"334":0,"335":0,"336":0,"337":0,"338":0,"340":32,"341":0,"342":0,"343":0,"344":0,"345":0,"346":0,"347":0,"348":0,"349":0,"351":0,"352":0,"353":0,"354":0,"357":0,"358":0,"360":0,"3600":3,"361":0,"362":0,"363":0,"365":0,"368":[0,55],"370":0,"371":0,"375":0,"377":0,"378":0,"379":0,"381":0,"385":[0,55],"386":0,"392":0,"393":0,"394":0,"395":0,"396":0,"397":0,"398":0,"3l":38,"4":[1,2,3,6,9,10,19,27,29,30,32,42,48],"400":[0,55],"405":0,"407":0,"408":[0,55],"409":0,"412":0,"413":0,"415":0,"416":0,"419fcdf":55,"42":[3,30,44],"422":[0,55],"429":0,"430":0,"432":0,"433":0,"434":0,"435":0,"438":0,"439":0,"442":0,"443":0,"444":0,"445":0,"447":0,"450":0,"451":0,"452":0,"454":0,"458":0,"459":0,"46":0,"464":0,"466":0,"467":0,"468":0,"469":0,"470":0,"471":0,"473":0,"475":0,"476":0,"477":0,"478":0,"479":0,"48":32,"480":0,"481":0,"482":0,"486":0,"487":0,"489":0,"495":0,"498":0,"4bd5909":55,"4l":38,"4th":0,"5":[1,3,9,10,19,27,38,44,45,46,54],"50":4,"500":10,"5000":[3,10,50],"501":0,"502":0,"503":0,"505":0,"507":0,"508":0,"509":0,"50m":38,"510":0,"512":0,"514":0,"520":0,"521":0,"522":0,"527":0,"528":0,"530":0,"531":0,"532":0,"533":0,"535":0,"537":0,"538":0,"542":0,"547":0,"548":0,"549":0,"550":0,"551":0,"553":0,"555":0,"556":0,"557":0,"559":0,"56":0,"560":0,"561":0,"562":0,"565":0,"566":0,"568":0,"569":0,"570":0,"572":0,"5723":0,"573":0,"574":0,"574266d":55,"576":0,"577":0,"578":0,"579":0,"580":0,"583":0,"584":0,"585":0,"589":0,"59":[0,32],"591":0,"593":0,"595":0,"596":0,"598":0,"599":0,"5l":38,"6":[1,3,6,10,19,25,27,30,38,45,46],"60":0,"600":0,"606":0,"607":0,"608":0,"609":0,"613":0,"614":0,"616":0,"617":0,"618":0,"619":0,"621":0,"622":0,"623":0,"626":0,"628":0,"630":0,"631":0,"636":0,"64":[6,9,27],"640":0,"642":0,"643":0,"644":0,"645":0,"646":0,"647":0,"648":0,"649":0,"65":1,"650":0,"653":0,"655":0,"656":0,"657":0,"66":[1,3],"665":0,"668":0,"669":0,"673":0,"676":0,"678":0,"682":0,"684":0,"686":0,"688":0,"69":0,"690":0,"692":0,"694":0,"697":0,"6l":38,"7":[1,3,6,10,27,45,46],"70":0,"700":0,"705":0,"706":0,"707":0,"708":0,"709":0,"71":0,"710":0,"714":0,"717":0,"719":0,"720":0,"721":0,"723":0,"724":0,"727":0,"728":0,"729":0,"73":0,"730":0,"732":0,"733":0,"734":0,"735":0,"736":0,"737":0,"739":0,"740":0,"741":0,"742":0,"743":0,"746":0,"747":0,"749":0,"75":0,"750":0,"751":0,"752":0,"754":0,"755":0,"759":0,"75percentil":26,"75th":26,"76":0,"761":0,"762":0,"763":0,"767":0,"768":0,"769":0,"77142":43,"772":0,"773":0,"774":0,"774000":38,"775":0,"778":0,"781":0,"782":0,"785":0,"7857":0,"78723":[3,56],"788":0,"789":0,"79":0,"793":0,"794":0,"798":0,"799":0,"79efe97":55,"7l":38,"8":[1,3,6,17,31,45,46,48],"80":0,"804dea3":0,"805":0,"808":0,"81":0,"810":0,"812":0,"813":0,"814":0,"819":0,"82":0,"827":0,"829":0,"831":0,"833":0,"836":0,"837":0,"838":0,"839":0,"84":0,"840":0,"843":0,"846":0,"848":0,"852c":44,"853":0,"86":0,"860":0,"861":0,"862":0,"863":0,"86400":9,"865":0,"868":0,"872":0,"8733":40,"877":0,"88":0,"885":0,"888":0,"89":0,"891":0,"892":0,"893":0,"894":0,"895":0,"897":0,"89fb":44,"8l":38,"9":[1,9,38],"90":0,"900":0,"901":0,"903":0,"9042":[3,5],"91":0,"910":0,"915":0,"916":0,"92":0,"9223372036854775808":43,"93":0,"932":0,"934":0,"937":0,"940":0,"941":0,"944":0,"945":0,"946":0,"947":0,"95":0,"953":0,"955":0,"95percentil":26,"95th":26,"96":0,"963":0,"96489cc":55,"966":0,"968":0,"97":0,"973":0,"978":0,"98":0,"98percentil":26,"98th":26,"99":[0,26],"992":0,"993":0,"995":0,"996":0,"998":0,"99999":37,"999percentil":26,"99percentil":26,"99th":26,"9d98c8e":55,"9l":38,"9th":26,"abstract":[0,2,6,9,25,30],"boolean":[0,1,6,25,27,44,47],"break":[0,27,45,46,55],"byte":[0,6,38],"case":[0,3,4,8,9,27,32,34,35,44,49,53,54],"catch":0,"char":0,"class":[0,1,2,3,5,6,9,10,12,13,14,15,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,40,41,48,50,53,54,55],"default":[0,1,3,6,7,9,10,11,12,14,15,17,18,26,27,29,30,31,34,43,44,46,48,49,50,54],"do":[0,3,4,6,9,17,27,30,37,38,41,44,46,54,55,56],"enum":[10,13,27,32,33],"export":[0,25],"final":[3,44,54],"float":[0,3,6,10,15,18,26,27,37,38,44,55],"function":[0,1,3,8,10,12,17,25,27,29,32,41,44,53,54,55],"import":[0,2,3,4,6,10,11,12,29,30,34,35,37,38,39,41,42,43,44,46,48,50,52,53,54],"int":[0,3,6,7,8,15,18,25,31,32,38,44,47,55,56],"long":[0,32,44,46,56],"new":[0,1,2,3,4,6,7,10,21,25,27,30,31,32,34,36,38,39,40,42,44,48,50,54,55,56],"null":[0,10,17,36,38,44],"public":27,"return":[0,1,2,3,4,9,10,12,14,15,18,25,26,27,29,30,31,32,33,37,38,39,41,43,44,47,48,50,52,54,56],"short":[0,30,37,52],"static":[0,3,6,10,12,13,32],"super":37,"switch":[0,10,46],"throw":[0,3,30],"transient":0,"true":[0,3,4,6,7,8,9,10,15,18,25,27,30,31,34,35,36,37,38,40,43,44,47,48,53,54],"try":[0,1,3,8,9,27,37,39,41,44],"while":[0,3,27,30,37,40,50,55],A:[0,1,2,3,4,7,8,10,12,13,14,17,18,25,26,27,30,32,35,37,38,44,45,46],AND:[47,53],And:[9,54,55],As:[9,32,40,44,53,56],BY:37,Be:49,But:30,By:[1,3,9,10,27,29,34,38,43,44,46,50,52,54,55],For:[0,1,3,6,7,9,10,25,27,30,32,36,37,38,40,41,42,44,46,47,48,49,50,51,53,54,55],IF:[0,10,27,30,47,53,55],IN:[17,25,30],INTO:[3,4,30,44,47,56],IS:[0,38,40],If:[0,2,3,4,7,8,9,10,11,14,25,27,30,31,32,34,35,36,37,41,42,44,46,47,50,54,55],In:[0,3,27,29,34,38,40,44,46,53,54,55],It:[0,3,9,21,22,27,32,35,37,38,43,44,46,47,54],NOT:[0,38,47,53],No:45,Not:[0,32],ONE:[1,3,10,40,55],Of:3,On:[0,27,46],One:[10,41],Or:3,Such:27,THERE:40,That:38,The:[0,1,2,3,4,5,6,7,9,10,12,13,14,15,17,18,25,26,27,28,29,30,32,34,36,37,38,40,41,42,44,45,46,47,49,52,54,55,56],Then:54,There:[1,3,6,8,30,38,44,46,55],These:[0,3,6,9,27,29,30,32,40,41,49,54,55],To:[3,9,11,27,34,35,37,38,40,41,42,43,44,46,51,54,55],WITH:[37,53],Will:9,With:[0,35,43,52,54,55],_1:54,_2:54,_3:54,_4:54,_:42,__:[10,38,55],__abstract__:9,__compute_routing_key__:9,__connection__:[8,9,35],__contain:38,__default_ttl__:9,__del__:0,__discrimin:55,__discriminator_value__:[6,9,37,40],__ge__:0,__gt:38,__gte:38,__in:[0,38],__init__:[0,3,27,31,50,55,56],__keyspace__:[8,9,35,37],__le__:0,__len__:0,__like:38,__lt:38,__lte:38,__name__:43,__ne__:0,__options__:[9,38],__polymorphic_:55,__polymorphic_key__:40,__repr__:0,__table_name__:[9,37,40],__table_name_case_sensitive__:9,__type_name__:11,__version__:[1,46],__version_info__:1,_connect:0,_dsegraphson2rowfactori:12,_gremlingraphson2rowfactori:12,_messagetyp:29,_metadata:55,_new_tim:21,_next_timestamp:31,_not_set:3,_protocolhand:29,_protocolhandl:29,_replicationstrategi:25,_set_final_except:0,_set_result:0,_timeout_watch:21,a2:10,a2d3a98:55,abil:[0,27,42,55],abl:46,about:[0,3,25,30,37,41,44,46,52,54,55],abov:[3,29,34,35,41,44,49],absolut:[32,40],accept:[0,3,27,32,40,41],access:[0,3,9,26,30,37,44,55],accommod:[0,41],accomplish:[38,46],accord:[0,3],accordingli:0,account:[0,37],accumul:10,accur:25,acheiv:27,achiev:[27,34,54],acknowledg:27,across:[0,19,20,21,22,27,42,43,49],act:54,activ:[0,3,21,22],actual:[0,1,27,30,38,44,47],ad:[0,1,3,10,21,25,27,30,34,37,38,46,55],add:[0,3,7,8,10,14,27,30,34,55,56],add_al:[14,30],add_callback:[3,10,34,44,49,50],add_collback:0,add_errback:[3,44],add_execution_profil:[3,12,42],add_failur:27,add_or_return_host:25,add_queri:10,add_request_init_listen:3,add_tim:0,addit:[0,3,10,12,29,34,37,38,44,47,48,54,55],addition:[30,37,40,54],additional_write_polici:0,addr:[27,37],address:[0,1,3,5,11,25,28,30,33,37,43,44,52,54,55,56],address_is_ignor:27,address_transl:3,addresstransl:[0,27],adher:41,adjust:[0,40],advanc:54,advic:3,affect:[3,30,34],after:[0,3,4,10,20,27,30,34,37,38,40,43,44,46,49],afterward:55,ag:[3,30,38,44],against:[0,1,3,9,27,30,37,44,48,54],aggreg:[0,1,3,25],agnost:32,agre:0,agreement:[0,3],ahead:[3,44],aim:[35,42],algorithm:[36,46],alia:[6,12,25,32,40],alias:0,alic:30,align:0,aliv:[1,26,27],alive_replica:[1,27],all:[0,1,3,4,6,8,9,10,17,21,22,25,26,27,28,29,30,35,41,44,46,47,49,53,54,55],all_host:[25,42,52],all_object:38,all_replica:25,allow:[0,3,6,9,10,12,13,27,29,30,31,32,34,36,37,46,52,53,54,55,56],allow_beta_protocol_vers:29,allow_filt:[10,38],almost:44,along:[3,25,50],alpha:0,alphanumer:0,alreadi:[0,1,3,5,8,35,46],alreadyexist:1,also:[0,3,4,9,10,13,27,30,32,35,37,38,42,43,44,46,54,55],alter:[9,27,37],altern:[3,29,37,40,44,46,49,54],although:[44,55,56],althought:44,alwai:[0,3,15,18,27,41,44,46,47],ambigu:0,among:[1,27],amount:[0,4,27],an:[0,1,2,3,4,5,6,8,9,10,12,13,15,17,18,19,20,21,22,23,24,25,26,27,29,30,31,32,34,35,36,37,38,40,41,42,44,45,46,48,49,50,53,54,55,56],analysi:29,analyt:[0,3,15,18],analyticskeyspac:3,analyticskeyspace_prepar:3,andrew:[46,54],ani:[0,1,3,8,9,10,13,14,17,19,20,21,22,26,27,30,34,37,38,41,43,44,45,46,47,49,54,56],annot:0,anomali:0,anoth:[27,34,35,38,44,54,55],anymor:[38,55],anyth:[34,41],anywai:46,apach:[38,46,55],api:[0,32,37,41,42,45,46,48,49,54],app:[39,43],appear:[0,47],append:[4,10,25,38,44],appli:[0,3,9,10,14,30,36,41,42,44,46,47,48,56],applic:[0,3,6,27,39,40,41,44,46,49,50,52,55],approach:[41,45],appropri:[3,37,46,54],april:0,apt:46,ar:[0,1,3,4,6,7,8,9,10,15,18,21,25,26,27,28,29,30,32,34,36,37,40,41,42,43,44,45,46,47,48,50,54],arbitrari:[6,32],archflag:46,architectur:46,arg:[3,4,6,9,10,19,20,21,22,23,27,32,34],arg_typ:1,argument:[0,1,3,4,7,9,10,15,18,27,30,31,32,34,35,44,46,54,55],argument_typ:1,arm:0,around:[0,9,32,40,41,55],arrai:[29,38],arriv:3,as_cql_queri:[0,25],as_edg:[15,18],as_graph_stat:14,as_path:[15,18],as_vertex:[15,18],ascend:[10,38],ascii:[0,6,44],ask:[45,48],assert:[6,36,53],assertionerror:38,assign:[0,6,11,37],associ:[0,3,55],assum:[3,21,22,38,41,54,55],assumpt:41,astimezon:41,astra:0,async:3,asynchron:[0,3,30,43,49],asyncio:[0,33],asyncioconnect:19,asyncioreactor:[0,33],asyncor:[0,33,46],asyncoreconnect:[0,20],asyncorereactor:[0,33],atexit:0,atlassian:27,atom:[27,30],attach:[0,3,15,18,34,44,49,50],attempt:[0,1,3,4,5,27,34,41,43,44,55],attr_kwarg:3,attribut:[0,3,6,8,9,10,11,15,18,25,27,29,30,31,37,38,40,42,44,47,55,56],attributeerror:0,aug:0,august:0,auth:[0,33,54,55],auth_provid:[2,3,54],authent:[0,1,3,33],authenticationfail:[1,2],author:[1,54],authorization_id:54,authprovid:[0,2,3,54],auto:35,automat:[0,1,3,35,37,38,44,46,50],automobil:[10,35,38],automobile2:10,avail:[0,3,10,30,38,45,46,53,55],avoid:[0,3,27,40,43,46],aw:27,awai:[3,30],awar:[0,3,26,27,41,46,54,55],ayncoreconnect:0,b:[3,4,12,14,15,18,34,35,36,38],back:[0,6,9,32,38],backoff:0,backpressur:0,backup:38,backward:[3,18,25,55],bad:0,badli:0,balanc:[0,3,33,42,55],bar:44,bark_all_night:37,base:[0,1,3,9,12,26,27,29,30,32,37,40,43,44,47,52,53,54],base_delai:27,basegraphrowfactori:12,basi:[0,55],basic:[0,3,12,37],batch:[0,1,3,9,10,12,14,25,27,33,35,38,48],batch_log:27,batch_obj:10,batch_object:9,batch_r:10,batch_typ:[10,30,34],batchqueri:[0,10,34,36,38],batchstat:[0,1,3,30,55],batchtyp:[0,10,30,34],bb984ee:55,beat_init:39,becam:[0,40],becaus:[0,3,4,15,18,27,30,32,40,41,44,46,53,55],becom:[0,3,8,49,55],been:[0,3,5,9,26,27,30,34,35,40,55],befor:[0,1,3,9,10,27,29,30,40,43,44,49,50,55],begin:[0,10,13,44],behav:32,behavior:[0,3,6,27,44,55],behind:[27,41],being:[0,3,6,26,30,36,42,44,46,47],below:[3,4,10,27,29,36,37,38,40,46,47,49,55],benchmark:[0,49],benefit:55,best:[27,44,51,54],beta5:1,beta:[1,46],beta_vers:1,better:[0,27,46,49],between:[0,2,6,29,30,46,53],bewar:27,beyond:37,big:[0,53],bigint:[6,15,18,44],binari:[0,6,30],binary_typ:29,bind:[0,3,12,30,43,44],bit:[6,32,46],bitmap:29,blacklist:27,blacklist_filter_polici:27,blah:44,blake:[9,38],blank:9,blind:[9,10],blindli:10,blist:0,blob:[0,6,17,44,53],block:[0,3,4,34,44,49],blog:49,bob:[3,30,44],bodi:[0,29],bool:[6,7,8,10,25,44,53],bootstrap:[0,26],bop:0,borrow_connect:0,both:[0,3,38,39,44,46,54],bound:[3,14,30,32,43,49],bound_stmt:3,boundstat:[0,30,44,55],bracket:47,brew:46,broadcast_address:27,broadcast_rpc_address:25,broadcast_rpc_port:25,broken:0,brought:55,brows:27,brute:27,bu:0,bucket_high:9,bucket_low:9,buffer:[0,17,44],bug:[40,45,55],build:[0,25,40,44,46,49],built:[0,32,42,46,49,55],bulk:12,bulkset:0,bump:0,bundl:52,busi:[3,28],bypass:[0,3,8,30],bytearrai:[0,17,44],bytebuff:0,bytecod:12,byteorderedpartition:[0,25],bytesio:0,bytestoken:25,c0:53,c:[0,6,12,25,27,38,54],ca:[0,27,54],ca_cert:54,cach:0,cacreateseri:54,cakei:54,calcul:0,call:[0,2,3,5,9,10,17,19,20,21,22,27,31,34,37,38,41,44,48,50,54],callabl:[6,10,12],callback:[0,3,10,44,49,54],callback_arg:3,callback_kwarg:3,camera:38,can:[0,1,3,4,6,8,9,10,13,14,15,17,18,21,25,27,29,30,31,32,34,35,37,38,39,41,42,43,44,45,46,48,49,50,52,53,54,55,56],cancel:0,cannon:40,cannot:[0,27,30,32,38,42],capabl:50,captur:[0,46],car:38,cardin:[15,18],care:[3,8],carri:34,cass_driver_build_concurr:46,cass_driver_no_cython:46,cass_driver_no_extens:46,cass_server_vers:0,cass_typ:32,cassandra:[0,33,34,35,36,37,38,39,40,42,43,46,48,49,50,52,53,54,56],cassandra_init:39,cassandra_vers:0,cast:44,cat:[37,40,54],caus:[0,3,10,26,37,47],caution:[8,37],caveat:27,cc94073:55,cdc:[0,27],cdef:0,ceas:27,ceil:1,celeri:48,cell:43,center:30,cento:[0,46],central:41,cert:54,cert_countri:54,cert_org_nam:54,cert_ou:54,cert_req:54,cert_requir:54,cert_valid:54,certain:[13,27,40,46],certfil:54,certif:[0,54],chain:34,challeng:[2,46],chanc:27,chang:[0,3,6,9,10,25,27,30,31,36,37,38,43,44,45],changelog:45,charact:[0,6,44],charl:30,check:[0,3,9,10,27,37,46,53,55],check_hostnam:[0,54],check_support:27,checkout:46,checksum:0,child:[0,27,43],child_polici:27,choic:[46,49],choos:[15,18,27,55],chosen:3,chunk:0,circuit:0,circumst:0,citi:55,civic:[10,35,38],cl:[0,10,21],clang:46,classic:0,classmethod:[1,9,15,18,19,20,21,22,25,29,32],claus:[0,10,25,37,47,55],clean:[0,39,46,55],cleanup:[0,20],clear:[0,14,27,30],clearer:41,client:[0,1,2,3,8,27,29,41,42,45,53],client_encryption_opt:54,client_protocol_handl:[3,29],clock:32,clock_seq:32,clone:[3,42],close:[0,3,5],closur:0,cloud:[0,3,27,45],cluster1:35,cluster2:[10,35],cluster3:35,cluster:[0,2,4,5,6,7,9,10,12,15,18,19,20,21,22,25,26,27,29,30,33,35,37,38,39,43,46,48,49,51,52,54,56],cluster_nam:52,cluster_opt:7,clustering_kei:38,clustering_ord:[6,37],clustertest:0,cn:54,code:[0,1,34,39,45,54,55,56],codebas:0,coerc:6,coincid:0,col:[0,47],col_nam:9,collect:[0,3,8,10,15,25,26,30,32,38,45,55],collis:0,colnam:[3,10,30],column:[0,8,9,10,11,13,17,25,30,33,35,36,37,38,44,47,48,55,56],column_family_nam:9,column_nam:[10,15,18,38],columnmetadata:[25,55],com:[6,10,53,54],combin:[0,3],come:0,comma:44,command:[0,35,46],comment:[9,10,37],comment_id:[10,37],common:[0,40,46,54,55],commun:[0,5,46],compact:[0,9,53],compar:[0,30,32,45],comparison:[0,6],compat:[0,3,18,25,33,55],compil:[0,29,46,49],complain:37,complet:[0,1,2,3,4,11,27,30,34,37,40,43,44,49,54],complex:[0,42,46],compliant:0,compon:[0,10,25,30,32,54],compos:29,composit:[0,30,38],compositetyp:0,compound:6,compress:[0,3,29],compressor:29,compris:[1,29],comput:[0,3,9,43],concern:41,concis:15,concurr:[0,3,8,30,33,43,44,49],condit:[0,1,3,8,10,30,45],conf:54,config:[0,54],configur:[0,1,2,3,5,7,9,15,18,27,31,42,44,45,53],configurationexcept:1,confirm:0,conflict:36,confus:[40,55],conn:35,connect:[0,1,2,3,4,8,9,10,11,12,19,20,22,23,24,26,27,30,33,37,38,39,40,42,45,46,48,51,52,53,54,55,56],connect_timeout:[0,3],connect_to_remote_host:3,connected_to:26,connection_class:[3,46,54],connection_error:26,connection_exc:27,connectionbusi:5,connectionexcept:[0,5],connectionshutdown:5,consensu:1,consid:[0,1,3,18,27,44,47,49,54,55],consider:[37,49],consist:[0,1,3,7,10,27,30,32],consistency_level:[3,15,18,30,42,44],consistencylevel:[0,1,3,7,10,15,18,26,27,30,40,44],consit:0,constant:[0,54],constantreconnectionpolici:[0,27],constantspeculativeexecutionpolici:[0,27,44],constrain:[4,10],constraint:[9,37],construct:[0,9,12,32,41,42,44],constructor:[0,3,6,38,52],consult:37,consum:[0,4,55],consumpt:[0,49],contact:[0,3,27,44],contact_point:[0,3,7,27,54],contain:[0,3,6,9,10,13,17,27,32,37,38,41,47,50,53],contains_kei:13,contains_valu:13,contend:0,content:[0,10,29],context:[0,3,8,9,10,12,15,18,34,39,46,49,54],contextqueri:[0,10,35],contin:0,continu:[0,2,27,50],continuous_paging_opt:3,contract:[0,29],control:[0,3,4,27,30,40,49,54],control_connection_timeout:3,conveni:[3,15,18,30,38],convent:37,convers:[15,18,40,41,55],convert:[0,13,15,17,18,32,40,41,55],convict:27,conviction_policy_factori:3,convictionpolici:27,coord:32,coordin:[1,3,4,27,32,43],coordinationfailur:1,copi:42,copyright:0,core:[0,3,4,38,40,46,49],core_connect:3,coroutin:0,correct:[0,9,41],correctli:[0,3],correspond:[2,4,6,8,37],cost:[0,9,10,38],costli:46,could:[0,10,55],count:[0,9,10,26,27,36,38,48],counter:[0,6,26,27,30,37,44],countri:45,cours:3,cover:[37,43],coverag:0,cpu:[0,4,44,49],cpython:[0,3,46],cql3:[36,38,45],cql:[0,1,6,9,10,11,13,15,17,18,25,30,32,36,37,38,40,41,47,48,53,55,56],cql_cluster:39,cql_encode_all_typ:17,cql_encode_byt:17,cql_encode_d:17,cql_encode_datetim:17,cql_encode_list_collect:17,cql_encode_map_collect:17,cql_encode_non:17,cql_encode_object:17,cql_encode_sequ:17,cql_encode_set_collect:17,cql_encode_str:17,cql_encode_tupl:[17,55],cql_encode_unicod:17,cql_keyword:25,cql_keywords_reserv:25,cql_keywords_unreserv:25,cql_refer:10,cql_session:39,cql_use:6,cql_version:[0,3],cqlcollect:13,cqle:0,cqlengin:[0,33,34,35,36,37,38,39,43,45,48,55],cqlengine_batch:34,cqlengine_test:38,cqlengineexcept:[0,40],cqltype:55,cqluseudt:6,crash:0,creat:[0,1,2,3,5,6,7,8,9,10,12,25,27,30,32,34,35,36,37,38,41,43,44,47,48,49,53,54,55,56],create_default_context:54,create_execution_profil:12,create_keyspac:40,create_keyspace_network_topolog:[8,40],create_keyspace_simpl:[8,40],create_simple_keyspac:35,created_at:[34,48],creation:[0,3,4,25,38],credenti:[0,3,52,54],credit:44,crt:54,crt_sign:54,crypto:54,csr:54,cstringio:0,cumbersom:41,current:[0,1,3,10,12,26,27,30,31,38,42,43,46,50,55],current_pag:3,current_row:3,custom:[0,1,3,6,10,17,27,30,33,41,42,44,46],custom_index:6,custom_payload:[3,15,18,29,30],cut:0,cute:37,cycl:3,cython:[0,29],cython_protocol_handl:3,cythonprotocolhandl:3,d:[3,6,10,30,41,44],daemon:0,dai:[6,27,32,54],dash:0,data:[0,1,3,9,10,27,30,33,37,38,41,43,44,53,55,56],data_retriev:[1,27],databas:[6,8,9,34,37,38,41,42,52],datacent:[0,1,27,28,52],dataset:[0,10,38],datastax:[0,6,10,18,27,44,45,46,48,54,55],datastream:38,datatyp:0,date:[0,6,17,32,44,45,55],daterang:[0,32],daterangebound:32,daterangeprecis:32,datetim:[0,6,10,17,32,34,36,38,40,41,44,48],datetime_from_timestamp:32,datetime_from_uuid1:32,datetyp:0,david:13,daylight:41,days_from_epoch:32,db:0,db_field:[0,6],dc:[0,3,27,55],dc_name:8,dc_replication_factor:25,dc_replication_map:8,dcawar:0,dcawareloadbalancingpolici:0,dcawareroundrobinpolici:[0,3,27,42,52],dclocal_read_repair_ch:0,dct:0,dd:[17,32],ddl:0,dead:33,deadlock:[0,4],deal:[0,41,42,49,55],debian:[0,46],debug:[0,3],decemb:0,decid:27,decim:[0,6,10,38,44],decimaltyp:0,decis:[0,26,41],declar:[11,37],decod:[0,3,29,30,33,55],decode_messag:29,decomiss:0,decommiss:[0,27],decompress:29,decompressor:29,decor:0,decrement:6,deem:41,def:[3,27,34,37,39,43,44,50,52,54,55,56],defacto:41,default_bit:54,default_consistency_level:[0,3,7,42],default_fetch_s:[3,50],default_keyspac:[0,7],default_retry_polici:[3,27,42,43],default_serial_consistency_level:[0,3,42],default_time_to_l:[0,38],default_timeout:[3,42],defaultloadbalancingpolici:[0,27,55],defer:[0,10,27],defici:41,defin:[0,1,2,3,6,8,9,10,15,18,25,27,30,33,35,38,40,42,44,45,48],definit:[0,3,6,15,29,38,40],defunct:[0,3,5],degre:13,delai:[0,27,44],deldyck:37,delet:[0,8,9,10,27,30,34,38],delete_keyspac:40,deliv:3,deliveri:3,demand:0,demonstr:54,dep:0,depend:[0,2,41,43,47,49],deploi:52,deploy:54,deprec:[3,9,16,27,54],deprecationwarn:[0,55],depth:0,dequ:0,deriv:[32,37,40,42,46,55],derivi:9,desc:37,descend:[10,37,38],describ:[1,27,29,32,38,40,41,54],descript:[0,3,15,18,27,30,34,43,48,54],descriptor:0,deseri:[0,15,18,33,41],deserialize_bigint:[15,18],deserialize_blob:[15,18],deserialize_d:[15,18],deserialize_decim:[15,18],deserialize_doubl:[15,18],deserialize_dur:[15,18],deserialize_float:[15,18],deserialize_int:[15,18],deserialize_linestr:[15,18],deserialize_point:[15,18],deserialize_polygon:[15,18],deserialize_tim:[15,18],deserialize_timestamp:[15,18],deserialize_uuid:[15,18],design:[44,49],desir:[3,10,27,34],despit:10,destroi:0,detail:[0,1,3,9,10,30,37,41,42,43,44,49,53,54,55],detect:[0,40],determin:[6,9,27,30,44],determinist:0,dev:[46,53],devel:46,deviat:26,devic:0,dict:[0,1,3,6,7,8,9,12,15,17,18,25,26,29,30,37,44,47,53,54],dict_factori:[0,3,7,16,30,55],dictionari:[0,6],dictlik:32,did:[5,10,27],didn:10,differ:[0,3,10,29,30,32,36,37,38,42,44,54,55],digest:27,dir:0,directli:[3,4,17,29,30,44,46,54],disabl:[0,3,9,10,46,53],disable_shardaware_port:53,discontinu:0,discourag:3,discov:[0,3,27,44],discoveri:0,discrimin:[6,9,37],discriminator_column:[6,37,40],discuss:[3,6,11,30,37,45,47,49],disentangl:0,disk:6,dispos:3,disproportion:27,distanc:[13,27,32],distant:27,distinct:[0,10,15,18],distinct_field:10,distinguish:0,distinguished_nam:54,distribut:[0,27,38,46],distrimin:37,distriminator_column:37,dll:0,dn:27,doc:[0,1,6,10,37,38,41,53,54],document:[0,6,27,32,41,42,45,46,48,54,55],doe:[0,3,10,17,32,34,38,40,44,46,47,56],doesn:[0,31,55],doesnotexist:[0,10],dog:[37,40],dollar:0,don:[0,10,38,44,49,56],done:[0,3,37,41,43,54,55],dont:0,dontprepareonignoredhoststest:0,doubl:[0,6,15,18,32,44,49,55],double_precis:[40,55],down:[0,3,33,46],downgrad:[0,27],downgradingconsistencyretrypolici:[0,27,44],download:52,drain:0,drift:31,driven:8,driver:[0,1,3,5,7,10,18,26,27,28,29,30,37,38,40,41,44,46,47,48,49,50,51,52,53,54,56],driverexcept:1,drop:[0,6,8,29],drop_keyspac:[8,40],drop_tabl:8,drope:0,dsa:0,dse:[0,1,3,6,12,14,15,18,32],dse_graph:55,dse_graph_query_languag:12,dse_graph_query_protocol:12,dse_v1:[0,1],dse_v2:1,dsegraph:12,dsegssapiauthprovid:[0,54],dseloadbalancingpolici:[0,27,55],dseplaintextauthprovid:54,dsesessionremotegraphconnect:12,dsl:12,dt:32,due:[0,1,10,26,34,49],duplic:0,durabl:3,durable_writ:8,durat:[0,30,32],durationtyp:0,dure:[0,1,2,3,5,9,40,46],dynam:[0,3],dynamiccompositetyp:0,e0b9a54a6d93:44,e16a073:55,e:[3,8,9,10,12,15,18,27,30,43,46],each:[1,2,3,4,6,9,27,30,36,37,38,41,44,50,55,56],each_quorum:1,eagain:0,eai:0,earlier:[0,21,37],eas:35,easi:[0,37,38],easier:[38,42,46],easiest:[41,46],easili:[0,10,41],east:52,eat:37,ec2:0,ec2multiregiontransl:27,ed:0,edg:[0,15,18,25],edgemetadata:25,effect:[0,3,8,34,54],effici:[0,29],effort:[0,40,54],eggleston:9,either:[2,3,15,18,32,37,38,41,45,46],element:[0,3,10,15,18,25,32,38,44],elementmap:0,els:[4,39,50],em1:[34,48],em2:[34,48],em3:[34,48],em4:48,em5:48,em6:48,em7:48,em8:48,email:44,emit:[3,40,46],empti:[0,2,3,25,47],en:[6,10],enabl:[0,3,10,44,53,54,55],enable_shard_aware_driv:53,encod:[0,3,6,15,18,29,33,41],encode_messag:29,encount:[0,3,10],encrypt:[0,54],end:[0,10,34],endian:0,endless:0,endors:45,endpoint:[5,25,27,28,52,54],endpoint_factori:3,endpoint_or_address:25,endpointfactori:[5,54],enforc:[0,37],engag:46,engin:[0,3],enough:[1,30],ensur:[0,3,4,9,27,39,46,54],enterpris:53,entir:[0,3,4,10,14,25],entiti:0,entri:[10,13,17,55],entry_eq:13,environ:[8,27,46],eof:54,ep:[3,44],epoch:[0,31,32,41],eq:0,equal:[0,3,6,30,38],equival:[9,36,41,44],errback:[0,3,44,50],errback_arg:3,errno:0,error:[0,1,3,4,5,6,10,27,44,50],error_code_map:1,errro:1,escap:[0,17],especi:[0,8,42,46],essenti:38,establish:[3,44],etc:[3,10,26,27,38],evaluate_challeng:2,even:[0,3,7,27,30,41,42,44],evenli:27,event:[0,3,4,21,27,30,33,39,43,44,46,50,54],eventlet:[0,33],eventletconnect:[21,54],eventletreactor:33,everi:[0,27,31,38,39,44],everyon:46,evict:0,evolv:42,ewouldblock:0,exact:2,exactli:[0,27,40],examin:32,exampl:[0,2,3,4,6,9,10,11,25,30,32,35,36,38,40,42,43,44,46,47,48,49,50,51,53,55,56],example1:48,example2:48,example3:48,example4:48,example5:48,example6:48,example7:48,example8:48,example_id:48,example_mapp:0,example_typ:[34,48],examplemodel:[34,48],exc:[3,50],exce:[0,50],exceed:[3,4],except:[0,3,4,5,6,7,9,10,15,18,27,28,29,30,32,33,34,37,38,39,44,50,54],excess:0,exclud:38,exclus:[7,32,45],exec_profile_default:[3,42,44,52],exec_profile_graph_analytics_default:3,exec_profile_graph_default:[3,12,55],exec_profile_graph_system_default:3,exect:0,execut:[0,1,3,8,9,10,12,14,15,18,25,27,29,30,33,35,37,38,43,45,47,49,50,53,56],execute_a:[3,54,55],execute_async:[0,3,4,29,43,44,49,50],execute_concurr:[0,4,49],execute_concurrent_with_arg:[4,49],execute_graph:[3,15,18],execute_graph_async:3,execute_on_except:[10,34],execution_profil:[3,4,12,14,42,44,52],execution_profile_clone_upd:[3,42],executionprofil:[0,3,12,42,44,52],executionresult:4,executor:0,executor_thread:3,exhaust:[0,27],exist:[0,1,3,8,9,10,27,28,42,47,48,53,55],exit:0,expand:0,expect:[0,5,9,43,47,54,55,56],expens:3,experi:4,experiment:[0,19],expir:3,explain:[0,42],explicit:[0,40,41],explicitli:[0,1,3,10,15,18,34,37,55],explod:42,explor:38,exponenti:[0,27],exponentialreconnectionpolici:[0,3,27],export_as_str:[0,25],export_for_schema:[0,25],export_schema_as_str:25,expos:[0,31,55],express:[4,13,32],extablish:3,extend:30,extens:[0,3,27,41,53],exterior:32,extern:41,extra:[0,25,30,46],extra_deserializer_map:[15,18],extract:[15,18],ey:45,f:3,facilit:29,factor:[0,8,25],factori:[3,12,33,47],fail:[0,1,3,4,7,14,15,18,26,33,34,37,44,47],failur:[0,1,7,9,26,33,34],fairli:37,fall:[0,32],fallback:[10,27,55],fallthroughretrypolici:27,fals:[3,4,6,7,8,9,10,15,18,25,27,30,47,48,53,54,55],falsei:27,falsi:27,famili:[0,5,9],faq:[43,45],fashion:3,faster:[0,33,46],favor:[27,40,53,55],feather:45,featur:[12,19,33,38,40,45,46,54],feb:0,februari:0,fedora:46,feedback:0,felcei:13,fetch:[0,3,10,30,38,44,50,55],fetch_next_pag:3,fetch_siz:[0,3,10,15,18,30,50,55],few:[3,44,46],field:[0,3,6,8,9,10,11,30,32,37,38,44,56],fieldnam:6,fierc:37,file:[0,40,49,52,54],fill:[15,18,30],filter:[0,6,9,27,33,35,48],finalis:1,find:[13,25,41,46],fine:56,finished_ev:50,finit:27,first:[0,3,4,6,7,9,27,36,37,38,40,44,45,46,48,50,54,55],first_nam:[9,37],first_pag:38,first_result:55,first_row:56,five:3,fix:[27,46,54,55],flag:[0,3,6,9,29,37,46,53],flake:0,flask:43,flat:38,flexibl:[0,45],flight:[0,5],flow:0,fluent:[0,33,46,55],fly:[0,4,9,10,35],fn:[3,10],focu:27,follow:[0,3,26,27,29,34,35,37,40,41,42,44,46,47,54,55],foo:[44,56],food:37,footprint:[4,38],forc:[0,27,54],force_token_rebuild:3,forev:[21,27,30],fork:[0,20,43,45,49],form:[1,17,32,44],format:[0,1,3,17,25,29,30,33,41,44,52,54,56],formerli:0,forward:[1,27,40],found:[0,10,25,30,45,49,54,55],foundat:45,four:32,fqdn:[0,54],fraction:32,frame:29,fraudul:0,free:44,frequent:[27,44,45,48],from:[1,2,3,4,5,6,8,9,10,11,12,15,18,20,25,27,29,30,32,34,35,37,38,39,40,42,43,44,45,46,47,48,50,52,53,54,56],from_datetim:55,from_kei:0,from_str:25,from_valu:32,from_wkt:32,frozen:[0,32,56],frozenset:44,full:[0,30,55],full_replica:25,fulli:55,functionfailur:1,functon:38,further:[3,4,27,38,43,49,54],furthermor:27,fuse:46,futur:[0,3,6,7,30,31,40,43,44,46,49,50,55],fuzzi:13,g:[0,3,12,15,18,27,30],garbag:[0,55],gc:0,gc_grace_second:9,gcc:46,gen_client_cert:54,gener:[0,1,2,4,27,29,32,33,41,44,53,54,55],geo:[0,13],geom:0,geomet:0,geometri:[13,32],geospati:0,geounit:13,get:[0,3,8,9,10,25,27,38,46,52],get_all_query_trac:[3,55],get_clust:52,get_control_connection_host:3,get_core_connections_per_host:3,get_credenti:54,get_execution_profil:[0,3],get_host:[0,25],get_host_by_host_id:25,get_lower_support:1,get_max_connections_per_host:3,get_max_requests_per_connect:3,get_min_requests_per_connect:3,get_query_trac:[0,3,43,55],get_replica:[0,25,43],get_stat:26,getstat:26,getter:[15,18],gevent:[0,33],geventconnect:[0,22],geventreactor:[0,33],gil:[0,49],github:[0,45,48,53],give:[3,27,54,56],given:[0,3,10,25,27,28,32,34,38,49],global:[0,7,43],go:[0,40,51],goal:[49,54],goe:0,good:[40,45],got:55,govern:[3,27],gracefulli:0,grant:54,graph:[0,3],graph_graphson2_row_factori:[15,18],graph_graphson3_row_factori:[3,15,18],graph_languag:[15,18],graph_nam:[12,15,18],graph_object_row_factori:[3,15,18],graph_opt:[0,3],graph_protocol:[3,12,14],graph_read_consistency_level:[15,18],graph_result_row_factori:[15,18],graph_sourc:[0,3,15,18],graph_traversal_dse_object_row_factori:12,graph_traversal_row_factori:12,graph_write_consistency_level:[15,18],graphanalyticsexecutionprofil:3,graphexecutionpolici:3,graphexecutionprofil:3,graphopt:[0,15,18],graphprotocol:[3,14,15,18],graphson1:[15,18],graphson1deseri:[15,18],graphson1seri:[15,18],graphson2:[0,15,18],graphson2read:[15,18],graphson3:[0,12,15,18],graphson3read:18,graphson:[0,12,14,15,18],graphson_1_0:[3,15,18],graphson_2_0:[14,15,18],graphson_3_0:[3,15,18],graphsonwrit:14,graphstat:[0,3,14],graphtravers:[12,14],graphtraversalsourc:12,greater:[27,50],greatli:0,greenlet:0,gremlin:[0,3,12,14,15,18,46],gremlinpython:[0,46],greplin:[0,26],groovi:[15,18],group:25,group_keys_by_replica:25,grow:0,gssapi:2,guarante:[0,27,30,55],guard:8,guid:[0,44,45,46,48,54],gx:0,h:[0,43],ha:[0,3,5,10,26,27,30,38,40,41,44,46,47,54,55,56],had:[0,40,55],handl:[0,2,3,9,10,12,29,33,38,39,41,43,44,46],handle_err:50,handle_error:[4,44,50],handle_fork:20,handle_pag:50,handle_result:3,handle_success:44,handle_writ:0,handler:[0,2,10,15,18,27,29,50],handshak:2,hang:[0,46],happen:[0,3,27],hard:46,has_more_pag:[0,3,50],hash:[0,38,46],hashabl:[0,32],hasn:0,have:[0,2,3,4,6,9,10,15,17,18,26,27,34,35,36,37,38,40,42,44,46,47,54,55,56],header:[0,29,46],healthmonitor:0,heap:0,heartbeat:0,help:[0,38,55],here:[3,9,10,34,35,37,38,39,40,41,46,48,52,54],hex:0,hh:32,high:[0,48,49],higher:[1,3,4,30,54,55],highli:44,highlight:55,hint:1,hit:[3,5],hold:[0,25,29],holder:44,homebrew:[0,46],honda2012:38,honda:[10,35,38],honor:[0,44],hook:[39,43],host1:27,host2:27,host3:27,host:[0,1,2,3,4,7,25,33,35,43,48,52,53,54,55],host_address:54,host_dist:3,host_id:25,hostconnect:0,hostdist:[0,3,27],hostfilterpolici:[0,27],hostfilterpolicyinittest:0,hostnam:[0,27,54],hoststatelisten:3,hot:46,hour:32,how:[0,1,4,6,9,27,30,38,39,41,42,44,45,47,50,54,55],howev:[0,3,10,30,34,37,38,41,46,47,50,55,56],html:[6,10,38,48],http:[6,10,27,38,48,50,53],huge:49,human:[25,41],i:[8,10,15,18,27,30,38],id:[0,3,4,6,9,10,15,18,29,34,36,37,38,44,54,56],idea:27,ideal:[32,41],idempot:[33,44],identifi:[0,1,37,47],identitytransl:[3,27],idl:0,idle_heartbeat_interv:3,idle_heartbeat_timeout:[0,3],ids_to_fetch:44,ie:[13,50,54],if_exist:[9,10],if_not_exist:[9,10],iff:9,ifnotexistswithcountercolumn:40,ignor:[0,3,8,26,27,29,30,44],ignored_address0:27,ignored_address1:27,imagin:27,immedi:[1,3,34,44],immut:[0,32,48],impact:4,implement:[0,2,3,5,15,18,19,20,21,22,23,24,27,29,32,41,46,49,50,54,55],impli:[30,45],implicit:[0,10,55],implicitli:[3,8,37],importerror:39,impos:37,improv:[0,1,35,49,55],in_memori:53,inbetween:27,includ:[0,3,9,10,25,26,40,45,49,54,55,56],include_keyspac:9,inclus:3,incomplet:0,inconsist:0,incorrect:[0,44],incorrectli:[0,30],increas:[0,27,31,46],increment:6,incur:9,indefinit:0,independ:[32,54],indetermin:3,index:[0,3,6,25,37,38,48,55],indexmetadata:25,indic:[0,1,2,3,6,8,9,10,25,27,38,47,53],individu:3,inet:[0,1,25],inet_address:0,inet_ntop:0,inet_pton:0,infin:0,infinit:[0,27],inflat:29,influenc:27,info:[0,3,33,44],inform:[0,3,5,9,25,27,41,52],inherit:[0,6,9,11,42],init:[0,3,36,40],initi:[0,2,3,5,6,7,9,15,18,27,29,31,32,35,38,39,44,46,47,54],initial_respons:2,initialize_reactor:[19,20,21,22],inititi:40,inject:[3,42,46],inmemorycompactionstrategi:53,inplac:32,input:[0,30,40,41,42],insanc:41,insensit:9,insert:[0,1,3,4,9,10,30,32,36,37,41,44,47,55,56],insert_stat:56,insert_us:30,insid:[13,34,44],insight:0,inspect:[3,8],instal:[0,40,44,45,49,54],instanc:[0,2,3,6,9,10,13,15,18,25,26,27,30,34,38,44,48,50,54,55,56],instanti:[0,27,29,31,44],instead:[0,3,4,30,38,40,44,50,54,55],instruct:38,insuffici:[0,26],intact:42,integ:[0,6,10,11,13,17,31,32,35,36,37,38,41,48],integer_typ:32,integr:[0,29,40,41,45,46,48,55],intend:[9,31,32,46],intent:40,interact:[3,44],interfac:[0,2,27,50],interior:32,intern:[0,3,10,27,31,32,40,41,55],interpol:56,interpret:[0,30,36,38,55],intranod:53,intrins:41,introduc:[0,19,25,30,37,38,40,42,55,56],introduct:45,intruct:54,intstat:26,inupt:0,inv:[15,18],invalid:[0,1,26,30],invalidparametertypeerror:0,invalidrequest:1,invalidtypeparametererror:0,invit:40,invlabel:[15,18],invoc:46,invok:[0,3,40],involv:[30,38],io:[0,3,4,10,33,46,48,54],ip:[0,3,5,27,28,44,54],ipv4address:0,ipv6:0,ipv6address:0,irc:0,iron:40,is_analytics_sourc:[15,18],is_cql_compat:25,is_default_sourc:[15,18],is_graph_sourc:[15,18],is_idempot:[0,15,18,30,44],is_schema_agre:3,is_seri:0,is_shard_awar:53,is_shutdown:0,is_up:0,isbootstrap:27,isn:[0,9,10],isnotnul:38,isoformat:0,isol:27,issu:[0,2,27,31,32,36,55],item1:17,item2:17,item:[0,4,9,10,15,18,27,30,32,37,38,44],iter:[0,3,25,27,29,30,32,38,50,55],its:[0,2,3,5,9,19,20,23,24,27,30,32,37,42,46,54,55],itself:[46,55],jan:0,januari:0,java:27,jit:49,jitter:[0,27],jk:54,joe:[37,54],john:44,join:0,jon:[10,37,38],json:[3,12,15,18],json_data:[15,18],juli:0,jump:48,junctur:40,june:0,just:[0,3,6,25,27,32,34,37,40,44,46,50,53,56],k:[34,47,54],keep:[0,27],keepal:0,kei:[0,1,3,6,8,9,10,13,15,25,26,27,29,30,32,37,38,42,43,44,47,53,54,56],kept:4,kerbero:[0,54],kevin5000:37,kevin:37,key1:17,key2:17,key_typ:6,keyerror:0,keyfil:54,keyout:54,keyspac:[0,1,3,7,8,9,10,11,15,18,25,27,29,30,35,43,53,55],keyspace1:53,keyspace_nam:55,keyspacemetadata:[0,25],keystor:54,keystore_password:54,keyword:[0,3,6,7,9,10],kill:0,kimberli:9,kind:[0,27,55],kinit:54,klass:3,know:[3,27,36,55,56],known:[0,15,18,25,40,55],known_host:26,ks1:35,ks2:35,ks:35,ks_name:8,kwarg:[0,3,4,6,7,9,10,12,15,18,19,20,21,22,23,27,32,34,39,54],label:[15,18],lambda:54,languag:[12,15,18,40,45,49],larg:[0,3,4,10,32,38,45,55],largest:36,last:[0,1,3,27,31,38],last_act:3,last_host:1,last_nam:[9,37],lastest:36,latenc:[26,44,53],later:[0,1,9,27,44,50],latest:[0,55],latter:[3,50],layout:25,lazi:0,lazili:29,lazy_connect:[0,7],lazyprotocolhandl:29,lbp:0,lead:[0,34,49,55],leak:0,learn:[30,54],least:[6,26,27,30,35,37,46],leav:[0,3],left:[0,3,4,9,41,55],legaci:[0,6,40,48,54,55],len:[0,9,10,35],length:[6,27,30],less:[0,46],let:[0,3,55],letter:13,level:[0,1,3,4,10,15,18,27,30,33,41,48,54],leveledcompactionstrategi:9,lib:0,libev4:46,libev:[0,33],libevconnect:[3,23,46],libevreactor:[0,3,33,46],libevwrapp:0,librari:[0,19,20,41,46,54],licens:45,lifecycl:2,lightweight:[0,1,10,30,44,45],lighweight:27,like:[0,1,3,4,9,10,15,18,26,27,30,37,38,41,44,46,50,54,56],limit:[0,3,10,30,38,41,49],line:[0,19,44,46],linear:32,lineariz:30,linestr:32,link:[0,41,46],linux:46,list:[0,1,3,4,6,7,8,9,10,13,15,17,18,25,27,29,30,32,35,43,44,45,46,48,50,55],list_col:44,list_column:10,list_column__append:10,list_column__prepend:10,listen:[0,3],listen_address:0,liter:[0,15,17,18,30,41,44,55,56],live:[1,27,43],ll:[38,54],load:[0,3,9,10,15,18,33,37,38,40,42,53,54,55],load_balancing_polici:[3,27,42,44,52,53],load_cert_chain:54,load_verify_loc:54,loadbalancingpolici:[0,3,27,42],local:[0,1,3,27,30,41,42,43,44,55],local_dc:[0,27,52],local_on:[0,1,3,44],local_queri:42,local_quorum:[0,1,44],local_seri:[1,30,44],localhost:[7,10],localstrategi:25,localtim:41,locat:[3,40,54,56],lock:0,locked_execut:42,log:[0,3,8,27,30,31,44,45,55],log_error:3,log_result:3,logentri:34,logger:0,logic:[0,37,53],logo:45,longer:[0,1,55],look:[13,37,38,54],lookup:[0,25,27],loop:[0,3,4,21,33,44,46,54],lose:0,loss:0,lot:[0,53],low:[15,18,27,33],lower:[1,4,27,32,38,44],lower_bound:32,lowercas:0,lwt:[0,3,9,47],lwtexcept:[0,9,10,40],lz4:[0,46],m:[9,36],mac:[0,46],machin:44,madd:46,made:[1,3,5,27,38,44,55],mai:[0,2,3,4,6,7,27,30,32,37,38,43,44,46,49,54,55],main:[0,3,54,56],maintain:[0,3,30,32,37,55],major:[0,27,42,54,55],make:[0,1,3,10,25,27,37,40,41,42,43,44,45,46,48,51,54,55],make_query_plan:27,make_token_replica_map:0,manag:[0,3,6,9,10,11,28,33,34,37,42,46,48,55],mandatori:[0,3],mani:[0,1,3,4,27,44,49,50,54,55],manifest:[0,43,47],manipul:[0,3],manner:32,manual:[3,9,34],manufactur:[10,35,38],map:[0,1,3,8,10,13,15,17,18,25,29,30,32,33,37,38,44,48,55],map_column:10,map_column__remov:10,map_column__upd:10,mapper:[0,7,40,45],march:0,margin:4,mark:[0,3,5,33,44,45],marker:41,master:[0,3,53],match:[0,3,5,9,10,15,18,25,30,38,40,42,43,44,46,54,55,56],materi:[0,3,4,25,29,46,55],materializedviewmetadata:25,math:0,max:[0,3,5,26,44],max_attempt:[27,44],max_connect:3,max_delai:27,max_length:6,max_request:3,max_schema_agreement_wait:3,max_support:1,max_threshold:9,max_tim:38,max_uuid_from_tim:32,max_wait:[3,30],max_wait_sec:3,max_wait_sec_p:3,maximum:[1,3,6,27,32,38],maxtimeuuid:38,maxyear:[32,41],md5token:25,md:53,mean:[3,9,26,27,38,44],meaningless:38,meant:41,measur:[3,27],mechan:[0,2,3,27,54],median:26,meet:[26,27,54],member:[32,37],memori:[0,4,38,53,55],mention:[0,41,44],merg:40,mesh:55,messag:[0,1,2,3,5,29],message_types_by_opcod:29,meta:[0,3,37],metadata:[0,3,15,18,27,30,33,42,43,52,53],method:[0,2,3,9,10,27,29,30,35,36,37,38,41,43,44,46,49,53],metri:26,metric:[0,3,33],metrics_en:3,micro:32,microsecond:[0,31,55],middl:13,might:[0,3,30,50,54],migrat:[48,55],millisecond:[0,17,32,41],millsecond:41,min:[0,26,43],min_length:[0,6],min_request:3,min_support:1,min_threshold:9,min_tim:38,min_uuid_from_tim:32,minim:[3,40,41,44],minimalist:32,minimum:[1,3,6,32,38],mintimeuuid:38,minut:[0,32,46],minyear:[32,41],mismatch:0,misplac:0,miss:[0,27],misspel:13,mistak:40,mitig:49,mix:[0,30],mke:0,mm:[17,32],mmmuuunnn:32,mno:46,mock:0,mode:0,model:[0,3,8,33,38,43,48,55],model__lik:38,modelexcept:40,modelqueryset:10,modern:0,modif:8,modifi:[0,1,8,9,10,32],modul:[0,9,11,18,19,20,40,46,49],monkei:[0,21,22,54],monkey_patch_loop:0,monoton:0,monotonictimestampgener:31,month:32,montonictimestampgener:0,more:[0,3,4,6,9,10,15,25,27,29,31,38,40,42,44,45,49,50,54,55],most:[3,27,30,37,40,41,43,50],mostli:[18,47],move:[0,3,30,55],ms:32,ms_timestamp_from_datetim:32,msg:29,much:[37,41,54,55],multipl:[0,3,10,12,14,15,18,27,34,35,44,48,49,55],multipleobjectsreturn:[0,10],multipli:13,multiprocess:0,multithread:0,murmur3:[0,3,46],murmur3partition:[0,25,46],murmur3token:[0,25],mussei:[46,54],must:[0,1,3,4,10,30,32,37,38,44,46,54,55,56],mutabl:[0,3],mutat:48,mutual:[7,32],mv:27,my:54,my_callback:34,my_graph:12,my_tabl:44,my_user_id:30,mycf:3,mykeyspac:[3,30,44,55,56],mymod:36,mymodel:36,mystery_funct:34,mystorepass:54,mytabl:4,n:10,naiv:[6,41],name:[0,1,3,7,8,9,10,11,12,13,15,18,25,26,27,29,30,34,37,40,44,47,56],named_arg:34,named_tuple_factori:[0,3,16,30,55],namedt:38,namedtupl:[0,3,4,30,37,44,47,55,56],namedtuple_factori:0,nan:[0,32],nanosecond:[6,32,41],nativ:[0,1,15,18,29,37,45],native_shard_aware_transport_port:53,native_shard_aware_transport_port_ssl:53,native_transport_address:0,natur:2,necessari:[3,44,46,54],need:[0,1,3,6,12,27,30,32,34,35,36,37,38,39,44,46,49,53,54,55,56],neg:[0,32,38],negoti:2,nest:[0,32],net:27,network:[0,30,44],networktopologystrategi:[0,8,25],never:[0,27,34,47,49,55],neverretrypolici:3,new_authent:2,new_nod:0,new_plan:27,new_schedul:27,newkei:54,newli:[0,25,27],next:[0,3,21,27,42,48,50,54],next_pag:38,ngdg:0,nice:0,nicer:38,no_compact:0,no_valid_replica:25,noconnectionsavail:28,node1:42,node1_profil:42,node1_whitelist:42,node2:42,node2_profil:42,node:[0,1,3,5,25,26,28,30,32,33,44,53,54],node_domain:5,nodesync:0,nodetool:27,nohostavail:[0,3],nomenclatur:55,non:[0,3,6,10,32,33,37,44,45],nonblock:0,none:[0,1,2,3,4,5,6,7,8,9,10,11,12,14,15,17,18,25,26,27,30,32,36,38,39,41,43,44,47,50],nonetyp:0,nonexist:[0,1],normal:[0,3,9,10,12,27,30,32,41,44,50],nose:0,notabl:55,note:[0,3,4,7,8,9,10,19,27,30,32,35,37,38,40,41,42,44,45,50,54,55],noth:[0,25,27],notic:0,notif:0,notifi:3,nov:0,novemb:0,now:[0,31,34,36,38,40,41,44,48],nt:0,nullhandl:0,num:26,number:[0,1,3,4,5,9,10,26,27,40,42,44,46,47,50],numer:[0,41],numpi:29,numpyprotocolhand:29,numpyprotocolhandl:[0,29],o:[44,54],obj:[15,18],object:[0,3,4,12,15,17,18,25,26,27,30,31,32,34,35,36,37,41,42,43,44,45,49,50,55,56],obtain:[3,10,43,49],occur:[1,27,30,34,44,55],oct:0,octob:0,od:32,off:3,offer:[32,46,49,50],offici:[54,55],offset:32,often:37,ok:[27,54],old:[0,10,40],omit:[1,30],on_add:27,on_authentication_success:2,on_down:27,on_read_timeout:27,on_remov:27,on_request_error:[0,27],on_unavail:27,on_up:[0,27],on_write_timeout:[0,27],onc:[3,4,19,20,21,22,27,29,30,34,36,38,46,50,53],one:[0,1,2,3,6,10,13,26,27,30,32,35,36,37,38,42,44,53,54,55],ones:[10,40],onli:[0,1,3,4,5,6,7,8,9,10,18,19,27,30,31,34,37,38,40,41,44,45,46,47,53,54,55],onward:53,op:38,opaqu:3,opcod:29,open:[0,2,3,26,27,28,32,45],open_connect:26,openssl:54,oper:[0,1,3,5,8,9,10,15,18,30,32,33,35,44,47,55],operationtimedout:[0,1,3],opertaion:0,oppos:27,optim:[0,45,46,49],option:[0,1,2,3,5,7,9,10,11,12,14,25,29,30,33,38,40,42,44,47,48,49,53,54,55,56],option_map:25,options__contain:38,options_map:25,order:[0,1,4,6,10,25,27,30,32,34,37,41,55],order_bi:[10,38],ordered_dict_factori:[0,3,16,30,55],ordereddict:[0,3,30,32,44],orderedmap:[0,32],orderedmapserializedkei:32,orderedset:0,org:38,organ:45,origin:[0,3,38,55],os:46,oss:[0,27],other:[2,3,6,8,9,15,18,26,27,30,32,38,44,45,46,53,54,55,56],other_error:26,otherstuff:56,otherwis:[2,3,6,9,27,32,54],ou:54,our:[38,44,48,54],out:[0,1,4,9,27,32,34,36,38,40,41,44,54],outcom:47,output:[0,41],output_password:54,outsid:[0,6,27,32],outv:[15,18],outvlabel:[15,18],over:[3,27,29,38,49,50,54,55],overcount:27,overflow:[0,41],overflowerror:[0,32],overhaul:55,overhead:[0,4,34],overload:[0,1,6,26,27],overrid:[0,3,9,15,18,42,44,55],overridden:[0,3,50],overriden:0,overs:3,overview:[40,41,45,48],overwrit:10,own:[3,9,37,54],owner:37,owner_id:[37,40],pack:[0,30],packag:[0,2,32,41,46,48,54,55],page:[0,1,3,45,51],pagedresult:[0,50,55],pagedresulthandl:50,pagin:[0,38,50],paging_st:[3,50],pair:[0,29],panda:29,parallel:0,param:[0,4,13],paramet:[0,3,4,6,7,8,9,10,12,14,15,18,27,29,30,31,32,37,40,47,52,54,56],parameter:56,parent:[0,20],pars:[0,15,18,29,32,43,44],parser:[0,29],part:[0,8,10,30,35,40,41,46],parti:[2,3,41,48],partial:[0,21,22,30],particular:[0,3,25,27,30,53],particularli:38,partit:[0,6,10,25,27,30,38],partition:0,partition_kei:[6,10,30,38],pass:[0,2,3,4,6,7,9,10,25,29,30,34,36,37,38,39,47,48,53,54,55,56],passin:54,password:[2,54],passwordauthent:[2,54],patch:[0,21,22,41,54],path:[0,15,18,29,46,54],path_to_bundle_yaml:52,pattern:[37,49],paxo:30,payload:[0,1,3,30,33],peer:[0,5,25],peers_v2:0,pem:54,pend:0,pending_us:30,pep:0,per:[0,3,4,6,9,10,25,27,35,37,43,44,50,53,55],percentil:26,perform:[0,1,3,9,10,27,30,33,37,38,45,46,51],perhap:46,period:39,permiss:54,permit:27,persist:[0,15,18,27,41],person:[9,37,38],person_id:37,perspect:[2,27],pertain:3,pertin:47,pet:[37,40],pet_id:[37,40],pet_typ:[37,40],phase:[2,3,30,46],photo_id:[10,37],phrase:13,pick:[36,44],pip:[0,55],pk:[38,44],pk__token:[0,38],pk__token__gt:[0,38],place:[0,40,44,55],placehold:[3,15,18,30,44,56],placement:[0,8],plai:0,plain:54,plaintextauthent:2,plaintextauthprovid:[0,2,3,54,55],plan:[0,8,27,45],platform:[0,42],pleas:[0,3,6,9,11,27,37,43,45,54],plu:[38,47],plug:39,pluggabl:0,pmfstat:26,point:[0,3,6,26,27,32,41,44,54,55],polic:27,polici:[0,3,33,42,43,44,52,53,55],poll:[3,30,43],polygon:32,polymorphic_kei:40,pool:[0,1,3,33,55],pool_wait_timeout:3,popul:[0,3,27,30,38],port:[0,3,5,25,44,53],portion:[30,32],posit:[3,10,30,34,38,44,47,55],possibl:[0,3,9,21,27,31,32,37,38,41,46,50,54,55],post:[0,49],postfork:[39,43],potenti:0,pr:0,practic:44,practiv:10,pre:[0,46],preced:[3,27,34,47],precis:[0,6,17,32,40,41,55],predic:[0,27,33],predict:38,preemptiv:44,preexist:7,prefer:[0,27,41,44,46,55],prefix:[9,11,13],prematur:0,prepar:[0,3,4,27,33,41,43,54,56],prepare_on_all_host:3,prepared_stat:30,preparedstat:[0,3,30,44],preparedstatementtest:0,preparemessag:0,prepend:[10,47,55],present:[0,7,10,30,41,42,43,46,47,55],preserv:[0,6,9,30,40],presist:37,pretti:49,preval:41,prevent:[0,10,40,44,46],previou:[0,3,54,55],previous:[0,40,42,55],previous_vers:1,price:[10,38],primari:[0,3,6,8,9,10,25,30,37,38,47,53,56],primary_host:27,primary_kei:[6,9,10,25,35,36,37,38,40,48],princip:[0,54],print:[3,9,10,12,30,32,35,37,41,42,43,44,46,48,52,53,56],prior:0,privat:[0,1,27],probabl:[27,38,54],problem:[0,3,26,43],process:[0,3,4,20,43,44,46,49,53,54,55],process_row:50,process_us:[3,4,44,50],produc:[2,4,15,18,38],product:[8,48,54,55],profil:[0,3,4,12,14,45,52],profile_long:44,program:52,programmat:3,project:[1,40,45,48,49],prompt:[46,54],proof:0,propag:[0,27,30],proper:[0,39,46],properli:[0,3,37,38,44],properti:[0,1,3,5,9,13,15,18,25,27,28,30,32,37],protect:0,protocol:[0,1,3,5,6,12,14,30,33,37,45,53],protocol_tl:[0,54],protocol_vers:[0,1,3,4,29,30,32,37,48,50,54,55,56],protocolerror:5,protocolhandl:[0,29],protocolvers:1,provid:[0,3,12,13,15,18,27,41,42,43,46,49,50,52,54,55],proxi:5,proxim:13,proxy_address:5,prudent:40,ps:50,ptyhon:0,publish:[0,46,54],pure:[0,2,27,29,46,54],purpos:[3,6],push:[0,46],py:[0,46],pyopenssl:[0,54],pypi:[0,46],python2:32,python3:0,python:[0,15,17,18,19,20,29,30,32,37,40,41,44,47,48,49,51,52,54,55,56],pyton:0,pytthon:0,pytz:41,q2:48,q:[35,38,48],qop:[2,54],quadrat:0,quantiz:6,queri:[0,1,3,4,6,9,12,15,16,18,25,27,29,32,33,35,37,40,41,42,45,46,48,49,56],query_cl:[3,30],query_from_travers:12,query_str:[15,18,30],queryexhaust:3,queryhandl:[3,29],queryoper:0,queryset:[0,9],querytrac:[0,30,43],question:[45,48],queu:34,quickli:[0,49],quorum:[1,10,27,30,44],quot:[0,17,41],race:0,rack:[0,28,52],radiu:32,rais:[0,1,2,3,4,5,6,9,10,15,18,27,30,32,34,37,38,40,44,50,55],raise_on_first_error:4,random:[0,27,32,38],randompartition:25,rang:[0,4,10,32,38,41,43],range_request_timeout_in_m:1,rare:0,rather:[0,32,46],raw:6,re:[0,27,30,37,38,39,44,46,54,56],reach:34,reachabl:27,reactor:[0,20,24,43],read:[0,1,6,15,18,26,27,30,32,34,36,43,54],read_inet:0,read_repair:0,read_repair_ch:0,read_request_timeout_in_m:1,read_timeout:26,readabl:25,reader:[12,15,18],readfailur:1,readm:0,readtimeout:[1,44],reason:[1,3,27,41,54],rebuild:[0,3],rebuilt:0,receiv:[0,1,3,27,44],received_respons:[1,27],recent:0,recogn:[15,18],recommend:[0,3,4,27,36,44,49,54,55,56],reconnect:[0,33],reconnection_polici:3,reconnectionpolici:[0,27],reconnector:0,record:[0,6,10,27,38],recreat:[0,25],recurs:0,redhat:46,reduc:[0,3,49,53],redund:40,reevalu:0,ref:0,refactor:[0,41],refer:[0,10,34,40,42,47,55],referenc:3,refresh:[0,3],refresh_:55,refresh_keyspace_metadata:3,refresh_nod:[0,3],refresh_schema:[0,55],refresh_schema_metadata:3,refresh_table_metadata:[3,53],refresh_user_aggregate_metadata:3,refresh_user_function_metadata:3,refresh_user_type_metadata:3,regard:[3,27,32],regardless:[26,27,46,47],regex:13,regist:[0,3,7,12,17,26,34,37,45,55],register_connect:[0,7,35],register_listen:[0,3],register_user_typ:[3,55,56],registr:35,registri:7,regress:0,regular:[13,30,36,38],reilli:44,reinstal:46,reject:47,rel:41,relat:[0,30,38,42],relax:7,releas:[0,9,27,40,42,54,55],release_vers:[43,44],reli:[27,38],reloc:40,remain:[3,20,27,40,42],rememb:44,remot:[0,3,27,53],remoteconnect:12,remov:[0,3,6,8,10,27,30,32,42,47],remove_request_init_listen:3,repair:27,repeat:[27,44],replac:[0,3,6,29,40,54,55],replai:[1,27],replic:[0,3,8,25,40,53],replica:[0,1,8,25,26,27,30,44],replication_factor:[8,25,53],replication_factor_info:25,replicationfactor:25,replicationstrategi:25,report:[0,27],reprepar:0,reprepare_on_up:3,repres:[1,3,5,6,9,15,18,25,26,28,30,31,32,37,38,40,41,55],represent:[0,25,30,32,55],reproduc:0,req:54,req_distinguished_nam:54,request:[0,1,3,4,26,27,38,39,42,44,45,47,49,54,55],request_id:0,request_tim:[0,26],request_timeout:[3,42,44],requestexecutionexcept:1,requestvalidationexcept:1,requir:[0,1,2,3,6,7,19,27,29,30,32,37,38,39,40,44,46,48,54,55],require_client_auth:54,required_replica:[1,27],required_respons:[1,27],reserv:0,reset:27,resolut:[0,32],resolv:[0,3,5,27,36,54],resort:27,resourc:[19,20,21,22,46,54],respect:[0,3,38],respond:[1,2,27,44],respons:[0,1,2,3,27,29,38,44],response_futur:3,responsefutur:[0,3,29,43,44,49,50,55],rest:[27,44],restart:[0,44],resulset:0,result:[0,3,4,9,10,12,15,18,25,26,27,29,30,32,37,38,41,43,44,45,53,56],result_cach:0,result_metadata:29,result_or_exc:4,result_set:3,results_gener:4,results_metadata:0,resultset:[0,3,50,55],resync:9,retain:[0,41],rethrow:27,rethrown:0,retri:[0,7,26,30,33,44],retriev:[1,3,10,30],retry_connect:7,retry_next_host:27,retry_num:27,retry_polici:[0,3,15,18,27,30,42,43,44],retrypolici:[0,3,26,27,30,43],retun:47,reus:[3,14,30],revers:[10,27],review:0,rework:55,rf:[0,1],rhel:46,rich:3,right:[27,30,44],ring:[0,3,27,32,33],risen:54,risk:27,rlac:0,robin:27,robust:[0,41],role:54,root:54,root_ca_base_nam:54,root_cert_pass:54,rootca:54,rotat:27,round:[0,27,32],roundrobinpolici:[27,53],roundtrip:30,rout:[0,3,9,27,43,46],routing_kei:[15,18,27,30,43],row:[0,3,4,5,10,12,29,33,34,37,38,41,42,43,44,47,48,50,55,56],row_factori:[0,3,7,29,30,42,44],row_id:10,row_list:55,rpc:[5,28],rpc_addr:0,rpc_address:[0,42],rsa:54,rule:30,run:[0,9,10,21,27,34,37,39,44,46,48],run_in_executor:0,runtim:[0,46,49],runtimeerror:0,s:[0,1,2,3,6,7,9,10,11,24,27,29,30,32,34,35,36,37,38,39,41,44,45,46,48,52,53,54,55,56],safe:[0,4],safeti:0,same:[0,3,4,6,7,12,15,18,25,27,30,32,34,35,36,37,38,42,43,44,46,54,55],sasi:38,sasl:[0,2,54],sasl_kwarg:[2,54],saslauthent:[0,2],saslauthprovid:[0,2,54],saslclient:0,satisfi:1,save:[0,9,10,34,35,37,38,41,44,50],scale:[0,26,41,46,49,55],scan:43,scenario:[0,36],schedul:[0,34],schema:[0,3,9,30,33,37,44,55],schema_event_refresh_window:3,schema_metadata_en:3,schema_trigg:0,schemapars:0,scope:[0,3,10],scratch:42,script:[0,40,46,49],scylla:[38,40,46,51,55],scylla_cloud:52,scylladb:[45,53],search:13,second:[0,3,10,26,27,30,31,32,38,41,44],secondari:[0,25,34,38],section:[0,38,40,45,47,49,54,55],secur:[0,45,55],see:[0,1,3,4,6,9,10,11,13,15,18,27,29,30,32,37,38,41,42,43,44,46,47,48,49,50,53,54,55],seen:[0,3,27],segment:40,select:[0,3,4,9,10,30,38,42,43,44,46,50,53,54,55,56],select_stat:4,self:[3,15,18,37,50,55,56],semant:[0,3],send:[0,1,2,3,5,27,44,45,55],sensibl:9,sensit:[0,9],sent:[0,1,2,3,29,44],sep:0,separ:[3,54],septemb:0,seq:43,sequenc:[0,3,4,14,17,27,30,32,44],sequenti:0,serd:0,serial:[0,1,3,12,15,18,30,41],serial_consistency_level:[3,15,18,30,42,44,47,55],serializ:3,serv:40,server:[0,1,2,3,9,15,18,25,29,30,33,38,44,47,48,55],server_authenticator_class:2,server_hostnam:54,server_nam:5,server_vers:43,servererror:27,serverless:45,servic:[2,54],service_timeout:21,session:[0,1,4,7,10,12,14,15,18,25,27,29,30,33,35,39,42,43,46,47,48,49,50,52,53,54,56],sesssion:0,set:[0,1,2,3,4,6,7,8,9,10,11,12,13,15,17,18,19,20,21,22,25,26,27,30,32,35,37,38,42,43,45,46,48,50,52,53,54,55],set_column:10,set_column__add:10,set_column__remov:10,set_core_connections_per_host:[3,4],set_default_connect:[7,35],set_keyspac:[0,3,27,44,56],set_max_connections_per_host:3,set_max_requests_per_connect:3,set_meta_refresh_en:3,set_min_requests_per_connect:3,set_sess:[0,7],set_source_analyt:[15,18],set_source_default:[15,18],set_source_graph:[15,18],set_stats_nam:26,set_verifi:54,setenv:46,setup:[0,7,10,35,37,38,39,40,44,46,48,54],setuptool:[0,46],sever:[0,38,40,44,46,49],shallow:[3,42],shard_aware_opt:53,shard_aware_stat:53,shards_count:53,share:[0,3,19,20,21,22,42,49],shed:[15,18],shell:46,shift:41,shortcut:[3,46],should:[0,2,3,4,6,7,8,9,10,15,18,19,20,21,22,25,27,30,31,37,40,42,44,46,49,53,54,55],should_log:3,shouldn:0,show:[0,8,32,36,38,40,42,47,54],shown:[3,35,37,56],shuffl:38,shuffle_replica:27,shutdown:[0,3,39,52],side:[0,1,2,3,15,18,27,40],sign:[6,54],signal:39,signatur:[1,3],significantli:[38,53],silent:27,similar:[27,29,34,52,54],simpl:[0,6,15,18,27,30,38,40,41,44,46,49],simpleconvictionpolici:[3,27],simplegraphstat:[15,18],simpler:55,simplest:[38,44],simplestat:[0,3,15,18,30,44,50],simplestrategi:[8,25,53],simpli:[0,9,17,27,34,37,40,44,46,56],simplifi:[15,18],simulacron:0,simultan:42,sinc:[0,9,29,31,32,36,38,41,43,55,56],singl:[0,3,4,6,8,9,10,14,25,27,28,30,32,37,38,40,42,44,46,47,55],single_object_row_factori:[15,18],site:[0,41],situat:[27,34,37],six:[0,46,55],size:[0,3,10,55],sizeti:0,sizetieredcompactionstrategi:9,skip:[0,9],slack:0,sleep:[27,37],slice:[0,3,38],slightli:0,slow:0,smaller:27,smallint:[0,6,15,18,44],smoke:0,snappi:46,snapshot:0,sni:5,sniendpoint:5,sniendpointfactori:5,so:[0,1,3,10,21,25,27,30,37,38,41,42,44,47,48,49,50,54,55],socket:[0,5,54],socket_famili:5,sockopt:3,soft:0,softwar:45,some:[0,1,9,15,18,27,34,37,38,41,44,45,46,47,48,50,54,55,56],some_id2:34,some_id:34,someth:[2,27,37,38,46,54],sometim:[0,10,15,18,27,46,50],somewher:[34,50],sort:[0,4,6,32,38],sortedset:[0,32,55],sourc:[0,3,15,18,45,46],source_elaps:[0,43],span:46,spark:[0,3],spcifi:1,spec:41,special:[0,6,29,37,38,40,43],specif:[0,2,5,13,15,17,18,25,27,40,45,46,55,56],specifi:[0,1,3,6,8,9,10,11,12,27,29,30,32,35,37,38,40,41,42,44,54,55],specul:[0,27],speculative_execution_polici:[3,44],speculativeexecutionpolici:[27,44],speed:3,speedup:38,spell:41,spin:0,split:2,squar:47,ss:32,ssl:[0,5,44],ssl_context:[0,3,44,54],ssl_error_want_read:0,ssl_error_want_writ:0,ssl_opt:54,ssl_option:[0,3,5,54],ssl_version:54,sslcontext:[0,54],sstabl:43,sstable_size_in_mb:9,st:[3,37,56],stabil:0,stabl:0,stale:27,stall:0,standard1:53,standard:[0,19,20,26,38,39,41,44,46,52,54,55],start:[0,3,34,38,41,45,50,55],start_fetching_next_pag:[3,50],start_tim:3,startup:0,stat:[0,26,53],state:[0,3,10,20,27,34,45,47],stateless:50,statement:[0,3,25,27,33,34,36,41,42,43,47,50,56],statements_and_param:4,statements_and_paramet:4,stats_nam:26,statu:[47,53],status_event_refresh_window:3,stddev:26,stdlib:0,step:[37,45],steroid:38,steve:10,still:[0,15,18,30,34,37,40,42,44,55,56],stmt:0,stop:[4,34],store:[0,1,6,9,30,37,41,52],str:[7,8,10,17,32,44],straightforward:[37,40,41,55],strategi:[0,40,55],stream:[0,29],stream_id:29,street:[3,11,37,55,56],stress:0,strict:[6,49],strictli:0,string:[0,1,2,3,6,12,13,15,17,18,25,26,27,29,30,32,41,44,54],string_typ:32,strip:0,strong:0,structur:[15,18,25,37],studio:46,stuff:[3,56],style:3,sub:[37,40],subclass:[0,1,2,3,27,30,37,54],submit:[0,43],submit_schema_refresh:55,submodul:[40,55],suboptim:27,subsequ:40,subset:38,substanc:39,substanti:[4,55],succe:[3,27],succeed:0,success:[0,1,2,3,4,10,27,30,44,46],successfulli:[0,53],sudo:46,suffici:27,suggest:[44,46],suit:[0,54],suitabl:[2,17,25,36],superset:25,suppli:[0,3,30,44,54,55],support:[0,1,2,3,8,9,10,12,27,32,34,36,38,41,44,45,50,53,54,55,56],supported_vers:1,suppos:[0,37,54],sure:[0,3,27,37,43,44,46,49,51,54],surfac:0,surround:0,swap:55,sy:0,sync:[9,35,37],sync_schema:0,sync_tabl:[0,8,10,35,37,48],sync_typ:[8,11,37],synch:8,synchron:[0,3,4,8,37,49,50],syntax:[0,10,34,38],syntaxexcept:0,system:[0,5,25,38,42,43,44,46,55],t:[0,9,10,15,31,37,38,43,44,47,49,54,55,56],tab:52,tabl:[0,1,3,6,8,25,30,32,33,37,44,47,48,55,56],tablemetadata:[0,25,53,55],tablemetadatadse68:25,tablemetadatav3:25,tag:[0,15,18],take:[0,3,4,8,9,15,18,25,27,35,44,46,54],taken:[15,18,40],tarbal:46,target:[0,3,13,15,18,27,46],task:[0,3,34,39],tcp:0,tear_up_couch:37,technic:40,techniqu:44,tell:56,tenant:41,term:27,tesla2012:38,tesla:[35,38],test2:10,test4:10,test:[0,10,21,22,27,31,35,46,47],test_clone_shared_lbp:0,test_clust:0,test_connect:0,test_fail_if_different_query_id_on_reprepar:0,test_set_keyspace_twic:0,test_single_interfac:0,testifexistsmodel:9,testifnotexistsmodel:9,testmodel:38,testtransactionmodel:9,text:[0,3,6,9,10,11,13,35,36,37,38,40,44,48,55,56],than:[0,1,3,6,10,27,30,31,32,38,42,44,46,49,50,54],thei:[0,1,3,4,6,8,9,10,15,18,27,29,32,34,36,37,38,40,41,55,56],them:[0,3,27,38,40,41,44,46,47,48,55],themselv:[15,18],therefor:[36,38,46],thi:[0,1,2,3,4,5,6,7,8,9,10,11,12,13,15,17,18,19,20,21,22,25,26,27,28,29,30,31,32,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,53,54,55,56],thing:[3,27,38,40,44],third:[2,41,48],thorough:[46,54],those:[0,3,26,27,30,42,46],though:55,thread:[0,3,4,44,46,49],threadpoolexecutor:0,three:[1,27,30,32,44,47],threshold:[0,3],thrift:0,throttl:0,through:[0,2,3,5,7,9,10,15,18,26,27,30,38,44,45,47,49,55,56],throughput:[0,4,49],thrown:34,thu:[10,27,30,47],ticket:54,time:[0,1,2,3,4,6,10,26,27,31,32,37,38,40,44,45,46,55],time__gt:38,time__lt:38,time_arg:32,timedata:9,timedelta:10,timedelta_or_datetim:9,timeout:[0,1,3,9,10,21,26,27,55],timer:[0,21,26],timestamp:[0,1,6,9,10,17,32,33,36,40,44,45],timestamp_gener:3,timestamp_na:41,timestamp_pres:41,timestamp_utc:41,timestamptyp:0,timeuuid:[0,6,10,32,37,44,55],timezon:[0,6,32,41],tinkerpop:[12,46],tinyint:[0,6,44],tip:45,tlsv1_2_method:54,tmp:42,to_bigint:[15,18],to_doubl:[15,18],to_float:[15,18],to_int:[15,18],to_python:0,to_smallint:[15,18],todo:32,token:[0,2,3,13,15,27,33,43,46,53],token_fuzzi:13,token_map:0,token_metadata_en:3,token_prefix:13,token_regex:13,token_str:25,tokenawar:0,tokenawarepolici:[0,3,27,42,52,53],tokenawarerout:9,tokenfun:38,tokenmap:[0,25],toler:0,tolist:12,tombston:[3,36,43],tombstone_compaction_interv:9,tombstone_threshold:9,too:[0,3,27,41],took:1,tool:46,toolkit:29,top:[15,18,27],topo:0,topolog:[0,3,27,33],topology_event_refresh_window:3,total:[3,27],trace:[0,3,33],traceev:30,traceunavail:[3,30],tracing_en:0,track:0,trade:4,trademark:45,traffic:[0,44],trail:0,transact:[0,1,3,12,14,27,30,45],transform:37,transient_replica:25,transit:0,translat:[33,40,44],transpar:[3,44,50],trap:34,trash:0,travers:[0,12,14,15,18,46],traversal_batch:14,traversal_class:12,traversal_sourc:12,traversalbatch:[12,14],traversalmetr:0,travisci:0,treat:[3,27,30,44,50],tree:3,tri:0,trigger:[0,3,27],truncat:[6,30,32,40],truncate_microsecond:6,truststor:54,truststore_password:54,truthi:27,ts:41,ttl:[0,9,10],ttl_in_sec:9,tunabl:49,tune:0,tupl:[0,1,3,4,9,12,17,25,27,30,38,44,55,56],tuple_factori:[0,3,16,29,30,42,44,55],turn:[3,43],twice:0,twist:[0,33,44],twistedconnect:[24,54],twistedreactor:[33,54],two:[0,1,3,13,27,29,32,38,44,46,54],txt:[0,46],type0:1,type1:1,type:[0,1,3,8,10,15,17,18,25,27,29,30,32,33,34,38,41,45,47],type_model:8,typeerror:[0,15,18],typestr:0,typic:[3,10,27,29,30,31,34,38,42,44],typo:0,tzinfo:41,u:[10,30,37,38,47],ubuntu:[0,46],uda:0,udf:0,udt:[0,3,12,18,37,45],un:[0,30],unabl:[0,27,46],unauthor:[0,1],unavail:[0,1,26,27],uncal:0,unchang:40,unclean:55,uncompar:0,uncomplet:30,uncondit:0,undefinedkeyspaceexcept:40,under:[0,25,27,37,45],underscor:0,understand:54,understood:[3,27],underutil:0,unexpect:27,unexpectedli:0,unfamiliar:38,unhexlifi:0,unicod:[0,17,44],unicodedecodeerror:0,unif:0,unifi:[0,55],unintend:0,union:3,uniqu:[1,6,25,37,42],unit:[0,13,27,45],unittest2:0,unittest:0,unix:[0,5,31,32,41],unix_socket_path:5,unix_time_from_uuid1:32,unixsocketendpoint:5,unknown:[0,15,18,46,55],unless:[3,6,27,35,55],unlik:41,unlog:30,unlogged_batch:27,unord:[6,25],unorder:0,unpack:[0,15,18,44],unprepar:56,unrecogn:0,unrecover:5,unreferenc:0,unregist:[0,56],unregister_connect:[7,35],unregister_listen:3,unset:0,unset_valu:30,unspecifi:[0,9],unsupport:0,unsupportedoper:3,until:[0,2,3,4,7,37,43,44],untrust:3,unus:[0,46],unwis:10,up:[0,3,8,13,19,20,21,22,32,33,34,37,38,52,54,55],updat:[0,1,3,8,9,10,30,32,34,38,40,42,44,45,47],update_view_metadata:0,updatestat:0,upfront:29,upgrad:[45,48,54],upon:[3,37],upper:32,upper_bound:32,uppercas:0,us:[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,35,36,37,38,40,41,43,44,45,46,47,49,50,51,52,53,54],usag:[0,2,3,4,9,25,27,30,55],use_certificate_fil:54,use_client_timestamp:[0,1,3,55],use_default_tempdir:0,use_list_t:6,use_privatekey_fil:54,use_set_t:6,used_hosts_per_remote_dc:27,usemap:6,user1:[44,54],user2:44,user3:44,user3_lookup:44,user:[0,1,3,4,6,8,9,10,17,18,25,30,33,38,40,44,45,46,50,54],user_act:3,user_id1:44,user_id2:44,user_id3:44,user_id:[4,9,30,38,44],user_ids_to_queri:44,user_lookup_stmt:44,user_row:[3,44,50],user_typ:[3,6],user_type_map:29,user_tz:41,useraggregatedescriptor:[1,3],userdefinedtyp:[0,6,37],userfunctiondescriptor:[1,3],usernam:[2,44,54],users_to_insert:30,usertyp:[0,6,25,33,37],usertypedoesnotexist:3,usual:[10,21,41,54],utc:[32,41],utc_datetime_from_ms_timestamp:32,utcfromtim:0,utcnow:[6,41],utctimetupl:41,utf8:0,utf8typ:0,utf:[0,6,17],util:[0,1,12,21,22,33,40,41,44,52,54,55],uuid1:[10,44],uuid4:[10,48],uuid:[0,6,9,10,32,37,38,40,44,48],uuid_arg:32,uuid_from_tim:[32,40],uwsgi:[43,48],uwsgidecor:[39,43],v1:[0,1,32],v2:[0,1,45],v3:[0,1,37,45],v4:[0,1,6,30],v5:[0,1],v6:1,v:[10,12,34,47,53],val1:17,val2:17,val:15,valid:[0,1,3,6,9,10,15,18,25,27,32,47,54],validationerror:[10,37,40],valu:[0,2,3,4,6,9,10,11,13,15,17,18,25,27,29,30,31,32,34,37,40,41,44,47,53,54,55,56],value2:32,value_typ:6,valueerror:[0,32],valuemap:12,values_list:[0,38],valuesequ:30,varchar:44,variabl:[0,6,9,44,46,54],variant:55,varint:[0,6,44],variou:[26,54],various:40,ve:[9,35,37,38],verb:40,verbatim:[15,18],veri:[52,54],verif:0,verifi:0,verify_mod:54,verify_p:54,version:[0,1,2,3,6,25,29,30,31,32,37,40,44,45,46,50,55,56],vertex:[15,18,25],vertexmetadata:25,vertexproperti:[15,18],via:[0,3,37,46,50,52,54],view:[0,25,27,43],violat:10,virtual:[0,38],visit:45,visual:46,vnode:3,vs:[0,27],wa:[0,1,2,3,4,5,7,25,26,27,30,36,40,46,47,55],wai:[0,3,6,15,18,27,30,36,38,41,42,44,45,46,54,55],wait:[0,1,3,21,27,30,43,44,50],wait_for_all_pool:3,wait_for_complet:30,wake:21,want:[0,3,6,9,27,34,35,37,38,44,50,54,56],warn:[0,1,3,31,40,55],warn_on_drift:31,warning_interv:31,warning_threshold:31,was_appli:[0,3],watcher:21,we:[0,7,27,36,38,39,41,42,44,48,54,56],weakref:0,web_sess:50,well:[0,27,35,44,54],were:[0,1,3,4,19,25,27,30,36,37,40],what:[27,30,37,41,54,55,56],wheel:[0,46],when:[0,1,2,3,4,5,7,9,10,17,21,27,28,29,30,31,32,35,36,37,38,40,41,42,44,46,47,50,54,55,56],whenev:[3,50],where:[0,3,4,10,25,27,30,32,37,43,44,46,47,55],whether:[1,3,6,25,26,27,47,53],which:[0,1,3,9,10,25,27,29,30,34,35,36,38,40,44,46,49,54,55,56],whilst:0,whitelist:27,whitelistroundrobinpolici:[0,27,42,44,55],whitespac:25,who:27,whose:3,wider:[32,41],window:[0,32],wish:3,within:[0,1,3,10,13,27,30,34,41,42,44,55],withing:13,without:[0,1,3,9,10,38,41,44],wkt:[0,32],wno:46,won:37,word:[27,38],work:[0,2,7,17,27,30,32,37,38,44,45,47,48,53,54,56],workaround:[0,36,40],worker:[0,39],worker_process_init:39,working_keyspac:27,workload:[0,42,49],worth:46,would:[0,9,27,36,37,38,42,44,53,54,55],wrap:[12,15,18,27,44],wrap_socket:54,wrapper:[0,27,30],write:[0,1,8,10,15,18,26,27,30],write_request_timeout_in_m:1,write_timeout:26,write_typ:[1,27],writefailur:1,writetimeout:[0,1],writetyp:[0,1,27],written:0,wrong:[0,44],wunus:46,www:6,x509:54,x:[1,4,10,27,32,46,47],xcode:46,xrang:0,y:[0,10,27,32],yaml:[1,27,52,53],year:[10,32,35,38],year__gt:38,year__in:38,year__lt:38,yet:[3,38,44,55],yield:[4,27],you:[0,3,4,6,9,12,27,30,34,35,37,38,43,44,46,49,50,52,53,54,55,56],your:[0,3,6,9,35,37,38,40,43,44,47,48,49,50,52,54,55,56],yourself:49,yum:46,yyyi:[17,32],z:10,zero:0,zip:[55,56],zipcod:[3,11,37,55,56]},titles:["CHANGELOG","cassandra - Exceptions and Enums","cassandra.auth - Authentication","cassandra.cluster - Clusters and Sessions","cassandra.concurrent - Utilities for Concurrent Statement Execution","cassandra.connection - Low Level Connection Info","cassandra.cqlengine.columns - Column types for object mapping models","cassandra.cqlengine.connection - Connection management for cqlengine","cassandra.cqlengine.management - Schema management for cqlengine","cassandra.cqlengine.models - Table models for object mapping","cassandra.cqlengine.query - Query and filter model objects","cassandra.cqlengine.usertype - Model classes for User Defined Types","cassandra.datastax.graph.fluent","cassandra.datastax.graph.fluent.predicates","cassandra.datastax.graph.fluent.query","cassandra.datastax.graph - Graph Statements, Options, and Row Factories","cassandra.decoder - Data Return Formats","cassandra.encoder - Encoders for non-prepared Statements","cassandra.graph - Graph Statements, Options, and Row Factories","cassandra.io.asyncioreactor - asyncio Event Loop","cassandra.io.asyncorereactor - asyncore Event Loop","cassandra.io.eventletreactor - eventlet-compatible Connection","cassandra.io.geventreactor - gevent-compatible Event Loop","cassandra.io.libevreactor - libev Event Loop","cassandra.io.twistedreactor - Twisted Event Loop","cassandra.metadata - Schema and Ring Topology","cassandra.metrics - Performance Metrics","cassandra.policies - Load balancing and Failure Handling Policies","cassandra.pool - Hosts and Connection Pools","cassandra.protocol - Protocol Features","cassandra.query - Prepared Statements, Batch Statements, Tracing, and Row Factories","cassandra.timestamps - Timestamp Generation","cassandra.util - Utilities","API Documentation","Batch Queries","Connections","Frequently Asked Questions","Models","Making Queries","Third party integrations","Upgrade Guide","Working with Dates and Times","Execution Profiles","Frequently Asked Questions","Getting Started","Python Driver for Scylla and Apache Cassandra\u00ae","Installation","Lightweight Transactions (Compare-and-set)","Object Mapper","Performance Notes","Paging Large Queries","ScyllaDB Cloud","ScyllaDB Cloud Serverless","Scylla Specific Features","Security","Upgrading","User Defined Types"],titleterms:{"0":[0,54,55],"0b1":0,"0b5":0,"0b6":0,"0b7":0,"0c1":0,"0c2":0,"0rc1":0,"1":[0,55],"10":0,"11":0,"12":0,"13":0,"14":0,"15":0,"16":[0,54],"17":0,"18":0,"19":0,"2":[0,55],"20":0,"21":0,"22":0,"23":0,"24":0,"25":0,"26":0,"3":[0,54,55],"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"class":[11,56],"default":[35,38,42,47,55],"do":43,"enum":1,"final":0,"float":40,"function":[38,40],"import":[40,55],"new":[35,53],"return":[16,55],No:54,access:38,ad:42,address:27,alias:40,all:38,apach:45,api:[33,40,55],applic:43,ar:[38,55],ask:[36,43],asynchron:44,asyncio:19,asyncioreactor:19,asyncor:20,asyncorereactor:20,attach:55,attribut:53,auth:2,authent:[2,54,55],automat:55,awar:53,balanc:27,base:[46,55],batch:[30,34,36,55],batchqueri:35,beta2:0,beta3:0,beta4:0,beta:0,bind:55,blist:55,bug:0,c:46,call:55,callback:[34,50],can:36,cassandra:[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,41,44,45,55],celeri:39,chang:[35,40,55],changelog:0,client:[54,55],cloud:[51,52],cluster:[3,42,44,53,55],column:[6,40],compar:47,compat:[21,22],compress:46,concurr:4,configur:[46,54],connect:[5,7,21,28,35,43,44],consist:[44,55],consolid:40,content:[45,48],context:35,control:50,convers:44,copyright:45,core:33,correctli:36,cql:44,cqlengin:[6,7,8,9,10,11,40],custom:[29,54,55],cython:[46,49],data:16,datastax:[12,13,14,15,33],date:[40,41],datetyp:41,dead:27,decod:16,defin:[11,37,55,56],definit:37,delet:36,depend:[46,55],deprec:[0,40,55],deseri:29,determin:43,dict:56,dict_factori:47,dictionari:37,document:33,doe:43,don:36,doubl:40,down:27,driver:[33,43,45,55],dse:[54,55],encod:[17,55],error:46,event:[19,20,22,23,24],eventlet:[21,54],eventletreactor:21,exampl:[37,54],except:[1,40],execut:[4,34,42,44,54,55],execute_async:55,extend:37,extens:[46,49],extra:55,factori:[15,18,30],fail:27,failur:27,faster:29,featur:[0,29,53,55],field2:36,field:36,filter:[10,38],fix:0,fluent:[12,13,14],format:16,frequent:[36,43],from:[0,36,55],from_datetim:40,gener:[31,34],get:[44,45,48],gevent:22,geventreactor:22,graph:[12,13,14,15,18,33,46,55],guid:40,handl:[27,50],help:45,helper:53,host:[27,28],how:[36,43],i:[36,43],idempot:27,ident:54,ignor:55,immut:38,individu:36,info:5,inform:55,inherit:[37,40],initi:42,instal:[46,55],instanc:[35,37,42],instanti:36,integr:39,io:[19,20,21,22,23,24,43],issu:45,keyspac:44,larg:50,legaci:42,level:[5,40,44,55],libev:[23,46],libevreactor:23,lightweight:[47,55],list:[38,40],load:27,local_on:55,log:34,login:54,loop:[19,20,22,23,24],low:5,lower:54,make:38,manag:[7,8,35,40,43],manipul:37,manual:46,map:[6,9,42,56],mapper:[33,48],mark:27,merg:0,metadata:[25,55],metric:[26,46],model:[6,9,10,11,35,36,37,40],modul:55,multiprocess:49,my:43,name:[38,42,55],named_tuple_factori:47,nativ:55,node:27,non:[17,46,55],normal:55,note:[46,49],now:55,object:[6,9,10,33,38,48],oper:[27,38,43],option:[15,18,46],order:[36,38],organ:40,osx:46,other:0,overload:40,packag:40,page:[50,55],paramet:[42,44,55],parti:39,pass:[42,44],path:41,pattern:34,payload:29,per:38,perform:[26,49],pip:46,platform:46,polici:27,pool:28,predic:13,prepar:[17,30,44,55],prepend:40,preserv:36,profil:[42,44],protocol:[29,54,55],proxi:54,pypi:49,python:[45,46],queri:[10,14,30,34,36,38,43,44,50,55],queryset:[10,35,38],question:[36,43],read:41,reconnect:27,regist:[35,56],remov:[40,55],replica:43,report:45,request:43,result:[47,50,55],resum:50,retri:[27,43],retriev:38,revers:40,ring:25,row:[15,18,30,36],sasl:55,schema:[8,25,40],scylla:[45,53],scylladb:[51,52],secur:54,select:35,server:[27,54],serverless:52,session:[3,44,55],set:[44,47],sever:55,shard:53,shutdown:55,side:55,size:50,soft:55,special:47,specif:53,specul:44,speed:46,ssl:[46,54],start:[44,48],statement:[4,15,17,18,30,44,55],support:46,t:36,tabl:[9,38,53],them:56,third:39,through:46,time:41,timeout:[38,43],timestamp:[31,41,55],timeuuid:[38,40],token:[25,38],topolog:25,trace:[30,43,55],transact:[47,55],translat:27,ttl:38,tuple_factori:47,twist:[24,54],twistedreactor:24,type:[6,11,37,40,44,55,56],udt:56,unicodemixin:40,unifi:54,unlog:34,unregist:35,up:[27,46],updat:[36,55],upgrad:[0,40,55],us:[34,42,55,56],user:[11,37,55,56],usertyp:11,util:[4,32],uwsgi:39,v1:54,v2:55,v3:55,valid:37,valu:[36,38],value2:36,verif:54,verifi:[46,54],version:54,vs:34,why:[36,43],window:46,without:[42,56],work:[36,41,55],write:41,wsgi:43,x:[0,55],your:46}}) \ No newline at end of file diff --git a/stable/security.html b/stable/security.html new file mode 100644 index 0000000000..c830d70a47 --- /dev/null +++ b/stable/security.html @@ -0,0 +1,1020 @@ + + + + + + + + + + + + + Security | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + + + +
+ +
+ +
+

Security

+

The two main security components you will use with the +Python driver are Authentication and SSL.

+
+

Authentication

+

Versions 2.0 and higher of the driver support a SASL-based +authentication mechanism when protocol_version +is set to 2 or higher. To use this authentication, set +auth_provider to an instance of a subclass +of AuthProvider. When working +with Cassandra’s PasswordAuthenticator, you can use +the PlainTextAuthProvider class.

+

For example, suppose Cassandra is setup with its default +‘cassandra’ user with a password of ‘cassandra’:

+
from cassandra.cluster import Cluster
+from cassandra.auth import PlainTextAuthProvider
+
+auth_provider = PlainTextAuthProvider(username='cassandra', password='cassandra')
+cluster = Cluster(auth_provider=auth_provider, protocol_version=2)
+
+
+
+

Custom Authenticators

+

If you’re using something other than Cassandra’s PasswordAuthenticator, +SaslAuthProvider is provided for generic SASL authentication mechanisms, +utilizing the pure-sasl package. +If these do not suit your needs, you may need to create your own subclasses of +AuthProvider and Authenticator. You can use the Sasl classes +as example implementations.

+
+
+

Protocol v1 Authentication

+

When working with Cassandra 1.2 (or a higher version with +protocol_version set to 1), you will not pass in +an AuthProvider instance. Instead, you should pass in a +function that takes one argument, the IP address of a host, and returns +a dict of credentials with a username and password key:

+
from cassandra.cluster import Cluster
+
+def get_credentials(host_address):
+    return {'username': 'joe', 'password': '1234'}
+
+cluster = Cluster(auth_provider=get_credentials, protocol_version=1)
+
+
+
+
+
+

SSL

+

SSL should be used when client encryption is enabled in Cassandra.

+

To give you as much control as possible over your SSL configuration, our SSL +API takes a user-created SSLContext instance from the Python standard library. +These docs will include some examples for how to achieve common configurations, +but the ssl.SSLContext documentation +gives a more complete description of what is possible.

+

To enable SSL with version 3.17.0 and higher, you will need to set Cluster.ssl_context to a +ssl.SSLContext instance to enable SSL. Optionally, you can also set Cluster.ssl_options +to a dict of options. These will be passed as kwargs to ssl.SSLContext.wrap_socket() +when new sockets are created.

+

If you create your SSLContext using ssl.create_default_context, +be aware that SSLContext.check_hostname is set to True by default, so the hostname validation will be done +by Python and not the driver. For this reason, we need to set the server_hostname at best effort, which is the +resolved ip address. If this validation needs to be done against the FQDN, consider enabling it using the ssl_options +as described in the following examples or implement your own EndPoint and +EndPointFactory.

+

The following examples assume you have generated your Cassandra certificate and +keystore files with these intructions:

+ +

It might be also useful to learn about the different levels of identity verification to understand the examples:

+ +
+

SSL with Twisted or Eventlet

+

Twisted and Eventlet both use an alternative SSL implementation called pyOpenSSL, so if your Cluster’s connection class is +TwistedConnection or EventletConnection, you must pass a +pyOpenSSL context instead. +An example is provided in these docs, and more details can be found in the +documentation. +pyOpenSSL is not installed by the driver and must be installed separately.

+
+
+

SSL Configuration Examples

+

Here, we’ll describe the server and driver configuration necessary to set up SSL to meet various goals, such as the client verifying the server and the server verifying the client. We’ll also include Python code demonstrating how to use servers and drivers configured in these ways.

+
+

No identity verification

+

No identity verification at all. Note that this is not recommended for for production deployments.

+

The Cassandra configuration:

+
client_encryption_options:
+  enabled: true
+  keystore: /path/to/127.0.0.1.keystore
+  keystore_password: myStorePass
+  require_client_auth: false
+
+
+

The driver configuration:

+
from cassandra.cluster import Cluster, Session
+from ssl import SSLContext, PROTOCOL_TLS
+
+ssl_context = SSLContext(PROTOCOL_TLS)
+
+cluster = Cluster(['127.0.0.1'], ssl_context=ssl_context)
+session = cluster.connect()
+
+
+
+
+

Client verifies server

+

Ensure the python driver verifies the identity of the server.

+

The Cassandra configuration:

+
client_encryption_options:
+  enabled: true
+  keystore: /path/to/127.0.0.1.keystore
+  keystore_password: myStorePass
+  require_client_auth: false
+
+
+

For the driver configuration, it’s very important to set ssl_context.verify_mode +to CERT_REQUIRED. Otherwise, the loaded verify certificate will have no effect:

+
from cassandra.cluster import Cluster, Session
+from ssl import SSLContext, PROTOCOL_TLS, CERT_REQUIRED
+
+ssl_context = SSLContext(PROTOCOL_TLS)
+ssl_context.load_verify_locations('/path/to/rootca.crt')
+ssl_context.verify_mode = CERT_REQUIRED
+
+cluster = Cluster(['127.0.0.1'], ssl_context=ssl_context)
+session = cluster.connect()
+
+
+

Additionally, you can also force the driver to verify the hostname of the server by passing additional options to ssl_context.wrap_socket via the ssl_options kwarg:

+
from cassandra.cluster import Cluster, Session
+from ssl import SSLContext, PROTOCOL_TLS, CERT_REQUIRED
+
+ssl_context = SSLContext(PROTOCOL_TLS)
+ssl_context.load_verify_locations('/path/to/rootca.crt')
+ssl_context.verify_mode = CERT_REQUIRED
+ssl_context.check_hostname = True
+ssl_options = {'server_hostname': '127.0.0.1'}
+
+cluster = Cluster(['127.0.0.1'], ssl_context=ssl_context, ssl_options=ssl_options)
+session = cluster.connect()
+
+
+
+
+

Server verifies client

+

If Cassandra is configured to verify clients (require_client_auth), you need to generate +SSL key and certificate files.

+

The cassandra configuration:

+
client_encryption_options:
+  enabled: true
+  keystore: /path/to/127.0.0.1.keystore
+  keystore_password: myStorePass
+  require_client_auth: true
+  truststore: /path/to/dse-truststore.jks
+  truststore_password: myStorePass
+
+
+

The Python ssl APIs require the certificate in PEM format. First, create a certificate +conf file:

+
cat > gen_client_cert.conf <<EOF
+[ req ]
+distinguished_name = req_distinguished_name
+prompt = no
+output_password = ${ROOT_CERT_PASS}
+default_bits = 2048
+
+[ req_distinguished_name ]
+C = ${CERT_COUNTRY}
+O = ${CERT_ORG_NAME}
+OU = ${CERT_OU}
+CN = client
+EOF
+
+
+

Make sure you replaced the variables with the same values you used for the initial +root CA certificate. Then, generate the key:

+
openssl req -newkey rsa:2048 -nodes -keyout client.key -out client.csr -config gen_client_cert.conf
+
+
+

And generate the client signed certificate:

+
openssl x509 -req -CA ${ROOT_CA_BASE_NAME}.crt -CAkey ${ROOT_CA_BASE_NAME}.key -passin pass:${ROOT_CERT_PASS} \
+    -in client.csr -out client.crt_signed -days ${CERT_VALIDITY} -CAcreateserial
+
+
+

Finally, you can use that configuration with the following driver code:

+
from cassandra.cluster import Cluster, Session
+from ssl import SSLContext, PROTOCOL_TLS
+
+ssl_context = SSLContext(PROTOCOL_TLS)
+ssl_context.load_cert_chain(
+    certfile='/path/to/client.crt_signed',
+    keyfile='/path/to/client.key')
+
+cluster = Cluster(['127.0.0.1'], ssl_context=ssl_context)
+session = cluster.connect()
+
+
+
+
+

Server verifies client and client verifies server

+

See the previous section for examples of Cassandra configuration and preparing +the client certificates.

+

The following driver code specifies that the connection should use two-way verification:

+
from cassandra.cluster import Cluster, Session
+from ssl import SSLContext, PROTOCOL_TLS, CERT_REQUIRED
+
+ssl_context = SSLContext(PROTOCOL_TLS)
+ssl_context.load_verify_locations('/path/to/rootca.crt')
+ssl_context.verify_mode = CERT_REQUIRED
+ssl_context.load_cert_chain(
+    certfile='/path/to/client.crt_signed',
+    keyfile='/path/to/client.key')
+
+cluster = Cluster(['127.0.0.1'], ssl_context=ssl_context)
+session = cluster.connect()
+
+
+

The driver uses SSLContext directly to give you many other options in configuring SSL. Consider reading the Python SSL documentation +for more details about SSLContext configuration.

+

Server verifies client and client verifies server using Twisted and pyOpenSSL

+
from OpenSSL import SSL, crypto
+from cassandra.cluster import Cluster
+from cassandra.io.twistedreactor import TwistedConnection
+
+ssl_context = SSL.Context(SSL.TLSv1_2_METHOD)
+ssl_context.set_verify(SSL.VERIFY_PEER, callback=lambda _1, _2, _3, _4, ok: ok)
+ssl_context.use_certificate_file('/path/to/client.crt_signed')
+ssl_context.use_privatekey_file('/path/to/client.key')
+ssl_context.load_verify_locations('/path/to/rootca.crt')
+
+cluster = Cluster(
+    contact_points=['127.0.0.1'],
+    connection_class=TwistedConnection,
+    ssl_context=ssl_context,
+    ssl_options={'check_hostname': True}
+)
+session = cluster.connect()
+
+
+

Connecting using Eventlet would look similar except instead of importing and using TwistedConnection, you would +import and use EventletConnection, including the appropriate monkey-patching.

+
+
+
+

Versions 3.16.0 and lower

+

To enable SSL you will need to set Cluster.ssl_options to a +dict of options. These will be passed as kwargs to ssl.wrap_socket() +when new sockets are created. Note that this use of ssl_options will be +deprecated in the next major release.

+

By default, a ca_certs value should be supplied (the value should be +a string pointing to the location of the CA certs file), and you probably +want to specify ssl_version as ssl.PROTOCOL_TLS to match +Cassandra’s default protocol.

+

For example:

+
from cassandra.cluster import Cluster
+from ssl import PROTOCOL_TLS, CERT_REQUIRED
+
+ssl_opts = {
+    'ca_certs': '/path/to/my/ca.certs',
+    'ssl_version': PROTOCOL_TLS,
+    'cert_reqs': CERT_REQUIRED  # Certificates are required and validated
+}
+cluster = Cluster(ssl_options=ssl_opts)
+
+
+

This is only an example to show how to pass the ssl parameters. Consider reading +the python ssl documentation for +your configuration. For further reading, Andrew Mussey has published a thorough guide on +Using SSL with the DataStax Python driver.

+
+

SSL with Twisted

+

In case the twisted event loop is used pyOpenSSL must be installed or an exception will be risen. Also +to set the ssl_version and cert_reqs in ssl_opts the appropriate constants from pyOpenSSL are expected.

+
+
+
+
+

DSE Authentication

+

When authenticating against DSE, the Cassandra driver provides two auth providers that work both with legacy kerberos and Cassandra authenticators, +as well as the new DSE Unified Authentication. This allows client to configure this auth provider independently, +and in advance of any server upgrade. These auth providers are configured in the same way as any previous implementation:

+
from cassandra.auth import DSEGSSAPIAuthProvider
+auth_provider = DSEGSSAPIAuthProvider(service='dse', qops=["auth"])
+cluster = Cluster(auth_provider=auth_provider)
+session = cluster.connect()
+
+
+

Implementations are DSEPlainTextAuthProvider, DSEGSSAPIAuthProvider and SaslAuthProvider.

+
+

DSE Unified Authentication

+

With DSE (>=5.1), unified Authentication allows you to:

+
    +
  • Proxy Login: Authenticate using a fixed set of authentication credentials but allow authorization of resources based another user id.

  • +
  • Proxy Execute: Authenticate using a fixed set of authentication credentials but execute requests based on another user id.

  • +
+
+

Proxy Login

+

Proxy login allows you to authenticate with a user but act as another one. You need to ensure the authenticated user has the permission to use the authorization of resources of the other user. ie. this example will allow the server user to authenticate as usual but use the authorization of user1:

+
GRANT PROXY.LOGIN on role user1 to server
+
+
+

then you can do the proxy authentication….

+
from cassandra.cluster import Cluster
+from cassandra.auth import SaslAuthProvider
+
+sasl_kwargs = {
+  "service": 'dse',
+  "mechanism":"PLAIN",
+  "username": 'server',
+  'password': 'server',
+  'authorization_id': 'user1'
+}
+
+auth_provider = SaslAuthProvider(**sasl_kwargs)
+c = Cluster(auth_provider=auth_provider)
+s = c.connect()
+s.execute(...)  # all requests will be executed as 'user1'
+
+
+

If you are using kerberos, you can use directly DSEGSSAPIAuthProvider and pass the authorization_id, like this:

+
from cassandra.cluster import Cluster
+from cassandra.auth import DSEGSSAPIAuthProvider
+
+# Ensure the kerberos ticket of the server user is set with the kinit utility.
+auth_provider = DSEGSSAPIAuthProvider(service='dse', qops=["auth"], principal="server@DATASTAX.COM",
+                                      authorization_id='user1@DATASTAX.COM')
+c = Cluster(auth_provider=auth_provider)
+s = c.connect()
+s.execute(...)  # all requests will be executed as 'user1'
+
+
+
+
+

Proxy Execute

+

Proxy execute allows you to execute requests as another user than the authenticated one. You need to ensure the authenticated user has the permission to use the authorization of resources of the specified user. ie. this example will allow the server user to execute requests as user1:

+
GRANT PROXY.EXECUTE on role user1 to server
+
+
+

then you can do a proxy execute…

+
from cassandra.cluster import Cluster
+from cassandra.auth import DSEPlainTextAuthProvider,
+
+auth_provider = DSEPlainTextAuthProvider('server', 'server')
+
+c = Cluster(auth_provider=auth_provider)
+s = c.connect()
+s.execute('select * from k.t;', execute_as='user1')  # the request will be executed as 'user1'
+
+
+

Please see the official documentation for more details on the feature and configuration process.

+
+
+
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/stable/sitemap.xml b/stable/sitemap.xml new file mode 100644 index 0000000000..bcdebfda06 --- /dev/null +++ b/stable/sitemap.xml @@ -0,0 +1,2 @@ + +https://python-driver.docs.scylladb.com/stable/CHANGELOG.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/auth.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/cluster.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/concurrent.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/connection.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/cqlengine/columns.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/cqlengine/connection.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/cqlengine/management.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/cqlengine/models.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/cqlengine/query.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/cqlengine/usertype.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/datastax/graph/fluent/index.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/datastax/graph/fluent/predicates.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/datastax/graph/fluent/query.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/datastax/graph/index.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/decoder.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/encoder.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/graph.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/io/asyncioreactor.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/io/asyncorereactor.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/io/eventletreactor.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/io/geventreactor.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/io/libevreactor.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/io/twistedreactor.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/metadata.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/metrics.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/policies.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/pool.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/protocol.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/query.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/timestamps.htmlhttps://python-driver.docs.scylladb.com/stable/api/cassandra/util.htmlhttps://python-driver.docs.scylladb.com/stable/api/index.htmlhttps://python-driver.docs.scylladb.com/stable/cqlengine/batches.htmlhttps://python-driver.docs.scylladb.com/stable/cqlengine/connections.htmlhttps://python-driver.docs.scylladb.com/stable/cqlengine/faq.htmlhttps://python-driver.docs.scylladb.com/stable/cqlengine/models.htmlhttps://python-driver.docs.scylladb.com/stable/cqlengine/queryset.htmlhttps://python-driver.docs.scylladb.com/stable/cqlengine/third-party.htmlhttps://python-driver.docs.scylladb.com/stable/cqlengine/upgrade-guide.htmlhttps://python-driver.docs.scylladb.com/stable/dates-and-times.htmlhttps://python-driver.docs.scylladb.com/stable/execution-profiles.htmlhttps://python-driver.docs.scylladb.com/stable/faq.htmlhttps://python-driver.docs.scylladb.com/stable/getting-started.htmlhttps://python-driver.docs.scylladb.com/stable/index.htmlhttps://python-driver.docs.scylladb.com/stable/installation.htmlhttps://python-driver.docs.scylladb.com/stable/lwt.htmlhttps://python-driver.docs.scylladb.com/stable/object-mapper.htmlhttps://python-driver.docs.scylladb.com/stable/performance.htmlhttps://python-driver.docs.scylladb.com/stable/query-paging.htmlhttps://python-driver.docs.scylladb.com/stable/scylla-cloud.htmlhttps://python-driver.docs.scylladb.com/stable/scylla-cloud-serverless.htmlhttps://python-driver.docs.scylladb.com/stable/scylla-specific.htmlhttps://python-driver.docs.scylladb.com/stable/security.htmlhttps://python-driver.docs.scylladb.com/stable/upgrading.htmlhttps://python-driver.docs.scylladb.com/stable/user-defined-types.htmlhttps://python-driver.docs.scylladb.com/stable/py-modindex.htmlhttps://python-driver.docs.scylladb.com/stable/404.htmlhttps://python-driver.docs.scylladb.com/stable/search.html \ No newline at end of file diff --git a/stable/upgrading.html b/stable/upgrading.html new file mode 100644 index 0000000000..48b1cd0e9e --- /dev/null +++ b/stable/upgrading.html @@ -0,0 +1,1019 @@ + + + + + + + + + + + + + Upgrading | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + + + +
+ +
+ +
+

Upgrading

+
+
+
+

Upgrading from dse-driver

+

Since 3.21.0, scylla-driver fully supports DataStax products. dse-driver and +dse-graph users should now migrate to scylla-driver to benefit from latest bug fixes +and new features. The upgrade to this new unified driver version is straightforward +with no major API changes.

+
+

Installation

+

Only the scylla-driver package should be installed. dse-driver and dse-graph +are not required anymore:

+
pip install scylla-driver
+
+
+

If you need the Graph Fluent API (features provided by dse-graph):

+
pip install scylla-driver[graph]
+
+
+

See Installation for more details.

+
+
+

Import from the cassandra module

+

There is no dse module, so you should import from the cassandra module. You +need to change only the first module of your import statements, not the submodules.

+
from dse.cluster import Cluster, EXEC_PROFILE_GRAPH_DEFAULT
+from dse.auth import PlainTextAuthProvider
+from dse.policies import WhiteListRoundRobinPolicy
+
+# becomes
+
+from cassandra.cluster import Cluster, EXEC_PROFILE_GRAPH_DEFAULT
+from cassandra.auth import PlainTextAuthProvider
+from cassandra.policies import WhiteListRoundRobinPolicy
+
+
+

Also note that the cassandra.hosts module doesn’t exist in scylla-driver. This +module is named cassandra.pool.

+
+
+

dse-graph

+

dse-graph features are now built into scylla-driver. The only change you need +to do is your import statements:

+
from dse_graph import ..
+from dse_graph.query import ..
+
+# becomes
+
+from cassandra.datastax.graph.fluent import ..
+from cassandra.datastax.graph.fluent.query import ..
+
+
+

See fluent.

+
+
+

Session.execute and Session.execute_async API

+

Although it is not common to use this API with positional arguments, it is +important to be aware that the host and execute_as parameters have had +their positional order swapped. This is only because execute_as was added +in dse-driver before host.

+

See Session.execute().

+
+
+

Deprecations

+

These changes are optional, but recommended:

+
    +
  • Importing from cassandra.graph is deprecated. Consider importing from cassandra.datastax.graph.

  • +
  • Use DefaultLoadBalancingPolicy instead of DSELoadBalancingPolicy.

  • +
+
+
+
+

Upgrading to 3.0

+

Version 3.0 of the DataStax Python driver for Apache Cassandra +adds support for Cassandra 3.0 while maintaining support for +previously supported versions. In addition to substantial internal rework, +there are several updates to the API that integrators will need +to consider:

+
+

Default consistency is now LOCAL_ONE

+

Previous value was ONE. The new value is introduced to mesh with the default +DC-aware load balancing policy and to match other drivers.

+
+
+

Execution API Updates

+
+

Result return normalization

+

PYTHON-368

+

Previously results would be returned as a list of rows for result rows +up to fetch_size, and PagedResult afterward. This could break +application code that assumed one type and got another.

+

Now, all results are returned as an iterable ResultSet.

+

The preferred way to consume results of unknown size is to iterate through +them, letting automatic paging occur as they are consumed.

+
results = session.execute("SELECT * FROM system.local")
+for row in results:
+    process(row)
+
+
+

If the expected size of the results is known, it is still possible to +materialize a list using the iterator:

+
results = session.execute("SELECT * FROM system.local")
+row_list = list(results)
+
+
+

For backward compatibility, ResultSet supports indexing. When +accessed at an index, a ~.ResultSet object will materialize all its pages:

+
results = session.execute("SELECT * FROM system.local")
+first_result = results[0]  # materializes results, fetching all pages
+
+
+

This can send requests and load (possibly large) results into memory, so +~.ResultSet will log a warning on implicit materialization.

+
+
+

Trace information is not attached to executed Statements

+

PYTHON-318

+

Previously trace data was attached to Statements if tracing was enabled. This +could lead to confusion if the same statement was used for multiple executions.

+

Now, trace data is associated with the ResponseFuture and ResultSet +returned for each query:

+

ResponseFuture.get_query_trace()

+

ResponseFuture.get_all_query_traces()

+

ResultSet.get_query_trace()

+

ResultSet.get_all_query_traces()

+
+
+

Binding named parameters now ignores extra names

+

PYTHON-178

+

Previously, BoundStatement.bind() would raise if a mapping +was passed with extra names not found in the prepared statement.

+

Behavior in 3.0+ is to ignore extra names.

+
+
+
+

blist removed as soft dependency

+

PYTHON-385

+

Previously the driver had a soft dependency on blist sortedset, using +that where available and using an internal fallback where possible.

+

Now, the driver never chooses the blist variant, instead returning the +internal util.SortedSet for all set results. The class implements +all standard set operations, so no integration code should need to change unless +it explicitly checks for sortedset type.

+
+
+

Metadata API Updates

+

PYTHON-276, PYTHON-408, PYTHON-400, PYTHON-422

+

Cassandra 3.0 brought a substantial overhaul to the internal schema metadata representation. +This version of the driver supports that metadata in addition to the legacy version. Doing so +also brought some changes to the metadata model.

+

The present API is documented: cassandra.metadata. Changes highlighted below:

+
    +
  • All types are now exposed as CQL types instead of types derived from the internal server implementation

  • +
  • Some metadata attributes have changed names to match current nomenclature (for example, Index.kind in place of Index.type).

  • +
  • Some metadata attributes removed

    +
      +
    • TableMetadata.keyspace reference replaced with TableMetadata.keyspace_name

    • +
    • ColumnMetadata.index is removed table- and keyspace-level mappings are still maintained

    • +
    +
  • +
+
+
+

Several deprecated features are removed

+

PYTHON-292

+
    +
  • ResponseFuture.result timeout parameter is removed, use Session.execute timeout instead (031ebb0)

  • +
  • Cluster.refresh_schema removed, use Cluster.refresh_*_metadata instead (419fcdf)

  • +
  • Cluster.submit_schema_refresh removed (574266d)

  • +
  • cqltypes time/date functions removed, use util entry points instead (bb984ee)

  • +
  • decoder module removed (e16a073)

  • +
  • TableMetadata.keyspace attribute replaced with keyspace_name (cc94073)

  • +
  • cqlengine.columns.TimeUUID.from_datetime removed, use util variant instead (96489cc)

  • +
  • cqlengine.columns.Float(double_precision) parameter removed, use columns.Double instead (a2d3a98)

  • +
  • cqlengine keyspace management functions are removed in favor of the strategy-specific entry points (4bd5909)

  • +
  • cqlengine.Model.__polymorphic_*__ attributes removed, use __discriminator* attributes instead (9d98c8e)

  • +
  • cqlengine.statements will no longer warn about list list prepend behavior (79efe97)

  • +
+
+
+
+

Upgrading to 2.1 from 2.0

+

Version 2.1 of the DataStax Python driver for Apache Cassandra +adds support for Cassandra 2.1 and version 3 of the native protocol.

+

Cassandra 1.2, 2.0, and 2.1 are all supported. However, 1.2 only +supports protocol version 1, and 2.0 only supports versions 1 and +2, so some features may not be available.

+
+

Using the v3 Native Protocol

+

By default, the driver will attempt to use version 2 of the +native protocol. To use version 3, you must explicitly +set the protocol_version:

+
from cassandra.cluster import Cluster
+
+cluster = Cluster(protocol_version=3)
+
+
+

Note that protocol version 3 is only supported by Cassandra 2.1+.

+

In future releases, the driver may default to using protocol version +3.

+
+
+

Working with User-Defined Types

+

Cassandra 2.1 introduced the ability to define new types:

+
USE KEYSPACE mykeyspace;
+
+CREATE TYPE address (street text, city text, zip int);
+
+
+

The driver generally expects you to use instances of a specific +class to represent column values of this type. You can let the +driver know what class to use with Cluster.register_user_type():

+
cluster = Cluster()
+
+class Address(object):
+
+    def __init__(self, street, city, zipcode):
+        self.street = street
+        self.city = text
+        self.zipcode = zipcode
+
+cluster.register_user_type('mykeyspace', 'address', Address)
+
+
+

When inserting data for address columns, you should pass in +instances of Address. When querying data, address column +values will be instances of Address.

+

If no class is registered for a user-defined type, query results +will use a namedtuple class and data may only be inserted +though prepared statements.

+

See User Defined Types for more details.

+
+
+

Customizing Encoders for Non-prepared Statements

+

Starting with version 2.1 of the driver, it is possible to customize +how Python types are converted to CQL literals when working with +non-prepared statements. This is done on a per-Session +basis through Session.encoder:

+
cluster = Cluster()
+session = cluster.connect()
+session.encoder.mapping[tuple] = session.encoder.cql_encode_tuple
+
+
+

See Type Conversions for the table of default CQL literal conversions.

+
+
+

Using Client-Side Protocol-Level Timestamps

+

With version 3 of the native protocol, timestamps may be supplied by the +client at the protocol level. (Normally, if they are not specified within +the CQL query itself, a timestamp is generated server-side.)

+

When protocol_version is set to 3 or higher, the driver +will automatically use client-side timestamps with microsecond precision +unless Session.use_client_timestamp is changed to False. +If a timestamp is specified within the CQL query, it will override the +timestamp generated by the driver.

+
+
+
+

Upgrading to 2.0 from 1.x

+

Version 2.0 of the DataStax Python driver for Apache Cassandra +includes some notable improvements over version 1.x. This version +of the driver supports Cassandra 1.2, 2.0, and 2.1. However, not +all features may be used with Cassandra 1.2, and some new features +in 2.1 are not yet supported.

+
+

Using the v2 Native Protocol

+

By default, the driver will attempt to use version 2 of Cassandra’s +native protocol. You can explicitly set the protocol version to +2, though:

+
from cassandra.cluster import Cluster
+
+cluster = Cluster(protocol_version=2)
+
+
+

When working with Cassandra 1.2, you will need to +explicitly set the protocol_version to 1:

+
from cassandra.cluster import Cluster
+
+cluster = Cluster(protocol_version=1)
+
+
+
+
+

Automatic Query Paging

+

Version 2 of the native protocol adds support for automatic query +paging, which can make dealing with large result sets much simpler.

+

See Paging Large Queries for full details.

+
+
+

Protocol-Level Batch Statements

+

With version 1 of the native protocol, batching of statements required +using a BATCH cql query. +With version 2 of the native protocol, you can now batch statements at +the protocol level. This allows you to use many different prepared +statements within a single batch.

+

See BatchStatement for details and usage examples.

+
+
+

SASL-based Authentication

+

Also new in version 2 of the native protocol is SASL-based authentication. +See the section on Security for details and examples.

+
+
+

Lightweight Transactions

+

Lightweight transactions are another new feature. To use lightweight transactions, add IF clauses +to your CQL queries and set the serial_consistency_level +on your statements.

+
+
+

Calling Cluster.shutdown()

+

In order to fix some issues around garbage collection and unclean interpreter +shutdowns, version 2.0 of the driver requires you to call Cluster.shutdown() +on your Cluster objects when you are through with them. +This helps to guarantee a clean shutdown.

+
+
+

Deprecations

+

The following functions have moved from cassandra.decoder to cassandra.query. +The original functions have been left in place with a DeprecationWarning for +now:

+ +
+
+

Dependency Changes

+

The following dependencies have officially been made optional:

+
    +
  • scales

  • +
  • blist

  • +
+

And one new dependency has been added (to enable Python 3 support):

+
    +
  • six

  • +
+
+
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/stable/user-defined-types.html b/stable/user-defined-types.html new file mode 100644 index 0000000000..518bdfb631 --- /dev/null +++ b/stable/user-defined-types.html @@ -0,0 +1,749 @@ + + + + + + + + + + + + + User Defined Types | ScyllaDB Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ Menu +
+
+
+
+
+ + + + +
+ +
+ +
+

User Defined Types

+

Cassandra 2.1 introduced user-defined types (UDTs). You can create a +new type through CREATE TYPE statements in CQL:

+
CREATE TYPE address (street text, zip int);
+
+
+

Version 2.1 of the Python driver adds support for user-defined types.

+
+

Registering a UDT

+

You can tell the Python driver to return columns of a specific UDT as +instances of a class or a dict by registering them with your Cluster +instance through Cluster.register_user_type():

+
+

Map a Class to a UDT

+
cluster = Cluster(protocol_version=3)
+session = cluster.connect()
+session.set_keyspace('mykeyspace')
+session.execute("CREATE TYPE address (street text, zipcode int)")
+session.execute("CREATE TABLE users (id int PRIMARY KEY, location frozen<address>)")
+
+# create a class to map to the "address" UDT
+class Address(object):
+
+    def __init__(self, street, zipcode):
+        self.street = street
+        self.zipcode = zipcode
+
+cluster.register_user_type('mykeyspace', 'address', Address)
+
+# insert a row using an instance of Address
+session.execute("INSERT INTO users (id, location) VALUES (%s, %s)",
+                (0, Address("123 Main St.", 78723)))
+
+# results will include Address instances
+results = session.execute("SELECT * FROM users")
+row = results[0]
+print(row.id, row.location.street, row.location.zipcode)
+
+
+
+
+

Map a dict to a UDT

+
cluster = Cluster(protocol_version=3)
+session = cluster.connect()
+session.set_keyspace('mykeyspace')
+session.execute("CREATE TYPE address (street text, zipcode int)")
+session.execute("CREATE TABLE users (id int PRIMARY KEY, location frozen<address>)")
+
+cluster.register_user_type('mykeyspace', 'address', dict)
+
+# insert a row using a prepared statement and a tuple
+insert_statement = session.prepare("INSERT INTO mykeyspace.users (id, location) VALUES (?, ?)")
+session.execute(insert_statement, [0, ("123 Main St.", 78723)])
+
+# results will include dict instances
+results = session.execute("SELECT * FROM users")
+row = results[0]
+print(row.id, row.location['street'], row.location['zipcode'])
+
+
+
+
+
+

Using UDTs Without Registering Them

+

Although it is recommended to register your types with +Cluster.register_user_type(), the driver gives you some options +for working with unregistered UDTS.

+

When you use prepared statements, the driver knows what data types to +expect for each placeholder. This allows you to pass any object you +want for a UDT, as long as it has attributes that match the field names +for the UDT:

+
cluster = Cluster(protocol_version=3)
+session = cluster.connect()
+session.set_keyspace('mykeyspace')
+session.execute("CREATE TYPE address (street text, zipcode int)")
+session.execute("CREATE TABLE users (id int PRIMARY KEY, location frozen<address>)")
+
+class Foo(object):
+
+    def __init__(self, street, zipcode, otherstuff):
+        self.street = street
+        self.zipcode = zipcode
+        self.otherstuff = otherstuff
+
+insert_statement = session.prepare("INSERT INTO users (id, location) VALUES (?, ?)")
+
+# since we're using a prepared statement, we don't *have* to register
+# a class to map to the UDT to insert data.  The object just needs to have
+# "street" and "zipcode" attributes (which Foo does):
+session.execute(insert_statement, [0, Foo("123 Main St.", 78723, "some other stuff")])
+
+# when we query data, UDT columns that don't have a class registered
+# will be returned as namedtuples:
+results = session.execute("SELECT * FROM users")
+first_row = results[0]
+address = first_row.location
+print(address)  # prints "Address(street='123 Main St.', zipcode=78723)"
+street = address.street
+zipcode = address.street
+
+
+

As shown in the code example, inserting data for UDT columns without registering +a class works fine for prepared statements. However, you must register a +class to insert UDT columns with unprepared statements.* You can still query +UDT columns without registered classes using unprepared statements, they will +simply return namedtuple instances (just like prepared statements do).

+

* this applies to parameterized unprepared statements, in which the driver will be formatting parameters – not statements with interpolated UDT literals.

+
+
+ + +
+ + + + + + +
+

+ScyllaDB Python Driver is available under the Apache v2 License. +ScyllaDB Python Driver is a fork of DataStax Python Driver. +See Copyright here.

+
+
+ +
+ + + + +
+ + + + + + + \ No newline at end of file